/opt/cpanel/ea-wappspector
NameSizeModeActions
.github/-0755rm
bin/-0755rm
src/-0755rm
vendor/-0755rm
composer-installer.php584440644editdlrm
composer.json13030644editdlrm
composer.lock1563570644editdlrm
composer.phar36392790755editdlrm
ea-wappspector-wrapper1000644editdlrm
LICENSE113570644editdlrm
README.md58930644editdlrm
wappspector.phar389139320755editdlrm
Edit: /opt/cpanel/ea-wappspector/wappspector.phar (38913932B)
#!/usr/bin/php '); define('BOX_EXTRACT_PATTERN_OPEN',"__HALT"."_COMPILER(); ?>\r\n"); if (class_exists('Phar')) { Phar::mapPhar(''); require 'phar://' . __FILE__ . '/bin/wappspector.php'; } else { $extract = new Extract(__FILE__, Extract::findStubLength(__FILE__)); $dir = $extract->go(); set_include_path($dir . PATH_SEPARATOR . get_include_path()); require "$dir/bin/wappspector.php"; } class Extract { const PATTERN_DEFAULT=BOX_EXTRACT_PATTERN_DEFAULT; const PATTERN_OPEN=BOX_EXTRACT_PATTERN_OPEN; const GZ=4096; const BZ2=8192; const MASK=12288; private$file; private$handle; private$stub; function __construct($file,$stub){ if(!is_file($file)){ throw new InvalidArgumentException(sprintf('The path "%s" is not a file or does not exist.',$file )); } $this->file=$file; $this->stub=$stub; } static function findStubLength($file,$pattern=self::PATTERN_OPEN ){ if(!($fp=fopen($file,'rb'))){ throw new RuntimeException(sprintf('The phar "%s" could not be opened for reading.',$file )); } $stub=null; $offset=0; $combo=str_split($pattern); while(!feof($fp)){ if(fgetc($fp)===$combo[$offset]){ $offset++; if(!isset($combo[$offset])){ $stub=ftell($fp); break; } }else{ $offset=0; } } fclose($fp); if(null===$stub){ throw new InvalidArgumentException(sprintf('The pattern could not be found in "%s".',$file )); } return$stub; } function go($dir=null){ if(null===$dir){ $dir=rtrim(sys_get_temp_dir(),'\\/').DIRECTORY_SEPARATOR .'pharextract'.DIRECTORY_SEPARATOR .basename($this->file,'.phar'); }else{ $dir=realpath($dir); } $md5=$dir.DIRECTORY_SEPARATOR.md5_file($this->file); if(file_exists($md5)){ return$dir; } if(!is_dir($dir)){ $this->createDir($dir); } $this->open(); if(-1===fseek($this->handle,$this->stub)){ throw new RuntimeException(sprintf('Could not seek to %d in the file "%s".',$this->stub,$this->file )); } $info=$this->readManifest(); if($info['flags']&self::GZ){ if(!function_exists('gzinflate')){ throw new RuntimeException('The zlib extension is (gzinflate()) is required for "%s.',$this->file ); } } if($info['flags']&self::BZ2){ if(!function_exists('bzdecompress')){ throw new RuntimeException('The bzip2 extension (bzdecompress()) is required for "%s".',$this->file ); } } self::purge($dir); $this->createDir($dir); $this->createFile($md5); foreach($info['files']as$info){ $path=$dir.DIRECTORY_SEPARATOR.$info['path']; $parent=dirname($path); if(!is_dir($parent)){ $this->createDir($parent); } if(preg_match('{/$}',$info['path'])){ $this->createDir($path,511,false); }else{ $this->createFile($path,$this->extractFile($info)); } } return$dir; } static function purge($path){ if(is_dir($path)){ foreach(scandir($path)as$item){ if(('.'===$item)||('..'===$item)){ continue; } self::purge($path.DIRECTORY_SEPARATOR.$item); } if(!rmdir($path)){ throw new RuntimeException(sprintf('The directory "%s" could not be deleted.',$path )); } }else{ if(!unlink($path)){ throw new RuntimeException(sprintf('The file "%s" could not be deleted.',$path )); } } } private function createDir($path,$chmod=511,$recursive=true){ if(!mkdir($path,$chmod,$recursive)){ throw new RuntimeException(sprintf('The directory path "%s" could not be created.',$path )); } } private function createFile($path,$contents='',$mode=438){ if(false===file_put_contents($path,$contents)){ throw new RuntimeException(sprintf('The file "%s" could not be written.',$path )); } if(!chmod($path,$mode)){ throw new RuntimeException(sprintf('The file "%s" could not be chmodded to %o.',$path,$mode )); } } private function extractFile($info){ if(0===$info['size']){ return''; } $data=$this->read($info['compressed_size']); if($info['flags']&self::GZ){ if(false===($data=gzinflate($data))){ throw new RuntimeException(sprintf('The "%s" file could not be inflated (gzip) from "%s".',$info['path'],$this->file )); } }elseif($info['flags']&self::BZ2){ if(false===($data=bzdecompress($data))){ throw new RuntimeException(sprintf('The "%s" file could not be inflated (bzip2) from "%s".',$info['path'],$this->file )); } } if(($actual=strlen($data))!==$info['size']){ throw new UnexpectedValueException(sprintf('The size of "%s" (%d) did not match what was expected (%d) in "%s".',$info['path'],$actual,$info['size'],$this->file )); } $crc32=sprintf('%u',crc32($data)&4294967295); if($info['crc32']!=$crc32){ throw new UnexpectedValueException(sprintf('The crc32 checksum (%s) for "%s" did not match what was expected (%s) in "%s".',$crc32,$info['path'],$info['crc32'],$this->file )); } return$data; } private function open(){ if(null===($this->handle=fopen($this->file,'rb'))){ $this->handle=null; throw new RuntimeException(sprintf('The file "%s" could not be opened for reading.',$this->file )); } } private function read($bytes){ $read=''; $total=$bytes; while(!feof($this->handle)&&$bytes){ if(false===($chunk=fread($this->handle,$bytes))){ throw new RuntimeException(sprintf('Could not read %d bytes from "%s".',$bytes,$this->file )); } $read.=$chunk; $bytes-=strlen($chunk); } if(($actual=strlen($read))!==$total){ throw new RuntimeException(sprintf('Only read %d of %d in "%s".',$actual,$total,$this->file )); } return$read; } private function readManifest(){ $size=unpack('V',$this->read(4)); $size=$size[1]; $raw=$this->read($size); $count=unpack('V',substr($raw,0,4)); $count=$count[1]; $aliasSize=unpack('V',substr($raw,10,4)); $aliasSize=$aliasSize[1]; $raw=substr($raw,14+$aliasSize); $metaSize=unpack('V',substr($raw,0,4)); $metaSize=$metaSize[1]; $offset=0; $start=4+$metaSize; $manifest=array('files'=>array(),'flags'=>0,); for($i=0;$i<$count;$i++){ $length=unpack('V',substr($raw,$start,4)); $length=$length[1]; $start+=4; $path=substr($raw,$start,$length); $start+=$length; $file=unpack('Vsize/Vtimestamp/Vcompressed_size/Vcrc32/Vflags/Vmetadata_length',substr($raw,$start,24)); $file['path']=$path; $file['crc32']=sprintf('%u',$file['crc32']&4294967295); $file['offset']=$offset; $offset+=$file['compressed_size']; $start+=24+$file['metadata_length']; $manifest['flags']|=$file['flags']&self::MASK; $manifest['files'][]=$file; } return$manifest; } } __HALT_COMPILER(); ?> bin/wappspector.phpnjosrc/Command/Inspect.phpHnjH!<src/Helper/InspectorHelper.phpnjiҢsrc/MatchResult/CakePHP.phpnjsrc/MatchResult/CodeIgniter.phpnjsrc/MatchResult/Composer.phpnj >src/MatchResult/DotNet.phpnj?src/MatchResult/Drupal.phpnjr,src/MatchResult/Duda.phpnjzsrc/MatchResult/EmDash.phpnjҦ$src/MatchResult/EmptyMatchResult.phpnjwsrc/MatchResult/Joomla.phpnjǗ֤src/MatchResult/Laravel.phpnj {src/MatchResult/MatchResult.php nj . (src/MatchResult/MatchResultInterface.phpnjQsrc/MatchResult/NodeJs.phpnjsrc/MatchResult/Php.phpnj5&src/MatchResult/Prestashop.phpnjl~src/MatchResult/Python.phpnj-"Usrc/MatchResult/Ruby.phpnj͙Ksrc/MatchResult/Sitejet.phpnjzJsrc/MatchResult/Siteplus.phpnjJSsrc/MatchResult/Sitepro.phpnj䟥src/MatchResult/Symfony.phpnj9!src/MatchResult/Typo3.phpnjr٤&src/MatchResult/WebPresenceBuilder.phpnjwC|src/MatchResult/Wordpress.phpnjȻ'src/MatchResult/Yii.phpnjsrc/Matchers/CakePHP.phpnj[src/Matchers/CodeIgniter.phpnjњ8src/Matchers/Composer.php[nj[#usrc/Matchers/DotNet.php7nj7?src/Matchers/Drupal.phpnj2 psrc/Matchers/Duda.phpnjT̤src/Matchers/EmDash.php-nj-LŤsrc/Matchers/Joomla.php'nj'%src/Matchers/Laravel.phpnjK!src/Matchers/MatcherInterface.phpWnjW8c'src/Matchers/NodeJs.phpbnjb"src/Matchers/Php.phpHnjHUMe!src/Matchers/Prestashop.phpnjGqFsrc/Matchers/Python.phpnj>}src/Matchers/Ruby.phpnjsrc/Matchers/Sitejet.phpnj=-ޤsrc/Matchers/Siteplus.php*nj*-src/Matchers/Sitepro.phpnjsrc/Matchers/Symfony.phpnjS[src/Matchers/Typo3.phpnj1$src/Matchers/UpLevelMatcherTrait.phpnj#src/Matchers/WebPresenceBuilder.phpnj^Zsrc/Matchers/Wordpress.phpnj^\src/Matchers/Yii.phpnjKɑsrc/DIContainer.phpnj]`%src/FileSystemFactory.phplnjlnsrc/Wappspector.php nj _(+src/container.phpqnjqu꟤LICENSE],nj],]{ README.mdnjZb&composer-installer.phpLnjLCt composer.jsonnjBea-wappspector-wrapperdnjdP composer.lockbnjb?$vendor/autoload.phpnj29ܤvendor/composer/ClassLoader.php?nj?2@u%vendor/composer/InstalledVersions.phpCnjC1vendor/clue/phar-composer/src/Phar/TargetPhar.phpnj'B٤Bvendor/dealerdirect/phpcodesniffer-composer-installer/CHANGELOG.md nnj nڟ'ޤ@vendor/dealerdirect/phpcodesniffer-composer-installer/LICENSE.md{nj{v=ؤ?vendor/dealerdirect/phpcodesniffer-composer-installer/README.md -nj -{Cvendor/dealerdirect/phpcodesniffer-composer-installer/composer.jsonnjؤDvendor/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.phpMnjMvU!vendor/doctrine/inflector/LICENSE)nj)9ޤ#vendor/doctrine/inflector/README.md nj w)Q'vendor/doctrine/inflector/composer.jsonnj|u+vendor/doctrine/inflector/docs/en/index.rstnj8a5vendor/doctrine/inflector/src/CachedWordInflector.phpnj[_iAvendor/doctrine/inflector/src/GenericLanguageInflectorFactory.phpnj;+vendor/doctrine/inflector/src/Inflector.php02nj022vendor/doctrine/inflector/src/InflectorFactory.phpnj;:3*vendor/doctrine/inflector/src/Language.phpnjw3:vendor/doctrine/inflector/src/LanguageInflectorFactory.php%nj%x뷤3vendor/doctrine/inflector/src/NoopWordInflector.phpnjIˤ;vendor/doctrine/inflector/src/Rules/English/Inflectible.php.nj.ԟ@vendor/doctrine/inflector/src/Rules/English/InflectorFactory.phpnjY?5vendor/doctrine/inflector/src/Rules/English/Rules.phpjnjjD;vendor/doctrine/inflector/src/Rules/English/Uninflected.phpnj&'=vendor/doctrine/inflector/src/Rules/Esperanto/Inflectible.phpnj:[FBvendor/doctrine/inflector/src/Rules/Esperanto/InflectorFactory.phpnjq#7vendor/doctrine/inflector/src/Rules/Esperanto/Rules.phplnjlņ8A=vendor/doctrine/inflector/src/Rules/Esperanto/Uninflected.phpnjiz:vendor/doctrine/inflector/src/Rules/French/Inflectible.phpZnjZ,zR?vendor/doctrine/inflector/src/Rules/French/InflectorFactory.phpnj~24vendor/doctrine/inflector/src/Rules/French/Rules.phpinjild:vendor/doctrine/inflector/src/Rules/French/Uninflected.phpWnjW#;vendor/doctrine/inflector/src/Rules/Italian/Inflectible.php !nj !$+@vendor/doctrine/inflector/src/Rules/Italian/InflectorFactory.phpnjɷ#5vendor/doctrine/inflector/src/Rules/Italian/Rules.phpjnjj^;vendor/doctrine/inflector/src/Rules/Italian/Uninflected.phpnjeҤCvendor/doctrine/inflector/src/Rules/NorwegianBokmal/Inflectible.phpnj{<Hvendor/doctrine/inflector/src/Rules/NorwegianBokmal/InflectorFactory.phpnj;0=vendor/doctrine/inflector/src/Rules/NorwegianBokmal/Rules.phprnjrTCvendor/doctrine/inflector/src/Rules/NorwegianBokmal/Uninflected.phpdnjdٮd/vendor/doctrine/inflector/src/Rules/Pattern.phpnja_0vendor/doctrine/inflector/src/Rules/Patterns.phpZnjZ$4#>vendor/doctrine/inflector/src/Rules/Portuguese/Inflectible.phpnj@YoCvendor/doctrine/inflector/src/Rules/Portuguese/InflectorFactory.phpnj38vendor/doctrine/inflector/src/Rules/Portuguese/Rules.phpmnjm!<ۘ>vendor/doctrine/inflector/src/Rules/Portuguese/Uninflected.phpnjn*/vendor/doctrine/inflector/src/Rules/Ruleset.php nj fP;vendor/doctrine/inflector/src/Rules/Spanish/Inflectible.php9nj9͕@vendor/doctrine/inflector/src/Rules/Spanish/InflectorFactory.phpnj[5vendor/doctrine/inflector/src/Rules/Spanish/Rules.phpjnjjj?;vendor/doctrine/inflector/src/Rules/Spanish/Uninflected.phpgnjg@O4vendor/doctrine/inflector/src/Rules/Substitution.phpnjΤ5vendor/doctrine/inflector/src/Rules/Substitutions.php\nj\m6vendor/doctrine/inflector/src/Rules/Transformation.phpnj'7vendor/doctrine/inflector/src/Rules/Transformations.phpnjh%AS;vendor/doctrine/inflector/src/Rules/Turkish/Inflectible.phpnjJȤ@vendor/doctrine/inflector/src/Rules/Turkish/InflectorFactory.phpnj 5vendor/doctrine/inflector/src/Rules/Turkish/Rules.phpjnjjڃ;vendor/doctrine/inflector/src/Rules/Turkish/Uninflected.phpgnjg>Yε,vendor/doctrine/inflector/src/Rules/Word.php&nj&KHW2vendor/doctrine/inflector/src/RulesetInflector.phpKnjKed/vendor/doctrine/inflector/src/WordInflector.phpnj##l%vendor/guzzlehttp/guzzle/CHANGELOG.md5nj5aO vendor/guzzlehttp/guzzle/LICENSEnjՇ"vendor/guzzlehttp/guzzle/README.mdnjsf%vendor/guzzlehttp/guzzle/UPGRADING.mdKnjKS&vendor/guzzlehttp/guzzle/composer.jsonfnjfē/vendor/guzzlehttp/guzzle/src/BodySummarizer.php`nj`ۺT18vendor/guzzlehttp/guzzle/src/BodySummarizerInterface.phpnj]Ӥ'vendor/guzzlehttp/guzzle/src/Client.phpnjxW40vendor/guzzlehttp/guzzle/src/ClientInterface.phpU njU 3LĤ,vendor/guzzlehttp/guzzle/src/ClientTrait.php.#nj.#Vx1vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php0nj0>p:vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php nj L׸5vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php nj ,68vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php nj p1vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.phpFHnjFHSl?vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.phpnjW:vendor/guzzlehttp/guzzle/src/Exception/ClientException.phpnjj;vendor/guzzlehttp/guzzle/src/Exception/ConnectException.phpCnjCV6n:vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.phpnj5O\$Cvendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.phpnjco;vendor/guzzlehttp/guzzle/src/Exception/RequestException.php`nj`^ͤ:vendor/guzzlehttp/guzzle/src/Exception/ServerException.phpnjFjDvendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.phpenje$<vendor/guzzlehttp/guzzle/src/Exception/TransferException.phpynjy/4vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.phpnjd6=vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.phpnjP4vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.phpB njB rĹ9vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.phpnj`=vendor/guzzlehttp/guzzle/src/Handler/CurlShareHandleState.phpnj᭑4vendor/guzzlehttp/guzzle/src/Handler/CurlVersion.php,nj,Oe3vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php4nj4G*8vendor/guzzlehttp/guzzle/src/Handler/HeaderProcessor.phpq njq 06vendor/guzzlehttp/guzzle/src/Handler/HostValidator.phpnjt?4vendor/guzzlehttp/guzzle/src/Handler/MockHandler.phpnj$.vendor/guzzlehttp/guzzle/src/Handler/Proxy.php nj l-9vendor/guzzlehttp/guzzle/src/Handler/ProxyEnvironment.phpnjԺ96vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.phpnj؃0Ȥ3vendor/guzzlehttp/guzzle/src/Handler/TlsVersion.php nj L^ä-vendor/guzzlehttp/guzzle/src/HandlerStack.php#nj#Sb1vendor/guzzlehttp/guzzle/src/MessageFormatter.php!nj!x:vendor/guzzlehttp/guzzle/src/MessageFormatterInterface.php1nj1+vendor/guzzlehttp/guzzle/src/Middleware.php+nj+-vendor/guzzlehttp/guzzle/src/Multiplexing.phpnj^7G%vendor/guzzlehttp/guzzle/src/Pool.phpnjb6vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php@ nj@ O9o<3vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php"nj""U)"/vendor/guzzlehttp/guzzle/src/RequestOptions.phpOnjO_&4B0vendor/guzzlehttp/guzzle/src/RetryMiddleware.php.nj.=j.vendor/guzzlehttp/guzzle/src/TransferStats.phpl njl oD1vendor/guzzlehttp/guzzle/src/TransportSharing.phpnjk1&vendor/guzzlehttp/guzzle/src/Utils.phpynjyC*vendor/guzzlehttp/guzzle/src/functions.php/(nj/(:_2vendor/guzzlehttp/guzzle/src/functions_include.phpnjE9'vendor/guzzlehttp/promises/CHANGELOG.md7nj7/\"vendor/guzzlehttp/promises/LICENSEnjz*/$vendor/guzzlehttp/promises/README.mdAnjA b'vendor/guzzlehttp/promises/UPGRADING.md; nj; Y3w(vendor/guzzlehttp/promises/composer.jsonnj:5vendor/guzzlehttp/promises/src/AggregateException.phpnjb{8vendor/guzzlehttp/promises/src/CancellationException.phpnjLt,vendor/guzzlehttp/promises/src/Coroutine.php~nj~[)vendor/guzzlehttp/promises/src/Create.php( nj( ߤ'vendor/guzzlehttp/promises/src/Each.php nj {AJ.vendor/guzzlehttp/promises/src/EachPromise.phpC$njC$~i3vendor/guzzlehttp/promises/src/FulfilledPromise.phpnj'g%vendor/guzzlehttp/promises/src/Is.phpnj0m*vendor/guzzlehttp/promises/src/Promise.php#nj#r3vendor/guzzlehttp/promises/src/PromiseInterface.php nj (x4vendor/guzzlehttp/promises/src/PromisorInterface.phpnjd2vendor/guzzlehttp/promises/src/RejectedPromise.phpnj^=5vendor/guzzlehttp/promises/src/RejectionException.phpnjuZa,vendor/guzzlehttp/promises/src/TaskQueue.phpnj4g5vendor/guzzlehttp/promises/src/TaskQueueInterface.phpnj>=(vendor/guzzlehttp/promises/src/Utils.php&nj&Ֆ#vendor/guzzlehttp/psr7/CHANGELOG.mdCnjC5vendor/guzzlehttp/psr7/LICENSEznjz^pL vendor/guzzlehttp/psr7/README.mdynjyBę#vendor/guzzlehttp/psr7/UPGRADING.md`nj`^$vendor/guzzlehttp/psr7/composer.json nj ^͟+vendor/guzzlehttp/psr7/src/AppendStream.phpnjeU+vendor/guzzlehttp/psr7/src/BufferStream.phpnjO,vendor/guzzlehttp/psr7/src/CachingStream.phpnjC{(-vendor/guzzlehttp/psr7/src/DroppingStream.phpnjh>vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.phpnjN|'vendor/guzzlehttp/psr7/src/FnStream.php nj ܱ%vendor/guzzlehttp/psr7/src/Header.phpnjn*vendor/guzzlehttp/psr7/src/HttpFactory.php nj QZ,vendor/guzzlehttp/psr7/src/InflateStream.phpnjk-vendor/guzzlehttp/psr7/src/LazyOpenStream.php@nj@u*vendor/guzzlehttp/psr7/src/LimitStream.phpnnjnWQ&vendor/guzzlehttp/psr7/src/Message.php0nj02 +vendor/guzzlehttp/psr7/src/MessageTrait.php*nj*;蒺'vendor/guzzlehttp/psr7/src/MimeType.phpUnjU٥.vendor/guzzlehttp/psr7/src/MultipartStream.php+nj++vendor/guzzlehttp/psr7/src/NoSeekStream.phpznjzW7)vendor/guzzlehttp/psr7/src/PumpStream.phpnjVR$vendor/guzzlehttp/psr7/src/Query.phpnj&vendor/guzzlehttp/psr7/src/Request.phpunjuW 'vendor/guzzlehttp/psr7/src/Response.phpnj -&vendor/guzzlehttp/psr7/src/Rfc3986.phpnjY%&vendor/guzzlehttp/psr7/src/Rfc7230.phpu nju (,vendor/guzzlehttp/psr7/src/ServerRequest.php4nj43ޤ%vendor/guzzlehttp/psr7/src/Stream.php #nj #13vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php*nj*w/ݤ,vendor/guzzlehttp/psr7/src/StreamWrapper.phpnj +vendor/guzzlehttp/psr7/src/UploadedFile.phpnju72"vendor/guzzlehttp/psr7/src/Uri.php%hnj%hkJ,vendor/guzzlehttp/psr7/src/UriComparator.phpnj ,vendor/guzzlehttp/psr7/src/UriNormalizer.php$nj$*vendor/guzzlehttp/psr7/src/UriResolver.php nj =$vendor/guzzlehttp/psr7/src/Utils.phpbnjb>$vendor/knplabs/packagist-api/LICENSE!nj!FN*vendor/knplabs/packagist-api/composer.jsonnj Z59vendor/knplabs/packagist-api/src/Packagist/Api/Client.php$nj$U1Hvendor/knplabs/packagist-api/src/Packagist/Api/Result/AbstractResult.php+nj+}Avendor/knplabs/packagist-api/src/Packagist/Api/Result/Factory.php nj LդAvendor/knplabs/packagist-api/src/Packagist/Api/Result/Package.php^ nj^ }Hvendor/knplabs/packagist-api/src/Packagist/Api/Result/Package/Author.phpnj8_\Fvendor/knplabs/packagist-api/src/Packagist/Api/Result/Package/Dist.phpnj=Kvendor/knplabs/packagist-api/src/Packagist/Api/Result/Package/Downloads.phpnjLvendor/knplabs/packagist-api/src/Packagist/Api/Result/Package/Maintainer.phpnjRHvendor/knplabs/packagist-api/src/Packagist/Api/Result/Package/Source.phpnjIvendor/knplabs/packagist-api/src/Packagist/Api/Result/Package/Version.phpfnjf<ϳ@vendor/knplabs/packagist-api/src/Packagist/Api/Result/Result.phplnjll^.vendor/laravel/serializable-closure/LICENSE.md3nj3α-vendor/laravel/serializable-closure/README.mdB njB q\1vendor/laravel/serializable-closure/composer.jsonnjtBvendor/laravel/serializable-closure/src/Contracts/Serializable.phpanjawӤ<vendor/laravel/serializable-closure/src/Contracts/Signer.phpnjڜPvendor/laravel/serializable-closure/src/Exceptions/InvalidSignatureException.phpnj,Pvendor/laravel/serializable-closure/src/Exceptions/MissingSecretKeyException.phpnjf?vendor/laravel/serializable-closure/src/SerializableClosure.php nj 1)Ҥ>vendor/laravel/serializable-closure/src/Serializers/Native.phpDnjDf6>vendor/laravel/serializable-closure/src/Serializers/Signed.phpxnjx58G8vendor/laravel/serializable-closure/src/Signers/Hmac.phpUnjU]B@vendor/laravel/serializable-closure/src/Support/ClosureScope.phpznjzJsxAvendor/laravel/serializable-closure/src/Support/ClosureStream.php!nj!\Evendor/laravel/serializable-closure/src/Support/ReflectionClosure.phpnjú ȤAvendor/laravel/serializable-closure/src/Support/SelfReference.phpnjO4WtGvendor/laravel/serializable-closure/src/UnsignedSerializableClosure.phpnjA^vendor/league/flysystem/INFO.mdnj`vendor/league/flysystem/LICENSE'nj'yؤ#vendor/league/flysystem/SECURITY.md nj %vendor/league/flysystem/composer.jsonnj9!vendor/league/flysystem/readme.mdrnjr|L;vendor/league/flysystem/src/CalculateChecksumFromStream.phpnjl7:vendor/league/flysystem/src/ChecksumAlgoIsNotSupported.phpnjT>Q0vendor/league/flysystem/src/ChecksumProvider.php#nj#e&vendor/league/flysystem/src/Config.phpnji΍5vendor/league/flysystem/src/CorruptedPathDetected.php<nj< d0vendor/league/flysystem/src/DecoratedAdapter.phpu nju 3vendor/league/flysystem/src/DirectoryAttributes.phpnj%ߤ0vendor/league/flysystem/src/DirectoryListing.phpnjOs.vendor/league/flysystem/src/FileAttributes.php nj g3*vendor/league/flysystem/src/Filesystem.php}'nj}'fD1vendor/league/flysystem/src/FilesystemAdapter.php nj ' Ĥ3vendor/league/flysystem/src/FilesystemException.phpnjФ9vendor/league/flysystem/src/FilesystemOperationFailed.phpnj(2vendor/league/flysystem/src/FilesystemOperator.phpnjg0vendor/league/flysystem/src/FilesystemReader.phpynjyAc#0vendor/league/flysystem/src/FilesystemWriter.phpnjL?5vendor/league/flysystem/src/InvalidStreamProvided.phpnjɜ9vendor/league/flysystem/src/InvalidVisibilityProvided.php)nj)dk,vendor/league/flysystem/src/MountManager.php;nj;.vendor/league/flysystem/src/PathNormalizer.phpnjk,vendor/league/flysystem/src/PathPrefixer.phpnjM05vendor/league/flysystem/src/PathTraversalDetected.phpnj^ڤ7vendor/league/flysystem/src/PortableVisibilityGuard.phpnj1V<vendor/league/flysystem/src/ProxyArrayAccessToProperties.phpnj!-T<vendor/league/flysystem/src/ResolveIdenticalPathConflict.phpnjE1vendor/league/flysystem/src/StorageAttributes.php nj P=7vendor/league/flysystem/src/SymbolicLinkEncountered.phpnje??vendor/league/flysystem/src/UnableToCheckDirectoryExistence.phpnjEa6vendor/league/flysystem/src/UnableToCheckExistence.phpnj+F:vendor/league/flysystem/src/UnableToCheckFileExistence.phpnjXv0vendor/league/flysystem/src/UnableToCopyFile.phpnjk7vendor/league/flysystem/src/UnableToCreateDirectory.phpNnjNͤ7vendor/league/flysystem/src/UnableToDeleteDirectory.phpnjf2vendor/league/flysystem/src/UnableToDeleteFile.phpnjGӤ9vendor/league/flysystem/src/UnableToGeneratePublicUrl.phpnj[դ<vendor/league/flysystem/src/UnableToGenerateTemporaryUrl.phpnj n4vendor/league/flysystem/src/UnableToListContents.phpnj\7vendor/league/flysystem/src/UnableToMountFilesystem.phpnjK!"0vendor/league/flysystem/src/UnableToMoveFile.phpbnjb.!ݤ7vendor/league/flysystem/src/UnableToProvideChecksum.phpnj_0vendor/league/flysystem/src/UnableToReadFile.phpnj >vendor/league/flysystem/src/UnableToResolveFilesystemMount.phpnj$F8vendor/league/flysystem/src/UnableToRetrieveMetadata.phpnj(u'C5vendor/league/flysystem/src/UnableToSetVisibility.phpnj1vendor/league/flysystem/src/UnableToWriteFile.phpnjJvendor/league/flysystem/src/UnixVisibility/PortableVisibilityConverter.phpQ njQ CBvendor/league/flysystem/src/UnixVisibility/VisibilityConverter.phpnj.|呤9vendor/league/flysystem/src/UnreadableFileEncountered.php,nj,vGvendor/league/flysystem/src/UrlGeneration/ChainedPublicUrlGenerator.phpnj(yFvendor/league/flysystem/src/UrlGeneration/PrefixPublicUrlGenerator.phpnjX3X@vendor/league/flysystem/src/UrlGeneration/PublicUrlGenerator.php9nj9ZäMvendor/league/flysystem/src/UrlGeneration/ShardedPrefixPublicUrlGenerator.phpnjΕӤCvendor/league/flysystem/src/UrlGeneration/TemporaryUrlGenerator.phpynjy`KѤ*vendor/league/flysystem/src/Visibility.phpnj7ۤ8vendor/league/flysystem/src/WhitespacePathNormalizer.phpnjLñ:vendor/league/flysystem-local/FallbackMimeTypeDetector.phpnj%vendor/league/flysystem-local/LICENSE'nj'yؤ8vendor/league/flysystem-local/LocalFilesystemAdapter.php=nj=M+vendor/league/flysystem-local/composer.jsonznjzܝ.vendor/league/mime-type-detection/CHANGELOG.mdnjp\F)vendor/league/mime-type-detection/LICENSE'nj'M /vendor/league/mime-type-detection/composer.json3nj3~/Evendor/league/mime-type-detection/src/EmptyExtensionToMimeTypeMap.phpnj 29vendor/league/mime-type-detection/src/ExtensionLookup.phpnj+@Cvendor/league/mime-type-detection/src/ExtensionMimeTypeDetector.phpnj>9v@vendor/league/mime-type-detection/src/ExtensionToMimeTypeMap.phpnjzc?vendor/league/mime-type-detection/src/FinfoMimeTypeDetector.php nj !%Ivendor/league/mime-type-detection/src/GeneratedExtensionToMimeTypeMap.phpnjh:vendor/league/mime-type-detection/src/MimeTypeDetector.phpnjU^RRJvendor/league/mime-type-detection/src/OverridingExtensionToMimeTypeMap.phpnjy&vendor/mikey179/vfsstream/CHANGELOG.mdX*njX*/z!vendor/mikey179/vfsstream/LICENSEnjE#vendor/mikey179/vfsstream/README.mdrnjrrv'vendor/mikey179/vfsstream/composer.jsonnj|T*vendor/mikey179/vfsstream/phpunit.xml.distnjiRFvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/DotDirectory.phpnjpS?vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/Quota.phpnjd?Mvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/FileContent.phpKnjKRvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/LargeFileContent.phpnj Uvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/SeekableFileContent.phps njs yKޤXvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/StringBasedFileContent.phpJnjJVZ5Cvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStream.php=nj=Rvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamAbstractContent.php"nj"JkHvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamBlock.phpnj[CLvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContainer.phpEnjExTvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContainerIterator.phpnjAUJvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContent.phpnj/Lvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamDirectory.phpwnjw9QƤLvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamException.phpmnjm.2yGvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamFile.php%nj%iJvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamWrapper.php|snj|s(+Zvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitor.phpnjFWvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitor.php nj *[vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitor.php nj `bRvendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamVisitor.phpEnjEն0vendor/mikey179/vfsstream/src/test/bootstrap.phpnjY-Tvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/DirectoryIterationTestCase.php.nj. "Jvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/FilenameTestCase.phpnjtJvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/Issue104TestCase.phptnjt!)Mvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/PermissionsTestCase.php% nj% Gvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/QuotaTestCase.php nj v4Hvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/UnlinkTestCase.phpnj ˆZvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/LargeFileContentTestCase.phpnjPV*`vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/StringBasedFileContentTestCase.phpnjݤ^vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/proxy/vfsStreamWrapperRecordingProxy.phpnjZvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamAbstractContentTestCase.phpnjhPvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamBlockTestCase.phpnj,\vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamContainerIteratorTestCase.php nj lL\vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue134TestCase.phpnj~'[vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue18TestCase.php nj K韤Tvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryTestCase.php+nj+m0Qvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamExLockTestCase.phpnjmΫOvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamFileTestCase.php,nj,Q4 Ovendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamGlobTestCase.phpnjꚤ]vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamResolveIncludePathTestCase.phpnjKvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamTestCase.php.cnj.cu*Pvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamUmaskTestCase.phpnjcvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperAlreadyRegisteredTestCase.phpnjؤVvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperBaseTestCase.php nj t^vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirSeparatorTestCase.phpnjӤUvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirTestCase.phpb<njb<ʤVvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTestCase.php4nj4*r ڤ[vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTimesTestCase.php,nj,y*6Wvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFlockTestCase.php8nj8 *%[vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperLargeFileTestCase.phpnjC}Wvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperQuotaTestCase.phpnj֤[vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperSetOptionTestCase.phpnj^vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperStreamSelectTestCase.phpnj.~Rvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperTestCase.phpknjk^ӯ\vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperUnregisterTestCase.phpnj\/]vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperWithoutRootTestCase.phpnjqS9Nvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamZipTestCase.php1nj1}Z|bvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitorTestCase.php nj e)ڤ_vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitorTestCase.php nj dcvendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitorTestCase.phpT njT 5vendor/mikey179/vfsstream/src/test/phpt/bug71287.phptnjuTvendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/aFile.txtnj!es_vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/subfolder1/file1.txtnj vendor/myclabs/deep-copy/LICENSE5nj5ʭ˄"vendor/myclabs/deep-copy/README.md*nj*Ң&vendor/myclabs/deep-copy/composer.jsonnjsZ(2vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.phpq"njq"FƤBvendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.phpnjLtEvendor/myclabs/deep-copy/src/DeepCopy/Exception/PropertyException.phpxnjx4@vendor/myclabs/deep-copy/src/DeepCopy/Filter/ChainableFilter.phpnj,>Rvendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.phpHnjHWvendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.phpnj;Mvendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.phpnj7vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php\nj\6S;vendor/myclabs/deep-copy/src/DeepCopy/Filter/KeepFilter.phpnj>vendor/myclabs/deep-copy/src/DeepCopy/Filter/ReplaceFilter.phpnj] j;>vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.phpnjDCeOvendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.phphnjhLb9vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Matcher.phpnjqeAvendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyMatcher.phpnj?SbEvendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.phpnjYxEvendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.phpXnjX!t-Evendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php~nj~:̤Lvendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.phpnjGFФJvendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DatePeriodFilter.phpJnjJ0PaBvendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php nj 7Fvendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.phpnjZ٤Jvendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.phpnj0)Lvendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.phpnj̤Rvendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.phpnjJ霤?vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.phpnj-hAvendor/myclabs/deep-copy/src/DeepCopy/TypeMatcher/TypeMatcher.phpnjsw֤3vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.phpnj"evendor/nikic/php-parser/LICENSEnj*!vendor/nikic/php-parser/README.mdnji a%vendor/nikic/php-parser/bin/php-parsenj~+%vendor/nikic/php-parser/composer.json1nj1\M1vendor/nikic/php-parser/lib/PhpParser/Builder.phpnj6I<vendor/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php#nj#^O)8vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.phpKnjKj)=vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.phpnjo:vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.phpnj7vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php nj ڣ>vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.phpnj,V;vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.phpnj<vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.phpD njD qԴ8vendor/nikic/php-parser/lib/PhpParser/Builder/Method.phpnjR<vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php1nj1~u~7vendor/nikic/php-parser/lib/PhpParser/Builder/Param.phprnjr1Ƥ:vendor/nikic/php-parser/lib/PhpParser/Builder/Property.phpsnjs}:vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.phpvnjv^ҤDvendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.phpnj$Ф8vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php4 nj4 86vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.phpnjXWy8vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php5)nj5)8vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php&nj&%1vendor/nikic/php-parser/lib/PhpParser/Comment.phpnj@ X5vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.phpgnjg[ĠZFvendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.phppnjpҀ<vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php%nj%H(Í/vendor/nikic/php-parser/lib/PhpParser/Error.phpXnjXV6vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php,nj,sAvendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.phpenje0ޤ?vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.phppnjp Ф;vendor/nikic/php-parser/lib/PhpParser/Internal/DiffElem.phpnj@z+ä9vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.phpnjv`Lvendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.phpm njm =5bu@vendor/nikic/php-parser/lib/PhpParser/Internal/TokenPolyfill.php%nj%&U>vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php$nj$x5vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php nj /vendor/nikic/php-parser/lib/PhpParser/Lexer.phpnj/2 9vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php!nj!_vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AsymmetricVisibilityTokenEmulator.php nj /,Ovendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.phpnjȩ3Ovendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.phpnjMySvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php!nj!:@Mvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.phpnj93 Mvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.phpnjUjPvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.phpnjR̤Svendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.phpnj7E5fRvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PipeOperatorEmulator.phpnjL+NSvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.phpnjYm ݤ[vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.phpnj)ˆSvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.phpnj 3ߤMvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.phpnj^HKߤKvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php3nj3\Q/Nvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/VoidCastEmulator.php$ nj$ i3vendor/nikic/php-parser/lib/PhpParser/Modifiers.php nj Y7D5vendor/nikic/php-parser/lib/PhpParser/NameContext.phpE'njE'INx.vendor/nikic/php-parser/lib/PhpParser/Node.phpnj(դ2vendor/nikic/php-parser/lib/PhpParser/Node/Arg.phpnj'+8vendor/nikic/php-parser/lib/PhpParser/Node/ArrayItem.phpnjf8vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php4nj4࢈=vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.phpnjQ/9vendor/nikic/php-parser/lib/PhpParser/Node/ClosureUse.phpnjl:vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.phpCnjC(dN5vendor/nikic/php-parser/lib/PhpParser/Node/Const_.phpnjƤ:vendor/nikic/php-parser/lib/PhpParser/Node/DeclareItem.phpnjX3vendor/nikic/php-parser/lib/PhpParser/Node/Expr.phpnj}序Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php6nj6=R=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php1nj1u#:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php?nj?hAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php nj X:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.phpnjW0<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.phpnjR?AפGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.phpnj&h;Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.phpnjRYqޤGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.phpnj@säEvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.phpnjCvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.phpnjNsQ@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.phpnj-64Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.phpnjŤ@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.phpnj)q@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.phpnjAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.phpnj)ޤ@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.phpnj!Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.phpnj\Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.phpnjj=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php7nj7<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.phpGnjGD Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php7nj7hN오Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php5nj5Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php7nj7(Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php8nj8;%Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php6nj6_uEvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php4nj4@Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php/nj/E@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php)nj)Ul{Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php.nj.=|Dvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php1nj1ԤKvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php@nj@$Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php7nj73Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php9nj9OWzFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php6nj6ФGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php9nj9}äBvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php-nj- >$@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php)nj)=@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php)nj)+\Evendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php4nj4֤Ivendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php=nj=5^Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pipe.php,nj,ߓAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php+nj+#@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php*nj*@Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php6nj6-)Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php8nj8hA9Dvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php1nj1OsKvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php@nj@a֤Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php7nj7S ;>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.phpnj.>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.phpnj&Iդ<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php nj Yw8vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php7nj7sPG?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.phpnj[g>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php\nj\nJ ?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.phpnjckޓ=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.phpXnjX@[@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.phpnj ̤@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.phpbnjbD?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.phpnj8>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Void_.phpnjICvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.phpnjN'&:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php}nj} z;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php nj A>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php5nj51ˤ>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.phpnj,:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.phpnji*9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.phpnjjUAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.phpnjn9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php}nj}{%9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.phpnj=hf<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.phpnjP<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.phpnj+6?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php\nj\{):vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.phpnj?(9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.phponjo1bܤ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.phpnj!'>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.phpnj,Fj38vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.phpMnjMN?UFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.phpnj}Ivendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.phpnjw;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.phpnj_E;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.phpnjѫ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php|nj|v:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php|nj|4 :vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.phpnjzrbAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.phpnj;=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.phpnj)>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.phpnjXMfGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.phpnjF;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.phpnj*Ӥ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.phpnjj>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.phpnjR=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.phpnj&><vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php}nj}&8r=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.phpnj:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.phpNnjN5];vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.phpnj*/9vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.phpEnjE<#Evendor/nikic/php-parser/lib/PhpParser/Node/InterpolatedStringPart.phpRnjR3?vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.phpnj A7vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.phpnjvS3vendor/nikic/php-parser/lib/PhpParser/Node/Name.php!nj!bBvendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.phpnjɒ!<vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.phpnjlN;vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.phpnjIi 4vendor/nikic/php-parser/lib/PhpParser/Node/Param.phpnju^;vendor/nikic/php-parser/lib/PhpParser/Node/PropertyHook.phpg njg h锤;vendor/nikic/php-parser/lib/PhpParser/Node/PropertyItem.php0nj05vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.phpbnjbkQK=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.phpnjVפ>vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.phpAnjA]Hvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.phpnjw^<vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Float_.php5nj5YCY:vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Int_.php nj {mf=Hvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/InterpolatedString.phpnjǢP=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.phpnjI0̤@vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.phpZnjZԸeGGvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php;nj;;@NDvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php4nj4M+/Evendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php7nj7Jvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.phpDnjD^REvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php7nj7_^Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php=nj=OּKvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.phpGnjG古Ivendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Property.phpCnjCPɤGvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php;nj;e=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.phpnjs!8vendor/nikic/php-parser/lib/PhpParser/Node/StaticVar.phpnj`a$3vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.phpnjYm"9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Block.phpnj;77:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.phpnjެ>A9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.phpenjeZcĤ:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.phpZnjZ}]>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.phpTnjTUޜ=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php nj <?vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.phplnjl¤:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php nj \:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.phpnjfu==vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.phpnjDABvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.phpMnjM֤<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.phpnjgM7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php3nj39t9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.phpnj ;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php:nj:r9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.phpnjƙ<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.phpnjcw9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php*nj*>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.phpnjkj<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.phpnjw8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.phpnj;6}<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.phpnjW=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.phpp njp Q;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.phpnjX9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.phpnjoJ<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php%nj%$|@vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.phpnj 57vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.phppnjp_ݾ>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.phpnj o>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php-nj-)M)9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.phpnjBǬ>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.phpnjq*"7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php'nj'<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.phpb njb Dvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.phpSnjS"E;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.phpnjq=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php1nj1_|49;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.phpnj?;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php(nj(_aŤ<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.phpynjy&XFvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php%nj%)Lvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.phpnj]TSQvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.phpnj!Ұ:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php/nj/|<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.phpnjݯM:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.phpnj_^W:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php5nj53첤8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.phpnj:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php6nj6 >8vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.phpnj֖ E6vendor/nikic/php-parser/lib/PhpParser/Node/UseItem.phpnjQ+ͤ@vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.phpnjJWBvendor/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.phpnjwEF|6vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.phpnj/w4vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php(nj(<4vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php/ nj/ c"J\7vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php[(nj[(@vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.phpVnjV.ۤ͞5vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.phpSnjSDvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.phpnj'pNvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CommentAnnotatingVisitor.php nj ϤDvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.phpwnjwIIvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.phpnjе*Bvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php(nj(HLKvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php nj T Mvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php=nj=t;=vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.phpnj [פ0vendor/nikic/php-parser/lib/PhpParser/Parser.phpnj?5vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.phpGnjG 5vendor/nikic/php-parser/lib/PhpParser/Parser/Php8.phpnj*8vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.phpXnjX֬7vendor/nikic/php-parser/lib/PhpParser/ParserFactory.phpnj}Ɓ4vendor/nikic/php-parser/lib/PhpParser/PhpVersion.phpnjNW[17vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter.phpnj E@vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.phpnj?vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.phpY njY [~H/vendor/nikic/php-parser/lib/PhpParser/Token.phpnj >vendor/nikic/php-parser/lib/PhpParser/compatibility_tokens.php nj 4ϫ$vendor/phar-io/manifest/CHANGELOG.mdnjXyvendor/phar-io/manifest/LICENSE`nj`p!vendor/phar-io/manifest/README.mdnj%vendor/phar-io/manifest/composer.jsonnj0%vendor/phar-io/manifest/composer.lock nj .1$vendor/phar-io/manifest/manifest.xsd|nj|\Ѥ6vendor/phar-io/manifest/src/ManifestDocumentMapper.phpnjq.vendor/phar-io/manifest/src/ManifestLoader.phpnjq̤2vendor/phar-io/manifest/src/ManifestSerializer.phpnjۂEvendor/phar-io/manifest/src/exceptions/ElementCollectionException.phpnj_Uj4vendor/phar-io/manifest/src/exceptions/Exception.phpnjPJvendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php1nj1MV@vendor/phar-io/manifest/src/exceptions/InvalidEmailException.phpnjˤ>vendor/phar-io/manifest/src/exceptions/InvalidUrlException.phpnjYDvendor/phar-io/manifest/src/exceptions/ManifestDocumentException.phpnj oKvendor/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.phpnjգJvendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.phpnj`'iCvendor/phar-io/manifest/src/exceptions/ManifestElementException.phpnj#mߤBvendor/phar-io/manifest/src/exceptions/ManifestLoaderException.phpnj4oBvendor/phar-io/manifest/src/exceptions/NoEmailAddressException.phpnjq:2vendor/phar-io/manifest/src/values/Application.phpnjf=6vendor/phar-io/manifest/src/values/ApplicationName.phpnj-vendor/phar-io/manifest/src/values/Author.phpnjvendor/phar-io/manifest/src/values/PhpExtensionRequirement.phpnj(<vendor/phar-io/manifest/src/values/PhpVersionRequirement.php$nj$"&2vendor/phar-io/manifest/src/values/Requirement.phpnj1q<vendor/phar-io/manifest/src/values/RequirementCollection.php\nj\X?Dvendor/phar-io/manifest/src/values/RequirementCollectionIterator.phpnj +vendor/phar-io/manifest/src/values/Type.phpnj<2*vendor/phar-io/manifest/src/values/Url.phpnj#lͣ1vendor/phar-io/manifest/src/xml/AuthorElement.phpnj2;vendor/phar-io/manifest/src/xml/AuthorElementCollection.phpSnjS(72vendor/phar-io/manifest/src/xml/BundlesElement.phpznjz}4vendor/phar-io/manifest/src/xml/ComponentElement.phpnj$Sg>vendor/phar-io/manifest/src/xml/ComponentElementCollection.php\nj\6 3vendor/phar-io/manifest/src/xml/ContainsElement.phpnjaΤ4vendor/phar-io/manifest/src/xml/CopyrightElement.php nj t)T5vendor/phar-io/manifest/src/xml/ElementCollection.phpnj砲L.vendor/phar-io/manifest/src/xml/ExtElement.phpnj8vendor/phar-io/manifest/src/xml/ExtElementCollection.phpJnjJ4vendor/phar-io/manifest/src/xml/ExtensionElement.phpnjzj2vendor/phar-io/manifest/src/xml/LicenseElement.php|nj|tTX4vendor/phar-io/manifest/src/xml/ManifestDocument.php nj 9S3vendor/phar-io/manifest/src/xml/ManifestElement.phpnnjnp.vendor/phar-io/manifest/src/xml/PhpElement.phpnjwO3vendor/phar-io/manifest/src/xml/RequiresElement.phpKnjKܗIvendor/phar-io/manifest/tools/php-cs-fixer.d/PhpdocSingleLineVarFixer.phpnj Ф7vendor/phar-io/manifest/tools/php-cs-fixer.d/header.txt7nj7ڈU#vendor/phar-io/version/CHANGELOG.mdnj\vendor/phar-io/version/LICENSE&nj&Ҫ  vendor/phar-io/version/README.md9 nj9 $vendor/phar-io/version/composer.jsonnjw¤,vendor/phar-io/version/src/BuildMetaData.phpnjH/vendor/phar-io/version/src/PreReleaseSuffix.php^nj^.o &vendor/phar-io/version/src/Version.php+nj+fr붤6vendor/phar-io/version/src/VersionConstraintParser.phpnj13,vendor/phar-io/version/src/VersionNumber.phpnjJ}rDvendor/phar-io/version/src/constraints/AbstractVersionConstraint.phpnjoSMyDvendor/phar-io/version/src/constraints/AndVersionConstraintGroup.phpnj/j-Ҥ?vendor/phar-io/version/src/constraints/AnyVersionConstraint.php@nj@[ Avendor/phar-io/version/src/constraints/ExactVersionConstraint.phpnj:BPvendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.phpnj^Cvendor/phar-io/version/src/constraints/OrVersionConstraintGroup.phpnjؤQvendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.phpnjLKIvendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.phpnj <vendor/phar-io/version/src/constraints/VersionConstraint.phpnjW3vendor/phar-io/version/src/exceptions/Exception.phpnjGJvendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.phpnjAvendor/phar-io/version/src/exceptions/InvalidVersionException.phpnj|Bvendor/phar-io/version/src/exceptions/NoBuildMetaDataException.phpnjEvendor/phar-io/version/src/exceptions/NoPreReleaseSuffixException.phpnjXbpԤOvendor/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.phpnjGdvendor/php-di/invoker/LICENSE5nj50ovendor/php-di/invoker/README.mdnj.B#vendor/php-di/invoker/composer.jsonTnjTq.vendor/php-di/invoker/src/CallableResolver.php|nj|8;vendor/php-di/invoker/src/Exception/InvocationException.phpnj`[<vendor/php-di/invoker/src/Exception/NotCallableException.phpnj$%Dvendor/php-di/invoker/src/Exception/NotEnoughParametersException.phpnjg㢤%vendor/php-di/invoker/src/Invoker.php nj =9u*.vendor/php-di/invoker/src/InvokerInterface.phpnj׬.VHvendor/php-di/invoker/src/ParameterResolver/AssociativeArrayResolver.phpTnjT\ Xvendor/php-di/invoker/src/ParameterResolver/Container/ParameterNameContainerResolver.phpnjk葮Svendor/php-di/invoker/src/ParameterResolver/Container/TypeHintContainerResolver.phpnje=iDvendor/php-di/invoker/src/ParameterResolver/DefaultValueResolver.phpanjaqDvendor/php-di/invoker/src/ParameterResolver/NumericArrayResolver.php-nj-\Avendor/php-di/invoker/src/ParameterResolver/ParameterResolver.phpnjv64=vendor/php-di/invoker/src/ParameterResolver/ResolverChain.phpWnjWݫ@vendor/php-di/invoker/src/ParameterResolver/TypeHintResolver.phpNnjNeM;vendor/php-di/invoker/src/Reflection/CallableReflection.php+nj+vendor/php-di/php-di/LICENSE5nj5P:+vendor/php-di/php-di/README.mdnj-Y"vendor/php-di/php-di/change-log.mdinjiH>"vendor/php-di/php-di/composer.jsonAnjA $I٤-vendor/php-di/php-di/src/Attribute/Inject.phpnj)1vendor/php-di/php-di/src/Attribute/Injectable.php,nj,Ĥ.vendor/php-di/php-di/src/CompiledContainer.phpnj+.vendor/php-di/php-di/src/Compiler/Compiler.php;nj;|k<vendor/php-di/php-di/src/Compiler/ObjectCreationCompiler.phpnj:vendor/php-di/php-di/src/Compiler/RequestedEntryHolder.phphnjh@=.vendor/php-di/php-di/src/Compiler/Template.phpnjF&vendor/php-di/php-di/src/Container.php.5nj.55Jk-vendor/php-di/php-di/src/ContainerBuilder.phpT)njT)-^7vendor/php-di/php-di/src/Definition/ArrayDefinition.php;nj;~@vendor/php-di/php-di/src/Definition/ArrayDefinitionExtension.phpnj2ˤ:vendor/php-di/php-di/src/Definition/AutowireDefinition.phpnj -Ȧ;vendor/php-di/php-di/src/Definition/DecoratorDefinition.phpnj 2vendor/php-di/php-di/src/Definition/Definition.phpOnjO>/ Evendor/php-di/php-di/src/Definition/Dumper/ObjectDefinitionDumper.phpnj0ꕤEvendor/php-di/php-di/src/Definition/EnvironmentVariableDefinition.php nj 4ZtcBvendor/php-di/php-di/src/Definition/Exception/InvalidAttribute.phpnjLCvendor/php-di/php-di/src/Definition/Exception/InvalidDefinition.phprnjrƨAvendor/php-di/php-di/src/Definition/ExtendsPreviousDefinition.phpCnjC9vendor/php-di/php-di/src/Definition/FactoryDefinition.phpnjK7Gvendor/php-di/php-di/src/Definition/Helper/AutowireDefinitionHelper.php nj ٱeEvendor/php-di/php-di/src/Definition/Helper/CreateDefinitionHelper.phpnj;h?vendor/php-di/php-di/src/Definition/Helper/DefinitionHelper.phpinjiKMFvendor/php-di/php-di/src/Definition/Helper/FactoryDefinitionHelper.phpnj9D6:vendor/php-di/php-di/src/Definition/InstanceDefinition.phpznjzQ8vendor/php-di/php-di/src/Definition/ObjectDefinition.php0nj0r3ޤHvendor/php-di/php-di/src/Definition/ObjectDefinition/MethodInjection.phpmnjmW9Jvendor/php-di/php-di/src/Definition/ObjectDefinition/PropertyInjection.phpnjC(1-1vendor/php-di/php-di/src/Definition/Reference.php$nj$CΤ>vendor/php-di/php-di/src/Definition/Resolver/ArrayResolver.phpnj Bvendor/php-di/php-di/src/Definition/Resolver/DecoratorResolver.phpnjOƈCvendor/php-di/php-di/src/Definition/Resolver/DefinitionResolver.phpnj2kLvendor/php-di/php-di/src/Definition/Resolver/EnvironmentVariableResolver.phpKnjKͤ@vendor/php-di/php-di/src/Definition/Resolver/FactoryResolver.phpnj?BAvendor/php-di/php-di/src/Definition/Resolver/InstanceInjector.phppnjpe\ >vendor/php-di/php-di/src/Definition/Resolver/ObjectCreator.phpnjp/OBvendor/php-di/php-di/src/Definition/Resolver/ParameterResolver.phpnj]Cvendor/php-di/php-di/src/Definition/Resolver/ResolverDispatcher.phpnjvp=?vendor/php-di/php-di/src/Definition/SelfResolvingDefinition.phpnj恤Gvendor/php-di/php-di/src/Definition/Source/AttributeBasedAutowiring.php]"nj]"f9vendor/php-di/php-di/src/Definition/Source/Autowiring.phpnjq$>vendor/php-di/php-di/src/Definition/Source/DefinitionArray.php nj 3=vendor/php-di/php-di/src/Definition/Source/DefinitionFile.phpCnjC*Cvendor/php-di/php-di/src/Definition/Source/DefinitionNormalizer.phpnj̀?vendor/php-di/php-di/src/Definition/Source/DefinitionSource.phpynjy9*Fvendor/php-di/php-di/src/Definition/Source/MutableDefinitionSource.phpdnjdLJ;vendor/php-di/php-di/src/Definition/Source/NoAutowiring.phpCnjC{qwHvendor/php-di/php-di/src/Definition/Source/ReflectionBasedAutowiring.phpv njv K6MΤ:vendor/php-di/php-di/src/Definition/Source/SourceCache.php nj E:vendor/php-di/php-di/src/Definition/Source/SourceChain.php nj GϬ8vendor/php-di/php-di/src/Definition/StringDefinition.phpnjcy7vendor/php-di/php-di/src/Definition/ValueDefinition.phptnjtΤ0vendor/php-di/php-di/src/DependencyException.phpnjj>3vendor/php-di/php-di/src/Factory/RequestedEntry.phpnjՌ٤-vendor/php-di/php-di/src/FactoryInterface.phpnj4y@vendor/php-di/php-di/src/Invoker/DefinitionParameterResolver.phpVnjVvW==vendor/php-di/php-di/src/Invoker/FactoryParameterResolver.phpnjv}.vendor/php-di/php-di/src/NotFoundException.phpnjB5vendor/php-di/php-di/src/Proxy/NativeProxyFactory.phpynjyq/vendor/php-di/php-di/src/Proxy/ProxyFactory.php nj 08vendor/php-di/php-di/src/Proxy/ProxyFactoryInterface.phpnj~ &vendor/php-di/php-di/src/functions.phpqnjq>1#vendor/php-di/php-di/support.md! nj! GW$$vendor/phpstan/phpdoc-parser/LICENSEQnjQw&vendor/phpstan/phpdoc-parser/README.mdwnjwɤ)vendor/phpstan/phpdoc-parser/UPGRADING.md#nj#&~g*vendor/phpstan/phpdoc-parser/composer.jsonnjޟ,e<vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.phpnjR#2vendor/phpstan/phpdoc-parser/src/Ast/Attribute.phpUnjUaa0vendor/phpstan/phpdoc-parser/src/Ast/Comment.phpnj]ܤIvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.phpnj洏Evendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.phpSnjSsqzEvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.phpLnjLEvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.phpnjxyGvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.phpnjK2@vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.phpnjwu{Dvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.phpJnjJiHBFvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.phpv njv G5Dvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.phpJnjJ$դAvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.phpnjlNvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php]nj])X-vendor/phpstan/phpdoc-parser/src/Ast/Node.php\nj\,7vendor/phpstan/phpdoc-parser/src/Ast/NodeAttributes.phpnj<&D6vendor/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php nj ݓf4vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php nj \\Cvendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.phpnjrʤHvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.phpnj9Jvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.phpnj?Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.phpnjfFvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php/nj/ĭؤKvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.phpnjz(@Ivendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.phpnjoUmFvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.phpnj+Jvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.phpinjiuMvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.phpnjktD&Cvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.phpnjfACvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.phpnj [nkFvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.phpnjo{ڤCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.phpJnjJFBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.phpnjy ȤKvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.phpYnjY-Avendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.phpnj>Lvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php]nj]땥[vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.phpnjrTȤUvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.phpnj -+Dvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.phpUnjUͱAvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.phpnjp?vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.phpnj:vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.phph+njh+h=vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.phpnjBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.phpnjfc:>vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.phpnjQ{Dvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.phpOnjO+Vvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.phpnjoWvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessParameterIsPassedTagValueNode.php`nj`FIJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.phpnjhjMvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.phpnjlBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.phpnjBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.phpnjb"Cvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.phpnjXuoPDvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.phpUnjUBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.phpnjA~_Kvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.phpnj^BZ-Evendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.phpznjz#@Ivendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.phpnjp @vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.phpnj '?vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.phpvnjvV@vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.phpnj74<vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.phpnjٝ Hvendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.phpnj;vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.phpznjz"Q>vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.phpnjBGvendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.phpnj-7Mvendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.phpnjFAvendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.phpnj`; ;vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php$nj$=vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.phpnjm(@vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.phpnj}Bvendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.phpnjIh=vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.phpnjB\[>vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.phpnj ~Avendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php-nj-D:T=vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.phpZnjZ;0Bvendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.phpnj^:vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php<nj<&Gz6vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.phpnj7P;vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.phpnj ZoC0vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.phpnj<Ǥ;vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.phpnjvڤ;vendor/phpstan/phpdoc-parser/src/Parser/ParserException.phphnjh즤8vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.phpJnjJD;vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.phpX njX 8z9vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php=#nj=#,6vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php4nj4%m1vendor/phpstan/phpdoc-parser/src/ParserConfig.php'nj'#65vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.phpknjk6%3vendor/phpstan/phpdoc-parser/src/Printer/Differ.phpnj%¤4vendor/phpstan/phpdoc-parser/src/Printer/Printer.phpr|njr|Gvendor/phpstan/phpstan/LICENSE/nj/#Ȥ vendor/phpstan/phpstan/README.md'nj'"n$vendor/phpstan/phpstan/bootstrap.phpnj3[$vendor/phpstan/phpstan/composer.jsonnj8-vendor/phpstan/phpstan/conf/bleedingEdge.neon8nj87vendor/phpstan/phpstan/phpstannjy.#vendor/phpstan/phpstan/phpstan.pharJ!knjJ!kz'vendor/phpstan/phpstan/phpstan.phar.ascAnjA\Ԥ2vendor/phpunit/php-code-coverage/ChangeLog-10.1.md9nj90W< (vendor/phpunit/php-code-coverage/LICENSEnj>R*vendor/phpunit/php-code-coverage/README.mdnj ,vendor/phpunit/php-code-coverage/SECURITY.mdunjuKJ.vendor/phpunit/php-code-coverage/composer.jsonnj:"5vendor/phpunit/php-code-coverage/src/CodeCoverage.phpEnjE~Y_Gvendor/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php'nj'^Avendor/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.phpS$njS$<_6vendor/phpunit/php-code-coverage/src/Driver/Driver.php nj Kvh:vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.phpnj78vendor/phpunit/php-code-coverage/src/Driver/Selector.phpnj+<vendor/phpunit/php-code-coverage/src/Driver/XdebugDriver.php=nj= $]vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.phpnjO}AYvendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.phpnjrDVvendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.phpnj;s <vendor/phpunit/php-code-coverage/src/Exception/Exception.phptnjtvQvendor/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.phpnjmwbwKvendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.phpnjTE9Yvendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php&nj&(E7pvendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.phpXnjX;Bvendor/phpunit/php-code-coverage/src/Exception/ParserException.phpnjs$Wvendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.phpnjLvendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.phpPnjP[8Fvendor/phpunit/php-code-coverage/src/Exception/ReflectionException.phpnj&LRvendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php1nj1tst\vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.phpnjcIvendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.phpnjVvendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.phpnjeW٤Pvendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.phpwnjwNvendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.phpTnjTLvendor/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.phpnjŒd?vendor/phpunit/php-code-coverage/src/Exception/XmlException.phpnj"/vendor/phpunit/php-code-coverage/src/Filter.php nj ,դ:vendor/phpunit/php-code-coverage/src/Node/AbstractNode.phpmnjm}5vendor/phpunit/php-code-coverage/src/Node/Builder.phpWnjW7vendor/phpunit/php-code-coverage/src/Node/CrapIndex.phpnjE7vendor/phpunit/php-code-coverage/src/Node/Directory.php &nj &y2vendor/phpunit/php-code-coverage/src/Node/File.phpanja/ 6vendor/phpunit/php-code-coverage/src/Node/Iterator.phpqnjqbI6vendor/phpunit/php-code-coverage/src/Report/Clover.php*nj*g09vendor/phpunit/php-code-coverage/src/Report/Cobertura.php*2nj*266vendor/phpunit/php-code-coverage/src/Report/Crap4j.phpKnjK;vendor/phpunit/php-code-coverage/src/Report/Html/Colors.phpnj'qBvendor/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.phpFnjFL;vendor/phpunit/php-code-coverage/src/Report/Html/Facade.phpnj-(=vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php'nj'$NGvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php'nj'[Gvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.phpnj(lФBvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php9nj9njUUvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.distnjh2+Yvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist'nj'O}`vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist'nj'O}Xvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.cssynjyĤQvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.cssnjTvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.cssX%njX%0,Svendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.cssXnjX'#Pvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.cssH njH BѺVvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.distnjD]vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.distnjDVvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.distnjՆ]vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.distnjn2][vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.distAnjAdsbvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist;nj;mۤQvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.distP njP j*Xvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist nj ㉞Vvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.distrnjr/y]vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.distlnjl-Vvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg0nj0QUU[vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svgnjZVvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.jscnjc"#Ovendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.jsPnjPhbMvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.jsnjb䆤Svendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js@^nj@^ Rvendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/nv.d3.min.jsRnjRnj>ǹ8vendor/phpunit/php-code-coverage/src/Report/Xml/Node.phpnj<;vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php nj :vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php8 nj8 ^E٤:vendor/phpunit/php-code-coverage/src/Report/Xml/Source.phpunjuKp9vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.phpnjMO:vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.phpnj8vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.phpMnjMhOCvendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.phpnjq"Kvendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.phpnjuiNvendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php'nj'[6Uvendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php1nj1/OiDvendor/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.phpnjFinRvendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.phpVnjV?yjKvendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php]nj]vC7vendor/phpunit/php-code-coverage/src/TestSize/Known.phpLnjL`7vendor/phpunit/php-code-coverage/src/TestSize/Large.phpnjY8T8vendor/phpunit/php-code-coverage/src/TestSize/Medium.phpnjx7vendor/phpunit/php-code-coverage/src/TestSize/Small.phpnjn:vendor/phpunit/php-code-coverage/src/TestSize/TestSize.php}nj}79vendor/phpunit/php-code-coverage/src/TestSize/Unknown.php]nj]9B;vendor/phpunit/php-code-coverage/src/TestStatus/Failure.php\nj\ =9vendor/phpunit/php-code-coverage/src/TestStatus/Known.phpnjE;vendor/phpunit/php-code-coverage/src/TestStatus/Success.php\nj\i>vendor/phpunit/php-code-coverage/src/TestStatus/TestStatus.phpnj0;vendor/phpunit/php-code-coverage/src/TestStatus/Unknown.phpanjauѤ8vendor/phpunit/php-code-coverage/src/Util/Filesystem.phpnj*98vendor/phpunit/php-code-coverage/src/Util/Percentage.php^nj^ae0vendor/phpunit/php-code-coverage/src/Version.phpnj-vendor/phpunit/php-file-iterator/ChangeLog.mdFnjFJz (vendor/phpunit/php-file-iterator/LICENSEnj-~y֤*vendor/phpunit/php-file-iterator/README.mdnj{C,vendor/phpunit/php-file-iterator/SECURITY.mdunjuKJ.vendor/phpunit/php-file-iterator/composer.jsonnj8vendor/phpunit/php-file-iterator/src/ExcludeIterator.phpLnjLwd/vendor/phpunit/php-file-iterator/src/Facade.phpnjY0vendor/phpunit/php-file-iterator/src/Factory.php nj nH1vendor/phpunit/php-file-iterator/src/Iterator.php nj 'vendor/phpunit/php-invoker/ChangeLog.mdnjD"vendor/phpunit/php-invoker/LICENSEnjp$vendor/phpunit/php-invoker/README.mdnjh&vendor/phpunit/php-invoker/SECURITY.mdPnjPE >Ϥ(vendor/phpunit/php-invoker/composer.jsonrnjr)*vendor/phpunit/php-invoker/src/Invoker.phpnjh\7vendor/phpunit/php-invoker/src/exceptions/Exception.phpinji֮Wvendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.phpnjGH6>vendor/phpunit/php-invoker/src/exceptions/TimeoutException.phpnjU&פ-vendor/phpunit/php-text-template/ChangeLog.mdnj(vendor/phpunit/php-text-template/LICENSEnj-~y֤*vendor/phpunit/php-text-template/README.mdnj(yK,vendor/phpunit/php-text-template/SECURITY.mdunjuKJ.vendor/phpunit/php-text-template/composer.json4nj4z 1vendor/phpunit/php-text-template/src/Template.php nj w=vendor/phpunit/php-text-template/src/exceptions/Exception.phppnjpז&Lvendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.phpnjDvendor/phpunit/php-text-template/src/exceptions/RuntimeException.phpnjVͤ%vendor/phpunit/php-timer/ChangeLog.mdknjk vendor/phpunit/php-timer/LICENSEnj"vendor/phpunit/php-timer/README.md nj 'Ǥ$vendor/phpunit/php-timer/SECURITY.mdPnjPE >Ϥ&vendor/phpunit/php-timer/composer.jsonnj-)vendor/phpunit/php-timer/src/Duration.php nj G6Ϋ7vendor/phpunit/php-timer/src/ResourceUsageFormatter.phpEnjE_&vendor/phpunit/php-timer/src/Timer.phpnjE%5vendor/phpunit/php-timer/src/exceptions/Exception.phpenjeѷtӤBvendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.phpnjƆXvendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.phpnjN(vendor/phpunit/phpunit/ChangeLog-10.5.mdsnjs;E &vendor/phpunit/phpunit/DEPRECATIONS.md5nj5vendor/phpunit/phpunit/LICENSEnje3 vendor/phpunit/phpunit/README.mdXnjX_d"vendor/phpunit/phpunit/SECURITY.mdnj$vendor/phpunit/phpunit/composer.json nj b!$vendor/phpunit/phpunit/composer.locknjȗvendor/phpunit/phpunit/phpunit nj K("vendor/phpunit/phpunit/phpunit.xsdGnjGaI&vendor/phpunit/phpunit/schema/10.0.xsd=nj=|H&vendor/phpunit/phpunit/schema/10.1.xsdBnjBܭr&vendor/phpunit/phpunit/schema/10.2.xsdQEnjQEn&vendor/phpunit/phpunit/schema/10.3.xsdFnjF3&&vendor/phpunit/phpunit/schema/10.4.xsdGFnjGF?%vendor/phpunit/phpunit/schema/8.5.xsdBnjB2A[%vendor/phpunit/phpunit/schema/9.0.xsd4Bnj4B7w%vendor/phpunit/phpunit/schema/9.1.xsdBnjBq'8%vendor/phpunit/phpunit/schema/9.2.xsdBnjBc-%vendor/phpunit/phpunit/schema/9.3.xsdEnjEq%vendor/phpunit/phpunit/schema/9.4.xsd Fnj FDOFI%vendor/phpunit/phpunit/schema/9.5.xsdDFnjDFs|%vendor/phpunit/phpunit/schema/9.6.xsdRFnjRFAgDvendor/phpunit/phpunit/src/Event/Dispatcher/CollectingDispatcher.phpnj7Cvendor/phpunit/phpunit/src/Event/Dispatcher/DeferringDispatcher.php nj j@vendor/phpunit/phpunit/src/Event/Dispatcher/DirectDispatcher.phpnjS~:vendor/phpunit/phpunit/src/Event/Dispatcher/Dispatcher.phplnjlFvendor/phpunit/phpunit/src/Event/Dispatcher/SubscribableDispatcher.phpnj@~yT?vendor/phpunit/phpunit/src/Event/Emitter/DispatchingEmitter.php;nj;H6^4vendor/phpunit/phpunit/src/Event/Emitter/Emitter.php-nj-Om@vendor/phpunit/phpunit/src/Event/Events/Application/Finished.phpnj1oJvendor/phpunit/phpunit/src/Event/Events/Application/FinishedSubscriber.phpnjʫ?vendor/phpunit/phpunit/src/Event/Events/Application/Started.phpnj! Ivendor/phpunit/phpunit/src/Event/Events/Application/StartedSubscriber.phpnj$1vendor/phpunit/phpunit/src/Event/Events/Event.phpnj տ;vendor/phpunit/phpunit/src/Event/Events/EventCollection.php!nj!|~Cvendor/phpunit/phpunit/src/Event/Events/EventCollectionIterator.phpnjGH Jvendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailed.php1nj1=Tvendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailedSubscriber.php3nj3m+ݤMvendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceeded.php7nj7>ĤWvendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceededSubscriber.php9nj9PEvendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegistered.php5nj5[,Ovendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php+nj+9\Uvendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.phpnja_vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php5nj5bNVvendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodErrored.php9nj9ccz`vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodErroredSubscriber.php7nj7xWvendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.phpnj%^avendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php9nj9 0Qvendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.phpnjr[vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php-nj-Vf_vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php5nj5AZTvendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.phphnjhb^vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php3nj3Lvendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php6nj6YodVvendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php#nj#>VKvendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php nj lYUvendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php!nj! *fvendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.php{nj{ 5pvendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.phpWnjW!hHvendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinished.phpnj GPRvendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php+nj+LAvendor/phpunit/phpunit/src/Event/Events/TestRunner/Configured.php}nj}N뜤Kvendor/phpunit/phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.phpnj8Kvendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggered.phpnjUvendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php1nj1"ϤHvendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealed.phpnjMRvendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php+nj+W/xGvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAborted.phpnjؤQvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php)nj)n+rHvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinished.phpnj+Rvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php+nj+㜤Gvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStarted.phpnjHQvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php)nj)-2gLvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.phpnjXVvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php3nj3Nvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.phpnj aXvendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php7nj72?vendor/phpunit/phpunit/src/Event/Events/TestRunner/Finished.php{nj{%tjIvendor/phpunit/phpunit/src/Event/Events/TestRunner/FinishedSubscriber.phpnj"Pvendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.phpnjkǧɤZvendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php;nj;kROvendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.phpnjyVYvendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php9nj9kQvendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.phpnj.[vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php=nj=> >vendor/phpunit/phpunit/src/Event/Events/TestRunner/Started.phpynjy8yHvendor/phpunit/phpunit/src/Event/Events/TestRunner/StartedSubscriber.phpnj=Gvendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggered.phpnjNN Qvendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php)nj)<>vendor/phpunit/phpunit/src/Event/Events/TestSuite/Filtered.phpnj Hvendor/phpunit/phpunit/src/Event/Events/TestSuite/FilteredSubscriber.phpnj>vendor/phpunit/phpunit/src/Event/Events/TestSuite/Finished.php nj :Hvendor/phpunit/phpunit/src/Event/Events/TestSuite/FinishedSubscriber.phpnj7<vendor/phpunit/phpunit/src/Event/Events/TestSuite/Loaded.phpnjFvendor/phpunit/phpunit/src/Event/Events/TestSuite/LoadedSubscriber.phpnj:r=vendor/phpunit/phpunit/src/Event/Events/TestSuite/Skipped.phponjo۰Gvendor/phpunit/phpunit/src/Event/Events/TestSuite/SkippedSubscriber.phpnjTܤ<vendor/phpunit/phpunit/src/Event/Events/TestSuite/Sorted.php8nj8S Fvendor/phpunit/phpunit/src/Event/Events/TestSuite/SortedSubscriber.phpnj՜=vendor/phpunit/phpunit/src/Event/Events/TestSuite/Started.phpnjna$Gvendor/phpunit/phpunit/src/Event/Events/TestSuite/StartedSubscriber.phpnjnTVĤLvendor/phpunit/phpunit/src/Event/Exception/EventAlreadyAssignedException.phpnj=Kvendor/phpunit/phpunit/src/Event/Exception/EventFacadeIsSealedException.phpnjR8vendor/phpunit/phpunit/src/Event/Exception/Exception.phpJnjJ:2*vGvendor/phpunit/phpunit/src/Event/Exception/InvalidArgumentException.phpnjSDvendor/phpunit/phpunit/src/Event/Exception/InvalidEventException.phpnj){Ivendor/phpunit/phpunit/src/Event/Exception/InvalidSubscriberException.phpnjyM7vendor/phpunit/phpunit/src/Event/Exception/MapError.phpnj7.Zvendor/phpunit/phpunit/src/Event/Exception/MoreThanOneDataSetFromDataProviderException.php/nj/ɤKvendor/phpunit/phpunit/src/Event/Exception/NoComparisonFailureException.phpnj.mQvendor/phpunit/phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php&nj&O0zKvendor/phpunit/phpunit/src/Event/Exception/NoPreviousThrowableException.phpnjSvendor/phpunit/phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.phpnj~7^?vendor/phpunit/phpunit/src/Event/Exception/RuntimeException.phpnj'oښWvendor/phpunit/phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.phpnjKDvendor/phpunit/phpunit/src/Event/Exception/UnknownEventException.phpnjѤ>Hvendor/phpunit/phpunit/src/Event/Exception/UnknownEventTypeException.phpnj~Ivendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberException.phpnj.Mvendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberTypeException.phpnj2[1+vendor/phpunit/phpunit/src/Event/Facade.php!nj!Lx/vendor/phpunit/phpunit/src/Event/Subscriber.phpnjf+vendor/phpunit/phpunit/src/Event/Tracer.phpnjJ1,vendor/phpunit/phpunit/src/Event/TypeMap.phpKnjKO8z6vendor/phpunit/phpunit/src/Event/Value/ClassMethod.phpnj]mX<vendor/phpunit/phpunit/src/Event/Value/ComparisonFailure.phpnj\8Cvendor/phpunit/phpunit/src/Event/Value/ComparisonFailureBuilder.php\nj\EgBvendor/phpunit/phpunit/src/Event/Value/Runtime/OperatingSystem.phpnj\6vendor/phpunit/phpunit/src/Event/Value/Runtime/PHP.php_ nj_ `ά:vendor/phpunit/phpunit/src/Event/Value/Runtime/PHPUnit.phpsnjscC:vendor/phpunit/phpunit/src/Event/Value/Runtime/Runtime.phpWnjWif=vendor/phpunit/phpunit/src/Event/Value/Telemetry/Duration.php nj kUKvendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.phpnj^Svendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.phpUnjU$獤;vendor/phpunit/phpunit/src/Event/Value/Telemetry/HRTime.php& nj& g9vendor/phpunit/phpunit/src/Event/Value/Telemetry/Info.phpA njA ^Ѥ@vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryMeter.phpqnjqrh@vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryUsage.phpfnjf.5nXvendor/phpunit/phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php%nj%gJXvendor/phpunit/phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.phpnj-ȳ=vendor/phpunit/phpunit/src/Event/Value/Telemetry/Snapshot.phpnj >vendor/phpunit/phpunit/src/Event/Value/Telemetry/StopWatch.php1nj1Aך;vendor/phpunit/phpunit/src/Event/Value/Telemetry/System.phpBnjBoLFvendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.phpinjieDvendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatch.phpnjR+Nvendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.phpDnjD4vendor/phpunit/phpunit/src/Event/Value/Test/Phpt.phpHnjH;Ϥ4vendor/phpunit/phpunit/src/Event/Value/Test/Test.phpnj1A,>vendor/phpunit/phpunit/src/Event/Value/Test/TestCollection.phpnjvFvendor/phpunit/phpunit/src/Event/Value/Test/TestCollectionIterator.phpnj!|¤Mvendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.phpnjݔ{Ovendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.phpnj|sAvendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestData.phpnj!X0Kvendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollection.php nj dSvendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.phpnjb7vendor/phpunit/phpunit/src/Event/Value/Test/TestDox.php$nj$(ۤ>vendor/phpunit/phpunit/src/Event/Value/Test/TestDoxBuilder.phpMnjMx3:vendor/phpunit/phpunit/src/Event/Value/Test/TestMethod.php7nj7ĕؤAvendor/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.phph njh [6ͤ>vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuite.phpnji}Evendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.phpj njj N:Jvendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.phpnj?[vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.phptnjtbLbFvendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteWithName.phpjnjjh4vendor/phpunit/phpunit/src/Event/Value/Throwable.phpW njW K;vendor/phpunit/phpunit/src/Event/Value/ThrowableBuilder.phpnj/ܤ(vendor/phpunit/phpunit/src/Exception.phpKnjK<[/vendor/phpunit/phpunit/src/Framework/Assert.php nj oW9vendor/phpunit/phpunit/src/Framework/Assert/Functions.phpNnjNGn9vendor/phpunit/phpunit/src/Framework/Attributes/After.phpnj{y>vendor/phpunit/phpunit/src/Framework/Attributes/AfterClass.phpnj7Avendor/phpunit/phpunit/src/Framework/Attributes/BackupGlobals.phpnjM٤Jvendor/phpunit/phpunit/src/Framework/Attributes/BackupStaticProperties.phpnjA:vendor/phpunit/phpunit/src/Framework/Attributes/Before.phpnj0?vendor/phpunit/phpunit/src/Framework/Attributes/BeforeClass.phpnjys`Fvendor/phpunit/phpunit/src/Framework/Attributes/CodeCoverageIgnore.phpmnjm ?vendor/phpunit/phpunit/src/Framework/Attributes/CoversClass.phpnjv蚤Bvendor/phpunit/phpunit/src/Framework/Attributes/CoversFunction.phpnjiIaAvendor/phpunit/phpunit/src/Framework/Attributes/CoversNothing.phpnj@vendor/phpunit/phpunit/src/Framework/Attributes/DataProvider.phpnjHvendor/phpunit/phpunit/src/Framework/Attributes/DataProviderExternal.phpnjY<ۤ;vendor/phpunit/phpunit/src/Framework/Attributes/Depends.phpnjuCvendor/phpunit/phpunit/src/Framework/Attributes/DependsExternal.phpnjeQvendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php nj v\{Tvendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php nj  IBvendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClass.phpnj{6Pvendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.phpnj@ZGSvendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.phpnjLYjIvendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingDeepClone.phpnjP^ILvendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingShallowClone.phpnj]Lvendor/phpunit/phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php(nj(ljSvendor/phpunit/phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.phpnj]_Svendor/phpunit/phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php6nj6uq9vendor/phpunit/phpunit/src/Framework/Attributes/Group.phpnj`<Nvendor/phpunit/phpunit/src/Framework/Attributes/IgnoreClassForCodeCoverage.phpnjפFvendor/phpunit/phpunit/src/Framework/Attributes/IgnoreDeprecations.php"nj"ĺ;Qvendor/phpunit/phpunit/src/Framework/Attributes/IgnoreFunctionForCodeCoverage.phpnj߫ɤOvendor/phpunit/phpunit/src/Framework/Attributes/IgnoreMethodForCodeCoverage.phpRnjRT¤9vendor/phpunit/phpunit/src/Framework/Attributes/Large.phpnjfR:vendor/phpunit/phpunit/src/Framework/Attributes/Medium.phpnj]  Avendor/phpunit/phpunit/src/Framework/Attributes/PostCondition.phpnj+@vendor/phpunit/phpunit/src/Framework/Attributes/PreCondition.phpnjƉGvendor/phpunit/phpunit/src/Framework/Attributes/PreserveGlobalState.phpnjUSdDvendor/phpunit/phpunit/src/Framework/Attributes/RequiresFunction.phpnjX:JBvendor/phpunit/phpunit/src/Framework/Attributes/RequiresMethod.phpnjD}Kvendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystem.phpnjRkQvendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.phpnjF?vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhp.phpnjHvendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpExtension.phpnj%n`Cvendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpunit.phpnji!OCvendor/phpunit/phpunit/src/Framework/Attributes/RequiresSetting.phpnj6Mvendor/phpunit/phpunit/src/Framework/Attributes/RunClassInSeparateProcess.phpnjBHvendor/phpunit/phpunit/src/Framework/Attributes/RunInSeparateProcess.php nj "*H Ovendor/phpunit/phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.phpnjl k9vendor/phpunit/phpunit/src/Framework/Attributes/Small.phpnj˵8vendor/phpunit/phpunit/src/Framework/Attributes/Test.phpnjvZ,;vendor/phpunit/phpunit/src/Framework/Attributes/TestDox.phpnjh핤<vendor/phpunit/phpunit/src/Framework/Attributes/TestWith.phpnj*@vendor/phpunit/phpunit/src/Framework/Attributes/TestWithJson.phpnj,L:vendor/phpunit/phpunit/src/Framework/Attributes/Ticket.phpnj#=vendor/phpunit/phpunit/src/Framework/Attributes/UsesClass.phpnj$_@vendor/phpunit/phpunit/src/Framework/Attributes/UsesFunction.phpnjeiߤGvendor/phpunit/phpunit/src/Framework/Attributes/WithoutErrorHandler.php nj >Cvendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php@nj@O9ԤBvendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php=nj=N;<vendor/phpunit/phpunit/src/Framework/Constraint/Callback.phpnjƤEvendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php nj hKvendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php7nj72 Gvendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.phpnj\ŏzHvendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php1nj1=|➤Hvendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.phpnjaQZ>vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php?!nj?!}rDvendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php nj T<Rvendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.phpW njW 7Pvendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.phpl njl %DѤMvendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php} nj} LJGvendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.phpdnjd@Kvendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.phpPnjP*BZvendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.phpjnjjZJ>fvendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php&nj&.Nvendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.phpnjIvendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.phpnj֗Ivendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.phpnj|Ivendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.phpnjXo>vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.phpjnjj?vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.phpnjhǤ?vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.phpc njc ;HAvendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php\nj\~uCvendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.phpdnjds'>vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.phpPnjP<2Gvendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.phpnjmLvendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasProperty.phpnjaϤKvendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php nj 竤Gvendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php;nj;2Gvendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.phpnj%owFvendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.phpnjޤGvendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.phpnjuEvendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.phpnj>[Jvendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php nj v1RAvendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php$ nj$ ULvendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.phpenjepԤIvendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php.nj.!mIvendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.phpnj8"0#`vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.phpnj*Yvendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php nj 7QyФKvendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.phpnj6Kvendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.phpcnjc Fvendor/phpunit/phpunit/src/Framework/Constraint/Traversable/IsList.php9nj9 omSvendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.phpnj!WXvendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php nj "P\vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.phpnjԨhWvendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.phpnjgݤEvendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.phpnjU?vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php=nj= ?vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.phpnj>vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php nj JGvendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.phpnjOlHvendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.phpnj8ɤGvendor/phpunit/phpunit/src/Framework/Exception/EmptyStringException.php.nj.tĤ<vendor/phpunit/phpunit/src/Framework/Exception/Exception.php, nj, !Mvendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.phpnj0|ǤQvendor/phpunit/phpunit/src/Framework/Exception/GeneratorNotSupportedException.phplnjlAxLvendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php+nj+GQvendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.phpCnjCoҾKvendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php&nj&EOvendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php3nj3D,[Ovendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php'nj'#=DMvendor/phpunit/phpunit/src/Framework/Exception/InvalidDependencyException.phpGnjG%q3ޤLvendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php$nj$h avendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.phpnj 91svendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.phpnj&Siuvendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.phpnj9?/zvendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.phpnj"|tvendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.phpnjevendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php]nj]T#ѤKvendor/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.phpnjILvendor/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php$nj$EFvendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTest.php(nj(Pvendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.phpBnjBXVvendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.phpHnjHXTSvendor/phpunit/phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php(nj(OGvendor/phpunit/phpunit/src/Framework/Exception/UnknownTypeException.php nj Avendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.phpnj9(Fvendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.phpZnjZ(-Tvendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.phpOnjOc[vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.phpnjŐGvendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php*nj*ݝ^vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.phpnjf[vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.phpUnjUqR_vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.phpMnjM%_vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.phpnj:mbvendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.phpnjO+w|^vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.phpnja}hvendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.phpnjZߤ[vendor/phpunit/phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.phpnjq7cvendor/phpunit/phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.phpnjL_vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.phpnjPvNvendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.phpCnjC[Apdvendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.phpnjW*tcvendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.phpgnjg,]vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.phpcnjc$֤`vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsReadonlyException.phpinjiE9Ӥ`vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.phpynjyTQvendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/Exception.phpmnjmޏbvendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.phpYnjY7ˤavendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.phpnj0Nvvendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php nj }?8 [vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php[nj[HeXvendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.phpXnjXҝ$jvendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.phpnjbPڤ]vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.phpHnjHO#]vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.phpnj?\vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.phpJnjJ&^GGvendor/phpunit/phpunit/src/Framework/MockObject/Generator/Generator.php4nj4{Gvendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockClass.php*nj*?Hvendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethod.php^0nj^0:Kvendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethodSet.phpnjwaGvendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockTrait.phpnjGFvendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockType.phprnjrkLvendor/phpunit/phpunit/src/Framework/MockObject/Generator/TemplateLoader.phpnjˑçSvendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/deprecation.tpl;nj;O5sVvendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_method.tplVnjV%]vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_static_method.tplnj 4RTvendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/intersection.tplLnjL-XVvendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/proxied_method.tplnj Yvendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/test_double_class.tplfnjf' Svendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/trait_class.tplQnjQ<ȤRvendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_class.tplnjSvendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_method.tpl<nj<i?vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php1nj1-aRvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.phpnj*ɽFvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/Method.phpnjcMvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php"nj"U$Rvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.phpnj16Gvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/StubApi.phpnjh#'Lvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Identity.phpnjkױpTvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.phpn#njn#K|Uvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.phpnj­Svendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php*nj*WFSvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.phponjoVIHvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php3nj3 X#¤Pvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.phpnjAA!.Xvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php nj 5wJvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/Stub.phpnjl(Rvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.phpsnjs#ФFvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Invocation.phpnjѤMvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/InvocationHandler.phpnj΁3Cvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Matcher.php]nj]]mPvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php6nj69{Pvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.phpnjzhCPvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php`nj`VNvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.phpnj}ѤPvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.phpCnjCPauTvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.phpnjҳȤSvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.phpDnjD|ӤSvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.phpnjMvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.php nj E+ˤKvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.php~nj~ܮZuKvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.phponjoUhܤOvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.phpnj#{Qvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.phpnj!SJvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Exception.phpnjy&Ovendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php}nj}_Ovendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.phpnjgPvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.phpDnjD3WԤKvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php!nj!ڤKvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php2nj2fޤOvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.phpnjEvendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.phpnj4vendor/phpunit/phpunit/src/Framework/Reorderable.phpnjm0,7vendor/phpunit/phpunit/src/Framework/SelfDescribing.phpwnjw|S-vendor/phpunit/phpunit/src/Framework/Test.phpnjp4vendor/phpunit/phpunit/src/Framework/TestBuilder.php+)nj+)[Z1vendor/phpunit/phpunit/src/Framework/TestCase.php!nj!xX3vendor/phpunit/phpunit/src/Framework/TestRunner.php?nj?,57vendor/phpunit/phpunit/src/Framework/TestSize/Known.phpnjYL7vendor/phpunit/phpunit/src/Framework/TestSize/Large.php_nj_h,68vendor/phpunit/phpunit/src/Framework/TestSize/Medium.phpbnjbS7vendor/phpunit/phpunit/src/Framework/TestSize/Small.phpRnjR#?:vendor/phpunit/phpunit/src/Framework/TestSize/TestSize.php!nj!FAڤ9vendor/phpunit/phpunit/src/Framework/TestSize/Unknown.phpnj?vendor/phpunit/phpunit/src/Framework/TestStatus/Deprecation.phpPnjPX 9vendor/phpunit/phpunit/src/Framework/TestStatus/Error.php8nj8;vendor/phpunit/phpunit/src/Framework/TestStatus/Failure.php@nj@ip'>vendor/phpunit/phpunit/src/Framework/TestStatus/Incomplete.phpLnjLv(9vendor/phpunit/phpunit/src/Framework/TestStatus/Known.phpnj q\:vendor/phpunit/phpunit/src/Framework/TestStatus/Notice.php<nj<T9vendor/phpunit/phpunit/src/Framework/TestStatus/Risky.php8nj86=;vendor/phpunit/phpunit/src/Framework/TestStatus/Skipped.php@nj@2dI;vendor/phpunit/phpunit/src/Framework/TestStatus/Success.php@nj@O[/>vendor/phpunit/phpunit/src/Framework/TestStatus/TestStatus.phpnj\aӤ;vendor/phpunit/phpunit/src/Framework/TestStatus/Unknown.phpFnjFH;vendor/phpunit/phpunit/src/Framework/TestStatus/Warning.php@nj@b]R2vendor/phpunit/phpunit/src/Framework/TestSuite.phpVKnjVK:vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.phpcnjc)2vendor/phpunit/phpunit/src/Logging/EventLogger.phpinji@;vendor/phpunit/phpunit/src/Logging/JUnit/JunitXmlLogger.php4nj4Bvendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/Subscriber.phpnj*邤Mvendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php\nj\FLvendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.phpVnjV^)Nvendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.phpbnjbaVvendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.phpnjrWvendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.phpnjjXvendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.phpnjwNvendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php\nj\h]vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPrintedUnexpectedOutputSubscriber.phpXnjXvendor/phpunit/phpunit/src/Logging/TeamCity/TeamCityLogger.php/nj/stqK;vendor/phpunit/phpunit/src/Logging/TestDox/HtmlRenderer.phpnj#Ѥ=vendor/phpunit/phpunit/src/Logging/TestDox/NamePrettifier.php"nj"%Ĥ@vendor/phpunit/phpunit/src/Logging/TestDox/PlainTextRenderer.phpnj=Ovendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.phpnjY!bvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php-nj-NA¤Zvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.phpnj2*Yvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.phpnjE[vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.phpgnjg @cvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php3nj3mݤYvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.phpnjHo[vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.phpnj]Zvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.phpnjCWrgvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.phpKnjKw bvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php-nj-֨8jvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php]nj](zevendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php?nj?$%pGfvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.phpEnjE䘤nvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.phpunjuThvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.phpQnjQ)Ԥjvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php]nj] 'cvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php3nj39Dvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResult.phpnj*,Nvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php6nj6`:jVvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php@nj@ѵ4Mvendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollector.phpY1njY1Hσ-vendor/phpunit/phpunit/src/Metadata/After.phpGnjG6c2vendor/phpunit/phpunit/src/Metadata/AfterClass.phpVnjVF8vendor/phpunit/phpunit/src/Metadata/Api/CodeCoverage.php*nj*ˤ8vendor/phpunit/phpunit/src/Metadata/Api/DataProvider.phpE+njE+8vendor/phpunit/phpunit/src/Metadata/Api/Dependencies.phpnjxX2vendor/phpunit/phpunit/src/Metadata/Api/Groups.php3nj34VY7vendor/phpunit/phpunit/src/Metadata/Api/HookMethods.phpnj8vendor/phpunit/phpunit/src/Metadata/Api/Requirements.php7nj795vendor/phpunit/phpunit/src/Metadata/BackupGlobals.phpnja o>vendor/phpunit/phpunit/src/Metadata/BackupStaticProperties.phpnjݵeˤ.vendor/phpunit/phpunit/src/Metadata/Before.phpJnjJF3vendor/phpunit/phpunit/src/Metadata/BeforeClass.phpYnjY^.vendor/phpunit/phpunit/src/Metadata/Covers.phpnj-gͤ3vendor/phpunit/phpunit/src/Metadata/CoversClass.php-nj-' :vendor/phpunit/phpunit/src/Metadata/CoversDefaultClass.phpEnjE e6vendor/phpunit/phpunit/src/Metadata/CoversFunction.php8nj8{Rc05vendor/phpunit/phpunit/src/Metadata/CoversNothing.php_nj_|4vendor/phpunit/phpunit/src/Metadata/DataProvider.phpnjc6vendor/phpunit/phpunit/src/Metadata/DependsOnClass.phpnj7vendor/phpunit/phpunit/src/Metadata/DependsOnMethod.phpnj@vendor/phpunit/phpunit/src/Metadata/DoesNotPerformAssertions.phpnjAgvendor/phpunit/phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.phpnjߦS;vendor/phpunit/phpunit/src/Metadata/Exception/Exception.phpMnjM Kvendor/phpunit/phpunit/src/Metadata/Exception/InvalidAttributeException.php nj 2դTvendor/phpunit/phpunit/src/Metadata/Exception/InvalidVersionRequirementException.phpnj.Ovendor/phpunit/phpunit/src/Metadata/Exception/NoVersionRequirementException.phpnj@ˤEvendor/phpunit/phpunit/src/Metadata/Exception/ReflectionException.phpgnjgjg`Gvendor/phpunit/phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.phpnj/aGvendor/phpunit/phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.phpnj7-vendor/phpunit/phpunit/src/Metadata/Group.php*nj*AYBvendor/phpunit/phpunit/src/Metadata/IgnoreClassForCodeCoverage.phpnjH:vendor/phpunit/phpunit/src/Metadata/IgnoreDeprecations.phpnnjn Evendor/phpunit/phpunit/src/Metadata/IgnoreFunctionForCodeCoverage.phpnj&C`Cvendor/phpunit/phpunit/src/Metadata/IgnoreMethodForCodeCoverage.phpnjǰ}0vendor/phpunit/phpunit/src/Metadata/Metadata.phpRnjRz:vendor/phpunit/phpunit/src/Metadata/MetadataCollection.php8nj8XnBvendor/phpunit/phpunit/src/Metadata/MetadataCollectionIterator.phpnj4Bvendor/phpunit/phpunit/src/Metadata/Parser/Annotation/DocBlock.php7&nj7&PBvendor/phpunit/phpunit/src/Metadata/Parser/Annotation/Registry.php nj ZC?vendor/phpunit/phpunit/src/Metadata/Parser/AnnotationParser.phpzKnjzKRߤ>vendor/phpunit/phpunit/src/Metadata/Parser/AttributeParser.phpanjaY<vendor/phpunit/phpunit/src/Metadata/Parser/CachingParser.php nj IC 5vendor/phpunit/phpunit/src/Metadata/Parser/Parser.phpJnjJ5t#:vendor/phpunit/phpunit/src/Metadata/Parser/ParserChain.phpnjE7vendor/phpunit/phpunit/src/Metadata/Parser/Registry.phpnjm".}5vendor/phpunit/phpunit/src/Metadata/PostCondition.php_nj_4vendor/phpunit/phpunit/src/Metadata/PreCondition.php\nj\[6;vendor/phpunit/phpunit/src/Metadata/PreserveGlobalState.phpnjV#8vendor/phpunit/phpunit/src/Metadata/RequiresFunction.php`nj`ç(6vendor/phpunit/phpunit/src/Metadata/RequiresMethod.phpnjPc¤?vendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystem.phpnj*3Evendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystemFamily.phpnj-\U3vendor/phpunit/phpunit/src/Metadata/RequiresPhp.phpnjnl <vendor/phpunit/phpunit/src/Metadata/RequiresPhpExtension.phpnj {7vendor/phpunit/phpunit/src/Metadata/RequiresPhpunit.phpnjOۤ7vendor/phpunit/phpunit/src/Metadata/RequiresSetting.phprnjrRSAvendor/phpunit/phpunit/src/Metadata/RunClassInSeparateProcess.phpnj٤<vendor/phpunit/phpunit/src/Metadata/RunInSeparateProcess.phptnjtCvendor/phpunit/phpunit/src/Metadata/RunTestsInSeparateProcesses.phpnjM,vendor/phpunit/phpunit/src/Metadata/Test.phpDnjDb@/vendor/phpunit/phpunit/src/Metadata/TestDox.php nj ;ڤ0vendor/phpunit/phpunit/src/Metadata/TestWith.phpynjy4,vendor/phpunit/phpunit/src/Metadata/Uses.phpnj>A1vendor/phpunit/phpunit/src/Metadata/UsesClass.php'nj'?I8vendor/phpunit/phpunit/src/Metadata/UsesDefaultClass.php?nj?il4vendor/phpunit/phpunit/src/Metadata/UsesFunction.php2nj2DEvendor/phpunit/phpunit/src/Metadata/Version/ComparisonRequirement.phpOnjO ]Evendor/phpunit/phpunit/src/Metadata/Version/ConstraintRequirement.php+nj+U;vendor/phpunit/phpunit/src/Metadata/Version/Requirement.phpDnjD_v;vendor/phpunit/phpunit/src/Metadata/WithoutErrorHandler.phpqnjqPt2ޤ7vendor/phpunit/phpunit/src/Runner/Baseline/Baseline.php6nj6*Tvendor/phpunit/phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php}nj}p +Uvendor/phpunit/phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.phpnjq8vendor/phpunit/phpunit/src/Runner/Baseline/Generator.phpnj@G4vendor/phpunit/phpunit/src/Runner/Baseline/Issue.php nj 5vendor/phpunit/phpunit/src/Runner/Baseline/Reader.phpS njS \zEvendor/phpunit/phpunit/src/Runner/Baseline/RelativePathCalculator.php# nj# -Dvendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/Subscriber.phpnj\vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.phpnjDaWvendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.phpnjk9_vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.phpnj]Zvendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.phpnjٴ[vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.phpnjB ͤXvendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.phpnj 8Z5vendor/phpunit/phpunit/src/Runner/Baseline/Writer.phpnj!2vendor/phpunit/phpunit/src/Runner/CodeCoverage.php7nj7KҤ2vendor/phpunit/phpunit/src/Runner/ErrorHandler.phpnjJKvendor/phpunit/phpunit/src/Runner/Exception/ClassCannotBeFoundException.phpjnjj0+Svendor/phpunit/phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.phpnjuHvendor/phpunit/phpunit/src/Runner/Exception/ClassIsAbstractException.phplnjl0zOvendor/phpunit/phpunit/src/Runner/Exception/CodeCoverageFileExistsException.phpZnjZD+Nvendor/phpunit/phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php`nj`5&>vendor/phpunit/phpunit/src/Runner/Exception/ErrorException.php7nj7de[9vendor/phpunit/phpunit/src/Runner/Exception/Exception.phpnj Ivendor/phpunit/phpunit/src/Runner/Exception/FileDoesNotExistException.php3nj3IEvendor/phpunit/phpunit/src/Runner/Exception/InvalidOrderException.phpPnjPPwHvendor/phpunit/phpunit/src/Runner/Exception/InvalidPhptFileException.phpSnjS(Nvendor/phpunit/phpunit/src/Runner/Exception/ParameterDoesNotExistException.php=nj=uWvendor/phpunit/phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.phpnj2]Ovendor/phpunit/phpunit/src/Runner/Exception/UnsupportedPhptSectionException.phpPnjP 9vendor/phpunit/phpunit/src/Runner/Extension/Extension.phpPnjPwLEvendor/phpunit/phpunit/src/Runner/Extension/ExtensionBootstrapper.php nj F#6vendor/phpunit/phpunit/src/Runner/Extension/Facade.php nj ΕCvendor/phpunit/phpunit/src/Runner/Extension/ParameterCollection.phpnj3 :vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.phpnjEGvendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.phpnj|j|4vendor/phpunit/phpunit/src/Runner/Filter/Factory.phpBnjBKL7@vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.phpnjzTGvendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.phpnjwR?vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.phpnj5(Avendor/phpunit/phpunit/src/Runner/Filter/TestIdFilterIterator.php,nj,!"Pvendor/phpunit/phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php nj @J^vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.phpnjJ]vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php nj CߨMvendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php'nj'utYvendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.phpnj(ä2vendor/phpunit/phpunit/src/Runner/PhptTestCase.php_nj_p/ӤDvendor/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.phpnjnAvendor/phpunit/phpunit/src/Runner/ResultCache/NullResultCache.phpnj>)=vendor/phpunit/phpunit/src/Runner/ResultCache/ResultCache.phpknjk?ɤDvendor/phpunit/phpunit/src/Runner/ResultCache/ResultCacheHandler.phpnjNGvendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/Subscriber.phpnjjZvendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php.nj.ĤRvendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.phpnjqPQvendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.phpnjSvendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.phpnjdפ[vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php4nj4מ/Svendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.phpnj ,٤Rvendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.phpnjĠXvendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.phpnjY.8Wvendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php nj 7Dݤ:vendor/phpunit/phpunit/src/Runner/TestResult/Collector.phpLnjLx7vendor/phpunit/phpunit/src/Runner/TestResult/Facade.php nj M(be6vendor/phpunit/phpunit/src/Runner/TestResult/Issue.php nj o ̤<vendor/phpunit/phpunit/src/Runner/TestResult/PassedTests.php' nj' Ew avendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/AfterTestClassMethodErroredSubscriber.phponjoA_tbvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.phpynjylޤVvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.phponjoѩ-Fvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/Subscriber.phpnj݀LYvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php3nj3wQvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.phpnj( Pvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.phpnjHRvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php nj ՘Zvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php9nj9Rvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.phpnj!+dvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.phpinjiJdC`vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.phpQnjQEOQvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.phpnjФWvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.phpnj'Vvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.phpnj~äVvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.phpnjn^vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.phpQnjQĤXvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php-nj-zBMUYvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php3nj3,|avendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.phpcnjc=O\vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.phpEnjEW]vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.phpKnjK$Z8evendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php{nj{;_vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.phpWnjW3avendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.phpcnjcUZvendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php9nj9դ;vendor/phpunit/phpunit/src/Runner/TestResult/TestResult.php+Cnj+Cc)Ҥ5vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.phpnjOJ5vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.phpx"njx"}-vendor/phpunit/phpunit/src/Runner/Version.phpKnjK <_1vendor/phpunit/phpunit/src/TextUI/Application.phpGfnjGf^Ϥ5vendor/phpunit/phpunit/src/TextUI/Command/Command.php.nj.btLvendor/phpunit/phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.phpnjySvendor/phpunit/phpunit/src/TextUI/Command/Commands/CheckPhpConfigurationCommand.phpMnjM-bSvendor/phpunit/phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php nj [\Hvendor/phpunit/phpunit/src/TextUI/Command/Commands/ListGroupsCommand.php nj hwLvendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.phpynjyMvendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php nj j:zLvendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.phpnjU"Rvendor/phpunit/phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.phpnjFvendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowHelpCommand.phptnjtjᧀIvendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowVersionCommand.phptnjtXۤJvendor/phpunit/phpunit/src/TextUI/Command/Commands/VersionCheckCommand.phpc njc rیSvendor/phpunit/phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php. nj. ˎ4vendor/phpunit/phpunit/src/TextUI/Command/Result.phpnj=D;vendor/phpunit/phpunit/src/TextUI/Configuration/Builder.phpnjx?vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Builder.phpnjtƤEvendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Configuration.php>nj>kqAvendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Exception.phpZnjZC٤Rvendor/phpunit/phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.phpmnjm"sNvendor/phpunit/phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.phpnj?Avendor/phpunit/phpunit/src/TextUI/Configuration/Configuration.php&nj&Wvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.phpnj(U^fvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.phpqnjq^kavendor/phpunit/phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.phplnjl TGvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/Exception.php1nj15PZvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.phpenjem[vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.phpfnjf|"Qvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php\nj\daRvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php]nj]N&Wvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.phpbnjbgZ3Tvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php_nj_alZvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.phpenjec1Y_vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.phpjnjjZ@Vvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.phpanjaYvendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.phpdnjd,~H_vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.phpjnjjU:vendor/phpunit/phpunit/src/TextUI/Configuration/Merger.phpnj#>vendor/phpunit/phpunit/src/TextUI/Configuration/PhpHandler.php,nj,3<vendor/phpunit/phpunit/src/TextUI/Configuration/Registry.phpQ njQ ܋@vendor/phpunit/phpunit/src/TextUI/Configuration/SourceFilter.phpnj@vendor/phpunit/phpunit/src/TextUI/Configuration/SourceMapper.php nj ,Dvendor/phpunit/phpunit/src/TextUI/Configuration/TestSuiteBuilder.phpnj Bvendor/phpunit/phpunit/src/TextUI/Configuration/Value/Constant.php>nj>v!GLvendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollection.phpCnjCzۤTvendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php^nj^ʅPCvendor/phpunit/phpunit/src/TextUI/Configuration/Value/Directory.phpnjZMvendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollection.phpnjW&Uvendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.phponjo ƤLvendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.phpnjYȸVvendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php_nj_ 8^vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.phpnj| >vendor/phpunit/phpunit/src/TextUI/Configuration/Value/File.php.nj.1Hvendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollection.phpVnjV Pvendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php2nj23Ivendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectory.phpnjSvendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.phpnj4Og[vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.phpnjħ?vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Group.phpnjW̋8Ivendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollection.phpnjQvendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php=nj=YDvendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSetting.php1nj1e+1Nvendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollection.phpenjeZE}Vvendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.phptnjtVB[=vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Php.php nj 89U@vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Source.phpnj=^Gvendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectory.phpnj~Qvendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.phpnjrYvendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.phpnjʤBvendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFile.phpnj͉Lvendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollection.phpunjul漤Tvendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.phpFnjF=|Cvendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuite.phpnjX[Mvendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.phpnjW Uvendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.phpinjimBvendor/phpunit/phpunit/src/TextUI/Configuration/Value/Variable.phpnjtLvendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollection.phpCnjCĿTvendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php^nj^5OQvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.phpnjޤRvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php-nj-ުUvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php0nj0\BRvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.phpnjq#3Pvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php nj \äOvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php*nj*&*qPvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.phpnjjzOvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php>nj>6=Evendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Configuration.php nj QLvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.phpmnjm%~Avendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Exception.php^nj^/PФAvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Generator.phpnj;>vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Groups.phpnjVSvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.phpnjk.~>vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Loader.phprnjr5>ۤEvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php nj 8Gvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Logging.phpC njC n=Hvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php#nj#[}DLvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php'nj'}"m=Lvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php'nj'vRvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.phpt njt TVTvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.phpunjuz*\vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php`nj`wcvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.phpnj'ӪRcvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.phpnj'avendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.phpnj#]Τ`vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.phpnj8 avendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.phpnjD?`vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.phpnjQ1mvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.phpnjevendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.phpNnjN:٤avendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.phpnj5ǖeVvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php^nj^W@/xvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.phpnj?mvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.phpnjmlvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.phpnjQdlvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.phpnjNH;$lvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.phpnj ]vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.phpnj/"_{vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.phpnjtkvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.phpnjФgvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php|nj|Jsvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.phpZnjZ ֺ7yvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.phpnjt*hvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.phpnjd^vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.phpnjt\vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.phprnjr E[[vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.phpnj7Tbvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.phpvnjv,BRivendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.phpnja}Ddvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.phpnjR@gvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.phpnjQ!lvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.phpnjqNʤcvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.phppnjp얤rvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.phpqnjq&9ۤyvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.phpnj m+qvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.phponjo-avendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.phpnjקk[Jvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.phpnjfRvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.phpnjO$?vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/PHPUnit.phpFnjFG0=bvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.phpWnjWDZI[\vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.phpnj Uvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.phpnjNfvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.phpunju:4Dvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaFinder.phpnj4&|Gvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.phpJnjJ<"Rvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php@nj@L:Kvendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php[nj[ԤIvendor/phpunit/phpunit/src/TextUI/Exception/CannotOpenSocketException.php]nj]P{9vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php#nj#Z`Fvendor/phpunit/phpunit/src/TextUI/Exception/InvalidSocketException.phpOnjO/d[@vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php5nj54)Nvendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php=nj=WIvendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php3nj3e*vendor/phpunit/phpunit/src/TextUI/Help.phpGnjG[[uTvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php/nj/d$vvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.phpnjxZvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.phpnjo]+mvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php;nj;ɓ,levendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.phpnjHUBdvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.phpnjjJfvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.phpnjAnvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.phpAnjAFhܤfvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.phpnj{tvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php_nj_asevendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php nj OѤrvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php_nj_% `lvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php;nj;`)mvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.phpAnjASuvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.phpqnjq2JĤpvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.phpSnjS;̤qvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.phpYnjY;yvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.phpnjxڤuvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.phpknjkwnvendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.phpGnjG Bvendor/phpunit/phpunit/src/TextUI/Output/Default/ResultPrinter.php'Rnj'R!rLvendor/phpunit/phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php5nj53vendor/phpunit/phpunit/src/TextUI/Output/Facade.php$nj$lۤCvendor/phpunit/phpunit/src/TextUI/Output/Printer/DefaultPrinter.phpC njC 3ʤ@vendor/phpunit/phpunit/src/TextUI/Output/Printer/NullPrinter.phpnjä<vendor/phpunit/phpunit/src/TextUI/Output/Printer/Printer.php[nj[u~;vendor/phpunit/phpunit/src/TextUI/Output/SummaryPrinter.phptnjtW%Bvendor/phpunit/phpunit/src/TextUI/Output/TestDox/ResultPrinter.php&nj&\r=vendor/phpunit/phpunit/src/TextUI/ShellExitCodeCalculator.phpnjK^0vendor/phpunit/phpunit/src/TextUI/TestRunner.php nj _i>vendor/phpunit/phpunit/src/TextUI/TestSuiteFilterProcessor.php nj [*vendor/phpunit/phpunit/src/Util/Cloner.phpbnjb%)vendor/phpunit/phpunit/src/Util/Color.phpnjE[7vendor/phpunit/phpunit/src/Util/Exception/Exception.php!nj!;ޤGvendor/phpunit/phpunit/src/Util/Exception/InvalidDirectoryException.php:nj: a5Bvendor/phpunit/phpunit/src/Util/Exception/InvalidJsonException.phpMnjMȸ=Mvendor/phpunit/phpunit/src/Util/Exception/InvalidVersionOperatorException.phpUnjU-_Avendor/phpunit/phpunit/src/Util/Exception/PhpProcessException.phplnjlT:vendor/phpunit/phpunit/src/Util/Exception/XmlException.phpenjehC/vendor/phpunit/phpunit/src/Util/ExcludeList.phpnj!5,vendor/phpunit/phpunit/src/Util/Exporter.php-nj-d@.vendor/phpunit/phpunit/src/Util/Filesystem.phpQnjQsv*vendor/phpunit/phpunit/src/Util/Filter.phpnjVȤ/vendor/phpunit/phpunit/src/Util/GlobalState.php )nj )FB3vendor/phpunit/phpunit/src/Util/Http/Downloader.phprnjrZ6vendor/phpunit/phpunit/src/Util/Http/PhpDownloader.phpnj[(vendor/phpunit/phpunit/src/Util/Json.php; nj; V:vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php nj CΤ9vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php;nj;3<=vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tplnjK>vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpld njd f{u ?vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tplj njj I.vendor/phpunit/phpunit/src/Util/Reflection.php nj cV£(vendor/phpunit/phpunit/src/Util/Test.phpnj$Z;vendor/phpunit/phpunit/src/Util/ThrowableToStringMapper.phpnj.==vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php%nj%1w-.vendor/phpunit/phpunit/src/Util/Xml/Loader.php3 nj3 \V+vendor/phpunit/phpunit/src/Util/Xml/Xml.phpnj])>vendor/psr/container/LICENSEynjyOpvendor/psr/container/README.mdBnjBg?"vendor/psr/container/composer.jsonnjm8vendor/psr/container/src/ContainerExceptionInterface.phpnj^33/vendor/psr/container/src/ContainerInterface.phpnj7vendor/psr/container/src/NotFoundExceptionInterface.phpnj>悤#vendor/psr/http-client/CHANGELOG.mdnjz򪌤vendor/psr/http-client/LICENSE=nj=S vendor/psr/http-client/README.md%nj%F$vendor/psr/http-client/composer.jsonnj7vendor/psr/http-client/src/ClientExceptionInterface.phpnj:.vendor/psr/http-client/src/ClientInterface.phpnjҞv 8vendor/psr/http-client/src/NetworkExceptionInterface.phpnj"78vendor/psr/http-client/src/RequestExceptionInterface.phpJnjJEuvendor/psr/http-factory/LICENSE(nj(}]!vendor/psr/http-factory/README.md,nj,zwf%vendor/psr/http-factory/composer.jsonnjO7vendor/psr/http-factory/src/RequestFactoryInterface.phpnjrTX8vendor/psr/http-factory/src/ResponseFactoryInterface.php"nj"X=vendor/psr/http-factory/src/ServerRequestFactoryInterface.phpnjBHA6vendor/psr/http-factory/src/StreamFactoryInterface.phpnjyۜ<vendor/psr/http-factory/src/UploadedFileFactoryInterface.phphnjhBj㬤3vendor/psr/http-factory/src/UriFactoryInterface.phpEnjEDh$vendor/psr/http-message/CHANGELOG.md3nj3:\Yvendor/psr/http-message/LICENSE=nj=!vendor/psr/http-message/README.mdnj%vendor/psr/http-message/composer.jsonsnjsLo$/vendor/psr/http-message/docs/PSR7-Interfaces.mdL%njL%6*vendor/psr/http-message/docs/PSR7-Usage.mdtnjtz X0vendor/psr/http-message/src/MessageInterface.phpnj?0vendor/psr/http-message/src/RequestInterface.php7nj7_81vendor/psr/http-message/src/ResponseInterface.phpJ njJ bY66vendor/psr/http-message/src/ServerRequestInterface.php:(nj:(iP:^/vendor/psr/http-message/src/StreamInterface.phpnjжJ5vendor/psr/http-message/src/UploadedFileInterface.phpnjZݤ,vendor/psr/http-message/src/UriInterface.php2nj2ovendor/psr/log/LICENSE=nj=pOvendor/psr/log/README.mdBnjB'vendor/psr/log/composer.json-nj-^%vendor/psr/log/src/AbstractLogger.phpnjۛ/vendor/psr/log/src/InvalidArgumentException.php`nj` X1vendor/psr/log/src/LogLevel.phpPnjP+vendor/psr/log/src/LoggerAwareInterface.php)nj)j 'vendor/psr/log/src/LoggerAwareTrait.phpnj"+ &vendor/psr/log/src/LoggerInterface.php nj 4"vendor/psr/log/src/LoggerTrait.phpAnjAlv!vendor/psr/log/src/NullLogger.phpnj*&vendor/ralouphie/getallheaders/LICENSE8nj8Ka(vendor/ralouphie/getallheaders/README.md@nj@\,vendor/ralouphie/getallheaders/composer.jsonnjG4vendor/ralouphie/getallheaders/src/getallheaders.phphnjhzvendor/rector/rector/LICENSEfnjf|vendor/rector/rector/README.mdunjuΙ@vendor/rector/rector/bin/rector_nj_7#vendor/rector/rector/bin/rector.phpnj,vendor/rector/rector/bin/resolve-version.phpnjk."vendor/rector/rector/bootstrap.php nj I僤"vendor/rector/rector/composer.jsonnjӒs&vendor/rector/rector/config/config.php4nj4/gE5vendor/rector/rector/config/phpstan/better-infer.neon>nj>/vendor/rector/rector/config/phpstan/parser.neonnj|Ĥ:vendor/rector/rector/config/phpstan/static-reflection.neonnj.90vendor/rector/rector/config/set/code-quality.php9nj9h0vendor/rector/rector/config/set/coding-style.php nj H$6vendor/rector/rector/config/set/datetime-to-carbon.phpRnjRȇ-vendor/rector/rector/config/set/dead-code.phpnj9O0vendor/rector/rector/config/set/early-return.phpanjaf |6vendor/rector/rector/config/set/gmagick-to-imagick.php (nj ( #ͤ.vendor/rector/rector/config/set/instanceof.phpnjG5vendor/rector/rector/config/set/level/up-to-php53.phpnj 5vendor/rector/rector/config/set/level/up-to-php54.php5nj54y5vendor/rector/rector/config/set/level/up-to-php55.php5nj5z5vendor/rector/rector/config/set/level/up-to-php56.php5nj50H5vendor/rector/rector/config/set/level/up-to-php70.php5nj5դ5vendor/rector/rector/config/set/level/up-to-php71.php5nj5,5vendor/rector/rector/config/set/level/up-to-php72.php5nj5LM5vendor/rector/rector/config/set/level/up-to-php73.php5nj5:Z5vendor/rector/rector/config/set/level/up-to-php74.php5nj5y5vendor/rector/rector/config/set/level/up-to-php80.php5nj5Q5vendor/rector/rector/config/set/level/up-to-php81.php5nj5\*5vendor/rector/rector/config/set/level/up-to-php82.php5nj5<`75vendor/rector/rector/config/set/level/up-to-php83.php5nj5JQ,5vendor/rector/rector/config/set/level/up-to-php84.php5nj5r*vendor/rector/rector/config/set/naming.phpnjvФ1vendor/rector/rector/config/set/php-polyfills.phpnjs)vendor/rector/rector/config/set/php52.phpnjyi)vendor/rector/rector/config/set/php53.phpnjӍrҤ)vendor/rector/rector/config/set/php54.phpnjF`)vendor/rector/rector/config/set/php55.php<nj<-lp)vendor/rector/rector/config/set/php56.phpnj,)vendor/rector/rector/config/set/php70.php nj nh)vendor/rector/rector/config/set/php71.phpnj_-d)vendor/rector/rector/config/set/php72.phpnjŤ)vendor/rector/rector/config/set/php73.phpnjrP)vendor/rector/rector/config/set/php74.php3nj3iVx)vendor/rector/rector/config/set/php80.php nj xq)vendor/rector/rector/config/set/php81.phpBnjBe)vendor/rector/rector/config/set/php82.phpnnjn-)vendor/rector/rector/config/set/php83.php{nj{ E)vendor/rector/rector/config/set/php84.php#nj#8Ѯ1vendor/rector/rector/config/set/privatization.php%nj%k.a1vendor/rector/rector/config/set/rector-preset.phpnj(3vendor/rector/rector/config/set/strict-booleans.phpnjG4vendor/rector/rector/config/set/type-declaration.phpnjN vendor/rector/rector/preload.phpAynjAyEvendor/rector/rector/rules/Arguments/ArgumentDefaultValueReplacer.php'nj'eVvendor/rector/rector/rules/Arguments/Contract/ReplaceArgumentDefaultValueInterface.php8nj8Ivendor/rector/rector/rules/Arguments/NodeAnalyzer/ArgumentAddingScope.php-nj-?hANvendor/rector/rector/rules/Arguments/NodeAnalyzer/ChangedArgumentsDetector.phpnj݀Ovendor/rector/rector/rules/Arguments/Rector/ClassMethod/ArgumentAdderRector.phpH2njH24]vendor/rector/rector/rules/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector.phpnj<'cvendor/rector/rector/rules/Arguments/Rector/FuncCall/FunctionArgumentDefaultValueReplacerRector.php nj G>Vvendor/rector/rector/rules/Arguments/Rector/MethodCall/RemoveMethodCallParamRector.php nj ĤBvendor/rector/rector/rules/Arguments/ValueObject/ArgumentAdder.phpnjUvendor/rector/rector/rules/Arguments/ValueObject/ArgumentAdderWithoutDefaultValue.phpnj>[SlJvendor/rector/rector/rules/Arguments/ValueObject/RemoveMethodCallParam.phpnj5Pvendor/rector/rector/rules/Arguments/ValueObject/ReplaceArgumentDefaultValue.phpnj- Xvendor/rector/rector/rules/Arguments/ValueObject/ReplaceFuncCallArgumentDefaultValue.phpnj {Cvendor/rector/rector/rules/Carbon/NodeFactory/CarbonCallFactory.phpznjz_)¤Pvendor/rector/rector/rules/Carbon/Rector/FuncCall/DateFuncCallToCarbonRector.php{nj{1Pvendor/rector/rector/rules/Carbon/Rector/FuncCall/TimeFuncCallToCarbonRector.phpvnjvs>Xvendor/rector/rector/rules/Carbon/Rector/MethodCall/DateTimeMethodCallToCarbonRector.php nj Pvendor/rector/rector/rules/Carbon/Rector/New_/DateTimeInstanceToCarbonRector.php nj >;vendor/rector/rector/rules/CodeQuality/CompactConverter.phpnjΚIvendor/rector/rector/rules/CodeQuality/NodeAnalyzer/ClassLikeAnalyzer.phpnjAUGvendor/rector/rector/rules/CodeQuality/NodeAnalyzer/ForeachAnalyzer.phpnjOMvendor/rector/rector/rules/CodeQuality/NodeAnalyzer/LocalPropertyAnalyzer.phpnj[bVvendor/rector/rector/rules/CodeQuality/NodeAnalyzer/VariableDimFetchAssignResolver.php nj BḤOvendor/rector/rector/rules/CodeQuality/NodeFactory/MissingPropertiesFactory.phpEnjEBƒLvendor/rector/rector/rules/CodeQuality/NodeFactory/PropertyTypeDecorator.phpnj}LKvendor/rector/rector/rules/CodeQuality/NodeFactory/TypedPropertyFactory.phpWnjWuwIvendor/rector/rector/rules/CodeQuality/NodeManipulator/ExprBoolCaster.php nj =ӤMvendor/rector/rector/rules/CodeQuality/Rector/Assign/CombinedAssignRector.phpnj[]vendor/rector/rector/rules/CodeQuality/Rector/BooleanAnd/RemoveUselessIsObjectCheckRector.phpMnjMKpΤZvendor/rector/rector/rules/CodeQuality/Rector/BooleanAnd/SimplifyEmptyArrayCheckRector.phpznjz4\vendor/rector/rector/rules/CodeQuality/Rector/BooleanNot/ReplaceMultipleBooleanNotRector.phpnj׋#Yvendor/rector/rector/rules/CodeQuality/Rector/BooleanNot/SimplifyDeMorganBinaryRector.phpbnjbïYvendor/rector/rector/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.phpPnjPGpLjvendor/rector/rector/rules/CodeQuality/Rector/ClassConstFetch/ConvertStaticPrivateConstantToSelfRector.php] nj] ( sVvendor/rector/rector/rules/CodeQuality/Rector/ClassMethod/ExplicitReturnNullRector.phpnj[vendor/rector/rector/rules/CodeQuality/Rector/ClassMethod/InlineArrayReturnAssignRector.phpnj0Xihvendor/rector/rector/rules/CodeQuality/Rector/ClassMethod/LocallyCalledStaticMethodToNonStaticRector.phpznjzUucvendor/rector/rector/rules/CodeQuality/Rector/ClassMethod/OptionalParametersAfterRequiredRector.php+nj+htߤXvendor/rector/rector/rules/CodeQuality/Rector/Class_/CompleteDynamicPropertiesRector.phpnj2fvendor/rector/rector/rules/CodeQuality/Rector/Class_/DynamicDocBlockPropertyToNativePropertyRector.phpJ njJ avendor/rector/rector/rules/CodeQuality/Rector/Class_/InlineConstructorDefaultToPropertyRector.phpnjgvendor/rector/rector/rules/CodeQuality/Rector/Class_/StaticToSelfStaticMethodCallOnFinalClassRector.php nj OOvendor/rector/rector/rules/CodeQuality/Rector/Concat/JoinStringConcatRector.php\ nj\ ˮ]vendor/rector/rector/rules/CodeQuality/Rector/Empty_/SimplifyEmptyCheckOnEmptyArrayRector.php4nj4 A0_vendor/rector/rector/rules/CodeQuality/Rector/Equal/UseIdenticalOverEqualWithSameTypeRector.php* nj* DWvendor/rector/rector/rules/CodeQuality/Rector/Expression/InlineIfToExplicitIfRector.phpA njA hVޤ]vendor/rector/rector/rules/CodeQuality/Rector/Expression/TernaryFalseExpressionToIfRector.phpgnjgG_)Zvendor/rector/rector/rules/CodeQuality/Rector/For_/ForRepeatedCountToOwnVariableRector.phpi nji ">gvendor/rector/rector/rules/CodeQuality/Rector/Foreach_/ForeachItemsAssignToEmptyArrayToAssignRector.phpnjVQvendor/rector/rector/rules/CodeQuality/Rector/Foreach_/ForeachToInArrayRector.phpTnjTu\vendor/rector/rector/rules/CodeQuality/Rector/Foreach_/SimplifyForeachToCoalescingRector.php_nj_ڋ^vendor/rector/rector/rules/CodeQuality/Rector/Foreach_/UnusedForeachValueToArrayKeysRector.phpnjIcvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/ArrayMergeOfNonArraysToSimpleArrayRector.php nj X_fvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/CallUserFuncWithArrowFunctionToInlineRector.php nj Mp]vendor/rector/rector/rules/CodeQuality/Rector/FuncCall/ChangeArrayPushToArrayAssignRector.php nj ZtSvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/CompactToVariablesRector.php nj +Tvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/InlineIsAInstanceOfRector.php nj _vendor/rector/rector/rules/CodeQuality/Rector/FuncCall/IsAWithStringWithThirdArgumentRector.phpnjAѤWvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/RemoveSoleValueSprintfRector.phpnj.Nvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/SetTypeToCastRector.php9nj9פYvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/SimplifyFuncGetArgsCountRector.phpnj)F3Vvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/SimplifyInArrayValuesRector.phpnjƧȤUvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/SimplifyRegexPatternRector.php nj 6cTvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/SimplifyStrposLowerRector.php\nj\\Wvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/SingleInArrayToCompareRector.phpnjW'Yvendor/rector/rector/rules/CodeQuality/Rector/FuncCall/UnwrapSprintfOneArgumentRector.phpdnjd\vendor/rector/rector/rules/CodeQuality/Rector/FunctionLike/SimplifyUselessVariableRector.phpnj(s{cvendor/rector/rector/rules/CodeQuality/Rector/Identical/BooleanNotIdenticalToNotIdenticalRector.php nj Z,dʤcvendor/rector/rector/rules/CodeQuality/Rector/Identical/FlipTypeControlToUseExclusiveTypeRector.phpDnjDAUvendor/rector/rector/rules/CodeQuality/Rector/Identical/SimplifyArraySearchRector.php nj QG[vendor/rector/rector/rules/CodeQuality/Rector/Identical/SimplifyBoolIdenticalTrueRector.php nj +IυTvendor/rector/rector/rules/CodeQuality/Rector/Identical/SimplifyConditionsRector.phpnjbvendor/rector/rector/rules/CodeQuality/Rector/Identical/StrlenZeroToIdenticalEmptyStringRector.php nj 6"=Evendor/rector/rector/rules/CodeQuality/Rector/If_/CombineIfRector.php nj 4Xvendor/rector/rector/rules/CodeQuality/Rector/If_/CompleteMissingIfElseBracketRector.php% nj% HpZlvendor/rector/rector/rules/CodeQuality/Rector/If_/ConsecutiveNullCompareReturnsToNullCoalesceQueueRector.phpnjAWgOvendor/rector/rector/rules/CodeQuality/Rector/If_/ExplicitBoolCompareRector.php5$nj5$bϦIvendor/rector/rector/rules/CodeQuality/Rector/If_/ShortenElseIfRector.phpD njD XSvendor/rector/rector/rules/CodeQuality/Rector/If_/SimplifyIfElseToTernaryRector.phpnj`FSvendor/rector/rector/rules/CodeQuality/Rector/If_/SimplifyIfNotNullReturnRector.php/ nj/ L~6Tvendor/rector/rector/rules/CodeQuality/Rector/If_/SimplifyIfNullableReturnRector.phpQ!njQ!dfPvendor/rector/rector/rules/CodeQuality/Rector/If_/SimplifyIfReturnBoolRector.phpnjQZ`vendor/rector/rector/rules/CodeQuality/Rector/Include_/AbsolutizeRequireAndIncludePathRector.php0nj0idvendor/rector/rector/rules/CodeQuality/Rector/Isset_/IssetOnPropertyObjectToPropertyExistsRector.phpnj^ɤ\vendor/rector/rector/rules/CodeQuality/Rector/LogicalAnd/AndAssignsToSeparateLinesRector.php(nj(Svendor/rector/rector/rules/CodeQuality/Rector/LogicalAnd/LogicalToBooleanRector.phpnj͕Ovendor/rector/rector/rules/CodeQuality/Rector/New_/NewStaticToNewSelfRector.phpnj4Ovendor/rector/rector/rules/CodeQuality/Rector/NotEqual/CommonNotEqualRector.phpnj |jvendor/rector/rector/rules/CodeQuality/Rector/NullsafeMethodCall/CleanupUnneededNullsafeOperatorRector.php nj | Rvendor/rector/rector/rules/CodeQuality/Rector/Switch_/SingularSwitchToIfRector.php{ nj{ /1Nvendor/rector/rector/rules/CodeQuality/Rector/Switch_/SwitchTrueToIfRector.phpi nji H{jvendor/rector/rector/rules/CodeQuality/Rector/Ternary/ArrayKeyExistsTernaryThenValueToCoalescingRector.php nj RMZvendor/rector/rector/rules/CodeQuality/Rector/Ternary/NumberCompareToMaxFuncCallRector.php nj ]@Xvendor/rector/rector/rules/CodeQuality/Rector/Ternary/SimplifyTautologyTernaryRector.phpWnjWm2eTvendor/rector/rector/rules/CodeQuality/Rector/Ternary/SwitchNegatedTernaryRector.phpknjkV׌hvendor/rector/rector/rules/CodeQuality/Rector/Ternary/TernaryEmptyArrayArrayDimFetchToCoalesceRector.phpmnjm..\vendor/rector/rector/rules/CodeQuality/Rector/Ternary/UnnecessaryTernaryExpressionRector.phpnj5)Qvendor/rector/rector/rules/CodeQuality/TypeResolver/ArrayDimFetchTypeResolver.phpynjyRvendor/rector/rector/rules/CodeQuality/TypeResolver/AssignVariableTypeResolver.php nj kusAvendor/rector/rector/rules/CodeQuality/ValueObject/KeyAndExpr.phpnjFvendor/rector/rector/rules/CodingStyle/Application/UseImportsAdder.php#nj#_Hvendor/rector/rector/rules/CodingStyle/Application/UseImportsRemover.phpnjLvendor/rector/rector/rules/CodingStyle/ClassNameImport/AliasUsesResolver.phpnjjqvendor/rector/rector/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/AliasClassNameImportSkipVoter.phpnjyvendor/rector/rector/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/ClassLikeNameClassNameImportSkipVoter.phpnj J~vendor/rector/rector/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/FullyQualifiedNameClassNameImportSkipVoter.php1nj12@)pvendor/rector/rector/rules/CodingStyle/ClassNameImport/ClassNameImportSkipVoter/UsesClassNameImportSkipVoter.phpnj{;4Qvendor/rector/rector/rules/CodingStyle/ClassNameImport/ClassNameImportSkipper.phpnjLvendor/rector/rector/rules/CodingStyle/ClassNameImport/ShortNameResolver.phpnj"MNvendor/rector/rector/rules/CodingStyle/ClassNameImport/UseImportsTraverser.phpKnjKcNvendor/rector/rector/rules/CodingStyle/ClassNameImport/UsedImportsResolver.php nj Rvendor/rector/rector/rules/CodingStyle/ClassNameImport/ValueObject/UsedImports.phpnj| evendor/rector/rector/rules/CodingStyle/Contract/ClassNameImport/ClassNameImportSkipVoterInterface.phpnjM<vendor/rector/rector/rules/CodingStyle/Guard/StaticGuard.phpnj2Tj=vendor/rector/rector/rules/CodingStyle/Naming/ClassNaming.phpnj%Ǥ<vendor/rector/rector/rules/CodingStyle/Node/NameImporter.php[nj[+Lvendor/rector/rector/rules/CodingStyle/NodeAnalyzer/UseImportNameMatcher.phpbnjbfWvendor/rector/rector/rules/CodingStyle/NodeFactory/ArrayCallableToMethodCallFactory.php>nj>gܤYvendor/rector/rector/rules/CodingStyle/Rector/ArrowFunction/StaticArrowFunctionRector.phpnj+!rPvendor/rector/rector/rules/CodingStyle/Rector/Assign/SplitDoubleAssignRector.phpO njO ]vendor/rector/rector/rules/CodingStyle/Rector/Catch_/CatchExceptionNameMatchingTypeRector.phpnjnΤWvendor/rector/rector/rules/CodingStyle/Rector/ClassConst/RemoveFinalFromConstRector.phpVnjV<_]vendor/rector/rector/rules/CodingStyle/Rector/ClassConst/SplitGroupedClassConstantsRector.phpnjB^vendor/rector/rector/rules/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector.phpnj=ͤmvendor/rector/rector/rules/CodingStyle/Rector/ClassMethod/MakeInheritedMethodVisibilitySameAsParentRector.phpnj 2~]vendor/rector/rector/rules/CodingStyle/Rector/ClassMethod/NewlineBeforeNewAssignSetRector.phpnj9Mvendor/rector/rector/rules/CodingStyle/Rector/Closure/StaticClosureRector.phpnj}QYvendor/rector/rector/rules/CodingStyle/Rector/Encapsed/EncapsedStringsToSprintfRector.phpnjJ bvendor/rector/rector/rules/CodingStyle/Rector/Encapsed/WrapEncapsedVariableInCurlyBracesRector.php[nj[f81evendor/rector/rector/rules/CodingStyle/Rector/Foreach_/MultiDimensionalArrayToArrayDestructRector.phpnj,G%_vendor/rector/rector/rules/CodingStyle/Rector/FuncCall/ArraySpreadInsteadOfArrayMergeRector.phpnjf\vendor/rector/rector/rules/CodingStyle/Rector/FuncCall/CallUserFuncArrayToVariadicRector.phpnjYvendor/rector/rector/rules/CodingStyle/Rector/FuncCall/CallUserFuncToMethodCallRector.php{ nj{ URvendor/rector/rector/rules/CodingStyle/Rector/FuncCall/ConsistentImplodeRector.phpY njY ¤avendor/rector/rector/rules/CodingStyle/Rector/FuncCall/CountArrayToEmptyArrayComparisonRector.phpnjC [vendor/rector/rector/rules/CodingStyle/Rector/FuncCall/FunctionFirstClassCallableRector.php nj [NRvendor/rector/rector/rules/CodingStyle/Rector/FuncCall/StrictArraySearchRector.phpnjɢZavendor/rector/rector/rules/CodingStyle/Rector/FuncCall/VersionCompareFuncCallToConstantRector.phpinji|Qvendor/rector/rector/rules/CodingStyle/Rector/If_/NullableCompareToNullRector.phpt njt m)}\Uvendor/rector/rector/rules/CodingStyle/Rector/PostInc/PostIncDecToPreIncDecRector.phpX njX F= 'Wvendor/rector/rector/rules/CodingStyle/Rector/Property/SplitGroupedPropertiesRector.phpnjJRvendor/rector/rector/rules/CodingStyle/Rector/Stmt/NewlineAfterStatementRector.phpnjv]vendor/rector/rector/rules/CodingStyle/Rector/Stmt/RemoveUselessAliasInUseStatementRector.phpnjܣCSvendor/rector/rector/rules/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector.phpnjyjevendor/rector/rector/rules/CodingStyle/Rector/String_/UseClassKeywordForClassNameResolutionRector.php]nj]dbvendor/rector/rector/rules/CodingStyle/Rector/Ternary/TernaryConditionVariableAssignmentRector.php9nj9뉔QTvendor/rector/rector/rules/CodingStyle/Rector/Use_/SeparateMultiUseImportsRector.phpnjpmLvendor/rector/rector/rules/CodingStyle/Reflection/VendorLocationDetector.phpnj]Ivendor/rector/rector/rules/CodingStyle/ValueObject/ObjectMagicMethods.phpnjr/7:vendor/rector/rector/rules/DeadCode/ConditionEvaluator.php nj p9vendor/rector/rector/rules/DeadCode/ConditionResolver.phpnjz@sCvendor/rector/rector/rules/DeadCode/Contract/ConditionInterface.phpgnjg)Kvendor/rector/rector/rules/DeadCode/NodeAnalyzer/CallCollectionAnalyzer.phpnj<;Kvendor/rector/rector/rules/DeadCode/NodeAnalyzer/ExprUsedInNodeAnalyzer.phpnj@Nvendor/rector/rector/rules/DeadCode/NodeAnalyzer/IsClassMethodUsedAnalyzer.php&nj&XNvendor/rector/rector/rules/DeadCode/NodeAnalyzer/PropertyWriteonlyAnalyzer.phpnjݠUvendor/rector/rector/rules/DeadCode/NodeAnalyzer/SafeLeftTypeBooleanAndOrAnalyzer.php- nj- )ʤMvendor/rector/rector/rules/DeadCode/NodeAnalyzer/UsedVariableNameAnalyzer.phpnjVMvendor/rector/rector/rules/DeadCode/NodeCollector/UnusedParameterResolver.php=nj=ܤOvendor/rector/rector/rules/DeadCode/NodeManipulator/ClassMethodParamRemover.phpbnjb$cXvendor/rector/rector/rules/DeadCode/NodeManipulator/ControllerClassMethodManipulator.phpnjHvendor/rector/rector/rules/DeadCode/NodeManipulator/CountManipulator.phpnj|Mvendor/rector/rector/rules/DeadCode/NodeManipulator/LivingCodeManipulator.phpdnjdTvendor/rector/rector/rules/DeadCode/NodeManipulator/VariadicFunctionLikeDetector.phpvnjv͐Lvendor/rector/rector/rules/DeadCode/PhpDoc/DeadParamTagValueNodeAnalyzer.php!nj!QMvendor/rector/rector/rules/DeadCode/PhpDoc/DeadReturnTagValueNodeAnalyzer.phpnjH`nJvendor/rector/rector/rules/DeadCode/PhpDoc/DeadVarTagValueNodeAnalyzer.php nj ڕOvendor/rector/rector/rules/DeadCode/PhpDoc/Guard/StandaloneTypeRemovalGuard.phpnj Mvendor/rector/rector/rules/DeadCode/PhpDoc/Guard/TemplateTypeRemovalGuard.phpnj )Ivendor/rector/rector/rules/DeadCode/PhpDoc/TagRemover/ParamTagRemover.php nj ;!Jvendor/rector/rector/rules/DeadCode/PhpDoc/TagRemover/ReturnTagRemover.phpZnjZZ=PGvendor/rector/rector/rules/DeadCode/PhpDoc/TagRemover/VarTagRemover.phpnj{Tvendor/rector/rector/rules/DeadCode/Rector/Array_/RemoveDuplicatedArrayKeyRector.phpnjߤNvendor/rector/rector/rules/DeadCode/Rector/Assign/RemoveDoubleAssignRector.php[nj[/4Vvendor/rector/rector/rules/DeadCode/Rector/Assign/RemoveUnusedVariableAssignRector.phpnj[Mvendor/rector/rector/rules/DeadCode/Rector/BooleanAnd/RemoveAndTrueRector.phpnjGJvendor/rector/rector/rules/DeadCode/Rector/Cast/RecastingRemovalRector.phpnjEuG`vendor/rector/rector/rules/DeadCode/Rector/ClassConst/RemoveUnusedPrivateClassConstantRector.php> nj> "sOvendor/rector/rector/rules/DeadCode/Rector/ClassLike/RemoveAnnotationRector.php$nj${aavendor/rector/rector/rules/DeadCode/Rector/ClassLike/RemoveTypedPropertyNonMockDocblockRector.phpnj)Wvendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveEmptyClassMethodRector.phpnjf׵Wvendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveNullTagValueNodeRector.phpnjM]vendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveUnusedConstructorParamRector.php nj (cvendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodParameterRector.phpEnjEKXZvendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPrivateMethodRector.phpnj13]Ƥ]vendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPromotedPropertyRector.phpnj?4Pbvendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveUnusedPublicMethodParameterRector.phpnjm=Vvendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveUselessParamTagRector.php nj cvendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnExprInConstructRector.php nj X4Wvendor/rector/rector/rules/DeadCode/Rector/ClassMethod/RemoveUselessReturnTagRector.php nj zPvendor/rector/rector/rules/DeadCode/Rector/Concat/RemoveConcatAutocastRector.phpvnjv5 ƟWvendor/rector/rector/rules/DeadCode/Rector/ConstFetch/RemovePhpVersionIdCheckRector.phpTnjTn;Nvendor/rector/rector/rules/DeadCode/Rector/Expression/RemoveDeadStmtRector.phpVnjVAFTvendor/rector/rector/rules/DeadCode/Rector/Expression/SimplifyMirrorAssignRector.phpFnjF~rQLvendor/rector/rector/rules/DeadCode/Rector/For_/RemoveDeadContinueRector.phpnjEݤPvendor/rector/rector/rules/DeadCode/Rector/For_/RemoveDeadIfForeachForRector.phpnjSAHvendor/rector/rector/rules/DeadCode/Rector/For_/RemoveDeadLoopRector.phpcnjc.dTvendor/rector/rector/rules/DeadCode/Rector/Foreach_/RemoveUnusedForeachKeyRector.phpnj/Rvendor/rector/rector/rules/DeadCode/Rector/FunctionLike/RemoveDeadReturnRector.php nj ayNvendor/rector/rector/rules/DeadCode/Rector/If_/ReduceAlwaysFalseIfOrRector.php nj S5)Tvendor/rector/rector/rules/DeadCode/Rector/If_/RemoveAlwaysTrueIfConditionRector.php1nj1Mvendor/rector/rector/rules/DeadCode/Rector/If_/RemoveDeadInstanceOfRector.phpnjTVҤZvendor/rector/rector/rules/DeadCode/Rector/If_/RemoveTypedPropertyDeadInstanceOfRector.phpnjB_vendor/rector/rector/rules/DeadCode/Rector/If_/RemoveUnusedNonEmptyArrayBeforeForeachRector.php-nj-:FTVvendor/rector/rector/rules/DeadCode/Rector/If_/SimplifyIfElseWithSameContentRector.php nj kl[vendor/rector/rector/rules/DeadCode/Rector/If_/UnwrapFutureCompatibleIfPhpVersionRector.php nj !PXvendor/rector/rector/rules/DeadCode/Rector/Node/RemoveNonExistingVarAnnotationRector.phpnjMWvendor/rector/rector/rules/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector.phplnjl8-Yvendor/rector/rector/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php_nj_;Vvendor/rector/rector/rules/DeadCode/Rector/Property/RemoveUselessReadOnlyTagRector.php nj +JQvendor/rector/rector/rules/DeadCode/Rector/Property/RemoveUselessVarTagRector.phpnj1k'fvendor/rector/rector/rules/DeadCode/Rector/PropertyProperty/RemoveNullPropertyInitializationRector.phpnjE[vendor/rector/rector/rules/DeadCode/Rector/Return_/RemoveDeadConditionAboveReturnRector.php nj ң]vendor/rector/rector/rules/DeadCode/Rector/StaticCall/RemoveParentCallWithoutParentRector.phpnjTTvendor/rector/rector/rules/DeadCode/Rector/Stmt/RemoveUnreachableStatementRector.php nj uYvendor/rector/rector/rules/DeadCode/Rector/Switch_/RemoveDuplicatedCaseInSwitchRector.phpnjs-C`vendor/rector/rector/rules/DeadCode/Rector/Ternary/TernaryToBooleanOrFalseToBooleanAndRector.php[nj[Y$Pvendor/rector/rector/rules/DeadCode/Rector/TryCatch/RemoveDeadTryCatchRector.php nj f|DGvendor/rector/rector/rules/DeadCode/SideEffect/PureFunctionDetector.phpnj*Ivendor/rector/rector/rules/DeadCode/SideEffect/SideEffectNodeDetector.php-nj-Pvendor/rector/rector/rules/DeadCode/TypeNodeAnalyzer/GenericTypeNodeAnalyzer.php<nj<N Svendor/rector/rector/rules/DeadCode/TypeNodeAnalyzer/MixedArrayTypeNodeAnalyzer.php{nj{c38Jvendor/rector/rector/rules/DeadCode/UselessIfCondBeforeForeachDetector.phpEnjEi=Svendor/rector/rector/rules/DeadCode/ValueObject/BinaryToVersionCompareCondition.phpnjO5lKvendor/rector/rector/rules/DeadCode/ValueObject/VersionCompareCondition.phpnjϤLvendor/rector/rector/rules/EarlyReturn/NodeTransformer/ConditionInverter.phpnj&fvendor/rector/rector/rules/EarlyReturn/Rector/Foreach_/ChangeNestedForeachIfsToEarlyContinueRector.phpnj`vendor/rector/rector/rules/EarlyReturn/Rector/If_/ChangeIfElseValueAssignToEarlyReturnRector.phpGnjGv.eXvendor/rector/rector/rules/EarlyReturn/Rector/If_/ChangeNestedIfsToEarlyReturnRector.phpnnjnw]^ ]vendor/rector/rector/rules/EarlyReturn/Rector/If_/ChangeOrIfContinueToMultiContinueRector.phpnjؤLvendor/rector/rector/rules/EarlyReturn/Rector/If_/RemoveAlwaysElseRector.phpYnjY,Zvendor/rector/rector/rules/EarlyReturn/Rector/Return_/PreparedValueToEarlyReturnRector.php}nj}Y[vendor/rector/rector/rules/EarlyReturn/Rector/Return_/ReturnBinaryOrToEarlyReturnRector.phpnjDr3,avendor/rector/rector/rules/EarlyReturn/Rector/StmtsAwareInterface/ReturnEarlyIfVariableRector.phpnj)Ivendor/rector/rector/rules/EarlyReturn/ValueObject/BareSingleAssignIf.phpnjY.\vendor/rector/rector/rules/Instanceof_/Rector/Ternary/FlipNegatedTernaryInstanceofRector.php?nj?B2}=^vendor/rector/rector/rules/Naming/AssignVariableNameResolver/NewAssignVariableNameResolver.phpmnjm(hvendor/rector/rector/rules/Naming/AssignVariableNameResolver/PropertyFetchAssignVariableNameResolver.phpnjERvendor/rector/rector/rules/Naming/Contract/AssignVariableNameResolverInterface.php7nj7W?Tvendor/rector/rector/rules/Naming/ExpectedNameResolver/InflectorSingularResolver.php nj ]vendor/rector/rector/rules/Naming/ExpectedNameResolver/MatchParamTypeExpectedNameResolver.phpnjS`vendor/rector/rector/rules/Naming/ExpectedNameResolver/MatchPropertyTypeExpectedNameResolver.phpnj`<Gvendor/rector/rector/rules/Naming/Guard/BreakingVariableRenameGuard.php nj V=Kvendor/rector/rector/rules/Naming/Guard/DateTimeAtNamingConventionGuard.phppnjpx?vendor/rector/rector/rules/Naming/Guard/HasMagicGetSetGuard.phpnj]#nvendor/rector/rector/rules/Naming/Guard/PropertyConflictingNameGuard/MatchPropertyTypeConflictingNameGuard.phpnj}9vendor/rector/rector/rules/Naming/Matcher/CallMatcher.php nj <vendor/rector/rector/rules/Naming/Matcher/ForeachMatcher.php nj OJvendor/rector/rector/rules/Naming/Matcher/VariableAndCallAssignMatcher.phpnjUؤ>vendor/rector/rector/rules/Naming/Naming/AliasNameResolver.phpnj8dDvendor/rector/rector/rules/Naming/Naming/ConflictingNameResolver.phpLnjLĤAvendor/rector/rector/rules/Naming/Naming/ExpectedNameResolver.phpnj2Kvendor/rector/rector/rules/Naming/Naming/OverridenExistingNamesResolver.phpnj#p;vendor/rector/rector/rules/Naming/Naming/PropertyNaming.phpf&njf&`?vendor/rector/rector/rules/Naming/Naming/UseImportsResolver.php nj bZ;vendor/rector/rector/rules/Naming/Naming/VariableNaming.phpmnjm0Ovendor/rector/rector/rules/Naming/NamingConvention/NamingConventionAnalyzer.phpnj9?vendor/rector/rector/rules/Naming/ParamRenamer/ParamRenamer.phpO njO ޡ:vendor/rector/rector/rules/Naming/PhpArray/ArrayFilter.php|nj|b0Cvendor/rector/rector/rules/Naming/PhpDoc/VarTagValueNodeRenamer.phpYnjYNvendor/rector/rector/rules/Naming/PropertyRenamer/MatchTypePropertyRenamer.phpnjVJvendor/rector/rector/rules/Naming/PropertyRenamer/PropertyFetchRenamer.phpnj7"Nvendor/rector/rector/rules/Naming/PropertyRenamer/PropertyPromotionRenamer.phpnjm/$vcvendor/rector/rector/rules/Naming/Rector/Assign/RenameVariableToMatchMethodCallReturnTypeRector.phpnj^ArUvendor/rector/rector/rules/Naming/Rector/ClassMethod/RenameParamToMatchTypeRector.phpnj;%[vendor/rector/rector/rules/Naming/Rector/ClassMethod/RenameVariableToMatchNewTypeRector.phpOnjOSѐqSvendor/rector/rector/rules/Naming/Rector/Class_/RenamePropertyToMatchTypeRector.phpsnjsBM1ivendor/rector/rector/rules/Naming/Rector/Foreach_/RenameForeachValueVariableToMatchExprVariableRector.phpnj_#iqvendor/rector/rector/rules/Naming/Rector/Foreach_/RenameForeachValueVariableToMatchMethodCallReturnTypeRector.phpnjl r;vendor/rector/rector/rules/Naming/RectorNamingInflector.phpnjgEvendor/rector/rector/rules/Naming/RenameGuard/PropertyRenameGuard.php_nj_|>vendor/rector/rector/rules/Naming/ValueObject/ExpectedName.phpnjcȤ=vendor/rector/rector/rules/Naming/ValueObject/ParamRename.phpnj8@vendor/rector/rector/rules/Naming/ValueObject/PropertyRename.phpnje,Gvendor/rector/rector/rules/Naming/ValueObject/VariableAndCallAssign.phpnj1Hvendor/rector/rector/rules/Naming/ValueObject/VariableAndCallForeach.phpnjeKvendor/rector/rector/rules/Naming/ValueObjectFactory/ParamRenameFactory.phpnj.ЉNvendor/rector/rector/rules/Naming/ValueObjectFactory/PropertyRenameFactory.phpLnjL(m5vendor/rector/rector/rules/Naming/VariableRenamer.php]nj]Nvendor/rector/rector/rules/Php52/Rector/Property/VarToPublicPropertyRector.php0nj0sڨQvendor/rector/rector/rules/Php52/Rector/Switch_/ContinueToBreakInSwitchRector.phpnjg˙[vendor/rector/rector/rules/Php53/Rector/FuncCall/DirNameFileConstantToDirConstantRector.phpnjV6Hvendor/rector/rector/rules/Php53/Rector/Ternary/TernaryToElvisRector.phpnj;4^Xvendor/rector/rector/rules/Php53/Rector/Variable/ReplaceHttpServerVarsByServerRector.phpnj|MbNvendor/rector/rector/rules/Php54/Rector/Array_/LongArrayToShortArrayRector.php@nj@NWPvendor/rector/rector/rules/Php54/Rector/Break_/RemoveZeroBreakContinueRector.php% nj% -'wRvendor/rector/rector/rules/Php54/Rector/FuncCall/RemoveReferenceFromCallRector.phpnj_Zvendor/rector/rector/rules/Php55/Rector/ClassConstFetch/StaticToSelfOnFinalClassRector.phpnj\CQvendor/rector/rector/rules/Php55/Rector/Class_/ClassConstantToSelfClassRector.phpnjWbTvendor/rector/rector/rules/Php55/Rector/FuncCall/GetCalledClassToSelfClassRector.php nj )Vvendor/rector/rector/rules/Php55/Rector/FuncCall/GetCalledClassToStaticClassRector.phpnj`| Ovendor/rector/rector/rules/Php55/Rector/FuncCall/PregReplaceEModifierRector.php: nj: }7_5Xvendor/rector/rector/rules/Php55/Rector/String_/StringClassNameToClassConstantRector.phpnj21vendor/rector/rector/rules/Php55/RegexMatcher.php nj =dCvendor/rector/rector/rules/Php56/Rector/FuncCall/PowToExpRector.phpnj B@vendor/rector/rector/rules/Php70/Enum/BattleshipCompareOrder.phpnjEe:vendor/rector/rector/rules/Php70/EregToPcreTransformer.php4*nj4*.'Cvendor/rector/rector/rules/Php70/Exception/InvalidEregException.phpnjKvendor/rector/rector/rules/Php70/NodeAnalyzer/BattleshipTernaryAnalyzer.phpnj^Tvendor/rector/rector/rules/Php70/NodeAnalyzer/Php4ConstructorClassMethodAnalyzer.php$nj$JHvendor/rector/rector/rules/Php70/Rector/Assign/ListSplitStringRector.phpnj֨VKvendor/rector/rector/rules/Php70/Rector/Assign/ListSwapArrayOrderRector.php nj FԤWvendor/rector/rector/rules/Php70/Rector/Break_/BreakNotInLoopOrSwitchToReturnRector.phpD njD ~lMvendor/rector/rector/rules/Php70/Rector/ClassMethod/Php4ConstructorRector.phpnjN&Ivendor/rector/rector/rules/Php70/Rector/FuncCall/CallUserMethodRector.phpnjCJvendor/rector/rector/rules/Php70/Rector/FuncCall/EregToPregMatchRector.phpnjyGvendor/rector/rector/rules/Php70/Rector/FuncCall/MultiDirnameRector.php nj Ivendor/rector/rector/rules/Php70/Rector/FuncCall/RandomFunctionRector.php nj MB Xvendor/rector/rector/rules/Php70/Rector/FuncCall/RenameMktimeWithoutArgsToTimeRector.phpnj򰹤Wvendor/rector/rector/rules/Php70/Rector/FunctionLike/ExceptionHandlerTypehintRector.php& nj& omCvendor/rector/rector/rules/Php70/Rector/If_/IfToSpaceshipRector.phpvnjv/Avendor/rector/rector/rules/Php70/Rector/List_/EmptyListRector.phpnjGD_vendor/rector/rector/rules/Php70/Rector/MethodCall/ThisCallOnStaticMethodToStaticCallRector.phpnjA`vendor/rector/rector/rules/Php70/Rector/StaticCall/StaticCallOnNonStaticToInstanceCallRector.phpSnjSI+Yvendor/rector/rector/rules/Php70/Rector/StmtsAwareInterface/IfIssetToCoalescingRector.php nj ;iUvendor/rector/rector/rules/Php70/Rector/Switch_/ReduceMultipleDefaultSwitchRector.phpUnjUBLQvendor/rector/rector/rules/Php70/Rector/Ternary/TernaryToNullCoalescingRector.phphnjhG#Lvendor/rector/rector/rules/Php70/Rector/Ternary/TernaryToSpaceshipRector.phpnj`vendor/rector/rector/rules/Php70/Rector/Variable/WrapVariableVariableNameInCurlyBracesRector.php@nj@gj>vendor/rector/rector/rules/Php70/ValueObject/ComparedExprs.phpnj]x>vendor/rector/rector/rules/Php71/IsArrayAndDualCheckToAble.php nj Lvendor/rector/rector/rules/Php71/Rector/Assign/AssignArrayToStringRector.phpnjA Yvendor/rector/rector/rules/Php71/Rector/BinaryOp/BinaryOpBetweenNumberAndStringRector.phpnj*7Fvendor/rector/rector/rules/Php71/Rector/BooleanOr/IsIterableRector.php nj H>Uvendor/rector/rector/rules/Php71/Rector/ClassConst/PublicConstantVisibilityRector.php nj ྤPvendor/rector/rector/rules/Php71/Rector/FuncCall/RemoveExtraParametersRector.phpnj$Kvendor/rector/rector/rules/Php71/Rector/List_/ListToArrayDestructRector.phpnjtDNvendor/rector/rector/rules/Php71/Rector/TryCatch/MultiExceptionCatchRector.php* nj* `=vendor/rector/rector/rules/Php71/ValueObject/TwoNodeMatch.phpnjL<Ivendor/rector/rector/rules/Php72/NodeFactory/AnonymousFunctionFactory.phpnjlpzAvendor/rector/rector/rules/Php72/Rector/Assign/ListEachRector.phpvnjv!@\vendor/rector/rector/rules/Php72/Rector/Assign/ReplaceEachAssignmentWithKeyCurrentRector.php\nj\k8d\vendor/rector/rector/rules/Php72/Rector/FuncCall/CreateFunctionToAnonymousFunctionRector.phpnjh$Ivendor/rector/rector/rules/Php72/Rector/FuncCall/GetClassOnNullRector.php nj KԤUvendor/rector/rector/rules/Php72/Rector/FuncCall/ParseStrWithResultArgumentRector.php nj _Jvendor/rector/rector/rules/Php72/Rector/FuncCall/StringifyDefineRector.php nj jMvendor/rector/rector/rules/Php72/Rector/FuncCall/StringsAssertNakedRector.php nj ydHBvendor/rector/rector/rules/Php72/Rector/Unset_/UnsetCastRector.phplnjliKvendor/rector/rector/rules/Php72/Rector/While_/WhileEachToForeachRector.phpd njd JR#<vendor/rector/rector/rules/Php72/ValueObject/ListAndEach.phpnjȗGvendor/rector/rector/rules/Php73/Rector/BooleanOr/IsCountableRector.phpm njm `'Rvendor/rector/rector/rules/Php73/Rector/ConstFetch/SensitiveConstantNameRector.phpnjSLvendor/rector/rector/rules/Php73/Rector/FuncCall/ArrayKeyFirstLastRector.php]nj]f4Kvendor/rector/rector/rules/Php73/Rector/FuncCall/JsonThrowOnErrorRector.php0nj01u Jvendor/rector/rector/rules/Php73/Rector/FuncCall/RegexDashEscapeRector.php3 nj3 VlJvendor/rector/rector/rules/Php73/Rector/FuncCall/SensitiveDefineRector.phpnjDvendor/rector/rector/rules/Php73/Rector/FuncCall/SetCookieRector.php nj ʤNvendor/rector/rector/rules/Php73/Rector/FuncCall/StringifyStrNeedlesRector.phpnjuHJMvendor/rector/rector/rules/Php73/Rector/String_/SensitiveHereNowDocRector.php` nj` 1EAvendor/rector/rector/rules/Php74/Guard/MakePropertyTypedGuard.phpnjrBvendor/rector/rector/rules/Php74/Guard/PropertyTypeChangeGuard.php nj aoNvendor/rector/rector/rules/Php74/NodeAnalyzer/ClosureArrowFunctionAnalyzer.phpZnjZɯL_vendor/rector/rector/rules/Php74/Rector/ArrayDimFetch/CurlyToSquareBracketArrayStringRector.phpnjGOvendor/rector/rector/rules/Php74/Rector/Assign/NullCoalescingOperatorRector.phpnjz]ߤPvendor/rector/rector/rules/Php74/Rector/Closure/ClosureToArrowFunctionRector.php nj ^m|OLvendor/rector/rector/rules/Php74/Rector/Double/RealToFloatTypeCastRector.php nj  8Svendor/rector/rector/rules/Php74/Rector/FuncCall/ArrayKeyExistsOnPropertyRector.phpnjMPvendor/rector/rector/rules/Php74/Rector/FuncCall/FilterVarToAddSlashesRector.php,nj,YᘤOvendor/rector/rector/rules/Php74/Rector/FuncCall/HebrevcToNl2brHebrevRector.phpnj̀\vendor/rector/rector/rules/Php74/Rector/FuncCall/MbStrrposEncodingArgumentPositionRector.phpinji6STvendor/rector/rector/rules/Php74/Rector/FuncCall/MoneyFormatToNumberFormatRector.php nj k9äYvendor/rector/rector/rules/Php74/Rector/FuncCall/RestoreIncludePathToIniRestoreRector.phpnjL`k+Uvendor/rector/rector/rules/Php74/Rector/LNumber/AddLiteralSeparatorToNumberRector.phpnjY0cvendor/rector/rector/rules/Php74/Rector/Property/RestoreDefaultNullToNullableTypePropertyRector.phpnjeWvendor/rector/rector/rules/Php74/Rector/StaticCall/ExportToReflectionFunctionRector.php nj Svendor/rector/rector/rules/Php74/Rector/Ternary/ParenthesizeNestedTernaryRector.phpDnjDQvendor/rector/rector/rules/Php74/Tokenizer/ParenthesizedNestedTernaryAnalyzer.phpnjQ{[vendor/rector/rector/rules/Php80/AttributeDecorator/DoctrineConverterAttributeDecorator.phpnj^vendor/rector/rector/rules/Php80/AttributeDecorator/SensioParamConverterAttributeDecorator.phpnjRvendor/rector/rector/rules/Php80/Contract/ConverterAttributeDecoratorInterface.phpnj̤Svendor/rector/rector/rules/Php80/Contract/StrStartWithMatchAndRefactorInterface.php1nj1e٤Xvendor/rector/rector/rules/Php80/Contract/ValueObject/AnnotationToAttributeInterface.phpnj<Mvendor/rector/rector/rules/Php80/DocBlock/PropertyPromotionDocBlockMerger.phpnjv'a3vendor/rector/rector/rules/Php80/Enum/MatchKind.phpsnjsŘEvendor/rector/rector/rules/Php80/Guard/MakePropertyPromotionGuard.phpnj jAkvendor/rector/rector/rules/Php80/MatchAndRefactor/StrStartsWithMatchAndRefactor/StrncmpMatchAndRefactor.phpinji .jvendor/rector/rector/rules/Php80/MatchAndRefactor/StrStartsWithMatchAndRefactor/StrposMatchAndRefactor.phpnjCjvendor/rector/rector/rules/Php80/MatchAndRefactor/StrStartsWithMatchAndRefactor/SubstrMatchAndRefactor.phpnjuEvendor/rector/rector/rules/Php80/NodeAnalyzer/MatchSwitchAnalyzer.phpnj4 Fvendor/rector/rector/rules/Php80/NodeAnalyzer/PhpAttributeAnalyzer.phpnjASvendor/rector/rector/rules/Php80/NodeAnalyzer/PromotedPropertyCandidateResolver.phpnj2QLJvendor/rector/rector/rules/Php80/NodeAnalyzer/PromotedPropertyResolver.php!nj!}*q@vendor/rector/rector/rules/Php80/NodeAnalyzer/SwitchAnalyzer.phpnjf<Bvendor/rector/rector/rules/Php80/NodeFactory/AttrGroupsFactory.phpanja[ӻAvendor/rector/rector/rules/Php80/NodeFactory/MatchArmsFactory.phpnjB=vendor/rector/rector/rules/Php80/NodeFactory/MatchFactory.php nj Hvendor/rector/rector/rules/Php80/NodeFactory/NestedAttrGroupsFactory.php,nj,."Mvendor/rector/rector/rules/Php80/NodeFactory/StrStartsWithFuncCallFactory.phpnjz[vendor/rector/rector/rules/Php80/NodeManipulator/AttributeGroupNamedArgumentManipulator.phpSnjSǎC@vendor/rector/rector/rules/Php80/NodeResolver/ArgumentSorter.php%nj% Nvendor/rector/rector/rules/Php80/NodeResolver/RequireOptionalParamResolver.phptnjt_jEvendor/rector/rector/rules/Php80/NodeResolver/SwitchExprsResolver.phpnjOTvendor/rector/rector/rules/Php80/Rector/Catch_/RemoveUnusedVariableInCatchRector.php6nj6[vendor/rector/rector/rules/Php80/Rector/ClassConstFetch/ClassOnThisVariableObjectRector.php nj 80^vendor/rector/rector/rules/Php80/Rector/ClassMethod/AddParamBasedOnParentClassMethodRector.php#nj# YH]vendor/rector/rector/rules/Php80/Rector/ClassMethod/FinalPrivateToPrivateVisibilityRector.phpnjaNvendor/rector/rector/rules/Php80/Rector/ClassMethod/SetStateToStaticRector.phpUnjU$ߤNvendor/rector/rector/rules/Php80/Rector/Class_/AnnotationToAttributeRector.phpZ'njZ''ũbvendor/rector/rector/rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php2-nj2-7AMNvendor/rector/rector/rules/Php80/Rector/Class_/StringableForToStringRector.phpnj@ȤHvendor/rector/rector/rules/Php80/Rector/FuncCall/ClassOnObjectRector.php2nj2򓎤Hvendor/rector/rector/rules/Php80/Rector/FunctionLike/MixedTypeRector.phpnj4tGvendor/rector/rector/rules/Php80/Rector/Identical/StrEndsWithRector.php nj zIvendor/rector/rector/rules/Php80/Rector/Identical/StrStartsWithRector.php nj MJvendor/rector/rector/rules/Php80/Rector/NotIdentical/StrContainsRector.phpnj=VVvendor/rector/rector/rules/Php80/Rector/Property/NestedAnnotationToAttributeRector.php nj .UlMvendor/rector/rector/rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php]nj]P,Fvendor/rector/rector/rules/Php80/Rector/Ternary/GetDebugTypeRector.phpknjk@sMSvendor/rector/rector/rules/Php80/ValueObject/AnnotationPropertyToAttributeClass.phpnjV_KFvendor/rector/rector/rules/Php80/ValueObject/AnnotationToAttribute.phpnj6b<vendor/rector/rector/rules/Php80/ValueObject/CondAndExpr.phpHnjHtTvendor/rector/rector/rules/Php80/ValueObject/DoctrineTagAndAnnotationToAttribute.phpTnjT@s<vendor/rector/rector/rules/Php80/ValueObject/MatchResult.phpnj|Lvendor/rector/rector/rules/Php80/ValueObject/NestedAnnotationToAttribute.php nj  GyZvendor/rector/rector/rules/Php80/ValueObject/NestedDoctrineTagAndAnnotationToAttribute.phpnjBKvendor/rector/rector/rules/Php80/ValueObject/PropertyPromotionCandidate.phpnjz@ʤ>vendor/rector/rector/rules/Php80/ValueObject/StrStartsWith.phpnj7*Lvendor/rector/rector/rules/Php80/ValueObjectFactory/StrStartsWithFactory.phpnjpdF7vendor/rector/rector/rules/Php81/Enum/AttributeName.phpnj]7Ivendor/rector/rector/rules/Php81/Enum/NameNullToStrictNullFunctionMap.php*nj*[ͤNvendor/rector/rector/rules/Php81/NodeAnalyzer/CoalesePropertyAssignMatcher.php3nj3ߤDvendor/rector/rector/rules/Php81/NodeAnalyzer/ComplexNewAnalyzer.phpnj<vendor/rector/rector/rules/Php81/NodeFactory/EnumFactory.php[nj[½[;Kvendor/rector/rector/rules/Php81/Rector/Array_/FirstClassCallableRector.phphnjh>ݤNvendor/rector/rector/rules/Php81/Rector/ClassMethod/NewInInitializerRector.phpnj0Kvendor/rector/rector/rules/Php81/Rector/Class_/MyCLabsClassToEnumRector.php'nj'!Nvendor/rector/rector/rules/Php81/Rector/Class_/SpatieEnumClassToEnumRector.php nj 3Xvendor/rector/rector/rules/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector.phpo&njo&-l_Yvendor/rector/rector/rules/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector.php#nj#?Q\vendor/rector/rector/rules/Php81/Rector/MethodCall/SpatieEnumMethodCallToEnumConstRector.phpnjlKvendor/rector/rector/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php%nj%Eg?Fvendor/rector/rector/rules/Php82/Rector/Class_/ReadOnlyClassRector.php$nj$~i]vendor/rector/rector/rules/Php82/Rector/Encapsed/VariableInStringInterpolationFixerRector.phpnj$H^vendor/rector/rector/rules/Php82/Rector/FuncCall/Utf8DecodeEncodeToMbConvertEncodingRector.phpFnjF"DQvendor/rector/rector/rules/Php82/Rector/New_/FilesystemIteratorSkipDotsRector.phpi nji (`#!Vvendor/rector/rector/rules/Php82/Rector/Param/AddSensitiveParameterAttributeRector.php nj դKvendor/rector/rector/rules/Php83/Rector/ClassConst/AddTypeToConstRector.phpnj.0evendor/rector/rector/rules/Php83/Rector/ClassMethod/AddOverrideAttributeToOverriddenMethodsRector.phpnjmQvendor/rector/rector/rules/Php83/Rector/FuncCall/CombineHostPortLdapUriRector.phpu nju >B]vendor/rector/rector/rules/Php83/Rector/FuncCall/RemoveGetClassGetParentClassNoArgsRector.phpnj"wQvendor/rector/rector/rules/Php84/Rector/Param/ExplicitNullableParamTypeRector.phpv njv wXMvendor/rector/rector/rules/Privatization/Guard/OverrideByParentClassGuard.phpnjZHLvendor/rector/rector/rules/Privatization/Guard/ParentPropertyLookupGuard.phpnj͝}Rvendor/rector/rector/rules/Privatization/NodeManipulator/VisibilityManipulator.php;nj;)M_vendor/rector/rector/rules/Privatization/Rector/ClassMethod/PrivatizeFinalClassMethodRector.phponjo|VVvendor/rector/rector/rules/Privatization/Rector/Class_/FinalizeTestCaseClassRector.php: nj: ~JI!cvendor/rector/rector/rules/Privatization/Rector/MethodCall/PrivatizeLocalGetterToPropertyRector.php nj =v^vendor/rector/rector/rules/Privatization/Rector/Property/PrivatizeFinalClassPropertyRector.phpnjkKvendor/rector/rector/rules/Privatization/TypeManipulator/TypeNormalizer.phpnjXWvendor/rector/rector/rules/Privatization/VisibilityGuard/ClassMethodVisibilityGuard.php?nj?UJvendor/rector/rector/rules/Removing/NodeManipulator/ComplexNodeRemover.php nj kS=Pvendor/rector/rector/rules/Removing/Rector/ClassMethod/ArgumentRemoverRector.phpnjb׏Lvendor/rector/rector/rules/Removing/Rector/Class_/RemoveInterfacesRector.phpnj yJvendor/rector/rector/rules/Removing/Rector/Class_/RemoveTraitUseRector.phpnjhslOvendor/rector/rector/rules/Removing/Rector/FuncCall/RemoveFuncCallArgRector.php nj |HLvendor/rector/rector/rules/Removing/Rector/FuncCall/RemoveFuncCallRector.php2nj2(Cvendor/rector/rector/rules/Removing/ValueObject/ArgumentRemover.phpnjCˤEvendor/rector/rector/rules/Removing/ValueObject/RemoveFuncCallArg.phpnjtFvendor/rector/rector/rules/Renaming/Collector/RenamedNameCollector.phpnjJvendor/rector/rector/rules/Renaming/Contract/MethodCallRenameInterface.php@nj@7=Jvendor/rector/rector/rules/Renaming/Contract/RenameAnnotationInterface.phpnj_08Ovendor/rector/rector/rules/Renaming/Contract/RenameClassConstFetchInterface.php#nj#"0VDvendor/rector/rector/rules/Renaming/NodeManipulator/ClassRenamer.php#nj#An܁Ivendor/rector/rector/rules/Renaming/NodeManipulator/SwitchManipulator.phpnj[Zvendor/rector/rector/rules/Renaming/Rector/ClassConstFetch/RenameClassConstFetchRector.php nj gmQvendor/rector/rector/rules/Renaming/Rector/ClassMethod/RenameAnnotationRector.phpxnjxKKvendor/rector/rector/rules/Renaming/Rector/Class_/RenameAttributeRector.php2 nj2 (NNvendor/rector/rector/rules/Renaming/Rector/ConstFetch/RenameConstantRector.phpnj5 DLvendor/rector/rector/rules/Renaming/Rector/FuncCall/RenameFunctionRector.phpnjC׶jvendor/rector/rector/rules/Renaming/Rector/FunctionLike/RenameFunctionLikeParamWithinCallLikeArgRector.php=nj=Lvendor/rector/rector/rules/Renaming/Rector/MethodCall/RenameMethodRector.php!nj!gOEvendor/rector/rector/rules/Renaming/Rector/Name/RenameClassRector.php8 nj8 vqQvendor/rector/rector/rules/Renaming/Rector/PropertyFetch/RenamePropertyRector.phpvnjvy3`Rvendor/rector/rector/rules/Renaming/Rector/StaticCall/RenameStaticMethodRector.php nj 4괤Ivendor/rector/rector/rules/Renaming/Rector/String_/RenameStringRector.phpnj qDvendor/rector/rector/rules/Renaming/ValueObject/MethodCallRename.phpnjbPvendor/rector/rector/rules/Renaming/ValueObject/MethodCallRenameWithArrayKey.phpnj{!Dvendor/rector/rector/rules/Renaming/ValueObject/RenameAnnotation.phpnj}Jvendor/rector/rector/rules/Renaming/ValueObject/RenameAnnotationByType.php+nj+Cvendor/rector/rector/rules/Renaming/ValueObject/RenameAttribute.phpnj Lvendor/rector/rector/rules/Renaming/ValueObject/RenameClassAndConstFetch.phpnjGIvendor/rector/rector/rules/Renaming/ValueObject/RenameClassConstFetch.phpnj6d\vendor/rector/rector/rules/Renaming/ValueObject/RenameFunctionLikeParamWithinCallLikeArg.phpnj)arTBvendor/rector/rector/rules/Renaming/ValueObject/RenameProperty.phpnjjFvendor/rector/rector/rules/Renaming/ValueObject/RenameStaticMethod.phpnjJNvendor/rector/rector/rules/Strict/NodeAnalyzer/UnitializedPropertyAnalyzer.php nj AʤEvendor/rector/rector/rules/Strict/NodeFactory/ExactCompareFactory.phpS'njS'xdOvendor/rector/rector/rules/Strict/Rector/AbstractFalsyScalarRuleFixerRector.phpnj,1Zvendor/rector/rector/rules/Strict/Rector/BooleanNot/BooleanInBooleanNotRuleFixerRector.phpQ njQ IRvendor/rector/rector/rules/Strict/Rector/Empty_/DisallowedEmptyRuleFixerRector.phpnj]Tvendor/rector/rector/rules/Strict/Rector/If_/BooleanInIfConditionRuleFixerRector.php, nj, 1d\vendor/rector/rector/rules/Strict/Rector/Ternary/BooleanInTernaryOperatorRuleFixerRector.phpl njl Zvendor/rector/rector/rules/Strict/Rector/Ternary/DisallowedShortTernaryRuleFixerRector.phpnj\vendor/rector/rector/rules/Transform/NodeAnalyzer/FuncCallStaticCallToMethodCallAnalyzer.phpnjaoIvendor/rector/rector/rules/Transform/NodeFactory/PropertyFetchFactory.phpnj@7\vendor/rector/rector/rules/Transform/NodeTypeAnalyzer/TypeProvidingExprFromClassResolver.phpKnjKP< ]vendor/rector/rector/rules/Transform/Rector/ArrayDimFetch/ArrayDimFetchToMethodCallRector.php?nj?k Wvendor/rector/rector/rules/Transform/Rector/Assign/PropertyAssignToMethodCallRector.phpE njE FVvendor/rector/rector/rules/Transform/Rector/Assign/PropertyFetchToMethodCallRector.phpPnjP5]vendor/rector/rector/rules/Transform/Rector/Attribute/AttributeKeyToClassConstFetchRector.phpnju7SVvendor/rector/rector/rules/Transform/Rector/ClassMethod/ReturnTypeWillChangeRector.phpnj}\M6Lvendor/rector/rector/rules/Transform/Rector/ClassMethod/WrapReturnRector.php- nj- *#_vendor/rector/rector/rules/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector.phpPnjP2_Pvendor/rector/rector/rules/Transform/Rector/Class_/AddInterfaceByTraitRector.php nj ^瑤Lvendor/rector/rector/rules/Transform/Rector/Class_/MergeInterfacesRector.php nj :Pvendor/rector/rector/rules/Transform/Rector/Class_/ParentClassToTraitsRector.php/ nj/ ?\vendor/rector/rector/rules/Transform/Rector/ConstFetch/ConstFetchToClassConstFetchRector.phpcnjcxh^vendor/rector/rector/rules/Transform/Rector/FileWithoutNamespace/RectorConfigBuilderRector.phpnj^/Svendor/rector/rector/rules/Transform/Rector/FuncCall/FuncCallToConstFetchRector.phpLnjL!BSvendor/rector/rector/rules/Transform/Rector/FuncCall/FuncCallToMethodCallRector.phpnjOФLvendor/rector/rector/rules/Transform/Rector/FuncCall/FuncCallToNewRector.phpnjSISvendor/rector/rector/rules/Transform/Rector/FuncCall/FuncCallToStaticCallRector.phpnjn-Uvendor/rector/rector/rules/Transform/Rector/MethodCall/MethodCallToFuncCallRector.php nj .0Pvendor/rector/rector/rules/Transform/Rector/MethodCall/MethodCallToNewRector.phpnjx(Zvendor/rector/rector/rules/Transform/Rector/MethodCall/MethodCallToPropertyFetchRector.php< nj< zZWvendor/rector/rector/rules/Transform/Rector/MethodCall/MethodCallToStaticCallRector.php nj $`vendor/rector/rector/rules/Transform/Rector/MethodCall/ReplaceParentCallByPropertyCallRector.php nj Jvendor/rector/rector/rules/Transform/Rector/New_/NewToStaticCallRector.phpnj=zYTvendor/rector/rector/rules/Transform/Rector/Scalar/ScalarValueToConstFetchRector.phpnjsPUvendor/rector/rector/rules/Transform/Rector/StaticCall/StaticCallToFuncCallRector.phpInjIHmWvendor/rector/rector/rules/Transform/Rector/StaticCall/StaticCallToMethodCallRector.phpnj‚!Pvendor/rector/rector/rules/Transform/Rector/StaticCall/StaticCallToNewRector.phpT njT oh!.Svendor/rector/rector/rules/Transform/Rector/String_/StringToClassConstantRector.php nj s"Nvendor/rector/rector/rules/Transform/ValueObject/ArrayDimFetchToMethodCall.phpnjˤRvendor/rector/rector/rules/Transform/ValueObject/AttributeKeyToClassConstFetch.php6nj6PIvendor/rector/rector/rules/Transform/ValueObject/ClassMethodReference.phpnjWPvendor/rector/rector/rules/Transform/ValueObject/ConstFetchToClassConstFetch.phpAnjAb ĤIvendor/rector/rector/rules/Transform/ValueObject/FuncCallToMethodCall.phpXnjX蓃Ivendor/rector/rector/rules/Transform/ValueObject/FuncCallToStaticCall.php&nj&=D/Ivendor/rector/rector/rules/Transform/ValueObject/MethodCallToFuncCall.phpVnjVWDvendor/rector/rector/rules/Transform/ValueObject/MethodCallToNew.phpnj9.Nvendor/rector/rector/rules/Transform/ValueObject/MethodCallToPropertyFetch.php#nj#AE fKvendor/rector/rector/rules/Transform/ValueObject/MethodCallToStaticCall.phpnjsXDvendor/rector/rector/rules/Transform/ValueObject/NewToStaticCall.phpNnjN V'Hvendor/rector/rector/rules/Transform/ValueObject/ParentClassToTraits.phpnj*:U:Ovendor/rector/rector/rules/Transform/ValueObject/PropertyAssignToMethodCall.phpMnjM6Nvendor/rector/rector/rules/Transform/ValueObject/PropertyFetchToMethodCall.php nj IޤTvendor/rector/rector/rules/Transform/ValueObject/ReplaceParentCallByPropertyCall.phpnjyLvendor/rector/rector/rules/Transform/ValueObject/ScalarValueToConstFetch.php<nj<Q)Ivendor/rector/rector/rules/Transform/ValueObject/StaticCallToFuncCall.phpnjŗKvendor/rector/rector/rules/Transform/ValueObject/StaticCallToMethodCall.phpknjk)Dvendor/rector/rector/rules/Transform/ValueObject/StaticCallToNew.phpnj$:KJvendor/rector/rector/rules/Transform/ValueObject/StringToClassConstant.phpVnjVFSH֤?vendor/rector/rector/rules/Transform/ValueObject/WrapReturn.phpnjeο^vendor/rector/rector/rules/TypeDeclaration/AlreadyAssignDetector/ConstructorAssignDetector.php1 nj1 1[vendor/rector/rector/rules/TypeDeclaration/AlreadyAssignDetector/NullTypeAssignDetector.phps njs VФbvendor/rector/rector/rules/TypeDeclaration/AlreadyAssignDetector/PropertyDefaultAssignDetector.php nj j4Mvendor/rector/rector/rules/TypeDeclaration/FunctionLikeReturnTypeResolver.phpQnjQ{zRڤFvendor/rector/rector/rules/TypeDeclaration/Guard/ParamTypeAddGuard.php nj YNvendor/rector/rector/rules/TypeDeclaration/Guard/PropertyTypeOverrideGuard.phpgnjgg¤Lvendor/rector/rector/rules/TypeDeclaration/Matcher/PropertyAssignMatcher.phpnj*u bvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/AutowiredClassMethodOrPropertyAnalyzer.phpSnjSMvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/CallTypesResolver.phpnjR $Nvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/CallerParamMatcher.phpnj5/ѤZvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/ClassMethodAndPropertyAnalyzer.php nj /fYvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/ClassMethodParamTypeCompleter.phpGnjGyӤSvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/DeclareStrictTypeFinder.phpnjr*IQvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/NeverFuncCallAnalyzer.phpGnjGIvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/ParamAnalyzer.phpYnjY&פJvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/ReturnAnalyzer.phpnj楤mvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/ReturnFilter/ExclusiveNativeCallLikeReturnMatcher.php}nj}̤uvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/ReturnTypeAnalyzer/StrictNativeFunctionReturnTypeAnalyzer.php4nj42Wfvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/ReturnTypeAnalyzer/StrictReturnNewAnalyzer.phpnjMvendor/rector/rector/rules/TypeDeclaration/NodeAnalyzer/TypeNodeUnwrapper.phpnj'Qvendor/rector/rector/rules/TypeDeclaration/NodeManipulator/AddNeverReturnType.php)nj)`;xgTvendor/rector/rector/rules/TypeDeclaration/NodeManipulator/AddReturnTypeFromCast.phpP njP QUvendor/rector/rector/rules/TypeDeclaration/NodeManipulator/AddReturnTypeFromParam.phpnj/`vendor/rector/rector/rules/TypeDeclaration/NodeManipulator/AddReturnTypeFromStrictNativeCall.phpU njU tkQvendor/rector/rector/rules/TypeDeclaration/NodeManipulator/AddUnionReturnType.php nj Tvendor/rector/rector/rules/TypeDeclaration/NodeTypeAnalyzer/DetailedTypeAnalyzer.phpnjqg`Uvendor/rector/rector/rules/TypeDeclaration/NodeTypeAnalyzer/PropertyTypeDecorator.php nj "ԤJvendor/rector/rector/rules/TypeDeclaration/PHPStan/ObjectTypeSpecifier.php#nj#1Rvendor/rector/rector/rules/TypeDeclaration/PhpDocParser/ParamPhpDocNodeFactory.phpnj_E\vendor/rector/rector/rules/TypeDeclaration/PhpDocParser/TypeExpressionFromVarTagResolver.phpnj/nxޤdvendor/rector/rector/rules/TypeDeclaration/Rector/ArrowFunction/AddArrowFunctionReturnTypeRector.phpqnjqͯäcvendor/rector/rector/rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.phpWnjWUNˤivendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddMethodCallBasedStrictParamTypeRector.phpnjrK0zvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddParamArrayDocblockBasedOnCallableNativeFuncCallRector.php"nj"Y]nvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php-nj-0 _vendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeDeclarationRector.phpxnjx(睤dvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeFromPropertyTypeRector.phpnjmdmvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddReturnArrayDocblockBasedOnArrayMapRector.phpnjoo1xvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddReturnTypeDeclarationBasedOnParentClassMethodRector.phpnjrB?`vendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddReturnTypeDeclarationRector.phpnj`cvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddTypeFromResourceDocblockRector.php/nj/lfvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/AddVoidReturnTypeWhereNoReturnRector.phpfnjf/Ymvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/BoolReturnTypeFromBooleanConstReturnsRector.phpnjnvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/BoolReturnTypeFromBooleanStrictReturnsRector.phpnjh#jvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/NumericReturnTypeFromStrictReturnsRector.phpxnjx\fpvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/NumericReturnTypeFromStrictScalarReturnsRector.phpnjJIavendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ParamTypeByMethodCallTypeRector.phpnjA\W٤avendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ParamTypeByParentCallTypeRector.phpnjyˤWvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnNeverTypeRector.phpnj&ʤZvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnNullableTypeRector.phpnj*r`vendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromMockObjectRector.phpnjC٤`vendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromReturnCastRector.phpnjÀwgvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromReturnDirectArrayRector.php nj DJդ_vendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromReturnNewRector.php&%nj&%kjvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictConstantReturnRector.phpnj`&hvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictFluentReturnRector.phpnjAfvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNativeCallRector.php9nj94ۤdvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php~%nj~%a~Wavendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictParamRector.phpnj,);jevendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictTypedCallRector.php"nj"Kivendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictTypedPropertyRector.phpnj˰gvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromSymfonySerializerRector.phpTnjTfWvendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/ReturnUnionTypeRector.phpnjgI-`vendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/StrictArrayParamDimFetchRector.php"nj"*_vendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/StrictStringParamConcatRector.phpnjn%ovendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/StringReturnTypeFromStrictScalarReturnsRector.phpPnjPHovendor/rector/rector/rules/TypeDeclaration/Rector/ClassMethod/StringReturnTypeFromStrictStringReturnsRector.php_nj_ ?bfvendor/rector/rector/rules/TypeDeclaration/Rector/Class_/AddTestsVoidReturnTypeWhereNoReturnRector.phps njs [7cvendor/rector/rector/rules/TypeDeclaration/Rector/Class_/ChildDoctrineRepositoryClassTypeRector.phpnjϤgvendor/rector/rector/rules/TypeDeclaration/Rector/Class_/MergeDateTimePropertyTypeDeclarationRector.phphnjh_ɸ)evendor/rector/rector/rules/TypeDeclaration/Rector/Class_/PropertyTypeFromStrictSetterGetterRector.phpnjv^vendor/rector/rector/rules/TypeDeclaration/Rector/Class_/ReturnTypeFromStrictTernaryRector.phpwnjwtּdvendor/rector/rector/rules/TypeDeclaration/Rector/Class_/TypedPropertyFromCreateMockAssignRector.php^nj^Wnvendor/rector/rector/rules/TypeDeclaration/Rector/Class_/TypedPropertyFromJMSSerializerAttributeTypeRector.php}nj}vvP]vendor/rector/rector/rules/TypeDeclaration/Rector/Closure/AddClosureNeverReturnTypeRector.phpnjE<ͤivendor/rector/rector/rules/TypeDeclaration/Rector/Closure/AddClosureVoidReturnTypeWhereNoReturnRector.phpnja[Uvendor/rector/rector/rules/TypeDeclaration/Rector/Closure/ClosureReturnTypeRector.php nj ~`Ǥdvendor/rector/rector/rules/TypeDeclaration/Rector/Empty_/EmptyOnNullableObjectToInstanceOfRector.phpZ njZ Ǯ$K^vendor/rector/rector/rules/TypeDeclaration/Rector/Expression/InlineVarDocTagToAssertRector.phpYnjYfi9cvendor/rector/rector/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromArgRector.phpRnjR'rvendor/rector/rector/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromIterableMethodCallRector.phptnjtfvendor/rector/rector/rules/TypeDeclaration/Rector/FunctionLike/AddClosureParamTypeFromObjectRector.phpnj nj> Yvendor/rector/rector/rules/Visibility/Rector/ClassMethod/ChangeMethodVisibilityRector.phpw njw r\vendor/rector/rector/rules/Visibility/Rector/ClassMethod/ExplicitPublicClassMethodRector.phpnj0+ȤNvendor/rector/rector/rules/Visibility/ValueObject/ChangeConstantVisibility.phpnj.Lvendor/rector/rector/rules/Visibility/ValueObject/ChangeMethodVisibility.php[nj[^Avendor/rector/rector/src/Application/ApplicationFileProcessor.php)+nj)+3Bvendor/rector/rector/src/Application/ChangedNodeScopeRefresher.php< nj< ^6vendor/rector/rector/src/Application/FileProcessor.phpl#njl#,Evendor/rector/rector/src/Application/Provider/CurrentFileProvider.phpnjՖ8vendor/rector/rector/src/Application/VersionResolver.phpnjX=vendor/rector/rector/src/Autoloading/AdditionalAutoloader.phpnjm-?vendor/rector/rector/src/Autoloading/BootstrapFilesIncluder.phpnjjKvendor/rector/rector/src/BetterPhpDocParser/Annotation/AnnotationNaming.phpnjCLvendor/rector/rector/src/BetterPhpDocParser/Attributes/AttributeMirrorer.phpnj{Fvendor/rector/rector/src/BetterPhpDocParser/Comment/CommentsMerger.phpnjCWvendor/rector/rector/src/BetterPhpDocParser/Contract/BasePhpDocNodeVisitorInterface.phpnjkR=bvendor/rector/rector/src/BetterPhpDocParser/Contract/PhpDocParser/PhpDocNodeDecoratorInterface.phpnj_Yvendor/rector/rector/src/BetterPhpDocParser/DataProvider/CurrentTokenIteratorProvider.phpnjXSvendor/rector/rector/src/BetterPhpDocParser/Guard/NewPhpDocFromPHPStanTypeGuard.phpnj/lA#Dvendor/rector/rector/src/BetterPhpDocParser/PhpDoc/ArrayItemNode.phpnjЩUvendor/rector/rector/src/BetterPhpDocParser/PhpDoc/DoctrineAnnotationTagValueNode.phpDnjDf lMvendor/rector/rector/src/BetterPhpDocParser/PhpDoc/SpacelessPhpDocTagNode.phpnjAvendor/rector/rector/src/BetterPhpDocParser/PhpDoc/StringNode.phpnj4c%Evendor/rector/rector/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.phpaBnjaBMΧLvendor/rector/rector/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfoFactory.phpnj3UOvendor/rector/rector/src/BetterPhpDocParser/PhpDocInfo/TokenIteratorFactory.php6nj6ITvendor/rector/rector/src/BetterPhpDocParser/PhpDocManipulator/PhpDocClassRenamer.phpnj<Rvendor/rector/rector/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTagRemover.phpnj_ySvendor/rector/rector/src/BetterPhpDocParser/PhpDocManipulator/PhpDocTypeChanger.php nj rjځWvendor/rector/rector/src/BetterPhpDocParser/PhpDocNodeFinder/PhpDocNodeByTypeFinder.php nj >@vendor/rector/rector/src/BetterPhpDocParser/PhpDocNodeMapper.phpnjo \vendor/rector/rector/src/BetterPhpDocParser/PhpDocNodeVisitor/ArrayTypePhpDocNodeVisitor.phpnjj_vendor/rector/rector/src/BetterPhpDocParser/PhpDocNodeVisitor/CallableTypePhpDocNodeVisitor.phpNnjNT;Zvendor/rector/rector/src/BetterPhpDocParser/PhpDocNodeVisitor/ChangedPhpDocNodeVisitor.phpDnjD9gvendor/rector/rector/src/BetterPhpDocParser/PhpDocNodeVisitor/IntersectionTypeNodePhpDocNodeVisitor.phpQnjQs̤[vendor/rector/rector/src/BetterPhpDocParser/PhpDocNodeVisitor/TemplatePhpDocNodeVisitor.php nj ڈ`vendor/rector/rector/src/BetterPhpDocParser/PhpDocNodeVisitor/UnionTypeNodePhpDocNodeVisitor.php nj MיXvendor/rector/rector/src/BetterPhpDocParser/PhpDocParser/ArrayItemClassNameDecorator.php nj sOvendor/rector/rector/src/BetterPhpDocParser/PhpDocParser/BetterPhpDocParser.php nj `Mvendor/rector/rector/src/BetterPhpDocParser/PhpDocParser/BetterTypeParser.phpnjqSvendor/rector/rector/src/BetterPhpDocParser/PhpDocParser/ClassAnnotationMatcher.phpnjM9Xvendor/rector/rector/src/BetterPhpDocParser/PhpDocParser/ConstExprClassNameDecorator.phpnjrorXvendor/rector/rector/src/BetterPhpDocParser/PhpDocParser/DoctrineAnnotationDecorator.phpFnjFQQJ[vendor/rector/rector/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser.phpnj_4gvendor/rector/rector/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/ArrayParser.phpnj2\ڑlvendor/rector/rector/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/PlainValueParser.phpnj[ Gvendor/rector/rector/src/BetterPhpDocParser/Printer/DocBlockInliner.phpnjKvendor/rector/rector/src/BetterPhpDocParser/Printer/EmptyPhpDocDetector.phpnjъIvendor/rector/rector/src/BetterPhpDocParser/Printer/PhpDocInfoPrinter.php0nj00GVvendor/rector/rector/src/BetterPhpDocParser/Printer/RemoveNodesStartAndEndResolver.phpnj/[vendor/rector/rector/src/BetterPhpDocParser/ValueObject/DoctrineAnnotation/SilentKeyMap.php!nj!פEvendor/rector/rector/src/BetterPhpDocParser/ValueObject/NodeTypes.phpLnjLyVvendor/rector/rector/src/BetterPhpDocParser/ValueObject/Parser/BetterTokenIterator.php nj *ʤmvendor/rector/rector/src/BetterPhpDocParser/ValueObject/PhpDoc/DoctrineAnnotation/AbstractValuesAwareNode.phpnjI*cvendor/rector/rector/src/BetterPhpDocParser/ValueObject/PhpDoc/DoctrineAnnotation/CurlyListNode.phpnj߾cvendor/rector/rector/src/BetterPhpDocParser/ValueObject/PhpDoc/SpacingAwareTemplateTagValueNode.phpnj+_Nvendor/rector/rector/src/BetterPhpDocParser/ValueObject/PhpDocAttributeKey.phpnj&Gvendor/rector/rector/src/BetterPhpDocParser/ValueObject/StartAndEnd.phpnj9`Hbvendor/rector/rector/src/BetterPhpDocParser/ValueObject/Type/BracketsAwareIntersectionTypeNode.phpQnjQϵ[vendor/rector/rector/src/BetterPhpDocParser/ValueObject/Type/BracketsAwareUnionTypeNode.phpnjavendor/rector/rector/src/BetterPhpDocParser/ValueObject/Type/FullyQualifiedIdentifierTypeNode.phpQnjQSҤ\vendor/rector/rector/src/BetterPhpDocParser/ValueObject/Type/ShortenedIdentifierTypeNode.phpnjAsZvendor/rector/rector/src/BetterPhpDocParser/ValueObject/Type/SpacingAwareArrayTypeNode.php, nj, 7o]vendor/rector/rector/src/BetterPhpDocParser/ValueObject/Type/SpacingAwareCallableTypeNode.php[ nj[ y>>vendor/rector/rector/src/Bootstrap/ExtensionConfigResolver.phpsnjs2d`A<vendor/rector/rector/src/Bootstrap/RectorConfigsResolver.php nj  ,8vendor/rector/rector/src/Bridge/SetProviderCollector.phplnjl\{Ȥ6vendor/rector/rector/src/Bridge/SetRectorsResolver.phpN njN *vendor/rector/rector/src/Caching/Cache.phpAnjA)&1vendor/rector/rector/src/Caching/CacheFactory.phpnjћg<vendor/rector/rector/src/Caching/Config/FileHashComputer.php[nj[븤Wvendor/rector/rector/src/Caching/Contract/ValueObject/Storage/CacheStorageInterface.php>nj>9ABvendor/rector/rector/src/Caching/Detector/ChangedFilesDetector.phpnj&+2vendor/rector/rector/src/Caching/Enum/CacheKey.phpnj>[rޤ9vendor/rector/rector/src/Caching/UnchangedFilesFilter.phpnj* ?vendor/rector/rector/src/Caching/ValueObject/CacheFilePaths.phplnjl1*S:vendor/rector/rector/src/Caching/ValueObject/CacheItem.phpnjPIvendor/rector/rector/src/Caching/ValueObject/Storage/FileCacheStorage.php)nj)boimKvendor/rector/rector/src/Caching/ValueObject/Storage/MemoryCacheStorage.phpnj#SVvendor/rector/rector/src/ChangesReporting/Contract/Output/OutputFormatterInterface.phpOnjOZKvendor/rector/rector/src/ChangesReporting/Output/ConsoleOutputFormatter.phpknjk0Hvendor/rector/rector/src/ChangesReporting/Output/JsonOutputFormatter.phpv njv ˽Nvendor/rector/rector/src/ChangesReporting/ValueObject/RectorWithLineChange.phpVnjVFMvendor/rector/rector/src/ChangesReporting/ValueObjectFactory/ErrorFactory.phpnjzPvendor/rector/rector/src/ChangesReporting/ValueObjectFactory/FileDiffFactory.phpnjSĤ4vendor/rector/rector/src/Comments/CommentRemover.phpnj|FBvendor/rector/rector/src/Comments/NodeDocBlock/DocBlockUpdater.phpnjpݤPvendor/rector/rector/src/Comments/NodeTraverser/CommentRemovingNodeTraverser.phpnj<Lvendor/rector/rector/src/Comments/NodeVisitor/CommentRemovingNodeVisitor.phpInjIqb>vendor/rector/rector/src/Composer/InstalledPackageResolver.phpnj Bvendor/rector/rector/src/Composer/ValueObject/InstalledPackage.php*nj*3:vendor/rector/rector/src/Config/Level/CodeQualityLevel.php'nj'F^7vendor/rector/rector/src/Config/Level/DeadCodeLevel.phpnjͽf>vendor/rector/rector/src/Config/Level/TypeDeclarationLevel.phpnjq{Ť0vendor/rector/rector/src/Config/RectorConfig.php6nj6h!U5vendor/rector/rector/src/Config/RegisteredService.phpnj4y<vendor/rector/rector/src/Configuration/ConfigInitializer.php nj _ ?vendor/rector/rector/src/Configuration/ConfigurationFactory.php<nj<Px8Svendor/rector/rector/src/Configuration/Deprecation/Contract/DeprecatedInterface.php7nj7fxDvendor/rector/rector/src/Configuration/Levels/LevelRulesResolver.phpnj71vendor/rector/rector/src/Configuration/Option.php&nj&8*Lvendor/rector/rector/src/Configuration/Parameter/SimpleParameterProvider.php nj >vendor/rector/rector/src/Configuration/PhpLevelSetResolver.phpnj>vendor/rector/rector/src/Configuration/RectorConfigBuilder.phpvnjv19 Fvendor/rector/rector/src/Configuration/RenamedClassesDataCollector.php4nj4Avendor/rector/rector/src/Configuration/VendorMissAnalyseGuard.phpOnjOj=>vendor/rector/rector/src/Console/Command/CustomRuleCommand.php'nj'y@Ǥ=vendor/rector/rector/src/Console/Command/ListRulesCommand.phpnj]ݤ;vendor/rector/rector/src/Console/Command/ProcessCommand.php!nj!R\ ;vendor/rector/rector/src/Console/Command/SetupCICommand.phpnjh:vendor/rector/rector/src/Console/Command/WorkerCommand.phpnj+}7vendor/rector/rector/src/Console/ConsoleApplication.phpnj=P6-vendor/rector/rector/src/Console/ExitCode.phpnjS)Hvendor/rector/rector/src/Console/Formatter/ColorConsoleDiffFormatter.php nj Ҥ<vendor/rector/rector/src/Console/Formatter/ConsoleDiffer.phpnjx5-vendor/rector/rector/src/Console/Notifier.phpnj)Dvendor/rector/rector/src/Console/Output/OutputFormatterCollector.phpnj<%wH>vendor/rector/rector/src/Console/ProcessConfigureDecorator.phpnj`6vendor/rector/rector/src/Console/Style/RectorStyle.php nj =B>vendor/rector/rector/src/Console/Style/SymfonyStyleFactory.php_nj_?Pvendor/rector/rector/src/Contract/DependencyInjection/RelatedConfigInterface.phpnjЫ_Lvendor/rector/rector/src/Contract/DependencyInjection/ResetableInterface.phpnjLHvendor/rector/rector/src/Contract/PhpParser/Node/StmtsAwareInterface.phpnjyeHvendor/rector/rector/src/Contract/Rector/ConfigurableRectorInterface.phplnjll$٤<vendor/rector/rector/src/Contract/Rector/RectorInterface.phpnjƤFvendor/rector/rector/src/Contract/Rector/ScopeAwareRectorInterface.phpnjƛ9vendor/rector/rector/src/CustomRules/SimpleNodeDumper.phpnjiKďIvendor/rector/rector/src/DependencyInjection/Laravel/ContainerMemento.phpnjcLEvendor/rector/rector/src/DependencyInjection/LazyContainerFactory.php:pnj:pGǣzGvendor/rector/rector/src/DependencyInjection/RectorContainerFactory.phpnjؒ21vendor/rector/rector/src/Differ/DefaultDiffer.phpnj{^+vendor/rector/rector/src/Enum/ClassName.phpnjp1vendor/rector/rector/src/Enum/ObjectReference.php*nj*oW_=vendor/rector/rector/src/Exception/Cache/CachingException.phpnj+ߛRvendor/rector/rector/src/Exception/Configuration/InvalidConfigurationException.phpnjEuAvendor/rector/rector/src/Exception/NotImplementedYetException.phpnjtTQvendor/rector/rector/src/Exception/Reflection/MissingPrivatePropertyException.phpnjƵA?vendor/rector/rector/src/Exception/ShouldNotHappenException.phpnj ä7vendor/rector/rector/src/Exception/VersionException.phpnjlGvendor/rector/rector/src/FamilyTree/NodeAnalyzer/ClassChildAnalyzer.phpg njg \4%Jvendor/rector/rector/src/FamilyTree/Reflection/FamilyRelationsAnalyzer.php nj ll>vendor/rector/rector/src/FileSystem/FileAndDirectoryFilter.phpnjw(6vendor/rector/rector/src/FileSystem/FilePathHelper.php nj \3vendor/rector/rector/src/FileSystem/FilesFinder.phpenje~9vendor/rector/rector/src/FileSystem/FilesystemTweaker.phpnj=vendor/rector/rector/src/FileSystem/InitFilePathsResolver.php?nj?Ő'6vendor/rector/rector/src/FileSystem/JsonFileSystem.phpnjt鰤1vendor/rector/rector/src/Git/RepositoryHelper.php+nj+;6vendor/rector/rector/src/NodeAnalyzer/ArgsAnalyzer.phpnj{Ӥ:vendor/rector/rector/src/NodeAnalyzer/BinaryOpAnalyzer.phpnj/6vendor/rector/rector/src/NodeAnalyzer/CallAnalyzer.php} nj} Ѥ7vendor/rector/rector/src/NodeAnalyzer/ClassAnalyzer.phpnj;*Avendor/rector/rector/src/NodeAnalyzer/CompactFuncCallAnalyzer.php?nj?j5<vendor/rector/rector/src/NodeAnalyzer/ConstFetchAnalyzer.phpnjSܤ@vendor/rector/rector/src/NodeAnalyzer/DoctrineEntityAnalyzer.phpnj6vendor/rector/rector/src/NodeAnalyzer/ExprAnalyzer.phpznjzfYįBvendor/rector/rector/src/NodeAnalyzer/MagicClassMethodAnalyzer.phpnj˶7vendor/rector/rector/src/NodeAnalyzer/ParamAnalyzer.phpnjƧ?`:vendor/rector/rector/src/NodeAnalyzer/PropertyAnalyzer.phpnj1j?vendor/rector/rector/src/NodeAnalyzer/PropertyFetchAnalyzer.phpnjoxAvendor/rector/rector/src/NodeAnalyzer/PropertyPresenceChecker.phpnjF7vendor/rector/rector/src/NodeAnalyzer/ScopeAnalyzer.phpnj'@vendor/rector/rector/src/NodeAnalyzer/TerminatedNodeAnalyzer.phpnjXP S:vendor/rector/rector/src/NodeAnalyzer/VariableAnalyzer.php[nj[6:vendor/rector/rector/src/NodeAnalyzer/VariadicAnalyzer.phpnj𕰡Fvendor/rector/rector/src/NodeCollector/BinaryOpConditionsCollector.phpnjQRvendor/rector/rector/src/NodeCollector/NodeAnalyzer/ArrayCallableMethodMatcher.php]nj]9Qvendor/rector/rector/src/NodeCollector/ScopeResolver/ParentClassScopeResolver.phpnjbޚ9vendor/rector/rector/src/NodeCollector/StaticAnalyzer.phpnj81Dvendor/rector/rector/src/NodeCollector/ValueObject/ArrayCallable.phpnj⦖Qvendor/rector/rector/src/NodeCollector/ValueObject/ArrayCallableDynamicMethod.phpnjjAvendor/rector/rector/src/NodeDecorator/CreatedByRuleDecorator.php;nj;=@vendor/rector/rector/src/NodeDecorator/PropertyTypeDecorator.phpnj>vendor/rector/rector/src/NodeManipulator/AssignManipulator.php nj I;@vendor/rector/rector/src/NodeManipulator/BinaryOpManipulator.phpPnjPn.Bvendor/rector/rector/src/NodeManipulator/ClassConstManipulator.phpm njm [Gvendor/rector/rector/src/NodeManipulator/ClassDependencyManipulator.phpU$njU$8ͤCvendor/rector/rector/src/NodeManipulator/ClassInsertManipulator.phpm njm =vendor/rector/rector/src/NodeManipulator/ClassManipulator.php+nj+X1Ivendor/rector/rector/src/NodeManipulator/ClassMethodAssignManipulator.phpdnjd,Cvendor/rector/rector/src/NodeManipulator/ClassMethodManipulator.phpnj Pvendor/rector/rector/src/NodeManipulator/ClassMethodPropertyFetchManipulator.phpnjQ٤@vendor/rector/rector/src/NodeManipulator/FuncCallManipulator.phpTnjT^Dvendor/rector/rector/src/NodeManipulator/FunctionLikeManipulator.phpnj`O_:vendor/rector/rector/src/NodeManipulator/IfManipulator.phpnj}Kvendor/rector/rector/src/NodeManipulator/PropertyFetchAssignManipulator.php nj $u@vendor/rector/rector/src/NodeManipulator/PropertyManipulator.php"nj"bJ=vendor/rector/rector/src/NodeManipulator/StmtsManipulator.phpS njS rbbrPvendor/rector/rector/src/NodeNameResolver/Contract/NodeNameResolverInterface.phpnjg)T>vendor/rector/rector/src/NodeNameResolver/NodeNameResolver.phpnj5#Zvendor/rector/rector/src/NodeNameResolver/NodeNameResolver/ClassConstFetchNameResolver.phpnjAUvendor/rector/rector/src/NodeNameResolver/NodeNameResolver/ClassConstNameResolver.phpnjDxPvendor/rector/rector/src/NodeNameResolver/NodeNameResolver/ClassNameResolver.phpenjewSvendor/rector/rector/src/NodeNameResolver/NodeNameResolver/FuncCallNameResolver.phpnjTSvendor/rector/rector/src/NodeNameResolver/NodeNameResolver/FunctionNameResolver.phpjnjj'lOvendor/rector/rector/src/NodeNameResolver/NodeNameResolver/NameNameResolver.phpCnjC7PPvendor/rector/rector/src/NodeNameResolver/NodeNameResolver/ParamNameResolver.php nj Svendor/rector/rector/src/NodeNameResolver/NodeNameResolver/PropertyNameResolver.phpnjXۤNvendor/rector/rector/src/NodeNameResolver/NodeNameResolver/UseNameResolver.phpnjSvendor/rector/rector/src/NodeNameResolver/NodeNameResolver/VariableNameResolver.phpnjpGHvendor/rector/rector/src/NodeNameResolver/Regex/RegexPatternDetector.php4nj4=vendor/rector/rector/src/NodeNestingScope/ContextAnalyzer.phpnj>8ӤJvendor/rector/rector/src/NodeNestingScope/ValueObject/ControlStructure.phpnjFȤUvendor/rector/rector/src/NodeTypeResolver/Contract/NodeTypeResolverAwareInterface.phpnjyRƮPvendor/rector/rector/src/NodeTypeResolver/Contract/NodeTypeResolverInterface.phpnjVXvendor/rector/rector/src/NodeTypeResolver/DependencyInjection/PHPStanServicesFactory.phpnjB勤?vendor/rector/rector/src/NodeTypeResolver/Node/AttributeKey.php~nj~UKvendor/rector/rector/src/NodeTypeResolver/NodeScopeAndMetadataDecorator.phpknjkLJdvendor/rector/rector/src/NodeTypeResolver/NodeTypeCorrector/AccessoryNonEmptyStringTypeCorrector.phpHnjHA_vendor/rector/rector/src/NodeTypeResolver/NodeTypeCorrector/GenericClassStringTypeCorrector.phpnjK>vendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver.phplJnjlJsǤOvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/CastTypeResolver.phpnjw+\vendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/ClassAndInterfaceTypeResolver.phpFnjFb֤Zvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/ClassConstFetchTypeResolver.phpnjDUĤUvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/IdentifierTypeResolver.phpWnjWxOvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/NameTypeResolver.php nj (1Nvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/NewTypeResolver.php nj Lt Pvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/ParamTypeResolver.phpnj9uXvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/PropertyFetchTypeResolver.php1 nj1 rSvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/PropertyTypeResolver.phpnj"Qvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/ScalarTypeResolver.phpnj^齤_vendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/StaticCallMethodCallTypeResolver.phpdnjdXPvendor/rector/rector/src/NodeTypeResolver/NodeTypeResolver/TraitTypeResolver.phpnj$|[vendor/rector/rector/src/NodeTypeResolver/PHPStan/ObjectWithoutClassTypeWithParentTypes.phpnj0_|_vendor/rector/rector/src/NodeTypeResolver/PHPStan/ParametersAcceptorSelectorVariantsWrapper.phpXnjXY rvendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/Contract/NodeVisitor/ScopeResolverNodeVisitorInterface.phpnj@Vvendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ArgNodeVisitor.php$nj$q]vendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/AssignedToNodeVisitor.phpnj}^vendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefReturnNodeVisitor.phpnj9`vendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ByRefVariableNodeVisitor.php nj ֤Zvendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/ContextNodeVisitor.phpnjeavendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/GlobalVariableNodeVisitor.php nj \Wvendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/NameNodeVisitor.phpnj!npavendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StaticVariableNodeVisitor.php nj VΤZvendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/NodeVisitor/StmtKeyNodeVisitor.php)nj)*Tvendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.phppRnjpRΏɤHvendor/rector/rector/src/NodeTypeResolver/PHPStan/Scope/ScopeFactory.phpnj$rSMvendor/rector/rector/src/NodeTypeResolver/PHPStan/Type/StaticTypeAnalyzer.php}nj}h0Fvendor/rector/rector/src/NodeTypeResolver/PHPStan/Type/TypeFactory.php+nj+@vendor/rector/rector/src/NodeTypeResolver/PHPStan/TypeHasher.phpd njd 6"jVvendor/rector/rector/src/NodeTypeResolver/PhpDoc/NodeAnalyzer/DocBlockClassRenamer.phpnj5hVvendor/rector/rector/src/NodeTypeResolver/PhpDoc/NodeAnalyzer/DocBlockNameImporter.phpnjφUvendor/rector/rector/src/NodeTypeResolver/PhpDoc/NodeAnalyzer/DocBlockTagReplacer.phpnj:&\vendor/rector/rector/src/NodeTypeResolver/PhpDocNodeVisitor/ClassRenamePhpDocNodeVisitor.phpnjlf-^vendor/rector/rector/src/NodeTypeResolver/PhpDocNodeVisitor/NameImportingPhpDocNodeVisitor.phpg)njg);Ptvendor/rector/rector/src/NodeTypeResolver/Reflection/BetterReflection/RectorBetterReflectionSourceLocatorFactory.phpnjrqvendor/rector/rector/src/NodeTypeResolver/Reflection/BetterReflection/SourceLocator/IntermediateSourceLocator.phpnj/Z;|vendor/rector/rector/src/NodeTypeResolver/Reflection/BetterReflection/SourceLocatorProvider/DynamicSourceLocatorProvider.php nj ILvendor/rector/rector/src/NodeTypeResolver/TypeAnalyzer/ArrayTypeAnalyzer.phpdnjd?UMvendor/rector/rector/src/NodeTypeResolver/TypeAnalyzer/StringTypeAnalyzer.phprnjr4_UPvendor/rector/rector/src/NodeTypeResolver/TypeComparator/ArrayTypeComparator.phpnjWQvendor/rector/rector/src/NodeTypeResolver/TypeComparator/ScalarTypeComparator.php<nj<{ޤKvendor/rector/rector/src/NodeTypeResolver/TypeComparator/TypeComparator.php"nj"Fvendor/rector/rector/src/NodeTypeResolver/ValueObject/OldToNewType.phpgnjg~ҤPvendor/rector/rector/src/PHPStan/NodeVisitor/UnreachableStatementNodeVisitor.php nj HPvendor/rector/rector/src/PHPStan/NodeVisitor/WrappedNodeRestoringNodeVisitor.phpnj<ϤQvendor/rector/rector/src/PHPStanStaticTypeMapper/Contract/TypeMapperInterface.phpnj LIvendor/rector/rector/src/PHPStanStaticTypeMapper/DoctrineTypeAnalyzer.php|nj|A+Bvendor/rector/rector/src/PHPStanStaticTypeMapper/Enum/TypeKind.phpnj/ Lvendor/rector/rector/src/PHPStanStaticTypeMapper/PHPStanStaticTypeMapper.phpnjMq6Svendor/rector/rector/src/PHPStanStaticTypeMapper/TypeAnalyzer/UnionTypeAnalyzer.php9nj9`vendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/AccessoryLiteralStringTypeMapper.phpnjKavendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/AccessoryNonEmptyStringTypeMapper.phpnjz8avendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/AccessoryNonFalsyStringTypeMapper.phpnjhN`vendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/AccessoryNumericStringTypeMapper.phpnj8-!Ovendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ArrayTypeMapper.phpnjQvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/BooleanTypeMapper.phpnj=TRvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/CallableTypeMapper.php5nj5|*p?Uvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ClassStringTypeMapper.php<nj<dQvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ClosureTypeMapper.php nj _avendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ConditionalTypeForParameterMapper.phpnji̤Uvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ConditionalTypeMapper.phpnj?B9Ovendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/FloatTypeMapper.phpnj\vendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/GenericClassStringTypeMapper.phpnnjnwP ƤSvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/HasMethodTypeMapper.phpnjYSvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/HasOffsetTypeMapper.phponjoNd\vendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/HasOffsetValueTypeTypeMapper.phpnjUUvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/HasPropertyTypeMapper.phpnj7Qvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/IntegerTypeMapper.phpnjN+Vvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/IntersectionTypeMapper.phpnj)k\2Rvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/IterableTypeMapper.phpbnjbáOvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/MixedTypeMapper.phpnj[کOvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/NeverTypeMapper.phpnj=PWvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/NonEmptyArrayTypeMapper.phpnj1mNvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/NullTypeMapper.phpnj$DNPvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ObjectTypeMapper.php nj Z\vendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ObjectWithoutClassTypeMapper.phpYnjY:AXvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/OversizedArrayTypeMapper.phpnjN.֤Vvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ParentStaticTypeMapper.phpnj Rvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ResourceTypeMapper.php-nj- ߡTvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/SelfObjectTypeMapper.phpznjz?9Pvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/StaticTypeMapper.phpKnjK@Uvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/StrictMixedTypeMapper.phpnjJEPvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/StringTypeMapper.phpnj\Nvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/ThisTypeMapper.php:nj:0V[vendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/TypeWithClassNameTypeMapper.phpLnjLTNOvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.phpnjNvendor/rector/rector/src/PHPStanStaticTypeMapper/TypeMapper/VoidTypeMapper.php1nj1< Hvendor/rector/rector/src/PHPStanStaticTypeMapper/Utils/TypeUnwrapper.php nj =YGvendor/rector/rector/src/Parallel/Application/ParallelFileProcessor.php%nj%vFvendor/rector/rector/src/Parallel/Command/WorkerCommandLineFactory.phpnjF8vendor/rector/rector/src/Parallel/ValueObject/Bridge.php nj ]8<vendor/rector/rector/src/Parallel/ValueObject/BridgeItem.phpnj F3vendor/rector/rector/src/Php/PhpVersionProvider.php nj Rvendor/rector/rector/src/Php/PhpVersionResolver/ComposerJsonPhpVersionResolver.php nj (9vendor/rector/rector/src/Php/PolyfillPackagesProvider.phpnjf 8vendor/rector/rector/src/Php/ReservedKeywordAnalyzer.phpnj2¤Evendor/rector/rector/src/PhpAttribute/AnnotationToAttributeMapper.phpInjI즤fvendor/rector/rector/src/PhpAttribute/AnnotationToAttributeMapper/ArrayAnnotationToAttributeMapper.php nj :nvendor/rector/rector/src/PhpAttribute/AnnotationToAttributeMapper/ArrayItemNodeAnnotationToAttributeMapper.php nj pvendor/rector/rector/src/PhpAttribute/AnnotationToAttributeMapper/ClassConstFetchAnnotationToAttributeMapper.phpnj٤nvendor/rector/rector/src/PhpAttribute/AnnotationToAttributeMapper/ConstExprNodeAnnotationToAttributeMapper.phpUnjUGb♤nvendor/rector/rector/src/PhpAttribute/AnnotationToAttributeMapper/CurlyListNodeAnnotationToAttributeMapper.phpnj;9svendor/rector/rector/src/PhpAttribute/AnnotationToAttributeMapper/DoctrineAnnotationAnnotationToAttributeMapper.phpc njc p9Lgvendor/rector/rector/src/PhpAttribute/AnnotationToAttributeMapper/StringAnnotationToAttributeMapper.phpnj(פkvendor/rector/rector/src/PhpAttribute/AnnotationToAttributeMapper/StringNodeAnnotationToAttributeMapper.phpQnjQ:eUCvendor/rector/rector/src/PhpAttribute/AttributeArrayNameInliner.php nj Q Wvendor/rector/rector/src/PhpAttribute/Contract/AnnotationToAttributeMapperInterface.php`nj`Sk>vendor/rector/rector/src/PhpAttribute/Enum/DocTagNodeState.phpnjd]vendor/rector/rector/src/PhpAttribute/NodeFactory/AnnotationToAttributeIntegerValueCaster.phpz njz /OJvendor/rector/rector/src/PhpAttribute/NodeFactory/AttributeNameFactory.phpu nju Fvendor/rector/rector/src/PhpAttribute/NodeFactory/NamedArgsFactory.php nj AڤNvendor/rector/rector/src/PhpAttribute/NodeFactory/PhpAttributeGroupFactory.phpnj7ZTvendor/rector/rector/src/PhpAttribute/NodeFactory/PhpNestedAttributeGroupFactory.php*nj*S=vendor/rector/rector/src/PhpAttribute/UseAliasNameMatcher.php nj  Fvendor/rector/rector/src/PhpAttribute/ValueObject/UseAliasMetadata.phpnjjvSvendor/rector/rector/src/PhpDocParser/NodeTraverser/SimpleCallableNodeTraverser.php nj  .Ivendor/rector/rector/src/PhpDocParser/NodeVisitor/CallableNodeVisitor.phpnjiZvendor/rector/rector/src/PhpDocParser/PhpDocParser/Contract/PhpDocNodeVisitorInterface.phpvnjvSK Yvendor/rector/rector/src/PhpDocParser/PhpDocParser/Exception/InvalidTraverseException.phpnj3WȤJvendor/rector/rector/src/PhpDocParser/PhpDocParser/PhpDocNodeTraverser.php nj bbvendor/rector/rector/src/PhpDocParser/PhpDocParser/PhpDocNodeVisitor/AbstractPhpDocNodeVisitor.phpQnjQbvendor/rector/rector/src/PhpDocParser/PhpDocParser/PhpDocNodeVisitor/CallablePhpDocNodeVisitor.phpnjǓbavendor/rector/rector/src/PhpDocParser/PhpDocParser/PhpDocNodeVisitor/CloningPhpDocNodeVisitor.phpnj&jvendor/rector/rector/src/PhpDocParser/PhpDocParser/PhpDocNodeVisitor/ParentConnectingPhpDocNodeVisitor.phpnj ȤUvendor/rector/rector/src/PhpDocParser/PhpDocParser/ValueObject/PhpDocAttributeKey.phpnjUBvendor/rector/rector/src/PhpDocParser/PhpParser/SmartPhpParser.phpnjxkIvendor/rector/rector/src/PhpDocParser/PhpParser/SmartPhpParserFactory.phpnjޛkBvendor/rector/rector/src/PhpDocParser/ValueObject/AttributeKey.phpnj&e2vendor/rector/rector/src/PhpParser/AstResolver.php&8nj&8y6?vendor/rector/rector/src/PhpParser/Comparing/NodeComparator.php nj AƤ>vendor/rector/rector/src/PhpParser/Node/AssignAndBinaryMap.phpDnjDi1<vendor/rector/rector/src/PhpParser/Node/BetterNodeFinder.php)nj)cPKvendor/rector/rector/src/PhpParser/Node/CustomNode/FileWithoutNamespace.phpnjF57vendor/rector/rector/src/PhpParser/Node/NodeFactory.php.:nj.:*AH?vendor/rector/rector/src/PhpParser/Node/Value/ValueResolver.php+nj+xGvendor/rector/rector/src/PhpParser/NodeFinder/LocalMethodCallFinder.php nj *p'ΤEvendor/rector/rector/src/PhpParser/NodeFinder/PropertyFetchFinder.php+nj+16vendor/rector/rector/src/PhpParser/NodeTransformer.php4nj4ۅrVvendor/rector/rector/src/PhpParser/NodeTraverser/FileWithoutNamespaceNodeTraverser.phpnj;O"Hvendor/rector/rector/src/PhpParser/NodeTraverser/RectorNodeTraverser.php nj b>vendor/rector/rector/src/PhpParser/Parser/InlineCodeParser.phpnj:*):vendor/rector/rector/src/PhpParser/Parser/ParserErrors.phpnji$:vendor/rector/rector/src/PhpParser/Parser/RectorParser.phpnjV ä=vendor/rector/rector/src/PhpParser/Parser/SimplePhpParser.phpi nji C`Dvendor/rector/rector/src/PhpParser/Printer/BetterStandardPrinter.phpKAnjKA)IAvendor/rector/rector/src/PhpParser/ValueObject/StmtsAndTokens.phpCnjCREvendor/rector/rector/src/PostRector/Application/PostFileProcessor.phpnjGz%Hvendor/rector/rector/src/PostRector/Collector/UseNodesToAddCollector.phpnjT4Kvendor/rector/rector/src/PostRector/Contract/Rector/PostRectorInterface.phpnj/ZĤBvendor/rector/rector/src/PostRector/Guard/AddUseStatementGuard.phpnjpAvendor/rector/rector/src/PostRector/Rector/AbstractPostRector.php:nj:?wFvendor/rector/rector/src/PostRector/Rector/ClassRenamingPostRector.php|nj|ŹNvendor/rector/rector/src/PostRector/Rector/DocblockNameImportingPostRector.php nj Fvendor/rector/rector/src/PostRector/Rector/NameImportingPostRector.php=nj=O{Mvendor/rector/rector/src/PostRector/Rector/UnusedImportRemovingPostRector.phpnjJ(Bvendor/rector/rector/src/PostRector/Rector/UseAddingPostRector.phplnjlTx|Dvendor/rector/rector/src/PostRector/ValueObject/PropertyMetadata.phpTnjT0>vendor/rector/rector/src/ProcessAnalyzer/RectifiedAnalyzer.php nj P 2vendor/rector/rector/src/Rector/AbstractRector.php61nj61s<vendor/rector/rector/src/Rector/AbstractScopeAwareRector.phpjnjjj6<vendor/rector/rector/src/Reflection/ClassModifierChecker.phpnjx?vendor/rector/rector/src/Reflection/ClassReflectionAnalyzer.phpnj V@vendor/rector/rector/src/Reflection/MethodReflectionResolver.phpnjt:vendor/rector/rector/src/Reflection/ReflectionResolver.php,nj,z̢ä>vendor/rector/rector/src/Reporting/DeprecatedRulesReporter.phpnj@vendor/rector/rector/src/Reporting/MissConfigurationReporter.php7 nj7 ۀ6vendor/rector/rector/src/Set/Contract/SetInterface.phpnjf2Ĥ:vendor/rector/rector/src/Set/Contract/SetListInterface.php;nj;S>vendor/rector/rector/src/Set/Contract/SetProviderInterface.phpnj`ͤ.vendor/rector/rector/src/Set/Enum/SetGroup.phpfnjf»+vendor/rector/rector/src/Set/SetManager.phpnjd<vendor/rector/rector/src/Set/SetProvider/CoreSetProvider.phpnj˝;vendor/rector/rector/src/Set/SetProvider/PHPSetProvider.php1nj1Avendor/rector/rector/src/Set/ValueObject/ComposerTriggeredSet.phpanja'1N{9vendor/rector/rector/src/Set/ValueObject/LevelSetList.phpqnjqI0vendor/rector/rector/src/Set/ValueObject/Set.phpnj4vendor/rector/rector/src/Set/ValueObject/SetList.php4 nj4 t¤Evendor/rector/rector/src/Skipper/FileSystem/FnMatchPathNormalizer.phpnj<$>vendor/rector/rector/src/Skipper/FileSystem/PathNormalizer.phpnj2g.vendor/rector/rector/src/Skipper/Fnmatcher.phpbnjbMlW<vendor/rector/rector/src/Skipper/Matcher/FileInfoMatcher.phpnj|0s4vendor/rector/rector/src/Skipper/RealpathMatcher.phpnj&٤Nvendor/rector/rector/src/Skipper/SkipCriteriaResolver/SkippedClassResolver.phpnjՀnNvendor/rector/rector/src/Skipper/SkipCriteriaResolver/SkippedPathsResolver.phpnj]=vendor/rector/rector/src/Skipper/SkipVoter/ClassSkipVoter.phpnj*#8vendor/rector/rector/src/Skipper/Skipper/PathSkipper.phpnjf2/8vendor/rector/rector/src/Skipper/Skipper/SkipSkipper.php$nj$(4vendor/rector/rector/src/Skipper/Skipper/Skipper.phpnjSFw6Kvendor/rector/rector/src/StaticReflection/DynamicSourceLocatorDecorator.php|nj|$Ur]vendor/rector/rector/src/StaticTypeMapper/Contract/PhpDocParser/PhpDocTypeMapperInterface.phpnjyZɤ]vendor/rector/rector/src/StaticTypeMapper/Contract/PhpParser/PhpParserNodeMapperInterface.phpnjiHvendor/rector/rector/src/StaticTypeMapper/Mapper/PhpParserNodeMapper.phpnjnEߤMvendor/rector/rector/src/StaticTypeMapper/Mapper/ScalarStringToTypeMapper.php nj ~Evendor/rector/rector/src/StaticTypeMapper/Naming/NameScopeFactory.phpnjYʥEvendor/rector/rector/src/StaticTypeMapper/PhpDoc/PhpDocTypeMapper.phpnjUvendor/rector/rector/src/StaticTypeMapper/PhpDocParser/IdentifierPhpDocTypeMapper.phpnj!/Wvendor/rector/rector/src/StaticTypeMapper/PhpDocParser/IntersectionPhpDocTypeMapper.php{nj{0ҥSvendor/rector/rector/src/StaticTypeMapper/PhpDocParser/NullablePhpDocTypeMapper.phpnj oޤPvendor/rector/rector/src/StaticTypeMapper/PhpDocParser/UnionPhpDocTypeMapper.php nj ܗdFvendor/rector/rector/src/StaticTypeMapper/PhpParser/ExprNodeMapper.php<nj<;sPvendor/rector/rector/src/StaticTypeMapper/PhpParser/FullyQualifiedNodeMapper.php,nj,m(Lvendor/rector/rector/src/StaticTypeMapper/PhpParser/IdentifierNodeMapper.phpnjA[Rvendor/rector/rector/src/StaticTypeMapper/PhpParser/IntersectionTypeNodeMapper.phpZnjZٲ#Fvendor/rector/rector/src/StaticTypeMapper/PhpParser/NameNodeMapper.php nj 1ˤNvendor/rector/rector/src/StaticTypeMapper/PhpParser/NullableTypeNodeMapper.phpnjhˤHvendor/rector/rector/src/StaticTypeMapper/PhpParser/StringNodeMapper.phppnjp/K@Kvendor/rector/rector/src/StaticTypeMapper/PhpParser/UnionTypeNodeMapper.php& nj& L6>vendor/rector/rector/src/StaticTypeMapper/StaticTypeMapper.phpnjؤPvendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/AliasedObjectType.phpBnjB_^vendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/FullyQualifiedGenericObjectType.phpnjeWvendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/FullyQualifiedObjectType.phpnjTvendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/NonExistingObjectType.phpnjO[vendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/ParentObjectWithoutClassType.phpnj GHOvendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/ParentStaticType.phpnjMvendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/SelfObjectType.phpnjT+դMvendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/SelfStaticType.phpnj#enYvendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/ShortenedGenericObjectType.phpnjԩRvendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/ShortenedObjectType.phpnjI!Ovendor/rector/rector/src/StaticTypeMapper/ValueObject/Type/SimpleStaticType.phpnjovendor/rector/rector/src/Testing/Fixture/FixtureFileFinder.php/nj/֤?vendor/rector/rector/src/Testing/Fixture/FixtureFileUpdater.phpfnjf^Ф<vendor/rector/rector/src/Testing/Fixture/FixtureSplitter.phpnj+>Bvendor/rector/rector/src/Testing/Fixture/FixtureTempFileDumper.phpnjZEEAvendor/rector/rector/src/Testing/PHPUnit/AbstractLazyTestCase.phpnj@Cvendor/rector/rector/src/Testing/PHPUnit/AbstractRectorTestCase.phpz*njz*=vendor/rector/rector/src/Testing/PHPUnit/AbstractTestCase.php-nj-[/Evendor/rector/rector/src/Testing/PHPUnit/StaticPHPUnitEnvironment.php]nj] "Ivendor/rector/rector/src/Testing/PHPUnit/ValueObject/RectorTestResult.phpbnjb`v9J@vendor/rector/rector/src/Testing/TestingParser/TestingParser.php" nj" 0+.vendor/rector/rector/src/Util/ArrayChecker.phpnjc7vendor/rector/rector/src/Util/ArrayParametersMerger.phpXnjX[ʤ,vendor/rector/rector/src/Util/FileHasher.phpnje/vendor/rector/rector/src/Util/MemoryLimiter.phpnj %1vendor/rector/rector/src/Util/NewLineSplitter.phpnj=-vendor/rector/rector/src/Util/NodePrinter.phpnj} 3vendor/rector/rector/src/Util/PhpVersionFactory.phpnj[=vendor/rector/rector/src/Util/Reflection/PrivatesAccessor.php nj 'Q-vendor/rector/rector/src/Util/StringUtils.php&nj&4vendor/rector/rector/src/Validation/RectorAssert.php nj l+)d=vendor/rector/rector/src/Validation/RectorConfigValidator.php nj \T9vendor/rector/rector/src/ValueObject/Application/File.php nj nϜ Cvendor/rector/rector/src/ValueObject/Bootstrap/BootstrapConfigs.phpnjVr6vendor/rector/rector/src/ValueObject/Configuration.phpnjR:vendor/rector/rector/src/ValueObject/Error/SystemError.php nj (:vendor/rector/rector/src/ValueObject/FileProcessResult.phpnjͻ8vendor/rector/rector/src/ValueObject/FuncCallAndExpr.phpnj5.3vendor/rector/rector/src/ValueObject/MethodName.phpnjb4 3vendor/rector/rector/src/ValueObject/PhpVersion.php|nj|b=פ:vendor/rector/rector/src/ValueObject/PhpVersionFeature.phpBnjB A8vendor/rector/rector/src/ValueObject/PolyfillPackage.phpnj-s6vendor/rector/rector/src/ValueObject/ProcessResult.php&nj&Uz ;vendor/rector/rector/src/ValueObject/Reporting/FileDiff.phpnjȤ=vendor/rector/rector/src/ValueObject/SprintfStringAndArgs.phpnj{먤3vendor/rector/rector/src/ValueObject/Visibility.phpnj4ȖNvendor/rector/rector/src/VendorLocker/Exception/UnresolvableClassException.phpnje]vendor/rector/rector/src/VendorLocker/NodeVendorLocker/ClassMethodParamVendorLockResolver.php nj 8Ԥ]vendor/rector/rector/src/VendorLocker/NodeVendorLocker/ClassMethodReturnTypeOverrideGuard.php{nj{L_^vendor/rector/rector/src/VendorLocker/NodeVendorLocker/ClassMethodReturnVendorLockResolver.phpj njj LMLvendor/rector/rector/src/VendorLocker/ParentClassMethodTypeOverrideGuard.phpAnjAxp0Kvendor/rector/rector/src/VersionBonding/Contract/MinPhpVersionInterface.phpnj# HMvendor/rector/rector/src/VersionBonding/Contract/RelatedPolyfillInterface.phpRnjRG?>vendor/rector/rector/src/VersionBonding/PhpVersionedFilter.phpEnjE2vendor/rector/rector/src/functions/node_helper.phpnj^S&8vendor/rector/rector/stubs-rector/Internal/Constants.php^nj^FȤ=vendor/rector/rector/stubs-rector/Internal/EnumInterfaces.phpnjYj<vendor/rector/rector/stubs-rector/Internal/NativeClasses.phpnjQ@vendor/rector/rector/stubs-rector/PHPUnit/Framework/TestCase.php?nj?\ԤOvendor/rector/rector/templates/custom-rule/utils/rector/src/Rector/__Name__.phpInjI'-+hvendor/rector/rector/templates/custom-rule/utils/rector/tests/Rector/__Name__/Fixture/some_class.php.incnj^vendor/rector/rector/templates/custom-rule/utils/rector/tests/Rector/__Name__/__Name__Test.php}nj}C$khvendor/rector/rector/templates/custom-rule/utils/rector/tests/Rector/__Name__/config/configured_rule.phpnj'̤kvendor/rector/rector/templates/custom-rules-annotations/utils/rector/tests/Rector/__Name__/__Name__Test.php^nj^r>vendor/rector/rector/templates/rector-github-action-check.yamlnjl7vendor/rector/rector/templates/rector-gitlab-check.yamlnjXͤ.vendor/rector/rector/templates/rector.php.distnjt4>(vendor/sebastian/cli-parser/ChangeLog.mdLnjL#vendor/sebastian/cli-parser/LICENSEnjk%vendor/sebastian/cli-parser/README.md+nj+b'vendor/sebastian/cli-parser/SECURITY.mdunjuKJ)vendor/sebastian/cli-parser/composer.jsonnj[9_*vendor/sebastian/cli-parser/src/Parser.phpnjjk Gvendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.phpnj ,x8vendor/sebastian/cli-parser/src/exceptions/Exception.phplnjl@1Rvendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.phpnj ?3Uvendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.phpnjwEvendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php|nj|'vendor/sebastian/code-unit/ChangeLog.md nj G3"vendor/sebastian/code-unit/LICENSEnjP@٤$vendor/sebastian/code-unit/README.mdnjsρ&vendor/sebastian/code-unit/SECURITY.mdPnjPE >Ϥ(vendor/sebastian/code-unit/composer.jsonnjˆ2vendor/sebastian/code-unit/src/ClassMethodUnit.php nj J,vendor/sebastian/code-unit/src/ClassUnit.phpnjm=+vendor/sebastian/code-unit/src/CodeUnit.php30nj30=i5vendor/sebastian/code-unit/src/CodeUnitCollection.phpnjN'=vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.phpUnjU%|+vendor/sebastian/code-unit/src/FileUnit.phpnj/vendor/sebastian/code-unit/src/FunctionUnit.phpnjrY6vendor/sebastian/code-unit/src/InterfaceMethodUnit.phpnjl`0vendor/sebastian/code-unit/src/InterfaceUnit.phpnj=%t)vendor/sebastian/code-unit/src/Mapper.phpnjXVX2vendor/sebastian/code-unit/src/TraitMethodUnit.php nj  1Z,vendor/sebastian/code-unit/src/TraitUnit.phpnjTJ˿7vendor/sebastian/code-unit/src/exceptions/Exception.phpjnjjwkFvendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.phpnj6*a>vendor/sebastian/code-unit/src/exceptions/NoTraitException.phpnjΤAvendor/sebastian/code-unit/src/exceptions/ReflectionException.phpnjO6vendor/sebastian/code-unit-reverse-lookup/ChangeLog.mdnjцd1vendor/sebastian/code-unit-reverse-lookup/LICENSEnjf3vendor/sebastian/code-unit-reverse-lookup/README.mdnj=8 5vendor/sebastian/code-unit-reverse-lookup/SECURITY.mdPnjPE >Ϥ7vendor/sebastian/code-unit-reverse-lookup/composer.jsonAnjAT솤8vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php nj 2(vendor/sebastian/comparator/ChangeLog.mdnj^#vendor/sebastian/comparator/LICENSEnj^2%vendor/sebastian/comparator/README.md;nj;'vendor/sebastian/comparator/SECURITY.mdunjuKJ)vendor/sebastian/comparator/composer.json$nj$3vendor/sebastian/comparator/src/ArrayComparator.php:nj:ԯ.vendor/sebastian/comparator/src/Comparator.phpFnjF0t5vendor/sebastian/comparator/src/ComparisonFailure.phpnjC-5vendor/sebastian/comparator/src/DOMNodeComparator.phpC njC 6vendor/sebastian/comparator/src/DateTimeComparator.php nj ɏ>[7vendor/sebastian/comparator/src/ExceptionComparator.phpnj'+vendor/sebastian/comparator/src/Factory.phpX njX + [8vendor/sebastian/comparator/src/MockObjectComparator.php8nj85vendor/sebastian/comparator/src/NumericComparator.phpnjZpR4vendor/sebastian/comparator/src/ObjectComparator.phpE njE bkA$6vendor/sebastian/comparator/src/ResourceComparator.phpnj:H4vendor/sebastian/comparator/src/ScalarComparator.php nj >vendor/sebastian/comparator/src/SplObjectStorageComparator.phpnjpr2vendor/sebastian/comparator/src/TypeComparator.phpnjq8vendor/sebastian/comparator/src/exceptions/Exception.phpmnjmt ?vendor/sebastian/comparator/src/exceptions/RuntimeException.phpnjӤ(vendor/sebastian/complexity/ChangeLog.mdnjH#vendor/sebastian/complexity/LICENSEnjP@٤%vendor/sebastian/complexity/README.mdnj['vendor/sebastian/complexity/SECURITY.mdunjuKJ)vendor/sebastian/complexity/composer.json;nj;N2ˤ.vendor/sebastian/complexity/src/Calculator.php9 nj9 $9vendor/sebastian/complexity/src/Complexity/Complexity.php;nj; Cvendor/sebastian/complexity/src/Complexity/ComplexityCollection.phpm njm xhKvendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.phpnjh7vendor/sebastian/complexity/src/Exception/Exception.phpmnjm->vendor/sebastian/complexity/src/Exception/RuntimeException.phpnjlEHvendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php nj %#2Rvendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.phpnj;ɽ,"vendor/sebastian/diff/ChangeLog.mdnjAvendor/sebastian/diff/LICENSEnjܡ7vendor/sebastian/diff/README.mdx njx Z!vendor/sebastian/diff/SECURITY.mdunjuKJ#vendor/sebastian/diff/composer.jsonnjY#vendor/sebastian/diff/src/Chunk.php nj cݤ"vendor/sebastian/diff/src/Diff.phpWnjWsv.$vendor/sebastian/diff/src/Differ.phpMnjMƤ>vendor/sebastian/diff/src/Exception/ConfigurationException.phpnj)1vendor/sebastian/diff/src/Exception/Exception.phpanja>f@vendor/sebastian/diff/src/Exception/InvalidArgumentException.phpnjL}f"vendor/sebastian/diff/src/Line.phpnjR@vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.phpnj>DOvendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.phps njs >A?vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.phpnjw:vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php1nj1M'?vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php nj 0Cvendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php*nj*K5P=vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php nj s$vendor/sebastian/diff/src/Parser.phpn njn FMvendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php@ nj@ KU{)vendor/sebastian/environment/ChangeLog.md nj WĤ$vendor/sebastian/environment/LICENSEnj'|&vendor/sebastian/environment/README.mdfnjf٤(vendor/sebastian/environment/SECURITY.mdunjuKJ*vendor/sebastian/environment/composer.json?nj?BB,vendor/sebastian/environment/src/Console.phpnj_B9,vendor/sebastian/environment/src/Runtime.phpnjF&vendor/sebastian/exporter/ChangeLog.mdwnjwMä!vendor/sebastian/exporter/LICENSEnj^2#vendor/sebastian/exporter/README.md nj _P%vendor/sebastian/exporter/SECURITY.mdunjuKJ'vendor/sebastian/exporter/composer.jsonAnjA*vendor/sebastian/exporter/src/Exporter.php6&nj6&[{*vendor/sebastian/global-state/ChangeLog.mdMnjM,Kf%vendor/sebastian/global-state/LICENSEnjik'vendor/sebastian/global-state/README.mdKnjKM)vendor/sebastian/global-state/SECURITY.mdunjuKJ+vendor/sebastian/global-state/composer.jsonnjƤ2vendor/sebastian/global-state/src/CodeExporter.php> nj> k1vendor/sebastian/global-state/src/ExcludeList.php nj .vendor/sebastian/global-state/src/Restorer.php nj vl.vendor/sebastian/global-state/src/Snapshot.phpi(nji(q:vendor/sebastian/global-state/src/exceptions/Exception.phppnjp Avendor/sebastian/global-state/src/exceptions/RuntimeException.phpnjpƤ+vendor/sebastian/lines-of-code/ChangeLog.mdnjD㩤&vendor/sebastian/lines-of-code/LICENSEnjP@٤(vendor/sebastian/lines-of-code/README.md=nj=Τ*vendor/sebastian/lines-of-code/SECURITY.mdunjuKJ,vendor/sebastian/lines-of-code/composer.jsonFnjFw.vendor/sebastian/lines-of-code/src/Counter.php nj i辪:vendor/sebastian/lines-of-code/src/Exception/Exception.phpqnjq0+Ivendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.phpnj Gvendor/sebastian/lines-of-code/src/Exception/NegativeValueException.phpnjy<Avendor/sebastian/lines-of-code/src/Exception/RuntimeException.phpnj/:vendor/sebastian/lines-of-code/src/LineCountingVisitor.php nj kJM2vendor/sebastian/lines-of-code/src/LinesOfCode.php^ nj^ s/vendor/sebastian/object-enumerator/ChangeLog.md nj *vendor/sebastian/object-enumerator/LICENSEnjf,vendor/sebastian/object-enumerator/README.mdnj_`U.vendor/sebastian/object-enumerator/SECURITY.mdPnjPE >Ϥ0vendor/sebastian/object-enumerator/composer.jsonnja&.vendor/sebastian/object-enumerator/phpunit.xmlnjx5vendor/sebastian/object-enumerator/src/Enumerator.php)nj)3.vendor/sebastian/object-reflector/ChangeLog.mdnja)vendor/sebastian/object-reflector/LICENSEnjR6+vendor/sebastian/object-reflector/README.mdnjɤ-vendor/sebastian/object-reflector/SECURITY.mdPnjPE >Ϥ/vendor/sebastian/object-reflector/composer.jsonnjp9vendor/sebastian/object-reflector/src/ObjectReflector.phpnjt/vendor/sebastian/recursion-context/ChangeLog.mdnj$ܤ*vendor/sebastian/recursion-context/LICENSEnj^2,vendor/sebastian/recursion-context/README.md-nj- >.vendor/sebastian/recursion-context/SECURITY.mdunjuKJ0vendor/sebastian/recursion-context/composer.jsonnjzWq2vendor/sebastian/recursion-context/src/Context.php>nj>9"vendor/sebastian/type/ChangeLog.mdnjyvendor/sebastian/type/LICENSEnj vendor/sebastian/type/README.mdnjM˳!vendor/sebastian/type/SECURITY.mdPnjPE >Ϥ#vendor/sebastian/type/composer.jsonnjMj$vendor/sebastian/type/infection.jsonnj 'vendor/sebastian/type/src/Parameter.phpnj .vendor/sebastian/type/src/ReflectionMapper.php.nj.@i&vendor/sebastian/type/src/TypeName.php@nj@X钤1vendor/sebastian/type/src/exception/Exception.phpanjag@ɼ8vendor/sebastian/type/src/exception/RuntimeException.phpwnjw56/vendor/sebastian/type/src/type/CallableType.phpnj/_Ȥ,vendor/sebastian/type/src/type/FalseType.phppnjpV!4vendor/sebastian/type/src/type/GenericObjectType.phpnj@53vendor/sebastian/type/src/type/IntersectionType.php nj <㤤/vendor/sebastian/type/src/type/IterableType.phpnj2A,vendor/sebastian/type/src/type/MixedType.phpnjL/̤,vendor/sebastian/type/src/type/NeverType.phpnj +vendor/sebastian/type/src/type/NullType.phpnjo|-vendor/sebastian/type/src/type/ObjectType.phpnj-{-vendor/sebastian/type/src/type/SimpleType.php6nj6Ť-vendor/sebastian/type/src/type/StaticType.phpnjӆs+vendor/sebastian/type/src/type/TrueType.phpknjk幤'vendor/sebastian/type/src/type/Type.phpnjP^+,vendor/sebastian/type/src/type/UnionType.php nj i.vendor/sebastian/type/src/type/UnknownType.php nj ?Ȥ+vendor/sebastian/type/src/type/VoidType.phpnj%vendor/sebastian/version/ChangeLog.mdnj>Bt vendor/sebastian/version/LICENSEnjVo"vendor/sebastian/version/README.mdnjW$vendor/sebastian/version/SECURITY.mdPnjPE >Ϥ&vendor/sebastian/version/composer.jsonnnjn(vendor/sebastian/version/src/Version.phpnjkvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowAttributesJoiningSniff.php7nj7`svendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowMultipleAttributesPerLineSniff.php nj ^ˤqvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/RequireAttributeAfterDocCommentSniff.php nj <avendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractMethodSignature.php nj )פtvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractPropertyConstantAndEnumCaseSpacing.phpnj2 dvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/BackedEnumTypeSpacingSniff.phpy njy &:fvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassConstantVisibilitySniff.php nj RZZvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassLengthSniff.phpnjuդavendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassMemberSpacingSniff.php"nj"\h ]vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassStructureSniff.php)mnj)m^vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ConstantSpacingSniff.phpJ njJ Ksvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowConstructorPropertyPromotionSniff.phpnj+0tvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowLateStaticBindingForConstantsSniff.php*nj*Panvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiConstantDefinitionSniff.phpgnjgJcnvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiPropertyDefinitionSniff.phpnjOtvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowStringExpressionPropertyFetchSniff.phpnjjfjvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EmptyLinesAroundClassBracesSniff.php{nj{ ?(^vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EnumCaseSpacingSniff.phpdnjdRfvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ForbiddenPublicPropertySniff.php" nj" A9\vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MethodSpacingSniff.phpnj[>|evendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MissingClassGroupsException.phpnj Hgvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ModernClassNameReferenceSniff.phpnj v`vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ParentCallSpacingSniff.php| nj| knbvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertyDeclarationSniff.php[3nj[3U^vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertySpacingSniff.phpu nju eYevendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireAbstractOrFinalSniff.phpnj,rvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireConstructorPropertyPromotionSniff.php /nj /őnvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireMultiLineMethodSignatureSniff.phpnjK\cvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSelfReferenceSniff.php nj  {<ovendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSingleLineMethodSignatureSniff.php nj EZrmvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousAbstractClassNamingSniff.php:nj:~$Фevendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousErrorNamingSniff.phpnjO<ivendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousExceptionNamingSniff.php$nj$[פivendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousInterfaceNamingSniff.phpnjñ]evendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousTraitNamingSniff.phpnj&bvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseDeclarationSniff.php nj ;^vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseSpacingSniff.php&nj&>hvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/UnsupportedClassGroupException.php2nj2hqwgvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/UselessLateStaticBindingSniff.php nj 6*1mvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AbstractRequireOneLineDocComment.php2nj2؂B`vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AnnotationNameSniff.phpnj"Jqvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DeprecatedAnnotationDeclarationSniff.php.nj.Ljvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowCommentAfterCodeSniff.phpnj4svendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowOneLinePropertyDocCommentSniff.php nj prŤcvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DocCommentSpacingSniff.phpdnjd72Z^vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/EmptyCommentSniff.phpnjjfvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenAnnotationsSniff.phpNnjNcvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenCommentsSniff.phpnjTJmvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/InlineDocCommentDeclarationSniff.php7nj7jvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLineDocCommentSniff.php8nj8orvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLinePropertyDocCommentSniff.phpnjkvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessFunctionDocCommentSniff.phpnjQ!jvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessInheritDocCommentSniff.php nj P[vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Complexity/CognitiveSniff.phpX njX ndsvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractControlStructureSpacing.phpEnjEf]ivendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractLineCondition.php0nj0Ҥnvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AssignmentInConditionSniff.php nj Duvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/BlockControlStructureSpacingSniff.php nj 3X[6vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowContinueWithoutIntegerOperandInSwitchSniff.phpqnjq3fvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowEmptySniff.phpnjo22wvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowNullSafeObjectOperatorSniff.php7nj7XJuvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowShortTernaryOperatorSniff.php[nj[[Hvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowTrailingMultiLineTernaryOperatorSniff.php nj hDovendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowYodaComparisonSniff.phpnjfCkbvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/EarlyExitSniff.php6nj6/!qnvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/JumpStatementsSpacingSniff.phpnjiyvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/LanguageConstructWithParenthesesSniff.phpP njP w,akvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithParenthesesSniff.php nj Xnvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithoutParenthesesSniff.php nj šrvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineConditionSniff.phpnjxvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineTernaryOperatorSniff.phpnj]yvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceEqualOperatorSniff.phpnjBFtvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceOperatorSniff.phpnj @vvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullSafeObjectOperatorSniff.phpAnjA>Rtvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireShortTernaryOperatorSniff.phpS njS \<svendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireSingleLineConditionSniff.phpN njN Jтovendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireTernaryOperatorSniff.phpa#nja#W3nvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireYodaComparisonSniff.phpnj*ovendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UnsupportedKeywordException.phppnjpF ¤uvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UselessIfConditionWithReturnSniff.php)nj)0ovendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UselessTernaryOperatorSniff.php nj n'[vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DeadCatchSniff.phpnjԤMkvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DisallowNonCapturingCatchSniff.php?nj?|tƤhvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/ReferenceThrowableOnlySniff.php@nj@~"jvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/RequireNonCapturingCatchSniff.php.nj.oޤWvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FileLengthSniff.php:nj: 񡒤bvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FilepathNamespaceExtractor.phpnj RgWvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/LineLengthSniff.php nj =dvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/TypeNameMatchesFileNameSniff.phpnjpY\vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/AbstractLineCall.php` nj` 9xivendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/ArrowFunctionDeclarationSniff.php;nj;ypfvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowArrowFunctionSniff.phpnj~zfvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowEmptyFunctionSniff.php"nj"`gvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowNamedArgumentsSniff.phpnj Τlvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInCallSniff.phpU njU x^rvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInClosureUseSniff.phpP njP Ɛ .svendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInDeclarationSniff.phpnjy S_vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/FunctionLengthSniff.phpxnjxdeevendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/NamedArgumentSpacingSniff.phpnj(jevendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireArrowFunctionSniff.phpnj!evendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireMultiLineCallSniff.php!nj!}cpfvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireSingleLineCallSniff.php~nj~?7kvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInCallSniff.php nj 8:qvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInClosureUseSniff.phpnjF0rvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInDeclarationSniff.phpnj.^vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StaticClosureSniff.phpC njC BX[vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StrictCallSniff.phpv njv 7%wvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedInheritedVariablePassedToClosureSniff.php3nj3{4`vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedParameterSniff.php nj omvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UselessParameterDefaultValueSniff.phpnjrvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AbstractFullyQualifiedGlobalReference.php?nj?JLjvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.phpnj=gݤbvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/DisallowGroupUseSniff.php nj 4 Ťuvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedClassNameInAnnotationSniff.phpEnjE<܈jvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedExceptionsSniff.php2nj2Vovendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalConstantsSniff.phpnj\ovendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalFunctionsSniff.phpnjevendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/MultipleUsesPerLineSniff.phpnjfvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceDeclarationSniff.phpnjMbvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceSpacingSniff.phpnjH?2hvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.phpfnjf6CKkvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/RequireOneNamespaceInFileSniff.phpnj\T\vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UnusedUsesSniff.php$nj$)*nvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.phpnj5Mfvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseFromSameNamespaceSniff.phpnjnvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseOnlyWhitelistedNamespacesSniff.phpknjk5 t\vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseSpacingSniff.phpB+njB+wJ^vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UselessAliasSniff.phpnj!Mnvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/DisallowNumericLiteralSeparatorSniff.phpnjㄧmvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/RequireNumericLiteralSeparatorSniff.phptnjtPyˤgvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowEqualOperatorsSniff.phpanja[XbPwvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowIncrementAndDecrementOperatorsSniff.php nj o2hvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/NegationOperatorSpacingSniff.php: nj: V8Τrvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireCombinedAssignmentOperatorSniff.php/nj/,=ˤvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireOnlyStandaloneIncrementAndDecrementOperatorsSniff.phpnjgC)fvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/SpreadOperatorSpacingSniff.php nj  1hvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowDirectMagicInvokeCallSniff.phpnj~ؤ\vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowReferenceSniff.phpj njj %n.[vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ForbiddenClassesSniff.php nj >3mvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/OptimizedFunctionsWithoutUnpackingSniff.phpnjywVѤ[vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ReferenceSpacingSniff.phpnjcvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireExplicitAssertionSniff.php8nj8#ӕXvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireNowdocSniff.phpnjZFTvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ShortListSniff.php/nj/[ESvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/TypeCastSniff.phpX njX ]%]vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessParenthesesSniff.phpJnjJܻ[vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessSemicolonSniff.phpnj6/fvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Strings/DisallowVariableParsingSniff.phpenjedziJvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TestCase.phpnj7Ҙfvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ClassConstantTypeHintSniff.php}nj}2tbvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DNFTypeHintFormatSniff.php+nj+6Фcvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DeclareStrictTypesSniff.php!nj!4plvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowArrayTypeHintSyntaxSniff.php!nj!R mfvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowMixedTypeHintSniff.phpnj^Ӥ^vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/LongTypeHintsSniff.php! nj! ~kvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullTypeHintOnLastPositionSniff.php nj pvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullableTypeForNullDefaultValueSniff.php nj bvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSniff.phpVnjVu4ivendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSpacingSniff.phpnjLavendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/PropertyTypeHintSniff.phpTnjT'_vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSniff.php]nj]-q1fvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSpacingSniff.phpnj^+dvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UnionTypeHintFormatSniff.php4 nj4 `hvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UselessConstantTypeHintSniff.phpM njM vlvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowSuperGlobalVariableSniff.php/nj/wivendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowVariableVariableSniff.php(nj( nvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DuplicateAssignmentToVariableSniff.php~nj~ _vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UnusedVariableSniff.php%Onj%OOn'`vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UselessVariableSniff.php-.nj-.7bvendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Whitespaces/DuplicateSpacesSniff.phpgnjg#RBvendor/slevomat/coding-standard/SlevomatCodingStandard/ruleset.xmlnjӒl6vendor/slevomat/coding-standard/autoload-bootstrap.php#nj#6Jd̤-vendor/slevomat/coding-standard/composer.jsonnjQܤ-vendor/slevomat/coding-standard/doc/arrays.mdMnjM1vendor/slevomat/coding-standard/doc/attributes.mdnj.vendor/slevomat/coding-standard/doc/classes.mdJ7njJ7C{1vendor/slevomat/coding-standard/doc/commenting.mdnjϤ1vendor/slevomat/coding-standard/doc/complexity.md nj ,C~9vendor/slevomat/coding-standard/doc/control-structures.mdL%njL%1vendor/slevomat/coding-standard/doc/exceptions.mdnj,vendor/slevomat/coding-standard/doc/files.md) nj) Pb0vendor/slevomat/coding-standard/doc/functions.mdnj(1vendor/slevomat/coding-standard/doc/namespaces.md nj x٠.vendor/slevomat/coding-standard/doc/numbers.mdqnjq Ɗ0vendor/slevomat/coding-standard/doc/operators.mdqnjqפ*vendor/slevomat/coding-standard/doc/php.mdX njX ^M.vendor/slevomat/coding-standard/doc/strings.mdnj\1vendor/slevomat/coding-standard/doc/type-hints.md*nj*0vendor/slevomat/coding-standard/doc/variables.mdnj@ʤ2vendor/slevomat/coding-standard/doc/whitespaces.mdonjo!բ&vendor/symfony/console/Application.php.nj.r&:.vendor/symfony/console/Attribute/AsCommand.php]nj]֚#vendor/symfony/console/CHANGELOG.md nj P2vendor/symfony/console/CI/GithubActionReporter.phpK njK 9Ό vendor/symfony/console/Color.phpnj*vendor/symfony/console/Formatter/OutputFormatterStyleStack.php nj d\Fvendor/symfony/console/Formatter/WrappableOutputFormatterInterface.phpnj}z6vendor/symfony/console/Helper/DebugFormatterHelper.phpJ njJ G(2vendor/symfony/console/Helper/DescriptorHelper.php nj X^}ߤ(vendor/symfony/console/Helper/Dumper.phpnjڮ?91vendor/symfony/console/Helper/FormatterHelper.phpX njX uwY(vendor/symfony/console/Helper/Helper.phpBnjBcE1vendor/symfony/console/Helper/HelperInterface.phpNnjNԎD+vendor/symfony/console/Helper/HelperSet.php nj AtW2vendor/symfony/console/Helper/InputAwareHelper.phpnj/vendor/symfony/console/Helper/ProcessHelper.phpznjz3-vendor/symfony/console/Helper/ProgressBar.php"Inj"Iez3vendor/symfony/console/Helper/ProgressIndicator.phpnjܤ0vendor/symfony/console/Helper/QuestionHelper.php5Lnj5LM=7vendor/symfony/console/Helper/SymfonyQuestionHelper.php nj 3T'vendor/symfony/console/Helper/Table.phptnjtf: +vendor/symfony/console/Helper/TableCell.phpnj.0vendor/symfony/console/Helper/TableCellStyle.phpnj-7+vendor/symfony/console/Helper/TableRows.phpEnjEa0vendor/symfony/console/Helper/TableSeparator.phpnj& ,vendor/symfony/console/Helper/TableStyle.php1nj1*vendor/symfony/console/Input/ArgvInput.php0nj0ce+vendor/symfony/console/Input/ArrayInput.phpnj&vendor/symfony/console/Input/Input.phpnjܤ.vendor/symfony/console/Input/InputArgument.phpu nju C4vendor/symfony/console/Input/InputAwareInterface.php:nj: '0vendor/symfony/console/Input/InputDefinition.php.nj./vendor/symfony/console/Input/InputInterface.phpmnjmӾ},vendor/symfony/console/Input/InputOption.phpnj{(9vendor/symfony/console/Input/StreamableInputInterface.phpinji,vendor/symfony/console/Input/StringInput.php nj H?vendor/symfony/console/LICENSE,nj,U/vendor/symfony/console/Logger/ConsoleLogger.phpnjU0vendor/symfony/console/Output/BufferedOutput.phpUnjUBE$ޤ/vendor/symfony/console/Output/ConsoleOutput.php8nj8S.8vendor/symfony/console/Output/ConsoleOutputInterface.php nj _6vendor/symfony/console/Output/ConsoleSectionOutput.phpXnjXGRä,vendor/symfony/console/Output/NullOutput.php nj Ф(vendor/symfony/console/Output/Output.php>nj>~81vendor/symfony/console/Output/OutputInterface.php\ nj\ t.vendor/symfony/console/Output/StreamOutput.phpnj5vendor/symfony/console/Output/TrimmedBufferOutput.php<nj<k 2vendor/symfony/console/Question/ChoiceQuestion.phpnj8vendor/symfony/console/Question/ConfirmationQuestion.phpnj?uȤ,vendor/symfony/console/Question/Question.phpYnjY9 vendor/symfony/console/README.mdnj=NP4vendor/symfony/console/Resources/bin/hiddeninput.exe$nj$v0vendor/symfony/console/Resources/completion.bash nj 'r8vendor/symfony/console/SignalRegistry/SignalRegistry.php1nj1v.3vendor/symfony/console/SingleCommandApplication.phpnjg,vendor/symfony/console/Style/OutputStyle.php nj /vendor/symfony/console/Style/StyleInterface.phpP njP p+Ť-vendor/symfony/console/Style/SymfonyStyle.php(9nj(91Ϥ#vendor/symfony/console/Terminal.phpBnjBri3vendor/symfony/console/Tester/ApplicationTester.php\ nj\ !t9vendor/symfony/console/Tester/CommandCompletionTester.phpnjt5N/vendor/symfony/console/Tester/CommandTester.php: nj: 7)a@vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.phpnjѧز-vendor/symfony/console/Tester/TesterTrait.phpnjC$vendor/symfony/console/composer.json=nj=|1vendor/symfony/deprecation-contracts/CHANGELOG.mdnjh{#,vendor/symfony/deprecation-contracts/LICENSE,nj, K.vendor/symfony/deprecation-contracts/README.mdnjX2vendor/symfony/deprecation-contracts/composer.jsonInjI 1vendor/symfony/deprecation-contracts/function.phpnjOݤ"vendor/symfony/finder/CHANGELOG.md nj 3g/vendor/symfony/finder/Comparator/Comparator.phpnj2TG3vendor/symfony/finder/Comparator/DateComparator.phpnjY5vendor/symfony/finder/Comparator/NumberComparator.php nj hMLۤ9vendor/symfony/finder/Exception/AccessDeniedException.phpnjcWޤ>vendor/symfony/finder/Exception/DirectoryNotFoundException.phpnjRI vendor/symfony/finder/Finder.php_nj_a_#vendor/symfony/finder/Gitignore.php nj hnvendor/symfony/finder/Glob.phpnjm+G7vendor/symfony/finder/Iterator/CustomFilterIterator.phpnj #:vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpynjy;vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpbnjb,Avendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php nj f19vendor/symfony/finder/Iterator/FileTypeFilterIterator.phponjo"f<vendor/symfony/finder/Iterator/FilecontentFilterIterator.phpnj~ 9vendor/symfony/finder/Iterator/FilenameFilterIterator.phpQnjQ/vendor/symfony/finder/Iterator/LazyIterator.phpnj-9=vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php nj D5vendor/symfony/finder/Iterator/PathFilterIterator.phpnjdސ{=vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php(nj( 襤:vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpPnjPgɤ3vendor/symfony/finder/Iterator/SortableIterator.phpnj澺;vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.phpnnjnكtvendor/symfony/finder/LICENSE,nj,Uvendor/symfony/finder/README.mdnjC%vendor/symfony/finder/SplFileInfo.phpnj* #vendor/symfony/finder/composer.jsonnj'vendor/symfony/polyfill-ctype/Ctype.phpnj8%vendor/symfony/polyfill-ctype/LICENSE,nj,'vendor/symfony/polyfill-ctype/README.md^nj^lHk+vendor/symfony/polyfill-ctype/bootstrap.php@nj@jQ9-vendor/symfony/polyfill-ctype/bootstrap80.phprnjrF)+vendor/symfony/polyfill-ctype/composer.jsonnje2vendor/symfony/polyfill-intl-grapheme/Grapheme.php5nj5?h>-vendor/symfony/polyfill-intl-grapheme/LICENSE,nj,H/vendor/symfony/polyfill-intl-grapheme/README.mdnj63vendor/symfony/polyfill-intl-grapheme/bootstrap.php nj ]W5vendor/symfony/polyfill-intl-grapheme/bootstrap80.php nj ԃR5vendor/symfony/polyfill-intl-grapheme/bootstrap85.php nj ɤ3vendor/symfony/polyfill-intl-grapheme/composer.jsonnjvs?/vendor/symfony/polyfill-intl-normalizer/LICENSE,nj,H6vendor/symfony/polyfill-intl-normalizer/Normalizer.php,nj,91vendor/symfony/polyfill-intl-normalizer/README.mdnj+tKFvendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.phpnj%Rvendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.phpDnjD'CԤTvendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php{nj{jeLvendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.phpD5njD5 Xvendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.phponjoc,Wvendor/symfony/polyfill-intl-normalizer/Resources/unidata/rawCanonicalDecomposition.phpnj1[s[vendor/symfony/polyfill-intl-normalizer/Resources/unidata/rawCompatibilityDecomposition.php nj c*❤5vendor/symfony/polyfill-intl-normalizer/bootstrap.phpnjk)7vendor/symfony/polyfill-intl-normalizer/bootstrap80.phpnjdt5vendor/symfony/polyfill-intl-normalizer/composer.jsonnj rT(vendor/symfony/polyfill-mbstring/LICENSE,nj,H-vendor/symfony/polyfill-mbstring/Mbstring.phpʛnjʛt1*vendor/symfony/polyfill-mbstring/README.mdrnjrA`Bvendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.phpa nja |ⳤ@vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php_nj_dFvendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php9nj9>|zK@vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpfnjfP.vendor/symfony/polyfill-mbstring/bootstrap.phpknjkАH@0vendor/symfony/polyfill-mbstring/bootstrap72.phpQ!njQ!3^0vendor/symfony/polyfill-mbstring/bootstrap80.php9'nj9'w*.vendor/symfony/polyfill-mbstring/composer.jsonnjvE%vendor/symfony/polyfill-php73/LICENSE,nj,'vendor/symfony/polyfill-php73/Php73.phpbnjbJ<'vendor/symfony/polyfill-php73/README.md/nj/m?vendor/symfony/polyfill-php73/Resources/stubs/JsonException.phpEnjE8S+vendor/symfony/polyfill-php73/bootstrap.phpnj|+vendor/symfony/polyfill-php73/composer.jsonnjt%vendor/symfony/polyfill-php80/LICENSE,nj, K'vendor/symfony/polyfill-php80/Php80.php nj )*vendor/symfony/polyfill-php80/PhpToken.phpnjϴ'vendor/symfony/polyfill-php80/README.mdnj"tF;vendor/symfony/polyfill-php80/Resources/stubs/Attribute.phpnjMK<:vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.phpwnjw=7T8<vendor/symfony/polyfill-php80/Resources/stubs/Stringable.phpnjt]\ڤEvendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.phpGnjGֈ+<vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php>nj>g+vendor/symfony/polyfill-php80/bootstrap.phpnj.Ĥ+vendor/symfony/polyfill-php80/composer.jsonnjJm#vendor/symfony/process/CHANGELOG.mdnj%87vendor/symfony/process/Exception/ExceptionInterface.phpnj+=vendor/symfony/process/Exception/InvalidArgumentException.phpnj˅3vendor/symfony/process/Exception/LogicException.phpnjW;vendor/symfony/process/Exception/ProcessFailedException.phpnjY'=vendor/symfony/process/Exception/ProcessSignaledException.phpnj4=vendor/symfony/process/Exception/ProcessTimedOutException.phpnjj#a>vendor/symfony/process/Exception/RunProcessFailedException.phpnjU-.5vendor/symfony/process/Exception/RuntimeException.phpnj>H+vendor/symfony/process/ExecutableFinder.php nj [bk&vendor/symfony/process/InputStream.php nj HgKvendor/symfony/process/LICENSE,nj,U6vendor/symfony/process/Messenger/RunProcessContext.phptnjt䌻p6vendor/symfony/process/Messenger/RunProcessMessage.phpnjQ=vendor/symfony/process/Messenger/RunProcessMessageHandler.phpnj^|Ĥ.vendor/symfony/process/PhpExecutableFinder.php nj 6˼%vendor/symfony/process/PhpProcess.php nj (vendor/symfony/process/PhpSubprocess.phpnjgsg.vendor/symfony/process/Pipes/AbstractPipes.phpnj/vendor/symfony/process/Pipes/PipesInterface.phpnj\ *vendor/symfony/process/Pipes/UnixPipes.php5nj5WŤ-vendor/symfony/process/Pipes/WindowsPipes.phpnj_"vendor/symfony/process/Process.phpUnjU7'vendor/symfony/process/ProcessUtils.phpnj0 vendor/symfony/process/README.mdnj\3$Ϥ$vendor/symfony/process/composer.jsonnjϱe7vendor/symfony/service-contracts/Attribute/Required.phpnje;Z@vendor/symfony/service-contracts/Attribute/SubscribedService.phpnjXѓ-vendor/symfony/service-contracts/CHANGELOG.mdnjh{#<vendor/symfony/service-contracts/ContainerAwareInterface.phpnj?vendor/symfony/service-contracts/ContainerProviderInterface.phpnjؤ(vendor/symfony/service-contracts/LICENSE,nj,*vendor/symfony/service-contracts/README.mdJnjJГ3vendor/symfony/service-contracts/ResetInterface.php nj 񁒳?vendor/symfony/service-contracts/ServiceCollectionInterface.phprnjrK08vendor/symfony/service-contracts/ServiceLocatorTrait.phpnjv|Bvendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.phpMnjMjĤ=vendor/symfony/service-contracts/ServiceProviderInterface.phpfnjfΤ?vendor/symfony/service-contracts/ServiceSubscriberInterface.php nj Ŵ;vendor/symfony/service-contracts/ServiceSubscriberTrait.php nj r<vendor/symfony/service-contracts/Test/ServiceLocatorTest.php~nj~Âs@vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php nj p>.vendor/symfony/service-contracts/composer.jsonvnjv6ʤ(vendor/symfony/string/AbstractString.phpInjI, /vendor/symfony/string/AbstractUnicodeString.phphnjh&U$vendor/symfony/string/ByteString.php9nj9*Ҥ"vendor/symfony/string/CHANGELOG.mdznjzub)vendor/symfony/string/CodePointString.phpnjS46vendor/symfony/string/Exception/ExceptionInterface.phpQnjQ$դ<vendor/symfony/string/Exception/InvalidArgumentException.phpnje4vendor/symfony/string/Exception/RuntimeException.phppnjp0ʤ4vendor/symfony/string/Inflector/EnglishInflector.phpFnjFΤ3vendor/symfony/string/Inflector/FrenchInflector.phpKnjKn@6vendor/symfony/string/Inflector/InflectorInterface.phpCnjCQccvendor/symfony/string/LICENSE,nj,զ_Ϥ$vendor/symfony/string/LazyString.phponjo jݤvendor/symfony/string/README.md+nj+L<vendor/symfony/string/Resources/data/wcswidth_table_wide.php2nj2?Y<vendor/symfony/string/Resources/data/wcswidth_table_zero.php]<nj]<?p-vendor/symfony/string/Resources/functions.phpTnjT0.vendor/symfony/string/Slugger/AsciiSlugger.phpnjq>2vendor/symfony/string/Slugger/SluggerInterface.phpnj^'vendor/symfony/string/UnicodeString.php5nj50}Y#vendor/symfony/string/composer.json4nj4Y&W%vendor/theseer/tokenizer/CHANGELOG.md?nj?/\ vendor/theseer/tokenizer/LICENSEnjR ("vendor/theseer/tokenizer/README.mdnjR;&vendor/theseer/tokenizer/composer.json2nj2xR&vendor/theseer/tokenizer/composer.locknj*vendor/theseer/tokenizer/src/Exception.phpfnjf-vendor/theseer/tokenizer/src/NamespaceUri.phpSnjS6vendor/theseer/tokenizer/src/NamespaceUriException.phpqnjq)0U&vendor/theseer/tokenizer/src/Token.phpnjK>j0vendor/theseer/tokenizer/src/TokenCollection.phpnj˜9vendor/theseer/tokenizer/src/TokenCollectionException.phptnjtu*vendor/theseer/tokenizer/src/Tokenizer.phpFnjFJ .vendor/theseer/tokenizer/src/XMLSerializer.phpnjO7get(Application::class); $app->run();addArgument('path', InputArgument::OPTIONAL, 'Root path', getcwd()); $this->addOption('json', '', InputOption::VALUE_NONE, 'JSON output'); $this->addOption('recursive', '', InputOption::VALUE_NEGATABLE, 'Traverse directories recursive', true); $this->addOption('depth', '', InputOption::VALUE_OPTIONAL, 'Depth of recurse', 1); $this->addOption( 'max', '', InputOption::VALUE_REQUIRED, 'Maximum number of technologies that can be found for directory. Default = 0 (no limit)', 0 ); } public function execute(InputInterface $input, OutputInterface $output): int { $isJson = (bool)$input->getOption('json'); $logger = new ConsoleLogger($output); $result = []; $matchersLimit = (int)$input->getOption('max'); try { foreach ($this->getPath($input) as $path) { $result = [...$result, ...$this->wappspector->run($path, '/', $matchersLimit)]; } $result = $this->filterResults($result); if ($isJson) { $this->jsonOutput($output, $result); return Command::SUCCESS; } $this->tableOutput($output, $result); return Command::SUCCESS; } catch (Throwable $exception) { $logger->error($exception->getMessage()); return Command::FAILURE; } } /** * @throws JsonException */ private function jsonOutput(OutputInterface $output, array $result): void { $output->writeln(json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR)); } /** * @param MatchResultInterface[] $matchers * @return void */ private function tableOutput(OutputInterface $output, array $matchers): void { $rows = []; foreach ($matchers as $matchResult) { $rows[] = [ $matchResult->getId(), $matchResult->getName(), $matchResult->getPath(), $matchResult->getVersion() ?? '-', ]; } $table = new Table($output); $table ->setHeaders(['ID', 'Technology', 'Path', 'Version']) ->setRows($rows); $table->render(); } private function getPath(InputInterface $input): iterable { $path = $input->getArgument('path'); $path = realpath($path); if (!$input->getOption('recursive')) { yield $path; return; } $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS; $itFlags = RecursiveIteratorIterator::SELF_FIRST; $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, $flags), $itFlags); $it->setMaxDepth((int)$input->getOption('depth')); foreach ($it as $path => $item) { /** @var SplFileInfo $item */ if (str_contains($path, '/.')) { continue; } if (!$item->isDir()) { continue; } yield $path; } } /** * @param MatchResultInterface[] $result * @return MatchResultInterface[] */ private function filterResults(array $result): array { return array_values( array_filter($result, static function (MatchResultInterface $matcher) { static $uniq = []; $key = $matcher->getId() . ':' . $matcher->getPath(); if (array_key_exists($key, $uniq)) { return false; } $uniq[$key] = true; return true; }) ); } } fileExists($filePath) && str_contains($fs->read($filePath), $searchString); } } path = (new WhitespacePathNormalizer())->normalizePath($this->path); } catch (PathTraversalDetected) { $this->path = '/'; } } public function getId(): string { return static::ID; } public function getName(): string { return static::NAME; } public function getPath(): string { return $this->path; } public function getVersion(): ?string { return $this->version; } public function getApplication(): ?string { return $this->application; } public function jsonSerialize(): array { return [ 'id' => $this->getId(), 'name' => $this->getName(), 'path' => $this->getPath(), 'version' => $this->getVersion(), 'application' => $this->getApplication(), ]; } public static function createById( string $id, ?string $path = null, ?string $version = null, ?string $application = null ): MatchResultInterface { $classname = match ($id) { CakePHP::ID => CakePHP::class, CodeIgniter::ID => CodeIgniter::class, Composer::ID => Composer::class, DotNet::ID => DotNet::class, Drupal::ID => Drupal::class, Joomla::ID => Joomla::class, Laravel::ID => Laravel::class, EmDash::ID => EmDash::class, NodeJs::ID => NodeJs::class, Php::ID => Php::class, Prestashop::ID => Prestashop::class, Python::ID => Python::class, Ruby::ID => Ruby::class, Symfony::ID => Symfony::class, Typo3::ID => Typo3::class, Wordpress::ID => Wordpress::class, Yii::ID => Yii::class, Sitejet::ID => Sitejet::class, WebPresenceBuilder::ID => WebPresenceBuilder::class, Sitepro::ID => Sitepro::class, Duda::ID => Duda::class, Siteplus::ID => Siteplus::class, default => null, }; if (!$classname) { return new EmptyMatchResult(); } return new $classname(path: $path ?? '', version: $version, application: $application); } } fileExists($path . '/bin/cake')) { return new EmptyMatchResult(); } $version = $this->detectVersion($fs, $path); return new MatchResult($path, $version); } private function detectVersion(Filesystem $fs, string $path): ?string { $version = null; $versionFile = $path . '/vendor/cakephp/cakephp/VERSION.txt'; if ($fs->fileExists($versionFile)) { $versionData = explode("\n", trim($fs->read($versionFile))); $version = trim(array_pop($versionData)); } return $version; } } fileExists($path . '/spark')) { return new EmptyMatchResult(); } return new MatchResult($path, $this->detectVersion($fs, $path)); } /** * @throws FilesystemException */ private function detectVersion(Filesystem $fs, string $path): ?string { $versionFile = $path . '/vendor/codeigniter4/framework/system/CodeIgniter.php'; if (!$fs->fileExists($versionFile)) { return null; } preg_match("/CI_VERSION\\s*=\\s*'([^']+)'/", $fs->read($versionFile), $matches); if ($matches !== []) { return $matches[1]; } return null; } } getPath($path); if (!$fs->fileExists($composerJsonFile)) { return new EmptyMatchResult(); } $json = []; try { $json = json_decode($fs->read($composerJsonFile), true, 512, JSON_THROW_ON_ERROR); } catch (JsonException) { // ignore composer.json errors } return new MatchResult($path, $json['version'] ?? 'dev', $json['name'] ?? 'unknown'); } } listContents($path) as $item) { /** @var StorageAttributes $item */ if (!$item->isFile() || !str_ends_with($item->path(), '.dll')) { continue; } $handle = $fs->readStream($item->path()); $hex = bin2hex(fread($handle, 4)); if (str_contains($hex, self::HEX_SIGNATURE)) { return new MatchResult($path); } } return new EmptyMatchResult(); } } 'modules/system/system.info', 'regex' => "/version\\s*=\\s*\"(\\d\\.[^']+)\"[\\s\\S]*project\\s*=\\s*\"drupal\"/", ], [ 'file' => 'core/modules/system/system.info.yml', 'regex' => "/version:\\s*'(\\d+\\.[^']+)'[\\s\\S]*project:\\s*'drupal'/", ], ]; /** * @throws FilesystemException */ public function match(Filesystem $fs, string $path): MatchResultInterface { // Iterate through version patterns foreach (self::VERSIONS as $version) { $versionFile = rtrim($path, '/') . '/' . $version['file']; if (!$fs->fileExists($versionFile)) { continue; } $version = $this->detectVersion($version['regex'], $versionFile, $fs); return new MatchResult($path, $version); } return new EmptyMatchResult(); } private function detectVersion(string $regexPattern, string $versionFile, Filesystem $fs): ?string { preg_match($regexPattern, $fs->read($versionFile), $matches); return count($matches) ? $matches[1] : null; } } getCssFile($fs, $rTrimPath); $inspectorHelper = new InspectorHelper(); if ($cssFile !== null) { $cssFileContent = $fs->read($rTrimPath . $cssFile); if ( $inspectorHelper->fileContentContainsString($cssFileContent, 'dmDudaonePreviewBody') || $inspectorHelper->fileContentContainsString($cssFileContent, 'dudaSnipcartProductGalleryId') ) { return new MatchResult($path); } } if (!$fs->fileExists($rTrimPath . self::RUNTIME_JS_FILE)) { return new EmptyMatchResult(); } return $inspectorHelper->fileContainsString($fs, $rTrimPath . self::RUNTIME_JS_FILE, 'duda') ? new MatchResult($path) : new EmptyMatchResult(); } private function getCssFile(Filesystem $fs, string $path): ?string { foreach (self::CSS_FILES as $cssFile) { if ($fs->fileExists($path . $cssFile)) { return $cssFile; } } return null; } } fileExists($packageJsonPath)) { return new EmptyMatchResult(); } $json = json_decode($fs->read($packageJsonPath), true); return is_array($json) && (isset($json['emdash']) || isset($json['dependencies']['emdash'])) ? new MatchResult($path) : new EmptyMatchResult(); } } [ "/includes/version.php", "/libraries/joomla/version.php", "/libraries/cms/version/version.php", "/libraries/src/Version.php", ], "regex_release" => "/\\\$?RELEASE\s*=\s*'([\d.]+)';/", "regex_devlevel" => "/\\\$?DEV_LEVEL\s*=\s*'([^']+)';/", "regex_major" => "/\\\$?MAJOR_VERSION\s*=\s*([\d.]+);/", "regex_minor" => "/\\\$?MINOR_VERSION\s*=\s*([\d.]+);/", "regex_patch" => "/\\\$?PATCH_VERSION\s*=\s*([\d.]+);/", ]; /** * @throws FilesystemException */ private function isJoomla(Filesystem $fs, string $path): bool { $configFile = rtrim($path, '/') . '/' . self::CONFIG_FILE; if (!$fs->fileExists($configFile)) { return false; } $configContents = $fs->read($configFile); if ( stripos($configContents, 'JConfig') === false && stripos($configContents, 'mosConfig') === false ) { return false; } // False positive "Akeeba Backup Installer" if (stripos($configContents, 'class ABIConfiguration') !== false) { return false; } // False positive mock file in unit test folder if (stripos($configContents, 'Joomla.UnitTest') !== false) { return false; } // False positive mock file in unit test folder return stripos($configContents, "Joomla\Framework\Test") === false; } /** * @throws FilesystemException */ private function detectVersion(Filesystem $fs, string $path): ?string { // Iterate through version files foreach (self::VERSION['files'] as $file) { $versionFile = rtrim($path, '/') . '/' . $file; if (!$fs->fileExists($versionFile)) { continue; } $fileContents = $fs->read($versionFile); preg_match(self::VERSION['regex_major'], $fileContents, $major); preg_match(self::VERSION['regex_minor'], $fileContents, $minor); preg_match(self::VERSION['regex_patch'], $fileContents, $patch); if (count($major) && count($minor) && count($patch)) { return $major[1] . '.' . $minor[1] . '.' . $patch[1]; } if (count($major) && count($minor)) { return $major[1] . '.' . $minor[1] . 'x'; } if ($major !== []) { return $major[1] . '.x.x'; } // Legacy handling for all version < 3.8.0 preg_match(self::VERSION['regex_release'], $fileContents, $release); preg_match(self::VERSION['regex_devlevel'], $fileContents, $devlevel); if (count($release) && count($devlevel)) { return $release[1] . '.' . $devlevel[1]; } if ($release !== []) { return $release[1] . '.x'; } } return null; } /** * @throws FilesystemException */ public function match(Filesystem $fs, string $path): MatchResultInterface { if (!$this->isJoomla($fs, $path)) { return new EmptyMatchResult(); } return new MatchResult($path, $this->detectVersion($fs, $path)); } } fileExists($path . '/' . self::ARTISAN)) { return new EmptyMatchResult(); } return new MatchResult($path, $this->detectVersion($path, $fs)); } private function detectVersion(string $path, Filesystem $fs): ?string { $result = null; $versionFile = $path . '/' . self::VERSION_FILE; if ($fs->fileExists($versionFile)) { preg_match("/VERSION\\s*=\\s*'([^']+)'/", $fs->read($versionFile), $matches); if ($matches !== []) { $result = $matches[1]; } } else { $composerJsonFile = $path . '/' . self::COMPOSER_JSON; if ($fs->fileExists($composerJsonFile)) { try { $json = json_decode($fs->read($composerJsonFile), true, 512, JSON_THROW_ON_ERROR); if ($laravelPackage = $json['require']['laravel/framework'] ?? null) { $result = str_replace('^', '', $laravelPackage); } } catch (JsonException) { // ignore composer.json errors } } } return $result; } } fileExists($packageFile)) { return new EmptyMatchResult(); } $json = []; try { $json = json_decode($fs->read($packageFile), true, 512, JSON_THROW_ON_ERROR); } catch (JsonException) { // ignore package.json errors } return new MatchResult($path, null, $json['name'] ?? null); } } listContents($path); foreach ($list as $item) { /** @var StorageAttributes $item */ if ($item->isFile() && str_ends_with($item->path(), '.php')) { return new MatchResult($path); } if ($item->isDir() && $item->path() === ltrim(rtrim($path, '/') . '/src', '/')) { return $this->match($fs, rtrim($path, '/') . '/src'); } } } catch (FilesystemException) { // skip dir if it is inaccessible } return new EmptyMatchResult(); } } '/config/settings.inc.php', 'regexp' => '/define\\(\'_PS_VERSION_\', \'(.+)\'\\)/', ], ]; /** * @throws FilesystemException */ public function match(Filesystem $fs, string $path): MatchResultInterface { foreach (self::VERSIONS as $version) { $versionFile = rtrim($path, '/') . '/' . $version['filename']; if (!$fs->fileExists($versionFile)) { continue; } return new MatchResult($path, $this->getVersion($version, $fs, $versionFile)); } return new EmptyMatchResult(); } public function getVersion(array $version, Filesystem $fs, string $versionFile): ?string { $result = null; try { if (preg_match($version['regexp'], $fs->read($versionFile), $matches) && count($matches) > 1) { $result = $matches[1]; } } catch (FilesystemException) { // ignore filesystem extensions } return $result; } } listContents($path) as $item) { /** @var StorageAttributes $item */ if ($item->isFile() && str_ends_with($item->path(), '.py')) { return new MatchResult($path); } } return new EmptyMatchResult(); } } fileExists(rtrim($path, '/') . '/' . self::RAKEFILE)) { return new EmptyMatchResult(); } return new MatchResult($path); } } fileExists($indexHtmlPath)) { return new EmptyMatchResult(); } $fileContent = $fs->read($indexHtmlPath); $inspectorHelper = new InspectorHelper(); return $inspectorHelper->fileContentContainsString($fileContent, 'ed-element') && $inspectorHelper->fileContentContainsString($fileContent, 'webcard.apiHost=') ? new MatchResult($path) : new EmptyMatchResult(); } } fileContainsString($fs, $rTrimPath . '/index.html', 'edit.site')) { return new EmptyMatchResult(); } if (!$fs->directoryExists($rTrimPath . self::PUBLISH_DIR_PATH)) { return new EmptyMatchResult(); } $publishDirList = $fs->listContents($rTrimPath . self::PUBLISH_DIR_PATH, false); // do not check if the item is a directory as on the server when the files a copied the type of the // directory is determined as 'file'. // By default, there should be just 1 directory in the publish directory $versionDirPath = $publishDirList->toArray()[0]['path'] ?? null; if ($versionDirPath === null) { return new EmptyMatchResult(); } return $inspectorHelper->fileContainsString($fs, $versionDirPath . '/bundle.js', 'siteplus') ? new MatchResult($rTrimPath, $this->getSiteplusVersion($versionDirPath)) : new EmptyMatchResult(); } private function getSiteplusVersion(string $versionDirPath): string { // get the last part of the path $versionDirPathParts = explode('/', $versionDirPath); return end($versionDirPathParts); } } directoryExists($siteproFolderPath)) { return new EmptyMatchResult(); } $inspectorHelper = new InspectorHelper(); return $inspectorHelper->fileContainsString($fs, $rTrimPath . '/web.config', 'sitepro') || $inspectorHelper->fileContainsString($fs, $rTrimPath . '/.htaccess', 'sitepro') ? new MatchResult($path) : new EmptyMatchResult(); } } fileExists($symfonyLockFile)) { return new EmptyMatchResult(); } $json = []; try { $json = json_decode($fs->read($symfonyLockFile), true, 512, JSON_THROW_ON_ERROR); } catch (JsonException) { // ignore symfony.lock errors } return new MatchResult($path, $json["symfony/framework-bundle"]["version"] ?? null); } } 'typo3/sysext/core/Classes/Information/Typo3Version.php', 'regexp' => '/VERSION = \'(.*?)\'/', ], [ 'filename' => 'typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php', 'regexp' => '/define\\(\'TYPO3_version\', \'(.*?)\'\\)/', ], [ 'filename' => 't3lib/config_default.php', 'regexp' => '/TYPO_VERSION = \'(.*?)\'/', ], ]; public function match(Filesystem $fs, string $path): MatchResultInterface { foreach (self::VERSIONS as $version) { $versionFile = rtrim($path, '/') . '/' . $version['filename']; if (!$fs->fileExists($versionFile)) { continue; } if ($version = $this->detectVersion($version['regexp'], $versionFile, $fs)) { return new MatchResult($path, $version); } } return new EmptyMatchResult(); } public function detectVersion(string $regexPattern, string $versionFile, Filesystem $fs): ?string { try { preg_match($regexPattern, $fs->read($versionFile), $matches); return count($matches) > 1 ? $matches[1] : null; } catch (FilesystemException) { // ignore file reading problem return null; } } } safeScanDir($fs, $path); if ($matcher instanceof EmptyMatchResult) { $matcher = $this->safeScanDir($fs, rtrim($path) . '/../'); } return $matcher; } private function safeScanDir(Filesystem $fs, string $path): MatchResultInterface { try { $result = $this->doMatch($fs, $path); } catch (FilesystemException) { // skip dir if it is inaccessible $result = new EmptyMatchResult(); } return $result; } } fileExists($indexHtmlPath)) { return new EmptyMatchResult(); } $fileContent = $fs->read($indexHtmlPath); $inspectorHelper = new InspectorHelper(); return $inspectorHelper->fileContentMatchesString( $fileContent, '//' ) || $this->fileContainsDOMStructure($fileContent) ? new MatchResult($path) : new EmptyMatchResult(); } private function fileContainsDOMStructure(string $fileContent): bool { $dom = new DOMDocument(); try { libxml_use_internal_errors(true); $domIsLoaded = $dom->loadHTML($fileContent); libxml_clear_errors(); } catch (Throwable) { return false; } if ($domIsLoaded === false) { return false; } $xpath = new DOMXPath($dom); // Find the
with id="page" $pageDiv = $xpath->query("//div[@id='page']"); if ($pageDiv->length === 0) { return false; } $pageNode = $pageDiv->item(0); // Check for direct children with the required IDs $watermarkDiv = $xpath->query("./div[@id='watermark']", $pageNode); $layoutDiv = $xpath->query("./div[@id='layout']", $pageNode); return $watermarkDiv->length > 0 && $layoutDiv->length > 0; } } read($versionFile), $matches); if ($matches !== []) { return $matches[1]; } return null; } /** * @throws FilesystemException */ private function isWordpress(Filesystem $fs, string $path): bool { $versionFile = rtrim($path, '/') . '/' . self::VERSION_FILE; if (!$fs->fileExists($versionFile)) { return false; } $fileContents = $fs->read($versionFile); return stripos($fileContents, '$wp_version =') !== false; } /** * @throws FilesystemException */ public function match(Filesystem $fs, string $path): MatchResultInterface { if (!$this->isWordpress($fs, $path)) { return new EmptyMatchResult(); } return new MatchResult($path, $this->detectVersion($fs, $path)); } } 'yii', 'versionFile' => '/vendor/yiisoft/yii2/BaseYii.php', 'versionRegexp' => '/public static function getVersion\(\)\s*\{\s*return \'([^\']+)\';\s*}/', ], [ 'file' => 'framework/yiic', 'versionFile' => '/framework/YiiBase.php', 'versionRegexp' => '/public static function getVersion\(\)\s*\{\s*return \'([^\']+)\';\s*}/', ], ]; public function match(Filesystem $fs, string $path): MatchResultInterface { $path = rtrim($path, '/'); foreach (self::VERSIONS as $version) { if (!$fs->fileExists($path . '/' . $version['file'])) { continue; } return new MatchResult($path, $this->detectVersion($fs, $path, $version)); } return new EmptyMatchResult(); } private function detectVersion(Filesystem $fs, string $path, array $versionInfo): ?string { $version = null; $yii2VersionFile = $path . $versionInfo['versionFile']; if ($fs->fileExists($yii2VersionFile)) { preg_match($versionInfo['versionRegexp'], $fs->read($yii2VersionFile), $matches); if (isset($matches[1])) { $version = $matches[1]; } } return $version; } } addDefinitions(__DIR__ . '/container.php'); return $containerBuilder->build(); } } fsFactory)($basePath); $result = []; /** @var MatcherInterface $matcher */ foreach ($this->matchers as $matcher) { if (($match = $matcher->match($fs, $path)) instanceof EmptyMatchResult) { continue; } $result[] = $match; if ($matchersLimit > 0 && count($result) >= $matchersLimit) { break; } } return $result; } } [ Matchers\Wordpress::class, Matchers\Joomla::class, Matchers\Drupal::class, Matchers\Prestashop::class, Matchers\Typo3::class, Matchers\Laravel::class, Matchers\Symfony::class, Matchers\CodeIgniter::class, Matchers\CakePHP::class, Matchers\Yii::class, Matchers\DotNet::class, Matchers\Ruby::class, Matchers\Python::class, Matchers\EmDash::class, Matchers\NodeJs::class, Matchers\Sitejet::class, Matchers\WebPresenceBuilder::class, Matchers\Sitepro::class, Matchers\Duda::class, Matchers\Siteplus::class, // Low priority wrappers. Should go last. Matchers\Composer::class, Matchers\Php::class, ], Wappspector::class => static function (Container $container): Wappspector { $matchers = []; foreach ($container->get('matchers') as $matcher) { $matchers[] = $container->get($matcher); } return new Wappspector($container->get(FileSystemFactory::class), $matchers); }, Inspect::class => static function (ContainerInterface $container): Inspect { return new Inspect($container->get(Wappspector::class)); }, Application::class => static function (ContainerInterface $container): Application { $application = new Application('Wappspector'); $inspectCommand = $container->get(Inspect::class); $application->add($inspectCommand); $application->setDefaultCommand($inspectCommand->getName(), true); return $application; }, ]; Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. # wappspector Command-line interface utility to analyze the file structure of a web hosting server and identify the frameworks and CMS used in the websites hosted on it. [![unit-test](https://github.com/plesk/wappspector/actions/workflows/unit-test.yml/badge.svg)](https://github.com/plesk/wappspector/actions/workflows/unit-test.yml) ## Matchers ### Technology & Frameworks | Technology | Version | Check type | |-------------|------------|----------------------------------| | PHP | - | Any `*.php` file | | Ruby | 2, 3 | `Rakefile` in root dir | | Python | 2, 3 | Any `*.py` file | | Laravel | 8, 9, 10 | `artisan` file in root dir | | Symfony | 3, 4, 5, 6 | `symfony.lock` file in root dir | | CodeIgniter | 4 | `spark` file in root dir | | CakePHP | 3, 4 | `bin/cake` file | | Yii | 2 | `yii` file in root dir | | Composer | - | `composer.json` file in root dir | | .NET | - | Any `*.dll` file | | Node.js | - | `package.json` file in root dir | ### CMS | Name | Major version | Check type | |------------|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | WordPress | 2 - 6 | Existence and contents of `wp-includes/version.php` | | Joomla! | 1 - 6 | Existence and contents of `configuration.php` in root dir and version files in `libraries/src/Version.php` or `libraries/cms/version/version.php` or similar | | Drupal | 6 - 10 | Existence and contents of `/modules/system/system.info` or `/core/modules/system/system.info.yml` | | PrestaShop | 1.6, 1.7.8, 8.0 | Existence and contents of `/config/settings.inc.php` | | TYPO3 | 7.6, 8.7, 9, 10, 11, 12 | Existence and contents of `/typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php` or `/typo3/sysext/core/Classes/Information/Typo3Version.php` or `/t3lib/config_default.php` | | EmDash | 0.0.3 - 0.4.0 | Existence and contents of `package.json` | ### Site builders | Name | Check type | |--------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Sitejet | The `index.html` file exists and contains the `ed-element` and `webcard.apiHost=` strings | | WebPresenceBuilder | The `index.html` file contains the `` tag or contains the following DOM structure: the `div` tag with the `page` ID contains the `div` tags with the `watermark` and `layout` IDs | | Site.pro | The `sitepro` folder exists and the `sitepro` string is contained in the `web.config` or `.htaccess` files | | Duda.co | The `Style` folder contains the `desktop.css`, `mobile.css`, or `tablet.css` files. The style file contains the `dmDudaonePreviewBody` or `dudaSnipcartProductGalleryId` strings, or the `Scripts/runtime.js` file contains the `duda` string | | Siteplus | The `index.html` file exists and contains the `edit.site` string, and the `/bundle/publish/` directory exists and contains the `bundle.js` file. The `bundle.js` file contains the `siteplus` string | ## How to build phar ```shell composer global require clue/phar-composer composer install php -d phar.readonly=off ~/.composer/vendor/bin/phar-composer build . ``` Run the created `wappspector.phar`: ```shell ./wappspector.phar ./test-data ``` ## Changing matchers order To change the matchers order or to disable some of them, you should override `matchers` entry of DI container. ```php $diContainer = \Plesk\Wappspector\DIContainer::build(); $matchers = $diContainer->get('matchers'); array_unshift($matchers, \Some\New\Matcher::class); $diContainer->set('matchers', $matchers); ``` or ```php // only detect WordPress installs $diContainer = \Plesk\Wappspector\DIContainer::build(); $diContainer->set('matchers', [\Plesk\Wappspector\Matchers\Wordpress::class]); ``` ## Testing ```shell ./vendor/bin/phpunit ``` * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ setupEnvironment(); process(is_array($argv) ? $argv : array()); /** * Initializes various values * * @throws RuntimeException If uopz extension prevents exit calls */ function setupEnvironment() { ini_set('display_errors', 1); if (extension_loaded('uopz') && !(ini_get('uopz.disable') || ini_get('uopz.exit'))) { // uopz works at opcode level and disables exit calls if (function_exists('uopz_allow_exit')) { @uopz_allow_exit(true); } else { throw new RuntimeException('The uopz extension ignores exit calls and breaks this installer.'); } } $installer = 'ComposerInstaller'; if (defined('PHP_WINDOWS_VERSION_MAJOR')) { if ($version = getenv('COMPOSERSETUP')) { $installer = sprintf('Composer-Setup.exe/%s', $version); } } define('COMPOSER_INSTALLER', $installer); } /** * Processes the installer */ function process($argv) { // Determine ANSI output from --ansi and --no-ansi flags setUseAnsi($argv); $help = in_array('--help', $argv) || in_array('-h', $argv); if ($help) { displayHelp(); exit(0); } $check = in_array('--check', $argv); $force = in_array('--force', $argv); $quiet = in_array('--quiet', $argv); $channel = 'stable'; if (in_array('--snapshot', $argv)) { $channel = 'snapshot'; } elseif (in_array('--preview', $argv)) { $channel = 'preview'; } elseif (in_array('--1', $argv)) { $channel = '1'; } elseif (in_array('--2', $argv)) { $channel = '2'; } elseif (in_array('--2.2', $argv)) { $channel = '2.2'; } $disableTls = in_array('--disable-tls', $argv); $installDir = getOptValue('--install-dir', $argv, false); $version = getOptValue('--version', $argv, false); $filename = getOptValue('--filename', $argv, 'composer.phar'); $cafile = getOptValue('--cafile', $argv, false); if (!checkParams($installDir, $version, $cafile)) { exit(1); } $ok = checkPlatform($warnings, $quiet, $disableTls, true); if ($check) { // Only show warnings if we haven't output any errors if ($ok) { showWarnings($warnings); showSecurityWarning($disableTls); } exit($ok ? 0 : 1); } if ($ok || $force) { if ($channel === '1' && !$quiet) { out('Warning: You forced the install of Composer 1.x via --1, but Composer 2.x is the latest stable version. Updating to it via composer self-update --stable is recommended.', 'error'); } $installer = new Installer($quiet, $disableTls, $cafile); if ($installer->run($version, $installDir, $filename, $channel)) { showWarnings($warnings); showSecurityWarning($disableTls); exit(0); } } exit(1); } /** * Displays the help */ function displayHelp() { echo << $value) { $next = $key + 1; if (0 === strpos($value, $opt)) { if ($optLength === strlen($value) && isset($argv[$next])) { return trim($argv[$next]); } else { return trim(substr($value, $optLength + 1)); } } } return $default; } /** * Checks that user-supplied params are valid * * @param mixed $installDir The required istallation directory * @param mixed $version The required composer version to install * @param mixed $cafile Certificate Authority file * * @return bool True if the supplied params are okay */ function checkParams($installDir, $version, $cafile) { $result = true; if (false !== $installDir && !is_dir($installDir)) { out("The defined install dir ({$installDir}) does not exist.", 'info'); $result = false; } if (false !== $version && 1 !== preg_match('/^\d+\.\d+\.\d+(\-(alpha|beta|RC)\d*)*$/', $version)) { out("The defined install version ({$version}) does not match release pattern.", 'info'); $result = false; } if (false !== $cafile && (!file_exists($cafile) || !is_readable($cafile))) { out("The defined Certificate Authority (CA) cert file ({$cafile}) does not exist or is not readable.", 'info'); $result = false; } return $result; } /** * Checks the platform for possible issues running Composer * * Errors are written to the output, warnings are saved for later display. * * @param array $warnings Populated by method, to be shown later * @param bool $quiet Quiet mode * @param bool $disableTls Bypass tls * @param bool $install If we are installing, rather than diagnosing * * @return bool True if there are no errors */ function checkPlatform(&$warnings, $quiet, $disableTls, $install) { getPlatformIssues($errors, $warnings, $install); // Make openssl warning an error if tls has not been specifically disabled if (isset($warnings['openssl']) && !$disableTls) { $errors['openssl'] = $warnings['openssl']; unset($warnings['openssl']); } if (!empty($errors)) { // Composer-Setup.exe uses "Some settings" to flag platform errors out('Some settings on your machine make Composer unable to work properly.', 'error'); out('Make sure that you fix the issues listed below and run this script again:', 'error'); outputIssues($errors); return false; } if (empty($warnings) && !$quiet) { out('All settings correct for using Composer', 'success'); } return true; } /** * Checks platform configuration for common incompatibility issues * * @param array $errors Populated by method * @param array $warnings Populated by method * @param bool $install If we are installing, rather than diagnosing * * @return bool If any errors or warnings have been found */ function getPlatformIssues(&$errors, &$warnings, $install) { $errors = array(); $warnings = array(); if ($iniPath = php_ini_loaded_file()) { $iniMessage = PHP_EOL.'The php.ini used by your command-line PHP is: ' . $iniPath; } else { $iniMessage = PHP_EOL.'A php.ini file does not exist. You will have to create one.'; } $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 (ini_get('detect_unicode')) { $errors['unicode'] = array( 'The detect_unicode setting must be disabled.', 'Add the following to the end of your `php.ini`:', ' detect_unicode = Off', $iniMessage ); } if (extension_loaded('suhosin')) { $suhosin = ini_get('suhosin.executor.include.whitelist'); $suhosinBlacklist = ini_get('suhosin.executor.include.blacklist'); if (false === stripos($suhosin, 'phar') && (!$suhosinBlacklist || false !== stripos($suhosinBlacklist, 'phar'))) { $errors['suhosin'] = array( 'The suhosin.executor.include.whitelist setting is incorrect.', 'Add the following to the end of your `php.ini` or suhosin.ini (Example path [for Debian]: /etc/php5/cli/conf.d/suhosin.ini):', ' suhosin.executor.include.whitelist = phar '.$suhosin, $iniMessage ); } } if (!function_exists('json_decode')) { $errors['json'] = array( 'The json extension is missing.', 'Install it or recompile php without --disable-json' ); } if (!extension_loaded('Phar')) { $errors['phar'] = array( 'The phar extension is missing.', 'Install it or recompile php without --disable-phar' ); } if (!extension_loaded('filter')) { $errors['filter'] = array( 'The filter extension is missing.', 'Install it or recompile php without --disable-filter' ); } if (!extension_loaded('hash')) { $errors['hash'] = array( 'The hash extension is missing.', 'Install it or recompile php without --disable-hash' ); } if (!extension_loaded('iconv') && !extension_loaded('mbstring')) { $errors['iconv_mbstring'] = array( 'The iconv OR mbstring extension is required and both are missing.', 'Install either of them or recompile php without --disable-iconv' ); } if (!ini_get('allow_url_fopen')) { $errors['allow_url_fopen'] = array( 'The allow_url_fopen setting is incorrect.', 'Add the following to the end of your `php.ini`:', ' allow_url_fopen = On', $iniMessage ); } if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) { $ioncube = ioncube_loader_version(); $errors['ioncube'] = array( 'Your ionCube Loader extension ('.$ioncube.') is incompatible with Phar files.', 'Upgrade to ionCube 4.0.9 or higher or remove this line (path may be different) from your `php.ini` to disable it:', ' zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so', $iniMessage ); } if (version_compare(PHP_VERSION, '5.3.2', '<')) { $errors['php'] = array( 'Your PHP ('.PHP_VERSION.') is too old, you must upgrade to PHP 5.3.2 or higher.' ); } if (version_compare(PHP_VERSION, '5.3.4', '<')) { $warnings['php'] = array( 'Your PHP ('.PHP_VERSION.') is quite old, upgrading to PHP 5.3.4 or higher is recommended.', 'Composer works with 5.3.2+ for most people, but there might be edge case issues.' ); } if (!extension_loaded('openssl')) { $warnings['openssl'] = array( 'The openssl extension is missing, which means that secure HTTPS transfers are impossible.', 'If possible you should enable it or recompile php with --with-openssl' ); } if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) { // Attempt to parse version number out, fallback to whole string value. $opensslVersion = trim(strstr(OPENSSL_VERSION_TEXT, ' ')); $opensslVersion = substr($opensslVersion, 0, strpos($opensslVersion, ' ')); $opensslVersion = $opensslVersion ? $opensslVersion : OPENSSL_VERSION_TEXT; $warnings['openssl_version'] = array( 'The OpenSSL library ('.$opensslVersion.') used by PHP does not support TLSv1.2 or TLSv1.1.', 'If possible you should upgrade OpenSSL to version 1.0.1 or above.' ); } if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) { $warnings['apc_cli'] = array( 'The apc.enable_cli setting is incorrect.', 'Add the following to the end of your `php.ini`:', ' apc.enable_cli = Off', $iniMessage ); } if (!$install && extension_loaded('xdebug')) { $warnings['xdebug_loaded'] = array( 'The xdebug extension is loaded, this can slow down Composer a little.', 'Disabling it when using Composer is recommended.' ); if (ini_get('xdebug.profiler_enabled')) { $warnings['xdebug_profile'] = array( 'The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.', 'Add the following to the end of your `php.ini` to disable it:', ' xdebug.profiler_enabled = 0', $iniMessage ); } } if (!extension_loaded('zlib')) { $warnings['zlib'] = array( 'The zlib extension is not loaded, this can slow down Composer a lot.', 'If possible, install it or recompile php with --with-zlib', $iniMessage ); } 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'] = array( 'The Windows OneDrive folder is not supported on PHP versions below 7.2.23 and 7.3.10.', 'Upgrade your PHP ('.PHP_VERSION.') to use this location with Composer.' ); } if (extension_loaded('uopz') && !(ini_get('uopz.disable') || ini_get('uopz.exit'))) { $warnings['uopz'] = array( 'The uopz extension ignores exit calls and may not work with all Composer commands.', 'Disabling it when using Composer is recommended.' ); } ob_start(); phpinfo(INFO_GENERAL); $phpinfo = ob_get_clean(); if (preg_match('{Configure Command(?: *| *=> *)(.*?)(?:|$)}m', $phpinfo, $match)) { $configure = $match[1]; if (false !== strpos($configure, '--enable-sigchild')) { $warnings['sigchild'] = array( 'PHP was compiled with --enable-sigchild which can cause issues on some platforms.', 'Recompile it without this flag if possible, see also:', ' https://bugs.php.net/bug.php?id=22999' ); } if (false !== strpos($configure, '--with-curlwrappers')) { $warnings['curlwrappers'] = array( 'PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.', 'Recompile it without this flag if possible' ); } } // Stringify the message arrays foreach ($errors as $key => $value) { $errors[$key] = PHP_EOL.implode(PHP_EOL, $value); } foreach ($warnings as $key => $value) { $warnings[$key] = PHP_EOL.implode(PHP_EOL, $value); } return !empty($errors) || !empty($warnings); } /** * Outputs an array of issues * * @param array $issues */ function outputIssues($issues) { foreach ($issues as $issue) { out($issue, 'info'); } out(''); } /** * Outputs any warnings found * * @param array $warnings */ function showWarnings($warnings) { if (!empty($warnings)) { out('Some settings on your machine may cause stability issues with Composer.', 'error'); out('If you encounter issues, try to change the following:', 'error'); outputIssues($warnings); } } /** * Outputs an end of process warning if tls has been bypassed * * @param bool $disableTls Bypass tls */ function showSecurityWarning($disableTls) { if ($disableTls) { out('You have instructed the Installer not to enforce SSL/TLS security on remote HTTPS requests.', 'info'); out('This will leave all downloads during installation vulnerable to Man-In-The-Middle (MITM) attacks', 'info'); } } /** * colorize output */ function out($text, $color = null, $newLine = true) { $styles = array( 'success' => "\033[0;32m%s\033[0m", 'error' => "\033[31;31m%s\033[0m", 'info' => "\033[33;33m%s\033[0m" ); $format = '%s'; if (isset($styles[$color]) && USE_ANSI) { $format = $styles[$color]; } if ($newLine) { $format .= PHP_EOL; } printf($format, $text); } /** * Returns the system-dependent Composer home location, which may not exist * * @return string */ function getHomeDir() { $home = getenv('COMPOSER_HOME'); if ($home) { return $home; } $userDir = getUserDir(); if (defined('PHP_WINDOWS_VERSION_MAJOR')) { return $userDir.'/Composer'; } $dirs = array(); if (useXdg()) { // XDG Base Directory Specifications $xdgConfig = 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 (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]; } /** * Returns the location of the user directory from the environment * @throws RuntimeException If the environment value does not exists * * @return string */ function getUserDir() { $userEnv = defined('PHP_WINDOWS_VERSION_MAJOR') ? 'APPDATA' : 'HOME'; $userDir = getenv($userEnv); if (!$userDir) { throw new RuntimeException('The '.$userEnv.' or COMPOSER_HOME environment variable must be set for composer to run correctly'); } return rtrim(strtr($userDir, '\\', '/'), '/'); } /** * @return bool */ function useXdg() { foreach (array_keys($_SERVER) as $key) { if (strpos($key, 'XDG_') === 0) { return true; } } if (is_dir('/etc/xdg')) { return true; } return false; } function validateCaFile($contents) { // assume the CA is valid if php is vulnerable to // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html if ( PHP_VERSION_ID <= 50327 || (PHP_VERSION_ID >= 50400 && PHP_VERSION_ID < 50422) || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50506) ) { return !empty($contents); } return (bool) openssl_x509_parse($contents); } class Installer { private $quiet; private $disableTls; private $cafile; private $displayPath; private $target; private $tmpFile; private $tmpCafile; private $baseUrl; private $algo; private $errHandler; private $httpClient; private $pubKeys = array(); private $installs = array(); /** * Constructor - must not do anything that throws an exception * * @param bool $quiet Quiet mode * @param bool $disableTls Bypass tls * @param mixed $cafile Path to CA bundle, or false */ public function __construct($quiet, $disableTls, $caFile) { if (($this->quiet = $quiet)) { ob_start(); } $this->disableTls = $disableTls; $this->cafile = $caFile; $this->errHandler = new ErrorHandler(); } /** * Runs the installer * * @param mixed $version Specific version to install, or false * @param mixed $installDir Specific installation directory, or false * @param string $filename Specific filename to save to, or composer.phar * @param string $channel Specific version channel to use * @throws Exception If anything other than a RuntimeException is caught * * @return bool If the installation succeeded */ public function run($version, $installDir, $filename, $channel) { try { $this->initTargets($installDir, $filename); $this->initTls(); $this->httpClient = new HttpClient($this->disableTls, $this->cafile); $result = $this->install($version, $channel); // in case --1 or --2 is passed, we leave the default channel for next self-update to stable if (1 === preg_match('{^\d+$}D', $channel)) { $channel = 'stable'; } if ($result && $channel !== 'stable' && !$version && defined('PHP_BINARY')) { $null = (defined('PHP_WINDOWS_VERSION_MAJOR') ? 'NUL' : '/dev/null'); @exec(escapeshellarg(PHP_BINARY) .' '.escapeshellarg($this->target).' self-update --'.$channel.' --set-channel-only -q > '.$null.' 2> '.$null, $output); } } catch (Exception $e) { $result = false; } // Always clean up $this->cleanUp($result); if (isset($e)) { // Rethrow anything that is not a RuntimeException if (!$e instanceof RuntimeException) { throw $e; } out($e->getMessage(), 'error'); } return $result; } /** * Initialization methods to set the required filenames and composer url * * @param mixed $installDir Specific installation directory, or false * @param string $filename Specific filename to save to, or composer.phar * @throws RuntimeException If the installation directory is not writable */ protected function initTargets($installDir, $filename) { $this->displayPath = ($installDir ? rtrim($installDir, '/').'/' : '').$filename; $installDir = $installDir ? realpath($installDir) : getcwd(); if (!is_writeable($installDir)) { throw new RuntimeException('The installation directory "'.$installDir.'" is not writable'); } $this->target = $installDir.DIRECTORY_SEPARATOR.$filename; $this->tmpFile = $installDir.DIRECTORY_SEPARATOR.basename($this->target, '.phar').'-temp.phar'; $uriScheme = $this->disableTls ? 'http' : 'https'; $this->baseUrl = $uriScheme.'://getcomposer.org'; } /** * A wrapper around methods to check tls and write public keys * @throws RuntimeException If SHA384 is not supported */ protected function initTls() { if ($this->disableTls) { return; } if (!in_array('sha384', array_map('strtolower', openssl_get_md_methods()))) { throw new RuntimeException('SHA384 is not supported by your openssl extension'); } $this->algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384'; $home = $this->getComposerHome(); $this->pubKeys = array( 'dev' => $this->installKey(self::getPKDev(), $home, 'keys.dev.pub'), 'tags' => $this->installKey(self::getPKTags(), $home, 'keys.tags.pub') ); if (empty($this->cafile) && !HttpClient::getSystemCaRootBundlePath()) { $this->cafile = $this->tmpCafile = $this->installKey(HttpClient::getPackagedCaFile(), $home, 'cacert-temp.pem'); } } /** * Returns the Composer home directory, creating it if required * @throws RuntimeException If the directory cannot be created * * @return string */ protected function getComposerHome() { $home = getHomeDir(); if (!is_dir($home)) { $this->errHandler->start(); if (!mkdir($home, 0777, true)) { throw new RuntimeException(sprintf( 'Unable to create Composer home directory "%s": %s', $home, $this->errHandler->message )); } $this->installs[] = $home; $this->errHandler->stop(); } return $home; } /** * Writes public key data to disc * * @param string $data The public key(s) in pem format * @param string $path The directory to write to * @param string $filename The name of the file * @throws RuntimeException If the file cannot be written * * @return string The path to the saved data */ protected function installKey($data, $path, $filename) { $this->errHandler->start(); $target = $path.DIRECTORY_SEPARATOR.$filename; $installed = file_exists($target); $write = file_put_contents($target, $data, LOCK_EX); @chmod($target, 0644); $this->errHandler->stop(); if (!$write) { throw new RuntimeException(sprintf('Unable to write %s to: %s', $filename, $path)); } if (!$installed) { $this->installs[] = $target; } return $target; } /** * The main install function * * @param mixed $version Specific version to install, or false * @param string $channel Version channel to use * * @return bool If the installation succeeded */ protected function install($version, $channel) { $retries = 3; $result = false; $infoMsg = 'Downloading...'; $infoType = 'info'; while ($retries--) { if (!$this->quiet) { out($infoMsg, $infoType); $infoMsg = 'Retrying...'; $infoType = 'error'; } if (!$this->getVersion($channel, $version, $url, $error)) { out($error, 'error'); continue; } if (!$this->downloadToTmp($url, $signature, $error)) { out($error, 'error'); continue; } if (!$this->verifyAndSave($version, $signature, $error)) { out($error, 'error'); continue; } $result = true; break; } if (!$this->quiet) { if ($result) { out(PHP_EOL."Composer (version {$version}) successfully installed to: {$this->target}", 'success'); out("Use it: php {$this->displayPath}", 'info'); out(''); } else { out('The download failed repeatedly, aborting.', 'error'); } } return $result; } /** * Sets the version url, downloading version data if required * * @param string $channel Version channel to use * @param false|string $version Version to install, or set by method * @param null|string $url The versioned url, set by method * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function getVersion($channel, &$version, &$url, &$error) { $error = ''; if ($version) { if (empty($url)) { $url = $this->baseUrl."/download/{$version}/composer.phar"; } return true; } $this->errHandler->start(); if ($this->downloadVersionData($data, $error)) { $this->parseVersionData($data, $channel, $version, $url); } $this->errHandler->stop(); return empty($error); } /** * Downloads and json-decodes version data * * @param null|array $data Downloaded version data, set by method * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function downloadVersionData(&$data, &$error) { $url = $this->baseUrl.'/versions'; $errFmt = 'The "%s" file could not be %s: %s'; if (!$json = $this->httpClient->get($url)) { $error = sprintf($errFmt, $url, 'downloaded', $this->errHandler->message); return false; } if (!$data = json_decode($json, true)) { $error = sprintf($errFmt, $url, 'json-decoded', $this->getJsonError()); return false; } return true; } /** * A wrapper around the methods needed to download and save the phar * * @param string $url The versioned download url * @param null|string $signature Set by method on successful download * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function downloadToTmp($url, &$signature, &$error) { $error = ''; $errFmt = 'The "%s" file could not be downloaded: %s'; $sigUrl = $url.'.sig'; $this->errHandler->start(); if (!$fh = fopen($this->tmpFile, 'w')) { $error = sprintf('Could not create file "%s": %s', $this->tmpFile, $this->errHandler->message); } elseif (!$this->getSignature($sigUrl, $signature)) { $error = sprintf($errFmt, $sigUrl, $this->errHandler->message); } elseif (!fwrite($fh, $this->httpClient->get($url))) { $error = sprintf($errFmt, $url, $this->errHandler->message); } if (is_resource($fh)) { fclose($fh); } $this->errHandler->stop(); return empty($error); } /** * Verifies the downloaded file and saves it to the target location * * @param string $version The composer version downloaded * @param string $signature The digital signature to check * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function verifyAndSave($version, $signature, &$error) { $error = ''; if (!$this->validatePhar($this->tmpFile, $pharError)) { $error = 'The download is corrupt: '.$pharError; } elseif (!$this->verifySignature($version, $signature, $this->tmpFile)) { $error = 'Signature mismatch, could not verify the phar file integrity'; } else { $this->errHandler->start(); if (!rename($this->tmpFile, $this->target)) { $error = sprintf('Could not write to file "%s": %s', $this->target, $this->errHandler->message); } chmod($this->target, 0755); $this->errHandler->stop(); } return empty($error); } /** * Parses an array of version data to match the required channel * * @param array $data Downloaded version data * @param mixed $channel Version channel to use * @param false|string $version Set by method * @param mixed $url The versioned url, set by method */ protected function parseVersionData(array $data, $channel, &$version, &$url) { foreach ($data[$channel] as $candidate) { if ($candidate['min-php'] <= PHP_VERSION_ID) { $version = $candidate['version']; $url = $this->baseUrl.$candidate['path']; break; } } if (!$version) { $error = sprintf( 'None of the %d %s version(s) of Composer matches your PHP version (%s / ID: %d)', count($data[$channel]), $channel, PHP_VERSION, PHP_VERSION_ID ); throw new RuntimeException($error); } } /** * Downloads the digital signature of required phar file * * @param string $url The signature url * @param null|string $signature Set by method on success * * @return bool If the download succeeded */ protected function getSignature($url, &$signature) { if (!$result = $this->disableTls) { $signature = $this->httpClient->get($url); if ($signature) { $signature = json_decode($signature, true); $signature = base64_decode($signature['sha384']); $result = true; } } return $result; } /** * Verifies the signature of the downloaded phar * * @param string $version The composer versione * @param string $signature The downloaded digital signature * @param string $file The temp phar file * * @return bool If the operation succeeded */ protected function verifySignature($version, $signature, $file) { if (!$result = $this->disableTls) { $path = preg_match('{^[0-9a-f]{40}$}', $version) ? $this->pubKeys['dev'] : $this->pubKeys['tags']; $pubkeyid = openssl_pkey_get_public('file://'.$path); $result = 1 === openssl_verify( file_get_contents($file), $signature, $pubkeyid, $this->algo ); // PHP 8 automatically frees the key instance and deprecates the function if (PHP_VERSION_ID < 80000) { openssl_free_key($pubkeyid); } } return $result; } /** * Validates the downloaded phar file * * @param string $pharFile The temp phar file * @param null|string $error Set by method on failure * * @return bool If the operation succeeded */ protected function validatePhar($pharFile, &$error) { if (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 a string representation of the last json error * * @return string The error string or code */ protected function getJsonError() { if (function_exists('json_last_error_msg')) { return json_last_error_msg(); } else { return 'json_last_error = '.json_last_error(); } } /** * Cleans up resources at the end of the installation * * @param bool $result If the installation succeeded */ protected function cleanUp($result) { if (!$result) { // Output buffered errors if ($this->quiet) { $this->outputErrors(); } // Clean up stuff we created $this->uninstall(); } elseif ($this->tmpCafile) { @unlink($this->tmpCafile); } } /** * Outputs unique errors when in quiet mode * */ protected function outputErrors() { $errors = explode(PHP_EOL, ob_get_clean()); $shown = array(); foreach ($errors as $error) { if ($error && !in_array($error, $shown)) { out($error, 'error'); $shown[] = $error; } } } /** * Uninstalls newly-created files and directories on failure * */ protected function uninstall() { foreach (array_reverse($this->installs) as $target) { if (is_file($target)) { @unlink($target); } elseif (is_dir($target)) { @rmdir($target); } } if ($this->tmpFile !== null && file_exists($this->tmpFile)) { @unlink($this->tmpFile); } } public static function getPKDev() { return <<message) { $this->message .= PHP_EOL; } $this->message .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg); } /** * Starts error-handling if not already active * * Any message is cleared */ public function start() { if (!$this->active) { set_error_handler(array($this, 'handleError')); $this->active = true; } $this->message = ''; } /** * Stops error-handling if active * * Any message is preserved until the next call to start() */ public function stop() { if ($this->active) { restore_error_handler(); $this->active = false; } } } class NoProxyPattern { private $composerInNoProxy = false; private $rulePorts = array(); public function __construct($pattern) { $rules = preg_split('{[\s,]+}', $pattern, null, PREG_SPLIT_NO_EMPTY); if ($matches = preg_grep('{getcomposer\.org(?::\d+)?}i', $rules)) { $this->composerInNoProxy = true; foreach ($matches as $match) { if (strpos($match, ':') !== false) { list(, $port) = explode(':', $match); $this->rulePorts[] = (int) $port; } } } } /** * Returns true if NO_PROXY contains getcomposer.org * * @param string $url http(s)://getcomposer.org * * @return bool */ public function test($url) { if (!$this->composerInNoProxy) { return false; } if (empty($this->rulePorts)) { return true; } if (strpos($url, 'http://') === 0) { $port = 80; } else { $port = 443; } return in_array($port, $this->rulePorts); } } class HttpClient { /** @var null|string */ private static $caPath; private $options = array('http' => array()); private $disableTls = false; public function __construct($disableTls = false, $cafile = false) { $this->disableTls = $disableTls; if ($this->disableTls === false) { if (!empty($cafile) && !is_dir($cafile)) { if (!is_readable($cafile) || !validateCaFile(file_get_contents($cafile))) { throw new RuntimeException('The configured cafile (' .$cafile. ') was not valid or could not be read.'); } } $options = $this->getTlsStreamContextDefaults($cafile); $this->options = array_replace_recursive($this->options, $options); } } public function get($url) { $context = $this->getStreamContext($url); $result = file_get_contents($url, false, $context); if ($result && extension_loaded('zlib')) { $decode = false; foreach ($http_response_header as $header) { if (preg_match('{^content-encoding: *gzip *$}i', $header)) { $decode = true; continue; } elseif (preg_match('{^HTTP/}i', $header)) { $decode = false; } } if ($decode) { if (version_compare(PHP_VERSION, '5.4.0', '>=')) { $result = zlib_decode($result); } else { // work around issue with gzuncompress & co that do not work with all gzip checksums $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result)); } if (!$result) { throw new RuntimeException('Failed to decode zlib stream'); } } } return $result; } protected function getStreamContext($url) { if ($this->disableTls === false) { if (PHP_VERSION_ID < 50600) { $this->options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST); } } // Keeping the above mostly isolated from the code copied from Composer. return $this->getMergedStreamContext($url); } protected function getTlsStreamContextDefaults($cafile) { $ciphers = implode(':', array( '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. */ $options = array( 'ssl' => array( 'ciphers' => $ciphers, 'verify_peer' => true, 'verify_depth' => 7, 'SNI_enabled' => true, ) ); /** * Attempt to find a local cafile or throw an exception. * The user may go download one if this occurs. */ if (!$cafile) { $cafile = self::getSystemCaRootBundlePath(); } if (is_dir($cafile)) { $options['ssl']['capath'] = $cafile; } elseif ($cafile) { $options['ssl']['cafile'] = $cafile; } else { throw new RuntimeException('A valid cafile could not be located automatically.'); } /** * Disable TLS compression to prevent CRIME attacks where supported. */ if (version_compare(PHP_VERSION, '5.4.13') >= 0) { $options['ssl']['disable_compression'] = true; } return $options; } /** * function copied from Composer\Util\StreamContextFactory::initOptions * * Any changes should be applied there as well, or backported here. * * @param string $url URL the context is to be used for * @return resource Default context * @throws \RuntimeException if https proxy required and OpenSSL uninstalled */ protected function getMergedStreamContext($url) { $options = $this->options; // 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 (strpos($proxyURL, 'http://') === 0) { $proxyURL .= ":80"; } elseif (strpos($proxyURL, 'https://') === 0) { $proxyURL .= ":443"; } // check for a secure proxy if (strpos($proxyURL, 'https://') === 0) { if (!extension_loaded('openssl')) { throw new RuntimeException('You must enable the openssl extension to use a secure proxy.'); } if (strpos($url, 'https://') === 0) { throw new RuntimeException('PHP does not support https requests through a secure proxy.'); } } // http(s):// is not supported in proxy $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL); $options['http'] = array( 'proxy' => $proxyURL, ); // add request_fulluri for http requests if ('http' === parse_url($url, PHP_URL_SCHEME)) { $options['http']['request_fulluri'] = true; } // 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); $options['http']['header'] = "Proxy-Authorization: Basic {$auth}\r\n"; } } if (isset($options['http']['header'])) { $options['http']['header'] .= "Connection: close\r\n"; } else { $options['http']['header'] = "Connection: close\r\n"; } if (extension_loaded('zlib')) { $options['http']['header'] .= "Accept-Encoding: gzip\r\n"; } $options['http']['header'] .= "User-Agent: ".COMPOSER_INSTALLER."\r\n"; $options['http']['protocol_version'] = 1.1; $options['http']['timeout'] = 600; return stream_context_create($options); } /** * This method was adapted from Sslurp. * https://github.com/EvanDotPro/Sslurp * * (c) Evan Coury * * 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 getSystemCaRootBundlePath() { if (self::$caPath !== null) { return self::$caPath; } // 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. $envCertFile = getenv('SSL_CERT_FILE'); if ($envCertFile && is_readable($envCertFile) && validateCaFile(file_get_contents($envCertFile))) { return self::$caPath = $envCertFile; } // 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. $envCertDir = getenv('SSL_CERT_DIR'); if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) { return self::$caPath = $envCertDir; } $configured = ini_get('openssl.cafile'); if ($configured && strlen($configured) > 0 && is_readable($configured) && validateCaFile(file_get_contents($configured))) { return self::$caPath = $configured; } $configured = ini_get('openssl.capath'); if ($configured && is_dir($configured) && is_readable($configured)) { return self::$caPath = $configured; } $caBundlePaths = array( '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package) '/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/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_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/ssl/cert.pem', // FreeBSD 10.x '/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 ); foreach ($caBundlePaths as $caBundle) { if (@is_readable($caBundle) && validateCaFile(file_get_contents($caBundle))) { return self::$caPath = $caBundle; } } foreach ($caBundlePaths as $caBundle) { $caBundle = dirname($caBundle); if (is_dir($caBundle) && glob($caBundle.'/*')) { return self::$caPath = $caBundle; } } return self::$caPath = false; } public static function getPackagedCaFile() { return <<=8.0", "clue/phar-composer": "^1.4", "league/flysystem": "^3.0", "php-di/php-di": "^6.0 || ^7.0" }, "config": { "sort-packages": true, "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true } } } #!/bin/bash exec /usr/local/cpanel/3rdparty/bin/php /opt/cpanel/ea-wappspector/wappspector.phar "$@"{ "_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": "230ab9d16b6d4c3e2c63cb852d917b4b", "packages": [ { "name": "clue/phar-composer", "version": "v1.4.0", "source": { "type": "git", "url": "https://github.com/clue/phar-composer.git", "reference": "0cae6984e0da45639881d3b26442d525b8b65406" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/clue/phar-composer/zipball/0cae6984e0da45639881d3b26442d525b8b65406", "reference": "0cae6984e0da45639881d3b26442d525b8b65406", "shasum": "" }, "require": { "knplabs/packagist-api": "^1.0", "php": ">=5.3.6", "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.0 || ^2.5", "symfony/finder": "^6.0 || ^5.0 || ^4.0 || ^3.0 || ^2.5", "symfony/process": "^6.0 || ^5.0 || ^4.0 || ^3.0 || ^2.5" }, "require-dev": { "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.36" }, "bin": [ "bin/phar-composer" ], "type": "library", "autoload": { "psr-4": { "Clue\\PharComposer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Christian Lück", "email": "christian@clue.engineering" } ], "description": "Simple phar creation for any project managed via Composer", "homepage": "https://github.com/clue/phar-composer", "keywords": [ "build process", "bundle dependencies", "composer", "executable phar", "phar" ], "support": { "issues": "https://github.com/clue/phar-composer/issues", "source": "https://github.com/clue/phar-composer/tree/v1.4.0" }, "funding": [ { "url": "https://clue.engineering/support", "type": "custom" }, { "url": "https://github.com/clue", "type": "github" } ], "time": "2022-02-14T11:28:08+00:00" }, { "name": "doctrine/inflector", "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^12.0 || ^13.0", "phpstan/phpstan": "^1.12 || ^2.0", "phpstan/phpstan-phpunit": "^1.4 || ^2.0", "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", "phpunit/phpunit": "^8.5 || ^12.2" }, "type": "library", "autoload": { "psr-4": { "Doctrine\\Inflector\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", "homepage": "https://www.doctrine-project.org/projects/inflector.html", "keywords": [ "inflection", "inflector", "lowercase", "manipulation", "php", "plural", "singular", "strings", "uppercase", "words" ], "support": { "issues": "https://github.com/doctrine/inflector/issues", "source": "https://github.com/doctrine/inflector/tree/2.1.0" }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", "type": "custom" }, { "url": "https://www.patreon.com/phpdoctrine", "type": "patreon" }, { "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", "type": "tidelift" } ], "time": "2025-08-10T19:31:58+00:00" }, { "name": "guzzlehttp/guzzle", "version": "7.15.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", "reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc", "reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/promises": "^2.5.2", "guzzlehttp/psr7": "^2.13", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-client-implementation": "1.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", "guzzle/client-integration-tests": "3.0.3", "guzzlehttp/test-server": "^0.7", "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { "ext-curl": "Required for CURL handler support", "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, "forward-command": false } }, "autoload": { "files": [ "src/functions_include.php" ], "psr-4": { "GuzzleHttp\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Graham Campbell", "email": "hello@gjcampbell.co.uk", "homepage": "https://github.com/GrahamCampbell" }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "Jeremy Lindblom", "email": "jeremeamia@gmail.com", "homepage": "https://github.com/jeremeamia" }, { "name": "George Mponos", "email": "gmponos@gmail.com", "homepage": "https://github.com/gmponos" }, { "name": "Tobias Nyholm", "email": "tobias.nyholm@gmail.com", "homepage": "https://github.com/Nyholm" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", "homepage": "https://github.com/sagikazarmark" }, { "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" } ], "description": "Guzzle is a PHP HTTP client library", "keywords": [ "client", "curl", "framework", "http", "http client", "psr-18", "psr-7", "rest", "web service" ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", "source": "https://github.com/guzzle/guzzle/tree/7.15.3" }, "funding": [ { "url": "https://github.com/GrahamCampbell", "type": "github" }, { "url": "https://github.com/Nyholm", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", "type": "tidelift" } ], "time": "2026-08-05T19:48:21+00:00" }, { "name": "guzzlehttp/promises", "version": "2.5.2", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", "reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/guzzle/promises/zipball/2823687acff28b2dbe67b2508a6b300e2c3fa4ce", "reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "symfony/deprecation-contracts": "^2.5 || ^3.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, "forward-command": false } }, "autoload": { "psr-4": { "GuzzleHttp\\Promise\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Graham Campbell", "email": "hello@gjcampbell.co.uk", "homepage": "https://github.com/GrahamCampbell" }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "Tobias Nyholm", "email": "tobias.nyholm@gmail.com", "homepage": "https://github.com/Nyholm" }, { "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" } ], "description": "Guzzle promises library", "keywords": [ "promise" ], "support": { "issues": "https://github.com/guzzle/promises/issues", "source": "https://github.com/guzzle/promises/tree/2.5.2" }, "funding": [ { "url": "https://github.com/GrahamCampbell", "type": "github" }, { "url": "https://github.com/Nyholm", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", "type": "tidelift" } ], "time": "2026-08-05T19:30:54+00:00" }, { "name": "guzzlehttp/psr7", "version": "2.13.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/guzzle/psr7/zipball/dad89620b7a6edb60c15858442eb2e408b45d8f4", "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.1 || ^2.0", "ralouphie/getallheaders": "^3.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "1.1.0", "jshttp/mime-db": "1.54.0.1", "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, "forward-command": false } }, "autoload": { "psr-4": { "GuzzleHttp\\Psr7\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Graham Campbell", "email": "hello@gjcampbell.co.uk", "homepage": "https://github.com/GrahamCampbell" }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "George Mponos", "email": "gmponos@gmail.com", "homepage": "https://github.com/gmponos" }, { "name": "Tobias Nyholm", "email": "tobias.nyholm@gmail.com", "homepage": "https://github.com/Nyholm" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", "homepage": "https://github.com/sagikazarmark" }, { "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", "homepage": "https://sagikazarmark.hu" } ], "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ "http", "message", "psr-7", "request", "response", "stream", "uri", "url" ], "support": { "issues": "https://github.com/guzzle/psr7/issues", "source": "https://github.com/guzzle/psr7/tree/2.13.0" }, "funding": [ { "url": "https://github.com/GrahamCampbell", "type": "github" }, { "url": "https://github.com/Nyholm", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", "type": "tidelift" } ], "time": "2026-07-16T22:23:49+00:00" }, { "name": "knplabs/packagist-api", "version": "v1.7.2", "source": { "type": "git", "url": "https://github.com/KnpLabs/packagist-api.git", "reference": "4feae228a4505c1cd817da61e752e5dea2b22c2d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/KnpLabs/packagist-api/zipball/4feae228a4505c1cd817da61e752e5dea2b22c2d", "reference": "4feae228a4505c1cd817da61e752e5dea2b22c2d", "shasum": "" }, "require": { "doctrine/inflector": "^1.0 || ^2.0", "guzzlehttp/guzzle": "^6.0 || ^7.0", "php": "^7.1 || ^8.0" }, "require-dev": { "phpspec/phpspec": "^5.1 || ^6.0 || ^7.0", "squizlabs/php_codesniffer": "^3.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.x-dev" } }, "autoload": { "psr-0": { "Packagist\\Api\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "KnpLabs Team", "homepage": "http://knplabs.com" } ], "description": "Packagist API client.", "homepage": "http://knplabs.com", "keywords": [ "api", "composer", "packagist" ], "support": { "issues": "https://github.com/KnpLabs/packagist-api/issues", "source": "https://github.com/KnpLabs/packagist-api/tree/v1.7.2" }, "time": "2022-03-01T08:20:15+00:00" }, { "name": "laravel/serializable-closure", "version": "v2.0.15", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/dccd8bcb851bb03fcc005df650b708b57cc52661", "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { "illuminate/support": "^10.0|^11.0|^12.0|^13.0", "nesbot/carbon": "^2.67|^3.0", "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/phpstan": "^2.0", "symfony/var-dumper": "^6.2.0|^7.0.0|^8.0.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { "Laravel\\SerializableClosure\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" }, { "name": "Nuno Maduro", "email": "nuno@laravel.com" } ], "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", "keywords": [ "closure", "laravel", "serializable" ], "support": { "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, "time": "2026-07-21T16:49:22+00:00" }, { "name": "league/flysystem", "version": "3.35.2", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", "reference": "b277b5dc3d56650b68904117124e79c851e12376" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/b277b5dc3d56650b68904117124e79c851e12376", "reference": "b277b5dc3d56650b68904117124e79c851e12376", "shasum": "" }, "require": { "league/flysystem-local": "^3.0.0", "league/mime-type-detection": "^1.0.0", "php": "^8.0.2" }, "conflict": { "async-aws/core": "<1.19.0", "async-aws/s3": "<1.14.0", "aws/aws-sdk-php": "3.209.31 || 3.210.0", "guzzlehttp/guzzle": "<7.0", "guzzlehttp/ringphp": "<1.1.1", "phpseclib/phpseclib": "3.0.15", "symfony/http-client": "<5.2" }, "require-dev": { "async-aws/s3": "^1.5 || ^2.0", "async-aws/simple-s3": "^1.1 || ^2.0", "aws/aws-sdk-php": "^3.295.10", "composer/semver": "^3.0", "ext-fileinfo": "*", "ext-ftp": "*", "ext-mongodb": "^1.3|^2", "ext-zip": "*", "friendsofphp/php-cs-fixer": "^3.5", "google/cloud-storage": "^1.23", "guzzlehttp/psr7": "^2.6", "microsoft/azure-storage-blob": "^1.1", "mongodb/mongodb": "^1.2|^2", "phpseclib/phpseclib": "^3.0.36", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.5.11|^10.0", "sabre/dav": "^4.6.0" }, "type": "library", "autoload": { "psr-4": { "League\\Flysystem\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Frank de Jonge", "email": "info@frankdejonge.nl" } ], "description": "File storage abstraction for PHP", "keywords": [ "WebDAV", "aws", "cloud", "file", "files", "filesystem", "filesystems", "ftp", "s3", "sftp", "storage" ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", "source": "https://github.com/thephpleague/flysystem/tree/3.35.2" }, "time": "2026-07-06T14:42:07+00:00" }, { "name": "league/flysystem-local", "version": "3.31.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/2f669db18a4c20c755c2bb7d3a7b0b2340488079", "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079", "shasum": "" }, "require": { "ext-fileinfo": "*", "league/flysystem": "^3.0.0", "league/mime-type-detection": "^1.0.0", "php": "^8.0.2" }, "type": "library", "autoload": { "psr-4": { "League\\Flysystem\\Local\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Frank de Jonge", "email": "info@frankdejonge.nl" } ], "description": "Local filesystem adapter for Flysystem.", "keywords": [ "Flysystem", "file", "files", "filesystem", "local" ], "support": { "source": "https://github.com/thephpleague/flysystem-local/tree/3.31.0" }, "time": "2026-01-23T15:30:45+00:00" }, { "name": "league/mime-type-detection", "version": "1.17.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/f5f47eff7c48ed1003069a2ca67f316fb4021c76", "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76", "shasum": "" }, "require": { "ext-fileinfo": "*", "php": "^7.4 || ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "phpstan/phpstan": "^0.12.68", "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0 || ^11.0 || ^12.0" }, "type": "library", "autoload": { "psr-4": { "League\\MimeTypeDetection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Frank de Jonge", "email": "info@frankdejonge.nl" } ], "description": "Mime-type detection for Flysystem", "support": { "issues": "https://github.com/thephpleague/mime-type-detection/issues", "source": "https://github.com/thephpleague/mime-type-detection/tree/1.17.0" }, "funding": [ { "url": "https://github.com/frankdejonge", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/league/flysystem", "type": "tidelift" } ], "time": "2026-07-09T11:49:27+00:00" }, { "name": "php-di/invoker", "version": "2.3.7", "source": { "type": "git", "url": "https://github.com/PHP-DI/Invoker.git", "reference": "3c1ddfdef181431fbc4be83378f6d036d59e81e1" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/3c1ddfdef181431fbc4be83378f6d036d59e81e1", "reference": "3c1ddfdef181431fbc4be83378f6d036d59e81e1", "shasum": "" }, "require": { "php": ">=7.3", "psr/container": "^1.0|^2.0" }, "require-dev": { "athletic/athletic": "~0.1.8", "mnapoli/hard-mode": "~0.3.0", "phpunit/phpunit": "^9.0 || ^10 || ^11 || ^12" }, "type": "library", "autoload": { "psr-4": { "Invoker\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Generic and extensible callable invoker", "homepage": "https://github.com/PHP-DI/Invoker", "keywords": [ "callable", "dependency", "dependency-injection", "injection", "invoke", "invoker" ], "support": { "issues": "https://github.com/PHP-DI/Invoker/issues", "source": "https://github.com/PHP-DI/Invoker/tree/2.3.7" }, "funding": [ { "url": "https://github.com/mnapoli", "type": "github" } ], "time": "2025-08-30T10:22:22+00:00" }, { "name": "php-di/php-di", "version": "7.1.1", "source": { "type": "git", "url": "https://github.com/PHP-DI/PHP-DI.git", "reference": "f88054cc052e40dbe7b383c8817c19442d480352" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/f88054cc052e40dbe7b383c8817c19442d480352", "reference": "f88054cc052e40dbe7b383c8817c19442d480352", "shasum": "" }, "require": { "laravel/serializable-closure": "^1.0 || ^2.0", "php": ">=8.0", "php-di/invoker": "^2.0", "psr/container": "^1.1 || ^2.0" }, "provide": { "psr/container-implementation": "^1.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", "friendsofphp/proxy-manager-lts": "^1", "mnapoli/phpunit-easymock": "^1.3", "phpunit/phpunit": "^9.6 || ^10 || ^11", "vimeo/psalm": "^5|^6" }, "suggest": { "friendsofphp/proxy-manager-lts": "Install it if you want to use lazy injection (version ^1)" }, "type": "library", "autoload": { "files": [ "src/functions.php" ], "psr-4": { "DI\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "The dependency injection container for humans", "homepage": "https://php-di.org/", "keywords": [ "PSR-11", "container", "container-interop", "dependency injection", "di", "ioc", "psr11" ], "support": { "issues": "https://github.com/PHP-DI/PHP-DI/issues", "source": "https://github.com/PHP-DI/PHP-DI/tree/7.1.1" }, "funding": [ { "url": "https://github.com/mnapoli", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/php-di/php-di", "type": "tidelift" } ], "time": "2025-08-16T11:10:48+00:00" }, { "name": "psr/container", "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "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/2.0.2" }, "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/http-client", "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { "php": "^7.0 || ^8.0", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { "Psr\\Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", "homepage": "https://github.com/php-fig/http-client", "keywords": [ "http", "http-client", "psr", "psr-18" ], "support": { "source": "https://github.com/php-fig/http-client" }, "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "https://www.php-fig.org/" } ], "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", "message", "psr", "psr-17", "psr-7", "request", "response" ], "support": { "source": "https://github.com/php-fig/http-factory" }, "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", "homepage": "https://github.com/php-fig/http-message", "keywords": [ "http", "http-message", "psr", "psr-7", "request", "response" ], "support": { "source": "https://github.com/php-fig/http-message/tree/2.0" }, "time": "2023-04-04T09:54:51+00:00" }, { "name": "ralouphie/getallheaders", "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/ralouphie/getallheaders.git", "reference": "120b605dfeb996808c31b6477290a714d356e822" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", "reference": "120b605dfeb996808c31b6477290a714d356e822", "shasum": "" }, "require": { "php": ">=5.6" }, "require-dev": { "php-coveralls/php-coveralls": "^2.1", "phpunit/phpunit": "^5 || ^6.5" }, "type": "library", "autoload": { "files": [ "src/getallheaders.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Ralph Khattar", "email": "ralph.khattar@gmail.com" } ], "description": "A polyfill for getallheaders.", "support": { "issues": "https://github.com/ralouphie/getallheaders/issues", "source": "https://github.com/ralouphie/getallheaders/tree/develop" }, "time": "2019-03-08T08:55:37+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": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", "shasum": "" }, "require": { "php": ">=8.1" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/contracts", "name": "symfony/contracts" }, "branch-alias": { "dev-main": "3.7-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/v3.7.1" }, "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-06-05T06:23:12+00:00" }, { "name": "symfony/finder", "version": "v6.4.42", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", "reference": "0b73dac42493acbadbba644207a715b254e9b029" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/finder/zipball/0b73dac42493acbadbba644207a715b254e9b029", "reference": "0b73dac42493acbadbba644207a715b254e9b029", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "symfony/filesystem": "^6.0|^7.0" }, "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/v6.4.42" }, "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-06-26T15:18:24+00:00" }, { "name": "symfony/polyfill-ctype", "version": "v1.37.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.37.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.41.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", "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.41.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-07-28T08:25:59+00:00" }, { "name": "symfony/polyfill-intl-normalizer", "version": "v1.38.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b", "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b", "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.38.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-05-25T13:48:31+00:00" }, { "name": "symfony/polyfill-mbstring", "version": "v1.38.2", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", "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.38.2" }, "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-05-27T06:59:30+00:00" }, { "name": "symfony/polyfill-php73", "version": "v1.37.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.37.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.37.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.37.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/process", "version": "v6.4.41", "source": { "type": "git", "url": "https://github.com/symfony/process.git", "reference": "c8fc09bdfe9fde9aaa89b415a4477feaccec16a7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/process/zipball/c8fc09bdfe9fde9aaa89b415a4477feaccec16a7", "reference": "c8fc09bdfe9fde9aaa89b415a4477feaccec16a7", "shasum": "" }, "require": { "php": ">=8.1" }, "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/v6.4.41" }, "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-05-23T13:47:21+00:00" }, { "name": "symfony/service-contracts", "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/c0a284bab1ed8aa0417e3d69250ab437739563a0", "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0", "shasum": "" }, "require": { "php": ">=8.1", "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/contracts", "name": "symfony/contracts" }, "branch-alias": { "dev-main": "3.7-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" }, "exclude-from-classmap": [ "/Test/" ] }, "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/v3.7.1" }, "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-06-16T09:55:08+00:00" }, { "name": "symfony/string", "version": "v6.4.43", "source": { "type": "git", "url": "https://github.com/symfony/string.git", "reference": "2a8d515c3eaa5d33cf76d5fa277cdadd0a4e5b49" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/string/zipball/2a8d515c3eaa5d33cf76d5fa277cdadd0a4e5b49", "reference": "2a8d515c3eaa5d33cf76d5fa277cdadd0a4e5b49", "shasum": "" }, "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" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "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" }, "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/v6.4.43" }, "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-07-28T07:28:15+00:00" } ], "packages-dev": [ { "name": "dealerdirect/phpcodesniffer-composer-installer", "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/composer-installer.git", "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd", "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd", "shasum": "" }, "require": { "composer-plugin-api": "^2.2", "php": ">=5.4", "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { "composer/composer": "^2.2", "ext-json": "*", "ext-zip": "*", "php-parallel-lint/php-parallel-lint": "^1.4.0", "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", "yoast/phpunit-polyfills": "^1.0" }, "type": "composer-plugin", "extra": { "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" }, "autoload": { "psr-4": { "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Franck Nijhof", "email": "opensource@frenck.dev", "homepage": "https://frenck.dev", "role": "Open source developer" }, { "name": "Contributors", "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", "code quality", "codesniffer", "composer", "installer", "phpcbf", "phpcs", "plugin", "qa", "quality", "standard", "standards", "style guide", "stylecheck", "tests" ], "support": { "issues": "https://github.com/PHPCSStandards/composer-installer/issues", "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", "source": "https://github.com/PHPCSStandards/composer-installer" }, "funding": [ { "url": "https://github.com/PHPCSStandards", "type": "github" }, { "url": "https://github.com/jrfnl", "type": "github" }, { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" }, { "url": "https://thanks.dev/u/gh/phpcsstandards", "type": "thanks_dev" } ], "time": "2026-05-06T08:26:05+00:00" }, { "name": "mikey179/vfsstream", "version": "v1.6.12", "source": { "type": "git", "url": "https://github.com/bovigo/vfsStream.git", "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", "shasum": "" }, "require": { "php": ">=7.1.0" }, "require-dev": { "phpunit/phpunit": "^7.5||^8.5||^9.6", "yoast/phpunit-polyfills": "^2.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.6.x-dev" } }, "autoload": { "psr-0": { "org\\bovigo\\vfs\\": "src/main/php" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Frank Kleine", "homepage": "http://frankkleine.de/", "role": "Developer" } ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", "support": { "issues": "https://github.com/bovigo/vfsStream/issues", "source": "https://github.com/bovigo/vfsStream/tree/master", "wiki": "https://github.com/bovigo/vfsStream/wiki" }, "time": "2024-08-29T18:43:31+00:00" }, { "name": "myclabs/deep-copy", "version": "1.14.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", "reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae", "reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae", "shasum": "" }, "require": { "php": "^8.0" }, "conflict": { "doctrine/collections": "<1.6.8", "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { "files": [ "src/DeepCopy/deep_copy.php" ], "psr-4": { "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Create deep copies (clones) of your objects", "keywords": [ "clone", "copy", "duplicate", "object", "object graph" ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", "source": "https://github.com/myclabs/DeepCopy/tree/1.14.0" }, "funding": [ { "url": "https://github.com/mnapoli", "type": "github" } ], "time": "2026-08-11T10:17:44+00:00" }, { "name": "nikic/php-parser", "version": "v5.8.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/044a6a392ff8ad0d61f14370a5fbbd0a0107152f", "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f", "shasum": "" }, "require": { "ext-json": "*", "ext-tokenizer": "*", "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" ], "type": "library", "extra": { "branch-alias": { "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Nikita Popov" } ], "description": "A PHP parser written in PHP", "keywords": [ "parser", "php" ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", "source": "https://github.com/nikic/PHP-Parser/tree/v5.8.0" }, "time": "2026-07-04T14:30:18+00:00" }, { "name": "phar-io/manifest", "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, "funding": [ { "url": "https://github.com/theseer", "type": "github" } ], "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", "source": "https://github.com/phar-io/version/tree/3.2.1" }, "time": "2022-02-21T01:04:05+00:00" }, { "name": "phpstan/phpdoc-parser", "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", "shasum": "" }, "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" }, "type": "library", "autoload": { "psr-4": { "PHPStan\\PhpDocParser\\": [ "src/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.3" }, "time": "2026-07-08T07:01:06+00:00" }, { "name": "phpstan/phpstan", "version": "1.12.34", "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/4dd89ca7aa30fdc6760be21550d583bcc32e8476", "reference": "4dd89ca7aa30fdc6760be21550d583bcc32e8476", "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-07-28T10:04:39+00:00" }, { "name": "phpunit/php-code-coverage", "version": "10.1.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", "reference": "7e308268858ed6baedc8704a304727d20bc07c77", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", "nikic/php-parser": "^4.19.1 || ^5.1.0", "php": ">=8.1", "phpunit/php-file-iterator": "^4.1.0", "phpunit/php-text-template": "^3.0.1", "sebastian/code-unit-reverse-lookup": "^3.0.0", "sebastian/complexity": "^3.2.0", "sebastian/environment": "^6.1.0", "sebastian/lines-of-code": "^2.0.2", "sebastian/version": "^4.0.1", "theseer/tokenizer": "^1.2.3" }, "require-dev": { "phpunit/phpunit": "^10.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { "dev-main": "10.1.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ "coverage", "testing", "xunit" ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-08-22T04:31:57+00:00" }, { "name": "phpunit/php-file-iterator", "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ "filesystem", "iterator" ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-08-31T06:24:48+00:00" }, { "name": "phpunit/php-invoker", "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "ext-pcntl": "*", "phpunit/phpunit": "^10.0" }, "suggest": { "ext-pcntl": "*" }, "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Invoke callables with a timeout", "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ "process" ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-02-03T06:56:09+00:00" }, { "name": "phpunit/php-text-template", "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ "template" ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-08-31T14:07:24+00:00" }, { "name": "phpunit/php-timer", "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "6.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ "timer" ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-02-03T06:57:52+00:00" }, { "name": "phpunit/phpunit", "version": "10.5.64", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", "reference": "0e8c1d19cea35ad97d4887f363d07c78e30fbf06" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e8c1d19cea35ad97d4887f363d07c78e30fbf06", "reference": "0e8c1d19cea35ad97d4887f363d07c78e30fbf06", "shasum": "" }, "require": { "ext-dom": "*", "ext-filter": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.1", "phpunit/php-code-coverage": "^10.1.16", "phpunit/php-file-iterator": "^4.1.0", "phpunit/php-invoker": "^4.0.0", "phpunit/php-text-template": "^3.0.1", "phpunit/php-timer": "^6.0.0", "sebastian/cli-parser": "^2.0.1", "sebastian/code-unit": "^2.0.0", "sebastian/comparator": "^5.0.5", "sebastian/diff": "^5.1.1", "sebastian/environment": "^6.1.0", "sebastian/exporter": "^5.1.4", "sebastian/global-state": "^6.0.2", "sebastian/object-enumerator": "^5.0.0", "sebastian/recursion-context": "^5.0.1", "sebastian/type": "^4.0.0", "sebastian/version": "^4.0.1" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" ], "type": "library", "extra": { "branch-alias": { "dev-main": "10.5-dev" } }, "autoload": { "files": [ "src/Framework/Assert/Functions.php" ], "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.64" }, "funding": [ { "url": "https://phpunit.de/sponsoring.html", "type": "other" } ], "time": "2026-07-06T14:50:35+00:00" }, { "name": "psr/log", "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", "shasum": "" }, "require": { "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { "Psr\\Log\\": "src" } }, "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/2.0.0" }, "time": "2021-07-14T16:41:46+00:00" }, { "name": "rector/rector", "version": "1.2.10", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", "reference": "40f9cf38c05296bd32f444121336a521a293fa61" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/rectorphp/rector/zipball/40f9cf38c05296bd32f444121336a521a293fa61", "reference": "40f9cf38c05296bd32f444121336a521a293fa61", "shasum": "" }, "require": { "php": "^7.2|^8.0", "phpstan/phpstan": "^1.12.5" }, "conflict": { "rector/rector-doctrine": "*", "rector/rector-downgrade-php": "*", "rector/rector-phpunit": "*", "rector/rector-symfony": "*" }, "suggest": { "ext-dom": "To manipulate phpunit.xml via the custom-rule command" }, "bin": [ "bin/rector" ], "type": "library", "autoload": { "files": [ "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Instant Upgrade and Automated Refactoring of any PHP code", "keywords": [ "automation", "dev", "migration", "refactoring" ], "support": { "issues": "https://github.com/rectorphp/rector/issues", "source": "https://github.com/rectorphp/rector/tree/1.2.10" }, "funding": [ { "url": "https://github.com/tomasvotruba", "type": "github" } ], "time": "2024-11-08T13:59:10+00:00" }, { "name": "sebastian/cli-parser", "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "2.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library for parsing CLI options", "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-03-02T07:12:49+00:00" }, { "name": "sebastian/code-unit", "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "2.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Collection of value objects that represent the PHP code units", "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-02-03T06:58:43+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-02-03T06:59:15+00:00" }, { "name": "sebastian/comparator", "version": "5.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d", "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", "php": ">=8.1", "sebastian/diff": "^5.0", "sebastian/exporter": "^5.0" }, "require-dev": { "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" } ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.5" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" }, { "url": "https://liberapay.com/sebastianbergmann", "type": "liberapay" }, { "url": "https://thanks.dev/u/gh/sebastianbergmann", "type": "thanks_dev" }, { "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", "type": "tidelift" } ], "time": "2026-01-24T09:25:16+00:00" }, { "name": "sebastian/complexity", "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.2-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library for calculating the complexity of PHP code units", "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-12-21T08:37:17+00:00" }, { "name": "sebastian/diff", "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0", "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { "dev-main": "5.1-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Kore Nordmann", "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ "diff", "udiff", "unidiff", "unified diff" ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-03-02T07:15:17+00:00" }, { "name": "sebastian/environment", "version": "6.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "suggest": { "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { "dev-main": "6.1-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", "hhvm" ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-03-23T08:47:14+00:00" }, { "name": "sebastian/exporter", "version": "5.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", "reference": "0735b90f4da94969541dac1da743446e276defa6" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", "reference": "0735b90f4da94969541dac1da743446e276defa6", "shasum": "" }, "require": { "ext-mbstring": "*", "php": ">=8.1", "sebastian/recursion-context": "^5.0" }, "require-dev": { "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { "dev-main": "5.1-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Adam Harvey", "email": "aharvey@php.net" }, { "name": "Bernhard Schussek", "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" }, { "url": "https://liberapay.com/sebastianbergmann", "type": "liberapay" }, { "url": "https://thanks.dev/u/gh/sebastianbergmann", "type": "thanks_dev" }, { "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", "type": "tidelift" } ], "time": "2025-09-24T06:09:11+00:00" }, { "name": "sebastian/global-state", "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { "php": ">=8.1", "sebastian/object-reflector": "^3.0", "sebastian/recursion-context": "^5.0" }, "require-dev": { "ext-dom": "*", "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "6.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Snapshotting of global state", "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-03-02T07:19:19+00:00" }, { "name": "sebastian/lines-of-code", "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "2.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library for counting the lines of code in PHP source code", "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-12-21T08:38:20+00:00" }, { "name": "sebastian/object-enumerator", "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { "php": ">=8.1", "sebastian/object-reflector": "^3.0", "sebastian/recursion-context": "^5.0" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-02-03T07:08:32+00:00" }, { "name": "sebastian/object-reflector", "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-02-03T07:06:18+00:00" }, { "name": "sebastian/recursion-context", "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", "reference": "5d32fe257a9b39cb63146924d6b4e32a22d4502a" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5d32fe257a9b39cb63146924d6b4e32a22d4502a", "reference": "5d32fe257a9b39cb63146924d6b4e32a22d4502a", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides functionality to recursively process PHP variables", "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" }, { "url": "https://liberapay.com/sebastianbergmann", "type": "liberapay" }, { "url": "https://thanks.dev/u/gh/sebastianbergmann", "type": "thanks_dev" }, { "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", "type": "tidelift" } ], "time": "2026-08-11T05:27:39+00:00" }, { "name": "sebastian/type", "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-02-03T07:10:45+00:00" }, { "name": "sebastian/version", "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2023-02-07T11:34:05+00:00" }, { "name": "slevomat/coding-standard", "version": "8.22.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/1dd80bf3b93692bedb21a6623c496887fad05fec", "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.1.2", "php": "^7.4 || ^8.0", "phpstan/phpdoc-parser": "^2.3.0", "squizlabs/php_codesniffer": "^3.13.4" }, "require-dev": { "phing/phing": "3.0.1|3.1.0", "php-parallel-lint/php-parallel-lint": "1.4.0", "phpstan/phpstan": "2.1.24", "phpstan/phpstan-deprecation-rules": "2.0.3", "phpstan/phpstan-phpunit": "2.0.7", "phpstan/phpstan-strict-rules": "2.0.6", "phpunit/phpunit": "9.6.8|10.5.48|11.4.4|11.5.36|12.3.10" }, "type": "phpcodesniffer-standard", "extra": { "branch-alias": { "dev-master": "8.x-dev" } }, "autoload": { "psr-4": { "SlevomatCodingStandard\\": "SlevomatCodingStandard/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", "keywords": [ "dev", "phpcs" ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", "source": "https://github.com/slevomat/coding-standard/tree/8.22.1" }, "funding": [ { "url": "https://github.com/kukulich", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", "type": "tidelift" } ], "time": "2025-09-13T08:53:30+00:00" }, { "name": "squizlabs/php_codesniffer", "version": "3.13.6", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", "reference": "4c378e1a528ea066890fc2397cbdd2f94eb2fc91" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/4c378e1a528ea066890fc2397cbdd2f94eb2fc91", "reference": "4c378e1a528ea066890fc2397cbdd2f94eb2fc91", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", "php": ">=5.4.0" }, "require-dev": { "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "bin": [ "bin/phpcbf", "bin/phpcs" ], "type": "library", "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Greg Sherwood", "role": "Former lead" }, { "name": "Juliette Reinders Folmer", "role": "Current lead" }, { "name": "Contributors", "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", "standards", "static analysis" ], "support": { "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, "funding": [ { "url": "https://github.com/PHPCSStandards", "type": "github" }, { "url": "https://github.com/jrfnl", "type": "github" }, { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" }, { "url": "https://thanks.dev/u/gh/phpcsstandards", "type": "thanks_dev" } ], "time": "2026-08-06T00:17:32+00:00" }, { "name": "theseer/tokenizer", "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { "url": "https://github.com/theseer", "type": "github" } ], "time": "2025-11-17T20:03:58+00:00" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=8.0" }, "platform-dev": {}, "plugin-api-version": "2.9.0" } * Jordi Boggiano * * 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 * @author Jordi Boggiano * @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> */ private $prefixLengthsPsr4 = array(); /** * @var array> */ private $prefixDirsPsr4 = array(); /** * @var list */ 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>> */ private $prefixesPsr0 = array(); /** * @var list */ private $fallbackDirsPsr0 = array(); /** @var bool */ private $useIncludePath = false; /** * @var array */ private $classMap = array(); /** @var bool */ private $classMapAuthoritative = false; /** * @var array */ private $missingClasses = array(); /** @var string|null */ private $apcuPrefix; /** * @var array */ private static $registeredLoaders = array(); /** * @param string|null $vendorDir */ public function __construct($vendorDir = null) { $this->vendorDir = $vendorDir; self::initializeIncludeClosure(); } /** * @return array> */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); } return array(); } /** * @return array> */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } /** * @return list */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } /** * @return list */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } /** * @return array Array of classname => path */ public function getClassMap() { return $this->classMap; } /** * @param array $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 $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 $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 $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 $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 */ 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); } } * Jordi Boggiano * * 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}|array{}|null */ private static $installed; /** * @var bool */ private static $installedIsLocalDir; /** * @var bool|null */ private static $canGetVendors; /** * @var array[] * @psalm-var array}> */ 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 */ 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 */ 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} */ 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}> */ 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} $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}> */ 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} $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} $required */ $required = require __DIR__ . '/installed.php'; self::$installed = $required; } else { self::$installed = array(); } } if (self::$installed !== array() && !$copiedLocalDir) { $installed[] = self::$installed; } return $installed; } } $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'PHPUnit\\Event\\Application\\Finished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Application/Finished.php', 'PHPUnit\\Event\\Application\\FinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Application/FinishedSubscriber.php', 'PHPUnit\\Event\\Application\\Started' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Application/Started.php', 'PHPUnit\\Event\\Application\\StartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Application/StartedSubscriber.php', 'PHPUnit\\Event\\Code\\ClassMethod' => $vendorDir . '/phpunit/phpunit/src/Event/Value/ClassMethod.php', 'PHPUnit\\Event\\Code\\ComparisonFailure' => $vendorDir . '/phpunit/phpunit/src/Event/Value/ComparisonFailure.php', 'PHPUnit\\Event\\Code\\ComparisonFailureBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/ComparisonFailureBuilder.php', 'PHPUnit\\Event\\Code\\NoTestCaseObjectOnCallStackException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.php', 'PHPUnit\\Event\\Code\\Phpt' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/Phpt.php', 'PHPUnit\\Event\\Code\\Test' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/Test.php', 'PHPUnit\\Event\\Code\\TestCollection' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestCollection.php', 'PHPUnit\\Event\\Code\\TestCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestCollectionIterator.php', 'PHPUnit\\Event\\Code\\TestDox' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestDox.php', 'PHPUnit\\Event\\Code\\TestDoxBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestDoxBuilder.php', 'PHPUnit\\Event\\Code\\TestMethod' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestMethod.php', 'PHPUnit\\Event\\Code\\TestMethodBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php', 'PHPUnit\\Event\\Code\\Throwable' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Throwable.php', 'PHPUnit\\Event\\Code\\ThrowableBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/ThrowableBuilder.php', 'PHPUnit\\Event\\CollectingDispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/CollectingDispatcher.php', 'PHPUnit\\Event\\DeferringDispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/DeferringDispatcher.php', 'PHPUnit\\Event\\DirectDispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/DirectDispatcher.php', 'PHPUnit\\Event\\Dispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/Dispatcher.php', 'PHPUnit\\Event\\DispatchingEmitter' => $vendorDir . '/phpunit/phpunit/src/Event/Emitter/DispatchingEmitter.php', 'PHPUnit\\Event\\Emitter' => $vendorDir . '/phpunit/phpunit/src/Event/Emitter/Emitter.php', 'PHPUnit\\Event\\Event' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Event.php', 'PHPUnit\\Event\\EventAlreadyAssignedException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/EventAlreadyAssignedException.php', 'PHPUnit\\Event\\EventCollection' => $vendorDir . '/phpunit/phpunit/src/Event/Events/EventCollection.php', 'PHPUnit\\Event\\EventCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Event/Events/EventCollectionIterator.php', 'PHPUnit\\Event\\EventFacadeIsSealedException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/EventFacadeIsSealedException.php', 'PHPUnit\\Event\\Exception' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/Exception.php', 'PHPUnit\\Event\\Facade' => $vendorDir . '/phpunit/phpunit/src/Event/Facade.php', 'PHPUnit\\Event\\InvalidArgumentException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/InvalidArgumentException.php', 'PHPUnit\\Event\\InvalidEventException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/InvalidEventException.php', 'PHPUnit\\Event\\InvalidSubscriberException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/InvalidSubscriberException.php', 'PHPUnit\\Event\\MapError' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/MapError.php', 'PHPUnit\\Event\\NoPreviousThrowableException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/NoPreviousThrowableException.php', 'PHPUnit\\Event\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/RuntimeException.php', 'PHPUnit\\Event\\Runtime\\OperatingSystem' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Runtime/OperatingSystem.php', 'PHPUnit\\Event\\Runtime\\PHP' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Runtime/PHP.php', 'PHPUnit\\Event\\Runtime\\PHPUnit' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Runtime/PHPUnit.php', 'PHPUnit\\Event\\Runtime\\Runtime' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Runtime/Runtime.php', 'PHPUnit\\Event\\SubscribableDispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/SubscribableDispatcher.php', 'PHPUnit\\Event\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Subscriber.php', 'PHPUnit\\Event\\SubscriberTypeAlreadyRegisteredException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.php', 'PHPUnit\\Event\\Telemetry\\Duration' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Duration.php', 'PHPUnit\\Event\\Telemetry\\GarbageCollectorStatus' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.php', 'PHPUnit\\Event\\Telemetry\\GarbageCollectorStatusProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.php', 'PHPUnit\\Event\\Telemetry\\HRTime' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/HRTime.php', 'PHPUnit\\Event\\Telemetry\\Info' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Info.php', 'PHPUnit\\Event\\Telemetry\\MemoryMeter' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/MemoryMeter.php', 'PHPUnit\\Event\\Telemetry\\MemoryUsage' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/MemoryUsage.php', 'PHPUnit\\Event\\Telemetry\\Php81GarbageCollectorStatusProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php', 'PHPUnit\\Event\\Telemetry\\Php83GarbageCollectorStatusProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.php', 'PHPUnit\\Event\\Telemetry\\Snapshot' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Snapshot.php', 'PHPUnit\\Event\\Telemetry\\StopWatch' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/StopWatch.php', 'PHPUnit\\Event\\Telemetry\\System' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/System.php', 'PHPUnit\\Event\\Telemetry\\SystemMemoryMeter' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.php', 'PHPUnit\\Event\\Telemetry\\SystemStopWatch' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatch.php', 'PHPUnit\\Event\\Telemetry\\SystemStopWatchWithOffset' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.php', 'PHPUnit\\Event\\TestData\\DataFromDataProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.php', 'PHPUnit\\Event\\TestData\\DataFromTestDependency' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.php', 'PHPUnit\\Event\\TestData\\MoreThanOneDataSetFromDataProviderException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/MoreThanOneDataSetFromDataProviderException.php', 'PHPUnit\\Event\\TestData\\NoDataSetFromDataProviderException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php', 'PHPUnit\\Event\\TestData\\TestData' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestData.php', 'PHPUnit\\Event\\TestData\\TestDataCollection' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollection.php', 'PHPUnit\\Event\\TestData\\TestDataCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.php', 'PHPUnit\\Event\\TestRunner\\BootstrapFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinished.php', 'PHPUnit\\Event\\TestRunner\\BootstrapFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\Configured' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/Configured.php', 'PHPUnit\\Event\\TestRunner\\ConfiguredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.php', 'PHPUnit\\Event\\TestRunner\\DeprecationTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggered.php', 'PHPUnit\\Event\\TestRunner\\DeprecationTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php', 'PHPUnit\\Event\\TestRunner\\EventFacadeSealed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealed.php', 'PHPUnit\\Event\\TestRunner\\EventFacadeSealedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExecutionAborted' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAborted.php', 'PHPUnit\\Event\\TestRunner\\ExecutionAbortedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExecutionFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinished.php', 'PHPUnit\\Event\\TestRunner\\ExecutionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExecutionStarted' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStarted.php', 'PHPUnit\\Event\\TestRunner\\ExecutionStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExtensionBootstrapped' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.php', 'PHPUnit\\Event\\TestRunner\\ExtensionBootstrappedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExtensionLoadedFromPhar' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.php', 'PHPUnit\\Event\\TestRunner\\ExtensionLoadedFromPharSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php', 'PHPUnit\\Event\\TestRunner\\Finished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/Finished.php', 'PHPUnit\\Event\\TestRunner\\FinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/FinishedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionDisabled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionDisabledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionEnabled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionEnabledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php', 'PHPUnit\\Event\\TestRunner\\Started' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/Started.php', 'PHPUnit\\Event\\TestRunner\\StartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/StartedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\WarningTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggered.php', 'PHPUnit\\Event\\TestRunner\\WarningTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Filtered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Filtered.php', 'PHPUnit\\Event\\TestSuite\\FilteredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/FilteredSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Finished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Finished.php', 'PHPUnit\\Event\\TestSuite\\FinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/FinishedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Loaded' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Loaded.php', 'PHPUnit\\Event\\TestSuite\\LoadedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/LoadedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Skipped' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Skipped.php', 'PHPUnit\\Event\\TestSuite\\SkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/SkippedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Sorted' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Sorted.php', 'PHPUnit\\Event\\TestSuite\\SortedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/SortedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Started' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Started.php', 'PHPUnit\\Event\\TestSuite\\StartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/StartedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuite.php', 'PHPUnit\\Event\\TestSuite\\TestSuiteBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.php', 'PHPUnit\\Event\\TestSuite\\TestSuiteForTestClass' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.php', 'PHPUnit\\Event\\TestSuite\\TestSuiteForTestMethodWithDataProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.php', 'PHPUnit\\Event\\TestSuite\\TestSuiteWithName' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteWithName.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodErrored' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodErrored.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodErroredSubscriber.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\AfterTestMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.php', 'PHPUnit\\Event\\Test\\AfterTestMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\AfterTestMethodErrored' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodErrored.php', 'PHPUnit\\Event\\Test\\AfterTestMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodErroredSubscriber.php', 'PHPUnit\\Event\\Test\\AfterTestMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinished.php', 'PHPUnit\\Event\\Test\\AfterTestMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\AssertionFailed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailed.php', 'PHPUnit\\Event\\Test\\AssertionFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailedSubscriber.php', 'PHPUnit\\Event\\Test\\AssertionSucceeded' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceeded.php', 'PHPUnit\\Event\\Test\\AssertionSucceededSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceededSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalled.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodErrored' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErrored.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErroredSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinished.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalled.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodErrored' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodErrored.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodErroredSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinished.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\ComparatorRegistered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/ComparatorRegistered.php', 'PHPUnit\\Event\\Test\\ComparatorRegisteredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php', 'PHPUnit\\Event\\Test\\ConsideredRisky' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRisky.php', 'PHPUnit\\Event\\Test\\ConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRiskySubscriber.php', 'PHPUnit\\Event\\Test\\DataProviderMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalled.php', 'PHPUnit\\Event\\Test\\DataProviderMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\DataProviderMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinished.php', 'PHPUnit\\Event\\Test\\DataProviderMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\DeprecationTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggered.php', 'PHPUnit\\Event\\Test\\DeprecationTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\ErrorTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggered.php', 'PHPUnit\\Event\\Test\\ErrorTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\Errored' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Errored.php', 'PHPUnit\\Event\\Test\\ErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/ErroredSubscriber.php', 'PHPUnit\\Event\\Test\\Failed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Failed.php', 'PHPUnit\\Event\\Test\\FailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/FailedSubscriber.php', 'PHPUnit\\Event\\Test\\Finished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Finished.php', 'PHPUnit\\Event\\Test\\FinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/FinishedSubscriber.php', 'PHPUnit\\Event\\Test\\MarkedIncomplete' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncomplete.php', 'PHPUnit\\Event\\Test\\MarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncompleteSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreated.php', 'PHPUnit\\Event\\Test\\MockObjectCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectForAbstractClassCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreated.php', 'PHPUnit\\Event\\Test\\MockObjectForAbstractClassCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectForIntersectionOfInterfacesCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreated.php', 'PHPUnit\\Event\\Test\\MockObjectForIntersectionOfInterfacesCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectForTraitCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreated.php', 'PHPUnit\\Event\\Test\\MockObjectForTraitCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectFromWsdlCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreated.php', 'PHPUnit\\Event\\Test\\MockObjectFromWsdlCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\NoComparisonFailureException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/NoComparisonFailureException.php', 'PHPUnit\\Event\\Test\\NoticeTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggered.php', 'PHPUnit\\Event\\Test\\NoticeTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PartialMockObjectCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.php', 'PHPUnit\\Event\\Test\\PartialMockObjectCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\Passed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Passed.php', 'PHPUnit\\Event\\Test\\PassedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/PassedSubscriber.php', 'PHPUnit\\Event\\Test\\PhpDeprecationTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggered.php', 'PHPUnit\\Event\\Test\\PhpDeprecationTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpNoticeTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggered.php', 'PHPUnit\\Event\\Test\\PhpNoticeTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpWarningTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggered.php', 'PHPUnit\\Event\\Test\\PhpWarningTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpunitDeprecationTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggered.php', 'PHPUnit\\Event\\Test\\PhpunitDeprecationTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpunitErrorTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggered.php', 'PHPUnit\\Event\\Test\\PhpunitErrorTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpunitWarningTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggered.php', 'PHPUnit\\Event\\Test\\PhpunitWarningTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PostConditionCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalled.php', 'PHPUnit\\Event\\Test\\PostConditionCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalledSubscriber.php', 'PHPUnit\\Event\\Test\\PostConditionErrored' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionErrored.php', 'PHPUnit\\Event\\Test\\PostConditionErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionErroredSubscriber.php', 'PHPUnit\\Event\\Test\\PostConditionFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinished.php', 'PHPUnit\\Event\\Test\\PostConditionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\PreConditionCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalled.php', 'PHPUnit\\Event\\Test\\PreConditionCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalledSubscriber.php', 'PHPUnit\\Event\\Test\\PreConditionErrored' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionErrored.php', 'PHPUnit\\Event\\Test\\PreConditionErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionErroredSubscriber.php', 'PHPUnit\\Event\\Test\\PreConditionFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinished.php', 'PHPUnit\\Event\\Test\\PreConditionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\PreparationFailed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailed.php', 'PHPUnit\\Event\\Test\\PreparationFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailedSubscriber.php', 'PHPUnit\\Event\\Test\\PreparationStarted' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStarted.php', 'PHPUnit\\Event\\Test\\PreparationStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStartedSubscriber.php', 'PHPUnit\\Event\\Test\\Prepared' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Prepared.php', 'PHPUnit\\Event\\Test\\PreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparedSubscriber.php', 'PHPUnit\\Event\\Test\\PrintedUnexpectedOutput' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutput.php', 'PHPUnit\\Event\\Test\\PrintedUnexpectedOutputSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutputSubscriber.php', 'PHPUnit\\Event\\Test\\Skipped' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Skipped.php', 'PHPUnit\\Event\\Test\\SkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/SkippedSubscriber.php', 'PHPUnit\\Event\\Test\\TestProxyCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php', 'PHPUnit\\Event\\Test\\TestProxyCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\TestStubCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php', 'PHPUnit\\Event\\Test\\TestStubCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\TestStubForIntersectionOfInterfacesCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.php', 'PHPUnit\\Event\\Test\\TestStubForIntersectionOfInterfacesCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\WarningTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggered.php', 'PHPUnit\\Event\\Test\\WarningTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggeredSubscriber.php', 'PHPUnit\\Event\\Tracer\\Tracer' => $vendorDir . '/phpunit/phpunit/src/Event/Tracer.php', 'PHPUnit\\Event\\TypeMap' => $vendorDir . '/phpunit/phpunit/src/Event/TypeMap.php', 'PHPUnit\\Event\\UnknownEventException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/UnknownEventException.php', 'PHPUnit\\Event\\UnknownEventTypeException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/UnknownEventTypeException.php', 'PHPUnit\\Event\\UnknownSubscriberException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/UnknownSubscriberException.php', 'PHPUnit\\Event\\UnknownSubscriberTypeException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/UnknownSubscriberTypeException.php', 'PHPUnit\\Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php', 'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.php', 'PHPUnit\\Framework\\Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php', 'PHPUnit\\Framework\\AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php', 'PHPUnit\\Framework\\Attributes\\After' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/After.php', 'PHPUnit\\Framework\\Attributes\\AfterClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/AfterClass.php', 'PHPUnit\\Framework\\Attributes\\BackupGlobals' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/BackupGlobals.php', 'PHPUnit\\Framework\\Attributes\\BackupStaticProperties' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/BackupStaticProperties.php', 'PHPUnit\\Framework\\Attributes\\Before' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Before.php', 'PHPUnit\\Framework\\Attributes\\BeforeClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/BeforeClass.php', 'PHPUnit\\Framework\\Attributes\\CodeCoverageIgnore' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/CodeCoverageIgnore.php', 'PHPUnit\\Framework\\Attributes\\CoversClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/CoversClass.php', 'PHPUnit\\Framework\\Attributes\\CoversFunction' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/CoversFunction.php', 'PHPUnit\\Framework\\Attributes\\CoversNothing' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/CoversNothing.php', 'PHPUnit\\Framework\\Attributes\\DataProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DataProvider.php', 'PHPUnit\\Framework\\Attributes\\DataProviderExternal' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DataProviderExternal.php', 'PHPUnit\\Framework\\Attributes\\Depends' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Depends.php', 'PHPUnit\\Framework\\Attributes\\DependsExternal' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsExternal.php', 'PHPUnit\\Framework\\Attributes\\DependsExternalUsingDeepClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php', 'PHPUnit\\Framework\\Attributes\\DependsExternalUsingShallowClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php', 'PHPUnit\\Framework\\Attributes\\DependsOnClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClass.php', 'PHPUnit\\Framework\\Attributes\\DependsOnClassUsingDeepClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.php', 'PHPUnit\\Framework\\Attributes\\DependsOnClassUsingShallowClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.php', 'PHPUnit\\Framework\\Attributes\\DependsUsingDeepClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsUsingDeepClone.php', 'PHPUnit\\Framework\\Attributes\\DependsUsingShallowClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsUsingShallowClone.php', 'PHPUnit\\Framework\\Attributes\\DoesNotPerformAssertions' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php', 'PHPUnit\\Framework\\Attributes\\ExcludeGlobalVariableFromBackup' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.php', 'PHPUnit\\Framework\\Attributes\\ExcludeStaticPropertyFromBackup' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php', 'PHPUnit\\Framework\\Attributes\\Group' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Group.php', 'PHPUnit\\Framework\\Attributes\\IgnoreClassForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/IgnoreClassForCodeCoverage.php', 'PHPUnit\\Framework\\Attributes\\IgnoreDeprecations' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/IgnoreDeprecations.php', 'PHPUnit\\Framework\\Attributes\\IgnoreFunctionForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/IgnoreFunctionForCodeCoverage.php', 'PHPUnit\\Framework\\Attributes\\IgnoreMethodForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/IgnoreMethodForCodeCoverage.php', 'PHPUnit\\Framework\\Attributes\\Large' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Large.php', 'PHPUnit\\Framework\\Attributes\\Medium' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Medium.php', 'PHPUnit\\Framework\\Attributes\\PostCondition' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/PostCondition.php', 'PHPUnit\\Framework\\Attributes\\PreCondition' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/PreCondition.php', 'PHPUnit\\Framework\\Attributes\\PreserveGlobalState' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/PreserveGlobalState.php', 'PHPUnit\\Framework\\Attributes\\RequiresFunction' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresFunction.php', 'PHPUnit\\Framework\\Attributes\\RequiresMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresMethod.php', 'PHPUnit\\Framework\\Attributes\\RequiresOperatingSystem' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystem.php', 'PHPUnit\\Framework\\Attributes\\RequiresOperatingSystemFamily' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.php', 'PHPUnit\\Framework\\Attributes\\RequiresPhp' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhp.php', 'PHPUnit\\Framework\\Attributes\\RequiresPhpExtension' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhpExtension.php', 'PHPUnit\\Framework\\Attributes\\RequiresPhpunit' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhpunit.php', 'PHPUnit\\Framework\\Attributes\\RequiresSetting' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresSetting.php', 'PHPUnit\\Framework\\Attributes\\RunClassInSeparateProcess' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RunClassInSeparateProcess.php', 'PHPUnit\\Framework\\Attributes\\RunInSeparateProcess' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RunInSeparateProcess.php', 'PHPUnit\\Framework\\Attributes\\RunTestsInSeparateProcesses' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.php', 'PHPUnit\\Framework\\Attributes\\Small' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Small.php', 'PHPUnit\\Framework\\Attributes\\Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Test.php', 'PHPUnit\\Framework\\Attributes\\TestDox' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/TestDox.php', 'PHPUnit\\Framework\\Attributes\\TestWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/TestWith.php', 'PHPUnit\\Framework\\Attributes\\TestWithJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/TestWithJson.php', 'PHPUnit\\Framework\\Attributes\\Ticket' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Ticket.php', 'PHPUnit\\Framework\\Attributes\\UsesClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/UsesClass.php', 'PHPUnit\\Framework\\Attributes\\UsesFunction' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/UsesFunction.php', 'PHPUnit\\Framework\\Attributes\\WithoutErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/WithoutErrorHandler.php', 'PHPUnit\\Framework\\CodeCoverageException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotAcceptParameterTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareBoolReturnTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareExactlyOneParameterException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareParameterTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php', 'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php', 'PHPUnit\\Framework\\Constraint\\BinaryOperator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php', 'PHPUnit\\Framework\\Constraint\\Callback' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Callback.php', 'PHPUnit\\Framework\\Constraint\\Constraint' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php', 'PHPUnit\\Framework\\Constraint\\Count' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php', 'PHPUnit\\Framework\\Constraint\\DirectoryExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php', 'PHPUnit\\Framework\\Constraint\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php', 'PHPUnit\\Framework\\Constraint\\ExceptionCode' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php', 'PHPUnit\\Framework\\Constraint\\ExceptionMessageIsOrContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.php', 'PHPUnit\\Framework\\Constraint\\ExceptionMessageMatchesRegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php', 'PHPUnit\\Framework\\Constraint\\FileExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php', 'PHPUnit\\Framework\\Constraint\\GreaterThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php', 'PHPUnit\\Framework\\Constraint\\IsAnything' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php', 'PHPUnit\\Framework\\Constraint\\IsEmpty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php', 'PHPUnit\\Framework\\Constraint\\IsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php', 'PHPUnit\\Framework\\Constraint\\IsEqualCanonicalizing' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php', 'PHPUnit\\Framework\\Constraint\\IsEqualIgnoringCase' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php', 'PHPUnit\\Framework\\Constraint\\IsEqualWithDelta' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php', 'PHPUnit\\Framework\\Constraint\\IsFalse' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php', 'PHPUnit\\Framework\\Constraint\\IsFinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php', 'PHPUnit\\Framework\\Constraint\\IsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php', 'PHPUnit\\Framework\\Constraint\\IsInfinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php', 'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php', 'PHPUnit\\Framework\\Constraint\\IsJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php', 'PHPUnit\\Framework\\Constraint\\IsList' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/IsList.php', 'PHPUnit\\Framework\\Constraint\\IsNan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php', 'PHPUnit\\Framework\\Constraint\\IsNull' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php', 'PHPUnit\\Framework\\Constraint\\IsReadable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php', 'PHPUnit\\Framework\\Constraint\\IsTrue' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php', 'PHPUnit\\Framework\\Constraint\\IsType' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php', 'PHPUnit\\Framework\\Constraint\\IsWritable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php', 'PHPUnit\\Framework\\Constraint\\JsonMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php', 'PHPUnit\\Framework\\Constraint\\LessThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php', 'PHPUnit\\Framework\\Constraint\\LogicalAnd' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php', 'PHPUnit\\Framework\\Constraint\\LogicalNot' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php', 'PHPUnit\\Framework\\Constraint\\LogicalOr' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php', 'PHPUnit\\Framework\\Constraint\\LogicalXor' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php', 'PHPUnit\\Framework\\Constraint\\ObjectEquals' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php', 'PHPUnit\\Framework\\Constraint\\ObjectHasProperty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasProperty.php', 'PHPUnit\\Framework\\Constraint\\Operator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php', 'PHPUnit\\Framework\\Constraint\\RegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php', 'PHPUnit\\Framework\\Constraint\\SameSize' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php', 'PHPUnit\\Framework\\Constraint\\StringContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php', 'PHPUnit\\Framework\\Constraint\\StringEndsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php', 'PHPUnit\\Framework\\Constraint\\StringEqualsStringIgnoringLineEndings' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.php', 'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php', 'PHPUnit\\Framework\\Constraint\\StringStartsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php', 'PHPUnit\\Framework\\Constraint\\TraversableContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php', 'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php', 'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php', 'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php', 'PHPUnit\\Framework\\Constraint\\UnaryOperator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php', 'PHPUnit\\Framework\\DataProviderTestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php', 'PHPUnit\\Framework\\EmptyStringException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/EmptyStringException.php', 'PHPUnit\\Framework\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Exception.php', 'PHPUnit\\Framework\\ExecutionOrderDependency' => $vendorDir . '/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php', 'PHPUnit\\Framework\\ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php', 'PHPUnit\\Framework\\GeneratorNotSupportedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/GeneratorNotSupportedException.php', 'PHPUnit\\Framework\\IncompleteTest' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php', 'PHPUnit\\Framework\\IncompleteTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.php', 'PHPUnit\\Framework\\InvalidArgumentException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php', 'PHPUnit\\Framework\\InvalidCoversTargetException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php', 'PHPUnit\\Framework\\InvalidDataProviderException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php', 'PHPUnit\\Framework\\InvalidDependencyException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidDependencyException.php', 'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php', 'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Identity.php', 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.php', 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.php', 'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php', 'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.php', 'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php', 'PHPUnit\\Framework\\MockObject\\CannotUseOnlyMethodsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php', 'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php', 'PHPUnit\\Framework\\MockObject\\DoubledCloneMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.php', 'PHPUnit\\Framework\\MockObject\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php', 'PHPUnit\\Framework\\MockObject\\Generator\\CannotUseAddMethodsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsEnumerationException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsFinalException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsReadonlyException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsReadonlyException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\DuplicateMethodException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/Exception.php', 'PHPUnit\\Framework\\MockObject\\Generator\\Generator' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Generator.php', 'PHPUnit\\Framework\\MockObject\\Generator\\InvalidMethodNameException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockClass' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockClass.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethod.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockMethodSet' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethodSet.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockTrait' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockTrait.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockType' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockType.php', 'PHPUnit\\Framework\\MockObject\\Generator\\NameAlreadyInUseException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\OriginalConstructorInvocationRequiredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\ReflectionException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\SoapExtensionNotAvailableException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\TemplateLoader' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/TemplateLoader.php', 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownClassException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownTraitException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.php', 'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php', 'PHPUnit\\Framework\\MockObject\\Invocation' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Invocation.php', 'PHPUnit\\Framework\\MockObject\\InvocationHandler' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/InvocationHandler.php', 'PHPUnit\\Framework\\MockObject\\MatchBuilderNotFoundException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php', 'PHPUnit\\Framework\\MockObject\\Matcher' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Matcher.php', 'PHPUnit\\Framework\\MockObject\\MatcherAlreadyRegisteredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php', 'PHPUnit\\Framework\\MockObject\\Method' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/Method.php', 'PHPUnit\\Framework\\MockObject\\MethodCannotBeConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\MethodNameAlreadyConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php', 'PHPUnit\\Framework\\MockObject\\MethodNameNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\MethodParametersAlreadyConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\MockBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php', 'PHPUnit\\Framework\\MockObject\\MockObject' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.php', 'PHPUnit\\Framework\\MockObject\\MockObjectApi' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php', 'PHPUnit\\Framework\\MockObject\\MockObjectInternal' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php', 'PHPUnit\\Framework\\MockObject\\NeverReturningMethodException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.php', 'PHPUnit\\Framework\\MockObject\\NoMoreReturnValuesConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\ProxiedCloneMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.php', 'PHPUnit\\Framework\\MockObject\\ReturnValueGenerator' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.php', 'PHPUnit\\Framework\\MockObject\\ReturnValueNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php', 'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.php', 'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.php', 'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.php', 'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.php', 'PHPUnit\\Framework\\MockObject\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php', 'PHPUnit\\Framework\\MockObject\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/Stub.php', 'PHPUnit\\Framework\\MockObject\\StubApi' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/StubApi.php', 'PHPUnit\\Framework\\MockObject\\StubInternal' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.php', 'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Exception.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php', 'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php', 'PHPUnit\\Framework\\NoChildTestSuiteException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php', 'PHPUnit\\Framework\\PhptAssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php', 'PHPUnit\\Framework\\ProcessIsolationException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php', 'PHPUnit\\Framework\\Reorderable' => $vendorDir . '/phpunit/phpunit/src/Framework/Reorderable.php', 'PHPUnit\\Framework\\SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php', 'PHPUnit\\Framework\\SkippedTest' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTest.php', 'PHPUnit\\Framework\\SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.php', 'PHPUnit\\Framework\\SkippedWithMessageException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.php', 'PHPUnit\\Framework\\Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Test.php', 'PHPUnit\\Framework\\TestBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/TestBuilder.php', 'PHPUnit\\Framework\\TestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/TestCase.php', 'PHPUnit\\Framework\\TestRunner' => $vendorDir . '/phpunit/phpunit/src/Framework/TestRunner.php', 'PHPUnit\\Framework\\TestSize\\Known' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Known.php', 'PHPUnit\\Framework\\TestSize\\Large' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Large.php', 'PHPUnit\\Framework\\TestSize\\Medium' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Medium.php', 'PHPUnit\\Framework\\TestSize\\Small' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Small.php', 'PHPUnit\\Framework\\TestSize\\TestSize' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/TestSize.php', 'PHPUnit\\Framework\\TestSize\\Unknown' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Unknown.php', 'PHPUnit\\Framework\\TestStatus\\Deprecation' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Deprecation.php', 'PHPUnit\\Framework\\TestStatus\\Error' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Error.php', 'PHPUnit\\Framework\\TestStatus\\Failure' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Failure.php', 'PHPUnit\\Framework\\TestStatus\\Incomplete' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Incomplete.php', 'PHPUnit\\Framework\\TestStatus\\Known' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Known.php', 'PHPUnit\\Framework\\TestStatus\\Notice' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Notice.php', 'PHPUnit\\Framework\\TestStatus\\Risky' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Risky.php', 'PHPUnit\\Framework\\TestStatus\\Skipped' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Skipped.php', 'PHPUnit\\Framework\\TestStatus\\Success' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Success.php', 'PHPUnit\\Framework\\TestStatus\\TestStatus' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/TestStatus.php', 'PHPUnit\\Framework\\TestStatus\\Unknown' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Unknown.php', 'PHPUnit\\Framework\\TestStatus\\Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Warning.php', 'PHPUnit\\Framework\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite.php', 'PHPUnit\\Framework\\TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php', 'PHPUnit\\Framework\\UnknownClassOrInterfaceException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php', 'PHPUnit\\Framework\\UnknownTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/UnknownTypeException.php', 'PHPUnit\\Logging\\EventLogger' => $vendorDir . '/phpunit/phpunit/src/Logging/EventLogger.php', 'PHPUnit\\Logging\\JUnit\\JunitXmlLogger' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/JunitXmlLogger.php', 'PHPUnit\\Logging\\JUnit\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/Subscriber.php', 'PHPUnit\\Logging\\JUnit\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestPreparationFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestPreparationStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestPrintedUnexpectedOutputSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPrintedUnexpectedOutputSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestRunnerExecutionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestRunnerExecutionFinishedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestSuiteFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteFinishedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestSuiteStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteStartedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/Subscriber.php', 'PHPUnit\\Logging\\TeamCity\\TeamCityLogger' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/TeamCityLogger.php', 'PHPUnit\\Logging\\TeamCity\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestRunnerExecutionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestRunnerExecutionFinishedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSuiteBeforeFirstTestMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteBeforeFirstTestMethodErroredSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSuiteFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSuiteSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteSkippedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSuiteStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\HtmlRenderer' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/HtmlRenderer.php', 'PHPUnit\\Logging\\TestDox\\NamePrettifier' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/NamePrettifier.php', 'PHPUnit\\Logging\\TestDox\\PlainTextRenderer' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/PlainTextRenderer.php', 'PHPUnit\\Logging\\TestDox\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.php', 'PHPUnit\\Logging\\TestDox\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestPassedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestResult' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResult.php', 'PHPUnit\\Logging\\TestDox\\TestResultCollection' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php', 'PHPUnit\\Logging\\TestDox\\TestResultCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php', 'PHPUnit\\Logging\\TestDox\\TestResultCollector' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollector.php', 'PHPUnit\\Logging\\TestDox\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitErrorSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php', 'PHPUnit\\Metadata\\After' => $vendorDir . '/phpunit/phpunit/src/Metadata/After.php', 'PHPUnit\\Metadata\\AfterClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/AfterClass.php', 'PHPUnit\\Metadata\\Annotation\\Parser\\DocBlock' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/Annotation/DocBlock.php', 'PHPUnit\\Metadata\\Annotation\\Parser\\Registry' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/Annotation/Registry.php', 'PHPUnit\\Metadata\\AnnotationsAreNotSupportedForInternalClassesException' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.php', 'PHPUnit\\Metadata\\Api\\CodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/CodeCoverage.php', 'PHPUnit\\Metadata\\Api\\DataProvider' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/DataProvider.php', 'PHPUnit\\Metadata\\Api\\Dependencies' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/Dependencies.php', 'PHPUnit\\Metadata\\Api\\Groups' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/Groups.php', 'PHPUnit\\Metadata\\Api\\HookMethods' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/HookMethods.php', 'PHPUnit\\Metadata\\Api\\Requirements' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/Requirements.php', 'PHPUnit\\Metadata\\BackupGlobals' => $vendorDir . '/phpunit/phpunit/src/Metadata/BackupGlobals.php', 'PHPUnit\\Metadata\\BackupStaticProperties' => $vendorDir . '/phpunit/phpunit/src/Metadata/BackupStaticProperties.php', 'PHPUnit\\Metadata\\Before' => $vendorDir . '/phpunit/phpunit/src/Metadata/Before.php', 'PHPUnit\\Metadata\\BeforeClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/BeforeClass.php', 'PHPUnit\\Metadata\\Covers' => $vendorDir . '/phpunit/phpunit/src/Metadata/Covers.php', 'PHPUnit\\Metadata\\CoversClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/CoversClass.php', 'PHPUnit\\Metadata\\CoversDefaultClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/CoversDefaultClass.php', 'PHPUnit\\Metadata\\CoversFunction' => $vendorDir . '/phpunit/phpunit/src/Metadata/CoversFunction.php', 'PHPUnit\\Metadata\\CoversNothing' => $vendorDir . '/phpunit/phpunit/src/Metadata/CoversNothing.php', 'PHPUnit\\Metadata\\DataProvider' => $vendorDir . '/phpunit/phpunit/src/Metadata/DataProvider.php', 'PHPUnit\\Metadata\\DependsOnClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/DependsOnClass.php', 'PHPUnit\\Metadata\\DependsOnMethod' => $vendorDir . '/phpunit/phpunit/src/Metadata/DependsOnMethod.php', 'PHPUnit\\Metadata\\DoesNotPerformAssertions' => $vendorDir . '/phpunit/phpunit/src/Metadata/DoesNotPerformAssertions.php', 'PHPUnit\\Metadata\\Exception' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/Exception.php', 'PHPUnit\\Metadata\\ExcludeGlobalVariableFromBackup' => $vendorDir . '/phpunit/phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.php', 'PHPUnit\\Metadata\\ExcludeStaticPropertyFromBackup' => $vendorDir . '/phpunit/phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.php', 'PHPUnit\\Metadata\\Group' => $vendorDir . '/phpunit/phpunit/src/Metadata/Group.php', 'PHPUnit\\Metadata\\IgnoreClassForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Metadata/IgnoreClassForCodeCoverage.php', 'PHPUnit\\Metadata\\IgnoreDeprecations' => $vendorDir . '/phpunit/phpunit/src/Metadata/IgnoreDeprecations.php', 'PHPUnit\\Metadata\\IgnoreFunctionForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Metadata/IgnoreFunctionForCodeCoverage.php', 'PHPUnit\\Metadata\\IgnoreMethodForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Metadata/IgnoreMethodForCodeCoverage.php', 'PHPUnit\\Metadata\\InvalidAttributeException' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/InvalidAttributeException.php', 'PHPUnit\\Metadata\\InvalidVersionRequirementException' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/InvalidVersionRequirementException.php', 'PHPUnit\\Metadata\\Metadata' => $vendorDir . '/phpunit/phpunit/src/Metadata/Metadata.php', 'PHPUnit\\Metadata\\MetadataCollection' => $vendorDir . '/phpunit/phpunit/src/Metadata/MetadataCollection.php', 'PHPUnit\\Metadata\\MetadataCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Metadata/MetadataCollectionIterator.php', 'PHPUnit\\Metadata\\NoVersionRequirementException' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/NoVersionRequirementException.php', 'PHPUnit\\Metadata\\Parser\\AnnotationParser' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/AnnotationParser.php', 'PHPUnit\\Metadata\\Parser\\AttributeParser' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/AttributeParser.php', 'PHPUnit\\Metadata\\Parser\\CachingParser' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/CachingParser.php', 'PHPUnit\\Metadata\\Parser\\Parser' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/Parser.php', 'PHPUnit\\Metadata\\Parser\\ParserChain' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/ParserChain.php', 'PHPUnit\\Metadata\\Parser\\Registry' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/Registry.php', 'PHPUnit\\Metadata\\PostCondition' => $vendorDir . '/phpunit/phpunit/src/Metadata/PostCondition.php', 'PHPUnit\\Metadata\\PreCondition' => $vendorDir . '/phpunit/phpunit/src/Metadata/PreCondition.php', 'PHPUnit\\Metadata\\PreserveGlobalState' => $vendorDir . '/phpunit/phpunit/src/Metadata/PreserveGlobalState.php', 'PHPUnit\\Metadata\\ReflectionException' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/ReflectionException.php', 'PHPUnit\\Metadata\\RequiresFunction' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresFunction.php', 'PHPUnit\\Metadata\\RequiresMethod' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresMethod.php', 'PHPUnit\\Metadata\\RequiresOperatingSystem' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresOperatingSystem.php', 'PHPUnit\\Metadata\\RequiresOperatingSystemFamily' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresOperatingSystemFamily.php', 'PHPUnit\\Metadata\\RequiresPhp' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresPhp.php', 'PHPUnit\\Metadata\\RequiresPhpExtension' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresPhpExtension.php', 'PHPUnit\\Metadata\\RequiresPhpunit' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresPhpunit.php', 'PHPUnit\\Metadata\\RequiresSetting' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresSetting.php', 'PHPUnit\\Metadata\\RunClassInSeparateProcess' => $vendorDir . '/phpunit/phpunit/src/Metadata/RunClassInSeparateProcess.php', 'PHPUnit\\Metadata\\RunInSeparateProcess' => $vendorDir . '/phpunit/phpunit/src/Metadata/RunInSeparateProcess.php', 'PHPUnit\\Metadata\\RunTestsInSeparateProcesses' => $vendorDir . '/phpunit/phpunit/src/Metadata/RunTestsInSeparateProcesses.php', 'PHPUnit\\Metadata\\Test' => $vendorDir . '/phpunit/phpunit/src/Metadata/Test.php', 'PHPUnit\\Metadata\\TestDox' => $vendorDir . '/phpunit/phpunit/src/Metadata/TestDox.php', 'PHPUnit\\Metadata\\TestWith' => $vendorDir . '/phpunit/phpunit/src/Metadata/TestWith.php', 'PHPUnit\\Metadata\\Uses' => $vendorDir . '/phpunit/phpunit/src/Metadata/Uses.php', 'PHPUnit\\Metadata\\UsesClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/UsesClass.php', 'PHPUnit\\Metadata\\UsesDefaultClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/UsesDefaultClass.php', 'PHPUnit\\Metadata\\UsesFunction' => $vendorDir . '/phpunit/phpunit/src/Metadata/UsesFunction.php', 'PHPUnit\\Metadata\\Version\\ComparisonRequirement' => $vendorDir . '/phpunit/phpunit/src/Metadata/Version/ComparisonRequirement.php', 'PHPUnit\\Metadata\\Version\\ConstraintRequirement' => $vendorDir . '/phpunit/phpunit/src/Metadata/Version/ConstraintRequirement.php', 'PHPUnit\\Metadata\\Version\\Requirement' => $vendorDir . '/phpunit/phpunit/src/Metadata/Version/Requirement.php', 'PHPUnit\\Metadata\\WithoutErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Metadata/WithoutErrorHandler.php', 'PHPUnit\\Runner\\Baseline\\Baseline' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Baseline.php', 'PHPUnit\\Runner\\Baseline\\CannotLoadBaselineException' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php', 'PHPUnit\\Runner\\Baseline\\FileDoesNotHaveLineException' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.php', 'PHPUnit\\Runner\\Baseline\\Generator' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Generator.php', 'PHPUnit\\Runner\\Baseline\\Issue' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Issue.php', 'PHPUnit\\Runner\\Baseline\\Reader' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Reader.php', 'PHPUnit\\Runner\\Baseline\\RelativePathCalculator' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/RelativePathCalculator.php', 'PHPUnit\\Runner\\Baseline\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/Subscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.php', 'PHPUnit\\Runner\\Baseline\\Writer' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Writer.php', 'PHPUnit\\Runner\\ClassCannotBeFoundException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ClassCannotBeFoundException.php', 'PHPUnit\\Runner\\ClassDoesNotExtendTestCaseException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.php', 'PHPUnit\\Runner\\ClassIsAbstractException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ClassIsAbstractException.php', 'PHPUnit\\Runner\\CodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Runner/CodeCoverage.php', 'PHPUnit\\Runner\\CodeCoverageFileExistsException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/CodeCoverageFileExistsException.php', 'PHPUnit\\Runner\\DirectoryDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php', 'PHPUnit\\Runner\\ErrorException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ErrorException.php', 'PHPUnit\\Runner\\ErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Runner/ErrorHandler.php', 'PHPUnit\\Runner\\Exception' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/Exception.php', 'PHPUnit\\Runner\\Extension\\Extension' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/Extension.php', 'PHPUnit\\Runner\\Extension\\ExtensionBootstrapper' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/ExtensionBootstrapper.php', 'PHPUnit\\Runner\\Extension\\Facade' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/Facade.php', 'PHPUnit\\Runner\\Extension\\ParameterCollection' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/ParameterCollection.php', 'PHPUnit\\Runner\\Extension\\PharLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/PharLoader.php', 'PHPUnit\\Runner\\FileDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/FileDoesNotExistException.php', 'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php', 'PHPUnit\\Runner\\Filter\\Factory' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Factory.php', 'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php', 'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php', 'PHPUnit\\Runner\\Filter\\NameFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php', 'PHPUnit\\Runner\\Filter\\TestIdFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/TestIdFilterIterator.php', 'PHPUnit\\Runner\\GarbageCollection\\ExecutionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.php', 'PHPUnit\\Runner\\GarbageCollection\\ExecutionStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php', 'PHPUnit\\Runner\\GarbageCollection\\GarbageCollectionHandler' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php', 'PHPUnit\\Runner\\GarbageCollection\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php', 'PHPUnit\\Runner\\GarbageCollection\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Runner\\InvalidOrderException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/InvalidOrderException.php', 'PHPUnit\\Runner\\InvalidPhptFileException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/InvalidPhptFileException.php', 'PHPUnit\\Runner\\ParameterDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ParameterDoesNotExistException.php', 'PHPUnit\\Runner\\PhptExternalFileCannotBeLoadedException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.php', 'PHPUnit\\Runner\\PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Runner/PhptTestCase.php', 'PHPUnit\\Runner\\ResultCache\\DefaultResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.php', 'PHPUnit\\Runner\\ResultCache\\NullResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/NullResultCache.php', 'PHPUnit\\Runner\\ResultCache\\ResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/ResultCache.php', 'PHPUnit\\Runner\\ResultCache\\ResultCacheHandler' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/ResultCacheHandler.php', 'PHPUnit\\Runner\\ResultCache\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/Subscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestSuiteFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestSuiteStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php', 'PHPUnit\\Runner\\TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php', 'PHPUnit\\Runner\\TestSuiteSorter' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php', 'PHPUnit\\Runner\\UnsupportedPhptSectionException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/UnsupportedPhptSectionException.php', 'PHPUnit\\Runner\\Version' => $vendorDir . '/phpunit/phpunit/src/Runner/Version.php', 'PHPUnit\\TestRunner\\TestResult\\AfterTestClassMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/AfterTestClassMethodErroredSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\BeforeTestClassMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\Collector' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Collector.php', 'PHPUnit\\TestRunner\\TestResult\\ExecutionStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\Facade' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Facade.php', 'PHPUnit\\TestRunner\\TestResult\\Issues\\Issue' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Issue.php', 'PHPUnit\\TestRunner\\TestResult\\PassedTests' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/PassedTests.php', 'PHPUnit\\TestRunner\\TestResult\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/Subscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestResult' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/TestResult.php', 'PHPUnit\\TestRunner\\TestResult\\TestRunnerTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestRunnerTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestSuiteFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestSuiteSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestSuiteStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredErrorSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitErrorSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php', 'PHPUnit\\TextUI\\Application' => $vendorDir . '/phpunit/phpunit/src/TextUI/Application.php', 'PHPUnit\\TextUI\\CannotOpenSocketException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/CannotOpenSocketException.php', 'PHPUnit\\TextUI\\CliArguments\\Builder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Builder.php', 'PHPUnit\\TextUI\\CliArguments\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Configuration.php', 'PHPUnit\\TextUI\\CliArguments\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Exception.php', 'PHPUnit\\TextUI\\CliArguments\\XmlConfigurationFileFinder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.php', 'PHPUnit\\TextUI\\Command\\AtLeastVersionCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.php', 'PHPUnit\\TextUI\\Command\\CheckPhpConfigurationCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/CheckPhpConfigurationCommand.php', 'PHPUnit\\TextUI\\Command\\Command' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Command.php', 'PHPUnit\\TextUI\\Command\\GenerateConfigurationCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php', 'PHPUnit\\TextUI\\Command\\ListGroupsCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ListGroupsCommand.php', 'PHPUnit\\TextUI\\Command\\ListTestSuitesCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.php', 'PHPUnit\\TextUI\\Command\\ListTestsAsTextCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php', 'PHPUnit\\TextUI\\Command\\ListTestsAsXmlCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.php', 'PHPUnit\\TextUI\\Command\\MigrateConfigurationCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.php', 'PHPUnit\\TextUI\\Command\\Result' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Result.php', 'PHPUnit\\TextUI\\Command\\ShowHelpCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ShowHelpCommand.php', 'PHPUnit\\TextUI\\Command\\ShowVersionCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ShowVersionCommand.php', 'PHPUnit\\TextUI\\Command\\VersionCheckCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/VersionCheckCommand.php', 'PHPUnit\\TextUI\\Command\\WarmCodeCoverageCacheCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php', 'PHPUnit\\TextUI\\Configuration\\Builder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Builder.php', 'PHPUnit\\TextUI\\Configuration\\CodeCoverageFilterRegistry' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.php', 'PHPUnit\\TextUI\\Configuration\\CodeCoverageReportNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.php', 'PHPUnit\\TextUI\\Configuration\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Configuration.php', 'PHPUnit\\TextUI\\Configuration\\ConfigurationCannotBeBuiltException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.php', 'PHPUnit\\TextUI\\Configuration\\Constant' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Constant.php', 'PHPUnit\\TextUI\\Configuration\\ConstantCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollection.php', 'PHPUnit\\TextUI\\Configuration\\ConstantCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\Directory' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Directory.php', 'PHPUnit\\TextUI\\Configuration\\DirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollection.php', 'PHPUnit\\TextUI\\Configuration\\DirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/Exception.php', 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrap' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.php', 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrapCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php', 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrapCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\File' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/File.php', 'PHPUnit\\TextUI\\Configuration\\FileCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollection.php', 'PHPUnit\\TextUI\\Configuration\\FileCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\FilterDirectory' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectory.php', 'PHPUnit\\TextUI\\Configuration\\FilterDirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.php', 'PHPUnit\\TextUI\\Configuration\\FilterDirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\FilterNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.php', 'PHPUnit\\TextUI\\Configuration\\Group' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Group.php', 'PHPUnit\\TextUI\\Configuration\\GroupCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollection.php', 'PHPUnit\\TextUI\\Configuration\\GroupCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\IniSetting' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSetting.php', 'PHPUnit\\TextUI\\Configuration\\IniSettingCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollection.php', 'PHPUnit\\TextUI\\Configuration\\IniSettingCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\LoggingNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.php', 'PHPUnit\\TextUI\\Configuration\\Merger' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Merger.php', 'PHPUnit\\TextUI\\Configuration\\NoBaselineException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php', 'PHPUnit\\TextUI\\Configuration\\NoBootstrapException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php', 'PHPUnit\\TextUI\\Configuration\\NoCacheDirectoryException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.php', 'PHPUnit\\TextUI\\Configuration\\NoCliArgumentException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php', 'PHPUnit\\TextUI\\Configuration\\NoConfigurationFileException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.php', 'PHPUnit\\TextUI\\Configuration\\NoCoverageCacheDirectoryException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.php', 'PHPUnit\\TextUI\\Configuration\\NoCustomCssFileException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.php', 'PHPUnit\\TextUI\\Configuration\\NoDefaultTestSuiteException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.php', 'PHPUnit\\TextUI\\Configuration\\NoPharExtensionDirectoryException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.php', 'PHPUnit\\TextUI\\Configuration\\Php' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Php.php', 'PHPUnit\\TextUI\\Configuration\\PhpHandler' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/PhpHandler.php', 'PHPUnit\\TextUI\\Configuration\\Registry' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Registry.php', 'PHPUnit\\TextUI\\Configuration\\Source' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Source.php', 'PHPUnit\\TextUI\\Configuration\\SourceFilter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/SourceFilter.php', 'PHPUnit\\TextUI\\Configuration\\SourceMapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/SourceMapper.php', 'PHPUnit\\TextUI\\Configuration\\TestDirectory' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectory.php', 'PHPUnit\\TextUI\\Configuration\\TestDirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.php', 'PHPUnit\\TextUI\\Configuration\\TestDirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\TestFile' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFile.php', 'PHPUnit\\TextUI\\Configuration\\TestFileCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollection.php', 'PHPUnit\\TextUI\\Configuration\\TestFileCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuite.php', 'PHPUnit\\TextUI\\Configuration\\TestSuiteBuilder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/TestSuiteBuilder.php', 'PHPUnit\\TextUI\\Configuration\\TestSuiteCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.php', 'PHPUnit\\TextUI\\Configuration\\TestSuiteCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\Variable' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Variable.php', 'PHPUnit\\TextUI\\Configuration\\VariableCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollection.php', 'PHPUnit\\TextUI\\Configuration\\VariableCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php', 'PHPUnit\\TextUI\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/Exception.php', 'PHPUnit\\TextUI\\Help' => $vendorDir . '/phpunit/phpunit/src/TextUI/Help.php', 'PHPUnit\\TextUI\\InvalidSocketException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/InvalidSocketException.php', 'PHPUnit\\TextUI\\Output\\DefaultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Printer/DefaultPrinter.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\BeforeTestClassMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\ProgressPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestRunnerExecutionStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredErrorSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpunitDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpunitWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ResultPrinter.php', 'PHPUnit\\TextUI\\Output\\Default\\UnexpectedOutputPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php', 'PHPUnit\\TextUI\\Output\\Facade' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Facade.php', 'PHPUnit\\TextUI\\Output\\NullPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Printer/NullPrinter.php', 'PHPUnit\\TextUI\\Output\\Printer' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Printer/Printer.php', 'PHPUnit\\TextUI\\Output\\SummaryPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/SummaryPrinter.php', 'PHPUnit\\TextUI\\Output\\TestDox\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/TestDox/ResultPrinter.php', 'PHPUnit\\TextUI\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php', 'PHPUnit\\TextUI\\ShellExitCodeCalculator' => $vendorDir . '/phpunit/phpunit/src/TextUI/ShellExitCodeCalculator.php', 'PHPUnit\\TextUI\\TestDirectoryNotFoundException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php', 'PHPUnit\\TextUI\\TestFileNotFoundException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php', 'PHPUnit\\TextUI\\TestRunner' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestRunner.php', 'PHPUnit\\TextUI\\TestSuiteFilterProcessor' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestSuiteFilterProcessor.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CannotFindSchemaException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Cobertura' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Html' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Php' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Xml' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Configuration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\ConvertLogTypes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCloverToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCrap4jToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageHtmlToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoveragePhpToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageTextToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageXmlToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\DefaultConfiguration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Exception.php', 'PHPUnit\\TextUI\\XmlConfiguration\\FailedSchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Generator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Generator.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Groups' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Groups.php', 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCacheDirectoryAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCoverageElement' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.php', 'PHPUnit\\TextUI\\XmlConfiguration\\LoadedFromFileConfiguration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Loader' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Loader.php', 'PHPUnit\\TextUI\\XmlConfiguration\\LogToReportMigration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Junit' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Logging' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Logging.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TeamCity' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Html' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Migration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Migrator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromFilterWhitelistToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromRootToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveCoverageDirectoriesToSource' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistExcludesToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistIncludesToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\PHPUnit' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/PHPUnit.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveBeStrictAboutTodoAnnotatedTestsAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheResultFileAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheTokensAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveConversionToExceptionsAttributes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCoverageElementCacheDirectoryAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCoverageElementProcessUncoveredFilesAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveEmptyFilter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveListeners' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLogTypes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLoggingElements' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveNoInteractionAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemovePrinterAttributes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveTestDoxGroupsElement' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveTestSuiteLoaderAttributes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveVerboseAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RenameBackupStaticAttributesAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RenameBeStrictAboutCoversAnnotationAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RenameForceCoversAnnotationAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaDetector' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaFinder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaFinder.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SnapshotNodeList' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SuccessfulSchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.php', 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteMapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.php', 'PHPUnit\\TextUI\\XmlConfiguration\\UpdateSchemaLocation' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.php', 'PHPUnit\\TextUI\\XmlConfiguration\\ValidationResult' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Validator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php', 'PHPUnit\\Util\\Cloner' => $vendorDir . '/phpunit/phpunit/src/Util/Cloner.php', 'PHPUnit\\Util\\Color' => $vendorDir . '/phpunit/phpunit/src/Util/Color.php', 'PHPUnit\\Util\\Exception' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/Exception.php', 'PHPUnit\\Util\\ExcludeList' => $vendorDir . '/phpunit/phpunit/src/Util/ExcludeList.php', 'PHPUnit\\Util\\Exporter' => $vendorDir . '/phpunit/phpunit/src/Util/Exporter.php', 'PHPUnit\\Util\\Filesystem' => $vendorDir . '/phpunit/phpunit/src/Util/Filesystem.php', 'PHPUnit\\Util\\Filter' => $vendorDir . '/phpunit/phpunit/src/Util/Filter.php', 'PHPUnit\\Util\\GlobalState' => $vendorDir . '/phpunit/phpunit/src/Util/GlobalState.php', 'PHPUnit\\Util\\Http\\Downloader' => $vendorDir . '/phpunit/phpunit/src/Util/Http/Downloader.php', 'PHPUnit\\Util\\Http\\PhpDownloader' => $vendorDir . '/phpunit/phpunit/src/Util/Http/PhpDownloader.php', 'PHPUnit\\Util\\InvalidDirectoryException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/InvalidDirectoryException.php', 'PHPUnit\\Util\\InvalidJsonException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/InvalidJsonException.php', 'PHPUnit\\Util\\InvalidVersionOperatorException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/InvalidVersionOperatorException.php', 'PHPUnit\\Util\\Json' => $vendorDir . '/phpunit/phpunit/src/Util/Json.php', 'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php', 'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php', 'PHPUnit\\Util\\PHP\\PhpProcessException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/PhpProcessException.php', 'PHPUnit\\Util\\Reflection' => $vendorDir . '/phpunit/phpunit/src/Util/Reflection.php', 'PHPUnit\\Util\\Test' => $vendorDir . '/phpunit/phpunit/src/Util/Test.php', 'PHPUnit\\Util\\ThrowableToStringMapper' => $vendorDir . '/phpunit/phpunit/src/Util/ThrowableToStringMapper.php', 'PHPUnit\\Util\\VersionComparisonOperator' => $vendorDir . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php', 'PHPUnit\\Util\\Xml' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Xml.php', 'PHPUnit\\Util\\Xml\\Loader' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Loader.php', 'PHPUnit\\Util\\Xml\\XmlException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/XmlException.php', 'PharIo\\Manifest\\Application' => $vendorDir . '/phar-io/manifest/src/values/Application.php', 'PharIo\\Manifest\\ApplicationName' => $vendorDir . '/phar-io/manifest/src/values/ApplicationName.php', 'PharIo\\Manifest\\Author' => $vendorDir . '/phar-io/manifest/src/values/Author.php', 'PharIo\\Manifest\\AuthorCollection' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollection.php', 'PharIo\\Manifest\\AuthorCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollectionIterator.php', 'PharIo\\Manifest\\AuthorElement' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElement.php', 'PharIo\\Manifest\\AuthorElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElementCollection.php', 'PharIo\\Manifest\\BundledComponent' => $vendorDir . '/phar-io/manifest/src/values/BundledComponent.php', 'PharIo\\Manifest\\BundledComponentCollection' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollection.php', 'PharIo\\Manifest\\BundledComponentCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php', 'PharIo\\Manifest\\BundlesElement' => $vendorDir . '/phar-io/manifest/src/xml/BundlesElement.php', 'PharIo\\Manifest\\ComponentElement' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElement.php', 'PharIo\\Manifest\\ComponentElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElementCollection.php', 'PharIo\\Manifest\\ContainsElement' => $vendorDir . '/phar-io/manifest/src/xml/ContainsElement.php', 'PharIo\\Manifest\\CopyrightElement' => $vendorDir . '/phar-io/manifest/src/xml/CopyrightElement.php', 'PharIo\\Manifest\\CopyrightInformation' => $vendorDir . '/phar-io/manifest/src/values/CopyrightInformation.php', 'PharIo\\Manifest\\ElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ElementCollection.php', 'PharIo\\Manifest\\ElementCollectionException' => $vendorDir . '/phar-io/manifest/src/exceptions/ElementCollectionException.php', 'PharIo\\Manifest\\Email' => $vendorDir . '/phar-io/manifest/src/values/Email.php', 'PharIo\\Manifest\\Exception' => $vendorDir . '/phar-io/manifest/src/exceptions/Exception.php', 'PharIo\\Manifest\\ExtElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtElement.php', 'PharIo\\Manifest\\ExtElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ExtElementCollection.php', 'PharIo\\Manifest\\Extension' => $vendorDir . '/phar-io/manifest/src/values/Extension.php', 'PharIo\\Manifest\\ExtensionElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtensionElement.php', 'PharIo\\Manifest\\InvalidApplicationNameException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php', 'PharIo\\Manifest\\InvalidEmailException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidEmailException.php', 'PharIo\\Manifest\\InvalidUrlException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidUrlException.php', 'PharIo\\Manifest\\Library' => $vendorDir . '/phar-io/manifest/src/values/Library.php', 'PharIo\\Manifest\\License' => $vendorDir . '/phar-io/manifest/src/values/License.php', 'PharIo\\Manifest\\LicenseElement' => $vendorDir . '/phar-io/manifest/src/xml/LicenseElement.php', 'PharIo\\Manifest\\Manifest' => $vendorDir . '/phar-io/manifest/src/values/Manifest.php', 'PharIo\\Manifest\\ManifestDocument' => $vendorDir . '/phar-io/manifest/src/xml/ManifestDocument.php', 'PharIo\\Manifest\\ManifestDocumentException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php', 'PharIo\\Manifest\\ManifestDocumentLoadingException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php', 'PharIo\\Manifest\\ManifestDocumentMapper' => $vendorDir . '/phar-io/manifest/src/ManifestDocumentMapper.php', 'PharIo\\Manifest\\ManifestDocumentMapperException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php', 'PharIo\\Manifest\\ManifestElement' => $vendorDir . '/phar-io/manifest/src/xml/ManifestElement.php', 'PharIo\\Manifest\\ManifestElementException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestElementException.php', 'PharIo\\Manifest\\ManifestLoader' => $vendorDir . '/phar-io/manifest/src/ManifestLoader.php', 'PharIo\\Manifest\\ManifestLoaderException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php', 'PharIo\\Manifest\\ManifestSerializer' => $vendorDir . '/phar-io/manifest/src/ManifestSerializer.php', 'PharIo\\Manifest\\NoEmailAddressException' => $vendorDir . '/phar-io/manifest/src/exceptions/NoEmailAddressException.php', 'PharIo\\Manifest\\PhpElement' => $vendorDir . '/phar-io/manifest/src/xml/PhpElement.php', 'PharIo\\Manifest\\PhpExtensionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpExtensionRequirement.php', 'PharIo\\Manifest\\PhpVersionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpVersionRequirement.php', 'PharIo\\Manifest\\Requirement' => $vendorDir . '/phar-io/manifest/src/values/Requirement.php', 'PharIo\\Manifest\\RequirementCollection' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollection.php', 'PharIo\\Manifest\\RequirementCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollectionIterator.php', 'PharIo\\Manifest\\RequiresElement' => $vendorDir . '/phar-io/manifest/src/xml/RequiresElement.php', 'PharIo\\Manifest\\Type' => $vendorDir . '/phar-io/manifest/src/values/Type.php', 'PharIo\\Manifest\\Url' => $vendorDir . '/phar-io/manifest/src/values/Url.php', 'PharIo\\Version\\AbstractVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AbstractVersionConstraint.php', 'PharIo\\Version\\AndVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php', 'PharIo\\Version\\AnyVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AnyVersionConstraint.php', 'PharIo\\Version\\BuildMetaData' => $vendorDir . '/phar-io/version/src/BuildMetaData.php', 'PharIo\\Version\\ExactVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/ExactVersionConstraint.php', 'PharIo\\Version\\Exception' => $vendorDir . '/phar-io/version/src/exceptions/Exception.php', 'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php', 'PharIo\\Version\\InvalidPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php', 'PharIo\\Version\\InvalidVersionException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidVersionException.php', 'PharIo\\Version\\NoBuildMetaDataException' => $vendorDir . '/phar-io/version/src/exceptions/NoBuildMetaDataException.php', 'PharIo\\Version\\NoPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php', 'PharIo\\Version\\OrVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php', 'PharIo\\Version\\PreReleaseSuffix' => $vendorDir . '/phar-io/version/src/PreReleaseSuffix.php', 'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php', 'PharIo\\Version\\SpecificMajorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php', 'PharIo\\Version\\UnsupportedVersionConstraintException' => $vendorDir . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php', 'PharIo\\Version\\Version' => $vendorDir . '/phar-io/version/src/Version.php', 'PharIo\\Version\\VersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/VersionConstraint.php', 'PharIo\\Version\\VersionConstraintParser' => $vendorDir . '/phar-io/version/src/VersionConstraintParser.php', 'PharIo\\Version\\VersionConstraintValue' => $vendorDir . '/phar-io/version/src/VersionConstraintValue.php', 'PharIo\\Version\\VersionNumber' => $vendorDir . '/phar-io/version/src/VersionNumber.php', 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'SebastianBergmann\\CliParser\\AmbiguousOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php', 'SebastianBergmann\\CliParser\\Exception' => $vendorDir . '/sebastian/cli-parser/src/exceptions/Exception.php', 'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php', 'SebastianBergmann\\CliParser\\Parser' => $vendorDir . '/sebastian/cli-parser/src/Parser.php', 'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php', 'SebastianBergmann\\CliParser\\UnknownOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php', 'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php', 'SebastianBergmann\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php', 'SebastianBergmann\\CodeCoverage\\Data\\ProcessedCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php', 'SebastianBergmann\\CodeCoverage\\Data\\RawCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php', 'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Driver.php', 'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php', 'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Selector.php', 'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/XdebugDriver.php', 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotEnabledException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php', 'SebastianBergmann\\CodeCoverage\\Exception' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Exception.php', 'SebastianBergmann\\CodeCoverage\\FileCouldNotBeWrittenException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php', 'SebastianBergmann\\CodeCoverage\\Filter' => $vendorDir . '/phpunit/php-code-coverage/src/Filter.php', 'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php', 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php', 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php', 'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => $vendorDir . '/phpunit/php-code-coverage/src/Node/AbstractNode.php', 'SebastianBergmann\\CodeCoverage\\Node\\Builder' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Builder.php', 'SebastianBergmann\\CodeCoverage\\Node\\CrapIndex' => $vendorDir . '/phpunit/php-code-coverage/src/Node/CrapIndex.php', 'SebastianBergmann\\CodeCoverage\\Node\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Directory.php', 'SebastianBergmann\\CodeCoverage\\Node\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Node/File.php', 'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Iterator.php', 'SebastianBergmann\\CodeCoverage\\ParserException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ParserException.php', 'SebastianBergmann\\CodeCoverage\\ReflectionException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php', 'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php', 'SebastianBergmann\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Clover.php', 'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Cobertura.php', 'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Crap4j.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Colors' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Colors.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\CustomCssFile' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Facade.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php', 'SebastianBergmann\\CodeCoverage\\Report\\PHP' => $vendorDir . '/phpunit/php-code-coverage/src/Report/PHP.php', 'SebastianBergmann\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Text.php', 'SebastianBergmann\\CodeCoverage\\Report\\Thresholds' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Thresholds.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/File.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Method.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Node.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Project.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Report.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Source.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\FileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php', 'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Known' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Known.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Large' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Large.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Medium' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Medium.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Small' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Small.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\TestSize' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/TestSize.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Unknown' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Unknown.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Failure' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Failure.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Known' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Known.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Success' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Success.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\TestStatus' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/TestStatus.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Unknown' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Unknown.php', 'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php', 'SebastianBergmann\\CodeCoverage\\Util\\DirectoryCouldNotBeCreatedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php', 'SebastianBergmann\\CodeCoverage\\Util\\Filesystem' => $vendorDir . '/phpunit/php-code-coverage/src/Util/Filesystem.php', 'SebastianBergmann\\CodeCoverage\\Util\\Percentage' => $vendorDir . '/phpunit/php-code-coverage/src/Util/Percentage.php', 'SebastianBergmann\\CodeCoverage\\Version' => $vendorDir . '/phpunit/php-code-coverage/src/Version.php', 'SebastianBergmann\\CodeCoverage\\XmlException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XmlException.php', 'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => $vendorDir . '/sebastian/code-unit-reverse-lookup/src/Wizard.php', 'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => $vendorDir . '/sebastian/code-unit/src/ClassMethodUnit.php', 'SebastianBergmann\\CodeUnit\\ClassUnit' => $vendorDir . '/sebastian/code-unit/src/ClassUnit.php', 'SebastianBergmann\\CodeUnit\\CodeUnit' => $vendorDir . '/sebastian/code-unit/src/CodeUnit.php', 'SebastianBergmann\\CodeUnit\\CodeUnitCollection' => $vendorDir . '/sebastian/code-unit/src/CodeUnitCollection.php', 'SebastianBergmann\\CodeUnit\\CodeUnitCollectionIterator' => $vendorDir . '/sebastian/code-unit/src/CodeUnitCollectionIterator.php', 'SebastianBergmann\\CodeUnit\\Exception' => $vendorDir . '/sebastian/code-unit/src/exceptions/Exception.php', 'SebastianBergmann\\CodeUnit\\FileUnit' => $vendorDir . '/sebastian/code-unit/src/FileUnit.php', 'SebastianBergmann\\CodeUnit\\FunctionUnit' => $vendorDir . '/sebastian/code-unit/src/FunctionUnit.php', 'SebastianBergmann\\CodeUnit\\InterfaceMethodUnit' => $vendorDir . '/sebastian/code-unit/src/InterfaceMethodUnit.php', 'SebastianBergmann\\CodeUnit\\InterfaceUnit' => $vendorDir . '/sebastian/code-unit/src/InterfaceUnit.php', 'SebastianBergmann\\CodeUnit\\InvalidCodeUnitException' => $vendorDir . '/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php', 'SebastianBergmann\\CodeUnit\\Mapper' => $vendorDir . '/sebastian/code-unit/src/Mapper.php', 'SebastianBergmann\\CodeUnit\\NoTraitException' => $vendorDir . '/sebastian/code-unit/src/exceptions/NoTraitException.php', 'SebastianBergmann\\CodeUnit\\ReflectionException' => $vendorDir . '/sebastian/code-unit/src/exceptions/ReflectionException.php', 'SebastianBergmann\\CodeUnit\\TraitMethodUnit' => $vendorDir . '/sebastian/code-unit/src/TraitMethodUnit.php', 'SebastianBergmann\\CodeUnit\\TraitUnit' => $vendorDir . '/sebastian/code-unit/src/TraitUnit.php', 'SebastianBergmann\\Comparator\\ArrayComparator' => $vendorDir . '/sebastian/comparator/src/ArrayComparator.php', 'SebastianBergmann\\Comparator\\Comparator' => $vendorDir . '/sebastian/comparator/src/Comparator.php', 'SebastianBergmann\\Comparator\\ComparisonFailure' => $vendorDir . '/sebastian/comparator/src/ComparisonFailure.php', 'SebastianBergmann\\Comparator\\DOMNodeComparator' => $vendorDir . '/sebastian/comparator/src/DOMNodeComparator.php', 'SebastianBergmann\\Comparator\\DateTimeComparator' => $vendorDir . '/sebastian/comparator/src/DateTimeComparator.php', 'SebastianBergmann\\Comparator\\Exception' => $vendorDir . '/sebastian/comparator/src/exceptions/Exception.php', 'SebastianBergmann\\Comparator\\ExceptionComparator' => $vendorDir . '/sebastian/comparator/src/ExceptionComparator.php', 'SebastianBergmann\\Comparator\\Factory' => $vendorDir . '/sebastian/comparator/src/Factory.php', 'SebastianBergmann\\Comparator\\MockObjectComparator' => $vendorDir . '/sebastian/comparator/src/MockObjectComparator.php', 'SebastianBergmann\\Comparator\\NumericComparator' => $vendorDir . '/sebastian/comparator/src/NumericComparator.php', 'SebastianBergmann\\Comparator\\ObjectComparator' => $vendorDir . '/sebastian/comparator/src/ObjectComparator.php', 'SebastianBergmann\\Comparator\\ResourceComparator' => $vendorDir . '/sebastian/comparator/src/ResourceComparator.php', 'SebastianBergmann\\Comparator\\RuntimeException' => $vendorDir . '/sebastian/comparator/src/exceptions/RuntimeException.php', 'SebastianBergmann\\Comparator\\ScalarComparator' => $vendorDir . '/sebastian/comparator/src/ScalarComparator.php', 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => $vendorDir . '/sebastian/comparator/src/SplObjectStorageComparator.php', 'SebastianBergmann\\Comparator\\TypeComparator' => $vendorDir . '/sebastian/comparator/src/TypeComparator.php', 'SebastianBergmann\\Complexity\\Calculator' => $vendorDir . '/sebastian/complexity/src/Calculator.php', 'SebastianBergmann\\Complexity\\Complexity' => $vendorDir . '/sebastian/complexity/src/Complexity/Complexity.php', 'SebastianBergmann\\Complexity\\ComplexityCalculatingVisitor' => $vendorDir . '/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php', 'SebastianBergmann\\Complexity\\ComplexityCollection' => $vendorDir . '/sebastian/complexity/src/Complexity/ComplexityCollection.php', 'SebastianBergmann\\Complexity\\ComplexityCollectionIterator' => $vendorDir . '/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php', 'SebastianBergmann\\Complexity\\CyclomaticComplexityCalculatingVisitor' => $vendorDir . '/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php', 'SebastianBergmann\\Complexity\\Exception' => $vendorDir . '/sebastian/complexity/src/Exception/Exception.php', 'SebastianBergmann\\Complexity\\RuntimeException' => $vendorDir . '/sebastian/complexity/src/Exception/RuntimeException.php', 'SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php', 'SebastianBergmann\\Diff\\ConfigurationException' => $vendorDir . '/sebastian/diff/src/Exception/ConfigurationException.php', 'SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php', 'SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php', 'SebastianBergmann\\Diff\\Exception' => $vendorDir . '/sebastian/diff/src/Exception/Exception.php', 'SebastianBergmann\\Diff\\InvalidArgumentException' => $vendorDir . '/sebastian/diff/src/Exception/InvalidArgumentException.php', 'SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php', 'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', 'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', 'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', 'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', 'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', 'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', 'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', 'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php', 'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', 'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php', 'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php', 'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php', 'SebastianBergmann\\FileIterator\\ExcludeIterator' => $vendorDir . '/phpunit/php-file-iterator/src/ExcludeIterator.php', 'SebastianBergmann\\FileIterator\\Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php', 'SebastianBergmann\\FileIterator\\Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php', 'SebastianBergmann\\FileIterator\\Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php', 'SebastianBergmann\\GlobalState\\CodeExporter' => $vendorDir . '/sebastian/global-state/src/CodeExporter.php', 'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/exceptions/Exception.php', 'SebastianBergmann\\GlobalState\\ExcludeList' => $vendorDir . '/sebastian/global-state/src/ExcludeList.php', 'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php', 'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/exceptions/RuntimeException.php', 'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php', 'SebastianBergmann\\Invoker\\Exception' => $vendorDir . '/phpunit/php-invoker/src/exceptions/Exception.php', 'SebastianBergmann\\Invoker\\Invoker' => $vendorDir . '/phpunit/php-invoker/src/Invoker.php', 'SebastianBergmann\\Invoker\\ProcessControlExtensionNotLoadedException' => $vendorDir . '/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php', 'SebastianBergmann\\Invoker\\TimeoutException' => $vendorDir . '/phpunit/php-invoker/src/exceptions/TimeoutException.php', 'SebastianBergmann\\LinesOfCode\\Counter' => $vendorDir . '/sebastian/lines-of-code/src/Counter.php', 'SebastianBergmann\\LinesOfCode\\Exception' => $vendorDir . '/sebastian/lines-of-code/src/Exception/Exception.php', 'SebastianBergmann\\LinesOfCode\\IllogicalValuesException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php', 'SebastianBergmann\\LinesOfCode\\LineCountingVisitor' => $vendorDir . '/sebastian/lines-of-code/src/LineCountingVisitor.php', 'SebastianBergmann\\LinesOfCode\\LinesOfCode' => $vendorDir . '/sebastian/lines-of-code/src/LinesOfCode.php', 'SebastianBergmann\\LinesOfCode\\NegativeValueException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/NegativeValueException.php', 'SebastianBergmann\\LinesOfCode\\RuntimeException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/RuntimeException.php', 'SebastianBergmann\\ObjectEnumerator\\Enumerator' => $vendorDir . '/sebastian/object-enumerator/src/Enumerator.php', 'SebastianBergmann\\ObjectReflector\\ObjectReflector' => $vendorDir . '/sebastian/object-reflector/src/ObjectReflector.php', 'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php', 'SebastianBergmann\\Template\\Exception' => $vendorDir . '/phpunit/php-text-template/src/exceptions/Exception.php', 'SebastianBergmann\\Template\\InvalidArgumentException' => $vendorDir . '/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php', 'SebastianBergmann\\Template\\RuntimeException' => $vendorDir . '/phpunit/php-text-template/src/exceptions/RuntimeException.php', 'SebastianBergmann\\Template\\Template' => $vendorDir . '/phpunit/php-text-template/src/Template.php', 'SebastianBergmann\\Timer\\Duration' => $vendorDir . '/phpunit/php-timer/src/Duration.php', 'SebastianBergmann\\Timer\\Exception' => $vendorDir . '/phpunit/php-timer/src/exceptions/Exception.php', 'SebastianBergmann\\Timer\\NoActiveTimerException' => $vendorDir . '/phpunit/php-timer/src/exceptions/NoActiveTimerException.php', 'SebastianBergmann\\Timer\\ResourceUsageFormatter' => $vendorDir . '/phpunit/php-timer/src/ResourceUsageFormatter.php', 'SebastianBergmann\\Timer\\TimeSinceStartOfRequestNotAvailableException' => $vendorDir . '/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php', 'SebastianBergmann\\Timer\\Timer' => $vendorDir . '/phpunit/php-timer/src/Timer.php', 'SebastianBergmann\\Type\\CallableType' => $vendorDir . '/sebastian/type/src/type/CallableType.php', 'SebastianBergmann\\Type\\Exception' => $vendorDir . '/sebastian/type/src/exception/Exception.php', 'SebastianBergmann\\Type\\FalseType' => $vendorDir . '/sebastian/type/src/type/FalseType.php', 'SebastianBergmann\\Type\\GenericObjectType' => $vendorDir . '/sebastian/type/src/type/GenericObjectType.php', 'SebastianBergmann\\Type\\IntersectionType' => $vendorDir . '/sebastian/type/src/type/IntersectionType.php', 'SebastianBergmann\\Type\\IterableType' => $vendorDir . '/sebastian/type/src/type/IterableType.php', 'SebastianBergmann\\Type\\MixedType' => $vendorDir . '/sebastian/type/src/type/MixedType.php', 'SebastianBergmann\\Type\\NeverType' => $vendorDir . '/sebastian/type/src/type/NeverType.php', 'SebastianBergmann\\Type\\NullType' => $vendorDir . '/sebastian/type/src/type/NullType.php', 'SebastianBergmann\\Type\\ObjectType' => $vendorDir . '/sebastian/type/src/type/ObjectType.php', 'SebastianBergmann\\Type\\Parameter' => $vendorDir . '/sebastian/type/src/Parameter.php', 'SebastianBergmann\\Type\\ReflectionMapper' => $vendorDir . '/sebastian/type/src/ReflectionMapper.php', 'SebastianBergmann\\Type\\RuntimeException' => $vendorDir . '/sebastian/type/src/exception/RuntimeException.php', 'SebastianBergmann\\Type\\SimpleType' => $vendorDir . '/sebastian/type/src/type/SimpleType.php', 'SebastianBergmann\\Type\\StaticType' => $vendorDir . '/sebastian/type/src/type/StaticType.php', 'SebastianBergmann\\Type\\TrueType' => $vendorDir . '/sebastian/type/src/type/TrueType.php', 'SebastianBergmann\\Type\\Type' => $vendorDir . '/sebastian/type/src/type/Type.php', 'SebastianBergmann\\Type\\TypeName' => $vendorDir . '/sebastian/type/src/TypeName.php', 'SebastianBergmann\\Type\\UnionType' => $vendorDir . '/sebastian/type/src/type/UnionType.php', 'SebastianBergmann\\Type\\UnknownType' => $vendorDir . '/sebastian/type/src/type/UnknownType.php', 'SebastianBergmann\\Type\\VoidType' => $vendorDir . '/sebastian/type/src/type/VoidType.php', 'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php', 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'TheSeer\\Tokenizer\\Exception' => $vendorDir . '/theseer/tokenizer/src/Exception.php', 'TheSeer\\Tokenizer\\NamespaceUri' => $vendorDir . '/theseer/tokenizer/src/NamespaceUri.php', 'TheSeer\\Tokenizer\\NamespaceUriException' => $vendorDir . '/theseer/tokenizer/src/NamespaceUriException.php', 'TheSeer\\Tokenizer\\Token' => $vendorDir . '/theseer/tokenizer/src/Token.php', 'TheSeer\\Tokenizer\\TokenCollection' => $vendorDir . '/theseer/tokenizer/src/TokenCollection.php', 'TheSeer\\Tokenizer\\TokenCollectionException' => $vendorDir . '/theseer/tokenizer/src/TokenCollectionException.php', 'TheSeer\\Tokenizer\\Tokenizer' => $vendorDir . '/theseer/tokenizer/src/Tokenizer.php', 'TheSeer\\Tokenizer\\XMLSerializer' => $vendorDir . '/theseer/tokenizer/src/XMLSerializer.php', 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); $vendorDir . '/symfony/deprecation-contracts/function.php', 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', '9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php', 'b33e3d135e5d9e47d845c576147bda89' => $vendorDir . '/php-di/php-di/src/functions.php', 'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php', '38143a9afc50997d55e4815db8489d1c' => $vendorDir . '/rector/rector/bootstrap.php', ); array($vendorDir . '/mikey179/vfsstream/src/main/php'), 'Packagist\\Api\\' => array($vendorDir . '/knplabs/packagist-api/src'), ); array($baseDir . '/tests'), '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'), 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), 'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), 'SlevomatCodingStandard\\' => array($vendorDir . '/slevomat/coding-standard/SlevomatCodingStandard'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/src'), 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Plesk\\Wappspector\\' => array($baseDir . '/src'), 'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), 'PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'), 'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => array($vendorDir . '/dealerdirect/phpcodesniffer-composer-installer/src'), 'League\\MimeTypeDetection\\' => array($vendorDir . '/league/mime-type-detection/src'), 'League\\Flysystem\\Local\\' => array($vendorDir . '/league/flysystem-local'), 'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'), 'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'), 'Invoker\\' => array($vendorDir . '/php-di/invoker/src'), 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), 'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/src'), 'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'), 'DI\\' => array($vendorDir . '/php-di/php-di/src'), 'Clue\\PharComposer\\' => array($vendorDir . '/clue/phar-composer/src'), ); register(true); $filesToLoad = \Composer\Autoload\ComposerStaticInit06bf6a7b47e3e59d138b1000d1d1b8a9::$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; } } __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', '6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', '9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php', 'b33e3d135e5d9e47d845c576147bda89' => __DIR__ . '/..' . '/php-di/php-di/src/functions.php', 'ec07570ca5a812141189b1fa81503674' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert/Functions.php', '38143a9afc50997d55e4815db8489d1c' => __DIR__ . '/..' . '/rector/rector/bootstrap.php', ); public static $prefixLengthsPsr4 = array ( 'T' => array ( 'Test\\' => 5, ), 'S' => array ( '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, 'Symfony\\Contracts\\Service\\' => 26, 'Symfony\\Component\\String\\' => 25, 'Symfony\\Component\\Process\\' => 26, 'Symfony\\Component\\Finder\\' => 25, 'Symfony\\Component\\Console\\' => 26, 'SlevomatCodingStandard\\' => 23, ), 'P' => array ( 'Psr\\Log\\' => 8, 'Psr\\Http\\Message\\' => 17, 'Psr\\Http\\Client\\' => 16, 'Psr\\Container\\' => 14, 'Plesk\\Wappspector\\' => 18, 'PhpParser\\' => 10, 'PHPStan\\PhpDocParser\\' => 21, 'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => 57, ), 'L' => array ( 'League\\MimeTypeDetection\\' => 25, 'League\\Flysystem\\Local\\' => 23, 'League\\Flysystem\\' => 17, 'Laravel\\SerializableClosure\\' => 28, ), 'I' => array ( 'Invoker\\' => 8, ), 'G' => array ( 'GuzzleHttp\\Psr7\\' => 16, 'GuzzleHttp\\Promise\\' => 19, 'GuzzleHttp\\' => 11, ), 'D' => array ( 'Doctrine\\Inflector\\' => 19, 'DeepCopy\\' => 9, 'DI\\' => 3, ), 'C' => array ( 'Clue\\PharComposer\\' => 18, ), ); public static $prefixDirsPsr4 = array ( 'Test\\' => array ( 0 => __DIR__ . '/../..' . '/tests', ), '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', ), 'Symfony\\Contracts\\Service\\' => array ( 0 => __DIR__ . '/..' . '/symfony/service-contracts', ), 'Symfony\\Component\\String\\' => array ( 0 => __DIR__ . '/..' . '/symfony/string', ), 'Symfony\\Component\\Process\\' => array ( 0 => __DIR__ . '/..' . '/symfony/process', ), 'Symfony\\Component\\Finder\\' => array ( 0 => __DIR__ . '/..' . '/symfony/finder', ), 'Symfony\\Component\\Console\\' => array ( 0 => __DIR__ . '/..' . '/symfony/console', ), 'SlevomatCodingStandard\\' => array ( 0 => __DIR__ . '/..' . '/slevomat/coding-standard/SlevomatCodingStandard', ), 'Psr\\Log\\' => array ( 0 => __DIR__ . '/..' . '/psr/log/src', ), 'Psr\\Http\\Message\\' => array ( 0 => __DIR__ . '/..' . '/psr/http-factory/src', 1 => __DIR__ . '/..' . '/psr/http-message/src', ), 'Psr\\Http\\Client\\' => array ( 0 => __DIR__ . '/..' . '/psr/http-client/src', ), 'Psr\\Container\\' => array ( 0 => __DIR__ . '/..' . '/psr/container/src', ), 'Plesk\\Wappspector\\' => array ( 0 => __DIR__ . '/../..' . '/src', ), 'PhpParser\\' => array ( 0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser', ), 'PHPStan\\PhpDocParser\\' => array ( 0 => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src', ), 'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => array ( 0 => __DIR__ . '/..' . '/dealerdirect/phpcodesniffer-composer-installer/src', ), 'League\\MimeTypeDetection\\' => array ( 0 => __DIR__ . '/..' . '/league/mime-type-detection/src', ), 'League\\Flysystem\\Local\\' => array ( 0 => __DIR__ . '/..' . '/league/flysystem-local', ), 'League\\Flysystem\\' => array ( 0 => __DIR__ . '/..' . '/league/flysystem/src', ), 'Laravel\\SerializableClosure\\' => array ( 0 => __DIR__ . '/..' . '/laravel/serializable-closure/src', ), 'Invoker\\' => array ( 0 => __DIR__ . '/..' . '/php-di/invoker/src', ), 'GuzzleHttp\\Psr7\\' => array ( 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src', ), 'GuzzleHttp\\Promise\\' => array ( 0 => __DIR__ . '/..' . '/guzzlehttp/promises/src', ), 'GuzzleHttp\\' => array ( 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src', ), 'Doctrine\\Inflector\\' => array ( 0 => __DIR__ . '/..' . '/doctrine/inflector/src', ), 'DeepCopy\\' => array ( 0 => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy', ), 'DI\\' => array ( 0 => __DIR__ . '/..' . '/php-di/php-di/src', ), 'Clue\\PharComposer\\' => array ( 0 => __DIR__ . '/..' . '/clue/phar-composer/src', ), ); public static $prefixesPsr0 = array ( 'o' => array ( 'org\\bovigo\\vfs\\' => array ( 0 => __DIR__ . '/..' . '/mikey179/vfsstream/src/main/php', ), ), 'P' => array ( 'Packagist\\Api\\' => array ( 0 => __DIR__ . '/..' . '/knplabs/packagist-api/src', ), ), ); public static $classMap = array ( 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'PHPUnit\\Event\\Application\\Finished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Application/Finished.php', 'PHPUnit\\Event\\Application\\FinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Application/FinishedSubscriber.php', 'PHPUnit\\Event\\Application\\Started' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Application/Started.php', 'PHPUnit\\Event\\Application\\StartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Application/StartedSubscriber.php', 'PHPUnit\\Event\\Code\\ClassMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/ClassMethod.php', 'PHPUnit\\Event\\Code\\ComparisonFailure' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/ComparisonFailure.php', 'PHPUnit\\Event\\Code\\ComparisonFailureBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/ComparisonFailureBuilder.php', 'PHPUnit\\Event\\Code\\NoTestCaseObjectOnCallStackException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.php', 'PHPUnit\\Event\\Code\\Phpt' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/Phpt.php', 'PHPUnit\\Event\\Code\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/Test.php', 'PHPUnit\\Event\\Code\\TestCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestCollection.php', 'PHPUnit\\Event\\Code\\TestCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestCollectionIterator.php', 'PHPUnit\\Event\\Code\\TestDox' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestDox.php', 'PHPUnit\\Event\\Code\\TestDoxBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestDoxBuilder.php', 'PHPUnit\\Event\\Code\\TestMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestMethod.php', 'PHPUnit\\Event\\Code\\TestMethodBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php', 'PHPUnit\\Event\\Code\\Throwable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Throwable.php', 'PHPUnit\\Event\\Code\\ThrowableBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/ThrowableBuilder.php', 'PHPUnit\\Event\\CollectingDispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/CollectingDispatcher.php', 'PHPUnit\\Event\\DeferringDispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/DeferringDispatcher.php', 'PHPUnit\\Event\\DirectDispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/DirectDispatcher.php', 'PHPUnit\\Event\\Dispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/Dispatcher.php', 'PHPUnit\\Event\\DispatchingEmitter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Emitter/DispatchingEmitter.php', 'PHPUnit\\Event\\Emitter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Emitter/Emitter.php', 'PHPUnit\\Event\\Event' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Event.php', 'PHPUnit\\Event\\EventAlreadyAssignedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/EventAlreadyAssignedException.php', 'PHPUnit\\Event\\EventCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/EventCollection.php', 'PHPUnit\\Event\\EventCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/EventCollectionIterator.php', 'PHPUnit\\Event\\EventFacadeIsSealedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/EventFacadeIsSealedException.php', 'PHPUnit\\Event\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/Exception.php', 'PHPUnit\\Event\\Facade' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Facade.php', 'PHPUnit\\Event\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/InvalidArgumentException.php', 'PHPUnit\\Event\\InvalidEventException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/InvalidEventException.php', 'PHPUnit\\Event\\InvalidSubscriberException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/InvalidSubscriberException.php', 'PHPUnit\\Event\\MapError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/MapError.php', 'PHPUnit\\Event\\NoPreviousThrowableException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/NoPreviousThrowableException.php', 'PHPUnit\\Event\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/RuntimeException.php', 'PHPUnit\\Event\\Runtime\\OperatingSystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Runtime/OperatingSystem.php', 'PHPUnit\\Event\\Runtime\\PHP' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Runtime/PHP.php', 'PHPUnit\\Event\\Runtime\\PHPUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Runtime/PHPUnit.php', 'PHPUnit\\Event\\Runtime\\Runtime' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Runtime/Runtime.php', 'PHPUnit\\Event\\SubscribableDispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/SubscribableDispatcher.php', 'PHPUnit\\Event\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Subscriber.php', 'PHPUnit\\Event\\SubscriberTypeAlreadyRegisteredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.php', 'PHPUnit\\Event\\Telemetry\\Duration' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Duration.php', 'PHPUnit\\Event\\Telemetry\\GarbageCollectorStatus' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.php', 'PHPUnit\\Event\\Telemetry\\GarbageCollectorStatusProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.php', 'PHPUnit\\Event\\Telemetry\\HRTime' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/HRTime.php', 'PHPUnit\\Event\\Telemetry\\Info' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Info.php', 'PHPUnit\\Event\\Telemetry\\MemoryMeter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/MemoryMeter.php', 'PHPUnit\\Event\\Telemetry\\MemoryUsage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/MemoryUsage.php', 'PHPUnit\\Event\\Telemetry\\Php81GarbageCollectorStatusProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php', 'PHPUnit\\Event\\Telemetry\\Php83GarbageCollectorStatusProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.php', 'PHPUnit\\Event\\Telemetry\\Snapshot' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Snapshot.php', 'PHPUnit\\Event\\Telemetry\\StopWatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/StopWatch.php', 'PHPUnit\\Event\\Telemetry\\System' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/System.php', 'PHPUnit\\Event\\Telemetry\\SystemMemoryMeter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.php', 'PHPUnit\\Event\\Telemetry\\SystemStopWatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatch.php', 'PHPUnit\\Event\\Telemetry\\SystemStopWatchWithOffset' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.php', 'PHPUnit\\Event\\TestData\\DataFromDataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.php', 'PHPUnit\\Event\\TestData\\DataFromTestDependency' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.php', 'PHPUnit\\Event\\TestData\\MoreThanOneDataSetFromDataProviderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/MoreThanOneDataSetFromDataProviderException.php', 'PHPUnit\\Event\\TestData\\NoDataSetFromDataProviderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php', 'PHPUnit\\Event\\TestData\\TestData' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestData.php', 'PHPUnit\\Event\\TestData\\TestDataCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollection.php', 'PHPUnit\\Event\\TestData\\TestDataCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.php', 'PHPUnit\\Event\\TestRunner\\BootstrapFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinished.php', 'PHPUnit\\Event\\TestRunner\\BootstrapFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\Configured' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/Configured.php', 'PHPUnit\\Event\\TestRunner\\ConfiguredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.php', 'PHPUnit\\Event\\TestRunner\\DeprecationTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggered.php', 'PHPUnit\\Event\\TestRunner\\DeprecationTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php', 'PHPUnit\\Event\\TestRunner\\EventFacadeSealed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealed.php', 'PHPUnit\\Event\\TestRunner\\EventFacadeSealedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExecutionAborted' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAborted.php', 'PHPUnit\\Event\\TestRunner\\ExecutionAbortedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExecutionFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinished.php', 'PHPUnit\\Event\\TestRunner\\ExecutionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExecutionStarted' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStarted.php', 'PHPUnit\\Event\\TestRunner\\ExecutionStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExtensionBootstrapped' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.php', 'PHPUnit\\Event\\TestRunner\\ExtensionBootstrappedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\ExtensionLoadedFromPhar' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.php', 'PHPUnit\\Event\\TestRunner\\ExtensionLoadedFromPharSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php', 'PHPUnit\\Event\\TestRunner\\Finished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/Finished.php', 'PHPUnit\\Event\\TestRunner\\FinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/FinishedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionDisabled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionDisabledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionEnabled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionEnabledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.php', 'PHPUnit\\Event\\TestRunner\\GarbageCollectionTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php', 'PHPUnit\\Event\\TestRunner\\Started' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/Started.php', 'PHPUnit\\Event\\TestRunner\\StartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/StartedSubscriber.php', 'PHPUnit\\Event\\TestRunner\\WarningTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggered.php', 'PHPUnit\\Event\\TestRunner\\WarningTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Filtered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Filtered.php', 'PHPUnit\\Event\\TestSuite\\FilteredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/FilteredSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Finished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Finished.php', 'PHPUnit\\Event\\TestSuite\\FinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/FinishedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Loaded' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Loaded.php', 'PHPUnit\\Event\\TestSuite\\LoadedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/LoadedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Skipped' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Skipped.php', 'PHPUnit\\Event\\TestSuite\\SkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/SkippedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Sorted' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Sorted.php', 'PHPUnit\\Event\\TestSuite\\SortedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/SortedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\Started' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Started.php', 'PHPUnit\\Event\\TestSuite\\StartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/StartedSubscriber.php', 'PHPUnit\\Event\\TestSuite\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuite.php', 'PHPUnit\\Event\\TestSuite\\TestSuiteBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.php', 'PHPUnit\\Event\\TestSuite\\TestSuiteForTestClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.php', 'PHPUnit\\Event\\TestSuite\\TestSuiteForTestMethodWithDataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.php', 'PHPUnit\\Event\\TestSuite\\TestSuiteWithName' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteWithName.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodErrored' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodErrored.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodErroredSubscriber.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.php', 'PHPUnit\\Event\\Test\\AfterLastTestMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\AfterTestMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.php', 'PHPUnit\\Event\\Test\\AfterTestMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\AfterTestMethodErrored' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodErrored.php', 'PHPUnit\\Event\\Test\\AfterTestMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodErroredSubscriber.php', 'PHPUnit\\Event\\Test\\AfterTestMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinished.php', 'PHPUnit\\Event\\Test\\AfterTestMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\AssertionFailed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailed.php', 'PHPUnit\\Event\\Test\\AssertionFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailedSubscriber.php', 'PHPUnit\\Event\\Test\\AssertionSucceeded' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceeded.php', 'PHPUnit\\Event\\Test\\AssertionSucceededSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceededSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalled.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodErrored' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErrored.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErroredSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinished.php', 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalled.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodErrored' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodErrored.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodErroredSubscriber.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinished.php', 'PHPUnit\\Event\\Test\\BeforeTestMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\ComparatorRegistered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/ComparatorRegistered.php', 'PHPUnit\\Event\\Test\\ComparatorRegisteredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php', 'PHPUnit\\Event\\Test\\ConsideredRisky' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRisky.php', 'PHPUnit\\Event\\Test\\ConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRiskySubscriber.php', 'PHPUnit\\Event\\Test\\DataProviderMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalled.php', 'PHPUnit\\Event\\Test\\DataProviderMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalledSubscriber.php', 'PHPUnit\\Event\\Test\\DataProviderMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinished.php', 'PHPUnit\\Event\\Test\\DataProviderMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\DeprecationTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggered.php', 'PHPUnit\\Event\\Test\\DeprecationTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\ErrorTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggered.php', 'PHPUnit\\Event\\Test\\ErrorTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\Errored' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Errored.php', 'PHPUnit\\Event\\Test\\ErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/ErroredSubscriber.php', 'PHPUnit\\Event\\Test\\Failed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Failed.php', 'PHPUnit\\Event\\Test\\FailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/FailedSubscriber.php', 'PHPUnit\\Event\\Test\\Finished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Finished.php', 'PHPUnit\\Event\\Test\\FinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/FinishedSubscriber.php', 'PHPUnit\\Event\\Test\\MarkedIncomplete' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncomplete.php', 'PHPUnit\\Event\\Test\\MarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncompleteSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreated.php', 'PHPUnit\\Event\\Test\\MockObjectCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectForAbstractClassCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreated.php', 'PHPUnit\\Event\\Test\\MockObjectForAbstractClassCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectForIntersectionOfInterfacesCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreated.php', 'PHPUnit\\Event\\Test\\MockObjectForIntersectionOfInterfacesCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectForTraitCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreated.php', 'PHPUnit\\Event\\Test\\MockObjectForTraitCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\MockObjectFromWsdlCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreated.php', 'PHPUnit\\Event\\Test\\MockObjectFromWsdlCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\NoComparisonFailureException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/NoComparisonFailureException.php', 'PHPUnit\\Event\\Test\\NoticeTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggered.php', 'PHPUnit\\Event\\Test\\NoticeTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PartialMockObjectCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.php', 'PHPUnit\\Event\\Test\\PartialMockObjectCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\Passed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Passed.php', 'PHPUnit\\Event\\Test\\PassedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/PassedSubscriber.php', 'PHPUnit\\Event\\Test\\PhpDeprecationTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggered.php', 'PHPUnit\\Event\\Test\\PhpDeprecationTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpNoticeTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggered.php', 'PHPUnit\\Event\\Test\\PhpNoticeTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpWarningTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggered.php', 'PHPUnit\\Event\\Test\\PhpWarningTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpunitDeprecationTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggered.php', 'PHPUnit\\Event\\Test\\PhpunitDeprecationTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpunitErrorTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggered.php', 'PHPUnit\\Event\\Test\\PhpunitErrorTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PhpunitWarningTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggered.php', 'PHPUnit\\Event\\Test\\PhpunitWarningTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggeredSubscriber.php', 'PHPUnit\\Event\\Test\\PostConditionCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalled.php', 'PHPUnit\\Event\\Test\\PostConditionCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalledSubscriber.php', 'PHPUnit\\Event\\Test\\PostConditionErrored' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionErrored.php', 'PHPUnit\\Event\\Test\\PostConditionErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionErroredSubscriber.php', 'PHPUnit\\Event\\Test\\PostConditionFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinished.php', 'PHPUnit\\Event\\Test\\PostConditionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\PreConditionCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalled.php', 'PHPUnit\\Event\\Test\\PreConditionCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalledSubscriber.php', 'PHPUnit\\Event\\Test\\PreConditionErrored' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionErrored.php', 'PHPUnit\\Event\\Test\\PreConditionErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionErroredSubscriber.php', 'PHPUnit\\Event\\Test\\PreConditionFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinished.php', 'PHPUnit\\Event\\Test\\PreConditionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinishedSubscriber.php', 'PHPUnit\\Event\\Test\\PreparationFailed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailed.php', 'PHPUnit\\Event\\Test\\PreparationFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailedSubscriber.php', 'PHPUnit\\Event\\Test\\PreparationStarted' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStarted.php', 'PHPUnit\\Event\\Test\\PreparationStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStartedSubscriber.php', 'PHPUnit\\Event\\Test\\Prepared' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Prepared.php', 'PHPUnit\\Event\\Test\\PreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparedSubscriber.php', 'PHPUnit\\Event\\Test\\PrintedUnexpectedOutput' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutput.php', 'PHPUnit\\Event\\Test\\PrintedUnexpectedOutputSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutputSubscriber.php', 'PHPUnit\\Event\\Test\\Skipped' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Skipped.php', 'PHPUnit\\Event\\Test\\SkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/SkippedSubscriber.php', 'PHPUnit\\Event\\Test\\TestProxyCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php', 'PHPUnit\\Event\\Test\\TestProxyCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\TestStubCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php', 'PHPUnit\\Event\\Test\\TestStubCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\TestStubForIntersectionOfInterfacesCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.php', 'PHPUnit\\Event\\Test\\TestStubForIntersectionOfInterfacesCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.php', 'PHPUnit\\Event\\Test\\WarningTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggered.php', 'PHPUnit\\Event\\Test\\WarningTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggeredSubscriber.php', 'PHPUnit\\Event\\Tracer\\Tracer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Tracer.php', 'PHPUnit\\Event\\TypeMap' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/TypeMap.php', 'PHPUnit\\Event\\UnknownEventException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/UnknownEventException.php', 'PHPUnit\\Event\\UnknownEventTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/UnknownEventTypeException.php', 'PHPUnit\\Event\\UnknownSubscriberException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/UnknownSubscriberException.php', 'PHPUnit\\Event\\UnknownSubscriberTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/UnknownSubscriberTypeException.php', 'PHPUnit\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php', 'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.php', 'PHPUnit\\Framework\\Assert' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert.php', 'PHPUnit\\Framework\\AssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php', 'PHPUnit\\Framework\\Attributes\\After' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/After.php', 'PHPUnit\\Framework\\Attributes\\AfterClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/AfterClass.php', 'PHPUnit\\Framework\\Attributes\\BackupGlobals' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/BackupGlobals.php', 'PHPUnit\\Framework\\Attributes\\BackupStaticProperties' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/BackupStaticProperties.php', 'PHPUnit\\Framework\\Attributes\\Before' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Before.php', 'PHPUnit\\Framework\\Attributes\\BeforeClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/BeforeClass.php', 'PHPUnit\\Framework\\Attributes\\CodeCoverageIgnore' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/CodeCoverageIgnore.php', 'PHPUnit\\Framework\\Attributes\\CoversClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/CoversClass.php', 'PHPUnit\\Framework\\Attributes\\CoversFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/CoversFunction.php', 'PHPUnit\\Framework\\Attributes\\CoversNothing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/CoversNothing.php', 'PHPUnit\\Framework\\Attributes\\DataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DataProvider.php', 'PHPUnit\\Framework\\Attributes\\DataProviderExternal' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DataProviderExternal.php', 'PHPUnit\\Framework\\Attributes\\Depends' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Depends.php', 'PHPUnit\\Framework\\Attributes\\DependsExternal' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsExternal.php', 'PHPUnit\\Framework\\Attributes\\DependsExternalUsingDeepClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php', 'PHPUnit\\Framework\\Attributes\\DependsExternalUsingShallowClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php', 'PHPUnit\\Framework\\Attributes\\DependsOnClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClass.php', 'PHPUnit\\Framework\\Attributes\\DependsOnClassUsingDeepClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.php', 'PHPUnit\\Framework\\Attributes\\DependsOnClassUsingShallowClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.php', 'PHPUnit\\Framework\\Attributes\\DependsUsingDeepClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsUsingDeepClone.php', 'PHPUnit\\Framework\\Attributes\\DependsUsingShallowClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsUsingShallowClone.php', 'PHPUnit\\Framework\\Attributes\\DoesNotPerformAssertions' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php', 'PHPUnit\\Framework\\Attributes\\ExcludeGlobalVariableFromBackup' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.php', 'PHPUnit\\Framework\\Attributes\\ExcludeStaticPropertyFromBackup' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php', 'PHPUnit\\Framework\\Attributes\\Group' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Group.php', 'PHPUnit\\Framework\\Attributes\\IgnoreClassForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/IgnoreClassForCodeCoverage.php', 'PHPUnit\\Framework\\Attributes\\IgnoreDeprecations' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/IgnoreDeprecations.php', 'PHPUnit\\Framework\\Attributes\\IgnoreFunctionForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/IgnoreFunctionForCodeCoverage.php', 'PHPUnit\\Framework\\Attributes\\IgnoreMethodForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/IgnoreMethodForCodeCoverage.php', 'PHPUnit\\Framework\\Attributes\\Large' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Large.php', 'PHPUnit\\Framework\\Attributes\\Medium' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Medium.php', 'PHPUnit\\Framework\\Attributes\\PostCondition' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/PostCondition.php', 'PHPUnit\\Framework\\Attributes\\PreCondition' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/PreCondition.php', 'PHPUnit\\Framework\\Attributes\\PreserveGlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/PreserveGlobalState.php', 'PHPUnit\\Framework\\Attributes\\RequiresFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresFunction.php', 'PHPUnit\\Framework\\Attributes\\RequiresMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresMethod.php', 'PHPUnit\\Framework\\Attributes\\RequiresOperatingSystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystem.php', 'PHPUnit\\Framework\\Attributes\\RequiresOperatingSystemFamily' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.php', 'PHPUnit\\Framework\\Attributes\\RequiresPhp' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhp.php', 'PHPUnit\\Framework\\Attributes\\RequiresPhpExtension' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhpExtension.php', 'PHPUnit\\Framework\\Attributes\\RequiresPhpunit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhpunit.php', 'PHPUnit\\Framework\\Attributes\\RequiresSetting' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresSetting.php', 'PHPUnit\\Framework\\Attributes\\RunClassInSeparateProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RunClassInSeparateProcess.php', 'PHPUnit\\Framework\\Attributes\\RunInSeparateProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RunInSeparateProcess.php', 'PHPUnit\\Framework\\Attributes\\RunTestsInSeparateProcesses' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.php', 'PHPUnit\\Framework\\Attributes\\Small' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Small.php', 'PHPUnit\\Framework\\Attributes\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Test.php', 'PHPUnit\\Framework\\Attributes\\TestDox' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/TestDox.php', 'PHPUnit\\Framework\\Attributes\\TestWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/TestWith.php', 'PHPUnit\\Framework\\Attributes\\TestWithJson' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/TestWithJson.php', 'PHPUnit\\Framework\\Attributes\\Ticket' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Ticket.php', 'PHPUnit\\Framework\\Attributes\\UsesClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/UsesClass.php', 'PHPUnit\\Framework\\Attributes\\UsesFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/UsesFunction.php', 'PHPUnit\\Framework\\Attributes\\WithoutErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/WithoutErrorHandler.php', 'PHPUnit\\Framework\\CodeCoverageException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotAcceptParameterTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareBoolReturnTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareExactlyOneParameterException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareParameterTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.php', 'PHPUnit\\Framework\\ComparisonMethodDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php', 'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php', 'PHPUnit\\Framework\\Constraint\\BinaryOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php', 'PHPUnit\\Framework\\Constraint\\Callback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Callback.php', 'PHPUnit\\Framework\\Constraint\\Constraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php', 'PHPUnit\\Framework\\Constraint\\Count' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php', 'PHPUnit\\Framework\\Constraint\\DirectoryExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php', 'PHPUnit\\Framework\\Constraint\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php', 'PHPUnit\\Framework\\Constraint\\ExceptionCode' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php', 'PHPUnit\\Framework\\Constraint\\ExceptionMessageIsOrContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.php', 'PHPUnit\\Framework\\Constraint\\ExceptionMessageMatchesRegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php', 'PHPUnit\\Framework\\Constraint\\FileExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php', 'PHPUnit\\Framework\\Constraint\\GreaterThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php', 'PHPUnit\\Framework\\Constraint\\IsAnything' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php', 'PHPUnit\\Framework\\Constraint\\IsEmpty' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php', 'PHPUnit\\Framework\\Constraint\\IsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php', 'PHPUnit\\Framework\\Constraint\\IsEqualCanonicalizing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php', 'PHPUnit\\Framework\\Constraint\\IsEqualIgnoringCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php', 'PHPUnit\\Framework\\Constraint\\IsEqualWithDelta' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php', 'PHPUnit\\Framework\\Constraint\\IsFalse' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php', 'PHPUnit\\Framework\\Constraint\\IsFinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php', 'PHPUnit\\Framework\\Constraint\\IsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php', 'PHPUnit\\Framework\\Constraint\\IsInfinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php', 'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php', 'PHPUnit\\Framework\\Constraint\\IsJson' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php', 'PHPUnit\\Framework\\Constraint\\IsList' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/IsList.php', 'PHPUnit\\Framework\\Constraint\\IsNan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php', 'PHPUnit\\Framework\\Constraint\\IsNull' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php', 'PHPUnit\\Framework\\Constraint\\IsReadable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php', 'PHPUnit\\Framework\\Constraint\\IsTrue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php', 'PHPUnit\\Framework\\Constraint\\IsType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php', 'PHPUnit\\Framework\\Constraint\\IsWritable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php', 'PHPUnit\\Framework\\Constraint\\JsonMatches' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php', 'PHPUnit\\Framework\\Constraint\\LessThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php', 'PHPUnit\\Framework\\Constraint\\LogicalAnd' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php', 'PHPUnit\\Framework\\Constraint\\LogicalNot' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php', 'PHPUnit\\Framework\\Constraint\\LogicalOr' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php', 'PHPUnit\\Framework\\Constraint\\LogicalXor' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php', 'PHPUnit\\Framework\\Constraint\\ObjectEquals' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php', 'PHPUnit\\Framework\\Constraint\\ObjectHasProperty' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasProperty.php', 'PHPUnit\\Framework\\Constraint\\Operator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php', 'PHPUnit\\Framework\\Constraint\\RegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php', 'PHPUnit\\Framework\\Constraint\\SameSize' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php', 'PHPUnit\\Framework\\Constraint\\StringContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php', 'PHPUnit\\Framework\\Constraint\\StringEndsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php', 'PHPUnit\\Framework\\Constraint\\StringEqualsStringIgnoringLineEndings' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.php', 'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php', 'PHPUnit\\Framework\\Constraint\\StringStartsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php', 'PHPUnit\\Framework\\Constraint\\TraversableContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php', 'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php', 'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php', 'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php', 'PHPUnit\\Framework\\Constraint\\UnaryOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php', 'PHPUnit\\Framework\\DataProviderTestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php', 'PHPUnit\\Framework\\EmptyStringException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/EmptyStringException.php', 'PHPUnit\\Framework\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Exception.php', 'PHPUnit\\Framework\\ExecutionOrderDependency' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php', 'PHPUnit\\Framework\\ExpectationFailedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php', 'PHPUnit\\Framework\\GeneratorNotSupportedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/GeneratorNotSupportedException.php', 'PHPUnit\\Framework\\IncompleteTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php', 'PHPUnit\\Framework\\IncompleteTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.php', 'PHPUnit\\Framework\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php', 'PHPUnit\\Framework\\InvalidCoversTargetException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php', 'PHPUnit\\Framework\\InvalidDataProviderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php', 'PHPUnit\\Framework\\InvalidDependencyException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidDependencyException.php', 'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php', 'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Identity.php', 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.php', 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.php', 'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php', 'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.php', 'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php', 'PHPUnit\\Framework\\MockObject\\CannotUseOnlyMethodsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php', 'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php', 'PHPUnit\\Framework\\MockObject\\DoubledCloneMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.php', 'PHPUnit\\Framework\\MockObject\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php', 'PHPUnit\\Framework\\MockObject\\Generator\\CannotUseAddMethodsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsEnumerationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsFinalException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsReadonlyException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsReadonlyException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\DuplicateMethodException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/Exception.php', 'PHPUnit\\Framework\\MockObject\\Generator\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Generator.php', 'PHPUnit\\Framework\\MockObject\\Generator\\InvalidMethodNameException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockClass.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethod.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockMethodSet' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethodSet.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockTrait' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockTrait.php', 'PHPUnit\\Framework\\MockObject\\Generator\\MockType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockType.php', 'PHPUnit\\Framework\\MockObject\\Generator\\NameAlreadyInUseException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\OriginalConstructorInvocationRequiredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\ReflectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\SoapExtensionNotAvailableException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\TemplateLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/TemplateLoader.php', 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownClassException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownTraitException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.php', 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.php', 'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php', 'PHPUnit\\Framework\\MockObject\\Invocation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Invocation.php', 'PHPUnit\\Framework\\MockObject\\InvocationHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/InvocationHandler.php', 'PHPUnit\\Framework\\MockObject\\MatchBuilderNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php', 'PHPUnit\\Framework\\MockObject\\Matcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Matcher.php', 'PHPUnit\\Framework\\MockObject\\MatcherAlreadyRegisteredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php', 'PHPUnit\\Framework\\MockObject\\Method' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/Method.php', 'PHPUnit\\Framework\\MockObject\\MethodCannotBeConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\MethodNameAlreadyConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php', 'PHPUnit\\Framework\\MockObject\\MethodNameNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\MethodParametersAlreadyConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\MockBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php', 'PHPUnit\\Framework\\MockObject\\MockObject' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.php', 'PHPUnit\\Framework\\MockObject\\MockObjectApi' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php', 'PHPUnit\\Framework\\MockObject\\MockObjectInternal' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php', 'PHPUnit\\Framework\\MockObject\\NeverReturningMethodException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.php', 'PHPUnit\\Framework\\MockObject\\NoMoreReturnValuesConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\ProxiedCloneMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.php', 'PHPUnit\\Framework\\MockObject\\ReturnValueGenerator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.php', 'PHPUnit\\Framework\\MockObject\\ReturnValueNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php', 'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php', 'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.php', 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.php', 'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.php', 'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.php', 'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.php', 'PHPUnit\\Framework\\MockObject\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php', 'PHPUnit\\Framework\\MockObject\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/Stub.php', 'PHPUnit\\Framework\\MockObject\\StubApi' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/StubApi.php', 'PHPUnit\\Framework\\MockObject\\StubInternal' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.php', 'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Exception.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php', 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php', 'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php', 'PHPUnit\\Framework\\NoChildTestSuiteException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php', 'PHPUnit\\Framework\\PhptAssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php', 'PHPUnit\\Framework\\ProcessIsolationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php', 'PHPUnit\\Framework\\Reorderable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Reorderable.php', 'PHPUnit\\Framework\\SelfDescribing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SelfDescribing.php', 'PHPUnit\\Framework\\SkippedTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTest.php', 'PHPUnit\\Framework\\SkippedTestSuiteError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.php', 'PHPUnit\\Framework\\SkippedWithMessageException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.php', 'PHPUnit\\Framework\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Test.php', 'PHPUnit\\Framework\\TestBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestBuilder.php', 'PHPUnit\\Framework\\TestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestCase.php', 'PHPUnit\\Framework\\TestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestRunner.php', 'PHPUnit\\Framework\\TestSize\\Known' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Known.php', 'PHPUnit\\Framework\\TestSize\\Large' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Large.php', 'PHPUnit\\Framework\\TestSize\\Medium' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Medium.php', 'PHPUnit\\Framework\\TestSize\\Small' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Small.php', 'PHPUnit\\Framework\\TestSize\\TestSize' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/TestSize.php', 'PHPUnit\\Framework\\TestSize\\Unknown' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Unknown.php', 'PHPUnit\\Framework\\TestStatus\\Deprecation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Deprecation.php', 'PHPUnit\\Framework\\TestStatus\\Error' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Error.php', 'PHPUnit\\Framework\\TestStatus\\Failure' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Failure.php', 'PHPUnit\\Framework\\TestStatus\\Incomplete' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Incomplete.php', 'PHPUnit\\Framework\\TestStatus\\Known' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Known.php', 'PHPUnit\\Framework\\TestStatus\\Notice' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Notice.php', 'PHPUnit\\Framework\\TestStatus\\Risky' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Risky.php', 'PHPUnit\\Framework\\TestStatus\\Skipped' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Skipped.php', 'PHPUnit\\Framework\\TestStatus\\Success' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Success.php', 'PHPUnit\\Framework\\TestStatus\\TestStatus' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/TestStatus.php', 'PHPUnit\\Framework\\TestStatus\\Unknown' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Unknown.php', 'PHPUnit\\Framework\\TestStatus\\Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Warning.php', 'PHPUnit\\Framework\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuite.php', 'PHPUnit\\Framework\\TestSuiteIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php', 'PHPUnit\\Framework\\UnknownClassOrInterfaceException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php', 'PHPUnit\\Framework\\UnknownTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/UnknownTypeException.php', 'PHPUnit\\Logging\\EventLogger' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/EventLogger.php', 'PHPUnit\\Logging\\JUnit\\JunitXmlLogger' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/JunitXmlLogger.php', 'PHPUnit\\Logging\\JUnit\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/Subscriber.php', 'PHPUnit\\Logging\\JUnit\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestPreparationFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestPreparationStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestPrintedUnexpectedOutputSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPrintedUnexpectedOutputSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestRunnerExecutionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestRunnerExecutionFinishedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestSuiteFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteFinishedSubscriber.php', 'PHPUnit\\Logging\\JUnit\\TestSuiteStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteStartedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/Subscriber.php', 'PHPUnit\\Logging\\TeamCity\\TeamCityLogger' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/TeamCityLogger.php', 'PHPUnit\\Logging\\TeamCity\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestRunnerExecutionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestRunnerExecutionFinishedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSuiteBeforeFirstTestMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteBeforeFirstTestMethodErroredSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSuiteFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSuiteSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteSkippedSubscriber.php', 'PHPUnit\\Logging\\TeamCity\\TestSuiteStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\HtmlRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/HtmlRenderer.php', 'PHPUnit\\Logging\\TestDox\\NamePrettifier' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/NamePrettifier.php', 'PHPUnit\\Logging\\TestDox\\PlainTextRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/PlainTextRenderer.php', 'PHPUnit\\Logging\\TestDox\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.php', 'PHPUnit\\Logging\\TestDox\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestPassedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResult.php', 'PHPUnit\\Logging\\TestDox\\TestResultCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php', 'PHPUnit\\Logging\\TestDox\\TestResultCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php', 'PHPUnit\\Logging\\TestDox\\TestResultCollector' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollector.php', 'PHPUnit\\Logging\\TestDox\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitErrorSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', 'PHPUnit\\Logging\\TestDox\\TestTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php', 'PHPUnit\\Metadata\\After' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/After.php', 'PHPUnit\\Metadata\\AfterClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/AfterClass.php', 'PHPUnit\\Metadata\\Annotation\\Parser\\DocBlock' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/Annotation/DocBlock.php', 'PHPUnit\\Metadata\\Annotation\\Parser\\Registry' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/Annotation/Registry.php', 'PHPUnit\\Metadata\\AnnotationsAreNotSupportedForInternalClassesException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.php', 'PHPUnit\\Metadata\\Api\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/CodeCoverage.php', 'PHPUnit\\Metadata\\Api\\DataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/DataProvider.php', 'PHPUnit\\Metadata\\Api\\Dependencies' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/Dependencies.php', 'PHPUnit\\Metadata\\Api\\Groups' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/Groups.php', 'PHPUnit\\Metadata\\Api\\HookMethods' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/HookMethods.php', 'PHPUnit\\Metadata\\Api\\Requirements' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/Requirements.php', 'PHPUnit\\Metadata\\BackupGlobals' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/BackupGlobals.php', 'PHPUnit\\Metadata\\BackupStaticProperties' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/BackupStaticProperties.php', 'PHPUnit\\Metadata\\Before' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Before.php', 'PHPUnit\\Metadata\\BeforeClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/BeforeClass.php', 'PHPUnit\\Metadata\\Covers' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Covers.php', 'PHPUnit\\Metadata\\CoversClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/CoversClass.php', 'PHPUnit\\Metadata\\CoversDefaultClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/CoversDefaultClass.php', 'PHPUnit\\Metadata\\CoversFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/CoversFunction.php', 'PHPUnit\\Metadata\\CoversNothing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/CoversNothing.php', 'PHPUnit\\Metadata\\DataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/DataProvider.php', 'PHPUnit\\Metadata\\DependsOnClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/DependsOnClass.php', 'PHPUnit\\Metadata\\DependsOnMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/DependsOnMethod.php', 'PHPUnit\\Metadata\\DoesNotPerformAssertions' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/DoesNotPerformAssertions.php', 'PHPUnit\\Metadata\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/Exception.php', 'PHPUnit\\Metadata\\ExcludeGlobalVariableFromBackup' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.php', 'PHPUnit\\Metadata\\ExcludeStaticPropertyFromBackup' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.php', 'PHPUnit\\Metadata\\Group' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Group.php', 'PHPUnit\\Metadata\\IgnoreClassForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/IgnoreClassForCodeCoverage.php', 'PHPUnit\\Metadata\\IgnoreDeprecations' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/IgnoreDeprecations.php', 'PHPUnit\\Metadata\\IgnoreFunctionForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/IgnoreFunctionForCodeCoverage.php', 'PHPUnit\\Metadata\\IgnoreMethodForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/IgnoreMethodForCodeCoverage.php', 'PHPUnit\\Metadata\\InvalidAttributeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/InvalidAttributeException.php', 'PHPUnit\\Metadata\\InvalidVersionRequirementException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/InvalidVersionRequirementException.php', 'PHPUnit\\Metadata\\Metadata' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Metadata.php', 'PHPUnit\\Metadata\\MetadataCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/MetadataCollection.php', 'PHPUnit\\Metadata\\MetadataCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/MetadataCollectionIterator.php', 'PHPUnit\\Metadata\\NoVersionRequirementException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/NoVersionRequirementException.php', 'PHPUnit\\Metadata\\Parser\\AnnotationParser' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/AnnotationParser.php', 'PHPUnit\\Metadata\\Parser\\AttributeParser' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/AttributeParser.php', 'PHPUnit\\Metadata\\Parser\\CachingParser' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/CachingParser.php', 'PHPUnit\\Metadata\\Parser\\Parser' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/Parser.php', 'PHPUnit\\Metadata\\Parser\\ParserChain' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/ParserChain.php', 'PHPUnit\\Metadata\\Parser\\Registry' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/Registry.php', 'PHPUnit\\Metadata\\PostCondition' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/PostCondition.php', 'PHPUnit\\Metadata\\PreCondition' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/PreCondition.php', 'PHPUnit\\Metadata\\PreserveGlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/PreserveGlobalState.php', 'PHPUnit\\Metadata\\ReflectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/ReflectionException.php', 'PHPUnit\\Metadata\\RequiresFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresFunction.php', 'PHPUnit\\Metadata\\RequiresMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresMethod.php', 'PHPUnit\\Metadata\\RequiresOperatingSystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresOperatingSystem.php', 'PHPUnit\\Metadata\\RequiresOperatingSystemFamily' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresOperatingSystemFamily.php', 'PHPUnit\\Metadata\\RequiresPhp' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresPhp.php', 'PHPUnit\\Metadata\\RequiresPhpExtension' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresPhpExtension.php', 'PHPUnit\\Metadata\\RequiresPhpunit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresPhpunit.php', 'PHPUnit\\Metadata\\RequiresSetting' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresSetting.php', 'PHPUnit\\Metadata\\RunClassInSeparateProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RunClassInSeparateProcess.php', 'PHPUnit\\Metadata\\RunInSeparateProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RunInSeparateProcess.php', 'PHPUnit\\Metadata\\RunTestsInSeparateProcesses' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RunTestsInSeparateProcesses.php', 'PHPUnit\\Metadata\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Test.php', 'PHPUnit\\Metadata\\TestDox' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/TestDox.php', 'PHPUnit\\Metadata\\TestWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/TestWith.php', 'PHPUnit\\Metadata\\Uses' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Uses.php', 'PHPUnit\\Metadata\\UsesClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/UsesClass.php', 'PHPUnit\\Metadata\\UsesDefaultClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/UsesDefaultClass.php', 'PHPUnit\\Metadata\\UsesFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/UsesFunction.php', 'PHPUnit\\Metadata\\Version\\ComparisonRequirement' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Version/ComparisonRequirement.php', 'PHPUnit\\Metadata\\Version\\ConstraintRequirement' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Version/ConstraintRequirement.php', 'PHPUnit\\Metadata\\Version\\Requirement' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Version/Requirement.php', 'PHPUnit\\Metadata\\WithoutErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/WithoutErrorHandler.php', 'PHPUnit\\Runner\\Baseline\\Baseline' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Baseline.php', 'PHPUnit\\Runner\\Baseline\\CannotLoadBaselineException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php', 'PHPUnit\\Runner\\Baseline\\FileDoesNotHaveLineException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.php', 'PHPUnit\\Runner\\Baseline\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Generator.php', 'PHPUnit\\Runner\\Baseline\\Issue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Issue.php', 'PHPUnit\\Runner\\Baseline\\Reader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Reader.php', 'PHPUnit\\Runner\\Baseline\\RelativePathCalculator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/RelativePathCalculator.php', 'PHPUnit\\Runner\\Baseline\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/Subscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.php', 'PHPUnit\\Runner\\Baseline\\TestTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.php', 'PHPUnit\\Runner\\Baseline\\Writer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Writer.php', 'PHPUnit\\Runner\\ClassCannotBeFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ClassCannotBeFoundException.php', 'PHPUnit\\Runner\\ClassDoesNotExtendTestCaseException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.php', 'PHPUnit\\Runner\\ClassIsAbstractException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ClassIsAbstractException.php', 'PHPUnit\\Runner\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/CodeCoverage.php', 'PHPUnit\\Runner\\CodeCoverageFileExistsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/CodeCoverageFileExistsException.php', 'PHPUnit\\Runner\\DirectoryDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php', 'PHPUnit\\Runner\\ErrorException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ErrorException.php', 'PHPUnit\\Runner\\ErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ErrorHandler.php', 'PHPUnit\\Runner\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/Exception.php', 'PHPUnit\\Runner\\Extension\\Extension' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/Extension.php', 'PHPUnit\\Runner\\Extension\\ExtensionBootstrapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/ExtensionBootstrapper.php', 'PHPUnit\\Runner\\Extension\\Facade' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/Facade.php', 'PHPUnit\\Runner\\Extension\\ParameterCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/ParameterCollection.php', 'PHPUnit\\Runner\\Extension\\PharLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/PharLoader.php', 'PHPUnit\\Runner\\FileDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/FileDoesNotExistException.php', 'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php', 'PHPUnit\\Runner\\Filter\\Factory' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Factory.php', 'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php', 'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php', 'PHPUnit\\Runner\\Filter\\NameFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php', 'PHPUnit\\Runner\\Filter\\TestIdFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/TestIdFilterIterator.php', 'PHPUnit\\Runner\\GarbageCollection\\ExecutionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.php', 'PHPUnit\\Runner\\GarbageCollection\\ExecutionStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php', 'PHPUnit\\Runner\\GarbageCollection\\GarbageCollectionHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php', 'PHPUnit\\Runner\\GarbageCollection\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php', 'PHPUnit\\Runner\\GarbageCollection\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Runner\\InvalidOrderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/InvalidOrderException.php', 'PHPUnit\\Runner\\InvalidPhptFileException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/InvalidPhptFileException.php', 'PHPUnit\\Runner\\ParameterDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ParameterDoesNotExistException.php', 'PHPUnit\\Runner\\PhptExternalFileCannotBeLoadedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.php', 'PHPUnit\\Runner\\PhptTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/PhptTestCase.php', 'PHPUnit\\Runner\\ResultCache\\DefaultResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.php', 'PHPUnit\\Runner\\ResultCache\\NullResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/NullResultCache.php', 'PHPUnit\\Runner\\ResultCache\\ResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/ResultCache.php', 'PHPUnit\\Runner\\ResultCache\\ResultCacheHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/ResultCacheHandler.php', 'PHPUnit\\Runner\\ResultCache\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/Subscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestSuiteFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.php', 'PHPUnit\\Runner\\ResultCache\\TestSuiteStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php', 'PHPUnit\\Runner\\TestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php', 'PHPUnit\\Runner\\TestSuiteSorter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php', 'PHPUnit\\Runner\\UnsupportedPhptSectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/UnsupportedPhptSectionException.php', 'PHPUnit\\Runner\\Version' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Version.php', 'PHPUnit\\TestRunner\\TestResult\\AfterTestClassMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/AfterTestClassMethodErroredSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\BeforeTestClassMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\Collector' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Collector.php', 'PHPUnit\\TestRunner\\TestResult\\ExecutionStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\Facade' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Facade.php', 'PHPUnit\\TestRunner\\TestResult\\Issues\\Issue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Issue.php', 'PHPUnit\\TestRunner\\TestResult\\PassedTests' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/PassedTests.php', 'PHPUnit\\TestRunner\\TestResult\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/Subscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/TestResult.php', 'PHPUnit\\TestRunner\\TestResult\\TestRunnerTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestRunnerTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestSuiteFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestSuiteSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestSuiteStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredErrorSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitErrorSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php', 'PHPUnit\\TextUI\\Application' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Application.php', 'PHPUnit\\TextUI\\CannotOpenSocketException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/CannotOpenSocketException.php', 'PHPUnit\\TextUI\\CliArguments\\Builder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Builder.php', 'PHPUnit\\TextUI\\CliArguments\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Configuration.php', 'PHPUnit\\TextUI\\CliArguments\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Exception.php', 'PHPUnit\\TextUI\\CliArguments\\XmlConfigurationFileFinder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.php', 'PHPUnit\\TextUI\\Command\\AtLeastVersionCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.php', 'PHPUnit\\TextUI\\Command\\CheckPhpConfigurationCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/CheckPhpConfigurationCommand.php', 'PHPUnit\\TextUI\\Command\\Command' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Command.php', 'PHPUnit\\TextUI\\Command\\GenerateConfigurationCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php', 'PHPUnit\\TextUI\\Command\\ListGroupsCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ListGroupsCommand.php', 'PHPUnit\\TextUI\\Command\\ListTestSuitesCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.php', 'PHPUnit\\TextUI\\Command\\ListTestsAsTextCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php', 'PHPUnit\\TextUI\\Command\\ListTestsAsXmlCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.php', 'PHPUnit\\TextUI\\Command\\MigrateConfigurationCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.php', 'PHPUnit\\TextUI\\Command\\Result' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Result.php', 'PHPUnit\\TextUI\\Command\\ShowHelpCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ShowHelpCommand.php', 'PHPUnit\\TextUI\\Command\\ShowVersionCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ShowVersionCommand.php', 'PHPUnit\\TextUI\\Command\\VersionCheckCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/VersionCheckCommand.php', 'PHPUnit\\TextUI\\Command\\WarmCodeCoverageCacheCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php', 'PHPUnit\\TextUI\\Configuration\\Builder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Builder.php', 'PHPUnit\\TextUI\\Configuration\\CodeCoverageFilterRegistry' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.php', 'PHPUnit\\TextUI\\Configuration\\CodeCoverageReportNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.php', 'PHPUnit\\TextUI\\Configuration\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Configuration.php', 'PHPUnit\\TextUI\\Configuration\\ConfigurationCannotBeBuiltException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.php', 'PHPUnit\\TextUI\\Configuration\\Constant' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Constant.php', 'PHPUnit\\TextUI\\Configuration\\ConstantCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollection.php', 'PHPUnit\\TextUI\\Configuration\\ConstantCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\Directory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Directory.php', 'PHPUnit\\TextUI\\Configuration\\DirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollection.php', 'PHPUnit\\TextUI\\Configuration\\DirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/Exception.php', 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrap' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.php', 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrapCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php', 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrapCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\File' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/File.php', 'PHPUnit\\TextUI\\Configuration\\FileCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollection.php', 'PHPUnit\\TextUI\\Configuration\\FileCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\FilterDirectory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectory.php', 'PHPUnit\\TextUI\\Configuration\\FilterDirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.php', 'PHPUnit\\TextUI\\Configuration\\FilterDirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\FilterNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.php', 'PHPUnit\\TextUI\\Configuration\\Group' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Group.php', 'PHPUnit\\TextUI\\Configuration\\GroupCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollection.php', 'PHPUnit\\TextUI\\Configuration\\GroupCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\IniSetting' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSetting.php', 'PHPUnit\\TextUI\\Configuration\\IniSettingCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollection.php', 'PHPUnit\\TextUI\\Configuration\\IniSettingCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\LoggingNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.php', 'PHPUnit\\TextUI\\Configuration\\Merger' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Merger.php', 'PHPUnit\\TextUI\\Configuration\\NoBaselineException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php', 'PHPUnit\\TextUI\\Configuration\\NoBootstrapException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php', 'PHPUnit\\TextUI\\Configuration\\NoCacheDirectoryException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.php', 'PHPUnit\\TextUI\\Configuration\\NoCliArgumentException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php', 'PHPUnit\\TextUI\\Configuration\\NoConfigurationFileException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.php', 'PHPUnit\\TextUI\\Configuration\\NoCoverageCacheDirectoryException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.php', 'PHPUnit\\TextUI\\Configuration\\NoCustomCssFileException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.php', 'PHPUnit\\TextUI\\Configuration\\NoDefaultTestSuiteException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.php', 'PHPUnit\\TextUI\\Configuration\\NoPharExtensionDirectoryException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.php', 'PHPUnit\\TextUI\\Configuration\\Php' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Php.php', 'PHPUnit\\TextUI\\Configuration\\PhpHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/PhpHandler.php', 'PHPUnit\\TextUI\\Configuration\\Registry' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Registry.php', 'PHPUnit\\TextUI\\Configuration\\Source' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Source.php', 'PHPUnit\\TextUI\\Configuration\\SourceFilter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/SourceFilter.php', 'PHPUnit\\TextUI\\Configuration\\SourceMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/SourceMapper.php', 'PHPUnit\\TextUI\\Configuration\\TestDirectory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectory.php', 'PHPUnit\\TextUI\\Configuration\\TestDirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.php', 'PHPUnit\\TextUI\\Configuration\\TestDirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\TestFile' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFile.php', 'PHPUnit\\TextUI\\Configuration\\TestFileCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollection.php', 'PHPUnit\\TextUI\\Configuration\\TestFileCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuite.php', 'PHPUnit\\TextUI\\Configuration\\TestSuiteBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/TestSuiteBuilder.php', 'PHPUnit\\TextUI\\Configuration\\TestSuiteCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.php', 'PHPUnit\\TextUI\\Configuration\\TestSuiteCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.php', 'PHPUnit\\TextUI\\Configuration\\Variable' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Variable.php', 'PHPUnit\\TextUI\\Configuration\\VariableCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollection.php', 'PHPUnit\\TextUI\\Configuration\\VariableCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php', 'PHPUnit\\TextUI\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/Exception.php', 'PHPUnit\\TextUI\\Help' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Help.php', 'PHPUnit\\TextUI\\InvalidSocketException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/InvalidSocketException.php', 'PHPUnit\\TextUI\\Output\\DefaultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Printer/DefaultPrinter.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\BeforeTestClassMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\ProgressPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestRunnerExecutionStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredErrorSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpunitDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpunitWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.php', 'PHPUnit\\TextUI\\Output\\Default\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ResultPrinter.php', 'PHPUnit\\TextUI\\Output\\Default\\UnexpectedOutputPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php', 'PHPUnit\\TextUI\\Output\\Facade' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Facade.php', 'PHPUnit\\TextUI\\Output\\NullPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Printer/NullPrinter.php', 'PHPUnit\\TextUI\\Output\\Printer' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Printer/Printer.php', 'PHPUnit\\TextUI\\Output\\SummaryPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/SummaryPrinter.php', 'PHPUnit\\TextUI\\Output\\TestDox\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/TestDox/ResultPrinter.php', 'PHPUnit\\TextUI\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php', 'PHPUnit\\TextUI\\ShellExitCodeCalculator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/ShellExitCodeCalculator.php', 'PHPUnit\\TextUI\\TestDirectoryNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php', 'PHPUnit\\TextUI\\TestFileNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php', 'PHPUnit\\TextUI\\TestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestRunner.php', 'PHPUnit\\TextUI\\TestSuiteFilterProcessor' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestSuiteFilterProcessor.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CannotFindSchemaException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Cobertura' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Html' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Php' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Configuration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\ConvertLogTypes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCloverToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCrap4jToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageHtmlToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoveragePhpToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageTextToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageXmlToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.php', 'PHPUnit\\TextUI\\XmlConfiguration\\DefaultConfiguration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Exception.php', 'PHPUnit\\TextUI\\XmlConfiguration\\FailedSchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Generator.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Groups' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Groups.php', 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCacheDirectoryAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCoverageElement' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.php', 'PHPUnit\\TextUI\\XmlConfiguration\\LoadedFromFileConfiguration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Loader' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Loader.php', 'PHPUnit\\TextUI\\XmlConfiguration\\LogToReportMigration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Junit' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Logging' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Logging.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TeamCity' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Html' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Migration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Migrator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromFilterWhitelistToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromRootToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveCoverageDirectoriesToSource' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistExcludesToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistIncludesToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.php', 'PHPUnit\\TextUI\\XmlConfiguration\\PHPUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/PHPUnit.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveBeStrictAboutTodoAnnotatedTestsAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheResultFileAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheTokensAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveConversionToExceptionsAttributes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCoverageElementCacheDirectoryAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCoverageElementProcessUncoveredFilesAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveEmptyFilter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveListeners' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLogTypes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLoggingElements' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveNoInteractionAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemovePrinterAttributes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveTestDoxGroupsElement' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveTestSuiteLoaderAttributes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveVerboseAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RenameBackupStaticAttributesAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RenameBeStrictAboutCoversAnnotationAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\RenameForceCoversAnnotationAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaDetector' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaFinder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaFinder.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SnapshotNodeList' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.php', 'PHPUnit\\TextUI\\XmlConfiguration\\SuccessfulSchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.php', 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.php', 'PHPUnit\\TextUI\\XmlConfiguration\\UpdateSchemaLocation' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.php', 'PHPUnit\\TextUI\\XmlConfiguration\\ValidationResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php', 'PHPUnit\\TextUI\\XmlConfiguration\\Validator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php', 'PHPUnit\\Util\\Cloner' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Cloner.php', 'PHPUnit\\Util\\Color' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Color.php', 'PHPUnit\\Util\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/Exception.php', 'PHPUnit\\Util\\ExcludeList' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ExcludeList.php', 'PHPUnit\\Util\\Exporter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exporter.php', 'PHPUnit\\Util\\Filesystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filesystem.php', 'PHPUnit\\Util\\Filter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filter.php', 'PHPUnit\\Util\\GlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/GlobalState.php', 'PHPUnit\\Util\\Http\\Downloader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Http/Downloader.php', 'PHPUnit\\Util\\Http\\PhpDownloader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Http/PhpDownloader.php', 'PHPUnit\\Util\\InvalidDirectoryException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/InvalidDirectoryException.php', 'PHPUnit\\Util\\InvalidJsonException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/InvalidJsonException.php', 'PHPUnit\\Util\\InvalidVersionOperatorException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/InvalidVersionOperatorException.php', 'PHPUnit\\Util\\Json' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Json.php', 'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php', 'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php', 'PHPUnit\\Util\\PHP\\PhpProcessException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/PhpProcessException.php', 'PHPUnit\\Util\\Reflection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Reflection.php', 'PHPUnit\\Util\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Test.php', 'PHPUnit\\Util\\ThrowableToStringMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ThrowableToStringMapper.php', 'PHPUnit\\Util\\VersionComparisonOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php', 'PHPUnit\\Util\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Xml.php', 'PHPUnit\\Util\\Xml\\Loader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Loader.php', 'PHPUnit\\Util\\Xml\\XmlException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/XmlException.php', 'PharIo\\Manifest\\Application' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Application.php', 'PharIo\\Manifest\\ApplicationName' => __DIR__ . '/..' . '/phar-io/manifest/src/values/ApplicationName.php', 'PharIo\\Manifest\\Author' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Author.php', 'PharIo\\Manifest\\AuthorCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollection.php', 'PharIo\\Manifest\\AuthorCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollectionIterator.php', 'PharIo\\Manifest\\AuthorElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElement.php', 'PharIo\\Manifest\\AuthorElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElementCollection.php', 'PharIo\\Manifest\\BundledComponent' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponent.php', 'PharIo\\Manifest\\BundledComponentCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollection.php', 'PharIo\\Manifest\\BundledComponentCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php', 'PharIo\\Manifest\\BundlesElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/BundlesElement.php', 'PharIo\\Manifest\\ComponentElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElement.php', 'PharIo\\Manifest\\ComponentElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElementCollection.php', 'PharIo\\Manifest\\ContainsElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ContainsElement.php', 'PharIo\\Manifest\\CopyrightElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/CopyrightElement.php', 'PharIo\\Manifest\\CopyrightInformation' => __DIR__ . '/..' . '/phar-io/manifest/src/values/CopyrightInformation.php', 'PharIo\\Manifest\\ElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ElementCollection.php', 'PharIo\\Manifest\\ElementCollectionException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ElementCollectionException.php', 'PharIo\\Manifest\\Email' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Email.php', 'PharIo\\Manifest\\Exception' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/Exception.php', 'PharIo\\Manifest\\ExtElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElement.php', 'PharIo\\Manifest\\ExtElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElementCollection.php', 'PharIo\\Manifest\\Extension' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Extension.php', 'PharIo\\Manifest\\ExtensionElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtensionElement.php', 'PharIo\\Manifest\\InvalidApplicationNameException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php', 'PharIo\\Manifest\\InvalidEmailException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidEmailException.php', 'PharIo\\Manifest\\InvalidUrlException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidUrlException.php', 'PharIo\\Manifest\\Library' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Library.php', 'PharIo\\Manifest\\License' => __DIR__ . '/..' . '/phar-io/manifest/src/values/License.php', 'PharIo\\Manifest\\LicenseElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/LicenseElement.php', 'PharIo\\Manifest\\Manifest' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Manifest.php', 'PharIo\\Manifest\\ManifestDocument' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestDocument.php', 'PharIo\\Manifest\\ManifestDocumentException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php', 'PharIo\\Manifest\\ManifestDocumentLoadingException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php', 'PharIo\\Manifest\\ManifestDocumentMapper' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestDocumentMapper.php', 'PharIo\\Manifest\\ManifestDocumentMapperException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php', 'PharIo\\Manifest\\ManifestElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestElement.php', 'PharIo\\Manifest\\ManifestElementException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestElementException.php', 'PharIo\\Manifest\\ManifestLoader' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestLoader.php', 'PharIo\\Manifest\\ManifestLoaderException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php', 'PharIo\\Manifest\\ManifestSerializer' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestSerializer.php', 'PharIo\\Manifest\\NoEmailAddressException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/NoEmailAddressException.php', 'PharIo\\Manifest\\PhpElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/PhpElement.php', 'PharIo\\Manifest\\PhpExtensionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpExtensionRequirement.php', 'PharIo\\Manifest\\PhpVersionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpVersionRequirement.php', 'PharIo\\Manifest\\Requirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Requirement.php', 'PharIo\\Manifest\\RequirementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollection.php', 'PharIo\\Manifest\\RequirementCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollectionIterator.php', 'PharIo\\Manifest\\RequiresElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/RequiresElement.php', 'PharIo\\Manifest\\Type' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Type.php', 'PharIo\\Manifest\\Url' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Url.php', 'PharIo\\Version\\AbstractVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AbstractVersionConstraint.php', 'PharIo\\Version\\AndVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php', 'PharIo\\Version\\AnyVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AnyVersionConstraint.php', 'PharIo\\Version\\BuildMetaData' => __DIR__ . '/..' . '/phar-io/version/src/BuildMetaData.php', 'PharIo\\Version\\ExactVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/ExactVersionConstraint.php', 'PharIo\\Version\\Exception' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/Exception.php', 'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php', 'PharIo\\Version\\InvalidPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php', 'PharIo\\Version\\InvalidVersionException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidVersionException.php', 'PharIo\\Version\\NoBuildMetaDataException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/NoBuildMetaDataException.php', 'PharIo\\Version\\NoPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php', 'PharIo\\Version\\OrVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php', 'PharIo\\Version\\PreReleaseSuffix' => __DIR__ . '/..' . '/phar-io/version/src/PreReleaseSuffix.php', 'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php', 'PharIo\\Version\\SpecificMajorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php', 'PharIo\\Version\\UnsupportedVersionConstraintException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php', 'PharIo\\Version\\Version' => __DIR__ . '/..' . '/phar-io/version/src/Version.php', 'PharIo\\Version\\VersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/VersionConstraint.php', 'PharIo\\Version\\VersionConstraintParser' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintParser.php', 'PharIo\\Version\\VersionConstraintValue' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintValue.php', 'PharIo\\Version\\VersionNumber' => __DIR__ . '/..' . '/phar-io/version/src/VersionNumber.php', 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'SebastianBergmann\\CliParser\\AmbiguousOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php', 'SebastianBergmann\\CliParser\\Exception' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/Exception.php', 'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php', 'SebastianBergmann\\CliParser\\Parser' => __DIR__ . '/..' . '/sebastian/cli-parser/src/Parser.php', 'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php', 'SebastianBergmann\\CliParser\\UnknownOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php', 'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php', 'SebastianBergmann\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage.php', 'SebastianBergmann\\CodeCoverage\\Data\\ProcessedCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php', 'SebastianBergmann\\CodeCoverage\\Data\\RawCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php', 'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Driver.php', 'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php', 'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Selector.php', 'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/XdebugDriver.php', 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php', 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotEnabledException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php', 'SebastianBergmann\\CodeCoverage\\Exception' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Exception.php', 'SebastianBergmann\\CodeCoverage\\FileCouldNotBeWrittenException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php', 'SebastianBergmann\\CodeCoverage\\Filter' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Filter.php', 'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php', 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php', 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php', 'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/AbstractNode.php', 'SebastianBergmann\\CodeCoverage\\Node\\Builder' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Builder.php', 'SebastianBergmann\\CodeCoverage\\Node\\CrapIndex' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/CrapIndex.php', 'SebastianBergmann\\CodeCoverage\\Node\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Directory.php', 'SebastianBergmann\\CodeCoverage\\Node\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/File.php', 'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Iterator.php', 'SebastianBergmann\\CodeCoverage\\ParserException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ParserException.php', 'SebastianBergmann\\CodeCoverage\\ReflectionException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php', 'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php', 'SebastianBergmann\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Clover.php', 'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Cobertura.php', 'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Crap4j.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Colors' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Colors.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\CustomCssFile' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Facade.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php', 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php', 'SebastianBergmann\\CodeCoverage\\Report\\PHP' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/PHP.php', 'SebastianBergmann\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Text.php', 'SebastianBergmann\\CodeCoverage\\Report\\Thresholds' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Thresholds.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/File.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Method.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Node.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Project.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Report.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Source.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php', 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\FileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php', 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php', 'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Known' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Known.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Large' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Large.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Medium' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Medium.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Small' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Small.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\TestSize' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/TestSize.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Unknown' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Unknown.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Failure' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Failure.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Known' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Known.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Success' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Success.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\TestStatus' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/TestStatus.php', 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Unknown' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Unknown.php', 'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php', 'SebastianBergmann\\CodeCoverage\\Util\\DirectoryCouldNotBeCreatedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php', 'SebastianBergmann\\CodeCoverage\\Util\\Filesystem' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Util/Filesystem.php', 'SebastianBergmann\\CodeCoverage\\Util\\Percentage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Util/Percentage.php', 'SebastianBergmann\\CodeCoverage\\Version' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Version.php', 'SebastianBergmann\\CodeCoverage\\XmlException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XmlException.php', 'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => __DIR__ . '/..' . '/sebastian/code-unit-reverse-lookup/src/Wizard.php', 'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassMethodUnit.php', 'SebastianBergmann\\CodeUnit\\ClassUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassUnit.php', 'SebastianBergmann\\CodeUnit\\CodeUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnit.php', 'SebastianBergmann\\CodeUnit\\CodeUnitCollection' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnitCollection.php', 'SebastianBergmann\\CodeUnit\\CodeUnitCollectionIterator' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnitCollectionIterator.php', 'SebastianBergmann\\CodeUnit\\Exception' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/Exception.php', 'SebastianBergmann\\CodeUnit\\FileUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/FileUnit.php', 'SebastianBergmann\\CodeUnit\\FunctionUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/FunctionUnit.php', 'SebastianBergmann\\CodeUnit\\InterfaceMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/InterfaceMethodUnit.php', 'SebastianBergmann\\CodeUnit\\InterfaceUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/InterfaceUnit.php', 'SebastianBergmann\\CodeUnit\\InvalidCodeUnitException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php', 'SebastianBergmann\\CodeUnit\\Mapper' => __DIR__ . '/..' . '/sebastian/code-unit/src/Mapper.php', 'SebastianBergmann\\CodeUnit\\NoTraitException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/NoTraitException.php', 'SebastianBergmann\\CodeUnit\\ReflectionException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/ReflectionException.php', 'SebastianBergmann\\CodeUnit\\TraitMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/TraitMethodUnit.php', 'SebastianBergmann\\CodeUnit\\TraitUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/TraitUnit.php', 'SebastianBergmann\\Comparator\\ArrayComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ArrayComparator.php', 'SebastianBergmann\\Comparator\\Comparator' => __DIR__ . '/..' . '/sebastian/comparator/src/Comparator.php', 'SebastianBergmann\\Comparator\\ComparisonFailure' => __DIR__ . '/..' . '/sebastian/comparator/src/ComparisonFailure.php', 'SebastianBergmann\\Comparator\\DOMNodeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DOMNodeComparator.php', 'SebastianBergmann\\Comparator\\DateTimeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DateTimeComparator.php', 'SebastianBergmann\\Comparator\\Exception' => __DIR__ . '/..' . '/sebastian/comparator/src/exceptions/Exception.php', 'SebastianBergmann\\Comparator\\ExceptionComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ExceptionComparator.php', 'SebastianBergmann\\Comparator\\Factory' => __DIR__ . '/..' . '/sebastian/comparator/src/Factory.php', 'SebastianBergmann\\Comparator\\MockObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/MockObjectComparator.php', 'SebastianBergmann\\Comparator\\NumericComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/NumericComparator.php', 'SebastianBergmann\\Comparator\\ObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ObjectComparator.php', 'SebastianBergmann\\Comparator\\ResourceComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ResourceComparator.php', 'SebastianBergmann\\Comparator\\RuntimeException' => __DIR__ . '/..' . '/sebastian/comparator/src/exceptions/RuntimeException.php', 'SebastianBergmann\\Comparator\\ScalarComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ScalarComparator.php', 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/SplObjectStorageComparator.php', 'SebastianBergmann\\Comparator\\TypeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/TypeComparator.php', 'SebastianBergmann\\Complexity\\Calculator' => __DIR__ . '/..' . '/sebastian/complexity/src/Calculator.php', 'SebastianBergmann\\Complexity\\Complexity' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/Complexity.php', 'SebastianBergmann\\Complexity\\ComplexityCalculatingVisitor' => __DIR__ . '/..' . '/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php', 'SebastianBergmann\\Complexity\\ComplexityCollection' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/ComplexityCollection.php', 'SebastianBergmann\\Complexity\\ComplexityCollectionIterator' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php', 'SebastianBergmann\\Complexity\\CyclomaticComplexityCalculatingVisitor' => __DIR__ . '/..' . '/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php', 'SebastianBergmann\\Complexity\\Exception' => __DIR__ . '/..' . '/sebastian/complexity/src/Exception/Exception.php', 'SebastianBergmann\\Complexity\\RuntimeException' => __DIR__ . '/..' . '/sebastian/complexity/src/Exception/RuntimeException.php', 'SebastianBergmann\\Diff\\Chunk' => __DIR__ . '/..' . '/sebastian/diff/src/Chunk.php', 'SebastianBergmann\\Diff\\ConfigurationException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/ConfigurationException.php', 'SebastianBergmann\\Diff\\Diff' => __DIR__ . '/..' . '/sebastian/diff/src/Diff.php', 'SebastianBergmann\\Diff\\Differ' => __DIR__ . '/..' . '/sebastian/diff/src/Differ.php', 'SebastianBergmann\\Diff\\Exception' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/Exception.php', 'SebastianBergmann\\Diff\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/InvalidArgumentException.php', 'SebastianBergmann\\Diff\\Line' => __DIR__ . '/..' . '/sebastian/diff/src/Line.php', 'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', 'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', 'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', 'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', 'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', 'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', 'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', 'SebastianBergmann\\Diff\\Parser' => __DIR__ . '/..' . '/sebastian/diff/src/Parser.php', 'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', 'SebastianBergmann\\Environment\\Console' => __DIR__ . '/..' . '/sebastian/environment/src/Console.php', 'SebastianBergmann\\Environment\\Runtime' => __DIR__ . '/..' . '/sebastian/environment/src/Runtime.php', 'SebastianBergmann\\Exporter\\Exporter' => __DIR__ . '/..' . '/sebastian/exporter/src/Exporter.php', 'SebastianBergmann\\FileIterator\\ExcludeIterator' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/ExcludeIterator.php', 'SebastianBergmann\\FileIterator\\Facade' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Facade.php', 'SebastianBergmann\\FileIterator\\Factory' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Factory.php', 'SebastianBergmann\\FileIterator\\Iterator' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Iterator.php', 'SebastianBergmann\\GlobalState\\CodeExporter' => __DIR__ . '/..' . '/sebastian/global-state/src/CodeExporter.php', 'SebastianBergmann\\GlobalState\\Exception' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/Exception.php', 'SebastianBergmann\\GlobalState\\ExcludeList' => __DIR__ . '/..' . '/sebastian/global-state/src/ExcludeList.php', 'SebastianBergmann\\GlobalState\\Restorer' => __DIR__ . '/..' . '/sebastian/global-state/src/Restorer.php', 'SebastianBergmann\\GlobalState\\RuntimeException' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/RuntimeException.php', 'SebastianBergmann\\GlobalState\\Snapshot' => __DIR__ . '/..' . '/sebastian/global-state/src/Snapshot.php', 'SebastianBergmann\\Invoker\\Exception' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/Exception.php', 'SebastianBergmann\\Invoker\\Invoker' => __DIR__ . '/..' . '/phpunit/php-invoker/src/Invoker.php', 'SebastianBergmann\\Invoker\\ProcessControlExtensionNotLoadedException' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php', 'SebastianBergmann\\Invoker\\TimeoutException' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/TimeoutException.php', 'SebastianBergmann\\LinesOfCode\\Counter' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Counter.php', 'SebastianBergmann\\LinesOfCode\\Exception' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/Exception.php', 'SebastianBergmann\\LinesOfCode\\IllogicalValuesException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php', 'SebastianBergmann\\LinesOfCode\\LineCountingVisitor' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/LineCountingVisitor.php', 'SebastianBergmann\\LinesOfCode\\LinesOfCode' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/LinesOfCode.php', 'SebastianBergmann\\LinesOfCode\\NegativeValueException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/NegativeValueException.php', 'SebastianBergmann\\LinesOfCode\\RuntimeException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/RuntimeException.php', 'SebastianBergmann\\ObjectEnumerator\\Enumerator' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/Enumerator.php', 'SebastianBergmann\\ObjectReflector\\ObjectReflector' => __DIR__ . '/..' . '/sebastian/object-reflector/src/ObjectReflector.php', 'SebastianBergmann\\RecursionContext\\Context' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Context.php', 'SebastianBergmann\\Template\\Exception' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/Exception.php', 'SebastianBergmann\\Template\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php', 'SebastianBergmann\\Template\\RuntimeException' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/RuntimeException.php', 'SebastianBergmann\\Template\\Template' => __DIR__ . '/..' . '/phpunit/php-text-template/src/Template.php', 'SebastianBergmann\\Timer\\Duration' => __DIR__ . '/..' . '/phpunit/php-timer/src/Duration.php', 'SebastianBergmann\\Timer\\Exception' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/Exception.php', 'SebastianBergmann\\Timer\\NoActiveTimerException' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/NoActiveTimerException.php', 'SebastianBergmann\\Timer\\ResourceUsageFormatter' => __DIR__ . '/..' . '/phpunit/php-timer/src/ResourceUsageFormatter.php', 'SebastianBergmann\\Timer\\TimeSinceStartOfRequestNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php', 'SebastianBergmann\\Timer\\Timer' => __DIR__ . '/..' . '/phpunit/php-timer/src/Timer.php', 'SebastianBergmann\\Type\\CallableType' => __DIR__ . '/..' . '/sebastian/type/src/type/CallableType.php', 'SebastianBergmann\\Type\\Exception' => __DIR__ . '/..' . '/sebastian/type/src/exception/Exception.php', 'SebastianBergmann\\Type\\FalseType' => __DIR__ . '/..' . '/sebastian/type/src/type/FalseType.php', 'SebastianBergmann\\Type\\GenericObjectType' => __DIR__ . '/..' . '/sebastian/type/src/type/GenericObjectType.php', 'SebastianBergmann\\Type\\IntersectionType' => __DIR__ . '/..' . '/sebastian/type/src/type/IntersectionType.php', 'SebastianBergmann\\Type\\IterableType' => __DIR__ . '/..' . '/sebastian/type/src/type/IterableType.php', 'SebastianBergmann\\Type\\MixedType' => __DIR__ . '/..' . '/sebastian/type/src/type/MixedType.php', 'SebastianBergmann\\Type\\NeverType' => __DIR__ . '/..' . '/sebastian/type/src/type/NeverType.php', 'SebastianBergmann\\Type\\NullType' => __DIR__ . '/..' . '/sebastian/type/src/type/NullType.php', 'SebastianBergmann\\Type\\ObjectType' => __DIR__ . '/..' . '/sebastian/type/src/type/ObjectType.php', 'SebastianBergmann\\Type\\Parameter' => __DIR__ . '/..' . '/sebastian/type/src/Parameter.php', 'SebastianBergmann\\Type\\ReflectionMapper' => __DIR__ . '/..' . '/sebastian/type/src/ReflectionMapper.php', 'SebastianBergmann\\Type\\RuntimeException' => __DIR__ . '/..' . '/sebastian/type/src/exception/RuntimeException.php', 'SebastianBergmann\\Type\\SimpleType' => __DIR__ . '/..' . '/sebastian/type/src/type/SimpleType.php', 'SebastianBergmann\\Type\\StaticType' => __DIR__ . '/..' . '/sebastian/type/src/type/StaticType.php', 'SebastianBergmann\\Type\\TrueType' => __DIR__ . '/..' . '/sebastian/type/src/type/TrueType.php', 'SebastianBergmann\\Type\\Type' => __DIR__ . '/..' . '/sebastian/type/src/type/Type.php', 'SebastianBergmann\\Type\\TypeName' => __DIR__ . '/..' . '/sebastian/type/src/TypeName.php', 'SebastianBergmann\\Type\\UnionType' => __DIR__ . '/..' . '/sebastian/type/src/type/UnionType.php', 'SebastianBergmann\\Type\\UnknownType' => __DIR__ . '/..' . '/sebastian/type/src/type/UnknownType.php', 'SebastianBergmann\\Type\\VoidType' => __DIR__ . '/..' . '/sebastian/type/src/type/VoidType.php', 'SebastianBergmann\\Version' => __DIR__ . '/..' . '/sebastian/version/src/Version.php', 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'TheSeer\\Tokenizer\\Exception' => __DIR__ . '/..' . '/theseer/tokenizer/src/Exception.php', 'TheSeer\\Tokenizer\\NamespaceUri' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUri.php', 'TheSeer\\Tokenizer\\NamespaceUriException' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUriException.php', 'TheSeer\\Tokenizer\\Token' => __DIR__ . '/..' . '/theseer/tokenizer/src/Token.php', 'TheSeer\\Tokenizer\\TokenCollection' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollection.php', 'TheSeer\\Tokenizer\\TokenCollectionException' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollectionException.php', 'TheSeer\\Tokenizer\\Tokenizer' => __DIR__ . '/..' . '/theseer/tokenizer/src/Tokenizer.php', 'TheSeer\\Tokenizer\\XMLSerializer' => __DIR__ . '/..' . '/theseer/tokenizer/src/XMLSerializer.php', 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInit06bf6a7b47e3e59d138b1000d1d1b8a9::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit06bf6a7b47e3e59d138b1000d1d1b8a9::$prefixDirsPsr4; $loader->prefixesPsr0 = ComposerStaticInit06bf6a7b47e3e59d138b1000d1d1b8a9::$prefixesPsr0; $loader->classMap = ComposerStaticInit06bf6a7b47e3e59d138b1000d1d1b8a9::$classMap; }, null, ClassLoader::class); } } { "packages": [ { "name": "clue/phar-composer", "version": "v1.4.0", "version_normalized": "1.4.0.0", "source": { "type": "git", "url": "https://github.com/clue/phar-composer.git", "reference": "0cae6984e0da45639881d3b26442d525b8b65406" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/clue/phar-composer/zipball/0cae6984e0da45639881d3b26442d525b8b65406", "reference": "0cae6984e0da45639881d3b26442d525b8b65406", "shasum": "" }, "require": { "knplabs/packagist-api": "^1.0", "php": ">=5.3.6", "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.0 || ^2.5", "symfony/finder": "^6.0 || ^5.0 || ^4.0 || ^3.0 || ^2.5", "symfony/process": "^6.0 || ^5.0 || ^4.0 || ^3.0 || ^2.5" }, "require-dev": { "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.36" }, "time": "2022-02-14T11:28:08+00:00", "bin": [ "bin/phar-composer" ], "type": "library", "installation-source": "dist", "autoload": { "psr-4": { "Clue\\PharComposer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Christian Lück", "email": "christian@clue.engineering" } ], "description": "Simple phar creation for any project managed via Composer", "homepage": "https://github.com/clue/phar-composer", "keywords": [ "build process", "bundle dependencies", "composer", "executable phar", "phar" ], "support": { "issues": "https://github.com/clue/phar-composer/issues", "source": "https://github.com/clue/phar-composer/tree/v1.4.0" }, "funding": [ { "url": "https://clue.engineering/support", "type": "custom" }, { "url": "https://github.com/clue", "type": "github" } ], "install-path": "../clue/phar-composer" }, { "name": "dealerdirect/phpcodesniffer-composer-installer", "version": "v1.2.1", "version_normalized": "1.2.1.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/composer-installer.git", "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd", "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd", "shasum": "" }, "require": { "composer-plugin-api": "^2.2", "php": ">=5.4", "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { "composer/composer": "^2.2", "ext-json": "*", "ext-zip": "*", "php-parallel-lint/php-parallel-lint": "^1.4.0", "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", "yoast/phpunit-polyfills": "^1.0" }, "time": "2026-05-06T08:26:05+00:00", "type": "composer-plugin", "extra": { "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" }, "installation-source": "dist", "autoload": { "psr-4": { "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Franck Nijhof", "email": "opensource@frenck.dev", "homepage": "https://frenck.dev", "role": "Open source developer" }, { "name": "Contributors", "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", "code quality", "codesniffer", "composer", "installer", "phpcbf", "phpcs", "plugin", "qa", "quality", "standard", "standards", "style guide", "stylecheck", "tests" ], "support": { "issues": "https://github.com/PHPCSStandards/composer-installer/issues", "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", "source": "https://github.com/PHPCSStandards/composer-installer" }, "funding": [ { "url": "https://github.com/PHPCSStandards", "type": "github" }, { "url": "https://github.com/jrfnl", "type": "github" }, { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" }, { "url": "https://thanks.dev/u/gh/phpcsstandards", "type": "thanks_dev" } ], "install-path": "../dealerdirect/phpcodesniffer-composer-installer" }, { "name": "doctrine/inflector", "version": "2.1.0", "version_normalized": "2.1.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^12.0 || ^13.0", "phpstan/phpstan": "^1.12 || ^2.0", "phpstan/phpstan-phpunit": "^1.4 || ^2.0", "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", "phpunit/phpunit": "^8.5 || ^12.2" }, "time": "2025-08-10T19:31:58+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { "Doctrine\\Inflector\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", "homepage": "https://www.doctrine-project.org/projects/inflector.html", "keywords": [ "inflection", "inflector", "lowercase", "manipulation", "php", "plural", "singular", "strings", "uppercase", "words" ], "support": { "issues": "https://github.com/doctrine/inflector/issues", "source": "https://github.com/doctrine/inflector/tree/2.1.0" }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", "type": "custom" }, { "url": "https://www.patreon.com/phpdoctrine", "type": "patreon" }, { "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", "type": "tidelift" } ], "install-path": "../doctrine/inflector" }, { "name": "guzzlehttp/guzzle", "version": "7.15.3", "version_normalized": "7.15.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", "reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc", "reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/promises": "^2.5.2", "guzzlehttp/psr7": "^2.13", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-client-implementation": "1.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", "guzzle/client-integration-tests": "3.0.3", "guzzlehttp/test-server": "^0.7", "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { "ext-curl": "Required for CURL handler support", "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "time": "2026-08-05T19:48:21+00:00", "type": "library", "extra": { "bamarni-bin": { "bin-links": true, "forward-command": false } }, "installation-source": "dist", "autoload": { "files": [ "src/functions_include.php" ], "psr-4": { "GuzzleHttp\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Graham Campbell", "email": "hello@gjcampbell.co.uk", "homepage": "https://github.com/GrahamCampbell" }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "Jeremy Lindblom", "email": "jeremeamia@gmail.com", "homepage": "https://github.com/jeremeamia" }, { "name": "George Mponos", "email": "gmponos@gmail.com", "homepage": "https://github.com/gmponos" }, { "name": "Tobias Nyholm", "email": "tobias.nyholm@gmail.com", "homepage": "https://github.com/Nyholm" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", "homepage": "https://github.com/sagikazarmark" }, { "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" } ], "description": "Guzzle is a PHP HTTP client library", "keywords": [ "client", "curl", "framework", "http", "http client", "psr-18", "psr-7", "rest", "web service" ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", "source": "https://github.com/guzzle/guzzle/tree/7.15.3" }, "funding": [ { "url": "https://github.com/GrahamCampbell", "type": "github" }, { "url": "https://github.com/Nyholm", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", "type": "tidelift" } ], "install-path": "../guzzlehttp/guzzle" }, { "name": "guzzlehttp/promises", "version": "2.5.2", "version_normalized": "2.5.2.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", "reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/guzzle/promises/zipball/2823687acff28b2dbe67b2508a6b300e2c3fa4ce", "reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "symfony/deprecation-contracts": "^2.5 || ^3.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "time": "2026-08-05T19:30:54+00:00", "type": "library", "extra": { "bamarni-bin": { "bin-links": true, "forward-command": false } }, "installation-source": "dist", "autoload": { "psr-4": { "GuzzleHttp\\Promise\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Graham Campbell", "email": "hello@gjcampbell.co.uk", "homepage": "https://github.com/GrahamCampbell" }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "Tobias Nyholm", "email": "tobias.nyholm@gmail.com", "homepage": "https://github.com/Nyholm" }, { "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" } ], "description": "Guzzle promises library", "keywords": [ "promise" ], "support": { "issues": "https://github.com/guzzle/promises/issues", "source": "https://github.com/guzzle/promises/tree/2.5.2" }, "funding": [ { "url": "https://github.com/GrahamCampbell", "type": "github" }, { "url": "https://github.com/Nyholm", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", "type": "tidelift" } ], "install-path": "../guzzlehttp/promises" }, { "name": "guzzlehttp/psr7", "version": "2.13.0", "version_normalized": "2.13.0.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/guzzle/psr7/zipball/dad89620b7a6edb60c15858442eb2e408b45d8f4", "reference": "dad89620b7a6edb60c15858442eb2e408b45d8f4", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.1 || ^2.0", "ralouphie/getallheaders": "^3.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", "symfony/polyfill-php80": "^1.25" }, "provide": { "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "1.1.0", "jshttp/mime-db": "1.54.0.1", "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "time": "2026-07-16T22:23:49+00:00", "type": "library", "extra": { "bamarni-bin": { "bin-links": true, "forward-command": false } }, "installation-source": "dist", "autoload": { "psr-4": { "GuzzleHttp\\Psr7\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Graham Campbell", "email": "hello@gjcampbell.co.uk", "homepage": "https://github.com/GrahamCampbell" }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "George Mponos", "email": "gmponos@gmail.com", "homepage": "https://github.com/gmponos" }, { "name": "Tobias Nyholm", "email": "tobias.nyholm@gmail.com", "homepage": "https://github.com/Nyholm" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", "homepage": "https://github.com/sagikazarmark" }, { "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", "homepage": "https://sagikazarmark.hu" } ], "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ "http", "message", "psr-7", "request", "response", "stream", "uri", "url" ], "support": { "issues": "https://github.com/guzzle/psr7/issues", "source": "https://github.com/guzzle/psr7/tree/2.13.0" }, "funding": [ { "url": "https://github.com/GrahamCampbell", "type": "github" }, { "url": "https://github.com/Nyholm", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", "type": "tidelift" } ], "install-path": "../guzzlehttp/psr7" }, { "name": "knplabs/packagist-api", "version": "v1.7.2", "version_normalized": "1.7.2.0", "source": { "type": "git", "url": "https://github.com/KnpLabs/packagist-api.git", "reference": "4feae228a4505c1cd817da61e752e5dea2b22c2d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/KnpLabs/packagist-api/zipball/4feae228a4505c1cd817da61e752e5dea2b22c2d", "reference": "4feae228a4505c1cd817da61e752e5dea2b22c2d", "shasum": "" }, "require": { "doctrine/inflector": "^1.0 || ^2.0", "guzzlehttp/guzzle": "^6.0 || ^7.0", "php": "^7.1 || ^8.0" }, "require-dev": { "phpspec/phpspec": "^5.1 || ^6.0 || ^7.0", "squizlabs/php_codesniffer": "^3.0" }, "time": "2022-03-01T08:20:15+00:00", "type": "library", "extra": { "branch-alias": { "dev-master": "1.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Packagist\\Api\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "KnpLabs Team", "homepage": "http://knplabs.com" } ], "description": "Packagist API client.", "homepage": "http://knplabs.com", "keywords": [ "api", "composer", "packagist" ], "support": { "issues": "https://github.com/KnpLabs/packagist-api/issues", "source": "https://github.com/KnpLabs/packagist-api/tree/v1.7.2" }, "install-path": "../knplabs/packagist-api" }, { "name": "laravel/serializable-closure", "version": "v2.0.15", "version_normalized": "2.0.15.0", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/dccd8bcb851bb03fcc005df650b708b57cc52661", "reference": "dccd8bcb851bb03fcc005df650b708b57cc52661", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { "illuminate/support": "^10.0|^11.0|^12.0|^13.0", "nesbot/carbon": "^2.67|^3.0", "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/phpstan": "^2.0", "symfony/var-dumper": "^6.2.0|^7.0.0|^8.0.0" }, "time": "2026-07-21T16:49:22+00:00", "type": "library", "extra": { "branch-alias": { "dev-master": "2.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Laravel\\SerializableClosure\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" }, { "name": "Nuno Maduro", "email": "nuno@laravel.com" } ], "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", "keywords": [ "closure", "laravel", "serializable" ], "support": { "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, "install-path": "../laravel/serializable-closure" }, { "name": "league/flysystem", "version": "3.35.2", "version_normalized": "3.35.2.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", "reference": "b277b5dc3d56650b68904117124e79c851e12376" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/b277b5dc3d56650b68904117124e79c851e12376", "reference": "b277b5dc3d56650b68904117124e79c851e12376", "shasum": "" }, "require": { "league/flysystem-local": "^3.0.0", "league/mime-type-detection": "^1.0.0", "php": "^8.0.2" }, "conflict": { "async-aws/core": "<1.19.0", "async-aws/s3": "<1.14.0", "aws/aws-sdk-php": "3.209.31 || 3.210.0", "guzzlehttp/guzzle": "<7.0", "guzzlehttp/ringphp": "<1.1.1", "phpseclib/phpseclib": "3.0.15", "symfony/http-client": "<5.2" }, "require-dev": { "async-aws/s3": "^1.5 || ^2.0", "async-aws/simple-s3": "^1.1 || ^2.0", "aws/aws-sdk-php": "^3.295.10", "composer/semver": "^3.0", "ext-fileinfo": "*", "ext-ftp": "*", "ext-mongodb": "^1.3|^2", "ext-zip": "*", "friendsofphp/php-cs-fixer": "^3.5", "google/cloud-storage": "^1.23", "guzzlehttp/psr7": "^2.6", "microsoft/azure-storage-blob": "^1.1", "mongodb/mongodb": "^1.2|^2", "phpseclib/phpseclib": "^3.0.36", "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.5.11|^10.0", "sabre/dav": "^4.6.0" }, "time": "2026-07-06T14:42:07+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { "League\\Flysystem\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Frank de Jonge", "email": "info@frankdejonge.nl" } ], "description": "File storage abstraction for PHP", "keywords": [ "WebDAV", "aws", "cloud", "file", "files", "filesystem", "filesystems", "ftp", "s3", "sftp", "storage" ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", "source": "https://github.com/thephpleague/flysystem/tree/3.35.2" }, "install-path": "../league/flysystem" }, { "name": "league/flysystem-local", "version": "3.31.0", "version_normalized": "3.31.0.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-local.git", "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/2f669db18a4c20c755c2bb7d3a7b0b2340488079", "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079", "shasum": "" }, "require": { "ext-fileinfo": "*", "league/flysystem": "^3.0.0", "league/mime-type-detection": "^1.0.0", "php": "^8.0.2" }, "time": "2026-01-23T15:30:45+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { "League\\Flysystem\\Local\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Frank de Jonge", "email": "info@frankdejonge.nl" } ], "description": "Local filesystem adapter for Flysystem.", "keywords": [ "Flysystem", "file", "files", "filesystem", "local" ], "support": { "source": "https://github.com/thephpleague/flysystem-local/tree/3.31.0" }, "install-path": "../league/flysystem-local" }, { "name": "league/mime-type-detection", "version": "1.17.0", "version_normalized": "1.17.0.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/f5f47eff7c48ed1003069a2ca67f316fb4021c76", "reference": "f5f47eff7c48ed1003069a2ca67f316fb4021c76", "shasum": "" }, "require": { "ext-fileinfo": "*", "php": "^7.4 || ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "phpstan/phpstan": "^0.12.68", "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0 || ^11.0 || ^12.0" }, "time": "2026-07-09T11:49:27+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { "League\\MimeTypeDetection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Frank de Jonge", "email": "info@frankdejonge.nl" } ], "description": "Mime-type detection for Flysystem", "support": { "issues": "https://github.com/thephpleague/mime-type-detection/issues", "source": "https://github.com/thephpleague/mime-type-detection/tree/1.17.0" }, "funding": [ { "url": "https://github.com/frankdejonge", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/league/flysystem", "type": "tidelift" } ], "install-path": "../league/mime-type-detection" }, { "name": "mikey179/vfsstream", "version": "v1.6.12", "version_normalized": "1.6.12.0", "source": { "type": "git", "url": "https://github.com/bovigo/vfsStream.git", "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", "shasum": "" }, "require": { "php": ">=7.1.0" }, "require-dev": { "phpunit/phpunit": "^7.5||^8.5||^9.6", "yoast/phpunit-polyfills": "^2.0" }, "time": "2024-08-29T18:43:31+00:00", "type": "library", "extra": { "branch-alias": { "dev-master": "1.6.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "org\\bovigo\\vfs\\": "src/main/php" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Frank Kleine", "homepage": "http://frankkleine.de/", "role": "Developer" } ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", "support": { "issues": "https://github.com/bovigo/vfsStream/issues", "source": "https://github.com/bovigo/vfsStream/tree/master", "wiki": "https://github.com/bovigo/vfsStream/wiki" }, "install-path": "../mikey179/vfsstream" }, { "name": "myclabs/deep-copy", "version": "1.14.0", "version_normalized": "1.14.0.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", "reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae", "reference": "8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae", "shasum": "" }, "require": { "php": "^8.0" }, "conflict": { "doctrine/collections": "<1.6.8", "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "time": "2026-08-11T10:17:44+00:00", "type": "library", "installation-source": "dist", "autoload": { "files": [ "src/DeepCopy/deep_copy.php" ], "psr-4": { "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Create deep copies (clones) of your objects", "keywords": [ "clone", "copy", "duplicate", "object", "object graph" ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", "source": "https://github.com/myclabs/DeepCopy/tree/1.14.0" }, "funding": [ { "url": "https://github.com/mnapoli", "type": "github" } ], "install-path": "../myclabs/deep-copy" }, { "name": "nikic/php-parser", "version": "v5.8.0", "version_normalized": "5.8.0.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/044a6a392ff8ad0d61f14370a5fbbd0a0107152f", "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f", "shasum": "" }, "require": { "ext-json": "*", "ext-tokenizer": "*", "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^9.0" }, "time": "2026-07-04T14:30:18+00:00", "bin": [ "bin/php-parse" ], "type": "library", "extra": { "branch-alias": { "dev-master": "5.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Nikita Popov" } ], "description": "A PHP parser written in PHP", "keywords": [ "parser", "php" ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", "source": "https://github.com/nikic/PHP-Parser/tree/v5.8.0" }, "install-path": "../nikic/php-parser" }, { "name": "phar-io/manifest", "version": "2.0.4", "version_normalized": "2.0.4.0", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", "php": "^7.2 || ^8.0" }, "time": "2024-03-03T12:33:53+00:00", "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, "funding": [ { "url": "https://github.com/theseer", "type": "github" } ], "install-path": "../phar-io/manifest" }, { "name": "phar-io/version", "version": "3.2.1", "version_normalized": "3.2.1.0", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "time": "2022-02-21T01:04:05+00:00", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", "source": "https://github.com/phar-io/version/tree/3.2.1" }, "install-path": "../phar-io/version" }, { "name": "php-di/invoker", "version": "2.3.7", "version_normalized": "2.3.7.0", "source": { "type": "git", "url": "https://github.com/PHP-DI/Invoker.git", "reference": "3c1ddfdef181431fbc4be83378f6d036d59e81e1" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/3c1ddfdef181431fbc4be83378f6d036d59e81e1", "reference": "3c1ddfdef181431fbc4be83378f6d036d59e81e1", "shasum": "" }, "require": { "php": ">=7.3", "psr/container": "^1.0|^2.0" }, "require-dev": { "athletic/athletic": "~0.1.8", "mnapoli/hard-mode": "~0.3.0", "phpunit/phpunit": "^9.0 || ^10 || ^11 || ^12" }, "time": "2025-08-30T10:22:22+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { "Invoker\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Generic and extensible callable invoker", "homepage": "https://github.com/PHP-DI/Invoker", "keywords": [ "callable", "dependency", "dependency-injection", "injection", "invoke", "invoker" ], "support": { "issues": "https://github.com/PHP-DI/Invoker/issues", "source": "https://github.com/PHP-DI/Invoker/tree/2.3.7" }, "funding": [ { "url": "https://github.com/mnapoli", "type": "github" } ], "install-path": "../php-di/invoker" }, { "name": "php-di/php-di", "version": "7.1.1", "version_normalized": "7.1.1.0", "source": { "type": "git", "url": "https://github.com/PHP-DI/PHP-DI.git", "reference": "f88054cc052e40dbe7b383c8817c19442d480352" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/f88054cc052e40dbe7b383c8817c19442d480352", "reference": "f88054cc052e40dbe7b383c8817c19442d480352", "shasum": "" }, "require": { "laravel/serializable-closure": "^1.0 || ^2.0", "php": ">=8.0", "php-di/invoker": "^2.0", "psr/container": "^1.1 || ^2.0" }, "provide": { "psr/container-implementation": "^1.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", "friendsofphp/proxy-manager-lts": "^1", "mnapoli/phpunit-easymock": "^1.3", "phpunit/phpunit": "^9.6 || ^10 || ^11", "vimeo/psalm": "^5|^6" }, "suggest": { "friendsofphp/proxy-manager-lts": "Install it if you want to use lazy injection (version ^1)" }, "time": "2025-08-16T11:10:48+00:00", "type": "library", "installation-source": "dist", "autoload": { "files": [ "src/functions.php" ], "psr-4": { "DI\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "The dependency injection container for humans", "homepage": "https://php-di.org/", "keywords": [ "PSR-11", "container", "container-interop", "dependency injection", "di", "ioc", "psr11" ], "support": { "issues": "https://github.com/PHP-DI/PHP-DI/issues", "source": "https://github.com/PHP-DI/PHP-DI/tree/7.1.1" }, "funding": [ { "url": "https://github.com/mnapoli", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/php-di/php-di", "type": "tidelift" } ], "install-path": "../php-di/php-di" }, { "name": "phpstan/phpdoc-parser", "version": "2.3.3", "version_normalized": "2.3.3.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", "reference": "fb19eedd2bb67ff8cf7a5502ad329e701d6398a3", "shasum": "" }, "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" }, "time": "2026-07-08T07:01:06+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { "PHPStan\\PhpDocParser\\": [ "src/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.3" }, "install-path": "../phpstan/phpdoc-parser" }, { "name": "phpstan/phpstan", "version": "1.12.34", "version_normalized": "1.12.34.0", "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/4dd89ca7aa30fdc6760be21550d583bcc32e8476", "reference": "4dd89ca7aa30fdc6760be21550d583bcc32e8476", "shasum": "" }, "require": { "php": "^7.2|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" }, "time": "2026-07-28T10:04:39+00:00", "bin": [ "phpstan", "phpstan.phar" ], "type": "library", "installation-source": "dist", "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" } ], "install-path": "../phpstan/phpstan" }, { "name": "phpunit/php-code-coverage", "version": "10.1.16", "version_normalized": "10.1.16.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", "reference": "7e308268858ed6baedc8704a304727d20bc07c77", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", "nikic/php-parser": "^4.19.1 || ^5.1.0", "php": ">=8.1", "phpunit/php-file-iterator": "^4.1.0", "phpunit/php-text-template": "^3.0.1", "sebastian/code-unit-reverse-lookup": "^3.0.0", "sebastian/complexity": "^3.2.0", "sebastian/environment": "^6.1.0", "sebastian/lines-of-code": "^2.0.2", "sebastian/version": "^4.0.1", "theseer/tokenizer": "^1.2.3" }, "require-dev": { "phpunit/phpunit": "^10.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "time": "2024-08-22T04:31:57+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "10.1.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ "coverage", "testing", "xunit" ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../phpunit/php-code-coverage" }, { "name": "phpunit/php-file-iterator", "version": "4.1.0", "version_normalized": "4.1.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-08-31T06:24:48+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ "filesystem", "iterator" ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../phpunit/php-file-iterator" }, { "name": "phpunit/php-invoker", "version": "4.0.0", "version_normalized": "4.0.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "ext-pcntl": "*", "phpunit/phpunit": "^10.0" }, "suggest": { "ext-pcntl": "*" }, "time": "2023-02-03T06:56:09+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Invoke callables with a timeout", "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ "process" ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../phpunit/php-invoker" }, { "name": "phpunit/php-text-template", "version": "3.0.1", "version_normalized": "3.0.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-08-31T14:07:24+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "3.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ "template" ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../phpunit/php-text-template" }, { "name": "phpunit/php-timer", "version": "6.0.0", "version_normalized": "6.0.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-02-03T06:57:52+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "6.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ "timer" ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../phpunit/php-timer" }, { "name": "phpunit/phpunit", "version": "10.5.64", "version_normalized": "10.5.64.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", "reference": "0e8c1d19cea35ad97d4887f363d07c78e30fbf06" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e8c1d19cea35ad97d4887f363d07c78e30fbf06", "reference": "0e8c1d19cea35ad97d4887f363d07c78e30fbf06", "shasum": "" }, "require": { "ext-dom": "*", "ext-filter": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.1", "phpunit/php-code-coverage": "^10.1.16", "phpunit/php-file-iterator": "^4.1.0", "phpunit/php-invoker": "^4.0.0", "phpunit/php-text-template": "^3.0.1", "phpunit/php-timer": "^6.0.0", "sebastian/cli-parser": "^2.0.1", "sebastian/code-unit": "^2.0.0", "sebastian/comparator": "^5.0.5", "sebastian/diff": "^5.1.1", "sebastian/environment": "^6.1.0", "sebastian/exporter": "^5.1.4", "sebastian/global-state": "^6.0.2", "sebastian/object-enumerator": "^5.0.0", "sebastian/recursion-context": "^5.0.1", "sebastian/type": "^4.0.0", "sebastian/version": "^4.0.1" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" }, "time": "2026-07-06T14:50:35+00:00", "bin": [ "phpunit" ], "type": "library", "extra": { "branch-alias": { "dev-main": "10.5-dev" } }, "installation-source": "dist", "autoload": { "files": [ "src/Framework/Assert/Functions.php" ], "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.64" }, "funding": [ { "url": "https://phpunit.de/sponsoring.html", "type": "other" } ], "install-path": "../phpunit/phpunit" }, { "name": "psr/container", "version": "2.0.2", "version_normalized": "2.0.2.0", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { "php": ">=7.4.0" }, "time": "2021-11-05T16:47:00+00:00", "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "installation-source": "dist", "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/2.0.2" }, "install-path": "../psr/container" }, { "name": "psr/http-client", "version": "1.0.3", "version_normalized": "1.0.3.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { "php": "^7.0 || ^8.0", "psr/http-message": "^1.0 || ^2.0" }, "time": "2023-09-23T14:17:50+00:00", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Psr\\Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", "homepage": "https://github.com/php-fig/http-client", "keywords": [ "http", "http-client", "psr", "psr-18" ], "support": { "source": "https://github.com/php-fig/http-client" }, "install-path": "../psr/http-client" }, { "name": "psr/http-factory", "version": "1.1.0", "version_normalized": "1.1.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "time": "2024-04-15T12:06:14+00:00", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "https://www.php-fig.org/" } ], "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", "message", "psr", "psr-17", "psr-7", "request", "response" ], "support": { "source": "https://github.com/php-fig/http-factory" }, "install-path": "../psr/http-factory" }, { "name": "psr/http-message", "version": "2.0", "version_normalized": "2.0.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "time": "2023-04-04T09:54:51+00:00", "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", "homepage": "https://github.com/php-fig/http-message", "keywords": [ "http", "http-message", "psr", "psr-7", "request", "response" ], "support": { "source": "https://github.com/php-fig/http-message/tree/2.0" }, "install-path": "../psr/http-message" }, { "name": "psr/log", "version": "2.0.0", "version_normalized": "2.0.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", "shasum": "" }, "require": { "php": ">=8.0.0" }, "time": "2021-07-14T16:41:46+00:00", "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Psr\\Log\\": "src" } }, "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/2.0.0" }, "install-path": "../psr/log" }, { "name": "ralouphie/getallheaders", "version": "3.0.3", "version_normalized": "3.0.3.0", "source": { "type": "git", "url": "https://github.com/ralouphie/getallheaders.git", "reference": "120b605dfeb996808c31b6477290a714d356e822" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", "reference": "120b605dfeb996808c31b6477290a714d356e822", "shasum": "" }, "require": { "php": ">=5.6" }, "require-dev": { "php-coveralls/php-coveralls": "^2.1", "phpunit/phpunit": "^5 || ^6.5" }, "time": "2019-03-08T08:55:37+00:00", "type": "library", "installation-source": "dist", "autoload": { "files": [ "src/getallheaders.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Ralph Khattar", "email": "ralph.khattar@gmail.com" } ], "description": "A polyfill for getallheaders.", "support": { "issues": "https://github.com/ralouphie/getallheaders/issues", "source": "https://github.com/ralouphie/getallheaders/tree/develop" }, "install-path": "../ralouphie/getallheaders" }, { "name": "rector/rector", "version": "1.2.10", "version_normalized": "1.2.10.0", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", "reference": "40f9cf38c05296bd32f444121336a521a293fa61" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/rectorphp/rector/zipball/40f9cf38c05296bd32f444121336a521a293fa61", "reference": "40f9cf38c05296bd32f444121336a521a293fa61", "shasum": "" }, "require": { "php": "^7.2|^8.0", "phpstan/phpstan": "^1.12.5" }, "conflict": { "rector/rector-doctrine": "*", "rector/rector-downgrade-php": "*", "rector/rector-phpunit": "*", "rector/rector-symfony": "*" }, "suggest": { "ext-dom": "To manipulate phpunit.xml via the custom-rule command" }, "time": "2024-11-08T13:59:10+00:00", "bin": [ "bin/rector" ], "type": "library", "installation-source": "dist", "autoload": { "files": [ "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Instant Upgrade and Automated Refactoring of any PHP code", "keywords": [ "automation", "dev", "migration", "refactoring" ], "support": { "issues": "https://github.com/rectorphp/rector/issues", "source": "https://github.com/rectorphp/rector/tree/1.2.10" }, "funding": [ { "url": "https://github.com/tomasvotruba", "type": "github" } ], "install-path": "../rector/rector" }, { "name": "sebastian/cli-parser", "version": "2.0.1", "version_normalized": "2.0.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2024-03-02T07:12:49+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "2.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library for parsing CLI options", "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/cli-parser" }, { "name": "sebastian/code-unit", "version": "2.0.0", "version_normalized": "2.0.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-02-03T06:58:43+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "2.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Collection of value objects that represent the PHP code units", "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/code-unit" }, { "name": "sebastian/code-unit-reverse-lookup", "version": "3.0.0", "version_normalized": "3.0.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-02-03T06:59:15+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "3.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/code-unit-reverse-lookup" }, { "name": "sebastian/comparator", "version": "5.0.5", "version_normalized": "5.0.5.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d", "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", "php": ">=8.1", "sebastian/diff": "^5.0", "sebastian/exporter": "^5.0" }, "require-dev": { "phpunit/phpunit": "^10.5" }, "time": "2026-01-24T09:25:16+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" } ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.5" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" }, { "url": "https://liberapay.com/sebastianbergmann", "type": "liberapay" }, { "url": "https://thanks.dev/u/gh/sebastianbergmann", "type": "thanks_dev" }, { "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", "type": "tidelift" } ], "install-path": "../sebastian/comparator" }, { "name": "sebastian/complexity", "version": "3.2.0", "version_normalized": "3.2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-12-21T08:37:17+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "3.2-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library for calculating the complexity of PHP code units", "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/complexity" }, { "name": "sebastian/diff", "version": "5.1.1", "version_normalized": "5.1.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0", "symfony/process": "^6.4" }, "time": "2024-03-02T07:15:17+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "5.1-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Kore Nordmann", "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ "diff", "udiff", "unidiff", "unified diff" ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/diff" }, { "name": "sebastian/environment", "version": "6.1.0", "version_normalized": "6.1.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "suggest": { "ext-posix": "*" }, "time": "2024-03-23T08:47:14+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "6.1-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", "hhvm" ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/environment" }, { "name": "sebastian/exporter", "version": "5.1.4", "version_normalized": "5.1.4.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", "reference": "0735b90f4da94969541dac1da743446e276defa6" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", "reference": "0735b90f4da94969541dac1da743446e276defa6", "shasum": "" }, "require": { "ext-mbstring": "*", "php": ">=8.1", "sebastian/recursion-context": "^5.0" }, "require-dev": { "phpunit/phpunit": "^10.5" }, "time": "2025-09-24T06:09:11+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "5.1-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Adam Harvey", "email": "aharvey@php.net" }, { "name": "Bernhard Schussek", "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" }, { "url": "https://liberapay.com/sebastianbergmann", "type": "liberapay" }, { "url": "https://thanks.dev/u/gh/sebastianbergmann", "type": "thanks_dev" }, { "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", "type": "tidelift" } ], "install-path": "../sebastian/exporter" }, { "name": "sebastian/global-state", "version": "6.0.2", "version_normalized": "6.0.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { "php": ">=8.1", "sebastian/object-reflector": "^3.0", "sebastian/recursion-context": "^5.0" }, "require-dev": { "ext-dom": "*", "phpunit/phpunit": "^10.0" }, "time": "2024-03-02T07:19:19+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "6.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Snapshotting of global state", "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/global-state" }, { "name": "sebastian/lines-of-code", "version": "2.0.2", "version_normalized": "2.0.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-12-21T08:38:20+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "2.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library for counting the lines of code in PHP source code", "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/lines-of-code" }, { "name": "sebastian/object-enumerator", "version": "5.0.0", "version_normalized": "5.0.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { "php": ">=8.1", "sebastian/object-reflector": "^3.0", "sebastian/recursion-context": "^5.0" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-02-03T07:08:32+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/object-enumerator" }, { "name": "sebastian/object-reflector", "version": "3.0.0", "version_normalized": "3.0.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-02-03T07:06:18+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "3.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/object-reflector" }, { "name": "sebastian/recursion-context", "version": "5.0.2", "version_normalized": "5.0.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", "reference": "5d32fe257a9b39cb63146924d6b4e32a22d4502a" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5d32fe257a9b39cb63146924d6b4e32a22d4502a", "reference": "5d32fe257a9b39cb63146924d6b4e32a22d4502a", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.5" }, "time": "2026-08-11T05:27:39+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides functionality to recursively process PHP variables", "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" }, { "url": "https://liberapay.com/sebastianbergmann", "type": "liberapay" }, { "url": "https://thanks.dev/u/gh/sebastianbergmann", "type": "thanks_dev" }, { "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", "type": "tidelift" } ], "install-path": "../sebastian/recursion-context" }, { "name": "sebastian/type", "version": "4.0.0", "version_normalized": "4.0.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "phpunit/phpunit": "^10.0" }, "time": "2023-02-03T07:10:45+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/type" }, { "name": "sebastian/version", "version": "4.0.1", "version_normalized": "4.0.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { "php": ">=8.1" }, "time": "2023-02-07T11:34:05+00:00", "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "install-path": "../sebastian/version" }, { "name": "slevomat/coding-standard", "version": "8.22.1", "version_normalized": "8.22.1.0", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/1dd80bf3b93692bedb21a6623c496887fad05fec", "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.1.2", "php": "^7.4 || ^8.0", "phpstan/phpdoc-parser": "^2.3.0", "squizlabs/php_codesniffer": "^3.13.4" }, "require-dev": { "phing/phing": "3.0.1|3.1.0", "php-parallel-lint/php-parallel-lint": "1.4.0", "phpstan/phpstan": "2.1.24", "phpstan/phpstan-deprecation-rules": "2.0.3", "phpstan/phpstan-phpunit": "2.0.7", "phpstan/phpstan-strict-rules": "2.0.6", "phpunit/phpunit": "9.6.8|10.5.48|11.4.4|11.5.36|12.3.10" }, "time": "2025-09-13T08:53:30+00:00", "type": "phpcodesniffer-standard", "extra": { "branch-alias": { "dev-master": "8.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "SlevomatCodingStandard\\": "SlevomatCodingStandard/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", "keywords": [ "dev", "phpcs" ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", "source": "https://github.com/slevomat/coding-standard/tree/8.22.1" }, "funding": [ { "url": "https://github.com/kukulich", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", "type": "tidelift" } ], "install-path": "../slevomat/coding-standard" }, { "name": "squizlabs/php_codesniffer", "version": "3.13.6", "version_normalized": "3.13.6.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", "reference": "4c378e1a528ea066890fc2397cbdd2f94eb2fc91" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/4c378e1a528ea066890fc2397cbdd2f94eb2fc91", "reference": "4c378e1a528ea066890fc2397cbdd2f94eb2fc91", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", "php": ">=5.4.0" }, "require-dev": { "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "time": "2026-08-06T00:17:32+00:00", "bin": [ "bin/phpcbf", "bin/phpcs" ], "type": "library", "installation-source": "dist", "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Greg Sherwood", "role": "Former lead" }, { "name": "Juliette Reinders Folmer", "role": "Current lead" }, { "name": "Contributors", "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", "standards", "static analysis" ], "support": { "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, "funding": [ { "url": "https://github.com/PHPCSStandards", "type": "github" }, { "url": "https://github.com/jrfnl", "type": "github" }, { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" }, { "url": "https://thanks.dev/u/gh/phpcsstandards", "type": "thanks_dev" } ], "install-path": "../squizlabs/php_codesniffer" }, { "name": "symfony/console", "version": "v5.4.47", "version_normalized": "5.4.47.0", "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": "" }, "time": "2024-11-06T11:30:55+00:00", "type": "library", "installation-source": "dist", "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" } ], "install-path": "../symfony/console" }, { "name": "symfony/deprecation-contracts", "version": "v3.7.1", "version_normalized": "3.7.1.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", "shasum": "" }, "require": { "php": ">=8.1" }, "time": "2026-06-05T06:23:12+00:00", "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/contracts", "name": "symfony/contracts" }, "branch-alias": { "dev-main": "3.7-dev" } }, "installation-source": "dist", "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/v3.7.1" }, "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" } ], "install-path": "../symfony/deprecation-contracts" }, { "name": "symfony/finder", "version": "v6.4.42", "version_normalized": "6.4.42.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", "reference": "0b73dac42493acbadbba644207a715b254e9b029" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/finder/zipball/0b73dac42493acbadbba644207a715b254e9b029", "reference": "0b73dac42493acbadbba644207a715b254e9b029", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { "symfony/filesystem": "^6.0|^7.0" }, "time": "2026-06-26T15:18:24+00:00", "type": "library", "installation-source": "dist", "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/v6.4.42" }, "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" } ], "install-path": "../symfony/finder" }, { "name": "symfony/polyfill-ctype", "version": "v1.37.0", "version_normalized": "1.37.0.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" }, "time": "2026-04-10T16:19:22+00:00", "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "installation-source": "dist", "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.37.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" } ], "install-path": "../symfony/polyfill-ctype" }, { "name": "symfony/polyfill-intl-grapheme", "version": "v1.41.0", "version_normalized": "1.41.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", "shasum": "" }, "require": { "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "time": "2026-07-28T08:25:59+00:00", "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "installation-source": "dist", "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.41.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" } ], "install-path": "../symfony/polyfill-intl-grapheme" }, { "name": "symfony/polyfill-intl-normalizer", "version": "v1.38.0", "version_normalized": "1.38.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b", "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b", "shasum": "" }, "require": { "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "time": "2026-05-25T13:48:31+00:00", "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "installation-source": "dist", "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.38.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" } ], "install-path": "../symfony/polyfill-intl-normalizer" }, { "name": "symfony/polyfill-mbstring", "version": "v1.38.2", "version_normalized": "1.38.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", "shasum": "" }, "require": { "ext-iconv": "*", "php": ">=7.2" }, "provide": { "ext-mbstring": "*" }, "suggest": { "ext-mbstring": "For best performance" }, "time": "2026-05-27T06:59:30+00:00", "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "installation-source": "dist", "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.38.2" }, "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" } ], "install-path": "../symfony/polyfill-mbstring" }, { "name": "symfony/polyfill-php73", "version": "v1.37.0", "version_normalized": "1.37.0.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" }, "time": "2024-09-09T11:45:10+00:00", "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "installation-source": "dist", "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.37.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" } ], "install-path": "../symfony/polyfill-php73" }, { "name": "symfony/polyfill-php80", "version": "v1.37.0", "version_normalized": "1.37.0.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" }, "time": "2026-04-10T16:19:22+00:00", "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/polyfill", "name": "symfony/polyfill" } }, "installation-source": "dist", "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.37.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" } ], "install-path": "../symfony/polyfill-php80" }, { "name": "symfony/process", "version": "v6.4.41", "version_normalized": "6.4.41.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", "reference": "c8fc09bdfe9fde9aaa89b415a4477feaccec16a7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/process/zipball/c8fc09bdfe9fde9aaa89b415a4477feaccec16a7", "reference": "c8fc09bdfe9fde9aaa89b415a4477feaccec16a7", "shasum": "" }, "require": { "php": ">=8.1" }, "time": "2026-05-23T13:47:21+00:00", "type": "library", "installation-source": "dist", "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/v6.4.41" }, "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" } ], "install-path": "../symfony/process" }, { "name": "symfony/service-contracts", "version": "v3.7.1", "version_normalized": "3.7.1.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/c0a284bab1ed8aa0417e3d69250ab437739563a0", "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0", "shasum": "" }, "require": { "php": ">=8.1", "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, "time": "2026-06-16T09:55:08+00:00", "type": "library", "extra": { "thanks": { "url": "https://github.com/symfony/contracts", "name": "symfony/contracts" }, "branch-alias": { "dev-main": "3.7-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" }, "exclude-from-classmap": [ "/Test/" ] }, "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/v3.7.1" }, "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" } ], "install-path": "../symfony/service-contracts" }, { "name": "symfony/string", "version": "v6.4.43", "version_normalized": "6.4.43.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", "reference": "2a8d515c3eaa5d33cf76d5fa277cdadd0a4e5b49" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/string/zipball/2a8d515c3eaa5d33cf76d5fa277cdadd0a4e5b49", "reference": "2a8d515c3eaa5d33cf76d5fa277cdadd0a4e5b49", "shasum": "" }, "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" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "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" }, "time": "2026-07-28T07:28:15+00:00", "type": "library", "installation-source": "dist", "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/v6.4.43" }, "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" } ], "install-path": "../symfony/string" }, { "name": "theseer/tokenizer", "version": "1.3.1", "version_normalized": "1.3.1.0", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", "php": "^7.2 || ^8.0" }, "time": "2025-11-17T20:03:58+00:00", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { "url": "https://github.com/theseer", "type": "github" } ], "install-path": "../theseer/tokenizer" } ], "dev": true, "dev-package-names": [ "dealerdirect/phpcodesniffer-composer-installer", "mikey179/vfsstream", "myclabs/deep-copy", "nikic/php-parser", "phar-io/manifest", "phar-io/version", "phpstan/phpdoc-parser", "phpstan/phpstan", "phpunit/php-code-coverage", "phpunit/php-file-iterator", "phpunit/php-invoker", "phpunit/php-text-template", "phpunit/php-timer", "phpunit/phpunit", "psr/log", "rector/rector", "sebastian/cli-parser", "sebastian/code-unit", "sebastian/code-unit-reverse-lookup", "sebastian/comparator", "sebastian/complexity", "sebastian/diff", "sebastian/environment", "sebastian/exporter", "sebastian/global-state", "sebastian/lines-of-code", "sebastian/object-enumerator", "sebastian/object-reflector", "sebastian/recursion-context", "sebastian/type", "sebastian/version", "slevomat/coding-standard", "squizlabs/php_codesniffer", "theseer/tokenizer" ] } array( 'name' => 'plesk/wappspector', 'pretty_version' => '0.2.9', 'version' => '0.2.9.0', 'reference' => null, 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => true, ), 'versions' => array( 'clue/phar-composer' => array( 'pretty_version' => 'v1.4.0', 'version' => '1.4.0.0', 'reference' => '0cae6984e0da45639881d3b26442d525b8b65406', 'type' => 'library', 'install_path' => __DIR__ . '/../clue/phar-composer', 'aliases' => array(), 'dev_requirement' => false, ), 'dealerdirect/phpcodesniffer-composer-installer' => array( 'pretty_version' => 'v1.2.1', 'version' => '1.2.1.0', 'reference' => '963f0c67bffde0eac41b56be71ac0e8ba132f0bd', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../dealerdirect/phpcodesniffer-composer-installer', 'aliases' => array(), 'dev_requirement' => true, ), 'doctrine/inflector' => array( 'pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '6d6c96277ea252fc1304627204c3d5e6e15faa3b', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/inflector', 'aliases' => array(), 'dev_requirement' => false, ), 'guzzlehttp/guzzle' => array( 'pretty_version' => '7.15.3', 'version' => '7.15.3.0', 'reference' => 'ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/guzzle', 'aliases' => array(), 'dev_requirement' => false, ), 'guzzlehttp/promises' => array( 'pretty_version' => '2.5.2', 'version' => '2.5.2.0', 'reference' => '2823687acff28b2dbe67b2508a6b300e2c3fa4ce', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/promises', 'aliases' => array(), 'dev_requirement' => false, ), 'guzzlehttp/psr7' => array( 'pretty_version' => '2.13.0', 'version' => '2.13.0.0', 'reference' => 'dad89620b7a6edb60c15858442eb2e408b45d8f4', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/psr7', 'aliases' => array(), 'dev_requirement' => false, ), 'knplabs/packagist-api' => array( 'pretty_version' => 'v1.7.2', 'version' => '1.7.2.0', 'reference' => '4feae228a4505c1cd817da61e752e5dea2b22c2d', 'type' => 'library', 'install_path' => __DIR__ . '/../knplabs/packagist-api', 'aliases' => array(), 'dev_requirement' => false, ), 'laravel/serializable-closure' => array( 'pretty_version' => 'v2.0.15', 'version' => '2.0.15.0', 'reference' => 'dccd8bcb851bb03fcc005df650b708b57cc52661', 'type' => 'library', 'install_path' => __DIR__ . '/../laravel/serializable-closure', 'aliases' => array(), 'dev_requirement' => false, ), 'league/flysystem' => array( 'pretty_version' => '3.35.2', 'version' => '3.35.2.0', 'reference' => 'b277b5dc3d56650b68904117124e79c851e12376', 'type' => 'library', 'install_path' => __DIR__ . '/../league/flysystem', 'aliases' => array(), 'dev_requirement' => false, ), 'league/flysystem-local' => array( 'pretty_version' => '3.31.0', 'version' => '3.31.0.0', 'reference' => '2f669db18a4c20c755c2bb7d3a7b0b2340488079', 'type' => 'library', 'install_path' => __DIR__ . '/../league/flysystem-local', 'aliases' => array(), 'dev_requirement' => false, ), 'league/mime-type-detection' => array( 'pretty_version' => '1.17.0', 'version' => '1.17.0.0', 'reference' => 'f5f47eff7c48ed1003069a2ca67f316fb4021c76', 'type' => 'library', 'install_path' => __DIR__ . '/../league/mime-type-detection', 'aliases' => array(), 'dev_requirement' => false, ), 'mikey179/vfsstream' => array( 'pretty_version' => 'v1.6.12', 'version' => '1.6.12.0', 'reference' => 'fe695ec993e0a55c3abdda10a9364eb31c6f1bf0', 'type' => 'library', 'install_path' => __DIR__ . '/../mikey179/vfsstream', 'aliases' => array(), 'dev_requirement' => true, ), 'myclabs/deep-copy' => array( 'pretty_version' => '1.14.0', 'version' => '1.14.0.0', 'reference' => '8680aa248f8e07bc8fb43f56f0f5fc77a0c96aae', 'type' => 'library', 'install_path' => __DIR__ . '/../myclabs/deep-copy', 'aliases' => array(), 'dev_requirement' => true, ), 'nikic/php-parser' => array( 'pretty_version' => 'v5.8.0', 'version' => '5.8.0.0', 'reference' => '044a6a392ff8ad0d61f14370a5fbbd0a0107152f', '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, ), 'php-di/invoker' => array( 'pretty_version' => '2.3.7', 'version' => '2.3.7.0', 'reference' => '3c1ddfdef181431fbc4be83378f6d036d59e81e1', 'type' => 'library', 'install_path' => __DIR__ . '/../php-di/invoker', 'aliases' => array(), 'dev_requirement' => false, ), 'php-di/php-di' => array( 'pretty_version' => '7.1.1', 'version' => '7.1.1.0', 'reference' => 'f88054cc052e40dbe7b383c8817c19442d480352', 'type' => 'library', 'install_path' => __DIR__ . '/../php-di/php-di', 'aliases' => array(), 'dev_requirement' => false, ), 'phpstan/phpdoc-parser' => array( 'pretty_version' => '2.3.3', 'version' => '2.3.3.0', 'reference' => 'fb19eedd2bb67ff8cf7a5502ad329e701d6398a3', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', 'aliases' => array(), 'dev_requirement' => true, ), 'phpstan/phpstan' => array( 'pretty_version' => '1.12.34', 'version' => '1.12.34.0', 'reference' => '4dd89ca7aa30fdc6760be21550d583bcc32e8476', 'type' => 'library', 'install_path' => __DIR__ . '/../phpstan/phpstan', 'aliases' => array(), 'dev_requirement' => true, ), 'phpunit/php-code-coverage' => array( 'pretty_version' => '10.1.16', 'version' => '10.1.16.0', 'reference' => '7e308268858ed6baedc8704a304727d20bc07c77', '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.64', 'version' => '10.5.64.0', 'reference' => '0e8c1d19cea35ad97d4887f363d07c78e30fbf06', 'type' => 'library', 'install_path' => __DIR__ . '/../phpunit/phpunit', 'aliases' => array(), 'dev_requirement' => true, ), 'plesk/wappspector' => array( 'pretty_version' => '0.2.9', 'version' => '0.2.9.0', 'reference' => null, 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false, ), '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.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-client-implementation' => array( 'dev_requirement' => false, 'provided' => array( 0 => '1.0', ), ), '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-factory-implementation' => array( 'dev_requirement' => false, 'provided' => array( 0 => '1.0', ), ), '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/http-message-implementation' => array( 'dev_requirement' => false, 'provided' => array( 0 => '1.0', ), ), 'psr/log' => array( 'pretty_version' => '2.0.0', 'version' => '2.0.0.0', 'reference' => 'ef29f6d262798707a9edd554e2b82517ef3a9376', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/log', 'aliases' => array(), 'dev_requirement' => true, ), 'psr/log-implementation' => array( 'dev_requirement' => false, 'provided' => array( 0 => '1.0|2.0', ), ), 'ralouphie/getallheaders' => array( 'pretty_version' => '3.0.3', 'version' => '3.0.3.0', 'reference' => '120b605dfeb996808c31b6477290a714d356e822', 'type' => 'library', 'install_path' => __DIR__ . '/../ralouphie/getallheaders', 'aliases' => array(), 'dev_requirement' => false, ), 'rector/rector' => array( 'pretty_version' => '1.2.10', 'version' => '1.2.10.0', 'reference' => '40f9cf38c05296bd32f444121336a521a293fa61', 'type' => 'library', 'install_path' => __DIR__ . '/../rector/rector', '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.5', 'version' => '5.0.5.0', 'reference' => '55dfef806eb7dfeb6e7a6935601fef866f8ca48d', '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.4', 'version' => '5.1.4.0', 'reference' => '0735b90f4da94969541dac1da743446e276defa6', '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.2', 'version' => '5.0.2.0', 'reference' => '5d32fe257a9b39cb63146924d6b4e32a22d4502a', '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, ), 'slevomat/coding-standard' => array( 'pretty_version' => '8.22.1', 'version' => '8.22.1.0', 'reference' => '1dd80bf3b93692bedb21a6623c496887fad05fec', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../slevomat/coding-standard', 'aliases' => array(), 'dev_requirement' => true, ), 'squizlabs/php_codesniffer' => array( 'pretty_version' => '3.13.6', 'version' => '3.13.6.0', 'reference' => '4c378e1a528ea066890fc2397cbdd2f94eb2fc91', 'type' => 'library', 'install_path' => __DIR__ . '/../squizlabs/php_codesniffer', 'aliases' => array(), 'dev_requirement' => true, ), 'symfony/console' => array( 'pretty_version' => 'v5.4.47', 'version' => '5.4.47.0', 'reference' => 'c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/deprecation-contracts' => array( 'pretty_version' => 'v3.7.1', 'version' => '3.7.1.0', 'reference' => 'f3202fa1b5097b0af062dc978b32ecf63404e31d', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/finder' => array( 'pretty_version' => 'v6.4.42', 'version' => '6.4.42.0', 'reference' => '0b73dac42493acbadbba644207a715b254e9b029', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-ctype' => array( 'pretty_version' => 'v1.37.0', 'version' => '1.37.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.41.0', 'version' => '1.41.0.0', 'reference' => 'bb899c1db0aa8127dc3afe8cda4a67eb24915f8d', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-normalizer' => array( 'pretty_version' => 'v1.38.0', 'version' => '1.38.0.0', 'reference' => '2d446c214bdbe5b71bde5011b060a05fece3ae6b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-mbstring' => array( 'pretty_version' => 'v1.38.2', 'version' => '1.38.2.0', 'reference' => 'd3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php73' => array( 'pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php73', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php80' => array( 'pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => 'dfb55726c3a76ea3b6459fcfda1ec2d80a682411', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/process' => array( 'pretty_version' => 'v6.4.41', 'version' => '6.4.41.0', 'reference' => 'c8fc09bdfe9fde9aaa89b415a4477feaccec16a7', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/process', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/service-contracts' => array( 'pretty_version' => 'v3.7.1', 'version' => '3.7.1.0', 'reference' => 'c0a284bab1ed8aa0417e3d69250ab437739563a0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/string' => array( 'pretty_version' => 'v6.4.43', 'version' => '6.4.43.0', 'reference' => '2a8d515c3eaa5d33cf76d5fa277cdadd0a4e5b49', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), 'dev_requirement' => false, ), 'theseer/tokenizer' => array( 'pretty_version' => '1.3.1', 'version' => '1.3.1.0', 'reference' => 'b7489ce515e168639d17feec34b8847c326b0b3c', 'type' => 'library', 'install_path' => __DIR__ . '/../theseer/tokenizer', 'aliases' => array(), 'dev_requirement' => true, ), ), ); = 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) ); } # Changelog ## 1.4.0 (2022-02-14) * Feature: Windows support, improve package path detection, and retry rename to fix slow network drives. (#129 and #130 by @clue) * Feature / Fix: Escape binary path when executing system binaries (git, php, composer). (#128 by @clue) * Drop legacy HHVM support due to lack of support. (#127 by @clue) ## 1.3.0 (2021-12-29) * Feature: Support Symfony 6 and PHP 8.1 release. (#122 and #123 by @clue) * Feature: Bundle `StubGenerator` and `Extract` from legacy herrera-io/box v1.6.1. (#119 by @clue) * Feature / Fix: Fix check for valid package URL. (#117 by @icedream) * Update project setup, use PSR-4 autoloading, drop `composer.lock` and instead lock PHP version when building phar. (#120 and #124 by @clue and #118 by @PaulRotmann) * Improve test suite and add `.gitattributes` to exclude dev files from exports. Update test suite to support PHPUnit 9 and test against PHP 8.1 release. (#121 and #125 by @clue) ## 1.2.0 (2020-12-11) * Feature: Support Composer 2.0! (#114 by @thojou and @clue) * Minor documentation improvements and simplify install instructions. (#98 and #99 by @clue) * Use GitHub actions for continuous integration (CI). (#112 by @SimonFrings and #113 by @szepeviktor) ## 1.1.0 (2019-11-22) * Feature: Update all dependencies and improve forward compatibility with symfony/console v5 through legacy v2.5. (#87 by @clue) * Feature: Significantly improve performance when adding phar contents. (#90 by @clue) * Feature: Support cloning projects from git SSH URLs. (#96 by @clue) * Feature: Ignore packages without autoload definition and missing vendor directory. (#94 by @clue) * Feature: Write phar to temporary file to support any extension and overwriting. (#93 by @clue) * Feature / Fix: Disable install subcommand on Windows. (#95 by @clue) * Improve test suite by adding PHPUnit to require-dev and support legacy PHP 5.3 through PHP 7.2 and HHVM, add tests for all commands and perform some minor code cleanup/maintenance, minor internal refactoring to clean up some unneeded code duplication and unneeded references and remove dedicated bundler classes, always bundle complete package. (#85, #86, #89 and #92 by @clue) * Add build script removing uneeded files and update development docs. (#91 by @clue) ## 1.0.0 (2015-11-15) * First stable release, now following SemVer. * Feature: Can now be installed as a `require-dev` Composer dependency and supports running as `./vendor/bin/phar-composer`. (#36 by @radford) * Fix: Actually exclude `vendor/` directory. This prevents processing all vendor files twice and reduces build time by 50%. (#38 by @radford) * Fix: Fix error reporting when processing invalid project paths. (#56 by @staabm and @clue) * Fix: Fix description of `phar-composer install` command. (#47 by @staabm) * Updated documentation, tests and project structure. (#54, #57, #58 and #59 by @clue) ## 0.5.0 (2014-07-10) * Feature: The `search` command is the new default if you do not pass any command ([#13](https://github.com/clue/phar-composer/pull/13)). You can now use the following command to get started: ```bash $ phar-composer ``` * Fix: Pass through STDERR output of child processes instead of aborting ([#33](https://github.com/clue/phar-composer/pull/33)) * Fix: Do not timeout when child process takes longer than 60s. This also helps users with slower internet connections. ([#31](https://github.com/clue/phar-composer/pull/31)) * Fix: Update broken dependencies ([#18](https://github.com/clue/phar-composer/pull/18)) * Fix: Fixed an undocumented config key ([#14](https://github.com/clue/phar-composer/pull/14), thanks @mikey179) ## 0.4.0 (2013-09-12) * Feature: New `install` command will now both build the given package and then install it into the system-wide bin directory `/usr/local/bin` (usually already in your `$PATH`). This works for any package name or URL just like with the `build` command, e.g.: ```bash $ phar-composer install phpunit/phpunit ``` After some (lengthy) build output, you should now be able to run it by just issuing: ```bash $ phpunit ``` * Feature: New `search` command provides an interactive command line search. It will ask for the package name and issue an search via packagist.org's API and present a list of matching packages. So if you don't know the exact package name, you can now use the following command: ```bash $ phar-composer search boris ``` * Feature: Both `build` and `install` commands now also optionally accept an additional target directory to place the resulting phar into. ## 0.3.0 (2013-08-21) * Feature: Resulting phar files can now be executed on systems without ext-phar (#8). This vastly improves portability for legacy setups by including a small startup script which self-extracts the current archive into a temporary directory. * Feature: Resulting phar files can now be executed without the phar file name extension. E.g. this convenient feature now allows you to move your `~demo.phar` to `/usr/bin/demo` for easy system wide installations. * Fix: Resolving absolute paths to `vendor/autoload.php` ## 0.2.0 (2013-08-15) * Feature: Packages can now also be cloned from any git URLs (#9), like this: ```bash $ phar-composer build https://github.com/clue/phar-composer.git ``` The above will clone the repository and check out the default branch. You can also specify either a tag or branch name very similar to how composer works: ```bash $ phar-composer build https://github.com/clue/phar-composer.git:dev-master ``` ## 0.1.0 (2013-08-12) * Feature: Packages listed on packagist.org can now automatically be downloaded and installed prior to generating phar (#7), like this: ```bash $ phar-composer build clue/phar-composer ``` The above will download and install the latest stable tagged release (if any). You can also specify a tagged version like this: ```bash $ phar-composer build clue/phar-composer:0.1.* ``` Or you can specify to install the head of a given branch like this: ```bash $ phar-composer build clue/phar-composer:dev-master ``` ## 0.0.2 (2013-05-25) * Feature: Bundle complete project directories ## 0.0.1 (2013-05-18) * First tagged release The MIT License (MIT) Copyright (c) 2013 Christian Lück 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. # clue/phar-composer [![CI status](https://github.com/clue/phar-composer/workflows/CI/badge.svg)](https://github.com/clue/phar-composer/actions) [![downloads on GitHub](https://img.shields.io/github/downloads/clue/phar-composer/total?color=blue&label=downloads%20on%20GitHub)](https://github.com/clue/phar-composer/releases) [![installs on Packagist](https://img.shields.io/packagist/dt/clue/phar-composer?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/clue/phar-composer) Simple phar creation for any project managed via Composer. It takes your existing project's `composer.json` and builds an executable phar for your project among with its bundled dependencies. * Create a single executable phar archive, including its dependencies (i.e. vendor directory included) * Automated build process * Zero additional configuration **Table of contents** * [Support us](#support-us) * [Usage](#usage) * [phar-composer](#phar-composer) * [phar-composer build](#phar-composer-build) * [phar-composer install](#phar-composer-install) * [phar-composer search](#phar-composer-search) * [Install](#install) * [As a phar (recommended)](#as-a-phar-recommended) * [Installation using Composer](#installation-using-composer) * [Development](#development) * [Tests](#tests) * [License](#license) ## Support us We invest a lot of time developing, maintaining and updating our awesome open-source projects. You can help us sustain this high-quality of our work by [becoming a sponsor on GitHub](https://github.com/sponsors/clue). Sponsors get numerous benefits in return, see our [sponsoring page](https://github.com/sponsors/clue) for details. Let's take these projects to the next level together! 🚀 ## Usage Once clue/phar-composer is [installed](#install), you can use it via command line like this. ### phar-composer This tool supports several sub-commands. To get you started, you can now use the following simple command: ```bash $ phar-composer ``` This will actually execute the `search` command that allows you to interactively search and build any package listed on packagist (see below description of the [search command](#phar-composer-search) for more details). ### phar-composer build The `build` command can be used to build an executable single-file phar (php archive) for any project managed by composer: ```bash $ phar-composer build ~/path/to/your/project ``` The second argument can be pretty much everything that can be resolved to a valid project managed by composer. Besides creating phar archives for locally installed packages like above, you can also easily download and bundle packages from packagist.org like this: ```bash $ phar-composer build d11wtq/boris ``` The above will download and install the latest stable tagged release (if any). You can also specify a tagged version like this: ```bash $ phar-composer build clue/phar-composer:~1.0 ``` Or you can specify to install the head of a given branch like this: ```bash $ phar-composer build clue/phar-composer:dev-master ``` A similar syntax can be used to clone a package from any git URL. This is particularly useful for private packages or temporary git clones not otherwise listed on packagist: ```bash $ phar-composer build https://github.com/composer/composer.git ``` The above will clone the repository and check out the default branch. Again, you can specify either a tag or branch name very similar to how composer works: ```bash $ phar-composer build https://github.com/composer/composer.git:dev-master ``` ### phar-composer install The `install` command will both build the given package and then install it into the system-wide bin directory `/usr/local/bin` (usually already in your `$PATH`). This works for any package name or URL just like with the `build` command, e.g.: ```bash $ phar-composer install phpunit/phpunit ``` After some (lengthy) build output, you should now be able to run it by just issuing: ```bash $ phpunit ``` > In essence, the `install` command will basically just issue a `build` and then `sudo mv $target.phar /usr/local/bin/$target`. It will ask you for your sudo password when necessary, so it's not needed (and in fact not *recommended*) to run the whole comamnd via `sudo`. > > Windows limitation: Note that this subcommand is not available on Windows. Please use the `build` command and place Phar in your `$PATH` manually. ### phar-composer search The `search` command provides an interactive command line search. It will ask for the package name and issue an search via packagist.org's API and present a list of matching packages. So if you don't know the exact package name, you can use the following command: ```bash $ phar-composer search boris ``` It uses an interactive command line menu to ask you for the matching package name, its version and will then offer you to either `build` or `install` it. ## Install You can grab a copy of clue/phar-composer in either of the following ways. This project aims to run on any platform and thus does not require any PHP extensions and supports running on legacy PHP 5.3 through current PHP 8+. It's *highly recommended to use the latest supported PHP version* for this project. ### As a phar (recommended) You can simply download a pre-compiled and ready-to-use version as a Phar to any directory. You can simply download the latest `phar-composer.phar` file from our [releases page](https://github.com/clue/phar-composer/releases). The [latest release](https://github.com/clue/phar-composer/releases/latest) can always be downloaded like this: ```bash $ curl -JOL https://clue.engineering/phar-composer-latest.phar ``` That's it already. Once downloaded, you can verify everything works by running this: ```bash $ cd ~/Downloads $ php phar-composer.phar --version ``` The above usage examples assume you've installed phar-composer system-wide to your $PATH (recommended), so you have the following options: 1. Only use phar-composer locally and adjust the usage examples: So instead of running `$ phar-composer --version`, you have to type `$ php phar-composer.phar --version`. 2. Use phar-composer's `install` command to install itself to your $PATH by running: ```bash $ php phar-composer.phar install clue/phar-composer ``` 3. Or you can manually make the `phar-composer.phar` executable and move it to your $PATH by running: ```bash $ chmod 755 phar-composer.phar $ sudo mv phar-composer.phar /usr/local/bin/phar-composer ``` If you have installed phar-composer system-wide, you can now verify everything works by running: ```bash $ phar-composer --version ``` There's no separate `update` procedure, simply download the latest release again and overwrite the existing phar. Again, if you have already installed phar-composer system-wide, updating is as easy as running a self-installation like this: ```bash $ phar-composer install clue/phar-composer ``` ### Installation using Composer Alternatively, you can also install phar-composer as part of your development dependencies. You will likely want to use the `require-dev` section to exclude phar-composer in your production environment. You can either modify your `composer.json` manually or run the following command to include the latest tagged release: ```bash $ composer require --dev clue/phar-composer ``` Now you should be able to invoke the following command in your project root: ```bash $ vendor/bin/phar-composer --version ``` > Note: You should only invoke and rely on the main phar-composer bin file. Installing this project as a non-dev dependency in order to use its source code as a library is *not supported*. To update to the latest release, just run `composer update clue/graph-composer`. ## Development clue/phar-composer is an [open-source project](#license) and encourages everybody to participate in its development. You're interested in checking out how clue/phar-composer works under the hood and/or want to contribute to the development of clue/phar-composer? Then this section is for you! The recommended way to install clue/phar-composer is to clone (or download) this repository and use [Composer](https://getcomposer.org/) to download its dependencies. Therefore you'll need PHP, Composer, git and curl installed. For example, on a recent Ubuntu/Debian-based system, simply run: ```bash $ sudo apt install php-cli git curl $ git clone https://github.com/clue/phar-composer.git $ cd phar-composer $ curl -s https://getcomposer.org/installer | php $ sudo mv composer.phar /usr/local/bin/composer $ composer install ``` You can now verify everything works by running clue/phar-composer like this: ```bash $ php bin/phar-composer --version ``` If you want to distribute clue/phar-composer as a single standalone release file, you may compile the project into a single `phar-composer.phar` file like this: ```bash $ composer build ``` > Note that compiling will temporarily install a copy of this project to the local `build/` directory and install all non-development dependencies for distribution. This should only take a second or two if you've previously installed its dependencies already. The build script optionally accepts the version number (`VERSION` env) and an output file name or will otherwise try to look up the last release tag, such as `phar-composer-1.0.0.phar`. You can now verify the resulting `phar-composer.phar` file works by running it like this: ```bash $ php phar-composer.phar --version ``` To update your development version to the latest version, just run this: ```bash $ git pull $ composer install ``` Made some changes to your local development version? Make sure to let the world know! :shipit: We welcome PRs and would love to hear from you! Happy hacking! ## 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 ``` ## License This project is released under the permissive [MIT license](LICENSE). This project bundles the `StubGenerator` and `Extract` classes with minor changes from the original herrera-io/box v1.6.1 licensed under MIT which no longer has an installable candidate. Copyright (c) 2013 Kevin Herrera. > Did you know that I offer custom development services and issuing invoices for sponsorships of releases and for contributions? Contact me (@clue) for details. #!/usr/bin/env php run(); { "name": "clue/phar-composer", "description": "Simple phar creation for any project managed via Composer", "keywords": ["executable phar", "build process", "bundle dependencies", "phar", "composer"], "homepage": "https://github.com/clue/phar-composer", "license": "MIT", "authors": [ { "name": "Christian Lück", "email": "christian@clue.engineering" } ], "require": { "php": ">=5.3.6", "knplabs/packagist-api": "^1.0", "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.0 || ^2.5", "symfony/finder": "^6.0 || ^5.0 || ^4.0 || ^3.0 || ^2.5", "symfony/process": "^6.0 || ^5.0 || ^4.0 || ^3.0 || ^2.5" }, "require-dev": { "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.36" }, "autoload": { "psr-4": {"Clue\\PharComposer\\": "src/"} }, "bin": ["bin/phar-composer"], "scripts": { "build": "@php bin/build.php" } } add(new Command\Build()); $this->add(new Command\Search()); $this->add(new Command\Install()); $this->setDefaultCommand('search'); } } '); define('BOX_EXTRACT_PATTERN_OPEN',"__HALT"."_COMPILER(); ?>\r\n"); class Extract { const PATTERN_DEFAULT=BOX_EXTRACT_PATTERN_DEFAULT; const PATTERN_OPEN=BOX_EXTRACT_PATTERN_OPEN; const GZ=4096; const BZ2=8192; const MASK=12288; private$file; private$handle; private$stub; function __construct($file,$stub){ if(!is_file($file)){ throw new InvalidArgumentException(sprintf('The path "%s" is not a file or does not exist.',$file )); } $this->file=$file; $this->stub=$stub; } static function findStubLength($file,$pattern=self::PATTERN_OPEN ){ if(!($fp=fopen($file,'rb'))){ throw new RuntimeException(sprintf('The phar "%s" could not be opened for reading.',$file )); } $stub=null; $offset=0; $combo=str_split($pattern); while(!feof($fp)){ if(fgetc($fp)===$combo[$offset]){ $offset++; if(!isset($combo[$offset])){ $stub=ftell($fp); break; } }else{ $offset=0; } } fclose($fp); if(null===$stub){ throw new InvalidArgumentException(sprintf('The pattern could not be found in "%s".',$file )); } return$stub; } function go($dir=null){ if(null===$dir){ $dir=rtrim(sys_get_temp_dir(),'\\/').DIRECTORY_SEPARATOR .'pharextract'.DIRECTORY_SEPARATOR .basename($this->file,'.phar'); }else{ $dir=realpath($dir); } $md5=$dir.DIRECTORY_SEPARATOR.md5_file($this->file); if(file_exists($md5)){ return$dir; } if(!is_dir($dir)){ $this->createDir($dir); } $this->open(); if(-1===fseek($this->handle,$this->stub)){ throw new RuntimeException(sprintf('Could not seek to %d in the file "%s".',$this->stub,$this->file )); } $info=$this->readManifest(); if($info['flags']&self::GZ){ if(!function_exists('gzinflate')){ throw new RuntimeException('The zlib extension is (gzinflate()) is required for "%s.',$this->file ); } } if($info['flags']&self::BZ2){ if(!function_exists('bzdecompress')){ throw new RuntimeException('The bzip2 extension (bzdecompress()) is required for "%s".',$this->file ); } } self::purge($dir); $this->createDir($dir); $this->createFile($md5); foreach($info['files']as$info){ $path=$dir.DIRECTORY_SEPARATOR.$info['path']; $parent=dirname($path); if(!is_dir($parent)){ $this->createDir($parent); } if(preg_match('{/$}',$info['path'])){ $this->createDir($path,511,false); }else{ $this->createFile($path,$this->extractFile($info)); } } return$dir; } static function purge($path){ if(is_dir($path)){ foreach(scandir($path)as$item){ if(('.'===$item)||('..'===$item)){ continue; } self::purge($path.DIRECTORY_SEPARATOR.$item); } if(!rmdir($path)){ throw new RuntimeException(sprintf('The directory "%s" could not be deleted.',$path )); } }else{ if(!unlink($path)){ throw new RuntimeException(sprintf('The file "%s" could not be deleted.',$path )); } } } private function createDir($path,$chmod=511,$recursive=true){ if(!mkdir($path,$chmod,$recursive)){ throw new RuntimeException(sprintf('The directory path "%s" could not be created.',$path )); } } private function createFile($path,$contents='',$mode=438){ if(false===file_put_contents($path,$contents)){ throw new RuntimeException(sprintf('The file "%s" could not be written.',$path )); } if(!chmod($path,$mode)){ throw new RuntimeException(sprintf('The file "%s" could not be chmodded to %o.',$path,$mode )); } } private function extractFile($info){ if(0===$info['size']){ return''; } $data=$this->read($info['compressed_size']); if($info['flags']&self::GZ){ if(false===($data=gzinflate($data))){ throw new RuntimeException(sprintf('The "%s" file could not be inflated (gzip) from "%s".',$info['path'],$this->file )); } }elseif($info['flags']&self::BZ2){ if(false===($data=bzdecompress($data))){ throw new RuntimeException(sprintf('The "%s" file could not be inflated (bzip2) from "%s".',$info['path'],$this->file )); } } if(($actual=strlen($data))!==$info['size']){ throw new UnexpectedValueException(sprintf('The size of "%s" (%d) did not match what was expected (%d) in "%s".',$info['path'],$actual,$info['size'],$this->file )); } $crc32=sprintf('%u',crc32($data)&4294967295); if($info['crc32']!=$crc32){ throw new UnexpectedValueException(sprintf('The crc32 checksum (%s) for "%s" did not match what was expected (%s) in "%s".',$crc32,$info['path'],$info['crc32'],$this->file )); } return$data; } private function open(){ if(null===($this->handle=fopen($this->file,'rb'))){ $this->handle=null; throw new RuntimeException(sprintf('The file "%s" could not be opened for reading.',$this->file )); } } private function read($bytes){ $read=''; $total=$bytes; while(!feof($this->handle)&&$bytes){ if(false===($chunk=fread($this->handle,$bytes))){ throw new RuntimeException(sprintf('Could not read %d bytes from "%s".',$bytes,$this->file )); } $read.=$chunk; $bytes-=strlen($chunk); } if(($actual=strlen($read))!==$total){ throw new RuntimeException(sprintf('Only read %d of %d in "%s".',$actual,$total,$this->file )); } return$read; } private function readManifest(){ $size=unpack('V',$this->read(4)); $size=$size[1]; $raw=$this->read($size); $count=unpack('V',substr($raw,0,4)); $count=$count[1]; $aliasSize=unpack('V',substr($raw,10,4)); $aliasSize=$aliasSize[1]; $raw=substr($raw,14+$aliasSize); $metaSize=unpack('V',substr($raw,0,4)); $metaSize=$metaSize[1]; $offset=0; $start=4+$metaSize; $manifest=array('files'=>array(),'flags'=>0,); for($i=0;$i<$count;$i++){ $length=unpack('V',substr($raw,$start,4)); $length=$length[1]; $start+=4; $path=substr($raw,$start,$length); $start+=$length; $file=unpack('Vsize/Vtimestamp/Vcompressed_size/Vcrc32/Vflags/Vmetadata_length',substr($raw,$start,24)); $file['path']=$path; $file['crc32']=sprintf('%u',$file['crc32']&4294967295); $file['offset']=$offset; $offset+=$file['compressed_size']; $start+=24+$file['metadata_length']; $manifest['flags']|=$file['flags']&self::MASK; $manifest['files'][]=$file; } return$manifest; } } '); /** * The open-ended stub pattern. * * @var string */ define('BOX_EXTRACT_PATTERN_OPEN', "__HALT" . "_COMPILER(); ?>\r\n"); /** * Extracts a phar without the extension. * * This class is a rewrite of the `Extract_Phar` class that is included * in the default stub for all phars. The class is designed to work from * inside and outside of a phar. Unlike the original class, the stub * length must be specified. * * @author Kevin Herrera * * @link https://github.com/php/php-src/blob/master/ext/phar/shortarc.php */ class Extract { /** * The default stub pattern. * * @var string */ const PATTERN_DEFAULT = BOX_EXTRACT_PATTERN_DEFAULT; /** * The open-ended stub pattern. * * @var string */ const PATTERN_OPEN = BOX_EXTRACT_PATTERN_OPEN; /** * The gzip compression flag. * * @var integer */ const GZ = 0x1000; /** * The bzip2 compression flag. * * @var integer */ const BZ2 = 0x2000; /** * @var integer */ const MASK = 0x3000; /** * The phar file path to extract. * * @var string */ private $file; /** * The open file handle. * * @var resource */ private $handle; /** * The length of the stub in the phar. * * @var integer */ private $stub; /** * Sets the file to extract and the stub length. * * @param string $file The file path. * @param integer $stub The stub length. * * @throws InvalidArgumentException If the file does not exist. */ public function __construct($file, $stub) { if (!is_file($file)) { throw new InvalidArgumentException( sprintf( 'The path "%s" is not a file or does not exist.', $file ) ); } $this->file = $file; $this->stub = $stub; } /** * Finds the phar's stub length using the end pattern. * * A "pattern" is a sequence of characters that indicate the end of a * stub, and the beginning of a manifest. This determines the complete * size of a stub, and is used as an offset to begin parsing the data * contained in the phar's manifest. * * The stub generated included with the Box library uses what I like * to call an open-ended pattern. This pattern uses the function * "__HALT_COMPILER();" at the end, with no following whitespace or * closing PHP tag. By default, this method will use that pattern, * defined as `Extract::PATTERN_OPEN`. * * The Phar class generates its own default stub. The pattern for the * default stub is slightly different than the one used by Box. This * pattern is defined as `Extract::PATTERN_DEFAULT`. * * If you have used your own custom stub, you will need to specify its * pattern as the `$pattern` argument, if you cannot use either of the * pattern constants defined. * * @param string $file The phar file path. * @param string $pattern The stub end pattern. * * @return integer The stub length. * * @throws InvalidArgumentException If the pattern could not be found. * @throws RuntimeException If the phar could not be read. */ public static function findStubLength( $file, $pattern = self::PATTERN_OPEN ) { if (!($fp = fopen($file, 'rb'))) { throw new RuntimeException( sprintf( 'The phar "%s" could not be opened for reading.', $file ) ); } $stub = null; $offset = 0; $combo = str_split($pattern); while (!feof($fp)) { if (fgetc($fp) === $combo[$offset]) { $offset++; if (!isset($combo[$offset])) { $stub = ftell($fp); break; } } else { $offset = 0; } } fclose($fp); if (null === $stub) { throw new InvalidArgumentException( sprintf( 'The pattern could not be found in "%s".', $file ) ); } return $stub; } /** * Extracts the phar to the directory path. * * If no directory path is given, a temporary one will be generated and * returned. If a directory path is given, the returned directory path * will be the same. * * @param string $dir The directory to extract to. * * @return string The directory extracted to. * * @throws LengthException * @throws RuntimeException */ public function go($dir = null) { // set up the output directory if (null === $dir) { $dir = rtrim(sys_get_temp_dir(), '\\/') . DIRECTORY_SEPARATOR . 'pharextract' . DIRECTORY_SEPARATOR . basename($this->file, '.phar'); } else { $dir = realpath($dir); } // skip if already extracted $md5 = $dir . DIRECTORY_SEPARATOR . md5_file($this->file); if (file_exists($md5)) { return $dir; } if (!is_dir($dir)) { $this->createDir($dir); } // open the file and skip stub $this->open(); if (-1 === fseek($this->handle, $this->stub)) { throw new RuntimeException( sprintf( 'Could not seek to %d in the file "%s".', $this->stub, $this->file ) ); } // read the manifest $info = $this->readManifest(); if ($info['flags'] & self::GZ) { if (!function_exists('gzinflate')) { throw new RuntimeException( 'The zlib extension is (gzinflate()) is required for "%s.', $this->file ); } } if ($info['flags'] & self::BZ2) { if (!function_exists('bzdecompress')) { throw new RuntimeException( 'The bzip2 extension (bzdecompress()) is required for "%s".', $this->file ); } } self::purge($dir); $this->createDir($dir); $this->createFile($md5); foreach ($info['files'] as $info) { $path = $dir . DIRECTORY_SEPARATOR . $info['path']; $parent = dirname($path); if (!is_dir($parent)) { $this->createDir($parent); } if (preg_match('{/$}', $info['path'])) { $this->createDir($path, 0777, false); } else { $this->createFile( $path, $this->extractFile($info) ); } } return $dir; } /** * Recursively deletes the directory or file path. * * @param string $path The path to delete. * * @throws RuntimeException If the path could not be deleted. */ public static function purge($path) { if (is_dir($path)) { foreach (scandir($path) as $item) { if (('.' === $item) || ('..' === $item)) { continue; } self::purge($path . DIRECTORY_SEPARATOR . $item); } if (!rmdir($path)) { throw new RuntimeException( sprintf( 'The directory "%s" could not be deleted.', $path ) ); } } else { if (!unlink($path)) { throw new RuntimeException( sprintf( 'The file "%s" could not be deleted.', $path ) ); } } } /** * Creates a new directory. * * @param string $path The directory path. * @param integer $chmod The file mode. * @param boolean $recursive Recursively create path? * * @throws RuntimeException If the path could not be created. */ private function createDir($path, $chmod = 0777, $recursive = true) { if (!mkdir($path, $chmod, $recursive)) { throw new RuntimeException( sprintf( 'The directory path "%s" could not be created.', $path ) ); } } /** * Creates a new file. * * @param string $path The file path. * @param string $contents The file contents. * @param integer $mode The file mode. * * @throws RuntimeException If the file could not be created. */ private function createFile($path, $contents = '', $mode = 0666) { if (false === file_put_contents($path, $contents)) { throw new RuntimeException( sprintf( 'The file "%s" could not be written.', $path ) ); } if (!chmod($path, $mode)) { throw new RuntimeException( sprintf( 'The file "%s" could not be chmodded to %o.', $path, $mode ) ); } } /** * Extracts a single file from the phar. * * @param array $info The file information. * * @return string The file data. * * @throws RuntimeException If the file could not be extracted. * @throws UnexpectedValueException If the crc32 checksum does not * match the expected value. */ private function extractFile($info) { if (0 === $info['size']) { return ''; } $data = $this->read($info['compressed_size']); if ($info['flags'] & self::GZ) { if (false === ($data = gzinflate($data))) { throw new RuntimeException( sprintf( 'The "%s" file could not be inflated (gzip) from "%s".', $info['path'], $this->file ) ); } } elseif ($info['flags'] & self::BZ2) { if (false === ($data = bzdecompress($data))) { throw new RuntimeException( sprintf( 'The "%s" file could not be inflated (bzip2) from "%s".', $info['path'], $this->file ) ); } } if (($actual = strlen($data)) !== $info['size']) { throw new UnexpectedValueException( sprintf( 'The size of "%s" (%d) did not match what was expected (%d) in "%s".', $info['path'], $actual, $info['size'], $this->file ) ); } $crc32 = sprintf('%u', crc32($data) & 0xffffffff); if ($info['crc32'] != $crc32) { throw new UnexpectedValueException( sprintf( 'The crc32 checksum (%s) for "%s" did not match what was expected (%s) in "%s".', $crc32, $info['path'], $info['crc32'], $this->file ) ); } return $data; } /** * Opens the file for reading. * * @throws RuntimeException If the file could not be opened. */ private function open() { if (null === ($this->handle = fopen($this->file, 'rb'))) { $this->handle = null; throw new RuntimeException( sprintf( 'The file "%s" could not be opened for reading.', $this->file ) ); } } /** * Reads the number of bytes from the file. * * @param integer $bytes The number of bytes. * * @return string The binary string read. * * @throws RuntimeException If the read fails. */ private function read($bytes) { $read = ''; $total = $bytes; while (!feof($this->handle) && $bytes) { if (false === ($chunk = fread($this->handle, $bytes))) { throw new RuntimeException( sprintf( 'Could not read %d bytes from "%s".', $bytes, $this->file ) ); } $read .= $chunk; $bytes -= strlen($chunk); } if (($actual = strlen($read)) !== $total) { throw new RuntimeException( sprintf( 'Only read %d of %d in "%s".', $actual, $total, $this->file ) ); } return $read; } /** * Reads and unpacks the manifest data from the phar. * * @return array The manifest. */ private function readManifest() { $size = unpack('V', $this->read(4)); $size = $size[1]; $raw = $this->read($size); // ++ start skip: API version, global flags, alias, and metadata $count = unpack('V', substr($raw, 0, 4)); $count = $count[1]; $aliasSize = unpack('V', substr($raw, 10, 4)); $aliasSize = $aliasSize[1]; $raw = substr($raw, 14 + $aliasSize); $metaSize = unpack('V', substr($raw, 0, 4)); $metaSize = $metaSize[1]; $offset = 0; $start = 4 + $metaSize; // -- end skip $manifest = array( 'files' => array(), 'flags' => 0, ); for ($i = 0; $i < $count; $i++) { $length = unpack('V', substr($raw, $start, 4)); $length = $length[1]; $start += 4; $path = substr($raw, $start, $length); $start += $length; $file = unpack( 'Vsize/Vtimestamp/Vcompressed_size/Vcrc32/Vflags/Vmetadata_length', substr($raw, $start, 24) ); $file['path'] = $path; $file['crc32'] = sprintf('%u', $file['crc32'] & 0xffffffff); $file['offset'] = $offset; $offset += $file['compressed_size']; $start += 24 + $file['metadata_length']; $manifest['flags'] |= $file['flags'] & self::MASK; $manifest['files'][] = $file; } return $manifest; } } */ class StubGenerator { /** * The list of server variables that are allowed to be modified. * * @var array */ private static $allowedMung = array( 'PHP_SELF', 'REQUEST_URI', 'SCRIPT_FILENAME', 'SCRIPT_NAME' ); /** * The alias to be used in "phar://" URLs. * * @var string */ private $alias; /** * The top header comment banner text. * * @var string. */ private $banner = 'Generated by Box. @link https://github.com/herrera-io/php-box/'; /** * Embed the Extract class in the stub? * * @var boolean */ private $extract = false; /** * The processed extract code. * * @var array */ private $extractCode = array(); /** * Force the use of the Extract class? * * @var boolean */ private $extractForce = false; /** * The location within the Phar of index script. * * @var string */ private $index; /** * Use the Phar::interceptFileFuncs() method? * * @var boolean */ private $intercept = false; /** * The map for file extensions and their mimetypes. * * @var array */ private $mimetypes = array(); /** * The list of server variables to modify. * * @var array */ private $mung = array(); /** * The location of the script to run when a file is not found. * * @var string */ private $notFound; /** * The rewrite function. * * @var string */ private $rewrite; /** * The shebang line. * * @var string */ private $shebang = '#!/usr/bin/env php'; /** * Use Phar::webPhar() instead of Phar::mapPhar()? * * @var boolean */ private $web = false; /** * Sets the alias to be used in "phar://" URLs. * * @param string $alias The alias. * * @return StubGenerator The stub generator. */ public function alias($alias) { $this->alias = $alias; return $this; } /** * Sets the top header comment banner text. * * @param string $banner The banner text. * * @return StubGenerator The stub generator. */ public function banner($banner) { $this->banner = $banner; return $this; } /** * Creates a new instance of the stub generator. * * @return StubGenerator The stub generator. */ public static function create() { return new static(); } /** * Embed the Extract class in the stub? * * @param boolean $extract Embed the class? * @param boolean $force Force the use of the class? * * @return StubGenerator The stub generator. */ public function extract($extract, $force = false) { $this->extract = $extract; $this->extractForce = $force; if ($extract) { $this->extractCode = array( 'constants' => array(), 'class' => array(), ); $code = file_get_contents(__DIR__ . '/Extract.min.php'); $code = preg_replace('/\n+/', "\n", $code); $code = explode("\n", $code); $code = array_slice($code, 2); foreach ($code as $i => $line) { if ((0 === strpos($line, 'use')) && (false === strpos($line, '\\')) ) { unset($code[$i]); } elseif (0 === strpos($line, 'define')) { $this->extractCode['constants'][] = $line; } else { $this->extractCode['class'][] = $line; } } } return $this; } /** * Sets location within the Phar of index script. * * @param string $index The index file. * * @return StubGenerator The stub generator. */ public function index($index) { $this->index = $index; return $this; } /** * Use the Phar::interceptFileFuncs() method in the stub? * * @param boolean $intercept Use interceptFileFuncs()? * * @return StubGenerator The stub generator. */ public function intercept($intercept) { $this->intercept = $intercept; return $this; } /** * Generates the stub. * * @return string The stub. */ public function generate() { $stub = array(); if ('' !== $this->shebang) { $stub[] = $this->shebang; } $stub[] = 'banner) { $stub[] = $this->getBanner(); } if ($this->extract) { $stub[] = join("\n", $this->extractCode['constants']); if ($this->extractForce) { $stub = array_merge($stub, $this->getExtractSections()); } } $stub = array_merge($stub, $this->getPharSections()); if ($this->extract) { if ($this->extractForce) { if ($this->index && !$this->web) { $stub[] = "require \"\$dir/{$this->index}\";"; } } else { end($stub); $stub[key($stub)] .= ' else {'; $stub = array_merge($stub, $this->getExtractSections()); if ($this->index) { $stub[] = "require \"\$dir/{$this->index}\";"; } $stub[] = '}'; } $stub[] = join("\n", $this->extractCode['class']); } $stub[] = "__HALT_COMPILER();"; return join("\n", $stub); } /** * Sets the map for file extensions and their mimetypes. * * @param array $mimetypes The map. * * @return StubGenerator The stub generator. */ public function mimetypes(array $mimetypes) { $this->mimetypes = $mimetypes; return $this; } /** * Sets the list of server variables to modify. * * @param array $list The list. * * @return StubGenerator The stub generator. * * @throws \InvalidArgumentException If the list contains an invalid value. */ public function mung(array $list) { foreach ($list as $value) { if (false === in_array($value, self::$allowedMung)) { throw new \InvalidArgumentException(sprintf( 'The $_SERVER variable "%s" is not allowed.', $value )); } } $this->mung = $list; return $this; } /** * Sets the location of the script to run when a file is not found. * * @param string $script The script. * * @return StubGenerator The stub generator. */ public function notFound($script) { $this->notFound = $script; return $this; } /** * Sets the rewrite function. * * @param string $function The function. * * @return StubGenerator The stub generator. */ public function rewrite($function) { $this->rewrite = $function; return $this; } /** * Sets the shebang line. * * @param string $shebang The shebang line. * * @return StubGenerator The stub generator. */ public function shebang($shebang) { $this->shebang = $shebang; return $this; } /** * Use Phar::webPhar() instead of Phar::mapPhar()? * * @param boolean $web Use Phar::webPhar()? * * @return StubGenerator The stub generator. */ public function web($web) { $this->web = $web; return $this; } /** * Escapes an argument so it can be written as a string in a call. * * @param string $arg The argument. * @param string $quote The quote. * * @return string The escaped argument. */ private function arg($arg, $quote = "'") { return $quote . addcslashes($arg, $quote) . $quote; } /** * Returns the alias map. * * @return string The alias map. */ private function getAlias() { $stub = ''; $prefix = ''; if ($this->extractForce) { $prefix = '$dir/'; } if ($this->web) { $stub .= 'Phar::webPhar(' . $this->arg($this->alias); if ($this->index) { $stub .= ', ' . $this->arg($prefix . $this->index, '"'); if ($this->notFound) { $stub .= ', ' . $this->arg($prefix . $this->notFound, '"'); if ($this->mimetypes) { $stub .= ', ' . var_export( $this->mimetypes, true ); if ($this->rewrite) { $stub .= ', ' . $this->arg($this->rewrite); } } } } $stub .= ');'; } else { $stub .= 'Phar::mapPhar(' . $this->arg($this->alias) . ');'; } return $stub; } /** * Returns the banner after it has been processed. * * @return string The processed banner. */ private function getBanner() { $banner = "/**\n * "; $banner .= str_replace( " \n", "\n", str_replace("\n", "\n * ", $this->banner) ); $banner .= "\n */"; return $banner; } /** * Returns the self extracting sections of the stub. * * @return array The stub sections. */ private function getExtractSections() { return array( '$extract = new Extract(__FILE__, Extract::findStubLength(__FILE__));', '$dir = $extract->go();', 'set_include_path($dir . PATH_SEPARATOR . get_include_path());', ); } /** * Returns the sections of the stub that use the Phar class. * * @return array The stub sections. */ private function getPharSections() { $stub = array( 'if (class_exists(\'Phar\')) {', $this->getAlias(), ); if ($this->intercept) { $stub[] = "Phar::interceptFileFuncs();"; } if ($this->mung) { $stub[] = 'Phar::mungServer(' . var_export($this->mung, true) . ");"; } if ($this->index && !$this->web && !$this->extractForce) { $stub[] = "require 'phar://' . __FILE__ . '/{$this->index}';"; } $stub[] = '}'; return $stub; } } packager = $packager; } protected function configure() { $this->setName('build') ->setDescription('Build phar for the given composer project') ->addArgument('project', InputArgument::OPTIONAL, 'Path to project directory or composer.json', '.') ->addArgument('target', InputArgument::OPTIONAL, 'Path to write phar output to (defaults to project name)'); } protected function execute(InputInterface $input, OutputInterface $output) { $this->packager->setOutput($output); $this->packager->coerceWritable(); $pharer = $this->packager->getPharer($input->getArgument('project')); $target = $input->getArgument('target'); if ($target !== null) { $pharer->setTarget($target); } $pharer->build(); return 0; } } packager = $packager; $this->isWindows = $isWindows; parent::__construct(); } protected function configure() { $this->setName('install') ->setDescription('Install phar into system wide binary directory' . ($this->isWindows ? ' (not available on Windows)' : '')) ->addArgument('project', InputArgument::OPTIONAL, 'Project name or path', '.') ->addArgument('target', InputArgument::OPTIONAL, 'Path to install to', '/usr/local/bin'); } protected function execute(InputInterface $input, OutputInterface $output) { if ($this->isWindows) { $output->writeln('Command not available on this platform. Please use the "build" command and place Phar in your $PATH manually.'); return 1; } $this->packager->setOutput($output); $this->packager->coerceWritable(); $pharer = $this->packager->getPharer($input->getArgument('project')); $path = $this->packager->getSystemBin($pharer->getPackageRoot(), $input->getArgument('target')); if (is_file($path)) { $helper = $this->getHelper('question'); assert($helper instanceof QuestionHelper); $question = new ConfirmationQuestion('Overwrite existing file ' . $path . '? [y] > ', true); if (!$helper->ask($input, $output, $question)) { $output->writeln('Aborting'); return 0; } } $this->packager->install($pharer, $path); return 0; } } packager = $packager; $this->packagist = $packagist; $this->isWindows = $isWindows; parent::__construct(); } protected function configure() { $this->setName('search') ->setDescription('Interactive search for project name') ->addArgument('project', InputArgument::OPTIONAL, 'Project name or path', null); } /** * @param InputInterface $input * @param OutputInterface $output * @param string $label * @param array $choices * @param ?string $abortable * @return ?string */ protected function select(InputInterface $input, OutputInterface $output, $label, array $choices, $abortable = null) { $helper = $this->getHelper('question'); assert($helper instanceof QuestionHelper); if (!$choices) { $output->writeln('No matching packages found'); return null; } // use numeric keys for all options $select = array_merge(array(0 => $abortable), array_values($choices)); if ($abortable === null) { unset($select[0]); } $question = new ChoiceQuestion($label, $select); $index = array_search($helper->ask($input, $output, $question), $select); if ($index === 0) { return null; } $indices = array_keys($choices); return $indices[$index - 1]; } protected function execute(InputInterface $input, OutputInterface $output) { $this->packager->setOutput($output); $this->packager->coerceWritable(); $helper = $this->getHelper('question'); assert($helper instanceof QuestionHelper); $project = $input->getArgument('project'); do { if ($project === null) { // ask for input $question = new Question('Enter (partial) project name > ', ''); $project = $helper->ask($input, $output, $question); } else { $output->writeln('Searching for ' . $project . '...'); } $choices = array(); foreach ($this->packagist->search($project) as $result) { assert($result instanceof Result); $label = str_pad($result->getName(), 39) . ' '; $label = str_replace($project, '' . $project . '', $label); $label .= $result->getDescription(); $label .= ' (⤓' . $result->getDownloads() . ')'; $choices[$result->getName()] = $label; } $project = $this->select($input, $output, 'Select matching package', $choices, 'Start new search'); } while ($project === null); $output->writeln('Selected ' . $project . ', listing versions...'); $package = $this->packagist->get($project); assert($package instanceof Package); $choices = array(); foreach ($package->getVersions() as $version) { assert($version instanceof Version); $label = $version->getVersion(); /* @var ?string $bin */ $bin = $version->getBin(); $label .= $bin !== null ? ' (☑ executable bin)' : ' (no executable bin)'; $choices[$version->getVersion()] = $label; } $version = $this->select($input, $output, 'Select available version', $choices); $action = $this->select( $input, $output, 'Action', array_filter(array( 'build' => 'Build project', 'install' => $this->isWindows ? null : 'Install project system-wide' )), 'Quit' ); if ($action === null) { return 0; } $pharer = $this->packager->getPharer($project, $version); if ($action === 'install') { $path = $this->packager->getSystemBin($pharer->getPackageRoot()); $this->packager->install($pharer, $path); } else { $pharer->build(); } return 0; } } output = $output; } public function log($message) { $this->output($message . PHP_EOL); } private function output($message) { if ($this->output === true) { echo $message; } elseif ($this->output !== false) { call_user_func($this->output, $message); } } } resources[] = $file; return $this; } /** * add given directory to bundle * * @param Finder $dir * @return Bundle */ public function addDir(Finder $dir) { $this->resources[] = $dir; return $this; } /** * checks if a bundle contains given resource * * @param string $resource * @return bool */ public function contains($resource) { foreach ($this->resources as $containedResource) { if (is_string($containedResource) && $containedResource == $resource) { return true; } if ($containedResource instanceof Finder && $this->directoryContains($containedResource, $resource)) { return true; } } return false; } /** * checks if given directory contains given resource * * @param Finder $dir * @param string $resource * @return bool */ private function directoryContains(Finder $dir, $resource) { foreach ($dir as $containedResource) { /* @var $containedResource \SplFileInfo */ if (substr($containedResource->getRealPath(), 0, strlen($resource)) == $resource) { return true; } } return false; } /** * returns list of resources * * @return \Traversable */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->resources); } } package = $package; $this->directory = rtrim($directory, '/') . '/'; } /** * get package name as defined in composer.json * * @return ?string */ public function getName() { return isset($this->package['name']) ? $this->package['name'] : null; } /** * @return string */ public function getShortName() { // skip vendor name from package name or default to last directory component $name = $this->getName(); if ($name === null) { $name = realpath($this->directory); if ($name === false) { $name = $this->directory; } } return basename($name); } /** * Get path to vendor directory (relative to package directory, always ends with slash) * * @return string */ public function getPathVendor() { $vendor = 'vendor'; if (isset($this->package['config']['vendor-dir'])) { $vendor = $this->package['config']['vendor-dir']; } return $vendor . '/'; } /** * Get package directory (the directory containing its composer.json, always ends with slash) * * @return string */ public function getDirectory() { return $this->directory; } /** * @return \Clue\PharComposer\Package\Bundle */ public function bundle() { $bundle = new Bundle(); // return empty bundle if this package does not define any files and directory does not exist if (empty($this->package['autoload']) && !is_dir($this->directory . $this->getPathVendor())) { return $bundle; } $iterator = Finder::create() ->files() ->ignoreVCS(true) ->exclude(rtrim($this->getPathVendor(), '/')) ->notPath('/^composer\.phar/') ->notPath('/^phar-composer\.phar/') ->in($this->getDirectory()); return $bundle->addDir($iterator); } /** * Get list of files defined as "bin" (relative to package directory) * * @return string[] */ public function getBins() { return isset($this->package['bin']) ? $this->package['bin'] : array(); } } setOutput(true); } private function log($message) { $fn = $this->output; $fn($message . PHP_EOL); } public function setBinSudo($bin) { $this->binSudo = $bin; } /** * @param OutputInterface|bool|callable $fn */ public function setOutput($fn) { if ($fn instanceof OutputInterface) { $fn = function ($line) use ($fn) { $fn->write($line); }; } elseif ($fn === true) { $fn = function ($line) { echo $line; }; } elseif ($fn === false) { $fn = function () { }; } $this->output = $fn; } /** * ensure writing phar files is enabled or respawn with PHP setting which allows writing * * @param int $wait * @return void * @uses assertWritable() */ public function coerceWritable($wait = 1) { try { $this->assertWritable(); } catch (UnexpectedValueException $e) { if (!function_exists('pcntl_exec')) { $this->log('' . $e->getMessage() . ''); return; } $this->log('' . $e->getMessage() . ', trying to re-spawn with correct config'); if ($wait) { sleep($wait); } $args = array_merge(array('php', '-d phar.readonly=off'), $_SERVER['argv']); if (pcntl_exec('/usr/bin/env', $args) === false) { $this->log('Unable to switch into new configuration'); return; } } } /** * ensure writing phar files is enabled or throw an exception * * @throws UnexpectedValueException */ public function assertWritable() { if (ini_get('phar.readonly') === '1') { throw new UnexpectedValueException('Your configuration disabled writing phar files (phar.readonly = On), please update your configuration or run with "php -d phar.readonly=off ' . $_SERVER['argv'][0].'"'); } } /** * @param string $path * @param string $version * @return PharComposer * @throws UnexpectedValueException * @throws InvalidArgumentException * @throws RuntimeException */ public function getPharer($path, $version = null) { if ($version !== null) { // TODO: should be the other way around $path .= ':' . $version; } $step = 1; $steps = 1; if ($this->isPackageUrl($path)) { $url = $path; $version = null; $steps = 3; if (preg_match('/(.+)\:((?:dev\-|v\d)\S+)$/i', $url, $match)) { $url = $match[1]; $version = $match[2]; if (substr($version, 0, 4) === 'dev-') { $version = substr($version, 4); } } $path = $this->getDirTemporary(); $finder = new ExecutableFinder(); $git = escapeshellarg($finder->find('git', 'git')); $that = $this; $this->displayMeasure( '[' . $step++ . '/' . $steps.'] Cloning ' . $url . ' into temporary directory ' . $path . '', function() use ($that, $url, $path, $version, $git) { $that->exec($git . ' clone ' . escapeshellarg($url) . ' ' . escapeshellarg($path)); if ($version !== null) { $this->exec($git . ' checkout ' . escapeshellarg($version) . ' 2>&1', $path); } }, 'Cloning base repository completed' ); $pharcomposer = new PharComposer($path . '/composer.json'); $package = $pharcomposer->getPackageRoot()->getName(); if (is_file('composer.phar')) { $command = escapeshellarg($finder->find('php', 'php')) . ' composer.phar'; } else { $command = escapeshellarg($finder->find('composer', 'composer')); } $command .= ' install --no-dev --no-progress --no-scripts'; $this->displayMeasure( '[' . $step++ . '/' . $steps.'] Installing dependencies for ' . $package . ' into ' . $path . ' (using ' . $command . ')', function () use ($that, $command, $path) { try { $that->exec($command, $path); } catch (UnexpectedValueException $e) { throw new UnexpectedValueException('Installing dependencies via composer failed', 0, $e); } }, 'Downloading dependencies completed' ); } elseif ($this->isPackageName($path)) { if (is_dir($path)) { $this->log('There\'s also a directory with the given name'); } $steps = 2; $package = $path; $path = $this->getDirTemporary(); $finder = new ExecutableFinder(); if (is_file('composer.phar')) { $command = escapeshellarg($finder->find('php', 'php')) . ' composer.phar'; } else { $command = escapeshellarg($finder->find('composer', 'composer')); } $command .= ' create-project ' . escapeshellarg($package) . ' ' . escapeshellarg($path) . ' --no-dev --no-progress --no-scripts'; $that = $this; $this->displayMeasure( '[' . $step++ . '/' . $steps.'] Installing ' . $package . ' to temporary directory ' . $path . ' (using ' . $command . ')', function () use ($that, $command) { try { $that->exec($command); } catch (UnexpectedValueException $e) { throw new UnexpectedValueException('Installing package via composer failed', 0, $e); } }, 'Downloading package completed' ); } if (is_dir($path)) { $path = rtrim($path, '/') . '/composer.json'; } if (!is_file($path)) { throw new InvalidArgumentException('The given path "' . $path . '" is not a readable file'); } $pharer = new PharComposer($path); $pharer->setOutput($this->output); $pharer->setStep($step); $pathVendor = $pharer->getPackageRoot()->getDirectory() . $pharer->getPackageRoot()->getPathVendor(); if (!is_dir($pathVendor)) { throw new RuntimeException('Project is not installed via composer. Run "composer install" manually'); } return $pharer; } public function measure($fn) { $time = microtime(true); $fn(); return max(microtime(true) - $time, 0); } public function displayMeasure($title, $fn, $success) { $this->log($title); $time = $this->measure($fn); $this->log(''); $this->log(' OK - ' . $success .' (after ' . round($time, 1) . 's)'); } /** * @param string $cmd * @param ?string $chdir * @return void * @throws UnexpectedValueException */ public function exec($cmd, $chdir = null) { $nl = true; // $output = $this->output; // Symfony 5+ requires 'fromShellCommandline', older versions support direct instantiation with command line // @codeCoverageIgnoreStart try { new \ReflectionMethod('Symfony\Component\Process\Process', 'fromShellCommandline'); $process = Process::fromShellCommandline($cmd, $chdir); } catch (\ReflectionException $e) { $process = new Process($cmd, $chdir); } // @codeCoverageIgnoreEnd $process->setTimeout(null); $code = $process->run(function($type, $data) use ($output, &$nl) { if ($nl === true) { $data = PHP_EOL . $data; $nl = false; } if (substr($data, -1) === "\n") { $nl = true; $data = substr($data, 0, -strlen(PHP_EOL)); } $data = str_replace("\n", "\n ", $data); $output($data); }); if ($nl) { $this->log(''); } if ($code !== 0) { throw new UnexpectedValueException('Error status code: ' . $process->getExitCodeText() . ' (code ' . $code . ')'); } } public function install(PharComposer $pharer, $path) { $pharer->build(); $this->log('Move resulting phar to ' . $path . ''); $this->exec($this->binSudo . ' -- mv -f ' . escapeshellarg($pharer->getTarget()) . ' ' . escapeshellarg($path)); $this->log(''); $this->log(' OK - Moved to ' . $path . ''); } /** * @param Package $package * @param ?string $path * @return string */ public function getSystemBin(Package $package, $path = null) { // no path given => place in system bin path if ($path === null) { $path = self::PATH_BIN; } // no slash => path is relative to system bin path if (strpos($path, '/') === false) { $path = self::PATH_BIN . '/' . $path; } // path is actually a directory => append package name if (is_dir($path)) { $path = rtrim($path, '/') . '/' . $package->getShortName(); } return $path; } private function isPackageName($path) { return !!preg_match('/^[^\s\/]+\/[^\s\/]+(\:[^\s]+)?$/i', $path); } public function isPackageUrl($path) { return (strpos($path, '://') !== false && @parse_url($path) !== false) || preg_match('/^[^-\/\s][^:\/\s]*:[^\s\\\\]\S*/', $path); } private function getDirTemporary() { $path = sys_get_temp_dir() . '/phar-composer' . mt_rand(0,9); while (is_dir($path)) { $path .= mt_rand(0, 9); } return $path; } } package = new Package($this->loadJson($path), dirname(realpath($path))); $this->logger = new Logger(); } /** * set output function to use to output log messages * * @param callable|boolean $output callable that receives a single $line argument or boolean echo */ public function setOutput($output) { $this->logger->setOutput($output); } /** * Get path to target phar file (absolute path or relative to current directory) * * @return string */ public function getTarget() { if ($this->target === null) { $this->target = $this->package->getShortName() . '.phar'; } return $this->target; } /** * Set path to target phar file (absolute path or relative to current directory) * * If the given path is a directory, the default target (package short name) * will be appended automatically. * * @param string $target * @return $this */ public function setTarget($target) { // path is actually a directory => append package name if (is_dir($target)) { $this->target = null; $target = rtrim($target, '/') . '/' . $this->getTarget(); } $this->target = $target; return $this; } /** * Get path to main bin (relative to package directory) * * @return string * @throws \UnexpectedValueException */ public function getMain() { if ($this->main === null) { foreach ($this->package->getBins() as $path) { if (!file_exists($this->package->getDirectory() . $path)) { throw new \UnexpectedValueException('Bin file "' . $path . '" does not exist'); } $this->main = $path; break; } } return $this->main; } /** * set path to main bin (relative to package directory) * * @param string $main * @return $this */ public function setMain($main) { $this->main = $main; return $this; } /** * * @return Package */ public function getPackageRoot() { return $this->package; } /** * * @return Package[] */ public function getPackagesDependencies() { $packages = array(); $pathVendor = $this->package->getDirectory() . $this->package->getPathVendor(); // load all installed packages (use installed.json which also includes version instead of composer.lock) if (is_file($pathVendor . 'composer/installed.json')) { // file does not exist if there's nothing to be installed $installed = $this->loadJson($pathVendor . 'composer/installed.json'); // Composer 2.0 format wrapped in additional root key if (isset($installed['packages'])) { $installed = $installed['packages']; } foreach ($installed as $package) { $dir = $package['name'] . '/'; if (isset($package['target-dir'])) { $dir .= trim($package['target-dir'], '/') . '/'; } $dir = $pathVendor . $dir; $packages []= new Package($package, $dir); } } return $packages; } public function build() { $this->log('[' . $this->step . '/' . $this->step.'] Creating phar ' . $this->getTarget() . ''); $time = microtime(true); $pathVendor = $this->package->getDirectory() . $this->package->getPathVendor(); if (!is_dir($pathVendor)) { throw new \RuntimeException('Directory "' . $pathVendor . '" not properly installed, did you run "composer install"?'); } // get target and tempory file name to write to $target = $this->getTarget(); do { $tmp = $target . '.' . mt_rand() . '.phar'; } while (file_exists($tmp)); $targetPhar = new TargetPhar(new \Phar($tmp), $this); $this->log(' - Adding main package "' . $this->package->getName() . '"'); $targetPhar->addBundle($this->package->bundle()); $this->log(' - Adding composer base files'); // explicitly add composer autoloader $targetPhar->addFile($pathVendor . 'autoload.php'); // only add composer base directory (no sub-directories!) $targetPhar->buildFromIterator(new \GlobIterator($pathVendor . 'composer/*.*', \FilesystemIterator::KEY_AS_FILENAME)); foreach ($this->getPackagesDependencies() as $package) { $this->log(' - Adding dependency "' . $package->getName() . '" from "' . $this->getPathLocalToBase($package->getDirectory()) . '"'); $targetPhar->addBundle($package->bundle()); } $this->log(' - Setting main/stub'); $chmod = 0755; $main = $this->getMain(); if ($main === null) { $this->log(' WARNING: No main bin file defined! Resulting phar will NOT be executable'); } else { $generator = StubGenerator::create() ->index($main) ->extract(true) ->banner("Bundled by phar-composer with the help of php-box.\n\n@link https://github.com/clue/phar-composer"); $lines = file($this->package->getDirectory() . $main, FILE_IGNORE_NEW_LINES); if (substr($lines[0], 0, 2) === '#!') { $this->log(' Using referenced shebang "'. $lines[0] . '"'); $generator->shebang($lines[0]); // remove shebang from main file and add (overwrite) unset($lines[0]); $targetPhar->addFromString($main, implode("\n", $lines)); } $targetPhar->setStub($generator->generate()); $chmod = octdec(substr(decoct(fileperms($this->package->getDirectory() . $main)),-4)); $this->log(' Using referenced chmod ' . sprintf('%04o', $chmod)); } // stop buffering contents in memory and write to file // failure to write will emit a warning (ignore) and throw an (uncaught) exception try { @$targetPhar->stopBuffering(); $targetPhar = null; } catch (\PharException $e) { throw new \RuntimeException('Unable to write phar: ' . $e->getMessage()); } if ($chmod !== null) { $this->log(' Applying chmod ' . sprintf('%04o', $chmod)); if (chmod($tmp, $chmod) === false) { throw new \UnexpectedValueException('Unable to chmod target file "' . $target .'"'); } } if (file_exists($target)) { $this->log(' - Overwriting existing file ' . $target . ' (' . $this->getSize($target) . ')'); } if (@rename($tmp, $target) === false) { // retry renaming after sleeping to give slow network drives some time to flush data sleep(5); if (rename($tmp, $target) === false) { throw new \UnexpectedValueException('Unable to rename temporary phar archive to "'.$target.'"'); } } $time = max(microtime(true) - $time, 0); $this->log(''); $this->log(' OK - Creating ' . $this->getTarget() .' (' . $this->getSize($this->getTarget()) . ') completed after ' . round($time, 1) . 's'); } private function getSize($path) { return round(filesize($path) / 1024, 1) . ' KiB'; } public function getPathLocalToBase($path) { $root = $this->package->getDirectory(); if (strpos($path, $root) !== 0) { throw new \UnexpectedValueException('Path "' . $path . '" is not within base project path "' . $root . '"'); } return substr($path, strlen($root)); } public function log($message) { $this->logger->log($message); } public function setStep($step) { $this->step = $step; } /** * @param string $path * @return mixed * @throws \InvalidArgumentException */ private function loadJson($path) { $ret = @json_decode(file_get_contents($path), true); if ($ret === null) { throw new \InvalidArgumentException('Unable to parse given path "' . $path . '"', json_last_error()); } return $ret; } } startBuffering(); $this->phar = $phar; $this->pharComposer = $pharComposer; } /** * finalize writing of phar file */ public function stopBuffering() { $this->phar->stopBuffering(); } /** * adds given list of resources to phar * * @param Bundle $bundle */ public function addBundle(Bundle $bundle) { foreach ($bundle as $resource) { if (is_string($resource)) { $this->addFile($resource); } else { $this->buildFromIterator($resource); } } } /** * Adds a file to the Phar * * @param string $file The file name. */ public function addFile($file) { $this->phar->addFile($file, $this->pharComposer->getPathLocalToBase($file)); } public function buildFromIterator(\Traversable $iterator) { $this->phar->buildFromIterator($iterator, $this->pharComposer->getPackageRoot()->getDirectory()); } /** * Used to set the PHP loader or bootstrap stub of a Phar archive * * @param string $stub */ public function setStub($stub) { $this->phar->setStub($stub); } public function addFromString($local, $contents) { $this->phar->addFromString($local, $contents); } } # Change Log for the Composer Installer for PHP CodeSniffer All notable changes to this project will be documented in this file. This projects adheres to [Keep a CHANGELOG](https://keepachangelog.com/) and uses [Semantic Versioning](https://semver.org/). ## [Unreleased] _Nothing yet._ ## [v1.2.1] - 2026-05-06 ### Changed - Various housekeeping, including improvements to CI. ### Fixed - Fix potential error when running `composer install` with an `open_basedir` restriction in effect. Thanks [@srebb] ! [#271], [#272] [#271]: https://github.com/PHPCSStandards/composer-installer/issues/271 [#272]: https://github.com/PHPCSStandards/composer-installer/pull/272 ## [v1.2.0] - 2025-11-11 ### Changed - Various housekeeping, including improvements to the documentation and tests. ### Removed - Drop support for PHP_CodeSniffer 2.x. Thanks [@jrfnl] ! [#261] [#261]: https://github.com/PHPCSStandards/composer-installer/pull/261 ## [v1.1.2] - 2025-07-17 ### Changed - General housekeeping. ### Fixed - [#247]: Potential fatal error when the Composer EventDispatcher is called programmatically from an integration. Thanks [@jrfnl] ! [#248] [#247]: https://github.com/PHPCSStandards/composer-installer/issues/247 [#248]: https://github.com/PHPCSStandards/composer-installer/pull/248 ## [v1.1.1] - 2025-06-27 ### Changed - Various housekeeping, including improvements to the documentation. ### Fixed - [#239]: The PHP_CodeSniffer package could not be always found when running the plugin in a Drupal or Magento setup. Thanks [@jrfnl] ! [#245] [#239]: https://github.com/PHPCSStandards/composer-installer/issues/239 [#245]: https://github.com/PHPCSStandards/composer-installer/pull/245 ## [v1.1.0] - 2025-06-24 ### Changed - Various housekeeping, including improvements to the documentation and tests. Thanks [@SplotyCode], [@fredden] for contributing! ### Removed - Drop support for Composer v1.x. Thanks [@fredden] ! [#230] [#230]: https://github.com/PHPCSStandards/composer-installer/pull/230 ## [v1.0.0] - 2023-01-05 ### Breaking changes - Rename namespace prefix from Dealerdirect to PHPCSStandards by [@jrfnl] in [#191] - Drop support for PHP 5.3 by [@jrfnl] in [#147] ### Changed - Correct grammar in error message by [@fredden] in [#189] - .gitattributes: sync with current repo state by [@jrfnl] in [#198] - PHPCSVersions: update URL references by [@jrfnl] in [#161] - README: remove references to Scrutinizer by [@jrfnl] in [#157] - Rename references to master branch by [@Potherca] in [#201] - Update repo references by [@jrfnl] in [#158] - GH Actions: add builds against Composer 2.2 for PHP 7.2 - 8.x by [@jrfnl] in [#172] - GH Actions: bust the cache semi-regularly by [@jrfnl] in [#192] - GH Actions: fix builds on Windows with PHP 8.2 by [@jrfnl] in [#180] - GH Actions: fix up fail-fast for setup-php by [@jrfnl] in [#195] - GH Actions: run integration tests against Composer snapshot by [@jrfnl] in [#163] - GH Actions: run linting against against ubuntu-latest by [@jrfnl] in [#184] - GH Actions/Securitycheck: update the security checker download by [@jrfnl] in [#178] - GH Actions/Securitycheck: update the security checker download by [@jrfnl] in [#186] - GH Actions/Securitycheck: update the security checker download by [@jrfnl] in [#190] - GH Actions: selectively use fail-fast with setup-php by [@jrfnl] in [#194] - GH Actions: stop running tests against PHP 5.5/Composer 1.x on Windows (and remove work-arounds) by [@jrfnl] in [#183] - GH Actions: various tweaks / PHP 8.2 not allowed to fail by [@jrfnl] in [#193] - GH Actions: version update for various predefined actions by [@jrfnl] in [#170] - Update YamLint by [@Potherca] in [#173] - Add initial integration test setup and first few tests by [@jrfnl] in [#153] - BaseLineTest: stabilize the message checks by [@jrfnl] in [#162] - PlayNiceWithScriptsTest: wrap output expectation in condition by [@jrfnl] in [#179] - RegisterExternalStandardsTest: add new tests by [@jrfnl] in [#165] - RegisterExternalStandardsTest: stabilize test for Composer v1 on Windows with PHP 5.5 by [@jrfnl] in [#171] - TestCase::executeCliCommand(): retry Composer commands on a particular exception by [@jrfnl] in [#164] - Tests: add new InstalledPathsOrderTest by [@jrfnl] in [#176] - Tests: add new InstallUpdateEventsTest and NonInstallUpdateEventsTest by [@jrfnl] in [#174] - Tests: add new InvalidPackagesTest by [@jrfnl] in [#168] - Tests: add new PlayNiceWithScriptsTest by [@jrfnl] in [#169] - Tests: add new PreexistingPHPCSConfigTest by [@jrfnl] in [#166] - Tests: add new PreexistingPHPCSInstalledPathsConfigTest + bug fix by [@jrfnl] in [#167] - Tests: add new RemovePluginTest by [@jrfnl] in [#177] - Tests: add new RootPackageHandlingTest + bugfix by [@jrfnl] in [#175] ### Fixed - Plugin: improve feedback by [@jrfnl] in [#182] [#147]: https://github.com/PHPCSStandards/composer-installer/pull/147 [#153]: https://github.com/PHPCSStandards/composer-installer/pull/153 [#157]: https://github.com/PHPCSStandards/composer-installer/pull/157 [#158]: https://github.com/PHPCSStandards/composer-installer/pull/158 [#161]: https://github.com/PHPCSStandards/composer-installer/pull/161 [#162]: https://github.com/PHPCSStandards/composer-installer/pull/162 [#163]: https://github.com/PHPCSStandards/composer-installer/pull/163 [#164]: https://github.com/PHPCSStandards/composer-installer/pull/164 [#165]: https://github.com/PHPCSStandards/composer-installer/pull/165 [#166]: https://github.com/PHPCSStandards/composer-installer/pull/166 [#167]: https://github.com/PHPCSStandards/composer-installer/pull/167 [#168]: https://github.com/PHPCSStandards/composer-installer/pull/168 [#169]: https://github.com/PHPCSStandards/composer-installer/pull/169 [#170]: https://github.com/PHPCSStandards/composer-installer/pull/170 [#171]: https://github.com/PHPCSStandards/composer-installer/pull/171 [#172]: https://github.com/PHPCSStandards/composer-installer/pull/172 [#173]: https://github.com/PHPCSStandards/composer-installer/pull/173 [#174]: https://github.com/PHPCSStandards/composer-installer/pull/174 [#175]: https://github.com/PHPCSStandards/composer-installer/pull/175 [#176]: https://github.com/PHPCSStandards/composer-installer/pull/176 [#177]: https://github.com/PHPCSStandards/composer-installer/pull/177 [#178]: https://github.com/PHPCSStandards/composer-installer/pull/178 [#179]: https://github.com/PHPCSStandards/composer-installer/pull/179 [#180]: https://github.com/PHPCSStandards/composer-installer/pull/180 [#182]: https://github.com/PHPCSStandards/composer-installer/pull/182 [#183]: https://github.com/PHPCSStandards/composer-installer/pull/183 [#184]: https://github.com/PHPCSStandards/composer-installer/pull/184 [#186]: https://github.com/PHPCSStandards/composer-installer/pull/186 [#189]: https://github.com/PHPCSStandards/composer-installer/pull/189 [#190]: https://github.com/PHPCSStandards/composer-installer/pull/190 [#191]: https://github.com/PHPCSStandards/composer-installer/pull/191 [#192]: https://github.com/PHPCSStandards/composer-installer/pull/192 [#193]: https://github.com/PHPCSStandards/composer-installer/pull/193 [#194]: https://github.com/PHPCSStandards/composer-installer/pull/194 [#195]: https://github.com/PHPCSStandards/composer-installer/pull/195 [#198]: https://github.com/PHPCSStandards/composer-installer/pull/198 [#201]: https://github.com/PHPCSStandards/composer-installer/pull/201 ## [v0.7.2] - 2022-02-04 ### Changed - Add details regarding QA automation in CONTRIBUTING.md file. by [@Potherca] in [#133] - Add mention of Composer and PHP compatibility to project README. by [@Potherca] in [#132] - Composer: tweak PHPCS version constraint by [@jrfnl] in [#152] - CONTRIBUTING: remove duplicate code of conduct by [@jrfnl] in [#148] - Document release process by [@Potherca] in [#118] - Plugin::loadInstalledPaths(): config-show always shows all by [@jrfnl] in [#154] - README: minor tweaks by [@jrfnl] in [#149] - README: update with information about Composer >= 2.2 by [@jrfnl] in [#141] - Replace deprecated Sensiolabs security checker by [@paras-malhotra] in [#130] - Stabilize a condition by [@jrfnl] in [#127] - Update copyright year by [@jrfnl] in [#138] - Various minor tweaks by [@jrfnl] in [#151] - Change YamlLint config to prevent "truthy" warning. by [@Potherca] in [#144] - GH Actions: PHP 8.1 has been released by [@jrfnl] in [#139] - Travis: line length tweaks by [@jrfnl] in [#128] - CI: Switch to GH Actions by [@jrfnl] in [#137] - CI: various updates by [@jrfnl] in [#140] [#118]: https://github.com/PHPCSStandards/composer-installer/pull/118 [#127]: https://github.com/PHPCSStandards/composer-installer/pull/127 [#128]: https://github.com/PHPCSStandards/composer-installer/pull/128 [#130]: https://github.com/PHPCSStandards/composer-installer/pull/130 [#132]: https://github.com/PHPCSStandards/composer-installer/pull/132 [#133]: https://github.com/PHPCSStandards/composer-installer/pull/133 [#137]: https://github.com/PHPCSStandards/composer-installer/pull/137 [#138]: https://github.com/PHPCSStandards/composer-installer/pull/138 [#139]: https://github.com/PHPCSStandards/composer-installer/pull/139 [#140]: https://github.com/PHPCSStandards/composer-installer/pull/140 [#141]: https://github.com/PHPCSStandards/composer-installer/pull/141 [#144]: https://github.com/PHPCSStandards/composer-installer/pull/144 [#148]: https://github.com/PHPCSStandards/composer-installer/pull/148 [#149]: https://github.com/PHPCSStandards/composer-installer/pull/149 [#151]: https://github.com/PHPCSStandards/composer-installer/pull/151 [#152]: https://github.com/PHPCSStandards/composer-installer/pull/152 [#154]: https://github.com/PHPCSStandards/composer-installer/pull/154 ## [v0.7.1] - 2020-12-07 ### Closed issues - Order of installed_paths inconsistent between runs [#125] - Maintaining this project and Admin rights [#113] ### Changed - Sort list of installed paths before saving for consistency by [@kevinfodness] in [#126] - Update code of conduct by [@Potherca] in [#117] - Add remark configuration by [@Potherca] in [#122] - Travis: add build against PHP 8.0 by [@jrfnl] in [#124] ### Fixed - Fixed v4 constraint by [@GrahamCampbell] in [#115] [#113]: https://github.com/PHPCSStandards/composer-installer/issues/113 [#115]: https://github.com/PHPCSStandards/composer-installer/pull/115 [#117]: https://github.com/PHPCSStandards/composer-installer/pull/117 [#122]: https://github.com/PHPCSStandards/composer-installer/pull/122 [#124]: https://github.com/PHPCSStandards/composer-installer/pull/124 [#125]: https://github.com/PHPCSStandards/composer-installer/issues/125 [#126]: https://github.com/PHPCSStandards/composer-installer/pull/126 ## [v0.7.0] - 2020-06-25 ### Closed issues - Composer 2.x compatibility [#108] - Add link to Packagist on main page [#110] - Switch from Travis CI .org to .com [#112] ### Added - Allow installation on PHP 8 by [@jrfnl] in [#106] - Support Composer 2.0 by [@jrfnl] in [#111] ### Changed - Test with PHPCS 4.x and allow installation when using PHPCS 4.x by [@jrfnl] in [#107] - Fix case of class name by [@Seldaek] in [#109] [#106]: https://github.com/PHPCSStandards/composer-installer/pull/106 [#107]: https://github.com/PHPCSStandards/composer-installer/pull/107 [#108]: https://github.com/PHPCSStandards/composer-installer/issues/108 [#109]: https://github.com/PHPCSStandards/composer-installer/pull/109 [#110]: https://github.com/PHPCSStandards/composer-installer/issues/110 [#111]: https://github.com/PHPCSStandards/composer-installer/pull/111 [#112]: https://github.com/PHPCSStandards/composer-installer/issues/112 ## [v0.6.2] - 2020-01-29 ### Fixed - Composer scripts/commands broken in 0.6.0 update by [@BrianHenryIE] in [#105] [#105]: https://github.com/PHPCSStandards/composer-installer/pull/105 ## [v0.6.1] - 2020-01-27 ### Closed issues - Do not exit with code 1 on uninstall (--no-dev) [#103] ### Changed - Readme: minor tweak now 0.6.0 has been released [#102] ([@jrfnl]) ### Fixed - [#103]: Fix for issue #103 [#104] ([@Potherca]) [#102]: https://github.com/PHPCSStandards/composer-installer/pull/102 [#103]: https://github.com/PHPCSStandards/composer-installer/issues/103 [#104]: https://github.com/PHPCSStandards/composer-installer/pull/104 ## [v0.6.0] - 2020-01-19 ### Closed issues - Composer PHP version appears not to be respected [#79] - Allow a string value for extra.phpcodesniffer-search-depth [#82] - Add [@jrfnl] as (co)maintainer to this project [#87] ### Added - Add support for a string phpcodesniffer-search-depth config value set via composer config by [@TravisCarden] in [#85] - Send an exit code when the script terminates by [@jrfnl] in [#93] - Verify the installed_paths after save by [@jrfnl] in [#97] ### Changed - CS: fix compliance with PSR12 by [@jrfnl] in [#88] - Improve GH issue template by [@jrfnl] in [#94] - Readme: add section about including this plugin from an external PHPCS standard by [@jrfnl] in [#95] - Bug report template: further enhancement by [@jrfnl] in [#99] - Update copyright year. by [@Potherca] in [#101] - Adding linting jobs in github action by [@mjrider] in [#96] - GH Actions: minor tweaks: by [@jrfnl] in [#100] - Travis: disable Xdebug by [@jrfnl] in [#89] - Travis: test against PHP 7.4, not snapshot by [@jrfnl] in [#90] - Travis: use a mix of PHPCS versions in the matrix by [@jrfnl] in [#91] - Update Travis file and fix build by [@Potherca] in [#86] ### Fixed - [#79]: Respect PHP version used by Composer and provide better feedback on failure by [@jrfnl] in [#80] - Bug fix: loadInstalledPaths() very very broken since PHPCS 3.1.0 by [@jrfnl] in [#98] [#79]: https://github.com/PHPCSStandards/composer-installer/issues/79 [#80]: https://github.com/PHPCSStandards/composer-installer/issues/80 [#82]: https://github.com/PHPCSStandards/composer-installer/issues/82 [#85]: https://github.com/PHPCSStandards/composer-installer/pull/85 [#86]: https://github.com/PHPCSStandards/composer-installer/pull/86 [#87]: https://github.com/PHPCSStandards/composer-installer/issues/87 [#88]: https://github.com/PHPCSStandards/composer-installer/pull/88 [#89]: https://github.com/PHPCSStandards/composer-installer/pull/89 [#90]: https://github.com/PHPCSStandards/composer-installer/pull/90 [#91]: https://github.com/PHPCSStandards/composer-installer/pull/91 [#93]: https://github.com/PHPCSStandards/composer-installer/pull/93 [#94]: https://github.com/PHPCSStandards/composer-installer/pull/94 [#95]: https://github.com/PHPCSStandards/composer-installer/pull/95 [#96]: https://github.com/PHPCSStandards/composer-installer/pull/96 [#97]: https://github.com/PHPCSStandards/composer-installer/pull/97 [#98]: https://github.com/PHPCSStandards/composer-installer/issues/98 [#99]: https://github.com/PHPCSStandards/composer-installer/pull/99 [#100]: https://github.com/PHPCSStandards/composer-installer/pull/100 [#101]: https://github.com/PHPCSStandards/composer-installer/pull/101 ## [v0.5.0] - 2018-10-26 ### Closed issues - Scan depth as parameter [#45] - phpcs: Exit Code: 127 (Command not found) on every Composer command [#48] - The composer plugin implementation seems to be breaking the composer lifecycle [#49] - Installation error [#53] - Broke composer commands when used with wp-cli/package-command [#59] - Getting a new stable release [#60] - Support PHP CodeSniffer standards in packages installed outside of the vendor directory [#63] ### Added - Adds the ability to set the max depth from the composer.json file by [@Potherca] in [#46] ### Changed - Build/PHPCS: update PHPCompatibility repo name by [@jrfnl] in [#54] - README: remove VersionEye badge by [@jrfnl] in [#55] - README: replace maintenance badge by [@jrfnl] in [#56] - Execute phpcs and security-checker from vendor/bin by [@gapple] in [#52] - PHPCS: various minor tweaks by [@jrfnl] in [#57] - Travis: various tweaks by [@jrfnl] in [#58] - Use PHPCompatibility 9.0.0 by [@jrfnl] in [#61] - Build/Travis: test builds against PHP 7.3 by [@jrfnl] in [#62] - Updates copyright year by [@frenck] in [#67] - Enforces PSR12 by [@frenck] in [#66] - Updates contact information by [@frenck] in [#68] - Updates README, spelling/grammar, removed Working section by [@frenck] in [#69] - Replaces ProcessBuilder by ProcessExecutor by [@frenck] in [#70] - Refactors relative path logic by [@frenck] in [#71] - Removes suggested packages by [@frenck] in [#72] - Ensures absolute paths during detection phase by [@frenck] in [#73] - Trivial code cleanup by [@frenck] in [#74] - Fixes duplicate declaration of cwd by [@frenck] in [#75] - Removes HHVM from TravisCI by [@frenck] in [#76] - Adds PHP_CodeSniffer version constraints by [@frenck] in [#77] ### Fixed - [#49]: Move loadInstalledPaths from init to onDependenciesChangedEvent by [@gapple] in [#51] [#45]: https://github.com/PHPCSStandards/composer-installer/issues/45 [#46]: https://github.com/PHPCSStandards/composer-installer/pull/46 [#48]: https://github.com/PHPCSStandards/composer-installer/issues/48 [#49]: https://github.com/PHPCSStandards/composer-installer/issues/49 [#51]: https://github.com/PHPCSStandards/composer-installer/pull/51 [#52]: https://github.com/PHPCSStandards/composer-installer/pull/52 [#53]: https://github.com/PHPCSStandards/composer-installer/issues/53 [#54]: https://github.com/PHPCSStandards/composer-installer/pull/54 [#55]: https://github.com/PHPCSStandards/composer-installer/pull/55 [#56]: https://github.com/PHPCSStandards/composer-installer/pull/56 [#57]: https://github.com/PHPCSStandards/composer-installer/pull/57 [#58]: https://github.com/PHPCSStandards/composer-installer/pull/58 [#59]: https://github.com/PHPCSStandards/composer-installer/issues/59 [#60]: https://github.com/PHPCSStandards/composer-installer/issues/60 [#61]: https://github.com/PHPCSStandards/composer-installer/pull/61 [#62]: https://github.com/PHPCSStandards/composer-installer/pull/62 [#63]: https://github.com/PHPCSStandards/composer-installer/issues/63 [#66]: https://github.com/PHPCSStandards/composer-installer/pull/66 [#67]: https://github.com/PHPCSStandards/composer-installer/pull/67 [#68]: https://github.com/PHPCSStandards/composer-installer/pull/68 [#69]: https://github.com/PHPCSStandards/composer-installer/pull/69 [#70]: https://github.com/PHPCSStandards/composer-installer/pull/70 [#71]: https://github.com/PHPCSStandards/composer-installer/pull/71 [#72]: https://github.com/PHPCSStandards/composer-installer/pull/72 [#73]: https://github.com/PHPCSStandards/composer-installer/pull/73 [#74]: https://github.com/PHPCSStandards/composer-installer/pull/74 [#75]: https://github.com/PHPCSStandards/composer-installer/pull/75 [#76]: https://github.com/PHPCSStandards/composer-installer/pull/76 [#77]: https://github.com/PHPCSStandards/composer-installer/pull/77 ## [v0.4.4] - 2017-12-06 ### Closed issues - PHP 7.2 compatibility issue [#43] ### Changed - Update Travis CI svg badge and link URLs [#42] ([@ntwb]) - Add PHP 7.2 to Travis CI [#41] ([@ntwb]) - Docs: Fix link to releases [#40] ([@GaryJones]) [#40]: https://github.com/PHPCSStandards/composer-installer/pull/40 [#41]: https://github.com/PHPCSStandards/composer-installer/pull/41 [#42]: https://github.com/PHPCSStandards/composer-installer/pull/42 [#43]: https://github.com/PHPCSStandards/composer-installer/issues/43 ## [v0.4.3] - 2017-09-18 ### Changed - CS: Add PHP 5.3 compatibility [#39] ([@GaryJones]) - Local PHPCS [#38] ([@GaryJones]) [#38]: https://github.com/PHPCSStandards/composer-installer/pull/38 [#39]: https://github.com/PHPCSStandards/composer-installer/pull/39 ## [v0.4.2] - 2017-08-16 ### Changed - Docs: Rename example script [#35] ([@GaryJones]) - Update README.md [#36] ([@jrfnl]) - Documentation update. [#37] ([@frenck]) [#35]: https://github.com/PHPCSStandards/composer-installer/pull/35 [#36]: https://github.com/PHPCSStandards/composer-installer/pull/36 [#37]: https://github.com/PHPCSStandards/composer-installer/pull/37 ## [v0.4.1] - 2017-08-01 ### Closed issues - Incorrect relative paths for WPCS [#33] ### Fixed - [#33]: Changes the way the installed_paths are set. [#34] ([@frenck]) [#33]: https://github.com/PHPCSStandards/composer-installer/issues/33 [#34]: https://github.com/PHPCSStandards/composer-installer/pull/34 ## [v0.4.0] - 2017-05-11 ### Closed issues - Add support for code standards in root of repository for PHP_CodeSniffer 3.x [#26] - Config codings styles in composer.json from project [#23] - Check the root package for sniffs to install [#20] - Document the ability to execute the main plugin functionality directly [#18] - Add a CHANGELOG.md [#17] - Install sniffs with relative paths in CodeSniffer.conf [#14] ### Added - Support for coding standard in the root repository for PHP_CodeSniffer v3.x [#30] ([@frenck]) - Added support for having coding standards in the root package [#25] ([@frenck]) ### Changed - Local projects uses relative paths to their coding standards [#28] ([@frenck]) - Docs: Updated README. [#31] ([@frenck]) - Docs: Adds reference to calling the script directly in the README. [#29] ([@Potherca]) - Adds Travis-CI configuration file. [#27] ([@Potherca]) [#14]: https://github.com/PHPCSStandards/composer-installer/issues/14 [#17]: https://github.com/PHPCSStandards/composer-installer/issues/17 [#18]: https://github.com/PHPCSStandards/composer-installer/issues/18 [#20]: https://github.com/PHPCSStandards/composer-installer/issues/20 [#23]: https://github.com/PHPCSStandards/composer-installer/issues/23 [#25]: https://github.com/PHPCSStandards/composer-installer/pull/25 [#26]: https://github.com/PHPCSStandards/composer-installer/issues/26 [#27]: https://github.com/PHPCSStandards/composer-installer/pull/27 [#28]: https://github.com/PHPCSStandards/composer-installer/pull/28 [#29]: https://github.com/PHPCSStandards/composer-installer/pull/29 [#31]: https://github.com/PHPCSStandards/composer-installer/pull/31 ## [v0.3.2] - 2017-03-29 ### Closed issues - Coding Standard tries itself to install with installPath when it's the root package [#19] ### Changed - Improvements to the documentation [#22] ([@Potherca]) - Added instanceof check to prevent root package from being installed [#21] ([@bastianschwarz]) ### Fixed - [#13]: Incorrect coding standards search depth [#15] ([@frenck]) [#19]: https://github.com/PHPCSStandards/composer-installer/issues/19 [#21]: https://github.com/PHPCSStandards/composer-installer/pull/21 [#22]: https://github.com/PHPCSStandards/composer-installer/pull/22 ## [v0.3.1] - 2017-02-17 ### Closed issues - Plugin not working correctly when sniffs install depth is equal to "1" [#13] - Create new stable release version to support wider use [#11] ### Fixed - [#13]: Incorrect coding standards search depth [#15] ([@frenck]) [#11]: https://github.com/PHPCSStandards/composer-installer/issues/11 [#13]: https://github.com/PHPCSStandards/composer-installer/issues/13 [#15]: https://github.com/PHPCSStandards/composer-installer/pull/15 ## [v0.3.0] - 2017-02-15 ### Implemented enhancements - Install Plugin provides no feedback [#7] - Installing coding standards when executing Composer with --no-scripts [#4] - Github contribution templates [#10] ([@christopher-hopper]) - Show config actions and a result as Console output [#8] ([@christopher-hopper]) - Adds static function to call the Plugin::onDependenciesChangedEvent() method [#5] ([@Potherca]) ### Added - Support existing standards packages with subfolders [#6] ([@christopher-hopper]) ### Changed - Improved documentation [#12] ([@frenck]) - Removal of lgtm.co [#3] ([@frenck]) [#3]: https://github.com/PHPCSStandards/composer-installer/pull/3 [#4]: https://github.com/PHPCSStandards/composer-installer/issues/4 [#5]: https://github.com/PHPCSStandards/composer-installer/pull/5 [#6]: https://github.com/PHPCSStandards/composer-installer/pull/6 [#7]: https://github.com/PHPCSStandards/composer-installer/issues/7 [#8]: https://github.com/PHPCSStandards/composer-installer/pull/8 [#10]: https://github.com/PHPCSStandards/composer-installer/pull/10 [#12]: https://github.com/PHPCSStandards/composer-installer/pull/12 ## [v0.2.1] - 2016-11-01 Fixes an issue with having this plugin installed globally within composer, but using your global composer installation on a local repository without PHP_CodeSniffer installed. ### Fixed - Bugfix: Plugin fails when PHP_CodeSniffer is not installed [#2] ([@frenck]) [#2]: https://github.com/PHPCSStandards/composer-installer/pull/2 ## [v0.2.0] - 2016-11-01 For this version on, this installer no longer messes with the installation paths of composer libraries, but instead, it configures PHP_CodeSniffer to look into other directories for coding standards. ### Changed - PHPCS Configuration management [#1] ([@frenck]) [#1]: https://github.com/PHPCSStandards/composer-installer/pull/1 ## [v0.1.1] - 2016-10-24 ### Changed - Standard name mapping improvements ## v0.1.0 - 2016-10-23 First useable release. [v1.2.1]: https://github.com/PHPCSStandards/composer-installer/compare/v1.2.0...v1.2.1 [v1.2.0]: https://github.com/PHPCSStandards/composer-installer/compare/v1.1.2...v1.2.0 [v1.1.2]: https://github.com/PHPCSStandards/composer-installer/compare/v1.1.1...v1.1.2 [v1.1.1]: https://github.com/PHPCSStandards/composer-installer/compare/v1.1.0...v1.1.1 [v1.1.0]: https://github.com/PHPCSStandards/composer-installer/compare/v1.0.0...v1.1.0 [v1.0.0]: https://github.com/PHPCSStandards/composer-installer/compare/v0.7.2...v1.0.0 [v0.7.2]: https://github.com/PHPCSStandards/composer-installer/compare/v0.7.1...v0.7.2 [v0.7.1]: https://github.com/PHPCSStandards/composer-installer/compare/v0.7.0...v0.7.1 [v0.7.0]: https://github.com/PHPCSStandards/composer-installer/compare/v0.6.2...v0.7.0 [v0.6.2]: https://github.com/PHPCSStandards/composer-installer/compare/v0.6.1...v0.6.2 [v0.6.1]: https://github.com/PHPCSStandards/composer-installer/compare/v0.6.0...v0.6.1 [v0.6.0]: https://github.com/PHPCSStandards/composer-installer/compare/v0.5.0...v0.6.0 [v0.5.0]: https://github.com/PHPCSStandards/composer-installer/compare/v0.4.4...v0.5.0 [v0.4.4]: https://github.com/PHPCSStandards/composer-installer/compare/v0.4.3...v0.4.4 [v0.4.3]: https://github.com/PHPCSStandards/composer-installer/compare/v0.4.2...v0.4.3 [v0.4.2]: https://github.com/PHPCSStandards/composer-installer/compare/v0.4.1...v0.4.2 [v0.4.1]: https://github.com/PHPCSStandards/composer-installer/compare/v0.4.0...v0.4.1 [v0.4.0]: https://github.com/PHPCSStandards/composer-installer/compare/v0.3.2...v0.4.0 [v0.3.2]: https://github.com/PHPCSStandards/composer-installer/compare/v0.3.1...v0.3.2 [v0.3.1]: https://github.com/PHPCSStandards/composer-installer/compare/v0.3.0...v0.3.1 [v0.3.0]: https://github.com/PHPCSStandards/composer-installer/compare/v0.2.1...v0.3.0 [v0.2.1]: https://github.com/PHPCSStandards/composer-installer/compare/v0.2.0...v0.2.1 [v0.2.0]: https://github.com/PHPCSStandards/composer-installer/compare/v0.1.1...v0.2.0 [v0.1.1]: https://github.com/PHPCSStandards/composer-installer/compare/v0.1.0...v0.1.1 [PHP_CodeSniffer]: https://github.com/PHPCSStandards/PHP_CodeSniffer [@bastianschwarz]: https://github.com/bastianschwarz [@BrianHenryIE]: https://github.com/BrianHenryIE [@christopher-hopper]: https://github.com/christopher-hopper [@fredden]: https://github.com/fredden [@frenck]: https://github.com/frenck [@gapple]: https://github.com/gapple [@GaryJones]: https://github.com/GaryJones [@GrahamCampbell]: https://github.com/GrahamCampbell [@jrfnl]: https://github.com/jrfnl [@kevinfodness]: https://github.com/kevinfodness [@mjrider]: https://github.com/mjrider [@ntwb]: https://github.com/ntwb [@paras-malhotra]: https://github.com/paras-malhotra [@Potherca]: https://github.com/Potherca [@Seldaek]: https://github.com/Seldaek [@SplotyCode]: https://github.com/SplotyCode [@srebb]: https://github.com/srebb [@TravisCarden]: https://github.com/TravisCarden MIT License Copyright (c) 2016-2022 Dealerdirect B.V. and contributors Copyright (c) 2022 PHPCSStandards and contributors 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_CodeSniffer Standards Composer Installer Plugin ![Last Commit][last-updated-shield] ![Awesome][awesome-shield] [![License][license-shield]](LICENSE.md) [![Tests][ghactionstest-shield]][ghactions] [![Latest Version on Packagist][packagist-version-shield]][packagist-version] [![Packagist][packagist-shield]][packagist] [![Contributor Covenant][code-of-conduct-shield]][code-of-conduct] This composer installer plugin makes installation of [PHP_CodeSniffer][codesniffer] coding standards (rulesets) straight-forward. No more symbolic linking of directories, checking out repositories on specific locations or manually changing the `phpcs` configuration. ## Usage Installation can be done with [Composer][composer], by requiring this package as a development dependency: ```bash composer require --dev dealerdirect/phpcodesniffer-composer-installer:"^1.0" ``` Since Composer 2.2, Composer will [ask for your permission](https://blog.packagist.com/composer-2-2/#more-secure-plugin-execution) to allow this plugin to execute code. For this plugin to be functional, permission needs to be granted. When permission has been granted, the following snippet will automatically be added to your `composer.json` file by Composer: ```json { "config": { "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true } } } ``` You can safely add the permission flag (to avoid Composer needing to ask), by running: ```bash composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true ``` That's it. ### Compatibility This plugin is compatible with: - PHP **5.4+**, **7.x**, and **8.x** (Support for PHP v8 is available since [`v0.7.0`][v0.7]) - [Composer][composer] **2.2+** (Support for Composer v2 is available since [`v0.7.0`][v0.7]; support for Composer < 2.2 was dropped in [`v1.1.0`][v1.1]) - [PHP_CodeSniffer][codesniffer] **3.x** and **4.x**(Support for PHP_CodeSniffer v4 is available since [`v0.7.0`][v0.7], support for PHP_CodeSniffer v2 was dropped in [`v1.2.0`][v1.2]) ### How it works Basically, this plugin executes the following steps: - This plugin searches for [`phpcodesniffer-standard` packages][] in all of your currently installed Composer packages. - Matching packages and the project itself are scanned for PHP_CodeSniffer rulesets. - The plugin will call PHP_CodeSniffer and configure the `installed_paths` option. ### Example project The following is an example Composer project and has included multiple `phpcodesniffer-standard` packages. ```json { "name": "example/project", "description": "Just an example project", "type": "project", "require": {}, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "*", "phpcompatibility/php-compatibility": "*", "wp-coding-standards/wpcs": "*" }, "config": { "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true } } } ``` After running `composer install` PHP_CodeSniffer just works: ```bash $ ./vendor/bin/phpcs -i The installed coding standards are PEAR, PSR1, PSR2, PSR12, Squiz, Zend, PHPCompatibility, Modernize, NormalizedArrays, Universal, PHPCSUtils, WordPress, WordPress-Core, WordPress-Docs and WordPress-Extra ``` ### Calling the plugin directly In some circumstances, it is desirable to call this plugin's functionality directly. For instance, during development or in [CI][definition-ci] environments. As the plugin requires Composer to work, direct calls need to be wired through a project's `composer.json`. This is done by adding a call to the `Plugin::run` function in the `script` section of the `composer.json`: ```json { "scripts": { "install-codestandards": [ "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" ] } } ``` The command can then be called using `composer run-script install-codestandards` or referenced from other script configurations, as follows: ```json { "scripts": { "install-codestandards": [ "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" ], "post-install-cmd": [ "@install-codestandards" ] } } ``` For more details about Composer scripts, please refer to [the section on scripts in the Composer manual][composer-manual-scripts]. ### Changing the Coding Standards search depth By default, this plugin searches up for Coding Standards up to three directories deep. In most cases, this should be sufficient. However, this plugin allows you to customize the search depth setting if needed. ```json { "extra": { "phpcodesniffer-search-depth": 5 } } ``` ### Caveats When this plugin is installed globally, composer will load the _global_ plugin rather than the one from the local repository. Despite [this behavior being documented in the composer manual][using-composer-plugins], it could potentially confuse as another version of the plugin could be run and not the one specified by the project. ## Developing Coding Standards Coding standard can be developed normally, as documented by [PHP_CodeSniffer][codesniffer], in the [Coding Standard Tutorial][tutorial]. Create a composer package of your coding standard by adding a `composer.json` file. ```json { "name" : "acme/phpcodesniffer-our-standards", "description" : "Package contains all coding standards of the Acme company", "require" : { "php" : ">=5.4.0", "squizlabs/php_codesniffer" : "^3.13" }, "type" : "phpcodesniffer-standard" } ``` Requirements: * The repository may contain one or more standards. * Each standard can have a separate directory no deeper than 3 levels from the repository root. * The package `type` must be `phpcodesniffer-standard`. Without this, the plugin will not trigger. ### Requiring the plugin from within your coding standard If your coding standard itself depends on additional external PHPCS standards, this plugin can make life easier on your end-users by taking care of the installation of all standards - yours and your dependencies - for them. This can help reduce the number of support questions about setting the `installed_paths`, as well as simplify your standard's installation instructions. For this to work, make sure your external standard adds this plugin to the `composer.json` config via `require`, **not** `require-dev`. > :warning: Your end-user may already `require-dev` this plugin and/or other external standards used > by your end-users may require this plugin as well. > > To prevent your end-users getting into "_dependency hell_", make sure to make the version requirement > for this plugin flexible. > > Remember that [Composer treats unstable minors as majors][composer-manual-caret] and will not be able to resolve > one config requiring this plugin at version `^0.7`, while another requires it at version `^1.0`. > Either allow multiple minors or use `*` as the version requirement. > > Some examples of flexible requirements which can be used: > ```bash > composer require dealerdirect/phpcodesniffer-composer-installer:"*" > composer require dealerdirect/phpcodesniffer-composer-installer:"^0.4.1 || ^0.5 || ^0.6 || ^0.7 || ^1.0" > ``` ## Contributing This is an active open-source project. We are always open to people who want to use the code or contribute to it. We've set up a separate document for our [contribution guidelines][contributing-guidelines]. Thank you for being involved! :heart_eyes: ## Authors & contributors The original idea and setup of this repository is by [Franck Nijhof][frenck], employee @ Dealerdirect. For a full list of all authors and/or contributors, check [the contributors page][contributors]. ## Funding This project is included in the projects supported via the [PHP_CodeSniffer Open Collective][phpcs-open-collective]. If you use this plugin, financial contributions to the Open Collective are encouraged and appreciated. ## License The MIT License (MIT) Copyright (c) 2016-2022 Dealerdirect B.V. and contributors Copyright (c) 2022- PHPCSStandards and contributors 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. [awesome-shield]: https://img.shields.io/badge/awesome%3F-yes-brightgreen.svg [code-of-conduct-shield]: https://img.shields.io/badge/Contributor%20Covenant-v2.0-ff69b4.svg [code-of-conduct]: CODE_OF_CONDUCT.md [codesniffer]: https://github.com/PHPCSStandards/PHP_CodeSniffer [composer-manual-scripts]: https://getcomposer.org/doc/articles/scripts.md [composer-manual-caret]: https://getcomposer.org/doc/articles/versions.md#caret-version-range- [composer]: https://getcomposer.org/ [contributing-guidelines]: CONTRIBUTING.md [contributors]: https://github.com/PHPCSStandards/composer-installer/graphs/contributors [definition-ci]: https://en.wikipedia.org/wiki/Continuous_integration [frenck]: https://github.com/frenck [last-updated-shield]: https://img.shields.io/github/last-commit/PHPCSStandards/composer-installer.svg [license-shield]: https://img.shields.io/github/license/PHPCSStandards/composer-installer.svg [packagist-shield]: https://img.shields.io/packagist/dt/dealerdirect/phpcodesniffer-composer-installer.svg [packagist-version-shield]: https://img.shields.io/packagist/v/dealerdirect/phpcodesniffer-composer-installer.svg [packagist-version]: https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer [packagist]: https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer [`phpcodesniffer-standard` packages]: https://packagist.org/explore/?type=phpcodesniffer-standard [phpcs-open-collective]: https://opencollective.com/php_codesniffer [scrutinizer-shield]: https://img.shields.io/scrutinizer/g/dealerdirect/phpcodesniffer-composer-installer.svg [scrutinizer]: https://scrutinizer-ci.com/g/dealerdirect/phpcodesniffer-composer-installer/ [ghactionstest-shield]: https://github.com/PHPCSStandards/composer-installer/actions/workflows/integrationtest.yml/badge.svg [ghactions]: https://github.com/PHPCSStandards/composer-installer/actions/workflows/integrationtest.yml [tutorial]: https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial [using-composer-plugins]: https://getcomposer.org/doc/articles/plugins.md#using-plugins [v0.7]: https://github.com/PHPCSStandards/composer-installer/releases/tag/v0.7.0 [v1.1]: https://github.com/PHPCSStandards/composer-installer/releases/tag/v1.1.0 [v1.2]: https://github.com/PHPCSStandards/composer-installer/releases/tag/v1.2.0 { "name": "dealerdirect/phpcodesniffer-composer-installer", "description": "PHP_CodeSniffer Standards Composer Installer Plugin", "type": "composer-plugin", "keywords": [ "composer", "installer", "plugin", "phpcs", "phpcbf", "codesniffer", "phpcodesniffer", "php_codesniffer", "standard", "standards", "style guide", "stylecheck", "qa", "quality", "code quality", "tests" ], "license": "MIT", "authors": [ { "name": "Franck Nijhof", "email": "opensource@frenck.dev", "homepage": "https://frenck.dev", "role": "Open source developer" }, { "name" : "Contributors", "homepage" : "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" } ], "support": { "issues": "https://github.com/PHPCSStandards/composer-installer/issues", "source": "https://github.com/PHPCSStandards/composer-installer", "security": "https://github.com/PHPCSStandards/composer-installer/security/policy" }, "require": { "php": ">=5.4", "composer-plugin-api": "^2.2", "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { "ext-json": "*", "ext-zip": "*", "composer/composer": "^2.2", "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", "php-parallel-lint/php-parallel-lint": "^1.4.0", "yoast/phpunit-polyfills": "^1.0" }, "minimum-stability": "dev", "prefer-stable": true, "autoload": { "psr-4": { "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" } }, "autoload-dev": { "psr-4": { "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Tests\\": "tests/" } }, "config": { "lock": false }, "extra": { "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" }, "scripts": { "install-codestandards": [ "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" ], "lint": [ "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git" ], "test": [ "@php ./vendor/phpunit/phpunit/phpunit --no-coverage" ], "coverage": [ "@php ./vendor/phpunit/phpunit/phpunit" ] } } */ class Plugin implements PluginInterface, EventSubscriberInterface { const KEY_MAX_DEPTH = 'phpcodesniffer-search-depth'; const MESSAGE_ERROR_WRONG_MAX_DEPTH = 'The value of "%s" (in the composer.json "extra".section) must be an integer larger than %d, %s given.'; const MESSAGE_NOT_INSTALLED = 'PHPCodeSniffer is not installed'; const MESSAGE_NOTHING_TO_INSTALL = 'No PHPCS standards to install or update'; const MESSAGE_PLUGIN_UNINSTALLED = 'PHPCodeSniffer Composer Installer is uninstalled'; const MESSAGE_RUNNING_INSTALLER = 'Running PHPCodeSniffer Composer Installer'; const PACKAGE_NAME = 'squizlabs/php_codesniffer'; const PACKAGE_TYPE = 'phpcodesniffer-standard'; const PHPCS_CONFIG_REGEX = '`%s:[^\r\n]+`'; const PHPCS_CONFIG_KEY = 'installed_paths'; const PLUGIN_NAME = 'dealerdirect/phpcodesniffer-composer-installer'; /** * @var Composer */ private $composer; /** * @var string */ private $cwd; /** * @var Filesystem */ private $filesystem; /** * @var array */ private $installedPaths; /** * @var IOInterface */ private $io; /** * @var ProcessExecutor */ private $processExecutor; /** * Triggers the plugin's main functionality. * * Makes it possible to run the plugin as a custom command. * * @param Event $event * * @throws \InvalidArgumentException * @throws \RuntimeException * @throws LogicException * @throws ProcessFailedException * @throws RuntimeException */ public static function run(Event $event) { $io = $event->getIO(); $composer = $event->getComposer(); $instance = new static(); $instance->io = $io; $instance->composer = $composer; $instance->init(); $instance->onDependenciesChangedEvent(); } /** * {@inheritDoc} * * @throws \RuntimeException * @throws LogicException * @throws ProcessFailedException * @throws RuntimeException */ public function activate(Composer $composer, IOInterface $io) { $this->composer = $composer; $this->io = $io; $this->init(); } /** * {@inheritDoc} */ public function deactivate(Composer $composer, IOInterface $io) { } /** * {@inheritDoc} */ public function uninstall(Composer $composer, IOInterface $io) { } /** * Prepares the plugin so it's main functionality can be run. * * @throws \RuntimeException * @throws LogicException * @throws ProcessFailedException * @throws RuntimeException */ private function init() { $this->cwd = getcwd(); $this->installedPaths = array(); $this->processExecutor = new ProcessExecutor($this->io); $this->filesystem = new Filesystem($this->processExecutor); } /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array( ScriptEvents::POST_INSTALL_CMD => array( array('onDependenciesChangedEvent', 0), ), ScriptEvents::POST_UPDATE_CMD => array( array('onDependenciesChangedEvent', 0), ), ); } /** * Entry point for post install and post update events. * * @throws \InvalidArgumentException * @throws LogicException * @throws ProcessFailedException * @throws RuntimeException */ public function onDependenciesChangedEvent() { $io = $this->io; $isVerbose = $io->isVerbose(); $exitCode = 0; if ($isVerbose) { $io->write(sprintf('%s', self::MESSAGE_RUNNING_INSTALLER)); } if ($this->isPHPCodeSnifferInstalled() === true) { $this->loadInstalledPaths(); $installPathCleaned = $this->cleanInstalledPaths(); $installPathUpdated = $this->updateInstalledPaths(); if ($installPathCleaned === true || $installPathUpdated === true) { $exitCode = $this->saveInstalledPaths(); } elseif ($isVerbose) { $io->write(sprintf('%s', self::MESSAGE_NOTHING_TO_INSTALL)); } } else { $pluginPackage = $this ->composer ->getRepositoryManager() ->getLocalRepository() ->findPackages(self::PLUGIN_NAME) ; $isPluginUninstalled = count($pluginPackage) === 0; if ($isPluginUninstalled) { if ($isVerbose) { $io->write(sprintf('%s', self::MESSAGE_PLUGIN_UNINSTALLED)); } } else { $exitCode = 1; if ($isVerbose) { $io->write(sprintf('%s', self::MESSAGE_NOT_INSTALLED)); } } } return $exitCode; } /** * Load all paths from PHP_CodeSniffer into an array. * * @throws LogicException * @throws ProcessFailedException * @throws RuntimeException */ private function loadInstalledPaths() { if ($this->isPHPCodeSnifferInstalled() === true) { $this->processExecutor->execute( $this->getPhpcsCommand() . ' --config-show', $output, $this->getPHPCodeSnifferInstallPath() ); $regex = sprintf(self::PHPCS_CONFIG_REGEX, self::PHPCS_CONFIG_KEY); if (preg_match($regex, $output, $match) === 1) { $phpcsInstalledPaths = str_replace(self::PHPCS_CONFIG_KEY . ': ', '', $match[0]); $phpcsInstalledPaths = trim($phpcsInstalledPaths); if ($phpcsInstalledPaths !== '') { $this->installedPaths = explode(',', $phpcsInstalledPaths); } } } } /** * Save all coding standard paths back into PHP_CodeSniffer * * @throws LogicException * @throws ProcessFailedException * @throws RuntimeException * * @return int Exit code. 0 for success, 1 or higher for failure. */ private function saveInstalledPaths() { // Check if we found installed paths to set. if (count($this->installedPaths) !== 0) { sort($this->installedPaths); $paths = implode(',', $this->installedPaths); $arguments = array('--config-set', self::PHPCS_CONFIG_KEY, $paths); $configMessage = sprintf( 'PHP CodeSniffer Config %s set to %s', self::PHPCS_CONFIG_KEY, $paths ); } else { // Delete the installed paths if none were found. $arguments = array('--config-delete', self::PHPCS_CONFIG_KEY); $configMessage = sprintf( 'PHP CodeSniffer Config %s delete', self::PHPCS_CONFIG_KEY ); } // Prepare message in case of failure $failMessage = sprintf( 'Failed to set PHP CodeSniffer %s Config', self::PHPCS_CONFIG_KEY ); // Okay, lets rock! $command = vsprintf( '%s %s', array( 'phpcs command' => $this->getPhpcsCommand(), 'arguments' => implode(' ', $arguments), ) ); $exitCode = $this->processExecutor->execute($command, $configResult, $this->getPHPCodeSnifferInstallPath()); if ($exitCode === 0) { $exitCode = $this->verifySaveSuccess(); } if ($exitCode === 0) { $this->io->write($configMessage); } else { $this->io->write($failMessage); } if ($this->io->isVerbose() && !empty($configResult)) { $this->io->write(sprintf('%s', $configResult)); } return $exitCode; } /** * Verify that the paths which were expected to be saved, have been. * * @return int Exit code. 0 for success, 1 for failure. */ private function verifySaveSuccess() { $exitCode = 1; $expectedPaths = $this->installedPaths; // Request the currently set installed paths after the save. $this->loadInstalledPaths(); $registeredPaths = array_intersect($this->installedPaths, $expectedPaths); $registeredCount = count($registeredPaths); $expectedCount = count($expectedPaths); if ($expectedCount === $registeredCount) { $exitCode = 0; } if ($exitCode === 1 && $this->io->isVerbose()) { $verificationMessage = sprintf( "Paths to external standards found by the plugin: %s\n" . 'Actual paths registered with PHPCS: %s', implode(', ', $expectedPaths), implode(', ', $this->installedPaths) ); $this->io->write($verificationMessage); } return $exitCode; } /** * Get the command to call PHPCS. */ protected function getPhpcsCommand() { return vsprintf( '%s %s', array( 'php executable' => $this->getPhpExecCommand(), 'phpcs executable' => './bin/phpcs', ) ); } /** * Get the path to the current PHP version being used. * * Duplicate of the same in the EventDispatcher class in Composer itself. */ protected function getPhpExecCommand() { $finder = new PhpExecutableFinder(); $phpPath = $finder->find(false); if ($phpPath === false) { throw new \RuntimeException('Failed to locate PHP binary to execute ' . $phpPath); } $phpArgs = $finder->findArguments(); $phpArgs = $phpArgs ? ' ' . implode(' ', $phpArgs) : '' ; $command = ProcessExecutor::escape($phpPath) . $phpArgs . ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen')) . ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions')) . ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit')) ; return $command; } /** * Iterate trough all known paths and check if they are still valid. * * If path does not exists, is not an directory or isn't readable, the path * is removed from the list. * * @return bool True if changes where made, false otherwise */ private function cleanInstalledPaths() { $changes = false; foreach ($this->installedPaths as $key => $path) { // Resolve relative paths to absolute using the PHPCS install path as the base // to avoid potential open_basedir warnings from is_dir() on relative paths. if ($this->filesystem->isAbsolutePath($path) === false) { $path = realpath($this->getPHPCodeSnifferInstallPath() . \DIRECTORY_SEPARATOR . $path); } if ($path === false || is_dir($path) === false || is_readable($path) === false) { unset($this->installedPaths[$key]); $changes = true; } } return $changes; } /** * Check all installed packages (including the root package) against * the installed paths from PHP_CodeSniffer and add the missing ones. * * @return bool True if changes where made, false otherwise * * @throws \InvalidArgumentException * @throws \RuntimeException */ private function updateInstalledPaths() { $changes = false; $searchPaths = array(); // Add root package only if it has the expected package type. if ( $this->composer->getPackage() instanceof RootPackageInterface && $this->composer->getPackage()->getType() === self::PACKAGE_TYPE ) { $searchPaths[] = $this->cwd; } $codingStandardPackages = $this->getPHPCodingStandardPackages(); foreach ($codingStandardPackages as $package) { $installPath = $this->composer->getInstallationManager()->getInstallPath($package); if ($this->filesystem->isAbsolutePath($installPath) === false) { $installPath = $this->filesystem->normalizePath( $this->cwd . \DIRECTORY_SEPARATOR . $installPath ); } $searchPaths[] = $installPath; } // Nothing to do. if ($searchPaths === array()) { return false; } $finder = new Finder(); $finder->files() ->depth('<= ' . $this->getMaxDepth()) ->depth('>= ' . $this->getMinDepth()) ->ignoreUnreadableDirs() ->ignoreVCS(true) ->in($searchPaths) ->name('ruleset.xml'); // Process each found possible ruleset. foreach ($finder as $ruleset) { $standardsPath = $ruleset->getPath(); // Pick the directory above the directory containing the standard, unless this is the project root. if ($standardsPath !== $this->cwd) { $standardsPath = dirname($standardsPath); } // Use relative paths for local project repositories. if ($this->isRunningGlobally() === false) { $standardsPath = $this->filesystem->findShortestPath( $this->getPHPCodeSnifferInstallPath(), $standardsPath, true ); } // De-duplicate and add when directory is not configured. if (in_array($standardsPath, $this->installedPaths, true) === false) { $this->installedPaths[] = $standardsPath; $changes = true; } } return $changes; } /** * Iterates through Composers' local repository looking for valid Coding * Standard packages. * * @return array Composer packages containing coding standard(s) */ private function getPHPCodingStandardPackages() { $codingStandardPackages = array_filter( $this->composer->getRepositoryManager()->getLocalRepository()->getPackages(), function (PackageInterface $package) { if ($package instanceof AliasPackage) { return false; } return $package->getType() === Plugin::PACKAGE_TYPE; } ); return $codingStandardPackages; } /** * Searches for the installed PHP_CodeSniffer Composer package * * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against * * @return PackageInterface|null */ private function getPHPCodeSnifferPackage($versionConstraint = null) { $packages = $this ->composer ->getRepositoryManager() ->getLocalRepository() ->findPackages(self::PACKAGE_NAME, $versionConstraint); return array_shift($packages); } /** * Returns the path to the PHP_CodeSniffer package installation location * * {@internal Do NOT try to modernize via the Composer 2.2 API (`InstalledVersions::getInstallPath()`). * Doing so doesn't play nice with other plugins. * {@link https://github.com/PHPCSStandards/composer-installer/issues/239}} * * @return string */ private function getPHPCodeSnifferInstallPath() { return $this->composer->getInstallationManager()->getInstallPath($this->getPHPCodeSnifferPackage()); } /** * Simple check if PHP_CodeSniffer is installed. * * {@internal Do NOT try to modernize via the Composer 2.2 API (`InstalledVersions::isInstalled()`). * Doing so doesn't play nice with integrations calling the Composer EventDispatcher programmatically. * {@link https://github.com/PHPCSStandards/composer-installer/issues/247}} * * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against * * @return bool Whether PHP_CodeSniffer is installed */ private function isPHPCodeSnifferInstalled($versionConstraint = null) { return ($this->getPHPCodeSnifferPackage($versionConstraint) !== null); } /** * Test if composer is running "global" * This check kinda dirty, but it is the "Composer Way" * * @return bool Whether Composer is running "globally" * * @throws \RuntimeException */ private function isRunningGlobally() { return ($this->composer->getConfig()->get('home') === $this->cwd); } /** * Determines the maximum search depth when searching for Coding Standards. * * @return int * * @throws \InvalidArgumentException */ private function getMaxDepth() { $maxDepth = 3; $extra = $this->composer->getPackage()->getExtra(); if (array_key_exists(self::KEY_MAX_DEPTH, $extra)) { $maxDepth = $extra[self::KEY_MAX_DEPTH]; $minDepth = $this->getMinDepth(); if ( (string) (int) $maxDepth !== (string) $maxDepth /* Must be an integer or cleanly castable to one */ || $maxDepth <= $minDepth /* Larger than the minimum */ || is_float($maxDepth) === true /* Within the boundaries of integer */ ) { $message = vsprintf( self::MESSAGE_ERROR_WRONG_MAX_DEPTH, array( 'key' => self::KEY_MAX_DEPTH, 'min' => $minDepth, 'given' => var_export($maxDepth, true), ) ); throw new \InvalidArgumentException($message); } } return (int) $maxDepth; } /** * Returns the minimal search depth for Coding Standard packages. * * Usually this is 0, unless PHP_CodeSniffer >= 3 is used. * * @return int */ private function getMinDepth() { if ($this->isPHPCodeSnifferInstalled('>= 3.0.0') !== true) { return 1; } return 0; } } Copyright (c) 2006-2015 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 Inflector Doctrine Inflector is a small library that can perform string manipulations with regard to uppercase/lowercase and singular/plural forms of words. [![Build Status](https://github.com/doctrine/inflector/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/inflector/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A4.0.x) [![Code Coverage](https://codecov.io/gh/doctrine/inflector/branch/2.0.x/graph/badge.svg)](https://codecov.io/gh/doctrine/inflector/branch/2.0.x) { "name": "doctrine/inflector", "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", "license": "MIT", "type": "library", "keywords": [ "php", "strings", "words", "manipulation", "inflector", "inflection", "uppercase", "lowercase", "singular", "plural" ], "authors": [ { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], "homepage": "https://www.doctrine-project.org/projects/inflector.html", "require": { "php": "^7.2 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^12.0 || ^13.0", "phpstan/phpstan": "^1.12 || ^2.0", "phpstan/phpstan-phpunit": "^1.4 || ^2.0", "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", "phpunit/phpunit": "^8.5 || ^12.2" }, "autoload": { "psr-4": { "Doctrine\\Inflector\\": "src" } }, "autoload-dev": { "psr-4": { "Doctrine\\Tests\\Inflector\\": "tests" } }, "config": { "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true }, "sort-packages": true } } Introduction ============ The Doctrine Inflector has methods for inflecting text. The features include pluralization, singularization, converting between camelCase and under_score and capitalizing words. Installation ============ You can install the Inflector with composer: .. code-block:: console $ composer require doctrine/inflector Usage ===== Using the inflector is easy, you can create a new ``Doctrine\Inflector\Inflector`` instance by using the ``Doctrine\Inflector\InflectorFactory`` class: .. code-block:: php use Doctrine\Inflector\InflectorFactory; $inflector = InflectorFactory::create()->build(); By default it will create an English inflector. If you want to use another language, just pass the language you want to create an inflector for to the ``createForLanguage()`` method: .. code-block:: php use Doctrine\Inflector\InflectorFactory; use Doctrine\Inflector\Language; $inflector = InflectorFactory::createForLanguage(Language::SPANISH)->build(); The supported languages are as follows: - ``Language::ENGLISH`` - ``Language::ESPERANTO`` - ``Language::FRENCH`` - ``Language::NORWEGIAN_BOKMAL`` - ``Language::PORTUGUESE`` - ``Language::SPANISH`` - ``Language::TURKISH`` If you want to manually construct the inflector instead of using a factory, you can do so like this: .. code-block:: php use Doctrine\Inflector\CachedWordInflector; use Doctrine\Inflector\RulesetInflector; use Doctrine\Inflector\Rules\English; $inflector = new Inflector( new CachedWordInflector(new RulesetInflector( English\Rules::getSingularRuleset() )), new CachedWordInflector(new RulesetInflector( English\Rules::getPluralRuleset() )) ); Adding Languages ---------------- If you are interested in adding support for your language, take a look at the other languages defined in the ``Doctrine\Inflector\Rules`` namespace and the tests located in ``Doctrine\Tests\Inflector\Rules``. You can copy one of the languages and update the rules for your language. Once you have done this, send a pull request to the ``doctrine/inflector`` repository with the additions. Custom Setup ============ If you want to setup custom singular and plural rules, you can configure these in the factory: .. code-block:: php use Doctrine\Inflector\InflectorFactory; use Doctrine\Inflector\Rules\Pattern; use Doctrine\Inflector\Rules\Patterns; use Doctrine\Inflector\Rules\Ruleset; use Doctrine\Inflector\Rules\Substitution; use Doctrine\Inflector\Rules\Substitutions; use Doctrine\Inflector\Rules\Transformation; use Doctrine\Inflector\Rules\Transformations; use Doctrine\Inflector\Rules\Word; $inflector = InflectorFactory::create() ->withSingularRules( new Ruleset( new Transformations( new Transformation(new Pattern('/^(bil)er$/i'), '\1'), new Transformation(new Pattern('/^(inflec|contribu)tors$/i'), '\1ta') ), new Patterns(new Pattern('singulars')), new Substitutions(new Substitution(new Word('spins'), new Word('spinor'))) ) ) ->withPluralRules( new Ruleset( new Transformations( new Transformation(new Pattern('^(bil)er$'), '\1'), new Transformation(new Pattern('^(inflec|contribu)tors$'), '\1ta') ), new Patterns(new Pattern('noflect'), new Pattern('abtuse')), new Substitutions( new Substitution(new Word('amaze'), new Word('amazable')), new Substitution(new Word('phone'), new Word('phonezes')) ) ) ) ->build(); No operation inflector ---------------------- The ``Doctrine\Inflector\NoopWordInflector`` may be used to configure an inflector that doesn't perform any operation for pluralization and/or singularization. If will simply return the input as output. This is an implementation of the `Null Object design pattern `_. .. code-block:: php use Doctrine\Inflector\Inflector; use Doctrine\Inflector\NoopWordInflector; $inflector = new Inflector(new NoopWordInflector(), new NoopWordInflector()); Tableize ======== Converts ``ModelName`` to ``model_name``: .. code-block:: php echo $inflector->tableize('ModelName'); // model_name Classify ======== Converts ``model_name`` to ``ModelName``: .. code-block:: php echo $inflector->classify('model_name'); // ModelName Camelize ======== This method uses `Classify`_ and then converts the first character to lowercase: .. code-block:: php echo $inflector->camelize('model_name'); // modelName Capitalize ========== Takes a string and capitalizes all of the words, like PHP's built-in ``ucwords`` function. This extends that behavior, however, by allowing the word delimiters to be configured, rather than only separating on whitespace. Here is an example: .. code-block:: php $string = 'top-o-the-morning to all_of_you!'; echo $inflector->capitalize($string); // Top-O-The-Morning To All_of_you! echo $inflector->capitalize($string, '-_ '); // Top-O-The-Morning To All_Of_You! Pluralize ========= Returns a word in plural form. .. code-block:: php echo $inflector->pluralize('browser'); // browsers Singularize =========== Returns a word in singular form. .. code-block:: php echo $inflector->singularize('browsers'); // browser Urlize ====== Generate a URL friendly string from a string of text: .. code-block:: php echo $inflector->urlize('My first blog post'); // my-first-blog-post Unaccent ======== You can unaccent a string of text using the ``unaccent()`` method: .. code-block:: php echo $inflector->unaccent('año'); // ano Legacy API ========== The API present in Inflector 1.x is still available, but will be deprecated in a future release and dropped for 3.0. Support for languages other than English is available in the 2.0 API only. Acknowledgements ================ The language rules in this library have been adapted from several different sources, including but not limited to: - `Ruby On Rails Inflector `_ - `ICanBoogie Inflector `_ - `CakePHP Inflector `_ wordInflector = $wordInflector; } public function inflect(string $word): string { return $this->cache[$word] ?? $this->cache[$word] = $this->wordInflector->inflect($word); } } singularRulesets[] = $this->getSingularRuleset(); $this->pluralRulesets[] = $this->getPluralRuleset(); } final public function build(): Inflector { return new Inflector( new CachedWordInflector(new RulesetInflector( ...$this->singularRulesets )), new CachedWordInflector(new RulesetInflector( ...$this->pluralRulesets )) ); } final public function withSingularRules(?Ruleset $singularRules, bool $reset = false): LanguageInflectorFactory { if ($reset) { $this->singularRulesets = []; } if ($singularRules instanceof Ruleset) { array_unshift($this->singularRulesets, $singularRules); } return $this; } final public function withPluralRules(?Ruleset $pluralRules, bool $reset = false): LanguageInflectorFactory { if ($reset) { $this->pluralRulesets = []; } if ($pluralRules instanceof Ruleset) { array_unshift($this->pluralRulesets, $pluralRules); } return $this; } abstract protected function getSingularRuleset(): Ruleset; abstract protected function getPluralRuleset(): Ruleset; } 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'Ae', 'Æ' => 'Ae', 'Å' => 'Aa', 'æ' => 'a', 'Ç' => 'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'Oe', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'Ue', 'Ý' => 'Y', 'ß' => 'ss', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'ae', 'å' => 'aa', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'oe', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'ue', 'ý' => 'y', 'ÿ' => 'y', 'Ā' => 'A', 'ā' => 'a', 'Ă' => 'A', 'ă' => 'a', 'Ą' => 'A', 'ą' => 'a', 'Ć' => 'C', 'ć' => 'c', 'Ĉ' => 'C', 'ĉ' => 'c', 'Ċ' => 'C', 'ċ' => 'c', 'Č' => 'C', 'č' => 'c', 'Ď' => 'D', 'ď' => 'd', 'Đ' => 'D', 'đ' => 'd', 'Ē' => 'E', 'ē' => 'e', 'Ĕ' => 'E', 'ĕ' => 'e', 'Ė' => 'E', 'ė' => 'e', 'Ę' => 'E', 'ę' => 'e', 'Ě' => 'E', 'ě' => 'e', 'Ĝ' => 'G', 'ĝ' => 'g', 'Ğ' => 'G', 'ğ' => 'g', 'Ġ' => 'G', 'ġ' => 'g', 'Ģ' => 'G', 'ģ' => 'g', 'Ĥ' => 'H', 'ĥ' => 'h', 'Ħ' => 'H', 'ħ' => 'h', 'Ĩ' => 'I', 'ĩ' => 'i', 'Ī' => 'I', 'ī' => 'i', 'Ĭ' => 'I', 'ĭ' => 'i', 'Į' => 'I', 'į' => 'i', 'İ' => 'I', 'ı' => 'i', 'IJ' => 'IJ', 'ij' => 'ij', 'Ĵ' => 'J', 'ĵ' => 'j', 'Ķ' => 'K', 'ķ' => 'k', 'ĸ' => 'k', 'Ĺ' => 'L', 'ĺ' => 'l', 'Ļ' => 'L', 'ļ' => 'l', 'Ľ' => 'L', 'ľ' => 'l', 'Ŀ' => 'L', 'ŀ' => 'l', 'Ł' => 'L', 'ł' => 'l', 'Ń' => 'N', 'ń' => 'n', 'Ņ' => 'N', 'ņ' => 'n', 'Ň' => 'N', 'ň' => 'n', 'ʼn' => 'N', 'Ŋ' => 'n', 'ŋ' => 'N', 'Ō' => 'O', 'ō' => 'o', 'Ŏ' => 'O', 'ŏ' => 'o', 'Ő' => 'O', 'ő' => 'o', 'Œ' => 'OE', 'œ' => 'oe', 'Ø' => 'O', 'ø' => 'o', 'Ŕ' => 'R', 'ŕ' => 'r', 'Ŗ' => 'R', 'ŗ' => 'r', 'Ř' => 'R', 'ř' => 'r', 'Ś' => 'S', 'ś' => 's', 'Ŝ' => 'S', 'ŝ' => 's', 'Ş' => 'S', 'ş' => 's', 'Š' => 'S', 'š' => 's', 'Ţ' => 'T', 'ţ' => 't', 'Ť' => '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', 'ſ' => 's', '€' => 'E', '£' => '', ]; /** @var WordInflector */ private $singularizer; /** @var WordInflector */ private $pluralizer; public function __construct(WordInflector $singularizer, WordInflector $pluralizer) { $this->singularizer = $singularizer; $this->pluralizer = $pluralizer; } /** * Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'. */ public function tableize(string $word): string { $tableized = preg_replace('~(?<=\\w)([A-Z])~u', '_$1', $word); if ($tableized === null) { throw new RuntimeException(sprintf( 'preg_replace returned null for value "%s"', $word )); } return mb_strtolower($tableized); } /** * Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'. */ public function classify(string $word): string { return str_replace([' ', '_', '-'], '', ucwords($word, ' _-')); } /** * Camelizes a word. This uses the classify() method and turns the first character to lowercase. */ public function camelize(string $word): string { return lcfirst($this->classify($word)); } /** * Uppercases words with configurable delimiters between words. * * Takes a string and capitalizes all of the words, like PHP's built-in * ucwords function. This extends that behavior, however, by allowing the * word delimiters to be configured, rather than only separating on * whitespace. * * Here is an example: * * capitalize($string); * // Top-O-The-Morning To All_of_you! * * echo $inflector->capitalize($string, '-_ '); * // Top-O-The-Morning To All_Of_You! * ?> * * * @param string $string The string to operate on. * @param string $delimiters A list of word separators. * * @return string The string with all delimiter-separated words capitalized. */ public function capitalize(string $string, string $delimiters = " \n\t\r\0\x0B-"): string { return ucwords($string, $delimiters); } /** * Checks if the given string seems like it has utf8 characters in it. * * @param string $string The string to check for utf8 characters in. */ public function seemsUtf8(string $string): bool { for ($i = 0; $i < strlen($string); $i++) { if (ord($string[$i]) < 0x80) { continue; // 0bbbbbbb } if ((ord($string[$i]) & 0xE0) === 0xC0) { $n = 1; // 110bbbbb } elseif ((ord($string[$i]) & 0xF0) === 0xE0) { $n = 2; // 1110bbbb } elseif ((ord($string[$i]) & 0xF8) === 0xF0) { $n = 3; // 11110bbb } elseif ((ord($string[$i]) & 0xFC) === 0xF8) { $n = 4; // 111110bb } elseif ((ord($string[$i]) & 0xFE) === 0xFC) { $n = 5; // 1111110b } else { return false; // Does not match any model } for ($j = 0; $j < $n; $j++) { // n bytes matching 10bbbbbb follow ? if (++$i === strlen($string) || ((ord($string[$i]) & 0xC0) !== 0x80)) { return false; } } } return true; } /** * Remove any illegal characters, accents, etc. * * @param string $string String to unaccent * * @return string Unaccented string */ public function unaccent(string $string): string { if (preg_match('/[\x80-\xff]/', $string) === false) { return $string; } if ($this->seemsUtf8($string)) { $string = strtr($string, self::ACCENTED_CHARACTERS); } else { $characters = []; // Assume ISO-8859-1 if not UTF-8 $characters['in'] = chr(128) . chr(131) . chr(138) . chr(142) . chr(154) . chr(158) . chr(159) . chr(162) . chr(165) . chr(181) . chr(192) . chr(193) . chr(194) . chr(195) . chr(196) . chr(197) . chr(199) . chr(200) . chr(201) . chr(202) . chr(203) . chr(204) . chr(205) . chr(206) . chr(207) . chr(209) . chr(210) . chr(211) . chr(212) . chr(213) . chr(214) . chr(216) . chr(217) . chr(218) . chr(219) . chr(220) . chr(221) . chr(224) . chr(225) . chr(226) . chr(227) . chr(228) . chr(229) . chr(231) . chr(232) . chr(233) . chr(234) . chr(235) . chr(236) . chr(237) . chr(238) . chr(239) . chr(241) . chr(242) . chr(243) . chr(244) . chr(245) . chr(246) . chr(248) . chr(249) . chr(250) . chr(251) . chr(252) . chr(253) . chr(255); $characters['out'] = 'EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy'; $string = strtr($string, $characters['in'], $characters['out']); $doubleChars = []; $doubleChars['in'] = [ chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254), ]; $doubleChars['out'] = ['OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th']; $string = str_replace($doubleChars['in'], $doubleChars['out'], $string); } return $string; } /** * Convert any passed string to a url friendly string. * Converts 'My first blog post' to 'my-first-blog-post' * * @param string $string String to urlize. * * @return string Urlized string. */ public function urlize(string $string): string { // Remove all non url friendly characters with the unaccent function $unaccented = $this->unaccent($string); if (function_exists('mb_strtolower')) { $lowered = mb_strtolower($unaccented); } else { $lowered = strtolower($unaccented); } $replacements = [ '/\W/' => ' ', '/([A-Z]+)([A-Z][a-z])/' => '\1_\2', '/([a-z\d])([A-Z])/' => '\1_\2', '/[^A-Z^a-z^0-9^\/]+/' => '-', ]; $urlized = $lowered; foreach ($replacements as $pattern => $replacement) { $replaced = preg_replace($pattern, $replacement, $urlized); if ($replaced === null) { throw new RuntimeException(sprintf( 'preg_replace returned null for value "%s"', $urlized )); } $urlized = $replaced; } return trim($urlized, '-'); } /** * Returns a word in singular form. * * @param string $word The word in plural form. * * @return string The word in singular form. */ public function singularize(string $word): string { return $this->singularizer->inflect($word); } /** * Returns a word in plural form. * * @param string $word The word in singular form. * * @return string The word in plural form. */ public function pluralize(string $word): string { return $this->pluralizer->inflect($word); } } getFlippedSubstitutions() ); } public static function getPluralRuleset(): Ruleset { return new Ruleset( new Transformations(...Inflectible::getPlural()), new Patterns(...Uninflected::getPlural()), new Substitutions(...Inflectible::getIrregular()) ); } } getFlippedSubstitutions() ); } public static function getPluralRuleset(): Ruleset { return new Ruleset( new Transformations(...Inflectible::getPlural()), new Patterns(...Uninflected::getPlural()), new Substitutions(...Inflectible::getIrregular()) ); } } getFlippedSubstitutions() ); } public static function getPluralRuleset(): Ruleset { return new Ruleset( new Transformations(...Inflectible::getPlural()), new Patterns(...Uninflected::getPlural()), new Substitutions(...Inflectible::getIrregular()) ); } } */ public static function getSingular(): iterable { // Reverse of -sce → -scia (fasce → fascia) yield new Transformation(new Pattern('([aeiou])sce$'), '\\1scia'); // Reverse of -cie → -cia (farmacia → farmacie) yield new Transformation(new Pattern('cie$'), 'cia'); // Reverse of -gie → -gia (bugia → bugie) yield new Transformation(new Pattern('gie$'), 'gia'); // Reverse of -ce → -cia (arance → arancia) yield new Transformation(new Pattern('([^aeiou])ce$'), '\1cia'); // Reverse of -ge → -gia (valige → valigia) yield new Transformation(new Pattern('([^aeiou])ge$'), '\1gia'); // Reverse of -chi → -co (bachi → baco) yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])chi$'), '\1co'); // Reverse of -ghi → -go (laghi → lago) yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])ghi$'), '\1go'); // Reverse of -ci → -co (medici → medico) yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])ci$'), '\1co'); // Reverse of -gi → -go (psicologi → psicologo) yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])gi$'), '\1go'); // Reverse of -i → -io (zii → zio, negozi → negozio) // This is more complex due to Italian's stress patterns, but we'll handle the basic case yield new Transformation(new Pattern('([^aeiou])i$'), '\1io'); // Handle words that end with -i but should go to -co/-go (amici → amico, not amice) yield new Transformation(new Pattern('([^aeiou])ci$'), '\1co'); yield new Transformation(new Pattern('([^aeiou])gi$'), '\1go'); // Reverse of -a → -e yield new Transformation(new Pattern('e$'), 'a'); // Reverse of -e → -i yield new Transformation(new Pattern('i$'), 'e'); // Reverse of -o → -i yield new Transformation(new Pattern('i$'), 'o'); } /** @return iterable */ public static function getPlural(): iterable { // Words ending in -scia without stress on 'i' become -sce (e.g. fascia → fasce) yield new Transformation(new Pattern('([aeiou])scia$'), '\\1sce'); // Words ending in -cia/gia with stress on 'i' keep the 'i' in plural yield new Transformation(new Pattern('cia$'), 'cie'); // e.g. farmacia → farmacie yield new Transformation(new Pattern('gia$'), 'gie'); // e.g. bugia → bugie // Words ending in -cia/gia without stress on 'i' lose the 'i' in plural yield new Transformation(new Pattern('([^aeiou])cia$'), '\\1ce'); // e.g. arancia → arance yield new Transformation(new Pattern('([^aeiou])gia$'), '\\1ge'); // e.g. valigia → valige // Words ending in -co/-go with stress on 'o' become -chi/-ghi yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])co$'), '\\1chi'); // e.g. baco → bachi yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])go$'), '\\1ghi'); // e.g. lago → laghi // Words ending in -co/-go with stress on the penultimate syllable become -ci/-gi yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])co$'), '\\1ci'); // e.g. medico → medici yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])go$'), '\\1gi'); // e.g. psicologo → psicologi // Words ending in -io with stress on 'i' keep the 'i' in plural yield new Transformation(new Pattern('([^aeiou])io$'), '\\1i'); // e.g. zio → zii // Words ending in -io with stress on 'o' lose the 'i' in plural yield new Transformation(new Pattern('([aeiou])io$'), '\\1i'); // e.g. negozio → negozi // Standard ending rules yield new Transformation(new Pattern('a$'), 'e'); // -a → -e yield new Transformation(new Pattern('e$'), 'i'); // -e → -i yield new Transformation(new Pattern('o$'), 'i'); // -o → -i } /** @return iterable */ public static function getIrregular(): iterable { // Irregular substitutions (singular => plural) $irregulars = [ 'ala' => 'ali', 'albergo' => 'alberghi', 'amica' => 'amiche', 'amico' => 'amici', 'ampio' => 'ampi', 'arancia' => 'arance', 'arma' => 'armi', 'asparago' => 'asparagi', 'banca' => 'banche', 'belga' => 'belgi', 'braccio' => 'braccia', 'budello' => 'budella', 'bue' => 'buoi', 'caccia' => 'cacce', 'calcagno' => 'calcagna', 'camicia' => 'camicie', 'cane' => 'cani', 'capitale' => 'capitali', 'carcere' => 'carceri', 'casa' => 'case', 'cavaliere' => 'cavalieri', 'centinaio' => 'centinaia', 'cerchio' => 'cerchia', 'cervello' => 'cervella', 'chiave' => 'chiavi', 'chirurgo' => 'chirurgi', 'ciglio' => 'ciglia', 'città' => 'città', 'corno' => 'corna', 'corpo' => 'corpi', 'crisi' => 'crisi', 'dente' => 'denti', 'dio' => 'dei', 'dito' => 'dita', 'dottore' => 'dottori', 'fiore' => 'fiori', 'fratello' => 'fratelli', 'fuoco' => 'fuochi', 'gamba' => 'gambe', 'ginocchio' => 'ginocchia', 'gioco' => 'giochi', 'giornale' => 'giornali', 'giraffa' => 'giraffe', 'labbro' => 'labbra', 'lenzuolo' => 'lenzuola', 'libro' => 'libri', 'madre' => 'madri', 'maestro' => 'maestri', 'magico' => 'magici', 'mago' => 'maghi', 'maniaco' => 'maniaci', 'manico' => 'manici', 'mano' => 'mani', 'medico' => 'medici', 'membro' => 'membri', 'metropoli' => 'metropoli', 'migliaio' => 'migliaia', 'miglio' => 'miglia', 'mille' => 'mila', 'mio' => 'miei', 'moglie' => 'mogli', 'mosaico' => 'mosaici', 'muro' => 'muri', 'nemico' => 'nemici', 'nome' => 'nomi', 'occhio' => 'occhi', 'orecchio' => 'orecchi', 'osso' => 'ossa', 'paio' => 'paia', 'pane' => 'pani', 'papa' => 'papi', 'pasta' => 'paste', 'penna' => 'penne', 'pesce' => 'pesci', 'piede' => 'piedi', 'pittore' => 'pittori', 'poeta' => 'poeti', 'porco' => 'porci', 'porto' => 'porti', 'problema' => 'problemi', 'ragazzo' => 'ragazzi', 're' => 're', 'rene' => 'reni', 'riso' => 'risa', 'rosa' => 'rosa', 'sale' => 'sali', 'sarto' => 'sarti', 'scuola' => 'scuole', 'serie' => 'serie', 'serramento' => 'serramenta', 'sorella' => 'sorelle', 'specie' => 'specie', 'staio' => 'staia', 'stazione' => 'stazioni', 'strido' => 'strida', 'strillo' => 'strilla', 'studio' => 'studi', 'suo' => 'suoi', 'superficie' => 'superfici', 'tavolo' => 'tavoli', 'tempio' => 'templi', 'treno' => 'treni', 'tuo' => 'tuoi', 'uomo' => 'uomini', 'uovo' => 'uova', 'urlo' => 'urla', 'valigia' => 'valigie', 'vestigio' => 'vestigia', 'vino' => 'vini', 'viola' => 'viola', 'zio' => 'zii', ]; foreach ($irregulars as $singular => $plural) { yield new Substitution(new Word($singular), new Word($plural)); } } } getFlippedSubstitutions() ); } public static function getPluralRuleset(): Ruleset { return new Ruleset( new Transformations(...Inflectible::getPlural()), new Patterns(...Uninflected::getPlural()), new Substitutions(...Inflectible::getIrregular()) ); } } */ public static function getSingular(): iterable { yield from self::getDefault(); } /** @return iterable */ public static function getPlural(): iterable { yield from self::getDefault(); } /** @return iterable */ private static function getDefault(): iterable { // Invariable words (same form in singular and plural) $invariables = [ 'alpaca', 'auto', 'bar', 'blu', 'boia', 'boomerang', 'brindisi', 'campus', 'computer', 'crisi', 'crocevia', 'dopocena', 'film', 'foto', 'fuchsia', 'gnu', 'gorilla', 'gru', 'iguana', 'kamikaze', 'karaoke', 'koala', 'lama', 'menu', 'metropoli', 'moto', 'opossum', 'panda', 'quiz', 'radio', 're', 'scacciapensieri', 'serie', 'smartphone', 'sosia', 'sottoscala', 'specie', 'sport', 'tablet', 'taxi', 'vaglia', 'virtù', 'virus', 'yogurt', 'foto', 'fuchsia', ]; foreach ($invariables as $word) { yield new Pattern($word); } } } getFlippedSubstitutions() ); } public static function getPluralRuleset(): Ruleset { return new Ruleset( new Transformations(...Inflectible::getPlural()), new Patterns(...Uninflected::getPlural()), new Substitutions(...Inflectible::getIrregular()) ); } } pattern = $pattern; if (isset($this->pattern[0]) && $this->pattern[0] === '/') { $this->regex = $this->pattern; } else { $this->regex = '/' . $this->pattern . '/i'; } } public function getPattern(): string { return $this->pattern; } public function getRegex(): string { return $this->regex; } public function matches(string $word): bool { return preg_match($this->getRegex(), $word) === 1; } } getPattern(); }, $patterns); $this->regex = '/^(?:' . implode('|', $patterns) . ')$/i'; } public function matches(string $word): bool { return preg_match($this->regex, $word, $regs) === 1; } } getFlippedSubstitutions() ); } public static function getPluralRuleset(): Ruleset { return new Ruleset( new Transformations(...Inflectible::getPlural()), new Patterns(...Uninflected::getPlural()), new Substitutions(...Inflectible::getIrregular()) ); } } regular = $regular; $this->uninflected = $uninflected; $this->irregular = $irregular; } public function getRegular(): Transformations { return $this->regular; } public function getUninflected(): Patterns { return $this->uninflected; } public function getIrregular(): Substitutions { return $this->irregular; } } getFlippedSubstitutions() ); } public static function getPluralRuleset(): Ruleset { return new Ruleset( new Transformations(...Inflectible::getPlural()), new Patterns(...Uninflected::getPlural()), new Substitutions(...Inflectible::getIrregular()) ); } } from = $from; $this->to = $to; } public function getFrom(): Word { return $this->from; } public function getTo(): Word { return $this->to; } } substitutions[$substitution->getFrom()->getWord()] = $substitution; } } public function getFlippedSubstitutions(): Substitutions { $substitutions = []; foreach ($this->substitutions as $substitution) { $substitutions[] = new Substitution( $substitution->getTo(), $substitution->getFrom() ); } return new Substitutions(...$substitutions); } public function inflect(string $word): string { $lowerWord = strtolower($word); if (isset($this->substitutions[$lowerWord])) { $firstLetterUppercase = $lowerWord[0] !== $word[0]; $toWord = $this->substitutions[$lowerWord]->getTo()->getWord(); if ($firstLetterUppercase) { return strtoupper($toWord[0]) . substr($toWord, 1); } return $toWord; } return $word; } } pattern = $pattern; $this->replacement = $replacement; } public function getPattern(): Pattern { return $this->pattern; } public function getReplacement(): string { return $this->replacement; } public function inflect(string $word): string { return (string) preg_replace($this->pattern->getRegex(), $this->replacement, $word); } } transformations = $transformations; } public function inflect(string $word): string { foreach ($this->transformations as $transformation) { if ($transformation->getPattern()->matches($word)) { return $transformation->inflect($word); } } return $word; } } getFlippedSubstitutions() ); } public static function getPluralRuleset(): Ruleset { return new Ruleset( new Transformations(...Inflectible::getPlural()), new Patterns(...Uninflected::getPlural()), new Substitutions(...Inflectible::getIrregular()) ); } } word = $word; } public function getWord(): string { return $this->word; } } rulesets = array_merge([$ruleset], $rulesets); } public function inflect(string $word): string { if ($word === '') { return ''; } foreach ($this->rulesets as $ruleset) { if ($ruleset->getUninflected()->matches($word)) { return $word; } $inflected = $ruleset->getIrregular()->inflect($word); if ($inflected !== $word) { return $inflected; } $inflected = $ruleset->getRegular()->inflect($word); if ($inflected !== $word) { return $inflected; } } return $word; } } true`) on cap-configured stream handlers - Distinguish CurlMultiHandler and StreamHandler outcomes in connection-cap custom-handler guidance - Reject raw cURL options that conflict with explicit multiplexing guarantees - Stop explicit multiplexing conflict checks faulting on non-array cURL multi `options` values - Reject required multiplexing when the final `CURLOPT_HTTPAUTH` mask permits NTLM - Require an integer `CURLMOPT_PIPELINING` when combined with explicit multiplexing - Check the required multiplexing cleartext proxy rule against the final cURL configuration - Bound cURL multi handler blocking selects by the earliest pending request delay - Stop synchronous cURL multi handler waits blocking on other transfers once the target has settled - Stop cURL multi completion processing double-settling promises canceled from completion callbacks - Run ready promise queue tasks before sleeping for delayed cURL multi requests - Avoid integer overflow in cURL multi delay timing on 32-bit platforms - Roll back failed cURL multi handle attachment instead of leaving requests pending - Release the cURL easy handle when the `on_stats` callback throws - Normalize response trailer field names to lowercase with values in wire order - Retain response trailers only when an `on_trailers` callback is configured - Validate the `on_trailers` callback before starting a cURL transfer - Reject the `on_trailers` request option on the stream handler, which cannot observe trailers - Match cookies, proxy schemes, auth types, and header names with locale-independent ASCII folding - Reject proxy option values that Guzzle cannot classify identically to ext-curl ## 7.14.0 - 2026-07-08 ### Added - Added the `on_trailers` request option to expose parsed HTTP response trailers - Added the `multiplex` request option with `Multiplexing::*` modes to control or require HTTP/2 multiplexing - Added rejection of explicit `multiplex` requests when `CURLMOPT_PIPELINING` disables multiplexing - Added the `max_host_connections` and `max_total_connections` client and cURL multi handler options ### Changed - Redirects that discard the request body no longer require it to be rewindable - Synchronous cURL multi handler requests no longer wait for other queued transfers - Section SOCKS proxy connections by credentials on libcurl before 7.69.0 - Reject request-level `CURLOPT_SHARE` when combined with authenticated SOCKS proxy configuration - Redact proxy userinfo containing raw control bytes in cURL errors - Check linked curl/libcurl NTLM support before applying NTLM auth - Clarify that NTLM is deprecated by both Guzzle and curl/libcurl - Remove deprecation for the raw cURL `CURLOPT_CERTINFO` option - Warn when a cURL multi option cannot be applied ### Deprecated - Deprecate the raw `CURLOPT_PIPEWAIT` cURL option in favour of the `multiplex` request option - Deprecate unknown handler constructor options - Deprecate invalid `select_timeout` cURL multi handler option values - Deprecate raw cURL multi connection cap options in favour of the named options ## 7.13.3 - 2026-07-08 ### Changed - Adjusted `guzzlehttp/promises` version constraint to `^2.5.1` - Adjusted `guzzlehttp/psr7` version constraint to `^2.12.4` - Pass explicit trim characters ahead of the PHP 8.6 trim default change ### Fixed - Stop matching cookie domains against hosts with a trailing newline - Reject HTTP status codes and certificate type extensions with a trailing newline - Treat PCRE engine failures as invalid cookie names during cookie validation - Report PCRE engine failures when formatting log messages - Report PCRE engine failures when splitting `no_proxy` values ## 7.13.2 - 2026-07-05 ### Fixed - Stop the cURL multi handler busy-waiting on request delays shorter than one second - Stop cURL HEAD requests with request bodies hanging on responses that declare a content length - The cURL handler no longer transmits request bodies on HEAD requests - Preserve response headers when a response includes HTTP trailers - Harden cURL response header block detection when HTTP trailers are received - Corrected the PSR-7 class names in the Pool iterator exception - Redirect body rewind failures no longer leak a bare `RuntimeException` ## 7.13.1 - 2026-06-29 ### Fixed - Allow middleware to rewrite partial URIs before transports validate them ## 7.13.0 - 2026-06-29 ### Added - Added the `crypto_method_max` request option to cap the maximum TLS protocol version - Added HTTP QUERY redirect support, preserving method and body on 301 and 302 ### Changed - Section proxy tunnel connection reuse by credential so distinct credentials never share a tunnel - Isolate concurrent foreign cURL proxy tunnels added while another owner's tunnel is active - Route credentialed HTTP(S) proxy Proxy-Authorization headers through cURL proxy header handling - Reject request-level `CURLOPT_SHARE` when combined with authenticated HTTP/HTTPS proxy tunnel configuration - Remove deprecation for raw cURL `CURLOPT_PREREQFUNCTION` callbacks when defined by PHP cURL - Route TLS 1.2 `crypto_method` requests to the stream handler when cURL cannot select TLS 1.2 - Reject final request URIs missing a scheme or host before transfer ### Deprecated - Deprecate invalid protocols, force_ip_resolve, delay, cookies, and allow_redirects values ## 7.12.3 - 2026-06-23 ### Changed - Adjusted `guzzlehttp/psr7` version constraint to `^2.12.3` ### Security - Treat IP and numeric cookie domains as exact-match-only (GHSA-g446-98w2-8p5w) ## 7.12.2 - 2026-06-23 ### Fixed - Clamp out-of-range `Max-Age` so a very large value no longer overflows to an already-expired timestamp - Use strict comparison in `CookieJar` conflict resolution so distinct numeric-string names don't overwrite - Store a cookie whose `Domain` has a trailing dot on the origin host instead of silently discarding it - Fix `StreamHandler` hard-failing on bracketed IPv6 literal hosts when `force_ip_resolve` is set - Use strict cookie `Path` comparison so `CookieJar::clear()` with a numeric path keeps a distinct-path cookie - Fixed cookie handling for falsey `Domain`, `Max-Age`, path, and name values - Fixed `decode_content` handling for falsey string values - Fixed deprecated request option values reaching built-in handlers before normalization ## 7.12.1 - 2026-06-18 ### Changed - Adjusted `guzzlehttp/psr7` version constraint to `^2.12.1` ### Fixed - Reject proxy URLs with a malformed scheme in the cURL handlers instead of letting libcurl mishandle them ### Security - Reject HTTPS proxies when the installed libcurl lacks HTTPS-proxy support (GHSA-wpwq-4j6v-78m3) - Reject dot-only cookie `Domain` attributes as match-all (GHSA-cwxw-98qj-8qjx) ## 7.12.0 - 2026-06-16 ### Added - Added `RequestOptions` constants for `curl`, `retries`, and `stream_context` ### Changed - Adjusted `guzzlehttp/psr7` version constraint to `^2.12` - Constrain cURL transport sharing to safe libcurl DNS and SSL session support - Resolve proxy environment variables in the cURL handlers; libcurl no longer reads the environment itself - Ignore proxy environment variables when the `proxy` request option makes a decision - Disable proxy environment variables on Windows SAPIs other than CLI (httpoxy hardening) - Redact proxy credentials from cURL handler error messages, following `Psr7\Utils::redactUserInfo()` - Normalize no-proxy domain and IP literal matching across the cURL and stream handlers ### Deprecated - Deprecated the request-level `handler` option, which will be ignored in 8.0 - Deprecated raw cURL request options outside the built-in cURL handlers' allow-list - Deprecated the `CURLOPT_PROXYTYPE` cURL request option; set the proxy type via a scheme-prefixed proxy URL - Deprecated PHP stream context options outside the built-in stream handler allow-list - Deprecated passing `ntlm` as a built-in `auth` type - Deprecated `Utils::describeType()` - Deprecated non-finite floats in the `query` and `form_params` options; 8.0 rejects them - Deprecated non-string scalar values in the `body` option; 8.0 rejects them ### Fixed - Fix cURL TLS and HTTP/2 capability detection using libcurl feature checks - Fix proxy `no` list matches being re-proxied through environment-configured proxies by libcurl - Fix `no` list and `NO_PROXY` matching to support IP CIDR ranges, matching libcurl - Fix the stream handler not applying scheme-less proxies and their credentials ## 7.11.2 - 2026-06-12 ### Fixed - Fixed non-finite float values emitting coercion warnings on PHP 8.5 ## 7.11.1 - 2026-06-07 ### Fixed - Ignore request-level `transport_sharing`, matching other unknown request options ## 7.11.0 - 2026-06-02 ### Added - Added support for providing the `proxy` request option's `no` value as a comma-delimited string - Added the `protocols` request option to restrict allowed URI schemes for request transfers - Added `cert_type` and `ssl_key_type` request options for TLS certificate and private-key file types - Added PHP stream handler support for the `ssl_key` request option - Added transport sharing via the `transport_sharing` client and cURL handler options ### Changed - Adjusted `guzzlehttp/promises` version constraint to `^2.5` - Adjusted `guzzlehttp/psr7` version constraint to `^2.11` - Allowed domainless `SetCookie` instances to be stored without wildcard request matching - Changed no-proxy matching to respect request ports for host-and-port rules - Prevented `CurlMultiHandler` destructors from throwing during cleanup - Improved invalid response handling across handlers ### Deprecated - Deprecated non-iterable `Pool` request collections, which will be rejected in 8.0 - Deprecated non-uppercase easy request methods; 8.0 preserves method casing - Deprecated non-string `headers` request option values, which will be rejected in 8.0 - Deprecated empty `headers` request option value arrays, which will be rejected in 8.0 - Deprecated empty and malformed request protocol versions, which will be rejected in 8.0 - Deprecated conflicting raw cURL request options, including `CURLOPT_SHARE`, which will be rejected in 8.0 - Deprecated scalar-coerced `idn_conversion` request option values, which will be rejected in 8.0 - Deprecated invalid documented request option value types, which will be rejected in 8.0 - Deprecated selected request options ignored by incompatible built-in handlers, which will be rejected in 8.0 - Deprecated `RequestException::wrapException()`, which will be removed in 8.0 - Deprecated `RetryMiddleware::exponentialDelay()`, which will be removed in 8.0 ## 7.10.6 - 2026-06-01 ### Fixed - `CurlMultiHandler` now rejects the promise when `CurlFactory::finish()` throws, preserving sibling transfers - `SetCookie` now normalizes unparseable `Expires` values to `null` instead of `false` - Fix stream handler decoded `gzip`/`deflate` truncation by dropping invalid `Content-Length` ## 7.10.5 - 2026-05-27 ### Fixed - Defer cURL multi cancellation cleanup until after progress callbacks return - Classify additional stream handler connection failures as `ConnectException` ## 7.10.4 - 2026-05-22 ### Fixed - Fix IPv6 literal matching in no-proxy rules - Handle cURL multi completion messages without handles after cancelled transfers - Fix magic client request methods such as `options()` to uppercase inferred HTTP methods ## 7.10.3 - 2026-05-20 ### Fixed - Fail clearly when an HTTP response header line is invalid - Remove middleware by name when the name is also a callable string - Treat empty request protocol versions as HTTP/1.1 ## 7.10.2 - 2026-05-20 ### Fixed - Normalize HTTP version request options before applying them to PSR-7 requests - Use string values for headers generated by request preparation and response decoding ## 7.10.1 - 2026-05-19 ### Fixed - Fail clearly when cURL options cannot be applied - Fail clearly when the certificate option is malformed - Fail clearly when JSON decode depth is invalid - Fail clearly when session cookie data is malformed - Fail clearly when the stream progress option is not callable - Prevent response creation failures from exposing stale cURL responses ## 7.10.0 - 2025-08-23 ### Added - Support for PHP 8.5 ### Changed - Adjusted `guzzlehttp/promises` version constraint to `^2.3` - Adjusted `guzzlehttp/psr7` version constraint to `^2.8` ## 7.9.3 - 2025-03-27 ### Changed - Remove explicit content-length header for GET requests - Improve compatibility with bad servers for boolean cookie values ## 7.9.2 - 2024-07-24 ### Fixed - Adjusted handler selection to use cURL if its version is 7.21.2 or higher, rather than 7.34.0 ## 7.9.1 - 2024-07-19 ### Fixed - Fix TLS 1.3 check for HTTP/2 requests ## 7.9.0 - 2024-07-18 ### Changed - Improve protocol version checks to provide feedback around unsupported protocols - Only select the cURL handler by default if 7.34.0 or higher is linked - Improved `CurlMultiHandler` to avoid busy wait if possible - Dropped support for EOL `guzzlehttp/psr7` v1 - Improved URI user info redaction in errors ## 7.8.2 - 2024-07-18 ### Added - Support for PHP 8.4 ## 7.8.1 - 2023-12-03 ### Changed - Updated links in docs to their canonical versions - Replaced `call_user_func*` with native calls ## 7.8.0 - 2023-08-27 ### Added - Support for PHP 8.3 - Added automatic closing of handles on `CurlFactory` object destruction ## 7.7.1 - 2023-08-27 ### Changed - Remove the need for `AllowDynamicProperties` in `CurlMultiHandler` ## 7.7.0 - 2023-05-21 ### Added - Support `guzzlehttp/promises` v2 ## 7.6.1 - 2023-05-15 ### Fixed - Fix `SetCookie::fromString` MaxAge deprecation warning and skip invalid MaxAge values ## 7.6.0 - 2023-05-14 ### Added - Support for setting the minimum TLS version in a unified way - Apply on request the version set in options parameters ## 7.5.2 - 2023-05-14 ### Fixed - Fixed set cookie constructor validation - Fixed handling of files with `'0'` body ### Changed - Corrected docs and default connect timeout value to 300 seconds ## 7.5.1 - 2023-04-17 ### Fixed - Fixed `NO_PROXY` settings so that setting the `proxy` option to `no` overrides the env variable ### Changed - Adjusted `guzzlehttp/psr7` version constraint to `^1.9.1 || ^2.4.5` ## 7.5.0 - 2022-08-28 ### Added - Support PHP 8.2 - Add request to delay closure params ## 7.4.5 - 2022-06-20 ### Fixed * Fix change in port should be considered a change in origin * Fix `CURLOPT_HTTPAUTH` option not cleared on change of origin ## 7.4.4 - 2022-06-09 ### Fixed * Fix failure to strip Authorization header on HTTP downgrade * Fix failure to strip the Cookie header on change in host or HTTP downgrade ## 7.4.3 - 2022-05-25 ### Fixed * Fix cross-domain cookie leakage ## 7.4.2 - 2022-03-20 ### Fixed - Remove curl auth on cross-domain redirects to align with the Authorization HTTP header - Reject non-HTTP schemes in StreamHandler - Set a default ssl.peer_name context in StreamHandler to allow `force_ip_resolve` ## 7.4.1 - 2021-12-06 ### Changed - Replaced implicit URI to string coercion [#2946](https://github.com/guzzle/guzzle/pull/2946) - Allow `symfony/deprecation-contracts` version 3 [#2961](https://github.com/guzzle/guzzle/pull/2961) ### Fixed - Only close curl handle if it's done [#2950](https://github.com/guzzle/guzzle/pull/2950) ## 7.4.0 - 2021-10-18 ### Added - Support PHP 8.1 [#2929](https://github.com/guzzle/guzzle/pull/2929), [#2939](https://github.com/guzzle/guzzle/pull/2939) - Support `psr/log` version 2 and 3 [#2943](https://github.com/guzzle/guzzle/pull/2943) ### Fixed - Make sure we always call `restore_error_handler()` [#2915](https://github.com/guzzle/guzzle/pull/2915) - Fix progress parameter type compatibility between the cURL and stream handlers [#2936](https://github.com/guzzle/guzzle/pull/2936) - Throw `InvalidArgumentException` when an incorrect `headers` array is provided [#2916](https://github.com/guzzle/guzzle/pull/2916), [#2942](https://github.com/guzzle/guzzle/pull/2942) ### Changed - Be more strict with types [#2914](https://github.com/guzzle/guzzle/pull/2914), [#2917](https://github.com/guzzle/guzzle/pull/2917), [#2919](https://github.com/guzzle/guzzle/pull/2919), [#2945](https://github.com/guzzle/guzzle/pull/2945) ## 7.3.0 - 2021-03-23 ### Added - Support for DER and P12 certificates [#2413](https://github.com/guzzle/guzzle/pull/2413) - Support the cURL (http://) scheme for StreamHandler proxies [#2850](https://github.com/guzzle/guzzle/pull/2850) - Support for `guzzlehttp/psr7:^2.0` [#2878](https://github.com/guzzle/guzzle/pull/2878) ### Fixed - Handle exceptions on invalid header consistently between PHP versions and handlers [#2872](https://github.com/guzzle/guzzle/pull/2872) ## 7.2.0 - 2020-10-10 ### Added - Support for PHP 8 [#2712](https://github.com/guzzle/guzzle/pull/2712), [#2715](https://github.com/guzzle/guzzle/pull/2715), [#2789](https://github.com/guzzle/guzzle/pull/2789) - Support passing a body summarizer to the http errors middleware [#2795](https://github.com/guzzle/guzzle/pull/2795) ### Fixed - Handle exceptions during response creation [#2591](https://github.com/guzzle/guzzle/pull/2591) - Fix CURLOPT_ENCODING not to be overwritten [#2595](https://github.com/guzzle/guzzle/pull/2595) - Make sure the Request always has a body object [#2804](https://github.com/guzzle/guzzle/pull/2804) ### Changed - The `TooManyRedirectsException` has a response [#2660](https://github.com/guzzle/guzzle/pull/2660) - Avoid "functions" from dependencies [#2712](https://github.com/guzzle/guzzle/pull/2712) ### Deprecated - Using environment variable GUZZLE_CURL_SELECT_TIMEOUT [#2786](https://github.com/guzzle/guzzle/pull/2786) ## 7.1.1 - 2020-09-30 ### Fixed - Incorrect EOF detection for response body streams on Windows. ### Changed - We dont connect curl `sink` on HEAD requests. - Removed some PHP 5 workarounds ## 7.1.0 - 2020-09-22 ### Added - `GuzzleHttp\MessageFormatterInterface` ### Fixed - Fixed issue that caused cookies with no value not to be stored. - On redirects, we allow all safe methods like GET, HEAD and OPTIONS. - Fixed logging on empty responses. - Make sure MessageFormatter::format returns string ### Deprecated - All functions in `GuzzleHttp` has been deprecated. Use static methods on `Utils` instead. - `ClientInterface::getConfig()` - `Client::getConfig()` - `Client::__call()` - `Utils::defaultCaBundle()` - `CurlFactory::LOW_CURL_VERSION_NUMBER` ## 7.0.1 - 2020-06-27 * Fix multiply defined functions fatal error [#2699](https://github.com/guzzle/guzzle/pull/2699) ## 7.0.0 - 2020-06-27 No changes since 7.0.0-rc1. ## 7.0.0-rc1 - 2020-06-15 ### Changed * Use error level for logging errors in Middleware [#2629](https://github.com/guzzle/guzzle/pull/2629) * Disabled IDN support by default and require ext-intl to use it [#2675](https://github.com/guzzle/guzzle/pull/2675) ## 7.0.0-beta2 - 2020-05-25 ### Added * Using `Utils` class instead of functions in the `GuzzleHttp` namespace. [#2546](https://github.com/guzzle/guzzle/pull/2546) * `ClientInterface::MAJOR_VERSION` [#2583](https://github.com/guzzle/guzzle/pull/2583) ### Changed * Avoid the `getenv` function when unsafe [#2531](https://github.com/guzzle/guzzle/pull/2531) * Added real client methods [#2529](https://github.com/guzzle/guzzle/pull/2529) * Avoid functions due to global install conflicts [#2546](https://github.com/guzzle/guzzle/pull/2546) * Use Symfony intl-idn polyfill [#2550](https://github.com/guzzle/guzzle/pull/2550) * Adding methods for HTTP verbs like `Client::get()`, `Client::head()`, `Client::patch()` etc [#2529](https://github.com/guzzle/guzzle/pull/2529) * `ConnectException` extends `TransferException` [#2541](https://github.com/guzzle/guzzle/pull/2541) * Updated the default User Agent to "GuzzleHttp/7" [#2654](https://github.com/guzzle/guzzle/pull/2654) ### Fixed * Various intl icu issues [#2626](https://github.com/guzzle/guzzle/pull/2626) ### Removed * Pool option `pool_size` [#2528](https://github.com/guzzle/guzzle/pull/2528) ## 7.0.0-beta1 - 2019-12-30 The diff might look very big but 95% of Guzzle users will be able to upgrade without modification. Please see [the upgrade document](UPGRADING.md) that describes all BC breaking changes. ### Added * Implement PSR-18 and dropped PHP 5 support [#2421](https://github.com/guzzle/guzzle/pull/2421) [#2474](https://github.com/guzzle/guzzle/pull/2474) * PHP 7 types [#2442](https://github.com/guzzle/guzzle/pull/2442) [#2449](https://github.com/guzzle/guzzle/pull/2449) [#2466](https://github.com/guzzle/guzzle/pull/2466) [#2497](https://github.com/guzzle/guzzle/pull/2497) [#2499](https://github.com/guzzle/guzzle/pull/2499) * IDN support for redirects [2424](https://github.com/guzzle/guzzle/pull/2424) ### Changed * Dont allow passing null as third argument to `BadResponseException::__construct()` [#2427](https://github.com/guzzle/guzzle/pull/2427) * Use SAPI constant instead of method call [#2450](https://github.com/guzzle/guzzle/pull/2450) * Use native function invocation [#2444](https://github.com/guzzle/guzzle/pull/2444) * Better defaults for PHP installations with old ICU lib [2454](https://github.com/guzzle/guzzle/pull/2454) * Added visibility to all constants [#2462](https://github.com/guzzle/guzzle/pull/2462) * Dont allow passing `null` as URI to `Client::request()` and `Client::requestAsync()` [#2461](https://github.com/guzzle/guzzle/pull/2461) * Widen the exception argument to throwable [#2495](https://github.com/guzzle/guzzle/pull/2495) ### Fixed * Logging when Promise rejected with a string [#2311](https://github.com/guzzle/guzzle/pull/2311) ### Removed * Class `SeekException` [#2162](https://github.com/guzzle/guzzle/pull/2162) * `RequestException::getResponseBodySummary()` [#2425](https://github.com/guzzle/guzzle/pull/2425) * `CookieJar::getCookieValue()` [#2433](https://github.com/guzzle/guzzle/pull/2433) * `uri_template()` and `UriTemplate` [#2440](https://github.com/guzzle/guzzle/pull/2440) * Request options `save_to` and `exceptions` [#2464](https://github.com/guzzle/guzzle/pull/2464) ## 6.5.2 - 2019-12-23 * idn_to_ascii() fix for old PHP versions [#2489](https://github.com/guzzle/guzzle/pull/2489) ## 6.5.1 - 2019-12-21 * Better defaults for PHP installations with old ICU lib [#2454](https://github.com/guzzle/guzzle/pull/2454) * IDN support for redirects [#2424](https://github.com/guzzle/guzzle/pull/2424) ## 6.5.0 - 2019-12-07 * Improvement: Added support for reset internal queue in MockHandler. [#2143](https://github.com/guzzle/guzzle/pull/2143) * Improvement: Added support to pass arbitrary options to `curl_multi_init`. [#2287](https://github.com/guzzle/guzzle/pull/2287) * Fix: Gracefully handle passing `null` to the `header` option. [#2132](https://github.com/guzzle/guzzle/pull/2132) * Fix: `RetryMiddleware` did not do exponential delay between retires due unit mismatch. [#2132](https://github.com/guzzle/guzzle/pull/2132) * Fix: Prevent undefined offset when using array for ssl_key options. [#2348](https://github.com/guzzle/guzzle/pull/2348) * Deprecated `ClientInterface::VERSION` ## 6.4.1 - 2019-10-23 * No `guzzle.phar` was created in 6.4.0 due expired API token. This release will fix that * Added `parent::__construct()` to `FileCookieJar` and `SessionCookieJar` ## 6.4.0 - 2019-10-23 * Improvement: Improved error messages when using curl < 7.21.2 [#2108](https://github.com/guzzle/guzzle/pull/2108) * Fix: Test if response is readable before returning a summary in `RequestException::getResponseBodySummary()` [#2081](https://github.com/guzzle/guzzle/pull/2081) * Fix: Add support for GUZZLE_CURL_SELECT_TIMEOUT environment variable [#2161](https://github.com/guzzle/guzzle/pull/2161) * Improvement: Added `GuzzleHttp\Exception\InvalidArgumentException` [#2163](https://github.com/guzzle/guzzle/pull/2163) * Improvement: Added `GuzzleHttp\_current_time()` to use `hrtime()` if that function exists. [#2242](https://github.com/guzzle/guzzle/pull/2242) * Improvement: Added curl's `appconnect_time` in `TransferStats` [#2284](https://github.com/guzzle/guzzle/pull/2284) * Improvement: Make GuzzleException extend Throwable wherever it's available [#2273](https://github.com/guzzle/guzzle/pull/2273) * Fix: Prevent concurrent writes to file when saving `CookieJar` [#2335](https://github.com/guzzle/guzzle/pull/2335) * Improvement: Update `MockHandler` so we can test transfer time [#2362](https://github.com/guzzle/guzzle/pull/2362) ## 6.3.3 - 2018-04-22 * Fix: Default headers when decode_content is specified ## 6.3.2 - 2018-03-26 * Fix: Release process ## 6.3.1 - 2018-03-26 * Bug fix: Parsing 0 epoch expiry times in cookies [#2014](https://github.com/guzzle/guzzle/pull/2014) * Improvement: Better ConnectException detection [#2012](https://github.com/guzzle/guzzle/pull/2012) * Bug fix: Malformed domain that contains a "/" [#1999](https://github.com/guzzle/guzzle/pull/1999) * Bug fix: Undefined offset when a cookie has no first key-value pair [#1998](https://github.com/guzzle/guzzle/pull/1998) * Improvement: Support PHPUnit 6 [#1953](https://github.com/guzzle/guzzle/pull/1953) * Bug fix: Support empty headers [#1915](https://github.com/guzzle/guzzle/pull/1915) * Bug fix: Ignore case during header modifications [#1916](https://github.com/guzzle/guzzle/pull/1916) + Minor code cleanups, documentation fixes and clarifications. ## 6.3.0 - 2017-06-22 * Feature: force IP resolution (ipv4 or ipv6) [#1608](https://github.com/guzzle/guzzle/pull/1608), [#1659](https://github.com/guzzle/guzzle/pull/1659) * Improvement: Don't include summary in exception message when body is empty [#1621](https://github.com/guzzle/guzzle/pull/1621) * Improvement: Handle `on_headers` option in MockHandler [#1580](https://github.com/guzzle/guzzle/pull/1580) * Improvement: Added SUSE Linux CA path [#1609](https://github.com/guzzle/guzzle/issues/1609) * Improvement: Use class reference for getting the name of the class instead of using hardcoded strings [#1641](https://github.com/guzzle/guzzle/pull/1641) * Feature: Added `read_timeout` option [#1611](https://github.com/guzzle/guzzle/pull/1611) * Bug fix: PHP 7.x fixes [#1685](https://github.com/guzzle/guzzle/pull/1685), [#1686](https://github.com/guzzle/guzzle/pull/1686), [#1811](https://github.com/guzzle/guzzle/pull/1811) * Deprecation: BadResponseException instantiation without a response [#1642](https://github.com/guzzle/guzzle/pull/1642) * Feature: Added NTLM auth [#1569](https://github.com/guzzle/guzzle/pull/1569) * Feature: Track redirect HTTP status codes [#1711](https://github.com/guzzle/guzzle/pull/1711) * Improvement: Check handler type during construction [#1745](https://github.com/guzzle/guzzle/pull/1745) * Improvement: Always include the Content-Length if there's a body [#1721](https://github.com/guzzle/guzzle/pull/1721) * Feature: Added convenience method to access a cookie by name [#1318](https://github.com/guzzle/guzzle/pull/1318) * Bug fix: Fill `CURLOPT_CAPATH` and `CURLOPT_CAINFO` properly [#1684](https://github.com/guzzle/guzzle/pull/1684) * Improvement: Use `\GuzzleHttp\Promise\rejection_for` function instead of object init [#1827](https://github.com/guzzle/guzzle/pull/1827) + Minor code cleanups, documentation fixes and clarifications. ## 6.2.3 - 2017-02-28 * Fix deprecations with guzzle/psr7 version 1.4 ## 6.2.2 - 2016-10-08 * Allow to pass nullable Response to delay callable * Only add scheme when host is present * Fix drain case where content-length is the literal string zero * Obfuscate in-URL credentials in exceptions ## 6.2.1 - 2016-07-18 * Address HTTP_PROXY security vulnerability, CVE-2016-5385: https://httpoxy.org/ * Fixing timeout bug with StreamHandler: https://github.com/guzzle/guzzle/pull/1488 * Only read up to `Content-Length` in PHP StreamHandler to avoid timeouts when a server does not honor `Connection: close`. * Ignore URI fragment when sending requests. ## 6.2.0 - 2016-03-21 * Feature: added `GuzzleHttp\json_encode` and `GuzzleHttp\json_decode`. https://github.com/guzzle/guzzle/pull/1389 * Bug fix: Fix sleep calculation when waiting for delayed requests. https://github.com/guzzle/guzzle/pull/1324 * Feature: More flexible history containers. https://github.com/guzzle/guzzle/pull/1373 * Bug fix: defer sink stream opening in StreamHandler. https://github.com/guzzle/guzzle/pull/1377 * Bug fix: do not attempt to escape cookie values. https://github.com/guzzle/guzzle/pull/1406 * Feature: report original content encoding and length on decoded responses. https://github.com/guzzle/guzzle/pull/1409 * Bug fix: rewind seekable request bodies before dispatching to cURL. https://github.com/guzzle/guzzle/pull/1422 * Bug fix: provide an empty string to `http_build_query` for HHVM workaround. https://github.com/guzzle/guzzle/pull/1367 ## 6.1.1 - 2015-11-22 * Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler https://github.com/guzzle/guzzle/commit/911bcbc8b434adce64e223a6d1d14e9a8f63e4e4 * Feature: HandlerStack is now more generic. https://github.com/guzzle/guzzle/commit/f2102941331cda544745eedd97fc8fd46e1ee33e * Bug fix: setting verify to false in the StreamHandler now disables peer verification. https://github.com/guzzle/guzzle/issues/1256 * Feature: Middleware now uses an exception factory, including more error context. https://github.com/guzzle/guzzle/pull/1282 * Feature: better support for disabled functions. https://github.com/guzzle/guzzle/pull/1287 * Bug fix: fixed regression where MockHandler was not using `sink`. https://github.com/guzzle/guzzle/pull/1292 ## 6.1.0 - 2015-09-08 * Feature: Added the `on_stats` request option to provide access to transfer statistics for requests. https://github.com/guzzle/guzzle/pull/1202 * Feature: Added the ability to persist session cookies in CookieJars. https://github.com/guzzle/guzzle/pull/1195 * Feature: Some compatibility updates for Google APP Engine https://github.com/guzzle/guzzle/pull/1216 * Feature: Added support for NO_PROXY to prevent the use of a proxy based on a simple set of rules. https://github.com/guzzle/guzzle/pull/1197 * Feature: Cookies can now contain square brackets. https://github.com/guzzle/guzzle/pull/1237 * Bug fix: Now correctly parsing `=` inside of quotes in Cookies. https://github.com/guzzle/guzzle/pull/1232 * Bug fix: Cusotm cURL options now correctly override curl options of the same name. https://github.com/guzzle/guzzle/pull/1221 * Bug fix: Content-Type header is now added when using an explicitly provided multipart body. https://github.com/guzzle/guzzle/pull/1218 * Bug fix: Now ignoring Set-Cookie headers that have no name. * Bug fix: Reason phrase is no longer cast to an int in some cases in the cURL handler. https://github.com/guzzle/guzzle/pull/1187 * Bug fix: Remove the Authorization header when redirecting if the Host header changes. https://github.com/guzzle/guzzle/pull/1207 * Bug fix: Cookie path matching fixes https://github.com/guzzle/guzzle/issues/1129 * Bug fix: Fixing the cURL `body_as_string` setting https://github.com/guzzle/guzzle/pull/1201 * Bug fix: quotes are no longer stripped when parsing cookies. https://github.com/guzzle/guzzle/issues/1172 * Bug fix: `form_params` and `query` now always uses the `&` separator. https://github.com/guzzle/guzzle/pull/1163 * Bug fix: Adding a Content-Length to PHP stream wrapper requests if not set. https://github.com/guzzle/guzzle/pull/1189 ## 6.0.2 - 2015-07-04 * Fixed a memory leak in the curl handlers in which references to callbacks were not being removed by `curl_reset`. * Cookies are now extracted properly before redirects. * Cookies now allow more character ranges. * Decoded Content-Encoding responses are now modified to correctly reflect their state if the encoding was automatically removed by a handler. This means that the `Content-Encoding` header may be removed an the `Content-Length` modified to reflect the message size after removing the encoding. * Added a more explicit error message when trying to use `form_params` and `multipart` in the same request. * Several fixes for HHVM support. * Functions are now conditionally required using an additional level of indirection to help with global Composer installations. ## 6.0.1 - 2015-05-27 * Fixed a bug with serializing the `query` request option where the `&` separator was missing. * Added a better error message for when `body` is provided as an array. Please use `form_params` or `multipart` instead. * Various doc fixes. ## 6.0.0 - 2015-05-26 * See the UPGRADING.md document for more information. * Added `multipart` and `form_params` request options. * Added `synchronous` request option. * Added the `on_headers` request option. * Fixed `expect` handling. * No longer adding default middlewares in the client ctor. These need to be present on the provided handler in order to work. * Requests are no longer initiated when sending async requests with the CurlMultiHandler. This prevents unexpected recursion from requests completing while ticking the cURL loop. * Removed the semantics of setting `default` to `true`. This is no longer required now that the cURL loop is not ticked for async requests. * Added request and response logging middleware. * No longer allowing self signed certificates when using the StreamHandler. * Ensuring that `sink` is valid if saving to a file. * Request exceptions now include a "handler context" which provides handler specific contextual information. * Added `GuzzleHttp\RequestOptions` to allow request options to be applied using constants. * `$maxHandles` has been removed from CurlMultiHandler. * `MultipartPostBody` is now part of the `guzzlehttp/psr7` package. ## 5.3.0 - 2015-05-19 * Mock now supports `save_to` * Marked `AbstractRequestEvent::getTransaction()` as public. * Fixed a bug in which multiple headers using different casing would overwrite previous headers in the associative array. * Added `Utils::getDefaultHandler()` * Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated. * URL scheme is now always lowercased. ## 6.0.0-beta.1 * Requires PHP >= 5.5 * Updated to use PSR-7 * Requires immutable messages, which basically means an event based system owned by a request instance is no longer possible. * Utilizing the [Guzzle PSR-7 package](https://github.com/guzzle/psr7). * Removed the dependency on `guzzlehttp/streams`. These stream abstractions are available in the `guzzlehttp/psr7` package under the `GuzzleHttp\Psr7` namespace. * Added middleware and handler system * Replaced the Guzzle event and subscriber system with a middleware system. * No longer depends on RingPHP, but rather places the HTTP handlers directly in Guzzle, operating on PSR-7 messages. * Retry logic is now encapsulated in `GuzzleHttp\Middleware::retry`, which means the `guzzlehttp/retry-subscriber` is now obsolete. * Mocking responses is now handled using `GuzzleHttp\Handler\MockHandler`. * Asynchronous responses * No longer supports the `future` request option to send an async request. Instead, use one of the `*Async` methods of a client (e.g., `requestAsync`, `getAsync`, etc.). * Utilizing `GuzzleHttp\Promise` instead of React's promise library to avoid recursion required by chaining and forwarding react promises. See https://github.com/guzzle/promises * Added `requestAsync` and `sendAsync` to send request asynchronously. * Added magic methods for `getAsync()`, `postAsync()`, etc. to send requests asynchronously. * Request options * POST and form updates * Added the `form_fields` and `form_files` request options. * Removed the `GuzzleHttp\Post` namespace. * The `body` request option no longer accepts an array for POST requests. * The `exceptions` request option has been deprecated in favor of the `http_errors` request options. * The `save_to` request option has been deprecated in favor of `sink` request option. * Clients no longer accept an array of URI template string and variables for URI variables. You will need to expand URI templates before passing them into a client constructor or request method. * Client methods `get()`, `post()`, `put()`, `patch()`, `options()`, etc. are now magic methods that will send synchronous requests. * Replaced `Utils.php` with plain functions in `functions.php`. * Removed `GuzzleHttp\Collection`. * Removed `GuzzleHttp\BatchResults`. Batched pool results are now returned as an array. * Removed `GuzzleHttp\Query`. Query string handling is now handled using an associative array passed into the `query` request option. The query string is serialized using PHP's `http_build_query`. If you need more control, you can pass the query string in as a string. * `GuzzleHttp\QueryParser` has been replaced with the `GuzzleHttp\Psr7\parse_query`. ## 5.2.0 - 2015-01-27 * Added `AppliesHeadersInterface` to make applying headers to a request based on the body more generic and not specific to `PostBodyInterface`. * Reduced the number of stack frames needed to send requests. * Nested futures are now resolved in the client rather than the RequestFsm * Finishing state transitions is now handled in the RequestFsm rather than the RingBridge. * Added a guard in the Pool class to not use recursion for request retries. ## 5.1.0 - 2014-12-19 * Pool class no longer uses recursion when a request is intercepted. * The size of a Pool can now be dynamically adjusted using a callback. See https://github.com/guzzle/guzzle/pull/943. * Setting a request option to `null` when creating a request with a client will ensure that the option is not set. This allows you to overwrite default request options on a per-request basis. See https://github.com/guzzle/guzzle/pull/937. * Added the ability to limit which protocols are allowed for redirects by specifying a `protocols` array in the `allow_redirects` request option. * Nested futures due to retries are now resolved when waiting for synchronous responses. See https://github.com/guzzle/guzzle/pull/947. * `"0"` is now an allowed URI path. See https://github.com/guzzle/guzzle/pull/935. * `Query` no longer typehints on the `$query` argument in the constructor, allowing for strings and arrays. * Exceptions thrown in the `end` event are now correctly wrapped with Guzzle specific exceptions if necessary. ## 5.0.3 - 2014-11-03 This change updates query strings so that they are treated as un-encoded values by default where the value represents an un-encoded value to send over the wire. A Query object then encodes the value before sending over the wire. This means that even value query string values (e.g., ":") are url encoded. This makes the Query class match PHP's http_build_query function. However, if you want to send requests over the wire using valid query string characters that do not need to be encoded, then you can provide a string to Url::setQuery() and pass true as the second argument to specify that the query string is a raw string that should not be parsed or encoded (unless a call to getQuery() is subsequently made, forcing the query-string to be converted into a Query object). ## 5.0.2 - 2014-10-30 * Added a trailing `\r\n` to multipart/form-data payloads. See https://github.com/guzzle/guzzle/pull/871 * Added a `GuzzleHttp\Pool::send()` convenience method to match the docs. * Status codes are now returned as integers. See https://github.com/guzzle/guzzle/issues/881 * No longer overwriting an existing `application/x-www-form-urlencoded` header when sending POST requests, allowing for customized headers. See https://github.com/guzzle/guzzle/issues/877 * Improved path URL serialization. * No longer double percent-encoding characters in the path or query string if they are already encoded. * Now properly encoding the supplied path to a URL object, instead of only encoding ' ' and '?'. * Note: This has been changed in 5.0.3 to now encode query string values by default unless the `rawString` argument is provided when setting the query string on a URL: Now allowing many more characters to be present in the query string without being percent encoded. See https://datatracker.ietf.org/doc/html/rfc3986#appendix-A ## 5.0.1 - 2014-10-16 Bugfix release. * Fixed an issue where connection errors still returned response object in error and end events event though the response is unusable. This has been corrected so that a response is not returned in the `getResponse` method of these events if the response did not complete. https://github.com/guzzle/guzzle/issues/867 * Fixed an issue where transfer statistics were not being populated in the RingBridge. https://github.com/guzzle/guzzle/issues/866 ## 5.0.0 - 2014-10-12 Adding support for non-blocking responses and some minor API cleanup. ### New Features * Added support for non-blocking responses based on `guzzlehttp/guzzle-ring`. * Added a public API for creating a default HTTP adapter. * Updated the redirect plugin to be non-blocking so that redirects are sent concurrently. Other plugins like this can now be updated to be non-blocking. * Added a "progress" event so that you can get upload and download progress events. * Added `GuzzleHttp\Pool` which implements FutureInterface and transfers requests concurrently using a capped pool size as efficiently as possible. * Added `hasListeners()` to EmitterInterface. * Removed `GuzzleHttp\ClientInterface::sendAll` and marked `GuzzleHttp\Client::sendAll` as deprecated (it's still there, just not the recommended way). ### Breaking changes The breaking changes in this release are relatively minor. The biggest thing to look out for is that request and response objects no longer implement fluent interfaces. * Removed the fluent interfaces (i.e., `return $this`) from requests, responses, `GuzzleHttp\Collection`, `GuzzleHttp\Url`, `GuzzleHttp\Query`, `GuzzleHttp\Post\PostBody`, and `GuzzleHttp\Cookie\SetCookie`. This blog post provides a good outline of why I did this: https://ocramius.github.io/blog/fluent-interfaces-are-evil/. This also makes the Guzzle message interfaces compatible with the current PSR-7 message proposal. * Removed "functions.php", so that Guzzle is truly PSR-4 compliant. Except for the HTTP request functions from function.php, these functions are now implemented in `GuzzleHttp\Utils` using camelCase. `GuzzleHttp\json_decode` moved to `GuzzleHttp\Utils::jsonDecode`. `GuzzleHttp\get_path` moved to `GuzzleHttp\Utils::getPath`. `GuzzleHttp\set_path` moved to `GuzzleHttp\Utils::setPath`. `GuzzleHttp\batch` should now be `GuzzleHttp\Pool::batch`, which returns an `objectStorage`. Using functions.php caused problems for many users: they aren't PSR-4 compliant, require an explicit include, and needed an if-guard to ensure that the functions are not declared multiple times. * Rewrote adapter layer. * Removing all classes from `GuzzleHttp\Adapter`, these are now implemented as callables that are stored in `GuzzleHttp\Ring\Client`. * Removed the concept of "parallel adapters". Sending requests serially or concurrently is now handled using a single adapter. * Moved `GuzzleHttp\Adapter\Transaction` to `GuzzleHttp\Transaction`. The Transaction object now exposes the request, response, and client as public properties. The getters and setters have been removed. * Removed the "headers" event. This event was only useful for changing the body a response once the headers of the response were known. You can implement a similar behavior in a number of ways. One example might be to use a FnStream that has access to the transaction being sent. For example, when the first byte is written, you could check if the response headers match your expectations, and if so, change the actual stream body that is being written to. * Removed the `asArray` parameter from `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header value as an array, then use the newly added `getHeaderAsArray()` method of `MessageInterface`. This change makes the Guzzle interfaces compatible with the PSR-7 interfaces. * `GuzzleHttp\Message\MessageFactory` no longer allows subclasses to add custom request options using double-dispatch (this was an implementation detail). Instead, you should now provide an associative array to the constructor which is a mapping of the request option name mapping to a function that applies the option value to a request. * Removed the concept of "throwImmediately" from exceptions and error events. This control mechanism was used to stop a transfer of concurrent requests from completing. This can now be handled by throwing the exception or by cancelling a pool of requests or each outstanding future request individually. * Updated to "GuzzleHttp\Streams" 3.0. * `GuzzleHttp\Stream\StreamInterface::getContents()` no longer accepts a `maxLen` parameter. This update makes the Guzzle streams project compatible with the current PSR-7 proposal. * `GuzzleHttp\Stream\Stream::__construct`, `GuzzleHttp\Stream\Stream::factory`, and `GuzzleHttp\Stream\Utils::create` no longer accept a size in the second argument. They now accept an associative array of options, including the "size" key and "metadata" key which can be used to provide custom metadata. ## 4.2.2 - 2014-09-08 * Fixed a memory leak in the CurlAdapter when reusing cURL handles. * No longer using `request_fulluri` in stream adapter proxies. * Relative redirects are now based on the last response, not the first response. ## 4.2.1 - 2014-08-19 * Ensuring that the StreamAdapter does not always add a Content-Type header * Adding automated github releases with a phar and zip ## 4.2.0 - 2014-08-17 * Now merging in default options using a case-insensitive comparison. Closes https://github.com/guzzle/guzzle/issues/767 * Added the ability to automatically decode `Content-Encoding` response bodies using the `decode_content` request option. This is set to `true` by default to decode the response body if it comes over the wire with a `Content-Encoding`. Set this value to `false` to disable decoding the response content, and pass a string to provide a request `Accept-Encoding` header and turn on automatic response decoding. This feature now allows you to pass an `Accept-Encoding` header in the headers of a request but still disable automatic response decoding. Closes https://github.com/guzzle/guzzle/issues/764 * Added the ability to throw an exception immediately when transferring requests in parallel. Closes https://github.com/guzzle/guzzle/issues/760 * Updating guzzlehttp/streams dependency to ~2.1 * No longer utilizing the now deprecated namespaced methods from the stream package. ## 4.1.8 - 2014-08-14 * Fixed an issue in the CurlFactory that caused setting the `stream=false` request option to throw an exception. See: https://github.com/guzzle/guzzle/issues/769 * TransactionIterator now calls rewind on the inner iterator. See: https://github.com/guzzle/guzzle/pull/765 * You can now set the `Content-Type` header to `multipart/form-data` when creating POST requests to force multipart bodies. See https://github.com/guzzle/guzzle/issues/768 ## 4.1.7 - 2014-08-07 * Fixed an error in the HistoryPlugin that caused the same request and response to be logged multiple times when an HTTP protocol error occurs. * Ensuring that cURL does not add a default Content-Type when no Content-Type has been supplied by the user. This prevents the adapter layer from modifying the request that is sent over the wire after any listeners may have already put the request in a desired state (e.g., signed the request). * Throwing an exception when you attempt to send requests that have the "stream" set to true in parallel using the MultiAdapter. * Only calling curl_multi_select when there are active cURL handles. This was previously changed and caused performance problems on some systems due to PHP always selecting until the maximum select timeout. * Fixed a bug where multipart/form-data POST fields were not correctly aggregated (e.g., values with "&"). ## 4.1.6 - 2014-08-03 * Added helper methods to make it easier to represent messages as strings, including getting the start line and getting headers as a string. ## 4.1.5 - 2014-08-02 * Automatically retrying cURL "Connection died, retrying a fresh connect" errors when possible. * cURL implementation cleanup * Allowing multiple event subscriber listeners to be registered per event by passing an array of arrays of listener configuration. ## 4.1.4 - 2014-07-22 * Fixed a bug that caused multi-part POST requests with more than one field to serialize incorrectly. * Paths can now be set to "0" * `ResponseInterface::xml` now accepts a `libxml_options` option and added a missing default argument that was required when parsing XML response bodies. * A `save_to` stream is now created lazily, which means that files are not created on disk unless a request succeeds. ## 4.1.3 - 2014-07-15 * Various fixes to multipart/form-data POST uploads * Wrapping function.php in an if-statement to ensure Guzzle can be used globally and in a Composer install * Fixed an issue with generating and merging in events to an event array * POST headers are only applied before sending a request to allow you to change the query aggregator used before uploading * Added much more robust query string parsing * Fixed various parsing and normalization issues with URLs * Fixing an issue where multi-valued headers were not being utilized correctly in the StreamAdapter ## 4.1.2 - 2014-06-18 * Added support for sending payloads with GET requests ## 4.1.1 - 2014-06-08 * Fixed an issue related to using custom message factory options in subclasses * Fixed an issue with nested form fields in a multi-part POST * Fixed an issue with using the `json` request option for POST requests * Added `ToArrayInterface` to `GuzzleHttp\Cookie\CookieJar` ## 4.1.0 - 2014-05-27 * Added a `json` request option to easily serialize JSON payloads. * Added a `GuzzleHttp\json_decode()` wrapper to safely parse JSON. * Added `setPort()` and `getPort()` to `GuzzleHttp\Message\RequestInterface`. * Added the ability to provide an emitter to a client in the client constructor. * Added the ability to persist a cookie session using $_SESSION. * Added a trait that can be used to add event listeners to an iterator. * Removed request method constants from RequestInterface. * Fixed warning when invalid request start-lines are received. * Updated MessageFactory to work with custom request option methods. * Updated cacert bundle to latest build. 4.0.2 (2014-04-16) ------------------ * Proxy requests using the StreamAdapter now properly use request_fulluri (#632) * Added the ability to set scalars as POST fields (#628) ## 4.0.1 - 2014-04-04 * The HTTP status code of a response is now set as the exception code of RequestException objects. * 303 redirects will now correctly switch from POST to GET requests. * The default parallel adapter of a client now correctly uses the MultiAdapter. * HasDataTrait now initializes the internal data array as an empty array so that the toArray() method always returns an array. ## 4.0.0 - 2014-03-29 * For information on changes and upgrading, see: https://github.com/guzzle/guzzle/blob/4.x/UPGRADING.md#3x-to-40 * Added `GuzzleHttp\batch()` as a convenience function for sending requests in parallel without needing to write asynchronous code. * Restructured how events are added to `GuzzleHttp\ClientInterface::sendAll()`. You can now pass a callable or an array of associative arrays where each associative array contains the "fn", "priority", and "once" keys. ## 4.0.0.rc-2 - 2014-03-25 * Removed `getConfig()` and `setConfig()` from clients to avoid confusion around whether things like base_url, message_factory, etc. should be able to be retrieved or modified. * Added `getDefaultOption()` and `setDefaultOption()` to ClientInterface * functions.php functions were renamed using snake_case to match PHP idioms * Added support for `HTTP_PROXY`, `HTTPS_PROXY`, and `GUZZLE_CURL_SELECT_TIMEOUT` environment variables * Added the ability to specify custom `sendAll()` event priorities * Added the ability to specify custom stream context options to the stream adapter. * Added a functions.php function for `get_path()` and `set_path()` * CurlAdapter and MultiAdapter now use a callable to generate curl resources * MockAdapter now properly reads a body and emits a `headers` event * Updated Url class to check if a scheme and host are set before adding ":" and "//". This allows empty Url (e.g., "") to be serialized as "". * Parsing invalid XML no longer emits warnings * Curl classes now properly throw AdapterExceptions * Various performance optimizations * Streams are created with the faster `Stream\create()` function * Marked deprecation_proxy() as internal * Test server is now a collection of static methods on a class ## 4.0.0-rc.1 - 2014-03-15 * See https://github.com/guzzle/guzzle/blob/4.x/UPGRADING.md#3x-to-40 ## 3.8.1 - 2014-01-28 * Bug: Always using GET requests when redirecting from a 303 response * Bug: CURLOPT_SSL_VERIFYHOST is now correctly set to false when setting `$certificateAuthority` to false in `Guzzle\Http\ClientInterface::setSslVerification()` * Bug: RedirectPlugin now uses strict RFC 3986 compliance when combining a base URL with a relative URL * Bug: The body of a request can now be set to `"0"` * Sending PHP stream requests no longer forces `HTTP/1.0` * Adding more information to ExceptionCollection exceptions so that users have more context, including a stack trace of each sub-exception * Updated the `$ref` attribute in service descriptions to merge over any existing parameters of a schema (rather than clobbering everything). * Merging URLs will now use the query string object from the relative URL (thus allowing custom query aggregators) * Query strings are now parsed in a way that they do no convert empty keys with no value to have a dangling `=`. For example `foo&bar=baz` is now correctly parsed and recognized as `foo&bar=baz` rather than `foo=&bar=baz`. * Now properly escaping the regular expression delimiter when matching Cookie domains. * Network access is now disabled when loading XML documents ## 3.8.0 - 2013-12-05 * Added the ability to define a POST name for a file * JSON response parsing now properly walks additionalProperties * cURL error code 18 is now retried automatically in the BackoffPlugin * Fixed a cURL error when URLs contain fragments * Fixed an issue in the BackoffPlugin retry event where it was trying to access all exceptions as if they were CurlExceptions * CURLOPT_PROGRESS function fix for PHP 5.5 (69fcc1e) * Added the ability for Guzzle to work with older versions of cURL that do not support `CURLOPT_TIMEOUT_MS` * Fixed a bug that was encountered when parsing empty header parameters * UriTemplate now has a `setRegex()` method to match the docs * The `debug` request parameter now checks if it is truthy rather than if it exists * Setting the `debug` request parameter to true shows verbose cURL output instead of using the LogPlugin * Added the ability to combine URLs using strict RFC 3986 compliance * Command objects can now return the validation errors encountered by the command * Various fixes to cache revalidation (#437 and 29797e5) * Various fixes to the AsyncPlugin * Cleaned up build scripts ## 3.7.4 - 2013-10-02 * Bug fix: 0 is now an allowed value in a description parameter that has a default value (#430) * Bug fix: SchemaFormatter now returns an integer when formatting to a Unix timestamp (see https://github.com/aws/aws-sdk-php/issues/147) * Bug fix: Cleaned up and fixed URL dot segment removal to properly resolve internal dots * Minimum PHP version is now properly specified as 5.3.3 (up from 5.3.2) (#420) * Updated the bundled cacert.pem (#419) * OauthPlugin now supports adding authentication to headers or query string (#425) ## 3.7.3 - 2013-09-08 * Added the ability to get the exception associated with a request/command when using `MultiTransferException` and `CommandTransferException`. * Setting `additionalParameters` of a response to false is now honored when parsing responses with a service description * Schemas are only injected into response models when explicitly configured. * No longer guessing Content-Type based on the path of a request. Content-Type is now only guessed based on the path of an EntityBody. * Bug fix: ChunkedIterator can now properly chunk a \Traversable as well as an \Iterator. * Bug fix: FilterIterator now relies on `\Iterator` instead of `\Traversable`. * Bug fix: Gracefully handling malformed responses in RequestMediator::writeResponseBody() * Bug fix: Replaced call to canCache with canCacheRequest in the CallbackCanCacheStrategy of the CachePlugin * Bug fix: Visiting XML attributes first before visiting XML children when serializing requests * Bug fix: Properly parsing headers that contain commas contained in quotes * Bug fix: mimetype guessing based on a filename is now case-insensitive ## 3.7.2 - 2013-08-02 * Bug fix: Properly URL encoding paths when using the PHP-only version of the UriTemplate expander See https://github.com/guzzle/guzzle/issues/371 * Bug fix: Cookie domains are now matched correctly according to RFC 6265 See https://github.com/guzzle/guzzle/issues/377 * Bug fix: GET parameters are now used when calculating an OAuth signature * Bug fix: Fixed an issue with cache revalidation where the If-None-Match header was being double quoted * `Guzzle\Common\AbstractHasDispatcher::dispatch()` now returns the event that was dispatched * `Guzzle\Http\QueryString::factory()` now guesses the most appropriate query aggregator to used based on the input. See https://github.com/guzzle/guzzle/issues/379 * Added a way to add custom domain objects to service description parsing using the `operation.parse_class` event. See https://github.com/guzzle/guzzle/pull/380 * cURL multi cleanup and optimizations ## 3.7.1 - 2013-07-05 * Bug fix: Setting default options on a client now works * Bug fix: Setting options on HEAD requests now works. See #352 * Bug fix: Moving stream factory before send event to before building the stream. See #353 * Bug fix: Cookies no longer match on IP addresses per RFC 6265 * Bug fix: Correctly parsing header parameters that are in `<>` and quotes * Added `cert` and `ssl_key` as request options * `Host` header can now diverge from the host part of a URL if the header is set manually * `Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor` was rewritten to change from using SimpleXML to XMLWriter * OAuth parameters are only added via the plugin if they aren't already set * Exceptions are now thrown when a URL cannot be parsed * Returning `false` if `Guzzle\Http\EntityBody::getContentMd5()` fails * Not setting a `Content-MD5` on a command if calculating the Content-MD5 fails via the CommandContentMd5Plugin ## 3.7.0 - 2013-06-10 * See UPGRADING.md for more information on how to upgrade. * Requests now support the ability to specify an array of $options when creating a request to more easily modify a request. You can pass a 'request.options' configuration setting to a client to apply default request options to every request created by a client (e.g. default query string variables, headers, curl options, etc.). * Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\Guzzle`. See `Guzzle\Http\StaticClient::mount`. * Added `command.request_options` to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests created by a command (e.g. custom headers, query string variables, timeout settings, etc.). * Stream size in `Guzzle\Stream\PhpStreamRequestFactory` will now be set if Content-Length is returned in the headers of a response * Added `Guzzle\Common\Collection::setPath($path, $value)` to set a value into an array using a nested key (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`) * ServiceBuilders now support storing and retrieving arbitrary data * CachePlugin can now purge all resources for a given URI * CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource * CachePlugin now uses the Vary header to determine if a resource is a cache hit * `Guzzle\Http\Message\Response` now implements `\Serializable` * Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters * `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable * Fixed a bug in `Guzzle\Http\Message\Header\Link::addLink()` * Better handling of calculating the size of a stream in `Guzzle\Stream\Stream` using fstat() and caching the size * `Guzzle\Common\Exception\ExceptionCollection` now creates a more readable exception message * Fixing BC break: Added back the MonologLogAdapter implementation rather than extending from PsrLog so that older Symfony users can still use the old version of Monolog. * Fixing BC break: Added the implementation back in for `Guzzle\Http\Message\AbstractMessage::getTokenizedHeader()`. Now triggering an E_USER_DEPRECATED warning when used. Use `$message->getHeader()->parseParams()`. * Several performance improvements to `Guzzle\Common\Collection` * Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`: createRequest, head, delete, put, patch, post, options, prepareRequest * Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()` * Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface` * Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a resource, string, or EntityBody into the $options parameter to specify the download location of the response. * Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a default `array()` * Added `Guzzle\Stream\StreamInterface::isRepeatable` * Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or $client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))`. * Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`. * Removed `Guzzle\Http\ClientInterface::expandTemplate()` * Removed `Guzzle\Http\ClientInterface::setRequestFactory()` * Removed `Guzzle\Http\ClientInterface::getCurlMulti()` * Removed `Guzzle\Http\Message\RequestInterface::canCache` * Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect` * Removed `Guzzle\Http\Message\RequestInterface::isRedirect` * Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods. * You can now enable E_USER_DEPRECATED warnings to see if you are using a deprecated method by setting `Guzzle\Common\Version::$emitWarnings` to true. * Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use `$request->getResponseBody()->isRepeatable()` instead. * Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. * Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. * Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead. * Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead. * Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated * Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0 * Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use [request.options][params]. * Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client. * Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use $client->getConfig()->getPath('request.options/headers')`. * Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. * Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8. * Marked `Guzzle\Common\Collection::inject()` as deprecated. * Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest');` * CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a CacheStorageInterface. These two objects and interface will be removed in a future version. * Always setting X-cache headers on cached responses * Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin * `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface $request, Response $response);` * `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);` * `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);` * Added `CacheStorageInterface::purge($url)` * `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache, CanCacheStrategyInterface $canCache = null)` * Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)` ## 3.6.0 - 2013-05-29 * ServiceDescription now implements ToArrayInterface * Added command.hidden_params to blacklist certain headers from being treated as additionalParameters * Guzzle can now correctly parse incomplete URLs * Mixed casing of headers are now forced to be a single consistent casing across all values for that header. * Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution * Removed the whole changedHeader() function system of messages because all header changes now go through addHeader(). * Specific header implementations can be created for complex headers. When a message creates a header, it uses a HeaderFactory which can map specific headers to specific header classes. There is now a Link header and CacheControl header implementation. * Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate * Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti() * Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in Guzzle\Http\Curl\RequestMediator * Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string. * Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface * Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders() * Removed Guzzle\Parser\ParserRegister::get(). Use getParser() * Removed Guzzle\Parser\ParserRegister::set(). Use registerParser(). * All response header helper functions return a string rather than mixing Header objects and strings inconsistently * Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle directly via interfaces * Removed the injecting of a request object onto a response object. The methods to get and set a request still exist but are a no-op until removed. * Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a `Guzzle\Service\Command\ArrayCommandInterface`. * Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response on a request while the request is still being transferred * The ability to case-insensitively search for header values * Guzzle\Http\Message\Header::hasExactHeader * Guzzle\Http\Message\Header::raw. Use getAll() * Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object instead. * `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess * Added the ability to cast Model objects to a string to view debug information. ## 3.5.0 - 2013-05-13 * Bug: Fixed a regression so that request responses are parsed only once per oncomplete event rather than multiple times * Bug: Better cleanup of one-time events across the board (when an event is meant to fire once, it will now remove itself from the EventDispatcher) * Bug: `Guzzle\Log\MessageFormatter` now properly writes "total_time" and "connect_time" values * Bug: Cloning an EntityEnclosingRequest now clones the EntityBody too * Bug: Fixed an undefined index error when parsing nested JSON responses with a sentAs parameter that reference a non-existent key * Bug: All __call() method arguments are now required (helps with mocking frameworks) * Deprecating Response::getRequest() and now using a shallow clone of a request object to remove a circular reference to help with refcount based garbage collection of resources created by sending a request * Deprecating ZF1 cache and log adapters. These will be removed in the next major version. * Deprecating `Response::getPreviousResponse()` (method signature still exists, but it's deprecated). Use the HistoryPlugin for a history. * Added a `responseBody` alias for the `response_body` location * Refactored internals to no longer rely on Response::getRequest() * HistoryPlugin can now be cast to a string * HistoryPlugin now logs transactions rather than requests and responses to more accurately keep track of the requests and responses that are sent over the wire * Added `getEffectiveUrl()` and `getRedirectCount()` to Response objects ## 3.4.3 - 2013-04-30 * Bug fix: Fixing bug introduced in 3.4.2 where redirect responses are duplicated on the final redirected response * Added a check to re-extract the temp cacert bundle from the phar before sending each request ## 3.4.2 - 2013-04-29 * Bug fix: Stream objects now work correctly with "a" and "a+" modes * Bug fix: Removing `Transfer-Encoding: chunked` header when a Content-Length is present * Bug fix: AsyncPlugin no longer forces HEAD requests * Bug fix: DateTime timezones are now properly handled when using the service description schema formatter * Bug fix: CachePlugin now properly handles stale-if-error directives when a request to the origin server fails * Setting a response on a request will write to the custom request body from the response body if one is specified * LogPlugin now writes to php://output when STDERR is undefined * Added the ability to set multiple POST files for the same key in a single call * application/x-www-form-urlencoded POSTs now use the utf-8 charset by default * Added the ability to queue CurlExceptions to the MockPlugin * Cleaned up how manual responses are queued on requests (removed "queued_response" and now using request.before_send) * Configuration loading now allows remote files ## 3.4.1 - 2013-04-16 * Large refactoring to how CurlMulti handles work. There is now a proxy that sits in front of a pool of CurlMulti handles. This greatly simplifies the implementation, fixes a couple bugs, and provides a small performance boost. * Exceptions are now properly grouped when sending requests in parallel * Redirects are now properly aggregated when a multi transaction fails * Redirects now set the response on the original object even in the event of a failure * Bug fix: Model names are now properly set even when using $refs * Added support for PHP 5.5's CurlFile to prevent warnings with the deprecated @ syntax * Added support for oauth_callback in OAuth signatures * Added support for oauth_verifier in OAuth signatures * Added support to attempt to retrieve a command first literally, then ucfirst, the with inflection ## 3.4.0 - 2013-04-11 * Bug fix: URLs are now resolved correctly based on https://datatracker.ietf.org/doc/html/rfc3986#section-5.2. #289 * Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289 * Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263 * Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264. * Bug fix: Added `number` type to service descriptions. * Bug fix: empty parameters are removed from an OAuth signature * Bug fix: Revalidating a cache entry prefers the Last-Modified over the Date header * Bug fix: Fixed "array to string" error when validating a union of types in a service description * Bug fix: Removed code that attempted to determine the size of a stream when data is written to the stream * Bug fix: Not including an `oauth_token` if the value is null in the OauthPlugin. * Bug fix: Now correctly aggregating successful requests and failed requests in CurlMulti when a redirect occurs. * The new default CURLOPT_TIMEOUT setting has been increased to 150 seconds so that Guzzle works on poor connections. * Added a feature to EntityEnclosingRequest::setBody() that will automatically set the Content-Type of the request if the Content-Type can be determined based on the entity body or the path of the request. * Added the ability to overwrite configuration settings in a client when grabbing a throwaway client from a builder. * Added support for a PSR-3 LogAdapter. * Added a `command.after_prepare` event * Added `oauth_callback` parameter to the OauthPlugin * Added the ability to create a custom stream class when using a stream factory * Added a CachingEntityBody decorator * Added support for `additionalParameters` in service descriptions to define how custom parameters are serialized. * The bundled SSL certificate is now provided in the phar file and extracted when running Guzzle from a phar. * You can now send any EntityEnclosingRequest with POST fields or POST files and cURL will handle creating bodies * POST requests using a custom entity body are now treated exactly like PUT requests but with a custom cURL method. This means that the redirect behavior of POST requests with custom bodies will not be the same as POST requests that use POST fields or files (the latter is only used when emulating a form POST in the browser). * Lots of cleanup to CurlHandle::factory and RequestFactory::createRequest ## 3.3.1 - 2013-03-10 * Added the ability to create PHP streaming responses from HTTP requests * Bug fix: Running any filters when parsing response headers with service descriptions * Bug fix: OauthPlugin fixes to allow for multi-dimensional array signing, and sorting parameters before signing * Bug fix: Removed the adding of default empty arrays and false Booleans to responses in order to be consistent across response location visitors. * Bug fix: Removed the possibility of creating configuration files with circular dependencies * RequestFactory::create() now uses the key of a POST file when setting the POST file name * Added xmlAllowEmpty to serialize an XML body even if no XML specific parameters are set ## 3.3.0 - 2013-03-03 * A large number of performance optimizations have been made * Bug fix: Added 'wb' as a valid write mode for streams * Bug fix: `Guzzle\Http\Message\Response::json()` now allows scalar values to be returned * Bug fix: Fixed bug in `Guzzle\Http\Message\Response` where wrapping quotes were stripped from `getEtag()` * BC: Removed `Guzzle\Http\Utils` class * BC: Setting a service description on a client will no longer modify the client's command factories. * BC: Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io' * BC: `Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getSteamType()` are no longer converted to lowercase * Operation parameter objects are now lazy loaded internally * Added ErrorResponsePlugin that can throw errors for responses defined in service description operations' errorResponses * Added support for instantiating responseType=class responseClass classes. Classes must implement `Guzzle\Service\Command\ResponseClassInterface` * Added support for additionalProperties for top-level parameters in responseType=model responseClasses. These additional properties also support locations and can be used to parse JSON responses where the outermost part of the JSON is an array * Added support for nested renaming of JSON models (rename sentAs to name) * CachePlugin * Added support for stale-if-error so that the CachePlugin can now serve stale content from the cache on error * Debug headers can now added to cached response in the CachePlugin ## 3.2.0 - 2013-02-14 * CurlMulti is no longer reused globally. A new multi object is created per-client. This helps to isolate clients. * URLs with no path no longer contain a "/" by default * Guzzle\Http\QueryString does no longer manages the leading "?". This is now handled in Guzzle\Http\Url. * BadResponseException no longer includes the full request and response message * Adding setData() to Guzzle\Service\Description\ServiceDescriptionInterface * Adding getResponseBody() to Guzzle\Http\Message\RequestInterface * Various updates to classes to use ServiceDescriptionInterface type hints rather than ServiceDescription * Header values can now be normalized into distinct values when multiple headers are combined with a comma separated list * xmlEncoding can now be customized for the XML declaration of a XML service description operation * Guzzle\Http\QueryString now uses Guzzle\Http\QueryAggregator\QueryAggregatorInterface objects to add custom value aggregation and no longer uses callbacks * The URL encoding implementation of Guzzle\Http\QueryString can now be customized * Bug fix: Filters were not always invoked for array service description parameters * Bug fix: Redirects now use a target response body rather than a temporary response body * Bug fix: The default exponential backoff BackoffPlugin was not giving when the request threshold was exceeded * Bug fix: Guzzle now takes the first found value when grabbing Cache-Control directives ## 3.1.2 - 2013-01-27 * Refactored how operation responses are parsed. Visitors now include a before() method responsible for parsing the response body. For example, the XmlVisitor now parses the XML response into an array in the before() method. * Fixed an issue where cURL would not automatically decompress responses when the Accept-Encoding header was sent * CURLOPT_SSL_VERIFYHOST is never set to 1 because it is deprecated (see 5e0ff2ef20f839e19d1eeb298f90ba3598784444) * Fixed a bug where redirect responses were not chained correctly using getPreviousResponse() * Setting default headers on a client after setting the user-agent will not erase the user-agent setting ## 3.1.1 - 2013-01-20 * Adding wildcard support to Guzzle\Common\Collection::getPath() * Adding alias support to ServiceBuilder configs * Adding Guzzle\Service\Resource\CompositeResourceIteratorFactory and cleaning up factory interface ## 3.1.0 - 2013-01-12 * BC: CurlException now extends from RequestException rather than BadResponseException * BC: Renamed Guzzle\Plugin\Cache\CanCacheStrategyInterface::canCache() to canCacheRequest() and added CanCacheResponse() * Added getData to ServiceDescriptionInterface * Added context array to RequestInterface::setState() * Bug: Removing hard dependency on the BackoffPlugin from Guzzle\Http * Bug: Adding required content-type when JSON request visitor adds JSON to a command * Bug: Fixing the serialization of a service description with custom data * Made it easier to deal with exceptions thrown when transferring commands or requests in parallel by providing an array of successful and failed responses * Moved getPath from Guzzle\Service\Resource\Model to Guzzle\Common\Collection * Added Guzzle\Http\IoEmittingEntityBody * Moved command filtration from validators to location visitors * Added `extends` attributes to service description parameters * Added getModels to ServiceDescriptionInterface ## 3.0.7 - 2012-12-19 * Fixing phar detection when forcing a cacert to system if null or true * Allowing filename to be passed to `Guzzle\Http\Message\Request::setResponseBody()` * Cleaning up `Guzzle\Common\Collection::inject` method * Adding a response_body location to service descriptions ## 3.0.6 - 2012-12-09 * CurlMulti performance improvements * Adding setErrorResponses() to Operation * composer.json tweaks ## 3.0.5 - 2012-11-18 * Bug: Fixing an infinite recursion bug caused from revalidating with the CachePlugin * Bug: Response body can now be a string containing "0" * Bug: Using Guzzle inside of a phar uses system by default but now allows for a custom cacert * Bug: QueryString::fromString now properly parses query string parameters that contain equal signs * Added support for XML attributes in service description responses * DefaultRequestSerializer now supports array URI parameter values for URI template expansion * Added better mimetype guessing to requests and post files ## 3.0.4 - 2012-11-11 * Bug: Fixed a bug when adding multiple cookies to a request to use the correct glue value * Bug: Cookies can now be added that have a name, domain, or value set to "0" * Bug: Using the system cacert bundle when using the Phar * Added json and xml methods to Response to make it easier to parse JSON and XML response data into data structures * Enhanced cookie jar de-duplication * Added the ability to enable strict cookie jars that throw exceptions when invalid cookies are added * Added setStream to StreamInterface to actually make it possible to implement custom rewind behavior for entity bodies * Added the ability to create any sort of hash for a stream rather than just an MD5 hash ## 3.0.3 - 2012-11-04 * Implementing redirects in PHP rather than cURL * Added PECL URI template extension and using as default parser if available * Bug: Fixed Content-Length parsing of Response factory * Adding rewind() method to entity bodies and streams. Allows for custom rewinding of non-repeatable streams. * Adding ToArrayInterface throughout library * Fixing OauthPlugin to create unique nonce values per request ## 3.0.2 - 2012-10-25 * Magic methods are enabled by default on clients * Magic methods return the result of a command * Service clients no longer require a base_url option in the factory * Bug: Fixed an issue with URI templates where null template variables were being expanded ## 3.0.1 - 2012-10-22 * Models can now be used like regular collection objects by calling filter, map, etc. * Models no longer require a Parameter structure or initial data in the constructor * Added a custom AppendIterator to get around a PHP bug with the `\AppendIterator` ## 3.0.0 - 2012-10-15 * Rewrote service description format to be based on Swagger * Now based on JSON schema * Added nested input structures and nested response models * Support for JSON and XML input and output models * Renamed `commands` to `operations` * Removed dot class notation * Removed custom types * Broke the project into smaller top-level namespaces to be more component friendly * Removed support for XML configs and descriptions. Use arrays or JSON files. * Removed the Validation component and Inspector * Moved all cookie code to Guzzle\Plugin\Cookie * Magic methods on a Guzzle\Service\Client now return the command un-executed. * Calling getResult() or getResponse() on a command will lazily execute the command if needed. * Now shipping with cURL's CA certs and using it by default * Added previousResponse() method to response objects * No longer sending Accept and Accept-Encoding headers on every request * Only sending an Expect header by default when a payload is greater than 1MB * Added/moved client options: * curl.blacklist to curl.option.blacklist * Added ssl.certificate_authority * Added a Guzzle\Iterator component * Moved plugins from Guzzle\Http\Plugin to Guzzle\Plugin * Added a more robust backoff retry strategy (replaced the ExponentialBackoffPlugin) * Added a more robust caching plugin * Added setBody to response objects * Updating LogPlugin to use a more flexible MessageFormatter * Added a completely revamped build process * Cleaning up Collection class and removing default values from the get method * Fixed ZF2 cache adapters ## 2.8.8 - 2012-10-15 * Bug: Fixed a cookie issue that caused dot prefixed domains to not match where popular browsers did ## 2.8.7 - 2012-09-30 * Bug: Fixed config file aliases for JSON includes * Bug: Fixed cookie bug on a request object by using CookieParser to parse cookies on requests * Bug: Removing the path to a file when sending a Content-Disposition header on a POST upload * Bug: Hardening request and response parsing to account for missing parts * Bug: Fixed PEAR packaging * Bug: Fixed Request::getInfo * Bug: Fixed cases where CURLM_CALL_MULTI_PERFORM return codes were causing curl transactions to fail * Adding the ability for the namespace Iterator factory to look in multiple directories * Added more getters/setters/removers from service descriptions * Added the ability to remove POST fields from OAuth signatures * OAuth plugin now supports 2-legged OAuth ## 2.8.6 - 2012-09-05 * Added the ability to modify and build service descriptions * Added the use of visitors to apply parameters to locations in service descriptions using the dynamic command * Added a `json` parameter location * Now allowing dot notation for classes in the CacheAdapterFactory * Using the union of two arrays rather than an array_merge when extending service builder services and service params * Ensuring that a service is a string before doing strpos() checks on it when substituting services for references in service builder config files. * Services defined in two different config files that include one another will by default replace the previously defined service, but you can now create services that extend themselves and merge their settings over the previous * The JsonLoader now supports aliasing filenames with different filenames. This allows you to alias something like '_default' with a default JSON configuration file. ## 2.8.5 - 2012-08-29 * Bug: Suppressed empty arrays from URI templates * Bug: Added the missing $options argument from ServiceDescription::factory to enable caching * Added support for HTTP responses that do not contain a reason phrase in the start-line * AbstractCommand commands are now invokable * Added a way to get the data used when signing an Oauth request before a request is sent ## 2.8.4 - 2012-08-15 * Bug: Custom delay time calculations are no longer ignored in the ExponentialBackoffPlugin * Added the ability to transfer entity bodies as a string rather than streamed. This gets around curl error 65. Set `body_as_string` in a request's curl options to enable. * Added a StreamInterface, EntityBodyInterface, and added ftell() to Guzzle\Common\Stream * Added an AbstractEntityBodyDecorator and a ReadLimitEntityBody decorator to transfer only a subset of a decorated stream * Stream and EntityBody objects will now return the file position to the previous position after a read required operation (e.g. getContentMd5()) * Added additional response status codes * Removed SSL information from the default User-Agent header * DELETE requests can now send an entity body * Added an EventDispatcher to the ExponentialBackoffPlugin and added an ExponentialBackoffLogger to log backoff retries * Added the ability of the MockPlugin to consume mocked request bodies * LogPlugin now exposes request and response objects in the extras array ## 2.8.3 - 2012-07-30 * Bug: Fixed a case where empty POST requests were sent as GET requests * Bug: Fixed a bug in ExponentialBackoffPlugin that caused fatal errors when retrying an EntityEnclosingRequest that does not have a body * Bug: Setting the response body of a request to null after completing a request, not when setting the state of a request to new * Added multiple inheritance to service description commands * Added an ApiCommandInterface and added `getParamNames()` and `hasParam()` * Removed the default 2mb size cutoff from the Md5ValidatorPlugin so that it now defaults to validating everything * Changed CurlMulti::perform to pass a smaller timeout to CurlMulti::executeHandles ## 2.8.2 - 2012-07-24 * Bug: Query string values set to 0 are no longer dropped from the query string * Bug: A Collection object is no longer created each time a call is made to `Guzzle\Service\Command\AbstractCommand::getRequestHeaders()` * Bug: `+` is now treated as an encoded space when parsing query strings * QueryString and Collection performance improvements * Allowing dot notation for class paths in filters attribute of a service descriptions ## 2.8.1 - 2012-07-16 * Loosening Event Dispatcher dependency * POST redirects can now be customized using CURLOPT_POSTREDIR ## 2.8.0 - 2012-07-15 * BC: Guzzle\Http\Query * Query strings with empty variables will always show an equal sign unless the variable is set to QueryString::BLANK (e.g. ?acl= vs ?acl) * Changed isEncodingValues() and isEncodingFields() to isUrlEncoding() * Changed setEncodeValues(bool) and setEncodeFields(bool) to useUrlEncoding(bool) * Changed the aggregation functions of QueryString to be static methods * Can now use fromString() with querystrings that have a leading ? * cURL configuration values can be specified in service descriptions using `curl.` prefixed parameters * Content-Length is set to 0 before emitting the request.before_send event when sending an empty request body * Cookies are no longer URL decoded by default * Bug: URI template variables set to null are no longer expanded ## 2.7.2 - 2012-07-02 * BC: Moving things to get ready for subtree splits. Moving Inflection into Common. Moving Guzzle\Http\Parser to Guzzle\Parser. * BC: Removing Guzzle\Common\Batch\Batch::count() and replacing it with isEmpty() * CachePlugin now allows for a custom request parameter function to check if a request can be cached * Bug fix: CachePlugin now only caches GET and HEAD requests by default * Bug fix: Using header glue when transferring headers over the wire * Allowing deeply nested arrays for composite variables in URI templates * Batch divisors can now return iterators or arrays ## 2.7.1 - 2012-06-26 * Minor patch to update version number in UA string * Updating build process ## 2.7.0 - 2012-06-25 * BC: Inflection classes moved to Guzzle\Inflection. No longer static methods. Can now inject custom inflectors into classes. * BC: Removed magic setX methods from commands * BC: Magic methods mapped to service description commands are now inflected in the command factory rather than the client __call() method * Verbose cURL options are no longer enabled by default. Set curl.debug to true on a client to enable. * Bug: Now allowing colons in a response start-line (e.g. HTTP/1.1 503 Service Unavailable: Back-end server is at capacity) * Guzzle\Service\Resource\ResourceIteratorApplyBatched now internally uses the Guzzle\Common\Batch namespace * Added Guzzle\Service\Plugin namespace and a PluginCollectionPlugin * Added the ability to set POST fields and files in a service description * Guzzle\Http\EntityBody::factory() now accepts objects with a __toString() method * Adding a command.before_prepare event to clients * Added BatchClosureTransfer and BatchClosureDivisor * BatchTransferException now includes references to the batch divisor and transfer strategies * Fixed some tests so that they pass more reliably * Added Guzzle\Common\Log\ArrayLogAdapter ## 2.6.6 - 2012-06-10 * BC: Removing Guzzle\Http\Plugin\BatchQueuePlugin * BC: Removing Guzzle\Service\Command\CommandSet * Adding generic batching system (replaces the batch queue plugin and command set) * Updating ZF cache and log adapters and now using ZF's composer repository * Bug: Setting the name of each ApiParam when creating through an ApiCommand * Adding result_type, result_doc, deprecated, and doc_url to service descriptions * Bug: Changed the default cookie header casing back to 'Cookie' ## 2.6.5 - 2012-06-03 * BC: Renaming Guzzle\Http\Message\RequestInterface::getResourceUri() to getResource() * BC: Removing unused AUTH_BASIC and AUTH_DIGEST constants from * BC: Guzzle\Http\Cookie is now used to manage Set-Cookie data, not Cookie data * BC: Renaming methods in the CookieJarInterface * Moving almost all cookie logic out of the CookiePlugin and into the Cookie or CookieJar implementations * Making the default glue for HTTP headers ';' instead of ',' * Adding a removeValue to Guzzle\Http\Message\Header * Adding getCookies() to request interface. * Making it easier to add event subscribers to HasDispatcherInterface classes. Can now directly call addSubscriber() ## 2.6.4 - 2012-05-30 * BC: Cleaning up how POST files are stored in EntityEnclosingRequest objects. Adding PostFile class. * BC: Moving ApiCommand specific functionality from the Inspector and on to the ApiCommand * Bug: Fixing magic method command calls on clients * Bug: Email constraint only validates strings * Bug: Aggregate POST fields when POST files are present in curl handle * Bug: Fixing default User-Agent header * Bug: Only appending or prepending parameters in commands if they are specified * Bug: Not requiring response reason phrases or status codes to match a predefined list of codes * Allowing the use of dot notation for class namespaces when using instance_of constraint * Added any_match validation constraint * Added an AsyncPlugin * Passing request object to the calculateWait method of the ExponentialBackoffPlugin * Allowing the result of a command object to be changed * Parsing location and type sub values when instantiating a service description rather than over and over at runtime ## 2.6.3 - 2012-05-23 * [BC] Guzzle\Common\FromConfigInterface no longer requires any config options. * [BC] Refactoring how POST files are stored on an EntityEnclosingRequest. They are now separate from POST fields. * You can now use an array of data when creating PUT request bodies in the request factory. * Removing the requirement that HTTPS requests needed a Cache-Control: public directive to be cacheable. * [Http] Adding support for Content-Type in multipart POST uploads per upload * [Http] Added support for uploading multiple files using the same name (foo[0], foo[1]) * Adding more POST data operations for easier manipulation of POST data. * You can now set empty POST fields. * The body of a request is only shown on EntityEnclosingRequest objects that do not use POST files. * Split the Guzzle\Service\Inspector::validateConfig method into two methods. One to initialize when a command is created, and one to validate. * CS updates ## 2.6.2 - 2012-05-19 * [Http] Better handling of nested scope requests in CurlMulti. Requests are now always prepares in the send() method rather than the addRequest() method. ## 2.6.1 - 2012-05-19 * [BC] Removing 'path' support in service descriptions. Use 'uri'. * [BC] Guzzle\Service\Inspector::parseDocBlock is now protected. Adding getApiParamsForClass() with cache. * [BC] Removing Guzzle\Common\NullObject. Use https://github.com/mtdowling/NullObject if you need it. * [BC] Removing Guzzle\Common\XmlElement. * All commands, both dynamic and concrete, have ApiCommand objects. * Adding a fix for CurlMulti so that if all of the connections encounter some sort of curl error, then the loop exits. * Adding checks to EntityEnclosingRequest so that empty POST files and fields are ignored. * Making the method signature of Guzzle\Service\Builder\ServiceBuilder::factory more flexible. ## 2.6.0 - 2012-05-15 * [BC] Moving Guzzle\Service\Builder to Guzzle\Service\Builder\ServiceBuilder * [BC] Executing a Command returns the result of the command rather than the command * [BC] Moving all HTTP parsing logic to Guzzle\Http\Parsers. Allows for faster C implementations if needed. * [BC] Changing the Guzzle\Http\Message\Response::setProtocol() method to accept a protocol and version in separate args. * [BC] Moving ResourceIterator* to Guzzle\Service\Resource * [BC] Completely refactored ResourceIterators to iterate over a cloned command object * [BC] Moved Guzzle\Http\UriTemplate to Guzzle\Http\Parser\UriTemplate\UriTemplate * [BC] Guzzle\Guzzle is now deprecated * Moving Guzzle\Common\Guzzle::inject to Guzzle\Common\Collection::inject * Adding Guzzle\Version class to give version information about Guzzle * Adding Guzzle\Http\Utils class to provide getDefaultUserAgent() and getHttpDate() * Adding Guzzle\Curl\CurlVersion to manage caching curl_version() data * ServiceDescription and ServiceBuilder are now cacheable using similar configs * Changing the format of XML and JSON service builder configs. Backwards compatible. * Cleaned up Cookie parsing * Trimming the default Guzzle User-Agent header * Adding a setOnComplete() method to Commands that is called when a command completes * Keeping track of requests that were mocked in the MockPlugin * Fixed a caching bug in the CacheAdapterFactory * Inspector objects can be injected into a Command object * Refactoring a lot of code and tests to be case insensitive when dealing with headers * Adding Guzzle\Http\Message\HeaderComparison for easy comparison of HTTP headers using a DSL * Adding the ability to set global option overrides to service builder configs * Adding the ability to include other service builder config files from within XML and JSON files * Moving the parseQuery method out of Url and on to QueryString::fromString() as a static factory method. ## 2.5.0 - 2012-05-08 * Major performance improvements * [BC] Simplifying Guzzle\Common\Collection. Please check to see if you are using features that are now deprecated. * [BC] Using a custom validation system that allows a flyweight implementation for much faster validation. No longer using Symfony2 Validation component. * [BC] No longer supporting "{{ }}" for injecting into command or UriTemplates. Use "{}" * Added the ability to passed parameters to all requests created by a client * Added callback functionality to the ExponentialBackoffPlugin * Using microtime in ExponentialBackoffPlugin to allow more granular backoff strategies. * Rewinding request stream bodies when retrying requests * Exception is thrown when JSON response body cannot be decoded * Added configurable magic method calls to clients and commands. This is off by default. * Fixed a defect that added a hash to every parsed URL part * Fixed duplicate none generation for OauthPlugin. * Emitting an event each time a client is generated by a ServiceBuilder * Using an ApiParams object instead of a Collection for parameters of an ApiCommand * cache.* request parameters should be renamed to params.cache.* * Added the ability to set arbitrary curl options on requests (disable_wire, progress, etc.). See CurlHandle. * Added the ability to disable type validation of service descriptions * ServiceDescriptions and ServiceBuilders are now Serializable The MIT License (MIT) Copyright (c) 2011 Michael Dowling Copyright (c) 2012 Jeremy Lindblom Copyright (c) 2014 Graham Campbell Copyright (c) 2015 Márk Sági-Kazár Copyright (c) 2015 Tobias Schultze Copyright (c) 2016 Tobias Nyholm Copyright (c) 2016 George Mponos 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. ![Guzzle](.github/logo.png?raw=true) # Guzzle, PHP HTTP client [![Latest Version](https://img.shields.io/github/release/guzzle/guzzle.svg?style=flat-square)](https://github.com/guzzle/guzzle/releases) [![Build Status](https://img.shields.io/github/actions/workflow/status/guzzle/guzzle/ci.yml?label=ci%20build&style=flat-square)](https://github.com/guzzle/guzzle/actions?query=workflow%3ACI) [![Total Downloads](https://img.shields.io/packagist/dt/guzzlehttp/guzzle.svg?style=flat-square)](https://packagist.org/packages/guzzlehttp/guzzle) Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services. - Simple interface for building query strings, POST requests, streaming large uploads, streaming large downloads, using HTTP cookies, uploading JSON data, etc... - Can send both synchronous and asynchronous requests using the same interface. - Uses PSR-7 interfaces for requests, responses, and streams. This allows you to utilize other PSR-7 compatible libraries with Guzzle. - Supports PSR-18 allowing interoperability between other PSR-18 HTTP Clients. - Abstracts away the underlying HTTP transport, allowing you to write environment and transport agnostic code; i.e., no hard dependency on cURL, PHP streams, sockets, or non-blocking event loops. - Middleware system allows you to augment and compose client behavior. ```php $client = new \GuzzleHttp\Client(); $response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle'); echo $response->getStatusCode(); // 200 echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8' echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}' // Send an asynchronous request. $request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org'); $promise = $client->sendAsync($request)->then(function ($response) { echo 'I completed! ' . $response->getBody(); }); $promise->wait(); ``` ## Help and docs We use GitHub issues only to discuss bugs and new features. For support please refer to: - [Documentation](docs/index.md) - [Stack Overflow](https://stackoverflow.com/questions/tagged/guzzle) - [#guzzle](https://app.slack.com/client/T0D2S9JCT/CE6UAAKL4) channel on [PHP-HTTP Slack](https://slack.httplug.io/) - [Gitter](https://gitter.im/guzzle/guzzle) ## Installing Guzzle The recommended way to install Guzzle is through [Composer](https://getcomposer.org/). ```bash composer require guzzlehttp/guzzle ``` ## Version Guidance | Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version | |---------|---------------------|---------------------|--------------|---------------------|---------------------|-------|--------------| | 3.x | EOL (2016-10-31) | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 | | 4.x | EOL (2016-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 | | 5.x | EOL (2019-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 | | 6.x | EOL (2023-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >=5.5,<8.0 | | 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >=7.2.5,<8.6 | [guzzle-3-repo]: https://github.com/guzzle/guzzle3 [guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x [guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3 [guzzle-6-repo]: https://github.com/guzzle/guzzle/tree/6.5 [guzzle-7-repo]: https://github.com/guzzle/guzzle/tree/7.15 [guzzle-3-docs]: https://github.com/guzzle/guzzle3/tree/master/docs [guzzle-5-docs]: https://github.com/guzzle/guzzle/tree/5.3/docs [guzzle-6-docs]: https://github.com/guzzle/guzzle/tree/6.5/docs [guzzle-7-docs]: https://github.com/guzzle/guzzle/blob/7.15/docs/index.md ## Security If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/guzzle/security/policy) for more information. ## License Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. ## For Enterprise Available as part of the Tidelift Subscription The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver 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. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-guzzle?utm_source=packagist-guzzlehttp-guzzle&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) Guzzle Upgrade Guide ==================== 6.0 to 7.0 ---------- In order to take advantage of the new features of PHP, Guzzle dropped the support of PHP 5. The minimum supported PHP version is now PHP 7.2. Type hints and return types for functions and methods have been added wherever possible. Please make sure: - You are calling a function or a method with the correct type. - If you extend a class of Guzzle; update all signatures on methods you override. #### Other Backwards Compatibility Breaking Changes - Class `GuzzleHttp\UriTemplate` is removed. - Class `GuzzleHttp\Exception\SeekException` is removed. - Classes `GuzzleHttp\Exception\BadResponseException`, `GuzzleHttp\Exception\ClientException`, `GuzzleHttp\Exception\ServerException` can no longer be initialized with an empty Response as argument. - Class `GuzzleHttp\Exception\ConnectException` now extends `GuzzleHttp\Exception\TransferException` instead of `GuzzleHttp\Exception\RequestException`. - Function `GuzzleHttp\Exception\ConnectException::getResponse()` is removed. - Function `GuzzleHttp\Exception\ConnectException::hasResponse()` is removed. - Constant `GuzzleHttp\ClientInterface::VERSION` is removed. Added `GuzzleHttp\ClientInterface::MAJOR_VERSION` instead. - Function `GuzzleHttp\Exception\RequestException::getResponseBodySummary` is removed. Use `\GuzzleHttp\Psr7\get_message_body_summary` as an alternative. - Function `GuzzleHttp\Cookie\CookieJar::getCookieValue` is removed. - Request option `exceptions` is removed. Please use `http_errors`. - Request option `save_to` is removed. Please use `sink`. - Pool option `pool_size` is removed. Please use `concurrency`. - We now look for environment variables in the `$_SERVER` super global, due to thread safety issues with `getenv`. We continue to fallback to `getenv` in CLI environments, for maximum compatibility. - The `get`, `head`, `put`, `post`, `patch`, `delete`, `getAsync`, `headAsync`, `putAsync`, `postAsync`, `patchAsync`, and `deleteAsync` methods are now implemented as genuine methods on `GuzzleHttp\Client`, with strong typing. The original `__call` implementation remains unchanged for now, for maximum backwards compatibility, but won't be invoked under normal operation. - The `log` middleware will log the errors with level `error` instead of `notice` - Support for international domain names (IDN) is now disabled by default, and enabling it requires installing ext-intl, linked against a modern version of the C library (ICU 4.6 or higher). #### Native Functions Calls All internal native functions calls of Guzzle are now prefixed with a slash. This change makes it impossible for method overloading by other libraries or applications. Example: ```php // Before: curl_version(); // After: \curl_version(); ``` For the full diff you can check [here](https://github.com/guzzle/guzzle/compare/6.5.4..7.0.0). 5.0 to 6.0 ---------- Guzzle now uses [PSR-7](https://www.php-fig.org/psr/psr-7/) for HTTP messages. Due to the fact that these messages are immutable, this prompted a refactoring of Guzzle to use a middleware based system rather than an event system. Any HTTP message interaction (e.g., `GuzzleHttp\Message\Request`) need to be updated to work with the new immutable PSR-7 request and response objects. Any event listeners or subscribers need to be updated to become middleware functions that wrap handlers (or are injected into a `GuzzleHttp\HandlerStack`). - Removed `GuzzleHttp\BatchResults` - Removed `GuzzleHttp\Collection` - Removed `GuzzleHttp\HasDataTrait` - Removed `GuzzleHttp\ToArrayInterface` - The `guzzlehttp/streams` dependency has been removed. Stream functionality is now present in the `GuzzleHttp\Psr7` namespace provided by the `guzzlehttp/psr7` package. - Guzzle no longer uses ReactPHP promises and now uses the `guzzlehttp/promises` library. We use a custom promise library for three significant reasons: 1. React promises (at the time of writing this) are recursive. Promise chaining and promise resolution will eventually blow the stack. Guzzle promises are not recursive as they use a sort of trampolining technique. Note: there has been movement in the React project to modify promises to no longer utilize recursion. 2. Guzzle needs to have the ability to synchronously block on a promise to wait for a result. Guzzle promises allows this functionality (and does not require the use of recursion). 3. Because we need to be able to wait on a result, doing so using React promises requires wrapping react promises with RingPHP futures. This overhead is no longer needed, reducing stack sizes, reducing complexity, and improving performance. - `GuzzleHttp\Mimetypes` has been moved to a function in `GuzzleHttp\Psr7\mimetype_from_extension` and `GuzzleHttp\Psr7\mimetype_from_filename`. - `GuzzleHttp\Query` and `GuzzleHttp\QueryParser` have been removed. Query strings must now be passed into request objects as strings, or provided to the `query` request option when creating requests with clients. The `query` option uses PHP's `http_build_query` to convert an array to a string. If you need a different serialization technique, you will need to pass the query string in as a string. There are a couple helper functions that will make working with query strings easier: `GuzzleHttp\Psr7\parse_query` and `GuzzleHttp\Psr7\build_query`. - Guzzle no longer has a dependency on RingPHP. Due to the use of a middleware system based on PSR-7, using RingPHP and it's middleware system as well adds more complexity than the benefits it provides. All HTTP handlers that were present in RingPHP have been modified to work directly with PSR-7 messages and placed in the `GuzzleHttp\Handler` namespace. This significantly reduces complexity in Guzzle, removes a dependency, and improves performance. RingPHP will be maintained for Guzzle 5 support, but will no longer be a part of Guzzle 6. - As Guzzle now uses a middleware based systems the event system and RingPHP integration has been removed. Note: while the event system has been removed, it is possible to add your own type of event system that is powered by the middleware system. - Removed the `Event` namespace. - Removed the `Subscriber` namespace. - Removed `Transaction` class - Removed `RequestFsm` - Removed `RingBridge` - `GuzzleHttp\Subscriber\Cookie` is now provided by `GuzzleHttp\Middleware::cookies` - `GuzzleHttp\Subscriber\HttpError` is now provided by `GuzzleHttp\Middleware::httpError` - `GuzzleHttp\Subscriber\History` is now provided by `GuzzleHttp\Middleware::history` - `GuzzleHttp\Subscriber\Mock` is now provided by `GuzzleHttp\Handler\MockHandler` - `GuzzleHttp\Subscriber\Prepare` is now provided by `GuzzleHttp\PrepareBodyMiddleware` - `GuzzleHttp\Subscriber\Redirect` is now provided by `GuzzleHttp\RedirectMiddleware` - Guzzle now uses `Psr\Http\Message\UriInterface` (implements in `GuzzleHttp\Psr7\Uri`) for URI support. `GuzzleHttp\Url` is now gone. - Static functions in `GuzzleHttp\Utils` have been moved to namespaced functions under the `GuzzleHttp` namespace. This requires either a Composer based autoloader or you to include functions.php. - `GuzzleHttp\ClientInterface::getDefaultOption` has been renamed to `GuzzleHttp\ClientInterface::getConfig`. - `GuzzleHttp\ClientInterface::setDefaultOption` has been removed. - The `json` and `xml` methods of response objects has been removed. With the migration to strictly adhering to PSR-7 as the interface for Guzzle messages, adding methods to message interfaces would actually require Guzzle messages to extend from PSR-7 messages rather then work with them directly. ## Migrating to middleware The change to PSR-7 unfortunately required significant refactoring to Guzzle due to the fact that PSR-7 messages are immutable. Guzzle 5 relied on an event system from plugins. The event system relied on mutability of HTTP messages and side effects in order to work. With immutable messages, you have to change your workflow to become more about either returning a value (e.g., functional middlewares) or setting a value on an object. Guzzle v6 has chosen the functional middleware approach. Instead of using the event system to listen for things like the `before` event, you now create a stack based middleware function that intercepts a request on the way in and the promise of the response on the way out. This is a much simpler and more predictable approach than the event system and works nicely with PSR-7 middleware. Due to the use of promises, the middleware system is also asynchronous. v5: ```php use GuzzleHttp\Event\BeforeEvent; $client = new GuzzleHttp\Client(); // Get the emitter and listen to the before event. $client->getEmitter()->on('before', function (BeforeEvent $e) { // Guzzle v5 events relied on mutation $e->getRequest()->setHeader('X-Foo', 'Bar'); }); ``` v6: In v6, you can modify the request before it is sent using the `mapRequest` middleware. The idiomatic way in v6 to modify the request/response lifecycle is to setup a handler middleware stack up front and inject the handler into a client. ```php use GuzzleHttp\Middleware; // Create a handler stack that has all of the default middlewares attached $handler = GuzzleHttp\HandlerStack::create(); // Push the handler onto the handler stack $handler->push(Middleware::mapRequest(function (RequestInterface $request) { // Notice that we have to return a request object return $request->withHeader('X-Foo', 'Bar'); })); // Inject the handler into the client $client = new GuzzleHttp\Client(['handler' => $handler]); ``` ## POST Requests This version added the [`form_params`](https://github.com/guzzle/guzzle/blob/6.5/docs/request-options.rst#form_params) and `multipart` request options. `form_params` is an associative array of strings or array of strings and is used to serialize an `application/x-www-form-urlencoded` POST request. The [`multipart`](https://github.com/guzzle/guzzle/blob/6.5/docs/request-options.rst#multipart) option is now used to send a multipart/form-data POST request. `GuzzleHttp\Post\PostFile` has been removed. Use the `multipart` option to add POST files to a multipart/form-data request. The `body` option no longer accepts an array to send POST requests. Please use `multipart` or `form_params` instead. The `base_url` option has been renamed to `base_uri`. 4.x to 5.0 ---------- ## Rewritten Adapter Layer Guzzle now uses [RingPHP](https://github.com/guzzle/RingPHP) to send HTTP requests. The `adapter` option in a `GuzzleHttp\Client` constructor is still supported, but it has now been renamed to `handler`. Instead of passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP `callable` that follows the RingPHP specification. ## Removed Fluent Interfaces [Fluent interfaces were removed](https://ocramius.github.io/blog/fluent-interfaces-are-evil/) from the following classes: - `GuzzleHttp\Collection` - `GuzzleHttp\Url` - `GuzzleHttp\Query` - `GuzzleHttp\Post\PostBody` - `GuzzleHttp\Cookie\SetCookie` ## Removed functions.php Removed "functions.php", so that Guzzle is truly PSR-4 compliant. The following functions can be used as replacements. - `GuzzleHttp\json_decode` -> `GuzzleHttp\Utils::jsonDecode` - `GuzzleHttp\get_path` -> `GuzzleHttp\Utils::getPath` - `GuzzleHttp\Utils::setPath` -> `GuzzleHttp\set_path` - `GuzzleHttp\Pool::batch` -> `GuzzleHttp\batch`. This function is, however, deprecated in favor of using `GuzzleHttp\Pool::batch()`. The "procedural" global client has been removed with no replacement (e.g., `GuzzleHttp\get()`, `GuzzleHttp\post()`, etc.). Use a `GuzzleHttp\Client` object as a replacement. ## `throwImmediately` has been removed The concept of "throwImmediately" has been removed from exceptions and error events. This control mechanism was used to stop a transfer of concurrent requests from completing. This can now be handled by throwing the exception or by cancelling a pool of requests or each outstanding future request individually. ## headers event has been removed Removed the "headers" event. This event was only useful for changing the body a response once the headers of the response were known. You can implement a similar behavior in a number of ways. One example might be to use a FnStream that has access to the transaction being sent. For example, when the first byte is written, you could check if the response headers match your expectations, and if so, change the actual stream body that is being written to. ## Updates to HTTP Messages Removed the `asArray` parameter from `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header value as an array, then use the newly added `getHeaderAsArray()` method of `MessageInterface`. This change makes the Guzzle interfaces compatible with the PSR-7 interfaces. 3.x to 4.0 ---------- ## Overarching changes: - Now requires PHP 5.4 or greater. - No longer requires cURL to send requests. - Guzzle no longer wraps every exception it throws. Only exceptions that are recoverable are now wrapped by Guzzle. - Various namespaces have been removed or renamed. - No longer requiring the Symfony EventDispatcher. A custom event dispatcher based on the Symfony EventDispatcher is now utilized in `GuzzleHttp\Event\EmitterInterface` (resulting in significant speed and functionality improvements). Changes per Guzzle 3.x namespace are described below. ## Batch The `Guzzle\Batch` namespace has been removed. This is best left to third-parties to implement on top of Guzzle's core HTTP library. ## Cache The `Guzzle\Cache` namespace has been removed. (Todo: No suitable replacement has been implemented yet, but hoping to utilize a PSR cache interface). ## Common - Removed all of the wrapped exceptions. It's better to use the standard PHP library for unrecoverable exceptions. - `FromConfigInterface` has been removed. - `Guzzle\Common\Version` has been removed. The VERSION constant can be found at `GuzzleHttp\ClientInterface::VERSION`. ### Collection - `getAll` has been removed. Use `toArray` to convert a collection to an array. - `inject` has been removed. - `keySearch` has been removed. - `getPath` no longer supports wildcard expressions. Use something better like JMESPath for this. - `setPath` now supports appending to an existing array via the `[]` notation. ### Events Guzzle no longer requires Symfony's EventDispatcher component. Guzzle now uses `GuzzleHttp\Event\Emitter`. - `Symfony\Component\EventDispatcher\EventDispatcherInterface` is replaced by `GuzzleHttp\Event\EmitterInterface`. - `Symfony\Component\EventDispatcher\EventDispatcher` is replaced by `GuzzleHttp\Event\Emitter`. - `Symfony\Component\EventDispatcher\Event` is replaced by `GuzzleHttp\Event\Event`, and Guzzle now has an EventInterface in `GuzzleHttp\Event\EventInterface`. - `AbstractHasDispatcher` has moved to a trait, `HasEmitterTrait`, and `HasDispatcherInterface` has moved to `HasEmitterInterface`. Retrieving the event emitter of a request, client, etc. now uses the `getEmitter` method rather than the `getDispatcher` method. #### Emitter - Use the `once()` method to add a listener that automatically removes itself the first time it is invoked. - Use the `listeners()` method to retrieve a list of event listeners rather than the `getListeners()` method. - Use `emit()` instead of `dispatch()` to emit an event from an emitter. - Use `attach()` instead of `addSubscriber()` and `detach()` instead of `removeSubscriber()`. ```php $mock = new Mock(); // 3.x $request->getEventDispatcher()->addSubscriber($mock); $request->getEventDispatcher()->removeSubscriber($mock); // 4.x $request->getEmitter()->attach($mock); $request->getEmitter()->detach($mock); ``` Use the `on()` method to add a listener rather than the `addListener()` method. ```php // 3.x $request->getEventDispatcher()->addListener('foo', function (Event $event) { /* ... */ } ); // 4.x $request->getEmitter()->on('foo', function (Event $event, $name) { /* ... */ } ); ``` ## Http ### General changes - The cacert.pem certificate has been moved to `src/cacert.pem`. - Added the concept of adapters that are used to transfer requests over the wire. - Simplified the event system. - Sending requests in parallel is still possible, but batching is no longer a concept of the HTTP layer. Instead, you must use the `complete` and `error` events to asynchronously manage parallel request transfers. - `Guzzle\Http\Url` has moved to `GuzzleHttp\Url`. - `Guzzle\Http\QueryString` has moved to `GuzzleHttp\Query`. - QueryAggregators have been rewritten so that they are simply callable functions. - `GuzzleHttp\StaticClient` has been removed. Use the functions provided in `functions.php` for an easy to use static client instance. - Exceptions in `GuzzleHttp\Exception` have been updated to all extend from `GuzzleHttp\Exception\TransferException`. ### Client Calling methods like `get()`, `post()`, `head()`, etc. no longer create and return a request, but rather creates a request, sends the request, and returns the response. ```php // 3.0 $request = $client->get('/'); $response = $request->send(); // 4.0 $response = $client->get('/'); // or, to mirror the previous behavior $request = $client->createRequest('GET', '/'); $response = $client->send($request); ``` `GuzzleHttp\ClientInterface` has changed. - The `send` method no longer accepts more than one request. Use `sendAll` to send multiple requests in parallel. - `setUserAgent()` has been removed. Use a default request option instead. You could, for example, do something like: `$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())`. - `setSslVerification()` has been removed. Use default request options instead, like `$client->setConfig('defaults/verify', true)`. `GuzzleHttp\Client` has changed. - The constructor now accepts only an associative array. You can include a `base_url` string or array to use a URI template as the base URL of a client. You can also specify a `defaults` key that is an associative array of default request options. You can pass an `adapter` to use a custom adapter, `batch_adapter` to use a custom adapter for sending requests in parallel, or a `message_factory` to change the factory used to create HTTP requests and responses. - The client no longer emits a `client.create_request` event. - Creating requests with a client no longer automatically utilize a URI template. You must pass an array into a creational method (e.g., `createRequest`, `get`, `put`, etc.) in order to expand a URI template. ### Messages Messages no longer have references to their counterparts (i.e., a request no longer has a reference to it's response, and a response no loger has a reference to its request). This association is now managed through a `GuzzleHttp\Adapter\TransactionInterface` object. You can get references to these transaction objects using request events that are emitted over the lifecycle of a request. #### Requests with a body - `GuzzleHttp\Message\EntityEnclosingRequest` and `GuzzleHttp\Message\EntityEnclosingRequestInterface` have been removed. The separation between requests that contain a body and requests that do not contain a body has been removed, and now `GuzzleHttp\Message\RequestInterface` handles both use cases. - Any method that previously accepts a `GuzzleHttp\Response` object now accept a `GuzzleHttp\Message\ResponseInterface`. - `GuzzleHttp\Message\RequestFactoryInterface` has been renamed to `GuzzleHttp\Message\MessageFactoryInterface`. This interface is used to create both requests and responses and is implemented in `GuzzleHttp\Message\MessageFactory`. - POST field and file methods have been removed from the request object. You must now use the methods made available to `GuzzleHttp\Post\PostBodyInterface` to control the format of a POST body. Requests that are created using a standard `GuzzleHttp\Message\MessageFactoryInterface` will automatically use a `GuzzleHttp\Post\PostBody` body if the body was passed as an array or if the method is POST and no body is provided. ```php $request = $client->createRequest('POST', '/'); $request->getBody()->setField('foo', 'bar'); $request->getBody()->addFile(new PostFile('file_key', fopen('/path/to/content', 'r'))); ``` #### Headers - `GuzzleHttp\Message\Header` has been removed. Header values are now simply represented by an array of values or as a string. Header values are returned as a string by default when retrieving a header value from a message. You can pass an optional argument of `true` to retrieve a header value as an array of strings instead of a single concatenated string. - `GuzzleHttp\PostFile` and `GuzzleHttp\PostFileInterface` have been moved to `GuzzleHttp\Post`. This interface has been simplified and now allows the addition of arbitrary headers. - Custom headers like `GuzzleHttp\Message\Header\Link` have been removed. Most of the custom headers are now handled separately in specific subscribers/plugins, and `GuzzleHttp\Message\HeaderValues::parseParams()` has been updated to properly handle headers that contain parameters (like the `Link` header). #### Responses - `GuzzleHttp\Message\Response::getInfo()` and `GuzzleHttp\Message\Response::setInfo()` have been removed. Use the event system to retrieve this type of information. - `GuzzleHttp\Message\Response::getRawHeaders()` has been removed. - `GuzzleHttp\Message\Response::getMessage()` has been removed. - `GuzzleHttp\Message\Response::calculateAge()` and other cache specific methods have moved to the CacheSubscriber. - Header specific helper functions like `getContentMd5()` have been removed. Just use `getHeader('Content-MD5')` instead. - `GuzzleHttp\Message\Response::setRequest()` and `GuzzleHttp\Message\Response::getRequest()` have been removed. Use the event system to work with request and response objects as a transaction. - `GuzzleHttp\Message\Response::getRedirectCount()` has been removed. Use the Redirect subscriber instead. - `GuzzleHttp\Message\Response::isSuccessful()` and other related methods have been removed. Use `getStatusCode()` instead. #### Streaming responses Streaming requests can now be created by a client directly, returning a `GuzzleHttp\Message\ResponseInterface` object that contains a body stream referencing an open PHP HTTP stream. ```php // 3.0 use Guzzle\Stream\PhpStreamRequestFactory; $request = $client->get('/'); $factory = new PhpStreamRequestFactory(); $stream = $factory->fromRequest($request); $data = $stream->read(1024); // 4.0 $response = $client->get('/', ['stream' => true]); // Read some data off of the stream in the response body $data = $response->getBody()->read(1024); ``` #### Redirects The `configureRedirects()` method has been removed in favor of a `allow_redirects` request option. ```php // Standard redirects with a default of a max of 5 redirects $request = $client->createRequest('GET', '/', ['allow_redirects' => true]); // Strict redirects with a custom number of redirects $request = $client->createRequest('GET', '/', [ 'allow_redirects' => ['max' => 5, 'strict' => true] ]); ``` #### EntityBody EntityBody interfaces and classes have been removed or moved to `GuzzleHttp\Stream`. All classes and interfaces that once required `GuzzleHttp\EntityBodyInterface` now require `GuzzleHttp\Stream\StreamInterface`. Creating a new body for a request no longer uses `GuzzleHttp\EntityBody::factory` but now uses `GuzzleHttp\Stream\Stream::factory` or even better: `GuzzleHttp\Stream\create()`. - `Guzzle\Http\EntityBodyInterface` is now `GuzzleHttp\Stream\StreamInterface` - `Guzzle\Http\EntityBody` is now `GuzzleHttp\Stream\Stream` - `Guzzle\Http\CachingEntityBody` is now `GuzzleHttp\Stream\CachingStream` - `Guzzle\Http\ReadLimitEntityBody` is now `GuzzleHttp\Stream\LimitStream` - `Guzzle\Http\IoEmittyinEntityBody` has been removed. #### Request lifecycle events Requests previously submitted a large number of requests. The number of events emitted over the lifecycle of a request has been significantly reduced to make it easier to understand how to extend the behavior of a request. All events emitted during the lifecycle of a request now emit a custom `GuzzleHttp\Event\EventInterface` object that contains context providing methods and a way in which to modify the transaction at that specific point in time (e.g., intercept the request and set a response on the transaction). - `request.before_send` has been renamed to `before` and now emits a `GuzzleHttp\Event\BeforeEvent` - `request.complete` has been renamed to `complete` and now emits a `GuzzleHttp\Event\CompleteEvent`. - `request.sent` has been removed. Use `complete`. - `request.success` has been removed. Use `complete`. - `error` is now an event that emits a `GuzzleHttp\Event\ErrorEvent`. - `request.exception` has been removed. Use `error`. - `request.receive.status_line` has been removed. - `curl.callback.progress` has been removed. Use a custom `StreamInterface` to maintain a status update. - `curl.callback.write` has been removed. Use a custom `StreamInterface` to intercept writes. - `curl.callback.read` has been removed. Use a custom `StreamInterface` to intercept reads. `headers` is a new event that is emitted after the response headers of a request have been received before the body of the response is downloaded. This event emits a `GuzzleHttp\Event\HeadersEvent`. You can intercept a request and inject a response using the `intercept()` event of a `GuzzleHttp\Event\BeforeEvent`, `GuzzleHttp\Event\CompleteEvent`, and `GuzzleHttp\Event\ErrorEvent` event. ## Inflection The `Guzzle\Inflection` namespace has been removed. This is not a core concern of Guzzle. ## Iterator The `Guzzle\Iterator` namespace has been removed. - `Guzzle\Iterator\AppendIterator`, `Guzzle\Iterator\ChunkedIterator`, and `Guzzle\Iterator\MethodProxyIterator` are nice, but not a core requirement of Guzzle itself. - `Guzzle\Iterator\FilterIterator` is no longer needed because an equivalent class is shipped with PHP 5.4. - `Guzzle\Iterator\MapIterator` is not really needed when using PHP 5.5 because it's easier to just wrap an iterator in a generator that maps values. For a replacement of these iterators, see https://github.com/nikic/iter ## Log The LogPlugin has moved to https://github.com/guzzle/log-subscriber. The `Guzzle\Log` namespace has been removed. Guzzle now relies on `Psr\Log\LoggerInterface` for all logging. The MessageFormatter class has been moved to `GuzzleHttp\Subscriber\Log\Formatter`. ## Parser The `Guzzle\Parser` namespace has been removed. This was previously used to make it possible to plug in custom parsers for cookies, messages, URI templates, and URLs; however, this level of complexity is not needed in Guzzle so it has been removed. - Cookie: Cookie parsing logic has been moved to `GuzzleHttp\Cookie\SetCookie::fromString`. - Message: Message parsing logic for both requests and responses has been moved to `GuzzleHttp\Message\MessageFactory::fromMessage`. Message parsing is only used in debugging or deserializing messages, so it doesn't make sense for Guzzle as a library to add this level of complexity to parsing messages. - UriTemplate: URI template parsing has been moved to `GuzzleHttp\UriTemplate`. The Guzzle library will automatically use the PECL URI template library if it is installed. - Url: URL parsing is now performed in `GuzzleHttp\Url::fromString` (previously it was `Guzzle\Http\Url::factory()`). If custom URL parsing is necessary, then developers are free to subclass `GuzzleHttp\Url`. ## Plugin The `Guzzle\Plugin` namespace has been renamed to `GuzzleHttp\Subscriber`. Several plugins are shipping with the core Guzzle library under this namespace. - `GuzzleHttp\Subscriber\Cookie`: Replaces the old CookiePlugin. Cookie jar code has moved to `GuzzleHttp\Cookie`. - `GuzzleHttp\Subscriber\History`: Replaces the old HistoryPlugin. - `GuzzleHttp\Subscriber\HttpError`: Throws errors when a bad HTTP response is received. - `GuzzleHttp\Subscriber\Mock`: Replaces the old MockPlugin. - `GuzzleHttp\Subscriber\Prepare`: Prepares the body of a request just before sending. This subscriber is attached to all requests by default. - `GuzzleHttp\Subscriber\Redirect`: Replaces the RedirectPlugin. The following plugins have been removed (third-parties are free to re-implement these if needed): - `GuzzleHttp\Plugin\Async` has been removed. - `GuzzleHttp\Plugin\CurlAuth` has been removed. - `GuzzleHttp\Plugin\ErrorResponse\ErrorResponsePlugin` has been removed. This functionality should instead be implemented with event listeners that occur after normal response parsing occurs in the guzzle/command package. The following plugins are not part of the core Guzzle package, but are provided in separate repositories: - `Guzzle\Http\Plugin\BackoffPlugin` has been rewritten to be much simpler to build custom retry policies using simple functions rather than various chained classes. See: https://github.com/guzzle/retry-subscriber - `Guzzle\Http\Plugin\Cache\CachePlugin` has moved to https://github.com/guzzle/cache-subscriber - `Guzzle\Http\Plugin\Log\LogPlugin` has moved to https://github.com/guzzle/log-subscriber - `Guzzle\Http\Plugin\Md5\Md5Plugin` has moved to https://github.com/guzzle/message-integrity-subscriber - `Guzzle\Http\Plugin\Mock\MockPlugin` has moved to `GuzzleHttp\Subscriber\MockSubscriber`. - `Guzzle\Http\Plugin\Oauth\OauthPlugin` has moved to https://github.com/guzzle/oauth-subscriber ## Service The service description layer of Guzzle has moved into two separate packages: - https://github.com/guzzle/command Provides a high level abstraction over web services by representing web service operations using commands. - https://github.com/guzzle/guzzle-services Provides an implementation of guzzle/command that provides request serialization and response parsing using Guzzle service descriptions. ## Stream Stream have moved to a separate package available at https://github.com/guzzle/streams. `Guzzle\Stream\StreamInterface` has been given a large update to cleanly take on the responsibilities of `Guzzle\Http\EntityBody` and `Guzzle\Http\EntityBodyInterface` now that they have been removed. The number of methods implemented by the `StreamInterface` has been drastically reduced to allow developers to more easily extend and decorate stream behavior. ## Removed methods from StreamInterface - `getStream` and `setStream` have been removed to better encapsulate streams. - `getMetadata` and `setMetadata` have been removed in favor of `GuzzleHttp\Stream\MetadataStreamInterface`. - `getWrapper`, `getWrapperData`, `getStreamType`, and `getUri` have all been removed. This data is accessible when using streams that implement `GuzzleHttp\Stream\MetadataStreamInterface`. - `rewind` has been removed. Use `seek(0)` for a similar behavior. ## Renamed methods - `detachStream` has been renamed to `detach`. - `feof` has been renamed to `eof`. - `ftell` has been renamed to `tell`. - `readLine` has moved from an instance method to a static class method of `GuzzleHttp\Stream\Stream`. ## Metadata streams `GuzzleHttp\Stream\MetadataStreamInterface` has been added to denote streams that contain additional metadata accessible via `getMetadata()`. `GuzzleHttp\Stream\StreamInterface::getMetadata` and `GuzzleHttp\Stream\StreamInterface::setMetadata` have been removed. ## StreamRequestFactory The entire concept of the StreamRequestFactory has been removed. The way this was used in Guzzle 3 broke the actual interface of sending streaming requests (instead of getting back a Response, you got a StreamInterface). Streaming PHP requests are now implemented through the `GuzzleHttp\Adapter\StreamAdapter`. 3.6 to 3.7 ---------- ### Deprecations - You can now enable E_USER_DEPRECATED warnings to see if you are using any deprecated methods.: ```php \Guzzle\Common\Version::$emitWarnings = true; ``` The following APIs and options have been marked as deprecated: - Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use `$request->getResponseBody()->isRepeatable()` instead. - Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. - Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. - Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead. - Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead. - Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated - Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client. - Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8. - Marked `Guzzle\Common\Collection::inject()` as deprecated. - Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use `$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` or `$client->setDefaultOption('auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` 3.7 introduces `request.options` as a parameter for a client configuration and as an optional argument to all creational request methods. When paired with a client's configuration settings, these options allow you to specify default settings for various aspects of a request. Because these options make other previous configuration options redundant, several configuration options and methods of a client and AbstractCommand have been deprecated. - Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use `$client->getDefaultOption('headers')`. - Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use `$client->setDefaultOption('headers/{header_name}', 'value')`. - Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use `$client->setDefaultOption('params/{param_name}', 'value')` - Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0 $command = $client->getCommand('foo', array( 'command.headers' => array('Test' => '123'), 'command.response_body' => '/path/to/file' )); // Should be changed to: $command = $client->getCommand('foo', array( 'command.request_options' => array( 'headers' => array('Test' => '123'), 'save_as' => '/path/to/file' ) )); ### Interface changes Additions and changes (you will need to update any implementations or subclasses you may have created): - Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`: createRequest, head, delete, put, patch, post, options, prepareRequest - Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()` - Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface` - Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a resource, string, or EntityBody into the $options parameter to specify the download location of the response. - Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a default `array()` - Added `Guzzle\Stream\StreamInterface::isRepeatable` - Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods. The following methods were removed from interfaces. All of these methods are still available in the concrete classes that implement them, but you should update your code to use alternative methods: - Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use `$client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or `$client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))` or `$client->setDefaultOption('headers/{header_name}', 'value')`. or `$client->setDefaultOption('headers', array('header_name' => 'value'))`. - Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use `$client->getConfig()->getPath('request.options/headers')`. - Removed `Guzzle\Http\ClientInterface::expandTemplate()`. This is an implementation detail. - Removed `Guzzle\Http\ClientInterface::setRequestFactory()`. This is an implementation detail. - Removed `Guzzle\Http\ClientInterface::getCurlMulti()`. This is a very specific implementation detail. - Removed `Guzzle\Http\Message\RequestInterface::canCache`. Use the CachePlugin. - Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`. Use the HistoryPlugin. - Removed `Guzzle\Http\Message\RequestInterface::isRedirect`. Use the HistoryPlugin. ### Cache plugin breaking changes - CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a CacheStorageInterface. These two objects and interface will be removed in a future version. - Always setting X-cache headers on cached responses - Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin - `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface $request, Response $response);` - `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);` - `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);` - Added `CacheStorageInterface::purge($url)` - `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin $plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache, CanCacheStrategyInterface $canCache = null)` - Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)` 3.5 to 3.6 ---------- * Mixed casing of headers are now forced to be a single consistent casing across all values for that header. * Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution * Removed the whole changedHeader() function system of messages because all header changes now go through addHeader(). For example, setHeader() first removes the header using unset on a HeaderCollection and then calls addHeader(). Keeping the Host header and URL host in sync is now handled by overriding the addHeader method in Request. * Specific header implementations can be created for complex headers. When a message creates a header, it uses a HeaderFactory which can map specific headers to specific header classes. There is now a Link header and CacheControl header implementation. * Moved getLinks() from Response to just be used on a Link header object. If you previously relied on Guzzle\Http\Message\Header::raw(), then you will need to update your code to use the HeaderInterface (e.g. toArray(), getAll(), etc.). ### Interface changes * Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate * Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti() * Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in Guzzle\Http\Curl\RequestMediator * Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string. * Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface * Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders() ### Removed deprecated functions * Removed Guzzle\Parser\ParserRegister::get(). Use getParser() * Removed Guzzle\Parser\ParserRegister::set(). Use registerParser(). ### Deprecations * The ability to case-insensitively search for header values * Guzzle\Http\Message\Header::hasExactHeader * Guzzle\Http\Message\Header::raw. Use getAll() * Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object instead. ### Other changes * All response header helper functions return a string rather than mixing Header objects and strings inconsistently * Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle directly via interfaces * Removed the injecting of a request object onto a response object. The methods to get and set a request still exist but are a no-op until removed. * Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a `Guzzle\Service\Command\ArrayCommandInterface`. * Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response on a request while the request is still being transferred * `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess 3.3 to 3.4 ---------- Base URLs of a client now follow the rules of https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.2 when merging URLs. 3.2 to 3.3 ---------- ### Response::getEtag() quote stripping removed `Guzzle\Http\Message\Response::getEtag()` no longer strips quotes around the ETag response header ### Removed `Guzzle\Http\Utils` The `Guzzle\Http\Utils` class was removed. This class was only used for testing. ### Stream wrapper and type `Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getStreamType()` are no longer converted to lowercase. ### curl.emit_io became emit_io Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io' 3.1 to 3.2 ---------- ### CurlMulti is no longer reused globally Before 3.2, the same CurlMulti object was reused globally for each client. This can cause issue where plugins added to a single client can pollute requests dispatched from other clients. If you still wish to reuse the same CurlMulti object with each client, then you can add a listener to the ServiceBuilder's `service_builder.create_client` event to inject a custom CurlMulti object into each client as it is created. ```php $multi = new Guzzle\Http\Curl\CurlMulti(); $builder = Guzzle\Service\Builder\ServiceBuilder::factory('/path/to/config.json'); $builder->addListener('service_builder.create_client', function ($event) use ($multi) { $event['client']->setCurlMulti($multi); } }); ``` ### No default path URLs no longer have a default path value of '/' if no path was specified. Before: ```php $request = $client->get('http://www.foo.com'); echo $request->getUrl(); // >> http://www.foo.com/ ``` After: ```php $request = $client->get('http://www.foo.com'); echo $request->getUrl(); // >> http://www.foo.com ``` ### Less verbose BadResponseException The exception message for `Guzzle\Http\Exception\BadResponseException` no longer contains the full HTTP request and response information. You can, however, get access to the request and response object by calling `getRequest()` or `getResponse()` on the exception object. ### Query parameter aggregation Multi-valued query parameters are no longer aggregated using a callback function. `Guzzle\Http\Query` now has a setAggregator() method that accepts a `Guzzle\Http\QueryAggregator\QueryAggregatorInterface` object. This object is responsible for handling the aggregation of multi-valued query string variables into a flattened hash. 2.8 to 3.x ---------- ### Guzzle\Service\Inspector Change `\Guzzle\Service\Inspector::fromConfig` to `\Guzzle\Common\Collection::fromConfig` **Before** ```php use Guzzle\Service\Inspector; class YourClient extends \Guzzle\Service\Client { public static function factory($config = array()) { $default = array(); $required = array('base_url', 'username', 'api_key'); $config = Inspector::fromConfig($config, $default, $required); $client = new self( $config->get('base_url'), $config->get('username'), $config->get('api_key') ); $client->setConfig($config); $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json')); return $client; } ``` **After** ```php use Guzzle\Common\Collection; class YourClient extends \Guzzle\Service\Client { public static function factory($config = array()) { $default = array(); $required = array('base_url', 'username', 'api_key'); $config = Collection::fromConfig($config, $default, $required); $client = new self( $config->get('base_url'), $config->get('username'), $config->get('api_key') ); $client->setConfig($config); $client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json')); return $client; } ``` ### Convert XML Service Descriptions to JSON **Before** ```xml Get a list of groups Uses a search query to get a list of groups Create a group Delete a group by ID Update a group ``` **After** ```json { "name": "Zendesk REST API v2", "apiVersion": "2012-12-31", "description":"Provides access to Zendesk views, groups, tickets, ticket fields, and users", "operations": { "list_groups": { "httpMethod":"GET", "uri": "groups.json", "summary": "Get a list of groups" }, "search_groups":{ "httpMethod":"GET", "uri": "search.json?query=\"{query} type:group\"", "summary": "Uses a search query to get a list of groups", "parameters":{ "query":{ "location": "uri", "description":"Zendesk Search Query", "type": "string", "required": true } } }, "create_group": { "httpMethod":"POST", "uri": "groups.json", "summary": "Create a group", "parameters":{ "data": { "type": "array", "location": "body", "description":"Group JSON", "filters": "json_encode", "required": true }, "Content-Type":{ "type": "string", "location":"header", "static": "application/json" } } }, "delete_group": { "httpMethod":"DELETE", "uri": "groups/{id}.json", "summary": "Delete a group", "parameters":{ "id":{ "location": "uri", "description":"Group to delete by ID", "type": "integer", "required": true } } }, "get_group": { "httpMethod":"GET", "uri": "groups/{id}.json", "summary": "Get a ticket", "parameters":{ "id":{ "location": "uri", "description":"Group to get by ID", "type": "integer", "required": true } } }, "update_group": { "httpMethod":"PUT", "uri": "groups/{id}.json", "summary": "Update a group", "parameters":{ "id": { "location": "uri", "description":"Group to update by ID", "type": "integer", "required": true }, "data": { "type": "array", "location": "body", "description":"Group JSON", "filters": "json_encode", "required": true }, "Content-Type":{ "type": "string", "location":"header", "static": "application/json" } } } } ``` ### Guzzle\Service\Description\ServiceDescription Commands are now called Operations **Before** ```php use Guzzle\Service\Description\ServiceDescription; $sd = new ServiceDescription(); $sd->getCommands(); // @returns ApiCommandInterface[] $sd->hasCommand($name); $sd->getCommand($name); // @returns ApiCommandInterface|null $sd->addCommand($command); // @param ApiCommandInterface $command ``` **After** ```php use Guzzle\Service\Description\ServiceDescription; $sd = new ServiceDescription(); $sd->getOperations(); // @returns OperationInterface[] $sd->hasOperation($name); $sd->getOperation($name); // @returns OperationInterface|null $sd->addOperation($operation); // @param OperationInterface $operation ``` ### Guzzle\Common\Inflection\Inflector Namespace is now `Guzzle\Inflection\Inflector` ### Guzzle\Http\Plugin Namespace is now `Guzzle\Plugin`. Many other changes occur within this namespace and are detailed in their own sections below. ### Guzzle\Http\Plugin\LogPlugin and Guzzle\Common\Log Now `Guzzle\Plugin\Log\LogPlugin` and `Guzzle\Log` respectively. **Before** ```php use Guzzle\Common\Log\ClosureLogAdapter; use Guzzle\Http\Plugin\LogPlugin; /** @var \Guzzle\Http\Client */ $client; // $verbosity is an integer indicating desired message verbosity level $client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $verbosity = LogPlugin::LOG_VERBOSE); ``` **After** ```php use Guzzle\Log\ClosureLogAdapter; use Guzzle\Log\MessageFormatter; use Guzzle\Plugin\Log\LogPlugin; /** @var \Guzzle\Http\Client */ $client; // $format is a string indicating desired message format -- @see MessageFormatter $client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $format = MessageFormatter::DEBUG_FORMAT); ``` ### Guzzle\Http\Plugin\CurlAuthPlugin Now `Guzzle\Plugin\CurlAuth\CurlAuthPlugin`. ### Guzzle\Http\Plugin\ExponentialBackoffPlugin Now `Guzzle\Plugin\Backoff\BackoffPlugin`, and other changes. **Before** ```php use Guzzle\Http\Plugin\ExponentialBackoffPlugin; $backoffPlugin = new ExponentialBackoffPlugin($maxRetries, array_merge( ExponentialBackoffPlugin::getDefaultFailureCodes(), array(429) )); $client->addSubscriber($backoffPlugin); ``` **After** ```php use Guzzle\Plugin\Backoff\BackoffPlugin; use Guzzle\Plugin\Backoff\HttpBackoffStrategy; // Use convenient factory method instead -- see implementation for ideas of what // you can do with chaining backoff strategies $backoffPlugin = BackoffPlugin::getExponentialBackoff($maxRetries, array_merge( HttpBackoffStrategy::getDefaultFailureCodes(), array(429) )); $client->addSubscriber($backoffPlugin); ``` ### Known Issues #### [BUG] Accept-Encoding header behavior changed unintentionally. (See #217) (Fixed in 09daeb8c666fb44499a0646d655a8ae36456575e) In version 2.8 setting the `Accept-Encoding` header would set the CURLOPT_ENCODING option, which permitted cURL to properly handle gzip/deflate compressed responses from the server. In versions affected by this bug this does not happen. See issue #217 for a workaround, or use a version containing the fix. { "name": "guzzlehttp/guzzle", "description": "Guzzle is a PHP HTTP client library", "license": "MIT", "keywords": [ "framework", "http", "rest", "web service", "curl", "client", "HTTP client", "PSR-7", "PSR-18" ], "authors": [ { "name": "Graham Campbell", "email": "hello@gjcampbell.co.uk", "homepage": "https://github.com/GrahamCampbell" }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "Jeremy Lindblom", "email": "jeremeamia@gmail.com", "homepage": "https://github.com/jeremeamia" }, { "name": "George Mponos", "email": "gmponos@gmail.com", "homepage": "https://github.com/gmponos" }, { "name": "Tobias Nyholm", "email": "tobias.nyholm@gmail.com", "homepage": "https://github.com/Nyholm" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", "homepage": "https://github.com/sagikazarmark" }, { "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" } ], "require": { "php": "^7.2.5 || ^8.0", "ext-json": "*", "guzzlehttp/promises": "^2.5.2", "guzzlehttp/psr7": "^2.13", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", "symfony/polyfill-php80": "^1.25" }, "require-dev": { "ext-curl": "*", "bamarni/composer-bin-plugin": "^1.8.2", "guzzle/client-integration-tests": "3.0.3", "guzzlehttp/test-server": "^0.7", "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "provide": { "psr/http-client-implementation": "1.0" }, "suggest": { "ext-curl": "Required for CURL handler support", "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "repositories": [ { "type": "package", "package": { "name": "guzzle/client-integration-tests", "version": "v3.0.3", "require": { "guzzlehttp/psr7": "^1.7 || ^2.0", "php": "^7.2.5 || ^8.0", "php-http/message": "^1.0 || ^2.0", "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.11", "th3n3rd/cartesian-product": "^0.3" }, "autoload": { "psr-4": { "Http\\Client\\Tests\\": "src/" } }, "bin": [ "bin/http_test_server" ], "dist": { "type": "zip", "url": "https://codeload.github.com/guzzle/client-integration-tests/zip/30edbabe49dedd95e3f21d8a25438f767b653d75" } } } ], "autoload": { "psr-4": { "GuzzleHttp\\": "src/" }, "files": [ "src/functions_include.php" ] }, "autoload-dev": { "psr-4": { "GuzzleHttp\\Tests\\": "tests/" } }, "config": { "allow-plugins": { "bamarni/composer-bin-plugin": true }, "preferred-install": "dist", "sort-packages": true }, "extra": { "bamarni-bin": { "bin-links": true, "forward-command": false } } } truncateAt = $truncateAt; } /** * Returns a summarized message body. */ public function summarize(MessageInterface $message): ?string { return $this->truncateAt === null ? Psr7\Message::bodySummary($message) : Psr7\Message::bodySummary($message, $this->truncateAt); } } 'http://www.foo.com/1.0/', * 'timeout' => 0, * 'allow_redirects' => false, * 'proxy' => '192.168.16.1:10' * ]); * * Client configuration settings include the following options: * * - handler: (callable) Function that transfers HTTP requests over the * wire. The function is called with a Psr7\Http\Message\RequestInterface * and array of transfer options, and must return a * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a * Psr7\Http\Message\ResponseInterface on success. * If no handler is provided, a default handler will be created * that enables all of the request options below by attaching all of the * default middleware to the handler. * - base_uri: (string|UriInterface) Base URI of the client that is merged * into relative URIs. Can be a string or instance of UriInterface. * - transport_sharing: (string|null) Transport sharing mode for the * default handler. Accepts TransportSharing::* or null. Defaults to null. * - max_host_connections: (int|null) Maximum concurrent connections per * host, applied by the default CurlMultiHandler. The default stream * fallback receives the cap as a marker only: it rejects enabled * response streaming ("stream" => true) and does not limit overlapping * buffered calls. * - max_total_connections: (int|null) Maximum concurrent connections * overall, applied by the default CurlMultiHandler. The default stream * fallback receives the cap as a marker only: it rejects enabled * response streaming ("stream" => true) and does not limit overlapping * buffered calls. * - multiplex: (string|null) Multiplexing::NONE to disable multiplexing on * the default CurlMultiHandler; the value also becomes the default * "multiplex" request option. Other Multiplexing::* values act as the * default request option only. * - **: any request option * * @param array $config Client configuration settings. * * @see RequestOptions for a list of available request options. */ public function __construct(array $config = []) { $handlerOptions = []; foreach (['max_host_connections', 'max_total_connections'] as $capOption) { if (\array_key_exists($capOption, $config)) { if ($config[$capOption] !== null) { $handlerOptions[$capOption] = $config[$capOption]; } unset($config[$capOption]); } } // Deliberately not unset: the value also becomes the default // "multiplex" request option, which the configured handler accepts. $handlerMultiplex = ($config['multiplex'] ?? null) === Multiplexing::NONE; $transportSharing = \array_key_exists('transport_sharing', $config) ? $config['transport_sharing'] : null; $transportSharingMode = CurlShareHandleState::normalizeMode($transportSharing, 'transport_sharing'); unset($config['transport_sharing']); if (!isset($config['handler'])) { if ($transportSharingMode !== TransportSharing::NONE) { $handlerOptions['transport_sharing'] = $transportSharingMode; } if ($handlerMultiplex) { $handlerOptions['multiplex'] = Multiplexing::NONE; } $config['handler'] = $handlerOptions === [] ? HandlerStack::create() : HandlerStack::create(Utils::chooseHandler($handlerOptions)); } elseif (!\is_callable($config['handler'])) { throw new InvalidArgumentException('handler must be a callable'); } elseif ($handlerOptions !== []) { throw new InvalidArgumentException('The "max_host_connections" and "max_total_connections" client options require Guzzle to create the default handler. Configure the options on the CurlMultiHandler constructor to apply numeric connection caps, or on the StreamHandler constructor to reject enabled response streaming, when providing a custom handler.'); } elseif ($transportSharingMode === TransportSharing::HANDLER_REQUIRE) { throw new InvalidArgumentException('The "transport_sharing" client option can only require sharing when Guzzle creates the default handler. Configure the "transport_sharing" option on CurlHandler or CurlMultiHandler when providing a custom cURL handler.'); } // Convert the base_uri to a UriInterface if (isset($config['base_uri'])) { $config['base_uri'] = Psr7\Utils::uriFor($config['base_uri']); } $this->configureDefaults($config); } /** * @param string $method * @param array $args * * @return PromiseInterface|ResponseInterface * * @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0. */ public function __call($method, $args) { \trigger_deprecation('guzzlehttp/guzzle', '7.1', '%s::%s() is deprecated and will be removed in 8.0.', __CLASS__, __FUNCTION__); if (\count($args) < 1) { throw new InvalidArgumentException('Magic request methods require a URI and optional options array'); } $uri = $args[0]; $opts = $args[1] ?? []; $isAsync = \substr($method, -5) === 'Async'; $method = $isAsync ? \substr($method, 0, -5) : $method; $method = Psr7\Utils::asciiToUpper($method); return $isAsync ? $this->requestAsync($method, $uri, $opts) : $this->request($method, $uri, $opts); } /** * Asynchronously send an HTTP request. * * @param array $options Request options to apply to the given * request and to the transfer. See {@see RequestOptions}. */ public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface { // Merge the base URI into the request URI if needed. $options = $this->prepareDefaults($options); return $this->transfer( $request->withUri($this->buildUri($request->getUri(), $options), self::shouldPreserveHost($request)), $options ); } /** * Send an HTTP request. * * @param array $options Request options to apply to the given * request and to the transfer. See {@see RequestOptions}. * * @throws GuzzleException */ public function send(RequestInterface $request, array $options = []): ResponseInterface { $options[RequestOptions::SYNCHRONOUS] = true; return $this->sendAsync($request, $options)->wait(); } /** * The HttpClient PSR (PSR-18) specify this method. * * {@inheritDoc} */ public function sendRequest(RequestInterface $request): ResponseInterface { $options[RequestOptions::SYNCHRONOUS] = true; $options[RequestOptions::ALLOW_REDIRECTS] = false; $options[RequestOptions::HTTP_ERRORS] = false; return $this->sendAsync($request, $options)->wait(); } /** * Create and send an asynchronous HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string $method HTTP method * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. See {@see RequestOptions}. */ public function requestAsync(string $method, $uri = '', array $options = []): PromiseInterface { $normalizedMethod = Psr7\Utils::asciiToUpper($method); if ($method !== $normalizedMethod) { \trigger_deprecation( 'guzzlehttp/guzzle', '7.11', 'Passing a non-uppercase HTTP method to Client::requestAsync() is deprecated; guzzlehttp/guzzle 8.0 will preserve HTTP method casing. Pass an uppercase method explicitly if uppercase is required.' ); $method = $normalizedMethod; } $options = $this->prepareDefaults($options); // Remove request modifying parameter because it can be done up-front. $headers = $options['headers'] ?? []; $droppedHeaderNames = self::castDeprecatedHeaderOptionValues($headers); if ($droppedHeaderNames !== [] && isset($options['_conditional'])) { $options['_conditional'] = Psr7\Utils::caselessRemove($droppedHeaderNames, $options['_conditional']); } $body = $options['body'] ?? null; $version = self::normalizeProtocolVersion($options['version'] ?? '1.1'); // Merge the URI into the base URI. $uri = $this->buildUri(Psr7\Utils::uriFor($uri), $options); if (\is_array($body)) { throw $this->invalidBody(); } $body = self::createBodyStream($body); $request = new Psr7\Request($method, $uri, $headers, $body, $version); // Remove the option so that they are not doubly-applied. unset($options['headers'], $options['body'], $options['version']); return $this->transfer($request, $options); } /** * Create and send an HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string $method HTTP method. * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. See {@see RequestOptions}. * * @throws GuzzleException */ public function request(string $method, $uri = '', array $options = []): ResponseInterface { $normalizedMethod = Psr7\Utils::asciiToUpper($method); if ($method !== $normalizedMethod) { \trigger_deprecation( 'guzzlehttp/guzzle', '7.11', 'Passing a non-uppercase HTTP method to Client::request() is deprecated; guzzlehttp/guzzle 8.0 will preserve HTTP method casing. Pass an uppercase method explicitly if uppercase is required.' ); $method = $normalizedMethod; } $options[RequestOptions::SYNCHRONOUS] = true; return $this->requestAsync($method, $uri, $options)->wait(); } /** * Get a client configuration option. * * These options include default request options of the client, a "handler" * (if utilized by the concrete client), and a "base_uri" if utilized by * the concrete client. * * @param string|null $option The config option to retrieve. * * @return mixed */ public function getConfig(?string $option = null) { return $option === null ? $this->config : ($this->config[$option] ?? null); } private function buildUri(UriInterface $uri, array $config): UriInterface { if (isset($config['base_uri'])) { $uri = Psr7\UriResolver::resolve(Psr7\Utils::uriFor($config['base_uri']), $uri); } $idnOptions = Utils::normalizeIdnConversionOption($config['idn_conversion'] ?? null); if ($idnOptions !== null) { $uri = Utils::idnUriConvert($uri, $idnOptions); } if ($uri->getScheme() === '' && $uri->getHost() !== '') { $uri = $uri->withScheme('http'); } return $uri; } /** * Whether to preserve an existing Host header when the URI changes. * * A header matching the current URI carries no explicit override and is * regenerated after base URI resolution or IDN conversion. Other values * are preserved as deliberate overrides, as PSR-7 requires. */ private static function shouldPreserveHost(RequestInterface $request): bool { if (!$request->hasHeader('Host')) { return false; } $uri = $request->getUri(); $host = $uri->getHost(); $port = $uri->getPort(); if ($port !== null) { $host .= ':'.$port; } return $host !== $request->getHeaderLine('Host'); } /** * Configures the default options for a client. */ private function configureDefaults(array $config): void { $defaults = [ 'allow_redirects' => RedirectMiddleware::$defaultSettings, 'http_errors' => true, 'decode_content' => true, 'verify' => true, 'cookies' => false, 'idn_conversion' => false, 'protocols' => ['http', 'https'], ]; // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. // We can only trust the HTTP_PROXY environment variable in a CLI // process due to the fact that PHP has no reliable mechanism to // get environment variables that start with "HTTP_". if (\PHP_SAPI === 'cli' && ($proxy = Utils::getenv('HTTP_PROXY'))) { $defaults['proxy']['http'] = $proxy; } if ($proxy = Utils::getenv('HTTPS_PROXY')) { $defaults['proxy']['https'] = $proxy; } if ($noProxy = Utils::getenv('NO_PROXY')) { $cleanedNoProxy = \str_replace(' ', '', $noProxy); $defaults['proxy']['no'] = \explode(',', $cleanedNoProxy); } $this->config = $config + $defaults; if (!empty($config['cookies']) && $config['cookies'] === true) { $this->config['cookies'] = new CookieJar(); } // Add the default user-agent header. if (!isset($this->config['headers'])) { $this->config['headers'] = ['User-Agent' => Utils::defaultUserAgent()]; } else { // Add the User-Agent header if one was not already set. $hasUserAgent = false; foreach (\array_keys($this->config['headers']) as $name) { if (Psr7\Utils::asciiToLower((string) $name) === 'user-agent') { $hasUserAgent = true; break; } } if (!$hasUserAgent) { $this->config['headers']['User-Agent'] = Utils::defaultUserAgent(); } } if (\is_array($this->config['headers'])) { self::warnAboutInvalidHeaderOptionTypes($this->config['headers']); self::castDeprecatedHeaderOptionValues($this->config['headers']); } } /** * Merges default options into the array. * * @param array $options Options to modify by reference */ private function prepareDefaults(array $options): array { self::warnAboutRequestLevelHandler($options); $defaults = $this->config; if (!empty($defaults['headers'])) { // Default headers are only added if they are not present. $defaults['_conditional'] = $defaults['headers']; unset($defaults['headers']); } // Special handling for headers is required as they are added as // conditional headers and as headers passed to a request ctor. if (\array_key_exists('headers', $options)) { // Allows default headers to be unset. if ($options['headers'] === null) { $defaults['_conditional'] = []; unset($options['headers']); } elseif (!\is_array($options['headers'])) { throw new InvalidArgumentException('headers must be an array'); } } // Shallow merge defaults underneath options. $result = $options + $defaults; // Remove null values. foreach ($result as $k => $v) { if ($v === null) { unset($result[$k]); } } self::warnAboutInvalidRequestOptionTypes($result); return self::normalizeDeprecatedRequestOptionValues($result); } /** * Normalize values that guzzlehttp/guzzle 8.0 rejects only after the * corresponding 7.x deprecation has already been emitted. * * @param array $options * * @return array */ private static function normalizeDeprecatedRequestOptionValues(array $options): array { self::normalizeDeprecatedAuthOptionValues($options); self::normalizeDeprecatedTlsFileOptionValues($options, 'cert'); self::normalizeDeprecatedTlsFileOptionValues($options, 'ssl_key'); self::normalizeDeprecatedStringOptionValues($options); self::normalizeDeprecatedNumericOptionValues($options); self::normalizeDeprecatedIntegerOptionValues($options); return $options; } /** * @param mixed $value */ private static function canStringifyDeprecatedValue($value): bool { return $value === null || \is_scalar($value) || (\is_object($value) && \method_exists($value, '__toString')); } /** * @param mixed $value */ private static function stringifyDeprecatedValue($value): string { if (\is_float($value) && !\is_finite($value)) { return \is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF'); } if ($value === null) { return ''; } if (\is_scalar($value)) { return (string) $value; } if (\is_object($value) && \method_exists($value, '__toString')) { return $value->__toString(); } throw new \LogicException('Value is not stringable.'); } /** * @param array $options */ private static function normalizeDeprecatedAuthOptionValues(array &$options): void { if (!isset($options['auth']) || !\is_array($options['auth']) || $options['auth'] === []) { return; } foreach ([0, 1] as $index) { if ( \array_key_exists($index, $options['auth']) && !\is_string($options['auth'][$index]) && self::canStringifyDeprecatedValue($options['auth'][$index]) ) { $options['auth'][$index] = self::stringifyDeprecatedValue($options['auth'][$index]); } } if ( \array_key_exists(2, $options['auth']) && $options['auth'][2] !== null && !\is_string($options['auth'][2]) && self::canStringifyDeprecatedValue($options['auth'][2]) ) { $options['auth'][2] = self::stringifyDeprecatedValue($options['auth'][2]); } } /** * @param array $options */ private static function normalizeDeprecatedTlsFileOptionValues(array &$options, string $option): void { if (!isset($options[$option]) || !\is_array($options[$option])) { return; } foreach ([0, 1] as $index) { if ( \array_key_exists($index, $options[$option]) && $options[$option][$index] !== null && !\is_string($options[$option][$index]) && self::canStringifyDeprecatedValue($options[$option][$index]) ) { $options[$option][$index] = self::stringifyDeprecatedValue($options[$option][$index]); } } } /** * @param array $options */ private static function normalizeDeprecatedStringOptionValues(array &$options): void { foreach (['cert_type', 'force_ip_resolve', 'ssl_key_type'] as $option) { if ( \array_key_exists($option, $options) && !\is_string($options[$option]) && self::canStringifyDeprecatedValue($options[$option]) ) { $options[$option] = self::stringifyDeprecatedValue($options[$option]); } } } /** * @param array $options */ private static function normalizeDeprecatedNumericOptionValues(array &$options): void { foreach (['connect_timeout', 'delay', 'read_timeout', 'timeout'] as $option) { if ( \array_key_exists($option, $options) && \is_string($options[$option]) && \is_numeric($options[$option]) ) { $options[$option] = $options[$option] + 0; } } } /** * @param array $options */ private static function normalizeDeprecatedIntegerOptionValues(array &$options): void { foreach (['crypto_method', 'crypto_method_max', 'retries'] as $option) { if (!\array_key_exists($option, $options)) { continue; } if (\is_string($options[$option]) && \preg_match('/^-?\d+$/D', $options[$option]) === 1) { $options[$option] = (int) $options[$option]; } elseif ( \is_float($options[$option]) && \is_finite($options[$option]) && $options[$option] === (float) (int) $options[$option] ) { $options[$option] = (int) $options[$option]; } } } private static function warnAboutRequestLevelHandler(array $options): void { if (!\array_key_exists('handler', $options)) { return; } \trigger_deprecation( 'guzzlehttp/guzzle', '7.12', 'Passing the "handler" request option is deprecated; guzzlehttp/guzzle 8.0 will ignore request-level handlers. Configure the handler when creating the Client, or use a separate Client instance for requests that need a different handler.' ); } private static function warnAboutInvalidRequestOptionTypes(array $options): void { if (isset($options['handler']) && !\is_callable($options['handler'])) { self::warnInvalidRequestOptionType('handler', 'callable', $options['handler']); } if (isset($options['allow_redirects']) && \is_array($options['allow_redirects'])) { self::warnAboutInvalidAllowRedirectsOptionTypes($options['allow_redirects']); } elseif (isset($options['allow_redirects']) && !\is_bool($options['allow_redirects'])) { self::warnInvalidRequestOptionType('allow_redirects', 'bool|array', $options['allow_redirects'], '7.13'); } if (isset($options['auth'])) { self::warnAboutInvalidAuthOptionTypes($options['auth']); } if (isset($options['body']) && \is_array($options['body'])) { self::warnInvalidRequestOptionType('body', 'resource|string|null|int|float|bool|StreamInterface|(callable&object)|\Iterator|\Stringable', $options['body']); } self::warnAboutInvalidTlsFileOptionTypes($options, 'cert'); self::warnIfPresentAndNotString($options, 'cert_type'); self::warnIfPresentAndNotNumber($options, 'connect_timeout'); self::warnIfPresentAndNotInt($options, 'crypto_method'); self::warnIfPresentAndNotInt($options, 'crypto_method_max', null, '7.13'); self::warnIfPresentAndNotBoolOrResource($options, 'debug'); self::warnIfPresentAndNotBoolOrString($options, 'decode_content'); self::warnIfPresentAndNotNumber($options, 'delay'); if (isset($options['delay']) && \is_numeric($options['delay'])) { $delay = (float) $options['delay']; if (!\is_finite($delay) || $delay < 0.0) { self::warnInvalidRequestOptionType('delay', 'finite int|float greater than or equal to 0', $options['delay'], '7.13'); } } self::warnIfPresentAndNotBoolOrInt($options, 'expect'); if (isset($options['form_params'])) { self::warnAboutInvalidFormParamTypes($options['form_params']); } if (isset($options['force_ip_resolve']) && !\is_string($options['force_ip_resolve'])) { self::warnInvalidRequestOptionType('force_ip_resolve', 'string', $options['force_ip_resolve']); } if ( isset($options['force_ip_resolve']) && \is_string($options['force_ip_resolve']) && $options['force_ip_resolve'] !== 'v4' && $options['force_ip_resolve'] !== 'v6' ) { self::warnInvalidRequestOptionType('force_ip_resolve', '"v4"|"v6"', $options['force_ip_resolve'], '7.13'); } if (isset($options['headers'])) { self::warnAboutInvalidHeaderOptionTypes($options['headers']); } self::warnIfPresentAndNotBool($options, 'http_errors'); if (isset($options['multipart'])) { self::warnAboutInvalidMultipartOptionTypes($options['multipart']); } self::warnIfPresentAndNotCallable($options, 'on_headers'); self::warnIfPresentAndNotCallable($options, 'on_stats'); self::warnIfPresentAndNotCallable($options, 'on_trailers', null, '7.14'); self::warnIfPresentAndNotCallable($options, 'progress'); self::warnIfPresentAndNotStringArray($options, 'protocols', true); self::warnAboutInvalidProtocolValues($options, 'protocols'); self::warnAboutInvalidProxyOptionTypes($options); self::warnIfPresentAndNotNumber($options, 'read_timeout'); self::warnIfPresentAndNotInt($options, 'retries'); if (isset($options['sink']) && !\is_bool($options['sink']) && !\is_resource($options['sink']) && !\is_string($options['sink']) && !$options['sink'] instanceof StreamInterface) { self::warnInvalidRequestOptionType('sink', 'resource|string|StreamInterface', $options['sink']); } self::warnAboutInvalidTlsFileOptionTypes($options, 'ssl_key'); self::warnIfPresentAndNotString($options, 'ssl_key_type'); self::warnIfPresentAndNotBool($options, 'stream'); self::warnIfPresentAndNotArray($options, 'stream_context', 'array'); self::warnIfPresentAndNotBool($options, 'synchronous'); self::warnIfPresentAndNotNumber($options, 'timeout'); self::warnIfPresentAndNotBoolOrString($options, 'verify'); self::warnIfPresentAndNotStringOrNumber($options, 'version'); self::warnIfPresentAndNotArray($options, 'curl', 'array'); if (isset($options['cookies']) && $options['cookies'] === true) { self::warnInvalidRequestOptionType('cookies', 'false|CookieJarInterface', $options['cookies']); } if ( isset($options['cookies']) && $options['cookies'] !== false && $options['cookies'] !== true && !($options['cookies'] instanceof CookieJarInterface) ) { self::warnInvalidRequestOptionType('cookies', 'false|CookieJarInterface', $options['cookies'], '7.13'); } } private static function warnAboutInvalidAllowRedirectsOptionTypes(array $allowRedirects): void { self::warnIfPresentAndNotInt($allowRedirects, 'max', 'allow_redirects.max'); self::warnIfPresentAndNotBool($allowRedirects, 'strict', 'allow_redirects.strict'); self::warnIfPresentAndNotBool($allowRedirects, 'referer', 'allow_redirects.referer'); self::warnIfPresentAndNotStringArray($allowRedirects, 'protocols', true, 'allow_redirects.protocols'); self::warnAboutInvalidProtocolValues($allowRedirects, 'protocols', 'allow_redirects.protocols'); self::warnIfPresentAndNotCallable($allowRedirects, 'on_redirect', 'allow_redirects.on_redirect'); self::warnIfPresentAndNotBool($allowRedirects, 'track_redirects', 'allow_redirects.track_redirects'); } /** * @param mixed $auth */ private static function warnAboutInvalidAuthOptionTypes($auth): void { if ($auth === false || \is_string($auth) || $auth === []) { return; } if (!\is_array($auth)) { self::warnInvalidRequestOptionType('auth', 'array{0: string, 1: string, 2?: string|null}|string|false|null', $auth); return; } if (!\array_key_exists(0, $auth) || !\is_string($auth[0])) { self::warnInvalidRequestOptionType('auth.0', 'string', $auth[0] ?? null); } if (!\array_key_exists(1, $auth) || !\is_string($auth[1])) { self::warnInvalidRequestOptionType('auth.1', 'string', $auth[1] ?? null); } if (\array_key_exists(2, $auth) && $auth[2] !== null && !\is_string($auth[2])) { self::warnInvalidRequestOptionType('auth.2', 'string|null', $auth[2]); } } /** * @param mixed $value */ private static function warnAboutInvalidFormParamTypes($value): void { if (!\is_array($value)) { self::warnInvalidRequestOptionType('form_params', 'array', $value); return; } self::warnAboutInvalidFormParamArray($value, 'form_params'); } private static function warnAboutInvalidFormParamArray(array $values, string $path): bool { foreach ($values as $key => $item) { $itemPath = $path.'.'.(string) $key; if (\is_array($item)) { if (!self::warnAboutInvalidFormParamArray($item, $itemPath)) { return false; } continue; } if ($item !== null && !\is_scalar($item)) { self::warnInvalidRequestOptionType($itemPath, 'string|int|float|bool|null|array', $item); return false; } } return true; } /** * @param mixed $headers */ private static function warnAboutInvalidHeaderOptionTypes($headers): void { if (!\is_array($headers)) { self::warnInvalidRequestOptionType('headers', 'array>|null', $headers); return; } foreach ($headers as $name => $value) { $path = 'headers.'.(string) $name; if (\is_array($value)) { if ($value === []) { self::warnInvalidRequestOptionType($path, 'string|non-empty-array', $value); break; } foreach ($value as $index => $item) { if (!\is_string($item)) { self::warnInvalidRequestOptionType($path.'.'.(string) $index, 'string', $item); break 2; } } } elseif (!\is_string($value)) { self::warnInvalidRequestOptionType($path, 'string|non-empty-array', $value); break; } } } /** * @param mixed $multipart */ private static function warnAboutInvalidMultipartOptionTypes($multipart): void { if (!\is_array($multipart)) { self::warnInvalidRequestOptionType('multipart', 'array, filename?: string}>', $multipart); return; } foreach ($multipart as $index => $part) { $path = 'multipart.'.(string) $index; if (!\is_array($part)) { self::warnInvalidRequestOptionType($path, 'array{name: string|int, contents: mixed, headers?: array, filename?: string}', $part); return; } if (!\array_key_exists('name', $part) || (!\is_string($part['name']) && !\is_int($part['name']))) { self::warnInvalidRequestOptionType($path.'.name', 'string|int', $part['name'] ?? null); } if (!\array_key_exists('contents', $part)) { self::warnInvalidRequestOptionType($path, 'array{name: string|int, contents: mixed, headers?: array, filename?: string}', $part); } if (\array_key_exists('headers', $part)) { if (!\is_array($part['headers'])) { self::warnInvalidRequestOptionType($path.'.headers', 'array', $part['headers']); } else { foreach ($part['headers'] as $name => $value) { if (!\is_string($value)) { self::warnInvalidRequestOptionType($path.'.headers.'.(string) $name, 'string', $value); break 2; } } } } if (\array_key_exists('filename', $part) && !\is_string($part['filename'])) { self::warnInvalidRequestOptionType($path.'.filename', 'string', $part['filename']); } } } private static function warnAboutInvalidProxyOptionTypes(array $options): void { if (!isset($options['proxy'])) { return; } if (!\is_string($options['proxy']) && !\is_array($options['proxy'])) { self::warnInvalidRequestOptionType('proxy', 'string|array{http?: string|null, https?: string|null, no?: string|array|null}', $options['proxy']); return; } if (!\is_array($options['proxy'])) { return; } foreach (['http', 'https'] as $scheme) { if (\array_key_exists($scheme, $options['proxy']) && $options['proxy'][$scheme] !== null && !\is_string($options['proxy'][$scheme])) { self::warnInvalidRequestOptionType('proxy.'.$scheme, 'string|null', $options['proxy'][$scheme]); } } if (!\array_key_exists('no', $options['proxy']) || $options['proxy']['no'] === null) { return; } if (\is_string($options['proxy']['no'])) { return; } if (!\is_array($options['proxy']['no'])) { self::warnInvalidRequestOptionType('proxy.no', 'string|array|null', $options['proxy']['no']); return; } foreach ($options['proxy']['no'] as $index => $noProxy) { if (!\is_string($noProxy)) { self::warnInvalidRequestOptionType('proxy.no.'.(string) $index, 'string', $noProxy); return; } } } private static function warnAboutInvalidTlsFileOptionTypes(array $options, string $option): void { if (!isset($options[$option])) { return; } if (\is_string($options[$option])) { return; } if (!\is_array($options[$option])) { self::warnInvalidRequestOptionType($option, 'string|array{0: string, 1?: string}', $options[$option]); return; } if (!\array_key_exists(0, $options[$option]) || !\is_string($options[$option][0])) { self::warnInvalidRequestOptionType($option.'.0', 'string', $options[$option][0] ?? null); } if (\array_key_exists(1, $options[$option]) && $options[$option][1] !== null && !\is_string($options[$option][1])) { self::warnInvalidRequestOptionType($option.'.1', 'string|null', $options[$option][1]); } } private static function warnIfPresentAndNotArray(array $options, string $option, string $expected): void { if (\array_key_exists($option, $options) && !\is_array($options[$option])) { self::warnInvalidRequestOptionType($option, $expected, $options[$option]); } } private static function warnIfPresentAndNotBool(array $options, string $option, ?string $path = null): void { if (\array_key_exists($option, $options) && !\is_bool($options[$option])) { self::warnInvalidRequestOptionType($path ?? $option, 'bool', $options[$option]); } } private static function warnIfPresentAndNotBoolOrInt(array $options, string $option): void { if (\array_key_exists($option, $options) && !\is_bool($options[$option]) && !\is_int($options[$option])) { self::warnInvalidRequestOptionType($option, 'bool|int', $options[$option]); } } private static function warnIfPresentAndNotBoolOrResource(array $options, string $option): void { if (\array_key_exists($option, $options) && !\is_bool($options[$option]) && !\is_resource($options[$option])) { self::warnInvalidRequestOptionType($option, 'bool|resource', $options[$option]); } } private static function warnIfPresentAndNotBoolOrString(array $options, string $option): void { if (\array_key_exists($option, $options) && !\is_bool($options[$option]) && !\is_string($options[$option])) { self::warnInvalidRequestOptionType($option, 'bool|string', $options[$option]); } } private static function warnIfPresentAndNotCallable( array $options, string $option, ?string $path = null, string $since = '7.11' ): void { if (\array_key_exists($option, $options) && !\is_callable($options[$option])) { self::warnInvalidRequestOptionType($path ?? $option, 'callable', $options[$option], $since); } } private static function warnIfPresentAndNotInt( array $options, string $option, ?string $path = null, string $since = '7.11' ): void { if (\array_key_exists($option, $options) && !\is_int($options[$option])) { self::warnInvalidRequestOptionType($path ?? $option, 'int', $options[$option], $since); } } private static function warnIfPresentAndNotNumber(array $options, string $option): void { if (\array_key_exists($option, $options) && !\is_int($options[$option]) && !\is_float($options[$option])) { self::warnInvalidRequestOptionType($option, 'int|float', $options[$option]); } } private static function warnIfPresentAndNotString(array $options, string $option): void { if (\array_key_exists($option, $options) && !\is_string($options[$option])) { self::warnInvalidRequestOptionType($option, 'string', $options[$option]); } } private static function warnIfPresentAndNotStringArray(array $options, string $option, bool $nonEmpty, ?string $path = null): void { if (!\array_key_exists($option, $options)) { return; } $path = $path ?? $option; $expected = ($nonEmpty ? 'non-empty-' : '').'array'; if (!\is_array($options[$option]) || ($nonEmpty && $options[$option] === [])) { self::warnInvalidRequestOptionType($path, $expected, $options[$option]); return; } foreach ($options[$option] as $index => $item) { if (!\is_string($item)) { self::warnInvalidRequestOptionType($path.'.'.(string) $index, 'string', $item); return; } } } /** * @param array $options */ private static function warnAboutInvalidProtocolValues(array $options, string $option, ?string $path = null): void { if (!isset($options[$option]) || !\is_array($options[$option])) { return; } $path = $path ?? $option; foreach ($options[$option] as $index => $protocol) { if (\is_string($protocol) && $protocol !== 'http' && $protocol !== 'https') { self::warnInvalidRequestOptionType($path.'.'.(string) $index, '"http"|"https"', $protocol, '7.13'); } } } private static function warnIfPresentAndNotStringOrNumber(array $options, string $option): void { if ( \array_key_exists($option, $options) && !\is_string($options[$option]) && !\is_int($options[$option]) && !\is_float($options[$option]) ) { self::warnInvalidRequestOptionType($option, 'string|int|float', $options[$option]); } } /** * @param mixed $value */ private static function warnInvalidRequestOptionType(string $option, string $expected, $value, string $since = '7.11'): void { \trigger_deprecation( 'guzzlehttp/guzzle', $since, 'Passing %s to request option "%s" is deprecated; guzzlehttp/guzzle 8.0 requires %s.', \get_debug_type($value), $option, $expected ); } /** * Transfers the given request and applies request options. * * The URI of the request is not modified and the request options are used * as-is without merging in default options. * * @param array $options See {@see RequestOptions}. */ private function transfer(RequestInterface $request, array $options): PromiseInterface { $request = $this->applyOptions($request, $options); $protocolVersion = $request->getProtocolVersion(); if ('' === $protocolVersion) { \trigger_deprecation('guzzlehttp/guzzle', '7.11', 'Sending a request with an empty protocol version is deprecated; guzzlehttp/guzzle 8.0 will reject empty protocol versions.'); $request = Psr7\Utils::modifyRequest($request, ['version' => '1.1']); } elseif (!self::isProtocolVersionValid($protocolVersion)) { \trigger_deprecation('guzzlehttp/guzzle', '7.11', 'Sending a request with a malformed protocol version is deprecated; guzzlehttp/guzzle 8.0 will reject malformed protocol versions.'); } /** @var HandlerStack $handler */ $handler = $options['handler']; try { return P\Create::promiseFor($handler($request, $options)); } catch (\Exception $e) { return P\Create::rejectionFor($e); } } /** * Applies the array of request options to a request. */ private function applyOptions(RequestInterface $request, array &$options): RequestInterface { $modify = [ 'set_headers' => [], ]; if (isset($options['headers'])) { if (array_keys($options['headers']) === range(0, count($options['headers']) - 1)) { throw new InvalidArgumentException('The headers array must have header name as keys.'); } $headers = $options['headers']; $droppedHeaderNames = self::castDeprecatedHeaderOptionValues($headers); if ($droppedHeaderNames !== [] && isset($options['_conditional'])) { $options['_conditional'] = Psr7\Utils::caselessRemove($droppedHeaderNames, $options['_conditional']); } $modify['set_headers'] = $headers; unset($options['headers']); } if (isset($options['form_params'])) { if (isset($options['multipart'])) { throw new InvalidArgumentException('You cannot use ' .'form_params and multipart at the same time. Use the ' .'form_params option if you want to send application/' .'x-www-form-urlencoded requests, and the multipart ' .'option to send multipart/form-data requests.'); } $options['body'] = \http_build_query(self::normalizeNonFiniteFloats($options['form_params'], 'form_params'), '', '&'); unset($options['form_params']); // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; } if (isset($options['multipart'])) { $options['body'] = new Psr7\MultipartStream($options['multipart']); unset($options['multipart']); } if (isset($options['json'])) { $json = \json_encode($options['json']); if (\JSON_ERROR_NONE !== \json_last_error()) { throw new InvalidArgumentException('json_encode error: '.\json_last_error_msg()); } /** @var non-empty-string $json */ $options['body'] = $json; unset($options['json']); // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/json'; } if (isset($options['decode_content']) && \is_string($options['decode_content'])) { // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']); $modify['set_headers']['Accept-Encoding'] = (string) $options['decode_content']; } if (isset($options['body'])) { if (\is_array($options['body'])) { throw $this->invalidBody(); } $modify['body'] = self::createBodyStream($options['body']); unset($options['body']); } if (!empty($options['auth']) && \is_array($options['auth'])) { $value = $options['auth']; $type = isset($value[2]) ? Psr7\Utils::asciiToLower($value[2]) : 'basic'; switch ($type) { case 'basic': // Ensure that we don't have the header in different case and set the new value. $modify['set_headers'] = Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']); $modify['set_headers']['Authorization'] = 'Basic ' .\base64_encode("$value[0]:$value[1]"); break; case 'digest': // @todo: Do not rely on curl $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST; $options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]"; break; case 'ntlm': \trigger_deprecation( 'guzzlehttp/guzzle', '7.12', 'Passing "ntlm" as the built-in auth type is deprecated; guzzlehttp/guzzle 8.0 will no longer apply NTLM through the "auth" request option. NTLM is also deprecated by curl/libcurl and may be unavailable in current or future libcurl builds. Avoid NTLM; if you must use it temporarily, configure cURL HTTP authentication options directly with a libcurl build that still supports NTLM.' ); if (!CurlVersion::supportsNtlm()) { throw new InvalidArgumentException('NTLM authentication is not available because the installed curl/libcurl build does not provide NTLM support.'); } $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM; $options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]"; break; } } if (isset($options['query'])) { $value = $options['query']; if (\is_array($value)) { $value = \http_build_query(self::normalizeNonFiniteFloats($value, 'query'), '', '&', \PHP_QUERY_RFC3986); } if (!\is_string($value)) { throw new InvalidArgumentException('query must be a string or array'); } $modify['query'] = $value; unset($options['query']); } // Ensure that sink is not an invalid value. if (isset($options['sink'])) { // TODO: Add more sink validation? if (\is_bool($options['sink'])) { throw new InvalidArgumentException('sink must not be a boolean'); } } if (isset($options['version'])) { $modify['version'] = self::normalizeProtocolVersion($options['version']); } $request = Psr7\Utils::modifyRequest($request, $modify); if ($request->getBody() instanceof Psr7\MultipartStream) { // Use a multipart/form-data POST if a Content-Type is not set. // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' .$request->getBody()->getBoundary(); } // Merge in conditional headers if they are not present. if (isset($options['_conditional'])) { // Build up the changes so it's in a single clone of the message. $modify = []; foreach ($options['_conditional'] as $k => $v) { $name = (string) $k; if (!$request->hasHeader($name)) { $modify['set_headers'][$name] = $v; } } $request = Psr7\Utils::modifyRequest($request, $modify); // Don't pass this internal value along to middleware/handlers. unset($options['_conditional']); } return $request; } /** * @param array $headers * * @return list */ private static function castDeprecatedHeaderOptionValues(array &$headers): array { $droppedHeaderNames = []; foreach ($headers as $name => $value) { if (\is_array($value)) { if ($value === []) { $droppedHeaderNames[] = (string) $name; unset($headers[$name]); continue; } foreach ($value as $index => $item) { if ($item === null || (!\is_string($item) && \is_scalar($item))) { if (\is_float($item) && !\is_finite($item)) { $item = \is_nan($item) ? 'NAN' : ($item > 0 ? 'INF' : '-INF'); } $value[$index] = (string) $item; } } $headers[$name] = $value; continue; } if ($value === null || (!\is_string($value) && \is_scalar($value))) { if (\is_float($value) && !\is_finite($value)) { $value = \is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF'); } $headers[$name] = (string) $value; } } return $droppedHeaderNames; } /** * @param mixed $body */ private static function createBodyStream($body): StreamInterface { if ($body instanceof StreamInterface) { return $body; } if (\is_resource($body) || $body === null || \is_string($body) || $body instanceof \Iterator) { return Psr7\Utils::streamFor($body); } if (\is_scalar($body)) { \trigger_deprecation('guzzlehttp/guzzle', '7.12', 'Passing a non-string scalar to the "body" request option is deprecated; guzzlehttp/guzzle 8.0 will reject non-string scalar bodies.'); return Psr7\Utils::streamFor(self::stringifyScalar($body)); } if (\is_object($body) && \method_exists($body, '__toString')) { return Psr7\Utils::streamFor((string) $body); } if (\is_callable($body)) { return Psr7\Utils::streamFor($body); } throw new InvalidArgumentException(\sprintf( 'Passing %s to request option "body" is invalid; expected resource|string|null|int|float|bool|StreamInterface|callable&object|Iterator|Stringable.', \get_debug_type($body) )); } /** * @param bool|float|int|string $value */ private static function stringifyScalar($value): string { // Normalize non-finite floats to dodge PHP 8.5's (string) NAN // coercion warning while the value is still accepted. if (\is_float($value) && !\is_finite($value)) { $value = \is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF'); } return (string) $value; } /** * Converts non-finite floats in the array to the strings PHP coerces * them to, as implicit coercion of NAN emits a warning on PHP 8.5. */ private static function normalizeNonFiniteFloats(array $values, string $option): array { foreach ($values as $key => $value) { if (\is_array($value)) { $values[$key] = self::normalizeNonFiniteFloats($value, $option); } elseif (\is_float($value) && !\is_finite($value)) { \trigger_deprecation('guzzlehttp/guzzle', '7.12', 'Passing a non-finite float in the "%s" request option is deprecated; guzzlehttp/guzzle 8.0 will reject non-finite floats.', $option); $values[$key] = \is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF'); } } return $values; } /** * @param string|int|float $version */ private static function normalizeProtocolVersion($version): string { if ('' === $version) { \trigger_deprecation('guzzlehttp/guzzle', '7.11', 'Passing an empty "version" request option is deprecated; guzzlehttp/guzzle 8.0 will reject empty protocol versions.'); return '1.1'; } return \is_float($version) ? \number_format($version, 1, '.', '') : (string) $version; } private static function isProtocolVersionValid(string $version): bool { return 1 === \preg_match('/^\d+(?:\.\d+)?$/D', $version); } /** * Return an InvalidArgumentException with pre-set message. */ private function invalidBody(): InvalidArgumentException { return new InvalidArgumentException('Passing in the "body" request ' .'option as an array to send a request is not supported. ' .'Please use the "form_params" request option to send a ' .'application/x-www-form-urlencoded request, or the "multipart" ' .'request option to send a multipart/form-data request.'); } } request('GET', $uri, $options); } /** * Create and send an HTTP HEAD request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function head($uri, array $options = []): ResponseInterface { return $this->request('HEAD', $uri, $options); } /** * Create and send an HTTP PUT request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function put($uri, array $options = []): ResponseInterface { return $this->request('PUT', $uri, $options); } /** * Create and send an HTTP POST request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function post($uri, array $options = []): ResponseInterface { return $this->request('POST', $uri, $options); } /** * Create and send an HTTP PATCH request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function patch($uri, array $options = []): ResponseInterface { return $this->request('PATCH', $uri, $options); } /** * Create and send an HTTP DELETE request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function delete($uri, array $options = []): ResponseInterface { return $this->request('DELETE', $uri, $options); } /** * Create and send an asynchronous HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string $method HTTP method * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ abstract public function requestAsync(string $method, $uri, array $options = []): PromiseInterface; /** * Create and send an asynchronous HTTP GET request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function getAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('GET', $uri, $options); } /** * Create and send an asynchronous HTTP HEAD request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function headAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('HEAD', $uri, $options); } /** * Create and send an asynchronous HTTP PUT request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function putAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('PUT', $uri, $options); } /** * Create and send an asynchronous HTTP POST request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function postAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('POST', $uri, $options); } /** * Create and send an asynchronous HTTP PATCH request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function patchAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('PATCH', $uri, $options); } /** * Create and send an asynchronous HTTP DELETE request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function deleteAsync($uri, array $options = []): PromiseInterface { return $this->requestAsync('DELETE', $uri, $options); } } strictMode = $strictMode; foreach ($cookieArray as $cookie) { if (!$cookie instanceof SetCookie) { $cookie = new SetCookie($cookie); } $this->setCookie($cookie); } } /** * Create a new Cookie jar from an associative array and domain. * * @param array $cookies Cookies to create the jar from * @param string $domain Domain to set the cookies to */ public static function fromArray(array $cookies, string $domain): self { $cookieJar = new self(); foreach ($cookies as $name => $value) { $cookieJar->setCookie(new SetCookie([ 'Domain' => $domain, 'Name' => $name, 'Value' => $value, 'Discard' => true, ])); } return $cookieJar; } /** * Evaluate if this cookie should be persisted to storage * that survives between requests. * * @param SetCookie $cookie Being evaluated. * @param bool $allowSessionCookies If we should persist session cookies */ public static function shouldPersist(SetCookie $cookie, bool $allowSessionCookies = false): bool { if ($cookie->getExpires() || $allowSessionCookies) { if (!$cookie->getDiscard()) { return true; } } return false; } /** * Finds and returns the cookie based on the name * * @param string $name cookie name to search for * * @return SetCookie|null cookie that was found or null if not found */ public function getCookieByName(string $name): ?SetCookie { foreach ($this->cookies as $cookie) { if ($cookie->getName() !== null && Psr7\Utils::caselessEquals($cookie->getName(), $name)) { return $cookie; } } return null; } public function toArray(): array { return \array_map(static function (SetCookie $cookie): array { return $cookie->toArray(); }, $this->getIterator()->getArrayCopy()); } public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void { if ($domain === null) { $this->cookies = []; return; } elseif ($path === null) { $this->cookies = \array_filter( $this->cookies, static function (SetCookie $cookie) use ($domain): bool { return $cookie->getDomain() === null || !$cookie->matchesDomain($domain); } ); } elseif ($name === null) { $this->cookies = \array_filter( $this->cookies, static function (SetCookie $cookie) use ($path, $domain): bool { return !($cookie->getDomain() !== null && $cookie->matchesPath($path) && $cookie->matchesDomain($domain)); } ); } else { $this->cookies = \array_filter( $this->cookies, static function (SetCookie $cookie) use ($path, $domain, $name) { return !($cookie->getDomain() !== null && $cookie->getName() === $name && $cookie->matchesPath($path) && $cookie->matchesDomain($domain)); } ); } } public function clearSessionCookies(): void { $this->cookies = \array_filter( $this->cookies, static function (SetCookie $cookie): bool { return !$cookie->getDiscard() && $cookie->getExpires(); } ); } public function setCookie(SetCookie $cookie): bool { // If the name string is empty (but not 0), ignore the set-cookie // string entirely. $name = $cookie->getName(); if (!$name && $name !== '0') { return false; } // Only allow cookies with set and valid domain, name, value $result = $cookie->validate(); if ($result !== true) { if ($this->strictMode) { throw new \RuntimeException('Invalid cookie: '.$result); } $this->removeCookieIfEmpty($cookie); return false; } $maxAge = $cookie->getMaxAge(); if ($maxAge !== null && $maxAge <= 0) { if ($cookie->getDomain() !== null) { $this->removeCookie($cookie); } return false; } // Resolve conflicts with previously set cookies foreach ($this->cookies as $i => $c) { // Two cookies are identical, when their path, and domain are // identical. if ($c->getPath() !== $cookie->getPath() || $c->getDomain() !== $cookie->getDomain() || $c->getHostOnly() !== $cookie->getHostOnly() || $c->getName() !== $cookie->getName() ) { continue; } // The previously set cookie is a discard cookie and this one is // not so allow the new cookie to be set if (!$cookie->getDiscard() && $c->getDiscard()) { unset($this->cookies[$i]); continue; } // If the new cookie's expiration is further into the future, then // replace the old cookie if ($cookie->getExpires() > $c->getExpires()) { unset($this->cookies[$i]); continue; } // If the value has changed, we better change it if ($cookie->getValue() !== $c->getValue()) { unset($this->cookies[$i]); continue; } // The cookie exists, so no need to continue return false; } $this->cookies[] = $cookie; return true; } public function count(): int { return \count($this->cookies); } /** * @return \ArrayIterator */ public function getIterator(): \ArrayIterator { return new \ArrayIterator(\array_values($this->cookies)); } public function extractCookies(RequestInterface $request, ResponseInterface $response): void { if ($cookieHeader = $response->getHeader('Set-Cookie')) { $accepted = 0; foreach ($cookieHeader as $cookie) { if (\strlen($cookie) > self::MAX_SET_COOKIE_FIELD_LENGTH) { continue; } $sc = SetCookie::fromString($cookie); $domain = $sc->getDomain(); if ($domain === null || $domain === '') { $sc->setDomain($request->getUri()->getHost()); $sc->setHostOnly(true); } elseif (\substr($domain, -1) === '.' && '' !== \trim($domain, '.')) { // Keep pure-dot domains rejected by the dot-only fix. $sc->setDomain($request->getUri()->getHost()); $sc->setHostOnly(true); } else { $sc->setHostOnly(false); } if (0 !== \strpos($sc->getPath(), '/')) { $sc->setPath($this->getCookiePathFromRequest($request)); } if (!$sc->matchesDomain($request->getUri()->getHost())) { continue; } // Note: At this point `$sc->getDomain()` being a public suffix should // be rejected, but we don't want to pull in the full PSL dependency. if ($this->setCookie($sc) && ++$accepted === self::MAX_SET_COOKIE_FIELDS) { break; } } } } /** * Computes cookie path following RFC 6265 section 5.1.4 * * @see https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4 */ private function getCookiePathFromRequest(RequestInterface $request): string { $uriPath = $request->getUri()->getPath(); if ('' === $uriPath) { return '/'; } if (0 !== \strpos($uriPath, '/')) { return '/'; } if ('/' === $uriPath) { return '/'; } $lastSlashPos = \strrpos($uriPath, '/'); if (0 === $lastSlashPos || false === $lastSlashPos) { return '/'; } return \substr($uriPath, 0, $lastSlashPos); } public function withCookieHeader(RequestInterface $request): RequestInterface { $values = []; $headerLength = 8; $uri = $request->getUri(); $scheme = $uri->getScheme(); $host = $uri->getHost(); $path = $uri->getPath() ?: '/'; foreach ($this->cookies as $cookie) { if ($cookie->getDomain() !== null && $cookie->matchesPath($path) && $cookie->matchesDomain($host) && !$cookie->isExpired() && (!$cookie->getSecure() || $scheme === 'https') ) { $name = (string) $cookie->getName(); $value = (string) $cookie->getValue(); $separatorLength = $values === [] ? 0 : 2; $valueLength = \strlen($name) + 1 + \strlen($value); if ($headerLength + $separatorLength + $valueLength > self::MAX_COOKIE_HEADER_LENGTH) { break; } $values[] = $name.'='.$value; $headerLength += $separatorLength + $valueLength; if (\count($values) === self::MAX_REQUEST_COOKIES) { break; } } } return $values ? $request->withHeader('Cookie', \implode('; ', $values)) : $request; } /** * If a cookie already exists and the server asks to set it again with a * null value, the cookie must be deleted. */ private function removeCookieIfEmpty(SetCookie $cookie): void { $cookieValue = $cookie->getValue(); if (($cookieValue === null || $cookieValue === '') && $cookie->getDomain() !== null) { $this->removeCookie($cookie); } } private function removeCookie(SetCookie $cookie): void { $this->cookies = \array_filter( $this->cookies, static function (SetCookie $stored) use ($cookie): bool { return !($stored->getName() === $cookie->getName() && $stored->getPath() === $cookie->getPath() && self::cookieDomainsEqual($stored->getDomain(), $cookie->getDomain()) && $stored->getHostOnly() === $cookie->getHostOnly()); } ); } private static function cookieDomainsEqual(?string $first, ?string $second): bool { if ($first === null || $second === null) { return $first === $second; } if (isset($first[0]) && $first[0] === '.') { $first = \substr($first, 1); } if (isset($second[0]) && $second[0] === '.') { $second = \substr($second, 1); } return Psr7\Utils::caselessEquals($first, $second); } } */ interface CookieJarInterface extends \Countable, \IteratorAggregate { /** * Create a request with added cookie headers. * * If no matching cookies are found in the cookie jar, then no Cookie * header is added to the request and the same request is returned. * * @param RequestInterface $request Request object to modify. * * @return RequestInterface returns the modified request. */ public function withCookieHeader(RequestInterface $request): RequestInterface; /** * Extract cookies from an HTTP response and store them in the CookieJar. * * @param RequestInterface $request Request that was sent * @param ResponseInterface $response Response that was received */ public function extractCookies(RequestInterface $request, ResponseInterface $response): void; /** * Sets a cookie in the cookie jar. * * @param SetCookie $cookie Cookie to set. * * @return bool Returns true on success or false on failure */ public function setCookie(SetCookie $cookie): bool; /** * Remove cookies currently held in the cookie jar. * * Invoking this method without arguments will empty the whole cookie jar. * If given a $domain argument only cookies belonging to that domain will * be removed. If given a $domain and $path argument, cookies belonging to * the specified path within that domain are removed. If given all three * arguments, then the cookie with the specified name, path and domain is * removed. * * @param string|null $domain Clears cookies matching a domain * @param string|null $path Clears cookies matching a domain and path * @param string|null $name Clears cookies matching a domain, path, and name */ public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void; /** * Discard all sessions cookies. * * Removes cookies that don't have an expire field or a have a discard * field set to true. To be called when the user agent shuts down according * to RFC 2965. */ public function clearSessionCookies(): void; /** * Converts the cookie jar to an array. */ public function toArray(): array; } filename = $cookieFile; $this->storeSessionCookies = $storeSessionCookies; if (\file_exists($cookieFile)) { $this->load($cookieFile); } } /** * Saves the file when shutting down */ public function __destruct() { $this->save($this->filename); } /** * Saves the cookies to a file. * * @param string $filename File to save * * @throws \RuntimeException if the file cannot be found or created */ public function save(string $filename): void { $json = []; /** @var SetCookie $cookie */ foreach ($this as $cookie) { if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { $data = $cookie->toArray(); $data['HostOnly'] = $cookie->getHostOnly(); $json[] = $data; } } $jsonStr = \json_encode($json); if (\JSON_ERROR_NONE !== \json_last_error()) { throw new InvalidArgumentException('json_encode error: '.\json_last_error_msg()); } /** @var non-empty-string $jsonStr */ if (false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) { throw new \RuntimeException("Unable to save file {$filename}"); } } /** * Load cookies from a JSON formatted file. * * Old cookies are kept unless overwritten by newly loaded ones. * * @param string $filename Cookie file to load. * * @throws \RuntimeException if the file cannot be loaded. */ public function load(string $filename): void { $json = \file_get_contents($filename); if (false === $json) { throw new \RuntimeException("Unable to load file {$filename}"); } if ($json === '') { return; } $data = \json_decode($json, true); if (\JSON_ERROR_NONE !== \json_last_error()) { throw new InvalidArgumentException('json_decode error: '.\json_last_error_msg()); } if (\is_array($data)) { $cookies = []; foreach ($data as $cookie) { if (!\is_array($cookie) || !\array_key_exists('HostOnly', $cookie) || !\is_bool($cookie['HostOnly'])) { throw new \RuntimeException("Invalid cookie file: {$filename}"); } $cookies[] = new SetCookie($cookie); } foreach ($cookies as $cookie) { $this->setCookie($cookie); } } elseif (\is_scalar($data) && !empty($data)) { throw new \RuntimeException("Invalid cookie file: {$filename}"); } } } sessionKey = $sessionKey; $this->storeSessionCookies = $storeSessionCookies; $this->load(); } /** * Saves cookies to session when shutting down */ public function __destruct() { $this->save(); } /** * Save cookies to the client session */ public function save(): void { $json = []; /** @var SetCookie $cookie */ foreach ($this as $cookie) { if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { $data = $cookie->toArray(); $data['HostOnly'] = $cookie->getHostOnly(); $json[] = $data; } } $json = \json_encode($json); if (false === $json) { throw new \RuntimeException('Unable to encode cookie data'); } $_SESSION[$this->sessionKey] = $json; } /** * Load the contents of the client session into the data array */ protected function load(): void { if (!isset($_SESSION[$this->sessionKey])) { return; } $json = $_SESSION[$this->sessionKey]; if (!\is_string($json)) { throw new \RuntimeException('Invalid cookie data'); } $data = \json_decode($json, true); if (\is_array($data)) { $cookies = []; foreach ($data as $cookie) { if (!\is_array($cookie) || !\array_key_exists('HostOnly', $cookie) || !\is_bool($cookie['HostOnly'])) { throw new \RuntimeException('Invalid cookie data'); } $cookies[] = new SetCookie($cookie); } foreach ($cookies as $cookie) { $this->setCookie($cookie); } } elseif (\is_scalar($data) && \strlen((string) $data)) { throw new \RuntimeException('Invalid cookie data'); } } } null, 'Value' => null, 'Domain' => null, 'Path' => '/', 'Max-Age' => null, 'Expires' => null, 'Secure' => false, 'Discard' => false, 'HttpOnly' => false, ]; /** * @var array Cookie data */ private $data; /** * @var bool Whether this cookie was set without a Domain attribute */ private $hostOnly = false; /** * Create a new SetCookie object from a string. * * @param string $cookie Set-Cookie header string */ public static function fromString(string $cookie): self { // Create the default return array $data = self::$defaults; // Explode the cookie string using a series of semicolons $pieces = \array_filter(\array_map(static function (string $piece): string { return \trim($piece, " \n\r\t\0\x0B"); }, \explode(';', $cookie))); // The name of the cookie (first kvp) must exist and include an equal sign. if (!isset($pieces[0]) || \strpos($pieces[0], '=') === false) { return new self($data); } // Add the cookie pieces into the parsed data array foreach ($pieces as $part) { $cookieParts = \explode('=', $part, 2); $key = \trim($cookieParts[0], " \n\r\t\0\x0B"); $value = isset($cookieParts[1]) ? \trim($cookieParts[1], " \n\r\t\0\x0B") : true; // Only check for non-cookies when cookies have been found if (!isset($data['Name'])) { $data['Name'] = $key; $data['Value'] = $value; } else { foreach (\array_keys(self::$defaults) as $search) { if (Psr7\Utils::caselessEquals($search, $key)) { if ($search === 'Max-Age') { if (is_numeric($value)) { $data[$search] = (int) $value; } } elseif ($search === 'Secure' || $search === 'Discard' || $search === 'HttpOnly') { if ($value) { $data[$search] = true; } } else { $data[$search] = $value; } continue 2; } } if (Psr7\Utils::caselessEquals('HostOnly', $key)) { continue; } $data[$key] = $value; } } return new self($data); } /** * @param array $data Array of cookie data provided by a Cookie parser */ public function __construct(array $data = []) { $this->data = self::$defaults; if (\array_key_exists('HostOnly', $data)) { if (!\is_bool($data['HostOnly'])) { throw new \InvalidArgumentException('Cookie field "HostOnly" must be a boolean'); } $this->setHostOnly($data['HostOnly']); unset($data['HostOnly']); } if (isset($data['Name'])) { $this->setName($data['Name']); } if (isset($data['Value'])) { $this->setValue($data['Value']); } if (isset($data['Domain'])) { $this->setDomain($data['Domain']); } if (isset($data['Path'])) { $this->setPath($data['Path']); } if (isset($data['Max-Age'])) { $this->setMaxAge($data['Max-Age']); } if (isset($data['Expires'])) { $this->setExpires($data['Expires']); } if (isset($data['Secure'])) { $this->setSecure($data['Secure']); } if (isset($data['Discard'])) { $this->setDiscard($data['Discard']); } if (isset($data['HttpOnly'])) { $this->setHttpOnly($data['HttpOnly']); } // Set the remaining values that don't have extra validation logic foreach (array_diff(array_keys($data), array_keys(self::$defaults)) as $key) { $this->data[$key] = $data[$key]; } // Extract the Expires value and turn it into a UNIX timestamp if needed $maxAge = $this->getMaxAge(); if (!$this->getExpires() && $maxAge !== null) { // Calculate the Expires date $this->setExpires(self::maxAgeToExpires($maxAge, \time())); } elseif (null !== ($expires = $this->getExpires()) && !\is_numeric($expires)) { $this->setExpires($expires); } } private static function maxAgeToExpires(int $maxAge, int $now): int { if ($maxAge <= 0) { return $now - 1; } if ($maxAge > \PHP_INT_MAX - $now) { return \PHP_INT_MAX; } return $now + $maxAge; } public function __toString() { $str = $this->data['Name'].'='.($this->data['Value'] ?? '').'; '; foreach ($this->data as $k => $v) { if ($k === 'Domain' && $this->getHostOnly()) { continue; } if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) { if ($k === 'Expires') { $str .= 'Expires='.\gmdate('D, d M Y H:i:s \G\M\T', $v).'; '; } else { $str .= ($v === true ? $k : "{$k}={$v}").'; '; } } } return \rtrim($str, '; '); } public function toArray(): array { $data = $this->data; if ($this->getHostOnly()) { $data['HostOnly'] = true; } return $data; } /** * Get the cookie name. * * @return string */ public function getName() { return $this->data['Name']; } /** * Set the cookie name. * * @param string $name Cookie name */ public function setName($name): void { if (!is_string($name)) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Name'] = (string) $name; } /** * Get the cookie value. * * @return string|null */ public function getValue() { return $this->data['Value']; } /** * Set the cookie value. * * @param string $value Cookie value */ public function setValue($value): void { if (!is_string($value)) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Value'] = (string) $value; } /** * Get the domain. * * @return string|null */ public function getDomain() { return $this->data['Domain']; } /** * Set the domain of the cookie. * * @param string|null $domain */ public function setDomain($domain): void { if (!is_string($domain) && null !== $domain) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Domain'] = null === $domain ? null : (string) $domain; } /** * Get whether this cookie is scoped to the origin host only. * * @return bool */ public function getHostOnly() { return $this->hostOnly; } /** * Set whether this cookie is scoped to the origin host only. * * @param bool $hostOnly Set to true for host-only cookies */ public function setHostOnly(bool $hostOnly): void { $this->hostOnly = $hostOnly; } /** * Get the path. * * @return string */ public function getPath() { return $this->data['Path']; } /** * Set the path of the cookie. * * @param string $path Path of the cookie */ public function setPath($path): void { if (!is_string($path)) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Path'] = (string) $path; } /** * Maximum lifetime of the cookie in seconds. * * @return int|null */ public function getMaxAge() { return null === $this->data['Max-Age'] ? null : (int) $this->data['Max-Age']; } /** * Set the max-age of the cookie. * * @param int|null $maxAge Max age of the cookie in seconds */ public function setMaxAge($maxAge): void { if (!is_int($maxAge) && null !== $maxAge) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Max-Age'] = $maxAge === null ? null : (int) $maxAge; } /** * The UNIX timestamp when the cookie Expires. * * @return string|int|null */ public function getExpires() { return $this->data['Expires']; } /** * Set the unix timestamp for which the cookie will expire. * * @param int|string|null $timestamp Unix timestamp or any English textual datetime description. */ public function setExpires($timestamp): void { if (!is_int($timestamp) && !is_string($timestamp) && null !== $timestamp) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int, string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } if (null === $timestamp) { $this->data['Expires'] = null; } elseif (\is_numeric($timestamp)) { $this->data['Expires'] = (int) $timestamp; } else { // Store unparseable dates as session cookies, not as expired cookies. $expires = \strtotime((string) $timestamp); $this->data['Expires'] = $expires === false ? null : $expires; } } /** * Get whether or not this is a secure cookie. * * @return bool */ public function getSecure() { return $this->data['Secure']; } /** * Set whether or not the cookie is secure. * * @param bool $secure Set to true or false if secure */ public function setSecure($secure): void { if (!is_bool($secure)) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Secure'] = (bool) $secure; } /** * Get whether or not this is a session cookie. * * @return bool|null */ public function getDiscard() { return $this->data['Discard']; } /** * Set whether or not this is a session cookie. * * @param bool $discard Set to true or false if this is a session cookie */ public function setDiscard($discard): void { if (!is_bool($discard)) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Discard'] = (bool) $discard; } /** * Get whether or not this is an HTTP only cookie. * * @return bool */ public function getHttpOnly() { return $this->data['HttpOnly']; } /** * Set whether or not this is an HTTP only cookie. * * @param bool $httpOnly Set to true or false if this is HTTP only */ public function setHttpOnly($httpOnly): void { if (!is_bool($httpOnly)) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['HttpOnly'] = (bool) $httpOnly; } /** * Check if the cookie matches a path value. * * A request-path path-matches a given cookie-path if at least one of * the following conditions holds: * * - The cookie-path and the request-path are identical. * - The cookie-path is a prefix of the request-path, and the last * character of the cookie-path is %x2F ("/"). * - The cookie-path is a prefix of the request-path, and the first * character of the request-path that is not included in the cookie- * path is a %x2F ("/") character. * * @param string $requestPath Path to check against */ public function matchesPath(string $requestPath): bool { $cookiePath = $this->getPath(); // Match on exact matches or when path is the default empty "/" if ($cookiePath === '/' || $cookiePath === $requestPath) { return true; } // Ensure that the cookie-path is a prefix of the request path. if (0 !== \strpos($requestPath, $cookiePath)) { return false; } // Match if the last character of the cookie-path is "/" if (\substr($cookiePath, -1, 1) === '/') { return true; } // Match if the first character not included in cookie path is "/" return \substr($requestPath, \strlen($cookiePath), 1) === '/'; } /** * Check if the cookie matches a domain value. * * @param string $domain Domain to check against */ public function matchesDomain(string $domain): bool { $cookieDomain = $this->getDomain(); if (null === $cookieDomain) { return !$this->getHostOnly(); } if ($this->getHostOnly()) { return Psr7\Utils::asciiToLower($domain) === Psr7\Utils::asciiToLower($cookieDomain); } // Remove the leading '.' as per spec in RFC 6265. // https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3 $cookieDomain = Psr7\Utils::asciiToLower($cookieDomain); if ($cookieDomain !== '' && $cookieDomain[0] === '.') { /** @var string */ $cookieDomain = \substr($cookieDomain, 1); } if ('' === $cookieDomain) { return false; } $domain = Psr7\Utils::asciiToLower($domain); if ($domain === $cookieDomain) { return true; } // A percent-escaped cookie domain can decode to another host spelling. // Keep it exact-match-only to avoid extending that host's cookie scope. if (\strpos($cookieDomain, '%') !== false) { return false; } // IP literals and numeric hosts are exact-match-only per RFC 6265. // Only the exact match above may succeed for those cookie domains. if (self::isIpAddressOrNumericHost($cookieDomain)) { return false; } // Matching the subdomain according to RFC 6265. // https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3 if (\filter_var($domain, \FILTER_VALIDATE_IP)) { return false; } return (bool) \preg_match('/\.'.\preg_quote($cookieDomain, '/').'$/D', $domain); } private static function isIpAddressOrNumericHost(string $host): bool { // Strip one root dot before detection so trailing-dot numeric hosts // still cannot be matched by subdomains. if ($host !== '' && \str_ends_with($host, '.')) { $host = \substr($host, 0, -1); } if (\str_starts_with($host, '[') && \str_ends_with($host, ']')) { $host = \substr($host, 1, -1); } if (\filter_var($host, \FILTER_VALIDATE_IP) !== false) { return true; } // Public DNS names do not have an all-numeric rightmost label; treat // those private/internal hosts as exact-match-only too. $labels = \explode('.', $host); $last = (string) \end($labels); if ($last !== '' && \ctype_digit($last)) { return true; } // Apply the transport's decimal, octal and hexadecimal inet_aton-style // grammar. Omitting range checks conservatively holds some names to an // exact match. return HostValidator::isNumericIpv4Host(\rtrim($host, '.')); } /** * Check if the cookie is expired. */ public function isExpired(): bool { return $this->getExpires() !== null && \time() > $this->getExpires(); } /** * Check if the cookie is valid according to RFC 6265. * * @return bool|string Returns true if valid or an error message if invalid */ public function validate() { $name = $this->getName(); if ($name === '') { return 'The cookie name must not be empty'; } // Check if any of the invalid characters are present in the cookie name if (\preg_match('/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/', $name) !== 0) { return 'Cookie name must not contain invalid characters: ASCII ' .'Control characters (0-31;127), space, tab and the ' .'following characters: ()<>@,;:\"/?={}'; } // Value must not be null. 0 and empty string are valid. Empty strings // are technically against RFC 6265, but known to happen in the wild. $value = $this->getValue(); if ($value === null) { return 'The cookie value must not be empty'; } // Domains must not be empty, but may be omitted. "0" is not a valid // internet domain, but may be used as server name in a private network. $domain = $this->getDomain(); if ($domain === '' || (null !== $domain && '' === \ltrim(\trim($domain, " \n\r\t\0\x0B"), '.'))) { return 'The cookie domain must not be empty'; } return true; } } request = $request; $this->handlerContext = $handlerContext; } /** * Get the request that caused the exception */ public function getRequest(): RequestInterface { return $this->request; } /** * Get contextual information about the error from the underlying handler. * * The contents of this array will vary depending on which handler you are * using. It may also be just an empty array. Relying on this data will * couple you to a specific handler, but can give more debug information * when needed. */ public function getHandlerContext(): array { return $this->handlerContext; } } getStatusCode() : 0; parent::__construct($message, $code, $previous); $this->request = $request; $this->response = $response; $this->handlerContext = $handlerContext; } /** * Wrap non-RequestExceptions with a RequestException * * @deprecated since 7.11. Create a RequestException directly instead. */ public static function wrapException(RequestInterface $request, \Throwable $e): RequestException { \trigger_deprecation('guzzlehttp/guzzle', '7.11', '%s::wrapException() is deprecated and will be removed in 8.0. Create a %s directly instead.', self::class, self::class); return $e instanceof RequestException ? $e : new RequestException($e->getMessage(), $request, null, $e); } /** * Factory method to create a new exception with a normalized error message * * @param RequestInterface $request Request sent * @param ResponseInterface $response Response received * @param \Throwable|null $previous Previous exception * @param array $handlerContext Optional handler context * @param BodySummarizerInterface|null $bodySummarizer Optional body summarizer */ public static function create( RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $previous = null, array $handlerContext = [], ?BodySummarizerInterface $bodySummarizer = null ): self { if (!$response) { return new self( 'Error completing request', $request, null, $previous, $handlerContext ); } $level = (int) \floor($response->getStatusCode() / 100); if ($level === 4) { $label = 'Client error'; $className = ClientException::class; } elseif ($level === 5) { $label = 'Server error'; $className = ServerException::class; } else { $label = 'Unsuccessful request'; $className = __CLASS__; } $uri = \GuzzleHttp\Psr7\Utils::redactUserInfo($request->getUri()); // Client Error: `GET /` resulted in a `404 Not Found` response: // ... (truncated) $message = \sprintf( '%s: `%s %s` resulted in a `%s %s` response', $label, $request->getMethod(), $uri->__toString(), $response->getStatusCode(), $response->getReasonPhrase() ); $summary = ($bodySummarizer ?? new BodySummarizer())->summarize($response); if ($summary !== null) { $message .= ":\n{$summary}\n"; } return new $className($message, $request, $response, $previous, $handlerContext); } /** * Get the request that caused the exception */ public function getRequest(): RequestInterface { return $this->request; } /** * Get the associated response */ public function getResponse(): ?ResponseInterface { return $this->response; } /** * Check if a response was received */ public function hasResponse(): bool { return $this->response !== null; } /** * Get contextual information about the error from the underlying handler. * * The contents of this array will vary depending on which handler you are * using. It may also be just an empty array. Relying on this data will * couple you to a specific handler, but can give more debug information * when needed. */ public function getHandlerContext(): array { return $this->handlerContext; } } maxHandles = $maxHandles; $this->shareMode = CurlShareHandleState::normalizeMode($shareMode, 'transport_sharing'); if ($shareHandle instanceof CurlShareHandleState) { if ($shareHandle->mode !== $this->shareMode) { throw new \InvalidArgumentException('The cURL share handle state mode does not match the configured transport sharing mode.'); } // A Guzzle-created handler-lifetime state locks only DNS and TLS // session data, so its handle can never own a connection cache. $shareHandle = $shareHandle->handle; } elseif ($shareHandle !== null) { // An externally supplied handle's lock set and cached contents // cannot be inspected from PHP, so it may own a connection cache // populated outside this factory. $this->opaqueShareConnectionCache = true; } if ($this->shareMode === TransportSharing::NONE && $shareHandle !== null) { throw new \InvalidArgumentException('A cURL share handle cannot be provided when transport sharing is disabled.'); } if ($this->shareMode !== TransportSharing::NONE && $shareHandle === null) { throw new \InvalidArgumentException('A cURL share handle is required when transport sharing is enabled.'); } if ($shareHandle !== null && !self::isCurlShareHandle($shareHandle)) { throw new \InvalidArgumentException('A cURL share handle must be an instance of CurlShareHandle or a curl_share resource.'); } $this->shareHandle = $shareHandle; } /** * @param mixed $value */ private static function isCurlShareHandle($value): bool { if (\PHP_VERSION_ID < 80000) { return \is_resource($value) && \get_resource_type($value) === 'curl_share'; } return $value instanceof \CurlShareHandle; } public function create(RequestInterface $request, array $options): EasyHandle { self::validateRequestUriScheme($request); if (isset($options['on_trailers']) && !\is_callable($options['on_trailers'])) { throw new \InvalidArgumentException('on_trailers must be callable'); } $protocolVersion = $request->getProtocolVersion(); if ('' === $protocolVersion) { \trigger_deprecation('guzzlehttp/guzzle', '7.11', 'Sending a request with an empty protocol version is deprecated; guzzlehttp/guzzle 8.0 will reject empty protocol versions.'); $protocolVersion = '1.1'; $request = Psr7\Utils::modifyRequest($request, ['version' => $protocolVersion]); } $multiplex = self::normalizeMultiplex($options); $requiredMultiplex = \in_array($multiplex, [Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true); if ($requiredMultiplex && isset($options['curl']) && \is_array($options['curl'])) { $requiredModeConflicts = [ \CURLOPT_HTTP_VERSION => ['CURLOPT_HTTP_VERSION', 'the request protocol version'], \CURLOPT_URL => ['CURLOPT_URL', 'the request URI'], \CURLOPT_FOLLOWLOCATION => ['CURLOPT_FOLLOWLOCATION', 'the "allow_redirects" request option'], ]; foreach ($requiredModeConflicts as $option => [$name, $replacement]) { if (\array_key_exists($option, $options['curl'])) { // Key presence alone conflicts: whatever the raw value, // it is a second authority over the protocol or route, // applied after the required mode's decisions. throw new \InvalidArgumentException(\sprintf('The "multiplex" request option cannot be required when the raw %s cURL option is set; remove the raw option and use %s instead.', $name, $replacement)); } } } if ('2' === $protocolVersion || '2.0' === $protocolVersion) { if (!CurlVersion::supportsHttp2()) { if ($requiredMultiplex) { throw new ConnectException('Required multiplexing needs libcurl 8.14.0 or newer built with HTTP/2 support.', $request); } throw new ConnectException('HTTP/2 is supported by the cURL handler, however libcurl is built without HTTP/2 support.', $request); } } elseif ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) { throw new ConnectException(sprintf('HTTP/%s is not supported by the cURL handler.', $protocolVersion), $request); } if (isset($options['curl']['body_as_string'])) { $options['_body_as_string'] = $options['curl']['body_as_string']; unset($options['curl']['body_as_string']); } self::triggerUnsupportedRequestOptionDeprecations($options); self::triggerUnsupportedCurlOptionDeprecations($options); self::triggerConflictingCurlOptionDeprecations($options); // Capture the managed Proxy-Authorization values before header // serialization so they never enter the origin header list, and // record whether a deprecated raw CURLOPT_HTTPHEADER value replaces // every generated header, the managed values included. Key presence // alone replaces: an empty or null raw value still suppresses the // generated list. $managedProxyAuthorization = self::managedProxyAuthorizationHeaderLines($request); $rawHttpHeadersReplaceManaged = isset($options['curl']) && \is_array($options['curl']) && \array_key_exists(\CURLOPT_HTTPHEADER, $options['curl']); $easy = new EasyHandle(); $easy->request = $request; $easy->options = $options; $conf = $this->getDefaultConf($easy); $this->applyMethod($easy, $conf); $this->applyHandlerOptions($easy, $conf); $this->applyHeaders($easy, $conf); unset($conf['_headers']); // Add handler options from the request configuration options if (isset($options['curl'])) { $conf = \array_replace($conf, $options['curl']); } self::assertFinalProxyOptionTypes($conf, $requiredMultiplex && 'https' !== $request->getUri()->getScheme()); self::isolatePreProxyOnAffectedCurl($conf); self::normalizeStringableProxyCredentialOptions($conf); if ($requiredMultiplex) { self::assertRequiredMultiplexRouteDirect($easy, $conf); self::assertRequiredMultiplexAuthSupported($conf); } self::normalizeCurlHeaderOptions($conf); self::applyProxyAuthorizationHeaderHandling($request, $conf); self::applyManagedProxyAuthorization($request, $conf, $managedProxyAuthorization, $rawHttpHeadersReplaceManaged); // Validate the appended managed lines too: a custom RequestInterface // can bypass a normal PSR-7 implementation's header validation. self::normalizeCurlHeaderOptions($conf); $this->rejectRequestLevelShareConflict($options); self::rejectRequestLevelShareWithProxyAuth($request, $options, $conf); if ($this->shareHandle !== null) { // Conservative blanket mode: a configured share handle hides the // pooled connections' provenance, so sectioned reuse cannot reason // about them. self::forceFreshConnectionForAuthenticatedProxy($request, $conf); $this->isolateOpaqueShareAnonymousProxyTunnel($request, $conf); } else { $signature = self::proxyTunnelSignature($request, $conf); $easy->proxyTunnelSignature = $signature; if ($signature !== null && $signature !== $this->proxyTunnelOwner) { if ($this->poolMayHoldTunnels) { // Pooled idle handles may hold a different owner's tunnel. $this->discardIdleHandles(); $this->poolMayHoldTunnels = false; } // The first in-domain owner latches without purging: the pool // provably holds no in-domain tunnel yet. $this->proxyTunnelOwner = $signature; } } $easy->effectiveProxy = self::getEffectiveProxy($conf); $conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); if ($this->shareHandle !== null) { if (!\defined('CURLOPT_SHARE')) { throw new \InvalidArgumentException('The configured cURL share handle requires CURLOPT_SHARE, but it is not available in the installed PHP cURL extension.'); } $conf[(int) \constant('CURLOPT_SHARE')] = $this->shareHandle; } if (\defined('CURLOPT_PIPEWAIT')) { $easy->usesPipewait = !empty($conf[(int) \constant('CURLOPT_PIPEWAIT')]); } $handle = $this->handles ? \array_pop($this->handles) : \curl_init(); if (false === $handle) { throw new \RuntimeException('Can not initialize cURL handle.'); } $easy->handle = $handle; try { $this->applyCurlOptions($handle, $conf); } catch (\Throwable $e) { if (PHP_VERSION_ID < 80000 && \is_resource($handle)) { \curl_close($handle); } unset($easy->handle); throw $e; } return $easy; } /** * @param resource|\CurlHandle $handle * @param array $conf */ private function applyCurlOptions($handle, array $conf): void { foreach ($conf as $option => $value) { if (!\is_int($option)) { throw new \InvalidArgumentException(\sprintf( 'Invalid cURL option %s.', self::formatCurlOption($option) )); } try { $success = curl_setopt($handle, $option, $value); } catch (\Throwable $e) { throw new \InvalidArgumentException( \sprintf( 'Unable to set cURL option %s: %s', self::formatCurlOption($option), $e->getMessage() ), 0, $e ); } if (!$success) { throw new \InvalidArgumentException(\sprintf( 'Unable to set cURL option %s.', self::formatCurlOption($option) )); } } } /** * @param array $conf */ private static function normalizeStringableProxyCredentialOptions(array &$conf): void { foreach (self::STRINGABLE_PROXY_CREDENTIAL_OPTIONS as $name) { if (!\defined($name)) { continue; } $option = (int) \constant($name); if (!isset($conf[$option]) || !\is_object($conf[$option]) || !\method_exists($conf[$option], '__toString')) { continue; } try { $conf[$option] = (string) $conf[$option]; } catch (\Throwable $e) { // Wrap the failure exactly as applyCurlOptions() does for a // value that cannot be applied. throw new \InvalidArgumentException( \sprintf( 'Unable to set cURL option %s: %s', self::formatCurlOption($option), $e->getMessage() ), 0, $e ); } } } private function rejectRequestLevelShareConflict(array $options): void { if ($this->shareHandle === null) { return; } if ( !\defined('CURLOPT_SHARE') || !isset($options['curl']) || !\is_array($options['curl']) || !\array_key_exists((int) \constant('CURLOPT_SHARE'), $options['curl']) ) { return; } throw new \InvalidArgumentException('The request-level CURLOPT_SHARE cURL option cannot be combined with configured transport sharing.'); } private static function normalizeMultiplex(array $options): ?string { $multiplex = $options['multiplex'] ?? null; if ($multiplex === null) { // Absent/null leaves multiplexing to libcurl: no CURLOPT_PIPEWAIT // is written and no guarantees apply. return null; } if (!\in_array($multiplex, [Multiplexing::NONE, Multiplexing::EAGER, Multiplexing::WAIT, Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) { throw new \InvalidArgumentException(\sprintf( 'The "multiplex" option must be null or a GuzzleHttp\\Multiplexing::* constant; received %s.', \get_debug_type($multiplex) )); } return $multiplex; } private static function assertRequiredMultiplexSupported(EasyHandle $easy): void { if (!CurlVersion::supportsRequiredMultiplex()) { throw new ConnectException('Required multiplexing needs libcurl 8.14.0 or newer built with HTTP/2 support.', $easy->request); } } /** * Required multiplexing sends cleartext requests with HTTP/2 prior * knowledge, which an HTTP proxy hop silently downgrades, so the request * must reach the origin directly. The check runs against the final * merged cURL configuration because deprecated raw proxy options are * applied after Guzzle's own decisions and may add, replace, or disable * the selected proxy. Value types that ext-curl would coerce are * rejected as ambiguous, and only the exact CURLOPT_NOPROXY wildcard '*' * counts as disabling the primary proxy and pre-proxy: host-specific * patterns are conservatively treated as leaving them active. * * @param array $conf */ private static function assertRequiredMultiplexRouteDirect(EasyHandle $easy, array $conf): void { if ('https' === $easy->request->getUri()->getScheme()) { return; } $proxyOptions = [\CURLOPT_PROXY => 'CURLOPT_PROXY']; if (\defined('CURLOPT_NOPROXY')) { $proxyOptions[(int) \constant('CURLOPT_NOPROXY')] = 'CURLOPT_NOPROXY'; } if (\defined('CURLOPT_PRE_PROXY')) { $proxyOptions[(int) \constant('CURLOPT_PRE_PROXY')] = 'CURLOPT_PRE_PROXY'; } foreach ($proxyOptions as $option => $name) { if (\array_key_exists($option, $conf) && !\is_string($conf[$option])) { throw new \InvalidArgumentException(\sprintf('The "multiplex" request option cannot be required when the final %s cURL option value is not a string.', $name)); } } if (\defined('CURLOPT_NOPROXY') && ($conf[(int) \constant('CURLOPT_NOPROXY')] ?? null) === '*') { // libcurl's exact wildcard disables the primary proxy and the // pre-proxy together, leaving a direct route. return; } if (self::getEffectiveProxy($conf) !== null || (\defined('CURLOPT_PRE_PROXY') && ($conf[(int) \constant('CURLOPT_PRE_PROXY')] ?? '') !== '') ) { throw new ConnectException('Required multiplexing cannot be guaranteed for cleartext requests sent through a proxy.', $easy->request); } } /** * libcurl forces NTLM-authenticated transfers onto HTTP/1.1: when the * server picks NTLM from the offered mask, the connection is closed and * the request is retried over HTTP/1.1 whatever HTTP version was asked * for, silently defeating the required protocol guarantee on both * cleartext and TLS routes. The final merged mask is checked so the * deprecated "auth" request option and the raw CURLOPT_HTTPAUTH cURL * option are both covered, and any mask permitting NTLM, such as * CURLAUTH_ANY, is rejected because the selection is server-controlled. * * @param array $conf */ private static function assertRequiredMultiplexAuthSupported(array $conf): void { if (!\array_key_exists(\CURLOPT_HTTPAUTH, $conf)) { return; } $auth = $conf[\CURLOPT_HTTPAUTH]; if (!\is_scalar($auth)) { throw new \InvalidArgumentException('The "multiplex" request option cannot be required when the final CURLOPT_HTTPAUTH cURL option value is not an integer.'); } $ntlmBits = \CURLAUTH_NTLM; if (\defined('CURLAUTH_NTLM_WB')) { $ntlmBits |= (int) \constant('CURLAUTH_NTLM_WB'); } if (((int) $auth & $ntlmBits) !== 0) { throw new \InvalidArgumentException('The "multiplex" request option cannot be required when the final CURLOPT_HTTPAUTH cURL option value permits NTLM; libcurl retries NTLM authentication over HTTP/1.1.'); } } /** * @param mixed $proxyConf */ private static function assertResolvedProxySupported(RequestInterface $request, $proxyConf): void { if (!\is_string($proxyConf) || $proxyConf === '') { return; } $scheme = self::proxyScheme($proxyConf); if ($scheme !== null && \preg_match('/^[a-z][a-z0-9.+-]*$/D', $scheme) !== 1) { throw new RequestException('The proxy URL is malformed.', $request); } if ($scheme === 'https' && !CurlVersion::supportsHttpsProxy()) { throw new RequestException('HTTPS proxies are not supported by the installed libcurl; libcurl 7.52.0 or newer built with HTTPS-proxy support is required.', $request); } } /** * @return array{0: mixed, 1: string} */ private static function resolveProxy(RequestInterface $request, array $options): array { $proxyConf = null; $noProxyConf = ''; if (isset($options['proxy'])) { if (!\is_array($options['proxy'])) { $proxyConf = $options['proxy']; } else { $scheme = $request->getUri()->getScheme(); if (isset($options['proxy'][$scheme])) { if ( isset($options['proxy']['no']) && Utils::isUriInNoProxy($request->getUri(), $options['proxy']['no']) ) { $proxyConf = ''; $noProxyConf = '*'; } else { $proxyConf = $options['proxy'][$scheme]; } } } } if ($proxyConf === null) { $proxyConf = ProxyEnvironment::getProxyForScheme($request->getUri()->getScheme()); if ($proxyConf === null) { $proxyConf = ''; } elseif ( ($noProxy = ProxyEnvironment::getNoProxy()) !== null && Utils::isUriInNoProxy($request->getUri(), ProxyEnvironment::splitNoProxy($noProxy)) ) { $proxyConf = ''; $noProxyConf = '*'; } } return [$proxyConf, $noProxyConf]; } /** * @param array $conf */ private static function rejectRequestLevelShareWithProxyAuth(RequestInterface $request, array $options, array $conf): void { if (!self::hasRequestLevelCurlShare($options)) { return; } $proxy = self::getEffectiveProxy($conf); if ($proxy === null) { return; } // An external share handle may pool SOCKS connections where no section // signature can reach them. On affected libcurl, even an anonymous // request could inherit authenticated state already in that pool. if (self::isSocksProxy($proxy, $conf)) { if (!CurlVersion::supportsSocksProxyCredentialAwareConnectionReuse()) { throw new \InvalidArgumentException('The request-level CURLOPT_SHARE cURL option cannot be combined with SOCKS proxy configuration on libcurl before 7.69.0; use Guzzle-managed "transport_sharing" or a custom handler/factory instead.'); } if (self::hasAuthenticatedSocksProxyState($proxy, $conf)) { throw new \InvalidArgumentException('The request-level CURLOPT_SHARE cURL option cannot be combined with authenticated SOCKS proxy configuration; use Guzzle-managed "transport_sharing" or a custom handler/factory instead.'); } } if ( !self::usesProxyTunnel($request, $conf) || !self::isHttpProxyForConnectionReuse($proxy, $conf) ) { return; } if (self::hasAuthenticatedHttpProxyState($proxy, $conf)) { throw new \InvalidArgumentException('The request-level CURLOPT_SHARE cURL option cannot be combined with authenticated HTTP/HTTPS proxy tunnel configuration; use Guzzle-managed "transport_sharing" or a custom handler/factory instead.'); } // From libcurl 7.57.0 the external share can also own a connection // cache seeded outside Guzzle with tunnel identity libcurl cannot // key, so anonymous tunnels are rejected there too. if (CurlVersion::supportsShareConnectionCaches()) { throw new \InvalidArgumentException('The request-level CURLOPT_SHARE cURL option cannot be combined with HTTP/HTTPS proxy tunnel configuration on libcurl 7.57.0 or newer; use Guzzle-managed "transport_sharing" or a custom handler/factory instead.'); } } private static function hasRequestLevelCurlShare(array $options): bool { return \defined('CURLOPT_SHARE') && isset($options['curl']) && \is_array($options['curl']) && \array_key_exists((int) \constant('CURLOPT_SHARE'), $options['curl']); } /** * @param array $conf */ private static function hasAuthenticatedHttpProxyState(string $proxy, array $conf): bool { $proxyForParsing = \strpos($proxy, '://') === false ? 'http://'.$proxy : $proxy; $proxyParts = \parse_url($proxyForParsing); if ( \is_array($proxyParts) && (\array_key_exists('user', $proxyParts) || \array_key_exists('pass', $proxyParts)) ) { return true; } if (self::hasCurlProxyCredentials($conf)) { return true; } if (self::hasCurlProxyAuthorizationHeader($conf)) { return true; } $httpHeaders = $conf[\CURLOPT_HTTPHEADER] ?? []; if (\is_array($httpHeaders) && self::proxyAuthorizationHeaderValuesFromList($httpHeaders) !== []) { return true; } return self::hasCurlProxyTlsCredentials($conf); } /** * @param int|string $option */ private static function formatCurlOption($option): string { if (!\is_int($option)) { return \sprintf('"%s"', $option); } static $names = null; if (null === $names) { $names = []; foreach (\get_defined_constants(true)['curl'] ?? [] as $name => $value) { if (\is_int($value) && \strpos($name, 'CURLOPT_') === 0 && !isset($names[$value])) { $names[$value] = $name; } } } if (isset($names[$option])) { return \sprintf('%s (%d)', $names[$option], $option); } return (string) $option; } private static function triggerConflictingCurlOptionDeprecations(array $options): void { if (!isset($options['curl']) || !\is_array($options['curl']) || $options['curl'] === []) { return; } $conflictingOptions = self::conflictingCurlOptions(); $sinceOverrides = self::conflictingCurlOptionSinceOverrides(); foreach ($options['curl'] as $option => $_) { if (!\array_key_exists($option, $conflictingOptions)) { continue; } $name = self::formatCurlOption($option); $replacement = $conflictingOptions[$option]; $since = $sinceOverrides[$option] ?? '7.11'; if ($replacement !== null) { \trigger_deprecation( 'guzzlehttp/guzzle', $since, \sprintf( 'Passing %s in the "curl" request option is deprecated; guzzlehttp/guzzle 8.0 will reject this option because it conflicts with Guzzle-managed request handling. Use %s instead.', $name, $replacement ) ); continue; } \trigger_deprecation( 'guzzlehttp/guzzle', $since, \sprintf( 'Passing %s in the "curl" request option is deprecated; guzzlehttp/guzzle 8.0 will reject this option because it conflicts with Guzzle-managed cURL internals.', $name ) ); } } private static function triggerUnsupportedCurlOptionDeprecations(array $options): void { if (!isset($options['curl']) || !\is_array($options['curl']) || $options['curl'] === []) { return; } if ( \defined('CURLOPT_PROXYHEADER') && \array_key_exists((int) \constant('CURLOPT_PROXYHEADER'), $options['curl']) && !CurlVersion::supportsProxyHeaderSeparation() ) { \trigger_deprecation( 'guzzlehttp/guzzle', '7.15', \sprintf( 'Passing %s in the "curl" request option on a build without proxy header separation support is deprecated; guzzlehttp/guzzle 8.0 will reject this configuration because proxy headers require libcurl 7.37.0 or newer built with proxy header separation support.', self::formatCurlOption((int) \constant('CURLOPT_PROXYHEADER')) ) ); } $supportedOptions = self::supportedCurlOptions(); $conflictingOptions = self::conflictingCurlOptions(); foreach ($options['curl'] as $option => $_) { if ( !\is_int($option) || \array_key_exists($option, $supportedOptions) || \array_key_exists($option, $conflictingOptions) ) { continue; } \trigger_deprecation( 'guzzlehttp/guzzle', '7.12', \sprintf( 'Passing %s in the "curl" request option is deprecated; guzzlehttp/guzzle 8.0 will reject raw cURL options outside the built-in cURL handlers\' allow-list.', self::formatCurlOption($option) ) ); } } private static function triggerUnsupportedRequestOptionDeprecations(array $options): void { if (\array_key_exists('stream_context', $options)) { \trigger_deprecation('guzzlehttp/guzzle', '7.11', 'Passing the "stream_context" request option to a cURL handler is deprecated; guzzlehttp/guzzle 8.0 will reject this option because cURL handlers ignore PHP stream context options.'); } } /** * @return array */ private static function conflictingCurlOptions(): array { static $options = null; if ($options !== null) { return $options; } $options = []; self::addConflictingCurlOption($options, 'CURLOPT_SHARE', 'the "transport_sharing" client option or cURL handler option'); self::addConflictingCurlOption($options, 'CURLOPT_URL', 'the request URI'); self::addConflictingCurlOption($options, 'CURLOPT_PORT', 'the request URI'); self::addConflictingCurlOption($options, 'CURLOPT_CUSTOMREQUEST', 'the request method'); self::addConflictingCurlOption($options, 'CURLOPT_HTTPGET', 'the request method'); self::addConflictingCurlOption($options, 'CURLOPT_POST', 'the request method and body'); self::addConflictingCurlOption($options, 'CURLOPT_PUT', 'the request method and body'); self::addConflictingCurlOption($options, 'CURLOPT_NOBODY', 'the request method'); self::addConflictingCurlOption($options, 'CURLOPT_UPLOAD', 'the request body'); self::addConflictingCurlOption($options, 'CURLOPT_POSTFIELDS', 'the request body'); self::addConflictingCurlOption($options, 'CURLOPT_READFUNCTION', 'the request body'); self::addConflictingCurlOption($options, 'CURLOPT_READDATA', 'the request body'); self::addConflictingCurlOption($options, 'CURLOPT_INFILE', 'the request body'); self::addConflictingCurlOption($options, 'CURLOPT_INFILESIZE', 'the request body'); self::addConflictingCurlOption($options, 'CURLOPT_INFILESIZE_LARGE', 'the request body'); self::addConflictingCurlOption($options, 'CURLOPT_HTTPHEADER', 'the request headers'); self::addConflictingCurlOption($options, 'CURLOPT_USERAGENT', 'the request headers'); self::addConflictingCurlOption($options, 'CURLOPT_REFERER', 'the request headers'); self::addConflictingCurlOption($options, 'CURLOPT_HEADERFUNCTION', 'the "on_headers" request option'); self::addConflictingCurlOption($options, 'CURLOPT_WRITEFUNCTION', 'the "sink" request option'); self::addConflictingCurlOption($options, 'CURLOPT_FILE', 'the "sink" request option'); self::addConflictingCurlOption($options, 'CURLOPT_TIMEOUT', 'the "timeout" request option'); self::addConflictingCurlOption($options, 'CURLOPT_TIMEOUT_MS', 'the "timeout" request option'); self::addConflictingCurlOption($options, 'CURLOPT_CONNECTTIMEOUT', 'the "connect_timeout" request option'); self::addConflictingCurlOption($options, 'CURLOPT_CONNECTTIMEOUT_MS', 'the "connect_timeout" request option'); self::addConflictingCurlOption($options, 'CURLOPT_NOSIGNAL', 'the "timeout" or "connect_timeout" request option'); self::addConflictingCurlOption($options, 'CURLOPT_NOPROGRESS', 'the "progress" request option'); self::addConflictingCurlOption($options, 'CURLOPT_PROGRESSFUNCTION', 'the "progress" request option'); self::addConflictingCurlOption($options, 'CURLOPT_XFERINFOFUNCTION', 'the "progress" request option'); self::addConflictingCurlOption($options, 'CURLOPT_VERBOSE', 'the "debug" request option'); self::addConflictingCurlOption($options, 'CURLOPT_STDERR', 'the "debug" request option'); self::addConflictingCurlOption($options, 'CURLOPT_PROXY', 'the "proxy" request option'); self::addConflictingCurlOption($options, 'CURLOPT_NOPROXY', 'the "proxy" request option'); self::addConflictingCurlOption($options, 'CURLOPT_PROXYTYPE', 'the "proxy" request option with a scheme-prefixed URL'); self::addConflictingCurlOption($options, 'CURLOPT_FOLLOWLOCATION', 'the "allow_redirects" request option'); self::addConflictingCurlOption($options, 'CURLOPT_MAXREDIRS', 'the "allow_redirects" request option'); self::addConflictingCurlOption($options, 'CURLOPT_POSTREDIR', 'the "allow_redirects" request option'); self::addConflictingCurlOption($options, 'CURLOPT_REDIR_PROTOCOLS', 'the "allow_redirects" request option'); self::addConflictingCurlOption($options, 'CURLOPT_REDIR_PROTOCOLS_STR', 'the "allow_redirects" request option'); self::addConflictingCurlOption($options, 'CURLOPT_PROTOCOLS', 'the "protocols" request option'); self::addConflictingCurlOption($options, 'CURLOPT_PROTOCOLS_STR', 'the "protocols" request option'); self::addConflictingCurlOption($options, 'CURLOPT_HTTP_VERSION', 'the request protocol version'); self::addConflictingCurlOption($options, 'CURLOPT_PIPEWAIT', 'the "multiplex" request option'); self::addConflictingCurlOption($options, 'CURLOPT_IPRESOLVE', 'the "force_ip_resolve" request option'); self::addConflictingCurlOption($options, 'CURLOPT_SSL_VERIFYPEER', 'the "verify" request option'); self::addConflictingCurlOption($options, 'CURLOPT_SSL_VERIFYHOST', 'the "verify" request option'); self::addConflictingCurlOption($options, 'CURLOPT_CAINFO', 'the "verify" request option'); self::addConflictingCurlOption($options, 'CURLOPT_CAPATH', 'the "verify" request option'); self::addConflictingCurlOption($options, 'CURLOPT_SSLVERSION', 'the "crypto_method" or "crypto_method_max" request option'); self::addConflictingCurlOption($options, 'CURLOPT_SSLCERT', 'the "cert" request option'); self::addConflictingCurlOption($options, 'CURLOPT_SSLCERTPASSWD', 'the "cert" request option'); self::addConflictingCurlOption($options, 'CURLOPT_SSLCERTTYPE', 'the "cert_type" request option'); self::addConflictingCurlOption($options, 'CURLOPT_SSLKEY', 'the "ssl_key" request option'); self::addConflictingCurlOption($options, 'CURLOPT_SSLKEYPASSWD', 'the "ssl_key" request option'); self::addConflictingCurlOption($options, 'CURLOPT_KEYPASSWD', 'the "ssl_key" request option'); self::addConflictingCurlOption($options, 'CURLOPT_SSLKEYTYPE', 'the "ssl_key_type" request option'); self::addConflictingCurlOption($options, 'CURLOPT_COOKIE', 'the "Cookie" request header or Guzzle cookie middleware'); self::addConflictingCurlOption($options, 'CURLOPT_COOKIEFILE', 'Guzzle cookie middleware'); self::addConflictingCurlOption($options, 'CURLOPT_COOKIEJAR', 'Guzzle cookie middleware'); self::addConflictingCurlOption($options, 'CURLOPT_COOKIELIST', 'Guzzle cookie middleware'); self::addConflictingCurlOption($options, 'CURLOPT_COOKIESESSION', 'Guzzle cookie middleware'); return $options; } /** * @return array */ private static function conflictingCurlOptionSinceOverrides(): array { static $options = null; if ($options !== null) { return $options; } $options = []; if (\defined('CURLOPT_PROXYTYPE')) { $options[\CURLOPT_PROXYTYPE] = '7.12'; } if (\defined('CURLOPT_PIPEWAIT')) { $options[\CURLOPT_PIPEWAIT] = '7.14'; } return $options; } /** * @return array */ private static function supportedCurlOptions(): array { static $options = null; if ($options !== null) { return $options; } $options = []; self::addSupportedCurlOption($options, 'CURLOPT_ADDRESS_SCOPE'); self::addSupportedCurlOption($options, 'CURLOPT_CERTINFO'); self::addSupportedCurlOption($options, 'CURLOPT_CONNECT_TO'); self::addSupportedCurlOption($options, 'CURLOPT_DNS_CACHE_TIMEOUT'); self::addSupportedCurlOption($options, 'CURLOPT_DNS_INTERFACE'); self::addSupportedCurlOption($options, 'CURLOPT_DNS_LOCAL_IP4'); self::addSupportedCurlOption($options, 'CURLOPT_DNS_LOCAL_IP6'); self::addSupportedCurlOption($options, 'CURLOPT_DNS_SERVERS'); self::addSupportedCurlOption($options, 'CURLOPT_DNS_SHUFFLE_ADDRESSES'); self::addSupportedCurlOption($options, 'CURLOPT_ENCODING'); self::addSupportedCurlOption($options, 'CURLOPT_FORBID_REUSE'); self::addSupportedCurlOption($options, 'CURLOPT_FRESH_CONNECT'); self::addSupportedCurlOption($options, 'CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS'); self::addSupportedCurlOption($options, 'CURLOPT_HTTPAUTH'); self::addSupportedCurlOption($options, 'CURLOPT_INTERFACE'); self::addSupportedCurlOption($options, 'CURLOPT_LOCALPORT'); self::addSupportedCurlOption($options, 'CURLOPT_LOCALPORTRANGE'); self::addSupportedCurlOption($options, 'CURLOPT_LOW_SPEED_LIMIT'); self::addSupportedCurlOption($options, 'CURLOPT_LOW_SPEED_TIME'); self::addSupportedCurlOption($options, 'CURLOPT_MAXAGE_CONN'); self::addSupportedCurlOption($options, 'CURLOPT_MAXCONNECTS'); self::addSupportedCurlOption($options, 'CURLOPT_MAXLIFETIME_CONN'); self::addSupportedCurlOption($options, 'CURLOPT_HTTPPROXYTUNNEL'); self::addSupportedCurlOption($options, 'CURLOPT_PREREQFUNCTION'); self::addSupportedCurlOption($options, 'CURLOPT_PROXYHEADER'); self::addSupportedCurlOption($options, 'CURLOPT_PROXYUSERPWD'); self::addSupportedCurlOption($options, 'CURLOPT_RESOLVE'); self::addSupportedCurlOption($options, 'CURLOPT_SSL_CIPHER_LIST'); self::addSupportedCurlOption($options, 'CURLOPT_SSL_EC_CURVES'); self::addSupportedCurlOption($options, 'CURLOPT_TCP_FASTOPEN'); self::addSupportedCurlOption($options, 'CURLOPT_TCP_KEEPALIVE'); self::addSupportedCurlOption($options, 'CURLOPT_TCP_KEEPIDLE'); self::addSupportedCurlOption($options, 'CURLOPT_TCP_KEEPINTVL'); self::addSupportedCurlOption($options, 'CURLOPT_TCP_KEEPCNT'); self::addSupportedCurlOption($options, 'CURLOPT_TCP_NODELAY'); self::addSupportedCurlOption($options, 'CURLOPT_TLS13_CIPHERS'); self::addSupportedCurlOption($options, 'CURLOPT_UNIX_SOCKET_PATH'); self::addSupportedCurlOption($options, 'CURLOPT_USERPWD'); return $options; } /** * @param array $options */ private static function addSupportedCurlOption(array &$options, string $constant): void { if (!\defined($constant)) { return; } $value = \constant($constant); if (\is_int($value)) { $options[$value] = true; } } /** * @param array $options */ private static function addConflictingCurlOption(array &$options, string $constant, ?string $replacement): void { if (!\defined($constant)) { return; } $value = \constant($constant); if (\is_int($value)) { $options[$value] = $replacement; } } public function release(EasyHandle $easy): void { $resource = $easy->handle; unset($easy->handle); if ( \count($this->handles) >= $this->maxHandles || ($easy->proxyTunnelSignature !== null && $easy->proxyTunnelSignature !== $this->proxyTunnelOwner) ) { // Pool is full, or this handle belongs to a superseded tunnel // owner (an async create/release overlap can hand a stale-owner // handle back after a purge) - drop it instead of pooling it. if (PHP_VERSION_ID < 80000) { \curl_close($resource); } return; } if ($easy->proxyTunnelSignature !== null) { // A pooled handle now carries the current owner's tunnel. $this->poolMayHoldTunnels = true; } // Remove all callback functions as they can hold onto references and // are not cleaned up by curl_reset. Using curl_setopt_array does not // work for some reason, so removing each one individually. \curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null); \curl_setopt($resource, \CURLOPT_READFUNCTION, null); \curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null); \curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null); if (\defined('CURLOPT_PREREQFUNCTION')) { \curl_setopt($resource, (int) \constant('CURLOPT_PREREQFUNCTION'), null); } \curl_reset($resource); $this->handles[] = $resource; } /** * Completes a cURL transaction, either returning a response promise or a * rejected promise. * * @param callable(RequestInterface, array): PromiseInterface $handler * @param CurlFactoryInterface $factory Dictates how the handle is released */ public static function finish(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface { if (isset($easy->options['on_stats'])) { try { self::invokeStats($easy); } catch (\Throwable $e) { try { $factory->release($easy); } catch (\Throwable $releaseFailure) { // Keep the on_stats throwable as the visible failure. } throw $e; } } if (!$easy->response || $easy->errno) { return self::finishError($handler, $easy, $factory); } // Return the response if it is present and there is no error. $factory->release($easy); // Rewind the body of the response if possible. $body = $easy->response->getBody(); if ($body->isSeekable()) { $body->rewind(); } if (isset($easy->options['on_trailers'])) { try { ($easy->options['on_trailers'])(self::headersFromTrailerLines($easy->trailers), $easy->response); } catch (\Throwable $e) { return P\Create::rejectionFor( new RequestException( 'An error was encountered during the on_trailers event', $easy->request, $easy->response, $e ) ); } } return new FulfilledPromise($easy->response); } private static function invokeStats(EasyHandle $easy): void { $curlStats = \curl_getinfo($easy->handle); $curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME); $stats = new TransferStats( $easy->request, $easy->response, $curlStats['total_time'], $easy->errno, $curlStats ); ($easy->options['on_stats'])($stats); } /** * @param callable(RequestInterface, array): PromiseInterface $handler */ private static function finishError(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface { // Get error information and release the handle to the factory. $ctx = [ 'errno' => $easy->errno, 'error' => \curl_error($easy->handle), 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME), ] + \curl_getinfo($easy->handle); $ctx[self::CURL_VERSION_STR] = CurlVersion::getVersion() ?? ''; $factory->release($easy); // Retry when nothing is present or when curl failed to rewind. if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) { return self::retryFailedRewind($handler, $easy, $ctx); } return self::createRejection($easy, $ctx); } private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface { static $connectionErrors = [ \CURLE_OPERATION_TIMEOUTED => true, \CURLE_COULDNT_RESOLVE_HOST => true, \CURLE_COULDNT_CONNECT => true, \CURLE_SSL_CONNECT_ERROR => true, \CURLE_GOT_NOTHING => true, ]; $uri = $easy->request->getUri(); // Redact the native error before it reaches any exception so the // handler context matches the sanitized exception message. $ctx['error'] = self::sanitizeCurlError((string) ($ctx['error'] ?? ''), $uri, $easy->effectiveProxy); if ($easy->createResponseException) { return P\Create::rejectionFor( new RequestException( 'An error was encountered while creating the response', $easy->request, null, $easy->createResponseException, $ctx ) ); } // If an exception was encountered during the onHeaders event, then // return a rejected promise that wraps that exception. if ($easy->onHeadersException) { return P\Create::rejectionFor( new RequestException( 'An error was encountered during the on_headers event', $easy->request, $easy->response, $easy->onHeadersException, $ctx ) ); } $sanitizedError = $ctx['error']; $message = \sprintf( 'cURL error %s: %s (%s)', $ctx['errno'], $sanitizedError, 'see https://curl.se/libcurl/c/libcurl-errors.html' ); if ('' !== $sanitizedError) { $redactedUriString = Psr7\Utils::redactUserInfo($uri)->__toString(); if ($redactedUriString !== '' && false === \strpos($sanitizedError, $redactedUriString)) { $message .= \sprintf(' for %s', $redactedUriString); } } // Create a connection exception if it was a specific error code. $error = isset($connectionErrors[$easy->errno]) ? new ConnectException($message, $easy->request, null, $ctx) : new RequestException($message, $easy->request, $easy->response, null, $ctx); return P\Create::rejectionFor($error); } private static function sanitizeCurlError(string $error, UriInterface $uri, ?string $proxy = null): string { if ('' === $error) { return $error; } $error = self::redactProxyUserInfo($error, $proxy); $baseUri = $uri->withQuery('')->withFragment(''); $baseUriString = $baseUri->__toString(); if ('' === $baseUriString) { return $error; } $redactedUriString = Psr7\Utils::redactUserInfo($baseUri)->__toString(); return str_replace($baseUriString, $redactedUriString, $error); } private static function redactProxyUserInfo(string $error, ?string $proxy): string { if ($proxy === null || $proxy === '' || \strpos($proxy, '@') === false) { return $error; } // The error message embeds the proxy string exactly as configured, so // the userinfo needle is taken verbatim from the raw string: // parse_url() and Psr7\Uri normalize the components, e.g. by rewriting // raw control bytes to '_', which could make the replacement miss. $proxyForParsing = \strpos($proxy, '://') === false ? 'http://'.$proxy : $proxy; $remainder = \substr($proxyForParsing, \strpos($proxyForParsing, '://') + 3); if (\parse_url($proxyForParsing) === false) { // Raw '/', '?', or '#' separators may sit inside the credentials // of a proxy that defeats parse_url(), so the redaction cannot // stop at the apparent authority. $atPosition = \strrpos($remainder, '@'); if ($atPosition === false || $atPosition === 0) { return $error; } return \str_replace(\substr($remainder, 0, $atPosition).'@', '***@', $error); } $authority = \substr($remainder, 0, \strcspn($remainder, '/?#')); $atPosition = \strrpos($authority, '@'); if ($atPosition === false || $atPosition === 0) { // A parseable proxy URL with '@' only past its authority, or with // an empty userinfo, carries no credentials to redact. return $error; } $rawUserInfo = \substr($authority, 0, $atPosition); // Redact with the same policy Psr7\Utils::redactUserInfo() applies to // request URIs, so the bundled psr7 version governs the redacted form. $redactedUserInfo = '***'; try { $proxyUri = new Uri($proxyForParsing); $redactedUserInfo = Psr7\Utils::redactUserInfo($proxyUri)->getUserInfo(); if ($redactedUserInfo === $proxyUri->getUserInfo()) { return $error; } } catch (\InvalidArgumentException $e) { // Unparseable as a URI: fall back to redacting the whole userinfo. } return \str_replace($rawUserInfo.'@', $redactedUserInfo.'@', $error); } /** * @param array $conf */ private static function forceFreshConnectionForAuthenticatedProxy(RequestInterface $request, array &$conf): void { $proxy = self::getEffectiveProxy($conf); if ($proxy === null || !self::requiresFreshConnectionForAuthenticatedProxy($request, $proxy, $conf)) { return; } $conf[\CURLOPT_FRESH_CONNECT] = true; $conf[\CURLOPT_FORBID_REUSE] = true; } /** * @param array $conf */ private function isolateOpaqueShareAnonymousProxyTunnel(RequestInterface $request, array &$conf): void { if (!$this->opaqueShareConnectionCache || !CurlVersion::supportsShareConnectionCaches()) { return; } $proxy = self::getEffectiveProxy($conf); if ( $proxy === null || !self::usesProxyTunnel($request, $conf) || !self::isHttpProxyForConnectionReuse($proxy, $conf) || self::hasAuthenticatedHttpProxyState($proxy, $conf) ) { return; } // From libcurl 7.57.0 an opaque share handle can own a connection // cache, and a tunnel seeded there with a literal Proxy-Authorization // header is never keyed on credentials, so an anonymous request could // inherit it on every later libcurl version. Requests carrying // recognized credential state keep the version-gated channel // safeguards above. $conf[\CURLOPT_FRESH_CONNECT] = true; $conf[\CURLOPT_FORBID_REUSE] = true; } /** * @param array $conf */ private static function assertFinalProxyOptionTypes(array $conf, bool $requiredCleartextMultiplex): void { if (\array_key_exists(\CURLOPT_PROXYTYPE, $conf) && !\is_int($conf[\CURLOPT_PROXYTYPE])) { throw new \InvalidArgumentException('CURLOPT_PROXYTYPE must be an integer.'); } foreach (['CURLOPT_PROXY', 'CURLOPT_NOPROXY', 'CURLOPT_PRE_PROXY'] as $name) { if (!\defined($name)) { continue; } $option = (int) \constant($name); if (\array_key_exists($option, $conf) && !\is_string($conf[$option])) { if ($requiredCleartextMultiplex) { throw new \InvalidArgumentException(\sprintf('The "multiplex" request option cannot be required when the final %s cURL option value is not a string.', $name)); } throw new \InvalidArgumentException($name.' must be a string.'); } } } /** * @param array $conf */ private static function isolatePreProxyOnAffectedCurl(array &$conf): void { if (CurlVersion::supportsSocksProxyCredentialAwareConnectionReuse() || !\defined('CURLOPT_PRE_PROXY')) { return; } $option = (int) \constant('CURLOPT_PRE_PROXY'); if (!\array_key_exists($option, $conf) || $conf[$option] === '') { return; } $conf[\CURLOPT_FRESH_CONNECT] = true; $conf[\CURLOPT_FORBID_REUSE] = true; } /** * @param array $conf */ private static function getEffectiveProxy(array $conf): ?string { if (!\array_key_exists(\CURLOPT_PROXY, $conf)) { return null; } $proxy = $conf[\CURLOPT_PROXY]; if (!\is_string($proxy) || $proxy === '') { return null; } // Only the exact raw wildcard is modeled here: libcurl treats '*' as // bypass-all by whole-string comparison, without trimming or host matching. if (\defined('CURLOPT_NOPROXY')) { $noProxy = $conf[(int) \constant('CURLOPT_NOPROXY')] ?? null; if (\is_string($noProxy) && $noProxy === '*') { return null; } } return $proxy; } /** * @param array $conf */ private static function normalizeCurlHeaderOptions(array &$conf): void { $options = [\CURLOPT_HTTPHEADER => 'CURLOPT_HTTPHEADER']; if (\defined('CURLOPT_PROXYHEADER')) { $options[(int) \constant('CURLOPT_PROXYHEADER')] = 'CURLOPT_PROXYHEADER'; } foreach ($options as $option => $label) { if (!\array_key_exists($option, $conf) || !\is_array($conf[$option])) { continue; } $normalized = []; foreach ($conf[$option] as $key => $entry) { if (\is_object($entry) && \method_exists($entry, '__toString')) { $entry = (string) $entry; } elseif (\is_float($entry) && !\is_finite($entry)) { $entry = \is_nan($entry) ? 'NAN' : ($entry > 0 ? 'INF' : '-INF'); } elseif (\is_scalar($entry)) { $entry = (string) $entry; } else { throw new \InvalidArgumentException(\sprintf('%s entries must be strings, stringable objects, or scalar values.', $label)); } if (\strpbrk($entry, "\r\n") !== false) { throw new \InvalidArgumentException(\sprintf('%s entries must not contain a carriage return or line feed.', $label)); } $normalized[$key] = $entry; } $conf[$option] = $normalized; } } private static function proxyScheme(string $proxy): ?string { $position = \strpos($proxy, '://'); return $position === false ? null : Psr7\Utils::asciiToLower(\substr($proxy, 0, $position)); } /** * @param array $conf */ private static function requiresFreshConnectionForAuthenticatedProxy(RequestInterface $request, string $proxy, array $conf): bool { // SOCKS authentication binds an identity to the connection itself, and // below 7.69.0 an opaque configured share may already contain a SOCKS // connection whose credential state Guzzle cannot inspect. Isolate // authenticated and anonymous requests so neither can inherit it. if (self::isSocksProxy($proxy, $conf)) { return !CurlVersion::supportsSocksProxyCredentialAwareConnectionReuse(); } if (!self::usesProxyTunnel($request, $conf) || !self::isHttpProxyForConnectionReuse($proxy, $conf)) { return false; } $proxyForParsing = \strpos($proxy, '://') === false ? 'http://'.$proxy : $proxy; $proxyParts = \parse_url($proxyForParsing); if (!\is_array($proxyParts)) { return false; } if (self::hasCurlProxyAuthorizationHeader($conf)) { return true; } // A proxy client certificate or TLS-SRP authenticates the client to the // HTTPS proxy at the TLS layer; libcurl ignored TLS-SRP before 7.83.1 // (CVE-2022-27782), so an old build can reuse a tunnel across those // identities. Force a fresh one, as the non-share signature path does. if ( !CurlVersion::supportsProxyTlsCredentialAwareConnectionReuse() && self::hasCurlProxyTlsCredentials($conf) ) { return true; } if (CurlVersion::supportsProxyCredentialAwareConnectionReuse()) { return false; } return \array_key_exists('user', $proxyParts) || \array_key_exists('pass', $proxyParts) || self::hasCurlProxyCredentials($conf); } /** * @param array $conf */ private static function hasAuthenticatedSocksProxyState(string $proxy, array $conf): bool { $proxyForParsing = \strpos($proxy, '://') === false ? 'http://'.$proxy : $proxy; $proxyParts = \parse_url($proxyForParsing); if ( \is_array($proxyParts) && (\array_key_exists('user', $proxyParts) || \array_key_exists('pass', $proxyParts)) ) { return true; } return self::hasCurlProxyCredentials($conf); } /** * @param array $conf */ private static function usesProxyTunnel(RequestInterface $request, array $conf): bool { $scheme = $request->getUri()->getScheme(); if ('https' === $scheme) { return true; } // An HTTP proxy auto-switches to a CONNECT tunnel when CONNECT_TO // redirects the origin, so an http:// target with it set tunnels too. if ('http' === $scheme && self::hasCurlConnectTo($conf)) { return true; } return \defined('CURLOPT_HTTPPROXYTUNNEL') && \array_key_exists((int) \constant('CURLOPT_HTTPPROXYTUNNEL'), $conf) && (bool) $conf[(int) \constant('CURLOPT_HTTPPROXYTUNNEL')]; } /** * @param array $conf */ private static function hasCurlConnectTo(array $conf): bool { if (!\defined('CURLOPT_CONNECT_TO')) { return false; } $option = (int) \constant('CURLOPT_CONNECT_TO'); if (!\array_key_exists($option, $conf)) { return false; } $value = $conf[$option]; return \is_array($value) ? $value !== [] : $value !== null && $value !== false && $value !== ''; } /** * @param array $conf */ private static function isHttpProxyForConnectionReuse(string $proxy, array $conf): bool { if (\strpos($proxy, '://') !== false) { $proxyParts = \parse_url($proxy); if (!\is_array($proxyParts) || !isset($proxyParts['scheme'])) { return false; } $proxyScheme = Psr7\Utils::asciiToLower($proxyParts['scheme']); return $proxyScheme === 'http' || $proxyScheme === 'https'; } return !self::isSocksProxyType($conf[\CURLOPT_PROXYTYPE] ?? null); } /** * @param array $conf */ private static function isSocksProxy(string $proxy, array $conf): bool { $scheme = self::proxyScheme($proxy); if ($scheme !== null) { if (\in_array($scheme, ['socks', 'socks4', 'socks4a', 'socks5', 'socks5h'], true)) { return true; } // libcurl preserves a raw SOCKS CURLOPT_PROXYTYPE behind an http // scheme, while every other scheme overrides the proxy type. if ($scheme !== 'http') { return false; } } return self::isSocksProxyType($conf[\CURLOPT_PROXYTYPE] ?? null); } /** * Computes the connection-reuse section signature for a SOCKS proxy. * libcurl compares SOCKS credentials on connection reuse from 7.69.0 (curl * #4835), so no sectioning is needed there. Older libcurl matches a SOCKS * proxy by type, host, and port only, so every SOCKS request is sectioned * by its credential state; hashing the credential-less state too keeps an * unauthenticated request from inheriting an authenticated connection. * * @param array $conf */ private static function socksProxySignature(string $proxy, array $conf): ?string { if (CurlVersion::supportsSocksProxyCredentialAwareConnectionReuse()) { return null; } $credentialState = []; foreach (['CURLOPT_PROXYUSERPWD', 'CURLOPT_PROXYUSERNAME', 'CURLOPT_PROXYPASSWORD', 'CURLOPT_PROXYTYPE'] as $name) { $credentialState[$name] = \defined($name) ? ($conf[(int) \constant($name)] ?? null) : null; } return \hash('sha256', \serialize(['socks', $proxy, $credentialState])); } /** * @param mixed $proxyType */ private static function isSocksProxyType($proxyType): bool { if (!\is_int($proxyType)) { return false; } foreach ([ 'CURLPROXY_SOCKS4' => 4, 'CURLPROXY_SOCKS5' => 5, 'CURLPROXY_SOCKS4A' => 6, 'CURLPROXY_SOCKS5_HOSTNAME' => 7, ] as $name => $fallback) { $value = \defined($name) ? (int) \constant($name) : $fallback; if ($proxyType === $value) { return true; } } return false; } /** * @param array $conf */ private static function hasCurlProxyCredentials(array $conf): bool { foreach (['CURLOPT_PROXYUSERPWD', 'CURLOPT_PROXYUSERNAME', 'CURLOPT_PROXYPASSWORD'] as $option) { if (\defined($option) && \array_key_exists((int) \constant($option), $conf)) { return true; } } return false; } /** * @param array $conf */ private static function hasCurlProxyTlsCredentials(array $conf): bool { foreach ([ 'CURLOPT_PROXY_SSLCERT', 'CURLOPT_PROXY_SSLCERT_BLOB', 'CURLOPT_PROXY_TLSAUTH_USERNAME', 'CURLOPT_PROXY_TLSAUTH_PASSWORD', ] as $option) { if (\defined($option) && \array_key_exists((int) \constant($option), $conf)) { return true; } } return false; } /** * @param array $conf */ private static function hasCurlProxyAuthorizationHeader(array $conf): bool { return self::curlProxyAuthorizationHeaderValues($conf) !== []; } /** * @param array $conf */ private static function applyProxyAuthorizationHeaderHandling(RequestInterface $request, array &$conf): void { $proxy = self::getEffectiveProxy($conf); if ($proxy === null || !self::isHttpProxyForConnectionReuse($proxy, $conf)) { return; } $httpHeaders = $conf[\CURLOPT_HTTPHEADER] ?? null; $movedHeaders = []; $originHeaders = []; if (\is_array($httpHeaders)) { foreach ($httpHeaders as $header) { if (\is_string($header) && self::isProxyAuthorizationHeaderLine($header)) { $movedHeaders[] = $header; continue; } $originHeaders[] = $header; } } if (CurlVersion::supportsProxyHeaderSeparation()) { if ($movedHeaders !== []) { $conf[\CURLOPT_HTTPHEADER] = $originHeaders; self::appendCurlProxyHeaders($conf, $movedHeaders); } // On libcurl 7.37.0-7.42.0 the default is CURLHEADER_UNIFIED. if ($movedHeaders !== [] || self::hasCurlProxyHeaderOption($conf) || self::usesProxyTunnel($request, $conf)) { $conf[(int) \constant('CURLOPT_HEADEROPT')] = (int) \constant('CURLHEADER_SEPARATE'); } return; } if (\is_array($httpHeaders) && self::proxyAuthorizationHeaderValuesFromList($httpHeaders) !== []) { $conf[\CURLOPT_FRESH_CONNECT] = true; $conf[\CURLOPT_FORBID_REUSE] = true; } } /** * Routes the managed first-class Proxy-Authorization values to libcurl's * proxy-only header channel, independently of Guzzle's proxy prediction: * libcurl alone decides whether the proxy-only list is used for the * actual transfer, so the credential can never reach an origin through * CURLOPT_HTTPHEADER. Without proxy header separation support, values are * safely omitted on known direct, bypassed, and SOCKS routes; a route that * may use an HTTP(S) proxy is rejected before cURL initialization and * network I/O. A deprecated raw CURLOPT_HTTPHEADER replacement suppresses * every generated header, the managed values included. * * @param array $conf * @param list $headers */ private static function applyManagedProxyAuthorization(RequestInterface $request, array &$conf, array $headers, bool $rawHttpHeadersReplaceManaged): void { if ($rawHttpHeadersReplaceManaged || $headers === []) { return; } if (!CurlVersion::supportsProxyHeaderSeparation()) { $proxy = self::getEffectiveProxy($conf); if ($proxy !== null && !self::isSocksProxy($proxy, $conf)) { throw new RequestException('Proxy-Authorization request headers through a possible HTTP or HTTPS proxy require libcurl 7.37.0 or newer built with proxy header separation support.', $request); } return; } self::appendCurlProxyHeaders($conf, $headers); $conf[(int) \constant('CURLOPT_HEADEROPT')] = (int) \constant('CURLHEADER_SEPARATE'); } /** * @return list */ private static function managedProxyAuthorizationHeaderLines(RequestInterface $request): array { $headers = []; foreach ($request->getHeader('Proxy-Authorization') as $value) { $headers[] = $value === '' ? 'Proxy-Authorization;' : 'Proxy-Authorization: '.$value; } return $headers; } /** * @param array $conf * @param list $headers */ private static function appendCurlProxyHeaders(array &$conf, array $headers): void { $option = (int) \constant('CURLOPT_PROXYHEADER'); if (\array_key_exists($option, $conf)) { if (!\is_array($conf[$option])) { throw new \InvalidArgumentException('CURLOPT_PROXYHEADER must be an array when a Proxy-Authorization request header is routed to the proxy header channel.'); } $headers = \array_merge($conf[$option], $headers); } $conf[$option] = $headers; } /** * @param array $conf */ private static function hasCurlProxyHeaderOption(array $conf): bool { return \defined('CURLOPT_PROXYHEADER') && \array_key_exists((int) \constant('CURLOPT_PROXYHEADER'), $conf); } private static function isProxyAuthorizationHeaderLine(string $header): bool { $length = \strcspn($header, ':;'); if ($length === \strlen($header)) { return false; } return Psr7\Utils::caselessEquals(\trim(\substr($header, 0, $length), " \n\r\t\0\x0B"), 'Proxy-Authorization'); } private static function proxyAuthorizationHeaderValue(string $header): ?string { $position = \strpos($header, ':'); if ($position === false) { return null; } if (!Psr7\Utils::caselessEquals(\trim(\substr($header, 0, $position), " \n\r\t\0\x0B"), 'Proxy-Authorization')) { return null; } $value = \trim(\substr($header, $position + 1), " \n\r\t\0\x0B"); return $value === '' ? null : $value; } /** * @param mixed[] $headers * * @return list */ private static function proxyAuthorizationHeaderValuesFromList(array $headers): array { $values = []; foreach ($headers as $header) { if (!\is_string($header)) { continue; } $value = self::proxyAuthorizationHeaderValue($header); if ($value !== null) { $values[] = $value; } } return $values; } /** * Computes the connection-reuse section signature for a proxy tunnel or * SOCKS proxy, or null when the request does not require sectioning. * * @param array $conf */ private static function proxyTunnelSignature(RequestInterface $request, array $conf): ?string { $proxy = self::getEffectiveProxy($conf); if ($proxy === null) { return null; } // SOCKS authentication binds an identity to the connection itself, for // plain http:// requests as much as https://, so it sections ahead of // the CONNECT tunnel domain checks. if (self::isSocksProxy($proxy, $conf)) { return self::socksProxySignature($proxy, $conf); } if ( !self::usesProxyTunnel($request, $conf) || !self::isHttpProxyForConnectionReuse($proxy, $conf) ) { return null; } $headerAuth = self::curlProxyAuthorizationHeaderValues($conf); if ($headerAuth === [] && CurlVersion::supportsProxyCredentialAwareConnectionReuse()) { // libcurl keys reuse on parsed proxy credentials only from 8.19.0, // trusted from 8.20.0 (PROXY_CREDENTIAL_REUSE_VERSION); a literal // Proxy-Authorization header is never keyed and always sections. return self::DELEGATED_PROXY_TUNNEL_OWNER; } // Hash every proxy channel an old libcurl might not key reuse on. A // changed signature only forces a fresh connection, never relaxes // reuse, so over-covering is always safe; under-covering leaks. Proxy // credentials are the channel CVE-2026-3784 missed; the proxy-TLS // options are load-bearing on builds before the proxy-TLS reuse fixes // (the proxy client cert is keyed from 7.52.0, libcurl's first // HTTPS-proxy release; CVE-2016-5420 (7.50.1) is only the origin-cert // precedent; TLS-SRP from 7.83.1, CVE-2022-27782) and harmless after. // The private-key file and passphrase are hashed on this non-delegated // path too, as fallback hardening: libcurl's mTLS private-key matching // on reuse was incomplete before 8.21.0 (CVE-2026-8932). This does not // cover the delegated path (the early return above) or configured share // handles, so it is not a complete pre-8.21.0 mitigation. The key blob // and cert/key type encodings (PROXY_SSLKEY_BLOB, PROXY_SSLKEYTYPE, // PROXY_SSLCERTTYPE) are not hashed and are an accepted residual. $credentialState = []; foreach ([ 'CURLOPT_PROXYUSERPWD', 'CURLOPT_PROXYUSERNAME', 'CURLOPT_PROXYPASSWORD', 'CURLOPT_PROXYTYPE', 'CURLOPT_PROXY_SSLCERT', 'CURLOPT_PROXY_SSLCERT_BLOB', 'CURLOPT_PROXY_SSLKEY', 'CURLOPT_PROXY_KEYPASSWD', 'CURLOPT_PROXY_TLSAUTH_USERNAME', 'CURLOPT_PROXY_TLSAUTH_PASSWORD', 'CURLOPT_PROXY_SSLVERSION', ] as $name) { $credentialState[$name] = \defined($name) ? ($conf[(int) \constant($name)] ?? null) : null; } return \hash('sha256', \serialize([$proxy, $credentialState, $headerAuth])); } /** * @param array $conf * * @return list */ private static function curlProxyAuthorizationHeaderValues(array $conf): array { if (!\defined('CURLOPT_PROXYHEADER')) { return []; } $option = (int) \constant('CURLOPT_PROXYHEADER'); if (!\array_key_exists($option, $conf)) { return []; } $headers = $conf[$option]; if (!\is_array($headers)) { return []; } return self::proxyAuthorizationHeaderValuesFromList($headers); } private function discardIdleHandles(): void { foreach ($this->handles as $id => $handle) { if (PHP_VERSION_ID < 80000) { \curl_close($handle); } unset($this->handles[$id]); } } /** * @return array */ private function getDefaultConf(EasyHandle $easy): array { $uri = $easy->request->getUri(); $protocols = Utils::normalizeProtocols($easy->options['protocols'] ?? ['http', 'https']); $scheme = $uri->getScheme(); if (!\in_array($scheme, $protocols, true)) { throw new RequestException(\sprintf('The scheme "%s" is not allowed by the protocols request option.', $scheme), $easy->request); } if ($uri->getHost() === '') { throw new RequestException('URI must include a scheme and host. Use an absolute URI, a network-path reference starting with //, or configure a base_uri.', $easy->request); } $conf = [ '_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $uri->withFragment(''), \CURLOPT_RETURNTRANSFER => false, \CURLOPT_HEADER => false, \CURLOPT_CONNECTTIMEOUT => 300, ]; if (\defined('CURLOPT_PROTOCOLS')) { $conf[\CURLOPT_PROTOCOLS] = self::curlProtocolMask($protocols); } $version = $easy->request->getProtocolVersion(); $multiplex = self::normalizeMultiplex($easy->options); if ('2' === $version || '2.0' === $version) { if (\in_array($multiplex, [Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) { self::assertRequiredMultiplexSupported($easy); // New HTTP/2 connections cannot negotiate HTTP/1.x here, and // the 8.14.0 floor's version-aware reuse matching keeps // reused connections on HTTP/2 as well. $conf[\CURLOPT_HTTP_VERSION] = (int) \constant('CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE'); } else { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0; } if (\in_array($multiplex, [Multiplexing::WAIT, Multiplexing::REQUIRE_WAIT], true) && CurlVersion::supportsMultiplex()) { // Wait for a connection that is still being established to the // same origin to reveal whether it can be multiplexed instead // of immediately opening another connection. $conf[(int) \constant('CURLOPT_PIPEWAIT')] = true; } } elseif ('1.1' === $version) { if (\in_array($multiplex, [Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) { throw new ConnectException(\sprintf('The "multiplex" request option cannot be required for HTTP/%s requests; use protocol version 2.', $version), $easy->request); } $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1; } else { if (\in_array($multiplex, [Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) { throw new ConnectException(\sprintf('The "multiplex" request option cannot be required for HTTP/%s requests; use protocol version 2.', $version), $easy->request); } $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0; } return $conf; } /** * @param string[] $protocols */ private static function curlProtocolMask(array $protocols): int { $mask = 0; if (\in_array('http', $protocols, true)) { $mask |= \CURLPROTO_HTTP; } if (\in_array('https', $protocols, true)) { $mask |= \CURLPROTO_HTTPS; } return $mask; } /** * @param mixed $type */ private static function normalizeTlsFileType(string $option, $type): string { if (!\is_string($type) || $type === '') { throw new \InvalidArgumentException(\sprintf('%s must be a non-empty string', $option)); } return Psr7\Utils::asciiToUpper($type); } private static function shouldValidateSslKeyFile(?string $type): bool { return $type !== 'ENG' && $type !== 'PROV'; } private function applyMethod(EasyHandle $easy, array &$conf): void { if ($easy->request->getMethod() === 'HEAD') { // libcurl stops at HEAD response headers only when CURLOPT_NOBODY // is set; CURLOPT_CUSTOMREQUEST changes only the method string. // NOBODY also suppresses request upload, so strip non-zero body // length, transfer coding, and a 100-continue expectation. $conf[\CURLOPT_CUSTOMREQUEST] = null; $conf[\CURLOPT_NOBODY] = true; unset( $conf[\CURLOPT_WRITEFUNCTION], $conf[\CURLOPT_READFUNCTION], $conf[\CURLOPT_FILE], $conf[\CURLOPT_INFILE] ); if (\trim($easy->request->getHeaderLine('Content-Length'), " \n\r\t\0\x0B") !== '0') { $this->removeHeader('Content-Length', $conf); } $this->removeHeader('Transfer-Encoding', $conf); if (Psr7\Utils::caselessEquals(\trim($easy->request->getHeaderLine('Expect'), " \n\r\t\0\x0B"), '100-continue')) { $this->removeHeader('Expect', $conf); } return; } $body = $easy->request->getBody(); $size = $body->getSize(); if ($size === null || $size > 0) { $this->applyBody($easy->request, $easy->options, $conf); return; } $method = $easy->request->getMethod(); if ($method === 'PUT' || $method === 'POST') { // See https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2 if (!$easy->request->hasHeader('Content-Length')) { $conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0'; } } } private function applyBody(RequestInterface $request, array $options, array &$conf): void { $size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') : null; // Send the body as a string if the size is less than 1MB OR if the // [curl][body_as_string] request value is set. if (($size !== null && $size < 1000000) || !empty($options['_body_as_string'])) { $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody(); // Don't duplicate the Content-Length header $this->removeHeader('Content-Length', $conf); $this->removeHeader('Transfer-Encoding', $conf); } else { $conf[\CURLOPT_UPLOAD] = true; if ($size !== null) { $conf[\CURLOPT_INFILESIZE] = $size; $this->removeHeader('Content-Length', $conf); } $body = $request->getBody(); if ($body->isSeekable()) { $body->rewind(); } $remaining = $size; $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body, &$remaining) { if ($remaining === 0) { return ''; } $limit = $remaining === null ? $length : \min($length, $remaining); $data = $body->read($limit); if ($remaining !== null) { $remaining -= \strlen($data); } return $data; }; } // If the Expect header is not present, prevent curl from adding it if (!$request->hasHeader('Expect')) { $conf[\CURLOPT_HTTPHEADER][] = 'Expect:'; } // cURL sometimes adds a content-type by default. Prevent this. if (!$request->hasHeader('Content-Type')) { $conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:'; } } private function applyHeaders(EasyHandle $easy, array &$conf): void { foreach ($conf['_headers'] as $name => $values) { // A first-class Proxy-Authorization header is proxy-scoped and // must never be generated in the origin header list; managed // handling routes it to CURLOPT_PROXYHEADER or safely omits it on // a legacy non-HTTP-proxy route. The // caselessEquals() helper is locale-independent, unlike // strcasecmp(), so a locale cannot make this match miss and // re-leak the credential. if (Psr7\Utils::caselessEquals((string) $name, 'Proxy-Authorization')) { continue; } foreach ($values as $value) { $value = (string) $value; if ($value === '') { // cURL requires a special format for empty headers. // See https://github.com/guzzle/guzzle/issues/1882 for more details. $conf[\CURLOPT_HTTPHEADER][] = "$name;"; } else { $conf[\CURLOPT_HTTPHEADER][] = "$name: $value"; } } } // Remove the Accept header if one was not set if (!$easy->request->hasHeader('Accept')) { $conf[\CURLOPT_HTTPHEADER][] = 'Accept:'; } } /** * Remove a header from the options array. * * @param string $name Case-insensitive header to remove * @param array $options Array of options to modify */ private function removeHeader(string $name, array &$options): void { foreach (\array_keys($options['_headers']) as $key) { if (Psr7\Utils::caselessEquals((string) $key, $name)) { unset($options['_headers'][$key]); return; } } } private function applyHandlerOptions(EasyHandle $easy, array &$conf): void { $options = $easy->options; if (isset($options['verify'])) { if ($options['verify'] === false) { unset($conf[\CURLOPT_CAINFO]); $conf[\CURLOPT_SSL_VERIFYHOST] = 0; $conf[\CURLOPT_SSL_VERIFYPEER] = false; } else { $conf[\CURLOPT_SSL_VERIFYHOST] = 2; $conf[\CURLOPT_SSL_VERIFYPEER] = true; if (\is_string($options['verify'])) { // Throw an error if the file/folder/link path is not valid or doesn't exist. if (!\file_exists($options['verify'])) { throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}"); } // If it's a directory or a link to a directory use CURLOPT_CAPATH. // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO. if ( \is_dir($options['verify']) || ( \is_link($options['verify']) === true && ($verifyLink = \readlink($options['verify'])) !== false && \is_dir($verifyLink) ) ) { $conf[\CURLOPT_CAPATH] = $options['verify']; } else { $conf[\CURLOPT_CAINFO] = $options['verify']; } } } } if (!isset($options['curl'][\CURLOPT_ENCODING]) && isset($options['decode_content']) && $options['decode_content'] !== false) { $accept = $easy->request->getHeaderLine('Accept-Encoding'); if ($accept !== '') { $conf[\CURLOPT_ENCODING] = $accept; } else { // The empty string enables all available decoders and implicitly // sets a matching 'Accept-Encoding' header. $conf[\CURLOPT_ENCODING] = ''; // But as the user did not specify any encoding preference, // let's leave it up to server by preventing curl from sending // the header, which will be interpreted as 'Accept-Encoding: *'. // https://www.rfc-editor.org/rfc/rfc9110#field.accept-encoding $conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; } } if (!isset($options['sink'])) { // Use a default temp stream if no sink was set. $options['sink'] = Psr7\Utils::tryFopen('php://temp', 'w+'); } $sink = $options['sink']; if (!\is_string($sink)) { $sink = Psr7\Utils::streamFor($sink); } elseif (!\is_dir(\dirname($sink))) { // Ensure that the directory exists before failing in curl. throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink)); } else { $sink = new LazyOpenStream($sink, 'w+'); } $easy->sink = $sink; $conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use ($sink): int { return $sink->write($write); }; $timeoutRequiresNoSignal = false; if (isset($options['timeout'])) { $timeoutRequiresNoSignal |= $options['timeout'] < 1; $conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000; } // CURL default value is CURL_IPRESOLVE_WHATEVER if (isset($options['force_ip_resolve'])) { if ('v4' === $options['force_ip_resolve']) { $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4; } elseif ('v6' === $options['force_ip_resolve']) { $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6; } } if (isset($options['connect_timeout'])) { $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1; $conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000; } if ($timeoutRequiresNoSignal && Psr7\Utils::asciiToUpper(\substr(\PHP_OS, 0, 3)) !== 'WIN') { $conf[\CURLOPT_NOSIGNAL] = true; } // Always pin CURLOPT_PROXY (and CURLOPT_NOPROXY when available) so // that libcurl never falls back to reading proxy environment // variables itself. When the proxy request option makes no decision, // the environment is resolved here with libcurl's own semantics. [$proxyConf, $noProxyConf] = self::resolveProxy($easy->request, $options); self::assertResolvedProxySupported($easy->request, $proxyConf); $conf[\CURLOPT_PROXY] = $proxyConf; if (\defined('CURLOPT_NOPROXY')) { $conf[(int) \constant('CURLOPT_NOPROXY')] = $noProxyConf; } $this->applyTlsVersionRange($easy, $conf); $certType = null; if (isset($options['cert_type'])) { $certType = self::normalizeTlsFileType('cert_type', $options['cert_type']); $conf[\CURLOPT_SSLCERTTYPE] = $certType; } if (isset($options['cert'])) { $cert = $options['cert']; if (\is_array($cert)) { if (!isset($cert[0]) || !\is_string($cert[0])) { throw new \InvalidArgumentException('Invalid cert request option'); } if (isset($cert[1])) { if (!\is_string($cert[1])) { throw new \InvalidArgumentException('Invalid cert request option'); } $conf[\CURLOPT_SSLCERTPASSWD] = $cert[1]; } $cert = $cert[0]; } if (!\is_string($cert)) { throw new \InvalidArgumentException('Invalid cert request option'); } if (!\file_exists($cert)) { throw new \InvalidArgumentException("SSL certificate not found: {$cert}"); } // OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files. // see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html $ext = pathinfo($cert, \PATHINFO_EXTENSION); if ($certType === null && preg_match('#^(der|p12)$#iD', $ext)) { $conf[\CURLOPT_SSLCERTTYPE] = Psr7\Utils::asciiToUpper($ext); } $conf[\CURLOPT_SSLCERT] = $cert; } $sslKeyType = null; if (isset($options['ssl_key_type'])) { $sslKeyType = self::normalizeTlsFileType('ssl_key_type', $options['ssl_key_type']); $conf[\CURLOPT_SSLKEYTYPE] = $sslKeyType; } if (isset($options['ssl_key'])) { if (\is_array($options['ssl_key'])) { if (!isset($options['ssl_key'][0]) || !\is_string($options['ssl_key'][0])) { throw new \InvalidArgumentException('Invalid ssl_key request option'); } if (isset($options['ssl_key'][1])) { if (!\is_string($options['ssl_key'][1])) { throw new \InvalidArgumentException('Invalid ssl_key request option'); } $conf[\CURLOPT_SSLKEYPASSWD] = $options['ssl_key'][1]; } $sslKey = $options['ssl_key'][0]; } $sslKey = $sslKey ?? $options['ssl_key']; if (!\is_string($sslKey)) { throw new \InvalidArgumentException('Invalid ssl_key request option'); } if (self::shouldValidateSslKeyFile($sslKeyType) && !\file_exists($sslKey)) { throw new \InvalidArgumentException("SSL private key not found: {$sslKey}"); } $conf[\CURLOPT_SSLKEY] = $sslKey; } if (isset($options['progress'])) { $progress = $options['progress']; if (!\is_callable($progress)) { throw new \InvalidArgumentException('progress client option must be callable'); } $conf[\CURLOPT_NOPROGRESS] = false; $conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use ($progress) { $progress($downloadSize, $downloaded, $uploadSize, $uploaded); }; } if (!empty($options['debug'])) { $conf[\CURLOPT_STDERR] = Utils::debugResource($options['debug']); $conf[\CURLOPT_VERBOSE] = true; } } private function applyTlsVersionRange(EasyHandle $easy, array &$conf): void { $options = $easy->options; $cryptoMethod = $options['crypto_method'] ?? null; $cryptoMethodMax = $options['crypto_method_max'] ?? null; if ($cryptoMethod === null && $cryptoMethodMax === null) { return; } $protocolVersion = $easy->request->getProtocolVersion(); $isHttp2 = '2' === $protocolVersion || '2.0' === $protocolVersion; if ($isHttp2 && $cryptoMethodMax !== null && TlsVersion::ordinal('crypto_method_max', $cryptoMethodMax) < 12) { throw new \InvalidArgumentException( 'Invalid crypto_method_max request option: HTTP/2 requires TLS 1.2 or higher' ); } if ($isHttp2 && $cryptoMethod !== null && TlsVersion::ordinal('crypto_method', $cryptoMethod) < 12) { $cryptoMethod = \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; } TlsVersion::assertRange($cryptoMethod, $cryptoMethodMax); $sslVersion = $cryptoMethod === null ? \CURL_SSLVERSION_DEFAULT : self::curlMinSslVersion($cryptoMethod); if ($cryptoMethodMax !== null) { $sslVersion |= self::curlMaxSslVersion($cryptoMethodMax); } $conf[\CURLOPT_SSLVERSION] = $sslVersion; } /** * @param mixed $value */ private static function curlMinSslVersion($value): int { if ($value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT) { return \CURL_SSLVERSION_TLSv1_0; } if ($value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT) { return \CURL_SSLVERSION_TLSv1_1; } if ($value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT) { if (!CurlVersion::supportsTls12()) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL'); } return \CURL_SSLVERSION_TLSv1_2; } if (\defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) { if (!CurlVersion::supportsTls13()) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL'); } return \CURL_SSLVERSION_TLSv1_3; } throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); } /** * @param mixed $value */ private static function curlMaxSslVersion($value): int { if ($value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT) { return self::requireCurlMaxSslVersion('CURL_SSLVERSION_MAX_TLSv1_0'); } if ($value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT) { return self::requireCurlMaxSslVersion('CURL_SSLVERSION_MAX_TLSv1_1'); } if ($value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT) { return self::requireCurlMaxSslVersion('CURL_SSLVERSION_MAX_TLSv1_2'); } if (\defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) { return self::requireCurlMaxSslVersion('CURL_SSLVERSION_MAX_TLSv1_3'); } throw new \InvalidArgumentException('Invalid crypto_method_max request option: unknown version provided'); } private static function requireCurlMaxSslVersion(string $constant): int { if (\defined($constant)) { /** @var int */ return \constant($constant); } throw new \InvalidArgumentException( 'Invalid crypto_method_max request option: maximum TLS version control is not supported by your version of cURL' ); } private static function validateRequestUriScheme(RequestInterface $request): void { $scheme = $request->getUri()->getScheme(); if ($scheme === '') { throw new RequestException('URI must include a scheme and host. Use an absolute URI, a network-path reference starting with //, or configure a base_uri.', $request); } if (!\in_array($scheme, ['http', 'https'], true)) { throw new RequestException(\sprintf("The scheme '%s' is not supported.", $scheme), $request); } } /** * This function ensures that a response was set on a transaction. If one * was not set, then the request is retried if possible. This error * typically means you are sending a payload, curl encountered a * "Connection died, retrying a fresh connect" error, tried to rewind the * stream, and then encountered a "necessary data rewind wasn't possible" * error, causing the request to be sent through curl_multi_info_read() * without an error status. * * @param callable(RequestInterface, array): PromiseInterface $handler */ private static function retryFailedRewind(callable $handler, EasyHandle $easy, array $ctx): PromiseInterface { try { // Only rewind if the body has been read from. $body = $easy->request->getBody(); if ($body->tell() > 0) { $body->rewind(); } } catch (\RuntimeException $e) { $ctx['error'] = 'The connection unexpectedly failed without ' .'providing an error. The request would have been retried, ' .'but attempting to rewind the request body failed. ' .'Exception: '.$e; return self::createRejection($easy, $ctx); } // Retry no more than 3 times before giving up. if (!isset($easy->options['_curl_retries'])) { $easy->options['_curl_retries'] = 1; } elseif ($easy->options['_curl_retries'] == 2) { $ctx['error'] = 'The cURL request was retried 3 times ' .'and did not succeed. The most likely reason for the failure ' .'is that cURL was unable to rewind the body of the request ' .'and subsequent retries resulted in the same error. Turn on ' .'the debug option to see what went wrong. See ' .'https://bugs.php.net/bug.php?id=47204 for more information.'; return self::createRejection($easy, $ctx); } else { ++$easy->options['_curl_retries']; } return $handler($easy->request, $easy->options); } /** * Parses validated trailer field lines into an associative array keyed by * lowercased field name, preserving first-occurrence key order and wire * value order. */ private static function headersFromTrailerLines(array $lines): array { $headers = []; foreach ($lines as $line) { [$name, $value] = \explode(':', $line, 2); $name = Psr7\Utils::asciiToLower(\trim($name, " \n\r\t\0\x0B")); $headers[$name][] = \trim($value, " \n\r\t\0\x0B"); } return $headers; } private function createHeaderFn(EasyHandle $easy): callable { if (isset($easy->options['on_headers'])) { $onHeaders = $easy->options['on_headers']; if (!\is_callable($onHeaders)) { throw new \InvalidArgumentException('on_headers must be callable'); } } else { $onHeaders = null; } $startingResponse = false; $collectingTrailers = false; $retainTrailers = isset($easy->options['on_trailers']); return static function ($ch, $h) use ( $onHeaders, $easy, &$startingResponse, &$collectingTrailers, $retainTrailers ) { $value = \trim($h, " \n\r\t\0\x0B"); if ($h === "\r\n" || $h === "\n" || $h === "\r" || $h === '') { if ($collectingTrailers) { // A blank line ends the trailer section; the response has // already been created. return \strlen($h); } $startingResponse = true; try { $easy->createResponse(); } catch (\Throwable $e) { $easy->response = null; $easy->createResponseException = $e; return -1; } if ($onHeaders !== null) { try { $onHeaders($easy->response); } catch (\Throwable $e) { // Associate the exception with the handle and trigger // a curl header write error by returning 0. $easy->onHeadersException = $e; return -1; } } } elseif ($startingResponse || $collectingTrailers) { if ($easy->response !== null && !HeaderProcessor::isStatusLineCandidate($h)) { // Trailer fields arrive through the header callback after // the body; a new header block always begins with a status // line. $collectingTrailers = true; if ($retainTrailers && HeaderProcessor::isValidHeaderFieldLine($h)) { $easy->trailers[] = $value; } } else { $collectingTrailers = false; $easy->trailers = []; $easy->headers = [$value]; } $startingResponse = false; } else { $easy->headers[] = $value; } return \strlen($h); }; } public function __destruct() { $this->discardIdleHandles(); } } true, 'transport_sharing' => true, ]; /** * @var CurlFactoryInterface */ private $factory; /** * @var CurlShareHandleState|null */ private $shareHandleState; /** * Accepts an associative array of options: * * - handle_factory: Optional curl factory used to create cURL handles. * - transport_sharing: Optional transport sharing mode. * * @param array{handle_factory?: ?CurlFactoryInterface, transport_sharing?: mixed} $options Array of options to use with the handler */ public function __construct(array $options = []) { foreach ($options as $name => $_) { if (!isset(self::KNOWN_CONSTRUCTOR_OPTIONS[$name])) { \trigger_deprecation('guzzlehttp/guzzle', '7.14', \sprintf('The "%s" CurlHandler constructor option is unknown; guzzlehttp/guzzle 8.0 will reject unknown constructor options.', (string) $name)); } } CurlShareHandleState::assertNoRequiredSharingCustomFactoryConflict($options, 'CurlHandler'); $transportSharing = $options['transport_sharing'] ?? null; $sharingMode = CurlShareHandleState::normalizeMode($transportSharing, 'transport_sharing'); if (\array_key_exists('handle_factory', $options) && $options['handle_factory'] !== null) { $this->shareHandleState = null; $this->factory = $options['handle_factory']; return; } $this->shareHandleState = $sharingMode !== TransportSharing::NONE ? CurlShareHandleState::fromOption($transportSharing) : null; $this->factory = $this->shareHandleState !== null ? new CurlFactory(3, $this->shareHandleState->mode, $this->shareHandleState) : new CurlFactory(3); } public function __invoke(RequestInterface $request, array $options): PromiseInterface { HostValidator::assertRequestHost($request); if (isset($options['delay'])) { \usleep($options['delay'] * 1000); } // A Multiplexing::NONE request option holds unconditionally here: // transport sharing never shares the connection cache on this // branch, and nothing else executes during the blocking curl_exec(), // so the transfer cannot share its connection with a concurrent // transfer. $easy = $this->factory->create($request, $options); \curl_exec($easy->handle); $easy->errno = \curl_errno($easy->handle); return CurlFactory::finish($this, $easy, $this->factory); } } true, 'max_host_connections' => true, 'max_total_connections' => true, 'multiplex' => true, 'options' => true, 'select_timeout' => true, 'transport_sharing' => true, ]; private const CONNECTION_CAP_OPTIONS = [ 'max_host_connections' => 'CURLMOPT_MAX_HOST_CONNECTIONS', 'max_total_connections' => 'CURLMOPT_MAX_TOTAL_CONNECTIONS', ]; /** * cURL options that isolate a transfer from foreign proxy tunnel * connections. Failing to apply either one would fall open into * credential-bearing connection reuse. */ private const PROXY_TUNNEL_ISOLATION_OPTIONS = [ 'CURLOPT_FRESH_CONNECT', 'CURLOPT_FORBID_REUSE', ]; /** * @var CurlFactoryInterface */ private $factory; /** * @var CurlShareHandleState|null */ private $shareHandleState; /** * @var int */ private $selectTimeout; /** * @var int Will be higher than 0 when `curl_multi_exec` is still running. */ private $active = 0; /** * @var array Request entry handles, indexed by handle id in `addRequest`. * * @see CurlMultiHandler::addRequest */ private $handles = []; /** * @var array An array of delay times, indexed by handle id in `addRequest`. * * @see CurlMultiHandler::addRequest */ private $delays = []; /** * @var array An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt() */ private $options = []; /** * @var array Native options derived from first-class * constructor options; failing to apply one is an * error rather than a compatibility warning. */ private $requiredOptions = []; /** * @var bool Whether any connection cap constructor option was applied */ private $connectionCapsApplied = false; /** * @var bool Whether the "multiplex" constructor option disabled * multiplexing on this handler's multi handle */ private $multiplexDisabled = false; /** * @var bool Whether a custom "handle_factory" constructor option supplies * the easy handles */ private $customHandleFactory = false; /** @var resource|\CurlMultiHandle */ private $_mh; /** * @var int Depth of nested guarded native operations (execution and * handle removal, both of which can run user callbacks). A * callback can re-enter tick(), and the nested frame must not * clear the outer frame's guard; deferred work stays parked * until the outermost frame unwinds. */ private $multiExecDepth = 0; /** * @var bool Guards finishDeferredWork() against re-entry from the * guarded native removals it performs while flushing. */ private $finishingDeferredWork = false; /** * @var array */ private $deferredCancels = []; /** * @var array Wait tokens of requests created from inside * a cURL callback, keyed by handle id; native * attachment is deferred until the outermost * native execution unwinds. */ private $deferredAdds = []; /** * @var string|null Owner signature of the proxy tunnels the multi handle's * connection cache may hold */ private $proxyTunnelOwner; /** @var array Count of attached transfers per proxy tunnel signature. */ private $activeProxyTunnelSignatures = []; /** @var array Maps an attached handle id to its proxy tunnel signature. */ private $activeProxyTunnelHandles = []; /** * @var int Depth of nested processMessages() calls. Guards against * multi-handle recreation re-entrancy from processMessages (a * retried transfer re-invokes the handler); a depth is tracked * because a completion callback can re-enter tick(). */ private $messageProcessingDepth = 0; /** * This handler accepts the following options: * * - handle_factory: An optional factory used to create curl handles * - transport_sharing: Optional transport sharing mode. * - select_timeout: Optional timeout (in seconds) to block before timing * out while selecting curl handles. Defaults to 1 second. * - max_host_connections: Optional maximum concurrent connections per host. * - max_total_connections: Optional maximum concurrent connections overall. * - multiplex: Optional Multiplexing::NONE to disallow multiplexing on * this handler's multi handle. The eager, wait, and required modes are * request options, not handler options; Multiplexing::NONE is also * conditionally accepted as a request option value. * - options: An associative array of CURLMOPT_* options and * corresponding values for curl_multi_setopt() */ public function __construct(array $options = []) { foreach ($options as $name => $_) { if (!isset(self::KNOWN_CONSTRUCTOR_OPTIONS[$name])) { \trigger_deprecation('guzzlehttp/guzzle', '7.14', \sprintf('The "%s" CurlMultiHandler constructor option is unknown; guzzlehttp/guzzle 8.0 will reject unknown constructor options.', (string) $name)); } } $handlerMultiplex = $options['multiplex'] ?? null; if (null !== $handlerMultiplex && Multiplexing::NONE !== $handlerMultiplex) { if (\in_array($handlerMultiplex, [Multiplexing::EAGER, Multiplexing::WAIT, Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) { throw new \InvalidArgumentException('The "multiplex" CurlMultiHandler option only accepts Multiplexing::NONE; the eager, wait, and required modes are request options.'); } throw new \InvalidArgumentException(\sprintf('The "multiplex" CurlMultiHandler option must be null or Multiplexing::NONE; received %s.', \get_debug_type($handlerMultiplex))); } $this->multiplexDisabled = null !== $handlerMultiplex; if ($this->multiplexDisabled && !\defined('CURLMOPT_PIPELINING')) { // ext-curl only defines the constant when built against libcurl // 7.16 or newer headers, and such builds compile out the matching // curl_multi_setopt() case, so the guarantee cannot be applied. throw new \InvalidArgumentException('The "multiplex" CurlMultiHandler option requires CURLMOPT_PIPELINING, but it is not available in the installed PHP cURL extension.'); } CurlShareHandleState::assertNoRequiredSharingCustomFactoryConflict($options, 'CurlMultiHandler'); $transportSharing = $options['transport_sharing'] ?? null; $sharingMode = CurlShareHandleState::normalizeMode($transportSharing, 'transport_sharing'); if (\array_key_exists('handle_factory', $options) && $options['handle_factory'] !== null) { $this->shareHandleState = null; $this->factory = $options['handle_factory']; $this->customHandleFactory = true; } else { $this->shareHandleState = $sharingMode !== TransportSharing::NONE ? CurlShareHandleState::fromOption($transportSharing) : null; $this->factory = $this->shareHandleState !== null ? new CurlFactory(50, $this->shareHandleState->mode, $this->shareHandleState) : new CurlFactory(50); } if (isset($options['select_timeout'])) { $selectTimeout = $options['select_timeout']; if (!\is_int($selectTimeout) && !\is_float($selectTimeout) && (!\is_string($selectTimeout) || !\is_numeric($selectTimeout))) { \trigger_deprecation('guzzlehttp/guzzle', '7.14', 'Passing a non-numeric "select_timeout" CurlMultiHandler option is deprecated; guzzlehttp/guzzle 8.0 will reject it.'); } else { $seconds = (float) $selectTimeout; if (!\is_finite($seconds) || $seconds < 0 || ($seconds > 0 && (int) ($seconds * 1000) === 0)) { \trigger_deprecation('guzzlehttp/guzzle', '7.14', 'Passing a "select_timeout" CurlMultiHandler option that is not 0 or greater than or equal to 0.001 seconds is deprecated; guzzlehttp/guzzle 8.0 will reject it.'); } } $this->selectTimeout = $selectTimeout; } elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) { \trigger_deprecation('guzzlehttp/guzzle', '7.2', 'The GUZZLE_CURL_SELECT_TIMEOUT environment variable is deprecated; use the "select_timeout" option instead.'); $this->selectTimeout = (int) $selectTimeout; } else { $this->selectTimeout = 1; } $multiOptions = $options['options'] ?? []; if (\is_array($multiOptions)) { self::rejectConnectionCapOptionConflicts($options, $multiOptions); if ($this->multiplexDisabled && \array_key_exists(\CURLMOPT_PIPELINING, $multiOptions)) { // Key presence alone conflicts, even with an agreeing value: // the named option is the single multiplexing authority. throw new \InvalidArgumentException('multiplex conflicts with a CURLMOPT_PIPELINING entry in the "options" array.'); } self::triggerConflictingCurlMultiOptionDeprecations($multiOptions); } elseif (self::hasConnectionCapOption($options)) { throw new \InvalidArgumentException('options must be an array of cURL multi options when using connection cap options.'); } elseif ($this->multiplexDisabled) { throw new \InvalidArgumentException('options must be an array of cURL multi options when using the "multiplex" option.'); } $this->options = $multiOptions; if (\is_array($multiOptions)) { $this->addConnectionCapOptions($options); if ($this->multiplexDisabled) { // CURLPIPE_NOTHING; the constant itself needs libcurl 7.43 // headers, newer than the oldest supported runtimes. The // option is required: a handler-wide guarantee must fail // closed rather than warn like the deprecated raw options. $this->options[\CURLMOPT_PIPELINING] = 0; $this->requiredOptions[\CURLMOPT_PIPELINING] = true; } } // unsetting the property forces the first access to go through // __get(). unset($this->_mh); } /** * @param string $name * * @return resource|\CurlMultiHandle * * @throws \BadMethodCallException when another field as `_mh` will be gotten * @throws \RuntimeException when curl can not initialize a multi handle * @throws \InvalidArgumentException when a required cURL multi option cannot be applied */ public function __get($name) { if ($name !== '_mh') { throw new \BadMethodCallException("Can not get other property as '_mh'."); } $multiHandle = \curl_multi_init(); if (false === $multiHandle) { throw new \RuntimeException('Can not initialize curl multi handle.'); } try { foreach ($this->options as $option => $value) { if (true === @curl_multi_setopt($multiHandle, $option, $value)) { continue; } if (isset($this->requiredOptions[$option])) { // A first-class option such as a connection cap must // never be silently dropped. throw new \InvalidArgumentException(\sprintf('Unable to apply the cURL multi option %s; it was rejected by the runtime libcurl.', self::formatCurlMultiOption($option))); } \trigger_error(\sprintf('Unable to apply the cURL multi option %s; it was ignored by the runtime libcurl.', self::formatCurlMultiOption($option)), \E_USER_WARNING); } } catch (\Throwable $e) { // Do not publish a partially configured handle; a later access // retries the initialization from scratch. try { \curl_multi_close($multiHandle); } catch (\Throwable $ignored) { // Preserve the original failure. } throw $e; } $this->_mh = $multiHandle; return $this->_mh; } public function __destruct() { if (isset($this->_mh)) { try { \curl_multi_close($this->_mh); } catch (\Throwable $e) { // Destructors must not throw. } finally { unset($this->_mh); } } } public function __invoke(RequestInterface $request, array $options): PromiseInterface { HostValidator::assertRequestHost($request); if ($this->connectionCapsApplied && \defined('CURLOPT_SHARE') && isset($options['curl']) && \is_array($options['curl']) && \array_key_exists((int) \constant('CURLOPT_SHARE'), $options['curl']) ) { // Key presence alone conflicts: Guzzle cannot verify that a // caller-managed shared connection pool honors the caps. throw new \InvalidArgumentException('The request-level CURLOPT_SHARE cURL option cannot be combined with CurlMultiHandler connection cap options because Guzzle cannot verify that an external shared connection pool honors cURL multi connection caps.'); } $easy = $this->factory->create($request, $options); try { $this->rejectMultiplexPipeliningConflict($easy, $options); $this->applyMultiplexNone($easy, $options); $this->applyProxyTunnelOwnership($easy); } catch (\Throwable $e) { try { $this->factory->release($easy); } catch (\Throwable $releaseFailure) { // Preserve the original failure. } throw $e; } $id = (int) $easy->handle; $waitToken = new \stdClass(); $promise = null; $promise = new Promise( function () use ($id, $waitToken, $easy, &$promise): void { // Waiting cannot drive native cURL while a callback has the // multi handle busy; fail the wait promptly instead of // self-deadlocking. $idReused = $this->multiExecDepth > 0 ? $this->failNestedWait($id, $waitToken) : $this->executeUntil($id, $waitToken); // Settling can be queued, and guzzlehttp/promises drains the // queue before deciding a wait function achieved nothing. P\Utils::queue()->run(); // Never null: assigned below before any wait can invoke this. /** @var Promise $promise */ if (!P\Is::pending($promise)) { return; } // Neither path guarantees the transfer settled, and returning // while pending makes guzzlehttp/promises reject with a bare // string naming nothing. $stalled = $idReused ? 'its native cURL handle ID was reused by another request' : 'its entry was removed without settling'; $message = \sprintf('Waiting on cURL multi handler transfer %d cannot make progress (%s).', $id, $stalled); // The entry is gone or belongs to another request, so // attribute from this easy handle. $promise->reject(new RequestException($message, $easy->request, $easy->response)); }, function () use ($id, $waitToken) { return $this->cancel($id, $waitToken); } ); $entry = ['easy' => $easy, 'deferred' => $promise, 'wait_token' => $waitToken]; try { $this->addRequest($entry); } catch (\Throwable $e) { throw $this->discardPendingRequest($id, $entry, $e); } return $promise; } /** * The "multiplex" request option sets CURLOPT_PIPEWAIT, which libcurl * ignores entirely when the multi handle's CURLMOPT_PIPELINING option * disables multiplexing, so an explicit request for multiplexing on a * handler configured against it is a configuration error. The required * family conflicts marker-independently: a required guarantee on a handler * that disables multiplexing is contradictory even when the transfer would * not wait. A raw CURLOPT_PIPEWAIT cURL option conflicts with every * explicit mode on this handler, where waiting is operationally * meaningful: whatever its value, it is a second wait/eager authority * applied after the mode's own decision. */ private function rejectMultiplexPipeliningConflict(EasyHandle $easy, array $options): void { $multiplex = $options['multiplex'] ?? null; if (null === $multiplex) { return; } if (\defined('CURLOPT_PIPEWAIT') && isset($options['curl']) && \is_array($options['curl']) && \array_key_exists((int) \constant('CURLOPT_PIPEWAIT'), $options['curl']) ) { // Key presence alone conflicts, and it must be rejected before // the marker below is consulted: the marker reflects the final // merged configuration, which the raw value has falsified. throw new \InvalidArgumentException('The "multiplex" request option cannot be combined with the raw CURLOPT_PIPEWAIT cURL option on the cURL multi handler; remove the raw option.'); } if (Multiplexing::WAIT === $multiplex && !$easy->usesPipewait) { // Explicit wait only conflicts when the transfer would actually // wait; an HTTP/1.1 wait request never sets the marker. return; } if (!\in_array($multiplex, [Multiplexing::WAIT, Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) { return; } if ($this->multiplexDisabled) { // Checked before the raw option: the handler wrote its own // CURLMOPT_PIPELINING value when "multiplex" disabled it. throw new \InvalidArgumentException('The "multiplex" request option cannot be combined with a CurlMultiHandler whose "multiplex" option is Multiplexing::NONE; remove the handler option or set the request option to "eager".'); } if (!\is_array($this->options) || !\array_key_exists(\CURLMOPT_PIPELINING, $this->options)) { // A legacy non-array "options" value is tolerated by the // constructor and cannot contain the option. return; } $pipelining = $this->options[\CURLMOPT_PIPELINING]; if (!\is_scalar($pipelining)) { // ext-curl derives the integer mask from non-scalar values with // type-dependent zval semantics, so the effective mask cannot be // predicted here; require an explicit integer instead. throw new \InvalidArgumentException('The CurlMultiHandler CURLMOPT_PIPELINING option must be an integer when combined with the "multiplex" request option.'); } $multiplexBit = \defined('CURLPIPE_MULTIPLEX') ? \CURLPIPE_MULTIPLEX : 2; if (((int) $pipelining & $multiplexBit) !== 0) { return; } throw new \InvalidArgumentException('The "multiplex" request option cannot be combined with a CurlMultiHandler CURLMOPT_PIPELINING option that disables multiplexing; set CURLMOPT_PIPELINING to CURLPIPE_MULTIPLEX, remove the option, or set the "multiplex" option to "eager".'); } /** * A Multiplexing::NONE request option is a sole-use guarantee: the * transfer must not share its connection with any concurrent transfer. * It holds structurally on a handler whose "multiplex" option is * Multiplexing::NONE, and for HTTP/1.x transfers, which never join a * multiplexed connection and open connections nothing can join. An * HTTP/2 request on a handler that multiplexes is rejected, as is any * configuration under which the guarantee cannot be verified (custom * handle factories control the native handle) or cannot be hardened * (challenge-response authentication retries and Expect 417 retries * re-enter connection selection as internal follows, which disarm * CURLOPT_FRESH_CONNECT). A raw CURLMOPT_PIPELINING multi option, and * deprecated-but-applied raw cURL options that can defeat the declared * protocol version, retry through internal follows, or replace the * managed header list, are rejected by key presence. On runtimes whose * matcher can hand an HTTP/1.x transfer an idle multiplexed connection * (below libcurl 7.77.0, and 8.11.0-8.12.1), accepted transfers force * a fresh connection. */ private function applyMultiplexNone(EasyHandle $easy, array $options): void { if (Multiplexing::NONE !== ($options['multiplex'] ?? null) || $this->multiplexDisabled) { return; } if (\defined('CURLMOPT_PIPELINING') && \is_array($this->options) && \array_key_exists(\CURLMOPT_PIPELINING, $this->options)) { // Key presence alone conflicts, matching the constructor's rule // for the named option: raw multi options that fail to apply only // warn (they are not in requiredOptions), so even an agreeing // zero mask cannot prove the guarantee. is_array: legacy non-array // "options" values are deprecated but still stored. throw new \InvalidArgumentException('The "multiplex" request option cannot be Multiplexing::NONE alongside a raw CURLMOPT_PIPELINING cURL multi option; replace the raw option with the "multiplex" cURL multi handler option.'); } if ($this->customHandleFactory) { throw new \InvalidArgumentException('The "multiplex" request option can only be Multiplexing::NONE on a CurlMultiHandler with a custom "handle_factory" when the handler\'s own "multiplex" option is Multiplexing::NONE, because the guarantee is enforced against the native easy handle the factory controls.'); } $version = $easy->request->getProtocolVersion(); if ('2' === $version || '2.0' === $version) { throw new \InvalidArgumentException('The "multiplex" request option can only be Multiplexing::NONE for an HTTP/1.x request on a CurlMultiHandler that permits multiplexing; set the "multiplex" client or CurlMultiHandler constructor option to Multiplexing::NONE to disable multiplexing for every transfer, or send the request with its "version" option set to "1.1".'); } if (isset($options['curl']) && \is_array($options['curl'])) { foreach (['CURLOPT_HTTP_VERSION', 'CURLOPT_HTTPAUTH', 'CURLOPT_PROXYAUTH', 'CURLOPT_FOLLOWLOCATION', 'CURLOPT_HTTPHEADER', 'CURLOPT_ALTSVC', 'CURLOPT_ALTSVC_CTRL', 'CURLOPT_PROXYTYPE'] as $constant) { if (\defined($constant) && \array_key_exists((int) \constant($constant), $options['curl'])) { // Key presence alone conflicts. A raw CURLOPT_HTTP_VERSION // overrides the declared version after the factory // mapping, and raw alt-svc options or an HTTPS2 proxy // type can put a declared-HTTP/1.x transfer on a joinable // HTTP/2 connection; raw challenge-response // authentication (origin 401 or proxy 407) and native // redirects re-enter connection selection as internal // follows, which disarm CURLOPT_FRESH_CONNECT, so the // hardening below cannot cover them; a raw // CURLOPT_HTTPHEADER replaces the managed header list, // including the Expect suppression the check below // relies on. throw new \InvalidArgumentException(\sprintf('The "multiplex" request option cannot be Multiplexing::NONE combined with the raw %s cURL option on a CurlMultiHandler that permits multiplexing; remove the raw option, or set the "multiplex" client or CurlMultiHandler constructor option to Multiplexing::NONE.', $constant)); } } } if (Psr7\Utils::caselessContains($easy->request->getHeaderLine('Expect'), '100-continue')) { // libcurl arms its Expect handling by a caseless substring scan // of the header value (Curl_compareheader), so any value // containing 100-continue can make a 417 response retry as an // internal follow, which disarms CURLOPT_FRESH_CONNECT; requests // without the header are safe because the factory suppresses // libcurl's automatic Expect. throw new \InvalidArgumentException('The "multiplex" request option cannot be Multiplexing::NONE for a request carrying an "Expect: 100-continue" header on a CurlMultiHandler that permits multiplexing; remove the explicitly supplied "Expect" header, set the "expect" request option to false to prevent it being added automatically, or set the "multiplex" client or CurlMultiHandler constructor option to Multiplexing::NONE.'); } if (CurlVersion::supportsHttpVersionReuseMatching()) { return; } // Unqualified curl_setopt so the test bootstrap shadow records it. if (true !== curl_setopt($easy->handle, \CURLOPT_FRESH_CONNECT, true)) { // The hardening is the guarantee on these runtimes; failing to // apply it must fail closed, mirroring applyCurlOptions(). throw new \InvalidArgumentException('Unable to set cURL option CURLOPT_FRESH_CONNECT.'); } } /** * @param array $options */ private static function triggerConflictingCurlMultiOptionDeprecations(array $options): void { if ($options === []) { return; } $conflictingOptions = self::conflictingCurlMultiOptions(); $sinceOverrides = self::conflictingCurlMultiOptionSinceOverrides(); foreach ($options as $option => $_) { if (\array_key_exists($option, $conflictingOptions)) { \trigger_deprecation('guzzlehttp/guzzle', $sinceOverrides[$option] ?? '7.14', \sprintf('Passing %s in the cURL multi handler "options" is deprecated; guzzlehttp/guzzle 8.0 will reject this option. Use %s instead.', self::formatCurlMultiOption($option), $conflictingOptions[$option])); } } } /** * @return array */ private static function conflictingCurlMultiOptionSinceOverrides(): array { if (!\defined('CURLMOPT_PIPELINING')) { // Matches conflictingCurlMultiOptions(): ext-curl builds against // pre-7.16 libcurl headers do not define the constant. return []; } return [\CURLMOPT_PIPELINING => '7.15']; } /** * @param array $options */ private static function hasConnectionCapOption(array $options): bool { foreach (self::CONNECTION_CAP_OPTIONS as $name => $_) { if (($options[$name] ?? null) !== null) { return true; } } return false; } /** * @param array $constructorOptions * @param array $multiOptions */ private static function rejectConnectionCapOptionConflicts(array $constructorOptions, array $multiOptions): void { foreach (self::CONNECTION_CAP_OPTIONS as $name => $constant) { if (($constructorOptions[$name] ?? null) === null || !\defined($constant)) { continue; } $option = \constant($constant); if (\array_key_exists($option, $multiOptions)) { throw new \InvalidArgumentException(\sprintf('%s conflicts with a %s entry in the "options" array.', $name, $constant)); } } } /** * @param array $options */ private function addConnectionCapOptions(array $options): void { foreach (self::CONNECTION_CAP_OPTIONS as $name => $constant) { $value = $options[$name] ?? null; if ($value === null) { continue; } if (!\is_int($value) || $value < 1) { throw new \InvalidArgumentException(\sprintf('%s must be a positive integer.', $name)); } CurlVersion::ensureConnectionCapsSupported($name); $option = \constant($constant); if (\array_key_exists($option, $this->options)) { throw new \InvalidArgumentException(\sprintf('%s conflicts with a %s entry in the "options" array.', $name, $constant)); } $this->options[$option] = $value; $this->requiredOptions[$option] = true; $this->connectionCapsApplied = true; } } /** * @param int|string $option */ private static function formatCurlMultiOption($option): string { if (!\is_int($option)) { return \sprintf('"%s"', $option); } static $names = null; if (null === $names) { $names = []; foreach (\get_defined_constants(true)['curl'] ?? [] as $name => $value) { if (\is_int($value) && \strpos($name, 'CURLMOPT_') === 0 && !isset($names[$value])) { $names[$value] = $name; } } } if (isset($names[$option])) { return \sprintf('%s (%d)', $names[$option], $option); } return (string) $option; } /** * @return array */ private static function conflictingCurlMultiOptions(): array { static $options = null; if ($options !== null) { return $options; } $options = []; self::addConflictingCurlMultiOption($options, 'CURLMOPT_MAX_HOST_CONNECTIONS', 'the "max_host_connections" client option or cURL multi handler option'); self::addConflictingCurlMultiOption($options, 'CURLMOPT_MAX_TOTAL_CONNECTIONS', 'the "max_total_connections" client option or cURL multi handler option'); self::addConflictingCurlMultiOption($options, 'CURLMOPT_PIPELINING', 'Multiplexing::NONE via the "multiplex" cURL multi handler or client option to disable multiplexing, or remove the raw option for the runtime default (multiplexing defaults on from libcurl 7.62, except 7.65.0 and 7.65.1)'); return $options; } /** * @param array $options */ private static function addConflictingCurlMultiOption(array &$options, string $constant, string $replacement): void { if (!\defined($constant)) { return; } $value = \constant($constant); if (\is_int($value)) { $options[$value] = $replacement; } } /** * Isolates the connection cache when the request's proxy tunnel section * differs from the one the multi handle's cache may already hold. */ private function applyProxyTunnelOwnership(EasyHandle $easy): void { $signature = $easy->proxyTunnelSignature; if ($signature === null || $signature === $this->proxyTunnelOwner) { return; } if ($this->proxyTunnelOwner === null) { // No in-domain transfer has ever run on this multi handle: latch // the owner without destroying pooled direct connections. $this->proxyTunnelOwner = $signature; return; } if ( $this->handles === [] && 0 === $this->multiExecDepth && 0 === $this->messageProcessingDepth && $this->deferredCancels === [] ) { // Idle: hand the connection cache over by recreating the multi // handle (unsetting re-arms the lazy __get initializer, which // re-applies the CURLMOPT_* options). if (isset($this->_mh)) { \curl_multi_close($this->_mh); unset($this->_mh); } $this->proxyTunnelOwner = $signature; return; } // Busy: isolate this transfer from the owner's pooled tunnels. $this->isolateProxyTunnelTransfer($easy); } private function addCurlHandle(EasyHandle $easy): void { $this->isolateFromForeignActiveProxyTunnel($easy); // Unqualified curl_multi_add_handle so the test bootstrap shadow can // override the result. $result = curl_multi_add_handle($this->_mh, $easy->handle); if (\CURLM_OK !== $result) { if (\PHP_VERSION_ID < 80226 || (\PHP_VERSION_ID >= 80300 && \PHP_VERSION_ID < 80314)) { // Before PHP 8.2.26 and 8.3.14, ext-curl kept the easy handle // in its multi bookkeeping even when the native add failed // (https://github.com/php/php-src/pull/16302); remove it so // the handle can be pooled or closed safely. \curl_multi_remove_handle($this->_mh, $easy->handle); } throw new RequestException(\sprintf('Unable to add the cURL handle to the cURL multi handler: %s (%d).', (string) \curl_multi_strerror($result), $result), $easy->request); } $this->markProxyTunnelActive($easy); $id = (int) $easy->handle; if (isset($this->handles[$id])) { $this->handles[$id]['attached'] = true; } } /** * @param resource|\CurlHandle $handle */ private function removeCompletedHandleFromMulti(int $id, $handle): void { $this->removeHandleFromMulti($handle); $this->unmarkProxyTunnelActiveById($id); } /** * Removes a transfer from the multi handle under the native execution * guard: removing a still-running transfer performs a final progress * update that can run a user progress callback. * * @param resource|\CurlHandle $handle */ private function removeHandleFromMulti($handle): void { ++$this->multiExecDepth; try { \curl_multi_remove_handle($this->_mh, $handle); } finally { --$this->multiExecDepth; $this->finishDeferredWork(); } } private function isolateFromForeignActiveProxyTunnel(EasyHandle $easy): void { $signature = $easy->proxyTunnelSignature; if ($signature === null || $this->activeProxyTunnelSignatures === []) { return; } if (\count($this->activeProxyTunnelSignatures) === 1 && isset($this->activeProxyTunnelSignatures[$signature])) { return; } $this->isolateProxyTunnelTransfer($easy); } private function isolateProxyTunnelTransfer(EasyHandle $easy): void { foreach (self::PROXY_TUNNEL_ISOLATION_OPTIONS as $name) { try { // Unqualified curl_setopt so the test bootstrap shadow records it. $applied = curl_setopt($easy->handle, (int) \constant($name), true); } catch (\Throwable $e) { throw new RequestException(self::proxyTunnelIsolationFailureMessage($name), $easy->request, null, $e); } if (true !== $applied) { throw new RequestException(self::proxyTunnelIsolationFailureMessage($name), $easy->request); } } } private static function proxyTunnelIsolationFailureMessage(string $name): string { return \sprintf('Unable to apply the %s cURL option required to isolate the transfer from foreign proxy tunnel connections.', $name); } private function markProxyTunnelActive(EasyHandle $easy): void { $signature = $easy->proxyTunnelSignature; if ($signature === null) { return; } $id = (int) $easy->handle; if (isset($this->activeProxyTunnelHandles[$id])) { if ($this->activeProxyTunnelHandles[$id] === $signature) { return; } $this->unmarkProxyTunnelActiveById($id); } $this->activeProxyTunnelHandles[$id] = $signature; $this->activeProxyTunnelSignatures[$signature] = ($this->activeProxyTunnelSignatures[$signature] ?? 0) + 1; } private function unmarkProxyTunnelActive(EasyHandle $easy): void { $this->unmarkProxyTunnelActiveById((int) $easy->handle); } private function unmarkProxyTunnelActiveById(int $id): void { if (!isset($this->activeProxyTunnelHandles[$id])) { return; } $signature = $this->activeProxyTunnelHandles[$id]; unset($this->activeProxyTunnelHandles[$id]); if (!isset($this->activeProxyTunnelSignatures[$signature])) { return; } --$this->activeProxyTunnelSignatures[$signature]; if ($this->activeProxyTunnelSignatures[$signature] <= 0) { unset($this->activeProxyTunnelSignatures[$signature]); } } /** * Ticks the curl event loop. */ public function tick(): void { $this->tickFor(null, null); } /** * Ticks the curl event loop, returning before the blocking select if the * targeted transfer has settled, been canceled, or been replaced by a * request that reused its native handle ID. */ private function tickFor(?int $targetId, ?object $waitToken): void { // Add any delayed handles if needed. Attachment is skipped while a // callback has native execution busy; the outer frame attaches due // transfers once it unwinds. if ($this->delays && 0 === $this->multiExecDepth) { $currentTime = Utils::currentTime(); foreach ($this->delays as $id => $delay) { if ($currentTime >= $delay) { $entry = $this->handles[$id]; unset($this->delays[$id]); try { $this->addCurlHandle($entry['easy']); } catch (\Throwable $e) { // The promise has already escaped, so reject it // rather than throw. $rejection = $this->discardPendingRequest($id, $entry, $e); if (P\Is::pending($entry['deferred'])) { $entry['deferred']->reject($rejection); } } } } } // Run curl_multi_exec in the queue to enable other async tasks to // run, surface completions, and drain any work they queued so a // ready cancellation or new transfer is not held behind the select. do { P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue'])); // Step through the task queue which may add additional requests. P\Utils::queue()->run(); if ($this->multiExecDepth > 0) { // A cURL callback re-entered the handler while native // execution is running; the outer frame drives native cURL // once it unwinds. return; } if (isset($this->_mh)) { $this->processMessages(); } } while (!P\Utils::queue()->isEmpty()); if (!isset($this->_mh)) { // Nothing is attached natively (or initialization just failed); // there is nothing to run and nothing to recreate the handle for. return; } if ($targetId !== null && !$this->hasRequest($targetId, $waitToken)) { return; } if ($this->active && \curl_multi_select($this->_mh, $this->effectiveSelectTimeout()) === -1) { // Perform a usleep if a select returns -1. // See: https://bugs.php.net/bug.php?id=61141 \usleep(250); } do { $exec = $this->executeMulti(); // Prevent busy looping for slow HTTP requests. if ($exec === \CURLM_CALL_MULTI_PERFORM) { \curl_multi_select($this->_mh, $this->effectiveSelectTimeout()); } } while ($exec === \CURLM_CALL_MULTI_PERFORM); $this->processMessages(); } /** * Runs \curl_multi_exec() inside the event loop, to prevent busy looping */ private function tickInQueue(): void { if ($this->multiExecDepth > 0) { // A cURL callback re-entered the handler while native execution // is running; the outer frame drives native cURL once it unwinds. return; } if (!isset($this->_mh)) { // Nothing is attached natively (or initialization just failed); // there is nothing to run and nothing to recreate the handle for. return; } $exec = $this->executeMulti(); if ($exec === \CURLM_CALL_MULTI_PERFORM) { \curl_multi_select($this->_mh, 0); P\Utils::queue()->add(Closure::fromCallable([$this, 'tickInQueue'])); } } /** * @phpstan-impure */ private function executeMulti(): int { ++$this->multiExecDepth; try { return \curl_multi_exec($this->_mh, $this->active); } finally { --$this->multiExecDepth; $this->finishDeferredWork(); } } /** * Flushes cancels and attachments deferred while the multi handle was * busy executing transfers or removing a handle. */ private function finishDeferredWork(): void { if ($this->multiExecDepth > 0 || $this->finishingDeferredWork) { // A nested frame (a cURL callback re-entered the handler) must // not flush while an outer frame is still using the multi // handle; the outermost frame flushes once it unwinds. return; } $this->finishingDeferredWork = true; try { $failure = null; // Removing a cancelled transfer runs its final progress update, // whose callback can cancel other transfers or create requests; // drain until no deferred work remains. do { $this->cleanupDeferredCancels($failure); $this->flushDeferredAdds(); } while ($this->deferredCancels !== [] || $this->deferredAdds !== []); if ($failure !== null) { throw $failure; } } finally { $this->finishingDeferredWork = false; } } /** * Runs until all outstanding connections have completed. */ public function execute(): void { if ($this->multiExecDepth > 0) { // Native cURL cannot be driven while a callback has it busy, so // the loop would spin without ever progressing. throw new \LogicException('Cannot run the cURL multi event loop from inside a cURL callback; the callback must return before transfers can progress.'); } $queue = P\Utils::queue(); while ($this->handles || !$queue->isEmpty()) { // If there are no transfers, then sleep for the next delay, // unless ready queue work could change what is pending. if (!$this->active && $this->delays && $queue->isEmpty()) { \usleep($this->timeToNext()); } $this->tick(); } } /** * Runs the event loop until the given transfer has finished, so waiting * on a promise does not wait for every other transfer on the handler * like execute() does. * * The native cURL handle ID can be reused by a request created from a * completion callback, so the wait token guards against waiting on an * unrelated transfer that inherited the ID. * * @return bool Whether another request had reused the native cURL handle * ID by the time the loop stopped */ private function executeUntil(int $id, object $waitToken): bool { $queue = P\Utils::queue(); while ($this->hasRequest($id, $waitToken)) { // If the transfer is delayed, then sleep until it is due, unless // ready queue work could cancel or replace it first. if (!$this->active && isset($this->delays[$id]) && $queue->isEmpty()) { \usleep($this->timeToNext()); } $this->tickFor($id, $waitToken); } // Sample before the drain below, which can add or remove an entry // under this ID and so rewrite the answer. $idReused = isset($this->handles[$id]); if (!$queue->isEmpty()) { $queue->run(); } return $idReused; } /** * Checks that the request with the given handle ID is still pending and, * when a wait token is given, has not been replaced by a request that * reused the ID. */ private function hasRequest(int $id, ?object $waitToken = null): bool { if (!isset($this->handles[$id])) { return false; } return $waitToken === null || ($this->handles[$id]['wait_token'] ?? null) === $waitToken; } private function addRequest(array $entry): void { $easy = $entry['easy']; $id = (int) $easy->handle; $entry['attached'] = false; $displaced = $this->handles[$id] ?? null; if ($displaced !== null) { // Never silently discard a tracked entry; settle it first. unset($this->handles[$id], $this->delays[$id], $this->deferredAdds[$id]); if (P\Is::pending($displaced['deferred'])) { $message = \sprintf('cURL multi handler transfer %d was displaced by another request that reused its native cURL handle ID.', $id); $displaced['deferred']->reject(new RequestException($message, $displaced['easy']->request, $displaced['easy']->response)); } } $this->handles[$id] = $entry; if (!empty($easy->options['delay'])) { $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000); } elseif ($this->multiExecDepth > 0) { // A request created from inside a cURL callback cannot be added // natively while curl_multi_exec() is running; libcurl 7.59+ // rejects the recursive call. Attach it once the outermost // native execution unwinds. $this->deferredAdds[$id] = $entry['wait_token'] ?? null; } else { $this->addCurlHandle($easy); } } /** * Rolls back a request that can no longer be attached, releasing the * easy handle exactly once and preserving the original failure. * * @param array{easy: EasyHandle, deferred: Promise, wait_token?: object|null, attached?: bool} $entry */ private function discardPendingRequest(int $id, array $entry, \Throwable $failure): \Throwable { unset($this->handles[$id], $this->delays[$id], $this->deferredAdds[$id]); try { $this->factory->release($entry['easy']); } catch (\Throwable $e) { // Preserve the original failure. } return $failure; } /** * Fails a synchronous wait attempted from inside a cURL callback, where * native execution cannot progress until the callback returns. * * @return bool Whether another request had reused the native cURL handle * ID, which only matters when no transfer was left to fail */ private function failNestedWait(int $id, object $token): bool { if (!$this->hasRequest($id, $token)) { // Nothing left to fail, so report which way the entry went. return isset($this->handles[$id]); } $entry = $this->handles[$id]; $failure = new RequestException('Cannot synchronously wait for a transfer from inside a cURL callback on the same cURL multi handler; the callback must return before the transfer can progress.', $entry['easy']->request, $entry['easy']->response); if (!empty($entry['attached'])) { // Native removal must wait until the outermost execution unwinds. unset($this->handles[$id], $this->delays[$id], $this->deferredAdds[$id]); $this->deferredCancels[$id] = ['easy' => $entry['easy'], 'attached' => true]; } else { $this->discardPendingRequest($id, $entry, $failure); } $entry['deferred']->reject($failure); return false; } /** * Attaches requests whose native attachment was deferred because they * were created from inside a cURL callback. */ private function flushDeferredAdds(): void { if ($this->deferredAdds === []) { return; } $adds = $this->deferredAdds; $this->deferredAdds = []; foreach ($adds as $id => $token) { if (!$this->hasRequest($id, $token)) { // Cancelled or replaced while the attachment was deferred. continue; } $entry = $this->handles[$id]; try { $this->addCurlHandle($entry['easy']); } catch (\Throwable $e) { // The promise has already escaped, so reject it rather than // throw. User code may have settled it directly; a settled // promise must not abort the rest of the snapshot. $rejection = $this->discardPendingRequest($id, $entry, $e); if (P\Is::pending($entry['deferred'])) { $entry['deferred']->reject($rejection); } } } } /** * Cancels a handle from sending and removes references to it. * * @param int $id Handle ID to cancel and remove. * @param object|null $waitToken Identity token that must still match the * entry when given. * * @return bool True on success, false on failure. */ private function cancel($id, ?object $waitToken = null): bool { if (!is_int($id)) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } // Cannot cancel if it has been processed or replaced by a request // that reused the native handle ID. if (!isset($this->handles[$id]) || ($waitToken !== null && ($this->handles[$id]['wait_token'] ?? null) !== $waitToken)) { return false; } $entry = $this->handles[$id]; $easy = $entry['easy']; $attached = !empty($entry['attached']); unset($this->delays[$id], $this->deferredAdds[$id], $this->handles[$id]); if ($this->multiExecDepth > 0) { $this->deferredCancels[$id] = ['easy' => $easy, 'attached' => $attached]; return true; } $this->cleanupCancelledHandle($easy, $attached); return true; } private function cleanupDeferredCancels(?\Throwable &$failure): void { if ($this->deferredCancels === []) { return; } $entries = $this->deferredCancels; $this->deferredCancels = []; foreach ($entries as $entry) { try { $this->cleanupCancelledHandle($entry['easy'], $entry['attached']); } catch (\Throwable $e) { // A final progress update can run a throwing user callback; // clean the remaining entries and surface the first failure // once the drain completes. if ($failure === null) { $failure = $e; } } } } private function cleanupCancelledHandle(EasyHandle $easy, bool $attached): void { $handle = $easy->handle; $failure = null; if ($attached) { try { $this->removeHandleFromMulti($handle); } catch (\Throwable $e) { // The native detach completes even when its final progress // callback throws; finish this entry before rethrowing. $failure = $e; } } $this->unmarkProxyTunnelActive($easy); if (PHP_VERSION_ID < 80000) { try { \curl_close($handle); } catch (\Throwable $e) { // An error handler can promote the close warning; keep the // first failure. if ($failure === null) { $failure = $e; } } } if ($failure !== null) { throw $failure; } } private function processMessages(): void { // CurlFactory::finish can retry a transfer by re-invoking this handler // from inside this loop; the guard keeps that re-entry from recreating // the multi handle mid-iteration (see applyProxyTunnelOwnership). A // depth is tracked because a completion callback can re-enter tick(), // and the nested frame must not clear the outer loop's guard. ++$this->messageProcessingDepth; try { while ($done = \curl_multi_info_read($this->_mh)) { if ($done['msg'] !== \CURLMSG_DONE) { // if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216 continue; } if (!isset($done['handle'])) { // Work around a PHP issue where cancelled transfers may omit the handle. // Remove this once we no longer support PHP versions before the fix in // https://github.com/php/php-src/pull/16302. continue; } $id = (int) $done['handle']; $this->removeCompletedHandleFromMulti($id, $done['handle']); if (!isset($this->handles[$id])) { // Probably was cancelled. continue; } $entry = $this->handles[$id]; unset($this->handles[$id], $this->delays[$id]); $entry['easy']->errno = $done['result']; // finish() can run completion callbacks that cancel this // promise; a settled promise must not be settled again. try { $result = CurlFactory::finish($this, $entry['easy'], $this->factory); } catch (\Throwable $e) { if (P\Is::pending($entry['deferred'])) { $entry['deferred']->reject($e); } continue; } if (P\Is::pending($entry['deferred'])) { $entry['deferred']->resolve($result); } } } finally { --$this->messageProcessingDepth; } } /** * Bounds a blocking select by the earliest pending request delay so a * delayed transfer becoming due does not wait out an unrelated * transfer's full select timeout. * * @return float|int */ private function effectiveSelectTimeout() { if ($this->delays === []) { return $this->selectTimeout; } return \min($this->selectTimeout, $this->secondsToNext()); } /** * @return float Seconds until the earliest pending delay is due */ private function secondsToNext(): float { $currentTime = Utils::currentTime(); $nextTime = \PHP_FLOAT_MAX; foreach ($this->delays as $time) { if ($time < $nextTime) { $nextTime = $time; } } return \max(0.0, $nextTime - $currentTime); } private function timeToNext(): int { // PHP_INT_MAX first: min() then returns the int operand whenever the // microseconds exceed it, so the cast never sees an oversized float. return (int) \min(\PHP_INT_MAX, $this->secondsToNext() * 1000000); } } mode = $mode; $this->handle = $handle; } /** * @param mixed $sharing */ public static function fromOption($sharing): ?self { if ($sharing instanceof self) { return $sharing; } $mode = self::normalizeMode($sharing, 'transport_sharing'); if ($mode === TransportSharing::NONE) { return null; } if ($mode === TransportSharing::HANDLER_PREFER) { return self::createHandlerShareOrNull($mode); } return self::createHandlerShare($mode); } /** * @param mixed $sharing */ public static function normalizeMode($sharing, string $option): string { if ($sharing instanceof self) { return $sharing->mode; } if ($sharing === null || $sharing === TransportSharing::NONE) { return TransportSharing::NONE; } if ($sharing === TransportSharing::HANDLER_PREFER || $sharing === TransportSharing::HANDLER_REQUIRE) { return $sharing; } throw new \InvalidArgumentException(\sprintf( 'The "%s" option must be null or a GuzzleHttp\\TransportSharing::* constant; received %s.', $option, \get_debug_type($sharing) )); } public static function assertNoRequiredSharingCustomFactoryConflict(array $options, string $handlerName): void { if (!\array_key_exists('handle_factory', $options) || $options['handle_factory'] === null) { return; } $mode = self::normalizeMode($options['transport_sharing'] ?? null, 'transport_sharing'); if ($mode !== TransportSharing::HANDLER_REQUIRE) { return; } throw new \InvalidArgumentException(\sprintf( 'The "transport_sharing" %s option cannot require sharing with a custom "handle_factory" because Guzzle cannot ensure that the custom factory applies CURLOPT_SHARE.', $handlerName )); } private static function createHandlerShareOrNull(string $mode): ?self { try { return self::createHandlerShare($mode); } catch (\Throwable $e) { return null; } } private static function createHandlerShare(string $mode): self { if (!\function_exists('curl_share_init') || !\function_exists('curl_share_setopt')) { throw new \InvalidArgumentException('The "transport_sharing" option requires cURL share support.'); } self::requireCurlConstant('CURLOPT_SHARE'); $shareOption = self::requireCurlConstant('CURLSHOPT_SHARE'); $locks = self::handlerLocks($mode); $handle = curl_share_init(); try { foreach ($locks as $lock) { try { $success = curl_share_setopt($handle, $shareOption, $lock); } catch (\Throwable $e) { throw new \InvalidArgumentException('Unable to configure cURL share handle: '.$e->getMessage(), 0, $e); } if (!$success) { throw new \InvalidArgumentException(\sprintf('Unable to configure cURL share handle with lock data %d.', $lock)); } } } catch (\Throwable $e) { self::closeHandlerShareHandleOnPhp7($handle); throw $e; } return new self($mode, $handle); } /** * @return int[] */ private static function handlerLocks(string $mode): array { CurlVersion::ensureHandlerSharingSupported(); if ($mode === TransportSharing::HANDLER_REQUIRE) { CurlVersion::ensureSslSessionSharingSupported(); } $locks = [ self::requireCurlConstant('CURL_LOCK_DATA_DNS'), ]; if (CurlVersion::supportsSslSessionSharing()) { $locks[] = self::requireCurlConstant('CURL_LOCK_DATA_SSL_SESSION'); } return $locks; } private static function requireCurlConstant(string $constant): int { if (!\defined($constant)) { throw new \InvalidArgumentException(\sprintf( 'The "transport_sharing" option requires %s, but it is not available in the installed PHP cURL extension.', $constant )); } $value = \constant($constant); if (!\is_int($value)) { throw new \InvalidArgumentException(\sprintf('The cURL constant %s must resolve to an integer.', $constant)); } return $value; } /** * @param resource|\CurlShareHandle $handle */ private static function closeHandlerShareHandleOnPhp7($handle): void { if (\PHP_VERSION_ID < 80000 && \is_resource($handle)) { curl_share_close($handle); } } } ='); } public static function supportsTls12(): bool { $version = self::getVersion(); return self::supportsSsl() && \defined('CURL_SSLVERSION_TLSv1_2') && $version !== null && \version_compare($version, self::TLS_12_VERSION, '>='); } public static function supportsTls13(): bool { $version = self::getVersion(); return self::supportsSsl() && \defined('CURL_SSLVERSION_TLSv1_3') && $version !== null && \version_compare($version, self::TLS_13_VERSION, '>='); } public static function supportsHttp2(): bool { $versionInfo = self::getVersionInfo(); return self::supportsTls12() && \defined('CURL_VERSION_HTTP2') && $versionInfo !== null && 0 !== (\CURL_VERSION_HTTP2 & $versionInfo['features']); } public static function supportsMultiplex(): bool { $version = self::getVersion(); return \defined('CURLOPT_PIPEWAIT') && $version !== null && \version_compare($version, self::MULTIPLEX_VERSION, '>='); } public static function supportsHttpVersionReuseMatching(): bool { $version = self::getVersion(); if ($version === null || \version_compare($version, self::HTTP_VERSION_REUSE_MATCH_VERSION, '<')) { return false; } return \version_compare($version, self::HTTP_VERSION_REUSE_MATCH_REGRESSION, '<') || \version_compare($version, self::HTTP_VERSION_REUSE_MATCH_RESTORED, '>='); } public static function supportsConnectionCaps(): bool { $version = self::getVersion(); return \defined('CURLMOPT_MAX_HOST_CONNECTIONS') && \defined('CURLMOPT_MAX_TOTAL_CONNECTIONS') && $version !== null && \version_compare($version, self::CONNECTION_CAP_VERSION, '>='); } public static function ensureConnectionCapsSupported(string $option): void { if (self::supportsConnectionCaps()) { return; } throw new \InvalidArgumentException(\sprintf( 'The "%s" option requires PHP cURL support for CURLMOPT_MAX_HOST_CONNECTIONS and CURLMOPT_MAX_TOTAL_CONNECTIONS with libcurl %s or newer.', $option, self::CONNECTION_CAP_VERSION )); } public static function supportsRequiredMultiplex(): bool { $version = self::getVersion(); return \defined('CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE') && $version !== null && self::supportsHttp2() && \version_compare($version, self::REQUIRED_MULTIPLEX_VERSION, '>='); } public static function supportsHttpsProxy(): bool { $versionInfo = self::getVersionInfo(); // CURL_VERSION_HTTPS_PROXY is not defined on every supported PHP // version; fall back to the curl.h bit value. $httpsProxyFeature = \defined('CURL_VERSION_HTTPS_PROXY') ? \CURL_VERSION_HTTPS_PROXY : (1 << 21); return $versionInfo !== null && \version_compare($versionInfo['version'], self::HTTPS_PROXY_VERSION, '>=') && 0 !== ($httpsProxyFeature & $versionInfo['features']); } public static function supportsNtlm(): bool { $versionInfo = self::getVersionInfo(); // CURL_VERSION_NTLM is not defined on every supported PHP version; fall // back to the curl.h bit value. $ntlmFeature = \defined('CURL_VERSION_NTLM') ? \CURL_VERSION_NTLM : (1 << 4); return \defined('CURLAUTH_NTLM') && $versionInfo !== null && 0 !== ($ntlmFeature & $versionInfo['features']); } public static function supportsHandlerSharing(): bool { $version = self::getVersion(); return $version !== null && \version_compare($version, self::HANDLER_SHARING_VERSION, '>='); } public static function ensureHandlerSharingSupported(): void { if (!self::supportsHandlerSharing()) { throw new \InvalidArgumentException(\sprintf( 'The "transport_sharing" option requires libcurl %s or higher for cURL share handles.', self::HANDLER_SHARING_VERSION )); } } public static function supportsSslSessionSharing(): bool { $version = self::getVersion(); return self::supportsSsl() && $version !== null && \version_compare($version, self::SSL_SESSION_SHARING_VERSION, '>='); } public static function ensureSslSessionSharingSupported(): void { if (!self::supportsSslSessionSharing()) { throw new \InvalidArgumentException(\sprintf( 'The "transport_sharing" option requires libcurl %s or higher with SSL support for SSL session sharing.', self::SSL_SESSION_SHARING_VERSION )); } } public static function supportsShareConnectionCaches(): bool { $version = self::getVersion(); // An undetectable libcurl version is treated as capable so the // opaque share safeguards fail closed. return $version === null || \version_compare($version, self::SHARE_CONNECTION_CACHE_VERSION, '>='); } public static function supportsProxyTlsCredentialAwareConnectionReuse(): bool { $version = self::getVersion(); return $version !== null && \version_compare($version, self::PROXY_TLS_CREDENTIAL_REUSE_VERSION, '>='); } public static function supportsProxyCredentialAwareConnectionReuse(): bool { $version = self::getVersion(); return $version !== null && \version_compare($version, self::PROXY_CREDENTIAL_REUSE_VERSION, '>='); } public static function supportsSocksProxyCredentialAwareConnectionReuse(): bool { $version = self::getVersion(); return $version !== null && \version_compare($version, self::SOCKS_PROXY_CREDENTIAL_REUSE_VERSION, '>='); } public static function supportsProxyHeaderSeparation(): bool { $version = self::getVersion(); return $version !== null && \version_compare($version, self::PROXY_HEADER_SEPARATION_VERSION, '>=') && \defined('CURLOPT_PROXYHEADER') && \defined('CURLOPT_HEADEROPT') && \defined('CURLHEADER_SEPARATE'); } private static function supportsSsl(): bool { $versionInfo = self::getVersionInfo(); return \defined('CURL_VERSION_SSL') && $versionInfo !== null && 0 !== (\CURL_VERSION_SSL & $versionInfo['features']); } public static function getVersion(): ?string { $versionInfo = self::getVersionInfo(); return $versionInfo === null ? null : $versionInfo['version']; } /** * @return array{version: string, features: int}|null */ private static function getVersionInfo(): ?array { if (self::$versionInfo === null) { if (!\function_exists('curl_version')) { self::$versionInfo = false; } else { $versionInfo = \curl_version(); self::$versionInfo = \is_array($versionInfo) && isset($versionInfo['version'], $versionInfo['features']) && \is_string($versionInfo['version']) && \is_int($versionInfo['features']) ? [ 'version' => $versionInfo['version'], 'features' => $versionInfo['features'], ] : false; } } return self::$versionInfo === false ? null : self::$versionInfo; } } response = null; [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($this->headers); $normalizedKeys = Utils::normalizeHeaderKeys($headers); if (isset($this->options['decode_content']) && $this->options['decode_content'] !== false && isset($normalizedKeys['content-encoding'])) { $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; unset($headers[$normalizedKeys['content-encoding']]); if (isset($normalizedKeys['content-length'])) { $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; $bodyLength = (int) $this->sink->getSize(); if ($bodyLength) { $headers[$normalizedKeys['content-length']] = [(string) $bodyLength]; } else { unset($headers[$normalizedKeys['content-length']]); } } } // Attach a response to the easy handle with the parsed headers. $this->response = new Response( $status, $headers, $this->sink, $ver, $reason ); } /** * @param string $name * * @return void * * @throws \BadMethodCallException */ public function __get($name) { $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: '.$name; throw new \BadMethodCallException($msg); } } $headers * * @return list */ private static function getLastHeaderBlock(array $headers): array { $lastStatusLine = 0; foreach ($headers as $index => $line) { if (self::isStatusLineCandidate($line)) { $lastStatusLine = $index; } } return \array_slice($headers, $lastStatusLine); } } getUri()->getHost(); self::assertUriHostValue($host, $request); self::assertNoAuthorityDelimiter($host, $request); self::assertNotADottedAddress($host, $request); foreach ($request->getHeader('Host') as $value) { self::assertHostHeaderValue((string) $value, $request); } } /** * @throws RequestException */ private static function assertUriHostValue(string $value, RequestInterface $request): void { if (!self::isPrintableAscii($value)) { throw new RequestException(\sprintf('The request URI host "%s" must contain only printable ASCII characters, because a handler can otherwise connect to a host that differs from the one the request names. An internationalized host name has an A-label form that this rule accepts.', self::escape($value)), $request); } if (\strpos($value, '%') !== false) { throw new RequestException(\sprintf('The request URI host "%s" must not contain a percent escape, because a handler can decode it and then connect to a host that differs from the one the request names.', self::escape($value)), $request); } } /** * The Host header is sent rather than reparsed for the connection, so its * diagnostics describe a request authority the caller did not write. * * @throws RequestException */ private static function assertHostHeaderValue(string $value, RequestInterface $request): void { if (!self::isPrintableAscii($value)) { throw new RequestException(\sprintf('The request Host header "%s" must contain only printable ASCII characters, because an intermediary or an origin server can otherwise read it as an authority that differs from the one the request names. An internationalized host name has an A-label form that this rule accepts.', self::escape($value)), $request); } if (\strpos($value, '%') !== false) { throw new RequestException(\sprintf('The request Host header "%s" must not contain a percent escape, because an intermediary or an origin server can decode it and then read it as an authority that differs from the one the request names.', self::escape($value)), $request); } } /** * Matches the accepted shape positively so a PCRE failure rejects. */ private static function isPrintableAscii(string $value): bool { return \preg_match('/\A[\x21-\x7E]*\z/D', $value) === 1; } /** * Rejects a delimiter the transport could treat as the end of the URI host. * * This mirrors GuzzleHttp\Psr7\Uri::assertValidHost() and only affects * third-party UriInterface values. Host headers may carry a port and are * sent verbatim. * * @throws RequestException */ private static function assertNoAuthorityDelimiter(string $host, RequestInterface $request): void { $message = 'The request URI host "%s" must not contain a URI authority delimiter, because a handler reparses the URI and can then connect to a host that differs from the one the request names.'; // Match the accepted shape positively so a PCRE engine failure rejects. if (\preg_match('/\A[^\/?#@\\\\]*\z/D', $host) !== 1) { throw new RequestException(\sprintf($message, self::escape($host)), $request); } if (\strpos($host, '[') !== false || \strpos($host, ']') !== false) { if (\strpos($host, '[') !== 0 || \substr($host, -1) !== ']') { throw new RequestException(\sprintf($message, self::escape($host)), $request); } return; } if (\strpos($host, ':') !== false) { throw new RequestException(\sprintf($message, self::escape($host)), $request); } } /** * Rejects one to four numeric-looking parts followed by trailing dots. * * libcurl 8.21.0 drops a trailing dot from inet_aton-style numeric hosts * before connecting, while other validators treat the input as a name. * Testing the shape also rejects some out-of-range values that transports * keep as names; isNumericIpv4Host() explains that fail-closed tradeoff. * Plain numeric shorthand stays accepted. * * @throws RequestException */ private static function assertNotADottedAddress(string $host, RequestInterface $request): void { if (\substr($host, -1) !== '.') { return; } if (!self::isNumericIpv4Host(\rtrim($host, '.'))) { return; } throw new RequestException(\sprintf('The request URI host "%s" must not be written as one to four decimal, octal or hexadecimal parts followed by one or more trailing dots, because a handler can read that spelling as an IPv4 address and connect to that address while the rest of the process reads a name.', self::escape($host)), $request); } /** * Reports whether a value has the transport's inet_aton-style shape: one * to four decimal, 0-prefixed octal, or 0x-prefixed hexadecimal parts. * * Range and 32-bit overflow checks are deliberately omitted. This may * reject a trailing-dot spelling the transport reads as a name, but avoids * missing one it resolves as an address. No PCRE is used. */ public static function isNumericIpv4Host(string $host): bool { if ($host === '') { return false; } $parts = \explode('.', $host); if (\count($parts) > 4) { return false; } foreach ($parts as $part) { if (!self::isNumericIpv4Part($part)) { return false; } } return true; } private static function isNumericIpv4Part(string $part): bool { if ($part === '') { return false; } if ($part[0] === '0' && isset($part[1]) && ($part[1] === 'x' || $part[1] === 'X')) { return \strlen($part) > 2 && \strspn($part, '0123456789abcdefABCDEF', 2) === \strlen($part) - 2; } $digits = $part[0] === '0' ? '01234567' : '0123456789'; return \strspn($part, $digits) === \strlen($part); } /** * Escapes non-printable bytes as uppercase \xNN for safe diagnostics. * Printable delimiters and dots stay visible. The result is not a * reversible encoding. */ private static function escape(string $value): string { $escaped = ''; for ($offset = 0, $length = \strlen($value); $offset < $length; ++$offset) { $byte = \ord($value[$offset]); $escaped .= $byte >= 0x21 && $byte <= 0x7E ? $value[$offset] : \sprintf('\\x%02X', $byte); } return $escaped; } } |null $queue The parameters to be passed to the append function, as an indexed array. * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. * @param callable|null $onRejected Callback to invoke when the return value is rejected. */ public function __construct(?array $queue = null, ?callable $onFulfilled = null, ?callable $onRejected = null) { $this->onFulfilled = $onFulfilled; $this->onRejected = $onRejected; if ($queue) { // array_values included for BC $this->append(...array_values($queue)); } } public function __invoke(RequestInterface $request, array $options): PromiseInterface { if (!$this->queue) { throw new \OutOfBoundsException('Mock queue is empty'); } if (isset($options['delay']) && \is_numeric($options['delay'])) { \usleep((int) $options['delay'] * 1000); } $this->lastRequest = $request; $this->lastOptions = $options; $response = \array_shift($this->queue); if (isset($options['on_headers'])) { if (!\is_callable($options['on_headers'])) { throw new \InvalidArgumentException('on_headers must be callable'); } try { $options['on_headers']($response); } catch (\Exception $e) { $msg = 'An error was encountered during the on_headers event'; $response = new RequestException($msg, $request, $response, $e); } } if (\is_callable($response)) { $response = $response($request, $options); } $response = $response instanceof \Throwable ? P\Create::rejectionFor($response) : P\Create::promiseFor($response); return $response->then( function (?ResponseInterface $value) use ($request, $options) { $this->invokeStats($request, $options, $value); if ($this->onFulfilled) { ($this->onFulfilled)($value); } if ($value !== null && isset($options['sink'])) { $contents = (string) $value->getBody(); $sink = $options['sink']; if (\is_resource($sink)) { \fwrite($sink, $contents); } elseif (\is_string($sink)) { \file_put_contents($sink, $contents); } elseif ($sink instanceof StreamInterface) { $sink->write($contents); } } return $value; }, function ($reason) use ($request, $options) { $this->invokeStats($request, $options, null, $reason); if ($this->onRejected) { ($this->onRejected)($reason); } return P\Create::rejectionFor($reason); } ); } /** * Adds one or more variadic requests, exceptions, callables, or promises * to the queue. * * @param mixed ...$values */ public function append(...$values): void { foreach ($values as $value) { if ($value instanceof ResponseInterface || $value instanceof \Throwable || $value instanceof PromiseInterface || \is_callable($value) ) { $this->queue[] = $value; } else { throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found '.\get_debug_type($value)); } } } /** * Get the last received request. */ public function getLastRequest(): ?RequestInterface { return $this->lastRequest; } /** * Get the last received request options. */ public function getLastOptions(): array { return $this->lastOptions; } /** * Returns the number of remaining items in the queue. */ public function count(): int { return \count($this->queue); } public function reset(): void { $this->queue = []; } /** * @param mixed $reason Promise or reason. */ private function invokeStats( RequestInterface $request, array $options, ?ResponseInterface $response = null, $reason = null ): void { if (isset($options['on_stats'])) { $transferTime = $options['transfer_time'] ?? 0; $stats = new TransferStats($request, $response, $transferTime, $reason); ($options['on_stats'])($stats); } } } $options */ private static function requiresTls12Fallback(array $options): bool { return isset($options[RequestOptions::CRYPTO_METHOD]) && $options[RequestOptions::CRYPTO_METHOD] === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT && !CurlVersion::supportsTls12(); } } true, 'max_total_connections' => true, 'transport_sharing' => true, ]; private const CONNECTION_ERRORS = [ 'php_network_getaddresses:', 'getaddrinfo', 'gethostbyname failed', 'Connection refused', 'No connection could be made because the target machine actively refused it', "couldn't connect to host", // error on HHVM 'connection attempt failed', 'connect() failed', 'Connection timed out', 'Operation timed out', 'Network is unreachable', 'No route to host', 'Host is unreachable', 'Host is down', 'Cannot connect to HTTPS server through proxy', ]; /** * @var array */ private $lastHeaders = []; /** * @var string */ private $transportSharingMode; /** * @var bool */ private $connectionCapsConfigured = false; /** * Accepts an associative array of options: * * - max_host_connections: Optional positive integer or null. A non-null * value marks the handler as incompatible with enabled response * streaming; the number is not used for stream-handler admission. * - max_total_connections: Optional positive integer or null. A non-null * value marks the handler as incompatible with enabled response * streaming; the number is not used for stream-handler admission. * - transport_sharing: Optional transport sharing mode. * * The stream handler cannot cap streamed connections, so a configured cap * marker rejects enabled response streaming ("stream" => true). Accepted * transfers are buffered and hold at most one connection per in-flight * call, but overlapping buffered calls are not collectively limited. * * @param array{max_host_connections?: mixed, max_total_connections?: mixed, transport_sharing?: mixed} $options Array of options to use with the handler */ public function __construct(array $options = []) { foreach ($options as $name => $_) { if (!isset(self::KNOWN_CONSTRUCTOR_OPTIONS[$name])) { \trigger_deprecation('guzzlehttp/guzzle', '7.14', \sprintf('The "%s" StreamHandler constructor option is unknown; guzzlehttp/guzzle 8.0 will reject unknown constructor options.', (string) $name)); } } $this->transportSharingMode = CurlShareHandleState::normalizeMode( $options['transport_sharing'] ?? null, 'transport_sharing' ); foreach (['max_host_connections', 'max_total_connections'] as $capOption) { $value = $options[$capOption] ?? null; if ($value === null) { continue; } if (!\is_int($value) || $value < 1) { throw new \InvalidArgumentException(\sprintf('%s must be a positive integer.', $capOption)); } $this->connectionCapsConfigured = true; } } /** * Sends an HTTP request. * * @param RequestInterface $request Request to send. * @param array $options Request transfer options. */ public function __invoke(RequestInterface $request, array $options): PromiseInterface { // Sleep if there is a delay specified. if (isset($options['delay'])) { \usleep($options['delay'] * 1000); } $multiplex = $options['multiplex'] ?? null; // Multiplexing::NONE is trivially satisfied: the stream handler sends // one HTTP/1.x request per connection and never multiplexes. if (null !== $multiplex && !\in_array($multiplex, [Multiplexing::NONE, Multiplexing::EAGER, Multiplexing::WAIT, Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) { throw new \InvalidArgumentException(\sprintf( 'The "multiplex" option must be null or a GuzzleHttp\\Multiplexing::* constant; received %s.', \get_debug_type($multiplex) )); } if (\in_array($multiplex, [Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) { throw new ConnectException('The stream handler cannot guarantee a multiplexed protocol; required multiplexing needs a cURL handler.', $request); } if ($this->connectionCapsConfigured && !empty($options['stream'])) { throw new \InvalidArgumentException('Enabling the "stream" request option on a stream handler configured with the "max_host_connections" or "max_total_connections" option is not supported because streamed connections cannot be capped.'); } if (isset($options['on_trailers'])) { throw new \InvalidArgumentException('Passing the "on_trailers" request option to the stream handler is not supported because the stream handler cannot observe trailers.'); } $protocolVersion = $request->getProtocolVersion(); if ('' === $protocolVersion) { \trigger_deprecation('guzzlehttp/guzzle', '7.11', 'Sending a request with an empty protocol version is deprecated; guzzlehttp/guzzle 8.0 will reject empty protocol versions.'); $protocolVersion = '1.1'; $request = Psr7\Utils::modifyRequest($request, ['version' => $protocolVersion]); } if ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) { throw new ConnectException(sprintf('HTTP/%s is not supported by the stream handler.', $protocolVersion), $request); } $startTime = isset($options['on_stats']) ? Utils::currentTime() : null; self::triggerUnsupportedRequestOptionDeprecations($request, $options); $this->assertTransportSharingSupported(); try { // Does not support the expect header. $request = $request->withoutHeader('Expect'); // Append a content-length header if body size is zero to match // the behavior of `CurlHandler` if ( ( Psr7\Utils::caselessEquals('PUT', $request->getMethod()) || Psr7\Utils::caselessEquals('POST', $request->getMethod()) ) && 0 === $request->getBody()->getSize() ) { $request = $request->withHeader('Content-Length', '0'); } return $this->createResponse( $request, $options, $this->createStream($request, $options), $startTime ); } catch (\InvalidArgumentException $e) { throw $e; } catch (\Exception $e) { if (!$e instanceof TransferException) { $e = self::isConnectionError($e->getMessage()) ? new ConnectException($e->getMessage(), $request, $e) : new RequestException($e->getMessage(), $request, null, $e); } $this->invokeStats($options, $request, $startTime, null, $e); return P\Create::rejectionFor($e); } } private static function isConnectionError(string $message): bool { foreach (self::CONNECTION_ERRORS as $connectionError) { if (false !== \strpos($message, $connectionError)) { return true; } } return false; } private function invokeStats( array $options, RequestInterface $request, ?float $startTime, ?ResponseInterface $response = null, ?\Throwable $error = null ): void { if (isset($options['on_stats'])) { $stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []); ($options['on_stats'])($stats); } } /** * @param resource $stream */ private function createResponse(RequestInterface $request, array $options, $stream, ?float $startTime): PromiseInterface { $hdrs = $this->lastHeaders; $this->lastHeaders = []; try { [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($hdrs); } catch (\Throwable $e) { return $this->rejectResponseCreation($options, $request, $startTime, $e); } [$stream, $headers] = $this->checkDecode($options, $headers, $stream); $stream = Psr7\Utils::streamFor($stream); $sink = $stream; if (!Psr7\Utils::caselessEquals('HEAD', $request->getMethod())) { $sink = $this->createSink($stream, $options); } try { $response = new Psr7\Response($status, $headers, $sink, $ver, $reason); } catch (\Throwable $e) { return $this->rejectResponseCreation($options, $request, $startTime, $e); } if (isset($options['on_headers'])) { try { $options['on_headers']($response); } catch (\Throwable $e) { return P\Create::rejectionFor( new RequestException('An error was encountered during the on_headers event', $request, $response, $e) ); } } // Do not drain when the request is a HEAD request because they have // no body. if ($sink !== $stream) { $this->drain($stream, $sink, $response->getHeaderLine('Content-Length')); } $this->invokeStats($options, $request, $startTime, $response, null); return new FulfilledPromise($response); } private function rejectResponseCreation( array $options, RequestInterface $request, ?float $startTime, \Throwable $previous ): PromiseInterface { $reason = new RequestException( 'An error was encountered while creating the response', $request, null, $previous ); $this->invokeStats($options, $request, $startTime, null, $reason); return P\Create::rejectionFor($reason); } private function createSink(StreamInterface $stream, array $options): StreamInterface { if (!empty($options['stream'])) { return $stream; } $sink = $options['sink'] ?? Psr7\Utils::tryFopen('php://temp', 'r+'); return \is_string($sink) ? new Psr7\LazyOpenStream($sink, 'w+') : Psr7\Utils::streamFor($sink); } /** * @param resource $stream */ private function checkDecode(array $options, array $headers, $stream): array { // Automatically decode responses when instructed. if (isset($options['decode_content']) && $options['decode_content'] !== false) { $normalizedKeys = Utils::normalizeHeaderKeys($headers); if (isset($normalizedKeys['content-encoding'])) { $encoding = $headers[$normalizedKeys['content-encoding']]; if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') { $stream = new Psr7\InflateStream(Psr7\Utils::streamFor($stream)); $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; // Remove content-encoding header unset($headers[$normalizedKeys['content-encoding']]); // The decoded length cannot be known without inflating the // stream, so keep the original length for inspection and // drop the now-unknown Content-Length header. if (isset($normalizedKeys['content-length'])) { $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; unset($headers[$normalizedKeys['content-length']]); } } } } return [$stream, $headers]; } /** * Drains the source stream into the "sink" client option. * * @param string $contentLength Header specifying the amount of * data to read. * * @throws \RuntimeException when the sink option is invalid. */ private function drain(StreamInterface $source, StreamInterface $sink, string $contentLength): StreamInterface { // If a content-length header is provided, then stop reading once // that number of bytes has been read. This can prevent infinitely // reading from a stream when dealing with servers that do not honor // Connection: Close headers. Psr7\Utils::copyToStream( $source, $sink, (\strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1 ); $sink->seek(0); $source->close(); return $sink; } /** * Create a resource and check to ensure it was created successfully * * @param callable $callback Callable that returns stream resource * * @return resource * * @throws \RuntimeException on error */ private function createResource(callable $callback) { $errors = []; \set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool { $errors[] = [ 'message' => $msg, 'file' => $file, 'line' => $line, ]; return true; }); try { $resource = $callback(); } finally { \restore_error_handler(); } if (!$resource) { $message = 'Error creating resource: '; foreach ($errors as $err) { foreach ($err as $key => $value) { $message .= "[$key] $value".\PHP_EOL; } } throw new \RuntimeException(\trim($message, " \n\r\t\0\x0B")); } return $resource; } /** * @return resource */ private function createStream(RequestInterface $request, array $options) { static $methods; if (!$methods) { $methods = \array_flip(\get_class_methods(__CLASS__)); } $uri = $request->getUri(); $scheme = $uri->getScheme(); if ($scheme === '') { throw new RequestException('URI must include a scheme and host. Use an absolute URI, a network-path reference starting with //, or configure a base_uri.', $request); } if (!\in_array($scheme, ['http', 'https'], true)) { throw new RequestException(\sprintf("The scheme '%s' is not supported.", $scheme), $request); } $protocols = Utils::normalizeProtocols($options['protocols'] ?? ['http', 'https']); if (!\in_array($scheme, $protocols, true)) { throw new RequestException(\sprintf('The scheme "%s" is not allowed by the protocols request option.', $scheme), $request); } if ($uri->getHost() === '') { throw new RequestException('URI must include a scheme and host. Use an absolute URI, a network-path reference starting with //, or configure a base_uri.', $request); } HostValidator::assertRequestHost($request); // HTTP/1.1 streams using the PHP stream wrapper require a // Connection: close header if ($request->getProtocolVersion() === '1.1' && !$request->hasHeader('Connection') ) { $request = $request->withHeader('Connection', 'close'); } // Ensure SSL is verified by default if (!isset($options['verify'])) { $options['verify'] = true; } $params = []; $context = $this->getDefaultContext($request); if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) { throw new \InvalidArgumentException('on_headers must be callable'); } self::assertTlsVersionRangeForOptions($options); $proxyAuthorizationAdded = false; if (!empty($options)) { foreach ($options as $key => $value) { $method = "add_{$key}"; if (isset($methods[$method])) { if ($method === 'add_proxy') { $proxyAuthorizationAdded = $this->add_proxy($request, $context, $value, $params); continue; } $this->{$method}($request, $context, $value, $params); } } } if (isset($options['stream_context'])) { if (!\is_array($options['stream_context'])) { throw new \InvalidArgumentException('stream_context must be an array'); } if ( $proxyAuthorizationAdded && isset($options['stream_context']['http']) && \is_array($options['stream_context']['http']) && \array_key_exists('proxy', $options['stream_context']['http']) ) { throw new \InvalidArgumentException('stream_context.http.proxy cannot override a proxy after the stream handler has generated a Proxy-Authorization header; configure the final proxy with the "proxy" request option.'); } self::triggerConflictingStreamContextOptionDeprecations($options['stream_context']); self::triggerUnsupportedStreamContextOptionDeprecations($options['stream_context']); $context = \array_replace_recursive($context, $options['stream_context']); } // Microsoft NTLM authentication only supported with curl handler if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) { throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler'); } $uri = $this->resolveHost($request, $options); $contextResource = $this->createResource( static function () use ($context, $params) { return \stream_context_create($context, $params); } ); return $this->createResource( function () use ($uri, $contextResource, $context, $options, $request) { $resource = @\fopen((string) $uri, 'r', false, $contextResource); // See https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_http_response_header_predefined_variable if (function_exists('http_get_last_response_headers')) { $http_response_header = \http_get_last_response_headers(); } $this->lastHeaders = $http_response_header ?? []; if (false === $resource) { throw new ConnectException(sprintf('Connection refused for URI %s', Psr7\Utils::redactUserInfo($uri)), $request, null, $context); } if (isset($options['read_timeout'])) { $readTimeout = $options['read_timeout']; $sec = (int) $readTimeout; $usec = ($readTimeout - $sec) * 100000; \stream_set_timeout($resource, $sec, $usec); } return $resource; } ); } private function resolveHost(RequestInterface $request, array $options): UriInterface { $uri = $request->getUri(); $host = $uri->getHost(); // Fold a numeric IPv4 spelling to the dotted quad libcurl connects // to, rather than leaving it to the platform resolver: macOS reads // the zero-padded 0177 as decimal 177 where glibc, musl and FreeBSD // read octal 127. The Host header is serialized from the request and // stays as written; the TLS peer name follows the same fold. $canonicalHost = self::canonicalConnectionHost($host); if ($canonicalHost !== $host) { $uri = $uri->withHost($canonicalHost); $host = $canonicalHost; } $hostForIpCheck = $host !== '' && $host[0] === '[' && \substr($host, -1) === ']' ? \substr($host, 1, -1) : $host; if (isset($options['force_ip_resolve']) && !\filter_var($hostForIpCheck, \FILTER_VALIDATE_IP)) { if ('v4' === $options['force_ip_resolve']) { $records = \dns_get_record($uri->getHost(), \DNS_A); if (false === $records || !isset($records[0]['ip'])) { throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); } return $uri->withHost($records[0]['ip']); } if ('v6' === $options['force_ip_resolve']) { $records = \dns_get_record($uri->getHost(), \DNS_AAAA); if (false === $records || !isset($records[0]['ipv6'])) { throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); } return $uri->withHost('['.$records[0]['ipv6'].']'); } } return $uri; } /** * Returns a numeric IPv4 spelling folded to the dotted quad libcurl's * ipv4_normalize() produces, and every other host unchanged. */ private static function canonicalConnectionHost(string $host): string { $binary = self::numericIpv4ToBinary($host); if ($binary === null) { return $host; } return (string) \inet_ntop($binary); } /** * Returns the four-byte binary form of a host that a transport reads as a * numeric IPv4 address, or null when it reads it as a name. * * The shape test is HostValidator::isNumericIpv4Host(); this method adds * the range checks that predicate omits: every part but the last must fit * one octet, and the last must fit the octets the earlier parts left. A * trailing root dot is not swallowed, unlike libcurl 8.21.0 and later, * because assertRequestHost() rejects that spelling first. */ private static function numericIpv4ToBinary(string $host): ?string { if (!HostValidator::isNumericIpv4Host($host)) { return null; } $values = []; foreach (\explode('.', $host) as $part) { $values[] = self::numericIpv4PartValue($part); } // Every accepted value is a whole number no larger than 0xFFFFFFFF, // which a float holds exactly, so the arithmetic below is correct on a // 32-bit build too, where the widest part overflows an integer. $address = (float) \array_pop($values); $packed = ''; foreach ($values as $value) { if ($value > 255.0) { return null; } $packed .= \chr((int) $value); } $width = 4 - \count($values); if ($address >= 256.0 ** $width) { return null; } for ($shift = $width - 1; $shift >= 0; --$shift) { $packed .= \chr((int) \fmod(\floor($address / 256.0 ** $shift), 256.0)); } return $packed; } /** * Returns the value of one accepted part as a float, so a part filling * all four octets such as 2130706433 stays exact on every integer width. */ private static function numericIpv4PartValue(string $part): float { if ($part[0] === '0' && isset($part[1]) && ($part[1] === 'x' || $part[1] === 'X')) { return (float) \hexdec((string) \substr($part, 2)); } if ($part[0] === '0') { return (float) \octdec($part); } return (float) $part; } private function getDefaultContext(RequestInterface $request): array { $headers = ''; foreach ($request->getHeaders() as $name => $value) { // A first-class Proxy-Authorization header is proxy-scoped. Keep // it out of the origin context; add_proxy() adds one // validated canonical line only when Guzzle selects a proxy; PHP // extracts that line for CONNECT and removes it before sending the // tunneled origin request. The caselessEquals() helper is // locale-independent, unlike strcasecmp(), so a locale cannot // make this match miss and re-leak the credential. if (Psr7\Utils::caselessEquals((string) $name, 'Proxy-Authorization')) { continue; } foreach ($value as $val) { $headers .= "$name: $val\r\n"; } } $context = [ 'http' => [ 'method' => $request->getMethod(), 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), 'ignore_errors' => true, 'follow_location' => 0, ], 'ssl' => [ 'peer_name' => self::canonicalConnectionHost($request->getUri()->getHost()), ], ]; $body = (string) $request->getBody(); if ('' !== $body) { $context['http']['content'] = $body; // Prevent the HTTP handler from adding a Content-Type header. if (!$request->hasHeader('Content-Type')) { $context['http']['header'] .= "Content-Type:\r\n"; } } $context['http']['header'] = \rtrim($context['http']['header'], " \n\r\t\0\x0B"); return $context; } private static function triggerUnsupportedRequestOptionDeprecations(RequestInterface $request, array $options): void { if ( \array_key_exists('curl', $options) && $options['curl'] !== null && $options['curl'] !== [] && !self::isCurlOptionGeneratedByAuth($options) ) { \trigger_deprecation('guzzlehttp/guzzle', '7.11', 'Passing the "curl" request option to the stream handler is deprecated; guzzlehttp/guzzle 8.0 will reject this option because the stream handler ignores cURL options.'); } if (\array_key_exists('expect', $options) && $options['expect'] !== false && $request->hasHeader('Expect')) { \trigger_deprecation('guzzlehttp/guzzle', '7.11', 'Passing the "expect" request option to the stream handler is deprecated when it adds an Expect header; guzzlehttp/guzzle 8.0 will reject this option because the stream handler does not support Expect: 100-Continue.'); } } private static function triggerConflictingStreamContextOptionDeprecations(array $streamContext): void { $conflictingOptions = self::conflictingStreamContextOptions(); foreach ($streamContext as $wrapper => $contextOptions) { if (!\is_string($wrapper) || !isset($conflictingOptions[$wrapper]) || !\is_array($contextOptions)) { continue; } foreach ($contextOptions as $option => $_) { if (!\is_string($option) || !\array_key_exists($option, $conflictingOptions[$wrapper])) { continue; } \trigger_deprecation( 'guzzlehttp/guzzle', '7.12', \sprintf( 'Passing stream_context.%s.%s in the "stream_context" request option is deprecated; guzzlehttp/guzzle 8.0 will reject this option because it conflicts with Guzzle-managed request handling. Use %s instead.', $wrapper, $option, $conflictingOptions[$wrapper][$option] ) ); } } } private static function triggerUnsupportedStreamContextOptionDeprecations(array $streamContext): void { $unsupportedOptions = self::unsupportedStreamContextOptions($streamContext); if ($unsupportedOptions === []) { return; } \trigger_deprecation( 'guzzlehttp/guzzle', '7.12', \sprintf( 'Passing PHP stream context options outside the built-in stream handler allow-list to the "stream_context" request option is deprecated; guzzlehttp/guzzle 8.0 will reject stream context options outside the allow-list. Deprecated option%s: %s.', \count($unsupportedOptions) === 1 ? '' : 's', \implode(', ', $unsupportedOptions) ) ); } /** * @return string[] */ private static function unsupportedStreamContextOptions(array $streamContext): array { $supportedOptions = self::supportedStreamContextOptions(); $conflictingOptions = self::conflictingStreamContextOptions(); $unsupportedOptions = []; foreach ($streamContext as $wrapper => $contextOptions) { if (!\is_string($wrapper) || !isset($supportedOptions[$wrapper])) { if (\is_array($contextOptions)) { foreach ($contextOptions as $option => $_) { if (\is_string($wrapper) && \is_string($option) && isset($conflictingOptions[$wrapper]) && \array_key_exists($option, $conflictingOptions[$wrapper])) { continue; } $unsupportedOptions[] = \sprintf('stream_context.%s.%s', (string) $wrapper, (string) $option); } } else { $unsupportedOptions[] = \sprintf('stream_context.%s', (string) $wrapper); } continue; } if (!\is_array($contextOptions)) { $unsupportedOptions[] = \sprintf('stream_context.%s', $wrapper); continue; } foreach ($contextOptions as $option => $_) { if (\is_string($option) && isset($conflictingOptions[$wrapper]) && \array_key_exists($option, $conflictingOptions[$wrapper])) { continue; } if (!\is_string($option) || !\array_key_exists($option, $supportedOptions[$wrapper])) { $unsupportedOptions[] = \sprintf('stream_context.%s.%s', $wrapper, (string) $option); } } } return $unsupportedOptions; } /** * @return array> */ private static function supportedStreamContextOptions(): array { return [ 'http' => [ 'request_fulluri' => true, ], 'socket' => [ 'bindto' => true, 'tcp_nodelay' => true, ], 'ssl' => [ 'SNI_enabled' => true, 'capture_peer_cert' => true, 'capture_peer_cert_chain' => true, 'ciphers' => true, 'disable_compression' => true, 'no_ticket' => true, 'peer_fingerprint' => true, 'security_level' => true, 'verify_depth' => true, ], ]; } /** * @return array> */ private static function conflictingStreamContextOptions(): array { return [ 'http' => [ 'content' => 'the request body', 'follow_location' => 'the "allow_redirects" request option', 'header' => 'the request headers', 'max_redirects' => 'the "allow_redirects" request option', 'method' => 'the request method', 'protocol_version' => 'the request protocol version', 'proxy' => 'the "proxy" request option', 'timeout' => 'the "timeout" request option', ], 'ssl' => [ 'allow_self_signed' => 'the "verify" request option', 'cafile' => 'the "verify" request option', 'capath' => 'the "verify" request option', 'crypto_method' => 'the "crypto_method" request option', 'local_cert' => 'the "cert" request option', 'local_pk' => 'the "ssl_key" request option', 'max_proto_version' => 'the "crypto_method_max" request option', 'min_proto_version' => 'the "crypto_method" request option', 'passphrase' => 'the "cert" or "ssl_key" request option', 'peer_name' => 'the request URI', 'verify_peer' => 'the "verify" request option', 'verify_peer_name' => 'the "verify" request option', ], ]; } private function assertTransportSharingSupported(): void { if ($this->transportSharingMode === TransportSharing::HANDLER_REQUIRE) { throw new \InvalidArgumentException('The "transport_sharing" option requires transport sharing, but the stream handler does not support it.'); } } private static function isCurlOptionGeneratedByAuth(array $options): bool { if (!isset($options['curl']) || !\is_array($options['curl']) || !isset($options['auth'][2]) || !\is_string($options['auth'][2])) { return false; } if (!\defined('CURLOPT_HTTPAUTH') || !\defined('CURLOPT_USERPWD')) { return false; } $type = Psr7\Utils::asciiToLower($options['auth'][2]); if ($type === 'digest') { $httpAuth = \defined('CURLAUTH_DIGEST') ? \constant('CURLAUTH_DIGEST') : null; } elseif ($type === 'ntlm') { $httpAuth = \defined('CURLAUTH_NTLM') ? \constant('CURLAUTH_NTLM') : null; } else { return false; } return $httpAuth !== null && \count($options['curl']) === 2 && isset($options['curl'][\CURLOPT_HTTPAUTH], $options['curl'][\CURLOPT_USERPWD]) && $options['curl'][\CURLOPT_HTTPAUTH] === $httpAuth; } /** * @param mixed $value as passed via Request transfer options. * * @return array{0: string, 1: string|null} */ private static function normalizeTlsFileOption(string $option, $value): array { $passphrase = null; if (\is_array($value)) { if (!isset($value[0]) || !\is_string($value[0])) { throw new \InvalidArgumentException(\sprintf('Invalid %s request option', $option)); } if (isset($value[1])) { if (!\is_string($value[1])) { throw new \InvalidArgumentException(\sprintf('Invalid %s request option', $option)); } $passphrase = $value[1]; } $value = $value[0]; } if (!\is_string($value)) { throw new \InvalidArgumentException(\sprintf('Invalid %s request option', $option)); } return [$value, $passphrase]; } private static function setTlsPassphrase(array &$options, ?string $passphrase, string $option): void { if ($passphrase === null) { return; } if (isset($options['ssl']['passphrase']) && $options['ssl']['passphrase'] !== $passphrase) { throw new \InvalidArgumentException(\sprintf('Cannot use different passphrases for cert and ssl_key with the stream handler; %s conflicts with an existing TLS passphrase.', $option)); } $options['ssl']['passphrase'] = $passphrase; } /** * @param mixed $value as passed via Request transfer options. */ private static function assertStreamTlsType(string $option, $value): void { if (!\is_string($value) || $value === '') { throw new \InvalidArgumentException(\sprintf('%s must be a non-empty string', $option)); } if (Psr7\Utils::asciiToUpper($value) !== 'PEM') { throw new \InvalidArgumentException(\sprintf('The stream handler only supports "PEM" for the %s request option.', $option)); } } /** * @param mixed $value as passed via Request transfer options. */ private function add_proxy(RequestInterface $request, array &$options, $value, array &$params): bool { $uri = null; if (!\is_array($value)) { $uri = $value; } else { $scheme = $request->getUri()->getScheme(); if (isset($value[$scheme])) { if ( !isset($value['no']) || !Utils::isUriInNoProxy($request->getUri(), $value['no']) ) { $uri = $value[$scheme]; } } } if (!$uri) { return false; } $parsed = $this->parse_proxy($uri); // PHP extracts and removes only one Proxy-Authorization line for a // CONNECT tunnel. Serialize exactly one validated first-class value; // more than one could leave a credential in the tunneled origin // request. A first-class value, including an empty one, is // authoritative over Basic credentials embedded in the proxy URI. $managed = $request->getHeader('Proxy-Authorization'); if (\count($managed) > 1) { throw new \InvalidArgumentException('The stream handler supports exactly one Proxy-Authorization request header value when a proxy is selected.'); } if ($managed !== [] && \strpbrk($managed[0], "\r\n") !== false) { throw new \InvalidArgumentException('Proxy-Authorization request header values must not contain a carriage return or line feed.'); } $options['http']['proxy'] = $parsed['proxy']; if (($managed !== [] || $parsed['auth']) && !isset($options['http']['header'])) { $options['http']['header'] = ''; } if ($managed !== []) { $options['http']['header'] .= "\r\nProxy-Authorization: {$managed[0]}"; return true; } elseif ($parsed['auth']) { $options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}"; return true; } return false; } /** * Parses the given proxy URL to make it compatible with the format PHP's stream context expects. */ private function parse_proxy(string $url): array { $parsed = \parse_url($url); // parse_url() misreads scheme-less proxy authorities like // "user:pass@host"; re-parse only those forms as HTTP. $schemeLessAuthority = \strpos($url, '://') === false && \strncmp($url, '//', 2) !== 0; if ($schemeLessAuthority) { if (\is_array($parsed) && !isset($parsed['scheme']) && isset($parsed['host'], $parsed['port'])) { $parsed['scheme'] = 'http'; } elseif ( (!\is_array($parsed) || !isset($parsed['host'])) && (\strpos($url, '@') !== false || \strncmp($url, '[', 1) === 0) ) { $parsed = \parse_url('http://'.$url); } } if (\is_array($parsed) && isset($parsed['scheme']) && Psr7\Utils::caselessEquals($parsed['scheme'], 'http')) { if (isset($parsed['host'], $parsed['port'])) { $user = $parsed['user'] ?? ''; $pass = $parsed['pass'] ?? ''; $auth = ($user !== '' || $pass !== '') ? 'Basic '.\base64_encode("{$user}:{$pass}") : null; return [ 'proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", 'auth' => $auth, ]; } } // Return proxy as-is. return [ 'proxy' => $url, 'auth' => null, ]; } /** * @param mixed $value as passed via Request transfer options. */ private function add_timeout(RequestInterface $request, array &$options, $value, array &$params): void { if ($value > 0) { $options['http']['timeout'] = $value; } } /** * @param mixed $value as passed via Request transfer options. */ private function add_crypto_method(RequestInterface $request, array &$options, $value, array &$params): void { if ( $value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT || (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) ) { $options['http']['crypto_method'] = $value; return; } throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); } /** * @param mixed $value as passed via Request transfer options. */ private function add_crypto_method_max(RequestInterface $request, array &$options, $value, array &$params): void { $options['ssl']['max_proto_version'] = TlsVersion::streamProtocolVersion('crypto_method_max', $value); } private static function assertTlsVersionRangeForOptions(array $options): void { if (!isset($options['crypto_method_max'])) { return; } TlsVersion::assertRange( $options['crypto_method'] ?? null, $options['crypto_method_max'] ); } /** * @param mixed $value as passed via Request transfer options. */ private function add_verify(RequestInterface $request, array &$options, $value, array &$params): void { if ($value === false) { $options['ssl']['verify_peer'] = false; $options['ssl']['verify_peer_name'] = false; return; } if (\is_string($value)) { $options['ssl']['cafile'] = $value; if (!\file_exists($value)) { throw new \RuntimeException("SSL CA bundle not found: $value"); } } elseif ($value !== true) { throw new \InvalidArgumentException('Invalid verify request option'); } $options['ssl']['verify_peer'] = true; $options['ssl']['verify_peer_name'] = true; $options['ssl']['allow_self_signed'] = false; } /** * @param mixed $value as passed via Request transfer options. */ private function add_cert(RequestInterface $request, array &$options, $value, array &$params): void { [$value, $passphrase] = self::normalizeTlsFileOption('cert', $value); if (!\file_exists($value)) { throw new \RuntimeException("SSL certificate not found: {$value}"); } self::setTlsPassphrase($options, $passphrase, 'cert'); $options['ssl']['local_cert'] = $value; } /** * @param mixed $value as passed via Request transfer options. */ private function add_cert_type(RequestInterface $request, array &$options, $value, array &$params): void { self::assertStreamTlsType('cert_type', $value); } /** * @param mixed $value as passed via Request transfer options. */ private function add_ssl_key(RequestInterface $request, array &$options, $value, array &$params): void { [$value, $passphrase] = self::normalizeTlsFileOption('ssl_key', $value); if (!\file_exists($value)) { throw new \RuntimeException("SSL private key not found: {$value}"); } self::setTlsPassphrase($options, $passphrase, 'ssl_key'); $options['ssl']['local_pk'] = $value; } /** * @param mixed $value as passed via Request transfer options. */ private function add_ssl_key_type(RequestInterface $request, array &$options, $value, array &$params): void { self::assertStreamTlsType('ssl_key_type', $value); } /** * @param mixed $value as passed via Request transfer options. */ private function add_progress(RequestInterface $request, array &$options, $value, array &$params): void { if (!\is_callable($value)) { throw new \InvalidArgumentException('progress client option must be callable'); } self::addNotification( $params, static function ($code, $a, $b, $c, $transferred, $total) use ($value) { if ($code == \STREAM_NOTIFY_PROGRESS) { // The upload progress cannot be determined. Use 0 for cURL compatibility: // https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html $value($total, $transferred, 0, 0); } } ); } /** * @param mixed $value as passed via Request transfer options. */ private function add_debug(RequestInterface $request, array &$options, $value, array &$params): void { if ($value === false) { return; } static $map = [ \STREAM_NOTIFY_CONNECT => 'CONNECT', \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', \STREAM_NOTIFY_PROGRESS => 'PROGRESS', \STREAM_NOTIFY_FAILURE => 'FAILURE', \STREAM_NOTIFY_COMPLETED => 'COMPLETED', \STREAM_NOTIFY_RESOLVE => 'RESOLVE', ]; static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max']; $value = Utils::debugResource($value); $ident = $request->getMethod().' '.$request->getUri()->withFragment(''); self::addNotification( $params, static function (int $code, ...$passed) use ($ident, $value, $map, $args): void { \fprintf($value, '<%s> [%s] ', $ident, $map[$code]); foreach (\array_filter($passed) as $i => $v) { \fwrite($value, $args[$i].': "'.$v.'" '); } \fwrite($value, "\n"); } ); } private static function addNotification(array &$params, callable $notify): void { // Wrap the existing function if needed. if (!isset($params['notification'])) { $params['notification'] = $notify; } else { $params['notification'] = self::callArray([ $params['notification'], $notify, ]); } } private static function callArray(array $functions): callable { return static function (...$args) use ($functions) { foreach ($functions as $fn) { $fn(...$args); } }; } } push(Middleware::httpErrors(), 'http_errors'); $stack->push(Middleware::redirect(), 'allow_redirects'); $stack->push(Middleware::cookies(), 'cookies'); $stack->push(Middleware::prepareBody(), 'prepare_body'); return $stack; } /** * @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler. */ public function __construct(?callable $handler = null) { $this->handler = $handler; } /** * Invokes the handler stack as a composed handler * * @return ResponseInterface|PromiseInterface */ public function __invoke(RequestInterface $request, array $options) { $handler = $this->resolve(); return $handler($request, $options); } /** * Dumps a string representation of the stack. * * @return string */ public function __toString() { $depth = 0; $stack = []; if ($this->handler !== null) { $stack[] = '0) Handler: '.$this->debugCallable($this->handler); } $result = ''; foreach (\array_reverse($this->stack) as $tuple) { ++$depth; $str = "{$depth}) Name: '{$tuple[1]}', "; $str .= 'Function: '.$this->debugCallable($tuple[0]); $result = "> {$str}\n{$result}"; $stack[] = $str; } foreach (\array_keys($stack) as $k) { $result .= "< {$stack[$k]}\n"; } return $result; } /** * Set the HTTP handler that actually returns a promise. * * @param callable(RequestInterface, array): PromiseInterface $handler Accepts a request and array of options and * returns a Promise. */ public function setHandler(callable $handler): void { $this->handler = $handler; $this->cached = null; } /** * Returns true if the builder has a handler. */ public function hasHandler(): bool { return $this->handler !== null; } /** * Unshift a middleware to the bottom of the stack. * * @param callable(callable): callable $middleware Middleware function * @param string $name Name to register for this middleware. */ public function unshift(callable $middleware, ?string $name = null): void { \array_unshift($this->stack, [$middleware, $name]); $this->cached = null; } /** * Push a middleware to the top of the stack. * * @param callable(callable): callable $middleware Middleware function * @param string $name Name to register for this middleware. */ public function push(callable $middleware, string $name = ''): void { $this->stack[] = [$middleware, $name]; $this->cached = null; } /** * Add a middleware before another middleware by name. * * @param string $findName Middleware to find * @param callable(callable): callable $middleware Middleware function * @param string $withName Name to register for this middleware. */ public function before(string $findName, callable $middleware, string $withName = ''): void { $this->splice($findName, $withName, $middleware, true); } /** * Add a middleware after another middleware by name. * * @param string $findName Middleware to find * @param callable(callable): callable $middleware Middleware function * @param string $withName Name to register for this middleware. */ public function after(string $findName, callable $middleware, string $withName = ''): void { $this->splice($findName, $withName, $middleware, false); } /** * Remove a middleware by instance or name from the stack. * * @param callable|string $remove Middleware to remove by instance or name. */ public function remove($remove): void { if (!is_string($remove) && !is_callable($remove)) { \trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a callable or string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->cached = null; if (\is_string($remove)) { $count = \count($this->stack); $this->stack = \array_values(\array_filter( $this->stack, static function ($tuple) use ($remove) { return $tuple[1] !== $remove; } )); if ($count !== \count($this->stack) || !\is_callable($remove)) { return; } } $this->stack = \array_values(\array_filter( $this->stack, static function ($tuple) use ($remove) { return $tuple[0] !== $remove; } )); } /** * Compose the middleware and handler into a single callable function. * * @return callable(RequestInterface, array): PromiseInterface */ public function resolve(): callable { if ($this->cached === null) { if (($prev = $this->handler) === null) { throw new \LogicException('No handler has been specified'); } foreach (\array_reverse($this->stack) as $fn) { /** @var callable(RequestInterface, array): PromiseInterface $prev */ $prev = $fn[0]($prev); } $this->cached = $prev; } return $this->cached; } private function findByName(string $name): int { foreach ($this->stack as $k => $v) { if ($v[1] === $name) { return $k; } } throw new \InvalidArgumentException("Middleware not found: $name"); } /** * Splices a function into the middleware list at a specific position. */ private function splice(string $findName, string $withName, callable $middleware, bool $before): void { $this->cached = null; $idx = $this->findByName($findName); $tuple = [$middleware, $withName]; if ($before) { if ($idx === 0) { \array_unshift($this->stack, $tuple); } else { $replacement = [$tuple, $this->stack[$idx]]; \array_splice($this->stack, $idx, 1, $replacement); } } elseif ($idx === \count($this->stack) - 1) { $this->stack[] = $tuple; } else { $replacement = [$this->stack[$idx], $tuple]; \array_splice($this->stack, $idx, 1, $replacement); } } /** * Provides a debug string for a given callable. * * @param callable|string $fn Function to write as a string. */ private function debugCallable($fn): string { if (\is_string($fn)) { return "callable({$fn})"; } if (\is_array($fn)) { return \is_string($fn[0]) ? "callable({$fn[0]}::{$fn[1]})" : "callable(['".\get_class($fn[0])."', '{$fn[1]}'])"; } /** @var object $fn */ return 'callable('.\spl_object_hash($fn).')'; } } >>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}"; public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}'; /** * @var string Template used to format log messages */ private $template; /** * @param string $template Log message template */ public function __construct(?string $template = self::CLF) { $this->template = $template ?: self::CLF; } /** * Returns a formatted message string. * * @param RequestInterface $request Request that was sent * @param ResponseInterface|null $response Response that was received * @param \Throwable|null $error Exception that was received */ public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string { $cache = []; $result = \preg_replace_callback( '/{\s*([A-Za-z_\-\.0-9]+)\s*}/', function (array $matches) use ($request, $response, $error, &$cache) { if (isset($cache[$matches[1]])) { return $cache[$matches[1]]; } $result = ''; switch ($matches[1]) { case 'request': $result = Psr7\Message::toString($request); break; case 'response': $result = $response ? Psr7\Message::toString($response) : ''; break; case 'req_headers': $result = \trim($request->getMethod() .' '.$request->getRequestTarget(), " \n\r\t\0\x0B") .' HTTP/'.$request->getProtocolVersion()."\r\n" .$this->headers($request); break; case 'res_headers': $result = $response ? \sprintf( 'HTTP/%s %d %s', $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase() )."\r\n".$this->headers($response) : 'NULL'; break; case 'req_body': $result = $request->getBody()->__toString(); break; case 'res_body': if (!$response instanceof ResponseInterface) { $result = 'NULL'; break; } $body = $response->getBody(); if (!$body->isSeekable()) { $result = 'RESPONSE_NOT_LOGGEABLE'; break; } $result = $response->getBody()->__toString(); break; case 'ts': case 'date_iso_8601': $result = \gmdate('c'); break; case 'date_common_log': $result = \date('d/M/Y:H:i:s O'); break; case 'method': $result = $request->getMethod(); break; case 'version': $result = $request->getProtocolVersion(); break; case 'uri': case 'url': $result = $request->getUri()->__toString(); break; case 'target': $result = $request->getRequestTarget(); break; case 'req_version': $result = $request->getProtocolVersion(); break; case 'res_version': $result = $response ? $response->getProtocolVersion() : 'NULL'; break; case 'host': $result = $request->getHeaderLine('Host'); break; case 'hostname': $result = \gethostname(); break; case 'code': $result = $response ? $response->getStatusCode() : 'NULL'; break; case 'phrase': $result = $response ? $response->getReasonPhrase() : 'NULL'; break; case 'error': $result = $error ? $error->getMessage() : 'NULL'; break; default: // handle prefixed dynamic headers if (\strpos($matches[1], 'req_header_') === 0) { $result = $request->getHeaderLine(\substr($matches[1], 11)); } elseif (\strpos($matches[1], 'res_header_') === 0) { $result = $response ? $response->getHeaderLine(\substr($matches[1], 11)) : 'NULL'; } } $cache[$matches[1]] = $result; return $result; }, $this->template ); if ($result === null) { throw new \RuntimeException('Unable to format message: '.\preg_last_error_msg()); } return $result; } /** * Get headers from message as string */ private function headers(MessageInterface $message): string { $result = ''; foreach ($message->getHeaders() as $name => $values) { $result .= $name.': '.\implode(', ', $values)."\r\n"; } return \trim($result, " \n\r\t\0\x0B"); } } withCookieHeader($request); return $handler($request, $options) ->then( static function (ResponseInterface $response) use ($cookieJar, $request): ResponseInterface { $cookieJar->extractCookies($request, $response); return $response; } ); }; }; } /** * Middleware that throws exceptions for 4xx or 5xx responses when the * "http_errors" request option is set to true. * * @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages. * * @return callable(callable): callable Returns a function that accepts the next handler. */ public static function httpErrors(?BodySummarizerInterface $bodySummarizer = null): callable { return static function (callable $handler) use ($bodySummarizer): callable { return static function ($request, array $options) use ($handler, $bodySummarizer) { if (empty($options['http_errors'])) { return $handler($request, $options); } return $handler($request, $options)->then( static function (ResponseInterface $response) use ($request, $bodySummarizer) { $code = $response->getStatusCode(); if ($code < 400) { return $response; } throw RequestException::create($request, $response, null, [], $bodySummarizer); } ); }; }; } /** * Middleware that pushes history data to an ArrayAccess container. * * @param array|\ArrayAccess $container Container to hold the history (by reference). * * @return callable(callable): callable Returns a function that accepts the next handler. * * @throws \InvalidArgumentException if container is not an array or ArrayAccess. */ public static function history(&$container): callable { if (!\is_array($container) && !$container instanceof \ArrayAccess) { throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess'); } return static function (callable $handler) use (&$container): callable { return static function (RequestInterface $request, array $options) use ($handler, &$container) { return $handler($request, $options)->then( static function ($value) use ($request, &$container, $options) { $container[] = [ 'request' => $request, 'response' => $value, 'error' => null, 'options' => $options, ]; return $value; }, static function ($reason) use ($request, &$container, $options) { $container[] = [ 'request' => $request, 'response' => null, 'error' => $reason, 'options' => $options, ]; return P\Create::rejectionFor($reason); } ); }; }; } /** * Middleware that invokes a callback before and after sending a request. * * The provided listener cannot modify or alter the response. It simply * "taps" into the chain to be notified before returning the promise. The * before listener accepts a request and options array, and the after * listener accepts a request, options array, and response promise. * * @param callable $before Function to invoke before forwarding the request. * @param callable $after Function invoked after forwarding. * * @return callable Returns a function that accepts the next handler. */ public static function tap(?callable $before = null, ?callable $after = null): callable { return static function (callable $handler) use ($before, $after): callable { return static function (RequestInterface $request, array $options) use ($handler, $before, $after) { if ($before) { $before($request, $options); } $response = $handler($request, $options); if ($after) { $after($request, $options, $response); } return $response; }; }; } /** * Middleware that handles request redirects. * * @return callable Returns a function that accepts the next handler. */ public static function redirect(): callable { return static function (callable $handler): RedirectMiddleware { return new RedirectMiddleware($handler); }; } /** * Middleware that retries requests based on the boolean result of * invoking the provided "decider" function. * * If no delay function is provided, a simple implementation of exponential * backoff will be utilized. * * @param callable $decider Function that accepts the number of retries, * a request, [response], and [exception] and * returns true if the request is to be retried. * @param callable $delay Function that accepts the number of retries and * returns the number of milliseconds to delay. * * @return callable Returns a function that accepts the next handler. */ public static function retry(callable $decider, ?callable $delay = null): callable { return static function (callable $handler) use ($decider, $delay): RetryMiddleware { return new RetryMiddleware($decider, $handler, $delay); }; } /** * Middleware that logs requests, responses, and errors using a message * formatter. * * @param LoggerInterface $logger Logs messages. * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings. * @param string $logLevel Level at which to log requests. * * @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests. * * @return callable Returns a function that accepts the next handler. */ public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info'): callable { // To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter if (!$formatter instanceof MessageFormatter && !$formatter instanceof MessageFormatterInterface) { throw new \LogicException(sprintf('Argument 2 to %s::log() must be of type %s', self::class, MessageFormatterInterface::class)); } return static function (callable $handler) use ($logger, $formatter, $logLevel): callable { return static function (RequestInterface $request, array $options = []) use ($handler, $logger, $formatter, $logLevel) { return $handler($request, $options)->then( static function ($response) use ($logger, $request, $formatter, $logLevel): ResponseInterface { $message = $formatter->format($request, $response); $logger->log($logLevel, $message); return $response; }, static function ($reason) use ($logger, $request, $formatter): PromiseInterface { $response = $reason instanceof RequestException ? $reason->getResponse() : null; $message = $formatter->format($request, $response, P\Create::exceptionFor($reason)); $logger->error($message); return P\Create::rejectionFor($reason); } ); }; }; } /** * This middleware adds a default content-type if possible, a default * content-length or transfer-encoding header, and the expect header. */ public static function prepareBody(): callable { return static function (callable $handler): PrepareBodyMiddleware { return new PrepareBodyMiddleware($handler); }; } /** * Middleware that applies a map function to the request before passing to * the next handler. * * @param callable $fn Function that accepts a RequestInterface and returns * a RequestInterface. */ public static function mapRequest(callable $fn): callable { return static function (callable $handler) use ($fn): callable { return static function (RequestInterface $request, array $options) use ($handler, $fn) { return $handler($fn($request), $options); }; }; } /** * Middleware that applies a map function to the resolved promise's * response. * * @param callable $fn Function that accepts a ResponseInterface and * returns a ResponseInterface. */ public static function mapResponse(callable $fn): callable { return static function (callable $handler) use ($fn): callable { return static function (RequestInterface $request, array $options) use ($handler, $fn) { return $handler($request, $options)->then($fn); }; }; } } $rfn) { if ($rfn instanceof RequestInterface) { yield $key => $client->sendAsync($rfn, $opts); } elseif (\is_callable($rfn)) { yield $key => $rfn($opts); } else { throw new \InvalidArgumentException('Each value yielded by the iterator must be a Psr\Http\Message\RequestInterface or a callable that returns a promise that fulfills with a Psr\Http\Message\ResponseInterface object.'); } } }; $this->each = new EachPromise($requests(), $config); } /** * Get promise */ public function promise(): PromiseInterface { return $this->each->promise(); } /** * Sends multiple requests concurrently and returns an array of responses * and exceptions that uses the same ordering as the provided requests. * * IMPORTANT: This method keeps every request and response in memory, and * as such, is NOT recommended when sending a large number or an * indeterminate number of requests concurrently. * * @param ClientInterface $client Client used to send the requests * @param array|\Iterator $requests Requests to send concurrently. * @param array $options Passes through the options available in * {@see Pool::__construct} * * @return array Returns an array containing the response or an exception * in the same order that the requests were sent. * * @throws \InvalidArgumentException if the event format is incorrect. */ public static function batch(ClientInterface $client, $requests, array $options = []): array { $res = []; self::cmpCallback($options, 'fulfilled', $res); self::cmpCallback($options, 'rejected', $res); $pool = new static($client, $requests, $options); $pool->promise()->wait(); \ksort($res); return $res; } /** * Execute callback(s) */ private static function cmpCallback(array &$options, string $name, array &$results): void { if (!isset($options[$name])) { $options[$name] = static function ($v, $k) use (&$results) { $results[$k] = $v; }; } else { $currentFn = $options[$name]; $options[$name] = static function ($v, $k) use (&$results, $currentFn) { $currentFn($v, $k); $results[$k] = $v; }; } } } nextHandler = $nextHandler; } public function __invoke(RequestInterface $request, array $options): PromiseInterface { $fn = $this->nextHandler; // Don't do anything if the request has no body. if ($request->getBody()->getSize() === 0) { return $fn($request, $options); } $modify = []; // Add a default content-type if possible. if (!$request->hasHeader('Content-Type')) { if ($uri = $request->getBody()->getMetadata('uri')) { if (is_string($uri) && $type = Psr7\MimeType::fromFilename($uri)) { $modify['set_headers']['Content-Type'] = $type; } } } // Add a default content-length or transfer-encoding header. if (!$request->hasHeader('Content-Length') && !$request->hasHeader('Transfer-Encoding') ) { $size = $request->getBody()->getSize(); if ($size !== null) { $modify['set_headers']['Content-Length'] = (string) $size; } else { $modify['set_headers']['Transfer-Encoding'] = 'chunked'; } } // Add the expect header if needed. $this->addExpectHeader($request, $options, $modify); return $fn(Psr7\Utils::modifyRequest($request, $modify), $options); } /** * Add expect header */ private function addExpectHeader(RequestInterface $request, array $options, array &$modify): void { // Determine if the Expect header should be used if ($request->hasHeader('Expect')) { return; } $expect = $options['expect'] ?? null; // Return if disabled or using HTTP/1.0 if ($expect === false || $request->getProtocolVersion() === '1.0') { return; } // The expect header is unconditionally enabled if ($expect === true) { $modify['set_headers']['Expect'] = '100-Continue'; return; } // By default, send the expect header when the payload is > 1mb if ($expect === null) { $expect = 1048576; } // Always add if the body cannot be rewound, the size cannot be // determined, or the size is greater than the cutoff threshold $body = $request->getBody(); $size = $body->getSize(); if ($size === null || $size >= (int) $expect || !$body->isSeekable()) { $modify['set_headers']['Expect'] = '100-Continue'; } } } 5, 'protocols' => ['http', 'https'], 'strict' => false, 'referer' => false, 'track_redirects' => false, ]; /** * @var callable(RequestInterface, array): PromiseInterface */ private $nextHandler; /** * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. */ public function __construct(callable $nextHandler) { $this->nextHandler = $nextHandler; } public function __invoke(RequestInterface $request, array $options): PromiseInterface { $fn = $this->nextHandler; if (empty($options['allow_redirects'])) { return $fn($request, $options); } if ($options['allow_redirects'] === true) { $options['allow_redirects'] = self::$defaultSettings; } elseif (!\is_array($options['allow_redirects'])) { throw new \InvalidArgumentException('allow_redirects must be true, false, or array'); } else { // Merge the default settings with the provided settings $options['allow_redirects'] += self::$defaultSettings; } if (empty($options['allow_redirects']['max'])) { return $fn($request, $options); } return $fn($request, $options) ->then(function (ResponseInterface $response) use ($request, $options) { return $this->checkRedirect($request, $options, $response); }); } /** * @return ResponseInterface|PromiseInterface */ public function checkRedirect(RequestInterface $request, array $options, ResponseInterface $response) { if (\strpos((string) $response->getStatusCode(), '3') !== 0 || !$response->hasHeader('Location') ) { return $response; } $this->guardMax($request, $response, $options); $nextRequest = $this->modifyRequest($request, $options, $response); // If authorization is handled by curl, unset it if URI is cross-origin. if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && defined('\CURLOPT_HTTPAUTH')) { unset( $options['curl'][\CURLOPT_HTTPAUTH], $options['curl'][\CURLOPT_USERPWD] ); } if (isset($options['allow_redirects']['on_redirect'])) { ($options['allow_redirects']['on_redirect'])( $request, $response, $nextRequest->getUri() ); } // The caller's delay applies once, before the initial request, not // before each followed redirect. unset($options['delay']); $promise = $this($nextRequest, $options); // Add headers to be able to track history of redirects. if (!empty($options['allow_redirects']['track_redirects'])) { return $this->withTracking( $promise, (string) $nextRequest->getUri(), $response->getStatusCode() ); } return $promise; } /** * Enable tracking on promise. */ private function withTracking(PromiseInterface $promise, string $uri, int $statusCode): PromiseInterface { return $promise->then( static function (ResponseInterface $response) use ($uri, $statusCode) { // Note that we are pushing to the front of the list as this // would be an earlier response than what is currently present // in the history header. $historyHeader = $response->getHeader(self::HISTORY_HEADER); $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER); \array_unshift($historyHeader, $uri); \array_unshift($statusHeader, (string) $statusCode); return $response->withHeader(self::HISTORY_HEADER, $historyHeader) ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader); } ); } /** * Check for too many redirects. * * @throws TooManyRedirectsException Too many redirects. */ private function guardMax(RequestInterface $request, ResponseInterface $response, array &$options): void { $current = $options['__redirect_count'] ?? 0; $options['__redirect_count'] = $current + 1; $max = $options['allow_redirects']['max']; if ($options['__redirect_count'] > $max) { throw new TooManyRedirectsException("Will not follow more than {$max} redirects", $request, $response); } } public function modifyRequest(RequestInterface $request, array $options, ResponseInterface $response): RequestInterface { // Request modifications to apply. $modify = []; $protocols = $options['allow_redirects']['protocols']; // Use a GET request if this is an entity enclosing request and we are // not forcing RFC compliance, but rather emulating what all browsers // would do. $statusCode = $response->getStatusCode(); if ($statusCode == 303 || ($statusCode <= 302 && !$options['allow_redirects']['strict']) ) { $requestMethod = $request->getMethod(); if ($requestMethod !== 'QUERY' || !\in_array($statusCode, [301, 302], true)) { $modify['method'] = \in_array($requestMethod, ['GET', 'HEAD', 'OPTIONS'], true) ? $requestMethod : 'GET'; $modify['body'] = ''; $modify['remove_headers'] = ['Content-Length', 'Transfer-Encoding']; } } $uri = self::redirectUri($request, $response, $protocols); $idnOptions = Utils::normalizeIdnConversionOption($options['idn_conversion'] ?? null); if ($idnOptions !== null) { $uri = Utils::idnUriConvert($uri, $idnOptions); } $modify['uri'] = $uri; // The body only needs to be rewound when the next request reuses it. if (!isset($modify['body'])) { try { Psr7\Message::rewindBody($request); } catch (\RuntimeException $e) { throw new RequestException( 'Redirect failed because the request body could not be rewound: '.$e->getMessage(), $request, $response, $e ); } } // Add the Referer header if it is told to do so and only // add the header if we are not redirecting from https to http. if ($options['allow_redirects']['referer'] && $modify['uri']->getScheme() === $request->getUri()->getScheme() ) { $uri = $request->getUri()->withUserInfo('')->withFragment(''); $modify['set_headers']['Referer'] = (string) $uri; } else { $modify['remove_headers'][] = 'Referer'; } // Remove Authorization and Cookie headers if URI is cross-origin. if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $modify['uri'])) { $modify['remove_headers'][] = 'Authorization'; $modify['remove_headers'][] = 'Cookie'; } return Psr7\Utils::modifyRequest($request, $modify); } /** * Set the appropriate URL on the request based on the location header. */ private static function redirectUri( RequestInterface $request, ResponseInterface $response, array $protocols ): UriInterface { $location = Psr7\UriResolver::resolve( $request->getUri(), new Psr7\Uri($response->getHeaderLine('Location')) ); // Ensure that the redirect URI is allowed based on the protocols. if (!\in_array($location->getScheme(), $protocols)) { throw new BadResponseException(\sprintf('Redirect URI, %s, does not use one of the allowed redirect protocols: %s', $location, \implode(', ', $protocols)), $request, $response); } return $location; } } , default=['http', 'https']) * Allowed redirect protocols. Redirect matching is case-sensitive; use * "http" and "https". * - on_redirect: (callable) PHP callable that is invoked when a redirect * is encountered. The callable is invoked with the request, the redirect * response that was received, and the effective URI. Any return value * from the on_redirect function is ignored. * - track_redirects: (bool, default=false) Track redirected URI and status * history in response headers. */ public const ALLOW_REDIRECTS = 'allow_redirects'; /** * auth: (array{0: string, 1: string, 2?: string|null}|string|false|null) * Pass an array of HTTP authentication parameters to use with the request. * The array must contain the username in index [0], the password in index * [1], and you can optionally provide a built-in authentication type in * index [2]. Pass false or null to disable authentication for a request. * String values are passed through for custom handlers. */ public const AUTH = 'auth'; /** * body: (resource|string|null|int|float|bool|\Psr\Http\Message\StreamInterface|(callable&object)|\Iterator|\Stringable) * Body to send in the request. Callable arrays are arrays, and arrays are * not valid body values in Guzzle. */ public const BODY = 'body'; /** * cert: (string|array{0: string, 1?: string|null}) Set to a string to * specify the path to a client certificate file. PEM is the default * certificate format. If a password is required, set cert to an array * containing the certificate path in the first array element followed by * the certificate password in the second array element. A null password is * treated the same as omitting it. Use cert_type to specify another * supported certificate format. */ public const CERT = 'cert'; /** * cert_type: (string) Specify the SSL client certificate file type. */ public const CERT_TYPE = 'cert_type'; /** * cookies: (false|GuzzleHttp\Cookie\CookieJarInterface, default=false) * Specifies whether or not cookies are used in a request or what cookie * jar to use or what cookies to send. This option only works if your * handler has the `cookie` middleware. Valid values are `false` and * an instance of {@see Cookie\CookieJarInterface}. */ public const COOKIES = 'cookies'; /** * connect_timeout: (int|float, default=0) Number of seconds to wait while * trying to connect to a server. Use 0 to wait 300 seconds (the default * behavior). */ public const CONNECT_TIMEOUT = 'connect_timeout'; /** * crypto_method: (int) A value describing the minimum TLS protocol * version to use. * * This setting must be set to one of the * ``STREAM_CRYPTO_METHOD_TLS*_CLIENT`` constants. PHP 7.4 or higher is * required in order to use TLS 1.3, and cURL 7.34.0 or higher is required * in order to specify a crypto method, with cURL 7.52.0 or higher being * required to use TLS 1.3. */ public const CRYPTO_METHOD = 'crypto_method'; /** * crypto_method_max: (int) A value describing the maximum TLS protocol * version to use. * * This setting must be set to one of the * ``STREAM_CRYPTO_METHOD_TLS*_CLIENT`` constants. On the stream handler, * PHP 7.3 or higher is required to set a maximum TLS version, and PHP 7.4 * or higher is required to use TLS 1.3. cURL 7.54.0 or higher is required * in order to specify a maximum TLS version with the cURL handler. */ public const CRYPTO_METHOD_MAX = 'crypto_method_max'; /** * curl: (array) Raw cURL options to apply when using a built-in cURL handler. */ public const CURL = 'curl'; /** * debug: (bool|resource) Set to true or set to a PHP stream returned by * fopen() enable debug output with the HTTP handler used to send a * request. */ public const DEBUG = 'debug'; /** * decode_content: (bool|string, default=true) Specify whether or not * Content-Encoding responses (gzip, deflate, etc.) are automatically * decoded. */ public const DECODE_CONTENT = 'decode_content'; /** * delay: (int|float) The amount of time to delay before sending in * milliseconds. */ public const DELAY = 'delay'; /** * expect: (bool|integer) Controls the behavior of the * "Expect: 100-Continue" header. * * Set to `true` to enable the "Expect: 100-Continue" header for all * requests that sends a body. Set to `false` to disable the * "Expect: 100-Continue" header for all requests. Set to a number so that * the size of the payload must be greater than the number in order to send * the Expect header. Setting to a number will send the Expect header for * all requests in which the size of the payload cannot be determined or * where the body is not rewindable. * * By default, Guzzle will add the "Expect: 100-Continue" header when the * size of the body of a request is greater than 1 MB and a request is * using HTTP/1.1. */ public const EXPECT = 'expect'; /** * form_params: (array) * Associative array of form field names to scalar, null, or nested array * values. Sets the Content-Type header to application/x-www-form-urlencoded * when no Content-Type header is already present. */ public const FORM_PARAMS = 'form_params'; /** * headers: (array>|null) * Associative array of HTTP headers. Each value MUST be a string or non-empty * array of strings. */ public const HEADERS = 'headers'; /** * http_errors: (bool, default=true) Set to false to disable exceptions * when a non- successful HTTP response is received. By default, * exceptions will be thrown for 4xx and 5xx responses. This option only * works if your handler has the `httpErrors` middleware. */ public const HTTP_ERRORS = 'http_errors'; /** * idn_conversion: (bool|int|null, default=false) A combination of IDNA_* * constants for PHP's idn_to_ascii() function. Set to false or null to * disable IDN support, or to true to use the default configuration * (IDNA_DEFAULT constant). */ public const IDN_CONVERSION = 'idn_conversion'; /** * json: (mixed) Adds JSON data to a request. The provided value is JSON * encoded and a Content-Type header of application/json will be added to * the request if no Content-Type header is already present. */ public const JSON = 'json'; /** * multipart: (array) Array of part arrays, each containing a required * "name" key mapping to the string or integer form field name, a required * "contents" key mapping to any non-array value accepted by PSR-7 * Utils::streamFor() or a nested array of field values, an optional * "headers" array of string custom header values, and an optional * "filename" key mapping to a string to send as the filename in the part. * "headers" and "filename" cannot be used when "contents" is an array. */ public const MULTIPART = 'multipart'; /** * multiplex: (string) Controls how a request sent through a built-in * cURL handler relates to shared, multiplexed connections: how an HTTP/2 * request pursues one, or, with Multiplexing::NONE, whether the transfer * may share its connection at all. When the option is not set, * multiplexing is left to libcurl: nothing waits, and established * multiplex-capable connections are still shared. Use * Multiplexing::EAGER to explicitly never wait for pending connections, * Multiplexing::WAIT to wait on libcurl-eligible pending connections with * CURLOPT_PIPEWAIT, normally to the same origin, * Multiplexing::REQUIRE_EAGER to fail unless a multiplexed protocol is * guaranteed while dialing eagerly, or Multiplexing::REQUIRE_WAIT for the * same guarantee while also waiting on pending connections. The required * modes require a handler that permits actual multiplexing, not merely a * multiplexed protocol, and are rejected on a Multiplexing::NONE handler. * The stream handler ignores EAGER and WAIT, and rejects the required * family; CurlHandler has no multi handle to multiplex over. Explicit * modes reject deprecated raw cURL options they conflict with: the * required family cannot be combined with a raw CURLOPT_HTTP_VERSION, * CURLOPT_URL, or CURLOPT_FOLLOWLOCATION; no explicit mode can be * combined with a raw CURLOPT_PIPEWAIT on the CurlMultiHandler; and * Multiplexing::NONE on a CurlMultiHandler that permits multiplexing * cannot be combined with the raw CURLOPT_HTTP_VERSION, CURLOPT_HTTPAUTH * (including the "auth" request option's "digest" and "ntlm" modes, * which set it), CURLOPT_PROXYAUTH, CURLOPT_FOLLOWLOCATION, * CURLOPT_HTTPHEADER, CURLOPT_ALTSVC, CURLOPT_ALTSVC_CTRL, or * CURLOPT_PROXYTYPE cURL options. The required family also * rejects final CURLOPT_HTTPAUTH masks that permit NTLM, which libcurl * retries over HTTP/1.1. The required family validates its cleartext * proxy rule against the final cURL configuration, after raw options * such as CURLOPT_PROXY and CURLOPT_PRE_PROXY are applied; only the * exact raw CURLOPT_NOPROXY wildcard '*' disables the primary proxy and * pre-proxy there, and raw host-specific patterns are conservatively * treated as leaving them active. These rejections are * configuration-conflict checks, not remote security checks. * * Multiplexing::NONE disables multiplexing for a whole handler when * passed as the "multiplex" client configuration option, which * configures the default handler and also becomes the default request * option, or, when constructing a handler directly, as the * CurlMultiHandler "multiplex" constructor option. A handler * configured with Multiplexing::NONE rejects explicitly requested wait * modes as a configuration conflict when the transfer would actually * wait, and always rejects the required modes, because they require a * handler that permits actual multiplexing, not merely a multiplexed * protocol. As a request option value, Multiplexing::NONE guarantees the * transfer does not share its connection with any concurrent transfer. * Multiplexing::NONE does not force HTTP/1.1: on a Multiplexing::NONE * handler, HTTP/2 still negotiates and each transfer keeps its * connection to itself. * * The request option value is accepted exactly where the guarantee * holds and can be verified: on a CurlMultiHandler configured with * Multiplexing::NONE, for requests whose declared protocol version is * HTTP/1.x, on CurlHandler, and on the stream handler, which never * multiplexes. An HTTP/2 request with a Multiplexing::NONE request * option is rejected on a CurlMultiHandler that permits multiplexing. * On a CurlMultiHandler that permits multiplexing, Multiplexing::NONE * is also rejected with a custom "handle_factory", alongside a raw * CURLMOPT_PIPELINING cURL multi option, and combined with the raw * CURLOPT_HTTP_VERSION, CURLOPT_HTTPAUTH (including the "auth" request * option's "digest" and "ntlm" modes, which set it), CURLOPT_PROXYAUTH, * CURLOPT_FOLLOWLOCATION, CURLOPT_HTTPHEADER, CURLOPT_ALTSVC, * CURLOPT_ALTSVC_CTRL, or CURLOPT_PROXYTYPE cURL options. It is also * rejected when the request carries an Expect: 100-continue header (its * 417 retries select connections outside the safeguards; remove an * explicitly supplied header, or set the "expect" request option to * false to prevent it being added automatically). * * On a client whose multi handler permits multiplexing, the ordinary * non-streaming default stack - both cURL handlers available and no * connection caps forcing multi-only routing - runs synchronous * requests on the CurlHandler path, which satisfies the guarantee for * any protocol version, while asynchronous requests run on the * CurlMultiHandler, so an HTTP/2 request with Multiplexing::NONE * succeeds synchronously and is rejected asynchronously on the same * client. Keep-alive reuse between consecutive transfers is * unaffected, except on libcurl versions below 7.77.0 and from 8.11.0 * through 8.12.1, where an accepted HTTP/1.x request on a multiplexing * CurlMultiHandler forces a fresh connection. Custom handlers receive * the "multiplex" option unchanged: its semantics are handler-defined, * Guzzle does not guarantee it is honored, and a client-level * Multiplexing::NONE with a custom handler flows to it as a default * request option without client-side enforcement. */ public const MULTIPLEX = 'multiplex'; /** * on_headers: (callable) A callable that is invoked when the HTTP headers * of the response have been received but the body has not yet begun to * download. */ public const ON_HEADERS = 'on_headers'; /** * on_stats: (callable) allows you to get access to transfer statistics of * a request and access the lower level transfer details of the handler * associated with your client. ``on_stats`` is a callable that is invoked * when a handler has finished sending a request. The callback is invoked * with transfer statistics about the request, the response received, or * the error encountered. Included in the data is the total amount of time * taken to send the request. */ public const ON_STATS = 'on_stats'; /** * on_trailers: (callable) A callable that is invoked by the built-in cURL * handlers once per successful transfer, after the response body has been * received, with an associative array of the parsed HTTP trailers followed * by the response. Trailer field names are lowercased and grouped * case-insensitively; values keep their wire order. Malformed trailer * field lines are discarded before parsing. Trailer fields are reported * separately from response headers and are never merged into the response. */ public const ON_TRAILERS = 'on_trailers'; /** * progress: (callable) Defines a function to invoke when transfer * progress is made. The function accepts the following positional * arguments: the total number of bytes expected to be downloaded, the * number of bytes downloaded so far, the number of bytes expected to be * uploaded, the number of bytes uploaded so far. */ public const PROGRESS = 'progress'; /** * protocols: (non-empty-array, default=['http', 'https']) * Allowed URI schemes. Built-in handlers accept only the case-sensitive * values "http" and "https". */ public const PROTOCOLS = 'protocols'; /** * proxy: (string|array) Pass a string to specify an HTTP proxy, or an * array to specify different proxies for different protocols (where the * key is the protocol and the value is a proxy string or null). Provide a * "no" key as a comma-delimited string, array of strings, or null to * specify hosts or host-and-port pairs that should not be proxied. */ public const PROXY = 'proxy'; /** * query: (array|string) Associative array of query string * values to add to the request. This option uses PHP's http_build_query() * to create the string representation. Pass a string value if you need * more control than what this method provides */ public const QUERY = 'query'; /** * sink: (resource|string|\Psr\Http\Message\StreamInterface) Where the data * of the response is written to. Defaults to a PHP temp stream. Providing * a string will write data to a file by the given name. */ public const SINK = 'sink'; /** * synchronous: (bool) Set to true to inform HTTP handlers that you intend * on waiting on the response. This can be useful for optimizations. Note * that a promise is still returned if you are using one of the async * client methods. */ public const SYNCHRONOUS = 'synchronous'; /** * ssl_key: (array{0: string, 1?: string|null}|string) Specify the path to * a private SSL key file. PEM is the default private key format. If a * password is required, set ssl_key to an array containing the key path in * the first array element followed by the key password in the second * element. A null password is treated the same as omitting it. Use * ssl_key_type to specify another supported key format. */ public const SSL_KEY = 'ssl_key'; /** * ssl_key_type: (string) Specify the SSL private key file type. */ public const SSL_KEY_TYPE = 'ssl_key_type'; /** * stream: (bool) Set to true to attempt to stream a response rather than * download it all up-front. */ public const STREAM = 'stream'; /** * stream_context: (array) PHP stream context options to merge into the * context used by the built-in stream handler. */ public const STREAM_CONTEXT = 'stream_context'; /** * verify: (bool|string, default=true) Describes the SSL certificate * verification behavior of a request. Set to true to enable SSL * certificate verification using the system CA bundle when available * (the default). Set to false to disable certificate verification (this * is insecure!). Set to a string to provide the path to a CA bundle on * disk to enable verification using a custom certificate. */ public const VERIFY = 'verify'; /** * timeout: (int|float, default=0) Number describing the timeout of the * request in seconds. Use 0 to wait indefinitely (the default behavior). */ public const TIMEOUT = 'timeout'; /** * read_timeout: (int|float, default=default_socket_timeout ini setting) * Number describing the body read timeout, for stream requests. */ public const READ_TIMEOUT = 'read_timeout'; /** * retries: (int) Current retry count used by the retry middleware. */ public const RETRIES = 'retries'; /** * version: (string|int|float) Specifies the HTTP protocol version to attempt * to use. */ public const VERSION = 'version'; /** * force_ip_resolve: (string) Set to "v4" to force IPv4 resolution or "v6" * for IPv6 resolution when supported by the handler. */ public const FORCE_IP_RESOLVE = 'force_ip_resolve'; } decider = $decider; $this->nextHandler = $nextHandler; $this->delay = $delay ?: static function (int $retries): int { return (int) 2 ** ($retries - 1) * 1000; }; } /** * Default exponential backoff delay function. * * @return int milliseconds. * * @deprecated since 7.11, will be removed in 8.0. */ public static function exponentialDelay(int $retries): int { \trigger_deprecation('guzzlehttp/guzzle', '7.11', '%s::%s() is deprecated and will be removed in 8.0.', __CLASS__, __FUNCTION__); return (int) 2 ** ($retries - 1) * 1000; } public function __invoke(RequestInterface $request, array $options): PromiseInterface { if (!isset($options['retries'])) { $options['retries'] = 0; } $fn = $this->nextHandler; return $fn($request, $options) ->then( $this->onFulfilled($request, $options), $this->onRejected($request, $options) ); } /** * Execute fulfilled closure */ private function onFulfilled(RequestInterface $request, array $options): callable { return function ($value) use ($request, $options) { if (!($this->decider)( $options['retries'], $request, $value, null )) { return $value; } return $this->doRetry($request, $options, $value); }; } /** * Execute rejected closure */ private function onRejected(RequestInterface $req, array $options): callable { return function ($reason) use ($req, $options) { if (!($this->decider)( $options['retries'], $req, null, $reason )) { return P\Create::rejectionFor($reason); } return $this->doRetry($req, $options); }; } private function doRetry(RequestInterface $request, array $options, ?ResponseInterface $response = null): PromiseInterface { $options['delay'] = ($this->delay)(++$options['retries'], $response, $request); return $this($request, $options); } } request = $request; $this->response = $response; $this->transferTime = $transferTime; $this->handlerErrorData = $handlerErrorData; $this->handlerStats = $handlerStats; } public function getRequest(): RequestInterface { return $this->request; } /** * Returns the response that was received (if any). */ public function getResponse(): ?ResponseInterface { return $this->response; } /** * Returns true if a response was received. */ public function hasResponse(): bool { return $this->response !== null; } /** * Gets handler specific error data. * * This might be an exception, a integer representing an error code, or * anything else. Relying on this value assumes that you know what handler * you are using. * * @return mixed */ public function getHandlerErrorData() { return $this->handlerErrorData; } /** * Get the effective URI the request was sent to. */ public function getEffectiveUri(): UriInterface { return $this->request->getUri(); } /** * Get the estimated time the request was being transferred by the handler. * * @return float|null Time in seconds. */ public function getTransferTime(): ?float { return $this->transferTime; } /** * Gets an array of all of the handler specific transfer data. */ public function getHandlerStats(): array { return $this->handlerStats; } /** * Get a specific handler statistic from the handler by name. * * @param string $stat Handler specific transfer stat to retrieve. * * @return mixed|null */ public function getHandlerStat(string $stat) { return $this->handlerStats[$stat] ?? null; } } */ private static function createCurlHandlerOptions(string $sharingMode): array { if ($sharingMode === TransportSharing::NONE) { return []; } $shareState = CurlShareHandleState::fromOption($sharingMode); return $shareState === null ? [] : ['transport_sharing' => $shareState]; } /** * @param array{max_host_connections?: mixed, max_total_connections?: mixed} $handlerOptions * * @return array{max_host_connections?: int, max_total_connections?: int} */ private static function connectionCapOptions(array $handlerOptions): array { $options = []; foreach (['max_host_connections', 'max_total_connections'] as $capOption) { $value = $handlerOptions[$capOption] ?? null; if ($value === null) { continue; } if (!\is_int($value) || $value < 1) { throw new InvalidArgumentException(\sprintf('%s must be a positive integer.', $capOption)); } $options[$capOption] = $value; } return $options; } /** * @param (callable(RequestInterface, array): Promise\PromiseInterface)|null $handler * @param array{max_host_connections?: int, max_total_connections?: int} $connectionCapOptions * * @return callable(RequestInterface, array): Promise\PromiseInterface */ private static function addStreamHandler(?callable $handler, string $sharingMode, bool $sharingRequired, array $connectionCapOptions): callable { $streamHandler = new StreamHandler(['transport_sharing' => $sharingMode] + $connectionCapOptions); if ($handler === null) { return $streamHandler; } if (!$sharingRequired) { $handler = Proxy::wrapTlsFallback($handler, $streamHandler); } return Proxy::wrapStreaming($handler, $streamHandler); } /** * Get the default User-Agent string to use with Guzzle. */ public static function defaultUserAgent(): string { return sprintf('GuzzleHttp/%d', ClientInterface::MAJOR_VERSION); } /** * Returns the default cacert bundle for the current system. * * First, the openssl.cafile and curl.cainfo php.ini settings are checked. * If those settings are not configured, then the common locations for * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X * and Windows are checked. If any of these file locations are found on * disk, they will be utilized. * * Note: the result of this function is cached for subsequent calls. * * @throws \RuntimeException if no bundle can be found. * * @deprecated Utils::defaultCaBundle will be removed in guzzlehttp/guzzle:8.0. This method is not needed in PHP 5.6+. */ public static function defaultCaBundle(): string { \trigger_deprecation('guzzlehttp/guzzle', '7.1', '%s() is deprecated and will be removed in 8.0. This method is not needed in PHP 5.6+.', __METHOD__); static $cached = null; static $cafiles = [ // Red Hat, CentOS, Fedora (provided by the ca-certificates package) '/etc/pki/tls/certs/ca-bundle.crt', // Ubuntu, Debian (provided by the ca-certificates package) '/etc/ssl/certs/ca-certificates.crt', // FreeBSD (provided by the ca_root_nss package) '/usr/local/share/certs/ca-root-nss.crt', // SLES 12 (provided by the ca-certificates package) '/var/lib/ca-certificates/ca-bundle.pem', // OS X provided by homebrew (using the default path) '/usr/local/etc/openssl/cert.pem', // Google app engine '/etc/ca-certificates.crt', // Windows? 'C:\\windows\\system32\\curl-ca-bundle.crt', 'C:\\windows\\curl-ca-bundle.crt', ]; if ($cached) { return $cached; } if ($ca = \ini_get('openssl.cafile')) { return $cached = $ca; } if ($ca = \ini_get('curl.cainfo')) { return $cached = $ca; } foreach ($cafiles as $filename) { if (\file_exists($filename)) { return $cached = $filename; } } throw new \RuntimeException( <<< EOT No system CA bundle could be found in any of the the common system locations. PHP versions earlier than 5.6 are not properly configured to use the system's CA bundle by default. In order to verify peer certificates, you will need to supply the path on disk to a certificate bundle to the 'verify' request option: https://github.com/guzzle/guzzle/blob/7.15/docs/request-options.md#verify. If you do not need a specific certificate bundle, then Mozilla provides a commonly used CA bundle which can be downloaded here (provided by the maintainer of cURL): https://curl.se/ca/cacert.pem. Once you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP ini setting to point to the path to the file, allowing you to omit the 'verify' request option. See https://curl.se/docs/sslcerts.html for more information. EOT ); } /** * Creates an associative array of lowercase header names to the actual * header casing. */ public static function normalizeHeaderKeys(array $headers): array { $result = []; foreach (\array_keys($headers) as $key) { $result[Psr7\Utils::asciiToLower((string) $key)] = $key; } return $result; } /** * @param mixed $protocols * * @return string[] * * @throws InvalidArgumentException */ public static function normalizeProtocols($protocols): array { if (!\is_array($protocols) || $protocols === []) { throw new InvalidArgumentException('protocols must be a non-empty array of "http" and/or "https"'); } $normalized = []; foreach ($protocols as $protocol) { if (!\is_string($protocol)) { throw new InvalidArgumentException('protocols must contain only strings'); } if ($protocol !== 'http' && $protocol !== 'https') { throw new InvalidArgumentException('protocols may only contain "http" and "https"'); } $normalized[$protocol] = true; } return \array_keys($normalized); } /** * Returns true if the provided host matches any of the no proxy areas. * * This method will strip a port from the host if it is present. Domain * patterns are matched case-insensitively. Exact IP literal patterns are * matched by their normalized binary address. * * Areas are matched in the following cases: * 1. "*" (without quotes) always matches any hosts. * 2. An exact domain or IP literal match. * 3. A bare domain matches itself and its subdomains. e.g. 'mit.edu' will * match 'mit.edu' and 'foo.mit.edu'. * 4. The area starts with "." and the area is the last part of the host. e.g. * '.mit.edu' will match any host that ends with '.mit.edu'. * 5. IP CIDR entries match IP literal hosts. e.g. '192.168.0.0/16' will * match '192.168.1.10' and 'fd00::/8' will match '[fd00::1]'. * * @param string $host Host to check against the patterns. * @param string[] $noProxyArray An array of host or CIDR patterns. * * @throws InvalidArgumentException */ public static function isHostInNoProxy(string $host, array $noProxyArray): bool { if (\strlen($host) === 0) { throw new InvalidArgumentException('Empty host provided'); } $target = self::parseNoProxyHostString($host); if ($target === null) { return false; } return self::matchesNoProxyList($target, $noProxyArray); } /** * Returns true if the provided URI matches any of the no proxy areas. * * Matching follows the same rules as isHostInNoProxy(), with the * addition that areas may carry a port (e.g. "example.com:8080" or * "[::1]:8080") which is compared against the URI port (or the scheme * default port when the URI has none). * * @param mixed $noProxy No-proxy host, host-and-port, or CIDR patterns. * * @internal */ public static function isUriInNoProxy(UriInterface $uri, $noProxy): bool { if (\is_string($noProxy)) { $noProxy = \explode(',', $noProxy); } if (!\is_array($noProxy)) { return false; } $target = self::parseNoProxyTarget($uri); if ($target === null) { return false; } return self::matchesNoProxyList($target, $noProxy); } /** * @param array{type: string, value: string, port: int|null, matchesRoot: bool} $target * @param array $noProxy */ private static function matchesNoProxyList(array $target, array $noProxy): bool { foreach ($noProxy as $area) { if (!\is_string($area)) { continue; } $area = \trim($area, " \n\r\t\0\x0B"); // Always match on wildcards. if ($area === '*') { return true; } $rule = self::parseNoProxyRule($area); if ($rule !== null && self::noProxyRuleMatches($target, $rule)) { return true; } } return false; } /** * @return array{type: string, value: string, port: int|null, matchesRoot: bool}|null */ private static function parseNoProxyTarget(UriInterface $uri): ?array { $host = $uri->getHost(); if ($host === '') { return null; } return self::parseNoProxyHost($host, $uri->getPort() ?? self::getDefaultPort($uri->getScheme()), true); } /** * @return array{type: string, value: string, port: int|null, matchesRoot: bool}|null */ private static function parseNoProxyHostString(string $host): ?array { $hostAndPort = self::splitNoProxyHostAndPort($host); if ($hostAndPort === null) { return null; } [$host] = $hostAndPort; return self::parseNoProxyHost($host, null, true); } /** * @return array{type: string, value: string, port: int|null, matchesRoot: bool}|array{type: string, value: string, prefix: int}|null */ private static function parseNoProxyRule(string $area): ?array { $area = \trim($area, " \n\r\t\0\x0B"); if ($area === '' || $area === '*') { return null; } if (\strpos($area, '/') !== false) { return self::parseNoProxyCidrRule($area); } $matchesRoot = true; if ($area[0] === '.') { $matchesRoot = false; $area = \substr($area, 1); } $hostAndPort = self::splitNoProxyHostAndPort($area); if ($hostAndPort === null) { return null; } [$host, $port] = $hostAndPort; if ($host === '*') { if (!$matchesRoot) { return null; } return [ 'type' => 'wildcard', 'value' => '*', 'port' => $port, 'matchesRoot' => true, ]; } $rule = self::parseNoProxyHost($host, $port, $matchesRoot); if ($rule !== null && !$matchesRoot && $rule['type'] === 'ip') { return null; } return $rule; } /** * @return array{type: string, value: string, port: int|null, matchesRoot: bool}|null */ private static function parseNoProxyHost(string $host, ?int $port, bool $matchesRoot): ?array { if ($host !== '' && $host[0] === '[') { if (\substr($host, -1) !== ']') { return null; } $address = \substr($host, 1, -1); if (!\filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { return null; } $host = $address; } $packedIp = self::packIpAddress($host); if ($packedIp !== false) { return [ 'type' => 'ip', 'value' => $packedIp, 'port' => $port, 'matchesRoot' => $matchesRoot, ]; } if ($host === '' || \strpos($host, ':') !== false) { return null; } // Normalize a single DNS root dot for no-proxy domain matching. if (\substr($host, -1) === '.') { $host = \substr($host, 0, -1); if ($host === '') { return null; } } return [ 'type' => 'domain', 'value' => Psr7\Utils::asciiToLower($host), 'port' => $port, 'matchesRoot' => $matchesRoot, ]; } /** * @return array{0: string, 1: int|null}|null */ private static function splitNoProxyHostAndPort(string $area): ?array { if ($area !== '' && $area[0] === '[') { $closingBracket = \strpos($area, ']'); if ($closingBracket === false) { return null; } $host = \substr($area, 0, $closingBracket + 1); $tail = \substr($area, $closingBracket + 1); if ($tail === '') { return [$host, null]; } if ($tail[0] !== ':') { return null; } $port = self::parseNoProxyPort(\substr($tail, 1)); return $port === null ? null : [$host, $port]; } if (self::packIpAddress($area) !== false) { return [$area, null]; } $colon = \strrpos($area, ':'); if ($colon === false) { return [$area, null]; } $port = self::parseNoProxyPort(\substr($area, $colon + 1)); if ($port === null) { return null; } return [\substr($area, 0, $colon), $port]; } private static function parseNoProxyPort(string $port): ?int { return self::parseBoundedUnsignedInteger($port, 65535); } /** * @return array{type: string, value: string, prefix: int}|null */ private static function parseNoProxyCidrRule(string $area): ?array { $slash = \strpos($area, '/'); if ($slash === false) { return null; } $prefix = \substr($area, $slash + 1); $network = \substr($area, 0, $slash); if ($network !== '' && $network[0] === '[' && \substr($network, -1) === ']') { $network = \substr($network, 1, -1); } $network = self::packIpAddress($network); if ($network === false) { return null; } $prefix = self::parseBoundedUnsignedInteger($prefix, \strlen($network) * 8); if ($prefix === null) { return null; } return [ 'type' => 'cidr', 'value' => $network, 'prefix' => $prefix, ]; } private static function parseBoundedUnsignedInteger(string $value, int $max): ?int { if ($value === '' || !\ctype_digit($value)) { return null; } $normalized = \ltrim($value, '0'); $normalized = $normalized === '' ? '0' : $normalized; $limit = (string) $max; if (\strlen($normalized) > \strlen($limit) || (\strlen($normalized) === \strlen($limit) && \strcmp($normalized, $limit) > 0)) { return null; } return (int) $normalized; } /** * @param array{type: string, value: string, port: int|null, matchesRoot: bool} $target * @param array{type: string, value: string, port?: int|null, matchesRoot?: bool, prefix?: int|null} $rule */ private static function noProxyRuleMatches(array $target, array $rule): bool { if ($rule['type'] === 'wildcard') { return ($rule['port'] ?? null) === null || $rule['port'] === $target['port']; } if ($rule['type'] === 'cidr') { if ($target['type'] !== 'ip' || !isset($rule['prefix'])) { return false; } if (\strlen($target['value']) !== \strlen($rule['value'])) { return false; } return self::ipMatchesPrefix($target['value'], $rule['value'], $rule['prefix']); } if (($rule['port'] ?? null) !== null && $rule['port'] !== $target['port']) { return false; } if ($rule['type'] !== $target['type']) { return false; } if ($rule['type'] === 'ip') { return $rule['value'] === $target['value']; } if (($rule['matchesRoot'] ?? false) && $target['value'] === $rule['value']) { return true; } $suffix = '.'.$rule['value']; return \substr($target['value'], -\strlen($suffix)) === $suffix; } /** * @return string|false */ private static function packIpAddress(string $ip) { if (!\filter_var($ip, \FILTER_VALIDATE_IP)) { return false; } return \inet_pton($ip); } private static function ipMatchesPrefix(string $address, string $network, int $prefix): bool { $fullBytes = \intdiv($prefix, 8); $remainingBits = $prefix % 8; if ($fullBytes > 0 && \substr($address, 0, $fullBytes) !== \substr($network, 0, $fullBytes)) { return false; } if ($remainingBits === 0) { return true; } $mask = (0xFF << (8 - $remainingBits)) & 0xFF; return (\ord($address[$fullBytes]) & $mask) === (\ord($network[$fullBytes]) & $mask); } private static function getDefaultPort(string $scheme): ?int { if ($scheme === 'http') { return 80; } if ($scheme === 'https') { return 443; } return null; } /** * Wrapper for json_decode that throws when an error occurs. * * @param string $json JSON data to parse * @param bool $assoc When true, returned objects will be converted * into associative arrays. * @param int $depth User specified recursion depth. * @param int $options Bitmask of JSON decode options. * * @return object|array|string|int|float|bool|null * * @throws InvalidArgumentException if the JSON cannot be decoded. * * @see https://www.php.net/manual/en/function.json-decode.php * @deprecated Utils::jsonDecode() will be removed in guzzlehttp/guzzle:8.0. Use PHP's json_decode() instead. */ public static function jsonDecode(string $json, bool $assoc = false, int $depth = 512, int $options = 0) { \trigger_deprecation('guzzlehttp/guzzle', '7.15', '%s() is deprecated and will be removed in 8.0. Use PHP\'s json_decode() instead.', __METHOD__); if ($depth < 1) { throw new InvalidArgumentException('json_decode error: Maximum stack depth exceeded'); } $data = \json_decode($json, $assoc, $depth, $options); if (\JSON_ERROR_NONE !== \json_last_error()) { throw new InvalidArgumentException('json_decode error: '.\json_last_error_msg()); } return $data; } /** * Wrapper for JSON encoding that throws when an error occurs. * * @param mixed $value The value being encoded * @param int $options JSON encode option bitmask * @param int $depth Set the maximum depth. Must be greater than zero. * * @throws InvalidArgumentException if the JSON cannot be encoded. * * @see https://www.php.net/manual/en/function.json-encode.php * @deprecated Utils::jsonEncode() will be removed in guzzlehttp/guzzle:8.0. Use PHP's json_encode() instead. */ public static function jsonEncode($value, int $options = 0, int $depth = 512): string { \trigger_deprecation('guzzlehttp/guzzle', '7.15', '%s() is deprecated and will be removed in 8.0. Use PHP\'s json_encode() instead.', __METHOD__); $json = \json_encode($value, $options, $depth); if (\JSON_ERROR_NONE !== \json_last_error()) { throw new InvalidArgumentException('json_encode error: '.\json_last_error_msg()); } /** @var string */ return $json; } /** * Wrapper for the hrtime() or microtime() functions * (depending on the PHP version, one of the two is used) * * @return float UNIX timestamp * * @internal */ public static function currentTime(): float { return (float) \function_exists('hrtime') ? \hrtime(true) / 1e9 : \microtime(true); } /** * @param mixed $value * * @internal */ public static function normalizeIdnConversionOption($value): ?int { if ($value === null || $value === false) { return null; } if ($value === true) { return \IDNA_DEFAULT; } if (\is_int($value)) { return $value; } if ((\is_string($value) && \is_numeric($value)) || (\is_float($value) && \is_finite($value))) { \trigger_deprecation( 'guzzlehttp/guzzle', '7.11', 'Passing %s as the "idn_conversion" request option is deprecated; guzzlehttp/guzzle 8.0 will reject values that are not true, false, null, or an integer IDNA_* bitmask.', \get_debug_type($value) ); return (int) $value; } throw new InvalidArgumentException('idn_conversion must be true, false, null, or an integer IDNA_* bitmask'); } /** * @throws InvalidArgumentException * * @internal */ public static function idnUriConvert(UriInterface $uri, int $options = 0): UriInterface { if ($uri->getHost()) { $asciiHost = self::idnToAsci($uri->getHost(), $options, $info); if ($asciiHost === false) { $errorBitSet = $info['errors'] ?? 0; $errorConstants = array_filter(array_keys(get_defined_constants()), static function (string $name): bool { return substr($name, 0, 11) === 'IDNA_ERROR_'; }); $errors = []; foreach ($errorConstants as $errorConstant) { if ($errorBitSet & constant($errorConstant)) { $errors[] = $errorConstant; } } $errorMessage = 'IDN conversion failed'; if ($errors) { $errorMessage .= ' (errors: '.implode(', ', $errors).')'; } throw new InvalidArgumentException($errorMessage); } if ($uri->getHost() !== $asciiHost) { // Replace URI only if the ASCII version is different $uri = $uri->withHost($asciiHost); } } return $uri; } /** * @internal */ public static function getenv(string $name): ?string { if (isset($_SERVER[$name])) { return (string) $_SERVER[$name]; } if (\PHP_SAPI === 'cli' && ($value = \getenv($name)) !== false && $value !== null) { return (string) $value; } return null; } /** * @return string|false */ private static function idnToAsci(string $domain, int $options, ?array &$info = []) { if (\function_exists('idn_to_ascii') && \defined('INTL_IDNA_VARIANT_UTS46')) { return \idn_to_ascii($domain, $options, \INTL_IDNA_VARIANT_UTS46, $info); } throw new \Error('ext-idn or symfony/polyfill-intl-idn not loaded or too old'); } } Copyright (c) 2015 Graham Campbell Copyright (c) 2017 Tobias Schultze Copyright (c) 2020 Tobias Nyholm 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. # Guzzle Promises [Promises/A+](https://promisesaplus.com/) implementation that handles promise chaining and resolution iteratively, allowing for "infinite" promise chaining while keeping the stack size constant. Read [this blog post](https://blog.domenic.me/youre-missing-the-point-of-promises/) for a general introduction to promises. - [Features](#features) - [Quick start](#quick-start) - [Synchronous wait](#synchronous-wait) - [Cancellation](#cancellation) - [API](#api) - [Promise](#promise) - [FulfilledPromise](#fulfilledpromise) - [RejectedPromise](#rejectedpromise) - [Promise interop](#promise-interop) - [Implementation notes](#implementation-notes) ## Features - [Promises/A+](https://promisesaplus.com/) implementation. - Promise resolution and chaining is handled iteratively, allowing for "infinite" promise chaining. - Promises have a synchronous `wait` method. - Promises can be cancelled. - Works with any object that has a `then` function. - C# style async/await coroutine promises using `GuzzleHttp\Promise\Coroutine::of()`. ## Installation ```shell composer require guzzlehttp/promises ``` ## Version Guidance | Version | Status | PHP Version | |---------|---------------------|--------------| | 1.x | Security fixes only | >=5.5,<8.3 | | 2.x | Latest | >=7.2.5,<8.6 | ## Quick Start A *promise* represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its `then` method, which registers callbacks to receive either a promise's eventual value or the reason why the promise cannot be fulfilled. ### Callbacks Callbacks are registered with the `then` method by providing an optional `$onFulfilled` followed by an optional `$onRejected` function. ```php use GuzzleHttp\Promise\Promise; $promise = new Promise(); $promise->then( // $onFulfilled function ($value) { echo 'The promise was fulfilled.'; }, // $onRejected function ($reason) { echo 'The promise was rejected.'; } ); ``` *Resolving* a promise means that you either fulfill a promise with a *value* or reject a promise with a *reason*. Resolving a promise triggers callbacks registered with the promise's `then` method. These callbacks are triggered only once and in the order in which they were added. ### Resolving a Promise Promises are fulfilled using the `resolve($value)` method. Resolving a promise with any value other than a `GuzzleHttp\Promise\RejectedPromise` will trigger all of the onFulfilled callbacks (resolving a promise with a rejected promise will reject the promise and trigger the `$onRejected` callbacks). ```php use GuzzleHttp\Promise\Promise; $promise = new Promise(); $promise ->then(function ($value) { // Return a value and don't break the chain return "Hello, " . $value; }) // This then is executed after the first then and receives the value // returned from the first then. ->then(function ($value) { echo $value; }); // Resolving the promise triggers the $onFulfilled callbacks and outputs // "Hello, reader." $promise->resolve('reader.'); ``` ### Promise Forwarding Promises can be chained one after the other. Each then in the chain is a new promise. The return value of a promise is what's forwarded to the next promise in the chain. Returning a promise in a `then` callback will cause the subsequent promises in the chain to only be fulfilled when the returned promise has been fulfilled. The next promise in the chain will be invoked with the resolved value of the promise. ```php use GuzzleHttp\Promise\Promise; $promise = new Promise(); $nextPromise = new Promise(); $promise ->then(function ($value) use ($nextPromise) { echo $value; return $nextPromise; }) ->then(function ($value) { echo $value; }); // Triggers the first callback and outputs "A" $promise->resolve('A'); // Triggers the second callback and outputs "B" $nextPromise->resolve('B'); ``` ### Promise Rejection When a promise is rejected, the `$onRejected` callbacks are invoked with the rejection reason. ```php use GuzzleHttp\Promise\Promise; $promise = new Promise(); $promise->then(null, function ($reason) { echo $reason; }); $promise->reject('Error!'); // Outputs "Error!" ``` ### Rejection Forwarding If an exception is thrown in an `$onRejected` callback, subsequent `$onRejected` callbacks are invoked with the thrown exception as the reason. ```php use GuzzleHttp\Promise\Promise; $promise = new Promise(); $promise->then(null, function ($reason) { throw new Exception($reason); })->then(null, function ($reason) { assert($reason->getMessage() === 'Error!'); }); $promise->reject('Error!'); ``` You can also forward a rejection down the promise chain by returning a `GuzzleHttp\Promise\RejectedPromise` in either an `$onFulfilled` or `$onRejected` callback. ```php use GuzzleHttp\Promise\Promise; use GuzzleHttp\Promise\RejectedPromise; $promise = new Promise(); $promise->then(null, function ($reason) { return new RejectedPromise($reason); })->then(null, function ($reason) { assert($reason === 'Error!'); }); $promise->reject('Error!'); ``` If an exception is not thrown in a `$onRejected` callback and the callback does not return a rejected promise, downstream `$onFulfilled` callbacks are invoked using the value returned from the `$onRejected` callback. ```php use GuzzleHttp\Promise\Promise; $promise = new Promise(); $promise ->then(null, function ($reason) { return "It's ok"; }) ->then(function ($value) { assert($value === "It's ok"); }); $promise->reject('Error!'); ``` ## Synchronous Wait You can synchronously force promises to complete using a promise's `wait` method. When creating a promise, you can provide a wait function that is used to synchronously force a promise to complete. When a wait function is invoked it is expected to deliver a value to the promise or reject the promise. If the wait function does not deliver a value, then an exception is thrown. The wait function provided to a promise constructor is invoked when the `wait` function of the promise is called. ```php $promise = new Promise(function () use (&$promise) { $promise->resolve('foo'); }); // Calling wait will return the value of the promise. echo $promise->wait(); // outputs "foo" ``` If a throwable is encountered while invoking the wait function of a promise, the promise is rejected with the throwable and the throwable is thrown. ```php $promise = new Promise(function () use (&$promise) { throw new Exception('foo'); }); $promise->wait(); // throws the exception. ``` Calling `wait` on a promise that has been fulfilled will not trigger the wait function. It will simply return the previously resolved value. ```php $promise = new Promise(function () { die('this is not called!'); }); $promise->resolve('foo'); echo $promise->wait(); // outputs "foo" ``` Calling `wait` on a promise that has been rejected will throw. If the rejection reason is an instance of `\Throwable` the reason is thrown. Otherwise, a `GuzzleHttp\Promise\RejectionException` is thrown and the reason can be obtained by calling the `getReason` method of the exception. ```php $promise = new Promise(); $promise->reject('foo'); $promise->wait(); ``` > PHP Fatal error: Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo' ### Unwrapping a Promise When synchronously waiting on a promise, you are joining the state of the promise into the current state of execution (i.e., return the value of the promise if it was fulfilled or throw an exception if it was rejected). This is called "unwrapping" the promise. Waiting on a promise will by default unwrap the promise state. You can force a promise to resolve and *not* unwrap the state of the promise by passing `false` to the first argument of the `wait` function: ```php $promise = new Promise(); $promise->reject('foo'); // This will not throw an exception. It simply ensures the promise has // been resolved. $promise->wait(false); ``` When unwrapping a promise, the resolved value of the promise will be waited upon until the unwrapped value is not a promise. This means that if you resolve promise A with a promise B and unwrap promise A, the value returned by the wait function will be the value delivered to promise B. **Note**: when you do not unwrap the promise, no value is returned. ## Cancellation You can cancel a promise that has not yet been fulfilled using the `cancel()` method of a promise. When creating a promise you can provide an optional cancel function that when invoked cancels the action of computing a resolution of the promise. ## API ### Promise When creating a promise object, you can provide an optional `$waitFn` and `$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is expected to resolve the promise. `$cancelFn` is a function with no arguments that is expected to cancel the computation of a promise. It is invoked when the `cancel()` method of a promise is called. ```php use GuzzleHttp\Promise\Promise; $promise = new Promise( function () use (&$promise) { $promise->resolve('waited'); }, function () { // do something that will cancel the promise computation (e.g., close // a socket, cancel a database query, etc...) } ); assert('waited' === $promise->wait()); ``` A promise has the following methods: - `then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface` Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler. If a handler is omitted, the original fulfillment value or rejection reason is forwarded. - `otherwise(callable $onRejected) : PromiseInterface` Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled. - `wait($unwrap = true) : mixed` Synchronously waits on the promise to complete. `$unwrap` controls whether or not the value of the promise is returned for a fulfilled promise or if an exception is thrown if the promise is rejected. This is set to `true` by default. - `cancel()` Attempts to cancel the promise if possible. The promise being cancelled and the parent most ancestor that has not yet been resolved will also be cancelled. Any promises waiting on the cancelled promise to resolve will also be cancelled. - `getState() : string` Returns the state of the promise. One of `pending`, `fulfilled`, or `rejected`. - `resolve($value)` Fulfills the promise with the given `$value`. - `reject($reason)` Rejects the promise with the given `$reason`. ### FulfilledPromise A fulfilled promise can be created to represent a promise that has been fulfilled. ```php use GuzzleHttp\Promise\FulfilledPromise; $promise = new FulfilledPromise('value'); // Fulfilled callbacks are immediately invoked. $promise->then(function ($value) { echo $value; }); ``` ### RejectedPromise A rejected promise can be created to represent a promise that has been rejected. ```php use GuzzleHttp\Promise\RejectedPromise; $promise = new RejectedPromise('Error'); // Rejected callbacks are immediately invoked. $promise->then(null, function ($reason) { echo $reason; }); ``` ## Promise Interoperability This library works with foreign promises that have a `then` method. This means you can use Guzzle promises with [React promises](https://github.com/reactphp/promise) for example. When a foreign promise is returned inside of a then method callback, promise resolution will occur recursively. ```php // Create a React promise $deferred = new React\Promise\Deferred(); $reactPromise = $deferred->promise(); // Create a Guzzle promise that is fulfilled with a React promise. $guzzlePromise = new GuzzleHttp\Promise\Promise(); $guzzlePromise->then(function ($value) use ($reactPromise) { // Do something something with the value... // Return the React promise return $reactPromise; }); ``` Please note that wait and cancel chaining is no longer possible when forwarding a foreign promise. You will need to wrap a third-party promise with a Guzzle promise in order to utilize wait and cancel functions with foreign promises. ### Event Loop Integration In order to keep the stack size constant, Guzzle promises are resolved asynchronously using a task queue. When waiting on promises synchronously, the task queue will be automatically run to ensure that the blocking promise and any forwarded promises are resolved. When using promises asynchronously in an event loop, you will need to run the task queue on each tick of the loop. If you do not run the task queue, then promises will not be resolved. You can run the task queue using the `run()` method of the global task queue instance. ```php // Get the global task queue $queue = GuzzleHttp\Promise\Utils::queue(); $queue->run(); ``` For example, you could use Guzzle promises with React using a short periodic timer. Avoid zero-interval timers because they may keep the loop busy even when there is no promise work to run. ```php $loop = React\EventLoop\Factory::create(); $loop->addPeriodicTimer(0.01, [$queue, 'run']); ``` ## Implementation Notes ### Promise Resolution and Chaining is Handled Iteratively By shuffling pending handlers from one owner to another, promises are resolved iteratively, allowing for "infinite" then chaining. ```php then(function ($v) { // The stack size remains constant (a good thing) echo xdebug_get_stack_depth() . ', '; return $v + 1; }); } $parent->resolve(0); var_dump($p->wait()); // int(1000) ``` When a promise is fulfilled or rejected with a non-promise value, the promise then takes ownership of the handlers of each child promise and delivers values down the chain without using recursion. When a promise is resolved with another promise, the original promise transfers all of its pending handlers to the new promise. When the new promise is eventually resolved, all of the pending handlers are delivered the forwarded value. ### A Promise is the Deferred Some promise libraries implement promises using a deferred object to represent a computation and a promise object to represent the delivery of the result of the computation. This is a nice separation of computation and delivery because consumers of the promise cannot modify the value that will be eventually delivered. One side effect of being able to implement promise resolution and chaining iteratively is that you need to be able for one promise to reach into the state of another promise to shuffle around ownership of handlers. In order to achieve this without making the handlers of a promise publicly mutable, a promise is also the deferred value, allowing promises of the same parent class to reach into and modify the private properties of promises of the same type. While this does allow consumers of the value to modify the resolution or rejection of the deferred, it is a small price to pay for keeping the stack size constant. ```php $promise = new Promise(); $promise->then(function ($value) { echo $value; }); // The promise is the deferred value, so you can deliver a value to it. $promise->resolve('foo'); // prints "foo" ``` ## Upgrading See [UPGRADING.md](UPGRADING.md) for package upgrade notes. ## Security If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/promises/security/policy) for more information. ## License Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. ## For Enterprise Available as part of the Tidelift Subscription The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver 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. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-promises?utm_source=packagist-guzzlehttp-promises&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) Guzzle Promises Upgrade Guide ============================= 1.x to 2.0 ---------- Guzzle Promises 2.0 is a major release that removes deprecated APIs, raises the minimum PHP version, and adds PHP 7 parameter and return types. Applications that only use the object-oriented API should usually need small changes. Applications that call helper functions, implement package interfaces, extend package classes, or pass invalid argument types need closer review. #### PHP Version and Dependencies Guzzle Promises 2.0 requires PHP `^7.2.5 || ^8.0`. Guzzle Promises 1.x supported PHP `>=5.5`. #### PHP 7 Type Hints and Return Types Type hints and return types were added wherever possible. Please make sure: - You pass values of the documented type when calling methods and functions. - Classes that implement `PromiseInterface`, `PromisorInterface`, or `TaskQueueInterface` update method signatures to remain compatible. - Classes that extend Guzzle Promises classes update any overridden method signatures to remain compatible. - Code that expected package-specific exceptions for invalid argument types may now receive PHP `TypeError` exceptions instead. #### Soft-Final Classes All previously non-final non-exception classes are now final or annotated with `@final`. If your code extends one of these classes, replace inheritance with composition or implement the relevant interface directly. #### Removed Function API The static API was introduced in 1.4.0 to mitigate problems with functions conflicting between global and local copies of the package. The function API was removed in 2.0.0, along with the Composer `files` autoload entry that loaded `src/functions_include.php`. Replace namespaced function calls with the corresponding static methods in the `GuzzleHttp\Promise` namespace: ```php // Before: use function GuzzleHttp\Promise\promise_for; $promise = promise_for('value'); // After: use GuzzleHttp\Promise\Create; $promise = Create::promiseFor('value'); ``` | Original Function | Replacement Method | |-------------------|--------------------| | `queue` | `Utils::queue` | | `task` | `Utils::task` | | `promise_for` | `Create::promiseFor` | | `rejection_for` | `Create::rejectionFor` | | `exception_for` | `Create::exceptionFor` | | `iter_for` | `Create::iterFor` | | `inspect` | `Utils::inspect` | | `inspect_all` | `Utils::inspectAll` | | `unwrap` | `Utils::unwrap` | | `all` | `Utils::all` | | `some` | `Utils::some` | | `any` | `Utils::any` | | `settle` | `Utils::settle` | | `each` | `Each::of` | | `each_limit` | `Each::ofLimit` | | `each_limit_all` | `Each::ofLimitAll` | | `!is_fulfilled` | `Is::pending` | | `is_fulfilled` | `Is::fulfilled` | | `is_rejected` | `Is::rejected` | | `is_settled` | `Is::settled` | | `coroutine` | `Coroutine::of` | For the full 2.0 diff, see https://github.com/guzzle/promises/compare/1.5.3...2.0.0. { "name": "guzzlehttp/promises", "description": "Guzzle promises library", "license": "MIT", "keywords": [ "promise" ], "authors": [ { "name": "Graham Campbell", "email": "hello@gjcampbell.co.uk", "homepage": "https://github.com/GrahamCampbell" }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "Tobias Nyholm", "email": "tobias.nyholm@gmail.com", "homepage": "https://github.com/Nyholm" }, { "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" } ], "require": { "php": "^7.2.5 || ^8.0", "symfony/deprecation-contracts": "^2.5 || ^3.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "autoload": { "psr-4": { "GuzzleHttp\\Promise\\": "src/" } }, "autoload-dev": { "psr-4": { "GuzzleHttp\\Promise\\Tests\\": "tests/" } }, "config": { "allow-plugins": { "bamarni/composer-bin-plugin": true }, "preferred-install": "dist", "sort-packages": true }, "extra": { "bamarni-bin": { "bin-links": true, "forward-command": false } } } then(function ($v) { echo $v; }); * * @param callable $generatorFn Generator function to wrap into a promise. * * @return Promise * * @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration */ final class Coroutine implements PromiseInterface { /** * @var PromiseInterface|null */ private $currentPromise; /** * @var Generator */ private $generator; /** * @var Promise */ private $result; public function __construct(callable $generatorFn) { $this->generator = $generatorFn(); $this->result = new Promise(function (): void { while (isset($this->currentPromise)) { $this->currentPromise->wait(); } }); try { $this->nextCoroutine($this->generator->current()); } catch (Throwable $throwable) { $this->result->reject($throwable); } } /** * Create a new coroutine. */ public static function of(callable $generatorFn): self { return new self($generatorFn); } public function then( ?callable $onFulfilled = null, ?callable $onRejected = null ): PromiseInterface { return $this->result->then($onFulfilled, $onRejected); } public function otherwise(callable $onRejected): PromiseInterface { return $this->result->otherwise($onRejected); } public function wait(bool $unwrap = true) { return $this->result->wait($unwrap); } public function getState(): string { return $this->result->getState(); } public function resolve($value): void { $this->result->resolve($value); } public function reject($reason): void { $this->result->reject($reason); } public function cancel(): void { if (isset($this->currentPromise)) { $this->currentPromise->cancel(); } $this->result->cancel(); } private function nextCoroutine($yielded): void { $this->currentPromise = Create::promiseFor($yielded) ->then([$this, '_handleSuccess'], [$this, '_handleFailure']); } /** * @internal */ public function _handleSuccess($value): void { unset($this->currentPromise); try { $next = $this->generator->send($value); if ($this->generator->valid()) { $this->nextCoroutine($next); } else { $this->result->resolve($value); } } catch (Throwable $throwable) { $this->result->reject($throwable); } } /** * @internal */ public function _handleFailure($reason): void { unset($this->currentPromise); try { $nextYield = $this->generator->throw(Create::exceptionFor($reason)); // The throw was caught, so keep iterating on the coroutine $this->nextCoroutine($nextYield); } catch (Throwable $throwable) { $this->result->reject($throwable); } } } then([$promise, 'resolve'], [$promise, 'reject']); return $promise; } return new FulfilledPromise($value); } /** * Creates a rejected promise for a reason if the reason is not a promise. * If the provided reason is a promise, then it is returned as-is. * * @param mixed $reason Promise or reason. */ public static function rejectionFor($reason): PromiseInterface { if ($reason instanceof PromiseInterface) { return $reason; } return new RejectedPromise($reason); } /** * Create an exception for a rejected promise value. * * @param mixed $reason */ public static function exceptionFor($reason): \Throwable { if ($reason instanceof \Throwable) { return $reason; } return new RejectionException($reason); } /** * Returns an iterator for the given value. * * @param mixed $value */ public static function iterFor($value): \Iterator { if ($value instanceof \Iterator) { return $value; } if (is_array($value)) { return new \ArrayIterator($value); } if (!is_iterable($value)) { \trigger_deprecation( 'guzzlehttp/promises', '2.5', 'Passing a non-iterable to %s::%s() is deprecated; guzzlehttp/promises 3.0 will require an iterable.', __CLASS__, __FUNCTION__ ); } return new \ArrayIterator([$value]); } } $onFulfilled, 'rejected' => $onRejected, ]))->promise(); } /** * Like of, but only allows a certain number of outstanding promises at any * given time. * * $concurrency may be an integer or a function that accepts the number of * pending promises and returns a numeric concurrency limit value to allow * for dynamic a concurrency size. * * @param mixed $iterable * @param int|callable $concurrency */ public static function ofLimit( $iterable, $concurrency, ?callable $onFulfilled = null, ?callable $onRejected = null ): PromiseInterface { $iterable = self::prepareIterable($iterable, __FUNCTION__); return (new EachPromise($iterable, [ 'fulfilled' => $onFulfilled, 'rejected' => $onRejected, 'concurrency' => $concurrency, ]))->promise(); } /** * Like limit, but ensures that no promise in the given $iterable argument * is rejected. If any promise is rejected, then the aggregate promise is * rejected with the encountered rejection. * * @param mixed $iterable * @param int|callable $concurrency */ public static function ofLimitAll( $iterable, $concurrency, ?callable $onFulfilled = null ): PromiseInterface { $iterable = self::prepareIterable($iterable, __FUNCTION__); return self::ofLimit( $iterable, $concurrency, $onFulfilled, function ($reason, $idx, PromiseInterface $aggregate): void { $aggregate->reject($reason); } ); } private static function prepareIterable($iterable, string $method): iterable { if (is_iterable($iterable)) { return $iterable; } \trigger_deprecation( 'guzzlehttp/promises', '2.5', 'Passing a non-iterable to %s::%s() is deprecated; guzzlehttp/promises 3.0 will require an iterable.', self::class, $method ); return [$iterable]; } } iterable = Create::iterFor($iterable); if (isset($config['concurrency'])) { $this->concurrency = $config['concurrency']; } if (isset($config['fulfilled'])) { $this->onFulfilled = $config['fulfilled']; } if (isset($config['rejected'])) { $this->onRejected = $config['rejected']; } } /** @psalm-suppress InvalidNullableReturnType */ public function promise(): PromiseInterface { if ($this->aggregate) { return $this->aggregate; } try { $this->createPromise(); /** @psalm-assert Promise $this->aggregate */ $this->iterable->rewind(); $this->refillPending(); if (!$this->pending) { Utils::queue()->add(function (): void { if (!$this->aggregate || Is::settled($this->aggregate)) { return; } try { $this->checkIfFinished(); } catch (\Throwable $e) { $this->aggregate->reject($e); } }); } } catch (\Throwable $e) { $this->aggregate->reject($e); } /** * @psalm-suppress NullableReturnStatement */ return $this->aggregate; } private function createPromise(): void { $this->mutex = false; $this->aggregate = new Promise(function (): void { while (true) { if ($this->checkIfFinished()) { return; } reset($this->pending); // Consume a potentially fluctuating list of promises while // ensuring that indexes are maintained (precluding array_shift). while ($promise = current($this->pending)) { next($this->pending); $promise->wait(); if (Is::settled($this->aggregate)) { return; } } // Refill and re-sweep; give up only when nothing remains. $this->refillPending(); if (Is::settled($this->aggregate) || !$this->pending) { return; } } }); // Clear the references when the promise is resolved. $clearFn = function (): void { $this->iterable = $this->concurrency = $this->pending = null; $this->onFulfilled = $this->onRejected = null; $this->nextPendingIndex = 0; }; $this->aggregate->then($clearFn, $clearFn); } private function refillPending(): void { if (!$this->concurrency) { // Add all pending promises. while ($this->addPending() && $this->advanceIterator()) { } return; } // Add only up to N pending promises. $concurrency = is_callable($this->concurrency) ? ($this->concurrency)(count($this->pending)) : $this->concurrency; // The callable can settle the aggregate; admit nothing more. if (Is::settled($this->aggregate)) { return; } $concurrency = max($concurrency - count($this->pending), 0); // Concurrency may be set to 0 to disallow new promises. if (!$concurrency) { return; } // Add the first pending promise. $this->addPending(); // Note this is special handling for concurrency=1 so that we do // not advance the iterator after adding the first promise. This // helps work around issues with generators that might not have the // next value to yield until promise callbacks are called. while (--$concurrency && $this->advanceIterator() && $this->addPending()) { } } private function addPending(): bool { if (!$this->iterable || !$this->iterable->valid()) { return false; } $promise = Create::promiseFor($this->iterable->current()); $key = $this->iterable->key(); // Iterable keys may not be unique, so we use a counter to // guarantee uniqueness $idx = $this->nextPendingIndex++; $this->pending[$idx] = $promise->then( function ($value) use ($idx, $key): void { if ($this->onFulfilled) { ($this->onFulfilled)( $value, $key, $this->aggregate ); } $this->step($idx); }, function ($reason) use ($idx, $key): void { if ($this->onRejected) { ($this->onRejected)( $reason, $key, $this->aggregate ); } $this->step($idx); } ); return true; } private function advanceIterator(): bool { // Place a lock on the iterator so that we ensure to not recurse, // preventing fatal generator errors. if ($this->mutex) { $this->stepWhileLocked = true; return false; } $this->mutex = true; try { $this->iterable->next(); $this->mutex = false; } catch (\Throwable $e) { $this->aggregate->reject($e); $this->mutex = false; return false; } // Run the completion check that locked steps skipped. if ($this->stepWhileLocked) { $this->stepWhileLocked = false; if (!Is::settled($this->aggregate)) { $this->checkIfFinished(); } } return true; } private function step(int $idx): void { // If the promise was already resolved, then ignore this step. if (Is::settled($this->aggregate)) { return; } unset($this->pending[$idx]); // Only refill pending promises if we are not locked, preventing the // EachPromise to recursively invoke the provided iterator, which // cause a fatal error: "Cannot resume an already running generator" if ($this->advanceIterator() && !$this->checkIfFinished()) { // Add more pending promises if possible. $this->refillPending(); } } /** @phpstan-impure */ private function checkIfFinished(): bool { if (!$this->pending && !$this->iterable->valid()) { // Resolve the promise if there's nothing left to do. $this->aggregate->resolve(null); return true; } return false; } } value = $value; } public function then( ?callable $onFulfilled = null, ?callable $onRejected = null ): PromiseInterface { // Return itself if there is no onFulfilled function. if (!$onFulfilled) { return $this; } $queue = Utils::queue(); $p = new Promise([$queue, 'run']); $value = $this->value; $queue->add(static function () use ($p, $value, $onFulfilled): void { if (Is::pending($p)) { try { $p->resolve($onFulfilled($value)); } catch (\Throwable $e) { $p->reject($e); } } }); return $p; } public function otherwise(callable $onRejected): PromiseInterface { return $this->then(null, $onRejected); } public function wait(bool $unwrap = true) { return $unwrap ? $this->value : null; } public function getState(): string { return self::FULFILLED; } public function resolve($value): void { if ($value !== $this->value) { throw new \LogicException('Cannot resolve a fulfilled promise'); } } public function reject($reason): void { throw new \LogicException('Cannot reject a fulfilled promise'); } public function cancel(): void { // pass } } getState() === PromiseInterface::PENDING; } /** * Returns true if a promise is fulfilled or rejected. */ public static function settled(PromiseInterface $promise): bool { return $promise->getState() !== PromiseInterface::PENDING; } /** * Returns true if a promise is fulfilled. */ public static function fulfilled(PromiseInterface $promise): bool { return $promise->getState() === PromiseInterface::FULFILLED; } /** * Returns true if a promise is rejected. */ public static function rejected(PromiseInterface $promise): bool { return $promise->getState() === PromiseInterface::REJECTED; } } waitFn = $waitFn; $this->cancelFn = $cancelFn; } public function then( ?callable $onFulfilled = null, ?callable $onRejected = null ): PromiseInterface { if ($this->state === self::PENDING) { $p = new Promise(null, [$this, 'cancel']); $this->handlers[] = [$p, $onFulfilled, $onRejected]; $p->waitList = $this->waitList; $p->waitList[] = $this; return $p; } // Return a fulfilled promise and immediately invoke any callbacks. if ($this->state === self::FULFILLED) { $promise = Create::promiseFor($this->result); return $onFulfilled ? $promise->then($onFulfilled) : $promise; } // It's either cancelled or rejected, so return a rejected promise // and immediately invoke any callbacks. $rejection = Create::rejectionFor($this->result); return $onRejected ? $rejection->then(null, $onRejected) : $rejection; } public function otherwise(callable $onRejected): PromiseInterface { return $this->then(null, $onRejected); } public function wait(bool $unwrap = true) { $this->waitIfPending(); if ($this->result instanceof PromiseInterface) { return $this->result->wait($unwrap); } if ($unwrap) { if ($this->state === self::FULFILLED) { return $this->result; } // It's rejected so "unwrap" and throw an exception. throw Create::exceptionFor($this->result); } } public function getState(): string { return $this->state; } public function cancel(): void { if ($this->state !== self::PENDING) { return; } $this->waitFn = $this->waitList = null; if ($this->cancelFn) { $fn = $this->cancelFn; $this->cancelFn = null; try { $fn(); } catch (\Throwable $e) { $this->reject($e); } } // Reject the promise only if it wasn't rejected in a then callback. /** @psalm-suppress RedundantCondition */ if ($this->state === self::PENDING) { $this->reject(new CancellationException('Promise has been cancelled')); } } public function resolve($value): void { $this->settle(self::FULFILLED, $value); } public function reject($reason): void { $this->settle(self::REJECTED, $reason); } private function settle(string $state, $value): void { if ($this->state !== self::PENDING) { // Ignore calls with the same resolution. if ($state === $this->state && $value === $this->result) { return; } throw $this->state === $state ? new \LogicException("The promise is already {$state}.") : new \LogicException("Cannot change a {$this->state} promise to {$state}"); } if ($value === $this) { throw new \LogicException('Cannot fulfill or reject a promise with itself'); } // Clear out the state of the promise but stash the handlers. $this->state = $state; $this->result = $value; $handlers = $this->handlers; $this->handlers = null; $this->waitList = $this->waitFn = null; $this->cancelFn = null; if (!$handlers) { return; } // If the value was not a settled promise or a thenable, then resolve // it in the task queue using the correct ID. if (!is_object($value) || !method_exists($value, 'then')) { $id = $state === self::FULFILLED ? 1 : 2; // It's a success, so resolve the handlers in the queue. Utils::queue()->add(static function () use ($id, $value, $handlers): void { foreach ($handlers as $handler) { self::callHandler($id, $value, $handler); } }); } elseif ($value instanceof Promise && Is::pending($value)) { // We can just merge our handlers onto the next promise. $value->handlers = array_merge($value->handlers, $handlers); } else { // Resolve the handlers when the forwarded promise is resolved. $value->then( static function ($value) use ($handlers): void { foreach ($handlers as $handler) { self::callHandler(1, $value, $handler); } }, static function ($reason) use ($handlers): void { foreach ($handlers as $handler) { self::callHandler(2, $reason, $handler); } } ); } } /** * Call a stack of handlers using a specific callback index and value. * * @param int $index 1 (resolve) or 2 (reject). * @param mixed $value Value to pass to the callback. * @param array $handler Array of handler data (promise and callbacks). */ private static function callHandler(int $index, $value, array $handler): void { /** @var PromiseInterface $promise */ $promise = $handler[0]; // The promise may have been cancelled or resolved before placing // this thunk in the queue. if (Is::settled($promise)) { return; } try { if (isset($handler[$index])) { /* * If $f throws an exception, then $handler will be in the exception * stack trace. Since $handler contains a reference to the callable * itself we get a circular reference. We clear the $handler * here to avoid that memory leak. */ $f = $handler[$index]; unset($handler); $promise->resolve($f($value)); } elseif ($index === 1) { // Forward resolution values as-is. $promise->resolve($value); } else { // Forward rejections down the chain. $promise->reject($value); } } catch (\Throwable $reason) { $promise->reject($reason); } } private function waitIfPending(): void { if ($this->state !== self::PENDING) { return; } elseif ($this->waitFn) { $this->invokeWaitFn(); } elseif ($this->waitList) { $this->invokeWaitList(); } else { // If there's no wait function, then reject the promise. $this->reject('Cannot wait on a promise that has ' .'no internal wait function. You must provide a wait ' .'function when constructing the promise to be able to ' .'wait on a promise.'); } Utils::queue()->run(); /** @psalm-suppress RedundantCondition */ if ($this->state === self::PENDING) { $this->reject('Invoking the wait callback did not resolve the promise'); } } private function invokeWaitFn(): void { try { $wfn = $this->waitFn; $this->waitFn = null; $wfn(true); } catch (\Throwable $reason) { if ($this->state === self::PENDING) { // The promise has not been resolved yet, so reject the promise // with the exception. $this->reject($reason); } else { // The promise was already resolved, so there's a problem in // the application. throw $reason; } } } private function invokeWaitList(): void { $waitList = $this->waitList; $this->waitList = null; foreach ($waitList as $result) { do { $result->waitIfPending(); $result = $result->result; } while ($result instanceof Promise); if ($result instanceof PromiseInterface) { $result->wait(false); } } } } reason = $reason; } public function then( ?callable $onFulfilled = null, ?callable $onRejected = null ): PromiseInterface { // If there's no onRejected callback then just return self. if (!$onRejected) { return $this; } $queue = Utils::queue(); $reason = $this->reason; $p = new Promise([$queue, 'run']); $queue->add(static function () use ($p, $reason, $onRejected): void { if (Is::pending($p)) { try { // Return a resolved promise if onRejected does not throw. $p->resolve($onRejected($reason)); } catch (\Throwable $e) { // onRejected threw, so return a rejected promise. $p->reject($e); } } }); return $p; } public function otherwise(callable $onRejected): PromiseInterface { return $this->then(null, $onRejected); } public function wait(bool $unwrap = true) { if ($unwrap) { throw Create::exceptionFor($this->reason); } return null; } public function getState(): string { return self::REJECTED; } public function resolve($value): void { throw new \LogicException('Cannot resolve a rejected promise'); } public function reject($reason): void { if ($reason !== $this->reason) { throw new \LogicException('Cannot reject a rejected promise'); } } public function cancel(): void { // pass } } reason = $reason; $message = 'The promise was rejected'; if ($description) { $message .= ' with reason: '.$description; } elseif (is_string($reason) || (is_object($reason) && method_exists($reason, '__toString')) ) { $message .= ' with reason: '.$this->reason; } elseif ($reason instanceof \JsonSerializable) { $message .= ' with reason: '.json_encode($this->reason, JSON_PRETTY_PRINT); } parent::__construct($message); } /** * Returns the rejection reason. * * @return mixed */ public function getReason() { return $this->reason; } } run(); * * @final */ class TaskQueue implements TaskQueueInterface { private $enableShutdown = true; private $queue = []; public function __construct(bool $withShutdown = true) { if ($withShutdown) { register_shutdown_function(function (): void { if ($this->enableShutdown) { // Only run the tasks if an E_ERROR didn't occur. $err = error_get_last(); if (!$err || ($err['type'] ^ E_ERROR)) { $this->run(); } } }); } } public function isEmpty(): bool { return !$this->queue; } public function add(callable $task): void { $this->queue[] = $task; } public function run(): void { while ($task = array_shift($this->queue)) { /** @var callable $task */ $task(); } } /** * The task queue will be run and exhausted by default when the process * exits IFF the exit is not the result of a PHP E_ERROR error. * * You can disable running the automatic shutdown of the queue by calling * this function. If you disable the task queue shutdown process, then you * MUST either run the task queue (as a result of running your event loop * or manually using the run() method) or wait on each outstanding promise. * * Note: This shutdown will occur before any destructors are triggered. */ public function disableShutdown(): void { $this->enableShutdown = false; } } * while ($eventLoop->isRunning()) { * GuzzleHttp\Promise\Utils::queue()->run(); * } * * * @param TaskQueueInterface|null $assign Optionally specify a new queue instance. */ public static function queue(?TaskQueueInterface $assign = null): TaskQueueInterface { static $queue; if ($assign) { $queue = $assign; } elseif (!$queue) { $queue = new TaskQueue(); } return $queue; } /** * Adds a function to run in the task queue when it is next `run()` and * returns a promise that is fulfilled or rejected with the result. * * @param callable $task Task function to run. */ public static function task(callable $task): PromiseInterface { $queue = self::queue(); $promise = new Promise([$queue, 'run']); $queue->add(function () use ($task, $promise): void { try { if (Is::pending($promise)) { $promise->resolve($task()); } } catch (\Throwable $e) { $promise->reject($e); } }); return $promise; } /** * Synchronously waits on a promise to resolve and returns an inspection * state array. * * Returns a state associative array containing a "state" key mapping to a * valid promise state. If the state of the promise is "fulfilled", the * array will contain a "value" key mapping to the fulfilled value of the * promise. If the promise is rejected, the array will contain a "reason" * key mapping to the rejection reason of the promise. * * @param PromiseInterface $promise Promise or value. */ public static function inspect(PromiseInterface $promise): array { try { return [ 'state' => PromiseInterface::FULFILLED, 'value' => $promise->wait(), ]; } catch (\Throwable $e) { if ($e instanceof AggregateException) { return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; } if ($e instanceof RejectionException) { return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()]; } return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; } } /** * Waits on all of the provided promises, but does not unwrap rejected * promises as thrown exception. * * Returns an array of inspection state arrays. * * @see inspect for the inspection state array format. * * @param PromiseInterface[] $promises Traversable of promises to wait upon. */ public static function inspectAll($promises): array { $promises = self::prepareIterable($promises, __FUNCTION__); $results = []; foreach ($promises as $key => $promise) { $results[$key] = self::inspect($promise); } return $results; } /** * Waits on all of the provided promises and returns the fulfilled values. * * Returns an array that contains the value of each promise (in the same * order the promises were provided). An exception is thrown if any of the * promises are rejected. * * @param iterable $promises Iterable of PromiseInterface objects to wait on. * * @throws \Throwable on error */ public static function unwrap($promises): array { $promises = self::prepareIterable($promises, __FUNCTION__); $results = []; foreach ($promises as $key => $promise) { $results[$key] = $promise->wait(); } return $results; } /** * Given an array of promises, return a promise that is fulfilled when all * the items in the array are fulfilled. * * The promise's fulfillment value is an array with fulfillment values at * respective positions to the original array. If any promise in the array * rejects, the returned promise is rejected with the rejection reason. * * @param mixed $promises Promises or values. * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution. */ public static function all($promises, bool $recursive = false): PromiseInterface { $promises = self::prepareIterable($promises, __FUNCTION__); $results = []; $promise = Each::of( $promises, function ($value, $idx) use (&$results): void { $results[$idx] = $value; }, function ($reason, $idx, Promise $aggregate): void { if (Is::pending($aggregate)) { $aggregate->reject($reason); } } )->then(function () use (&$results) { ksort($results); return $results; }); if (true === $recursive) { $promise = $promise->then(function ($results) use ($recursive, &$promises) { // A consumed generator cannot be traversed again, so a // recursive pass has nothing further to observe. if ($promises instanceof \Generator) { return $results; } foreach ($promises as $promise) { if (Is::pending($promise)) { return self::all($promises, $recursive); } } return $results; }); } return $promise; } /** * Initiate a competitive race between multiple promises or values (values * will become immediately fulfilled promises). * * When count amount of promises have been fulfilled, the returned promise * is fulfilled with an array that contains the fulfillment values of the * winners in order of resolution. * * This promise is rejected with a {@see AggregateException} if the number * of fulfilled promises is less than the desired $count. * * @param int $count Total number of promises. * @param mixed $promises Promises or values. */ public static function some(int $count, $promises): PromiseInterface { $promises = self::prepareIterable($promises, __FUNCTION__); $results = []; $rejections = []; return Each::of( $promises, function ($value, $idx, PromiseInterface $p) use (&$results, $count): void { if (Is::settled($p)) { return; } $results[$idx] = $value; if (count($results) >= $count) { $p->resolve(null); } }, function ($reason) use (&$rejections): void { $rejections[] = $reason; } )->then( function () use (&$results, &$rejections, $count) { if (count($results) !== $count) { throw new AggregateException( 'Not enough promises to fulfill count', $rejections ); } ksort($results); return array_values($results); } ); } /** * Like some(), with 1 as count. However, if the promise fulfills, the * fulfillment value is not an array of 1 but the value directly. * * @param mixed $promises Promises or values. */ public static function any($promises): PromiseInterface { $promises = self::prepareIterable($promises, __FUNCTION__); return self::some(1, $promises)->then(function ($values) { return $values[0]; }); } /** * Returns a promise that is fulfilled when all of the provided promises have * been fulfilled or rejected. * * The returned promise is fulfilled with an array of inspection state arrays. * * @see inspect for the inspection state array format. * * @param mixed $promises Promises or values. */ public static function settle($promises): PromiseInterface { $promises = self::prepareIterable($promises, __FUNCTION__); $results = []; return Each::of( $promises, function ($value, $idx) use (&$results): void { $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value]; }, function ($reason, $idx) use (&$results): void { $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason]; } )->then(function () use (&$results) { ksort($results); return $results; }); } private static function prepareIterable($promises, string $method): iterable { if (is_iterable($promises)) { return $promises; } self::triggerNonIterableDeprecation($promises, $method); return [$promises]; } private static function triggerNonIterableDeprecation($promises, string $method): void { if (is_iterable($promises)) { return; } \trigger_deprecation( 'guzzlehttp/promises', '2.5', 'Passing a non-iterable to %s::%s() is deprecated; guzzlehttp/promises 3.0 will require an iterable.', self::class, $method ); } } # Change Log 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.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## 2.13.0 - 2026-07-16 ### Added - Add `Utils::` `asciiToLower`, `asciiToUpper`, `asciiUcFirst`, `caselessEquals`, `caselessContains` ### Changed - Use locale-independent ASCII case folding everywhere case is normalized - Trigger a runtime deprecation for previously deprecated functionality in 2.3.0 ## 2.12.5 - 2026-07-13 ### Fixed - Compare header names and hosts with locale-independent ASCII lowercasing - Compare hosts without locale sensitivity when detecting cross-origin redirects ## 2.12.4 - 2026-07-08 ### Changed - Pass explicit trim characters ahead of the PHP 8.6 trim default change ### Fixed - Anchor server port and response start-line patterns to the true end of input - Treat host-less origin-form request targets starting with `//` as paths in `Message::parseRequest()` - Reject raw DEL bytes in bracketed IP-literal hosts instead of parsing a mutated host - Reject invalid bytes after a bracketed IP-literal host instead of reparsing a different host ## 2.12.3 - 2026-06-23 ### Security - Validate the URI host so `getHost()` matches the URI authority (GHSA-c2w2-prh8-qm98) ## 2.12.2 - 2026-06-23 ### Fixed - Report URI parsing, filtering, and normalization PCRE failures explicitly - Report HTTP message parser PCRE failures explicitly - Fail closed when PCRE validation fails for request targets and hosts ## 2.12.1 - 2026-06-18 ### Security - Reject CR/LF in HTTP method, protocol version, and reason phrase (GHSA-vm85-hxw5-5432) ## 2.12.0 - 2026-06-16 ### Deprecated - Deprecated non-finite float values in `Query::build()` that guzzlehttp/psr7 3.0 rejects - Deprecated non-finite float multipart contents that guzzlehttp/psr7 3.0 rejects - Deprecated non-string scalar bodies in `Utils::streamFor()`; cast them to a string for 3.0 - Deprecated non-string `Uri::withQueryValues()` values; cast them to a string for 3.0 ## 2.11.1 - 2026-06-12 ### Fixed - Fixed non-finite float values emitting coercion warnings on PHP 8.5 ## 2.11.0 - 2026-06-02 ### Changed - Changed `Utils::modifyRequest()` to reject conflicting URI and `Host` header changes in the same call - Changed `Header::parse()` to split semicolon-separated parameters without repeated regular expression lookaheads - Changed `UriComparator::isCrossOrigin()` so only HTTP and HTTPS missing ports receive implicit default ports ### Deprecated - Deprecated invalid PSR-7 arguments that guzzlehttp/psr7 3.0 will require native types for - Deprecated non-string header values that guzzlehttp/psr7 3.0 will reject - Deprecated empty header value arrays that guzzlehttp/psr7 3.0 will reject - Deprecated URI schemes that do not match guzzlehttp/psr7 3.0 syntax requirements - Deprecated multipart boundary and custom part header metadata that guzzlehttp/psr7 3.0 will reject - Deprecated reliance on automatic uppercasing of request methods; guzzlehttp/psr7 3.0 preserves method casing - Deprecated invalid `Utils::modifyRequest()` change values that guzzlehttp/psr7 3.0 will reject ### Fixed - Fixed `Utils::copyToStream()` to retry short destination writes instead of dropping the unwritten remainder - Fixed `Header::parse()` splitting of semicolon-separated parameters with escaped quotes ## 2.10.4 - 2026-05-29 ### Fixed - Apply `UriNormalizer` percent-encoding normalizations to URI fragments - Make `LimitStream::getSize()` return `0` for slices past the underlying stream end - Make `AppendStream::read()` return an empty string when no streams are attached - Make `CachingStream::read()` throw on an incomplete cache-target write instead of silently corrupting replays - Prevent `CachingStream::seek()` from looping indefinitely when the remote stream makes no progress ## 2.10.3 - 2026-05-27 ### Fixed - Fixed URI parsing for IPv6 literals containing embedded IPv4 addresses - Fixed malformed UTF-8 URI strings being parsed as empty URIs ## 2.10.2 - 2026-05-25 ### Security - Reject control and whitespace characters in URI host components (GHSA-hq7v-mx3g-29hw) - Reject malformed Host values when constructing request URIs (GHSA-34xg-wgjx-8xph) ### Fixed - Make `ServerRequest::fromGlobals()` robust against unexpected HTTP header value types in `$_SERVER` ## 2.10.1 - 2026-05-20 ### Fixed - Fix `Utils::modifyRequest()` with numeric header names ## 2.10.0 - 2026-05-19 ### Changed - Harden `ServerRequest::fromGlobals()` against malformed `$_SERVER` values - Prevent custom stream metadata from affecting internal size handling - Throw when `StreamWrapper::getResource()` cannot create a resource - Preserve custom request implementations in `Utils::modifyRequest()` - Preserve custom URI implementations in `UriResolver::resolve()` - Make `Uri::__toString()` side-effect-free ## 2.9.1 - 2026-05-19 ### Fixed - Fix parsing of relative path references containing a colon in a non-initial path segment - Fix `CachingStream::detach()` returning an incomplete resource before the decorated stream has been fully read - Fix `Message::bodySummary()` returning `null` when truncating printable UTF-8 bodies inside a multibyte character ## 2.9.0 - 2026-03-10 ### Added - Added nested array expansion support to `MultipartStream` - Added `@return static` to `MessageTrait` methods ### Changed - Updated MIME type mappings ## 2.8.1 - 2026-03-10 ### Fixed - Encode `+` signs in `Uri::withQueryValue()` and `Uri::withQueryValues()` to prevent them being interpreted as spaces ## 2.8.0 - 2025-08-23 ### Added - Allow empty lists as header values ### Changed - PHP 8.5 support ## 2.7.1 - 2025-03-27 ### Fixed - Fixed uppercase IPv6 addresses in URI ### Changed - Improve uploaded file error message ## 2.7.0 - 2024-07-18 ### Added - Add `Utils::redactUserInfo()` method - Add ability to encode bools as ints in `Query::build` ## 2.6.3 - 2024-07-18 ### Fixed - Make `StreamWrapper::stream_stat()` return `false` if inner stream's size is `null` ### Changed - PHP 8.4 support ## 2.6.2 - 2023-12-03 ### Fixed - Fixed another issue with the fact that PHP transforms numeric strings in array keys to ints ### Changed - Updated links in docs to their canonical versions - Replaced `call_user_func*` with native calls ## 2.6.1 - 2023-08-27 ### Fixed - Properly handle the fact that PHP transforms numeric strings in array keys to ints ## 2.6.0 - 2023-08-03 ### Changed - Updated the mime type map to add some new entries, fix a couple of invalid entries, and remove an invalid entry - Fallback to `application/octet-stream` if we are unable to guess the content type for a multipart file upload ## 2.5.1 - 2023-08-03 ### Fixed - Corrected mime type for `.acc` files to `audio/aac` ### Changed - PHP 8.3 support ## 2.5.0 - 2023-04-17 ### Changed - Adjusted `psr/http-message` version constraint to `^1.1 || ^2.0` ## 2.4.5 - 2023-04-17 ### Fixed - Prevent possible warnings on unset variables in `ServerRequest::normalizeNestedFileSpec` - Fixed `Message::bodySummary` when `preg_match` fails - Fixed header validation issue ## 2.4.4 - 2023-03-09 ### Changed - Removed the need for `AllowDynamicProperties` in `LazyOpenStream` ## 2.4.3 - 2022-10-26 ### Changed - Replaced `sha1(uniqid())` by `bin2hex(random_bytes(20))` ## 2.4.2 - 2022-10-25 ### Fixed - Fixed erroneous behaviour when combining host and relative path ## 2.4.1 - 2022-08-28 ### Fixed - Rewind body before reading in `Message::bodySummary` ## 2.4.0 - 2022-06-20 ### Added - Added provisional PHP 8.2 support - Added `UriComparator::isCrossOrigin` method ## 2.3.0 - 2022-06-09 ### Fixed - Added `Header::splitList` method - Added `Utils::tryGetContents` method - Improved `Stream::getContents` method - Updated mimetype mappings ## 2.2.2 - 2022-06-08 ### Fixed - Fix `Message::parseRequestUri` for numeric headers - Re-wrap exceptions thrown in `fread` into runtime exceptions - Throw an exception when multipart options is misformatted ## 2.2.1 - 2022-03-20 ### Fixed - Correct header value validation ## 2.2.0 - 2022-03-20 ### Added - A more compressive list of mime types - Add JsonSerializable to Uri - Missing return types ### Fixed - Bug MultipartStream no `uri` metadata - Bug MultipartStream with filename for `data://` streams - Fixed new line handling in MultipartStream - Reduced RAM usage when copying streams - Updated parsing in `Header::normalize()` ## 2.1.1 - 2022-03-20 ### Fixed - Validate header values properly ## 2.1.0 - 2021-10-06 ### Changed - Attempting to create a `Uri` object from a malformed URI will no longer throw a generic `InvalidArgumentException`, but rather a `MalformedUriException`, which inherits from the former for backwards compatibility. Callers relying on the exception being thrown to detect invalid URIs should catch the new exception. ### Fixed - Return `null` in caching stream size if remote size is `null` ## 2.0.0 - 2021-06-30 Identical to the RC release. ## 2.0.0@RC-1 - 2021-04-29 ### Fixed - Handle possibly unset `url` in `stream_get_meta_data` ## 2.0.0@beta-1 - 2021-03-21 ### Added - PSR-17 factories - Made classes final - PHP7 type hints ### Changed - When building a query string, booleans are represented as 1 and 0. ### Removed - PHP < 7.2 support - All functions in the `GuzzleHttp\Psr7` namespace ## 1.8.1 - 2021-03-21 ### Fixed - Issue parsing IPv6 URLs - Issue modifying ServerRequest lost all its attributes ## 1.8.0 - 2021-03-21 ### Added - Locale independent URL parsing - Most classes got a `@final` annotation to prepare for 2.0 ### Fixed - Issue when creating stream from `php://input` and curl-ext is not installed - Broken `Utils::tryFopen()` on PHP 8 ## 1.7.0 - 2020-09-30 ### Added - Replaced functions by static methods ### Fixed - Converting a non-seekable stream to a string - Handle multiple Set-Cookie correctly - Ignore array keys in header values when merging - Allow multibyte characters to be parsed in `Message:bodySummary()` ### Changed - Restored partial HHVM 3 support ## [1.6.1] - 2019-07-02 ### Fixed - Accept null and bool header values again ## [1.6.0] - 2019-06-30 ### Added - Allowed version `^3.0` of `ralouphie/getallheaders` dependency (#244) - Added MIME type for WEBP image format (#246) - Added more validation of values according to PSR-7 and RFC standards, e.g. status code range (#250, #272) ### Changed - Tests don't pass with HHVM 4.0, so HHVM support got dropped. Other libraries like composer have done the same. (#262) - Accept port number 0 to be valid (#270) ### Fixed - Fixed subsequent reads from `php://input` in ServerRequest (#247) - Fixed readable/writable detection for certain stream modes (#248) - Fixed encoding of special characters in the `userInfo` component of an URI (#253) ## [1.5.2] - 2018-12-04 ### Fixed - Check body size when getting the message summary ## [1.5.1] - 2018-12-04 ### Fixed - Get the summary of a body only if it is readable ## [1.5.0] - 2018-12-03 ### Added - Response first-line to response string exception (fixes #145) - A test for #129 behavior - `get_message_body_summary` function in order to get the message summary - `3gp` and `mkv` mime types ### Changed - Clarify exception message when stream is detached ### Deprecated - Deprecated parsing folded header lines as per RFC 7230 ### Fixed - Fix `AppendStream::detach` to not close streams - `InflateStream` preserves `isSeekable` attribute of the underlying stream - `ServerRequest::getUriFromGlobals` to support URLs in query parameters Several other fixes and improvements. ## [1.4.2] - 2017-03-20 ### Fixed - Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing calls to `trigger_error` when deprecated methods are invoked. ## [1.4.1] - 2017-02-27 ### Added - Rriggering of silenced deprecation warnings. ### Fixed - Reverted BC break by reintroducing behavior to automagically fix a URI with a relative path and an authority by adding a leading slash to the path. It's only deprecated now. ## [1.4.0] - 2017-02-21 ### Added - Added common URI utility methods based on RFC 3986 (see documentation in the readme): - `Uri::isDefaultPort` - `Uri::isAbsolute` - `Uri::isNetworkPathReference` - `Uri::isAbsolutePathReference` - `Uri::isRelativePathReference` - `Uri::isSameDocumentReference` - `Uri::composeComponents` - `UriNormalizer::normalize` - `UriNormalizer::isEquivalent` - `UriResolver::relativize` ### Changed - Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form. - Allow `parse_response` to parse a response without delimiting space and reason. - Ensure each URI modification results in a valid URI according to PSR-7 discussions. Invalid modifications will throw an exception instead of returning a wrong URI or doing some magic. - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception because the path of a URI with an authority must start with a slash "/" or be empty - `(new Uri())->withScheme('http')` will return `'http://localhost'` ### Deprecated - `Uri::resolve` in favor of `UriResolver::resolve` - `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments` ### Fixed - `Stream::read` when length parameter <= 0. - `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory. - `ServerRequest::getUriFromGlobals` when `Host` header contains port. - Compatibility of URIs with `file` scheme and empty host. ## [1.3.1] - 2016-06-25 ### Fixed - `Uri::__toString` for network path references, e.g. `//example.org`. - Missing lowercase normalization for host. - Handling of URI components in case they are `'0'` in a lot of places, e.g. as a user info password. - `Uri::withAddedHeader` to correctly merge headers with different case. - Trimming of header values in `Uri::withAddedHeader`. Header values may be surrounded by whitespace which should be ignored according to RFC 7230 Section 3.2.4. This does not apply to header names. - `Uri::withAddedHeader` with an array of header values. - `Uri::resolve` when base path has no slash and handling of fragment. - Handling of encoding in `Uri::with(out)QueryValue` so one can pass the key/value both in encoded as well as decoded form to those methods. This is consistent with withPath, withQuery etc. - `ServerRequest::withoutAttribute` when attribute value is null. ## [1.3.0] - 2016-04-13 ### Added - Remaining interfaces needed for full PSR7 compatibility (ServerRequestInterface, UploadedFileInterface, etc.). - Support for stream_for from scalars. ### Changed - Can now extend Uri. ### Fixed - A bug in validating request methods by making it more permissive. ## [1.2.3] - 2016-02-18 ### Fixed - Support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote streams, which can sometimes return fewer bytes than requested with `fread`. - Handling of gzipped responses with FNAME headers. ## [1.2.2] - 2016-01-22 ### Added - Support for URIs without any authority. - Support for HTTP 451 'Unavailable For Legal Reasons.' - Support for using '0' as a filename. - Support for including non-standard ports in Host headers. ## [1.2.1] - 2015-11-02 ### Changes - Now supporting negative offsets when seeking to SEEK_END. ## [1.2.0] - 2015-08-15 ### Changed - Body as `"0"` is now properly added to a response. - Now allowing forward seeking in CachingStream. - Now properly parsing HTTP requests that contain proxy targets in `parse_request`. - functions.php is now conditionally required. - user-info is no longer dropped when resolving URIs. ## [1.1.0] - 2015-06-24 ### Changed - URIs can now be relative. - `multipart/form-data` headers are now overridden case-insensitively. - URI paths no longer encode the following characters because they are allowed in URIs: "(", ")", "*", "!", "'" - A port is no longer added to a URI when the scheme is missing and no port is present. ## 1.0.0 - 2015-05-19 Initial release. Currently unsupported: - `Psr\Http\Message\ServerRequestInterface` - `Psr\Http\Message\UploadedFileInterface` [1.6.0]: https://github.com/guzzle/psr7/compare/1.5.2...1.6.0 [1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2 [1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1 [1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0 [1.4.2]: https://github.com/guzzle/psr7/compare/1.4.1...1.4.2 [1.4.1]: https://github.com/guzzle/psr7/compare/1.4.0...1.4.1 [1.4.0]: https://github.com/guzzle/psr7/compare/1.3.1...1.4.0 [1.3.1]: https://github.com/guzzle/psr7/compare/1.3.0...1.3.1 [1.3.0]: https://github.com/guzzle/psr7/compare/1.2.3...1.3.0 [1.2.3]: https://github.com/guzzle/psr7/compare/1.2.2...1.2.3 [1.2.2]: https://github.com/guzzle/psr7/compare/1.2.1...1.2.2 [1.2.1]: https://github.com/guzzle/psr7/compare/1.2.0...1.2.1 [1.2.0]: https://github.com/guzzle/psr7/compare/1.1.0...1.2.0 [1.1.0]: https://github.com/guzzle/psr7/compare/1.0.0...1.1.0 The MIT License (MIT) Copyright (c) 2015 Michael Dowling Copyright (c) 2015 Márk Sági-Kazár Copyright (c) 2015 Graham Campbell Copyright (c) 2016 Tobias Schultze Copyright (c) 2016 George Mponos Copyright (c) 2018 Tobias Nyholm 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-7 Message Implementation This repository contains a full [PSR-7](https://www.php-fig.org/psr/psr-7/) message implementation, several stream decorators, and some helpful functionality like query string parsing. ![CI](https://github.com/guzzle/psr7/workflows/CI/badge.svg) ![Static analysis](https://github.com/guzzle/psr7/workflows/Static%20analysis/badge.svg) ## Features This package comes with a number of stream implementations and stream decorators. ## Installation ```shell composer require guzzlehttp/psr7 ``` ## Version Guidance | Version | Status | PHP Version | |---------|---------------------|--------------| | 1.x | EOL (2024-06-30) | >=5.4,<8.2 | | 2.x | Latest | >=7.2.5,<8.6 | See [UPGRADING.md](UPGRADING.md) for notes on upgrading from 1.x to 2.0. ## AppendStream `GuzzleHttp\Psr7\AppendStream` Reads from multiple streams, one after the other. ```php use GuzzleHttp\Psr7; $a = Psr7\Utils::streamFor('abc, '); $b = Psr7\Utils::streamFor('123.'); $composed = new Psr7\AppendStream([$a, $b]); $composed->addStream(Psr7\Utils::streamFor(' Above all listen to me')); echo $composed; // abc, 123. Above all listen to me. ``` ## BufferStream `GuzzleHttp\Psr7\BufferStream` Provides a buffer stream that can be written to fill a buffer, and read from to remove bytes from the buffer. This stream returns a "hwm" metadata value that tells upstream consumers what the configured high water mark of the stream is, or the maximum preferred size of the buffer. ```php use GuzzleHttp\Psr7; // When more than 1024 bytes are in the buffer, it will begin returning // 0 to writes. This is an indication that writers should slow down. $buffer = new Psr7\BufferStream(1024); ``` ## CachingStream The CachingStream is used to allow seeking over previously read bytes on non-seekable streams. This can be useful when transferring a non-seekable entity body fails due to needing to rewind the stream (for example, resulting from a redirect). Data that is read from the remote stream will be buffered in a PHP temp stream so that previously read bytes are cached first in memory, then on disk. ```php use GuzzleHttp\Psr7; $original = Psr7\Utils::streamFor(fopen('http://www.google.com', 'r')); $stream = new Psr7\CachingStream($original); $stream->read(1024); echo $stream->tell(); // 1024 $stream->seek(0); echo $stream->tell(); // 0 ``` ## DroppingStream `GuzzleHttp\Psr7\DroppingStream` Stream decorator that begins dropping data once the size of the underlying stream becomes too full. ```php use GuzzleHttp\Psr7; // Create an empty stream $stream = Psr7\Utils::streamFor(); // Start dropping data when the stream has more than 10 bytes $dropping = new Psr7\DroppingStream($stream, 10); $dropping->write('01234567890123456789'); echo $stream; // 0123456789 ``` ## FnStream `GuzzleHttp\Psr7\FnStream` Compose stream implementations based on a hash of callables. Allows for easy testing and extension of a provided stream without needing to create a concrete class for a simple extension point. ```php use GuzzleHttp\Psr7; $stream = Psr7\Utils::streamFor('hi'); $fnStream = Psr7\FnStream::decorate($stream, [ 'rewind' => function () use ($stream) { echo 'About to rewind - '; $stream->rewind(); echo 'rewound!'; } ]); $fnStream->rewind(); // Outputs: About to rewind - rewound! ``` ## InflateStream `GuzzleHttp\Psr7\InflateStream` Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content. This stream decorator converts the provided stream to a PHP stream resource, then appends the zlib.inflate filter. The stream is then converted back to a Guzzle stream resource to be used as a Guzzle stream. ## LazyOpenStream `GuzzleHttp\Psr7\LazyOpenStream` Lazily reads or writes to a file that is opened only after an IO operation take place on the stream. ```php use GuzzleHttp\Psr7; $stream = new Psr7\LazyOpenStream('/path/to/file', 'r'); // The file has not yet been opened... echo $stream->read(10); // The file is opened and read from only when needed. ``` ## LimitStream `GuzzleHttp\Psr7\LimitStream` LimitStream can be used to read a subset or slice of an existing stream object. This can be useful for breaking a large file into smaller pieces to be sent in chunks (e.g. Amazon S3's multipart upload API). ```php use GuzzleHttp\Psr7; $original = Psr7\Utils::streamFor(fopen('/tmp/test.txt', 'r+')); echo $original->getSize(); // >>> 1048576 // Limit the size of the body to 1024 bytes and start reading from byte 2048 $stream = new Psr7\LimitStream($original, 1024, 2048); echo $stream->getSize(); // >>> 1024 echo $stream->tell(); // >>> 0 ``` ## MultipartStream `GuzzleHttp\Psr7\MultipartStream` Stream that when read returns bytes for a streaming multipart or multipart/form-data stream. Each multipart element must contain a `name` and `contents` key. `contents` may be any non-array value accepted by `GuzzleHttp\Psr7\Utils::streamFor()`, including closures and invokable objects. Array contents are recursively expanded into nested form fields. ## NoSeekStream `GuzzleHttp\Psr7\NoSeekStream` NoSeekStream wraps a stream and does not allow seeking. ```php use GuzzleHttp\Psr7; $original = Psr7\Utils::streamFor('foo'); $noSeek = new Psr7\NoSeekStream($original); echo $noSeek->read(3); // foo var_export($noSeek->isSeekable()); // false $noSeek->seek(0); var_export($noSeek->read(3)); // NULL ``` ## PumpStream `GuzzleHttp\Psr7\PumpStream` Provides a read only stream that pumps data from a PHP callable. When invoking the provided callable, the PumpStream will pass the suggested number of bytes to read to the callable. The callable can choose to ignore this value and return fewer or more bytes than requested. Any extra data returned by the provided callable is buffered internally until drained using the read() function of the PumpStream. The provided callable MUST return false or null when there is no more data to read. Userland callables that declare no parameters are tolerated by PHP, but length-aware callables remain the recommended formal shape. ## Implementing stream decorators Creating a stream decorator is very easy thanks to the `GuzzleHttp\Psr7\StreamDecoratorTrait`. This trait provides methods that implement `Psr\Http\Message\StreamInterface` by proxying to an underlying stream. Just `use` the `StreamDecoratorTrait` and implement your custom methods. For example, let's say we wanted to call a specific function each time the last byte is read from a stream. This could be implemented by overriding the `read()` method. ```php use Psr\Http\Message\StreamInterface; use GuzzleHttp\Psr7\StreamDecoratorTrait; class EofCallbackStream implements StreamInterface { use StreamDecoratorTrait; private $callback; private $stream; public function __construct(StreamInterface $stream, callable $cb) { $this->stream = $stream; $this->callback = $cb; } public function read($length) { $result = $this->stream->read($length); // Invoke the callback when EOF is hit. if ($this->eof()) { ($this->callback)(); } return $result; } } ``` This decorator could be added to any existing stream and used like so: ```php use GuzzleHttp\Psr7; $original = Psr7\Utils::streamFor('foo'); $eofStream = new EofCallbackStream($original, function () { echo 'EOF!'; }); $eofStream->read(2); $eofStream->read(1); // echoes "EOF!" $eofStream->seek(0); $eofStream->read(3); // echoes "EOF!" ``` ## PHP StreamWrapper You can use the `GuzzleHttp\Psr7\StreamWrapper` class if you need to use a PSR-7 stream as a PHP stream resource. Use the `GuzzleHttp\Psr7\StreamWrapper::getResource()` method to create a PHP stream from a PSR-7 stream. ```php use GuzzleHttp\Psr7\StreamWrapper; $stream = GuzzleHttp\Psr7\Utils::streamFor('hello!'); $resource = StreamWrapper::getResource($stream); echo fread($resource, 6); // outputs hello! ``` # Static API There are various static methods available under the `GuzzleHttp\Psr7` namespace. ## `GuzzleHttp\Psr7\Message::toString` `public static function toString(MessageInterface $message): string` Returns the string representation of an HTTP message. ```php $request = new GuzzleHttp\Psr7\Request('GET', 'http://example.com'); echo GuzzleHttp\Psr7\Message::toString($request); ``` ## `GuzzleHttp\Psr7\Message::bodySummary` `public static function bodySummary(MessageInterface $message, int $truncateAt = 120): string|null` Get a short summary of the message body. Will return `null` if the response is not printable. ## `GuzzleHttp\Psr7\Message::rewindBody` `public static function rewindBody(MessageInterface $message): void` Attempts to rewind a message body and throws an exception on failure. The body of the message will only be rewound if a call to `tell()` returns a value other than `0`. ## `GuzzleHttp\Psr7\Message::parseMessage` `public static function parseMessage(string $message): array` Parses an HTTP message into an associative array. The array contains the "start-line" key containing the start line of the message, "headers" key containing an associative array of header array values, and a "body" key containing the body of the message. ## `GuzzleHttp\Psr7\Message::parseRequestUri` `public static function parseRequestUri(string $path, array $headers): string` Constructs a URI for an HTTP request message. ## `GuzzleHttp\Psr7\Message::parseRequest` `public static function parseRequest(string $message): Request` Parses a request message string into a request object. ## `GuzzleHttp\Psr7\Message::parseResponse` `public static function parseResponse(string $message): Response` Parses a response message string into a response object. ## `GuzzleHttp\Psr7\Header::parse` `public static function parse(string|array $header): array` Parse an array of header values containing ";" separated data into an array of associative arrays representing the header key value pair data of the header. When a parameter does not contain a value, but just contains a key, this function will inject a key with a '' string value. ## `GuzzleHttp\Psr7\Header::splitList` `public static function splitList(string|string[] $header): string[]` Splits a HTTP header defined to contain a comma-separated list into each individual value: ``` $knownEtags = Header::splitList($request->getHeader('if-none-match')); ``` Example headers include `accept`, `cache-control` and `if-none-match`. ## `GuzzleHttp\Psr7\Header::normalize` (deprecated) `public static function normalize(string|array $header): array` `Header::normalize()` is deprecated in favor of [`Header::splitList()`](README.md#guzzlehttppsr7headersplitlist) which performs the same operation with a cleaned up API and improved documentation. Converts an array of header values that may contain comma separated headers into an array of headers with no comma separated values. ## `GuzzleHttp\Psr7\Query::parse` `public static function parse(string $str, int|bool $urlEncoding = true): array` Parse a query string into an associative array. If multiple values are found for the same key, the value of that key value pair will become an array. This function does not parse nested PHP style arrays into an associative array (e.g., `foo[a]=1&foo[b]=2` will be parsed into `['foo[a]' => '1', 'foo[b]' => '2'])`. ## `GuzzleHttp\Psr7\Query::build` `public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986, bool $treatBoolsAsInts = true): string` Build a query string from an array of key value pairs. This function can use the return value of `parse()` to build a query string. This function does not modify the provided keys when an array is encountered (like `http_build_query()` would). ## `GuzzleHttp\Psr7\Utils::asciiToLower` `public static function asciiToLower(string $string): string` Converts ASCII uppercase letters in a string to lowercase. Unlike strtolower(), which honors LC_CTYPE before PHP 8.2, the conversion is locale-independent and leaves every non-ASCII byte unchanged, as HTTP protocol elements require. ## `GuzzleHttp\Psr7\Utils::asciiToUpper` `public static function asciiToUpper(string $string): string` Converts ASCII lowercase letters in a string to uppercase. Unlike strtoupper(), which honors LC_CTYPE before PHP 8.2, the conversion is locale-independent and leaves every non-ASCII byte unchanged, as HTTP protocol elements require. ## `GuzzleHttp\Psr7\Utils::asciiUcFirst` `public static function asciiUcFirst(string $string): string` Converts the first character of a string to uppercase when it is an ASCII lowercase letter. Unlike ucfirst(), which honors LC_CTYPE before PHP 8.2, the conversion is locale-independent and leaves every non-ASCII byte unchanged, as HTTP protocol elements require. ## `GuzzleHttp\Psr7\Utils::caselessContains` `public static function caselessContains(string $haystack, string $needle): bool` Checks whether the haystack contains the needle, comparing ASCII letters case-insensitively and without locale sensitivity. ## `GuzzleHttp\Psr7\Utils::caselessEquals` `public static function caselessEquals(string $left, string $right): bool` Checks whether two strings are equal, comparing ASCII letters case-insensitively and without locale sensitivity. ## `GuzzleHttp\Psr7\Utils::caselessRemove` `public static function caselessRemove(iterable $keys, $keys, array $data): array` Remove the items given by the keys, case insensitively from the data. ## `GuzzleHttp\Psr7\Utils::copyToStream` `public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void` Copy the contents of a stream into another stream until the given number of bytes have been read. The copy stops if the destination `write()` returns 0, for example a `BufferStream` at its high water mark or a full `DroppingStream`. For a guaranteed full copy, use a normal writable stream such as a file or `php://temp` stream. ## `GuzzleHttp\Psr7\Utils::copyToString` `public static function copyToString(StreamInterface $stream, int $maxLen = -1): string` Copy the contents of a stream into a string until the given number of bytes have been read. ## `GuzzleHttp\Psr7\Utils::hash` `public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string` Calculate a hash of a stream. This method reads the entire stream to calculate a rolling hash, based on PHP's `hash_init` functions. ## `GuzzleHttp\Psr7\Utils::modifyRequest` `public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface` Clone and modify a request with the given changes. This method is useful for reducing the number of clones needed to mutate a message. - method: (string) Changes the HTTP method. - set_headers: (array) Sets the given headers. - remove_headers: (array) Remove the given headers. - body: (mixed) Sets the given body. Present non-null values are converted with `GuzzleHttp\Psr7\Utils::streamFor()`, including scalar values, resources, streams, iterators, callable arrays, closures, invokable objects, and objects with `__toString()`. String inputs remain literal bodies. - uri: (UriInterface) Set the URI. - query: (string) Set the query string value of the URI. - version: (string) Set the protocol version. ## `GuzzleHttp\Psr7\Utils::readLine` `public static function readLine(StreamInterface $stream, ?int $maxLength = null): string` Read a line from the stream up to the maximum allowed buffer length. ## `GuzzleHttp\Psr7\Utils::redactUserInfo` `public static function redactUserInfo(UriInterface $uri): UriInterface` Redact the password in the user info part of a URI. ## `GuzzleHttp\Psr7\Utils::streamFor` `public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource = '', array $options = []): StreamInterface` Create a new stream based on the input type. Options is an associative array that can contain the following keys: - metadata: Array of custom metadata. - size: Size of the stream. This method accepts the following `$resource` types: - `Psr\Http\Message\StreamInterface`: Returns the value as-is. - `string`: Creates a stream object that uses the given string as the contents. - `resource`: Creates a stream object that wraps the given PHP stream resource. - `Iterator`: If the provided value implements `Iterator`, then a read-only stream object will be created that wraps the given iterable. Each time the stream is read from, data from the iterator will fill a buffer and will be continuously called until the buffer is equal to the requested read size. Subsequent read calls will first read from the buffer and then call `next` on the underlying iterator until it is exhausted. - `object` with `__toString()`: If the object has the `__toString()` method, the object will be cast to a string and then a stream will be returned that uses the string value. - `NULL`: When `null` is passed, an empty stream object is returned. - `callable`: When a callable array, closure, or invokable object is passed and no earlier resource or object rule applies, a read-only stream object will be created that invokes the given callable. The callable is invoked with the suggested number of bytes to read. The callable can return fewer or more bytes than requested, but MUST return `false` or `null` when there is no more data to return. Any additional bytes will be buffered and used in subsequent reads. String inputs are always treated as string bodies, even when they name callable functions. ```php $stream = GuzzleHttp\Psr7\Utils::streamFor('foo'); $stream = GuzzleHttp\Psr7\Utils::streamFor(fopen('/path/to/file', 'r')); $generator = function ($bytes) { for ($i = 0; $i < $bytes; $i++) { yield ' '; } } $stream = GuzzleHttp\Psr7\Utils::streamFor($generator(100)); ``` ## `GuzzleHttp\Psr7\Utils::tryFopen` `public static function tryFopen(string $filename, string $mode): resource` Safely opens a PHP stream resource using a filename. When fopen fails, PHP normally raises a warning. This function adds an error handler that checks for errors and throws an exception instead. ## `GuzzleHttp\Psr7\Utils::tryGetContents` `public static function tryGetContents(resource $stream): string` Safely gets the contents of a given stream. When stream_get_contents fails, PHP normally raises a warning. This function adds an error handler that checks for errors and throws an exception instead. ## `GuzzleHttp\Psr7\Utils::uriFor` `public static function uriFor(string|UriInterface $uri): UriInterface` Returns a UriInterface for the given value. This function accepts a string or UriInterface and returns a UriInterface for the given value. If the value is already a UriInterface, it is returned as-is. ## `GuzzleHttp\Psr7\MimeType::fromFilename` `public static function fromFilename(string $filename): string|null` Determines the mimetype of a file by looking at its extension. ## `GuzzleHttp\Psr7\MimeType::fromExtension` `public static function fromExtension(string $extension): string|null` Maps a file extensions to a mimetype. # Additional URI Methods Aside from the standard `Psr\Http\Message\UriInterface` implementation in form of the `GuzzleHttp\Psr7\Uri` class, this library also provides additional functionality when working with URIs as static methods. ## URI Types An instance of `Psr\Http\Message\UriInterface` can either be an absolute URI or a relative reference. An absolute URI has a scheme. A relative reference is used to express a URI relative to another URI, the base URI. Relative references can be divided into several forms according to [RFC 3986 Section 4.2](https://datatracker.ietf.org/doc/html/rfc3986#section-4.2): - network-path references, e.g. `//example.com/path` - absolute-path references, e.g. `/path` - relative-path references, e.g. `subpath` The following methods can be used to identify the type of the URI. ### `GuzzleHttp\Psr7\Uri::isAbsolute` `public static function isAbsolute(UriInterface $uri): bool` Whether the URI is absolute, i.e. it has a scheme. ### `GuzzleHttp\Psr7\Uri::isNetworkPathReference` `public static function isNetworkPathReference(UriInterface $uri): bool` Whether the URI is a network-path reference. A relative reference that begins with two slash characters is termed an network-path reference. ### `GuzzleHttp\Psr7\Uri::isAbsolutePathReference` `public static function isAbsolutePathReference(UriInterface $uri): bool` Whether the URI is a absolute-path reference. A relative reference that begins with a single slash character is termed an absolute-path reference. ### `GuzzleHttp\Psr7\Uri::isRelativePathReference` `public static function isRelativePathReference(UriInterface $uri): bool` Whether the URI is a relative-path reference. A relative reference that does not begin with a slash character is termed a relative-path reference. ### `GuzzleHttp\Psr7\Uri::isSameDocumentReference` `public static function isSameDocumentReference(UriInterface $uri, ?UriInterface $base = null): bool` Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its fragment component, identical to the base URI. When no base URI is given, only an empty URI reference (apart from its fragment) is considered a same-document reference. ## URI Components Additional methods to work with URI components. ### `GuzzleHttp\Psr7\Uri::isDefaultPort` `public static function isDefaultPort(UriInterface $uri): bool` Whether the URI has the default port of the current scheme. `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used independently of the implementation. ### `GuzzleHttp\Psr7\Uri::composeComponents` `public static function composeComponents($scheme, $authority, $path, $query, $fragment): string` Composes a URI reference string from its various components according to [RFC 3986 Section 5.3](https://datatracker.ietf.org/doc/html/rfc3986#section-5.3). Usually this method does not need to be called manually but instead is used indirectly via `Psr\Http\Message\UriInterface::__toString`. ### `GuzzleHttp\Psr7\Uri::fromParts` `public static function fromParts(array $parts): UriInterface` Creates a URI from a hash of [`parse_url`](https://www.php.net/manual/en/function.parse-url.php) components. ### `GuzzleHttp\Psr7\Uri::withQueryValue` `public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface` Creates a new URI with a specific query string value. Any existing query string values that exactly match the provided key are removed and replaced with the given key value pair. A value of null will set the query string key without a value, e.g. "key" instead of "key=value". ### `GuzzleHttp\Psr7\Uri::withQueryValues` `public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface` Creates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an associative array of key => value. ### `GuzzleHttp\Psr7\Uri::withoutQueryValue` `public static function withoutQueryValue(UriInterface $uri, $key): UriInterface` Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the provided key are removed. ## Cross-Origin Detection `GuzzleHttp\Psr7\UriComparator` provides methods to determine if a modified URL should be considered cross-origin. ### `GuzzleHttp\Psr7\UriComparator::isCrossOrigin` `public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool` Determines if a modified URL should be considered cross-origin with respect to an original URL. Two URLs are cross-origin when their scheme, host, or effective port differ. Host comparison is case-insensitive, and missing ports use the default port for `http` or `https`. Other schemes do not receive implicit default ports. This helper only compares URI origins. It does not implement redirect handling or credential policy. ## Reference Resolution `GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according to [RFC 3986 Section 5](https://datatracker.ietf.org/doc/html/rfc3986#section-5). This is for example also what web browsers do when resolving a link in a website based on the current request URI. ### `GuzzleHttp\Psr7\UriResolver::resolve` `public static function resolve(UriInterface $base, UriInterface $rel): UriInterface` Converts the relative URI into a new URI that is resolved against the base URI. ### `GuzzleHttp\Psr7\UriResolver::removeDotSegments` `public static function removeDotSegments(string $path): string` Removes dot segments from a path and returns the new path according to [RFC 3986 Section 5.2.4](https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4). ### `GuzzleHttp\Psr7\UriResolver::relativize` `public static function relativize(UriInterface $base, UriInterface $target): UriInterface` Returns the target URI as a relative reference from the base URI. This method is the counterpart to resolve(): ```php (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target)) ``` One use-case is to use the current request URI as base URI and then generate relative links in your documents to reduce the document size or offer self-contained downloadable document archives. ```php $base = new Uri('http://example.com/a/b/'); echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'. echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'. echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'. echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'. ``` ## Normalization and Comparison `GuzzleHttp\Psr7\UriNormalizer` provides methods to normalize and compare URIs according to [RFC 3986 Section 6](https://datatracker.ietf.org/doc/html/rfc3986#section-6). ### `GuzzleHttp\Psr7\UriNormalizer::normalize` `public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS): UriInterface` Returns a normalized URI. The scheme and host component are already normalized to lowercase per PSR-7 UriInterface. This methods adds additional normalizations that can be configured with the `$flags` parameter which is a bitmask of normalizations to apply. The following normalizations are available: - `UriNormalizer::PRESERVING_NORMALIZATIONS` Default normalizations which only include the ones that preserve semantics. - `UriNormalizer::CAPITALIZE_PERCENT_ENCODING` All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized. Example: `http://example.org/a%c2%b1b` → `http://example.org/a%C2%B1b` - `UriNormalizer::DECODE_UNRESERVED_CHARACTERS` Decodes percent-encoded octets of unreserved characters. For consistency, percent-encoded octets in the ranges of ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers. Example: `http://example.org/%7Eusern%61me/` → `http://example.org/~username/` - `UriNormalizer::CONVERT_EMPTY_PATH` Converts the empty path to "/" for http and https URIs. Example: `http://example.org` → `http://example.org/` - `UriNormalizer::REMOVE_DEFAULT_HOST` Removes the default host of the given URI scheme from the URI. Only the "file" scheme defines the default host "localhost". All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile` are equivalent according to RFC 3986. Example: `file://localhost/myfile` → `file:///myfile` - `UriNormalizer::REMOVE_DEFAULT_PORT` Removes the default port of the given URI scheme from the URI. Example: `http://example.org:80/` → `http://example.org/` - `UriNormalizer::REMOVE_DOT_SEGMENTS` Removes unnecessary dot-segments. Dot-segments in relative-path references are not removed as it would change the semantics of the URI reference. Example: `http://example.org/../a/b/../c/./d.html` → `http://example.org/a/c/d.html` - `UriNormalizer::REMOVE_DUPLICATE_SLASHES` Paths which include two or more adjacent slashes are converted to one. Webservers usually ignore duplicate slashes and treat those URIs equivalent. But in theory those URIs do not need to be equivalent. So this normalization may change the semantics. Encoded slashes (%2F) are not removed. Example: `http://example.org//foo///bar.html` → `http://example.org/foo/bar.html` - `UriNormalizer::SORT_QUERY_PARAMETERS` Sort query parameters with their values in alphabetical order. However, the order of parameters in a URI may be significant (this is not defined by the standard). So this normalization is not safe and may change the semantics of the URI. Example: `?lang=en&article=fred` → `?article=fred&lang=en` ### `GuzzleHttp\Psr7\UriNormalizer::isEquivalent` `public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS): bool` Whether two URIs can be considered equivalent. Both URIs are normalized automatically before comparison with the given `$normalizations` bitmask. The method also accepts relative URI references and returns true when they are equivalent. This of course assumes they will be resolved against the same base URI. If this is not the case, determination of equivalence or difference of relative references does not mean anything. ## Security If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/psr7/security/policy) for more information. ## License Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. ## For Enterprise Available as part of the Tidelift Subscription The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver 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. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-psr7?utm_source=packagist-guzzlehttp-psr7&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) Guzzle PSR-7 Upgrade Guide ========================== 1.x to 2.0 ---------- Guzzle PSR-7 2.0 is a major release that removes deprecated APIs, raises the minimum PHP version, and adds PHP 7 parameter and return types. Applications that only depend on PSR-7 interfaces should usually need small changes. Applications that call helper functions, extend package classes, or pass invalid argument types need closer review. #### PHP Version and Dependencies Guzzle PSR-7 2.0 requires PHP `^7.2.5 || ^8.0`. Guzzle PSR-7 1.x supported PHP `>=5.4.0`. Composer dependency changes that can affect upgrades: - `ralouphie/getallheaders` v2 support was dropped; 2.0 requires `^3.0`. - `psr/http-factory:^1.0` is required because 2.0 ships PSR-17 factories through `GuzzleHttp\Psr7\HttpFactory`. #### PHP 7 Type Hints and Return Types Type hints and return types were added wherever possible. Please make sure: - You pass values of the documented type when calling methods and functions. - Classes that extend Guzzle PSR-7 classes update any overridden method signatures to remain compatible. - Code that expected package-specific `InvalidArgumentException` exceptions for invalid argument types may now receive PHP `TypeError` exceptions instead. Common examples include passing a real integer status code to `Response::__construct()` and passing a string method to `Request::__construct()`. #### Removed Function API The static API was introduced in 1.7.0 to mitigate problems with functions conflicting between global and local copies of the package. The function API was removed in 2.0.0, along with the Composer `files` autoload entry that loaded `src/functions_include.php`. Replace namespaced function calls with the corresponding static methods in the `GuzzleHttp\Psr7` namespace: ```php // Before: use function GuzzleHttp\Psr7\stream_for; $stream = stream_for('body'); // After: use GuzzleHttp\Psr7\Utils; $stream = Utils::streamFor('body'); ``` | Original Function | Replacement Method | |-------------------|--------------------| | `str` | `Message::toString` | | `uri_for` | `Utils::uriFor` | | `stream_for` | `Utils::streamFor` | | `parse_header` | `Header::parse` | | `normalize_header` | `Header::normalize` | | `modify_request` | `Utils::modifyRequest` | | `rewind_body` | `Message::rewindBody` | | `try_fopen` | `Utils::tryFopen` | | `copy_to_string` | `Utils::copyToString` | | `copy_to_stream` | `Utils::copyToStream` | | `hash` | `Utils::hash` | | `readline` | `Utils::readLine` | | `parse_request` | `Message::parseRequest` | | `parse_response` | `Message::parseResponse` | | `parse_query` | `Query::parse` | | `build_query` | `Query::build` | | `mimetype_from_filename` | `MimeType::fromFilename` | | `mimetype_from_extension` | `MimeType::fromExtension` | | `_parse_message` | `Message::parseMessage` | | `_parse_request_uri` | `Message::parseRequestUri` | | `get_message_body_summary` | `Message::bodySummary` | | `_caseless_remove` | `Utils::caselessRemove` | `Header::normalize()` remains the direct 2.0 replacement for `normalize_header()`. In newer 2.x versions, prefer `Header::splitList()` for new code. #### Deprecated URI Methods Removed The deprecated `Uri::resolve()` and `Uri::removeDotSegments()` methods were removed. Use `UriResolver` instead. ```php // Before: $resolved = Uri::resolve($base, '../path'); $path = Uri::removeDotSegments('/a/../b'); // After: use GuzzleHttp\Psr7\UriResolver; use GuzzleHttp\Psr7\Utils; $resolved = UriResolver::resolve($base, Utils::uriFor('../path')); $path = UriResolver::removeDotSegments('/a/../b'); ``` #### Stricter URI Validation Guzzle PSR-7 1.x automatically fixed a URI that combined an authority with a relative path by prepending `/` to the path. That deprecated behavior was removed in 2.0. Such URIs now throw `InvalidArgumentException`. ```php // Before: automatically converted to //example.com/foo. $uri = (new Uri())->withHost('example.com')->withPath('foo'); // After: make the absolute path explicit. $uri = (new Uri())->withHost('example.com')->withPath('/foo'); ``` #### Header Validation Header names are validated more strictly according to RFC 7230 token syntax. Names containing whitespace, `/`, `(`, `)`, `\\`, or other invalid characters are rejected. If you construct messages from untrusted or non-standard input, normalize or reject invalid header names before constructing `Request`, `Response`, or `ServerRequest` instances. #### Query String Boolean Serialization `Query::build()` now serializes booleans as `1` and `0`, matching `http_build_query()` behavior. ```php Query::build(['enabled' => true, 'disabled' => false]); // enabled=1&disabled=0 ``` In current 2.x versions, pass `false` as the third argument if you need textual boolean values: ```php Query::build(['enabled' => true, 'disabled' => false], PHP_QUERY_RFC3986, false); // enabled=true&disabled=false ``` #### Final Stream and Decorator Classes Several classes that were annotated with `@final` in 1.x are declared `final` in 2.0: - `AppendStream` - `BufferStream` - `CachingStream` - `DroppingStream` - `FnStream` - `InflateStream` - `LazyOpenStream` - `LimitStream` - `MultipartStream` - `NoSeekStream` - `PumpStream` - `StreamWrapper` If your code extends one of these classes, replace inheritance with composition. For custom streams, implement `Psr\Http\Message\StreamInterface` directly or use `GuzzleHttp\Psr7\StreamDecoratorTrait` in your own class. `Request`, `Response`, `ServerRequest`, `Stream`, `UploadedFile`, and `Uri` remain extendable in 2.0, but overridden methods must have compatible signatures. #### Public Constants and Internal Details Some constants that were public in 1.x are implementation details in 2.0: - `Stream::READABLE_MODES` - `Stream::WRITABLE_MODES` - `Uri::HTTP_DEFAULT_HOST` If your code used these constants, define application-specific constants instead of depending on package internals. #### Stream Behavior Changes `BufferStream::write()` returns `0` instead of `false` when the buffer exceeds its high-water mark. This keeps the method compatible with the `int` return type from `StreamInterface::write()`. Several stream `__toString()` implementations now catch `Throwable`. On PHP 7.4 and newer, exceptions thrown during stringification are rethrown. Avoid relying on `(string) $stream` to hide read failures; call `getContents()` or `read()` and handle exceptions when failures are possible. #### PSR-17 Factories Guzzle PSR-7 2.0 adds `GuzzleHttp\Psr7\HttpFactory`, an implementation of the PSR-17 factory interfaces from `psr/http-factory`. This is additive, but it is the reason for the new required dependency. For the full 2.0 diff, see https://github.com/guzzle/psr7/compare/1.8.1...2.0.0. { "name": "guzzlehttp/psr7", "description": "PSR-7 message implementation that also provides common utility methods", "license": "MIT", "keywords": [ "request", "response", "message", "stream", "http", "uri", "url", "psr-7" ], "authors": [ { "name": "Graham Campbell", "email": "hello@gjcampbell.co.uk", "homepage": "https://github.com/GrahamCampbell" }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "George Mponos", "email": "gmponos@gmail.com", "homepage": "https://github.com/gmponos" }, { "name": "Tobias Nyholm", "email": "tobias.nyholm@gmail.com", "homepage": "https://github.com/Nyholm" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", "homepage": "https://github.com/sagikazarmark" }, { "name": "Tobias Schultze", "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", "homepage": "https://sagikazarmark.hu" } ], "require": { "php": "^7.2.5 || ^8.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.1 || ^2.0", "ralouphie/getallheaders": "^3.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", "symfony/polyfill-php80": "^1.25" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "1.1.0", "jshttp/mime-db": "1.54.0.1", "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "provide": { "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "repositories": [ { "type": "package", "package": { "name": "jshttp/mime-db", "version": "1.54.0.1", "dist": { "type": "zip", "url": "https://codeload.github.com/jshttp/mime-db/zip/0a9fd0bfbc87a725ff638495839114e7807b7177" } } } ], "autoload": { "psr-4": { "GuzzleHttp\\Psr7\\": "src/" } }, "autoload-dev": { "psr-4": { "GuzzleHttp\\Tests\\Psr7\\": "tests/" } }, "config": { "allow-plugins": { "bamarni/composer-bin-plugin": true }, "preferred-install": "dist", "sort-packages": true }, "extra": { "bamarni-bin": { "bin-links": true, "forward-command": false } } } addStream($stream); } } public function __toString(): string { try { $this->rewind(); return $this->getContents(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } /** * Add a stream to the AppendStream * * @param StreamInterface $stream Stream to append. Must be readable. * * @throws \InvalidArgumentException if the stream is not readable */ public function addStream(StreamInterface $stream): void { if (!$stream->isReadable()) { throw new \InvalidArgumentException('Each stream must be readable'); } // The stream is only seekable if all streams are seekable if (!$stream->isSeekable()) { $this->seekable = false; } $this->streams[] = $stream; } public function getContents(): string { return Utils::copyToString($this); } /** * Closes each attached stream. */ public function close(): void { $this->pos = $this->current = 0; $this->seekable = true; foreach ($this->streams as $stream) { $stream->close(); } $this->streams = []; } /** * Detaches each attached stream. * * Returns null as it's not clear which underlying stream resource to return. */ public function detach() { $this->pos = $this->current = 0; $this->seekable = true; foreach ($this->streams as $stream) { $stream->detach(); } $this->streams = []; return null; } public function tell(): int { return $this->pos; } /** * Tries to calculate the size by adding the size of each stream. * * If any of the streams do not return a valid number, then the size of the * append stream cannot be determined and null is returned. */ public function getSize(): ?int { $size = 0; foreach ($this->streams as $stream) { $s = $stream->getSize(); if ($s === null) { return null; } $size += $s; } return $size; } public function eof(): bool { return !$this->streams || ($this->current >= count($this->streams) - 1 && $this->streams[$this->current]->eof()); } public function rewind(): void { $this->seek(0); } /** * Attempts to seek to the given position. Only supports SEEK_SET. */ public function seek($offset, $whence = SEEK_SET): void { if (!\is_int($offset)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $offset.', \get_debug_type($offset) ); } if (!\is_int($whence)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $whence.', \get_debug_type($whence) ); } if (!$this->seekable) { throw new \RuntimeException('This AppendStream is not seekable'); } elseif ($whence !== SEEK_SET) { throw new \RuntimeException('The AppendStream can only seek with SEEK_SET'); } $this->pos = $this->current = 0; // Rewind each stream foreach ($this->streams as $i => $stream) { try { $stream->rewind(); } catch (\Exception $e) { throw new \RuntimeException('Unable to seek stream ' .$i.' of the AppendStream', 0, $e); } } // Seek to the actual position by reading from each stream while ($this->pos < $offset && !$this->eof()) { $result = $this->read(min(8096, $offset - $this->pos)); if ($result === '') { break; } } } /** * Reads from all of the appended streams until the length is met or EOF. */ public function read($length): string { if (!\is_int($length)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::read() is deprecated; guzzlehttp/psr7 3.0 requires int for $length.', \get_debug_type($length) ); } if ($this->streams === []) { return ''; } $buffer = ''; $total = count($this->streams) - 1; $remaining = $length; $progressToNext = false; while ($remaining > 0) { // Progress to the next stream if needed. if ($progressToNext || $this->streams[$this->current]->eof()) { $progressToNext = false; if ($this->current === $total) { break; } ++$this->current; } $result = $this->streams[$this->current]->read($remaining); if ($result === '') { $progressToNext = true; continue; } $buffer .= $result; $remaining = $length - strlen($buffer); } $this->pos += strlen($buffer); return $buffer; } public function isReadable(): bool { return true; } public function isWritable(): bool { return false; } public function isSeekable(): bool { return $this->seekable; } public function write($string): int { if (!\is_string($string)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::write() is deprecated; guzzlehttp/psr7 3.0 requires string for $string.', \get_debug_type($string) ); } throw new \RuntimeException('Cannot write to an AppendStream'); } /** * @return mixed */ public function getMetadata($key = null) { if ($key !== null && !\is_string($key)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::getMetadata() is deprecated; guzzlehttp/psr7 3.0 requires string|null for $key.', \get_debug_type($key) ); } return $key ? null : []; } } hwm = $hwm; } public function __toString(): string { return $this->getContents(); } public function getContents(): string { $buffer = $this->buffer; $this->buffer = ''; return $buffer; } public function close(): void { $this->buffer = ''; } public function detach() { $this->close(); return null; } public function getSize(): ?int { return strlen($this->buffer); } public function isReadable(): bool { return true; } public function isWritable(): bool { return true; } public function isSeekable(): bool { return false; } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { if (!\is_int($offset)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $offset.', \get_debug_type($offset) ); } if (!\is_int($whence)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $whence.', \get_debug_type($whence) ); } throw new \RuntimeException('Cannot seek a BufferStream'); } public function eof(): bool { return strlen($this->buffer) === 0; } public function tell(): int { throw new \RuntimeException('Cannot determine the position of a BufferStream'); } /** * Reads data from the buffer. */ public function read($length): string { if (!\is_int($length)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::read() is deprecated; guzzlehttp/psr7 3.0 requires int for $length.', \get_debug_type($length) ); } $currentLength = strlen($this->buffer); if ($length >= $currentLength) { // No need to slice the buffer because we don't have enough data. $result = $this->buffer; $this->buffer = ''; } else { // Slice up the result to provide a subset of the buffer. $result = substr($this->buffer, 0, $length); $this->buffer = substr($this->buffer, $length); } return $result; } /** * Writes data to the buffer. */ public function write($string): int { if (!\is_string($string)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::write() is deprecated; guzzlehttp/psr7 3.0 requires string for $string.', \get_debug_type($string) ); } $this->buffer .= $string; if (strlen($this->buffer) >= $this->hwm) { return 0; } return strlen($string); } /** * @return mixed */ public function getMetadata($key = null) { if ($key !== null && !\is_string($key)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::getMetadata() is deprecated; guzzlehttp/psr7 3.0 requires string|null for $key.', \get_debug_type($key) ); } if ($key === 'hwm') { return $this->hwm; } return $key ? null : []; } } remoteStream = $stream; $this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+')); } public function getSize(): ?int { if ($this->detached) { return null; } $remoteSize = $this->remoteStream->getSize(); if (null === $remoteSize) { return null; } return max($this->stream->getSize(), $remoteSize); } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { if (!\is_int($offset)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $offset.', \get_debug_type($offset) ); } if (!\is_int($whence)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $whence.', \get_debug_type($whence) ); } if ($whence === SEEK_SET) { $byte = $offset; } elseif ($whence === SEEK_CUR) { $byte = $offset + $this->tell(); } elseif ($whence === SEEK_END) { $size = $this->remoteStream->getSize(); if ($size === null) { $size = $this->cacheEntireStream(); } $byte = $size + $offset; } else { throw new \InvalidArgumentException('Invalid whence'); } $diff = $byte - $this->stream->getSize(); if ($diff > 0) { // Read the remoteStream until we have read in at least the amount // of bytes requested, or we reach the end of the file. while ($diff > 0 && !$this->remoteStream->eof()) { $previousSize = $this->stream->getSize(); $previousSkipReadBytes = $this->skipReadBytes; $data = $this->read($diff); $currentSize = $this->stream->getSize(); if ($data === '' && $currentSize === $previousSize && $this->skipReadBytes === $previousSkipReadBytes) { break; } $diff = $byte - $currentSize; } } else { // We can just do a normal seek since we've already seen this byte. $this->stream->seek($byte); } } public function read($length): string { if (!\is_int($length)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::read() is deprecated; guzzlehttp/psr7 3.0 requires int for $length.', \get_debug_type($length) ); } // Perform a regular read on any previously read data from the buffer $data = $this->stream->read($length); $remaining = $length - strlen($data); // More data was requested so read from the remote stream if ($remaining) { // If data was written to the buffer in a position that would have // been filled from the remote stream, then we must skip bytes on // the remote stream to emulate overwriting bytes from that // position. This mimics the behavior of other PHP stream wrappers. $remoteData = $this->remoteStream->read( $remaining + $this->skipReadBytes ); if ($this->skipReadBytes) { $len = strlen($remoteData); $remoteData = substr($remoteData, $this->skipReadBytes); $this->skipReadBytes = max(0, $this->skipReadBytes - $len); } $data .= $remoteData; // A short cache write would silently corrupt later replays, so fail loudly. if ($this->stream->write($remoteData) !== strlen($remoteData)) { throw new \RuntimeException('Unable to cache the entire read from the remote stream'); } } return $data; } public function write($string): int { if (!\is_string($string)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::write() is deprecated; guzzlehttp/psr7 3.0 requires string for $string.', \get_debug_type($string) ); } // When appending to the end of the currently read stream, you'll want // to skip bytes from being read from the remote stream to emulate // other stream wrappers. Basically replacing bytes of data of a fixed // length. $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell(); if ($overflow > 0) { $this->skipReadBytes += $overflow; } return $this->stream->write($string); } public function eof(): bool { return $this->stream->eof() && $this->remoteStream->eof(); } public function detach() { if ($this->detached) { return null; } $position = $this->tell(); $this->cacheEntireStream(); $this->stream->seek($position); $resource = $this->stream->detach(); $this->detached = true; return $resource; } /** * Close both the remote stream and buffer stream */ public function close(): void { $this->remoteStream->close(); $this->stream->close(); $this->detached = true; } private function cacheEntireStream(): int { $target = new FnStream(['write' => 'strlen']); Utils::copyToStream($this, $target); return $this->tell(); } } stream = $stream; $this->maxLength = $maxLength; } public function write($string): int { if (!\is_string($string)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::write() is deprecated; guzzlehttp/psr7 3.0 requires string for $string.', \get_debug_type($string) ); } $diff = $this->maxLength - $this->stream->getSize(); // Begin returning 0 when the underlying stream is too large. if ($diff <= 0) { return 0; } // Write the stream or a subset of the stream if needed. if (strlen($string) < $diff) { return $this->stream->write($string); } return $this->stream->write(substr($string, 0, $diff)); } } */ private $methods; /** * @param array $methods Hash of method name to a callable. */ public function __construct(array $methods) { $this->methods = $methods; // Create the callables on the class foreach ($methods as $name => $fn) { $this->{'_fn_'.$name} = $fn; } } /** * Lazily determine which methods are not implemented. * * @throws \BadMethodCallException */ public function __get(string $name): void { throw new \BadMethodCallException(str_replace('_fn_', '', $name) .'() is not implemented in the FnStream'); } /** * The close method is called on the underlying stream only if possible. */ public function __destruct() { if (isset($this->_fn_close)) { ($this->_fn_close)(); } } /** * An unserialize would allow the __destruct to run when the unserialized value goes out of scope. * * @throws \LogicException */ public function __wakeup(): void { throw new \LogicException('FnStream should never be unserialized'); } /** * Adds custom functionality to an underlying stream by intercepting * specific method calls. * * @param StreamInterface $stream Stream to decorate * @param array $methods Hash of method name to a callable * * @return FnStream */ public static function decorate(StreamInterface $stream, array $methods) { // If any of the required methods were not provided, then simply // proxy to the decorated stream. foreach (array_diff(self::SLOTS, array_keys($methods)) as $diff) { /** @var callable $callable */ $callable = [$stream, $diff]; $methods[$diff] = $callable; } return new self($methods); } public function __toString(): string { try { /** @var string */ return ($this->_fn___toString)(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } public function close(): void { ($this->_fn_close)(); } public function detach() { return ($this->_fn_detach)(); } public function getSize(): ?int { return ($this->_fn_getSize)(); } public function tell(): int { return ($this->_fn_tell)(); } public function eof(): bool { return ($this->_fn_eof)(); } public function isSeekable(): bool { return ($this->_fn_isSeekable)(); } public function rewind(): void { ($this->_fn_rewind)(); } public function seek($offset, $whence = SEEK_SET): void { if (!\is_int($offset)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $offset.', \get_debug_type($offset) ); } if (!\is_int($whence)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $whence.', \get_debug_type($whence) ); } ($this->_fn_seek)($offset, $whence); } public function isWritable(): bool { return ($this->_fn_isWritable)(); } public function write($string): int { if (!\is_string($string)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::write() is deprecated; guzzlehttp/psr7 3.0 requires string for $string.', \get_debug_type($string) ); } return ($this->_fn_write)($string); } public function isReadable(): bool { return ($this->_fn_isReadable)(); } public function read($length): string { if (!\is_int($length)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::read() is deprecated; guzzlehttp/psr7 3.0 requires int for $length.', \get_debug_type($length) ); } return ($this->_fn_read)($length); } public function getContents(): string { return ($this->_fn_getContents)(); } /** * @return mixed */ public function getMetadata($key = null) { if ($key !== null && !\is_string($key)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::getMetadata() is deprecated; guzzlehttp/psr7 3.0 requires string|null for $key.', \get_debug_type($key) ); } return ($this->_fn_getMetadata)($key); } } ]+>|[^=]+/', $kvp, $matches)) { $m = $matches[0]; if (isset($m[1])) { $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed); } else { $part[] = trim($m[0], $trimmed); } } } if ($part) { $params[] = $part; } } } return $params; } /** * Split a header value into semicolon-separated parameters. * * @return string[] */ private static function splitParameters(string $value): array { $values = []; $start = 0; $isQuoted = false; $isEscaped = false; for ($i = 0, $max = \strlen($value); $i < $max; ++$i) { $char = $value[$i]; if ($isEscaped) { $isEscaped = false; continue; } if ($isQuoted && $char === '\\') { $isEscaped = true; continue; } if ($char === '"') { $isQuoted = !$isQuoted; continue; } if (!$isQuoted && $char === ';') { $values[] = \substr($value, $start, $i - $start); $start = $i + 1; } } $values[] = \substr($value, $start); return $values; } /** * Converts an array of header values that may contain comma separated * headers into an array of headers with no comma separated values. * * @param string|array $header Header to normalize. * * @deprecated Use self::splitList() instead. */ public static function normalize($header): array { \trigger_deprecation('guzzlehttp/psr7', '2.3', 'Header::normalize() is deprecated and will be removed in guzzlehttp/psr7 3.0. Use Header::splitList() instead.'); $result = []; foreach ((array) $header as $value) { foreach (self::splitList($value) as $parsed) { $result[] = $parsed; } } return $result; } /** * Splits a HTTP header defined to contain a comma-separated list into * each individual value. Empty values will be removed. * * Example headers include 'accept', 'cache-control' and 'if-none-match'. * * This method must not be used to parse headers that are not defined as * a list, such as 'user-agent' or 'set-cookie'. * * @param string|string[] $values Header value as returned by MessageInterface::getHeader() * * @return string[] */ public static function splitList($values): array { if (!\is_array($values)) { $values = [$values]; } $result = []; foreach ($values as $value) { if (!\is_string($value)) { throw new \TypeError('$header must either be a string or an array containing strings.'); } $v = ''; $isQuoted = false; $isEscaped = false; for ($i = 0, $max = \strlen($value); $i < $max; ++$i) { if ($isEscaped) { $v .= $value[$i]; $isEscaped = false; continue; } if (!$isQuoted && $value[$i] === ',') { $v = \trim($v, " \n\r\t\0\x0B"); if ($v !== '') { $result[] = $v; } $v = ''; continue; } if ($isQuoted && $value[$i] === '\\') { $isEscaped = true; $v .= $value[$i]; continue; } if ($value[$i] === '"') { $isQuoted = !$isQuoted; $v .= $value[$i]; continue; } $v .= $value[$i]; } $v = \trim($v, " \n\r\t\0\x0B"); if ($v !== '') { $result[] = $v; } } return $result; } } getSize(); } return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType); } public function createStream(string $content = ''): StreamInterface { return Utils::streamFor($content); } public function createStreamFromFile(string $file, string $mode = 'r'): StreamInterface { try { $resource = Utils::tryFopen($file, $mode); } catch (\RuntimeException $e) { if ('' === $mode || false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], true)) { throw new \InvalidArgumentException(sprintf('Invalid file opening mode "%s"', $mode), 0, $e); } throw $e; } return Utils::streamFor($resource); } public function createStreamFromResource($resource): StreamInterface { return Utils::streamFor($resource); } public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface { if (empty($method)) { if (!empty($serverParams['REQUEST_METHOD'])) { $method = $serverParams['REQUEST_METHOD']; } else { throw new \InvalidArgumentException('Cannot determine HTTP method'); } } return new ServerRequest($method, $uri, [], null, '1.1', $serverParams); } public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface { return new Response($code, [], null, '1.1', $reasonPhrase); } public function createRequest(string $method, $uri): RequestInterface { return new Request($method, $uri); } public function createUri(string $uri = ''): UriInterface { return new Uri($uri); } } 15 + 32]); $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource)); } } filename = $filename; $this->mode = $mode; // unsetting the property forces the first access to go through // __get(). unset($this->stream); } /** * Creates the underlying stream lazily when required. */ protected function createStream(): StreamInterface { return Utils::streamFor(Utils::tryFopen($this->filename, $this->mode)); } } stream = $stream; $this->setLimit($limit); $this->setOffset($offset); } public function eof(): bool { // Always return true if the underlying stream is EOF if ($this->stream->eof()) { return true; } // No limit and the underlying stream is not at EOF if ($this->limit === -1) { return false; } return $this->stream->tell() >= $this->offset + $this->limit; } /** * Returns the size of the limited subset of data */ public function getSize(): ?int { if (null === ($length = $this->stream->getSize())) { return null; } $size = $length - $this->offset; if ($this->limit !== -1) { $size = min($this->limit, $size); } return max(0, $size); } /** * Allow for a bounded seek on the read limited stream */ public function seek($offset, $whence = SEEK_SET): void { if (!\is_int($offset)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $offset.', \get_debug_type($offset) ); } if (!\is_int($whence)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $whence.', \get_debug_type($whence) ); } if ($whence !== SEEK_SET || $offset < 0) { throw new \RuntimeException(sprintf( 'Cannot seek to offset %s with whence %s', $offset, $whence )); } $offset += $this->offset; if ($this->limit !== -1) { if ($offset > $this->offset + $this->limit) { $offset = $this->offset + $this->limit; } } $this->stream->seek($offset); } /** * Give a relative tell() */ public function tell(): int { return $this->stream->tell() - $this->offset; } /** * Set the offset to start limiting from * * @param int $offset Offset to seek to and begin byte limiting from * * @throws \RuntimeException if the stream cannot be seeked. */ public function setOffset(int $offset): void { $current = $this->stream->tell(); if ($current !== $offset) { // If the stream cannot seek to the offset position, then read to it if ($this->stream->isSeekable()) { $this->stream->seek($offset); } elseif ($current > $offset) { throw new \RuntimeException("Could not seek to stream offset $offset"); } else { $this->stream->read($offset - $current); } } $this->offset = $offset; } /** * Set the limit of bytes that the decorator allows to be read from the * stream. * * @param int $limit Number of bytes to allow to be read from the stream. * Use -1 for no limit. */ public function setLimit(int $limit): void { $this->limit = $limit; } public function read($length): string { if (!\is_int($length)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::read() is deprecated; guzzlehttp/psr7 3.0 requires int for $length.', \get_debug_type($length) ); } if ($this->limit === -1) { return $this->stream->read($length); } // Check if the current position is less than the total allowed // bytes + original offset $remaining = ($this->offset + $this->limit) - $this->stream->tell(); if ($remaining > 0) { // Only return the amount of requested data, ensuring that the byte // limit is not exceeded return $this->stream->read(min($remaining, $length)); } return ''; } } getMethod().' ' .$message->getRequestTarget(), " \n\r\t\0\x0B") .' HTTP/'.$message->getProtocolVersion(); if (!$message->hasHeader('host')) { $msg .= "\r\nHost: ".$message->getUri()->getHost(); } } elseif ($message instanceof ResponseInterface) { $msg = 'HTTP/'.$message->getProtocolVersion().' ' .$message->getStatusCode().' ' .$message->getReasonPhrase(); } else { throw new \InvalidArgumentException('Unknown message type'); } foreach ($message->getHeaders() as $name => $values) { if (is_string($name) && Utils::asciiToLower($name) === 'set-cookie') { foreach ($values as $value) { $msg .= "\r\n{$name}: ".$value; } } else { $msg .= "\r\n{$name}: ".implode(', ', $values); } } return "{$msg}\r\n\r\n".$message->getBody(); } /** * Get a short summary of the message body. * * Will return `null` if the response is not printable. * * @param MessageInterface $message The message to get the body summary * @param int $truncateAt The maximum allowed size of the summary */ public static function bodySummary(MessageInterface $message, int $truncateAt = 120): ?string { $body = $message->getBody(); if (!$body->isSeekable() || !$body->isReadable()) { return null; } $size = $body->getSize(); if ($size === 0) { return null; } $body->rewind(); $summary = $body->read($truncateAt); if ($size > $truncateAt) { if (preg_match('//u', $summary) !== 1) { $summary = self::trimTrailingIncompleteUtf8Character($summary, $body->read(3)); } $summary .= ' (truncated...)'; } $body->rewind(); // Matches any printable character, including unicode characters: // letters, marks, numbers, punctuation, spacing, and separators. if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/u', $summary) !== 0) { return null; } return $summary; } /** * Trims a partial UTF-8 character from the end of a truncated string. */ private static function trimTrailingIncompleteUtf8Character(string $summary, string $lookahead): string { $length = strlen($summary); if ($length === 0) { return $summary; } $start = $length - 1; while ($start >= 0) { $byte = ord($summary[$start]); if ($byte < 0x80 || $byte > 0xBF) { break; } --$start; } if ($start < 0) { return $summary; } $lead = ord($summary[$start]); if ($lead >= 0xC2 && $lead <= 0xDF) { $expectedLength = 2; } elseif ($lead >= 0xE0 && $lead <= 0xEF) { $expectedLength = 3; } elseif ($lead >= 0xF0 && $lead <= 0xF4) { $expectedLength = 4; } else { return $summary; } $availableLength = $length - $start; if ($availableLength >= $expectedLength) { return $summary; } $sequence = substr($summary, $start).substr($lookahead, 0, $expectedLength - $availableLength); if (strlen($sequence) !== $expectedLength || preg_match('//u', $sequence) !== 1) { return $summary; } return substr($summary, 0, $start); } /** * Attempts to rewind a message body and throws an exception on failure. * * The body of the message will only be rewound if a call to `tell()` * returns a value other than `0`. * * @param MessageInterface $message Message to rewind * * @throws \RuntimeException */ public static function rewindBody(MessageInterface $message): void { $body = $message->getBody(); if ($body->tell()) { $body->rewind(); } } /** * Parses an HTTP message into an associative array. * * The array contains the "start-line" key containing the start line of * the message, "headers" key containing an associative array of header * array values, and a "body" key containing the body of the message. * * @param string $message HTTP request or response to parse. */ public static function parseMessage(string $message): array { if (!$message) { throw new \InvalidArgumentException('Invalid message'); } $message = ltrim($message, "\r\n"); $messageParts = preg_split("/\r?\n\r?\n/", $message, 2); if ($messageParts === false) { throw new \RuntimeException('Unable to split HTTP message: '.preg_last_error_msg()); } if (count($messageParts) !== 2) { throw new \InvalidArgumentException('Invalid message: Missing header delimiter'); } [$rawHeaders, $body] = $messageParts; $rawHeaders .= "\r\n"; // Put back the delimiter we split previously $headerParts = preg_split("/\r?\n/", $rawHeaders, 2); if ($headerParts === false) { throw new \RuntimeException('Unable to split HTTP message headers: '.preg_last_error_msg()); } if (count($headerParts) !== 2) { throw new \InvalidArgumentException('Invalid message: Missing status line'); } [$startLine, $rawHeaders] = $headerParts; $versionMatch = preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches); if ($versionMatch === false) { throw new \RuntimeException('Unable to parse HTTP start line: '.preg_last_error_msg()); } if ($versionMatch === 1 && $matches[1] === '1.0') { // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0 $rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders); if ($rawHeaders === null) { throw new \RuntimeException('Unable to unfold HTTP headers: '.preg_last_error_msg()); } } /** @var array[] $headerLines */ $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER); if ($count === false) { throw new \RuntimeException('Unable to parse HTTP headers: '.preg_last_error_msg()); } // If these aren't the same, then one line didn't match and there's an invalid header. if ($count !== substr_count($rawHeaders, "\n")) { // Folding is deprecated, see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4 $hasFoldedHeader = preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders); if ($hasFoldedHeader === false) { throw new \RuntimeException('Unable to inspect HTTP header folding: '.preg_last_error_msg()); } if ($hasFoldedHeader === 1) { throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding'); } throw new \InvalidArgumentException('Invalid header syntax'); } $headers = []; foreach ($headerLines as $headerLine) { $headers[$headerLine[1]][] = $headerLine[2]; } return [ 'start-line' => $startLine, 'headers' => $headers, 'body' => $body, ]; } /** * Constructs a URI for an HTTP request message. * * @param string $path Path from the start-line * @param array $headers Array of headers (each value an array). */ public static function parseRequestUri(string $path, array $headers): string { $host = self::getHostFromHeaders($headers); // If no host is found, then a full URI cannot be constructed. // Collapse leading slashes so an origin-form target cannot be // parsed as a network-path reference with its own authority. if ($host === null) { return self::normalizePathForOriginForm($path); } $scheme = substr($host, -4) === ':443' ? 'https' : 'http'; return $scheme.'://'.$host.'/'.ltrim($path, '/'); } private static function normalizePathForOriginForm(string $path): string { if (0 === strpos($path, '//')) { return '/'.ltrim($path, '/'); } return $path; } /** * @param array $headers Array of headers (each value an array). */ private static function getHostFromHeaders(array $headers): ?string { $hostKey = array_filter(array_keys($headers), function ($k) { // Numeric array keys are converted to int by PHP. $k = (string) $k; return Utils::asciiToLower($k) === 'host'; }); if (!$hostKey) { return null; } $host = $headers[reset($hostKey)][0]; if (!is_string($host) || Rfc7230::parseHostHeader($host) === null) { throw new \InvalidArgumentException('Invalid request string'); } return $host; } /** * Parses a request message string into a request object. * * @param string $message Request message string. */ public static function parseRequest(string $message): RequestInterface { $data = self::parseMessage($message); if (strpbrk($data['start-line'], "\r\n") !== false) { throw new \InvalidArgumentException('Invalid request string'); } $matches = []; $requestStartLineMatch = preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches); if ($requestStartLineMatch === false) { throw new \RuntimeException('Unable to parse request start line: '.preg_last_error_msg()); } if ($requestStartLineMatch === 0) { throw new \InvalidArgumentException('Invalid request string'); } $parts = explode(' ', $data['start-line'], 3); $version = isset($parts[2]) ? explode('/', $parts[2])[1] : '1.1'; $request = new Request( $parts[0], $matches[1] === '/' ? self::parseRequestUri($parts[1], $data['headers']) : $parts[1], $data['headers'], $data['body'], $version ); return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]); } /** * Parses a response message string into a response object. * * @param string $message Response message string. */ public static function parseResponse(string $message): ResponseInterface { $data = self::parseMessage($message); if (strpbrk($data['start-line'], "\r\n") !== false) { throw new \InvalidArgumentException('Invalid response string'); } // According to https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2 // the space between status-code and reason-phrase is required. But // browsers accept responses without space and reason as well. $responseStartLineMatch = preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/D', $data['start-line']); if ($responseStartLineMatch === false) { throw new \RuntimeException('Unable to parse response start line: '.preg_last_error_msg()); } if ($responseStartLineMatch === 0) { throw new \InvalidArgumentException('Invalid response string: '.$data['start-line']); } $parts = explode(' ', $data['start-line'], 3); return new Response( (int) $parts[1], $data['headers'], $data['body'], explode('/', $parts[0])[1], $parts[2] ?? null ); } } array of values */ private $headers = []; /** @var string[] Map of lowercase header name => original name at registration */ private $headerNames = []; /** @var string */ private $protocol = '1.1'; /** @var StreamInterface|null */ private $stream; public function getProtocolVersion(): string { return $this->protocol; } /** * @return static */ public function withProtocolVersion($version): MessageInterface { if (!\is_string($version)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to MessageInterface::withProtocolVersion() is deprecated; guzzlehttp/psr7 3.0 requires string.', \get_debug_type($version) ); } $this->assertProtocolVersion($version); if ($this->protocol === $version) { return $this; } $new = clone $this; $new->protocol = $version; return $new; } public function getHeaders(): array { return $this->headers; } public function hasHeader($header): bool { return isset($this->headerNames[Utils::asciiToLower($header)]); } public function getHeader($header): array { $header = Utils::asciiToLower($header); if (!isset($this->headerNames[$header])) { return []; } $header = $this->headerNames[$header]; return $this->headers[$header]; } public function getHeaderLine($header): string { return implode(', ', $this->getHeader($header)); } /** * @return static */ public function withHeader($header, $value): MessageInterface { $this->assertHeader($header); $values = \is_array($value) ? $value : [$value]; foreach ($values as $item) { if (!\is_string($item) && (\is_scalar($item) || $item === null)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to MessageInterface::withHeader() is deprecated; guzzlehttp/psr7 3.0 requires string|string[].', \get_debug_type($item) ); break; } } $value = $this->normalizeHeaderValue($value); $normalized = Utils::asciiToLower($header); $new = clone $this; if (isset($new->headerNames[$normalized])) { unset($new->headers[$new->headerNames[$normalized]]); } $new->headerNames[$normalized] = $header; $new->headers[$header] = $value; return $new; } /** * @return static */ public function withAddedHeader($header, $value): MessageInterface { $this->assertHeader($header); $values = \is_array($value) ? $value : [$value]; foreach ($values as $item) { if (!\is_string($item) && (\is_scalar($item) || $item === null)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to MessageInterface::withAddedHeader() is deprecated; guzzlehttp/psr7 3.0 requires string|string[].', \get_debug_type($item) ); break; } } $value = $this->normalizeHeaderValue($value); $normalized = Utils::asciiToLower($header); $new = clone $this; if (isset($new->headerNames[$normalized])) { $header = $this->headerNames[$normalized]; $new->headers[$header] = array_merge($this->headers[$header], $value); } else { $new->headerNames[$normalized] = $header; $new->headers[$header] = $value; } return $new; } /** * @return static */ public function withoutHeader($header): MessageInterface { $normalized = Utils::asciiToLower($header); if (!isset($this->headerNames[$normalized])) { return $this; } $header = $this->headerNames[$normalized]; $new = clone $this; unset($new->headers[$header], $new->headerNames[$normalized]); return $new; } public function getBody(): StreamInterface { if (!$this->stream) { $this->stream = Utils::streamFor(''); } return $this->stream; } /** * @return static */ public function withBody(StreamInterface $body): MessageInterface { if ($body === $this->stream) { return $this; } $new = clone $this; $new->stream = $body; return $new; } /** * @param (string|string[])[] $headers */ private function setHeaders(array $headers): void { $this->headerNames = $this->headers = []; foreach ($headers as $header => $value) { // Numeric array keys are converted to int by PHP. $header = (string) $header; $this->assertHeader($header); $values = \is_array($value) ? $value : [$value]; foreach ($values as $item) { if (!\is_string($item) && (\is_scalar($item) || $item === null)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to %s::__construct() is deprecated; guzzlehttp/psr7 3.0 requires string|string[].', \get_debug_type($item), static::class ); break; } } $value = $this->normalizeHeaderValue($value); $normalized = Utils::asciiToLower($header); if (isset($this->headerNames[$normalized])) { $header = $this->headerNames[$normalized]; $this->headers[$header] = array_merge($this->headers[$header], $value); } else { $this->headerNames[$normalized] = $header; $this->headers[$header] = $value; } } } /** * @param mixed $value * * @return string[] */ private function normalizeHeaderValue($value): array { if (is_array($value) && $value === []) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing an empty array as a header value is deprecated; guzzlehttp/psr7 3.0 rejects empty header value arrays.' ); } if (!is_array($value)) { return $this->trimAndValidateHeaderValues([$value]); } return $this->trimAndValidateHeaderValues($value); } /** * Trims whitespace from the header values. * * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field. * * header-field = field-name ":" OWS field-value OWS * OWS = *( SP / HTAB ) * * @param mixed[] $values Header values * * @return string[] Trimmed header values * * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4 */ private function trimAndValidateHeaderValues(array $values): array { return array_map(function ($value) { if (!is_scalar($value) && null !== $value) { throw new \InvalidArgumentException(sprintf( 'Header value must be scalar or null but %s provided.', is_object($value) ? get_class($value) : gettype($value) )); } // Convert non-finite floats explicitly, as implicit coercion of // NAN emits a warning on PHP 8.5. if (is_float($value) && !is_finite($value)) { $value = is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF'); } $trimmed = trim((string) $value, " \t"); $this->assertValue($trimmed); return $trimmed; }, array_values($values)); } /** * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2 * * @param mixed $header */ private function assertHeader($header): void { if (!is_string($header)) { throw new \InvalidArgumentException(sprintf( 'Header name must be a string but %s provided.', is_object($header) ? get_class($header) : gettype($header) )); } if (!preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) { throw new \InvalidArgumentException( sprintf('"%s" is not valid header name.', $header) ); } } /** * @param mixed $version */ private function assertProtocolVersion($version): void { if (is_string($version)) { $this->assertNoLineSeparators($version, 'Protocol version'); } } private function assertNoLineSeparators(string $value, string $field): void { if (strpbrk($value, "\r\n") !== false) { throw new \InvalidArgumentException($field.' must not contain CR or LF characters.'); } } /** * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2 * * field-value = *( field-content / obs-fold ) * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] * field-vchar = VCHAR / obs-text * VCHAR = %x21-7E * obs-text = %x80-FF * obs-fold = CRLF 1*( SP / HTAB ) */ private function assertValue(string $value): void { // The regular expression intentionally does not support the obs-fold production, because as // per RFC 7230#3.2.4: // // A sender MUST NOT generate a message that includes // line folding (i.e., that has any field-value that contains a match to // the obs-fold rule) unless the message is intended for packaging // within the message/http media type. // // Clients must not send a request with line folding and a server sending folded headers is // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting // folding is not likely to break any legitimate use case. if (!preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D', $value)) { throw new \InvalidArgumentException( sprintf('"%s" is not valid header value.', $value) ); } } } 'application/vnd.lotus-1-2-3', '1km' => 'application/vnd.1000minds.decision-model+xml', '210' => 'model/step', '3dml' => 'text/vnd.in3d.3dml', '3ds' => 'image/x-3ds', '3g2' => 'video/3gpp2', '3gp' => 'video/3gpp', '3gpp' => 'video/3gpp', '3mf' => 'model/3mf', '7z' => 'application/x-7z-compressed', '7zip' => 'application/x-7z-compressed', 'aab' => 'application/x-authorware-bin', 'aac' => 'audio/aac', 'aam' => 'application/x-authorware-map', 'aas' => 'application/x-authorware-seg', 'abw' => 'application/x-abiword', 'ac' => 'application/pkix-attr-cert', 'ac3' => 'audio/ac3', 'acc' => 'application/vnd.americandynamics.acc', 'ace' => 'application/x-ace-compressed', 'acu' => 'application/vnd.acucobol', 'acutc' => 'application/vnd.acucorp', 'adp' => 'audio/adpcm', 'adts' => 'audio/aac', 'aep' => 'application/vnd.audiograph', 'afm' => 'application/x-font-type1', 'afp' => 'application/vnd.ibm.modcap', 'age' => 'application/vnd.age', 'ahead' => 'application/vnd.ahead.space', 'ai' => 'application/postscript', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'air' => 'application/vnd.adobe.air-application-installer-package+zip', 'ait' => 'application/vnd.dvb.ait', 'ami' => 'application/vnd.amiga.ami', 'aml' => 'application/automationml-aml+xml', 'amlx' => 'application/automationml-amlx+zip', 'amr' => 'audio/amr', 'apk' => 'application/vnd.android.package-archive', 'apng' => 'image/apng', 'appcache' => 'text/cache-manifest', 'appinstaller' => 'application/appinstaller', 'application' => 'application/x-ms-application', 'appx' => 'application/appx', 'appxbundle' => 'application/appxbundle', 'apr' => 'application/vnd.lotus-approach', 'arc' => 'application/x-freearc', 'arj' => 'application/x-arj', 'asc' => 'application/pgp-keys', 'asf' => 'video/x-ms-asf', 'asm' => 'text/x-asm', 'aso' => 'application/vnd.accpac.simply.aso', 'asx' => 'video/x-ms-asf', 'atc' => 'application/vnd.acucorp', 'atom' => 'application/atom+xml', 'atomcat' => 'application/atomcat+xml', 'atomdeleted' => 'application/atomdeleted+xml', 'atomsvc' => 'application/atomsvc+xml', 'atx' => 'application/vnd.antix.game-component', 'au' => 'audio/basic', 'avci' => 'image/avci', 'avcs' => 'image/avcs', 'avi' => 'video/x-msvideo', 'avif' => 'image/avif', 'aw' => 'application/applixware', 'azf' => 'application/vnd.airzip.filesecure.azf', 'azs' => 'application/vnd.airzip.filesecure.azs', 'azv' => 'image/vnd.airzip.accelerator.azv', 'azw' => 'application/vnd.amazon.ebook', 'b16' => 'image/vnd.pco.b16', 'bary' => 'model/vnd.bary', 'bat' => 'application/x-msdownload', 'bcpio' => 'application/x-bcpio', 'bdf' => 'application/x-font-bdf', 'bdm' => 'application/vnd.syncml.dm+wbxml', 'bdo' => 'application/vnd.nato.bindingdataobject+xml', 'bdoc' => 'application/bdoc', 'bed' => 'application/vnd.realvnc.bed', 'bh2' => 'application/vnd.fujitsu.oasysprs', 'bin' => 'application/octet-stream', 'blb' => 'application/x-blorb', 'blend' => 'application/x-blender', 'blorb' => 'application/x-blorb', 'bmi' => 'application/vnd.bmi', 'bmml' => 'application/vnd.balsamiq.bmml+xml', 'bmp' => 'image/bmp', 'book' => 'application/vnd.framemaker', 'box' => 'application/vnd.previewsystems.box', 'boz' => 'application/x-bzip2', 'bpk' => 'application/octet-stream', 'bpmn' => 'application/octet-stream', 'brush' => 'application/vnd.procreate.brush', 'brushset' => 'application/vnd.procreate.brushset', 'bsp' => 'model/vnd.valve.source.compiled-map', 'btf' => 'image/prs.btif', 'btif' => 'image/prs.btif', 'buffer' => 'application/octet-stream', 'bz' => 'application/x-bzip', 'bz2' => 'application/x-bzip2', 'c' => 'text/x-c', 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', 'c4d' => 'application/vnd.clonk.c4group', 'c4f' => 'application/vnd.clonk.c4group', 'c4g' => 'application/vnd.clonk.c4group', 'c4p' => 'application/vnd.clonk.c4group', 'c4u' => 'application/vnd.clonk.c4group', 'cab' => 'application/vnd.ms-cab-compressed', 'caf' => 'audio/x-caf', 'cap' => 'application/vnd.tcpdump.pcap', 'car' => 'application/vnd.curl.car', 'cat' => 'application/vnd.ms-pki.seccat', 'cb7' => 'application/x-cbr', 'cba' => 'application/x-cbr', 'cbr' => 'application/x-cbr', 'cbt' => 'application/x-cbr', 'cbz' => 'application/x-cbr', 'cc' => 'text/x-c', 'cco' => 'application/x-cocoa', 'cct' => 'application/x-director', 'ccxml' => 'application/ccxml+xml', 'cdbcmsg' => 'application/vnd.contact.cmsg', 'cdf' => 'application/x-netcdf', 'cdfx' => 'application/cdfx+xml', 'cdkey' => 'application/vnd.mediastation.cdkey', 'cdmia' => 'application/cdmi-capability', 'cdmic' => 'application/cdmi-container', 'cdmid' => 'application/cdmi-domain', 'cdmio' => 'application/cdmi-object', 'cdmiq' => 'application/cdmi-queue', 'cdx' => 'chemical/x-cdx', 'cdxml' => 'application/vnd.chemdraw+xml', 'cdy' => 'application/vnd.cinderella', 'cer' => 'application/pkix-cert', 'cfs' => 'application/x-cfs-compressed', 'cgm' => 'image/cgm', 'chat' => 'application/x-chat', 'chm' => 'application/vnd.ms-htmlhelp', 'chrt' => 'application/vnd.kde.kchart', 'cif' => 'chemical/x-cif', 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', 'cil' => 'application/vnd.ms-artgalry', 'cjs' => 'application/node', 'cla' => 'application/vnd.claymore', 'class' => 'application/java-vm', 'cld' => 'model/vnd.cld', 'clkk' => 'application/vnd.crick.clicker.keyboard', 'clkp' => 'application/vnd.crick.clicker.palette', 'clkt' => 'application/vnd.crick.clicker.template', 'clkw' => 'application/vnd.crick.clicker.wordbank', 'clkx' => 'application/vnd.crick.clicker', 'clp' => 'application/x-msclip', 'cmc' => 'application/vnd.cosmocaller', 'cmdf' => 'chemical/x-cmdf', 'cml' => 'chemical/x-cml', 'cmp' => 'application/vnd.yellowriver-custom-menu', 'cmx' => 'image/x-cmx', 'cod' => 'application/vnd.rim.cod', 'coffee' => 'text/coffeescript', 'com' => 'application/x-msdownload', 'conf' => 'text/plain', 'cpio' => 'application/x-cpio', 'cpl' => 'application/cpl+xml', 'cpp' => 'text/x-c', 'cpt' => 'application/mac-compactpro', 'crd' => 'application/x-mscardfile', 'crl' => 'application/pkix-crl', 'crt' => 'application/x-x509-ca-cert', 'crx' => 'application/x-chrome-extension', 'cryptonote' => 'application/vnd.rig.cryptonote', 'csh' => 'application/x-csh', 'csl' => 'application/vnd.citationstyles.style+xml', 'csml' => 'chemical/x-csml', 'csp' => 'application/vnd.commonspace', 'csr' => 'application/octet-stream', 'css' => 'text/css', 'cst' => 'application/x-director', 'csv' => 'text/csv', 'cu' => 'application/cu-seeme', 'curl' => 'text/vnd.curl', 'cwl' => 'application/cwl', 'cww' => 'application/prs.cww', 'cxt' => 'application/x-director', 'cxx' => 'text/x-c', 'dae' => 'model/vnd.collada+xml', 'daf' => 'application/vnd.mobius.daf', 'dart' => 'application/vnd.dart', 'dataless' => 'application/vnd.fdsn.seed', 'davmount' => 'application/davmount+xml', 'dbf' => 'application/vnd.dbf', 'dbk' => 'application/docbook+xml', 'dcm' => 'application/dicom', 'dcmp' => 'application/vnd.dcmp+xml', 'dcr' => 'application/x-director', 'dcurl' => 'text/vnd.curl.dcurl', 'dd2' => 'application/vnd.oma.dd2+xml', 'ddd' => 'application/vnd.fujixerox.ddd', 'ddf' => 'application/vnd.syncml.dmddf+xml', 'dds' => 'image/vnd.ms-dds', 'deb' => 'application/x-debian-package', 'def' => 'text/plain', 'deploy' => 'application/octet-stream', 'der' => 'application/x-x509-ca-cert', 'dfac' => 'application/vnd.dreamfactory', 'dgc' => 'application/x-dgc-compressed', 'dib' => 'image/bmp', 'dic' => 'text/x-c', 'dir' => 'application/x-director', 'dis' => 'application/vnd.mobius.dis', 'disposition-notification' => 'message/disposition-notification', 'dist' => 'application/octet-stream', 'distz' => 'application/octet-stream', 'djv' => 'image/vnd.djvu', 'djvu' => 'image/vnd.djvu', 'dll' => 'application/octet-stream', 'dmg' => 'application/x-apple-diskimage', 'dmn' => 'application/octet-stream', 'dmp' => 'application/vnd.tcpdump.pcap', 'dms' => 'application/octet-stream', 'dna' => 'application/vnd.dna', 'dng' => 'image/x-adobe-dng', 'doc' => 'application/msword', 'docm' => 'application/vnd.ms-word.document.macroenabled.12', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'dot' => 'application/msword', 'dotm' => 'application/vnd.ms-word.template.macroenabled.12', 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'dp' => 'application/vnd.osgi.dp', 'dpg' => 'application/vnd.dpgraph', 'dpx' => 'image/dpx', 'dra' => 'audio/vnd.dra', 'drle' => 'image/dicom-rle', 'drm' => 'application/vnd.procreate.dream', 'dsc' => 'text/prs.lines.tag', 'dssc' => 'application/dssc+der', 'dst' => 'application/octet-stream', 'dtb' => 'application/x-dtbook+xml', 'dtd' => 'application/xml-dtd', 'dts' => 'audio/vnd.dts', 'dtshd' => 'audio/vnd.dts.hd', 'dump' => 'application/octet-stream', 'dvb' => 'video/vnd.dvb.file', 'dvi' => 'application/x-dvi', 'dwd' => 'application/atsc-dwd+xml', 'dwf' => 'model/vnd.dwf', 'dwg' => 'image/vnd.dwg', 'dxf' => 'image/vnd.dxf', 'dxp' => 'application/vnd.spotfire.dxp', 'dxr' => 'application/x-director', 'ear' => 'application/java-archive', 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', 'ecma' => 'application/ecmascript', 'edm' => 'application/vnd.novadigm.edm', 'edx' => 'application/vnd.novadigm.edx', 'efif' => 'application/vnd.picsel', 'ei6' => 'application/vnd.pg.osasli', 'elc' => 'application/octet-stream', 'emf' => 'image/emf', 'eml' => 'message/rfc822', 'emma' => 'application/emma+xml', 'emotionml' => 'application/emotionml+xml', 'emz' => 'application/x-msmetafile', 'eol' => 'audio/vnd.digital-winds', 'eot' => 'application/vnd.ms-fontobject', 'eps' => 'application/postscript', 'epub' => 'application/epub+zip', 'es3' => 'application/vnd.eszigno3+xml', 'esa' => 'application/vnd.osgi.subsystem', 'esf' => 'application/vnd.epson.esf', 'et3' => 'application/vnd.eszigno3+xml', 'etx' => 'text/x-setext', 'eva' => 'application/x-eva', 'evy' => 'application/x-envoy', 'exe' => 'application/octet-stream', 'exi' => 'application/exi', 'exp' => 'application/express', 'exr' => 'image/aces', 'ext' => 'application/vnd.novadigm.ext', 'ez' => 'application/andrew-inset', 'ez2' => 'application/vnd.ezpix-album', 'ez3' => 'application/vnd.ezpix-package', 'f' => 'text/x-fortran', 'f4v' => 'video/mp4', 'f77' => 'text/x-fortran', 'f90' => 'text/x-fortran', 'facti' => 'image/vnd.blockfact.facti', 'fbs' => 'image/vnd.fastbidsheet', 'fbx' => 'application/vnd.autodesk.fbx', 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', 'fcs' => 'application/vnd.isac.fcs', 'fdf' => 'application/fdf', 'fdt' => 'application/fdt+xml', 'fe_launch' => 'application/vnd.denovo.fcselayout-link', 'fg5' => 'application/vnd.fujitsu.oasysgp', 'fgd' => 'application/x-director', 'fh' => 'image/x-freehand', 'fh4' => 'image/x-freehand', 'fh5' => 'image/x-freehand', 'fh7' => 'image/x-freehand', 'fhc' => 'image/x-freehand', 'fig' => 'application/x-xfig', 'fits' => 'image/fits', 'flac' => 'audio/x-flac', 'fli' => 'video/x-fli', 'flo' => 'application/vnd.micrografx.flo', 'flv' => 'video/x-flv', 'flw' => 'application/vnd.kde.kivio', 'flx' => 'text/vnd.fmi.flexstor', 'fly' => 'text/vnd.fly', 'fm' => 'application/vnd.framemaker', 'fnc' => 'application/vnd.frogans.fnc', 'fo' => 'application/vnd.software602.filler.form+xml', 'for' => 'text/x-fortran', 'fpx' => 'image/vnd.fpx', 'frame' => 'application/vnd.framemaker', 'fsc' => 'application/vnd.fsc.weblaunch', 'fst' => 'image/vnd.fst', 'ftc' => 'application/vnd.fluxtime.clip', 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', 'fvt' => 'video/vnd.fvt', 'fxp' => 'application/vnd.adobe.fxp', 'fxpl' => 'application/vnd.adobe.fxp', 'fzs' => 'application/vnd.fuzzysheet', 'g2w' => 'application/vnd.geoplan', 'g3' => 'image/g3fax', 'g3w' => 'application/vnd.geospace', 'gac' => 'application/vnd.groove-account', 'gam' => 'application/x-tads', 'gbr' => 'application/rpki-ghostbusters', 'gca' => 'application/x-gca-compressed', 'gdl' => 'model/vnd.gdl', 'gdoc' => 'application/vnd.google-apps.document', 'gdraw' => 'application/vnd.google-apps.drawing', 'ged' => 'text/vnd.familysearch.gedcom', 'geo' => 'application/vnd.dynageo', 'geojson' => 'application/geo+json', 'gex' => 'application/vnd.geometry-explorer', 'gform' => 'application/vnd.google-apps.form', 'ggb' => 'application/vnd.geogebra.file', 'ggs' => 'application/vnd.geogebra.slides', 'ggt' => 'application/vnd.geogebra.tool', 'ghf' => 'application/vnd.groove-help', 'gif' => 'image/gif', 'gim' => 'application/vnd.groove-identity-message', 'gjam' => 'application/vnd.google-apps.jam', 'glb' => 'model/gltf-binary', 'gltf' => 'model/gltf+json', 'gmap' => 'application/vnd.google-apps.map', 'gml' => 'application/gml+xml', 'gmx' => 'application/vnd.gmx', 'gnumeric' => 'application/x-gnumeric', 'gph' => 'application/vnd.flographit', 'gpx' => 'application/gpx+xml', 'gqf' => 'application/vnd.grafeq', 'gqs' => 'application/vnd.grafeq', 'gram' => 'application/srgs', 'gramps' => 'application/x-gramps-xml', 'gre' => 'application/vnd.geometry-explorer', 'grv' => 'application/vnd.groove-injector', 'grxml' => 'application/srgs+xml', 'gscript' => 'application/vnd.google-apps.script', 'gsf' => 'application/x-font-ghostscript', 'gsheet' => 'application/vnd.google-apps.spreadsheet', 'gsite' => 'application/vnd.google-apps.site', 'gslides' => 'application/vnd.google-apps.presentation', 'gtar' => 'application/x-gtar', 'gtm' => 'application/vnd.groove-tool-message', 'gtw' => 'model/vnd.gtw', 'gv' => 'text/vnd.graphviz', 'gxf' => 'application/gxf', 'gxt' => 'application/vnd.geonext', 'gz' => 'application/gzip', 'gzip' => 'application/gzip', 'h' => 'text/x-c', 'h261' => 'video/h261', 'h263' => 'video/h263', 'h264' => 'video/h264', 'hal' => 'application/vnd.hal+xml', 'hbci' => 'application/vnd.hbci', 'hbs' => 'text/x-handlebars-template', 'hdd' => 'application/x-virtualbox-hdd', 'hdf' => 'application/x-hdf', 'heic' => 'image/heic', 'heics' => 'image/heic-sequence', 'heif' => 'image/heif', 'heifs' => 'image/heif-sequence', 'hej2' => 'image/hej2k', 'held' => 'application/atsc-held+xml', 'hh' => 'text/x-c', 'hjson' => 'application/hjson', 'hlp' => 'application/winhlp', 'hpgl' => 'application/vnd.hp-hpgl', 'hpid' => 'application/vnd.hp-hpid', 'hps' => 'application/vnd.hp-hps', 'hqx' => 'application/mac-binhex40', 'htc' => 'text/x-component', 'htke' => 'application/vnd.kenameaapp', 'htm' => 'text/html', 'html' => 'text/html', 'hvd' => 'application/vnd.yamaha.hv-dic', 'hvp' => 'application/vnd.yamaha.hv-voice', 'hvs' => 'application/vnd.yamaha.hv-script', 'i2g' => 'application/vnd.intergeo', 'icc' => 'application/vnd.iccprofile', 'ice' => 'x-conference/x-cooltalk', 'icm' => 'application/vnd.iccprofile', 'ico' => 'image/vnd.microsoft.icon', 'ics' => 'text/calendar', 'ief' => 'image/ief', 'ifb' => 'text/calendar', 'ifm' => 'application/vnd.shana.informed.formdata', 'iges' => 'model/iges', 'igl' => 'application/vnd.igloader', 'igm' => 'application/vnd.insors.igm', 'igs' => 'model/iges', 'igx' => 'application/vnd.micrografx.igx', 'iif' => 'application/vnd.shana.informed.interchange', 'img' => 'application/octet-stream', 'imp' => 'application/vnd.accpac.simply.imp', 'ims' => 'application/vnd.ms-ims', 'in' => 'text/plain', 'indd' => 'application/x-indesign', 'ini' => 'text/plain', 'ink' => 'application/inkml+xml', 'inkml' => 'application/inkml+xml', 'install' => 'application/x-install-instructions', 'iota' => 'application/vnd.astraea-software.iota', 'ipfix' => 'application/ipfix', 'ipk' => 'application/vnd.shana.informed.package', 'ipynb' => 'application/x-ipynb+json', 'irm' => 'application/vnd.ibm.rights-management', 'irp' => 'application/vnd.irepository.package+xml', 'iso' => 'application/x-iso9660-image', 'itp' => 'application/vnd.shana.informed.formtemplate', 'its' => 'application/its+xml', 'ivp' => 'application/vnd.immervision-ivp', 'ivu' => 'application/vnd.immervision-ivu', 'jad' => 'text/vnd.sun.j2me.app-descriptor', 'jade' => 'text/jade', 'jaii' => 'image/jaii', 'jais' => 'image/jais', 'jam' => 'application/vnd.jam', 'jar' => 'application/java-archive', 'jardiff' => 'application/x-java-archive-diff', 'java' => 'text/x-java-source', 'jfif' => 'image/jpeg', 'jhc' => 'image/jphc', 'jisp' => 'application/vnd.jisp', 'jls' => 'image/jls', 'jlt' => 'application/vnd.hp-jlyt', 'jng' => 'image/x-jng', 'jnlp' => 'application/x-java-jnlp-file', 'joda' => 'application/vnd.joost.joda-archive', 'jp2' => 'image/jp2', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpf' => 'image/jpx', 'jpg' => 'image/jpeg', 'jpg2' => 'image/jp2', 'jpgm' => 'image/jpm', 'jpgv' => 'video/jpeg', 'jph' => 'image/jph', 'jpm' => 'image/jpm', 'jpx' => 'image/jpx', 'js' => 'text/javascript', 'json' => 'application/json', 'json5' => 'application/json5', 'jsonld' => 'application/ld+json', 'jsonml' => 'application/jsonml+json', 'jsx' => 'text/jsx', 'jt' => 'model/jt', 'jxl' => 'image/jxl', 'jxr' => 'image/jxr', 'jxra' => 'image/jxra', 'jxrs' => 'image/jxrs', 'jxs' => 'image/jxs', 'jxsc' => 'image/jxsc', 'jxsi' => 'image/jxsi', 'jxss' => 'image/jxss', 'kar' => 'audio/midi', 'karbon' => 'application/vnd.kde.karbon', 'kbl' => 'application/kbl+xml', 'kdb' => 'application/octet-stream', 'kdbx' => 'application/x-keepass2', 'key' => 'application/vnd.apple.keynote', 'kfo' => 'application/vnd.kde.kformula', 'kia' => 'application/vnd.kidspiration', 'kml' => 'application/vnd.google-earth.kml+xml', 'kmz' => 'application/vnd.google-earth.kmz', 'kne' => 'application/vnd.kinar', 'knp' => 'application/vnd.kinar', 'kon' => 'application/vnd.kde.kontour', 'kpr' => 'application/vnd.kde.kpresenter', 'kpt' => 'application/vnd.kde.kpresenter', 'kpxx' => 'application/vnd.ds-keypoint', 'ksp' => 'application/vnd.kde.kspread', 'ktr' => 'application/vnd.kahootz', 'ktx' => 'image/ktx', 'ktx2' => 'image/ktx2', 'ktz' => 'application/vnd.kahootz', 'kwd' => 'application/vnd.kde.kword', 'kwt' => 'application/vnd.kde.kword', 'lasxml' => 'application/vnd.las.las+xml', 'latex' => 'application/x-latex', 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', 'les' => 'application/vnd.hhe.lesson-player', 'less' => 'text/less', 'lgr' => 'application/lgr+xml', 'lha' => 'application/x-lzh-compressed', 'link66' => 'application/vnd.route66.link66+xml', 'list' => 'text/plain', 'list3820' => 'application/vnd.ibm.modcap', 'listafp' => 'application/vnd.ibm.modcap', 'litcoffee' => 'text/coffeescript', 'lnk' => 'application/x-ms-shortcut', 'log' => 'text/plain', 'lostxml' => 'application/lost+xml', 'lottie' => 'application/zip+dotlottie', 'lrf' => 'application/octet-stream', 'lrm' => 'application/vnd.ms-lrm', 'ltf' => 'application/vnd.frogans.ltf', 'lua' => 'text/x-lua', 'luac' => 'application/x-lua-bytecode', 'lvp' => 'audio/vnd.lucent.voice', 'lwp' => 'application/vnd.lotus-wordpro', 'lzh' => 'application/x-lzh-compressed', 'm13' => 'application/x-msmediaview', 'm14' => 'application/x-msmediaview', 'm1v' => 'video/mpeg', 'm21' => 'application/mp21', 'm2a' => 'audio/mpeg', 'm2t' => 'video/mp2t', 'm2ts' => 'video/mp2t', 'm2v' => 'video/mpeg', 'm3a' => 'audio/mpeg', 'm3u' => 'audio/x-mpegurl', 'm3u8' => 'application/vnd.apple.mpegurl', 'm4a' => 'audio/mp4', 'm4b' => 'audio/mp4', 'm4p' => 'application/mp4', 'm4s' => 'video/iso.segment', 'm4u' => 'video/vnd.mpegurl', 'm4v' => 'video/x-m4v', 'ma' => 'application/mathematica', 'mads' => 'application/mads+xml', 'maei' => 'application/mmt-aei+xml', 'mag' => 'application/vnd.ecowin.chart', 'maker' => 'application/vnd.framemaker', 'man' => 'text/troff', 'manifest' => 'text/cache-manifest', 'map' => 'application/json', 'mar' => 'application/octet-stream', 'markdown' => 'text/markdown', 'mathml' => 'application/mathml+xml', 'mb' => 'application/mathematica', 'mbk' => 'application/vnd.mobius.mbk', 'mbox' => 'application/mbox', 'mc1' => 'application/vnd.medcalcdata', 'mcd' => 'application/vnd.mcd', 'mcurl' => 'text/vnd.curl.mcurl', 'md' => 'text/markdown', 'mdb' => 'application/x-msaccess', 'mdi' => 'image/vnd.ms-modi', 'mdx' => 'text/mdx', 'me' => 'text/troff', 'mesh' => 'model/mesh', 'meta4' => 'application/metalink4+xml', 'metalink' => 'application/metalink+xml', 'mets' => 'application/mets+xml', 'mfm' => 'application/vnd.mfmp', 'mft' => 'application/rpki-manifest', 'mgp' => 'application/vnd.osgeo.mapguide.package', 'mgz' => 'application/vnd.proteus.magazine', 'mht' => 'message/rfc822', 'mhtml' => 'message/rfc822', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mie' => 'application/x-mie', 'mif' => 'application/vnd.mif', 'mime' => 'message/rfc822', 'mj2' => 'video/mj2', 'mjp2' => 'video/mj2', 'mjs' => 'text/javascript', 'mk3d' => 'video/matroska-3d', 'mka' => 'audio/matroska', 'mkd' => 'text/x-markdown', 'mks' => 'video/x-matroska', 'mkv' => 'video/matroska', 'mlp' => 'application/vnd.dolby.mlp', 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', 'mmf' => 'application/vnd.smaf', 'mml' => 'text/mathml', 'mmr' => 'image/vnd.fujixerox.edmics-mmr', 'mng' => 'video/x-mng', 'mny' => 'application/x-msmoney', 'mobi' => 'application/x-mobipocket-ebook', 'mods' => 'application/mods+xml', 'mov' => 'video/quicktime', 'movie' => 'video/x-sgi-movie', 'mp2' => 'audio/mpeg', 'mp21' => 'application/mp21', 'mp2a' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mp4a' => 'audio/mp4', 'mp4s' => 'application/mp4', 'mp4v' => 'video/mp4', 'mpc' => 'application/vnd.mophun.certificate', 'mpd' => 'application/dash+xml', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpf' => 'application/media-policy-dataset+xml', 'mpg' => 'video/mpeg', 'mpg4' => 'video/mp4', 'mpga' => 'audio/mpeg', 'mpkg' => 'application/vnd.apple.installer+xml', 'mpm' => 'application/vnd.blueice.multipass', 'mpn' => 'application/vnd.mophun.application', 'mpp' => 'application/vnd.ms-project', 'mpt' => 'application/vnd.ms-project', 'mpy' => 'application/vnd.ibm.minipay', 'mqy' => 'application/vnd.mobius.mqy', 'mrc' => 'application/marc', 'mrcx' => 'application/marcxml+xml', 'ms' => 'text/troff', 'mscml' => 'application/mediaservercontrol+xml', 'mseed' => 'application/vnd.fdsn.mseed', 'mseq' => 'application/vnd.mseq', 'msf' => 'application/vnd.epson.msf', 'msg' => 'application/vnd.ms-outlook', 'msh' => 'model/mesh', 'msi' => 'application/octet-stream', 'msix' => 'application/msix', 'msixbundle' => 'application/msixbundle', 'msl' => 'application/vnd.mobius.msl', 'msm' => 'application/octet-stream', 'msp' => 'application/octet-stream', 'msty' => 'application/vnd.muvee.style', 'mtl' => 'model/mtl', 'mts' => 'video/mp2t', 'mus' => 'application/vnd.musician', 'musd' => 'application/mmt-usd+xml', 'musicxml' => 'application/vnd.recordare.musicxml+xml', 'mvb' => 'application/x-msmediaview', 'mvt' => 'application/vnd.mapbox-vector-tile', 'mwf' => 'application/vnd.mfer', 'mxf' => 'application/mxf', 'mxl' => 'application/vnd.recordare.musicxml', 'mxmf' => 'audio/mobile-xmf', 'mxml' => 'application/xv+xml', 'mxs' => 'application/vnd.triscape.mxs', 'mxu' => 'video/vnd.mpegurl', 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', 'n3' => 'text/n3', 'nb' => 'application/mathematica', 'nbp' => 'application/vnd.wolfram.player', 'nc' => 'application/x-netcdf', 'ncx' => 'application/x-dtbncx+xml', 'ndjson' => 'application/x-ndjson', 'nfo' => 'text/x-nfo', 'ngdat' => 'application/vnd.nokia.n-gage.data', 'nitf' => 'application/vnd.nitf', 'nlu' => 'application/vnd.neurolanguage.nlu', 'nml' => 'application/vnd.enliven', 'nnd' => 'application/vnd.noblenet-directory', 'nns' => 'application/vnd.noblenet-sealer', 'nnw' => 'application/vnd.noblenet-web', 'npx' => 'image/vnd.net-fpx', 'nq' => 'application/n-quads', 'nsc' => 'application/x-conference', 'nsf' => 'application/vnd.lotus-notes', 'nt' => 'application/n-triples', 'ntf' => 'application/vnd.nitf', 'numbers' => 'application/vnd.apple.numbers', 'nzb' => 'application/x-nzb', 'oa2' => 'application/vnd.fujitsu.oasys2', 'oa3' => 'application/vnd.fujitsu.oasys3', 'oas' => 'application/vnd.fujitsu.oasys', 'obd' => 'application/x-msbinder', 'obgx' => 'application/vnd.openblox.game+xml', 'obj' => 'model/obj', 'oda' => 'application/oda', 'odb' => 'application/vnd.oasis.opendocument.database', 'odc' => 'application/vnd.oasis.opendocument.chart', 'odf' => 'application/vnd.oasis.opendocument.formula', 'odft' => 'application/vnd.oasis.opendocument.formula-template', 'odg' => 'application/vnd.oasis.opendocument.graphics', 'odi' => 'application/vnd.oasis.opendocument.image', 'odm' => 'application/vnd.oasis.opendocument.text-master', 'odp' => 'application/vnd.oasis.opendocument.presentation', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 'odt' => 'application/vnd.oasis.opendocument.text', 'oga' => 'audio/ogg', 'ogex' => 'model/vnd.opengex', 'ogg' => 'audio/ogg', 'ogv' => 'video/ogg', 'ogx' => 'application/ogg', 'omdoc' => 'application/omdoc+xml', 'one' => 'application/onenote', 'onea' => 'application/onenote', 'onepkg' => 'application/onenote', 'onetmp' => 'application/onenote', 'onetoc' => 'application/onenote', 'onetoc2' => 'application/onenote', 'opf' => 'application/oebps-package+xml', 'opml' => 'text/x-opml', 'oprc' => 'application/vnd.palm', 'opus' => 'audio/ogg', 'org' => 'application/vnd.lotus-organizer', 'osf' => 'application/vnd.yamaha.openscoreformat', 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', 'osm' => 'application/vnd.openstreetmap.data+xml', 'otc' => 'application/vnd.oasis.opendocument.chart-template', 'otf' => 'font/otf', 'otg' => 'application/vnd.oasis.opendocument.graphics-template', 'oth' => 'application/vnd.oasis.opendocument.text-web', 'oti' => 'application/vnd.oasis.opendocument.image-template', 'otp' => 'application/vnd.oasis.opendocument.presentation-template', 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', 'ott' => 'application/vnd.oasis.opendocument.text-template', 'ova' => 'application/x-virtualbox-ova', 'ovf' => 'application/x-virtualbox-ovf', 'owl' => 'application/rdf+xml', 'oxps' => 'application/oxps', 'oxt' => 'application/vnd.openofficeorg.extension', 'p' => 'text/x-pascal', 'p10' => 'application/pkcs10', 'p12' => 'application/x-pkcs12', 'p21' => 'model/step', 'p7a' => 'application/x-pkcs7-signature', 'p7b' => 'application/x-pkcs7-certificates', 'p7c' => 'application/pkcs7-mime', 'p7e' => 'application/pkcs7-mime', 'p7m' => 'application/pkcs7-mime', 'p7r' => 'application/x-pkcs7-certreqresp', 'p7s' => 'application/pkcs7-signature', 'p8' => 'application/pkcs8', 'pac' => 'application/x-ns-proxy-autoconfig', 'pages' => 'application/vnd.apple.pages', 'parquet' => 'application/vnd.apache.parquet', 'pas' => 'text/x-pascal', 'paw' => 'application/vnd.pawaafile', 'pbd' => 'application/vnd.powerbuilder6', 'pbm' => 'image/x-portable-bitmap', 'pcap' => 'application/vnd.tcpdump.pcap', 'pcf' => 'application/x-font-pcf', 'pcl' => 'application/vnd.hp-pcl', 'pclxl' => 'application/vnd.hp-pclxl', 'pct' => 'image/x-pict', 'pcurl' => 'application/vnd.curl.pcurl', 'pcx' => 'image/vnd.zbrush.pcx', 'pdb' => 'application/vnd.palm', 'pde' => 'text/x-processing', 'pdf' => 'application/pdf', 'pem' => 'application/x-x509-user-cert', 'pfa' => 'application/x-font-type1', 'pfb' => 'application/x-font-type1', 'pfm' => 'application/x-font-type1', 'pfr' => 'application/font-tdpfr', 'pfx' => 'application/x-pkcs12', 'pgm' => 'image/x-portable-graymap', 'pgn' => 'application/x-chess-pgn', 'pgp' => 'application/pgp-encrypted', 'phar' => 'application/octet-stream', 'php' => 'application/x-httpd-php', 'php3' => 'application/x-httpd-php', 'php4' => 'application/x-httpd-php', 'phps' => 'application/x-httpd-php-source', 'phtml' => 'application/x-httpd-php', 'pic' => 'image/x-pict', 'pkg' => 'application/octet-stream', 'pki' => 'application/pkixcmp', 'pkipath' => 'application/pkix-pkipath', 'pkpass' => 'application/vnd.apple.pkpass', 'pl' => 'application/x-perl', 'plb' => 'application/vnd.3gpp.pic-bw-large', 'plc' => 'application/vnd.mobius.plc', 'plf' => 'application/vnd.pocketlearn', 'pls' => 'application/pls+xml', 'pm' => 'application/x-perl', 'pml' => 'application/vnd.ctc-posml', 'png' => 'image/png', 'pnm' => 'image/x-portable-anymap', 'portpkg' => 'application/vnd.macports.portpkg', 'pot' => 'application/vnd.ms-powerpoint', 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12', 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ppa' => 'application/vnd.ms-powerpoint', 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12', 'ppd' => 'application/vnd.cups-ppd', 'ppm' => 'image/x-portable-pixmap', 'pps' => 'application/vnd.ms-powerpoint', 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 'ppt' => 'application/vnd.ms-powerpoint', 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pqa' => 'application/vnd.palm', 'prc' => 'model/prc', 'pre' => 'application/vnd.lotus-freelance', 'prf' => 'application/pics-rules', 'provx' => 'application/provenance+xml', 'ps' => 'application/postscript', 'psb' => 'application/vnd.3gpp.pic-bw-small', 'psd' => 'image/vnd.adobe.photoshop', 'psf' => 'application/x-font-linux-psf', 'pskcxml' => 'application/pskc+xml', 'pti' => 'image/prs.pti', 'ptid' => 'application/vnd.pvi.ptid1', 'pub' => 'application/x-mspublisher', 'pv' => 'application/octet-stream', 'pvb' => 'application/vnd.3gpp.pic-bw-var', 'pwn' => 'application/vnd.3m.post-it-notes', 'pxf' => 'application/octet-stream', 'pya' => 'audio/vnd.ms-playready.media.pya', 'pyo' => 'model/vnd.pytha.pyox', 'pyox' => 'model/vnd.pytha.pyox', 'pyv' => 'video/vnd.ms-playready.media.pyv', 'qam' => 'application/vnd.epson.quickanime', 'qbo' => 'application/vnd.intu.qbo', 'qfx' => 'application/vnd.intu.qfx', 'qps' => 'application/vnd.publishare-delta-tree', 'qt' => 'video/quicktime', 'qwd' => 'application/vnd.quark.quarkxpress', 'qwt' => 'application/vnd.quark.quarkxpress', 'qxb' => 'application/vnd.quark.quarkxpress', 'qxd' => 'application/vnd.quark.quarkxpress', 'qxl' => 'application/vnd.quark.quarkxpress', 'qxt' => 'application/vnd.quark.quarkxpress', 'ra' => 'audio/x-realaudio', 'ram' => 'audio/x-pn-realaudio', 'raml' => 'application/raml+yaml', 'rapd' => 'application/route-apd+xml', 'rar' => 'application/vnd.rar', 'ras' => 'image/x-cmu-raster', 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', 'rdf' => 'application/rdf+xml', 'rdz' => 'application/vnd.data-vision.rdz', 'relo' => 'application/p2p-overlay+xml', 'rep' => 'application/vnd.businessobjects', 'res' => 'application/x-dtbresource+xml', 'rgb' => 'image/x-rgb', 'rif' => 'application/reginfo+xml', 'rip' => 'audio/vnd.rip', 'ris' => 'application/x-research-info-systems', 'rl' => 'application/resource-lists+xml', 'rlc' => 'image/vnd.fujixerox.edmics-rlc', 'rld' => 'application/resource-lists-diff+xml', 'rm' => 'application/vnd.rn-realmedia', 'rmi' => 'audio/midi', 'rmp' => 'audio/x-pn-realaudio-plugin', 'rms' => 'application/vnd.jcp.javame.midlet-rms', 'rmvb' => 'application/vnd.rn-realmedia-vbr', 'rnc' => 'application/relax-ng-compact-syntax', 'rng' => 'application/xml', 'roa' => 'application/rpki-roa', 'roff' => 'text/troff', 'rp9' => 'application/vnd.cloanto.rp9', 'rpm' => 'application/x-redhat-package-manager', 'rpss' => 'application/vnd.nokia.radio-presets', 'rpst' => 'application/vnd.nokia.radio-preset', 'rq' => 'application/sparql-query', 'rs' => 'application/rls-services+xml', 'rsa' => 'application/x-pkcs7', 'rsat' => 'application/atsc-rsat+xml', 'rsd' => 'application/rsd+xml', 'rsheet' => 'application/urc-ressheet+xml', 'rss' => 'application/rss+xml', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', 'run' => 'application/x-makeself', 'rusd' => 'application/route-usd+xml', 'rv' => 'video/vnd.rn-realvideo', 's' => 'text/x-asm', 's3m' => 'audio/s3m', 'saf' => 'application/vnd.yamaha.smaf-audio', 'sass' => 'text/x-sass', 'sbml' => 'application/sbml+xml', 'sc' => 'application/vnd.ibm.secure-container', 'scd' => 'application/x-msschedule', 'scm' => 'application/vnd.lotus-screencam', 'scq' => 'application/scvp-cv-request', 'scs' => 'application/scvp-cv-response', 'scss' => 'text/x-scss', 'scurl' => 'text/vnd.curl.scurl', 'sda' => 'application/vnd.stardivision.draw', 'sdc' => 'application/vnd.stardivision.calc', 'sdd' => 'application/vnd.stardivision.impress', 'sdkd' => 'application/vnd.solent.sdkm+xml', 'sdkm' => 'application/vnd.solent.sdkm+xml', 'sdp' => 'application/sdp', 'sdw' => 'application/vnd.stardivision.writer', 'sea' => 'application/x-sea', 'see' => 'application/vnd.seemail', 'seed' => 'application/vnd.fdsn.seed', 'sema' => 'application/vnd.sema', 'semd' => 'application/vnd.semd', 'semf' => 'application/vnd.semf', 'senmlx' => 'application/senml+xml', 'sensmlx' => 'application/sensml+xml', 'ser' => 'application/java-serialized-object', 'setpay' => 'application/set-payment-initiation', 'setreg' => 'application/set-registration-initiation', 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', 'sfs' => 'application/vnd.spotfire.sfs', 'sfv' => 'text/x-sfv', 'sgi' => 'image/sgi', 'sgl' => 'application/vnd.stardivision.writer-global', 'sgm' => 'text/sgml', 'sgml' => 'text/sgml', 'sh' => 'application/x-sh', 'shar' => 'application/x-shar', 'shex' => 'text/shex', 'shf' => 'application/shf+xml', 'shtml' => 'text/html', 'sid' => 'image/x-mrsid-image', 'sieve' => 'application/sieve', 'sig' => 'application/pgp-signature', 'sil' => 'audio/silk', 'silo' => 'model/mesh', 'sis' => 'application/vnd.symbian.install', 'sisx' => 'application/vnd.symbian.install', 'sit' => 'application/x-stuffit', 'sitx' => 'application/x-stuffitx', 'siv' => 'application/sieve', 'skd' => 'application/vnd.koan', 'skm' => 'application/vnd.koan', 'skp' => 'application/vnd.koan', 'skt' => 'application/vnd.koan', 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', 'slim' => 'text/slim', 'slm' => 'text/slim', 'sls' => 'application/route-s-tsid+xml', 'slt' => 'application/vnd.epson.salt', 'sm' => 'application/vnd.stepmania.stepchart', 'smf' => 'application/vnd.stardivision.math', 'smi' => 'application/smil+xml', 'smil' => 'application/smil+xml', 'smv' => 'video/x-smv', 'smzip' => 'application/vnd.stepmania.package', 'snd' => 'audio/basic', 'snf' => 'application/x-font-snf', 'so' => 'application/octet-stream', 'spc' => 'application/x-pkcs7-certificates', 'spdx' => 'text/spdx', 'spf' => 'application/vnd.yamaha.smaf-phrase', 'spl' => 'application/x-futuresplash', 'spot' => 'text/vnd.in3d.spot', 'spp' => 'application/scvp-vp-response', 'spq' => 'application/scvp-vp-request', 'spx' => 'audio/ogg', 'sql' => 'application/sql', 'sqlite' => 'application/vnd.sqlite3', 'sqlite3' => 'application/vnd.sqlite3', 'src' => 'application/x-wais-source', 'srt' => 'application/x-subrip', 'sru' => 'application/sru+xml', 'srx' => 'application/sparql-results+xml', 'ssdl' => 'application/ssdl+xml', 'sse' => 'application/vnd.kodak-descriptor', 'ssf' => 'application/vnd.epson.ssf', 'ssml' => 'application/ssml+xml', 'sst' => 'application/octet-stream', 'st' => 'application/vnd.sailingtracker.track', 'stc' => 'application/vnd.sun.xml.calc.template', 'std' => 'application/vnd.sun.xml.draw.template', 'step' => 'model/step', 'stf' => 'application/vnd.wt.stf', 'sti' => 'application/vnd.sun.xml.impress.template', 'stk' => 'application/hyperstudio', 'stl' => 'model/stl', 'stp' => 'model/step', 'stpnc' => 'model/step', 'stpx' => 'model/step+xml', 'stpxz' => 'model/step-xml+zip', 'stpz' => 'model/step+zip', 'str' => 'application/vnd.pg.format', 'stw' => 'application/vnd.sun.xml.writer.template', 'styl' => 'text/stylus', 'stylus' => 'text/stylus', 'sub' => 'image/vnd.dvb.subtitle', 'sus' => 'application/vnd.sus-calendar', 'susp' => 'application/vnd.sus-calendar', 'sv4cpio' => 'application/x-sv4cpio', 'sv4crc' => 'application/x-sv4crc', 'svc' => 'application/vnd.dvb.service', 'svd' => 'application/vnd.svd', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', 'swa' => 'application/x-director', 'swf' => 'application/x-shockwave-flash', 'swi' => 'application/vnd.aristanetworks.swi', 'swidtag' => 'application/swid+xml', 'sxc' => 'application/vnd.sun.xml.calc', 'sxd' => 'application/vnd.sun.xml.draw', 'sxg' => 'application/vnd.sun.xml.writer.global', 'sxi' => 'application/vnd.sun.xml.impress', 'sxm' => 'application/vnd.sun.xml.math', 'sxw' => 'application/vnd.sun.xml.writer', 'systemverify' => 'application/vnd.pp.systemverify+xml', 't' => 'text/troff', 't3' => 'application/x-t3vm-image', 't38' => 'image/t38', 'taglet' => 'application/vnd.mynfc', 'tao' => 'application/vnd.tao.intent-module-archive', 'tap' => 'image/vnd.tencent.tap', 'tar' => 'application/x-tar', 'tcap' => 'application/vnd.3gpp2.tcap', 'tcl' => 'application/x-tcl', 'td' => 'application/urc-targetdesc+xml', 'teacher' => 'application/vnd.smart.teacher', 'tei' => 'application/tei+xml', 'teicorpus' => 'application/tei+xml', 'tex' => 'application/x-tex', 'texi' => 'application/x-texinfo', 'texinfo' => 'application/x-texinfo', 'text' => 'text/plain', 'tfi' => 'application/thraud+xml', 'tfm' => 'application/x-tex-tfm', 'tfx' => 'image/tiff-fx', 'tga' => 'image/x-tga', 'tgz' => 'application/gzip', 'thmx' => 'application/vnd.ms-officetheme', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'tk' => 'application/x-tcl', 'tmo' => 'application/vnd.tmobile-livetv', 'toml' => 'application/toml', 'torrent' => 'application/x-bittorrent', 'tpl' => 'application/vnd.groove-tool-template', 'tpt' => 'application/vnd.trid.tpt', 'tr' => 'text/troff', 'tra' => 'application/vnd.trueapp', 'trig' => 'application/trig', 'trm' => 'application/x-msterminal', 'ts' => 'video/mp2t', 'tsd' => 'application/timestamped-data', 'tsv' => 'text/tab-separated-values', 'ttc' => 'font/collection', 'ttf' => 'font/ttf', 'ttl' => 'text/turtle', 'ttml' => 'application/ttml+xml', 'twd' => 'application/vnd.simtech-mindmapper', 'twds' => 'application/vnd.simtech-mindmapper', 'txd' => 'application/vnd.genomatix.tuxedo', 'txf' => 'application/vnd.mobius.txf', 'txt' => 'text/plain', 'u32' => 'application/x-authorware-bin', 'u3d' => 'model/u3d', 'u8dsn' => 'message/global-delivery-status', 'u8hdr' => 'message/global-headers', 'u8mdn' => 'message/global-disposition-notification', 'u8msg' => 'message/global', 'ubj' => 'application/ubjson', 'udeb' => 'application/x-debian-package', 'ufd' => 'application/vnd.ufdl', 'ufdl' => 'application/vnd.ufdl', 'ulx' => 'application/x-glulx', 'umj' => 'application/vnd.umajin', 'unityweb' => 'application/vnd.unity', 'uo' => 'application/vnd.uoml+xml', 'uoml' => 'application/vnd.uoml+xml', 'uri' => 'text/uri-list', 'uris' => 'text/uri-list', 'urls' => 'text/uri-list', 'usda' => 'model/vnd.usda', 'usdz' => 'model/vnd.usdz+zip', 'ustar' => 'application/x-ustar', 'utz' => 'application/vnd.uiq.theme', 'uu' => 'text/x-uuencode', 'uva' => 'audio/vnd.dece.audio', 'uvd' => 'application/vnd.dece.data', 'uvf' => 'application/vnd.dece.data', 'uvg' => 'image/vnd.dece.graphic', 'uvh' => 'video/vnd.dece.hd', 'uvi' => 'image/vnd.dece.graphic', 'uvm' => 'video/vnd.dece.mobile', 'uvp' => 'video/vnd.dece.pd', 'uvs' => 'video/vnd.dece.sd', 'uvt' => 'application/vnd.dece.ttml+xml', 'uvu' => 'video/vnd.uvvu.mp4', 'uvv' => 'video/vnd.dece.video', 'uvva' => 'audio/vnd.dece.audio', 'uvvd' => 'application/vnd.dece.data', 'uvvf' => 'application/vnd.dece.data', 'uvvg' => 'image/vnd.dece.graphic', 'uvvh' => 'video/vnd.dece.hd', 'uvvi' => 'image/vnd.dece.graphic', 'uvvm' => 'video/vnd.dece.mobile', 'uvvp' => 'video/vnd.dece.pd', 'uvvs' => 'video/vnd.dece.sd', 'uvvt' => 'application/vnd.dece.ttml+xml', 'uvvu' => 'video/vnd.uvvu.mp4', 'uvvv' => 'video/vnd.dece.video', 'uvvx' => 'application/vnd.dece.unspecified', 'uvvz' => 'application/vnd.dece.zip', 'uvx' => 'application/vnd.dece.unspecified', 'uvz' => 'application/vnd.dece.zip', 'vbox' => 'application/x-virtualbox-vbox', 'vbox-extpack' => 'application/x-virtualbox-vbox-extpack', 'vcard' => 'text/vcard', 'vcd' => 'application/x-cdlink', 'vcf' => 'text/x-vcard', 'vcg' => 'application/vnd.groove-vcard', 'vcs' => 'text/x-vcalendar', 'vcx' => 'application/vnd.vcx', 'vdi' => 'application/x-virtualbox-vdi', 'vds' => 'model/vnd.sap.vds', 'vdx' => 'application/vnd.ms-visio.viewer', 'vec' => 'application/vec+xml', 'vhd' => 'application/x-virtualbox-vhd', 'vis' => 'application/vnd.visionary', 'viv' => 'video/vnd.vivo', 'vmdk' => 'application/x-virtualbox-vmdk', 'vob' => 'video/x-ms-vob', 'vor' => 'application/vnd.stardivision.writer', 'vox' => 'application/x-authorware-bin', 'vrml' => 'model/vrml', 'vsd' => 'application/vnd.visio', 'vsdx' => 'application/vnd.visio', 'vsf' => 'application/vnd.vsf', 'vss' => 'application/vnd.visio', 'vst' => 'application/vnd.visio', 'vsw' => 'application/vnd.visio', 'vtf' => 'image/vnd.valve.source.texture', 'vtt' => 'text/vtt', 'vtu' => 'model/vnd.vtu', 'vtx' => 'application/vnd.visio', 'vxml' => 'application/voicexml+xml', 'w3d' => 'application/x-director', 'wad' => 'application/x-doom', 'wadl' => 'application/vnd.sun.wadl+xml', 'war' => 'application/java-archive', 'wasm' => 'application/wasm', 'wav' => 'audio/wav', 'wax' => 'audio/x-ms-wax', 'wbmp' => 'image/vnd.wap.wbmp', 'wbs' => 'application/vnd.criticaltools.wbs+xml', 'wbxml' => 'application/vnd.wap.wbxml', 'wcm' => 'application/vnd.ms-works', 'wdb' => 'application/vnd.ms-works', 'wdp' => 'image/vnd.ms-photo', 'weba' => 'audio/webm', 'webapp' => 'application/x-web-app-manifest+json', 'webm' => 'video/webm', 'webmanifest' => 'application/manifest+json', 'webp' => 'image/webp', 'wg' => 'application/vnd.pmi.widget', 'wgsl' => 'text/wgsl', 'wgt' => 'application/widget', 'wif' => 'application/watcherinfo+xml', 'wks' => 'application/vnd.ms-works', 'wm' => 'video/x-ms-wm', 'wma' => 'audio/x-ms-wma', 'wmd' => 'application/x-ms-wmd', 'wmf' => 'image/wmf', 'wml' => 'text/vnd.wap.wml', 'wmlc' => 'application/vnd.wap.wmlc', 'wmls' => 'text/vnd.wap.wmlscript', 'wmlsc' => 'application/vnd.wap.wmlscriptc', 'wmv' => 'video/x-ms-wmv', 'wmx' => 'video/x-ms-wmx', 'wmz' => 'application/x-ms-wmz', 'woff' => 'font/woff', 'woff2' => 'font/woff2', 'word' => 'application/msword', 'wpd' => 'application/vnd.wordperfect', 'wpl' => 'application/vnd.ms-wpl', 'wps' => 'application/vnd.ms-works', 'wqd' => 'application/vnd.wqd', 'wri' => 'application/x-mswrite', 'wrl' => 'model/vrml', 'wsc' => 'message/vnd.wfa.wsc', 'wsdl' => 'application/wsdl+xml', 'wspolicy' => 'application/wspolicy+xml', 'wtb' => 'application/vnd.webturbo', 'wvx' => 'video/x-ms-wvx', 'x32' => 'application/x-authorware-bin', 'x3d' => 'model/x3d+xml', 'x3db' => 'model/x3d+fastinfoset', 'x3dbz' => 'model/x3d+binary', 'x3dv' => 'model/x3d-vrml', 'x3dvz' => 'model/x3d+vrml', 'x3dz' => 'model/x3d+xml', 'x_b' => 'model/vnd.parasolid.transmit.binary', 'x_t' => 'model/vnd.parasolid.transmit.text', 'xaml' => 'application/xaml+xml', 'xap' => 'application/x-silverlight-app', 'xar' => 'application/vnd.xara', 'xav' => 'application/xcap-att+xml', 'xbap' => 'application/x-ms-xbap', 'xbd' => 'application/vnd.fujixerox.docuworks.binder', 'xbm' => 'image/x-xbitmap', 'xca' => 'application/xcap-caps+xml', 'xcs' => 'application/calendar+xml', 'xdcf' => 'application/vnd.gov.sk.xmldatacontainer+xml', 'xdf' => 'application/xcap-diff+xml', 'xdm' => 'application/vnd.syncml.dm+xml', 'xdp' => 'application/vnd.adobe.xdp+xml', 'xdssc' => 'application/dssc+xml', 'xdw' => 'application/vnd.fujixerox.docuworks', 'xel' => 'application/xcap-el+xml', 'xenc' => 'application/xenc+xml', 'xer' => 'application/patch-ops-error+xml', 'xfdf' => 'application/xfdf', 'xfdl' => 'application/vnd.xfdl', 'xht' => 'application/xhtml+xml', 'xhtm' => 'application/vnd.pwg-xhtml-print+xml', 'xhtml' => 'application/xhtml+xml', 'xhvml' => 'application/xv+xml', 'xif' => 'image/vnd.xiff', 'xl' => 'application/vnd.ms-excel', 'xla' => 'application/vnd.ms-excel', 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12', 'xlc' => 'application/vnd.ms-excel', 'xlf' => 'application/xliff+xml', 'xlm' => 'application/vnd.ms-excel', 'xls' => 'application/vnd.ms-excel', 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12', 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlt' => 'application/vnd.ms-excel', 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12', 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'xlw' => 'application/vnd.ms-excel', 'xm' => 'audio/xm', 'xml' => 'application/xml', 'xns' => 'application/xcap-ns+xml', 'xo' => 'application/vnd.olpc-sugar', 'xop' => 'application/xop+xml', 'xpi' => 'application/x-xpinstall', 'xpl' => 'application/xproc+xml', 'xpm' => 'image/x-xpixmap', 'xpr' => 'application/vnd.is-xpr', 'xps' => 'application/vnd.ms-xpsdocument', 'xpw' => 'application/vnd.intercon.formnet', 'xpx' => 'application/vnd.intercon.formnet', 'xsd' => 'application/xml', 'xsf' => 'application/prs.xsf+xml', 'xsl' => 'application/xslt+xml', 'xslt' => 'application/xslt+xml', 'xsm' => 'application/vnd.syncml+xml', 'xspf' => 'application/xspf+xml', 'xul' => 'application/vnd.mozilla.xul+xml', 'xvm' => 'application/xv+xml', 'xvml' => 'application/xv+xml', 'xwd' => 'image/x-xwindowdump', 'xyz' => 'chemical/x-xyz', 'xz' => 'application/x-xz', 'yaml' => 'text/yaml', 'yang' => 'application/yang', 'yin' => 'application/yin+xml', 'yml' => 'text/yaml', 'ymp' => 'text/x-suse-ymp', 'z' => 'application/x-compress', 'z1' => 'application/x-zmachine', 'z2' => 'application/x-zmachine', 'z3' => 'application/x-zmachine', 'z4' => 'application/x-zmachine', 'z5' => 'application/x-zmachine', 'z6' => 'application/x-zmachine', 'z7' => 'application/x-zmachine', 'z8' => 'application/x-zmachine', 'zaz' => 'application/vnd.zzazz.deck+xml', 'zip' => 'application/zip', 'zir' => 'application/vnd.zul', 'zirz' => 'application/vnd.zul', 'zmm' => 'application/vnd.handheld-entertainment+xml', 'zsh' => 'text/x-scriptzsh', ]; /** * Determines the mimetype of a file by looking at its extension. * * @see https://raw.githubusercontent.com/jshttp/mime-db/master/db.json */ public static function fromFilename(string $filename): ?string { return self::fromExtension(pathinfo($filename, PATHINFO_EXTENSION)); } /** * Maps a file extensions to a mimetype. * * @see https://raw.githubusercontent.com/jshttp/mime-db/master/db.json */ public static function fromExtension(string $extension): ?string { return self::MIME_TYPES[Utils::asciiToLower($extension)] ?? null; } } boundary = $boundary ?: bin2hex(random_bytes(20)); $this->stream = $this->createStream($elements); } public function getBoundary(): string { return $this->boundary; } public function isWritable(): bool { return false; } /** * Get the headers needed before transferring the content of a POST file * * @param array $headers */ private function getHeaders(array $headers): string { $str = ''; foreach ($headers as $key => $value) { $key = (string) $key; $str .= "{$key}: {$value}\r\n"; } return "--{$this->boundary}\r\n".trim($str, " \n\r\t\0\x0B")."\r\n\r\n"; } /** * Create the aggregate stream that will be used to upload the POST data */ protected function createStream(array $elements = []): StreamInterface { $stream = new AppendStream(); foreach ($elements as $element) { if (!is_array($element)) { throw new \UnexpectedValueException('An array is expected'); } $this->addElement($stream, $element); } // Add the trailing boundary with CRLF $stream->addStream(Utils::streamFor("--{$this->boundary}--\r\n")); return $stream; } private function addElement(AppendStream $stream, array $element): void { foreach (['contents', 'name'] as $key) { if (!array_key_exists($key, $element)) { throw new \InvalidArgumentException("A '{$key}' key is required"); } } if (!is_string($element['name']) && !is_int($element['name'])) { throw new \InvalidArgumentException("The 'name' key must be a string or integer"); } if (is_array($element['contents'])) { if (array_key_exists('filename', $element) || array_key_exists('headers', $element)) { throw new \InvalidArgumentException( "The 'filename' and 'headers' options cannot be used when 'contents' is an array" ); } $this->addNestedElements($stream, $element['contents'], (string) $element['name']); return; } $contents = $element['contents']; if (is_scalar($contents) && !is_string($contents)) { // Multipart field values are byte strings on the wire, so finite // numeric and boolean field values are cast to string here rather // than tripping streamFor()'s non-string-scalar deprecation. Non-finite // floats are deprecated and normalized here too, so the deprecation is // reported against MultipartStream instead of transitively through // streamFor(). if (is_float($contents) && !is_finite($contents)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.12', 'Passing a non-finite float as multipart contents is deprecated; guzzlehttp/psr7 3.0 rejects non-finite floats.' ); $contents = is_nan($contents) ? 'NAN' : ($contents > 0 ? 'INF' : '-INF'); } $contents = (string) $contents; } $element['contents'] = Utils::streamFor($contents); if (empty($element['filename'])) { $uri = $element['contents']->getMetadata('uri'); if ($uri && \is_string($uri) && \substr($uri, 0, 6) !== 'php://' && \substr($uri, 0, 7) !== 'data://') { $element['filename'] = $uri; } } [$body, $headers] = $this->createElement( (string) $element['name'], $element['contents'], $element['filename'] ?? null, $element['headers'] ?? [] ); $stream->addStream(Utils::streamFor($this->getHeaders($headers))); $stream->addStream($body); $stream->addStream(Utils::streamFor("\r\n")); } /** * Recursively expand array contents into multiple form fields. * * @param array $contents */ private function addNestedElements(AppendStream $stream, array $contents, string $root): void { foreach ($contents as $key => $value) { $fieldName = $root === '' ? sprintf('[%s]', (string) $key) : sprintf('%s[%s]', $root, (string) $key); if (is_array($value)) { $this->addNestedElements($stream, $value, $fieldName); } else { $this->addElement($stream, ['name' => $fieldName, 'contents' => $value]); } } } /** * @param array $headers * * @return array{0: StreamInterface, 1: array} */ private function createElement(string $name, StreamInterface $stream, ?string $filename, array $headers): array { $headers = self::normalizePartHeaders($headers); // Set a default content-disposition header if one was no provided $disposition = self::getHeader($headers, 'content-disposition'); if (!$disposition) { $headers['Content-Disposition'] = ($filename === '0' || $filename) ? sprintf( 'form-data; name="%s"; filename="%s"', $name, basename($filename) ) : "form-data; name=\"{$name}\""; } // Set a default content-length header if one was no provided $length = self::getHeader($headers, 'content-length'); if (!$length) { if ($length = $stream->getSize()) { $headers['Content-Length'] = (string) $length; } } // Set a default Content-Type if one was not supplied $type = self::getHeader($headers, 'content-type'); if (!$type && ($filename === '0' || $filename)) { $headers['Content-Type'] = MimeType::fromFilename($filename) ?? 'application/octet-stream'; } return [$stream, $headers]; } /** * @param array $headers */ private static function getHeader(array $headers, string $key): ?string { $lowercaseHeader = Utils::asciiToLower($key); foreach ($headers as $k => $v) { if (Utils::asciiToLower((string) $k) === $lowercaseHeader) { return $v; } } return null; } private static function isValidBoundary(string $boundary): bool { $length = strlen($boundary); if ($length < 1 || $length > 70 || $boundary[$length - 1] === ' ') { return false; } return strspn($boundary, self::BOUNDARY_CHARS) === $length; } /** * @param array $headers * * @return array */ private static function normalizePartHeaders(array $headers): array { $normalized = []; foreach ($headers as $key => $value) { self::deprecateInvalidPartHeaderName((string) $key); if (!is_string($value)) { if (!is_scalar($value) && $value !== null && !(is_object($value) && method_exists($value, '__toString'))) { throw new \InvalidArgumentException(sprintf( 'Multipart part header value must be a string or stringable value but %s provided.', \get_debug_type($value) )); } \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s as a multipart part header value is deprecated; guzzlehttp/psr7 3.0 requires string multipart part header values.', \get_debug_type($value) ); } $value = (string) $value; self::deprecateInvalidPartHeaderValue($value); $normalized[$key] = $value; } return $normalized; } private static function deprecateInvalidPartHeaderName(string $name): void { if (!preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $name)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing an invalid multipart part header name to MultipartStream is deprecated; guzzlehttp/psr7 3.0 rejects invalid multipart part header names.' ); } } private static function deprecateInvalidPartHeaderValue(string $value): void { if (!preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D', $value)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing an invalid multipart part header value to MultipartStream is deprecated; guzzlehttp/psr7 3.0 rejects invalid multipart part header values.' ); } } } source = $source; $this->size = $options['size'] ?? null; $this->metadata = $options['metadata'] ?? []; $this->buffer = new BufferStream(); } public function __toString(): string { try { return Utils::copyToString($this); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } public function close(): void { $this->detach(); } public function detach() { $this->tellPos = 0; $this->source = null; return null; } public function getSize(): ?int { return $this->size; } public function tell(): int { return $this->tellPos; } public function eof(): bool { return $this->source === null; } public function isSeekable(): bool { return false; } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { if (!\is_int($offset)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $offset.', \get_debug_type($offset) ); } if (!\is_int($whence)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $whence.', \get_debug_type($whence) ); } throw new \RuntimeException('Cannot seek a PumpStream'); } public function isWritable(): bool { return false; } public function write($string): int { if (!\is_string($string)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::write() is deprecated; guzzlehttp/psr7 3.0 requires string for $string.', \get_debug_type($string) ); } throw new \RuntimeException('Cannot write to a PumpStream'); } public function isReadable(): bool { return true; } public function read($length): string { if (!\is_int($length)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::read() is deprecated; guzzlehttp/psr7 3.0 requires int for $length.', \get_debug_type($length) ); } $data = $this->buffer->read($length); $readLen = strlen($data); $this->tellPos += $readLen; $remaining = $length - $readLen; if ($remaining) { $this->pump($remaining); $data .= $this->buffer->read($remaining); $this->tellPos += strlen($data) - $readLen; } return $data; } public function getContents(): string { $result = ''; while (!$this->eof()) { $result .= $this->read(1000000); } return $result; } /** * @return mixed */ public function getMetadata($key = null) { if ($key !== null && !\is_string($key)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::getMetadata() is deprecated; guzzlehttp/psr7 3.0 requires string|null for $key.', \get_debug_type($key) ); } if (!$key) { return $this->metadata; } return $this->metadata[$key] ?? null; } private function pump(int $length): void { if ($this->source !== null) { do { $data = ($this->source)($length); if ($data === false || $data === null) { $this->source = null; return; } $this->buffer->write($data); $length -= strlen($data); } while ($length > 0); } } } '1', 'foo[b]' => '2'])`. * * @param string $str Query string to parse * @param int|bool $urlEncoding How the query string is encoded */ public static function parse(string $str, $urlEncoding = true): array { $result = []; if ($str === '') { return $result; } if ($urlEncoding === true) { $decoder = function ($value) { return rawurldecode(str_replace('+', ' ', (string) $value)); }; } elseif ($urlEncoding === PHP_QUERY_RFC3986) { $decoder = 'rawurldecode'; } elseif ($urlEncoding === PHP_QUERY_RFC1738) { $decoder = 'urldecode'; } else { $decoder = function ($str) { return $str; }; } foreach (explode('&', $str) as $kvp) { $parts = explode('=', $kvp, 2); $key = $decoder($parts[0]); $value = isset($parts[1]) ? $decoder($parts[1]) : null; if (!array_key_exists($key, $result)) { $result[$key] = $value; } else { if (!is_array($result[$key])) { $result[$key] = [$result[$key]]; } $result[$key][] = $value; } } return $result; } /** * Build a query string from an array of key value pairs. * * This function can use the return value of `parse()` to build a query * string. This function does not modify the provided keys when an array is * encountered (like `http_build_query()` would). * * @param array $params Query string parameters. * @param int|false $encoding Set to false to not encode, * PHP_QUERY_RFC3986 to encode using * RFC3986, or PHP_QUERY_RFC1738 to * encode using RFC1738. * @param bool $treatBoolsAsInts Set to true to encode as 0/1, and * false as false/true. */ public static function build(array $params, $encoding = PHP_QUERY_RFC3986, bool $treatBoolsAsInts = true): string { if (!$params) { return ''; } if ($encoding === false) { $encoder = function (string $str): string { return $str; }; } elseif ($encoding === PHP_QUERY_RFC3986) { $encoder = 'rawurlencode'; } elseif ($encoding === PHP_QUERY_RFC1738) { $encoder = 'urlencode'; } else { throw new \InvalidArgumentException('Invalid type'); } $castBool = $treatBoolsAsInts ? static function ($v) { return (int) $v; } : static function ($v) { return $v ? 'true' : 'false'; }; $qs = ''; foreach ($params as $k => $v) { $k = $encoder((string) $k); if (!is_array($v)) { $qs .= $k; $v = is_bool($v) ? $castBool($v) : self::normalizeNonFiniteFloat($v); if ($v !== null) { $qs .= '='.$encoder((string) $v); } $qs .= '&'; } else { foreach ($v as $vv) { $qs .= $k; $vv = is_bool($vv) ? $castBool($vv) : self::normalizeNonFiniteFloat($vv); if ($vv !== null) { $qs .= '='.$encoder((string) $vv); } $qs .= '&'; } } } return $qs ? (string) substr($qs, 0, -1) : ''; } /** * Converts non-finite floats to the strings PHP coerces them to, as * implicit coercion of NAN emits a warning on PHP 8.5. * * @param mixed $value * * @return mixed */ private static function normalizeNonFiniteFloat($value) { if (is_float($value) && !is_finite($value)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.12', 'Passing a non-finite float to Query::build() is deprecated; guzzlehttp/psr7 3.0 rejects non-finite floats.' ); return is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF'); } return $value; } } assertMethod($method); $this->assertProtocolVersion($version); if (!$uri instanceof UriInterface) { $uri = new Uri($uri); } self::warnOnMethodCasingChange($method); $this->method = Utils::asciiToUpper($method); $this->uri = $uri; $this->setHeaders($headers); $this->protocol = $version; if (!isset($this->headerNames['host'])) { $this->updateHostFromUri(); } if ($body !== '' && $body !== null) { $this->stream = Utils::streamFor($body); } } public function getRequestTarget(): string { if ($this->requestTarget !== null) { return $this->requestTarget; } $target = $this->uri->getPath(); if ($target === '') { $target = '/'; } if ($this->uri->getQuery() != '') { $target .= '?'.$this->uri->getQuery(); } return $target; } public function withRequestTarget($requestTarget): RequestInterface { $hasWhitespace = preg_match('#\s#', $requestTarget); if ($hasWhitespace === false) { throw new \RuntimeException('Unable to validate request target: '.preg_last_error_msg()); } if ($hasWhitespace === 1) { throw new InvalidArgumentException( 'Invalid request target provided; cannot contain whitespace' ); } $new = clone $this; $new->requestTarget = $requestTarget; return $new; } public function getMethod(): string { return $this->method; } public function withMethod($method): RequestInterface { $this->assertMethod($method); self::warnOnMethodCasingChange($method); $new = clone $this; $new->method = Utils::asciiToUpper($method); return $new; } public function getUri(): UriInterface { return $this->uri; } public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface { if (!\is_bool($preserveHost)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to RequestInterface::withUri() is deprecated; guzzlehttp/psr7 3.0 requires bool for $preserveHost.', \get_debug_type($preserveHost) ); } if ($uri === $this->uri) { return $this; } $new = clone $this; $new->uri = $uri; if (!$preserveHost || !isset($this->headerNames['host'])) { $new->updateHostFromUri(); } return $new; } private function updateHostFromUri(): void { $host = $this->uri->getHost(); if ($host == '') { return; } Uri::assertValidHost($host); if (($port = $this->uri->getPort()) !== null) { $host .= ':'.$port; } $this->assertValue($host); if (isset($this->headerNames['host'])) { $header = $this->headerNames['host']; } else { $header = 'Host'; $this->headerNames['host'] = 'Host'; } // Ensure Host is the first header. // See: https://datatracker.ietf.org/doc/html/rfc7230#section-5.4 $this->headers = [$header => [$host]] + $this->headers; } /** * @param mixed $method */ private function assertMethod($method): void { if (!is_string($method) || $method === '') { throw new InvalidArgumentException('Method must be a non-empty string.'); } $this->assertNoLineSeparators($method, 'Method'); } private static function warnOnMethodCasingChange(string $method): void { if ($method !== Utils::asciiToUpper($method)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing a non-uppercase HTTP method is deprecated; guzzlehttp/psr7 3.0 preserves method casing and will no longer uppercase it. Normalize the method before constructing or modifying requests if uppercase is required.' ); } } } 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 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 Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 510 => 'Not Extended', 511 => 'Network Authentication Required', ]; /** @var string */ private $reasonPhrase; /** @var int */ private $statusCode; /** * @param int $status Status code * @param (string|string[])[] $headers Response headers * @param string|resource|StreamInterface|null $body Response body * @param string $version Protocol version * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) */ public function __construct( int $status = 200, array $headers = [], $body = null, string $version = '1.1', ?string $reason = null ) { $this->assertStatusCodeRange($status); $this->assertProtocolVersion($version); $this->statusCode = $status; if ($body !== '' && $body !== null) { $this->stream = Utils::streamFor($body); } $this->setHeaders($headers); if ($reason == '' && isset(self::PHRASES[$this->statusCode])) { $reasonPhrase = self::PHRASES[$this->statusCode]; } else { $reasonPhrase = (string) $reason; } $this->assertNoLineSeparators($reasonPhrase, 'Reason phrase'); $this->reasonPhrase = $reasonPhrase; $this->protocol = $version; } public function getStatusCode(): int { return $this->statusCode; } public function getReasonPhrase(): string { return $this->reasonPhrase; } public function withStatus($code, $reasonPhrase = ''): ResponseInterface { if (!\is_int($code) && \filter_var($code, \FILTER_VALIDATE_INT) !== false) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to ResponseInterface::withStatus() is deprecated; guzzlehttp/psr7 3.0 requires int for $code.', \get_debug_type($code) ); } if (!\is_string($reasonPhrase)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to ResponseInterface::withStatus() is deprecated; guzzlehttp/psr7 3.0 requires string for $reasonPhrase.', \get_debug_type($reasonPhrase) ); } $this->assertStatusCodeIsInteger($code); $code = (int) $code; $this->assertStatusCodeRange($code); $new = clone $this; $new->statusCode = $code; if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) { $reasonPhrase = self::PHRASES[$new->statusCode]; } $reasonPhrase = (string) $reasonPhrase; $this->assertNoLineSeparators($reasonPhrase, 'Reason phrase'); $new->reasonPhrase = $reasonPhrase; return $new; } /** * @param mixed $statusCode */ private function assertStatusCodeIsInteger($statusCode): void { if (filter_var($statusCode, FILTER_VALIDATE_INT) === false) { throw new \InvalidArgumentException('Status code must be an integer value.'); } } private function assertStatusCodeRange(int $statusCode): void { if ($statusCode < 100 || $statusCode >= 600) { throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.'); } } } @,;:\\\"/[\]?={}\x01-\x20\x7F]++):[ \t]*+((?:[ \t]*+[\x21-\x7E\x80-\xFF]++)*+)[ \t]*+\r?\n)m"; public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; /** * @return array{0: string, 1: int|null}|null */ public static function parseHostHeader(string $authority): ?array { if ($authority === '') { return null; } $host = $authority; $port = null; if ($authority[0] === '[') { $closingBracket = strpos($authority, ']'); if ($closingBracket === false) { return null; } $host = substr($authority, 0, $closingBracket + 1); $remainder = substr($authority, $closingBracket + 1); if ($remainder !== '') { if ($remainder[0] !== ':') { return null; } $port = self::parseAuthorityPort(substr($remainder, 1)); if ($port === null) { return null; } } } elseif (false !== ($colon = strpos($authority, ':'))) { $host = substr($authority, 0, $colon); $port = self::parseAuthorityPort(substr($authority, $colon + 1)); if ($port === null) { return null; } } if ($host === '' || !self::isValidHostHeaderHost($host)) { return null; } return [$host, $port]; } private static function isValidHostHeaderHost(string $host): bool { $invalidHost = preg_match('/[\x00-\x20\x7F\/\?#@\\\\]/', $host); if ($invalidHost === false) { return false; } if ($invalidHost === 1) { return false; } if (strpos($host, '[') !== false || strpos($host, ']') !== false) { if ($host[0] !== '[' || substr($host, -1) !== ']') { return false; } $address = substr($host, 1, -1); return filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6) !== false || preg_match('/^v[0-9a-f]+\.['.Rfc3986::CHAR_UNRESERVED.Rfc3986::CHAR_SUB_DELIMS.':]+$/iD', $address) === 1; } return strpos($host, ':') === false; } private static function parseAuthorityPort(string $port): ?int { if ($port === '' || !ctype_digit($port)) { return null; } $normalized = ltrim($port, '0'); if ($normalized === '') { return 0; } if (strlen($normalized) > 5 || (int) $normalized > 0xFFFF) { return null; } return (int) $normalized; } } serverParams = $serverParams; parent::__construct($method, $uri, $headers, $body, $version); } /** * Return an UploadedFile instance array. * * @param array $files An array which respect $_FILES structure * * @throws InvalidArgumentException for unrecognized values */ public static function normalizeFiles(array $files): array { $normalized = []; foreach ($files as $key => $value) { if ($value instanceof UploadedFileInterface) { $normalized[$key] = $value; } elseif (is_array($value) && isset($value['tmp_name'])) { $normalized[$key] = self::createUploadedFileFromSpec($value); } elseif (is_array($value)) { $normalized[$key] = self::normalizeFiles($value); continue; } else { throw new InvalidArgumentException('Invalid value in files specification'); } } return $normalized; } /** * Create and return an UploadedFile instance from a $_FILES specification. * * If the specification represents an array of values, this method will * delegate to normalizeNestedFileSpec() and return that return value. * * @param array $value $_FILES struct * * @return UploadedFileInterface|UploadedFileInterface[] */ private static function createUploadedFileFromSpec(array $value) { if (is_array($value['tmp_name'])) { return self::normalizeNestedFileSpec($value); } return new UploadedFile( $value['tmp_name'], (int) $value['size'], (int) $value['error'], $value['name'], $value['type'] ); } /** * Normalize an array of file specifications. * * Loops through all nested files and returns a normalized array of * UploadedFileInterface instances. * * @return UploadedFileInterface[] */ private static function normalizeNestedFileSpec(array $files = []): array { $normalizedFiles = []; foreach (array_keys($files['tmp_name']) as $key) { $spec = [ 'tmp_name' => $files['tmp_name'][$key], 'size' => $files['size'][$key] ?? null, 'error' => $files['error'][$key] ?? null, 'name' => $files['name'][$key] ?? null, 'type' => $files['type'][$key] ?? null, ]; $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); } return $normalizedFiles; } /** * Return a ServerRequest populated with superglobals: * $_GET * $_POST * $_COOKIE * $_FILES * $_SERVER */ public static function fromGlobals(): ServerRequestInterface { $method = Utils::asciiToUpper(self::getServerParam('REQUEST_METHOD') ?? 'GET'); $headers = self::removeInvalidHostHeader(self::getAllHeaders()); $uri = self::getUriFromGlobals(); $body = new CachingStream(new LazyOpenStream('php://input', 'r+')); $serverProtocol = self::getServerParam('SERVER_PROTOCOL'); $protocol = $serverProtocol !== null ? str_replace('HTTP/', '', $serverProtocol) : '1.1'; $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); return $serverRequest ->withCookieParams($_COOKIE) ->withQueryParams($_GET) ->withParsedBody($_POST) ->withUploadedFiles(self::normalizeFiles($_FILES)); } /** * @return array */ private static function getAllHeaders(): array { return self::normalizeHeaderValues(getallheaders()); } /** * @param array $headers * * @return array */ private static function normalizeHeaderValues(array $headers): array { $normalized = []; foreach ($headers as $name => $value) { if (is_scalar($value) || (is_object($value) && method_exists($value, '__toString'))) { $normalized[$name] = (string) $value; } } return $normalized; } private static function getServerParam(string $key): ?string { return isset($_SERVER[$key]) && is_string($_SERVER[$key]) ? $_SERVER[$key] : null; } /** * @param array $headers * * @return array */ private static function removeInvalidHostHeader(array $headers): array { foreach ($headers as $name => $value) { if (Utils::asciiToLower((string) $name) !== 'host') { continue; } if (Rfc7230::parseHostHeader($value) === null) { unset($headers[$name]); } } return $headers; } /** * @return array{0: string|null, 1: int|null} */ private static function extractHostAndPortFromAuthority(string $authority): array { return Rfc7230::parseHostHeader($authority) ?? [null, null]; } /** * Get a Uri populated with values from $_SERVER. */ public static function getUriFromGlobals(): UriInterface { $uri = new Uri(''); $https = self::getServerParam('HTTPS'); $uri = $uri->withScheme(!empty($https) && $https !== 'off' ? 'https' : 'http'); $hasPort = false; $authority = self::getServerParam('HTTP_HOST'); if ($authority !== null) { [$host, $port] = self::extractHostAndPortFromAuthority($authority); if ($host !== null) { $uri = $uri->withHost($host); } if ($port !== null) { $hasPort = true; $uri = $uri->withPort($port); } } elseif (($serverName = self::getServerParam('SERVER_NAME')) !== null) { $uri = $uri->withHost($serverName); } elseif (($serverAddr = self::getServerParam('SERVER_ADDR')) !== null) { $uri = $uri->withHost($serverAddr); } $serverPort = self::getServerParam('SERVER_PORT'); if (!$hasPort && $serverPort !== null && preg_match('/^[+-]?\d+$/D', $serverPort) === 1) { $uri = $uri->withPort((int) $serverPort); } $hasQuery = false; $requestUri = self::getServerParam('REQUEST_URI'); if ($requestUri !== null) { $requestUriParts = explode('?', $requestUri, 2); $uri = $uri->withPath($requestUriParts[0]); if (isset($requestUriParts[1])) { $hasQuery = true; $uri = $uri->withQuery($requestUriParts[1]); } } $queryString = self::getServerParam('QUERY_STRING'); if (!$hasQuery && $queryString !== null) { $uri = $uri->withQuery($queryString); } return $uri; } public function getServerParams(): array { return $this->serverParams; } public function getUploadedFiles(): array { return $this->uploadedFiles; } public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface { $invalidUploadedFileFound = false; $invalidUploadedFile = null; $stack = [$uploadedFiles]; while ($stack !== []) { foreach (\array_pop($stack) as $uploadedFile) { if ($uploadedFile instanceof UploadedFileInterface) { continue; } if (\is_array($uploadedFile)) { $stack[] = $uploadedFile; continue; } $invalidUploadedFileFound = true; $invalidUploadedFile = $uploadedFile; break 2; } } if ($invalidUploadedFileFound) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s inside ServerRequestInterface::withUploadedFiles() is deprecated; guzzlehttp/psr7 3.0 requires an UploadedFileInterface[] tree.', \get_debug_type($invalidUploadedFile) ); } $new = clone $this; $new->uploadedFiles = $uploadedFiles; return $new; } public function getCookieParams(): array { return $this->cookieParams; } public function withCookieParams(array $cookies): ServerRequestInterface { $new = clone $this; $new->cookieParams = $cookies; return $new; } public function getQueryParams(): array { return $this->queryParams; } public function withQueryParams(array $query): ServerRequestInterface { $new = clone $this; $new->queryParams = $query; return $new; } /** * @return array|object|null */ public function getParsedBody() { return $this->parsedBody; } public function withParsedBody($data): ServerRequestInterface { if ($data !== null && !\is_array($data) && !\is_object($data)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to ServerRequestInterface::withParsedBody() is deprecated; guzzlehttp/psr7 3.0 requires array|object|null.', \get_debug_type($data) ); } $new = clone $this; $new->parsedBody = $data; return $new; } public function getAttributes(): array { return $this->attributes; } /** * @return mixed */ public function getAttribute($attribute, $default = null) { if (!\is_string($attribute)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to ServerRequestInterface::getAttribute() is deprecated; guzzlehttp/psr7 3.0 requires string for $attribute.', \get_debug_type($attribute) ); } if (false === array_key_exists($attribute, $this->attributes)) { return $default; } return $this->attributes[$attribute]; } public function withAttribute($attribute, $value): ServerRequestInterface { if (!\is_string($attribute)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to ServerRequestInterface::withAttribute() is deprecated; guzzlehttp/psr7 3.0 requires string for $attribute.', \get_debug_type($attribute) ); } $new = clone $this; $new->attributes[$attribute] = $value; return $new; } public function withoutAttribute($attribute): ServerRequestInterface { if (!\is_string($attribute)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to ServerRequestInterface::withoutAttribute() is deprecated; guzzlehttp/psr7 3.0 requires string for $attribute.', \get_debug_type($attribute) ); } if (false === array_key_exists($attribute, $this->attributes)) { return $this; } $new = clone $this; unset($new->attributes[$attribute]); return $new; } } size = $options['size']; } $this->customMetadata = $options['metadata'] ?? []; $this->stream = $stream; $meta = stream_get_meta_data($this->stream); $this->seekable = $meta['seekable']; $this->readable = (bool) preg_match(self::READABLE_MODES, $meta['mode']); $this->writable = (bool) preg_match(self::WRITABLE_MODES, $meta['mode']); $this->uri = $meta['uri'] ?? null; } /** * Closes the stream when the destructed */ public function __destruct() { $this->close(); } public function __toString(): string { try { if ($this->isSeekable()) { $this->seek(0); } return $this->getContents(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } public function getContents(): string { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->readable) { throw new \RuntimeException('Cannot read from non-readable stream'); } return Utils::tryGetContents($this->stream); } public function close(): void { if (isset($this->stream)) { if (is_resource($this->stream)) { fclose($this->stream); } $this->detach(); } } public function detach() { if (!isset($this->stream)) { return null; } $result = $this->stream; unset($this->stream); $this->size = $this->uri = null; $this->readable = $this->writable = $this->seekable = false; return $result; } public function getSize(): ?int { if ($this->size !== null) { return $this->size; } if (!isset($this->stream)) { return null; } // Clear the stat cache if the stream has a URI if ($this->uri) { clearstatcache(true, $this->uri); } $stats = fstat($this->stream); if (is_array($stats) && isset($stats['size'])) { $this->size = $stats['size']; return $this->size; } return null; } public function isReadable(): bool { return $this->readable; } public function isWritable(): bool { return $this->writable; } public function isSeekable(): bool { return $this->seekable; } public function eof(): bool { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } return feof($this->stream); } public function tell(): int { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } $result = ftell($this->stream); if ($result === false) { throw new \RuntimeException('Unable to determine stream position'); } return $result; } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { if (!\is_int($offset)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $offset.', \get_debug_type($offset) ); } if (!\is_int($whence)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $whence.', \get_debug_type($whence) ); } $whence = (int) $whence; if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->seekable) { throw new \RuntimeException('Stream is not seekable'); } if (fseek($this->stream, $offset, $whence) === -1) { throw new \RuntimeException('Unable to seek to stream position ' .$offset.' with whence '.var_export($whence, true)); } } public function read($length): string { if (!\is_int($length)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::read() is deprecated; guzzlehttp/psr7 3.0 requires int for $length.', \get_debug_type($length) ); } if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->readable) { throw new \RuntimeException('Cannot read from non-readable stream'); } if ($length < 0) { throw new \RuntimeException('Length parameter cannot be negative'); } if (0 === $length) { return ''; } try { $string = fread($this->stream, $length); } catch (\Exception $e) { throw new \RuntimeException('Unable to read from stream', 0, $e); } if (false === $string) { throw new \RuntimeException('Unable to read from stream'); } return $string; } public function write($string): int { if (!\is_string($string)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::write() is deprecated; guzzlehttp/psr7 3.0 requires string for $string.', \get_debug_type($string) ); } if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->writable) { throw new \RuntimeException('Cannot write to a non-writable stream'); } // We can't know the size after writing anything $this->size = null; $result = fwrite($this->stream, $string); if ($result === false) { throw new \RuntimeException('Unable to write to stream'); } return $result; } /** * @return mixed */ public function getMetadata($key = null) { if ($key !== null && !\is_string($key)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::getMetadata() is deprecated; guzzlehttp/psr7 3.0 requires string|null for $key.', \get_debug_type($key) ); } if (!isset($this->stream)) { return $key ? null : []; } elseif (!$key) { return $this->customMetadata + stream_get_meta_data($this->stream); } elseif (isset($this->customMetadata[$key])) { return $this->customMetadata[$key]; } $meta = stream_get_meta_data($this->stream); return $meta[$key] ?? null; } } stream = $stream; } /** * Magic method used to create a new stream if streams are not added in * the constructor of a decorator (e.g., LazyOpenStream). * * @return StreamInterface */ public function __get(string $name) { if ($name === 'stream') { $this->stream = $this->createStream(); return $this->stream; } throw new \UnexpectedValueException("$name not found on class"); } public function __toString(): string { try { if ($this->isSeekable()) { $this->seek(0); } return $this->getContents(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } public function getContents(): string { return Utils::copyToString($this); } /** * Allow decorators to implement custom methods * * @return mixed */ public function __call(string $method, array $args) { /** @var callable $callable */ $callable = [$this->stream, $method]; $result = ($callable)(...$args); // Always return the wrapped object if the result is a return $this return $result === $this->stream ? $this : $result; } public function close(): void { $this->stream->close(); } /** * @return mixed */ public function getMetadata($key = null) { if ($key !== null && !\is_string($key)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::getMetadata() is deprecated; guzzlehttp/psr7 3.0 requires string|null for $key.', \get_debug_type($key) ); } return $this->stream->getMetadata($key); } public function detach() { return $this->stream->detach(); } public function getSize(): ?int { return $this->stream->getSize(); } public function eof(): bool { return $this->stream->eof(); } public function tell(): int { return $this->stream->tell(); } public function isReadable(): bool { return $this->stream->isReadable(); } public function isWritable(): bool { return $this->stream->isWritable(); } public function isSeekable(): bool { return $this->stream->isSeekable(); } public function rewind(): void { $this->seek(0); } public function seek($offset, $whence = SEEK_SET): void { if (!\is_int($offset)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $offset.', \get_debug_type($offset) ); } if (!\is_int($whence)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::seek() is deprecated; guzzlehttp/psr7 3.0 requires int for $whence.', \get_debug_type($whence) ); } $this->stream->seek($offset, $whence); } public function read($length): string { if (!\is_int($length)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::read() is deprecated; guzzlehttp/psr7 3.0 requires int for $length.', \get_debug_type($length) ); } return $this->stream->read($length); } public function write($string): int { if (!\is_string($string)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to StreamInterface::write() is deprecated; guzzlehttp/psr7 3.0 requires string for $string.', \get_debug_type($string) ); } return $this->stream->write($string); } /** * Implement in subclasses to dynamically create streams when requested. * * @throws \BadMethodCallException */ protected function createStream(): StreamInterface { throw new \BadMethodCallException('Not implemented'); } } isReadable()) { $mode = $stream->isWritable() ? 'r+' : 'r'; } elseif ($stream->isWritable()) { $mode = 'w'; } else { throw new \InvalidArgumentException('The stream must be readable, ' .'writable, or both.'); } $resource = @fopen('guzzle://stream', $mode, false, self::createStreamContext($stream)); if ($resource === false) { throw new \RuntimeException('Unable to create stream resource'); } return $resource; } /** * Creates a stream context that can be used to open a stream as a php stream resource. * * @return resource */ public static function createStreamContext(StreamInterface $stream) { return stream_context_create([ 'guzzle' => ['stream' => $stream], ]); } /** * Registers the stream wrapper if needed */ public static function register(): void { if (!in_array('guzzle', stream_get_wrappers())) { stream_wrapper_register('guzzle', __CLASS__); } } public function stream_open(string $path, string $mode, int $options, ?string &$opened_path = null): bool { $options = stream_context_get_options($this->context); if (!isset($options['guzzle']['stream'])) { return false; } $this->mode = $mode; $this->stream = $options['guzzle']['stream']; return true; } public function stream_read(int $count): string { return $this->stream->read($count); } public function stream_write(string $data): int { return $this->stream->write($data); } public function stream_tell(): int { return $this->stream->tell(); } public function stream_eof(): bool { return $this->stream->eof(); } public function stream_seek(int $offset, int $whence): bool { $this->stream->seek($offset, $whence); return true; } /** * @return resource|false */ public function stream_cast(int $cast_as) { $stream = clone $this->stream; $resource = $stream->detach(); return $resource ?? false; } /** * @return array{ * dev: int, * ino: int, * mode: int, * nlink: int, * uid: int, * gid: int, * rdev: int, * size: int, * atime: int, * mtime: int, * ctime: int, * blksize: int, * blocks: int * }|false */ public function stream_stat() { if ($this->stream->getSize() === null) { return false; } static $modeMap = [ 'r' => 33060, 'rb' => 33060, 'r+' => 33206, 'w' => 33188, 'wb' => 33188, ]; return [ 'dev' => 0, 'ino' => 0, 'mode' => $modeMap[$this->mode], 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => $this->stream->getSize() ?: 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0, ]; } /** * @return array{ * dev: int, * ino: int, * mode: int, * nlink: int, * uid: int, * gid: int, * rdev: int, * size: int, * atime: int, * mtime: int, * ctime: int, * blksize: int, * blocks: int * } */ public function url_stat(string $path, int $flags): array { return [ 'dev' => 0, 'ino' => 0, 'mode' => 0, 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0, ]; } } 'UPLOAD_ERR_OK', UPLOAD_ERR_INI_SIZE => 'UPLOAD_ERR_INI_SIZE', UPLOAD_ERR_FORM_SIZE => 'UPLOAD_ERR_FORM_SIZE', UPLOAD_ERR_PARTIAL => 'UPLOAD_ERR_PARTIAL', UPLOAD_ERR_NO_FILE => 'UPLOAD_ERR_NO_FILE', UPLOAD_ERR_NO_TMP_DIR => 'UPLOAD_ERR_NO_TMP_DIR', UPLOAD_ERR_CANT_WRITE => 'UPLOAD_ERR_CANT_WRITE', UPLOAD_ERR_EXTENSION => 'UPLOAD_ERR_EXTENSION', ]; /** * @var string|null */ private $clientFilename; /** * @var string|null */ private $clientMediaType; /** * @var int */ private $error; /** * @var string|null */ private $file; /** * @var bool */ private $moved = false; /** * @var int|null */ private $size; /** * @var StreamInterface|null */ private $stream; /** * @param StreamInterface|string|resource $streamOrFile */ public function __construct( $streamOrFile, ?int $size, int $errorStatus, ?string $clientFilename = null, ?string $clientMediaType = null ) { $this->setError($errorStatus); $this->size = $size; $this->clientFilename = $clientFilename; $this->clientMediaType = $clientMediaType; if ($this->isOk()) { $this->setStreamOrFile($streamOrFile); } } /** * Depending on the value set file or stream variable * * @param StreamInterface|string|resource $streamOrFile * * @throws InvalidArgumentException */ private function setStreamOrFile($streamOrFile): void { if (is_string($streamOrFile)) { $this->file = $streamOrFile; } elseif (is_resource($streamOrFile)) { $this->stream = new Stream($streamOrFile); } elseif ($streamOrFile instanceof StreamInterface) { $this->stream = $streamOrFile; } else { throw new InvalidArgumentException( 'Invalid stream or file provided for UploadedFile' ); } } /** * @throws InvalidArgumentException */ private function setError(int $error): void { if (!isset(UploadedFile::ERROR_MAP[$error])) { throw new InvalidArgumentException( 'Invalid error status for UploadedFile' ); } $this->error = $error; } private static function isStringNotEmpty($param): bool { return is_string($param) && false === empty($param); } /** * Return true if there is no upload error */ private function isOk(): bool { return $this->error === UPLOAD_ERR_OK; } public function isMoved(): bool { return $this->moved; } /** * @throws RuntimeException if is moved or not ok */ private function validateActive(): void { if (false === $this->isOk()) { throw new RuntimeException(\sprintf('Cannot retrieve stream due to upload error (%s)', self::ERROR_MAP[$this->error])); } if ($this->isMoved()) { throw new RuntimeException('Cannot retrieve stream after it has already been moved'); } } public function getStream(): StreamInterface { $this->validateActive(); if ($this->stream instanceof StreamInterface) { return $this->stream; } /** @var string $file */ $file = $this->file; return new LazyOpenStream($file, 'r+'); } public function moveTo($targetPath): void { $this->validateActive(); if (false === self::isStringNotEmpty($targetPath)) { throw new InvalidArgumentException( 'Invalid path provided for move operation; must be a non-empty string' ); } if ($this->file) { $this->moved = PHP_SAPI === 'cli' ? rename($this->file, $targetPath) : move_uploaded_file($this->file, $targetPath); } else { Utils::copyToStream( $this->getStream(), new LazyOpenStream($targetPath, 'w') ); $this->moved = true; } if (false === $this->moved) { throw new RuntimeException( sprintf('Uploaded file could not be moved to %s', $targetPath) ); } } public function getSize(): ?int { return $this->size; } public function getError(): int { return $this->error; } public function getClientFilename(): ?string { return $this->clientFilename; } public function getClientMediaType(): ?string { return $this->clientMediaType; } } 80, 'https' => 443, 'ftp' => 21, 'gopher' => 70, 'nntp' => 119, 'news' => 119, 'telnet' => 23, 'tn3270' => 23, 'imap' => 143, 'pop' => 110, 'ldap' => 389, ]; private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26', '+' => '%2B']; /** @var string Uri scheme. */ private $scheme = ''; /** @var string Uri user info. */ private $userInfo = ''; /** @var string Uri host. */ private $host = ''; /** @var int|null Uri port. */ private $port; /** @var string Uri path. */ private $path = ''; /** @var string Uri query string. */ private $query = ''; /** @var string Uri fragment. */ private $fragment = ''; public function __construct(string $uri = '') { if ($uri !== '') { $parts = self::parse($uri); if ($parts === false) { throw new MalformedUriException("Unable to parse URI: $uri"); } try { $this->applyParts($parts); } catch (MalformedUriException $e) { throw $e; } catch (\InvalidArgumentException $e) { throw new MalformedUriException($e->getMessage(), 0, $e); } } } /** * UTF-8 aware \parse_url() replacement. * * The internal function produces broken output for non ASCII domain names * (IDN) when used with locales other than "C". * * On the other hand, cURL understands IDN correctly only when UTF-8 locale * is configured ("C.UTF-8", "en_US.UTF-8", etc.). * * @see https://bugs.php.net/bug.php?id=52923 * @see https://www.php.net/manual/en/function.parse-url.php#114817 * @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING * * @return array|false */ private static function parse(string $url) { if (self::isPathNoSchemeReference($url)) { return self::parsePathNoSchemeReference($url); } // Preserve bracketed IPv6 literals before encoding, including dotted IPv4 // tails. DEL (\x7F) is excluded so a raw-DEL host falls through to the // general path and is rejected rather than silently mutated by parse_url(). $prefix = ''; $ipv6Prefix = preg_match('%\A([0-9A-Za-z+.-]+://\[[^\]\x00-\x20\x7F/?#@]+\])(.*)\z%s', $url, $matches); if ($ipv6Prefix === false) { return false; } if ($ipv6Prefix === 1) { /** @var array{0:string, 1:string, 2:string} $matches */ $suffix = $matches[2]; // After the bracketed host only an optional numeric port and/or a // path, query, or fragment may follow. Anything else (for example // `:80@evil` or `:80x`) would let parse_url() reinterpret a // different host. if (preg_match('%\A(?::[0-9]*)?(?:[/?#].*)?\z%s', $suffix) !== 1) { return false; } $prefix = $matches[1]; $url = $suffix; } /** @var string|null */ $encodedUrl = preg_replace_callback( '%[^:/@?&=#]+%usD', static function ($matches) { return urlencode($matches[0]); }, $url ); if ($encodedUrl === null) { return false; } $result = parse_url($prefix.$encodedUrl); if ($result === false) { return false; } return array_map('urldecode', $result); } private static function isPathNoSchemeReference(string $url): bool { if ($url === '' || $url[0] === '/' || $url[0] === '?' || $url[0] === '#') { return false; } $firstSegment = substr($url, 0, strcspn($url, '/?#')); return strpos($firstSegment, ':') === false; } /** * @return array{path: string, query?: string, fragment?: string} */ private static function parsePathNoSchemeReference(string $url): array { $parts = []; if (false !== ($fragmentPosition = strpos($url, '#'))) { $parts['fragment'] = substr($url, $fragmentPosition + 1); $url = substr($url, 0, $fragmentPosition); } if (false !== ($queryPosition = strpos($url, '?'))) { $parts['query'] = substr($url, $queryPosition + 1); $url = substr($url, 0, $queryPosition); } $parts['path'] = $url; return $parts; } public function __toString(): string { return self::composeComponents( $this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment ); } /** * Composes a URI reference string from its various components. * * Usually this method does not need to be called manually but instead is used indirectly via * `Psr\Http\Message\UriInterface::__toString`. * * PSR-7 UriInterface treats an empty component the same as a missing component as * getQuery(), getFragment() etc. always return a string. This explains the slight * difference to RFC 3986 Section 5.3. * * Another adjustment is that the authority separator is added even when the authority is missing/empty * for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to * that format). * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.3 */ public static function composeComponents(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment): string { $uri = ''; // weak type checks to also accept null until we can add scalar type hints if ($scheme != '') { $uri .= $scheme.':'; } if ($authority != '' || $scheme === 'file') { $uri .= '//'.$authority; } if ($authority != '' && $path != '' && $path[0] != '/') { $path = '/'.$path; } $uri .= $path; if ($query != '') { $uri .= '?'.$query; } if ($fragment != '') { $uri .= '#'.$fragment; } return $uri; } /** * Whether the URI has the default port of the current scheme. * * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used * independently of the implementation. */ public static function isDefaultPort(UriInterface $uri): bool { return $uri->getPort() === null || (isset(self::DEFAULT_PORTS[$uri->getScheme()]) && $uri->getPort() === self::DEFAULT_PORTS[$uri->getScheme()]); } /** * Whether the URI is absolute, i.e. it has a scheme. * * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative * to another URI, the base URI. Relative references can be divided into several forms: * - network-path references, e.g. '//example.com/path' * - absolute-path references, e.g. '/path' * - relative-path references, e.g. 'subpath' * * @see Uri::isNetworkPathReference * @see Uri::isAbsolutePathReference * @see Uri::isRelativePathReference * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4 */ public static function isAbsolute(UriInterface $uri): bool { return $uri->getScheme() !== ''; } /** * Whether the URI is a network-path reference. * * A relative reference that begins with two slash characters is termed an network-path reference. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.2 */ public static function isNetworkPathReference(UriInterface $uri): bool { return $uri->getScheme() === '' && $uri->getAuthority() !== ''; } /** * Whether the URI is a absolute-path reference. * * A relative reference that begins with a single slash character is termed an absolute-path reference. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.2 */ public static function isAbsolutePathReference(UriInterface $uri): bool { return $uri->getScheme() === '' && $uri->getAuthority() === '' && isset($uri->getPath()[0]) && $uri->getPath()[0] === '/'; } /** * Whether the URI is a relative-path reference. * * A relative reference that does not begin with a slash character is termed a relative-path reference. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.2 */ public static function isRelativePathReference(UriInterface $uri): bool { return $uri->getScheme() === '' && $uri->getAuthority() === '' && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/'); } /** * Whether the URI is a same-document reference. * * A same-document reference refers to a URI that is, aside from its fragment * component, identical to the base URI. When no base URI is given, only an empty * URI reference (apart from its fragment) is considered a same-document reference. * * @param UriInterface $uri The URI to check * @param UriInterface|null $base An optional base URI to compare against * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.4 */ public static function isSameDocumentReference(UriInterface $uri, ?UriInterface $base = null): bool { if ($base !== null) { $uri = UriResolver::resolve($base, $uri); return ($uri->getScheme() === $base->getScheme()) && ($uri->getAuthority() === $base->getAuthority()) && ($uri->getPath() === $base->getPath()) && ($uri->getQuery() === $base->getQuery()); } return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === ''; } /** * Creates a new URI with a specific query string value removed. * * Any existing query string values that exactly match the provided key are * removed. * * @param UriInterface $uri URI to use as a base. * @param string $key Query string key to remove. */ public static function withoutQueryValue(UriInterface $uri, string $key): UriInterface { $result = self::getFilteredQueryString($uri, [$key]); return $uri->withQuery(implode('&', $result)); } /** * Creates a new URI with a specific query string value. * * Any existing query string values that exactly match the provided key are * removed and replaced with the given key value pair. * * A value of null will set the query string key without a value, e.g. "key" * instead of "key=value". * * @param UriInterface $uri URI to use as a base. * @param string $key Key to set. * @param string|null $value Value to set */ public static function withQueryValue(UriInterface $uri, string $key, ?string $value): UriInterface { $result = self::getFilteredQueryString($uri, [$key]); $result[] = self::generateQueryString($key, $value); return $uri->withQuery(implode('&', $result)); } /** * Creates a new URI with multiple specific query string values. * * It has the same behavior as withQueryValue() but for an associative array of key => value. * * @param UriInterface $uri URI to use as a base. * @param (string|null)[] $keyValueArray Associative array of key and values */ public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface { $result = self::getFilteredQueryString($uri, array_keys($keyValueArray)); foreach ($keyValueArray as $key => $value) { $result[] = self::generateQueryString((string) $key, $value !== null ? self::stringifyQueryValue($value) : null); } return $uri->withQuery(implode('&', $result)); } /** * Stringifies a non-null query value, deprecating non-string values that * guzzlehttp/psr7 3.0 will reject. Non-finite floats are normalized to the * strings PHP coerces them to, as implicit coercion of NAN emits a warning * on PHP 8.5. * * @param mixed $value */ private static function stringifyQueryValue($value): string { if (!is_string($value)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.12', 'Passing %s to Uri::withQueryValues() is deprecated; cast it to a string. guzzlehttp/psr7 3.0 will only accept string or null query values.', \gettype($value) ); if (is_float($value) && !is_finite($value)) { return is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF'); } } return (string) $value; } /** * Creates a URI from a hash of `parse_url` components. * * @see https://www.php.net/manual/en/function.parse-url.php * * @throws MalformedUriException If the components do not form a valid URI. */ public static function fromParts(array $parts): UriInterface { $uri = new self(); try { $uri->applyParts($parts); $uri->validateState(); } catch (MalformedUriException $e) { throw $e; } catch (\InvalidArgumentException $e) { throw new MalformedUriException($e->getMessage(), 0, $e); } return $uri; } /** * @throws \InvalidArgumentException If the host is invalid. * * @internal */ public static function assertValidHost(string $host): void { if ($host === '') { return; } // Reject control characters and URI authority delimiters so getHost() // cannot disagree with the on-wire authority. $invalidHost = preg_match('/[\x00-\x20\x7F\/\?#@\\\\]/', $host); if ($invalidHost === false) { throw new \RuntimeException('Unable to validate URI host: '.preg_last_error_msg()); } if ($invalidHost === 1) { throw new \InvalidArgumentException(sprintf('Invalid host: "%s"', $host)); } if (strpos($host, '[') !== false || strpos($host, ']') !== false) { if ($host[0] !== '[' || substr($host, -1) !== ']') { throw new \InvalidArgumentException(sprintf('Invalid host: "%s"', $host)); } return; } if (strpos($host, ':') !== false) { throw new \InvalidArgumentException(sprintf('Invalid host: "%s"', $host)); } } public function getScheme(): string { return $this->scheme; } public function getAuthority(): string { $authority = $this->host; if ($this->userInfo !== '') { $authority = $this->userInfo.'@'.$authority; } if ($this->port !== null) { $authority .= ':'.$this->port; } return $authority; } public function getUserInfo(): string { return $this->userInfo; } public function getHost(): string { return $this->host; } public function getPort(): ?int { return $this->port; } public function getPath(): string { return $this->path; } public function getQuery(): string { return $this->query; } public function getFragment(): string { return $this->fragment; } public function withScheme($scheme): UriInterface { $scheme = $this->filterScheme($scheme); if ($this->scheme === $scheme) { return $this; } $new = clone $this; $new->scheme = $scheme; $new->removeDefaultPort(); $new->validateState(); return $new; } public function withUserInfo($user, $password = null): UriInterface { $info = $this->filterUserInfoComponent($user); if ($password !== null) { $info .= ':'.$this->filterUserInfoComponent($password); } if ($this->userInfo === $info) { return $this; } $new = clone $this; $new->userInfo = $info; $new->validateState(); return $new; } public function withHost($host): UriInterface { $host = $this->filterHost($host); if ($this->host === $host) { return $this; } $new = clone $this; $new->host = $host; $new->validateState(); return $new; } public function withPort($port): UriInterface { if ($port !== null && !\is_int($port)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to UriInterface::withPort() is deprecated; guzzlehttp/psr7 3.0 requires int|null.', \get_debug_type($port) ); } $port = $this->filterPort($port); if ($this->port === $port) { return $this; } $new = clone $this; $new->port = $port; $new->removeDefaultPort(); $new->validateState(); return $new; } public function withPath($path): UriInterface { $path = $this->filterPath($path); if ($this->path === $path) { return $this; } $new = clone $this; $new->path = $path; $new->validateState(); return $new; } public function withQuery($query): UriInterface { $query = $this->filterQueryAndFragment($query); if ($this->query === $query) { return $this; } $new = clone $this; $new->query = $query; return $new; } public function withFragment($fragment): UriInterface { $fragment = $this->filterQueryAndFragment($fragment); if ($this->fragment === $fragment) { return $this; } $new = clone $this; $new->fragment = $fragment; return $new; } public function jsonSerialize(): string { return $this->__toString(); } /** * Apply parse_url parts to a URI. * * @param array $parts Array of parse_url parts to apply. */ private function applyParts(array $parts): void { $this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : ''; $this->userInfo = isset($parts['user']) ? $this->filterUserInfoComponent($parts['user']) : ''; $this->host = isset($parts['host']) ? $this->filterHost($parts['host']) : ''; $this->port = isset($parts['port']) ? $this->filterPort($parts['port']) : null; $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; $this->query = isset($parts['query']) ? $this->filterQueryAndFragment($parts['query']) : ''; $this->fragment = isset($parts['fragment']) ? $this->filterQueryAndFragment($parts['fragment']) : ''; if (isset($parts['pass'])) { $this->userInfo .= ':'.$this->filterUserInfoComponent($parts['pass']); } $this->removeDefaultPort(); } /** * @param mixed $scheme * * @throws \InvalidArgumentException If the scheme is invalid. */ private function filterScheme($scheme): string { if (!is_string($scheme)) { throw new \InvalidArgumentException('Scheme must be a string'); } $scheme = Utils::asciiToLower($scheme); if ($scheme !== '' && !preg_match('/^[a-z][a-z0-9.+-]*$/D', $scheme)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing "%s" as a URI scheme is deprecated; guzzlehttp/psr7 3.0 requires URI schemes to match RFC 3986 syntax and begin with a letter.', $scheme ); } return $scheme; } /** * @param mixed $component * * @throws \InvalidArgumentException If the user info is invalid. */ private function filterUserInfoComponent($component): string { if (!is_string($component)) { throw new \InvalidArgumentException('User info must be a string'); } return $this->filterComponent( '/(?:[^%'.Rfc3986::CHAR_UNRESERVED.Rfc3986::CHAR_SUB_DELIMS.']+|%(?![A-Fa-f0-9]{2}))/', $component, 'Unable to filter URI user info' ); } /** * @param mixed $host * * @throws \InvalidArgumentException If the host is invalid. */ private function filterHost($host): string { if (!is_string($host)) { throw new \InvalidArgumentException('Host must be a string'); } $host = Utils::asciiToLower($host); self::assertValidHost($host); return $host; } /** * @param mixed $port * * @throws \InvalidArgumentException If the port is invalid. */ private function filterPort($port): ?int { if ($port === null) { return null; } $port = (int) $port; if (0 > $port || 0xFFFF < $port) { throw new \InvalidArgumentException( sprintf('Invalid port: %d. Must be between 0 and 65535', $port) ); } return $port; } /** * @param (string|int)[] $keys * * @return string[] */ private static function getFilteredQueryString(UriInterface $uri, array $keys): array { $current = $uri->getQuery(); if ($current === '') { return []; } $decodedKeys = array_map(function ($k): string { return rawurldecode((string) $k); }, $keys); return array_filter(explode('&', $current), function ($part) use ($decodedKeys) { return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true); }); } private static function generateQueryString(string $key, ?string $value): string { // Query string separators ("=", "&") and literal plus signs ("+") within the // key or value need to be encoded // (while preventing double-encoding) before setting the query string. All other // chars that need percent-encoding will be encoded by withQuery(). $queryString = strtr($key, self::QUERY_SEPARATORS_REPLACEMENT); if ($value !== null) { $queryString .= '='.strtr($value, self::QUERY_SEPARATORS_REPLACEMENT); } return $queryString; } private function removeDefaultPort(): void { if ($this->port !== null && self::isDefaultPort($this)) { $this->port = null; } } /** * Filters the path of a URI * * @param mixed $path * * @throws \InvalidArgumentException If the path is invalid. */ private function filterPath($path): string { if (!is_string($path)) { throw new \InvalidArgumentException('Path must be a string'); } return $this->filterComponent( '/(?:[^'.Rfc3986::CHAR_UNRESERVED.Rfc3986::CHAR_SUB_DELIMS.'%:@\/]++|%(?![A-Fa-f0-9]{2}))/', $path, 'Unable to filter URI path' ); } /** * Filters the query string or fragment of a URI. * * @param mixed $str * * @throws \InvalidArgumentException If the query or fragment is invalid. */ private function filterQueryAndFragment($str): string { if (!is_string($str)) { throw new \InvalidArgumentException('Query and fragment must be a string'); } return $this->filterComponent( '/(?:[^'.Rfc3986::CHAR_UNRESERVED.Rfc3986::CHAR_SUB_DELIMS.'%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', $str, 'Unable to filter URI query or fragment' ); } private function filterComponent(string $pattern, string $component, string $context): string { $filtered = preg_replace_callback($pattern, [$this, 'rawurlencodeMatchZero'], $component); if ($filtered === null) { throw new \RuntimeException($context.': '.preg_last_error_msg()); } return $filtered; } private function rawurlencodeMatchZero(array $match): string { return rawurlencode($match[0]); } private function validateState(): void { if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) { $this->host = self::HTTP_DEFAULT_HOST; } if ($this->getAuthority() === '') { if (0 === strpos($this->path, '//')) { throw new MalformedUriException('The path of a URI without an authority must not start with two slashes "//"'); } if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) { throw new MalformedUriException('A relative URI must not have a path beginning with a segment containing a colon'); } } } } getHost(), $modified->getHost())) { return true; } if ($original->getScheme() !== $modified->getScheme()) { return true; } if (self::computePort($original) !== self::computePort($modified)) { return true; } return false; } private static function computePort(UriInterface $uri): ?int { $port = $uri->getPort(); if (null !== $port) { return $port; } if ('http' === $uri->getScheme()) { return 80; } if ('https' === $uri->getScheme()) { return 443; } return null; } private function __construct() { // cannot be instantiated } } getPath() === '' && ($uri->getScheme() === 'http' || $uri->getScheme() === 'https') ) { $uri = $uri->withPath('/'); } if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') { $uri = $uri->withHost(''); } if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) { $uri = $uri->withPort(null); } if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) { $uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath())); } if ($flags & self::REMOVE_DUPLICATE_SLASHES) { $path = preg_replace('#//++#', '/', $uri->getPath()); if ($path === null) { throw new \RuntimeException('Unable to remove duplicate slashes from URI path: '.preg_last_error_msg()); } $uri = $uri->withPath($path); } if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') { $queryKeyValues = explode('&', $uri->getQuery()); sort($queryKeyValues); $uri = $uri->withQuery(implode('&', $queryKeyValues)); } return $uri; } /** * Whether two URIs can be considered equivalent. * * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be * resolved against the same base URI. If this is not the case, determination of equivalence or difference of * relative references does not mean anything. * * @param UriInterface $uri1 An URI to compare * @param UriInterface $uri2 An URI to compare * @param int $normalizations A bitmask of normalizations to apply, see constants * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-6.1 */ public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, int $normalizations = self::PRESERVING_NORMALIZATIONS): bool { return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations); } private static function capitalizePercentEncoding(UriInterface $uri): UriInterface { $regex = '/(?:%[A-Fa-f0-9]{2})++/'; $callback = function (array $match): string { return Utils::asciiToUpper($match[0]); }; return $uri ->withPath(self::normalizePercentEncodingInComponent($uri->getPath(), $regex, $callback)) ->withQuery(self::normalizePercentEncodingInComponent($uri->getQuery(), $regex, $callback)) ->withFragment(self::normalizePercentEncodingInComponent($uri->getFragment(), $regex, $callback)); } private static function decodeUnreservedCharacters(UriInterface $uri): UriInterface { $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i'; $callback = function (array $match): string { return rawurldecode($match[0]); }; return $uri ->withPath(self::normalizePercentEncodingInComponent($uri->getPath(), $regex, $callback)) ->withQuery(self::normalizePercentEncodingInComponent($uri->getQuery(), $regex, $callback)) ->withFragment(self::normalizePercentEncodingInComponent($uri->getFragment(), $regex, $callback)); } /** * @param callable(array): string $callback */ private static function normalizePercentEncodingInComponent(string $component, string $regex, callable $callback): string { $normalized = preg_replace_callback($regex, $callback, $component); if ($normalized === null) { throw new \RuntimeException('Unable to normalize URI component percent-encoding: '.preg_last_error_msg()); } return $normalized; } private function __construct() { // cannot be instantiated } } getScheme() != '') { return $rel->withPath(self::removeDotSegments($rel->getPath())); } if ($rel->getAuthority() != '') { return $rel ->withScheme($base->getScheme()) ->withPath(self::removeDotSegments($rel->getPath())); } if ($rel->getPath() === '') { $targetPath = $base->getPath(); $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery(); } else { if ($rel->getPath()[0] === '/') { $targetPath = $rel->getPath(); } else { if ($base->getAuthority() != '' && $base->getPath() === '') { $targetPath = '/'.$rel->getPath(); } else { $lastSlashPos = strrpos($base->getPath(), '/'); if ($lastSlashPos === false) { $targetPath = $rel->getPath(); } else { $targetPath = substr($base->getPath(), 0, $lastSlashPos + 1).$rel->getPath(); } } } $targetPath = self::removeDotSegments($targetPath); $targetQuery = $rel->getQuery(); } return $base ->withPath($targetPath) ->withQuery($targetQuery) ->withFragment($rel->getFragment()); } /** * Returns the target URI as a relative reference from the base URI. * * This method is the counterpart to resolve(): * * (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target)) * * One use-case is to use the current request URI as base URI and then generate relative links in your documents * to reduce the document size or offer self-contained downloadable document archives. * * $base = new Uri('http://example.com/a/b/'); * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'. * echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'. * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'. * echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'. * * This method also accepts a target that is already relative and will try to relativize it further. Only a * relative-path reference will be returned as-is. * * echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well */ public static function relativize(UriInterface $base, UriInterface $target): UriInterface { if ($target->getScheme() !== '' && ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '') ) { return $target; } if (Uri::isRelativePathReference($target)) { // As the target is already highly relative we return it as-is. It would be possible to resolve // the target with `$target = self::resolve($base, $target);` and then try make it more relative // by removing a duplicate query. But let's not do that automatically. return $target; } if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) { return $target->withScheme(''); } // We must remove the path before removing the authority because if the path starts with two slashes, the URI // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also // invalid. $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost(''); if ($base->getPath() !== $target->getPath()) { return $emptyPathUri->withPath(self::getRelativePath($base, $target)); } if ($base->getQuery() === $target->getQuery()) { // Only the target fragment is left. And it must be returned even if base and target fragment are the same. return $emptyPathUri->withQuery(''); } // If the base URI has a query but the target has none, we cannot return an empty path reference as it would // inherit the base query component when resolving. if ($target->getQuery() === '') { $segments = explode('/', $target->getPath()); /** @var string $lastSegment */ $lastSegment = end($segments); return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment); } return $emptyPathUri; } private static function getRelativePath(UriInterface $base, UriInterface $target): string { $sourceSegments = explode('/', $base->getPath()); $targetSegments = explode('/', $target->getPath()); array_pop($sourceSegments); $targetLastSegment = array_pop($targetSegments); foreach ($sourceSegments as $i => $segment) { if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) { unset($sourceSegments[$i], $targetSegments[$i]); } else { break; } } $targetSegments[] = $targetLastSegment; $relativePath = str_repeat('../', count($sourceSegments)).implode('/', $targetSegments); // A reference to am empty last segment or an empty first sub-segment 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. if ('' === $relativePath || false !== strpos(explode('/', $relativePath, 2)[0], ':')) { $relativePath = "./$relativePath"; } elseif ('/' === $relativePath[0]) { if ($base->getAuthority() != '' && $base->getPath() === '') { // In this case an extra slash is added by resolve() automatically. So we must not add one here. $relativePath = ".$relativePath"; } else { $relativePath = "./$relativePath"; } } return $relativePath; } private function __construct() { // cannot be instantiated } } $v) { if (!in_array(self::asciiToLower((string) $k), $keys)) { $result[$k] = $v; } } return $result; } /** * Copy the contents of a stream into another stream until the given number * of bytes have been read. * * The copy stops if the destination write returns 0, for example a * BufferStream at its high water mark or a full DroppingStream. For a * guaranteed full copy use a normal writable stream such as a file or * php://temp stream. * * @param StreamInterface $source Stream to read from * @param StreamInterface $dest Stream to write to * @param int $maxLen Maximum number of bytes to read. Pass -1 * to read the entire stream. * * @throws \RuntimeException on error. */ public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void { $bufferSize = 8192; if ($maxLen === -1) { while (!$source->eof()) { $buf = $source->read($bufferSize); if ($buf === '') { break; } if (!self::writeAll($dest, $buf)) { break; } } } else { $remaining = $maxLen; while ($remaining > 0 && !$source->eof()) { $buf = $source->read(min($bufferSize, $remaining)); $len = strlen($buf); if (!$len) { break; } $remaining -= $len; if (!self::writeAll($dest, $buf)) { break; } } } } /** * Writes the full buffer to the destination, retrying short writes. * * Returns false when the destination write returns 0 or less. */ private static function writeAll(StreamInterface $dest, string $buf): bool { $written = 0; $len = strlen($buf); while ($written < $len) { $result = $dest->write(substr($buf, $written)); if ($result <= 0) { return false; } $written += $result; } return true; } /** * Copy the contents of a stream into a string until the given number of * bytes have been read. * * @param StreamInterface $stream Stream to read * @param int $maxLen Maximum number of bytes to read. Pass -1 * to read the entire stream. * * @throws \RuntimeException on error. */ public static function copyToString(StreamInterface $stream, int $maxLen = -1): string { $buffer = ''; if ($maxLen === -1) { while (!$stream->eof()) { $buf = $stream->read(1048576); if ($buf === '') { break; } $buffer .= $buf; } return $buffer; } $len = 0; while (!$stream->eof() && $len < $maxLen) { $buf = $stream->read($maxLen - $len); if ($buf === '') { break; } $buffer .= $buf; $len = strlen($buffer); } return $buffer; } /** * Calculate a hash of a stream. * * This method reads the entire stream to calculate a rolling hash, based * on PHP's `hash_init` functions. * * @param StreamInterface $stream Stream to calculate the hash for * @param string $algo Hash algorithm (e.g. md5, crc32, etc) * @param bool $rawOutput Whether or not to use raw output * * @throws \RuntimeException on error. */ public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string { $pos = $stream->tell(); if ($pos > 0) { $stream->rewind(); } $ctx = hash_init($algo); while (!$stream->eof()) { hash_update($ctx, $stream->read(1048576)); } $out = hash_final($ctx, $rawOutput); $stream->seek($pos); return $out; } /** * Clone and modify a request with the given changes. * * This method is useful for reducing the number of clones needed to mutate * a message. * * The changes can be one of: * - method: (string) Changes the HTTP method. * - set_headers: (array) Sets the given headers. Values must be strings * or non-empty arrays of strings. * - remove_headers: (array) Remove the given headers. Values may be * strings or integers. * - body: (mixed) Sets the given body. Present non-null values are converted * with self::streamFor(), including scalar values, resources, streams, * iterators, callable arrays, closures, invokable objects, and objects * with __toString(). String inputs remain literal bodies. * - uri: (UriInterface) Set the URI. * - query: (string) Set the query string value of the URI. * - version: (string) Set the protocol version. * * @param RequestInterface $request Request to clone and modify. * @param array $changes Changes to apply. */ public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface { if (!$changes) { return $request; } self::warnOnInvalidModifyRequestChanges($changes); $headers = $request->getHeaders(); if (!isset($changes['uri'])) { $uri = $request->getUri(); } else { // Remove the host header if one is on the URI $host = $changes['uri']->getHost(); if ($host !== '') { if (isset($changes['set_headers']) && is_array($changes['set_headers'])) { foreach (array_keys($changes['set_headers']) as $header) { if (self::asciiToLower((string) $header) === 'host') { throw new \InvalidArgumentException( 'Cannot modify request with both a URI containing a host and an explicit Host header.' ); } } } $changes['set_headers']['Host'] = $host; if ($port = $changes['uri']->getPort()) { $standardPorts = ['http' => 80, 'https' => 443]; $scheme = $changes['uri']->getScheme(); if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) { $changes['set_headers']['Host'] .= ':'.$port; } } } $uri = $changes['uri']; } if (!empty($changes['remove_headers'])) { $headers = self::caselessRemove($changes['remove_headers'], $headers); } if (!empty($changes['set_headers'])) { $headers = self::caselessRemove(array_keys($changes['set_headers']), $headers); $headers = $changes['set_headers'] + $headers; } if (isset($changes['query'])) { $uri = $uri->withQuery($changes['query']); } $hasHost = false; foreach (array_keys($headers) as $header) { if (self::asciiToLower((string) $header) === 'host') { $hasHost = true; break; } } // Match Request::__construct() by adding a Host header when one is not provided. if (!$hasHost && $uri->getHost() !== '') { $host = $uri->getHost(); if (($port = $uri->getPort()) !== null) { $host .= ':'.$port; } $headers = ['Host' => [$host]] + $headers; } $new = $request; if (isset($changes['method'])) { $new = $new->withMethod($changes['method']); } if (isset($changes['uri']) || isset($changes['query'])) { $new = $new->withUri($uri, true); } if ($headers !== $new->getHeaders()) { foreach (array_keys($new->getHeaders()) as $header) { /** @var RequestInterface */ $new = $new->withoutHeader((string) $header); } $addedHeaders = []; foreach ($headers as $header => $value) { $header = (string) $header; $normalized = self::asciiToLower($header); if (isset($addedHeaders[$normalized])) { /** @var RequestInterface */ $new = $new->withAddedHeader($addedHeaders[$normalized], $value); } else { /** @var RequestInterface */ $new = $new->withHeader($header, $value); $addedHeaders[$normalized] = $header; } } } if (isset($changes['body'])) { /** @var RequestInterface */ $new = $new->withBody(self::streamFor($changes['body'])); } if (isset($changes['version'])) { /** @var RequestInterface */ $new = $new->withProtocolVersion($changes['version']); } return $new; } /** * @param array $changes */ private static function warnOnInvalidModifyRequestChanges(array $changes): void { foreach (['method', 'query', 'version'] as $key) { if (\array_key_exists($key, $changes) && !\is_string($changes[$key])) { self::warnOnInvalidModifyRequestChange($key, 'string', $changes[$key]); } } if (\array_key_exists('uri', $changes) && !$changes['uri'] instanceof UriInterface) { self::warnOnInvalidModifyRequestChange('uri', 'UriInterface', $changes['uri']); } if (\array_key_exists('body', $changes) && $changes['body'] === null) { self::warnOnInvalidModifyRequestChange('body', 'resource|string|int|float|bool|StreamInterface|callable|\Iterator|\Stringable', $changes['body']); } if (\array_key_exists('set_headers', $changes)) { if (!\is_array($changes['set_headers'])) { self::warnOnInvalidModifyRequestChange('set_headers', 'array>', $changes['set_headers']); } else { foreach ($changes['set_headers'] as $header => $value) { $headerPath = \sprintf('set_headers.%s', (string) $header); if (\is_array($value)) { if ($value === []) { self::warnOnInvalidModifyRequestChange($headerPath, 'string|non-empty-array', $value); break; } foreach ($value as $index => $item) { if (!\is_string($item)) { self::warnOnInvalidModifyRequestChange(\sprintf('%s.%s', $headerPath, (string) $index), 'string', $item); break 2; } } } elseif (!\is_string($value)) { self::warnOnInvalidModifyRequestChange($headerPath, 'string|non-empty-array', $value); break; } } } } if (!\array_key_exists('remove_headers', $changes)) { return; } if (!\is_array($changes['remove_headers'])) { self::warnOnInvalidModifyRequestChange('remove_headers', 'array', $changes['remove_headers']); return; } foreach ($changes['remove_headers'] as $index => $header) { if (!\is_string($header) && !\is_int($header)) { self::warnOnInvalidModifyRequestChange(\sprintf('remove_headers.%s', (string) $index), 'string|int', $header); return; } } } /** * @param mixed $value */ private static function warnOnInvalidModifyRequestChange(string $key, string $expected, $value): void { \trigger_deprecation( 'guzzlehttp/psr7', '2.11', 'Passing %s to Utils::modifyRequest() change "%s" is deprecated; guzzlehttp/psr7 3.0 requires %s.', \get_debug_type($value), $key, $expected ); } /** * Read a line from the stream up to the maximum allowed buffer length. * * @param StreamInterface $stream Stream to read from * @param int|null $maxLength Maximum buffer length */ public static function readLine(StreamInterface $stream, ?int $maxLength = null): string { $buffer = ''; $size = 0; while (!$stream->eof()) { if ('' === ($byte = $stream->read(1))) { return $buffer; } $buffer .= $byte; // Break when a new line is found or the max length - 1 is reached if ($byte === "\n" || ++$size === $maxLength - 1) { break; } } return $buffer; } /** * Redact the password in the user info part of a URI. */ public static function redactUserInfo(UriInterface $uri): UriInterface { $userInfo = $uri->getUserInfo(); if (false !== ($pos = \strpos($userInfo, ':'))) { return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***'); } return $uri; } /** * Create a new stream based on the input type. * * Options is an associative array that can contain the following keys: * - metadata: Array of custom metadata. * - size: Size of the stream. * * This method accepts the following `$resource` types: * - `Psr\Http\Message\StreamInterface`: Returns the value as-is. * - `string`: Creates a stream object that uses the given string as the contents. * - `resource`: Creates a stream object that wraps the given PHP stream resource. * - `Iterator`: If the provided value implements `Iterator`, then a read-only * stream object will be created that wraps the given iterable. Each time the * stream is read from, data from the iterator will fill a buffer and will be * continuously called until the buffer is equal to the requested read size. * Subsequent read calls will first read from the buffer and then call `next` * on the underlying iterator until it is exhausted. * - `object` with `__toString()`: If the object has the `__toString()` method, * the object will be cast to a string and then a stream will be returned that * uses the string value. * - `NULL`: When `null` is passed, an empty stream object is returned. * - `callable`: When a callable array, closure, or invokable object is passed * and no earlier resource or object rule applies, a read-only stream object * will be created that invokes the given callable. The callable is invoked * with the suggested number of bytes to read. The callable can return fewer * or more bytes than requested, but MUST return `false` or `null` when there * is no more data to return. Any additional bytes will be buffered and used * in subsequent reads. String inputs are always treated as string bodies, * even when they name callable functions. * * Passing a non-string scalar (`int`, `float`, or `bool`) is deprecated; cast * it to a string instead. guzzlehttp/psr7 3.0 will reject non-string scalars. * * @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data * @param array{size?: int, metadata?: array} $options Additional options * * @throws \InvalidArgumentException if the $resource arg is not valid. */ public static function streamFor($resource = '', array $options = []): StreamInterface { if (is_scalar($resource)) { if (!is_string($resource)) { \trigger_deprecation( 'guzzlehttp/psr7', '2.12', 'Passing %s to Utils::streamFor() is deprecated; cast it to a string. guzzlehttp/psr7 3.0 will only accept string, resource, StreamInterface, Stringable, Iterator, callable, or null.', \gettype($resource) ); if (is_float($resource) && !is_finite($resource)) { // Normalized only to avoid PHP 8.5's (string) NAN warning // while deprecated; 3.0 rejects non-finite floats with every // other non-string scalar. $resource = is_nan($resource) ? 'NAN' : ($resource > 0 ? 'INF' : '-INF'); } } $stream = self::tryFopen('php://temp', 'r+'); if ($resource !== '') { fwrite($stream, (string) $resource); fseek($stream, 0); } return new Stream($stream, $options); } switch (gettype($resource)) { case 'resource': /* * The 'php://input' is a special stream with quirks and inconsistencies. * We avoid using that stream by reading it into php://temp */ /** @var resource $resource */ if ((\stream_get_meta_data($resource)['uri'] ?? '') === 'php://input') { $stream = self::tryFopen('php://temp', 'w+'); stream_copy_to_stream($resource, $stream); fseek($stream, 0); $resource = $stream; } return new Stream($resource, $options); case 'object': /** @var object $resource */ if ($resource instanceof StreamInterface) { return $resource; } elseif ($resource instanceof \Iterator) { return new PumpStream(function () use ($resource) { if (!$resource->valid()) { return false; } $result = $resource->current(); $resource->next(); return $result; }, $options); } elseif (method_exists($resource, '__toString')) { return self::streamFor((string) $resource, $options); } break; case 'NULL': return new Stream(self::tryFopen('php://temp', 'r+'), $options); } if (is_callable($resource)) { return new PumpStream($resource, $options); } throw new \InvalidArgumentException('Invalid resource type: '.gettype($resource)); } /** * Safely opens a PHP stream resource using a filename. * * When fopen fails, PHP normally raises a warning. This function adds an * error handler that checks for errors and throws an exception instead. * * @param string $filename File to open * @param string $mode Mode used to open the file * * @return resource * * @throws \RuntimeException if the file cannot be opened */ public static function tryFopen(string $filename, string $mode) { $ex = null; set_error_handler(static function (int $errno, string $errstr) use ($filename, $mode, &$ex): bool { $ex = new \RuntimeException(sprintf( 'Unable to open "%s" using mode "%s": %s', $filename, $mode, $errstr )); return true; }); try { /** @var resource $handle */ $handle = fopen($filename, $mode); } catch (\Throwable $e) { $ex = new \RuntimeException(sprintf( 'Unable to open "%s" using mode "%s": %s', $filename, $mode, $e->getMessage() ), 0, $e); } restore_error_handler(); if ($ex) { /** @var \RuntimeException $ex */ throw $ex; } return $handle; } /** * Safely gets the contents of a given stream. * * When stream_get_contents fails, PHP normally raises a warning. This * function adds an error handler that checks for errors and throws an * exception instead. * * @param resource $stream * * @throws \RuntimeException if the stream cannot be read */ public static function tryGetContents($stream): string { $ex = null; set_error_handler(static function (int $errno, string $errstr) use (&$ex): bool { $ex = new \RuntimeException(sprintf( 'Unable to read stream contents: %s', $errstr )); return true; }); try { /** @var string|false $contents */ $contents = stream_get_contents($stream); if ($contents === false) { $ex = new \RuntimeException('Unable to read stream contents'); } } catch (\Throwable $e) { $ex = new \RuntimeException(sprintf( 'Unable to read stream contents: %s', $e->getMessage() ), 0, $e); } restore_error_handler(); if ($ex) { /** @var \RuntimeException $ex */ throw $ex; } return $contents; } /** * Returns a UriInterface for the given value. * * This function accepts a string or UriInterface and returns a * UriInterface for the given value. If the value is already a * UriInterface, it is returned as-is. * * @param string|UriInterface $uri * * @throws \InvalidArgumentException */ public static function uriFor($uri): UriInterface { if ($uri instanceof UriInterface) { return $uri; } if (is_string($uri)) { return new Uri($uri); } throw new \InvalidArgumentException('URI must be a string or UriInterface'); } } Copyright (c) 2013-2015 KNP 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": "knplabs/packagist-api", "type": "library", "description": "Packagist API client.", "keywords": ["packagist", "api", "composer"], "homepage": "http://knplabs.com", "license": "MIT", "authors": [ { "name": "KnpLabs Team", "homepage": "http://knplabs.com" } ], "require": { "php": "^7.1 || ^8.0", "guzzlehttp/guzzle": "^6.0 || ^7.0", "doctrine/inflector": "^1.0 || ^2.0" }, "require-dev": { "phpspec/phpspec": "^5.1 || ^6.0 || ^7.0", "squizlabs/php_codesniffer": "^3.0" }, "config": { "bin-dir": "bin" }, "autoload": { "psr-0": { "Packagist\\Api\\": "src/" } }, "extra": { "branch-alias": { "dev-master": "1.x-dev" } }, "scripts": { "lint": "bin/phpcs --standard=PSR12 src/", "test": "bin/phpspec run -f pretty" } } httpClient = $httpClient; $this->resultFactory = $resultFactory; $this->packagistUrl = $packagistUrl; } /** * Search packages * * Available filters : * * * vendor: vendor of package (require or require-dev in composer.json) * * type: type of package (type in composer.json) * * tags: tags of package (keywords in composer.json) * * @since 1.0 * * @param string $query Name of package * @param array $filters An array of filters * @param int $limit Pages to limit results (0 = all pages) * * @return array The results */ public function search($query, array $filters = array(), int $limit = 0) { $results = $response = array(); $filters['q'] = $query; $url = '/search.json?' . http_build_query($filters); $response['next'] = $this->url($url); do { $response = $this->request($response['next']); $response = $this->parse($response); $createResult = $this->create($response); if (!is_array($createResult)) { $createResult = [$createResult]; } $results = array_merge($results, $createResult); if (isset($response['next'])) { parse_str(parse_url($response['next'], PHP_URL_QUERY), $parse); } } while (isset($response['next']) && (0 === $limit || $parse['page'] <= $limit)); return $results; } /** * Retrieve full package information * * @since 1.0 * * @param string $package Full qualified name ex : myname/mypackage * * @return array|\Packagist\Api\Result\Package A package instance or array of packages */ public function get($package) { return $this->respond(sprintf($this->url('/packages/%s.json'), $package)); } /** * Search packages * * Available filters : * * * vendor: vendor of package (require or require-dev in composer.json) * * type: type of package (type in composer.json) * * tags: tags of package (keywords in composer.json) * * @since 1.0 * * @param array $filters An array of filters * * @return array|\Packagist\Api\Result\Package The results, or single result */ public function all(array $filters = array()) { $url = '/packages/list.json'; if ($filters) { $url .= '?' . http_build_query($filters); } return $this->respond($this->url($url)); } /** * Popular packages * * @since 1.3 * * @param int $total * @return array The results */ public function popular($total) { $results = $response = array(); $url = '/explore/popular.json?' . http_build_query(array('page' => 1)); $response['next'] = $this->url($url); do { $response = $this->request($response['next']); $response = $this->parse($response); $createResult = $this->create($response); if (!is_array($createResult)) { $createResult = [$createResult]; } $results = array_merge($results, $createResult); } while (count($results) < $total && isset($response['next'])); return array_slice($results, 0, $total); } /** * Assemble the packagist URL with the route * * @param string $route API Route that we want to achieve * * @return string Fully qualified URL */ protected function url($route) { return $this->packagistUrl . $route; } /** * Execute the url request and parse the response * * @param string $url * * @return array|\Packagist\Api\Result\Package */ protected function respond($url) { $response = $this->request($url); $response = $this->parse($response); return $this->create($response); } /** * Execute the url request * * @param string $url * * @return \Psr\Http\Message\StreamInterface */ protected function request($url) { if (null === $this->httpClient) { $this->httpClient = new HttpClient(); } return $this->httpClient ->request('GET', $url) ->getBody(); } /** * Decode json * * @param string $data Json string * * @return array Json decode */ protected function parse($data) { return json_decode($data, true); } /** * Hydrate the knowing type depending on passed data * * @param array $data * * @return array|\Packagist\Api\Result\Package */ protected function create(array $data) { if (null === $this->resultFactory) { $this->resultFactory = new Factory(); } return $this->resultFactory->create($data); } /** * Change the packagist URL * * @since 1.1 * * @param string $packagistUrl URL */ public function setPackagistUrl($packagistUrl) { $this->packagistUrl = $packagistUrl; } /** * Return the actual packagist URL * * @since 1.1 * * @return string|null URL */ public function getPackagistUrl() { return $this->packagistUrl; } } build() : null; foreach ($data as $key => $value) { $property = null === $inflector ? Inflector::camelize($key) : $inflector->camelize($key); $this->$property = $value; } } } createSearchResults($data['results']); } if (isset($data['packages'])) { return $this->createSearchResults($data['packages']); } if (isset($data['package'])) { return $this->createPackageResults($data['package']); } if (isset($data['packageNames'])) { return $data['packageNames']; } throw new InvalidArgumentException('Invalid input data.'); } /** * Create a collection of \Packagist\Api\Result\Result * @param array $results * * @return array */ public function createSearchResults(array $results) { $created = array(); foreach ($results as $key => $result) { $created[$key] = $this->createResult('Packagist\Api\Result\Result', $result); } return $created; } /** * Parse array to \Packagist\Api\Result\Result * @param array $package * * @return Package */ public function createPackageResults(array $package) { $created = array(); if (isset($package['maintainers']) && $package['maintainers']) { foreach ($package['maintainers'] as $key => $maintainer) { $package['maintainers'][$key] = $this->createResult( 'Packagist\Api\Result\Package\Maintainer', $maintainer ); } } if (isset($package['downloads']) && $package['downloads']) { $package['downloads'] = $this->createResult( 'Packagist\Api\Result\Package\Downloads', $package['downloads'] ); } $package['description'] = (string) $package['description'] ?? ''; foreach ($package['versions'] as $branch => $version) { if (isset($version['authors']) && $version['authors']) { foreach ($version['authors'] as $key => $author) { $version['authors'][$key] = $this->createResult('Packagist\Api\Result\Package\Author', $author); } } if ($version['source']) { $version['source'] = $this->createResult('Packagist\Api\Result\Package\Source', $version['source']); } if (isset($version['dist']) && $version['dist']) { $version['dist'] = $this->createResult('Packagist\Api\Result\Package\Dist', $version['dist']); } $package['versions'][$branch] = $this->createResult('Packagist\Api\Result\Package\Version', $version); } $created = new Package(); $created->fromArray($package); return $created; } /** * Dynamically create DataObject of type $class and hydrate * * @param string $class DataObject class * @param array $data Array of data * * @return mixed DataObject $class hydrated */ protected function createResult($class, array $data) { $result = new $class(); $result->fromArray($data); return $result; } } name; } /** * @return string */ public function getDescription() { return $this->description; } /** * @return string */ public function getTime() { return $this->time; } /** * @return Package\Maintainer[] */ public function getMaintainers() { return $this->maintainers; } /** * @return Package\Version[] */ public function getVersions() { return $this->versions; } /** * @return string */ public function getType() { return $this->type; } /** * @return string */ public function getRepository() { return $this->repository; } /** * @return Package\Downloads */ public function getDownloads() { return $this->downloads; } /** * @return string */ public function getFavers() { return $this->favers; } /** * @return bool */ public function isAbandoned() { return (bool) $this->abandoned; } /** * Gets the package name to use as a replacement if this package is abandoned * * @return string|null */ public function getReplacementPackage(): ?string { // The Packagist API will either return a boolean, or a string value for `abandoned`. It will be a boolean // if no replacement package was provided when the package was marked as abandoned in Packagist, or it will be // a string containing the replacement package name to use if one was provided. // @see https://github.com/KnpLabs/packagist-api/pull/56#discussion_r306426997 if (is_string($this->abandoned)) { return $this->abandoned; } return null; } /** * @return integer */ public function getSuggesters() { return $this->suggesters; } /** * @return integer */ public function getDependents() { return $this->dependents; } /** * @return integer */ public function getGithubStars() { return $this->githubStars; } /** * @return integer */ public function getGithubForks() { return $this->githubForks; } } role; } } shasum; } /** * @return string */ public function getType() { return $this->type; } /** * @return string */ public function getUrl() { return $this->url; } /** * @return string */ public function getReference() { return $this->reference; } } total = $total; } /** * @param integer $monthly */ public function setMonthly($monthly) { $this->monthly = $monthly; } /** * @param integer $daily */ public function setDaily($daily) { $this->daily = $daily; } /** * @return integer */ public function getTotal() { return $this->total; } /** * @return integer */ public function getMonthly() { return $this->monthly; } /** * @return integer */ public function getDaily() { return $this->daily; } } name; } /** * @return string */ public function getEmail() { return $this->email; } /** * @return string */ public function getHomepage() { return $this->homepage; } } type; } /** * @return string */ public function getUrl() { return $this->url; } /** * @return string */ public function getReference() { return $this->reference; } } name; } /** * @return string */ public function getDescription() { return $this->description; } /** * @return array */ public function getKeywords() { return $this->keywords; } /** * @return string */ public function getHomepage() { return $this->homepage; } /** * @return string */ public function getVersion() { return $this->version; } /** * @return string */ public function getVersionNormalized() { return $this->versionNormalized; } /** * @return string */ public function getLicense() { return $this->license; } /** * @return array */ public function getAuthors() { return $this->authors; } /** * @return Source */ public function getSource() { return $this->source; } /** * @return Dist */ public function getDist() { return $this->dist; } /** * @return string */ public function getType() { return $this->type; } /** * @return string */ public function getTime() { return $this->time; } /** * @return array */ public function getAutoload() { return $this->autoload; } /** * @return array */ public function getExtra() { return $this->extra; } /** * @return array */ public function getRequire() { return $this->require; } /** * @return array */ public function getRequireDev() { return $this->requireDev; } /** * @return string */ public function getConflict() { return $this->conflict; } /** * @return string */ public function getProvide() { return $this->provide; } /** * @return string */ public function getReplace() { return $this->replace; } /** * @return string */ public function getBin() { return $this->bin; } /** * @return array */ public function getSuggest() { return $this->suggest; } /** * @return bool */ public function isAbandoned() { return (bool) $this->abandoned; } /** * Gets the package name to use as a replacement if this package is abandoned * * @return string|null */ public function getReplacementPackage(): ?string { // The Packagist API will either return a boolean, or a string value for `abandoned`. It will be a boolean // if no replacement package was provided when the package was marked as abandoned in Packagist, or it will be // a string containing the replacement package name to use if one was provided. // @see https://github.com/KnpLabs/packagist-api/pull/56#discussion_r306426997 if (is_string($this->abandoned)) { return $this->abandoned; } return null; } } name; } /** * @return string */ public function getDescription() { return $this->description; } /** * @return string */ public function getUrl() { return $this->url; } /** * @return string */ public function getDownloads() { return $this->downloads; } /** * @return string */ public function getFavers() { return $this->favers; } /** * @return string */ public function getRepository() { return $this->repository; } } The MIT License (MIT) Copyright (c) Taylor Otwell 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. # Serializable Closure Build Status Total Downloads Latest Stable Version License ## Introduction > This project is a fork of the excellent [opis/closure: 3.x](https://github.com/opis/closure) package. At Laravel, we decided to fork this package as the upcoming version [4.x](https://github.com/opis/closure) is a complete rewrite on top of the [FFI extension](https://www.php.net/manual/en/book.ffi.php). As Laravel is a web framework, and FFI is not enabled by default in web requests, this fork allows us to keep using the `3.x` series while adding support for new PHP versions. Laravel Serializable Closure provides an easy and secure way to **serialize closures in PHP**. ## Official Documentation ### Installation > **Requires [PHP 7.4+](https://php.net/releases/)** First, install Laravel Serializable Closure via the [Composer](https://getcomposer.org/) package manager: ```bash composer require laravel/serializable-closure ``` ### Usage You may serialize a closure this way: ```php use Laravel\SerializableClosure\SerializableClosure; $closure = fn () => 'james'; // Recommended SerializableClosure::setSecretKey('secret'); $serialized = serialize(new SerializableClosure($closure)); $closure = unserialize($serialized)->getClosure(); echo $closure(); // james; ``` ### Caveats * Serializing closures on REPL environments like Laravel Tinker is not supported. * Multiple closures defined on the same source line with identical signatures may not be distinguishable after serialization. Place each closure on its own line to avoid this. ## Contributing Thank you for considering contributing to Serializable Closure! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). ## Code of Conduct In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). ## Security Vulnerabilities Please review [our security policy](https://github.com/laravel/serializable-closure/security/policy) on how to report security vulnerabilities. ## License Serializable Closure is open-sourced software licensed under the [MIT license](LICENSE.md). { "name": "laravel/serializable-closure", "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", "keywords": ["laravel", "Serializable", "closure"], "license": "MIT", "support": { "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" }, { "name": "Nuno Maduro", "email": "nuno@laravel.com" } ], "require": { "php": "^8.1" }, "require-dev": { "illuminate/support": "^10.0|^11.0|^12.0|^13.0", "nesbot/carbon": "^2.67|^3.0", "pestphp/pest": "^2.36|^3.0|^4.0", "phpstan/phpstan": "^2.0", "symfony/var-dumper": "^6.2.0|^7.0.0|^8.0.0" }, "autoload": { "psr-4": { "Laravel\\SerializableClosure\\": "src/" } }, "autoload-dev": { "psr-4": { "Tests\\": "tests/" } }, "extra": { "branch-alias": { "dev-master": "2.x-dev" } }, "config": { "allow-plugins": { "pestphp/pest-plugin": true }, "audit": { "block-insecure": false }, "sort-packages": true }, "minimum-stability": "dev", "prefer-stable": true } serializable = Serializers\Signed::$signer ? new Serializers\Signed($closure) : new Serializers\Native($closure); } /** * Resolve the closure with the given arguments. * * @return mixed */ public function __invoke() { return call_user_func_array($this->serializable, func_get_args()); } /** * Gets the closure. * * @return \Closure */ public function getClosure() { return $this->serializable->getClosure(); } /** * Create a new unsigned serializable closure instance. * * @param Closure $closure * @return \Laravel\SerializableClosure\UnsignedSerializableClosure */ public static function unsigned(Closure $closure) { return new UnsignedSerializableClosure($closure); } /** * Sets the serializable closure secret key. * * @param string|null $secret * @return void */ public static function setSecretKey($secret) { Serializers\Signed::$signer = $secret ? new Hmac($secret) : null; } /** * Sets the transformer that should be used when serializing use variables. * * @param \Closure|null $transformer * @return void */ public static function transformUseVariablesUsing($transformer) { Serializers\Native::$transformUseVariables = $transformer; } /** * Sets the resolver that should be used when unserializing use variables. * * @param \Closure|null $resolver * @return void */ public static function resolveUseVariablesUsing($resolver) { Serializers\Native::$resolveUseVariables = $resolver; } /** * Get the serializable representation of the closure. * * @return array{serializable: \Laravel\SerializableClosure\Serializers\Signed|\Laravel\SerializableClosure\Contracts\Serializable} */ public function __serialize() { return [ 'serializable' => $this->serializable, ]; } /** * Restore the closure after serialization. * * @param array{serializable: \Laravel\SerializableClosure\Serializers\Signed|\Laravel\SerializableClosure\Contracts\Serializable} $data * @return void * * @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException */ public function __unserialize($data) { if (Signed::$signer && ! $data['serializable'] instanceof Signed) { throw new InvalidSignatureException(); } $this->serializable = $data['serializable']; } } closure = $closure; } /** * Resolve the closure with the given arguments. * * @return mixed */ public function __invoke() { return call_user_func_array($this->closure, func_get_args()); } /** * Gets the closure. * * @return \Closure */ public function getClosure() { return $this->closure; } /** * Get the serializable representation of the closure. * * @return array */ public function __serialize() { if ($this->scope === null) { $this->scope = new ClosureScope(); $this->scope->toSerialize++; } $this->scope->serializations++; $scope = $object = null; $reflector = $this->getReflector(); if ($reflector->isBindingRequired()) { $object = $reflector->getClosureThis(); static::wrapClosures($object, $this->scope); } if ($scope = $reflector->getClosureScopeClass()) { if (! $scope->isAnonymous() || $reflector->isBindingRequired() || $reflector->isScopeRequired()) { $scope = $scope->name; } else { $scope = null; } } $this->reference = spl_object_hash($this->closure); $this->scope[$this->closure] = $this; $use = $reflector->getUseVariables(); if (static::$transformUseVariables) { $use = call_user_func(static::$transformUseVariables, $reflector->getUseVariables()); } $code = $reflector->getCode(); $this->mapByReference($use); $data = [ 'use' => $use, 'function' => $code, 'scope' => $scope, 'this' => $object, 'self' => $this->reference, ]; if (! --$this->scope->serializations && ! --$this->scope->toSerialize) { $this->scope = null; } return $data; } /** * Restore the closure after serialization. * * @param array $data * @return void */ public function __unserialize($data) { ClosureStream::register(); $this->code = $data; unset($data); $this->code['objects'] = []; if ($this->code['use']) { $this->scope = new ClosureScope(); if (static::$resolveUseVariables) { $this->code['use'] = call_user_func(static::$resolveUseVariables, $this->code['use']); } $this->mapPointers($this->code['use']); extract($this->code['use'], EXTR_OVERWRITE | EXTR_REFS); $this->scope = null; } $this->closure = include ClosureStream::STREAM_PROTO.'://'.$this->code['function']; if ($this->code['this'] === $this) { $this->code['this'] = null; } $this->closure = $this->closure->bindTo($this->code['this'], $this->code['scope']); if (! empty($this->code['objects'])) { foreach ($this->code['objects'] as $item) { static::setPropertyValue( $item['property'], $item['instance'], $item['object'] instanceof SerializableClosure || $item['object'] instanceof UnsignedSerializableClosure ? $item['object'] : $item['object']->getClosure() ); } } $this->code = $this->code['function']; } /** * Ensures the given closures are serializable. * * @param mixed $data * @param \Laravel\SerializableClosure\Support\ClosureScope $storage * @return void */ public static function wrapClosures(&$data, $storage) { if ($data instanceof Closure) { $data = new static($data); } elseif (is_array($data)) { if (isset($data[self::ARRAY_RECURSIVE_KEY])) { return; } $data[self::ARRAY_RECURSIVE_KEY] = true; foreach ($data as $key => &$value) { if ($key === self::ARRAY_RECURSIVE_KEY) { continue; } static::wrapClosures($value, $storage); } unset($value); unset($data[self::ARRAY_RECURSIVE_KEY]); } elseif ($data instanceof \stdClass) { if (isset($storage[$data])) { $data = $storage[$data]; return; } $data = $storage[$data] = clone $data; foreach ($data as &$value) { static::wrapClosures($value, $storage); } unset($value); } elseif (is_object($data) && ! $data instanceof static && ! $data instanceof UnitEnum) { if (isset($storage[$data])) { $data = $storage[$data]; return; } $instance = $data; $reflection = new ReflectionObject($instance); if (! $reflection->isUserDefined()) { $storage[$instance] = $data; return; } $storage[$instance] = $data = $reflection->newInstanceWithoutConstructor(); do { if (! $reflection->isUserDefined()) { break; } foreach ($reflection->getProperties() as $property) { if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined() || static::isVirtualProperty($property)) { continue; } if (! $property->isInitialized($instance)) { continue; } $value = static::getPropertyValue($property, $instance); if (static::isClosureTypedProperty($property)) { static::setPropertyValue($property, $data, $value); continue; } if (is_array($value) || is_object($value)) { static::wrapClosures($value, $storage); } static::setPropertyValue($property, $data, $value); } } while ($reflection = $reflection->getParentClass()); } } /** * Gets the closure's reflector. * * @return \Laravel\SerializableClosure\Support\ReflectionClosure */ public function getReflector() { if ($this->reflector === null) { $this->code = null; $this->reflector = new ReflectionClosure($this->closure); } return $this->reflector; } /** * Internal method used to map closure pointers. * * @param mixed $data * @return void */ protected function mapPointers(&$data) { if ($data instanceof SerializableClosure || $data instanceof UnsignedSerializableClosure) { return; } $scope = $this->scope; if ($data instanceof static) { $data = &$data->closure; } elseif (is_array($data)) { if (isset($data[self::ARRAY_RECURSIVE_KEY])) { return; } $data[self::ARRAY_RECURSIVE_KEY] = true; foreach ($data as $key => &$value) { if ($key === self::ARRAY_RECURSIVE_KEY) { continue; } elseif ($value instanceof static) { $data[$key] = &$value->closure; } elseif ($value instanceof SelfReference && $value->hash === $this->code['self']) { $data[$key] = &$this->closure; } else { $this->mapPointers($value); } } unset($value); unset($data[self::ARRAY_RECURSIVE_KEY]); } elseif ($data instanceof \stdClass) { if (isset($scope[$data])) { return; } $scope[$data] = true; foreach ($data as $key => &$value) { if ($value instanceof SelfReference && $value->hash === $this->code['self']) { $data->{$key} = &$this->closure; } elseif ($value instanceof static) { $data->{$key} = &$value->closure; } elseif (is_array($value) || is_object($value)) { $this->mapPointers($value); } } unset($value); } elseif (is_object($data) && ! ($data instanceof Closure)) { if (isset($scope[$data])) { return; } $scope[$data] = true; $reflection = new ReflectionObject($data); do { if (! $reflection->isUserDefined()) { break; } foreach ($reflection->getProperties() as $property) { if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined() || static::isVirtualProperty($property)) { continue; } if (! $property->isInitialized($data) || $property->isReadOnly()) { continue; } $item = static::getPropertyValue($property, $data); if ($item instanceof SerializableClosure || $item instanceof UnsignedSerializableClosure || ($item instanceof SelfReference && $item->hash === $this->code['self'])) { $this->code['objects'][] = [ 'instance' => $data, 'property' => $property, 'object' => $item instanceof SelfReference ? $this : $item, ]; } elseif ($item instanceof static) { static::setPropertyValue($property, $data, $item->closure); } elseif (is_array($item) || is_object($item)) { $this->mapPointers($item); static::setPropertyValue($property, $data, $item); } } } while ($reflection = $reflection->getParentClass()); } } /** * Internal method used to map closures by reference. * * @param mixed $data * @return void */ protected function mapByReference(&$data) { if ($data instanceof Closure) { if ($data === $this->closure) { $data = new SelfReference($this->reference); return; } if (isset($this->scope[$data])) { $data = $this->scope[$data]; return; } $instance = new static($data); $instance->scope = $this->scope; $data = $this->scope[$data] = $instance; } elseif (is_array($data)) { if (isset($data[self::ARRAY_RECURSIVE_KEY])) { return; } $data[self::ARRAY_RECURSIVE_KEY] = true; foreach ($data as $key => &$value) { if ($key === self::ARRAY_RECURSIVE_KEY) { continue; } $this->mapByReference($value); } unset($value); unset($data[self::ARRAY_RECURSIVE_KEY]); } elseif ($data instanceof \stdClass) { if (isset($this->scope[$data])) { $data = $this->scope[$data]; return; } $instance = $data; $this->scope[$instance] = $data = clone $data; foreach ($data as &$value) { $this->mapByReference($value); } unset($value); } elseif (is_object($data) && ! $data instanceof SerializableClosure && ! $data instanceof UnsignedSerializableClosure) { if (isset($this->scope[$data])) { $data = $this->scope[$data]; return; } $instance = $data; if ($data instanceof DateTimeInterface) { $this->scope[$instance] = $data; return; } if ($data instanceof UnitEnum) { $this->scope[$instance] = $data; return; } $reflection = new ReflectionObject($data); if (! $reflection->isUserDefined()) { $this->scope[$instance] = $data; return; } $this->scope[$instance] = $data = $reflection->newInstanceWithoutConstructor(); do { if (! $reflection->isUserDefined()) { break; } foreach ($reflection->getProperties() as $property) { if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined() || static::isVirtualProperty($property)) { continue; } if (! $property->isInitialized($instance) || ($property->isReadOnly() && $property->class !== $reflection->name)) { continue; } $value = static::getPropertyValue($property, $instance); if (static::isClosureTypedProperty($property)) { static::setPropertyValue($property, $data, $value); continue; } if (is_array($value) || is_object($value)) { $this->mapByReference($value); } static::setPropertyValue($property, $data, $value); } } while ($reflection = $reflection->getParentClass()); } } /** * Get the value of a property, bypassing hooks on PHP 8.4+. * * @param \ReflectionProperty $property * @param object $object * @return mixed */ protected static function getPropertyValue(ReflectionProperty $property, object $object): mixed { return PHP_VERSION_ID >= 80400 ? $property->getRawValue($object) : $property->getValue($object); } /** * Set the value of a property, bypassing hooks on PHP 8.4+. * * @param \ReflectionProperty $property * @param object $object * @param mixed $value * @return void */ protected static function setPropertyValue(ReflectionProperty $property, object $object, mixed $value): void { PHP_VERSION_ID >= 80400 ? $property->setRawValue($object, $value) : $property->setValue($object, $value); } /** * Determine is virtual property. * * @param \ReflectionProperty $property * @return bool */ protected static function isVirtualProperty(ReflectionProperty $property): bool { return method_exists($property, 'isVirtual') && $property->isVirtual(); } /** * Determine if property is typed as Closure. * * @param \ReflectionProperty $property * @return bool */ protected static function isClosureTypedProperty(ReflectionProperty $property): bool { $type = $property->getType(); if ($type instanceof \ReflectionNamedType) { return $type->getName() === 'Closure'; } if ($type instanceof \ReflectionUnionType || $type instanceof \ReflectionIntersectionType) { foreach ($type->getTypes() as $t) { if ($t instanceof \ReflectionNamedType && $t->getName() === 'Closure') { return true; } } } return false; } } closure = $closure; } /** * Resolve the closure with the given arguments. * * @return mixed */ public function __invoke() { return call_user_func_array($this->closure, func_get_args()); } /** * Gets the closure. * * @return \Closure */ public function getClosure() { return $this->closure; } /** * Get the serializable representation of the closure. * * @return array */ public function __serialize() { if (! static::$signer) { throw new MissingSecretKeyException(); } return static::$signer->sign( serialize(new Native($this->closure)) ); } /** * Restore the closure after serialization. * * @param array{serializable: string, hash: string} $signature * @return void * * @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException */ public function __unserialize($signature) { if (static::$signer && ! static::$signer->verify($signature)) { throw new InvalidSignatureException(); } /** @var \Laravel\SerializableClosure\Contracts\Serializable $serializable */ $serializable = unserialize($signature['serializable']); $this->closure = $serializable->getClosure(); } } secret = $secret; } /** * Sign the given serializable. * * @param string $serialized * @return array */ public function sign($serialized) { return [ 'serializable' => $serialized, 'hash' => base64_encode(hash_hmac('sha256', $serialized, $this->secret, true)), ]; } /** * Verify the given signature. * * @param array{serializable: string, hash: string} $signature * @return bool */ public function verify($signature) { return hash_equals(base64_encode( hash_hmac('sha256', $signature['serializable'], $this->secret, true) ), $signature['hash']); } } content = "length = strlen($this->content); return true; } /** * Read from stream. * * @param int $count * @return string */ public function stream_read($count) { $value = substr($this->content, $this->pointer, $count); $this->pointer += $count; return $value; } /** * Tests for end-of-file on a file pointer. * * @return bool */ public function stream_eof() { return $this->pointer >= $this->length; } /** * Change stream options. * * @param int $option * @param int $arg1 * @param int $arg2 * @return bool */ public function stream_set_option($option, $arg1, $arg2) { return false; } /** * Retrieve information about a file resource. * * @return array|bool */ public function stream_stat() { $stat = stat(__FILE__); // @phpstan-ignore-next-line $stat[7] = $stat['size'] = $this->length; return $stat; } /** * Retrieve information about a file. * * @param string $path * @param int $flags * @return array|bool */ public function url_stat($path, $flags) { $stat = stat(__FILE__); // @phpstan-ignore-next-line $stat[7] = $stat['size'] = $this->length; return $stat; } /** * Seeks to specific location in a stream. * * @param int $offset * @param int $whence * @return bool */ public function stream_seek($offset, $whence = SEEK_SET) { $crt = $this->pointer; switch ($whence) { case SEEK_SET: $this->pointer = $offset; break; case SEEK_CUR: $this->pointer += $offset; break; case SEEK_END: $this->pointer = $this->length + $offset; break; } if ($this->pointer < 0 || $this->pointer >= $this->length) { $this->pointer = $crt; return false; } return true; } /** * Retrieve the current position of a stream. * * @return int */ public function stream_tell() { return $this->pointer; } /** * Registers the stream. * * @return void */ public static function register() { if (! static::$isRegistered) { static::$isRegistered = stream_wrapper_register(static::STREAM_PROTO, __CLASS__); } } } isStaticClosure === null) { $this->isStaticClosure = strtolower(substr($this->getCode(), 0, 6)) === 'static'; } return $this->isStaticClosure; } /** * Checks if the closure is a "short closure". * * @return bool */ public function isShortClosure() { if ($this->isShortClosure === null) { $code = $this->getCode(); if ($this->isStatic()) { $code = substr($code, 6); } $this->isShortClosure = strtolower(substr(trim($code), 0, 2)) === 'fn'; } return $this->isShortClosure; } /** * Get the closure's code. * * @return string */ public function getCode() { if ($this->code !== null) { return $this->code; } $fileName = $this->getFileName(); $line = $this->getStartLine() - 1; $className = null; if (null !== $className = $this->getClosureScopeClass()) { $className = '\\'.trim($className->getName(), '\\'); } $builtin_types = self::getBuiltinTypes(); $class_keywords = ['self', 'static', 'parent']; $ns = $this->getClosureNamespaceName(); $nsf = $ns == '' ? '' : ($ns[0] == '\\' ? $ns : '\\'.$ns); $_file = var_export($fileName, true); $_dir = var_export(dirname($fileName), true); $_namespace = var_export($ns, true); $_class = var_export(trim($className ?: '', '\\'), true); $_function = $ns.($ns == '' ? '' : '\\').'{closure}'; $_method = ($className == '' ? '' : trim($className, '\\').'::').$_function; $_function = var_export($_function, true); $_method = var_export($_method, true); $_trait = null; $tokens = $this->getTokens(); $state = $lastState = 'start'; $inside_structure = false; $isFirstClassCallable = false; $isShortClosure = false; $inside_structure_mark = 0; $open = 0; $code = ''; $id_start = $id_start_ci = $id_name = $context = ''; $classes = $functions = $constants = null; $use = []; $lineAdd = 0; $isUsingScope = false; $isUsingThisObject = false; $closureArgsInnerFuncCount = 0; $closureArgsBraceDepth = 0; $candidates = []; for ($i = 0, $l = count($tokens); $i < $l; $i++) { $token = $tokens[$i]; switch ($state) { case 'start': if ($token[0] === T_FUNCTION || $token[0] === T_STATIC) { $code .= $token[1]; $state = $token[0] === T_FUNCTION ? 'function' : 'static'; } elseif ($token[0] === T_FN) { $isShortClosure = true; $code .= $token[1]; $state = 'closure_args'; } elseif ($token[0] === T_PUBLIC || $token[0] === T_PROTECTED || $token[0] === T_PRIVATE) { $code = ''; $isFirstClassCallable = true; } break; case 'static': if ($token[0] === T_WHITESPACE || $token[0] === T_COMMENT || $token[0] === T_FUNCTION) { $code .= $token[1]; if ($token[0] === T_FUNCTION) { $state = 'function'; } } elseif ($token[0] === T_FN) { $isShortClosure = true; $code .= $token[1]; $state = 'closure_args'; } else { $code = ''; $state = 'start'; } break; case 'function': switch ($token[0]) { case T_STRING: if ($isFirstClassCallable) { $state = 'closure_args'; break; } $code = ''; $state = 'named_function'; break; case '(': $code .= '('; $state = 'closure_args'; break; default: $code .= is_array($token) ? $token[1] : $token; } break; case 'named_function': if ($token[0] === T_FUNCTION || $token[0] === T_STATIC) { $code = $token[1]; $state = $token[0] === T_FUNCTION ? 'function' : 'static'; } elseif ($token[0] === T_FN) { $isShortClosure = true; $code .= $token[1]; $state = 'closure_args'; } break; case 'closure_args': $insideClosureArgsInner = $closureArgsBraceDepth > 0 || $closureArgsInnerFuncCount > 0; if ($insideClosureArgsInner) { switch ($token[0]) { case T_FUNCTION: $closureArgsInnerFuncCount++; $code .= $token[1]; break; case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: $closureArgsBraceDepth++; $code .= $token[1]; break; case '{': if ($closureArgsInnerFuncCount > 0) { $closureArgsInnerFuncCount--; } $closureArgsBraceDepth++; $code .= '{'; break; case '}': $closureArgsBraceDepth--; $code .= '}'; break; default: $code .= is_array($token) ? $token[1] : $token; } break; } switch ($token[0]) { case T_FUNCTION: $closureArgsInnerFuncCount++; $code .= $token[1]; break; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $context = 'args'; $state = 'id_name'; $lastState = 'closure_args'; break; case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $context = 'args'; $state = 'id_name'; $lastState = 'closure_args'; break; case T_USE: $code .= $token[1]; $state = 'use'; break; case T_DOUBLE_ARROW: $code .= $token[1]; if ($isShortClosure) { $state = 'closure'; } break; case ':': $code .= ':'; $state = 'return'; break; case '{': $code .= '{'; $state = 'closure'; $open++; break; default: $code .= is_array($token) ? $token[1] : $token; } break; case 'use': switch ($token[0]) { case T_VARIABLE: $use[] = substr($token[1], 1); $code .= $token[1]; break; case '{': $code .= '{'; $state = 'closure'; $open++; break; case ':': $code .= ':'; $state = 'return'; break; default: $code .= is_array($token) ? $token[1] : $token; break; } break; case 'return': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $code .= $token[1]; break; case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $context = 'return_type'; $state = 'id_name'; $lastState = 'return'; break 2; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $context = 'return_type'; $state = 'id_name'; $lastState = 'return'; break 2; case T_DOUBLE_ARROW: $code .= $token[1]; if ($isShortClosure) { $state = 'closure'; } break; case '{': $code .= '{'; $state = 'closure'; $open++; break; default: $code .= is_array($token) ? $token[1] : $token; break; } break; case 'closure': switch ($token[0]) { case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: case '{': $code .= is_array($token) ? $token[1] : $token; $open++; break; case '}': $code .= '}'; if (--$open === 0 && ! $isShortClosure) { $reset = $this->collectCandidate($candidates, $code, $use, $isShortClosure, $isUsingThisObject, $isUsingScope); $code = $reset['code']; $state = $reset['state']; $open = $reset['open']; $use = $reset['use']; $isShortClosure = $reset['isShortClosure']; $isUsingThisObject = $reset['isUsingThisObject']; $isUsingScope = $reset['isUsingScope']; $closureArgsInnerFuncCount = $reset['closureArgsInnerFuncCount']; $closureArgsBraceDepth = $reset['closureArgsBraceDepth']; } elseif ($inside_structure) { $inside_structure = ! ($open === $inside_structure_mark); } break; case '(': case '[': $code .= $token[0]; if ($isShortClosure) { $open++; } break; case ')': case ']': if ($isShortClosure) { if ($open === 0) { $reset = $this->collectCandidate($candidates, $code, $use, $isShortClosure, $isUsingThisObject, $isUsingScope); $code = $reset['code']; $state = $reset['state']; $open = $reset['open']; $use = $reset['use']; $isShortClosure = $reset['isShortClosure']; $isUsingThisObject = $reset['isUsingThisObject']; $isUsingScope = $reset['isUsingScope']; $closureArgsInnerFuncCount = $reset['closureArgsInnerFuncCount']; $closureArgsBraceDepth = $reset['closureArgsBraceDepth']; continue 3; } $open--; } $code .= $token[0]; break; case ',': case ';': if ($isShortClosure && $open === 0) { $reset = $this->collectCandidate($candidates, $code, $use, $isShortClosure, $isUsingThisObject, $isUsingScope); $code = $reset['code']; $state = $reset['state']; $open = $reset['open']; $use = $reset['use']; $isShortClosure = $reset['isShortClosure']; $isUsingThisObject = $reset['isUsingThisObject']; $isUsingScope = $reset['isUsingScope']; $closureArgsInnerFuncCount = $reset['closureArgsInnerFuncCount']; $closureArgsBraceDepth = $reset['closureArgsBraceDepth']; continue 3; } $code .= $token[0]; break; case T_LINE: $code .= $token[2] - $line + $lineAdd; break; case T_FILE: $code .= $_file; break; case T_DIR: $code .= $_dir; break; case T_NS_C: $code .= $_namespace; break; case T_CLASS_C: $code .= $inside_structure ? $token[1] : $_class; break; case T_FUNC_C: $code .= $inside_structure ? $token[1] : $_function; break; case T_METHOD_C: $code .= $inside_structure ? $token[1] : $_method; break; case T_COMMENT: if (substr($token[1], 0, 8) === '#trackme') { $timestamp = time(); $code .= '/**'.PHP_EOL; $code .= '* Date : '.date(DATE_W3C, $timestamp).PHP_EOL; $code .= '* Timestamp : '.$timestamp.PHP_EOL; $code .= '* Line : '.($line + 1).PHP_EOL; $code .= '* File : '.$_file.PHP_EOL.'*/'.PHP_EOL; $lineAdd += 5; } else { $code .= $token[1]; } break; case T_VARIABLE: if ($token[1] == '$this' && ! $inside_structure) { $isUsingThisObject = true; } $code .= $token[1]; break; case T_STATIC: case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $context = 'root'; $state = 'id_name'; $lastState = 'closure'; break 2; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $context = 'root'; $state = 'id_name'; $lastState = 'closure'; break 2; case T_NEW: $code .= $token[1]; $context = 'new'; $state = 'id_start'; $lastState = 'closure'; break 2; case T_USE: $code .= $token[1]; $context = 'use'; $state = 'id_start'; $lastState = 'closure'; break; case T_INSTANCEOF: case T_INSTEADOF: $code .= $token[1]; $context = 'instanceof'; $state = 'id_start'; $lastState = 'closure'; break; case T_OBJECT_OPERATOR: case T_NULLSAFE_OBJECT_OPERATOR: case T_DOUBLE_COLON: $code .= $token[1]; $lastState = 'closure'; $state = 'ignore_next'; break; case T_FUNCTION: $code .= $token[1]; $state = 'closure_args'; if (! $inside_structure) { $inside_structure = true; $inside_structure_mark = $open; } break; case T_TRAIT_C: if ($_trait === null) { $startLine = $this->getStartLine(); $endLine = $this->getEndLine(); $structures = $this->getStructures(); $_trait = ''; foreach ($structures as &$struct) { if ($struct['type'] === 'trait' && $struct['start'] <= $startLine && $struct['end'] >= $endLine ) { $_trait = ($ns == '' ? '' : $ns.'\\').$struct['name']; break; } } $_trait = var_export($_trait, true); } $code .= $_trait; break; default: $code .= is_array($token) ? $token[1] : $token; } break; case 'ignore_next': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $code .= $token[1]; break; case T_CLASS: case T_NEW: case T_STATIC: case T_VARIABLE: case T_STRING: case T_CLASS_C: case T_FILE: case T_DIR: case T_METHOD_C: case T_FUNC_C: case T_FUNCTION: case T_INSTANCEOF: case T_LINE: case T_NS_C: case T_TRAIT_C: case T_USE: $code .= $token[1]; $state = $lastState; break; default: $state = $lastState; $i--; } break; case 'id_start': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $code .= $token[1]; break; case T_NS_SEPARATOR: case T_NAME_FULLY_QUALIFIED: case T_STRING: case T_STATIC: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $state = 'id_name'; break 2; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $state = 'id_name'; break 2; case T_VARIABLE: $code .= $token[1]; $state = $lastState; break; case T_CLASS: $code .= $token[1]; $state = 'anonymous'; break; case '(': if ($context === 'instanceof') { $code .= '('; if ($isShortClosure) { $open++; } $state = $lastState; break; } // no break default: $i--; //reprocess last $state = 'id_name'; } break; case 'id_name': switch ($token[0]) { case $token[0] === ':' && ! in_array($context, ['instanceof', 'new'], true): if ($lastState === 'closure' && $context === 'root') { $state = 'closure'; $code .= $id_start.$token; } break; case T_NAME_QUALIFIED: case T_NS_SEPARATOR: case T_STRING: case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $id_name .= $token[1]; break; case '(': if ($isShortClosure) { $open++; } if ($context === 'new' || false !== strpos($id_name, '\\')) { if ($id_start_ci === 'self' || $id_start_ci === 'static') { if (! $inside_structure) { $isUsingScope = true; } } elseif ($id_start !== '\\' && ! in_array($id_start_ci, $class_keywords)) { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } else { if ($id_start !== '\\') { if ($functions === null) { $functions = $this->getFunctions(); } if (isset($functions[$id_start_ci])) { $id_start = $functions[$id_start_ci]; } elseif ($nsf !== '\\' && function_exists($nsf.'\\'.$id_start)) { $id_start = $nsf.'\\'.$id_start; // Cache it to functions array $functions[$id_start_ci] = $id_start; } } } $code .= $id_start.$id_name.'('; $state = $lastState; break; case T_VARIABLE: case T_DOUBLE_COLON: if ($id_start !== '\\') { if ($id_start_ci === 'self' || $id_start_ci === 'parent') { if (! $inside_structure) { $isUsingScope = true; } } elseif ($id_start_ci === 'static') { if (! $inside_structure) { $isUsingScope = $token[0] === T_DOUBLE_COLON; } } elseif (! in_array($id_start_ci, $builtin_types)) { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } $code .= $id_start.$id_name.$token[1]; $state = $token[0] === T_DOUBLE_COLON ? 'ignore_next' : $lastState; break; default: if ($id_start !== '\\' && ! defined($id_start)) { if ($constants === null) { $constants = $this->getConstants(); } if (isset($constants[$id_start])) { $id_start = $constants[$id_start]; } elseif ($context === 'new') { if (in_array($id_start_ci, $class_keywords)) { if (! $inside_structure) { $isUsingScope = true; } } else { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } elseif ($context === 'use' || $context === 'instanceof' || $context === 'args' || $context === 'return_type' || $context === 'extends' || $context === 'root' ) { if (in_array($id_start_ci, $class_keywords)) { if (! $inside_structure && $id_start_ci !== 'static') { $isUsingScope = true; } } elseif (! in_array($id_start_ci, $builtin_types)) { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } } $code .= $id_start.$id_name; $state = $lastState; $i--; //reprocess last token } break; case 'anonymous': switch ($token[0]) { case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $state = 'id_name'; $lastState = 'anonymous'; break 2; case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $state = 'id_name'; $context = 'extends'; $lastState = 'anonymous'; break; case '{': $state = 'closure'; if (! $inside_structure) { $inside_structure = true; $inside_structure_mark = $open; } $i--; break; default: $code .= is_array($token) ? $token[1] : $token; } break; } } $attributesCode = array_values(array_filter(array_map(function ($attribute) { $name = $attribute->getName(); // Skip attributes that cannot target functions. When a closure is // created from a method (e.g. `$obj->method(...)`), the method's // attributes are inherited. Attributes that only target methods // (like #[\Override]) would cause a fatal error when applied to // the serialized closure function. if (class_exists($name)) { $ref = new \ReflectionClass($name); $attrAttributes = $ref->getAttributes(\Attribute::class); if (! empty($attrAttributes)) { $flags = $attrAttributes[0]->getArguments()[0] ?? \Attribute::TARGET_ALL; if (($flags & \Attribute::TARGET_FUNCTION) === 0) { return null; } } } $arguments = $attribute->getArguments(); $arguments = implode(', ', array_map(function ($argument, $key) { $argument = var_export($argument, true); if (is_string($key)) { $argument = sprintf('%s: %s', $key, $argument); } return $argument; }, $arguments, array_keys($arguments))); return "#[$name($arguments)]"; }, $this->getAttributes()))); if (count($candidates) > 1) { $lastItem = array_pop($candidates); foreach ($candidates as $candidate) { if (! $this->verifyCandidateSignature($candidate)) { continue; } $this->applyCandidate($candidate); $code = $candidate['code']; if (! empty($attributesCode)) { $code = implode("\n", array_merge($attributesCode, [$code])); } $this->code = $code; return $this->code; } $candidates[] = $lastItem; } $lastItem = array_pop($candidates); if ($lastItem) { $this->applyCandidate($lastItem); $code = $lastItem['code']; } else { if ($isShortClosure) { $this->useVariables = $this->getStaticVariables(); } else { $this->useVariables = empty($use) ? $use : array_intersect_key($this->getStaticVariables(), array_flip($use)); } $this->isShortClosure = $isShortClosure; $this->isBindingRequired = $isUsingThisObject; $this->isScopeRequired = $isUsingScope; } if (! empty($attributesCode)) { $code = implode("\n", array_merge($attributesCode, [$code])); } $this->code = $code; return $this->code; } /** * Get PHP native built in types. * * @return array */ protected static function getBuiltinTypes() { return ['array', 'callable', 'string', 'int', 'bool', 'float', 'iterable', 'void', 'object', 'mixed', 'false', 'null', 'never', 'true']; } /** * Gets the use variables by the closure. * * @return array */ public function getUseVariables() { if ($this->useVariables !== null) { return $this->useVariables; } if ($this->isShortClosure()) { return $this->useVariables; } $tokens = $this->getTokens(); $use = []; $state = 'start'; foreach ($tokens as &$token) { $is_array = is_array($token); switch ($state) { case 'start': if ($is_array && $token[0] === T_USE) { $state = 'use'; } break; case 'use': if ($is_array) { if ($token[0] === T_VARIABLE) { $use[] = substr($token[1], 1); } } elseif ($token == ')') { break 2; } break; } } $this->useVariables = empty($use) ? $use : array_intersect_key($this->getStaticVariables(), array_flip($use)); return $this->useVariables; } /** * Checks if binding is required. * * @return bool */ public function isBindingRequired() { if ($this->isBindingRequired === null) { $this->getCode(); } return $this->isBindingRequired; } /** * Checks if access to the scope is required. * * @return bool */ public function isScopeRequired() { if ($this->isScopeRequired === null) { $this->getCode(); } return $this->isScopeRequired; } /** * The hash of the current file name. * * @return string */ protected function getHashedFileName() { if ($this->hashedName === null) { $this->hashedName = sha1($this->getFileName()); } return $this->hashedName; } /** * Get the file tokens. * * @return array */ protected function getFileTokens() { $key = $this->getHashedFileName(); if (! isset(static::$files[$key])) { static::$files[$key] = token_get_all(file_get_contents($this->getFileName())); } return static::$files[$key]; } /** * Get the tokens. * * @return array */ protected function getTokens() { if ($this->tokens === null) { $tokens = $this->getFileTokens(); $startLine = $this->getStartLine(); $endLine = $this->getEndLine(); $results = []; $start = false; foreach ($tokens as &$token) { if (! is_array($token)) { if ($start) { $results[] = $token; } continue; } $line = $token[2]; if ($line <= $endLine) { if ($line >= $startLine) { $start = true; $results[] = $token; } continue; } break; } $this->tokens = $results; } return $this->tokens; } /** * Get the classes. * * @return array */ protected function getClasses() { $line = $this->getStartLine(); foreach ($this->getStructures() as $struct) { if ($struct['type'] === 'namespace' && $struct['start'] <= $line && $struct['end'] >= $line ) { return $struct['classes']; } } return []; } /** * Get the functions. * * @return array */ protected function getFunctions() { $key = $this->getHashedFileName(); if (! isset(static::$functions[$key])) { $this->fetchItems(); } return static::$functions[$key]; } /** * Gets the constants. * * @return array */ protected function getConstants() { $key = $this->getHashedFileName(); if (! isset(static::$constants[$key])) { $this->fetchItems(); } return static::$constants[$key]; } /** * Get the structures. * * @return array */ protected function getStructures() { $key = $this->getHashedFileName(); if (! isset(static::$structures[$key])) { $this->fetchItems(); } return static::$structures[$key]; } /** * Fetch the items. * * @return void. */ protected function fetchItems() { $key = $this->getHashedFileName(); $classes = []; $functions = []; $constants = []; $structures = []; $tokens = $this->getFileTokens(); $open = 0; $state = 'start'; $lastState = ''; $prefix = ''; $name = ''; $alias = ''; $isFunc = $isConst = false; $startLine = $lastKnownLine = 0; $structType = $structName = ''; $structIgnore = false; $namespace = ''; $namespaceStartLine = 0; $namespaceBraced = false; $namespaceClasses = []; foreach ($tokens as $token) { if (is_array($token)) { $lastKnownLine = $token[2]; } switch ($state) { case 'start': switch ($token[0]) { case T_NAMESPACE: $structures[] = [ 'type' => 'namespace', 'name' => $namespace, 'start' => $namespaceStartLine, 'end' => $token[2] - 1, 'classes' => $namespaceClasses, ]; $namespace = ''; $namespaceClasses = []; $state = 'namespace'; $namespaceStartLine = $token[2]; break; case T_CLASS: case T_INTERFACE: case T_TRAIT: $state = 'before_structure'; $startLine = $token[2]; $structType = $token[0] == T_CLASS ? 'class' : ($token[0] == T_INTERFACE ? 'interface' : 'trait'); break; case T_USE: $state = 'use'; $prefix = $name = $alias = ''; $isFunc = $isConst = false; break; case T_FUNCTION: $state = 'structure'; $structIgnore = true; break; case T_NEW: $state = 'new'; break; case T_OBJECT_OPERATOR: case T_DOUBLE_COLON: $state = 'invoke'; break; case '}': if ($namespaceBraced) { $structures[] = [ 'type' => 'namespace', 'name' => $namespace, 'start' => $namespaceStartLine, 'end' => $lastKnownLine, 'classes' => $namespaceClasses, ]; $namespaceBraced = false; $namespace = ''; $namespaceClasses = []; } break; } break; case 'namespace': switch ($token[0]) { case T_STRING: case T_NAME_QUALIFIED: $namespace = $token[1]; break; case ';': case '{': $state = 'start'; $namespaceBraced = $token[0] === '{'; break; } break; case 'use': switch ($token[0]) { case T_FUNCTION: $isFunc = true; break; case T_CONST: $isConst = true; break; case T_NS_SEPARATOR: $name .= $token[1]; break; case T_STRING: $name .= $token[1]; $alias = $token[1]; break; case T_NAME_QUALIFIED: $name .= $token[1]; $pieces = explode('\\', $token[1]); $alias = end($pieces); break; case T_AS: $lastState = 'use'; $state = 'alias'; break; case '{': $prefix = $name; $name = $alias = ''; $state = 'use-group'; break; case ',': case ';': if ($name === '' || $name[0] !== '\\') { $name = '\\'.$name; } if ($alias !== '') { if ($isFunc) { $functions[strtolower($alias)] = $name; } elseif ($isConst) { $constants[$alias] = $name; } else { $classes[strtolower($alias)] = $name; $namespaceClasses[strtolower($alias)] = $name; } } $name = $alias = ''; $state = $token === ';' ? 'start' : 'use'; break; } break; case 'use-group': switch ($token[0]) { case T_NS_SEPARATOR: $name .= $token[1]; break; case T_NAME_QUALIFIED: $name .= $token[1]; $pieces = explode('\\', $token[1]); $alias = end($pieces); break; case T_STRING: $name .= $token[1]; $alias = $token[1]; break; case T_AS: $lastState = 'use-group'; $state = 'alias'; break; case ',': case '}': if ($prefix === '' || $prefix[0] !== '\\') { $prefix = '\\'.$prefix; } if ($alias !== '') { if ($isFunc) { $functions[strtolower($alias)] = $prefix.$name; } elseif ($isConst) { $constants[$alias] = $prefix.$name; } else { $classes[strtolower($alias)] = $prefix.$name; $namespaceClasses[strtolower($alias)] = $prefix.$name; } } $name = $alias = ''; $state = $token === '}' ? 'use' : 'use-group'; break; } break; case 'alias': if ($token[0] === T_STRING) { $alias = $token[1]; $state = $lastState; } break; case 'new': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: break 2; case T_CLASS: $state = 'structure'; $structIgnore = true; break; default: $state = 'start'; } break; case 'invoke': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: break 2; default: $state = 'start'; } break; case 'before_structure': if ($token[0] == T_STRING) { $structName = $token[1]; $state = 'structure'; } break; case 'structure': switch ($token[0]) { case '{': case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: $open++; break; case '}': if (--$open == 0) { if (! $structIgnore) { $structures[] = [ 'type' => $structType, 'name' => $structName, 'start' => $startLine, 'end' => $lastKnownLine, ]; } $structIgnore = false; $state = 'start'; } break; } break; } } $structures[] = [ 'type' => 'namespace', 'name' => $namespace, 'start' => $namespaceStartLine, 'end' => PHP_INT_MAX, 'classes' => $namespaceClasses, ]; static::$classes[$key] = $classes; static::$functions[$key] = $functions; static::$constants[$key] = $constants; static::$structures[$key] = $structures; } /** * Returns the namespace associated to the closure. * * @return string */ protected function getClosureNamespaceName() { $startLine = $this->getStartLine(); $endLine = $this->getEndLine(); foreach ($this->getStructures() as $struct) { if ($struct['type'] === 'namespace' && $struct['start'] <= $startLine && $struct['end'] >= $endLine ) { return $struct['name']; } } return ''; } /** * Parse the given token. * * @param string $token * @return array */ protected function parseNameQualified($token) { $pieces = explode('\\', $token); $id_start = array_shift($pieces); $id_start_ci = strtolower($id_start); $id_name = '\\'.implode('\\', $pieces); return [$id_start, $id_start_ci, $id_name]; } /** * Collect a closure candidate and reset state for finding the next one. * * @param array $candidates * @param string $code * @param array $use * @param bool $isShortClosure * @param bool $isUsingThisObject * @param bool $isUsingScope * @return array */ protected function collectCandidate(&$candidates, $code, $use, $isShortClosure, $isUsingThisObject, $isUsingScope) { $candidates[] = [ 'code' => $code, 'use' => $use, 'isShortClosure' => $isShortClosure, 'isUsingThisObject' => $isUsingThisObject, 'isUsingScope' => $isUsingScope, ]; return [ 'code' => '', 'state' => 'start', 'open' => 0, 'use' => [], 'isShortClosure' => false, 'isUsingThisObject' => false, 'isUsingScope' => false, 'closureArgsInnerFuncCount' => 0, 'closureArgsBraceDepth' => 0, ]; } /** * Apply a candidate's properties to this instance. * * @param array $candidate * @return void */ protected function applyCandidate($candidate) { if ($candidate['isShortClosure']) { $this->useVariables = $this->getStaticVariables(); } else { $this->useVariables = empty($candidate['use']) ? $candidate['use'] : array_intersect_key($this->getStaticVariables(), array_flip($candidate['use'])); } $this->isShortClosure = $candidate['isShortClosure']; $this->isBindingRequired = $candidate['isUsingThisObject']; $this->isScopeRequired = $candidate['isUsingScope']; } /** * Verify that a candidate matches the closure's signature. * * @param array $candidate * @return bool */ protected function verifyCandidateSignature($candidate) { $code = $candidate['code']; $use = $candidate['use']; $isShortClosure = $candidate['isShortClosure']; // Check if code starts with 'static' (more precise than searching anywhere in code) $isStaticCode = strtolower(substr(ltrim($code), 0, 6)) === 'static'; if (parent::isStatic() !== $isStaticCode) { return false; } // Parse the candidate to extract parameters and variables $tokens = token_get_all(' 0) { return false; } } else { $actualStaticVariables = array_keys(parent::getStaticVariables()); if (! empty($use) && count(array_diff($use, $actualStaticVariables)) > 0) { return false; } if (count($use) !== count(parent::getStaticVariables())) { return false; } } return true; } } hash = $hash; } } serializable = new Serializers\Native($closure); } /** * Resolve the closure with the given arguments. * * @return mixed */ public function __invoke() { return call_user_func_array($this->serializable, func_get_args()); } /** * Gets the closure. * * @return \Closure */ public function getClosure() { return $this->serializable->getClosure(); } /** * Get the serializable representation of the closure. * * @return array{serializable: \Laravel\SerializableClosure\Contracts\Serializable} */ public function __serialize() { return [ 'serializable' => $this->serializable, ]; } /** * Restore the closure after serialization. * * @param array{serializable: \Laravel\SerializableClosure\Contracts\Serializable} $data * @return void */ public function __unserialize($data) { $this->serializable = $data['serializable']; } } View the docs at: https://flysystem.thephpleague.com/docs/ Changelog at: https://github.com/thephpleague/flysystem/blob/3.x/CHANGELOG.md Copyright (c) 2013-2026 Frank de Jonge 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. # Security Policy ## Supported versions | Version | Phase | End of Bugfix Support | |-------------|--------------|-----------------------| | Flysystem 3 | Supported | Not specified yet | Flysystem 2 and earlier have reached End-of-Life. > FYI: There is no bug-bounty program. ## Reporting a Vulnerability If you believe you have found a security vulnerability in Flysystem, please report it to me through coordinated disclosure. **Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** Instead, please email `info+flysystem@frankdejonge.nl`. Please include as much of the information listed below as you can to help me 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 me triage your report more quickly. If you used an AI assistant (LLM, coding agent, or similar) to find, reproduce, or write up the issue, please say so and describe how it was used. This does not disqualify a report, but it changes how I triage it. ### Path Traversal attacks Path traversal attacks for the *root* path should not occur. Under standard configurations, using the security features Flysystem ships an attacker should not be able to escape out of the configured root path through path traversal attacks. Root paths are configured at the adapter level. Any path inside the root path can resolve relative paths. Breaking out of a sub-directory is NOT considered a vulnerability. If you wish to prevent path traversal attacks, configure the appropriate root path or disable relative path traveral. When relative path traversal is disabled, any relative path traversal IS be considered a vulnerability. Relative path resolution is enabled by default and can be disabled by setting the `allow_relative_path_traversal` configuration option on the `Filesystem` instance to `false` or by passing a `PathNormalizer` instance configured to reject relative path traversal. ```php use League\Flysystem\Filesystem;use League\Flysystem\WhitespacePathNormalizer; $filesystem = new Filesystem( $adapter, [ 'allow_relative_path_traversal' => false, ] ); $filesystem = new Filesystem( $adapter, [], new WhitespacePathNormalizer(allowRelativePathTraversal: false), ); ``` > [!IMPORTANT] > Note that, passing a `PathNormalizer` instance takes precedence over the `allow_relative_path_traversal` configuration > option. If the configuration option is set to `false` but the configured `PathNormalizer` instance does not reject > relative path traversal, path traversal attacks are still possible. This is considered a faulty configuration and is > not considered a security vulnerability. { "name": "league/flysystem", "description": "File storage abstraction for PHP", "keywords": [ "filesystem", "filesystems", "files", "storage", "aws", "s3", "ftp", "sftp", "webdav", "file", "cloud" ], "scripts": { "phpstan": "vendor/bin/phpstan analyse -l 6 src" }, "type": "library", "minimum-stability": "dev", "prefer-stable": true, "autoload": { "psr-4": { "League\\Flysystem\\": "src" } }, "require": { "php": "^8.0.2", "league/flysystem-local": "^3.0.0", "league/mime-type-detection": "^1.0.0" }, "require-dev": { "ext-zip": "*", "ext-fileinfo": "*", "ext-ftp": "*", "ext-mongodb": "^1.3|^2", "microsoft/azure-storage-blob": "^1.1", "phpunit/phpunit": "^9.5.11|^10.0", "phpstan/phpstan": "^1.10", "phpseclib/phpseclib": "^3.0.36", "aws/aws-sdk-php": "^3.295.10", "composer/semver": "^3.0", "friendsofphp/php-cs-fixer": "^3.5", "google/cloud-storage": "^1.23", "async-aws/s3": "^1.5 || ^2.0", "async-aws/simple-s3": "^1.1 || ^2.0", "mongodb/mongodb": "^1.2|^2", "sabre/dav": "^4.6.0", "guzzlehttp/psr7": "^2.6" }, "conflict": { "async-aws/core": "<1.19.0", "async-aws/s3": "<1.14.0", "symfony/http-client": "<5.2", "guzzlehttp/ringphp": "<1.1.1", "guzzlehttp/guzzle": "<7.0", "aws/aws-sdk-php": "3.209.31 || 3.210.0", "phpseclib/phpseclib": "3.0.15" }, "license": "MIT", "authors": [ { "name": "Frank de Jonge", "email": "info@frankdejonge.nl" } ], "repositories": [ { "type": "package", "package": { "name": "league/flysystem-local", "version": "3.0.0", "dist": { "type": "path", "url": "src/Local" } } } ] } # League\Flysystem [![Author](https://img.shields.io/badge/author-@frankdejonge-blue.svg)](https://twitter.com/frankdejonge) [![Source Code](https://img.shields.io/badge/source-thephpleague/flysystem-blue.svg)](https://github.com/thephpleague/flysystem) [![Latest Version](https://img.shields.io/github/tag/thephpleague/flysystem.svg)](https://github.com/thephpleague/flysystem/releases) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/thephpleague/flysystem/blob/master/LICENSE) [![Quality Assurance](https://github.com/thephpleague/flysystem/workflows/Quality%20Assurance/badge.svg?branch=2.x)](https://github.com/thephpleague/flysystem/actions?query=workflow%3A%22Quality+Assurance%22) [![Total Downloads](https://img.shields.io/packagist/dt/league/flysystem.svg)](https://packagist.org/packages/league/flysystem) ![php 7.2+](https://img.shields.io/badge/php-min%208.0.2-red.svg) ## About Flysystem Flysystem is a file storage library for PHP. It provides one interface to interact with many types of filesystems. When you use Flysystem, you're not only protected from vendor lock-in, you'll also have a consistent experience for which ever storage is right for you. ## Getting Started * **[New in V3](https://flysystem.thephpleague.com/docs/what-is-new/)**: What is new in Flysystem V2/V3? * **[Architecture](https://flysystem.thephpleague.com/docs/architecture/)**: Flysystem's internal architecture * **[Flysystem API](https://flysystem.thephpleague.com/docs/usage/filesystem-api/)**: How to interact with your Flysystem instance * **[Upgrade from 1x](https://flysystem.thephpleague.com/docs/upgrade-from-1.x/)**: How to upgrade from 1.x/2.x ### Officially supported adapters * **[Local](https://flysystem.thephpleague.com/docs/adapter/local/)** * **[FTP](https://flysystem.thephpleague.com/docs/adapter/ftp/)** * **[SFTP](https://flysystem.thephpleague.com/docs/adapter/sftp-v3/)** * **[Memory](https://flysystem.thephpleague.com/docs/adapter/in-memory/)** * **[AWS S3](https://flysystem.thephpleague.com/docs/adapter/aws-s3-v3/)** * **[AsyncAws S3](https://flysystem.thephpleague.com/docs/adapter/async-aws-s3/)** * **[Google Cloud Storage](https://flysystem.thephpleague.com/docs/adapter/google-cloud-storage/)** * **[MongoDB GridFS](https://flysystem.thephpleague.com/docs/adapter/gridfs/)** * **[WebDAV](https://flysystem.thephpleague.com/docs/adapter/webdav/)** * **[ZipArchive](https://flysystem.thephpleague.com/docs/adapter/zip-archive/)** ### Third party Adapters * **[Azure Blob Storage](https://github.com/Azure-OSS/azure-storage-php-adapter-flysystem)** * **[Gitlab](https://github.com/RoyVoetman/flysystem-gitlab-storage)** * **[Google Drive (using regular paths)](https://github.com/masbug/flysystem-google-drive-ext)** * **[bunny.net / BunnyCDN](https://github.com/PlatformCommunity/flysystem-bunnycdn/tree/v3)** * **[Sharepoint 365 / One Drive (Using MS Graph)](https://github.com/shitware-ltd/flysystem-msgraph)** * **[OneDrive](https://github.com/doerffler/flysystem-onedrive)** * **[Dropbox](https://github.com/spatie/flysystem-dropbox)** * **[ReplicateAdapter](https://github.com/ajgarlag/flysystem-replicate)** * **[Uploadcare](https://github.com/vormkracht10/flysystem-uploadcare)** * **[Useful adapters (FallbackAdapter, LogAdapter, ReadWriteAdapter, RetryAdapter)](https://github.com/ElGigi/FlysystemUsefulAdapters)** * **[Metadata Cache](https://github.com/jgivoni/flysystem-cache-adapter)** * **[Migration adapter (lazy)](https://github.com/antonsacred/flysystem-lazy-migration-adapter)** You can always [create an adapter](https://flysystem.thephpleague.com/docs/advanced/creating-an-adapter/) yourself. ## Security If you discover any security related issues, please email info@frankdejonge.nl instead of using the issue tracker. ## Enjoy Oh, and if you've come down this far, you might as well follow me on [twitter](https://twitter.com/frankdejonge). readStream($path); $algo = (string) $config->get('checksum_algo', 'md5'); $context = hash_init($algo); hash_update_stream($context, $stream); return hash_final($context); } catch (FilesystemException $exception) { throw new UnableToProvideChecksum($exception->getMessage(), $path, $exception); } } /** * @return resource */ abstract public function readStream(string $path); } options[$property] ?? $default; } public function extend(array $options): Config { return new Config(array_merge($this->options, $options)); } public function withDefaults(array $defaults): Config { return new Config($this->options + $defaults); } public function toArray(): array { return $this->options; } public function withSetting(string $property, mixed $setting): Config { return $this->extend([$property => $setting]); } public function withoutSettings(string ...$settings): Config { return new Config(array_diff_key($this->options, array_flip($settings))); } } adapter->fileExists($path); } public function directoryExists(string $path): bool { return $this->adapter->directoryExists($path); } public function write(string $path, string $contents, Config $config): void { $this->adapter->write($path, $contents, $config); } public function writeStream(string $path, $contents, Config $config): void { $this->adapter->writeStream($path, $contents, $config); } public function read(string $path): string { return $this->adapter->read($path); } public function readStream(string $path) { return $this->adapter->readStream($path); } public function delete(string $path): void { $this->adapter->delete($path); } public function deleteDirectory(string $path): void { $this->adapter->deleteDirectory($path); } public function createDirectory(string $path, Config $config): void { $this->adapter->createDirectory($path, $config); } public function setVisibility(string $path, string $visibility): void { $this->adapter->setVisibility($path, $visibility); } public function visibility(string $path): FileAttributes { return $this->adapter->visibility($path); } public function mimeType(string $path): FileAttributes { return $this->adapter->mimeType($path); } public function lastModified(string $path): FileAttributes { return $this->adapter->lastModified($path); } public function fileSize(string $path): FileAttributes { return $this->adapter->fileSize($path); } public function listContents(string $path, bool $deep): iterable { return $this->adapter->listContents($path, $deep); } public function move(string $source, string $destination, Config $config): void { $this->adapter->move($source, $destination, $config); } public function copy(string $source, string $destination, Config $config): void { $this->adapter->copy($source, $destination, $config); } } path = trim($this->path, '/'); } public function path(): string { return $this->path; } public function type(): string { return $this->type; } public function visibility(): ?string { return $this->visibility; } public function lastModified(): ?int { return $this->lastModified; } public function extraMetadata(): array { return $this->extraMetadata; } public function isFile(): bool { return false; } public function isDir(): bool { return true; } public function withPath(string $path): self { $clone = clone $this; $clone->path = $path; return $clone; } public static function fromArray(array $attributes): self { return new DirectoryAttributes( $attributes[StorageAttributes::ATTRIBUTE_PATH], $attributes[StorageAttributes::ATTRIBUTE_VISIBILITY] ?? null, $attributes[StorageAttributes::ATTRIBUTE_LAST_MODIFIED] ?? null, $attributes[StorageAttributes::ATTRIBUTE_EXTRA_METADATA] ?? [] ); } /** * @inheritDoc */ public function jsonSerialize(): array { return [ StorageAttributes::ATTRIBUTE_TYPE => $this->type, StorageAttributes::ATTRIBUTE_PATH => $this->path, StorageAttributes::ATTRIBUTE_VISIBILITY => $this->visibility, StorageAttributes::ATTRIBUTE_LAST_MODIFIED => $this->lastModified, StorageAttributes::ATTRIBUTE_EXTRA_METADATA => $this->extraMetadata, ]; } } $listing */ public function __construct(private iterable $listing) { } /** * @param callable(T): bool $filter * * @return DirectoryListing */ public function filter(callable $filter): DirectoryListing { $generator = (static function (iterable $listing) use ($filter): Generator { foreach ($listing as $item) { if ($filter($item)) { yield $item; } } })($this->listing); return new DirectoryListing($generator); } /** * @template R * * @param callable(T): R $mapper * * @return DirectoryListing */ public function map(callable $mapper): DirectoryListing { $generator = (static function (iterable $listing) use ($mapper): Generator { foreach ($listing as $item) { yield $mapper($item); } })($this->listing); return new DirectoryListing($generator); } /** * @return DirectoryListing */ public function sortByPath(): DirectoryListing { $listing = $this->toArray(); usort($listing, function (StorageAttributes $a, StorageAttributes $b) { return $a->path() <=> $b->path(); }); return new DirectoryListing($listing); } /** * @return Traversable */ public function getIterator(): Traversable { return $this->listing instanceof Traversable ? $this->listing : new ArrayIterator($this->listing); } /** * @return T[] */ public function toArray(): array { return $this->listing instanceof Traversable ? iterator_to_array($this->listing, false) : (array) $this->listing; } } path = ltrim($this->path, '/'); } public function type(): string { return $this->type; } public function path(): string { return $this->path; } public function fileSize(): ?int { return $this->fileSize; } public function visibility(): ?string { return $this->visibility; } public function lastModified(): ?int { return $this->lastModified; } public function mimeType(): ?string { return $this->mimeType; } public function extraMetadata(): array { return $this->extraMetadata; } public function isFile(): bool { return true; } public function isDir(): bool { return false; } public function withPath(string $path): self { $clone = clone $this; $clone->path = $path; return $clone; } public static function fromArray(array $attributes): self { return new FileAttributes( $attributes[StorageAttributes::ATTRIBUTE_PATH], $attributes[StorageAttributes::ATTRIBUTE_FILE_SIZE] ?? null, $attributes[StorageAttributes::ATTRIBUTE_VISIBILITY] ?? null, $attributes[StorageAttributes::ATTRIBUTE_LAST_MODIFIED] ?? null, $attributes[StorageAttributes::ATTRIBUTE_MIME_TYPE] ?? null, $attributes[StorageAttributes::ATTRIBUTE_EXTRA_METADATA] ?? [] ); } public function jsonSerialize(): array { return [ StorageAttributes::ATTRIBUTE_TYPE => self::TYPE_FILE, StorageAttributes::ATTRIBUTE_PATH => $this->path, StorageAttributes::ATTRIBUTE_FILE_SIZE => $this->fileSize, StorageAttributes::ATTRIBUTE_VISIBILITY => $this->visibility, StorageAttributes::ATTRIBUTE_LAST_MODIFIED => $this->lastModified, StorageAttributes::ATTRIBUTE_MIME_TYPE => $this->mimeType, StorageAttributes::ATTRIBUTE_EXTRA_METADATA => $this->extraMetadata, ]; } } config = new Config($config); $this->pathNormalizer = $pathNormalizer ?? new WhitespacePathNormalizer($this->config->get('allow_relative_path_traversal', true)); } public function fileExists(string $location): bool { return $this->adapter->fileExists($this->pathNormalizer->normalizePath($location)); } public function directoryExists(string $location): bool { return $this->adapter->directoryExists($this->pathNormalizer->normalizePath($location)); } public function has(string $location): bool { $path = $this->pathNormalizer->normalizePath($location); return $this->adapter->fileExists($path) || $this->adapter->directoryExists($path); } public function write(string $location, string $contents, array $config = []): void { $this->adapter->write( $this->pathNormalizer->normalizePath($location), $contents, $this->config->extend($config) ); } public function writeStream(string $location, $contents, array $config = []): void { /* @var resource $contents */ $this->assertIsResource($contents); $this->rewindStream($contents); $this->adapter->writeStream( $this->pathNormalizer->normalizePath($location), $contents, $this->config->extend($config) ); } public function read(string $location): string { return $this->adapter->read($this->pathNormalizer->normalizePath($location)); } public function readStream(string $location) { return $this->adapter->readStream($this->pathNormalizer->normalizePath($location)); } public function delete(string $location): void { $this->adapter->delete($this->pathNormalizer->normalizePath($location)); } public function deleteDirectory(string $location): void { $this->adapter->deleteDirectory($this->pathNormalizer->normalizePath($location)); } public function createDirectory(string $location, array $config = []): void { $this->adapter->createDirectory( $this->pathNormalizer->normalizePath($location), $this->config->extend($config) ); } public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing { $path = $this->pathNormalizer->normalizePath($location); $listing = $this->adapter->listContents($path, $deep); return new DirectoryListing($this->pipeListing($location, $deep, $listing)); } private function pipeListing(string $location, bool $deep, iterable $listing): Generator { try { foreach ($listing as $item) { yield $item; } } catch (Throwable $exception) { throw UnableToListContents::atLocation($location, $deep, $exception); } } public function move(string $source, string $destination, array $config = []): void { $config = $this->resolveConfigForMoveAndCopy($config); $from = $this->pathNormalizer->normalizePath($source); $to = $this->pathNormalizer->normalizePath($destination); if ($from === $to) { $resolutionStrategy = $config->get(Config::OPTION_MOVE_IDENTICAL_PATH, ResolveIdenticalPathConflict::TRY); if ($resolutionStrategy === ResolveIdenticalPathConflict::FAIL) { throw UnableToMoveFile::sourceAndDestinationAreTheSame($source, $destination); } elseif ($resolutionStrategy === ResolveIdenticalPathConflict::IGNORE) { return; } } $this->adapter->move($from, $to, $config); } public function copy(string $source, string $destination, array $config = []): void { $config = $this->resolveConfigForMoveAndCopy($config); $from = $this->pathNormalizer->normalizePath($source); $to = $this->pathNormalizer->normalizePath($destination); if ($from === $to) { $resolutionStrategy = $config->get(Config::OPTION_COPY_IDENTICAL_PATH, ResolveIdenticalPathConflict::TRY); if ($resolutionStrategy === ResolveIdenticalPathConflict::FAIL) { throw UnableToCopyFile::sourceAndDestinationAreTheSame($source, $destination); } elseif ($resolutionStrategy === ResolveIdenticalPathConflict::IGNORE) { return; } } $this->adapter->copy($from, $to, $config); } public function lastModified(string $path): int { return $this->adapter->lastModified($this->pathNormalizer->normalizePath($path))->lastModified(); } public function fileSize(string $path): int { return $this->adapter->fileSize($this->pathNormalizer->normalizePath($path))->fileSize(); } public function mimeType(string $path): string { $normalizedPath = $this->pathNormalizer->normalizePath($path); $attributes = $this->adapter->mimeType($normalizedPath); if ($attributes->mimeType() === null) { throw UnableToRetrieveMetadata::mimeType($path); } return $attributes->mimeType(); } public function setVisibility(string $path, string $visibility): void { $this->adapter->setVisibility($this->pathNormalizer->normalizePath($path), $visibility); } public function visibility(string $path): string { return $this->adapter->visibility($this->pathNormalizer->normalizePath($path))->visibility(); } public function publicUrl(string $path, array $config = []): string { $this->publicUrlGenerator ??= $this->resolvePublicUrlGenerator() ?? throw UnableToGeneratePublicUrl::noGeneratorConfigured($path); $config = $this->config->extend($config); return $this->publicUrlGenerator->publicUrl( $this->pathNormalizer->normalizePath($path), $config, ); } public function temporaryUrl(string $path, DateTimeInterface $expiresAt, array $config = []): string { $generator = $this->temporaryUrlGenerator ?? $this->adapter; if ($generator instanceof TemporaryUrlGenerator) { return $generator->temporaryUrl( $this->pathNormalizer->normalizePath($path), $expiresAt, $this->config->extend($config) ); } throw UnableToGenerateTemporaryUrl::noGeneratorConfigured($path); } public function checksum(string $path, array $config = []): string { $config = $this->config->extend($config); if ( ! $this->adapter instanceof ChecksumProvider) { return $this->calculateChecksumFromStream($path, $config); } try { return $this->adapter->checksum( $this->pathNormalizer->normalizePath($path), $config, ); } catch (ChecksumAlgoIsNotSupported) { return $this->calculateChecksumFromStream( $this->pathNormalizer->normalizePath($path), $config, ); } } private function resolvePublicUrlGenerator(): ?PublicUrlGenerator { if ($publicUrl = $this->config->get('public_url')) { return match (true) { is_array($publicUrl) => new ShardedPrefixPublicUrlGenerator($publicUrl), default => new PrefixPublicUrlGenerator($publicUrl), }; } if ($this->adapter instanceof PublicUrlGenerator) { return $this->adapter; } return null; } /** * @param mixed $contents */ private function assertIsResource($contents): void { if (is_resource($contents) === false) { throw new InvalidStreamProvided( "Invalid stream provided, expected stream resource, received " . gettype($contents) ); } elseif (($type = get_resource_type($contents)) !== 'stream') { throw new InvalidStreamProvided( "Invalid stream provided, expected stream resource, received resource of type " . $type ); } } /** * @param resource $resource */ private function rewindStream($resource): void { if (ftell($resource) !== 0 && stream_get_meta_data($resource)['seekable']) { rewind($resource); } } private function resolveConfigForMoveAndCopy(array $config): Config { $retainVisibility = $this->config->get(Config::OPTION_RETAIN_VISIBILITY, $config[Config::OPTION_RETAIN_VISIBILITY] ?? true); $fullConfig = $this->config->extend($config); /* * By default, we retain visibility. When we do not retain visibility, the visibility setting * from the default configuration is ignored. Only when it is set explicitly, we propagate the * setting. */ if ($retainVisibility && ! array_key_exists(Config::OPTION_VISIBILITY, $config)) { $fullConfig = $fullConfig->withoutSettings(Config::OPTION_VISIBILITY)->extend($config); } return $fullConfig; } } * * @throws FilesystemException */ public function listContents(string $path, bool $deep): iterable; /** * @throws UnableToMoveFile * @throws FilesystemException */ public function move(string $source, string $destination, Config $config): void; /** * @throws UnableToCopyFile * @throws FilesystemException */ public function copy(string $source, string $destination, Config $config): void; } * * @throws FilesystemException * @throws UnableToListContents */ public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing; /** * @throws UnableToRetrieveMetadata * @throws FilesystemException */ public function lastModified(string $path): int; /** * @throws UnableToRetrieveMetadata * @throws FilesystemException */ public function fileSize(string $path): int; /** * @throws UnableToRetrieveMetadata * @throws FilesystemException */ public function mimeType(string $path): string; /** * @throws UnableToRetrieveMetadata * @throws FilesystemException */ public function visibility(string $path): string; } */ private $filesystems = []; /** * @var Config */ private $config; /** * MountManager constructor. * * @param array $filesystems */ public function __construct(array $filesystems = [], array $config = []) { $this->mountFilesystems($filesystems); $this->config = new Config($config); } /** * It is not recommended to mount filesystems after creation because interacting * with the Mount Manager becomes unpredictable. Use this as an escape hatch. */ public function dangerouslyMountFilesystems(string $key, FilesystemOperator $filesystem): void { $this->mountFilesystem($key, $filesystem); } /** * @param array $filesystems */ public function extend(array $filesystems, array $config = []): MountManager { $clone = clone $this; $clone->config = $this->config->extend($config); $clone->mountFilesystems($filesystems); return $clone; } public function fileExists(string $location): bool { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { return $filesystem->fileExists($path); } catch (Throwable $exception) { throw UnableToCheckFileExistence::forLocation($location, $exception); } } public function has(string $location): bool { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { return $filesystem->fileExists($path) || $filesystem->directoryExists($path); } catch (Throwable $exception) { throw UnableToCheckExistence::forLocation($location, $exception); } } public function directoryExists(string $location): bool { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { return $filesystem->directoryExists($path); } catch (Throwable $exception) { throw UnableToCheckDirectoryExistence::forLocation($location, $exception); } } public function read(string $location): string { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { return $filesystem->read($path); } catch (UnableToReadFile $exception) { throw UnableToReadFile::fromLocation($location, $exception->reason(), $exception); } } public function readStream(string $location) { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { return $filesystem->readStream($path); } catch (UnableToReadFile $exception) { throw UnableToReadFile::fromLocation($location, $exception->reason(), $exception); } } public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing { /** @var FilesystemOperator $filesystem */ [$filesystem, $path, $mountIdentifier] = $this->determineFilesystemAndPath($location); return $filesystem ->listContents($path, $deep) ->map( function (StorageAttributes $attributes) use ($mountIdentifier) { return $attributes->withPath(sprintf('%s://%s', $mountIdentifier, $attributes->path())); } ); } public function lastModified(string $location): int { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { return $filesystem->lastModified($path); } catch (UnableToRetrieveMetadata $exception) { throw UnableToRetrieveMetadata::lastModified($location, $exception->reason(), $exception); } } public function fileSize(string $location): int { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { return $filesystem->fileSize($path); } catch (UnableToRetrieveMetadata $exception) { throw UnableToRetrieveMetadata::fileSize($location, $exception->reason(), $exception); } } public function mimeType(string $location): string { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { return $filesystem->mimeType($path); } catch (UnableToRetrieveMetadata $exception) { throw UnableToRetrieveMetadata::mimeType($location, $exception->reason(), $exception); } } public function visibility(string $path): string { /** @var FilesystemOperator $filesystem */ [$filesystem, $location] = $this->determineFilesystemAndPath($path); try { return $filesystem->visibility($location); } catch (UnableToRetrieveMetadata $exception) { throw UnableToRetrieveMetadata::visibility($path, $exception->reason(), $exception); } } public function write(string $location, string $contents, array $config = []): void { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { $filesystem->write($path, $contents, $this->config->extend($config)->toArray()); } catch (UnableToWriteFile $exception) { throw UnableToWriteFile::atLocation($location, $exception->reason(), $exception); } } public function writeStream(string $location, $contents, array $config = []): void { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); $filesystem->writeStream($path, $contents, $this->config->extend($config)->toArray()); } public function setVisibility(string $path, string $visibility): void { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($path); $filesystem->setVisibility($path, $visibility); } public function delete(string $location): void { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { $filesystem->delete($path); } catch (UnableToDeleteFile $exception) { throw UnableToDeleteFile::atLocation($location, $exception->reason(), $exception); } } public function deleteDirectory(string $location): void { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { $filesystem->deleteDirectory($path); } catch (UnableToDeleteDirectory $exception) { throw UnableToDeleteDirectory::atLocation($location, $exception->reason(), $exception); } } public function createDirectory(string $location, array $config = []): void { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { $filesystem->createDirectory($path, $this->config->extend($config)->toArray()); } catch (UnableToCreateDirectory $exception) { throw UnableToCreateDirectory::dueToFailure($location, $exception); } } public function move(string $source, string $destination, array $config = []): void { /** @var FilesystemOperator $sourceFilesystem */ /* @var FilesystemOperator $destinationFilesystem */ [$sourceFilesystem, $sourcePath] = $this->determineFilesystemAndPath($source); [$destinationFilesystem, $destinationPath] = $this->determineFilesystemAndPath($destination); $sourceFilesystem === $destinationFilesystem ? $this->moveInTheSameFilesystem( $sourceFilesystem, $sourcePath, $destinationPath, $source, $destination, $config, ) : $this->moveAcrossFilesystems($source, $destination, $config); } public function copy(string $source, string $destination, array $config = []): void { /** @var FilesystemOperator $sourceFilesystem */ /* @var FilesystemOperator $destinationFilesystem */ [$sourceFilesystem, $sourcePath] = $this->determineFilesystemAndPath($source); [$destinationFilesystem, $destinationPath] = $this->determineFilesystemAndPath($destination); $sourceFilesystem === $destinationFilesystem ? $this->copyInSameFilesystem( $sourceFilesystem, $sourcePath, $destinationPath, $source, $destination, $config, ) : $this->copyAcrossFilesystem( $sourceFilesystem, $sourcePath, $destinationFilesystem, $destinationPath, $source, $destination, $config, ); } public function publicUrl(string $path, array $config = []): string { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($path); if ( ! method_exists($filesystem, 'publicUrl')) { throw new UnableToGeneratePublicUrl(sprintf('%s does not support generating public urls.', $filesystem::class), $path); } return $filesystem->publicUrl($path, $config); } public function temporaryUrl(string $path, DateTimeInterface $expiresAt, array $config = []): string { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($path); if ( ! method_exists($filesystem, 'temporaryUrl')) { throw new UnableToGenerateTemporaryUrl(sprintf('%s does not support generating public urls.', $filesystem::class), $path); } return $filesystem->temporaryUrl($path, $expiresAt, $this->config->extend($config)->toArray()); } public function checksum(string $path, array $config = []): string { /** @var FilesystemOperator $filesystem */ [$filesystem, $path] = $this->determineFilesystemAndPath($path); if ( ! method_exists($filesystem, 'checksum')) { throw new UnableToProvideChecksum(sprintf('%s does not support providing checksums.', $filesystem::class), $path); } return $filesystem->checksum($path, $this->config->extend($config)->toArray()); } private function mountFilesystems(array $filesystems): void { foreach ($filesystems as $key => $filesystem) { $this->guardAgainstInvalidMount($key, $filesystem); /* @var string $key */ /* @var FilesystemOperator $filesystem */ $this->mountFilesystem($key, $filesystem); } } private function guardAgainstInvalidMount(mixed $key, mixed $filesystem): void { if ( ! is_string($key)) { throw UnableToMountFilesystem::becauseTheKeyIsNotValid($key); } if ( ! $filesystem instanceof FilesystemOperator) { throw UnableToMountFilesystem::becauseTheFilesystemWasNotValid($filesystem); } } private function mountFilesystem(string $key, FilesystemOperator $filesystem): void { $this->filesystems[$key] = $filesystem; } /** * @param string $path * * @return array{0:FilesystemOperator, 1:string, 2:string} */ private function determineFilesystemAndPath(string $path): array { if (strpos($path, '://') < 1) { throw UnableToResolveFilesystemMount::becauseTheSeparatorIsMissing($path); } /** @var string $mountIdentifier */ /** @var string $mountPath */ [$mountIdentifier, $mountPath] = explode('://', $path, 2); if ( ! array_key_exists($mountIdentifier, $this->filesystems)) { throw UnableToResolveFilesystemMount::becauseTheMountWasNotRegistered($mountIdentifier); } return [$this->filesystems[$mountIdentifier], $mountPath, $mountIdentifier]; } private function copyInSameFilesystem( FilesystemOperator $sourceFilesystem, string $sourcePath, string $destinationPath, string $source, string $destination, array $config, ): void { try { $sourceFilesystem->copy($sourcePath, $destinationPath, $this->config->extend($config)->toArray()); } catch (UnableToCopyFile $exception) { throw UnableToCopyFile::fromLocationTo($source, $destination, $exception); } } private function copyAcrossFilesystem( FilesystemOperator $sourceFilesystem, string $sourcePath, FilesystemOperator $destinationFilesystem, string $destinationPath, string $source, string $destination, array $config, ): void { $config = $this->config->extend($config); $retainVisibility = (bool) $config->get(Config::OPTION_RETAIN_VISIBILITY, true); $visibility = $config->get(Config::OPTION_VISIBILITY); try { if ($visibility == null && $retainVisibility) { $visibility = $sourceFilesystem->visibility($sourcePath); $config = $config->extend(compact('visibility')); } $stream = $sourceFilesystem->readStream($sourcePath); $destinationFilesystem->writeStream($destinationPath, $stream, $config->toArray()); } catch (UnableToRetrieveMetadata | UnableToReadFile | UnableToWriteFile $exception) { throw UnableToCopyFile::fromLocationTo($source, $destination, $exception); } } private function moveInTheSameFilesystem( FilesystemOperator $sourceFilesystem, string $sourcePath, string $destinationPath, string $source, string $destination, array $config, ): void { try { $sourceFilesystem->move($sourcePath, $destinationPath, $this->config->extend($config)->toArray()); } catch (UnableToMoveFile $exception) { throw UnableToMoveFile::fromLocationTo($source, $destination, $exception); } } private function moveAcrossFilesystems(string $source, string $destination, array $config = []): void { try { $this->copy($source, $destination, $config); $this->delete($source); } catch (UnableToCopyFile | UnableToDeleteFile $exception) { throw UnableToMoveFile::fromLocationTo($source, $destination, $exception); } } } prefix = rtrim($prefix, '\\/'); if ($this->prefix !== '' || $prefix === $separator) { $this->prefix .= $separator; } } public function prefixPath(string $path): string { return $this->prefix . ltrim($path, '\\/'); } public function stripPrefix(string $path): string { /* @var string */ return substr($path, strlen($this->prefix)); } public function stripDirectoryPrefix(string $path): string { return rtrim($this->stripPrefix($path), '\\/'); } public function prefixDirectoryPath(string $path): string { $prefixedPath = $this->prefixPath(rtrim($path, '\\/')); if ($prefixedPath === '' || substr($prefixedPath, -1) === $this->separator) { return $prefixedPath; } return $prefixedPath . $this->separator; } } path; } public static function forPath(string $path): PathTraversalDetected { $e = new PathTraversalDetected("Path traversal detected: {$path}"); $e->path = $path; return $e; } } formatPropertyName((string) $offset); return isset($this->{$property}); } /** * @param mixed $offset * * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet($offset) { $property = $this->formatPropertyName((string) $offset); return $this->{$property}; } /** * @param mixed $offset * @param mixed $value */ #[\ReturnTypeWillChange] public function offsetSet($offset, $value): void { throw new RuntimeException('Properties can not be manipulated'); } /** * @param mixed $offset */ #[\ReturnTypeWillChange] public function offsetUnset($offset): void { throw new RuntimeException('Properties can not be manipulated'); } } location; } public static function atLocation(string $pathName): SymbolicLinkEncountered { $e = new static("Unsupported symbolic link encountered at location $pathName"); $e->location = $pathName; return $e; } } source; } public function destination(): string { return $this->destination; } public static function fromLocationTo( string $sourcePath, string $destinationPath, ?Throwable $previous = null ): UnableToCopyFile { $e = new static("Unable to copy file from $sourcePath to $destinationPath", 0 , $previous); $e->source = $sourcePath; $e->destination = $destinationPath; return $e; } public static function sourceAndDestinationAreTheSame(string $source, string $destination): UnableToCopyFile { return UnableToCopyFile::because('Source and destination are the same', $source, $destination); } public static function because(string $reason, string $sourcePath, string $destinationPath): UnableToCopyFile { $e = new static("Unable to copy file from $sourcePath to $destinationPath, because $reason"); $e->source = $sourcePath; $e->destination = $destinationPath; return $e; } public function operation(): string { return FilesystemOperationFailed::OPERATION_COPY; } } location = $dirname; $e->reason = $errorMessage; return $e; } public static function dueToFailure(string $dirname, Throwable $previous): UnableToCreateDirectory { $reason = $previous instanceof UnableToCreateDirectory ? $previous->reason() : ''; $message = "Unable to create a directory at $dirname. $reason"; $e = new static(rtrim($message), 0, $previous); $e->location = $dirname; $e->reason = $reason ?: $message; return $e; } public function operation(): string { return FilesystemOperationFailed::OPERATION_CREATE_DIRECTORY; } public function reason(): string { return $this->reason; } public function location(): string { return $this->location; } } location = $location; $e->reason = $reason; return $e; } public function operation(): string { return FilesystemOperationFailed::OPERATION_DELETE_DIRECTORY; } public function reason(): string { return $this->reason; } public function location(): string { return $this->location; } } location = $location; $e->reason = $reason; return $e; } public function operation(): string { return FilesystemOperationFailed::OPERATION_DELETE; } public function reason(): string { return $this->reason; } public function location(): string { return $this->location; } } getMessage(), $path, $exception); } public static function noGeneratorConfigured(string $path, string $extraReason = ''): static { return new static('No generator was configured ' . $extraReason, $path); } } getMessage(), $path, $exception); } public static function noGeneratorConfigured(string $path, string $extraReason = ''): static { return new static('No generator was configured ' . $extraReason, $path); } } getMessage(); return new UnableToListContents($message, 0, $previous); } public function operation(): string { return self::OPERATION_LIST_CONTENTS; } } source; } public function destination(): string { return $this->destination; } public static function fromLocationTo( string $sourcePath, string $destinationPath, ?Throwable $previous = null ): UnableToMoveFile { $message = $previous?->getMessage() ?? "Unable to move file from $sourcePath to $destinationPath"; $e = new static($message, 0, $previous); $e->source = $sourcePath; $e->destination = $destinationPath; return $e; } public static function because( string $reason, string $sourcePath, string $destinationPath, ): UnableToMoveFile { $message = "Unable to move file from $sourcePath to $destinationPath, because $reason"; $e = new static($message); $e->source = $sourcePath; $e->destination = $destinationPath; return $e; } public function operation(): string { return FilesystemOperationFailed::OPERATION_MOVE; } } location = $location; $e->reason = $reason; return $e; } public function operation(): string { return FilesystemOperationFailed::OPERATION_READ; } public function reason(): string { return $this->reason; } public function location(): string { return $this->location; } } reason = $reason; $e->location = $location; $e->metadataType = $type; return $e; } public function reason(): string { return $this->reason; } public function location(): string { return $this->location; } public function metadataType(): string { return $this->metadataType; } public function operation(): string { return FilesystemOperationFailed::OPERATION_RETRIEVE_METADATA; } } reason; } public static function atLocation(string $filename, string $extraMessage = '', ?Throwable $previous = null): self { $message = "Unable to set visibility for file {$filename}. $extraMessage"; $e = new static(rtrim($message), 0, $previous); $e->reason = $extraMessage; $e->location = $filename; return $e; } public function operation(): string { return FilesystemOperationFailed::OPERATION_SET_VISIBILITY; } public function location(): string { return $this->location; } } location = $location; $e->reason = $reason; return $e; } public function operation(): string { return FilesystemOperationFailed::OPERATION_WRITE; } public function reason(): string { return $this->reason; } public function location(): string { return $this->location; } } filePublic : $this->filePrivate; } public function forDirectory(string $visibility): int { PortableVisibilityGuard::guardAgainstInvalidInput($visibility); return $visibility === Visibility::PUBLIC ? $this->directoryPublic : $this->directoryPrivate; } public function inverseForFile(int $visibility): string { if ($visibility === $this->filePublic) { return Visibility::PUBLIC; } elseif ($visibility === $this->filePrivate) { return Visibility::PRIVATE; } return Visibility::PUBLIC; // default } public function inverseForDirectory(int $visibility): string { if ($visibility === $this->directoryPublic) { return Visibility::PUBLIC; } elseif ($visibility === $this->directoryPrivate) { return Visibility::PRIVATE; } return Visibility::PUBLIC; // default } public function defaultForDirectories(): int { return $this->defaultForDirectories === Visibility::PUBLIC ? $this->directoryPublic : $this->directoryPrivate; } /** * @param array $permissionMap */ public static function fromArray(array $permissionMap, string $defaultForDirectories = Visibility::PRIVATE): PortableVisibilityConverter { return new PortableVisibilityConverter( $permissionMap['file']['public'] ?? 0644, $permissionMap['file']['private'] ?? 0600, $permissionMap['dir']['public'] ?? 0755, $permissionMap['dir']['private'] ?? 0700, $defaultForDirectories ); } } location; } public static function atLocation(string $location): UnreadableFileEncountered { $e = new static("Unreadable file encountered at location {$location}."); $e->location = $location; return $e; } } generators as $generator) { try { return $generator->publicUrl($path, $config); } catch (UnableToGeneratePublicUrl) { } } throw new UnableToGeneratePublicUrl('No supported public url generator found.', $path); } } prefixer = new PathPrefixer($urlPrefix, '/'); } public function publicUrl(string $path, Config $config): string { return $this->prefixer->prefixPath($path); } } count = count($prefixes); if ($this->count === 0) { throw new InvalidArgumentException('At least one prefix is required.'); } $this->prefixes = array_map(static fn (string $prefix) => new PathPrefixer($prefix, '/'), $prefixes); } public function publicUrl(string $path, Config $config): string { $index = abs(crc32($path)) % $this->count; return $this->prefixes[$index]->prefixPath($path); } } allowRelativePaths = $allowRelativePathTraversal; } public function normalizePath(string $path): string { $unixPath = str_replace('\\', '/', $path); if (preg_match('#\p{C}+#u', $unixPath)) { throw CorruptedPathDetected::forPath($path); } $parts = []; foreach (explode('/', $unixPath) as $part) { switch ($part) { case '': case '.': break; case '..': if ($this->allowRelativePaths === false || empty($parts)) { throw PathTraversalDetected::forPath($path); } array_pop($parts); break; default: $parts[] = $part; break; } } return implode('/', $parts); } } detector->detectMimeType($path, $contents); } public function detectMimeTypeFromBuffer(string $contents): ?string { return $this->detector->detectMimeTypeFromBuffer($contents); } public function detectMimeTypeFromPath(string $path): ?string { return $this->detector->detectMimeTypeFromPath($path); } public function detectMimeTypeFromFile(string $path): ?string { $mimeType = $this->detector->detectMimeTypeFromFile($path); if ($mimeType !== null && ! in_array($mimeType, $this->inconclusiveMimetypes)) { return $mimeType; } return $this->detector->detectMimeTypeFromPath($path) ?? ($this->useInconclusiveMimeTypeFallback ? $mimeType : null); } } Copyright (c) 2013-2026 Frank de Jonge 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. prefixer = new PathPrefixer($location, DIRECTORY_SEPARATOR); $visibility ??= new PortableVisibilityConverter(); $this->visibility = $visibility; $this->rootLocation = $location; $this->mimeTypeDetector = $mimeTypeDetector ?? new FallbackMimeTypeDetector( detector: new FinfoMimeTypeDetector(), useInconclusiveMimeTypeFallback: $useInconclusiveMimeTypeFallback, ); if ( ! $lazyRootCreation) { $this->ensureRootDirectoryExists(); } } private function ensureRootDirectoryExists(): void { if ($this->rootLocationIsSetup) { return; } $this->ensureDirectoryExists($this->rootLocation, $this->visibility->defaultForDirectories()); $this->rootLocationIsSetup = true; } public function write(string $path, string $contents, Config $config): void { $this->writeToFile($path, $contents, $config); } public function writeStream(string $path, $contents, Config $config): void { $this->writeToFile($path, $contents, $config); } /** * @param resource|string $contents */ private function writeToFile(string $path, $contents, Config $config): void { $prefixedLocation = $this->prefixer->prefixPath($path); $this->ensureRootDirectoryExists(); $this->ensureDirectoryExists( dirname($prefixedLocation), $this->resolveDirectoryVisibility($config->get(Config::OPTION_DIRECTORY_VISIBILITY)) ); error_clear_last(); if (@file_put_contents($prefixedLocation, $contents, $this->writeFlags) === false) { throw UnableToWriteFile::atLocation($path, error_get_last()['message'] ?? ''); } if ($visibility = $config->get(Config::OPTION_VISIBILITY)) { $this->setVisibility($path, (string) $visibility); } } public function delete(string $path): void { $location = $this->prefixer->prefixPath($path); if ( ! file_exists($location)) { return; } error_clear_last(); if ( ! @unlink($location)) { throw UnableToDeleteFile::atLocation($location, error_get_last()['message'] ?? ''); } } public function deleteDirectory(string $prefix): void { $location = $this->prefixer->prefixPath($prefix); if ( ! is_dir($location)) { return; } $contents = $this->listDirectoryRecursively($location, RecursiveIteratorIterator::CHILD_FIRST); /** @var SplFileInfo $file */ foreach ($contents as $file) { if ( ! $this->deleteFileInfoObject($file)) { throw UnableToDeleteDirectory::atLocation($prefix, "Unable to delete file at " . $file->getPathname()); } } unset($contents); if ( ! @rmdir($location)) { throw UnableToDeleteDirectory::atLocation($prefix, error_get_last()['message'] ?? ''); } } private function listDirectoryRecursively( string $path, int $mode = RecursiveIteratorIterator::SELF_FIRST ): Generator { if ( ! is_dir($path)) { return; } yield from new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), $mode ); } protected function deleteFileInfoObject(SplFileInfo $file): bool { switch ($file->getType()) { case 'dir': return @rmdir((string) $file->getRealPath()); case 'link': return @unlink((string) $file->getPathname()); default: return @unlink((string) $file->getRealPath()); } } public function listContents(string $path, bool $deep): iterable { $location = $this->prefixer->prefixPath($path); if ( ! is_dir($location)) { return; } /** @var SplFileInfo[] $iterator */ $iterator = $deep ? $this->listDirectoryRecursively($location) : $this->listDirectory($location); foreach ($iterator as $fileInfo) { $pathName = $fileInfo->getPathname(); try { if ($fileInfo->isLink()) { if ($this->linkHandling & self::SKIP_LINKS) { continue; } throw SymbolicLinkEncountered::atLocation($pathName); } $path = $this->prefixer->stripPrefix($pathName); $lastModified = $fileInfo->getMTime(); $isDirectory = $fileInfo->isDir(); $permissions = octdec(substr(sprintf('%o', $fileInfo->getPerms()), -4)); $visibility = $isDirectory ? $this->visibility->inverseForDirectory($permissions) : $this->visibility->inverseForFile($permissions); yield $isDirectory ? new DirectoryAttributes(str_replace('\\', '/', $path), $visibility, $lastModified) : new FileAttributes( str_replace('\\', '/', $path), $fileInfo->getSize(), $visibility, $lastModified ); } catch (Throwable $exception) { if (file_exists($pathName)) { throw $exception; } } } } public function move(string $source, string $destination, Config $config): void { $sourcePath = $this->prefixer->prefixPath($source); $destinationPath = $this->prefixer->prefixPath($destination); $this->ensureRootDirectoryExists(); $this->ensureDirectoryExists( dirname($destinationPath), $this->resolveDirectoryVisibility($config->get(Config::OPTION_DIRECTORY_VISIBILITY)) ); error_clear_last(); if ( ! @rename($sourcePath, $destinationPath)) { throw UnableToMoveFile::because(error_get_last()['message'] ?? 'unknown reason', $source, $destination); } if ($visibility = $config->get(Config::OPTION_VISIBILITY)) { $this->setVisibility($destination, (string) $visibility); } } public function copy(string $source, string $destination, Config $config): void { $sourcePath = $this->prefixer->prefixPath($source); $destinationPath = $this->prefixer->prefixPath($destination); $this->ensureRootDirectoryExists(); $this->ensureDirectoryExists( dirname($destinationPath), $this->resolveDirectoryVisibility($config->get(Config::OPTION_DIRECTORY_VISIBILITY)) ); error_clear_last(); if ($sourcePath !== $destinationPath && ! @copy($sourcePath, $destinationPath)) { throw UnableToCopyFile::because(error_get_last()['message'] ?? 'unknown', $source, $destination); } $visibility = $config->get( Config::OPTION_VISIBILITY, $config->get(Config::OPTION_RETAIN_VISIBILITY, true) ? $this->visibility($source)->visibility() : null, ); if ($visibility) { $this->setVisibility($destination, (string) $visibility); } } public function read(string $path): string { $location = $this->prefixer->prefixPath($path); error_clear_last(); $contents = @file_get_contents($location); if ($contents === false) { throw UnableToReadFile::fromLocation($path, error_get_last()['message'] ?? ''); } return $contents; } public function readStream(string $path) { $location = $this->prefixer->prefixPath($path); error_clear_last(); $contents = @fopen($location, 'rb'); if ($contents === false) { throw UnableToReadFile::fromLocation($path, error_get_last()['message'] ?? ''); } return $contents; } protected function ensureDirectoryExists(string $dirname, int $visibility): void { if (is_dir($dirname)) { return; } error_clear_last(); if ( ! @mkdir($dirname, $visibility, true)) { $mkdirError = error_get_last(); } clearstatcache(true, $dirname); if ( ! is_dir($dirname)) { $errorMessage = isset($mkdirError['message']) ? $mkdirError['message'] : ''; throw UnableToCreateDirectory::atLocation($dirname, $errorMessage); } } public function fileExists(string $location): bool { $location = $this->prefixer->prefixPath($location); clearstatcache(); return is_file($location); } public function directoryExists(string $location): bool { $location = $this->prefixer->prefixPath($location); clearstatcache(); return is_dir($location); } public function createDirectory(string $path, Config $config): void { $this->ensureRootDirectoryExists(); $location = $this->prefixer->prefixPath($path); $visibility = $config->get(Config::OPTION_VISIBILITY, $config->get(Config::OPTION_DIRECTORY_VISIBILITY)); $permissions = $this->resolveDirectoryVisibility($visibility); if (is_dir($location)) { $this->setPermissions($location, $permissions); return; } error_clear_last(); if ( ! @mkdir($location, $permissions, true)) { throw UnableToCreateDirectory::atLocation($path, error_get_last()['message'] ?? ''); } } public function setVisibility(string $path, string $visibility): void { $path = $this->prefixer->prefixPath($path); $visibility = is_dir($path) ? $this->visibility->forDirectory($visibility) : $this->visibility->forFile( $visibility ); $this->setPermissions($path, $visibility); } public function visibility(string $path): FileAttributes { $location = $this->prefixer->prefixPath($path); clearstatcache(false, $location); error_clear_last(); $fileperms = @fileperms($location); if ($fileperms === false) { throw UnableToRetrieveMetadata::visibility($path, error_get_last()['message'] ?? ''); } $permissions = $fileperms & 0777; $visibility = $this->visibility->inverseForFile($permissions); return new FileAttributes($path, null, $visibility); } private function resolveDirectoryVisibility(?string $visibility): int { return $visibility === null ? $this->visibility->defaultForDirectories() : $this->visibility->forDirectory( $visibility ); } public function mimeType(string $path): FileAttributes { $location = $this->prefixer->prefixPath($path); error_clear_last(); if ( ! is_file($location)) { throw UnableToRetrieveMetadata::mimeType($location, 'No such file exists.'); } $mimeType = $this->mimeTypeDetector->detectMimeTypeFromFile($location); if ($mimeType === null) { throw UnableToRetrieveMetadata::mimeType($path, error_get_last()['message'] ?? ''); } return new FileAttributes($path, null, null, null, $mimeType); } public function lastModified(string $path): FileAttributes { $location = $this->prefixer->prefixPath($path); clearstatcache(); error_clear_last(); $lastModified = @filemtime($location); if ($lastModified === false) { throw UnableToRetrieveMetadata::lastModified($path, error_get_last()['message'] ?? ''); } return new FileAttributes($path, null, null, $lastModified); } public function fileSize(string $path): FileAttributes { $location = $this->prefixer->prefixPath($path); clearstatcache(); error_clear_last(); if (is_file($location) && ($fileSize = @filesize($location)) !== false) { return new FileAttributes($path, $fileSize); } throw UnableToRetrieveMetadata::fileSize($path, error_get_last()['message'] ?? ''); } public function checksum(string $path, Config $config): string { $algo = $config->get('checksum_algo', 'md5'); $location = $this->prefixer->prefixPath($path); error_clear_last(); $checksum = @hash_file($algo, $location); if ($checksum === false) { throw new UnableToProvideChecksum(error_get_last()['message'] ?? '', $path); } return $checksum; } private function listDirectory(string $location): Generator { $iterator = new DirectoryIterator($location); foreach ($iterator as $item) { if ($item->isDot()) { continue; } yield $item; } } private function setPermissions(string $location, int $visibility): void { error_clear_last(); if ( ! @chmod($location, $visibility)) { $extraMessage = error_get_last()['message'] ?? ''; throw UnableToSetVisibility::atLocation($this->prefixer->stripPrefix($location), $extraMessage); } } } { "name": "league/flysystem-local", "description": "Local filesystem adapter for Flysystem.", "keywords": ["flysystem", "filesystem", "local", "file", "files"], "type": "library", "prefer-stable": true, "autoload": { "psr-4": { "League\\Flysystem\\Local\\": "" } }, "require": { "php": "^8.0.2", "ext-fileinfo": "*", "league/flysystem": "^3.0.0", "league/mime-type-detection": "^1.0.0" }, "license": "MIT", "authors": [ { "name": "Frank de Jonge", "email": "info@frankdejonge.nl" } ] } # Changelog ## 1.17.0 - 2026-07-09 - Updated lookup ## 1.16.0 - 2025-09-21 - Updated lookup - Prepped for 8.4 implicit nullable deprecation ## 1.15.0 - 2024-01-28 - Updated lookup ## 1.14.0 - 2022-10-17 ### Updated - Updated lookup ## 1.13.0 - 2023-08-05 ### Added - A reverse lookup mechanism to fetch one or all extensions for a given mimetype ## 1.12.0 - 2023-08-03 ### Updated - Updated lookup ## 1.11.0 - 2023-04-17 ### Updated - Updated lookup ## 1.10.0 - 2022-04-11 ### Fixed - Added Flysystem v1 inconclusive mime-types and made it configurable as a constructor parameter. ## 1.9.0 - 2021-11-21 ### Updated - Updated lookup ## 1.8.0 - 2021-09-25 ### Added - Added the decorator `OverridingExtensionToMimeTypeMap` which allows you to override values. ## 1.7.0 - 2021-01-18 ### Added - Added a `bufferSampleSize` parameter to the `FinfoMimeTypeDetector` class that allows you to send a reduced content sample which costs less memory. ## 1.6.0 - 2021-01-18 ### Changes - Updated generated mime-type map Copyright (c) 2013-2023 Frank de Jonge 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": "league/mime-type-detection", "description": "Mime-type detection for Flysystem", "license": "MIT", "authors": [ { "name": "Frank de Jonge", "email": "info@frankdejonge.nl" } ], "scripts": { "test": "vendor/bin/phpunit", "phpstan": "vendor/bin/phpstan analyse -l 6 src" }, "require": { "php": "^7.4 || ^8.0", "ext-fileinfo": "*" }, "require-dev": { "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0 || ^11.0 || ^12.0", "phpstan/phpstan": "^0.12.68", "friendsofphp/php-cs-fixer": "^3.2" }, "autoload": { "psr-4": { "League\\MimeTypeDetection\\": "src" } }, "config": { "platform": { "php": "7.4.0" } } } extensions = $extensions ?: new GeneratedExtensionToMimeTypeMap(); } public function detectMimeType(string $path, $contents): ?string { return $this->detectMimeTypeFromPath($path); } public function detectMimeTypeFromPath(string $path): ?string { $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION)); return $this->extensions->lookupMimeType($extension); } public function detectMimeTypeFromFile(string $path): ?string { return $this->detectMimeTypeFromPath($path); } public function detectMimeTypeFromBuffer(string $contents): ?string { return null; } public function lookupExtension(string $mimetype): ?string { return $this->extensions instanceof ExtensionLookup ? $this->extensions->lookupExtension($mimetype) : null; } public function lookupAllExtensions(string $mimetype): array { return $this->extensions instanceof ExtensionLookup ? $this->extensions->lookupAllExtensions($mimetype) : []; } } */ private $inconclusiveMimetypes; public function __construct( string $magicFile = '', ?ExtensionToMimeTypeMap $extensionMap = null, ?int $bufferSampleSize = null, array $inconclusiveMimetypes = self::INCONCLUSIVE_MIME_TYPES ) { $this->finfo = new finfo(FILEINFO_MIME_TYPE, $magicFile); $this->extensionMap = $extensionMap ?: new GeneratedExtensionToMimeTypeMap(); $this->bufferSampleSize = $bufferSampleSize; $this->inconclusiveMimetypes = $inconclusiveMimetypes; } public function detectMimeType(string $path, $contents): ?string { $mimeType = is_string($contents) ? (@$this->finfo->buffer($this->takeSample($contents)) ?: null) : null; if ($mimeType !== null && ! in_array($mimeType, $this->inconclusiveMimetypes)) { return $mimeType; } return $this->detectMimeTypeFromPath($path); } public function detectMimeTypeFromPath(string $path): ?string { $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION)); return $this->extensionMap->lookupMimeType($extension); } public function detectMimeTypeFromFile(string $path): ?string { return @$this->finfo->file($path) ?: null; } public function detectMimeTypeFromBuffer(string $contents): ?string { return @$this->finfo->buffer($this->takeSample($contents)) ?: null; } private function takeSample(string $contents): string { if ($this->bufferSampleSize === null) { return $contents; } return (string) substr($contents, 0, $this->bufferSampleSize); } public function lookupExtension(string $mimetype): ?string { return $this->extensionMap instanceof ExtensionLookup ? $this->extensionMap->lookupExtension($mimetype) : null; } public function lookupAllExtensions(string $mimetype): array { return $this->extensionMap instanceof ExtensionLookup ? $this->extensionMap->lookupAllExtensions($mimetype) : []; } } * * @internal */ public const MIME_TYPES_FOR_EXTENSIONS = [ '1km' => 'application/vnd.1000minds.decision-model+xml', '3dml' => 'text/vnd.in3d.3dml', '3ds' => 'image/x-3ds', '3g2' => 'video/3gpp2', '3gp' => 'video/3gp', '3gpp' => 'video/3gpp', '3mf' => 'model/3mf', '7z' => 'application/x-7z-compressed', '7zip' => 'application/x-7z-compressed', '123' => 'application/vnd.lotus-1-2-3', '210' => 'model/step', 'aab' => 'application/x-authorware-bin', 'aac' => 'audio/acc', 'aam' => 'application/x-authorware-map', 'aas' => 'application/x-authorware-seg', 'abw' => 'application/x-abiword', 'ac' => 'application/vnd.nokia.n-gage.ac+xml', 'ac3' => 'audio/ac3', 'acc' => 'application/vnd.americandynamics.acc', 'ace' => 'application/x-ace-compressed', 'acu' => 'application/vnd.acucobol', 'acutc' => 'application/vnd.acucorp', 'adp' => 'audio/adpcm', 'adts' => 'audio/aac', 'aep' => 'application/vnd.audiograph', 'afm' => 'application/x-font-type1', 'afp' => 'application/vnd.ibm.modcap', 'age' => 'application/vnd.age', 'ahead' => 'application/vnd.ahead.space', 'ai' => 'application/illustrator', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'air' => 'application/vnd.adobe.air-application-installer-package+zip', 'ait' => 'application/vnd.dvb.ait', 'ami' => 'application/vnd.amiga.ami', 'aml' => 'application/automationml-aml+xml', 'amlx' => 'application/automationml-amlx+zip', 'amr' => 'audio/amr', 'apk' => 'application/vnd.android.package-archive', 'apng' => 'image/apng', 'appcache' => 'text/cache-manifest', 'appinstaller' => 'application/appinstaller', 'application' => 'application/x-ms-application', 'appx' => 'application/appx', 'appxbundle' => 'application/appxbundle', 'apr' => 'application/vnd.lotus-approach', 'arc' => 'application/x-freearc', 'arj' => 'application/x-arj', 'asc' => 'application/pgp-signature', 'asf' => 'video/x-ms-asf', 'asm' => 'text/x-asm', 'aso' => 'application/vnd.accpac.simply.aso', 'asx' => 'video/x-ms-asf', 'atc' => 'application/vnd.acucorp', 'atom' => 'application/atom+xml', 'atomcat' => 'application/atomcat+xml', 'atomdeleted' => 'application/atomdeleted+xml', 'atomsvc' => 'application/atomsvc+xml', 'atx' => 'application/vnd.antix.game-component', 'au' => 'audio/x-au', 'avci' => 'image/avci', 'avcs' => 'image/avcs', 'avi' => 'video/x-msvideo', 'avif' => 'image/avif', 'aw' => 'application/applixware', 'azf' => 'application/vnd.airzip.filesecure.azf', 'azs' => 'application/vnd.airzip.filesecure.azs', 'azv' => 'image/vnd.airzip.accelerator.azv', 'azw' => 'application/vnd.amazon.ebook', 'b16' => 'image/vnd.pco.b16', 'bary' => 'model/vnd.bary', 'bat' => 'application/x-msdownload', 'bcpio' => 'application/x-bcpio', 'bdf' => 'application/x-font-bdf', 'bdm' => 'application/vnd.syncml.dm+wbxml', 'bdo' => 'application/vnd.nato.bindingdataobject+xml', 'bdoc' => 'application/x-bdoc', 'bed' => 'application/vnd.realvnc.bed', 'bh2' => 'application/vnd.fujitsu.oasysprs', 'bin' => 'application/octet-stream', 'blb' => 'application/x-blorb', 'blend' => 'application/x-blender', 'blorb' => 'application/x-blorb', 'bmi' => 'application/vnd.bmi', 'bmml' => 'application/vnd.balsamiq.bmml+xml', 'bmp' => 'image/bmp', 'book' => 'application/vnd.framemaker', 'box' => 'application/vnd.previewsystems.box', 'boz' => 'application/x-bzip2', 'bpk' => 'application/octet-stream', 'bpmn' => 'application/octet-stream', 'brf' => 'application/braille', 'brush' => 'application/vnd.procreate.brush', 'brushset' => 'application/vnd.procreate.brushset', 'bsp' => 'model/vnd.valve.source.compiled-map', 'btf' => 'image/prs.btif', 'btif' => 'image/prs.btif', 'buffer' => 'application/octet-stream', 'bz' => 'application/x-bzip', 'bz2' => 'application/x-bzip2', 'c' => 'text/x-c', 'c4d' => 'application/vnd.clonk.c4group', 'c4f' => 'application/vnd.clonk.c4group', 'c4g' => 'application/vnd.clonk.c4group', 'c4p' => 'application/vnd.clonk.c4group', 'c4u' => 'application/vnd.clonk.c4group', 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', 'cab' => 'application/vnd.ms-cab-compressed', 'caf' => 'audio/x-caf', 'cap' => 'application/vnd.tcpdump.pcap', 'car' => 'application/vnd.curl.car', 'cat' => 'application/vnd.ms-pki.seccat', 'cb7' => 'application/x-cbr', 'cba' => 'application/x-cbr', 'cbr' => 'application/x-cbr', 'cbt' => 'application/x-cbr', 'cbz' => 'application/x-cbr', 'cc' => 'text/x-c', 'cco' => 'application/x-cocoa', 'cct' => 'application/x-director', 'ccxml' => 'application/ccxml+xml', 'cdbcmsg' => 'application/vnd.contact.cmsg', 'cdf' => 'application/x-netcdf', 'cdfx' => 'application/cdfx+xml', 'cdkey' => 'application/vnd.mediastation.cdkey', 'cdmia' => 'application/cdmi-capability', 'cdmic' => 'application/cdmi-container', 'cdmid' => 'application/cdmi-domain', 'cdmio' => 'application/cdmi-object', 'cdmiq' => 'application/cdmi-queue', 'cdr' => 'application/cdr', 'cdx' => 'chemical/x-cdx', 'cdxml' => 'application/vnd.chemdraw+xml', 'cdy' => 'application/vnd.cinderella', 'cer' => 'application/pkix-cert', 'cfs' => 'application/x-cfs-compressed', 'cgm' => 'image/cgm', 'chat' => 'application/x-chat', 'chm' => 'application/vnd.ms-htmlhelp', 'chrt' => 'application/vnd.kde.kchart', 'cif' => 'chemical/x-cif', 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', 'cil' => 'application/vnd.ms-artgalry', 'cjs' => 'application/node', 'cla' => 'application/vnd.claymore', 'class' => 'application/octet-stream', 'cld' => 'model/vnd.cld', 'clkk' => 'application/vnd.crick.clicker.keyboard', 'clkp' => 'application/vnd.crick.clicker.palette', 'clkt' => 'application/vnd.crick.clicker.template', 'clkw' => 'application/vnd.crick.clicker.wordbank', 'clkx' => 'application/vnd.crick.clicker', 'clp' => 'application/x-msclip', 'cmc' => 'application/vnd.cosmocaller', 'cmdf' => 'chemical/x-cmdf', 'cml' => 'chemical/x-cml', 'cmp' => 'application/vnd.yellowriver-custom-menu', 'cmx' => 'image/x-cmx', 'cod' => 'application/vnd.rim.cod', 'coffee' => 'text/coffeescript', 'com' => 'application/x-msdownload', 'conf' => 'text/plain', 'cpio' => 'application/x-cpio', 'cpl' => 'application/cpl+xml', 'cpp' => 'text/x-c', 'cpt' => 'application/mac-compactpro', 'crd' => 'application/x-mscardfile', 'crl' => 'application/pkix-crl', 'crt' => 'application/x-x509-ca-cert', 'crx' => 'application/x-chrome-extension', 'cryptonote' => 'application/vnd.rig.cryptonote', 'csh' => 'application/x-csh', 'csl' => 'application/vnd.citationstyles.style+xml', 'csml' => 'chemical/x-csml', 'csp' => 'application/vnd.commonspace', 'csr' => 'application/octet-stream', 'css' => 'text/css', 'cst' => 'application/x-director', 'csv' => 'text/csv', 'cu' => 'application/cu-seeme', 'curl' => 'text/vnd.curl', 'cwl' => 'application/cwl', 'cww' => 'application/prs.cww', 'cxt' => 'application/x-director', 'cxx' => 'text/x-c', 'dae' => 'model/vnd.collada+xml', 'daf' => 'application/vnd.mobius.daf', 'dart' => 'application/vnd.dart', 'dataless' => 'application/vnd.fdsn.seed', 'davmount' => 'application/davmount+xml', 'dbf' => 'application/vnd.dbf', 'dbk' => 'application/docbook+xml', 'dcm' => 'application/dicom', 'dcmp' => 'application/vnd.dcmp+xml', 'dcr' => 'application/x-director', 'dcurl' => 'text/vnd.curl.dcurl', 'dd2' => 'application/vnd.oma.dd2+xml', 'ddd' => 'application/vnd.fujixerox.ddd', 'ddf' => 'application/vnd.syncml.dmddf+xml', 'dds' => 'image/vnd.ms-dds', 'deb' => 'application/x-debian-package', 'def' => 'text/plain', 'deploy' => 'application/octet-stream', 'der' => 'application/x-x509-ca-cert', 'dfac' => 'application/vnd.dreamfactory', 'dgc' => 'application/x-dgc-compressed', 'dib' => 'image/bmp', 'dic' => 'text/x-c', 'dir' => 'application/x-director', 'dis' => 'application/vnd.mobius.dis', 'disposition-notification' => 'message/disposition-notification', 'dist' => 'application/octet-stream', 'distz' => 'application/octet-stream', 'djv' => 'image/vnd.djvu', 'djvu' => 'image/vnd.djvu', 'dll' => 'application/octet-stream', 'dmg' => 'application/x-apple-diskimage', 'dmn' => 'application/octet-stream', 'dmp' => 'application/vnd.tcpdump.pcap', 'dms' => 'application/octet-stream', 'dna' => 'application/vnd.dna', 'dng' => 'image/x-adobe-dng', 'doc' => 'application/msword', 'docm' => 'application/vnd.ms-word.template.macroEnabled.12', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'dot' => 'application/msword', 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'dp' => 'application/vnd.osgi.dp', 'dpg' => 'application/vnd.dpgraph', 'dpx' => 'image/dpx', 'dra' => 'audio/vnd.dra', 'drle' => 'image/dicom-rle', 'drm' => 'application/vnd.procreate.dream', 'dsc' => 'text/prs.lines.tag', 'dssc' => 'application/dssc+der', 'dst' => 'application/octet-stream', 'dtb' => 'application/x-dtbook+xml', 'dtd' => 'application/xml-dtd', 'dts' => 'audio/vnd.dts', 'dtshd' => 'audio/vnd.dts.hd', 'dump' => 'application/octet-stream', 'dvb' => 'video/vnd.dvb.file', 'dvi' => 'application/x-dvi', 'dwd' => 'application/atsc-dwd+xml', 'dwf' => 'model/vnd.dwf', 'dwg' => 'image/vnd.dwg', 'dxf' => 'image/vnd.dxf', 'dxp' => 'application/vnd.spotfire.dxp', 'dxr' => 'application/x-director', 'ear' => 'application/java-archive', 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', 'ecma' => 'application/ecmascript', 'edm' => 'application/vnd.novadigm.edm', 'edx' => 'application/vnd.novadigm.edx', 'efif' => 'application/vnd.picsel', 'ei6' => 'application/vnd.pg.osasli', 'elc' => 'application/octet-stream', 'emf' => 'image/emf', 'eml' => 'message/rfc822', 'emma' => 'application/emma+xml', 'emotionml' => 'application/emotionml+xml', 'emz' => 'application/x-msmetafile', 'eol' => 'audio/vnd.digital-winds', 'eot' => 'application/vnd.ms-fontobject', 'eps' => 'application/postscript', 'epub' => 'application/epub+zip', 'es3' => 'application/vnd.eszigno3+xml', 'esa' => 'application/vnd.osgi.subsystem', 'esf' => 'application/vnd.epson.esf', 'et3' => 'application/vnd.eszigno3+xml', 'etx' => 'text/x-setext', 'eva' => 'application/x-eva', 'evy' => 'application/x-envoy', 'exe' => 'application/octet-stream', 'exi' => 'application/exi', 'exp' => 'application/express', 'exr' => 'image/aces', 'ext' => 'application/vnd.novadigm.ext', 'ez' => 'application/andrew-inset', 'ez2' => 'application/vnd.ezpix-album', 'ez3' => 'application/vnd.ezpix-package', 'f' => 'text/x-fortran', 'f4v' => 'video/mp4', 'f77' => 'text/x-fortran', 'f90' => 'text/x-fortran', 'facti' => 'image/vnd.blockfact.facti', 'fbs' => 'image/vnd.fastbidsheet', 'fbx' => 'application/vnd.autodesk.fbx', 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', 'fcs' => 'application/vnd.isac.fcs', 'fdf' => 'application/vnd.fdf', 'fdt' => 'application/fdt+xml', 'fe_launch' => 'application/vnd.denovo.fcselayout-link', 'fg5' => 'application/vnd.fujitsu.oasysgp', 'fgd' => 'application/x-director', 'fh' => 'image/x-freehand', 'fh4' => 'image/x-freehand', 'fh5' => 'image/x-freehand', 'fh7' => 'image/x-freehand', 'fhc' => 'image/x-freehand', 'fig' => 'application/x-xfig', 'fits' => 'image/fits', 'flac' => 'audio/x-flac', 'fli' => 'video/x-fli', 'flo' => 'application/vnd.micrografx.flo', 'flv' => 'video/x-flv', 'flw' => 'application/vnd.kde.kivio', 'flx' => 'text/vnd.fmi.flexstor', 'fly' => 'text/vnd.fly', 'fm' => 'application/vnd.framemaker', 'fnc' => 'application/vnd.frogans.fnc', 'fo' => 'application/vnd.software602.filler.form+xml', 'for' => 'text/x-fortran', 'fpx' => 'image/vnd.fpx', 'frame' => 'application/vnd.framemaker', 'fsc' => 'application/vnd.fsc.weblaunch', 'fst' => 'image/vnd.fst', 'ftc' => 'application/vnd.fluxtime.clip', 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', 'fvt' => 'video/vnd.fvt', 'fxp' => 'application/vnd.adobe.fxp', 'fxpl' => 'application/vnd.adobe.fxp', 'fzs' => 'application/vnd.fuzzysheet', 'g2w' => 'application/vnd.geoplan', 'g3' => 'image/g3fax', 'g3w' => 'application/vnd.geospace', 'gac' => 'application/vnd.groove-account', 'gam' => 'application/x-tads', 'gbr' => 'application/rpki-ghostbusters', 'gca' => 'application/x-gca-compressed', 'gdl' => 'model/vnd.gdl', 'gdoc' => 'application/vnd.google-apps.document', 'gdraw' => 'application/vnd.google-apps.drawing', 'ged' => 'text/vnd.familysearch.gedcom', 'geo' => 'application/vnd.dynageo', 'geojson' => 'application/geo+json', 'gex' => 'application/vnd.geometry-explorer', 'gform' => 'application/vnd.google-apps.form', 'ggb' => 'application/vnd.geogebra.file', 'ggs' => 'application/vnd.geogebra.slides', 'ggt' => 'application/vnd.geogebra.tool', 'ghf' => 'application/vnd.groove-help', 'gif' => 'image/gif', 'gim' => 'application/vnd.groove-identity-message', 'gjam' => 'application/vnd.google-apps.jam', 'glb' => 'model/gltf-binary', 'gltf' => 'model/gltf+json', 'gmap' => 'application/vnd.google-apps.map', 'gml' => 'application/gml+xml', 'gmx' => 'application/vnd.gmx', 'gnumeric' => 'application/x-gnumeric', 'gpg' => 'application/gpg-keys', 'gph' => 'application/vnd.flographit', 'gpx' => 'application/gpx+xml', 'gqf' => 'application/vnd.grafeq', 'gqs' => 'application/vnd.grafeq', 'gram' => 'application/srgs', 'gramps' => 'application/x-gramps-xml', 'gre' => 'application/vnd.geometry-explorer', 'grv' => 'application/vnd.groove-injector', 'grxml' => 'application/srgs+xml', 'gscript' => 'application/vnd.google-apps.script', 'gsf' => 'application/x-font-ghostscript', 'gsheet' => 'application/vnd.google-apps.spreadsheet', 'gsite' => 'application/vnd.google-apps.site', 'gslides' => 'application/vnd.google-apps.presentation', 'gtar' => 'application/x-gtar', 'gtm' => 'application/vnd.groove-tool-message', 'gtw' => 'model/vnd.gtw', 'gv' => 'text/vnd.graphviz', 'gxf' => 'application/gxf', 'gxt' => 'application/vnd.geonext', 'gz' => 'application/gzip', 'gzip' => 'application/gzip', 'h' => 'text/x-c', 'h261' => 'video/h261', 'h263' => 'video/h263', 'h264' => 'video/h264', 'hal' => 'application/vnd.hal+xml', 'hbci' => 'application/vnd.hbci', 'hbs' => 'text/x-handlebars-template', 'hdd' => 'application/x-virtualbox-hdd', 'hdf' => 'application/x-hdf', 'heic' => 'image/heic', 'heics' => 'image/heic-sequence', 'heif' => 'image/heif', 'heifs' => 'image/heif-sequence', 'hej2' => 'image/hej2k', 'held' => 'application/atsc-held+xml', 'hh' => 'text/x-c', 'hjson' => 'application/hjson', 'hlp' => 'application/winhlp', 'hpgl' => 'application/vnd.hp-hpgl', 'hpid' => 'application/vnd.hp-hpid', 'hps' => 'application/vnd.hp-hps', 'hqx' => 'application/mac-binhex40', 'htc' => 'text/x-component', 'htke' => 'application/vnd.kenameaapp', 'htm' => 'text/html', 'html' => 'text/html', 'hvd' => 'application/vnd.yamaha.hv-dic', 'hvp' => 'application/vnd.yamaha.hv-voice', 'hvs' => 'application/vnd.yamaha.hv-script', 'i2g' => 'application/vnd.intergeo', 'icc' => 'application/vnd.iccprofile', 'ice' => 'x-conference/x-cooltalk', 'icm' => 'application/vnd.iccprofile', 'ico' => 'image/x-icon', 'ics' => 'text/calendar', 'ief' => 'image/ief', 'ifb' => 'text/calendar', 'ifm' => 'application/vnd.shana.informed.formdata', 'iges' => 'model/iges', 'igl' => 'application/vnd.igloader', 'igm' => 'application/vnd.insors.igm', 'igs' => 'model/iges', 'igx' => 'application/vnd.micrografx.igx', 'iif' => 'application/vnd.shana.informed.interchange', 'img' => 'application/octet-stream', 'imp' => 'application/vnd.accpac.simply.imp', 'ims' => 'application/vnd.ms-ims', 'in' => 'text/plain', 'indd' => 'application/x-indesign', 'ini' => 'text/plain', 'ink' => 'application/inkml+xml', 'inkml' => 'application/inkml+xml', 'install' => 'application/x-install-instructions', 'iota' => 'application/vnd.astraea-software.iota', 'ipfix' => 'application/ipfix', 'ipk' => 'application/vnd.shana.informed.package', 'ipynb' => 'application/x-ipynb+json', 'irm' => 'application/vnd.ibm.rights-management', 'irp' => 'application/vnd.irepository.package+xml', 'iso' => 'application/x-iso9660-image', 'itp' => 'application/vnd.shana.informed.formtemplate', 'its' => 'application/its+xml', 'ivp' => 'application/vnd.immervision-ivp', 'ivu' => 'application/vnd.immervision-ivu', 'jad' => 'text/vnd.sun.j2me.app-descriptor', 'jade' => 'text/jade', 'jaii' => 'image/jaii', 'jais' => 'image/jais', 'jam' => 'application/vnd.jam', 'jar' => 'application/java-archive', 'jardiff' => 'application/x-java-archive-diff', 'java' => 'text/x-java-source', 'jfif' => 'image/jpeg', 'jhc' => 'image/jphc', 'jisp' => 'application/vnd.jisp', 'jls' => 'image/jls', 'jlt' => 'application/vnd.hp-jlyt', 'jng' => 'image/x-jng', 'jnlp' => 'application/x-java-jnlp-file', 'joda' => 'application/vnd.joost.joda-archive', 'jp2' => 'image/jp2', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpf' => 'image/jpx', 'jpg' => 'image/jpeg', 'jpg2' => 'image/jp2', 'jpgm' => 'video/jpm', 'jpgv' => 'video/jpeg', 'jph' => 'image/jph', 'jpm' => 'video/jpm', 'jpx' => 'image/jpx', 'js' => 'application/javascript', 'json' => 'application/json', 'json5' => 'application/json5', 'jsonld' => 'application/ld+json', 'jsonml' => 'application/jsonml+json', 'jsx' => 'text/jsx', 'jt' => 'model/jt', 'jxl' => 'image/jxl', 'jxr' => 'image/jxr', 'jxra' => 'image/jxra', 'jxrs' => 'image/jxrs', 'jxs' => 'image/jxs', 'jxsc' => 'image/jxsc', 'jxsi' => 'image/jxsi', 'jxss' => 'image/jxss', 'kar' => 'audio/midi', 'karbon' => 'application/vnd.kde.karbon', 'kbl' => 'application/kbl+xml', 'kdb' => 'application/octet-stream', 'kdbx' => 'application/x-keepass2', 'key' => 'application/x-iwork-keynote-sffkey', 'kfo' => 'application/vnd.kde.kformula', 'kia' => 'application/vnd.kidspiration', 'kml' => 'application/vnd.google-earth.kml+xml', 'kmz' => 'application/vnd.google-earth.kmz', 'kne' => 'application/vnd.kinar', 'knp' => 'application/vnd.kinar', 'kon' => 'application/vnd.kde.kontour', 'kpr' => 'application/vnd.kde.kpresenter', 'kpt' => 'application/vnd.kde.kpresenter', 'kpxx' => 'application/vnd.ds-keypoint', 'ksp' => 'application/vnd.kde.kspread', 'ktr' => 'application/vnd.kahootz', 'ktx' => 'image/ktx', 'ktx2' => 'image/ktx2', 'ktz' => 'application/vnd.kahootz', 'kwd' => 'application/vnd.kde.kword', 'kwt' => 'application/vnd.kde.kword', 'lasxml' => 'application/vnd.las.las+xml', 'latex' => 'application/x-latex', 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', 'les' => 'application/vnd.hhe.lesson-player', 'less' => 'text/less', 'lgr' => 'application/lgr+xml', 'lha' => 'application/octet-stream', 'link66' => 'application/vnd.route66.link66+xml', 'list' => 'text/plain', 'list3820' => 'application/vnd.ibm.modcap', 'listafp' => 'application/vnd.ibm.modcap', 'litcoffee' => 'text/coffeescript', 'lnk' => 'application/x-ms-shortcut', 'log' => 'text/plain', 'lostxml' => 'application/lost+xml', 'lottie' => 'application/zip+dotlottie', 'lrf' => 'application/octet-stream', 'lrm' => 'application/vnd.ms-lrm', 'ltf' => 'application/vnd.frogans.ltf', 'lua' => 'text/x-lua', 'luac' => 'application/x-lua-bytecode', 'lvp' => 'audio/vnd.lucent.voice', 'lwp' => 'application/vnd.lotus-wordpro', 'lzh' => 'application/octet-stream', 'm1v' => 'video/mpeg', 'm2a' => 'audio/mpeg', 'm2t' => 'video/mp2t', 'm2ts' => 'video/mp2t', 'm2v' => 'video/mpeg', 'm3a' => 'audio/mpeg', 'm3u' => 'text/plain', 'm3u8' => 'application/vnd.apple.mpegurl', 'm4a' => 'audio/x-m4a', 'm4b' => 'audio/mp4', 'm4p' => 'application/mp4', 'm4s' => 'video/iso.segment', 'm4u' => 'application/vnd.mpegurl', 'm4v' => 'video/x-m4v', 'm13' => 'application/x-msmediaview', 'm14' => 'application/x-msmediaview', 'm21' => 'application/mp21', 'ma' => 'application/mathematica', 'mads' => 'application/mads+xml', 'maei' => 'application/mmt-aei+xml', 'mag' => 'application/vnd.ecowin.chart', 'maker' => 'application/vnd.framemaker', 'man' => 'text/troff', 'manifest' => 'text/cache-manifest', 'map' => 'application/json', 'mar' => 'application/octet-stream', 'markdown' => 'text/markdown', 'mathml' => 'application/mathml+xml', 'mb' => 'application/mathematica', 'mbk' => 'application/vnd.mobius.mbk', 'mbox' => 'application/mbox', 'mc1' => 'application/vnd.medcalcdata', 'mcd' => 'application/vnd.mcd', 'mcurl' => 'text/vnd.curl.mcurl', 'md' => 'text/markdown', 'mdb' => 'application/x-msaccess', 'mdi' => 'image/vnd.ms-modi', 'mdx' => 'text/mdx', 'me' => 'text/troff', 'mesh' => 'model/mesh', 'meta4' => 'application/metalink4+xml', 'metalink' => 'application/metalink+xml', 'mets' => 'application/mets+xml', 'mfm' => 'application/vnd.mfmp', 'mft' => 'application/rpki-manifest', 'mgp' => 'application/vnd.osgeo.mapguide.package', 'mgz' => 'application/vnd.proteus.magazine', 'mht' => 'message/rfc822', 'mhtml' => 'message/rfc822', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mie' => 'application/x-mie', 'mif' => 'application/vnd.mif', 'mime' => 'message/rfc822', 'mj2' => 'video/mj2', 'mjp2' => 'video/mj2', 'mjs' => 'text/javascript', 'mk3d' => 'video/x-matroska', 'mka' => 'audio/x-matroska', 'mkd' => 'text/x-markdown', 'mks' => 'video/x-matroska', 'mkv' => 'video/x-matroska', 'mlp' => 'application/vnd.dolby.mlp', 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', 'mmf' => 'application/vnd.smaf', 'mml' => 'text/mathml', 'mmr' => 'image/vnd.fujixerox.edmics-mmr', 'mng' => 'video/x-mng', 'mny' => 'application/x-msmoney', 'mobi' => 'application/x-mobipocket-ebook', 'mods' => 'application/mods+xml', 'mov' => 'video/quicktime', 'movie' => 'video/x-sgi-movie', 'mp2' => 'audio/mpeg', 'mp2a' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mp4a' => 'audio/mp4', 'mp4s' => 'application/mp4', 'mp4v' => 'video/mp4', 'mp21' => 'application/mp21', 'mpc' => 'application/vnd.mophun.certificate', 'mpd' => 'application/dash+xml', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpf' => 'application/media-policy-dataset+xml', 'mpg' => 'video/mpeg', 'mpg4' => 'video/mp4', 'mpga' => 'audio/mpeg', 'mpkg' => 'application/vnd.apple.installer+xml', 'mpm' => 'application/vnd.blueice.multipass', 'mpn' => 'application/vnd.mophun.application', 'mpp' => 'application/vnd.ms-project', 'mpt' => 'application/vnd.ms-project', 'mpy' => 'application/vnd.ibm.minipay', 'mqy' => 'application/vnd.mobius.mqy', 'mrc' => 'application/marc', 'mrcx' => 'application/marcxml+xml', 'ms' => 'text/troff', 'mscml' => 'application/mediaservercontrol+xml', 'mseed' => 'application/vnd.fdsn.mseed', 'mseq' => 'application/vnd.mseq', 'msf' => 'application/vnd.epson.msf', 'msg' => 'application/vnd.ms-outlook', 'msh' => 'model/mesh', 'msi' => 'application/x-msdownload', 'msix' => 'application/msix', 'msixbundle' => 'application/msixbundle', 'msl' => 'application/vnd.mobius.msl', 'msm' => 'application/octet-stream', 'msp' => 'application/octet-stream', 'msty' => 'application/vnd.muvee.style', 'mtl' => 'model/mtl', 'mts' => 'video/mp2t', 'mus' => 'application/vnd.musician', 'musd' => 'application/mmt-usd+xml', 'musicxml' => 'application/vnd.recordare.musicxml+xml', 'mvb' => 'application/x-msmediaview', 'mvt' => 'application/vnd.mapbox-vector-tile', 'mwf' => 'application/vnd.mfer', 'mxf' => 'application/mxf', 'mxl' => 'application/vnd.recordare.musicxml', 'mxmf' => 'audio/mobile-xmf', 'mxml' => 'application/xv+xml', 'mxs' => 'application/vnd.triscape.mxs', 'mxu' => 'video/vnd.mpegurl', 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', 'n3' => 'text/n3', 'nb' => 'application/mathematica', 'nbp' => 'application/vnd.wolfram.player', 'nc' => 'application/x-netcdf', 'ncx' => 'application/x-dtbncx+xml', 'ndjson' => 'application/x-ndjson', 'nfo' => 'text/x-nfo', 'ngdat' => 'application/vnd.nokia.n-gage.data', 'nitf' => 'application/vnd.nitf', 'nlu' => 'application/vnd.neurolanguage.nlu', 'nml' => 'application/vnd.enliven', 'nnd' => 'application/vnd.noblenet-directory', 'nns' => 'application/vnd.noblenet-sealer', 'nnw' => 'application/vnd.noblenet-web', 'npx' => 'image/vnd.net-fpx', 'nq' => 'application/n-quads', 'nsc' => 'application/x-conference', 'nsf' => 'application/vnd.lotus-notes', 'nt' => 'application/n-triples', 'ntf' => 'application/vnd.nitf', 'numbers' => 'application/x-iwork-numbers-sffnumbers', 'nzb' => 'application/x-nzb', 'oa2' => 'application/vnd.fujitsu.oasys2', 'oa3' => 'application/vnd.fujitsu.oasys3', 'oas' => 'application/vnd.fujitsu.oasys', 'obd' => 'application/x-msbinder', 'obgx' => 'application/vnd.openblox.game+xml', 'obj' => 'model/obj', 'oda' => 'application/oda', 'odb' => 'application/vnd.oasis.opendocument.database', 'odc' => 'application/vnd.oasis.opendocument.chart', 'odf' => 'application/vnd.oasis.opendocument.formula', 'odft' => 'application/vnd.oasis.opendocument.formula-template', 'odg' => 'application/vnd.oasis.opendocument.graphics', 'odi' => 'application/vnd.oasis.opendocument.image', 'odm' => 'application/vnd.oasis.opendocument.text-master', 'odp' => 'application/vnd.oasis.opendocument.presentation', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 'odt' => 'application/vnd.oasis.opendocument.text', 'oga' => 'audio/ogg', 'ogex' => 'model/vnd.opengex', 'ogg' => 'audio/ogg', 'ogv' => 'video/ogg', 'ogx' => 'application/ogg', 'omdoc' => 'application/omdoc+xml', 'one' => 'application/onenote', 'onea' => 'application/onenote', 'onepkg' => 'application/onenote', 'onetmp' => 'application/onenote', 'onetoc' => 'application/onenote', 'onetoc2' => 'application/onenote', 'opf' => 'application/oebps-package+xml', 'opml' => 'text/x-opml', 'oprc' => 'application/vnd.palm', 'opus' => 'audio/ogg', 'org' => 'text/x-org', 'osf' => 'application/vnd.yamaha.openscoreformat', 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', 'osm' => 'application/vnd.openstreetmap.data+xml', 'otc' => 'application/vnd.oasis.opendocument.chart-template', 'otf' => 'font/otf', 'otg' => 'application/vnd.oasis.opendocument.graphics-template', 'oth' => 'application/vnd.oasis.opendocument.text-web', 'oti' => 'application/vnd.oasis.opendocument.image-template', 'otp' => 'application/vnd.oasis.opendocument.presentation-template', 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', 'ott' => 'application/vnd.oasis.opendocument.text-template', 'ova' => 'application/x-virtualbox-ova', 'ovf' => 'application/x-virtualbox-ovf', 'owl' => 'application/rdf+xml', 'oxps' => 'application/oxps', 'oxt' => 'application/vnd.openofficeorg.extension', 'p' => 'text/x-pascal', 'p7a' => 'application/x-pkcs7-signature', 'p7b' => 'application/x-pkcs7-certificates', 'p7c' => 'application/pkcs7-mime', 'p7m' => 'application/pkcs7-mime', 'p7r' => 'application/x-pkcs7-certreqresp', 'p7s' => 'application/pkcs7-signature', 'p8' => 'application/pkcs8', 'p10' => 'application/x-pkcs10', 'p12' => 'application/x-pkcs12', 'p21' => 'model/step', 'pac' => 'application/x-ns-proxy-autoconfig', 'pages' => 'application/x-iwork-pages-sffpages', 'parquet' => 'application/vnd.apache.parquet', 'pas' => 'text/x-pascal', 'paw' => 'application/vnd.pawaafile', 'pbd' => 'application/vnd.powerbuilder6', 'pbm' => 'image/x-portable-bitmap', 'pcap' => 'application/vnd.tcpdump.pcap', 'pcf' => 'application/x-font-pcf', 'pcl' => 'application/vnd.hp-pcl', 'pclxl' => 'application/vnd.hp-pclxl', 'pct' => 'image/x-pict', 'pcurl' => 'application/vnd.curl.pcurl', 'pcx' => 'image/x-pcx', 'pdb' => 'application/x-pilot', 'pde' => 'text/x-processing', 'pdf' => 'application/pdf', 'pem' => 'application/x-x509-user-cert', 'pfa' => 'application/x-font-type1', 'pfb' => 'application/x-font-type1', 'pfm' => 'application/x-font-type1', 'pfr' => 'application/font-tdpfr', 'pfx' => 'application/x-pkcs12', 'pgm' => 'image/x-portable-graymap', 'pgn' => 'application/x-chess-pgn', 'pgp' => 'application/pgp', 'phar' => 'application/octet-stream', 'php' => 'application/x-httpd-php', 'php3' => 'application/x-httpd-php', 'php4' => 'application/x-httpd-php', 'phps' => 'application/x-httpd-php-source', 'phtml' => 'application/x-httpd-php', 'pic' => 'image/x-pict', 'pkg' => 'application/octet-stream', 'pki' => 'application/pkixcmp', 'pkipath' => 'application/pkix-pkipath', 'pkpass' => 'application/vnd.apple.pkpass', 'pl' => 'application/x-perl', 'plb' => 'application/vnd.3gpp.pic-bw-large', 'plc' => 'application/vnd.mobius.plc', 'plf' => 'application/vnd.pocketlearn', 'pls' => 'application/pls+xml', 'pm' => 'application/x-perl', 'pml' => 'application/vnd.ctc-posml', 'png' => 'image/png', 'pnm' => 'image/x-portable-anymap', 'portpkg' => 'application/vnd.macports.portpkg', 'pot' => 'application/vnd.ms-powerpoint', 'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ppa' => 'application/vnd.ms-powerpoint', 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', 'ppd' => 'application/vnd.cups-ppd', 'ppm' => 'image/x-portable-pixmap', 'pps' => 'application/vnd.ms-powerpoint', 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 'ppt' => 'application/powerpoint', 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pqa' => 'application/vnd.palm', 'prc' => 'model/prc', 'pre' => 'application/vnd.lotus-freelance', 'prf' => 'application/pics-rules', 'provx' => 'application/provenance+xml', 'ps' => 'application/postscript', 'psb' => 'application/vnd.3gpp.pic-bw-small', 'psd' => 'application/x-photoshop', 'psf' => 'application/x-font-linux-psf', 'pskcxml' => 'application/pskc+xml', 'pti' => 'image/prs.pti', 'ptid' => 'application/vnd.pvi.ptid1', 'pub' => 'application/x-mspublisher', 'pv' => 'application/octet-stream', 'pvb' => 'application/vnd.3gpp.pic-bw-var', 'pwn' => 'application/vnd.3m.post-it-notes', 'pxf' => 'application/octet-stream', 'pya' => 'audio/vnd.ms-playready.media.pya', 'pyo' => 'model/vnd.pytha.pyox', 'pyox' => 'model/vnd.pytha.pyox', 'pyv' => 'video/vnd.ms-playready.media.pyv', 'qam' => 'application/vnd.epson.quickanime', 'qbo' => 'application/vnd.intu.qbo', 'qfx' => 'application/vnd.intu.qfx', 'qps' => 'application/vnd.publishare-delta-tree', 'qt' => 'video/quicktime', 'qwd' => 'application/vnd.quark.quarkxpress', 'qwt' => 'application/vnd.quark.quarkxpress', 'qxb' => 'application/vnd.quark.quarkxpress', 'qxd' => 'application/vnd.quark.quarkxpress', 'qxl' => 'application/vnd.quark.quarkxpress', 'qxt' => 'application/vnd.quark.quarkxpress', 'ra' => 'audio/x-realaudio', 'ram' => 'audio/x-pn-realaudio', 'raml' => 'application/raml+yaml', 'rapd' => 'application/route-apd+xml', 'rar' => 'application/x-rar', 'ras' => 'image/x-cmu-raster', 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', 'rdf' => 'application/rdf+xml', 'rdz' => 'application/vnd.data-vision.rdz', 'relo' => 'application/p2p-overlay+xml', 'rep' => 'application/vnd.businessobjects', 'res' => 'application/x-dtbresource+xml', 'rgb' => 'image/x-rgb', 'rif' => 'application/reginfo+xml', 'rip' => 'audio/vnd.rip', 'ris' => 'application/x-research-info-systems', 'rl' => 'application/resource-lists+xml', 'rlc' => 'image/vnd.fujixerox.edmics-rlc', 'rld' => 'application/resource-lists-diff+xml', 'rm' => 'audio/x-pn-realaudio', 'rmi' => 'audio/midi', 'rmp' => 'audio/x-pn-realaudio-plugin', 'rms' => 'application/vnd.jcp.javame.midlet-rms', 'rmvb' => 'application/vnd.rn-realmedia-vbr', 'rnc' => 'application/relax-ng-compact-syntax', 'rng' => 'application/xml', 'roa' => 'application/rpki-roa', 'roff' => 'text/troff', 'rp9' => 'application/vnd.cloanto.rp9', 'rpm' => 'audio/x-pn-realaudio-plugin', 'rpss' => 'application/vnd.nokia.radio-presets', 'rpst' => 'application/vnd.nokia.radio-preset', 'rq' => 'application/sparql-query', 'rs' => 'application/rls-services+xml', 'rsa' => 'application/x-pkcs7', 'rsat' => 'application/atsc-rsat+xml', 'rsd' => 'application/rsd+xml', 'rsheet' => 'application/urc-ressheet+xml', 'rss' => 'application/rss+xml', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', 'run' => 'application/x-makeself', 'rusd' => 'application/route-usd+xml', 'rv' => 'video/vnd.rn-realvideo', 's' => 'text/x-asm', 's3m' => 'audio/s3m', 'saf' => 'application/vnd.yamaha.smaf-audio', 'sass' => 'text/x-sass', 'sbml' => 'application/sbml+xml', 'sc' => 'application/vnd.ibm.secure-container', 'scd' => 'application/x-msschedule', 'scm' => 'application/vnd.lotus-screencam', 'scq' => 'application/scvp-cv-request', 'scs' => 'application/scvp-cv-response', 'scss' => 'text/x-scss', 'scurl' => 'text/vnd.curl.scurl', 'sda' => 'application/vnd.stardivision.draw', 'sdc' => 'application/vnd.stardivision.calc', 'sdd' => 'application/vnd.stardivision.impress', 'sdkd' => 'application/vnd.solent.sdkm+xml', 'sdkm' => 'application/vnd.solent.sdkm+xml', 'sdp' => 'application/sdp', 'sdw' => 'application/vnd.stardivision.writer', 'sea' => 'application/octet-stream', 'see' => 'application/vnd.seemail', 'seed' => 'application/vnd.fdsn.seed', 'sema' => 'application/vnd.sema', 'semd' => 'application/vnd.semd', 'semf' => 'application/vnd.semf', 'senmlx' => 'application/senml+xml', 'sensmlx' => 'application/sensml+xml', 'ser' => 'application/java-serialized-object', 'setpay' => 'application/set-payment-initiation', 'setreg' => 'application/set-registration-initiation', 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', 'sfs' => 'application/vnd.spotfire.sfs', 'sfv' => 'text/x-sfv', 'sgi' => 'image/sgi', 'sgl' => 'application/vnd.stardivision.writer-global', 'sgm' => 'text/sgml', 'sgml' => 'text/sgml', 'sh' => 'application/x-sh', 'shar' => 'application/x-shar', 'shex' => 'text/shex', 'shf' => 'application/shf+xml', 'shtml' => 'text/html', 'sid' => 'image/x-mrsid-image', 'sieve' => 'application/sieve', 'sig' => 'application/pgp-signature', 'sil' => 'audio/silk', 'silo' => 'model/mesh', 'sis' => 'application/vnd.symbian.install', 'sisx' => 'application/vnd.symbian.install', 'sit' => 'application/x-stuffit', 'sitx' => 'application/x-stuffitx', 'siv' => 'application/sieve', 'skd' => 'application/vnd.koan', 'skm' => 'application/vnd.koan', 'skp' => 'application/vnd.koan', 'skt' => 'application/vnd.koan', 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', 'slim' => 'text/slim', 'slm' => 'text/slim', 'sls' => 'application/route-s-tsid+xml', 'slt' => 'application/vnd.epson.salt', 'sm' => 'application/vnd.stepmania.stepchart', 'smf' => 'application/vnd.stardivision.math', 'smi' => 'application/smil', 'smil' => 'application/smil', 'smv' => 'video/x-smv', 'smzip' => 'application/vnd.stepmania.package', 'snd' => 'audio/basic', 'snf' => 'application/x-font-snf', 'so' => 'application/octet-stream', 'spc' => 'application/x-pkcs7-certificates', 'spdx' => 'text/spdx', 'spf' => 'application/vnd.yamaha.smaf-phrase', 'spl' => 'application/x-futuresplash', 'spot' => 'text/vnd.in3d.spot', 'spp' => 'application/scvp-vp-response', 'spq' => 'application/scvp-vp-request', 'spx' => 'audio/ogg', 'sql' => 'application/x-sql', 'sqlite' => 'application/vnd.sqlite3', 'sqlite3' => 'application/vnd.sqlite3', 'src' => 'application/x-wais-source', 'srt' => 'application/x-subrip', 'sru' => 'application/sru+xml', 'srx' => 'application/sparql-results+xml', 'ssdl' => 'application/ssdl+xml', 'sse' => 'application/vnd.kodak-descriptor', 'ssf' => 'application/vnd.epson.ssf', 'ssml' => 'application/ssml+xml', 'sst' => 'application/octet-stream', 'st' => 'application/vnd.sailingtracker.track', 'stc' => 'application/vnd.sun.xml.calc.template', 'std' => 'application/vnd.sun.xml.draw.template', 'step' => 'application/STEP', 'stf' => 'application/vnd.wt.stf', 'sti' => 'application/vnd.sun.xml.impress.template', 'stk' => 'application/hyperstudio', 'stl' => 'model/stl', 'stp' => 'application/STEP', 'stpnc' => 'model/step', 'stpx' => 'model/step+xml', 'stpxz' => 'model/step-xml+zip', 'stpz' => 'model/step+zip', 'str' => 'application/vnd.pg.format', 'stw' => 'application/vnd.sun.xml.writer.template', 'styl' => 'text/stylus', 'stylus' => 'text/stylus', 'sub' => 'text/vnd.dvb.subtitle', 'sus' => 'application/vnd.sus-calendar', 'susp' => 'application/vnd.sus-calendar', 'sv4cpio' => 'application/x-sv4cpio', 'sv4crc' => 'application/x-sv4crc', 'svc' => 'application/vnd.dvb.service', 'svd' => 'application/vnd.svd', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', 'swa' => 'application/x-director', 'swf' => 'application/x-shockwave-flash', 'swi' => 'application/vnd.aristanetworks.swi', 'swidtag' => 'application/swid+xml', 'sxc' => 'application/vnd.sun.xml.calc', 'sxd' => 'application/vnd.sun.xml.draw', 'sxg' => 'application/vnd.sun.xml.writer.global', 'sxi' => 'application/vnd.sun.xml.impress', 'sxm' => 'application/vnd.sun.xml.math', 'sxw' => 'application/vnd.sun.xml.writer', 'systemverify' => 'application/vnd.pp.systemverify+xml', 't' => 'text/troff', 't3' => 'application/x-t3vm-image', 't38' => 'image/t38', 'taglet' => 'application/vnd.mynfc', 'tao' => 'application/vnd.tao.intent-module-archive', 'tap' => 'image/vnd.tencent.tap', 'tar' => 'application/x-tar', 'tcap' => 'application/vnd.3gpp2.tcap', 'tcl' => 'application/x-tcl', 'td' => 'application/urc-targetdesc+xml', 'teacher' => 'application/vnd.smart.teacher', 'tei' => 'application/tei+xml', 'teicorpus' => 'application/tei+xml', 'tex' => 'application/x-tex', 'texi' => 'application/x-texinfo', 'texinfo' => 'application/x-texinfo', 'text' => 'text/plain', 'tfi' => 'application/thraud+xml', 'tfm' => 'application/x-tex-tfm', 'tfx' => 'image/tiff-fx', 'tga' => 'image/x-tga', 'tgz' => 'application/x-tar', 'thmx' => 'application/vnd.ms-officetheme', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'tk' => 'application/x-tcl', 'tmo' => 'application/vnd.tmobile-livetv', 'toml' => 'application/toml', 'torrent' => 'application/x-bittorrent', 'tpl' => 'application/vnd.groove-tool-template', 'tpt' => 'application/vnd.trid.tpt', 'tr' => 'text/troff', 'tra' => 'application/vnd.trueapp', 'trig' => 'application/trig', 'trm' => 'application/x-msterminal', 'ts' => 'video/mp2t', 'tsd' => 'application/timestamped-data', 'tsv' => 'text/tab-separated-values', 'ttc' => 'font/collection', 'ttf' => 'font/ttf', 'ttl' => 'text/turtle', 'ttml' => 'application/ttml+xml', 'twd' => 'application/vnd.simtech-mindmapper', 'twds' => 'application/vnd.simtech-mindmapper', 'txd' => 'application/vnd.genomatix.tuxedo', 'txf' => 'application/vnd.mobius.txf', 'txt' => 'text/plain', 'u3d' => 'model/u3d', 'u8dsn' => 'message/global-delivery-status', 'u8hdr' => 'message/global-headers', 'u8mdn' => 'message/global-disposition-notification', 'u8msg' => 'message/global', 'u32' => 'application/x-authorware-bin', 'ubj' => 'application/ubjson', 'udeb' => 'application/x-debian-package', 'ufd' => 'application/vnd.ufdl', 'ufdl' => 'application/vnd.ufdl', 'ulx' => 'application/x-glulx', 'umj' => 'application/vnd.umajin', 'unityweb' => 'application/vnd.unity', 'uo' => 'application/vnd.uoml+xml', 'uoml' => 'application/vnd.uoml+xml', 'uri' => 'text/uri-list', 'uris' => 'text/uri-list', 'urls' => 'text/uri-list', 'usda' => 'model/vnd.usda', 'usdz' => 'model/vnd.usdz+zip', 'ustar' => 'application/x-ustar', 'utz' => 'application/vnd.uiq.theme', 'uu' => 'text/x-uuencode', 'uva' => 'audio/vnd.dece.audio', 'uvd' => 'application/vnd.dece.data', 'uvf' => 'application/vnd.dece.data', 'uvg' => 'image/vnd.dece.graphic', 'uvh' => 'video/vnd.dece.hd', 'uvi' => 'image/vnd.dece.graphic', 'uvm' => 'video/vnd.dece.mobile', 'uvp' => 'video/vnd.dece.pd', 'uvs' => 'video/vnd.dece.sd', 'uvt' => 'application/vnd.dece.ttml+xml', 'uvu' => 'video/vnd.uvvu.mp4', 'uvv' => 'video/vnd.dece.video', 'uvva' => 'audio/vnd.dece.audio', 'uvvd' => 'application/vnd.dece.data', 'uvvf' => 'application/vnd.dece.data', 'uvvg' => 'image/vnd.dece.graphic', 'uvvh' => 'video/vnd.dece.hd', 'uvvi' => 'image/vnd.dece.graphic', 'uvvm' => 'video/vnd.dece.mobile', 'uvvp' => 'video/vnd.dece.pd', 'uvvs' => 'video/vnd.dece.sd', 'uvvt' => 'application/vnd.dece.ttml+xml', 'uvvu' => 'video/vnd.uvvu.mp4', 'uvvv' => 'video/vnd.dece.video', 'uvvx' => 'application/vnd.dece.unspecified', 'uvvz' => 'application/vnd.dece.zip', 'uvx' => 'application/vnd.dece.unspecified', 'uvz' => 'application/vnd.dece.zip', 'vbox' => 'application/x-virtualbox-vbox', 'vbox-extpack' => 'application/x-virtualbox-vbox-extpack', 'vcard' => 'text/vcard', 'vcd' => 'application/x-cdlink', 'vcf' => 'text/x-vcard', 'vcg' => 'application/vnd.groove-vcard', 'vcs' => 'text/x-vcalendar', 'vcx' => 'application/vnd.vcx', 'vdi' => 'application/x-virtualbox-vdi', 'vds' => 'model/vnd.sap.vds', 'vdx' => 'application/vnd.ms-visio.viewer', 'vec' => 'application/vec+xml', 'vhd' => 'application/x-virtualbox-vhd', 'vis' => 'application/vnd.visionary', 'viv' => 'video/vnd.vivo', 'vlc' => 'application/videolan', 'vmdk' => 'application/x-virtualbox-vmdk', 'vob' => 'video/x-ms-vob', 'vor' => 'application/vnd.stardivision.writer', 'vox' => 'application/x-authorware-bin', 'vrml' => 'model/vrml', 'vsd' => 'application/vnd.visio', 'vsdx' => 'application/vnd.visio', 'vsf' => 'application/vnd.vsf', 'vss' => 'application/vnd.visio', 'vst' => 'application/vnd.visio', 'vsw' => 'application/vnd.visio', 'vtf' => 'image/vnd.valve.source.texture', 'vtt' => 'text/vtt', 'vtu' => 'model/vnd.vtu', 'vtx' => 'application/vnd.visio', 'vxml' => 'application/voicexml+xml', 'w3d' => 'application/x-director', 'wad' => 'application/x-doom', 'wadl' => 'application/vnd.sun.wadl+xml', 'war' => 'application/java-archive', 'wasm' => 'application/wasm', 'wav' => 'audio/x-wav', 'wax' => 'audio/x-ms-wax', 'wbmp' => 'image/vnd.wap.wbmp', 'wbs' => 'application/vnd.criticaltools.wbs+xml', 'wbxml' => 'application/wbxml', 'wcm' => 'application/vnd.ms-works', 'wdb' => 'application/vnd.ms-works', 'wdp' => 'image/vnd.ms-photo', 'weba' => 'audio/webm', 'webapp' => 'application/x-web-app-manifest+json', 'webm' => 'video/webm', 'webmanifest' => 'application/manifest+json', 'webp' => 'image/webp', 'wg' => 'application/vnd.pmi.widget', 'wgsl' => 'text/wgsl', 'wgt' => 'application/widget', 'wif' => 'application/watcherinfo+xml', 'wks' => 'application/vnd.ms-works', 'wm' => 'video/x-ms-wm', 'wma' => 'audio/x-ms-wma', 'wmd' => 'application/x-ms-wmd', 'wmf' => 'image/wmf', 'wml' => 'text/vnd.wap.wml', 'wmlc' => 'application/wmlc', 'wmls' => 'text/vnd.wap.wmlscript', 'wmlsc' => 'application/vnd.wap.wmlscriptc', 'wmv' => 'video/x-ms-wmv', 'wmx' => 'video/x-ms-wmx', 'wmz' => 'application/x-msmetafile', 'woff' => 'font/woff', 'woff2' => 'font/woff2', 'word' => 'application/msword', 'wpd' => 'application/vnd.wordperfect', 'wpl' => 'application/vnd.ms-wpl', 'wps' => 'application/vnd.ms-works', 'wqd' => 'application/vnd.wqd', 'wri' => 'application/x-mswrite', 'wrl' => 'model/vrml', 'wsc' => 'message/vnd.wfa.wsc', 'wsdl' => 'application/wsdl+xml', 'wspolicy' => 'application/wspolicy+xml', 'wtb' => 'application/vnd.webturbo', 'wvx' => 'video/x-ms-wvx', 'x3d' => 'model/x3d+xml', 'x3db' => 'model/x3d+fastinfoset', 'x3dbz' => 'model/x3d+binary', 'x3dv' => 'model/x3d-vrml', 'x3dvz' => 'model/x3d+vrml', 'x3dz' => 'model/x3d+xml', 'x32' => 'application/x-authorware-bin', 'x_b' => 'model/vnd.parasolid.transmit.binary', 'x_t' => 'model/vnd.parasolid.transmit.text', 'xaml' => 'application/xaml+xml', 'xap' => 'application/x-silverlight-app', 'xar' => 'application/vnd.xara', 'xav' => 'application/xcap-att+xml', 'xbap' => 'application/x-ms-xbap', 'xbd' => 'application/vnd.fujixerox.docuworks.binder', 'xbm' => 'image/x-xbitmap', 'xca' => 'application/xcap-caps+xml', 'xcs' => 'application/calendar+xml', 'xdcf' => 'application/vnd.gov.sk.xmldatacontainer+xml', 'xdf' => 'application/xcap-diff+xml', 'xdm' => 'application/vnd.syncml.dm+xml', 'xdp' => 'application/vnd.adobe.xdp+xml', 'xdssc' => 'application/dssc+xml', 'xdw' => 'application/vnd.fujixerox.docuworks', 'xel' => 'application/xcap-el+xml', 'xenc' => 'application/xenc+xml', 'xer' => 'application/patch-ops-error+xml', 'xfdf' => 'application/xfdf', 'xfdl' => 'application/vnd.xfdl', 'xht' => 'application/xhtml+xml', 'xhtm' => 'application/vnd.pwg-xhtml-print+xml', 'xhtml' => 'application/xhtml+xml', 'xhvml' => 'application/xv+xml', 'xif' => 'image/vnd.xiff', 'xl' => 'application/excel', 'xla' => 'application/vnd.ms-excel', 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', 'xlc' => 'application/vnd.ms-excel', 'xlf' => 'application/xliff+xml', 'xlm' => 'application/vnd.ms-excel', 'xls' => 'application/vnd.ms-excel', 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlt' => 'application/vnd.ms-excel', 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'xlw' => 'application/vnd.ms-excel', 'xm' => 'audio/xm', 'xml' => 'application/xml', 'xns' => 'application/xcap-ns+xml', 'xo' => 'application/vnd.olpc-sugar', 'xop' => 'application/xop+xml', 'xpi' => 'application/x-xpinstall', 'xpl' => 'application/xproc+xml', 'xpm' => 'image/x-xpixmap', 'xpr' => 'application/vnd.is-xpr', 'xps' => 'application/vnd.ms-xpsdocument', 'xpw' => 'application/vnd.intercon.formnet', 'xpx' => 'application/vnd.intercon.formnet', 'xsd' => 'application/xml', 'xsf' => 'application/prs.xsf+xml', 'xsl' => 'application/xml', 'xslt' => 'application/xslt+xml', 'xsm' => 'application/vnd.syncml+xml', 'xspf' => 'application/xspf+xml', 'xul' => 'application/vnd.mozilla.xul+xml', 'xvm' => 'application/xv+xml', 'xvml' => 'application/xv+xml', 'xwd' => 'image/x-xwindowdump', 'xyz' => 'chemical/x-xyz', 'xz' => 'application/x-xz', 'yaml' => 'text/yaml', 'yang' => 'application/yang', 'yin' => 'application/yin+xml', 'yml' => 'text/yaml', 'ymp' => 'text/x-suse-ymp', 'z' => 'application/x-compress', 'z1' => 'application/x-zmachine', 'z2' => 'application/x-zmachine', 'z3' => 'application/x-zmachine', 'z4' => 'application/x-zmachine', 'z5' => 'application/x-zmachine', 'z6' => 'application/x-zmachine', 'z7' => 'application/x-zmachine', 'z8' => 'application/x-zmachine', 'zaz' => 'application/vnd.zzazz.deck+xml', 'zip' => 'application/zip', 'zir' => 'application/vnd.zul', 'zirz' => 'application/vnd.zul', 'zmm' => 'application/vnd.handheld-entertainment+xml', 'zsh' => 'text/x-scriptzsh', ]; /** * @var array * * @internal */ public const EXTENSIONS_FOR_MIME_TIMES = [ 'application/andrew-inset' => ['ez'], 'application/appinstaller' => ['appinstaller'], 'application/applixware' => ['aw'], 'application/appx' => ['appx'], 'application/appxbundle' => ['appxbundle'], 'application/atom+xml' => ['atom'], 'application/atomcat+xml' => ['atomcat'], 'application/atomdeleted+xml' => ['atomdeleted'], 'application/atomsvc+xml' => ['atomsvc'], 'application/atsc-dwd+xml' => ['dwd'], 'application/atsc-held+xml' => ['held'], 'application/atsc-rsat+xml' => ['rsat'], 'application/automationml-aml+xml' => ['aml'], 'application/automationml-amlx+zip' => ['amlx'], 'application/bdoc' => ['bdoc'], 'application/calendar+xml' => ['xcs'], 'application/ccxml+xml' => ['ccxml'], 'application/cdfx+xml' => ['cdfx'], 'application/cdmi-capability' => ['cdmia'], 'application/cdmi-container' => ['cdmic'], 'application/cdmi-domain' => ['cdmid'], 'application/cdmi-object' => ['cdmio'], 'application/cdmi-queue' => ['cdmiq'], 'application/cpl+xml' => ['cpl'], 'application/cu-seeme' => ['cu'], 'application/cwl' => ['cwl'], 'application/dash+xml' => ['mpd'], 'application/dash-patch+xml' => ['mpp'], 'application/davmount+xml' => ['davmount'], 'application/dicom' => ['dcm'], 'application/docbook+xml' => ['dbk'], 'application/dssc+der' => ['dssc'], 'application/dssc+xml' => ['xdssc'], 'application/ecmascript' => ['ecma'], 'application/emma+xml' => ['emma'], 'application/emotionml+xml' => ['emotionml'], 'application/epub+zip' => ['epub'], 'application/exi' => ['exi'], 'application/express' => ['exp'], 'application/fdf' => ['fdf'], 'application/fdt+xml' => ['fdt'], 'application/font-tdpfr' => ['pfr'], 'application/geo+json' => ['geojson'], 'application/gml+xml' => ['gml'], 'application/gpx+xml' => ['gpx'], 'application/gxf' => ['gxf'], 'application/gzip' => ['gz', 'gzip'], 'application/hjson' => ['hjson'], 'application/hyperstudio' => ['stk'], 'application/inkml+xml' => ['ink', 'inkml'], 'application/ipfix' => ['ipfix'], 'application/its+xml' => ['its'], 'application/java-archive' => ['jar', 'war', 'ear'], 'application/java-serialized-object' => ['ser'], 'application/java-vm' => ['class'], 'application/javascript' => ['js'], 'application/json' => ['json', 'map'], 'application/json5' => ['json5'], 'application/jsonml+json' => ['jsonml'], 'application/kbl+xml' => ['kbl'], 'application/ld+json' => ['jsonld'], 'application/lgr+xml' => ['lgr'], 'application/lost+xml' => ['lostxml'], 'application/mac-binhex40' => ['hqx'], 'application/mac-compactpro' => ['cpt'], 'application/mads+xml' => ['mads'], 'application/manifest+json' => ['webmanifest'], 'application/marc' => ['mrc'], 'application/marcxml+xml' => ['mrcx'], 'application/mathematica' => ['ma', 'nb', 'mb'], 'application/mathml+xml' => ['mathml'], 'application/mbox' => ['mbox'], 'application/media-policy-dataset+xml' => ['mpf'], 'application/mediaservercontrol+xml' => ['mscml'], 'application/metalink+xml' => ['metalink'], 'application/metalink4+xml' => ['meta4'], 'application/mets+xml' => ['mets'], 'application/mmt-aei+xml' => ['maei'], 'application/mmt-usd+xml' => ['musd'], 'application/mods+xml' => ['mods'], 'application/mp21' => ['m21', 'mp21'], 'application/mp4' => ['mp4', 'mpg4', 'mp4s', 'm4p'], 'application/msix' => ['msix'], 'application/msixbundle' => ['msixbundle'], 'application/msword' => ['doc', 'dot', 'word'], 'application/mxf' => ['mxf'], 'application/n-quads' => ['nq'], 'application/n-triples' => ['nt'], 'application/node' => ['cjs'], 'application/octet-stream' => ['bin', 'dms', 'lrf', 'mar', 'so', 'dist', 'distz', 'pkg', 'bpk', 'dump', 'elc', 'deploy', 'exe', 'dll', 'deb', 'dmg', 'iso', 'img', 'msi', 'msp', 'msm', 'buffer', 'phar', 'lha', 'lzh', 'class', 'sea', 'dmn', 'bpmn', 'kdb', 'sst', 'csr', 'dst', 'pv', 'pxf'], 'application/oda' => ['oda'], 'application/oebps-package+xml' => ['opf'], 'application/ogg' => ['ogx'], 'application/omdoc+xml' => ['omdoc'], 'application/onenote' => ['onetoc', 'onetoc2', 'onetmp', 'onepkg', 'one', 'onea'], 'application/oxps' => ['oxps'], 'application/p2p-overlay+xml' => ['relo'], 'application/patch-ops-error+xml' => ['xer'], 'application/pdf' => ['pdf'], 'application/pgp-encrypted' => ['pgp'], 'application/pgp-keys' => ['asc'], 'application/pgp-signature' => ['sig', 'asc'], 'application/pics-rules' => ['prf'], 'application/pkcs10' => ['p10'], 'application/pkcs7-mime' => ['p7m', 'p7c'], 'application/pkcs7-signature' => ['p7s'], 'application/pkcs8' => ['p8'], 'application/pkix-attr-cert' => ['ac'], 'application/pkix-cert' => ['cer'], 'application/pkix-crl' => ['crl'], 'application/pkix-pkipath' => ['pkipath'], 'application/pkixcmp' => ['pki'], 'application/pls+xml' => ['pls'], 'application/postscript' => ['ai', 'eps', 'ps'], 'application/provenance+xml' => ['provx'], 'application/prs.cww' => ['cww'], 'application/prs.xsf+xml' => ['xsf'], 'application/pskc+xml' => ['pskcxml'], 'application/raml+yaml' => ['raml'], 'application/rdf+xml' => ['rdf', 'owl'], 'application/reginfo+xml' => ['rif'], 'application/relax-ng-compact-syntax' => ['rnc'], 'application/resource-lists+xml' => ['rl'], 'application/resource-lists-diff+xml' => ['rld'], 'application/rls-services+xml' => ['rs'], 'application/route-apd+xml' => ['rapd'], 'application/route-s-tsid+xml' => ['sls'], 'application/route-usd+xml' => ['rusd'], 'application/rpki-ghostbusters' => ['gbr'], 'application/rpki-manifest' => ['mft'], 'application/rpki-roa' => ['roa'], 'application/rsd+xml' => ['rsd'], 'application/rss+xml' => ['rss'], 'application/rtf' => ['rtf'], 'application/sbml+xml' => ['sbml'], 'application/scvp-cv-request' => ['scq'], 'application/scvp-cv-response' => ['scs'], 'application/scvp-vp-request' => ['spq'], 'application/scvp-vp-response' => ['spp'], 'application/sdp' => ['sdp'], 'application/senml+xml' => ['senmlx'], 'application/sensml+xml' => ['sensmlx'], 'application/set-payment-initiation' => ['setpay'], 'application/set-registration-initiation' => ['setreg'], 'application/shf+xml' => ['shf'], 'application/sieve' => ['siv', 'sieve'], 'application/smil+xml' => ['smi', 'smil'], 'application/sparql-query' => ['rq'], 'application/sparql-results+xml' => ['srx'], 'application/sql' => ['sql'], 'application/srgs' => ['gram'], 'application/srgs+xml' => ['grxml'], 'application/sru+xml' => ['sru'], 'application/ssdl+xml' => ['ssdl'], 'application/ssml+xml' => ['ssml'], 'application/swid+xml' => ['swidtag'], 'application/tei+xml' => ['tei', 'teicorpus'], 'application/thraud+xml' => ['tfi'], 'application/timestamped-data' => ['tsd'], 'application/toml' => ['toml'], 'application/trig' => ['trig'], 'application/ttml+xml' => ['ttml'], 'application/ubjson' => ['ubj'], 'application/urc-ressheet+xml' => ['rsheet'], 'application/urc-targetdesc+xml' => ['td'], 'application/vec+xml' => ['vec'], 'application/vnd.1000minds.decision-model+xml' => ['1km'], 'application/vnd.3gpp.pic-bw-large' => ['plb'], 'application/vnd.3gpp.pic-bw-small' => ['psb'], 'application/vnd.3gpp.pic-bw-var' => ['pvb'], 'application/vnd.3gpp2.tcap' => ['tcap'], 'application/vnd.3m.post-it-notes' => ['pwn'], 'application/vnd.accpac.simply.aso' => ['aso'], 'application/vnd.accpac.simply.imp' => ['imp'], 'application/vnd.acucobol' => ['acu'], 'application/vnd.acucorp' => ['atc', 'acutc'], 'application/vnd.adobe.air-application-installer-package+zip' => ['air'], 'application/vnd.adobe.formscentral.fcdt' => ['fcdt'], 'application/vnd.adobe.fxp' => ['fxp', 'fxpl'], 'application/vnd.adobe.xdp+xml' => ['xdp'], 'application/vnd.adobe.xfdf' => ['xfdf'], 'application/vnd.age' => ['age'], 'application/vnd.ahead.space' => ['ahead'], 'application/vnd.airzip.filesecure.azf' => ['azf'], 'application/vnd.airzip.filesecure.azs' => ['azs'], 'application/vnd.amazon.ebook' => ['azw'], 'application/vnd.americandynamics.acc' => ['acc'], 'application/vnd.amiga.ami' => ['ami'], 'application/vnd.android.package-archive' => ['apk'], 'application/vnd.anser-web-certificate-issue-initiation' => ['cii'], 'application/vnd.anser-web-funds-transfer-initiation' => ['fti'], 'application/vnd.antix.game-component' => ['atx'], 'application/vnd.apache.parquet' => ['parquet'], 'application/vnd.apple.installer+xml' => ['mpkg'], 'application/vnd.apple.keynote' => ['key'], 'application/vnd.apple.mpegurl' => ['m3u8'], 'application/vnd.apple.numbers' => ['numbers'], 'application/vnd.apple.pages' => ['pages'], 'application/vnd.apple.pkpass' => ['pkpass'], 'application/vnd.aristanetworks.swi' => ['swi'], 'application/vnd.astraea-software.iota' => ['iota'], 'application/vnd.audiograph' => ['aep'], 'application/vnd.autodesk.fbx' => ['fbx'], 'application/vnd.balsamiq.bmml+xml' => ['bmml'], 'application/vnd.blueice.multipass' => ['mpm'], 'application/vnd.bmi' => ['bmi'], 'application/vnd.businessobjects' => ['rep'], 'application/vnd.chemdraw+xml' => ['cdxml'], 'application/vnd.chipnuts.karaoke-mmd' => ['mmd'], 'application/vnd.cinderella' => ['cdy'], 'application/vnd.citationstyles.style+xml' => ['csl'], 'application/vnd.claymore' => ['cla'], 'application/vnd.cloanto.rp9' => ['rp9'], 'application/vnd.clonk.c4group' => ['c4g', 'c4d', 'c4f', 'c4p', 'c4u'], 'application/vnd.cluetrust.cartomobile-config' => ['c11amc'], 'application/vnd.cluetrust.cartomobile-config-pkg' => ['c11amz'], 'application/vnd.commonspace' => ['csp'], 'application/vnd.contact.cmsg' => ['cdbcmsg'], 'application/vnd.cosmocaller' => ['cmc'], 'application/vnd.crick.clicker' => ['clkx'], 'application/vnd.crick.clicker.keyboard' => ['clkk'], 'application/vnd.crick.clicker.palette' => ['clkp'], 'application/vnd.crick.clicker.template' => ['clkt'], 'application/vnd.crick.clicker.wordbank' => ['clkw'], 'application/vnd.criticaltools.wbs+xml' => ['wbs'], 'application/vnd.ctc-posml' => ['pml'], 'application/vnd.cups-ppd' => ['ppd'], 'application/vnd.curl.car' => ['car'], 'application/vnd.curl.pcurl' => ['pcurl'], 'application/vnd.dart' => ['dart'], 'application/vnd.data-vision.rdz' => ['rdz'], 'application/vnd.dbf' => ['dbf'], 'application/vnd.dcmp+xml' => ['dcmp'], 'application/vnd.dece.data' => ['uvf', 'uvvf', 'uvd', 'uvvd'], 'application/vnd.dece.ttml+xml' => ['uvt', 'uvvt'], 'application/vnd.dece.unspecified' => ['uvx', 'uvvx'], 'application/vnd.dece.zip' => ['uvz', 'uvvz'], 'application/vnd.denovo.fcselayout-link' => ['fe_launch'], 'application/vnd.dna' => ['dna'], 'application/vnd.dolby.mlp' => ['mlp'], 'application/vnd.dpgraph' => ['dpg'], 'application/vnd.dreamfactory' => ['dfac'], 'application/vnd.ds-keypoint' => ['kpxx'], 'application/vnd.dvb.ait' => ['ait'], 'application/vnd.dvb.service' => ['svc'], 'application/vnd.dynageo' => ['geo'], 'application/vnd.ecowin.chart' => ['mag'], 'application/vnd.enliven' => ['nml'], 'application/vnd.epson.esf' => ['esf'], 'application/vnd.epson.msf' => ['msf'], 'application/vnd.epson.quickanime' => ['qam'], 'application/vnd.epson.salt' => ['slt'], 'application/vnd.epson.ssf' => ['ssf'], 'application/vnd.eszigno3+xml' => ['es3', 'et3'], 'application/vnd.ezpix-album' => ['ez2'], 'application/vnd.ezpix-package' => ['ez3'], 'application/vnd.fdf' => ['fdf'], 'application/vnd.fdsn.mseed' => ['mseed'], 'application/vnd.fdsn.seed' => ['seed', 'dataless'], 'application/vnd.flographit' => ['gph'], 'application/vnd.fluxtime.clip' => ['ftc'], 'application/vnd.framemaker' => ['fm', 'frame', 'maker', 'book'], 'application/vnd.frogans.fnc' => ['fnc'], 'application/vnd.frogans.ltf' => ['ltf'], 'application/vnd.fsc.weblaunch' => ['fsc'], 'application/vnd.fujitsu.oasys' => ['oas'], 'application/vnd.fujitsu.oasys2' => ['oa2'], 'application/vnd.fujitsu.oasys3' => ['oa3'], 'application/vnd.fujitsu.oasysgp' => ['fg5'], 'application/vnd.fujitsu.oasysprs' => ['bh2'], 'application/vnd.fujixerox.ddd' => ['ddd'], 'application/vnd.fujixerox.docuworks' => ['xdw'], 'application/vnd.fujixerox.docuworks.binder' => ['xbd'], 'application/vnd.fuzzysheet' => ['fzs'], 'application/vnd.genomatix.tuxedo' => ['txd'], 'application/vnd.geogebra.file' => ['ggb'], 'application/vnd.geogebra.slides' => ['ggs'], 'application/vnd.geogebra.tool' => ['ggt'], 'application/vnd.geometry-explorer' => ['gex', 'gre'], 'application/vnd.geonext' => ['gxt'], 'application/vnd.geoplan' => ['g2w'], 'application/vnd.geospace' => ['g3w'], 'application/vnd.gmx' => ['gmx'], 'application/vnd.google-apps.document' => ['gdoc'], 'application/vnd.google-apps.drawing' => ['gdraw'], 'application/vnd.google-apps.form' => ['gform'], 'application/vnd.google-apps.jam' => ['gjam'], 'application/vnd.google-apps.map' => ['gmap'], 'application/vnd.google-apps.presentation' => ['gslides'], 'application/vnd.google-apps.script' => ['gscript'], 'application/vnd.google-apps.site' => ['gsite'], 'application/vnd.google-apps.spreadsheet' => ['gsheet'], 'application/vnd.google-earth.kml+xml' => ['kml'], 'application/vnd.google-earth.kmz' => ['kmz'], 'application/vnd.gov.sk.xmldatacontainer+xml' => ['xdcf'], 'application/vnd.grafeq' => ['gqf', 'gqs'], 'application/vnd.groove-account' => ['gac'], 'application/vnd.groove-help' => ['ghf'], 'application/vnd.groove-identity-message' => ['gim'], 'application/vnd.groove-injector' => ['grv'], 'application/vnd.groove-tool-message' => ['gtm'], 'application/vnd.groove-tool-template' => ['tpl'], 'application/vnd.groove-vcard' => ['vcg'], 'application/vnd.hal+xml' => ['hal'], 'application/vnd.handheld-entertainment+xml' => ['zmm'], 'application/vnd.hbci' => ['hbci'], 'application/vnd.hhe.lesson-player' => ['les'], 'application/vnd.hp-hpgl' => ['hpgl'], 'application/vnd.hp-hpid' => ['hpid'], 'application/vnd.hp-hps' => ['hps'], 'application/vnd.hp-jlyt' => ['jlt'], 'application/vnd.hp-pcl' => ['pcl'], 'application/vnd.hp-pclxl' => ['pclxl'], 'application/vnd.hydrostatix.sof-data' => ['sfd-hdstx'], 'application/vnd.ibm.minipay' => ['mpy'], 'application/vnd.ibm.modcap' => ['afp', 'listafp', 'list3820'], 'application/vnd.ibm.rights-management' => ['irm'], 'application/vnd.ibm.secure-container' => ['sc'], 'application/vnd.iccprofile' => ['icc', 'icm'], 'application/vnd.igloader' => ['igl'], 'application/vnd.immervision-ivp' => ['ivp'], 'application/vnd.immervision-ivu' => ['ivu'], 'application/vnd.insors.igm' => ['igm'], 'application/vnd.intercon.formnet' => ['xpw', 'xpx'], 'application/vnd.intergeo' => ['i2g'], 'application/vnd.intu.qbo' => ['qbo'], 'application/vnd.intu.qfx' => ['qfx'], 'application/vnd.ipunplugged.rcprofile' => ['rcprofile'], 'application/vnd.irepository.package+xml' => ['irp'], 'application/vnd.is-xpr' => ['xpr'], 'application/vnd.isac.fcs' => ['fcs'], 'application/vnd.jam' => ['jam'], 'application/vnd.jcp.javame.midlet-rms' => ['rms'], 'application/vnd.jisp' => ['jisp'], 'application/vnd.joost.joda-archive' => ['joda'], 'application/vnd.kahootz' => ['ktz', 'ktr'], 'application/vnd.kde.karbon' => ['karbon'], 'application/vnd.kde.kchart' => ['chrt'], 'application/vnd.kde.kformula' => ['kfo'], 'application/vnd.kde.kivio' => ['flw'], 'application/vnd.kde.kontour' => ['kon'], 'application/vnd.kde.kpresenter' => ['kpr', 'kpt'], 'application/vnd.kde.kspread' => ['ksp'], 'application/vnd.kde.kword' => ['kwd', 'kwt'], 'application/vnd.kenameaapp' => ['htke'], 'application/vnd.kidspiration' => ['kia'], 'application/vnd.kinar' => ['kne', 'knp'], 'application/vnd.koan' => ['skp', 'skd', 'skt', 'skm'], 'application/vnd.kodak-descriptor' => ['sse'], 'application/vnd.las.las+xml' => ['lasxml'], 'application/vnd.llamagraphics.life-balance.desktop' => ['lbd'], 'application/vnd.llamagraphics.life-balance.exchange+xml' => ['lbe'], 'application/vnd.lotus-1-2-3' => ['123'], 'application/vnd.lotus-approach' => ['apr'], 'application/vnd.lotus-freelance' => ['pre'], 'application/vnd.lotus-notes' => ['nsf'], 'application/vnd.lotus-organizer' => ['org'], 'application/vnd.lotus-screencam' => ['scm'], 'application/vnd.lotus-wordpro' => ['lwp'], 'application/vnd.macports.portpkg' => ['portpkg'], 'application/vnd.mapbox-vector-tile' => ['mvt'], 'application/vnd.mcd' => ['mcd'], 'application/vnd.medcalcdata' => ['mc1'], 'application/vnd.mediastation.cdkey' => ['cdkey'], 'application/vnd.mfer' => ['mwf'], 'application/vnd.mfmp' => ['mfm'], 'application/vnd.micrografx.flo' => ['flo'], 'application/vnd.micrografx.igx' => ['igx'], 'application/vnd.mif' => ['mif'], 'application/vnd.mobius.daf' => ['daf'], 'application/vnd.mobius.dis' => ['dis'], 'application/vnd.mobius.mbk' => ['mbk'], 'application/vnd.mobius.mqy' => ['mqy'], 'application/vnd.mobius.msl' => ['msl'], 'application/vnd.mobius.plc' => ['plc'], 'application/vnd.mobius.txf' => ['txf'], 'application/vnd.mophun.application' => ['mpn'], 'application/vnd.mophun.certificate' => ['mpc'], 'application/vnd.mozilla.xul+xml' => ['xul'], 'application/vnd.ms-artgalry' => ['cil'], 'application/vnd.ms-cab-compressed' => ['cab'], 'application/vnd.ms-excel' => ['xls', 'xlm', 'xla', 'xlc', 'xlt', 'xlw'], 'application/vnd.ms-excel.addin.macroenabled.12' => ['xlam'], 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => ['xlsb'], 'application/vnd.ms-excel.sheet.macroenabled.12' => ['xlsm'], 'application/vnd.ms-excel.template.macroenabled.12' => ['xltm'], 'application/vnd.ms-fontobject' => ['eot'], 'application/vnd.ms-htmlhelp' => ['chm'], 'application/vnd.ms-ims' => ['ims'], 'application/vnd.ms-lrm' => ['lrm'], 'application/vnd.ms-officetheme' => ['thmx'], 'application/vnd.ms-outlook' => ['msg'], 'application/vnd.ms-pki.seccat' => ['cat'], 'application/vnd.ms-pki.stl' => ['stl'], 'application/vnd.ms-powerpoint' => ['ppt', 'pps', 'pot', 'ppa'], 'application/vnd.ms-powerpoint.addin.macroenabled.12' => ['ppam'], 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => ['pptm'], 'application/vnd.ms-powerpoint.slide.macroenabled.12' => ['sldm'], 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => ['ppsm'], 'application/vnd.ms-powerpoint.template.macroenabled.12' => ['potm'], 'application/vnd.ms-project' => ['mpp', 'mpt'], 'application/vnd.ms-visio.viewer' => ['vdx'], 'application/vnd.ms-word.document.macroenabled.12' => ['docm'], 'application/vnd.ms-word.template.macroenabled.12' => ['dotm'], 'application/vnd.ms-works' => ['wps', 'wks', 'wcm', 'wdb'], 'application/vnd.ms-wpl' => ['wpl'], 'application/vnd.ms-xpsdocument' => ['xps'], 'application/vnd.mseq' => ['mseq'], 'application/vnd.musician' => ['mus'], 'application/vnd.muvee.style' => ['msty'], 'application/vnd.mynfc' => ['taglet'], 'application/vnd.nato.bindingdataobject+xml' => ['bdo'], 'application/vnd.neurolanguage.nlu' => ['nlu'], 'application/vnd.nitf' => ['ntf', 'nitf'], 'application/vnd.noblenet-directory' => ['nnd'], 'application/vnd.noblenet-sealer' => ['nns'], 'application/vnd.noblenet-web' => ['nnw'], 'application/vnd.nokia.n-gage.ac+xml' => ['ac'], 'application/vnd.nokia.n-gage.data' => ['ngdat'], 'application/vnd.nokia.n-gage.symbian.install' => ['n-gage'], 'application/vnd.nokia.radio-preset' => ['rpst'], 'application/vnd.nokia.radio-presets' => ['rpss'], 'application/vnd.novadigm.edm' => ['edm'], 'application/vnd.novadigm.edx' => ['edx'], 'application/vnd.novadigm.ext' => ['ext'], 'application/vnd.oasis.opendocument.chart' => ['odc'], 'application/vnd.oasis.opendocument.chart-template' => ['otc'], 'application/vnd.oasis.opendocument.database' => ['odb'], 'application/vnd.oasis.opendocument.formula' => ['odf'], 'application/vnd.oasis.opendocument.formula-template' => ['odft'], 'application/vnd.oasis.opendocument.graphics' => ['odg'], 'application/vnd.oasis.opendocument.graphics-template' => ['otg'], 'application/vnd.oasis.opendocument.image' => ['odi'], 'application/vnd.oasis.opendocument.image-template' => ['oti'], 'application/vnd.oasis.opendocument.presentation' => ['odp'], 'application/vnd.oasis.opendocument.presentation-template' => ['otp'], 'application/vnd.oasis.opendocument.spreadsheet' => ['ods'], 'application/vnd.oasis.opendocument.spreadsheet-template' => ['ots'], 'application/vnd.oasis.opendocument.text' => ['odt'], 'application/vnd.oasis.opendocument.text-master' => ['odm'], 'application/vnd.oasis.opendocument.text-template' => ['ott'], 'application/vnd.oasis.opendocument.text-web' => ['oth'], 'application/vnd.olpc-sugar' => ['xo'], 'application/vnd.oma.dd2+xml' => ['dd2'], 'application/vnd.openblox.game+xml' => ['obgx'], 'application/vnd.openofficeorg.extension' => ['oxt'], 'application/vnd.openstreetmap.data+xml' => ['osm'], 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => ['pptx'], 'application/vnd.openxmlformats-officedocument.presentationml.slide' => ['sldx'], 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => ['ppsx'], 'application/vnd.openxmlformats-officedocument.presentationml.template' => ['potx'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['xlsx'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => ['xltx'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => ['dotx'], 'application/vnd.osgeo.mapguide.package' => ['mgp'], 'application/vnd.osgi.dp' => ['dp'], 'application/vnd.osgi.subsystem' => ['esa'], 'application/vnd.palm' => ['pdb', 'pqa', 'oprc'], 'application/vnd.pawaafile' => ['paw'], 'application/vnd.pg.format' => ['str'], 'application/vnd.pg.osasli' => ['ei6'], 'application/vnd.picsel' => ['efif'], 'application/vnd.pmi.widget' => ['wg'], 'application/vnd.pocketlearn' => ['plf'], 'application/vnd.powerbuilder6' => ['pbd'], 'application/vnd.pp.systemverify+xml' => ['systemverify'], 'application/vnd.previewsystems.box' => ['box'], 'application/vnd.procreate.brush' => ['brush'], 'application/vnd.procreate.brushset' => ['brushset'], 'application/vnd.procreate.dream' => ['drm'], 'application/vnd.proteus.magazine' => ['mgz'], 'application/vnd.publishare-delta-tree' => ['qps'], 'application/vnd.pvi.ptid1' => ['ptid'], 'application/vnd.pwg-xhtml-print+xml' => ['xhtm'], 'application/vnd.quark.quarkxpress' => ['qxd', 'qxt', 'qwd', 'qwt', 'qxl', 'qxb'], 'application/vnd.rar' => ['rar'], 'application/vnd.realvnc.bed' => ['bed'], 'application/vnd.recordare.musicxml' => ['mxl'], 'application/vnd.recordare.musicxml+xml' => ['musicxml'], 'application/vnd.rig.cryptonote' => ['cryptonote'], 'application/vnd.rim.cod' => ['cod'], 'application/vnd.rn-realmedia' => ['rm'], 'application/vnd.rn-realmedia-vbr' => ['rmvb'], 'application/vnd.route66.link66+xml' => ['link66'], 'application/vnd.sailingtracker.track' => ['st'], 'application/vnd.seemail' => ['see'], 'application/vnd.sema' => ['sema'], 'application/vnd.semd' => ['semd'], 'application/vnd.semf' => ['semf'], 'application/vnd.shana.informed.formdata' => ['ifm'], 'application/vnd.shana.informed.formtemplate' => ['itp'], 'application/vnd.shana.informed.interchange' => ['iif'], 'application/vnd.shana.informed.package' => ['ipk'], 'application/vnd.simtech-mindmapper' => ['twd', 'twds'], 'application/vnd.smaf' => ['mmf'], 'application/vnd.smart.teacher' => ['teacher'], 'application/vnd.software602.filler.form+xml' => ['fo'], 'application/vnd.solent.sdkm+xml' => ['sdkm', 'sdkd'], 'application/vnd.spotfire.dxp' => ['dxp'], 'application/vnd.spotfire.sfs' => ['sfs'], 'application/vnd.sqlite3' => ['sqlite', 'sqlite3'], 'application/vnd.stardivision.calc' => ['sdc'], 'application/vnd.stardivision.draw' => ['sda'], 'application/vnd.stardivision.impress' => ['sdd'], 'application/vnd.stardivision.math' => ['smf'], 'application/vnd.stardivision.writer' => ['sdw', 'vor'], 'application/vnd.stardivision.writer-global' => ['sgl'], 'application/vnd.stepmania.package' => ['smzip'], 'application/vnd.stepmania.stepchart' => ['sm'], 'application/vnd.sun.wadl+xml' => ['wadl'], 'application/vnd.sun.xml.calc' => ['sxc'], 'application/vnd.sun.xml.calc.template' => ['stc'], 'application/vnd.sun.xml.draw' => ['sxd'], 'application/vnd.sun.xml.draw.template' => ['std'], 'application/vnd.sun.xml.impress' => ['sxi'], 'application/vnd.sun.xml.impress.template' => ['sti'], 'application/vnd.sun.xml.math' => ['sxm'], 'application/vnd.sun.xml.writer' => ['sxw'], 'application/vnd.sun.xml.writer.global' => ['sxg'], 'application/vnd.sun.xml.writer.template' => ['stw'], 'application/vnd.sus-calendar' => ['sus', 'susp'], 'application/vnd.svd' => ['svd'], 'application/vnd.symbian.install' => ['sis', 'sisx'], 'application/vnd.syncml+xml' => ['xsm'], 'application/vnd.syncml.dm+wbxml' => ['bdm'], 'application/vnd.syncml.dm+xml' => ['xdm'], 'application/vnd.syncml.dmddf+xml' => ['ddf'], 'application/vnd.tao.intent-module-archive' => ['tao'], 'application/vnd.tcpdump.pcap' => ['pcap', 'cap', 'dmp'], 'application/vnd.tmobile-livetv' => ['tmo'], 'application/vnd.trid.tpt' => ['tpt'], 'application/vnd.triscape.mxs' => ['mxs'], 'application/vnd.trueapp' => ['tra'], 'application/vnd.ufdl' => ['ufd', 'ufdl'], 'application/vnd.uiq.theme' => ['utz'], 'application/vnd.umajin' => ['umj'], 'application/vnd.unity' => ['unityweb'], 'application/vnd.uoml+xml' => ['uoml', 'uo'], 'application/vnd.vcx' => ['vcx'], 'application/vnd.visio' => ['vsd', 'vst', 'vss', 'vsw', 'vsdx', 'vtx'], 'application/vnd.visionary' => ['vis'], 'application/vnd.vsf' => ['vsf'], 'application/vnd.wap.wbxml' => ['wbxml'], 'application/vnd.wap.wmlc' => ['wmlc'], 'application/vnd.wap.wmlscriptc' => ['wmlsc'], 'application/vnd.webturbo' => ['wtb'], 'application/vnd.wolfram.player' => ['nbp'], 'application/vnd.wordperfect' => ['wpd'], 'application/vnd.wqd' => ['wqd'], 'application/vnd.wt.stf' => ['stf'], 'application/vnd.xara' => ['xar'], 'application/vnd.xfdl' => ['xfdl'], 'application/vnd.yamaha.hv-dic' => ['hvd'], 'application/vnd.yamaha.hv-script' => ['hvs'], 'application/vnd.yamaha.hv-voice' => ['hvp'], 'application/vnd.yamaha.openscoreformat' => ['osf'], 'application/vnd.yamaha.openscoreformat.osfpvg+xml' => ['osfpvg'], 'application/vnd.yamaha.smaf-audio' => ['saf'], 'application/vnd.yamaha.smaf-phrase' => ['spf'], 'application/vnd.yellowriver-custom-menu' => ['cmp'], 'application/vnd.zul' => ['zir', 'zirz'], 'application/vnd.zzazz.deck+xml' => ['zaz'], 'application/voicexml+xml' => ['vxml'], 'application/wasm' => ['wasm'], 'application/watcherinfo+xml' => ['wif'], 'application/widget' => ['wgt'], 'application/winhlp' => ['hlp'], 'application/wsdl+xml' => ['wsdl'], 'application/wspolicy+xml' => ['wspolicy'], 'application/x-7z-compressed' => ['7z', '7zip'], 'application/x-abiword' => ['abw'], 'application/x-ace-compressed' => ['ace'], 'application/x-apple-diskimage' => ['dmg'], 'application/x-arj' => ['arj'], 'application/x-authorware-bin' => ['aab', 'x32', 'u32', 'vox'], 'application/x-authorware-map' => ['aam'], 'application/x-authorware-seg' => ['aas'], 'application/x-bcpio' => ['bcpio'], 'application/x-bdoc' => ['bdoc'], 'application/x-bittorrent' => ['torrent'], 'application/x-blender' => ['blend'], 'application/x-blorb' => ['blb', 'blorb'], 'application/x-bzip' => ['bz'], 'application/x-bzip2' => ['bz2', 'boz'], 'application/x-cbr' => ['cbr', 'cba', 'cbt', 'cbz', 'cb7'], 'application/x-cdlink' => ['vcd'], 'application/x-cfs-compressed' => ['cfs'], 'application/x-chat' => ['chat'], 'application/x-chess-pgn' => ['pgn'], 'application/x-chrome-extension' => ['crx'], 'application/x-cocoa' => ['cco'], 'application/x-compressed' => ['rar'], 'application/x-conference' => ['nsc'], 'application/x-cpio' => ['cpio'], 'application/x-csh' => ['csh'], 'application/x-debian-package' => ['deb', 'udeb'], 'application/x-dgc-compressed' => ['dgc'], 'application/x-director' => ['dir', 'dcr', 'dxr', 'cst', 'cct', 'cxt', 'w3d', 'fgd', 'swa'], 'application/x-doom' => ['wad'], 'application/x-dtbncx+xml' => ['ncx'], 'application/x-dtbook+xml' => ['dtb'], 'application/x-dtbresource+xml' => ['res'], 'application/x-dvi' => ['dvi'], 'application/x-envoy' => ['evy'], 'application/x-eva' => ['eva'], 'application/x-font-bdf' => ['bdf'], 'application/x-font-ghostscript' => ['gsf'], 'application/x-font-linux-psf' => ['psf'], 'application/x-font-pcf' => ['pcf'], 'application/x-font-snf' => ['snf'], 'application/x-font-type1' => ['pfa', 'pfb', 'pfm', 'afm'], 'application/x-freearc' => ['arc'], 'application/x-futuresplash' => ['spl'], 'application/x-gca-compressed' => ['gca'], 'application/x-glulx' => ['ulx'], 'application/x-gnumeric' => ['gnumeric'], 'application/x-gramps-xml' => ['gramps'], 'application/x-gtar' => ['gtar'], 'application/x-hdf' => ['hdf'], 'application/x-httpd-php' => ['php', 'php4', 'php3', 'phtml'], 'application/x-install-instructions' => ['install'], 'application/x-ipynb+json' => ['ipynb'], 'application/x-iso9660-image' => ['iso'], 'application/x-iwork-keynote-sffkey' => ['key'], 'application/x-iwork-numbers-sffnumbers' => ['numbers'], 'application/x-iwork-pages-sffpages' => ['pages'], 'application/x-java-archive-diff' => ['jardiff'], 'application/x-java-jnlp-file' => ['jnlp'], 'application/x-keepass2' => ['kdbx'], 'application/x-latex' => ['latex'], 'application/x-lua-bytecode' => ['luac'], 'application/x-lzh-compressed' => ['lzh', 'lha'], 'application/x-makeself' => ['run'], 'application/x-mie' => ['mie'], 'application/x-mobipocket-ebook' => ['prc', 'mobi'], 'application/x-ms-application' => ['application'], 'application/x-ms-shortcut' => ['lnk'], 'application/x-ms-wmd' => ['wmd'], 'application/x-ms-wmz' => ['wmz'], 'application/x-ms-xbap' => ['xbap'], 'application/x-msaccess' => ['mdb'], 'application/x-msbinder' => ['obd'], 'application/x-mscardfile' => ['crd'], 'application/x-msclip' => ['clp'], 'application/x-msdos-program' => ['exe'], 'application/x-msdownload' => ['exe', 'dll', 'com', 'bat', 'msi'], 'application/x-msmediaview' => ['mvb', 'm13', 'm14'], 'application/x-msmetafile' => ['wmf', 'wmz', 'emf', 'emz'], 'application/x-msmoney' => ['mny'], 'application/x-mspublisher' => ['pub'], 'application/x-msschedule' => ['scd'], 'application/x-msterminal' => ['trm'], 'application/x-mswrite' => ['wri'], 'application/x-netcdf' => ['nc', 'cdf'], 'application/x-ns-proxy-autoconfig' => ['pac'], 'application/x-nzb' => ['nzb'], 'application/x-perl' => ['pl', 'pm'], 'application/x-pilot' => ['prc', 'pdb'], 'application/x-pkcs12' => ['p12', 'pfx'], 'application/x-pkcs7-certificates' => ['p7b', 'spc'], 'application/x-pkcs7-certreqresp' => ['p7r'], 'application/x-rar-compressed' => ['rar'], 'application/x-redhat-package-manager' => ['rpm'], 'application/x-research-info-systems' => ['ris'], 'application/x-sea' => ['sea'], 'application/x-sh' => ['sh'], 'application/x-shar' => ['shar'], 'application/x-shockwave-flash' => ['swf'], 'application/x-silverlight-app' => ['xap'], 'application/x-sql' => ['sql'], 'application/x-stuffit' => ['sit'], 'application/x-stuffitx' => ['sitx'], 'application/x-subrip' => ['srt'], 'application/x-sv4cpio' => ['sv4cpio'], 'application/x-sv4crc' => ['sv4crc'], 'application/x-t3vm-image' => ['t3'], 'application/x-tads' => ['gam'], 'application/x-tar' => ['tar', 'tgz'], 'application/x-tcl' => ['tcl', 'tk'], 'application/x-tex' => ['tex'], 'application/x-tex-tfm' => ['tfm'], 'application/x-texinfo' => ['texinfo', 'texi'], 'application/x-tgif' => ['obj'], 'application/x-ustar' => ['ustar'], 'application/x-virtualbox-hdd' => ['hdd'], 'application/x-virtualbox-ova' => ['ova'], 'application/x-virtualbox-ovf' => ['ovf'], 'application/x-virtualbox-vbox' => ['vbox'], 'application/x-virtualbox-vbox-extpack' => ['vbox-extpack'], 'application/x-virtualbox-vdi' => ['vdi'], 'application/x-virtualbox-vhd' => ['vhd'], 'application/x-virtualbox-vmdk' => ['vmdk'], 'application/x-wais-source' => ['src'], 'application/x-web-app-manifest+json' => ['webapp'], 'application/x-x509-ca-cert' => ['der', 'crt', 'pem'], 'application/x-xfig' => ['fig'], 'application/x-xliff+xml' => ['xlf'], 'application/x-xpinstall' => ['xpi'], 'application/x-xz' => ['xz'], 'application/x-zip-compressed' => ['zip'], 'application/x-zmachine' => ['z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8'], 'application/xaml+xml' => ['xaml'], 'application/xcap-att+xml' => ['xav'], 'application/xcap-caps+xml' => ['xca'], 'application/xcap-diff+xml' => ['xdf'], 'application/xcap-el+xml' => ['xel'], 'application/xcap-ns+xml' => ['xns'], 'application/xenc+xml' => ['xenc'], 'application/xfdf' => ['xfdf'], 'application/xhtml+xml' => ['xhtml', 'xht'], 'application/xliff+xml' => ['xlf'], 'application/xml' => ['xml', 'xsl', 'xsd', 'rng'], 'application/xml-dtd' => ['dtd'], 'application/xop+xml' => ['xop'], 'application/xproc+xml' => ['xpl'], 'application/xslt+xml' => ['xsl', 'xslt'], 'application/xspf+xml' => ['xspf'], 'application/xv+xml' => ['mxml', 'xhvml', 'xvml', 'xvm'], 'application/yang' => ['yang'], 'application/yin+xml' => ['yin'], 'application/zip' => ['zip'], 'application/zip+dotlottie' => ['lottie'], 'audio/3gpp' => ['3gpp'], 'audio/aac' => ['adts', 'aac'], 'audio/adpcm' => ['adp'], 'audio/amr' => ['amr'], 'audio/basic' => ['au', 'snd'], 'audio/matroska' => ['mka'], 'audio/midi' => ['mid', 'midi', 'kar', 'rmi'], 'audio/mobile-xmf' => ['mxmf'], 'audio/mp3' => ['mp3'], 'audio/mp4' => ['m4a', 'mp4a', 'm4b'], 'audio/mpeg' => ['mpga', 'mp2', 'mp2a', 'mp3', 'm2a', 'm3a'], 'audio/ogg' => ['oga', 'ogg', 'spx', 'opus'], 'audio/s3m' => ['s3m'], 'audio/silk' => ['sil'], 'audio/vnd.dece.audio' => ['uva', 'uvva'], 'audio/vnd.digital-winds' => ['eol'], 'audio/vnd.dra' => ['dra'], 'audio/vnd.dts' => ['dts'], 'audio/vnd.dts.hd' => ['dtshd'], 'audio/vnd.lucent.voice' => ['lvp'], 'audio/vnd.ms-playready.media.pya' => ['pya'], 'audio/vnd.nuera.ecelp4800' => ['ecelp4800'], 'audio/vnd.nuera.ecelp7470' => ['ecelp7470'], 'audio/vnd.nuera.ecelp9600' => ['ecelp9600'], 'audio/vnd.rip' => ['rip'], 'audio/wav' => ['wav'], 'audio/wave' => ['wav'], 'audio/webm' => ['weba'], 'audio/x-aac' => ['aac'], 'audio/x-aiff' => ['aif', 'aiff', 'aifc'], 'audio/x-caf' => ['caf'], 'audio/x-flac' => ['flac'], 'audio/x-m4a' => ['m4a'], 'audio/x-matroska' => ['mka'], 'audio/x-mpegurl' => ['m3u'], 'audio/x-ms-wax' => ['wax'], 'audio/x-ms-wma' => ['wma'], 'audio/x-pn-realaudio' => ['ram', 'ra', 'rm'], 'audio/x-pn-realaudio-plugin' => ['rmp', 'rpm'], 'audio/x-realaudio' => ['ra'], 'audio/x-wav' => ['wav'], 'audio/xm' => ['xm'], 'chemical/x-cdx' => ['cdx'], 'chemical/x-cif' => ['cif'], 'chemical/x-cmdf' => ['cmdf'], 'chemical/x-cml' => ['cml'], 'chemical/x-csml' => ['csml'], 'chemical/x-xyz' => ['xyz'], 'font/collection' => ['ttc'], 'font/otf' => ['otf'], 'font/ttf' => ['ttf'], 'font/woff' => ['woff'], 'font/woff2' => ['woff2'], 'image/aces' => ['exr'], 'image/apng' => ['apng'], 'image/avci' => ['avci'], 'image/avcs' => ['avcs'], 'image/avif' => ['avif'], 'image/bmp' => ['bmp', 'dib'], 'image/cgm' => ['cgm'], 'image/dicom-rle' => ['drle'], 'image/dpx' => ['dpx'], 'image/emf' => ['emf'], 'image/fits' => ['fits'], 'image/g3fax' => ['g3'], 'image/gif' => ['gif'], 'image/heic' => ['heic'], 'image/heic-sequence' => ['heics'], 'image/heif' => ['heif'], 'image/heif-sequence' => ['heifs'], 'image/hej2k' => ['hej2'], 'image/ief' => ['ief'], 'image/jaii' => ['jaii'], 'image/jais' => ['jais'], 'image/jls' => ['jls'], 'image/jp2' => ['jp2', 'jpg2'], 'image/jpeg' => ['jpg', 'jpeg', 'jpe', 'jfif'], 'image/jph' => ['jph'], 'image/jphc' => ['jhc'], 'image/jpm' => ['jpm', 'jpgm'], 'image/jpx' => ['jpx', 'jpf'], 'image/jxl' => ['jxl'], 'image/jxr' => ['jxr'], 'image/jxra' => ['jxra'], 'image/jxrs' => ['jxrs'], 'image/jxs' => ['jxs'], 'image/jxsc' => ['jxsc'], 'image/jxsi' => ['jxsi'], 'image/jxss' => ['jxss'], 'image/ktx' => ['ktx'], 'image/ktx2' => ['ktx2'], 'image/pjpeg' => ['jfif'], 'image/png' => ['png'], 'image/prs.btif' => ['btif', 'btf'], 'image/prs.pti' => ['pti'], 'image/sgi' => ['sgi'], 'image/svg+xml' => ['svg', 'svgz'], 'image/t38' => ['t38'], 'image/tiff' => ['tif', 'tiff'], 'image/tiff-fx' => ['tfx'], 'image/vnd.adobe.photoshop' => ['psd'], 'image/vnd.airzip.accelerator.azv' => ['azv'], 'image/vnd.blockfact.facti' => ['facti'], 'image/vnd.dece.graphic' => ['uvi', 'uvvi', 'uvg', 'uvvg'], 'image/vnd.djvu' => ['djvu', 'djv'], 'image/vnd.dvb.subtitle' => ['sub'], 'image/vnd.dwg' => ['dwg'], 'image/vnd.dxf' => ['dxf'], 'image/vnd.fastbidsheet' => ['fbs'], 'image/vnd.fpx' => ['fpx'], 'image/vnd.fst' => ['fst'], 'image/vnd.fujixerox.edmics-mmr' => ['mmr'], 'image/vnd.fujixerox.edmics-rlc' => ['rlc'], 'image/vnd.microsoft.icon' => ['ico'], 'image/vnd.ms-dds' => ['dds'], 'image/vnd.ms-modi' => ['mdi'], 'image/vnd.ms-photo' => ['wdp'], 'image/vnd.net-fpx' => ['npx'], 'image/vnd.pco.b16' => ['b16'], 'image/vnd.tencent.tap' => ['tap'], 'image/vnd.valve.source.texture' => ['vtf'], 'image/vnd.wap.wbmp' => ['wbmp'], 'image/vnd.xiff' => ['xif'], 'image/vnd.zbrush.pcx' => ['pcx'], 'image/webp' => ['webp'], 'image/wmf' => ['wmf'], 'image/x-3ds' => ['3ds'], 'image/x-adobe-dng' => ['dng'], 'image/x-cmu-raster' => ['ras'], 'image/x-cmx' => ['cmx'], 'image/x-freehand' => ['fh', 'fhc', 'fh4', 'fh5', 'fh7'], 'image/x-icon' => ['ico'], 'image/x-jng' => ['jng'], 'image/x-mrsid-image' => ['sid'], 'image/x-ms-bmp' => ['bmp'], 'image/x-pcx' => ['pcx'], 'image/x-pict' => ['pic', 'pct'], 'image/x-portable-anymap' => ['pnm'], 'image/x-portable-bitmap' => ['pbm'], 'image/x-portable-graymap' => ['pgm'], 'image/x-portable-pixmap' => ['ppm'], 'image/x-rgb' => ['rgb'], 'image/x-tga' => ['tga'], 'image/x-xbitmap' => ['xbm'], 'image/x-xpixmap' => ['xpm'], 'image/x-xwindowdump' => ['xwd'], 'message/disposition-notification' => ['disposition-notification'], 'message/global' => ['u8msg'], 'message/global-delivery-status' => ['u8dsn'], 'message/global-disposition-notification' => ['u8mdn'], 'message/global-headers' => ['u8hdr'], 'message/rfc822' => ['eml', 'mime', 'mht', 'mhtml'], 'message/vnd.wfa.wsc' => ['wsc'], 'model/3mf' => ['3mf'], 'model/gltf+json' => ['gltf'], 'model/gltf-binary' => ['glb'], 'model/iges' => ['igs', 'iges'], 'model/jt' => ['jt'], 'model/mesh' => ['msh', 'mesh', 'silo'], 'model/mtl' => ['mtl'], 'model/obj' => ['obj'], 'model/prc' => ['prc'], 'model/step' => ['step', 'stp', 'stpnc', 'p21', '210'], 'model/step+xml' => ['stpx'], 'model/step+zip' => ['stpz'], 'model/step-xml+zip' => ['stpxz'], 'model/stl' => ['stl'], 'model/u3d' => ['u3d'], 'model/vnd.bary' => ['bary'], 'model/vnd.cld' => ['cld'], 'model/vnd.collada+xml' => ['dae'], 'model/vnd.dwf' => ['dwf'], 'model/vnd.gdl' => ['gdl'], 'model/vnd.gtw' => ['gtw'], 'model/vnd.mts' => ['mts'], 'model/vnd.opengex' => ['ogex'], 'model/vnd.parasolid.transmit.binary' => ['x_b'], 'model/vnd.parasolid.transmit.text' => ['x_t'], 'model/vnd.pytha.pyox' => ['pyo', 'pyox'], 'model/vnd.sap.vds' => ['vds'], 'model/vnd.usda' => ['usda'], 'model/vnd.usdz+zip' => ['usdz'], 'model/vnd.valve.source.compiled-map' => ['bsp'], 'model/vnd.vtu' => ['vtu'], 'model/vrml' => ['wrl', 'vrml'], 'model/x3d+binary' => ['x3db', 'x3dbz'], 'model/x3d+fastinfoset' => ['x3db'], 'model/x3d+vrml' => ['x3dv', 'x3dvz'], 'model/x3d+xml' => ['x3d', 'x3dz'], 'model/x3d-vrml' => ['x3dv'], 'text/cache-manifest' => ['appcache', 'manifest'], 'text/calendar' => ['ics', 'ifb'], 'text/coffeescript' => ['coffee', 'litcoffee'], 'text/css' => ['css'], 'text/csv' => ['csv'], 'text/html' => ['html', 'htm', 'shtml'], 'text/jade' => ['jade'], 'text/javascript' => ['js', 'mjs'], 'text/jsx' => ['jsx'], 'text/less' => ['less'], 'text/markdown' => ['md', 'markdown'], 'text/mathml' => ['mml'], 'text/mdx' => ['mdx'], 'text/n3' => ['n3'], 'text/plain' => ['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'ini', 'm3u'], 'text/prs.lines.tag' => ['dsc'], 'text/richtext' => ['rtx'], 'text/rtf' => ['rtf'], 'text/sgml' => ['sgml', 'sgm'], 'text/shex' => ['shex'], 'text/slim' => ['slim', 'slm'], 'text/spdx' => ['spdx'], 'text/stylus' => ['stylus', 'styl'], 'text/tab-separated-values' => ['tsv'], 'text/troff' => ['t', 'tr', 'roff', 'man', 'me', 'ms'], 'text/turtle' => ['ttl'], 'text/uri-list' => ['uri', 'uris', 'urls'], 'text/vcard' => ['vcard'], 'text/vnd.curl' => ['curl'], 'text/vnd.curl.dcurl' => ['dcurl'], 'text/vnd.curl.mcurl' => ['mcurl'], 'text/vnd.curl.scurl' => ['scurl'], 'text/vnd.dvb.subtitle' => ['sub'], 'text/vnd.familysearch.gedcom' => ['ged'], 'text/vnd.fly' => ['fly'], 'text/vnd.fmi.flexstor' => ['flx'], 'text/vnd.graphviz' => ['gv'], 'text/vnd.in3d.3dml' => ['3dml'], 'text/vnd.in3d.spot' => ['spot'], 'text/vnd.sun.j2me.app-descriptor' => ['jad'], 'text/vnd.wap.wml' => ['wml'], 'text/vnd.wap.wmlscript' => ['wmls'], 'text/vtt' => ['vtt'], 'text/wgsl' => ['wgsl'], 'text/x-asm' => ['s', 'asm'], 'text/x-c' => ['c', 'cc', 'cxx', 'cpp', 'h', 'hh', 'dic'], 'text/x-component' => ['htc'], 'text/x-fortran' => ['f', 'for', 'f77', 'f90'], 'text/x-handlebars-template' => ['hbs'], 'text/x-java-source' => ['java'], 'text/x-lua' => ['lua'], 'text/x-markdown' => ['mkd'], 'text/x-nfo' => ['nfo'], 'text/x-opml' => ['opml'], 'text/x-org' => ['org'], 'text/x-pascal' => ['p', 'pas'], 'text/x-php' => ['php'], 'text/x-processing' => ['pde'], 'text/x-sass' => ['sass'], 'text/x-scss' => ['scss'], 'text/x-setext' => ['etx'], 'text/x-sfv' => ['sfv'], 'text/x-suse-ymp' => ['ymp'], 'text/x-uuencode' => ['uu'], 'text/x-vcalendar' => ['vcs'], 'text/x-vcard' => ['vcf'], 'text/xml' => ['xml'], 'text/yaml' => ['yaml', 'yml'], 'video/3gpp' => ['3gp', '3gpp'], 'video/3gpp2' => ['3g2'], 'video/h261' => ['h261'], 'video/h263' => ['h263'], 'video/h264' => ['h264'], 'video/iso.segment' => ['m4s'], 'video/jpeg' => ['jpgv'], 'video/jpm' => ['jpm', 'jpgm'], 'video/matroska' => ['mkv'], 'video/matroska-3d' => ['mk3d'], 'video/mj2' => ['mj2', 'mjp2'], 'video/mp2t' => ['ts', 'm2t', 'm2ts', 'mts'], 'video/mp4' => ['mp4', 'mp4v', 'mpg4', 'f4v'], 'video/mpeg' => ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v'], 'video/ogg' => ['ogv'], 'video/quicktime' => ['qt', 'mov'], 'video/vnd.dece.hd' => ['uvh', 'uvvh'], 'video/vnd.dece.mobile' => ['uvm', 'uvvm'], 'video/vnd.dece.pd' => ['uvp', 'uvvp'], 'video/vnd.dece.sd' => ['uvs', 'uvvs'], 'video/vnd.dece.video' => ['uvv', 'uvvv'], 'video/vnd.dvb.file' => ['dvb'], 'video/vnd.fvt' => ['fvt'], 'video/vnd.mpegurl' => ['mxu', 'm4u'], 'video/vnd.ms-playready.media.pyv' => ['pyv'], 'video/vnd.uvvu.mp4' => ['uvu', 'uvvu'], 'video/vnd.vivo' => ['viv'], 'video/webm' => ['webm'], 'video/x-f4v' => ['f4v'], 'video/x-fli' => ['fli'], 'video/x-flv' => ['flv'], 'video/x-m4v' => ['m4v'], 'video/x-matroska' => ['mkv', 'mk3d', 'mks'], 'video/x-mng' => ['mng'], 'video/x-ms-asf' => ['asf', 'asx'], 'video/x-ms-vob' => ['vob'], 'video/x-ms-wm' => ['wm'], 'video/x-ms-wmv' => ['wmv'], 'video/x-ms-wmx' => ['wmx'], 'video/x-ms-wvx' => ['wvx'], 'video/x-msvideo' => ['avi'], 'video/x-sgi-movie' => ['movie'], 'video/x-smv' => ['smv'], 'x-conference/x-cooltalk' => ['ice'], 'application/x-photoshop' => ['psd'], 'application/x-indesign' => ['indd'], 'application/illustrator' => ['ai'], 'application/smil' => ['smi', 'smil'], 'application/powerpoint' => ['ppt'], 'application/vnd.ms-powerpoint.addin.macroEnabled.12' => ['ppam'], 'application/vnd.ms-powerpoint.presentation.macroEnabled.12' => ['pptm', 'potm'], 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' => ['ppsm'], 'application/wbxml' => ['wbxml'], 'application/wmlc' => ['wmlc'], 'application/x-httpd-php-source' => ['phps'], 'application/x-compress' => ['z'], 'application/x-rar' => ['rar'], 'video/vnd.rn-realvideo' => ['rv'], 'application/vnd.ms-word.template.macroEnabled.12' => ['docm', 'dotm'], 'application/vnd.ms-excel.sheet.macroEnabled.12' => ['xlsm'], 'application/vnd.ms-excel.template.macroEnabled.12' => ['xltm'], 'application/vnd.ms-excel.addin.macroEnabled.12' => ['xlam'], 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => ['xlsb'], 'application/excel' => ['xl'], 'application/x-x509-user-cert' => ['pem'], 'application/x-pkcs10' => ['p10'], 'application/x-pkcs7-signature' => ['p7a'], 'application/pgp' => ['pgp'], 'application/gpg-keys' => ['gpg'], 'application/x-pkcs7' => ['rsa'], 'video/3gp' => ['3gp'], 'audio/acc' => ['aac'], 'application/vnd.mpegurl' => ['m4u'], 'application/videolan' => ['vlc'], 'audio/x-au' => ['au'], 'audio/ac3' => ['ac3'], 'text/x-scriptzsh' => ['zsh'], 'application/cdr' => ['cdr'], 'application/STEP' => ['step', 'stp'], 'application/x-ndjson' => ['ndjson'], 'application/braille' => ['brf'], ]; public function lookupMimeType(string $extension): ?string { return self::MIME_TYPES_FOR_EXTENSIONS[$extension] ?? null; } public function lookupExtension(string $mimetype): ?string { return self::EXTENSIONS_FOR_MIME_TIMES[$mimetype][0] ?? null; } /** * @return string[] */ public function lookupAllExtensions(string $mimetype): array { return self::EXTENSIONS_FOR_MIME_TIMES[$mimetype] ?? []; } } $overrides */ public function __construct(ExtensionToMimeTypeMap $innerMap, array $overrides) { $this->innerMap = $innerMap; $this->overrides = $overrides; } public function lookupMimeType(string $extension): ?string { return $this->overrides[$extension] ?? $this->innerMap->lookupMimeType($extension); } } 1.6.12 (2024-08-29) ------------------- * Drop php 5 and 7.0 support as new versions enforced a syntax change that is not compatible with the old versions. 1.6.11 (2022-07-26) ------------------- * Add support for PHP 8.2's `$content` property in `vfsStreamWrapper` 1.6.10 (2021-09-25) ------------------- * Fix more deprecation warnings for PHP 8.1 support affecting the following: - `vfsStreamContainerIterator::current()` - `vfsStreamContainerIterator::next()` - `vfsStreamContainerIterator::key()` - `vfsStreamContainerIterator::rewind()` - `vfsStreamDirectory::getIterator()` - `vfsStreamPrintVisitor::printContent()` * Fix PHP 8.1 support in `vfsStreamPrintVisitor` 1.6.9 (2021-07-16) ------------------ * Fix deprecation warning on `StringBasedFileContent` for PHP 8.1 (#252) * Fix return type for `FileContent::write()` to fix static analysis tools 1.6.8 (2019-10-30) ------------------ * Fix `StringBasedFileContent::doRead` to always return a string (#204) 1.6.7 (2019-07-31) ------------------ * fix PHP 7.4 deprecation warnings (backported #189 from master) 1.6.6 (2019-04-08) ------------------ * backported #174 from master, original PR provided by @localheinz 1.6.5 (2017-08-01) ------------------ * fixed #157 seeking before beginning of file should fail, reported and fixed by @merijnvdk * structure array in `vfsStream::create()` and `vfsStream::setup()` now can contain instances of `org\bovigo\vfs\content\FileContent` and `org\bovigo\vfs\vfsStreamFile`, patch provivded by Joshua Smith (@jsmitty12) 1.6.4 (2016-07-18) ------------------ * fixed #134 type safe directory names, reported and fixed by Sebastian Hopfe 1.6.3 (2016-04-09) ------------------ * fixed #131 recursive mkdir() fails if the last dirname is '0' 1.6.2 (2016-01-13) ------------------ * fixed #128 duplicate "valid" files/directories and incorrect file names 1.6.1 (2015-12-04) ------------------ * `vfsStream::url()` didn't urlencode single path parts while `vfsStream::path()` did urldecode them * fixed #120, #122: create directory with trailing slash results in "Uninitialized string offset: 0" 1.6.0 (2015-10-06) ------------------ * added `vfsStreamWrapper::unregister()`, provided by @malkusch with #114 * fixed #115: incorrect handling of `..` in root directory on PHP 5.5, fix provided by @acoulton with #116 1.5.0 (2015-03-29) ------------------ * implemented #91: `vfsStream::copyFromFileSystem()` should create large file instances * implemented #92: `vfsStream::copyFromFileSystem()` should respect block devices * fixed #107: `touch()` does not respect file permissions * fixed #105: vfs directory structure is not reset after each test * fixed #104: vfsStream can't handle url encoded pathes 1.4.0 (2014-09-14) ------------------ * implemented #85: Added support for emulating block devices in the virtual filesystem, feature provided by Harris Borawski * fixed #68: Unlink a non-existing file now triggers a PHP warning 1.3.0 (2014-07-21) ------------------ * implemented #79: possibility to mock large files without large memory footprint, see https://github.com/mikey179/vfsStream/wiki/MockingLargeFiles * implemented #67: added partial support for text-mode translation flag (i.e., no actual translation of line endings takes place) so it no longer throws an exception (provided by Anthon Pang) * fixed issue #74: issue with trailing windows path separators (provided by Sebastian Krüger) * fixed issue #50: difference between real file system and vfs with `RecursiveDirectoryIterator` * fixed issue #80: touch with no arguments for modification and access time behave incorrect * deprecated `org\bovigo\vfs\vfsStreamFile::readUntilEnd()` * deprecated `org\bovigo\vfs\vfsStreamFile::getBytesRead()` 1.2.0 (2013-04-01) ------------------ * implemented issue #34: provide `url()` method on all `vfsStreamContent` instances * added `org\bovigo\vfs\vfsStreamContent::url()` * added `org\bovigo\vfs\vfsStreamContent::path()` * fixed issue #40: flock implementation doesn't work correctly, patch provided by Kamil Dziedzic * fixed issue #49: call to member function on a non-object when trying to delete a file one above root where a file with same name in root exists * fixed issue #51: `unlink()` must consider permissions of directory where file is inside, not of the file to unlink itself * fixed issue #52: `chmod()`, `chown()` and `chgrp()` must consider permissions of directory where file/directory is inside * fixed issue #53: `chmod()`, `chown()` and `chgrp()` must consider current user and current owner of file/directoy to change 1.1.0 (2012-08-25) ------------------ * implemented issue #11: add support for `streamWrapper::stream_metadata()` vfsStream now supports `touch()`, `chown()`, `chgrp()` and `chmod()` * implemented issue #33: add support for `stream_truncate()` (provided by https://github.com/nikcorg) * implemented issue #35: size limit (quota) for VFS 1.0.0 (2012-05-15) ------------------ * raised requirement for PHP version to 5.3.0 * migrated codebase to use namespaces * changed distribution from PEAR to Composer * implemented issue #30: support "c" mode for `fopen()` * fixed issue #31: prohibit aquiring locks when already locked / release lock on `fclose()` * fixed issue #32: problems when subfolder has same name as folder * fixed issue #36: `vfsStreamWrapper::stream_open()` should return false while trying to open existing non-writable file, patch provided by Alexander Peresypkin 0.11.2 (2012-01-14) ------------------- * fixed issue #29: set permissions properly when using `vfsStream::copyFromFileSystem()`, patch provided by predakanga * fixed failing tests under PHP > 5.3.2 0.11.1 (2011-12-04) ------------------- * fixed issue #28: `mkdir()` overwrites existing directories/files 0.11.0 (2011-11-29) ------------------- * implemented issue #20: `vfsStream::create()` removes old structure * implemented issue #4: possibility to copy structure from existing file system * fixed issue #23: `unlink()` should not remove any directory * fixed issue #25: `vfsStreamDirectory::hasChild()` gives false positives for nested paths, patch provided by Andrew Coulton * fixed issue #26: opening a file for reading only should not update its modification time, reported and initial patch provided by Ludovic Chabant 0.10.1 (2011-08-22) ------------------- * fixed issue #16: replace `vfsStreamContent` to `vfsStreamContainer` for autocompletion * fixed issue #17: `vfsStream::create()` has issues with numeric directories, patch provided by mathieuk 0.10.0 (2011-07-22) ------------------- * added new method `vfsStreamContainer::hasChildren()` and `vfsStreamDirectory::hasChildren()` * implemented issue #14: less verbose way to initialize vfsStream * implemented issue #13: remove deprecated method `vfsStreamContent::setFilemtime()` * implemented issue #6: locking meachanism for files * ensured that `stream_set_blocking()`, `stream_set_timeout()` and `stream_set_write_buffer()` on vfsStream urls have the same behaviour with PHP 5.2 and 5.3 * implemented issue #10: method to print directory structure 0.9.0 (2011-07-13) ------------------ * implemented feature request issue #7: add support for `fileatime()` and `filectime()` * fixed issue #3: add support for `streamWrapper::stream_cast()` * fixed issue #9: resolve path not called everywhere its needed * deprecated `vfsStreamAbstractContent::setFilemtime()`, use `vfsStreamAbstractContent::lastModified()` instead, will be removed with 0.10.0 0.8.0 (2010-10-08) ------------------ * implemented enhancement #6: use `vfsStream::umask()` to influence initial file mode for files and directories * implemented enhancement #19: support of .. in the url, patch provided by Guislain Duthieuw * fixed issue #18: `getChild()` returns NULL when child's name contains parent name * fixed bug with incomplete error message when accessing non-existing files on root level 0.7.0 (2010-06-08) ------------------ * added new `vfsStream::setup()` method to simplify vfsStream usage * fixed issue #15: `mkdir()` creates a subfolder in a folder without permissions 0.6.0 (2010-02-15) ------------------ * added support for `$mode` param when opening files, implements enhancement #7 and fixes issue #13 * `vfsStreamWrapper::stream_open()` now evaluates `$options` for `STREAM_REPORT_ERRORS` 0.5.0 (2010-01-25) ------------------ * added support for `rename()`, patch provided by Benoit Aubuchon * added support for . as directory alias so that `vfs://foo/.` resolves to `vfs://foo`, can be used as workaround for bug #8 0.4.0 (2009-07-13) ------------------ * added support for file modes, users and groups (with restrictions, see http://code.google.com/p/bovigo/wiki/vfsStreamDocsKnownIssues) * fixed bug #5: `vfsStreamDirectory::addChild()` does not replace child with same name * fixed bug with `is_writable()` because of missing `stat()` fields, patch provided by Sergey Galkin 0.3.2 (2009-02-16) ------------------ * support trailing slashes on directories in vfsStream urls, patch provided by Gabriel Birke * fixed bug #4: vfsstream can only be read once, reported by Christoph Bloemer * enabled multiple iterations at the same time over the same directory 0.3.1 (2008-02-18) ------------------ * fixed path/directory separator issues under linux systems * fixed uid/gid issues under linux systems 0.3.0 (2008-01-02) ------------------ * added support for `rmdir()` * added `vfsStream::newDirectory()`, dropped `vfsStreamDirectory::ceate()` * added new interface `vfsStreamContainer` * added `vfsStreamContent::at()` which allows code like `$file = vfsStream::newFile('file.txt.')->withContent('foo')->at($otherDir);` * added `vfsStreamContent::lastModified()`, made `vfsStreamContent::setFilemtime()` an alias for this * moved from Stubbles development environment to bovigo * refactorings to reduce crap index of various methods 0.2.0 (2007-12-29) ------------------ * moved `vfsStreamWrapper::PROTOCOL` to `vfsStream::SCHEME` * added new `vfsStream::url()` method to assist in creating correct vfsStream urls * added `vfsStream::path()` method as opposite to `vfsStream::url()` * a call to `vfsStreamWrapper::register()` will now reset the root to null, implemented on request from David Zuelke * added support for `is_readable()`, `is_dir()`, `is_file()` * added `vfsStream::newFile()` to be able to do `$file = vfsStream::newFile("foo.txt")->withContent("bar");` 0.1.0 (2007-12-14) ------------------ * Initial release. Copyright (c) 2007-2015, Frank Kleine 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 Stubbles 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 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. You can find documentation in the [wiki](https://github.com/mikey179/vfsStream/wiki). Also you might want to check [vfsStream examples](https://github.com/mikey179/vfsStream-examples). [![Build Status](https://secure.travis-ci.org/mikey179/vfsStream.png)](http://travis-ci.org/mikey179/vfsStream) [![Build Status Windows](https://ci.appveyor.com/api/projects/status/6whqgluyeggspjp1/branch/master?svg=true)](https://ci.appveyor.com/project/mikey179/vfsstream) [![Coverage Status](https://coveralls.io/repos/github/bovigo/vfsStream/badge.svg?branch=v1.x)](https://coveralls.io/github/bovigo/vfsStream?branch=v1.x) [![Latest Stable Version](https://poser.pugx.org/mikey179/vfsStream/version.png)](https://packagist.org/packages/mikey179/vfsStream) [![Latest Unstable Version](https://poser.pugx.org/mikey179/vfsStream/v/unstable.png)](//packagist.org/packages/mikey179/vfsStream) { "name": "mikey179/vfsstream", "type": "library", "homepage": "http://vfs.bovigo.org/", "description": "Virtual file system to mock the real file system in unit tests.", "license": "BSD-3-Clause", "authors": [ { "name": "Frank Kleine", "homepage": "http://frankkleine.de/", "role": "Developer" } ], "support": { "issues": "https://github.com/bovigo/vfsStream/issues", "source": "https://github.com/bovigo/vfsStream/tree/master", "wiki": "https://github.com/bovigo/vfsStream/wiki" }, "require": { "php": ">=7.1.0" }, "require-dev": { "phpunit/phpunit": "^7.5||^8.5||^9.6", "yoast/phpunit-polyfills": "^2.0" }, "autoload": { "psr-0": { "org\\bovigo\\vfs\\": "src/main/php" } }, "scripts": { "test": "phpunit" }, "extra": { "branch-alias": { "dev-master": "1.6.x-dev" } } } ./src/test/phpt ./src/test/php src/main/php amount = $amount; } /** * create with unlimited space * * @return Quota */ public static function unlimited() { return new self(self::UNLIMITED); } /** * checks if a quota is set * * @return bool */ public function isLimited() { return self::UNLIMITED < $this->amount; } /** * checks if given used space exceeda quota limit * * * @param int $usedSpace * @return int */ public function spaceLeft($usedSpace) { if (self::UNLIMITED === $this->amount) { return $usedSpace; } if ($usedSpace >= $this->amount) { return 0; } $spaceLeft = $this->amount - $usedSpace; if (0 >= $spaceLeft) { return 0; } return $spaceLeft; } } size = $size; } /** * create large file with given size in kilobyte * * @param int $kilobyte * @return LargeFileContent */ public static function withKilobytes($kilobyte) { return new self($kilobyte * 1024); } /** * create large file with given size in megabyte * * @param int $megabyte * @return LargeFileContent */ public static function withMegabytes($megabyte) { return self::withKilobytes($megabyte * 1024); } /** * create large file with given size in gigabyte * * @param int $gigabyte * @return LargeFileContent */ public static function withGigabytes($gigabyte) { return self::withMegabytes($gigabyte * 1024); } /** * returns actual content * * @return string */ public function content() { return $this->doRead(0, $this->size); } /** * returns size of content * * @return int */ public function size() { return $this->size; } /** * actual reading of given byte count starting at given offset * * @param int $offset * @param int $count */ protected function doRead($offset, $count) { if (($offset + $count) > $this->size) { $count = $this->size - $offset; } $result = ''; for ($i = 0; $i < $count; $i++) { if (isset($this->content[$i + $offset])) { $result .= $this->content[$i + $offset]; } else { $result .= ' '; } } return $result; } /** * actual writing of data with specified length at given offset * * @param string $data * @param int $offset * @param int $length */ protected function doWrite($data, $offset, $length) { for ($i = 0; $i < $length; $i++) { $this->content[$i + $offset] = substr($data, $i, 1); } if ($offset >= $this->size) { $this->size += $length; } elseif (($offset + $length) > $this->size) { $this->size = $offset + $length; } } /** * Truncates a file to a given length * * @param int $size length to truncate file to * @return bool */ public function truncate($size) { $this->size = $size; foreach (array_filter(array_keys($this->content), function($pos) use ($size) { return $pos >= $size; } ) as $removePos) { unset($this->content[$removePos]); } return true; } } doRead($this->offset, $count); $this->offset += $count; return $data; } /** * actual reading of given byte count starting at given offset * * @param int $offset * @param int $count */ protected abstract function doRead($offset, $count); /** * seeks to the given offset * * @param int $offset * @param int $whence * @return bool */ public function seek($offset, $whence) { $newOffset = $this->offset; switch ($whence) { case SEEK_CUR: $newOffset += $offset; break; case SEEK_END: $newOffset = $this->size() + $offset; break; case SEEK_SET: $newOffset = $offset; break; default: return false; } if ($newOffset<0) { return false; } $this->offset = $newOffset; return true; } /** * checks whether pointer is at end of file * * @return bool */ public function eof() { return $this->size() <= $this->offset; } /** * writes an amount of data * * @param string $data * @return int amount of written bytes */ public function write($data) { $dataLength = strlen($data); $this->doWrite($data, $this->offset, $dataLength); $this->offset += $dataLength; return $dataLength; } /** * actual writing of data with specified length at given offset * * @param string $data * @param int $offset * @param int $length */ protected abstract function doWrite($data, $offset, $length); /** * for backwards compatibility with vfsStreamFile::bytesRead() * * @return int * @deprecated */ public function bytesRead() { return $this->offset; } /** * for backwards compatibility with vfsStreamFile::readUntilEnd() * * @return string * @deprecated */ public function readUntilEnd() { return substr($this->content(), $this->offset); } } content = $content; } /** * returns actual content * * @return string */ public function content() { return $this->content; } /** * returns size of content * * @return int */ public function size() { return strlen($this->content); } /** * actual reading of length starting at given offset * * @param int $offset * @param int $count */ protected function doRead($offset, $count) { return (string) substr($this->content, $offset, $count); } /** * actual writing of data with specified length at given offset * * @param string $data * @param int $offset * @param int $length */ protected function doWrite($data, $offset, $length) { $this->content = substr($this->content, 0, $offset) . $data . substr($this->content, $offset + $length); } /** * Truncates a file to a given length * * @param int $size length to truncate file to * @return bool */ public function truncate($size) { if ($size > $this->size()) { // Pad with null-chars if we're "truncating up" $this->content .= str_repeat("\0", $size - $this->size()); } else { $this->content = substr($this->content, 0, $size); } return true; } } * array('Core' = array('AbstractFactory' => array('test.php' => 'some text content', * 'other.php' => 'Some more text content', * 'Invalid.csv' => 'Something else', * ), * 'AnEmptyFolder' => array(), * 'badlocation.php' => 'some bad content', * ) * ) * * the resulting directory tree will look like this: *
     * root
     * \- Core
     *  |- badlocation.php
     *  |- AbstractFactory
     *  | |- test.php
     *  | |- other.php
     *  | \- Invalid.csv
     *  \- AnEmptyFolder
     * 
* Arrays will become directories with their key as directory name, and * strings becomes files with their key as file name and their value as file * content. * * @param string $rootDirName name of root directory * @param int $permissions file permissions of root directory * @param array $structure directory structure to add under root directory * @return \org\bovigo\vfs\vfsStreamDirectory * @since 0.7.0 * @see https://github.com/mikey179/vfsStream/issues/14 * @see https://github.com/mikey179/vfsStream/issues/20 */ public static function setup($rootDirName = 'root', $permissions = null, array $structure = array()) { vfsStreamWrapper::register(); return self::create($structure, vfsStreamWrapper::setRoot(self::newDirectory($rootDirName, $permissions))); } /** * creates vfsStream directory structure from an array and adds it to given base dir * * Assumed $structure contains an array like this: * * array('Core' = array('AbstractFactory' => array('test.php' => 'some text content', * 'other.php' => 'Some more text content', * 'Invalid.csv' => 'Something else', * ), * 'AnEmptyFolder' => array(), * 'badlocation.php' => 'some bad content', * ) * ) * * the resulting directory tree will look like this: *
     * baseDir
     * \- Core
     *  |- badlocation.php
     *  |- AbstractFactory
     *  | |- test.php
     *  | |- other.php
     *  | \- Invalid.csv
     *  \- AnEmptyFolder
     * 
* Arrays will become directories with their key as directory name, and * strings becomes files with their key as file name and their value as file * content. * * If no baseDir is given it will try to add the structure to the existing * root directory without replacing existing childs except those with equal * names. * * @param array $structure directory structure to add under root directory * @param vfsStreamDirectory $baseDir base directory to add structure to * @return vfsStreamDirectory * @throws \InvalidArgumentException * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/14 * @see https://github.com/mikey179/vfsStream/issues/20 */ public static function create(array $structure, ?vfsStreamDirectory $baseDir = null) { if (null === $baseDir) { $baseDir = vfsStreamWrapper::getRoot(); } if (null === $baseDir) { throw new \InvalidArgumentException('No baseDir given and no root directory set.'); } return self::addStructure($structure, $baseDir); } /** * helper method to create subdirectories recursively * * @param array $structure subdirectory structure to add * @param vfsStreamDirectory $baseDir directory to add the structure to * @return vfsStreamDirectory */ protected static function addStructure(array $structure, vfsStreamDirectory $baseDir) { foreach ($structure as $name => $data) { $name = (string) $name; if (is_array($data) === true) { self::addStructure($data, self::newDirectory($name)->at($baseDir)); } elseif (is_string($data) === true) { $matches = null; preg_match('/^\[(.*)\]$/', $name, $matches); if ($matches !== array()) { self::newBlock($matches[1])->withContent($data)->at($baseDir); } else { self::newFile($name)->withContent($data)->at($baseDir); } } elseif ($data instanceof FileContent) { self::newFile($name)->withContent($data)->at($baseDir); } elseif ($data instanceof vfsStreamFile) { $baseDir->addChild($data); } } return $baseDir; } /** * copies the file system structure from given path into the base dir * * If no baseDir is given it will try to add the structure to the existing * root directory without replacing existing childs except those with equal * names. * File permissions are copied as well. * Please note that file contents will only be copied if their file size * does not exceed the given $maxFileSize which defaults to 1024 KB. In case * the file is larger file content will be mocked, see * https://github.com/mikey179/vfsStream/wiki/MockingLargeFiles. * * @param string $path path to copy the structure from * @param vfsStreamDirectory $baseDir directory to add the structure to * @param int $maxFileSize maximum file size of files to copy content from * @return vfsStreamDirectory * @throws \InvalidArgumentException * @since 0.11.0 * @see https://github.com/mikey179/vfsStream/issues/4 */ public static function copyFromFileSystem($path, ?vfsStreamDirectory $baseDir = null, $maxFileSize = 1048576) { if (null === $baseDir) { $baseDir = vfsStreamWrapper::getRoot(); } if (null === $baseDir) { throw new \InvalidArgumentException('No baseDir given and no root directory set.'); } $dir = new \DirectoryIterator($path); foreach ($dir as $fileinfo) { switch (filetype($fileinfo->getPathname())) { case 'file': if ($fileinfo->getSize() <= $maxFileSize) { $content = file_get_contents($fileinfo->getPathname()); } else { $content = new LargeFileContent($fileinfo->getSize()); } self::newFile( $fileinfo->getFilename(), octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4)) ) ->withContent($content) ->at($baseDir); break; case 'dir': if (!$fileinfo->isDot()) { self::copyFromFileSystem( $fileinfo->getPathname(), self::newDirectory( $fileinfo->getFilename(), octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4)) )->at($baseDir), $maxFileSize ); } break; case 'block': self::newBlock( $fileinfo->getFilename(), octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4)) )->at($baseDir); break; } } return $baseDir; } /** * returns a new file with given name * * @param string $name name of file to create * @param int $permissions permissions of file to create * @return vfsStreamFile */ public static function newFile($name, $permissions = null) { return new vfsStreamFile($name, $permissions); } /** * returns a new directory with given name * * If the name contains slashes, a new directory structure will be created. * The returned directory will always be the parent directory of this * directory structure. * * @param string $name name of directory to create * @param int $permissions permissions of directory to create * @return vfsStreamDirectory */ public static function newDirectory($name, $permissions = null) { if ('/' === substr($name, 0, 1)) { $name = substr($name, 1); } $firstSlash = strpos($name, '/'); if (false === $firstSlash) { return new vfsStreamDirectory($name, $permissions); } $ownName = substr($name, 0, $firstSlash); $subDirs = substr($name, $firstSlash + 1); $directory = new vfsStreamDirectory($ownName, $permissions); if (is_string($subDirs) && strlen($subDirs) > 0) { self::newDirectory($subDirs, $permissions)->at($directory); } return $directory; } /** * returns a new block with the given name * * @param string $name name of the block device * @param int $permissions permissions of block to create * @return vfsStreamBlock */ public static function newBlock($name, $permissions = null) { return new vfsStreamBlock($name, $permissions); } /** * returns current user * * If the system does not support posix_getuid() the current user will be root (0). * * @return int */ public static function getCurrentUser() { return function_exists('posix_getuid') ? posix_getuid() : self::OWNER_ROOT; } /** * returns current group * * If the system does not support posix_getgid() the current group will be root (0). * * @return int */ public static function getCurrentGroup() { return function_exists('posix_getgid') ? posix_getgid() : self::GROUP_ROOT; } /** * use visitor to inspect a content structure * * If the given content is null it will fall back to use the current root * directory of the stream wrapper. * * Returns given visitor for method chaining comfort. * * @param vfsStreamVisitor $visitor the visitor who inspects * @param vfsStreamContent $content directory structure to inspect * @return vfsStreamVisitor * @throws \InvalidArgumentException * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/10 */ public static function inspect(vfsStreamVisitor $visitor, ?vfsStreamContent $content = null) { if (null !== $content) { return $visitor->visit($content); } $root = vfsStreamWrapper::getRoot(); if (null === $root) { throw new \InvalidArgumentException('No content given and no root directory set.'); } return $visitor->visitDirectory($root); } /** * sets quota to given amount of bytes * * @param int $bytes * @since 1.1.0 */ public static function setQuota($bytes) { vfsStreamWrapper::setQuota(new Quota($bytes)); } /** * checks if vfsStream lists dotfiles in directory listings * * @return bool * @since 1.3.0 */ public static function useDotfiles() { return self::$dotFiles; } /** * disable dotfiles in directory listings * * @since 1.3.0 */ public static function disableDotfiles() { self::$dotFiles = false; } /** * enable dotfiles in directory listings * * @since 1.3.0 */ public static function enableDotfiles() { self::$dotFiles = true; } } name = "{$name}"; $time = time(); if (null === $permissions) { $permissions = $this->getDefaultPermissions() & ~vfsStream::umask(); } $this->lastAccessed = $time; $this->lastAttributeModified = $time; $this->lastModified = $time; $this->permissions = $permissions; $this->user = vfsStream::getCurrentUser(); $this->group = vfsStream::getCurrentGroup(); } /** * returns default permissions for concrete implementation * * @return int * @since 0.8.0 */ protected abstract function getDefaultPermissions(); /** * returns the file name of the content * * @return string */ public function getName() { return $this->name; } /** * renames the content * * @param string $newName */ public function rename($newName) { $this->name = "{$newName}"; } /** * checks whether the container can be applied to given name * * @param string $name * @return bool */ public function appliesTo($name) { if ($name === $this->name) { return true; } $segment_name = $this->name.'/'; return (strncmp($segment_name, $name, strlen($segment_name)) == 0); } /** * returns the type of the container * * @return int */ public function getType() { return $this->type; } /** * sets the last modification time of the stream content * * @param int $filemtime * @return $this */ public function lastModified($filemtime) { $this->lastModified = $filemtime; return $this; } /** * returns the last modification time of the stream content * * @return int */ public function filemtime() { return $this->lastModified; } /** * sets last access time of the stream content * * @param int $fileatime * @return $this * @since 0.9 */ public function lastAccessed($fileatime) { $this->lastAccessed = $fileatime; return $this; } /** * returns the last access time of the stream content * * @return int * @since 0.9 */ public function fileatime() { return $this->lastAccessed; } /** * sets the last attribute modification time of the stream content * * @param int $filectime * @return $this * @since 0.9 */ public function lastAttributeModified($filectime) { $this->lastAttributeModified = $filectime; return $this; } /** * returns the last attribute modification time of the stream content * * @return int * @since 0.9 */ public function filectime() { return $this->lastAttributeModified; } /** * adds content to given container * * @param vfsStreamContainer $container * @return $this */ public function at(vfsStreamContainer $container) { $container->addChild($this); return $this; } /** * change file mode to given permissions * * @param int $permissions * @return $this */ public function chmod($permissions) { $this->permissions = $permissions; $this->lastAttributeModified = time(); clearstatcache(); return $this; } /** * returns permissions * * @return int */ public function getPermissions() { return $this->permissions; } /** * checks whether content is readable * * @param int $user id of user to check for * @param int $group id of group to check for * @return bool */ public function isReadable($user, $group) { if ($this->user === $user) { $check = 0400; } elseif ($this->group === $group) { $check = 0040; } else { $check = 0004; } return (bool) ($this->permissions & $check); } /** * checks whether content is writable * * @param int $user id of user to check for * @param int $group id of group to check for * @return bool */ public function isWritable($user, $group) { if ($this->user === $user) { $check = 0200; } elseif ($this->group === $group) { $check = 0020; } else { $check = 0002; } return (bool) ($this->permissions & $check); } /** * checks whether content is executable * * @param int $user id of user to check for * @param int $group id of group to check for * @return bool */ public function isExecutable($user, $group) { if ($this->user === $user) { $check = 0100; } elseif ($this->group === $group) { $check = 0010; } else { $check = 0001; } return (bool) ($this->permissions & $check); } /** * change owner of file to given user * * @param int $user * @return $this */ public function chown($user) { $this->user = $user; $this->lastAttributeModified = time(); return $this; } /** * checks whether file is owned by given user * * @param int $user * @return bool */ public function isOwnedByUser($user) { return $this->user === $user; } /** * returns owner of file * * @return int */ public function getUser() { return $this->user; } /** * change owner group of file to given group * * @param int $group * @return $this */ public function chgrp($group) { $this->group = $group; $this->lastAttributeModified = time(); return $this; } /** * checks whether file is owned by group * * @param int $group * @return bool */ public function isOwnedByGroup($group) { return $this->group === $group; } /** * returns owner group of file * * @return int */ public function getGroup() { return $this->group; } /** * sets parent path * * @param string $parentPath * @internal only to be set by parent * @since 1.2.0 */ public function setParentPath($parentPath) { $this->parentPath = $parentPath; } /** * returns path to this content * * @return string * @since 1.2.0 */ public function path() { if (null === $this->parentPath) { return $this->name; } return $this->parentPath . '/' . $this->name; } /** * returns complete vfsStream url for this content * * @return string * @since 1.2.0 */ public function url() { return vfsStream::url($this->path()); } } type = vfsStreamContent::TYPE_BLOCK; } } children = $children; if (vfsStream::useDotfiles()) { array_unshift($this->children, new DotDirectory('.'), new DotDirectory('..')); } reset($this->children); } /** * resets children pointer */ #[\ReturnTypeWillChange] public function rewind() { reset($this->children); } /** * returns the current child * * @return vfsStreamContent */ #[\ReturnTypeWillChange] public function current() { $child = current($this->children); if (false === $child) { return null; } return $child; } /** * returns the name of the current child * * @return string */ #[\ReturnTypeWillChange] public function key() { $child = current($this->children); if (false === $child) { return null; } return $child->getName(); } /** * iterates to next child */ #[\ReturnTypeWillChange] public function next() { next($this->children); } /** * checks if the current value is valid * * @return bool */ #[\ReturnTypeWillChange] public function valid() { return (false !== current($this->children)); } } type = vfsStreamContent::TYPE_DIR; parent::__construct($name, $permissions); } /** * returns default permissions for concrete implementation * * @return int * @since 0.8.0 */ protected function getDefaultPermissions() { return 0777; } /** * returns size of directory * * The size of a directory is always 0 bytes. To calculate the summarized * size of all children in the directory use sizeSummarized(). * * @return int */ public function size() { return 0; } /** * returns summarized size of directory and its children * * @return int */ public function sizeSummarized() { $size = 0; foreach ($this->children as $child) { if ($child->getType() === vfsStreamContent::TYPE_DIR) { $size += $child->sizeSummarized(); } else { $size += $child->size(); } } return $size; } /** * renames the content * * @param string $newName * @throws vfsStreamException */ public function rename($newName) { if (strstr($newName, '/') !== false) { throw new vfsStreamException('Directory name can not contain /.'); } parent::rename($newName); } /** * sets parent path * * @param string $parentPath * @internal only to be set by parent * @since 1.2.0 */ public function setParentPath($parentPath) { parent::setParentPath($parentPath); foreach ($this->children as $child) { $child->setParentPath($this->path()); } } /** * adds child to the directory * * @param vfsStreamContent $child */ public function addChild(vfsStreamContent $child) { $child->setParentPath($this->path()); $this->children[$child->getName()] = $child; $this->updateModifications(); } /** * removes child from the directory * * @param string $name * @return bool */ public function removeChild($name) { foreach ($this->children as $key => $child) { if ($child->appliesTo($name)) { $child->setParentPath(null); unset($this->children[$key]); $this->updateModifications(); return true; } } return false; } /** * updates internal timestamps */ protected function updateModifications() { $time = time(); $this->lastAttributeModified = $time; $this->lastModified = $time; } /** * checks whether the container contains a child with the given name * * @param string $name * @return bool */ public function hasChild($name) { return ($this->getChild($name) !== null); } /** * returns the child with the given name * * @param string $name * @return vfsStreamContent */ public function getChild($name) { $childName = $this->getRealChildName($name); foreach ($this->children as $child) { if ($child->getName() === $childName) { return $child; } if ($child->appliesTo($childName) === true && $child->hasChild($childName) === true) { return $child->getChild($childName); } } return null; } /** * helper method to detect the real child name * * @param string $name * @return string */ protected function getRealChildName($name) { if ($this->appliesTo($name) === true) { return self::getChildName($name, $this->name); } return $name; } /** * helper method to calculate the child name * * @param string $name * @param string $ownName * @return string */ protected static function getChildName($name, $ownName) { if ($name === $ownName) { return $name; } return substr($name, strlen($ownName) + 1); } /** * checks whether directory contains any children * * @return bool * @since 0.10.0 */ public function hasChildren() { return (count($this->children) > 0); } /** * returns a list of children for this directory * * @return vfsStreamContent[] */ public function getChildren() { return array_values($this->children); } /** * returns iterator for the children * * @return vfsStreamContainerIterator */ #[\ReturnTypeWillChange] public function getIterator() { return new vfsStreamContainerIterator($this->children); } /** * checks whether dir is a dot dir * * @return bool */ public function isDot() { if ('.' === $this->name || '..' === $this->name) { return true; } return false; } } content = new StringBasedFileContent(''); $this->type = vfsStreamContent::TYPE_FILE; parent::__construct($name, $permissions); } /** * returns default permissions for concrete implementation * * @return int * @since 0.8.0 */ protected function getDefaultPermissions() { return 0666; } /** * checks whether the container can be applied to given name * * @param string $name * @return bool */ public function appliesTo($name) { return ($name === $this->name); } /** * alias for withContent() * * @param string $content * @return vfsStreamFile * @see withContent() */ public function setContent($content) { return $this->withContent($content); } /** * sets the contents of the file * * Setting content with this method does not change the time when the file * was last modified. * * @param string]FileContent $content * @return vfsStreamFile * @throws \InvalidArgumentException */ public function withContent($content) { if (is_string($content)) { $this->content = new StringBasedFileContent($content); } elseif ($content instanceof FileContent) { $this->content = $content; } else { throw new \InvalidArgumentException('Given content must either be a string or an instance of org\bovigo\vfs\content\FileContent'); } return $this; } /** * returns the contents of the file * * Getting content does not change the time when the file * was last accessed. * * @return string */ public function getContent() { return $this->content->content(); } /** * simply open the file * * @since 0.9 */ public function open() { $this->content->seek(0, SEEK_SET); $this->lastAccessed = time(); } /** * open file and set pointer to end of file * * @since 0.9 */ public function openForAppend() { $this->content->seek(0, SEEK_END); $this->lastAccessed = time(); } /** * open file and truncate content * * @since 0.9 */ public function openWithTruncate() { $this->open(); $this->content->truncate(0); $time = time(); $this->lastAccessed = $time; $this->lastModified = $time; } /** * reads the given amount of bytes from content * * Using this method changes the time when the file was last accessed. * * @param int $count * @return string */ public function read($count) { $this->lastAccessed = time(); return $this->content->read($count); } /** * returns the content until its end from current offset * * Using this method changes the time when the file was last accessed. * * @return string * @deprecated since 1.3.0 */ public function readUntilEnd() { $this->lastAccessed = time(); return $this->content->readUntilEnd(); } /** * writes an amount of data * * Using this method changes the time when the file was last modified. * * @param string $data * @return int amount of written bytes */ public function write($data) { $this->lastModified = time(); return $this->content->write($data); } /** * Truncates a file to a given length * * @param int $size length to truncate file to * @return bool * @since 1.1.0 */ public function truncate($size) { $this->content->truncate($size); $this->lastModified = time(); return true; } /** * checks whether pointer is at end of file * * @return bool */ public function eof() { return $this->content->eof(); } /** * returns the current position within the file * * @return int * @deprecated since 1.3.0 */ public function getBytesRead() { return $this->content->bytesRead(); } /** * seeks to the given offset * * @param int $offset * @param int $whence * @return bool */ public function seek($offset, $whence) { return $this->content->seek($offset, $whence); } /** * returns size of content * * @return int */ public function size() { return $this->content->size(); } /** * locks file for * * @param resource|vfsStreamWrapper $resource * @param int $operation * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function lock($resource, $operation) { if ((LOCK_NB & $operation) == LOCK_NB) { $operation = $operation - LOCK_NB; } // call to lock file on the same file handler firstly releases the lock $this->unlock($resource); if (LOCK_EX === $operation) { if ($this->isLocked()) { return false; } $this->setExclusiveLock($resource); } elseif(LOCK_SH === $operation) { if ($this->hasExclusiveLock()) { return false; } $this->addSharedLock($resource); } return true; } /** * Removes lock from file acquired by given resource * * @param resource|vfsStreamWrapper $resource * @see https://github.com/mikey179/vfsStream/issues/40 */ public function unlock($resource) { if ($this->hasExclusiveLock($resource)) { $this->exclusiveLock = null; } if ($this->hasSharedLock($resource)) { unset($this->sharedLock[$this->getResourceId($resource)]); } } /** * Set exlusive lock on file by given resource * * @param resource|vfsStreamWrapper $resource * @see https://github.com/mikey179/vfsStream/issues/40 */ protected function setExclusiveLock($resource) { $this->exclusiveLock = $this->getResourceId($resource); } /** * Add shared lock on file by given resource * * @param resource|vfsStreamWrapper $resource * @see https://github.com/mikey179/vfsStream/issues/40 */ protected function addSharedLock($resource) { $this->sharedLock[$this->getResourceId($resource)] = true; } /** * checks whether file is locked * * @param resource|vfsStreamWrapper $resource * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function isLocked($resource = null) { return $this->hasSharedLock($resource) || $this->hasExclusiveLock($resource); } /** * checks whether file is locked in shared mode * * @param resource|vfsStreamWrapper $resource * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function hasSharedLock($resource = null) { if (null !== $resource) { return isset($this->sharedLock[$this->getResourceId($resource)]); } return !empty($this->sharedLock); } /** * Returns unique resource id * * @param resource|vfsStreamWrapper $resource * @return string * @see https://github.com/mikey179/vfsStream/issues/40 */ public function getResourceId($resource) { if (is_resource($resource)) { $data = stream_get_meta_data($resource); $resource = $data['wrapper_data']; } return spl_object_hash($resource); } /** * checks whether file is locked in exclusive mode * * @param resource|vfsStreamWrapper $resource * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function hasExclusiveLock($resource = null) { if (null !== $resource) { return $this->exclusiveLock === $this->getResourceId($resource); } return null !== $this->exclusiveLock; } } getName() === $path) { return self::$root; } if ($this->isInRoot($path) && self::$root->hasChild($path) === true) { return self::$root->getChild($path); } return null; } /** * helper method to detect whether given path is in root path * * @param string $path * @return bool */ private function isInRoot($path) { return substr($path, 0, strlen(self::$root->getName())) === self::$root->getName(); } /** * returns content for given path but only when it is of given type * * @param string $path * @param int $type * @return vfsStreamContent */ protected function getContentOfType($path, $type) { $content = $this->getContent($path); if (null !== $content && $content->getType() === $type) { return $content; } return null; } /** * splits path into its dirname and the basename * * @param string $path * @return string[] */ protected function splitPath($path) { $lastSlashPos = strrpos($path, '/'); if (false === $lastSlashPos) { return array('dirname' => '', 'basename' => $path); } return array('dirname' => substr($path, 0, $lastSlashPos), 'basename' => substr($path, $lastSlashPos + 1) ); } /** * helper method to resolve a path from /foo/bar/. to /foo/bar * * @param string $path * @return string */ protected function resolvePath($path) { $newPath = array(); foreach (explode('/', $path) as $pathPart) { if ('.' !== $pathPart) { if ('..' !== $pathPart) { $newPath[] = $pathPart; } elseif (count($newPath) > 1) { array_pop($newPath); } } } return implode('/', $newPath); } /** * open the stream * * @param string $path the path to open * @param string $mode mode for opening * @param string $options options for opening * @param string $opened_path full path that was actually opened * @return bool */ public function stream_open($path, $mode, $options, $opened_path) { $extended = ((strstr($mode, '+') !== false) ? (true) : (false)); $mode = str_replace(array('t', 'b', '+'), '', $mode); if (in_array($mode, array('r', 'w', 'a', 'x', 'c')) === false) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Illegal mode ' . $mode . ', use r, w, a, x or c, flavoured with t, b and/or +', E_USER_WARNING); } return false; } $this->mode = $this->calculateMode($mode, $extended); $path = $this->resolvePath(vfsStream::path($path)); $this->content = $this->getContentOfType($path, vfsStreamContent::TYPE_FILE); if (null !== $this->content) { if (self::WRITE === $mode) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('File ' . $path . ' already exists, can not open with mode x', E_USER_WARNING); } return false; } if ( (self::TRUNCATE === $mode || self::APPEND === $mode) && $this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false ) { return false; } if (self::TRUNCATE === $mode) { $this->content->openWithTruncate(); } elseif (self::APPEND === $mode) { $this->content->openForAppend(); } else { if (!$this->content->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Permission denied', E_USER_WARNING); } return false; } $this->content->open(); } return true; } $content = $this->createFile($path, $mode, $options); if (false === $content) { return false; } $this->content = $content; return true; } /** * creates a file at given path * * @param string $path the path to open * @param string $mode mode for opening * @param string $options options for opening * @return bool */ private function createFile($path, $mode = null, $options = null) { $names = $this->splitPath($path); if (empty($names['dirname']) === true) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('File ' . $names['basename'] . ' does not exist', E_USER_WARNING); } return false; } $dir = $this->getContentOfType($names['dirname'], vfsStreamContent::TYPE_DIR); if (null === $dir) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Directory ' . $names['dirname'] . ' does not exist', E_USER_WARNING); } return false; } elseif ($dir->hasChild($names['basename']) === true) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Directory ' . $names['dirname'] . ' already contains a director named ' . $names['basename'], E_USER_WARNING); } return false; } if (self::READ === $mode) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Can not open non-existing file ' . $path . ' for reading', E_USER_WARNING); } return false; } if ($dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { trigger_error('Can not create new file in non-writable path ' . $names['dirname'], E_USER_WARNING); } return false; } return vfsStream::newFile($names['basename'])->at($dir); } /** * calculates the file mode * * @param string $mode opening mode: r, w, a or x * @param bool $extended true if + was set with opening mode * @return int */ protected function calculateMode($mode, $extended) { if (true === $extended) { return self::ALL; } if (self::READ === $mode) { return self::READONLY; } return self::WRITEONLY; } /** * closes the stream * * @see https://github.com/mikey179/vfsStream/issues/40 */ public function stream_close() { $this->content->lock($this, LOCK_UN); } /** * read the stream up to $count bytes * * @param int $count amount of bytes to read * @return string */ public function stream_read($count) { if (self::WRITEONLY === $this->mode) { return ''; } if ($this->content->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return ''; } return $this->content->read($count); } /** * writes data into the stream * * @param string $data * @return int amount of bytes written */ public function stream_write($data) { if (self::READONLY === $this->mode) { return 0; } if ($this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return 0; } if (self::$quota->isLimited()) { $data = substr($data, 0, self::$quota->spaceLeft(self::$root->sizeSummarized())); } return $this->content->write($data); } /** * truncates a file to a given length * * @param int $size length to truncate file to * @return bool * @since 1.1.0 */ public function stream_truncate($size) { if (self::READONLY === $this->mode) { return false; } if ($this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return false; } if ($this->content->getType() !== vfsStreamContent::TYPE_FILE) { return false; } if (self::$quota->isLimited() && $this->content->size() < $size) { $maxSize = self::$quota->spaceLeft(self::$root->sizeSummarized()); if (0 === $maxSize) { return false; } if ($size > $maxSize) { $size = $maxSize; } } return $this->content->truncate($size); } /** * sets metadata like owner, user or permissions * * @param string $path * @param int $option * @param mixed $var * @return bool * @since 1.1.0 */ public function stream_metadata($path, $option, $var) { $path = $this->resolvePath(vfsStream::path($path)); $content = $this->getContent($path); switch ($option) { case STREAM_META_TOUCH: if (null === $content) { $content = $this->createFile($path, null, STREAM_REPORT_ERRORS); // file creation may not be allowed at provided path if (false === $content) { return false; } } $currentTime = time(); $content->lastModified(((isset($var[0])) ? ($var[0]) : ($currentTime))) ->lastAccessed(((isset($var[1])) ? ($var[1]) : ($currentTime))); return true; case STREAM_META_OWNER_NAME: return false; case STREAM_META_OWNER: if (null === $content) { return false; } return $this->doPermChange($path, $content, function() use ($content, $var) { $content->chown($var); } ); case STREAM_META_GROUP_NAME: return false; case STREAM_META_GROUP: if (null === $content) { return false; } return $this->doPermChange($path, $content, function() use ($content, $var) { $content->chgrp($var); } ); case STREAM_META_ACCESS: if (null === $content) { return false; } return $this->doPermChange($path, $content, function() use ($content, $var) { $content->chmod($var); } ); default: return false; } } /** * executes given permission change when necessary rights allow such a change * * @param string $path * @param vfsStreamAbstractContent $content * @param \Closure $change * @return bool */ private function doPermChange($path, vfsStreamAbstractContent $content, \Closure $change) { if (!$content->isOwnedByUser(vfsStream::getCurrentUser())) { return false; } if (self::$root->getName() !== $path) { $names = $this->splitPath($path); $parent = $this->getContent($names['dirname']); if (!$parent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { return false; } } $change(); return true; } /** * checks whether stream is at end of file * * @return bool */ public function stream_eof() { return $this->content->eof(); } /** * returns the current position of the stream * * @return int */ public function stream_tell() { return $this->content->getBytesRead(); } /** * seeks to the given offset * * @param int $offset * @param int $whence * @return bool */ public function stream_seek($offset, $whence) { return $this->content->seek($offset, $whence); } /** * flushes unstored data into storage * * @return bool */ public function stream_flush() { return true; } /** * returns status of stream * * @return array */ public function stream_stat() { $fileStat = array('dev' => 0, 'ino' => 0, 'mode' => $this->content->getType() | $this->content->getPermissions(), 'nlink' => 0, 'uid' => $this->content->getUser(), 'gid' => $this->content->getGroup(), 'rdev' => 0, 'size' => $this->content->size(), 'atime' => $this->content->fileatime(), 'mtime' => $this->content->filemtime(), 'ctime' => $this->content->filectime(), 'blksize' => -1, 'blocks' => -1 ); return array_merge(array_values($fileStat), $fileStat); } /** * retrieve the underlaying resource * * Please note that this method always returns false as there is no * underlaying resource to return. * * @param int $cast_as * @since 0.9.0 * @see https://github.com/mikey179/vfsStream/issues/3 * @return bool */ public function stream_cast($cast_as) { return false; } /** * set lock status for stream * * @param int $operation * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/6 * @see https://github.com/mikey179/vfsStream/issues/31 * @see https://github.com/mikey179/vfsStream/issues/40 */ public function stream_lock($operation) { if ((LOCK_NB & $operation) == LOCK_NB) { $operation = $operation - LOCK_NB; } return $this->content->lock($this, $operation); } /** * sets options on the stream * * @param int $option key of option to set * @param int $arg1 * @param int $arg2 * @return bool * @since 0.10.0 * @see https://github.com/mikey179/vfsStream/issues/15 * @see http://www.php.net/manual/streamwrapper.stream-set-option.php */ public function stream_set_option($option, $arg1, $arg2) { switch ($option) { case STREAM_OPTION_BLOCKING: // break omitted case STREAM_OPTION_READ_TIMEOUT: // break omitted case STREAM_OPTION_WRITE_BUFFER: // break omitted default: // nothing to do here } return false; } /** * remove the data under the given path * * @param string $path * @return bool */ public function unlink($path) { $realPath = $this->resolvePath(vfsStream::path($path)); $content = $this->getContent($realPath); if (null === $content) { trigger_error('unlink(' . $path . '): No such file or directory', E_USER_WARNING); return false; } if ($content->getType() !== vfsStreamContent::TYPE_FILE) { trigger_error('unlink(' . $path . '): Operation not permitted', E_USER_WARNING); return false; } return $this->doUnlink($realPath); } /** * removes a path * * @param string $path * @return bool */ protected function doUnlink($path) { if (self::$root->getName() === $path) { // delete root? very brave. :) self::$root = null; clearstatcache(); return true; } $names = $this->splitPath($path); $content = $this->getContent($names['dirname']); if (!$content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { return false; } clearstatcache(); return $content->removeChild($names['basename']); } /** * rename from one path to another * * @param string $path_from * @param string $path_to * @return bool * @author Benoit Aubuchon */ public function rename($path_from, $path_to) { $srcRealPath = $this->resolvePath(vfsStream::path($path_from)); $dstRealPath = $this->resolvePath(vfsStream::path($path_to)); $srcContent = $this->getContent($srcRealPath); if (null == $srcContent) { trigger_error(' No such file or directory', E_USER_WARNING); return false; } $dstNames = $this->splitPath($dstRealPath); $dstParentContent = $this->getContent($dstNames['dirname']); if (null == $dstParentContent) { trigger_error('No such file or directory', E_USER_WARNING); return false; } if (!$dstParentContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { trigger_error('Permission denied', E_USER_WARNING); return false; } if ($dstParentContent->getType() !== vfsStreamContent::TYPE_DIR) { trigger_error('Target is not a directory', E_USER_WARNING); return false; } // remove old source first, so we can rename later // (renaming first would lead to not being able to remove the old path) if (!$this->doUnlink($srcRealPath)) { return false; } $dstContent = $srcContent; // Renaming the filename $dstContent->rename($dstNames['basename']); // Copying to the destination $dstParentContent->addChild($dstContent); return true; } /** * creates a new directory * * @param string $path * @param int $mode * @param int $options * @return bool */ public function mkdir($path, $mode, $options) { $umask = vfsStream::umask(); if (0 < $umask) { $permissions = $mode & ~$umask; } else { $permissions = $mode; } $path = $this->resolvePath(vfsStream::path($path)); if (null !== $this->getContent($path)) { trigger_error('mkdir(): Path vfs://' . $path . ' exists', E_USER_WARNING); return false; } if (null === self::$root) { self::$root = vfsStream::newDirectory($path, $permissions); return true; } $maxDepth = count(explode('/', $path)); $names = $this->splitPath($path); $newDirs = $names['basename']; $dir = null; $i = 0; while ($dir === null && $i < $maxDepth) { $dir = $this->getContent($names['dirname']); $names = $this->splitPath($names['dirname']); if (null == $dir) { $newDirs = $names['basename'] . '/' . $newDirs; } $i++; } if (null === $dir || $dir->getType() !== vfsStreamContent::TYPE_DIR || $dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return false; } $recursive = ((STREAM_MKDIR_RECURSIVE & $options) !== 0) ? (true) : (false); if (strpos($newDirs, '/') !== false && false === $recursive) { return false; } vfsStream::newDirectory($newDirs, $permissions)->at($dir); return true; } /** * removes a directory * * @param string $path * @param int $options * @return bool * @todo consider $options with STREAM_MKDIR_RECURSIVE */ public function rmdir($path, $options) { $path = $this->resolvePath(vfsStream::path($path)); $child = $this->getContentOfType($path, vfsStreamContent::TYPE_DIR); if (null === $child) { return false; } // can only remove empty directories if (count($child->getChildren()) > 0) { return false; } if (self::$root->getName() === $path) { // delete root? very brave. :) self::$root = null; clearstatcache(); return true; } $names = $this->splitPath($path); $dir = $this->getContentOfType($names['dirname'], vfsStreamContent::TYPE_DIR); if ($dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return false; } clearstatcache(); return $dir->removeChild($child->getName()); } /** * opens a directory * * @param string $path * @param int $options * @return bool */ public function dir_opendir($path, $options) { $path = $this->resolvePath(vfsStream::path($path)); $this->dir = $this->getContentOfType($path, vfsStreamContent::TYPE_DIR); if (null === $this->dir || $this->dir->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { return false; } $this->dirIterator = $this->dir->getIterator(); return true; } /** * reads directory contents * * @return string */ public function dir_readdir() { $dir = $this->dirIterator->current(); if (null === $dir) { return false; } $this->dirIterator->next(); return $dir->getName(); } /** * reset directory iteration * * @return bool */ public function dir_rewinddir() { return $this->dirIterator->rewind(); } /** * closes directory * * @return bool */ public function dir_closedir() { $this->dirIterator = null; return true; } /** * returns status of url * * @param string $path path of url to return status for * @param int $flags flags set by the stream API * @return array */ public function url_stat($path, $flags) { $content = $this->getContent($this->resolvePath(vfsStream::path($path))); if (null === $content) { if (($flags & STREAM_URL_STAT_QUIET) != STREAM_URL_STAT_QUIET) { trigger_error(' No such file or directory: ' . $path, E_USER_WARNING); } return false; } $fileStat = array('dev' => 0, 'ino' => 0, 'mode' => $content->getType() | $content->getPermissions(), 'nlink' => 0, 'uid' => $content->getUser(), 'gid' => $content->getGroup(), 'rdev' => 0, 'size' => $content->size(), 'atime' => $content->fileatime(), 'mtime' => $content->filemtime(), 'ctime' => $content->filectime(), 'blksize' => -1, 'blocks' => -1 ); return array_merge(array_values($fileStat), $fileStat); } } getType()) { case vfsStreamContent::TYPE_BLOCK: $this->visitBlockDevice($content); break; case vfsStreamContent::TYPE_FILE: $this->visitFile($content); break; case vfsStreamContent::TYPE_DIR: if (!$content->isDot()) { $this->visitDirectory($content); } break; default: throw new \InvalidArgumentException('Unknown content type ' . $content->getType() . ' for ' . $content->getName()); } return $this; } /** * visit a block device and process it * * @param vfsStreamBlock $block * @return vfsStreamVisitor */ public function visitBlockDevice(vfsStreamBlock $block) { return $this->visitFile($block); } } out = $out; $this->depth = 0; } /** * visit a file and process it * * @param vfsStreamFile $file * @return vfsStreamPrintVisitor */ public function visitFile(vfsStreamFile $file) { $this->printContent($file->getName()); return $this; } /** * visit a block device and process it * * @param vfsStreamBlock $block * @return vfsStreamPrintVisitor */ public function visitBlockDevice(vfsStreamBlock $block) { $name = '[' . $block->getName() . ']'; $this->printContent($name); return $this; } /** * visit a directory and process it * * @param vfsStreamDirectory $dir * @return vfsStreamPrintVisitor */ public function visitDirectory(vfsStreamDirectory $dir) { $this->printContent($dir->getName()); $this->depth++; foreach ($dir as $child) { $this->visit($child); } $this->depth--; return $this; } /** * helper method to print the content * * @param string $name */ protected function printContent($name) { fwrite($this->out, str_repeat(' ', $this->depth) . '- ' . $name . "\n"); } } reset(); } /** * visit a file and process it * * @param vfsStreamFile $file * @return vfsStreamStructureVisitor */ public function visitFile(vfsStreamFile $file) { $this->current[$file->getName()] = $file->getContent(); return $this; } /** * visit a block device and process it * * @param vfsStreamBlock $block * @return vfsStreamStructureVisitor */ public function visitBlockDevice(vfsStreamBlock $block) { $this->current['[' . $block->getName() . ']'] = $block->getContent(); return $this; } /** * visit a directory and process it * * @param vfsStreamDirectory $dir * @return vfsStreamStructureVisitor */ public function visitDirectory(vfsStreamDirectory $dir) { $this->current[$dir->getName()] = array(); $tmp =& $this->current; $this->current =& $tmp[$dir->getName()]; foreach ($dir as $child) { $this->visit($child); } $this->current =& $tmp; return $this; } /** * returns structure of visited contents * * @return array * @api */ public function getStructure() { return $this->structure; } /** * resets structure so visitor could be reused * * @return vfsStreamStructureVisitor */ public function reset() { $this->structure = array(); $this->current =& $this->structure; return $this; } } expectException($exception); } elseif (method_exists($this, 'setExpectedException')) { $this->setExpectedException($exception); } } // A BC hack to get handle the deprecation of this method in PHPUnit public function bc_getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false, $callOriginalMethods = false, $proxyTarget = null) { if (method_exists($this, "getMockBuilder")) { return $this ->getMockBuilder($originalClassName) ->setMethods($methods) ->getMock() ; } return parent::getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget); } } assertEquals($expectedCount, $actualCount, 'Directory foo contains ' . $expectedCount . ' children, but got ' . $actualCount . ' children while iterating over directory contents' ); } /** * @param \Closure $dotFilesSwitch * @param string[] $expectedDirectories * @test * @dataProvider provideSwitchWithExpectations */ public function directoryIteration(\Closure $dotFilesSwitch, array $expectedDirectories) { $dotFilesSwitch(); $dir = dir($this->fooURL); $i = 0; while (false !== ($entry = $dir->read())) { $i++; $this->assertTrue(in_array($entry, $expectedDirectories)); } $this->assertDirectoryCount(count($expectedDirectories), $i); $dir->rewind(); $i = 0; while (false !== ($entry = $dir->read())) { $i++; $this->assertTrue(in_array($entry, $expectedDirectories)); } $this->assertDirectoryCount(count($expectedDirectories), $i); $dir->close(); } /** * @param \Closure $dotFilesSwitch * @param string[] $expectedDirectories * @test * @dataProvider provideSwitchWithExpectations */ public function directoryIterationWithDot(\Closure $dotFilesSwitch, array $expectedDirectories) { $dotFilesSwitch(); $dir = dir($this->fooURL . '/.'); $i = 0; while (false !== ($entry = $dir->read())) { $i++; $this->assertTrue(in_array($entry, $expectedDirectories)); } $this->assertDirectoryCount(count($expectedDirectories), $i); $dir->rewind(); $i = 0; while (false !== ($entry = $dir->read())) { $i++; $this->assertTrue(in_array($entry, $expectedDirectories)); } $this->assertDirectoryCount(count($expectedDirectories), $i); $dir->close(); } /** * assure that a directory iteration works as expected * * @param \Closure $dotFilesSwitch * @param string[] $expectedDirectories * @test * @dataProvider provideSwitchWithExpectations * @group regression * @group bug_2 */ public function directoryIterationWithOpenDir_Bug_2(\Closure $dotFilesSwitch, array $expectedDirectories) { $dotFilesSwitch(); $handle = opendir($this->fooURL); $i = 0; while (false !== ($entry = readdir($handle))) { $i++; $this->assertTrue(in_array($entry, $expectedDirectories)); } $this->assertDirectoryCount(count($expectedDirectories), $i); rewinddir($handle); $i = 0; while (false !== ($entry = readdir($handle))) { $i++; $this->assertTrue(in_array($entry, $expectedDirectories)); } $this->assertDirectoryCount(count($expectedDirectories), $i); closedir($handle); } /** * assure that a directory iteration works as expected * * @author Christoph Bloemer * @param \Closure $dotFilesSwitch * @param string[] $expectedDirectories * @test * @dataProvider provideSwitchWithExpectations * @group regression * @group bug_4 */ public function directoryIteration_Bug_4(\Closure $dotFilesSwitch, array $expectedDirectories) { $dotFilesSwitch(); $dir = $this->fooURL; $list1 = array(); if ($handle = opendir($dir)) { while (false !== ($listItem = readdir($handle))) { if ('.' != $listItem && '..' != $listItem) { if (is_file($dir . '/' . $listItem) === true) { $list1[] = 'File:[' . $listItem . ']'; } elseif (is_dir($dir . '/' . $listItem) === true) { $list1[] = 'Folder:[' . $listItem . ']'; } } } closedir($handle); } $list2 = array(); if ($handle = opendir($dir)) { while (false !== ($listItem = readdir($handle))) { if ('.' != $listItem && '..' != $listItem) { if (is_file($dir . '/' . $listItem) === true) { $list2[] = 'File:[' . $listItem . ']'; } elseif (is_dir($dir . '/' . $listItem) === true) { $list2[] = 'Folder:[' . $listItem . ']'; } } } closedir($handle); } $this->assertEquals($list1, $list2); $this->assertEquals(2, count($list1)); $this->assertEquals(2, count($list2)); } /** * assure that a directory iteration works as expected * * @param \Closure $dotFilesSwitch * @param string[] $expectedDirectories * @test * @dataProvider provideSwitchWithExpectations */ public function directoryIterationShouldBeIndependent(\Closure $dotFilesSwitch, array $expectedDirectories) { $dotFilesSwitch(); $list1 = array(); $list2 = array(); $handle1 = opendir($this->fooURL); if (false !== ($listItem = readdir($handle1))) { $list1[] = $listItem; } $handle2 = opendir($this->fooURL); if (false !== ($listItem = readdir($handle2))) { $list2[] = $listItem; } if (false !== ($listItem = readdir($handle1))) { $list1[] = $listItem; } if (false !== ($listItem = readdir($handle2))) { $list2[] = $listItem; } closedir($handle1); closedir($handle2); $this->assertEquals($list1, $list2); $this->assertEquals(2, count($list1)); $this->assertEquals(2, count($list2)); } /** * @test * @group issue_50 */ public function recursiveDirectoryIterationWithDotsEnabled() { vfsStream::enableDotfiles(); vfsStream::setup(); $structure = array( 'Core' => array( 'AbstractFactory' => array( 'test.php' => 'some text content', 'other.php' => 'Some more text content', 'Invalid.csv' => 'Something else', ), 'AnEmptyFolder' => array(), 'badlocation.php' => 'some bad content', ) ); $root = vfsStream::create($structure); $rootPath = vfsStream::url($root->getName()); $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($rootPath), \RecursiveIteratorIterator::CHILD_FIRST); $pathes = array(); foreach ($iterator as $fullFileName => $fileSPLObject) { $pathes[] = $fullFileName; } $this->assertEquals(array('vfs://root'.DIRECTORY_SEPARATOR.'.', 'vfs://root'.DIRECTORY_SEPARATOR.'..', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'.', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'..', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'.', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'..', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'test.php', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'other.php', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'Invalid.csv', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AnEmptyFolder'.DIRECTORY_SEPARATOR.'.', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AnEmptyFolder'.DIRECTORY_SEPARATOR.'..', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AnEmptyFolder', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'badlocation.php', 'vfs://root'.DIRECTORY_SEPARATOR.'Core' ), $pathes ); } /** * @test * @group issue_50 */ public function recursiveDirectoryIterationWithDotsDisabled() { vfsStream::disableDotfiles(); vfsStream::setup(); $structure = array( 'Core' => array( 'AbstractFactory' => array( 'test.php' => 'some text content', 'other.php' => 'Some more text content', 'Invalid.csv' => 'Something else', ), 'AnEmptyFolder' => array(), 'badlocation.php' => 'some bad content', ) ); $root = vfsStream::create($structure); $rootPath = vfsStream::url($root->getName()); $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($rootPath), \RecursiveIteratorIterator::CHILD_FIRST); $pathes = array(); foreach ($iterator as $fullFileName => $fileSPLObject) { $pathes[] = $fullFileName; } $this->assertEquals(array('vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'test.php', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'other.php', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'Invalid.csv', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AnEmptyFolder', 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'badlocation.php', 'vfs://root'.DIRECTORY_SEPARATOR.'Core' ), $pathes ); } } rootDir = vfsStream::url('root'); $this->lostAndFound = $this->rootDir . '/lost+found/'; mkdir($this->lostAndFound); } /** * @test */ public function worksWithCorrectName() { $results = array(); $it = new \RecursiveDirectoryIterator($this->lostAndFound); foreach ($it as $f) { $results[] = $f->getPathname(); } $this->assertEquals( array( 'vfs://root/lost+found' . DIRECTORY_SEPARATOR . '.', 'vfs://root/lost+found' . DIRECTORY_SEPARATOR . '..' ), $results ); } /** * @test */ public function doesNotWorkWithInvalidName() { $this->expectException(\UnexpectedValueException::class); $this->expectExceptionMessage('ailed to open dir'); $results = array(); $it = new \RecursiveDirectoryIterator($this->rootDir . '/lost found/'); foreach ($it as $f) { $results[] = $f->getPathname(); } } /** * @test */ public function returnsCorrectNames() { $results = array(); $it = new \RecursiveDirectoryIterator($this->rootDir); foreach ($it as $f) { $results[] = $f->getPathname(); } $this->assertEquals( array( 'vfs://root' . DIRECTORY_SEPARATOR . '.', 'vfs://root' . DIRECTORY_SEPARATOR . '..', 'vfs://root' . DIRECTORY_SEPARATOR . 'lost+found' ), $results ); } } array( 'schema.xsd' => ' ', ) ); vfsStream::setup('root', null, $structure); $doc = new \DOMDocument(); $this->assertTrue($doc->load(vfsStream::url('root/foo bar/schema.xsd'))); } /** * @test */ public function vfsStreamCanHandleUrlEncodedPath() { $content = ' '; $structure = array('foo bar' => array( 'schema.xsd' => $content, ) ); vfsStream::setup('root', null, $structure); $this->assertEquals( $content, file_get_contents(vfsStream::url('root/foo bar/schema.xsd')) ); } } array('test.file' => '')); $this->root = vfsStream::setup('root', null, $structure); } /** * @test * @group issue_52 */ public function canNotChangePermissionWhenDirectoryNotWriteable() { $this->root->getChild('test_directory')->chmod(0444); $this->assertFalse(@chmod(vfsStream::url('root/test_directory/test.file'), 0777)); } /** * @test * @group issue_53 */ public function canNotChangePermissionWhenFileNotOwned() { $this->root->getChild('test_directory')->getChild('test.file')->chown(vfsStream::OWNER_USER_1); $this->assertFalse(@chmod(vfsStream::url('root/test_directory/test.file'), 0777)); } /** * @test * @group issue_52 */ public function canNotChangeOwnerWhenDirectoryNotWriteable() { $this->root->getChild('test_directory')->chmod(0444); $this->assertFalse(@chown(vfsStream::url('root/test_directory/test.file'), vfsStream::OWNER_USER_2)); } /** * @test * @group issue_53 */ public function canNotChangeOwnerWhenFileNotOwned() { $this->root->getChild('test_directory')->getChild('test.file')->chown(vfsStream::OWNER_USER_1); $this->assertFalse(@chown(vfsStream::url('root/test_directory/test.file'), vfsStream::OWNER_USER_2)); } /** * @test * @group issue_52 */ public function canNotChangeGroupWhenDirectoryNotWriteable() { $this->root->getChild('test_directory')->chmod(0444); $this->assertFalse(@chgrp(vfsStream::url('root/test_directory/test.file'), vfsStream::GROUP_USER_2)); } /** * @test * @group issue_53 */ public function canNotChangeGroupWhenFileNotOwned() { $this->root->getChild('test_directory')->getChild('test.file')->chown(vfsStream::OWNER_USER_1); $this->assertFalse(@chgrp(vfsStream::url('root/test_directory/test.file'), vfsStream::GROUP_USER_2)); } /** * @test * @group issue_107 * @requires PHP 5.4 * @since 1.5.0 */ public function touchOnNonWriteableDirectoryTriggersError() { $this->expectException(Error\Warning::class); $this->expectExceptionMessage('Can not create new file in non-writable path root'); $this->root->chmod(0555); touch($this->root->url() . '/touch.txt'); } /** * @test * @group issue_107 * @requires PHP 5.4 * @since 1.5.0 */ public function touchOnNonWriteableDirectoryDoesNotCreateFile() { $this->root->chmod(0555); $this->assertFalse(@touch($this->root->url() . '/touch.txt')); $this->assertFalse($this->root->hasChild('touch.txt')); } } quota = new Quota(10); } /** * @test */ public function unlimitedQuotaIsNotLimited() { $this->assertFalse(Quota::unlimited()->isLimited()); } /** * @test */ public function limitedQuotaIsLimited() { $this->assertTrue($this->quota->isLimited()); } /** * @test */ public function unlimitedQuotaHasAlwaysSpaceLeft() { $this->assertEquals(303, Quota::unlimited()->spaceLeft(303)); } /** * @test */ public function hasNoSpaceLeftWhenUsedSpaceIsLargerThanQuota() { $this->assertEquals(0, $this->quota->spaceLeft(11)); } /** * @test */ public function hasNoSpaceLeftWhenUsedSpaceIsEqualToQuota() { $this->assertEquals(0, $this->quota->spaceLeft(10)); } /** * @test */ public function hasSpaceLeftWhenUsedSpaceIsLowerThanQuota() { $this->assertEquals(1, $this->quota->spaceLeft(9)); } } array('test.file' => '')); $root = vfsStream::setup('root', null, $structure); $root->getChild('test_directory')->chmod(0777); $root->getChild('test_directory')->getChild('test.file')->chmod(0444); $this->assertTrue(@unlink(vfsStream::url('root/test_directory/test.file'))); } /** * @test * @group issue_51 */ public function canNotRemoveWritableFileFromNonWritableDirectory() { $structure = array('test_directory' => array('test.file' => '')); $root = vfsStream::setup('root', null, $structure); $root->getChild('test_directory')->chmod(0444); $root->getChild('test_directory')->getChild('test.file')->chmod(0777); $this->assertFalse(@unlink(vfsStream::url('root/test_directory/test.file'))); } /** * @test * @since 1.4.0 * @group issue_68 */ public function unlinkNonExistingFileTriggersError() { vfsStream::setup(); try { $this->assertFalse(unlink('vfs://root/foo.txt')); } catch (\PHPUnit_Framework_Error $fe) { $this->assertEquals('unlink(vfs://root/foo.txt): No such file or directory', $fe->getMessage()); } } } largeFileContent = new LargeFileContent(100); } /** * @test */ public function hasSizeOriginallyGiven() { $this->assertEquals(100, $this->largeFileContent->size()); } /** * @test */ public function contentIsFilledUpWithSpacesIfNoDataWritten() { $this->assertEquals( str_repeat(' ', 100), $this->largeFileContent->content() ); } /** * @test */ public function readReturnsSpacesWhenNothingWrittenAtOffset() { $this->assertEquals( str_repeat(' ', 10), $this->largeFileContent->read(10) ); } /** * @test */ public function readReturnsContentFilledWithSpaces() { $this->largeFileContent->write('foobarbaz'); $this->largeFileContent->seek(0, SEEK_SET); $this->assertEquals( 'foobarbaz ', $this->largeFileContent->read(10) ); } /** * @test */ public function writesDataAtStartWhenOffsetNotMoved() { $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); $this->assertEquals( 'foobarbaz' . str_repeat(' ', 91), $this->largeFileContent->content() ); } /** * @test */ public function writeDataAtStartDoesNotIncreaseSize() { $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); $this->assertEquals(100, $this->largeFileContent->size()); } /** * @test */ public function writesDataAtOffsetWhenOffsetMoved() { $this->largeFileContent->seek(50, SEEK_SET); $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); $this->assertEquals( str_repeat(' ', 50) . 'foobarbaz' . str_repeat(' ', 41), $this->largeFileContent->content() ); } /** * @test */ public function writeDataInBetweenDoesNotIncreaseSize() { $this->largeFileContent->seek(50, SEEK_SET); $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); $this->assertEquals(100, $this->largeFileContent->size()); } /** * @test */ public function writesDataOverEndWhenOffsetAndDataLengthLargerThanSize() { $this->largeFileContent->seek(95, SEEK_SET); $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); $this->assertEquals( str_repeat(' ', 95) . 'foobarbaz', $this->largeFileContent->content() ); } /** * @test */ public function writeDataOverLastOffsetIncreasesSize() { $this->largeFileContent->seek(95, SEEK_SET); $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); $this->assertEquals(104, $this->largeFileContent->size()); } /** * @test */ public function writesDataAfterEndWhenOffsetAfterEnd() { $this->largeFileContent->seek(0, SEEK_END); $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); $this->assertEquals( str_repeat(' ', 100) . 'foobarbaz', $this->largeFileContent->content() ); } /** * @test */ public function writeDataAfterLastOffsetIncreasesSize() { $this->largeFileContent->seek(0, SEEK_END); $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); $this->assertEquals(109, $this->largeFileContent->size()); } /** * @test */ public function truncateReducesSize() { $this->assertTrue($this->largeFileContent->truncate(50)); $this->assertEquals(50, $this->largeFileContent->size()); } /** * @test */ public function truncateRemovesWrittenContentAfterOffset() { $this->largeFileContent->seek(45, SEEK_SET); $this->largeFileContent->write('foobarbaz'); $this->assertTrue($this->largeFileContent->truncate(50)); $this->assertEquals( str_repeat(' ', 45) . 'fooba', $this->largeFileContent->content() ); } /** * @test */ public function createInstanceWithKilobytes() { $this->assertEquals( 100 * 1024, LargeFileContent::withKilobytes(100) ->size() ); } /** * @test */ public function createInstanceWithMegabytes() { $this->assertEquals( 100 * 1024 * 1024, LargeFileContent::withMegabytes(100) ->size() ); } /** * @test */ public function createInstanceWithGigabytes() { $this->assertEquals( 100 * 1024 * 1024 * 1024, LargeFileContent::withGigabytes(100) ->size() ); } } stringBasedFileContent = new StringBasedFileContent('foobarbaz'); } /** * @test */ public function hasContentOriginallySet() { $this->assertEquals('foobarbaz', $this->stringBasedFileContent->content()); } /** * @test */ public function hasNotReachedEofAfterCreation() { $this->assertFalse($this->stringBasedFileContent->eof()); } /** * @test */ public function sizeEqualsLengthOfGivenString() { $this->assertEquals(9, $this->stringBasedFileContent->size()); } /** * @test */ public function readReturnsSubstringWithRequestedLength() { $this->assertEquals('foo', $this->stringBasedFileContent->read(3)); } /** * @test */ public function readMovesOffset() { $this->assertEquals('foo', $this->stringBasedFileContent->read(3)); $this->assertEquals('bar', $this->stringBasedFileContent->read(3)); $this->assertEquals('baz', $this->stringBasedFileContent->read(3)); } /** * @test */ public function reaMoreThanSizeReturnsWholeContent() { $this->assertEquals('foobarbaz', $this->stringBasedFileContent->read(10)); } /** * @test */ public function readAfterEndReturnsEmptyString() { // Read more than the length of the string to test substr() returning // false. $this->stringBasedFileContent->read(10); $this->assertSame('', $this->stringBasedFileContent->read(3)); } /** * @test */ public function readDoesNotChangeSize() { $this->stringBasedFileContent->read(3); $this->assertEquals(9, $this->stringBasedFileContent->size()); } /** * @test */ public function readLessThenSizeDoesNotReachEof() { $this->stringBasedFileContent->read(3); $this->assertFalse($this->stringBasedFileContent->eof()); } /** * @test */ public function readSizeReachesEof() { $this->stringBasedFileContent->read(9); $this->assertTrue($this->stringBasedFileContent->eof()); } /** * @test */ public function readMoreThanSizeReachesEof() { $this->stringBasedFileContent->read(10); $this->assertTrue($this->stringBasedFileContent->eof()); } /** * @test */ public function seekWithInvalidOptionReturnsFalse() { $this->assertFalse($this->stringBasedFileContent->seek(0, 55)); } /** * @test */ public function canSeekToGivenOffset() { $this->assertTrue($this->stringBasedFileContent->seek(5, SEEK_SET)); $this->assertEquals('rbaz', $this->stringBasedFileContent->read(10)); } /** * @test */ public function canSeekFromCurrentOffset() { $this->assertTrue($this->stringBasedFileContent->seek(5, SEEK_SET)); $this->assertTrue($this->stringBasedFileContent->seek(2, SEEK_CUR)); $this->assertEquals('az', $this->stringBasedFileContent->read(10)); } /** * @test */ public function canSeekToEnd() { $this->assertTrue($this->stringBasedFileContent->seek(0, SEEK_END)); $this->assertEquals('', $this->stringBasedFileContent->read(10)); } /** * @test */ public function writeOverwritesExistingContentWhenOffsetNotAtEof() { $this->assertEquals(3, $this->stringBasedFileContent->write('bar')); $this->assertEquals('barbarbaz', $this->stringBasedFileContent->content()); } /** * @test */ public function writeAppendsContentWhenOffsetAtEof() { $this->assertTrue($this->stringBasedFileContent->seek(0, SEEK_END)); $this->assertEquals(3, $this->stringBasedFileContent->write('bar')); $this->assertEquals('foobarbazbar', $this->stringBasedFileContent->content()); } /** * @test * @group issue_33 * @since 1.1.0 */ public function truncateRemovesSuperflouosContent() { $this->assertTrue($this->stringBasedFileContent->truncate(6)); $this->assertEquals('foobar', $this->stringBasedFileContent->content()); } /** * @test * @group issue_33 * @since 1.1.0 */ public function truncateDecreasesSize() { $this->assertTrue($this->stringBasedFileContent->truncate(6)); $this->assertEquals(6, $this->stringBasedFileContent->size()); } /** * @test * @group issue_33 * @since 1.1.0 */ public function truncateToGreaterSizeAddsZeroBytes() { $this->assertTrue($this->stringBasedFileContent->truncate(25)); $this->assertEquals( "foobarbaz\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", $this->stringBasedFileContent->content() ); } /** * @test * @group issue_33 * @since 1.1.0 */ public function truncateToGreaterSizeIncreasesSize() { $this->assertTrue($this->stringBasedFileContent->truncate(25)); $this->assertEquals(25, $this->stringBasedFileContent->size()); } } */ public static function getMethodCalls($path) { if (isset(self::$calledMethods[$path]) === true) { return self::$calledMethods[$path]; } return array(); } /** * helper method for setting up vfsStream with the proxy * * @param string $rootDirName optional name of root directory * @param int $permissions optional file permissions of root directory * @return vfsStreamDirectory * @throws vfsStreamException */ public static function setup($rootDirName = 'root', $permissions = null) { self::$root = vfsStream::newDirectory($rootDirName, $permissions); if (true === self::$registered) { return self::$root; } if (@stream_wrapper_register(vfsStream::SCHEME, __CLASS__) === false) { throw new vfsStreamException('A handler has already been registered for the ' . vfsStream::SCHEME . ' protocol.'); } self::$registered = true; return self::$root; } /** * open the stream * * @param string $path the path to open * @param string $mode mode for opening * @param string $options options for opening * @param string $opened_path full path that was actually opened * @return bool */ public function stream_open($path, $mode, $options, $opened_path) { $this->path = $path; self::recordMethodCall('stream_open', $this->path); return parent::stream_open($path, $mode, $options, $opened_path); } /** * closes the stream */ public function stream_close() { self::recordMethodCall('stream_close', $this->path); return parent::stream_close(); } /** * read the stream up to $count bytes * * @param int $count amount of bytes to read * @return string */ public function stream_read($count) { self::recordMethodCall('stream_read', $this->path); return parent::stream_read($count); } /** * writes data into the stream * * @param string $data * @return int amount of bytes written */ public function stream_write($data) { self::recordMethodCall('stream_write', $this->path); return parent::stream_write($data); } /** * checks whether stream is at end of file * * @return bool */ public function stream_eof() { self::recordMethodCall('stream_eof', $this->path); return parent::stream_eof(); } /** * returns the current position of the stream * * @return int */ public function stream_tell() { self::recordMethodCall('stream_tell', $this->path); return parent::stream_tell(); } /** * seeks to the given offset * * @param int $offset * @param int $whence * @return bool */ public function stream_seek($offset, $whence) { self::recordMethodCall('stream_seek', $this->path); return parent::stream_seek($offset, $whence); } /** * flushes unstored data into storage * * @return bool */ public function stream_flush() { self::recordMethodCall('stream_flush', $this->path); return parent::stream_flush(); } /** * returns status of stream * * @return array */ public function stream_stat() { self::recordMethodCall('stream_stat', $this->path); return parent::stream_stat(); } /** * retrieve the underlaying resource * * @param int $cast_as * @return bool */ public function stream_cast($cast_as) { self::recordMethodCall('stream_cast', $this->path); return parent::stream_cast($cast_as); } /** * set lock status for stream * * @param int $operation * @return bool */ public function stream_lock($operation) { self::recordMethodCall('stream_link', $this->path); return parent::stream_lock($operation); } /** * remove the data under the given path * * @param string $path * @return bool */ public function unlink($path) { self::recordMethodCall('unlink', $path); return parent::unlink($path); } /** * rename from one path to another * * @param string $path_from * @param string $path_to * @return bool */ public function rename($path_from, $path_to) { self::recordMethodCall('rename', $path_from); return parent::rename($path_from, $path_to); } /** * creates a new directory * * @param string $path * @param int $mode * @param int $options * @return bool */ public function mkdir($path, $mode, $options) { self::recordMethodCall('mkdir', $path); return parent::mkdir($path, $mode, $options); } /** * removes a directory * * @param string $path * @param int $options * @return bool */ public function rmdir($path, $options) { self::recordMethodCall('rmdir', $path); return parent::rmdir($path, $options); } /** * opens a directory * * @param string $path * @param int $options * @return bool */ public function dir_opendir($path, $options) { $this->path = $path; self::recordMethodCall('dir_opendir', $this->path); return parent::dir_opendir($path, $options); } /** * reads directory contents * * @return string */ public function dir_readdir() { self::recordMethodCall('dir_readdir', $this->path); return parent::dir_readdir(); } /** * reset directory iteration * * @return bool */ public function dir_rewinddir() { self::recordMethodCall('dir_rewinddir', $this->path); return parent::dir_rewinddir(); } /** * closes directory * * @return bool */ public function dir_closedir() { self::recordMethodCall('dir_closedir', $this->path); return parent::dir_closedir(); } /** * returns status of url * * @param string $path path of url to return status for * @param int $flags flags set by the stream API * @return array */ public function url_stat($path, $flags) { self::recordMethodCall('url_stat', $path); return parent::url_stat($path, $flags); } } assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function executePermissionsForUser() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0100); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function executePermissionsForGroup() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0010); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function executePermissionsForOther() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0001); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function writePermissionsForUser() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0200); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function writePermissionsForGroup() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0020); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function writePermissionsForOther() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0002); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function executeAndWritePermissionsForUser() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0300); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function executeAndWritePermissionsForGroup() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0030); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function executeAndWritePermissionsForOther() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0003); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function readPermissionsForUser() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0400); $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function readPermissionsForGroup() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0040); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function readPermissionsForOther() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0004); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function readAndExecutePermissionsForUser() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0500); $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function readAndExecutePermissionsForGroup() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0050); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function readAndExecutePermissionsForOther() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0005); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function readAndWritePermissionsForUser() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0600); $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function readAndWritePermissionsForGroup() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0060); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function readAndWritePermissionsForOther() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0006); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function allPermissionsForUser() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0700); $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function allPermissionsForGroup() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0070); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, -1 ) ); } /** * @test * @group permissions * @group bug_15 */ public function allPermissionsForOther() { $abstractContent = new TestvfsStreamAbstractContent('foo', 0007); $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isReadable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isReadable(-1, -1 ) ); $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isWritable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isWritable(-1, -1 ) ); $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup() ) ); $this->assertFalse($abstractContent->isExecutable(-1, vfsStream::getCurrentGroup() ) ); $this->assertTrue($abstractContent->isExecutable(-1, -1 ) ); } } block = new vfsStreamBlock('foo'); } /** * test default values and methods * * @test */ public function defaultValues() { $this->assertEquals(vfsStreamContent::TYPE_BLOCK, $this->block->getType()); $this->assertEquals('foo', $this->block->getName()); $this->assertTrue($this->block->appliesTo('foo')); $this->assertFalse($this->block->appliesTo('foo/bar')); $this->assertFalse($this->block->appliesTo('bar')); } /** * tests how external functions see this object * * @test */ public function external() { $root = vfsStream::setup('root'); $root->addChild(vfsStream::newBlock('foo')); $this->assertEquals('block', filetype(vfsStream::url('root/foo'))); } /** * tests adding a complex structure * * @test */ public function addStructure() { $structure = array( 'topLevel' => array( 'thisIsAFile' => 'file contents', '[blockDevice]' => 'block contents' ) ); $root = vfsStream::create($structure); $this->assertSame('block', filetype(vfsStream::url('root/topLevel/blockDevice'))); } /** * tests that a blank name for a block device throws an exception * @test */ public function createWithEmptyName() { $this->expectException(vfsStreamException::class); $structure = array( 'topLevel' => array( 'thisIsAFile' => 'file contents', '[]' => 'block contents' ) ); $root = vfsStream::create($structure); } } dir = new vfsStreamDirectory('foo'); $this->mockChild1 = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $this->mockChild1->expects($this->any()) ->method('getName') ->will($this->returnValue('bar')); $this->dir->addChild($this->mockChild1); $this->mockChild2 = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $this->mockChild2->expects($this->any()) ->method('getName') ->will($this->returnValue('baz')); $this->dir->addChild($this->mockChild2); } /** * clean up test environment */ public function tearDown(): void { vfsStream::enableDotfiles(); } /** * @return array */ public function provideSwitchWithExpectations() { return array(array(function() { vfsStream::disableDotfiles(); }, array() ), array(function() { vfsStream::enableDotfiles(); }, array('.', '..') ) ); } private function getDirName($dir) { if (is_string($dir)) { return $dir; } return $dir->getName(); } /** * @param \Closure $dotFilesSwitch * @param array $dirNames * @test * @dataProvider provideSwitchWithExpectations */ public function iteration(\Closure $dotFilesSwitch, array $dirs) { $dirs[] = $this->mockChild1; $dirs[] = $this->mockChild2; $dotFilesSwitch(); $dirIterator = $this->dir->getIterator(); foreach ($dirs as $dir) { $this->assertEquals($this->getDirName($dir), $dirIterator->key()); $this->assertTrue($dirIterator->valid()); if (!is_string($dir)) { $this->assertSame($dir, $dirIterator->current()); } $dirIterator->next(); } $this->assertFalse($dirIterator->valid()); $this->assertNull($dirIterator->key()); $this->assertNull($dirIterator->current()); } } rootDirectory = vfsStream::newDirectory('/'); $this->rootDirectory->addChild(vfsStream::newDirectory('var/log/app')); } /** * Test: should save directory name as string internal * * @small */ public function testShouldSaveDirectoryNameAsStringInternal() { $dir = $this->rootDirectory->getChild('var/log/app'); $dir->addChild(vfsStream::newDirectory(80)); static::assertNotNull($this->rootDirectory->getChild('var/log/app/80')); } /** * Test: should rename directory name as string internal * * @small */ public function testShouldRenameDirectoryNameAsStringInternal() { $dir = $this->rootDirectory->getChild('var/log/app'); $dir->addChild(vfsStream::newDirectory(80)); $child = $this->rootDirectory->getChild('var/log/app/80'); $child->rename(90); static::assertNotNull($this->rootDirectory->getChild('var/log/app/90')); } } rootDirectory = vfsStream::newDirectory('/'); $this->rootDirectory->addChild(vfsStream::newDirectory('var/log/app')); $dir = $this->rootDirectory->getChild('var/log/app'); $dir->addChild(vfsStream::newDirectory('app1')); $dir->addChild(vfsStream::newDirectory('app2')); $dir->addChild(vfsStream::newDirectory('foo')); } /** * @test */ public function shouldContainThreeSubdirectories() { $this->assertEquals(3, count($this->rootDirectory->getChild('var/log/app')->getChildren()) ); } /** * @test */ public function shouldContainSubdirectoryFoo() { $this->assertTrue($this->rootDirectory->getChild('var/log/app')->hasChild('foo')); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $this->rootDirectory->getChild('var/log/app')->getChild('foo') ); } /** * @test */ public function shouldContainSubdirectoryApp1() { $this->assertTrue($this->rootDirectory->getChild('var/log/app')->hasChild('app1')); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $this->rootDirectory->getChild('var/log/app')->getChild('app1') ); } /** * @test */ public function shouldContainSubdirectoryApp2() { $this->assertTrue($this->rootDirectory->getChild('var/log/app')->hasChild('app2')); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $this->rootDirectory->getChild('var/log/app')->getChild('app2') ); } } dir = new vfsStreamDirectory('foo'); } /** * assure that a directory seperator inside the name throws an exception * * @test */ public function invalidCharacterInName() { $this->expectException(vfsStreamException::class); $dir = new vfsStreamDirectory('foo/bar'); } /** * test default values and methods * * @test */ public function defaultValues() { $this->assertEquals(vfsStreamContent::TYPE_DIR, $this->dir->getType()); $this->assertEquals('foo', $this->dir->getName()); $this->assertTrue($this->dir->appliesTo('foo')); $this->assertTrue($this->dir->appliesTo('foo/bar')); $this->assertFalse($this->dir->appliesTo('bar')); $this->assertEquals(array(), $this->dir->getChildren()); } /** * test renaming the directory * * @test */ public function rename() { $this->dir->rename('bar'); $this->assertEquals('bar', $this->dir->getName()); $this->assertFalse($this->dir->appliesTo('foo')); $this->assertFalse($this->dir->appliesTo('foo/bar')); $this->assertTrue($this->dir->appliesTo('bar')); } /** * renaming the directory to an invalid name throws a vfsStreamException * * @test */ public function renameToInvalidNameThrowsvfsStreamException() { $this->expectException(vfsStreamException::class); $this->dir->rename('foo/baz'); } /** * @test * @since 0.10.0 */ public function hasNoChildrenByDefault() { $this->assertFalse($this->dir->hasChildren()); } /** * @test * @since 0.10.0 */ public function hasChildrenReturnsTrueIfAtLeastOneChildPresent() { $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $mockChild->expects($this->any()) ->method('appliesTo') ->will($this->returnValue(false)); $mockChild->expects($this->any()) ->method('getName') ->will($this->returnValue('baz')); $this->dir->addChild($mockChild); $this->assertTrue($this->dir->hasChildren()); } /** * @test */ public function hasChildReturnsFalseForNonExistingChild() { $this->assertFalse($this->dir->hasChild('bar')); } /** * @test */ public function getChildReturnsNullForNonExistingChild() { $this->assertNull($this->dir->getChild('bar')); } /** * @test */ public function removeChildReturnsFalseForNonExistingChild() { $this->assertFalse($this->dir->removeChild('bar')); } /** * @test */ public function nonExistingChild() { $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $mockChild->expects($this->any()) ->method('appliesTo') ->will($this->returnValue(false)); $mockChild->expects($this->any()) ->method('getName') ->will($this->returnValue('baz')); $this->dir->addChild($mockChild); $this->assertFalse($this->dir->removeChild('bar')); } /** * test that adding, handling and removing of a child works as expected * * @test */ public function childHandling() { $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $mockChild->expects($this->any()) ->method('getType') ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); $mockChild->expects($this->any()) ->method('getName') ->will($this->returnValue('bar')); $mockChild->expects($this->any()) ->method('appliesTo') ->with($this->equalTo('bar')) ->will($this->returnValue(true)); $mockChild->expects($this->once()) ->method('size') ->will($this->returnValue(5)); $this->dir->addChild($mockChild); $this->assertTrue($this->dir->hasChild('bar')); $bar = $this->dir->getChild('bar'); $this->assertSame($mockChild, $bar); $this->assertEquals(array($mockChild), $this->dir->getChildren()); $this->assertEquals(0, $this->dir->size()); $this->assertEquals(5, $this->dir->sizeSummarized()); $this->assertTrue($this->dir->removeChild('bar')); $this->assertEquals(array(), $this->dir->getChildren()); $this->assertEquals(0, $this->dir->size()); $this->assertEquals(0, $this->dir->sizeSummarized()); } /** * test that adding, handling and removing of a child works as expected * * @test */ public function childHandlingWithSubdirectory() { $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $mockChild->expects($this->any()) ->method('getType') ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); $mockChild->expects($this->any()) ->method('getName') ->will($this->returnValue('bar')); $mockChild->expects($this->once()) ->method('size') ->will($this->returnValue(5)); $subdir = new vfsStreamDirectory('subdir'); $subdir->addChild($mockChild); $this->dir->addChild($subdir); $this->assertTrue($this->dir->hasChild('subdir')); $this->assertSame($subdir, $this->dir->getChild('subdir')); $this->assertEquals(array($subdir), $this->dir->getChildren()); $this->assertEquals(0, $this->dir->size()); $this->assertEquals(5, $this->dir->sizeSummarized()); $this->assertTrue($this->dir->removeChild('subdir')); $this->assertEquals(array(), $this->dir->getChildren()); $this->assertEquals(0, $this->dir->size()); $this->assertEquals(0, $this->dir->sizeSummarized()); } /** * dd * * @test * @group regression * @group bug_5 */ public function addChildReplacesChildWithSameName_Bug_5() { $mockChild1 = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $mockChild1->expects($this->any()) ->method('getType') ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); $mockChild1->expects($this->any()) ->method('getName') ->will($this->returnValue('bar')); $mockChild2 = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $mockChild2->expects($this->any()) ->method('getType') ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); $mockChild2->expects($this->any()) ->method('getName') ->will($this->returnValue('bar')); $this->dir->addChild($mockChild1); $this->assertTrue($this->dir->hasChild('bar')); $this->assertSame($mockChild1, $this->dir->getChild('bar')); $this->dir->addChild($mockChild2); $this->assertTrue($this->dir->hasChild('bar')); $this->assertSame($mockChild2, $this->dir->getChild('bar')); } /** * When testing for a nested path, verify that directory separators are respected properly * so that subdir1/subdir2 is not considered equal to subdir1Xsubdir2. * * @test * @group bug_24 * @group regression */ public function explicitTestForSeparatorWithNestedPaths_Bug_24() { $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $mockChild->expects($this->any()) ->method('getType') ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); $mockChild->expects($this->any()) ->method('getName') ->will($this->returnValue('bar')); $subdir1 = new vfsStreamDirectory('subdir1'); $this->dir->addChild($subdir1); $subdir2 = new vfsStreamDirectory('subdir2'); $subdir1->addChild($subdir2); $subdir2->addChild($mockChild); $this->assertTrue($this->dir->hasChild('subdir1'), "Level 1 path with separator exists"); $this->assertTrue($this->dir->hasChild('subdir1/subdir2'), "Level 2 path with separator exists"); $this->assertTrue($this->dir->hasChild('subdir1/subdir2/bar'), "Level 3 path with separator exists"); $this->assertFalse($this->dir->hasChild('subdir1.subdir2'), "Path with period does not exist"); $this->assertFalse($this->dir->hasChild('subdir1.subdir2/bar'), "Nested path with period does not exist"); } /** * setting and retrieving permissions for a directory * * @test * @group permissions */ public function permissions() { $this->assertEquals(0777, $this->dir->getPermissions()); $this->assertSame($this->dir, $this->dir->chmod(0755)); $this->assertEquals(0755, $this->dir->getPermissions()); } /** * setting and retrieving permissions for a directory * * @test * @group permissions */ public function permissionsSet() { $this->dir = new vfsStreamDirectory('foo', 0755); $this->assertEquals(0755, $this->dir->getPermissions()); $this->assertSame($this->dir, $this->dir->chmod(0700)); $this->assertEquals(0700, $this->dir->getPermissions()); } /** * setting and retrieving owner of a file * * @test * @group permissions */ public function owner() { $this->assertEquals(vfsStream::getCurrentUser(), $this->dir->getUser()); $this->assertTrue($this->dir->isOwnedByUser(vfsStream::getCurrentUser())); $this->assertSame($this->dir, $this->dir->chown(vfsStream::OWNER_USER_1)); $this->assertEquals(vfsStream::OWNER_USER_1, $this->dir->getUser()); $this->assertTrue($this->dir->isOwnedByUser(vfsStream::OWNER_USER_1)); } /** * setting and retrieving owner group of a file * * @test * @group permissions */ public function group() { $this->assertEquals(vfsStream::getCurrentGroup(), $this->dir->getGroup()); $this->assertTrue($this->dir->isOwnedByGroup(vfsStream::getCurrentGroup())); $this->assertSame($this->dir, $this->dir->chgrp(vfsStream::GROUP_USER_1)); $this->assertEquals(vfsStream::GROUP_USER_1, $this->dir->getGroup()); $this->assertTrue($this->dir->isOwnedByGroup(vfsStream::GROUP_USER_1)); } } at($root); } /** * This test verifies the current behaviour where vfsStream URLs do not work * with file_put_contents() and LOCK_EX. The test is intended to break once * PHP changes this so we get notified about the change. * * @test */ public function filePutContentsLockShouldReportError() { @file_put_contents(vfsStream::url('root/testfile'), "some string\n", LOCK_EX); $php_error = error_get_last(); $this->assertEquals("file_put_contents(): Exclusive locks may only be set for regular files", $php_error['message']); } /** * @test */ public function flockSouldPass() { $fp = fopen(vfsStream::url('root/testfile'), 'w'); flock($fp, LOCK_EX); fwrite($fp, "another string\n"); flock($fp, LOCK_UN); fclose($fp); $this->assertEquals("another string\n", file_get_contents(vfsStream::url('root/testfile'))); } } file = new vfsStreamFile('foo'); } /** * test default values and methods * * @test */ public function defaultValues() { $this->assertEquals(vfsStreamContent::TYPE_FILE, $this->file->getType()); $this->assertEquals('foo', $this->file->getName()); $this->assertTrue($this->file->appliesTo('foo')); $this->assertFalse($this->file->appliesTo('foo/bar')); $this->assertFalse($this->file->appliesTo('bar')); } /** * test setting and getting the content of a file * * @test */ public function content() { $this->assertEquals('', $this->file->getContent()); $this->assertSame($this->file, $this->file->setContent('bar')); $this->assertEquals('bar', $this->file->getContent()); $this->assertSame($this->file, $this->file->withContent('baz')); $this->assertEquals('baz', $this->file->getContent()); } /** * test renaming the directory * * @test */ public function rename() { $this->file->rename('bar'); $this->assertEquals('bar', $this->file->getName()); $this->assertFalse($this->file->appliesTo('foo')); $this->assertFalse($this->file->appliesTo('foo/bar')); $this->assertTrue($this->file->appliesTo('bar')); } /** * test reading contents from the file * * @test */ public function readEmptyFile() { $this->assertTrue($this->file->eof()); $this->assertEquals(0, $this->file->size()); $this->assertEquals('', $this->file->read(5)); $this->assertEquals(5, $this->file->getBytesRead()); $this->assertTrue($this->file->eof()); } /** * test reading contents from the file * * @test */ public function read() { $this->file->setContent('foobarbaz'); $this->assertFalse($this->file->eof()); $this->assertEquals(9, $this->file->size()); $this->assertEquals('foo', $this->file->read(3)); $this->assertEquals(3, $this->file->getBytesRead()); $this->assertFalse($this->file->eof()); $this->assertEquals(9, $this->file->size()); $this->assertEquals('bar', $this->file->read(3)); $this->assertEquals(6, $this->file->getBytesRead()); $this->assertFalse($this->file->eof()); $this->assertEquals(9, $this->file->size()); $this->assertEquals('baz', $this->file->read(3)); $this->assertEquals(9, $this->file->getBytesRead()); $this->assertEquals(9, $this->file->size()); $this->assertTrue($this->file->eof()); $this->assertEquals('', $this->file->read(3)); } /** * test seeking to offset * * @test */ public function seekEmptyFile() { $this->assertFalse($this->file->seek(0, 55)); $this->assertTrue($this->file->seek(0, SEEK_SET)); $this->assertEquals(0, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(5, SEEK_SET)); $this->assertEquals(5, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(0, SEEK_CUR)); $this->assertEquals(5, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(2, SEEK_CUR)); $this->assertEquals(7, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(0, SEEK_END)); $this->assertEquals(0, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(2, SEEK_END)); $this->assertEquals(2, $this->file->getBytesRead()); } /** * @test * @since 1.6.5 */ public function seekEmptyFileBeforeBeginningDoesNotChangeOffset() { $this->assertFalse($this->file->seek(-5, SEEK_SET), 'Seek before beginning of file'); $this->assertEquals(0, $this->file->getBytesRead()); } /** * test seeking to offset * * @test */ public function seekRead() { $this->file->setContent('foobarbaz'); $this->assertFalse($this->file->seek(0, 55)); $this->assertTrue($this->file->seek(0, SEEK_SET)); $this->assertEquals('foobarbaz', $this->file->readUntilEnd()); $this->assertEquals(0, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(5, SEEK_SET)); $this->assertEquals('rbaz', $this->file->readUntilEnd()); $this->assertEquals(5, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(0, SEEK_CUR)); $this->assertEquals('rbaz', $this->file->readUntilEnd()); $this->assertEquals(5, $this->file->getBytesRead(), 5); $this->assertTrue($this->file->seek(2, SEEK_CUR)); $this->assertEquals('az', $this->file->readUntilEnd()); $this->assertEquals(7, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(0, SEEK_END)); $this->assertEquals('', $this->file->readUntilEnd()); $this->assertEquals(9, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(2, SEEK_END)); $this->assertEquals('', $this->file->readUntilEnd()); $this->assertEquals(11, $this->file->getBytesRead()); } /** * @test * @since 1.6.5 */ public function seekFileBeforeBeginningDoesNotChangeOffset() { $this->file->setContent('foobarbaz'); $this->assertFalse($this->file->seek(-5, SEEK_SET), 'Seek before beginning of file'); $this->assertEquals(0, $this->file->getBytesRead()); $this->assertTrue($this->file->seek(2, SEEK_CUR)); $this->assertFalse($this->file->seek(-5, SEEK_SET), 'Seek before beginning of file'); $this->assertEquals(2, $this->file->getBytesRead()); $this->assertEquals('obarbaz', $this->file->readUntilEnd()); $this->assertFalse($this->file->seek(-5, SEEK_CUR), 'Seek before beginning of file'); $this->assertEquals(2, $this->file->getBytesRead()); $this->assertEquals('obarbaz', $this->file->readUntilEnd()); $this->assertFalse($this->file->seek(-20, SEEK_END), 'Seek before beginning of file'); $this->assertEquals(2, $this->file->getBytesRead()); $this->assertEquals('obarbaz', $this->file->readUntilEnd()); } /** * test writing data into the file * * @test */ public function writeEmptyFile() { $this->assertEquals(3, $this->file->write('foo')); $this->assertEquals('foo', $this->file->getContent()); $this->assertEquals(3, $this->file->size()); $this->assertEquals(3, $this->file->write('bar')); $this->assertEquals('foobar', $this->file->getContent()); $this->assertEquals(6, $this->file->size()); } /** * test writing data into the file * * @test */ public function write() { $this->file->setContent('foobarbaz'); $this->assertTrue($this->file->seek(3, SEEK_SET)); $this->assertEquals(3, $this->file->write('foo')); $this->assertEquals('foofoobaz', $this->file->getContent()); $this->assertEquals(9, $this->file->size()); $this->assertEquals(3, $this->file->write('bar')); $this->assertEquals('foofoobar', $this->file->getContent()); $this->assertEquals(9, $this->file->size()); } /** * setting and retrieving permissions for a file * * @test * @group permissions */ public function permissions() { $this->assertEquals(0666, $this->file->getPermissions()); $this->assertSame($this->file, $this->file->chmod(0644)); $this->assertEquals(0644, $this->file->getPermissions()); } /** * setting and retrieving permissions for a file * * @test * @group permissions */ public function permissionsSet() { $this->file = new vfsStreamFile('foo', 0644); $this->assertEquals(0644, $this->file->getPermissions()); $this->assertSame($this->file, $this->file->chmod(0600)); $this->assertEquals(0600, $this->file->getPermissions()); } /** * setting and retrieving owner of a file * * @test * @group permissions */ public function owner() { $this->assertEquals(vfsStream::getCurrentUser(), $this->file->getUser()); $this->assertTrue($this->file->isOwnedByUser(vfsStream::getCurrentUser())); $this->assertSame($this->file, $this->file->chown(vfsStream::OWNER_USER_1)); $this->assertEquals(vfsStream::OWNER_USER_1, $this->file->getUser()); $this->assertTrue($this->file->isOwnedByUser(vfsStream::OWNER_USER_1)); } /** * setting and retrieving owner group of a file * * @test * @group permissions */ public function group() { $this->assertEquals(vfsStream::getCurrentGroup(), $this->file->getGroup()); $this->assertTrue($this->file->isOwnedByGroup(vfsStream::getCurrentGroup())); $this->assertSame($this->file, $this->file->chgrp(vfsStream::GROUP_USER_1)); $this->assertEquals(vfsStream::GROUP_USER_1, $this->file->getGroup()); $this->assertTrue($this->file->isOwnedByGroup(vfsStream::GROUP_USER_1)); } /** * @test * @group issue_33 * @since 1.1.0 */ public function truncateRemovesSuperflouosContent() { $this->assertEquals(11, $this->file->write("lorem ipsum")); $this->assertTrue($this->file->truncate(5)); $this->assertEquals(5, $this->file->size()); $this->assertEquals('lorem', $this->file->getContent()); } /** * @test * @group issue_33 * @since 1.1.0 */ public function truncateToGreaterSizeAddsZeroBytes() { $this->assertEquals(11, $this->file->write("lorem ipsum")); $this->assertTrue($this->file->truncate(25)); $this->assertEquals(25, $this->file->size()); $this->assertEquals("lorem ipsum\0\0\0\0\0\0\0\0\0\0\0\0\0\0", $this->file->getContent()); } /** * @test * @group issue_79 * @since 1.3.0 */ public function withContentAcceptsAnyFileContentInstance() { $mockFileContent = $this->bc_getMock('org\bovigo\vfs\content\FileContent'); $mockFileContent->expects($this->once()) ->method('content') ->will($this->returnValue('foobarbaz')); $this->assertEquals( 'foobarbaz', $this->file->withContent($mockFileContent) ->getContent() ); } /** * @test * @group issue_79 * @since 1.3.0 */ public function withContentThrowsInvalidArgumentExceptionWhenContentIsNoStringAndNoFileContent() { $this->expectException(\InvalidArgumentException::class); $this->file->withContent(313); } } assertEmpty(glob(vfsStream::url('example'), GLOB_MARK)); } } backupIncludePath = get_include_path(); vfsStream::setup(); mkdir('vfs://root/a/path', 0777, true); set_include_path('vfs://root/a' . PATH_SEPARATOR . $this->backupIncludePath); } /** * clean up test environment */ public function tearDown(): void { set_include_path($this->backupIncludePath); } /** * @test */ public function knownFileCanBeResolved() { file_put_contents('vfs://root/a/path/knownFile.php', ''); $this->assertEquals('vfs://root/a/path/knownFile.php', stream_resolve_include_path('path/knownFile.php')); } /** * @test */ public function unknownFileCanNotBeResolvedYieldsFalse() { $this->assertFalse(@stream_resolve_include_path('path/unknownFile.php')); } } assertEquals('vfs://foo', vfsStream::url('foo')); $this->assertEquals('vfs://foo/bar.baz', vfsStream::url('foo/bar.baz')); $this->assertEquals('vfs://foo/bar.baz', vfsStream::url('foo\bar.baz')); } /** * assure that url2path conversion works correct * * @test */ public function path() { $this->assertEquals('foo', vfsStream::path('vfs://foo')); $this->assertEquals('foo/bar.baz', vfsStream::path('vfs://foo/bar.baz')); $this->assertEquals('foo/bar.baz', vfsStream::path('vfs://foo\bar.baz')); } /** * windows directory separators are converted into default separator * * @author Gabriel Birke * @test */ public function pathConvertsWindowsDirectorySeparators() { $this->assertEquals('foo/bar', vfsStream::path('vfs://foo\\bar')); } /** * trailing whitespace should be removed * * @author Gabriel Birke * @test */ public function pathRemovesTrailingWhitespace() { $this->assertEquals('foo/bar', vfsStream::path('vfs://foo/bar ')); } /** * trailing slashes are removed * * @author Gabriel Birke * @test */ public function pathRemovesTrailingSlash() { $this->assertEquals('foo/bar', vfsStream::path('vfs://foo/bar/')); } /** * trailing slash and whitespace should be removed * * @author Gabriel Birke * @test */ public function pathRemovesTrailingSlashAndWhitespace() { $this->assertEquals('foo/bar', vfsStream::path('vfs://foo/bar/ ')); } /** * double slashes should be replaced by single slash * * @author Gabriel Birke * @test */ public function pathRemovesDoubleSlashes() { // Regular path $this->assertEquals('my/path', vfsStream::path('vfs://my/path')); // Path with double slashes $this->assertEquals('my/path', vfsStream::path('vfs://my//path')); } /** * test to create a new file * * @test */ public function newFile() { $file = vfsStream::newFile('filename.txt'); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamFile', $file); $this->assertEquals('filename.txt', $file->getName()); $this->assertEquals(0666, $file->getPermissions()); } /** * test to create a new file with non-default permissions * * @test * @group permissions */ public function newFileWithDifferentPermissions() { $file = vfsStream::newFile('filename.txt', 0644); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamFile', $file); $this->assertEquals('filename.txt', $file->getName()); $this->assertEquals(0644, $file->getPermissions()); } /** * test to create a new directory structure * * @test */ public function newSingleDirectory() { $foo = vfsStream::newDirectory('foo'); $this->assertEquals('foo', $foo->getName()); $this->assertEquals(0, count($foo->getChildren())); $this->assertEquals(0777, $foo->getPermissions()); } /** * test to create a new directory structure with non-default permissions * * @test * @group permissions */ public function newSingleDirectoryWithDifferentPermissions() { $foo = vfsStream::newDirectory('foo', 0755); $this->assertEquals('foo', $foo->getName()); $this->assertEquals(0, count($foo->getChildren())); $this->assertEquals(0755, $foo->getPermissions()); } /** * test to create a new directory structure * * @test */ public function newDirectoryStructure() { $foo = vfsStream::newDirectory('foo/bar/baz'); $this->assertEquals('foo', $foo->getName()); $this->assertEquals(0777, $foo->getPermissions()); $this->assertTrue($foo->hasChild('bar')); $this->assertTrue($foo->hasChild('bar/baz')); $this->assertFalse($foo->hasChild('baz')); $bar = $foo->getChild('bar'); $this->assertEquals('bar', $bar->getName()); $this->assertEquals(0777, $bar->getPermissions()); $this->assertTrue($bar->hasChild('baz')); $baz1 = $bar->getChild('baz'); $this->assertEquals('baz', $baz1->getName()); $this->assertEquals(0777, $baz1->getPermissions()); $baz2 = $foo->getChild('bar/baz'); $this->assertSame($baz1, $baz2); } /** * test that correct directory structure is created * * @test */ public function newDirectoryWithSlashAtStart() { $foo = vfsStream::newDirectory('/foo/bar/baz', 0755); $this->assertEquals('foo', $foo->getName()); $this->assertEquals(0755, $foo->getPermissions()); $this->assertTrue($foo->hasChild('bar')); $this->assertTrue($foo->hasChild('bar/baz')); $this->assertFalse($foo->hasChild('baz')); $bar = $foo->getChild('bar'); $this->assertEquals('bar', $bar->getName()); $this->assertEquals(0755, $bar->getPermissions()); $this->assertTrue($bar->hasChild('baz')); $baz1 = $bar->getChild('baz'); $this->assertEquals('baz', $baz1->getName()); $this->assertEquals(0755, $baz1->getPermissions()); $baz2 = $foo->getChild('bar/baz'); $this->assertSame($baz1, $baz2); } /** * @test * @group setup * @since 0.7.0 */ public function setupRegistersStreamWrapperAndCreatesRootDirectoryWithDefaultNameAndPermissions() { $root = vfsStream::setup(); $this->assertSame($root, vfsStreamWrapper::getRoot()); $this->assertEquals('root', $root->getName()); $this->assertEquals(0777, $root->getPermissions()); } /** * @test * @group setup * @since 0.7.0 */ public function setupRegistersStreamWrapperAndCreatesRootDirectoryWithGivenNameAndDefaultPermissions() { $root = vfsStream::setup('foo'); $this->assertSame($root, vfsStreamWrapper::getRoot()); $this->assertEquals('foo', $root->getName()); $this->assertEquals(0777, $root->getPermissions()); } /** * @test * @group setup * @since 0.7.0 */ public function setupRegistersStreamWrapperAndCreatesRootDirectoryWithGivenNameAndPermissions() { $root = vfsStream::setup('foo', 0444); $this->assertSame($root, vfsStreamWrapper::getRoot()); $this->assertEquals('foo', $root->getName()); $this->assertEquals(0444, $root->getPermissions()); } /** * @test * @group issue_14 * @group issue_20 * @since 0.10.0 */ public function setupWithEmptyArrayIsEqualToSetup() { $root = vfsStream::setup('example', 0755, array() ); $this->assertEquals('example', $root->getName()); $this->assertEquals(0755, $root->getPermissions()); $this->assertFalse($root->hasChildren()); } /** * @test * @group issue_14 * @group issue_20 * @since 0.10.0 */ public function setupArraysAreTurnedIntoSubdirectories() { $root = vfsStream::setup('root', null, array('test' => array()) ); $this->assertTrue($root->hasChildren()); $this->assertTrue($root->hasChild('test')); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $root->getChild('test') ); $this->assertFalse($root->getChild('test')->hasChildren()); } /** * @test * @group issue_14 * @group issue_20 * @since 0.10.0 */ public function setupStringsAreTurnedIntoFilesWithContent() { $root = vfsStream::setup('root', null, array('test.txt' => 'some content') ); $this->assertTrue($root->hasChildren()); $this->assertTrue($root->hasChild('test.txt')); $this->assertVfsFile($root->getChild('test.txt'), 'some content'); } /** * @test * @group issue_14 * @group issue_20 * @since 0.10.0 */ public function setupWorksRecursively() { $root = vfsStream::setup('root', null, array('test' => array('foo' => array('test.txt' => 'hello'), 'baz.txt' => 'world' ) ) ); $this->assertTrue($root->hasChildren()); $this->assertTrue($root->hasChild('test')); $test = $root->getChild('test'); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $test); $this->assertTrue($test->hasChildren()); $this->assertTrue($test->hasChild('baz.txt')); $this->assertVfsFile($test->getChild('baz.txt'), 'world'); $this->assertTrue($test->hasChild('foo')); $foo = $test->getChild('foo'); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $foo); $this->assertTrue($foo->hasChildren()); $this->assertTrue($foo->hasChild('test.txt')); $this->assertVfsFile($foo->getChild('test.txt'), 'hello'); } /** * @test * @group issue_17 * @group issue_20 */ public function setupCastsNumericDirectoriesToStrings() { $root = vfsStream::setup('root', null, array(2011 => array ('test.txt' => 'some content')) ); $this->assertTrue($root->hasChild('2011')); $directory = $root->getChild('2011'); $this->assertVfsFile($directory->getChild('test.txt'), 'some content'); $this->assertTrue(file_exists('vfs://root/2011/test.txt')); } /** * @test * @group issue_20 * @since 0.11.0 */ public function createArraysAreTurnedIntoSubdirectories() { $baseDir = vfsStream::create(array('test' => array()), new vfsStreamDirectory('baseDir')); $this->assertTrue($baseDir->hasChildren()); $this->assertTrue($baseDir->hasChild('test')); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $baseDir->getChild('test') ); $this->assertFalse($baseDir->getChild('test')->hasChildren()); } /** * @test * @group issue_20 * @since 0.11.0 */ public function createArraysAreTurnedIntoSubdirectoriesOfRoot() { $root = vfsStream::setup(); $this->assertSame($root, vfsStream::create(array('test' => array()))); $this->assertTrue($root->hasChildren()); $this->assertTrue($root->hasChild('test')); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $root->getChild('test') ); $this->assertFalse($root->getChild('test')->hasChildren()); } /** * @test * @group issue_20 * @since 0.11.0 */ public function createThrowsExceptionIfNoBaseDirGivenAndNoRootSet() { $this->expectException(\InvalidArgumentException::class); vfsStream::create(array('test' => array())); } /** * @test * @group issue_20 * @since 0.11.0 */ public function createWorksRecursively() { $baseDir = vfsStream::create(array('test' => array('foo' => array('test.txt' => 'hello'), 'baz.txt' => 'world' ) ), new vfsStreamDirectory('baseDir') ); $this->assertTrue($baseDir->hasChildren()); $this->assertTrue($baseDir->hasChild('test')); $test = $baseDir->getChild('test'); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $test); $this->assertTrue($test->hasChildren()); $this->assertTrue($test->hasChild('baz.txt')); $this->assertVfsFile($test->getChild('baz.txt'), 'world'); $this->assertTrue($test->hasChild('foo')); $foo = $test->getChild('foo'); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $foo); $this->assertTrue($foo->hasChildren()); $this->assertTrue($foo->hasChild('test.txt')); $this->assertVfsFile($foo->getChild('test.txt'), 'hello'); } /** * @test * @group issue_20 * @since 0.11.0 */ public function createWorksRecursivelyWithRoot() { $root = vfsStream::setup(); $this->assertSame($root, vfsStream::create(array('test' => array('foo' => array('test.txt' => 'hello'), 'baz.txt' => 'world' ) ) ) ); $this->assertTrue($root->hasChildren()); $this->assertTrue($root->hasChild('test')); $test = $root->getChild('test'); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $test); $this->assertTrue($test->hasChildren()); $this->assertTrue($test->hasChild('baz.txt')); $this->assertVfsFile($test->getChild('baz.txt'), 'world'); $this->assertTrue($test->hasChild('foo')); $foo = $test->getChild('foo'); $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $foo); $this->assertTrue($foo->hasChildren()); $this->assertTrue($foo->hasChild('test.txt')); $this->assertVfsFile($foo->getChild('test.txt'), 'hello'); } /** * @test * @group issue_20 * @since 0.10.0 */ public function createStringsAreTurnedIntoFilesWithContent() { $baseDir = vfsStream::create(array('test.txt' => 'some content'), new vfsStreamDirectory('baseDir')); $this->assertTrue($baseDir->hasChildren()); $this->assertTrue($baseDir->hasChild('test.txt')); $this->assertVfsFile($baseDir->getChild('test.txt'), 'some content'); } /** * @test * @group issue_20 * @since 0.11.0 */ public function createStringsAreTurnedIntoFilesWithContentWithRoot() { $root = vfsStream::setup(); $this->assertSame($root, vfsStream::create(array('test.txt' => 'some content')) ); $this->assertTrue($root->hasChildren()); $this->assertTrue($root->hasChild('test.txt')); $this->assertVfsFile($root->getChild('test.txt'), 'some content'); } /** * @test * @group issue_20 * @since 0.11.0 */ public function createCastsNumericDirectoriesToStrings() { $baseDir = vfsStream::create(array(2011 => array ('test.txt' => 'some content')), new vfsStreamDirectory('baseDir')); $this->assertTrue($baseDir->hasChild('2011')); $directory = $baseDir->getChild('2011'); $this->assertVfsFile($directory->getChild('test.txt'), 'some content'); } /** * @test * @group issue_20 * @since 0.11.0 */ public function createCastsNumericDirectoriesToStringsWithRoot() { $root = vfsStream::setup(); $this->assertSame($root, vfsStream::create(array(2011 => array ('test.txt' => 'some content'))) ); $this->assertTrue($root->hasChild('2011')); $directory = $root->getChild('2011'); $this->assertVfsFile($directory->getChild('test.txt'), 'some content'); } /** * helper function for assertions on vfsStreamFile * * @param vfsStreamFile $file * @param string $content */ protected function assertVfsFile(vfsStreamFile $file, $content) { $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamFile', $file ); $this->assertEquals($content, $file->getContent() ); } /** * @test * @group issue_10 * @since 0.10.0 */ public function inspectWithContentGivesContentToVisitor() { $mockContent = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $mockVisitor = $this->bc_getMock('org\\bovigo\\vfs\\visitor\\vfsStreamVisitor'); $mockVisitor->expects($this->once()) ->method('visit') ->with($this->equalTo($mockContent)) ->will($this->returnValue($mockVisitor)); $this->assertSame($mockVisitor, vfsStream::inspect($mockVisitor, $mockContent)); } /** * @test * @group issue_10 * @since 0.10.0 */ public function inspectWithoutContentGivesRootToVisitor() { $root = vfsStream::setup(); $mockVisitor = $this->bc_getMock('org\\bovigo\\vfs\\visitor\\vfsStreamVisitor'); $mockVisitor->expects($this->once()) ->method('visitDirectory') ->with($this->equalTo($root)) ->will($this->returnValue($mockVisitor)); $this->assertSame($mockVisitor, vfsStream::inspect($mockVisitor)); } /** * @test * @group issue_10 * @since 0.10.0 */ public function inspectWithoutContentAndWithoutRootThrowsInvalidArgumentException() { $this->expectException(\InvalidArgumentException::class); $mockVisitor = $this->bc_getMock('org\\bovigo\\vfs\\visitor\\vfsStreamVisitor'); $mockVisitor->expects($this->never()) ->method('visit'); $mockVisitor->expects($this->never()) ->method('visitDirectory'); vfsStream::inspect($mockVisitor); } /** * returns path to file system copy resource directory * * @return string */ protected function getFileSystemCopyDir() { return realpath(dirname(__FILE__) . '/../../../../resources/filesystemcopy'); } /** * @test * @group issue_4 * @since 0.11.0 */ public function copyFromFileSystemThrowsExceptionIfNoBaseDirGivenAndNoRootSet() { $this->expectException(\InvalidArgumentException::class); vfsStream::copyFromFileSystem($this->getFileSystemCopyDir()); } /** * @test * @group issue_4 * @since 0.11.0 */ public function copyFromEmptyFolder() { $baseDir = vfsStream::copyFromFileSystem($this->getFileSystemCopyDir() . '/emptyFolder', vfsStream::newDirectory('test') ); $baseDir->removeChild('.gitignore'); $this->assertFalse($baseDir->hasChildren()); } /** * @test * @group issue_4 * @since 0.11.0 */ public function copyFromEmptyFolderWithRoot() { $root = vfsStream::setup(); $this->assertEquals($root, vfsStream::copyFromFileSystem($this->getFileSystemCopyDir() . '/emptyFolder') ); $root->removeChild('.gitignore'); $this->assertFalse($root->hasChildren()); } /** * @test * @group issue_4 * @since 0.11.0 */ public function copyFromWithSubFolders() { $baseDir = vfsStream::copyFromFileSystem($this->getFileSystemCopyDir(), vfsStream::newDirectory('test'), 3 ); $this->assertTrue($baseDir->hasChildren()); $this->assertTrue($baseDir->hasChild('emptyFolder')); $this->assertTrue($baseDir->hasChild('withSubfolders')); $subfolderDir = $baseDir->getChild('withSubfolders'); $this->assertTrue($subfolderDir->hasChild('subfolder1')); $this->assertTrue($subfolderDir->getChild('subfolder1')->hasChild('file1.txt')); $this->assertVfsFile($subfolderDir->getChild('subfolder1/file1.txt'), ' '); $this->assertTrue($subfolderDir->hasChild('subfolder2')); $this->assertTrue($subfolderDir->hasChild('aFile.txt')); $this->assertVfsFile($subfolderDir->getChild('aFile.txt'), 'foo'); } /** * @test * @group issue_4 * @since 0.11.0 */ public function copyFromWithSubFoldersWithRoot() { $root = vfsStream::setup(); $this->assertEquals($root, vfsStream::copyFromFileSystem($this->getFileSystemCopyDir(), null, 3 ) ); $this->assertTrue($root->hasChildren()); $this->assertTrue($root->hasChild('emptyFolder')); $this->assertTrue($root->hasChild('withSubfolders')); $subfolderDir = $root->getChild('withSubfolders'); $this->assertTrue($subfolderDir->hasChild('subfolder1')); $this->assertTrue($subfolderDir->getChild('subfolder1')->hasChild('file1.txt')); $this->assertVfsFile($subfolderDir->getChild('subfolder1/file1.txt'), ' '); $this->assertTrue($subfolderDir->hasChild('subfolder2')); $this->assertTrue($subfolderDir->hasChild('aFile.txt')); $this->assertVfsFile($subfolderDir->getChild('aFile.txt'), 'foo'); } /** * @test * @group issue_4 * @group issue_29 * @since 0.11.2 */ public function copyFromPreservesFilePermissions() { if (DIRECTORY_SEPARATOR !== '/') { $this->markTestSkipped('Only applicable on Linux style systems.'); } $copyDir = $this->getFileSystemCopyDir(); $root = vfsStream::setup(); $this->assertEquals($root, vfsStream::copyFromFileSystem($copyDir, null ) ); $this->assertEquals(fileperms($copyDir . '/withSubfolders') - vfsStreamContent::TYPE_DIR, $root->getChild('withSubfolders') ->getPermissions() ); $this->assertEquals(fileperms($copyDir . '/withSubfolders/aFile.txt') - vfsStreamContent::TYPE_FILE, $root->getChild('withSubfolders/aFile.txt') ->getPermissions() ); } /** * To test this the max file size is reduced to something reproduceable. * * @test * @group issue_91 * @since 1.5.0 */ public function copyFromFileSystemMocksLargeFiles() { if (DIRECTORY_SEPARATOR !== '/') { $this->markTestSkipped('Only applicable on Linux style systems.'); } $copyDir = $this->getFileSystemCopyDir(); $root = vfsStream::setup(); vfsStream::copyFromFileSystem($copyDir, $root, 3); $this->assertEquals( ' ', $root->getChild('withSubfolders/subfolder1/file1.txt')->getContent() ); } /** * @test * @group issue_121 * @since 1.6.1 */ public function createDirectoryWithTrailingSlashShouldNotCreateSubdirectoryWithEmptyName() { $directory = vfsStream::newDirectory('foo/'); $this->assertFalse($directory->hasChildren()); } /** * @test * @group issue_149 */ public function addStructureHandlesVfsStreamFileObjects() { $structure = array( 'topLevel' => array( 'thisIsAFile' => 'file contents', vfsStream::newFile('anotherFile'), ), ); vfsStream::setup(); $root = vfsStream::create($structure); $this->assertTrue($root->hasChild('topLevel/anotherFile')); } /** * @test * @group issue_149 */ public function createHandlesLargeFileContentObjects() { $structure = array( 'topLevel' => array( 'thisIsAFile' => 'file contents', 'anotherFile' => LargeFileContent::withMegabytes(2), ), ); vfsStream::setup(); $root = vfsStream::create($structure); $this->assertTrue($root->hasChild('topLevel/anotherFile')); } } assertEquals(vfsStream::umask(), vfsStream::umask() ); $this->assertEquals(0000, vfsStream::umask() ); } /** * @test */ public function changingUmaskSettingReturnsOldUmaskSetting() { $this->assertEquals(0000, vfsStream::umask(0022) ); $this->assertEquals(0022, vfsStream::umask() ); } /** * @test */ public function createFileWithDefaultUmaskSetting() { $file = new vfsStreamFile('foo'); $this->assertEquals(0666, $file->getPermissions()); } /** * @test */ public function createFileWithDifferentUmaskSetting() { vfsStream::umask(0022); $file = new vfsStreamFile('foo'); $this->assertEquals(0644, $file->getPermissions()); } /** * @test */ public function createDirectoryWithDefaultUmaskSetting() { $directory = new vfsStreamDirectory('foo'); $this->assertEquals(0777, $directory->getPermissions()); } /** * @test */ public function createDirectoryWithDifferentUmaskSetting() { vfsStream::umask(0022); $directory = new vfsStreamDirectory('foo'); $this->assertEquals(0755, $directory->getPermissions()); } /** * @test */ public function createFileUsingStreamWithDefaultUmaskSetting() { $root = vfsStream::setup(); file_put_contents(vfsStream::url('root/newfile.txt'), 'file content'); $this->assertEquals(0666, $root->getChild('newfile.txt')->getPermissions()); } /** * @test */ public function createFileUsingStreamWithDifferentUmaskSetting() { $root = vfsStream::setup(); vfsStream::umask(0022); file_put_contents(vfsStream::url('root/newfile.txt'), 'file content'); $this->assertEquals(0644, $root->getChild('newfile.txt')->getPermissions()); } /** * @test */ public function createDirectoryUsingStreamWithDefaultUmaskSetting() { $root = vfsStream::setup(); mkdir(vfsStream::url('root/newdir')); $this->assertEquals(0777, $root->getChild('newdir')->getPermissions()); } /** * @test */ public function createDirectoryUsingStreamWithDifferentUmaskSetting() { $root = vfsStream::setup(); vfsStream::umask(0022); mkdir(vfsStream::url('root/newdir')); $this->assertEquals(0755, $root->getChild('newdir')->getPermissions()); } /** * @test */ public function createDirectoryUsingStreamWithExplicit0() { $root = vfsStream::setup(); vfsStream::umask(0022); mkdir(vfsStream::url('root/newdir'), 0000); $this->assertEquals(0000, $root->getChild('newdir')->getPermissions()); } /** * @test * */ public function createDirectoryUsingStreamWithDifferentUmaskSettingButExplicit0777() { $root = vfsStream::setup(); vfsStream::umask(0022); mkdir(vfsStream::url('root/newdir'), 0777); $this->assertEquals(0755, $root->getChild('newdir')->getPermissions()); } /** * @test */ public function createDirectoryUsingStreamWithDifferentUmaskSettingButExplicitModeRequestedByCall() { $root = vfsStream::setup(); vfsStream::umask(0022); mkdir(vfsStream::url('root/newdir'), 0700); $this->assertEquals(0700, $root->getChild('newdir')->getPermissions()); } /** * @test */ public function defaultUmaskSettingDoesNotInfluenceSetup() { $root = vfsStream::setup(); $this->assertEquals(0777, $root->getPermissions()); } /** * @test */ public function umaskSettingShouldBeRespectedBySetup() { vfsStream::umask(0022); $root = vfsStream::setup(); $this->assertEquals(0755, $root->getPermissions()); } } bc_getMock('org\\bovigo\\vfs\\vfsStreamWrapper'); stream_wrapper_register(vfsStream::SCHEME, get_class($mock)); } /** * clean up test environment */ public function tearDown(): void { TestvfsStreamWrapper::unregister(); } /** * registering the stream wrapper when another stream wrapper is already * registered for the vfs scheme should throw an exception * * @test */ public function registerOverAnotherStreamWrapper() { $this->expectException(vfsStreamException::class); vfsStreamWrapper::register(); } } fooURL = vfsStream::url('foo'); $this->barURL = vfsStream::url('foo/bar'); $this->baz1URL = vfsStream::url('foo/bar/baz1'); $this->baz2URL = vfsStream::url('foo/baz2'); $this->foo = new vfsStreamDirectory('foo'); $this->bar = new vfsStreamDirectory('bar'); $this->baz1 = vfsStream::newFile('baz1') ->lastModified(300) ->lastAccessed(300) ->lastAttributeModified(300) ->withContent('baz 1'); $this->baz2 = vfsStream::newFile('baz2') ->withContent('baz2') ->lastModified(400) ->lastAccessed(400) ->lastAttributeModified(400); $this->bar->addChild($this->baz1); $this->foo->addChild($this->bar); $this->foo->addChild($this->baz2); $this->foo->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); $this->bar->lastModified(200) ->lastAccessed(100) ->lastAttributeModified(100); vfsStreamWrapper::register(); vfsStreamWrapper::setRoot($this->foo); } } root = vfsStream::setup(); } /** * @test */ public function fileCanBeAccessedUsingWinDirSeparator() { vfsStream::newFile('foo/bar/baz.txt') ->at($this->root) ->withContent('test'); $this->assertEquals('test', file_get_contents('vfs://root/foo\bar\baz.txt')); } /** * @test */ public function directoryCanBeCreatedUsingWinDirSeparator() { mkdir('vfs://root/dir\bar\foo', true, 0777); $this->assertTrue($this->root->hasChild('dir')); $this->assertTrue($this->root->getChild('dir')->hasChild('bar')); $this->assertTrue($this->root->getChild('dir/bar')->hasChild('foo')); } /** * @test */ public function directoryExitsTestUsingTrailingWinDirSeparator() { $structure = array( 'dir' => array( 'bar' => array( ) ) ); vfsStream::create($structure, $this->root); $this->assertTrue(file_exists(vfsStream::url('root/').'dir\\')); } } assertFalse(mkdir(vfsStream::url('another'))); $this->assertEquals(2, count($this->foo->getChildren())); $this->assertSame($this->foo, vfsStreamWrapper::getRoot()); } /** * mkdir() should not overwrite existing root * * @test */ public function mkdirNoNewRootRecursively() { $this->assertFalse(mkdir(vfsStream::url('another/more'), 0777, true)); $this->assertEquals(2, count($this->foo->getChildren())); $this->assertSame($this->foo, vfsStreamWrapper::getRoot()); } /** * assert that mkdir() creates the correct directory structure * * @test * @group permissions */ public function mkdirNonRecursively() { $this->assertFalse(mkdir($this->barURL . '/another/more')); $this->assertEquals(2, count($this->foo->getChildren())); $this->assertTrue(mkdir($this->fooURL . '/another')); $this->assertEquals(3, count($this->foo->getChildren())); $this->assertEquals(0777, $this->foo->getChild('another')->getPermissions()); } /** * assert that mkdir() creates the correct directory structure * * @test * @group permissions */ public function mkdirRecursively() { $this->assertTrue(mkdir($this->fooURL . '/another/more', 0777, true)); $this->assertEquals(3, count($this->foo->getChildren())); $another = $this->foo->getChild('another'); $this->assertTrue($another->hasChild('more')); $this->assertEquals(0777, $this->foo->getChild('another')->getPermissions()); $this->assertEquals(0777, $this->foo->getChild('another')->getChild('more')->getPermissions()); } /** * @test * @group issue_9 * @since 0.9.0 */ public function mkdirWithDots() { $this->assertTrue(mkdir($this->fooURL . '/another/../more/.', 0777, true)); $this->assertEquals(3, count($this->foo->getChildren())); $this->assertTrue($this->foo->hasChild('more')); } /** * no root > new directory becomes root * * @test * @group permissions */ public function mkdirWithoutRootCreatesNewRoot() { vfsStreamWrapper::register(); $this->assertTrue(@mkdir(vfsStream::url('foo'))); $this->assertEquals(vfsStreamContent::TYPE_DIR, vfsStreamWrapper::getRoot()->getType()); $this->assertEquals('foo', vfsStreamWrapper::getRoot()->getName()); $this->assertEquals(0777, vfsStreamWrapper::getRoot()->getPermissions()); } /** * trying to create a subdirectory of a file should not work * * @test */ public function mkdirOnFileReturnsFalse() { $this->assertFalse(mkdir($this->baz1URL . '/another/more', 0777, true)); } /** * assert that mkdir() creates the correct directory structure * * @test * @group permissions */ public function mkdirNonRecursivelyDifferentPermissions() { $this->assertTrue(mkdir($this->fooURL . '/another', 0755)); $this->assertEquals(0755, $this->foo->getChild('another')->getPermissions()); } /** * assert that mkdir() creates the correct directory structure * * @test * @group permissions */ public function mkdirRecursivelyDifferentPermissions() { $this->assertTrue(mkdir($this->fooURL . '/another/more', 0755, true)); $this->assertEquals(3, count($this->foo->getChildren())); $another = $this->foo->getChild('another'); $this->assertTrue($another->hasChild('more')); $this->assertEquals(0755, $this->foo->getChild('another')->getPermissions()); $this->assertEquals(0755, $this->foo->getChild('another')->getChild('more')->getPermissions()); } /** * assert that mkdir() creates the correct directory structure * * @test * @group permissions */ public function mkdirRecursivelyUsesDefaultPermissions() { $this->foo->chmod(0700); $this->assertTrue(mkdir($this->fooURL . '/another/more', 0777, true)); $this->assertEquals(3, count($this->foo->getChildren())); $another = $this->foo->getChild('another'); $this->assertTrue($another->hasChild('more')); $this->assertEquals(0777, $this->foo->getChild('another')->getPermissions()); $this->assertEquals(0777, $this->foo->getChild('another')->getChild('more')->getPermissions()); } /** * no root > new directory becomes root * * @test * @group permissions */ public function mkdirWithoutRootCreatesNewRootDifferentPermissions() { vfsStreamWrapper::register(); $this->assertTrue(@mkdir(vfsStream::url('foo'), 0755)); $this->assertEquals(vfsStreamContent::TYPE_DIR, vfsStreamWrapper::getRoot()->getType()); $this->assertEquals('foo', vfsStreamWrapper::getRoot()->getName()); $this->assertEquals(0755, vfsStreamWrapper::getRoot()->getPermissions()); } /** * no root > new directory becomes root * * @test * @group permissions */ public function mkdirWithoutRootCreatesNewRootWithDefaultPermissions() { vfsStreamWrapper::register(); $this->assertTrue(@mkdir(vfsStream::url('foo'))); $this->assertEquals(vfsStreamContent::TYPE_DIR, vfsStreamWrapper::getRoot()->getType()); $this->assertEquals('foo', vfsStreamWrapper::getRoot()->getName()); $this->assertEquals(0777, vfsStreamWrapper::getRoot()->getPermissions()); } /** * @test * @group permissions * @group bug_15 */ public function mkdirDirCanNotCreateNewDirInNonWritingDirectory() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('root')); vfsStreamWrapper::getRoot()->addChild(new vfsStreamDirectory('restrictedFolder', 0000)); $this->assertFalse(is_writable(vfsStream::url('root/restrictedFolder/'))); $this->assertFalse(mkdir(vfsStream::url('root/restrictedFolder/newFolder'))); $this->assertFalse(vfsStreamWrapper::getRoot()->hasChild('restrictedFolder/newFolder')); } /** * @test * @group issue_28 */ public function mkDirShouldNotOverwriteExistingDirectories() { vfsStream::setup('root'); $dir = vfsStream::url('root/dir'); $this->assertTrue(mkdir($dir)); $this->assertFalse(@mkdir($dir)); } /** * @test * @group issue_28 */ public function mkDirShouldNotOverwriteExistingDirectoriesAndTriggerE_USER_WARNING() { $this->expectException(Error\Warning::class); $this->expectExceptionMessage('mkdir(): Path vfs://root/dir exists'); vfsStream::setup('root'); $dir = vfsStream::url('root/dir'); $this->assertTrue(mkdir($dir)); $this->assertFalse(mkdir($dir)); } /** * @test * @group issue_28 */ public function mkDirShouldNotOverwriteExistingFiles() { $root = vfsStream::setup('root'); vfsStream::newFile('test.txt')->at($root); $this->assertFalse(@mkdir(vfsStream::url('root/test.txt'))); } /** * @test * @group issue_28 */ public function mkDirShouldNotOverwriteExistingFilesAndTriggerE_USER_WARNING() { $this->expectException(Error\Warning::class); $this->expectExceptionMessage('mkdir(): Path vfs://root/test.txt exists'); $root = vfsStream::setup('root'); vfsStream::newFile('test.txt')->at($root); $this->assertFalse(mkdir(vfsStream::url('root/test.txt'))); } /** * @test * @group issue_131 * @since 1.6.3 */ public function allowsRecursiveMkDirWithDirectoryName0() { vfsStream::setup('root'); $subdir = vfsStream::url('root/a/0'); mkdir($subdir, 0777, true); $this->assertFileExists($subdir); } /** * @test * @group permissions * @group bug_15 */ public function canNotIterateOverNonReadableDirectory() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); $this->assertFalse(@opendir(vfsStream::url('root'))); $this->assertFalse(@dir(vfsStream::url('root'))); } /** * assert is_dir() returns correct result * * @test */ public function is_dir() { $this->assertTrue(is_dir($this->fooURL)); $this->assertTrue(is_dir($this->fooURL . '/.')); $this->assertTrue(is_dir($this->barURL)); $this->assertTrue(is_dir($this->barURL . '/.')); $this->assertFalse(is_dir($this->baz1URL)); $this->assertFalse(is_dir($this->baz2URL)); $this->assertFalse(is_dir($this->fooURL . '/another')); $this->assertFalse(is_dir(vfsStream::url('another'))); } /** * can not unlink without root * * @test */ public function canNotUnlinkDirectoryWithoutRoot() { vfsStreamWrapper::register(); $this->assertFalse(@rmdir(vfsStream::url('foo'))); } /** * rmdir() can not remove files * * @test */ public function rmdirCanNotRemoveFiles() { $this->assertFalse(rmdir($this->baz1URL)); $this->assertFalse(rmdir($this->baz2URL)); } /** * rmdir() can not remove a non-existing directory * * @test */ public function rmdirCanNotRemoveNonExistingDirectory() { $this->assertFalse(rmdir($this->fooURL . '/another')); } /** * rmdir() can not remove non-empty directories * * @test */ public function rmdirCanNotRemoveNonEmptyDirectory() { $this->assertFalse(rmdir($this->fooURL)); $this->assertFalse(rmdir($this->barURL)); } /** * @test */ public function rmdirCanRemoveEmptyDirectory() { vfsStream::newDirectory('empty')->at($this->foo); $this->assertTrue($this->foo->hasChild('empty')); $this->assertTrue(rmdir($this->fooURL . '/empty')); $this->assertFalse($this->foo->hasChild('empty')); } /** * @test */ public function rmdirCanRemoveEmptyDirectoryWithDot() { vfsStream::newDirectory('empty')->at($this->foo); $this->assertTrue($this->foo->hasChild('empty')); $this->assertTrue(rmdir($this->fooURL . '/empty/.')); $this->assertFalse($this->foo->hasChild('empty')); } /** * rmdir() can remove empty directories * * @test */ public function rmdirCanRemoveEmptyRoot() { $this->foo->removeChild('bar'); $this->foo->removeChild('baz2'); $this->assertTrue(rmdir($this->fooURL)); $this->assertFalse(file_exists($this->fooURL)); // make sure statcache was cleared $this->assertNull(vfsStreamWrapper::getRoot()); } /** * @test * @group permissions * @group bug_15 */ public function rmdirDirCanNotRemoveDirFromNonWritingDirectory() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); vfsStreamWrapper::getRoot()->addChild(new vfsStreamDirectory('nonRemovableFolder')); $this->assertFalse(is_writable(vfsStream::url('root'))); $this->assertFalse(rmdir(vfsStream::url('root/nonRemovableFolder'))); $this->assertTrue(vfsStreamWrapper::getRoot()->hasChild('nonRemovableFolder')); } /** * @test * @group permissions * @group bug_17 */ public function issue17() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0770)); vfsStreamWrapper::getRoot()->chgrp(vfsStream::GROUP_USER_1) ->chown(vfsStream::OWNER_USER_1); $this->assertFalse(mkdir(vfsStream::url('root/doesNotWork'))); $this->assertFalse(vfsStreamWrapper::getRoot()->hasChild('doesNotWork')); } /** * @test * @group bug_19 */ public function accessWithDoubleDotReturnsCorrectContent() { $this->assertEquals('baz2', file_get_contents(vfsStream::url('foo/bar/../baz2')) ); } /** * @test * @group bug_115 */ public function accessWithExcessDoubleDotsReturnsCorrectContent() { $this->assertEquals('baz2', file_get_contents(vfsStream::url('foo/../../../../bar/../baz2')) ); } /** * @test * @group bug_115 */ public function alwaysResolvesRootDirectoryAsOwnParentWithDoubleDot() { vfsStreamWrapper::getRoot()->chown(vfsStream::OWNER_USER_1); $this->assertTrue(is_dir(vfsStream::url('foo/..'))); $stat = stat(vfsStream::url('foo/..')); $this->assertEquals( vfsStream::OWNER_USER_1, $stat['uid'] ); } /** * @test * @since 0.11.0 * @group issue_23 */ public function unlinkCanNotRemoveNonEmptyDirectory() { try { $this->assertFalse(unlink($this->barURL)); } catch (\PHPUnit_Framework_Error $fe) { $this->assertEquals('unlink(vfs://foo/bar): Operation not permitted', $fe->getMessage()); } $this->assertTrue($this->foo->hasChild('bar')); $this->assertFileExists($this->barURL); } /** * @test * @since 0.11.0 * @group issue_23 */ public function unlinkCanNotRemoveEmptyDirectory() { vfsStream::newDirectory('empty')->at($this->foo); try { $this->assertTrue(unlink($this->fooURL . '/empty')); } catch (\PHPUnit_Framework_Error $fe) { $this->assertEquals('unlink(vfs://foo/empty): Operation not permitted', $fe->getMessage()); } $this->assertTrue($this->foo->hasChild('empty')); $this->assertFileExists($this->fooURL . '/empty'); } /** * @test * @group issue_32 */ public function canCreateFolderOfSameNameAsParentFolder() { $root = vfsStream::setup('testFolder'); mkdir(vfsStream::url('testFolder') . '/testFolder/subTestFolder', 0777, true); $this->assertTrue(file_exists(vfsStream::url('testFolder/testFolder/subTestFolder/.'))); } /** * @test * @group issue_32 */ public function canRetrieveFolderOfSameNameAsParentFolder() { $root = vfsStream::setup('testFolder'); mkdir(vfsStream::url('testFolder') . '/testFolder/subTestFolder', 0777, true); $this->assertTrue($root->hasChild('testFolder')); $this->assertNotNull($root->getChild('testFolder')); } } assertEquals('baz2', file_get_contents($this->baz2URL)); $this->assertEquals('baz 1', file_get_contents($this->baz1URL)); $this->assertFalse(@file_get_contents($this->barURL)); $this->assertFalse(@file_get_contents($this->fooURL)); } /** * @test * @group permissions * @group bug_15 */ public function file_get_contentsNonReadableFile() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('root')); vfsStream::newFile('new.txt', 0000)->at(vfsStreamWrapper::getRoot())->withContent('content'); $this->assertEquals('', @file_get_contents(vfsStream::url('root/new.txt'))); } /** * assert that file_put_contents() delivers correct file contents * * @test */ public function file_put_contentsExistingFile() { $this->assertEquals(14, file_put_contents($this->baz2URL, 'baz is not bar')); $this->assertEquals('baz is not bar', $this->baz2->getContent()); $this->assertEquals(6, file_put_contents($this->baz1URL, 'foobar')); $this->assertEquals('foobar', $this->baz1->getContent()); $this->assertFalse(@file_put_contents($this->barURL, 'This does not work.')); $this->assertFalse(@file_put_contents($this->fooURL, 'This does not work, too.')); } /** * @test * @group permissions * @group bug_15 */ public function file_put_contentsExistingFileNonWritableDirectory() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); vfsStream::newFile('new.txt')->at(vfsStreamWrapper::getRoot())->withContent('content'); $this->assertEquals(15, @file_put_contents(vfsStream::url('root/new.txt'), 'This does work.')); $this->assertEquals('This does work.', file_get_contents(vfsStream::url('root/new.txt'))); } /** * @test * @group permissions * @group bug_15 */ public function file_put_contentsExistingNonWritableFile() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('root')); vfsStream::newFile('new.txt', 0400)->at(vfsStreamWrapper::getRoot())->withContent('content'); $this->assertFalse(@file_put_contents(vfsStream::url('root/new.txt'), 'This does not work.')); $this->assertEquals('content', file_get_contents(vfsStream::url('root/new.txt'))); } /** * assert that file_put_contents() delivers correct file contents * * @test */ public function file_put_contentsNonExistingFile() { $this->assertEquals(14, file_put_contents($this->fooURL . '/baznot.bar', 'baz is not bar')); $this->assertEquals(3, count($this->foo->getChildren())); $this->assertEquals(14, file_put_contents($this->barURL . '/baznot.bar', 'baz is not bar')); $this->assertEquals(2, count($this->bar->getChildren())); } /** * @test * @group permissions * @group bug_15 */ public function file_put_contentsNonExistingFileNonWritableDirectory() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); $this->assertFalse(@file_put_contents(vfsStream::url('root/new.txt'), 'This does not work.')); $this->assertFalse(file_exists(vfsStream::url('root/new.txt'))); } /** * using a file pointer should work without any problems * * @test */ public function usingFilePointer() { $fp = fopen($this->baz1URL, 'r'); $this->assertEquals(0, ftell($fp)); $this->assertFalse(feof($fp)); $this->assertEquals(0, fseek($fp, 2)); $this->assertEquals(2, ftell($fp)); $this->assertEquals(0, fseek($fp, 1, SEEK_CUR)); $this->assertEquals(3, ftell($fp)); $this->assertEquals(0, fseek($fp, 1, SEEK_END)); $this->assertEquals(6, ftell($fp)); $this->assertTrue(feof($fp)); $this->assertEquals(0, fseek($fp, 2)); $this->assertFalse(feof($fp)); $this->assertEquals(2, ftell($fp)); $this->assertEquals('z', fread($fp, 1)); $this->assertEquals(3, ftell($fp)); $this->assertEquals(' 1', fread($fp, 8092)); $this->assertEquals(5, ftell($fp)); $this->assertTrue(fclose($fp)); } /** * assert is_file() returns correct result * * @test */ public function is_file() { $this->assertFalse(is_file($this->fooURL)); $this->assertFalse(is_file($this->barURL)); $this->assertTrue(is_file($this->baz1URL)); $this->assertTrue(is_file($this->baz2URL)); $this->assertFalse(is_file($this->fooURL . '/another')); $this->assertFalse(is_file(vfsStream::url('another'))); } /** * @test * @group issue7 * @group issue13 */ public function issue13CanNotOverwriteFiles() { $vfsFile = vfsStream::url('foo/overwrite.txt'); file_put_contents($vfsFile, 'test'); file_put_contents($vfsFile, 'd'); $this->assertEquals('d', file_get_contents($vfsFile)); } /** * @test * @group issue7 * @group issue13 */ public function appendContentIfOpenedWithModeA() { $vfsFile = vfsStream::url('foo/overwrite.txt'); file_put_contents($vfsFile, 'test'); $fp = fopen($vfsFile, 'ab'); fwrite($fp, 'd'); fclose($fp); $this->assertEquals('testd', file_get_contents($vfsFile)); } /** * @test * @group issue7 * @group issue13 */ public function canOverwriteNonExistingFileWithModeX() { $vfsFile = vfsStream::url('foo/overwrite.txt'); $fp = fopen($vfsFile, 'xb'); fwrite($fp, 'test'); fclose($fp); $this->assertEquals('test', file_get_contents($vfsFile)); } /** * @test * @group issue7 * @group issue13 */ public function canNotOverwriteExistingFileWithModeX() { $vfsFile = vfsStream::url('foo/overwrite.txt'); file_put_contents($vfsFile, 'test'); $this->assertFalse(@fopen($vfsFile, 'xb')); $this->assertEquals('test', file_get_contents($vfsFile)); } /** * @test * @group issue7 * @group issue13 */ public function canNotOpenNonExistingFileReadonly() { $this->assertFalse(@fopen(vfsStream::url('foo/doesNotExist.txt'), 'rb')); } /** * @test * @group issue7 * @group issue13 */ public function canNotOpenNonExistingFileReadAndWrite() { $this->assertFalse(@fopen(vfsStream::url('foo/doesNotExist.txt'), 'rb+')); } /** * @test * @group issue7 * @group issue13 */ public function canNotOpenWithIllegalMode() { $this->assertFalse(@fopen($this->baz2URL, 'invalid')); } /** * @test * @group issue7 * @group issue13 */ public function canNotWriteToReadOnlyFile() { $fp = fopen($this->baz2URL, 'rb'); $this->assertEquals('baz2', fread($fp, 4096)); $this->assertEquals(0, fwrite($fp, 'foo')); fclose($fp); $this->assertEquals('baz2', file_get_contents($this->baz2URL)); } /** * @test * @group issue7 * @group issue13 */ public function canNotReadFromWriteOnlyFileWithModeW() { $fp = fopen($this->baz2URL, 'wb'); $this->assertEquals('', fread($fp, 4096)); $this->assertEquals(3, fwrite($fp, 'foo')); fseek($fp, 0); $this->assertEquals('', fread($fp, 4096)); fclose($fp); $this->assertEquals('foo', file_get_contents($this->baz2URL)); } /** * @test * @group issue7 * @group issue13 */ public function canNotReadFromWriteOnlyFileWithModeA() { $fp = fopen($this->baz2URL, 'ab'); $this->assertEquals('', fread($fp, 4096)); $this->assertEquals(3, fwrite($fp, 'foo')); fseek($fp, 0); $this->assertEquals('', fread($fp, 4096)); fclose($fp); $this->assertEquals('baz2foo', file_get_contents($this->baz2URL)); } /** * @test * @group issue7 * @group issue13 */ public function canNotReadFromWriteOnlyFileWithModeX() { $vfsFile = vfsStream::url('foo/modeXtest.txt'); $fp = fopen($vfsFile, 'xb'); $this->assertEquals('', fread($fp, 4096)); $this->assertEquals(3, fwrite($fp, 'foo')); fseek($fp, 0); $this->assertEquals('', fread($fp, 4096)); fclose($fp); $this->assertEquals('foo', file_get_contents($vfsFile)); } /** * @test * @group permissions * @group bug_15 */ public function canNotRemoveFileFromDirectoryWithoutWritePermissions() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); vfsStream::newFile('new.txt')->at(vfsStreamWrapper::getRoot()); $this->assertFalse(unlink(vfsStream::url('root/new.txt'))); $this->assertTrue(file_exists(vfsStream::url('root/new.txt'))); } /** * @test * @group issue_30 */ public function truncatesFileWhenOpenedWithModeW() { $vfsFile = vfsStream::url('foo/overwrite.txt'); file_put_contents($vfsFile, 'test'); $fp = fopen($vfsFile, 'wb'); $this->assertEquals('', file_get_contents($vfsFile)); fclose($fp); } /** * @test * @group issue_30 */ public function createsNonExistingFileWhenOpenedWithModeC() { $vfsFile = vfsStream::url('foo/tobecreated.txt'); $fp = fopen($vfsFile, 'cb'); fwrite($fp, 'some content'); $this->assertTrue($this->foo->hasChild('tobecreated.txt')); fclose($fp); $this->assertEquals('some content', file_get_contents($vfsFile)); } /** * @test * @group issue_30 */ public function createsNonExistingFileWhenOpenedWithModeCplus() { $vfsFile = vfsStream::url('foo/tobecreated.txt'); $fp = fopen($vfsFile, 'cb+'); fwrite($fp, 'some content'); $this->assertTrue($this->foo->hasChild('tobecreated.txt')); fclose($fp); $this->assertEquals('some content', file_get_contents($vfsFile)); } /** * @test * @group issue_30 */ public function doesNotTruncateFileWhenOpenedWithModeC() { $vfsFile = vfsStream::url('foo/overwrite.txt'); file_put_contents($vfsFile, 'test'); $fp = fopen($vfsFile, 'cb'); $this->assertEquals('test', file_get_contents($vfsFile)); fclose($fp); } /** * @test * @group issue_30 */ public function setsPointerToStartWhenOpenedWithModeC() { $vfsFile = vfsStream::url('foo/overwrite.txt'); file_put_contents($vfsFile, 'test'); $fp = fopen($vfsFile, 'cb'); $this->assertEquals(0, ftell($fp)); fclose($fp); } /** * @test * @group issue_30 */ public function doesNotTruncateFileWhenOpenedWithModeCplus() { $vfsFile = vfsStream::url('foo/overwrite.txt'); file_put_contents($vfsFile, 'test'); $fp = fopen($vfsFile, 'cb+'); $this->assertEquals('test', file_get_contents($vfsFile)); fclose($fp); } /** * @test * @group issue_30 */ public function setsPointerToStartWhenOpenedWithModeCplus() { $vfsFile = vfsStream::url('foo/overwrite.txt'); file_put_contents($vfsFile, 'test'); $fp = fopen($vfsFile, 'cb+'); $this->assertEquals(0, ftell($fp)); fclose($fp); } /** * @test */ public function cannotOpenExistingNonwritableFileWithModeA() { $this->baz1->chmod(0400); $this->assertFalse(@fopen($this->baz1URL, 'a')); } /** * @test */ public function cannotOpenExistingNonwritableFileWithModeW() { $this->baz1->chmod(0400); $this->assertFalse(@fopen($this->baz1URL, 'w')); } /** * @test */ public function cannotOpenNonReadableFileWithModeR() { $this->baz1->chmod(0); $this->assertFalse(@fopen($this->baz1URL, 'r')); } /** * @test */ public function cannotRenameToNonWritableDir() { $this->bar->chmod(0); $this->assertFalse(@rename($this->baz2URL, vfsStream::url('foo/bar/baz3'))); } /** * @test * @group issue_38 */ public function cannotReadFileFromNonReadableDir() { $this->markTestSkipped("Issue #38."); $this->bar->chmod(0); $this->assertFalse(@file_get_contents($this->baz1URL)); } } lastModified(50) ->lastAccessed(50) ->lastAttributeModified(50); $this->fooUrl = vfsStream::url('root/foo.txt'); $this->barUrl = vfsStream::url('root/bar'); $this->bazUrl = vfsStream::url('root/bar/baz.txt'); } /** * helper assertion for the tests * * @param string $url url to check * @param vfsStreamContent $content content to compare */ protected function assertFileTimesEqualStreamTimes($url, vfsStreamContent $content) { $this->assertEquals(filemtime($url), $content->filemtime()); $this->assertEquals(fileatime($url), $content->fileatime()); $this->assertEquals(filectime($url), $content->filectime()); } /** * @test * @group issue_7 * @group issue_26 */ public function openFileChangesAttributeTimeOnly() { $file = vfsStream::newFile('foo.txt') ->withContent('test') ->at(vfsStreamWrapper::getRoot()) ->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); fclose(fopen($this->fooUrl, 'rb')); $this->assertGreaterThan(time() - 2, fileatime($this->fooUrl)); $this->assertLessThanOrEqual(time(), fileatime($this->fooUrl)); $this->assertLessThanOrEqual(100, filemtime($this->fooUrl)); $this->assertEquals(100, filectime($this->fooUrl)); $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); } /** * @test * @group issue_7 * @group issue_26 */ public function fileGetContentsChangesAttributeTimeOnly() { $file = vfsStream::newFile('foo.txt') ->withContent('test') ->at(vfsStreamWrapper::getRoot()) ->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); file_get_contents($this->fooUrl); $this->assertGreaterThan(time() - 2, fileatime($this->fooUrl)); $this->assertLessThanOrEqual(time(), fileatime($this->fooUrl)); $this->assertLessThanOrEqual(100, filemtime($this->fooUrl)); $this->assertEquals(100, filectime($this->fooUrl)); $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); } /** * @test * @group issue_7 * @group issue_26 */ public function openFileWithTruncateChangesAttributeAndModificationTime() { $file = vfsStream::newFile('foo.txt') ->withContent('test') ->at(vfsStreamWrapper::getRoot()) ->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); fclose(fopen($this->fooUrl, 'wb')); $this->assertGreaterThan(time() - 2, filemtime($this->fooUrl)); $this->assertGreaterThan(time() - 2, fileatime($this->fooUrl)); $this->assertLessThanOrEqual(time(), filemtime($this->fooUrl)); $this->assertLessThanOrEqual(time(), fileatime($this->fooUrl)); $this->assertEquals(100, filectime($this->fooUrl)); $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); } /** * @test * @group issue_7 */ public function readFileChangesAccessTime() { $file = vfsStream::newFile('foo.txt') ->withContent('test') ->at(vfsStreamWrapper::getRoot()) ->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); $fp = fopen($this->fooUrl, 'rb'); $openTime = time(); sleep(2); fread($fp, 1024); fclose($fp); $this->assertLessThanOrEqual($openTime, filemtime($this->fooUrl)); $this->assertLessThanOrEqual($openTime + 3, fileatime($this->fooUrl)); $this->assertEquals(100, filectime($this->fooUrl)); $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); } /** * @test * @group issue_7 */ public function writeFileChangesModificationTime() { $file = vfsStream::newFile('foo.txt') ->at(vfsStreamWrapper::getRoot()) ->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); $fp = fopen($this->fooUrl, 'wb'); $openTime = time(); sleep(2); fwrite($fp, 'test'); fclose($fp); $this->assertLessThanOrEqual($openTime + 3, filemtime($this->fooUrl)); $this->assertLessThanOrEqual($openTime, fileatime($this->fooUrl)); $this->assertEquals(100, filectime($this->fooUrl)); $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); } /** * @test * @group issue_7 */ public function createNewFileSetsAllTimesToCurrentTime() { file_put_contents($this->fooUrl, 'test'); $this->assertLessThanOrEqual(time(), filemtime($this->fooUrl)); $this->assertEquals(fileatime($this->fooUrl), filectime($this->fooUrl)); $this->assertEquals(fileatime($this->fooUrl), filemtime($this->fooUrl)); $this->assertFileTimesEqualStreamTimes($this->fooUrl, vfsStreamWrapper::getRoot()->getChild('foo.txt')); } /** * @test * @group issue_7 */ public function createNewFileChangesAttributeAndModificationTimeOfContainingDirectory() { $dir = vfsStream::newDirectory('bar') ->at(vfsStreamWrapper::getRoot()) ->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); file_put_contents($this->bazUrl, 'test'); $this->assertLessThanOrEqual(time(), filemtime($this->barUrl)); $this->assertLessThanOrEqual(time(), filectime($this->barUrl)); $this->assertEquals(100, fileatime($this->barUrl)); $this->assertFileTimesEqualStreamTimes($this->barUrl, $dir); } /** * @test * @group issue_7 */ public function addNewFileNameWithLinkFunctionChangesAttributeTimeOfOriginalFile() { $this->markTestSkipped('Links are currently not supported by vfsStream.'); } /** * @test * @group issue_7 */ public function addNewFileNameWithLinkFunctionChangesAttributeAndModificationTimeOfDirectoryContainingLink() { $this->markTestSkipped('Links are currently not supported by vfsStream.'); } /** * @test * @group issue_7 */ public function removeFileChangesAttributeAndModificationTimeOfContainingDirectory() { $dir = vfsStream::newDirectory('bar') ->at(vfsStreamWrapper::getRoot()); $file = vfsStream::newFile('baz.txt') ->at($dir) ->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); $dir->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); unlink($this->bazUrl); $this->assertLessThanOrEqual(time(), filemtime($this->barUrl)); $this->assertLessThanOrEqual(time(), filectime($this->barUrl)); $this->assertEquals(100, fileatime($this->barUrl)); $this->assertFileTimesEqualStreamTimes($this->barUrl, $dir); } /** * @test * @group issue_7 */ public function renameFileChangesAttributeAndModificationTimeOfAffectedDirectories() { $target = vfsStream::newDirectory('target') ->at(vfsStreamWrapper::getRoot()) ->lastModified(200) ->lastAccessed(200) ->lastAttributeModified(200); $source = vfsStream::newDirectory('bar') ->at(vfsStreamWrapper::getRoot()); $file = vfsStream::newFile('baz.txt') ->at($source) ->lastModified(300) ->lastAccessed(300) ->lastAttributeModified(300); $source->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); rename($this->bazUrl, vfsStream::url('root/target/baz.txt')); $this->assertLessThanOrEqual(time(), filemtime($this->barUrl)); $this->assertLessThanOrEqual(time(), filectime($this->barUrl)); $this->assertEquals(100, fileatime($this->barUrl)); $this->assertFileTimesEqualStreamTimes($this->barUrl, $source); $this->assertLessThanOrEqual(time(), filemtime(vfsStream::url('root/target'))); $this->assertLessThanOrEqual(time(), filectime(vfsStream::url('root/target'))); $this->assertEquals(200, fileatime(vfsStream::url('root/target'))); $this->assertFileTimesEqualStreamTimes(vfsStream::url('root/target'), $target); } /** * @test * @group issue_7 */ public function renameFileDoesNotChangeFileTimesOfFileItself() { $target = vfsStream::newDirectory('target') ->at(vfsStreamWrapper::getRoot()) ->lastModified(200) ->lastAccessed(200) ->lastAttributeModified(200); $source = vfsStream::newDirectory('bar') ->at(vfsStreamWrapper::getRoot()); $file = vfsStream::newFile('baz.txt') ->at($source) ->lastModified(300) ->lastAccessed(300) ->lastAttributeModified(300); $source->lastModified(100) ->lastAccessed(100) ->lastAttributeModified(100); rename($this->bazUrl, vfsStream::url('root/target/baz.txt')); $this->assertEquals(300, filemtime(vfsStream::url('root/target/baz.txt'))); $this->assertEquals(300, filectime(vfsStream::url('root/target/baz.txt'))); $this->assertEquals(300, fileatime(vfsStream::url('root/target/baz.txt'))); $this->assertFileTimesEqualStreamTimes(vfsStream::url('root/target/baz.txt'), $file); } /** * @test * @group issue_7 */ public function changeFileAttributesChangesAttributeTimeOfFileItself() { $this->markTestSkipped('Changing file attributes via stream wrapper for self-defined streams is not supported by PHP.'); } } root = vfsStream::setup(); } /** * @test */ public function fileIsNotLockedByDefault() { $this->assertFalse(vfsStream::newFile('foo.txt')->isLocked()); } /** * @test */ public function streamIsNotLockedByDefault() { file_put_contents(vfsStream::url('root/foo.txt'), 'content'); $this->assertFalse($this->root->getChild('foo.txt')->isLocked()); } /** * @test */ public function canAquireSharedLock() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $this->assertTrue(flock($fp, LOCK_SH)); $this->assertTrue($file->isLocked()); $this->assertTrue($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); fclose($fp); } /** * @test */ public function canAquireSharedLockWithNonBlockingFlockCall() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $this->assertTrue(flock($fp, LOCK_SH | LOCK_NB)); $this->assertTrue($file->isLocked()); $this->assertTrue($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); fclose($fp); } /** * @test */ public function canAquireEclusiveLock() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $this->assertTrue(flock($fp, LOCK_EX)); $this->assertTrue($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertTrue($file->hasExclusiveLock()); fclose($fp); } /** * @test */ public function canAquireEclusiveLockWithNonBlockingFlockCall() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $this->assertTrue(flock($fp, LOCK_EX | LOCK_NB)); $this->assertTrue($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertTrue($file->hasExclusiveLock()); fclose($fp); } /** * @test */ public function canRemoveLock() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp, LOCK_EX); $this->assertTrue(flock($fp, LOCK_UN)); $this->assertFalse($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); fclose($fp); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canRemoveLockWhenNotLocked() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $this->assertTrue(flock($fp, LOCK_UN)); $this->assertFalse($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertFalse($file->hasSharedLock($fp)); $this->assertFalse($file->hasExclusiveLock()); $this->assertFalse($file->hasExclusiveLock($fp)); fclose($fp); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canRemoveSharedLockWithoutRemovingSharedLockOnOtherFileHandler() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp1, LOCK_SH); $file->lock($fp2, LOCK_SH); $this->assertTrue(flock($fp1, LOCK_UN)); $this->assertTrue($file->hasSharedLock()); $this->assertFalse($file->hasSharedLock($fp1)); $this->assertTrue($file->hasSharedLock($fp2)); fclose($fp1); fclose($fp2); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canNotRemoveSharedLockAcquiredOnOtherFileHandler() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp1, LOCK_SH); $this->assertTrue(flock($fp2, LOCK_UN)); $this->assertTrue($file->isLocked()); $this->assertTrue($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); fclose($fp1); fclose($fp2); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canNotRemoveExlusiveLockAcquiredOnOtherFileHandler() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp1, LOCK_EX); $this->assertTrue(flock($fp2, LOCK_UN)); $this->assertTrue($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertTrue($file->hasExclusiveLock()); fclose($fp1); fclose($fp2); } /** * @test */ public function canRemoveLockWithNonBlockingFlockCall() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp, LOCK_EX); $this->assertTrue(flock($fp, LOCK_UN | LOCK_NB)); $this->assertFalse($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); fclose($fp); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canNotAquireExclusiveLockIfAlreadyExclusivelyLockedOnOtherFileHandler() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp1, LOCK_EX); $this->assertFalse(flock($fp2, LOCK_EX + LOCK_NB)); $this->assertTrue($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertTrue($file->hasExclusiveLock()); $this->assertTrue($file->hasExclusiveLock($fp1)); $this->assertFalse($file->hasExclusiveLock($fp2)); fclose($fp1); fclose($fp2); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canAquireExclusiveLockIfAlreadySelfExclusivelyLocked() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp, LOCK_EX); $this->assertTrue(flock($fp, LOCK_EX + LOCK_NB)); $this->assertTrue($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertTrue($file->hasExclusiveLock()); fclose($fp); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canNotAquireExclusiveLockIfAlreadySharedLockedOnOtherFileHandler() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp1, LOCK_SH); $this->assertFalse(flock($fp2, LOCK_EX)); $this->assertTrue($file->isLocked()); $this->assertTrue($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); fclose($fp1); fclose($fp2); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canAquireExclusiveLockIfAlreadySelfSharedLocked() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp, LOCK_SH); $this->assertTrue(flock($fp, LOCK_EX)); $this->assertTrue($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertTrue($file->hasExclusiveLock()); fclose($fp); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canNotAquireSharedLockIfAlreadyExclusivelyLockedOnOtherFileHandler() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp1, LOCK_EX); $this->assertFalse(flock($fp2, LOCK_SH + LOCK_NB)); $this->assertTrue($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertTrue($file->hasExclusiveLock()); fclose($fp1); fclose($fp2); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canAquireSharedLockIfAlreadySelfExclusivelyLocked() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp, LOCK_EX); $this->assertTrue(flock($fp, LOCK_SH + LOCK_NB)); $this->assertTrue($file->isLocked()); $this->assertTrue($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); fclose($fp); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canAquireSharedLockIfAlreadySelfSharedLocked() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp, LOCK_SH); $this->assertTrue(flock($fp, LOCK_SH)); $this->assertTrue($file->isLocked()); $this->assertTrue($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); fclose($fp); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function canAquireSharedLockIfAlreadySharedLockedOnOtherFileHandler() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp1, LOCK_SH); $this->assertTrue(flock($fp2, LOCK_SH)); $this->assertTrue($file->isLocked()); $this->assertTrue($file->hasSharedLock()); $this->assertTrue($file->hasSharedLock($fp1)); $this->assertTrue($file->hasSharedLock($fp2)); $this->assertFalse($file->hasExclusiveLock()); fclose($fp1); fclose($fp2); } /** * @see https://github.com/mikey179/vfsStream/issues/31 * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_31 * @group issue_40 */ public function removesExclusiveLockOnStreamClose() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp, LOCK_EX); fclose($fp); $this->assertFalse($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); } /** * @see https://github.com/mikey179/vfsStream/issues/31 * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_31 * @group issue_40 */ public function removesSharedLockOnStreamClose() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp, LOCK_SH); fclose($fp); $this->assertFalse($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertFalse($file->hasExclusiveLock()); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function notRemovesExclusiveLockOnStreamCloseIfExclusiveLockAcquiredOnOtherFileHandler() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp2, LOCK_EX); fclose($fp1); $this->assertTrue($file->isLocked()); $this->assertFalse($file->hasSharedLock()); $this->assertTrue($file->hasExclusiveLock()); $this->assertTrue($file->hasExclusiveLock($fp2)); fclose($fp2); } /** * @see https://github.com/mikey179/vfsStream/issues/40 * @test * @group issue_40 */ public function notRemovesSharedLockOnStreamCloseIfSharedLockAcquiredOnOtherFileHandler() { $file = vfsStream::newFile('foo.txt')->at($this->root); $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); $file->lock($fp2, LOCK_SH); fclose($fp1); $this->assertTrue($file->isLocked()); $this->assertTrue($file->hasSharedLock()); $this->assertTrue($file->hasSharedLock($fp2)); $this->assertFalse($file->hasExclusiveLock()); fclose($fp2); } } largeFile = vfsStream::newFile('large.txt') ->withContent(LargeFileContent::withGigabytes(100)) ->at($root); } /** * @test */ public function hasLargeFileSize() { if (PHP_INT_MAX == 2147483647) { $this->markTestSkipped('Requires 64-bit version of PHP'); } $this->assertEquals( 100 * 1024 * 1024 * 1024, filesize($this->largeFile->url()) ); } /** * @test */ public function canReadFromLargeFile() { $fp = fopen($this->largeFile->url(), 'rb'); $data = fread($fp, 15); fclose($fp); $this->assertEquals(str_repeat(' ', 15), $data); } /** * @test */ public function canWriteIntoLargeFile() { $fp = fopen($this->largeFile->url(), 'rb+'); fseek($fp, 100 * 1024 * 1024, SEEK_SET); fwrite($fp, 'foobarbaz'); fclose($fp); $this->largeFile->seek((100 * 1024 * 1024) - 3, SEEK_SET); $this->assertEquals( ' foobarbaz ', $this->largeFile->read(15) ); } } root = vfsStream::setup(); vfsStream::setQuota(10); } /** * @test */ public function writeLessThanQuotaWritesEverything() { $this->assertEquals(9, file_put_contents(vfsStream::url('root/file.txt'), '123456789')); $this->assertEquals('123456789', $this->root->getChild('file.txt')->getContent()); } /** * @test */ public function writeUpToQotaWritesEverything() { $this->assertEquals(10, file_put_contents(vfsStream::url('root/file.txt'), '1234567890')); $this->assertEquals('1234567890', $this->root->getChild('file.txt')->getContent()); } /** * @test */ public function writeMoreThanQotaWritesOnlyUpToQuota() { try { file_put_contents(vfsStream::url('root/file.txt'), '12345678901'); } catch (\PHPUnit_Framework_Error $e) { $this->assertEquals('file_put_contents(): Only 10 of 11 bytes written, possibly out of free disk space', $e->getMessage() ); } $this->assertEquals('1234567890', $this->root->getChild('file.txt')->getContent()); } /** * @test */ public function considersAllFilesForQuota() { vfsStream::newFile('foo.txt') ->withContent('foo') ->at(vfsStream::newDirectory('bar') ->at($this->root) ); try { file_put_contents(vfsStream::url('root/file.txt'), '12345678901'); } catch (\PHPUnit_Framework_Error $e) { $this->assertEquals('file_put_contents(): Only 7 of 11 bytes written, possibly out of free disk space', $e->getMessage() ); } $this->assertEquals('1234567', $this->root->getChild('file.txt')->getContent()); } /** * @test * @group issue_33 */ public function truncateToLessThanQuotaWritesEverything() { if (version_compare(PHP_VERSION, '5.4.0', '<')) { $this->markTestSkipped('Requires PHP 5.4'); } if (strstr(PHP_VERSION, 'hiphop') !== false) { $this->markTestSkipped('Not supported on hhvm'); } $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); $this->assertTrue(ftruncate($fp, 9)); fclose($fp); $this->assertEquals(9, $this->root->getChild('file.txt')->size() ); $this->assertEquals("\0\0\0\0\0\0\0\0\0", $this->root->getChild('file.txt')->getContent() ); } /** * @test * @group issue_33 */ public function truncateUpToQotaWritesEverything() { if (version_compare(PHP_VERSION, '5.4.0', '<')) { $this->markTestSkipped('Requires PHP 5.4'); } if (strstr(PHP_VERSION, 'hiphop') !== false) { $this->markTestSkipped('Not supported on hhvm'); } $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); $this->assertTrue(ftruncate($fp, 10)); fclose($fp); $this->assertEquals(10, $this->root->getChild('file.txt')->size() ); $this->assertEquals("\0\0\0\0\0\0\0\0\0\0", $this->root->getChild('file.txt')->getContent() ); } /** * @test * @group issue_33 */ public function truncateToMoreThanQotaWritesOnlyUpToQuota() { if (version_compare(PHP_VERSION, '5.4.0', '<')) { $this->markTestSkipped('Requires PHP 5.4'); } if (strstr(PHP_VERSION, 'hiphop') !== false) { $this->markTestSkipped('Not supported on hhvm'); } $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); $this->assertTrue(ftruncate($fp, 11)); fclose($fp); $this->assertEquals(10, $this->root->getChild('file.txt')->size() ); $this->assertEquals("\0\0\0\0\0\0\0\0\0\0", $this->root->getChild('file.txt')->getContent() ); } /** * @test * @group issue_33 */ public function truncateConsidersAllFilesForQuota() { if (version_compare(PHP_VERSION, '5.4.0', '<')) { $this->markTestSkipped('Requires PHP 5.4'); } if (strstr(PHP_VERSION, 'hiphop') !== false) { $this->markTestSkipped('Not supported on hhvm'); } vfsStream::newFile('bar.txt') ->withContent('bar') ->at(vfsStream::newDirectory('bar') ->at($this->root) ); $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); $this->assertTrue(ftruncate($fp, 11)); fclose($fp); $this->assertEquals(7, $this->root->getChild('file.txt')->size() ); $this->assertEquals("\0\0\0\0\0\0\0", $this->root->getChild('file.txt')->getContent() ); } /** * @test * @group issue_33 */ public function canNotTruncateToGreaterLengthWhenDiscQuotaReached() { if (version_compare(PHP_VERSION, '5.4.0', '<')) { $this->markTestSkipped('Requires PHP 5.4'); } if (strstr(PHP_VERSION, 'hiphop') !== false) { $this->markTestSkipped('Not supported on hhvm'); } vfsStream::newFile('bar.txt') ->withContent('1234567890') ->at(vfsStream::newDirectory('bar') ->at($this->root) ); $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); $this->assertFalse(ftruncate($fp, 11)); fclose($fp); $this->assertEquals(0, $this->root->getChild('file.txt')->size() ); $this->assertEquals('', $this->root->getChild('file.txt')->getContent() ); } } root = vfsStream::setup(); vfsStream::newFile('foo.txt')->at($this->root); } /** * @test */ public function setBlockingDoesNotWork() { $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $this->assertFalse(stream_set_blocking($fp, 1)); fclose($fp); } /** * @test */ public function removeBlockingDoesNotWork() { $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $this->assertFalse(stream_set_blocking($fp, 0)); fclose($fp); } /** * @test */ public function setTimeoutDoesNotWork() { $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $this->assertFalse(stream_set_timeout($fp, 1)); fclose($fp); } /** * @test */ public function setWriteBufferDoesNotWork() { $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $this->assertEquals(-1, stream_set_write_buffer($fp, 512)); fclose($fp); } } = 80000) { $this->bc_expectException('\ValueError'); } else { $this->bc_expectException('\PHPUnit_Framework_Error'); } $root = vfsStream::setup(); $file = vfsStream::newFile('foo.txt')->at($root)->withContent('testContent'); $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); $readarray = array($fp); $writearray = array(); $exceptarray = array(); stream_select($readarray, $writearray, $exceptarray, 1); } } assertSame($this->foo, vfsStreamWrapper::getRoot()); vfsStreamWrapper::register(); $this->assertNull(vfsStreamWrapper::getRoot()); } /** * @test * @since 0.11.0 */ public function setRootReturnsRoot() { vfsStreamWrapper::register(); $root = vfsStream::newDirectory('root'); $this->assertSame($root, vfsStreamWrapper::setRoot($root)); } /** * assure that filesize is returned correct * * @test */ public function filesize() { $this->assertEquals(0, filesize($this->fooURL)); $this->assertEquals(0, filesize($this->fooURL . '/.')); $this->assertEquals(0, filesize($this->barURL)); $this->assertEquals(0, filesize($this->barURL . '/.')); $this->assertEquals(4, filesize($this->baz2URL)); $this->assertEquals(5, filesize($this->baz1URL)); } /** * assert that file_exists() delivers correct result * * @test */ public function file_exists() { $this->assertTrue(file_exists($this->fooURL)); $this->assertTrue(file_exists($this->fooURL . '/.')); $this->assertTrue(file_exists($this->barURL)); $this->assertTrue(file_exists($this->barURL . '/.')); $this->assertTrue(file_exists($this->baz1URL)); $this->assertTrue(file_exists($this->baz2URL)); $this->assertFalse(file_exists($this->fooURL . '/another')); $this->assertFalse(file_exists(vfsStream::url('another'))); } /** * assert that filemtime() delivers correct result * * @test */ public function filemtime() { $this->assertEquals(100, filemtime($this->fooURL)); $this->assertEquals(100, filemtime($this->fooURL . '/.')); $this->assertEquals(200, filemtime($this->barURL)); $this->assertEquals(200, filemtime($this->barURL . '/.')); $this->assertEquals(300, filemtime($this->baz1URL)); $this->assertEquals(400, filemtime($this->baz2URL)); } /** * @test * @group issue_23 */ public function unlinkRemovesFilesOnly() { $this->assertTrue(unlink($this->baz2URL)); $this->assertFalse(file_exists($this->baz2URL)); // make sure statcache was cleared $this->assertEquals(array($this->bar), $this->foo->getChildren()); $this->assertFalse(@unlink($this->fooURL . '/another')); $this->assertFalse(@unlink(vfsStream::url('another'))); $this->assertEquals(array($this->bar), $this->foo->getChildren()); } /** * @test * @group issue_49 */ public function unlinkReturnsFalseWhenFileDoesNotExist() { vfsStream::setup()->addChild(vfsStream::newFile('foo.blubb')); $this->assertFalse(@unlink(vfsStream::url('foo.blubb2'))); } /** * @test * @group issue_49 */ public function unlinkReturnsFalseWhenFileDoesNotExistAndFileWithSameNameExistsInRoot() { vfsStream::setup()->addChild(vfsStream::newFile('foo.blubb')); $this->assertFalse(@unlink(vfsStream::url('foo.blubb'))); } /** * assert dirname() returns correct directory name * * @test */ public function dirname() { $this->assertEquals($this->fooURL, dirname($this->barURL)); $this->assertEquals($this->barURL, dirname($this->baz1URL)); # returns "vfs:" instead of "." # however this seems not to be fixable because dirname() does not # call the stream wrapper #$this->assertEquals(dirname(vfsStream::url('doesNotExist')), '.'); } /** * assert basename() returns correct file name * * @test */ public function basename() { $this->assertEquals('bar', basename($this->barURL)); $this->assertEquals('baz1', basename($this->baz1URL)); $this->assertEquals('doesNotExist', basename(vfsStream::url('doesNotExist'))); } /** * assert is_readable() works correct * * @test */ public function is_readable() { $this->assertTrue(is_readable($this->fooURL)); $this->assertTrue(is_readable($this->fooURL . '/.')); $this->assertTrue(is_readable($this->barURL)); $this->assertTrue(is_readable($this->barURL . '/.')); $this->assertTrue(is_readable($this->baz1URL)); $this->assertTrue(is_readable($this->baz2URL)); $this->assertFalse(is_readable($this->fooURL . '/another')); $this->assertFalse(is_readable(vfsStream::url('another'))); $this->foo->chmod(0222); $this->assertFalse(is_readable($this->fooURL)); $this->baz1->chmod(0222); $this->assertFalse(is_readable($this->baz1URL)); } /** * assert is_writable() works correct * * @test */ public function is_writable() { $this->assertTrue(is_writable($this->fooURL)); $this->assertTrue(is_writable($this->fooURL . '/.')); $this->assertTrue(is_writable($this->barURL)); $this->assertTrue(is_writable($this->barURL . '/.')); $this->assertTrue(is_writable($this->baz1URL)); $this->assertTrue(is_writable($this->baz2URL)); $this->assertFalse(is_writable($this->fooURL . '/another')); $this->assertFalse(is_writable(vfsStream::url('another'))); $this->foo->chmod(0444); $this->assertFalse(is_writable($this->fooURL)); $this->baz1->chmod(0444); $this->assertFalse(is_writable($this->baz1URL)); } /** * assert is_executable() works correct * * @test */ public function is_executable() { $this->assertFalse(is_executable($this->baz1URL)); $this->baz1->chmod(0766); $this->assertTrue(is_executable($this->baz1URL)); $this->assertFalse(is_executable($this->baz2URL)); } /** * assert is_executable() works correct * * @test */ public function directoriesAndNonExistingFilesAreSometimesExecutable() { // Inconsistent behavior has been fixed in 7.3 // see https://github.com/php/php-src/commit/94b4abdbc4d if (PHP_VERSION_ID >= 70300) { $this->assertTrue(is_executable($this->fooURL)); $this->assertTrue(is_executable($this->fooURL . '/.')); $this->assertTrue(is_executable($this->barURL)); $this->assertTrue(is_executable($this->barURL . '/.')); } else { $this->assertFalse(is_executable($this->fooURL)); $this->assertFalse(is_executable($this->fooURL . '/.')); $this->assertFalse(is_executable($this->barURL)); $this->assertFalse(is_executable($this->barURL . '/.')); } $this->assertFalse(is_executable($this->fooURL . '/another')); $this->assertFalse(is_executable(vfsStream::url('another'))); } /** * file permissions * * @test * @group permissions */ public function chmod() { $this->assertEquals(40777, decoct(fileperms($this->fooURL))); $this->assertEquals(40777, decoct(fileperms($this->fooURL . '/.'))); $this->assertEquals(40777, decoct(fileperms($this->barURL))); $this->assertEquals(40777, decoct(fileperms($this->barURL . '/.'))); $this->assertEquals(100666, decoct(fileperms($this->baz1URL))); $this->assertEquals(100666, decoct(fileperms($this->baz2URL))); $this->foo->chmod(0755); $this->bar->chmod(0700); $this->baz1->chmod(0644); $this->baz2->chmod(0600); $this->assertEquals(40755, decoct(fileperms($this->fooURL))); $this->assertEquals(40755, decoct(fileperms($this->fooURL . '/.'))); $this->assertEquals(40700, decoct(fileperms($this->barURL))); $this->assertEquals(40700, decoct(fileperms($this->barURL . '/.'))); $this->assertEquals(100644, decoct(fileperms($this->baz1URL))); $this->assertEquals(100600, decoct(fileperms($this->baz2URL))); } /** * @test * @group issue_11 * @group permissions */ public function chmodModifiesPermissions() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->assertFalse(@chmod($this->fooURL, 0755)); $this->assertFalse(@chmod($this->barURL, 0711)); $this->assertFalse(@chmod($this->baz1URL, 0644)); $this->assertFalse(@chmod($this->baz2URL, 0664)); $this->assertEquals(40777, decoct(fileperms($this->fooURL))); $this->assertEquals(40777, decoct(fileperms($this->barURL))); $this->assertEquals(100666, decoct(fileperms($this->baz1URL))); $this->assertEquals(100666, decoct(fileperms($this->baz2URL))); } else { $this->assertTrue(chmod($this->fooURL, 0755)); $this->assertTrue(chmod($this->barURL, 0711)); $this->assertTrue(chmod($this->baz1URL, 0644)); $this->assertTrue(chmod($this->baz2URL, 0664)); $this->assertEquals(40755, decoct(fileperms($this->fooURL))); $this->assertEquals(40711, decoct(fileperms($this->barURL))); $this->assertEquals(100644, decoct(fileperms($this->baz1URL))); $this->assertEquals(100664, decoct(fileperms($this->baz2URL))); } } /** * @test * @group permissions */ public function fileownerIsCurrentUserByDefault() { $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->fooURL)); $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->fooURL . '/.')); $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->barURL)); $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->barURL . '/.')); $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->baz1URL)); $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->baz2URL)); } /** * @test * @group issue_11 * @group permissions */ public function chownChangesUser() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->foo->chown(vfsStream::OWNER_USER_1); $this->bar->chown(vfsStream::OWNER_USER_1); $this->baz1->chown(vfsStream::OWNER_USER_2); $this->baz2->chown(vfsStream::OWNER_USER_2); } else { chown($this->fooURL, vfsStream::OWNER_USER_1); chown($this->barURL, vfsStream::OWNER_USER_1); chown($this->baz1URL, vfsStream::OWNER_USER_2); chown($this->baz2URL, vfsStream::OWNER_USER_2); } $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->fooURL)); $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->fooURL . '/.')); $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->barURL)); $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->barURL . '/.')); $this->assertEquals(vfsStream::OWNER_USER_2, fileowner($this->baz1URL)); $this->assertEquals(vfsStream::OWNER_USER_2, fileowner($this->baz2URL)); } /** * @test * @group issue_11 * @group permissions */ public function chownDoesNotWorkOnVfsStreamUrls() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->assertFalse(@chown($this->fooURL, vfsStream::OWNER_USER_2)); $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->fooURL)); } } /** * @test * @group issue_11 * @group permissions */ public function groupIsCurrentGroupByDefault() { $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->fooURL)); $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->fooURL . '/.')); $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->barURL)); $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->barURL . '/.')); $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->baz1URL)); $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->baz2URL)); } /** * @test * @group issue_11 * @group permissions */ public function chgrp() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->foo->chgrp(vfsStream::GROUP_USER_1); $this->bar->chgrp(vfsStream::GROUP_USER_1); $this->baz1->chgrp(vfsStream::GROUP_USER_2); $this->baz2->chgrp(vfsStream::GROUP_USER_2); } else { chgrp($this->fooURL, vfsStream::GROUP_USER_1); chgrp($this->barURL, vfsStream::GROUP_USER_1); chgrp($this->baz1URL, vfsStream::GROUP_USER_2); chgrp($this->baz2URL, vfsStream::GROUP_USER_2); } $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->fooURL)); $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->fooURL . '/.')); $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->barURL)); $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->barURL . '/.')); $this->assertEquals(vfsStream::GROUP_USER_2, filegroup($this->baz1URL)); $this->assertEquals(vfsStream::GROUP_USER_2, filegroup($this->baz2URL)); } /** * @test * @group issue_11 * @group permissions */ public function chgrpDoesNotWorkOnVfsStreamUrls() { if (version_compare(phpversion(), '5.4.0', '<')) { $this->assertFalse(@chgrp($this->fooURL, vfsStream::GROUP_USER_2)); $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->fooURL)); } } /** * @test * @author Benoit Aubuchon */ public function renameDirectory() { // move foo/bar to foo/baz3 $baz3URL = vfsStream::url('foo/baz3'); $this->assertTrue(rename($this->barURL, $baz3URL)); $this->assertFileExists($baz3URL); $this->assertFileDoesNotExist($this->barURL); } /** * @test */ public function renameDirectoryWithDots() { // move foo/bar to foo/baz3 $baz3URL = vfsStream::url('foo/baz3'); $this->assertTrue(rename($this->barURL . '/.', $baz3URL)); $this->assertFileExists($baz3URL); $this->assertFileDoesNotExist($this->barURL); } /** * @test * @group issue_9 * @since 0.9.0 */ public function renameDirectoryWithDotsInTarget() { // move foo/bar to foo/baz3 $baz3URL = vfsStream::url('foo/../baz3/.'); $this->assertTrue(rename($this->barURL . '/.', $baz3URL)); $this->assertFileExists($baz3URL); $this->assertFileDoesNotExist($this->barURL); } /** * @test * @author Benoit Aubuchon */ public function renameDirectoryOverwritingExistingFile() { // move foo/bar to foo/baz2 $this->assertTrue(rename($this->barURL, $this->baz2URL)); $this->assertFileExists(vfsStream::url('foo/baz2/baz1')); $this->assertFileDoesNotExist($this->barURL); } /** * @test */ public function renameFileIntoFile() { $this->expectException(Error\Warning::class); // foo/baz2 is a file, so it can not be turned into a directory $baz3URL = vfsStream::url('foo/baz2/baz3'); $this->assertTrue(rename($this->baz1URL, $baz3URL)); $this->assertFileExists($baz3URL); $this->assertFileDoesNotExist($this->baz1URL); } /** * @test * @author Benoit Aubuchon */ public function renameFileToDirectory() { // move foo/bar/baz1 to foo/baz3 $baz3URL = vfsStream::url('foo/baz3'); $this->assertTrue(rename($this->baz1URL, $baz3URL)); $this->assertFileExists($this->barURL); $this->assertFileExists($baz3URL); $this->assertFileDoesNotExist($this->baz1URL); } /** * assert that trying to rename from a non existing file trigger a warning * * @test */ public function renameOnSourceFileNotFound() { $this->expectException(Error\Warning::class); rename(vfsStream::url('notfound'), $this->baz1URL); } /** * assert that trying to rename to a directory that is not found trigger a warning * @test */ public function renameOnDestinationDirectoryFileNotFound() { $this->expectException(Error\Warning::class); rename($this->baz1URL, vfsStream::url('foo/notfound/file2')); } /** * stat() and fstat() should return the same result * * @test */ public function statAndFstatReturnSameResult() { $fp = fopen($this->baz2URL, 'r'); $this->assertEquals(stat($this->baz2URL), fstat($fp) ); fclose($fp); } /** * stat() returns full data * * @test */ public function statReturnsFullDataForFiles() { $this->assertEquals(array(0 => 0, 1 => 0, 2 => 0100666, 3 => 0, 4 => vfsStream::getCurrentUser(), 5 => vfsStream::getCurrentGroup(), 6 => 0, 7 => 4, 8 => 400, 9 => 400, 10 => 400, 11 => -1, 12 => -1, 'dev' => 0, 'ino' => 0, 'mode' => 0100666, 'nlink' => 0, 'uid' => vfsStream::getCurrentUser(), 'gid' => vfsStream::getCurrentGroup(), 'rdev' => 0, 'size' => 4, 'atime' => 400, 'mtime' => 400, 'ctime' => 400, 'blksize' => -1, 'blocks' => -1 ), stat($this->baz2URL) ); } /** * @test */ public function statReturnsFullDataForDirectories() { $this->assertEquals(array(0 => 0, 1 => 0, 2 => 0040777, 3 => 0, 4 => vfsStream::getCurrentUser(), 5 => vfsStream::getCurrentGroup(), 6 => 0, 7 => 0, 8 => 100, 9 => 100, 10 => 100, 11 => -1, 12 => -1, 'dev' => 0, 'ino' => 0, 'mode' => 0040777, 'nlink' => 0, 'uid' => vfsStream::getCurrentUser(), 'gid' => vfsStream::getCurrentGroup(), 'rdev' => 0, 'size' => 0, 'atime' => 100, 'mtime' => 100, 'ctime' => 100, 'blksize' => -1, 'blocks' => -1 ), stat($this->fooURL) ); } /** * @test */ public function statReturnsFullDataForDirectoriesWithDot() { $this->assertEquals(array(0 => 0, 1 => 0, 2 => 0040777, 3 => 0, 4 => vfsStream::getCurrentUser(), 5 => vfsStream::getCurrentGroup(), 6 => 0, 7 => 0, 8 => 100, 9 => 100, 10 => 100, 11 => -1, 12 => -1, 'dev' => 0, 'ino' => 0, 'mode' => 0040777, 'nlink' => 0, 'uid' => vfsStream::getCurrentUser(), 'gid' => vfsStream::getCurrentGroup(), 'rdev' => 0, 'size' => 0, 'atime' => 100, 'mtime' => 100, 'ctime' => 100, 'blksize' => -1, 'blocks' => -1 ), stat($this->fooURL . '/.') ); } /** * @test */ public function openFileWithoutDirectory() { $this->expectException(Error\Warning::class); vfsStreamWrapper::register(); $this->assertFalse(file_get_contents(vfsStream::url('file.txt'))); } /** * @test * @group issue_33 * @since 1.1.0 * @requires PHP 5.4.0 */ public function truncateRemovesSuperflouosContent() { if (strstr(PHP_VERSION, 'hiphop') !== false) { $this->markTestSkipped('Not supported on hhvm'); } $handle = fopen($this->baz1URL, "r+"); $this->assertTrue(ftruncate($handle, 0)); $this->assertEquals(0, filesize($this->baz1URL)); $this->assertEquals('', file_get_contents($this->baz1URL)); fclose($handle); } /** * @test * @group issue_33 * @since 1.1.0 * @requires PHP 5.4.0 */ public function truncateToGreaterSizeAddsZeroBytes() { if (strstr(PHP_VERSION, 'hiphop') !== false) { $this->markTestSkipped('Not supported on hhvm'); } $handle = fopen($this->baz1URL, "r+"); $this->assertTrue(ftruncate($handle, 25)); $this->assertEquals(25, filesize($this->baz1URL)); $this->assertEquals("baz 1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", file_get_contents($this->baz1URL)); fclose($handle); } /** * @test * @group issue_11 * @requires PHP 5.4.0 */ public function touchCreatesNonExistingFile() { $this->assertTrue(touch($this->fooURL . '/new.txt')); $this->assertTrue($this->foo->hasChild('new.txt')); } /** * @test * @group issue_11 * @requires PHP 5.4.0 */ public function touchChangesAccessAndModificationTimeForFile() { $this->assertTrue(touch($this->baz1URL, 303, 313)); $this->assertEquals(303, $this->baz1->filemtime()); $this->assertEquals(313, $this->baz1->fileatime()); } /** * @test * @group issue_11 * @group issue_80 * @requires PHP 5.4.0 */ public function touchChangesTimesToCurrentTimestampWhenNoTimesGiven() { $this->assertTrue(touch($this->baz1URL)); $this->assertEquals(time(), $this->baz1->filemtime(), '', 1); $this->assertEquals(time(), $this->baz1->fileatime(), '', 1); } /** * @test * @group issue_11 * @requires PHP 5.4.0 */ public function touchWithModifiedTimeChangesAccessAndModifiedTime() { $this->assertTrue(touch($this->baz1URL, 303)); $this->assertEquals(303, $this->baz1->filemtime()); $this->assertEquals(303, $this->baz1->fileatime()); } /** * @test * @group issue_11 * @requires PHP 5.4.0 */ public function touchChangesAccessAndModificationTimeForDirectory() { $this->assertTrue(touch($this->fooURL, 303, 313)); $this->assertEquals(303, $this->foo->filemtime()); $this->assertEquals(313, $this->foo->fileatime()); } /** * @test * @group issue_34 * @since 1.2.0 */ public function pathesAreCorrectlySet() { $this->assertEquals(vfsStream::path($this->fooURL), $this->foo->path()); $this->assertEquals(vfsStream::path($this->barURL), $this->bar->path()); $this->assertEquals(vfsStream::path($this->baz1URL), $this->baz1->path()); $this->assertEquals(vfsStream::path($this->baz2URL), $this->baz2->path()); } /** * @test * @group issue_34 * @since 1.2.0 */ public function urlsAreCorrectlySet() { $this->assertEquals($this->fooURL, $this->foo->url()); $this->assertEquals($this->barURL, $this->bar->url()); $this->assertEquals($this->baz1URL, $this->baz1->url()); $this->assertEquals($this->baz2URL, $this->baz2->url()); } /** * @test * @group issue_34 * @since 1.2.0 */ public function pathIsUpdatedAfterMove() { // move foo/bar/baz1 to foo/baz3 $baz3URL = vfsStream::url('foo/baz3'); $this->assertTrue(rename($this->baz1URL, $baz3URL)); $this->assertEquals(vfsStream::path($baz3URL), $this->baz1->path()); } /** * @test * @group issue_34 * @since 1.2.0 */ public function urlIsUpdatedAfterMove() { // move foo/bar/baz1 to foo/baz3 $baz3URL = vfsStream::url('foo/baz3'); $this->assertTrue(rename($this->baz1URL, $baz3URL)); $this->assertEquals($baz3URL, $this->baz1->url()); } /** * @test */ public function fileCopy() { $baz3URL = vfsStream::url('foo/baz3'); $this->assertTrue(copy($this->baz1URL, $baz3URL)); } } assertNotContains(vfsStream::SCHEME, stream_get_wrappers()); } /** * Unregistering a third party wrapper for vfs:// fails. * * @test * @runInSeparateProcess */ public function unregisterThirdPartyVfsScheme() { $this->expectException(vfsStreamException::class); // Unregister possible registered URL wrapper. vfsStreamWrapper::unregister(); $mock = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamWrapper'); stream_wrapper_register(vfsStream::SCHEME, get_class($mock)); vfsStreamWrapper::unregister(); } /** * Unregistering when not in registered state will fail. * * @test * @runInSeparateProcess */ public function unregisterWhenNotInRegisteredState() { $this->expectException(vfsStreamException::class); vfsStreamWrapper::register(); stream_wrapper_unregister(vfsStream::SCHEME); vfsStreamWrapper::unregister(); } /** * Unregistering while not registers won't fail. * * @test */ public function unregisterWhenNotRegistered() { // Unregister possible registered URL wrapper. vfsStreamWrapper::unregister(); $this->assertNotContains(vfsStream::SCHEME, stream_get_wrappers()); vfsStreamWrapper::unregister(); } } no directory to open * * @test */ public function canNotOpenDirectory() { $this->assertFalse(@dir(vfsStream::url('foo'))); } /** * can not unlink without root * * @test */ public function canNotUnlink() { $this->assertFalse(@unlink(vfsStream::url('foo'))); } /** * can not open a file without root * * @test */ public function canNotOpen() { $this->assertFalse(@fopen(vfsStream::url('foo'), 'r')); } /** * can not rename a file without root * * @test */ public function canNotRename() { $this->assertFalse(@rename(vfsStream::url('foo'), vfsStream::url('bar'))); } } markTestSkipped('No ext/zip installed, skipping test.'); } $this->markTestSkipped('Zip extension can not work with vfsStream urls.'); vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(vfsStream::newDirectory('root')); } /** * @test */ public function createZipArchive() { $zip = new ZipArchive(); $this->assertTrue($zip->open(vfsStream::url('root/test.zip'), ZipArchive::CREATE)); $this->assertTrue($zip->addFromString("testfile1.txt", "#1 This is a test string added as testfile1.txt.\n")); $this->assertTrue($zip->addFromString("testfile2.txt", "#2 This is a test string added as testfile2.txt.\n")); $zip->setArchiveComment('a test'); var_dump($zip); $this->assertTrue($zip->close()); var_dump($zip->getStatusString()); var_dump($zip->close()); var_dump($zip->getStatusString()); var_dump($zip); var_dump(file_exists(vfsStream::url('root/test.zip'))); } } abstractVisitor = $this->bc_getMock('org\\bovigo\\vfs\\visitor\\vfsStreamAbstractVisitor', array('visitFile', 'visitDirectory') ); } /** * @test */ public function visitThrowsInvalidArgumentExceptionOnUnknownContentType() { $this->expectException(\InvalidArgumentException::class); $mockContent = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); $mockContent->expects($this->any()) ->method('getType') ->will($this->returnValue('invalid')); $this->assertSame($this->abstractVisitor, $this->abstractVisitor->visit($mockContent) ); } /** * @test */ public function visitWithFileCallsVisitFile() { $file = new vfsStreamFile('foo.txt'); $this->abstractVisitor->expects($this->once()) ->method('visitFile') ->with($this->equalTo($file)); $this->assertSame($this->abstractVisitor, $this->abstractVisitor->visit($file) ); } /** * tests that a block device eventually calls out to visit file * * @test */ public function visitWithBlockCallsVisitFile() { $block = new vfsStreamBlock('foo'); $this->abstractVisitor->expects($this->once()) ->method('visitFile') ->with($this->equalTo($block)); $this->assertSame($this->abstractVisitor, $this->abstractVisitor->visit($block) ); } /** * @test */ public function visitWithDirectoryCallsVisitDirectory() { $dir = new vfsStreamDirectory('bar'); $this->abstractVisitor->expects($this->once()) ->method('visitDirectory') ->with($this->equalTo($dir)); $this->assertSame($this->abstractVisitor, $this->abstractVisitor->visit($dir) ); } } expectException(\InvalidArgumentException::class); new vfsStreamPrintVisitor('invalid'); } /** * @test */ public function constructWithNonStreamResourceThrowsInvalidArgumentException() { $this->expectException(\InvalidArgumentException::class); new vfsStreamPrintVisitor(xml_parser_create()); } /** * @test */ public function visitFileWritesFileNameToStream() { $output = vfsStream::newFile('foo.txt') ->at(vfsStream::setup()); $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb')); $this->assertSame($printVisitor, $printVisitor->visitFile(vfsStream::newFile('bar.txt')) ); $this->assertEquals("- bar.txt\n", $output->getContent()); } /** * @test */ public function visitFileWritesBlockDeviceToStream() { $output = vfsStream::newFile('foo.txt') ->at(vfsStream::setup()); $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb')); $this->assertSame($printVisitor, $printVisitor->visitBlockDevice(vfsStream::newBlock('bar')) ); $this->assertEquals("- [bar]\n", $output->getContent()); } /** * @test */ public function visitDirectoryWritesDirectoryNameToStream() { $output = vfsStream::newFile('foo.txt') ->at(vfsStream::setup()); $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb')); $this->assertSame($printVisitor, $printVisitor->visitDirectory(vfsStream::newDirectory('baz')) ); $this->assertEquals("- baz\n", $output->getContent()); } /** * @test */ public function visitRecursiveDirectoryStructure() { $root = vfsStream::setup('root', null, array('test' => array('foo' => array('test.txt' => 'hello'), 'baz.txt' => 'world' ), 'foo.txt' => '' ) ); $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb')); $this->assertSame($printVisitor, $printVisitor->visitDirectory($root) ); $this->assertEquals("- root\n - test\n - foo\n - test.txt\n - baz.txt\n - foo.txt\n", file_get_contents('vfs://root/foo.txt')); } } assertEquals(array('foo.txt' => 'test'), $structureVisitor->visitFile(vfsStream::newFile('foo.txt') ->withContent('test') ) ->getStructure() ); } /** * @test */ public function visitFileCreatesStructureForBlock() { $structureVisitor = new vfsStreamStructureVisitor(); $this->assertEquals(array('[foo]' => 'test'), $structureVisitor->visitBlockDevice(vfsStream::newBlock('foo') ->withContent('test') ) ->getStructure() ); } /** * @test */ public function visitDirectoryCreatesStructureForDirectory() { $structureVisitor = new vfsStreamStructureVisitor(); $this->assertEquals(array('baz' => array()), $structureVisitor->visitDirectory(vfsStream::newDirectory('baz')) ->getStructure() ); } /** * @test */ public function visitRecursiveDirectoryStructure() { $root = vfsStream::setup('root', null, array('test' => array('foo' => array('test.txt' => 'hello'), 'baz.txt' => 'world' ), 'foo.txt' => '' ) ); $structureVisitor = new vfsStreamStructureVisitor(); $this->assertEquals(array('root' => array('test' => array('foo' => array('test.txt' => 'hello'), 'baz.txt' => 'world' ), 'foo.txt' => '' ), ), $structureVisitor->visitDirectory($root) ->getStructure() ); } } --TEST-- Reproduce octal output from stream wrapper invocation See https://bugs.php.net/bug.php?id=71287 See https://github.com/mikey179/vfsStream/issues/120 --FILE-- --EXPECTF-- Warning: file_put_contents(): Only 7 of 9 bytes written, possibly out of free disk space in %s on line %dfoofoobarThe MIT License (MIT) Copyright (c) 2013 My C-Sense 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. # DeepCopy DeepCopy helps you create deep copies (clones) of your objects. It is designed to handle cycles in the association graph. [![Total Downloads](https://poser.pugx.org/myclabs/deep-copy/downloads.svg)](https://packagist.org/packages/myclabs/deep-copy) [![Integrate](https://github.com/myclabs/DeepCopy/actions/workflows/ci.yaml/badge.svg?branch=1.x)](https://github.com/myclabs/DeepCopy/actions/workflows/ci.yaml) ## Table of Contents 1. [How](#how) 1. [Why](#why) 1. [Using simply `clone`](#using-simply-clone) 1. [Overriding `__clone()`](#overriding-__clone) 1. [With `DeepCopy`](#with-deepcopy) 1. [How it works](#how-it-works) 1. [Going further](#going-further) 1. [Matchers](#matchers) 1. [Property name](#property-name) 1. [Specific property](#specific-property) 1. [Type](#type) 1. [Filters](#filters) 1. [`SetNullFilter`](#setnullfilter-filter) 1. [`KeepFilter`](#keepfilter-filter) 1. [`DoctrineCollectionFilter`](#doctrinecollectionfilter-filter) 1. [`DoctrineEmptyCollectionFilter`](#doctrineemptycollectionfilter-filter) 1. [`DoctrineProxyFilter`](#doctrineproxyfilter-filter) 1. [`ReplaceFilter`](#replacefilter-type-filter) 1. [`ShallowCopyFilter`](#shallowcopyfilter-type-filter) 1. [Edge cases](#edge-cases) 1. [Contributing](#contributing) 1. [Tests](#tests) ## How? Install with Composer: ``` composer require myclabs/deep-copy ``` Use it: ```php use DeepCopy\DeepCopy; $copier = new DeepCopy(); $myCopy = $copier->copy($myObject); ``` ## Why? - How do you create copies of your objects? ```php $myCopy = clone $myObject; ``` - How do you create **deep** copies of your objects (i.e. copying also all the objects referenced in the properties)? You use [`__clone()`](http://www.php.net/manual/en/language.oop5.cloning.php#object.clone) and implement the behavior yourself. - But how do you handle **cycles** in the association graph? Now you're in for a big mess :( ![association graph](doc/graph.png) ### Using simply `clone` ![Using clone](doc/clone.png) ### Overriding `__clone()` ![Overriding __clone](doc/deep-clone.png) ### With `DeepCopy` ![With DeepCopy](doc/deep-copy.png) ## How it works DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it keeps a map of source objects to their copies and thus preserves the object graph. To use it: ```php use function DeepCopy\deep_copy; $copy = deep_copy($var); ``` Alternatively, you can create your own `DeepCopy` instance to configure it differently for example: ```php use DeepCopy\DeepCopy; $copier = new DeepCopy(true); $copy = $copier->copy($var); ``` You may want to roll your own deep copy function: ```php namespace Acme; use DeepCopy\DeepCopy; function deep_copy($var) { static $copier = null; if (null === $copier) { $copier = new DeepCopy(true); } return $copier->copy($var); } ``` ## Going further You can add filters to customize the copy process. The method to add a filter is `DeepCopy\DeepCopy::addFilter($filter, $matcher)`, with `$filter` implementing `DeepCopy\Filter\Filter` and `$matcher` implementing `DeepCopy\Matcher\Matcher`. We provide some generic filters and matchers. ### Matchers - `DeepCopy\Matcher` applies on a object attribute. - `DeepCopy\TypeMatcher` applies on any element found in graph, including array elements. #### Property name The `PropertyNameMatcher` will match a property by its name: ```php use DeepCopy\Matcher\PropertyNameMatcher; // Will apply a filter to any property of any objects named "id" $matcher = new PropertyNameMatcher('id'); ``` #### Specific property The `PropertyMatcher` will match a specific property of a specific class: ```php use DeepCopy\Matcher\PropertyMatcher; // Will apply a filter to the property "id" of any objects of the class "MyClass" $matcher = new PropertyMatcher('MyClass', 'id'); ``` #### Type The `TypeMatcher` will match any element by its type (instance of a class or any value that could be parameter of [gettype()](http://php.net/manual/en/function.gettype.php) function): ```php use DeepCopy\TypeMatcher\TypeMatcher; // Will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection $matcher = new TypeMatcher('Doctrine\Common\Collections\Collection'); ``` ### Filters - `DeepCopy\Filter` applies a transformation to the object attribute matched by `DeepCopy\Matcher` - `DeepCopy\TypeFilter` applies a transformation to any element matched by `DeepCopy\TypeMatcher` By design, matching a filter will stop the chain of filters (i.e. the next ones will not be applied). Using the ([`ChainableFilter`](#chainablefilter-filter)) won't stop the chain of filters. #### `SetNullFilter` (filter) Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have any ID: ```php use DeepCopy\DeepCopy; use DeepCopy\Filter\SetNullFilter; use DeepCopy\Matcher\PropertyNameMatcher; $object = MyClass::load(123); echo $object->id; // 123 $copier = new DeepCopy(); $copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id')); $copy = $copier->copy($object); echo $copy->id; // null ``` #### `KeepFilter` (filter) If you want a property to remain untouched (for example, an association to an object): ```php use DeepCopy\DeepCopy; use DeepCopy\Filter\KeepFilter; use DeepCopy\Matcher\PropertyMatcher; $copier = new DeepCopy(); $copier->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category')); $copy = $copier->copy($object); // $copy->category has not been touched ``` #### `ChainableFilter` (filter) If you use cloning on proxy classes, you might want to apply two filters for: 1. loading the data 2. applying a transformation You can use the `ChainableFilter` as a decorator of the proxy loader filter, which won't stop the chain of filters (i.e. the next ones may be applied). ```php use DeepCopy\DeepCopy; use DeepCopy\Filter\ChainableFilter; use DeepCopy\Filter\Doctrine\DoctrineProxyFilter; use DeepCopy\Filter\SetNullFilter; use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher; use DeepCopy\Matcher\PropertyNameMatcher; $copier = new DeepCopy(); $copier->addFilter(new ChainableFilter(new DoctrineProxyFilter()), new DoctrineProxyMatcher()); $copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id')); $copy = $copier->copy($object); echo $copy->id; // null ``` #### `DoctrineCollectionFilter` (filter) If you use Doctrine and want to copy an entity, you will need to use the `DoctrineCollectionFilter`: ```php use DeepCopy\DeepCopy; use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter; use DeepCopy\Matcher\PropertyTypeMatcher; $copier = new DeepCopy(); $copier->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection')); $copy = $copier->copy($object); ``` #### `DoctrineEmptyCollectionFilter` (filter) If you use Doctrine and want to copy an entity who contains a `Collection` that you want to be reset, you can use the `DoctrineEmptyCollectionFilter` ```php use DeepCopy\DeepCopy; use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter; use DeepCopy\Matcher\PropertyMatcher; $copier = new DeepCopy(); $copier->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty')); $copy = $copier->copy($object); // $copy->myProperty will return an empty collection ``` #### `DoctrineProxyFilter` (filter) If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a Doctrine proxy class (...\\\_\_CG\_\_\Proxy). You can use the `DoctrineProxyFilter` to load the actual entity behind the Doctrine proxy class. **Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded before other filters are applied!** We recommend to decorate the `DoctrineProxyFilter` with the `ChainableFilter` to allow applying other filters to the cloned lazy loaded entities. ```php use DeepCopy\DeepCopy; use DeepCopy\Filter\Doctrine\DoctrineProxyFilter; use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher; $copier = new DeepCopy(); $copier->addFilter(new ChainableFilter(new DoctrineProxyFilter()), new DoctrineProxyMatcher()); $copy = $copier->copy($object); // $copy should now contain a clone of all entities, including those that were not yet fully loaded. ``` #### `ReplaceFilter` (type filter) 1. If you want to replace the value of a property: ```php use DeepCopy\DeepCopy; use DeepCopy\Filter\ReplaceFilter; use DeepCopy\Matcher\PropertyMatcher; $copier = new DeepCopy(); $callback = function ($currentValue) { return $currentValue . ' (copy)' }; $copier->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title')); $copy = $copier->copy($object); // $copy->title will contain the data returned by the callback, e.g. 'The title (copy)' ``` 2. If you want to replace whole element: ```php use DeepCopy\DeepCopy; use DeepCopy\TypeFilter\ReplaceFilter; use DeepCopy\TypeMatcher\TypeMatcher; $copier = new DeepCopy(); $callback = function (MyClass $myClass) { return get_class($myClass); }; $copier->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass')); $copy = $copier->copy([new MyClass, 'some string', new MyClass]); // $copy will contain ['MyClass', 'some string', 'MyClass'] ``` The `$callback` parameter of the `ReplaceFilter` constructor accepts any PHP callable. #### `ShallowCopyFilter` (type filter) Stop *DeepCopy* from recursively copying element, using standard `clone` instead: ```php use DeepCopy\DeepCopy; use DeepCopy\TypeFilter\ShallowCopyFilter; use DeepCopy\TypeMatcher\TypeMatcher; use Mockery as m; $this->deepCopy = new DeepCopy(); $this->deepCopy->addTypeFilter( new ShallowCopyFilter, new TypeMatcher(m\MockInterface::class) ); $myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDependency2::class)); // All mocks will be just cloned, not deep copied ``` ## Edge cases The following structures cannot be deep-copied with PHP Reflection. As a result they are shallow cloned and filters are not applied. There is two ways for you to handle them: - Implement your own `__clone()` method - Use a filter with a type matcher ## Contributing DeepCopy is distributed under the MIT license. ### Tests Running the tests is simple: ```php vendor/bin/phpunit ``` ### Support Get professional support via [the Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-myclabs-deep-copy?utm_source=packagist-myclabs-deep-copy&utm_medium=referral&utm_campaign=readme). { "name": "myclabs/deep-copy", "description": "Create deep copies (clones) of your objects", "license": "MIT", "type": "library", "keywords": [ "clone", "copy", "duplicate", "object", "object graph" ], "require": { "php": "^8.0" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "conflict": { "doctrine/collections": "<1.6.8", "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "autoload": { "psr-4": { "DeepCopy\\": "src/DeepCopy/" }, "files": [ "src/DeepCopy/deep_copy.php" ] }, "autoload-dev": { "psr-4": { "DeepCopyTest\\": "tests/DeepCopyTest/", "DeepCopy\\": "fixtures/" } }, "config": { "sort-packages": true } } Map of source objects to their copies. */ private $objectMap; /** * Filters to apply. * * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs. */ private $filters = []; /** * Type Filters to apply. * * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs. */ private $typeFilters = []; /** * @var bool */ private $skipUncloneable = false; /** * @var bool */ private $useCloneMethod; /** * @param bool $useCloneMethod If set to true, when an object implements the __clone() function, it will be used * instead of the regular deep cloning. */ public function __construct($useCloneMethod = false) { $this->useCloneMethod = $useCloneMethod; $this->objectMap = new WeakMap(); $this->addTypeFilter(new ArrayObjectFilter($this), new TypeMatcher(ArrayObject::class)); $this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class)); $this->addTypeFilter(new DatePeriodFilter(), new TypeMatcher(DatePeriod::class)); $this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class)); } /** * If enabled, will not throw an exception when coming across an uncloneable property. * * @param $skipUncloneable * * @return $this */ public function skipUncloneable($skipUncloneable = true) { $this->skipUncloneable = $skipUncloneable; return $this; } /** * Deep copies the given object. * * @template TObject * * @param TObject $object * * @return TObject */ public function copy($object) { $this->objectMap = new WeakMap(); return $this->recursiveCopy($object); } public function addFilter(Filter $filter, Matcher $matcher) { $this->filters[] = [ 'matcher' => $matcher, 'filter' => $filter, ]; } public function prependFilter(Filter $filter, Matcher $matcher) { array_unshift($this->filters, [ 'matcher' => $matcher, 'filter' => $filter, ]); } public function addTypeFilter(TypeFilter $filter, TypeMatcher $matcher) { $this->typeFilters[] = [ 'matcher' => $matcher, 'filter' => $filter, ]; } public function prependTypeFilter(TypeFilter $filter, TypeMatcher $matcher) { array_unshift($this->typeFilters, [ 'matcher' => $matcher, 'filter' => $filter, ]); } private function recursiveCopy($var) { // Matches Type Filter if ($filter = $this->getFirstMatchedTypeFilter($this->typeFilters, $var)) { return $filter->apply($var); } // Resource if (is_resource($var)) { return $var; } // Array if (is_array($var)) { return $this->copyArray($var); } // Scalar if (! is_object($var)) { return $var; } // Enum if (PHP_VERSION_ID >= 80100 && enum_exists(get_class($var))) { return $var; } // Object return $this->copyObject($var); } /** * Copy an array * @param array $array * @return array */ private function copyArray(array $array) { foreach ($array as $key => $value) { $array[$key] = $this->recursiveCopy($value); } return $array; } /** * Copies an object. * * @param object $object * * @throws CloneException * * @return object */ private function copyObject($object) { if (isset($this->objectMap[$object])) { return $this->objectMap[$object]; } $reflectedObject = new ReflectionObject($object); $isCloneable = $reflectedObject->isCloneable(); if (false === $isCloneable) { if ($this->skipUncloneable) { $this->objectMap[$object] = $object; return $object; } throw new CloneException( sprintf( 'The class "%s" is not cloneable.', $reflectedObject->getName() ) ); } $newObject = clone $object; $this->objectMap[$object] = $newObject; if ($this->useCloneMethod && $reflectedObject->hasMethod('__clone')) { return $newObject; } if ($newObject instanceof DateTimeInterface || $newObject instanceof DateTimeZone) { return $newObject; } foreach (ReflectionHelper::getProperties($reflectedObject) as $property) { $this->copyObjectProperty($newObject, $property); } return $newObject; } private function copyObjectProperty($object, ReflectionProperty $property) { // Ignore static properties if ($property->isStatic()) { return; } // Ignore readonly properties if (method_exists($property, 'isReadOnly') && $property->isReadOnly()) { return; } // Apply the filters foreach ($this->filters as $item) { /** @var Matcher $matcher */ $matcher = $item['matcher']; /** @var Filter $filter */ $filter = $item['filter']; if ($matcher->matches($object, $property->getName())) { $filter->apply( $object, $property->getName(), function ($object) { return $this->recursiveCopy($object); } ); if ($filter instanceof ChainableFilter) { continue; } // If a filter matches, we stop processing this property return; } } if (PHP_VERSION_ID < 80100) { $property->setAccessible(true); } // Ignore uninitialized properties (for PHP >7.4) if (method_exists($property, 'isInitialized') && !$property->isInitialized($object)) { return; } $propertyValue = $property->getValue($object); // Copy the property $property->setValue($object, $this->recursiveCopy($propertyValue)); } /** * Returns first filter that matches variable, `null` if no such filter found. * * @param array $filterRecords Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and * 'matcher' with value of type {@see TypeMatcher} * @param mixed $var * * @return TypeFilter|null */ private function getFirstMatchedTypeFilter(array $filterRecords, $var) { $matched = $this->first( $filterRecords, function (array $record) use ($var) { /* @var TypeMatcher $matcher */ $matcher = $record['matcher']; return $matcher->matches($var); } ); return isset($matched) ? $matched['filter'] : null; } /** * Returns first element that matches predicate, `null` if no such element found. * * @param array $elements Array of ['filter' => Filter, 'matcher' => Matcher] pairs. * @param callable $predicate Predicate arguments are: element. * * @return array|null Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and 'matcher' * with value of type {@see TypeMatcher} or `null`. */ private function first(array $elements, callable $predicate) { foreach ($elements as $element) { if (call_user_func($predicate, $element)) { return $element; } } return null; } } filter = $filter; } public function apply($object, $property, $objectCopier) { $this->filter->apply($object, $property, $objectCopier); } } setAccessible(true); } $oldCollection = $reflectionProperty->getValue($object); $newCollection = $oldCollection->map( function ($item) use ($objectCopier) { return $objectCopier($item); } ); $reflectionProperty->setValue($object, $newCollection); } } setAccessible(true); } $reflectionProperty->setValue($object, new ArrayCollection()); } } __load(); } } callback = $callable; } /** * Replaces the object property by the result of the callback called with the object property. * * {@inheritdoc} */ public function apply($object, $property, $objectCopier) { $reflectionProperty = ReflectionHelper::getProperty($object, $property); if (PHP_VERSION_ID < 80100) { $reflectionProperty->setAccessible(true); } $value = call_user_func($this->callback, $reflectionProperty->getValue($object)); $reflectionProperty->setValue($object, $value); } } setAccessible(true); } $reflectionProperty->setValue($object, null); } } class = $class; $this->property = $property; } /** * Matches a specific property of a specific class. * * {@inheritdoc} */ public function matches($object, $property) { return ($object instanceof $this->class) && $property == $this->property; } } property = $property; } /** * Matches a property by its name. * * {@inheritdoc} */ public function matches($object, $property) { return $property == $this->property; } } propertyType = $propertyType; } /** * {@inheritdoc} */ public function matches($object, $property) { try { $reflectionProperty = ReflectionHelper::getProperty($object, $property); } catch (ReflectionException $exception) { return false; } if (PHP_VERSION_ID < 80100) { $reflectionProperty->setAccessible(true); } // Uninitialized properties (for PHP >7.4) if (method_exists($reflectionProperty, 'isInitialized') && !$reflectionProperty->isInitialized($object)) { // null instanceof $this->propertyType return false; } return $reflectionProperty->getValue($object) instanceof $this->propertyType; } } getProperties() does not return private properties from ancestor classes. * * @author muratyaman@gmail.com * @see http://php.net/manual/en/reflectionclass.getproperties.php * * @param ReflectionClass $ref * * @return ReflectionProperty[] */ public static function getProperties(ReflectionClass $ref) { $props = $ref->getProperties(); $propsArr = array(); foreach ($props as $prop) { $propertyName = $prop->getName(); $propsArr[$propertyName] = $prop; } if ($parentClass = $ref->getParentClass()) { $parentPropsArr = self::getProperties($parentClass); foreach ($propsArr as $key => $property) { $parentPropsArr[$key] = $property; } return $parentPropsArr; } return $propsArr; } /** * Retrieves property by name from object and all its ancestors. * * @param object|string $object * @param string $name * * @throws PropertyException * @throws ReflectionException * * @return ReflectionProperty */ public static function getProperty($object, $name) { $reflection = is_object($object) ? new ReflectionObject($object) : new ReflectionClass($object); if ($reflection->hasProperty($name)) { return $reflection->getProperty($name); } if ($parentClass = $reflection->getParentClass()) { return self::getProperty($parentClass->getName(), $name); } throw new PropertyException( sprintf( 'The class "%s" doesn\'t have a property with the given name: "%s".', is_object($object) ? get_class($object) : $object, $name ) ); } } $propertyValue) { $copy->{$propertyName} = $propertyValue; } return $copy; } } = 80200 && $element->include_end_date) { $options |= DatePeriod::INCLUDE_END_DATE; } if (!$element->include_start_date) { $options |= DatePeriod::EXCLUDE_START_DATE; } if ($element->getEndDate()) { return new DatePeriod($element->getStartDate(), $element->getDateInterval(), $element->getEndDate(), $options); } if (PHP_VERSION_ID >= 70217) { $recurrences = $element->getRecurrences(); } else { $recurrences = $element->recurrences - $element->include_start_date; } return new DatePeriod($element->getStartDate(), $element->getDateInterval(), $recurrences, $options); } } callback = $callable; } /** * {@inheritdoc} */ public function apply($element) { return call_user_func($this->callback, $element); } } copier = $copier; } /** * {@inheritdoc} */ public function apply($arrayObject) { $clone = clone $arrayObject; foreach ($arrayObject->getArrayCopy() as $k => $v) { $clone->offsetSet($k, $this->copier->copy($v)); } return $clone; } } copier = $copier; } /** * {@inheritdoc} */ public function apply($element) { $newElement = clone $element; $copy = $this->createCopyClosure(); return $copy($newElement); } private function createCopyClosure() { $copier = $this->copier; $copy = function (SplDoublyLinkedList $list) use ($copier) { // Replace each element in the list with a deep copy of itself for ($i = 1; $i <= $list->count(); $i++) { $copy = $copier->recursiveCopy($list->shift()); $list->push($copy); } return $list; }; return Closure::bind($copy, null, DeepCopy::class); } } type = $type; } /** * @param mixed $element * * @return boolean */ public function matches($element) { return is_object($element) ? is_a($element, $this->type) : gettype($element) === $this->type; } } copy($value); } } BSD 3-Clause License Copyright (c) 2011, Nikita Popov 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. PHP Parser ========== [![Coverage Status](https://coveralls.io/repos/github/nikic/PHP-Parser/badge.svg?branch=master)](https://coveralls.io/github/nikic/PHP-Parser?branch=master) This is a PHP parser written in PHP. Its purpose is to simplify static code analysis and manipulation. [**Documentation for version 5.x**][doc_master] (current; for running on PHP >= 7.4; for parsing PHP 7.0 to PHP 8.4, with limited support for parsing PHP 5.x). [Documentation for version 4.x][doc_4_x] (supported; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 8.3). Features -------- The main features provided by this library are: * Parsing PHP 7, and PHP 8 code into an abstract syntax tree (AST). * Invalid code can be parsed into a partial AST. * The AST contains accurate location information. * Dumping the AST in human-readable form. * Converting an AST back to PHP code. * Formatting can be preserved for partially changed ASTs. * Infrastructure to traverse and modify ASTs. * Resolution of namespaced names. * Evaluation of constant expressions. * Builders to simplify AST construction for code generation. * Converting an AST into JSON and back. Quick Start ----------- Install the library using [composer](https://getcomposer.org): php composer.phar require nikic/php-parser Parse some PHP code into an AST and dump the result in human-readable form: ```php createForNewestSupportedVersion(); try { $ast = $parser->parse($code); } catch (Error $error) { echo "Parse error: {$error->getMessage()}\n"; return; } $dumper = new NodeDumper; echo $dumper->dump($ast) . "\n"; ``` This dumps an AST looking something like this: ``` array( 0: Stmt_Function( attrGroups: array( ) byRef: false name: Identifier( name: test ) params: array( 0: Param( attrGroups: array( ) flags: 0 type: null byRef: false variadic: false var: Expr_Variable( name: foo ) default: null ) ) returnType: null stmts: array( 0: Stmt_Expression( expr: Expr_FuncCall( name: Name( name: var_dump ) args: array( 0: Arg( name: null value: Expr_Variable( name: foo ) byRef: false unpack: false ) ) ) ) ) ) ) ``` Let's traverse the AST and perform some kind of modification. For example, drop all function bodies: ```php use PhpParser\Node; use PhpParser\Node\Stmt\Function_; use PhpParser\NodeTraverser; use PhpParser\NodeVisitorAbstract; $traverser = new NodeTraverser(); $traverser->addVisitor(new class extends NodeVisitorAbstract { public function enterNode(Node $node) { if ($node instanceof Function_) { // Clean out the function body $node->stmts = []; } } }); $ast = $traverser->traverse($ast); echo $dumper->dump($ast) . "\n"; ``` This gives us an AST where the `Function_::$stmts` are empty: ``` array( 0: Stmt_Function( attrGroups: array( ) byRef: false name: Identifier( name: test ) params: array( 0: Param( attrGroups: array( ) type: null byRef: false variadic: false var: Expr_Variable( name: foo ) default: null ) ) returnType: null stmts: array( ) ) ) ``` Finally, we can convert the new AST back to PHP code: ```php use PhpParser\PrettyPrinter; $prettyPrinter = new PrettyPrinter\Standard; echo $prettyPrinter->prettyPrintFile($ast); ``` This gives us our original code, minus the `var_dump()` call inside the function: ```php createForVersion($attributes['version']); $dumper = new PhpParser\NodeDumper([ 'dumpComments' => true, 'dumpPositions' => $attributes['with-positions'], ]); $prettyPrinter = new PhpParser\PrettyPrinter\Standard; $traverser = new PhpParser\NodeTraverser(); $traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); foreach ($files as $file) { if ($file === '-') { $code = file_get_contents('php://stdin'); fwrite(STDERR, "====> Stdin:\n"); } else if (strpos($file, ' Code $code\n"); } else { if (!file_exists($file)) { fwrite(STDERR, "File $file does not exist.\n"); exit(1); } $code = file_get_contents($file); fwrite(STDERR, "====> File $file:\n"); } if ($attributes['with-recovery']) { $errorHandler = new PhpParser\ErrorHandler\Collecting; $stmts = $parser->parse($code, $errorHandler); foreach ($errorHandler->getErrors() as $error) { $message = formatErrorMessage($error, $code, $attributes['with-column-info']); fwrite(STDERR, $message . "\n"); } if (null === $stmts) { continue; } } else { try { $stmts = $parser->parse($code); } catch (PhpParser\Error $error) { $message = formatErrorMessage($error, $code, $attributes['with-column-info']); fwrite(STDERR, $message . "\n"); exit(1); } } foreach ($operations as $operation) { if ('dump' === $operation) { fwrite(STDERR, "==> Node dump:\n"); echo $dumper->dump($stmts, $code), "\n"; } elseif ('pretty-print' === $operation) { fwrite(STDERR, "==> Pretty print:\n"); echo $prettyPrinter->prettyPrintFile($stmts), "\n"; } elseif ('json-dump' === $operation) { fwrite(STDERR, "==> JSON dump:\n"); echo json_encode($stmts, JSON_PRETTY_PRINT), "\n"; } elseif ('var-dump' === $operation) { fwrite(STDERR, "==> var_dump():\n"); var_dump($stmts); } elseif ('resolve-names' === $operation) { fwrite(STDERR, "==> Resolved names.\n"); $stmts = $traverser->traverse($stmts); } } } function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) { if ($withColumnInfo && $e->hasColumnInfo()) { return $e->getMessageWithColumnInfo($code); } else { return $e->getMessage(); } } function showHelp($error = '') { if ($error) { fwrite(STDERR, $error . "\n\n"); } fwrite($error ? STDERR : STDOUT, <<<'OUTPUT' Usage: php-parse [operations] file1.php [file2.php ...] or: php-parse [operations] " false, 'with-positions' => false, 'with-recovery' => false, 'version' => PhpParser\PhpVersion::getNewestSupported(), ]; array_shift($args); $parseOptions = true; foreach ($args as $arg) { if (!$parseOptions) { $files[] = $arg; continue; } switch ($arg) { case '--dump': case '-d': $operations[] = 'dump'; break; case '--pretty-print': case '-p': $operations[] = 'pretty-print'; break; case '--json-dump': case '-j': $operations[] = 'json-dump'; break; case '--var-dump': $operations[] = 'var-dump'; break; case '--resolve-names': case '-N': $operations[] = 'resolve-names'; break; case '--with-column-info': case '-c': $attributes['with-column-info'] = true; break; case '--with-positions': case '-P': $attributes['with-positions'] = true; break; case '--with-recovery': case '-r': $attributes['with-recovery'] = true; break; case '--help': case '-h': showHelp(); break; case '--': $parseOptions = false; break; default: if (preg_match('/^--version=(.*)$/', $arg, $matches)) { $attributes['version'] = PhpParser\PhpVersion::fromString($matches[1]); } elseif ($arg[0] === '-' && \strlen($arg[0]) > 1) { showHelp("Invalid operation $arg."); } else { $files[] = $arg; } } } return [$operations, $files, $attributes]; } { "name": "nikic/php-parser", "type": "library", "description": "A PHP parser written in PHP", "keywords": [ "php", "parser" ], "license": "BSD-3-Clause", "authors": [ { "name": "Nikita Popov" } ], "require": { "php": ">=7.4", "ext-tokenizer": "*", "ext-json": "*" }, "require-dev": { "phpunit/phpunit": "^9.0", "ircmaxell/php-yacc": "^0.0.7" }, "extra": { "branch-alias": { "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { "PhpParser\\": "lib/PhpParser" } }, "autoload-dev": { "psr-4": { "PhpParser\\": "test/PhpParser/" } }, "bin": [ "bin/php-parse" ] } */ protected array $attributes = []; /** @var list */ protected array $constants = []; /** @var list */ protected array $attributeGroups = []; /** @var Identifier|Node\Name|Node\ComplexType|null */ protected ?Node $type = null; /** * Creates a class constant builder * * @param string|Identifier $name Name * @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value Value */ public function __construct($name, $value) { $this->constants = [new Const_($name, BuilderHelpers::normalizeValue($value))]; } /** * Add another constant to const group * * @param string|Identifier $name Name * @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value Value * * @return $this The builder instance (for fluid interface) */ public function addConst($name, $value) { $this->constants[] = new Const_($name, BuilderHelpers::normalizeValue($value)); return $this; } /** * Makes the constant public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PUBLIC); return $this; } /** * Makes the constant protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED); return $this; } /** * Makes the constant private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE); return $this; } /** * Makes the constant final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::FINAL); return $this; } /** * Sets doc comment for the constant. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes = [ 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] ]; return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Sets the constant type. * * @param string|Node\Name|Identifier|Node\ComplexType $type * * @return $this */ public function setType($type) { $this->type = BuilderHelpers::normalizeType($type); return $this; } /** * Returns the built class node. * * @return Stmt\ClassConst The built constant node */ public function getNode(): PhpParser\Node { return new Stmt\ClassConst( $this->constants, $this->flags, $this->attributes, $this->attributeGroups, $this->type ); } } */ protected array $implements = []; protected int $flags = 0; /** @var list */ protected array $uses = []; /** @var list */ protected array $constants = []; /** @var list */ protected array $properties = []; /** @var list */ protected array $methods = []; /** @var list */ protected array $attributeGroups = []; /** * Creates a class builder. * * @param string $name Name of the class */ public function __construct(string $name) { $this->name = $name; } /** * Extends a class. * * @param Name|string $class Name of class to extend * * @return $this The builder instance (for fluid interface) */ public function extend($class) { $this->extends = BuilderHelpers::normalizeName($class); return $this; } /** * Implements one or more interfaces. * * @param Name|string ...$interfaces Names of interfaces to implement * * @return $this The builder instance (for fluid interface) */ public function implement(...$interfaces) { foreach ($interfaces as $interface) { $this->implements[] = BuilderHelpers::normalizeName($interface); } return $this; } /** * Makes the class abstract. * * @return $this The builder instance (for fluid interface) */ public function makeAbstract() { $this->flags = BuilderHelpers::addClassModifier($this->flags, Modifiers::ABSTRACT); return $this; } /** * Makes the class final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->flags = BuilderHelpers::addClassModifier($this->flags, Modifiers::FINAL); return $this; } /** * Makes the class readonly. * * @return $this The builder instance (for fluid interface) */ public function makeReadonly() { $this->flags = BuilderHelpers::addClassModifier($this->flags, Modifiers::READONLY); return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = BuilderHelpers::normalizeNode($stmt); if ($stmt instanceof Stmt\Property) { $this->properties[] = $stmt; } elseif ($stmt instanceof Stmt\ClassMethod) { $this->methods[] = $stmt; } elseif ($stmt instanceof Stmt\TraitUse) { $this->uses[] = $stmt; } elseif ($stmt instanceof Stmt\ClassConst) { $this->constants[] = $stmt; } else { throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); } return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built class node. * * @return Stmt\Class_ The built class node */ public function getNode(): PhpParser\Node { return new Stmt\Class_($this->name, [ 'flags' => $this->flags, 'extends' => $this->extends, 'implements' => $this->implements, 'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods), 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } */ protected array $attributes = []; /** * Adds a statement. * * @param PhpParser\Node\Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ abstract public function addStmt($stmt); /** * Adds multiple statements. * * @param (PhpParser\Node\Stmt|PhpParser\Builder)[] $stmts The statements to add * * @return $this The builder instance (for fluid interface) */ public function addStmts(array $stmts) { foreach ($stmts as $stmt) { $this->addStmt($stmt); } return $this; } /** * Sets doc comment for the declaration. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes['comments'] = [ BuilderHelpers::normalizeDocComment($docComment) ]; return $this; } } */ protected array $attributes = []; /** @var list */ protected array $attributeGroups = []; /** * Creates an enum case builder. * * @param string|Identifier $name Name */ public function __construct($name) { $this->name = $name; } /** * Sets the value. * * @param Node\Expr|string|int $value * * @return $this */ public function setValue($value) { $this->value = BuilderHelpers::normalizeValue($value); return $this; } /** * Sets doc comment for the constant. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes = [ 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] ]; return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built enum case node. * * @return Stmt\EnumCase The built constant node */ public function getNode(): PhpParser\Node { return new Stmt\EnumCase( $this->name, $this->value, $this->attributeGroups, $this->attributes ); } } */ protected array $implements = []; /** @var list */ protected array $uses = []; /** @var list */ protected array $enumCases = []; /** @var list */ protected array $constants = []; /** @var list */ protected array $methods = []; /** @var list */ protected array $attributeGroups = []; /** * Creates an enum builder. * * @param string $name Name of the enum */ public function __construct(string $name) { $this->name = $name; } /** * Sets the scalar type. * * @param string|Identifier $scalarType * * @return $this */ public function setScalarType($scalarType) { $this->scalarType = BuilderHelpers::normalizeType($scalarType); return $this; } /** * Implements one or more interfaces. * * @param Name|string ...$interfaces Names of interfaces to implement * * @return $this The builder instance (for fluid interface) */ public function implement(...$interfaces) { foreach ($interfaces as $interface) { $this->implements[] = BuilderHelpers::normalizeName($interface); } return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = BuilderHelpers::normalizeNode($stmt); if ($stmt instanceof Stmt\EnumCase) { $this->enumCases[] = $stmt; } elseif ($stmt instanceof Stmt\ClassMethod) { $this->methods[] = $stmt; } elseif ($stmt instanceof Stmt\TraitUse) { $this->uses[] = $stmt; } elseif ($stmt instanceof Stmt\ClassConst) { $this->constants[] = $stmt; } else { throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); } return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built class node. * * @return Stmt\Enum_ The built enum node */ public function getNode(): PhpParser\Node { return new Stmt\Enum_($this->name, [ 'scalarType' => $this->scalarType, 'implements' => $this->implements, 'stmts' => array_merge($this->uses, $this->enumCases, $this->constants, $this->methods), 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } returnByRef = true; return $this; } /** * Adds a parameter. * * @param Node\Param|Param $param The parameter to add * * @return $this The builder instance (for fluid interface) */ public function addParam($param) { $param = BuilderHelpers::normalizeNode($param); if (!$param instanceof Node\Param) { throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType())); } $this->params[] = $param; return $this; } /** * Adds multiple parameters. * * @param (Node\Param|Param)[] $params The parameters to add * * @return $this The builder instance (for fluid interface) */ public function addParams(array $params) { foreach ($params as $param) { $this->addParam($param); } return $this; } /** * Sets the return type for PHP 7. * * @param string|Node\Name|Node\Identifier|Node\ComplexType $type * * @return $this The builder instance (for fluid interface) */ public function setReturnType($type) { $this->returnType = BuilderHelpers::normalizeType($type); return $this; } } */ protected array $stmts = []; /** @var list */ protected array $attributeGroups = []; /** * Creates a function builder. * * @param string $name Name of the function */ public function __construct(string $name) { $this->name = $name; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built function node. * * @return Stmt\Function_ The built function node */ public function getNode(): Node { return new Stmt\Function_($this->name, [ 'byRef' => $this->returnByRef, 'params' => $this->params, 'returnType' => $this->returnType, 'stmts' => $this->stmts, 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } */ protected array $extends = []; /** @var list */ protected array $constants = []; /** @var list */ protected array $methods = []; /** @var list */ protected array $attributeGroups = []; /** * Creates an interface builder. * * @param string $name Name of the interface */ public function __construct(string $name) { $this->name = $name; } /** * Extends one or more interfaces. * * @param Name|string ...$interfaces Names of interfaces to extend * * @return $this The builder instance (for fluid interface) */ public function extend(...$interfaces) { foreach ($interfaces as $interface) { $this->extends[] = BuilderHelpers::normalizeName($interface); } return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = BuilderHelpers::normalizeNode($stmt); if ($stmt instanceof Stmt\ClassConst) { $this->constants[] = $stmt; } elseif ($stmt instanceof Stmt\ClassMethod) { // we erase all statements in the body of an interface method $stmt->stmts = null; $this->methods[] = $stmt; } else { throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); } return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built interface node. * * @return Stmt\Interface_ The built interface node */ public function getNode(): PhpParser\Node { return new Stmt\Interface_($this->name, [ 'extends' => $this->extends, 'stmts' => array_merge($this->constants, $this->methods), 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } |null */ protected ?array $stmts = []; /** @var list */ protected array $attributeGroups = []; /** * Creates a method builder. * * @param string $name Name of the method */ public function __construct(string $name) { $this->name = $name; } /** * Makes the method public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PUBLIC); return $this; } /** * Makes the method protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED); return $this; } /** * Makes the method private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE); return $this; } /** * Makes the method static. * * @return $this The builder instance (for fluid interface) */ public function makeStatic() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::STATIC); return $this; } /** * Makes the method abstract. * * @return $this The builder instance (for fluid interface) */ public function makeAbstract() { if (!empty($this->stmts)) { throw new \LogicException('Cannot make method with statements abstract'); } $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::ABSTRACT); $this->stmts = null; // abstract methods don't have statements return $this; } /** * Makes the method final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::FINAL); return $this; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { if (null === $this->stmts) { throw new \LogicException('Cannot add statements to an abstract method'); } $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built method node. * * @return Stmt\ClassMethod The built method node */ public function getNode(): Node { return new Stmt\ClassMethod($this->name, [ 'flags' => $this->flags, 'byRef' => $this->returnByRef, 'params' => $this->params, 'returnType' => $this->returnType, 'stmts' => $this->stmts, 'attrGroups' => $this->attributeGroups, ], $this->attributes); } } name = null !== $name ? BuilderHelpers::normalizeName($name) : null; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); return $this; } /** * Returns the built node. * * @return Stmt\Namespace_ The built node */ public function getNode(): Node { return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes); } } */ protected array $attributeGroups = []; /** * Creates a parameter builder. * * @param string $name Name of the parameter */ public function __construct(string $name) { $this->name = $name; } /** * Sets default value for the parameter. * * @param mixed $value Default value to use * * @return $this The builder instance (for fluid interface) */ public function setDefault($value) { $this->default = BuilderHelpers::normalizeValue($value); return $this; } /** * Sets type for the parameter. * * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type * * @return $this The builder instance (for fluid interface) */ public function setType($type) { $this->type = BuilderHelpers::normalizeType($type); if ($this->type == 'void') { throw new \LogicException('Parameter type cannot be void'); } return $this; } /** * Make the parameter accept the value by reference. * * @return $this The builder instance (for fluid interface) */ public function makeByRef() { $this->byRef = true; return $this; } /** * Make the parameter variadic * * @return $this The builder instance (for fluid interface) */ public function makeVariadic() { $this->variadic = true; return $this; } /** * Makes the (promoted) parameter public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PUBLIC); return $this; } /** * Makes the (promoted) parameter protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED); return $this; } /** * Makes the (promoted) parameter private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE); return $this; } /** * Makes the (promoted) parameter readonly. * * @return $this The builder instance (for fluid interface) */ public function makeReadonly() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::READONLY); return $this; } /** * Gives the promoted property private(set) visibility. * * @return $this The builder instance (for fluid interface) */ public function makePrivateSet() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE_SET); return $this; } /** * Gives the promoted property protected(set) visibility. * * @return $this The builder instance (for fluid interface) */ public function makeProtectedSet() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED_SET); return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built parameter node. * * @return Node\Param The built parameter node */ public function getNode(): Node { return new Node\Param( new Node\Expr\Variable($this->name), $this->default, $this->type, $this->byRef, $this->variadic, [], $this->flags, $this->attributeGroups ); } } */ protected array $attributes = []; /** @var null|Identifier|Name|ComplexType */ protected ?Node $type = null; /** @var list */ protected array $attributeGroups = []; /** @var list */ protected array $hooks = []; /** * Creates a property builder. * * @param string $name Name of the property */ public function __construct(string $name) { $this->name = $name; } /** * Makes the property public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PUBLIC); return $this; } /** * Makes the property protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED); return $this; } /** * Makes the property private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE); return $this; } /** * Makes the property static. * * @return $this The builder instance (for fluid interface) */ public function makeStatic() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::STATIC); return $this; } /** * Makes the property readonly. * * @return $this The builder instance (for fluid interface) */ public function makeReadonly() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::READONLY); return $this; } /** * Makes the property abstract. Requires at least one property hook to be specified as well. * * @return $this The builder instance (for fluid interface) */ public function makeAbstract() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::ABSTRACT); return $this; } /** * Makes the property final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::FINAL); return $this; } /** * Gives the property private(set) visibility. * * @return $this The builder instance (for fluid interface) */ public function makePrivateSet() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE_SET); return $this; } /** * Gives the property protected(set) visibility. * * @return $this The builder instance (for fluid interface) */ public function makeProtectedSet() { $this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED_SET); return $this; } /** * Sets default value for the property. * * @param mixed $value Default value to use * * @return $this The builder instance (for fluid interface) */ public function setDefault($value) { $this->default = BuilderHelpers::normalizeValue($value); return $this; } /** * Sets doc comment for the property. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes = [ 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] ]; return $this; } /** * Sets the property type for PHP 7.4+. * * @param string|Name|Identifier|ComplexType $type * * @return $this */ public function setType($type) { $this->type = BuilderHelpers::normalizeType($type); return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Adds a property hook. * * @return $this The builder instance (for fluid interface) */ public function addHook(Node\PropertyHook $hook) { $this->hooks[] = $hook; return $this; } /** * Returns the built class node. * * @return Stmt\Property The built property node */ public function getNode(): PhpParser\Node { if ($this->flags & Modifiers::ABSTRACT && !$this->hooks) { throw new PhpParser\Error('Only hooked properties may be declared abstract'); } return new Stmt\Property( $this->flags !== 0 ? $this->flags : Modifiers::PUBLIC, [ new Node\PropertyItem($this->name, $this->default) ], $this->attributes, $this->type, $this->attributeGroups, $this->hooks ); } } and($trait); } } /** * Adds used trait. * * @param Node\Name|string $trait Trait name * * @return $this The builder instance (for fluid interface) */ public function and($trait) { $this->traits[] = BuilderHelpers::normalizeName($trait); return $this; } /** * Adds trait adaptation. * * @param Stmt\TraitUseAdaptation|Builder\TraitUseAdaptation $adaptation Trait adaptation * * @return $this The builder instance (for fluid interface) */ public function with($adaptation) { $adaptation = BuilderHelpers::normalizeNode($adaptation); if (!$adaptation instanceof Stmt\TraitUseAdaptation) { throw new \LogicException('Adaptation must have type TraitUseAdaptation'); } $this->adaptations[] = $adaptation; return $this; } /** * Returns the built node. * * @return Node The built node */ public function getNode(): Node { return new Stmt\TraitUse($this->traits, $this->adaptations); } } type = self::TYPE_UNDEFINED; $this->trait = is_null($trait) ? null : BuilderHelpers::normalizeName($trait); $this->method = BuilderHelpers::normalizeIdentifier($method); } /** * Sets alias of method. * * @param Node\Identifier|string $alias Alias for adapted method * * @return $this The builder instance (for fluid interface) */ public function as($alias) { if ($this->type === self::TYPE_UNDEFINED) { $this->type = self::TYPE_ALIAS; } if ($this->type !== self::TYPE_ALIAS) { throw new \LogicException('Cannot set alias for not alias adaptation buider'); } $this->alias = BuilderHelpers::normalizeIdentifier($alias); return $this; } /** * Sets adapted method public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->setModifier(Modifiers::PUBLIC); return $this; } /** * Sets adapted method protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->setModifier(Modifiers::PROTECTED); return $this; } /** * Sets adapted method private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->setModifier(Modifiers::PRIVATE); return $this; } /** * Adds overwritten traits. * * @param Node\Name|string ...$traits Traits for overwrite * * @return $this The builder instance (for fluid interface) */ public function insteadof(...$traits) { if ($this->type === self::TYPE_UNDEFINED) { if (is_null($this->trait)) { throw new \LogicException('Precedence adaptation must have trait'); } $this->type = self::TYPE_PRECEDENCE; } if ($this->type !== self::TYPE_PRECEDENCE) { throw new \LogicException('Cannot add overwritten traits for not precedence adaptation buider'); } foreach ($traits as $trait) { $this->insteadof[] = BuilderHelpers::normalizeName($trait); } return $this; } protected function setModifier(int $modifier): void { if ($this->type === self::TYPE_UNDEFINED) { $this->type = self::TYPE_ALIAS; } if ($this->type !== self::TYPE_ALIAS) { throw new \LogicException('Cannot set access modifier for not alias adaptation buider'); } if (is_null($this->modifier)) { $this->modifier = $modifier; } else { throw new \LogicException('Multiple access type modifiers are not allowed'); } } /** * Returns the built node. * * @return Node The built node */ public function getNode(): Node { switch ($this->type) { case self::TYPE_ALIAS: return new Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias); case self::TYPE_PRECEDENCE: return new Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof); default: throw new \LogicException('Type of adaptation is not defined'); } } } */ protected array $uses = []; /** @var list */ protected array $constants = []; /** @var list */ protected array $properties = []; /** @var list */ protected array $methods = []; /** @var list */ protected array $attributeGroups = []; /** * Creates an interface builder. * * @param string $name Name of the interface */ public function __construct(string $name) { $this->name = $name; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = BuilderHelpers::normalizeNode($stmt); if ($stmt instanceof Stmt\Property) { $this->properties[] = $stmt; } elseif ($stmt instanceof Stmt\ClassMethod) { $this->methods[] = $stmt; } elseif ($stmt instanceof Stmt\TraitUse) { $this->uses[] = $stmt; } elseif ($stmt instanceof Stmt\ClassConst) { $this->constants[] = $stmt; } else { throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); } return $this; } /** * Adds an attribute group. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return $this The builder instance (for fluid interface) */ public function addAttribute($attribute) { $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); return $this; } /** * Returns the built trait node. * * @return Stmt\Trait_ The built interface node */ public function getNode(): PhpParser\Node { return new Stmt\Trait_( $this->name, [ 'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods), 'attrGroups' => $this->attributeGroups, ], $this->attributes ); } } name = BuilderHelpers::normalizeName($name); $this->type = $type; } /** * Sets alias for used name. * * @param string $alias Alias to use (last component of full name by default) * * @return $this The builder instance (for fluid interface) */ public function as(string $alias) { $this->alias = $alias; return $this; } /** * Returns the built node. * * @return Stmt\Use_ The built node */ public function getNode(): Node { return new Stmt\Use_([ new Node\UseItem($this->name, $this->alias) ], $this->type); } } args($args) ); } /** * Creates a namespace builder. * * @param null|string|Node\Name $name Name of the namespace * * @return Builder\Namespace_ The created namespace builder */ public function namespace($name): Builder\Namespace_ { return new Builder\Namespace_($name); } /** * Creates a class builder. * * @param string $name Name of the class * * @return Builder\Class_ The created class builder */ public function class(string $name): Builder\Class_ { return new Builder\Class_($name); } /** * Creates an interface builder. * * @param string $name Name of the interface * * @return Builder\Interface_ The created interface builder */ public function interface(string $name): Builder\Interface_ { return new Builder\Interface_($name); } /** * Creates a trait builder. * * @param string $name Name of the trait * * @return Builder\Trait_ The created trait builder */ public function trait(string $name): Builder\Trait_ { return new Builder\Trait_($name); } /** * Creates an enum builder. * * @param string $name Name of the enum * * @return Builder\Enum_ The created enum builder */ public function enum(string $name): Builder\Enum_ { return new Builder\Enum_($name); } /** * Creates a trait use builder. * * @param Node\Name|string ...$traits Trait names * * @return Builder\TraitUse The created trait use builder */ public function useTrait(...$traits): Builder\TraitUse { return new Builder\TraitUse(...$traits); } /** * Creates a trait use adaptation builder. * * @param Node\Name|string|null $trait Trait name * @param Node\Identifier|string $method Method name * * @return Builder\TraitUseAdaptation The created trait use adaptation builder */ public function traitUseAdaptation($trait, $method = null): Builder\TraitUseAdaptation { if ($method === null) { $method = $trait; $trait = null; } return new Builder\TraitUseAdaptation($trait, $method); } /** * Creates a method builder. * * @param string $name Name of the method * * @return Builder\Method The created method builder */ public function method(string $name): Builder\Method { return new Builder\Method($name); } /** * Creates a parameter builder. * * @param string $name Name of the parameter * * @return Builder\Param The created parameter builder */ public function param(string $name): Builder\Param { return new Builder\Param($name); } /** * Creates a property builder. * * @param string $name Name of the property * * @return Builder\Property The created property builder */ public function property(string $name): Builder\Property { return new Builder\Property($name); } /** * Creates a function builder. * * @param string $name Name of the function * * @return Builder\Function_ The created function builder */ public function function(string $name): Builder\Function_ { return new Builder\Function_($name); } /** * Creates a namespace/class use builder. * * @param Node\Name|string $name Name of the entity (namespace or class) to alias * * @return Builder\Use_ The created use builder */ public function use($name): Builder\Use_ { return new Builder\Use_($name, Use_::TYPE_NORMAL); } /** * Creates a function use builder. * * @param Node\Name|string $name Name of the function to alias * * @return Builder\Use_ The created use function builder */ public function useFunction($name): Builder\Use_ { return new Builder\Use_($name, Use_::TYPE_FUNCTION); } /** * Creates a constant use builder. * * @param Node\Name|string $name Name of the const to alias * * @return Builder\Use_ The created use const builder */ public function useConst($name): Builder\Use_ { return new Builder\Use_($name, Use_::TYPE_CONSTANT); } /** * Creates a class constant builder. * * @param string|Identifier $name Name * @param Node\Expr|bool|null|int|float|string|array $value Value * * @return Builder\ClassConst The created use const builder */ public function classConst($name, $value): Builder\ClassConst { return new Builder\ClassConst($name, $value); } /** * Creates an enum case builder. * * @param string|Identifier $name Name * * @return Builder\EnumCase The created use const builder */ public function enumCase($name): Builder\EnumCase { return new Builder\EnumCase($name); } /** * Creates node a for a literal value. * * @param Expr|bool|null|int|float|string|array|\UnitEnum $value $value */ public function val($value): Expr { return BuilderHelpers::normalizeValue($value); } /** * Creates variable node. * * @param string|Expr $name Name */ public function var($name): Expr\Variable { if (!\is_string($name) && !$name instanceof Expr) { throw new \LogicException('Variable name must be string or Expr'); } return new Expr\Variable($name); } /** * Normalizes an argument list. * * Creates Arg nodes for all arguments and converts literal values to expressions. * * @param array $args List of arguments to normalize * * @return list */ public function args(array $args): array { $normalizedArgs = []; foreach ($args as $key => $arg) { if (!($arg instanceof Arg)) { $arg = new Arg(BuilderHelpers::normalizeValue($arg)); } if (\is_string($key)) { $arg->name = BuilderHelpers::normalizeIdentifier($key); } $normalizedArgs[] = $arg; } return $normalizedArgs; } /** * Creates a function call node. * * @param string|Name|Expr $name Function name * @param array $args Function arguments */ public function funcCall($name, array $args = []): Expr\FuncCall { return new Expr\FuncCall( BuilderHelpers::normalizeNameOrExpr($name), $this->args($args) ); } /** * Creates a method call node. * * @param Expr $var Variable the method is called on * @param string|Identifier|Expr $name Method name * @param array $args Method arguments */ public function methodCall(Expr $var, $name, array $args = []): Expr\MethodCall { return new Expr\MethodCall( $var, BuilderHelpers::normalizeIdentifierOrExpr($name), $this->args($args) ); } /** * Creates a static method call node. * * @param string|Name|Expr $class Class name * @param string|Identifier|Expr $name Method name * @param array $args Method arguments */ public function staticCall($class, $name, array $args = []): Expr\StaticCall { return new Expr\StaticCall( BuilderHelpers::normalizeNameOrExpr($class), BuilderHelpers::normalizeIdentifierOrExpr($name), $this->args($args) ); } /** * Creates an object creation node. * * @param string|Name|Expr $class Class name * @param array $args Constructor arguments */ public function new($class, array $args = []): Expr\New_ { return new Expr\New_( BuilderHelpers::normalizeNameOrExpr($class), $this->args($args) ); } /** * Creates a constant fetch node. * * @param string|Name $name Constant name */ public function constFetch($name): Expr\ConstFetch { return new Expr\ConstFetch(BuilderHelpers::normalizeName($name)); } /** * Creates a property fetch node. * * @param Expr $var Variable holding object * @param string|Identifier|Expr $name Property name */ public function propertyFetch(Expr $var, $name): Expr\PropertyFetch { return new Expr\PropertyFetch($var, BuilderHelpers::normalizeIdentifierOrExpr($name)); } /** * Creates a class constant fetch node. * * @param string|Name|Expr $class Class name * @param string|Identifier|Expr $name Constant name */ public function classConstFetch($class, $name): Expr\ClassConstFetch { return new Expr\ClassConstFetch( BuilderHelpers::normalizeNameOrExpr($class), BuilderHelpers::normalizeIdentifierOrExpr($name) ); } /** * Creates nested Concat nodes from a list of expressions. * * @param Expr|string ...$exprs Expressions or literal strings */ public function concat(...$exprs): Concat { $numExprs = count($exprs); if ($numExprs < 2) { throw new \LogicException('Expected at least two expressions'); } $lastConcat = $this->normalizeStringExpr($exprs[0]); for ($i = 1; $i < $numExprs; $i++) { $lastConcat = new Concat($lastConcat, $this->normalizeStringExpr($exprs[$i])); } return $lastConcat; } /** * @param string|Expr $expr */ private function normalizeStringExpr($expr): Expr { if ($expr instanceof Expr) { return $expr; } if (\is_string($expr)) { return new String_($expr); } throw new \LogicException('Expected string or Expr'); } } getNode(); } if ($node instanceof Node) { return $node; } throw new \LogicException('Expected node or builder object'); } /** * Normalizes a node to a statement. * * Expressions are wrapped in a Stmt\Expression node. * * @param Node|Builder $node The node to normalize * * @return Stmt The normalized statement node */ public static function normalizeStmt($node): Stmt { $node = self::normalizeNode($node); if ($node instanceof Stmt) { return $node; } if ($node instanceof Expr) { return new Stmt\Expression($node); } throw new \LogicException('Expected statement or expression node'); } /** * Normalizes strings to Identifier. * * @param string|Identifier $name The identifier to normalize * * @return Identifier The normalized identifier */ public static function normalizeIdentifier($name): Identifier { if ($name instanceof Identifier) { return $name; } if (\is_string($name)) { return new Identifier($name); } throw new \LogicException('Expected string or instance of Node\Identifier'); } /** * Normalizes strings to Identifier, also allowing expressions. * * @param string|Identifier|Expr $name The identifier to normalize * * @return Identifier|Expr The normalized identifier or expression */ public static function normalizeIdentifierOrExpr($name) { if ($name instanceof Identifier || $name instanceof Expr) { return $name; } if (\is_string($name)) { return new Identifier($name); } throw new \LogicException('Expected string or instance of Node\Identifier or Node\Expr'); } /** * Normalizes a name: Converts string names to Name nodes. * * @param Name|string $name The name to normalize * * @return Name The normalized name */ public static function normalizeName($name): Name { if ($name instanceof Name) { return $name; } if (is_string($name)) { if (!$name) { throw new \LogicException('Name cannot be empty'); } if ($name[0] === '\\') { return new Name\FullyQualified(substr($name, 1)); } if (0 === strpos($name, 'namespace\\')) { return new Name\Relative(substr($name, strlen('namespace\\'))); } return new Name($name); } throw new \LogicException('Name must be a string or an instance of Node\Name'); } /** * Normalizes a name: Converts string names to Name nodes, while also allowing expressions. * * @param Expr|Name|string $name The name to normalize * * @return Name|Expr The normalized name or expression */ public static function normalizeNameOrExpr($name) { if ($name instanceof Expr) { return $name; } if (!is_string($name) && !($name instanceof Name)) { throw new \LogicException( 'Name must be a string or an instance of Node\Name or Node\Expr' ); } return self::normalizeName($name); } /** * Normalizes a type: Converts plain-text type names into proper AST representation. * * In particular, builtin types become Identifiers, custom types become Names and nullables * are wrapped in NullableType nodes. * * @param string|Name|Identifier|ComplexType $type The type to normalize * * @return Name|Identifier|ComplexType The normalized type */ public static function normalizeType($type) { if (!is_string($type)) { if ( !$type instanceof Name && !$type instanceof Identifier && !$type instanceof ComplexType ) { throw new \LogicException( 'Type must be a string, or an instance of Name, Identifier or ComplexType' ); } return $type; } $nullable = false; if (strlen($type) > 0 && $type[0] === '?') { $nullable = true; $type = substr($type, 1); } $builtinTypes = [ 'array', 'callable', 'bool', 'int', 'float', 'string', 'iterable', 'void', 'object', 'null', 'false', 'mixed', 'never', 'true', ]; $lowerType = strtolower($type); if (in_array($lowerType, $builtinTypes)) { $type = new Identifier($lowerType); } else { $type = self::normalizeName($type); } $notNullableTypes = [ 'void', 'mixed', 'never', ]; if ($nullable && in_array((string) $type, $notNullableTypes)) { throw new \LogicException(sprintf('%s type cannot be nullable', $type)); } return $nullable ? new NullableType($type) : $type; } /** * Normalizes a value: Converts nulls, booleans, integers, * floats, strings and arrays into their respective nodes * * @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value The value to normalize * * @return Expr The normalized value */ public static function normalizeValue($value): Expr { if ($value instanceof Node\Expr) { return $value; } if (is_null($value)) { return new Expr\ConstFetch( new Name('null') ); } if (is_bool($value)) { return new Expr\ConstFetch( new Name($value ? 'true' : 'false') ); } if (is_int($value)) { return new Scalar\Int_($value); } if (is_float($value)) { return new Scalar\Float_($value); } if (is_string($value)) { return new Scalar\String_($value); } if (is_array($value)) { $items = []; $lastKey = -1; foreach ($value as $itemKey => $itemValue) { // for consecutive, numeric keys don't generate keys if (null !== $lastKey && ++$lastKey === $itemKey) { $items[] = new Node\ArrayItem( self::normalizeValue($itemValue) ); } else { $lastKey = null; $items[] = new Node\ArrayItem( self::normalizeValue($itemValue), self::normalizeValue($itemKey) ); } } return new Expr\Array_($items); } if ($value instanceof \UnitEnum) { return new Expr\ClassConstFetch(new FullyQualified(\get_class($value)), new Identifier($value->name)); } throw new \LogicException('Invalid value'); } /** * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc. * * @param Comment\Doc|string $docComment The doc comment to normalize * * @return Comment\Doc The normalized doc comment */ public static function normalizeDocComment($docComment): Comment\Doc { if ($docComment instanceof Comment\Doc) { return $docComment; } if (is_string($docComment)) { return new Comment\Doc($docComment); } throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); } /** * Normalizes a attribute: Converts attribute to the Attribute Group if needed. * * @param Node\Attribute|Node\AttributeGroup $attribute * * @return Node\AttributeGroup The Attribute Group */ public static function normalizeAttribute($attribute): Node\AttributeGroup { if ($attribute instanceof Node\AttributeGroup) { return $attribute; } if (!($attribute instanceof Node\Attribute)) { throw new \LogicException('Attribute must be an instance of PhpParser\Node\Attribute or PhpParser\Node\AttributeGroup'); } return new Node\AttributeGroup([$attribute]); } /** * Adds a modifier and returns new modifier bitmask. * * @param int $modifiers Existing modifiers * @param int $modifier Modifier to set * * @return int New modifiers */ public static function addModifier(int $modifiers, int $modifier): int { Modifiers::verifyModifier($modifiers, $modifier); return $modifiers | $modifier; } /** * Adds a modifier and returns new modifier bitmask. * @return int New modifiers */ public static function addClassModifier(int $existingModifiers, int $modifierToSet): int { Modifiers::verifyClassModifier($existingModifiers, $modifierToSet); return $existingModifiers | $modifierToSet; } } text = $text; $this->startLine = $startLine; $this->startFilePos = $startFilePos; $this->startTokenPos = $startTokenPos; $this->endLine = $endLine; $this->endFilePos = $endFilePos; $this->endTokenPos = $endTokenPos; } /** * Gets the comment text. * * @return string The comment text (including comment delimiters like /*) */ public function getText(): string { return $this->text; } /** * Gets the line number the comment started on. * * @return int Line number (or -1 if not available) * @phpstan-return -1|positive-int */ public function getStartLine(): int { return $this->startLine; } /** * Gets the file offset the comment started on. * * @return int File offset (or -1 if not available) */ public function getStartFilePos(): int { return $this->startFilePos; } /** * Gets the token offset the comment started on. * * @return int Token offset (or -1 if not available) */ public function getStartTokenPos(): int { return $this->startTokenPos; } /** * Gets the line number the comment ends on. * * @return int Line number (or -1 if not available) * @phpstan-return -1|positive-int */ public function getEndLine(): int { return $this->endLine; } /** * Gets the file offset the comment ends on. * * @return int File offset (or -1 if not available) */ public function getEndFilePos(): int { return $this->endFilePos; } /** * Gets the token offset the comment ends on. * * @return int Token offset (or -1 if not available) */ public function getEndTokenPos(): int { return $this->endTokenPos; } /** * Gets the comment text. * * @return string The comment text (including comment delimiters like /*) */ public function __toString(): string { return $this->text; } /** * Gets the reformatted comment text. * * "Reformatted" here means that we try to clean up the whitespace at the * starts of the lines. This is necessary because we receive the comments * without leading whitespace on the first line, but with leading whitespace * on all subsequent lines. * * Additionally, this normalizes CRLF newlines to LF newlines. */ public function getReformattedText(): string { $text = str_replace("\r\n", "\n", $this->text); $newlinePos = strpos($text, "\n"); if (false === $newlinePos) { // Single line comments don't need further processing return $text; } if (preg_match('(^.*(?:\n\s+\*.*)+$)', $text)) { // Multi line comment of the type // // /* // * Some text. // * Some more text. // */ // // is handled by replacing the whitespace sequences before the * by a single space return preg_replace('(^\s+\*)m', ' *', $text); } if (preg_match('(^/\*\*?\s*\n)', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) { // Multi line comment of the type // // /* // Some text. // Some more text. // */ // // is handled by removing the whitespace sequence on the line before the closing // */ on all lines. So if the last line is " */", then " " is removed at the // start of all lines. return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text); } if (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) { // Multi line comment of the type // // /* Some text. // Some more text. // Indented text. // Even more text. */ // // is handled by removing the difference between the shortest whitespace prefix on all // lines and the length of the "/* " opening sequence. $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1)); $removeLen = $prefixLen - strlen($matches[0]); return preg_replace('(^\s{' . $removeLen . '})m', '', $text); } // No idea how to format this comment, so simply return as is return $text; } /** * Get length of shortest whitespace prefix (at the start of a line). * * If there is a line with no prefix whitespace, 0 is a valid return value. * * @param string $str String to check * @return int Length in characters. Tabs count as single characters. */ private function getShortestWhitespacePrefixLen(string $str): int { $lines = explode("\n", $str); $shortestPrefixLen = \PHP_INT_MAX; foreach ($lines as $line) { preg_match('(^\s*)', $line, $matches); $prefixLen = strlen($matches[0]); if ($prefixLen < $shortestPrefixLen) { $shortestPrefixLen = $prefixLen; } } return $shortestPrefixLen; } /** * @return array{nodeType:string, text:mixed, line:mixed, filePos:mixed} */ public function jsonSerialize(): array { // Technically not a node, but we make it look like one anyway $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment'; return [ 'nodeType' => $type, 'text' => $this->text, // TODO: Rename these to include "start". 'line' => $this->startLine, 'filePos' => $this->startFilePos, 'tokenPos' => $this->startTokenPos, 'endLine' => $this->endLine, 'endFilePos' => $this->endFilePos, 'endTokenPos' => $this->endTokenPos, ]; } } fallbackEvaluator = $fallbackEvaluator ?? function (Expr $expr) { throw new ConstExprEvaluationException( "Expression of type {$expr->getType()} cannot be evaluated" ); }; } /** * Silently evaluates a constant expression into a PHP value. * * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException. * The original source of the exception is available through getPrevious(). * * If some part of the expression cannot be evaluated, the fallback evaluator passed to the * constructor will be invoked. By default, if no fallback is provided, an exception of type * ConstExprEvaluationException is thrown. * * See class doc comment for caveats and limitations. * * @param Expr $expr Constant expression to evaluate * @return mixed Result of evaluation * * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred */ public function evaluateSilently(Expr $expr) { set_error_handler(function ($num, $str, $file, $line) { throw new \ErrorException($str, 0, $num, $file, $line); }); try { return $this->evaluate($expr); } catch (\Throwable $e) { if (!$e instanceof ConstExprEvaluationException) { $e = new ConstExprEvaluationException( "An error occurred during constant expression evaluation", 0, $e); } throw $e; } finally { restore_error_handler(); } } /** * Directly evaluates a constant expression into a PHP value. * * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these * into a ConstExprEvaluationException. * * If some part of the expression cannot be evaluated, the fallback evaluator passed to the * constructor will be invoked. By default, if no fallback is provided, an exception of type * ConstExprEvaluationException is thrown. * * See class doc comment for caveats and limitations. * * @param Expr $expr Constant expression to evaluate * @return mixed Result of evaluation * * @throws ConstExprEvaluationException if the expression cannot be evaluated */ public function evaluateDirectly(Expr $expr) { return $this->evaluate($expr); } /** @return mixed */ private function evaluate(Expr $expr) { if ($expr instanceof Scalar\Int_ || $expr instanceof Scalar\Float_ || $expr instanceof Scalar\String_ ) { return $expr->value; } if ($expr instanceof Expr\Array_) { return $this->evaluateArray($expr); } // Unary operators if ($expr instanceof Expr\UnaryPlus) { return +$this->evaluate($expr->expr); } if ($expr instanceof Expr\UnaryMinus) { return -$this->evaluate($expr->expr); } if ($expr instanceof Expr\BooleanNot) { return !$this->evaluate($expr->expr); } if ($expr instanceof Expr\BitwiseNot) { return ~$this->evaluate($expr->expr); } if ($expr instanceof Expr\BinaryOp) { return $this->evaluateBinaryOp($expr); } if ($expr instanceof Expr\Ternary) { return $this->evaluateTernary($expr); } if ($expr instanceof Expr\ArrayDimFetch && null !== $expr->dim) { return $this->evaluate($expr->var)[$this->evaluate($expr->dim)]; } if ($expr instanceof Expr\ConstFetch) { return $this->evaluateConstFetch($expr); } return ($this->fallbackEvaluator)($expr); } private function evaluateArray(Expr\Array_ $expr): array { $array = []; foreach ($expr->items as $item) { if (null !== $item->key) { $array[$this->evaluate($item->key)] = $this->evaluate($item->value); } elseif ($item->unpack) { $array = array_merge($array, $this->evaluate($item->value)); } else { $array[] = $this->evaluate($item->value); } } return $array; } /** @return mixed */ private function evaluateTernary(Expr\Ternary $expr) { if (null === $expr->if) { return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else); } return $this->evaluate($expr->cond) ? $this->evaluate($expr->if) : $this->evaluate($expr->else); } /** @return mixed */ private function evaluateBinaryOp(Expr\BinaryOp $expr) { if ($expr instanceof Expr\BinaryOp\Coalesce && $expr->left instanceof Expr\ArrayDimFetch ) { // This needs to be special cased to respect BP_VAR_IS fetch semantics return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)] ?? $this->evaluate($expr->right); } // The evaluate() calls are repeated in each branch, because some of the operators are // short-circuiting and evaluating the RHS in advance may be illegal in that case $l = $expr->left; $r = $expr->right; switch ($expr->getOperatorSigil()) { case '&': return $this->evaluate($l) & $this->evaluate($r); case '|': return $this->evaluate($l) | $this->evaluate($r); case '^': return $this->evaluate($l) ^ $this->evaluate($r); case '&&': return $this->evaluate($l) && $this->evaluate($r); case '||': return $this->evaluate($l) || $this->evaluate($r); case '??': return $this->evaluate($l) ?? $this->evaluate($r); case '.': return $this->evaluate($l) . $this->evaluate($r); case '/': return $this->evaluate($l) / $this->evaluate($r); case '==': return $this->evaluate($l) == $this->evaluate($r); case '>': return $this->evaluate($l) > $this->evaluate($r); case '>=': return $this->evaluate($l) >= $this->evaluate($r); case '===': return $this->evaluate($l) === $this->evaluate($r); case 'and': return $this->evaluate($l) and $this->evaluate($r); case 'or': return $this->evaluate($l) or $this->evaluate($r); case 'xor': return $this->evaluate($l) xor $this->evaluate($r); case '-': return $this->evaluate($l) - $this->evaluate($r); case '%': return $this->evaluate($l) % $this->evaluate($r); case '*': return $this->evaluate($l) * $this->evaluate($r); case '!=': return $this->evaluate($l) != $this->evaluate($r); case '!==': return $this->evaluate($l) !== $this->evaluate($r); case '+': return $this->evaluate($l) + $this->evaluate($r); case '**': return $this->evaluate($l) ** $this->evaluate($r); case '<<': return $this->evaluate($l) << $this->evaluate($r); case '>>': return $this->evaluate($l) >> $this->evaluate($r); case '<': return $this->evaluate($l) < $this->evaluate($r); case '<=': return $this->evaluate($l) <= $this->evaluate($r); case '<=>': return $this->evaluate($l) <=> $this->evaluate($r); case '|>': return ($this->fallbackEvaluator)($expr); } throw new \Exception('Should not happen'); } /** @return mixed */ private function evaluateConstFetch(Expr\ConstFetch $expr) { $name = $expr->name->toLowerString(); switch ($name) { case 'null': return null; case 'false': return false; case 'true': return true; } return ($this->fallbackEvaluator)($expr); } } */ protected array $attributes; /** * Creates an Exception signifying a parse error. * * @param string $message Error message * @param array $attributes Attributes of node/token where error occurred */ public function __construct(string $message, array $attributes = []) { $this->rawMessage = $message; $this->attributes = $attributes; $this->updateMessage(); } /** * Gets the error message * * @return string Error message */ public function getRawMessage(): string { return $this->rawMessage; } /** * Gets the line the error starts in. * * @return int Error start line * @phpstan-return -1|positive-int */ public function getStartLine(): int { return $this->attributes['startLine'] ?? -1; } /** * Gets the line the error ends in. * * @return int Error end line * @phpstan-return -1|positive-int */ public function getEndLine(): int { return $this->attributes['endLine'] ?? -1; } /** * Gets the attributes of the node/token the error occurred at. * * @return array */ public function getAttributes(): array { return $this->attributes; } /** * Sets the attributes of the node/token the error occurred at. * * @param array $attributes */ public function setAttributes(array $attributes): void { $this->attributes = $attributes; $this->updateMessage(); } /** * Sets the line of the PHP file the error occurred in. * * @param string $message Error message */ public function setRawMessage(string $message): void { $this->rawMessage = $message; $this->updateMessage(); } /** * Sets the line the error starts in. * * @param int $line Error start line */ public function setStartLine(int $line): void { $this->attributes['startLine'] = $line; $this->updateMessage(); } /** * Returns whether the error has start and end column information. * * For column information enable the startFilePos and endFilePos in the lexer options. */ public function hasColumnInfo(): bool { return isset($this->attributes['startFilePos'], $this->attributes['endFilePos']); } /** * Gets the start column (1-based) into the line where the error started. * * @param string $code Source code of the file */ public function getStartColumn(string $code): int { if (!$this->hasColumnInfo()) { throw new \RuntimeException('Error does not have column information'); } return $this->toColumn($code, $this->attributes['startFilePos']); } /** * Gets the end column (1-based) into the line where the error ended. * * @param string $code Source code of the file */ public function getEndColumn(string $code): int { if (!$this->hasColumnInfo()) { throw new \RuntimeException('Error does not have column information'); } return $this->toColumn($code, $this->attributes['endFilePos']); } /** * Formats message including line and column information. * * @param string $code Source code associated with the error, for calculation of the columns * * @return string Formatted message */ public function getMessageWithColumnInfo(string $code): string { return sprintf( '%s from %d:%d to %d:%d', $this->getRawMessage(), $this->getStartLine(), $this->getStartColumn($code), $this->getEndLine(), $this->getEndColumn($code) ); } /** * Converts a file offset into a column. * * @param string $code Source code that $pos indexes into * @param int $pos 0-based position in $code * * @return int 1-based column (relative to start of line) */ private function toColumn(string $code, int $pos): int { if ($pos > strlen($code)) { throw new \RuntimeException('Invalid position information'); } $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); if (false === $lineStartPos) { $lineStartPos = -1; } return $pos - $lineStartPos; } /** * Updates the exception message after a change to rawMessage or rawLine. */ protected function updateMessage(): void { $this->message = $this->rawMessage; if (-1 === $this->getStartLine()) { $this->message .= ' on unknown line'; } else { $this->message .= ' on line ' . $this->getStartLine(); } } } errors[] = $error; } /** * Get collected errors. * * @return Error[] */ public function getErrors(): array { return $this->errors; } /** * Check whether there are any errors. */ public function hasErrors(): bool { return !empty($this->errors); } /** * Reset/clear collected errors. */ public function clearErrors(): void { $this->errors = []; } } type = $type; $this->old = $old; $this->new = $new; } } 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 { $old = \array_values($old); $new = \array_values($new); list($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, 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> $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; } } $attributes Attributes */ public function __construct( array $attrGroups, int $flags, array $args, ?Node\Name $extends, array $implements, array $stmts, array $attributes ) { parent::__construct($attributes); $this->attrGroups = $attrGroups; $this->flags = $flags; $this->args = $args; $this->extends = $extends; $this->implements = $implements; $this->stmts = $stmts; } public static function fromNewNode(Expr\New_ $newNode): self { $class = $newNode->class; assert($class instanceof Node\Stmt\Class_); // We don't assert that $class->name is null here, to allow consumers to assign unique names // to anonymous classes for their own purposes. We simplify ignore the name here. return new self( $class->attrGroups, $class->flags, $newNode->args, $class->extends, $class->implements, $class->stmts, $newNode->getAttributes() ); } public function getType(): string { return 'Expr_PrintableNewAnonClass'; } public function getSubNodeNames(): array { return ['attrGroups', 'flags', 'args', 'extends', 'implements', 'stmts']; } } = 80000) { class TokenPolyfill extends \PhpToken { } return; } /** * This is a polyfill for the PhpToken class introduced in PHP 8.0. We do not actually polyfill * PhpToken, because composer might end up picking a different polyfill implementation, which does * not meet our requirements. * * @internal */ class TokenPolyfill { /** @var int The ID of the token. Either a T_* constant of a character code < 256. */ public int $id; /** @var string The textual content of the token. */ public string $text; /** @var int The 1-based starting line of the token (or -1 if unknown). */ public int $line; /** @var int The 0-based starting position of the token (or -1 if unknown). */ public int $pos; /** @var array Tokens ignored by the PHP parser. */ private const IGNORABLE_TOKENS = [ \T_WHITESPACE => true, \T_COMMENT => true, \T_DOC_COMMENT => true, \T_OPEN_TAG => true, ]; /** @var array Tokens that may be part of a T_NAME_* identifier. */ private static array $identifierTokens; /** * Create a Token with the given ID and text, as well optional line and position information. */ final public function __construct(int $id, string $text, int $line = -1, int $pos = -1) { $this->id = $id; $this->text = $text; $this->line = $line; $this->pos = $pos; } /** * Get the name of the token. For single-char tokens this will be the token character. * Otherwise it will be a T_* style name, or null if the token ID is unknown. */ public function getTokenName(): ?string { if ($this->id < 256) { return \chr($this->id); } $name = token_name($this->id); return $name === 'UNKNOWN' ? null : $name; } /** * Check whether the token is of the given kind. The kind may be either an integer that matches * the token ID, a string that matches the token text, or an array of integers/strings. In the * latter case, the function returns true if any of the kinds in the array match. * * @param int|string|(int|string)[] $kind */ public function is($kind): bool { if (\is_int($kind)) { return $this->id === $kind; } if (\is_string($kind)) { return $this->text === $kind; } if (\is_array($kind)) { foreach ($kind as $entry) { if (\is_int($entry)) { if ($this->id === $entry) { return true; } } elseif (\is_string($entry)) { if ($this->text === $entry) { return true; } } else { throw new \TypeError( 'Argument #1 ($kind) must only have elements of type string|int, ' . gettype($entry) . ' given'); } } return false; } throw new \TypeError( 'Argument #1 ($kind) must be of type string|int|array, ' .gettype($kind) . ' given'); } /** * Check whether this token would be ignored by the PHP parser. Returns true for T_WHITESPACE, * T_COMMENT, T_DOC_COMMENT and T_OPEN_TAG, and false for everything else. */ public function isIgnorable(): bool { return isset(self::IGNORABLE_TOKENS[$this->id]); } /** * Return the textual content of the token. */ public function __toString(): string { return $this->text; } /** * Tokenize the given source code and return an array of tokens. * * This performs certain canonicalizations to match the PHP 8.0 token format: * * Bad characters are represented using T_BAD_CHARACTER rather than omitted. * * T_COMMENT does not include trailing newlines, instead the newline is part of a following * T_WHITESPACE token. * * Namespaced names are represented using T_NAME_* tokens. * * @return static[] */ public static function tokenize(string $code, int $flags = 0): array { self::init(); $tokens = []; $line = 1; $pos = 0; $origTokens = \token_get_all($code, $flags); $numTokens = \count($origTokens); for ($i = 0; $i < $numTokens; $i++) { $token = $origTokens[$i]; if (\is_string($token)) { if (\strlen($token) === 2) { // b" and B" are tokenized as single-char tokens, even though they aren't. $tokens[] = new static(\ord('"'), $token, $line, $pos); $pos += 2; } else { $tokens[] = new static(\ord($token), $token, $line, $pos); $pos++; } } else { $id = $token[0]; $text = $token[1]; // Emulate PHP 8.0 comment format, which does not include trailing whitespace anymore. if ($id === \T_COMMENT && \substr($text, 0, 2) !== '/*' && \preg_match('/(\r\n|\n|\r)$/D', $text, $matches) ) { $trailingNewline = $matches[0]; $text = \substr($text, 0, -\strlen($trailingNewline)); $tokens[] = new static($id, $text, $line, $pos); $pos += \strlen($text); if ($i + 1 < $numTokens && $origTokens[$i + 1][0] === \T_WHITESPACE) { // Move trailing newline into following T_WHITESPACE token, if it already exists. $origTokens[$i + 1][1] = $trailingNewline . $origTokens[$i + 1][1]; $origTokens[$i + 1][2]--; } else { // Otherwise, we need to create a new T_WHITESPACE token. $tokens[] = new static(\T_WHITESPACE, $trailingNewline, $line, $pos); $line++; $pos += \strlen($trailingNewline); } continue; } // Emulate PHP 8.0 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and // T_STRING into a single token. if (($id === \T_NS_SEPARATOR || isset(self::$identifierTokens[$id]))) { $newText = $text; $lastWasSeparator = $id === \T_NS_SEPARATOR; for ($j = $i + 1; $j < $numTokens; $j++) { if ($lastWasSeparator) { if (!isset(self::$identifierTokens[$origTokens[$j][0]])) { break; } $lastWasSeparator = false; } else { if ($origTokens[$j][0] !== \T_NS_SEPARATOR) { break; } $lastWasSeparator = true; } $newText .= $origTokens[$j][1]; } if ($lastWasSeparator) { // Trailing separator is not part of the name. $j--; $newText = \substr($newText, 0, -1); } if ($j > $i + 1) { if ($id === \T_NS_SEPARATOR) { $id = \T_NAME_FULLY_QUALIFIED; } elseif ($id === \T_NAMESPACE) { $id = \T_NAME_RELATIVE; } else { $id = \T_NAME_QUALIFIED; } $tokens[] = new static($id, $newText, $line, $pos); $pos += \strlen($newText); $i = $j - 1; continue; } } $tokens[] = new static($id, $text, $line, $pos); $line += \substr_count($text, "\n"); $pos += \strlen($text); } } return $tokens; } /** Initialize private static state needed by tokenize(). */ private static function init(): void { if (isset(self::$identifierTokens)) { return; } // Based on semi_reserved production. self::$identifierTokens = \array_fill_keys([ \T_STRING, \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY, \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND, \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE, \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH, \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO, \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT, \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS, \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN, \T_MATCH, ], true); } } tokens = $tokens; $this->indentMap = $this->calcIndentMap($tabWidth); } /** * Whether the given position is immediately surrounded by parenthesis. * * @param int $startPos Start position * @param int $endPos End position */ public function haveParens(int $startPos, int $endPos): bool { return $this->haveTokenImmediatelyBefore($startPos, '(') && $this->haveTokenImmediatelyAfter($endPos, ')'); } /** * Whether the given position is immediately surrounded by braces. * * @param int $startPos Start position * @param int $endPos End position */ public function haveBraces(int $startPos, int $endPos): bool { return ($this->haveTokenImmediatelyBefore($startPos, '{') || $this->haveTokenImmediatelyBefore($startPos, T_CURLY_OPEN)) && $this->haveTokenImmediatelyAfter($endPos, '}'); } /** * Check whether the position is directly preceded by a certain token type. * * During this check whitespace and comments are skipped. * * @param int $pos Position before which the token should occur * @param int|string $expectedTokenType Token to check for * * @return bool Whether the expected token was found */ public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType): bool { $tokens = $this->tokens; $pos--; for (; $pos >= 0; $pos--) { $token = $tokens[$pos]; if ($token->is($expectedTokenType)) { return true; } if (!$token->isIgnorable()) { break; } } return false; } /** * Check whether the position is directly followed by a certain token type. * * During this check whitespace and comments are skipped. * * @param int $pos Position after which the token should occur * @param int|string $expectedTokenType Token to check for * * @return bool Whether the expected token was found */ public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType): bool { $tokens = $this->tokens; $pos++; for ($c = \count($tokens); $pos < $c; $pos++) { $token = $tokens[$pos]; if ($token->is($expectedTokenType)) { return true; } if (!$token->isIgnorable()) { break; } } return false; } /** @param int|string|(int|string)[] $skipTokenType */ public function skipLeft(int $pos, $skipTokenType): int { $tokens = $this->tokens; $pos = $this->skipLeftWhitespace($pos); if ($skipTokenType === \T_WHITESPACE) { return $pos; } if (!$tokens[$pos]->is($skipTokenType)) { // Shouldn't happen. The skip token MUST be there throw new \Exception('Encountered unexpected token'); } $pos--; return $this->skipLeftWhitespace($pos); } /** @param int|string|(int|string)[] $skipTokenType */ public function skipRight(int $pos, $skipTokenType): int { $tokens = $this->tokens; $pos = $this->skipRightWhitespace($pos); if ($skipTokenType === \T_WHITESPACE) { return $pos; } if (!$tokens[$pos]->is($skipTokenType)) { // Shouldn't happen. The skip token MUST be there throw new \Exception('Encountered unexpected token'); } $pos++; return $this->skipRightWhitespace($pos); } /** * Return first non-whitespace token position smaller or equal to passed position. * * @param int $pos Token position * @return int Non-whitespace token position */ public function skipLeftWhitespace(int $pos): int { $tokens = $this->tokens; for (; $pos >= 0; $pos--) { if (!$tokens[$pos]->isIgnorable()) { break; } } return $pos; } /** * Return first non-whitespace position greater or equal to passed position. * * @param int $pos Token position * @return int Non-whitespace token position */ public function skipRightWhitespace(int $pos): int { $tokens = $this->tokens; for ($count = \count($tokens); $pos < $count; $pos++) { if (!$tokens[$pos]->isIgnorable()) { break; } } return $pos; } /** @param int|string|(int|string)[] $findTokenType */ public function findRight(int $pos, $findTokenType): int { $tokens = $this->tokens; for ($count = \count($tokens); $pos < $count; $pos++) { if ($tokens[$pos]->is($findTokenType)) { return $pos; } } return -1; } /** * Whether the given position range contains a certain token type. * * @param int $startPos Starting position (inclusive) * @param int $endPos Ending position (exclusive) * @param int|string $tokenType Token type to look for * @return bool Whether the token occurs in the given range */ public function haveTokenInRange(int $startPos, int $endPos, $tokenType): bool { $tokens = $this->tokens; for ($pos = $startPos; $pos < $endPos; $pos++) { if ($tokens[$pos]->is($tokenType)) { return true; } } return false; } public function haveTagInRange(int $startPos, int $endPos): bool { return $this->haveTokenInRange($startPos, $endPos, \T_OPEN_TAG) || $this->haveTokenInRange($startPos, $endPos, \T_CLOSE_TAG); } /** * Get indentation before token position. * * @param int $pos Token position * * @return int Indentation depth (in spaces) */ public function getIndentationBefore(int $pos): int { return $this->indentMap[$pos]; } /** * Get the code corresponding to a token offset range, optionally adjusted for indentation. * * @param int $from Token start position (inclusive) * @param int $to Token end position (exclusive) * @param int $indent By how much the code should be indented (can be negative as well) * * @return string Code corresponding to token range, adjusted for indentation */ public function getTokenCode(int $from, int $to, int $indent): string { $tokens = $this->tokens; $result = ''; for ($pos = $from; $pos < $to; $pos++) { $token = $tokens[$pos]; $id = $token->id; $text = $token->text; if ($id === \T_CONSTANT_ENCAPSED_STRING || $id === \T_ENCAPSED_AND_WHITESPACE) { $result .= $text; } else { // TODO Handle non-space indentation if ($indent < 0) { $result .= str_replace("\n" . str_repeat(" ", -$indent), "\n", $text); } elseif ($indent > 0) { $result .= str_replace("\n", "\n" . str_repeat(" ", $indent), $text); } else { $result .= $text; } } } return $result; } /** * Precalculate the indentation at every token position. * * @return int[] Token position to indentation map */ private function calcIndentMap(int $tabWidth): array { $indentMap = []; $indent = 0; foreach ($this->tokens as $i => $token) { $indentMap[] = $indent; if ($token->id === \T_WHITESPACE) { $content = $token->text; $newlinePos = \strrpos($content, "\n"); if (false !== $newlinePos) { $indent = $this->getIndent(\substr($content, $newlinePos + 1), $tabWidth); } elseif ($i === 1 && $this->tokens[0]->id === \T_OPEN_TAG && $this->tokens[0]->text[\strlen($this->tokens[0]->text) - 1] === "\n") { // Special case: Newline at the end of opening tag followed by whitespace. $indent = $this->getIndent($content, $tabWidth); } } } // Add a sentinel for one past end of the file $indentMap[] = $indent; return $indentMap; } private function getIndent(string $ws, int $tabWidth): int { $spaces = \substr_count($ws, " "); $tabs = \substr_count($ws, "\t"); assert(\strlen($ws) === $spaces + $tabs); return $spaces + $tabs * $tabWidth; } } [] Node type to reflection class map */ private array $reflectionClassCache; /** @return mixed */ public function decode(string $json) { $value = json_decode($json, true); if (json_last_error()) { throw new \RuntimeException('JSON decoding error: ' . json_last_error_msg()); } return $this->decodeRecursive($value); } /** * @param mixed $value * @return mixed */ private function decodeRecursive($value) { if (\is_array($value)) { if (isset($value['nodeType'])) { if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') { return $this->decodeComment($value); } return $this->decodeNode($value); } return $this->decodeArray($value); } return $value; } private function decodeArray(array $array): array { $decodedArray = []; foreach ($array as $key => $value) { $decodedArray[$key] = $this->decodeRecursive($value); } return $decodedArray; } private function decodeNode(array $value): Node { $nodeType = $value['nodeType']; if (!\is_string($nodeType)) { throw new \RuntimeException('Node type must be a string'); } $reflectionClass = $this->reflectionClassFromNodeType($nodeType); $node = $reflectionClass->newInstanceWithoutConstructor(); if (isset($value['attributes'])) { if (!\is_array($value['attributes'])) { throw new \RuntimeException('Attributes must be an array'); } $node->setAttributes($this->decodeArray($value['attributes'])); } foreach ($value as $name => $subNode) { if ($name === 'nodeType' || $name === 'attributes') { continue; } $node->$name = $this->decodeRecursive($subNode); } return $node; } private function decodeComment(array $value): Comment { $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class; if (!isset($value['text'])) { throw new \RuntimeException('Comment must have text'); } return new $className( $value['text'], $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1, $value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1 ); } /** @return \ReflectionClass */ private function reflectionClassFromNodeType(string $nodeType): \ReflectionClass { if (!isset($this->reflectionClassCache[$nodeType])) { $className = $this->classNameFromNodeType($nodeType); $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className); } return $this->reflectionClassCache[$nodeType]; } /** @return class-string */ private function classNameFromNodeType(string $nodeType): string { $className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\'); if (class_exists($className)) { return $className; } $className .= '_'; if (class_exists($className)) { return $className; } throw new \RuntimeException("Unknown node type \"$nodeType\""); } } postprocessTokens($tokens, $errorHandler); if (false !== $scream) { ini_set('xdebug.scream', $scream); } return $tokens; } private function handleInvalidCharacter(Token $token, ErrorHandler $errorHandler): void { $chr = $token->text; if ($chr === "\0") { // PHP cuts error message after null byte, so need special case $errorMsg = 'Unexpected null byte'; } else { $errorMsg = sprintf( 'Unexpected character "%s" (ASCII %d)', $chr, ord($chr) ); } $errorHandler->handleError(new Error($errorMsg, [ 'startLine' => $token->line, 'endLine' => $token->line, 'startFilePos' => $token->pos, 'endFilePos' => $token->pos, ])); } private function isUnterminatedComment(Token $token): bool { return $token->is([\T_COMMENT, \T_DOC_COMMENT]) && substr($token->text, 0, 2) === '/*' && substr($token->text, -2) !== '*/'; } /** * @param list $tokens */ protected function postprocessTokens(array &$tokens, ErrorHandler $errorHandler): void { // This function reports errors (bad characters and unterminated comments) in the token // array, and performs certain canonicalizations: // * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and // T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types. // * Add a sentinel token with ID 0. $numTokens = \count($tokens); if ($numTokens === 0) { // Empty input edge case: Just add the sentinel token. $tokens[] = new Token(0, "\0", 1, 0); return; } for ($i = 0; $i < $numTokens; $i++) { $token = $tokens[$i]; if ($token->id === \T_BAD_CHARACTER) { $this->handleInvalidCharacter($token, $errorHandler); } if ($token->id === \ord('&')) { $next = $i + 1; while (isset($tokens[$next]) && $tokens[$next]->id === \T_WHITESPACE) { $next++; } $followedByVarOrVarArg = isset($tokens[$next]) && $tokens[$next]->is([\T_VARIABLE, \T_ELLIPSIS]); $token->id = $followedByVarOrVarArg ? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG : \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG; } } // Check for unterminated comment $lastToken = $tokens[$numTokens - 1]; if ($this->isUnterminatedComment($lastToken)) { $errorHandler->handleError(new Error('Unterminated comment', [ 'startLine' => $lastToken->line, 'endLine' => $lastToken->getEndLine(), 'startFilePos' => $lastToken->pos, 'endFilePos' => $lastToken->getEndPos(), ])); } // Add sentinel token. $tokens[] = new Token(0, "\0", $lastToken->getEndLine(), $lastToken->getEndPos()); } } */ private array $emulators = []; private PhpVersion $targetPhpVersion; private PhpVersion $hostPhpVersion; /** * @param PhpVersion|null $phpVersion PHP version to emulate. Defaults to newest supported. */ public function __construct(?PhpVersion $phpVersion = null) { $this->targetPhpVersion = $phpVersion ?? PhpVersion::getNewestSupported(); $this->hostPhpVersion = PhpVersion::getHostVersion(); $emulators = [ new FnTokenEmulator(), new MatchTokenEmulator(), new NullsafeTokenEmulator(), new AttributeEmulator(), new EnumTokenEmulator(), new ReadonlyTokenEmulator(), new ExplicitOctalEmulator(), new ReadonlyFunctionTokenEmulator(), new PropertyTokenEmulator(), new AsymmetricVisibilityTokenEmulator(), new PipeOperatorEmulator(), new VoidCastEmulator(), ]; // Collect emulators that are relevant for the PHP version we're running // and the PHP version we're targeting for emulation. foreach ($emulators as $emulator) { $emulatorPhpVersion = $emulator->getPhpVersion(); if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) { $this->emulators[] = $emulator; } elseif ($this->isReverseEmulationNeeded($emulatorPhpVersion)) { $this->emulators[] = new ReverseEmulator($emulator); } } } public function tokenize(string $code, ?ErrorHandler $errorHandler = null): array { $emulators = array_filter($this->emulators, function ($emulator) use ($code) { return $emulator->isEmulationNeeded($code); }); if (empty($emulators)) { // Nothing to emulate, yay return parent::tokenize($code, $errorHandler); } if ($errorHandler === null) { $errorHandler = new ErrorHandler\Throwing(); } $this->patches = []; foreach ($emulators as $emulator) { $code = $emulator->preprocessCode($code, $this->patches); } $collector = new ErrorHandler\Collecting(); $tokens = parent::tokenize($code, $collector); $this->sortPatches(); $tokens = $this->fixupTokens($tokens); $errors = $collector->getErrors(); if (!empty($errors)) { $this->fixupErrors($errors); foreach ($errors as $error) { $errorHandler->handleError($error); } } foreach ($emulators as $emulator) { $tokens = $emulator->emulate($code, $tokens); } return $tokens; } private function isForwardEmulationNeeded(PhpVersion $emulatorPhpVersion): bool { return $this->hostPhpVersion->older($emulatorPhpVersion) && $this->targetPhpVersion->newerOrEqual($emulatorPhpVersion); } private function isReverseEmulationNeeded(PhpVersion $emulatorPhpVersion): bool { return $this->hostPhpVersion->newerOrEqual($emulatorPhpVersion) && $this->targetPhpVersion->older($emulatorPhpVersion); } private function sortPatches(): void { // Patches may be contributed by different emulators. // Make sure they are sorted by increasing patch position. usort($this->patches, function ($p1, $p2) { return $p1[0] <=> $p2[0]; }); } /** * @param list $tokens * @return list */ private function fixupTokens(array $tokens): array { if (\count($this->patches) === 0) { return $tokens; } // Load first patch $patchIdx = 0; list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; // We use a manual loop over the tokens, because we modify the array on the fly $posDelta = 0; $lineDelta = 0; for ($i = 0, $c = \count($tokens); $i < $c; $i++) { $token = $tokens[$i]; $pos = $token->pos; $token->pos += $posDelta; $token->line += $lineDelta; $localPosDelta = 0; $len = \strlen($token->text); while ($patchPos >= $pos && $patchPos < $pos + $len) { $patchTextLen = \strlen($patchText); if ($patchType === 'remove') { if ($patchPos === $pos && $patchTextLen === $len) { // Remove token entirely array_splice($tokens, $i, 1, []); $i--; $c--; } else { // Remove from token string $token->text = substr_replace( $token->text, '', $patchPos - $pos + $localPosDelta, $patchTextLen ); $localPosDelta -= $patchTextLen; } $lineDelta -= \substr_count($patchText, "\n"); } elseif ($patchType === 'add') { // Insert into the token string $token->text = substr_replace( $token->text, $patchText, $patchPos - $pos + $localPosDelta, 0 ); $localPosDelta += $patchTextLen; $lineDelta += \substr_count($patchText, "\n"); } elseif ($patchType === 'replace') { // Replace inside the token string $token->text = substr_replace( $token->text, $patchText, $patchPos - $pos + $localPosDelta, $patchTextLen ); } else { assert(false); } // Fetch the next patch $patchIdx++; if ($patchIdx >= \count($this->patches)) { // No more patches. However, we still need to adjust position. $patchPos = \PHP_INT_MAX; break; } list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; } $posDelta += $localPosDelta; } return $tokens; } /** * Fixup line and position information in errors. * * @param Error[] $errors */ private function fixupErrors(array $errors): void { foreach ($errors as $error) { $attrs = $error->getAttributes(); $posDelta = 0; $lineDelta = 0; foreach ($this->patches as $patch) { list($patchPos, $patchType, $patchText) = $patch; if ($patchPos >= $attrs['startFilePos']) { // No longer relevant break; } if ($patchType === 'add') { $posDelta += strlen($patchText); $lineDelta += substr_count($patchText, "\n"); } elseif ($patchType === 'remove') { $posDelta -= strlen($patchText); $lineDelta -= substr_count($patchText, "\n"); } } $attrs['startFilePos'] += $posDelta; $attrs['endFilePos'] += $posDelta; $attrs['startLine'] += $lineDelta; $attrs['endLine'] += $lineDelta; $error->setAttributes($attrs); } } } \T_PUBLIC_SET, \T_PROTECTED => \T_PROTECTED_SET, \T_PRIVATE => \T_PRIVATE_SET, ]; for ($i = 0, $c = count($tokens); $i < $c; ++$i) { $token = $tokens[$i]; if (isset($map[$token->id]) && $i + 3 < $c && $tokens[$i + 1]->text === '(' && $tokens[$i + 2]->id === \T_STRING && \strtolower($tokens[$i + 2]->text) === 'set' && $tokens[$i + 3]->text === ')' && $this->isKeywordContext($tokens, $i) ) { array_splice($tokens, $i, 4, [ new Token( $map[$token->id], $token->text . '(' . $tokens[$i + 2]->text . ')', $token->line, $token->pos), ]); $c -= 3; } } return $tokens; } public function reverseEmulate(string $code, array $tokens): array { $reverseMap = [ \T_PUBLIC_SET => \T_PUBLIC, \T_PROTECTED_SET => \T_PROTECTED, \T_PRIVATE_SET => \T_PRIVATE, ]; for ($i = 0, $c = count($tokens); $i < $c; ++$i) { $token = $tokens[$i]; if (isset($reverseMap[$token->id]) && \preg_match('/(public|protected|private)\((set)\)/i', $token->text, $matches) ) { [, $modifier, $set] = $matches; $modifierLen = \strlen($modifier); array_splice($tokens, $i, 1, [ new Token($reverseMap[$token->id], $modifier, $token->line, $token->pos), new Token(\ord('('), '(', $token->line, $token->pos + $modifierLen), new Token(\T_STRING, $set, $token->line, $token->pos + $modifierLen + 1), new Token(\ord(')'), ')', $token->line, $token->pos + $modifierLen + 4), ]); $i += 3; $c += 3; } } return $tokens; } /** @param Token[] $tokens */ protected function isKeywordContext(array $tokens, int $pos): bool { $prevToken = $this->getPreviousNonSpaceToken($tokens, $pos); if ($prevToken === null) { return false; } return $prevToken->id !== \T_OBJECT_OPERATOR && $prevToken->id !== \T_NULLSAFE_OBJECT_OPERATOR; } /** @param Token[] $tokens */ private function getPreviousNonSpaceToken(array $tokens, int $start): ?Token { for ($i = $start - 1; $i >= 0; --$i) { if ($tokens[$i]->id === T_WHITESPACE) { continue; } return $tokens[$i]; } return null; } } text === '#' && isset($tokens[$i + 1]) && $tokens[$i + 1]->text === '[') { array_splice($tokens, $i, 2, [ new Token(\T_ATTRIBUTE, '#[', $token->line, $token->pos), ]); $c--; continue; } } return $tokens; } public function reverseEmulate(string $code, array $tokens): array { // TODO return $tokens; } public function preprocessCode(string $code, array &$patches): string { $pos = 0; while (false !== $pos = strpos($code, '#[', $pos)) { // Replace #[ with %[ $code[$pos] = '%'; $patches[] = [$pos, 'replace', '#']; $pos += 2; } return $code; } } id === \T_WHITESPACE && $tokens[$pos + 2]->id === \T_STRING; } } id == \T_LNUMBER && $token->text === '0' && isset($tokens[$i + 1]) && $tokens[$i + 1]->id == \T_STRING && preg_match('/[oO][0-7]+(?:_[0-7]+)*/', $tokens[$i + 1]->text) ) { $tokenKind = $this->resolveIntegerOrFloatToken($tokens[$i + 1]->text); array_splice($tokens, $i, 2, [ new Token($tokenKind, '0' . $tokens[$i + 1]->text, $token->line, $token->pos), ]); $c--; } } return $tokens; } private function resolveIntegerOrFloatToken(string $str): int { $str = substr($str, 1); $str = str_replace('_', '', $str); $num = octdec($str); return is_float($num) ? \T_DNUMBER : \T_LNUMBER; } public function reverseEmulate(string $code, array $tokens): array { // Explicit octals were not legal code previously, don't bother. return $tokens; } } getKeywordString()) !== false; } /** @param Token[] $tokens */ protected function isKeywordContext(array $tokens, int $pos): bool { $prevToken = $this->getPreviousNonIgnorableToken($tokens, $pos); if ($prevToken === null) { return false; } return $prevToken->id !== \T_OBJECT_OPERATOR && $prevToken->id !== \T_NULLSAFE_OBJECT_OPERATOR; } public function emulate(string $code, array $tokens): array { $keywordString = $this->getKeywordString(); foreach ($tokens as $i => $token) { if ($token->id === T_STRING && strtolower($token->text) === $keywordString && $this->isKeywordContext($tokens, $i)) { $token->id = $this->getKeywordToken(); } } return $tokens; } /** @param Token[] $tokens */ private function getPreviousNonIgnorableToken(array $tokens, int $start): ?Token { for ($i = $start - 1; $i >= 0; --$i) { $token = $tokens[$i]; if ($token->id === T_WHITESPACE || $token->id == T_COMMENT || $token->id === T_DOC_COMMENT) { continue; } return $token; } return null; } public function reverseEmulate(string $code, array $tokens): array { $keywordToken = $this->getKeywordToken(); foreach ($tokens as $token) { if ($token->id === $keywordToken) { $token->id = \T_STRING; } } return $tokens; } } ') !== false; } public function emulate(string $code, array $tokens): array { // We need to manually iterate and manage a count because we'll change // the tokens array on the way for ($i = 0, $c = count($tokens); $i < $c; ++$i) { $token = $tokens[$i]; if ($token->text === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1]->id === \T_OBJECT_OPERATOR) { array_splice($tokens, $i, 2, [ new Token(\T_NULLSAFE_OBJECT_OPERATOR, '?->', $token->line, $token->pos), ]); $c--; continue; } // Handle ?-> inside encapsed string. if ($token->id === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1]) && $tokens[$i - 1]->id === \T_VARIABLE && preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $token->text, $matches) ) { $replacement = [ new Token(\T_NULLSAFE_OBJECT_OPERATOR, '?->', $token->line, $token->pos), new Token(\T_STRING, $matches[1], $token->line, $token->pos + 3), ]; $matchLen = \strlen($matches[0]); if ($matchLen !== \strlen($token->text)) { $replacement[] = new Token( \T_ENCAPSED_AND_WHITESPACE, \substr($token->text, $matchLen), $token->line, $token->pos + $matchLen ); } array_splice($tokens, $i, 1, $replacement); $c += \count($replacement) - 1; continue; } } return $tokens; } public function reverseEmulate(string $code, array $tokens): array { // ?-> was not valid code previously, don't bother. return $tokens; } } ') !== false; } public function emulate(string $code, array $tokens): array { for ($i = 0, $c = count($tokens); $i < $c; ++$i) { $token = $tokens[$i]; if ($token->text === '|' && isset($tokens[$i + 1]) && $tokens[$i + 1]->text === '>') { array_splice($tokens, $i, 2, [ new Token(\T_PIPE, '|>', $token->line, $token->pos), ]); $c--; } } return $tokens; } public function reverseEmulate(string $code, array $tokens): array { for ($i = 0, $c = count($tokens); $i < $c; ++$i) { $token = $tokens[$i]; if ($token->id === \T_PIPE) { array_splice($tokens, $i, 1, [ new Token(\ord('|'), '|', $token->line, $token->pos), new Token(\ord('>'), '>', $token->line, $token->pos + 1), ]); $i++; $c++; } } return $tokens; } } text === '(' || ($tokens[$pos + 1]->id === \T_WHITESPACE && isset($tokens[$pos + 2]) && $tokens[$pos + 2]->text === '('))); } } emulator = $emulator; } public function getPhpVersion(): PhpVersion { return $this->emulator->getPhpVersion(); } public function isEmulationNeeded(string $code): bool { return $this->emulator->isEmulationNeeded($code); } public function emulate(string $code, array $tokens): array { return $this->emulator->reverseEmulate($code, $tokens); } public function reverseEmulate(string $code, array $tokens): array { return $this->emulator->emulate($code, $tokens); } public function preprocessCode(string $code, array &$patches): string { return $code; } } text !== '(') { continue; } $numTokens = 1; $text = '('; $j = $i + 1; if ($j < $c && $tokens[$j]->id === \T_WHITESPACE && preg_match('/[ \t]+/', $tokens[$j]->text)) { $text .= $tokens[$j]->text; $numTokens++; $j++; } if ($j >= $c || $tokens[$j]->id !== \T_STRING || \strtolower($tokens[$j]->text) !== 'void') { continue; } $text .= $tokens[$j]->text; $numTokens++; $k = $j + 1; if ($k < $c && $tokens[$k]->id === \T_WHITESPACE && preg_match('/[ \t]+/', $tokens[$k]->text)) { $text .= $tokens[$k]->text; $numTokens++; $k++; } if ($k >= $c || $tokens[$k]->text !== ')') { continue; } $text .= ')'; $numTokens++; array_splice($tokens, $i, $numTokens, [ new Token(\T_VOID_CAST, $text, $token->line, $token->pos), ]); $c -= $numTokens - 1; } return $tokens; } public function reverseEmulate(string $code, array $tokens): array { for ($i = 0, $c = count($tokens); $i < $c; ++$i) { $token = $tokens[$i]; if ($token->id !== \T_VOID_CAST) { continue; } if (!preg_match('/^\(([ \t]*)(void)([ \t]*)\)$/i', $token->text, $match)) { throw new \LogicException('Unexpected T_VOID_CAST contents'); } $newTokens = []; $pos = $token->pos; $newTokens[] = new Token(\ord('('), '(', $token->line, $pos); $pos++; if ($match[1] !== '') { $newTokens[] = new Token(\T_WHITESPACE, $match[1], $token->line, $pos); $pos += \strlen($match[1]); } $newTokens[] = new Token(\T_STRING, $match[2], $token->line, $pos); $pos += \strlen($match[2]); if ($match[3] !== '') { $newTokens[] = new Token(\T_WHITESPACE, $match[3], $token->line, $pos); $pos += \strlen($match[3]); } $newTokens[] = new Token(\ord(')'), ')', $token->line, $pos); array_splice($tokens, $i, 1, $newTokens); $i += \count($newTokens) - 1; $c += \count($newTokens) - 1; } return $tokens; } } 'public', self::PROTECTED => 'protected', self::PRIVATE => 'private', self::STATIC => 'static', self::ABSTRACT => 'abstract', self::FINAL => 'final', self::READONLY => 'readonly', self::PUBLIC_SET => 'public(set)', self::PROTECTED_SET => 'protected(set)', self::PRIVATE_SET => 'private(set)', ]; public static function toString(int $modifier): string { if (!isset(self::TO_STRING_MAP[$modifier])) { throw new \InvalidArgumentException("Unknown modifier $modifier"); } return self::TO_STRING_MAP[$modifier]; } private static function isValidModifier(int $modifier): bool { $isPow2 = ($modifier & ($modifier - 1)) == 0 && $modifier != 0; return $isPow2 && $modifier <= self::PRIVATE_SET; } /** * @internal */ public static function verifyClassModifier(int $a, int $b): void { assert(self::isValidModifier($b)); if (($a & $b) != 0) { throw new Error( 'Multiple ' . self::toString($b) . ' modifiers are not allowed'); } if ($a & 48 && $b & 48) { throw new Error('Cannot use the final modifier on an abstract class'); } } /** * @internal */ public static function verifyModifier(int $a, int $b): void { assert(self::isValidModifier($b)); if (($a & Modifiers::VISIBILITY_MASK && $b & Modifiers::VISIBILITY_MASK) || ($a & Modifiers::VISIBILITY_SET_MASK && $b & Modifiers::VISIBILITY_SET_MASK) ) { throw new Error('Multiple access type modifiers are not allowed'); } if (($a & $b) != 0) { throw new Error( 'Multiple ' . self::toString($b) . ' modifiers are not allowed'); } if ($a & 48 && $b & 48) { throw new Error('Cannot use the final modifier on an abstract class member'); } } } [aliasName => originalName]] */ protected array $aliases = []; /** @var Name[][] Same as $aliases but preserving original case */ protected array $origAliases = []; /** @var ErrorHandler Error handler */ protected ErrorHandler $errorHandler; /** * Create a name context. * * @param ErrorHandler $errorHandler Error handling used to report errors */ public function __construct(ErrorHandler $errorHandler) { $this->errorHandler = $errorHandler; } /** * Start a new namespace. * * This also resets the alias table. * * @param Name|null $namespace Null is the global namespace */ public function startNamespace(?Name $namespace = null): void { $this->namespace = $namespace; $this->origAliases = $this->aliases = [ Stmt\Use_::TYPE_NORMAL => [], Stmt\Use_::TYPE_FUNCTION => [], Stmt\Use_::TYPE_CONSTANT => [], ]; } /** * Add an alias / import. * * @param Name $name Original name * @param string $aliasName Aliased name * @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_* * @param array $errorAttrs Attributes to use to report an error */ public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = []): void { // Constant names are case sensitive, everything else case insensitive if ($type === Stmt\Use_::TYPE_CONSTANT) { $aliasLookupName = $aliasName; } else { $aliasLookupName = strtolower($aliasName); } if (isset($this->aliases[$type][$aliasLookupName])) { $typeStringMap = [ Stmt\Use_::TYPE_NORMAL => '', Stmt\Use_::TYPE_FUNCTION => 'function ', Stmt\Use_::TYPE_CONSTANT => 'const ', ]; $this->errorHandler->handleError(new Error( sprintf( 'Cannot use %s%s as %s because the name is already in use', $typeStringMap[$type], $name, $aliasName ), $errorAttrs )); return; } $this->aliases[$type][$aliasLookupName] = $name; $this->origAliases[$type][$aliasName] = $name; } /** * Get current namespace. * * @return null|Name Namespace (or null if global namespace) */ public function getNamespace(): ?Name { return $this->namespace; } /** * Get resolved name. * * @param Name $name Name to resolve * @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT} * * @return null|Name Resolved name, or null if static resolution is not possible */ public function getResolvedName(Name $name, int $type): ?Name { // don't resolve special class names if ($type === Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) { if (!$name->isUnqualified()) { $this->errorHandler->handleError(new Error( sprintf("'\\%s' is an invalid class name", $name->toString()), $name->getAttributes() )); } return $name; } // fully qualified names are already resolved if ($name->isFullyQualified()) { return $name; } // Try to resolve aliases if (null !== $resolvedName = $this->resolveAlias($name, $type)) { return $resolvedName; } if ($type !== Stmt\Use_::TYPE_NORMAL && $name->isUnqualified()) { if (null === $this->namespace) { // outside of a namespace unaliased unqualified is same as fully qualified return new FullyQualified($name, $name->getAttributes()); } // Cannot resolve statically return null; } // if no alias exists prepend current namespace return FullyQualified::concat($this->namespace, $name, $name->getAttributes()); } /** * Get resolved class name. * * @param Name $name Class ame to resolve * * @return Name Resolved name */ public function getResolvedClassName(Name $name): Name { return $this->getResolvedName($name, Stmt\Use_::TYPE_NORMAL); } /** * Get possible ways of writing a fully qualified name (e.g., by making use of aliases). * * @param string $name Fully-qualified name (without leading namespace separator) * @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_* * * @return Name[] Possible representations of the name */ public function getPossibleNames(string $name, int $type): array { $lcName = strtolower($name); if ($type === Stmt\Use_::TYPE_NORMAL) { // self, parent and static must always be unqualified if ($lcName === "self" || $lcName === "parent" || $lcName === "static") { return [new Name($name)]; } } // Collect possible ways to write this name, starting with the fully-qualified name $possibleNames = [new FullyQualified($name)]; if (null !== $nsRelativeName = $this->getNamespaceRelativeName($name, $lcName, $type)) { // Make sure there is no alias that makes the normally namespace-relative name // into something else if (null === $this->resolveAlias($nsRelativeName, $type)) { $possibleNames[] = $nsRelativeName; } } // Check for relevant namespace use statements foreach ($this->origAliases[Stmt\Use_::TYPE_NORMAL] as $alias => $orig) { $lcOrig = $orig->toLowerString(); if (0 === strpos($lcName, $lcOrig . '\\')) { $possibleNames[] = new Name($alias . substr($name, strlen($lcOrig))); } } // Check for relevant type-specific use statements foreach ($this->origAliases[$type] as $alias => $orig) { if ($type === Stmt\Use_::TYPE_CONSTANT) { // Constants are complicated-sensitive $normalizedOrig = $this->normalizeConstName($orig->toString()); if ($normalizedOrig === $this->normalizeConstName($name)) { $possibleNames[] = new Name($alias); } } else { // Everything else is case-insensitive if ($orig->toLowerString() === $lcName) { $possibleNames[] = new Name($alias); } } } return $possibleNames; } /** * Get shortest representation of this fully-qualified name. * * @param string $name Fully-qualified name (without leading namespace separator) * @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_* * * @return Name Shortest representation */ public function getShortName(string $name, int $type): Name { $possibleNames = $this->getPossibleNames($name, $type); // Find shortest name $shortestName = null; $shortestLength = \INF; foreach ($possibleNames as $possibleName) { $length = strlen($possibleName->toCodeString()); if ($length < $shortestLength) { $shortestName = $possibleName; $shortestLength = $length; } } return $shortestName; } private function resolveAlias(Name $name, int $type): ?FullyQualified { $firstPart = $name->getFirst(); if ($name->isQualified()) { // resolve aliases for qualified names, always against class alias table $checkName = strtolower($firstPart); if (isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName])) { $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName]; return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); } } elseif ($name->isUnqualified()) { // constant aliases are case-sensitive, function aliases case-insensitive $checkName = $type === Stmt\Use_::TYPE_CONSTANT ? $firstPart : strtolower($firstPart); if (isset($this->aliases[$type][$checkName])) { // resolve unqualified aliases return new FullyQualified($this->aliases[$type][$checkName], $name->getAttributes()); } } // No applicable aliases return null; } private function getNamespaceRelativeName(string $name, string $lcName, int $type): ?Name { if (null === $this->namespace) { return new Name($name); } if ($type === Stmt\Use_::TYPE_CONSTANT) { // The constants true/false/null always resolve to the global symbols, even inside a // namespace, so they may be used without qualification if ($lcName === "true" || $lcName === "false" || $lcName === "null") { return new Name($name); } } $namespacePrefix = strtolower($this->namespace . '\\'); if (0 === strpos($lcName, $namespacePrefix)) { return new Name(substr($name, strlen($namespacePrefix))); } return null; } private function normalizeConstName(string $name): string { $nsSep = strrpos($name, '\\'); if (false === $nsSep) { return $name; } // Constants have case-insensitive namespace and case-sensitive short-name $ns = substr($name, 0, $nsSep); $shortName = substr($name, $nsSep + 1); return strtolower($ns) . '\\' . $shortName; } } */ public function getAttributes(): array; /** * Replaces all the attributes of this node. * * @param array $attributes */ public function setAttributes(array $attributes): void; } $attributes Additional attributes * @param Identifier|null $name Parameter name (for named parameters) */ public function __construct( Expr $value, bool $byRef = false, bool $unpack = false, array $attributes = [], ?Identifier $name = null ) { $this->attributes = $attributes; $this->name = $name; $this->value = $value; $this->byRef = $byRef; $this->unpack = $unpack; } public function getSubNodeNames(): array { return ['name', 'value', 'byRef', 'unpack']; } public function getType(): string { return 'Arg'; } } $attributes Additional attributes */ public function __construct(Expr $value, ?Expr $key = null, bool $byRef = false, array $attributes = [], bool $unpack = false) { $this->attributes = $attributes; $this->key = $key; $this->value = $value; $this->byRef = $byRef; $this->unpack = $unpack; } public function getSubNodeNames(): array { return ['key', 'value', 'byRef', 'unpack']; } public function getType(): string { return 'ArrayItem'; } } // @deprecated compatibility alias class_alias(ArrayItem::class, Expr\ArrayItem::class); Attribute arguments */ public array $args; /** * @param Node\Name $name Attribute name * @param list $args Attribute arguments * @param array $attributes Additional node attributes */ public function __construct(Name $name, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->name = $name; $this->args = $args; } public function getSubNodeNames(): array { return ['name', 'args']; } public function getType(): string { return 'Attribute'; } } $attributes Additional node attributes */ public function __construct(array $attrs, array $attributes = []) { $this->attributes = $attributes; $this->attrs = $attrs; } public function getSubNodeNames(): array { return ['attrs']; } public function getType(): string { return 'AttributeGroup'; } } $attributes Additional attributes */ public function __construct(Expr\Variable $var, bool $byRef = false, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->byRef = $byRef; } public function getSubNodeNames(): array { return ['var', 'byRef']; } public function getType(): string { return 'ClosureUse'; } } // @deprecated compatibility alias class_alias(ClosureUse::class, Expr\ClosureUse::class); $attributes Additional attributes */ public function __construct($name, Expr $value, array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new Identifier($name) : $name; $this->value = $value; } public function getSubNodeNames(): array { return ['name', 'value']; } public function getType(): string { return 'Const'; } } value pair node. * * @param string|Node\Identifier $key Key * @param Node\Expr $value Value * @param array $attributes Additional attributes */ public function __construct($key, Node\Expr $value, array $attributes = []) { $this->attributes = $attributes; $this->key = \is_string($key) ? new Node\Identifier($key) : $key; $this->value = $value; } public function getSubNodeNames(): array { return ['key', 'value']; } public function getType(): string { return 'DeclareItem'; } } // @deprecated compatibility alias class_alias(DeclareItem::class, Stmt\DeclareDeclare::class); $attributes Additional attributes */ public function __construct(Expr $var, ?Expr $dim = null, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->dim = $dim; } public function getSubNodeNames(): array { return ['var', 'dim']; } public function getType(): string { return 'Expr_ArrayDimFetch'; } } $attributes Additional attributes */ public function __construct(array $items = [], array $attributes = []) { $this->attributes = $attributes; $this->items = $items; } public function getSubNodeNames(): array { return ['items']; } public function getType(): string { return 'Expr_Array'; } } false : Whether the closure is static * 'byRef' => false : Whether to return by reference * 'params' => array() : Parameters * 'returnType' => null : Return type * 'attrGroups' => array() : PHP attribute groups * @param array $attributes Additional attributes */ public function __construct(array $subNodes, array $attributes = []) { $this->attributes = $attributes; $this->static = $subNodes['static'] ?? false; $this->byRef = $subNodes['byRef'] ?? false; $this->params = $subNodes['params'] ?? []; $this->returnType = $subNodes['returnType'] ?? null; $this->expr = $subNodes['expr']; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames(): array { return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr']; } public function returnsByRef(): bool { return $this->byRef; } public function getParams(): array { return $this->params; } public function getReturnType() { return $this->returnType; } public function getAttrGroups(): array { return $this->attrGroups; } /** * @return Node\Stmt\Return_[] */ public function getStmts(): array { return [new Node\Stmt\Return_($this->expr)]; } public function getType(): string { return 'Expr_ArrowFunction'; } } $attributes Additional attributes */ public function __construct(Expr $var, Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->expr = $expr; } public function getSubNodeNames(): array { return ['var', 'expr']; } public function getType(): string { return 'Expr_Assign'; } } $attributes Additional attributes */ public function __construct(Expr $var, Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->expr = $expr; } public function getSubNodeNames(): array { return ['var', 'expr']; } } $attributes Additional attributes */ public function __construct(Expr $var, Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->expr = $expr; } public function getSubNodeNames(): array { return ['var', 'expr']; } public function getType(): string { return 'Expr_AssignRef'; } } $attributes Additional attributes */ public function __construct(Expr $left, Expr $right, array $attributes = []) { $this->attributes = $attributes; $this->left = $left; $this->right = $right; } public function getSubNodeNames(): array { return ['left', 'right']; } /** * Get the operator sigil for this binary operation. * * In the case there are multiple possible sigils for an operator, this method does not * necessarily return the one used in the parsed code. */ abstract public function getOperatorSigil(): string; } '; } public function getType(): string { return 'Expr_BinaryOp_Greater'; } } ='; } public function getType(): string { return 'Expr_BinaryOp_GreaterOrEqual'; } } '; } public function getType(): string { return 'Expr_BinaryOp_Pipe'; } } >'; } public function getType(): string { return 'Expr_BinaryOp_ShiftRight'; } } '; } public function getType(): string { return 'Expr_BinaryOp_Spaceship'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_BitwiseNot'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_BooleanNot'; } } */ abstract public function getRawArgs(): array; /** * Returns whether this call expression is actually a first class callable. */ public function isFirstClassCallable(): bool { $rawArgs = $this->getRawArgs(); return count($rawArgs) === 1 && current($rawArgs) instanceof VariadicPlaceholder; } /** * Assert that this is not a first-class callable and return only ordinary Args. * * @return Arg[] */ public function getArgs(): array { assert(!$this->isFirstClassCallable()); return $this->getRawArgs(); } /** * Retrieves a specific argument from the raw arguments. * * Returns the named argument that matches the given `$name`, or the * positional (unnamed) argument that exists at the given `$position`, * otherwise, returns `null` for first-class callables or if no match is found. */ public function getArg(string $name, int $position): ?Arg { if ($this->isFirstClassCallable()) { return null; } foreach ($this->getRawArgs() as $i => $arg) { if ($arg->unpack) { continue; } if ( ($arg->name !== null && $arg->name->toString() === $name) || ($arg->name === null && $i === $position) ) { return $arg; } } return null; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } } $attributes Additional attributes */ public function __construct(Node $class, $name, array $attributes = []) { $this->attributes = $attributes; $this->class = $class; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames(): array { return ['class', 'name']; } public function getType(): string { return 'Expr_ClassConstFetch'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_Clone'; } } false : Whether the closure is static * 'byRef' => false : Whether to return by reference * 'params' => array(): Parameters * 'uses' => array(): use()s * 'returnType' => null : Return type * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attributes groups * @param array $attributes Additional attributes */ public function __construct(array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->static = $subNodes['static'] ?? false; $this->byRef = $subNodes['byRef'] ?? false; $this->params = $subNodes['params'] ?? []; $this->uses = $subNodes['uses'] ?? []; $this->returnType = $subNodes['returnType'] ?? null; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames(): array { return ['attrGroups', 'static', 'byRef', 'params', 'uses', 'returnType', 'stmts']; } public function returnsByRef(): bool { return $this->byRef; } public function getParams(): array { return $this->params; } public function getReturnType() { return $this->returnType; } /** @return Node\Stmt[] */ public function getStmts(): array { return $this->stmts; } public function getAttrGroups(): array { return $this->attrGroups; } public function getType(): string { return 'Expr_Closure'; } } $attributes Additional attributes */ public function __construct(Name $name, array $attributes = []) { $this->attributes = $attributes; $this->name = $name; } public function getSubNodeNames(): array { return ['name']; } public function getType(): string { return 'Expr_ConstFetch'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_Empty'; } } $attributes Additional attributes */ public function __construct(array $attributes = []) { $this->attributes = $attributes; } public function getSubNodeNames(): array { return []; } public function getType(): string { return 'Expr_Error'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_ErrorSuppress'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_Eval'; } } $attributes Additional attributes */ public function __construct(?Expr $expr = null, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_Exit'; } } Arguments */ public array $args; /** * Constructs a function call node. * * @param Node\Name|Expr $name Function name * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct(Node $name, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->name = $name; $this->args = $args; } public function getSubNodeNames(): array { return ['name', 'args']; } public function getType(): string { return 'Expr_FuncCall'; } public function getRawArgs(): array { return $this->args; } } $attributes Additional attributes */ public function __construct(Expr $expr, int $type, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; $this->type = $type; } public function getSubNodeNames(): array { return ['expr', 'type']; } public function getType(): string { return 'Expr_Include'; } } $attributes Additional attributes */ public function __construct(Expr $expr, Node $class, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; $this->class = $class; } public function getSubNodeNames(): array { return ['expr', 'class']; } public function getType(): string { return 'Expr_Instanceof'; } } $attributes Additional attributes */ public function __construct(array $vars, array $attributes = []) { $this->attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames(): array { return ['vars']; } public function getType(): string { return 'Expr_Isset'; } } $attributes Additional attributes */ public function __construct(array $items, array $attributes = []) { $this->attributes = $attributes; $this->items = $items; } public function getSubNodeNames(): array { return ['items']; } public function getType(): string { return 'Expr_List'; } } $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $arms = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->arms = $arms; } public function getSubNodeNames(): array { return ['cond', 'arms']; } public function getType(): string { return 'Expr_Match'; } } Arguments */ public array $args; /** * Constructs a function call node. * * @param Expr $var Variable holding object * @param string|Identifier|Expr $name Method name * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new Identifier($name) : $name; $this->args = $args; } public function getSubNodeNames(): array { return ['var', 'name', 'args']; } public function getType(): string { return 'Expr_MethodCall'; } public function getRawArgs(): array { return $this->args; } } Arguments */ public array $args; /** * Constructs a function call node. * * @param Node\Name|Expr|Node\Stmt\Class_ $class Class name (or class node for anonymous classes) * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct(Node $class, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->class = $class; $this->args = $args; } public function getSubNodeNames(): array { return ['class', 'args']; } public function getType(): string { return 'Expr_New'; } public function getRawArgs(): array { return $this->args; } } Arguments */ public array $args; /** * Constructs a nullsafe method call node. * * @param Expr $var Variable holding object * @param string|Identifier|Expr $name Method name * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new Identifier($name) : $name; $this->args = $args; } public function getSubNodeNames(): array { return ['var', 'name', 'args']; } public function getType(): string { return 'Expr_NullsafeMethodCall'; } public function getRawArgs(): array { return $this->args; } } $attributes Additional attributes */ public function __construct(Expr $var, $name, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames(): array { return ['var', 'name']; } public function getType(): string { return 'Expr_NullsafePropertyFetch'; } } $attributes Additional attributes */ public function __construct(Expr $var, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; } public function getSubNodeNames(): array { return ['var']; } public function getType(): string { return 'Expr_PostDec'; } } $attributes Additional attributes */ public function __construct(Expr $var, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; } public function getSubNodeNames(): array { return ['var']; } public function getType(): string { return 'Expr_PostInc'; } } $attributes Additional attributes */ public function __construct(Expr $var, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; } public function getSubNodeNames(): array { return ['var']; } public function getType(): string { return 'Expr_PreDec'; } } $attributes Additional attributes */ public function __construct(Expr $var, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; } public function getSubNodeNames(): array { return ['var']; } public function getType(): string { return 'Expr_PreInc'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_Print'; } } $attributes Additional attributes */ public function __construct(Expr $var, $name, array $attributes = []) { $this->attributes = $attributes; $this->var = $var; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames(): array { return ['var', 'name']; } public function getType(): string { return 'Expr_PropertyFetch'; } } $attributes Additional attributes */ public function __construct(array $parts, array $attributes = []) { $this->attributes = $attributes; $this->parts = $parts; } public function getSubNodeNames(): array { return ['parts']; } public function getType(): string { return 'Expr_ShellExec'; } } Arguments */ public array $args; /** * Constructs a static method call node. * * @param Node\Name|Expr $class Class name * @param string|Identifier|Expr $name Method name * @param array $args Arguments * @param array $attributes Additional attributes */ public function __construct(Node $class, $name, array $args = [], array $attributes = []) { $this->attributes = $attributes; $this->class = $class; $this->name = \is_string($name) ? new Identifier($name) : $name; $this->args = $args; } public function getSubNodeNames(): array { return ['class', 'name', 'args']; } public function getType(): string { return 'Expr_StaticCall'; } public function getRawArgs(): array { return $this->args; } } $attributes Additional attributes */ public function __construct(Node $class, $name, array $attributes = []) { $this->attributes = $attributes; $this->class = $class; $this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name; } public function getSubNodeNames(): array { return ['class', 'name']; } public function getType(): string { return 'Expr_StaticPropertyFetch'; } } $attributes Additional attributes */ public function __construct(Expr $cond, ?Expr $if, Expr $else, array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->if = $if; $this->else = $else; } public function getSubNodeNames(): array { return ['cond', 'if', 'else']; } public function getType(): string { return 'Expr_Ternary'; } } $attributes Additional attributes */ public function __construct(Node\Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_Throw'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_UnaryMinus'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_UnaryPlus'; } } $attributes Additional attributes */ public function __construct($name, array $attributes = []) { $this->attributes = $attributes; $this->name = $name; } public function getSubNodeNames(): array { return ['name']; } public function getType(): string { return 'Expr_Variable'; } } $attributes Additional attributes */ public function __construct(Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Expr_YieldFrom'; } } $attributes Additional attributes */ public function __construct(?Expr $value = null, ?Expr $key = null, array $attributes = []) { $this->attributes = $attributes; $this->key = $key; $this->value = $value; } public function getSubNodeNames(): array { return ['key', 'value']; } public function getType(): string { return 'Expr_Yield'; } } */ private static array $specialClassNames = [ 'self' => true, 'parent' => true, 'static' => true, ]; /** * Constructs an identifier node. * * @param string $name Identifier as string * @param array $attributes Additional attributes */ public function __construct(string $name, array $attributes = []) { if ($name === '') { throw new \InvalidArgumentException('Identifier name cannot be empty'); } $this->attributes = $attributes; $this->name = $name; } public function getSubNodeNames(): array { return ['name']; } /** * Get identifier as string. * * @psalm-return non-empty-string * @return string Identifier as string. */ public function toString(): string { return $this->name; } /** * Get lowercased identifier as string. * * @psalm-return non-empty-string&lowercase-string * @return string Lowercased identifier as string */ public function toLowerString(): string { return strtolower($this->name); } /** * Checks whether the identifier is a special class name (self, parent or static). * * @return bool Whether identifier is a special class name */ public function isSpecialClassName(): bool { return isset(self::$specialClassNames[strtolower($this->name)]); } /** * Get identifier as string. * * @psalm-return non-empty-string * @return string Identifier as string */ public function __toString(): string { return $this->name; } public function getType(): string { return 'Identifier'; } } $attributes Additional attributes */ public function __construct(string $value, array $attributes = []) { $this->attributes = $attributes; $this->value = $value; } public function getSubNodeNames(): array { return ['value']; } public function getType(): string { return 'InterpolatedStringPart'; } } // @deprecated compatibility alias class_alias(InterpolatedStringPart::class, Scalar\EncapsedStringPart::class); $attributes Additional attributes */ public function __construct(array $types, array $attributes = []) { $this->attributes = $attributes; $this->types = $types; } public function getSubNodeNames(): array { return ['types']; } public function getType(): string { return 'IntersectionType'; } } */ public ?array $conds; public Expr $body; /** * @param null|list $conds */ public function __construct(?array $conds, Node\Expr $body, array $attributes = []) { $this->conds = $conds; $this->body = $body; $this->attributes = $attributes; } public function getSubNodeNames(): array { return ['conds', 'body']; } public function getType(): string { return 'MatchArm'; } } */ private static array $specialClassNames = [ 'self' => true, 'parent' => true, 'static' => true, ]; /** * Constructs a name node. * * @param string|string[]|self $name Name as string, part array or Name instance (copy ctor) * @param array $attributes Additional attributes */ final public function __construct($name, array $attributes = []) { $this->attributes = $attributes; $this->name = self::prepareName($name); } public function getSubNodeNames(): array { return ['name']; } /** * Get parts of name (split by the namespace separator). * * @psalm-return non-empty-list * @return string[] Parts of name */ public function getParts(): array { return \explode('\\', $this->name); } /** * Gets the first part of the name, i.e. everything before the first namespace separator. * * @return string First part of the name */ public function getFirst(): string { if (false !== $pos = \strpos($this->name, '\\')) { return \substr($this->name, 0, $pos); } return $this->name; } /** * Gets the last part of the name, i.e. everything after the last namespace separator. * * @return string Last part of the name */ public function getLast(): string { if (false !== $pos = \strrpos($this->name, '\\')) { return \substr($this->name, $pos + 1); } return $this->name; } /** * Checks whether the name is unqualified. (E.g. Name) * * @return bool Whether the name is unqualified */ public function isUnqualified(): bool { return false === \strpos($this->name, '\\'); } /** * Checks whether the name is qualified. (E.g. Name\Name) * * @return bool Whether the name is qualified */ public function isQualified(): bool { return false !== \strpos($this->name, '\\'); } /** * Checks whether the name is fully qualified. (E.g. \Name) * * @return bool Whether the name is fully qualified */ public function isFullyQualified(): bool { return false; } /** * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) * * @return bool Whether the name is relative */ public function isRelative(): bool { return false; } /** * Returns a string representation of the name itself, without taking the name type into * account (e.g., not including a leading backslash for fully qualified names). * * @psalm-return non-empty-string * @return string String representation */ public function toString(): string { return $this->name; } /** * Returns a string representation of the name as it would occur in code (e.g., including * leading backslash for fully qualified names. * * @psalm-return non-empty-string * @return string String representation */ public function toCodeString(): string { return $this->toString(); } /** * Returns lowercased string representation of the name, without taking the name type into * account (e.g., no leading backslash for fully qualified names). * * @psalm-return non-empty-string&lowercase-string * @return string Lowercased string representation */ public function toLowerString(): string { return strtolower($this->name); } /** * Checks whether the identifier is a special class name (self, parent or static). * * @return bool Whether identifier is a special class name */ public function isSpecialClassName(): bool { return isset(self::$specialClassNames[strtolower($this->name)]); } /** * Returns a string representation of the name by imploding the namespace parts with the * namespace separator. * * @psalm-return non-empty-string * @return string String representation */ public function __toString(): string { return $this->name; } /** * Gets a slice of a name (similar to array_slice). * * This method returns a new instance of the same type as the original and with the same * attributes. * * If the slice is empty, null is returned. The null value will be correctly handled in * concatenations using concat(). * * Offset and length have the same meaning as in array_slice(). * * @param int $offset Offset to start the slice at (may be negative) * @param int|null $length Length of the slice (may be negative) * * @return static|null Sliced name */ public function slice(int $offset, ?int $length = null) { if ($offset === 1 && $length === null) { // Short-circuit the common case. if (false !== $pos = \strpos($this->name, '\\')) { return new static(\substr($this->name, $pos + 1)); } return null; } $parts = \explode('\\', $this->name); $numParts = \count($parts); $realOffset = $offset < 0 ? $offset + $numParts : $offset; if ($realOffset < 0 || $realOffset > $numParts) { throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset)); } if (null === $length) { $realLength = $numParts - $realOffset; } else { $realLength = $length < 0 ? $length + $numParts - $realOffset : $length; if ($realLength < 0 || $realLength > $numParts - $realOffset) { throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length)); } } if ($realLength === 0) { // Empty slice is represented as null return null; } return new static(array_slice($parts, $realOffset, $realLength), $this->attributes); } /** * Concatenate two names, yielding a new Name instance. * * The type of the generated instance depends on which class this method is called on, for * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance. * * If one of the arguments is null, a new instance of the other name will be returned. If both * arguments are null, null will be returned. As such, writing * Name::concat($namespace, $shortName) * where $namespace is a Name node or null will work as expected. * * @param string|string[]|self|null $name1 The first name * @param string|string[]|self|null $name2 The second name * @param array $attributes Attributes to assign to concatenated name * * @return static|null Concatenated name */ public static function concat($name1, $name2, array $attributes = []) { if (null === $name1 && null === $name2) { return null; } if (null === $name1) { return new static($name2, $attributes); } if (null === $name2) { return new static($name1, $attributes); } else { return new static( self::prepareName($name1) . '\\' . self::prepareName($name2), $attributes ); } } /** * Prepares a (string, array or Name node) name for use in name changing methods by converting * it to a string. * * @param string|string[]|self $name Name to prepare * * @psalm-return non-empty-string * @return string Prepared name */ private static function prepareName($name): string { if (\is_string($name)) { if ('' === $name) { throw new \InvalidArgumentException('Name cannot be empty'); } return $name; } if (\is_array($name)) { if (empty($name)) { throw new \InvalidArgumentException('Name cannot be empty'); } return implode('\\', $name); } if ($name instanceof self) { return $name->name; } throw new \InvalidArgumentException( 'Expected string, array of parts or Name instance' ); } public function getType(): string { return 'Name'; } } toString(); } public function getType(): string { return 'Name_FullyQualified'; } } toString(); } public function getType(): string { return 'Name_Relative'; } } $attributes Additional attributes */ public function __construct(Node $type, array $attributes = []) { $this->attributes = $attributes; $this->type = $type; } public function getSubNodeNames(): array { return ['type']; } public function getType(): string { return 'NullableType'; } } $attributes Additional attributes * @param int $flags Optional visibility flags * @param list $attrGroups PHP attribute groups * @param PropertyHook[] $hooks Property hooks for promoted properties */ public function __construct( Expr $var, ?Expr $default = null, ?Node $type = null, bool $byRef = false, bool $variadic = false, array $attributes = [], int $flags = 0, array $attrGroups = [], array $hooks = [] ) { $this->attributes = $attributes; $this->type = $type; $this->byRef = $byRef; $this->variadic = $variadic; $this->var = $var; $this->default = $default; $this->flags = $flags; $this->attrGroups = $attrGroups; $this->hooks = $hooks; } public function getSubNodeNames(): array { return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default', 'hooks']; } public function getType(): string { return 'Param'; } /** * Whether this parameter uses constructor property promotion. */ public function isPromoted(): bool { return $this->flags !== 0 || $this->hooks !== []; } public function isFinal(): bool { return (bool) ($this->flags & Modifiers::FINAL); } public function isPublic(): bool { $public = (bool) ($this->flags & Modifiers::PUBLIC); if ($public) { return true; } if (!$this->isPromoted()) { return false; } return ($this->flags & Modifiers::VISIBILITY_MASK) === 0; } public function isProtected(): bool { return (bool) ($this->flags & Modifiers::PROTECTED); } public function isPrivate(): bool { return (bool) ($this->flags & Modifiers::PRIVATE); } public function isReadonly(): bool { return (bool) ($this->flags & Modifiers::READONLY); } /** * Whether the promoted property has explicit public(set) visibility. */ public function isPublicSet(): bool { return (bool) ($this->flags & Modifiers::PUBLIC_SET); } /** * Whether the promoted property has explicit protected(set) visibility. */ public function isProtectedSet(): bool { return (bool) ($this->flags & Modifiers::PROTECTED_SET); } /** * Whether the promoted property has explicit private(set) visibility. */ public function isPrivateSet(): bool { return (bool) ($this->flags & Modifiers::PRIVATE_SET); } } 0 : Flags * 'byRef' => false : Whether hook returns by reference * 'params' => array(): Parameters * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, $body, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new Identifier($name) : $name; $this->body = $body; $this->flags = $subNodes['flags'] ?? 0; $this->byRef = $subNodes['byRef'] ?? false; $this->params = $subNodes['params'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function returnsByRef(): bool { return $this->byRef; } public function getParams(): array { return $this->params; } public function getReturnType() { return null; } /** * Whether the property hook is final. */ public function isFinal(): bool { return (bool) ($this->flags & Modifiers::FINAL); } public function getStmts(): ?array { if ($this->body instanceof Expr) { $name = $this->name->toLowerString(); if ($name === 'get') { return [new Return_($this->body)]; } if ($name === 'set') { if (!$this->hasAttribute('propertyName')) { throw new \LogicException( 'Can only use getStmts() on a "set" hook if the "propertyName" attribute is set'); } $propName = $this->getAttribute('propertyName'); $prop = new PropertyFetch(new Variable('this'), (string) $propName); return [new Expression(new Assign($prop, $this->body))]; } throw new \LogicException('Unknown property hook "' . $name . '"'); } return $this->body; } public function getAttrGroups(): array { return $this->attrGroups; } public function getType(): string { return 'PropertyHook'; } public function getSubNodeNames(): array { return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'body']; } } $attributes Additional attributes */ public function __construct($name, ?Node\Expr $default = null, array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new Node\VarLikeIdentifier($name) : $name; $this->default = $default; } public function getSubNodeNames(): array { return ['name', 'default']; } public function getType(): string { return 'PropertyItem'; } } // @deprecated compatibility alias class_alias(PropertyItem::class, Stmt\PropertyProperty::class); $attributes Additional attributes */ public function __construct(float $value, array $attributes = []) { $this->attributes = $attributes; $this->value = $value; } public function getSubNodeNames(): array { return ['value']; } /** * @param mixed[] $attributes */ public static function fromString(string $str, array $attributes = []): Float_ { $attributes['rawValue'] = $str; $float = self::parse($str); return new Float_($float, $attributes); } /** * @internal * * Parses a DNUMBER token like PHP would. * * @param string $str A string number * * @return float The parsed number */ public static function parse(string $str): float { $str = str_replace('_', '', $str); // Check whether this is one of the special integer notations. if ('0' === $str[0]) { // hex if ('x' === $str[1] || 'X' === $str[1]) { return hexdec($str); } // bin if ('b' === $str[1] || 'B' === $str[1]) { return bindec($str); } // oct, but only if the string does not contain any of '.eE'. if (false === strpbrk($str, '.eE')) { // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit // (8 or 9) so that only the digits before that are used. return octdec(substr($str, 0, strcspn($str, '89'))); } } // dec return (float) $str; } public function getType(): string { return 'Scalar_Float'; } } // @deprecated compatibility alias class_alias(Float_::class, DNumber::class); $attributes Additional attributes */ public function __construct(int $value, array $attributes = []) { $this->attributes = $attributes; $this->value = $value; } public function getSubNodeNames(): array { return ['value']; } /** * Constructs an Int node from a string number literal. * * @param string $str String number literal (decimal, octal, hex or binary) * @param array $attributes Additional attributes * @param bool $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5) * * @return Int_ The constructed LNumber, including kind attribute */ public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = false): Int_ { $attributes['rawValue'] = $str; $str = str_replace('_', '', $str); if ('0' !== $str[0] || '0' === $str) { $attributes['kind'] = Int_::KIND_DEC; return new Int_((int) $str, $attributes); } if ('x' === $str[1] || 'X' === $str[1]) { $attributes['kind'] = Int_::KIND_HEX; return new Int_(hexdec($str), $attributes); } if ('b' === $str[1] || 'B' === $str[1]) { $attributes['kind'] = Int_::KIND_BIN; return new Int_(bindec($str), $attributes); } if (!$allowInvalidOctal && strpbrk($str, '89')) { throw new Error('Invalid numeric literal', $attributes); } // Strip optional explicit octal prefix. if ('o' === $str[1] || 'O' === $str[1]) { $str = substr($str, 2); } // use intval instead of octdec to get proper cutting behavior with malformed numbers $attributes['kind'] = Int_::KIND_OCT; return new Int_(intval($str, 8), $attributes); } public function getType(): string { return 'Scalar_Int'; } } // @deprecated compatibility alias class_alias(Int_::class, LNumber::class); $attributes Additional attributes */ public function __construct(array $parts, array $attributes = []) { $this->attributes = $attributes; $this->parts = $parts; } public function getSubNodeNames(): array { return ['parts']; } public function getType(): string { return 'Scalar_InterpolatedString'; } } // @deprecated compatibility alias class_alias(InterpolatedString::class, Encapsed::class); $attributes Additional attributes */ public function __construct(array $attributes = []) { $this->attributes = $attributes; } public function getSubNodeNames(): array { return []; } /** * Get name of magic constant. * * @return string Name of magic constant */ abstract public function getName(): string; } Escaped character to its decoded value */ protected static array $replacements = [ '\\' => '\\', '$' => '$', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\x1B", ]; /** * Constructs a string scalar node. * * @param string $value Value of the string * @param array $attributes Additional attributes */ public function __construct(string $value, array $attributes = []) { $this->attributes = $attributes; $this->value = $value; } public function getSubNodeNames(): array { return ['value']; } /** * @param array $attributes * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes */ public static function fromString(string $str, array $attributes = [], bool $parseUnicodeEscape = true): self { $attributes['kind'] = ($str[0] === "'" || ($str[1] === "'" && ($str[0] === 'b' || $str[0] === 'B'))) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED; $attributes['rawValue'] = $str; $string = self::parse($str, $parseUnicodeEscape); return new self($string, $attributes); } /** * @internal * * Parses a string token. * * @param string $str String token content * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes * * @return string The parsed string */ public static function parse(string $str, bool $parseUnicodeEscape = true): string { $bLength = 0; if ('b' === $str[0] || 'B' === $str[0]) { $bLength = 1; } if ('\'' === $str[$bLength]) { return str_replace( ['\\\\', '\\\''], ['\\', '\''], substr($str, $bLength + 1, -1) ); } else { return self::parseEscapeSequences( substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape ); } } /** * @internal * * Parses escape sequences in strings (all string types apart from single quoted). * * @param string $str String without quotes * @param null|string $quote Quote type * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes * * @return string String with escape sequences parsed */ public static function parseEscapeSequences(string $str, ?string $quote, bool $parseUnicodeEscape = true): string { if (null !== $quote) { $str = str_replace('\\' . $quote, $quote, $str); } $extra = ''; if ($parseUnicodeEscape) { $extra = '|u\{([0-9a-fA-F]+)\}'; } return preg_replace_callback( '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~', function ($matches) { $str = $matches[1]; if (isset(self::$replacements[$str])) { return self::$replacements[$str]; } if ('x' === $str[0] || 'X' === $str[0]) { return chr(hexdec(substr($str, 1))); } if ('u' === $str[0]) { $dec = hexdec($matches[2]); // If it overflowed to float, treat as INT_MAX, it will throw an error anyway. return self::codePointToUtf8(\is_int($dec) ? $dec : \PHP_INT_MAX); } else { return chr(octdec($str) & 255); } }, $str ); } /** * Converts a Unicode code point to its UTF-8 encoded representation. * * @param int $num Code point * * @return string UTF-8 representation of code point */ 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); } throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large'); } public function getType(): string { return 'Scalar_String'; } } $attributes Additional attributes */ public function __construct( Expr\Variable $var, ?Node\Expr $default = null, array $attributes = [] ) { $this->attributes = $attributes; $this->var = $var; $this->default = $default; } public function getSubNodeNames(): array { return ['var', 'default']; } public function getType(): string { return 'StaticVar'; } } // @deprecated compatibility alias class_alias(StaticVar::class, Stmt\StaticVar::class); $attributes Additional attributes */ public function __construct(array $stmts, array $attributes = []) { $this->attributes = $attributes; $this->stmts = $stmts; } public function getType(): string { return 'Stmt_Block'; } public function getSubNodeNames(): array { return ['stmts']; } } $attributes Additional attributes */ public function __construct(?Node\Expr $num = null, array $attributes = []) { $this->attributes = $attributes; $this->num = $num; } public function getSubNodeNames(): array { return ['num']; } public function getType(): string { return 'Stmt_Break'; } } $attributes Additional attributes */ public function __construct(?Node\Expr $cond, array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames(): array { return ['cond', 'stmts']; } public function getType(): string { return 'Stmt_Case'; } } $attributes Additional attributes */ public function __construct( array $types, ?Expr\Variable $var = null, array $stmts = [], array $attributes = [] ) { $this->attributes = $attributes; $this->types = $types; $this->var = $var; $this->stmts = $stmts; } public function getSubNodeNames(): array { return ['types', 'var', 'stmts']; } public function getType(): string { return 'Stmt_Catch'; } } $attributes Additional attributes * @param list $attrGroups PHP attribute groups * @param null|Node\Identifier|Node\Name|Node\ComplexType $type Type declaration */ public function __construct( array $consts, int $flags = 0, array $attributes = [], array $attrGroups = [], ?Node $type = null ) { $this->attributes = $attributes; $this->flags = $flags; $this->consts = $consts; $this->attrGroups = $attrGroups; $this->type = $type; } public function getSubNodeNames(): array { return ['attrGroups', 'flags', 'type', 'consts']; } /** * Whether constant is explicitly or implicitly public. */ public function isPublic(): bool { return ($this->flags & Modifiers::PUBLIC) !== 0 || ($this->flags & Modifiers::VISIBILITY_MASK) === 0; } /** * Whether constant is protected. */ public function isProtected(): bool { return (bool) ($this->flags & Modifiers::PROTECTED); } /** * Whether constant is private. */ public function isPrivate(): bool { return (bool) ($this->flags & Modifiers::PRIVATE); } /** * Whether constant is final. */ public function isFinal(): bool { return (bool) ($this->flags & Modifiers::FINAL); } public function getType(): string { return 'Stmt_ClassConst'; } } */ public function getTraitUses(): array { $traitUses = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof TraitUse) { $traitUses[] = $stmt; } } return $traitUses; } /** * @return list */ public function getConstants(): array { $constants = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof ClassConst) { $constants[] = $stmt; } } return $constants; } /** * @return list */ public function getProperties(): array { $properties = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof Property) { $properties[] = $stmt; } } return $properties; } /** * Gets property with the given name defined directly in this class/interface/trait. * * @param string $name Name of the property * * @return Property|null Property node or null if the property does not exist */ public function getProperty(string $name): ?Property { foreach ($this->stmts as $stmt) { if ($stmt instanceof Property) { foreach ($stmt->props as $prop) { if ($prop instanceof PropertyItem && $name === $prop->name->toString()) { return $stmt; } } } } return null; } /** * Gets all methods defined directly in this class/interface/trait * * @return list */ public function getMethods(): array { $methods = []; foreach ($this->stmts as $stmt) { if ($stmt instanceof ClassMethod) { $methods[] = $stmt; } } return $methods; } /** * Gets method with the given name defined directly in this class/interface/trait. * * @param string $name Name of the method (compared case-insensitively) * * @return ClassMethod|null Method node or null if the method does not exist */ public function getMethod(string $name): ?ClassMethod { $lowerName = strtolower($name); foreach ($this->stmts as $stmt) { if ($stmt instanceof ClassMethod && $lowerName === $stmt->name->toLowerString()) { return $stmt; } } return null; } } */ private static array $magicNames = [ '__construct' => true, '__destruct' => true, '__call' => true, '__callstatic' => true, '__get' => true, '__set' => true, '__isset' => true, '__unset' => true, '__sleep' => true, '__wakeup' => true, '__tostring' => true, '__set_state' => true, '__clone' => true, '__invoke' => true, '__debuginfo' => true, '__serialize' => true, '__unserialize' => true, ]; /** * Constructs a class method node. * * @param string|Node\Identifier $name Name * @param array{ * flags?: int, * byRef?: bool, * params?: Node\Param[], * returnType?: null|Node\Identifier|Node\Name|Node\ComplexType, * stmts?: Node\Stmt[]|null, * attrGroups?: Node\AttributeGroup[], * } $subNodes Array of the following optional subnodes: * 'flags => 0 : Flags * 'byRef' => false : Whether to return by reference * 'params' => array() : Parameters * 'returnType' => null : Return type * 'stmts' => array() : Statements * 'attrGroups' => array() : PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; $this->byRef = $subNodes['byRef'] ?? false; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->params = $subNodes['params'] ?? []; $this->returnType = $subNodes['returnType'] ?? null; $this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames(): array { return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'returnType', 'stmts']; } public function returnsByRef(): bool { return $this->byRef; } public function getParams(): array { return $this->params; } public function getReturnType() { return $this->returnType; } public function getStmts(): ?array { return $this->stmts; } public function getAttrGroups(): array { return $this->attrGroups; } /** * Whether the method is explicitly or implicitly public. */ public function isPublic(): bool { return ($this->flags & Modifiers::PUBLIC) !== 0 || ($this->flags & Modifiers::VISIBILITY_MASK) === 0; } /** * Whether the method is protected. */ public function isProtected(): bool { return (bool) ($this->flags & Modifiers::PROTECTED); } /** * Whether the method is private. */ public function isPrivate(): bool { return (bool) ($this->flags & Modifiers::PRIVATE); } /** * Whether the method is abstract. */ public function isAbstract(): bool { return (bool) ($this->flags & Modifiers::ABSTRACT); } /** * Whether the method is final. */ public function isFinal(): bool { return (bool) ($this->flags & Modifiers::FINAL); } /** * Whether the method is static. */ public function isStatic(): bool { return (bool) ($this->flags & Modifiers::STATIC); } /** * Whether the method is magic. */ public function isMagic(): bool { return isset(self::$magicNames[$this->name->toLowerString()]); } public function getType(): string { return 'Stmt_ClassMethod'; } } 0 : Flags * 'extends' => null : Name of extended class * 'implements' => array(): Names of implemented interfaces * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->extends = $subNodes['extends'] ?? null; $this->implements = $subNodes['implements'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames(): array { return ['attrGroups', 'flags', 'name', 'extends', 'implements', 'stmts']; } /** * Whether the class is explicitly abstract. */ public function isAbstract(): bool { return (bool) ($this->flags & Modifiers::ABSTRACT); } /** * Whether the class is final. */ public function isFinal(): bool { return (bool) ($this->flags & Modifiers::FINAL); } public function isReadonly(): bool { return (bool) ($this->flags & Modifiers::READONLY); } /** * Whether the class is anonymous. */ public function isAnonymous(): bool { return null === $this->name; } public function getType(): string { return 'Stmt_Class'; } } $attributes Additional attributes * @param list $attrGroups PHP attribute groups */ public function __construct( array $consts, array $attributes = [], array $attrGroups = [] ) { $this->attributes = $attributes; $this->attrGroups = $attrGroups; $this->consts = $consts; } public function getSubNodeNames(): array { return ['attrGroups', 'consts']; } public function getType(): string { return 'Stmt_Const'; } } $attributes Additional attributes */ public function __construct(?Node\Expr $num = null, array $attributes = []) { $this->attributes = $attributes; $this->num = $num; } public function getSubNodeNames(): array { return ['num']; } public function getType(): string { return 'Stmt_Continue'; } } $attributes Additional attributes */ public function __construct(array $declares, ?array $stmts = null, array $attributes = []) { $this->attributes = $attributes; $this->declares = $declares; $this->stmts = $stmts; } public function getSubNodeNames(): array { return ['declares', 'stmts']; } public function getType(): string { return 'Stmt_Declare'; } } $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames(): array { return ['stmts', 'cond']; } public function getType(): string { return 'Stmt_Do'; } } $attributes Additional attributes */ public function __construct(array $exprs, array $attributes = []) { $this->attributes = $attributes; $this->exprs = $exprs; } public function getSubNodeNames(): array { return ['exprs']; } public function getType(): string { return 'Stmt_Echo'; } } $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames(): array { return ['cond', 'stmts']; } public function getType(): string { return 'Stmt_ElseIf'; } } $attributes Additional attributes */ public function __construct(array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->stmts = $stmts; } public function getSubNodeNames(): array { return ['stmts']; } public function getType(): string { return 'Stmt_Else'; } } $attrGroups PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, ?Node\Expr $expr = null, array $attrGroups = [], array $attributes = []) { parent::__construct($attributes); $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->expr = $expr; $this->attrGroups = $attrGroups; } public function getSubNodeNames(): array { return ['attrGroups', 'name', 'expr']; } public function getType(): string { return 'Stmt_EnumCase'; } } null : Scalar type * 'implements' => array() : Names of implemented interfaces * 'stmts' => array() : Statements * 'attrGroups' => array() : PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->scalarType = $subNodes['scalarType'] ?? null; $this->implements = $subNodes['implements'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; parent::__construct($attributes); } public function getSubNodeNames(): array { return ['attrGroups', 'name', 'scalarType', 'implements', 'stmts']; } public function getType(): string { return 'Stmt_Enum'; } } $attributes Additional attributes */ public function __construct(Node\Expr $expr, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Stmt_Expression'; } } $attributes Additional attributes */ public function __construct(array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->stmts = $stmts; } public function getSubNodeNames(): array { return ['stmts']; } public function getType(): string { return 'Stmt_Finally'; } } array(): Init expressions * 'cond' => array(): Loop conditions * 'loop' => array(): Loop expressions * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct(array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->init = $subNodes['init'] ?? []; $this->cond = $subNodes['cond'] ?? []; $this->loop = $subNodes['loop'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; } public function getSubNodeNames(): array { return ['init', 'cond', 'loop', 'stmts']; } public function getType(): string { return 'Stmt_For'; } } null : Variable to assign key to * 'byRef' => false : Whether to assign value by reference * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; $this->keyVar = $subNodes['keyVar'] ?? null; $this->byRef = $subNodes['byRef'] ?? false; $this->valueVar = $valueVar; $this->stmts = $subNodes['stmts'] ?? []; } public function getSubNodeNames(): array { return ['expr', 'keyVar', 'byRef', 'valueVar', 'stmts']; } public function getType(): string { return 'Stmt_Foreach'; } } false : Whether to return by reference * 'params' => array(): Parameters * 'returnType' => null : Return type * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->byRef = $subNodes['byRef'] ?? false; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->params = $subNodes['params'] ?? []; $this->returnType = $subNodes['returnType'] ?? null; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames(): array { return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; } public function returnsByRef(): bool { return $this->byRef; } public function getParams(): array { return $this->params; } public function getReturnType() { return $this->returnType; } public function getAttrGroups(): array { return $this->attrGroups; } /** @return Node\Stmt[] */ public function getStmts(): array { return $this->stmts; } public function getType(): string { return 'Stmt_Function'; } } $attributes Additional attributes */ public function __construct(array $vars, array $attributes = []) { $this->attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames(): array { return ['vars']; } public function getType(): string { return 'Stmt_Global'; } } $attributes Additional attributes */ public function __construct($name, array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames(): array { return ['name']; } public function getType(): string { return 'Stmt_Goto'; } } $attributes Additional attributes */ public function __construct(Name $prefix, array $uses, int $type = Use_::TYPE_NORMAL, array $attributes = []) { $this->attributes = $attributes; $this->type = $type; $this->prefix = $prefix; $this->uses = $uses; } public function getSubNodeNames(): array { return ['type', 'prefix', 'uses']; } public function getType(): string { return 'Stmt_GroupUse'; } } $attributes Additional attributes */ public function __construct(string $remaining, array $attributes = []) { $this->attributes = $attributes; $this->remaining = $remaining; } public function getSubNodeNames(): array { return ['remaining']; } public function getType(): string { return 'Stmt_HaltCompiler'; } } array(): Statements * 'elseifs' => array(): Elseif clauses * 'else' => null : Else clause * @param array $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $subNodes['stmts'] ?? []; $this->elseifs = $subNodes['elseifs'] ?? []; $this->else = $subNodes['else'] ?? null; } public function getSubNodeNames(): array { return ['cond', 'stmts', 'elseifs', 'else']; } public function getType(): string { return 'Stmt_If'; } } $attributes Additional attributes */ public function __construct(string $value, array $attributes = []) { $this->attributes = $attributes; $this->value = $value; } public function getSubNodeNames(): array { return ['value']; } public function getType(): string { return 'Stmt_InlineHTML'; } } array(): Name of extended interfaces * 'stmts' => array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->extends = $subNodes['extends'] ?? []; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames(): array { return ['attrGroups', 'name', 'extends', 'stmts']; } public function getType(): string { return 'Stmt_Interface'; } } $attributes Additional attributes */ public function __construct($name, array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new Identifier($name) : $name; } public function getSubNodeNames(): array { return ['name']; } public function getType(): string { return 'Stmt_Label'; } } $attributes Additional attributes */ public function __construct(?Node\Name $name = null, ?array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->name = $name; $this->stmts = $stmts; } public function getSubNodeNames(): array { return ['name', 'stmts']; } public function getType(): string { return 'Stmt_Namespace'; } } $attributes Additional attributes * @param null|Identifier|Name|ComplexType $type Type declaration * @param Node\AttributeGroup[] $attrGroups PHP attribute groups * @param Node\PropertyHook[] $hooks Property hooks */ public function __construct(int $flags, array $props, array $attributes = [], ?Node $type = null, array $attrGroups = [], array $hooks = []) { $this->attributes = $attributes; $this->flags = $flags; $this->props = $props; $this->type = $type; $this->attrGroups = $attrGroups; $this->hooks = $hooks; } public function getSubNodeNames(): array { return ['attrGroups', 'flags', 'type', 'props', 'hooks']; } /** * Whether the property is explicitly or implicitly public. */ public function isPublic(): bool { return ($this->flags & Modifiers::PUBLIC) !== 0 || ($this->flags & Modifiers::VISIBILITY_MASK) === 0; } /** * Whether the property is protected. */ public function isProtected(): bool { return (bool) ($this->flags & Modifiers::PROTECTED); } /** * Whether the property is private. */ public function isPrivate(): bool { return (bool) ($this->flags & Modifiers::PRIVATE); } /** * Whether the property is static. */ public function isStatic(): bool { return (bool) ($this->flags & Modifiers::STATIC); } /** * Whether the property is readonly. */ public function isReadonly(): bool { return (bool) ($this->flags & Modifiers::READONLY); } /** * Whether the property is abstract. */ public function isAbstract(): bool { return (bool) ($this->flags & Modifiers::ABSTRACT); } /** * Whether the property is final. */ public function isFinal(): bool { return (bool) ($this->flags & Modifiers::FINAL); } /** * Whether the property has explicit public(set) visibility. */ public function isPublicSet(): bool { return (bool) ($this->flags & Modifiers::PUBLIC_SET); } /** * Whether the property has explicit protected(set) visibility. */ public function isProtectedSet(): bool { return (bool) ($this->flags & Modifiers::PROTECTED_SET); } /** * Whether the property has explicit private(set) visibility. */ public function isPrivateSet(): bool { return (bool) ($this->flags & Modifiers::PRIVATE_SET); } public function getType(): string { return 'Stmt_Property'; } } $attributes Additional attributes */ public function __construct(?Node\Expr $expr = null, array $attributes = []) { $this->attributes = $attributes; $this->expr = $expr; } public function getSubNodeNames(): array { return ['expr']; } public function getType(): string { return 'Stmt_Return'; } } $attributes Additional attributes */ public function __construct(array $vars, array $attributes = []) { $this->attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames(): array { return ['vars']; } public function getType(): string { return 'Stmt_Static'; } } $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $cases, array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->cases = $cases; } public function getSubNodeNames(): array { return ['cond', 'cases']; } public function getType(): string { return 'Stmt_Switch'; } } $attributes Additional attributes */ public function __construct(array $traits, array $adaptations = [], array $attributes = []) { $this->attributes = $attributes; $this->traits = $traits; $this->adaptations = $adaptations; } public function getSubNodeNames(): array { return ['traits', 'adaptations']; } public function getType(): string { return 'Stmt_TraitUse'; } } $attributes Additional attributes */ public function __construct(?Node\Name $trait, $method, ?int $newModifier, $newName, array $attributes = []) { $this->attributes = $attributes; $this->trait = $trait; $this->method = \is_string($method) ? new Node\Identifier($method) : $method; $this->newModifier = $newModifier; $this->newName = \is_string($newName) ? new Node\Identifier($newName) : $newName; } public function getSubNodeNames(): array { return ['trait', 'method', 'newModifier', 'newName']; } public function getType(): string { return 'Stmt_TraitUseAdaptation_Alias'; } } $attributes Additional attributes */ public function __construct(Node\Name $trait, $method, array $insteadof, array $attributes = []) { $this->attributes = $attributes; $this->trait = $trait; $this->method = \is_string($method) ? new Node\Identifier($method) : $method; $this->insteadof = $insteadof; } public function getSubNodeNames(): array { return ['trait', 'method', 'insteadof']; } public function getType(): string { return 'Stmt_TraitUseAdaptation_Precedence'; } } array(): Statements * 'attrGroups' => array(): PHP attribute groups * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = [], array $attributes = []) { $this->attributes = $attributes; $this->name = \is_string($name) ? new Node\Identifier($name) : $name; $this->stmts = $subNodes['stmts'] ?? []; $this->attrGroups = $subNodes['attrGroups'] ?? []; } public function getSubNodeNames(): array { return ['attrGroups', 'name', 'stmts']; } public function getType(): string { return 'Stmt_Trait'; } } $attributes Additional attributes */ public function __construct(array $stmts, array $catches, ?Finally_ $finally = null, array $attributes = []) { $this->attributes = $attributes; $this->stmts = $stmts; $this->catches = $catches; $this->finally = $finally; } public function getSubNodeNames(): array { return ['stmts', 'catches', 'finally']; } public function getType(): string { return 'Stmt_TryCatch'; } } $attributes Additional attributes */ public function __construct(array $vars, array $attributes = []) { $this->attributes = $attributes; $this->vars = $vars; } public function getSubNodeNames(): array { return ['vars']; } public function getType(): string { return 'Stmt_Unset'; } } $attributes Additional attributes */ public function __construct(array $uses, int $type = self::TYPE_NORMAL, array $attributes = []) { $this->attributes = $attributes; $this->type = $type; $this->uses = $uses; } public function getSubNodeNames(): array { return ['type', 'uses']; } public function getType(): string { return 'Stmt_Use'; } } $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) { $this->attributes = $attributes; $this->cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames(): array { return ['cond', 'stmts']; } public function getType(): string { return 'Stmt_While'; } } $attributes Additional attributes */ public function __construct(array $types, array $attributes = []) { $this->attributes = $attributes; $this->types = $types; } public function getSubNodeNames(): array { return ['types']; } public function getType(): string { return 'UnionType'; } } $attributes Additional attributes */ public function __construct(Node\Name $name, $alias = null, int $type = Use_::TYPE_UNKNOWN, array $attributes = []) { $this->attributes = $attributes; $this->type = $type; $this->name = $name; $this->alias = \is_string($alias) ? new Identifier($alias) : $alias; } public function getSubNodeNames(): array { return ['type', 'name', 'alias']; } /** * Get alias. If not explicitly given this is the last component of the used name. */ public function getAlias(): Identifier { if (null !== $this->alias) { return $this->alias; } return new Identifier($this->name->getLast()); } public function getType(): string { return 'UseItem'; } } // @deprecated compatibility alias class_alias(UseItem::class, Stmt\UseUse::class); $attributes Additional attributes */ public function __construct(array $attributes = []) { $this->attributes = $attributes; } public function getType(): string { return 'VariadicPlaceholder'; } public function getSubNodeNames(): array { return []; } } Attributes */ protected array $attributes; /** * Creates a Node. * * @param array $attributes Array of attributes */ public function __construct(array $attributes = []) { $this->attributes = $attributes; } /** * Gets line the node started in (alias of getStartLine). * * @return int Start line (or -1 if not available) * @phpstan-return -1|positive-int */ public function getLine(): int { return $this->attributes['startLine'] ?? -1; } /** * Gets line the node started in. * * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default). * * @return int Start line (or -1 if not available) * @phpstan-return -1|positive-int */ public function getStartLine(): int { return $this->attributes['startLine'] ?? -1; } /** * Gets the line the node ended in. * * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default). * * @return int End line (or -1 if not available) * @phpstan-return -1|positive-int */ public function getEndLine(): int { return $this->attributes['endLine'] ?? -1; } /** * Gets the token offset of the first token that is part of this node. * * The offset is an index into the array returned by Lexer::getTokens(). * * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default). * * @return int Token start position (or -1 if not available) */ public function getStartTokenPos(): int { return $this->attributes['startTokenPos'] ?? -1; } /** * Gets the token offset of the last token that is part of this node. * * The offset is an index into the array returned by Lexer::getTokens(). * * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default). * * @return int Token end position (or -1 if not available) */ public function getEndTokenPos(): int { return $this->attributes['endTokenPos'] ?? -1; } /** * Gets the file offset of the first character that is part of this node. * * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default). * * @return int File start position (or -1 if not available) */ public function getStartFilePos(): int { return $this->attributes['startFilePos'] ?? -1; } /** * Gets the file offset of the last character that is part of this node. * * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default). * * @return int File end position (or -1 if not available) */ public function getEndFilePos(): int { return $this->attributes['endFilePos'] ?? -1; } /** * Gets all comments directly preceding this node. * * The comments are also available through the "comments" attribute. * * @return Comment[] */ public function getComments(): array { return $this->attributes['comments'] ?? []; } /** * Gets the doc comment of the node. * * @return null|Comment\Doc Doc comment object or null */ public function getDocComment(): ?Comment\Doc { $comments = $this->getComments(); for ($i = count($comments) - 1; $i >= 0; $i--) { $comment = $comments[$i]; if ($comment instanceof Comment\Doc) { return $comment; } } return null; } /** * Sets the doc comment of the node. * * This will either replace an existing doc comment or add it to the comments array. * * @param Comment\Doc $docComment Doc comment to set */ public function setDocComment(Comment\Doc $docComment): void { $comments = $this->getComments(); for ($i = count($comments) - 1; $i >= 0; $i--) { if ($comments[$i] instanceof Comment\Doc) { // Replace existing doc comment. $comments[$i] = $docComment; $this->setAttribute('comments', $comments); return; } } // Append new doc comment. $comments[] = $docComment; $this->setAttribute('comments', $comments); } public function setAttribute(string $key, $value): void { $this->attributes[$key] = $value; } public function hasAttribute(string $key): bool { return array_key_exists($key, $this->attributes); } public function getAttribute(string $key, $default = null) { if (array_key_exists($key, $this->attributes)) { return $this->attributes[$key]; } return $default; } public function getAttributes(): array { return $this->attributes; } public function setAttributes(array $attributes): void { $this->attributes = $attributes; } /** * @return array */ public function jsonSerialize(): array { return ['nodeType' => $this->getType()] + get_object_vars($this); } } true, 'startLine' => true, 'endLine' => true, 'startFilePos' => true, 'endFilePos' => true, 'startTokenPos' => true, 'endTokenPos' => true, ]; /** * Constructs a NodeDumper. * * Supported options: * * bool dumpComments: Whether comments should be dumped. * * bool dumpPositions: Whether line/offset information should be dumped. To dump offset * information, the code needs to be passed to dump(). * * bool dumpOtherAttributes: Whether non-comment, non-position attributes should be dumped. * * @param array $options Options (see description) */ public function __construct(array $options = []) { $this->dumpComments = !empty($options['dumpComments']); $this->dumpPositions = !empty($options['dumpPositions']); $this->dumpOtherAttributes = !empty($options['dumpOtherAttributes']); } /** * Dumps a node or array. * * @param array|Node $node Node or array to dump * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if * the dumpPositions option is enabled and the dumping of node offsets * is desired. * * @return string Dumped value */ public function dump($node, ?string $code = null): string { $this->code = $code; $this->res = ''; $this->nl = "\n"; $this->dumpRecursive($node, false); return $this->res; } /** @param mixed $node */ protected function dumpRecursive($node, bool $indent = true): void { if ($indent) { $this->nl .= " "; } if ($node instanceof Node) { $this->res .= $node->getType(); if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) { $this->res .= $p; } $this->res .= '('; foreach ($node->getSubNodeNames() as $key) { $this->res .= "$this->nl " . $key . ': '; $value = $node->$key; if (\is_int($value)) { if ('flags' === $key || 'newModifier' === $key) { $this->res .= $this->dumpFlags($value); continue; } if ('type' === $key && $node instanceof Include_) { $this->res .= $this->dumpIncludeType($value); continue; } if ('type' === $key && ($node instanceof Use_ || $node instanceof UseItem || $node instanceof GroupUse)) { $this->res .= $this->dumpUseType($value); continue; } } $this->dumpRecursive($value); } if ($this->dumpComments && $comments = $node->getComments()) { $this->res .= "$this->nl comments: "; $this->dumpRecursive($comments); } if ($this->dumpOtherAttributes) { foreach ($node->getAttributes() as $key => $value) { if (isset(self::IGNORE_ATTRIBUTES[$key])) { continue; } $this->res .= "$this->nl $key: "; if (\is_int($value)) { if ('kind' === $key) { if ($node instanceof Int_) { $this->res .= $this->dumpIntKind($value); continue; } if ($node instanceof String_ || $node instanceof InterpolatedString) { $this->res .= $this->dumpStringKind($value); continue; } if ($node instanceof Array_) { $this->res .= $this->dumpArrayKind($value); continue; } if ($node instanceof List_) { $this->res .= $this->dumpListKind($value); continue; } } } $this->dumpRecursive($value); } } $this->res .= "$this->nl)"; } elseif (\is_array($node)) { $this->res .= 'array('; foreach ($node as $key => $value) { $this->res .= "$this->nl " . $key . ': '; $this->dumpRecursive($value); } $this->res .= "$this->nl)"; } elseif ($node instanceof Comment) { $this->res .= \str_replace("\n", $this->nl, $node->getReformattedText()); } elseif (\is_string($node)) { $this->res .= \str_replace("\n", $this->nl, $node); } elseif (\is_int($node) || \is_float($node)) { $this->res .= $node; } elseif (null === $node) { $this->res .= 'null'; } elseif (false === $node) { $this->res .= 'false'; } elseif (true === $node) { $this->res .= 'true'; } else { throw new \InvalidArgumentException('Can only dump nodes and arrays.'); } if ($indent) { $this->nl = \substr($this->nl, 0, -4); } } protected function dumpFlags(int $flags): string { $strs = []; if ($flags & Modifiers::PUBLIC) { $strs[] = 'PUBLIC'; } if ($flags & Modifiers::PROTECTED) { $strs[] = 'PROTECTED'; } if ($flags & Modifiers::PRIVATE) { $strs[] = 'PRIVATE'; } if ($flags & Modifiers::ABSTRACT) { $strs[] = 'ABSTRACT'; } if ($flags & Modifiers::STATIC) { $strs[] = 'STATIC'; } if ($flags & Modifiers::FINAL) { $strs[] = 'FINAL'; } if ($flags & Modifiers::READONLY) { $strs[] = 'READONLY'; } if ($flags & Modifiers::PUBLIC_SET) { $strs[] = 'PUBLIC_SET'; } if ($flags & Modifiers::PROTECTED_SET) { $strs[] = 'PROTECTED_SET'; } if ($flags & Modifiers::PRIVATE_SET) { $strs[] = 'PRIVATE_SET'; } if ($strs) { return implode(' | ', $strs) . ' (' . $flags . ')'; } else { return (string) $flags; } } /** @param array $map */ private function dumpEnum(int $value, array $map): string { if (!isset($map[$value])) { return (string) $value; } return $map[$value] . ' (' . $value . ')'; } private function dumpIncludeType(int $type): string { return $this->dumpEnum($type, [ Include_::TYPE_INCLUDE => 'TYPE_INCLUDE', Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE', Include_::TYPE_REQUIRE => 'TYPE_REQUIRE', Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE', ]); } private function dumpUseType(int $type): string { return $this->dumpEnum($type, [ Use_::TYPE_UNKNOWN => 'TYPE_UNKNOWN', Use_::TYPE_NORMAL => 'TYPE_NORMAL', Use_::TYPE_FUNCTION => 'TYPE_FUNCTION', Use_::TYPE_CONSTANT => 'TYPE_CONSTANT', ]); } private function dumpIntKind(int $kind): string { return $this->dumpEnum($kind, [ Int_::KIND_BIN => 'KIND_BIN', Int_::KIND_OCT => 'KIND_OCT', Int_::KIND_DEC => 'KIND_DEC', Int_::KIND_HEX => 'KIND_HEX', ]); } private function dumpStringKind(int $kind): string { return $this->dumpEnum($kind, [ String_::KIND_SINGLE_QUOTED => 'KIND_SINGLE_QUOTED', String_::KIND_DOUBLE_QUOTED => 'KIND_DOUBLE_QUOTED', String_::KIND_HEREDOC => 'KIND_HEREDOC', String_::KIND_NOWDOC => 'KIND_NOWDOC', ]); } private function dumpArrayKind(int $kind): string { return $this->dumpEnum($kind, [ Array_::KIND_LONG => 'KIND_LONG', Array_::KIND_SHORT => 'KIND_SHORT', ]); } private function dumpListKind(int $kind): string { return $this->dumpEnum($kind, [ List_::KIND_LIST => 'KIND_LIST', List_::KIND_ARRAY => 'KIND_ARRAY', ]); } /** * Dump node position, if possible. * * @param Node $node Node for which to dump position * * @return string|null Dump of position, or null if position information not available */ protected function dumpPosition(Node $node): ?string { if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) { return null; } $start = $node->getStartLine(); $end = $node->getEndLine(); if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos') && null !== $this->code ) { $start .= ':' . $this->toColumn($this->code, $node->getStartFilePos()); $end .= ':' . $this->toColumn($this->code, $node->getEndFilePos()); } return "[$start - $end]"; } // Copied from Error class private function toColumn(string $code, int $pos): int { if ($pos > strlen($code)) { throw new \RuntimeException('Invalid position information'); } $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); if (false === $lineStartPos) { $lineStartPos = -1; } return $pos - $lineStartPos; } } traverse($nodes); return $visitor->getFoundNodes(); } /** * Find all nodes that are instances of a certain class. * @template TNode as Node * * @param Node|Node[] $nodes Single node or array of nodes to search in * @param class-string $class Class name * * @return TNode[] Found nodes (all instances of $class) */ public function findInstanceOf($nodes, string $class): array { return $this->find($nodes, function ($node) use ($class) { return $node instanceof $class; }); } /** * Find first node satisfying a filter callback. * * @param Node|Node[] $nodes Single node or array of nodes to search in * @param callable $filter Filter callback: function(Node $node) : bool * * @return null|Node Found node (or null if none found) */ public function findFirst($nodes, callable $filter): ?Node { if ($nodes === []) { return null; } if (!is_array($nodes)) { $nodes = [$nodes]; } $visitor = new FirstFindingVisitor($filter); $traverser = new NodeTraverser($visitor); $traverser->traverse($nodes); return $visitor->getFoundNode(); } /** * Find first node that is an instance of a certain class. * * @template TNode as Node * * @param Node|Node[] $nodes Single node or array of nodes to search in * @param class-string $class Class name * * @return null|TNode Found node, which is an instance of $class (or null if none found) */ public function findFirstInstanceOf($nodes, string $class): ?Node { return $this->findFirst($nodes, function ($node) use ($class) { return $node instanceof $class; }); } } Visitors */ protected array $visitors = []; /** @var bool Whether traversal should be stopped */ protected bool $stopTraversal; /** * Create a traverser with the given visitors. * * @param NodeVisitor ...$visitors Node visitors */ public function __construct(NodeVisitor ...$visitors) { $this->visitors = $visitors; } /** * Adds a visitor. * * @param NodeVisitor $visitor Visitor to add */ public function addVisitor(NodeVisitor $visitor): void { $this->visitors[] = $visitor; } /** * Removes an added visitor. */ public function removeVisitor(NodeVisitor $visitor): void { $index = array_search($visitor, $this->visitors); if ($index !== false) { array_splice($this->visitors, $index, 1, []); } } /** * 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) { if (null !== $return = $visitor->beforeTraverse($nodes)) { $nodes = $return; } } $nodes = $this->traverseArray($nodes); for ($i = \count($this->visitors) - 1; $i >= 0; --$i) { $visitor = $this->visitors[$i]; if (null !== $return = $visitor->afterTraverse($nodes)) { $nodes = $return; } } return $nodes; } /** * Recursively traverse a node. * * @param Node $node Node to traverse. */ protected function traverseNode(Node $node): void { foreach ($node->getSubNodeNames() as $name) { $subNode = $node->$name; if (\is_array($subNode)) { $node->$name = $this->traverseArray($subNode); if ($this->stopTraversal) { break; } continue; } if (!$subNode instanceof Node) { continue; } $traverseChildren = true; $visitorIndex = -1; foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($subNode); if (null !== $return) { if ($return instanceof Node) { $this->ensureReplacementReasonable($subNode, $return); $subNode = $node->$name = $return; } elseif (NodeVisitor::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = false; } elseif (NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { $traverseChildren = false; break; } elseif (NodeVisitor::STOP_TRAVERSAL === $return) { $this->stopTraversal = true; break 2; } elseif (NodeVisitor::REPLACE_WITH_NULL === $return) { $node->$name = null; continue 2; } else { throw new \LogicException( 'enterNode() returned invalid value of type ' . gettype($return) ); } } } if ($traverseChildren) { $this->traverseNode($subNode); if ($this->stopTraversal) { break; } } for (; $visitorIndex >= 0; --$visitorIndex) { $visitor = $this->visitors[$visitorIndex]; $return = $visitor->leaveNode($subNode); if (null !== $return) { if ($return instanceof Node) { $this->ensureReplacementReasonable($subNode, $return); $subNode = $node->$name = $return; } elseif (NodeVisitor::STOP_TRAVERSAL === $return) { $this->stopTraversal = true; break 2; } elseif (NodeVisitor::REPLACE_WITH_NULL === $return) { $node->$name = null; break; } 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) ); } } } } } /** * Recursively traverse array (usually of nodes). * * @param Node[] $nodes Array to traverse * * @return Node[] Result of traversal (may be original array or changed one) */ protected function traverseArray(array $nodes): array { $doNodes = []; foreach ($nodes as $i => $node) { if (!$node instanceof Node) { if (\is_array($node)) { throw new \LogicException('Invalid node structure: Contains nested arrays'); } continue; } $traverseChildren = true; $visitorIndex = -1; foreach ($this->visitors as $visitorIndex => $visitor) { $return = $visitor->enterNode($node); if (null !== $return) { if ($return instanceof Node) { $this->ensureReplacementReasonable($node, $return); $nodes[$i] = $node = $return; } elseif (\is_array($return)) { $doNodes[] = [$i, $return]; continue 2; } elseif (NodeVisitor::REMOVE_NODE === $return) { $doNodes[] = [$i, []]; continue 2; } elseif (NodeVisitor::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = false; } elseif (NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { $traverseChildren = false; break; } elseif (NodeVisitor::STOP_TRAVERSAL === $return) { $this->stopTraversal = true; break 2; } elseif (NodeVisitor::REPLACE_WITH_NULL === $return) { throw new \LogicException( 'REPLACE_WITH_NULL can not be used if the parent structure is an array'); } else { throw new \LogicException( 'enterNode() returned invalid value of type ' . gettype($return) ); } } } if ($traverseChildren) { $this->traverseNode($node); if ($this->stopTraversal) { break; } } for (; $visitorIndex >= 0; --$visitorIndex) { $visitor = $this->visitors[$visitorIndex]; $return = $visitor->leaveNode($node); if (null !== $return) { if ($return instanceof Node) { $this->ensureReplacementReasonable($node, $return); $nodes[$i] = $node = $return; } elseif (\is_array($return)) { $doNodes[] = [$i, $return]; break; } elseif (NodeVisitor::REMOVE_NODE === $return) { $doNodes[] = [$i, []]; break; } elseif (NodeVisitor::STOP_TRAVERSAL === $return) { $this->stopTraversal = true; break 2; } elseif (NodeVisitor::REPLACE_WITH_NULL === $return) { throw new \LogicException( 'REPLACE_WITH_NULL can not be used if the parent structure is an array'); } else { throw new \LogicException( 'leaveNode() returned invalid value of type ' . gettype($return) ); } } } } if (!empty($doNodes)) { while (list($i, $replace) = array_pop($doNodes)) { array_splice($nodes, $i, 1, $replace); } } return $nodes; } private function ensureReplacementReasonable(Node $old, Node $new): void { if ($old instanceof Node\Stmt && $new instanceof Node\Expr) { throw new \LogicException( "Trying to replace statement ({$old->getType()}) " . "with expression ({$new->getType()}). Are you missing a " . "Stmt_Expression wrapper?" ); } if ($old instanceof Node\Expr && $new instanceof Node\Stmt) { throw new \LogicException( "Trying to replace expression ({$old->getType()}) " . "with statement ({$new->getType()})" ); } } } $node stays as-is * * array (of Nodes) * => The return value is merged into the parent array (at the position of the $node) * * NodeVisitor::REMOVE_NODE * => $node is removed from the parent array * * NodeVisitor::REPLACE_WITH_NULL * => $node is replaced with null * * NodeVisitor::DONT_TRAVERSE_CHILDREN * => Children of $node are not traversed. $node stays as-is * * NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN * => Further visitors for the current node are skipped, and its children are not * traversed. $node stays as-is. * * NodeVisitor::STOP_TRAVERSAL * => Traversal is aborted. $node stays as-is * * otherwise * => $node is set to the return value * * @param Node $node Node * * @return null|int|Node|Node[] Replacement node (or special return value) */ public function enterNode(Node $node); /** * Called when leaving a node. * * Return value semantics: * * null * => $node stays as-is * * NodeVisitor::REMOVE_NODE * => $node is removed from the parent array * * NodeVisitor::REPLACE_WITH_NULL * => $node is replaced with null * * NodeVisitor::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 null|int|Node|Node[] 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 null|Node[] Array of nodes */ public function afterTraverse(array $nodes); } setAttribute('origNode', $origNode); return $node; } } Token positions of comments */ private array $commentPositions = []; /** * Create a comment annotation visitor. * * @param Token[] $tokens Token array */ public function __construct(array $tokens) { $this->tokens = $tokens; // Collect positions of comments. We use this to avoid traversing parts of the AST where // there are no comments. foreach ($tokens as $i => $token) { if ($token->id === \T_COMMENT || $token->id === \T_DOC_COMMENT) { $this->commentPositions[] = $i; } } } public function enterNode(Node $node) { $nextCommentPos = current($this->commentPositions); if ($nextCommentPos === false) { // No more comments. return self::STOP_TRAVERSAL; } $oldPos = $this->pos; $this->pos = $pos = $node->getStartTokenPos(); if ($nextCommentPos > $oldPos && $nextCommentPos < $pos) { $comments = []; while (--$pos >= $oldPos) { $token = $this->tokens[$pos]; if ($token->id === \T_DOC_COMMENT) { $comments[] = new Comment\Doc( $token->text, $token->line, $token->pos, $pos, $token->getEndLine(), $token->getEndPos() - 1, $pos); continue; } if ($token->id === \T_COMMENT) { $comments[] = new Comment( $token->text, $token->line, $token->pos, $pos, $token->getEndLine(), $token->getEndPos() - 1, $pos); continue; } if ($token->id !== \T_WHITESPACE) { break; } } if (!empty($comments)) { $node->setAttribute('comments', array_reverse($comments)); } do { $nextCommentPos = next($this->commentPositions); } while ($nextCommentPos !== false && $nextCommentPos < $this->pos); } $endPos = $node->getEndTokenPos(); if ($nextCommentPos > $endPos) { // Skip children if there are no comments located inside this node. $this->pos = $endPos; return self::DONT_TRAVERSE_CHILDREN; } return null; } } Found nodes */ protected array $foundNodes; public function __construct(callable $filterCallback) { $this->filterCallback = $filterCallback; } /** * Get found nodes satisfying the filter callback. * * Nodes are returned in pre-order. * * @return list Found nodes */ public function getFoundNodes(): array { return $this->foundNodes; } public function beforeTraverse(array $nodes): ?array { $this->foundNodes = []; return null; } public function enterNode(Node $node) { $filterCallback = $this->filterCallback; if ($filterCallback($node)) { $this->foundNodes[] = $node; } return null; } } filterCallback = $filterCallback; } /** * Get found node satisfying the filter callback. * * Returns null if no node satisfies the filter callback. * * @return null|Node Found node (or null if not found) */ public function getFoundNode(): ?Node { return $this->foundNode; } public function beforeTraverse(array $nodes): ?array { $this->foundNode = null; return null; } public function enterNode(Node $node) { $filterCallback = $this->filterCallback; if ($filterCallback($node)) { $this->foundNode = $node; return NodeVisitor::STOP_TRAVERSAL; } return null; } } nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing()); $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false; $this->replaceNodes = $options['replaceNodes'] ?? true; } /** * Get name resolution context. */ public function getNameContext(): NameContext { return $this->nameContext; } public function beforeTraverse(array $nodes): ?array { $this->nameContext->startNamespace(); return null; } public function enterNode(Node $node) { if ($node instanceof Stmt\Namespace_) { $this->nameContext->startNamespace($node->name); } elseif ($node instanceof Stmt\Use_) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type, null); } } elseif ($node instanceof Stmt\GroupUse) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type, $node->prefix); } } elseif ($node instanceof Stmt\Class_) { if (null !== $node->extends) { $node->extends = $this->resolveClassName($node->extends); } foreach ($node->implements as &$interface) { $interface = $this->resolveClassName($interface); } $this->resolveAttrGroups($node); if (null !== $node->name) { $this->addNamespacedName($node); } else { $node->namespacedName = null; } } elseif ($node instanceof Stmt\Interface_) { foreach ($node->extends as &$interface) { $interface = $this->resolveClassName($interface); } $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof Stmt\Enum_) { foreach ($node->implements as &$interface) { $interface = $this->resolveClassName($interface); } $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof Stmt\Trait_) { $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof Stmt\Function_) { $this->resolveSignature($node); $this->resolveAttrGroups($node); $this->addNamespacedName($node); } elseif ($node instanceof Stmt\ClassMethod || $node instanceof Expr\Closure || $node instanceof Expr\ArrowFunction ) { $this->resolveSignature($node); $this->resolveAttrGroups($node); } elseif ($node instanceof Stmt\Property) { if (null !== $node->type) { $node->type = $this->resolveType($node->type); } $this->resolveAttrGroups($node); } elseif ($node instanceof Node\PropertyHook) { foreach ($node->params as $param) { $param->type = $this->resolveType($param->type); $this->resolveAttrGroups($param); } $this->resolveAttrGroups($node); } elseif ($node instanceof Stmt\Const_) { foreach ($node->consts as $const) { $this->addNamespacedName($const); } $this->resolveAttrGroups($node); } elseif ($node instanceof Stmt\ClassConst) { if (null !== $node->type) { $node->type = $this->resolveType($node->type); } $this->resolveAttrGroups($node); } elseif ($node instanceof Stmt\EnumCase) { $this->resolveAttrGroups($node); } elseif ($node instanceof Expr\StaticCall || $node instanceof Expr\StaticPropertyFetch || $node instanceof Expr\ClassConstFetch || $node instanceof Expr\New_ || $node instanceof Expr\Instanceof_ ) { if ($node->class instanceof Name) { $node->class = $this->resolveClassName($node->class); } } elseif ($node instanceof Stmt\Catch_) { foreach ($node->types as &$type) { $type = $this->resolveClassName($type); } } elseif ($node instanceof Expr\FuncCall) { if ($node->name instanceof Name) { $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION); } } elseif ($node instanceof Expr\ConstFetch) { $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT); } elseif ($node instanceof Stmt\TraitUse) { foreach ($node->traits as &$trait) { $trait = $this->resolveClassName($trait); } foreach ($node->adaptations as $adaptation) { if (null !== $adaptation->trait) { $adaptation->trait = $this->resolveClassName($adaptation->trait); } if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { foreach ($adaptation->insteadof as &$insteadof) { $insteadof = $this->resolveClassName($insteadof); } } } } return null; } /** @param Stmt\Use_::TYPE_* $type */ private function addAlias(Node\UseItem $use, int $type, ?Name $prefix = null): void { // Add prefix for group uses $name = $prefix ? Name::concat($prefix, $use->name) : $use->name; // Type is determined either by individual element or whole use declaration $type |= $use->type; $this->nameContext->addAlias( $name, (string) $use->getAlias(), $type, $use->getAttributes() ); } /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure|Expr\ArrowFunction $node */ private function resolveSignature($node): void { foreach ($node->params as $param) { $param->type = $this->resolveType($param->type); $this->resolveAttrGroups($param); } $node->returnType = $this->resolveType($node->returnType); } /** * @template T of Node\Identifier|Name|Node\ComplexType|null * @param T $node * @return T */ private function resolveType(?Node $node): ?Node { if ($node instanceof Name) { return $this->resolveClassName($node); } if ($node instanceof Node\NullableType) { $node->type = $this->resolveType($node->type); return $node; } if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) { foreach ($node->types as &$type) { $type = $this->resolveType($type); } return $node; } return $node; } /** * Resolve name, according to name resolver options. * * @param Name $name Function or constant name to resolve * @param Stmt\Use_::TYPE_* $type One of Stmt\Use_::TYPE_* * * @return Name Resolved name, or original name with attribute */ protected function resolveName(Name $name, int $type): Name { if (!$this->replaceNodes) { $resolvedName = $this->nameContext->getResolvedName($name, $type); if (null !== $resolvedName) { $name->setAttribute('resolvedName', $resolvedName); } else { $name->setAttribute('namespacedName', FullyQualified::concat( $this->nameContext->getNamespace(), $name, $name->getAttributes())); } return $name; } if ($this->preserveOriginalNames) { // Save the original name $originalName = $name; $name = clone $originalName; $name->setAttribute('originalName', $originalName); } $resolvedName = $this->nameContext->getResolvedName($name, $type); if (null !== $resolvedName) { return $resolvedName; } // unqualified names inside a namespace cannot be resolved at compile-time // add the namespaced version of the name as an attribute $name->setAttribute('namespacedName', FullyQualified::concat( $this->nameContext->getNamespace(), $name, $name->getAttributes())); return $name; } protected function resolveClassName(Name $name): Name { return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL); } protected function addNamespacedName(Node $node): void { $node->namespacedName = Name::concat( $this->nameContext->getNamespace(), (string) $node->name); } protected function resolveAttrGroups(Node $node): void { foreach ($node->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { $attr->name = $this->resolveClassName($attr->name); } } } } $weakReferences=false on the child node, the parent node can be accessed through * $node->getAttribute('parent'), the previous * node can be accessed through $node->getAttribute('previous'), * and the next node can be accessed through $node->getAttribute('next'). * * With $weakReferences=true attribute names are prefixed by "weak_", e.g. "weak_parent". */ final class NodeConnectingVisitor extends NodeVisitorAbstract { /** * @var Node[] */ private array $stack = []; /** * @var ?Node */ private $previous; private bool $weakReferences; public function __construct(bool $weakReferences = false) { $this->weakReferences = $weakReferences; } public function beforeTraverse(array $nodes) { $this->stack = []; $this->previous = null; } public function enterNode(Node $node) { if (!empty($this->stack)) { $parent = $this->stack[count($this->stack) - 1]; if ($this->weakReferences) { $node->setAttribute('weak_parent', \WeakReference::create($parent)); } else { $node->setAttribute('parent', $parent); } } if ($this->previous !== null) { if ( $this->weakReferences ) { if ($this->previous->getAttribute('weak_parent') === $node->getAttribute('weak_parent')) { $node->setAttribute('weak_previous', \WeakReference::create($this->previous)); $this->previous->setAttribute('weak_next', \WeakReference::create($node)); } } elseif ($this->previous->getAttribute('parent') === $node->getAttribute('parent')) { $node->setAttribute('previous', $this->previous); $this->previous->setAttribute('next', $node); } } $this->stack[] = $node; } public function leaveNode(Node $node) { $this->previous = $node; array_pop($this->stack); } } $weakReferences=false on the child node, the parent node can be accessed through * $node->getAttribute('parent'). * * With $weakReferences=true the attribute name is "weak_parent" instead. */ final class ParentConnectingVisitor extends NodeVisitorAbstract { /** * @var Node[] */ private array $stack = []; private bool $weakReferences; public function __construct(bool $weakReferences = false) { $this->weakReferences = $weakReferences; } public function beforeTraverse(array $nodes) { $this->stack = []; } public function enterNode(Node $node) { if (!empty($this->stack)) { $parent = $this->stack[count($this->stack) - 1]; if ($this->weakReferences) { $node->setAttribute('weak_parent', \WeakReference::create($parent)); } else { $node->setAttribute('parent', $parent); } } $this->stack[] = $node; } public function leaveNode(Node $node) { array_pop($this->stack); } } '", "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "'+'", "'-'", "'.'", "'*'", "'/'", "'%'", "'!'", "T_INSTANCEOF", "'~'", "T_INC", "T_DEC", "T_INT_CAST", "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", "T_BOOL_CAST", "T_UNSET_CAST", "'@'", "T_POW", "'['", "T_NEW", "T_CLONE", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_MATCH", "T_ENDSWITCH", "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_GOTO", "T_FUNCTION", "T_FN", "T_CONST", "T_RETURN", "T_TRY", "T_CATCH", "T_FINALLY", "T_USE", "T_INSTEADOF", "T_GLOBAL", "T_STATIC", "T_ABSTRACT", "T_FINAL", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", "T_READONLY", "T_PUBLIC_SET", "T_PROTECTED_SET", "T_PRIVATE_SET", "T_VAR", "T_UNSET", "T_ISSET", "T_EMPTY", "T_HALT_COMPILER", "T_CLASS", "T_TRAIT", "T_INTERFACE", "T_ENUM", "T_EXTENDS", "T_IMPLEMENTS", "T_OBJECT_OPERATOR", "T_NULLSAFE_OBJECT_OPERATOR", "T_LIST", "T_ARRAY", "T_CALLABLE", "T_CLASS_C", "T_TRAIT_C", "T_METHOD_C", "T_FUNC_C", "T_PROPERTY_C", "T_LINE", "T_FILE", "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", "T_ELLIPSIS", "T_NAME_FULLY_QUALIFIED", "T_NAME_QUALIFIED", "T_NAME_RELATIVE", "T_ATTRIBUTE", "';'", "']'", "'('", "')'", "'{'", "'}'", "'`'", "'\"'", "'$'" ); protected array $tokenToSymbol = array( 0, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 57, 171, 173, 172, 56, 173, 173, 166, 167, 54, 51, 9, 52, 53, 55, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 32, 164, 45, 17, 47, 31, 69, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 71, 173, 165, 37, 173, 170, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 168, 36, 169, 59, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 35, 38, 39, 40, 41, 42, 43, 44, 46, 48, 49, 50, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163 ); protected array $action = array( 133, 134, 135, 575, 136, 137, 1049, 766, 767, 768, 138, 41, 850, -341, 495, 1390,-32766,-32766,-32766, 1008, 841, 1145, 1146, 1147, 1141, 1140, 1139, 1148, 1142, 1143, 1144,-32766,-32766,-32766, -195, 760, 759,-32766, -194,-32766, -32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, -32767, 0,-32766, 3, 4, 769, 1145, 1146, 1147, 1141, 1140, 1139, 1148, 1142, 1143, 1144, 388, 389, 448, 272, 53, 391, 773, 774, 775, 776, 433, 5, 434, 571, 337, 39, 254, 29, 298, 830, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 806, 576, 807, 808, 809, 810, 798, 799, 353, 354, 801, 802, 787, 788, 789, 791, 792, 793, 364, 833, 834, 835, 836, 837, 577, -382, 306, -382, 794, 795, 578, 579, 244, 818, 816, 817, 829, 813, 814, 1313, 38, 580, 581, 812, 582, 583, 584, 585, 1325, 586, 587, 481, 482, -628, 496, 1009, 815, 588, 589, 140, 139, -628, 133, 134, 135, 575, 136, 137, 1085, 766, 767, 768, 138, 41, -32766, -341, 1046, 1041, 1040, 1039, 1045, 1042, 1043, 1044, -32766,-32766,-32766,-32767,-32767,-32767,-32767, 106, 107, 108, 109, 110, -195, 760, 759, 1058, -194,-32766,-32766,-32766, 149,-32766, 852,-32766,-32766,-32766,-32766,-32766,-32766,-32766, 936, 303, 257, 769,-32766,-32766,-32766, 850,-32766, 297, -32766,-32766,-32766,-32766,-32766, 1371, 1355, 272, 53, 391, 773, 774, 775, 776, -625,-32766, 434,-32766,-32766,-32766, -32766, 730, -625, 830, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 806, 576, 807, 808, 809, 810, 798, 799, 353, 354, 801, 802, 787, 788, 789, 791, 792, 793, 364, 833, 834, 835, 836, 837, 577, -579, -275, 317, 794, 795, 578, 579, -577, 818, 816, 817, 829, 813, 814, 957, 926, 580, 581, 812, 582, 583, 584, 585, 144, 586, 587, 841, 336,-32766,-32766,-32766, 815, 588, 589, -628, 139, -628, 133, 134, 135, 575, 136, 137, 1082, 766, 767, 768, 138, 41,-32766, 1375, -32766,-32766,-32766,-32766,-32766,-32766,-32766, 1374, 629, 388, 389,-32766,-32766,-32766,-32766,-32766, -579, -579, 1081, 433, 321, 760, 759, -577, -577,-32766, 1293,-32766,-32766, 111, 112, 113, -579, 282, 843, 851, 623, 1400, 936, -577, 1401, 769, 333, 938, -585, 114, -579, 725, 294, 298, 1119, -584, 349, -577, 752, 272, 53, 391, 773, 774, 775, 776, 145, 86, 434, 306, 336, 336, -625, 731, -625, 830, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 806, 576, 807, 808, 809, 810, 798, 799, 353, 354, 801, 802, 787, 788, 789, 791, 792, 793, 364, 833, 834, 835, 836, 837, 577, -576, 850, -578, 794, 795, 578, 579, 845, 818, 816, 817, 829, 813, 814, 727, 926, 580, 581, 812, 582, 583, 584, 585, 740, 586, 587, 243, 1055,-32766,-32766, -85, 815, 588, 589, 878, 152, 879, 133, 134, 135, 575, 136, 137, 1087, 766, 767, 768, 138, 41, 350, 961, 960, 1058, 1058, 1058,-32766,-32766,-32766, 841,-32766, 131, 977, 978, 400, 1055, 10, 979, -576, -576, -578, -578, 378, 760, 759, 936, 973, 290, 297, 297,-32766, 846, 936, 154, -576, 79, -578, 382, 849, 936, 1058, 336, 878, 769, 879, 938, -583, -85, -576, 725, -578, 959, 108, 109, 110, 1058, 732, 272, 53, 391, 773, 774, 775, 776, 290, 155, 434, 470, 471, 472, 735, 760, 759, 830, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 806, 576, 807, 808, 809, 810, 798, 799, 353, 354, 801, 802, 787, 788, 789, 791, 792, 793, 364, 833, 834, 835, 836, 837, 577, 926, 434, 847, 794, 795, 578, 579, 926, 818, 816, 817, 829, 813, 814, 926, 398, 580, 581, 812, 582, 583, 584, 585, 452, 586, 587, 157, 87, 88, 89, 453, 815, 588, 589, 454, 152, 790, 761, 762, 763, 764, 765, 158, 766, 767, 768, 803, 804, 40, 27, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 1134, 282, 1055, 455,-32766, 994, 1288, 1287, 1289, 725, 390, 389, 938, 114, 856, 1120, 725, 769, 159, 938, 433, 672, 23, 725, 1118, 691, 692, 1058,-32766, 153, 416, 770, 771, 772, 773, 774, 775, 776, -78, -619, 839, -619, -581, 386, 387, 392, 393, 830, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 806, 828, 807, 808, 809, 810, 798, 799, 800, 827, 801, 802, 787, 788, 789, 791, 792, 793, 832, 833, 834, 835, 836, 837, 838, 161, 663, 664, 794, 795, 796, 797, 36, 818, 816, 817, 829, 813, 814, -58, -57, 805, 811, 812, 819, 820, 822, 821, -87, 823, 824, -581, -581, 128, 129, 141, 815, 826, 825, 54, 55, 56, 57, 527, 58, 59, 142, -110, 148, 162, 60, 61, -110, 62, -110, 936, 163, 164, 165, 313, 166, -581, -110, -110, -110, -110, -110, -110, -110, -110, -110, -110, -110, 1293, -84, 953, -78, -73, -72, -71, -70, -69, -68, -67, -66, -65, 742, -46, 63, 64, -18, -575, 1286, 146, 65, 51, 66, 251, 252, 67, 68, 69, 70, 71, 72, 73, 74, 281, 31, 273, 47, 450, 528, 291, -357, 741, 1319, 1320, 529, 744, 850, 935, 151, 295, 1317, 45, 22, 530, 1284, 531, -309, 532, -305, 533, 286, 936, 534, 535, 287, 926, 292, 48, 49, 456, 385, 384, 293, 50, 536, 342, 296, 282, 1057, 376, 348, 850, 299, 300, -575, -575, 1279, 114, 307, 308, 701, 538, 539, 540, 150, 841,-32766, 1288, 1287, 1289, -575, 850, 294, 542, 543, 1402, 1305, 1306, 1307, 1308, 1310, 1302, 1303, 305, -575, 716, -110, -110, 130, 1309, 1304, -110, 593, 1288, 1287, 1289, 306, 13, 673, 75, -110, 1152, 678, 331, 332, 336, -154, -154, -154, -32766, 718, 694, -4, 936, 938, 926, 314, 478, 725, 506, 1324, -154, 705, -154, 679, -154, 695, -154, 974, 1326, -541, 306, 312, 311, 79, 849, 661, 383, 43, 320, 336, 37, 1252, 0, 0, 52, 0, 0, 977, 978, 0, 760, 759, 537,-32766, 0, 0, 0, 706, 0, 0, 912, 973, -110, -110, -110, 35, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, -531, 11, 707, 708, 31, 274, 30, 380, 955, 599, -613, 306, 627, 0, 938, 0, 850, 926, 725, -154, 1317, 1288, 1287, 1289, 44, -612, 749, 290, 750, 1194, 1196, 869, 309, 310, 917, 1018, 995, 1002, 992, 383, -575, 446, 1003, 915, 990, 1123, 304, 1126, 381, 1127, 977, 978, 1124, 1125, 1131, 537, 1279, 1314, 861, 330, 760, 759, 132, 541, 973, -110, -110, -110, 1341, 1359, 1393, 1293, 666, 542, 543, -611, 1305, 1306, 1307, 1308, 1310, 1302, 1303, -585, -584, -583, -582, 21, -525, 1309, 1304, 1, 32, 760, 759, 33, 938,-32766, -278, 77, 725, -4, -16, 1286, 332, 336, 42, -575, -575, 46,-32766,-32766,-32766, 76,-32766, 80,-32766, 81,-32766, 82, 83,-32766, 84, -575, 85, 147,-32766,-32766,-32766, 156,-32766, 160,-32766,-32766, 249, 379, 1286, -575,-32766, 430, 31, 273, 338,-32766,-32766,-32766, 365,-32766, 366, -32766,-32766,-32766, 850, 850,-32766, 367, 1317, 368, 369, -32766,-32766,-32766, 370, 371, 372,-32766,-32766, 373, 374, 375, 377,-32766, 430, 447, 570, 31, 274, -276, -275, 15, 16, 78, 17,-32766, 18, 20, 414, 850, -110, -110, 497, 1317, 1279, -110, 498, 505, 508, 509, 510, 511, 515, 516, -110, 517, 525, 604, 711, 1088, 1084, 1234, 543,-32766, 1305, 1306, 1307, 1308, 1310, 1302, 1303, 1315, 1086, 1083, -50, 1064, 1274, 1309, 1304, 1279, 1060, -280, -102, 14, 19, 306, 24, 77, 79, 415, 303, 413, 332, 336, 336, 618, 624, 543, 652, 1305, 1306, 1307, 1308, 1310, 1302, 1303, 717, 143, 1238, 1292, 1235, 1372, 1309, 1304, 726, 729, 733,-32766, 734, 736, 737, 738, 77, 1286, 419, 739, 743, 332, 336, 728,-32766, -32766,-32766, 746,-32766, 913,-32766, 1397,-32766, 1399, 872, -32766, 871, 967, 1010, 1398,-32766,-32766,-32766, 966,-32766, 964,-32766,-32766, 965, 968, 1286, 1267,-32766, 430, 946, 956, 944,-32766,-32766,-32766, 1000,-32766, 1001,-32766,-32766, -32766, 650, 1396,-32766, 1353, 1342, 1360, 1369,-32766,-32766, -32766, 1318,-32766, 336,-32766,-32766, 936, 0, 1286, 0, -32766, 430, 0, 0, 0,-32766,-32766,-32766, 0,-32766, 0,-32766,-32766,-32766, 0, 0,-32766, 0, 0, 936, 0,-32766,-32766,-32766, 0,-32766, 0,-32766,-32766, 0, 0, 1286, 0,-32766, 430, 0, 0, 0,-32766,-32766, -32766, 0,-32766, 0,-32766,-32766,-32766, 0, 0,-32766, 0, 0, 0, 501,-32766,-32766,-32766, 0,-32766, 0, -32766,-32766, 0, 0, 1286, 606,-32766, 430, 0, 0, 0,-32766,-32766,-32766, 0,-32766, 0,-32766,-32766,-32766, 926, 0,-32766, 2, 0, 0, 0,-32766,-32766,-32766, 0, 0, 0,-32766,-32766, 0, -253, -253, -253,-32766, 430, 0, 383, 926, 0, 0, 0, 0, 0, 0, 0,-32766, 0, 977, 978, 0, 0, 0, 537, -252, -252, -252, 0, 0, 0, 383, 912, 973, -110, -110, -110, 0, 0, 0, 0, 0, 977, 978, 0, 0, 0, 537, 0, 0, 0, 0, 0, 0, 0, 912, 973, -110, -110, -110,-32766, 0, 0, 0, 0, 938, 1286, 0, 0, 725, -253, 0, 0,-32766,-32766,-32766, 0,-32766, 0,-32766, 0,-32766, 0, 0,-32766, 0, 0, 0, 938,-32766,-32766,-32766, 725, -252, 0,-32766, -32766, 0, 0, 0, 0,-32766, 430, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-32766 ); protected array $actionCheck = array( 3, 4, 5, 6, 7, 8, 1, 10, 11, 12, 13, 14, 83, 9, 32, 86, 10, 11, 12, 32, 81, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 10, 11, 12, 9, 38, 39, 31, 9, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 0, 31, 9, 9, 58, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 107, 108, 109, 72, 73, 74, 75, 76, 77, 78, 117, 9, 81, 86, 71, 152, 153, 9, 31, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 107, 163, 109, 127, 128, 129, 130, 15, 132, 133, 134, 135, 136, 137, 1, 9, 140, 141, 142, 143, 144, 145, 146, 151, 148, 149, 138, 139, 1, 168, 164, 155, 156, 157, 9, 159, 9, 3, 4, 5, 6, 7, 8, 167, 10, 11, 12, 13, 14, 117, 167, 119, 120, 121, 122, 123, 124, 125, 126, 10, 11, 12, 45, 46, 47, 48, 49, 50, 51, 52, 53, 167, 38, 39, 142, 167, 10, 11, 12, 9, 31, 1, 33, 34, 35, 36, 37, 38, 39, 1, 167, 9, 58, 10, 11, 12, 83, 31, 166, 33, 34, 35, 36, 37, 1, 1, 72, 73, 74, 75, 76, 77, 78, 1, 31, 81, 33, 34, 35, 36, 32, 9, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 71, 167, 9, 127, 128, 129, 130, 71, 132, 133, 134, 135, 136, 137, 1, 85, 140, 141, 142, 143, 144, 145, 146, 168, 148, 149, 81, 172, 10, 11, 12, 155, 156, 157, 165, 159, 167, 3, 4, 5, 6, 7, 8, 167, 10, 11, 12, 13, 14, 31, 1, 33, 34, 35, 10, 10, 11, 12, 9, 52, 107, 108, 10, 11, 12, 10, 11, 138, 139, 1, 117, 9, 38, 39, 138, 139, 31, 1, 33, 34, 54, 55, 56, 154, 58, 81, 164, 1, 81, 1, 154, 84, 58, 9, 164, 166, 70, 168, 168, 31, 31, 164, 166, 9, 168, 168, 72, 73, 74, 75, 76, 77, 78, 168, 168, 81, 163, 172, 172, 165, 32, 167, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 71, 83, 71, 127, 128, 129, 130, 161, 132, 133, 134, 135, 136, 137, 168, 85, 140, 141, 142, 143, 144, 145, 146, 168, 148, 149, 98, 117, 117, 117, 32, 155, 156, 157, 107, 159, 109, 3, 4, 5, 6, 7, 8, 167, 10, 11, 12, 13, 14, 9, 73, 74, 142, 142, 142, 10, 11, 12, 81, 141, 15, 118, 119, 107, 117, 109, 123, 138, 139, 138, 139, 9, 38, 39, 1, 132, 166, 166, 166, 117, 81, 1, 15, 154, 166, 154, 9, 160, 1, 142, 172, 107, 58, 109, 164, 166, 98, 168, 168, 168, 123, 51, 52, 53, 142, 32, 72, 73, 74, 75, 76, 77, 78, 166, 15, 81, 133, 134, 135, 32, 38, 39, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 85, 81, 161, 127, 128, 129, 130, 85, 132, 133, 134, 135, 136, 137, 85, 9, 140, 141, 142, 143, 144, 145, 146, 9, 148, 149, 15, 10, 11, 12, 9, 155, 156, 157, 9, 159, 3, 4, 5, 6, 7, 8, 15, 10, 11, 12, 13, 14, 31, 102, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 127, 58, 117, 9, 117, 164, 160, 161, 162, 168, 107, 108, 164, 70, 9, 169, 168, 58, 15, 164, 117, 76, 77, 168, 1, 76, 77, 142, 141, 102, 103, 72, 73, 74, 75, 76, 77, 78, 17, 165, 81, 167, 71, 107, 108, 107, 108, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 15, 112, 113, 127, 128, 129, 130, 15, 132, 133, 134, 135, 136, 137, 17, 17, 140, 141, 142, 143, 144, 145, 146, 32, 148, 149, 138, 139, 17, 17, 17, 155, 156, 157, 2, 3, 4, 5, 6, 7, 8, 17, 102, 17, 17, 13, 14, 107, 16, 109, 1, 17, 17, 17, 114, 17, 168, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 1, 32, 39, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 51, 52, 32, 71, 81, 32, 57, 71, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 32, 71, 72, 73, 74, 75, 32, 169, 32, 79, 80, 81, 32, 83, 32, 32, 38, 87, 88, 89, 90, 117, 92, 36, 94, 36, 96, 36, 1, 99, 100, 36, 85, 36, 104, 105, 106, 107, 108, 36, 110, 111, 36, 38, 58, 141, 116, 117, 83, 38, 38, 138, 139, 123, 70, 138, 139, 78, 128, 129, 130, 71, 81, 86, 160, 161, 162, 154, 83, 31, 140, 141, 84, 143, 144, 145, 146, 147, 148, 149, 150, 168, 81, 118, 119, 168, 156, 157, 123, 90, 160, 161, 162, 163, 98, 91, 166, 132, 83, 97, 170, 171, 172, 76, 77, 78, 141, 93, 95, 0, 1, 164, 85, 115, 98, 168, 98, 151, 91, 81, 93, 101, 95, 101, 97, 132, 151, 154, 163, 137, 136, 166, 160, 114, 107, 164, 136, 172, 168, 170, -1, -1, 71, -1, -1, 118, 119, -1, 38, 39, 123, 141, -1, -1, -1, 117, -1, -1, 131, 132, 133, 134, 135, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 154, 154, 141, 142, 71, 72, 154, 154, 159, 158, 166, 163, 158, -1, 164, -1, 83, 85, 168, 169, 87, 160, 161, 162, 164, 166, 164, 166, 164, 60, 61, 164, 138, 139, 164, 164, 164, 164, 164, 107, 71, 109, 164, 164, 164, 164, 114, 164, 154, 164, 118, 119, 164, 164, 164, 123, 123, 165, 165, 168, 38, 39, 168, 131, 132, 133, 134, 135, 165, 165, 165, 1, 165, 140, 141, 166, 143, 144, 145, 146, 147, 148, 149, 166, 166, 166, 166, 155, 166, 156, 157, 166, 166, 38, 39, 166, 164, 75, 167, 166, 168, 169, 32, 81, 171, 172, 166, 138, 139, 166, 88, 89, 90, 166, 92, 166, 94, 166, 96, 166, 166, 99, 166, 154, 166, 166, 104, 105, 106, 166, 75, 166, 110, 111, 166, 168, 81, 168, 116, 117, 71, 72, 166, 88, 89, 90, 166, 92, 166, 94, 128, 96, 83, 83, 99, 166, 87, 166, 166, 104, 105, 106, 166, 166, 166, 110, 111, 166, 166, 166, 166, 116, 117, 166, 166, 71, 72, 167, 167, 167, 167, 159, 167, 128, 167, 167, 167, 83, 118, 119, 167, 87, 123, 123, 167, 167, 167, 167, 167, 167, 167, 167, 132, 167, 167, 167, 167, 167, 167, 167, 141, 141, 143, 144, 145, 146, 147, 148, 149, 167, 167, 167, 32, 167, 167, 156, 157, 123, 167, 167, 167, 167, 167, 163, 167, 166, 166, 169, 167, 167, 171, 172, 172, 167, 167, 141, 167, 143, 144, 145, 146, 147, 148, 149, 167, 32, 167, 167, 167, 167, 156, 157, 168, 168, 168, 75, 168, 168, 168, 168, 166, 81, 169, 168, 168, 171, 172, 168, 88, 89, 90, 169, 92, 169, 94, 169, 96, 169, 169, 99, 169, 169, 169, 169, 104, 105, 106, 169, 75, 169, 110, 111, 169, 169, 81, 169, 116, 117, 169, 169, 169, 88, 89, 90, 169, 92, 169, 94, 128, 96, 169, 169, 99, 169, 169, 169, 169, 104, 105, 106, 171, 75, 172, 110, 111, 1, -1, 81, -1, 116, 117, -1, -1, -1, 88, 89, 90, -1, 92, -1, 94, 128, 96, -1, -1, 99, -1, -1, 1, -1, 104, 105, 106, -1, 75, -1, 110, 111, -1, -1, 81, -1, 116, 117, -1, -1, -1, 88, 89, 90, -1, 92, -1, 94, 128, 96, -1, -1, 99, -1, -1, -1, 103, 104, 105, 106, -1, 75, -1, 110, 111, -1, -1, 81, 82, 116, 117, -1, -1, -1, 88, 89, 90, -1, 92, -1, 94, 128, 96, 85, -1, 99, 166, -1, -1, -1, 104, 105, 106, -1, -1, -1, 110, 111, -1, 101, 102, 103, 116, 117, -1, 107, 85, -1, -1, -1, -1, -1, -1, -1, 128, -1, 118, 119, -1, -1, -1, 123, 101, 102, 103, -1, -1, -1, 107, 131, 132, 133, 134, 135, -1, -1, -1, -1, -1, 118, 119, -1, -1, -1, 123, -1, -1, -1, -1, -1, -1, -1, 131, 132, 133, 134, 135, 75, -1, -1, -1, -1, 164, 81, -1, -1, 168, 169, -1, -1, 88, 89, 90, -1, 92, -1, 94, -1, 96, -1, -1, 99, -1, -1, -1, 164, 104, 105, 106, 168, 169, -1, 110, 111, -1, -1, -1, -1, 116, 117, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 128 ); protected array $actionBase = array( 0, 155, -3, 313, 471, 471, 881, 963, 1365, 1388, 892, 134, 515, -61, 367, 524, 524, 801, 524, 209, 510, 283, 517, 517, 517, 920, 855, 628, 628, 855, 628, 1053, 1053, 1053, 1053, 1086, 1086, 1320, 1320, 1353, 1254, 1221, 1449, 1449, 1449, 1449, 1449, 1287, 1449, 1449, 1449, 1449, 1449, 1287, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 1449, 201, -13, 44, 365, 744, 1102, 1120, 1107, 1121, 1096, 1095, 1103, 1108, 1122, 1183, 1185, 837, 1186, 1187, 1182, 1188, 1110, 938, 1098, 1118, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 323, 482, 334, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 964, 964, 21, 21, 21, 324, 1135, 1100, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 297, 204, 1000, 187, 170, 170, 6, 6, 6, 6, 6, 692, 53, 1101, 819, 819, 138, 138, 138, 138, 542, 14, 347, 355, -41, 348, 232, 384, 384, 487, 487, 554, 554, 349, 349, 554, 554, 554, 399, 399, 399, 399, 208, 215, 366, 364, -7, 864, 224, 224, 224, 224, 864, 864, 864, 864, 829, 1190, 864, 1011, 1027, 864, 864, 368, 767, 767, 925, 305, 305, 305, 767, 421, -71, -71, 421, 380, -71, 225, 286, 556, 847, 572, 543, 556, 640, 771, 233, 148, 826, 605, 826, 1094, 831, 831, 802, 792, 921, 1140, 1123, 874, 1176, 876, 1178, 420, 9, 791, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1191, 519, 1094, 436, 1191, 1191, 1191, 519, 519, 519, 519, 519, 519, 519, 519, 805, 519, 519, 641, 436, 614, 618, 436, 860, 519, 877, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, -18, 201, 201, -13, 292, 292, 201, 216, 5, 292, 292, 292, 292, 201, 201, 201, 201, 605, 840, 882, 607, 435, 885, 29, 840, 840, 840, 4, 113, 25, 841, 843, 393, 835, 835, 835, 869, 956, 956, 835, 839, 835, 869, 835, 835, 956, 956, 879, 956, 146, 609, 373, 514, 616, 956, 272, 835, 835, 835, 835, 854, 956, 45, 68, 620, 835, 203, 191, 835, 835, 854, 848, 828, 846, 956, 956, 956, 854, 499, 846, 846, 846, 893, 895, 873, 822, 363, 341, 674, 127, 783, 822, 822, 835, 601, 873, 822, 873, 822, 880, 822, 822, 822, 873, 822, 839, 477, 822, 779, 786, 663, 74, 822, 51, 978, 980, 743, 982, 971, 984, 1038, 985, 987, 1125, 953, 999, 974, 989, 1039, 960, 957, 836, 763, 764, 878, 827, 951, 838, 838, 838, 948, 949, 838, 838, 838, 838, 838, 838, 838, 838, 763, 923, 884, 853, 1013, 765, 776, 1069, 820, 1145, 823, 1011, 978, 987, 789, 974, 989, 960, 957, 800, 799, 797, 798, 796, 795, 793, 794, 808, 1071, 1072, 990, 825, 778, 1049, 1020, 1143, 922, 1022, 1023, 1050, 1073, 898, 1083, 1147, 844, 1149, 1150, 924, 1028, 1126, 838, 940, 875, 934, 1027, 950, 763, 935, 1084, 1085, 1043, 824, 1054, 1058, 998, 870, 842, 936, 1152, 1029, 1032, 1033, 1127, 1129, 891, 1044, 962, 1059, 872, 1099, 1060, 1061, 1062, 1063, 1130, 1153, 1131, 890, 1132, 901, 858, 1041, 856, 1154, 504, 851, 857, 866, 1035, 536, 1007, 1136, 1134, 1155, 1064, 1065, 1067, 1159, 1161, 994, 902, 1046, 867, 1048, 1042, 903, 904, 606, 865, 1087, 845, 849, 859, 622, 672, 1164, 1165, 1167, 996, 830, 833, 905, 909, 1088, 832, 1092, 1170, 737, 910, 1171, 1070, 787, 788, 690, 750, 749, 790, 868, 1137, 883, 852, 850, 1034, 788, 834, 911, 1172, 912, 914, 916, 1068, 919, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 784, 784, 784, 784, 784, 784, 784, 784, 784, 628, 628, 628, 628, 784, 784, 784, 784, 784, 784, 784, 628, 784, 784, 784, 628, 628, 0, 0, 628, 0, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, 758, 758, 612, 612, 612, 612, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 612, 612, 0, 612, 612, 612, 612, 612, 612, 612, 612, 879, 758, 758, 758, 758, 305, 305, 305, 305, -96, -96, 758, 758, 380, 758, 380, 758, 758, 305, 305, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 0, 0, 0, 436, -71, 758, 839, 839, 839, 839, 758, 758, 758, 758, -71, -71, 758, 414, 414, 758, 758, 0, 0, 0, 0, 0, 0, 0, 0, 436, 0, 0, 436, 0, 0, 839, 839, 758, 380, 879, 328, 758, 0, 0, 0, 0, 436, 839, 436, 519, -71, -71, 519, 519, 292, 201, 328, 596, 596, 596, 596, 0, 0, 605, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 839, 0, 879, 0, 839, 839, 839, 0, 0, 0, 0, 0, 0, 0, 0, 956, 0, 0, 0, 0, 0, 0, 0, 839, 0, 956, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 838, 870, 0, 0, 870, 0, 838, 838, 838, 0, 0, 0, 865, 832 ); protected array $actionDefault = array( 3,32767,32767,32767, 102, 102,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767, 100, 32767, 631, 631, 631, 631,32767,32767, 257, 102,32767, 32767, 500, 415, 415, 415,32767,32767,32767, 573, 573, 573, 573, 573, 17,32767,32767,32767,32767,32767,32767, 32767, 500,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767, 36, 7, 8, 10, 11, 49, 338, 100,32767,32767,32767,32767,32767,32767,32767,32767, 102, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767, 624,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767, 403, 494, 504, 482, 483, 485, 486, 414, 574, 630, 344, 627, 342, 413, 146, 354, 343, 245, 261, 505, 262, 506, 509, 510, 218, 400, 150, 151, 446, 501, 448, 499, 503, 447, 420, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 418, 419, 502,32767,32767, 479, 478, 477, 444,32767, 32767,32767,32767,32767,32767,32767,32767, 102,32767, 445, 449, 417, 452, 450, 451, 468, 469, 466, 467, 470, 32767, 323,32767,32767,32767, 471, 472, 473, 474, 381, 379,32767,32767, 111, 323, 111,32767,32767, 459, 460, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767, 517, 567, 476,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767, 102,32767,32767, 32767, 100, 569, 441, 443, 537, 454, 455, 453, 421, 32767, 542,32767, 102,32767, 544,32767,32767,32767,32767, 32767,32767,32767, 568,32767, 575, 575,32767, 530, 100, 196,32767, 543, 196, 196,32767,32767,32767,32767,32767, 32767,32767,32767, 638, 530, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,32767, 196, 110,32767, 32767,32767, 100, 196, 196, 196, 196, 196, 196, 196, 196, 545, 196, 196, 191,32767, 271, 273, 102, 592, 196, 547,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 530, 464, 139,32767, 532, 139, 575, 456, 457, 458, 575, 575, 575, 319, 296,32767,32767,32767,32767,32767, 545, 545, 100, 100, 100, 100,32767,32767,32767,32767, 111, 516, 99, 99, 99, 99, 99, 103, 101,32767, 32767,32767,32767, 226,32767, 101, 101, 99,32767, 101, 101,32767,32767, 226, 228, 215, 230,32767, 596, 597, 226, 101, 230, 230, 230, 250, 250, 519, 325, 101, 99, 101, 101, 198, 325, 325,32767, 101, 519, 325, 519, 325, 200, 325, 325, 325, 519, 325,32767, 101, 325, 217, 403, 99, 99, 325,32767,32767,32767, 532, 32767,32767,32767,32767,32767,32767,32767, 225,32767,32767, 32767,32767,32767,32767,32767,32767, 562,32767, 580, 594, 462, 463, 465, 579, 577, 487, 488, 489, 490, 491, 492, 493, 496, 626,32767, 536,32767,32767,32767, 353, 32767, 636,32767,32767,32767, 9, 74, 525, 42, 43, 51, 57, 551, 552, 553, 554, 548, 549, 555, 550, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767, 637,32767, 575,32767, 32767,32767,32767, 461, 557, 602,32767,32767, 576, 629, 32767,32767,32767,32767,32767,32767,32767,32767, 139,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767, 562, 32767, 137,32767,32767,32767,32767,32767,32767,32767,32767, 558,32767,32767,32767, 575,32767,32767,32767,32767, 321, 318,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767, 575,32767,32767, 32767,32767,32767, 298,32767, 315,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767, 399, 532, 301, 303, 304,32767, 32767,32767,32767, 375,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767, 153, 153, 3, 3, 356, 153, 153, 153, 356, 356, 153, 356, 356, 356, 153, 153, 153, 153, 153, 153, 283, 186, 265, 268, 250, 250, 153, 367, 153 ); protected array $goto = array( 202, 169, 202, 202, 202, 1056, 842, 712, 359, 670, 671, 598, 688, 689, 690, 748, 653, 655, 591, 929, 675, 930, 1090, 721, 699, 702, 1028, 710, 719, 1024, 171, 171, 171, 171, 226, 203, 199, 199, 181, 183, 221, 199, 199, 199, 199, 199, 1180, 200, 200, 200, 200, 200, 1180, 193, 194, 195, 196, 197, 198, 223, 221, 224, 550, 551, 431, 552, 555, 556, 557, 558, 559, 560, 561, 562, 172, 173, 174, 201, 175, 176, 177, 170, 178, 179, 180, 182, 220, 222, 225, 245, 248, 259, 260, 262, 263, 264, 265, 266, 267, 268, 269, 275, 276, 277, 278, 288, 289, 326, 327, 328, 437, 438, 439, 613, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 184, 242, 185, 194, 195, 196, 197, 198, 223, 204, 205, 206, 207, 246, 186, 187, 208, 188, 209, 205, 189, 247, 204, 168, 210, 211, 190, 212, 213, 214, 191, 215, 216, 192, 217, 218, 219, 285, 283, 285, 285, 870, 1089, 1091, 1094, 615, 255, 255, 255, 255, 255, 441, 677, 614, 1130, 884, 867, 436, 329, 323, 324, 345, 608, 440, 346, 442, 654, 724, 492, 521, 715, 896, 1128, 993, 883, 494, 253, 253, 253, 253, 250, 256, 489, 1361, 1362, 1386, 1386, 925, 920, 921, 934, 876, 922, 873, 923, 924, 874, 877, 363, 928, 881, 480, 480, 868, 880, 1386, 848, 474, 363, 363, 480, 1117, 1112, 1113, 1114, 1229, 351, 362, 362, 362, 362, 1389, 1389, 429, 363, 363, 1017, 902, 363, 989, 1403, 747, 360, 361, 566, 1026, 1021, 1056, 1285, 1285, 1285, 569, 352, 351, 363, 363, 605, 1056, 1285, 848, 1056, 848, 1056, 1056, 1137, 1138, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 357, 1261, 962, 637, 674, 1285, 1262, 1265, 963, 1266, 1285, 1285, 1285, 1285, 1376, 435, 1285, 628, 402, 1285, 1285, 1368, 1368, 1368, 1368, 1347, 574, 567, 1062, 1061, 1059, 1059, 958, 958, 697, 970, 1014, 942, 1051, 1067, 1068, 943, 565, 565, 565, 603, 513, 522, 514, 863, 676, 863, 565, 709, 520, 1176, 318, 567, 574, 600, 601, 319, 611, 617, 844, 633, 634, 1080, 8, 709, 9, 449, 709, 28, 1065, 1066, 467, 335, 316, 569, 698, 987, 987, 987, 987, 1363, 1364, 467, 639, 639, 981, 988, 609, 631, 1316, 1316, 1316, 1316, 1316, 1316, 1316, 1316, 1316, 1316, 1335, 1335, 863, 469, 682, 469, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 1335, 347, 258, 258, 626, 640, 643, 644, 645, 646, 667, 668, 669, 723, 632, 460, 860, 460, 460, 460, 1358, 1358, 1358, 553, 553, 1278, 985, 420, 720, 553, 1358, 553, 553, 553, 553, 553, 553, 553, 553, 451, 889, 568, 595, 568, 647, 649, 651, 568, 976, 595, 411, 405, 473, 886, 1276, 1370, 1370, 1370, 1370, 909, 866, 909, 909, 1036, 483, 612, 484, 485, 751, 563, 563, 563, 563, 894, 619, 1101, 1394, 1395, 412, 1332, 1332, 898, 490, 1151, 1354, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 279, 1105, 334, 334, 334, 998, 892, 0, 1280, 1047, 0, 0, 863, 0, 0, 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, 0, 0, 460, 1103, 554, 554, 0, 1356, 1356, 1103, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 621, 622, 417, 418, 947, 1166, 0, 686, 0, 687, 0, 422, 423, 424, 0, 700, 1033, 0, 425, 1281, 1282, 0, 1268, 355, 888, 0, 680, 1012, 858, 0, 0, 0, 882, 443, 0, 1268, 0, 897, 885, 1100, 1104, 0, 0, 0, 1275, 0, 443, 0, 1283, 1344, 1345, 996, 0, 0, 1063, 1063, 0, 0, 0, 681, 1074, 1070, 1071, 404, 407, 616, 620, 0, 0, 0, 0, 0, 0, 0, 986, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1149, 901, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1031, 1031 ); protected array $gotoCheck = array( 42, 42, 42, 42, 42, 73, 6, 73, 97, 86, 86, 48, 86, 86, 86, 48, 48, 48, 127, 65, 48, 65, 131, 9, 48, 48, 48, 48, 48, 48, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 23, 23, 23, 23, 15, 130, 130, 130, 134, 5, 5, 5, 5, 5, 66, 66, 8, 8, 35, 26, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 8, 84, 8, 8, 35, 8, 49, 35, 84, 5, 5, 5, 5, 5, 5, 185, 185, 185, 191, 191, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 157, 157, 27, 15, 191, 12, 159, 14, 14, 157, 15, 15, 15, 15, 159, 177, 24, 24, 24, 24, 191, 191, 43, 14, 14, 50, 45, 14, 50, 14, 50, 97, 97, 50, 50, 50, 73, 73, 73, 73, 14, 177, 177, 14, 14, 181, 73, 73, 12, 73, 12, 73, 73, 148, 148, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 188, 79, 79, 56, 56, 73, 79, 79, 79, 79, 73, 73, 73, 73, 190, 13, 73, 13, 62, 73, 73, 9, 9, 9, 9, 14, 76, 76, 119, 119, 89, 89, 9, 9, 89, 89, 103, 73, 89, 89, 89, 73, 19, 19, 19, 104, 163, 14, 163, 22, 64, 22, 19, 7, 163, 158, 76, 76, 76, 76, 76, 76, 76, 76, 7, 76, 76, 115, 46, 7, 46, 113, 7, 76, 120, 120, 19, 178, 178, 14, 117, 19, 19, 19, 19, 187, 187, 19, 108, 108, 19, 19, 2, 2, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 179, 179, 22, 83, 121, 83, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 29, 5, 5, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 80, 23, 18, 23, 23, 23, 134, 134, 134, 165, 165, 14, 93, 93, 93, 165, 134, 165, 165, 165, 165, 165, 165, 165, 165, 83, 39, 9, 9, 9, 85, 85, 85, 9, 92, 9, 28, 9, 9, 37, 169, 134, 134, 134, 134, 25, 25, 25, 25, 110, 9, 9, 9, 9, 99, 107, 107, 107, 107, 9, 107, 133, 9, 9, 31, 180, 180, 41, 160, 151, 134, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 24, 136, 24, 24, 24, 96, 9, -1, 20, 114, -1, -1, 22, -1, -1, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, -1, -1, 23, 134, 182, 182, -1, 134, 134, 134, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 17, 17, 82, 82, 17, 17, -1, 82, -1, 82, -1, 82, 82, 82, -1, 82, 17, -1, 82, 20, 20, -1, 20, 82, 17, -1, 17, 17, 20, -1, -1, -1, 17, 118, -1, 20, -1, 16, 16, 16, 16, -1, -1, -1, 17, -1, 118, -1, 20, 20, 20, 16, -1, -1, 118, 118, -1, -1, -1, 118, 118, 118, 118, 59, 59, 59, 59, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 107, 107 ); protected array $gotoBase = array( 0, 0, -339, 0, 0, 174, -7, 339, 171, 10, 0, 0, -69, -36, -78, -186, 130, 81, 114, 66, 117, 0, 62, 160, 240, 468, 178, 225, 118, 112, 0, 45, 0, 0, 0, -195, 0, 119, 0, 122, 0, 44, -1, 226, 0, 227, -387, 0, -715, 182, 241, 0, 0, 0, 0, 0, 256, 0, 0, 570, 0, 0, 269, 0, 102, 3, -63, 0, 0, 0, 0, 0, 0, -5, 0, 0, -31, 0, 0, -120, 110, 53, 54, 120, -286, -33, -724, 0, 0, 40, 0, 0, 124, 129, 0, 0, 61, -488, 0, 67, 0, 0, 0, 294, 295, 0, 0, 453, 141, 0, 100, 0, 0, 83, -3, 82, 0, 86, 318, 38, 78, 107, 0, 0, 0, 0, 0, 16, 0, 0, 168, 20, 0, 108, 163, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 43, 0, 0, 0, 0, 0, 193, 101, -38, 46, 0, 0, -166, 0, 195, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, -60, 42, 157, 251, 243, 297, 0, 0, -97, 0, 1, 263, 0, 276, -101, 0, 0 ); protected array $gotoDefault = array( -32768, 526, 755, 7, 756, 951, 831, 840, 590, 544, 722, 356, 641, 432, 1352, 927, 1165, 610, 859, 1294, 1300, 468, 862, 340, 745, 939, 910, 911, 408, 395, 875, 406, 665, 642, 507, 895, 464, 887, 499, 890, 463, 899, 167, 428, 524, 903, 6, 906, 572, 937, 991, 396, 914, 397, 693, 916, 594, 918, 919, 403, 409, 410, 1170, 602, 638, 931, 261, 596, 932, 394, 933, 941, 399, 401, 703, 479, 518, 512, 421, 1132, 597, 625, 662, 457, 486, 636, 648, 635, 493, 444, 426, 339, 975, 983, 500, 477, 997, 358, 1005, 753, 1178, 656, 502, 1013, 657, 1020, 1023, 545, 546, 491, 1035, 271, 1038, 503, 1048, 26, 683, 1053, 1054, 684, 658, 1076, 659, 685, 660, 1078, 476, 592, 1179, 475, 1093, 1099, 465, 1102, 1340, 466, 1106, 270, 1109, 284, 427, 445, 1115, 1116, 12, 1122, 713, 714, 25, 280, 523, 1150, 704,-32768,-32768,-32768,-32768, 462, 1177, 461, 1249, 1251, 573, 504, 1269, 301, 1272, 696, 519, 1277, 458, 1343, 459, 547, 487, 325, 548, 1387, 315, 343, 322, 564, 302, 344, 549, 488, 1349, 1357, 341, 34, 1377, 1388, 607, 630 ); protected array $ruleToNonTerminal = array( 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18, 21, 21, 22, 23, 23, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 30, 30, 32, 34, 34, 28, 36, 36, 33, 38, 38, 35, 35, 37, 37, 39, 39, 31, 40, 40, 41, 43, 44, 44, 45, 45, 46, 46, 48, 47, 47, 47, 47, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 25, 25, 50, 69, 69, 72, 72, 71, 70, 70, 63, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 80, 80, 26, 26, 27, 27, 27, 27, 27, 88, 88, 90, 90, 83, 83, 91, 91, 92, 92, 92, 84, 84, 87, 87, 85, 85, 93, 94, 94, 57, 57, 65, 65, 68, 68, 68, 67, 95, 95, 96, 58, 58, 58, 58, 97, 97, 98, 98, 99, 99, 100, 101, 101, 102, 102, 103, 103, 55, 55, 51, 51, 105, 53, 53, 106, 52, 52, 54, 54, 64, 64, 64, 64, 81, 81, 109, 109, 111, 111, 112, 112, 112, 112, 112, 112, 112, 112, 110, 110, 110, 115, 115, 115, 115, 89, 89, 118, 118, 118, 119, 119, 116, 116, 120, 120, 122, 122, 123, 123, 117, 124, 124, 121, 125, 125, 125, 125, 113, 113, 82, 82, 82, 20, 20, 20, 128, 128, 128, 128, 129, 129, 129, 127, 126, 126, 131, 131, 131, 130, 130, 60, 132, 132, 133, 61, 135, 135, 136, 136, 137, 137, 86, 138, 138, 138, 138, 138, 138, 138, 143, 143, 144, 144, 145, 145, 145, 145, 145, 146, 147, 147, 142, 142, 139, 139, 141, 141, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 140, 150, 150, 152, 151, 151, 153, 153, 114, 154, 154, 156, 156, 156, 155, 155, 62, 104, 157, 157, 56, 56, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 164, 165, 165, 166, 158, 158, 163, 163, 167, 168, 168, 169, 170, 171, 171, 171, 171, 19, 19, 73, 73, 73, 73, 159, 159, 159, 159, 173, 173, 162, 162, 162, 160, 160, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 180, 180, 180, 108, 182, 182, 182, 182, 161, 161, 161, 161, 161, 161, 161, 161, 59, 59, 176, 176, 176, 176, 176, 183, 183, 172, 172, 172, 172, 184, 184, 184, 184, 184, 184, 74, 74, 66, 66, 66, 66, 134, 134, 134, 134, 187, 186, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 185, 185, 185, 185, 107, 181, 189, 189, 188, 188, 190, 190, 190, 190, 190, 190, 190, 190, 178, 178, 178, 178, 177, 192, 191, 191, 191, 191, 191, 191, 191, 191, 193, 193, 193, 193 ); protected array $ruleToLength = array( 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 2, 1, 3, 4, 1, 2, 0, 1, 1, 1, 1, 4, 3, 5, 4, 3, 4, 1, 3, 4, 1, 1, 8, 7, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 3, 1, 3, 1, 2, 2, 3, 1, 3, 2, 3, 1, 3, 3, 2, 0, 1, 1, 1, 1, 1, 3, 7, 10, 5, 7, 9, 5, 3, 3, 3, 3, 3, 3, 1, 2, 5, 7, 9, 6, 5, 6, 3, 2, 1, 1, 1, 1, 0, 2, 1, 3, 8, 0, 4, 2, 1, 3, 0, 1, 0, 1, 0, 1, 3, 1, 1, 1, 1, 1, 8, 9, 7, 8, 7, 6, 8, 0, 2, 0, 2, 1, 2, 1, 2, 1, 1, 1, 0, 2, 0, 2, 0, 2, 2, 1, 3, 1, 4, 1, 4, 1, 1, 4, 2, 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, 1, 7, 0, 2, 1, 3, 3, 4, 1, 4, 0, 2, 5, 0, 2, 6, 0, 2, 0, 3, 1, 2, 1, 1, 2, 0, 1, 3, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 7, 9, 6, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, 1, 1, 2, 1, 1, 0, 1, 0, 2, 2, 2, 4, 3, 2, 4, 4, 3, 3, 1, 3, 1, 1, 3, 2, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 3, 2, 0, 1, 5, 5, 6, 10, 3, 5, 1, 1, 3, 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, 1, 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 3, 1, 1, 3, 0, 2, 0, 5, 8, 1, 3, 3, 0, 2, 2, 2, 3, 1, 0, 1, 1, 3, 3, 3, 4, 4, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 2, 1, 2, 4, 2, 2, 8, 9, 8, 9, 9, 10, 9, 10, 8, 3, 2, 2, 1, 1, 0, 4, 2, 1, 3, 2, 1, 2, 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 3, 3, 4, 1, 1, 3, 1, 1, 1, 1, 1, 3, 2, 3, 0, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 4, 4, 1, 4, 4, 0, 1, 1, 1, 3, 3, 1, 4, 2, 2, 1, 3, 1, 4, 4, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, 1, 4, 1, 1, 1, 3, 1, 1, 2, 1, 3, 4, 3, 2, 0, 2, 2, 1, 2, 1, 1, 1, 4, 3, 3, 3, 3, 6, 3, 1, 1, 2, 1 ); protected function initReduceCallbacks(): void { $this->reduceCallbacks = [ 0 => null, 1 => static function ($self, $stackPos) { $self->semValue = $self->handleNamespaces($self->semStack[$stackPos-(1-1)]); }, 2 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(2-2)] !== null) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; } $self->semValue = $self->semStack[$stackPos-(2-1)];; }, 3 => static function ($self, $stackPos) { $self->semValue = array(); }, 4 => static function ($self, $stackPos) { $nop = $self->maybeCreateZeroLengthNop($self->tokenPos);; if ($nop !== null) { $self->semStack[$stackPos-(1-1)][] = $nop; } $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 5 => null, 6 => null, 7 => null, 8 => null, 9 => null, 10 => null, 11 => null, 12 => null, 13 => null, 14 => null, 15 => null, 16 => null, 17 => null, 18 => null, 19 => null, 20 => null, 21 => null, 22 => null, 23 => null, 24 => null, 25 => null, 26 => null, 27 => null, 28 => null, 29 => null, 30 => null, 31 => null, 32 => null, 33 => null, 34 => null, 35 => null, 36 => null, 37 => null, 38 => null, 39 => null, 40 => null, 41 => null, 42 => null, 43 => null, 44 => null, 45 => null, 46 => null, 47 => null, 48 => null, 49 => null, 50 => null, 51 => null, 52 => null, 53 => null, 54 => null, 55 => null, 56 => null, 57 => null, 58 => null, 59 => null, 60 => null, 61 => null, 62 => null, 63 => null, 64 => null, 65 => null, 66 => null, 67 => null, 68 => null, 69 => null, 70 => null, 71 => null, 72 => null, 73 => null, 74 => null, 75 => null, 76 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; if ($self->semValue === "emitError(new Error('Cannot use "getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]))); }, 77 => null, 78 => null, 79 => null, 80 => null, 81 => null, 82 => null, 83 => null, 84 => null, 85 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 86 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 87 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 88 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 89 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 90 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 91 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 92 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 93 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 94 => null, 95 => static function ($self, $stackPos) { $self->semValue = new Name(substr($self->semStack[$stackPos-(1-1)], 1), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 96 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable(substr($self->semStack[$stackPos-(1-1)], 1), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 97 => static function ($self, $stackPos) { /* nothing */ }, 98 => static function ($self, $stackPos) { /* nothing */ }, 99 => static function ($self, $stackPos) { /* nothing */ }, 100 => static function ($self, $stackPos) { $self->emitError(new Error('A trailing comma is not allowed here', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]))); }, 101 => null, 102 => null, 103 => static function ($self, $stackPos) { $self->semValue = new Node\Attribute($self->semStack[$stackPos-(1-1)], [], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 104 => static function ($self, $stackPos) { $self->semValue = new Node\Attribute($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 105 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 106 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 107 => static function ($self, $stackPos) { $self->semValue = new Node\AttributeGroup($self->semStack[$stackPos-(4-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 108 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 109 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 110 => static function ($self, $stackPos) { $self->semValue = []; }, 111 => null, 112 => null, 113 => null, 114 => null, 115 => static function ($self, $stackPos) { $self->semValue = new Stmt\HaltCompiler($self->handleHaltCompiler(), $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 116 => static function ($self, $stackPos) { $self->semValue = new Stmt\Namespace_($self->semStack[$stackPos-(3-2)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); $self->checkNamespace($self->semValue); }, 117 => static function ($self, $stackPos) { $self->semValue = new Stmt\Namespace_($self->semStack[$stackPos-(5-2)], $self->semStack[$stackPos-(5-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $self->checkNamespace($self->semValue); }, 118 => static function ($self, $stackPos) { $self->semValue = new Stmt\Namespace_(null, $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $self->checkNamespace($self->semValue); }, 119 => static function ($self, $stackPos) { $self->semValue = new Stmt\Use_($self->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 120 => static function ($self, $stackPos) { $self->semValue = new Stmt\Use_($self->semStack[$stackPos-(4-3)], $self->semStack[$stackPos-(4-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 121 => null, 122 => static function ($self, $stackPos) { $self->semValue = new Stmt\Const_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]), []); }, 123 => static function ($self, $stackPos) { $self->semValue = new Stmt\Const_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(4-1)]); $self->checkConstantAttributes($self->semValue); }, 124 => static function ($self, $stackPos) { $self->semValue = Stmt\Use_::TYPE_FUNCTION; }, 125 => static function ($self, $stackPos) { $self->semValue = Stmt\Use_::TYPE_CONSTANT; }, 126 => static function ($self, $stackPos) { $self->semValue = new Stmt\GroupUse($self->semStack[$stackPos-(8-3)], $self->semStack[$stackPos-(8-6)], $self->semStack[$stackPos-(8-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 127 => static function ($self, $stackPos) { $self->semValue = new Stmt\GroupUse($self->semStack[$stackPos-(7-2)], $self->semStack[$stackPos-(7-5)], Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 128 => null, 129 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 130 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 131 => null, 132 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 133 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 134 => null, 135 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 136 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 137 => static function ($self, $stackPos) { $self->semValue = new Node\UseItem($self->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->checkUseUse($self->semValue, $stackPos-(1-1)); }, 138 => static function ($self, $stackPos) { $self->semValue = new Node\UseItem($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->checkUseUse($self->semValue, $stackPos-(3-3)); }, 139 => static function ($self, $stackPos) { $self->semValue = new Node\UseItem($self->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->checkUseUse($self->semValue, $stackPos-(1-1)); }, 140 => static function ($self, $stackPos) { $self->semValue = new Node\UseItem($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->checkUseUse($self->semValue, $stackPos-(3-3)); }, 141 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; $self->semValue->type = Stmt\Use_::TYPE_NORMAL; }, 142 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; $self->semValue->type = $self->semStack[$stackPos-(2-1)]; }, 143 => null, 144 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 145 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 146 => static function ($self, $stackPos) { $self->semValue = new Node\Const_($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 147 => null, 148 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 149 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 150 => static function ($self, $stackPos) { $self->semValue = new Node\Const_(new Node\Identifier($self->semStack[$stackPos-(3-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos-(3-1)])), $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 151 => static function ($self, $stackPos) { $self->semValue = new Node\Const_(new Node\Identifier($self->semStack[$stackPos-(3-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos-(3-1)])), $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 152 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(2-2)] !== null) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; } $self->semValue = $self->semStack[$stackPos-(2-1)];; }, 153 => static function ($self, $stackPos) { $self->semValue = array(); }, 154 => static function ($self, $stackPos) { $nop = $self->maybeCreateZeroLengthNop($self->tokenPos);; if ($nop !== null) { $self->semStack[$stackPos-(1-1)][] = $nop; } $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 155 => null, 156 => null, 157 => null, 158 => static function ($self, $stackPos) { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 159 => static function ($self, $stackPos) { $self->semValue = new Stmt\Block($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 160 => static function ($self, $stackPos) { $self->semValue = new Stmt\If_($self->semStack[$stackPos-(7-3)], ['stmts' => $self->semStack[$stackPos-(7-5)], 'elseifs' => $self->semStack[$stackPos-(7-6)], 'else' => $self->semStack[$stackPos-(7-7)]], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 161 => static function ($self, $stackPos) { $self->semValue = new Stmt\If_($self->semStack[$stackPos-(10-3)], ['stmts' => $self->semStack[$stackPos-(10-6)], 'elseifs' => $self->semStack[$stackPos-(10-7)], 'else' => $self->semStack[$stackPos-(10-8)]], $self->getAttributes($self->tokenStartStack[$stackPos-(10-1)], $self->tokenEndStack[$stackPos])); }, 162 => static function ($self, $stackPos) { $self->semValue = new Stmt\While_($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 163 => static function ($self, $stackPos) { $self->semValue = new Stmt\Do_($self->semStack[$stackPos-(7-5)], $self->semStack[$stackPos-(7-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 164 => static function ($self, $stackPos) { $self->semValue = new Stmt\For_(['init' => $self->semStack[$stackPos-(9-3)], 'cond' => $self->semStack[$stackPos-(9-5)], 'loop' => $self->semStack[$stackPos-(9-7)], 'stmts' => $self->semStack[$stackPos-(9-9)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 165 => static function ($self, $stackPos) { $self->semValue = new Stmt\Switch_($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 166 => static function ($self, $stackPos) { $self->semValue = new Stmt\Break_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 167 => static function ($self, $stackPos) { $self->semValue = new Stmt\Continue_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 168 => static function ($self, $stackPos) { $self->semValue = new Stmt\Return_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 169 => static function ($self, $stackPos) { $self->semValue = new Stmt\Global_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 170 => static function ($self, $stackPos) { $self->semValue = new Stmt\Static_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 171 => static function ($self, $stackPos) { $self->semValue = new Stmt\Echo_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 172 => static function ($self, $stackPos) { $self->semValue = new Stmt\InlineHTML($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('hasLeadingNewline', $self->inlineHtmlHasLeadingNewline($stackPos-(1-1))); }, 173 => static function ($self, $stackPos) { $self->semValue = new Stmt\Expression($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 174 => static function ($self, $stackPos) { $self->semValue = new Stmt\Unset_($self->semStack[$stackPos-(5-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 175 => static function ($self, $stackPos) { $self->semValue = new Stmt\Foreach_($self->semStack[$stackPos-(7-3)], $self->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $self->semStack[$stackPos-(7-5)][1], 'stmts' => $self->semStack[$stackPos-(7-7)]], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 176 => static function ($self, $stackPos) { $self->semValue = new Stmt\Foreach_($self->semStack[$stackPos-(9-3)], $self->semStack[$stackPos-(9-7)][0], ['keyVar' => $self->semStack[$stackPos-(9-5)], 'byRef' => $self->semStack[$stackPos-(9-7)][1], 'stmts' => $self->semStack[$stackPos-(9-9)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 177 => static function ($self, $stackPos) { $self->semValue = new Stmt\Foreach_($self->semStack[$stackPos-(6-3)], new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(6-4)], $self->tokenEndStack[$stackPos-(6-4)])), ['stmts' => $self->semStack[$stackPos-(6-6)]], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); }, 178 => static function ($self, $stackPos) { $self->semValue = new Stmt\Declare_($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 179 => static function ($self, $stackPos) { $self->semValue = new Stmt\TryCatch($self->semStack[$stackPos-(6-3)], $self->semStack[$stackPos-(6-5)], $self->semStack[$stackPos-(6-6)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); $self->checkTryCatch($self->semValue); }, 180 => static function ($self, $stackPos) { $self->semValue = new Stmt\Goto_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 181 => static function ($self, $stackPos) { $self->semValue = new Stmt\Label($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 182 => static function ($self, $stackPos) { $self->semValue = null; /* means: no statement */ }, 183 => null, 184 => static function ($self, $stackPos) { $self->semValue = $self->maybeCreateNop($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]); }, 185 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(1-1)] instanceof Stmt\Block) { $self->semValue = $self->semStack[$stackPos-(1-1)]->stmts; } else if ($self->semStack[$stackPos-(1-1)] === null) { $self->semValue = []; } else { $self->semValue = [$self->semStack[$stackPos-(1-1)]]; }; }, 186 => static function ($self, $stackPos) { $self->semValue = array(); }, 187 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 188 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 189 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 190 => static function ($self, $stackPos) { $self->semValue = new Stmt\Catch_($self->semStack[$stackPos-(8-3)], $self->semStack[$stackPos-(8-4)], $self->semStack[$stackPos-(8-7)], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 191 => static function ($self, $stackPos) { $self->semValue = null; }, 192 => static function ($self, $stackPos) { $self->semValue = new Stmt\Finally_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 193 => null, 194 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 195 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 196 => static function ($self, $stackPos) { $self->semValue = false; }, 197 => static function ($self, $stackPos) { $self->semValue = true; }, 198 => static function ($self, $stackPos) { $self->semValue = false; }, 199 => static function ($self, $stackPos) { $self->semValue = true; }, 200 => static function ($self, $stackPos) { $self->semValue = false; }, 201 => static function ($self, $stackPos) { $self->semValue = true; }, 202 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 203 => static function ($self, $stackPos) { $self->semValue = []; }, 204 => null, 205 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 206 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 207 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 208 => static function ($self, $stackPos) { $self->semValue = new Stmt\Function_($self->semStack[$stackPos-(8-3)], ['byRef' => $self->semStack[$stackPos-(8-2)], 'params' => $self->semStack[$stackPos-(8-5)], 'returnType' => $self->semStack[$stackPos-(8-7)], 'stmts' => $self->semStack[$stackPos-(8-8)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 209 => static function ($self, $stackPos) { $self->semValue = new Stmt\Function_($self->semStack[$stackPos-(9-4)], ['byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-6)], 'returnType' => $self->semStack[$stackPos-(9-8)], 'stmts' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => $self->semStack[$stackPos-(9-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 210 => static function ($self, $stackPos) { $self->semValue = new Stmt\Class_($self->semStack[$stackPos-(7-2)], ['type' => $self->semStack[$stackPos-(7-1)], 'extends' => $self->semStack[$stackPos-(7-3)], 'implements' => $self->semStack[$stackPos-(7-4)], 'stmts' => $self->semStack[$stackPos-(7-6)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); $self->checkClass($self->semValue, $stackPos-(7-2)); }, 211 => static function ($self, $stackPos) { $self->semValue = new Stmt\Class_($self->semStack[$stackPos-(8-3)], ['type' => $self->semStack[$stackPos-(8-2)], 'extends' => $self->semStack[$stackPos-(8-4)], 'implements' => $self->semStack[$stackPos-(8-5)], 'stmts' => $self->semStack[$stackPos-(8-7)], 'attrGroups' => $self->semStack[$stackPos-(8-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); $self->checkClass($self->semValue, $stackPos-(8-3)); }, 212 => static function ($self, $stackPos) { $self->semValue = new Stmt\Interface_($self->semStack[$stackPos-(7-3)], ['extends' => $self->semStack[$stackPos-(7-4)], 'stmts' => $self->semStack[$stackPos-(7-6)], 'attrGroups' => $self->semStack[$stackPos-(7-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); $self->checkInterface($self->semValue, $stackPos-(7-3)); }, 213 => static function ($self, $stackPos) { $self->semValue = new Stmt\Trait_($self->semStack[$stackPos-(6-3)], ['stmts' => $self->semStack[$stackPos-(6-5)], 'attrGroups' => $self->semStack[$stackPos-(6-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); }, 214 => static function ($self, $stackPos) { $self->semValue = new Stmt\Enum_($self->semStack[$stackPos-(8-3)], ['scalarType' => $self->semStack[$stackPos-(8-4)], 'implements' => $self->semStack[$stackPos-(8-5)], 'stmts' => $self->semStack[$stackPos-(8-7)], 'attrGroups' => $self->semStack[$stackPos-(8-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); $self->checkEnum($self->semValue, $stackPos-(8-3)); }, 215 => static function ($self, $stackPos) { $self->semValue = null; }, 216 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 217 => static function ($self, $stackPos) { $self->semValue = null; }, 218 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 219 => static function ($self, $stackPos) { $self->semValue = 0; }, 220 => null, 221 => null, 222 => static function ($self, $stackPos) { $self->checkClassModifier($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $self->semValue = $self->semStack[$stackPos-(2-1)] | $self->semStack[$stackPos-(2-2)]; }, 223 => static function ($self, $stackPos) { $self->semValue = Modifiers::ABSTRACT; }, 224 => static function ($self, $stackPos) { $self->semValue = Modifiers::FINAL; }, 225 => static function ($self, $stackPos) { $self->semValue = Modifiers::READONLY; }, 226 => static function ($self, $stackPos) { $self->semValue = null; }, 227 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 228 => static function ($self, $stackPos) { $self->semValue = array(); }, 229 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 230 => static function ($self, $stackPos) { $self->semValue = array(); }, 231 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 232 => null, 233 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 234 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 235 => null, 236 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 237 => null, 238 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 239 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(1-1)] instanceof Stmt\Block) { $self->semValue = $self->semStack[$stackPos-(1-1)]->stmts; } else if ($self->semStack[$stackPos-(1-1)] === null) { $self->semValue = []; } else { $self->semValue = [$self->semStack[$stackPos-(1-1)]]; }; }, 240 => static function ($self, $stackPos) { $self->semValue = null; }, 241 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 242 => null, 243 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 244 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 245 => static function ($self, $stackPos) { $self->semValue = new Node\DeclareItem($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 246 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 247 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-3)]; }, 248 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 249 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(5-3)]; }, 250 => static function ($self, $stackPos) { $self->semValue = array(); }, 251 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 252 => static function ($self, $stackPos) { $self->semValue = new Stmt\Case_($self->semStack[$stackPos-(4-2)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 253 => static function ($self, $stackPos) { $self->semValue = new Stmt\Case_(null, $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 254 => null, 255 => null, 256 => static function ($self, $stackPos) { $self->semValue = new Expr\Match_($self->semStack[$stackPos-(7-3)], $self->semStack[$stackPos-(7-6)], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 257 => static function ($self, $stackPos) { $self->semValue = []; }, 258 => null, 259 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 260 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 261 => static function ($self, $stackPos) { $self->semValue = new Node\MatchArm($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 262 => static function ($self, $stackPos) { $self->semValue = new Node\MatchArm(null, $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 263 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 264 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 265 => static function ($self, $stackPos) { $self->semValue = array(); }, 266 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 267 => static function ($self, $stackPos) { $self->semValue = new Stmt\ElseIf_($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 268 => static function ($self, $stackPos) { $self->semValue = array(); }, 269 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 270 => static function ($self, $stackPos) { $self->semValue = new Stmt\ElseIf_($self->semStack[$stackPos-(6-3)], $self->semStack[$stackPos-(6-6)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); $self->fixupAlternativeElse($self->semValue); }, 271 => static function ($self, $stackPos) { $self->semValue = null; }, 272 => static function ($self, $stackPos) { $self->semValue = new Stmt\Else_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 273 => static function ($self, $stackPos) { $self->semValue = null; }, 274 => static function ($self, $stackPos) { $self->semValue = new Stmt\Else_($self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->fixupAlternativeElse($self->semValue); }, 275 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)], false); }, 276 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(2-2)], true); }, 277 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)], false); }, 278 => static function ($self, $stackPos) { $self->semValue = array($self->fixupArrayDestructuring($self->semStack[$stackPos-(1-1)]), false); }, 279 => null, 280 => static function ($self, $stackPos) { $self->semValue = array(); }, 281 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 282 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 283 => static function ($self, $stackPos) { $self->semValue = 0; }, 284 => static function ($self, $stackPos) { $self->checkModifier($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $self->semValue = $self->semStack[$stackPos-(2-1)] | $self->semStack[$stackPos-(2-2)]; }, 285 => static function ($self, $stackPos) { $self->semValue = Modifiers::PUBLIC; }, 286 => static function ($self, $stackPos) { $self->semValue = Modifiers::PROTECTED; }, 287 => static function ($self, $stackPos) { $self->semValue = Modifiers::PRIVATE; }, 288 => static function ($self, $stackPos) { $self->semValue = Modifiers::PUBLIC_SET; }, 289 => static function ($self, $stackPos) { $self->semValue = Modifiers::PROTECTED_SET; }, 290 => static function ($self, $stackPos) { $self->semValue = Modifiers::PRIVATE_SET; }, 291 => static function ($self, $stackPos) { $self->semValue = Modifiers::READONLY; }, 292 => static function ($self, $stackPos) { $self->semValue = Modifiers::FINAL; }, 293 => static function ($self, $stackPos) { $self->semValue = new Node\Param($self->semStack[$stackPos-(7-6)], null, $self->semStack[$stackPos-(7-3)], $self->semStack[$stackPos-(7-4)], $self->semStack[$stackPos-(7-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(7-2)], $self->semStack[$stackPos-(7-1)], $self->semStack[$stackPos-(7-7)]); $self->checkParam($self->semValue); $self->addPropertyNameToHooks($self->semValue); }, 294 => static function ($self, $stackPos) { $self->semValue = new Node\Param($self->semStack[$stackPos-(9-6)], $self->semStack[$stackPos-(9-8)], $self->semStack[$stackPos-(9-3)], $self->semStack[$stackPos-(9-4)], $self->semStack[$stackPos-(9-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(9-2)], $self->semStack[$stackPos-(9-1)], $self->semStack[$stackPos-(9-9)]); $self->checkParam($self->semValue); $self->addPropertyNameToHooks($self->semValue); }, 295 => static function ($self, $stackPos) { $self->semValue = new Node\Param(new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])), null, $self->semStack[$stackPos-(6-3)], $self->semStack[$stackPos-(6-4)], $self->semStack[$stackPos-(6-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(6-2)], $self->semStack[$stackPos-(6-1)]); }, 296 => null, 297 => static function ($self, $stackPos) { $self->semValue = new Node\NullableType($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 298 => static function ($self, $stackPos) { $self->semValue = new Node\UnionType($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 299 => null, 300 => null, 301 => static function ($self, $stackPos) { $self->semValue = new Node\Name('static', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 302 => static function ($self, $stackPos) { $self->semValue = $self->handleBuiltinTypes($self->semStack[$stackPos-(1-1)]); }, 303 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier('array', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 304 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier('callable', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 305 => null, 306 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 307 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 308 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 309 => null, 310 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 311 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 312 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 313 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 314 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 315 => static function ($self, $stackPos) { $self->semValue = new Node\IntersectionType($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 316 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 317 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 318 => static function ($self, $stackPos) { $self->semValue = new Node\IntersectionType($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 319 => null, 320 => static function ($self, $stackPos) { $self->semValue = new Node\NullableType($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 321 => static function ($self, $stackPos) { $self->semValue = new Node\UnionType($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 322 => null, 323 => static function ($self, $stackPos) { $self->semValue = null; }, 324 => null, 325 => static function ($self, $stackPos) { $self->semValue = null; }, 326 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 327 => static function ($self, $stackPos) { $self->semValue = null; }, 328 => static function ($self, $stackPos) { $self->semValue = array(); }, 329 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 330 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-2)]); }, 331 => static function ($self, $stackPos) { $self->semValue = array(); }, 332 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 333 => static function ($self, $stackPos) { $self->semValue = array(new Node\Arg($self->semStack[$stackPos-(4-2)], false, false, $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos]))); }, 334 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-2)]); }, 335 => static function ($self, $stackPos) { $self->semValue = array(new Node\Arg($self->semStack[$stackPos-(3-1)], false, false, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos-(3-1)])), $self->semStack[$stackPos-(3-3)]); }, 336 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 337 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 338 => static function ($self, $stackPos) { $self->semValue = new Node\VariadicPlaceholder($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 339 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 340 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 341 => static function ($self, $stackPos) { $self->semValue = new Node\Arg($self->semStack[$stackPos-(2-2)], true, false, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 342 => static function ($self, $stackPos) { $self->semValue = new Node\Arg($self->semStack[$stackPos-(2-2)], false, true, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 343 => static function ($self, $stackPos) { $self->semValue = new Node\Arg($self->semStack[$stackPos-(3-3)], false, false, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(3-1)]); }, 344 => static function ($self, $stackPos) { $self->semValue = new Node\Arg($self->semStack[$stackPos-(1-1)], false, false, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 345 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 346 => null, 347 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 348 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 349 => null, 350 => null, 351 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 352 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 353 => static function ($self, $stackPos) { $self->semValue = new Node\StaticVar($self->semStack[$stackPos-(1-1)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 354 => static function ($self, $stackPos) { $self->semValue = new Node\StaticVar($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 355 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(2-2)] !== null) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; } else { $self->semValue = $self->semStack[$stackPos-(2-1)]; } }, 356 => static function ($self, $stackPos) { $self->semValue = array(); }, 357 => static function ($self, $stackPos) { $nop = $self->maybeCreateZeroLengthNop($self->tokenPos);; if ($nop !== null) { $self->semStack[$stackPos-(1-1)][] = $nop; } $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 358 => static function ($self, $stackPos) { $self->semValue = new Stmt\Property($self->semStack[$stackPos-(5-2)], $self->semStack[$stackPos-(5-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-1)]); }, 359 => static function ($self, $stackPos) { $self->semValue = new Stmt\ClassConst($self->semStack[$stackPos-(5-4)], $self->semStack[$stackPos-(5-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(5-1)]); $self->checkClassConst($self->semValue, $stackPos-(5-2)); }, 360 => static function ($self, $stackPos) { $self->semValue = new Stmt\ClassConst($self->semStack[$stackPos-(6-5)], $self->semStack[$stackPos-(6-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(6-1)], $self->semStack[$stackPos-(6-4)]); $self->checkClassConst($self->semValue, $stackPos-(6-2)); }, 361 => static function ($self, $stackPos) { $self->semValue = new Stmt\ClassMethod($self->semStack[$stackPos-(10-5)], ['type' => $self->semStack[$stackPos-(10-2)], 'byRef' => $self->semStack[$stackPos-(10-4)], 'params' => $self->semStack[$stackPos-(10-7)], 'returnType' => $self->semStack[$stackPos-(10-9)], 'stmts' => $self->semStack[$stackPos-(10-10)], 'attrGroups' => $self->semStack[$stackPos-(10-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(10-1)], $self->tokenEndStack[$stackPos])); $self->checkClassMethod($self->semValue, $stackPos-(10-2)); }, 362 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUse($self->semStack[$stackPos-(3-2)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 363 => static function ($self, $stackPos) { $self->semValue = new Stmt\EnumCase($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-4)], $self->semStack[$stackPos-(5-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 364 => static function ($self, $stackPos) { $self->semValue = null; /* will be skipped */ }, 365 => static function ($self, $stackPos) { $self->semValue = array(); }, 366 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 367 => static function ($self, $stackPos) { $self->semValue = array(); }, 368 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 369 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Precedence($self->semStack[$stackPos-(4-1)][0], $self->semStack[$stackPos-(4-1)][1], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 370 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Alias($self->semStack[$stackPos-(5-1)][0], $self->semStack[$stackPos-(5-1)][1], $self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 371 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Alias($self->semStack[$stackPos-(4-1)][0], $self->semStack[$stackPos-(4-1)][1], $self->semStack[$stackPos-(4-3)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 372 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Alias($self->semStack[$stackPos-(4-1)][0], $self->semStack[$stackPos-(4-1)][1], null, $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 373 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Alias($self->semStack[$stackPos-(4-1)][0], $self->semStack[$stackPos-(4-1)][1], null, $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 374 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 375 => null, 376 => static function ($self, $stackPos) { $self->semValue = array(null, $self->semStack[$stackPos-(1-1)]); }, 377 => static function ($self, $stackPos) { $self->semValue = null; }, 378 => null, 379 => null, 380 => static function ($self, $stackPos) { $self->semValue = 0; }, 381 => static function ($self, $stackPos) { $self->semValue = 0; }, 382 => null, 383 => null, 384 => static function ($self, $stackPos) { $self->checkModifier($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $self->semValue = $self->semStack[$stackPos-(2-1)] | $self->semStack[$stackPos-(2-2)]; }, 385 => static function ($self, $stackPos) { $self->semValue = Modifiers::PUBLIC; }, 386 => static function ($self, $stackPos) { $self->semValue = Modifiers::PROTECTED; }, 387 => static function ($self, $stackPos) { $self->semValue = Modifiers::PRIVATE; }, 388 => static function ($self, $stackPos) { $self->semValue = Modifiers::PUBLIC_SET; }, 389 => static function ($self, $stackPos) { $self->semValue = Modifiers::PROTECTED_SET; }, 390 => static function ($self, $stackPos) { $self->semValue = Modifiers::PRIVATE_SET; }, 391 => static function ($self, $stackPos) { $self->semValue = Modifiers::STATIC; }, 392 => static function ($self, $stackPos) { $self->semValue = Modifiers::ABSTRACT; }, 393 => static function ($self, $stackPos) { $self->semValue = Modifiers::FINAL; }, 394 => static function ($self, $stackPos) { $self->semValue = Modifiers::READONLY; }, 395 => null, 396 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 397 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 398 => static function ($self, $stackPos) { $self->semValue = new Node\VarLikeIdentifier(substr($self->semStack[$stackPos-(1-1)], 1), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 399 => static function ($self, $stackPos) { $self->semValue = new Node\PropertyItem($self->semStack[$stackPos-(1-1)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 400 => static function ($self, $stackPos) { $self->semValue = new Node\PropertyItem($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 401 => static function ($self, $stackPos) { $self->semValue = []; }, 402 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 403 => static function ($self, $stackPos) { $self->semValue = []; }, 404 => static function ($self, $stackPos) { $self->semValue = new Node\PropertyHook($self->semStack[$stackPos-(5-4)], $self->semStack[$stackPos-(5-5)], ['flags' => $self->semStack[$stackPos-(5-2)], 'byRef' => $self->semStack[$stackPos-(5-3)], 'params' => [], 'attrGroups' => $self->semStack[$stackPos-(5-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); $self->checkPropertyHook($self->semValue, null); }, 405 => static function ($self, $stackPos) { $self->semValue = new Node\PropertyHook($self->semStack[$stackPos-(8-4)], $self->semStack[$stackPos-(8-8)], ['flags' => $self->semStack[$stackPos-(8-2)], 'byRef' => $self->semStack[$stackPos-(8-3)], 'params' => $self->semStack[$stackPos-(8-6)], 'attrGroups' => $self->semStack[$stackPos-(8-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); $self->checkPropertyHook($self->semValue, $stackPos-(8-5)); }, 406 => static function ($self, $stackPos) { $self->semValue = null; }, 407 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 408 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 409 => static function ($self, $stackPos) { $self->semValue = 0; }, 410 => static function ($self, $stackPos) { $self->checkPropertyHookModifiers($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $self->semValue = $self->semStack[$stackPos-(2-1)] | $self->semStack[$stackPos-(2-2)]; }, 411 => null, 412 => null, 413 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 414 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 415 => static function ($self, $stackPos) { $self->semValue = array(); }, 416 => null, 417 => null, 418 => static function ($self, $stackPos) { $self->semValue = new Expr\Assign($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 419 => static function ($self, $stackPos) { $self->semValue = new Expr\Assign($self->fixupArrayDestructuring($self->semStack[$stackPos-(3-1)]), $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 420 => static function ($self, $stackPos) { $self->semValue = new Expr\Assign($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 421 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignRef($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 422 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignRef($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); if (!$self->phpVersion->allowsAssignNewByReference()) { $self->emitError(new Error('Cannot assign new by reference', $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos]))); } }, 423 => null, 424 => null, 425 => static function ($self, $stackPos) { $self->semValue = new Expr\FuncCall(new Node\Name($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos-(2-1)])), $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 426 => static function ($self, $stackPos) { $self->semValue = new Expr\Clone_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 427 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Plus($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 428 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Minus($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 429 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Mul($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 430 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Div($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 431 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Concat($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 432 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Mod($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 433 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\BitwiseAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 434 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\BitwiseOr($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 435 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\BitwiseXor($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 436 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\ShiftLeft($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 437 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\ShiftRight($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 438 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Pow($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 439 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Coalesce($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 440 => static function ($self, $stackPos) { $self->semValue = new Expr\PostInc($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 441 => static function ($self, $stackPos) { $self->semValue = new Expr\PreInc($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 442 => static function ($self, $stackPos) { $self->semValue = new Expr\PostDec($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 443 => static function ($self, $stackPos) { $self->semValue = new Expr\PreDec($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 444 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BooleanOr($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 445 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BooleanAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 446 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\LogicalOr($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 447 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\LogicalAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 448 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\LogicalXor($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 449 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BitwiseOr($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 450 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BitwiseAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 451 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BitwiseAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 452 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BitwiseXor($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 453 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Concat($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 454 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Plus($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 455 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Minus($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 456 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Mul($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 457 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Div($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 458 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Mod($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 459 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\ShiftLeft($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 460 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\ShiftRight($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 461 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Pow($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 462 => static function ($self, $stackPos) { $self->semValue = new Expr\UnaryPlus($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 463 => static function ($self, $stackPos) { $self->semValue = new Expr\UnaryMinus($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 464 => static function ($self, $stackPos) { $self->semValue = new Expr\BooleanNot($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 465 => static function ($self, $stackPos) { $self->semValue = new Expr\BitwiseNot($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 466 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Identical($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 467 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\NotIdentical($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 468 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Equal($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 469 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\NotEqual($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 470 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Spaceship($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 471 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Smaller($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 472 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\SmallerOrEqual($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 473 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Greater($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 474 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\GreaterOrEqual($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 475 => static function ($self, $stackPos) { $self->semValue = new Expr\Instanceof_($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 476 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; if ($self->semValue instanceof Expr\ArrowFunction) { $self->parenthesizedArrowFunctions->offsetSet($self->semValue); } }, 477 => static function ($self, $stackPos) { $self->semValue = new Expr\Ternary($self->semStack[$stackPos-(5-1)], $self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 478 => static function ($self, $stackPos) { $self->semValue = new Expr\Ternary($self->semStack[$stackPos-(4-1)], null, $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 479 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Coalesce($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 480 => static function ($self, $stackPos) { $self->semValue = new Expr\Isset_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 481 => static function ($self, $stackPos) { $self->semValue = new Expr\Empty_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 482 => static function ($self, $stackPos) { $self->semValue = new Expr\Include_($self->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 483 => static function ($self, $stackPos) { $self->semValue = new Expr\Include_($self->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 484 => static function ($self, $stackPos) { $self->semValue = new Expr\Eval_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 485 => static function ($self, $stackPos) { $self->semValue = new Expr\Include_($self->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 486 => static function ($self, $stackPos) { $self->semValue = new Expr\Include_($self->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 487 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = $self->getIntCastKind($self->semStack[$stackPos-(2-1)]); $self->semValue = new Expr\Cast\Int_($self->semStack[$stackPos-(2-2)], $attrs); }, 488 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = $self->getFloatCastKind($self->semStack[$stackPos-(2-1)]); $self->semValue = new Expr\Cast\Double($self->semStack[$stackPos-(2-2)], $attrs); }, 489 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = $self->getStringCastKind($self->semStack[$stackPos-(2-1)]); $self->semValue = new Expr\Cast\String_($self->semStack[$stackPos-(2-2)], $attrs); }, 490 => static function ($self, $stackPos) { $self->semValue = new Expr\Cast\Array_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 491 => static function ($self, $stackPos) { $self->semValue = new Expr\Cast\Object_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 492 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = $self->getBoolCastKind($self->semStack[$stackPos-(2-1)]); $self->semValue = new Expr\Cast\Bool_($self->semStack[$stackPos-(2-2)], $attrs); }, 493 => static function ($self, $stackPos) { $self->semValue = new Expr\Cast\Unset_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 494 => static function ($self, $stackPos) { $self->semValue = new Expr\Cast\Void_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 495 => static function ($self, $stackPos) { $self->semValue = $self->createExitExpr($self->semStack[$stackPos-(2-1)], $stackPos-(2-1), $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 496 => static function ($self, $stackPos) { $self->semValue = new Expr\ErrorSuppress($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 497 => null, 498 => static function ($self, $stackPos) { $self->semValue = new Expr\ShellExec($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 499 => static function ($self, $stackPos) { $self->semValue = new Expr\Print_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 500 => static function ($self, $stackPos) { $self->semValue = new Expr\Yield_(null, null, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 501 => static function ($self, $stackPos) { $self->semValue = new Expr\Yield_($self->semStack[$stackPos-(2-2)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 502 => static function ($self, $stackPos) { $self->semValue = new Expr\Yield_($self->semStack[$stackPos-(4-4)], $self->semStack[$stackPos-(4-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 503 => static function ($self, $stackPos) { $self->semValue = new Expr\YieldFrom($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 504 => static function ($self, $stackPos) { $self->semValue = new Expr\Throw_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 505 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $self->semStack[$stackPos-(8-2)], 'params' => $self->semStack[$stackPos-(8-4)], 'returnType' => $self->semStack[$stackPos-(8-6)], 'expr' => $self->semStack[$stackPos-(8-8)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 506 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-5)], 'returnType' => $self->semStack[$stackPos-(9-7)], 'expr' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 507 => static function ($self, $stackPos) { $self->semValue = new Expr\Closure(['static' => false, 'byRef' => $self->semStack[$stackPos-(8-2)], 'params' => $self->semStack[$stackPos-(8-4)], 'uses' => $self->semStack[$stackPos-(8-6)], 'returnType' => $self->semStack[$stackPos-(8-7)], 'stmts' => $self->semStack[$stackPos-(8-8)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 508 => static function ($self, $stackPos) { $self->semValue = new Expr\Closure(['static' => true, 'byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-5)], 'uses' => $self->semStack[$stackPos-(9-7)], 'returnType' => $self->semStack[$stackPos-(9-8)], 'stmts' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 509 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-5)], 'returnType' => $self->semStack[$stackPos-(9-7)], 'expr' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => $self->semStack[$stackPos-(9-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 510 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $self->semStack[$stackPos-(10-4)], 'params' => $self->semStack[$stackPos-(10-6)], 'returnType' => $self->semStack[$stackPos-(10-8)], 'expr' => $self->semStack[$stackPos-(10-10)], 'attrGroups' => $self->semStack[$stackPos-(10-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(10-1)], $self->tokenEndStack[$stackPos])); }, 511 => static function ($self, $stackPos) { $self->semValue = new Expr\Closure(['static' => false, 'byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-5)], 'uses' => $self->semStack[$stackPos-(9-7)], 'returnType' => $self->semStack[$stackPos-(9-8)], 'stmts' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => $self->semStack[$stackPos-(9-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 512 => static function ($self, $stackPos) { $self->semValue = new Expr\Closure(['static' => true, 'byRef' => $self->semStack[$stackPos-(10-4)], 'params' => $self->semStack[$stackPos-(10-6)], 'uses' => $self->semStack[$stackPos-(10-8)], 'returnType' => $self->semStack[$stackPos-(10-9)], 'stmts' => $self->semStack[$stackPos-(10-10)], 'attrGroups' => $self->semStack[$stackPos-(10-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(10-1)], $self->tokenEndStack[$stackPos])); }, 513 => static function ($self, $stackPos) { $self->semValue = array(new Stmt\Class_(null, ['type' => $self->semStack[$stackPos-(8-2)], 'extends' => $self->semStack[$stackPos-(8-4)], 'implements' => $self->semStack[$stackPos-(8-5)], 'stmts' => $self->semStack[$stackPos-(8-7)], 'attrGroups' => $self->semStack[$stackPos-(8-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])), $self->semStack[$stackPos-(8-3)]); $self->checkClass($self->semValue[0], -1); }, 514 => static function ($self, $stackPos) { $self->semValue = new Expr\New_($self->semStack[$stackPos-(3-2)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 515 => static function ($self, $stackPos) { list($class, $ctorArgs) = $self->semStack[$stackPos-(2-2)]; $self->semValue = new Expr\New_($class, $ctorArgs, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 516 => static function ($self, $stackPos) { $self->semValue = new Expr\New_($self->semStack[$stackPos-(2-2)], [], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 517 => null, 518 => null, 519 => static function ($self, $stackPos) { $self->semValue = array(); }, 520 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-3)]; }, 521 => null, 522 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 523 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 524 => static function ($self, $stackPos) { $self->semValue = new Node\ClosureUse($self->semStack[$stackPos-(2-2)], $self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 525 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 526 => static function ($self, $stackPos) { $self->semValue = new Expr\FuncCall($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 527 => static function ($self, $stackPos) { $self->semValue = new Expr\FuncCall($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 528 => static function ($self, $stackPos) { $self->semValue = new Expr\FuncCall($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 529 => static function ($self, $stackPos) { $self->semValue = new Expr\StaticCall($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 530 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 531 => null, 532 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 533 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 534 => static function ($self, $stackPos) { $self->semValue = new Name\FullyQualified(substr($self->semStack[$stackPos-(1-1)], 1), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 535 => static function ($self, $stackPos) { $self->semValue = new Name\Relative(substr($self->semStack[$stackPos-(1-1)], 10), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 536 => null, 537 => null, 538 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 539 => static function ($self, $stackPos) { $self->semValue = new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->errorState = 2; }, 540 => null, 541 => null, 542 => static function ($self, $stackPos) { $self->semValue = array(); }, 543 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); foreach ($self->semValue as $s) { if ($s instanceof Node\InterpolatedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', $self->phpVersion->supportsUnicodeEscapes()); } }; }, 544 => static function ($self, $stackPos) { foreach ($self->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\InterpolatedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', $self->phpVersion->supportsUnicodeEscapes()); } }; $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 545 => static function ($self, $stackPos) { $self->semValue = array(); }, 546 => null, 547 => static function ($self, $stackPos) { $self->semValue = new Expr\ConstFetch($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 548 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Line($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 549 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\File($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 550 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Dir($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 551 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Class_($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 552 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Trait_($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 553 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Method($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 554 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Function_($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 555 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Namespace_($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 556 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Property($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 557 => static function ($self, $stackPos) { $self->semValue = new Expr\ClassConstFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 558 => static function ($self, $stackPos) { $self->semValue = new Expr\ClassConstFetch($self->semStack[$stackPos-(5-1)], $self->semStack[$stackPos-(5-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 559 => static function ($self, $stackPos) { $self->semValue = new Expr\ClassConstFetch($self->semStack[$stackPos-(3-1)], new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(3-3)], $self->tokenEndStack[$stackPos-(3-3)])), $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->errorState = 2; }, 560 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = Expr\Array_::KIND_SHORT; $self->semValue = new Expr\Array_($self->semStack[$stackPos-(3-2)], $attrs); }, 561 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = Expr\Array_::KIND_LONG; $self->semValue = new Expr\Array_($self->semStack[$stackPos-(4-3)], $attrs); $self->createdArrays->offsetSet($self->semValue); }, 562 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; $self->createdArrays->offsetSet($self->semValue); }, 563 => static function ($self, $stackPos) { $self->semValue = Scalar\String_::fromString($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]), $self->phpVersion->supportsUnicodeEscapes()); }, 564 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; foreach ($self->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\InterpolatedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', $self->phpVersion->supportsUnicodeEscapes()); } }; $self->semValue = new Scalar\InterpolatedString($self->semStack[$stackPos-(3-2)], $attrs); }, 565 => static function ($self, $stackPos) { $self->semValue = $self->parseLNumber($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]), $self->phpVersion->allowsInvalidOctals()); }, 566 => static function ($self, $stackPos) { $self->semValue = Scalar\Float_::fromString($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 567 => null, 568 => null, 569 => null, 570 => static function ($self, $stackPos) { $self->semValue = $self->parseDocString($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-2)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]), $self->getAttributes($self->tokenStartStack[$stackPos-(3-3)], $self->tokenEndStack[$stackPos-(3-3)]), true); }, 571 => static function ($self, $stackPos) { $self->semValue = $self->parseDocString($self->semStack[$stackPos-(2-1)], '', $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]), $self->getAttributes($self->tokenStartStack[$stackPos-(2-2)], $self->tokenEndStack[$stackPos-(2-2)]), true); }, 572 => static function ($self, $stackPos) { $self->semValue = $self->parseDocString($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-2)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]), $self->getAttributes($self->tokenStartStack[$stackPos-(3-3)], $self->tokenEndStack[$stackPos-(3-3)]), true); }, 573 => static function ($self, $stackPos) { $self->semValue = null; }, 574 => null, 575 => null, 576 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 577 => null, 578 => null, 579 => null, 580 => null, 581 => null, 582 => null, 583 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 584 => null, 585 => null, 586 => null, 587 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 588 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 589 => null, 590 => static function ($self, $stackPos) { $self->semValue = new Expr\MethodCall($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 591 => static function ($self, $stackPos) { $self->semValue = new Expr\NullsafeMethodCall($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 592 => static function ($self, $stackPos) { $self->semValue = null; }, 593 => null, 594 => null, 595 => null, 596 => static function ($self, $stackPos) { $self->semValue = new Expr\PropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 597 => static function ($self, $stackPos) { $self->semValue = new Expr\NullsafePropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 598 => null, 599 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 600 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 601 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable(new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])), $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); $self->errorState = 2; }, 602 => static function ($self, $stackPos) { $var = $self->semStack[$stackPos-(1-1)]->name; $self->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])) : $var; }, 603 => static function ($self, $stackPos) { $self->semValue = new Expr\StaticPropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 604 => null, 605 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 606 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 607 => static function ($self, $stackPos) { $self->semValue = new Expr\PropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 608 => static function ($self, $stackPos) { $self->semValue = new Expr\NullsafePropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 609 => static function ($self, $stackPos) { $self->semValue = new Expr\StaticPropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 610 => static function ($self, $stackPos) { $self->semValue = new Expr\StaticPropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 611 => null, 612 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 613 => null, 614 => null, 615 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 616 => null, 617 => static function ($self, $stackPos) { $self->semValue = new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->errorState = 2; }, 618 => static function ($self, $stackPos) { $self->semValue = new Expr\List_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('kind', Expr\List_::KIND_LIST); $self->postprocessList($self->semValue); }, 619 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; $end = count($self->semValue)-1; if ($self->semValue[$end]->value instanceof Expr\Error) array_pop($self->semValue); }, 620 => null, 621 => static function ($self, $stackPos) { /* do nothing -- prevent default action of $$=$self->semStack[$1]. See $551. */ }, 622 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 623 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 624 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(1-1)], null, false, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 625 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(2-2)], null, true, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 626 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(1-1)], null, false, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 627 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(3-3)], $self->semStack[$stackPos-(3-1)], false, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 628 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(4-4)], $self->semStack[$stackPos-(4-1)], true, $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 629 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(3-3)], $self->semStack[$stackPos-(3-1)], false, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 630 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(2-2)], null, false, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]), true); }, 631 => static function ($self, $stackPos) { /* Create an Error node now to remember the position. We'll later either report an error, or convert this into a null element, depending on whether this is a creation or destructuring context. */ $attrs = $self->createEmptyElemAttributes($self->tokenPos); $self->semValue = new Node\ArrayItem(new Expr\Error($attrs), null, false, $attrs); }, 632 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 633 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 634 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 635 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)]); }, 636 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]); $attrs['rawValue'] = $self->semStack[$stackPos-(1-1)]; $self->semValue = new Node\InterpolatedStringPart($self->semStack[$stackPos-(1-1)], $attrs); }, 637 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 638 => null, 639 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 640 => static function ($self, $stackPos) { $self->semValue = new Expr\PropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 641 => static function ($self, $stackPos) { $self->semValue = new Expr\NullsafePropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 642 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 643 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 644 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(6-2)], $self->semStack[$stackPos-(6-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); }, 645 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 646 => static function ($self, $stackPos) { $self->semValue = new Scalar\String_($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 647 => static function ($self, $stackPos) { $self->semValue = $self->parseNumString($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 648 => static function ($self, $stackPos) { $self->semValue = $self->parseNumString('-' . $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 649 => null, ]; } } '", "T_IS_GREATER_OR_EQUAL", "T_PIPE", "'.'", "T_SL", "T_SR", "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "T_INSTANCEOF", "'~'", "T_INC", "T_DEC", "T_INT_CAST", "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", "T_BOOL_CAST", "T_UNSET_CAST", "'@'", "T_POW", "'['", "T_NEW", "T_CLONE", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_MATCH", "T_ENDSWITCH", "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_GOTO", "T_FUNCTION", "T_FN", "T_CONST", "T_RETURN", "T_TRY", "T_CATCH", "T_FINALLY", "T_USE", "T_INSTEADOF", "T_GLOBAL", "T_STATIC", "T_ABSTRACT", "T_FINAL", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", "T_READONLY", "T_PUBLIC_SET", "T_PROTECTED_SET", "T_PRIVATE_SET", "T_VAR", "T_UNSET", "T_ISSET", "T_EMPTY", "T_HALT_COMPILER", "T_CLASS", "T_TRAIT", "T_INTERFACE", "T_ENUM", "T_EXTENDS", "T_IMPLEMENTS", "T_OBJECT_OPERATOR", "T_NULLSAFE_OBJECT_OPERATOR", "T_LIST", "T_ARRAY", "T_CALLABLE", "T_CLASS_C", "T_TRAIT_C", "T_METHOD_C", "T_FUNC_C", "T_PROPERTY_C", "T_LINE", "T_FILE", "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", "T_ELLIPSIS", "T_NAME_FULLY_QUALIFIED", "T_NAME_QUALIFIED", "T_NAME_RELATIVE", "T_ATTRIBUTE", "';'", "']'", "'('", "')'", "'{'", "'}'", "'`'", "'\"'", "'$'" ); protected array $tokenToSymbol = array( 0, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 58, 172, 174, 173, 57, 174, 174, 167, 168, 55, 53, 9, 54, 50, 56, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 32, 165, 45, 17, 47, 31, 70, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 72, 174, 166, 37, 174, 171, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 36, 170, 60, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 35, 38, 39, 40, 41, 42, 43, 44, 46, 48, 49, 51, 52, 59, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164 ); protected array $action = array( 132, 133, 134, 582, 135, 136, 162, 779, 780, 781, 137, 41, 863,-32766, 970, 1404, -584, 974, 973, 1302, 0, 395, 396, 455, 246, 854,-32766,-32766,-32766,-32766, -32766, 440,-32766, 27,-32766, 773, 772,-32766,-32766,-32766, -32766, 508,-32766,-32766,-32766,-32766,-32766,-32766,-32766,-32766, 131,-32766,-32766,-32766,-32766, 437, 782, 859, 1148,-32766, 949,-32766,-32766,-32766,-32766,-32766,-32766, 972, 1385, 300, 271, 53, 398, 786, 787, 788, 789, 305, 865, 441, -341, 39, 254, -584, -584, -195, 843, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 819, 583, 820, 821, 822, 823, 811, 812, 353, 354, 814, 815, 800, 801, 802, 804, 805, 806, 368, 846, 847, 848, 849, 850, 584, 1062, -194, 856, 807, 808, 585, 586, 3, 831, 829, 830, 842, 826, 827, 4, 860, 587, 588, 825, 589, 590, 591, 592, 939, 593, 594, 5, 854, -32766,-32766,-32766, 828, 595, 596,-32766, 138, 764, 132, 133, 134, 582, 135, 136, 1098, 779, 780, 781, 137, 41,-32766,-32766,-32766,-32766,-32766,-32766, -275, 1302, 613, 153, 1071, 749, 990, 991,-32766,-32766,-32766, 992,-32766, 891,-32766, 892,-32766, 773, 772,-32766, 986, 1309, 397, 396,-32766,-32766,-32766, 858, 299, 630,-32766,-32766, 440, 502, 736,-32766,-32766, 437, 782,-32767,-32767,-32767,-32767, 106, 107, 108, 109, 951,-32766, 1021, 29, 734, 271, 53, 398, 786, 787, 788, 789, 144, 1071, 441, -341, 332, 38, 864, 862, -195, 843, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 819, 583, 820, 821, 822, 823, 811, 812, 353, 354, 814, 815, 800, 801, 802, 804, 805, 806, 368, 846, 847, 848, 849, 850, 584, 863, -194, 139, 807, 808, 585, 586, 323, 831, 829, 830, 842, 826, 827, 1370, 148, 587, 588, 825, 589, 590, 591, 592, 245, 593, 594, 395, 396,-32766, -32766,-32766, 828, 595, 596, -85, 138, 440, 132, 133, 134, 582, 135, 136, 1095, 779, 780, 781, 137, 41, -32766,-32766,-32766,-32766,-32766, 51, 578, 1302, 257,-32766, 636, 107, 108, 109,-32766,-32766,-32766, 503,-32766, 316, -32766,-32766,-32766, 773, 772,-32766, -383, 166, -383, 1022, -32766,-32766,-32766, 305, 79, 1133,-32766,-32766, 1414, 762, 332, 1415,-32766, 437, 782,-32766, 1071, 110, 111, 112, 113, 114, -85, 283,-32766, 477, 478, 479, 271, 53, 398, 786, 787, 788, 789, 115, 407, 441, 10,-32766, 299, 1341, 306, 307, 843, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 819, 583, 820, 821, 822, 823, 811, 812, 353, 354, 814, 815, 800, 801, 802, 804, 805, 806, 368, 846, 847, 848, 849, 850, 584, 320, 1068, -582, 807, 808, 585, 586, 1389, 831, 829, 830, 842, 826, 827, 329, 1388, 587, 588, 825, 589, 590, 591, 592, 86, 593, 594, 1071, 332,-32766,-32766, -32766, 828, 595, 596, 349, 151, -581, 132, 133, 134, 582, 135, 136, 1100, 779, 780, 781, 137, 41,-32766, 290,-32766,-32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767, -32767,-32767,-32767,-32766,-32766,-32766, 891, 1175, 892, -582, -582, 754, 773, 772, 1159, 1160, 1161, 1155, 1154, 1153, 1162, 1156, 1157, 1158,-32766, -582,-32766,-32766,-32766,-32766, -32766,-32766,-32766, 782,-32766,-32766,-32766, -588, -78,-32766, -32766,-32766, 350, -581, -581,-32766,-32766, 271, 53, 398, 786, 787, 788, 789, 383,-32766, 441,-32766,-32766, -581, -32766, 773, 772, 843, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 819, 583, 820, 821, 822, 823, 811, 812, 353, 354, 814, 815, 800, 801, 802, 804, 805, 806, 368, 846, 847, 848, 849, 850, 584, -620, 1068, -620, 807, 808, 585, 586, 389, 831, 829, 830, 842, 826, 827, 441, 405, 587, 588, 825, 589, 590, 591, 592, 333, 593, 594, 1071, 87, 88, 89, 459, 828, 595, 596, 460, 151, 803, 774, 775, 776, 777, 778, 854, 779, 780, 781, 816, 817, 40, 461, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 462, 283, 1329, 1159, 1160, 1161, 1155, 1154, 1153, 1162, 1156, 1157, 1158, 115, 869, 488, 489, 782, 1304, 1303, 1305, 108, 109, 1132, 154,-32766, -32766, 1134, 679, 23, 156, 783, 784, 785, 786, 787, 788, 789, 698, 699, 852, 152, 423, -580, 393, 394, 157, 843, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 819, 841, 820, 821, 822, 823, 811, 812, 813, 840, 814, 815, 800, 801, 802, 804, 805, 806, 845, 846, 847, 848, 849, 850, 851, 1094, -578, 863, 807, 808, 809, 810, -58, 831, 829, 830, 842, 826, 827, 399, 400, 818, 824, 825, 832, 833, 835, 834, 294, 836, 837, 158, -580, -580, 160, 294, 828, 839, 838, 54, 55, 56, 57, 534, 58, 59, 36, -110, -580, -57, 60, 61, -110, 62, -110, 670, 671, 129, 130, 312, -587, 140, -110, -110, -110, -110, -110, -110, -110, -110, -110, -110, -110, -578, -578, 141, 147, 949, 161, 712, -87, 163, 164, 165, -84, 949, -78, -73, -72, -578, 63, 64, 143, -309, -71, 65, 332, 66, 251, 252, 67, 68, 69, 70, 71, 72, 73, 74, 739, 31, 276, 47, 457, 535, -357, 713, 740, 1335, 1336, 536, -70, 863, 1068, -69, -68, 1333, 45, 22, 537, 949, 538, -67, 539, -66, 540, 52, -65, 541, 542, 714, 715, -46, 48, 49, 463, 392, 391, 1071, 50, 543, -18, 145, 281, 1302, 381, 348, 291, 750, 1304, 1303, 1305, 1295, 939, 753, 290, 948, 545, 546, 547, 150, 939, 290, -305, 295, 288, 289, 292, 293, 549, 550, 338, 1321, 1322, 1323, 1324, 1326, 1318, 1319, 304, 1300, 296, 301, 302, 283, 1325, 1320, 773, 772, 1304, 1303, 1305, 305, 308, 309, 75, -154, -154, -154, 327, 328, 332, 966, 854, 1070, 939, 149, 115, 1416, 388, 680, -154, 708, -154, 725, -154, 13, -154, 668, 723, 313, 31, 277, 1304, 1303, 1305, 863, 390,-32766, 600, 1166, 987, 951, 863, 310, 701, 734, 1333, 990, 991, 951,-32766, 686, 544, 734, 949, 685, 606, 1340, 485, 513, 925, 986, -110, -110, -110, 35, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 702, 949, 634, 1295, 773, 772, 741, -579, 305, -614, 1334, 0, 0, 0, 951, 311, 949, 0, 734, -154, 549, 550, 319, 1321, 1322, 1323, 1324, 1326, 1318, 1319, 1209, 1211, 744, 0, 1342, 0, 1325, 1320, -544, -534, 0, -578,-32766, -4, 949, 11, 77, 751, 1302, 30, 387, 328, 332, 862, 43,-32766,-32766,-32766, -613, -32766, 939,-32766, 968,-32766, 44, 759,-32766, 1330, 773, 772, 760,-32766,-32766,-32766, -579, -579, 882,-32766,-32766, 930, 1031, 1008, 1015,-32766, 437, 1005, 939, 1016, 928, 1003, -579, 1137, 1140, 1141, 1138,-32766, 1177, 1139, 1145, 37, 874, 939, -586, 1357, 1374, 1407,-32766, 673, -578, -578, -612, -588, 1302, -587, -586, -585, 31, 276, -528, -32766,-32766,-32766, 1,-32766, -578,-32766, 78,-32766, 863, 939,-32766, 32, 1333, -278, 33,-32766,-32766,-32766, 42, 1007, 46,-32766,-32766, 734, 76, 80, 81,-32766, 437, 82, 83, 390, 84, 453, 31, 277, 85, 146, 303, -32766, 155, 159, 990, 991, 249, 951, 863, 544, 1295, 734, 1333, 334, 369, 370, 371, 548, 986, -110, -110, -110, 951, 372, 326, 373, 734, 374, 550, 375, 1321, 1322, 1323, 1324, 1326, 1318, 1319, 376, 377, 422, 378, 21, -50, 1325, 1320, 379, 382, 454, 1295, 577, 951, 380, 384, 77, 734, -4, -276, -275, 328, 332, 15, 16, 17, 18, 20, 363, 550, 421, 1321, 1322, 1323, 1324, 1326, 1318, 1319, 142, 504, 505, 512, 515, 516, 1325, 1320, 949, 517, 518,-32766, 522, 523, 524, 531, 77, 1302, 611, 718, 1101, 328, 332, 1097,-32766,-32766, -32766, 1250,-32766, 1331,-32766, 949,-32766, 1099, 1096,-32766, 1077, 1290, 1309, 1073,-32766,-32766,-32766, -280,-32766, -102, -32766,-32766, 14, 19, 1302, 24,-32766, 437, 323, 420, 625,-32766,-32766,-32766, 631,-32766, 659,-32766,-32766,-32766, 724, 1254,-32766, -16, 1308, 1251, 1386,-32766,-32766,-32766, 735,-32766, 738,-32766,-32766, 742, 743, 1302, 745,-32766, 437, 746, 747, 748,-32766,-32766,-32766, 939,-32766, 300, -32766,-32766,-32766, 752, 1309,-32766, 764, 737, 332, 765, -32766,-32766,-32766, -253, -253, -253,-32766,-32766, 426, 390, 939, 756,-32766, 437, 926, 863, 1411, 1413, 885, 884, 990, 991, 980, 1023,-32766, 544, -252, -252, -252, 1412, 979, 977, 390, 925, 986, -110, -110, -110, 978, 981, 1283, 959, 969, 990, 991, 957, 1176, 1172, 544, 1126, -110, -110, 1013, 1014, 657, -110, 925, 986, -110, -110, -110, 1410, 2, 1368, -110, 1268, 951, 1383, 0, 0, 734, -253, 0,-32766, 0, 0,-32766, 863, 1059, 1054, 1053, 1052, 1058, 1055, 1056, 1057, 0, 0, 0, 951, 0, 0, 0, 734, -252, 305, 0, 0, 79, 0, 0, 1071, 0, 0, 332, 0, 0, 0, 0, 0, 0, 0, -110, -110, 0, 0, 0, -110, 0, 0, 0, 0, 0, 0, 0, 299, -110, 0, 0, 0, 0, 0, 0, 0, 0,-32766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 305, 0, 0, 79, 0, 0, 0, 0, 0, 332 ); protected array $actionCheck = array( 3, 4, 5, 6, 7, 8, 17, 10, 11, 12, 13, 14, 84, 76, 1, 87, 72, 74, 75, 82, 0, 108, 109, 110, 15, 82, 89, 90, 91, 10, 93, 118, 95, 103, 97, 38, 39, 100, 10, 11, 12, 104, 105, 106, 107, 10, 11, 12, 111, 112, 15, 10, 11, 12, 117, 118, 59, 82, 128, 31, 1, 33, 34, 35, 36, 37, 129, 124, 1, 31, 73, 74, 75, 76, 77, 78, 79, 164, 1, 82, 9, 153, 154, 139, 140, 9, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 1, 9, 82, 128, 129, 130, 131, 9, 133, 134, 135, 136, 137, 138, 9, 162, 141, 142, 143, 144, 145, 146, 147, 86, 149, 150, 9, 82, 10, 11, 12, 156, 157, 158, 118, 160, 169, 3, 4, 5, 6, 7, 8, 168, 10, 11, 12, 13, 14, 31, 76, 33, 34, 35, 36, 168, 82, 83, 15, 143, 169, 119, 120, 89, 90, 91, 124, 93, 108, 95, 110, 97, 38, 39, 100, 133, 1, 108, 109, 105, 106, 107, 162, 167, 1, 111, 112, 118, 32, 169, 118, 117, 118, 59, 45, 46, 47, 48, 49, 50, 51, 52, 165, 129, 32, 9, 169, 73, 74, 75, 76, 77, 78, 79, 169, 143, 82, 168, 173, 9, 165, 161, 168, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 84, 168, 9, 128, 129, 130, 131, 168, 133, 134, 135, 136, 137, 138, 1, 9, 141, 142, 143, 144, 145, 146, 147, 99, 149, 150, 108, 109, 10, 11, 12, 156, 157, 158, 32, 160, 118, 3, 4, 5, 6, 7, 8, 168, 10, 11, 12, 13, 14, 31, 76, 33, 34, 35, 72, 87, 82, 9, 142, 54, 50, 51, 52, 89, 90, 91, 169, 93, 9, 95, 118, 97, 38, 39, 100, 108, 15, 110, 165, 105, 106, 107, 164, 167, 165, 111, 112, 82, 169, 173, 85, 117, 118, 59, 118, 143, 53, 54, 55, 56, 57, 99, 59, 129, 134, 135, 136, 73, 74, 75, 76, 77, 78, 79, 71, 108, 82, 110, 142, 167, 152, 139, 140, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 9, 118, 72, 128, 129, 130, 131, 1, 133, 134, 135, 136, 137, 138, 9, 9, 141, 142, 143, 144, 145, 146, 147, 169, 149, 150, 143, 173, 10, 11, 12, 156, 157, 158, 9, 160, 72, 3, 4, 5, 6, 7, 8, 168, 10, 11, 12, 13, 14, 31, 167, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 10, 11, 12, 108, 165, 110, 139, 140, 169, 38, 39, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 31, 155, 33, 34, 35, 36, 37, 38, 39, 59, 10, 11, 12, 167, 17, 10, 11, 12, 9, 139, 140, 10, 11, 73, 74, 75, 76, 77, 78, 79, 9, 31, 82, 33, 34, 155, 31, 38, 39, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 166, 118, 168, 128, 129, 130, 131, 9, 133, 134, 135, 136, 137, 138, 82, 9, 141, 142, 143, 144, 145, 146, 147, 72, 149, 150, 143, 10, 11, 12, 9, 156, 157, 158, 9, 160, 3, 4, 5, 6, 7, 8, 82, 10, 11, 12, 13, 14, 31, 9, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 9, 59, 1, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 71, 9, 139, 140, 59, 161, 162, 163, 51, 52, 1, 15, 53, 54, 170, 77, 78, 15, 73, 74, 75, 76, 77, 78, 79, 77, 78, 82, 103, 104, 72, 108, 109, 15, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 1, 72, 84, 128, 129, 130, 131, 17, 133, 134, 135, 136, 137, 138, 108, 109, 141, 142, 143, 144, 145, 146, 147, 31, 149, 150, 15, 139, 140, 15, 31, 156, 157, 158, 2, 3, 4, 5, 6, 7, 8, 15, 103, 155, 17, 13, 14, 108, 16, 110, 113, 114, 17, 17, 115, 167, 17, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 139, 140, 17, 17, 1, 17, 82, 32, 17, 17, 17, 32, 1, 32, 32, 32, 155, 53, 54, 169, 36, 32, 58, 173, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 32, 72, 73, 74, 75, 76, 170, 118, 32, 80, 81, 82, 32, 84, 118, 32, 32, 88, 89, 90, 91, 1, 93, 32, 95, 32, 97, 72, 32, 100, 101, 142, 143, 32, 105, 106, 107, 108, 109, 143, 111, 112, 32, 32, 32, 82, 117, 118, 32, 32, 161, 162, 163, 124, 86, 32, 167, 32, 129, 130, 131, 32, 86, 167, 36, 38, 36, 36, 36, 36, 141, 142, 36, 144, 145, 146, 147, 148, 149, 150, 151, 118, 38, 38, 38, 59, 157, 158, 38, 39, 161, 162, 163, 164, 139, 140, 167, 77, 78, 79, 171, 172, 173, 39, 82, 142, 86, 72, 71, 85, 155, 92, 92, 79, 94, 94, 96, 99, 98, 115, 82, 116, 72, 73, 161, 162, 163, 84, 108, 87, 91, 84, 133, 165, 84, 137, 96, 169, 88, 119, 120, 165, 142, 102, 124, 169, 1, 98, 159, 152, 99, 99, 132, 133, 134, 135, 136, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 102, 1, 159, 124, 38, 39, 32, 72, 164, 167, 172, -1, -1, -1, 165, 138, 1, -1, 169, 170, 141, 142, 137, 144, 145, 146, 147, 148, 149, 150, 61, 62, 32, -1, 152, -1, 157, 158, 155, 155, -1, 72, 76, 0, 1, 155, 167, 32, 82, 155, 155, 172, 173, 161, 165, 89, 90, 91, 167, 93, 86, 95, 160, 97, 165, 165, 100, 166, 38, 39, 165, 105, 106, 107, 139, 140, 165, 111, 112, 165, 165, 165, 165, 117, 118, 165, 86, 165, 165, 165, 155, 165, 165, 165, 165, 129, 165, 165, 165, 169, 166, 86, 167, 166, 166, 166, 76, 166, 139, 140, 167, 167, 82, 167, 167, 167, 72, 73, 167, 89, 90, 91, 167, 93, 155, 95, 160, 97, 84, 86, 100, 167, 88, 168, 167, 105, 106, 107, 167, 165, 167, 111, 112, 169, 167, 167, 167, 117, 118, 167, 167, 108, 167, 110, 72, 73, 167, 167, 115, 129, 167, 167, 119, 120, 167, 165, 84, 124, 124, 169, 88, 167, 167, 167, 167, 132, 133, 134, 135, 136, 165, 167, 169, 167, 169, 167, 142, 167, 144, 145, 146, 147, 148, 149, 150, 167, 167, 170, 167, 156, 32, 157, 158, 167, 167, 167, 124, 167, 165, 167, 169, 167, 169, 170, 168, 168, 172, 173, 168, 168, 168, 168, 168, 168, 142, 168, 144, 145, 146, 147, 148, 149, 150, 32, 168, 168, 168, 168, 168, 157, 158, 1, 168, 168, 76, 168, 168, 168, 168, 167, 82, 168, 168, 168, 172, 173, 168, 89, 90, 91, 168, 93, 168, 95, 1, 97, 168, 168, 100, 168, 168, 1, 168, 105, 106, 107, 168, 76, 168, 111, 112, 168, 168, 82, 168, 117, 118, 168, 168, 168, 89, 90, 91, 168, 93, 168, 95, 129, 97, 168, 168, 100, 32, 168, 168, 168, 105, 106, 107, 169, 76, 169, 111, 112, 169, 169, 82, 169, 117, 118, 169, 169, 169, 89, 90, 91, 86, 93, 31, 95, 129, 97, 169, 1, 100, 169, 169, 173, 169, 105, 106, 107, 102, 103, 104, 111, 112, 170, 108, 86, 170, 117, 118, 170, 84, 170, 170, 170, 170, 119, 120, 170, 170, 129, 124, 102, 103, 104, 170, 170, 170, 108, 132, 133, 134, 135, 136, 170, 170, 170, 170, 170, 119, 120, 170, 170, 170, 124, 170, 119, 120, 170, 170, 170, 124, 132, 133, 134, 135, 136, 170, 167, 170, 133, 171, 165, 170, -1, -1, 169, 170, -1, 142, -1, -1, 118, 84, 120, 121, 122, 123, 124, 125, 126, 127, -1, -1, -1, 165, -1, -1, -1, 169, 170, 164, -1, -1, 167, -1, -1, 143, -1, -1, 173, -1, -1, -1, -1, -1, -1, -1, 119, 120, -1, -1, -1, 124, -1, -1, -1, -1, -1, -1, -1, 167, 133, -1, -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 164, -1, -1, 167, -1, -1, -1, -1, -1, 173 ); protected array $actionBase = array( 0, 156, -3, 315, 474, 474, 880, 1074, 1271, 1294, 749, 675, 531, 559, 836, 1031, 1031, 1046, 1031, 828, 1005, 42, 59, 59, 59, 963, 898, 632, 632, 898, 632, 997, 997, 997, 997, 1061, 1061, -63, -63, 96, 1232, 1199, 255, 255, 255, 255, 255, 1265, 255, 255, 255, 255, 255, 1265, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 77, 194, 120, 205, 1197, 783, 1150, 1163, 1152, 1166, 1145, 1144, 1151, 1156, 1167, 1261, 1263, 889, 1254, 1267, 1158, 972, 1147, 1162, 962, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 19, 35, 535, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 529, 529, 529, 910, 910, 524, 299, 1113, 1075, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 140, 28, 1000, 493, 493, 458, 458, 458, 458, 458, 696, 1328, 1301, 171, 171, 171, 171, 1363, 1363, -70, 523, 248, 756, 291, 197, -87, 644, 38, 199, 323, 323, 482, 482, 233, 233, 482, 482, 482, 324, 324, 94, 94, 94, 94, 82, 249, 860, 67, 67, 67, 67, 860, 860, 860, 860, 913, 869, 860, 1036, 1049, 860, 860, 370, 645, 966, 646, 646, 398, -72, -72, 398, 64, -72, 294, 286, 257, 859, 91, 433, 257, 1073, 404, 686, 686, 815, 686, 686, 686, 923, 610, 923, 1141, 902, 902, 861, 807, 964, 1198, 1168, 901, 1252, 929, 1253, 1200, 342, 251, -56, 263, 550, 806, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1195, 523, 1141, -25, 1247, 1249, 1195, 1195, 1195, 523, 523, 523, 523, 523, 523, 523, 523, 870, 523, 523, 694, -25, 625, 635, -25, 896, 523, 915, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 178, 77, 77, 194, 13, 13, 77, 200, 121, 13, 13, 13, -11, 13, 77, 77, 77, 610, 886, 849, 663, 283, 874, 114, 886, 886, 886, 71, 9, 76, 809, 888, 288, 882, 882, 882, 907, 986, 986, 882, 903, 882, 907, 882, 882, 986, 986, 875, 986, 274, 620, 465, 597, 624, 986, 340, 882, 882, 882, 882, 916, 986, 127, 139, 639, 882, 329, 287, 882, 882, 916, 858, 876, 908, 986, 986, 986, 916, 545, 908, 908, 908, 931, 936, 864, 872, 445, 431, 679, 232, 924, 872, 872, 882, 605, 864, 872, 864, 872, 933, 872, 872, 872, 864, 872, 903, 533, 872, 813, 665, 218, 872, 882, 20, 1008, 1009, 800, 1010, 1002, 1013, 1069, 1014, 1016, 1171, 982, 1028, 1004, 1020, 1071, 998, 995, 885, 792, 793, 921, 914, 979, 897, 897, 897, 975, 977, 897, 897, 897, 897, 897, 897, 897, 897, 792, 932, 926, 899, 1037, 796, 810, 1114, 857, 1214, 1264, 1036, 1008, 1016, 804, 1004, 1020, 998, 995, 856, 853, 844, 851, 843, 840, 808, 814, 871, 1116, 1119, 1021, 920, 811, 1085, 1038, 1211, 1044, 1045, 1047, 1088, 1123, 942, 1125, 1216, 895, 1217, 1218, 965, 1051, 1173, 897, 974, 873, 968, 1049, 978, 792, 969, 1129, 1130, 1081, 961, 1097, 1098, 1072, 911, 884, 970, 1219, 1059, 1060, 1062, 1176, 1177, 930, 1082, 996, 1099, 912, 1058, 1100, 1101, 1105, 1106, 1179, 1222, 1182, 922, 1183, 945, 879, 1077, 909, 1223, 165, 892, 893, 906, 1068, 683, 1035, 1184, 1208, 1229, 1108, 1109, 1110, 1230, 1231, 1024, 946, 1083, 900, 1084, 1078, 947, 948, 689, 905, 1132, 890, 891, 904, 705, 768, 1238, 1239, 1240, 1025, 877, 894, 951, 953, 1133, 887, 1135, 1241, 771, 954, 1242, 1115, 816, 817, 521, 784, 747, 818, 881, 1194, 925, 865, 878, 1067, 817, 883, 955, 1245, 957, 958, 959, 1111, 960, 1086, 1246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 789, 789, 789, 789, 789, 789, 789, 789, 789, 632, 632, 632, 632, 789, 789, 789, 789, 789, 789, 789, 632, 789, 789, 789, 632, 632, 0, 0, 632, 0, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 823, 823, 616, 616, 823, 823, 823, 823, 823, 823, 823, 823, 823, 823, 616, 616, 0, 616, 616, 616, 616, 616, 616, 616, 875, 823, 823, 324, 324, 324, 324, 823, 823, 396, 396, 396, 823, 324, 823, 64, 324, 823, 64, 823, 823, 823, 823, 823, 823, 823, 823, 823, 0, 0, 823, 823, 823, 823, -25, -72, 823, 903, 903, 903, 903, 823, 823, 823, 823, -72, -72, 823, -57, -57, 823, 823, 0, 0, 0, 324, 324, -25, 0, 0, -25, 0, 0, 903, 903, 823, 64, 875, 446, 823, 342, 0, 0, 0, 0, 0, 0, 0, -25, 903, -25, 523, -72, -72, 523, 523, 13, 77, 446, 612, 612, 612, 612, 77, 0, 0, 0, 0, 0, 610, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 903, 0, 875, 0, 875, 875, 903, 903, 903, 0, 0, 0, 0, 0, 0, 0, 0, 986, 0, 0, 0, 0, 0, 0, 0, 903, 0, 986, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 903, 0, 0, 0, 0, 0, 0, 0, 0, 0, 897, 911, 0, 0, 911, 0, 897, 897, 897, 0, 0, 0, 905, 887 ); protected array $actionDefault = array( 3,32767,32767,32767, 102, 102,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767, 100, 32767, 632, 632, 632, 632,32767,32767, 257, 102,32767, 32767, 503, 417, 417, 417,32767,32767,32767, 576, 576, 576, 576, 576, 17,32767,32767,32767,32767,32767,32767, 32767, 503,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767, 36, 7, 8, 10, 11, 49, 338, 100, 32767,32767,32767,32767,32767,32767,32767,32767, 102,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767, 404, 625,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767, 497, 507, 485, 486, 488, 489, 416, 577, 631, 344, 628, 342, 415, 146, 354, 343, 245, 261, 508, 262, 509, 512, 513, 218, 401, 150, 151, 448, 504, 450, 502, 506, 449, 422, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 420, 421, 505, 482, 481, 480,32767,32767, 446, 447,32767, 32767,32767,32767,32767,32767,32767,32767, 102,32767, 451, 454, 419, 452, 453, 470, 471, 468, 469, 472,32767, 323,32767, 473, 474, 475, 476,32767,32767, 382, 196, 380,32767, 477,32767, 111, 455, 323, 111,32767,32767, 32767,32767,32767,32767,32767,32767,32767, 461, 462,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767, 102,32767,32767,32767, 100, 520, 570, 479, 456, 457,32767, 545,32767, 102, 32767, 547,32767,32767,32767,32767,32767,32767,32767,32767, 572, 443, 445, 540, 626, 423, 629,32767, 533, 100, 196,32767, 546, 196, 196,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767, 571,32767, 639, 533, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,32767, 196, 110,32767, 110, 110,32767,32767, 100, 196, 196, 196, 196, 196, 196, 196, 196, 548, 196, 196, 191,32767, 271, 273, 102, 594, 196, 550,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767, 404,32767,32767,32767,32767, 533, 466, 139, 32767, 535, 139, 578, 458, 459, 460, 578, 578, 578, 319, 296,32767,32767,32767,32767,32767, 548, 548, 100, 100, 100, 100,32767,32767,32767,32767, 111, 519, 99, 99, 99, 99, 99, 103, 101,32767,32767,32767,32767, 226,32767, 101, 101, 99,32767, 101, 101,32767,32767, 226, 228, 215, 230,32767, 598, 599, 226, 101, 230, 230, 230, 250, 250, 522, 325, 101, 99, 101, 101, 198, 325, 325,32767, 101, 522, 325, 522, 325, 200, 325, 325, 325, 522, 325,32767, 101, 325, 217, 99, 99, 325,32767,32767,32767,32767, 535,32767,32767,32767, 32767,32767,32767,32767, 225,32767,32767,32767,32767,32767, 32767,32767,32767, 565,32767, 583, 596, 464, 465, 467, 582, 580, 490, 491, 492, 493, 494, 495, 496, 499, 627,32767, 539,32767,32767,32767, 353,32767, 637,32767, 32767,32767, 9, 74, 528, 42, 43, 51, 57, 554, 555, 556, 557, 551, 552, 558, 553,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767, 638,32767, 578,32767,32767,32767,32767, 463, 560, 604,32767,32767, 579, 630,32767,32767,32767, 32767,32767,32767,32767,32767, 139,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767, 565,32767, 137,32767, 32767,32767,32767,32767,32767,32767,32767, 561,32767,32767, 32767, 578,32767,32767,32767,32767, 321, 318,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767, 578,32767,32767,32767,32767,32767, 298,32767, 315,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767, 400, 535, 301, 303, 304,32767,32767,32767,32767, 376,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767, 153, 153, 3, 3, 356, 153, 153, 153, 356, 356, 153, 356, 356, 356, 153, 153, 153, 153, 153, 153, 153, 283, 186, 265, 268, 250, 250, 153, 368, 153, 402, 402, 411 ); protected array $goto = array( 201, 169, 201, 201, 201, 1069, 598, 719, 448, 684, 644, 681, 443, 345, 341, 342, 344, 615, 447, 346, 449, 661, 481, 728, 570, 570, 570, 570, 1245, 626, 172, 172, 172, 172, 225, 202, 198, 198, 182, 184, 220, 198, 198, 198, 198, 198, 1195, 199, 199, 199, 199, 199, 1195, 192, 193, 194, 195, 196, 197, 222, 220, 223, 557, 558, 438, 559, 562, 563, 564, 565, 566, 567, 568, 569, 173, 174, 175, 200, 176, 177, 178, 170, 179, 180, 181, 183, 219, 221, 224, 242, 247, 248, 259, 260, 262, 263, 264, 265, 266, 267, 268, 272, 273, 274, 275, 282, 285, 297, 298, 324, 325, 444, 445, 446, 620, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 193, 194, 195, 196, 197, 222, 203, 204, 205, 206, 243, 185, 186, 207, 187, 208, 204, 188, 244, 203, 168, 209, 210, 189, 211, 212, 213, 190, 214, 215, 171, 216, 217, 218, 191, 287, 284, 287, 287, 883, 255, 255, 255, 255, 255, 1125, 605, 487, 487, 622, 758, 660, 662, 1103, 359, 682, 487, 1075, 1074, 706, 709, 1041, 717, 726, 1037, 733, 922, 879, 922, 922, 253, 253, 253, 253, 250, 256, 646, 646, 1078, 1079, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 880, 351, 938, 933, 934, 947, 889, 935, 886, 936, 937, 887, 890, 476, 941, 894, 476, 1044, 1044, 893, 364, 364, 364, 364, 352, 351, 532, 1131, 1127, 1128, 1351, 1351, 331, 315, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1069, 1301, 1072, 1072, 704, 983, 1301, 1301, 1064, 1080, 1081, 1069, 942, 1301, 943, 458, 1069, 881, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 897, 855, 1069, 1069, 1069, 1069, 677, 678, 1301, 695, 696, 697, 1006, 1301, 1301, 1301, 1301, 450, 909, 1301, 436, 896, 1301, 1301, 1382, 1382, 1382, 1382, 915, 581, 574, 499, 612, 450, 367, 971, 971, 955, 501, 1076, 1076, 956, 1400, 1400, 367, 367, 688, 1087, 1083, 1084, 572, 411, 414, 623, 627, 572, 572, 367, 367, 1400, 357, 367, 572, 1417, 1377, 1378, 317, 574, 581, 607, 608, 318, 618, 624, 1390, 640, 641, 1027, 576, 1403, 1403, 367, 367, 28, 474, 520, 442, 521, 635, 1000, 1000, 1000, 1000, 527, 409, 474, 1348, 1348, 994, 1001, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 633, 647, 650, 651, 652, 653, 674, 675, 676, 730, 732, 561, 561, 258, 258, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 610, 1362, 467, 683, 467, 876, 616, 638, 876, 467, 467, 1191, 861, 1373, 360, 361, 1093, 456, 1373, 1373, 560, 560, 705, 432, 560, 1373, 560, 560, 560, 560, 560, 560, 560, 560, 1277, 975, 575, 602, 575, 1278, 1281, 976, 575, 1282, 602, 689, 412, 480, 1384, 1384, 1384, 1384, 347, 873, 716, 576, 861, 876, 861, 490, 619, 491, 492, 639, 8, 857, 9, 902, 907, 989, 716, 1408, 1409, 716, 1369, 418, 1296, 278, 899, 330, 1174, 424, 425, 1292, 330, 330, 693, 1049, 694, 1114, 429, 430, 431, 761, 707, 1060, 905, 433, 1102, 1104, 1107, 355, 467, 467, 467, 467, 467, 467, 467, 467, 467, 467, 467, 467, 419, 339, 467, 911, 467, 467, 1294, 628, 629, 1116, 497, 960, 1181, 621, 1144, 1371, 1371, 1116, 1118, 1297, 1298, 1011, 1284, 1046, 1151, 1179, 1152, 731, 871, 528, 722, 901, 1142, 687, 1025, 1284, 496, 1375, 1376, 895, 910, 898, 1113, 1117, 998, 427, 727, 1165, 1299, 1359, 1360, 1291, 1030, 386, 1009, 1002, 0, 757, 0, 0, 573, 1039, 1034, 654, 656, 658, 0, 0, 0, 0, 0, 0, 0, 0, 876, 0, 0, 999, 0, 766, 766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1163, 914 ); protected array $gotoCheck = array( 42, 42, 42, 42, 42, 73, 127, 73, 66, 66, 56, 56, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 159, 9, 107, 107, 107, 107, 159, 107, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 23, 23, 23, 23, 15, 5, 5, 5, 5, 5, 15, 48, 157, 157, 134, 48, 48, 48, 131, 97, 48, 157, 119, 119, 48, 48, 48, 48, 48, 48, 48, 25, 25, 25, 25, 5, 5, 5, 5, 5, 5, 108, 108, 120, 120, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 26, 177, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 83, 15, 15, 83, 107, 107, 15, 24, 24, 24, 24, 177, 177, 76, 15, 15, 15, 179, 179, 178, 178, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 73, 73, 89, 89, 89, 89, 73, 73, 89, 89, 89, 73, 65, 73, 65, 83, 73, 27, 73, 73, 73, 73, 73, 73, 73, 73, 73, 35, 6, 73, 73, 73, 73, 86, 86, 73, 86, 86, 86, 49, 73, 73, 73, 73, 118, 35, 73, 43, 35, 73, 73, 9, 9, 9, 9, 45, 76, 76, 84, 181, 118, 14, 9, 9, 73, 84, 118, 118, 73, 191, 191, 14, 14, 118, 118, 118, 118, 19, 59, 59, 59, 59, 19, 19, 14, 14, 191, 188, 14, 19, 14, 187, 187, 76, 76, 76, 76, 76, 76, 76, 76, 190, 76, 76, 103, 14, 191, 191, 14, 14, 76, 19, 163, 13, 163, 13, 19, 19, 19, 19, 163, 62, 19, 180, 180, 19, 19, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 182, 182, 5, 5, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 104, 14, 23, 64, 23, 22, 2, 2, 22, 23, 23, 158, 12, 134, 97, 97, 115, 113, 134, 134, 165, 165, 117, 14, 165, 134, 165, 165, 165, 165, 165, 165, 165, 165, 79, 79, 9, 9, 9, 79, 79, 79, 9, 79, 9, 121, 9, 9, 134, 134, 134, 134, 29, 18, 7, 14, 12, 22, 12, 9, 9, 9, 9, 80, 46, 7, 46, 39, 9, 92, 7, 9, 9, 7, 134, 28, 20, 24, 37, 24, 156, 82, 82, 169, 24, 24, 82, 110, 82, 133, 82, 82, 82, 99, 82, 114, 9, 82, 130, 130, 130, 82, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 31, 9, 23, 41, 23, 23, 14, 17, 17, 134, 160, 17, 17, 8, 8, 134, 134, 134, 136, 20, 20, 96, 20, 17, 149, 149, 149, 8, 20, 8, 8, 17, 8, 17, 17, 20, 185, 185, 185, 17, 16, 16, 16, 16, 93, 93, 93, 152, 20, 20, 20, 17, 50, 141, 16, 50, -1, 50, -1, -1, 50, 50, 50, 85, 85, 85, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, 16, -1, 24, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 16 ); protected array $gotoBase = array( 0, 0, -303, 0, 0, 170, 280, 471, 543, 10, 0, 0, 136, 31, 22, -186, 111, 66, 164, 71, 95, 0, 148, 160, 235, 191, 214, 275, 155, 176, 0, 86, 0, 0, 0, -92, 0, 156, 0, 165, 0, 85, -1, 286, 0, 291, -270, 0, -558, 284, 579, 0, 0, 0, 0, 0, -33, 0, 0, 294, 0, 0, 341, 0, 184, 261, -237, 0, 0, 0, 0, 0, 0, -5, 0, 0, -32, 0, 0, 37, 172, 32, -3, -50, -167, 105, -444, 0, 0, -21, 0, 0, 161, 274, 0, 0, 101, -318, 0, 97, 0, 0, 0, 331, 381, 0, 0, -7, -38, 0, 131, 0, 0, 158, 90, 162, 0, 159, 39, -100, -83, 173, 0, 0, 0, 0, 0, 4, 0, 0, 522, 182, 0, 127, 169, 0, 99, 0, 0, 0, 0, -171, 0, 0, 0, 0, 0, 0, 0, 287, 0, 0, 126, 0, 0, 0, 144, 141, 188, -255, 93, 0, 0, -138, 0, 202, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, -82, -74, 6, 143, 292, 168, 0, 0, 270, 0, -31, 319, 0, 332, 20, 0, 0 ); protected array $gotoDefault = array( -32768, 533, 768, 7, 769, 964, 844, 853, 597, 551, 729, 356, 648, 439, 1367, 940, 1180, 617, 872, 1310, 1316, 475, 875, 336, 755, 952, 923, 924, 415, 402, 888, 413, 672, 649, 514, 908, 471, 900, 506, 903, 470, 912, 167, 435, 530, 916, 6, 919, 579, 950, 1004, 403, 927, 404, 700, 929, 601, 931, 932, 410, 416, 417, 1185, 609, 645, 944, 261, 603, 945, 401, 946, 954, 406, 408, 710, 486, 525, 519, 428, 1146, 604, 632, 669, 464, 493, 643, 655, 642, 500, 451, 434, 335, 988, 996, 507, 484, 1010, 358, 1018, 763, 1193, 663, 509, 1026, 664, 1033, 1036, 552, 553, 498, 1048, 270, 1051, 510, 1061, 26, 690, 1066, 1067, 691, 665, 1089, 666, 692, 667, 1091, 483, 599, 1194, 482, 1106, 1112, 472, 1115, 1356, 473, 1119, 269, 1122, 286, 362, 385, 452, 1129, 1130, 12, 1136, 720, 721, 25, 280, 529, 1164, 711, 1170, 279, 1173, 469, 1192, 468, 1265, 1267, 580, 511, 1285, 321, 1288, 703, 526, 1293, 465, 1358, 466, 554, 494, 343, 555, 1401, 314, 365, 340, 571, 322, 366, 556, 495, 1364, 1372, 337, 34, 1391, 1402, 614, 637 ); protected array $ruleToNonTerminal = array( 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18, 21, 21, 22, 23, 23, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 30, 30, 32, 34, 34, 28, 36, 36, 33, 38, 38, 35, 35, 37, 37, 39, 39, 31, 40, 40, 41, 43, 44, 44, 45, 45, 46, 46, 48, 47, 47, 47, 47, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 25, 25, 50, 69, 69, 72, 72, 71, 70, 70, 63, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 80, 80, 26, 26, 27, 27, 27, 27, 27, 88, 88, 90, 90, 83, 83, 91, 91, 92, 92, 92, 84, 84, 87, 87, 85, 85, 93, 94, 94, 57, 57, 65, 65, 68, 68, 68, 67, 95, 95, 96, 58, 58, 58, 58, 97, 97, 98, 98, 99, 99, 100, 101, 101, 102, 102, 103, 103, 55, 55, 51, 51, 105, 53, 53, 106, 52, 52, 54, 54, 64, 64, 64, 64, 81, 81, 109, 109, 111, 111, 112, 112, 112, 112, 112, 112, 112, 112, 110, 110, 110, 115, 115, 115, 115, 89, 89, 118, 118, 118, 119, 119, 116, 116, 120, 120, 122, 122, 123, 123, 117, 124, 124, 121, 125, 125, 125, 125, 113, 113, 82, 82, 82, 20, 20, 20, 128, 128, 128, 128, 129, 129, 129, 127, 126, 126, 131, 131, 131, 130, 130, 60, 132, 132, 133, 61, 135, 135, 136, 136, 137, 137, 86, 138, 138, 138, 138, 138, 138, 138, 138, 144, 144, 145, 145, 146, 146, 146, 146, 146, 147, 148, 148, 143, 143, 139, 139, 142, 142, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 140, 151, 151, 153, 152, 152, 141, 141, 114, 114, 154, 154, 156, 156, 156, 155, 155, 62, 104, 157, 157, 56, 56, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 164, 165, 165, 166, 158, 158, 163, 163, 167, 168, 168, 169, 170, 171, 171, 171, 171, 19, 19, 73, 73, 73, 73, 159, 159, 159, 159, 173, 173, 162, 162, 162, 160, 160, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 180, 180, 180, 108, 182, 182, 182, 182, 161, 161, 161, 161, 161, 161, 161, 161, 59, 59, 176, 176, 176, 176, 176, 183, 183, 172, 172, 172, 172, 184, 184, 184, 184, 184, 74, 74, 66, 66, 66, 66, 134, 134, 134, 134, 187, 186, 175, 175, 175, 175, 175, 175, 174, 174, 174, 185, 185, 185, 185, 107, 181, 189, 189, 188, 188, 190, 190, 190, 190, 190, 190, 190, 190, 178, 178, 178, 178, 177, 192, 191, 191, 191, 191, 191, 191, 191, 191, 193, 193, 193, 193 ); protected array $ruleToLength = array( 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 2, 1, 3, 4, 1, 2, 0, 1, 1, 1, 1, 4, 3, 5, 4, 3, 4, 1, 3, 4, 1, 1, 8, 7, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 3, 1, 3, 1, 2, 2, 3, 1, 3, 2, 3, 1, 3, 3, 2, 0, 1, 1, 1, 1, 1, 3, 7, 10, 5, 7, 9, 5, 3, 3, 3, 3, 3, 3, 1, 2, 5, 7, 9, 6, 5, 6, 3, 2, 1, 1, 1, 1, 0, 2, 1, 3, 8, 0, 4, 2, 1, 3, 0, 1, 0, 1, 0, 1, 3, 1, 1, 1, 1, 1, 8, 9, 7, 8, 7, 6, 8, 0, 2, 0, 2, 1, 2, 1, 2, 1, 1, 1, 0, 2, 0, 2, 0, 2, 2, 1, 3, 1, 4, 1, 4, 1, 1, 4, 2, 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, 1, 7, 0, 2, 1, 3, 3, 4, 1, 4, 0, 2, 5, 0, 2, 6, 0, 2, 0, 3, 1, 2, 1, 1, 2, 0, 1, 3, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 7, 9, 6, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, 1, 1, 2, 1, 1, 0, 1, 0, 2, 2, 2, 4, 3, 2, 4, 4, 3, 3, 1, 3, 1, 1, 3, 2, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 3, 2, 0, 1, 5, 7, 5, 6, 10, 3, 5, 1, 1, 3, 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, 1, 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 3, 1, 1, 3, 0, 2, 0, 3, 5, 8, 1, 3, 3, 0, 2, 2, 2, 3, 1, 0, 1, 1, 3, 3, 3, 4, 4, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 2, 1, 2, 4, 2, 2, 8, 9, 8, 9, 9, 10, 9, 10, 8, 3, 2, 2, 1, 1, 0, 4, 2, 1, 3, 2, 1, 2, 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 3, 3, 4, 1, 1, 3, 1, 1, 1, 1, 1, 3, 2, 3, 0, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 4, 1, 4, 4, 0, 1, 1, 1, 3, 3, 1, 4, 2, 2, 1, 3, 1, 4, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, 1, 4, 1, 1, 1, 3, 1, 1, 2, 1, 3, 4, 3, 2, 0, 2, 2, 1, 2, 1, 1, 1, 4, 3, 3, 3, 3, 6, 3, 1, 1, 2, 1 ); protected function initReduceCallbacks(): void { $this->reduceCallbacks = [ 0 => null, 1 => static function ($self, $stackPos) { $self->semValue = $self->handleNamespaces($self->semStack[$stackPos-(1-1)]); }, 2 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(2-2)] !== null) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; } $self->semValue = $self->semStack[$stackPos-(2-1)];; }, 3 => static function ($self, $stackPos) { $self->semValue = array(); }, 4 => static function ($self, $stackPos) { $nop = $self->maybeCreateZeroLengthNop($self->tokenPos);; if ($nop !== null) { $self->semStack[$stackPos-(1-1)][] = $nop; } $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 5 => null, 6 => null, 7 => null, 8 => null, 9 => null, 10 => null, 11 => null, 12 => null, 13 => null, 14 => null, 15 => null, 16 => null, 17 => null, 18 => null, 19 => null, 20 => null, 21 => null, 22 => null, 23 => null, 24 => null, 25 => null, 26 => null, 27 => null, 28 => null, 29 => null, 30 => null, 31 => null, 32 => null, 33 => null, 34 => null, 35 => null, 36 => null, 37 => null, 38 => null, 39 => null, 40 => null, 41 => null, 42 => null, 43 => null, 44 => null, 45 => null, 46 => null, 47 => null, 48 => null, 49 => null, 50 => null, 51 => null, 52 => null, 53 => null, 54 => null, 55 => null, 56 => null, 57 => null, 58 => null, 59 => null, 60 => null, 61 => null, 62 => null, 63 => null, 64 => null, 65 => null, 66 => null, 67 => null, 68 => null, 69 => null, 70 => null, 71 => null, 72 => null, 73 => null, 74 => null, 75 => null, 76 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; if ($self->semValue === "emitError(new Error('Cannot use "getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]))); }, 77 => null, 78 => null, 79 => null, 80 => null, 81 => null, 82 => null, 83 => null, 84 => null, 85 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 86 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 87 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 88 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 89 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 90 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 91 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 92 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 93 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 94 => null, 95 => static function ($self, $stackPos) { $self->semValue = new Name(substr($self->semStack[$stackPos-(1-1)], 1), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 96 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable(substr($self->semStack[$stackPos-(1-1)], 1), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 97 => static function ($self, $stackPos) { /* nothing */ }, 98 => static function ($self, $stackPos) { /* nothing */ }, 99 => static function ($self, $stackPos) { /* nothing */ }, 100 => static function ($self, $stackPos) { $self->emitError(new Error('A trailing comma is not allowed here', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]))); }, 101 => null, 102 => null, 103 => static function ($self, $stackPos) { $self->semValue = new Node\Attribute($self->semStack[$stackPos-(1-1)], [], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 104 => static function ($self, $stackPos) { $self->semValue = new Node\Attribute($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 105 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 106 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 107 => static function ($self, $stackPos) { $self->semValue = new Node\AttributeGroup($self->semStack[$stackPos-(4-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 108 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 109 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 110 => static function ($self, $stackPos) { $self->semValue = []; }, 111 => null, 112 => null, 113 => null, 114 => null, 115 => static function ($self, $stackPos) { $self->semValue = new Stmt\HaltCompiler($self->handleHaltCompiler(), $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 116 => static function ($self, $stackPos) { $self->semValue = new Stmt\Namespace_($self->semStack[$stackPos-(3-2)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); $self->checkNamespace($self->semValue); }, 117 => static function ($self, $stackPos) { $self->semValue = new Stmt\Namespace_($self->semStack[$stackPos-(5-2)], $self->semStack[$stackPos-(5-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $self->checkNamespace($self->semValue); }, 118 => static function ($self, $stackPos) { $self->semValue = new Stmt\Namespace_(null, $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); $self->checkNamespace($self->semValue); }, 119 => static function ($self, $stackPos) { $self->semValue = new Stmt\Use_($self->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 120 => static function ($self, $stackPos) { $self->semValue = new Stmt\Use_($self->semStack[$stackPos-(4-3)], $self->semStack[$stackPos-(4-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 121 => null, 122 => static function ($self, $stackPos) { $self->semValue = new Stmt\Const_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]), []); }, 123 => static function ($self, $stackPos) { $self->semValue = new Stmt\Const_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(4-1)]); $self->checkConstantAttributes($self->semValue); }, 124 => static function ($self, $stackPos) { $self->semValue = Stmt\Use_::TYPE_FUNCTION; }, 125 => static function ($self, $stackPos) { $self->semValue = Stmt\Use_::TYPE_CONSTANT; }, 126 => static function ($self, $stackPos) { $self->semValue = new Stmt\GroupUse($self->semStack[$stackPos-(8-3)], $self->semStack[$stackPos-(8-6)], $self->semStack[$stackPos-(8-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 127 => static function ($self, $stackPos) { $self->semValue = new Stmt\GroupUse($self->semStack[$stackPos-(7-2)], $self->semStack[$stackPos-(7-5)], Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 128 => null, 129 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 130 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 131 => null, 132 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 133 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 134 => null, 135 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 136 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 137 => static function ($self, $stackPos) { $self->semValue = new Node\UseItem($self->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->checkUseUse($self->semValue, $stackPos-(1-1)); }, 138 => static function ($self, $stackPos) { $self->semValue = new Node\UseItem($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->checkUseUse($self->semValue, $stackPos-(3-3)); }, 139 => static function ($self, $stackPos) { $self->semValue = new Node\UseItem($self->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->checkUseUse($self->semValue, $stackPos-(1-1)); }, 140 => static function ($self, $stackPos) { $self->semValue = new Node\UseItem($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->checkUseUse($self->semValue, $stackPos-(3-3)); }, 141 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; $self->semValue->type = Stmt\Use_::TYPE_NORMAL; }, 142 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; $self->semValue->type = $self->semStack[$stackPos-(2-1)]; }, 143 => null, 144 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 145 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 146 => static function ($self, $stackPos) { $self->semValue = new Node\Const_($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 147 => null, 148 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 149 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 150 => static function ($self, $stackPos) { $self->semValue = new Node\Const_(new Node\Identifier($self->semStack[$stackPos-(3-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos-(3-1)])), $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 151 => static function ($self, $stackPos) { $self->semValue = new Node\Const_(new Node\Identifier($self->semStack[$stackPos-(3-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos-(3-1)])), $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 152 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(2-2)] !== null) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; } $self->semValue = $self->semStack[$stackPos-(2-1)];; }, 153 => static function ($self, $stackPos) { $self->semValue = array(); }, 154 => static function ($self, $stackPos) { $nop = $self->maybeCreateZeroLengthNop($self->tokenPos);; if ($nop !== null) { $self->semStack[$stackPos-(1-1)][] = $nop; } $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 155 => null, 156 => null, 157 => null, 158 => static function ($self, $stackPos) { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 159 => static function ($self, $stackPos) { $self->semValue = new Stmt\Block($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 160 => static function ($self, $stackPos) { $self->semValue = new Stmt\If_($self->semStack[$stackPos-(7-3)], ['stmts' => $self->semStack[$stackPos-(7-5)], 'elseifs' => $self->semStack[$stackPos-(7-6)], 'else' => $self->semStack[$stackPos-(7-7)]], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 161 => static function ($self, $stackPos) { $self->semValue = new Stmt\If_($self->semStack[$stackPos-(10-3)], ['stmts' => $self->semStack[$stackPos-(10-6)], 'elseifs' => $self->semStack[$stackPos-(10-7)], 'else' => $self->semStack[$stackPos-(10-8)]], $self->getAttributes($self->tokenStartStack[$stackPos-(10-1)], $self->tokenEndStack[$stackPos])); }, 162 => static function ($self, $stackPos) { $self->semValue = new Stmt\While_($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 163 => static function ($self, $stackPos) { $self->semValue = new Stmt\Do_($self->semStack[$stackPos-(7-5)], $self->semStack[$stackPos-(7-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 164 => static function ($self, $stackPos) { $self->semValue = new Stmt\For_(['init' => $self->semStack[$stackPos-(9-3)], 'cond' => $self->semStack[$stackPos-(9-5)], 'loop' => $self->semStack[$stackPos-(9-7)], 'stmts' => $self->semStack[$stackPos-(9-9)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 165 => static function ($self, $stackPos) { $self->semValue = new Stmt\Switch_($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 166 => static function ($self, $stackPos) { $self->semValue = new Stmt\Break_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 167 => static function ($self, $stackPos) { $self->semValue = new Stmt\Continue_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 168 => static function ($self, $stackPos) { $self->semValue = new Stmt\Return_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 169 => static function ($self, $stackPos) { $self->semValue = new Stmt\Global_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 170 => static function ($self, $stackPos) { $self->semValue = new Stmt\Static_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 171 => static function ($self, $stackPos) { $self->semValue = new Stmt\Echo_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 172 => static function ($self, $stackPos) { $self->semValue = new Stmt\InlineHTML($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('hasLeadingNewline', $self->inlineHtmlHasLeadingNewline($stackPos-(1-1))); }, 173 => static function ($self, $stackPos) { $self->semValue = new Stmt\Expression($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 174 => static function ($self, $stackPos) { $self->semValue = new Stmt\Unset_($self->semStack[$stackPos-(5-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 175 => static function ($self, $stackPos) { $self->semValue = new Stmt\Foreach_($self->semStack[$stackPos-(7-3)], $self->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $self->semStack[$stackPos-(7-5)][1], 'stmts' => $self->semStack[$stackPos-(7-7)]], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 176 => static function ($self, $stackPos) { $self->semValue = new Stmt\Foreach_($self->semStack[$stackPos-(9-3)], $self->semStack[$stackPos-(9-7)][0], ['keyVar' => $self->semStack[$stackPos-(9-5)], 'byRef' => $self->semStack[$stackPos-(9-7)][1], 'stmts' => $self->semStack[$stackPos-(9-9)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 177 => static function ($self, $stackPos) { $self->semValue = new Stmt\Foreach_($self->semStack[$stackPos-(6-3)], new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(6-4)], $self->tokenEndStack[$stackPos-(6-4)])), ['stmts' => $self->semStack[$stackPos-(6-6)]], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); }, 178 => static function ($self, $stackPos) { $self->semValue = new Stmt\Declare_($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 179 => static function ($self, $stackPos) { $self->semValue = new Stmt\TryCatch($self->semStack[$stackPos-(6-3)], $self->semStack[$stackPos-(6-5)], $self->semStack[$stackPos-(6-6)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); $self->checkTryCatch($self->semValue); }, 180 => static function ($self, $stackPos) { $self->semValue = new Stmt\Goto_($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 181 => static function ($self, $stackPos) { $self->semValue = new Stmt\Label($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 182 => static function ($self, $stackPos) { $self->semValue = null; /* means: no statement */ }, 183 => null, 184 => static function ($self, $stackPos) { $self->semValue = $self->maybeCreateNop($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]); }, 185 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(1-1)] instanceof Stmt\Block) { $self->semValue = $self->semStack[$stackPos-(1-1)]->stmts; } else if ($self->semStack[$stackPos-(1-1)] === null) { $self->semValue = []; } else { $self->semValue = [$self->semStack[$stackPos-(1-1)]]; }; }, 186 => static function ($self, $stackPos) { $self->semValue = array(); }, 187 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 188 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 189 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 190 => static function ($self, $stackPos) { $self->semValue = new Stmt\Catch_($self->semStack[$stackPos-(8-3)], $self->semStack[$stackPos-(8-4)], $self->semStack[$stackPos-(8-7)], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 191 => static function ($self, $stackPos) { $self->semValue = null; }, 192 => static function ($self, $stackPos) { $self->semValue = new Stmt\Finally_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 193 => null, 194 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 195 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 196 => static function ($self, $stackPos) { $self->semValue = false; }, 197 => static function ($self, $stackPos) { $self->semValue = true; }, 198 => static function ($self, $stackPos) { $self->semValue = false; }, 199 => static function ($self, $stackPos) { $self->semValue = true; }, 200 => static function ($self, $stackPos) { $self->semValue = false; }, 201 => static function ($self, $stackPos) { $self->semValue = true; }, 202 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 203 => static function ($self, $stackPos) { $self->semValue = []; }, 204 => null, 205 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 206 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 207 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 208 => static function ($self, $stackPos) { $self->semValue = new Stmt\Function_($self->semStack[$stackPos-(8-3)], ['byRef' => $self->semStack[$stackPos-(8-2)], 'params' => $self->semStack[$stackPos-(8-5)], 'returnType' => $self->semStack[$stackPos-(8-7)], 'stmts' => $self->semStack[$stackPos-(8-8)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 209 => static function ($self, $stackPos) { $self->semValue = new Stmt\Function_($self->semStack[$stackPos-(9-4)], ['byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-6)], 'returnType' => $self->semStack[$stackPos-(9-8)], 'stmts' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => $self->semStack[$stackPos-(9-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 210 => static function ($self, $stackPos) { $self->semValue = new Stmt\Class_($self->semStack[$stackPos-(7-2)], ['type' => $self->semStack[$stackPos-(7-1)], 'extends' => $self->semStack[$stackPos-(7-3)], 'implements' => $self->semStack[$stackPos-(7-4)], 'stmts' => $self->semStack[$stackPos-(7-6)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); $self->checkClass($self->semValue, $stackPos-(7-2)); }, 211 => static function ($self, $stackPos) { $self->semValue = new Stmt\Class_($self->semStack[$stackPos-(8-3)], ['type' => $self->semStack[$stackPos-(8-2)], 'extends' => $self->semStack[$stackPos-(8-4)], 'implements' => $self->semStack[$stackPos-(8-5)], 'stmts' => $self->semStack[$stackPos-(8-7)], 'attrGroups' => $self->semStack[$stackPos-(8-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); $self->checkClass($self->semValue, $stackPos-(8-3)); }, 212 => static function ($self, $stackPos) { $self->semValue = new Stmt\Interface_($self->semStack[$stackPos-(7-3)], ['extends' => $self->semStack[$stackPos-(7-4)], 'stmts' => $self->semStack[$stackPos-(7-6)], 'attrGroups' => $self->semStack[$stackPos-(7-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); $self->checkInterface($self->semValue, $stackPos-(7-3)); }, 213 => static function ($self, $stackPos) { $self->semValue = new Stmt\Trait_($self->semStack[$stackPos-(6-3)], ['stmts' => $self->semStack[$stackPos-(6-5)], 'attrGroups' => $self->semStack[$stackPos-(6-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); }, 214 => static function ($self, $stackPos) { $self->semValue = new Stmt\Enum_($self->semStack[$stackPos-(8-3)], ['scalarType' => $self->semStack[$stackPos-(8-4)], 'implements' => $self->semStack[$stackPos-(8-5)], 'stmts' => $self->semStack[$stackPos-(8-7)], 'attrGroups' => $self->semStack[$stackPos-(8-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); $self->checkEnum($self->semValue, $stackPos-(8-3)); }, 215 => static function ($self, $stackPos) { $self->semValue = null; }, 216 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 217 => static function ($self, $stackPos) { $self->semValue = null; }, 218 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 219 => static function ($self, $stackPos) { $self->semValue = 0; }, 220 => null, 221 => null, 222 => static function ($self, $stackPos) { $self->checkClassModifier($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $self->semValue = $self->semStack[$stackPos-(2-1)] | $self->semStack[$stackPos-(2-2)]; }, 223 => static function ($self, $stackPos) { $self->semValue = Modifiers::ABSTRACT; }, 224 => static function ($self, $stackPos) { $self->semValue = Modifiers::FINAL; }, 225 => static function ($self, $stackPos) { $self->semValue = Modifiers::READONLY; }, 226 => static function ($self, $stackPos) { $self->semValue = null; }, 227 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 228 => static function ($self, $stackPos) { $self->semValue = array(); }, 229 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 230 => static function ($self, $stackPos) { $self->semValue = array(); }, 231 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 232 => null, 233 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 234 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 235 => null, 236 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 237 => null, 238 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 239 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(1-1)] instanceof Stmt\Block) { $self->semValue = $self->semStack[$stackPos-(1-1)]->stmts; } else if ($self->semStack[$stackPos-(1-1)] === null) { $self->semValue = []; } else { $self->semValue = [$self->semStack[$stackPos-(1-1)]]; }; }, 240 => static function ($self, $stackPos) { $self->semValue = null; }, 241 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 242 => null, 243 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 244 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 245 => static function ($self, $stackPos) { $self->semValue = new Node\DeclareItem($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 246 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 247 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-3)]; }, 248 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 249 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(5-3)]; }, 250 => static function ($self, $stackPos) { $self->semValue = array(); }, 251 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 252 => static function ($self, $stackPos) { $self->semValue = new Stmt\Case_($self->semStack[$stackPos-(4-2)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 253 => static function ($self, $stackPos) { $self->semValue = new Stmt\Case_(null, $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 254 => null, 255 => null, 256 => static function ($self, $stackPos) { $self->semValue = new Expr\Match_($self->semStack[$stackPos-(7-3)], $self->semStack[$stackPos-(7-6)], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos])); }, 257 => static function ($self, $stackPos) { $self->semValue = []; }, 258 => null, 259 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 260 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 261 => static function ($self, $stackPos) { $self->semValue = new Node\MatchArm($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 262 => static function ($self, $stackPos) { $self->semValue = new Node\MatchArm(null, $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 263 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 264 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 265 => static function ($self, $stackPos) { $self->semValue = array(); }, 266 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 267 => static function ($self, $stackPos) { $self->semValue = new Stmt\ElseIf_($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 268 => static function ($self, $stackPos) { $self->semValue = array(); }, 269 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 270 => static function ($self, $stackPos) { $self->semValue = new Stmt\ElseIf_($self->semStack[$stackPos-(6-3)], $self->semStack[$stackPos-(6-6)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); $self->fixupAlternativeElse($self->semValue); }, 271 => static function ($self, $stackPos) { $self->semValue = null; }, 272 => static function ($self, $stackPos) { $self->semValue = new Stmt\Else_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 273 => static function ($self, $stackPos) { $self->semValue = null; }, 274 => static function ($self, $stackPos) { $self->semValue = new Stmt\Else_($self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->fixupAlternativeElse($self->semValue); }, 275 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)], false); }, 276 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(2-2)], true); }, 277 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)], false); }, 278 => static function ($self, $stackPos) { $self->semValue = array($self->fixupArrayDestructuring($self->semStack[$stackPos-(1-1)]), false); }, 279 => null, 280 => static function ($self, $stackPos) { $self->semValue = array(); }, 281 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 282 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 283 => static function ($self, $stackPos) { $self->semValue = 0; }, 284 => static function ($self, $stackPos) { $self->checkModifier($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $self->semValue = $self->semStack[$stackPos-(2-1)] | $self->semStack[$stackPos-(2-2)]; }, 285 => static function ($self, $stackPos) { $self->semValue = Modifiers::PUBLIC; }, 286 => static function ($self, $stackPos) { $self->semValue = Modifiers::PROTECTED; }, 287 => static function ($self, $stackPos) { $self->semValue = Modifiers::PRIVATE; }, 288 => static function ($self, $stackPos) { $self->semValue = Modifiers::PUBLIC_SET; }, 289 => static function ($self, $stackPos) { $self->semValue = Modifiers::PROTECTED_SET; }, 290 => static function ($self, $stackPos) { $self->semValue = Modifiers::PRIVATE_SET; }, 291 => static function ($self, $stackPos) { $self->semValue = Modifiers::READONLY; }, 292 => static function ($self, $stackPos) { $self->semValue = Modifiers::FINAL; }, 293 => static function ($self, $stackPos) { $self->semValue = new Node\Param($self->semStack[$stackPos-(7-6)], null, $self->semStack[$stackPos-(7-3)], $self->semStack[$stackPos-(7-4)], $self->semStack[$stackPos-(7-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(7-2)], $self->semStack[$stackPos-(7-1)], $self->semStack[$stackPos-(7-7)]); $self->checkParam($self->semValue); $self->addPropertyNameToHooks($self->semValue); }, 294 => static function ($self, $stackPos) { $self->semValue = new Node\Param($self->semStack[$stackPos-(9-6)], $self->semStack[$stackPos-(9-8)], $self->semStack[$stackPos-(9-3)], $self->semStack[$stackPos-(9-4)], $self->semStack[$stackPos-(9-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(9-2)], $self->semStack[$stackPos-(9-1)], $self->semStack[$stackPos-(9-9)]); $self->checkParam($self->semValue); $self->addPropertyNameToHooks($self->semValue); }, 295 => static function ($self, $stackPos) { $self->semValue = new Node\Param(new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])), null, $self->semStack[$stackPos-(6-3)], $self->semStack[$stackPos-(6-4)], $self->semStack[$stackPos-(6-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(6-2)], $self->semStack[$stackPos-(6-1)]); }, 296 => null, 297 => static function ($self, $stackPos) { $self->semValue = new Node\NullableType($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 298 => static function ($self, $stackPos) { $self->semValue = new Node\UnionType($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 299 => null, 300 => null, 301 => static function ($self, $stackPos) { $self->semValue = new Node\Name('static', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 302 => static function ($self, $stackPos) { $self->semValue = $self->handleBuiltinTypes($self->semStack[$stackPos-(1-1)]); }, 303 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier('array', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 304 => static function ($self, $stackPos) { $self->semValue = new Node\Identifier('callable', $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 305 => null, 306 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 307 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 308 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 309 => null, 310 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 311 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 312 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 313 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 314 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 315 => static function ($self, $stackPos) { $self->semValue = new Node\IntersectionType($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 316 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 317 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 318 => static function ($self, $stackPos) { $self->semValue = new Node\IntersectionType($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 319 => null, 320 => static function ($self, $stackPos) { $self->semValue = new Node\NullableType($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 321 => static function ($self, $stackPos) { $self->semValue = new Node\UnionType($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 322 => null, 323 => static function ($self, $stackPos) { $self->semValue = null; }, 324 => null, 325 => static function ($self, $stackPos) { $self->semValue = null; }, 326 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(2-2)]; }, 327 => static function ($self, $stackPos) { $self->semValue = null; }, 328 => static function ($self, $stackPos) { $self->semValue = array(); }, 329 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 330 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-2)]); }, 331 => static function ($self, $stackPos) { $self->semValue = array(); }, 332 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-2)]; }, 333 => static function ($self, $stackPos) { $self->semValue = array(new Node\Arg($self->semStack[$stackPos-(4-2)], false, false, $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos]))); }, 334 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-2)]); }, 335 => static function ($self, $stackPos) { $self->semValue = array(new Node\Arg($self->semStack[$stackPos-(3-1)], false, false, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos-(3-1)])), $self->semStack[$stackPos-(3-3)]); }, 336 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 337 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 338 => static function ($self, $stackPos) { $self->semValue = new Node\VariadicPlaceholder($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 339 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 340 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 341 => static function ($self, $stackPos) { $self->semValue = new Node\Arg($self->semStack[$stackPos-(2-2)], true, false, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 342 => static function ($self, $stackPos) { $self->semValue = new Node\Arg($self->semStack[$stackPos-(2-2)], false, true, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 343 => static function ($self, $stackPos) { $self->semValue = new Node\Arg($self->semStack[$stackPos-(3-3)], false, false, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(3-1)]); }, 344 => static function ($self, $stackPos) { $self->semValue = new Node\Arg($self->semStack[$stackPos-(1-1)], false, false, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 345 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 346 => null, 347 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 348 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 349 => null, 350 => null, 351 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 352 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 353 => static function ($self, $stackPos) { $self->semValue = new Node\StaticVar($self->semStack[$stackPos-(1-1)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 354 => static function ($self, $stackPos) { $self->semValue = new Node\StaticVar($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 355 => static function ($self, $stackPos) { if ($self->semStack[$stackPos-(2-2)] !== null) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; } else { $self->semValue = $self->semStack[$stackPos-(2-1)]; } }, 356 => static function ($self, $stackPos) { $self->semValue = array(); }, 357 => static function ($self, $stackPos) { $nop = $self->maybeCreateZeroLengthNop($self->tokenPos);; if ($nop !== null) { $self->semStack[$stackPos-(1-1)][] = $nop; } $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 358 => static function ($self, $stackPos) { $self->semValue = new Stmt\Property($self->semStack[$stackPos-(5-2)], $self->semStack[$stackPos-(5-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-1)]); }, 359 => static function ($self, $stackPos) { $self->semValue = new Stmt\Property($self->semStack[$stackPos-(7-2)], $self->semStack[$stackPos-(7-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(7-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(7-3)], $self->semStack[$stackPos-(7-1)], $self->semStack[$stackPos-(7-6)]); $self->checkPropertyHooksForMultiProperty($self->semValue, $stackPos-(7-5)); $self->checkEmptyPropertyHookList($self->semStack[$stackPos-(7-6)], $stackPos-(7-5)); $self->addPropertyNameToHooks($self->semValue); }, 360 => static function ($self, $stackPos) { $self->semValue = new Stmt\ClassConst($self->semStack[$stackPos-(5-4)], $self->semStack[$stackPos-(5-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(5-1)]); $self->checkClassConst($self->semValue, $stackPos-(5-2)); }, 361 => static function ($self, $stackPos) { $self->semValue = new Stmt\ClassConst($self->semStack[$stackPos-(6-5)], $self->semStack[$stackPos-(6-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos]), $self->semStack[$stackPos-(6-1)], $self->semStack[$stackPos-(6-4)]); $self->checkClassConst($self->semValue, $stackPos-(6-2)); }, 362 => static function ($self, $stackPos) { $self->semValue = new Stmt\ClassMethod($self->semStack[$stackPos-(10-5)], ['type' => $self->semStack[$stackPos-(10-2)], 'byRef' => $self->semStack[$stackPos-(10-4)], 'params' => $self->semStack[$stackPos-(10-7)], 'returnType' => $self->semStack[$stackPos-(10-9)], 'stmts' => $self->semStack[$stackPos-(10-10)], 'attrGroups' => $self->semStack[$stackPos-(10-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(10-1)], $self->tokenEndStack[$stackPos])); $self->checkClassMethod($self->semValue, $stackPos-(10-2)); }, 363 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUse($self->semStack[$stackPos-(3-2)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 364 => static function ($self, $stackPos) { $self->semValue = new Stmt\EnumCase($self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-4)], $self->semStack[$stackPos-(5-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 365 => static function ($self, $stackPos) { $self->semValue = null; /* will be skipped */ }, 366 => static function ($self, $stackPos) { $self->semValue = array(); }, 367 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 368 => static function ($self, $stackPos) { $self->semValue = array(); }, 369 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 370 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Precedence($self->semStack[$stackPos-(4-1)][0], $self->semStack[$stackPos-(4-1)][1], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 371 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Alias($self->semStack[$stackPos-(5-1)][0], $self->semStack[$stackPos-(5-1)][1], $self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 372 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Alias($self->semStack[$stackPos-(4-1)][0], $self->semStack[$stackPos-(4-1)][1], $self->semStack[$stackPos-(4-3)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 373 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Alias($self->semStack[$stackPos-(4-1)][0], $self->semStack[$stackPos-(4-1)][1], null, $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 374 => static function ($self, $stackPos) { $self->semValue = new Stmt\TraitUseAdaptation\Alias($self->semStack[$stackPos-(4-1)][0], $self->semStack[$stackPos-(4-1)][1], null, $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 375 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)]); }, 376 => null, 377 => static function ($self, $stackPos) { $self->semValue = array(null, $self->semStack[$stackPos-(1-1)]); }, 378 => static function ($self, $stackPos) { $self->semValue = null; }, 379 => null, 380 => null, 381 => static function ($self, $stackPos) { $self->semValue = 0; }, 382 => static function ($self, $stackPos) { $self->semValue = 0; }, 383 => null, 384 => null, 385 => static function ($self, $stackPos) { $self->checkModifier($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $self->semValue = $self->semStack[$stackPos-(2-1)] | $self->semStack[$stackPos-(2-2)]; }, 386 => static function ($self, $stackPos) { $self->semValue = Modifiers::PUBLIC; }, 387 => static function ($self, $stackPos) { $self->semValue = Modifiers::PROTECTED; }, 388 => static function ($self, $stackPos) { $self->semValue = Modifiers::PRIVATE; }, 389 => static function ($self, $stackPos) { $self->semValue = Modifiers::PUBLIC_SET; }, 390 => static function ($self, $stackPos) { $self->semValue = Modifiers::PROTECTED_SET; }, 391 => static function ($self, $stackPos) { $self->semValue = Modifiers::PRIVATE_SET; }, 392 => static function ($self, $stackPos) { $self->semValue = Modifiers::STATIC; }, 393 => static function ($self, $stackPos) { $self->semValue = Modifiers::ABSTRACT; }, 394 => static function ($self, $stackPos) { $self->semValue = Modifiers::FINAL; }, 395 => static function ($self, $stackPos) { $self->semValue = Modifiers::READONLY; }, 396 => null, 397 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 398 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 399 => static function ($self, $stackPos) { $self->semValue = new Node\VarLikeIdentifier(substr($self->semStack[$stackPos-(1-1)], 1), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 400 => static function ($self, $stackPos) { $self->semValue = new Node\PropertyItem($self->semStack[$stackPos-(1-1)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 401 => static function ($self, $stackPos) { $self->semValue = new Node\PropertyItem($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 402 => static function ($self, $stackPos) { $self->semValue = []; }, 403 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 404 => static function ($self, $stackPos) { $self->semValue = []; }, 405 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; $self->checkEmptyPropertyHookList($self->semStack[$stackPos-(3-2)], $stackPos-(3-1)); }, 406 => static function ($self, $stackPos) { $self->semValue = new Node\PropertyHook($self->semStack[$stackPos-(5-4)], $self->semStack[$stackPos-(5-5)], ['flags' => $self->semStack[$stackPos-(5-2)], 'byRef' => $self->semStack[$stackPos-(5-3)], 'params' => [], 'attrGroups' => $self->semStack[$stackPos-(5-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); $self->checkPropertyHook($self->semValue, null); }, 407 => static function ($self, $stackPos) { $self->semValue = new Node\PropertyHook($self->semStack[$stackPos-(8-4)], $self->semStack[$stackPos-(8-8)], ['flags' => $self->semStack[$stackPos-(8-2)], 'byRef' => $self->semStack[$stackPos-(8-3)], 'params' => $self->semStack[$stackPos-(8-6)], 'attrGroups' => $self->semStack[$stackPos-(8-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); $self->checkPropertyHook($self->semValue, $stackPos-(8-5)); }, 408 => static function ($self, $stackPos) { $self->semValue = null; }, 409 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 410 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 411 => static function ($self, $stackPos) { $self->semValue = 0; }, 412 => static function ($self, $stackPos) { $self->checkPropertyHookModifiers($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $self->semValue = $self->semStack[$stackPos-(2-1)] | $self->semStack[$stackPos-(2-2)]; }, 413 => null, 414 => null, 415 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 416 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 417 => static function ($self, $stackPos) { $self->semValue = array(); }, 418 => null, 419 => null, 420 => static function ($self, $stackPos) { $self->semValue = new Expr\Assign($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 421 => static function ($self, $stackPos) { $self->semValue = new Expr\Assign($self->fixupArrayDestructuring($self->semStack[$stackPos-(3-1)]), $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 422 => static function ($self, $stackPos) { $self->semValue = new Expr\Assign($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 423 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignRef($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 424 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignRef($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); if (!$self->phpVersion->allowsAssignNewByReference()) { $self->emitError(new Error('Cannot assign new by reference', $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos]))); } }, 425 => null, 426 => null, 427 => static function ($self, $stackPos) { $self->semValue = new Expr\FuncCall(new Node\Name($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos-(2-1)])), $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 428 => static function ($self, $stackPos) { $self->semValue = new Expr\Clone_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 429 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Plus($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 430 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Minus($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 431 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Mul($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 432 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Div($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 433 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Concat($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 434 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Mod($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 435 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\BitwiseAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 436 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\BitwiseOr($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 437 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\BitwiseXor($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 438 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\ShiftLeft($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 439 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\ShiftRight($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 440 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Pow($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 441 => static function ($self, $stackPos) { $self->semValue = new Expr\AssignOp\Coalesce($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 442 => static function ($self, $stackPos) { $self->semValue = new Expr\PostInc($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 443 => static function ($self, $stackPos) { $self->semValue = new Expr\PreInc($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 444 => static function ($self, $stackPos) { $self->semValue = new Expr\PostDec($self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 445 => static function ($self, $stackPos) { $self->semValue = new Expr\PreDec($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 446 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BooleanOr($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 447 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BooleanAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 448 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\LogicalOr($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 449 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\LogicalAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 450 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\LogicalXor($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 451 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BitwiseOr($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 452 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BitwiseAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 453 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BitwiseAnd($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 454 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\BitwiseXor($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 455 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Concat($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 456 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Plus($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 457 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Minus($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 458 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Mul($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 459 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Div($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 460 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Mod($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 461 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\ShiftLeft($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 462 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\ShiftRight($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 463 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Pow($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 464 => static function ($self, $stackPos) { $self->semValue = new Expr\UnaryPlus($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 465 => static function ($self, $stackPos) { $self->semValue = new Expr\UnaryMinus($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 466 => static function ($self, $stackPos) { $self->semValue = new Expr\BooleanNot($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 467 => static function ($self, $stackPos) { $self->semValue = new Expr\BitwiseNot($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 468 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Identical($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 469 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\NotIdentical($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 470 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Equal($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 471 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\NotEqual($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 472 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Spaceship($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 473 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Smaller($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 474 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\SmallerOrEqual($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 475 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Greater($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 476 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\GreaterOrEqual($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 477 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Pipe($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->checkPipeOperatorParentheses($self->semStack[$stackPos-(3-3)]); }, 478 => static function ($self, $stackPos) { $self->semValue = new Expr\Instanceof_($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 479 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; if ($self->semValue instanceof Expr\ArrowFunction) { $self->parenthesizedArrowFunctions->offsetSet($self->semValue); } }, 480 => static function ($self, $stackPos) { $self->semValue = new Expr\Ternary($self->semStack[$stackPos-(5-1)], $self->semStack[$stackPos-(5-3)], $self->semStack[$stackPos-(5-5)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 481 => static function ($self, $stackPos) { $self->semValue = new Expr\Ternary($self->semStack[$stackPos-(4-1)], null, $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 482 => static function ($self, $stackPos) { $self->semValue = new Expr\BinaryOp\Coalesce($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 483 => static function ($self, $stackPos) { $self->semValue = new Expr\Isset_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 484 => static function ($self, $stackPos) { $self->semValue = new Expr\Empty_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 485 => static function ($self, $stackPos) { $self->semValue = new Expr\Include_($self->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 486 => static function ($self, $stackPos) { $self->semValue = new Expr\Include_($self->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 487 => static function ($self, $stackPos) { $self->semValue = new Expr\Eval_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 488 => static function ($self, $stackPos) { $self->semValue = new Expr\Include_($self->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 489 => static function ($self, $stackPos) { $self->semValue = new Expr\Include_($self->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 490 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = $self->getIntCastKind($self->semStack[$stackPos-(2-1)]); $self->semValue = new Expr\Cast\Int_($self->semStack[$stackPos-(2-2)], $attrs); }, 491 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = $self->getFloatCastKind($self->semStack[$stackPos-(2-1)]); $self->semValue = new Expr\Cast\Double($self->semStack[$stackPos-(2-2)], $attrs); }, 492 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = $self->getStringCastKind($self->semStack[$stackPos-(2-1)]); $self->semValue = new Expr\Cast\String_($self->semStack[$stackPos-(2-2)], $attrs); }, 493 => static function ($self, $stackPos) { $self->semValue = new Expr\Cast\Array_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 494 => static function ($self, $stackPos) { $self->semValue = new Expr\Cast\Object_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 495 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = $self->getBoolCastKind($self->semStack[$stackPos-(2-1)]); $self->semValue = new Expr\Cast\Bool_($self->semStack[$stackPos-(2-2)], $attrs); }, 496 => static function ($self, $stackPos) { $self->semValue = new Expr\Cast\Unset_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 497 => static function ($self, $stackPos) { $self->semValue = new Expr\Cast\Void_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 498 => static function ($self, $stackPos) { $self->semValue = $self->createExitExpr($self->semStack[$stackPos-(2-1)], $stackPos-(2-1), $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 499 => static function ($self, $stackPos) { $self->semValue = new Expr\ErrorSuppress($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 500 => null, 501 => static function ($self, $stackPos) { $self->semValue = new Expr\ShellExec($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 502 => static function ($self, $stackPos) { $self->semValue = new Expr\Print_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 503 => static function ($self, $stackPos) { $self->semValue = new Expr\Yield_(null, null, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 504 => static function ($self, $stackPos) { $self->semValue = new Expr\Yield_($self->semStack[$stackPos-(2-2)], null, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 505 => static function ($self, $stackPos) { $self->semValue = new Expr\Yield_($self->semStack[$stackPos-(4-4)], $self->semStack[$stackPos-(4-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 506 => static function ($self, $stackPos) { $self->semValue = new Expr\YieldFrom($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 507 => static function ($self, $stackPos) { $self->semValue = new Expr\Throw_($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 508 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $self->semStack[$stackPos-(8-2)], 'params' => $self->semStack[$stackPos-(8-4)], 'returnType' => $self->semStack[$stackPos-(8-6)], 'expr' => $self->semStack[$stackPos-(8-8)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 509 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-5)], 'returnType' => $self->semStack[$stackPos-(9-7)], 'expr' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 510 => static function ($self, $stackPos) { $self->semValue = new Expr\Closure(['static' => false, 'byRef' => $self->semStack[$stackPos-(8-2)], 'params' => $self->semStack[$stackPos-(8-4)], 'uses' => $self->semStack[$stackPos-(8-6)], 'returnType' => $self->semStack[$stackPos-(8-7)], 'stmts' => $self->semStack[$stackPos-(8-8)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])); }, 511 => static function ($self, $stackPos) { $self->semValue = new Expr\Closure(['static' => true, 'byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-5)], 'uses' => $self->semStack[$stackPos-(9-7)], 'returnType' => $self->semStack[$stackPos-(9-8)], 'stmts' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => []], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 512 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-5)], 'returnType' => $self->semStack[$stackPos-(9-7)], 'expr' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => $self->semStack[$stackPos-(9-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 513 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $self->semStack[$stackPos-(10-4)], 'params' => $self->semStack[$stackPos-(10-6)], 'returnType' => $self->semStack[$stackPos-(10-8)], 'expr' => $self->semStack[$stackPos-(10-10)], 'attrGroups' => $self->semStack[$stackPos-(10-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(10-1)], $self->tokenEndStack[$stackPos])); }, 514 => static function ($self, $stackPos) { $self->semValue = new Expr\Closure(['static' => false, 'byRef' => $self->semStack[$stackPos-(9-3)], 'params' => $self->semStack[$stackPos-(9-5)], 'uses' => $self->semStack[$stackPos-(9-7)], 'returnType' => $self->semStack[$stackPos-(9-8)], 'stmts' => $self->semStack[$stackPos-(9-9)], 'attrGroups' => $self->semStack[$stackPos-(9-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(9-1)], $self->tokenEndStack[$stackPos])); }, 515 => static function ($self, $stackPos) { $self->semValue = new Expr\Closure(['static' => true, 'byRef' => $self->semStack[$stackPos-(10-4)], 'params' => $self->semStack[$stackPos-(10-6)], 'uses' => $self->semStack[$stackPos-(10-8)], 'returnType' => $self->semStack[$stackPos-(10-9)], 'stmts' => $self->semStack[$stackPos-(10-10)], 'attrGroups' => $self->semStack[$stackPos-(10-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(10-1)], $self->tokenEndStack[$stackPos])); }, 516 => static function ($self, $stackPos) { $self->semValue = array(new Stmt\Class_(null, ['type' => $self->semStack[$stackPos-(8-2)], 'extends' => $self->semStack[$stackPos-(8-4)], 'implements' => $self->semStack[$stackPos-(8-5)], 'stmts' => $self->semStack[$stackPos-(8-7)], 'attrGroups' => $self->semStack[$stackPos-(8-1)]], $self->getAttributes($self->tokenStartStack[$stackPos-(8-1)], $self->tokenEndStack[$stackPos])), $self->semStack[$stackPos-(8-3)]); $self->checkClass($self->semValue[0], -1); }, 517 => static function ($self, $stackPos) { $self->semValue = new Expr\New_($self->semStack[$stackPos-(3-2)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 518 => static function ($self, $stackPos) { list($class, $ctorArgs) = $self->semStack[$stackPos-(2-2)]; $self->semValue = new Expr\New_($class, $ctorArgs, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 519 => static function ($self, $stackPos) { $self->semValue = new Expr\New_($self->semStack[$stackPos-(2-2)], [], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 520 => null, 521 => null, 522 => static function ($self, $stackPos) { $self->semValue = array(); }, 523 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(4-3)]; }, 524 => null, 525 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 526 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 527 => static function ($self, $stackPos) { $self->semValue = new Node\ClosureUse($self->semStack[$stackPos-(2-2)], $self->semStack[$stackPos-(2-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 528 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 529 => static function ($self, $stackPos) { $self->semValue = new Expr\FuncCall($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 530 => static function ($self, $stackPos) { $self->semValue = new Expr\FuncCall($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 531 => static function ($self, $stackPos) { $self->semValue = new Expr\FuncCall($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 532 => static function ($self, $stackPos) { $self->semValue = new Expr\StaticCall($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 533 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 534 => null, 535 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 536 => static function ($self, $stackPos) { $self->semValue = new Name($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 537 => static function ($self, $stackPos) { $self->semValue = new Name\FullyQualified(substr($self->semStack[$stackPos-(1-1)], 1), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 538 => static function ($self, $stackPos) { $self->semValue = new Name\Relative(substr($self->semStack[$stackPos-(1-1)], 10), $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 539 => null, 540 => null, 541 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 542 => static function ($self, $stackPos) { $self->semValue = new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->errorState = 2; }, 543 => null, 544 => null, 545 => static function ($self, $stackPos) { $self->semValue = array(); }, 546 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); foreach ($self->semValue as $s) { if ($s instanceof Node\InterpolatedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', $self->phpVersion->supportsUnicodeEscapes()); } }; }, 547 => static function ($self, $stackPos) { foreach ($self->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\InterpolatedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', $self->phpVersion->supportsUnicodeEscapes()); } }; $self->semValue = $self->semStack[$stackPos-(1-1)]; }, 548 => static function ($self, $stackPos) { $self->semValue = array(); }, 549 => null, 550 => static function ($self, $stackPos) { $self->semValue = new Expr\ConstFetch($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 551 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Line($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 552 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\File($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 553 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Dir($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 554 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Class_($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 555 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Trait_($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 556 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Method($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 557 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Function_($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 558 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Namespace_($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 559 => static function ($self, $stackPos) { $self->semValue = new Scalar\MagicConst\Property($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 560 => static function ($self, $stackPos) { $self->semValue = new Expr\ClassConstFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 561 => static function ($self, $stackPos) { $self->semValue = new Expr\ClassConstFetch($self->semStack[$stackPos-(5-1)], $self->semStack[$stackPos-(5-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(5-1)], $self->tokenEndStack[$stackPos])); }, 562 => static function ($self, $stackPos) { $self->semValue = new Expr\ClassConstFetch($self->semStack[$stackPos-(3-1)], new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(3-3)], $self->tokenEndStack[$stackPos-(3-3)])), $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); $self->errorState = 2; }, 563 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = Expr\Array_::KIND_SHORT; $self->semValue = new Expr\Array_($self->semStack[$stackPos-(3-2)], $attrs); }, 564 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = Expr\Array_::KIND_LONG; $self->semValue = new Expr\Array_($self->semStack[$stackPos-(4-3)], $attrs); $self->createdArrays->offsetSet($self->semValue); }, 565 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; $self->createdArrays->offsetSet($self->semValue); }, 566 => static function ($self, $stackPos) { $self->semValue = Scalar\String_::fromString($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]), $self->phpVersion->supportsUnicodeEscapes()); }, 567 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; foreach ($self->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\InterpolatedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', $self->phpVersion->supportsUnicodeEscapes()); } }; $self->semValue = new Scalar\InterpolatedString($self->semStack[$stackPos-(3-2)], $attrs); }, 568 => static function ($self, $stackPos) { $self->semValue = $self->parseLNumber($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]), $self->phpVersion->allowsInvalidOctals()); }, 569 => static function ($self, $stackPos) { $self->semValue = Scalar\Float_::fromString($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 570 => null, 571 => null, 572 => null, 573 => static function ($self, $stackPos) { $self->semValue = $self->parseDocString($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-2)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]), $self->getAttributes($self->tokenStartStack[$stackPos-(3-3)], $self->tokenEndStack[$stackPos-(3-3)]), true); }, 574 => static function ($self, $stackPos) { $self->semValue = $self->parseDocString($self->semStack[$stackPos-(2-1)], '', $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]), $self->getAttributes($self->tokenStartStack[$stackPos-(2-2)], $self->tokenEndStack[$stackPos-(2-2)]), true); }, 575 => static function ($self, $stackPos) { $self->semValue = $self->parseDocString($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-2)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos]), $self->getAttributes($self->tokenStartStack[$stackPos-(3-3)], $self->tokenEndStack[$stackPos-(3-3)]), true); }, 576 => static function ($self, $stackPos) { $self->semValue = null; }, 577 => null, 578 => null, 579 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 580 => null, 581 => null, 582 => null, 583 => null, 584 => null, 585 => null, 586 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 587 => null, 588 => null, 589 => null, 590 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 591 => null, 592 => static function ($self, $stackPos) { $self->semValue = new Expr\MethodCall($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 593 => static function ($self, $stackPos) { $self->semValue = new Expr\NullsafeMethodCall($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->semStack[$stackPos-(4-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 594 => static function ($self, $stackPos) { $self->semValue = null; }, 595 => null, 596 => null, 597 => null, 598 => static function ($self, $stackPos) { $self->semValue = new Expr\PropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 599 => static function ($self, $stackPos) { $self->semValue = new Expr\NullsafePropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 600 => null, 601 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 602 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 603 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable(new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])), $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); $self->errorState = 2; }, 604 => static function ($self, $stackPos) { $var = $self->semStack[$stackPos-(1-1)]->name; $self->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])) : $var; }, 605 => static function ($self, $stackPos) { $self->semValue = new Expr\StaticPropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 606 => null, 607 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 608 => static function ($self, $stackPos) { $self->semValue = new Expr\PropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 609 => static function ($self, $stackPos) { $self->semValue = new Expr\NullsafePropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 610 => static function ($self, $stackPos) { $self->semValue = new Expr\StaticPropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 611 => static function ($self, $stackPos) { $self->semValue = new Expr\StaticPropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 612 => null, 613 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 614 => null, 615 => null, 616 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 617 => null, 618 => static function ($self, $stackPos) { $self->semValue = new Expr\Error($self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); $self->errorState = 2; }, 619 => static function ($self, $stackPos) { $self->semValue = new Expr\List_($self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); $self->semValue->setAttribute('kind', Expr\List_::KIND_LIST); $self->postprocessList($self->semValue); }, 620 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(1-1)]; $end = count($self->semValue)-1; if ($self->semValue[$end]->value instanceof Expr\Error) array_pop($self->semValue); }, 621 => null, 622 => static function ($self, $stackPos) { /* do nothing -- prevent default action of $$=$self->semStack[$1]. See $551. */ }, 623 => static function ($self, $stackPos) { $self->semStack[$stackPos-(3-1)][] = $self->semStack[$stackPos-(3-3)]; $self->semValue = $self->semStack[$stackPos-(3-1)]; }, 624 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 625 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(1-1)], null, false, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 626 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(2-2)], null, true, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 627 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(1-1)], null, false, $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 628 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(3-3)], $self->semStack[$stackPos-(3-1)], false, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 629 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(4-4)], $self->semStack[$stackPos-(4-1)], true, $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 630 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(3-3)], $self->semStack[$stackPos-(3-1)], false, $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 631 => static function ($self, $stackPos) { $self->semValue = new Node\ArrayItem($self->semStack[$stackPos-(2-2)], null, false, $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos]), true); }, 632 => static function ($self, $stackPos) { /* Create an Error node now to remember the position. We'll later either report an error, or convert this into a null element, depending on whether this is a creation or destructuring context. */ $attrs = $self->createEmptyElemAttributes($self->tokenPos); $self->semValue = new Node\ArrayItem(new Expr\Error($attrs), null, false, $attrs); }, 633 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 634 => static function ($self, $stackPos) { $self->semStack[$stackPos-(2-1)][] = $self->semStack[$stackPos-(2-2)]; $self->semValue = $self->semStack[$stackPos-(2-1)]; }, 635 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(1-1)]); }, 636 => static function ($self, $stackPos) { $self->semValue = array($self->semStack[$stackPos-(2-1)], $self->semStack[$stackPos-(2-2)]); }, 637 => static function ($self, $stackPos) { $attrs = $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos]); $attrs['rawValue'] = $self->semStack[$stackPos-(1-1)]; $self->semValue = new Node\InterpolatedStringPart($self->semStack[$stackPos-(1-1)], $attrs); }, 638 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 639 => null, 640 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(4-1)], $self->semStack[$stackPos-(4-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(4-1)], $self->tokenEndStack[$stackPos])); }, 641 => static function ($self, $stackPos) { $self->semValue = new Expr\PropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 642 => static function ($self, $stackPos) { $self->semValue = new Expr\NullsafePropertyFetch($self->semStack[$stackPos-(3-1)], $self->semStack[$stackPos-(3-3)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 643 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 644 => static function ($self, $stackPos) { $self->semValue = new Expr\Variable($self->semStack[$stackPos-(3-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(3-1)], $self->tokenEndStack[$stackPos])); }, 645 => static function ($self, $stackPos) { $self->semValue = new Expr\ArrayDimFetch($self->semStack[$stackPos-(6-2)], $self->semStack[$stackPos-(6-4)], $self->getAttributes($self->tokenStartStack[$stackPos-(6-1)], $self->tokenEndStack[$stackPos])); }, 646 => static function ($self, $stackPos) { $self->semValue = $self->semStack[$stackPos-(3-2)]; }, 647 => static function ($self, $stackPos) { $self->semValue = new Scalar\String_($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 648 => static function ($self, $stackPos) { $self->semValue = $self->parseNumString($self->semStack[$stackPos-(1-1)], $self->getAttributes($self->tokenStartStack[$stackPos-(1-1)], $self->tokenEndStack[$stackPos])); }, 649 => static function ($self, $stackPos) { $self->semValue = $self->parseNumString('-' . $self->semStack[$stackPos-(2-2)], $self->getAttributes($self->tokenStartStack[$stackPos-(2-1)], $self->tokenEndStack[$stackPos])); }, 650 => null, ]; } } Map of PHP token IDs to drop */ protected array $dropTokens; /** @var int[] Map of external symbols (static::T_*) to internal symbols */ protected array $tokenToSymbol; /** @var string[] Map of symbols to their names */ protected array $symbolToName; /** @var array Names of the production rules (only necessary for debugging) */ protected array $productions; /** @var int[] Map of states to a displacement into the $action table. The corresponding action for this * state/symbol pair is $action[$actionBase[$state] + $symbol]. If $actionBase[$state] is 0, the * action is defaulted, i.e. $actionDefault[$state] should be used instead. */ protected array $actionBase; /** @var int[] Table of actions. Indexed according to $actionBase comment. */ protected array $action; /** @var int[] Table indexed analogously to $action. If $actionCheck[$actionBase[$state] + $symbol] != $symbol * then the action is defaulted, i.e. $actionDefault[$state] should be used instead. */ protected array $actionCheck; /** @var int[] Map of states to their default action */ protected array $actionDefault; /** @var callable[] Semantic action callbacks */ protected array $reduceCallbacks; /** @var int[] Map of non-terminals to a displacement into the $goto table. The corresponding goto state for this * non-terminal/state pair is $goto[$gotoBase[$nonTerminal] + $state] (unless defaulted) */ protected array $gotoBase; /** @var int[] Table of states to goto after reduction. Indexed according to $gotoBase comment. */ protected array $goto; /** @var int[] Table indexed analogously to $goto. If $gotoCheck[$gotoBase[$nonTerminal] + $state] != $nonTerminal * then the goto state is defaulted, i.e. $gotoDefault[$nonTerminal] should be used. */ protected array $gotoCheck; /** @var int[] Map of non-terminals to the default state to goto after their reduction */ protected array $gotoDefault; /** @var int[] Map of rules to the non-terminal on their left-hand side, i.e. the non-terminal to use for * determining the state to goto after reduction. */ protected array $ruleToNonTerminal; /** @var int[] Map of rules to the length of their right-hand side, which is the number of elements that have to * be popped from the stack(s) on reduction. */ protected array $ruleToLength; /* * The following members are part of the parser state: */ /** @var mixed Temporary value containing the result of last semantic action (reduction) */ protected $semValue; /** @var mixed[] Semantic value stack (contains values of tokens and semantic action results) */ protected array $semStack; /** @var int[] Token start position stack */ protected array $tokenStartStack; /** @var int[] Token end position stack */ protected array $tokenEndStack; /** @var ErrorHandler Error handler */ protected ErrorHandler $errorHandler; /** @var int Error state, used to avoid error floods */ protected int $errorState; /** @var \SplObjectStorage|null Array nodes created during parsing, for postprocessing of empty elements. */ protected ?\SplObjectStorage $createdArrays; /** @var \SplObjectStorage|null * Arrow functions that are wrapped in parentheses, to enforce the pipe operator parentheses requirements. */ protected ?\SplObjectStorage $parenthesizedArrowFunctions; /** @var Token[] Tokens for the current parse */ protected array $tokens; /** @var int Current position in token array */ protected int $tokenPos; /** * Initialize $reduceCallbacks map. */ abstract protected function initReduceCallbacks(): void; /** * Creates a parser instance. * * Options: * * phpVersion: ?PhpVersion, * * @param Lexer $lexer A lexer * @param PhpVersion $phpVersion PHP version to target, defaults to latest supported. This * option is best-effort: Even if specified, parsing will generally assume the latest * supported version and only adjust behavior in minor ways, for example by omitting * errors in older versions and interpreting type hints as a name or identifier depending * on version. */ public function __construct(Lexer $lexer, ?PhpVersion $phpVersion = null) { $this->lexer = $lexer; $this->phpVersion = $phpVersion ?? PhpVersion::getNewestSupported(); $this->initReduceCallbacks(); $this->phpTokenToSymbol = $this->createTokenMap(); $this->dropTokens = array_fill_keys( [\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], true ); } /** * Parses PHP code into a node tree. * * If a non-throwing error handler is used, the parser will continue parsing after an error * occurred and attempt to build a partial AST. * * @param string $code The source code to parse * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults * to ErrorHandler\Throwing. * * @return Node\Stmt[]|null Array of statements (or null non-throwing error handler is used and * the parser was unable to recover from an error). */ public function parse(string $code, ?ErrorHandler $errorHandler = null): ?array { $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing(); $this->createdArrays = new \SplObjectStorage(); $this->parenthesizedArrowFunctions = new \SplObjectStorage(); $this->tokens = $this->lexer->tokenize($code, $this->errorHandler); $result = $this->doParse(); // Report errors for any empty elements used inside arrays. This is delayed until after the main parse, // because we don't know a priori whether a given array expression will be used in a destructuring context // or not. foreach ($this->createdArrays as $node) { foreach ($node->items as $item) { if ($item->value instanceof Expr\Error) { $this->errorHandler->handleError( new Error('Cannot use empty array elements in arrays', $item->getAttributes())); } } } // Clear out some of the interior state, so we don't hold onto unnecessary // memory between uses of the parser $this->tokenStartStack = []; $this->tokenEndStack = []; $this->semStack = []; $this->semValue = null; $this->createdArrays = null; $this->parenthesizedArrowFunctions = null; if ($result !== null) { $traverser = new NodeTraverser(new CommentAnnotatingVisitor($this->tokens)); $traverser->traverse($result); } return $result; } public function getTokens(): array { return $this->tokens; } /** @return Stmt[]|null */ protected function doParse(): ?array { // We start off with no lookahead-token $symbol = self::SYMBOL_NONE; $tokenValue = null; $this->tokenPos = -1; // Keep stack of start and end attributes $this->tokenStartStack = []; $this->tokenEndStack = [0]; // Start off in the initial state and keep a stack of previous states $state = 0; $stateStack = [$state]; // Semantic value stack (contains values of tokens and semantic action results) $this->semStack = []; // Current position in the stack(s) $stackPos = 0; $this->errorState = 0; for (;;) { //$this->traceNewState($state, $symbol); if ($this->actionBase[$state] === 0) { $rule = $this->actionDefault[$state]; } else { if ($symbol === self::SYMBOL_NONE) { do { $token = $this->tokens[++$this->tokenPos]; $tokenId = $token->id; } while (isset($this->dropTokens[$tokenId])); // Map the lexer token id to the internally used symbols. $tokenValue = $token->text; if (!isset($this->phpTokenToSymbol[$tokenId])) { throw new \RangeException(sprintf( 'The lexer returned an invalid token (id=%d, value=%s)', $tokenId, $tokenValue )); } $symbol = $this->phpTokenToSymbol[$tokenId]; //$this->traceRead($symbol); } $idx = $this->actionBase[$state] + $symbol; if ((($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) || ($state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol)) && ($action = $this->action[$idx]) !== $this->defaultAction) { /* * >= numNonLeafStates: shift and reduce * > 0: shift * = 0: accept * < 0: reduce * = -YYUNEXPECTED: error */ if ($action > 0) { /* shift */ //$this->traceShift($symbol); ++$stackPos; $stateStack[$stackPos] = $state = $action; $this->semStack[$stackPos] = $tokenValue; $this->tokenStartStack[$stackPos] = $this->tokenPos; $this->tokenEndStack[$stackPos] = $this->tokenPos; $symbol = self::SYMBOL_NONE; if ($this->errorState) { --$this->errorState; } if ($action < $this->numNonLeafStates) { continue; } /* $yyn >= numNonLeafStates means shift-and-reduce */ $rule = $action - $this->numNonLeafStates; } else { $rule = -$action; } } else { $rule = $this->actionDefault[$state]; } } for (;;) { if ($rule === 0) { /* accept */ //$this->traceAccept(); return $this->semValue; } if ($rule !== $this->unexpectedTokenRule) { /* reduce */ //$this->traceReduce($rule); $ruleLength = $this->ruleToLength[$rule]; try { $callback = $this->reduceCallbacks[$rule]; if ($callback !== null) { $callback($this, $stackPos); } elseif ($ruleLength > 0) { $this->semValue = $this->semStack[$stackPos - $ruleLength + 1]; } } catch (Error $e) { if (-1 === $e->getStartLine()) { $e->setStartLine($this->tokens[$this->tokenPos]->line); } $this->emitError($e); // Can't recover from this type of error return null; } /* Goto - shift nonterminal */ $lastTokenEnd = $this->tokenEndStack[$stackPos]; $stackPos -= $ruleLength; $nonTerminal = $this->ruleToNonTerminal[$rule]; $idx = $this->gotoBase[$nonTerminal] + $stateStack[$stackPos]; if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] === $nonTerminal) { $state = $this->goto[$idx]; } else { $state = $this->gotoDefault[$nonTerminal]; } ++$stackPos; $stateStack[$stackPos] = $state; $this->semStack[$stackPos] = $this->semValue; $this->tokenEndStack[$stackPos] = $lastTokenEnd; if ($ruleLength === 0) { // Empty productions use the start attributes of the lookahead token. $this->tokenStartStack[$stackPos] = $this->tokenPos; } } else { /* error */ switch ($this->errorState) { case 0: $msg = $this->getErrorMessage($symbol, $state); $this->emitError(new Error($msg, $this->getAttributesForToken($this->tokenPos))); // Break missing intentionally // no break case 1: case 2: $this->errorState = 3; // Pop until error-expecting state uncovered while (!( (($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) || ($state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) ) || ($action = $this->action[$idx]) === $this->defaultAction) { // Not totally sure about this if ($stackPos <= 0) { // Could not recover from error return null; } $state = $stateStack[--$stackPos]; //$this->tracePop($state); } //$this->traceShift($this->errorSymbol); ++$stackPos; $stateStack[$stackPos] = $state = $action; // We treat the error symbol as being empty, so we reset the end attributes // to the end attributes of the last non-error symbol $this->tokenStartStack[$stackPos] = $this->tokenPos; $this->tokenEndStack[$stackPos] = $this->tokenEndStack[$stackPos - 1]; break; case 3: if ($symbol === 0) { // Reached EOF without recovering from error return null; } //$this->traceDiscard($symbol); $symbol = self::SYMBOL_NONE; break 2; } } if ($state < $this->numNonLeafStates) { break; } /* >= numNonLeafStates means shift-and-reduce */ $rule = $state - $this->numNonLeafStates; } } } protected function emitError(Error $error): void { $this->errorHandler->handleError($error); } /** * Format error message including expected tokens. * * @param int $symbol Unexpected symbol * @param int $state State at time of error * * @return string Formatted error message */ protected function getErrorMessage(int $symbol, int $state): string { $expectedString = ''; if ($expected = $this->getExpectedTokens($state)) { $expectedString = ', expecting ' . implode(' or ', $expected); } return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString; } /** * Get limited number of expected tokens in given state. * * @param int $state State * * @return string[] Expected tokens. If too many, an empty array is returned. */ protected function getExpectedTokens(int $state): array { $expected = []; $base = $this->actionBase[$state]; foreach ($this->symbolToName as $symbol => $name) { $idx = $base + $symbol; if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol ) { if ($this->action[$idx] !== $this->unexpectedTokenRule && $this->action[$idx] !== $this->defaultAction && $symbol !== $this->errorSymbol ) { if (count($expected) === 4) { /* Too many expected tokens */ return []; } $expected[] = $name; } } } return $expected; } /** * Get attributes for a node with the given start and end token positions. * * @param int $tokenStartPos Token position the node starts at * @param int $tokenEndPos Token position the node ends at * @return array Attributes */ protected function getAttributes(int $tokenStartPos, int $tokenEndPos): array { $startToken = $this->tokens[$tokenStartPos]; $afterEndToken = $this->tokens[$tokenEndPos + 1]; return [ 'startLine' => $startToken->line, 'startTokenPos' => $tokenStartPos, 'startFilePos' => $startToken->pos, 'endLine' => $afterEndToken->line, 'endTokenPos' => $tokenEndPos, 'endFilePos' => $afterEndToken->pos - 1, ]; } /** * Get attributes for a single token at the given token position. * * @return array Attributes */ protected function getAttributesForToken(int $tokenPos): array { if ($tokenPos < \count($this->tokens) - 1) { return $this->getAttributes($tokenPos, $tokenPos); } // Get attributes for the sentinel token. $token = $this->tokens[$tokenPos]; return [ 'startLine' => $token->line, 'startTokenPos' => $tokenPos, 'startFilePos' => $token->pos, 'endLine' => $token->line, 'endTokenPos' => $tokenPos, 'endFilePos' => $token->pos, ]; } /* * Tracing functions used for debugging the parser. */ /* protected function traceNewState($state, $symbol): void { echo '% State ' . $state . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n"; } protected function traceRead($symbol): void { echo '% Reading ' . $this->symbolToName[$symbol] . "\n"; } protected function traceShift($symbol): void { echo '% Shift ' . $this->symbolToName[$symbol] . "\n"; } protected function traceAccept(): void { echo "% Accepted.\n"; } protected function traceReduce($n): void { echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n"; } protected function tracePop($state): void { echo '% Recovering, uncovered state ' . $state . "\n"; } protected function traceDiscard($symbol): void { echo '% Discard ' . $this->symbolToName[$symbol] . "\n"; } */ /* * Helper functions invoked by semantic actions */ /** * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions. * * @param Node\Stmt[] $stmts * @return Node\Stmt[] */ protected function handleNamespaces(array $stmts): array { $hasErrored = false; $style = $this->getNamespacingStyle($stmts); if (null === $style) { // not namespaced, nothing to do return $stmts; } if ('brace' === $style) { // For braced namespaces we only have to check that there are no invalid statements between the namespaces $afterFirstNamespace = false; foreach ($stmts as $stmt) { if ($stmt instanceof Node\Stmt\Namespace_) { $afterFirstNamespace = true; } elseif (!$stmt instanceof Node\Stmt\HaltCompiler && !$stmt instanceof Node\Stmt\Nop && $afterFirstNamespace && !$hasErrored) { $this->emitError(new Error( 'No code may exist outside of namespace {}', $stmt->getAttributes())); $hasErrored = true; // Avoid one error for every statement } } return $stmts; } else { // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts $resultStmts = []; $targetStmts = &$resultStmts; $lastNs = null; foreach ($stmts as $stmt) { if ($stmt instanceof Node\Stmt\Namespace_) { if ($lastNs !== null) { $this->fixupNamespaceAttributes($lastNs); } if ($stmt->stmts === null) { $stmt->stmts = []; $targetStmts = &$stmt->stmts; $resultStmts[] = $stmt; } else { // This handles the invalid case of mixed style namespaces $resultStmts[] = $stmt; $targetStmts = &$resultStmts; } $lastNs = $stmt; } elseif ($stmt instanceof Node\Stmt\HaltCompiler) { // __halt_compiler() is not moved into the namespace $resultStmts[] = $stmt; } else { $targetStmts[] = $stmt; } } if ($lastNs !== null) { $this->fixupNamespaceAttributes($lastNs); } return $resultStmts; } } private function fixupNamespaceAttributes(Node\Stmt\Namespace_ $stmt): void { // We moved the statements into the namespace node, as such the end of the namespace node // needs to be extended to the end of the statements. if (empty($stmt->stmts)) { return; } // We only move the builtin end attributes here. This is the best we can do with the // knowledge we have. $endAttributes = ['endLine', 'endFilePos', 'endTokenPos']; $lastStmt = $stmt->stmts[count($stmt->stmts) - 1]; foreach ($endAttributes as $endAttribute) { if ($lastStmt->hasAttribute($endAttribute)) { $stmt->setAttribute($endAttribute, $lastStmt->getAttribute($endAttribute)); } } } /** @return array */ private function getNamespaceErrorAttributes(Namespace_ $node): array { $attrs = $node->getAttributes(); // Adjust end attributes to only cover the "namespace" keyword, not the whole namespace. if (isset($attrs['startLine'])) { $attrs['endLine'] = $attrs['startLine']; } if (isset($attrs['startTokenPos'])) { $attrs['endTokenPos'] = $attrs['startTokenPos']; } if (isset($attrs['startFilePos'])) { $attrs['endFilePos'] = $attrs['startFilePos'] + \strlen('namespace') - 1; } return $attrs; } /** * Determine namespacing style (semicolon or brace) * * @param Node[] $stmts Top-level statements. * * @return null|string One of "semicolon", "brace" or null (no namespaces) */ private function getNamespacingStyle(array $stmts): ?string { $style = null; $hasNotAllowedStmts = false; foreach ($stmts as $i => $stmt) { if ($stmt instanceof Node\Stmt\Namespace_) { $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace'; if (null === $style) { $style = $currentStyle; if ($hasNotAllowedStmts) { $this->emitError(new Error( 'Namespace declaration statement has to be the very first statement in the script', $this->getNamespaceErrorAttributes($stmt) )); } } elseif ($style !== $currentStyle) { $this->emitError(new Error( 'Cannot mix bracketed namespace declarations with unbracketed namespace declarations', $this->getNamespaceErrorAttributes($stmt) )); // Treat like semicolon style for namespace normalization return 'semicolon'; } continue; } /* declare(), __halt_compiler() and nops can be used before a namespace declaration */ if ($stmt instanceof Node\Stmt\Declare_ || $stmt instanceof Node\Stmt\HaltCompiler || $stmt instanceof Node\Stmt\Nop) { continue; } /* There may be a hashbang line at the very start of the file */ if ($i === 0 && $stmt instanceof Node\Stmt\InlineHTML && preg_match('/\A#!.*\r?\n\z/', $stmt->value)) { continue; } /* Everything else if forbidden before namespace declarations */ $hasNotAllowedStmts = true; } return $style; } /** @return Name|Identifier */ protected function handleBuiltinTypes(Name $name) { if (!$name->isUnqualified()) { return $name; } $lowerName = $name->toLowerString(); if (!$this->phpVersion->supportsBuiltinType($lowerName)) { return $name; } return new Node\Identifier($lowerName, $name->getAttributes()); } /** * Get combined start and end attributes at a stack location * * @param int $stackPos Stack location * * @return array Combined start and end attributes */ protected function getAttributesAt(int $stackPos): array { return $this->getAttributes($this->tokenStartStack[$stackPos], $this->tokenEndStack[$stackPos]); } protected function getFloatCastKind(string $cast): int { $cast = strtolower($cast); if (strpos($cast, 'float') !== false) { return Double::KIND_FLOAT; } if (strpos($cast, 'real') !== false) { return Double::KIND_REAL; } return Double::KIND_DOUBLE; } protected function getIntCastKind(string $cast): int { $cast = strtolower($cast); if (strpos($cast, 'integer') !== false) { return Expr\Cast\Int_::KIND_INTEGER; } return Expr\Cast\Int_::KIND_INT; } protected function getBoolCastKind(string $cast): int { $cast = strtolower($cast); if (strpos($cast, 'boolean') !== false) { return Expr\Cast\Bool_::KIND_BOOLEAN; } return Expr\Cast\Bool_::KIND_BOOL; } protected function getStringCastKind(string $cast): int { $cast = strtolower($cast); if (strpos($cast, 'binary') !== false) { return Expr\Cast\String_::KIND_BINARY; } return Expr\Cast\String_::KIND_STRING; } /** @param array $attributes */ protected function parseLNumber(string $str, array $attributes, bool $allowInvalidOctal = false): Int_ { try { return Int_::fromString($str, $attributes, $allowInvalidOctal); } catch (Error $error) { $this->emitError($error); // Use dummy value return new Int_(0, $attributes); } } /** * Parse a T_NUM_STRING token into either an integer or string node. * * @param string $str Number string * @param array $attributes Attributes * * @return Int_|String_ Integer or string node. */ protected function parseNumString(string $str, array $attributes) { if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) { return new String_($str, $attributes); } $num = +$str; if (!is_int($num)) { return new String_($str, $attributes); } return new Int_($num, $attributes); } /** @param array $attributes */ protected function stripIndentation( string $string, int $indentLen, string $indentChar, bool $newlineAtStart, bool $newlineAtEnd, array $attributes ): string { if ($indentLen === 0) { return $string; } $start = $newlineAtStart ? '(?:(?<=\n)|\A)' : '(?<=\n)'; $end = $newlineAtEnd ? '(?:(?=[\r\n])|\z)' : '(?=[\r\n])'; $regex = '/' . $start . '([ \t]*)(' . $end . ')?/'; return preg_replace_callback( $regex, function ($matches) use ($indentLen, $indentChar, $attributes) { $prefix = substr($matches[1], 0, $indentLen); if (false !== strpos($prefix, $indentChar === " " ? "\t" : " ")) { $this->emitError(new Error( 'Invalid indentation - tabs and spaces cannot be mixed', $attributes )); } elseif (strlen($prefix) < $indentLen && !isset($matches[2])) { $this->emitError(new Error( 'Invalid body indentation level ' . '(expecting an indentation level of at least ' . $indentLen . ')', $attributes )); } return substr($matches[0], strlen($prefix)); }, $string ); } /** * @param string|(Expr|InterpolatedStringPart)[] $contents * @param array $attributes * @param array $endTokenAttributes */ protected function parseDocString( string $startToken, $contents, string $endToken, array $attributes, array $endTokenAttributes, bool $parseUnicodeEscape ): Expr { $kind = strpos($startToken, "'") === false ? String_::KIND_HEREDOC : String_::KIND_NOWDOC; $regex = '/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/'; $result = preg_match($regex, $startToken, $matches); assert($result === 1); $label = $matches[1]; $result = preg_match('/\A[ \t]*/', $endToken, $matches); assert($result === 1); $indentation = $matches[0]; $attributes['kind'] = $kind; $attributes['docLabel'] = $label; $attributes['docIndentation'] = $indentation; $indentHasSpaces = false !== strpos($indentation, " "); $indentHasTabs = false !== strpos($indentation, "\t"); if ($indentHasSpaces && $indentHasTabs) { $this->emitError(new Error( 'Invalid indentation - tabs and spaces cannot be mixed', $endTokenAttributes )); // Proceed processing as if this doc string is not indented $indentation = ''; } $indentLen = \strlen($indentation); $indentChar = $indentHasSpaces ? " " : "\t"; if (\is_string($contents)) { if ($contents === '') { $attributes['rawValue'] = $contents; return new String_('', $attributes); } $contents = $this->stripIndentation( $contents, $indentLen, $indentChar, true, true, $attributes ); $contents = preg_replace('~(\r\n|\n|\r)\z~', '', $contents); $attributes['rawValue'] = $contents; if ($kind === String_::KIND_HEREDOC) { $contents = String_::parseEscapeSequences($contents, null, $parseUnicodeEscape); } return new String_($contents, $attributes); } else { assert(count($contents) > 0); if (!$contents[0] instanceof Node\InterpolatedStringPart) { // If there is no leading encapsed string part, pretend there is an empty one $this->stripIndentation( '', $indentLen, $indentChar, true, false, $contents[0]->getAttributes() ); } $newContents = []; foreach ($contents as $i => $part) { if ($part instanceof Node\InterpolatedStringPart) { $isLast = $i === \count($contents) - 1; $part->value = $this->stripIndentation( $part->value, $indentLen, $indentChar, $i === 0, $isLast, $part->getAttributes() ); if ($isLast) { $part->value = preg_replace('~(\r\n|\n|\r)\z~', '', $part->value); } $part->setAttribute('rawValue', $part->value); $part->value = String_::parseEscapeSequences($part->value, null, $parseUnicodeEscape); if ('' === $part->value) { continue; } } $newContents[] = $part; } return new InterpolatedString($newContents, $attributes); } } protected function createCommentFromToken(Token $token, int $tokenPos): Comment { assert($token->id === \T_COMMENT || $token->id == \T_DOC_COMMENT); return \T_DOC_COMMENT === $token->id ? new Comment\Doc($token->text, $token->line, $token->pos, $tokenPos, $token->getEndLine(), $token->getEndPos() - 1, $tokenPos) : new Comment($token->text, $token->line, $token->pos, $tokenPos, $token->getEndLine(), $token->getEndPos() - 1, $tokenPos); } /** * Get last comment before the given token position, if any */ protected function getCommentBeforeToken(int $tokenPos): ?Comment { while (--$tokenPos >= 0) { $token = $this->tokens[$tokenPos]; if (!isset($this->dropTokens[$token->id])) { break; } if ($token->id === \T_COMMENT || $token->id === \T_DOC_COMMENT) { return $this->createCommentFromToken($token, $tokenPos); } } return null; } /** * Create a zero-length nop to capture preceding comments, if any. */ protected function maybeCreateZeroLengthNop(int $tokenPos): ?Nop { $comment = $this->getCommentBeforeToken($tokenPos); if ($comment === null) { return null; } $commentEndLine = $comment->getEndLine(); $commentEndFilePos = $comment->getEndFilePos(); $commentEndTokenPos = $comment->getEndTokenPos(); $attributes = [ 'startLine' => $commentEndLine, 'endLine' => $commentEndLine, 'startFilePos' => $commentEndFilePos + 1, 'endFilePos' => $commentEndFilePos, 'startTokenPos' => $commentEndTokenPos + 1, 'endTokenPos' => $commentEndTokenPos, ]; return new Nop($attributes); } protected function maybeCreateNop(int $tokenStartPos, int $tokenEndPos): ?Nop { if ($this->getCommentBeforeToken($tokenStartPos) === null) { return null; } return new Nop($this->getAttributes($tokenStartPos, $tokenEndPos)); } protected function handleHaltCompiler(): string { // Prevent the lexer from returning any further tokens. $nextToken = $this->tokens[$this->tokenPos + 1]; $this->tokenPos = \count($this->tokens) - 2; // Return text after __halt_compiler. return $nextToken->id === \T_INLINE_HTML ? $nextToken->text : ''; } protected function inlineHtmlHasLeadingNewline(int $stackPos): bool { $tokenPos = $this->tokenStartStack[$stackPos]; $token = $this->tokens[$tokenPos]; assert($token->id == \T_INLINE_HTML); if ($tokenPos > 0) { $prevToken = $this->tokens[$tokenPos - 1]; assert($prevToken->id == \T_CLOSE_TAG); return false !== strpos($prevToken->text, "\n") || false !== strpos($prevToken->text, "\r"); } return true; } /** * @return array */ protected function createEmptyElemAttributes(int $tokenPos): array { return $this->getAttributesForToken($tokenPos); } protected function fixupArrayDestructuring(Array_ $node): Expr\List_ { $this->createdArrays->offsetUnset($node); return new Expr\List_(array_map(function (Node\ArrayItem $item) { if ($item->value instanceof Expr\Error) { // We used Error as a placeholder for empty elements, which are legal for destructuring. return null; } if ($item->value instanceof Array_) { return new Node\ArrayItem( $this->fixupArrayDestructuring($item->value), $item->key, $item->byRef, $item->getAttributes()); } return $item; }, $node->items), ['kind' => Expr\List_::KIND_ARRAY] + $node->getAttributes()); } protected function postprocessList(Expr\List_ $node): void { foreach ($node->items as $i => $item) { if ($item->value instanceof Expr\Error) { // We used Error as a placeholder for empty elements, which are legal for destructuring. $node->items[$i] = null; } } } /** @param ElseIf_|Else_ $node */ protected function fixupAlternativeElse($node): void { // Make sure a trailing nop statement carrying comments is part of the node. $numStmts = \count($node->stmts); if ($numStmts !== 0 && $node->stmts[$numStmts - 1] instanceof Nop) { $nopAttrs = $node->stmts[$numStmts - 1]->getAttributes(); if (isset($nopAttrs['endLine'])) { $node->setAttribute('endLine', $nopAttrs['endLine']); } if (isset($nopAttrs['endFilePos'])) { $node->setAttribute('endFilePos', $nopAttrs['endFilePos']); } if (isset($nopAttrs['endTokenPos'])) { $node->setAttribute('endTokenPos', $nopAttrs['endTokenPos']); } } } protected function checkClassModifier(int $a, int $b, int $modifierPos): void { try { Modifiers::verifyClassModifier($a, $b); } catch (Error $error) { $error->setAttributes($this->getAttributesAt($modifierPos)); $this->emitError($error); } } protected function checkModifier(int $a, int $b, int $modifierPos): void { // Jumping through some hoops here because verifyModifier() is also used elsewhere try { Modifiers::verifyModifier($a, $b); } catch (Error $error) { $error->setAttributes($this->getAttributesAt($modifierPos)); $this->emitError($error); } } protected function checkParam(Param $node): void { if ($node->variadic && null !== $node->default) { $this->emitError(new Error( 'Variadic parameter cannot have a default value', $node->default->getAttributes() )); } if ($node->type instanceof Identifier && $node->type->name === 'void') { $this->emitError(new Error( 'void cannot be used as a parameter type', $node->type->getAttributes() )); } } protected function checkTryCatch(TryCatch $node): void { if (empty($node->catches) && null === $node->finally) { $this->emitError(new Error( 'Cannot use try without catch or finally', $node->getAttributes() )); } } protected function checkNamespace(Namespace_ $node): void { if (null !== $node->stmts) { foreach ($node->stmts as $stmt) { if ($stmt instanceof Namespace_) { $this->emitError(new Error( 'Namespace declarations cannot be nested', $stmt->getAttributes() )); } } } } private function checkClassName(?Identifier $name, int $namePos): void { if (null !== $name && $name->isSpecialClassName()) { $this->emitError(new Error( sprintf('Cannot use \'%s\' as class name as it is reserved', $name), $this->getAttributesAt($namePos) )); } } /** @param Name[] $interfaces */ private function checkImplementedInterfaces(array $interfaces): void { foreach ($interfaces as $interface) { if ($interface->isSpecialClassName()) { $this->emitError(new Error( sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), $interface->getAttributes() )); } } } protected function checkClass(Class_ $node, int $namePos): void { $this->checkClassName($node->name, $namePos); if ($node->extends && $node->extends->isSpecialClassName()) { $this->emitError(new Error( sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends), $node->extends->getAttributes() )); } $this->checkImplementedInterfaces($node->implements); } protected function checkInterface(Interface_ $node, int $namePos): void { $this->checkClassName($node->name, $namePos); $this->checkImplementedInterfaces($node->extends); } protected function checkEnum(Enum_ $node, int $namePos): void { $this->checkClassName($node->name, $namePos); $this->checkImplementedInterfaces($node->implements); } protected function checkClassMethod(ClassMethod $node, int $modifierPos): void { if ($node->flags & Modifiers::STATIC) { switch ($node->name->toLowerString()) { case '__construct': $this->emitError(new Error( sprintf('Constructor %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos))); break; case '__destruct': $this->emitError(new Error( sprintf('Destructor %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos))); break; case '__clone': $this->emitError(new Error( sprintf('Clone method %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos))); break; } } if ($node->flags & Modifiers::READONLY) { $this->emitError(new Error( sprintf('Method %s() cannot be readonly', $node->name), $this->getAttributesAt($modifierPos))); } } protected function checkClassConst(ClassConst $node, int $modifierPos): void { foreach ([Modifiers::STATIC, Modifiers::ABSTRACT, Modifiers::READONLY] as $modifier) { if ($node->flags & $modifier) { $this->emitError(new Error( "Cannot use '" . Modifiers::toString($modifier) . "' as constant modifier", $this->getAttributesAt($modifierPos))); } } } protected function checkUseUse(UseItem $node, int $namePos): void { if ($node->alias && $node->alias->isSpecialClassName()) { $this->emitError(new Error( sprintf( 'Cannot use %s as %s because \'%2$s\' is a special class name', $node->name, $node->alias ), $this->getAttributesAt($namePos) )); } } protected function checkPropertyHooksForMultiProperty(Property $property, int $hookPos): void { if (count($property->props) > 1) { $this->emitError(new Error( 'Cannot use hooks when declaring multiple properties', $this->getAttributesAt($hookPos))); } } /** @param PropertyHook[] $hooks */ protected function checkEmptyPropertyHookList(array $hooks, int $hookPos): void { if (empty($hooks)) { $this->emitError(new Error( 'Property hook list cannot be empty', $this->getAttributesAt($hookPos))); } } protected function checkPropertyHook(PropertyHook $hook, ?int $paramListPos): void { $name = $hook->name->toLowerString(); if ($name !== 'get' && $name !== 'set') { $this->emitError(new Error( 'Unknown hook "' . $hook->name . '", expected "get" or "set"', $hook->name->getAttributes())); } if ($name === 'get' && $paramListPos !== null) { $this->emitError(new Error( 'get hook must not have a parameter list', $this->getAttributesAt($paramListPos))); } } protected function checkPropertyHookModifiers(int $a, int $b, int $modifierPos): void { try { Modifiers::verifyModifier($a, $b); } catch (Error $error) { $error->setAttributes($this->getAttributesAt($modifierPos)); $this->emitError($error); } if ($b != Modifiers::FINAL) { $this->emitError(new Error( 'Cannot use the ' . Modifiers::toString($b) . ' modifier on a property hook', $this->getAttributesAt($modifierPos))); } } protected function checkConstantAttributes(Const_ $node): void { if ($node->attrGroups !== [] && count($node->consts) > 1) { $this->emitError(new Error( 'Cannot use attributes on multiple constants at once', $node->getAttributes())); } } protected function checkPipeOperatorParentheses(Expr $node): void { if ($node instanceof Expr\ArrowFunction && !$this->parenthesizedArrowFunctions->offsetExists($node)) { $this->emitError(new Error( 'Arrow functions on the right hand side of |> must be parenthesized', $node->getAttributes())); } } /** * @param Property|Param $node */ protected function addPropertyNameToHooks(Node $node): void { if ($node instanceof Property) { $name = $node->props[0]->name->toString(); } else { $name = $node->var->name; } foreach ($node->hooks as $hook) { $hook->setAttribute('propertyName', $name); } } /** @param array $args */ private function isSimpleExit(array $args): bool { if (\count($args) === 0) { return true; } if (\count($args) === 1) { $arg = $args[0]; return $arg instanceof Arg && $arg->name === null && $arg->byRef === false && $arg->unpack === false; } return false; } /** * @param array $args * @param array $attrs */ protected function createExitExpr(string $name, int $namePos, array $args, array $attrs): Expr { if ($this->isSimpleExit($args)) { // Create Exit node for backwards compatibility. $attrs['kind'] = strtolower($name) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; return new Expr\Exit_(\count($args) === 1 ? $args[0]->value : null, $attrs); } return new Expr\FuncCall(new Name($name, $this->getAttributesAt($namePos)), $args, $attrs); } /** * Creates the token map. * * The token map maps the PHP internal token identifiers * to the identifiers used by the Parser. Additionally it * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'. * * @return array The token map */ protected function createTokenMap(): array { $tokenMap = []; // Single-char tokens use an identity mapping. for ($i = 0; $i < 256; ++$i) { $tokenMap[$i] = $i; } foreach ($this->symbolToName as $name) { if ($name[0] === 'T') { $tokenMap[\constant($name)] = constant(static::class . '::' . $name); } } // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO $tokenMap[\T_OPEN_TAG_WITH_ECHO] = static::T_ECHO; // T_CLOSE_TAG is equivalent to ';' $tokenMap[\T_CLOSE_TAG] = ord(';'); // We have created a map from PHP token IDs to external symbol IDs. // Now map them to the internal symbol ID. $fullTokenMap = []; foreach ($tokenMap as $phpToken => $extSymbol) { $intSymbol = $this->tokenToSymbol[$extSymbol]; if ($intSymbol === $this->invalidSymbol) { continue; } $fullTokenMap[$phpToken] = $intSymbol; } return $fullTokenMap; } } isHostVersion()) { $lexer = new Lexer(); } else { $lexer = new Lexer\Emulative($version); } if ($version->id >= 80000) { return new Php8($lexer, $version); } return new Php7($lexer, $version); } /** * Create a parser targeting the newest version supported by this library. Code for older * versions will be accepted if there have been no relevant backwards-compatibility breaks in * PHP. */ public function createForNewestSupportedVersion(): Parser { return $this->createForVersion(PhpVersion::getNewestSupported()); } /** * Create a parser targeting the host PHP version, that is the PHP version we're currently * running on. This parser will not use any token emulation. */ public function createForHostVersion(): Parser { return $this->createForVersion(PhpVersion::getHostVersion()); } } 50100, 'callable' => 50400, 'bool' => 70000, 'int' => 70000, 'float' => 70000, 'string' => 70000, 'iterable' => 70100, 'void' => 70100, 'object' => 70200, 'null' => 80000, 'false' => 80000, 'mixed' => 80000, 'never' => 80100, 'true' => 80200, ]; private function __construct(int $id) { $this->id = $id; } /** * Create a PhpVersion object from major and minor version components. */ public static function fromComponents(int $major, int $minor): self { return new self($major * 10000 + $minor * 100); } /** * Get the newest PHP version supported by this library. Support for this version may be partial, * if it is still under development. */ public static function getNewestSupported(): self { return self::fromComponents(8, 5); } /** * Get the host PHP version, that is the PHP version we're currently running on. */ public static function getHostVersion(): self { return self::fromComponents(\PHP_MAJOR_VERSION, \PHP_MINOR_VERSION); } /** * Parse the version from a string like "8.1". */ public static function fromString(string $version): self { if (!preg_match('/^(\d+)\.(\d+)/', $version, $matches)) { throw new \LogicException("Invalid PHP version \"$version\""); } return self::fromComponents((int) $matches[1], (int) $matches[2]); } /** * Check whether two versions are the same. */ public function equals(PhpVersion $other): bool { return $this->id === $other->id; } /** * Check whether this version is greater than or equal to the argument. */ public function newerOrEqual(PhpVersion $other): bool { return $this->id >= $other->id; } /** * Check whether this version is older than the argument. */ public function older(PhpVersion $other): bool { return $this->id < $other->id; } /** * Check whether this is the host PHP version. */ public function isHostVersion(): bool { return $this->equals(self::getHostVersion()); } /** * Check whether this PHP version supports the given builtin type. Type name must be lowercase. */ public function supportsBuiltinType(string $type): bool { $minVersion = self::BUILTIN_TYPE_VERSIONS[$type] ?? null; return $minVersion !== null && $this->id >= $minVersion; } /** * Whether this version supports [] array literals. */ public function supportsShortArraySyntax(): bool { return $this->id >= 50400; } /** * Whether this version supports [] for destructuring. */ public function supportsShortArrayDestructuring(): bool { return $this->id >= 70100; } /** * Whether this version supports flexible heredoc/nowdoc. */ public function supportsFlexibleHeredoc(): bool { return $this->id >= 70300; } /** * Whether this version supports trailing commas in parameter lists. */ public function supportsTrailingCommaInParamList(): bool { return $this->id >= 80000; } /** * Whether this version allows "$var =& new Obj". */ public function allowsAssignNewByReference(): bool { return $this->id < 70000; } /** * Whether this version allows invalid octals like "08". */ public function allowsInvalidOctals(): bool { return $this->id < 70000; } /** * Whether this version allows DEL (\x7f) to occur in identifiers. */ public function allowsDelInIdentifiers(): bool { return $this->id < 70100; } /** * Whether this version supports yield in expression context without parentheses. */ public function supportsYieldWithoutParentheses(): bool { return $this->id >= 70000; } /** * Whether this version supports unicode escape sequences in strings. */ public function supportsUnicodeEscapes(): bool { return $this->id >= 70000; } /* * Whether this version supports attributes. */ public function supportsAttributes(): bool { return $this->id >= 80000; } public function supportsNewDereferenceWithoutParentheses(): bool { return $this->id >= 80400; } } pAttrGroups($node->attrGroups, $this->phpVersion->supportsAttributes()) . $this->pModifiers($node->flags) . ($node->type ? $this->p($node->type) . ' ' : '') . ($node->byRef ? '&' : '') . ($node->variadic ? '...' : '') . $this->p($node->var) . ($node->default ? ' = ' . $this->p($node->default) : '') . ($node->hooks ? ' {' . $this->pStmts($node->hooks) . $this->nl . '}' : ''); } protected function pArg(Node\Arg $node): string { return ($node->name ? $node->name->toString() . ': ' : '') . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value); } protected function pVariadicPlaceholder(Node\VariadicPlaceholder $node): string { return '...'; } protected function pConst(Node\Const_ $node): string { return $node->name . ' = ' . $this->p($node->value); } protected function pNullableType(Node\NullableType $node): string { return '?' . $this->p($node->type); } protected function pUnionType(Node\UnionType $node): string { $types = []; foreach ($node->types as $typeNode) { if ($typeNode instanceof Node\IntersectionType) { $types[] = '('. $this->p($typeNode) . ')'; continue; } $types[] = $this->p($typeNode); } return implode('|', $types); } protected function pIntersectionType(Node\IntersectionType $node): string { return $this->pImplode($node->types, '&'); } protected function pIdentifier(Node\Identifier $node): string { return $node->name; } protected function pVarLikeIdentifier(Node\VarLikeIdentifier $node): string { return '$' . $node->name; } protected function pAttribute(Node\Attribute $node): string { return $this->p($node->name) . ($node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : ''); } protected function pAttributeGroup(Node\AttributeGroup $node): string { return '#[' . $this->pCommaSeparated($node->attrs) . ']'; } // Names protected function pName(Name $node): string { return $node->name; } protected function pName_FullyQualified(Name\FullyQualified $node): string { return '\\' . $node->name; } protected function pName_Relative(Name\Relative $node): string { return 'namespace\\' . $node->name; } // Magic Constants protected function pScalar_MagicConst_Class(MagicConst\Class_ $node): string { return '__CLASS__'; } protected function pScalar_MagicConst_Dir(MagicConst\Dir $node): string { return '__DIR__'; } protected function pScalar_MagicConst_File(MagicConst\File $node): string { return '__FILE__'; } protected function pScalar_MagicConst_Function(MagicConst\Function_ $node): string { return '__FUNCTION__'; } protected function pScalar_MagicConst_Line(MagicConst\Line $node): string { return '__LINE__'; } protected function pScalar_MagicConst_Method(MagicConst\Method $node): string { return '__METHOD__'; } protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node): string { return '__NAMESPACE__'; } protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node): string { return '__TRAIT__'; } protected function pScalar_MagicConst_Property(MagicConst\Property $node): string { return '__PROPERTY__'; } // Scalars private function indentString(string $str): string { return str_replace("\n", $this->nl, $str); } protected function pScalar_String(Scalar\String_ $node): string { $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED); switch ($kind) { case Scalar\String_::KIND_NOWDOC: $label = $node->getAttribute('docLabel'); if ($label && !$this->containsEndLabel($node->value, $label)) { $shouldIdent = $this->phpVersion->supportsFlexibleHeredoc(); $nl = $shouldIdent ? $this->nl : $this->newline; if ($node->value === '') { return "<<<'$label'$nl$label{$this->docStringEndToken}"; } // Make sure trailing \r is not combined with following \n into CRLF. if ($node->value[strlen($node->value) - 1] !== "\r") { $value = $shouldIdent ? $this->indentString($node->value) : $node->value; return "<<<'$label'$nl$value$nl$label{$this->docStringEndToken}"; } } /* break missing intentionally */ // no break case Scalar\String_::KIND_SINGLE_QUOTED: return $this->pSingleQuotedString($node->value); case Scalar\String_::KIND_HEREDOC: $label = $node->getAttribute('docLabel'); $escaped = $this->escapeString($node->value, null); if ($label && !$this->containsEndLabel($escaped, $label)) { $nl = $this->phpVersion->supportsFlexibleHeredoc() ? $this->nl : $this->newline; if ($escaped === '') { return "<<<$label$nl$label{$this->docStringEndToken}"; } return "<<<$label$nl$escaped$nl$label{$this->docStringEndToken}"; } /* break missing intentionally */ // no break case Scalar\String_::KIND_DOUBLE_QUOTED: return '"' . $this->escapeString($node->value, '"') . '"'; } throw new \Exception('Invalid string kind'); } protected function pScalar_InterpolatedString(Scalar\InterpolatedString $node): string { if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) { $label = $node->getAttribute('docLabel'); if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) { $nl = $this->phpVersion->supportsFlexibleHeredoc() ? $this->nl : $this->newline; if (count($node->parts) === 1 && $node->parts[0] instanceof Node\InterpolatedStringPart && $node->parts[0]->value === '' ) { return "<<<$label$nl$label{$this->docStringEndToken}"; } return "<<<$label$nl" . $this->pEncapsList($node->parts, null) . "$nl$label{$this->docStringEndToken}"; } } return '"' . $this->pEncapsList($node->parts, '"') . '"'; } protected function pScalar_Int(Scalar\Int_ $node): string { if ($node->getAttribute('shouldPrintRawValue') === true) { return $node->getAttribute('rawValue'); } if ($node->value === -\PHP_INT_MAX - 1) { // PHP_INT_MIN cannot be represented as a literal, // because the sign is not part of the literal return '(-' . \PHP_INT_MAX . '-1)'; } $kind = $node->getAttribute('kind', Scalar\Int_::KIND_DEC); if (Scalar\Int_::KIND_DEC === $kind) { return (string) $node->value; } if ($node->value < 0) { $sign = '-'; $str = (string) -$node->value; } else { $sign = ''; $str = (string) $node->value; } switch ($kind) { case Scalar\Int_::KIND_BIN: return $sign . '0b' . base_convert($str, 10, 2); case Scalar\Int_::KIND_OCT: return $sign . '0' . base_convert($str, 10, 8); case Scalar\Int_::KIND_HEX: return $sign . '0x' . base_convert($str, 10, 16); } throw new \Exception('Invalid number kind'); } protected function pScalar_Float(Scalar\Float_ $node): string { if (!is_finite($node->value)) { if ($node->value === \INF) { return '1.0E+1000'; } if ($node->value === -\INF) { return '-1.0E+1000'; } else { return '\NAN'; } } // Try to find a short full-precision representation $stringValue = sprintf('%.16G', $node->value); if ($node->value !== (float) $stringValue) { $stringValue = sprintf('%.17G', $node->value); } // %G is locale dependent and there exists no locale-independent alternative. We don't want // mess with switching locales here, so let's assume that a comma is the only non-standard // decimal separator we may encounter... $stringValue = str_replace(',', '.', $stringValue); // ensure that number is really printed as float return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; } // Assignments protected function pExpr_Assign(Expr\Assign $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\Assign::class, $this->p($node->var) . ' = ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignRef(Expr\AssignRef $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\AssignRef::class, $this->p($node->var) . ' =& ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_Plus(AssignOp\Plus $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\Plus::class, $this->p($node->var) . ' += ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_Minus(AssignOp\Minus $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\Minus::class, $this->p($node->var) . ' -= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_Mul(AssignOp\Mul $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\Mul::class, $this->p($node->var) . ' *= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_Div(AssignOp\Div $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\Div::class, $this->p($node->var) . ' /= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_Concat(AssignOp\Concat $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\Concat::class, $this->p($node->var) . ' .= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_Mod(AssignOp\Mod $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\Mod::class, $this->p($node->var) . ' %= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\BitwiseAnd::class, $this->p($node->var) . ' &= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\BitwiseOr::class, $this->p($node->var) . ' |= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\BitwiseXor::class, $this->p($node->var) . ' ^= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\ShiftLeft::class, $this->p($node->var) . ' <<= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\ShiftRight::class, $this->p($node->var) . ' >>= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_Pow(AssignOp\Pow $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\Pow::class, $this->p($node->var) . ' **= ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_AssignOp_Coalesce(AssignOp\Coalesce $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(AssignOp\Coalesce::class, $this->p($node->var) . ' ??= ', $node->expr, $precedence, $lhsPrecedence); } // Binary expressions protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Plus::class, $node->left, ' + ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Minus::class, $node->left, ' - ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Mul::class, $node->left, ' * ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Div(BinaryOp\Div $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Div::class, $node->left, ' / ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Concat::class, $node->left, ' . ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Mod::class, $node->left, ' % ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\BooleanAnd::class, $node->left, ' && ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\BooleanOr::class, $node->left, ' || ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\BitwiseAnd::class, $node->left, ' & ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\BitwiseOr::class, $node->left, ' | ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\BitwiseXor::class, $node->left, ' ^ ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\ShiftLeft::class, $node->left, ' << ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\ShiftRight::class, $node->left, ' >> ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Pow::class, $node->left, ' ** ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\LogicalAnd::class, $node->left, ' and ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\LogicalOr::class, $node->left, ' or ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\LogicalXor::class, $node->left, ' xor ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Equal::class, $node->left, ' == ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\NotEqual::class, $node->left, ' != ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Identical::class, $node->left, ' === ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\NotIdentical::class, $node->left, ' !== ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Spaceship::class, $node->left, ' <=> ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Greater::class, $node->left, ' > ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\GreaterOrEqual::class, $node->left, ' >= ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Smaller::class, $node->left, ' < ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\SmallerOrEqual::class, $node->left, ' <= ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node, int $precedence, int $lhsPrecedence): string { return $this->pInfixOp(BinaryOp\Coalesce::class, $node->left, ' ?? ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_BinaryOp_Pipe(BinaryOp\Pipe $node, int $precedence, int $lhsPrecedence): string { if ($node->right instanceof Expr\ArrowFunction) { // Force parentheses around arrow functions. $lhsPrecedence = $this->precedenceMap[Expr\ArrowFunction::class][0]; } return $this->pInfixOp(BinaryOp\Pipe::class, $node->left, ' |> ', $node->right, $precedence, $lhsPrecedence); } protected function pExpr_Instanceof(Expr\Instanceof_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPostfixOp( Expr\Instanceof_::class, $node->expr, ' instanceof ' . $this->pNewOperand($node->class), $precedence, $lhsPrecedence); } // Unary expressions protected function pExpr_BooleanNot(Expr\BooleanNot $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\BooleanNot::class, '!', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_BitwiseNot(Expr\BitwiseNot $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\BitwiseNot::class, '~', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_UnaryMinus(Expr\UnaryMinus $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\UnaryMinus::class, '-', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_UnaryPlus(Expr\UnaryPlus $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\UnaryPlus::class, '+', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_PreInc(Expr\PreInc $node): string { return '++' . $this->p($node->var); } protected function pExpr_PreDec(Expr\PreDec $node): string { return '--' . $this->p($node->var); } protected function pExpr_PostInc(Expr\PostInc $node): string { return $this->p($node->var) . '++'; } protected function pExpr_PostDec(Expr\PostDec $node): string { return $this->p($node->var) . '--'; } protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\ErrorSuppress::class, '@', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_YieldFrom(Expr\YieldFrom $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\YieldFrom::class, 'yield from ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Print(Expr\Print_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\Print_::class, 'print ', $node->expr, $precedence, $lhsPrecedence); } // Casts protected function pExpr_Cast_Int(Cast\Int_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Cast\Int_::class, '(int) ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Cast_Double(Cast\Double $node, int $precedence, int $lhsPrecedence): string { $kind = $node->getAttribute('kind', Cast\Double::KIND_DOUBLE); if ($kind === Cast\Double::KIND_DOUBLE) { $cast = '(double)'; } elseif ($kind === Cast\Double::KIND_FLOAT) { $cast = '(float)'; } else { assert($kind === Cast\Double::KIND_REAL); $cast = '(real)'; } return $this->pPrefixOp(Cast\Double::class, $cast . ' ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Cast_String(Cast\String_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Cast\String_::class, '(string) ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Cast_Array(Cast\Array_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Cast\Array_::class, '(array) ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Cast_Object(Cast\Object_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Cast\Object_::class, '(object) ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Cast_Bool(Cast\Bool_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Cast\Bool_::class, '(bool) ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Cast_Unset(Cast\Unset_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Cast\Unset_::class, '(unset) ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Cast_Void(Cast\Void_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Cast\Void_::class, '(void) ', $node->expr, $precedence, $lhsPrecedence); } // Function calls and similar constructs protected function pExpr_FuncCall(Expr\FuncCall $node): string { return $this->pCallLhs($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_MethodCall(Expr\MethodCall $node): string { return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_NullsafeMethodCall(Expr\NullsafeMethodCall $node): string { return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_StaticCall(Expr\StaticCall $node): string { return $this->pStaticDereferenceLhs($node->class) . '::' . ($node->name instanceof Expr ? ($node->name instanceof Expr\Variable ? $this->p($node->name) : '{' . $this->p($node->name) . '}') : $node->name) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_Empty(Expr\Empty_ $node): string { return 'empty(' . $this->p($node->expr) . ')'; } protected function pExpr_Isset(Expr\Isset_ $node): string { return 'isset(' . $this->pCommaSeparated($node->vars) . ')'; } protected function pExpr_Eval(Expr\Eval_ $node): string { return 'eval(' . $this->p($node->expr) . ')'; } protected function pExpr_Include(Expr\Include_ $node, int $precedence, int $lhsPrecedence): string { static $map = [ Expr\Include_::TYPE_INCLUDE => 'include', Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', Expr\Include_::TYPE_REQUIRE => 'require', Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once', ]; return $this->pPrefixOp(Expr\Include_::class, $map[$node->type] . ' ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_List(Expr\List_ $node): string { $syntax = $node->getAttribute('kind', $this->phpVersion->supportsShortArrayDestructuring() ? Expr\List_::KIND_ARRAY : Expr\List_::KIND_LIST); if ($syntax === Expr\List_::KIND_ARRAY) { return '[' . $this->pMaybeMultiline($node->items, true) . ']'; } else { return 'list(' . $this->pMaybeMultiline($node->items, true) . ')'; } } // Other protected function pExpr_Error(Expr\Error $node): string { throw new \LogicException('Cannot pretty-print AST with Error nodes'); } protected function pExpr_Variable(Expr\Variable $node): string { if ($node->name instanceof Expr) { return '${' . $this->p($node->name) . '}'; } else { return '$' . $node->name; } } protected function pExpr_Array(Expr\Array_ $node): string { $syntax = $node->getAttribute('kind', $this->shortArraySyntax ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG); if ($syntax === Expr\Array_::KIND_SHORT) { return '[' . $this->pMaybeMultiline($node->items, true) . ']'; } else { return 'array(' . $this->pMaybeMultiline($node->items, true) . ')'; } } protected function pKey(?Node $node): string { if ($node === null) { return ''; } // => is not really an operator and does not typically participate in precedence resolution. // However, there is an exception if yield expressions with keys are involved: // [yield $a => $b] is interpreted as [(yield $a => $b)], so we need to ensure that // [(yield $a) => $b] is printed with parentheses. We approximate this by lowering the LHS // precedence to that of yield (which will also print unnecessary parentheses for rare low // precedence unary operators like include). $yieldPrecedence = $this->precedenceMap[Expr\Yield_::class][0]; return $this->p($node, self::MAX_PRECEDENCE, $yieldPrecedence) . ' => '; } protected function pArrayItem(Node\ArrayItem $node): string { return $this->pKey($node->key) . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value); } protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node): string { return $this->pDereferenceLhs($node->var) . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']'; } protected function pExpr_ConstFetch(Expr\ConstFetch $node): string { return $this->p($node->name); } protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node): string { return $this->pStaticDereferenceLhs($node->class) . '::' . $this->pObjectProperty($node->name); } protected function pExpr_PropertyFetch(Expr\PropertyFetch $node): string { return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name); } protected function pExpr_NullsafePropertyFetch(Expr\NullsafePropertyFetch $node): string { return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name); } protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node): string { return $this->pStaticDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name); } protected function pExpr_ShellExec(Expr\ShellExec $node): string { return '`' . $this->pEncapsList($node->parts, '`') . '`'; } protected function pExpr_Closure(Expr\Closure $node): string { return $this->pAttrGroups($node->attrGroups, true) . $this->pStatic($node->static) . 'function ' . ($node->byRef ? '&' : '') . '(' . $this->pParams($node->params) . ')' . (!empty($node->uses) ? ' use (' . $this->pCommaSeparated($node->uses) . ')' : '') . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pExpr_Match(Expr\Match_ $node): string { return 'match (' . $this->p($node->cond) . ') {' . $this->pCommaSeparatedMultiline($node->arms, true) . $this->nl . '}'; } protected function pMatchArm(Node\MatchArm $node): string { $result = ''; if ($node->conds) { for ($i = 0, $c = \count($node->conds); $i + 1 < $c; $i++) { $result .= $this->p($node->conds[$i]) . ', '; } $result .= $this->pKey($node->conds[$i]); } else { $result = 'default => '; } return $result . $this->p($node->body); } protected function pExpr_ArrowFunction(Expr\ArrowFunction $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp( Expr\ArrowFunction::class, $this->pAttrGroups($node->attrGroups, true) . $this->pStatic($node->static) . 'fn' . ($node->byRef ? '&' : '') . '(' . $this->pParams($node->params) . ')' . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') . ' => ', $node->expr, $precedence, $lhsPrecedence); } protected function pClosureUse(Node\ClosureUse $node): string { return ($node->byRef ? '&' : '') . $this->p($node->var); } protected function pExpr_New(Expr\New_ $node): string { if ($node->class instanceof Stmt\Class_) { $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : ''; return 'new ' . $this->pClassCommon($node->class, $args); } return 'new ' . $this->pNewOperand($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')'; } protected function pExpr_Clone(Expr\Clone_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\Clone_::class, 'clone ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Ternary(Expr\Ternary $node, int $precedence, int $lhsPrecedence): string { // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator. // this is okay because the part between ? and : never needs parentheses. return $this->pInfixOp(Expr\Ternary::class, $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else, $precedence, $lhsPrecedence ); } protected function pExpr_Exit(Expr\Exit_ $node): string { $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE); return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die') . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : ''); } protected function pExpr_Throw(Expr\Throw_ $node, int $precedence, int $lhsPrecedence): string { return $this->pPrefixOp(Expr\Throw_::class, 'throw ', $node->expr, $precedence, $lhsPrecedence); } protected function pExpr_Yield(Expr\Yield_ $node, int $precedence, int $lhsPrecedence): string { if ($node->value === null) { $opPrecedence = $this->precedenceMap[Expr\Yield_::class][0]; return $opPrecedence >= $lhsPrecedence ? '(yield)' : 'yield'; } else { if (!$this->phpVersion->supportsYieldWithoutParentheses()) { return '(yield ' . $this->pKey($node->key) . $this->p($node->value) . ')'; } return $this->pPrefixOp( Expr\Yield_::class, 'yield ' . $this->pKey($node->key), $node->value, $precedence, $lhsPrecedence); } } // Declarations protected function pStmt_Namespace(Stmt\Namespace_ $node): string { if ($this->canUseSemicolonNamespaces) { return 'namespace ' . $this->p($node->name) . ';' . $this->nl . $this->pStmts($node->stmts, false); } else { return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; } } protected function pStmt_Use(Stmt\Use_ $node): string { return 'use ' . $this->pUseType($node->type) . $this->pCommaSeparated($node->uses) . ';'; } protected function pStmt_GroupUse(Stmt\GroupUse $node): string { return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix) . '\{' . $this->pCommaSeparated($node->uses) . '};'; } protected function pUseItem(Node\UseItem $node): string { return $this->pUseType($node->type) . $this->p($node->name) . (null !== $node->alias ? ' as ' . $node->alias : ''); } protected function pUseType(int $type): string { return $type === Stmt\Use_::TYPE_FUNCTION ? 'function ' : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : ''); } protected function pStmt_Interface(Stmt\Interface_ $node): string { return $this->pAttrGroups($node->attrGroups) . 'interface ' . $node->name . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Enum(Stmt\Enum_ $node): string { return $this->pAttrGroups($node->attrGroups) . 'enum ' . $node->name . ($node->scalarType ? ' : ' . $this->p($node->scalarType) : '') . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Class(Stmt\Class_ $node): string { return $this->pClassCommon($node, ' ' . $node->name); } protected function pStmt_Trait(Stmt\Trait_ $node): string { return $this->pAttrGroups($node->attrGroups) . 'trait ' . $node->name . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_EnumCase(Stmt\EnumCase $node): string { return $this->pAttrGroups($node->attrGroups) . 'case ' . $node->name . ($node->expr ? ' = ' . $this->p($node->expr) : '') . ';'; } protected function pStmt_TraitUse(Stmt\TraitUse $node): string { return 'use ' . $this->pCommaSeparated($node->traits) . (empty($node->adaptations) ? ';' : ' {' . $this->pStmts($node->adaptations) . $this->nl . '}'); } protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node): string { return $this->p($node->trait) . '::' . $node->method . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';'; } protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node): string { return (null !== $node->trait ? $this->p($node->trait) . '::' : '') . $node->method . ' as' . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '') . (null !== $node->newName ? ' ' . $node->newName : '') . ';'; } protected function pStmt_Property(Stmt\Property $node): string { return $this->pAttrGroups($node->attrGroups) . (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) . ($node->type ? $this->p($node->type) . ' ' : '') . $this->pCommaSeparated($node->props) . ($node->hooks ? ' {' . $this->pStmts($node->hooks) . $this->nl . '}' : ';'); } protected function pPropertyItem(Node\PropertyItem $node): string { return '$' . $node->name . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); } protected function pPropertyHook(Node\PropertyHook $node): string { return $this->pAttrGroups($node->attrGroups) . $this->pModifiers($node->flags) . ($node->byRef ? '&' : '') . $node->name . ($node->params ? '(' . $this->pParams($node->params) . ')' : '') . (\is_array($node->body) ? ' {' . $this->pStmts($node->body) . $this->nl . '}' : ($node->body !== null ? ' => ' . $this->p($node->body) : '') . ';'); } protected function pStmt_ClassMethod(Stmt\ClassMethod $node): string { return $this->pAttrGroups($node->attrGroups) . $this->pModifiers($node->flags) . 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pParams($node->params) . ')' . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') . (null !== $node->stmts ? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}' : ';'); } protected function pStmt_ClassConst(Stmt\ClassConst $node): string { return $this->pAttrGroups($node->attrGroups) . $this->pModifiers($node->flags) . 'const ' . (null !== $node->type ? $this->p($node->type) . ' ' : '') . $this->pCommaSeparated($node->consts) . ';'; } protected function pStmt_Function(Stmt\Function_ $node): string { return $this->pAttrGroups($node->attrGroups) . 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pParams($node->params) . ')' . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Const(Stmt\Const_ $node): string { return $this->pAttrGroups($node->attrGroups) . 'const ' . $this->pCommaSeparated($node->consts) . ';'; } protected function pStmt_Declare(Stmt\Declare_ $node): string { return 'declare (' . $this->pCommaSeparated($node->declares) . ')' . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . $this->nl . '}' : ';'); } protected function pDeclareItem(Node\DeclareItem $node): string { return $node->key . '=' . $this->p($node->value); } // Control flow protected function pStmt_If(Stmt\If_ $node): string { return 'if (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}' . ($node->elseifs ? ' ' . $this->pImplode($node->elseifs, ' ') : '') . (null !== $node->else ? ' ' . $this->p($node->else) : ''); } protected function pStmt_ElseIf(Stmt\ElseIf_ $node): string { return 'elseif (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Else(Stmt\Else_ $node): string { if (\count($node->stmts) === 1 && $node->stmts[0] instanceof Stmt\If_) { // Print as "else if" rather than "else { if }" return 'else ' . $this->p($node->stmts[0]); } return 'else {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_For(Stmt\For_ $node): string { return 'for (' . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') . $this->pCommaSeparated($node->loop) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Foreach(Stmt\Foreach_ $node): string { return 'foreach (' . $this->p($node->expr) . ' as ' . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_While(Stmt\While_ $node): string { return 'while (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Do(Stmt\Do_ $node): string { return 'do {' . $this->pStmts($node->stmts) . $this->nl . '} while (' . $this->p($node->cond) . ');'; } protected function pStmt_Switch(Stmt\Switch_ $node): string { return 'switch (' . $this->p($node->cond) . ') {' . $this->pStmts($node->cases) . $this->nl . '}'; } protected function pStmt_Case(Stmt\Case_ $node): string { return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' . $this->pStmts($node->stmts); } protected function pStmt_TryCatch(Stmt\TryCatch $node): string { return 'try {' . $this->pStmts($node->stmts) . $this->nl . '}' . ($node->catches ? ' ' . $this->pImplode($node->catches, ' ') : '') . ($node->finally !== null ? ' ' . $this->p($node->finally) : ''); } protected function pStmt_Catch(Stmt\Catch_ $node): string { return 'catch (' . $this->pImplode($node->types, '|') . ($node->var !== null ? ' ' . $this->p($node->var) : '') . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Finally(Stmt\Finally_ $node): string { return 'finally {' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pStmt_Break(Stmt\Break_ $node): string { return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; } protected function pStmt_Continue(Stmt\Continue_ $node): string { return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; } protected function pStmt_Return(Stmt\Return_ $node): string { return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';'; } protected function pStmt_Label(Stmt\Label $node): string { return $node->name . ':'; } protected function pStmt_Goto(Stmt\Goto_ $node): string { return 'goto ' . $node->name . ';'; } // Other protected function pStmt_Expression(Stmt\Expression $node): string { return $this->p($node->expr) . ';'; } protected function pStmt_Echo(Stmt\Echo_ $node): string { return 'echo ' . $this->pCommaSeparated($node->exprs) . ';'; } protected function pStmt_Static(Stmt\Static_ $node): string { return 'static ' . $this->pCommaSeparated($node->vars) . ';'; } protected function pStmt_Global(Stmt\Global_ $node): string { return 'global ' . $this->pCommaSeparated($node->vars) . ';'; } protected function pStaticVar(Node\StaticVar $node): string { return $this->p($node->var) . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); } protected function pStmt_Unset(Stmt\Unset_ $node): string { return 'unset(' . $this->pCommaSeparated($node->vars) . ');'; } protected function pStmt_InlineHTML(Stmt\InlineHTML $node): string { $newline = $node->getAttribute('hasLeadingNewline', true) ? $this->newline : ''; return '?>' . $newline . $node->value . 'remaining; } protected function pStmt_Nop(Stmt\Nop $node): string { return ''; } protected function pStmt_Block(Stmt\Block $node): string { return '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } // Helpers protected function pClassCommon(Stmt\Class_ $node, string $afterClassToken): string { return $this->pAttrGroups($node->attrGroups, $node->name === null) . $this->pModifiers($node->flags) . 'class' . $afterClassToken . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; } protected function pObjectProperty(Node $node): string { if ($node instanceof Expr) { return '{' . $this->p($node) . '}'; } else { assert($node instanceof Node\Identifier); return $node->name; } } /** @param (Expr|Node\InterpolatedStringPart)[] $encapsList */ protected function pEncapsList(array $encapsList, ?string $quote): string { $return = ''; foreach ($encapsList as $element) { if ($element instanceof Node\InterpolatedStringPart) { $return .= $this->escapeString($element->value, $quote); } else { $return .= '{' . $this->p($element) . '}'; } } return $return; } protected function pSingleQuotedString(string $string): string { // It is idiomatic to only escape backslashes when necessary, i.e. when followed by ', \ or // the end of the string ('Foo\Bar' instead of 'Foo\\Bar'). However, we also don't want to // produce an odd number of backslashes, so '\\\\a' should not get rendered as '\\\a', even // though that would be legal. $regex = '/\'|\\\\(?=[\'\\\\]|$)|(?<=\\\\)\\\\/'; return '\'' . preg_replace($regex, '\\\\$0', $string) . '\''; } protected function escapeString(string $string, ?string $quote): string { if (null === $quote) { // For doc strings, don't escape newlines $escaped = addcslashes($string, "\t\f\v$\\"); // But do escape isolated \r. Combined with the terminating newline, it might get // interpreted as \r\n and dropped from the string contents. $escaped = preg_replace('/\r(?!\n)/', '\\r', $escaped); if ($this->phpVersion->supportsFlexibleHeredoc()) { $escaped = $this->indentString($escaped); } } else { $escaped = addcslashes($string, "\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 | (? $part) { if ($part instanceof Node\InterpolatedStringPart && $this->containsEndLabel($this->escapeString($part->value, null), $label, $i === 0) ) { return true; } } return false; } protected function pDereferenceLhs(Node $node): string { if (!$this->dereferenceLhsRequiresParens($node)) { return $this->p($node); } else { return '(' . $this->p($node) . ')'; } } protected function pStaticDereferenceLhs(Node $node): string { if (!$this->staticDereferenceLhsRequiresParens($node)) { return $this->p($node); } else { return '(' . $this->p($node) . ')'; } } protected function pCallLhs(Node $node): string { if (!$this->callLhsRequiresParens($node)) { return $this->p($node); } else { return '(' . $this->p($node) . ')'; } } protected function pNewOperand(Node $node): string { if (!$this->newOperandRequiresParens($node)) { return $this->p($node); } else { return '(' . $this->p($node) . ')'; } } /** * @param Node[] $nodes */ protected function hasNodeWithComments(array $nodes): bool { foreach ($nodes as $node) { if ($node && $node->getComments()) { return true; } } return false; } /** @param Node[] $nodes */ protected function pMaybeMultiline(array $nodes, bool $trailingComma = false): string { if (!$this->hasNodeWithComments($nodes)) { return $this->pCommaSeparated($nodes); } else { return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl; } } /** @param Node\Param[] $params */ private function hasParamWithAttributes(array $params): bool { foreach ($params as $param) { if ($param->attrGroups) { return true; } } return false; } /** @param Node\Param[] $params */ protected function pParams(array $params): string { if ($this->hasNodeWithComments($params) || ($this->hasParamWithAttributes($params) && !$this->phpVersion->supportsAttributes()) ) { return $this->pCommaSeparatedMultiline($params, $this->phpVersion->supportsTrailingCommaInParamList()) . $this->nl; } return $this->pCommaSeparated($params); } /** @param Node\AttributeGroup[] $nodes */ protected function pAttrGroups(array $nodes, bool $inline = false): string { $result = ''; $sep = $inline ? ' ' : $this->nl; foreach ($nodes as $node) { $result .= $this->p($node) . $sep; } return $result; } } */ protected array $precedenceMap = [ // [precedence, precedenceLHS, precedenceRHS] // Where the latter two are the precedences to use for the LHS and RHS of a binary operator, // where 1 is added to one of the sides depending on associativity. This information is not // used for unary operators and set to -1. Expr\Clone_::class => [-10, 0, 1], BinaryOp\Pow::class => [ 0, 0, 1], Expr\BitwiseNot::class => [ 10, -1, -1], Expr\UnaryPlus::class => [ 10, -1, -1], Expr\UnaryMinus::class => [ 10, -1, -1], Cast\Int_::class => [ 10, -1, -1], Cast\Double::class => [ 10, -1, -1], Cast\String_::class => [ 10, -1, -1], Cast\Array_::class => [ 10, -1, -1], Cast\Object_::class => [ 10, -1, -1], Cast\Bool_::class => [ 10, -1, -1], Cast\Unset_::class => [ 10, -1, -1], Expr\ErrorSuppress::class => [ 10, -1, -1], Expr\Instanceof_::class => [ 20, -1, -1], Expr\BooleanNot::class => [ 30, -1, -1], BinaryOp\Mul::class => [ 40, 41, 40], BinaryOp\Div::class => [ 40, 41, 40], BinaryOp\Mod::class => [ 40, 41, 40], BinaryOp\Plus::class => [ 50, 51, 50], BinaryOp\Minus::class => [ 50, 51, 50], // FIXME: This precedence is incorrect for PHP 8. BinaryOp\Concat::class => [ 50, 51, 50], BinaryOp\ShiftLeft::class => [ 60, 61, 60], BinaryOp\ShiftRight::class => [ 60, 61, 60], BinaryOp\Pipe::class => [ 65, 66, 65], BinaryOp\Smaller::class => [ 70, 70, 70], BinaryOp\SmallerOrEqual::class => [ 70, 70, 70], BinaryOp\Greater::class => [ 70, 70, 70], BinaryOp\GreaterOrEqual::class => [ 70, 70, 70], BinaryOp\Equal::class => [ 80, 80, 80], BinaryOp\NotEqual::class => [ 80, 80, 80], BinaryOp\Identical::class => [ 80, 80, 80], BinaryOp\NotIdentical::class => [ 80, 80, 80], BinaryOp\Spaceship::class => [ 80, 80, 80], BinaryOp\BitwiseAnd::class => [ 90, 91, 90], BinaryOp\BitwiseXor::class => [100, 101, 100], BinaryOp\BitwiseOr::class => [110, 111, 110], BinaryOp\BooleanAnd::class => [120, 121, 120], BinaryOp\BooleanOr::class => [130, 131, 130], BinaryOp\Coalesce::class => [140, 140, 141], Expr\Ternary::class => [150, 150, 150], Expr\Assign::class => [160, -1, -1], Expr\AssignRef::class => [160, -1, -1], AssignOp\Plus::class => [160, -1, -1], AssignOp\Minus::class => [160, -1, -1], AssignOp\Mul::class => [160, -1, -1], AssignOp\Div::class => [160, -1, -1], AssignOp\Concat::class => [160, -1, -1], AssignOp\Mod::class => [160, -1, -1], AssignOp\BitwiseAnd::class => [160, -1, -1], AssignOp\BitwiseOr::class => [160, -1, -1], AssignOp\BitwiseXor::class => [160, -1, -1], AssignOp\ShiftLeft::class => [160, -1, -1], AssignOp\ShiftRight::class => [160, -1, -1], AssignOp\Pow::class => [160, -1, -1], AssignOp\Coalesce::class => [160, -1, -1], Expr\YieldFrom::class => [170, -1, -1], Expr\Yield_::class => [175, -1, -1], Expr\Print_::class => [180, -1, -1], BinaryOp\LogicalAnd::class => [190, 191, 190], BinaryOp\LogicalXor::class => [200, 201, 200], BinaryOp\LogicalOr::class => [210, 211, 210], Expr\Include_::class => [220, -1, -1], Expr\ArrowFunction::class => [230, -1, -1], Expr\Throw_::class => [240, -1, -1], Expr\Cast\Void_::class => [250, -1, -1], ]; /** @var int Current indentation level. */ protected int $indentLevel; /** @var string String for single level of indentation */ private string $indent; /** @var int Width in spaces to indent by. */ private int $indentWidth; /** @var bool Whether to use tab indentation. */ private bool $useTabs; /** @var int Width in spaces of one tab. */ private int $tabWidth = 4; /** @var string Newline style. Does not include current indentation. */ protected string $newline; /** @var string Newline including current indentation. */ protected string $nl; /** @var string|null Token placed at end of doc string to ensure it is followed by a newline. * Null if flexible doc strings are used. */ protected ?string $docStringEndToken; /** @var bool Whether semicolon namespaces can be used (i.e. no global namespace is used) */ protected bool $canUseSemicolonNamespaces; /** @var bool Whether to use short array syntax if the node specifies no preference */ protected bool $shortArraySyntax; /** @var PhpVersion PHP version to target */ protected PhpVersion $phpVersion; /** @var TokenStream|null Original tokens for use in format-preserving pretty print */ protected ?TokenStream $origTokens; /** @var Internal\Differ Differ for node lists */ protected Differ $nodeListDiffer; /** @var array Map determining whether a certain character is a label character */ protected array $labelCharMap; /** * @var array> Map from token classes and subnode names to FIXUP_* constants. * This is used during format-preserving prints to place additional parens/braces if necessary. */ protected array $fixupMap; /** * @var array Map from "{$node->getType()}->{$subNode}" * to ['left' => $l, 'right' => $r], where $l and $r specify the token type that needs to be stripped * when removing this node. */ protected array $removalMap; /** * @var array Map from * "{$node->getType()}->{$subNode}" to [$find, $beforeToken, $extraLeft, $extraRight]. * $find is an optional token after which the insertion occurs. $extraLeft/Right * are optionally added before/after the main insertions. */ protected array $insertionMap; /** * @var array Map From "{$class}->{$subNode}" to string that should be inserted * between elements of this list subnode. */ protected array $listInsertionMap; /** * @var array */ protected array $emptyListInsertionMap; /** @var array * Map from "{$class}->{$subNode}" to [$printFn, $skipToken, $findToken] where $printFn is the function to * print the modifiers, $skipToken is the token to skip at the start and $findToken is the token before which * the modifiers should be reprinted. */ protected array $modifierChangeMap; /** * Creates a pretty printer instance using the given options. * * Supported options: * * PhpVersion $phpVersion: The PHP version to target (default to PHP 7.4). This option * controls compatibility of the generated code with older PHP * versions in cases where a simple stylistic choice exists (e.g. * array() vs []). It is safe to pretty-print an AST for a newer * PHP version while specifying an older target (but the result will * of course not be compatible with the older version in that case). * * string $newline: The newline style to use. Should be "\n" (default) or "\r\n". * * string $indent: The indentation to use. Should either be all spaces or a single * tab. Defaults to four spaces (" "). * * bool $shortArraySyntax: Whether to use [] instead of array() as the default array * syntax, if the node does not specify a format. Defaults to whether * the phpVersion support short array syntax. * * @param array{ * phpVersion?: PhpVersion, newline?: string, indent?: string, shortArraySyntax?: bool * } $options Dictionary of formatting options */ public function __construct(array $options = []) { $this->phpVersion = $options['phpVersion'] ?? PhpVersion::fromComponents(7, 4); $this->newline = $options['newline'] ?? "\n"; if ($this->newline !== "\n" && $this->newline != "\r\n") { throw new \LogicException('Option "newline" must be one of "\n" or "\r\n"'); } $this->shortArraySyntax = $options['shortArraySyntax'] ?? $this->phpVersion->supportsShortArraySyntax(); $this->docStringEndToken = $this->phpVersion->supportsFlexibleHeredoc() ? null : '_DOC_STRING_END_' . mt_rand(); $this->indent = $indent = $options['indent'] ?? ' '; if ($indent === "\t") { $this->useTabs = true; $this->indentWidth = $this->tabWidth; } elseif ($indent === \str_repeat(' ', \strlen($indent))) { $this->useTabs = false; $this->indentWidth = \strlen($indent); } else { throw new \LogicException('Option "indent" must either be all spaces or a single tab'); } } /** * Reset pretty printing state. */ protected function resetState(): void { $this->indentLevel = 0; $this->nl = $this->newline; $this->origTokens = null; } /** * Set indentation level * * @param int $level Level in number of spaces */ protected function setIndentLevel(int $level): void { $this->indentLevel = $level; if ($this->useTabs) { $tabs = \intdiv($level, $this->tabWidth); $spaces = $level % $this->tabWidth; $this->nl = $this->newline . \str_repeat("\t", $tabs) . \str_repeat(' ', $spaces); } else { $this->nl = $this->newline . \str_repeat(' ', $level); } } /** * Increase indentation level. */ protected function indent(): void { $this->indentLevel += $this->indentWidth; $this->nl .= $this->indent; } /** * Decrease indentation level. */ protected function outdent(): void { assert($this->indentLevel >= $this->indentWidth); $this->setIndentLevel($this->indentLevel - $this->indentWidth); } /** * Pretty prints an array of statements. * * @param Node[] $stmts Array of statements * * @return string Pretty printed statements */ public function prettyPrint(array $stmts): string { $this->resetState(); $this->preprocessNodes($stmts); return ltrim($this->handleMagicTokens($this->pStmts($stmts, false))); } /** * Pretty prints an expression. * * @param Expr $node Expression node * * @return string Pretty printed node */ public function prettyPrintExpr(Expr $node): string { $this->resetState(); return $this->handleMagicTokens($this->p($node)); } /** * Pretty prints a file of statements (includes the opening newline . $this->newline; } $p = "newline . $this->newline . $this->prettyPrint($stmts); if ($stmts[0] instanceof Stmt\InlineHTML) { $p = preg_replace('/^<\?php\s+\?>\r?\n?/', '', $p); } if ($stmts[count($stmts) - 1] instanceof Stmt\InlineHTML) { $p = preg_replace('/<\?php$/', '', rtrim($p)); } return $p; } /** * Preprocesses the top-level nodes to initialize pretty printer state. * * @param Node[] $nodes Array of nodes */ protected function preprocessNodes(array $nodes): void { /* We can use semicolon-namespaces unless there is a global namespace declaration */ $this->canUseSemicolonNamespaces = true; foreach ($nodes as $node) { if ($node instanceof Stmt\Namespace_ && null === $node->name) { $this->canUseSemicolonNamespaces = false; break; } } } /** * Handles (and removes) doc-string-end tokens. */ protected function handleMagicTokens(string $str): string { if ($this->docStringEndToken !== null) { // Replace doc-string-end tokens with nothing or a newline $str = str_replace( $this->docStringEndToken . ';' . $this->newline, ';' . $this->newline, $str); $str = str_replace($this->docStringEndToken, $this->newline, $str); } return $str; } /** * Pretty prints an array of nodes (statements) and indents them optionally. * * @param Node[] $nodes Array of nodes * @param bool $indent Whether to indent the printed nodes * * @return string Pretty printed statements */ protected function pStmts(array $nodes, bool $indent = true): string { if ($indent) { $this->indent(); } $result = ''; foreach ($nodes as $node) { $comments = $node->getComments(); if ($comments) { $result .= $this->nl . $this->pComments($comments); if ($node instanceof Stmt\Nop) { continue; } } $result .= $this->nl . $this->p($node); } if ($indent) { $this->outdent(); } return $result; } /** * Pretty-print an infix operation while taking precedence into account. * * @param string $class Node class of operator * @param Node $leftNode Left-hand side node * @param string $operatorString String representation of the operator * @param Node $rightNode Right-hand side node * @param int $precedence Precedence of parent operator * @param int $lhsPrecedence Precedence for unary operator on LHS of binary operator * * @return string Pretty printed infix operation */ protected function pInfixOp( string $class, Node $leftNode, string $operatorString, Node $rightNode, int $precedence, int $lhsPrecedence ): string { list($opPrecedence, $newPrecedenceLHS, $newPrecedenceRHS) = $this->precedenceMap[$class]; $prefix = ''; $suffix = ''; if ($opPrecedence >= $precedence) { $prefix = '('; $suffix = ')'; $lhsPrecedence = self::MAX_PRECEDENCE; } return $prefix . $this->p($leftNode, $newPrecedenceLHS, $newPrecedenceLHS) . $operatorString . $this->p($rightNode, $newPrecedenceRHS, $lhsPrecedence) . $suffix; } /** * Pretty-print a prefix operation while taking precedence into account. * * @param string $class Node class of operator * @param string $operatorString String representation of the operator * @param Node $node Node * @param int $precedence Precedence of parent operator * @param int $lhsPrecedence Precedence for unary operator on LHS of binary operator * * @return string Pretty printed prefix operation */ protected function pPrefixOp(string $class, string $operatorString, Node $node, int $precedence, int $lhsPrecedence): string { $opPrecedence = $this->precedenceMap[$class][0]; $prefix = ''; $suffix = ''; if ($opPrecedence >= $lhsPrecedence) { $prefix = '('; $suffix = ')'; $lhsPrecedence = self::MAX_PRECEDENCE; } $printedArg = $this->p($node, $opPrecedence, $lhsPrecedence); if (($operatorString === '+' && $printedArg[0] === '+') || ($operatorString === '-' && $printedArg[0] === '-') ) { // Avoid printing +(+$a) as ++$a and similar. $printedArg = '(' . $printedArg . ')'; } return $prefix . $operatorString . $printedArg . $suffix; } /** * Pretty-print a postfix operation while taking precedence into account. * * @param string $class Node class of operator * @param string $operatorString String representation of the operator * @param Node $node Node * @param int $precedence Precedence of parent operator * @param int $lhsPrecedence Precedence for unary operator on LHS of binary operator * * @return string Pretty printed postfix operation */ protected function pPostfixOp(string $class, Node $node, string $operatorString, int $precedence, int $lhsPrecedence): string { $opPrecedence = $this->precedenceMap[$class][0]; $prefix = ''; $suffix = ''; if ($opPrecedence >= $precedence) { $prefix = '('; $suffix = ')'; $lhsPrecedence = self::MAX_PRECEDENCE; } if ($opPrecedence < $lhsPrecedence) { $lhsPrecedence = $opPrecedence; } return $prefix . $this->p($node, $opPrecedence, $lhsPrecedence) . $operatorString . $suffix; } /** * Pretty prints an array of nodes and implodes the printed values. * * @param Node[] $nodes Array of Nodes to be printed * @param string $glue Character to implode with * * @return string Imploded pretty printed nodes> $pre */ protected function pImplode(array $nodes, string $glue = ''): string { $pNodes = []; foreach ($nodes as $node) { if (null === $node) { $pNodes[] = ''; } else { $pNodes[] = $this->p($node); } } return implode($glue, $pNodes); } /** * Pretty prints an array of nodes and implodes the printed values with commas. * * @param Node[] $nodes Array of Nodes to be printed * * @return string Comma separated pretty printed nodes */ protected function pCommaSeparated(array $nodes): string { return $this->pImplode($nodes, ', '); } /** * Pretty prints a comma-separated list of nodes in multiline style, including comments. * * The result includes a leading newline and one level of indentation (same as pStmts). * * @param Node[] $nodes Array of Nodes to be printed * @param bool $trailingComma Whether to use a trailing comma * * @return string Comma separated pretty printed nodes in multiline style */ protected function pCommaSeparatedMultiline(array $nodes, bool $trailingComma): string { $this->indent(); $result = ''; $lastIdx = count($nodes) - 1; foreach ($nodes as $idx => $node) { if ($node !== null) { $comments = $node->getComments(); if ($comments) { $result .= $this->nl . $this->pComments($comments); } $result .= $this->nl . $this->p($node); } else { $result .= $this->nl; } if ($trailingComma || $idx !== $lastIdx) { $result .= ','; } } $this->outdent(); return $result; } /** * Prints reformatted text of the passed comments. * * @param Comment[] $comments List of comments * * @return string Reformatted text of comments */ protected function pComments(array $comments): string { $formattedComments = []; foreach ($comments as $comment) { $formattedComments[] = str_replace("\n", $this->nl, $comment->getReformattedText()); } return implode($this->nl, $formattedComments); } /** * Perform a format-preserving pretty print of an AST. * * The format preservation is best effort. For some changes to the AST the formatting will not * be preserved (at least not locally). * * In order to use this method a number of prerequisites must be satisfied: * * The startTokenPos and endTokenPos attributes in the lexer must be enabled. * * The CloningVisitor must be run on the AST prior to modification. * * The original tokens must be provided, using the getTokens() method on the lexer. * * @param Node[] $stmts Modified AST with links to original AST * @param Node[] $origStmts Original AST with token offset information * @param Token[] $origTokens Tokens of the original code */ public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens): string { $this->initializeNodeListDiffer(); $this->initializeLabelCharMap(); $this->initializeFixupMap(); $this->initializeRemovalMap(); $this->initializeInsertionMap(); $this->initializeListInsertionMap(); $this->initializeEmptyListInsertionMap(); $this->initializeModifierChangeMap(); $this->resetState(); $this->origTokens = new TokenStream($origTokens, $this->tabWidth); $this->preprocessNodes($stmts); $pos = 0; $result = $this->pArray($stmts, $origStmts, $pos, 0, 'File', 'stmts', null); if (null !== $result) { $result .= $this->origTokens->getTokenCode($pos, count($origTokens) - 1, 0); } else { // Fallback // TODO Add newline . $this->pStmts($stmts, false); } return $this->handleMagicTokens($result); } protected function pFallback(Node $node, int $precedence, int $lhsPrecedence): string { return $this->{'p' . $node->getType()}($node, $precedence, $lhsPrecedence); } /** * Pretty prints a node. * * This method also handles formatting preservation for nodes. * * @param Node $node Node to be pretty printed * @param int $precedence Precedence of parent operator * @param int $lhsPrecedence Precedence for unary operator on LHS of binary operator * @param bool $parentFormatPreserved Whether parent node has preserved formatting * * @return string Pretty printed node */ protected function p( Node $node, int $precedence = self::MAX_PRECEDENCE, int $lhsPrecedence = self::MAX_PRECEDENCE, bool $parentFormatPreserved = false ): string { // No orig tokens means this is a normal pretty print without preservation of formatting if (!$this->origTokens) { return $this->{'p' . $node->getType()}($node, $precedence, $lhsPrecedence); } /** @var Node|null $origNode */ $origNode = $node->getAttribute('origNode'); if (null === $origNode) { return $this->pFallback($node, $precedence, $lhsPrecedence); } $class = \get_class($node); \assert($class === \get_class($origNode)); $startPos = $origNode->getStartTokenPos(); $endPos = $origNode->getEndTokenPos(); \assert($startPos >= 0 && $endPos >= 0); $fallbackNode = $node; if ($node instanceof Expr\New_ && $node->class instanceof Stmt\Class_) { // Normalize node structure of anonymous classes assert($origNode instanceof Expr\New_); $node = PrintableNewAnonClassNode::fromNewNode($node); $origNode = PrintableNewAnonClassNode::fromNewNode($origNode); $class = PrintableNewAnonClassNode::class; } // InlineHTML node does not contain closing and opening PHP tags. If the parent formatting // is not preserved, then we need to use the fallback code to make sure the tags are // printed. if ($node instanceof Stmt\InlineHTML && !$parentFormatPreserved) { return $this->pFallback($fallbackNode, $precedence, $lhsPrecedence); } $indentAdjustment = $this->indentLevel - $this->origTokens->getIndentationBefore($startPos); $type = $node->getType(); $fixupInfo = $this->fixupMap[$class] ?? null; $result = ''; $pos = $startPos; foreach ($node->getSubNodeNames() as $subNodeName) { $subNode = $node->$subNodeName; $origSubNode = $origNode->$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->pArray( $subNode, $origSubNode, $pos, $indentAdjustment, $class, $subNodeName, $fixupInfo[$subNodeName] ?? null ); if (null === $listResult) { return $this->pFallback($fallbackNode, $precedence, $lhsPrecedence); } $result .= $listResult; continue; } // Check if this is a modifier change $key = $class . '->' . $subNodeName; if (!isset($this->modifierChangeMap[$key])) { return $this->pFallback($fallbackNode, $precedence, $lhsPrecedence); } [$printFn, $skipToken, $findToken] = $this->modifierChangeMap[$key]; $skipWSPos = $this->origTokens->skipRight($pos, $skipToken); $result .= $this->origTokens->getTokenCode($pos, $skipWSPos, $indentAdjustment); $result .= $this->$printFn($subNode); $pos = $this->origTokens->findRight($skipWSPos, $findToken); continue; } $extraLeft = ''; $extraRight = ''; if ($origSubNode !== null) { $subStartPos = $origSubNode->getStartTokenPos(); $subEndPos = $origSubNode->getEndTokenPos(); \assert($subStartPos >= 0 && $subEndPos >= 0); } else { if ($subNode === null) { // Both null, nothing to do continue; } // A node has been inserted, check if we have insertion information for it $key = $type . '->' . $subNodeName; if (!isset($this->insertionMap[$key])) { return $this->pFallback($fallbackNode, $precedence, $lhsPrecedence); } list($findToken, $beforeToken, $extraLeft, $extraRight) = $this->insertionMap[$key]; if (null !== $findToken) { $subStartPos = $this->origTokens->findRight($pos, $findToken) + (int) !$beforeToken; } else { $subStartPos = $pos; } if (null === $extraLeft && null !== $extraRight) { // If inserting on the right only, skipping whitespace looks better $subStartPos = $this->origTokens->skipRightWhitespace($subStartPos); } $subEndPos = $subStartPos - 1; } if (null === $subNode) { // A node has been removed, check if we have removal information for it $key = $type . '->' . $subNodeName; if (!isset($this->removalMap[$key])) { return $this->pFallback($fallbackNode, $precedence, $lhsPrecedence); } // Adjust positions to account for additional tokens that must be skipped $removalInfo = $this->removalMap[$key]; if (isset($removalInfo['left'])) { $subStartPos = $this->origTokens->skipLeft($subStartPos - 1, $removalInfo['left']) + 1; } if (isset($removalInfo['right'])) { $subEndPos = $this->origTokens->skipRight($subEndPos + 1, $removalInfo['right']) - 1; } } $result .= $this->origTokens->getTokenCode($pos, $subStartPos, $indentAdjustment); if (null !== $subNode) { $result .= $extraLeft; $origIndentLevel = $this->indentLevel; $this->setIndentLevel(max($this->origTokens->getIndentationBefore($subStartPos) + $indentAdjustment, 0)); // If it's the same node that was previously in this position, it certainly doesn't // need fixup. It's important to check this here, because our fixup checks are more // conservative than strictly necessary. if (isset($fixupInfo[$subNodeName]) && $subNode->getAttribute('origNode') !== $origSubNode ) { $fixup = $fixupInfo[$subNodeName]; $res = $this->pFixup($fixup, $subNode, $class, $subStartPos, $subEndPos); } else { $res = $this->p($subNode, self::MAX_PRECEDENCE, self::MAX_PRECEDENCE, true); } $this->safeAppend($result, $res); $this->setIndentLevel($origIndentLevel); $result .= $extraRight; } $pos = $subEndPos + 1; } $result .= $this->origTokens->getTokenCode($pos, $endPos + 1, $indentAdjustment); return $result; } /** * Perform a format-preserving pretty print of an array. * * @param Node[] $nodes New nodes * @param Node[] $origNodes Original nodes * @param int $pos Current token position (updated by reference) * @param int $indentAdjustment Adjustment for indentation * @param string $parentNodeClass Class of the containing node. * @param string $subNodeName Name of array subnode. * @param null|int $fixup Fixup information for array item nodes * * @return null|string Result of pretty print or null if cannot preserve formatting */ protected function pArray( array $nodes, array $origNodes, int &$pos, int $indentAdjustment, string $parentNodeClass, string $subNodeName, ?int $fixup ): ?string { $diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes); $mapKey = $parentNodeClass . '->' . $subNodeName; $insertStr = $this->listInsertionMap[$mapKey] ?? null; $isStmtList = $subNodeName === 'stmts'; $beforeFirstKeepOrReplace = true; $skipRemovedNode = false; $delayedAdd = []; $lastElemIndentLevel = $this->indentLevel; $insertNewline = false; if ($insertStr === "\n") { $insertStr = ''; $insertNewline = true; } if ($isStmtList && \count($origNodes) === 1 && \count($nodes) !== 1) { $startPos = $origNodes[0]->getStartTokenPos(); $endPos = $origNodes[0]->getEndTokenPos(); \assert($startPos >= 0 && $endPos >= 0); if (!$this->origTokens->haveBraces($startPos, $endPos)) { // This was a single statement without braces, but either additional statements // have been added, or the single statement has been removed. This requires the // addition of braces. For now fall back. // TODO: Try to preserve formatting return null; } } $result = ''; foreach ($diff as $i => $diffElem) { $diffType = $diffElem->type; /** @var Node|string|null $arrItem */ $arrItem = $diffElem->new; /** @var Node|string|null $origArrItem */ $origArrItem = $diffElem->old; if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) { $beforeFirstKeepOrReplace = false; if ($origArrItem === null || $arrItem === null) { // We can only handle the case where both are null if ($origArrItem === $arrItem) { continue; } return null; } if (!$arrItem instanceof Node || !$origArrItem instanceof Node) { // We can only deal with nodes. This can occur for Names, which use string arrays. return null; } $itemStartPos = $origArrItem->getStartTokenPos(); $itemEndPos = $origArrItem->getEndTokenPos(); \assert($itemStartPos >= 0 && $itemEndPos >= 0 && $itemStartPos >= $pos); $origIndentLevel = $this->indentLevel; $lastElemIndentLevel = max($this->origTokens->getIndentationBefore($itemStartPos) + $indentAdjustment, 0); $this->setIndentLevel($lastElemIndentLevel); $comments = $arrItem->getComments(); $origComments = $origArrItem->getComments(); $commentStartPos = $origComments ? $origComments[0]->getStartTokenPos() : $itemStartPos; \assert($commentStartPos >= 0); if ($commentStartPos < $pos) { // Comments may be assigned to multiple nodes if they start at the same position. // Make sure we don't try to print them multiple times. $commentStartPos = $itemStartPos; } if ($skipRemovedNode) { if ($isStmtList && $this->origTokens->haveTagInRange($pos, $itemStartPos)) { // We'd remove an opening/closing PHP tag. // TODO: Preserve formatting. $this->setIndentLevel($origIndentLevel); return null; } } else { $result .= $this->origTokens->getTokenCode( $pos, $commentStartPos, $indentAdjustment); } if (!empty($delayedAdd)) { /** @var Node $delayedAddNode */ foreach ($delayedAdd as $delayedAddNode) { if ($insertNewline) { $delayedAddComments = $delayedAddNode->getComments(); if ($delayedAddComments) { $result .= $this->pComments($delayedAddComments) . $this->nl; } } $this->safeAppend($result, $this->p($delayedAddNode, self::MAX_PRECEDENCE, self::MAX_PRECEDENCE, true)); if ($insertNewline) { $result .= $insertStr . $this->nl; } else { $result .= $insertStr; } } $delayedAdd = []; } if ($comments !== $origComments) { if ($comments) { $result .= $this->pComments($comments) . $this->nl; } } else { $result .= $this->origTokens->getTokenCode( $commentStartPos, $itemStartPos, $indentAdjustment); } // If we had to remove anything, we have done so now. $skipRemovedNode = false; } elseif ($diffType === DiffElem::TYPE_ADD) { if (null === $insertStr) { // We don't have insertion information for this list type return null; } if (!$arrItem instanceof Node) { // We only support list insertion of nodes. return null; } // We go multiline if the original code was multiline, // or if it's an array item with a comment above it. // Match always uses multiline formatting. if ($insertStr === ', ' && ($this->isMultiline($origNodes) || $arrItem->getComments() || $parentNodeClass === Expr\Match_::class) ) { $insertStr = ','; $insertNewline = true; } if ($beforeFirstKeepOrReplace) { // Will be inserted at the next "replace" or "keep" element $delayedAdd[] = $arrItem; continue; } $itemStartPos = $pos; $itemEndPos = $pos - 1; $origIndentLevel = $this->indentLevel; $this->setIndentLevel($lastElemIndentLevel); if ($insertNewline) { $result .= $insertStr . $this->nl; $comments = $arrItem->getComments(); if ($comments) { $result .= $this->pComments($comments) . $this->nl; } } else { $result .= $insertStr; } } elseif ($diffType === DiffElem::TYPE_REMOVE) { if (!$origArrItem instanceof Node) { // We only support removal for nodes return null; } $itemStartPos = $origArrItem->getStartTokenPos(); $itemEndPos = $origArrItem->getEndTokenPos(); \assert($itemStartPos >= 0 && $itemEndPos >= 0); // Consider comments part of the node. $origComments = $origArrItem->getComments(); if ($origComments) { $itemStartPos = $origComments[0]->getStartTokenPos(); } 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. $result .= $this->origTokens->getTokenCode( $pos, $itemStartPos, $indentAdjustment); $skipRemovedNode = true; } else { if ($isStmtList && $this->origTokens->haveTagInRange($pos, $itemStartPos)) { // We'd remove an opening/closing PHP tag. // TODO: Preserve formatting. return null; } } $pos = $itemEndPos + 1; continue; } else { throw new \Exception("Shouldn't happen"); } if (null !== $fixup && $arrItem->getAttribute('origNode') !== $origArrItem) { $res = $this->pFixup($fixup, $arrItem, null, $itemStartPos, $itemEndPos); } else { $res = $this->p($arrItem, self::MAX_PRECEDENCE, self::MAX_PRECEDENCE, true); } $this->safeAppend($result, $res); $this->setIndentLevel($origIndentLevel); $pos = $itemEndPos + 1; } if ($skipRemovedNode) { // TODO: Support removing single node. return null; } if (!empty($delayedAdd)) { if (!isset($this->emptyListInsertionMap[$mapKey])) { return null; } list($findToken, $extraLeft, $extraRight) = $this->emptyListInsertionMap[$mapKey]; if (null !== $findToken) { // For anon classes skip to the class keyword. $isAnonClassArgs = $mapKey === PrintableNewAnonClassNode::class . '->args'; if ($isAnonClassArgs) { $insertPos = $this->origTokens->findRight($pos, \T_CLASS) + 1; $result .= $this->origTokens->getTokenCode($pos, $insertPos, $indentAdjustment); $pos = $insertPos; } // If "new Foo" was used without arguments, we need to convert to "new Foo()". if (($mapKey === Expr\New_::class . '->args' || $isAnonClassArgs) && !$this->origTokens->haveTokenImmediatelyAfter($pos - 1, '(') ) { $extraLeft = '('; $extraRight = ')'; } else { $insertPos = $this->origTokens->findRight($pos, $findToken) + 1; $result .= $this->origTokens->getTokenCode($pos, $insertPos, $indentAdjustment); $pos = $insertPos; } } $first = true; $result .= $extraLeft; foreach ($delayedAdd as $delayedAddNode) { if (!$first) { $result .= $insertStr; if ($insertNewline) { $result .= $this->nl; } } $result .= $this->p($delayedAddNode, self::MAX_PRECEDENCE, self::MAX_PRECEDENCE, true); $first = false; } $result .= $extraRight === "\n" ? $this->nl : $extraRight; } return $result; } /** * Print node with fixups. * * Fixups here refer to the addition of extra parentheses, braces or other characters, that * are required to preserve program semantics in a certain context (e.g. to maintain precedence * or because only certain expressions are allowed in certain places). * * @param int $fixup Fixup type * @param Node $subNode Subnode to print * @param string|null $parentClass Class of parent node * @param int $subStartPos Original start pos of subnode * @param int $subEndPos Original end pos of subnode * * @return string Result of fixed-up print of subnode */ protected function pFixup(int $fixup, Node $subNode, ?string $parentClass, int $subStartPos, int $subEndPos): string { switch ($fixup) { case self::FIXUP_PREC_LEFT: // We use a conservative approximation where lhsPrecedence == precedence. if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) { $precedence = $this->precedenceMap[$parentClass][1]; return $this->p($subNode, $precedence, $precedence); } break; case self::FIXUP_PREC_RIGHT: if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) { $precedence = $this->precedenceMap[$parentClass][2]; return $this->p($subNode, $precedence, $precedence); } break; case self::FIXUP_PREC_UNARY: if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) { $precedence = $this->precedenceMap[$parentClass][0]; return $this->p($subNode, $precedence, $precedence); } break; case self::FIXUP_CALL_LHS: if ($this->callLhsRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos) ) { return '(' . $this->p($subNode) . ')'; } break; case self::FIXUP_DEREF_LHS: if ($this->dereferenceLhsRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos) ) { return '(' . $this->p($subNode) . ')'; } break; case self::FIXUP_STATIC_DEREF_LHS: if ($this->staticDereferenceLhsRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos) ) { return '(' . $this->p($subNode) . ')'; } break; case self::FIXUP_NEW: if ($this->newOperandRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos)) { return '(' . $this->p($subNode) . ')'; } break; case self::FIXUP_BRACED_NAME: case self::FIXUP_VAR_BRACED_NAME: if ($subNode instanceof Expr && !$this->origTokens->haveBraces($subStartPos, $subEndPos) ) { return ($fixup === self::FIXUP_VAR_BRACED_NAME ? '$' : '') . '{' . $this->p($subNode) . '}'; } break; case self::FIXUP_ENCAPSED: if (!$subNode instanceof Node\InterpolatedStringPart && !$this->origTokens->haveBraces($subStartPos, $subEndPos) ) { return '{' . $this->p($subNode) . '}'; } break; default: throw new \Exception('Cannot happen'); } // Nothing special to do return $this->p($subNode); } /** * Appends to a string, ensuring whitespace between label characters. * * Example: "echo" and "$x" result in "echo$x", but "echo" and "x" result in "echo x". * Without safeAppend the result would be "echox", which does not preserve semantics. */ protected function safeAppend(string &$str, string $append): void { if ($str === "") { $str = $append; return; } if ($append === "") { return; } if (!$this->labelCharMap[$append[0]] || !$this->labelCharMap[$str[\strlen($str) - 1]]) { $str .= $append; } else { $str .= " " . $append; } } /** * Determines whether the LHS of a call must be wrapped in parenthesis. * * @param Node $node LHS of a call * * @return bool Whether parentheses are required */ protected function callLhsRequiresParens(Node $node): bool { if ($node instanceof Expr\New_) { return !$this->phpVersion->supportsNewDereferenceWithoutParentheses(); } return !($node instanceof Node\Name || $node instanceof Expr\Variable || $node instanceof Expr\ArrayDimFetch || $node instanceof Expr\FuncCall || $node instanceof Expr\MethodCall || $node instanceof Expr\NullsafeMethodCall || $node instanceof Expr\StaticCall || $node instanceof Expr\Array_); } /** * Determines whether the LHS of an array/object operation must be wrapped in parentheses. * * @param Node $node LHS of dereferencing operation * * @return bool Whether parentheses are required */ protected function dereferenceLhsRequiresParens(Node $node): bool { // A constant can occur on the LHS of an array/object deref, but not a static deref. return $this->staticDereferenceLhsRequiresParens($node) && !$node instanceof Expr\ConstFetch; } /** * Determines whether the LHS of a static operation must be wrapped in parentheses. * * @param Node $node LHS of dereferencing operation * * @return bool Whether parentheses are required */ protected function staticDereferenceLhsRequiresParens(Node $node): bool { if ($node instanceof Expr\New_) { return !$this->phpVersion->supportsNewDereferenceWithoutParentheses(); } return !($node instanceof Expr\Variable || $node instanceof Node\Name || $node instanceof Expr\ArrayDimFetch || $node instanceof Expr\PropertyFetch || $node instanceof Expr\NullsafePropertyFetch || $node instanceof Expr\StaticPropertyFetch || $node instanceof Expr\FuncCall || $node instanceof Expr\MethodCall || $node instanceof Expr\NullsafeMethodCall || $node instanceof Expr\StaticCall || $node instanceof Expr\Array_ || $node instanceof Scalar\String_ || $node instanceof Expr\ClassConstFetch); } /** * Determines whether an expression used in "new" or "instanceof" requires parentheses. * * @param Node $node New or instanceof operand * * @return bool Whether parentheses are required */ protected function newOperandRequiresParens(Node $node): bool { if ($node instanceof Node\Name || $node instanceof Expr\Variable) { return false; } if ($node instanceof Expr\ArrayDimFetch || $node instanceof Expr\PropertyFetch || $node instanceof Expr\NullsafePropertyFetch ) { return $this->newOperandRequiresParens($node->var); } if ($node instanceof Expr\StaticPropertyFetch) { return $this->newOperandRequiresParens($node->class); } return true; } /** * Print modifiers, including trailing whitespace. * * @param int $modifiers Modifier mask to print * * @return string Printed modifiers */ protected function pModifiers(int $modifiers): string { return ($modifiers & Modifiers::FINAL ? 'final ' : '') . ($modifiers & Modifiers::ABSTRACT ? 'abstract ' : '') . ($modifiers & Modifiers::PUBLIC ? 'public ' : '') . ($modifiers & Modifiers::PROTECTED ? 'protected ' : '') . ($modifiers & Modifiers::PRIVATE ? 'private ' : '') . ($modifiers & Modifiers::PUBLIC_SET ? 'public(set) ' : '') . ($modifiers & Modifiers::PROTECTED_SET ? 'protected(set) ' : '') . ($modifiers & Modifiers::PRIVATE_SET ? 'private(set) ' : '') . ($modifiers & Modifiers::STATIC ? 'static ' : '') . ($modifiers & Modifiers::READONLY ? 'readonly ' : ''); } protected function pStatic(bool $static): string { return $static ? 'static ' : ''; } /** * Determine whether a list of nodes uses multiline formatting. * * @param (Node|null)[] $nodes Node list * * @return bool Whether multiline formatting is used */ protected function isMultiline(array $nodes): bool { if (\count($nodes) < 2) { return false; } $pos = -1; foreach ($nodes as $node) { if (null === $node) { continue; } $endPos = $node->getEndTokenPos() + 1; if ($pos >= 0) { $text = $this->origTokens->getTokenCode($pos, $endPos, 0); if (false === strpos($text, "\n")) { // 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 return false; } } $pos = $endPos; } return true; } /** * Lazily initializes label char map. * * The label char map determines whether a certain character may occur in a label. */ protected function initializeLabelCharMap(): void { if (isset($this->labelCharMap)) { return; } $this->labelCharMap = []; for ($i = 0; $i < 256; $i++) { $chr = chr($i); $this->labelCharMap[$chr] = (bool) preg_match('/^[a-zA-Z0-9_\x80-\xff]$/', $chr); } if ($this->phpVersion->allowsDelInIdentifiers()) { $this->labelCharMap["\x7f"] = true; } } /** * Lazily initializes node list differ. * * The node list differ is used to determine differences between two array subnodes. */ protected function initializeNodeListDiffer(): void { if (isset($this->nodeListDiffer)) { return; } $this->nodeListDiffer = new Internal\Differ(function ($a, $b) { if ($a instanceof Node && $b instanceof Node) { return $a === $b->getAttribute('origNode'); } // Can happen for array destructuring return $a === null && $b === null; }); } /** * Lazily initializes fixup map. * * The fixup map is used to determine whether a certain subnode of a certain node may require * some kind of "fixup" operation, e.g. the addition of parenthesis or braces. */ protected function initializeFixupMap(): void { if (isset($this->fixupMap)) { return; } $this->fixupMap = [ Expr\Instanceof_::class => [ 'expr' => self::FIXUP_PREC_UNARY, 'class' => self::FIXUP_NEW, ], Expr\Ternary::class => [ 'cond' => self::FIXUP_PREC_LEFT, 'else' => self::FIXUP_PREC_RIGHT, ], Expr\Yield_::class => ['value' => self::FIXUP_PREC_UNARY], Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS], Expr\StaticCall::class => ['class' => self::FIXUP_STATIC_DEREF_LHS], Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS], Expr\ClassConstFetch::class => [ 'class' => self::FIXUP_STATIC_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME, ], Expr\New_::class => ['class' => self::FIXUP_NEW], Expr\MethodCall::class => [ 'var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME, ], Expr\NullsafeMethodCall::class => [ 'var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME, ], Expr\StaticPropertyFetch::class => [ 'class' => self::FIXUP_STATIC_DEREF_LHS, 'name' => self::FIXUP_VAR_BRACED_NAME, ], Expr\PropertyFetch::class => [ 'var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME, ], Expr\NullsafePropertyFetch::class => [ 'var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME, ], Scalar\InterpolatedString::class => [ 'parts' => self::FIXUP_ENCAPSED, ], ]; $binaryOps = [ BinaryOp\Pow::class, BinaryOp\Mul::class, BinaryOp\Div::class, BinaryOp\Mod::class, BinaryOp\Plus::class, BinaryOp\Minus::class, BinaryOp\Concat::class, BinaryOp\ShiftLeft::class, BinaryOp\ShiftRight::class, BinaryOp\Smaller::class, BinaryOp\SmallerOrEqual::class, BinaryOp\Greater::class, BinaryOp\GreaterOrEqual::class, BinaryOp\Equal::class, BinaryOp\NotEqual::class, BinaryOp\Identical::class, BinaryOp\NotIdentical::class, BinaryOp\Spaceship::class, BinaryOp\BitwiseAnd::class, BinaryOp\BitwiseXor::class, BinaryOp\BitwiseOr::class, BinaryOp\BooleanAnd::class, BinaryOp\BooleanOr::class, BinaryOp\Coalesce::class, BinaryOp\LogicalAnd::class, BinaryOp\LogicalXor::class, BinaryOp\LogicalOr::class, BinaryOp\Pipe::class, ]; foreach ($binaryOps as $binaryOp) { $this->fixupMap[$binaryOp] = [ 'left' => self::FIXUP_PREC_LEFT, 'right' => self::FIXUP_PREC_RIGHT ]; } $prefixOps = [ Expr\Clone_::class, Expr\BitwiseNot::class, Expr\BooleanNot::class, Expr\UnaryPlus::class, Expr\UnaryMinus::class, Cast\Int_::class, Cast\Double::class, Cast\String_::class, Cast\Array_::class, Cast\Object_::class, Cast\Bool_::class, Cast\Unset_::class, Expr\ErrorSuppress::class, Expr\YieldFrom::class, Expr\Print_::class, Expr\Include_::class, Expr\Assign::class, Expr\AssignRef::class, AssignOp\Plus::class, AssignOp\Minus::class, AssignOp\Mul::class, AssignOp\Div::class, AssignOp\Concat::class, AssignOp\Mod::class, AssignOp\BitwiseAnd::class, AssignOp\BitwiseOr::class, AssignOp\BitwiseXor::class, AssignOp\ShiftLeft::class, AssignOp\ShiftRight::class, AssignOp\Pow::class, AssignOp\Coalesce::class, Expr\ArrowFunction::class, Expr\Throw_::class, ]; foreach ($prefixOps as $prefixOp) { $this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_UNARY]; } } /** * Lazily initializes the removal map. * * The removal map is used to determine which additional tokens should be removed when a * certain node is replaced by null. */ protected function initializeRemovalMap(): void { if (isset($this->removalMap)) { return; } $stripBoth = ['left' => \T_WHITESPACE, 'right' => \T_WHITESPACE]; $stripLeft = ['left' => \T_WHITESPACE]; $stripRight = ['right' => \T_WHITESPACE]; $stripDoubleArrow = ['right' => \T_DOUBLE_ARROW]; $stripColon = ['left' => ':']; $stripEquals = ['left' => '=']; $this->removalMap = [ 'Expr_ArrayDimFetch->dim' => $stripBoth, 'ArrayItem->key' => $stripDoubleArrow, 'Expr_ArrowFunction->returnType' => $stripColon, 'Expr_Closure->returnType' => $stripColon, 'Expr_Exit->expr' => $stripBoth, 'Expr_Ternary->if' => $stripBoth, 'Expr_Yield->key' => $stripDoubleArrow, 'Expr_Yield->value' => $stripBoth, 'Param->type' => $stripRight, 'Param->default' => $stripEquals, 'Stmt_Break->num' => $stripBoth, 'Stmt_Catch->var' => $stripLeft, 'Stmt_ClassConst->type' => $stripRight, 'Stmt_ClassMethod->returnType' => $stripColon, 'Stmt_Class->extends' => ['left' => \T_EXTENDS], 'Stmt_Enum->scalarType' => $stripColon, 'Stmt_EnumCase->expr' => $stripEquals, 'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS], 'Stmt_Continue->num' => $stripBoth, 'Stmt_Foreach->keyVar' => $stripDoubleArrow, 'Stmt_Function->returnType' => $stripColon, 'Stmt_If->else' => $stripLeft, 'Stmt_Namespace->name' => $stripLeft, 'Stmt_Property->type' => $stripRight, 'PropertyItem->default' => $stripEquals, 'Stmt_Return->expr' => $stripBoth, 'Stmt_StaticVar->default' => $stripEquals, 'Stmt_TraitUseAdaptation_Alias->newName' => $stripLeft, 'Stmt_TryCatch->finally' => $stripLeft, // 'Stmt_Case->cond': Replace with "default" // 'Stmt_Class->name': Unclear what to do // 'Stmt_Declare->stmts': Not a plain node // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a plain node ]; } protected function initializeInsertionMap(): void { if (isset($this->insertionMap)) { return; } // TODO: "yield" where both key and value are inserted doesn't work // [$find, $beforeToken, $extraLeft, $extraRight] $this->insertionMap = [ 'Expr_ArrayDimFetch->dim' => ['[', false, null, null], 'ArrayItem->key' => [null, false, null, ' => '], 'Expr_ArrowFunction->returnType' => [')', false, ': ', null], 'Expr_Closure->returnType' => [')', false, ': ', null], 'Expr_Ternary->if' => ['?', false, ' ', ' '], 'Expr_Yield->key' => [\T_YIELD, false, null, ' => '], 'Expr_Yield->value' => [\T_YIELD, false, ' ', null], 'Param->type' => [null, false, null, ' '], 'Param->default' => [null, false, ' = ', null], 'Stmt_Break->num' => [\T_BREAK, false, ' ', null], 'Stmt_Catch->var' => [null, false, ' ', null], 'Stmt_ClassMethod->returnType' => [')', false, ': ', null], 'Stmt_ClassConst->type' => [\T_CONST, false, ' ', null], 'Stmt_Class->extends' => [null, false, ' extends ', null], 'Stmt_Enum->scalarType' => [null, false, ' : ', null], 'Stmt_EnumCase->expr' => [null, false, ' = ', null], 'Expr_PrintableNewAnonClass->extends' => [null, false, ' extends ', null], 'Stmt_Continue->num' => [\T_CONTINUE, false, ' ', null], 'Stmt_Foreach->keyVar' => [\T_AS, false, null, ' => '], 'Stmt_Function->returnType' => [')', false, ': ', null], 'Stmt_If->else' => [null, false, ' ', null], 'Stmt_Namespace->name' => [\T_NAMESPACE, false, ' ', null], 'Stmt_Property->type' => [\T_VARIABLE, true, null, ' '], 'PropertyItem->default' => [null, false, ' = ', null], 'Stmt_Return->expr' => [\T_RETURN, false, ' ', null], 'Stmt_StaticVar->default' => [null, false, ' = ', null], //'Stmt_TraitUseAdaptation_Alias->newName' => [T_AS, false, ' ', null], // TODO 'Stmt_TryCatch->finally' => [null, false, ' ', null], // 'Expr_Exit->expr': Complicated due to optional () // 'Stmt_Case->cond': Conversion from default to case // 'Stmt_Class->name': Unclear // 'Stmt_Declare->stmts': Not a proper node // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a proper node ]; } protected function initializeListInsertionMap(): void { if (isset($this->listInsertionMap)) { return; } $this->listInsertionMap = [ // special //'Expr_ShellExec->parts' => '', // TODO These need to be treated more carefully //'Scalar_InterpolatedString->parts' => '', Stmt\Catch_::class . '->types' => '|', UnionType::class . '->types' => '|', IntersectionType::class . '->types' => '&', Stmt\If_::class . '->elseifs' => ' ', Stmt\TryCatch::class . '->catches' => ' ', // comma-separated lists Expr\Array_::class . '->items' => ', ', Expr\ArrowFunction::class . '->params' => ', ', Expr\Closure::class . '->params' => ', ', Expr\Closure::class . '->uses' => ', ', Expr\FuncCall::class . '->args' => ', ', Expr\Isset_::class . '->vars' => ', ', Expr\List_::class . '->items' => ', ', Expr\MethodCall::class . '->args' => ', ', Expr\NullsafeMethodCall::class . '->args' => ', ', Expr\New_::class . '->args' => ', ', PrintableNewAnonClassNode::class . '->args' => ', ', Expr\StaticCall::class . '->args' => ', ', Stmt\ClassConst::class . '->consts' => ', ', Stmt\ClassMethod::class . '->params' => ', ', Stmt\Class_::class . '->implements' => ', ', Stmt\Enum_::class . '->implements' => ', ', PrintableNewAnonClassNode::class . '->implements' => ', ', Stmt\Const_::class . '->consts' => ', ', Stmt\Declare_::class . '->declares' => ', ', Stmt\Echo_::class . '->exprs' => ', ', Stmt\For_::class . '->init' => ', ', Stmt\For_::class . '->cond' => ', ', Stmt\For_::class . '->loop' => ', ', Stmt\Function_::class . '->params' => ', ', Stmt\Global_::class . '->vars' => ', ', Stmt\GroupUse::class . '->uses' => ', ', Stmt\Interface_::class . '->extends' => ', ', Expr\Match_::class . '->arms' => ', ', Stmt\Property::class . '->props' => ', ', Stmt\StaticVar::class . '->vars' => ', ', Stmt\TraitUse::class . '->traits' => ', ', Stmt\TraitUseAdaptation\Precedence::class . '->insteadof' => ', ', Stmt\Unset_::class . '->vars' => ', ', Stmt\UseUse::class . '->uses' => ', ', MatchArm::class . '->conds' => ', ', AttributeGroup::class . '->attrs' => ', ', PropertyHook::class . '->params' => ', ', // statement lists Expr\Closure::class . '->stmts' => "\n", Stmt\Case_::class . '->stmts' => "\n", Stmt\Catch_::class . '->stmts' => "\n", Stmt\Class_::class . '->stmts' => "\n", Stmt\Enum_::class . '->stmts' => "\n", PrintableNewAnonClassNode::class . '->stmts' => "\n", Stmt\Interface_::class . '->stmts' => "\n", Stmt\Trait_::class . '->stmts' => "\n", Stmt\ClassMethod::class . '->stmts' => "\n", Stmt\Declare_::class . '->stmts' => "\n", Stmt\Do_::class . '->stmts' => "\n", Stmt\ElseIf_::class . '->stmts' => "\n", Stmt\Else_::class . '->stmts' => "\n", Stmt\Finally_::class . '->stmts' => "\n", Stmt\Foreach_::class . '->stmts' => "\n", Stmt\For_::class . '->stmts' => "\n", Stmt\Function_::class . '->stmts' => "\n", Stmt\If_::class . '->stmts' => "\n", Stmt\Namespace_::class . '->stmts' => "\n", Stmt\Block::class . '->stmts' => "\n", // Attribute groups Stmt\Class_::class . '->attrGroups' => "\n", Stmt\Enum_::class . '->attrGroups' => "\n", Stmt\EnumCase::class . '->attrGroups' => "\n", Stmt\Interface_::class . '->attrGroups' => "\n", Stmt\Trait_::class . '->attrGroups' => "\n", Stmt\Function_::class . '->attrGroups' => "\n", Stmt\ClassMethod::class . '->attrGroups' => "\n", Stmt\ClassConst::class . '->attrGroups' => "\n", Stmt\Property::class . '->attrGroups' => "\n", PrintableNewAnonClassNode::class . '->attrGroups' => ' ', Expr\Closure::class . '->attrGroups' => ' ', Expr\ArrowFunction::class . '->attrGroups' => ' ', Param::class . '->attrGroups' => ' ', PropertyHook::class . '->attrGroups' => ' ', Stmt\Switch_::class . '->cases' => "\n", Stmt\TraitUse::class . '->adaptations' => "\n", Stmt\TryCatch::class . '->stmts' => "\n", Stmt\While_::class . '->stmts' => "\n", PropertyHook::class . '->body' => "\n", Stmt\Property::class . '->hooks' => "\n", Param::class . '->hooks' => "\n", // dummy for top-level context 'File->stmts' => "\n", ]; } protected function initializeEmptyListInsertionMap(): void { if (isset($this->emptyListInsertionMap)) { return; } // TODO Insertion into empty statement lists. // [$find, $extraLeft, $extraRight] $this->emptyListInsertionMap = [ Expr\ArrowFunction::class . '->params' => ['(', '', ''], Expr\Closure::class . '->uses' => [')', ' use (', ')'], Expr\Closure::class . '->params' => ['(', '', ''], Expr\FuncCall::class . '->args' => ['(', '', ''], Expr\MethodCall::class . '->args' => ['(', '', ''], Expr\NullsafeMethodCall::class . '->args' => ['(', '', ''], Expr\New_::class . '->args' => ['(', '', ''], PrintableNewAnonClassNode::class . '->args' => ['(', '', ''], PrintableNewAnonClassNode::class . '->implements' => [null, ' implements ', ''], Expr\StaticCall::class . '->args' => ['(', '', ''], Stmt\Class_::class . '->implements' => [null, ' implements ', ''], Stmt\Enum_::class . '->implements' => [null, ' implements ', ''], Stmt\ClassMethod::class . '->params' => ['(', '', ''], Stmt\Interface_::class . '->extends' => [null, ' extends ', ''], Stmt\Function_::class . '->params' => ['(', '', ''], Stmt\Interface_::class . '->attrGroups' => [null, '', "\n"], Stmt\Class_::class . '->attrGroups' => [null, '', "\n"], Stmt\ClassConst::class . '->attrGroups' => [null, '', "\n"], Stmt\ClassMethod::class . '->attrGroups' => [null, '', "\n"], Stmt\Function_::class . '->attrGroups' => [null, '', "\n"], Stmt\Property::class . '->attrGroups' => [null, '', "\n"], Stmt\Trait_::class . '->attrGroups' => [null, '', "\n"], Expr\ArrowFunction::class . '->attrGroups' => [null, '', ' '], Expr\Closure::class . '->attrGroups' => [null, '', ' '], Stmt\Const_::class . '->attrGroups' => [null, '', "\n"], PrintableNewAnonClassNode::class . '->attrGroups' => [\T_NEW, ' ', ''], /* These cannot be empty to start with: * Expr_Isset->vars * Stmt_Catch->types * Stmt_Const->consts * Stmt_ClassConst->consts * Stmt_Declare->declares * Stmt_Echo->exprs * Stmt_Global->vars * Stmt_GroupUse->uses * Stmt_Property->props * Stmt_StaticVar->vars * Stmt_TraitUse->traits * Stmt_TraitUseAdaptation_Precedence->insteadof * Stmt_Unset->vars * Stmt_Use->uses * UnionType->types */ /* TODO * Stmt_If->elseifs * Stmt_TryCatch->catches * Expr_Array->items * Expr_List->items * Stmt_For->init * Stmt_For->cond * Stmt_For->loop */ ]; } protected function initializeModifierChangeMap(): void { if (isset($this->modifierChangeMap)) { return; } $this->modifierChangeMap = [ Stmt\ClassConst::class . '->flags' => ['pModifiers', \T_WHITESPACE, \T_CONST], Stmt\ClassMethod::class . '->flags' => ['pModifiers', \T_WHITESPACE, \T_FUNCTION], Stmt\Class_::class . '->flags' => ['pModifiers', \T_WHITESPACE, \T_CLASS], Stmt\Property::class . '->flags' => ['pModifiers', \T_WHITESPACE, \T_VARIABLE], PrintableNewAnonClassNode::class . '->flags' => ['pModifiers', \T_NEW, \T_CLASS], Param::class . '->flags' => ['pModifiers', \T_WHITESPACE, \T_VARIABLE], PropertyHook::class . '->flags' => ['pModifiers', \T_WHITESPACE, \T_STRING], Expr\Closure::class . '->static' => ['pStatic', \T_WHITESPACE, \T_FUNCTION], Expr\ArrowFunction::class . '->static' => ['pStatic', \T_WHITESPACE, \T_FN], //Stmt\TraitUseAdaptation\Alias::class . '->newModifier' => 0, // TODO ]; // List of integer subnodes that are not modifiers: // Expr_Include->type // Stmt_GroupUse->type // Stmt_Use->type // UseItem->type } } pos + \strlen($this->text); } /** Get 1-based end line number of the token. */ public function getEndLine(): int { return $this->line + \substr_count($this->text, "\n"); } } , Sebastian Heuer , Sebastian Bergmann , and contributors 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 Arne Blankerts nor the names of 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. # Manifest Component for reading [phar.io](https://phar.io/) manifest information from a [PHP Archive (PHAR)](http://php.net/phar). ## Installation You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): composer require phar-io/manifest 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 phar-io/manifest ## Usage Examples ### Read from `manifest.xml` ```php use PharIo\Manifest\ManifestLoader; use PharIo\Manifest\ManifestSerializer; $manifest = ManifestLoader::fromFile('manifest.xml'); var_dump($manifest); echo (new ManifestSerializer)->serializeToString($manifest); ```
Output ```shell object(PharIo\Manifest\Manifest)#14 (6) { ["name":"PharIo\Manifest\Manifest":private]=> object(PharIo\Manifest\ApplicationName)#10 (1) { ["name":"PharIo\Manifest\ApplicationName":private]=> string(12) "some/library" } ["version":"PharIo\Manifest\Manifest":private]=> object(PharIo\Version\Version)#12 (5) { ["originalVersionString":"PharIo\Version\Version":private]=> string(5) "1.0.0" ["major":"PharIo\Version\Version":private]=> object(PharIo\Version\VersionNumber)#13 (1) { ["value":"PharIo\Version\VersionNumber":private]=> int(1) } ["minor":"PharIo\Version\Version":private]=> object(PharIo\Version\VersionNumber)#23 (1) { ["value":"PharIo\Version\VersionNumber":private]=> int(0) } ["patch":"PharIo\Version\Version":private]=> object(PharIo\Version\VersionNumber)#22 (1) { ["value":"PharIo\Version\VersionNumber":private]=> int(0) } ["preReleaseSuffix":"PharIo\Version\Version":private]=> NULL } ["type":"PharIo\Manifest\Manifest":private]=> object(PharIo\Manifest\Library)#6 (0) { } ["copyrightInformation":"PharIo\Manifest\Manifest":private]=> object(PharIo\Manifest\CopyrightInformation)#19 (2) { ["authors":"PharIo\Manifest\CopyrightInformation":private]=> object(PharIo\Manifest\AuthorCollection)#9 (1) { ["authors":"PharIo\Manifest\AuthorCollection":private]=> array(1) { [0]=> object(PharIo\Manifest\Author)#15 (2) { ["name":"PharIo\Manifest\Author":private]=> string(13) "Reiner Zufall" ["email":"PharIo\Manifest\Author":private]=> object(PharIo\Manifest\Email)#16 (1) { ["email":"PharIo\Manifest\Email":private]=> string(16) "reiner@zufall.de" } } } } ["license":"PharIo\Manifest\CopyrightInformation":private]=> object(PharIo\Manifest\License)#11 (2) { ["name":"PharIo\Manifest\License":private]=> string(12) "BSD-3-Clause" ["url":"PharIo\Manifest\License":private]=> object(PharIo\Manifest\Url)#18 (1) { ["url":"PharIo\Manifest\Url":private]=> string(26) "https://domain.tld/LICENSE" } } } ["requirements":"PharIo\Manifest\Manifest":private]=> object(PharIo\Manifest\RequirementCollection)#17 (1) { ["requirements":"PharIo\Manifest\RequirementCollection":private]=> array(1) { [0]=> object(PharIo\Manifest\PhpVersionRequirement)#20 (1) { ["versionConstraint":"PharIo\Manifest\PhpVersionRequirement":private]=> object(PharIo\Version\SpecificMajorAndMinorVersionConstraint)#24 (3) { ["originalValue":"PharIo\Version\AbstractVersionConstraint":private]=> string(3) "7.0" ["major":"PharIo\Version\SpecificMajorAndMinorVersionConstraint":private]=> int(7) ["minor":"PharIo\Version\SpecificMajorAndMinorVersionConstraint":private]=> int(0) } } } } ["bundledComponents":"PharIo\Manifest\Manifest":private]=> object(PharIo\Manifest\BundledComponentCollection)#8 (1) { ["bundledComponents":"PharIo\Manifest\BundledComponentCollection":private]=> array(0) { } } } ```
### Create via API ```php $bundled = new \PharIo\Manifest\BundledComponentCollection(); $bundled->add( new \PharIo\Manifest\BundledComponent('vendor/packageA', new \PharIo\Version\Version('1.2.3-dev') ) ); $manifest = new PharIo\Manifest\Manifest( new \PharIo\Manifest\ApplicationName('vendor/package'), new \PharIo\Version\Version('1.0.0'), new \PharIo\Manifest\Library(), new \PharIo\Manifest\CopyrightInformation( new \PharIo\Manifest\AuthorCollection(), new \PharIo\Manifest\License( 'BSD-3-Clause', new \PharIo\Manifest\Url('https://spdx.org/licenses/BSD-3-Clause.html') ) ), new \PharIo\Manifest\RequirementCollection(), $bundled ); echo (new ManifestSerializer)->serializeToString($manifest); ```
Output ```xml ```
{ "name": "phar-io/manifest", "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "license": "BSD-3-Clause", "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "support": { "issues": "https://github.com/phar-io/manifest/issues" }, "require": { "php": "^7.2 || ^8.0", "ext-dom": "*", "ext-phar": "*", "ext-libxml": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1" }, "autoload": { "classmap": [ "src/" ] }, "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } } } { "_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": "279b3c4fe44357abd924fdcc0cfa5664", "packages": [ { "name": "phar-io/version", "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", "source": "https://github.com/phar-io/version/tree/3.2.1" }, "time": "2022-02-21T01:04:05+00:00" } ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": "^7.2 || ^8.0", "ext-dom": "*", "ext-phar": "*", "ext-libxml": "*", "ext-xmlwriter": "*" }, "platform-dev": [], "plugin-api-version": "2.3.0" } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\Exception as VersionException; use PharIo\Version\Version; use PharIo\Version\VersionConstraintParser; use Throwable; use function sprintf; class ManifestDocumentMapper { public function map(ManifestDocument $document): Manifest { try { $contains = $document->getContainsElement(); $type = $this->mapType($contains); $copyright = $this->mapCopyright($document->getCopyrightElement()); $requirements = $this->mapRequirements($document->getRequiresElement()); $bundledComponents = $this->mapBundledComponents($document); return new Manifest( new ApplicationName($contains->getName()), new Version($contains->getVersion()), $type, $copyright, $requirements, $bundledComponents ); } catch (Throwable $e) { throw new ManifestDocumentMapperException($e->getMessage(), (int)$e->getCode(), $e); } } private function mapType(ContainsElement $contains): Type { switch ($contains->getType()) { case 'application': return Type::application(); case 'library': return Type::library(); case 'extension': return $this->mapExtension($contains->getExtensionElement()); } throw new ManifestDocumentMapperException( sprintf('Unsupported type %s', $contains->getType()) ); } private function mapCopyright(CopyrightElement $copyright): CopyrightInformation { $authors = new AuthorCollection(); foreach ($copyright->getAuthorElements() as $authorElement) { $authors->add( new Author( $authorElement->getName(), $authorElement->hasEMail() ? new Email($authorElement->getEmail()) : null ) ); } $licenseElement = $copyright->getLicenseElement(); $license = new License( $licenseElement->getType(), new Url($licenseElement->getUrl()) ); return new CopyrightInformation( $authors, $license ); } private function mapRequirements(RequiresElement $requires): RequirementCollection { $collection = new RequirementCollection(); $phpElement = $requires->getPHPElement(); $parser = new VersionConstraintParser; try { $versionConstraint = $parser->parse($phpElement->getVersion()); } catch (VersionException $e) { throw new ManifestDocumentMapperException( sprintf('Unsupported version constraint - %s', $e->getMessage()), (int)$e->getCode(), $e ); } $collection->add( new PhpVersionRequirement( $versionConstraint ) ); if (!$phpElement->hasExtElements()) { return $collection; } foreach ($phpElement->getExtElements() as $extElement) { $collection->add( new PhpExtensionRequirement($extElement->getName()) ); } return $collection; } private function mapBundledComponents(ManifestDocument $document): BundledComponentCollection { $collection = new BundledComponentCollection(); if (!$document->hasBundlesElement()) { return $collection; } foreach ($document->getBundlesElement()->getComponentElements() as $componentElement) { $collection->add( new BundledComponent( $componentElement->getName(), new Version( $componentElement->getVersion() ) ) ); } return $collection; } private function mapExtension(ExtensionElement $extension): Extension { try { $versionConstraint = (new VersionConstraintParser)->parse($extension->getCompatible()); return Type::extension( new ApplicationName($extension->getFor()), $versionConstraint ); } catch (VersionException $e) { throw new ManifestDocumentMapperException( sprintf('Unsupported version constraint - %s', $e->getMessage()), (int)$e->getCode(), $e ); } } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use function sprintf; class ManifestLoader { public static function fromFile(string $filename): Manifest { try { return (new ManifestDocumentMapper())->map( ManifestDocument::fromFile($filename) ); } catch (Exception $e) { throw new ManifestLoaderException( sprintf('Loading %s failed.', $filename), (int)$e->getCode(), $e ); } } public static function fromPhar(string $filename): Manifest { return self::fromFile('phar://' . $filename . '/manifest.xml'); } public static function fromString(string $manifest): Manifest { try { return (new ManifestDocumentMapper())->map( ManifestDocument::fromString($manifest) ); } catch (Exception $e) { throw new ManifestLoaderException( 'Processing string failed', (int)$e->getCode(), $e ); } } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\AnyVersionConstraint; use PharIo\Version\Version; use PharIo\Version\VersionConstraint; use XMLWriter; use function count; use function file_put_contents; use function str_repeat; /** @psalm-suppress MissingConstructor */ class ManifestSerializer { /** @var XMLWriter */ private $xmlWriter; public function serializeToFile(Manifest $manifest, string $filename): void { file_put_contents( $filename, $this->serializeToString($manifest) ); } public function serializeToString(Manifest $manifest): string { $this->startDocument(); $this->addContains($manifest->getName(), $manifest->getVersion(), $manifest->getType()); $this->addCopyright($manifest->getCopyrightInformation()); $this->addRequirements($manifest->getRequirements()); $this->addBundles($manifest->getBundledComponents()); return $this->finishDocument(); } private function startDocument(): void { $xmlWriter = new XMLWriter(); $xmlWriter->openMemory(); $xmlWriter->setIndent(true); $xmlWriter->setIndentString(str_repeat(' ', 4)); $xmlWriter->startDocument('1.0', 'UTF-8'); $xmlWriter->startElement('phar'); $xmlWriter->writeAttribute('xmlns', 'https://phar.io/xml/manifest/1.0'); $this->xmlWriter = $xmlWriter; } private function finishDocument(): string { $this->xmlWriter->endElement(); $this->xmlWriter->endDocument(); return $this->xmlWriter->outputMemory(); } private function addContains(ApplicationName $name, Version $version, Type $type): void { $this->xmlWriter->startElement('contains'); $this->xmlWriter->writeAttribute('name', $name->asString()); $this->xmlWriter->writeAttribute('version', $version->getVersionString()); switch (true) { case $type->isApplication(): { $this->xmlWriter->writeAttribute('type', 'application'); break; } case $type->isLibrary(): { $this->xmlWriter->writeAttribute('type', 'library'); break; } case $type->isExtension(): { $this->xmlWriter->writeAttribute('type', 'extension'); /* @var $type Extension */ $this->addExtension( $type->getApplicationName(), $type->getVersionConstraint() ); break; } default: { $this->xmlWriter->writeAttribute('type', 'custom'); } } $this->xmlWriter->endElement(); } private function addCopyright(CopyrightInformation $copyrightInformation): void { $this->xmlWriter->startElement('copyright'); foreach ($copyrightInformation->getAuthors() as $author) { $this->xmlWriter->startElement('author'); $this->xmlWriter->writeAttribute('name', $author->getName()); $this->xmlWriter->writeAttribute('email', $author->getEmail()->asString()); $this->xmlWriter->endElement(); } $license = $copyrightInformation->getLicense(); $this->xmlWriter->startElement('license'); $this->xmlWriter->writeAttribute('type', $license->getName()); $this->xmlWriter->writeAttribute('url', $license->getUrl()->asString()); $this->xmlWriter->endElement(); $this->xmlWriter->endElement(); } private function addRequirements(RequirementCollection $requirementCollection): void { $phpRequirement = new AnyVersionConstraint(); $extensions = []; foreach ($requirementCollection as $requirement) { if ($requirement instanceof PhpVersionRequirement) { $phpRequirement = $requirement->getVersionConstraint(); continue; } if ($requirement instanceof PhpExtensionRequirement) { $extensions[] = $requirement->asString(); } } $this->xmlWriter->startElement('requires'); $this->xmlWriter->startElement('php'); $this->xmlWriter->writeAttribute('version', $phpRequirement->asString()); foreach ($extensions as $extension) { $this->xmlWriter->startElement('ext'); $this->xmlWriter->writeAttribute('name', $extension); $this->xmlWriter->endElement(); } $this->xmlWriter->endElement(); $this->xmlWriter->endElement(); } private function addBundles(BundledComponentCollection $bundledComponentCollection): void { if (count($bundledComponentCollection) === 0) { return; } $this->xmlWriter->startElement('bundles'); foreach ($bundledComponentCollection as $bundledComponent) { $this->xmlWriter->startElement('component'); $this->xmlWriter->writeAttribute('name', $bundledComponent->getName()); $this->xmlWriter->writeAttribute('version', $bundledComponent->getVersion()->getVersionString()); $this->xmlWriter->endElement(); } $this->xmlWriter->endElement(); } private function addExtension(ApplicationName $applicationName, VersionConstraint $versionConstraint): void { $this->xmlWriter->startElement('extension'); $this->xmlWriter->writeAttribute('for', $applicationName->asString()); $this->xmlWriter->writeAttribute('compatible', $versionConstraint->asString()); $this->xmlWriter->endElement(); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class ElementCollectionException extends InvalidArgumentException implements Exception { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Throwable; interface Exception extends Throwable { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class InvalidApplicationNameException extends InvalidArgumentException implements Exception { public const InvalidFormat = 2; } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class InvalidEmailException extends InvalidArgumentException implements Exception { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class InvalidUrlException extends InvalidArgumentException implements Exception { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use RuntimeException; class ManifestDocumentException extends RuntimeException implements Exception { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use LibXMLError; use function sprintf; class ManifestDocumentLoadingException extends \Exception implements Exception { /** @var LibXMLError[] */ private $libxmlErrors; /** * ManifestDocumentLoadingException constructor. * * @param LibXMLError[] $libxmlErrors */ public function __construct(array $libxmlErrors) { $this->libxmlErrors = $libxmlErrors; $first = $this->libxmlErrors[0]; parent::__construct( sprintf( '%s (Line: %d / Column: %d / File: %s)', $first->message, $first->line, $first->column, $first->file ), $first->code ); } /** * @return LibXMLError[] */ public function getLibxmlErrors(): array { return $this->libxmlErrors; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use RuntimeException; class ManifestDocumentMapperException extends RuntimeException implements Exception { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use RuntimeException; class ManifestElementException extends RuntimeException implements Exception { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ManifestLoaderException extends \Exception implements Exception { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use InvalidArgumentException; class NoEmailAddressException extends InvalidArgumentException implements Exception { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class Application extends Type { public function isApplication(): bool { return true; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use function preg_match; use function sprintf; class ApplicationName { /** @var string */ private $name; public function __construct(string $name) { $this->ensureValidFormat($name); $this->name = $name; } public function asString(): string { return $this->name; } public function isEqual(ApplicationName $name): bool { return $this->name === $name->name; } private function ensureValidFormat(string $name): void { if (!preg_match('#\w/\w#', $name)) { throw new InvalidApplicationNameException( sprintf('Format of name "%s" is not valid - expected: vendor/packagename', $name), InvalidApplicationNameException::InvalidFormat ); } } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use function sprintf; class Author { /** @var string */ private $name; /** @var null|Email */ private $email; public function __construct(string $name, ?Email $email = null) { $this->name = $name; $this->email = $email; } public function asString(): string { if (!$this->hasEmail()) { return $this->name; } return sprintf( '%s <%s>', $this->name, $this->email->asString() ); } public function getName(): string { return $this->name; } /** * @psalm-assert-if-true Email $this->email */ public function hasEmail(): bool { return $this->email !== null; } public function getEmail(): Email { if (!$this->hasEmail()) { throw new NoEmailAddressException(); } return $this->email; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Countable; use IteratorAggregate; use function count; /** @template-implements IteratorAggregate */ class AuthorCollection implements Countable, IteratorAggregate { /** @var Author[] */ private $authors = []; public function add(Author $author): void { $this->authors[] = $author; } /** * @return Author[] */ public function getAuthors(): array { return $this->authors; } public function count(): int { return count($this->authors); } public function getIterator(): AuthorCollectionIterator { return new AuthorCollectionIterator($this); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Iterator; use function count; /** @template-implements Iterator */ class AuthorCollectionIterator implements Iterator { /** @var Author[] */ private $authors; /** @var int */ private $position = 0; public function __construct(AuthorCollection $authors) { $this->authors = $authors->getAuthors(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->authors); } public function key(): int { return $this->position; } public function current(): Author { return $this->authors[$this->position]; } public function next(): void { $this->position++; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\Version; class BundledComponent { /** @var string */ private $name; /** @var Version */ private $version; public function __construct(string $name, Version $version) { $this->name = $name; $this->version = $version; } public function getName(): string { return $this->name; } public function getVersion(): Version { return $this->version; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Countable; use IteratorAggregate; use function count; /** @template-implements IteratorAggregate */ class BundledComponentCollection implements Countable, IteratorAggregate { /** @var BundledComponent[] */ private $bundledComponents = []; public function add(BundledComponent $bundledComponent): void { $this->bundledComponents[] = $bundledComponent; } /** * @return BundledComponent[] */ public function getBundledComponents(): array { return $this->bundledComponents; } public function count(): int { return count($this->bundledComponents); } public function getIterator(): BundledComponentCollectionIterator { return new BundledComponentCollectionIterator($this); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Iterator; use function count; /** @template-implements Iterator */ class BundledComponentCollectionIterator implements Iterator { /** @var BundledComponent[] */ private $bundledComponents; /** @var int */ private $position = 0; public function __construct(BundledComponentCollection $bundledComponents) { $this->bundledComponents = $bundledComponents->getBundledComponents(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->bundledComponents); } public function key(): int { return $this->position; } public function current(): BundledComponent { return $this->bundledComponents[$this->position]; } public function next(): void { $this->position++; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class CopyrightInformation { /** @var AuthorCollection */ private $authors; /** @var License */ private $license; public function __construct(AuthorCollection $authors, License $license) { $this->authors = $authors; $this->license = $license; } public function getAuthors(): AuthorCollection { return $this->authors; } public function getLicense(): License { return $this->license; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use const FILTER_VALIDATE_EMAIL; use function filter_var; class Email { /** @var string */ private $email; public function __construct(string $email) { $this->ensureEmailIsValid($email); $this->email = $email; } public function asString(): string { return $this->email; } private function ensureEmailIsValid(string $url): void { if (filter_var($url, FILTER_VALIDATE_EMAIL) === false) { throw new InvalidEmailException; } } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\Version; use PharIo\Version\VersionConstraint; class Extension extends Type { /** @var ApplicationName */ private $application; /** @var VersionConstraint */ private $versionConstraint; public function __construct(ApplicationName $application, VersionConstraint $versionConstraint) { $this->application = $application; $this->versionConstraint = $versionConstraint; } public function getApplicationName(): ApplicationName { return $this->application; } public function getVersionConstraint(): VersionConstraint { return $this->versionConstraint; } public function isExtension(): bool { return true; } public function isExtensionFor(ApplicationName $name): bool { return $this->application->isEqual($name); } public function isCompatibleWith(ApplicationName $name, Version $version): bool { return $this->isExtensionFor($name) && $this->versionConstraint->complies($version); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class Library extends Type { public function isLibrary(): bool { return true; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class License { /** @var string */ private $name; /** @var Url */ private $url; public function __construct(string $name, Url $url) { $this->name = $name; $this->url = $url; } public function getName(): string { return $this->name; } public function getUrl(): Url { return $this->url; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\Version; class Manifest { /** @var ApplicationName */ private $name; /** @var Version */ private $version; /** @var Type */ private $type; /** @var CopyrightInformation */ private $copyrightInformation; /** @var RequirementCollection */ private $requirements; /** @var BundledComponentCollection */ private $bundledComponents; public function __construct(ApplicationName $name, Version $version, Type $type, CopyrightInformation $copyrightInformation, RequirementCollection $requirements, BundledComponentCollection $bundledComponents) { $this->name = $name; $this->version = $version; $this->type = $type; $this->copyrightInformation = $copyrightInformation; $this->requirements = $requirements; $this->bundledComponents = $bundledComponents; } public function getName(): ApplicationName { return $this->name; } public function getVersion(): Version { return $this->version; } public function getType(): Type { return $this->type; } public function getCopyrightInformation(): CopyrightInformation { return $this->copyrightInformation; } public function getRequirements(): RequirementCollection { return $this->requirements; } public function getBundledComponents(): BundledComponentCollection { return $this->bundledComponents; } public function isApplication(): bool { return $this->type->isApplication(); } public function isLibrary(): bool { return $this->type->isLibrary(); } public function isExtension(): bool { return $this->type->isExtension(); } public function isExtensionFor(ApplicationName $application, ?Version $version = null): bool { if (!$this->isExtension()) { return false; } /** @var Extension $type */ $type = $this->type; if ($version !== null) { return $type->isCompatibleWith($application, $version); } return $type->isExtensionFor($application); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class PhpExtensionRequirement implements Requirement { /** @var string */ private $extension; public function __construct(string $extension) { $this->extension = $extension; } public function asString(): string { return $this->extension; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\VersionConstraint; class PhpVersionRequirement implements Requirement { /** @var VersionConstraint */ private $versionConstraint; public function __construct(VersionConstraint $versionConstraint) { $this->versionConstraint = $versionConstraint; } public function getVersionConstraint(): VersionConstraint { return $this->versionConstraint; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; interface Requirement { } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Countable; use IteratorAggregate; use function count; /** @template-implements IteratorAggregate */ class RequirementCollection implements Countable, IteratorAggregate { /** @var Requirement[] */ private $requirements = []; public function add(Requirement $requirement): void { $this->requirements[] = $requirement; } /** * @return Requirement[] */ public function getRequirements(): array { return $this->requirements; } public function count(): int { return count($this->requirements); } public function getIterator(): RequirementCollectionIterator { return new RequirementCollectionIterator($this); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use Iterator; use function count; /** @template-implements Iterator */ class RequirementCollectionIterator implements Iterator { /** @var Requirement[] */ private $requirements; /** @var int */ private $position = 0; public function __construct(RequirementCollection $requirements) { $this->requirements = $requirements->getRequirements(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->requirements); } public function key(): int { return $this->position; } public function current(): Requirement { return $this->requirements[$this->position]; } public function next(): void { $this->position++; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use PharIo\Version\VersionConstraint; abstract class Type { public static function application(): Application { return new Application; } public static function library(): Library { return new Library; } public static function extension(ApplicationName $application, VersionConstraint $versionConstraint): Extension { return new Extension($application, $versionConstraint); } /** @psalm-assert-if-true Application $this */ public function isApplication(): bool { return false; } /** @psalm-assert-if-true Library $this */ public function isLibrary(): bool { return false; } /** @psalm-assert-if-true Extension $this */ public function isExtension(): bool { return false; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use const FILTER_VALIDATE_URL; use function filter_var; class Url { /** @var string */ private $url; public function __construct(string $url) { $this->ensureUrlIsValid($url); $this->url = $url; } public function asString(): string { return $this->url; } /** * @throws InvalidUrlException */ private function ensureUrlIsValid(string $url): void { if (filter_var($url, FILTER_VALIDATE_URL) === false) { throw new InvalidUrlException; } } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class AuthorElement extends ManifestElement { public function getName(): string { return $this->getAttributeValue('name'); } public function getEmail(): string { return $this->getAttributeValue('email'); } public function hasEMail(): bool { return $this->hasAttribute('email'); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class AuthorElementCollection extends ElementCollection { public function current(): AuthorElement { return new AuthorElement( $this->getCurrentElement() ); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class BundlesElement extends ManifestElement { public function getComponentElements(): ComponentElementCollection { return new ComponentElementCollection( $this->getChildrenByName('component') ); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ComponentElement extends ManifestElement { public function getName(): string { return $this->getAttributeValue('name'); } public function getVersion(): string { return $this->getAttributeValue('version'); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ComponentElementCollection extends ElementCollection { public function current(): ComponentElement { return new ComponentElement( $this->getCurrentElement() ); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ContainsElement extends ManifestElement { public function getName(): string { return $this->getAttributeValue('name'); } public function getVersion(): string { return $this->getAttributeValue('version'); } public function getType(): string { return $this->getAttributeValue('type'); } public function getExtensionElement(): ExtensionElement { return new ExtensionElement( $this->getChildByName('extension') ); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class CopyrightElement extends ManifestElement { public function getAuthorElements(): AuthorElementCollection { return new AuthorElementCollection( $this->getChildrenByName('author') ); } public function getLicenseElement(): LicenseElement { return new LicenseElement( $this->getChildByName('license') ); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use DOMElement; use DOMNodeList; use Iterator; use ReturnTypeWillChange; use function count; use function get_class; use function sprintf; /** @template-implements Iterator */ abstract class ElementCollection implements Iterator { /** @var DOMElement[] */ private $nodes = []; /** @var int */ private $position; public function __construct(DOMNodeList $nodeList) { $this->position = 0; $this->importNodes($nodeList); } #[ReturnTypeWillChange] abstract public function current(); public function next(): void { $this->position++; } public function key(): int { return $this->position; } public function valid(): bool { return $this->position < count($this->nodes); } public function rewind(): void { $this->position = 0; } protected function getCurrentElement(): DOMElement { return $this->nodes[$this->position]; } private function importNodes(DOMNodeList $nodeList): void { foreach ($nodeList as $node) { if (!$node instanceof DOMElement) { throw new ElementCollectionException( sprintf('\DOMElement expected, got \%s', get_class($node)) ); } $this->nodes[] = $node; } } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ExtElement extends ManifestElement { public function getName(): string { return $this->getAttributeValue('name'); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ExtElementCollection extends ElementCollection { public function current(): ExtElement { return new ExtElement( $this->getCurrentElement() ); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class ExtensionElement extends ManifestElement { public function getFor(): string { return $this->getAttributeValue('for'); } public function getCompatible(): string { return $this->getAttributeValue('compatible'); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class LicenseElement extends ManifestElement { public function getType(): string { return $this->getAttributeValue('type'); } public function getUrl(): string { return $this->getAttributeValue('url'); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use DOMDocument; use DOMElement; use Throwable; use function count; use function file_get_contents; use function is_file; use function libxml_clear_errors; use function libxml_get_errors; use function libxml_use_internal_errors; use function sprintf; class ManifestDocument { public const XMLNS = 'https://phar.io/xml/manifest/1.0'; /** @var DOMDocument */ private $dom; public static function fromFile(string $filename): ManifestDocument { if (!is_file($filename)) { throw new ManifestDocumentException( sprintf('File "%s" not found', $filename) ); } return self::fromString( file_get_contents($filename) ); } public static function fromString(string $xmlString): ManifestDocument { $prev = libxml_use_internal_errors(true); libxml_clear_errors(); try { $dom = new DOMDocument(); $dom->loadXML($xmlString); $errors = libxml_get_errors(); libxml_use_internal_errors($prev); } catch (Throwable $t) { throw new ManifestDocumentException($t->getMessage(), 0, $t); } if (count($errors) !== 0) { throw new ManifestDocumentLoadingException($errors); } return new self($dom); } private function __construct(DOMDocument $dom) { $this->ensureCorrectDocumentType($dom); $this->dom = $dom; } public function getContainsElement(): ContainsElement { return new ContainsElement( $this->fetchElementByName('contains') ); } public function getCopyrightElement(): CopyrightElement { return new CopyrightElement( $this->fetchElementByName('copyright') ); } public function getRequiresElement(): RequiresElement { return new RequiresElement( $this->fetchElementByName('requires') ); } public function hasBundlesElement(): bool { return $this->dom->getElementsByTagNameNS(self::XMLNS, 'bundles')->length === 1; } public function getBundlesElement(): BundlesElement { return new BundlesElement( $this->fetchElementByName('bundles') ); } private function ensureCorrectDocumentType(DOMDocument $dom): void { $root = $dom->documentElement; if ($root->localName !== 'phar' || $root->namespaceURI !== self::XMLNS) { throw new ManifestDocumentException('Not a phar.io manifest document'); } } private function fetchElementByName(string $elementName): DOMElement { $element = $this->dom->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); if (!$element instanceof DOMElement) { throw new ManifestDocumentException( sprintf('Element %s missing', $elementName) ); } return $element; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; use DOMElement; use DOMNodeList; use function sprintf; class ManifestElement { public const XMLNS = 'https://phar.io/xml/manifest/1.0'; /** @var DOMElement */ private $element; public function __construct(DOMElement $element) { $this->element = $element; } protected function getAttributeValue(string $name): string { if (!$this->element->hasAttribute($name)) { throw new ManifestElementException( sprintf( 'Attribute %s not set on element %s', $name, $this->element->localName ) ); } return $this->element->getAttribute($name); } protected function hasAttribute(string $name): bool { return $this->element->hasAttribute($name); } protected function getChildByName(string $elementName): DOMElement { $element = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); if (!$element instanceof DOMElement) { throw new ManifestElementException( sprintf('Element %s missing', $elementName) ); } return $element; } protected function getChildrenByName(string $elementName): DOMNodeList { $elementList = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName); if ($elementList->length === 0) { throw new ManifestElementException( sprintf('Element(s) %s missing', $elementName) ); } return $elementList; } protected function hasChild(string $elementName): bool { return $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->length !== 0; } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class PhpElement extends ManifestElement { public function getVersion(): string { return $this->getAttributeValue('version'); } public function hasExtElements(): bool { return $this->hasChild('ext'); } public function getExtElements(): ExtElementCollection { return new ExtElementCollection( $this->getChildrenByName('ext') ); } } , Sebastian Heuer , Sebastian Bergmann and contributors * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * */ namespace PharIo\Manifest; class RequiresElement extends ManifestElement { public function getPHPElement(): PhpElement { return new PhpElement( $this->getChildByName('php') ); } } isTokenKindFound(T_DOC_COMMENT); } public function isRisky(): bool { return false; } public function fix(\SplFileInfo $file, Tokens $tokens): void { foreach($tokens as $index => $token) { if (!$token->isGivenKind(T_DOC_COMMENT)) { continue; } if (\stripos($token->getContent(), '@var') === false) { continue; } if (preg_match('#^/\*\*[\s\*]+(@var[^\r\n]+)[\s\*]*\*\/$#u', $token->getContent(), $matches) !== 1) { continue; } $newContent = '/** ' . \rtrim($matches[1]) . ' */'; if ($newContent === $token->getContent()) { continue; } $tokens[$index] = new Token([T_DOC_COMMENT, $newContent]); } } public function getPriority(): int { return 0; } public function getName(): string { return 'PharIo/phpdoc_single_line_var_fixer'; } public function supports(\SplFileInfo $file): bool { return true; } } This file is part of PharIo\Manifest. Copyright (c) Arne Blankerts , Sebastian Heuer , Sebastian Bergmann and contributors For the full copyright and license information, please view the LICENSE file that was distributed with this source code. # Changelog All notable changes to phar-io/version are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. ## [3.2.1] - 2022-02-21 ### Fixed - Have ExactVersionConstraint honor build metadata (added in 3.2.0) ## [3.2.0] - 2022-02-21 ### Added - Build metadata is now supported and considered for equality checks only ## [3.1.1] - 2022-02-07 ### Fixed - [#28](https://github.com/phar-io/version/issues/28): `VersionConstraintParser` does not support logical OR represented by single pipe (|) (Thanks @llaville) ## [3.1.0] - 2021-02-23 ### Changed - Internal Refactoring - More scalar types ### Added - [#24](https://github.com/phar-io/version/issues/24): `Version::getOriginalString()` added (Thanks @addshore) - Version constraints using the caret operator (`^`) now honor pre-1.0 releases, e.g. `^0.3` translates to `0.3.*`) - Various integration tests for version constraint processing ### Fixed - [#23](https://github.com/phar-io/version/pull/23): Tilde operator without patch level ## [3.0.4] - 14.12.2020 ### Fixed - [#22](https://github.com/phar-io/version/pull/22): make dev suffix rank works for uppercase too ## [3.0.3] - 30.11.2020 ### Added - Comparator method `Version::equals()` added ## [3.0.2] - 27.06.2020 This release now supports PHP 7.2+ and PHP ^8.0. No other changes included. ## [3.0.1] - 09.05.2020 __Potential BC Break Notice:__ `Version::getVersionString()` no longer returns `v` prefixes in case the "input" string contained one. These are not part of the semver specs (see https://semver.org/#is-v123-a-semantic-version) and get stripped out. As of Version 3.1.0 `Version::getOriginalString()` can be used to still retrieve it as given. ### Changed - Internal Refactoring - More scalar types ### Fixed - Fixed Constraint processing Regression for ^1.2 and ~1.2 ## [3.0.0] - 05.05.2020 ### Changed - Require PHP 7.2+ - All code now uses strict mode - Scalar types have been added as needed ### Added - The technically invalid format using 'v' prefix ("v1.2.3") is now properly supported ## [2.0.1] - 08.07.2018 ### Fixed - Versions without a pre-release suffix are now always considered greater than versions with a pre-release suffix. Example: `3.0.0 > 3.0.0-alpha.1` ## [2.0.0] - 23.06.2018 Changes to public API: - `PreReleaseSuffix::construct()`: optional parameter `$number` removed - `PreReleaseSuffix::isGreaterThan()`: introduced - `Version::hasPreReleaseSuffix()`: introduced ### Added - [#11](https://github.com/phar-io/version/issues/11): Added support for pre-release version suffixes. Supported values are: - `dev` - `beta` (also abbreviated form `b`) - `rc` - `alpha` (also abbreviated form `a`) - `patch` (also abbreviated form `p`) All values can be followed by a number, e.g. `beta3`. When comparing versions, the pre-release suffix is taken into account. Example: `1.5.0 > 1.5.0-beta1 > 1.5.0-alpha3 > 1.5.0-alpha2 > 1.5.0-dev11` ### Changed - reorganized the source directories ### Fixed - [#10](https://github.com/phar-io/version/issues/10): Version numbers containing a numeric suffix as seen in Debian packages are now supported. [3.1.0]: https://github.com/phar-io/version/compare/3.0.4...3.1.0 [3.0.4]: https://github.com/phar-io/version/compare/3.0.3...3.0.4 [3.0.3]: https://github.com/phar-io/version/compare/3.0.2...3.0.3 [3.0.2]: https://github.com/phar-io/version/compare/3.0.1...3.0.2 [3.0.1]: https://github.com/phar-io/version/compare/3.0.0...3.0.1 [3.0.0]: https://github.com/phar-io/version/compare/2.0.1...3.0.0 [2.0.1]: https://github.com/phar-io/version/compare/2.0.0...2.0.1 [2.0.0]: https://github.com/phar-io/version/compare/1.0.1...2.0.0 Copyright (c) 2016-2017 Arne Blankerts , Sebastian Heuer and contributors 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 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. # Version Library for handling version information and constraints [![Build Status](https://travis-ci.org/phar-io/version.svg?branch=master)](https://travis-ci.org/phar-io/version) ## Installation You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): composer require phar-io/version 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 phar-io/version ## Version constraints A Version constraint describes a range of versions or a discrete version number. The format of version numbers follows the schema of [semantic versioning](http://semver.org): `..`. A constraint might contain an operator that describes the range. Beside the typical mathematical operators like `<=`, `>=`, there are two special operators: *Caret operator*: `^1.0` can be written as `>=1.0.0 <2.0.0` and read as »every Version within major version `1`«. *Tilde operator*: `~1.0.0` can be written as `>=1.0.0 <1.1.0` and read as »every version within minor version `1.1`. The behavior of tilde operator depends on whether a patch level version is provided or not. If no patch level is provided, tilde operator behaves like the caret operator: `~1.0` is identical to `^1.0`. ## Usage examples Parsing version constraints and check discrete versions for compliance: ```php use PharIo\Version\Version; use PharIo\Version\VersionConstraintParser; $parser = new VersionConstraintParser(); $caret_constraint = $parser->parse( '^7.0' ); $caret_constraint->complies( new Version( '7.0.17' ) ); // true $caret_constraint->complies( new Version( '7.1.0' ) ); // true $caret_constraint->complies( new Version( '6.4.34' ) ); // false $tilde_constraint = $parser->parse( '~1.1.0' ); $tilde_constraint->complies( new Version( '1.1.4' ) ); // true $tilde_constraint->complies( new Version( '1.2.0' ) ); // false ``` As of version 2.0.0, pre-release labels are supported and taken into account when comparing versions: ```php $leftVersion = new PharIo\Version\Version('3.0.0-alpha.1'); $rightVersion = new PharIo\Version\Version('3.0.0-alpha.2'); $leftVersion->isGreaterThan($rightVersion); // false $rightVersion->isGreaterThan($leftVersion); // true ``` { "name": "phar-io/version", "description": "Library for handling version information and constraints", "license": "BSD-3-Clause", "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "support": { "issues": "https://github.com/phar-io/version/issues" }, "require": { "php": "^7.2 || ^8.0" }, "autoload": { "classmap": [ "src/" ] } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class BuildMetaData { /** @var string */ private $value; public function __construct(string $value) { $this->value = $value; } public function asString(): string { return $this->value; } public function equals(BuildMetaData $other): bool { return $this->asString() === $other->asString(); } } 0, 'a' => 1, 'alpha' => 1, 'b' => 2, 'beta' => 2, 'rc' => 3, 'p' => 4, 'pl' => 4, 'patch' => 4, ]; /** @var string */ private $value; /** @var int */ private $valueScore; /** @var int */ private $number = 0; /** @var string */ private $full; /** * @throws InvalidPreReleaseSuffixException */ public function __construct(string $value) { $this->parseValue($value); } public function asString(): string { return $this->full; } public function getValue(): string { return $this->value; } public function getNumber(): ?int { return $this->number; } public function isGreaterThan(PreReleaseSuffix $suffix): bool { if ($this->valueScore > $suffix->valueScore) { return true; } if ($this->valueScore < $suffix->valueScore) { return false; } return $this->getNumber() > $suffix->getNumber(); } private function mapValueToScore(string $value): int { $value = \strtolower($value); return self::valueScoreMap[$value]; } private function parseValue(string $value): void { $regex = '/-?((dev|beta|b|rc|alpha|a|patch|p|pl)\.?(\d*)).*$/i'; if (\preg_match($regex, $value, $matches) !== 1) { throw new InvalidPreReleaseSuffixException(\sprintf('Invalid label %s', $value)); } $this->full = $matches[1]; $this->value = $matches[2]; if ($matches[3] !== '') { $this->number = (int)$matches[3]; } $this->valueScore = $this->mapValueToScore($matches[2]); } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class Version { /** @var string */ private $originalVersionString; /** @var VersionNumber */ private $major; /** @var VersionNumber */ private $minor; /** @var VersionNumber */ private $patch; /** @var null|PreReleaseSuffix */ private $preReleaseSuffix; /** @var null|BuildMetaData */ private $buildMetadata; public function __construct(string $versionString) { $this->ensureVersionStringIsValid($versionString); $this->originalVersionString = $versionString; } /** * @throws NoPreReleaseSuffixException */ public function getPreReleaseSuffix(): PreReleaseSuffix { if ($this->preReleaseSuffix === null) { throw new NoPreReleaseSuffixException('No pre-release suffix set'); } return $this->preReleaseSuffix; } public function getOriginalString(): string { return $this->originalVersionString; } public function getVersionString(): string { $str = \sprintf( '%d.%d.%d', $this->getMajor()->getValue() ?? 0, $this->getMinor()->getValue() ?? 0, $this->getPatch()->getValue() ?? 0 ); if (!$this->hasPreReleaseSuffix()) { return $str; } return $str . '-' . $this->getPreReleaseSuffix()->asString(); } public function hasPreReleaseSuffix(): bool { return $this->preReleaseSuffix !== null; } public function equals(Version $other): bool { if ($this->getVersionString() !== $other->getVersionString()) { return false; } if ($this->hasBuildMetaData() !== $other->hasBuildMetaData()) { return false; } if ($this->hasBuildMetaData() && $other->hasBuildMetaData() && !$this->getBuildMetaData()->equals($other->getBuildMetaData())) { return false; } return true; } public function isGreaterThan(Version $version): bool { if ($version->getMajor()->getValue() > $this->getMajor()->getValue()) { return false; } if ($version->getMajor()->getValue() < $this->getMajor()->getValue()) { return true; } if ($version->getMinor()->getValue() > $this->getMinor()->getValue()) { return false; } if ($version->getMinor()->getValue() < $this->getMinor()->getValue()) { return true; } if ($version->getPatch()->getValue() > $this->getPatch()->getValue()) { return false; } if ($version->getPatch()->getValue() < $this->getPatch()->getValue()) { return true; } if (!$version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) { return false; } if ($version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) { return true; } if (!$version->hasPreReleaseSuffix() && $this->hasPreReleaseSuffix()) { return false; } return $this->getPreReleaseSuffix()->isGreaterThan($version->getPreReleaseSuffix()); } public function getMajor(): VersionNumber { return $this->major; } public function getMinor(): VersionNumber { return $this->minor; } public function getPatch(): VersionNumber { return $this->patch; } /** * @psalm-assert-if-true BuildMetaData $this->buildMetadata * @psalm-assert-if-true BuildMetaData $this->getBuildMetaData() */ public function hasBuildMetaData(): bool { return $this->buildMetadata !== null; } /** * @throws NoBuildMetaDataException */ public function getBuildMetaData(): BuildMetaData { if (!$this->hasBuildMetaData()) { throw new NoBuildMetaDataException('No build metadata set'); } return $this->buildMetadata; } /** * @param string[] $matches * * @throws InvalidPreReleaseSuffixException */ private function parseVersion(array $matches): void { $this->major = new VersionNumber((int)$matches['Major']); $this->minor = new VersionNumber((int)$matches['Minor']); $this->patch = isset($matches['Patch']) ? new VersionNumber((int)$matches['Patch']) : new VersionNumber(0); if (isset($matches['PreReleaseSuffix']) && $matches['PreReleaseSuffix'] !== '') { $this->preReleaseSuffix = new PreReleaseSuffix($matches['PreReleaseSuffix']); } if (isset($matches['BuildMetadata'])) { $this->buildMetadata = new BuildMetaData($matches['BuildMetadata']); } } /** * @param string $version * * @throws InvalidVersionException */ private function ensureVersionStringIsValid($version): void { $regex = '/^v? (?P0|[1-9]\d*) \\. (?P0|[1-9]\d*) (\\. (?P0|[1-9]\d*) )? (?: - (?(?:(dev|beta|b|rc|alpha|a|patch|p|pl)\.?\d*)) )? (?: \\+ (?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-@]+)*) )? $/xi'; if (\preg_match($regex, $version, $matches) !== 1) { throw new InvalidVersionException( \sprintf("Version string '%s' does not follow SemVer semantics", $version) ); } $this->parseVersion($matches); } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class VersionConstraintParser { /** * @throws UnsupportedVersionConstraintException */ public function parse(string $value): VersionConstraint { if (\strpos($value, '|') !== false) { return $this->handleOrGroup($value); } if (!\preg_match('/^[\^~*]?v?[\d.*]+(?:-.*)?$/i', $value)) { throw new UnsupportedVersionConstraintException( \sprintf('Version constraint %s is not supported.', $value) ); } switch ($value[0]) { case '~': return $this->handleTildeOperator($value); case '^': return $this->handleCaretOperator($value); } $constraint = new VersionConstraintValue($value); if ($constraint->getMajor()->isAny()) { return new AnyVersionConstraint(); } if ($constraint->getMinor()->isAny()) { return new SpecificMajorVersionConstraint( $constraint->getVersionString(), $constraint->getMajor()->getValue() ?? 0 ); } if ($constraint->getPatch()->isAny()) { return new SpecificMajorAndMinorVersionConstraint( $constraint->getVersionString(), $constraint->getMajor()->getValue() ?? 0, $constraint->getMinor()->getValue() ?? 0 ); } return new ExactVersionConstraint($constraint->getVersionString()); } private function handleOrGroup(string $value): OrVersionConstraintGroup { $constraints = []; foreach (\preg_split('{\s*\|\|?\s*}', \trim($value)) as $groupSegment) { $constraints[] = $this->parse(\trim($groupSegment)); } return new OrVersionConstraintGroup($value, $constraints); } private function handleTildeOperator(string $value): AndVersionConstraintGroup { $constraintValue = new VersionConstraintValue(\substr($value, 1)); if ($constraintValue->getPatch()->isAny()) { return $this->handleCaretOperator($value); } $constraints = [ new GreaterThanOrEqualToVersionConstraint( $value, new Version(\substr($value, 1)) ), new SpecificMajorAndMinorVersionConstraint( $value, $constraintValue->getMajor()->getValue() ?? 0, $constraintValue->getMinor()->getValue() ?? 0 ) ]; return new AndVersionConstraintGroup($value, $constraints); } private function handleCaretOperator(string $value): AndVersionConstraintGroup { $constraintValue = new VersionConstraintValue(\substr($value, 1)); $constraints = [ new GreaterThanOrEqualToVersionConstraint($value, new Version(\substr($value, 1))) ]; if ($constraintValue->getMajor()->getValue() === 0) { $constraints[] = new SpecificMajorAndMinorVersionConstraint( $value, $constraintValue->getMajor()->getValue() ?? 0, $constraintValue->getMinor()->getValue() ?? 0 ); } else { $constraints[] = new SpecificMajorVersionConstraint( $value, $constraintValue->getMajor()->getValue() ?? 0 ); } return new AndVersionConstraintGroup( $value, $constraints ); } } versionString = $versionString; $this->parseVersion($versionString); } public function getLabel(): string { return $this->label; } public function getBuildMetaData(): string { return $this->buildMetaData; } public function getVersionString(): string { return $this->versionString; } public function getMajor(): VersionNumber { return $this->major; } public function getMinor(): VersionNumber { return $this->minor; } public function getPatch(): VersionNumber { return $this->patch; } private function parseVersion(string $versionString): void { $this->extractBuildMetaData($versionString); $this->extractLabel($versionString); $this->stripPotentialVPrefix($versionString); $versionSegments = \explode('.', $versionString); $this->major = new VersionNumber(\is_numeric($versionSegments[0]) ? (int)$versionSegments[0] : null); $minorValue = isset($versionSegments[1]) && \is_numeric($versionSegments[1]) ? (int)$versionSegments[1] : null; $patchValue = isset($versionSegments[2]) && \is_numeric($versionSegments[2]) ? (int)$versionSegments[2] : null; $this->minor = new VersionNumber($minorValue); $this->patch = new VersionNumber($patchValue); } private function extractBuildMetaData(string &$versionString): void { if (\preg_match('/\+(.*)/', $versionString, $matches) === 1) { $this->buildMetaData = $matches[1]; $versionString = \str_replace($matches[0], '', $versionString); } } private function extractLabel(string &$versionString): void { if (\preg_match('/-(.*)/', $versionString, $matches) === 1) { $this->label = $matches[1]; $versionString = \str_replace($matches[0], '', $versionString); } } private function stripPotentialVPrefix(string &$versionString): void { if ($versionString[0] !== 'v') { return; } $versionString = \substr($versionString, 1); } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class VersionNumber { /** @var ?int */ private $value; public function __construct(?int $value) { $this->value = $value; } public function isAny(): bool { return $this->value === null; } public function getValue(): ?int { return $this->value; } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; abstract class AbstractVersionConstraint implements VersionConstraint { /** @var string */ private $originalValue; public function __construct(string $originalValue) { $this->originalValue = $originalValue; } public function asString(): string { return $this->originalValue; } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class AndVersionConstraintGroup extends AbstractVersionConstraint { /** @var VersionConstraint[] */ private $constraints = []; /** * @param VersionConstraint[] $constraints */ public function __construct(string $originalValue, array $constraints) { parent::__construct($originalValue); $this->constraints = $constraints; } public function complies(Version $version): bool { foreach ($this->constraints as $constraint) { if (!$constraint->complies($version)) { return false; } } return true; } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class AnyVersionConstraint implements VersionConstraint { public function complies(Version $version): bool { return true; } public function asString(): string { return '*'; } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class ExactVersionConstraint extends AbstractVersionConstraint { public function complies(Version $version): bool { $other = $version->getVersionString(); if ($version->hasBuildMetaData()) { $other .= '+' . $version->getBuildMetaData()->asString(); } return $this->asString() === $other; } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class GreaterThanOrEqualToVersionConstraint extends AbstractVersionConstraint { /** @var Version */ private $minimalVersion; public function __construct(string $originalValue, Version $minimalVersion) { parent::__construct($originalValue); $this->minimalVersion = $minimalVersion; } public function complies(Version $version): bool { return $version->getVersionString() === $this->minimalVersion->getVersionString() || $version->isGreaterThan($this->minimalVersion); } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class OrVersionConstraintGroup extends AbstractVersionConstraint { /** @var VersionConstraint[] */ private $constraints = []; /** * @param string $originalValue * @param VersionConstraint[] $constraints */ public function __construct($originalValue, array $constraints) { parent::__construct($originalValue); $this->constraints = $constraints; } public function complies(Version $version): bool { foreach ($this->constraints as $constraint) { if ($constraint->complies($version)) { return true; } } return false; } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class SpecificMajorAndMinorVersionConstraint extends AbstractVersionConstraint { /** @var int */ private $major; /** @var int */ private $minor; public function __construct(string $originalValue, int $major, int $minor) { parent::__construct($originalValue); $this->major = $major; $this->minor = $minor; } public function complies(Version $version): bool { if ($version->getMajor()->getValue() !== $this->major) { return false; } return $version->getMinor()->getValue() === $this->minor; } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class SpecificMajorVersionConstraint extends AbstractVersionConstraint { /** @var int */ private $major; public function __construct(string $originalValue, int $major) { parent::__construct($originalValue); $this->major = $major; } public function complies(Version $version): bool { return $version->getMajor()->getValue() === $this->major; } } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; interface VersionConstraint { public function complies(Version $version): bool; public function asString(): string; } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use Throwable; interface Exception extends Throwable { } , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; final class UnsupportedVersionConstraintException extends \RuntimeException implements Exception { } The MIT License (MIT) Copyright (c) Matthieu Napoli 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. # Invoker Generic and extensible callable invoker. [![CI](https://github.com/PHP-DI/Invoker/actions/workflows/ci.yml/badge.svg)](https://github.com/PHP-DI/Invoker/actions/workflows/ci.yml) [![Latest Version](https://img.shields.io/github/release/PHP-DI/invoker.svg?style=flat-square)](https://packagist.org/packages/PHP-DI/invoker) [![Total Downloads](https://img.shields.io/packagist/dt/php-di/invoker.svg?style=flat-square)](https://packagist.org/packages/php-di/invoker) ## Why? Who doesn't need an over-engineered `call_user_func()`? ### Named parameters Does this [Silex](https://github.com/silexphp/Silex#readme) example look familiar: ```php $app->get('/project/{project}/issue/{issue}', function ($project, $issue) { // ... }); ``` Or this command defined with [Silly](https://github.com/mnapoli/silly#usage): ```php $app->command('greet [name] [--yell]', function ($name, $yell) { // ... }); ``` Same pattern in [Slim](https://www.slimframework.com): ```php $app->get('/hello/:name', function ($name) { // ... }); ``` You get the point. These frameworks invoke the controller/command/handler using something akin to named parameters: whatever the order of the parameters, they are matched by their name. **This library allows to invoke callables with named parameters in a generic and extensible way.** ### Dependency injection Anyone familiar with AngularJS is familiar with how dependency injection is performed: ```js angular.controller('MyController', ['dep1', 'dep2', function(dep1, dep2) { // ... }]); ``` In PHP we find this pattern again in some frameworks and DI containers with partial to full support. For example in Silex you can type-hint the application to get it injected, but it only works with `Silex\Application`: ```php $app->get('/hello/{name}', function (Silex\Application $app, $name) { // ... }); ``` In Silly, it only works with `OutputInterface` to inject the application output: ```php $app->command('greet [name]', function ($name, OutputInterface $output) { // ... }); ``` [PHP-DI](https://php-di.org/doc/container.html) provides a way to invoke a callable and resolve all dependencies from the container using type-hints: ```php $container->call(function (Logger $logger, EntityManager $em) { // ... }); ``` **This library provides clear extension points to let frameworks implement any kind of dependency injection support they want.** ### TL/DR In short, this library is meant to be a base building block for calling a function with named parameters and/or dependency injection. ## Installation ```sh $ composer require PHP-DI/invoker ``` ## Usage ### Default behavior By default the `Invoker` can call using named parameters: ```php $invoker = new Invoker\Invoker; $invoker->call(function () { echo 'Hello world!'; }); // Simple parameter array $invoker->call(function ($name) { echo 'Hello ' . $name; }, ['John']); // Named parameters $invoker->call(function ($name) { echo 'Hello ' . $name; }, [ 'name' => 'John' ]); // Use the default value $invoker->call(function ($name = 'world') { echo 'Hello ' . $name; }); // Invoke any PHP callable $invoker->call(['MyClass', 'myStaticMethod']); // Using Class::method syntax $invoker->call('MyClass::myStaticMethod'); ``` Dependency injection in parameters is supported but needs to be configured with your container. Read on or jump to [*Built-in support for dependency injection*](#built-in-support-for-dependency-injection) if you are impatient. Additionally, callables can also be resolved from your container. Read on or jump to [*Resolving callables from a container*](#resolving-callables-from-a-container) if you are impatient. ### Parameter resolvers Extending the behavior of the `Invoker` is easy and is done by implementing a [`ParameterResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ParameterResolver.php). This is explained in details the [Parameter resolvers documentation](doc/parameter-resolvers.md). #### Built-in support for dependency injection Rather than have you re-implement support for dependency injection with different containers every time, this package ships with 2 optional resolvers: - [`TypeHintContainerResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/TypeHintContainerResolver.php) This resolver will inject container entries by searching for the class name using the type-hint: ```php $invoker->call(function (Psr\Logger\LoggerInterface $logger) { // ... }); ``` In this example it will `->get('Psr\Logger\LoggerInterface')` from the container and inject it. This resolver is only useful if you store objects in your container using the class (or interface) name. Silex or Symfony for example store services under a custom name (e.g. `twig`, `db`, etc.) instead of the class name: in that case use the resolver shown below. - [`ParameterNameContainerResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/ParameterNameContainerResolver.php) This resolver will inject container entries by searching for the name of the parameter: ```php $invoker->call(function ($twig) { // ... }); ``` In this example it will `->get('twig')` from the container and inject it. These resolvers can work with any dependency injection container compliant with [PSR-11](http://www.php-fig.org/psr/psr-11/). Setting up those resolvers is simple: ```php // $container must be an instance of Psr\Container\ContainerInterface $container = ... $containerResolver = new TypeHintContainerResolver($container); // or $containerResolver = new ParameterNameContainerResolver($container); $invoker = new Invoker\Invoker; // Register it before all the other parameter resolvers $invoker->getParameterResolver()->prependResolver($containerResolver); ``` You can also register both resolvers at the same time if you wish by prepending both. Implementing support for more tricky things is easy and up to you! ### Resolving callables from a container The `Invoker` can be wired to your DI container to resolve the callables. For example with an invokable class: ```php class MyHandler { public function __invoke() { // ... } } // By default this doesn't work: an instance of the class should be provided $invoker->call('MyHandler'); // If we set up the container to use $invoker = new Invoker\Invoker(null, $container); // Now 'MyHandler' is resolved using the container! $invoker->call('MyHandler'); ``` The same works for a class method: ```php class WelcomeController { public function home() { // ... } } // By default this doesn't work: home() is not a static method $invoker->call(['WelcomeController', 'home']); // If we set up the container to use $invoker = new Invoker\Invoker(null, $container); // Now 'WelcomeController' is resolved using the container! $invoker->call(['WelcomeController', 'home']); // Alternatively we can use the Class::method syntax $invoker->call('WelcomeController::home'); ``` That feature can be used as the base building block for a framework's dispatcher. Again, any [PSR-11](https://www.php-fig.org/psr/psr-11/) compliant container can be provided. { "name": "php-di/invoker", "description": "Generic and extensible callable invoker", "keywords": ["invoker", "dependency-injection", "dependency", "injection", "callable", "invoke"], "homepage": "https://github.com/PHP-DI/Invoker", "license": "MIT", "type": "library", "autoload": { "psr-4": { "Invoker\\": "src/" } }, "autoload-dev": { "psr-4": { "Invoker\\Test\\": "tests/" } }, "require": { "php": ">=7.3", "psr/container": "^1.0|^2.0" }, "require-dev": { "phpunit/phpunit": "^9.0 || ^10 || ^11 || ^12", "athletic/athletic": "~0.1.8", "mnapoli/hard-mode": "~0.3.0" }, "config": { "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true } } } container = $container; } /** * Resolve the given callable into a real PHP callable. * * @param callable|string|array $callable * @return callable Real PHP callable. * @throws NotCallableException|ReflectionException */ public function resolve($callable): callable { if (is_string($callable) && strpos($callable, '::') !== false) { $callable = explode('::', $callable, 2); } $callable = $this->resolveFromContainer($callable); if (! is_callable($callable)) { throw NotCallableException::fromInvalidCallable($callable, true); } return $callable; } /** * @param callable|string|array $callable * @return callable|mixed * @throws NotCallableException|ReflectionException */ private function resolveFromContainer($callable) { // Shortcut for a very common use case if ($callable instanceof Closure) { return $callable; } // If it's already a callable there is nothing to do if (is_callable($callable)) { // TODO with PHP 8 that should not be necessary to check this anymore if (! $this->isStaticCallToNonStaticMethod($callable)) { return $callable; } } // The callable is a container entry name if (is_string($callable)) { try { return $this->container->get($callable); } catch (NotFoundExceptionInterface $e) { if ($this->container->has($callable)) { throw $e; } throw NotCallableException::fromInvalidCallable($callable, true); } } // The callable is an array whose first item is a container entry name // e.g. ['some-container-entry', 'methodToCall'] if (is_array($callable) && is_string($callable[0])) { try { // Replace the container entry name by the actual object $callable[0] = $this->container->get($callable[0]); return $callable; } catch (NotFoundExceptionInterface $e) { if ($this->container->has($callable[0])) { throw $e; } throw new NotCallableException(sprintf( 'Cannot call %s() on %s because it is not a class nor a valid container entry', $callable[1], $callable[0] )); } } // Unrecognized stuff, we let it fail later return $callable; } /** * Check if the callable represents a static call to a non-static method. * * @param mixed $callable * @throws ReflectionException */ private function isStaticCallToNonStaticMethod($callable): bool { if (is_array($callable) && is_string($callable[0])) { [$class, $method] = $callable; if (! method_exists($class, $method)) { return false; } $reflection = new ReflectionMethod($class, $method); return ! $reflection->isStatic(); } return false; } } parameterResolver = $parameterResolver ?: $this->createParameterResolver(); $this->container = $container; if ($container) { $this->callableResolver = new CallableResolver($container); } } /** * {@inheritdoc} */ public function call($callable, array $parameters = []) { if ($this->callableResolver) { $callable = $this->callableResolver->resolve($callable); } if (! is_callable($callable)) { throw new NotCallableException(sprintf( '%s is not a callable', is_object($callable) ? 'Instance of ' . get_class($callable) : var_export($callable, true) )); } $callableReflection = CallableReflection::create($callable); $args = $this->parameterResolver->getParameters($callableReflection, $parameters, []); // Sort by array key because call_user_func_array ignores numeric keys ksort($args); // Check all parameters are resolved $diff = array_diff_key($callableReflection->getParameters(), $args); $parameter = reset($diff); if ($parameter && \assert($parameter instanceof ReflectionParameter) && ! $parameter->isVariadic()) { throw new NotEnoughParametersException(sprintf( 'Unable to invoke the callable because no value was given for parameter %d ($%s)', $parameter->getPosition() + 1, $parameter->name )); } return call_user_func_array($callable, $args); } /** * Create the default parameter resolver. */ private function createParameterResolver(): ParameterResolver { return new ResolverChain([ new NumericArrayResolver, new AssociativeArrayResolver, new DefaultValueResolver, ]); } /** * @return ParameterResolver By default it's a ResolverChain */ public function getParameterResolver(): ParameterResolver { return $this->parameterResolver; } public function getContainer(): ?ContainerInterface { return $this->container; } /** * @return CallableResolver|null Returns null if no container was given in the constructor. */ public function getCallableResolver(): ?CallableResolver { return $this->callableResolver; } } call($callable, ['foo' => 'bar'])` will inject the string `'bar'` * in the parameter named `$foo`. * * Parameters that are not indexed by a string are ignored. */ class AssociativeArrayResolver implements ParameterResolver { public function getParameters( ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters ): array { $parameters = $reflection->getParameters(); // Skip parameters already resolved if (! empty($resolvedParameters)) { $parameters = array_diff_key($parameters, $resolvedParameters); } foreach ($parameters as $index => $parameter) { if (array_key_exists($parameter->name, $providedParameters)) { $resolvedParameters[$index] = $providedParameters[$parameter->name]; } } return $resolvedParameters; } } container = $container; } public function getParameters( ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters ): array { $parameters = $reflection->getParameters(); // Skip parameters already resolved if (! empty($resolvedParameters)) { $parameters = array_diff_key($parameters, $resolvedParameters); } foreach ($parameters as $index => $parameter) { $name = $parameter->name; if ($name && $this->container->has($name)) { $resolvedParameters[$index] = $this->container->get($name); } } return $resolvedParameters; } } container = $container; } public function getParameters( ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters ): array { $parameters = $reflection->getParameters(); // Skip parameters already resolved if (! empty($resolvedParameters)) { $parameters = array_diff_key($parameters, $resolvedParameters); } foreach ($parameters as $index => $parameter) { $parameterType = $parameter->getType(); if (! $parameterType) { // No type continue; } if (! $parameterType instanceof ReflectionNamedType) { // Union types are not supported continue; } if ($parameterType->isBuiltin()) { // Primitive types are not supported continue; } $parameterClass = $parameterType->getName(); if ($parameterClass === 'self') { $parameterClass = $parameter->getDeclaringClass()->getName(); } if ($this->container->has($parameterClass)) { $resolvedParameters[$index] = $this->container->get($parameterClass); } } return $resolvedParameters; } } getParameters(); // Skip parameters already resolved if (! empty($resolvedParameters)) { $parameters = array_diff_key($parameters, $resolvedParameters); } foreach ($parameters as $index => $parameter) { \assert($parameter instanceof \ReflectionParameter); if ($parameter->isDefaultValueAvailable()) { try { $resolvedParameters[$index] = $parameter->getDefaultValue(); } catch (ReflectionException $e) { // Can't get default values from PHP internal classes and functions } } else { $parameterType = $parameter->getType(); if ($parameterType && $parameterType->allowsNull()) { $resolvedParameters[$index] = null; } } } return $resolvedParameters; } } call($callable, ['foo', 'bar'])` will simply resolve the parameters * to `['foo', 'bar']`. * * Parameters that are not indexed by a number (i.e. parameter position) * will be ignored. */ class NumericArrayResolver implements ParameterResolver { public function getParameters( ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters ): array { // Skip parameters already resolved if (! empty($resolvedParameters)) { $providedParameters = array_diff_key($providedParameters, $resolvedParameters); } foreach ($providedParameters as $key => $value) { if (is_int($key)) { $resolvedParameters[$key] = $value; } } return $resolvedParameters; } } resolvers = $resolvers; } public function getParameters( ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters ): array { $reflectionParameters = $reflection->getParameters(); foreach ($this->resolvers as $resolver) { $resolvedParameters = $resolver->getParameters( $reflection, $providedParameters, $resolvedParameters ); $diff = array_diff_key($reflectionParameters, $resolvedParameters); if (empty($diff)) { // Stop traversing: all parameters are resolved return $resolvedParameters; } } return $resolvedParameters; } /** * Push a parameter resolver after the ones already registered. */ public function appendResolver(ParameterResolver $resolver): void { $this->resolvers[] = $resolver; } /** * Insert a parameter resolver before the ones already registered. */ public function prependResolver(ParameterResolver $resolver): void { array_unshift($this->resolvers, $resolver); } } getParameters(); // Skip parameters already resolved if (! empty($resolvedParameters)) { $parameters = array_diff_key($parameters, $resolvedParameters); } foreach ($parameters as $index => $parameter) { $parameterType = $parameter->getType(); if (! $parameterType) { // No type continue; } if (! $parameterType instanceof ReflectionNamedType) { // Union types are not supported continue; } if ($parameterType->isBuiltin()) { // Primitive types are not supported continue; } $parameterClass = $parameterType->getName(); if ($parameterClass === 'self') { $parameterClass = $parameter->getDeclaringClass()->getName(); } if (array_key_exists($parameterClass, $providedParameters)) { $resolvedParameters[$index] = $providedParameters[$parameterClass]; } } return $resolvedParameters; } } DI\factory(function ($host) {...}) ->parameter('host', DI\get('db.host')), ]; ``` Read the [factories documentation](https://php-di.org/doc/php-definitions.html#factories) to learn more. Feature implemented by [@predakanga](https://github.com/predakanga). Improvements: - [#429](https://github.com/PHP-DI/PHP-DI/pull/429): performance improvements in definition resolution (by [@mnapoli](https://github.com/mnapoli)) - [#421](https://github.com/PHP-DI/PHP-DI/issues/421): once a `ContainerBuilder` has built a container, it is locked to prevent confusion when adding new definitions to it (by [@mnapoli](https://github.com/mnapoli)) - [#423](https://github.com/PHP-DI/PHP-DI/pull/423): improved exception messages (by [@mnapoli](https://github.com/mnapoli)) ## 5.3 Read the [news entry](news/19-php-di-5-3-released.md). - release of the [2.0 version](https://github.com/PHP-DI/Symfony-Bridge/releases/tag/2.0.0) of the Symfony bridge (by [@mnapoli](https://github.com/mnapoli)) - PHP 5.5 or above is now required - a lot of documentation improvements by 9 different contributors - [#389](https://github.com/PHP-DI/PHP-DI/pull/389): exception message improvement by [@mopahle](https://github.com/mopahle) - [#359](https://github.com/PHP-DI/PHP-DI/issues/359), [#411](https://github.com/PHP-DI/PHP-DI/issues/411), [#414](https://github.com/PHP-DI/PHP-DI/pull/414), [#412](https://github.com/PHP-DI/PHP-DI/pull/412): compatibility with ProxyManager 1.* and 2.* (by [@holtkamp](https://github.com/holtkamp) and [@mnapoli](https://github.com/mnapoli)) - [#416](https://github.com/PHP-DI/PHP-DI/pull/416): dumping definitions was refactored into a more lightweight and simple solution; definition "dumpers" have been removed (internal classes), definitions can now be cast to string directly (by [@mnapoli](https://github.com/mnapoli)) ## 5.2 Read the [news entry](news/17-php-di-5-2-released.md). Improvements: - [#347](https://github.com/PHP-DI/PHP-DI/pull/347) (includes [#333](https://github.com/PHP-DI/PHP-DI/pull/333) and [#345](https://github.com/PHP-DI/PHP-DI/pull/345)): by [@jdreesen](https://github.com/jdreesen), [@quimcalpe](https://github.com/quimcalpe) and [@mnapoli](https://github.com/mnapoli) - Allow injection of any container object as factory parameter via type hinting - Allow injection of a `DI\Factory\RequestedEntry` object to get the requested entry name - [#272](https://github.com/PHP-DI/PHP-DI/issues/272): Support `"Class::method""` syntax for callables (by [@jdreesen](https://github.com/jdreesen)) - [#332](https://github.com/PHP-DI/PHP-DI/issues/332): IDE support (plugin and documentation) (by [@pulyaevskiy](https://github.com/pulyaevskiy), [@avant1](https://github.com/avant1) and [@mnapoli](https://github.com/mnapoli)) - [#326](https://github.com/PHP-DI/PHP-DI/pull/326): Exception messages are simpler and more consistent (by [@mnapoli](https://github.com/mnapoli)) - [#325](https://github.com/PHP-DI/PHP-DI/pull/325): Add a "Edit this page" button in the website to encourage users to improve the documentation (by [@jdreesen](https://github.com/jdreesen)) Bugfixes: - [#321](https://github.com/PHP-DI/PHP-DI/pull/321): Allow factory definitions to reference arbitrary container entries as callables (by [@jdreesen](https://github.com/jdreesen)) - [#335](https://github.com/PHP-DI/PHP-DI/issues/335): Class imports in traits are now considered when parsing annotations (by [@thebigb](https://github.com/thebigb)) ## 5.1 Read the [news entry](news/16-php-di-5-1-released.md). Improvements: - [Zend Framework 2 integration](https://github.com/PHP-DI/ZF2-Bridge) (by @Rastusik) - [#308](https://github.com/PHP-DI/PHP-DI/pull/308): Instantiate factories using the container (`DI\factory(['FooFactory', 'create'])`) - Many performances improvements - some benchmarks show up to 35% performance improvements, real results may vary of course - Many documentation improvements (@jdreesen, @mindplay-dk, @mnapoli, @holtkamp, @Rastusik) - [#296](https://github.com/PHP-DI/PHP-DI/issues/296): Provide a faster `ArrayCache` implementation, mostly useful in micro-benchmarks Bugfixes: - [#257](https://github.com/PHP-DI/PHP-DI/issues/257) & [#274](https://github.com/PHP-DI/PHP-DI/issues/274): Private properties of parent classes are not injected when using annotations - [#300](https://github.com/PHP-DI/PHP-DI/pull/300): Exception if object definition extends an incompatible definition - [#306](https://github.com/PHP-DI/PHP-DI/issues/306): Errors when using parameters passed by reference (fixed by @bradynpoulsen) - [#318](https://github.com/PHP-DI/PHP-DI/issues/318): `Container::call()` ignores parameter's default value Internal changes: - [#276](https://github.com/PHP-DI/PHP-DI/pull/276): Tests now pass on Windows (@bgaillard) ## 5.0 This is the complete change log. You can also read the [migration guide](doc/migration/5.0.md) for upgrading, or [the news article](news/15-php-di-5-0-released.md) for a nicer introduction to this new version. Improvements: - Moved to an organization on GitHub: [github.com/PHP-DI/PHP-DI](https://github.com/PHP-DI/PHP-DI) - The package has been renamed to: from `mnapoli/php-di` to [`php-di/php-di`](https://packagist.org/packages/php-di/php-di) - New [Silex integration](doc/frameworks/silex.md) - Lighter package: from 10 to 3 Composer dependencies! - [#235](https://github.com/PHP-DI/PHP-DI/issues/235): `DI\link()` is now deprecated in favor of `DI\get()`. There is no BC break as `DI\link()` still works. - [#207](https://github.com/PHP-DI/PHP-DI/issues/207): Support for `DI\link()` in arrays - [#203](https://github.com/PHP-DI/PHP-DI/issues/203): New `DI\string()` helper ([documentation](doc/php-definitions.md)) - [#208](https://github.com/PHP-DI/PHP-DI/issues/208): Support for nested definitions - [#226](https://github.com/PHP-DI/PHP-DI/pull/226): `DI\factory()` can now be omitted with closures: ```php // before 'My\Class' => DI\factory(function () { ... }) // now (optional shortcut) 'My\Class' => function () { ... } ``` - [#193](https://github.com/PHP-DI/PHP-DI/issues/193): `DI\object()->method()` now supports calling the same method twice (or more). - [#248](https://github.com/PHP-DI/PHP-DI/issues/248): New `DI\decorate()` helper to decorate a previously defined entry ([documentation](doc/definition-overriding.md)) - [#215](https://github.com/PHP-DI/PHP-DI/pull/215): New `DI\add()` helper to add entries to an existing array ([documentation](doc/definition-overriding.md)) - [#218](https://github.com/PHP-DI/PHP-DI/issues/218): `ContainerBuilder::addDefinitions()` can now take an array of definitions - [#211](https://github.com/PHP-DI/PHP-DI/pull/211): `ContainerBuilder::addDefinitions()` is now fluent (return `$this`) - [#250](https://github.com/PHP-DI/PHP-DI/issues/250): `Container::call()` now also accepts parameters not indexed by name as well as embedded definitions ([documentation](doc/container.md)) - Various performance improvements, e.g. lower the number of files loaded, simpler architecture, … BC breaks: - PHP-DI now requires a version of PHP >= 5.4.0 - The package is lighter by default: - [#251](https://github.com/PHP-DI/PHP-DI/issues/251): Annotations are disabled by default, if you use annotations enable them with `$containerBuilder->useAnnotations(true)`. Additionally the `doctrine/annotations` package isn't required by default anymore, so you also need to run `composer require doctrine/annotations`. - `doctrine/cache` is not installed by default anymore, you need to require it in `composer.json` (`~1.0`) if you want to configure a cache for PHP-DI - [#198](https://github.com/PHP-DI/PHP-DI/issues/198): `ocramius/proxy-manager` is not installed by default anymore, you need to require it in `composer.json` (`~1.0`) if you want to use **lazy injection** - Closures are now converted into factory definitions automatically. If you ever defined a closure as a value (e.g. to have the closure injected in a class), you need to wrap the closure with the new `DI\value()` helper. - [#223](https://github.com/PHP-DI/PHP-DI/issues/223): `DI\ContainerInterface` was deprecated since v4.1 and has been removed Internal changes in case you were replacing/extending some parts: - the definition sources architecture has been refactored, if you defined custom definition sources you will need to update your code (it should be much easier now) - [#252](https://github.com/PHP-DI/PHP-DI/pull/252): `DI\Scope` internal implementation has changed. You are encouraged to use the constants (`DI\Scope::SINGLETON` and `DI\Scope::PROTOTYPE`) instead of the static methods, but backward compatibility is kept (static methods still work). - [#241](https://github.com/PHP-DI/PHP-DI/issues/241): `Container::call()` now uses the *Invoker* external library ## 4.4 Read the [news entry](news/13-php-di-4-4-released.md). - [#185](https://github.com/PHP-DI/PHP-DI/issues/185) Support for invokable objects in `Container::call()` - [#192](https://github.com/PHP-DI/PHP-DI/pull/192) Support for invokable classes in `Container::call()` (will instantiate the class) - [#184](https://github.com/PHP-DI/PHP-DI/pull/184) Option to ignore phpdoc errors ## 4.3 Read the [news entry](news/11-php-di-4-3-released.md). - [#176](https://github.com/PHP-DI/PHP-DI/pull/176) New definition type for reading environment variables: `DI\env()` - [#181](https://github.com/PHP-DI/PHP-DI/pull/181) `DI\FactoryInterface` and `DI\InvokerInterface` are now auto-registered inside the container so that you can inject them without any configuration needed - [#173](https://github.com/PHP-DI/PHP-DI/pull/173) `$container->call(['MyClass', 'method]);` will get `MyClass` from the container if `method()` is not a static method ## 4.2.2 - Fixed [#180](https://github.com/PHP-DI/PHP-DI/pull/180): `Container::call()` with object methods (`[$object, 'method']`) is now supported ## 4.2.1 - Support for PHP 5.3.3, which was previously incomplete because of a bug in the reflection (there is now a workaround for this bug) But if you can, seriously avoid this (really old) PHP version and upgrade. ## 4.2 Read the [news entry](news/10-php-di-4-2-released.md). **Minor BC-break**: Optional parameters (that were not configured) were injected, they are now ignored, which is what naturally makes sense since they are optional. Example: ```php public function __construct(Bar $bar = null) { $this->bar = $bar ?: $this->createDefaultBar(); } ``` Before 4.2, PHP-DI would try to inject a `Bar` instance. From 4.2 and onwards, it will inject `null`. Of course, you can still explicitly define an injection for the optional parameters and that will work. All changes: * [#162](https://github.com/PHP-DI/PHP-DI/pull/162) Added `Container::call()` to call functions with dependency injection * [#156](https://github.com/PHP-DI/PHP-DI/issues/156) Wildcards (`*`) in definitions * [#164](https://github.com/PHP-DI/PHP-DI/issues/164) Prototype scope is now available for `factory()` definitions too * FIXED [#168](https://github.com/PHP-DI/PHP-DI/pull/168) `Container::has()` now returns false for interfaces and abstract classes that are not mapped in the definitions * FIXED [#171](https://github.com/PHP-DI/PHP-DI/issues/171) Optional parameters are now ignored (not injected) if not set in the definitions (see the BC-break warning above) ## 4.1 Read the [news entry](news/09-php-di-4-1-released.md). BC-breaks: None. * [#138](https://github.com/PHP-DI/PHP-DI/issues/138) [Container-interop](https://github.com/container-interop/container-interop) compliance * [#143](https://github.com/PHP-DI/PHP-DI/issues/143) Much more explicit exception messages * [#157](https://github.com/PHP-DI/PHP-DI/issues/157) HHVM support * [#158](https://github.com/PHP-DI/PHP-DI/issues/158) Improved the documentation for [Symfony 2 integration](https://php-di.org/doc/frameworks/symfony2.html) ## 4.0 Major changes: * The configuration format has changed ([read more here to understand why](news/06-php-di-4-0-new-definitions.md)) Read the migration guide if you are using 3.x: [Migration guide from 3.x to 4.0](doc/migration/4.0.md). BC-breaks: * YAML, XML and JSON definitions have been removed, and the PHP definition format has changed (see above) * `ContainerSingleton` has been removed * You cannot configure an injection as lazy anymore, you can only configure a container entry as lazy * The Container constructor now takes mandatory parameters. Use the ContainerBuilder to create a Container. * Removed `ContainerBuilder::setDefinitionsValidation()` (no definition validation anymore) * `ContainerBuilder::useReflection()` is now named: `ContainerBuilder::useAutowiring()` * `ContainerBuilder::addDefinitionsFromFile()` is now named: `ContainerBuilder::addDefinitions()` * The `$proxy` parameter in `Container::get($name, $proxy = true)` hase been removed. To get a proxy, you now need to define an entry as "lazy". Other changes: * Added `ContainerInterface` and `FactoryInterface`, both implemented by the container. * [#115](https://github.com/PHP-DI/PHP-DI/issues/115) Added `Container::has()` * [#142](https://github.com/PHP-DI/PHP-DI/issues/142) Added `Container::make()` to resolve an entry * [#127](https://github.com/PHP-DI/PHP-DI/issues/127) Added support for cases where PHP-DI is wrapped by another container (like Acclimate): PHP-DI can now use the wrapping container to perform injections * [#128](https://github.com/PHP-DI/PHP-DI/issues/128) Configure entry aliases * [#110](https://github.com/PHP-DI/PHP-DI/issues/110) XML definitions are not supported anymore * [#122](https://github.com/PHP-DI/PHP-DI/issues/122) JSON definitions are not supported anymore * `ContainerSingleton` has finally been removed * Added `ContainerBuilder::buildDevContainer()` to get started with a default container very easily. * [#99](https://github.com/PHP-DI/PHP-DI/issues/99) Fixed "`@param` with PHP internal type throws exception" ## 3.5.1 * FIXED [#126](https://github.com/PHP-DI/PHP-DI/issues/126): `Container::set` without effect if a value has already been set and retrieved ## 3.5 Read the [news entry](news/05-php-di-3-5.md). * Importing `@Inject` and `@Injectable` annotations is now optional! It means that you don't have to write `use DI\Annotation\Inject` anymore * FIXED [#124](https://github.com/PHP-DI/PHP-DI/issues/124): `@Injects` annotation conflicts with other annotations ## 3.4 Read the [news entry](news/04-php-di-3-4.md). * [#106](https://github.com/PHP-DI/PHP-DI/pull/106) You can now define arrays of values (in YAML, PHP, …) thanks to [@unkind](https://github.com/unkind) * [#98](https://github.com/PHP-DI/PHP-DI/issues/98) `ContainerBuilder` is now fluent thanks to [@drdamour](https://github.com/drdamour) * [#101](https://github.com/PHP-DI/PHP-DI/pull/101) Optional parameters are now supported: if you don't define a value to inject, their default value will be used * XML definitions have been deprecated, there weren't even documented and were not maintained. They will be removed in 4.0. * FIXED [#100](https://github.com/PHP-DI/PHP-DI/issues/100): bug for lazy injection in constructors ## 3.3 Read the [news entry](news/03-php-di-3-3.md). * Inject dependencies on an existing instance with `Container::injectOn` (work from [Jeff Flitton](https://github.com/jflitton): [#89](https://github.com/PHP-DI/PHP-DI/pull/89)). * [#86](https://github.com/PHP-DI/PHP-DI/issues/86): Optimized definition lookup (faster) * FIXED [#87](https://github.com/PHP-DI/PHP-DI/issues/87): Rare bug in the `PhpDocParser`, fixed by [drdamour](https://github.com/drdamour) ## 3.2 Read the [news entry](news/02-php-di-3-2.md). Small BC-break: PHP-DI 3.0 and 3.1 injected properties before calling the constructor. This was confusing and [not supported for internal classes](https://github.com/PHP-DI/PHP-DI/issues/74). From 3.2 and on, properties are injected after calling the constructor. * **[Lazy injection](doc/lazy-injection.md)**: it is now possible to use lazy injection on properties and methods (setters and constructors). * Lazy dependencies are now proxies that extend the class they proxy, so type-hinting works. * Addition of the **`ContainerBuilder`** object, that helps to [create and configure a `Container`](doc/container-configuration.md). * Some methods for configuring the Container have gone **deprecated** in favor of the `ContainerBuilder`. Fear not, these deprecated methods will remain until next major version (4.0). * `Container::useReflection`, use ContainerBuilder::useReflection instead * `Container::useAnnotations`, use ContainerBuilder::useAnnotations instead * `Container::setDefinitionCache`, use ContainerBuilder::setDefinitionCache instead * `Container::setDefinitionsValidation`, use ContainerBuilder::setDefinitionsValidation instead * The container is now auto-registered (as 'DI\Container'). You can now inject the container without registering it. ## 3.1.1 * Value definitions (`$container->set('foo', 80)`) are not cached anymore * FIXED [#82](https://github.com/PHP-DI/PHP-DI/issues/82): Serialization error when using a cache ## 3.1 Read the [news entry](news/01-php-di-3-1.md). * Zend Framework 1 integration through the [PHP-DI-ZF1 project](https://github.com/PHP-DI/PHP-DI-ZF1) * Fixed the order of priorities when you mix different definition sources (reflection, annotations, files, …). See [Definition overriding](doc/definition-overriding.md) * Now possible to define null values with `$container->set('foo', null)` (see [#79](https://github.com/PHP-DI/PHP-DI/issues/79)). * Deprecated usage of `ContainerSingleton`, will be removed in next major version (4.0) ## 3.0.6 * FIXED [#76](https://github.com/PHP-DI/PHP-DI/issues/76): Definition conflict when setting a closure for a class name ## 3.0.5 * FIXED [#70](https://github.com/PHP-DI/PHP-DI/issues/70): Definition conflict when setting a value for a class name ## 3.0.4 * FIXED [#69](https://github.com/PHP-DI/PHP-DI/issues/69): YamlDefinitionFileLoader crashes if YAML file is empty ## 3.0.3 * Fixed over-restrictive dependencies in composer.json ## 3.0.2 * [#64](https://github.com/PHP-DI/PHP-DI/issues/64): Non PHP-DI exceptions are not captured-rethrown anymore when injecting dependencies (cleaner stack trace) ## 3.0.1 * [#62](https://github.com/PHP-DI/PHP-DI/issues/62): When using aliases, definitions are now merged ## 3.0 Major compatibility breaks with 2.x. * The container is no longer a Singleton (but `ContainerSingleton::getInstance()` is available for fools who like it) * Setter injection * Constructor injection * Scopes: singleton (share the same instance of the class) or prototype (create a new instance each time it is fetched). Defined at class level. * Configuration is reworked from scratch. Now every configuration backend can do 100% of the job. * Provided configuration backends: * Reflection * Annotations: @Inject, @Injectable * PHP code (`Container::set()`) * PHP array * YAML file * As a consequence, annotations are not mandatory anymore, all functionalities can be used with or without annotations. * Renamed `DI\Annotations\` to `DI\Annotation\` * `Container` no longer implements ArrayAccess, use only `$container->get($key)` now * ZF1 integration broken and removed (work in progress for next releases) * Code now follows PSR1 and PSR2 coding styles * FIXED: [#58](https://github.com/PHP-DI/PHP-DI/issues/58) Getting a proxy of an alias didn't work ## 2.1 * `use` statements to import classes from other namespaces are now taken into account with the `@var` annotation * Updated and lightened the dependencies : `doctrine/common` has been replaced with more specific `doctrine/annotations` and `doctrine/cache` ## 2.0 Major compatibility breaks with 1.x. * `Container::resolveDependencies()` has been renamed to `Container::injectAll()` * Dependencies are now injected **before** the constructor is called, and thus are available in the constructor * Merged `@Value` annotation with `@Inject`: no difference between value and bean injection anymore * Container implements ArrayAccess for get() and set() (`$container['db.host'] = 'localhost';`) * Ini configuration files removed: configuration is done in PHP * Allow to define beans within closures for lazy-loading * Switched to MIT License Warning: * If you use PHP 5.3 and __wakeup() methods, they will be called when PHP-DI creates new instances of those classes. ## 1.1 * Caching of annotations based on Doctrine caches ## 1.0 * DependencyManager renamed to Container * Refactored basic Container usage with `get` and `set` * Allow named injection `@Inject(name="")` * Zend Framework integration { "name": "php-di/php-di", "type": "library", "description": "The dependency injection container for humans", "keywords": ["di", "dependency injection", "container", "ioc", "psr-11", "psr11", "container-interop"], "homepage": "https://php-di.org/", "license": "MIT", "autoload": { "psr-4": { "DI\\": "src/" }, "files": [ "src/functions.php" ] }, "autoload-dev": { "psr-4": { "DI\\Test\\IntegrationTest\\": "tests/IntegrationTest/", "DI\\Test\\UnitTest\\": "tests/UnitTest/" } }, "scripts": { "test": "phpunit", "format-code": "php-cs-fixer fix --allow-risky=yes" }, "require": { "php": ">=8.0", "psr/container": "^1.1 || ^2.0", "php-di/invoker": "^2.0", "laravel/serializable-closure": "^1.0 || ^2.0" }, "require-dev": { "phpunit/phpunit": "^9.6 || ^10 || ^11", "mnapoli/phpunit-easymock": "^1.3", "friendsofphp/proxy-manager-lts": "^1", "friendsofphp/php-cs-fixer": "^3", "vimeo/psalm": "^5|^6" }, "provide": { "psr/container-implementation": "^1.0" }, "suggest": { "friendsofphp/proxy-manager-lts": "Install it if you want to use lazy injection (version ^1)" } } */ #[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_METHOD | Attribute::TARGET_PARAMETER)] class Inject { /** * Entry name. */ private ?string $name = null; /** * Parameters, indexed by the parameter number (index) or name. * * Used if the attribute is set on a method */ private array $parameters = []; /** * @throws InvalidAttribute */ public function __construct(string|array|null $name = null) { // #[Inject('foo')] or #[Inject(name: 'foo')] if (is_string($name)) { $this->name = $name; } // #[Inject([...])] on a method if (is_array($name)) { foreach ($name as $key => $value) { if (! is_string($value)) { throw new InvalidAttribute(sprintf( "#[Inject(['param' => 'value'])] expects \"value\" to be a string, %s given.", json_encode($value, \JSON_THROW_ON_ERROR) )); } $this->parameters[$key] = $value; } } } /** * @return string|null Name of the entry to inject */ public function getName() : ?string { return $this->name; } /** * @return array Parameters, indexed by the parameter number (index) or name */ public function getParameters() : array { return $this->parameters; } } * @author Matthieu Napoli */ #[Attribute(Attribute::TARGET_CLASS)] class Injectable { /** * @param bool|null $lazy Should the object be lazy-loaded. */ public function __construct( private ?bool $lazy = null, ) { } public function isLazy() : ?bool { return $this->lazy; } } */ abstract class CompiledContainer extends Container { /** * This const is overridden in child classes (compiled containers). * @var array */ protected const METHOD_MAPPING = []; private ?InvokerInterface $factoryInvoker = null; public function get(string $id) : mixed { // Try to find the entry in the singleton map if (isset($this->resolvedEntries[$id]) || array_key_exists($id, $this->resolvedEntries)) { return $this->resolvedEntries[$id]; } /** @psalm-suppress UndefinedConstant */ $method = static::METHOD_MAPPING[$id] ?? null; // If it's a compiled entry, then there is a method in this class if ($method !== null) { // Check if we are already getting this entry -> circular dependency if (isset($this->entriesBeingResolved[$id])) { $idList = implode(' -> ', [...array_keys($this->entriesBeingResolved), $id]); throw new DependencyException("Circular dependency detected while trying to resolve entry '$id': Dependencies: " . $idList); } $this->entriesBeingResolved[$id] = true; try { $value = $this->$method(); } finally { unset($this->entriesBeingResolved[$id]); } // Store the entry to always return it without recomputing it $this->resolvedEntries[$id] = $value; return $value; } return parent::get($id); } public function has(string $id) : bool { // The parent method is overridden to check in our array, it avoids resolving definitions /** @psalm-suppress UndefinedConstant */ if (isset(static::METHOD_MAPPING[$id])) { return true; } return parent::has($id); } protected function setDefinition(string $name, Definition $definition) : void { // It needs to be forbidden because that would mean get() must go through the definitions // every time, which kinds of defeats the performance gains of the compiled container throw new \LogicException('You cannot set a definition at runtime on a compiled container. You can either put your definitions in a file, disable compilation or ->set() a raw value directly (PHP object, string, int, ...) instead of a PHP-DI definition.'); } /** * Invoke the given callable. */ protected function resolveFactory($callable, $entryName, array $extraParameters = []) : mixed { // Initialize the factory resolver if (! $this->factoryInvoker) { $parameterResolver = new ResolverChain([ new AssociativeArrayResolver, new FactoryParameterResolver($this->delegateContainer), new NumericArrayResolver, new DefaultValueResolver, ]); $this->factoryInvoker = new Invoker($parameterResolver, $this->delegateContainer); } $parameters = [$this->delegateContainer, new RequestedEntryHolder($entryName)]; $parameters = array_merge($parameters, $extraParameters); try { return $this->factoryInvoker->call($callable, $parameters); } catch (NotCallableException $e) { throw new InvalidDefinition("Entry \"$entryName\" cannot be resolved: factory " . $e->getMessage()); } catch (NotEnoughParametersException $e) { throw new InvalidDefinition("Entry \"$entryName\" cannot be resolved: " . $e->getMessage()); } } } */ class Compiler { private string $containerClass; private string $containerParentClass; /** * Definitions indexed by the entry name. The value can be null if the definition needs to be fetched. * * Keys are strings, values are `Definition` objects or null. */ private \ArrayIterator $entriesToCompile; /** * Progressive counter for definitions. * * Each key in $entriesToCompile is defined as 'SubEntry' + counter * and each definition has always the same key in the CompiledContainer * if PHP-DI configuration does not change. */ private int $subEntryCounter = 0; /** * Progressive counter for CompiledContainer get methods. * * Each CompiledContainer method name is defined as 'get' + counter * and remains the same after each recompilation * if PHP-DI configuration does not change. */ private int $methodMappingCounter = 0; /** * Map of entry names to method names. * * @var string[] */ private array $entryToMethodMapping = []; /** * @var string[] */ private array $methods = []; private bool $autowiringEnabled; public function __construct( private ProxyFactoryInterface $proxyFactory, ) { } public function getProxyFactory() : ProxyFactoryInterface { return $this->proxyFactory; } /** * Compile the container. * * @return string The compiled container file name. */ public function compile( DefinitionSource $definitionSource, string $directory, string $className, string $parentClassName, bool $autowiringEnabled, ) : string { $fileName = rtrim($directory, '/') . '/' . $className . '.php'; if (file_exists($fileName)) { // The container is already compiled return $fileName; } $this->autowiringEnabled = $autowiringEnabled; // Validate that a valid class name was provided $validClassName = preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $className); if (!$validClassName) { throw new InvalidArgumentException("The container cannot be compiled: `$className` is not a valid PHP class name"); } $this->entriesToCompile = new \ArrayIterator($definitionSource->getDefinitions()); // We use an ArrayIterator so that we can keep adding new items to the list while we compile entries foreach ($this->entriesToCompile as $entryName => $definition) { $silenceErrors = false; // This is an entry found by reference during autowiring if (!$definition) { $definition = $definitionSource->getDefinition($entryName); // We silence errors for those entries because type-hints may reference interfaces/abstract classes // which could later be defined, or even not used (we don't want to block the compilation for those) $silenceErrors = true; } if (!$definition) { // We do not throw a `NotFound` exception here because the dependency // could be defined at runtime continue; } // Check that the definition can be compiled $errorMessage = $this->isCompilable($definition); if ($errorMessage !== true) { continue; } try { $this->compileDefinition($entryName, $definition); } catch (InvalidDefinition $e) { if ($silenceErrors) { // forget the entry unset($this->entryToMethodMapping[$entryName]); } else { throw $e; } } } $this->containerClass = $className; $this->containerParentClass = $parentClassName; ob_start(); require __DIR__ . '/Template.php'; $fileContent = ob_get_clean(); $fileContent = "createCompilationDirectory(dirname($fileName)); $this->writeFileAtomic($fileName, $fileContent); return $fileName; } private function writeFileAtomic(string $fileName, string $content) : void { $tmpFile = @tempnam(dirname($fileName), 'swap-compile'); if ($tmpFile === false) { throw new InvalidArgumentException( sprintf('Error while creating temporary file in %s', dirname($fileName)) ); } @chmod($tmpFile, 0666); $written = file_put_contents($tmpFile, $content); if ($written === false) { @unlink($tmpFile); throw new InvalidArgumentException(sprintf('Error while writing to %s', $tmpFile)); } @chmod($tmpFile, 0666); $renamed = @rename($tmpFile, $fileName); if (!$renamed) { @unlink($tmpFile); throw new InvalidArgumentException(sprintf('Error while renaming %s to %s', $tmpFile, $fileName)); } } /** * @return string The method name * @throws DependencyException * @throws InvalidDefinition */ private function compileDefinition(string $entryName, Definition $definition) : string { // Generate a unique method name $methodName = 'get' . (++$this->methodMappingCounter); $this->entryToMethodMapping[$entryName] = $methodName; switch (true) { case $definition instanceof ValueDefinition: $value = $definition->getValue(); $code = 'return ' . $this->compileValue($value) . ';'; break; case $definition instanceof Reference: $targetEntryName = $definition->getTargetEntryName(); $code = 'return $this->delegateContainer->get(' . $this->compileValue($targetEntryName) . ');'; // If this method is not yet compiled we store it for compilation if (!isset($this->entriesToCompile[$targetEntryName])) { $this->entriesToCompile[$targetEntryName] = null; } break; case $definition instanceof StringDefinition: $entryName = $this->compileValue($definition->getName()); $expression = $this->compileValue($definition->getExpression()); $code = 'return \DI\Definition\StringDefinition::resolveExpression(' . $entryName . ', ' . $expression . ', $this->delegateContainer);'; break; case $definition instanceof EnvironmentVariableDefinition: $variableName = $this->compileValue($definition->getVariableName()); $isOptional = $this->compileValue($definition->isOptional()); $defaultValue = $this->compileValue($definition->getDefaultValue()); $code = <<getVariableName()}' has not been defined"); } return $defaultValue; PHP; break; case $definition instanceof ArrayDefinition: try { $code = 'return ' . $this->compileValue($definition->getValues()) . ';'; } catch (\Exception $e) { throw new DependencyException(sprintf( 'Error while compiling %s. %s', $definition->getName(), $e->getMessage() ), 0, $e); } break; case $definition instanceof ObjectDefinition: $compiler = new ObjectCreationCompiler($this); $code = $compiler->compile($definition); $code .= "\n return \$object;"; break; case $definition instanceof DecoratorDefinition: $decoratedDefinition = $definition->getDecoratedDefinition(); if (! $decoratedDefinition instanceof Definition) { if (! $definition->getName()) { throw new InvalidDefinition('Decorators cannot be nested in another definition'); } throw new InvalidDefinition(sprintf( 'Entry "%s" decorates nothing: no previous definition with the same name was found', $definition->getName() )); } $code = sprintf( 'return call_user_func(%s, %s, $this->delegateContainer);', $this->compileValue($definition->getCallable()), $this->compileValue($decoratedDefinition) ); break; case $definition instanceof FactoryDefinition: $value = $definition->getCallable(); // Custom error message to help debugging $isInvokableClass = is_string($value) && class_exists($value) && method_exists($value, '__invoke'); if ($isInvokableClass && !$this->autowiringEnabled) { throw new InvalidDefinition(sprintf( 'Entry "%s" cannot be compiled. Invokable classes cannot be automatically resolved if autowiring is disabled on the container, you need to enable autowiring or define the entry manually.', $entryName )); } $definitionParameters = ''; if (!empty($definition->getParameters())) { $definitionParameters = ', ' . $this->compileValue($definition->getParameters()); } $code = sprintf( 'return $this->resolveFactory(%s, %s%s);', $this->compileValue($value), var_export($entryName, true), $definitionParameters ); break; default: // This case should not happen (so it cannot be tested) throw new \Exception('Cannot compile definition of type ' . $definition::class); } $this->methods[$methodName] = $code; return $methodName; } public function compileValue(mixed $value) : string { // Check that the value can be compiled $errorMessage = $this->isCompilable($value); if ($errorMessage !== true) { throw new InvalidDefinition($errorMessage); } if ($value instanceof Definition) { // Give it an arbitrary unique name $subEntryName = 'subEntry' . (++$this->subEntryCounter); // Compile the sub-definition in another method $methodName = $this->compileDefinition($subEntryName, $value); // The value is now a method call to that method (which returns the value) return "\$this->$methodName()"; } if (is_array($value)) { $value = array_map(function ($value, $key) { $compiledValue = $this->compileValue($value); $key = var_export($key, true); return " $key => $compiledValue,\n"; }, $value, array_keys($value)); $value = implode('', $value); return "[\n$value ]"; } if ($value instanceof \Closure) { return $this->compileClosure($value); } return var_export($value, true); } private function createCompilationDirectory(string $directory) : void { if (!is_dir($directory) && !@mkdir($directory, 0777, true) && !is_dir($directory)) { throw new InvalidArgumentException(sprintf('Compilation directory does not exist and cannot be created: %s.', $directory)); } if (!is_writable($directory)) { throw new InvalidArgumentException(sprintf('Compilation directory is not writable: %s.', $directory)); } } /** * @return string|true If true is returned that means that the value is compilable. */ private function isCompilable($value) : string|bool { if ($value instanceof ValueDefinition) { return $this->isCompilable($value->getValue()); } if (($value instanceof DecoratorDefinition) && empty($value->getName())) { return 'Decorators cannot be nested in another definition'; } // All other definitions are compilable if ($value instanceof Definition) { return true; } if ($value instanceof \Closure) { return true; } /** @psalm-suppress UndefinedClass */ if ((\PHP_VERSION_ID >= 80100) && ($value instanceof \UnitEnum)) { return true; } if (is_object($value)) { return 'An object was found but objects cannot be compiled'; } if (is_resource($value)) { return 'A resource was found but resources cannot be compiled'; } return true; } /** * @throws InvalidDefinition */ private function compileClosure(\Closure $closure) : string { $reflector = new ReflectionClosure($closure); if ($reflector->getUseVariables()) { throw new InvalidDefinition('Cannot compile closures which import variables using the `use` keyword'); } if ($reflector->isBindingRequired() || $reflector->isScopeRequired()) { throw new InvalidDefinition('Cannot compile closures which use $this or self/static/parent references'); } // Force all closures to be static (add the `static` keyword), i.e. they can't use // $this, which makes sense since their code is copied into another class. $code = ($reflector->isStatic() ? '' : 'static ') . $reflector->getCode(); return trim($code, "\t\n\r;"); } } */ class ObjectCreationCompiler { public function __construct( private Compiler $compiler, ) { } public function compile(ObjectDefinition $definition) : string { $this->assertClassIsNotAnonymous($definition); $this->assertClassIsInstantiable($definition); /** @var class-string $className At this point we have checked the class is valid */ $className = $definition->getClassName(); // Lazy? if ($definition->isLazy()) { return $this->compileLazyDefinition($definition); } try { $classReflection = new ReflectionClass($className); $constructorArguments = $this->resolveParameters($definition->getConstructorInjection(), $classReflection->getConstructor()); $dumpedConstructorArguments = array_map(function ($value) { return $this->compiler->compileValue($value); }, $constructorArguments); $code = []; $code[] = sprintf( '$object = new %s(%s);', $className, implode(', ', $dumpedConstructorArguments) ); // Property injections foreach ($definition->getPropertyInjections() as $propertyInjection) { $value = $propertyInjection->getValue(); $value = $this->compiler->compileValue($value); $propertyClassName = $propertyInjection->getClassName() ?: $className; $property = new ReflectionProperty($propertyClassName, $propertyInjection->getPropertyName()); if ($property->isPublic() && !(\PHP_VERSION_ID >= 80100 && $property->isReadOnly())) { $code[] = sprintf('$object->%s = %s;', $propertyInjection->getPropertyName(), $value); } else { // Private/protected/readonly property $code[] = sprintf( '\DI\Definition\Resolver\ObjectCreator::setPrivatePropertyValue(%s, $object, \'%s\', %s);', var_export($propertyInjection->getClassName(), true), $propertyInjection->getPropertyName(), $value ); } } // Method injections foreach ($definition->getMethodInjections() as $methodInjection) { $methodReflection = new ReflectionMethod($className, $methodInjection->getMethodName()); $parameters = $this->resolveParameters($methodInjection, $methodReflection); $dumpedParameters = array_map(function ($value) { return $this->compiler->compileValue($value); }, $parameters); $code[] = sprintf( '$object->%s(%s);', $methodInjection->getMethodName(), implode(', ', $dumpedParameters) ); } } catch (InvalidDefinition $e) { throw InvalidDefinition::create($definition, sprintf( 'Entry "%s" cannot be compiled: %s', $definition->getName(), $e->getMessage() )); } return implode("\n ", $code); } public function resolveParameters(?MethodInjection $definition, ?ReflectionMethod $method) : array { $args = []; if (! $method) { return $args; } $definitionParameters = $definition ? $definition->getParameters() : []; foreach ($method->getParameters() as $index => $parameter) { if (array_key_exists($index, $definitionParameters)) { // Look in the definition $value = &$definitionParameters[$index]; } elseif ($parameter->isOptional()) { // If the parameter is optional and wasn't specified, we take its default value $args[] = $this->getParameterDefaultValue($parameter, $method); continue; } else { throw new InvalidDefinition(sprintf( 'Parameter $%s of %s has no value defined or guessable', $parameter->getName(), $this->getFunctionName($method) )); } $args[] = &$value; } return $args; } private function compileLazyDefinition(ObjectDefinition $definition) : string { $subDefinition = clone $definition; $subDefinition->setLazy(false); $subDefinition = $this->compiler->compileValue($subDefinition); /** @var class-string $className At this point we have checked the class is valid */ $className = $definition->getClassName(); $this->compiler->getProxyFactory()->generateProxyClass($className); return <<proxyFactory->createProxy( '{$definition->getClassName()}', function () { return $subDefinition; } ); STR; } /** * Returns the default value of a function parameter. * * @throws InvalidDefinition Can't get default values from PHP internal classes and functions */ private function getParameterDefaultValue(ReflectionParameter $parameter, ReflectionMethod $function) : mixed { try { return $parameter->getDefaultValue(); } catch (\ReflectionException) { throw new InvalidDefinition(sprintf( 'The parameter "%s" of %s has no type defined or guessable. It has a default value, ' . 'but the default value can\'t be read through Reflection because it is a PHP internal class.', $parameter->getName(), $this->getFunctionName($function) )); } } private function getFunctionName(ReflectionMethod $method) : string { return $method->getName() . '()'; } private function assertClassIsNotAnonymous(ObjectDefinition $definition) : void { if (str_contains($definition->getClassName(), '@')) { throw InvalidDefinition::create($definition, sprintf( 'Entry "%s" cannot be compiled: anonymous classes cannot be compiled', $definition->getName() )); } } private function assertClassIsInstantiable(ObjectDefinition $definition) : void { if ($definition->isInstantiable()) { return; } $message = ! $definition->classExists() ? 'Entry "%s" cannot be compiled: the class doesn\'t exist' : 'Entry "%s" cannot be compiled: the class is not instantiable'; throw InvalidDefinition::create($definition, sprintf($message, $definition->getName())); } } */ class RequestedEntryHolder implements RequestedEntry { public function __construct( private string $name, ) { } public function getName() : string { return $this->name; } } /** * This class has been auto-generated by PHP-DI. */ class containerClass; ?> extends containerParentClass; ?> { const METHOD_MAPPING = entryToMethodMapping); ?>; methods as $methodName => $methodContent) { ?> protected function () { } } */ class Container implements ContainerInterface, FactoryInterface, InvokerInterface { /** * Map of entries that are already resolved. */ protected array $resolvedEntries = []; private MutableDefinitionSource $definitionSource; private DefinitionResolver $definitionResolver; /** * Map of definitions that are already fetched (local cache). * * @var array */ private array $fetchedDefinitions = []; /** * Array of entries being resolved. Used to avoid circular dependencies and infinite loops. */ protected array $entriesBeingResolved = []; private ?InvokerInterface $invoker = null; /** * Container that wraps this container. If none, points to $this. */ protected ContainerInterface $delegateContainer; protected ProxyFactoryInterface $proxyFactory; public static function create( array $definitions, ) : static { $source = new SourceChain([new ReflectionBasedAutowiring]); $source->setMutableDefinitionSource(new DefinitionArray($definitions, new ReflectionBasedAutowiring)); return new static($definitions); } /** * Use `$container = new Container()` if you want a container with the default configuration. * * If you want to customize the container's behavior, you are discouraged to create and pass the * dependencies yourself, the ContainerBuilder class is here to help you instead. * * @see ContainerBuilder * * @param ContainerInterface $wrapperContainer If the container is wrapped by another container. */ public function __construct( array|MutableDefinitionSource $definitions = [], ?ProxyFactoryInterface $proxyFactory = null, ?ContainerInterface $wrapperContainer = null, ) { if (is_array($definitions)) { $this->definitionSource = $this->createDefaultDefinitionSource($definitions); } else { $this->definitionSource = $definitions; } $this->delegateContainer = $wrapperContainer ?: $this; if ($proxyFactory === null) { $proxyFactory = (\PHP_VERSION_ID >= 80400) ? new NativeProxyFactory : new ProxyFactory; } $this->proxyFactory = $proxyFactory; $this->definitionResolver = new ResolverDispatcher($this->delegateContainer, $this->proxyFactory); // Auto-register the container $this->resolvedEntries = [ self::class => $this, ContainerInterface::class => $this->delegateContainer, FactoryInterface::class => $this, InvokerInterface::class => $this, ]; } /** * Returns an entry of the container by its name. * * @template T * @param string|class-string $id Entry name or a class name. * * @return mixed|T * @throws DependencyException Error while resolving the entry. * @throws NotFoundException No entry found for the given name. */ public function get(string $id) : mixed { // If the entry is already resolved we return it if (isset($this->resolvedEntries[$id]) || array_key_exists($id, $this->resolvedEntries)) { return $this->resolvedEntries[$id]; } $definition = $this->getDefinition($id); if (! $definition) { throw new NotFoundException("No entry or class found for '$id'"); } $value = $this->resolveDefinition($definition); $this->resolvedEntries[$id] = $value; return $value; } private function getDefinition(string $name) : ?Definition { // Local cache that avoids fetching the same definition twice if (!array_key_exists($name, $this->fetchedDefinitions)) { $this->fetchedDefinitions[$name] = $this->definitionSource->getDefinition($name); } return $this->fetchedDefinitions[$name]; } /** * Build an entry of the container by its name. * * This method behave like get() except resolves the entry again every time. * For example if the entry is a class then a new instance will be created each time. * * This method makes the container behave like a factory. * * @template T * @param string|class-string $name Entry name or a class name. * @param array $parameters Optional parameters to use to build the entry. Use this to force * specific parameters to specific values. Parameters not defined in this * array will be resolved using the container. * * @return mixed|T * @throws InvalidArgumentException The name parameter must be of type string. * @throws DependencyException Error while resolving the entry. * @throws NotFoundException No entry found for the given name. */ public function make(string $name, array $parameters = []) : mixed { $definition = $this->getDefinition($name); if (! $definition) { // If the entry is already resolved we return it if (array_key_exists($name, $this->resolvedEntries)) { return $this->resolvedEntries[$name]; } throw new NotFoundException("No entry or class found for '$name'"); } return $this->resolveDefinition($definition, $parameters); } public function has(string $id) : bool { if (array_key_exists($id, $this->resolvedEntries)) { return true; } $definition = $this->getDefinition($id); if ($definition === null) { return false; } return $this->definitionResolver->isResolvable($definition); } /** * Inject all dependencies on an existing instance. * * @template T * @param object|T $instance Object to perform injection upon * @return object|T $instance Returns the same instance * @throws InvalidArgumentException * @throws DependencyException Error while injecting dependencies */ public function injectOn(object $instance) : object { $className = $instance::class; // If the class is anonymous, don't cache its definition // Checking for anonymous classes is cleaner via Reflection, but also slower $objectDefinition = str_contains($className, '@anonymous') ? $this->definitionSource->getDefinition($className) : $this->getDefinition($className); if (! $objectDefinition instanceof ObjectDefinition) { return $instance; } $definition = new InstanceDefinition($instance, $objectDefinition); $this->definitionResolver->resolve($definition); return $instance; } /** * Call the given function using the given parameters. * * Missing parameters will be resolved from the container. * * @param callable|array|string $callable Function to call. * @param array $parameters Parameters to use. Can be indexed by the parameter names * or not indexed (same order as the parameters). * The array can also contain DI definitions, e.g. DI\get(). * * @return mixed Result of the function. */ public function call($callable, array $parameters = []) : mixed { return $this->getInvoker()->call($callable, $parameters); } /** * Define an object or a value in the container. * * @param string $name Entry name * @param mixed|DefinitionHelper $value Value, use definition helpers to define objects */ public function set(string $name, mixed $value) : void { if ($value instanceof DefinitionHelper) { $value = $value->getDefinition($name); } elseif ($value instanceof \Closure) { $value = new FactoryDefinition($name, $value); } if ($value instanceof ValueDefinition) { $this->resolvedEntries[$name] = $value->getValue(); } elseif ($value instanceof Definition) { $value->setName($name); $this->setDefinition($name, $value); } else { $this->resolvedEntries[$name] = $value; } } /** * Get defined container entries. * * @return string[] */ public function getKnownEntryNames() : array { $entries = array_unique(array_merge( array_keys($this->definitionSource->getDefinitions()), array_keys($this->resolvedEntries) )); sort($entries); return $entries; } /** * Get entry debug information. * * @param string $name Entry name * * @throws InvalidDefinition * @throws NotFoundException */ public function debugEntry(string $name) : string { $definition = $this->definitionSource->getDefinition($name); if ($definition instanceof Definition) { return (string) $definition; } if (array_key_exists($name, $this->resolvedEntries)) { return $this->getEntryType($this->resolvedEntries[$name]); } throw new NotFoundException("No entry or class found for '$name'"); } /** * Get formatted entry type. */ private function getEntryType(mixed $entry) : string { if (is_object($entry)) { return sprintf("Object (\n class = %s\n)", $entry::class); } if (is_array($entry)) { return preg_replace(['/^array \(/', '/\)$/'], ['[', ']'], var_export($entry, true)); } if (is_string($entry)) { return sprintf('Value (\'%s\')', $entry); } if (is_bool($entry)) { return sprintf('Value (%s)', $entry === true ? 'true' : 'false'); } return sprintf('Value (%s)', is_scalar($entry) ? (string) $entry : ucfirst(gettype($entry))); } /** * Resolves a definition. * * Checks for circular dependencies while resolving the definition. * * @throws DependencyException Error while resolving the entry. */ private function resolveDefinition(Definition $definition, array $parameters = []) : mixed { $entryName = $definition->getName(); // Check if we are already getting this entry -> circular dependency if (isset($this->entriesBeingResolved[$entryName])) { $entryList = implode(' -> ', [...array_keys($this->entriesBeingResolved), $entryName]); throw new DependencyException("Circular dependency detected while trying to resolve entry '$entryName': Dependencies: " . $entryList); } $this->entriesBeingResolved[$entryName] = true; // Resolve the definition try { $value = $this->definitionResolver->resolve($definition, $parameters); } finally { unset($this->entriesBeingResolved[$entryName]); } return $value; } protected function setDefinition(string $name, Definition $definition) : void { // Clear existing entry if it exists if (array_key_exists($name, $this->resolvedEntries)) { unset($this->resolvedEntries[$name]); } $this->fetchedDefinitions = []; // Completely clear this local cache $this->definitionSource->addDefinition($definition); } private function getInvoker() : InvokerInterface { if (! $this->invoker) { $parameterResolver = new ResolverChain([ new DefinitionParameterResolver($this->definitionResolver), new NumericArrayResolver, new AssociativeArrayResolver, new DefaultValueResolver, new TypeHintContainerResolver($this->delegateContainer), ]); $this->invoker = new Invoker($parameterResolver, $this); } return $this->invoker; } private function createDefaultDefinitionSource(array $definitions) : SourceChain { $autowiring = new ReflectionBasedAutowiring; $source = new SourceChain([$autowiring]); $source->setMutableDefinitionSource(new DefinitionArray($definitions, $autowiring)); return $source; } } build(); * * @api * * @since 3.2 * @author Matthieu Napoli * * @psalm-template ContainerClass of Container */ class ContainerBuilder { /** * Name of the container class, used to create the container. * @var class-string * @psalm-var class-string */ private string $containerClass; /** * Name of the container parent class, used on compiled container. * @var class-string * @psalm-var class-string */ private string $containerParentClass; private bool $useAutowiring = true; private bool $useAttributes = false; /** * If set, write the proxies to disk in this directory to improve performances. */ private ?string $proxyDirectory = null; /** * If PHP-DI is wrapped in another container, this references the wrapper. */ private ?ContainerInterface $wrapperContainer = null; /** * @var DefinitionSource[]|string[]|array[] */ private array $definitionSources = []; /** * Whether the container has already been built. */ private bool $locked = false; private ?string $compileToDirectory = null; private bool $sourceCache = false; protected string $sourceCacheNamespace = ''; /** * @param class-string $containerClass Name of the container class, used to create the container. * @psalm-param class-string $containerClass */ public function __construct(string $containerClass = Container::class) { $this->containerClass = $containerClass; } /** * Build and return a container. * * @return Container * @psalm-return ContainerClass */ public function build() { $sources = array_reverse($this->definitionSources); if ($this->useAttributes) { $autowiring = new AttributeBasedAutowiring; $sources[] = $autowiring; } elseif ($this->useAutowiring) { $autowiring = new ReflectionBasedAutowiring; $sources[] = $autowiring; } else { $autowiring = new NoAutowiring; } $sources = array_map(function ($definitions) use ($autowiring) { if (is_string($definitions)) { // File return new DefinitionFile($definitions, $autowiring); } if (is_array($definitions)) { return new DefinitionArray($definitions, $autowiring); } return $definitions; }, $sources); $source = new SourceChain($sources); // Mutable definition source $source->setMutableDefinitionSource(new DefinitionArray([], $autowiring)); if ($this->sourceCache) { if (!SourceCache::isSupported()) { throw new \Exception('APCu is not enabled, PHP-DI cannot use it as a cache'); } // Wrap the source with the cache decorator $source = new SourceCache($source, $this->sourceCacheNamespace); } $proxyFactory = (\PHP_VERSION_ID >= 80400) ? new NativeProxyFactory() : new ProxyFactory($this->proxyDirectory); $this->locked = true; $containerClass = $this->containerClass; if ($this->compileToDirectory) { $compiler = new Compiler($proxyFactory); $compiledContainerFile = $compiler->compile( $source, $this->compileToDirectory, $containerClass, $this->containerParentClass, $this->useAutowiring ); // Only load the file if it hasn't been already loaded // (the container can be created multiple times in the same process) if (!class_exists($containerClass, false)) { require $compiledContainerFile; } } return new $containerClass($source, $proxyFactory, $this->wrapperContainer); } /** * Compile the container for optimum performances. * * Be aware that the container is compiled once and never updated! * * Therefore: * * - in production you should clear that directory every time you deploy * - in development you should not compile the container * * @see https://php-di.org/doc/performances.html * * @psalm-template T of CompiledContainer * * @param string $directory Directory in which to put the compiled container. * @param string $containerClass Name of the compiled class. Customize only if necessary. * @param class-string $containerParentClass Name of the compiled container parent class. Customize only if necessary. * @psalm-param class-string $containerParentClass * * @psalm-return self */ public function enableCompilation( string $directory, string $containerClass = 'CompiledContainer', string $containerParentClass = CompiledContainer::class, ) : self { $this->ensureNotLocked(); $this->compileToDirectory = $directory; $this->containerClass = $containerClass; $this->containerParentClass = $containerParentClass; return $this; } /** * Enable or disable the use of autowiring to guess injections. * * Enabled by default. * * @return $this */ public function useAutowiring(bool $bool) : self { $this->ensureNotLocked(); $this->useAutowiring = $bool; return $this; } /** * Enable or disable the use of PHP 8 attributes to configure injections. * * Disabled by default. * * @return $this */ public function useAttributes(bool $bool) : self { $this->ensureNotLocked(); $this->useAttributes = $bool; return $this; } /** * Configure the proxy generation. * * For dev environment, use `writeProxiesToFile(false)` (default configuration) * For production environment, use `writeProxiesToFile(true, 'tmp/proxies')` * * @see https://php-di.org/doc/lazy-injection.html * * @param bool $writeToFile If true, write the proxies to disk to improve performances * @param string|null $proxyDirectory Directory where to write the proxies * @return $this * @throws InvalidArgumentException when writeToFile is set to true and the proxy directory is null */ public function writeProxiesToFile(bool $writeToFile, ?string $proxyDirectory = null) : self { $this->ensureNotLocked(); if ($writeToFile && $proxyDirectory === null) { throw new InvalidArgumentException( 'The proxy directory must be specified if you want to write proxies on disk' ); } $this->proxyDirectory = $writeToFile ? $proxyDirectory : null; return $this; } /** * If PHP-DI's container is wrapped by another container, we can * set this so that PHP-DI will use the wrapper rather than itself for building objects. * * @return $this */ public function wrapContainer(ContainerInterface $otherContainer) : self { $this->ensureNotLocked(); $this->wrapperContainer = $otherContainer; return $this; } /** * Add definitions to the container. * * @param string|array|DefinitionSource ...$definitions Can be an array of definitions, the * name of a file containing definitions * or a DefinitionSource object. * @return $this */ public function addDefinitions(string|array|DefinitionSource ...$definitions) : self { $this->ensureNotLocked(); foreach ($definitions as $definition) { $this->definitionSources[] = $definition; } return $this; } /** * Enables the use of APCu to cache definitions. * * You must have APCu enabled to use it. * * Before using this feature, you should try these steps first: * - enable compilation if not already done (see `enableCompilation()`) * - if you use autowiring or attributes, add all the classes you are using into your configuration so that * PHP-DI knows about them and compiles them * Once this is done, you can try to optimize performances further with APCu. It can also be useful if you use * `Container::make()` instead of `get()` (`make()` calls cannot be compiled so they are not optimized). * * Remember to clear APCu on each deploy else your application will have a stale cache. Do not enable the cache * in development environment: any change you will make to the code will be ignored because of the cache. * * @see https://php-di.org/doc/performances.html * * @param string $cacheNamespace use unique namespace per container when sharing a single APC memory pool to prevent cache collisions * @return $this */ public function enableDefinitionCache(string $cacheNamespace = '') : self { $this->ensureNotLocked(); $this->sourceCache = true; $this->sourceCacheNamespace = $cacheNamespace; return $this; } /** * Are we building a compiled container? */ public function isCompilationEnabled() : bool { return (bool) $this->compileToDirectory; } private function ensureNotLocked() : void { if ($this->locked) { throw new \LogicException('The ContainerBuilder cannot be modified after the container has been built'); } } } */ class ArrayDefinition implements Definition { /** Entry name. */ private string $name = ''; public function __construct( private array $values, ) { } public function getName() : string { return $this->name; } public function setName(string $name) : void { $this->name = $name; } public function getValues() : array { return $this->values; } public function replaceNestedDefinitions(callable $replacer) : void { $this->values = array_map($replacer, $this->values); } public function __toString() : string { $str = '[' . \PHP_EOL; foreach ($this->values as $key => $value) { if (is_string($key)) { $key = "'" . $key . "'"; } $str .= ' ' . $key . ' => '; if ($value instanceof Definition) { $str .= str_replace(\PHP_EOL, \PHP_EOL . ' ', (string) $value); } else { $str .= var_export($value, true); } $str .= ',' . \PHP_EOL; } return $str . ']'; } } */ class ArrayDefinitionExtension extends ArrayDefinition implements ExtendsPreviousDefinition { private ?ArrayDefinition $subDefinition = null; public function getValues() : array { if (! $this->subDefinition) { return parent::getValues(); } return array_merge($this->subDefinition->getValues(), parent::getValues()); } public function setExtendedDefinition(Definition $definition) : void { if (! $definition instanceof ArrayDefinition) { throw new InvalidDefinition(sprintf( 'Definition %s tries to add array entries but the previous definition is not an array', $this->getName() )); } $this->subDefinition = $definition; } } */ class AutowireDefinition extends ObjectDefinition { } */ class DecoratorDefinition extends FactoryDefinition implements Definition, ExtendsPreviousDefinition { private ?Definition $decorated = null; public function setExtendedDefinition(Definition $definition) : void { $this->decorated = $definition; } public function getDecoratedDefinition() : ?Definition { return $this->decorated; } public function replaceNestedDefinitions(callable $replacer) : void { // no nested definitions } public function __toString() : string { return 'Decorate(' . $this->getName() . ')'; } } */ interface Definition extends RequestedEntry, \Stringable { /** * Returns the name of the entry in the container. */ public function getName() : string; /** * Set the name of the entry in the container. */ public function setName(string $name) : void; /** * Apply a callable that replaces the definitions nested in this definition. */ public function replaceNestedDefinitions(callable $replacer) : void; /** * Definitions can be cast to string for debugging information. */ public function __toString() : string; } */ class ObjectDefinitionDumper { /** * Returns the definition as string representation. */ public function dump(ObjectDefinition $definition) : string { $className = $definition->getClassName(); $classExist = class_exists($className) || interface_exists($className); // Class if (! $classExist) { $warning = '#UNKNOWN# '; } else { $class = new \ReflectionClass($className); $warning = $class->isInstantiable() ? '' : '#NOT INSTANTIABLE# '; } $str = sprintf(' class = %s%s', $warning, $className); // Lazy $str .= \PHP_EOL . ' lazy = ' . var_export($definition->isLazy(), true); if ($classExist) { // Constructor $str .= $this->dumpConstructor($className, $definition); // Properties $str .= $this->dumpProperties($definition); // Methods $str .= $this->dumpMethods($className, $definition); } return sprintf('Object (' . \PHP_EOL . '%s' . \PHP_EOL . ')', $str); } /** * @param class-string $className */ private function dumpConstructor(string $className, ObjectDefinition $definition) : string { $str = ''; $constructorInjection = $definition->getConstructorInjection(); if ($constructorInjection !== null) { $parameters = $this->dumpMethodParameters($className, $constructorInjection); $str .= sprintf(\PHP_EOL . ' __construct(' . \PHP_EOL . ' %s' . \PHP_EOL . ' )', $parameters); } return $str; } private function dumpProperties(ObjectDefinition $definition) : string { $str = ''; foreach ($definition->getPropertyInjections() as $propertyInjection) { $value = $propertyInjection->getValue(); $valueStr = $value instanceof Definition ? (string) $value : var_export($value, true); $str .= sprintf(\PHP_EOL . ' $%s = %s', $propertyInjection->getPropertyName(), $valueStr); } return $str; } /** * @param class-string $className */ private function dumpMethods(string $className, ObjectDefinition $definition) : string { $str = ''; foreach ($definition->getMethodInjections() as $methodInjection) { $parameters = $this->dumpMethodParameters($className, $methodInjection); $str .= sprintf(\PHP_EOL . ' %s(' . \PHP_EOL . ' %s' . \PHP_EOL . ' )', $methodInjection->getMethodName(), $parameters); } return $str; } /** * @param class-string $className */ private function dumpMethodParameters(string $className, MethodInjection $methodInjection) : string { $methodReflection = new \ReflectionMethod($className, $methodInjection->getMethodName()); $args = []; $definitionParameters = $methodInjection->getParameters(); foreach ($methodReflection->getParameters() as $index => $parameter) { if (array_key_exists($index, $definitionParameters)) { $value = $definitionParameters[$index]; $valueStr = $value instanceof Definition ? (string) $value : var_export($value, true); $args[] = sprintf('$%s = %s', $parameter->getName(), $valueStr); continue; } // If the parameter is optional and wasn't specified, we take its default value if ($parameter->isOptional()) { try { $value = $parameter->getDefaultValue(); $args[] = sprintf( '$%s = (default value) %s', $parameter->getName(), var_export($value, true) ); continue; } catch (ReflectionException) { // The default value can't be read through Reflection because it is a PHP internal class } } $args[] = sprintf('$%s = #UNDEFINED#', $parameter->getName()); } return implode(\PHP_EOL . ' ', $args); } } */ class EnvironmentVariableDefinition implements Definition { /** Entry name. */ private string $name = ''; /** * @param string $variableName The name of the environment variable * @param bool $isOptional Whether or not the environment variable definition is optional. If true and the environment variable given by $variableName has not been defined, $defaultValue is used. * @param mixed $defaultValue The default value to use if the environment variable is optional and not provided */ public function __construct( private string $variableName, private bool $isOptional = false, private mixed $defaultValue = null, ) { } public function getName() : string { return $this->name; } public function setName(string $name) : void { $this->name = $name; } /** * @return string The name of the environment variable */ public function getVariableName() : string { return $this->variableName; } /** * @return bool Whether or not the environment variable definition is optional */ public function isOptional() : bool { return $this->isOptional; } /** * @return mixed The default value to use if the environment variable is optional and not provided */ public function getDefaultValue() : mixed { return $this->defaultValue; } public function replaceNestedDefinitions(callable $replacer) : void { $this->defaultValue = $replacer($this->defaultValue); } public function __toString() : string { $str = ' variable = ' . $this->variableName . \PHP_EOL . ' optional = ' . ($this->isOptional ? 'yes' : 'no'); if ($this->isOptional) { if ($this->defaultValue instanceof Definition) { $nestedDefinition = (string) $this->defaultValue; $defaultValueStr = str_replace(\PHP_EOL, \PHP_EOL . ' ', $nestedDefinition); } else { $defaultValueStr = var_export($this->defaultValue, true); } $str .= \PHP_EOL . ' default = ' . $defaultValueStr; } return sprintf('Environment variable (' . \PHP_EOL . '%s' . \PHP_EOL . ')', $str); } } */ class InvalidAttribute extends InvalidDefinition { } */ class InvalidDefinition extends \Exception implements ContainerExceptionInterface { public static function create(Definition $definition, string $message, ?\Exception $previous = null) : self { return new self(sprintf( '%s' . \PHP_EOL . 'Full definition:' . \PHP_EOL . '%s', $message, (string) $definition ), 0, $previous); } } */ interface ExtendsPreviousDefinition extends Definition { public function setExtendedDefinition(Definition $definition) : void; } */ class FactoryDefinition implements Definition { /** * Entry name. */ private string $name; /** * Callable that returns the value. * @var callable */ private $factory; /** * Factory parameters. * @var mixed[] */ private array $parameters; /** * @param string $name Entry name * @param callable|array|string $factory Callable that returns the value associated to the entry name. * @param array $parameters Parameters to be passed to the callable */ public function __construct(string $name, callable|array|string $factory, array $parameters = []) { $this->name = $name; $this->factory = $factory; $this->parameters = $parameters; } public function getName() : string { return $this->name; } public function setName(string $name) : void { $this->name = $name; } /** * @return callable|array|string Callable that returns the value associated to the entry name. */ public function getCallable() : callable|array|string { return $this->factory; } /** * @return array Array containing the parameters to be passed to the callable, indexed by name. */ public function getParameters() : array { return $this->parameters; } public function replaceNestedDefinitions(callable $replacer) : void { $this->parameters = array_map($replacer, $this->parameters); } public function __toString() : string { return 'Factory'; } } */ class AutowireDefinitionHelper extends CreateDefinitionHelper { public const DEFINITION_CLASS = AutowireDefinition::class; /** * Defines a value for a specific argument of the constructor. * * This method is usually used together with attributes or autowiring, when a parameter * is not (or cannot be) type-hinted. Using this method instead of constructor() allows to * avoid defining all the parameters (letting them being resolved using attributes or autowiring) * and only define one. * * @param string|int $parameter Parameter name of position for which the value will be given. * @param mixed $value Value to give to this parameter. * * @return $this */ public function constructorParameter(string|int $parameter, mixed $value) : self { $this->constructor[$parameter] = $value; return $this; } /** * Defines a method to call and a value for a specific argument. * * This method is usually used together with attributes or autowiring, when a parameter * is not (or cannot be) type-hinted. Using this method instead of method() allows to * avoid defining all the parameters (letting them being resolved using attributes or * autowiring) and only define one. * * If multiple calls to the method have been configured already (e.g. in a previous definition) * then this method only overrides the parameter for the *first* call. * * @param string $method Name of the method to call. * @param string|int $parameter Parameter name of position for which the value will be given. * @param mixed $value Value to give to this parameter. * * @return $this */ public function methodParameter(string $method, string|int $parameter, mixed $value) : self { // Special case for the constructor if ($method === '__construct') { $this->constructor[$parameter] = $value; return $this; } if (! isset($this->methods[$method])) { $this->methods[$method] = [0 => []]; } $this->methods[$method][0][$parameter] = $value; return $this; } } */ class CreateDefinitionHelper implements DefinitionHelper { private const DEFINITION_CLASS = ObjectDefinition::class; private ?string $className; private ?bool $lazy = null; /** * Array of constructor parameters. */ protected array $constructor = []; /** * Array of properties and their value. */ private array $properties = []; /** * Array of methods and their parameters. */ protected array $methods = []; /** * Helper for defining an object. * * @param string|null $className Class name of the object. * If null, the name of the entry (in the container) will be used as class name. */ public function __construct(?string $className = null) { $this->className = $className; } /** * Define the entry as lazy. * * A lazy entry is created only when it is used, a proxy is injected instead. * * @return $this */ public function lazy() : self { $this->lazy = true; return $this; } /** * Defines the arguments to use to call the constructor. * * This method takes a variable number of arguments, example: * ->constructor($param1, $param2, $param3) * * @param mixed ...$parameters Parameters to use for calling the constructor of the class. * * @return $this */ public function constructor(mixed ...$parameters) : self { $this->constructor = $parameters; return $this; } /** * Defines a value to inject in a property of the object. * * @param string $property Entry in which to inject the value. * @param mixed $value Value to inject in the property. * * @return $this */ public function property(string $property, mixed $value) : self { $this->properties[$property] = $value; return $this; } /** * Defines a method to call and the arguments to use. * * This method takes a variable number of arguments after the method name, example: * * ->method('myMethod', $param1, $param2) * * Can be used multiple times to declare multiple calls. * * @param string $method Name of the method to call. * @param mixed ...$parameters Parameters to use for calling the method. * * @return $this */ public function method(string $method, mixed ...$parameters) : self { if (! isset($this->methods[$method])) { $this->methods[$method] = []; } $this->methods[$method][] = $parameters; return $this; } public function getDefinition(string $entryName) : ObjectDefinition { $class = $this::DEFINITION_CLASS; /** @var ObjectDefinition $definition */ $definition = new $class($entryName, $this->className); if ($this->lazy !== null) { $definition->setLazy($this->lazy); } if (! empty($this->constructor)) { $parameters = $this->fixParameters($definition, '__construct', $this->constructor); $constructorInjection = MethodInjection::constructor($parameters); $definition->setConstructorInjection($constructorInjection); } if (! empty($this->properties)) { foreach ($this->properties as $property => $value) { $definition->addPropertyInjection( new PropertyInjection($property, $value) ); } } if (! empty($this->methods)) { foreach ($this->methods as $method => $calls) { foreach ($calls as $parameters) { $parameters = $this->fixParameters($definition, $method, $parameters); $methodInjection = new MethodInjection($method, $parameters); $definition->addMethodInjection($methodInjection); } } } return $definition; } /** * Fixes parameters indexed by the parameter name -> reindex by position. * * This is necessary so that merging definitions between sources is possible. * * @throws InvalidDefinition */ private function fixParameters(ObjectDefinition $definition, string $method, array $parameters) : array { $fixedParameters = []; foreach ($parameters as $index => $parameter) { // Parameter indexed by the parameter name, we reindex it with its position if (is_string($index)) { $callable = [$definition->getClassName(), $method]; try { $reflectionParameter = new \ReflectionParameter($callable, $index); } catch (\ReflectionException $e) { throw InvalidDefinition::create($definition, sprintf("Parameter with name '%s' could not be found. %s.", $index, $e->getMessage())); } $index = $reflectionParameter->getPosition(); } $fixedParameters[$index] = $parameter; } return $fixedParameters; } } */ interface DefinitionHelper { /** * @param string $entryName Container entry name */ public function getDefinition(string $entryName) : Definition; } */ class FactoryDefinitionHelper implements DefinitionHelper { /** * @var callable */ private $factory; private bool $decorate; private array $parameters = []; /** * @param bool $decorate Is the factory decorating a previous definition? */ public function __construct(callable|array|string $factory, bool $decorate = false) { $this->factory = $factory; $this->decorate = $decorate; } public function getDefinition(string $entryName) : FactoryDefinition { if ($this->decorate) { return new DecoratorDefinition($entryName, $this->factory, $this->parameters); } return new FactoryDefinition($entryName, $this->factory, $this->parameters); } /** * Defines arguments to pass to the factory. * * Because factory methods do not yet support attributes or autowiring, this method * should be used to define all parameters except the ContainerInterface and RequestedEntry. * * Multiple calls can be made to the method to override individual values. * * @param string $parameter Name or index of the parameter for which the value will be given. * @param mixed $value Value to give to this parameter. * * @return $this */ public function parameter(string $parameter, mixed $value) : self { $this->parameters[$parameter] = $value; return $this; } } */ class InstanceDefinition implements Definition { /** * @param object $instance Instance on which to inject dependencies. */ public function __construct( private object $instance, private ObjectDefinition $objectDefinition, ) { } public function getName() : string { // Name are superfluous for instance definitions return ''; } public function setName(string $name) : void { // Name are superfluous for instance definitions } public function getInstance() : object { return $this->instance; } public function getObjectDefinition() : ObjectDefinition { return $this->objectDefinition; } public function replaceNestedDefinitions(callable $replacer) : void { $this->objectDefinition->replaceNestedDefinitions($replacer); } public function __toString() : string { return 'Instance'; } } */ class ObjectDefinition implements Definition { /** * Entry name (most of the time, same as $classname). */ private string $name; /** * Class name (if null, then the class name is $name). */ protected ?string $className = null; protected ?MethodInjection $constructorInjection = null; protected array $propertyInjections = []; /** * Method calls. * @var MethodInjection[][] */ protected array $methodInjections = []; protected ?bool $lazy = null; /** * Store if the class exists. Storing it (in cache) avoids recomputing this. */ private bool $classExists; /** * Store if the class is instantiable. Storing it (in cache) avoids recomputing this. */ private bool $isInstantiable; /** * @param string $name Entry name */ public function __construct(string $name, ?string $className = null) { $this->name = $name; $this->setClassName($className); } public function getName() : string { return $this->name; } public function setName(string $name) : void { $this->name = $name; } public function setClassName(?string $className) : void { $this->className = $className; $this->updateCache(); } public function getClassName() : string { return $this->className ?? $this->name; } public function getConstructorInjection() : ?MethodInjection { return $this->constructorInjection; } public function setConstructorInjection(MethodInjection $constructorInjection) : void { $this->constructorInjection = $constructorInjection; } public function completeConstructorInjection(MethodInjection $injection) : void { if ($this->constructorInjection !== null) { // Merge $this->constructorInjection->merge($injection); } else { // Set $this->constructorInjection = $injection; } } /** * @return PropertyInjection[] Property injections */ public function getPropertyInjections() : array { return $this->propertyInjections; } public function addPropertyInjection(PropertyInjection $propertyInjection) : void { $className = $propertyInjection->getClassName(); if ($className) { // Index with the class name to avoid collisions between parent and // child private properties with the same name $key = $className . '::' . $propertyInjection->getPropertyName(); } else { $key = $propertyInjection->getPropertyName(); } $this->propertyInjections[$key] = $propertyInjection; } /** * @return MethodInjection[] Method injections */ public function getMethodInjections() : array { // Return array leafs $injections = []; array_walk_recursive($this->methodInjections, function ($injection) use (&$injections) { $injections[] = $injection; }); return $injections; } public function addMethodInjection(MethodInjection $methodInjection) : void { $method = $methodInjection->getMethodName(); if (! isset($this->methodInjections[$method])) { $this->methodInjections[$method] = []; } $this->methodInjections[$method][] = $methodInjection; } public function completeFirstMethodInjection(MethodInjection $injection) : void { $method = $injection->getMethodName(); if (isset($this->methodInjections[$method][0])) { // Merge $this->methodInjections[$method][0]->merge($injection); } else { // Set $this->addMethodInjection($injection); } } public function setLazy(?bool $lazy = null) : void { $this->lazy = $lazy; } public function isLazy() : bool { if ($this->lazy !== null) { return $this->lazy; } // Default value return false; } public function classExists() : bool { return $this->classExists; } public function isInstantiable() : bool { return $this->isInstantiable; } public function replaceNestedDefinitions(callable $replacer) : void { array_walk($this->propertyInjections, function (PropertyInjection $propertyInjection) use ($replacer) { $propertyInjection->replaceNestedDefinition($replacer); }); $this->constructorInjection?->replaceNestedDefinitions($replacer); array_walk($this->methodInjections, function ($injectionArray) use ($replacer) { array_walk($injectionArray, function (MethodInjection $methodInjection) use ($replacer) { $methodInjection->replaceNestedDefinitions($replacer); }); }); } /** * Replaces all the wildcards in the string with the given replacements. * * @param string[] $replacements */ public function replaceWildcards(array $replacements) : void { $className = $this->getClassName(); foreach ($replacements as $replacement) { $pos = strpos($className, DefinitionArray::WILDCARD); if ($pos !== false) { $className = substr_replace($className, $replacement, $pos, 1); } } $this->setClassName($className); } public function __toString() : string { return (new ObjectDefinitionDumper)->dump($this); } private function updateCache() : void { $className = $this->getClassName(); $this->classExists = class_exists($className) || interface_exists($className); if (! $this->classExists) { $this->isInstantiable = false; return; } /** @var class-string $className */ $class = new ReflectionClass($className); $this->isInstantiable = $class->isInstantiable(); } } */ class MethodInjection implements Definition { /** * @param mixed[] $parameters */ public function __construct( private string $methodName, private array $parameters = [], ) { } public static function constructor(array $parameters = []) : self { return new self('__construct', $parameters); } public function getMethodName() : string { return $this->methodName; } /** * @return mixed[] */ public function getParameters() : array { return $this->parameters; } /** * Replace the parameters of the definition by a new array of parameters. */ public function replaceParameters(array $parameters) : void { $this->parameters = $parameters; } public function merge(self $definition) : void { // In case of conflicts, the current definition prevails. $this->parameters += $definition->parameters; } public function getName() : string { return ''; } public function setName(string $name) : void { // The name does not matter for method injections } public function replaceNestedDefinitions(callable $replacer) : void { $this->parameters = array_map($replacer, $this->parameters); } public function __toString() : string { return sprintf('method(%s)', $this->methodName); } } */ class PropertyInjection { private string $propertyName; /** * Value that should be injected in the property. */ private mixed $value; /** * Use for injecting in properties of parent classes: the class name * must be the name of the parent class because private properties * can be attached to the parent classes, not the one we are resolving. */ private ?string $className; /** * @param string $propertyName Property name * @param mixed $value Value that should be injected in the property */ public function __construct(string $propertyName, mixed $value, ?string $className = null) { $this->propertyName = $propertyName; $this->value = $value; $this->className = $className; } public function getPropertyName() : string { return $this->propertyName; } /** * @return mixed Value that should be injected in the property */ public function getValue() : mixed { return $this->value; } public function getClassName() : ?string { return $this->className; } public function replaceNestedDefinition(callable $replacer) : void { $this->value = $replacer($this->value); } } */ class Reference implements Definition, SelfResolvingDefinition { /** Entry name. */ private string $name = ''; /** * @param string $targetEntryName Name of the target entry */ public function __construct( private string $targetEntryName, ) { } public function getName() : string { return $this->name; } public function setName(string $name) : void { $this->name = $name; } public function getTargetEntryName() : string { return $this->targetEntryName; } public function resolve(ContainerInterface $container) : mixed { return $container->get($this->getTargetEntryName()); } public function isResolvable(ContainerInterface $container) : bool { return $container->has($this->getTargetEntryName()); } public function replaceNestedDefinitions(callable $replacer) : void { // no nested definitions } public function __toString() : string { return sprintf( 'get(%s)', $this->targetEntryName ); } } * * @since 5.0 * @author Matthieu Napoli */ class ArrayResolver implements DefinitionResolver { /** * @param DefinitionResolver $definitionResolver Used to resolve nested definitions. */ public function __construct( private DefinitionResolver $definitionResolver, ) { } /** * {@inheritDoc} * * Resolve an array definition to a value. * * An array definition can contain simple values or references to other entries. * * @param ArrayDefinition $definition */ public function resolve(Definition $definition, array $parameters = []) : array { $values = $definition->getValues(); // Resolve nested definitions array_walk_recursive($values, function (& $value, $key) use ($definition) { if ($value instanceof Definition) { $value = $this->resolveDefinition($value, $definition, $key); } }); return $values; } public function isResolvable(Definition $definition, array $parameters = []) : bool { return true; } /** * @throws DependencyException */ private function resolveDefinition(Definition $value, ArrayDefinition $definition, int|string $key) : mixed { try { return $this->definitionResolver->resolve($value); } catch (DependencyException $e) { throw $e; } catch (Exception $e) { throw new DependencyException(sprintf( 'Error while resolving %s[%s]. %s', $definition->getName(), $key, $e->getMessage() ), 0, $e); } } } * * @since 5.0 * @author Matthieu Napoli */ class DecoratorResolver implements DefinitionResolver { /** * The resolver needs a container. This container will be passed to the factory as a parameter * so that the factory can access other entries of the container. * * @param DefinitionResolver $definitionResolver Used to resolve nested definitions. */ public function __construct( private ContainerInterface $container, private DefinitionResolver $definitionResolver, ) { } /** * Resolve a decorator definition to a value. * * This will call the callable of the definition and pass it the decorated entry. * * @param DecoratorDefinition $definition */ public function resolve(Definition $definition, array $parameters = []) : mixed { $callable = $definition->getCallable(); if (! is_callable($callable)) { throw new InvalidDefinition(sprintf( 'The decorator "%s" is not callable', $definition->getName() )); } $decoratedDefinition = $definition->getDecoratedDefinition(); if (! $decoratedDefinition instanceof Definition) { if (! $definition->getName()) { throw new InvalidDefinition('Decorators cannot be nested in another definition'); } throw new InvalidDefinition(sprintf( 'Entry "%s" decorates nothing: no previous definition with the same name was found', $definition->getName() )); } $decorated = $this->definitionResolver->resolve($decoratedDefinition, $parameters); return $callable($decorated, $this->container); } public function isResolvable(Definition $definition, array $parameters = []) : bool { return true; } } * * @template T of Definition */ interface DefinitionResolver { /** * Resolve a definition to a value. * * @param Definition $definition Object that defines how the value should be obtained. * @psalm-param T $definition * @param array $parameters Optional parameters to use to build the entry. * @return mixed Value obtained from the definition. * * @throws InvalidDefinition If the definition cannot be resolved. * @throws DependencyException */ public function resolve(Definition $definition, array $parameters = []) : mixed; /** * Check if a definition can be resolved. * * @param Definition $definition Object that defines how the value should be obtained. * @psalm-param T $definition * @param array $parameters Optional parameters to use to build the entry. */ public function isResolvable(Definition $definition, array $parameters = []) : bool; } * * @author James Harris */ class EnvironmentVariableResolver implements DefinitionResolver { /** @var callable */ private $variableReader; public function __construct( private DefinitionResolver $definitionResolver, $variableReader = null, ) { $this->variableReader = $variableReader ?? [$this, 'getEnvVariable']; } /** * Resolve an environment variable definition to a value. * * @param EnvironmentVariableDefinition $definition */ public function resolve(Definition $definition, array $parameters = []) : mixed { $value = call_user_func($this->variableReader, $definition->getVariableName()); if (false !== $value) { return $value; } if (!$definition->isOptional()) { throw new InvalidDefinition(sprintf( "The environment variable '%s' has not been defined", $definition->getVariableName() )); } $value = $definition->getDefaultValue(); // Nested definition if ($value instanceof Definition) { return $this->definitionResolver->resolve($value); } return $value; } public function isResolvable(Definition $definition, array $parameters = []) : bool { return true; } protected function getEnvVariable(string $variableName) { return $_ENV[$variableName] ?? $_SERVER[$variableName] ?? getenv($variableName); } } * * @since 4.0 * @author Matthieu Napoli */ class FactoryResolver implements DefinitionResolver { private ?Invoker $invoker = null; /** * The resolver needs a container. This container will be passed to the factory as a parameter * so that the factory can access other entries of the container. */ public function __construct( private ContainerInterface $container, private DefinitionResolver $resolver, ) { } /** * Resolve a factory definition to a value. * * This will call the callable of the definition. * * @param FactoryDefinition $definition */ public function resolve(Definition $definition, array $parameters = []) : mixed { if (! $this->invoker) { $parameterResolver = new ResolverChain([ new AssociativeArrayResolver, new FactoryParameterResolver($this->container), new NumericArrayResolver, new DefaultValueResolver, ]); $this->invoker = new Invoker($parameterResolver, $this->container); } $callable = $definition->getCallable(); try { $providedParams = [$this->container, $definition]; $extraParams = $this->resolveExtraParams($definition->getParameters()); $providedParams = array_merge($providedParams, $extraParams, $parameters); return $this->invoker->call($callable, $providedParams); } catch (NotCallableException $e) { // Custom error message to help debugging if (is_string($callable) && class_exists($callable) && method_exists($callable, '__invoke')) { throw new InvalidDefinition(sprintf( 'Entry "%s" cannot be resolved: factory %s. Invokable classes cannot be automatically resolved if autowiring is disabled on the container, you need to enable autowiring or define the entry manually.', $definition->getName(), $e->getMessage() )); } throw new InvalidDefinition(sprintf( 'Entry "%s" cannot be resolved: factory %s', $definition->getName(), $e->getMessage() )); } catch (NotEnoughParametersException $e) { throw new InvalidDefinition(sprintf( 'Entry "%s" cannot be resolved: %s', $definition->getName(), $e->getMessage() )); } } public function isResolvable(Definition $definition, array $parameters = []) : bool { return true; } private function resolveExtraParams(array $params) : array { $resolved = []; foreach ($params as $key => $value) { // Nested definitions if ($value instanceof Definition) { $value = $this->resolver->resolve($value); } $resolved[$key] = $value; } return $resolved; } } * * @since 5.0 * @author Matthieu Napoli */ class InstanceInjector extends ObjectCreator implements DefinitionResolver { /** * Injects dependencies on an existing instance. * * @param InstanceDefinition $definition * @psalm-suppress ImplementedParamTypeMismatch */ public function resolve(Definition $definition, array $parameters = []) : ?object { /** @psalm-suppress InvalidCatch */ try { $this->injectMethodsAndProperties($definition->getInstance(), $definition->getObjectDefinition()); } catch (NotFoundExceptionInterface $e) { $message = sprintf( 'Error while injecting dependencies into %s: %s', get_class($definition->getInstance()), $e->getMessage() ); throw new DependencyException($message, 0, $e); } return $definition; } public function isResolvable(Definition $definition, array $parameters = []) : bool { return true; } } * * @since 4.0 * @author Matthieu Napoli */ class ObjectCreator implements DefinitionResolver { private ParameterResolver $parameterResolver; /** * @param DefinitionResolver $definitionResolver Used to resolve nested definitions. * @param ProxyFactoryInterface $proxyFactory Used to create proxies for lazy injections. */ public function __construct( private DefinitionResolver $definitionResolver, private ProxyFactoryInterface $proxyFactory, ) { $this->parameterResolver = new ParameterResolver($definitionResolver); } /** * Resolve a class definition to a value. * * This will create a new instance of the class using the injections points defined. * * @param ObjectDefinition $definition */ public function resolve(Definition $definition, array $parameters = []) : ?object { // Lazy? if ($definition->isLazy()) { return $this->createProxy($definition, $parameters); } return $this->createInstance($definition, $parameters); } /** * The definition is not resolvable if the class is not instantiable (interface or abstract) * or if the class doesn't exist. * * @param ObjectDefinition $definition */ public function isResolvable(Definition $definition, array $parameters = []) : bool { return $definition->isInstantiable(); } /** * Returns a proxy instance. */ private function createProxy(ObjectDefinition $definition, array $parameters) : object { /** @var class-string $className */ $className = $definition->getClassName(); return $this->proxyFactory->createProxy( $className, function () use ($definition, $parameters) { return $this->createInstance($definition, $parameters); } ); } /** * Creates an instance of the class and injects dependencies.. * * @param array $parameters Optional parameters to use to create the instance. * * @throws DependencyException * @throws InvalidDefinition */ private function createInstance(ObjectDefinition $definition, array $parameters) : object { // Check that the class is instantiable if (! $definition->isInstantiable()) { // Check that the class exists if (! $definition->classExists()) { throw InvalidDefinition::create($definition, sprintf( 'Entry "%s" cannot be resolved: the class doesn\'t exist', $definition->getName() )); } throw InvalidDefinition::create($definition, sprintf( 'Entry "%s" cannot be resolved: the class is not instantiable', $definition->getName() )); } /** @psalm-var class-string $classname */ $classname = $definition->getClassName(); $classReflection = new ReflectionClass($classname); $constructorInjection = $definition->getConstructorInjection(); /** @psalm-suppress InvalidCatch */ try { $args = $this->parameterResolver->resolveParameters( $constructorInjection, $classReflection->getConstructor(), $parameters ); $object = new $classname(...$args); $this->injectMethodsAndProperties($object, $definition); } catch (NotFoundExceptionInterface $e) { throw new DependencyException(sprintf( 'Error while injecting dependencies into %s: %s', $classReflection->getName(), $e->getMessage() ), 0, $e); } catch (InvalidDefinition $e) { throw InvalidDefinition::create($definition, sprintf( 'Entry "%s" cannot be resolved: %s', $definition->getName(), $e->getMessage() )); } return $object; } protected function injectMethodsAndProperties(object $object, ObjectDefinition $objectDefinition) : void { // Property injections foreach ($objectDefinition->getPropertyInjections() as $propertyInjection) { $this->injectProperty($object, $propertyInjection); } // Method injections foreach ($objectDefinition->getMethodInjections() as $methodInjection) { $methodReflection = new \ReflectionMethod($object, $methodInjection->getMethodName()); $args = $this->parameterResolver->resolveParameters($methodInjection, $methodReflection); $methodReflection->invokeArgs($object, $args); } } /** * Inject dependencies into properties. * * @param object $object Object to inject dependencies into * @param PropertyInjection $propertyInjection Property injection definition * * @throws DependencyException */ private function injectProperty(object $object, PropertyInjection $propertyInjection) : void { $propertyName = $propertyInjection->getPropertyName(); $value = $propertyInjection->getValue(); if ($value instanceof Definition) { try { $value = $this->definitionResolver->resolve($value); } catch (DependencyException $e) { throw $e; } catch (Exception $e) { throw new DependencyException(sprintf( 'Error while injecting in %s::%s. %s', $object::class, $propertyName, $e->getMessage() ), 0, $e); } } self::setPrivatePropertyValue($propertyInjection->getClassName(), $object, $propertyName, $value); } public static function setPrivatePropertyValue(?string $className, $object, string $propertyName, mixed $propertyValue) : void { $className = $className ?: $object::class; $property = new ReflectionProperty($className, $propertyName); if (! $property->isPublic() && \PHP_VERSION_ID < 80100) { $property->setAccessible(true); } $property->setValue($object, $propertyValue); } } */ class ParameterResolver { /** * @param DefinitionResolver $definitionResolver Will be used to resolve nested definitions. */ public function __construct( private DefinitionResolver $definitionResolver, ) { } /** * @return array Parameters to use to call the function. * @throws InvalidDefinition A parameter has no value defined or guessable. */ public function resolveParameters( ?MethodInjection $definition = null, ?ReflectionMethod $method = null, array $parameters = [], ) : array { $args = []; if (! $method) { return $args; } $definitionParameters = $definition ? $definition->getParameters() : []; foreach ($method->getParameters() as $index => $parameter) { if (array_key_exists($parameter->getName(), $parameters)) { // Look in the $parameters array $value = &$parameters[$parameter->getName()]; } elseif (array_key_exists($index, $definitionParameters)) { // Look in the definition $value = &$definitionParameters[$index]; } else { // If the parameter is optional and wasn't specified, we take its default value if ($parameter->isDefaultValueAvailable() || $parameter->isOptional()) { $args[] = $this->getParameterDefaultValue($parameter, $method); continue; } throw new InvalidDefinition(sprintf( 'Parameter $%s of %s has no value defined or guessable', $parameter->getName(), $this->getFunctionName($method) )); } // Nested definitions if ($value instanceof Definition) { // If the container cannot produce the entry, we can use the default parameter value if ($parameter->isOptional() && ! $this->definitionResolver->isResolvable($value)) { $value = $this->getParameterDefaultValue($parameter, $method); } else { $value = $this->definitionResolver->resolve($value); } } $args[] = &$value; } return $args; } /** * Returns the default value of a function parameter. * * @throws InvalidDefinition Can't get default values from PHP internal classes and functions */ private function getParameterDefaultValue(ReflectionParameter $parameter, ReflectionMethod $function) : mixed { try { return $parameter->getDefaultValue(); } catch (\ReflectionException) { throw new InvalidDefinition(sprintf( 'The parameter "%s" of %s has no type defined or guessable. It has a default value, ' . 'but the default value can\'t be read through Reflection because it is a PHP internal class.', $parameter->getName(), $this->getFunctionName($function) )); } } private function getFunctionName(ReflectionMethod $method) : string { return $method->getName() . '()'; } } * * @psalm-suppress MissingTemplateParam */ class ResolverDispatcher implements DefinitionResolver { private ?ArrayResolver $arrayResolver = null; private ?FactoryResolver $factoryResolver = null; private ?DecoratorResolver $decoratorResolver = null; private ?ObjectCreator $objectResolver = null; private ?InstanceInjector $instanceResolver = null; private ?EnvironmentVariableResolver $envVariableResolver = null; public function __construct( private ContainerInterface $container, private ProxyFactoryInterface $proxyFactory, ) { } /** * Resolve a definition to a value. * * @param Definition $definition Object that defines how the value should be obtained. * @param array $parameters Optional parameters to use to build the entry. * * @return mixed Value obtained from the definition. * @throws InvalidDefinition If the definition cannot be resolved. */ public function resolve(Definition $definition, array $parameters = []) : mixed { // Special case, tested early for speed if ($definition instanceof SelfResolvingDefinition) { return $definition->resolve($this->container); } $definitionResolver = $this->getDefinitionResolver($definition); return $definitionResolver->resolve($definition, $parameters); } public function isResolvable(Definition $definition, array $parameters = []) : bool { // Special case, tested early for speed if ($definition instanceof SelfResolvingDefinition) { return $definition->isResolvable($this->container); } $definitionResolver = $this->getDefinitionResolver($definition); return $definitionResolver->isResolvable($definition, $parameters); } /** * Returns a resolver capable of handling the given definition. * * @throws \RuntimeException No definition resolver was found for this type of definition. */ private function getDefinitionResolver(Definition $definition) : DefinitionResolver { switch (true) { case $definition instanceof ObjectDefinition: if (! $this->objectResolver) { $this->objectResolver = new ObjectCreator($this, $this->proxyFactory); } return $this->objectResolver; case $definition instanceof DecoratorDefinition: if (! $this->decoratorResolver) { $this->decoratorResolver = new DecoratorResolver($this->container, $this); } return $this->decoratorResolver; case $definition instanceof FactoryDefinition: if (! $this->factoryResolver) { $this->factoryResolver = new FactoryResolver($this->container, $this); } return $this->factoryResolver; case $definition instanceof ArrayDefinition: if (! $this->arrayResolver) { $this->arrayResolver = new ArrayResolver($this); } return $this->arrayResolver; case $definition instanceof EnvironmentVariableDefinition: if (! $this->envVariableResolver) { $this->envVariableResolver = new EnvironmentVariableResolver($this); } return $this->envVariableResolver; case $definition instanceof InstanceDefinition: if (! $this->instanceResolver) { $this->instanceResolver = new InstanceInjector($this, $this->proxyFactory); } return $this->instanceResolver; default: throw new \RuntimeException('No definition resolver was configured for definition of type ' . $definition::class); } } } */ interface SelfResolvingDefinition { /** * Resolve the definition and return the resulting value. */ public function resolve(ContainerInterface $container) : mixed; /** * Check if a definition can be resolved. */ public function isResolvable(ContainerInterface $container) : bool; } */ class AttributeBasedAutowiring implements DefinitionSource, Autowiring { /** * @throws InvalidAttribute */ public function autowire(string $name, ?ObjectDefinition $definition = null) : ?ObjectDefinition { $className = $definition ? $definition->getClassName() : $name; if (!class_exists($className) && !interface_exists($className)) { return $definition; } $definition = $definition ?: new ObjectDefinition($name); $class = new ReflectionClass($className); $this->readInjectableAttribute($class, $definition); // Browse the class properties looking for annotated properties $this->readProperties($class, $definition); // Browse the object's methods looking for annotated methods $this->readMethods($class, $definition); return $definition; } /** * @throws InvalidAttribute * @throws InvalidArgumentException The class doesn't exist */ public function getDefinition(string $name) : ?ObjectDefinition { return $this->autowire($name); } /** * Autowiring cannot guess all existing definitions. */ public function getDefinitions() : array { return []; } /** * Browse the class properties looking for annotated properties. */ private function readProperties(ReflectionClass $class, ObjectDefinition $definition) : void { foreach ($class->getProperties() as $property) { $this->readProperty($property, $definition); } // Read also the *private* properties of the parent classes /** @noinspection PhpAssignmentInConditionInspection */ while ($class = $class->getParentClass()) { foreach ($class->getProperties(ReflectionProperty::IS_PRIVATE) as $property) { $this->readProperty($property, $definition, $class->getName()); } } } /** * @throws InvalidAttribute */ private function readProperty(ReflectionProperty $property, ObjectDefinition $definition, ?string $classname = null) : void { if ($property->isStatic() || $property->isPromoted()) { return; } // Look for #[Inject] attribute try { $attribute = $property->getAttributes(Inject::class)[0] ?? null; if (! $attribute) { return; } /** @var Inject $inject */ $inject = $attribute->newInstance(); } catch (Throwable $e) { throw new InvalidAttribute(sprintf( '#[Inject] annotation on property %s::%s is malformed. %s', $property->getDeclaringClass()->getName(), $property->getName(), $e->getMessage() ), 0, $e); } // Try to #[Inject("name")] or look for the property type $entryName = $inject->getName(); // Try using typed properties $propertyType = $property->getType(); if ($entryName === null && $propertyType instanceof ReflectionNamedType) { if (! class_exists($propertyType->getName()) && ! interface_exists($propertyType->getName())) { throw new InvalidAttribute(sprintf( '#[Inject] found on property %s::%s but unable to guess what to inject, the type of the property does not look like a valid class or interface name', $property->getDeclaringClass()->getName(), $property->getName() )); } $entryName = $propertyType->getName(); } if ($entryName === null) { throw new InvalidAttribute(sprintf( '#[Inject] found on property %s::%s but unable to guess what to inject, please add a type to the property', $property->getDeclaringClass()->getName(), $property->getName() )); } $definition->addPropertyInjection( new PropertyInjection($property->getName(), new Reference($entryName), $classname) ); } /** * Browse the object's methods looking for annotated methods. */ private function readMethods(ReflectionClass $class, ObjectDefinition $objectDefinition) : void { // This will look in all the methods, including those of the parent classes foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { if ($method->isStatic()) { continue; } $methodInjection = $this->getMethodInjection($method); if (! $methodInjection) { continue; } if ($method->isConstructor()) { $objectDefinition->completeConstructorInjection($methodInjection); } else { $objectDefinition->completeFirstMethodInjection($methodInjection); } } } private function getMethodInjection(ReflectionMethod $method) : ?MethodInjection { // Look for #[Inject] attribute $attribute = $method->getAttributes(Inject::class)[0] ?? null; if ($attribute) { /** @var Inject $inject */ $inject = $attribute->newInstance(); $annotationParameters = $inject->getParameters(); } elseif ($method->isConstructor()) { // #[Inject] on constructor is implicit, we continue $annotationParameters = []; } else { return null; } $parameters = []; foreach ($method->getParameters() as $index => $parameter) { $entryName = $this->getMethodParameter($index, $parameter, $annotationParameters); if ($entryName !== null) { $parameters[$index] = new Reference($entryName); } } if ($method->isConstructor()) { return MethodInjection::constructor($parameters); } return new MethodInjection($method->getName(), $parameters); } /** * @return string|null Entry name or null if not found. */ private function getMethodParameter(int $parameterIndex, ReflectionParameter $parameter, array $annotationParameters) : ?string { // Let's check if this parameter has an #[Inject] attribute $attribute = $parameter->getAttributes(Inject::class)[0] ?? null; if ($attribute) { /** @var Inject $inject */ $inject = $attribute->newInstance(); return $inject->getName(); } // #[Inject] has definition for this parameter (by index, or by name) if (isset($annotationParameters[$parameterIndex])) { return $annotationParameters[$parameterIndex]; } if (isset($annotationParameters[$parameter->getName()])) { return $annotationParameters[$parameter->getName()]; } // Skip optional parameters if not explicitly defined if ($parameter->isOptional()) { return null; } // Look for the property type $parameterType = $parameter->getType(); if ($parameterType instanceof ReflectionNamedType && !$parameterType->isBuiltin()) { return $parameterType->getName(); } return null; } /** * @throws InvalidAttribute */ private function readInjectableAttribute(ReflectionClass $class, ObjectDefinition $definition) : void { try { $attribute = $class->getAttributes(Injectable::class)[0] ?? null; if (! $attribute) { return; } $attribute = $attribute->newInstance(); } catch (Throwable $e) { throw new InvalidAttribute(sprintf( 'Error while reading #[Injectable] on %s: %s', $class->getName(), $e->getMessage() ), 0, $e); } if ($attribute->isLazy() !== null) { $definition->setLazy($attribute->isLazy()); } } } */ interface Autowiring { /** * Autowire the given definition. * * @throws InvalidDefinition An invalid definition was found. */ public function autowire(string $name, ?ObjectDefinition $definition = null) : ?ObjectDefinition; } */ class DefinitionArray implements DefinitionSource, MutableDefinitionSource { public const WILDCARD = '*'; /** * Matches anything except "\". */ private const WILDCARD_PATTERN = '([^\\\\]+)'; /** DI definitions in a PHP array. */ private array $definitions; /** Cache of wildcard definitions. */ private ?array $wildcardDefinitions = null; private DefinitionNormalizer $normalizer; public function __construct(array $definitions = [], ?Autowiring $autowiring = null) { if (isset($definitions[0])) { throw new \Exception('The PHP-DI definition is not indexed by an entry name in the definition array'); } $this->definitions = $definitions; $this->normalizer = new DefinitionNormalizer($autowiring ?: new NoAutowiring); } /** * @param array $definitions DI definitions in a PHP array indexed by the definition name. */ public function addDefinitions(array $definitions) : void { if (isset($definitions[0])) { throw new \Exception('The PHP-DI definition is not indexed by an entry name in the definition array'); } // The newly added data prevails // "for keys that exist in both arrays, the elements from the left-hand array will be used" $this->definitions = $definitions + $this->definitions; // Clear cache $this->wildcardDefinitions = null; } public function addDefinition(Definition $definition) : void { $this->definitions[$definition->getName()] = $definition; // Clear cache $this->wildcardDefinitions = null; } public function getDefinition(string $name) : ?Definition { // Look for the definition by name if (array_key_exists($name, $this->definitions)) { $definition = $this->definitions[$name]; return $this->normalizer->normalizeRootDefinition($definition, $name); } // Build the cache of wildcard definitions if ($this->wildcardDefinitions === null) { $this->wildcardDefinitions = []; foreach ($this->definitions as $key => $definition) { if (str_contains($key, self::WILDCARD)) { $this->wildcardDefinitions[$key] = $definition; } } } // Look in wildcards definitions foreach ($this->wildcardDefinitions as $key => $definition) { // Turn the pattern into a regex $key = preg_quote($key, '#'); $key = '#^' . str_replace('\\' . self::WILDCARD, self::WILDCARD_PATTERN, $key) . '#'; if (preg_match($key, $name, $matches) === 1) { array_shift($matches); return $this->normalizer->normalizeRootDefinition($definition, $name, $matches); } } return null; } public function getDefinitions() : array { // Return all definitions except wildcard definitions $definitions = []; foreach ($this->definitions as $key => $definition) { if (! str_contains($key, self::WILDCARD)) { $definitions[$key] = $definition; } } return $definitions; } } */ class DefinitionFile extends DefinitionArray { private bool $initialized = false; /** * @param string $file File in which the definitions are returned as an array. */ public function __construct( private string $file, ?Autowiring $autowiring = null, ) { // Lazy-loading to improve performances parent::__construct([], $autowiring); } public function getDefinition(string $name) : ?Definition { $this->initialize(); return parent::getDefinition($name); } public function getDefinitions() : array { $this->initialize(); return parent::getDefinitions(); } /** * Lazy-loading of the definitions. */ private function initialize() : void { if ($this->initialized === true) { return; } $definitions = require $this->file; if (! is_array($definitions)) { throw new \Exception("File $this->file should return an array of definitions"); } $this->addDefinitions($definitions); $this->initialized = true; } } */ class DefinitionNormalizer { public function __construct( private Autowiring $autowiring, ) { } /** * Normalize a definition that is *not* nested in another one. * * This is usually a definition declared at the root of a definition array. * * @param string $name The definition name. * @param string[] $wildcardsReplacements Replacements for wildcard definitions. * * @throws InvalidDefinition */ public function normalizeRootDefinition(mixed $definition, string $name, ?array $wildcardsReplacements = null) : Definition { if ($definition instanceof DefinitionHelper) { $definition = $definition->getDefinition($name); } elseif (is_array($definition)) { $definition = new ArrayDefinition($definition); } elseif ($definition instanceof \Closure) { $definition = new FactoryDefinition($name, $definition); } elseif (! $definition instanceof Definition) { $definition = new ValueDefinition($definition); } // For a class definition, we replace * in the class name with the matches // *Interface -> *Impl => FooInterface -> FooImpl if ($wildcardsReplacements && $definition instanceof ObjectDefinition) { $definition->replaceWildcards($wildcardsReplacements); } if ($definition instanceof AutowireDefinition) { /** @var AutowireDefinition $definition */ $definition = $this->autowiring->autowire($name, $definition); } $definition->setName($name); try { $definition->replaceNestedDefinitions([$this, 'normalizeNestedDefinition']); } catch (InvalidDefinition $e) { throw InvalidDefinition::create($definition, sprintf( 'Definition "%s" contains an error: %s', $definition->getName(), $e->getMessage() ), $e); } return $definition; } /** * Normalize a definition that is nested in another one. * * @throws InvalidDefinition */ public function normalizeNestedDefinition(mixed $definition) : mixed { $name = ''; if ($definition instanceof DefinitionHelper) { $definition = $definition->getDefinition($name); } elseif (is_array($definition)) { $definition = new ArrayDefinition($definition); } elseif ($definition instanceof \Closure) { $definition = new FactoryDefinition($name, $definition); } if ($definition instanceof DecoratorDefinition) { throw new InvalidDefinition('Decorators cannot be nested in another definition'); } if ($definition instanceof AutowireDefinition) { $definition = $this->autowiring->autowire($name, $definition); } if ($definition instanceof Definition) { $definition->setName($name); // Recursively traverse nested definitions $definition->replaceNestedDefinitions([$this, 'normalizeNestedDefinition']); } return $definition; } } */ interface DefinitionSource { /** * Returns the DI definition for the entry name. * * @throws InvalidDefinition An invalid definition was found. */ public function getDefinition(string $name) : ?Definition; /** * @return array Definitions indexed by their name. */ public function getDefinitions() : array; } */ interface MutableDefinitionSource extends DefinitionSource { public function addDefinition(Definition $definition) : void; } */ class NoAutowiring implements Autowiring { public function autowire(string $name, ?ObjectDefinition $definition = null) : ?ObjectDefinition { throw new InvalidDefinition(sprintf( 'Cannot autowire entry "%s" because autowiring is disabled', $name )); } } */ class ReflectionBasedAutowiring implements DefinitionSource, Autowiring { public function autowire(string $name, ?ObjectDefinition $definition = null) : ?ObjectDefinition { $className = $definition ? $definition->getClassName() : $name; if (!class_exists($className) && !interface_exists($className)) { return $definition; } $definition = $definition ?: new ObjectDefinition($name); // Constructor $class = new \ReflectionClass($className); $constructor = $class->getConstructor(); if ($constructor && $constructor->isPublic()) { $constructorInjection = MethodInjection::constructor($this->getParametersDefinition($constructor)); $definition->completeConstructorInjection($constructorInjection); } return $definition; } public function getDefinition(string $name) : ?ObjectDefinition { return $this->autowire($name); } /** * Autowiring cannot guess all existing definitions. */ public function getDefinitions() : array { return []; } /** * Read the type-hinting from the parameters of the function. */ private function getParametersDefinition(\ReflectionFunctionAbstract $constructor) : array { $parameters = []; foreach ($constructor->getParameters() as $index => $parameter) { // Skip optional parameters if ($parameter->isOptional()) { continue; } $parameterType = $parameter->getType(); if (!$parameterType) { // No type continue; } if (!$parameterType instanceof ReflectionNamedType) { // Union types are not supported continue; } if ($parameterType->isBuiltin()) { // Primitive types are not supported continue; } $parameters[$index] = new Reference($parameterType->getName()); } return $parameters; } } */ class SourceCache implements DefinitionSource, MutableDefinitionSource { public const CACHE_KEY = 'php-di.definitions.'; public function __construct( private DefinitionSource $cachedSource, private string $cacheNamespace = '', ) { } public function getDefinition(string $name) : ?Definition { $definition = apcu_fetch($this->getCacheKey($name)); if ($definition === false) { $definition = $this->cachedSource->getDefinition($name); // Update the cache if ($this->shouldBeCached($definition)) { apcu_store($this->getCacheKey($name), $definition); } } return $definition; } /** * Used only for the compilation so we can skip the cache safely. */ public function getDefinitions() : array { return $this->cachedSource->getDefinitions(); } public static function isSupported() : bool { return function_exists('apcu_fetch') && ini_get('apc.enabled') && ! ('cli' === \PHP_SAPI && ! ini_get('apc.enable_cli')); } public function getCacheKey(string $name) : string { return self::CACHE_KEY . $this->cacheNamespace . $name; } public function addDefinition(Definition $definition) : void { throw new \LogicException('You cannot set a definition at runtime on a container that has caching enabled. Doing so would risk caching the definition for the next execution, where it might be different. You can either put your definitions in a file, remove the cache or ->set() a raw value directly (PHP object, string, int, ...) instead of a PHP-DI definition.'); } private function shouldBeCached(?Definition $definition = null) : bool { return // Cache missing definitions ($definition === null) // Object definitions are used with `make()` || ($definition instanceof ObjectDefinition) // Autowired definitions cannot be all compiled and are used with `make()` || ($definition instanceof AutowireDefinition); } } */ class SourceChain implements DefinitionSource, MutableDefinitionSource { private ?MutableDefinitionSource $mutableSource; /** * @param list $sources */ public function __construct( private array $sources, ) { } /** * @param int $startIndex Use this parameter to start looking from a specific * point in the source chain. */ public function getDefinition(string $name, int $startIndex = 0) : ?Definition { $count = count($this->sources); for ($i = $startIndex; $i < $count; ++$i) { $source = $this->sources[$i]; $definition = $source->getDefinition($name); if ($definition) { if ($definition instanceof ExtendsPreviousDefinition) { $this->resolveExtendedDefinition($definition, $i); } return $definition; } } return null; } public function getDefinitions() : array { $allDefinitions = array_merge(...array_map(fn ($source) => $source->getDefinitions(), $this->sources)); /** @var string[] $allNames */ $allNames = array_keys($allDefinitions); $allValues = array_filter(array_map(fn ($name) => $this->getDefinition($name), $allNames)); return array_combine($allNames, $allValues); } public function addDefinition(Definition $definition) : void { if (! $this->mutableSource) { throw new \LogicException("The container's definition source has not been initialized correctly"); } $this->mutableSource->addDefinition($definition); } private function resolveExtendedDefinition(ExtendsPreviousDefinition $definition, int $currentIndex) { // Look in the next sources only (else infinite recursion, and we can only extend // entries defined in the previous definition files - a previous == next here because // the array was reversed ;) ) $subDefinition = $this->getDefinition($definition->getName(), $currentIndex + 1); if ($subDefinition) { $definition->setExtendedDefinition($subDefinition); } } public function setMutableDefinitionSource(MutableDefinitionSource $mutableSource) : void { $this->mutableSource = $mutableSource; array_unshift($this->sources, $mutableSource); } } */ class StringDefinition implements Definition, SelfResolvingDefinition { /** Entry name. */ private string $name = ''; public function __construct( private string $expression, ) { } public function getName() : string { return $this->name; } public function setName(string $name) : void { $this->name = $name; } public function getExpression() : string { return $this->expression; } public function resolve(ContainerInterface $container) : string { return self::resolveExpression($this->name, $this->expression, $container); } public function isResolvable(ContainerInterface $container) : bool { return true; } public function replaceNestedDefinitions(callable $replacer) : void { // no nested definitions } public function __toString() : string { return $this->expression; } /** * Resolve a string expression. */ public static function resolveExpression( string $entryName, string $expression, ContainerInterface $container, ) : string { $callback = function (array $matches) use ($entryName, $container) { /** @psalm-suppress InvalidCatch */ try { return $container->get($matches[1]); } catch (NotFoundExceptionInterface $e) { throw new DependencyException(sprintf( "Error while parsing string expression for entry '%s': %s", $entryName, $e->getMessage() ), 0, $e); } }; $result = preg_replace_callback('#\{([^{}]+)}#', $callback, $expression); if ($result === null) { throw new \RuntimeException(sprintf('An unknown error occurred while parsing the string definition: \'%s\'', $expression)); } return $result; } } */ class ValueDefinition implements Definition, SelfResolvingDefinition { /** * Entry name. */ private string $name = ''; public function __construct( private mixed $value, ) { } public function getName() : string { return $this->name; } public function setName(string $name) : void { $this->name = $name; } public function getValue() : mixed { return $this->value; } public function resolve(ContainerInterface $container) : mixed { return $this->getValue(); } public function isResolvable(ContainerInterface $container) : bool { return true; } public function replaceNestedDefinitions(callable $replacer) : void { // no nested definitions } public function __toString() : string { return sprintf('Value (%s)', var_export($this->value, true)); } } */ interface RequestedEntry { /** * Returns the name of the entry that was requested by the container. */ public function getName() : string; } */ interface FactoryInterface { /** * Resolves an entry by its name. If given a class name, it will return a new instance of that class. * * @param string $name Entry name or a class name. * @param array $parameters Optional parameters to use to build the entry. Use this to force specific * parameters to specific values. Parameters not defined in this array will * be automatically resolved. * * @throws \InvalidArgumentException The name parameter must be of type string. * @throws DependencyException Error while resolving the entry. * @throws NotFoundException No entry or class found for the given name. */ public function make(string $name, array $parameters = []) : mixed; } */ class DefinitionParameterResolver implements ParameterResolver { public function __construct( private DefinitionResolver $definitionResolver, ) { } public function getParameters( ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters, ) : array { // Skip parameters already resolved if (! empty($resolvedParameters)) { $providedParameters = array_diff_key($providedParameters, $resolvedParameters); } foreach ($providedParameters as $key => $value) { if ($value instanceof DefinitionHelper) { $value = $value->getDefinition(''); } if (! $value instanceof Definition) { continue; } $value = $this->definitionResolver->resolve($value); if (is_int($key)) { // Indexed by position $resolvedParameters[$key] = $value; } else { // Indexed by parameter name // TODO optimize? $reflectionParameters = $reflection->getParameters(); foreach ($reflectionParameters as $reflectionParameter) { if ($key === $reflectionParameter->name) { $resolvedParameters[$reflectionParameter->getPosition()] = $value; } } } } return $resolvedParameters; } } * @author Matthieu Napoli */ class FactoryParameterResolver implements ParameterResolver { public function __construct( private ContainerInterface $container, ) { } public function getParameters( ReflectionFunctionAbstract $reflection, array $providedParameters, array $resolvedParameters, ) : array { $parameters = $reflection->getParameters(); // Skip parameters already resolved if (! empty($resolvedParameters)) { $parameters = array_diff_key($parameters, $resolvedParameters); } foreach ($parameters as $index => $parameter) { $parameterType = $parameter->getType(); if (!$parameterType) { // No type continue; } if (!$parameterType instanceof ReflectionNamedType) { // Union types are not supported continue; } if ($parameterType->isBuiltin()) { // Primitive types are not supported continue; } $parameterClass = $parameterType->getName(); if ($parameterClass === 'Psr\Container\ContainerInterface') { $resolvedParameters[$index] = $this->container; } elseif ($parameterClass === 'DI\Factory\RequestedEntry') { // By convention the second parameter is the definition $resolvedParameters[$index] = $providedParameters[1]; } elseif ($this->container->has($parameterClass)) { $resolvedParameters[$index] = $this->container->get($parameterClass); } } return $resolvedParameters; } } */ class NativeProxyFactory implements ProxyFactoryInterface { /** * Creates a new lazy proxy instance of the given class with * the given initializer. * * {@inheritDoc} */ public function createProxy(string $className, \Closure $createFunction) : object { if (\PHP_VERSION_ID < 80400) { throw new LogicException('Lazy loading proxies require PHP 8.4 or higher.'); } $reflector = new \ReflectionClass($className); return $reflector->newLazyProxy($createFunction); } public function generateProxyClass(string $className) : void { // Noop for this type. } } */ class ProxyFactory implements ProxyFactoryInterface { private ?LazyLoadingValueHolderFactory $proxyManager = null; /** * @param string|null $proxyDirectory If set, write the proxies to disk in this directory to improve performances. */ public function __construct( private ?string $proxyDirectory = null, ) { } /** * Creates a new lazy proxy instance of the given class with * the given initializer. * * {@inheritDoc} */ public function createProxy(string $className, \Closure $createFunction): object { return $this->proxyManager()->createProxy( $className, function (& $wrappedObject, $proxy, $method, $params, & $initializer) use ($createFunction) { $wrappedObject = $createFunction(); $initializer = null; // turning off further lazy initialization return true; } ); } /** * Generates and writes the proxy class to file. * * @param class-string $className name of the class to be proxied */ public function generateProxyClass(string $className) : void { // If proxy classes a written to file then we pre-generate the class // If they are not written to file then there is no point to do this if ($this->proxyDirectory) { $this->createProxy($className, function () {}); } } private function proxyManager() : LazyLoadingValueHolderFactory { if ($this->proxyManager === null) { if (! class_exists(Configuration::class)) { throw new \RuntimeException('The ocramius/proxy-manager library is not installed. Lazy injection requires that library to be installed with Composer in order to work. Run "composer require ocramius/proxy-manager:~2.0".'); } $config = new Configuration(); if ($this->proxyDirectory) { $config->setProxiesTargetDir($this->proxyDirectory); $config->setGeneratorStrategy(new FileWriterGeneratorStrategy(new FileLocator($this->proxyDirectory))); // @phpstan-ignore-next-line spl_autoload_register($config->getProxyAutoloader()); } else { $config->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); } $this->proxyManager = new LazyLoadingValueHolderFactory($config); } return $this->proxyManager; } } */ interface ProxyFactoryInterface { /** * Creates a new lazy proxy instance of the given class with * the given initializer. * * @param class-string $className name of the class to be proxied * @param \Closure $createFunction initializer to be passed to the proxy initializer to be passed to the proxy */ public function createProxy(string $className, \Closure $createFunction) : object; /** * If the proxy generator depends on a filesystem component, * this step writes the proxy for that class to file. Otherwise, * it is a no-op. * * @param class-string $className name of the class to be proxied */ public function generateProxyClass(string $className) : void; } decorate(function ($foo, $container) { * return new CachedFoo($foo, $container->get('cache')); * }) * * @param callable $callable The callable takes the decorated object as first parameter and * the container as second. */ function decorate(callable|array|string $callable) : FactoryDefinitionHelper { return new FactoryDefinitionHelper($callable, true); } } if (! function_exists('DI\get')) { /** * Helper for referencing another container entry in an object definition. */ function get(string $entryName) : Reference { return new Reference($entryName); } } if (! function_exists('DI\env')) { /** * Helper for referencing environment variables. * * @param string $variableName The name of the environment variable. * @param mixed $defaultValue The default value to be used if the environment variable is not defined. */ function env(string $variableName, mixed $defaultValue = null) : EnvironmentVariableDefinition { // Only mark as optional if the default value was *explicitly* provided. $isOptional = 2 === func_num_args(); return new EnvironmentVariableDefinition($variableName, $isOptional, $defaultValue); } } if (! function_exists('DI\add')) { /** * Helper for extending another definition. * * Example: * * 'log.backends' => DI\add(DI\get('My\Custom\LogBackend')) * * or: * * 'log.backends' => DI\add([ * DI\get('My\Custom\LogBackend') * ]) * * @param mixed|array $values A value or an array of values to add to the array. * * @since 5.0 */ function add($values) : ArrayDefinitionExtension { if (! is_array($values)) { $values = [$values]; } return new ArrayDefinitionExtension($values); } } if (! function_exists('DI\string')) { /** * Helper for concatenating strings. * * Example: * * 'log.filename' => DI\string('{app.path}/app.log') * * @param string $expression A string expression. Use the `{}` placeholders to reference other container entries. * * @since 5.0 */ function string(string $expression) : StringDefinition { return new StringDefinition($expression); } } --- layout: documentation current_menu: enterprise-support title: Enterprise support for PHP-DI --- # PHP-DI for Enterprise > *Available as part of the Tidelift Subscription* Tidelift is working with the maintainers of PHP-DI and thousands of other open source projects to deliver 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. #### [Learn more](https://tidelift.com/subscription/pkg/packagist-php-di-php-di?utm_source=packagist-php-di-php-di&utm_medium=referral&utm_campaign=enterprise) | [**Request a demo**](https://tidelift.com/subscription/request-a-demo?utm_source=packagist-php-di-php-di&utm_medium=referral&utm_campaign=enterprise) ## Enterprise-ready open source software—managed for you The Tidelift Subscription is a managed open source subscription for application dependencies covering millions of open source projects across JavaScript, Python, Java, PHP, Ruby, .NET, and more. Your subscription includes: - **Security updates** Tidelift’s security response team coordinates patches for new breaking security vulnerabilities and alerts immediately through a private channel, so your software supply chain is always secure. - **Licensing verification and indemnification** Tidelift verifies license information to enable easy policy enforcement and adds intellectual property indemnification to cover creators and users in case something goes wrong. You always have a 100% up-to-date bill of materials for your dependencies to share with your legal team, customers, or partners. - **Maintenance and code improvement** Tidelift ensures the software you rely on keeps working as long as you need it to work. Your managed dependencies are actively maintained and we recruit additional maintainers where required. - **Package selection and version guidance** We help you choose the best open source packages from the start—and then guide you through updates to stay on the best releases as new issues arise. - **Roadmap input** Take a seat at the table with the creators behind the software you use. Tidelift’s participating maintainers earn more income as their software is used by more subscribers, so they’re interested in knowing what you need. - **Tooling and cloud integration** Tidelift works with GitHub, GitLab, BitBucket, and more. We support every cloud platform (and other deployment targets, too). The end result? All of the capabilities you expect from commercial-grade software, for the full breadth of open source you use. That means less time grappling with esoteric open source trivia, and more time building your own applications—and your business. [Learn more](https://tidelift.com/subscription/pkg/packagist-php-di-php-di?utm_source=packagist-php-di-php-di&utm_medium=referral&utm_campaign=enterprise) | [**Request a demo**](https://tidelift.com/subscription/request-a-demo?utm_source=packagist-php-di-php-di&utm_medium=referral&utm_campaign=enterprise) 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.

PHPDoc Parser for PHPStan

Build Status Latest Stable Version License PHPStan Enabled

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). ## Features ### Supported type syntax The parser supports a rich type system including: - Basic types: `string`, `int`, `bool`, `null`, `self`, `static`, `$this`, etc. - Nullable types: `?string` - Union and intersection types: `string|int`, `Foo&Bar` - Generic types with variance: `array`, `Collection` - Array shapes: `array{name: string, age: int, ...}` - Object shapes: `object{name: string, age: int}` - Callable/closure types: `callable(string): bool`, `Closure(int): void` - Conditional types: `($input is string ? string : int)` - Offset access types: `T[K]` - Constant type expressions: `self::CONST*`, `123`, `'string'` ### Constant expression parsing Constant expressions used in PHPDoc tags are parsed via `ConstExprParser`: - Scalar values: integers, floats, strings, `true`, `false`, `null` - Arrays: `{1, 2, 'key' => 'value'}` - Class constant fetches: `ClassName::CONSTANT` ### AST node traversal The library provides a visitor-based traversal system (inspired by [nikic/PHP-Parser](https://github.com/nikic/PHP-Parser)) for reading and transforming the AST. ```php use PHPStan\PhpDocParser\Ast\AbstractNodeVisitor; use PHPStan\PhpDocParser\Ast\Node; use PHPStan\PhpDocParser\Ast\NodeTraverser; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; $visitor = new class extends AbstractNodeVisitor { public function enterNode(Node $node) { if ($node instanceof IdentifierTypeNode) { // inspect or transform the node } return $node; } }; $traverser = new NodeTraverser([$visitor]); $traverser->traverse([$phpDocNode]); ``` The `NodeTraverser` supports `DONT_TRAVERSE_CHILDREN`, `STOP_TRAVERSAL`, `REMOVE_NODE`, and `DONT_TRAVERSE_CURRENT_AND_CHILDREN` control constants. A built-in `CloningVisitor` is included for creating deep copies of the AST (used by the format-preserving printer). ### Node attributes Nodes can carry attributes such as line numbers, token indexes, and comments. Enable them via `ParserConfig`: ```php $config = new ParserConfig(usedAttributes: ['lines' => true, 'indexes' => true, 'comments' => true]); ``` These attributes are required for the format-preserving printer and can also be used for mapping AST nodes back to source positions. ## Installation ``` composer require phpstan/phpdoc-parser ``` ## Basic usage ```php 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 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": { "PHPStan\\PhpDocParser\\": [ "src/" ] } }, "autoload-dev": { "psr-4": { "PHPStan\\PhpDocParser\\": [ "tests/PHPStan" ] } }, "minimum-stability": "dev", "prefer-stable": true } text = $text; $this->startLine = $startLine; $this->startIndex = $startIndex; } public function getReformattedText(): string { return trim($this->text); } /** * @param array $properties */ public static function __set_state(array $properties): self { return new self($properties['text'], $properties['startLine'], $properties['startIndex']); } } 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 $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; } } items = $items; } public function __toString(): string { return '[' . implode(', ', $this->items) . ']'; } /** * @param array $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; } } $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; } } value = $value; } public function __toString(): string { return $this->value; } /** * @param array $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; } } value = $value; } public function __toString(): string { return $this->value; } /** * @param array $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; } } $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; } } 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 | (? $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; } } $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; } } className = $className; $this->name = $name; } public function __toString(): string { if ($this->className === '') { return $this->name; } return "{$this->className}::{$this->name}"; } /** * @param array $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; } } 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 $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; } } */ 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; } } Visitors */ private array $visitors = []; /** @var bool Whether traversal should be stopped */ private bool $stopTraversal; /** * @param list $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))); } } } $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; } setAttribute(Attribute::ORIGINAL_NODE, $originalNode); return $node; } } 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 $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; } } 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 $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; } } 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 $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; } } description = $description; } public function __toString(): string { return trim($this->description); } /** * @param array $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; } } */ public array $arguments; /** * @param list $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 $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; } } key = $key; $this->value = $value; } public function __toString(): string { if ($this->key === null) { return (string) $this->value; } return $this->key . '=' . $this->value; } /** * @param array $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; } } */ public array $items; /** * @param list $items */ public function __construct(array $items) { $this->items = $items; } public function __toString(): string { $items = implode(', ', $this->items); return '{' . $items . '}'; } /** * @param array $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; } } key = $key; $this->value = $value; } public function __toString(): string { if ($this->key === null) { return (string) $this->value; } return $this->key . '=' . $this->value; } /** * @param array $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; } } annotation = $annotation; $this->description = $description; } public function __toString(): string { return trim("{$this->annotation} {$this->description}"); } /** * @param array $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; } } type = $type; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->description}"); } /** * @param array $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; } } value = $value; } public function __toString(): string { return $this->value; } /** * @param array $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; } } type = $type; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->description}"); } /** * @param array $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; } } 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 $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; } } 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 $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; } } 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 $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; } } type = $type; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->description}"); } /** * @param array $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; } } type = $type; $this->parameterName = $parameterName; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->parameterName} {$this->description}"); } /** * @param array $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; } } parameterName = $parameterName; $this->description = $description; } public function __toString(): string { return trim("{$this->parameterName} {$this->description}"); } /** * @param array $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; } } parameterName = $parameterName; $this->description = $description; } public function __toString(): string { return trim("{$this->parameterName} {$this->description}"); } /** * @param array $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; } } type = $type; $this->parameterName = $parameterName; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->parameterName} {$this->description}"); } /** * @param array $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; } } 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 $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; } } 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 PureUnlessParameterIsPassedTagValueNode[] */ public function getPureUnlessParameterIsPassedTagValues(string $tagName = '@pure-unless-parameter-passed'): array { return array_filter( array_column($this->getTagsByName($tagName), 'value'), static fn (PhpDocTagValueNode $value): bool => $value instanceof PureUnlessParameterIsPassedTagValueNode, ); } /** * @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 $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; } } 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 $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; } } text = $text; } public function __toString(): string { return $this->text; } /** * @param array $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; } } type = $type; $this->propertyName = $propertyName; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->propertyName} {$this->description}"); } /** * @param array $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; } } parameterName = $parameterName; $this->description = $description; } public function __toString(): string { return trim("{$this->parameterName} {$this->description}"); } /** * @param array $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; } } parameterName = $parameterName; $this->description = $description; } public function __toString(): string { return trim("{$this->parameterName} {$this->description}"); } } type = $type; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->description}"); } /** * @param array $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; } } type = $type; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->description}"); } /** * @param array $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; } } type = $type; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->description}"); } /** * @param array $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; } } type = $type; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->description}"); } /** * @param array $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; } } type = $type; $this->description = $description; } public function __toString(): string { return trim($this->type . ' ' . $this->description); } /** * @param array $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; } } 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 $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; } } type = $type; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->description}"); } /** * @param array $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; } } 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 $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; } } alias = $alias; $this->type = $type; } public function __toString(): string { return trim("{$this->alias} {$this->type}"); } /** * @param array $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; } } 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 $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; } } type = $type; $this->description = $description; } public function __toString(): string { return trim("{$this->type} {$this->description}"); } /** * @param array $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; } } type = $type; $this->variableName = $variableName; $this->description = $description; } public function __toString(): string { return trim("$this->type " . trim("{$this->variableName} {$this->description}")); } /** * @param array $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; } } 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 $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; } } 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 $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; } } 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 $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; } } 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 $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; } } 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 $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; } } 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 $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; } } 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 $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; } } 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 $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; } } constExpr = $constExpr; } public function __toString(): string { return $this->constExpr->__toString(); } /** * @param array $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; } } 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 $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; } } name = $name; } public function __toString(): string { return $this->name; } /** * @param array $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; } } 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 $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; } } 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 $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; } } type = $type; } public function __toString(): string { return '?' . $this->type; } /** * @param array $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; } } 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 $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; } } items = $items; } public function __toString(): string { $items = $this->items; return 'object{' . implode(', ', $items) . '}'; } /** * @param array $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; } } 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 $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; } } $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; } } 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 $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; } } '\'&\'', 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 */ 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'; } } 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; } } 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; } } 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 '@pure-unless-parameter-passed': case '@phpstan-pure-unless-parameter-passed': $tagValue = $this->parsePureUnlessParameterIsPassed($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 */ 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 parsePureUnlessParameterIsPassed(TokenIterator $tokens): Ast\PhpDoc\PureUnlessParameterIsPassedTagValueNode { $parameterName = $this->parseRequiredVariableName($tokens); $description = $this->parseOptionalDescription($tokens, false); return new Ast\PhpDoc\PureUnlessParameterIsPassedTagValueNode($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; } } '\\', '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 "\xef\xbf\xbd"; } } */ private array $tokens; private int $index; /** @var list */ private array $comments = []; /** @var list}> */ private array $savePoints = []; /** @var list */ private array $skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS]; private ?string $newline = null; /** * @param list $tokens */ public function __construct(array $tokens, int $index = 0) { $this->tokens = $tokens; $this->index = $index; $this->skipIrrelevantTokens(); } /** * @return list */ 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 */ 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); } } 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 = ''; $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); } } useLinesAttributes = $usedAttributes['lines'] ?? false; $this->useIndexAttributes = $usedAttributes['indexes'] ?? false; $this->useCommentsAttributes = $usedAttributes['comments'] ?? false; } } type = $type; $this->old = $old; $this->new = $new; } } 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, 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> $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; } } */ private Differ $differ; /** * Map From "{$class}->{$subNode}" to string that should be inserted * between elements of this list subnode * * @var array */ 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 */ private array $emptyListInsertionMap = [ CallableTypeNode::class . '->parameters' => ['(', '', ''], ArrayShapeNode::class . '->items' => ['{', '', ''], ObjectShapeNode::class . '->items' => ['{', '', ''], DoctrineArray::class . '->items' => ['{', '', ''], DoctrineAnnotation::class . '->arguments' => ['(', '', ''], ]; /** @var array>> */ 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>> */ 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 PureUnlessParameterIsPassedTagValueNode) { 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 $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 $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(?[\\x09\\x20]*)\*(?\\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); } } MIT License Copyright (c) 2016 Ondřej Mirtes 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.

PHPStan - PHP Static Analysis Tool

PHPStan

Build Status Latest Stable Version Total Downloads License PHPStan Enabled

------ PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code can be checked before you run the actual line. **[Read more about PHPStan »](https://phpstan.org/)** **[Try out PHPStan on the on-line playground! »](https://phpstan.org/try)** ## Sponsors TheCodingMachine     Private Packagist
CDN77     Blackfire.io
iO     Fame Helsinki
ShipMonk     Togetter
RightCapital     ContentKing
ZOL     EdgeNext
Shopware     Craft CMS
Worksome     campoint AG
Crisp.nl     Inviqa
GetResponse     Shoptet
Route4Me: Route Optimizer and Route Planner Software     TicketSwap [**You can now sponsor my open-source work on PHPStan through GitHub Sponsors.**](https://github.com/sponsors/ondrejmirtes) Does GitHub already have your 💳? Do you use PHPStan to find 🐛 before they reach production? [Send a couple of 💸 a month my way too.](https://github.com/sponsors/ondrejmirtes) Thank you! One-time donations [through Revolut.me](https://revolut.me/ondrejmirtes) are also accepted. To request an invoice, [contact me](mailto:ondrej@mirtes.cz) through e-mail. ## Documentation All the documentation lives on the [phpstan.org website](https://phpstan.org/): * [Getting Started & User Guide](https://phpstan.org/user-guide/getting-started) * [Config Reference](https://phpstan.org/config-reference) * [PHPDocs Basics](https://phpstan.org/writing-php-code/phpdocs-basics) & [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types) * [Extension Library](https://phpstan.org/user-guide/extension-library) * [Developing Extensions](https://phpstan.org/developing-extensions/extension-types) * [API Reference](https://apiref.phpstan.org/) ## PHPStan Pro PHPStan Pro is a paid add-on on top of open-source PHPStan Static Analysis Tool with these premium features: * Web UI for browsing found errors, you can click and open your editor of choice on the offending line. * Continuous analysis (watch mode): scans changed files in the background, refreshes the UI automatically. Try it on PHPStan 0.12.45 or later by running it with the `--pro` option. You can create an account either by following the on-screen instructions, or by visiting [account.phpstan.com](https://account.phpstan.com/). After 30-day free trial period it costs 7 EUR for individuals monthly, 70 EUR for teams (up to 25 members). By paying for PHPStan Pro, you're supporting the development of open-source PHPStan. You can read more about it on [PHPStan's website](https://phpstan.org/blog/introducing-phpstan-pro). ## Code of Conduct This project adheres to a [Contributor Code of Conduct](https://github.com/phpstan/phpstan/blob/master/CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code. ## Contributing Any contributions are welcome. PHPStan's source code open to pull requests lives at [`phpstan/phpstan-src`](https://github.com/phpstan/phpstan-src). loadClass($class); return; } if (strpos($class, 'PHPStan\\') !== 0 || strpos($class, 'PHPStan\\PhpDocParser\\') === 0) { return; } if (!in_array('phar', stream_get_wrappers(), true)) { throw new \Exception('Phar wrapper is not registered. Please review your php.ini settings.'); } if (!self::$polyfillsLoaded) { self::$polyfillsLoaded = true; if ( PHP_VERSION_ID < 80000 && empty($GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e']) && !class_exists(\Symfony\Polyfill\Php80\Php80::class, false) ) { $GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e'] = true; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/Php80.php'; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/bootstrap.php'; } if ( empty($GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a']) && !class_exists(\Symfony\Polyfill\Mbstring\Mbstring::class, false) ) { $GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a'] = true; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/Mbstring.php'; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/bootstrap.php'; } if ( empty($GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38']) && !class_exists(\Symfony\Polyfill\Intl\Normalizer\Normalizer::class, false) ) { $GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38'] = true; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/Normalizer.php'; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/bootstrap.php'; } if ( PHP_VERSION_ID < 70300 && empty($GLOBALS['__composer_autoload_files']['0d59ee240a4cd96ddbb4ff164fccea4d']) && !class_exists(\Symfony\Polyfill\Php73\Php73::class, false) ) { $GLOBALS['__composer_autoload_files']['0d59ee240a4cd96ddbb4ff164fccea4d'] = true; // already loaded by bootstrap inside the hrtime condition // require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php73/Php73.php'; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php73/bootstrap.php'; } if ( PHP_VERSION_ID < 70400 && empty($GLOBALS['__composer_autoload_files']['b686b8e46447868025a15ce5d0cb2634']) && !class_exists(\Symfony\Polyfill\Php74\Php74::class, false) ) { $GLOBALS['__composer_autoload_files']['b686b8e46447868025a15ce5d0cb2634'] = true; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php74/Php74.php'; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php74/bootstrap.php'; } if ( !extension_loaded('intl') && empty($GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8']) && !class_exists(\Symfony\Polyfill\Intl\Grapheme\Grapheme::class, false) ) { $GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8'] = true; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/Grapheme.php'; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/bootstrap.php'; } if ( PHP_VERSION_ID < 80100 && empty ($GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f']) && !class_exists(\Symfony\Polyfill\Php81\Php81::class, false) ) { $GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f'] = true; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/Php81.php'; require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/bootstrap.php'; } } $filename = str_replace('\\', DIRECTORY_SEPARATOR, $class); if (strpos($class, 'PHPStan\\BetterReflection\\') === 0) { $filename = substr($filename, strlen('PHPStan\\BetterReflection\\')); $filepath = 'phar://' . __DIR__ . '/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/' . $filename . '.php'; } else { $filename = substr($filename, strlen('PHPStan\\')); $filepath = 'phar://' . __DIR__ . '/phpstan.phar/src/' . $filename . '.php'; } if (!file_exists($filepath)) { return; } require $filepath; } } spl_autoload_register([PharAutoloader::class, 'loadClass']); { "name": "phpstan/phpstan", "description": "PHPStan - PHP Static Analysis Tool", "license": ["MIT"], "keywords": ["dev", "static analysis"], "require": { "php": "^7.2|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" }, "bin": [ "phpstan", "phpstan.phar" ], "autoload": { "files": ["bootstrap.php"] }, "source": { "type": "", "url": "", "reference": "" }, "support": { "issues": "https://github.com/phpstan/phpstan/issues", "forum": "https://github.com/phpstan/phpstan/discussions", "source": "https://github.com/phpstan/phpstan-src", "docs": "https://phpstan.org/user-guide/getting-started", "security": "https://github.com/phpstan/phpstan/security/policy" } } includes: - phar://phpstan.phar/conf/bleedingEdge.neon #!/usr/bin/env php } stubs/typeCheckingFunctions.stub^R~hj^U5 ¤stubs/SplObjectStorage.stubR~hj+qstubs/ReflectionAttribute.stub R~hj qstubs/ext-ds.stubw8R~hjw8 &stubs/mysqli.stubXR~hjX FVstubs/WeakReference.stub`R~hj``stubs/core.stub"R~hj">stubs/ReflectionClass.stubR~hjڤstubs/ibm_db2.stubR~hjcҤstubs/bleedingEdge/Rule.stubR~hjߤ !stubs/bleedingEdge/Countable.stuboR~hjo Ustubs/dom.stubMR~hjMM =stubs/ReflectionMethod.stubR~hjästubs/socket_select.stubR~hjf/stubs/ReflectionParameter.stubR~hj5Τ%stubs/ReflectionFunctionAbstract.stubR~hjVcȤstubs/spl.stub/R~hj/ stubs/PDOStatement.stubR~hjstubs/ImagickPixel.stubpR~hjp+stubs/ArrayObject.stubR~hjjMstubs/socket_select_php8.stubR~hj٤stubs/json_validate.stubR~hjvRstubs/iterable.stub#R~hj#)kstubs/zip.stub4R~hj4#stubs/date.stubR~hjfastubs/ReflectionEnum.stubhR~hjhݠFߤstubs/Countable.stubdR~hjd䞤stubs/ReflectionProperty.stubR~hjXڛڤstubs/Exception.stub- R~hj- Wm,stubs/runtime/ReflectionIntersectionType.phpR~hj;%stubs/runtime/ReflectionAttribute.phpR~hj="/stubs/runtime/Enum/ReflectionEnumBackedCase.phpR~hj;7ystubs/runtime/Enum/UnitEnum.phpR~hj!stubs/runtime/Enum/BackedEnum.php R~hj M-stubs/runtime/Enum/ReflectionEnumUnitCase.phpR~hj%stubs/runtime/Enum/ReflectionEnum.phpR~hjmG%stubs/runtime/ReflectionUnionType.phpR~hjD=stubs/runtime/Attribute.php9R~hj9Qۊstubs/arrayFunctions.stub5R~hj5."stubs/ReflectionClassConstant.stubR~hjDxd bin/phpstanR~hj$resources/functionMap_php74delta.php5R~hj5 resources/functionMap.phpvR~hjvqresources/RegexGrammar.ppR~hj7?y$resources/functionMap_php84delta.phpR~hjb$resources/functionMap_php80delta.phpljR~hjlj1resources/functionMap_php80delta_bleedingEdge.phpR~hjH)resources/functionMetadata.php[R~hj[>I&resources/functionMap_bleedingEdge.phpHLR~hjHL*Y$resources/functionMap_php81delta.phpR~hj@-src/DependencyInjection/Neon/OptionalPath.phpR~hj`GŤTsrc/DependencyInjection/Type/LazyOperatorTypeSpecifyingExtensionRegistryProvider.phpR~hje('Bsrc/DependencyInjection/Type/ParameterOutTypeExtensionProvider.phpR~hjJsrc/DependencyInjection/Type/LazyParameterClosureTypeExtensionProvider.php{R~hj{ äBsrc/DependencyInjection/Type/DynamicThrowTypeExtensionProvider.phpR~hjpդFsrc/DependencyInjection/Type/ParameterClosureTypeExtensionProvider.phpR~hjI{Fsrc/DependencyInjection/Type/LazyDynamicThrowTypeExtensionProvider.php[R~hj[*ǤFsrc/DependencyInjection/Type/LazyParameterOutTypeExtensionProvider.php[R~hj[j4Tsrc/DependencyInjection/Type/LazyExpressionTypeResolverExtensionRegistryProvider.phpR~hjRפOsrc/DependencyInjection/Type/LazyDynamicReturnTypeExtensionRegistryProvider.php!R~hj!;-jPsrc/DependencyInjection/Type/ExpressionTypeResolverExtensionRegistryProvider.phpR~hj楤Psrc/DependencyInjection/Type/OperatorTypeSpecifyingExtensionRegistryProvider.phpR~hjs)Ksrc/DependencyInjection/Type/DynamicReturnTypeExtensionRegistryProvider.phpR~hj;r'src/DependencyInjection/NeonAdapter.phpR~hj]4src/DependencyInjection/ConditionalTagsExtension.phpR~hjɈjI6src/DependencyInjection/ParameterNotFoundException.phpPR~hjP D6src/DependencyInjection/DerivativeContainerFactory.php R~hj 0src/DependencyInjection/Nette/NetteContainer.php R~hj }B)src/DependencyInjection/LoaderFactory.php,R~hj,)FE1;src/DependencyInjection/DuplicateIncludedFilesException.phppR~hjp԰;iOsrc/DependencyInjection/Reflection/ClassReflectionExtensionRegistryProvider.php R~hj rSsrc/DependencyInjection/Reflection/LazyClassReflectionExtensionRegistryProvider.php+ R~hj+ Pyʤ5src/DependencyInjection/ParametersSchemaExtension.phpR~hjW/2,src/DependencyInjection/ContainerFactory.php&<R~hj&<ӎ&src/DependencyInjection/NeonLoader.phpR~hj s/src/DependencyInjection/ProjectConfigHelper.phpR~hj B8src/DependencyInjection/InvalidExcludePathsException.php'R~hj'Ԕ~.src/DependencyInjection/MemoizingContainer.phpR~hjmr(src/DependencyInjection/Configurator.php R~hj cI@src/DependencyInjection/InvalidIgnoredErrorPatternsException.php/R~hj/6:src/DependencyInjection/ValidateIgnoredErrorsExtension.php! R~hj! 1%src/DependencyInjection/Container.phpR~hj؋R.src/DependencyInjection/BleedingEdgeToggle.phpR~hj7a9src/DependencyInjection/ValidateExcludePathsExtension.phpw R~hjw a*src/DependencyInjection/RulesExtension.phpR~hjewGsrc/AnalysedCodeException.phpR~hjiqE^&src/Dependency/ExportedNodeFetcher.phpR~hj*^#src/Dependency/RootExportedNode.phpR~hj]65src/Dependency/ExportedNode.phpaR~hjaVN&src/Dependency/ExportedNodeVisitor.phpR~hj‚Y5src/Dependency/ExportedNode/ExportedInterfaceNode.php R~hj }A1src/Dependency/ExportedNode/ExportedClassNode.phpSR~hjS o9src/Dependency/ExportedNode/ExportedClassConstantNode.phpU R~hjU a%4src/Dependency/ExportedNode/ExportedEnumCaseNode.phpR~hj5src/Dependency/ExportedNode/ExportedParameterNode.php R~hj Ȥ5src/Dependency/ExportedNode/ExportedAttributeNode.phpR~hj071src/Dependency/ExportedNode/ExportedTraitNode.phpR~hj:4src/Dependency/ExportedNode/ExportedFunctionNode.phpR~hj6u:src/Dependency/ExportedNode/ExportedClassConstantsNode.php R~hj )8:src/Dependency/ExportedNode/ExportedTraitUseAdaptation.phpF R~hjF )2src/Dependency/ExportedNode/ExportedPhpDocNode.php)R~hj)2src/Dependency/ExportedNode/ExportedMethodNode.phpR~hjB6src/Dependency/ExportedNode/ExportedPropertiesNode.php$R~hj$2l٤0src/Dependency/ExportedNode/ExportedEnumNode.phpR~hjVt%src/Dependency/DependencyResolver.phpR~hjt#src/Dependency/NodeDependencies.phpR~hjW'src/Dependency/ExportedNodeResolver.php4R~hj4-$src/Testing/PHPStanTestCase.php!%R~hj!%zQsrc/Testing/functions.phpR~hj-c&src/Testing/ErrorFormatterTestCase.php;R~hj;ӏE],src/Testing/TestCaseSourceLocatorFactory.phpiR~hji%src/Testing/TypeInferenceTestCase.php5R~hj5]src/Testing/RuleTestCase.phpOR~hjOIsrc/Testing/LevelsTestCase.phpR~hj&[src/Testing/TestCase.neonR~hj;,!src/Type/IterableType.php=R~hj=e,src/Type/ExpressionTypeResolverExtension.phpIR~hjIC8src/Type/IntegerRangeType.phpc\R~hjc\Y]src/Type/ConditionalType.phpR~hjsrc/Type/VoidType.phpR~hjʃl¤src/Type/StrictMixedType.phpu/R~hju/ֹ.src/Type/FunctionParameterOutTypeExtension.phpR~hj$%¤0src/Type/StaticMethodTypeSpecifyingExtension.phpGR~hjGz;src/Type/ConstantType.php|R~hj|>Gsrc/Type/CallableType.phpgSR~hjgS* 'src/Type/CircularTypeAliasErrorType.phpR~hj[}#src/Type/ObjectWithoutClassType.phpR~hjX@src/Type/ArrayType.phpcR~hjcpsrc/Type/StaticTypeFactory.phpR~hjesrc/Type/NewObjectType.php6 R~hj6 )src/Type/Constant/ConstantIntegerType.php R~hj j)src/Type/Constant/ConstantBooleanType.php R~hj (src/Type/Constant/ConstantStringType.phpKR~hjKD2src/Type/Constant/ConstantScalarToBooleanTrait.phpR~hj&+src/Type/Constant/OversizedArrayBuilder.phpR~hjvj''src/Type/Constant/ConstantFloatType.php R~hj B'src/Type/Constant/ConstantArrayType.phppR~hjpF0src/Type/Constant/ConstantArrayTypeAndMethod.phpR~hj..src/Type/Constant/ConstantArrayTypeBuilder.php0R~hj0Ksrc/Type/VerbosityLevel.phpuR~hjuSsrc/Type/UnionTypeHelper.php~R~hj~"osrc/Type/FileTypeMapper.php4R~hj4:릤src/Type/ClassStringType.phpM R~hjM src/Type/FloatType.phpR~hjj:src/Type/BitwiseFlagHelper.php R~hj *-{src/Type/KeyOfType.php& R~hj& s٤*src/Type/LazyTypeAliasResolverProvider.phpR~hjcksrc/Type/TypeAlias.phpiR~hji9 src/Type/IntegerType.phpR~hjsrc/Type/NullType.phpo)R~hjo),@2src/Type/StaticMethodParameterOutTypeExtension.phpR~hj-src/Type/DynamicMethodReturnTypeExtension.phpR~hjC$$src/Type/Enum/EnumCaseObjectType.phpR~hj Msrc/Type/ExponentiateHelper.phpR~hjM/src/Type/DynamicFunctionReturnTypeExtension.php~R~hj~,src/Type/DirectTypeAliasResolverProvider.phpR~hj),src/Type/FunctionTypeSpecifyingExtension.phpR~hjg\P"src/Type/JustNullableTypeTrait.php2R~hj2OchGsrc/Type/TypeResult.phpR~hj( src/Type/GeneralizePrecision.phpR~hj0"?src/Type/TypeCombinator.phpR~hjERjsrc/Type/BooleanType.phpR~hj D]src/Type/TypeAliasResolver.php4R~hj4Л#src/Type/Regex/RegexGroupParser.phpTR~hjTlդ'src/Type/Regex/RegexGroupWalkResult.php R~hj c)src/Type/Regex/RegexNonCapturingGroup.phpmR~hjm%D%src/Type/Regex/RegexAstWalkResult.php R~hj iڤ(src/Type/Regex/RegexExpressionHelper.phpR~hj(Ϥ#src/Type/Regex/RegexAlternation.phpR~hj^ m&src/Type/Regex/RegexCapturingGroup.phpR~hj+-ڤsrc/Type/ErrorType.phpR~hjXä/src/Type/DynamicReturnTypeExtensionRegistry.phpR~hjn&'src/Type/Helper/GetTemplateTypeType.php R~hj 3src/Type/DynamicStaticMethodReturnTypeExtension.phpR~hjCѤsrc/Type/RecursionGuard.phpR~hj}Osrc/Type/StringType.phpI!R~hjI!G \src/Type/ValueOfType.php R~hj Esrc/Type/TypeWithClassName.php\R~hj\'ܤsrc/Type/TypeUtils.php~2R~hj~2&,src/Type/ClosureType.phpaR~hjaF;$src/Type/UsefulTypeAliasResolver.phpR~hjпsrc/Type/UnionType.php(R~hj([src/Type/ObjectType.phpxR~hjxF282src/Type/FunctionParameterClosureTypeExtension.phpR~hj_(src/Type/ConditionalTypeForParameter.phpR~hjΤ2src/Type/DynamicStaticMethodThrowTypeExtension.phpR~hjsrc/Type/ConstantScalarType.phpR~hj)Y*src/Type/ObjectShapePropertyReflection.phpR~hjc"src/Type/LooseComparisonHelper.php R~hj 9ͤ-src/Type/Accessory/AccessoryArrayListType.php10R~hj104$src/Type/Accessory/HasMethodType.phpR~hjǚ(src/Type/Accessory/NonEmptyArrayType.php+R~hj+դ1src/Type/Accessory/AccessoryLiteralStringType.php$R~hj$dT)src/Type/Accessory/HasOffsetValueType.php5R~hj5fс3src/Type/Accessory/AccessoryUppercaseStringType.phpo$R~hjo$o $src/Type/Accessory/AccessoryType.phpR~hj;ʠ&src/Type/Accessory/HasPropertyType.phpR~hjȨ`2src/Type/Accessory/AccessoryNonFalsyStringType.php'$R~hj'$!f1src/Type/Accessory/AccessoryNumericStringType.php%R~hj%+2src/Type/Accessory/AccessoryNonEmptyStringType.php&R~hj&Ѥ$src/Type/Accessory/HasOffsetType.phpO,R~hjO,)9)src/Type/Accessory/OversizedArrayType.phpk*R~hjk*T%aӤ3src/Type/Accessory/AccessoryLowercaseStringType.phpo$R~hjo$src/Type/StaticType.php^R~hj^ID src/Type/IsSuperTypeOfResult.phpVR~hjV0\src/Type/ObjectShapeType.phpGR~hjGa.src/Type/DynamicFunctionThrowTypeExtension.phplR~hjl+,src/Type/Generic/TemplateStrictMixedType.phpR~hjA&src/Type/Generic/TemplateArrayType.php|R~hj|`&src/Type/Generic/GenericObjectType.php6R~hj6_'Ф&src/Type/Generic/TemplateUnionType.php-R~hj-`mh-src/Type/Generic/TemplateIntersectionType.phpR~hj $src/Type/Generic/TemplateTypeMap.php_R~hj_T)src/Type/Generic/TemplateTypeStrategy.php<R~hj<Uzܤ'src/Type/Generic/TemplateTypeHelper.phpR~hj/%&src/Type/Generic/TemplateKeyOfType.php{R~hj{f1src/Type/Generic/TemplateTypeArgumentStrategy.phpR~hjfy'src/Type/Generic/TemplateObjectType.php R~hj 8&src/Type/Generic/GenericStaticType.php%R~hj%])src/Type/Generic/TypeProjectionHelper.phpsR~hjsH^1)src/Type/Generic/TemplateIterableType.php+R~hj+^2src/Type/Generic/TemplateTypeParameterStrategy.phpR~hj(}'src/Type/Generic/TemplateStringType.phpVR~hjV6yI/3src/Type/Generic/TemplateObjectWithoutClassType.php,R~hj,</src/Type/Generic/TemplateConstantStringType.phpR~hj+T,src/Type/Generic/TemplateObjectShapeType.phpR~hj b&src/Type/Generic/TemplateTypeTrait.php0R~hj0$y(src/Type/Generic/TemplateBooleanType.php[R~hj[.src/Type/Generic/TemplateGenericObjectType.phpR~hj"*src/Type/Generic/TemplateTypeReference.phpR~hjB8(src/Type/Generic/TemplateIntegerType.php[R~hj[˝L+src/Type/Generic/GenericClassStringType.phpR~hj{0src/Type/Generic/TemplateConstantIntegerType.phpR~hjGA8դ.src/Type/Generic/TemplateConstantArrayType.phpR~hj(\&&src/Type/Generic/TemplateFloatType.phpQR~hjQ$Z0src/Type/Generic/TemplateBenevolentUnionType.phpER~hjE֤!src/Type/Generic/TemplateType.php|R~hj|r/)src/Type/Generic/TemplateTypeVariance.phpR~hjK(src/Type/Generic/TemplateTypeFactory.phpTR~hjTiI&src/Type/Generic/TemplateTypeScope.phpR~hjG,src/Type/Generic/TemplateTypeVarianceMap.phpR~hj$.&src/Type/Generic/TemplateMixedType.phphR~hjho,src/Type/OperatorTypeSpecifyingExtension.phpR~hj tFsrc/Type/TypeTraverser.php*R~hj*pIsrc/Type/NeverType.php6R~hj6&"src/Type/NonAcceptingNeverType.phpR~hjE3src/Type/ConstantTypeHelper.php R~hj D㫤src/Type/MixedType.php8R~hj81src/Type/CircularTypeAliasDefinitionException.phpR~hjűä&src/Type/TypeAliasResolverProvider.phpR~hj!nsrc/Type/OffsetAccessType.php R~hj <'src/Type/NonexistentParentClassType.phpR~hjz(src/Type/GenericTypeVariableResolver.phpR~hj0?(src/Type/ParserNodeTypeToPHPStanType.phpR~hj2src/Type/AcceptsResult.php R~hj x|wsrc/Type/SubtractableType.phpR~hj6src/Type/Php/PregFilterFunctionReturnTypeExtension.phpR~hj|7src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.phpR~hj$Ұ4src/Type/Php/PregSplitDynamicReturnTypeExtension.phpsR~hjs1src/Type/Php/RoundFunctionReturnTypeExtension.php R~hj Mcw9src/Type/Php/DateTimeCreateDynamicReturnTypeExtension.php.R~hj.(1[:src/Type/Php/IsIterableFunctionTypeSpecifyingExtension.php.R~hj.R3:src/Type/Php/GetDefinedVarsFunctionReturnTypeExtension.phpR~hj {-src/Type/Php/ThrowableReturnTypeExtension.phpR~hjs@src/Type/Php/ArrayPointerFunctionsDynamicReturnTypeExtension.phpR~hjuC:src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php R~hj {`֤7src/Type/Php/TriggerErrorDynamicReturnTypeExtension.phpR~hjq=src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.phpR~hjlӤ@src/Type/Php/ReflectionFunctionConstructorThrowTypeExtension.phpjR~hjj23src/Type/Php/DateTimeDynamicReturnTypeExtension.php;R~hj;00*src/Type/Php/IniGetReturnTypeExtension.phpR~hjWN>src/Type/Php/ArrayChangeKeyCaseFunctionReturnTypeExtension.phpR~hjy-l?src/Type/Php/StrWordCountFunctionDynamicReturnTypeExtension.php$R~hj$|45src/Type/Php/ArrayFindFunctionReturnTypeExtension.php3R~hj3S-src/Type/Php/DateFunctionReturnTypeHelper.phpR~hjݠ_@src/Type/Php/MbSubstituteCharacterDynamicReturnTypeExtension.php\R~hj\ )6src/Type/Php/DefineConstantTypeSpecifyingExtension.phpR~hj^/src/Type/Php/PowFunctionReturnTypeExtension.php{R~hj{_ڤ9src/Type/Php/ArgumentBasedFunctionReturnTypeExtension.php R~hj x:src/Type/Php/HighlightStringDynamicReturnTypeExtension.phpR~hjk8Asrc/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php R~hj 7src/Type/Php/DefinedConstantTypeSpecifyingExtension.phpR~hjӰ3src/Type/Php/GetClassDynamicReturnTypeExtension.php% R~hj% wϡ:src/Type/Php/DateIntervalConstructorThrowTypeExtension.phpR~hjP476src/Type/Php/ClosureBindDynamicReturnTypeExtension.phpR~hj]9src/Type/Php/GetCalledClassDynamicReturnTypeExtension.phpR~hj*1src/Type/Php/SubstrDynamicReturnTypeExtension.phpoR~hjofڤ>src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.phpf R~hjf 3src/Type/Php/PregMatchParameterOutTypeExtension.phphR~hjhH 1src/Type/Php/LtrimFunctionReturnTypeExtension.php[R~hj[ILɤ;src/Type/Php/ParseUrlFunctionDynamicReturnTypeExtension.phpR~hjΉ<src/Type/Php/ArrayKeysFunctionDynamicReturnTypeExtension.php:R~hj:0~8src/Type/Php/ArrayKeyFirstDynamicReturnTypeExtension.phpR~hjyZ9src/Type/Php/DatePeriodConstructorReturnTypeExtension.php$ R~hj$ mFܤ4src/Type/Php/ArrayMapFunctionReturnTypeExtension.phpmR~hjmvaAsrc/Type/Php/GetParentClassDynamicFunctionReturnTypeExtension.php R~hj #hŤ9src/Type/Php/FilterVarArrayDynamicReturnTypeExtension.php R~hj Gv8src/Type/Php/ClosureBindToDynamicReturnTypeExtension.phpR~hj2src/Type/Php/StrlenFunctionReturnTypeExtension.php R~hj S]4src/Type/Php/MethodExistsTypeSpecifyingExtension.phpR~hj̓98src/Type/Php/StrvalFamilyFunctionReturnTypeExtension.phpR~hjа6src/Type/Php/AssertFunctionTypeSpecifyingExtension.phpR~hj&f6src/Type/Php/DateFormatFunctionReturnTypeExtension.phpR~hj¥Cs4src/Type/Php/FilterVarDynamicReturnTypeExtension.phpR~hj7!4src/Type/Php/ArrayPopFunctionReturnTypeExtension.phpR~hjƤ0src/Type/Php/IsAFunctionTypeSpecifyingHelper.php R~hj 2ζ2src/Type/Php/StrPadFunctionReturnTypeExtension.php) R~hj) apAsrc/Type/Php/StrIncrementDecrementFunctionReturnTypeExtension.phpR~hj*Z>src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php&R~hj&O 7src/Type/Php/ArrayReduceFunctionReturnTypeExtension.phpR~hj{uAsrc/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.phpR~hj-rJ'src/Type/Php/RegexArrayShapeMatcher.phpDR~hjD>src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php} R~hj} *Τ6src/Type/Php/DateTimeConstructorThrowTypeExtension.phpR~hj4src/Type/Php/ConstantFunctionReturnTypeExtension.phpR~hjԤ>src/Type/Php/ArrayValuesFunctionDynamicReturnTypeExtension.php@R~hj@E"?=src/Type/Php/ReflectionClassConstructorThrowTypeExtension.php&R~hj&9;src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.phpR~hj-ۤ?src/Type/Php/Base64DecodeDynamicFunctionReturnTypeExtension.phpR~hjgR8src/Type/Php/GetDebugTypeFunctionReturnTypeExtension.phpR~hjL5src/Type/Php/StrRepeatFunctionReturnTypeExtension.phpR~hj8 7src/Type/Php/DateTimeModifyMethodThrowTypeExtension.phpR~hj1-3src/Type/Php/CompactFunctionReturnTypeExtension.phpt R~hjt bj2src/Type/Php/DateTimeModifyReturnTypeExtension.php9 R~hj9 w;src/Type/Php/IteratorToArrayFunctionReturnTypeExtension.phpaR~hjamUBɤ8src/Type/Php/ArrayFindKeyFunctionReturnTypeExtension.php+R~hj+*":src/Type/Php/DioStatDynamicFunctionReturnTypeExtension.phpR~hj )src/Type/Php/AssertThrowTypeExtension.php$R~hj$M>src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php~R~hj~{s$4src/Type/Php/ArrayNextDynamicReturnTypeExtension.phpR~hj*E8src/Type/Php/OpenSslEncryptParameterOutTypeExtension.php R~hj U3src/Type/Php/GettypeFunctionReturnTypeExtension.phpF R~hjF 1Ŗ6src/Type/Php/ArrayShiftFunctionReturnTypeExtension.phpR~hj5l7src/Type/Php/DateIntervalDynamicReturnTypeExtension.phpR~hjqM>;src/Type/Php/PathinfoFunctionDynamicReturnTypeExtension.php R~hj U8src/Type/Php/ArrayReverseFunctionReturnTypeExtension.phpR~hj"ˤ:src/Type/Php/ExplodeFunctionDynamicReturnTypeExtension.php R~hj f*@src/Type/Php/ReflectionPropertyConstructorThrowTypeExtension.php R~hj 7src/Type/Php/ArraySpliceFunctionReturnTypeExtension.phpR~hjn>src/Type/Php/CurlGetinfoFunctionDynamicReturnTypeExtension.phpR~hjx!5src/Type/Php/StrtotimeFunctionReturnTypeExtension.php R~hj 1)S2src/Type/Php/HrtimeFunctionReturnTypeExtension.phpR~hj>src/Type/Php/SimpleXMLElementConstructorThrowTypeExtension.phpwR~hjwtZˤ6src/Type/Php/ArraySliceFunctionReturnTypeExtension.phpyR~hjyX9src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.phpg R~hjg ns5src/Type/Php/ArrayFillFunctionReturnTypeExtension.php) R~hj) b1src/Type/Php/XMLReaderOpenReturnTypeExtension.phpR~hjh2src/Type/Php/StrrevFunctionReturnTypeExtension.php R~hj -5src/Type/Php/StrContainingTypeSpecifyingExtension.php R~hj s*0src/Type/Php/DsMapDynamicReturnTypeExtension.php:R~hj:̢8src/Type/Php/PregReplaceCallbackClosureTypeExtension.phpR~hj ?src/Type/Php/GettimeofdayDynamicFunctionReturnTypeExtension.phpJR~hjJR>7src/Type/Php/TrimFunctionDynamicReturnTypeExtension.phpR~hjv5src/Type/Php/RandomIntFunctionReturnTypeExtension.php R~hj ߻4+Asrc/Type/Php/SimpleXMLElementClassPropertyReflectionExtension.phpR~hj?@6src/Type/Php/BcMathStringOrNullReturnTypeExtension.phpj(R~hjj(WYB4src/Type/Php/ArrayFilterFunctionReturnTypeHelper.php1R~hj1! K4src/Type/Php/MbStrlenFunctionReturnTypeExtension.phpR~hj^Yܤ6src/Type/Php/PropertyExistsTypeSpecifyingExtension.php R~hj /m5src/Type/Php/MicrotimeFunctionReturnTypeExtension.phpR~hj¤5src/Type/Php/ArrayFlipFunctionReturnTypeExtension.php R~hj VQ6src/Type/Php/AbsFunctionDynamicReturnTypeExtension.phpR~hjD2src/Type/Php/MinMaxFunctionReturnTypeExtension.php R~hj wl?src/Type/Php/SimpleXMLElementXpathMethodReturnTypeExtension.phpR~hjY?/3src/Type/Php/IsAFunctionTypeSpecifyingExtension.phpH R~hjH ΃eCsrc/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.phpR~hj,Ф;src/Type/Php/ArraySumFunctionDynamicReturnTypeExtension.phpR~hjVN5src/Type/Php/CountFunctionTypeSpecifyingExtension.phpR~hjbQ/src/Type/Php/MbFunctionsReturnTypeExtension.php R~hj `,0src/Type/Php/DateFunctionReturnTypeExtension.phpR~hjDԤ4src/Type/Php/StrCaseFunctionsReturnTypeExtension.php,R~hj,Bsrc/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php/ R~hj/ ⩏;src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.phpR~hj j8src/Type/Php/ArrayReplaceFunctionReturnTypeExtension.phpjR~hjjbp:src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php R~hj W4src/Type/Php/MbFunctionsReturnTypeExtensionTrait.phpR~hjo% 9?src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.phpR~hj vQ4src/Type/Php/StrSplitFunctionReturnTypeExtension.phpR~hj*4src/Type/Php/DateFormatMethodReturnTypeExtension.php&R~hj&9Ӥ9src/Type/Php/ArrayFillKeysFunctionReturnTypeExtension.phpFR~hjFCl 5src/Type/Php/DsMapDynamicMethodThrowTypeExtension.phpR~hj fS?src/Type/Php/SimpleXMLElementAsXMLMethodReturnTypeExtension.php;R~hj;OX-?src/Type/Php/BackedEnumFromMethodDynamicReturnTypeExtension.phpz R~hjz 5src/Type/Php/ArrayRandFunctionReturnTypeExtension.php!R~hj!`>src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.phpAR~hjA /src/Type/Php/StatDynamicReturnTypeExtension.phpnR~hjnڤPD'src/Type/Php/JsonThrowTypeExtension.phpNR~hjND+26src/Type/Php/FilterInputDynamicReturnTypeExtension.phpR~hj^(Ȥ7src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php; R~hj; G1src/Type/Php/CountFunctionReturnTypeExtension.phpR~hjj.m)src/Type/Php/IntdivThrowTypeExtension.phpgR~hjgC;src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.phpR~hjcQK;src/Type/Php/ClassImplementsFunctionReturnTypeExtension.php{R~hj{c%w7src/Type/Php/ArrayFilterFunctionReturnTypeExtension.phpR~hjov1src/Type/Php/RangeFunctionReturnTypeExtension.php5R~hj5 3src/Type/Php/ImplodeFunctionReturnTypeExtension.phpR~hjy4src/Type/Php/DateTimeSubMethodThrowTypeExtension.php R~hj դ1src/Type/Php/HashFunctionsReturnTypeExtension.php@R~hj@"D3src/Type/Php/ArrayKeyDynamicReturnTypeExtension.phpR~hj*1==src/Type/Php/MbConvertEncodingFunctionReturnTypeExtension.phpR~hjg#2src/Type/Php/ParseStrParameterOutTypeExtension.phpR~hjǬ7src/Type/Php/ArrayColumnFunctionReturnTypeExtension.phpR~hjI[Ф<src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php R~hj *٤8src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php^R~hj^¤=src/Type/Php/ArrayIntersectKeyFunctionReturnTypeExtension.phpR~hjmBsrc/Type/Php/ConstantHelper.phpZR~hjZt9;src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.phpHR~hjHkԤ1src/Type/Php/PregMatchTypeSpecifyingExtension.php4 R~hj4 iKsrc/Type/ThisType.php? R~hj? w- src/Type/BenevolentUnionType.phpR~hjDfr0src/Type/MethodParameterClosureTypeExtension.phpsR~hjsMҌ4src/Type/ExpressionTypeResolverExtensionRegistry.php'R~hj'ynsrc/Type/TypehintHelper.php%R~hj%Z},src/Type/MethodParameterOutTypeExtension.phpR~hj src/Type/ClosureTypeFactory.phplR~hjl?ݤsrc/Type/LateResolvableType.phpR~hj1src/Type/ResourceType.phpw R~hjw ,src/Type/DynamicMethodThrowTypeExtension.phpgR~hjgޭ^8src/Type/StringAlwaysAcceptingObjectWithToStringType.phpR~hjY 9src/Type/CallableTypeHelper.phpR~hj"Tʤsrc/Type/CompoundType.phpR~hjU*src/Type/MethodTypeSpecifyingExtension.php'R~hj'T\0esrc/Type/Type.php0R~hj0$F4src/Type/OperatorTypeSpecifyingExtensionRegistry.php R~hj 46src/Type/StaticMethodParameterClosureTypeExtension.phpR~hjc}B0src/Type/Traits/UndecidedComparisonTypeTrait.phpR~hjn-src/Type/Traits/UndecidedBooleanTypeTrait.phpR~hjȷ*src/Type/Traits/FalseyBooleanTypeTrait.phpR~hj4k1%src/Type/Traits/NonArrayTypeTrait.phpR~hj݄#*src/Type/Traits/TruthyBooleanTypeTrait.phpR~hj &src/Type/Traits/NonObjectTypeTrait.phpu R~hju B'src/Type/Traits/MaybeArrayTypeTrait.phpR~hj{*src/Type/Traits/NonRemoveableTypeTrait.phpR~hj4i8+src/Type/Traits/LateResolvableTypeTrait.php=R~hj=: *src/Type/Traits/MaybeIterableTypeTrait.phpIR~hjI-src/Type/Traits/NonGeneralizableTypeTrait.phpR~hjf7ݤ0src/Type/Traits/NonOffsetAccessibleTypeTrait.phpR~hj*src/Type/Traits/MaybeCallableTypeTrait.phpR~hj+src/Type/Traits/ConstantScalarTypeTrait.php6R~hj6z;r1(src/Type/Traits/NonIterableTypeTrait.phpR~hj. |2src/Type/Traits/MaybeOffsetAccessibleTypeTrait.phpxR~hjx6src/Type/Traits/ConstantNumericComparisonTypeTrait.php) R~hj) 58src/Type/Traits/UndecidedComparisonCompoundTypeTrait.phpR~hj#src/Type/Traits/ObjectTypeTrait.php{R~hj{s>0(src/Type/Traits/MaybeObjectTypeTrait.php R~hj 2{(src/Type/Traits/NonCallableTypeTrait.phpR~hjզ['src/Type/Traits/NonGenericTypeTrait.phpR~hjށsrc/Type/IntersectionType.php\R~hj\Ww&src/Type/SimultaneousTypeTraverser.phpR~hj,դ%src/Broker/ClassNotFoundException.phpR~hj^zߤ'src/Broker/AnonymousClassNameHelper.phpR~hjk0<(src/Broker/ClassAutoloadingException.phpR~hj!uV(src/Broker/ConstantNotFoundException.phpR~hjcH(src/Broker/FunctionNotFoundException.phpR~hjrsrc/Broker/Broker.phpR~hj&src/Broker/BrokerFactory.phpR~hj6QΗ4src/PhpDoc/NameScopeAlreadyBeingCreatedException.phpR~hj//>src/PhpDoc/DirectTypeNodeResolverExtensionRegistryProvider.php&R~hj& Nsrc/PhpDoc/TypeNodeResolver.phpR~hjz/"src/PhpDoc/ResolvedPhpDocBlock.phpҙR~hjҙ8'src/PhpDoc/DefaultStubFilesProvider.php R~hj Pۤsrc/PhpDoc/Tag/PropertyTag.phpR~hj %src/PhpDoc/Tag/TypeAliasImportTag.php8R~hj8Atw src/PhpDoc/Tag/ImplementsTag.php_R~hj_%A;src/PhpDoc/Tag/AssertTag.php R~hj 3src/PhpDoc/Tag/ParamOutTag.phpR~hj~m;src/PhpDoc/Tag/UsesTag.phpYR~hjY{02!src/PhpDoc/Tag/SelfOutTypeTag.php R~hj src/PhpDoc/Tag/TemplateTag.phpbR~hjbasrc/PhpDoc/Tag/TypeAliasTag.php?R~hj?%src/PhpDoc/Tag/MethodTagParameter.phpR~hjP4(src/Process/ProcessCanceledException.phpR~hjw@Xsrc/Process/ProcessHelper.phpY R~hjY }src/Process/ProcessPromise.phpz R~hjz }p'src/Process/ProcessCrashedException.phpR~hj &Ф+src/Classes/ForbiddenClassNameExtension.phpLR~hjL}жsrc/Rules/TipRuleError.phpR~hj|src/Rules/AttributesCheck.phplR~hjlF[)src/Rules/Api/ApiInterfaceExtendsRule.php) R~hj) z6ݤ%src/Rules/Api/ApiClassExtendsRule.php R~hj R4src/Rules/Api/RuntimeReflectionInstantiationRule.php: R~hj: Mh%(src/Rules/Api/ApiClassConstFetchRule.phpf R~hjf _2z!src/Rules/Api/ApiTraitUseRule.phpR~hjL5src/Rules/Api/NodeConnectingVisitorAttributesRule.php R~hj `b7src/Rules/Api/PhpStanNamespaceIn3rdPartyPackageRule.php R~hj Hä#src/Rules/Api/ApiMethodCallRule.php> R~hj> +`|#src/Rules/Api/ApiStaticCallRule.php R~hj (src/Rules/Api/ApiClassImplementsRule.php+ R~hj+ Y/src/Rules/Api/RuntimeReflectionFunctionRule.phpR~hjU src/Rules/Api/ApiRuleHelper.phph R~hjh 1J'src/Rules/Api/ApiInstanceofTypeRule.php<R~hj<&src/Rules/Api/BcUncoveredInterface.phpR~hj ٤&src/Rules/Api/ApiInstantiationRule.php R~hj ױ#src/Rules/Api/ApiInstanceofRule.php[R~hj[jlZ%src/Rules/Api/GetTemplateTypeRule.php R~hj )src/Rules/Ignore/IgnoreParseErrorRule.phpBR~hjBb-src/Rules/DirectRegistry.php%R~hj%u6src/Rules/Properties/TypesAssignedToPropertiesRule.php R~hj >>1src/Rules/Properties/PropertyReflectionFinder.phpR~hj0src/Rules/Properties/FoundPropertyReflection.php0R~hj0_HĤ;src/Rules/Properties/ReadOnlyByPhpDocPropertyAssignRule.phpR~hjzAsrc/Rules/Properties/LazyReadWritePropertiesExtensionProvider.phpR~hjÁ=src/Rules/Properties/ReadWritePropertiesExtensionProvider.php.R~hj._:src/Rules/Properties/MissingReadOnlyPropertyAssignRule.phpO R~hjO my8src/Rules/Properties/ExistingClassesInPropertiesRule.phpR~hjyt2src/Rules/Properties/UninitializedPropertyRule.phpR~hj:UpФ2src/Rules/Properties/NullsafePropertyFetchRule.php R~hj :̑-src/Rules/Properties/AccessPropertiesRule.php6R~hj6٤6src/Rules/Properties/ReadOnlyPropertyAssignRefRule.php<R~hj<Bsrc/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php)R~hj)[-src/Rules/Properties/ReadOnlyPropertyRule.phpR~hj84src/Rules/Properties/MissingPropertyTypehintRule.phpB R~hjB H;src/Rules/Properties/AccessStaticPropertiesInAssignRule.phpR~hj.ڤ5src/Rules/Properties/ReadOnlyByPhpDocPropertyRule.phpR~hj۫G3src/Rules/Properties/ReadOnlyPropertyAssignRule.phpR~hjS5src/Rules/Properties/AccessPropertiesInAssignRule.phpR~hj)Bsrc/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRule.php R~hj ź/src/Rules/Properties/PropertyAttributesRule.phpR~hjr78src/Rules/Properties/InvalidCallablePropertyTypeRule.phpR~hjh/src/Rules/Properties/OverridingPropertyRule.php R~hj "ؤ+src/Rules/Properties/PropertyDescriptor.phpR~hjOVQ2src/Rules/Properties/PropertiesInInterfaceRule.phpR~hjZ鎤8src/Rules/Properties/WritingToReadOnlyPropertiesRule.phpR~hj8Ġ3src/Rules/Properties/AccessStaticPropertiesRule.phpE"R~hjE"1u7src/Rules/Properties/ReadingWriteOnlyPropertiesRule.phpR~hj@Csrc/Rules/Properties/DirectReadWritePropertiesExtensionProvider.phphR~hjhe*5src/Rules/Properties/ReadWritePropertiesExtension.phpR~hj>src/Rules/Properties/ReadOnlyByPhpDocPropertyAssignRefRule.phpxR~hjx1?src/Rules/Properties/AccessPrivatePropertyThroughStaticRule.php=R~hj=uɤ(src/Rules/PhpDoc/RequireExtendsCheck.phpD R~hjD 5.src/Rules/PhpDoc/InvalidPhpDocTagValueRule.phpR~hj/src/Rules/PhpDoc/IncompatiblePhpDocTypeRule.phpc.R~hjc.)A39src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php R~hj qf<src/Rules/PhpDoc/IncompatibleClassConstantPhpDocTypeRule.php R~hj j逘6src/Rules/PhpDoc/FunctionConditionalReturnTypeRule.phpR~hjF9src/Rules/PhpDoc/RequireImplementsDefinitionClassRule.phpR~hj[)src/Rules/PhpDoc/VarTagTypeRuleHelper.phpJ#R~hjJ#]E4src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.phpR~hjyƐ6src/Rules/PhpDoc/RequireExtendsDefinitionTraitRule.php R~hj FC=.src/Rules/PhpDoc/GenericCallableRuleHelper.phpR~hj -src/Rules/PhpDoc/InvalidPHPStanDocTagRule.phpR~hjaB6src/Rules/PhpDoc/RequireExtendsDefinitionClassRule.php0R~hj0BF1src/Rules/PhpDoc/InvalidThrowsPhpDocValueRule.php R~hj #+src/Rules/PhpDoc/UnresolvableTypeHelper.phpER~hjE u%src/Rules/PhpDoc/PhpDocLineHelper.php:R~hj:6}4src/Rules/PhpDoc/VarTagChangedExpressionTypeRule.phphR~hjhˊ0src/Rules/PhpDoc/IncompatibleSelfOutTypeRule.phpd R~hjd O'src/Rules/PhpDoc/FunctionAssertRule.phpR~hjU֤0src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.phpR~hjQգ2src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php6R~hj6laDsrc/Rules/PhpDoc/IncompatibleParamImmediatelyInvokedCallableRule.php R~hj U%src/Rules/PhpDoc/AssertRuleHelper.php%R~hj%vZ%src/Rules/PhpDoc/MethodAssertRule.phpR~hjχ4src/Rules/PhpDoc/MethodConditionalReturnTypeRule.phpR~hj!̷ܤ7src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.phpR~hjޤ%src/Rules/RuleErrors/RuleError113.phpXR~hjXkOȜ%src/Rules/RuleErrors/RuleError111.php<R~hj<g0!:#src/Rules/RuleErrors/RuleError3.phpR~hj``$src/Rules/RuleErrors/RuleError75.phpR~hj䎀$src/Rules/RuleErrors/RuleError61.phpR~hjyY#src/Rules/RuleErrors/RuleError5.phpR~hjk*$src/Rules/RuleErrors/RuleError27.phpR~hjG:$src/Rules/RuleErrors/RuleError55.phpR~hjti%src/Rules/RuleErrors/RuleError105.php5R~hj5b0$src/Rules/RuleErrors/RuleError41.phpR~hjy{z$src/Rules/RuleErrors/RuleError73.phpQR~hjQUq<$src/Rules/RuleErrors/RuleError29.php<R~hj<F$src/Rules/RuleErrors/RuleError97.phpR~hj B$src/Rules/RuleErrors/RuleError13.phpjR~hjjŤ%src/Rules/RuleErrors/RuleError103.phpR~hj$src/Rules/RuleErrors/RuleError19.phpR~hj.~U#src/Rules/RuleErrors/RuleError7.phphR~hjh%src/Rules/RuleErrors/RuleError115.phpR~hj |%src/Rules/RuleErrors/RuleError123.phpR~hj$src/Rules/RuleErrors/RuleError51.phpR~hj0%src/Rules/RuleErrors/RuleError121.phpR~hj2 ܤ$src/Rules/RuleErrors/RuleError93.php|R~hj|J $src/Rules/RuleErrors/RuleError83.php"R~hj"S$src/Rules/RuleErrors/RuleError45.phpMR~hjM;$src/Rules/RuleErrors/RuleError49.phpR~hj+ݫ`$src/Rules/RuleErrors/RuleError69.phpR~hjR%%src/Rules/RuleErrors/RuleError119.php_R~hj_y%src/Rules/RuleErrors/RuleError125.php`R~hj`+$src/Rules/RuleErrors/RuleError15.phpR~hj$src/Rules/RuleErrors/RuleError85.phpR~hj@9$src/Rules/RuleErrors/RuleError39.phpLR~hjL $src/Rules/RuleErrors/RuleError31.phpR~hjȵ$src/Rules/RuleErrors/RuleError71.phpR~hjⳠ$src/Rules/RuleErrors/RuleError11.phpR~hj3J$src/Rules/RuleErrors/RuleError57.phpR~hjc $src/Rules/RuleErrors/RuleError99.php3R~hj3?$src/Rules/RuleErrors/RuleError25.phpR~hj-$Ť$src/Rules/RuleErrors/RuleError81.phptR~hjtȃe$src/Rules/RuleErrors/RuleError63.phpR~hjiL$src/Rules/RuleErrors/RuleError21.phpR~hjR#x%src/Rules/RuleErrors/RuleError127.phpR~hjV`L$src/Rules/RuleErrors/RuleError37.phpR~hjb $src/Rules/RuleErrors/RuleError91.phpR~hj *$src/Rules/RuleErrors/RuleError87.php{R~hj{oY%src/Rules/RuleErrors/RuleError107.phpR~hjU)$src/Rules/RuleErrors/RuleError65.phpR~hj<$src/Rules/RuleErrors/RuleError53.phppR~hjpJ*$src/Rules/RuleErrors/RuleError23.php;R~hj;[D$src/Rules/RuleErrors/RuleError33.phpER~hjE M$src/Rules/RuleErrors/RuleError59.phptR~hjt#src/Rules/RuleErrors/RuleError9.phpR~hjq&$src/Rules/RuleErrors/RuleError77.phpR~hjFTФ$src/Rules/RuleErrors/RuleError17.php4R~hj4ȹsrc/Rules/Rule.phpR~hjYړ.src/Rules/EnumCases/EnumCaseAttributesRule.phpR~hj8]*)src/Rules/Classes/AllowedSubTypesRule.php R~hj 7D3src/Rules/Classes/DuplicateClassDeclarationRule.php R~hj 1=L;src/Rules/Classes/ExistingClassesInInterfaceExtendsRule.php R~hj '21#src/Rules/Classes/NewStaticRule.phpR~hjO%src/Rules/Classes/PropertyTagRule.phpR~hj?&src/Rules/Classes/PropertyTagCheck.php\'R~hj\' 9$src/Rules/Classes/MixinTraitRule.phpwR~hjw5src/Rules/Classes/UnusedConstructorParametersRule.phpR~hj src/Rules/Classes/MixinCheck.phpR~hj߫.src/Rules/Classes/ImpossibleInstanceOfRule.phpR~hjwO3src/Rules/Classes/ExistingClassInInstanceOfRule.php R~hj @.'src/Rules/Classes/ClassConstantRule.phpR~hj`ä*src/Rules/Classes/PropertyTagTraitRule.phpR~hj'src/Rules/Classes/ReadOnlyClassRule.phpR~hj iB-src/Rules/Classes/PropertyTagTraitUseRule.phpR~hjwbv(src/Rules/Classes/MethodTagTraitRule.phpR~hjjyK2src/Rules/Classes/LocalTypeTraitUseAliasesRule.phpR~hj_v<src/Rules/Classes/AccessPrivateConstantThroughStaticRule.phpR~hj⌵1src/Rules/Classes/ClassConstantAttributesRule.php$R~hj$p0src/Rules/Classes/NonClassAttributeClassRule.phpfR~hjf-Y#src/Rules/Classes/MethodTagRule.phpR~hjF)src/Rules/Classes/ClassAttributesRule.phpRR~hjRcx-src/Rules/Classes/TraitAttributeClassRule.phpPR~hjPE\w$src/Rules/Classes/MethodTagCheck.phpH/R~hjH/}9(src/Rules/Classes/RequireExtendsRule.phpR~hjәi/src/Rules/Classes/InstantiationCallableRule.phpR~hjݦ3src/Rules/Classes/InvalidPromotedPropertiesRule.php R~hj cؕ'src/Rules/Classes/InstantiationRule.php $R~hj $fX:src/Rules/Classes/ExistingClassesInClassImplementsRule.php5 R~hj5 ^.+src/Rules/Classes/RequireImplementsRule.phpR~hjʤ9src/Rules/Classes/ExistingClassesInEnumImplementsRule.php R~hj aV*src/Rules/Classes/LocalTypeAliasesRule.phpR~hjUG}.src/Rules/Classes/DuplicateDeclarationRule.phpR~hj/ 1src/Rules/Classes/ExistingClassInTraitUseRule.php R~hj BկԤ$src/Rules/Classes/EnumSanityRule.php^R~hj^85src/Rules/Classes/ExistingClassInClassExtendsRule.php+R~hj+"Pw-+src/Rules/Classes/MethodTagTraitUseRule.phpR~hj)D'src/Rules/Classes/MixinTraitUseRule.phpR~hj~+src/Rules/Classes/LocalTypeAliasesCheck.php6;R~hj6;(usrc/Rules/Classes/MixinRule.phpR~hjc/src/Rules/Classes/LocalTypeTraitAliasesRule.phpR~hj{ج+src/Rules/Types/InvalidTypesInUnionRule.phpL R~hjL K0src/Rules/FileRuleError.phpR~hj!v*src/Rules/Generators/YieldFromTypeRule.php"R~hj"QҤ&src/Rules/Generators/YieldTypeRule.phpU R~hjU b-src/Rules/Generators/YieldInGeneratorRule.php"R~hj"}! ,src/Rules/Methods/FinalPrivateMethodRule.phpR~hj'ߙ/src/Rules/Methods/AlwaysUsedMethodExtension.phpKR~hjKGe;src/Rules/Methods/LazyAlwaysUsedMethodExtensionProvider.phpR~hjܤ=src/Rules/Methods/DirectAlwaysUsedMethodExtensionProvider.phpR~hjA/src/Rules/Methods/ConstructorReturnTypeRule.phpR~hj:m6src/Rules/Methods/IllegalConstructorMethodCallRule.phpR~hjx</src/Rules/Methods/ConsistentConstructorRule.php6R~hj6>Ф.src/Rules/Methods/StaticMethodCallableRule.php<R~hj<n,src/Rules/Methods/NullsafeMethodCallRule.phppR~hjpu(Ť:src/Rules/Methods/MissingMagicSerializationMethodsRule.php R~hj )Fsrc/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.phpR~hjцꑤ8src/Rules/Methods/CallPrivateMethodThroughStaticRule.phpR~hj1y $src/Rules/Methods/ReturnTypeRule.phpR~hjDۊ*src/Rules/Methods/MethodAttributesRule.phpR~hjU95src/Rules/Methods/MissingMethodReturnTypehintRule.php R~hj g7Gsrc/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.phpI R~hjI +src/Rules/Methods/CallStaticMethodsRule.php R~hj ӆ5src/Rules/Methods/MissingMethodImplementationRule.phpR~hj}Ť7src/Rules/Methods/AlwaysUsedMethodExtensionProvider.php)R~hj)E)src/Rules/Methods/MethodSignatureRule.php.R~hj.)[2src/Rules/Methods/MissingMethodSelfOutTypeRule.phpM R~hjM p~4src/Rules/Methods/ExistingClassesInTypehintsRule.phpR~hjj3 (src/Rules/Methods/MethodCallableRule.phpR~hj^oN5src/Rules/Methods/MethodVisibilityInInterfaceRule.php?R~hj?/src/Rules/Methods/AbstractPrivateMethodRule.phpR~hj~)*src/Rules/Methods/OverridingMethodRule.php?R~hj? %%src/Rules/Methods/MethodCallCheck.phpR~hj:src/Rules/Methods/AbstractMethodInNonAbstractClassRule.phpSR~hjS Asrc/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php R~hj >[Ф+src/Rules/Methods/StaticMethodCallCheck.php'R~hj'_P5src/Rules/Methods/MethodParameterComparisonHelper.php8R~hj8?:src/Rules/Methods/IncompatibleDefaultParameterTypeRule.phpR~hj%src/Rules/Methods/CallMethodsRule.php R~hj Wb8src/Rules/Methods/MissingMethodParameterTypehintRule.phpR~hj@b6src/Rules/Methods/IllegalConstructorStaticCallRule.php R~hj %g%src/Rules/FunctionDefinitionCheck.phpfR~hjfUҤsrc/Rules/LazyRegistry.phpR~hjoϒ0src/Rules/Generics/InterfaceTemplateTypeRule.phpR~hja1(src/Rules/Generics/TemplateTypeCheck.php)'R~hj)'j֤,src/Rules/Generics/ClassTemplateTypeRule.phpR~hj訤4src/Rules/Generics/FunctionSignatureVarianceRule.phpR~hjjr2+src/Rules/Generics/PropertyVarianceRule.phpR~hj?,src/Rules/Generics/GenericAncestorsCheck.phpBR~hjBo?/src/Rules/Generics/FunctionTemplateTypeRule.php R~hj faI,1src/Rules/Generics/CrossCheckInterfacesHelper.php R~hj Ԥ-src/Rules/Generics/InterfaceAncestorsRule.php R~hj =ps%src/Rules/Generics/UsedTraitsRule.php R~hj [ ,src/Rules/Generics/TraitTemplateTypeRule.phpZ R~hjZ 3-src/Rules/Generics/MethodTemplateTypeRule.php)R~hj)<;)src/Rules/Generics/ClassAncestorsRule.phpR~hjxM7I-src/Rules/Generics/GenericObjectTypeCheck.phpR~hj-~ˤ$src/Rules/Generics/VarianceCheck.php,R~hj,%61src/Rules/Generics/MethodTagTemplateTypeCheck.php R~hj 0src/Rules/Generics/MethodTagTemplateTypeRule.phptR~hjtӛ:+src/Rules/Generics/EnumTemplateTypeRule.phpR~hj5src/Rules/Generics/MethodTagTemplateTypeTraitRule.php+R~hj++\(src/Rules/Generics/EnumAncestorsRule.phpn R~hjn ۻ2src/Rules/Generics/MethodSignatureVarianceRule.php R~hj  &src/Rules/Debug/DumpPhpDocTypeRule.php*R~hj*zB"src/Rules/Debug/DebugScopeRule.phpHR~hjH  src/Rules/Debug/DumpTypeRule.phpR~hjӤ"src/Rules/Debug/FileAssertRule.phpR~hj~src/Rules/IssetCheck.php/R~hj/c쑤1src/Rules/Regexp/RegularExpressionPatternRule.phpR~hjŜ)1src/Rules/Regexp/RegularExpressionQuotingRule.phpR~hj]pĤ4src/Rules/Namespaces/ExistingNamesInGroupUseRule.phpR~hj6/src/Rules/Namespaces/ExistingNamesInUseRule.phphR~hjhI'src/Rules/Missing/MissingReturnRule.phppR~hjp6src/Rules/MetadataRuleError.phpR~hjh+src/Rules/Whitespace/FileWhitespaceRule.php_ R~hj_ դEsrc/Rules/DeadCode/CallToFunctionStatementWithoutImpurePointsRule.phpR~hj|/src/Rules/DeadCode/UnreachableStatementRule.phpR~hj!0src/Rules/DeadCode/UnusedPrivateConstantRule.phpTR~hjT8KHsrc/Rules/DeadCode/CallToConstructorStatementWithoutImpurePointsRule.phpR~hj Bsrc/Rules/DeadCode/NoopRule.phpR~hj6src/Rules/DeadCode/PossiblyPureStaticCallCollector.phpR~hjj/src/Rules/DeadCode/PossiblyPureNewCollector.php3R~hj3٤0src/Rules/DeadCode/UnusedPrivatePropertyRule.phpC!R~hjC!50.src/Rules/DeadCode/UnusedPrivateMethodRule.phpR~hj2>src/Rules/DeadCode/ConstructorWithoutImpurePointsCollector.phpR~hje;src/Rules/DeadCode/FunctionWithoutImpurePointsCollector.phpR~hjiIsrc/Rules/DeadCode/CallToStaticMethodStatementWithoutImpurePointsRule.phpR~hju9src/Rules/DeadCode/MethodWithoutImpurePointsCollector.phpR~hjCsrc/Rules/DeadCode/CallToMethodStatementWithoutImpurePointsRule.phphR~hjhʩ%src/Rules/DeadCode/BetterNoopRule.phpKR~hjK\6src/Rules/DeadCode/PossiblyPureMethodCallCollector.phpR~hj˒4src/Rules/DeadCode/PossiblyPureFuncCallCollector.phpR~hj+fY@src/Rules/TooWideTypehints/TooWideFunctionReturnTypehintRule.php R~hj Ĕ>src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.phpMR~hjMhݤEsrc/Rules/TooWideTypehints/TooWideArrowFunctionReturnTypehintRule.phpR~hj] WBsrc/Rules/TooWideTypehints/TooWideFunctionParameterOutTypeRule.phpR~hjg;src/Rules/TooWideTypehints/TooWideParameterOutTypeCheck.php? R~hj? o|?src/Rules/TooWideTypehints/TooWideClosureReturnTypehintRule.phpR~hji Ф@src/Rules/TooWideTypehints/TooWideMethodParameterOutTypeRule.phpR~hj͉6src/Rules/TooWideTypehints/TooWidePropertyTypeRule.phpR~hj;'6src/Rules/Operators/InvalidComparisonOperationRule.phpR~hj1src/Rules/Operators/InvalidUnaryOperationRule.php R~hj U`,src/Rules/Operators/InvalidAssignVarRule.php R~hj [2src/Rules/Operators/InvalidBinaryOperationRule.php#R~hj#'8P2src/Rules/Operators/InvalidIncDecOperationRule.phpR~hjn)iĤ,src/Rules/ParameterCastableToStringCheck.phpjR~hjjLsrc/Rules/NullsafeCheck.phpR~hjìsrc/Rules/ClassNameCheck.phpR~hjcHsrc/Rules/Registry.php'R~hj'*src/Rules/RuleLevelHelperAcceptsResult.phpR~hjzJ Bsrc/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.phpR~hjg .src/Rules/Exceptions/TooWideThrowTypeCheck.phpR~hjVѤ,src/Rules/Exceptions/ThrowExpressionRule.phpR~hj]5src/Rules/Exceptions/DefaultExceptionTypeResolver.phpR~hj#5src/Rules/Exceptions/CaughtExceptionExistenceRule.php R~hj ~w)=src/Rules/Exceptions/MissingCheckedExceptionInThrowsCheck.phpR~hj~Dsrc/Rules/Exceptions/MissingCheckedExceptionInFunctionThrowsRule.php}R~hj}煤*src/Rules/Exceptions/ThrowExprTypeRule.phpVR~hjVM(K.src/Rules/Exceptions/NoncapturingCatchRule.phpR~hj$5src/Rules/Exceptions/TooWideFunctionThrowTypeRule.phpZR~hjZSڱ7src/Rules/Exceptions/CatchWithUnthrownExceptionRule.phpTR~hjTX:src/Rules/Exceptions/OverwrittenExitPointByFinallyRule.php$R~hj$9}Esrc/Rules/Exceptions/ThrowsVoidFunctionWithExplicitThrowPointRule.php R~hj ӗ.src/Rules/Exceptions/ExceptionTypeResolver.phpR~hjsCsrc/Rules/Exceptions/ThrowsVoidMethodWithExplicitThrowPointRule.php R~hj /zh3src/Rules/Exceptions/TooWideMethodThrowTypeRule.phpR~hj_~,src/Rules/Keywords/RequireFileExistsRule.phpR~hj(.src/Rules/Keywords/ContinueBreakInLoopRule.phpR~hj0r-src/Rules/Keywords/DeclareStrictTypesRule.phpR~hj[B&src/Rules/Playground/NoPhpCodeRule.phpVR~hjV:E Ԥ-src/Rules/Playground/NotAnalysedTraitRule.phpR~hjZʆ*src/Rules/Playground/FunctionNeverRule.phpUR~hjU{٤(src/Rules/Playground/NeverRuleHelper.phpR~hj@.(src/Rules/Playground/MethodNeverRule.phpwR~hjw]r%src/Rules/FunctionReturnTypeCheck.phpP R~hjP Ȯsrc/Rules/RuleError.phpR~hjt@Ф'src/Rules/ClassCaseSensitivityCheck.phpR~hjP%src/Rules/ClassForbiddenNameCheck.php R~hj =s:src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.phpR~hjy.src/Rules/Arrays/InvalidKeyInArrayItemRule.phpR~hj>Zf'src/Rules/Arrays/EmptyArrayItemRule.php:R~hj:Yr:5src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.phpiR~hji P-src/Rules/Arrays/OffsetAccessAssignOpRule.php R~hj ,7($src/Rules/Arrays/DeadForeachRule.phpR~hjAȤ+src/Rules/Arrays/ArrayDestructuringRule.phpZ R~hjZ 1s*src/Rules/Arrays/IterableInForeachRule.phpBR~hjBpz9src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php R~hj r}{o*src/Rules/Arrays/AllowedArrayKeysTypes.php{ R~hj{ ~mB.src/Rules/Arrays/UnpackIterableInArrayRule.phpR~hjr-src/Rules/Arrays/AppendedArrayKeyTypeRule.php R~hj e'src/Rules/Arrays/ArrayUnpackingRule.phpgR~hjg⩤.src/Rules/Arrays/AppendedArrayItemTypeRule.php R~hj ģ4src/Rules/Arrays/OffsetAccessValueAssignmentRule.php R~hj UV/src/Rules/Arrays/OffsetAccessAssignmentRule.php R~hj :9src/Rules/Arrays/OffsetAccessWithoutDimForReadingRule.phpR~hj?2src/Rules/Arrays/InvalidKeyInArrayDimFetchRule.phpR~hjMGsrc/Rules/Comparison/NumberComparisonOperatorsConstantConditionRule.phpp R~hjp , 9src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php R~hj x8c=src/Rules/Comparison/TernaryOperatorConstantConditionRule.phpR~hj2< :src/Rules/Comparison/ImpossibleCheckTypeMethodCallRule.phpR~hj{2src/Rules/Comparison/ImpossibleCheckTypeHelper.php"FR~hj"FExǤ:src/Rules/Comparison/WhileLoopAlwaysFalseConditionRule.php2R~hj2P48src/Rules/Comparison/LogicalXorConstantConditionRule.phpR~hjI0src/Rules/Comparison/IfConstantConditionRule.phpR~hjEW@src/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRule.phpR~hjS=src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php=R~hj=;&9src/Rules/Comparison/DoWhileLoopConstantConditionRule.php R~hj Eb8src/Rules/Comparison/BooleanAndConstantConditionRule.phpR~hj8src/Rules/Comparison/BooleanNotConstantConditionRule.php R~hj Y]7src/Rules/Comparison/UsageOfVoidMatchExpressionRule.php"R~hj"<src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.phpQR~hjQQ4src/Rules/Comparison/ConstantLooseComparisonRule.phpR~hjDu Ӥ2src/Rules/Comparison/UnreachableIfBranchesRule.php R~hj cIK4src/Rules/Comparison/ConstantConditionRuleHelper.php R~hj k7src/Rules/Comparison/BooleanOrConstantConditionRule.phpR~hj kb4src/Rules/Comparison/ElseIfConstantConditionRule.php R~hj 9src/Rules/Comparison/UnreachableTernaryElseBranchRule.php R~hj ^,src/Rules/Comparison/MatchExpressionRule.php>R~hj>Y(@"src/Rules/MissingTypehintCheck.phpR~hjrc'src/Rules/DateTimeInstantiationRule.php/R~hj/+^src/Rules/Cast/PrintRule.phpYR~hjYQf¤ src/Rules/Cast/UnsetCastRule.phpR~hj|Ҥ"src/Rules/Cast/InvalidCastRule.php R~hj (y2src/Rules/Cast/InvalidPartOfEncapsedStringRule.phpR~hj<src/Rules/Cast/EchoRule.phpR~hjv<src/Rules/Functions/ImplodeParameterCastableToStringRule.php R~hj 3src/Rules/Functions/ArrowFunctionAttributesRule.php R~hj m0-src/Rules/Functions/UnusedClosureUsesRule.phpR~hjM<src/Rules/Functions/MissingFunctionParameterTypehintRule.phpR~hj{Esrc/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.phpHR~hjH'>5src/Rules/Functions/CallToNonExistentFunctionRule.php'R~hj'.Isrc/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRule.phpR~hjD,src/Rules/Functions/DefineParametersRule.phpR~hjx 6src/Rules/Functions/UselessFunctionReturnValueRule.php R~hj h59src/Rules/Functions/MissingFunctionReturnTypehintRule.php R~hj 8:+src/Rules/Functions/ParamAttributesRule.phpR~hjg$ϤCsrc/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRule.phpR~hjU$$src/Rules/Functions/PrintfHelper.php@ R~hj@ HL5src/Rules/Functions/ParameterCastableToStringRule.php R~hj 鸤)src/Rules/Functions/InnerFunctionRule.phpeR~hjeEl9src/Rules/Functions/SortParameterCastableToStringRule.phpR~hj2%l{&src/Rules/Functions/ReturnTypeRule.php(R~hj(t$7Ϥ?src/Rules/Functions/InvalidLexicalVariablesInClosureUseRule.phpR~hjdu<src/Rules/Functions/ArrowFunctionReturnNullsafeByRefRule.phpR~hj6 4src/Rules/Functions/CallToFunctionParametersRule.php R~hj -l-src/Rules/Functions/ClosureReturnTypeRule.php@R~hj@fn)src/Rules/Functions/CallCallablesRule.phpPR~hjP/src/Rules/Functions/ReturnNullsafeByRefRule.phpZR~hjZן6src/Rules/Functions/ExistingClassesInTypehintsRule.phpR~hjΤ-src/Rules/Functions/ClosureAttributesRule.phpR~hj7f93src/Rules/Functions/ArrowFunctionReturnTypeRule.phpR~hj\MCsrc/Rules/Functions/IncompatibleClosureDefaultParameterTypeRule.phpR~hjW)8src/Rules/Functions/DuplicateFunctionDeclarationRule.phpR~hj7ҭ'src/Rules/Functions/ArrayValuesRule.phpTR~hjT.+src/Rules/Functions/ImplodeFunctionRule.php R~hj CR/src/Rules/Functions/RedefinedParametersRule.phpR~hj4(src/Rules/Functions/CallUserFuncRule.php R~hj K9src/Rules/Functions/VariadicParametersDeclarationRule.php2R~hj2k.src/Rules/Functions/FunctionAttributesRule.phpR~hj'src/Rules/Functions/ArrayFilterRule.phpR~hj;.Ӥ,src/Rules/Functions/FunctionCallableRule.phpR~hj ֤,src/Rules/Functions/PrintfParametersRule.phps R~hjs G=src/Rules/Functions/ExistingClassesInClosureTypehintsRule.php\R~hj\(l1src/Rules/Functions/PrintfArrayParametersRule.phpR~hjۤ<src/Rules/Functions/IncompatibleDefaultParameterTypeRule.phpR~hjƈ/src/Rules/Functions/RandomIntParametersRule.phpR~hjsrc/Rules/ClassNameNodePair.phpR~hj$hͤsrc/Rules/FoundTypeResult.phpR~hjh[gsrc/Rules/RuleErrorBuilder.phpR~hj/)src/Rules/FunctionCallParametersCheck.phpdR~hjde#src/Rules/Pure/PureFunctionRule.phpR~hj=!src/Rules/Pure/PureMethodRule.phpR~hjۅ&src/Rules/Pure/FunctionPurityCheck.phpR~hj4src/Rules/Variables/ParameterOutAssignedTypeRule.php R~hj @%src/Rules/Variables/ThrowTypeRule.phpQR~hjQO,src/Rules/Variables/CompactVariablesRule.php R~hj A!src/Rules/Variables/UnsetRule.phpR~hjSY5+src/Rules/Variables/DefinedVariableRule.phpR~hj^ɤ+src/Rules/Variables/VariableCloningRule.phpR~hj-8src/Rules/Variables/ParameterOutExecutionEndTypeRule.phpR~hjjt(src/Rules/Variables/NullCoalesceRule.phpR~hj1T[!src/Rules/Variables/EmptyRule.phpUR~hjUeR!src/Rules/Variables/IssetRule.phpR~hj⿤!src/Rules/Names/UsedNamesRule.phpR~hjv#src/Rules/NonIgnorableRuleError.phpR~hj6y̤0src/Rules/Constants/ClassAsClassConstantRule.php}R~hj}Esrc/Rules/Constants/LazyAlwaysUsedClassConstantsExtensionProvider.php!R~hj!j0src/Rules/Constants/MagicConstantContextRule.phpvR~hjvɺ5src/Rules/Constants/DynamicClassConstantFetchRule.phpR~hj0a$src/Rules/Constants/ConstantRule.phpR~hjo^ک8src/Rules/Constants/ValueAssignedToClassConstantRule.phpR~hjY4src/Rules/Constants/NativeTypedClassConstantRule.phpR~hjxL.src/Rules/Constants/OverridingConstantRule.phpR~hjZk)src/Rules/Constants/FinalConstantRule.phpR~hja29src/Rules/Constants/AlwaysUsedClassConstantsExtension.phpR~hjޡr8src/Rules/Constants/MissingClassConstantTypehintRule.phpE R~hjE ݤAsrc/Rules/Constants/AlwaysUsedClassConstantsExtensionProvider.phpER~hjER?*src/Rules/Traits/ConstantsInTraitsRule.php*R~hj*٤)src/Rules/Traits/NotAnalysedTraitRule.phpR~hjx^*.src/Rules/Traits/TraitDeclarationCollector.php[R~hj[놤2src/Rules/Traits/ConflictingTraitConstantsRule.php#R~hj#$Pפ&src/Rules/Traits/TraitUseCollector.phpR~hj8+src/Rules/UnusedFunctionParametersCheck.php R~hj ʐԤsrc/Rules/RuleLevelHelper.phpMBR~hjMBxRG!src/Rules/IdentifierRuleError.phpR~hjMT3src/Rules/LineRuleError.phpR~hj[%7"src/Collectors/RegistryFactory.phpR~hjwʤsrc/Collectors/Registry.phpvR~hjv(src/Collectors/Collector.php R~hj ; src/Collectors/CollectedData.phpZR~hjZnasrc/File/FileExcluder.php^R~hj^:UHsrc/File/FileFinderResult.phpZR~hjZ {src/File/FileMonitor.phpSR~hjS>m $src/File/FuzzyRelativePathHelper.phpPR~hjP𜍤#src/File/FileExcluderRawFactory.phpR~hj) f.src/File/ParentDirectoryRelativePathHelper.phpR~hjBhsrc/File/RelativePathHelper.phpR~hj+l3src/File/SystemAgnosticSimpleRelativePathHelper.phpR~hjͤ%src/File/SimpleRelativePathHelper.php.R~hj.cq src/File/FileExcluderFactory.phpKR~hjK[#src/File/NullRelativePathHelper.phpR~hjz'src/File/CouldNotWriteFileException.phpR~hjsrc/File/FileMonitorResult.phpR~hj.src/File/FileWriter.phpR~hjR&src/File/CouldNotReadFileException.phpR~hjx1gsrc/File/FileFinder.phpR~hjiBsrc/File/FileReader.phpR~hjBWͤsrc/File/FileHelper.php R~hj @"src/File/PathNotFoundException.phpR~hjOJ5src/TrinaryLogic.phpR~hj3*src/Parser/CleaningParser.phpR~hjԱDsrc/Parser/SimpleParser.phpR~hjFasrc/Parser/CleaningVisitor.php\ R~hj\ H-src/Parser/TypeTraverserInstanceofVisitor.php(R~hj(QF/src/Parser/ImmediatelyInvokedClosureVisitor.phpR~hjŇo src/Parser/ClosureArgVisitor.phpR~hjgˤ%src/Parser/TraitCollectingVisitor.phpR~hj}4(Ĥ$src/Parser/ParserErrorsException.phpR~hj<)"src/Parser/TryCatchTypeVisitor.phpR~hjK>%src/Parser/ParentStmtTypesVisitor.phpnR~hjn &ܤ$src/Parser/AnonymousClassVisitor.phpfR~hjf,G+src/Parser/NewAssignedToPropertyVisitor.phpR~hjX#src/Parser/CurlSetOptArgVisitor.phpR~hjAc$src/Parser/ClosureBindArgVisitor.phpR~hj`isrc/Parser/CachedParser.php R~hj 64l*src/Parser/FunctionCallStatementFinder.phpR~hjJy%src/Parser/DeclarePositionVisitor.phpR~hjmA"src/Parser/ArrayWalkArgVisitor.phpR~hj+F"src/Parser/ArrayFindArgVisitor.phpR~hj̲?!src/Parser/PhpParserDecorator.phpR~hj#ߤ/src/Parser/MagicConstantParamDefaultVisitor.phpR~hjBä$src/Parser/ArrayFilterArgVisitor.phpR~hjNh5&src/Parser/ArrowFunctionArgVisitor.phpR~hjǤsrc/Parser/Parser.phpR~hj_8#src/Parser/LastConditionVisitor.php R~hj osrc/Parser/RichParser.php4R~hj4dRsrc/Parser/LexerFactory.phpR~hj$B9!src/Parser/ArrayMapArgVisitor.phpR~hj,z츤&src/Parser/ClosureBindToVarVisitor.phpR~hjB4src/Parser/RemoveUnusedCodeByPhpVersionIdVisitor.phpS R~hjS SL src/Parser/PathRoutingParser.php R~hj ҂M src/ShouldNotHappenException.phpR~hjsrc/Command/AnalyseCommand.phpR~hjMC%src/Command/Symfony/SymfonyOutput.phpR~hj1$src/Command/Symfony/SymfonyStyle.phpR~hj%src/Command/IgnoredRegexValidator.phpR~hj9!8 "src/Command/FixerWorkerCommand.php>R~hj>src/Command/AnalyserRunner.php]R~hj]5+src/Command/IgnoredRegexValidatorResult.phpR~hj3?src/Command/OutputStyle.phpR~hj>g"src/Command/ErrorsConsoleStyle.phpR~hj\p src/Command/FixerApplication.phpUR~hjU-TQsrc/Command/AnalysisResult.phpcR~hjc$esrc/Command/WorkerCommand.php,R~hj,PZ"src/Command/AnalyseApplication.php7R~hj7v %src/Command/FixerProcessException.phpR~hjH}%src/Command/DumpParametersCommand.phpFR~hjF"p src/Command/DiagnoseCommand.php?R~hj?N7src/Command/ErrorFormatter/CheckstyleErrorFormatter.phpR~hj=49src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php R~hj 曃3src/Command/ErrorFormatter/GithubErrorFormatter.phph R~hjh VԤ5src/Command/ErrorFormatter/TeamcityErrorFormatter.phpR~hjK.8src/Command/ErrorFormatter/BaselinePhpErrorFormatter.phpP R~hjP W7src/Command/ErrorFormatter/CiDetectedErrorFormatter.phpR~hj,0src/Command/ErrorFormatter/RawErrorFormatter.phpjR~hjj2src/Command/ErrorFormatter/JunitErrorFormatter.php R~hj U+3src/Command/ErrorFormatter/GitlabErrorFormatter.php5R~hj5z\`-src/Command/ErrorFormatter/ErrorFormatter.phpR~hjs̤1src/Command/ErrorFormatter/JsonErrorFormatter.phpRR~hjRʐr2src/Command/ErrorFormatter/TableErrorFormatter.phpPR~hjPt6/src/Command/InceptionNotSuccessfulException.phpR~hj_src/Command/Output.phpR~hj9'src/Command/ClearResultCacheCommand.php R~hj Xdiڤsrc/Command/CommandHelper.php߉R~hj߉xH src/Command/fixer-phar.pubkey R~hj u䪤src/Command/InceptionResult.phpzR~hjzPsrc/Parallel/ProcessPool.phpjR~hjjFsrc/Parallel/Schedule.phpR~hj޻src/Parallel/Scheduler.php R~hj src/Parallel/Process.phpR~hj$~)src/Parallel/ProcessTimedOutException.phpR~hjߤ!src/Parallel/ParallelAnalyser.php!5R~hj!5_#2src/Reflection/SignatureMap/SignatureMapParser.php R~hj Ȥ<src/Reflection/SignatureMap/FunctionSignatureMapProvider.php 'R~hj 'vRp@src/Reflection/SignatureMap/NativeFunctionReflectionProvider.php R~hj 7֥;src/Reflection/SignatureMap/SignatureMapProviderFactory.phpRR~hjR%ڏ4src/Reflection/SignatureMap/SignatureMapProvider.phpR~hjX 72src/Reflection/SignatureMap/ParameterSignature.php?R~hj?ᷤ8src/Reflection/SignatureMap/Php8SignatureMapProvider.phpNR~hjN`Mu1src/Reflection/SignatureMap/FunctionSignature.phpR~hj%src/Reflection/EnumCaseReflection.phpR~hjK"src/Reflection/ClassNameHelper.php R~hj y髤(src/Reflection/ClassMemberReflection.phpdR~hjdY3٤8src/Reflection/Type/IntersectionTypeMethodReflection.phpR~hjDsrc/Reflection/Type/UnionTypeUnresolvedMethodPrototypeReflection.php R~hj 0SФ:src/Reflection/Type/IntersectionTypePropertyReflection.phpnR~hjnT3src/Reflection/Type/UnionTypePropertyReflection.phppR~hjp/~1src/Reflection/Type/UnionTypeMethodReflection.phpTR~hjT?eGsrc/Reflection/Type/CalledOnTypeUnresolvedMethodPrototypeReflection.php?R~hj?cNIsrc/Reflection/Type/CalledOnTypeUnresolvedPropertyPrototypeReflection.phpcR~hjcD耤=src/Reflection/Type/UnresolvedPropertyPrototypeReflection.phpR~hjT`Esrc/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.phphR~hjh-3Ksrc/Reflection/Type/IntersectionTypeUnresolvedMethodPrototypeReflection.php R~hj '¤;src/Reflection/Type/UnresolvedMethodPrototypeReflection.phpR~hjC.Msrc/Reflection/Type/IntersectionTypeUnresolvedPropertyPrototypeReflection.php R~hj Cy̤Fsrc/Reflection/Type/UnionTypeUnresolvedPropertyPrototypeReflection.php R~hj ]U_Csrc/Reflection/Type/CallbackUnresolvedMethodPrototypeReflection.php.R~hj.eg0src/Reflection/ParametersAcceptorWithPhpDocs.phpR~hjO$E2src/Reflection/MethodsClassReflectionExtension.php:R~hj:GgN5src/Reflection/CallableFunctionVariantWithPhpDocs.php R~hj 4*Zޤ'src/Reflection/BrokerAwareExtension.phpR~hjJ0src/Reflection/Dummy/DummyPropertyReflection.phpOR~hjOvE3src/Reflection/Dummy/DummyConstructorReflection.php R~hj w.src/Reflection/Dummy/DummyMethodReflection.php R~hj 2gV0src/Reflection/Dummy/DummyConstantReflection.phpuR~hjuA6src/Reflection/Dummy/ChangedTypePropertyReflection.php R~hj m4src/Reflection/Dummy/ChangedTypeMethodReflection.phpR~hj0*-src/Reflection/ResolvedPropertyReflection.phpKR~hjK^p-src/Reflection/ExtendedPropertyReflection.phpR~hjS5src/Reflection/Constant/RuntimeConstantReflection.phpR~hj`@+src/Reflection/PhpVersionStaticAccessor.phpkR~hjkq?5src/Reflection/PropertiesClassReflectionExtension.phpSR~hjS-=[%src/Reflection/PropertyReflection.phpWR~hjWG&src/Reflection/ParameterReflection.phpR~hj`}1Isrc/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.phpR~hj% 9src/Reflection/Annotations/AnnotationMethodReflection.phpR~hjol㿤;src/Reflection/Annotations/AnnotationPropertyReflection.phpkR~hjkEۡԤLsrc/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.phpmR~hjmUaCsrc/Reflection/Annotations/AnnotationsMethodParameterReflection.php.R~hj.3src/Reflection/ClassReflectionExtensionRegistry.php R~hj {#4src/Reflection/WrappedExtendedPropertyReflection.php7R~hj7]Osrc/Reflection/PHPStan/NativeReflectionEnumReturnDynamicReturnTypeExtension.phpR~hjG6src/Reflection/ResolvedFunctionVariantWithCallable.phpR~hjӤ+src/Reflection/ExtendedMethodReflection.phpIR~hjIX\%src/Reflection/InaccessibleMethod.php*R~hj*C؂Dsrc/Reflection/BetterReflection/SourceLocator/FetchedNodesResult.php'R~hj'QOsrc/Reflection/BetterReflection/SourceLocator/OptimizedPsrAutoloaderLocator.phpR~hj[bBVsrc/Reflection/BetterReflection/SourceLocator/OptimizedPsrAutoloaderLocatorFactory.phpsR~hjsǣ/`Qsrc/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php4R~hj4=Bsrc/Reflection/BetterReflection/SourceLocator/FileNodesFetcher.phpR~hjjn̤Xsrc/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorFactory.phpiR~hjiGsrc/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.phpo6R~hjo6%zTsrc/Reflection/BetterReflection/SourceLocator/NewOptimizedDirectorySourceLocator.php R~hj Rp}=src/Reflection/BetterReflection/SourceLocator/FetchedNode.php R~hj Psrc/Reflection/BetterReflection/SourceLocator/AutoloadFunctionsSourceLocator.phpR~hj[HRsrc/Reflection/BetterReflection/SourceLocator/PhpVersionBlacklistSourceLocator.phpR~hj@src/Reflection/BetterReflection/SourceLocator/CachingVisitor.phpR~hjc$fVMsrc/Reflection/BetterReflection/SourceLocator/SkipClassAliasSourceLocator.phpR~hjsФYsrc/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocatorFactory.phpR~hji`src/Reflection/BetterReflection/SourceLocator/ComposerJsonAndInstalledJsonSourceLocatorMaker.php*R~hj*H-[src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorRepository.phpR~hjbĥ@src/Reflection/BetterReflection/SourceLocator/PhpFileCleaner.php"R~hj"`Nsrc/Reflection/BetterReflection/SourceLocator/ReflectionClassSourceLocator.phpLR~hjL+?\src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocatorRepository.phpR~hj?BPsrc/Reflection/BetterReflection/SourceLocator/RewriteClassAliasSourceLocator.phpR~hj,Ksrc/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php)R~hj)q|Rsrc/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php%%R~hj%%K!Hsrc/Reflection/BetterReflection/BetterReflectionSourceLocatorFactory.php!R~hj!"k<src/Reflection/BetterReflection/BetterReflectionProvider.phplTR~hjlT@src/Reflection/BetterReflection/Reflector/MemoizingReflector.phpR~hj'bSsrc/Reflection/BetterReflection/SourceStubber/PhpStormStubsSourceStubberFactory.phpR~hjԊPsrc/Reflection/BetterReflection/SourceStubber/ReflectionSourceStubberFactory.phpR~hjhCsrc/Reflection/BetterReflection/BetterReflectionProviderFactory.php#R~hj#)y9src/Reflection/MissingPropertyFromReflectionException.php}R~hj}D$#src/Reflection/MethodReflection.phpR~hju*6src/Reflection/ResolvedFunctionVariantWithOriginal.php)R~hj)&U,src/Reflection/WrapperPropertyReflection.phpR~hj6@:src/Reflection/AllowedSubTypesClassReflectionExtension.phpR~hjUlb=src/Reflection/Mixin/MixinMethodsClassReflectionExtension.php: R~hj: jVޤ@src/Reflection/Mixin/MixinPropertiesClassReflectionExtension.php R~hj D^פ.src/Reflection/Mixin/MixinMethodReflection.php4R~hj4 #]$src/Reflection/PassedByReference.php%R~hj%B%src/Reflection/ConstantNameHelper.phpR~hjB*src/Reflection/ClassConstantReflection.php\R~hj\\JN%src/Reflection/ConstantReflection.php|R~hj|, = +src/Reflection/ResolvedMethodReflection.php=R~hj=-src/Reflection/ParametersAcceptorSelector.phpR~hjі9src/Reflection/MissingConstantFromReflectionException.php|R~hj|'ʤ3src/Reflection/ReflectionProviderStaticAccessor.phpR~hj2H.src/Reflection/InitializerExprTypeResolver.php,aR~hj,a4ٕ,,src/Reflection/ClassMemberAccessAnswerer.phptR~hjtJ*src/Reflection/ResolvedFunctionVariant.phpR~hjli'Ԥ%src/Reflection/ReflectionProvider.phpR~hjr!4src/Reflection/GenericParametersAcceptorResolver.phpER~hjE =%src/Reflection/ConstructorsHelper.php R~hj (Q2src/Reflection/AdditionalConstructorsExtension.phpR~hj W<"src/Reflection/ClassReflection.php1R~hj1ͤ'%src/Reflection/ParametersAcceptor.phpIR~hjI6UEsrc/Reflection/Php/Soap/SoapClientMethodsClassReflectionExtension.phpR~hj+6src/Reflection/Php/Soap/SoapClientMethodReflection.phpFR~hjFi:src/Reflection/Php/PhpFunctionFromParserNodeReflection.php,R~hj,T"Ȥ2src/Reflection/Php/PhpClassReflectionExtension.php6R~hj6'11src/Reflection/Php/PhpMethodReflectionFactory.phpR~hj8src/Reflection/Php/PhpMethodFromParserNodeReflection.phpR~hj6f2src/Reflection/Php/ClosureCallMethodReflection.phpR~hjYƢ-src/Reflection/Php/PhpParameterReflection.phpzR~hjzf *src/Reflection/Php/PhpMethodReflection.phpxFR~hjxFྤ3src/Reflection/Php/UniversalObjectCrateProperty.phpJR~hjJt?/src/Reflection/Php/SimpleXMLElementProperty.phpR~hj0src/Reflection/Php/EnumCasesMethodReflection.phpS R~hjS Aw)-src/Reflection/Php/ExitFunctionReflection.php R~hj V;src/Reflection/Php/PhpParameterFromParserNodeReflection.phpH R~hjH ^@%src/Reflection/Php/DummyParameter.php R~hj XB@src/Reflection/Php/EnumUnresolvedPropertyPrototypeReflection.phpR~hj'70src/Reflection/Php/DummyParameterWithPhpDocs.phpR~hjj-Dsrc/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php R~hj NN,src/Reflection/Php/PhpFunctionReflection.php.R~hj.-Jդ.src/Reflection/Php/BuiltinMethodReflection.php R~hj l,src/Reflection/Php/PhpPropertyReflection.phpR~hjv4src/Reflection/Php/NativeBuiltinMethodReflection.phpR~hj*KBsrc/Reflection/Php/EnumAllowedSubTypesClassReflectionExtension.php R~hj  Esrc/Reflection/Php/ClosureCallUnresolvedMethodPrototypeReflection.php~R~hj~Kr-src/Reflection/Php/EnumPropertyReflection.phpR~hjT)src/Reflection/InitializerExprContext.phpR~hj"7src/Reflection/MissingMethodFromReflectionException.phpvR~hjvCzb,src/Reflection/FunctionReflectionFactory.phpER~hjEt,src/Reflection/MethodPrototypeReflection.php R~hj # @=src/Reflection/ReflectionProvider/DummyReflectionProvider.phpR~hj1"?src/Reflection/ReflectionProvider/ReflectionProviderFactory.phpSR~hjSG+Fsrc/Reflection/ReflectionProvider/SetterReflectionProviderProvider.phpaR~hja3Asrc/Reflection/ReflectionProvider/MemoizingReflectionProvider.php R~hj T)r@src/Reflection/ReflectionProvider/ReflectionProviderProvider.phpR~hj Dsrc/Reflection/ReflectionProvider/LazyReflectionProviderProvider.php`R~hj`Fsrc/Reflection/ReflectionProvider/DirectReflectionProviderProvider.phpPR~hjPn̪>src/Reflection/Native/NativeParameterWithPhpDocsReflection.php R~hj 52src/Reflection/Native/NativeFunctionReflection.phpR~hjUR3src/Reflection/Native/NativeParameterReflection.phpR~hjatʤ0src/Reflection/Native/NativeMethodReflection.php R~hj A>$src/Reflection/NamespaceAnswerer.phpR~hj\w.src/Reflection/Callables/SimpleImpurePoint.phpR~hjn-src/Reflection/Callables/SimpleThrowPoint.phpR~hjkC4src/Reflection/Callables/FunctionCallableVariant.phptR~hjt,N17src/Reflection/Callables/CallableParametersAcceptor.phpR~hj"R1src/Reflection/ParameterReflectionWithPhpDocs.phpR~hjysrc/Reflection/Assertions.php R~hj kXƤQsrc/Reflection/RequireExtension/RequireExtendsMethodsClassReflectionExtension.phpFR~hjFޤTsrc/Reflection/RequireExtension/RequireExtendsPropertiesClassReflectionExtension.phplR~hjl>-src/Reflection/FunctionVariantWithPhpDocs.phpR~hj src/autoloadFunctions.phpR~hjѤ"src/Diagnose/DiagnoseExtension.phpR~hjפ)src/Diagnose/PHPStanDiagnoseExtension.phpR~hjsrc/dumpType.phpAR~hjA 6src/Analyser/EnsuredNonNullabilityResultExpression.phppR~hjpYCZ%src/Analyser/ProcessClosureResult.phpR~hj 1(src/Analyser/AnalyserResultFinalizer.php%R~hj%p0src/Analyser/Ignore/IgnoredErrorHelperResult.php(R~hj(@q7#src/Analyser/Ignore/IgnoreLexer.phpy R~hjy MZb,src/Analyser/Ignore/IgnoreParseException.phpR~hj툤9src/Analyser/Ignore/IgnoredErrorHelperProcessedResult.php R~hj 48C$src/Analyser/Ignore/IgnoredError.php4 R~hj4 {V%*src/Analyser/Ignore/IgnoredErrorHelper.phpR~hjޓW6src/Analyser/ResultCache/ResultCacheManagerFactory.php R~hj Pk/src/Analyser/ResultCache/ResultCacheManager.phpR~hj8i/src/Analyser/ResultCache/ResultCacheClearer.phpKR~hjKu5src/Analyser/ResultCache/ResultCacheProcessResult.phpwR~hjwv(src/Analyser/ResultCache/ResultCache.phpR~hj}src/Analyser/TypeSpecifier.php2~R~hj2~]#src/Analyser/FileAnalyserResult.phppR~hjpoHN%src/Analyser/TypeSpecifierContext.php R~hj EEsrc/Analyser/ThrowPoint.phpR~hj'#e+src/Analyser/DirectInternalScopeFactory.phpR~hj[1Фsrc/Analyser/FileAnalyser.phpCR~hjC"src/Analyser/NodeScopeResolver.phpx{R~hjx{MUӤ#src/Analyser/StatementExitPoint.phpqR~hjqI%src/Analyser/TypeSpecifierFactory.php=R~hj=yO%src/Analyser/RuleErrorTransformer.php! R~hj! ~&src/Analyser/LocalIgnoresProcessor.php R~hj DWY,src/Analyser/LocalIgnoresProcessorResult.php9R~hj9 n,src/Analyser/ConditionalExpressionHolder.phpR~hjp7src/Analyser/Analyser.phpR~hjL)src/Analyser/RicherScopeGetTypeHelper.php" R~hj" src/Analyser/ScopeContext.php R~hj *src/Analyser/Error.phpR~hj_I%src/Analyser/ExpressionTypeHolder.phpR~hj*-src/Analyser/ScopeFactory.phpR~hjC$src/Analyser/ArgumentsNormalizer.phpR~hj l src/Analyser/StatementResult.phpR~hj.: src/Analyser/FinalizerResult.phpLR~hjLKsrc/Analyser/ImpurePoint.phpR~hjv? src/Analyser/OutOfClassScope.phpR~hj#src/Analyser/Scope.phpR~hj]{src/Analyser/SpecifiedTypes.php^R~hj^Z=src/Analyser/MutatingScope.php\R~hj\8'src/Analyser/NullsafeOperatorHelper.php R~hj src/Analyser/AnalyserResult.php}R~hj}M̤,src/Analyser/EnsuredNonNullabilityResult.phpWR~hjW{=msrc/Analyser/NameScope.phpIR~hjIe=9src/Analyser/InternalError.phpx R~hjx m&x"src/Analyser/ExpressionContext.phpR~hjn,a!src/Analyser/StatementContext.phpR~hj_8(src/Analyser/ConstantResolverFactory.php?R~hj?)&%src/Analyser/InternalScopeFactory.phpR~hjϤƷ)src/Analyser/LazyInternalScopeFactory.phpR~hj9i!src/Analyser/ExpressionResult.phpU R~hjU #src/Analyser/EndStatementResult.phpiR~hji>,src/Analyser/TypeSpecifierAwareExtension.phpR~hjQ+src/Analyser/UndefinedVariableException.php;R~hj;!!src/Analyser/ConstantResolver.php+R~hj+31src/Cache/CacheStorage.php0R~hj0 src/Cache/MemoryCacheStorage.phpOR~hjO kBsrc/Cache/CacheItem.php8R~hj8OIWsrc/Cache/FileCacheStorage.phpO R~hjO ,#ysrc/Cache/Cache.phpgR~hjg`src/debugScope.phpR~hj $src/Php/PhpVersionFactoryFactory.phpR~hj娾src/Php/PhpVersion.php+"R~hj+"P\src/Php/PhpVersionFactory.phpR~hj^ Ф preload.phpR~hj6aդconf/config.neonR~hjDLconf/config.level0.neonp+R~hjp+Uf(conf/config.stubValidator.neon-R~hj-kconf/bleedingEdge.neonR~hjDconf/config.level9.neonHR~hjHuconf/config.level1.neonR~hj?$conf/config.level7.neonYR~hjY^bZconf/config.levelmax.neon!R~hj!hconf/config.level5.neonBR~hjBO'conf/parametersSchema.neonR~hjxconf/config.level3.neonF R~hjF D~conf/config.level4.neon-R~hj-'ϟconf/config.level8.neonDR~hjDsJcconf/config.level2.neonR~hj <conf/config.level6.neonR~hj?~%vendor/ondram/ci-detector/src/Env.phpR~hj1vendor/ondram/ci-detector/src/Ci/AwsCodeBuild.phpR~hj 8/vendor/ondram/ci-detector/src/Ci/AbstractCi.phpR~hjq+vendor/ondram/ci-detector/src/Ci/Circle.phpR~hj+vendor/ondram/ci-detector/src/Ci/GitLab.phpR~hj+vendor/ondram/ci-detector/src/Ci/Travis.phpR~hj# ,vendor/ondram/ci-detector/src/Ci/Wercker.php.R~hj.Yg-vendor/ondram/ci-detector/src/Ci/TeamCity.phpR~hjr-vendor/ondram/ci-detector/src/Ci/AppVeyor.phpR~hjGN*vendor/ondram/ci-detector/src/Ci/Buddy.phpR~hj--vendor/ondram/ci-detector/src/Ci/Codeship.phpR~hjZ2vendor/ondram/ci-detector/src/Ci/GitHubActions.phpR~hjc7vendor/ondram/ci-detector/src/Ci/BitbucketPipelines.phpR~hj+vendor/ondram/ci-detector/src/Ci/Bamboo.php8R~hj8X>0vendor/ondram/ci-detector/src/Ci/CiInterface.phpR~hjU,vendor/ondram/ci-detector/src/Ci/Jenkins.phpR~hj*vendor/ondram/ci-detector/src/Ci/Drone.php2R~hj2}2vendor/ondram/ci-detector/src/Ci/Continuousphp.phpiR~hjil.vendor/ondram/ci-detector/src/TrinaryLogic.php?R~hj? Bvendor/ondram/ci-detector/src/Exception/CiNotDetectedException.phpR~hj=o,vendor/ondram/ci-detector/src/CiDetector.php R~hj VA3vendor/ondrejmirtes/better-reflection/renovate.jsonR~hj{Vvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/ComposerSourceLocator.phpR~hjҤVvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AbstractSourceLocator.php= R~hj= *|vendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForComposerJsonAndInstalledJson.phpo R~hjo :lvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForComposerJson.phpR~hjL+mvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/MakeLocatorForInstalledJson.phpR~hj#@pvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/MissingInstalledJson.phpR~hj"osvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/InvalidProjectDirectory.phpR~hj!4lovendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/MissingComposerJson.phpR~hjT_ʤevendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/Exception.phpR~hjZ\mvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Factory/Exception/FailedToParseJson.phpR~hj'<^vendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/PsrAutoloaderLocator.php R~hj X4mbvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/PsrAutoloaderMapping.phpvR~hjv'֤Yvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Psr0Mapping.phpGR~hjG'eYvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Psr4Mapping.php R~hj lvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Exception/InvalidPrefixMapping.phpsR~hjs󴜤avendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/Composer/Psr/Exception/Exception.phpR~hjZvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/FileIteratorSourceLocator.php R~hj ʑqWYvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/DirectoriesSourceLocator.phpR~hj8QvYTvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/StringSourceLocator.php1R~hj1<>٤Vvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AutoloadSourceLocator.php.R~hj.ySXvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/SingleFileSourceLocator.phpTR~hjTzE{GWvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/MemoizingSourceLocator.php R~hj _ۤNvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/SourceLocator.php+R~hj+C=Wvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AggregateSourceLocator.phpR~hjHpvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AutoloadSourceLocator/FileReadTrapStreamWrapper.php~R~hj~J`Uvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/ClosureSourceLocator.php}R~hj}M$Фbvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AnonymousClassObjectSourceLocator.phpDR~hjDNwXvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/EvaledCodeSourceLocator.phpR~hjWvYvendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/PhpInternalSourceLocator.php2 R~hj2 Wvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/EvaledLocatedSource.php4R~hj4{rjVvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/AliasLocatedSource.phpOR~hjOZvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/AnonymousLocatedSource.phptR~hjtm Qvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/LocatedSource.php R~hj SΤYvendor/ondrejmirtes/better-reflection/src/SourceLocator/Located/InternalLocatedSource.php R~hj zavendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/ReflectionSourceStubber.php(zR~hj(zL5^fvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/PhpStormStubs/CachingVisitor.phptR~hjt`vendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/AggregateSourceStubber.phpR~hj)Wvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/SourceStubber.phpR~hjϭRvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/StubData.phpR~hj$դmvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/Exception/CouldNotFindPhpStormStubs.php0R~hj0~dvendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/PhpStormStubsSourceStubber.php|R~hj|fE \vendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NoAnonymousClassOnLine.phpR~hj\Vvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidDirectory.phpR~hjdTbvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/EvaledClosureCannotBeLocated.php$R~hj$dϤUvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidFileInfo.php+R~hj+J"Wvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/FunctionUndefined.phpVR~hjVN0ivendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/EvaledAnonymousClassCannotBeLocated.php3R~hj36ǮUvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NoClosureOnLine.phppR~hjpGcvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/TwoAnonymousClassesOnSameLine.phpR~hjM/Yvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/InvalidFileLocation.phpR~hjVvendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/NotInternalClass.phpR~hjzׯ[vendor/ondrejmirtes/better-reflection/src/SourceLocator/Exception/TwoClosuresOnSameLine.phprR~hjrӤUvendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/FindReflectionsInTree.php0R~hj0d Vvendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Parser/MemoizingParser.phpR~hjg ^vendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Strategy/AstConversionStrategy.phpR~hjϜYvendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Strategy/NodeToReflection.php R~hj |~Gvendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Locator.php( R~hj( a[vendor/ondrejmirtes/better-reflection/src/SourceLocator/Ast/Exception/ParseToAstFailure.phpR~hjJ:Gvendor/ondrejmirtes/better-reflection/src/SourceLocator/FileChecker.phpR~hj)MHvendor/ondrejmirtes/better-reflection/src/NodeCompiler/CompiledValue.phpR~hj_Jvendor/ondrejmirtes/better-reflection/src/NodeCompiler/CompilerContext.php_R~hj_ZWMvendor/ondrejmirtes/better-reflection/src/NodeCompiler/CompileNodeToValue.php3R~hj3TXvendor/ondrejmirtes/better-reflection/src/NodeCompiler/Exception/UnableToCompileNode.phpR~hjvNҺKvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionEnumCase.phpR~hj='Kvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionProperty.php"KR~hj"K]Svendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionIntersectionType.php R~hj Vvendor/ondrejmirtes/better-reflection/src/Reflection/Support/AlreadyVisitedClasses.php]R~hj]%0Hvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionClass.phpR~hj ZCvendor/ondrejmirtes/better-reflection/src/Reflection/Reflection.phpR~hjRuKIvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionObject.php6R~hj6PBeevendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionClassConstantStringCast.phpR~hjm4`vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionPropertyStringCast.phpJR~hjJ/avendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionAttributeStringCast.phpWR~hjWhW]vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionClassStringCast.php(#R~hj(#U^vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionMethodStringCast.phpyR~hjy+`vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionConstantStringCast.phpR~hjp`vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionFunctionStringCast.php R~hj F[3avendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionParameterStringCast.phpeR~hje *`vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionEnumCaseStringCast.phpR~hj2^\vendor/ondrejmirtes/better-reflection/src/Reflection/StringCast/ReflectionTypeStringCast.php:R~hj:l1τLvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionAttribute.phpR~hjĤLvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionNamedType.php.R~hj.\ڤLvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionParameter.php?ER~hj?E ISvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionFunctionAbstract.phpj<R~hjj<LGvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionType.phpV R~hjV =aLvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionUnionType.php R~hj XQvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionObject.phprGR~hjrGeTvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionAttribute.phpR~hjC,Tvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionNamedType.phpR~hjSNTvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionParameter.phpt#R~hjt#.Ovendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionType.php R~hj Rc/FTvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionUnionType.phpR~hj|Qvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionMethod.phpV-R~hjV-S <Xvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionClassConstant.phphR~hjh̬![vendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionAttributeFactory.php6R~hj6Svendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionFunction.php\"R~hj\"MaWvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnumUnitCase.phpR~hj1?~Xvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/FakeReflectionAttribute.phpR~hjr Yvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/Exception/NotImplemented.phpR~hjIReOvendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionEnum.phpSKR~hjSKWKvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionConstant.php'R~hj'Zvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/MethodPrototypeNotFound.phpR~hj27VWvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/PropertyDoesNotExist.php]R~hj]/7i[Zvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidDefaultValueType.phpR~hjudBNvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/NotAnObject.phpR~hjVvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/CodeLocationMissing.phpR~hjKvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/NoParent.phpR~hjߤ_vendor/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidArrowFunctionBodyNode.php,R~hj,pJͤVvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/InvalidConstantNode.phpR~hj ՗Wvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/FunctionDoesNotExist.php{R~hj{cTvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/ClassDoesNotExist.phpR~hjnSvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/NoObjectProvided.phpR~hj/Tvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/CircularReference.phpmR~hjm"Vvendor/ondrejmirtes/better-reflection/src/Reflection/Exception/PropertyIsNotStatic.php[R~hj[[vendor/ondrejmirtes/better-reflection/src/Reflection/Exception/ObjectNotInstanceOfClass.phpxR~hjx w\vendor/ondrejmirtes/better-reflection/src/Reflection/Attribute/ReflectionAttributeHelper.php3 R~hj3 KGvendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionEnum.phpjR~hjj 2Ivendor/ondrejmirtes/better-reflection/src/Reflector/ConstantReflector.phpR~hj$EIvendor/ondrejmirtes/better-reflection/src/Reflector/FunctionReflector.phpR~hja8ҤAvendor/ondrejmirtes/better-reflection/src/Reflector/Reflector.phpR~hjbyFvendor/ondrejmirtes/better-reflection/src/Reflector/ClassReflector.phpR~hjEHvendor/ondrejmirtes/better-reflection/src/Reflector/DefaultReflector.phpR~hjTvendor/ondrejmirtes/better-reflection/src/Reflector/Exception/IdentifierNotFound.phpLR~hjLޤ'Gvendor/ondrejmirtes/better-reflection/src/Util/FindReflectionOnLine.phpR~hjP5ˤHvendor/ondrejmirtes/better-reflection/src/Util/ClassExistenceChecker.php{R~hj{JFvendor/ondrejmirtes/better-reflection/src/Util/ConstantNodeChecker.phpR~hj߸CPvendor/ondrejmirtes/better-reflection/src/Util/Exception/InvalidNodePosition.phpVR~hjV>UݤKvendor/ondrejmirtes/better-reflection/src/Util/Exception/NoNodePosition.phpR~hj$Dvendor/ondrejmirtes/better-reflection/src/Util/GetLastDocComment.phpR~hjt=vendor/ondrejmirtes/better-reflection/src/Util/FileHelper.phpf R~hjf AuLLvendor/ondrejmirtes/better-reflection/src/Util/CalculateReflectionColumn.phpR~hj5_>vendor/ondrejmirtes/better-reflection/src/BetterReflection.phpR~hjJSo3Gvendor/ondrejmirtes/better-reflection/src/Identifier/IdentifierType.phpR~hjlޤCvendor/ondrejmirtes/better-reflection/src/Identifier/Identifier.phpR~hjqb!Xvendor/ondrejmirtes/better-reflection/src/Identifier/Exception/InvalidIdentifierName.phpeR~hjeZJ-vendor/ondrejmirtes/better-reflection/LICENSE6R~hj6Wwvendor/autoload.phpR~hjv֤>vendor/jetbrains/phpstorm-stubs/parallel/parallel/Runtime.stubR~hj0ˤNvendor/jetbrains/phpstorm-stubs/parallel/parallel/Sync/Error/IllegalValue.stubeR~hje> wAvendor/jetbrains/phpstorm-stubs/parallel/parallel/Sync/Error.stubHR~hjHb=vendor/jetbrains/phpstorm-stubs/parallel/parallel/Events.stub R~hj ܤNvendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel/Error/Existence.stubhR~hjhyäKvendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel/Error/Closed.stubeR~hjez Qvendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel/Error/IllegalValue.stubkR~hjkDvendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel/Error.stubKR~hjK%Nvendor/jetbrains/phpstorm-stubs/parallel/parallel/Runtime/Error/Bootstrap.stubhR~hjhUR~hj>^Qvendor/jetbrains/phpstorm-stubs/parallel/parallel/Runtime/Object/Unavailable.stub@R~hj@:ǦDvendor/jetbrains/phpstorm-stubs/parallel/parallel/Runtime/Error.stubKR~hjK;vendor/jetbrains/phpstorm-stubs/parallel/parallel/Sync.stubR~hj4R=vendor/jetbrains/phpstorm-stubs/parallel/parallel/Future.stub`R~hj`.?Dä>vendor/jetbrains/phpstorm-stubs/parallel/parallel/Channel.stub(R~hj(&Mvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Error/Existence.stubfR~hjfRbKvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Error/Timeout.stubdR~hjdJ6Svendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Input/Error/Existence.stubrR~hjr7oVvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Input/Error/IllegalValue.stubuR~hjuiIvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Input/Error.stubPR~hjP?Cvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Error.stubJR~hjJžCvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Input.stub0R~hj0>Cvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Event.stubR~hj̀8Hvendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Event/Type.stub.R~hj.ϞZ>Ivendor/jetbrains/phpstorm-stubs/parallel/parallel/Events/Event/Error.stubPR~hjPRJvendor/jetbrains/phpstorm-stubs/parallel/parallel/Future/Error/Killed.stub\R~hj\< Kvendor/jetbrains/phpstorm-stubs/parallel/parallel/Future/Error/Foreign.stub]R~hj]}Mvendor/jetbrains/phpstorm-stubs/parallel/parallel/Future/Error/Cancelled.stub_R~hj_Cvendor/jetbrains/phpstorm-stubs/parallel/parallel/Future/Error.stubJR~hjJb<vendor/jetbrains/phpstorm-stubs/parallel/parallel/Error.stub:R~hj:{6vendor/jetbrains/phpstorm-stubs/parallel/parallel.stubR~hjz.vendor/jetbrains/phpstorm-stubs/geos/geos.stubAR~hjAU.vendor/jetbrains/phpstorm-stubs/judy/judy.stubF"R~hjF"q32vendor/jetbrains/phpstorm-stubs/random/random.stubR~hj^50vendor/jetbrains/phpstorm-stubs/redis/Redis.stubR~hj*Y5vendor/jetbrains/phpstorm-stubs/redis/RedisArray.stubLR~hjLfL7vendor/jetbrains/phpstorm-stubs/redis/RedisCluster.stub,R~hj,IU8vendor/jetbrains/phpstorm-stubs/redis/RedisSentinel.stubR~hjz A.vendor/jetbrains/phpstorm-stubs/snmp/snmp.stubR~hj.vendor/jetbrains/phpstorm-stubs/grpc/grpc.stubYR~hjYXK٤0vendor/jetbrains/phpstorm-stubs/uuid/uuid_c.stub R~hj }j.vendor/jetbrains/phpstorm-stubs/dom/dom_n.stub R~hj ~,vendor/jetbrains/phpstorm-stubs/dom/dom.stubyR~hjy9.vendor/jetbrains/phpstorm-stubs/dom/dom_c.stub_R~hj_4vendor/jetbrains/phpstorm-stubs/imap/Connection.stubHR~hjHF?.vendor/jetbrains/phpstorm-stubs/imap/imap.stub;R~hj;Е.vendor/jetbrains/phpstorm-stubs/exif/exif.stubR~hj 0 Ѥ.vendor/jetbrains/phpstorm-stubs/amqp/amqp.stub3R~hj3{8vendor/jetbrains/phpstorm-stubs/ZendUtils/ZendUtils.stub8R~hj8܌.vendor/jetbrains/phpstorm-stubs/pcov/pcov.stubR~hj\X,vendor/jetbrains/phpstorm-stubs/svn/svn.stublR~hjl R4vendor/jetbrains/phpstorm-stubs/leveldb/LevelDB.stubR~hj;4vendor/jetbrains/phpstorm-stubs/aerospike/Bytes.stub R~hj ʍ8vendor/jetbrains/phpstorm-stubs/aerospike/aerospike.stub24R~hj24ٸe4vendor/jetbrains/phpstorm-stubs/gearman/gearman.stubR~hjଉ,vendor/jetbrains/phpstorm-stubs/dio/dio.stub%R~hj%'&.vendor/jetbrains/phpstorm-stubs/dio/dio_d.stubR~hjC/vendor/jetbrains/phpstorm-stubs/Inspections.xmlR~hjwl.vendor/jetbrains/phpstorm-stubs/tidy/tidy.stubLR~hjLדN8vendor/jetbrains/phpstorm-stubs/xlswriter/xlswriter.stub'>R~hj'>@2vendor/jetbrains/phpstorm-stubs/xmlrpc/xmlrpc.stubR~hj.vendor/jetbrains/phpstorm-stubs/sync/sync.stubi7R~hji7VB2vendor/jetbrains/phpstorm-stubs/SaxonC/SaxonC.stublR~hjl# ,vendor/jetbrains/phpstorm-stubs/rrd/rrd.stub0R~hj0Τ6vendor/jetbrains/phpstorm-stubs/simdjson/simdjson.stub/R~hj/P^4vendor/jetbrains/phpstorm-stubs/gmagick/gmagick.stubjR~hjjY\ ,vendor/jetbrains/phpstorm-stubs/yar/yar.stubR~hjۤ0vendor/jetbrains/phpstorm-stubs/curl/curl_d.stubNR~hjNr.W?8vendor/jetbrains/phpstorm-stubs/curl/CURLStringFile.stubR~hj@b.vendor/jetbrains/phpstorm-stubs/curl/curl.stubsR~hjs/vendor/jetbrains/phpstorm-stubs/regex/ereg.stubz R~hjz =cP0vendor/jetbrains/phpstorm-stubs/pcntl/pcntl.stubYXR~hjYXۖ<Ȥ2vendor/jetbrains/phpstorm-stubs/pcntl/pcntl_c.stubR~hjzEh.vendor/jetbrains/phpstorm-stubs/yaml/yaml.stubhR~hjh{Ȥ8vendor/jetbrains/phpstorm-stubs/ZendCache/ZendCache.stub R~hj ab;vendor/jetbrains/phpstorm-stubs/couchbase_v2/couchbase.stubR~hjdz :vendor/jetbrains/phpstorm-stubs/couchbase_v2/toplevel.stubWR~hjWa->4vendor/jetbrains/phpstorm-stubs/suhosin/suhosin.stubR~hjQ8vendor/jetbrains/phpstorm-stubs/winbinder/winbinder.stubxR~hjx:0vendor/jetbrains/phpstorm-stubs/stats/stats.stub"HR~hj"He.vendor/jetbrains/phpstorm-stubs/fann/fann.stubhR~hjha*@vendor/jetbrains/phpstorm-stubs/mosquitto-php/mosquitto-php.stubq5R~hjq5H^2vendor/jetbrains/phpstorm-stubs/xhprof/xhprof.stubR~hjg"դ,vendor/jetbrains/phpstorm-stubs/ftp/ftp.stubiR~hjiy("3vendor/jetbrains/phpstorm-stubs/ftp/Connection.stubGR~hjG!2vendor/jetbrains/phpstorm-stubs/docker-compose.ymlZR~hjZzNq.vendor/jetbrains/phpstorm-stubs/ming/ming.stubr"R~hjr"2: 6vendor/jetbrains/phpstorm-stubs/pthreads/pthreads.stubHR~hjH>90vendor/jetbrains/phpstorm-stubs/oci8/oci8v3.stubE9R~hjE9.vendor/jetbrains/phpstorm-stubs/oci8/oci8.stuboR~hjoh!p2vendor/jetbrains/phpstorm-stubs/sodium/sodium.stubR~hj D*vendor/jetbrains/phpstorm-stubs/Ev/Ev.stubR~hjr+vendor/jetbrains/phpstorm-stubs/qodana.yaml R~hj 'JX;8vendor/jetbrains/phpstorm-stubs/memcached/memcached.stubR~hjH@.vendor/jetbrains/phpstorm-stubs/apcu/apcu.stub[nR~hj[nF9vendor/jetbrains/phpstorm-stubs/snappy/snappy/snappy.stubR~hj 0vendor/jetbrains/phpstorm-stubs/mssql/mssql.stub6MR~hj6MW˟8vendor/jetbrains/phpstorm-stubs/xmlreader/xmlreader.stubsDR~hjsD+{ˤ9vendor/jetbrains/phpstorm-stubs/Parle/LexerException.stubwR~hjw^Ut0vendor/jetbrains/phpstorm-stubs/Parle/Token.stubR~hjN1vendor/jetbrains/phpstorm-stubs/Parle/RLexer.stubR~hj w0vendor/jetbrains/phpstorm-stubs/Parle/Lexer.stub*R~hj*; 2vendor/jetbrains/phpstorm-stubs/Parle/RParser.stubR~hjɥФ1vendor/jetbrains/phpstorm-stubs/Parle/Parser.stub,R~hj,0vendor/jetbrains/phpstorm-stubs/Parle/Stack.stubAR~hjA.>o_:vendor/jetbrains/phpstorm-stubs/Parle/ParserException.stubxR~hjxL4vendor/jetbrains/phpstorm-stubs/Parle/ErrorInfo.stubAR~hjA4vendor/jetbrains/phpstorm-stubs/sysvsem/sysvsem.stub R~hj zX@vendor/jetbrains/phpstorm-stubs/mysql_xdevapi/mysql_xdevapi.stubR~hj^6vendor/jetbrains/phpstorm-stubs/mbstring/mbstring.stubR~hjK M2vendor/jetbrains/phpstorm-stubs/libxml/libxml.stub$R~hj$V92vendor/jetbrains/phpstorm-stubs/crypto/crypto.stub1?R~hj1?ګפ0vendor/jetbrains/phpstorm-stubs/date/date_c.stubšR~hjš?Ao0vendor/jetbrains/phpstorm-stubs/date/date_d.stub"R~hj"e.vendor/jetbrains/phpstorm-stubs/date/date.stub+R~hj+s4vendor/jetbrains/phpstorm-stubs/SplType/SplType.stub R~hj o6vendor/jetbrains/phpstorm-stubs/mqseries/mqseries.stubR~hj1%6vendor/jetbrains/phpstorm-stubs/libevent/libevent.stub"YR~hj"Y08vendor/jetbrains/phpstorm-stubs/mailparse/mailparse.stubwR~hjwr4vendor/jetbrains/phpstorm-stubs/session/session.stubiGR~hjiGޤ;vendor/jetbrains/phpstorm-stubs/session/SessionHandler.stub[(R~hj[(mf.vendor/jetbrains/phpstorm-stubs/gd/GdFont.stub3R~hj3`I=*vendor/jetbrains/phpstorm-stubs/gd/gd.stubR~hj*vendor/jetbrains/phpstorm-stubs/ds/ds.stubR~hjREJvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient.stubR~hj!Bvendor/jetbrains/phpstorm-stubs/simple_kafka_client/functions.stubR~hjBQRvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Message.stubR~hjk^vendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/KafkaErrorException.stubR~hji',Svendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata.stub9R~hj9!aXvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Configuration.stubxR~hjxռvYvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/TopicPartition.stub&R~hj&>~Svendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Producer.stubR~hjИSvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Consumer.stubWR~hjWZvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata/Broker.stub9R~hj9uo`Yvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata/Topic.stubSR~hjS\]vendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata/Partition.stubR~hjg^vendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Metadata/Collection.stub R~hj Pvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Topic.stubR~hj Tvendor/jetbrains/phpstorm-stubs/simple_kafka_client/SimpleKafkaClient/Exception.stubdR~hjdYv:vendor/jetbrains/phpstorm-stubs/libsodium/libsodium_d.stub@R~hj@+Ƥ:vendor/jetbrains/phpstorm-stubs/libsodium/libsodium_f.stubR~hjړ+8vendor/jetbrains/phpstorm-stubs/libsodium/libsodium.stube<R~hje<`-8vendor/jetbrains/phpstorm-stubs/couchbase/couchbase.stubR~hjCƤ0vendor/jetbrains/phpstorm-stubs/geoip/geoip.stub$R~hj$66vendor/jetbrains/phpstorm-stubs/standard/password.stub'R~hj'Ou8vendor/jetbrains/phpstorm-stubs/standard/standard_4.stubR~hjgR8vendor/jetbrains/phpstorm-stubs/standard/standard_1.stublR~hjlO8vendor/jetbrains/phpstorm-stubs/standard/standard_0.stub$R~hj$>9vendor/jetbrains/phpstorm-stubs/standard/standard_10.stubR~hj@G8vendor/jetbrains/phpstorm-stubs/standard/standard_3.stubyyR~hjyynN3vendor/jetbrains/phpstorm-stubs/standard/basic.stub,R~hj,ND>vendor/jetbrains/phpstorm-stubs/standard/standard_defines.stub R~hj ~۞4vendor/jetbrains/phpstorm-stubs/standard/_types.stubHR~hjHW8vendor/jetbrains/phpstorm-stubs/standard/standard_8.stubR~hj=N8vendor/jetbrains/phpstorm-stubs/standard/standard_6.stubR~hjbQ8vendor/jetbrains/phpstorm-stubs/standard/standard_2.stub"R~hj"-Qʤ8vendor/jetbrains/phpstorm-stubs/standard/standard_9.stubR~hj/c;/8vendor/jetbrains/phpstorm-stubs/standard/standard_7.stubR~hj.Ť>vendor/jetbrains/phpstorm-stubs/standard/_standard_manual.stub)R~hj)ػD8vendor/jetbrains/phpstorm-stubs/standard/standard_5.stubÄR~hjÄ 4:vendor/jetbrains/phpstorm-stubs/frankenphp/frankenphp.stubR~hjx0vendor/jetbrains/phpstorm-stubs/xdiff/xdiff.stub"(R~hj"(7vendor/jetbrains/phpstorm-stubs/tokenizer/PhpToken.stubR~hj&8vendor/jetbrains/phpstorm-stubs/tokenizer/tokenizer.stubR~hj&>vendor/jetbrains/phpstorm-stubs/ZendDebugger/ZendDebugger.stubR~hjw!6vendor/jetbrains/phpstorm-stubs/wincache/wincache.stubaR~hjaЃ 4vendor/jetbrains/phpstorm-stubs/msgpack/msgpack.stubXR~hjX2d\,vendor/jetbrains/phpstorm-stubs/xsl/xsl.stub;R~hj;$Ȥ.vendor/jetbrains/phpstorm-stubs/v8js/v8js.stubR~hjU90vendor/jetbrains/phpstorm-stubs/pgsql/pgsql.stubsR~hjs Tj2vendor/jetbrains/phpstorm-stubs/pgsql/pgsql_c.stubR~hj޲2vendor/jetbrains/phpstorm-stubs/mysqli/mysqli.stub2R~hj2?4vendor/jetbrains/phpstorm-stubs/sysvmsg/sysvmsg.stub&R~hj&jΤ6vendor/jetbrains/phpstorm-stubs/readline/readline.stubCR~hjCc/vendor/jetbrains/phpstorm-stubs/SPL/SPL_c1.stub ?R~hj ?L,vendor/jetbrains/phpstorm-stubs/SPL/SPL.stubR~hjh .vendor/jetbrains/phpstorm-stubs/SPL/SPL_f.stubmR~hjmO:äFvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionEnumUnitCase.stubR~hjE;Cvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionUnionType.stub R~hj ˜Cvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionAttribute.stubR~hjזCvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionNamedType.stubpR~hjp'Bvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionFunction.stubR~hjbCvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionExtension.stub2R~hj2~?vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionClass.stub\R~hj\ۆ$9vendor/jetbrains/phpstorm-stubs/Reflection/Reflector.stubR~hjT>vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionType.stubR~hjR?vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionFiber.stubR~hj*a@vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionMethod.stubU*R~hjU*@vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionObject.stubR~hj0Hvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionEnumBackedCase.stubPR~hjPgCvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionParameter.stub'R~hj'EOJvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionFunctionAbstract.stubh(R~hjh(#@vendor/jetbrains/phpstorm-stubs/Reflection/PropertyHookType.stub3R~hj3FCvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionException.stubR~hj#5Bvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionConstant.stubR~hj|Gvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionZendExtension.stub R~hj b{`Jvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionIntersectionType.stubR~hj6c8Cvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionReference.stubR~hj؆5>vendor/jetbrains/phpstorm-stubs/Reflection/ReflectionEnum.stubR~hjNBvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionProperty.stuba.R~hja. -:vendor/jetbrains/phpstorm-stubs/Reflection/Reflection.stubR~hjCCvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionGenerator.stubL R~hjL +KGvendor/jetbrains/phpstorm-stubs/Reflection/ReflectionClassConstant.stub4R~hj4|,vendor/jetbrains/phpstorm-stubs/bz2/bz2.stubqR~hjq4 <vendor/jetbrains/phpstorm-stubs/elastic_apm/elastic_apm.stub~R~hj~4vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.php" R~hj" 1 Ǘ8vendor/jetbrains/phpstorm-stubs/zookeeper/zookeeper.stub")R~hj") ޛ?vendor/jetbrains/phpstorm-stubs/superglobals/_superglobals.stubR~hjFe5vendor/jetbrains/phpstorm-stubs/swoole/constants.stubAR~hjA@y3vendor/jetbrains/phpstorm-stubs/swoole/aliases.stubX R~hjX ᕤ5vendor/jetbrains/phpstorm-stubs/swoole/functions.stub8"R~hj8"6|9vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server.stubq&R~hjq&EĤ:vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Runtime.stubR~hj9vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Atomic.stubR~hjeKͤ?vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Process/Pool.stubR~hjL4!@vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/Packet.stubR~hj+>vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/Task.stubR~hjeZvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/Port.stubR~hj_{?vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/Event.stubR~hj4Evendor/jetbrains/phpstorm-stubs/swoole/Swoole/Server/PipeMessage.stubR~hjvDCvendor/jetbrains/phpstorm-stubs/swoole/Swoole/WebSocket/Server.stubR~hj!AfBvendor/jetbrains/phpstorm-stubs/swoole/Swoole/WebSocket/Frame.stubR~hjDGvendor/jetbrains/phpstorm-stubs/swoole/Swoole/WebSocket/CloseFrame.stubR~hj%<vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine.stubR~hjNˤ7vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Lock.stubR~hj.n8vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Table.stubR~hjƂwդ>vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Atomic/Long.stubR~hjCvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Client/Exception.stubhR~hjh;9vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Client.stub R~hj Ѥ8vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Timer.stub{R~hj{U@vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http2/Request.stubR~hjH1Avendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http2/Response.stubR~hji8vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Error.stubRR~hjRT@vendor/jetbrains/phpstorm-stubs/swoole/Swoole/ExitException.stub R~hj _Avendor/jetbrains/phpstorm-stubs/swoole/Swoole/Timer/Iterator.stubR~hjg8'?vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Redis/Server.stub R~hj ?Bvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/MySQL.stub<R~hj<& Mvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Socket/Exception.stubrR~hjr-| Bvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Redis.stubmR~hjm%TCvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Socket.stubaR~hjaMCvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Client.stubR~hjpծLvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/MySQL/Statement.stubR~hj5Lvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/MySQL/Exception.stubqR~hjqQïSvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http2/Client/Exception.stubxR~hjxP Ivendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http2/Client.stuboR~hjoG>Dvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Channel.stubR~hjOhEvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Iterator.stubR~hj4;Dvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Context.stubR~hjFvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Scheduler.stubR~hj9Kvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Curl/Exception.stubpR~hjp{_ԤHvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http/Server.stubR~hjy*Rvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http/Client/Exception.stubwR~hjwHvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/Http/Client.stub)R~hj) g&Cvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Coroutine/System.stub R~hj SAۤFvendor/jetbrains/phpstorm-stubs/swoole/Swoole/Connection/Iterator.stubR~hjfoƤ8vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Event.stubR~hjw<vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Exception.stubZR~hjZ:vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Process.stubR~hj8<ڋ>vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http/Server.stub`R~hj`Y?vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http/Request.stubR~hj],@vendor/jetbrains/phpstorm-stubs/swoole/Swoole/Http/Response.stubR~hjc+vendor/jetbrains/phpstorm-stubs/PATCHES.txtER~hjEZΤ0vendor/jetbrains/phpstorm-stubs/ctype/ctype.stubRR~hjRP2vendor/jetbrains/phpstorm-stubs/sqlsrv/sqlsrv.stub~R~hj~i8vendor/jetbrains/phpstorm-stubs/cassandra/cassandra.stub R~hj 3Ԥ.vendor/jetbrains/phpstorm-stubs/Phar/Phar.stub(R~hj(6K,vendor/jetbrains/phpstorm-stubs/zip/zip.stub R~hj C94vendor/jetbrains/phpstorm-stubs/rpminfo/rpminfo.stub-R~hj-8vendor/jetbrains/phpstorm-stubs/blackfire/blackfire.stubHR~hjHZ46vendor/jetbrains/phpstorm-stubs/igbinary/igbinary.stubR~hjo/0vendor/jetbrains/phpstorm-stubs/mysql/mysql.stub|R~hj|0{,vendor/jetbrains/phpstorm-stubs/svm/SVM.stubR~hjg1vendor/jetbrains/phpstorm-stubs/svm/SVMModel.stubR~hj p8vendor/jetbrains/phpstorm-stubs/SimpleXML/SimpleXML.stubQLR~hjQLO4vendor/jetbrains/phpstorm-stubs/enchant/enchant.stub)R~hj)R4vendor/jetbrains/phpstorm-stubs/ibm_db2/ibm_db2.stubR~hj̯6vendor/jetbrains/phpstorm-stubs/newrelic/newrelic.stubR~hjϤ,vendor/jetbrains/phpstorm-stubs/rar/rar.stub_R~hj_EQ`2vendor/jetbrains/phpstorm-stubs/pdflib/PDFlib.stub/TR~hj/T5% K,vendor/jetbrains/phpstorm-stubs/fpm/fpm.stubR~hjB9vendor/jetbrains/phpstorm-stubs/meta/attributes/Pure.stubR~hj;Ś?vendor/jetbrains/phpstorm-stubs/meta/attributes/Deprecated.stubR~hjk^Cvendor/jetbrains/phpstorm-stubs/meta/attributes/ExpectedValues.stubR~hjђ~>vendor/jetbrains/phpstorm-stubs/meta/attributes/Immutable.stubR~hja'[vendor/jetbrains/phpstorm-stubs/meta/attributes/internal/PhpStormStubsElementAvailable.stubR~hje3Kvendor/jetbrains/phpstorm-stubs/meta/attributes/internal/TentativeType.stubR~hj()Pvendor/jetbrains/phpstorm-stubs/meta/attributes/internal/ReturnTypeContract.stubhR~hjh< xTvendor/jetbrains/phpstorm-stubs/meta/attributes/internal/LanguageLevelTypeAware.stuboR~hjo%?vendor/jetbrains/phpstorm-stubs/meta/attributes/ArrayShape.stubVR~hjVO7=vendor/jetbrains/phpstorm-stubs/meta/attributes/NoReturn.stubR~hj4@vendor/jetbrains/phpstorm-stubs/meta/attributes/ObjectShape.stubR~hjk p=vendor/jetbrains/phpstorm-stubs/meta/attributes/Language.stubR~hjMJ.vendor/jetbrains/phpstorm-stubs/json/json.stub4R~hj4tA6vendor/jetbrains/phpstorm-stubs/fileinfo/fileinfo.stubr!R~hjr!WY12vendor/jetbrains/phpstorm-stubs/phpdbg/phpdbg.stubgR~hjgAȾO+vendor/jetbrains/phpstorm-stubs/runTests.sh`R~hj`Rz1,vendor/jetbrains/phpstorm-stubs/FFI/FFI.stubMR~hjMt4vendor/jetbrains/phpstorm-stubs/ncurses/ncurses.stubR~hj*֩,vendor/jetbrains/phpstorm-stubs/zmq/zmq.stubzuR~hjzuZ:vendor/jetbrains/phpstorm-stubs/com_dotnet/com_dotnet.stubf/R~hjf/b,vendor/jetbrains/phpstorm-stubs/xml/xml.stubZR~hjZ]!8vendor/jetbrains/phpstorm-stubs/mapscript/mapscript.stubR~hj{|K'vendor/jetbrains/phpstorm-stubs/LICENSEW,R~hjW,M̤,vendor/jetbrains/phpstorm-stubs/lua/lua.stub< R~hj< €.vendor/jetbrains/phpstorm-stubs/http/http.stubR~hj/vendor/jetbrains/phpstorm-stubs/http/http3.stub]R~hj]<0vendor/jetbrains/phpstorm-stubs/oauth/oauth.stubb R~hjb bp0vendor/jetbrains/phpstorm-stubs/Core/Core_c.stubԋR~hjԋ60vendor/jetbrains/phpstorm-stubs/Core/Core_d.stub $R~hj $Zy.vendor/jetbrains/phpstorm-stubs/Core/Core.stub_R~hj_R.vendor/jetbrains/phpstorm-stubs/zstd/zstd.stubR~hjLV.vendor/jetbrains/phpstorm-stubs/zlib/zlib.stubKR~hjKZԤ4vendor/jetbrains/phpstorm-stubs/pspell/pspell_c.stubR~hjR 2vendor/jetbrains/phpstorm-stubs/pspell/pspell.stubq.R~hjq.0\,vendor/jetbrains/phpstorm-stubs/PDO/PDO.stubcGR~hjcGK&sʤ.vendor/jetbrains/phpstorm-stubs/uopz/uopz.stub&R~hj&-#:vendor/jetbrains/phpstorm-stubs/LuaSandbox/LuaSandbox.stubER~hjE0vendor/jetbrains/phpstorm-stubs/iconv/iconv.stub5R~hj51+G0vendor/jetbrains/phpstorm-stubs/shmop/shmop.stubR~hj2ɤ*vendor/jetbrains/phpstorm-stubs/pq/pq.stub+R~hj+5vendor/jetbrains/phpstorm-stubs/sybase/sybase_ct.stub7R~hj7#!2vendor/jetbrains/phpstorm-stubs/ffmpeg/ffmpeg.stubR~hjg%2vendor/jetbrains/phpstorm-stubs/relay/Cluster.stub?R~hj?_p0vendor/jetbrains/phpstorm-stubs/relay/Table.stubrR~hjrGͤ1vendor/jetbrains/phpstorm-stubs/relay/Events.stubR~hj)3vendor/jetbrains/phpstorm-stubs/relay/Sentinel.stubR~hj&vY2vendor/jetbrains/phpstorm-stubs/relay/KeyType.stubR~hjۼ0vendor/jetbrains/phpstorm-stubs/relay/Event.stubR~hj,7A4vendor/jetbrains/phpstorm-stubs/relay/Exception.stubcR~hjcr!0vendor/jetbrains/phpstorm-stubs/relay/Relay.stub;R~hj;0vendor/jetbrains/phpstorm-stubs/event/event.stubR~hjzI6vendor/jetbrains/phpstorm-stubs/calendar/calendar.stub&R~hj&fxݤ4vendor/jetbrains/phpstorm-stubs/sysvshm/sysvshm.stub>R~hj> 0vendor/jetbrains/phpstorm-stubs/xxtea/xxtea.stubR~hj$nڤ.vendor/jetbrains/phpstorm-stubs/soap/soap.stubGR~hjGZ0vendor/jetbrains/phpstorm-stubs/soap/soap_n.stubR~hju2vendor/jetbrains/phpstorm-stubs/intl/IntlChar.stubL/R~hjL/]tBvendor/jetbrains/phpstorm-stubs/intl/IntlDatePatternGenerator.stubR~hj$J.vendor/jetbrains/phpstorm-stubs/intl/intl.stub.}R~hj.}P,vendor/jetbrains/phpstorm-stubs/lzf/lzf.stubR~hjƤ0vendor/jetbrains/phpstorm-stubs/posix/posix.stubTkR~hjTkd 9vendor/jetbrains/phpstorm-stubs/Zend OPcache/OPcache.stubm R~hjm Im2vendor/jetbrains/phpstorm-stubs/expect/expect.stub R~hj I.Ȥ2vendor/jetbrains/phpstorm-stubs/xdebug/xdebug.stub3R~hj3^Ȥ.vendor/jetbrains/phpstorm-stubs/ssh2/ssh2.stubZR~hjZo.vendor/jetbrains/phpstorm-stubs/odbc/odbc.stubyR~hjyJvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerChangedEvent.stubR~hjpSvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerHeartbeatStartedEvent.stubxR~hjxxKvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/CommandStartedEvent.stubR~hjTLvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/TopologyChangedEvent.stubR~hje4Kvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/TopologyClosedEvent.stubR~hj89Avendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/functions.stubuR~hjuƽgFvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/SDAMSubscriber.stub R~hj ƐLvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/TopologyOpeningEvent.stubR~hjYWuBvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/Subscriber.stubR~hjEvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/LogSubscriber.stubR~hjn̅Mvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/CommandSucceededEvent.stubR~hjuIvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/CommandSubscriber.stubR~hj;OJvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerOpeningEvent.stubvR~hjv62Uvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerHeartbeatSucceededEvent.stubUR~hjU2y{Ivendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerClosedEvent.stubrR~hjr:SRvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/ServerHeartbeatFailedEvent.stub]R~hj]5Jvendor/jetbrains/phpstorm-stubs/mongodb/Monitoring/CommandFailedEvent.stubR~hjc됒3vendor/jetbrains/phpstorm-stubs/mongodb/Server.stub'R~hj';d4vendor/jetbrains/phpstorm-stubs/mongodb/Manager.stub*R~hj*dk>vendor/jetbrains/phpstorm-stubs/mongodb/WriteConcernError.stubR~hjVZ>vendor/jetbrains/phpstorm-stubs/mongodb/ServerDescription.stubR~hj.6vendor/jetbrains/phpstorm-stubs/mongodb/ServerApi.stubR~hj֤;vendor/jetbrains/phpstorm-stubs/mongodb/ReadPreference.stubDR~hjDϣ9vendor/jetbrains/phpstorm-stubs/mongodb/WriteConcern.stubE R~hjE S8vendor/jetbrains/phpstorm-stubs/mongodb/WriteResult.stubd R~hjd ݚ2vendor/jetbrains/phpstorm-stubs/mongodb/Query.stubR~hjԶǤ3vendor/jetbrains/phpstorm-stubs/mongodb/Cursor.stubR~hjH5vendor/jetbrains/phpstorm-stubs/mongodb/CursorId.stubwR~hjw:?8vendor/jetbrains/phpstorm-stubs/mongodb/ReadConcern.stub R~hj w=vendor/jetbrains/phpstorm-stubs/mongodb/ClientEncryption.stubfR~hjf8DZ97vendor/jetbrains/phpstorm-stubs/mongodb/WriteError.stub`R~hj`__K4vendor/jetbrains/phpstorm-stubs/mongodb/Session.stubTR~hjTڸ76vendor/jetbrains/phpstorm-stubs/mongodb/BulkWrite.stub R~hj #Z4vendor/jetbrains/phpstorm-stubs/mongodb/Command.stubR~hj޾d@vendor/jetbrains/phpstorm-stubs/mongodb/TopologyDescription.stubR~hj,Ovendor/jetbrains/phpstorm-stubs/mongodb/Exception/UnexpectedValueException.stubjR~hjjMmQvendor/jetbrains/phpstorm-stubs/mongodb/Exception/ConnectionTimeoutException.stubdR~hjd -;Mvendor/jetbrains/phpstorm-stubs/mongodb/Exception/SSLConnectionException.stub2R~hj2Gvendor/jetbrains/phpstorm-stubs/mongodb/Exception/RuntimeException.stubFR~hjFEIvendor/jetbrains/phpstorm-stubs/mongodb/Exception/BulkWriteException.stubR~hjJvendor/jetbrains/phpstorm-stubs/mongodb/Exception/ConnectionException.stubGR~hjGAlNvendor/jetbrains/phpstorm-stubs/mongodb/Exception/AuthenticationException.stub5R~hj5KPvendor/jetbrains/phpstorm-stubs/mongodb/Exception/ExecutionTimeoutException.stubHR~hjHAEvendor/jetbrains/phpstorm-stubs/mongodb/Exception/LogicException.stubR~hjZŤJvendor/jetbrains/phpstorm-stubs/mongodb/Exception/EncryptionException.stub,R~hj, 5Evendor/jetbrains/phpstorm-stubs/mongodb/Exception/WriteException.stubR~hjGgGvendor/jetbrains/phpstorm-stubs/mongodb/Exception/CommandException.stub R~hj K*Lvendor/jetbrains/phpstorm-stubs/mongodb/Exception/WriteConcernException.stubyR~hjyFvendor/jetbrains/phpstorm-stubs/mongodb/Exception/ServerException.stubR~hj`Ovendor/jetbrains/phpstorm-stubs/mongodb/Exception/InvalidArgumentException.stubSR~hjS5k:@vendor/jetbrains/phpstorm-stubs/mongodb/Exception/Exception.stub:R~hj:M4vendor/jetbrains/phpstorm-stubs/mongodb/mongodb.stubFR~hjF.@vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Unserializable.stubR~hj"t_=vendor/jetbrains/phpstorm-stubs/mongodb/BSON/PackedArray.stubR~hjפAvendor/jetbrains/phpstorm-stubs/mongodb/BSON/MinKeyInterface.stubR~hjGuEvendor/jetbrains/phpstorm-stubs/mongodb/BSON/Decimal128Interface.stub8R~hj8L=p@vendor/jetbrains/phpstorm-stubs/mongodb/BSON/RegexInterface.stubeR~hjemFvendor/jetbrains/phpstorm-stubs/mongodb/BSON/UTCDateTimeInterface.stub+R~hj+2,<vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Decimal128.stubR~hjWϤAvendor/jetbrains/phpstorm-stubs/mongodb/BSON/MaxKeyInterface.stubR~hj#;vendor/jetbrains/phpstorm-stubs/mongodb/BSON/functions.stub^ R~hj^ 9;vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Undefined.stubOR~hjOU6vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Type.stubR~hj'J-8vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Binary.stub R~hj ?8vendor/jetbrains/phpstorm-stubs/mongodb/BSON/MinKey.stubR~hj =vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Persistable.stubR~hj!tDvendor/jetbrains/phpstorm-stubs/mongodb/BSON/TimestampInterface.stubR~hjE p8vendor/jetbrains/phpstorm-stubs/mongodb/BSON/MaxKey.stubR~hjW:vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Iterator.stubR~hj 7vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Int64.stubOR~hjO$>vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Serializable.stubR~hj@}Cvendor/jetbrains/phpstorm-stubs/mongodb/BSON/ObjectIdInterface.stubR~hjC_8vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Symbol.stub/R~hj/RAvendor/jetbrains/phpstorm-stubs/mongodb/BSON/BinaryInterface.stubR~hj0>F7vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Regex.stubVR~hjVuk<vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Javascript.stubR~hj#<Ѥ:vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Document.stubR~hjhbT;vendor/jetbrains/phpstorm-stubs/mongodb/BSON/Timestamp.stubq R~hjq gH=vendor/jetbrains/phpstorm-stubs/mongodb/BSON/UTCDateTime.stubN R~hjN dEvendor/jetbrains/phpstorm-stubs/mongodb/BSON/JavascriptInterface.stubR~hj]O؇;vendor/jetbrains/phpstorm-stubs/mongodb/BSON/DBPointer.stubR~hj7:vendor/jetbrains/phpstorm-stubs/mongodb/BSON/ObjectId.stubR~hjtl?<vendor/jetbrains/phpstorm-stubs/mongodb/CursorInterface.stubR~hj ,vendor/jetbrains/phpstorm-stubs/pam/pam.stubR~hjs]7>vendor/jetbrains/phpstorm-stubs/win32service/win32service.stubEcR~hjEcRۤ.vendor/jetbrains/phpstorm-stubs/wddx/wddx.stub R~hj [L4vendor/jetbrains/phpstorm-stubs/decimal/decimal.stub<<R~hj<<zy4vendor/jetbrains/phpstorm-stubs/inotify/inotify.stubNR~hjNn.vendor/jetbrains/phpstorm-stubs/hash/hash.stubER~hjE̠4vendor/jetbrains/phpstorm-stubs/gettext/gettext.stub\R~hj\f2vendor/jetbrains/phpstorm-stubs/bcmath/bcmath.stub#R~hj#b2vendor/jetbrains/phpstorm-stubs/mcrypt/mcrypt.stub_R~hj_iXV2vendor/jetbrains/phpstorm-stubs/cubrid/cubrid.stubtR~hjt ~4vendor/jetbrains/phpstorm-stubs/sqlite3/sqlite3.stubfR~hjfԽ.vendor/jetbrains/phpstorm-stubs/ldap/ldap.stubR~hj5vendor/jetbrains/phpstorm-stubs/ldap/ResultEntry.stubIR~hjIPx_0vendor/jetbrains/phpstorm-stubs/ldap/Result.stubDR~hjDvZ4vendor/jetbrains/phpstorm-stubs/ldap/Connection.stubHR~hjH4vendor/jetbrains/phpstorm-stubs/uv/uv_functions.stubfR~hjft*vendor/jetbrains/phpstorm-stubs/uv/UV.stub R~hj h<6vendor/jetbrains/phpstorm-stubs/rdkafka/constants.stub#R~hj# 6vendor/jetbrains/phpstorm-stubs/rdkafka/functions.stubR~hj>vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/TopicConf.stub R~hj x<vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Message.stubrR~hjrbWHvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/KafkaErrorException.stubR~hjQGvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/KafkaConsumerTopic.stubR~hjC٤=vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata.stubR~hjώCvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/TopicPartition.stub!R~hj!9<9vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Conf.stubqR~hjq8Bvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/ConsumerTopic.stubR~hj>Bvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/ProducerTopic.stubaR~hja=vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Producer.stub9R~hj9߲=vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Consumer.stubR~hjTYDvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata/Broker.stubR~hjIQuRCvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata/Topic.stubR~hjcGvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata/Partition.stubR~hjHvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Metadata/Collection.stubR~hjLBvendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/KafkaConsumer.stubq R~hjq F!:vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Topic.stub{R~hj{t{=>vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Exception.stubAR~hjAD/Q:vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka/Queue.stubR~hjhh4vendor/jetbrains/phpstorm-stubs/rdkafka/RdKafka.stubqR~hjq;Ҥ0vendor/jetbrains/phpstorm-stubs/mongo/mongo.stubR~hj;n.vendor/jetbrains/phpstorm-stubs/zend/zend.stubXR~hjXB 0vendor/jetbrains/phpstorm-stubs/zend/zend_f.stub.R~hj.6x0vendor/jetbrains/phpstorm-stubs/zend/zend_d.stubR~hj-|j2vendor/jetbrains/phpstorm-stubs/recode/recode.stubR~hjO4vendor/jetbrains/phpstorm-stubs/sockets/sockets.stub=R~hj=`p4vendor/jetbrains/phpstorm-stubs/meminfo/meminfo.stubR~hjrbɤ2vendor/jetbrains/phpstorm-stubs/brotli/brotli.stubR~hjp<5ʤ2vendor/jetbrains/phpstorm-stubs/radius/radius.stubGR~hjG4g2vendor/jetbrains/phpstorm-stubs/SQLite/SQLite.stublR~hjl L,vendor/jetbrains/phpstorm-stubs/eio/eio.stubfyR~hjfy2vendor/jetbrains/phpstorm-stubs/apache/apache.stub-R~hj-LBvendor/jetbrains/phpstorm-stubs/uploadprogress/uploadprogress.stub R~hj r݋8vendor/jetbrains/phpstorm-stubs/xmlwriter/xmlwriter.stubR~hjO< 6vendor/jetbrains/phpstorm-stubs/memcache/memcache.stub$RR~hj$RU*4vendor/jetbrains/phpstorm-stubs/imagick/imagick.stubmR~hjm~4vendor/jetbrains/phpstorm-stubs/openssl/openssl.stubR~hjФ0vendor/jetbrains/phpstorm-stubs/gnupg/gnupg.stubZIR~hjZI 3,vendor/jetbrains/phpstorm-stubs/dba/dba.stubE0R~hjE0Nԣ3vendor/jetbrains/phpstorm-stubs/dba/Connection.stubGR~hjGo@33vendor/jetbrains/phpstorm-stubs/solr/constants.stubDR~hjD c9vendor/jetbrains/phpstorm-stubs/solr/Utils/SolrUtils.stub R~hj O:vendor/jetbrains/phpstorm-stubs/solr/Utils/SolrObject.stub R~hj t 3vendor/jetbrains/phpstorm-stubs/solr/functions.stubR~hjAA@vendor/jetbrains/phpstorm-stubs/solr/Documents/SolrDocument.stub/R~hj/F&Evendor/jetbrains/phpstorm-stubs/solr/Documents/SolrInputDocument.stub&R~hj&?J Evendor/jetbrains/phpstorm-stubs/solr/Documents/SolrDocumentField.stubR~hj \Fvendor/jetbrains/phpstorm-stubs/solr/Queries/SolrModifiableParams.stubkR~hjk%Avendor/jetbrains/phpstorm-stubs/solr/Queries/SolrDisMaxQuery.stub-R~hj-I!;vendor/jetbrains/phpstorm-stubs/solr/Queries/SolrQuery.stubs>R~hjs><vendor/jetbrains/phpstorm-stubs/solr/Queries/SolrParams.stubR~hj(DFvendor/jetbrains/phpstorm-stubs/solr/Queries/SolrCollapseFunction.stubR~hjE Bvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrException.stubR~hj&[vendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrMissingMandatoryParameterException.stubR~hjnRvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrIllegalOperationException.stubR~hj-N%Qvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrIllegalArgumentException.stubR~hj)4Hvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrClientException.stubsR~hjsGPHvendor/jetbrains/phpstorm-stubs/solr/Exceptions/SolrServerException.stubyR~hjyC$4vendor/jetbrains/phpstorm-stubs/solr/SolrClient.stubMR~hjMC|@vendor/jetbrains/phpstorm-stubs/solr/Responses/SolrResponse.stubR~hj/I%Dvendor/jetbrains/phpstorm-stubs/solr/Responses/SolrPingResponse.stubR~hjޡޤGvendor/jetbrains/phpstorm-stubs/solr/Responses/SolrGenericResponse.stub+R~hj+Evendor/jetbrains/phpstorm-stubs/solr/Responses/SolrQueryResponse.stubR~hjɤFvendor/jetbrains/phpstorm-stubs/solr/Responses/SolrUpdateResponse.stub%R~hj%>H٤2vendor/jetbrains/phpstorm-stubs/filter/filter.stub;R~hj;v2֬0vendor/jetbrains/phpstorm-stubs/stomp/stomp.stubA"R~hjA"!K2vendor/jetbrains/phpstorm-stubs/xcache/xcache.stubR~hj^).vendor/jetbrains/phpstorm-stubs/pcre/pcre.stubzPR~hjzPY,vendor/jetbrains/phpstorm-stubs/yaf/yaf.stub`R~hj`k6vendor/jetbrains/phpstorm-stubs/yaf/yaf_namespace.stub^[R~hj^[vD,vendor/jetbrains/phpstorm-stubs/ast/ast.stub [R~hj [nΤ8vendor/jetbrains/phpstorm-stubs/interbase/interbase.stubR~hj@vendor/jetbrains/phpstorm-stubs/opentelemetry/opentelemetry.stubPR~hjP<vendor/jetbrains/phpstorm-stubs/libvirt-php/libvirt-php.stub9R~hj9:`,vendor/jetbrains/phpstorm-stubs/gmp/gmp.stubuR~hjuO*vendor/nette/utils/src/Utils/Paginator.phpR~hj&vendor/nette/utils/src/Utils/Image.php`R~hj`s}S(vendor/nette/utils/src/Utils/Strings.phpqQR~hjqQA+vendor/nette/utils/src/Utils/Reflection.php{7R~hj{7,,*vendor/nette/utils/src/Utils/ArrayList.php R~hj ŧ+vendor/nette/utils/src/Utils/Validators.php+R~hj+pqW(vendor/nette/utils/src/Utils/Helpers.php R~hj 5dZ,vendor/nette/utils/src/Utils/ObjectMixin.phpR~hj+vendor/nette/utils/src/Utils/FileSystem.php R~hj H %vendor/nette/utils/src/Utils/Json.phpR~hjC*vendor/nette/utils/src/Utils/ArrayHash.phpNR~hjN(n+vendor/nette/utils/src/Iterators/Mapper.phpR~hj39&4vendor/nette/utils/src/Iterators/CachingIterator.php R~hj <Qw(vendor/nette/utils/src/compatibility.phpR~hj1a%vendor/nette/utils/src/exceptions.phpR~hj )vendor/nette/utils/src/HtmlStringable.phplR~hjlD&vendor/nette/utils/src/SmartObject.phpR~hj@ 4ؤ%vendor/nette/utils/src/Translator.phpR~hj g&vendor/nette/utils/src/StaticClass.phpR~hj8vendor/nette/utils/ncs.php8R~hj85vendor/nette/utils/ncs.xmlR~hj(vendor/nette/finder/src/Utils/Finder.php*R~hj*aFvendor/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php)R~hj)q@vendor/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.phpQR~hjQ(o(5vendor/nette/bootstrap/src/Bootstrap/Configurator.php,R~hj,O+vendor/nette/bootstrap/src/Configurator.phpR~hjq?p9vendor/nette/robot-loader/src/RobotLoader/RobotLoader.php@R~hj@Zg<6vendor/nette/php-generator/src/PhpGenerator/Dumper.php8#R~hj8#>Avendor/nette/php-generator/src/PhpGenerator/PromotedParameter.phpR~hj8vendor/nette/php-generator/src/PhpGenerator/Constant.phpR~hjH7vendor/nette/php-generator/src/PhpGenerator/Printer.php[4R~hj[4Mo7vendor/nette/php-generator/src/PhpGenerator/Closure.phpR~hj 7vendor/nette/php-generator/src/PhpGenerator/Literal.php R~hj &P:vendor/nette/php-generator/src/PhpGenerator/PsrPrinter.phpR~hj Ӣ6vendor/nette/php-generator/src/PhpGenerator/Method.php R~hj TV[7vendor/nette/php-generator/src/PhpGenerator/Helpers.phpR~hja8vendor/nette/php-generator/src/PhpGenerator/TraitUse.phpR~hj55>vendor/nette/php-generator/src/PhpGenerator/GlobalFunction.phpR~hj48:vendor/nette/php-generator/src/PhpGenerator/PhpLiteral.phpR~hjO78vendor/nette/php-generator/src/PhpGenerator/EnumCase.phpR~hjG"9vendor/nette/php-generator/src/PhpGenerator/Parameter.php+ R~hj+ + 9vendor/nette/php-generator/src/PhpGenerator/Attribute.php_R~hj_p7vendor/nette/php-generator/src/PhpGenerator/Factory.php3R~hj3Ĥ8vendor/nette/php-generator/src/PhpGenerator/Property.php R~hj 2ޤ<vendor/nette/php-generator/src/PhpGenerator/PhpNamespace.phpC'R~hjC'l7vendor/nette/php-generator/src/PhpGenerator/PhpFile.phpR~hjXwʤ9vendor/nette/php-generator/src/PhpGenerator/ClassType.phpF;R~hjF;{9vendor/nette/php-generator/src/PhpGenerator/Extractor.php >R~hj >4vendor/nette/php-generator/src/PhpGenerator/Type.phpXR~hjXR"eCvendor/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php0R~hj0] 3Fvendor/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php<R~hj<@vendor/nette/php-generator/src/PhpGenerator/Traits/NameAware.phpR~hjPh9Cvendor/nette/php-generator/src/PhpGenerator/Traits/CommentAware.phpR~hj~Evendor/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.phpR~hjZr"vendor/nette/php-generator/ncs.php'R~hj'|&vendor/nette/neon/PATCHES.txtR~hj0Ovendor/nette/neon/bin/neon-lintKR~hjK\b$vendor/nette/neon/src/Neon/Token.php}R~hj}3vendor/nette/neon/src/Neon/Node/EntityChainNode.phpR~hj N2vendor/nette/neon/src/Neon/Node/BlockArrayNode.phpR~hj-ӝ/vendor/nette/neon/src/Neon/Node/LiteralNode.phpE R~hjE :|3vendor/nette/neon/src/Neon/Node/InlineArrayNode.php_R~hj_!^1vendor/nette/neon/src/Neon/Node/ArrayItemNode.phpR~hjm.vendor/nette/neon/src/Neon/Node/StringNode.php R~hj 89".-vendor/nette/neon/src/Neon/Node/ArrayNode.phpR~hj.vendor/nette/neon/src/Neon/Node/EntityNode.phpYR~hjYE+#vendor/nette/neon/src/Neon/Neon.phpR~hj*m*vendor/nette/neon/src/Neon/TokenStream.php.R~hj.f!&vendor/nette/neon/src/Neon/Encoder.phph R~hjh Yդ&vendor/nette/neon/src/Neon/Decoder.phpR~hj?B%vendor/nette/neon/src/Neon/Parser.php!R~hj!$m$vendor/nette/neon/src/Neon/Lexer.php R~hj 7@*%vendor/nette/neon/src/Neon/Entity.phpR~hjBl\#vendor/nette/neon/src/Neon/Node.phpR~hj(vendor/nette/neon/src/Neon/Exception.php7R~hj7r(vendor/nette/neon/src/Neon/Traverser.phpjR~hjjvendor/nette/di/PATCHES.txtR~hj%vendor/nette/di/src/compatibility.phpR~hjm?Fvendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.tab.phtmlR~hj>F-Hvendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.panel.phtmlR~hj]띦6vendor/nette/di/src/Bridges/DITracy/ContainerPanel.phpi R~hji +vendor/nette/di/src/DI/ContainerBuilder.php+R~hj+i^9vendor/nette/di/src/DI/Definitions/ImportedDefinition.phpR~hjp0vendor/nette/di/src/DI/Definitions/Reference.phpR~hjwR8vendor/nette/di/src/DI/Definitions/FactoryDefinition.phpG#R~hjG##1vendor/nette/di/src/DI/Definitions/Definition.php'R~hj' #8vendor/nette/di/src/DI/Definitions/LocatorDefinition.phpuR~hjuI$0vendor/nette/di/src/DI/Definitions/Statement.phpR~hjWi9vendor/nette/di/src/DI/Definitions/AccessorDefinition.php$R~hj$S8vendor/nette/di/src/DI/Definitions/ServiceDefinition.phpiR~hji "vendor/nette/di/src/DI/Helpers.php#R~hj#Vq%vendor/nette/di/src/DI/exceptions.php6R~hj6Vݤ6vendor/nette/di/src/DI/Extensions/DefinitionSchema.phpoR~hjo7#H9vendor/nette/di/src/DI/Extensions/ParametersExtension.php{R~hj{ /8vendor/nette/di/src/DI/Extensions/ConstantsExtension.phpR~hj,Lf5vendor/nette/di/src/DI/Extensions/InjectExtension.phpR~hj}2vendor/nette/di/src/DI/Extensions/PhpExtension.phpR~hj8vendor/nette/di/src/DI/Extensions/DecoratorExtension.phpg R~hjg ,Â7vendor/nette/di/src/DI/Extensions/ServicesExtension.phpR~hjI1vendor/nette/di/src/DI/Extensions/DIExtension.php9 R~hj9 X9vendor/nette/di/src/DI/Extensions/ExtensionsExtension.phpR~hj_r]5vendor/nette/di/src/DI/Extensions/SearchExtension.phpR~hjѤ%vendor/nette/di/src/DI/Autowiring.phpcR~hjctc,vendor/nette/di/src/DI/DependencyChecker.phpR~hj7+vendor/nette/di/src/DI/DynamicParameter.phpoR~hjoY%p#vendor/nette/di/src/DI/Compiler.php%R~hj%l=qJ,vendor/nette/di/src/DI/Attributes/Inject.php!R~hj!K)vendor/nette/di/src/DI/Config/Helpers.php%R~hj%څ`t)vendor/nette/di/src/DI/Config/Adapter.phpR~hj>פ(vendor/nette/di/src/DI/Config/Loader.php4R~hj4{a 6vendor/nette/di/src/DI/Config/Adapters/NeonAdapter.phpR~hjŊ)5vendor/nette/di/src/DI/Config/Adapters/PhpAdapter.phpR~hj&Ǥ,vendor/nette/di/src/DI/CompilerExtension.phpR~hj(*vendor/nette/di/src/DI/ContainerLoader.phpLR~hjLɤ#vendor/nette/di/src/DI/Resolver.phpbR~hjb$vendor/nette/di/src/DI/Container.php:,R~hj:,QL'vendor/nette/di/src/DI/PhpGenerator.phpR~hj*vendor/nette/schema/src/Schema/Message.php R~hj 'C;%*vendor/nette/schema/src/Schema/Context.phpR~hjB ,vendor/nette/schema/src/Schema/Processor.php R~hj 5*vendor/nette/schema/src/Schema/Helpers.php R~hj n3vendor/nette/schema/src/Schema/DynamicParameter.phpR~hj; )vendor/nette/schema/src/Schema/Expect.php R~hj Q)vendor/nette/schema/src/Schema/Schema.phpyR~hjyST0vendor/nette/schema/src/Schema/Elements/Base.phpR~hj5u1vendor/nette/schema/src/Schema/Elements/AnyOf.phpVR~hjV}j5vendor/nette/schema/src/Schema/Elements/Structure.phpR~hji?l0vendor/nette/schema/src/Schema/Elements/Type.phpR~hj 4m6vendor/nette/schema/src/Schema/ValidationException.phpR~hjx4vendor/evenement/evenement/src/EventEmitterTrait.phpYR~hjY>d/vendor/evenement/evenement/src/EventEmitter.phprR~hjr!/g8vendor/evenement/evenement/src/EventEmitterInterface.phpR~hjb"vendor/evenement/evenement/LICENSE R~hj {I=#vendor/composer/autoload_static.phpMR~hjM֣q%vendor/composer/ca-bundle/PATCHES.txtR~hjrbmW(vendor/composer/ca-bundle/res/cacert.pemzR~hjz%O*vendor/composer/ca-bundle/src/CaBundle.php+R~hj+ Ǥ!vendor/composer/ca-bundle/LICENSER~hj*!^`%vendor/composer/autoload_classmap.phpR~hjTu-vendor/composer/xdebug-handler/src/Status.phpeR~hjez~[0vendor/composer/xdebug-handler/src/PhpConfig.phpR~hjڤ.vendor/composer/xdebug-handler/src/Process.phpn R~hjn pA4vendor/composer/xdebug-handler/src/XdebugHandler.php}TR~hj}TxӤ&vendor/composer/xdebug-handler/LICENSE)R~hj)#;^vendor/composer/installed.phpR~hjz!vendor/composer/autoload_real.phpR~hjD5'vendor/composer/autoload_namespaces.phpR~hj/t)vendor/composer/semver/src/Comparator.phpb R~hjb hi4vendor/composer/semver/src/Constraint/Constraint.php0R~hj0Mj=vendor/composer/semver/src/Constraint/MatchNoneConstraint.phpR~hj9vendor/composer/semver/src/Constraint/MultiConstraint.php@#R~hj@#t!w/vendor/composer/semver/src/Constraint/Bound.phpE R~hjE Ji =vendor/composer/semver/src/Constraint/ConstraintInterface.phpR~hjhf<vendor/composer/semver/src/Constraint/MatchAllConstraint.phpR~hj's7'vendor/composer/semver/src/Interval.phpR~hj ݤ%vendor/composer/semver/src/Semver.phpT R~hjT dj,vendor/composer/semver/src/VersionParser.phpTR~hjT{$ȳ/vendor/composer/semver/src/CompilingMatcher.php) R~hj) Fz(vendor/composer/semver/src/Intervals.phpNR~hjNvendor/composer/semver/LICENSER~hjBh%vendor/composer/InstalledVersions.phpCR~hjCBbԤ.vendor/react/socket/src/ConnectorInterface.php=R~hj=p,vendor/react/socket/src/StreamEncryption.phpR~hj˛|vendor/react/socket/LICENSEuR~hju{0vendor/react/event-loop/src/StreamSelectLoop.php/R~hj/D@ۤ4vendor/react/event-loop/src/Tick/FutureTickQueue.phpR~hjҩ)vendor/react/event-loop/src/ExtEvLoop.phpR~hj6\-vendor/react/event-loop/src/LoopInterface.phpKR~hjK#N&$vendor/react/event-loop/src/Loop.php9R~hj9?.vendor/react/event-loop/src/SignalsHandler.php+R~hj+^.vendor/react/event-loop/src/TimerInterface.phpR~hjw#B,vendor/react/event-loop/src/ExtLibevLoop.phpR~hjb*L+vendor/react/event-loop/src/Timer/Timer.php6R~hj6&ݤ,vendor/react/event-loop/src/Timer/Timers.php R~hj g'vendor/react/event-loop/src/Factory.php<R~hj</vendor/react/event-loop/src/ExtLibeventLoop.php!R~hj!T,vendor/react/event-loop/src/ExtEventLoop.phpR~hjNz)vendor/react/event-loop/src/ExtUvLoop.php#R~hj#Wvendor/react/event-loop/LICENSEuR~hju{)vendor/react/cache/src/CacheInterface.php0 R~hj0 O%vendor/react/cache/src/ArrayCache.php_R~hj_CbgPvendor/react/cache/LICENSEuR~hju{ vendor/react/stream/src/Util.phpR~hj2vendor/react/stream/src/WritableResourceStream.phpR~hjפ0vendor/react/stream/src/DuplexResourceStream.phpR~hj"{3vendor/react/stream/src/ReadableStreamInterface.php7R~hj7b3vendor/react/stream/src/WritableStreamInterface.php9R~hj92vendor/react/stream/src/ReadableResourceStream.phpR~hj$Ӥ1vendor/react/stream/src/DuplexStreamInterface.phpR~hjXB:)vendor/react/stream/src/ThroughStream.phpR~hj(\+vendor/react/stream/src/CompositeStream.phphR~hjhepvendor/react/stream/LICENSEuR~hju{vendor/react/http/PATCHES.txtR~hj!=y@vendor/react/http/src/Middleware/RequestBodyBufferMiddleware.php3R~hj3f%@vendor/react/http/src/Middleware/RequestBodyParserMiddleware.php^R~hj^/Fvendor/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.phpR~hjm1?vendor/react/http/src/Middleware/StreamingRequestMiddleware.php/ R~hj/ u)vendor/react/http/src/Io/UploadedFile.php R~hj > ̤$vendor/react/http/src/Io/IniUtil.phpsR~hjsIc+vendor/react/http/src/Io/ChunkedEncoder.phpQR~hjQv.vendor/react/http/src/Io/PauseBufferStream.phpR~hj4$vendor/react/http/src/HttpServer.php<R~hj<܅'vendor/react/http/src/Client/Client.phpR~hjfeA vendor/react/http/src/Server.phpFR~hjF8两3vendor/react/http/src/Message/ResponseException.phpR~hj6%vendor/react/http/src/Message/Uri.phpL%R~hjL%GKV)vendor/react/http/src/Message/Request.php" R~hj" @}Ƥ/vendor/react/http/src/Message/ServerRequest.php/R~hj/J=*vendor/react/http/src/Message/Response.php}9R~hj}9hVvendor/react/http/LICENSEuR~hju{$vendor/react/async/src/functions.phpBR~hjB-,vendor/react/async/src/functions_include.phpR~hj~-vendor/react/async/LICENSE^R~hj^yT*vendor/react/child-process/src/Process.php:R~hj:\9"vendor/react/child-process/LICENSEuR~hju{0vendor/react/dns/src/Query/HostsFileExecutor.php R~hj E+vendor/react/dns/src/Query/CoopExecutor.php R~hj .vendor/react/dns/src/Query/CachingExecutor.phpU R~hjU /vendor/react/dns/src/Query/FallbackExecutor.phpR~hjd4vendor/react/dns/src/Query/CancellationException.phpvR~hjv@9vendor/react/dns/src/Query/SelectiveTransportExecutor.php R~hj r0vendor/react/dns/src/Query/ExecutorInterface.phpR~hj4Ƈ3vendor/react/dns/src/Query/UdpTransportExecutor.phph!R~hjh!"$vendor/react/dns/src/Query/Query.phpR~hj{gH/vendor/react/dns/src/Query/TimeoutException.phpjR~hjjk.vendor/react/dns/src/Query/TimeoutExecutor.php R~hj ?_,vendor/react/dns/src/Query/RetryExecutor.phpK R~hjK mܤ3vendor/react/dns/src/Query/TcpTransportExecutor.php6R~hj6E+E0vendor/react/dns/src/RecordNotFoundException.phpkR~hjkT&vendor/react/dns/src/Config/Config.phpKR~hjK4 )vendor/react/dns/src/Config/HostsFile.phpR~hj|i/&vendor/react/dns/src/Model/Message.phpR~hj<%vendor/react/dns/src/Model/Record.phpR~hj.^ .vendor/react/dns/src/Protocol/BinaryDumper.phpQR~hjQǜ(vendor/react/dns/src/Protocol/Parser.php,R~hj,pZ)vendor/react/dns/src/Resolver/Factory.php R~hj *vendor/react/dns/src/Resolver/Resolver.phpR~hjΗ3vendor/react/dns/src/Resolver/ResolverInterface.phpR~hjK+vendor/react/dns/src/BadServerException.phpfR~hjfvendor/react/dns/LICENSEuR~hju{6vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.phpR~hjYդ8vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.phpYR~hjY=ߤ;vendor/phpstan/phpdoc-parser/src/Parser/ParserException.phpg R~hjg u/g;vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php<'R~hj<'t;vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php> R~hj> +t99vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php#R~hj#G#|0vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.phpR~hj gIvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.phpR~hj4|ͤDvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php;R~hj;g @vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.phpR~hj0KPvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/QuoteAwareConstExprStringNode.phpP R~hjP ]Fvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.phpR~hjč Evendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.phpFR~hjFDEvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.phpR~hj Gvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.phpR~hjҳNvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.phpuR~hju,wѤAvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.phpR~hj[eDvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php;R~hj;ĉEEvendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php=R~hj=P1w1Hvendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php!R~hj!>vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.phpR~hj/,|;vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.phpR~hj!.ߤAvendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.phpNR~hjN@;vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php?R~hj?T=vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.phpRR~hjRq`6vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.phpR~hj]ˤMvendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.phpAR~hjA>a<vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php$R~hj$̤Bvendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.phpFR~hjF76:vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php(R~hj(+œ;vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.phpR~hjΞ@vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.phpR~hjԯBvendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php_R~hj_HǤ>vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.phpR~hjK6ˤ@vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.phpR~hjF=vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.phpSR~hjSAvendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.phpR~hjGvendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.phpR~hj\6=vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.phpMR~hjMͥRBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.phpR~hj6Kvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.phpR~hjpк>vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.phpR~hjNIvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.phpR~hj<Dvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php2R~hj2mKvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php3R~hj3뉤=vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php(R~hj(XrCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.phpR~hjuE此Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.phpR~hj9eBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.phppR~hjp>䍤Bvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.phpR~hj4>ˤCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.phpR~hj>NFvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.phpTR~hjT|mKvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.phpR~hj(TͤJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.phpLR~hjL0BIvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.phpR~hjLM*Mvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.phpR~hj^Dvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php-R~hj-Y?ŤBvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.phpR~hjHJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.phpR~hjB'Cvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.phpR~hj&Avendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.phpR~hjaLvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php:R~hj:ę:vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php65R~hj65}nzDvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php:R~hj:UFvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.phpR~hj??vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.phpR~hjFvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.phpR~hj2w[vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.phpR~hj5SUvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.phpR~hjOؼJvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.phpR~hjPoAvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.phpR~hjHvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.phpR~hjĚdEvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.phpwR~hjw6&"!@vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.phpR~hj?vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.phpBR~hjBkN-Vvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.phpR~hjZtCvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.phpR~hj2KMvendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.phpR~hj:Eˤ<vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.phpR~hj/6vendor/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php*R~hj*B,2vendor/phpstan/phpdoc-parser/src/Ast/Attribute.php9R~hj94vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php R~hj oCvendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.phpR~hjd-vendor/phpstan/phpdoc-parser/src/Ast/Node.phpwR~hjw?S; 7vendor/phpstan/phpdoc-parser/src/Ast/NodeAttributes.phpR~hjYXT4vendor/phpstan/phpdoc-parser/src/Printer/Printer.phpjR~hjji1M3vendor/phpstan/phpdoc-parser/src/Printer/Differ.phpR~hjRǀ5vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.phpR~hjZ6$vendor/phpstan/phpdoc-parser/LICENSE.R~hj.-+vendor/phpstan/php-8-stubs/Php8StubsMap.phpR~hj*4ڤ;vendor/phpstan/php-8-stubs/stubs/Zend/get_defined_vars.stubER~hjE[m6vendor/phpstan/php-8-stubs/stubs/Zend/strncasecmp.stubTR~hjT*b 7vendor/phpstan/php-8-stubs/stubs/Zend/trait_exists.stubMR~hjMϐ8=vendor/phpstan/php-8-stubs/stubs/Zend/ArgumentCountError.stub7R~hj7f-@vendor/phpstan/php-8-stubs/stubs/Zend/get_defined_constants.stubbR~hjbVɤ7vendor/phpstan/php-8-stubs/stubs/Zend/zend_version.stubMR~hjM吤:vendor/phpstan/php-8-stubs/stubs/Zend/ArithmeticError.stub0R~hj0ڏ:vendor/phpstan/php-8-stubs/stubs/Zend/function_exists.stub<R~hj<$m8vendor/phpstan/php-8-stubs/stubs/Zend/trigger_error.stubR~hj;c5vendor/phpstan/php-8-stubs/stubs/Zend/ValueError.stub+R~hj+&Ȳ9vendor/phpstan/php-8-stubs/stubs/Zend/is_subclass_of.stubR~hj1=vendor/phpstan/php-8-stubs/stubs/Zend/get_included_files.stubGR~hjGT @vendor/phpstan/php-8-stubs/stubs/Zend/set_exception_handler.stubgR~hjg#\%4vendor/phpstan/php-8-stubs/stubs/Zend/TypeError.stub*R~hj*֤/vendor/phpstan/php-8-stubs/stubs/Zend/is_a.stubR~hjߤ5vendor/phpstan/php-8-stubs/stubs/Zend/Deprecated.stub_R~hj_<vendor/phpstan/php-8-stubs/stubs/Zend/get_class_methods.stubdR~hjd]S4vendor/phpstan/php-8-stubs/stubs/Zend/Throwable.stuboR~hjo׍x>vendor/phpstan/php-8-stubs/stubs/Zend/DivisionByZeroError.stub>R~hj>8դ4vendor/phpstan/php-8-stubs/stubs/Zend/get_class.stub@R~hj@Ap9vendor/phpstan/php-8-stubs/stubs/Zend/ErrorException.stub R~hj  m9vendor/phpstan/php-8-stubs/stubs/Zend/zend_thread_id.stubIR~hjI0o8vendor/phpstan/php-8-stubs/stubs/Zend/WeakReference.stubR~hjqq7vendor/phpstan/php-8-stubs/stubs/Zend/func_get_arg.stub7R~hj7<vendor/phpstan/php-8-stubs/stubs/Zend/set_error_handler.stub~R~hj~SQ<vendor/phpstan/php-8-stubs/stubs/Zend/gc_collect_cycles.stub-R~hj-W1vendor/phpstan/php-8-stubs/stubs/Zend/strcmp.stubBR~hjB07vendor/phpstan/php-8-stubs/stubs/Zend/CompileError.stub-R~hj-5vendor/phpstan/php-8-stubs/stubs/Zend/gc_disable.stub'R~hj'@vendor/phpstan/php-8-stubs/stubs/Zend/debug_print_backtrace.stubRR~hjRL:vendor/phpstan/php-8-stubs/stubs/Zend/debug_backtrace.stubR~hjw|z6vendor/phpstan/php-8-stubs/stubs/Zend/Traversable.stubCR~hjCł8vendor/phpstan/php-8-stubs/stubs/Zend/get_resources.stub?R~hj?P2鮤;vendor/phpstan/php-8-stubs/stubs/Zend/extension_loaded.stub>R~hj>2[놤:vendor/phpstan/php-8-stubs/stubs/Zend/property_exists.stub{R~hj{yBvendor/phpstan/php-8-stubs/stubs/Zend/get_declared_interfaces.stubLR~hjLu 56vendor/phpstan/php-8-stubs/stubs/Zend/enum_exists.stub\R~hj\ԩ Bvendor/phpstan/php-8-stubs/stubs/Zend/get_mangled_object_vars.stubCR~hjC2vendor/phpstan/php-8-stubs/stubs/Zend/Closure.stubR~hjɵ(5vendor/phpstan/php-8-stubs/stubs/Zend/Stringable.stubJR~hjJ}ވ?vendor/phpstan/php-8-stubs/stubs/Zend/get_declared_classes.stubIR~hjI\8vendor/phpstan/php-8-stubs/stubs/Zend/func_get_args.stub+R~hj+6Avendor/phpstan/php-8-stubs/stubs/Zend/AllowDynamicProperties.stubR~hj]%5vendor/phpstan/php-8-stubs/stubs/Zend/BackedEnum.stubR~hjH+@vendor/phpstan/php-8-stubs/stubs/Zend/get_defined_functions.stubgR~hjg^&>vendor/phpstan/php-8-stubs/stubs/Zend/get_extension_funcs.stub_R~hj_!S1vendor/phpstan/php-8-stubs/stubs/Zend/define.stubR~hjn>vendor/phpstan/php-8-stubs/stubs/Zend/UnhandledMatchError.stub4R~hj4-A0vendor/phpstan/php-8-stubs/stubs/Zend/Error.stubR~hje;vendor/phpstan/php-8-stubs/stubs/Zend/InternalIterator.stubR~hj }@vendor/phpstan/php-8-stubs/stubs/Zend/restore_error_handler.stubR~hj$P%)8vendor/phpstan/php-8-stubs/stubs/Zend/gc_mem_caches.stub0R~hj0c2vendor/phpstan/php-8-stubs/stubs/Zend/WeakMap.stubDR~hjD-<vendor/phpstan/php-8-stubs/stubs/Zend/get_resource_type.stubZR~hjZ(ˤ4vendor/phpstan/php-8-stubs/stubs/Zend/gc_enable.stub&R~hj&V/4vendor/phpstan/php-8-stubs/stubs/Zend/Attribute.stubR~hj{3vendor/phpstan/php-8-stubs/stubs/Zend/Iterator.stubR~hj]燤2vendor/phpstan/php-8-stubs/stubs/Zend/defined.stub9R~hj9n*b7vendor/phpstan/php-8-stubs/stubs/Zend/class_exists.stubMR~hjM*CF5vendor/phpstan/php-8-stubs/stubs/Zend/user_error.stubR~hjR~hj>0O;vendor/phpstan/php-8-stubs/stubs/Zend/interface_exists.stubUR~hjUy8vendor/phpstan/php-8-stubs/stubs/Zend/func_num_args.stub)R~hj)OPh>vendor/phpstan/php-8-stubs/stubs/Zend/get_declared_traits.stubHR~hjH{8 Cvendor/phpstan/php-8-stubs/stubs/Zend/ClosedGeneratorException.stub=R~hj=kQ:vendor/phpstan/php-8-stubs/stubs/Zend/error_reporting.stubCR~hjCATpDvendor/phpstan/php-8-stubs/stubs/Zend/restore_exception_handler.stubR~hjҤ2vendor/phpstan/php-8-stubs/stubs/Zend/strncmp.stubPR~hjP)6vendor/phpstan/php-8-stubs/stubs/Zend/ArrayAccess.stub5R~hj5&+0vendor/phpstan/php-8-stubs/stubs/Zend/Fiber.stub R~hj m5vendor/phpstan/php-8-stubs/stubs/Zend/FiberError.stubpR~hjpU3<vendor/phpstan/php-8-stubs/stubs/Zend/IteratorAggregate.stubR~hj-E9vendor/phpstan/php-8-stubs/stubs/Zend/get_class_vars.stubPR~hjPu@vendor/phpstan/php-8-stubs/stubs/Zend/get_loaded_extensions.stubgR~hjgO6;vendor/phpstan/php-8-stubs/stubs/Zend/get_called_class.stub/R~hj/歉3vendor/phpstan/php-8-stubs/stubs/Zend/UnitEnum.stubyR~hjywGuפ4vendor/phpstan/php-8-stubs/stubs/Zend/Countable.stub}R~hj}ҿ3vendor/phpstan/php-8-stubs/stubs/Zend/stdClass.stubJR~hjJ" _3vendor/phpstan/php-8-stubs/stubs/Zend/Override.stubR~hj~}Ϥ6vendor/phpstan/php-8-stubs/stubs/Zend/class_alias.stub[R~hj[Ĥ?vendor/phpstan/php-8-stubs/stubs/Zend/ReturnTypeWillChange.stubkR~hjkY:vendor/phpstan/php-8-stubs/stubs/Zend/get_resource_id.stubUR~hjU\ ߤ1vendor/phpstan/php-8-stubs/stubs/Zend/strlen.stub0R~hj0<Bvendor/phpstan/php-8-stubs/stubs/Zend/SensitiveParameterValue.stubR~hjCzO=vendor/phpstan/php-8-stubs/stubs/Zend/SensitiveParameter.stubR~hjQ4vendor/phpstan/php-8-stubs/stubs/Zend/Exception.stubdR~hjd?[i4vendor/phpstan/php-8-stubs/stubs/Zend/Generator.stub:R~hj:5vendor/phpstan/php-8-stubs/stubs/Zend/strcasecmp.stubFR~hjFXDvendor/phpstan/php-8-stubs/stubs/Zend/RequestParseBodyException.stubOR~hjOZ4_;vendor/phpstan/php-8-stubs/stubs/Zend/get_parent_class.stub]R~hj]5vendor/phpstan/php-8-stubs/stubs/Zend/ParseError.stub2R~hj2!(vendor/phpstan/php-8-stubs/stubs/LICENSE R~hj V;vendor/phpstan/php-8-stubs/stubs/ext/random/getrandmax.stubSR~hjS~Rw5vendor/phpstan/php-8-stubs/stubs/ext/random/rand.stubWR~hjW4!8vendor/phpstan/php-8-stubs/stubs/ext/random/mt_rand.stubZR~hjZݐ^6vendor/phpstan/php-8-stubs/stubs/ext/random/srand.stubR~hj6x<>vendor/phpstan/php-8-stubs/stubs/ext/random/mt_getrandmax.stub:R~hj:gCvendor/phpstan/php-8-stubs/stubs/ext/random/Random/RandomError.stubnR~hjnwYGvendor/phpstan/php-8-stubs/stubs/ext/random/Random/RandomException.stubvR~hjva>vendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine.stubhR~hjh*Hvendor/phpstan/php-8-stubs/stubs/ext/random/Random/CryptoSafeEngine.stubaR~hja?Fvendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine/Mt19937.stubR~hjRvendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine/PcgOneseq128XslRr64.stubR~hj|l!Evendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine/Secure.stubR~hjǥkQvendor/phpstan/php-8-stubs/stubs/ext/random/Random/Engine/Xoshiro256StarStar.stub"R~hj"n !Bvendor/phpstan/php-8-stubs/stubs/ext/random/Random/Randomizer.stubR~hj e]Ovendor/phpstan/php-8-stubs/stubs/ext/random/Random/BrokenRandomEngineError.stubR~hjiHvendor/phpstan/php-8-stubs/stubs/ext/random/Random/IntervalBoundary.stubER~hjEI;vendor/phpstan/php-8-stubs/stubs/ext/random/random_int.stubIR~hjIY:vendor/phpstan/php-8-stubs/stubs/ext/random/lcg_value.stub8R~hj8=vendor/phpstan/php-8-stubs/stubs/ext/random/random_bytes.stubZR~hjZTP9vendor/phpstan/php-8-stubs/stubs/ext/random/mt_srand.stubR~hjdKvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionEnumUnitCase.stub~R~hj~D%Hvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionUnionType.stuboR~hjoHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionAttribute.stubR~hj:Hvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionNamedType.stubR~hjLQGvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionFunction.stubR~hjDnHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionExtension.stubR~hjT1Dvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionClass.stubG$R~hjG$Ҹդ>vendor/phpstan/php-8-stubs/stubs/ext/reflection/Reflector.stub3R~hj3Cvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionType.stubR~hj9Dvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionFiber.stubR~hjEvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionMethod.stub R~hj 6Evendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionObject.stubwR~hjwMvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionEnumBackedCase.stubR~hj^hHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionParameter.stub R~hj Q*6Ovendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionFunctionAbstract.stubR~hj|ҤEvendor/phpstan/php-8-stubs/stubs/ext/reflection/PropertyHookType.stubgR~hjg`פHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionException.stubZR~hjZ&Gvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionConstant.stubR~hj$KLvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionZendExtension.stubR~hjOvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionIntersectionType.stubR~hjoQHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionReference.stubbR~hjb^8Cvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionEnum.stub4R~hj4q6ϤGvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionProperty.stub"R~hj"G?vendor/phpstan/php-8-stubs/stubs/ext/reflection/Reflection.stubR~hjHvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionGenerator.stubR~hjQLvendor/phpstan/php-8-stubs/stubs/ext/reflection/ReflectionClassConstant.stub. R~hj. I 3vendor/phpstan/php-8-stubs/stubs/ext/snmp/SNMP.stubR~hj}|$>vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_real_walk.stubR~hj}9vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_walk.stubR~hj'|M<vendor/phpstan/php-8-stubs/stubs/ext/snmp/SNMPException.stub9R~hj9=w7vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpwalk.stubR~hjRS:vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpwalkoid.stubR~hjJA̤9vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_walk.stubR~hjuڤ8vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_get.stubR~hjKIvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_oid_numeric_print.stubR~hjjΤCvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_quick_print.stubR~hj{<vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_getnext.stubR~hjD|Bvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_enum_print.stubR~hjiFvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_valueretrieval.stubR~hjޤ<vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_getnext.stubR~hjZݤIvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_set_oid_output_format.stubR~hj:`M;vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmprealwalk.stubR~hjhƤ>vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_real_walk.stubR~hjC`Cvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_get_quick_print.stub1R~hj1::vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpgetnext.stubR~hj38vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_get.stub R~hj -!LFvendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_get_valueretrieval.stub3R~hj3K Z6vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpget.stubR~hjWޤ6vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmpset.stubR~hj8vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp3_set.stub3R~hj3x8vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp2_set.stubR~hj"a<vendor/phpstan/php-8-stubs/stubs/ext/snmp/snmp_read_mib.stub:R~hj:nUBvendor/phpstan/php-8-stubs/stubs/ext/dom/dom_import_simplexml.stubKR~hjKE8vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMElement.stubR~hjs=vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMDocumentType.stubTR~hjToW=6vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMXPath.stubR~hjI@vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMEntityReference.stuboR~hjo*5vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNode.stub R~hj q':vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMException.stub7R~hj7wH>vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNameSpaceNode.stubR~hjPHۤ=vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNamedNodeMap.stubR~hj5vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMAttr.stubR~hjAvendor/phpstan/php-8-stubs/stubs/ext/dom/DOMDocumentFragment.stub7R~hj7 Τ9vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNotation.stub.R~hj.c9vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMNodeList.stubCR~hjCGQ9vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMDocument.stubR~hj㖑5vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMText.stubR~hj8葰:vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMChildNode.stubIR~hjIheL?vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMImplementation.stub.R~hj. Z=vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMCdataSection.stublR~hjl Fvendor/phpstan/php-8-stubs/stubs/ext/dom/DOMProcessingInstruction.stubR~hjBȤ>vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMCharacterData.stub$R~hj$!28vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMComment.stubuR~hjup=1>vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/CDATASection.stubQR~hjQfƤ=vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/HTMLElement.stubSR~hjSd7z<vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/ParentNode.stubyR~hjycq=vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/XMLDocument.stubR~hjR7vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/XPath.stubR~hj>vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/NamedNodeMap.stub%R~hj%C (@vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/HTMLCollection.stub7R~hj7h+ZGvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/ProcessingInstruction.stubR~hjMiHAvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/EntityReference.stubTR~hjTn݁:vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/NodeList.stubR~hj) ;vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/TokenList.stubR~hj͵ȤBvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/DocumentFragment.stubR~hj\+@m6vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Text.stubR~hjA􆕤Bvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/import_simplexml.stubiR~hji*E@vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Implementation.stubR~hj:vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Notation.stubR~hjgL>vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/DocumentType.stub(R~hj((y;vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/ChildNode.stubR~hj Ť8vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Entity.stub<R~hj<}]l6vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Attr.stub=R~hj=eBvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/AdjacentPosition.stubR~hjб+?vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/NamespaceInfo.stubCR~hjC\*xAvendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/DtdNamedNodeMap.stubUR~hjUd ?vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/CharacterData.stub+R~hj+:vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Document.stubR~hj ={9vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Element.stubR~hj%ܤ9vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Comment.stubR~hjӜ6vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/Node.stub'R~hj'HRvפ>vendor/phpstan/php-8-stubs/stubs/ext/dom/Dom/HTMLDocument.stubR~hjq;vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMParentNode.stubAR~hjA7vendor/phpstan/php-8-stubs/stubs/ext/dom/DOMEntity.stub,R~hj,vHvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_rfc822_parse_headers.stubpR~hjpóAvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_renamemailbox.stubR~hj8P@vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_getmailboxes.stubR~hjӤ:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_qprint.stub>R~hj>;vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_timeout.stubQR~hjQϔnФ8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_body.stubR~hj;vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_expunge.stubR~hjΡ@vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mail_compose.stubTR~hjT0Avendor/phpstan/php-8-stubs/stubs/ext/imap/imap_deletemailbox.stubR~hj*ɧ8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_8bit.stub<R~hj<W>vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_bodystruct.stubR~hj Z;vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_is_open.stubPR~hjPzAvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_createmailbox.stubR~hj#%Hvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_rfc822_write_address.stubqR~hjqٹ:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_alerts.stub/R~hj/@vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_setflag_full.stubR~hjqhA=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchtext.stub-R~hj-erAvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_getsubscribed.stubR~hjAvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_utf8_to_mutf7.stub\R~hj\hBvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetch_overview.stubR~hj+Bvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchstructure.stub R~hj `=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchbody.stubR~hj$>vendor/phpstan/php-8-stubs/stubs/ext/imap/IMAP/Connection.stubwR~hjw̑^f8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_list.stubR~hjREȤ8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_lsub.stubR~hj ݤ=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_set_quota.stubR~hj=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchmime.stubR~hj"?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_fetchheader.stubR~hj:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_binary.stub>R~hj>s8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mail.stubR~hjcp|?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_utf7_encode.stub=R~hj=N 9vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_close.stub-R~hj-J]7vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_uid.stubR~hj*Bvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mailboxmsginfo.stubR~hj28Bvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_listsubscribed.stub9R~hj9?9:8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_scan.stubOR~hjO^BeM=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mail_copy.stubR~hjt<vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_listscan.stubR~hj!Iۤ:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_search.stub-R~hj-R-vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_last_error.stub4R~hj48vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_open.stubR~hjD;vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_num_msg.stubR~hjb19vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_msgno.stubR~hj^7.Fvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mime_header_decode.stubPR~hjPplr:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_setacl.stubR~hj9v:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_errors.stub/R~hj/r8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_sort.stub}R~hj}-?ܤ:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_delete.stubrR~hjrǖ{>vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_num_recent.stubR~hjE67Avendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mutf7_to_utf8.stubER~hjE:ܤ9vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_check.stubR~hj?8<vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_savebody.stubuR~hjuQp=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_mail_move.stubR~hj)Ԥ:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_thread.stubR~hjvW8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_ping.stubR~hjI@@<vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_undelete.stubxR~hjx>$?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_listmailbox.stub3R~hj3hk:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_create.stubR~hje6Bvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_clearflag_full.stubR~hjcڤ:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_status.stubR~hj(%2:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_append.stubUR~hjU(^:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_base64.stub>R~hj>T'Avendor/phpstan/php-8-stubs/stubs/ext/imap/imap_get_quotaroot.stubR~hjž?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_scanmailbox.stub]R~hj]?=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_subscribe.stubR~hj-f=vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_get_quota.stubIR~hjIR<;vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_headers.stubR~hja 8vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_utf8.stubAR~hjA t:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_getacl.stubR~hjk>vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_headerinfo.stubCR~hjC}V@Hvendor/phpstan/php-8-stubs/stubs/ext/imap/imap_rfc822_parse_adrlist.stub_R~hj_c6vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_gc.stubR~hj!װ:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_reopen.stub R~hj 7:o?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_utf7_decode.stubCR~hjCb5:vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_rename.stubR~hjX֤?vendor/phpstan/php-8-stubs/stubs/ext/imap/imap_unsubscribe.stubR~hj'{J=vendor/phpstan/php-8-stubs/stubs/ext/exif/exif_read_data.stubR~hj~&;vendor/phpstan/php-8-stubs/stubs/ext/exif/exif_tagname.stub]R~hj]J)f=vendor/phpstan/php-8-stubs/stubs/ext/exif/exif_imagetype.stub@R~hj@vY=vendor/phpstan/php-8-stubs/stubs/ext/exif/exif_thumbnail.stubR~hj-)@vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_clean_repair.stub9R~hj9c]<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_head.stub;R~hj;{`<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_body.stub;R~hj;):vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_is_xml.stub3R~hj3դ@vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_parse_string.stubR~hjf*H:vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_getopt.stubNR~hjN\T->vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_output.stub9R~hj9J@vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_config_count.stub8R~hj8ŗ?vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_repair_file.stubR~hj絲7vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidyNode.stubR~hjѲޤ@vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_access_count.stub8R~hj8>vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_parse_file.stubR~hj_xN?vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_error_count.stub7R~hj7Å@Avendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_repair_string.stubR~hjc @vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_html_ver.stub8R~hj83vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy.stubY R~hjY q?vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_release.stub/R~hj/[6G<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_root.stub;R~hj;I<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_diagnose.stub5R~hj5¤>vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_config.stub?R~hj?=Dvendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_error_buffer.stubER~hjE&+?vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_opt_doc.stubjR~hjj-<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_is_xhtml.stub5R~hj5>0Avendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_warning_count.stub9R~hj9>vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_status.stub6R~hj6731<vendor/phpstan/php-8-stubs/stubs/ext/tidy/tidy_get_html.stub;R~hj;g5;vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_version.stubGR~hjG_F9vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_pause.stubvR~hjv i;9vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_errno.stub9R~hj9?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_close.stubKR~hjKD$)<vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_strerror.stub<R~hj<óqBvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_strerror.stubBR~hjBm2?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_errno.stubJR~hjJu9vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_error.stub<R~hj<>ti@vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_setopt.stubgR~hjg?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_copy_handle.stubMR~hjM 8vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_exec.stubGR~hjGa<vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_unescape.stubUR~hjU:vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_upkeep.stubR~hjj:vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_escape.stubR~hj>vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_exec.stub{R~hj{ IJGvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_remove_handle.stubgR~hjgm?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_file_create.stub~R~hj~1$jBvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_strerror.stubBR~hjB@vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_setopt_array.stubQR~hjQxgLDvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_getcontent.stubHR~hjH87vendor/phpstan/php-8-stubs/stubs/ext/curl/CURLFile.stubR~hjn7B=vendor/phpstan/php-8-stubs/stubs/ext/curl/CURLStringFile.stubR~hj'V;vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_getinfo.stubRR~hjR3?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_errno.stubJR~hjJ h9vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_reset.stubAR~hjAuL@vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_setopt.stubgR~hjg}ˤ>vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_init.stub8R~hj85ƤDvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_add_handle.stubdR~hjd8QA:9vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_close.stub:R~hj:09q?vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_close.stubKR~hjK>n>vendor/phpstan/php-8-stubs/stubs/ext/curl/CurlMultiHandle.stub'R~hj'`f`@vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_select.stubaR~hja`x>vendor/phpstan/php-8-stubs/stubs/ext/curl/CurlShareHandle.stub'R~hj'4\4Cvendor/phpstan/php-8-stubs/stubs/ext/curl/curl_multi_info_read.stubR~hjԂ:vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_setopt.stubVR~hjVb9vendor/phpstan/php-8-stubs/stubs/ext/curl/CurlHandle.stubDR~hjD8vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_init.stubFR~hjFB4>vendor/phpstan/php-8-stubs/stubs/ext/curl/curl_share_init.stub8R~hj8ZHɤ;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_alarm.stub3R~hj3u>>vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_strerror.stubCR~hjCfV:vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_fork.stubHR~hjHҤ=vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_unshare.stubHR~hjHk5<vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_waitid.stubR~hjܸ =vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_waitpid.stubR~hjAAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_sigprocmask.stubR~hjvBvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_getqos_class.stub|R~hj|%<vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_getcpu.stubYR~hjY2;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_setns.stubR~hjG<vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_signal.stubR~hjAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_setpriority.stubR~hj9Dvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_getcpuaffinity.stubR~hjIn;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_errno.stubJR~hjJ6~:vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wait.stubR~hjtMCvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_async_signals.stubDR~hjD>8>vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wtermsig.stub;R~hj;LQAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wexitstatus.stub>R~hj>Ӑ !Evendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_signal_dispatch.stub2R~hj2:"Hvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_signal_get_handler.stubVR~hjV%>vendor/phpstan/php-8-stubs/stubs/ext/pcntl/Pcntl/QosClass.stubR~hjitVAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_sigwaitinfo.stubR~hj"OBvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_sigtimedwait.stubR~hji>vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wstopsig.stub;R~hj; tu;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_rfork.stublR~hjl :vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_exec.stub[R~hj[ʤ;vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_forkx.stub[R~hj[1ߤ?vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wifexited.stubER~hjE4 5Bvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_setqos_class.stubtR~hjtDbBvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wifcontinued.stubQR~hjQhAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wifsignaled.stub@R~hj@Dvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_get_last_error.stub0R~hj0h1@vendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_wifstopped.stub8R~hj8pAvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_getpriority.stub|R~hj|Dvendor/phpstan/php-8-stubs/stubs/ext/pcntl/pcntl_setcpuaffinity.stubnR~hjn~=Ƥ8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_get.stubUR~hjU7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_chmod.stubR~hjoG6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_site.stubR~hj<vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_set_option.stub R~hj ^e8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_append.stub/R~hj/w8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_rename.stubR~hj^❤6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_mlsd.stubR~hj٬Ԥ7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_close.stubR~hjƅV<vendor/phpstan/php-8-stubs/stubs/ext/ftp/FTP/Connection.stubvR~hjv;p6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_pasv.stubR~hja~6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_quit.stubR~hj_9vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_fget.stubqR~hjqBE5vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_get.stubKR~hjKŧ6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_exec.stubR~hjXB`7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_login.stubR~hjB"9vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_fput.stubqR~hjq6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_fput.stubmR~hjm3y<vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_get_option.stubR~hjWU!=vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_continue.stubR~hjc Ǥ9vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_systype.stubR~hjn8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_delete.stubR~hj_96vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_cdup.stubR~hj"=vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_ssl_connect.stub*R~hj*kv7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nlist.stub R~hj ]6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_mdtm.stubR~hj@ԅ5vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_raw.stubR~hj.Z7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_alloc.stubR~hj*6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_fget.stubmR~hjm~F8vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_nb_put.stub[R~hj[dC#T5vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_put.stubKR~hjK&ۤ9vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_connect.stubR~hj`q5vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_pwd.stubR~hjvEF6vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_size.stubR~hj'E7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_mkdir.stubR~hjԵ19vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_rawlist.stub@R~hj@_7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_rmdir.stubR~hj7vendor/phpstan/php-8-stubs/stubs/ext/ftp/ftp_chdir.stubR~hj0e;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_rollback.stubWR~hjWUD]7vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifetch.stubxR~hjxAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_max.stubNR~hjNpo<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocibindbyname.stubR~hjܸt7vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociparse.stubR~hjW[Dvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_assign.stubZR~hjZ=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_append.stubER~hjEҒ<>vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocidefinebyname.stubR~hj:vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolltrim.stubR~hj;vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifetchinto.stubR~hj%:vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_connect.stubR~hjb]m=vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocisavelobfile.stubyR~hjySp;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_save.stubTR~hjTyD*9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociexecute.stubR~hju7vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocierror.stubR~hj__Avendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_client_version.stub1R~hj1;vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinewcursor.stubR~hjtգ>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_array.stubR~hjQ?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_prefetch.stubdR~hjdק:vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollsize.stub|R~hj|?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociserverversion.stubR~hjh:vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_eof.stub4R~hj4D,nBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_free_descriptor.stub<R~hj<# >vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_new_connect.stubR~hjqHBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_password_change.stubR~hjP;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_tell.stub:R~hj:yK@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociwritelobtofile.stubR~hjѯAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_type_raw.stubtR~hjt+k=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_export.stubsR~hjsH>=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_name.stubsR~hjs%ɤAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_new_descriptor.stub|R~hj|C"Bvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_free_collection.stubJR~hjJM|y=vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollgetelem.stubR~hj"<vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_all.stubR~hj(?1>vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnisnull.stubR~hjׄ;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_num_rows.stubZR~hjZ ƤAvendor/phpstan/php-8-stubs/stubs/ext/oci8/ocigetbufferinglob.stub;R~hj;dȤ<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnname.stubR~hj:?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_object.stubR~hjVLWͤAvendor/phpstan/php-8-stubs/stubs/ext/oci8/ocisetbufferinglob.stubGR~hjGPD0Ф>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_scale.stubqR~hjqHvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_client_identifier.stubwR~hjws<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollappend.stubR~hj158vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinlogon.stubR~hjd \9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinumcols.stub~R~hj~NY9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocisavelob.stubR~hj%y<>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_assoc.stub_R~hj_i@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifreecollection.stub}R~hj}~a8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicancel.stubzR~hjzV_<vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_erase.stubeR~hjeBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_module_name.stublR~hjlog?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumntyperaw.stubR~hjHuä=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_num_fields.stubVR~hjVTwAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_define_by_name.stubR~hj^٬Lvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_element_assign.stuboR~hjoAÀ;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_copy.stubXR~hjXۅњ=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_import.stubIR~hjI95֤:vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocirollback.stubR~hj8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociresult.stubR~hjM;:vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocirowcount.stubR~hjԧIvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_element_get.stubpR~hjp 8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicommit.stub|R~hj|Ҥ<vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_flush.stubER~hjEţ;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_seek.stub^R~hj^5ݤ9vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_commit.stubUR~hjU&ФCvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_call_timeout.stubmR~hjm2=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_size.stubpR~hjpH3Τ?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_bind_by_name.stubR~hjZ<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumntype.stubR~hjF ?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocistatementtype.stubR~hjaÅ9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociloadlob.stubiR~hji#e=8vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_error.stubR~hjYAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_server_version.stubeR~hje>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_edition.stub;R~hj;?r@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifetchstatement.stubR~hj ex9vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollmax.stubzR~hjz,?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinewdescriptor.stubR~hjʆH?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_is_equal.stubIR~hjISYAvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_statement_type.stubcR~hjci%H:vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifreedesc.stubiR~hjitD(=vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocisetprefetch.stubR~hj98vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch.stubRR~hjR&դ:vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_execute.stubwR~hjwHj;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_load.stub=R~hj=?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocinewcollection.stubR~hjEvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_bind_array_by_name.stubR~hj^$<vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_write.stub^R~hj^8kBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_trim.stubTR~hjT+S=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_type.stubwR~hjwG8vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_close.stubUR~hjU'^N;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_pconnect.stubR~hj+v;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_read.stubJR~hjJBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_size.stubOR~hjOX=vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnscale.stubR~hjEF=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_action.stubiR~hjiDà֤<vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_fetch_row.stub]R~hj]ҺޤBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_client_info.stubwR~hjwJ8;vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_size.stub:R~hj:!0:9vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_result.stubhR~hjhG%ȤHvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_register_taf_callback.stubyR~hjyN Dvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_collection_append.stub[R~hj[8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocilogoff.stub|R~hj|Ĭ0y7vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocilogon.stubR~hj{c2Avendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_free_statement.stub[R~hj[+6+@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocipasswordchange.stubR~hj@vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_is_null.stubnR~hjnJ<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnsize.stubR~hj0Cvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_prefetch_lob.stubR~hj <<vendor/phpstan/php-8-stubs/stubs/ext/oci8/OCICollection.stubR~hjqX]9vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_cancel.stubSR~hjSBvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_field_precision.stubuR~hjuڙCvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_set_db_operation.stuboR~hjo,}b>vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_free_cursor.stubyR~hjysQ5vendor/phpstan/php-8-stubs/stubs/ext/oci8/OCILob.stub< R~hj< Ĥ=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_new_cursor.stubqR~hjq ʤIvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_get_implicit_resultset.stub{R~hj{Avendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_new_collection.stubR~hj4 8vendor/phpstan/php-8-stubs/stubs/ext/oci8/ociplogon.stubR~hj<@vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicollassignelem.stubR~hj KV<vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifreecursor.stubR~hj`Y'Jvendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_unregister_taf_callback.stubfR~hjfƤ8vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_parse.stubyR~hjyä?vendor/phpstan/php-8-stubs/stubs/ext/oci8/ocifreestatement.stubR~hje Avendor/phpstan/php-8-stubs/stubs/ext/oci8/ocicolumnprecision.stubR~hj/m?vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_truncate.stubJR~hjJ=vendor/phpstan/php-8-stubs/stubs/ext/oci8/oci_lob_rewind.stub7R~hj7T6RDvendor/phpstan/php-8-stubs/stubs/ext/simplexml/SimpleXMLElement.stub R~hj Evendor/phpstan/php-8-stubs/stubs/ext/simplexml/SimpleXMLIterator.stub=R~hj= Ivendor/phpstan/php-8-stubs/stubs/ext/simplexml/simplexml_load_string.stubR~hjs,Gvendor/phpstan/php-8-stubs/stubs/ext/simplexml/simplexml_load_file.stubR~hjHvendor/phpstan/php-8-stubs/stubs/ext/simplexml/simplexml_import_dom.stub#R~hj#u֤Tvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis128l_keygen.stubSR~hjSMUvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis128l_encrypt.stubR~hjځWvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_random.stubVR~hjVzLvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_sign_detached.stub]R~hj] UUvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aes256gcm_encrypt.stubR~hjr;vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_pad.stubHR~hjHZO[Ovendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_generichash_init.stub|R~hj|UD8sOvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_secretbox_keygen.stub=R~hj=oTvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_sub.stubgR~hjgo:Mvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_secretbox_open.stuboR~hjo07(Kvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_sign_keypair.stub9R~hj9ۥ?vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_memzero.stub:R~hj:Ivendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_kx_keypair.stub7R~hj7;&Kvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_kx_secretkey.stubIR~hjIgS}Vvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_stream_xchacha20_xor_ic.stubR~hj:8Jvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_auth_verify.stub_R~hj_W#Nvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_scalarmult_base.stubR~hjYL!;vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_add.stubHR~hjHETvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aes256gcm_keygen.stubBR~hjBTE%avendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_chacha20poly1305_ietf_encrypt.stubR~hjJ>vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_memcmp.stubIR~hjI+H Ovendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_stream_xchacha20.stubR~hjzgvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_secretstream_xchacha20poly1305_init_pull.stubpR~hjp"nMvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_sign_secretkey.stubKR~hjK*Vvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_scalarmult_ristretto255.stubR~hjWhHvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_shorthash.stubYR~hjYxˁ\vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_sign_ed25519_sk_to_curve25519.stub\R~hj\!,Qvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_generichash_keygen.stub?R~hj? a`vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_chacha20poly1305_ietf_keygen.stubNR~hjNu?vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_compare.stubJR~hjJ(gIZvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_pwhash_scryptsalsa208sha256.stubR~hjo^vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_negate.stubfR~hjfUĤIvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_scalarmult.stubRR~hjR+(dvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_secretstream_xchacha20poly1305_keygen.stubR~hjgvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_secretstream_xchacha20poly1305_init_push.stub_R~hj_7$m%?vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_hex2bin.stubPR~hjP$54Cvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_auth.stubTR~hjTVȮbvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_xchacha20poly1305_ietf_decrypt.stubR~hjh\Lhvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_sign_keypair_from_secretkey_and_publickey.stub|R~hj|2ڤPvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_sign_seed_keypair.stubJR~hjJy@Ivendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_stream_xor.stubbR~hjb[Svendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_sign_verify_detached.stubuR~hju"R[vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_add.stubnR~hjn3>m[vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_scalarmult_ristretto255_base.stubcR~hjc-ُ~Hvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_sign_open.stubfR~hjfY\Mvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_sign_publickey.stubKR~hjK|O Pvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_pwhash_str_verify.stubZR~hjZ9Bvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_bin2base64.stubmR~hjmfߤJvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_auth_keygen.stub8R~hj8`@Qbvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_secretstream_xchacha20poly1305_push.stubR~hjauZvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_from_hash.stubbR~hjbฤOvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_shorthash_keygen.stub=R~hj=]N̤Zvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aes256gcm_is_available.stubhR~hjh<Uvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_kx_client_session_keys.stubmR~hjm#,[vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_sub.stubnR~hjnKm@vendor/phpstan/php-8-stubs/stubs/ext/sodium/SodiumException.stub4R~hj4\Svendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis256_keygen.stubRR~hjR'0XLvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_box_publickey.stubJR~hjJВ3Svendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_stream_xchacha20_xor.stub}R~hj}kUIvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_kdf_keygen.stub7R~hj7IǤ^vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_core_ristretto255_scalar_invert.stubfR~hjfwLvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_box_seal_open.stubdR~hjdgVvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_pwhash_str_needs_rehash.stubR~hjq{WDTvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_aegis256_decrypt.stubR~hjcvendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_secretstream_xchacha20poly1305_rekey.stub]R~hj] 9[vendor/phpstan/php-8-stubs/stubs/ext/sodium/sodium_crypto_aead_chacha20poly1305_keygen.stubIR~hjIvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strripos.stubxR~hjxȴ;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_eregi.stubsR~hjs>vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strwidth.stubOR~hjO*Jvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_substitute_character.stubkR~hjk5sϤ=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_lcfirst.stubbR~hjbUO=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ucfirst.stubbR~hjbS~ۤFvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_convert_encoding.stubR~hj)Jv@vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_http_input.stubcR~hjcGBvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_replace.stubR~hjD>vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_get_info.stub/R~hj/bߗ Gvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_convert_variables.stubR~hj}Z=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_stripos.stubwR~hjwn?vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_parse_str.stub]R~hj]'&Gvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_regex_set_options.stubJR~hjJRޘ@vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_match.stubbR~hjb^@vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strimwidth.stubR~hjcG=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strrchr.stubR~hj铤Kvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_replace_callback.stubR~hj9vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ord.stubPR~hjP_Bvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_convert_kana.stubkR~hjkyQI~Bvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_convert_case.stubaR~hja7).Evendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_pos.stub}R~hj}AߤHvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_getpos.stub1R~hj1]5>vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_language.stubiR~hjiqCvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_eregi_replace.stubR~hj%7Dvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_output_handler.stubKR~hjKi0Dvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_check_encoding.stubgR~hjgP=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_stristr.stubR~hj3;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ltrim.stub|R~hj|o᪤<vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_substr.stubqR~hjqW@vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strtoupper.stubTR~hjT;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_rtrim.stub|R~hj|@Fvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_regs.stub~R~hj~j?vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_send_mail.stubR~hjAHvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_ereg_search_setpos.stub=R~hj=d^;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_scrub.stubOR~hjO(RR<vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strstr.stubR~hjB@vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strtolower.stubTR~hjTnWFvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_encoding_aliases.stubXR~hjXZEvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_detect_encoding.stubR~hjE9vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_chr.stubSR~hjS9,;vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_split.stubsR~hjs Gvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_internal_encoding.stubPR~hjP{Dvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_list_encodings.stub/R~hj/f-=vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_str_pad.stubR~hj 2Jvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_decode_numericentity.stubjR~hjj3䍤Avendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_http_output.stubJR~hjJT.<vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strlen.stubMR~hjM*j>vendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_strrichr.stubR~hjRBvendor/phpstan/php-8-stubs/stubs/ext/mbstring/mb_substr_count.stubeR~hjeJRvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_get_external_entity_loader.stubTR~hjTaARvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_set_external_entity_loader.stubZR~hjZfrlKvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_use_internal_errors.stubOR~hjOnu8Fvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_get_last_error.stub@R~hj@)Mvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_disable_entity_loader.stub`R~hj`Kvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_set_streams_context.stub_R~hj_pu+Dvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_clear_errors.stub0R~hj0'<vendor/phpstan/php-8-stubs/stubs/ext/libxml/LibXMLError.stub?R~hj?Bvendor/phpstan/php-8-stubs/stubs/ext/libxml/libxml_get_errors.stub/R~hj/Gvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_transitions_get.stubR~hj 7vendor/phpstan/php-8-stubs/stubs/ext/date/date_add.stubTR~hjT57fCvendor/phpstan/php-8-stubs/stubs/ext/date/date_interval_format.stubXR~hjXDHvendor/phpstan/php-8-stubs/stubs/ext/date/date_default_timezone_get.stub8R~hj8 H6<vendor/phpstan/php-8-stubs/stubs/ext/date/date_date_set.stubaR~hjai&5vendor/phpstan/php-8-stubs/stubs/ext/date/mktime.stubR~hjqdPvendor/phpstan/php-8-stubs/stubs/ext/date/date_create_immutable_from_format.stubR~hjhBvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_offset_get.stubbR~hjb 8vendor/phpstan/php-8-stubs/stubs/ext/date/checkdate.stubER~hjE&<vendor/phpstan/php-8-stubs/stubs/ext/date/timezone_open.stubIR~hjI.4vendor/phpstan/php-8-stubs/stubs/ext/date/idate.stubMR~hjM18Hvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_identifiers_list.stubR~hj:vendor/phpstan/php-8-stubs/stubs/ext/date/date_modify.stubVR~hjV {U@vendor/phpstan/php-8-stubs/stubs/ext/date/date_timezone_get.stubWR~hjW |Kvendor/phpstan/php-8-stubs/stubs/ext/date/DateInvalidTimeZoneException.stubtR~hjt~M=vendor/phpstan/php-8-stubs/stubs/ext/date/DateRangeError.stubbR~hjb(uTvendor/phpstan/php-8-stubs/stubs/ext/date/date_interval_create_from_date_string.stubaR~hjaa׀ 5vendor/phpstan/php-8-stubs/stubs/ext/date/gmdate.stubKR~hjKeHvendor/phpstan/php-8-stubs/stubs/ext/date/date_default_timezone_set.stubHR~hjH`eKvendor/phpstan/php-8-stubs/stubs/ext/date/DateMalformedStringException.stubtR~hjttkw>vendor/phpstan/php-8-stubs/stubs/ext/date/DateObjectError.stubcR~hjcG\;vendor/phpstan/php-8-stubs/stubs/ext/date/date_sunrise.stubR~hjˠEvendor/phpstan/php-8-stubs/stubs/ext/date/date_parse_from_format.stubkR~hjkMYu;vendor/phpstan/php-8-stubs/stubs/ext/date/DateTimeZone.stubaR~hjaƲ@vendor/phpstan/php-8-stubs/stubs/ext/date/timezone_name_get.stubER~hjEJ<vendor/phpstan/php-8-stubs/stubs/ext/date/DateException.stubaR~hjaf@vendor/phpstan/php-8-stubs/stubs/ext/date/DateTimeInterface.stub R~hj 8vendor/phpstan/php-8-stubs/stubs/ext/date/localtime.stuboR~hjo#v3vendor/phpstan/php-8-stubs/stubs/ext/date/time.stub R~hj e<vendor/phpstan/php-8-stubs/stubs/ext/date/date_sun_info.stubsR~hjs&)Fvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_name_from_abbr.stubnR~hjn7vendor/phpstan/php-8-stubs/stubs/ext/date/gmmktime.stubR~hj˜7vendor/phpstan/php-8-stubs/stubs/ext/date/date_sub.stubTR~hjTq}@vendor/phpstan/php-8-stubs/stubs/ext/date/DateTimeImmutable.stub R~hj _s1:vendor/phpstan/php-8-stubs/stubs/ext/date/date_format.stubTR~hjTq(%ӤAvendor/phpstan/php-8-stubs/stubs/ext/date/date_timestamp_set.stubUR~hjU%=7vendor/phpstan/php-8-stubs/stubs/ext/date/DateTime.stubR~hjҤ<vendor/phpstan/php-8-stubs/stubs/ext/date/date_time_set.stubR~hjr@9vendor/phpstan/php-8-stubs/stubs/ext/date/DatePeriod.stubR~hj@#ZLvendor/phpstan/php-8-stubs/stubs/ext/date/DateInvalidOperationException.stubuR~hju+`Cvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_version_get.stub3R~hj3a1njSvendor/phpstan/php-8-stubs/stubs/ext/date/DateMalformedIntervalStringException.stub|R~hj|oȗAvendor/phpstan/php-8-stubs/stubs/ext/date/date_timestamp_get.stubHR~hjH/a=?vendor/phpstan/php-8-stubs/stubs/ext/date/date_isodate_set.stubmR~hjmwl;vendor/phpstan/php-8-stubs/stubs/ext/date/DateInterval.stubR~hjf8vendor/phpstan/php-8-stubs/stubs/ext/date/date_diff.stubR~hjS~8vendor/phpstan/php-8-stubs/stubs/ext/date/DateError.stubYR~hjYCvendor/phpstan/php-8-stubs/stubs/ext/date/date_get_last_errors.stubOR~hjO֩[9vendor/phpstan/php-8-stubs/stubs/ext/date/gmstrftime.stubUR~hjU~_qFvendor/phpstan/php-8-stubs/stubs/ext/date/date_create_from_format.stubR~hj4:vendor/phpstan/php-8-stubs/stubs/ext/date/date_create.stublR~hjl/8vendor/phpstan/php-8-stubs/stubs/ext/date/strtotime.stubyR~hjyIѤ3vendor/phpstan/php-8-stubs/stubs/ext/date/date.stubIR~hjIY7vendor/phpstan/php-8-stubs/stubs/ext/date/strftime.stubSR~hjStQvendor/phpstan/php-8-stubs/stubs/ext/date/DateMalformedPeriodStringException.stubzR~hjz& TJvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_abbreviations_list.stubPR~hjPP69Dvendor/phpstan/php-8-stubs/stubs/ext/date/timezone_location_get.stubeR~hje:¤Dvendor/phpstan/php-8-stubs/stubs/ext/date/date_create_immutable.stubR~hj:vendor/phpstan/php-8-stubs/stubs/ext/date/date_sunset.stubR~hj`qg6vendor/phpstan/php-8-stubs/stubs/ext/date/getdate.stubRR~hjR]Tp<9vendor/phpstan/php-8-stubs/stubs/ext/date/date_parse.stubOR~hjO%->vendor/phpstan/php-8-stubs/stubs/ext/date/date_offset_get.stubER~hjEZ)@vendor/phpstan/php-8-stubs/stubs/ext/date/date_timezone_set.stub]R~hj](?vendor/phpstan/php-8-stubs/stubs/ext/session/session_abort.stub*R~hj*]ĤJvendor/phpstan/php-8-stubs/stubs/ext/session/session_set_save_handler.stubR~hj_Ӥ>vendor/phpstan/php-8-stubs/stubs/ext/session/session_name.stubgR~hjgC;?vendor/phpstan/php-8-stubs/stubs/ext/session/session_reset.stub*R~hj*l@vendor/phpstan/php-8-stubs/stubs/ext/session/session_commit.stubMR~hjMn =Dvendor/phpstan/php-8-stubs/stubs/ext/session/SessionIdInterface.stubR~hjbᣤKvendor/phpstan/php-8-stubs/stubs/ext/session/session_set_cookie_params.stubR~hj4@vendor/phpstan/php-8-stubs/stubs/ext/session/session_status.stub*R~hj*Qe@vendor/phpstan/php-8-stubs/stubs/ext/session/session_encode.stub3R~hj3 o4Avendor/phpstan/php-8-stubs/stubs/ext/session/session_destroy.stub,R~hj,N@vendor/phpstan/php-8-stubs/stubs/ext/session/SessionHandler.stubR~hj?vendor/phpstan/php-8-stubs/stubs/ext/session/session_start.stub=R~hj=1T<vendor/phpstan/php-8-stubs/stubs/ext/session/session_id.stubAR~hjA󁬤?vendor/phpstan/php-8-stubs/stubs/ext/session/session_unset.stub*R~hj* P%Gvendor/phpstan/php-8-stubs/stubs/ext/session/session_cache_limiter.stubOR~hjOV<vendor/phpstan/php-8-stubs/stubs/ext/session/session_gc.stub,R~hj,Kvendor/phpstan/php-8-stubs/stubs/ext/session/session_get_cookie_params.stubNR~hjN:\aIvendor/phpstan/php-8-stubs/stubs/ext/session/SessionHandlerInterface.stubR~hj&)Cvendor/phpstan/php-8-stubs/stubs/ext/session/session_save_path.stubJR~hjJ.ZXvendor/phpstan/php-8-stubs/stubs/ext/session/SessionUpdateTimestampHandlerInterface.stub+R~hj+BFvendor/phpstan/php-8-stubs/stubs/ext/session/session_cache_expire.stubHR~hjHEvendor/phpstan/php-8-stubs/stubs/ext/session/session_module_name.stubNR~hjNrQKvendor/phpstan/php-8-stubs/stubs/ext/session/session_register_shutdown.stub6R~hj6KSGvendor/phpstan/php-8-stubs/stubs/ext/session/session_regenerate_id.stubRR~hjRMch@vendor/phpstan/php-8-stubs/stubs/ext/session/session_decode.stub7R~hj7쭤Evendor/phpstan/php-8-stubs/stubs/ext/session/session_write_close.stub0R~hj0H8Cvendor/phpstan/php-8-stubs/stubs/ext/session/session_create_id.stubIR~hjI)i8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreate.stubIR~hjI$>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegammacorrect.stubfR~hjft<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegrabscreen.stub6R~hj6cODvendor/phpstan/php-8-stubs/stubs/ext/gd/imagetruecolortopalette.stubbR~hjb?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopymergegray.stubR~hj0cX4vendor/phpstan/php-8-stubs/stubs/ext/gd/GdImage.stubAR~hjA_n ¤Cvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromgd2part.stubvR~hjvH?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromgif.stubIR~hjIik7<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolormatch.stubNR~hjN}LǤ?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorallocate.stubdR~hjdպ9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagettftext.stubR~hj*j:vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecropauto.stubR~hj-Avendor/phpstan/php-8-stubs/stubs/ext/gd/imageaffinematrixget.stubR~hj{9;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefontwidth.stubR~hjd~Ҥ6vendor/phpstan/php-8-stubs/stubs/ext/gd/imageavif.stubR~hjJ(a@vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromjpeg.stub]R~hj]x<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegrabwindow.stubmR~hjmp5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagexbm.stubmR~hjm/n5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegd2.stubR~hjfaDvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorallocatealpha.stubuR~hjuX3vendor/phpstan/php-8-stubs/stubs/ext/gd/GdFont.stubbR~hjb+<8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecharup.stubR~hjڤ5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegif.stubkR~hjk 6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopy.stubR~hjo=vendor/phpstan/php-8-stubs/stubs/ext/gd/imageconvolution.stubjR~hjj$ݤ@vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromwebp.stubeR~hjeY >vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetthickness.stubMR~hjM݉6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagejpeg.stubR~hjQfDvendor/phpstan/php-8-stubs/stubs/ext/gd/imagepalettetotruecolor.stubCR~hjCI;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopymerge.stubR~hj2\>?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopyresampled.stubR~hju88vendor/phpstan/php-8-stubs/stubs/ext/gd/imageftbbox.stubR~hjM?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagealphablending.stubLR~hjLc=vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecopyresized.stubR~hjbKܤ<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagedashedline.stubkR~hjkV?8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefttext.stubR~hj^ 8vendor/phpstan/php-8-stubs/stubs/ext/gd/imageaffine.stubeR~hje Avendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatetruecolor.stubRR~hjRޤ;vendor/phpstan/php-8-stubs/stubs/ext/gd/imageinterlace.stubPR~hjP;7vendor/phpstan/php-8-stubs/stubs/ext/gd/imagetypes.stub&R~hj&o JAvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorclosesthwb.stub`R~hj`-خ9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagepolygon.stubuR~hjuCCvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorclosestalpha.stubnR~hjnPAvendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilledrectangle.stubpR~hjpVd0Bvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolortransparent.stubTR~hjTϤ6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagewebp.stubR~hj%b;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesavealpha.stubHR~hjHF[Bvendor/phpstan/php-8-stubs/stubs/ext/gd/imagegetinterpolation.stub@R~hj@W"u@vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromavif.stubR~hjK5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagearc.stubR~hj]sF>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilltoborder.stublR~hjlyb9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegetclip.stubPR~hjPrBդ@vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorsforindex.stubcR~hjcO?9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesettile.stubHR~hjH̤?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefrombmp.stub\R~hj\DE>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorclosest.stub]R~hj]xp6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefill.stubQR~hjQdBvendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetinterpolation.stubcR~hjc$mDvendor/phpstan/php-8-stubs/stubs/ext/gd/imageaffinematrixconcat.stubpR~hjpI.4=vendor/phpstan/php-8-stubs/stubs/ext/gd/imageistruecolor.stub<R~hj< @f5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagebmp.stubR~hjx+Cvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorresolvealpha.stubnR~hjn1hV6vendor/phpstan/php-8-stubs/stubs/ext/gd/imageflip.stub@R~hj@k-Z 8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagerotate.stubUR~hjUNv8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilter.stub~R~hj~|&6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagechar.stubR~hjڅ4vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesy.stub2R~hj2iJ䫤=vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorstotal.stub;R~hj;Fp5vendor/phpstan/php-8-stubs/stubs/ext/gd/imagepng.stubR~hjXGC ;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilledarc.stubR~hj/?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefrompng.stubcR~hjcBvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromstring.stubHR~hjHc6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecrop.stubQR~hjQ :vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetpixel.stubUR~hjUBiW 6vendor/phpstan/php-8-stubs/stubs/ext/gd/imagewbmp.stubR~hjU?4vendor/phpstan/php-8-stubs/stubs/ext/gd/imagegd.stubIR~hjI9v9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagedestroy.stub?R~hj? ݪ@vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromwbmp.stubQR~hjQ ?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromxpm.stub\R~hj\:q>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorresolve.stub]R~hj]#ޤ:vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetbrush.stubJR~hjJs><vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorexact.stub[R~hj[Avendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorexactalpha.stublR~hjl<vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefontheight.stubR~hjPjKK=vendor/phpstan/php-8-stubs/stubs/ext/gd/imagepalettecopy.stubIR~hjI\4?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilledpolygon.stub{R~hj{)E:vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetstyle.stubGR~hjG]=vendor/phpstan/php-8-stubs/stubs/ext/gd/imageopenpolygon.stubyR~hjyޅL;vendor/phpstan/php-8-stubs/stubs/ext/gd/imageantialias.stubHR~hjHYT<vendor/phpstan/php-8-stubs/stubs/ext/gd/imageresolution.stubR~hj)9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorat.stubMR~hjMF&?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromtga.stubcR~hjc6>&8vendor/phpstan/php-8-stubs/stubs/ext/gd/imagestring.stubR~hj@>vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromgd.stubHR~hjH7rAvendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolordeallocate.stubLR~hjLGڤ4vendor/phpstan/php-8-stubs/stubs/ext/gd/gd_info.stub<R~hj<ՙG?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromgd2.stubIR~hjI.4vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesx.stub2R~hj2(QhŤ?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagefilledellipse.stubR~hj7!ܤ6vendor/phpstan/php-8-stubs/stubs/ext/gd/imageline.stubeR~hjex9vendor/phpstan/php-8-stubs/stubs/ext/gd/imageellipse.stub{R~hj{:=vendor/phpstan/php-8-stubs/stubs/ext/gd/imagelayereffect.stubIR~hjIf^?vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecreatefromxbm.stubPR~hjPW9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagesetclip.stub\R~hj\7vendor/phpstan/php-8-stubs/stubs/ext/gd/imagescale.stub~R~hj~F2|>:vendor/phpstan/php-8-stubs/stubs/ext/gd/imagestringup.stubR~hjE9vendor/phpstan/php-8-stubs/stubs/ext/gd/imagettfbbox.stubR~hjdQ:vendor/phpstan/php-8-stubs/stubs/ext/gd/imagecolorset.stubR~hj\y.;vendor/phpstan/php-8-stubs/stubs/ext/gd/imagerectangle.stubjR~hjj~C7:vendor/phpstan/php-8-stubs/stubs/ext/gd/imageloadfont.stubR~hj"t禤7vendor/phpstan/php-8-stubs/stubs/ext/standard/stat.stubOR~hjO,`Lvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_get_params.stubrR~hjrt;vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_start.stubrR~hjr}<9vendor/phpstan/php-8-stubs/stubs/ext/standard/printf.stubBR~hjB(<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_pad.stubNR~hjN{~ ;vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_clean.stub%R~hj%MҤ9vendor/phpstan/php-8-stubs/stubs/ext/standard/putenv.stubHR~hjH+V:vendor/phpstan/php-8-stubs/stubs/ext/standard/implode.stubSR~hjSq?V<vendor/phpstan/php-8-stubs/stubs/ext/standard/inet_ntop.stubUR~hjUYt٤=vendor/phpstan/php-8-stubs/stubs/ext/standard/addslashes.stub7R~hj7PYӛ>vendor/phpstan/php-8-stubs/stubs/ext/standard/get_headers.stubR~hj CC8vendor/phpstan/php-8-stubs/stubs/ext/standard/mkdir.stubR~hj Bvendor/phpstan/php-8-stubs/stubs/ext/standard/array_multisort.stubR~hjnla>vendor/phpstan/php-8-stubs/stubs/ext/standard/str_replace.stubR~hjIvendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect_uassoc.stubmR~hjm=:|?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_values.stubTR~hjTGvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_sendto.stubR~hjg=vendor/phpstan/php-8-stubs/stubs/ext/standard/dns_get_mx.stubR~hj%<vendor/phpstan/php-8-stubs/stubs/ext/standard/filegroup.stub;R~hj;4Avendor/phpstan/php-8-stubs/stubs/ext/standard/array_key_last.stubBR~hjBs79vendor/phpstan/php-8-stubs/stubs/ext/standard/uksort.stubR~hjDĄCvendor/phpstan/php-8-stubs/stubs/ext/standard/time_sleep_until.stub=R~hj=hEBvendor/phpstan/php-8-stubs/stubs/ext/standard/php_user_filter.stubR~hjb@k<vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_alter.stubR~hjg}٤9vendor/phpstan/php-8-stubs/stubs/ext/standard/intval.stub>R~hj>YAvendor/phpstan/php-8-stubs/stubs/ext/standard/substr_compare.stubR~hjИG?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_column.stubvR~hjv%Lvendor/phpstan/php-8-stubs/stubs/ext/standard/output_reset_rewrite_vars.stub6R~hj6Avendor/phpstan/php-8-stubs/stubs/ext/standard/escapeshellarg.stub8R~hj8 ܤ>vendor/phpstan/php-8-stubs/stubs/ext/standard/array_shift.stub6R~hj60S:vendor/phpstan/php-8-stubs/stubs/ext/standard/settype.stub=R~hj==vendor/phpstan/php-8-stubs/stubs/ext/standard/phpcredits.stubR~hj Lvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_set_option.stubR~hjK <vendor/phpstan/php-8-stubs/stubs/ext/standard/is_scalar.stub2R~hj22m8vendor/phpstan/php-8-stubs/stubs/ext/standard/fopen.stubR~hjFvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_blocking.stubdR~hjdu<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_sum.stub7R~hj7̮@vendor/phpstan/php-8-stubs/stubs/ext/standard/stripcslashes.stub:R~hj:N_X>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_writable.stub8R~hj8b=vendor/phpstan/php-8-stubs/stubs/ext/standard/strtoupper.stub7R~hj79Z+Kvendor/phpstan/php-8-stubs/stubs/ext/standard/header_register_callback.stubYR~hjYq&Gvendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect_ukey.stubkR~hjk|<vendor/phpstan/php-8-stubs/stubs/ext/standard/fsockopen.stubR~hj/A7vendor/phpstan/php-8-stubs/stubs/ext/standard/fmod.stub:R~hj:"-Cvendor/phpstan/php-8-stubs/stubs/ext/standard/ob_list_handlers.stubER~hjEDT e?vendor/phpstan/php-8-stubs/stubs/ext/standard/htmlentities.stub]R~hj]Ri~:vendor/phpstan/php-8-stubs/stubs/ext/standard/tmpfile.stub<R~hj<?8vendor/phpstan/php-8-stubs/stubs/ext/standard/chgrp.stubER~hjE* ?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_unique.stubPR~hjP|3J9vendor/phpstan/php-8-stubs/stubs/ext/standard/decbin.stub-R~hj-!K:vendor/phpstan/php-8-stubs/stubs/ext/standard/opendir.stubR~hj#`rHvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_create.stubqR~hjqR5R?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_reduce.stubaR~hja AEvendor/phpstan/php-8-stubs/stubs/ext/standard/html_entity_decode.stubR~hjR{Evendor/phpstan/php-8-stubs/stubs/ext/standard/ini_parse_quantity.stubPR~hjP3 Cvendor/phpstan/php-8-stubs/stubs/ext/standard/set_include_path.stubIR~hjI7vendor/phpstan/php-8-stubs/stubs/ext/standard/sort.stubR~hj(vY?vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_end_clean.stub)R~hj)"?E<vendor/phpstan/php-8-stubs/stubs/ext/standard/strnatcmp.stubER~hjEhL<vendor/phpstan/php-8-stubs/stubs/ext/standard/fileinode.stub;R~hj;l6"M8vendor/phpstan/php-8-stubs/stubs/ext/standard/floor.stub1R~hj1opZ9vendor/phpstan/php-8-stubs/stubs/ext/standard/getenv.stubvR~hjvq@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_reverse.stubTR~hjT¼)0:vendor/phpstan/php-8-stubs/stubs/ext/standard/fnmatch.stubiR~hjibDvendor/phpstan/php-8-stubs/stubs/ext/standard/socket_get_status.stubxR~hjxդ=vendor/phpstan/php-8-stubs/stubs/ext/standard/getrandmax.stubBR~hjBlaMvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_get_default.stub_R~hj_׬ؤ;vendor/phpstan/php-8-stubs/stubs/ext/standard/filetype.stub=R~hj=L?vendor/phpstan/php-8-stubs/stubs/ext/standard/RoundingMode.stubR~hjtBvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_is_local.stubYR~hjYI(Ѥ;vendor/phpstan/php-8-stubs/stubs/ext/standard/getmypid.stub*R~hj*o4<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_all.stubWR~hjW¤8vendor/phpstan/php-8-stubs/stubs/ext/standard/crc32.stub=R~hj=@<vendor/phpstan/php-8-stubs/stubs/ext/standard/serialize.stub4R~hj4פ:vendor/phpstan/php-8-stubs/stubs/ext/standard/strrchr.stubR~hj vAvendor/phpstan/php-8-stubs/stubs/ext/standard/array_find_key.stub]R~hj]x#8vendor/phpstan/php-8-stubs/stubs/ext/standard/sleep.stub-R~hj-3cLHvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_bucket_prepend.stubR~hjqmEvendor/phpstan/php-8-stubs/stubs/ext/standard/socket_set_timeout.stubR~hjUR<vendor/phpstan/php-8-stubs/stubs/ext/standard/Directory.stubR~hjtw]>vendor/phpstan/php-8-stubs/stubs/ext/standard/addcslashes.stubLR~hjLaq=vendor/phpstan/php-8-stubs/stubs/ext/standard/pfsockopen.stubR~hj{[h=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_flip.stubaR~hja%菤Gvendor/phpstan/php-8-stubs/stubs/ext/standard/php_strip_whitespace.stubCR~hjC%`;vendor/phpstan/php-8-stubs/stubs/ext/standard/realpath.stub9R~hj9/'~>vendor/phpstan/php-8-stubs/stubs/ext/standard/gethostname.stub[R~hj[1);vendor/phpstan/php-8-stubs/stubs/ext/standard/var_dump.stubOR~hjO}>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_infinite.stub2R~hj2ko>vendor/phpstan/php-8-stubs/stubs/ext/standard/count_chars.stubzR~hjz7n>vendor/phpstan/php-8-stubs/stubs/ext/standard/str_shuffle.stub8R~hj87j<vendor/phpstan/php-8-stubs/stubs/ext/standard/urldecode.stub6R~hj6qv8vendor/phpstan/php-8-stubs/stubs/ext/standard/round.stubR~hjp|mqCvendor/phpstan/php-8-stubs/stubs/ext/standard/get_current_user.stub6R~hj6RAvendor/phpstan/php-8-stubs/stubs/ext/standard/password_algos.stub,R~hj,פ6vendor/phpstan/php-8-stubs/stubs/ext/standard/max.stub?R~hj?8vendor/phpstan/php-8-stubs/stubs/ext/standard/ltrim.stubXR~hjX;-?vendor/phpstan/php-8-stubs/stubs/ext/standard/headers_list.stubAR~hjAgŤ9vendor/phpstan/php-8-stubs/stubs/ext/standard/unlink.stubiR~hjiȤ:vendor/phpstan/php-8-stubs/stubs/ext/standard/stristr.stubiR~hjiOzHvendor/phpstan/php-8-stubs/stubs/ext/standard/php_ini_scanned_files.stub:R~hj:WeBvendor/phpstan/php-8-stubs/stubs/ext/standard/password_verify.stubJR~hjJJvendor/phpstan/php-8-stubs/stubs/ext/standard/array_uintersect_uassoc.stubnR~hjnFvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_wrappers.stubHR~hjH!Fvendor/phpstan/php-8-stubs/stubs/ext/standard/socket_set_blocking.stubR~hj @~9vendor/phpstan/php-8-stubs/stubs/ext/standard/strrev.stub3R~hj3Jvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_register_wrapper.stubR~hjE8vendor/phpstan/php-8-stubs/stubs/ext/standard/usort.stubR~hj>vendor/phpstan/php-8-stubs/stubs/ext/standard/show_source.stubrR~hjrv6@vendor/phpstan/php-8-stubs/stubs/ext/standard/stream_select.stubOR~hjOݤJvendor/phpstan/php-8-stubs/stubs/ext/standard/array_replace_recursive.stubYR~hjY>Y=vendor/phpstan/php-8-stubs/stubs/ext/standard/proc_close.stubNR~hjNמ<vendor/phpstan/php-8-stubs/stubs/ext/standard/filemtime.stub;R~hj;S;vendor/phpstan/php-8-stubs/stubs/ext/standard/wordwrap.stubzR~hjzcEb<vendor/phpstan/php-8-stubs/stubs/ext/standard/iptcembed.stubmR~hjm/*8vendor/phpstan/php-8-stubs/stubs/ext/standard/fsync.stubYR~hjY+ <vendor/phpstan/php-8-stubs/stubs/ext/standard/is_object.stub2R~hj2*jLvendor/phpstan/php-8-stubs/stubs/ext/standard/forward_static_call_array.stubVR~hjVq;Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_server.stub-R~hj-gY;vendor/phpstan/php-8-stubs/stubs/ext/standard/linkinfo.stub6R~hj6ݍ@vendor/phpstan/php-8-stubs/stubs/ext/standard/stream_isatty.stubPR~hjPk;vendor/phpstan/php-8-stubs/stubs/ext/standard/md5_file.stubSR~hjS&ۤ8vendor/phpstan/php-8-stubs/stubs/ext/standard/chdir.stub3R~hj3{RQ=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_fill.stubRR~hjRˤGvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_meta_data.stub\R~hj\.>(7vendor/phpstan/php-8-stubs/stubs/ext/standard/sha1.stubTR~hjT ¤Cvendor/phpstan/php-8-stubs/stubs/ext/standard/getprotobynumber.stubcR~hjc<vendor/phpstan/php-8-stubs/stubs/ext/standard/metaphone.stubfR~hjfФ:vendor/phpstan/php-8-stubs/stubs/ext/standard/boolval.stub0R~hj0#AGvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_supports_lock.stubWR~hjWx Ĥ6vendor/phpstan/php-8-stubs/stubs/ext/standard/chr.stub0R~hj04nDvendor/phpstan/php-8-stubs/stubs/ext/standard/ignore_user_abort.stubAR~hjAJvendor/phpstan/php-8-stubs/stubs/ext/standard/quoted_printable_decode.stub^R~hj^n;vendor/phpstan/php-8-stubs/stubs/ext/standard/is_float.stub1R~hj1ʛ:vendor/phpstan/php-8-stubs/stubs/ext/standard/fprintf.stubkR~hjkU8vendor/phpstan/php-8-stubs/stubs/ext/standard/fgets.stubeR~hjeπ28vendor/phpstan/php-8-stubs/stubs/ext/standard/ksort.stubR~hjUf=vendor/phpstan/php-8-stubs/stubs/ext/standard/phpversion.stubHR~hjHL:vendor/phpstan/php-8-stubs/stubs/ext/standard/dirname.stubCR~hjC!jФ=vendor/phpstan/php-8-stubs/stubs/ext/standard/shell_exec.stubCR~hjCWCvendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff_assoc.stubLR~hjLBDvendor/phpstan/php-8-stubs/stubs/ext/standard/password_get_info.stubcR~hjc ?vendor/phpstan/php-8-stubs/stubs/ext/standard/headers_sent.stubR~hjHAvendor/phpstan/php-8-stubs/stubs/ext/standard/parse_ini_file.stubR~hj eJvendor/phpstan/php-8-stubs/stubs/ext/standard/htmlspecialchars_decode.stubR~hj+7vendor/phpstan/php-8-stubs/stubs/ext/standard/sinh.stub,R~hj,+.8vendor/phpstan/php-8-stubs/stubs/ext/standard/rtrim.stubXR~hjXt157vendor/phpstan/php-8-stubs/stubs/ext/standard/chop.stubkR~hjk;vendor/phpstan/php-8-stubs/stubs/ext/standard/getmyuid.stub;R~hj;4G @vendor/phpstan/php-8-stubs/stubs/ext/standard/diskfreespace.stub`R~hj`kK;vendor/phpstan/php-8-stubs/stubs/ext/standard/getmygid.stub*R~hj*59vendor/phpstan/php-8-stubs/stubs/ext/standard/uasort.stubR~hjVnHBvendor/phpstan/php-8-stubs/stubs/ext/standard/str_starts_with.stubLR~hjLY7vendor/phpstan/php-8-stubs/stubs/ext/standard/file.stubR~hjK7vendor/phpstan/php-8-stubs/stubs/ext/standard/rand.stubFR~hjF8vendor/phpstan/php-8-stubs/stubs/ext/standard/count.stubRR~hjRG=vendor/phpstan/php-8-stubs/stubs/ext/standard/is_numeric.stub3R~hj3r9vendor/phpstan/php-8-stubs/stubs/ext/standard/is_dir.stub3R~hj3:vendor/phpstan/php-8-stubs/stubs/ext/standard/is_link.stub4R~hj4@vendor/phpstan/php-8-stubs/stubs/ext/standard/base64_decode.stubVR~hjV5lQ7vendor/phpstan/php-8-stubs/stubs/ext/standard/cosh.stub,R~hj,ge9vendor/phpstan/php-8-stubs/stubs/ext/standard/strval.stub1R~hj18vendor/phpstan/php-8-stubs/stubs/ext/standard/atan2.stub5R~hj5zABvendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_contents.stub4R~hj4 p>R<vendor/phpstan/php-8-stubs/stubs/ext/standard/fileperms.stub;R~hj;FIvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_recvfrom.stubR~hjUq5$Avendor/phpstan/php-8-stubs/stubs/ext/standard/dns_get_record.stubR~hja[88vendor/phpstan/php-8-stubs/stubs/ext/standard/range.stubR~hjj%>9vendor/phpstan/php-8-stubs/stubs/ext/standard/chroot.stubtR~hjtFvendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect_key.stubOR~hjO 釤;vendor/phpstan/php-8-stubs/stubs/ext/standard/readfile.stubR~hj8vendor/phpstan/php-8-stubs/stubs/ext/standard/atanh.stub-R~hj-OYHvendor/phpstan/php-8-stubs/stubs/ext/standard/array_merge_recursive.stubCR~hjC<Mvendor/phpstan/php-8-stubs/stubs/ext/standard/get_html_translation_table.stubR~hji@vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_length.stub/R~hj/ ם>vendor/phpstan/php-8-stubs/stubs/ext/standard/levenshtein.stubR~hjBvendor/phpstan/php-8-stubs/stubs/ext/standard/proc_get_status.stubhR~hjh_l]9vendor/phpstan/php-8-stubs/stubs/ext/standard/rewind.stubIR~hjIBӐ8vendor/phpstan/php-8-stubs/stubs/ext/standard/rmdir.stubiR~hjipO#?vendor/phpstan/php-8-stubs/stubs/ext/standard/str_ireplace.stubR~hjY9?vendor/phpstan/php-8-stubs/stubs/ext/standard/gettimeofday.stub]R~hj]q;?<vendor/phpstan/php-8-stubs/stubs/ext/standard/microtime.stuboR~hjooĕ:vendor/phpstan/php-8-stubs/stubs/ext/standard/long2ip.stubR~hjQ8vendor/phpstan/php-8-stubs/stubs/ext/standard/fputs.stubR~hj' rDvendor/phpstan/php-8-stubs/stubs/ext/standard/array_udiff_assoc.stubhR~hjhPj>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_callable.stubR~hj(6vendor/phpstan/php-8-stubs/stubs/ext/standard/min.stub?R~hj?Ԥ>vendor/phpstan/php-8-stubs/stubs/ext/standard/utf8_encode.stub8R~hj8_??vendor/phpstan/php-8-stubs/stubs/ext/standard/substr_count.stubnR~hjnH?vendor/phpstan/php-8-stubs/stubs/ext/standard/setrawcookie.stubR~hj$؃Svendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_generate_ctrl_event.stubUR~hjU`?vendor/phpstan/php-8-stubs/stubs/ext/standard/base_convert.stubTR~hjTY!t9vendor/phpstan/php-8-stubs/stubs/ext/standard/hrtime.stubaR~hja2 Evendor/phpstan/php-8-stubs/stubs/ext/standard/move_uploaded_file.stubGR~hjGU*Evendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_timeout.stubR~hjiه;vendor/phpstan/php-8-stubs/stubs/ext/standard/passthru.stubR~hjO^Cvendor/phpstan/php-8-stubs/stubs/ext/standard/http_build_query.stubR~hj:vendor/phpstan/php-8-stubs/stubs/ext/standard/mt_rand.stubIR~hjI:Cvendor/phpstan/php-8-stubs/stubs/ext/standard/array_key_exists.stub]R~hj]^2Gvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_cp_conv.stubvR~hjvI]7vendor/phpstan/php-8-stubs/stubs/ext/standard/feof.stubGR~hjG=m>vendor/phpstan/php-8-stubs/stubs/ext/standard/get_cfg_var.stubDR~hjDA:vendor/phpstan/php-8-stubs/stubs/ext/standard/stripos.stubZR~hjZBSAѤ9vendor/phpstan/php-8-stubs/stubs/ext/standard/strspn.stubjR~hjjx7vendor/phpstan/php-8-stubs/stubs/ext/standard/atan.stub,R~hj,ͤ=vendor/phpstan/php-8-stubs/stubs/ext/standard/localeconv.stub?R~hj?{<vendor/phpstan/php-8-stubs/stubs/ext/standard/error_log.stubR~hj-8vendor/phpstan/php-8-stubs/stubs/ext/standard/popen.stubWR~hjWo.9vendor/phpstan/php-8-stubs/stubs/ext/standard/krsort.stubR~hjbK5vendor/phpstan/php-8-stubs/stubs/ext/standard/pi.stub R~hj _loͤ<vendor/phpstan/php-8-stubs/stubs/ext/standard/fileatime.stubLR~hjL|?vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_flush.stub1R~hj1x7vendor/phpstan/php-8-stubs/stubs/ext/standard/next.stub6R~hj6UPLvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_wrapper_unregister.stubFR~hjFy@vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_status.stub[R~hj[ӁW&9vendor/phpstan/php-8-stubs/stubs/ext/standard/strpos.stubYR~hjYO?:vendor/phpstan/php-8-stubs/stubs/ext/standard/lcfirst.stub4R~hj4 ,9vendor/phpstan/php-8-stubs/stubs/ext/standard/strtok.stubPR~hjPGL9vendor/phpstan/php-8-stubs/stubs/ext/standard/usleep.stub4R~hj4Gvendor/phpstan/php-8-stubs/stubs/ext/standard/array_walk_recursive.stubR~hjc2Evendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_filters.stubGR~hjG4, `Cvendor/phpstan/php-8-stubs/stubs/ext/standard/convert_uudecode.stubCR~hjC6bEvendor/phpstan/php-8-stubs/stubs/ext/standard/request_parse_body.stubR~hj[+Evendor/phpstan/php-8-stubs/stubs/ext/standard/connection_aborted.stub.R~hj.7Avendor/phpstan/php-8-stubs/stubs/ext/standard/call_user_func.stubNR~hjNEvendor/phpstan/php-8-stubs/stubs/ext/standard/array_udiff_uassoc.stubiR~hjiBJӤ9vendor/phpstan/php-8-stubs/stubs/ext/standard/syslog.stubR~hjx;vendor/phpstan/php-8-stubs/stubs/ext/standard/vsprintf.stubDR~hjD?cIvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_shutdown.stubyR~hjy" Dvendor/phpstan/php-8-stubs/stubs/ext/standard/file_get_contents.stubR~hjј7:vendor/phpstan/php-8-stubs/stubs/ext/standard/is_bool.stub0R~hj0=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_push.stubSR~hjS^;?vendor/phpstan/php-8-stubs/stubs/ext/standard/rawurlencode.stub9R~hj99vendor/phpstan/php-8-stubs/stubs/ext/standard/decoct.stub-R~hj-+@vendor/phpstan/php-8-stubs/stubs/ext/standard/base64_encode.stubIR~hjI:vendor/phpstan/php-8-stubs/stubs/ext/standard/fputcsv.stubR~hj^@"9vendor/phpstan/php-8-stubs/stubs/ext/standard/rename.stubqR~hjq<vendor/phpstan/php-8-stubs/stubs/ext/standard/ftruncate.stubWR~hjWӌӣ<vendor/phpstan/php-8-stubs/stubs/ext/standard/inet_pton.stubUR~hjUɔBvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_line.stub|R~hj|9vendor/phpstan/php-8-stubs/stubs/ext/standard/intdiv.stub6R~hj6]aФ>vendor/phpstan/php-8-stubs/stubs/ext/standard/array_slice.stubtR~hjt8vendor/phpstan/php-8-stubs/stubs/ext/standard/chown.stubDR~hjDs8vendor/phpstan/php-8-stubs/stubs/ext/standard/reset.stub7R~hj7?_6vendor/phpstan/php-8-stubs/stubs/ext/standard/abs.stub@R~hj@D_fӤ?vendor/phpstan/php-8-stubs/stubs/ext/standard/str_contains.stubIR~hjIi:3ˤ<vendor/phpstan/php-8-stubs/stubs/ext/standard/fdatasync.stub]R~hj]@9vendor/phpstan/php-8-stubs/stubs/ext/standard/octdec.stub<R~hj<9Cvendor/phpstan/php-8-stubs/stubs/ext/standard/highlight_string.stubR~hjkb>vendor/phpstan/php-8-stubs/stubs/ext/standard/array_chunk.stub_R~hj_ZǤ<vendor/phpstan/php-8-stubs/stubs/ext/standard/proc_open.stubR~hj >vendor/phpstan/php-8-stubs/stubs/ext/standard/array_udiff.stubbR~hjbKBvendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff_ukey.stubfR~hjf7 <vendor/phpstan/php-8-stubs/stubs/ext/standard/getrusage.stubnR~hjn<=vendor/phpstan/php-8-stubs/stubs/ext/standard/getlastmod.stub,R~hj,ӤBvendor/phpstan/php-8-stubs/stubs/ext/standard/array_key_first.stubCR~hjCHrʷ:vendor/phpstan/php-8-stubs/stubs/ext/standard/is_null.stub0R~hj0E87vendor/phpstan/php-8-stubs/stubs/ext/standard/join.stubfR~hjfa)Evendor/phpstan/php-8-stubs/stubs/ext/standard/realpath_cache_get.stubGR~hjG֧7vendor/phpstan/php-8-stubs/stubs/ext/standard/prev.stub6R~hj6l:vendor/phpstan/php-8-stubs/stubs/ext/standard/getmxrr.stubR~hj~ߤ6vendor/phpstan/php-8-stubs/stubs/ext/standard/sin.stub+R~hj+֊Ivendor/phpstan/php-8-stubs/stubs/ext/standard/__PHP_Incomplete_Class.stub^R~hj^LG8HAvendor/phpstan/php-8-stubs/stubs/ext/standard/str_word_count.stubR~hjw}Avendor/phpstan/php-8-stubs/stubs/ext/standard/clearstatcache.stubkR~hjk?Evendor/phpstan/php-8-stubs/stubs/ext/standard/http_response_code.stubIR~hjIyg Bvendor/phpstan/php-8-stubs/stubs/ext/standard/debug_zval_dump.stubJR~hjJd5͉?vendor/phpstan/php-8-stubs/stubs/ext/standard/stripslashes.stub9R~hj9mHvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_copy_to_stream.stubR~hj?K8vendor/phpstan/php-8-stubs/stubs/ext/standard/srand.stubR~hjv N=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_walk.stubR~hjZ8vendor/phpstan/php-8-stubs/stubs/ext/standard/asinh.stub-R~hj-ޤ:vendor/phpstan/php-8-stubs/stubs/ext/standard/sprintf.stub^R~hj^SJvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_write_buffer.stubdR~hjd<vendor/phpstan/php-8-stubs/stubs/ext/standard/setcookie.stubR~hjN~:vendor/phpstan/php-8-stubs/stubs/ext/standard/natsort.stub}R~hj}*#<vendor/phpstan/php-8-stubs/stubs/ext/standard/quotemeta.stub6R~hj6V 8vendor/phpstan/php-8-stubs/stubs/ext/standard/rsort.stubR~hj1>\EGvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_filter_remove.stubeR~hje8m%Bvendor/phpstan/php-8-stubs/stubs/ext/standard/set_file_buffer.stubR~hjOKAvendor/phpstan/php-8-stubs/stubs/ext/standard/escapeshellcmd.stub<R~hj<E-_=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_keys.stubR~hj b>vendor/phpstan/php-8-stubs/stubs/ext/standard/natcasesort.stubR~hjAi:vendor/phpstan/php-8-stubs/stubs/ext/standard/current.stub8R~hj8Nr7vendor/phpstan/php-8-stubs/stubs/ext/standard/fpow.stubiR~hji v<vendor/phpstan/php-8-stubs/stubs/ext/standard/proc_nice.stubDR~hjDFvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_cp_set.stubeR~hjeNv[7vendor/phpstan/php-8-stubs/stubs/ext/standard/copy.stuboR~hjoK=>vendor/phpstan/php-8-stubs/stubs/ext/standard/chunk_split.stubfR~hjf-j:vendor/phpstan/php-8-stubs/stubs/ext/standard/symlink.stub@R~hj@/jHvendor/phpstan/php-8-stubs/stubs/ext/standard/array_change_key_case.stubWR~hjWQIvendor/phpstan/php-8-stubs/stubs/ext/standard/register_tick_function.stub\R~hj\n(Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_accept.stubR~hj(_@vendor/phpstan/php-8-stubs/stubs/ext/standard/password_hash.stubhR~hjh4YBvendor/phpstan/php-8-stubs/stubs/ext/standard/version_compare.stubR~hjZ5g8vendor/phpstan/php-8-stubs/stubs/ext/standard/crypt.stubNR~hjN7;vendor/phpstan/php-8-stubs/stubs/ext/standard/closedir.stub_R~hj_DyJSvendor/phpstan/php-8-stubs/stubs/ext/standard/http_clear_last_response_headers.stubNR~hjNA#:vendor/phpstan/php-8-stubs/stubs/ext/standard/shuffle.stub}R~hj}ʓc~:vendor/phpstan/php-8-stubs/stubs/ext/standard/strcspn.stubkR~hjk~:vendor/phpstan/php-8-stubs/stubs/ext/standard/hex2bin.stub:R~hj:@Q\1:vendor/phpstan/php-8-stubs/stubs/ext/standard/compact.stubR~hjzؤ7vendor/phpstan/php-8-stubs/stubs/ext/standard/asin.stub,R~hj,+99vendor/phpstan/php-8-stubs/stubs/ext/standard/lchgrp.stubFR~hjFa;9vendor/phpstan/php-8-stubs/stubs/ext/standard/fflush.stubIR~hjId$_`;vendor/phpstan/php-8-stubs/stubs/ext/standard/basename.stubHR~hjH]aפ9vendor/phpstan/php-8-stubs/stubs/ext/standard/fscanf.stubR~hjt[ <vendor/phpstan/php-8-stubs/stubs/ext/standard/array_pop.stub4R~hj4mߤ@vendor/phpstan/php-8-stubs/stubs/ext/standard/mt_getrandmax.stub)R~hj)ag?vendor/phpstan/php-8-stubs/stubs/ext/standard/getimagesize.stubR~hj:vendor/phpstan/php-8-stubs/stubs/ext/standard/deg2rad.stub/R~hj/C~Jvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_cp_is_utf8.stub4R~hj4VЋ8vendor/phpstan/php-8-stubs/stubs/ext/standard/lstat.stubPR~hjPBvendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect.stubKR~hjK]6vendor/phpstan/php-8-stubs/stubs/ext/standard/pow.stubGR~hjG\4ϤDvendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff_uassoc.stubhR~hjh:vendor/phpstan/php-8-stubs/stubs/ext/standard/ip2long.stub3R~hj3Evendor/phpstan/php-8-stubs/stubs/ext/standard/array_count_values.stubiR~hjirZe8vendor/phpstan/php-8-stubs/stubs/ext/standard/acosh.stub-R~hj-3>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_readable.stub8R~hj8[Kz@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_is_list.stubGR~hjG86vendor/phpstan/php-8-stubs/stubs/ext/standard/key.stub>R~hj>{ܠ@vendor/phpstan/php-8-stubs/stubs/ext/standard/get_meta_tags.stubxR~hjxRp@vendor/phpstan/php-8-stubs/stubs/ext/standard/strnatcasecmp.stubIR~hjIA_'Hvendor/phpstan/php-8-stubs/stubs/ext/standard/array_intersect_assoc.stubQR~hjQ³L>vendor/phpstan/php-8-stubs/stubs/ext/standard/unserialize.stubJR~hjJɒ<vendor/phpstan/php-8-stubs/stubs/ext/standard/parse_url.stubR~hjs+Bvendor/phpstan/php-8-stubs/stubs/ext/standard/config_get_hash.stubSR~hjSV+Gvendor/phpstan/php-8-stubs/stubs/ext/standard/call_user_func_array.stubQR~hjQ+wBvendor/phpstan/php-8-stubs/stubs/ext/standard/disk_free_space.stubDR~hjD,TAvendor/phpstan/php-8-stubs/stubs/ext/standard/time_nanosleep.stubyR~hjy08vendor/phpstan/php-8-stubs/stubs/ext/standard/fgetc.stubPR~hjP̳khDvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_bucket_new.stubR~hj6놞6vendor/phpstan/php-8-stubs/stubs/ext/standard/exp.stub+R~hj+ۤ<vendor/phpstan/php-8-stubs/stubs/ext/standard/is_finite.stub0R~hj0Ar7vendor/phpstan/php-8-stubs/stubs/ext/standard/sqrt.stub,R~hj,9vendor/phpstan/php-8-stubs/stubs/ext/standard/is_int.stub/R~hj/^:vendor/phpstan/php-8-stubs/stubs/ext/standard/print_r.stubR~hj"N;vendor/phpstan/php-8-stubs/stubs/ext/standard/strripos.stub[R~hj[ҤBvendor/phpstan/php-8-stubs/stubs/ext/standard/array_fill_keys.stubFR~hjFmIvendor/phpstan/php-8-stubs/stubs/ext/standard/getimagesizefromstring.stubR~hjyCvendor/phpstan/php-8-stubs/stubs/ext/standard/error_clear_last.stub-R~hj-sq8:vendor/phpstan/php-8-stubs/stubs/ext/standard/explode.stubR~hjҤ(M@vendor/phpstan/php-8-stubs/stubs/ext/standard/str_decrement.stubKR~hjKzR>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_iterable.stub4R~hj48ŝ:vendor/phpstan/php-8-stubs/stubs/ext/standard/tempnam.stubMR~hjM>{$Cvendor/phpstan/php-8-stubs/stubs/ext/standard/get_include_path.stub5R~hj5ha;vendor/phpstan/php-8-stubs/stubs/ext/standard/strptime.stubR~hj~Mvendor/phpstan/php-8-stubs/stubs/ext/standard/register_shutdown_function.stubR~hjJKJvendor/phpstan/php-8-stubs/stubs/ext/standard/memory_reset_peak_usage.stubER~hjE4?9vendor/phpstan/php-8-stubs/stubs/ext/standard/hexdec.stub:R~hj:AT9vendor/phpstan/php-8-stubs/stubs/ext/standard/dechex.stub-R~hj-•UCvendor/phpstan/php-8-stubs/stubs/ext/standard/convert_uuencode.stubNR~hjN~<vendor/phpstan/php-8-stubs/stubs/ext/standard/setlocale.stubR~hj Ib9vendor/phpstan/php-8-stubs/stubs/ext/standard/strchr.stub}R~hj}F:vendor/phpstan/php-8-stubs/stubs/ext/standard/fgetcsv.stubR~hj('Avendor/phpstan/php-8-stubs/stubs/ext/standard/proc_terminate.stubeR~hjeuOCvendor/phpstan/php-8-stubs/stubs/ext/standard/memory_get_usage.stubDR~hjDEN>vendor/phpstan/php-8-stubs/stubs/ext/standard/nl_langinfo.stubNR~hjNvendor/phpstan/php-8-stubs/stubs/ext/standard/array_merge.stub9R~hj9d>vendor/phpstan/php-8-stubs/stubs/ext/standard/file_exists.stub8R~hj8^,=vendor/phpstan/php-8-stubs/stubs/ext/standard/strtolower.stub7R~hj7<vendor/phpstan/php-8-stubs/stubs/ext/standard/str_split.stubdR~hjdͤ:vendor/phpstan/php-8-stubs/stubs/ext/standard/soundex.stubDR~hjD+/DAvendor/phpstan/php-8-stubs/stubs/ext/standard/substr_replace.stubR~hj[[>vendor/phpstan/php-8-stubs/stubs/ext/standard/utf8_decode.stub8R~hj8{,6vendor/phpstan/php-8-stubs/stubs/ext/standard/ord.stub0R~hj02a/Evendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_pair.stubR~hjXy:vendor/phpstan/php-8-stubs/stubs/ext/standard/ucfirst.stub4R~hj4 ܤ;vendor/phpstan/php-8-stubs/stubs/ext/standard/vfprintf.stubiR~hjiAɤ6vendor/phpstan/php-8-stubs/stubs/ext/standard/log.stub>R~hj>G5vendor/phpstan/php-8-stubs/stubs/ext/standard/dl.stub9R~hj9-U~Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_filter_append.stubR~hj;<vendor/phpstan/php-8-stubs/stubs/ext/standard/php_uname.stub:R~hj::vendor/phpstan/php-8-stubs/stubs/ext/standard/strrpos.stubZR~hjZG} 7vendor/phpstan/php-8-stubs/stubs/ext/standard/fdiv.stub:R~hj:];vendor/phpstan/php-8-stubs/stubs/ext/standard/readlink.stubvR~hjvHPMvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_get_options.stubxR~hjxໄ=vendor/phpstan/php-8-stubs/stubs/ext/standard/random_int.stub8R~hj8#sJvendor/phpstan/php-8-stubs/stubs/ext/standard/image_type_to_mime_type.stubSR~hjS1{Τ<vendor/phpstan/php-8-stubs/stubs/ext/standard/sha1_file.stubTR~hjTdEW":vendor/phpstan/php-8-stubs/stubs/ext/standard/rad2deg.stub/R~hj/dO-@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_combine.stubER~hjEc`Cvendor/phpstan/php-8-stubs/stubs/ext/standard/parse_ini_string.stubR~hj t9vendor/phpstan/php-8-stubs/stubs/ext/standard/getopt.stubR~hj<vendor/phpstan/php-8-stubs/stubs/ext/standard/lcg_value.stub3R~hj3r*@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_unshift.stubHR~hjHb`?vendor/phpstan/php-8-stubs/stubs/ext/standard/StreamBucket.stub R~hj "i7?vendor/phpstan/php-8-stubs/stubs/ext/standard/random_bytes.stubER~hjEO;vendor/phpstan/php-8-stubs/stubs/ext/standard/in_array.stubYR~hjY(1ä@vendor/phpstan/php-8-stubs/stubs/ext/standard/gethostbyname.stub<R~hj<?N<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_any.stubWR~hjWD9vendor/phpstan/php-8-stubs/stubs/ext/standard/sscanf.stubsR~hjs ]@vendor/phpstan/php-8-stubs/stubs/ext/standard/php_sapi_name.stub2R~hj2Y<vendor/phpstan/php-8-stubs/stubs/ext/standard/filectime.stub;R~hj;3:vendor/phpstan/php-8-stubs/stubs/ext/standard/readdir.stubfR~hjf97Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_bucket_append.stubR~hjkKvendor/phpstan/php-8-stubs/stubs/ext/standard/unregister_tick_function.stubGR~hjG{5:vendor/phpstan/php-8-stubs/stubs/ext/standard/phpinfo.stubR~hjߒAvendor/phpstan/php-8-stubs/stubs/ext/standard/getprotobyname.stub_R~hj_q7vendor/phpstan/php-8-stubs/stubs/ext/standard/ftok.stubfR~hjf/':vendor/phpstan/php-8-stubs/stubs/ext/standard/bin2hex.stubCR~hjCFۤ>vendor/phpstan/php-8-stubs/stubs/ext/standard/is_resource.stub4R~hj4U8vendor/phpstan/php-8-stubs/stubs/ext/standard/log10.stub-R~hj-nɤDvendor/phpstan/php-8-stubs/stubs/ext/standard/ob_implicit_flush.stubAR~hjAQvendor/phpstan/php-8-stubs/stubs/ext/standard/http_get_last_response_headers.stubNR~hjN=Ĥ@vendor/phpstan/php-8-stubs/stubs/ext/standard/gethostbyaddr.stubCR~hjC9vendor/phpstan/php-8-stubs/stubs/ext/standard/substr.stubUR~hjUE#Ovendor/phpstan/php-8-stubs/stubs/ext/standard/stream_bucket_make_writeable.stub'R~hj'PΤCvendor/phpstan/php-8-stubs/stubs/ext/standard/htmlspecialchars.stubR~hjW֤:vendor/phpstan/php-8-stubs/stubs/ext/standard/gettype.stubFR~hjF_8vendor/phpstan/php-8-stubs/stubs/ext/standard/expm1.stub-R~hj-Bf:vendor/phpstan/php-8-stubs/stubs/ext/standard/str_pad.stubzR~hjze!>vendor/phpstan/php-8-stubs/stubs/ext/standard/get_browser.stubR~hj/.8vendor/phpstan/php-8-stubs/stubs/ext/standard/umask.stub2R~hj2&M<vendor/phpstan/php-8-stubs/stubs/ext/standard/rewinddir.stub`R~hj`=8vendor/phpstan/php-8-stubs/stubs/ext/standard/fstat.stubbR~hjbh7:vendor/phpstan/php-8-stubs/stubs/ext/standard/is_long.stubER~hjEH;vendor/phpstan/php-8-stubs/stubs/ext/standard/pathinfo.stubkR~hjk6[Ĥ<vendor/phpstan/php-8-stubs/stubs/ext/standard/fileowner.stub;R~hj;OhDvendor/phpstan/php-8-stubs/stubs/ext/standard/connection_status.stub-R~hj-n @vendor/phpstan/php-8-stubs/stubs/ext/standard/number_format.stubR~hj49vendor/phpstan/php-8-stubs/stubs/ext/standard/pclose.stubHR~hjH=t=vendor/phpstan/php-8-stubs/stubs/ext/standard/is_integer.stubHR~hjH =vendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff.stubFR~hjFC@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_replace.stubOR~hjO|7c:vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_set.stubR~hjP<vendor/phpstan/php-8-stubs/stubs/ext/standard/array_map.stubZR~hjZKcܤ:vendor/phpstan/php-8-stubs/stubs/ext/standard/ucwords.stubXR~hjX|ΤIvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_get_name.stuboR~hjo QQJvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_wrapper_register.stubR~hjK$8vendor/phpstan/php-8-stubs/stubs/ext/standard/fseek.stublR~hjl7vendor/phpstan/php-8-stubs/stubs/ext/standard/tanh.stub,R~hj,ש7vendor/phpstan/php-8-stubs/stubs/ext/standard/link.stub=R~hj= Jvendor/phpstan/php-8-stubs/stubs/ext/standard/image_type_to_extension.stubeR~hjecNvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_resolve_include_path.stubPR~hjP'F^Ivendor/phpstan/php-8-stubs/stubs/ext/standard/stream_filter_register.stubUR~hjU-n=vendor/phpstan/php-8-stubs/stubs/ext/standard/var_export.stubLR~hjLk\}Evendor/phpstan/php-8-stubs/stubs/ext/standard/net_get_interfaces.stubR~hjt1Mvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_set_default.stubWR~hjWD8vendor/phpstan/php-8-stubs/stubs/ext/standard/chmod.stubKR~hjK8vendor/phpstan/php-8-stubs/stubs/ext/standard/flush.stub"R~hj"E9vendor/phpstan/php-8-stubs/stubs/ext/standard/fclose.stubIR~hjIp|9vendor/phpstan/php-8-stubs/stubs/ext/standard/is_nan.stub-R~hj-#"Ivendor/phpstan/php-8-stubs/stubs/ext/standard/stream_wrapper_restore.stubCR~hjCAe:vendor/phpstan/php-8-stubs/stubs/ext/standard/vprintf.stub@R~hj@^ACvendor/phpstan/php-8-stubs/stubs/ext/standard/is_uploaded_file.stub=R~hj=Էr2Mvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_set_options.stub R~hj 'hĤ?vendor/phpstan/php-8-stubs/stubs/ext/standard/rawurldecode.stub9R~hj96<vendor/phpstan/php-8-stubs/stubs/ext/standard/is_string.stub2R~hj2x?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_search.stubiR~hjiaiPvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_set_ctrl_handler.stub^R~hj^|Lvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_context_set_params.stubR~hj9<Fvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_contents.stubR~hj0$7vendor/phpstan/php-8-stubs/stubs/ext/standard/exec.stubR~hj67vendor/phpstan/php-8-stubs/stubs/ext/standard/ceil.stub0R~hj0R>9vendor/phpstan/php-8-stubs/stubs/ext/standard/header.stubpR~hjp7^=vendor/phpstan/php-8-stubs/stubs/ext/standard/getmyinode.stub,R~hj,$h8vendor/phpstan/php-8-stubs/stubs/ext/standard/strtr.stubZR~hjZ<Jvendor/phpstan/php-8-stubs/stubs/ext/standard/quoted_printable_encode.stubDR~hjD0,>vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_restore.stub6R~hj6ik@vendor/phpstan/php-8-stubs/stubs/ext/standard/str_ends_with.stubJR~hjJJO8vendor/phpstan/php-8-stubs/stubs/ext/standard/nl2br.stubJR~hjJ;WtB<vendor/phpstan/php-8-stubs/stubs/ext/standard/is_double.stubIR~hjIFvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_cp_get.stub@R~hj@9Avendor/phpstan/php-8-stubs/stubs/ext/standard/error_get_last.stubDR~hjDU1̤?vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_level.stub(R~hj(y,Avendor/phpstan/php-8-stubs/stubs/ext/standard/sys_getloadavg.stubgR~hjg{dv?vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_get_clean.stub1R~hj1zդ9vendor/phpstan/php-8-stubs/stubs/ext/standard/fwrite.stubqR~hjqAvendor/phpstan/php-8-stubs/stubs/ext/standard/assert_options.stubOR~hjO}dIvendor/phpstan/php-8-stubs/stubs/ext/standard/output_add_rewrite_var.stubNR~hjN]4:vendor/phpstan/php-8-stubs/stubs/ext/standard/strcoll.stubJR~hjJ09vendor/phpstan/php-8-stubs/stubs/ext/standard/unpack.stubR~hjS}T٤<vendor/phpstan/php-8-stubs/stubs/ext/standard/iptcparse.stubVR~hjVה9vendor/phpstan/php-8-stubs/stubs/ext/standard/arsort.stubR~hjD=vendor/phpstan/php-8-stubs/stubs/ext/standard/str_getcsv.stubR~hj:7 Cvendor/phpstan/php-8-stubs/stubs/ext/standard/dns_check_record.stubR~hj@vendor/phpstan/php-8-stubs/stubs/ext/standard/is_executable.stub:R~hj:Hp9vendor/phpstan/php-8-stubs/stubs/ext/standard/getcwd.stub2R~hj288Ǥ;vendor/phpstan/php-8-stubs/stubs/ext/standard/filesize.stub:R~hj:Ivendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_read_buffer.stubcR~hjcm@vendor/phpstan/php-8-stubs/stubs/ext/standard/header_remove.stub>R~hj>}Hvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_filter_prepend.stubR~hj)8vendor/phpstan/php-8-stubs/stubs/ext/standard/hypot.stub5R~hj5(47vendor/phpstan/php-8-stubs/stubs/ext/standard/acos.stub,R~hj,t׽9vendor/phpstan/php-8-stubs/stubs/ext/standard/assert.stubxR~hjx͢Mo<vendor/phpstan/php-8-stubs/stubs/ext/standard/doubleval.stubJR~hjJg(6vendor/phpstan/php-8-stubs/stubs/ext/standard/md5.stubRR~hjR)<vendor/phpstan/php-8-stubs/stubs/ext/standard/str_rot13.stub6R~hj6谛;Avendor/phpstan/php-8-stubs/stubs/ext/standard/set_time_limit.stubkR~hjk,mz8vendor/phpstan/php-8-stubs/stubs/ext/standard/asort.stubR~hjU!Fvendor/phpstan/php-8-stubs/stubs/ext/standard/forward_static_call.stubSR~hjS;vendor/phpstan/php-8-stubs/stubs/ext/standard/floatval.stub2R~hj229vendor/phpstan/php-8-stubs/stubs/ext/standard/lchown.stubUR~hjUY6vendor/phpstan/php-8-stubs/stubs/ext/standard/tan.stub+R~hj+*>BZ@vendor/phpstan/php-8-stubs/stubs/ext/standard/getservbyname.stubgR~hjg@vendor/phpstan/php-8-stubs/stubs/ext/standard/str_increment.stubKR~hjKtMvendor/phpstan/php-8-stubs/stubs/ext/standard/sapi_windows_vt100_support.stubR~hj?@vendor/phpstan/php-8-stubs/stubs/ext/standard/array_product.stub;R~hj;q-?vendor/phpstan/php-8-stubs/stubs/ext/standard/is_countable.stub5R~hj5s=vendor/phpstan/php-8-stubs/stubs/ext/standard/checkdnsrr.stubkR~hjk:vendor/phpstan/php-8-stubs/stubs/ext/standard/extract.stub|R~hj|f;vendor/phpstan/php-8-stubs/stubs/ext/standard/mt_srand.stubR~hj'=vendor/phpstan/php-8-stubs/stubs/ext/standard/strip_tags.stub_R~hj_fAvendor/phpstan/php-8-stubs/stubs/ext/standard/gethostbynamel.stubYR~hjY{Ivendor/phpstan/php-8-stubs/stubs/ext/standard/array_uintersect_assoc.stubmR~hjmM)wAvendor/phpstan/php-8-stubs/stubs/ext/standard/AssertionError.stub@R~hj@6¤Fvendor/phpstan/php-8-stubs/stubs/ext/standard/realpath_cache_size.stub/R~hj/zl?vendor/phpstan/php-8-stubs/stubs/ext/standard/similar_text.stubwR~hjw<9vendor/phpstan/php-8-stubs/stubs/ext/standard/strstr.stubhR~hjh<:vendor/phpstan/php-8-stubs/stubs/ext/standard/openlog.stubR~hj&r`Cvendor/phpstan/php-8-stubs/stubs/ext/standard/array_uintersect.stubgR~hjgVś;vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_flush.stub%R~hj%$E8vendor/phpstan/php-8-stubs/stubs/ext/standard/ftell.stubMR~hjMT46vendor/phpstan/php-8-stubs/stubs/ext/standard/end.stub5R~hj5e?vendor/phpstan/php-8-stubs/stubs/ext/standard/is_writeable.stubSR~hjS>vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_get_all.stubuR~hjṳ7vendor/phpstan/php-8-stubs/stubs/ext/standard/mail.stubR~hjfc?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_filter.stubaR~hja:vendor/phpstan/php-8-stubs/stubs/ext/standard/is_file.stub4R~hj4J8vendor/phpstan/php-8-stubs/stubs/ext/standard/flock.stubR~hj)-&6vendor/phpstan/php-8-stubs/stubs/ext/standard/cos.stub+R~hj+YF*Avendor/phpstan/php-8-stubs/stubs/ext/standard/get_debug_type.stub9R~hj91&D7vendor/phpstan/php-8-stubs/stubs/ext/standard/glob.stuboR~hjoѤFvendor/phpstan/php-8-stubs/stubs/ext/standard/php_ini_loaded_file.stub8R~hj80 Avendor/phpstan/php-8-stubs/stubs/ext/standard/array_diff_key.stubJR~hjJ=+Nvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_enable_crypto.stubR~hj|j"Gvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_socket_client.stub1R~hj1sx6vendor/phpstan/php-8-stubs/stubs/ext/standard/dir.stubsR~hjs??vendor/phpstan/php-8-stubs/stubs/ext/standard/ob_end_flush.stub)R~hj)Ҥ;vendor/phpstan/php-8-stubs/stubs/ext/standard/closelog.stubeR~hjeI;vendor/phpstan/php-8-stubs/stubs/ext/standard/is_array.stub1R~hj1曤9vendor/phpstan/php-8-stubs/stubs/ext/standard/uniqid.stub|R~hj|=7Cvendor/phpstan/php-8-stubs/stubs/ext/standard/sys_get_temp_dir.stub6R~hj6QqDvendor/phpstan/php-8-stubs/stubs/ext/standard/file_put_contents.stubR~hjAvendor/phpstan/php-8-stubs/stubs/ext/standard/highlight_file.stubXR~hjXH:7vendor/phpstan/php-8-stubs/stubs/ext/standard/trim.stubWR~hjW+8vendor/phpstan/php-8-stubs/stubs/ext/standard/log1p.stub-R~hj-`9:vendor/phpstan/php-8-stubs/stubs/ext/standard/ini_get.stub:R~hj:=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_find.stubYR~hjYn<9vendor/phpstan/php-8-stubs/stubs/ext/standard/hebrev.stubPR~hjPJ=I?vendor/phpstan/php-8-stubs/stubs/ext/standard/array_splice.stubrR~hjrÝ5Hvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_get_transports.stubJR~hjJǤ7vendor/phpstan/php-8-stubs/stubs/ext/standard/pack.stubWR~hjW1ݤCvendor/phpstan/php-8-stubs/stubs/ext/standard/disk_total_space.stubER~hjEBx̤<vendor/phpstan/php-8-stubs/stubs/ext/standard/parse_str.stubZR~hjZȇPIHvendor/phpstan/php-8-stubs/stubs/ext/standard/password_needs_rehash.stubjR~hjj7O9vendor/phpstan/php-8-stubs/stubs/ext/standard/system.stuboR~hjo7қ=vendor/phpstan/php-8-stubs/stubs/ext/standard/key_exists.stubvR~hjv@);;vendor/phpstan/php-8-stubs/stubs/ext/standard/constant.stubJR~hjJk,=vendor/phpstan/php-8-stubs/stubs/ext/standard/array_rand.stubMR~hjMBQ8vendor/phpstan/php-8-stubs/stubs/ext/standard/touch.stubiR~hjiA8vendor/phpstan/php-8-stubs/stubs/ext/standard/fread.stub]R~hj]kO:vendor/phpstan/php-8-stubs/stubs/ext/standard/scandir.stubR~hj:=vendor/phpstan/php-8-stubs/stubs/ext/standard/str_repeat.stubCR~hjC+:vendor/phpstan/php-8-stubs/stubs/ext/standard/strpbrk.stubNR~hjNKݤ6vendor/phpstan/php-8-stubs/stubs/ext/standard/pos.stubJR~hjJ@vendor/phpstan/php-8-stubs/stubs/ext/standard/getservbyport.stubkR~hjkFW9vendor/phpstan/php-8-stubs/stubs/ext/standard/bindec.stub=R~hj=kXa<vendor/phpstan/php-8-stubs/stubs/ext/standard/urlencode.stub6R~hj6zeHvendor/phpstan/php-8-stubs/stubs/ext/standard/memory_get_peak_usage.stubIR~hjI)*<vendor/phpstan/php-8-stubs/stubs/ext/standard/fpassthru.stubKR~hjK9vendor/phpstan/php-8-stubs/stubs/ext/standard/sizeof.stubgR~hjgDHvendor/phpstan/php-8-stubs/stubs/ext/standard/stream_set_chunk_size.stubiR~hji@)>vendor/phpstan/php-8-stubs/stubs/ext/tokenizer/token_name.stub0R~hj0$E<vendor/phpstan/php-8-stubs/stubs/ext/tokenizer/PhpToken.stubR~hj+nAvendor/phpstan/php-8-stubs/stubs/ext/tokenizer/token_get_all.stubiR~hji8L+;vendor/phpstan/php-8-stubs/stubs/ext/xsl/XSLTProcessor.stubR~hj_Y:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_read.stubR~hjdO :vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_untrace.stub/R~hj/>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_socket_poll.stubR~hj@{;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_write.stubR~hj u?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connect_poll.stubR~hj34>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldisnull.stubR~hjy =vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_freeresult.stubR~hjע<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loreadall.stubR~hje4@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_is_null.stubR~hj6>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_last_notice.stubR~hjWnXBvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connection_busy.stubR~hjQEvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_memory_size.stubyR~hjyڤAvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_unescape_bytea.stub>R~hj>} T=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_type.stubR~hjD1Cvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connection_reset.stubR~hjMW<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldname.stubR~hjt;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldnum.stubR~hjogǤ=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_get_result.stubR~hjvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldprtlen.stubR~hj ʤFvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_set_client_encoding.stub)R~hj)H);vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_put_line.stubR~hjƤ?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_cancel_query.stubR~hj)2T>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_seek.stubR~hjƼI;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_end_copy.stubR~hjng:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_version.stub R~hj  !:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connect.stubR~hjEvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_error_field.stub R~hj ~Z>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_read_all.stubR~hjpH@?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_send_execute.stubR~hjRDvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_send_query_params.stub R~hj 7/:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_copy_to.stubR~hj@>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_truncate.stubR~hj@I=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_get_notify.stub:R~hj:%9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_delete.stub[R~hj[H_%:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loclose.stubR~hję;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lounlink.stubwR~hjw ?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_query_params.stubR~hjF?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_errormessage.stub0R~hj0zHvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_set_chunked_rows_size.stubR~hjj/:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_get_pid.stubR~hjgr ?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_send_prepare.stubR~hj\*;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_last_oid.stubR~hjSb6vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_jit.stubR~hjf9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_socket.stubR~hjГOvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_set_error_context_visibility.stubR~hjz뇤:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lowrite.stub>R~hj>ITe<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldsize.stubR~hj8bx@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_consume_input.stubR~hjEe<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_create.stubhR~hjh8.@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_affected_rows.stubR~hjh+9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/PgSql/Lob.stubqR~hjq<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/PgSql/Result.stubtR~hjtK}@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/PgSql/Connection.stubxR~hjxZ@ 18vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_query.stubCR~hjC>[@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_put_copy_data.stubgR~hjgg;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_num_rows.stubR~hj}h78vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_close.stub)R~hj)jI8vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_trace.stubR~hj%;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loimport.stubR~hj` <vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_numfields.stubR~hjX:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_numrows.stubR~hjx?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_object.stubiR~hjip,ؤ7vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_host.stubR~hjݤpm=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_last_error.stubR~hjADAvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_type_oid.stubR~hjmRk<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_export.stubR~hj>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_table.stub R~hj FAvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_clientencoding.stub>R~hj>b<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_meta_data.stub[R~hj[>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_array.stubYR~hjYmyƤ?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_error.stubR~hja&Bvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_client_encoding.stubR~hj9 Dvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_connection_status.stubR~hjy;>vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_assoc.stub)R~hj)Dl灤9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_update.stubyR~hjy=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_getlastoid.stubR~hj{ ?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_put_copy_end.stubpR~hjpܳפ@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_escape_string.stub2R~hj2I8vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_flush.stubR~hj'[7vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_port.stubR~hjƤ;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loexport.stubR~hjvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_free_result.stubR~hjD<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fieldtype.stubR~hjvEvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_transaction_status.stubR~hj3 ;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_locreate.stubR~hj:"=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_name.stubR~hja<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_row.stubSR~hjSVn?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_prtlen.stubR~hj'4:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_seek.stubR~hjW:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_convert.stubeR~hje%˯Cvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_parameter_status.stub@R~hj@ϧݤ9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_loopen.stubR~hjo<@vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_result_status.stub R~hj 4J=vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_num_fields.stubR~hj <vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_field_num.stubR~hj8,7vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_ping.stubR~hjG<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_copy_from.stubdR~hjddSf:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_tell.stubR~hjN;vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_pconnect.stubR~hjBĤDvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_setclientencoding.stubR~hj|:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_prepare.stubwR~hjwt7vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_exec.stubXR~hjXRDvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_escape_identifier.stubFR~hjF;l^Avendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_escape_literal.stub@R~hj@yȤ<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_all.stubR~hj14?vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_escape_bytea.stub0R~hj0WmI:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_options.stubR~hjwfS<vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_cmdtuples.stubR~hj; 9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_insert.stubxR~hjx1(9vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_select.stubR~hj]KJ6vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_tty.stubR~hjM ݤ:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_lo_open.stubR~hjHT:vendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_execute.stubR~hj^wDvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_fetch_all_columns.stubR~hjEBvendor/phpstan/php-8-stubs/stubs/ext/pgsql/pg_change_password.stubR~hj-9[<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_kill.stubGR~hjG/BI<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_poll.stubR~hjeEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_affected_rows.stubER~hjECvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_thread_safe.stub/R~hj/GĤDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_prepare.stubVR~hjV`Cvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_change_user.stubtR~hjtvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_driver.stubGR~hjGAiDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_more_results.stub>R~hj>yCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_field_count.stub<R~hj<FGV?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_connect.stubR~hjpFvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_proto_info.stub?R~hj?0!<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_ping.stub6R~hj6DFvAvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_thread_id.stub:R~hj:YXHvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_free_result.stubKR~hjK,Cvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_free_result.stubER~hjE@@vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_rollback.stub`R~hj`Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_num_rows.stubUR~hjUIDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_object.stubR~hj'U=vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_errno.stub6R~hj6깤Jvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_real_escape_string.stubVR~hjV<1Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_warning_count.stub>R~hj>Y!%<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_info.stub9R~hj9nmCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_multi_query.stubLR~hjLRIvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_more_results.stublR~hjl#>vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_result.stub% R~hj% Xo?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_set_opt.stubR~hj=7vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli.stub2R~hj2aqDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_column.stubR~hj^EBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_error.stubGR~hjG}*Jvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_client_version.stub5R~hj5DCEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_host_info.stubAR~hjA`Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_lengths.stubeR~hje{ܧIvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_get_warnings.stubdR~hjd\'<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt.stub8 R~hj8 rdAvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_savepoint.stubIR~hjIBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_autocommit.stubJR~hjJ>6Dvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_warnings.stubOR~hjO|Bvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_errno.stubDR~hjD2v6Gvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_error_list.stubbR~hjbIgDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_execute.stubR~hj&2ԤLvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_connection_stats.stub~R~hj~vCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_set_charset.stubNR~hjN='6?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_execute.stubR~hj=cEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_connect_error.stub4R~hj4xHvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_client_stats.stubLR~hjL Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_attr_get.stubWR~hjW}>Gvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_get_result.stubzR~hjzZ}Avendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_select_db.stubMR~hjM[Ivendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_release_savepoint.stubXR~hjX֮Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_escape_string.stubyR~hjy0Bvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_field_seek.stubR~hjlJvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_character_set_name.stubFR~hjF6ě>vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_report.stubR~hjpͦIvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_begin_transaction.stubiR~hjiwФCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_next_result.stub=R~hj=OlCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_assoc.stubhR~hjh[kBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_fetch.stubFR~hjFz?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_ssl_set.stubYR~hjYOYBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_num_fields.stubCR~hjCs>Bvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_close.stubR~hjxFvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_data_seek.stubVR~hjVVqTBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_use_result.stubLR~hjL˞ Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_sql_exception.stubR~hj.@vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_sqlstate.stub<R~hj<A4Avendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_data_seek.stubPR~hjP}KBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_error_list.stubTR~hjT6GQEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_attr_set.stubdR~hjd[Bvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_real_query.stubKR~hjKl=vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_error.stub9R~hj9H`Hvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_reap_async_query.stubqR~hjqK Jvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_affected_rows.stubSR~hjSM=vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_close.stubR~hjޤHvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_bind_result.stub\R~hj\f[Avendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_row.stubfR~hjfDg?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_prepare.stub]R~hj]ڤEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_connect_errno.stub0R~hj0S>=vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_query.stub}R~hj}vBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_reset.stubER~hjEoϤCvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_charset.stubGR~hjGwޤEvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_sqlstate.stubJR~hjJ}KBvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_field_tell.stubCR~hjC`Dvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_real_connect.stubR~hjo<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_init.stub1R~hj1xfέGvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_dump_debug_info.stubAR~hjA+UGJvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_field_direct.stub`R~hj`g`?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_warning.stubR~hj@`<Lvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_result_metadata.stub_R~hj_퀞٤Jvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_server_version.stubCR~hjC"Gvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_server_info.stubCR~hjC6Avendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_all.stubR~hjJD{EKvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_send_long_data.stublR~hjlr?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_refresh.stubER~hjE٤Hvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_field_count.stubJR~hjJK?vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_options.stubnR~hjn>vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_commit.stub^R~hj^JAvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_insert_id.stubAR~hjAƙs<vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stat.stub>R~hj>ۑDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_store_result.stub]R~hj]qHvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_next_result.stubKR~hjK'4Cvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_array.stubR~hj؇Avendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_init.stubIR~hjI-1*Ivendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_store_result.stubLR~hjL繽iGvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_bind_param.stubjR~hjjuX̬Evendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_execute_query.stubR~hj(iۤ=vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_debug.stubR~hj+Hvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_stmt_param_count.stubJR~hjJ܌F@vendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_num_rows.stubHR~hjHPDvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_fetch_fields.stub^R~hj^Gvendor/phpstan/php-8-stubs/stubs/ext/mysqli/mysqli_get_client_info.stubKR~hjK2ܤ?vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_get_queue.stub^R~hj^+u.=vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_receive.stub"R~hj"s-Bvendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/SysvMessageQueue.stubJR~hjJ[6M?vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_set_queue.stubOR~hjOޕ>@vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_stat_queue.stubJR~hjJ~Bvendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_queue_exists.stub5R~hj5zlBvendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_remove_queue.stubER~hjE:vendor/phpstan/php-8-stubs/stubs/ext/sysvmsg/msg_send.stubR~hj,Svendor/phpstan/php-8-stubs/stubs/ext/readline/readline_callback_handler_remove.stub=R~hj=yOvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_completion_function.stubKR~hjKqRIvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_clear_history.stub3R~hj3$Gvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_on_new_line.stubIR~hjItȸ;vendor/phpstan/php-8-stubs/stubs/ext/readline/readline.stubeR~hje%ؤ@vendor/phpstan/php-8-stubs/stubs/ext/readline/readline_info.stubR~hjGTvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_callback_handler_install.stubR~hj7#Nvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_callback_read_char.stub8R~hj8~qeHvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_read_history.stubQR~hjQ$7ФGvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_add_history.stub?R~hj?fՁIvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_write_history.stubKR~hjK@bRHvendor/phpstan/php-8-stubs/stubs/ext/readline/readline_list_history.stubcR~hjc%Evendor/phpstan/php-8-stubs/stubs/ext/readline/readline_redisplay.stub/R~hj/''8vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzcompress.stubdR~hjd?Qmu5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzwrite.stubR~hj1]5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzerror.stubR~hj5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzflush.stubfR~hjf6vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzerrstr.stubR~hjWǤ:vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzdecompress.stub`R~hj`V4vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzread.stub]R~hj] ѤC4vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzopen.stubR~hjDӤ5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzclose.stubfR~hjf\m5vendor/phpstan/php-8-stubs/stubs/ext/bz2/bzerrno.stubR~hj-+;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_alnum.stubUR~hjU=4c7;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_space.stub3R~hj36 <vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_xdigit.stub4R~hj4u;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_alpha.stub3R~hj3;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_lower.stub3R~hj3̤;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_cntrl.stub3R~hj3Ҥ;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_punct.stub3R~hj3!^;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_print.stub3R~hj3Ë&;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_digit.stub3R~hj3簤;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_upper.stub3R~hj3mM;vendor/phpstan/php-8-stubs/stubs/ext/ctype/ctype_graph.stub3R~hj3_r<vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_read.stubR~hj/Ivendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_compressionmethod.stubR~hj|䆤<vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_name.stubrR~hjrESFvendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_compressedsize.stubyR~hjyN7vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_close.stubYR~hjYb$6vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_open.stubR~hjC>6vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_read.stublR~hjlJ@vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_filesize.stubsR~hjs yr8vendor/phpstan/php-8-stubs/stubs/ext/zip/ZipArchive.stubR~hj<vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_open.stubR~hjSy=vendor/phpstan/php-8-stubs/stubs/ext/zip/zip_entry_close.stubkR~hjkj5=vendor/phpstan/php-8-stubs/stubs/ext/pdo_pgsql/Pdo/Pgsql.stub[R~hj[}3$Avendor/phpstan/php-8-stubs/stubs/ext/pdo_pgsql/PDO_PGSql_Ext.stubgR~hjg4vendor/phpstan/php-8-stubs/stubs/ext/pdo/PDORow.stubR~hjӪ!2:vendor/phpstan/php-8-stubs/stubs/ext/pdo/PDOException.stubZR~hjZ4:vendor/phpstan/php-8-stubs/stubs/ext/pdo/PDOStatement.stubK R~hjK xҤ9vendor/phpstan/php-8-stubs/stubs/ext/pdo/pdo_drivers.stub@R~hj@C1vendor/phpstan/php-8-stubs/stubs/ext/pdo/PDO.stubbZR~hjbZ-0Cvendor/phpstan/php-8-stubs/stubs/ext/pdo_sqlite/PDO_SQLite_Ext.stubR~hjW?vendor/phpstan/php-8-stubs/stubs/ext/pdo_sqlite/Pdo/Sqlite.stubmR~hjm =vendor/phpstan/php-8-stubs/stubs/ext/pdo_mysql/Pdo/Mysql.stubR~hjLvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_dict_exists.stubZR~hjZG;פFvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_suggest.stubuR~hju4Kvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_list_dicts.stubdR~hjdlSԤCvendor/phpstan/php-8-stubs/stubs/ext/enchant/EnchantDictionary.stub)R~hj)u.=^Gvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_describe.stubhR~hjhj}Nvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_get_dict_path.stubuR~hjux kEvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_init.stub@R~hj@:Pvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_store_replacement.stub~R~hj~EJvUJvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_get_error.stubSR~hjS;ӤMvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_add_to_session.stubdR~hjdYNvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_set_dict_path.stub{R~hj{OQvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_request_pwl_dict.stubxR~hjx{*N7Mvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_set_ordering.stubmR~hjmGvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_is_added.stub^R~hj^8<Dvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_check.stub[R~hj[u?vendor/phpstan/php-8-stubs/stubs/ext/enchant/EnchantBroker.stubGR~hjG!Lvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_is_in_session.stubR~hjTIvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_describe.stubbR~hjbJvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_free_dict.stubfR~hjf Jvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_quick_check.stubR~hjrAEvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_free.stubYR~hjY}Bvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_add.stubYR~hjY'W\Hvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_get_error.stubYR~hjYiJNvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_dict_add_to_personal.stubR~hjʹMvendor/phpstan/php-8-stubs/stubs/ext/enchant/enchant_broker_request_dict.stuboR~hjo$_ Bvendor/phpstan/php-8-stubs/stubs/ext/json/json_last_error_msg.stub2R~hj2 :vendor/phpstan/php-8-stubs/stubs/ext/json/json_decode.stubrR~hjrh)<vendor/phpstan/php-8-stubs/stubs/ext/json/json_validate.stubiR~hji>vendor/phpstan/php-8-stubs/stubs/ext/json/json_last_error.stub+R~hj+ߏ,Ӥ:vendor/phpstan/php-8-stubs/stubs/ext/json/json_encode.stubR~hjx褤?vendor/phpstan/php-8-stubs/stubs/ext/json/JsonSerializable.stubR~hjaH<vendor/phpstan/php-8-stubs/stubs/ext/json/JsonException.stub2R~hj2P'8vendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo.stub>R~hj> >vendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_close.stubR~hjޠ8Dvendor/phpstan/php-8-stubs/stubs/ext/fileinfo/mime_content_type.stubkR~hjk}.=vendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_open.stubR~hj<*?vendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_buffer.stubR~hj6 rHBvendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_set_flags.stub R~hj +6%=vendor/phpstan/php-8-stubs/stubs/ext/fileinfo/finfo_file.stubR~hjvz@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_int.stub8R~hj8(?^Hvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_safearray_proxy.stubCR~hjCj@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_imp.stubER~hjE26W;vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/dotnet.stubR~hj`*?vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_or.stubDR~hjDS@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_add.stubER~hjE'Z5@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_fix.stub8R~hj8FNvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_date_to_timestamp.stubGR~hjG뾤@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_xor.stubER~hjE؏+@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_eqv.stubER~hjE=@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_mul.stubER~hjE5[Pvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_date_from_timestamp.stubJR~hjJz@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_neg.stub8R~hj8ox@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_not.stub8R~hj8F@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_cat.stubER~hjEjCvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_event_sink.stub{R~hj{B0ԅ@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_sub.stubER~hjEAg3Avendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_cast.stubIR~hjI*Avendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_idiv.stubFR~hjFh@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_div.stubER~hjE@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_and.stubER~hjE{wq8vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com.stubR~hjKϯ@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_cmp.stubxR~hjx?@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_mod.stubER~hjEYEvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/COMPersistHelper.stubR~hj찤Dvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_create_guid.stub4R~hj4\B#<vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant.stubR~hj4b@pEvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_set_type.stubIR~hjIkjoJvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_get_active_object.stub\R~hj\)ˤEvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_load_typelib.stub[R~hj[g@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_pow.stubER~hjEWgBvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_round.stubJR~hjJ.Evendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_message_pump.stubJR~hjJ@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_abs.stub8R~hj8<դ@vendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_set.stubiR~hji Gvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_print_typeinfo.stubR~hj?oEvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/variant_get_type.stub=R~hj=NDBvendor/phpstan/php-8-stubs/stubs/ext/com_dotnet/com_exception.stub?R~hj?PfLvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_character_data_handler.stubR~hjb7vendor/phpstan/php-8-stubs/stubs/ext/xml/XMLParser.stub!R~hj!; A?vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_create.stubnR~hjnkPCvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_get_option.stubR~hj=tKvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_get_current_column_number.stubKR~hjKVJIvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_get_current_line_number.stubIR~hjI< Rvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_unparsed_entity_decl_handler.stubR~hj||ߤBvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_create_ns.stubhR~hjh>vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_error_string.stub?R~hj?wKTvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_processing_instruction_handler.stubR~hj{NQCvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_set_option.stubR~hjI\xPvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_end_namespace_decl_handler.stubR~hjՇ-{Hvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_get_current_byte_index.stubHR~hjHqF@vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_get_error_code.stub@R~hj@m:Kvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_notation_decl_handler.stubR~hj7vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parse.stub]R~hj] NCvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parse_into_struct.stubeR~hjeG<vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_object.stubR~hjjEvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_element_handler.stub R~hj ;a=vendor/phpstan/php-8-stubs/stubs/ext/xml/xml_parser_free.stub>R~hj>X9ޤQvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_external_entity_ref_handler.stubR~hjqEvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_default_handler.stub{R~hj{Rvendor/phpstan/php-8-stubs/stubs/ext/xml/xml_set_start_namespace_decl_handler.stubR~hj "1vendor/phpstan/php-8-stubs/stubs/ext/ffi/FFI.stub R~hj Cg7vendor/phpstan/php-8-stubs/stubs/ext/ffi/FFI/CType.stubF+R~hjF+xAvendor/phpstan/php-8-stubs/stubs/ext/ffi/FFI/ParserException.stubNR~hjN2q 0;vendor/phpstan/php-8-stubs/stubs/ext/ffi/FFI/Exception.stub:R~hj:ڧ7vendor/phpstan/php-8-stubs/stubs/ext/ffi/FFI/CData.stub-R~hj-9vendor/phpstan/php-8-stubs/stubs/ext/zlib/readgzfile.stubWR~hjW1<38vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzdeflate.stubnR~hjn{eq:vendor/phpstan/php-8-stubs/stubs/ext/zlib/zlib_encode.stub\R~hj\dI5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzseek.stubR~hjF;vendor/phpstan/php-8-stubs/stubs/ext/zlib/ob_gzhandler.stubIR~hjI F08vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzinflate.stubOR~hjO6ޤ6vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzclose.stub_R~hj_c6vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzwrite.stubR~hjD4vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzeof.stub[R~hj[9:l^7vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzdecode.stubNR~hjN]xAvendor/phpstan/php-8-stubs/stubs/ext/zlib/inflate_get_status.stubFR~hjFMsO5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzgets.stubzR~hjzEl5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzfile.stublR~hjlۥ;vendor/phpstan/php-8-stubs/stubs/ext/zlib/deflate_init.stub\R~hj\<5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzgetc.stubeR~hjeZ5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzputs.stubR~hjd:vendor/phpstan/php-8-stubs/stubs/ext/zlib/zlib_decode.stubQR~hjQB5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzread.stubrR~hjr:vendor/phpstan/php-8-stubs/stubs/ext/zlib/inflate_add.stubyR~hjyu9vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzcompress.stubsR~hjseֆ=vendor/phpstan/php-8-stubs/stubs/ext/zlib/InflateContext.stubHR~hjHI:vendor/phpstan/php-8-stubs/stubs/ext/zlib/deflate_add.stubyR~hjy9Cvendor/phpstan/php-8-stubs/stubs/ext/zlib/zlib_get_coding_type.stub9R~hj9s);vendor/phpstan/php-8-stubs/stubs/ext/zlib/inflate_init.stub\R~hj\-Ǥ7vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzencode.stubnR~hjnD9~=vendor/phpstan/php-8-stubs/stubs/ext/zlib/DeflateContext.stub&R~hj&Ǭ5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gztell.stubbR~hjb]g5vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzopen.stubtR~hjt6Cvendor/phpstan/php-8-stubs/stubs/ext/zlib/inflate_get_read_len.stubHR~hjH8;vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzuncompress.stubRR~hjR;nx9vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzpassthru.stubdR~hjdjҤ7vendor/phpstan/php-8-stubs/stubs/ext/zlib/gzrewind.stub`R~hj` ~d]Evendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_clear_session.stubR~hjoΤFvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_add_to_session.stubR~hj(Bvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_new_config.stubR~hjCvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_mode.stubR~hjA2aEvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_save_wordlist.stubR~hj[WOEvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_ignore.stubR~hj`S Gvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_add_to_personal.stubR~hjz&yGvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_personal.stubR~hj0 ۤEvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_create.stub,R~hj,(Ivendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_store_replacement.stubR~hjGvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_data_dir.stubR~hjj<_?vendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_suggest.stubR~hj|Bvendor/phpstan/php-8-stubs/stubs/ext/pspell/PSpell/Dictionary.stubyR~hjyS>vendor/phpstan/php-8-stubs/stubs/ext/pspell/PSpell/Config.stubuR~hjuFF=vendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_check.stubR~hj8ϤGvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_dict_dir.stubR~hjtXDvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_new_personal.stub|R~hj|p|Jvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_runtogether.stubR~hjwCvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_repl.stubR~hj S,;vendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_new.stubhR~hjh?Hvendor/phpstan/php-8-stubs/stubs/ext/pspell/pspell_config_save_repl.stubR~hjFJvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_is_script_cached.stubER~hjEd%?vendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_reset.stubLR~hjLuKvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_get_configuration.stubTR~hjTzFvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_compile_file.stubAR~hjA:ÑҤDvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_invalidate.stubTR~hjT1Gvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_jit_blacklist.stubTR~hjTֹDvendor/phpstan/php-8-stubs/stubs/ext/opcache/opcache_get_status.stubiR~hjiZH"<vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_strlen.stubxR~hjxBvendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_get_encoding.stubhR~hjhW=vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_strrpos.stubiR~hjia2<vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_substr.stub{R~hj{'6Avendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_mime_encode.stubrR~hjrx Avendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_mime_decode.stubmR~hjm:<vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_strpos.stubyR~hjy2h*Bvendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_set_encoding.stubMR~hjM۱Ivendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv_mime_decode_headers.stubR~hjz\믤5vendor/phpstan/php-8-stubs/stubs/ext/iconv/iconv.stubdR~hjdzޱCvendor/phpstan/php-8-stubs/stubs/ext/pdo_firebird/Pdo/Firebird.stubR~hjA_g5vendor/phpstan/php-8-stubs/stubs/ext/shmop/Shmop.stub?R~hj?f+<vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_delete.stub6R~hj6[;vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_write.stubOR~hjOME&;vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_close.stubHR~hjH1e%:vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_read.stubNR~hjNRΤ:vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_size.stub3R~hj3:vendor/phpstan/php-8-stubs/stubs/ext/shmop/shmop_open.stubbR~hjb:=vendor/phpstan/php-8-stubs/stubs/ext/pdo_dblib/Pdo/Dblib.stubQR~hjQM-u>vendor/phpstan/php-8-stubs/stubs/ext/calendar/jddayofweek.stubXR~hjXb=vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtofrench.stub8R~hj8dV=vendor/phpstan/php-8-stubs/stubs/ext/calendar/juliantojd.stubER~hjE@vendor/phpstan/php-8-stubs/stubs/ext/calendar/gregoriantojd.stubHR~hjH%g^<vendor/phpstan/php-8-stubs/stubs/ext/calendar/cal_to_jd.stubSR~hjSoY@vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtogregorian.stub;R~hj; >vendor/phpstan/php-8-stubs/stubs/ext/calendar/easter_date.stubXR~hjXM=vendor/phpstan/php-8-stubs/stubs/ext/calendar/frenchtojd.stubER~hjE;vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtounix.stub3R~hj3)&=vendor/phpstan/php-8-stubs/stubs/ext/calendar/jewishtojd.stubER~hjE>vendor/phpstan/php-8-stubs/stubs/ext/calendar/easter_days.stubXR~hjXTX2=vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtojulian.stub8R~hj8ݝ>vendor/phpstan/php-8-stubs/stubs/ext/calendar/cal_from_jd.stub^R~hj^xա=vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdtojewish.stub^R~hj^zA>vendor/phpstan/php-8-stubs/stubs/ext/calendar/jdmonthname.stubDR~hjDt;vendor/phpstan/php-8-stubs/stubs/ext/calendar/cal_info.stubOR~hjOVfDvendor/phpstan/php-8-stubs/stubs/ext/calendar/cal_days_in_month.stubsR~hjs V;vendor/phpstan/php-8-stubs/stubs/ext/calendar/unixtojd.stub@R~hj@bv<vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_detach.stub=R~hj=:Pā=vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_has_var.stubHR~hjH9<vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_attach.stubnR~hjn I!=vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_get_var.stubIR~hjIu=vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_put_var.stubVR~hjV¾@vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_remove_var.stubKR~hjK)q<vendor/phpstan/php-8-stubs/stubs/ext/sysvshm/shm_remove.stub=R~hj=BEBvendor/phpstan/php-8-stubs/stubs/ext/sysvshm/SysvSharedMemory.stubJR~hjJI_+7vendor/phpstan/php-8-stubs/stubs/ext/phar/PharData.stub.(R~hj.(2T/<vendor/phpstan/php-8-stubs/stubs/ext/phar/PharException.stubTR~hjTvO3vendor/phpstan/php-8-stubs/stubs/ext/phar/Phar.stube+R~hje+Vפ;vendor/phpstan/php-8-stubs/stubs/ext/phar/PharFileInfo.stubR~hj!yi7vendor/phpstan/php-8-stubs/stubs/ext/soap/Soap/Sdl.stubpR~hjpWͤ7vendor/phpstan/php-8-stubs/stubs/ext/soap/Soap/Url.stubpR~hjpR{Evendor/phpstan/php-8-stubs/stubs/ext/soap/use_soap_error_handler.stubhR~hjhīd9vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapServer.stub&R~hj&}Zn8vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapFault.stubR~hj19vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapHeader.stubR~hjV9vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapClient.stubBR~hjBB<6vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapVar.stubR~hjT|l<vendor/phpstan/php-8-stubs/stubs/ext/soap/is_soap_fault.stub7R~hj7ת*8vendor/phpstan/php-8-stubs/stubs/ext/soap/SoapParam.stubbR~hjbd>Evendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_error_code.stubOR~hjO4.Lvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator/Transliterator.stubR~hjDvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_has_same_rules.stubfR~hjf <vendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_parse.stubR~hj7@vendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_region.stubHR~hjHW_̤Hvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_set_text_attribute.stubpR~hjpaFvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_display_name.stubR~hjhWDvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_filter_matches.stubrR~hjr?vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_stripos.stubcR~hjc Evendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_dst_savings.stubIR~hjICತOvendor/phpstan/php-8-stubs/stubs/ext/intl/intlgregcal_set_gregorian_change.stuboR~hjo<}@vendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_set_symbol.stubeR~hje I٤@vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_script.stub?R~hj?Fʿ>vendor/phpstan/php-8-stubs/stubs/ext/intl/intl_is_failure.stub:R~hj:{yHvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_error_message.stubUR~hjU<vendor/phpstan/php-8-stubs/stubs/ext/intl/locale/Locale.stuboR~hjoFvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_error_code.stubJR~hjJ.ȤGvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_equivalent_id.stub\R~hj\5=vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_equals.stubXR~hjXeWBvendor/phpstan/php-8-stubs/stubs/ext/intl/common/IntlIterator.stubiR~hjiXAHvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_create_enumeration.stubR~hj5Fvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_create_time_zone.stubPR~hjP{ФDvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_raw_offset.stubHR~hjHDBvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_set_lenient.stub\R~hj\n*wAvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_set_default.stubR~hj=dKvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_sort_with_sort_keys.stubYR~hjY$r_Bvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_maximum.stubXR~hjX{Evendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_error_code.stubOR~hjO,%室=vendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_gmt.stub4R~hj4Hvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_script.stubkR~hjkdkAvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_is_weekend.stub`R~hj`c)Dvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_error_code.stubNR~hjNU;vendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_parse.stubR~hjҤ<vendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_format.stub]R~hj]X/_?vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_stristr.stubqR~hjqԺU?vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_time.stubVR~hjVsDvendor/phpstan/php-8-stubs/stubs/ext/intl/timezone/IntlTimeZone.stubR~hjWHvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_least_maximum.stub^R~hj^RvLvendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle_get_error_code.stubPR~hjP9eHvendor/phpstan/php-8-stubs/stubs/ext/intl/formatter/NumberFormatter.stub\R~hj\Ҥ@vendor/phpstan/php-8-stubs/stubs/ext/intl/collator/Collator.stubF R~hjF CT{Dvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_sort_key.stub[R~hj[KHvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_error_message.stubUR~hjUDo<vendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_create.stubgR~hjgbAvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_set_pattern.stub[R~hj[$դ@vendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_get_symbol.stub^R~hj^ACvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_set_calendar.stubpR~hjpW)`Ivendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_actual_minimum.stub_R~hj_%B@<vendor/phpstan/php-8-stubs/stubs/ext/intl/collator_sort.stuboR~hjoǍEvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_attribute.stubYR~hjY'C $Kvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_id_for_windows_id.stubkR~hjkR-Ivendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_actual_maximum.stub_R~hj_'zyLvendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle/ResourceBundle.stubhR~hjh+Gvendor/phpstan/php-8-stubs/stubs/ext/intl/intlgregcal_is_leap_year.stub`R~hj`Kvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_greatest_minimum.stubaR~hja1zBvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_locale.stubTR~hjT/<Bvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_canonicalize.stubAR~hjA:Jvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_count_equivalent_ids.stub^R~hj^$'Avendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_default.stub>R~hj>FPJvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_calendar_object.stubiR~hjiV*+}Dvendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle_create.stubR~hjkOvendor/phpstan/php-8-stubs/stubs/ext/intl/intlgregcal_get_gregorian_change.stub^R~hj^dƤGvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_is_equivalent_to.stubbR~hjbqrFvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_list_ids.stubRR~hjR."9Bvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_set_pattern.stub^R~hj^C-Dvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_get_error_code.stubLR~hjL$Fvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_all_variants.stubDR~hjDlAvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_locale.stubYR~hjY Cvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_timezone.stub]R~hj]^=Uvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_minimal_days_in_first_week.stubR~hjM=<vendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_create.stubzR~hjz5ڈtOvendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle_get_error_message.stubVR~hjV6Avendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_str_split.stubfR~hjf-sq<vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_lookup.stubR~hjrqCvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_set_attribute.stubnR~hjn XR;vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_parse.stub9R~hj9p<vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_clear.stubR~hjVʤ@vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strripos.stubdR~hjd='Bvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_pattern.stubUR~hjUSX<vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_after.stubWR~hjWUAvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_is_lenient.stubLR~hjLGԤSvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_skipped_wall_time_option.stubWR~hjWyDvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_create.stubR~hjw%;vendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_parse.stubsR~hjsخ0Dvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_create_default.stub;R~hj;9B:vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set.stubR~hj&ʵCJvendor/phpstan/php-8-stubs/stubs/ext/intl/intlgregcal_create_instance.stubR~hjioM>vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strstr.stubpR~hjp(5Evendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle_locales.stub_R~hj_O_}=vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_is_set.stubNR~hjNi=Gvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_field_difference.stuboR~hjo?Cvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_get_attribute.stubgR~hjg{Gvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_to_date_time_zone.stub[R~hj[}KIvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_variant.stublR~hjl2T[Dvendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_format_message.stubhR~hjh>vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_substr.stubdR~hjdFvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_create_instance.stubR~hj<|?vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_type.stubFR~hjF|Nvendor/phpstan/php-8-stubs/stubs/ext/intl/breakiterator/IntlBreakIterator.stubLR~hjLp WqNvendor/phpstan/php-8-stubs/stubs/ext/intl/breakiterator/IntlPartsIterator.stub@R~hj@m6Wvendor/phpstan/php-8-stubs/stubs/ext/intl/breakiterator/IntlCodePointBreakIterator.stubR~hj?Wvendor/phpstan/php-8-stubs/stubs/ext/intl/breakiterator/IntlRuleBasedBreakIterator.stubR~hjf,Ivendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_from_date_time_zone.stubXR~hjXtEGvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_get_error_message.stubRR~hjRHvendor/phpstan/php-8-stubs/stubs/ext/intl/spoofchecker/Spoofchecker.stubR~hjda=vendor/phpstan/php-8-stubs/stubs/ext/intl/collator_asort.stubpR~hjp^RUvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_minimal_days_in_first_week.stub_R~hj_F@Mvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_weekend_transition.stubgR~hjgwr=vendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_format.stubR~hj4Cvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_timetype.stubSR~hjS`PUvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_create_time_zone_id_enumeration.stubR~hj:Kvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_day_of_week_type.stubeR~hje2Tvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_keyword_values_for_locale.stubR~hjOvendor/phpstan/php-8-stubs/stubs/ext/intl/normalizer_get_raw_decomposition.stubR~hj½Evendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_from_date_time.stuboR~hjoJKCvendor/phpstan/php-8-stubs/stubs/ext/intl/normalizer_normalize.stubxR~hjx'@vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_region.stub?R~hj?Dvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_time_zone.stubXR~hjXCLvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_first_day_of_week.stubR~hjtGvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_error_message.stubTR~hjTySvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_skipped_wall_time_option.stubR~hjJ?vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_time.stubKR~hjK]Evendor/phpstan/php-8-stubs/stubs/ext/intl/intl_get_error_message.stub5R~hj5C;$Hvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_region.stubkR~hjk+_Lvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_available_locales.stubRR~hjR*e?@vendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_offset.stubR~hjqs(ɤAvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_iana_id.stub|R~hj|`Lvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_get_error_code.stub^R~hj^*`;vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_roll.stubrR~hjrFeJvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_primary_language.stubIR~hjI@~Cvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_calendar.stubSR~hjS{эFvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_name.stubiR~hji8դ>vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strpos.stubbR~hjb9hⓤJvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_display_language.stubmR~hjm׫>vendor/phpstan/php-8-stubs/stubs/ext/intl/intl_error_name.stub<R~hj<vz1Bvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_lenient.stubR~hj\Cvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_set_timezone.stubJR~hjJ݆<vendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_format.stubR~hjCZCvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_datetype.stubSR~hjSyAvendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle_get.stub2R~hj2O>=vendor/phpstan/php-8-stubs/stubs/ext/intl/locale_compose.stubAR~hjA~`Ф<vendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_id.stubIR~hjIATvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_repeated_wall_time_option.stubXR~hjX=vendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_create.stubcR~hjc/u@vendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_localtime.stubR~hjeƤ@vendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_get_locale.stubLR~hjL+ Dvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_format_object.stubR~hj2wBvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_minimum.stubXR~hjXB(Ovendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_get_error_message.stubdR~hjd"KAvendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_get_pattern.stubSR~hjSuFvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_accept_from_http.stubJR~hjJg׽Gvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_use_daylight_time.stubLR~hjLҤDvendor/phpstan/php-8-stubs/stubs/ext/intl/calendar/IntlCalendar.stubFR~hjF8+Mvendor/phpstan/php-8-stubs/stubs/ext/intl/calendar/IntlGregorianCalendar.stubR~hj`TAvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_locale.stubtR~hjt:LԤAvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_unknown.stub8R~hj8Cvendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_parse_message.stubR~hjADvendor/phpstan/php-8-stubs/stubs/ext/intl/normalizer/Normalizer.stub R~hj hDvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_windows_id.stubnR~hjn{$ŋRvendor/phpstan/php-8-stubs/stubs/ext/intl/dateformat/IntlDatePatternGenerator.stubNR~hjNޒ!Kvendor/phpstan/php-8-stubs/stubs/ext/intl/dateformat/IntlDateFormatter.stubR~hj~a4Ivendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_tz_data_version.stub?R~hj?KU^>@vendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_get_locale.stubqR~hjqJ=vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_before.stubXR~hjX3TBvendor/phpstan/php-8-stubs/stubs/ext/intl/intl_get_error_code.stub<R~hj<Q/>vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strlen.stubSR~hjS 4;vendor/phpstan/php-8-stubs/stubs/ext/intl/idn_to_ascii.stubR~hj3HTvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_repeated_wall_time_option.stubR~hj^`lDvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_parse_currency.stubR~hjˤCvendor/phpstan/php-8-stubs/stubs/ext/intl/resourcebundle_count.stubGR~hjGIvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_error_message.stubPR~hjP]#Cvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_to_date_time.stubSR~hjS!=rBvendor/phpstan/php-8-stubs/stubs/ext/intl/locale_get_keywords.stubaR~hjaϹn>vendor/phpstan/php-8-stubs/stubs/ext/intl/collator_create.stubOR~hjO `>vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_now.stub-R~hj-Z2Ivendor/phpstan/php-8-stubs/stubs/ext/intl/msgformat/MessageFormatter.stubR~hjL?vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_strrpos.stubcR~hjcDҤOvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_create_from_rules.stubR~hjw4?vendor/phpstan/php-8-stubs/stubs/ext/intl/collator_compare.stubeR~hje<=RDvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_set_strength.stubR~hjІp=vendor/phpstan/php-8-stubs/stubs/ext/intl/uchar/IntlChar.stubJR~hjJD Kvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_transliterate.stubR~hj!nr?vendor/phpstan/php-8-stubs/stubs/ext/intl/grapheme_extract.stubR~hj恤Gvendor/phpstan/php-8-stubs/stubs/ext/intl/normalizer_is_normalized.stubcR~hjc|Fvendor/phpstan/php-8-stubs/stubs/ext/intl/datefmt_get_timezone_id.stubYR~hjYk:vendor/phpstan/php-8-stubs/stubs/ext/intl/idn_to_utf8.stubR~hjJuGvendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_get_error_message.stubSR~hjSVYHvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_get_text_attribute.stubiR~hjiFvendor/phpstan/php-8-stubs/stubs/ext/intl/intltz_get_canonical_id.stubR~hj7Avendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_set_pattern.stub\R~hj\Avendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_is_lenient.stubFR~hjFsFLqAvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_get_pattern.stubRR~hjRKEvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_set_attribute.stub`R~hj`:vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get.stubPR~hjP@D :vendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_add.stubWR~hjWy;zGvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_in_daylight_time.stubLR~hjLLvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_get_first_day_of_week.stubVR~hjVPC̤Cvendor/phpstan/php-8-stubs/stubs/ext/intl/converter/UConverter.stub(1R~hj(1Lvendor/phpstan/php-8-stubs/stubs/ext/intl/transliterator_create_inverse.stubeR~hje~1KDvendor/phpstan/php-8-stubs/stubs/ext/intl/collator_get_strength.stubBR~hjB4[Dvendor/phpstan/php-8-stubs/stubs/ext/intl/intlcal_set_time_zone.stubR~hj Dvendor/phpstan/php-8-stubs/stubs/ext/intl/msgfmt_get_error_code.stubMR~hjMwυ<vendor/phpstan/php-8-stubs/stubs/ext/intl/IntlException.stubTR~hjTcEvendor/phpstan/php-8-stubs/stubs/ext/intl/numfmt_format_currency.stubwR~hjwMd<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getuid.stub(R~hj(0<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_isatty.stubeR~hjeN=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpgid.stubRR~hjR 4eDvendor/phpstan/php-8-stubs/stubs/ext/posix/posix_get_last_error.stub7R~hj7C7=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setpgid.stubWR~hjW%N>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getlogin.stubOR~hjO^dH@vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_initgroups.stubcR~hjcYW:vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_kill.stubeR~hjen1<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setuid.stub5R~hj5><vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_mkfifo.stub^R~hj^y<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getsid.stubWR~hjWxx<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_access.stubPR~hjPi?vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setrlimit.stubxR~hjxhp =vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setegid.stubKR~hjKrK=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_eaccess.stuboR~hjoTk'>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getgrgid.stubVR~hjV)?vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getgroups.stubgR~hjgfK=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_seteuid.stubJR~hjJwpp=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_ctermid.stubFR~hjFQoM;vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_errno.stubJR~hjJǤ?vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getrlimit.stubR~hj+=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getegid.stub)R~hj)&D<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setsid.stub;R~hj;:|>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getgrnam.stubUR~hjU"y>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_strerror.stub<R~hj<.=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_geteuid.stub)R~hj)Pޘ%<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_setgid.stub6R~hj6ht;vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_times.stubFR~hjF_v=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpgrp.stub0R~hj0x>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpwuid.stubUR~hjU;ߖ=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getppid.stub)R~hj)֤=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_ttyname.stubuR~hjuQ<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpid.stub(R~hj(!=vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_sysconf.stubMR~hjMX;vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_mknod.stub}R~hj}4?vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_fpathconf.stubR~hj<&<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getcwd.stub1R~hj1I[;vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_uname.stubMR~hjM"hr<vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getgid.stub/R~hj/fIE>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_pathconf.stubmR~hjmLb+>vendor/phpstan/php-8-stubs/stubs/ext/posix/posix_getpwnam.stubYR~hjYk8P>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_result_all.stubR~hjlz>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_name.stubR~hjDvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_columnprivileges.stub_R~hj_ Q7=vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_num.stubR~hjp:vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_result.stubR~hjn|<vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_pconnect.stubhR~hjhSj;vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_connect.stubfR~hjf;vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_prepare.stubR~hj㈤<vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_rollback.stubR~hjN?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_primarykeys.stub5R~hj5!a<vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_num_rows.stubR~hjPȤ=vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_close_all.stubMR~hjM]j&9vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_error.stubR~hj{ ?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_next_result.stub R~hj mKKvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_connection_string_quote.stubWR~hjWA٤?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_longreadlen.stubR~hjCvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_precision.stubR~hjPؤBvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_specialcolumns.stubR~hjg`g5?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_data_source.stubR~hj.;vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_columns.stubR~hjDl=vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_len.stubR~hj^e6vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_do.stub R~hj :vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_commit.stubR~hj|OC?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_gettypeinfo.stubR~hjQ=vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_setoption.stubR~hjp1>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_fetch_into.stubKR~hjK55?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_foreignkeys.stubR~hj?>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_statistics.stubkR~hjkf[=vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_fetch_row.stubR~hj)Ovendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_connection_string_is_quoted.stubsR~hjsPipRvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_connection_string_should_quote.stub\R~hj\q?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_scale.stubR~hj bV9vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_close.stubR~hjX`N @vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_fetch_object.stubFR~hjF\hCvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_tableprivileges.stub R~hj H?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_fetch_array.stubR~hj%\:vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_cursor.stubR~hjl<vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_errormsg.stubR~hjOi};vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_execute.stubR~hj_e;vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_binmode.stubR~hj9V>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_autocommit.stubbR~hjb(I>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_procedures.stubiR~hji9G,>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_field_type.stubR~hjYi:vendor/phpstan/php-8-stubs/stubs/ext/odbc/Odbc/Result.stubmR~hjmܕ>b>vendor/phpstan/php-8-stubs/stubs/ext/odbc/Odbc/Connection.stubqR~hjqWk?vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_free_result.stubR~hjxDDvendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_procedurecolumns.stubCR~hjCѳc:vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_tables.stubR~hj>vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_num_fields.stubR~hj:}f8vendor/phpstan/php-8-stubs/stubs/ext/odbc/odbc_exec.stubR~hjJڮ?vendor/phpstan/php-8-stubs/stubs/ext/hash/mhash_keygen_s2k.stubkR~hjkڣ:vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_equals.stubQR~hjQݍ:vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_update.stubR~hjd89vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_final.stubTR~hjT+i8vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_init.stubR~hjP8=vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_hmac_file.stubtR~hjtm4vendor/phpstan/php-8-stubs/stubs/ext/hash/mhash.stubVR~hjV `8vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_hmac.stubeR~hjeZ饤:vendor/phpstan/php-8-stubs/stubs/ext/hash/mhash_count.stub'R~hj'v 3vendor/phpstan/php-8-stubs/stubs/ext/hash/hash.stub*R~hj*N:vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_pbkdf2.stub_R~hj_DѤ>vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_hmac_algos.stubZR~hjZMU8vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_hkdf.stubxR~hjx:vendor/phpstan/php-8-stubs/stubs/ext/hash/HashContext.stubR~hj Cvendor/phpstan/php-8-stubs/stubs/ext/hash/mhash_get_block_size.stubSR~hjSx?vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_update_file.stubR~hj\Bvendor/phpstan/php-8-stubs/stubs/ext/hash/mhash_get_hash_name.stubAR~hjA3n8vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_copy.stubCR~hjCjAvendor/phpstan/php-8-stubs/stubs/ext/hash/hash_update_stream.stub}R~hj}WZ9vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_algos.stubUR~hjU78vendor/phpstan/php-8-stubs/stubs/ext/hash/hash_file.stubR~hjT53vendor/phpstan/php-8-stubs/stubs/ext/gettext/_.stubER~hjEhﳀIvendor/phpstan/php-8-stubs/stubs/ext/gettext/bind_textdomain_codeset.stubCR~hjCEމ<vendor/phpstan/php-8-stubs/stubs/ext/gettext/textdomain.stubR~hjǕ:vendor/phpstan/php-8-stubs/stubs/ext/gettext/ngettext.stubhR~hjhٵ;vendor/phpstan/php-8-stubs/stubs/ext/gettext/dngettext.stubR~hjO9vendor/phpstan/php-8-stubs/stubs/ext/gettext/gettext.stub5R~hj5R9ג<vendor/phpstan/php-8-stubs/stubs/ext/gettext/dcngettext.stubR~hj:vendor/phpstan/php-8-stubs/stubs/ext/gettext/dgettext.stubFR~hjF;;vendor/phpstan/php-8-stubs/stubs/ext/gettext/dcgettext.stubVR~hjVr-T@vendor/phpstan/php-8-stubs/stubs/ext/gettext/bindtextdomain.stubR~hjh7vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcceil.stubTR~hjT>vendor/phpstan/php-8-stubs/stubs/ext/bcmath/BcMath/Number.stub6R~hj6]8vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcfloor.stubUR~hjU6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcpow.stubUR~hjUzä8vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcscale.stub5R~hj5<6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcadd.stubtR~hjt˯9vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcdivmod.stubR~hjc788vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcround.stubR~hj6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcdiv.stubRR~hjR 6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcsub.stubRR~hjRrjD6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcmul.stubRR~hjRf=7vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcsqrt.stubDR~hjD=M9vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcpowmod.stubiR~hji"?57vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bccomp.stubPR~hjPt 6vendor/phpstan/php-8-stubs/stubs/ext/bcmath/bcmod.stubRR~hjR5P?vendor/phpstan/php-8-stubs/stubs/ext/sqlite3/SQLite3Result.stub.R~hj. 9vendor/phpstan/php-8-stubs/stubs/ext/sqlite3/SQLite3.stub9R~hj9=7Bvendor/phpstan/php-8-stubs/stubs/ext/sqlite3/SQLite3Exception.stubkR~hjk*Y=vendor/phpstan/php-8-stubs/stubs/ext/sqlite3/SQLite3Stmt.stubR~hjLȤ:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_search.stubpR~hjpZ[Hդ9vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_close.stubR~hj6j?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_free_result.stubR~hjM[Cvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_set_rebind_proc.stubR~hjf:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_delete.stubR~hjpQAvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_count_entries.stubR~hj7DCvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_parse_reference.stubR~hjHΤ>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_parse_exop.stub)R~hj)a">vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_set_option.stub1R~hj1h6M>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_rename_ext.stubR~hj4le>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_explode_dn.stubfR~hjf&":vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_rename.stubR~hj;?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_add_ext.stub9R~hj9}?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_first_entry.stubR~hjS@vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_parse_result.stubR~hjXC?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_replace.stubR~hj=q㧤@vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_modify_batch.stub/R~hj/g>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_values.stubR~hjD`:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_escape.stubcR~hjcD[Gt=vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_sasl_bind.stub!R~hj!й8vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_bind.stubR~hjʸ?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_8859_to_t61.stubBR~hjB-A?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop_passwd.stubR~hj%0Bvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_next_attribute.stubR~hj75\<Dvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_count_references.stubR~hjR'Bvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_connect_wallet.stubR~hj5D>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_delete_ext.stubR~hj~w>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_option.stub1R~hj1 0;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_connect.stubR~hjŤBvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_values_len.stubmR~hjm.)ͤ9vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_error.stubR~hjlM;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_del.stub R~hj 6LBvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_next_reference.stubR~hjmy8vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_list.stublR~hjle%?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_del_ext.stub9R~hj9Cvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_replace_ext.stubAR~hjA/7vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_add.stubR~hjbS;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_mod_add.stub R~hj oQv?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_t61_to_8859.stubYR~hjY Bvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_attributes.stub;R~hj;\4yCvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_first_attribute.stubR~hj6 :vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_dn2ufn.stub:R~hj:bŤ=vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop_sync.stubLR~hjL)/ :vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_dn.stubR~hj}0?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop_whoami.stubR~hj*8vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_read.stubzR~hjz~3Cvendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_first_reference.stubR~hj3>;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_err2str.stub5R~hj5:3ސ;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_compare.stub;R~hj;|?٤;vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_add_ext.stub1R~hj1)f8vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop.stubR~hjҝT<vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_bind_ext.stub[R~hj[̖9vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_errno.stubR~hj;:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_modify.stubGR~hjGҙ8@vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_exop_refresh.stub)R~hj)?vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_get_entries.stub>R~hj> (|=vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_start_tls.stubR~hjg>vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_next_entry.stubR~hj$9:vendor/phpstan/php-8-stubs/stubs/ext/ldap/ldap_unbind.stubR~hjsɤ?vendor/phpstan/php-8-stubs/stubs/ext/ldap/LDAP/ResultEntry.stubxR~hjxoq(:vendor/phpstan/php-8-stubs/stubs/ext/ldap/LDAP/Result.stubsR~hjsA7=>vendor/phpstan/php-8-stubs/stubs/ext/ldap/LDAP/Connection.stubwR~hjw;ըѤ@vendor/phpstan/php-8-stubs/stubs/ext/spl/FilesystemIterator.stubIR~hjI$>vendor/phpstan/php-8-stubs/stubs/ext/spl/IteratorIterator.stub,R~hj,h絤>vendor/phpstan/php-8-stubs/stubs/ext/spl/SplObjectStorage.stubX R~hjX ɤ;vendor/phpstan/php-8-stubs/stubs/ext/spl/OuterIterator.stubR~hj==<vendor/phpstan/php-8-stubs/stubs/ext/spl/RangeException.stubKR~hjK7gͤ5vendor/phpstan/php-8-stubs/stubs/ext/spl/SplHeap.stubZR~hjZ4Y`=vendor/phpstan/php-8-stubs/stubs/ext/spl/CachingIterator.stub R~hj 8vendor/phpstan/php-8-stubs/stubs/ext/spl/class_uses.stubR~hjC=vendor/phpstan/php-8-stubs/stubs/ext/spl/DomainException.stubJR~hjJ|HR;vendor/phpstan/php-8-stubs/stubs/ext/spl/EmptyIterator.stubjR~hjjGځݤ9vendor/phpstan/php-8-stubs/stubs/ext/spl/SplFileInfo.stubR~hjY;vendor/phpstan/php-8-stubs/stubs/ext/spl/SplFixedArray.stubR~hj}1m9vendor/phpstan/php-8-stubs/stubs/ext/spl/SplObserver.stubR~hjMƵ;vendor/phpstan/php-8-stubs/stubs/ext/spl/ArrayIterator.stubR~hjuP>vendor/phpstan/php-8-stubs/stubs/ext/spl/MultipleIterator.stubi R~hji cX䌤;vendor/phpstan/php-8-stubs/stubs/ext/spl/SplFileObject.stubR~hjzFvendor/phpstan/php-8-stubs/stubs/ext/spl/UnexpectedValueException.stubUR~hjUh8vendor/phpstan/php-8-stubs/stubs/ext/spl/SplMaxHeap.stubR~hjC0>vendor/phpstan/php-8-stubs/stubs/ext/spl/NoRewindIterator.stubR~hjKmEvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveFilterIterator.stubR~hjAvendor/phpstan/php-8-stubs/stubs/ext/spl/SplDoublyLinkedList.stubrR~hjrCvendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_register.stubwR~hjwn{<vendor/phpstan/php-8-stubs/stubs/ext/spl/AppendIterator.stubR~hjYT>vendor/phpstan/php-8-stubs/stubs/ext/spl/SeekableIterator.stubR~hj֤=vendor/phpstan/php-8-stubs/stubs/ext/spl/LengthException.stubJR~hjJ2?<vendor/phpstan/php-8-stubs/stubs/ext/spl/iterator_apply.stubiR~hji8vendor/phpstan/php-8-stubs/stubs/ext/spl/SplMinHeap.stubR~hj];vendor/phpstan/php-8-stubs/stubs/ext/spl/class_parents.stubR~hjLwHFvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveCachingIterator.stubR~hj)>vendor/phpstan/php-8-stubs/stubs/ext/spl/InfiniteIterator.stubR~hj3VH?vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_call.stub;R~hj;{ń"Hvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveDirectoryIterator.stubR~hjt6>vendor/phpstan/php-8-stubs/stubs/ext/spl/RuntimeException.stubFR~hjFG;vendor/phpstan/php-8-stubs/stubs/ext/spl/LimitIterator.stubR~hj9vendor/phpstan/php-8-stubs/stubs/ext/spl/ArrayObject.stub]R~hj]_>vendor/phpstan/php-8-stubs/stubs/ext/spl/class_implements.stubR~hjqNl@;vendor/phpstan/php-8-stubs/stubs/ext/spl/RegexIterator.stub R~hj 1<vendor/phpstan/php-8-stubs/stubs/ext/spl/LogicException.stubcR~hjcU;9vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_classes.stub@R~hj@n;@vendor/phpstan/php-8-stubs/stubs/ext/spl/UnderflowException.stubOR~hjOABvendor/phpstan/php-8-stubs/stubs/ext/spl/OutOfBoundsException.stubQR~hjQ$":vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload.stubWR~hjW5=Evendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_unregister.stubFR~hjFWEvendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_extensions.stubUR~hjUc ?vendor/phpstan/php-8-stubs/stubs/ext/spl/OverflowException.stubNR~hjNƤDvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveRegexIterator.stubR~hj6&:vendor/phpstan/php-8-stubs/stubs/ext/spl/GlobIterator.stubcR~hjc 6vendor/phpstan/php-8-stubs/stubs/ext/spl/SplQueue.stubR~hjtVAvendor/phpstan/php-8-stubs/stubs/ext/spl/OutOfRangeException.stubNR~hjN"8<vendor/phpstan/php-8-stubs/stubs/ext/spl/iterator_count.stubR~hjS46vendor/phpstan/php-8-stubs/stubs/ext/spl/SplStack.stub7R~hj7>?vendor/phpstan/php-8-stubs/stubs/ext/spl/DirectoryIterator.stub!R~hj!iECDvendor/phpstan/php-8-stubs/stubs/ext/spl/BadMethodCallException.stub[R~hj[&Gvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveIteratorIterator.stub R~hj _Tq<vendor/phpstan/php-8-stubs/stubs/ext/spl/ParentIterator.stub7R~hj7ml=vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_object_hash.stub<R~hj<x~8vendor/phpstan/php-8-stubs/stubs/ext/spl/SplSubject.stubjR~hjjrϤ<vendor/phpstan/php-8-stubs/stubs/ext/spl/FilterIterator.stubR~hjŹ?vendor/phpstan/php-8-stubs/stubs/ext/spl/iterator_to_array.stubR~hj:6Yؤ>vendor/phpstan/php-8-stubs/stubs/ext/spl/SplPriorityQueue.stub R~hj x^;vendor/phpstan/php-8-stubs/stubs/ext/spl/spl_object_id.stub7R~hj7[ 3Dvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveArrayIterator.stubqR~hjqZ)#ޤMvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveCallbackFilterIterator.stub R~hj :ir&Fvendor/phpstan/php-8-stubs/stubs/ext/spl/InvalidArgumentException.stubSR~hjSWDvendor/phpstan/php-8-stubs/stubs/ext/spl/spl_autoload_functions.stub4R~hj4mpi?vendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveIterator.stubR~hjۤCvendor/phpstan/php-8-stubs/stubs/ext/spl/RecursiveTreeIterator.stubV R~hjV 41?Dvendor/phpstan/php-8-stubs/stubs/ext/spl/CallbackFilterIterator.stubR~hj Fvendor/phpstan/php-8-stubs/stubs/ext/spl/BadFunctionCallException.stubSR~hjS7}Ҥ?vendor/phpstan/php-8-stubs/stubs/ext/spl/SplTempFileObject.stubR~hjhv?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_setopt.stubR~hjĉ =vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_recv.stub}R~hj}>Cvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_last_error.stubKR~hjK8vendor/phpstan/php-8-stubs/stubs/ext/sockets/Socket.stub@R~hj@RoCvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_cmsg_space.stubQR~hjQ\դ@vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_connect.stub^R~hj^[`Pvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_wsaprotocol_info_import.stubSR~hjSFvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_addrinfo_bind.stubOR~hjOIDvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_create_pair.stubR~hj l?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_getopt.stubR~hjtzVFvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_create_listen.stubR~hj7@vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_recvmsg.stub`R~hj`ۓ?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_accept.stubBR~hjBjդEvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_set_nonblock.stub?R~hj?ܟ0HDvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_clear_error.stubFR~hjF_{ZQvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_wsaprotocol_info_release.stubKR~hjK攘?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_select.stubR~hjZOޤ?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_atmark.stubhR~hjh%|@vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_sendmsg.stub_R~hj_qp Cvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_set_option.stubR~hjCvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_get_option.stubxR~hjx]IIvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_addrinfo_explain.stubaR~hjaJ NHvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_addrinfo_lookup.stubR~hj\urFvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_export_stream.stubXR~hjXhPAvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_recvfrom.stubR~hj4!ˤBvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_set_block.stub<R~hj<vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_close.stub8R~hj8?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_sendto.stubR~hj6qPvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_wsaprotocol_info_export.stubtR~hjtPv=vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_send.stubcR~hjcN.[4=vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_read.stubiR~hjiqb?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_listen.stubKR~hjK%lIvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_addrinfo_connect.stubRR~hjR~HGAvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_shutdown.stubfR~hjfFvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_import_stream.stub`R~hj`R7Ť=vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_bind.stubWR~hjW%Dvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_getsockname.stubR~hjPI2>vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_write.stub`R~hj`)?vendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_create.stubXR~hjXRODvendor/phpstan/php-8-stubs/stubs/ext/sockets/socket_getpeername.stubR~hjxNvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_dtd_entity.stubR~hjtd+ʤIvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_open_memory.stub>R~hj>۽Lvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_document.stubR~hj.wӤNvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_element_ns.stubR~hj#=vendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/XMLWriter.stub:R~hj:TX Gvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_dtd.stubR~hjoGvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_dtd.stubR~hjxN`Ivendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_comment.stubDR~hjDVPvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_attribute_ns.stubR~hjVMvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_attribute.stubeR~hjeϤHvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_set_indent.stubQR~hjQ bHIvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_element.stubDR~hjD򉯤Gvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_raw.stubSR~hjSkˤPvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_attribute_ns.stub~R~hj~zIvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_cdata.stubUR~hjUEvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_dtd.stub@R~hj@U|Lvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_dtd_entity.stubGR~hjG&m%Nvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_full_end_element.stubIR~hjI `\Kvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_comment.stubWR~hjWdOvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_dtd_element.stubaR~hja&htNvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_element_ns.stub|R~hj|ǚ>Bvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_text.stubNR~hjNR=kޤKvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_element.stubmR~hjmOvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_dtd_element.stubiR~hji Gvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_cdata.stubBR~hjBW@Ovendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_set_indent_string.stub_R~hj__pMvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_dtd_element.stubHR~hjH JHzJvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_document.stubER~hjEFkuCvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_flush.stubXR~hjXnŤMvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_dtd_attlist.stubHR~hjHYJ.Ovendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_dtd_attlist.stubiR~hji"hKvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_comment.stubFR~hjFb~oMvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_attribute.stubVR~hjV+$UFvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_open_uri.stubhR~hjhsOvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_dtd_attlist.stubXR~hjXKvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_attribute.stubFR~hjF Dvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_end_pi.stub?R~hj?C0Kvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_output_memory.stub\R~hj\<-5Fvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_pi.stubQR~hjQCNvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_dtd_entity.stubfR~hjfdIvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_cdata.stubDR~hjDQ܋2Fvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_write_pi.stubbR~hjbVKvendor/phpstan/php-8-stubs/stubs/ext/xmlwriter/xmlwriter_start_element.stubTR~hjT,dDvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_verify.stub(R~hj(ۤFvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_error_string.stub9R~hj97G1Fvendor/phpstan/php-8-stubs/stubs/ext/openssl/OpenSSLAsymmetricKey.stub,R~hj,{ՔLvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_cipher_methods.stubdR~hjd$Evendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_derive.stubR~hjIGEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_decrypt.stub4R~hj4CzHvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_dh_compute_key.stubqR~hjq 6Dvendor/phpstan/php-8-stubs/stubs/ext/openssl/OpenSSLCertificate.stubLR~hjLLYZBvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_sign.stub]R~hj]Yh8Evendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_export.stubR~hjOky>vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_seal.stubR~hjKAvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_encrypt.stubR~hjlS8Evendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_export.stubR~hj[Lvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_cert_locations.stubOR~hjO?Lvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_get_public_key.stubR~hjOXϤHvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_public_decrypt.stubR~hjKvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cipher_key_length.stub_R~hj_HIvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_password_verify.stubR~hjB;(Dvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_export.stubR~hjiAvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_new.stubR~hja^AEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_spki_export.stubDR~hjD]ȤBvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_sign.stubR~hjäGvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_publickey.stubR~hjUHvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_public_encrypt.stubR~hj'>vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_open.stubR~hj1̽tGvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_encrypt.stub R~hj h+ !Cvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_free.stubaR~hja.MIԤDvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_read.stubmR~hjmzDvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_sign.stubDR~hjD%Hvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_privatekey.stubR~hjNdLvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_export_to_file.stubR~hj;!sGvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_decrypt.stubR~hj.ͤEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_verify.stubR~hjkMMvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_export_to_file.stubR~hjw#Ivendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_get_public.stubR~hj`Evendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs12_read.stubR~hjJvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_get_private.stubR~hj*oAvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_decrypt.stub~R~hj~8Cvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_free.stub[R~hj[[j@vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_digest.stubqR~hjq~ՒHvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_md_methods.stub`R~hj` IFvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs7_verify.stubR~hjդMvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_random_pseudo_bytes.stubR~hj%Kp%Gvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_password_hash.stubR~hjlz3Cvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_read.stubjR~hjjb({eIvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_private_decrypt.stubR~hj{Dvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_parse.stubR~hj%Evendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_spki_verify.stub<R~hj<NKvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_checkpurpose.stubR~hjJvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cipher_iv_length.stubMR~hjM~Jvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_fingerprint.stubR~hjABvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_new.stubZR~hjZN>vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_sign.stubR~hjȤIvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_private_encrypt.stubR~hj ZIvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_csr_get_subject.stubR~hj+sBvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_read.stubuR~hju(oBvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_free_key.stubzR~hjz\҅Gvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs12_export.stubR~hj=IWIvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_get_curve_names.stubjR~hjj⡤Ovendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkcs12_export_to_file.stubR~hj4bBvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_spki_new.stubR~hj].@vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_verify.stubR~hj8o@vendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pbkdf2.stubR~hjsPvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_check_private_key.stubR~hj LOvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_spki_export_challenge.stubNR~hjNJvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_pkey_get_details.stubmR~hjmDEvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_cms_encrypt.stubVR~hjV0ΤRvendor/phpstan/php-8-stubs/stubs/ext/openssl/OpenSSLCertificateSigningRequest.stub8R~hj8wmWMvendor/phpstan/php-8-stubs/stubs/ext/openssl/openssl_x509_export_to_file.stubR~hjC m:vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_handlers.stubXR~hjXN+b8vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_delete.stubKR~hjKmj,7vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_close.stubR~hjٻ6vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_list.stub&R~hj&8vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_exists.stubKR~hjKl;vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_key_split.stubGR~hjGP:vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_firstkey.stubR~hj<vendor/phpstan/php-8-stubs/stubs/ext/dba/Dba/Connection.stubvR~hjvh+7vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_popen.stubR~hj% ޤ6vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_sync.stubR~hj[:vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_optimize.stubR~hjR9vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_replace.stub{R~hj{B9vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_nextkey.stubR~hjT̤7vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_fetch.stubR~hjIؤ8vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_insert.stubxR~hjx9#$6vendor/phpstan/php-8-stubs/stubs/ext/dba/dba_open.stubkR~hjkf?vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_has_var.stubnR~hjnu`Cvendor/phpstan/php-8-stubs/stubs/ext/filter/filter_input_array.stubR~hjKx;vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_var.stubjR~hjjc=vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_input.stub{R~hj{`@8<vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_list.stub@R~hj@V:vendor/phpstan/php-8-stubs/stubs/ext/filter/filter_id.stub7R~hj7Avendor/phpstan/php-8-stubs/stubs/ext/filter/filter_var_array.stubR~hj+{KJvendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_replace_callback_array.stubR~hj?3:vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_filter.stubR~hj`FH>vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_last_error.stub+R~hj+9{j ;vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_replace.stubR~hj<=vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_match_all.stubR~hjx^Dvendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_replace_callback.stubR~hjόѤ9vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_quote.stubOR~hjO-Bvendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_last_error_msg.stub2R~hj2tK8vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_grep.stubZR~hjZ9vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_split.stubR~hj}X9vendor/phpstan/php-8-stubs/stubs/ext/pcre/preg_match.stubR~hj +=vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_random_bits.stub5R~hj5:vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_popcount.stub<R~hj<=56vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_sign.stub8R~hj8}6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_fact.stub9R~hj9B烤7vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_div_r.stubwR~hjwlo9?5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_lcm.stubPR~hjPZ%8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_clrbit.stub<R~hj<-ؤ9vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_sqrtrem.stubTR~hjT^8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_invert.stubYR~hjY^ 5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_add.stubPR~hjP<6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_root.stubCR~hjCF1vendor/phpstan/php-8-stubs/stubs/ext/gmp/GMP.stub<R~hj<(8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_jacobi.stubRR~hjRj5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_neg.stub8R~hj88vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_setbit.stubPR~hjP +5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_abs.stub8R~hj8ܕp8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_strval.stubMR~hjMO-5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_com.stub8R~hj8SԴ9vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_hamdist.stubSR~hjS0)";vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_nextprime.stub>R~hj>:vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_divexact.stubUR~hjUj<vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_prob_prime.stubUR~hjUY6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_sqrt.stub9R~hj92H@vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_perfect_square.stubCR~hjCeE*05vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_pow.stubGR~hjG7vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_scan1.stubFR~hjF6:vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_legendre.stubTR~hjTN6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_powm.stubnR~hjnzR9vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_rootrem.stub^R~hj^se`>vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_random_range.stubWR~hjW-?vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_perfect_power.stubBR~hjBIqΤ9vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_testbit.stubHR~hjHaOX6vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_init.stubCR~hjC'¿J8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_gcdext.stubkR~hjk~?08vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_div_qr.stubR~hj *7vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_div_q.stubwR~hjww:vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_binomial.stubCR~hjC 7vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_scan0.stubFR~hjFHV8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_export.stubR~hjt8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_intval.stub:R~hj:Z5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_gcd.stubPR~hjP64vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_or.stubOR~hjON4;vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_kronecker.stubUR~hjU#¤5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_mul.stubPR~hjPFF5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_and.stubPR~hjPcmΒ5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_cmp.stubOR~hjOЃ5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_sub.stubPR~hjPAi5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_xor.stubPR~hjPɐm5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_mod.stubPR~hjPPZ5vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_div.stubR~hj>}8vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_import.stubwR~hjw[Y=vendor/phpstan/php-8-stubs/stubs/ext/gmp/gmp_random_seed.stubAR~hjA8Dvendor/phpstan/php-8-stubs/stubs/sapi/cli/cli_get_process_title.stub5R~hj5|}p<vendor/phpstan/php-8-stubs/stubs/sapi/cli/getallheaders.stub+R~hj+BEvendor/phpstan/php-8-stubs/stubs/sapi/cli/apache_request_headers.stub4R~hj4DhH:Fvendor/phpstan/php-8-stubs/stubs/sapi/cli/apache_response_headers.stub5R~hj5Dvendor/phpstan/php-8-stubs/stubs/sapi/cli/cli_set_process_title.stub?R~hj?R~hj>jKvendor/phpstan/php-8-stubs/stubs/sapi/litespeed/apache_request_headers.stub\R~hj\8Lvendor/phpstan/php-8-stubs/stubs/sapi/litespeed/apache_response_headers.stubdR~hjdcLNvendor/phpstan/php-8-stubs/stubs/sapi/litespeed/litespeed_request_headers.stubYR~hjY4S@vendor/phpstan/php-8-stubs/stubs/sapi/fpm/fpm/getallheaders.stubPR~hjP(Ivendor/phpstan/php-8-stubs/stubs/sapi/fpm/fpm/fastcgi_finish_request.stubUR~hjURrIvendor/phpstan/php-8-stubs/stubs/sapi/fpm/fpm/apache_request_headers.stub4R~hj4DhH:Avendor/phpstan/php-8-stubs/stubs/sapi/fpm/fpm/fpm_get_status.stub2R~hj2 Lvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_get_modules.stub0R~hj07ҤAvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/virtual.stub/R~hj/{XӤGvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/getallheaders.stubPR~hjP(Pvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_request_headers.stub4R~hj4DhH:Lvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_get_version.stub7R~hj7>֤Gvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_setenv.stubdR~hjdKݤGvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_getenv.stub]R~hj]]3Evendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_note.stub]R~hj]7dQvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_response_headers.stub5R~hj5Kvendor/phpstan/php-8-stubs/stubs/sapi/apache2handler/apache_lookup_uri.stubhR~hjhkz->vendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_color.stubDR~hjDψ?vendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_prompt.stub8R~hj85SGvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_get_executable.stubFR~hjF)FGvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_break_function.stubBR~hjB{&=vendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_exec.stub>R~hj>e>vendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_clear.stub)R~hj)jwCvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_break_next.stubPR~hjPdL,Bvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_end_oplog.stubBR~hjBoqEvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_break_method.stubMR~hjMJDvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_start_oplog.stub/R~hj/)NCvendor/phpstan/php-8-stubs/stubs/sapi/phpdbg/phpdbg_break_file.stubER~hjEr;cEvendor/phpstan/php-8-stubs/stubs/sapi/cgi/apache_child_terminate.stubUR~hjU Ϥ<vendor/phpstan/php-8-stubs/stubs/sapi/cgi/getallheaders.stubPR~hjP(Evendor/phpstan/php-8-stubs/stubs/sapi/cgi/apache_request_headers.stub4R~hj4DhH:Fvendor/phpstan/php-8-stubs/stubs/sapi/cgi/apache_response_headers.stub5R~hj5"vendor/phpstan/php-8-stubs/LICENSE/R~hj/#Ȥ&vendor/hoa/consistency/Consistency.php~ R~hj~ bT$vendor/hoa/consistency/Xcallable.phpt R~hjt t"vendor/hoa/consistency/PATCHES.txtR~hjoV?"vendor/hoa/consistency/Prelude.phpR~hjY`i%vendor/hoa/consistency/Autoloader.phpaR~hja$vendor/hoa/consistency/Exception.phpR~hjmXvendor/hoa/visitor/Element.phpR~hjebvendor/hoa/visitor/Visit.phpR~hj5vendor/hoa/regex/Grammar.pp R~hj AL&vendor/hoa/regex/Visitor/Isotropic.php>$R~hj>$CId;vendor/hoa/regex/Exception.phpR~hj  vendor/hoa/zformat/Parameter.phpGR~hjG? vendor/hoa/zformat/Exception.phpR~hjNf&vendor/hoa/zformat/Parameterizable.phpR~hjKn.vendor/hoa/compiler/Documentation/En/Index.xylR~hjd/.vendor/hoa/compiler/Documentation/Fr/Index.xyltR~hjtEvendor/hoa/compiler/PATCHES.txt;R~hj;Tsvendor/hoa/compiler/Bin/Pp.phpR~hj%$vendor/hoa/compiler/Visitor/Dump.php? R~hj? L护&vendor/hoa/compiler/Exception/Rule.phpR~hj5<@.vendor/hoa/compiler/Exception/IllegalToken.php R~hj EW 'vendor/hoa/compiler/Exception/Lexer.phpR~hj1vendor/hoa/compiler/Exception/UnexpectedToken.phpR~hj/+vendor/hoa/compiler/Exception/Exception.php R~hj ?3vendor/hoa/compiler/Exception/UnrecognizedToken.php R~hj wؤ=vendor/hoa/compiler/Exception/FinalStateHasNotBeenReached.phpR~hjbsϤvendor/hoa/compiler/Ll1.php`kR~hj`k[&vendor/hoa/compiler/Llk/Rule/Token.php=R~hj=i/'vendor/hoa/compiler/Llk/Rule/Choice.phpeR~hjeOᙤ%vendor/hoa/compiler/Llk/Rule/Rule.php"R~hj"hg7+vendor/hoa/compiler/Llk/Rule/Invocation.phpLR~hjLᙤ+vendor/hoa/compiler/Llk/Rule/Repetition.php R~hj T1&&vendor/hoa/compiler/Llk/Rule/Entry.phphR~hjh+ͤ)vendor/hoa/compiler/Llk/Rule/Analyzer.php"4R~hj"4xF.vendor/hoa/compiler/Llk/Rule/Concatenation.phpzR~hjz_oP&vendor/hoa/compiler/Llk/Rule/Ekzit.phpoR~hjoV|vendor/hoa/compiler/Llk/Llk.pp R~hj Gr5vendor/hoa/compiler/Llk/Sampler/BoundedExhaustive.php&R~hj&Uo+vendor/hoa/compiler/Llk/Sampler/Uniform.php"R~hj",vendor/hoa/compiler/Llk/Sampler/Coverage.php{FR~hj{FCC+vendor/hoa/compiler/Llk/Sampler/Sampler.phpR~hjk<*-vendor/hoa/compiler/Llk/Sampler/Exception.phpR~hjk"vendor/hoa/compiler/Llk/Parser.php QR~hj QJ(!vendor/hoa/compiler/Llk/Lexer.phpR~hj|O$vendor/hoa/compiler/Llk/TreeNode.phpR~hjIC\ۤvendor/hoa/compiler/Llk/Llk.php.R~hj.&vendor/hoa/math/Context.php R~hj J/vendor/hoa/math/Util.phpYR~hjYc] -vendor/hoa/math/Combinatorics/Permutation.phpR~hjsY7*vendor/hoa/math/Combinatorics/Counting.phpR~hjsY7+vendor/hoa/math/Combinatorics/FiniteSet.phpR~hjsY7>vendor/hoa/math/Combinatorics/Combination/CartesianProduct.phpR~hj3vendor/hoa/math/Combinatorics/Combination/Gamma.php?R~hj?ʤ9vendor/hoa/math/Combinatorics/Combination/Combination.php R~hj  K-vendor/hoa/math/Combinatorics/Arrangement.phpR~hjsY7vendor/hoa/math/Bin/Calc.phpR~hj&~"vendor/hoa/math/Sampler/Random.php R~hj P%#vendor/hoa/math/Sampler/Sampler.php!R~hj!M&vendor/hoa/math/Visitor/Arithmetic.phpG'R~hjG'-}ڤ-vendor/hoa/math/Exception/UnknownFunction.phpR~hj䒤-vendor/hoa/math/Exception/UnknownVariable.phpR~hj*-vendor/hoa/math/Exception/UnknownConstant.phpR~hjq4vendor/hoa/math/Exception/AlreadyDefinedConstant.phpR~hj='vendor/hoa/math/Exception/Exception.phpR~hj vendor/hoa/math/Arithmetic.pp R~hj ٤vendor/hoa/file/File.php%R~hj%W vendor/hoa/file/Link/Link.phpRR~hjRM"vendor/hoa/file/Link/ReadWrite.php"R~hj"ͤvendor/hoa/file/Link/Read.phpPR~hjPX<6vendor/hoa/file/Link/Write.phpR~hjGvendor/hoa/file/Finder.php%DR~hj%Dސvendor/hoa/file/Watcher.phpR~hjċvvendor/hoa/file/PATCHES.txtR~hj)'vendor/hoa/file/Temporary/ReadWrite.php"R~hj"'vendor/hoa/file/Temporary/Temporary.phpR~hj09"vendor/hoa/file/Temporary/Read.phpmR~hjm3#vendor/hoa/file/Temporary/Write.phpR~hjF6vendor/hoa/file/SplFileInfo.php R~hj RKvendor/hoa/file/Directory.phpR~hjVvendor/hoa/file/ReadWrite.php"R~hj".vendor/hoa/file/Exception/FileDoesNotExist.phpR~hjKi'vendor/hoa/file/Exception/Exception.phpR~hjU墕vendor/hoa/file/Read.phpAR~hjA$vendor/hoa/file/Generic.php44R~hj44W\/vendor/hoa/file/Write.phpR~hj0M vendor/hoa/iterator/Iterator.phpR~hj"%vendor/hoa/iterator/Demultiplexer.phpR~hj: + vendor/hoa/iterator/Seekable.phpqR~hjqפ&vendor/hoa/iterator/CallbackFilter.php~R~hj~L vendor/hoa/iterator/Multiple.php R~hj  !vendor/hoa/iterator/Lookahead.phpqR~hjq_"vendor/hoa/iterator/Lookbehind.php4R~hj4*4vendor/hoa/iterator/Filter.phpgR~hjgiһ vendor/hoa/iterator/Infinite.phpfR~hjf*vendor/hoa/iterator/Limit.phpZR~hjZ!x#vendor/hoa/iterator/PATCHES.txtR~hj2vendor/hoa/iterator/Map.phpVR~hjVw#vendor/hoa/iterator/SplFileInfo.phphR~hjholvendor/hoa/iterator/Counter.phpR~hj6՟)vendor/hoa/iterator/CallbackGenerator.php R~hj 6H9vendor/hoa/iterator/Buffer.phpR~hjMtʤ!vendor/hoa/iterator/Directory.phpR~hj~!vendor/hoa/iterator/Aggregate.phpvR~hjvˤ vendor/hoa/iterator/NoRewind.phpfR~hjf7Z/}*vendor/hoa/iterator/Recursive/Iterator.phpR~hjs0vendor/hoa/iterator/Recursive/CallbackFilter.phpR~hj(vendor/hoa/iterator/Recursive/Filter.phpR~hj҅%vendor/hoa/iterator/Recursive/Map.php|R~hj|PX:+vendor/hoa/iterator/Recursive/Directory.phpR~hj6FY+vendor/hoa/iterator/Recursive/Recursive.phpR~hjZr 3vendor/hoa/iterator/Recursive/RegularExpression.phpR~hjlֲ&vendor/hoa/iterator/Recursive/Mock.phpoR~hjow!vendor/hoa/iterator/Exception.phpR~hj>Tvendor/hoa/iterator/Glob.phpVR~hjVǻ vendor/hoa/iterator/Repeater.php5R~hj5qvendor/hoa/iterator/Append.php^R~hj^{F)vendor/hoa/iterator/RegularExpression.php!R~hj!^Iuvendor/hoa/iterator/Mock.phpXR~hjX|!"vendor/hoa/iterator/FileSystem.php R~hj vendor/hoa/iterator/Outer.phpfR~hjf񽲤(vendor/hoa/iterator/IteratorIterator.phpvR~hjviÃ#vendor/hoa/stream/Context.phpeR~hjelp)vendor/hoa/stream/Filter/LateComputed.phpcR~hjc4G#vendor/hoa/stream/Filter/Filter.phpR~hjY&:&vendor/hoa/stream/Filter/Exception.phpR~hj"vendor/hoa/stream/Filter/Basic.phpR~hjxvendor/hoa/stream/Bucket.phpR~hjevendor/hoa/stream/PATCHES.txtR~hjaQvendor/hoa/stream/Composite.php R~hj ¯~vendor/hoa/stream/Exception.phpR~hje3vendor/hoa/stream/Stream.phpAR~hjA](vendor/hoa/stream/IStream/Structural.phpR~hjq~'vendor/hoa/stream/IStream/Pointable.php R~hj gq!vendor/hoa/stream/IStream/Out.php R~hj ǟΤ'vendor/hoa/stream/IStream/Touchable.phpR~hj-6&vendor/hoa/stream/IStream/Pathable.phpsR~hjsI7 vendor/hoa/stream/IStream/In.phpnR~hjnT (vendor/hoa/stream/IStream/Bufferable.php R~hj Yq&vendor/hoa/stream/IStream/Lockable.phph R~hjh $vendor/hoa/stream/IStream/Stream.phpR~hjg&vendor/hoa/stream/IStream/Statable.php R~hj i%vendor/hoa/stream/Wrapper/Wrapper.phpR~hjLQ+vendor/hoa/stream/Wrapper/IWrapper/File.phpR~hj݉=/vendor/hoa/stream/Wrapper/IWrapper/IWrapper.phpR~hj?-vendor/hoa/stream/Wrapper/IWrapper/Stream.php0(R~hj0(_S'vendor/hoa/stream/Wrapper/Exception.phpR~hjXevendor/hoa/protocol/Wrapper.php&FR~hj&F[ ZC$vendor/hoa/protocol/Node/Library.php R~hj 7!vendor/hoa/protocol/Node/Node.php&R~hj&zvendor/hoa/protocol/PATCHES.txtR~hjP#vendor/hoa/protocol/Bin/Resolve.phpR~hjAM vendor/hoa/protocol/Protocol.phpR~hjH!vendor/hoa/protocol/Exception.phpR~hj6\vendor/hoa/event/Event.phpR~hjGṳvendor/hoa/event/Listener.phpR~hjݤvendor/hoa/event/Bucket.phpD R~hjD 4u*vendor/hoa/event/Listens.php R~hj #vvendor/hoa/event/Listenable.phpR~hjGOvendor/hoa/event/Exception.phpR~hj=vendor/hoa/event/Source.php_R~hj_vendor/hoa/ustring/Ustring.phpeR~hje -vendor/hoa/ustring/Documentation/En/Index.xylhR~hjhv-vendor/hoa/ustring/Documentation/Fr/Index.xylEnR~hjEnFp!vendor/hoa/ustring/Bin/Tocode.php R~hj #vendor/hoa/ustring/Bin/Fromcode.php R~hj ;m vendor/hoa/ustring/Exception.phpR~hjPRvendor/hoa/ustring/Search.php R~hj  vendor/hoa/exception/Error.phpH R~hjH *b&vendor/hoa/exception/Idle.phpR~hj= vendor/hoa/exception/PATCHES.txtR~hj`on"vendor/hoa/exception/Exception.phpO R~hjO vendor/hoa/exception/Group.phpZR~hjZf$6vendor/psr/http-message/src/ServerRequestInterface.php'R~hj' (/vendor/psr/http-message/src/StreamInterface.phpR~hj<1vendor/psr/http-message/src/ResponseInterface.phpU R~hjU FSj5vendor/psr/http-message/src/UploadedFileInterface.phppR~hjp+0vendor/psr/http-message/src/MessageInterface.phpRR~hjR"10vendor/psr/http-message/src/RequestInterface.php R~hj ;B",vendor/psr/http-message/src/UriInterface.php1R~hj1?mvendor/psr/http-message/LICENSE=R~hj=/vendor/psr/container/src/ContainerInterface.php"R~hj"@'7vendor/psr/container/src/NotFoundExceptionInterface.phpR~hj8vendor/psr/container/src/ContainerExceptionInterface.phpR~hj+Ivendor/psr/container/LICENSEyR~hjyOp/vendor/psr/log/src/InvalidArgumentException.phpsR~hjs&^M+vendor/psr/log/src/LoggerAwareInterface.php<R~hj<+4L"vendor/psr/log/src/LoggerTrait.phpLR~hjL.L'vendor/psr/log/src/LoggerAwareTrait.phpR~hjtvendor/psr/log/src/LogLevel.phpLR~hjLX%vendor/psr/log/src/AbstractLogger.phpR~hj1.&vendor/psr/log/src/LoggerInterface.php R~hj !vendor/psr/log/src/NullLogger.phpR~hjۤvendor/psr/log/LICENSE=R~hj=pO7vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.phpg R~hjg koä>vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.phpR~hj8vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php{R~hj{a,;#:vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php/R~hj/G6vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.phpR~hjixL<vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php R~hj w8vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.phpR~hj6ۤ<vendor/nikic/php-parser/lib/PhpParser/Builder/ClassConst.phpR~hjż0Dvendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.phpbR~hjba:vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php.R~hj.(=vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.phpR~hj?{;vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php1R~hj1(jL:vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php<R~hj<L8vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.phpR~hj<vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php%R~hj%7vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php[R~hj[\P58vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.phpR~hj ?vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.phpR~hj 6vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php~R~hj~[W{>vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php#R~hj#*tY 9vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.phpR~hj'>;;vendor/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php/R~hj/Lvendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.phpzR~hjz56Z7vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php'R~hj'kBvendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.phpR~hj!<vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.phpR~hjħJ7vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.phpR~hjj,q;vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.phpR~hj,O3vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.phpR~hjEt13vendor/nikic/php-parser/lib/PhpParser/Node/Expr.phpR~hj:=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.phpYR~hjY28Evendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php@R~hj@g¤Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.phpFR~hjF3Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.phpDR~hjDCJvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.phpMR~hjMfAEvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php@R~hj@&Q&Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.phpDR~hjD+0 Dvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php=R~hj=)GKvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.phpPR~hjPt@vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.phpSR~hjSix=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.phpR~hj^T=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.phpi R~hji 1Hvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.phpR~hj՝>vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.phpR~hjd3vendor/nikic/php-parser/lib/PhpParser/Node/Name.phpR~hjV5Bvendor/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.phpR~hjE 5vendor/nikic/php-parser/lib/PhpParser/Node/Const_.phpR~hj<Ѥ9vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.phpR~hjm{8vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.phpR~hj8vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php@R~hj@`@vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php R~hj T.:vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.phpCR~hjC y=vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.phpR~hjUPR9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.phpBR~hjB~Ȥ;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.phpR~hj¤<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php*R~hj* >vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.phpR~hji=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.phpR~hj$Uq?vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.phpxR~hjx59vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.phpR~hjyh>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.phpR~hj+[:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.phpeR~hje#><vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.phpR~hjQM8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php\R~hj\,:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.phpR~hjc%=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.phpR~hjU:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.phpR~hj7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php0R~hj0cL >vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.phpR~hjxRBvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.phpR~hjץ1:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.phpR~hjp/>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php R~hj GU7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php2R~hj2?9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.phpR~hj+9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.phpR~hjwC<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.phpR~hj!9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php\R~hj\XEuFvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php R~hj !<Qvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.phpJR~hjJ:`Lvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php1R~hj1Q9:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.phpR~hjF=eL<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.phpR~hj_:Ǥ:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.phpaR~hja957vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php*R~hj*<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.phpR~hjYƤ9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.phpR~hjci:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php5R~hj5^?<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.phpwR~hjw ,;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php9R~hj9t=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php R~hj ܄h<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php_R~hj_h<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php R~hj / :vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.phprR~hjrŠ;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.phpR~hjJ}@vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.phpR~hj )=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php R~hj >7;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php%R~hj%ߩ'8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php.R~hj.cW>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.phpR~hjFHod:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.phpR~hj Dvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.phpR~hjn;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.phpR~hj:;vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.phpR~hj{Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.phpR~hjDG;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php~R~hj~4Q:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php(R~hj(93'>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.phpR~hj l Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php>R~hj>08vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php1R~hj1k;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php R~hj lפ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php{R~hj{Y=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.phpiR~hjinTGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.phpR~hjM Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.phpR~hjj77:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.phpR~hjx ,9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.phpR~hj2:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php{R~hj{Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.phpAR~hjA(@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php2R~hj2̒_@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php3R~hj39VFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php@R~hj@.?Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php?R~hj?эFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php?R~hj? 72Dvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php:R~hj:Ivendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.phpFR~hjF1Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php@R~hj@Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php?R~hj?d;xBvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php6R~hj6߉Dvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php:R~hj:KEvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php=R~hj=:Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.phpAR~hjArL0Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php4R~hj4~i1Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php7R~hj7(Kvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.phpIR~hjIKCvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php8R~hj8"ɼGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.phpBR~hjBاGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.phpBR~hjBGp@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php2R~hj21Evendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php=R~hj=5p6Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php>R~hj>Η0Kvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.phpIR~hjI#tGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php@R~hj@ݞ@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php2R~hj2iaGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php@R~hj@LK >vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.phpR~hj+28:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.phpR~hjճŤAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.phph R~hjh Ll^Ť:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.phpR~hjix<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.phpR~hj@ˤ8vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.phpxR~hjxP9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.phpR~hj<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.phpR~hj%6`;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php~R~hj~J@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.phpR~hjc@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.phpR~hj|Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.phpR~hjwúBvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.phpR~hjUEvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.phpR~hjQGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.phpR~hj7FAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.phpR~hj BCvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.phpR~hj@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.phpR~hjǒ߿Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.phpR~hj.Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.phpR~hj( f@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.phpR~hjU#`ɤGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.phpR~hjx>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.phpJR~hjJIvendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.phpR~hjĤ<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.phpR~hjp Ф:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.phpR~hj =:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php{R~hj{Ly0:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.phpNR~hjNoP?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.phpR~hj8)J]>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.phpR~hjd?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.phpR~hj@@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.phpR~hj`̤=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.phpR~hjo=@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.phpR~hjm3?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.phpR~hjkO#ͤ9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.phpR~hj*I<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php_R~hj_4A=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.phpR~hji$>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.phpR~hj$>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.phpR~hj9Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.phpSR~hjS3ͤ>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php<R~hj<89vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php{R~hj{~=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php8R~hj8)=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.phpR~hj'(=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.phpR~hjg;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.phpR~hjH:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php~R~hj~۵Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.phpR~hjAʤ<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php0R~hj0,fS>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.phpwR~hjwp5vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.phpsR~hjsuQ4vendor/nikic/php-parser/lib/PhpParser/Node/Param.phpsR~hjsbN2vendor/nikic/php-parser/lib/PhpParser/Node/Arg.php9R~hj9[?vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.phpR~hjaD5vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.phphR~hjhy6vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php2R~hj2L/vendor/nikic/php-parser/lib/PhpParser/Error.phpR~hj%b&7vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.phpR~hjy\9vendor/nikic/php-parser/lib/PhpParser/Parser/Multiple.phpR~hjFR5vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.phpTR~hjTH5vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php+R~hj+PĤFvendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.phpWR~hjW "?vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.phpnR~hjnZAMAvendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php|R~hj|8vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php,R~hj,O@vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.phpR~hjJ5vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.phpD R~hjD CD8vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php%R~hj%M͔=vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.phpR~hj8@vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.phpӤR~hjӤw5vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.phpR~hjY0vendor/nikic/php-parser/lib/PhpParser/Parser.phpR~hjC2Ӥ4vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php R~hj v/vendor/nikic/php-parser/lib/PhpParser/Lexer.php&[R~hj&[N<Dvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.phpR~hj!FMvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php]R~hj] Ivendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.phpR~hj+Bvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php&R~hj&6Dvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.phplR~hjl=*Kvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.phptR~hjtkڤ<vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.phpv%R~hjv%Svendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.phpR~hjx,[vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.phpR~hjpXSvendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.phpR~hjvendor/fidry/cpu-core-counter/src/Executor/ProcessExecutor.phpR~hjbWW>vendor/fidry/cpu-core-counter/src/Finder/NullCpuCoreFinder.phpR~hj'b~M?vendor/fidry/cpu-core-counter/src/Finder/WmicPhysicalFinder.phpR~hj`T|>vendor/fidry/cpu-core-counter/src/Finder/_NProcessorFinder.phpR~hj&oIvendor/fidry/cpu-core-counter/src/Finder/WindowsRegistryLogicalFinder.phpxR~hjx:2<vendor/fidry/cpu-core-counter/src/Finder/HwLogicalFinder.phpvR~hjv@vendor/fidry/cpu-core-counter/src/Finder/ProcOpenBasedFinder.php R~hj q1Dvendor/fidry/cpu-core-counter/src/Finder/CmiCmdletPhysicalFinder.phpR~hjAvendor/fidry/cpu-core-counter/src/Finder/SkipOnOSFamilyFinder.phpR~hjCvendor/fidry/cpu-core-counter/src/Finder/CmiCmdletLogicalFinder.phpR~hjz>vendor/fidry/cpu-core-counter/src/Finder/WmicLogicalFinder.phpR~hjr :vendor/fidry/cpu-core-counter/src/Finder/CpuCoreFinder.php R~hj 셋@vendor/fidry/cpu-core-counter/src/Finder/LscpuPhysicalFinder.phpxR~hjxL>vendor/fidry/cpu-core-counter/src/Finder/EnvVariableFinder.phpR~hj:/jCvendor/fidry/cpu-core-counter/src/Finder/OnlyInPowerShellFinder.phpR~hjJuWAvendor/fidry/cpu-core-counter/src/Finder/OnlyOnOSFamilyFinder.phpR~hj#P(;vendor/fidry/cpu-core-counter/src/Finder/FinderRegistry.phpR~hji]?vendor/fidry/cpu-core-counter/src/Finder/DummyCpuCoreFinder.phpAR~hjAJ[?H=vendor/fidry/cpu-core-counter/src/Finder/NProcessorFinder.phpR~hj29:vendor/fidry/cpu-core-counter/src/Finder/CpuInfoFinder.php R~hj Vv=vendor/fidry/cpu-core-counter/src/Finder/HwPhysicalFinder.phpzR~hjzgФ?vendor/fidry/cpu-core-counter/src/Finder/LscpuLogicalFinder.phpMR~hjM8vendor/fidry/cpu-core-counter/src/Finder/NProcFinder.phpR~hjS=vendor/fidry/cpu-core-counter/src/NumberOfCpuCoreNotFound.php$R~hj$sX;vendor/fidry/cpu-core-counter/src/ParallelisationResult.phpR~hj./vendor/fidry/cpu-core-counter/src/Diagnoser.php{R~hj{RC;vendor/fig/http-message-util/src/RequestMethodInterface.phpR~hjTw8vendor/fig/http-message-util/src/StatusCodeInterface.phpyR~hjyY;$vendor/fig/http-message-util/LICENSE=R~hj=? vendor/symfony/finder/Finder.phpXR~hjX{&#vendor/symfony/finder/Gitignore.php% R~hj% @_%vendor/symfony/finder/SplFileInfo.php,R~hj,vendor/symfony/finder/LICENSE,R~hj,U9vendor/symfony/finder/Exception/AccessDeniedException.phpR~hj|yy>vendor/symfony/finder/Exception/DirectoryNotFoundException.phpR~hjTܤvendor/symfony/finder/Glob.phpJR~hjJ螤;vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpR~hj7<vendor/symfony/finder/Iterator/FilecontentFilterIterator.phpR~hjJ:vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpR~hjFA=vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.phpR~hj)5Avendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php R~hj Q:vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpR~hjz9vendor/symfony/finder/Iterator/FileTypeFilterIterator.phpR~hj@=vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php R~hj "5vendor/symfony/finder/Iterator/PathFilterIterator.phpR~hj63vendor/symfony/finder/Iterator/SortableIterator.phpjR~hjj8;vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.phpR~hjU/vendor/symfony/finder/Iterator/LazyIterator.phpR~hj79vendor/symfony/finder/Iterator/FilenameFilterIterator.phpR~hjP)7vendor/symfony/finder/Iterator/CustomFilterIterator.php3R~hj3uq5vendor/symfony/finder/Comparator/NumberComparator.php R~hj vk/vendor/symfony/finder/Comparator/Comparator.php R~hj o{3vendor/symfony/finder/Comparator/DateComparator.phpR~hjӇɤ'vendor/symfony/polyfill-php81/Php81.phpR~hj$%vendor/symfony/polyfill-php81/LICENSE,R~hj,0+vendor/symfony/polyfill-php81/bootstrap.phpR~hj<P@vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.phpR~hjJTFvendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.phpR~hj5+=vendor/symfony/service-contracts/ServiceProviderInterface.phpR~hj.8vendor/symfony/service-contracts/ServiceLocatorTrait.php R~hj ޤ;vendor/symfony/service-contracts/ServiceSubscriberTrait.phpR~hj4<?vendor/symfony/service-contracts/ServiceSubscriberInterface.phpR~hjyʤ3vendor/symfony/service-contracts/ResetInterface.phpR~hj^6(vendor/symfony/service-contracts/LICENSE,R~hj,@vendor/symfony/service-contracts/Attribute/SubscribedService.php:R~hj:57vendor/symfony/service-contracts/Attribute/Required.phpR~hj\D'vendor/symfony/polyfill-php73/Php73.phpbR~hjbJ<%vendor/symfony/polyfill-php73/LICENSE,R~hj,+vendor/symfony/polyfill-php73/bootstrap.phpR~hj|?vendor/symfony/polyfill-php73/Resources/stubs/JsonException.phpER~hjE8S-vendor/symfony/polyfill-ctype/bootstrap80.phphR~hjhˤ'vendor/symfony/polyfill-ctype/Ctype.phpR~hj{5%vendor/symfony/polyfill-ctype/LICENSE,R~hj,+vendor/symfony/polyfill-ctype/bootstrap.php,R~hj,i'ޤ(vendor/symfony/string/AbstractString.phpOR~hjOR$'vendor/symfony/string/UnicodeString.php2R~hj2 $vendor/symfony/string/LazyString.phprR~hjr6I)vendor/symfony/string/CodePointString.phpR~hj/nɤ/vendor/symfony/string/AbstractUnicodeString.phpaiR~hjaiuAǤvendor/symfony/string/LICENSE,R~hj,զ_Ϥ3vendor/symfony/string/Inflector/FrenchInflector.php$R~hj$-{4vendor/symfony/string/Inflector/EnglishInflector.phpBR~hjBzIݤ6vendor/symfony/string/Inflector/InflectorInterface.phpVR~hjV2vendor/symfony/string/Slugger/SluggerInterface.phpR~hjev.vendor/symfony/string/Slugger/AsciiSlugger.php3R~hj3EN#$vendor/symfony/string/ByteString.php<R~hj< <vendor/symfony/string/Exception/InvalidArgumentException.phpR~hjH&6vendor/symfony/string/Exception/ExceptionInterface.phpcR~hjcm4vendor/symfony/string/Exception/RuntimeException.phpR~hj-n-vendor/symfony/string/Resources/functions.phppR~hjp=<vendor/symfony/string/Resources/data/wcswidth_table_wide.phpR~hje<vendor/symfony/string/Resources/data/wcswidth_table_zero.phpR~hjKĭ%vendor/symfony/process/PhpProcess.php R~hj EѤ'vendor/symfony/process/ProcessUtils.php\R~hj\N1 &vendor/symfony/process/InputStream.php R~hj u-+vendor/symfony/process/ExecutableFinder.php R~hj ^"vendor/symfony/process/Process.phpR~hj)Dvendor/symfony/process/LICENSE,R~hj,U.vendor/symfony/process/PhpExecutableFinder.phpa R~hja )-vendor/symfony/process/Pipes/WindowsPipes.phpoR~hjodgؤ.vendor/symfony/process/Pipes/AbstractPipes.phpR~hjr^/vendor/symfony/process/Pipes/PipesInterface.phpR~hjyH,*vendor/symfony/process/Pipes/UnixPipes.phpR~hjh=vendor/symfony/process/Exception/InvalidArgumentException.phpR~hjP13vendor/symfony/process/Exception/LogicException.phpR~hjw-7vendor/symfony/process/Exception/ExceptionInterface.phpR~hj}i=vendor/symfony/process/Exception/ProcessSignaledException.phpR~hjx ;vendor/symfony/process/Exception/ProcessFailedException.phpIR~hjI:=vendor/symfony/process/Exception/ProcessTimedOutException.php|R~hj|V5vendor/symfony/process/Exception/RuntimeException.phpR~hj',~'vendor/symfony/polyfill-php74/Php74.php R~hj AV܀%vendor/symfony/polyfill-php74/LICENSE,R~hj,զ_Ϥ+vendor/symfony/polyfill-php74/bootstrap.php%R~hj% 1vendor/symfony/deprecation-contracts/function.php2R~hj2p<,vendor/symfony/deprecation-contracts/LICENSE,R~hj, K*vendor/symfony/polyfill-php80/PhpToken.phpR~hj]f'vendor/symfony/polyfill-php80/Php80.php R~hj cH%vendor/symfony/polyfill-php80/LICENSE,R~hj, K+vendor/symfony/polyfill-php80/bootstrap.phpR~hj.Ĥ:vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.phpwR~hjw=7T8<vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php>R~hj>gEvendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.phpGR~hjGֈ+;vendor/symfony/polyfill-php80/Resources/stubs/Attribute.phpR~hjMK<<vendor/symfony/polyfill-php80/Resources/stubs/Stringable.phpR~hjt]\ڤ-vendor/symfony/polyfill-mbstring/Mbstring.phpJR~hjJŮ0vendor/symfony/polyfill-mbstring/bootstrap80.php'R~hj'L#\M(vendor/symfony/polyfill-mbstring/LICENSE,R~hj,H.vendor/symfony/polyfill-mbstring/bootstrap.php!R~hj!dFvendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php9R~hj9>|zKBvendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.phpa R~hja |ⳤ@vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php_R~hj_d@vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpfR~hjfP7vendor/symfony/polyfill-intl-normalizer/bootstrap80.phpR~hj,/vendor/symfony/polyfill-intl-normalizer/LICENSE,R~hj,H5vendor/symfony/polyfill-intl-normalizer/bootstrap.phpR~hj#p 6vendor/symfony/polyfill-intl-normalizer/Normalizer.phpd%R~hjd%uFvendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.phpR~hj%Rvendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.phpDR~hjD'CԤTvendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php{R~hj{jeXvendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.phpoR~hjoc,Lvendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.phpD5R~hjD5 8vendor/symfony/console/Formatter/NullOutputFormatter.phpoR~hjoOq*Fvendor/symfony/console/Formatter/WrappableOutputFormatterInterface.phpR~hjь=vendor/symfony/console/Formatter/NullOutputFormatterStyle.phpR~hjF ֤=vendor/symfony/console/Formatter/OutputFormatterInterface.phpDR~hjD\jBvendor/symfony/console/Formatter/OutputFormatterStyleInterface.phpiR~hjiy>vendor/symfony/console/Formatter/OutputFormatterStyleStack.php+ R~hj+ $٤9vendor/symfony/console/Formatter/OutputFormatterStyle.php R~hj nĤ4vendor/symfony/console/Formatter/OutputFormatter.php R~hj πäDvendor/symfony/console/DependencyInjection/AddConsoleCommandPass.phpR~hj3%/vendor/symfony/console/Logger/ConsoleLogger.phpR~hj2vendor/symfony/console/Question/ChoiceQuestion.phpR~hj)̤8vendor/symfony/console/Question/ConfirmationQuestion.php)R~hj)@ m,vendor/symfony/console/Question/Question.php~R~hj~Ĥ(vendor/symfony/console/ConsoleEvents.phpR~hj覤2vendor/symfony/console/CI/GithubActionReporter.php# R~hj# &ڴm=vendor/symfony/console/CommandLoader/FactoryCommandLoader.phpeR~hje.?vendor/symfony/console/CommandLoader/CommandLoaderInterface.phpR~hj7?vendor/symfony/console/CommandLoader/ContainerCommandLoader.phpR~hj,,vendor/symfony/console/Input/StringInput.php R~hj .k9vendor/symfony/console/Input/StreamableInputInterface.phpzR~hjz0vendor/symfony/console/Input/InputDefinition.phpT.R~hjT.~,vendor/symfony/console/Input/InputOption.php`R~hj`,hw+vendor/symfony/console/Input/ArrayInput.phpR~hj@Ť/vendor/symfony/console/Input/InputInterface.phpR~hjZ.vendor/symfony/console/Input/InputArgument.php R~hj U 4vendor/symfony/console/Input/InputAwareInterface.phpLR~hjLI &vendor/symfony/console/Input/Input.php=R~hj=H*vendor/symfony/console/Input/ArgvInput.php0R~hj0XV vendor/symfony/console/Color.phpZR~hjZ}8vendor/symfony/console/SignalRegistry/SignalRegistry.phpDR~hjD* Ĥ=vendor/symfony/console/Command/SignalableCommandInterface.phpR~hjA{8vendor/symfony/console/Command/DumpCompletionCommand.phpR~hjmb+2vendor/symfony/console/Command/CompleteCommand.php R~hj e^*vendor/symfony/console/Command/Command.phpPR~hjPrﮤ.vendor/symfony/console/Command/LazyCommand.phpFR~hjF0vendor/symfony/console/Command/LockableTrait.php$R~hj$L%l.vendor/symfony/console/Command/ListCommand.php R~hj .vendor/symfony/console/Command/HelpCommand.php R~hj |̜V&vendor/symfony/console/Application.phpR~hj{<3vendor/symfony/console/SingleCommandApplication.php9R~hj91 6vendor/symfony/console/EventListener/ErrorListener.php^ R~hj^ f(vendor/symfony/console/Helper/Dumper.phpXR~hjX o 1vendor/symfony/console/Helper/HelperInterface.php^R~hj^?oa'vendor/symfony/console/Helper/Table.phpsR~hjsZ_0vendor/symfony/console/Helper/QuestionHelper.phpLR~hjL0vendor/symfony/console/Helper/TableSeparator.php%R~hj%΍657vendor/symfony/console/Helper/SymfonyQuestionHelper.phpG R~hjG ֤+vendor/symfony/console/Helper/TableCell.phpR~hjmƕ6vendor/symfony/console/Helper/DebugFormatterHelper.php\ R~hj\ $Ȥ/vendor/symfony/console/Helper/ProcessHelper.phpR~hj3vendor/symfony/console/Helper/ProgressIndicator.phpR~hjB+vendor/symfony/console/Helper/HelperSet.phpE R~hjE kV,vendor/symfony/console/Helper/TableStyle.php0R~hj0ﯤ(vendor/symfony/console/Helper/Helper.phpR~hjK$ߤ-vendor/symfony/console/Helper/ProgressBar.phpOHR~hjOHRm2vendor/symfony/console/Helper/InputAwareHelper.php!R~hj!+vendor/symfony/console/Helper/TableRows.phpVR~hjV|1vendor/symfony/console/Helper/FormatterHelper.php R~hj ˿c2vendor/symfony/console/Helper/DescriptorHelper.php R~hj >I|0vendor/symfony/console/Helper/TableCellStyle.phpdR~hjdV5vendor/symfony/console/Completion/CompletionInput.php[ R~hj[ 360vendor/symfony/console/Completion/Suggestion.phpR~hjEh@;vendor/symfony/console/Completion/CompletionSuggestions.phpnR~hjn9Avendor/symfony/console/Completion/Output/BashCompletionOutput.phpR~hj,ͤFvendor/symfony/console/Completion/Output/CompletionOutputInterface.phpR~hj&Wk09vendor/symfony/console/Descriptor/DescriptorInterface.phpQR~hjQ+Ф3vendor/symfony/console/Descriptor/XmlDescriptor.php.'R~hj.'(8vendor/symfony/console/Descriptor/MarkdownDescriptor.phpkR~hjkr4vendor/symfony/console/Descriptor/JsonDescriptor.phpR~hjP<vendor/symfony/console/Descriptor/ApplicationDescription.php%R~hj%P)0vendor/symfony/console/Descriptor/Descriptor.php R~hj  4vendor/symfony/console/Descriptor/TextDescriptor.php2R~hj29^)vendor/symfony/console/LICENSE,R~hj,U!vendor/symfony/console/Cursor.php?R~hj?:w=vendor/symfony/console/Exception/InvalidArgumentException.phpR~hjTؤ=vendor/symfony/console/Exception/CommandNotFoundException.phpR~hjפ?vendor/symfony/console/Exception/NamespaceNotFoundException.phpR~hjh:vendor/symfony/console/Exception/MissingInputException.phpR~hj"=3vendor/symfony/console/Exception/LogicException.phpR~hj?uƤ7vendor/symfony/console/Exception/ExceptionInterface.phpR~hj;vendor/symfony/console/Exception/InvalidOptionException.phpR~hj}a*#5vendor/symfony/console/Exception/RuntimeException.phpR~hjȨm@vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.phpR~hj T9vendor/symfony/console/Tester/CommandCompletionTester.phpLR~hjLͪ3vendor/symfony/console/Tester/ApplicationTester.php R~hj "-vendor/symfony/console/Tester/TesterTrait.phpR~hjTҤ/vendor/symfony/console/Tester/CommandTester.phpJ R~hjJ 5vendor/symfony/console/Output/TrimmedBufferOutput.phpoR~hjoi/vendor/symfony/console/Output/ConsoleOutput.php)R~hj)40vendor/symfony/console/Output/BufferedOutput.phpcR~hjc+,vendor/symfony/console/Output/NullOutput.php8 R~hj8 r1vendor/symfony/console/Output/OutputInterface.phpt R~hjt (-8vendor/symfony/console/Output/ConsoleOutputInterface.php1R~hj1DGߤ(vendor/symfony/console/Output/Output.phpgR~hjgh6vendor/symfony/console/Output/ConsoleSectionOutput.phpR~hj=].vendor/symfony/console/Output/StreamOutput.phpR~hjSw".vendor/symfony/console/Attribute/AsCommand.phpNR~hjN6@#vendor/symfony/console/Terminal.phpmR~hjmHlu4vendor/symfony/console/Resources/bin/hiddeninput.exe$R~hj$v0vendor/symfony/console/Resources/completion.bash R~hj z(3vendor/symfony/console/Event/ConsoleSignalEvent.phpR~hj*4ؤ6vendor/symfony/console/Event/ConsoleTerminateEvent.phpjR~hjjÒ}-vendor/symfony/console/Event/ConsoleEvent.phpR~hjV!2vendor/symfony/console/Event/ConsoleErrorEvent.php"R~hj"M%4vendor/symfony/console/Event/ConsoleCommandEvent.php=R~hj=k},vendor/symfony/console/Style/OutputStyle.phpL R~hjL >-vendor/symfony/console/Style/SymfonyStyle.php9R~hj9˩Ӥ/vendor/symfony/console/Style/StyleInterface.phpR R~hjR :r5vendor/symfony/polyfill-intl-grapheme/bootstrap80.phpg R~hjg E{2vendor/symfony/polyfill-intl-grapheme/Grapheme.php8&R~hj8&I-vendor/symfony/polyfill-intl-grapheme/LICENSE,R~hj,H3vendor/symfony/polyfill-intl-grapheme/bootstrap.phpR~hj|\Countable ? true : false) */ function is_countable(mixed $value): bool { } /** * @return ($value is object ? true : false) */ function is_object(mixed $value): bool { } /** * @return ($value is scalar ? true : false) */ function is_scalar(mixed $value): bool { } /** * @return ($value is int ? true : false) */ function is_int(mixed $value): bool { } /** * @return ($value is int ? true : false) */ function is_integer(mixed $value): bool { } /** * @return ($value is int ? true : false) */ function is_long(mixed $value): bool { } /** * @phpstan-assert-if-true =resource $value * @return bool */ function is_resource(mixed $value): bool { } /** * @return ($value is array ? true : false) */ function is_array(mixed $value): bool { } /** * @return ($value is iterable ? true : false) */ function is_iterable(mixed $value): bool { } * @template-implements SeekableIterator * @template-implements ArrayAccess */ class SplObjectStorage implements Countable, Iterator, SeekableIterator, Serializable, ArrayAccess { /** * @param \SplObjectStorage $storage */ public function addAll(SplObjectStorage $storage): void { } /** * @param TObject $object * @param TData $data */ public function attach(object $object, $data = null): void { } /** * @param TObject $object */ public function contains(object $object): bool { } /** * @param TObject $object */ public function detach(object $object): void { } /** * @param TObject $object */ public function getHash(object $object): string { } /** * @return TData */ public function getInfo() { } /** * @param \SplObjectStorage<*, *> $storage */ public function removeAll(SplObjectStorage $storage): void { } /** * @param \SplObjectStorage<*, *> $storage */ public function removeAllExcept(SplObjectStorage $storage): void { } /** * @param TData $data */ public function setInfo($data): void { } /** * @param TObject $offset * @return TData */ public function offsetGet($offset); } */ public function getName() : string { } /** * @return T */ public function newInstance() : object { } } */ interface Collection extends IteratorAggregate, Countable, JsonSerializable { /** * @return static */ public function copy(); /** * @return array */ public function toArray(): array; } /** * @template TValue * @implements Sequence */ final class Deque implements Sequence { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Deque */ public function copy() { } /** * @template TValue2 * @param iterable $values * @return Deque */ public function merge(iterable $values): Deque { } /** * @param (callable(TValue): bool)|null $callback * @return Deque */ public function filter(?callable $callback = null): Deque { } /** * @template TNewValue * @param callable(TValue): TNewValue $callback * @return Deque */ public function map(callable $callback): Deque { } /** * @return Deque */ public function reversed(): Deque { } /** * @return Deque */ public function slice(int $offset, ?int $length = null): Deque { } } /** * @template TKey * @template TValue * @implements Collection * @implements ArrayAccess */ final class Map implements Collection, ArrayAccess { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Map */ public function copy(): Map { } /** * @param callable(TKey, TValue): TValue $callback * @return void */ public function apply(callable $callback) { } /** * @return Pair * @throws UnderflowException */ public function first(): Pair { } /** * @return Pair * @throws UnderflowException */ public function last(): Pair { } /** * @return Pair * @throws OutOfRangeException */ public function skip(int $position): Pair { } /** * @template TKey2 * @template TValue2 * @param iterable $values * @return Map */ public function merge(iterable $values): Map { } /** * @template TKey2 * @template TValue2 * @param Map $map * @return Map */ public function intersect(Map $map): Map { } /** * @template TValue2 * @param Map $map * @return Map */ public function diff(Map $map): Map { } /** * @param TKey $key */ public function hasKey($key): bool { } /** * @param TValue $value */ public function hasValue($value): bool { } /** * @param (callable(TKey, TValue): bool)|null $callback * @return Map */ public function filter(?callable $callback = null): Map { } /** * @template TDefault * @param TKey $key * @param TDefault $default * @return TValue|TDefault * @throws OutOfBoundsException */ public function get($key, $default = null) { } /** * @return Set */ public function keys(): Set { } /** * @template TNewValue * @param callable(TKey, TValue): TNewValue $callback * @return Map */ public function map(callable $callback): Map { } /** * @return Sequence> */ public function pairs(): Sequence { } /** * @param TKey $key * @param TValue $value * @return void */ public function put($key, $value) { } /** * @param iterable $values * @return void */ public function putAll(iterable $values) { } /** * @template TCarry * @param callable(TCarry, TKey, TValue): TCarry $callback * @param TCarry $initial * @return TCarry */ public function reduce(callable $callback, $initial = null) { } /** * @template TDefault * @param TKey $key * @param TDefault $default * @return TValue|TDefault * @throws \OutOfBoundsException */ public function remove($key, $default = null) { } /** * @return Map */ public function reversed(): Map { } /** * @return Map */ public function slice(int $offset, ?int $length = null): Map { } /** * @param (callable(TValue, TValue): int)|null $comparator * @return void */ public function sort(?callable $comparator = null) { } /** * @param (callable(TValue, TValue): int)|null $comparator * @return Map */ public function sorted(?callable $comparator = null): Map { } /** * @param (callable(TKey, TKey): int)|null $comparator * @return void */ public function ksort(?callable $comparator = null) { } /** * @param (callable(TKey, TKey): int)|null $comparator * @return Map */ public function ksorted(?callable $comparator = null): Map { } /** * @return array */ public function toArray(): array { } /** * @return Sequence */ public function values(): Sequence { } /** * @template TKey2 * @template TValue2 * @param Map $map * @return Map */ public function union(Map $map): Map { } /** * @template TKey2 * @template TValue2 * @param Map $map * @return Map */ public function xor(Map $map): Map { } } /** * @template-covariant TKey * @template-covariant TValue */ final class Pair implements JsonSerializable { /** * @var TKey */ public $key; /** * @var TValue */ public $value; /** * @param TKey $key * @param TValue $value */ public function __construct($key = null, $value = null) { } /** * @return Pair */ public function copy(): Pair { } } /** * @template TValue * @extends Collection * @extends ArrayAccess */ interface Sequence extends Collection, ArrayAccess { /** * @param callable(TValue): TValue $callback * @return void */ public function apply(callable $callback); /** * @param TValue ...$values */ public function contains(...$values): bool; /** * @param (callable(TValue): bool)|null $callback * @return Sequence */ public function filter(?callable $callback = null); /** * @param TValue $value * @return int|false */ public function find($value); /** * @return TValue * @throws \UnderflowException */ public function first(); /** * @return TValue * @throws \OutOfRangeException */ public function get(int $index); /** * @param TValue ...$values * @throws \OutOfRangeException * @return void */ public function insert(int $index, ...$values); /** * @param string $glue * @return string */ public function join(?string $glue = null): string; /** * @return TValue * @throws \UnderflowException */ public function last(); /** * @template TNewValue * @param callable(TValue): TNewValue $callback * @return Sequence */ public function map(callable $callback); /** * @template TValue2 * @param iterable $values * @return Sequence */ public function merge(iterable $values); /** * @return TValue * @throws \UnderflowException * @phpstan-impure */ public function pop(); /** * @param TValue ...$values * @return void */ public function push(...$values); /** * @template TCarry * @param callable(TCarry, TValue): TCarry $callback * @param TCarry $initial * @return TCarry */ public function reduce(callable $callback, $initial = null); /** * @return TValue * @throws \OutOfRangeException */ public function remove(int $index); /** * @return Sequence */ public function reversed(); /** * @param TValue $value * @throws \OutOfRangeException * @return void */ public function set(int $index, $value); /** * @return TValue * @throws \UnderflowException * @phpstan-impure */ public function shift(); /** * @return Sequence */ public function slice(int $index, ?int $length = null); /** * @param (callable(TValue, TValue): int)|null $comparator * @return void */ public function sort(?callable $comparator = null); /** * @param (callable(TValue, TValue): int)|null $comparator * @return Sequence */ public function sorted(?callable $comparator = null); /** * @param TValue ...$values * @return void */ public function unshift(...$values); } /** * @template TValue * @implements Sequence */ final class Vector implements Sequence { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Vector */ public function copy() { } /** * @return Vector */ public function reversed(): Vector { } /** * @return Vector */ public function slice(int $offset, ?int $length = null): Vector { } /** * @param (callable(TValue, TValue): int)|null $comparator * @return Vector */ public function sorted(?callable $comparator = null): Vector { } /** * @param (callable(TValue): bool)|null $callback * @return Vector */ public function filter(?callable $callback = null): Vector { } /** * @template TNewValue * @param callable(TValue): TNewValue $callback * @return Vector */ public function map(callable $callback): Vector { } /** * @template TValue2 * @param iterable $values * @return Vector */ public function merge(iterable $values): Vector { } } /** * @template TValue * @implements Collection * @implements ArrayAccess */ final class Set implements Collection, ArrayAccess { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @param TValue ...$values */ public function add(...$values): void { } /** * @param TValue ...$values */ public function contains(...$values): bool { } /** * @return Set */ public function copy(): Set { } /** * @template TValue2 * @param Set $set * @return Set */ public function diff(Set $set): Set { } /** * @param (callable(TValue): bool)|null $callback * @return Set */ public function filter(?callable $callback = null): Set { } /** * @return TValue * @throws \UnderflowException */ public function first() { } /** * @return TValue * @throws \OutOfRangeException */ public function get(int $index) { } /** * @template TValue2 * @param Set $set * @return Set */ public function intersect(Set $set): Set { } /** * @return TValue * @throws \UnderflowException */ public function last() { } /** * @template TNewValue * @param callable(TValue): TNewValue $callback * @return Set */ public function map(callable $callback): Set { } /** * @template TValue2 * @param iterable $values * @return Set */ public function merge(iterable $values): Set { } /** * @template TCarry * @param callable(TCarry, TValue): TCarry $callback * @param TCarry $initial * @return TCarry */ public function reduce(callable $callback, $initial = null) { } /** * @param TValue ...$values */ public function remove(...$values): void { } /** * @return Set */ public function reversed(): Set { } /** * @return Set */ public function slice(int $index, ?int $length = null): Set { } /** * @param (callable(TValue, TValue): int)|null $comparator */ public function sort(?callable $comparator = null): void { } /** * @param (callable(TValue, TValue): int)|null $comparator * @return Set */ public function sorted(?callable $comparator = null): Set { } /** * @return list */ public function toArray(): array { } /** * @template TValue2 * @param Set $set * @return Set */ public function union(Set $set): Set { } /** * @template TValue2 * @param Set $set * @return Set */ public function xor(Set $set): Set { } } /** * @template TValue * @implements Collection * @implements ArrayAccess */ final class Stack implements Collection, ArrayAccess { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Stack */ public function copy(): Stack { } /** * @return TValue * @throws UnderflowException */ public function peek() { } /** * @return TValue * @throws UnderflowException * @phpstan-impure */ public function pop() { } /** * @param TValue ...$values * @return void */ public function push(...$values): void { } /** * @return list */ public function toArray(): array { } } /** * @template TValue * @implements Collection * @implements ArrayAccess */ final class Queue implements Collection, ArrayAccess { /** * @param iterable $values */ public function __construct(iterable $values = []) { } /** * @return Queue */ public function copy(): Queue { } /** * @return TValue * @throws UnderflowException */ public function peek() { } /** * @return TValue * @throws UnderflowException * @phpstan-impure */ public function pop() { } /** * @param TValue ...$values */ public function push(...$values): void { } /** * @return list */ public function toArray(): array { } } /** * @template TValue * @implements Collection */ final class PriorityQueue implements Collection { /** * @return PriorityQueue */ public function copy(): PriorityQueue { } /** * @return TValue * @throws UnderflowException */ public function peek() { } /** * @return TValue * @throws UnderflowException * @phpstan-impure */ public function pop() { } /** * @param TValue $value */ public function push($value, int $priority): void { } /** * @return list */ public function toArray(): array { } } |numeric-string */ public $affected_rows; } class mysqli_result { /** * @var int<0,max>|numeric-string */ public $num_rows; /** * @template T of object * @param class-string $class * @param array $constructor_args * @return T|null|false */ function fetch_object(string $class = 'stdClass', array $constructor_args = []) {} } /** * @template T of object * * @param class-string $class * @param array $constructor_args * @return T|null|false */ function mysqli_fetch_object(mysqli_result $result, string $class = 'stdClass', array $constructor_args = []) {} class mysqli_stmt { /** * @var int<-1,max>|numeric-string */ public $affected_rows; /** * @var int */ public $errno; /** * @var list */ public $error_list; /** * @var string */ public $error; /** * @var 0|positive-int */ public $field_count; /** * @var int|string */ public $insert_id; /** * @var int<0,max>|numeric-string */ public $num_rows; /** * @var 0|positive-int */ public $param_count; /** * @var non-empty-string */ public $sqlstate; } */ public static function create(object $referent): WeakReference {} /** @return ?T */ public function get() {} } /** * @template TKey of object * @template TValue * @implements \ArrayAccess * @implements \IteratorAggregate */ final class WeakMap implements \ArrayAccess, \Countable, \IteratorAggregate { /** * @param TKey $offset * @return TValue */ public function offsetGet($offset) {} } $result * @param-out array|string> $result */ function parse_str(string $string, array &$result): void {} /** * @param array $result * @param-out array|string> $result */ function mb_parse_str(string $string, array &$result): bool {} /** @param-out float $percent */ function similar_text(string $string1, string $string2, ?float &$percent = null) : int {} /** * @param mixed $output * @param mixed $result_code * * @param-out list $output * @param-out int $result_code * * @return string|false */ function exec(string $command, &$output, &$result_code) {} /** * @param mixed $result_code * @param-out int $result_code * * @return string|false */ function system(string $command, &$result_code) {} /** * @param mixed $result_code * @param-out int $result_code */ function passthru(string $command, &$result_code): ?bool {} /** * @template T * @template TArray as array * * @param TArray $array */ function shuffle(array &$array): bool { } /** * @template T * @template TArray as array * * @param TArray $array */ function sort(array &$array, int $flags = SORT_REGULAR): bool { } /** * @template T * @template TArray as array * * @param TArray $array */ function rsort(array &$array, int $flags = SORT_REGULAR): bool { } /** * @param string $string * @param-out null $string */ function sodium_memzero(string &$string): void { } /** * @param resource $stream * @param mixed $vars * @param-out string|int|float|null $vars * * @return list|int|false */ function fscanf($stream, string $format, &...$vars) {} /** * @param mixed $war * @param mixed $vars * @param-out string|int|float|null $war * @param-out string|int|float|null $vars * * @return int|array|null */ function sscanf(string $string, string $format, &$war, &...$vars) {} /** * @template TFlags as int * * @param string $pattern * @param string $subject * @param mixed $matches * @param TFlags $flags * @param-out ( * TFlags is 1 * ? array> * : (TFlags is 2 * ? list> * : (TFlags is 256|257 * ? array> * : (TFlags is 258 * ? list> * : (TFlags is 512|513 * ? array> * : (TFlags is 514 * ? list> * : (TFlags is 770 * ? list> * : (TFlags is 0 ? array> : array) * ) * ) * ) * ) * ) * ) * ) $matches * @return int|false */ function preg_match_all($pattern, $subject, &$matches = [], int $flags = 1, int $offset = 0) {} /** * @template TFlags as int-mask<0, 256, 512> * * @param string $pattern * @param string $subject * @param mixed $matches * @param TFlags $flags * @param-out ( * TFlags is 256 * ? array * : (TFlags is 512 * ? array * : (TFlags is 768 * ? array * : array * ) * ) * ) $matches * @return 1|0|false */ function preg_match($pattern, $subject, &$matches = [], int $flags = 0, int $offset = 0) {} /** * @param string|array $pattern * @param callable(array):string $callback * @param string|array $subject * @param int $count * @param-out 0|positive-int $count * @return ($subject is array ? list|null : string|null) */ function preg_replace_callback($pattern, $callback, $subject, int $limit = -1, &$count = null, int $flags = 0) {} /** * @param string|array $pattern * @param string|array $replacement * @param string|array $subject * @param int $count * @param-out 0|positive-int $count * @return ($subject is array ? list|null : string|null) */ function preg_replace($pattern, $replacement, $subject, int $limit = -1, &$count = null) {} /** * @param string|array $pattern * @param string|array $replacement * @param string|array $subject * @param int $count * @param-out 0|positive-int $count * @return ($subject is array ? list : string|null) */ function preg_filter($pattern, $replacement, $subject, int $limit = -1, &$count = null) {} /** * @param array|string $search * @param array|string $replace * @param array|string $subject * @param-out int $count * @return list|string */ function str_replace($search, $replace, $subject, ?int &$count = null) {} /** * @param array|string $search * @param array|string $replace * @param array|string $subject * @param-out int $count * @return list|string */ function str_ireplace($search, $replace, $subject, ?int &$count = null) {} /** * @template TRead of null|array * @template TWrite of null|array * @template TExcept of null|array * @param TRead $read * @param TWrite $write * @param TExcept $except * @return false|0|positive-int * @param-out (TRead is null ? null : array) $read * @param-out (TWrite is null ? null : array) $write * @param-out (TExcept is null ? null : array) $except */ function stream_select(?array &$read, ?array &$write, ?array &$except, ?int $seconds, ?int $microseconds = null) {} /** * @param resource $stream * @param-out 0|1 $would_block */ function flock($stream, int $operation, mixed &$would_block = null): bool {} /** * @param-out int $error_code * @param-out string $error_message * @return resource|false */ function fsockopen(string $hostname, int $port = -1, ?int &$error_code = null, ?string &$error_message = null, ?float $timeout = null) {} /** * @param-out string $filename * @param-out int $line */ function headers_sent(?string &$filename = null, ?int &$line = null): bool {} /** * @param-out callable-string $callable_name * @return ($value is callable ? true : false) */ function is_callable(mixed $value, bool $syntax_only = false, ?string &$callable_name = null): bool {} /** * @param float|int $num * @return ($num is float ? float : $num is int ? non-negative-int : float|non-negative-int) */ function abs($num) {} /** * @return ($categorize is true ? array> : array) */ function get_defined_constants(bool $categorize = false): array {} */ public $name; /** * @param T|class-string $argument * @throws ReflectionException */ public function __construct($argument) {} /** * @return class-string */ public function getName() : string; /** * @param mixed ...$args * * @return T */ public function newInstance(...$args) {} /** * @param array $args * * @return T */ public function newInstanceArgs(array $args) {} /** * @return T */ public function newInstanceWithoutConstructor(); /** * @return list> */ public function getAttributes(?string $name = null, int $flags = 0) { } } */ public function getNodeType(): string; /** * @param TNodeType $node * @return list */ public function processNode(Node $node, Scope $scope): array; } */ public function getElementsByTagName ($name) {} /** * @param string $namespaceURI * @param string $localName * @return DOMNodeList */ public function getElementsByTagNameNS ($namespaceURI, $localName) {} } class DOMNode { } class DOMElement extends DOMNode { /** @var DOMDocument */ public $ownerDocument; /** * @param string $name * @return DOMNodeList */ public function getElementsByTagName ($name) {} /** * @param string $namespaceURI * @param string $localName * @return DOMNodeList */ public function getElementsByTagNameNS ($namespaceURI, $localName) {} } /** * @template-covariant TNode as DOMNode * @implements Traversable * @implements IteratorAggregate */ class DOMNodeList implements Traversable, IteratorAggregate, Countable { /** * @param int $index * @return TNode|null */ public function item ($index) {} } class DOMXPath { /** * @param string $expression * @param DOMNode|null $contextNode * @param boolean $registerNodeNS * @return DOMNodeList|false */ public function query($expression, $contextNode, $registerNodeNS) {} } class DOMAttr { /** @var DOMDocument */ public $ownerDocument; } class DOMCharacterData { /** @var DOMDocument */ public $ownerDocument; } class DOMDocumentType { /** @var DOMDocument */ public $ownerDocument; } class DOMEntity { /** @var DOMDocument */ public $ownerDocument; } class DOMNotation { /** @var DOMDocument */ public $ownerDocument; } class DOMProcessingInstruction { /** @var DOMDocument */ public $ownerDocument; /** * @var string */ public $target; /** * @var string */ public $data; } /** * @property-read int $length */ class DOMNamedNodeMap { } class DOMText { /** @var string */ public $wholeText; } |null &$read * @param array|null &$write * @param array|null &$except * @param-out ($read is not null ? array : null) $read * @param-out ($write is not null ? array : null) $write * @param-out ($except is not null ? array : null) $except * @return int|false */ function socket_select(?array &$read, ?array &$write, ?array &$except, ?int $seconds, int $microseconds = 0) {} > */ public function getAttributes(?string $name = null, int $flags = 0) { } } > */ public function getAttributes(?string $name = null, int $flags = 0) { } } * @implements \ArrayAccess */ class SplDoublyLinkedList implements \Iterator, \ArrayAccess { /** * @param int $index * @param TValue $newval * @return void */ public function add($index, $newval) {} /** * @return TValue */ public function pop () {} /** * @return TValue */ public function shift () {} /** * @param TValue $value * @return void */ public function push ($value) {} /** * @param TValue $value * @return void */ public function unshift ($value) {} /** * @return TValue */ public function top () {} /** * @return TValue */ public function bottom () {} /** * @param int $offset * @return TValue */ public function offsetGet ($offset) {} } /** * @template TValue * @extends \SplDoublyLinkedList */ class SplQueue extends \SplDoublyLinkedList { /** * @param TValue $value * @return void */ public function enqueue ($value) {} /** * @return TValue */ public function dequeue () {} } /** * @template TPriority * @template TValue * * @implements \Iterator */ class SplPriorityQueue implements \Iterator { /** * @param TPriority $priority1 * @param TPriority $priority2 * @return int */ public function compare ($priority1, $priority2) {} /** * @param TValue $value * @param TPriority $priority * @return true */ public function insert ($value, $priority) {} /** * @return TPriority|TValue|array{priority: TPriority, data: TValue} */ public function top () {} /** * @return TPriority|TValue|array{priority: TPriority, data: TValue} */ public function extract () {} /** * @return TPriority|TValue|array{priority: TPriority, data: TValue} */ public function current () {} } > * @implements IteratorAggregate> * @link https://php.net/manual/en/class.pdostatement.php */ class PDOStatement implements Traversable, IteratorAggregate { /** * @template T of object * @param class-string $class * @param array $ctorArgs * @return false|T */ public function fetchObject($class = \stdClass::class, array $ctorArgs = array()) {} /** * @return array{name: string, table?: string, native_type?: string, len: int, flags: array, precision: int<0, max>, pdo_type: PDO::PARAM_* }|false */ public function getColumnMeta(int $column) {} } , g: int<0, 255>, b: int<0, 255>, a: int<0, 1>} : ($normalized is 1 ? array{r: float, g: float, b: float, a: float} : ($normalized is 2 ? array{r: int<0, 255>, g: int<0, 255>, b: int<0, 255>, a: int<0, 255>} : array{}))) */ public function getColor(int $normalized = 0): array; } * @implements ArrayAccess */ class ArrayObject implements IteratorAggregate, ArrayAccess { /** * @param array|object $input * @param int $flags * @param class-string $iterator_class */ public function __construct($input = null, $flags = 0, $iterator_class = "ArrayIterator") { } /** * @param TValue $value * @return void */ public function append($value) { } /** * @return array */ public function getArrayCopy() { } /** * @param callable(TValue, TValue): int $cmp_function * @return void */ public function uasort($cmp_function) { } /** * @param callable(TKey, TKey): int $cmp_function * @return void */ public function uksort($cmp_function) { } /** * @return ArrayIterator */ public function getIterator() { } /** * @param class-string $iterator_class * @return void */ public function setIteratorClass($iterator_class) { } } /** * @template TValue * @implements Iterator * @implements IteratorAggregate * @implements ArrayAccess */ class SplFixedArray implements Iterator, IteratorAggregate, ArrayAccess, Countable { /** * @template TInput * @param array $array * @return SplFixedArray */ public static function fromArray(array $array, bool $save_indexes = true): SplFixedArray { } /** * @return array */ public function toArray(): array { } } |null &$read * @param array|null &$write * @param array|null &$except * @param-out ($read is not null ? array : null) $read * @param-out ($write is not null ? array : null) $write * @param-out ($except is not null ? array : null) $except */ function socket_select(?array &$read, ?array &$write, ?array &$except, ?int $seconds, int $microseconds = 0): int|false {} $flags * @phpstan-assert-if-true =non-empty-string $json */ function json_validate(string $json, int $depth = 512, int $flags = 0): bool { } */ interface IteratorAggregate extends Traversable { /** * @return Traversable */ public function getIterator(); } /** * @template-covariant TKey * @template-covariant TValue * * @extends Traversable */ interface Iterator extends Traversable { /** * @return TValue */ public function current(); /** * @return TKey */ public function key(); } /** * @template-covariant TKey * @template-covariant TValue * * @extends Iterator */ interface RecursiveIterator extends Iterator { } /** * @template-covariant TKey * @template-covariant TValue * @template TSend * @template-covariant TReturn * * @implements Iterator */ class Generator implements Iterator { /** * @return TReturn */ public function getReturn() {} /** * @param TSend $value * @return TValue */ public function send($value) {} } /** * @implements Traversable * @implements ArrayAccess * @implements Iterator * @implements RecursiveIterator */ class SimpleXMLElement implements Traversable, ArrayAccess, Iterator, RecursiveIterator { /** * @return ($filename is null ? string|false : bool) */ public function asXML(?string $filename = null) { } /** * @return ($filename is null ? string|false : bool) */ public function saveXML(?string $filename = null) { } } /** * @template-covariant TKey * @template-covariant TValue * @extends Iterator */ interface SeekableIterator extends Iterator { } /** * @template TKey of array-key * @template TValue * @implements SeekableIterator * @implements ArrayAccess */ class ArrayIterator implements SeekableIterator, ArrayAccess, Countable { /** * @param array $array * @param int $flags */ public function __construct($array = array(), $flags = 0) { } /** * @param TValue $value * @return void */ public function append($value) { } /** * @return array */ public function getArrayCopy() { } /** * @param callable(TValue, TValue): int $cmp_function * @return void */ public function uasort($cmp_function) { } /** * @param callable(TKey, TKey): int $cmp_function * @return void */ public function uksort($cmp_function) { } } /** * @template T of \RecursiveIterator|\IteratorAggregate * @mixin T */ class RecursiveIteratorIterator { /** * @param T $iterator */ public function __construct( $iterator, int $mode = RecursiveIteratorIterator::LEAVES_ONLY, int $flags = 0 ) { } } /** * @template-covariant TKey * @template-covariant TValue * * @template-extends Iterator */ interface OuterIterator extends Iterator { /** * @return Iterator */ public function getInnerIterator(); } /** * @template-covariant TKey * @template-covariant TValue * @template TIterator as Traversable * * @template-implements OuterIterator * * @mixin TIterator */ class IteratorIterator implements OuterIterator { /** * @param TIterator $iterator */ public function __construct(Traversable $iterator) {} } /** * @template-covariant TKey * @template-covariant TValue * @template TIterator as Traversable * * @template-extends IteratorIterator */ class FilterIterator extends IteratorIterator { } /** * @template-covariant TKey * @template-covariant TValue * @template TIterator as Traversable * * @extends FilterIterator */ class CallbackFilterIterator extends FilterIterator { } /** * @template-covariant TKey * @template-covariant TValue * @template TIterator as Traversable * * @extends CallbackFilterIterator * @implements RecursiveIterator */ class RecursiveCallbackFilterIterator extends CallbackFilterIterator implements RecursiveIterator { /** * @return bool */ public function hasChildren() {} /** * @return RecursiveCallbackFilterIterator */ public function getChildren() {} } /** * @template TKey of array-key * @template TValue * * @template-implements RecursiveIterator * @template-extends ArrayIterator */ class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator { /** * @return RecursiveArrayIterator */ public function getChildren() {} /** * @return bool */ public function hasChildren() {} /** * @return TValue */ public function current() {} /** * @return TKey */ public function key() {} /** * @param callable(TKey, TKey): int $cmp_function * @return void */ public function uksort($cmp_function) { } } /** * @template TKey * @template TValue * @template TIterator as Iterator * * @template-extends IteratorIterator */ class AppendIterator extends IteratorIterator { /** * @param TIterator $iterator * @return void */ public function append(Iterator $iterator) {} /** * @return ArrayIterator */ public function getArrayIterator() {} } /** * @template-covariant TKey * @template-covariant TValue * @template TIterator as Iterator * * @template-extends IteratorIterator */ class NoRewindIterator extends IteratorIterator { /** * @param TIterator $iterator */ public function __construct(Iterator $iterator) {} /** * @return TValue */ public function current() {} /** * @return TKey */ public function key() {} } /** * @template-covariant TKey * @template-covariant TValue * @template TIterator as Iterator * * @template-implements OuterIterator * @template-extends IteratorIterator */ class LimitIterator extends IteratorIterator implements OuterIterator { /** * @param TIterator $iterator */ public function __construct(Iterator $iterator, int $offset = 0, int $count = -1) {} /** * @return TValue */ public function current() {} /** * @return TKey */ public function key() {} } /** * @template-covariant TKey * @template-covariant TValue * @template TIterator as Iterator * * @template-extends IteratorIterator */ class InfiniteIterator extends IteratorIterator { /** * @param TIterator $iterator */ public function __construct(Iterator $iterator) {} /** * @return TValue */ public function current() {} /** * @return TKey */ public function key() {} } /** * @template TKey * @template TValue * @template TIterator as Iterator * * @template-implements OuterIterator * @template-implements ArrayAccess * * @template-extends IteratorIterator */ class CachingIterator extends IteratorIterator implements OuterIterator, ArrayAccess, Countable { const CALL_TOSTRING = 1 ; const CATCH_GET_CHILD = 16 ; const TOSTRING_USE_KEY = 2 ; const TOSTRING_USE_CURRENT = 4 ; const TOSTRING_USE_INNER = 8 ; const FULL_CACHE = 256 ; /** * @param TIterator $iterator * @param int-mask-of $flags */ public function __construct(Iterator $iterator, int $flags = self::CALL_TOSTRING) {} /** * @return TValue */ public function current() {} /** * @return TKey */ public function key() {} /** * @return array */ public function getCache() {} } /** * @template TKey * @template TValue * @template TIterator of Traversable * * @template-extends FilterIterator */ class RegexIterator extends FilterIterator { const MATCH = 0 ; const GET_MATCH = 1 ; const ALL_MATCHES = 2 ; const SPLIT = 3 ; const REPLACE = 4 ; const USE_KEY = 1 ; /** * @param Iterator $iterator * @param self::MATCH|self::GET_MATCH|self::ALL_MATCHES|self::SPLIT|self::REPLACE $mode */ public function __construct(Iterator $iterator, string $regex, int $mode = self::MATCH, int $flags = 0, int $preg_flags = 0) {} /** * @return TValue */ public function current() {} /** * @return TKey */ public function key() {} } /** * @template-implements Iterator */ class EmptyIterator implements Iterator { /** * @return never */ public function current() {} /** * @return never */ public function key() {} /** * @return false */ public function valid() {} } * @implements \Traversable */ class DatePeriod implements \IteratorAggregate, \Traversable { /** * @return TEnd */ public function getEndDate() { } /** * @return TRecurrences */ public function getRecurrences() { } /** * @return TDate */ public function getStartDate(): DateTimeInterface { } } */ class ReflectionEnum extends ReflectionClass { /** * @return (T is BackedEnum ? ReflectionEnumBackedCase[] : ReflectionEnumUnitCase[]) */ public function getCases(): array {} /** * @return (T is BackedEnum ? ReflectionEnumBackedCase : ReflectionEnumUnitCase) * @throws ReflectionException */ public function getCase(string $name): ReflectionEnumUnitCase {} /** * @phpstan-assert-if-true self $this * @phpstan-assert-if-true !null $this->getBackingType() */ public function isBacked(): bool {} } > */ public function getAttributes(?string $name = null, int $flags = 0) { } } ',args?:mixed[],object?:object}> * @throws void */ public function getTrace(); /** * @return string * @throws void */ public function getTraceAsString(); /** * @return null|Throwable * @throws void */ public function getPrevious(); /** * @return string */ public function __toString(); } class Exception implements Throwable { /** * @return string * @throws void */ final public function getMessage(): string {} /** * @return mixed * @throws void */ final public function getCode() {} /** * @return string * @throws void */ final public function getFile(): string {} /** * @return int * @throws void */ final public function getLine(): int {} /** * @return list',args?:mixed[],object?:object}> * @throws void */ final public function getTrace(): array {} /** * @return null|Throwable * @throws void */ final public function getPrevious(): ?Throwable {} /** * @return string * @throws void */ final public function getTraceAsString(): string {} } class Error implements Throwable { /** * @return string * @throws void */ final public function getMessage(): string {} /** * @return mixed * @throws void */ final public function getCode() {} /** * @return string * @throws void */ final public function getFile(): string {} /** * @return int * @throws void */ final public function getLine(): int {} /** * @return list',args?:mixed[],object?:object}> * @throws void */ final public function getTrace(): array {} /** * @return null|Throwable * @throws void */ final public function getPrevious(): ?Throwable {} /** * @return string * @throws void */ final public function getTraceAsString(): string {} } */ public static function cases(): array; } } flags = $flags; } } } if (\PHP_VERSION_ID < 80100 && !class_exists('ReturnTypeWillChange', false)) { #[Attribute(Attribute::TARGET_METHOD)] final class ReturnTypeWillChange { } } if (\PHP_VERSION_ID < 80200 && !class_exists('AllowDynamicProperties', false)) { #[Attribute(Attribute::TARGET_CLASS)] final class AllowDynamicProperties { } } if (\PHP_VERSION_ID < 80200 && !class_exists('SensitiveParameter', false)) { #[Attribute(Attribute::TARGET_PARAMETER)] final class SensitiveParameter { } } $one * @param callable(TReturn, TIn): TReturn $two * @param TReturn $three * * @return TReturn */ function array_reduce( array $one, callable $two, $three = null ) {} /** * @template T of mixed * * @param array $array * @return ($array is non-empty-array ? non-empty-list : list) */ function array_values(array $array): array {} /** * @template TKey as (int|string) * @template T * @template TArray as array * * @param TArray $array * @param callable(T,T):int $callback */ function uasort(array &$array, callable $callback): bool {} /** * @template T * @template TArray as array * * @param TArray $array * @param callable(T,T):int $callback */ function usort(array &$array, callable $callback): bool {} /** * @template TKey as (int|string) * @template T * @template TArray as array * * @param TArray $array * @param callable(TKey,TKey):int $callback */ function uksort(array &$array, callable $callback): bool { } /** * @template TV of mixed * @template TK of mixed * * @param array $one * @param array $two * @param callable(TV, TV): int $three * @return array */ function array_udiff( array $one, array $two, callable $three ): array {} /** * @param array $value * @return ($value is __always-list ? true : false) */ function array_is_list(array $value): bool {} /** * @template TK of array-key * @template TV of mixed * * @param array $one * @param array $two * @param callable(TK, TK): int $three * @return array */ function array_diff_uassoc( array $one, array $two, callable $three ): array {} /** * @template TK of array-key * @template TV of mixed * * @param array $one * @param array $two * @param callable(TK, TK): int $three * @return array */ function array_diff_ukey( array $one, array $two, callable $three ): array {} /** * @template TK of array-key * @template TV of mixed * * @param array $one * @param array $two * @param callable(TK, TK): int $three * @return array */ function array_intersect_uassoc( array $one, array $two, callable $three ): array {} /** * @template TK of array-key * @template TV of mixed * * @param array $one * @param array $two * @param callable(TK, TK): int $three * * @return array */ function array_intersect_ukey( array $one, array $two, callable $three ): array {} /** * @template TK of array-key * @template TV of mixed * * @param array $one * @param array $two * @param callable(TV, TV): int $three * * @return array */ function array_udiff_assoc( array $one, array $two, callable $three ): array {} /** * @template TK of array-key * @template TV of mixed * * @param array $one * @param array $two * @param callable(TV, TV): int $three * @param callable(TK, TK): int $four * @return array */ function array_udiff_uassoc( array $one, array $two, callable $three, callable $four ): array {} /** * @template TK of array-key * @template TV of mixed * * @param array $one * @param array $two * @param callable(TV, TV): int $three * @return array */ function array_uintersect_assoc( array $one, array $two, callable $three, ): array {} /** * @template TK of array-key * @template TV of mixed * * @param array $one * @param array $two * @param callable(TV, TV): int $three * @param callable(TK, TK): int $four * @return array */ function array_uintersect_uassoc( array $one, array $two, callable $three, callable $four ): array {} /** * @template TK of array-key * @template TV of mixed * * @param array $one * @param array $two * @param callable(TV, TV): int $three * @return array */ function array_uintersect( array $one, array $two, callable $three, ): array {} > */ public function getAttributes(?string $name = null, int $flags = 0) { } } unregister(); $composerAutoloadFiles = $GLOBALS['__composer_autoload_files']; if (!\array_key_exists('e88992873b7765f9b5710cab95ba5dd7', $composerAutoloadFiles) || !\array_key_exists('3e76f7f02b41af8cea96018933f6b7e3', $composerAutoloadFiles) || !\array_key_exists('a4a119a56e50fbb293281d9a48007e0e', $composerAutoloadFiles) || !\array_key_exists('0e6d7bf4a5811bfa5cf40c5ccd6fae6a', $composerAutoloadFiles) || !\array_key_exists('e69f7f6ee287b969198c3c9d6777bd38', $composerAutoloadFiles) || !\array_key_exists('0d59ee240a4cd96ddbb4ff164fccea4d', $composerAutoloadFiles) || !\array_key_exists('b686b8e46447868025a15ce5d0cb2634', $composerAutoloadFiles) || !\array_key_exists('8825ede83f2f289127722d4e842cf7e8', $composerAutoloadFiles) || !\array_key_exists('23c18046f52bef3eea034657bafda50f', $composerAutoloadFiles)) { echo "Composer autoloader changed\n"; exit(1); } // empty the global variable so that unprefixed functions from user-space can be loaded $GLOBALS['__composer_autoload_files'] = [ // fix unprefixed Hoa namespace - files already loaded 'e88992873b7765f9b5710cab95ba5dd7' => \true, '3e76f7f02b41af8cea96018933f6b7e3' => \true, // vendor/symfony/polyfill-php80/bootstrap.php 'a4a119a56e50fbb293281d9a48007e0e' => \true, // vendor/symfony/polyfill-mbstring/bootstrap.php '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => \true, // vendor/symfony/polyfill-intl-normalizer/bootstrap.php 'e69f7f6ee287b969198c3c9d6777bd38' => \true, // vendor/symfony/polyfill-php73/bootstrap.php '0d59ee240a4cd96ddbb4ff164fccea4d' => \true, // vendor/symfony/polyfill-php74/bootstrap.php 'b686b8e46447868025a15ce5d0cb2634' => \true, // vendor/symfony/polyfill-intl-grapheme/bootstrap.php '8825ede83f2f289127722d4e842cf7e8' => \true, // vendor/symfony/polyfill-php81/bootstrap.php '23c18046f52bef3eea034657bafda50f' => \true, ]; $autoloaderInWorkingDirectory = $vendorDirectory . '/autoload.php'; $composerAutoloaderProjectPaths = []; /** @var array|false $autoloadFunctionsBefore */ $autoloadFunctionsBefore = \spl_autoload_functions(); if (@\is_file($autoloaderInWorkingDirectory)) { $composerAutoloaderProjectPaths[] = \dirname($autoloaderInWorkingDirectory, 2); require_once $autoloaderInWorkingDirectory; } $path = \dirname(__DIR__, 3) . '/autoload.php'; if (!\extension_loaded('phar')) { if (@\is_file($path)) { $composerAutoloaderProjectPaths[] = \dirname($path, 2); require_once $path; } } else { $pharPath = \Phar::running(\false); if ($pharPath === '') { if (@\is_file($path)) { $composerAutoloaderProjectPaths[] = \dirname($path, 2); require_once $path; } } else { $path = \dirname($pharPath, 3) . '/autoload.php'; if (@\is_file($path)) { $composerAutoloaderProjectPaths[] = \dirname($path, 2); require_once $path; } } } /** @var array|false $autoloadFunctionsAfter */ $autoloadFunctionsAfter = \spl_autoload_functions(); if ($autoloadFunctionsBefore !== \false && $autoloadFunctionsAfter !== \false) { $newAutoloadFunctions = []; foreach ($autoloadFunctionsAfter as $after) { if (\is_array($after) && \count($after) > 0) { if (\is_object($after[0]) && \get_class($after[0]) === \Composer\Autoload\ClassLoader::class) { continue; } if ($after[0] === 'PHPStan\\PharAutoloader') { continue; } } foreach ($autoloadFunctionsBefore as $before) { if ($after === $before) { continue 2; } } $newAutoloadFunctions[] = $after; } $GLOBALS['__phpstanAutoloadFunctions'] = $newAutoloadFunctions; } $devOrPharLoader->register(\true); $application = new \_PHPStan_c2fbb2235\Symfony\Component\Console\Application('PHPStan - PHP Static Analysis Tool', ComposerHelper::getPhpStanVersion()); $application->setDefaultCommand('analyse'); ProgressBar::setFormatDefinition('file_download', ' [%bar%] %percent:3s%% %fileSize%'); $composerAutoloaderProjectPaths = \array_map(function (string $s) : string { return \str_replace(\DIRECTORY_SEPARATOR, '/', $s); }, $composerAutoloaderProjectPaths); $reversedComposerAutoloaderProjectPaths = \array_values(\array_unique(\array_reverse($composerAutoloaderProjectPaths))); $application->add(new AnalyseCommand($reversedComposerAutoloaderProjectPaths, $analysisStartTime)); $application->add(new WorkerCommand($reversedComposerAutoloaderProjectPaths)); $application->add(new ClearResultCacheCommand($reversedComposerAutoloaderProjectPaths)); $application->add(new FixerWorkerCommand($reversedComposerAutoloaderProjectPaths)); $application->add(new DumpParametersCommand($reversedComposerAutoloaderProjectPaths)); $application->add(new DiagnoseCommand($reversedComposerAutoloaderProjectPaths)); $application->run(); })(); [ 'FFI::addr' => ['FFI\CData', 'ptr'=>'FFI\CData'], 'FFI::alignof' => ['int', 'ptr'=>'mixed'], 'FFI::arrayType' => ['FFI\CType', 'type'=>'string|FFI\CType', 'dims'=>'array'], 'FFI::cast' => ['FFI\CData', 'type'=>'string|FFI\CType', 'ptr'=>''], 'FFI::cdef' => ['FFI', 'code='=>'string', 'lib='=>'?string'], 'FFI::free' => ['void', 'ptr'=>'FFI\CData'], 'FFI::load' => ['FFI', 'filename'=>'string'], 'FFI::memcmp' => ['int', 'ptr1'=>'FFI\CData|string', 'ptr2'=>'FFI\CData|string', 'size'=>'int'], 'FFI::memcpy' => ['void', 'dst'=>'FFI\CData', 'src'=>'string|FFI\CData', 'size'=>'int'], 'FFI::memset' => ['void', 'ptr'=>'FFI\CData', 'ch'=>'int', 'size'=>'int'], 'FFI::new' => ['FFI\CData', 'type'=>'string|FFI\CType', 'owned='=>'bool', 'persistent='=>'bool'], 'FFI::scope' => ['FFI', 'scope_name'=>'string'], 'FFI::sizeof' => ['int', 'ptr'=>'FFI\CData|FFI\CType'], 'FFI::string' => ['string', 'ptr'=>'FFI\CData', 'size='=>'int'], 'FFI::typeof' => ['FFI\CType', 'ptr'=>'FFI\CData'], 'FFI::type' => ['FFI\CType', 'type'=>'string'], 'fread' => ['string|false', 'fp'=>'resource', 'length'=>'positive-int'], 'get_mangled_object_vars' => ['array', 'obj'=>'object'], 'mb_str_split' => ['list|false', 'str'=>'string', 'split_length='=>'int', 'encoding='=>'string'], 'password_algos' => ['list'], 'password_needs_rehash' => ['bool', 'hash'=>'string', 'algo'=>'string|null', 'options='=>'array'], 'preg_replace_callback' => ['string|array|null', 'regex'=>'string|array', 'callback'=>'callable(array):string', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int', 'flags='=>'int'], 'preg_replace_callback_array' => ['string|array|null', 'pattern'=>'array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int', 'flags='=>'int'], 'sapi_windows_set_ctrl_handler' => ['bool', 'callable'=>'callable(int):void', 'add='=>'bool'], 'ReflectionProperty::getType' => ['?ReflectionType'], 'ReflectionProperty::hasType' => ['bool'], 'ReflectionProperty::isInitialized' => ['bool', 'object='=>'?object'], 'ReflectionReference::fromArrayElement' => ['?ReflectionReference', 'array'=>'array', 'key'=>'int|string'], 'ReflectionReference::getId' => ['string'], 'SQLite3Stmt::getSQL' => ['string', 'expanded='=>'bool'], 'strip_tags' => ['string', 'str'=>'string', 'allowable_tags='=>'string|array'], 'WeakReference::create' => ['WeakReference', 'referent'=>'object'], 'WeakReference::get' => ['?object'], 'proc_open' => ['resource|false', 'command'=>'string|list', 'descriptorspec'=>'array', '&w_pipes'=>'resource[]', 'cwd='=>'?string', 'env='=>'?array', 'other_options='=>'array'], ], 'old' => [ 'implode\'2' => ['string', 'pieces'=>'array', 'glue'=>'string'], ], ]; ' => [', ''=>''] * alternative signature for the same function * '' => [', ''=>''] * * A '&' in front of the means the arg is always passed by reference. * (i.e. ReflectionParameter->isPassedByReference()) * This was previously only used in cases where the function actually created the * variable in the local scope. * Some reference arguments will have prefixes in to indicate the way the argument is used. * Currently, the only prefixes with meaning are 'rw_' (read-write) and 'w_' (write). * Those prefixes don't mean anything for non-references. * Code using these signatures should remove those prefixes from messages rendered to the user. * 1. '&rw_' indicates that a parameter with a value is expected to be passed in, and may be modified. * Phan will warn if the variable has an incompatible type, or is undefined. * 2. '&w_' indicates that a parameter is expected to be passed in, and the value will be ignored, and may be overwritten. * 3. The absence of a prefix is treated by Phan the same way as having the prefix 'w_' (Some may be changed to 'rw_name'). These will have prefixes added later. * * So, for functions like sort() where technically the arg is by-ref, * indicate the reference param's signature by-ref and read-write, * as `'&rw_array'=>'array'` * so that Phan won't create it in the local scope * * However, for a function like preg_match() where the 3rd arg is an array of sub-pattern matches (and optional), * this arg needs to be marked as by-ref and write-only, as `'&w_matches='=>'array'`. * * A '=' following the indicates this arg is optional. * * The can begin with '...' to indicate the arg is variadic. * '...args=' indicates it is both variadic and optional. * * Some reference arguments will have prefixes in to indicate the way the argument is used. * Currently, the only prefixes with meaning are 'rw_' and 'w_'. * Code using these signatures should remove those prefixes from messages rendered to the user. * 1. '&rw_name' indicates that a parameter with a value is expected to be passed in, and may be modified. * 2. '&w_name' indicates that a parameter is expected to be passed in, and the value will be ignored, and may be overwritten. * * Sources of stub info: * * 1. Reflection * 2. docs.php.net's SVN repo or website, and examples (See internal/internalsignatures.php) * 3. Various websites documenting individual extensions * 4. PHPStorm stubs (For anything missing from the above sources) * See internal/internalsignatures.php */ return [ '_' => ['string', 'message'=>'string'], 'abs' => ['float|0|positive-int', 'num'=>'int|float'], 'accelerator_get_configuration' => ['array'], 'accelerator_get_scripts' => ['array'], 'accelerator_get_status' => ['array', 'fetch_scripts'=>'bool'], 'accelerator_reset' => [''], 'accelerator_set_status' => ['void', 'status'=>''], 'acos' => ['float', 'number'=>'float'], 'acosh' => ['float', 'number'=>'float'], 'addcslashes' => ['string', 'str'=>'string', 'charlist'=>'string'], 'addslashes' => ['string', 'str'=>'string'], 'AMQPChannel::__construct' => ['void', 'connection'=>'AMQPConnection'], 'AMQPChannel::basicRecover' => ['void', 'requeue='=>'bool'], 'AMQPChannel::commitTransaction' => ['void'], 'AMQPChannel::getChannelId' => ['int<1, 65535>'], 'AMQPChannel::getConnection' => ['AMQPConnection'], 'AMQPChannel::getPrefetchCount' => ['int<0, 65535>'], 'AMQPChannel::getPrefetchSize' => ['int<0, max>'], 'AMQPChannel::isConnected' => ['bool'], 'AMQPChannel::qos' => ['void', 'size'=>'int', 'count'=>'int', 'global='=>'bool'], 'AMQPChannel::rollbackTransaction' => ['void'], 'AMQPChannel::setPrefetchCount' => ['void', 'count'=>'int'], 'AMQPChannel::setPrefetchSize' => ['void', 'size'=>'int'], 'AMQPChannel::startTransaction' => ['void'], 'AMQPConnection::__construct' => ['void', 'credentials='=>'array'], 'AMQPConnection::connect' => ['void'], 'AMQPConnection::disconnect' => ['void'], 'AMQPConnection::getHost' => ['string'], 'AMQPConnection::getLogin' => ['string'], 'AMQPConnection::getMaxChannels' => ['int<1, 65535>'], 'AMQPConnection::getPassword' => ['string'], 'AMQPConnection::getPort' => ['int<1, 65535>'], 'AMQPConnection::getReadTimeout' => ['float'], 'AMQPConnection::getTimeout' => ['float'], 'AMQPConnection::getUsedChannels' => ['int<1, 65535>'], 'AMQPConnection::getVhost' => ['string'], 'AMQPConnection::getWriteTimeout' => ['float'], 'AMQPConnection::isConnected' => ['bool'], 'AMQPConnection::isPersistent' => ['bool'], 'AMQPConnection::pconnect' => ['void'], 'AMQPConnection::pdisconnect' => ['void'], 'AMQPConnection::preconnect' => ['void'], 'AMQPConnection::reconnect' => ['void'], 'AMQPConnection::setHost' => ['void', 'host'=>'string'], 'AMQPConnection::setLogin' => ['void', 'login'=>'string'], 'AMQPConnection::setPassword' => ['void', 'password'=>'string'], 'AMQPConnection::setPort' => ['void', 'port'=>'int'], 'AMQPConnection::setReadTimeout' => ['void', 'timeout'=>'int'], 'AMQPConnection::setTimeout' => ['void', 'timeout'=>'int'], 'AMQPConnection::setVhost' => ['void', 'vhost'=>'string'], 'AMQPConnection::setWriteTimeout' => ['void', 'timeout'=>'int'], 'AMQPEnvelope::getAppId' => ['string|null'], 'AMQPEnvelope::getBody' => ['string'], 'AMQPEnvelope::getContentEncoding' => ['string|null'], 'AMQPEnvelope::getContentType' => ['string|null'], 'AMQPEnvelope::getCorrelationId' => ['string|null'], 'AMQPEnvelope::getDeliveryMode' => ['int'], 'AMQPEnvelope::getDeliveryTag' => ['int|null'], 'AMQPEnvelope::getExchangeName' => ['string|null'], 'AMQPEnvelope::getExpiration' => ['string|null'], 'AMQPEnvelope::getHeader' => ['mixed', 'headerName'=>'string'], 'AMQPEnvelope::getHeaders' => ['array'], 'AMQPEnvelope::getMessageId' => ['string|null'], 'AMQPEnvelope::getPriority' => ['int<0, max>'], 'AMQPEnvelope::getReplyTo' => ['string|null'], 'AMQPEnvelope::getRoutingKey' => ['string'], 'AMQPEnvelope::getTimestamp' => ['int|null'], 'AMQPEnvelope::getType' => ['string|null'], 'AMQPEnvelope::getUserId' => ['string|null'], 'AMQPEnvelope::isRedelivery' => ['bool'], 'AMQPExchange::__construct' => ['void', 'channel'=>'AMQPChannel'], 'AMQPExchange::bind' => ['void', 'exchangeName'=>'string', 'routingKey='=>'string|null', 'arguments='=>'array'], 'AMQPExchange::declareExchange' => ['void'], 'AMQPExchange::delete' => ['void', 'exchangeName='=>'string', 'flags='=>'int'], 'AMQPExchange::getArgument' => ['scalar|null', 'argumentName'=>'string'], 'AMQPExchange::getArguments' => ['array'], 'AMQPExchange::getChannel' => ['AMQPChannel'], 'AMQPExchange::getConnection' => ['AMQPConnection'], 'AMQPExchange::getFlags' => ['int'], 'AMQPExchange::getName' => ['string|null'], 'AMQPExchange::getType' => ['string|null'], 'AMQPExchange::publish' => ['void', 'message'=>'string', 'routingKey='=>'string|null', 'flags='=>'int|null', 'header='=>'array'], 'AMQPExchange::setArgument' => ['void', 'argumentName'=>'string', 'argumentValue'=>'scalar|null'], 'AMQPExchange::setArguments' => ['void', 'arguments'=>'array'], 'AMQPExchange::setFlags' => ['void', 'flags'=>'int|null'], 'AMQPExchange::setName' => ['void', 'exchangeName'=>'string|null'], 'AMQPExchange::setType' => ['void', 'exchangeType'=>'string|null'], 'AMQPExchange::unbind' => ['void', 'exchangeName'=>'string', 'routingKey='=>'string|null', 'arguments='=>'array'], 'AMQPQueue::__construct' => ['void', 'channel'=>'AMQPChannel'], 'AMQPQueue::ack' => ['void', 'deliveryTag'=>'int', 'flags='=>'int|null'], 'AMQPQueue::bind' => ['void', 'exchangeName'=>'string', 'routingKey='=>'string|null', 'arguments='=>'array'], 'AMQPQueue::cancel' => ['void', 'consumerTag='=>'string'], 'AMQPQueue::consume' => ['void', 'callback='=>'null|callable(AMQPEnvelope, AMQPQueue): mixed', 'flags='=>'int|null', 'consumerTag='=>'string|null'], 'AMQPQueue::declareQueue' => ['int'], 'AMQPQueue::delete' => ['int', 'flags='=>'int|null'], 'AMQPQueue::get' => ['AMQPEnvelope|null', 'flags='=>'int|null'], 'AMQPQueue::getArgument' => ['scalar|null|array|AMQPValue|AMQPDecimal|AMQPTimestamp', 'argumentName'=>'string'], 'AMQPQueue::getArguments' => ['array'], 'AMQPQueue::getChannel' => ['AMQPChannel'], 'AMQPQueue::getConnection' => ['AMQPConnection'], 'AMQPQueue::getFlags' => ['int'], 'AMQPQueue::getName' => ['string|null'], 'AMQPQueue::nack' => ['void', 'deliveryTag'=>'int', 'flags='=>'int|null'], 'AMQPQueue::purge' => ['int'], 'AMQPQueue::reject' => ['void', 'deliveryTag'=>'int', 'flags='=>'int|null'], 'AMQPQueue::setArgument' => ['void', 'argumentName'=>'string', 'argumentValue'=>'scalar|null|array|AMQPValue|AMQPDecimal|AMQPTimestamp'], 'AMQPQueue::setArguments' => ['void', 'arguments'=>'array'], 'AMQPQueue::setFlags' => ['void', 'flags'=>'int|null'], 'AMQPQueue::setName' => ['void', 'name'=>'string'], 'AMQPQueue::unbind' => ['void', 'exchangeName'=>'string', 'routingKey='=>'string|null', 'arguments='=>'array'], 'apache_child_terminate' => ['bool'], 'apache_get_modules' => ['array'], 'apache_get_version' => ['string|false'], 'apache_getenv' => ['string|false', 'variable'=>'string', 'walk_to_top='=>'bool'], 'apache_lookup_uri' => ['object|false', 'filename'=>'string'], 'apache_note' => ['string|false', 'note_name'=>'string', 'note_value='=>'string'], 'apache_request_headers' => ['array|false'], 'apache_reset_timeout' => ['bool'], 'apache_response_headers' => ['array|false'], 'apache_setenv' => ['bool', 'variable'=>'string', 'value'=>'string', 'walk_to_top='=>'bool'], 'apc_add' => ['bool', 'key'=>'string', 'var'=>'mixed', 'ttl='=>'int'], 'apc_add\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'apc_bin_dump' => ['string', 'files='=>'array', 'user_vars='=>'array'], 'apc_bin_dumpfile' => ['int', 'files'=>'array', 'user_vars'=>'array', 'filename'=>'string', 'flags='=>'int', 'context='=>'resource'], 'apc_bin_load' => ['bool', 'data'=>'string', 'flags='=>'int'], 'apc_bin_loadfile' => ['bool', 'filename'=>'string', 'context='=>'resource', 'flags='=>'int'], 'apc_cache_info' => ['array', 'cache_type='=>'string', 'limited='=>'bool'], 'apc_cas' => ['bool', 'key'=>'string', 'old'=>'int', 'new'=>'int'], 'apc_clear_cache' => ['bool', 'cache_type='=>'string'], 'apc_compile_file' => ['mixed', 'filename'=>'string', 'atomic='=>'bool'], 'apc_dec' => ['int', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool'], 'apc_define_constants' => ['bool', 'key'=>'string', 'constants'=>'array', 'case_sensitive='=>'bool'], 'apc_delete' => ['bool', 'key'=>'string|string[]|APCIterator'], 'apc_delete_file' => ['mixed', 'keys'=>'mixed'], 'apc_exists' => ['bool', 'keys'=>'string'], 'apc_exists\'1' => ['array', 'keys'=>'string[]'], 'apc_fetch' => ['mixed', 'key'=>'mixed', '&w_success='=>'bool'], 'apc_inc' => ['int', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool'], 'apc_load_constants' => ['bool', 'key'=>'string', 'case_sensitive='=>'bool'], 'apc_sma_info' => ['array', 'limited='=>'bool'], 'apc_store' => ['bool', 'key'=>'string', 'var'=>'', 'ttl='=>'int'], 'apc_store\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'APCIterator::__construct' => ['void', 'cache'=>'string', 'search='=>'', 'format='=>'int', 'chunk_size='=>'int', 'list='=>'int'], 'APCIterator::current' => ['mixed'], 'APCIterator::getTotalCount' => ['int'], 'APCIterator::getTotalHits' => ['int'], 'APCIterator::getTotalSize' => ['int'], 'APCIterator::key' => ['string'], 'APCIterator::next' => ['void'], 'APCIterator::rewind' => ['void'], 'APCIterator::valid' => ['bool'], 'apcu_add' => ['bool', 'key'=>'string', 'var'=>'', 'ttl='=>'int'], 'apcu_add\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'apcu_cache_info' => ['array', 'limited='=>'bool'], 'apcu_cas' => ['bool', 'key'=>'string', 'old'=>'int', 'new'=>'int'], 'apcu_clear_cache' => ['bool'], 'apcu_dec' => ['int', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool', 'ttl='=>'int'], 'apcu_delete' => ['bool', 'key'=>'string|APCuIterator'], 'apcu_delete\'1' => ['list', 'key'=>'string[]'], 'apcu_entry' => ['mixed', 'key'=>'string', 'generator'=>'callable', 'ttl='=>'int'], 'apcu_exists' => ['bool', 'keys'=>'string'], 'apcu_exists\'1' => ['array', 'keys'=>'string[]'], 'apcu_fetch' => ['mixed', 'key'=>'string|string[]', '&w_success='=>'bool'], 'apcu_inc' => ['int', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool', 'ttl='=>'int'], 'apcu_sma_info' => ['array', 'limited='=>'bool'], 'apcu_store' => ['bool', 'key'=>'string', 'var='=>'', 'ttl='=>'int'], 'apcu_store\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'APCuIterator::__construct' => ['void', 'search='=>'string|string[]|null', 'format='=>'int', 'chunk_size='=>'int', 'list='=>'int'], 'APCuIterator::current' => ['mixed'], 'APCuIterator::getTotalCount' => ['int'], 'APCuIterator::getTotalHits' => ['int'], 'APCuIterator::getTotalSize' => ['int'], 'APCuIterator::key' => ['string'], 'APCuIterator::next' => ['void'], 'APCuIterator::rewind' => ['void'], 'APCuIterator::valid' => ['bool'], 'apd_breakpoint' => ['bool', 'debug_level'=>'int'], 'apd_callstack' => ['array'], 'apd_clunk' => ['void', 'warning'=>'string', 'delimiter='=>'string'], 'apd_continue' => ['bool', 'debug_level'=>'int'], 'apd_croak' => ['void', 'warning'=>'string', 'delimiter='=>'string'], 'apd_dump_function_table' => ['void'], 'apd_dump_persistent_resources' => ['array'], 'apd_dump_regular_resources' => ['array'], 'apd_echo' => ['bool', 'output'=>'string'], 'apd_get_active_symbols' => ['array'], 'apd_set_pprof_trace' => ['string', 'dump_directory='=>'string', 'fragment='=>'string'], 'apd_set_session' => ['void', 'debug_level'=>'int'], 'apd_set_session_trace' => ['void', 'debug_level'=>'int', 'dump_directory='=>'string'], 'apd_set_session_trace_socket' => ['bool', 'tcp_server'=>'string', 'socket_type'=>'int', 'port'=>'int', 'debug_level'=>'int'], 'AppendIterator::__construct' => ['void'], 'AppendIterator::append' => ['void', 'iterator'=>'Iterator'], 'AppendIterator::current' => ['mixed'], 'AppendIterator::getArrayIterator' => ['ArrayIterator'], 'AppendIterator::getInnerIterator' => ['iterator'], 'AppendIterator::getIteratorIndex' => ['int'], 'AppendIterator::key' => ['mixed'], 'AppendIterator::next' => ['void'], 'AppendIterator::rewind' => ['void'], 'AppendIterator::valid' => ['bool'], 'array_change_key_case' => ['array', 'input'=>'array', 'case='=>'int'], 'array_chunk' => ['list', 'input'=>'array', 'size'=>'positive-int', 'preserve_keys='=>'bool'], 'array_column' => ['array', 'array'=>'array', 'column_key'=>'mixed', 'index_key='=>'mixed'], 'array_combine' => ['array|false', 'keys'=>'array', 'values'=>'array'], 'array_count_values' => ['array', 'input'=>'array'], 'array_diff' => ['array', 'arr1'=>'array', 'arr2'=>'array', '...args='=>'array'], 'array_diff_assoc' => ['array', 'arr1'=>'array', 'arr2'=>'array', '...args='=>'array'], 'array_diff_key' => ['array', 'arr1'=>'array', 'arr2'=>'array', '...args='=>'array'], 'array_diff_uassoc' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'data_comp_func'=>'callable(mixed,mixed):int'], 'array_diff_uassoc\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable'], 'array_diff_ukey' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'key_comp_func'=>'callable(mixed,mixed):int'], 'array_diff_ukey\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_fill' => ['array', 'start_key'=>'int', 'num'=>'int', 'val'=>'mixed'], 'array_fill_keys' => ['array', 'keys'=>'array', 'val'=>'mixed'], 'array_filter' => ['array', 'input'=>'array', 'callback='=>'callable(mixed,mixed):bool|callable(mixed):bool', 'flag='=>'int'], 'array_flip' => ['array', 'input'=>'array'], 'array_intersect' => ['array', 'arr1'=>'array', 'arr2'=>'array', '...args='=>'array'], 'array_intersect_assoc' => ['array', 'arr1'=>'array', 'arr2'=>'array', '...args='=>'array'], 'array_intersect_key' => ['array', 'arr1'=>'array', 'arr2'=>'array', '...args='=>'array'], 'array_intersect_uassoc' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'key_compare_func'=>'callable(mixed,mixed):int'], 'array_intersect_uassoc\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest'=>'array|callable'], 'array_intersect_ukey' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'key_compare_func'=>'callable(mixed,mixed):int'], 'array_intersect_ukey\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest'=>'array|callable(mixed,mixed):int'], 'array_key_exists' => ['bool', 'key'=>'string|int', 'search'=>'array'], 'array_key_first' => ['int|string|null', 'array'=>'array'], 'array_key_last' => ['int|string|null', 'array'=>'array'], 'array_keys' => ['list', 'input'=>'array', 'search_value='=>'mixed', 'strict='=>'bool'], 'array_map' => ['array', 'callback'=>'?callable', 'array'=>'array', '...args='=>'array'], 'array_merge' => ['array', 'arr1'=>'array', '...args='=>'array'], 'array_merge_recursive' => ['array', 'arr1'=>'array', '...args='=>'array'], 'array_multisort' => ['bool', 'array1'=>'array', 'array1_sort_order='=>'array|int', 'array1_sort_flags='=>'array|int', '...args='=>'array|int'], 'array_pad' => ['array', 'input'=>'array', 'pad_size'=>'int', 'pad_value'=>'mixed'], 'array_pop' => ['mixed', '&rw_stack'=>'array'], 'array_product' => ['int|float', 'input'=>'array'], 'array_push' => ['int', '&rw_stack'=>'array', 'var'=>'mixed', '...vars='=>'mixed'], 'array_rand' => ['int|string|array|array', 'input'=>'array', 'num_req'=>'int'], 'array_rand\'1' => ['int|string', 'input'=>'array'], 'array_reduce' => ['mixed', 'input'=>'array', 'callback'=>'callable(mixed,mixed):mixed', 'initial='=>'mixed'], 'array_replace' => ['array', 'arr1'=>'array', 'arr2'=>'array', '...args='=>'array'], 'array_replace_recursive' => ['array', 'arr1'=>'array', 'arr2'=>'array', '...args='=>'array'], 'array_reverse' => ['array', 'input'=>'array', 'preserve='=>'bool'], 'array_search' => ['int|string|false', 'needle'=>'mixed', 'haystack'=>'array', 'strict='=>'bool'], 'array_shift' => ['mixed', '&rw_stack'=>'array'], 'array_slice' => ['array', 'input'=>'array', 'offset'=>'int', 'length='=>'?int', 'preserve_keys='=>'bool'], 'array_splice' => ['array', '&rw_input'=>'array', 'offset'=>'int', 'length='=>'int', 'replacement='=>'mixed'], 'array_sum' => ['int|float', 'input'=>'array'], 'array_udiff' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'data_comp_func'=>'callable(mixed,mixed):int'], 'array_udiff\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_udiff_assoc' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'key_comp_func'=>'callable(mixed,mixed):int'], 'array_udiff_assoc\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_udiff_uassoc' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'data_comp_func'=>'callable', 'key_comp_func'=>'callable(mixed,mixed):int'], 'array_udiff_uassoc\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', 'arg5'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_uintersect' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int'], 'array_uintersect\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_uintersect_assoc' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int'], 'array_uintersect_assoc\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_uintersect_uassoc' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int', 'key_compare_func'=>'callable(mixed,mixed):int'], 'array_uintersect_uassoc\'1' => ['array', 'arr1'=>'array', 'arr2'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', 'arg5'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'], 'array_unique' => ['array', 'array'=>'array', 'flags='=>'int'], 'array_unshift' => ['positive-int', '&rw_stack'=>'array', 'var'=>'mixed', '...vars='=>'mixed'], 'array_values' => ['list', 'input'=>'array'], 'array_walk' => ['bool', '&rw_input'=>'array|object', 'callback'=>'callable', 'userdata='=>'mixed'], 'array_walk_recursive' => ['bool', '&rw_input'=>'array|object', 'callback'=>'callable', 'userdata='=>'mixed'], 'ArrayAccess::offsetExists' => ['bool', 'offset'=>'mixed'], 'ArrayAccess::offsetGet' => ['mixed', 'offset'=>'mixed'], 'ArrayAccess::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'ArrayAccess::offsetUnset' => ['void', 'offset'=>'mixed'], 'ArrayIterator::__construct' => ['void', 'array='=>'array|object', 'flags='=>'int'], 'ArrayIterator::append' => ['void', 'value'=>'mixed'], 'ArrayIterator::asort' => ['void'], 'ArrayIterator::count' => ['0|positive-int'], 'ArrayIterator::current' => ['mixed'], 'ArrayIterator::getArrayCopy' => ['array'], 'ArrayIterator::getFlags' => ['int'], 'ArrayIterator::key' => ['int|string|false'], 'ArrayIterator::ksort' => ['void'], 'ArrayIterator::natcasesort' => ['void'], 'ArrayIterator::natsort' => ['void'], 'ArrayIterator::next' => ['void'], 'ArrayIterator::offsetExists' => ['bool', 'index'=>'string|int|bool|null'], 'ArrayIterator::offsetGet' => ['mixed', 'index'=>'string|int|bool|null'], 'ArrayIterator::offsetSet' => ['void', 'index'=>'string|int|bool|null', 'newval'=>'mixed'], 'ArrayIterator::offsetUnset' => ['void', 'index'=>'string|int|bool|null'], 'ArrayIterator::rewind' => ['void'], 'ArrayIterator::seek' => ['void', 'position'=>'int'], 'ArrayIterator::serialize' => ['string'], 'ArrayIterator::setFlags' => ['void', 'flags'=>'string'], 'ArrayIterator::uasort' => ['void', 'callback'=>'callable(mixed,mixed):int'], 'ArrayIterator::uksort' => ['void', 'callback'=>'callable(array-key,array-key):int'], 'ArrayIterator::unserialize' => ['void', 'serialized'=>'string'], 'ArrayIterator::valid' => ['bool'], 'ArrayObject::__construct' => ['void', 'input='=>'array|object', 'flags='=>'int', 'iterator_class='=>'class-string'], 'ArrayObject::append' => ['void', 'value'=>'mixed'], 'ArrayObject::asort' => ['void'], 'ArrayObject::count' => ['0|positive-int'], 'ArrayObject::exchangeArray' => ['array', 'ar'=>'mixed'], 'ArrayObject::getArrayCopy' => ['array'], 'ArrayObject::getFlags' => ['int'], 'ArrayObject::getIterator' => ['ArrayIterator'], 'ArrayObject::getIteratorClass' => ['string'], 'ArrayObject::ksort' => ['void'], 'ArrayObject::natcasesort' => ['void'], 'ArrayObject::natsort' => ['void'], 'ArrayObject::offsetExists' => ['bool', 'index'=>'mixed'], 'ArrayObject::offsetGet' => ['mixed', 'index'=>'mixed'], 'ArrayObject::offsetSet' => ['void', 'index'=>'mixed', 'newval'=>'mixed'], 'ArrayObject::offsetUnset' => ['void', 'index'=>'mixed'], 'ArrayObject::serialize' => ['string'], 'ArrayObject::setFlags' => ['void', 'flags'=>'int'], 'ArrayObject::setIteratorClass' => ['void', 'iterator_class'=>'string'], 'ArrayObject::uasort' => ['void', 'callback'=>'callable'], 'ArrayObject::uksort' => ['void', 'callback'=>'callable(array-key,array-key):int'], 'ArrayObject::unserialize' => ['void', 'serialized'=>'string'], 'arsort' => ['bool', '&rw_array_arg'=>'array', 'sort_flags='=>'int'], 'asin' => ['float', 'number'=>'float'], 'asinh' => ['float', 'number'=>'float'], 'asort' => ['bool', '&rw_array_arg'=>'array', 'sort_flags='=>'int'], 'assert' => ['bool', 'assertion'=>'string|bool', 'description='=>'string|Throwable|null'], 'assert_options' => ['mixed', 'what'=>'int', 'value='=>'mixed'], 'ast\get_kind_name' => ['string', 'kind'=>'int'], 'ast\get_metadata' => ['array'], 'ast\get_supported_versions' => ['array', 'exclude_deprecated='=>'bool'], 'ast\kind_uses_flags' => ['bool', 'kind'=>'int'], 'ast\Node::__construct' => ['void', 'kind='=>'int', 'flags='=>'int', 'children='=>'ast\Node\Decl[]|ast\Node[]|array[]|int[]|string[]|float[]|bool[]|null[]', 'start_line='=>'int'], 'ast\parse_code' => ['ast\Node', 'code'=>'string', 'version'=>'int', 'filename='=>'string'], 'ast\parse_file' => ['ast\Node', 'filename'=>'string', 'version'=>'int'], 'atan' => ['float', 'number'=>'float'], 'atan2' => ['float', 'y'=>'float', 'x'=>'float'], 'atanh' => ['float', 'number'=>'float'], 'BadFunctionCallException::__clone' => ['void'], 'BadFunctionCallException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?BadFunctionCallException)'], 'BadFunctionCallException::__toString' => ['string'], 'BadFunctionCallException::getCode' => ['int'], 'BadFunctionCallException::getFile' => ['string'], 'BadFunctionCallException::getLine' => ['int'], 'BadFunctionCallException::getMessage' => ['string'], 'BadFunctionCallException::getPrevious' => ['(?Throwable)|(?BadFunctionCallException)'], 'BadFunctionCallException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'BadFunctionCallException::getTraceAsString' => ['string'], 'BadMethodCallException::__clone' => ['void'], 'BadMethodCallException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?BadMethodCallException)'], 'BadMethodCallException::__toString' => ['string'], 'BadMethodCallException::getCode' => ['int'], 'BadMethodCallException::getFile' => ['string'], 'BadMethodCallException::getLine' => ['int'], 'BadMethodCallException::getMessage' => ['string'], 'BadMethodCallException::getPrevious' => ['(?Throwable)|(?BadMethodCallException)'], 'BadMethodCallException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'BadMethodCallException::getTraceAsString' => ['string'], 'base64_decode' => ['string', 'str'=>'string', 'strict='=>'false'], 'base64_decode\'1' => ['string|false', 'str'=>'string', 'strict='=>'true'], 'base64_encode' => ['string', 'str'=>'string'], 'base_convert' => ['string', 'number'=>'string', 'frombase'=>'int', 'tobase'=>'int'], 'basename' => ['string', 'path'=>'string', 'suffix='=>'string'], 'bbcode_add_element' => ['bool', 'bbcode_container'=>'resource', 'tag_name'=>'string', 'tag_rules'=>'array'], 'bbcode_add_smiley' => ['bool', 'bbcode_container'=>'resource', 'smiley'=>'string', 'replace_by'=>'string'], 'bbcode_create' => ['resource', 'bbcode_initial_tags='=>'array'], 'bbcode_destroy' => ['bool', 'bbcode_container'=>'resource'], 'bbcode_parse' => ['string', 'bbcode_container'=>'resource', 'to_parse'=>'string'], 'bbcode_set_arg_parser' => ['bool', 'bbcode_container'=>'resource', 'bbcode_arg_parser'=>'resource'], 'bbcode_set_flags' => ['bool', 'bbcode_container'=>'resource', 'flags'=>'int', 'mode='=>'int'], 'bcadd' => ['numeric-string', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], 'bccomp' => ['int', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], 'bcdiv' => ['numeric-string|null', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], 'bcmod' => ['numeric-string|null', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], 'bcmul' => ['numeric-string', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], 'bcompiler_load' => ['bool', 'filename'=>'string'], 'bcompiler_load_exe' => ['bool', 'filename'=>'string'], 'bcompiler_parse_class' => ['bool', 'class'=>'string', 'callback'=>'string'], 'bcompiler_read' => ['bool', 'filehandle'=>'resource'], 'bcompiler_write_class' => ['bool', 'filehandle'=>'resource', 'classname'=>'string', 'extends='=>'string'], 'bcompiler_write_constant' => ['bool', 'filehandle'=>'resource', 'constantname'=>'string'], 'bcompiler_write_exe_footer' => ['bool', 'filehandle'=>'resource', 'startpos'=>'int'], 'bcompiler_write_file' => ['bool', 'filehandle'=>'resource', 'filename'=>'string'], 'bcompiler_write_footer' => ['bool', 'filehandle'=>'resource'], 'bcompiler_write_function' => ['bool', 'filehandle'=>'resource', 'functionname'=>'string'], 'bcompiler_write_functions_from_file' => ['bool', 'filehandle'=>'resource', 'filename'=>'string'], 'bcompiler_write_header' => ['bool', 'filehandle'=>'resource', 'write_ver='=>'string'], 'bcompiler_write_included_filename' => ['bool', 'filehandle'=>'resource', 'filename'=>'string'], 'bcpow' => ['numeric-string', 'base'=>'string', 'exponent'=>'string', 'scale='=>'int'], 'bcpowmod' => ['numeric-string|null', 'base'=>'string', 'exponent'=>'string', 'modulus'=>'string', 'scale='=>'int'], 'bcscale' => ['int', 'scale='=>'int'], 'bcsqrt' => ['numeric-string', 'operand'=>'string', 'scale='=>'int'], 'bcsub' => ['numeric-string', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], 'bin2hex' => ['string', 'data'=>'string'], 'bind_textdomain_codeset' => ['string|false', 'domain'=>'string', 'codeset'=>'string'], 'bindec' => ['float|int', 'binary_number'=>'string'], 'bindtextdomain' => ['string|false', 'domain_name'=>'string', 'dir'=>'string'], 'birdstep_autocommit' => ['bool', 'index'=>'int'], 'birdstep_close' => ['bool', 'id'=>'int'], 'birdstep_commit' => ['bool', 'index'=>'int'], 'birdstep_connect' => ['int', 'server'=>'string', 'user'=>'string', 'pass'=>'string'], 'birdstep_exec' => ['int', 'index'=>'int', 'exec_str'=>'string'], 'birdstep_fetch' => ['bool', 'index'=>'int'], 'birdstep_fieldname' => ['string', 'index'=>'int', 'col'=>'int'], 'birdstep_fieldnum' => ['int', 'index'=>'int'], 'birdstep_freeresult' => ['bool', 'index'=>'int'], 'birdstep_off_autocommit' => ['bool', 'index'=>'int'], 'birdstep_result' => ['', 'index'=>'int', 'col'=>''], 'birdstep_rollback' => ['bool', 'index'=>'int'], 'blenc_encrypt' => ['string', 'plaintext'=>'string', 'encodedfile'=>'string', 'encryption_key='=>'string'], 'boolval' => ['bool', 'var'=>'mixed'], 'BSON\Binary::__construct' => ['void', 'data'=>'string', 'subtype'=>'string'], 'BSON\Binary::getSubType' => [''], 'BSON\fromArray' => ['string', 'array'=>'string'], 'BSON\fromJSON' => ['string', 'json'=>'string'], 'BSON\Javascript::__construct' => ['void', 'javascript'=>'string', 'scope='=>'string'], 'BSON\ObjectID::__construct' => ['void', 'id='=>'string'], 'BSON\ObjectID::__toString' => ['string'], 'BSON\Regex::__construct' => ['void', 'pattern'=>'string', 'flags'=>'string'], 'BSON\Regex::__toString' => ['string'], 'BSON\Regex::getFlags' => [''], 'BSON\Regex::getPattern' => [''], 'BSON\Serializable::bsonSerialize' => ['string'], 'BSON\Timestamp::__construct' => ['void', 'increment'=>'string', 'timestamp'=>'string'], 'BSON\Timestamp::__toString' => ['string'], 'BSON\toArray' => ['array', 'bson'=>'string'], 'BSON\toJSON' => ['string', 'bson'=>'string'], 'BSON\Unserializable::bsonUnserialize' => ['', 'data'=>'array'], 'BSON\UTCDatetime::__construct' => ['void', 'milliseconds'=>'string'], 'BSON\UTCDatetime::__toString' => ['string'], 'BSON\UTCDatetime::toDateTime' => [''], 'bson_decode' => ['array', 'bson'=>'string'], 'bson_encode' => ['string', 'anything'=>'mixed'], 'bzclose' => ['bool', 'bz'=>'resource'], 'bzcompress' => ['string|int', 'source'=>'string', 'blocksize100k='=>'int', 'workfactor='=>'int'], 'bzdecompress' => ['string|int|false', 'source'=>'string', 'small='=>'int'], 'bzerrno' => ['int', 'bz'=>'resource'], 'bzerror' => ['array', 'bz'=>'resource'], 'bzerrstr' => ['string', 'bz'=>'resource'], 'bzflush' => ['bool', 'bz'=>'resource'], 'bzopen' => ['resource|false', 'file'=>'string|resource', 'mode'=>'string'], 'bzread' => ['string|false', 'bz'=>'resource', 'length='=>'int'], 'bzwrite' => ['int|false', 'bz'=>'resource', 'data'=>'string', 'length='=>'int'], 'CachingIterator::__construct' => ['void', 'iterator'=>'Iterator', 'flags='=>''], 'CachingIterator::__toString' => ['string'], 'CachingIterator::count' => ['0|positive-int'], 'CachingIterator::current' => ['mixed'], 'CachingIterator::getCache' => ['array'], 'CachingIterator::getFlags' => ['int'], 'CachingIterator::getInnerIterator' => ['Iterator'], 'CachingIterator::hasNext' => ['bool'], 'CachingIterator::key' => ['mixed'], 'CachingIterator::next' => ['void'], 'CachingIterator::offsetExists' => ['bool', 'index'=>'string'], 'CachingIterator::offsetGet' => ['mixed', 'index'=>'string'], 'CachingIterator::offsetSet' => ['void', 'index'=>'string', 'newval'=>'mixed'], 'CachingIterator::offsetUnset' => ['void', 'index'=>'string'], 'CachingIterator::rewind' => ['void'], 'CachingIterator::setFlags' => ['void', 'flags'=>'int'], 'CachingIterator::valid' => ['bool'], 'Cairo::availableFonts' => ['array'], 'Cairo::availableSurfaces' => ['array'], 'Cairo::statusToString' => ['string', 'status'=>'int'], 'Cairo::version' => ['int'], 'Cairo::versionString' => ['string'], 'cairo_append_path' => ['', 'path'=>'cairopath', 'context'=>'cairocontext'], 'cairo_arc' => ['', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'angle1'=>'float', 'angle2'=>'float', 'context'=>'cairocontext'], 'cairo_arc_negative' => ['', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'angle1'=>'float', 'angle2'=>'float', 'context'=>'cairocontext'], 'cairo_available_fonts' => ['array'], 'cairo_available_surfaces' => ['array'], 'cairo_clip' => ['', 'context'=>'cairocontext'], 'cairo_clip_extents' => ['array', 'context'=>'cairocontext'], 'cairo_clip_preserve' => ['', 'context'=>'cairocontext'], 'cairo_clip_rectangle_list' => ['array', 'context'=>'cairocontext'], 'cairo_close_path' => ['', 'context'=>'cairocontext'], 'cairo_copy_page' => ['', 'context'=>'cairocontext'], 'cairo_copy_path' => ['CairoPath', 'context'=>'cairocontext'], 'cairo_copy_path_flat' => ['CairoPath', 'context'=>'cairocontext'], 'cairo_create' => ['CairoContext', 'surface'=>'cairosurface'], 'cairo_curve_to' => ['', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float', 'context'=>'cairocontext'], 'cairo_device_to_user' => ['array', 'x'=>'float', 'y'=>'float', 'context'=>'cairocontext'], 'cairo_device_to_user_distance' => ['array', 'x'=>'float', 'y'=>'float', 'context'=>'cairocontext'], 'cairo_fill' => ['', 'context'=>'cairocontext'], 'cairo_fill_extents' => ['array', 'context'=>'cairocontext'], 'cairo_fill_preserve' => ['', 'context'=>'cairocontext'], 'cairo_font_extents' => ['array', 'context'=>'cairocontext'], 'cairo_font_face_get_type' => ['int', 'fontface'=>'cairofontface'], 'cairo_font_face_status' => ['int', 'fontface'=>'cairofontface'], 'cairo_font_options_create' => ['CairoFontOptions'], 'cairo_font_options_equal' => ['bool', 'options'=>'cairofontoptions', 'other'=>'cairofontoptions'], 'cairo_font_options_get_antialias' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_get_hint_metrics' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_get_hint_style' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_get_subpixel_order' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_hash' => ['int', 'options'=>'cairofontoptions'], 'cairo_font_options_merge' => ['void', 'options'=>'cairofontoptions', 'other'=>'cairofontoptions'], 'cairo_font_options_set_antialias' => ['void', 'options'=>'cairofontoptions', 'antialias'=>'int'], 'cairo_font_options_set_hint_metrics' => ['void', 'options'=>'cairofontoptions', 'hint_metrics'=>'int'], 'cairo_font_options_set_hint_style' => ['void', 'options'=>'cairofontoptions', 'hint_style'=>'int'], 'cairo_font_options_set_subpixel_order' => ['void', 'options'=>'cairofontoptions', 'subpixel_order'=>'int'], 'cairo_font_options_status' => ['int', 'options'=>'cairofontoptions'], 'cairo_format_stride_for_width' => ['int', 'format'=>'int', 'width'=>'int'], 'cairo_get_antialias' => ['int', 'context'=>'cairocontext'], 'cairo_get_current_point' => ['array', 'context'=>'cairocontext'], 'cairo_get_dash' => ['array', 'context'=>'cairocontext'], 'cairo_get_dash_count' => ['int', 'context'=>'cairocontext'], 'cairo_get_fill_rule' => ['int', 'context'=>'cairocontext'], 'cairo_get_font_face' => ['', 'context'=>'cairocontext'], 'cairo_get_font_matrix' => ['', 'context'=>'cairocontext'], 'cairo_get_font_options' => ['', 'context'=>'cairocontext'], 'cairo_get_group_target' => ['', 'context'=>'cairocontext'], 'cairo_get_line_cap' => ['int', 'context'=>'cairocontext'], 'cairo_get_line_join' => ['int', 'context'=>'cairocontext'], 'cairo_get_line_width' => ['float', 'context'=>'cairocontext'], 'cairo_get_matrix' => ['', 'context'=>'cairocontext'], 'cairo_get_miter_limit' => ['float', 'context'=>'cairocontext'], 'cairo_get_operator' => ['int', 'context'=>'cairocontext'], 'cairo_get_scaled_font' => ['', 'context'=>'cairocontext'], 'cairo_get_source' => ['', 'context'=>'cairocontext'], 'cairo_get_target' => ['', 'context'=>'cairocontext'], 'cairo_get_tolerance' => ['float', 'context'=>'cairocontext'], 'cairo_glyph_path' => ['', 'glyphs'=>'array', 'context'=>'cairocontext'], 'cairo_has_current_point' => ['bool', 'context'=>'cairocontext'], 'cairo_identity_matrix' => ['', 'context'=>'cairocontext'], 'cairo_image_surface_create' => ['CairoImageSurface', 'format'=>'int', 'width'=>'int', 'height'=>'int'], 'cairo_image_surface_create_for_data' => ['CairoImageSurface', 'data'=>'string', 'format'=>'int', 'width'=>'int', 'height'=>'int', 'stride='=>'int'], 'cairo_image_surface_create_from_png' => ['CairoImageSurface', 'file'=>'string'], 'cairo_image_surface_get_data' => ['string', 'surface'=>'cairoimagesurface'], 'cairo_image_surface_get_format' => ['int', 'surface'=>'cairoimagesurface'], 'cairo_image_surface_get_height' => ['int', 'surface'=>'cairoimagesurface'], 'cairo_image_surface_get_stride' => ['int', 'surface'=>'cairoimagesurface'], 'cairo_image_surface_get_width' => ['int', 'surface'=>'cairoimagesurface'], 'cairo_in_fill' => ['bool', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_in_stroke' => ['bool', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_line_to' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_mask' => ['', 'pattern'=>'cairopattern', 'context'=>'cairocontext'], 'cairo_mask_surface' => ['', 'surface'=>'cairosurface', 'x='=>'string', 'y='=>'string', 'context='=>'cairocontext'], 'cairo_matrix_create_scale' => ['object', 'sx'=>'float', 'sy'=>'float'], 'cairo_matrix_init' => ['object', 'xx='=>'float', 'yx='=>'float', 'xy='=>'float', 'yy='=>'float', 'x0='=>'float', 'y0='=>'float'], 'cairo_matrix_init_identity' => ['object'], 'cairo_matrix_init_rotate' => ['object', 'radians'=>'float'], 'cairo_matrix_init_scale' => ['object', 'sx'=>'float', 'sy'=>'float'], 'cairo_matrix_init_translate' => ['object', 'tx'=>'float', 'ty'=>'float'], 'cairo_matrix_invert' => ['void', 'matrix'=>'cairomatrix'], 'cairo_matrix_multiply' => ['CairoMatrix', 'matrix1'=>'cairomatrix', 'matrix2'=>'cairomatrix'], 'cairo_matrix_rotate' => ['', 'matrix'=>'cairomatrix', 'radians'=>'float'], 'cairo_matrix_scale' => ['', 'sx'=>'float', 'sy'=>'float', 'context'=>'cairocontext'], 'cairo_matrix_transform_distance' => ['array', 'matrix'=>'cairomatrix', 'dx'=>'float', 'dy'=>'float'], 'cairo_matrix_transform_point' => ['array', 'matrix'=>'cairomatrix', 'dx'=>'float', 'dy'=>'float'], 'cairo_matrix_translate' => ['void', 'matrix'=>'cairomatrix', 'tx'=>'float', 'ty'=>'float'], 'cairo_move_to' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_new_path' => ['', 'context'=>'cairocontext'], 'cairo_new_sub_path' => ['', 'context'=>'cairocontext'], 'cairo_paint' => ['', 'context'=>'cairocontext'], 'cairo_paint_with_alpha' => ['', 'alpha'=>'string', 'context'=>'cairocontext'], 'cairo_path_extents' => ['array', 'context'=>'cairocontext'], 'cairo_pattern_add_color_stop_rgb' => ['void', 'pattern'=>'cairogradientpattern', 'offset'=>'float', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'cairo_pattern_add_color_stop_rgba' => ['void', 'pattern'=>'cairogradientpattern', 'offset'=>'float', 'red'=>'float', 'green'=>'float', 'blue'=>'float', 'alpha'=>'float'], 'cairo_pattern_create_for_surface' => ['CairoPattern', 'surface'=>'cairosurface'], 'cairo_pattern_create_linear' => ['CairoPattern', 'x0'=>'float', 'y0'=>'float', 'x1'=>'float', 'y1'=>'float'], 'cairo_pattern_create_radial' => ['CairoPattern', 'x0'=>'float', 'y0'=>'float', 'r0'=>'float', 'x1'=>'float', 'y1'=>'float', 'r1'=>'float'], 'cairo_pattern_create_rgb' => ['CairoPattern', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'cairo_pattern_create_rgba' => ['CairoPattern', 'red'=>'float', 'green'=>'float', 'blue'=>'float', 'alpha'=>'float'], 'cairo_pattern_get_color_stop_count' => ['int', 'pattern'=>'cairogradientpattern'], 'cairo_pattern_get_color_stop_rgba' => ['array', 'pattern'=>'cairogradientpattern', 'index'=>'int'], 'cairo_pattern_get_extend' => ['int', 'pattern'=>'string'], 'cairo_pattern_get_filter' => ['int', 'pattern'=>'cairosurfacepattern'], 'cairo_pattern_get_linear_points' => ['array', 'pattern'=>'cairolineargradient'], 'cairo_pattern_get_matrix' => ['CairoMatrix', 'pattern'=>'cairopattern'], 'cairo_pattern_get_radial_circles' => ['array', 'pattern'=>'cairoradialgradient'], 'cairo_pattern_get_rgba' => ['array', 'pattern'=>'cairosolidpattern'], 'cairo_pattern_get_surface' => ['CairoSurface', 'pattern'=>'cairosurfacepattern'], 'cairo_pattern_get_type' => ['int', 'pattern'=>'cairopattern'], 'cairo_pattern_set_extend' => ['void', 'pattern'=>'string', 'extend'=>'string'], 'cairo_pattern_set_filter' => ['void', 'pattern'=>'cairosurfacepattern', 'filter'=>'int'], 'cairo_pattern_set_matrix' => ['void', 'pattern'=>'cairopattern', 'matrix'=>'cairomatrix'], 'cairo_pattern_status' => ['int', 'pattern'=>'cairopattern'], 'cairo_pdf_surface_create' => ['CairoPdfSurface', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'cairo_pdf_surface_set_size' => ['void', 'surface'=>'cairopdfsurface', 'width'=>'float', 'height'=>'float'], 'cairo_pop_group' => ['', 'context'=>'cairocontext'], 'cairo_pop_group_to_source' => ['', 'context'=>'cairocontext'], 'cairo_ps_get_levels' => ['array'], 'cairo_ps_level_to_string' => ['string', 'level'=>'int'], 'cairo_ps_surface_create' => ['CairoPsSurface', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'cairo_ps_surface_dsc_begin_page_setup' => ['void', 'surface'=>'cairopssurface'], 'cairo_ps_surface_dsc_begin_setup' => ['void', 'surface'=>'cairopssurface'], 'cairo_ps_surface_dsc_comment' => ['void', 'surface'=>'cairopssurface', 'comment'=>'string'], 'cairo_ps_surface_get_eps' => ['bool', 'surface'=>'cairopssurface'], 'cairo_ps_surface_restrict_to_level' => ['void', 'surface'=>'cairopssurface', 'level'=>'int'], 'cairo_ps_surface_set_eps' => ['void', 'surface'=>'cairopssurface', 'level'=>'bool'], 'cairo_ps_surface_set_size' => ['void', 'surface'=>'cairopssurface', 'width'=>'float', 'height'=>'float'], 'cairo_push_group' => ['', 'context'=>'cairocontext'], 'cairo_push_group_with_content' => ['', 'content'=>'string', 'context'=>'cairocontext'], 'cairo_rectangle' => ['', 'x'=>'string', 'y'=>'string', 'width'=>'string', 'height'=>'string', 'context'=>'cairocontext'], 'cairo_rel_curve_to' => ['', 'x1'=>'string', 'y1'=>'string', 'x2'=>'string', 'y2'=>'string', 'x3'=>'string', 'y3'=>'string', 'context'=>'cairocontext'], 'cairo_rel_line_to' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_rel_move_to' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_reset_clip' => ['', 'context'=>'cairocontext'], 'cairo_restore' => ['', 'context'=>'cairocontext'], 'cairo_rotate' => ['', 'sx'=>'string', 'sy'=>'string', 'context'=>'cairocontext', 'angle'=>'string'], 'cairo_save' => ['', 'context'=>'cairocontext'], 'cairo_scale' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_scaled_font_create' => ['CairoScaledFont', 'fontface'=>'cairofontface', 'matrix'=>'cairomatrix', 'ctm'=>'cairomatrix', 'fontoptions'=>'cairofontoptions'], 'cairo_scaled_font_extents' => ['array', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_ctm' => ['CairoMatrix', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_font_face' => ['CairoFontFace', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_font_matrix' => ['CairoFontOptions', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_font_options' => ['CairoFontOptions', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_scale_matrix' => ['CairoMatrix', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_get_type' => ['int', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_glyph_extents' => ['array', 'scaledfont'=>'cairoscaledfont', 'glyphs'=>'array'], 'cairo_scaled_font_status' => ['int', 'scaledfont'=>'cairoscaledfont'], 'cairo_scaled_font_text_extents' => ['array', 'scaledfont'=>'cairoscaledfont', 'text'=>'string'], 'cairo_select_font_face' => ['', 'family'=>'string', 'slant='=>'string', 'weight='=>'string', 'context='=>'cairocontext'], 'cairo_set_antialias' => ['', 'antialias='=>'string', 'context='=>'cairocontext'], 'cairo_set_dash' => ['', 'dashes'=>'array', 'offset='=>'string', 'context='=>'cairocontext'], 'cairo_set_fill_rule' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'cairo_set_font_face' => ['', 'fontface'=>'cairofontface', 'context'=>'cairocontext'], 'cairo_set_font_matrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'cairo_set_font_options' => ['', 'fontoptions'=>'cairofontoptions', 'context'=>'cairocontext'], 'cairo_set_font_size' => ['', 'size'=>'string', 'context'=>'cairocontext'], 'cairo_set_line_cap' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'cairo_set_line_join' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'cairo_set_line_width' => ['', 'width'=>'string', 'context'=>'cairocontext'], 'cairo_set_matrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'cairo_set_miter_limit' => ['', 'limit'=>'string', 'context'=>'cairocontext'], 'cairo_set_operator' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'cairo_set_scaled_font' => ['', 'scaledfont'=>'cairoscaledfont', 'context'=>'cairocontext'], 'cairo_set_source' => ['', 'red'=>'string', 'green'=>'string', 'blue'=>'string', 'alpha'=>'string', 'context'=>'cairocontext', 'pattern'=>'cairopattern'], 'cairo_set_source_surface' => ['', 'surface'=>'cairosurface', 'x='=>'string', 'y='=>'string', 'context='=>'cairocontext'], 'cairo_set_tolerance' => ['', 'tolerance'=>'string', 'context'=>'cairocontext'], 'cairo_show_page' => ['', 'context'=>'cairocontext'], 'cairo_show_text' => ['', 'text'=>'string', 'context'=>'cairocontext'], 'cairo_status' => ['int', 'context'=>'cairocontext'], 'cairo_status_to_string' => ['string', 'status'=>'int'], 'cairo_stroke' => ['', 'context'=>'cairocontext'], 'cairo_stroke_extents' => ['array', 'context'=>'cairocontext'], 'cairo_stroke_preserve' => ['', 'context'=>'cairocontext'], 'cairo_surface_copy_page' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_create_similar' => ['CairoSurface', 'surface'=>'cairosurface', 'content'=>'int', 'width'=>'float', 'height'=>'float'], 'cairo_surface_finish' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_flush' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_get_content' => ['int', 'surface'=>'cairosurface'], 'cairo_surface_get_device_offset' => ['array', 'surface'=>'cairosurface'], 'cairo_surface_get_font_options' => ['CairoFontOptions', 'surface'=>'cairosurface'], 'cairo_surface_get_type' => ['int', 'surface'=>'cairosurface'], 'cairo_surface_mark_dirty' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_mark_dirty_rectangle' => ['void', 'surface'=>'cairosurface', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'cairo_surface_set_device_offset' => ['void', 'surface'=>'cairosurface', 'x'=>'float', 'y'=>'float'], 'cairo_surface_set_fallback_resolution' => ['void', 'surface'=>'cairosurface', 'x'=>'float', 'y'=>'float'], 'cairo_surface_show_page' => ['void', 'surface'=>'cairosurface'], 'cairo_surface_status' => ['int', 'surface'=>'cairosurface'], 'cairo_surface_write_to_png' => ['void', 'surface'=>'cairosurface', 'stream'=>'resource'], 'cairo_svg_get_versions' => ['array'], 'cairo_svg_surface_create' => ['CairoSvgSurface', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'cairo_svg_surface_get_versions' => ['array'], 'cairo_svg_surface_restrict_to_version' => ['void', 'surface'=>'cairosvgsurface', 'version'=>'int'], 'cairo_svg_version_to_string' => ['string', 'version'=>'int'], 'cairo_text_extents' => ['array', 'text'=>'string', 'context'=>'cairocontext'], 'cairo_text_path' => ['', 'string'=>'string', 'context'=>'cairocontext', 'text'=>'string'], 'cairo_transform' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'cairo_translate' => ['', 'tx'=>'string', 'ty'=>'string', 'context'=>'cairocontext', 'x'=>'string', 'y'=>'string'], 'cairo_user_to_device' => ['array', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_user_to_device_distance' => ['array', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'cairo_version' => ['int'], 'cairo_version_string' => ['string'], 'CairoContext::__construct' => ['void', 'surface'=>'CairoSurface'], 'CairoContext::appendPath' => ['', 'path'=>'cairopath', 'context'=>'cairocontext'], 'CairoContext::arc' => ['', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'angle1'=>'float', 'angle2'=>'float', 'context'=>'cairocontext'], 'CairoContext::arcNegative' => ['', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'angle1'=>'float', 'angle2'=>'float', 'context'=>'cairocontext'], 'CairoContext::clip' => ['', 'context'=>'cairocontext'], 'CairoContext::clipExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::clipPreserve' => ['', 'context'=>'cairocontext'], 'CairoContext::clipRectangleList' => ['array', 'context'=>'cairocontext'], 'CairoContext::closePath' => ['', 'context'=>'cairocontext'], 'CairoContext::copyPage' => ['', 'context'=>'cairocontext'], 'CairoContext::copyPath' => ['CairoPath', 'context'=>'cairocontext'], 'CairoContext::copyPathFlat' => ['CairoPath', 'context'=>'cairocontext'], 'CairoContext::curveTo' => ['', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float', 'context'=>'cairocontext'], 'CairoContext::deviceToUser' => ['array', 'x'=>'float', 'y'=>'float', 'context'=>'cairocontext'], 'CairoContext::deviceToUserDistance' => ['array', 'x'=>'float', 'y'=>'float', 'context'=>'cairocontext'], 'CairoContext::fill' => ['', 'context'=>'cairocontext'], 'CairoContext::fillExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::fillPreserve' => ['', 'context'=>'cairocontext'], 'CairoContext::fontExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::getAntialias' => ['int', 'context'=>'cairocontext'], 'CairoContext::getCurrentPoint' => ['array', 'context'=>'cairocontext'], 'CairoContext::getDash' => ['array', 'context'=>'cairocontext'], 'CairoContext::getDashCount' => ['int', 'context'=>'cairocontext'], 'CairoContext::getFillRule' => ['int', 'context'=>'cairocontext'], 'CairoContext::getFontFace' => ['', 'context'=>'cairocontext'], 'CairoContext::getFontMatrix' => ['', 'context'=>'cairocontext'], 'CairoContext::getFontOptions' => ['', 'context'=>'cairocontext'], 'CairoContext::getGroupTarget' => ['', 'context'=>'cairocontext'], 'CairoContext::getLineCap' => ['int', 'context'=>'cairocontext'], 'CairoContext::getLineJoin' => ['int', 'context'=>'cairocontext'], 'CairoContext::getLineWidth' => ['float', 'context'=>'cairocontext'], 'CairoContext::getMatrix' => ['', 'context'=>'cairocontext'], 'CairoContext::getMiterLimit' => ['float', 'context'=>'cairocontext'], 'CairoContext::getOperator' => ['int', 'context'=>'cairocontext'], 'CairoContext::getScaledFont' => ['', 'context'=>'cairocontext'], 'CairoContext::getSource' => ['', 'context'=>'cairocontext'], 'CairoContext::getTarget' => ['', 'context'=>'cairocontext'], 'CairoContext::getTolerance' => ['float', 'context'=>'cairocontext'], 'CairoContext::glyphPath' => ['', 'glyphs'=>'array', 'context'=>'cairocontext'], 'CairoContext::hasCurrentPoint' => ['bool', 'context'=>'cairocontext'], 'CairoContext::identityMatrix' => ['', 'context'=>'cairocontext'], 'CairoContext::inFill' => ['bool', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::inStroke' => ['bool', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::lineTo' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::mask' => ['', 'pattern'=>'cairopattern', 'context'=>'cairocontext'], 'CairoContext::maskSurface' => ['', 'surface'=>'cairosurface', 'x='=>'string', 'y='=>'string', 'context='=>'cairocontext'], 'CairoContext::moveTo' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::newPath' => ['', 'context'=>'cairocontext'], 'CairoContext::newSubPath' => ['', 'context'=>'cairocontext'], 'CairoContext::paint' => ['', 'context'=>'cairocontext'], 'CairoContext::paintWithAlpha' => ['', 'alpha'=>'string', 'context'=>'cairocontext'], 'CairoContext::pathExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::popGroup' => ['', 'context'=>'cairocontext'], 'CairoContext::popGroupToSource' => ['', 'context'=>'cairocontext'], 'CairoContext::pushGroup' => ['', 'context'=>'cairocontext'], 'CairoContext::pushGroupWithContent' => ['', 'content'=>'string', 'context'=>'cairocontext'], 'CairoContext::rectangle' => ['', 'x'=>'string', 'y'=>'string', 'width'=>'string', 'height'=>'string', 'context'=>'cairocontext'], 'CairoContext::relCurveTo' => ['', 'x1'=>'string', 'y1'=>'string', 'x2'=>'string', 'y2'=>'string', 'x3'=>'string', 'y3'=>'string', 'context'=>'cairocontext'], 'CairoContext::relLineTo' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::relMoveTo' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::resetClip' => ['', 'context'=>'cairocontext'], 'CairoContext::restore' => ['', 'context'=>'cairocontext'], 'CairoContext::rotate' => ['', 'angle'=>'string', 'context'=>'cairocontext'], 'CairoContext::save' => ['', 'context'=>'cairocontext'], 'CairoContext::scale' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::selectFontFace' => ['', 'family'=>'string', 'slant='=>'string', 'weight='=>'string', 'context='=>'cairocontext'], 'CairoContext::setAntialias' => ['', 'antialias='=>'string', 'context='=>'cairocontext'], 'CairoContext::setDash' => ['', 'dashes'=>'array', 'offset='=>'string', 'context='=>'cairocontext'], 'CairoContext::setFillRule' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'CairoContext::setFontFace' => ['', 'fontface'=>'cairofontface', 'context'=>'cairocontext'], 'CairoContext::setFontMatrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'CairoContext::setFontOptions' => ['', 'fontoptions'=>'cairofontoptions', 'context'=>'cairocontext'], 'CairoContext::setFontSize' => ['', 'size'=>'string', 'context'=>'cairocontext'], 'CairoContext::setLineCap' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'CairoContext::setLineJoin' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'CairoContext::setLineWidth' => ['', 'width'=>'string', 'context'=>'cairocontext'], 'CairoContext::setMatrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'CairoContext::setMiterLimit' => ['', 'limit'=>'string', 'context'=>'cairocontext'], 'CairoContext::setOperator' => ['', 'setting'=>'string', 'context'=>'cairocontext'], 'CairoContext::setScaledFont' => ['', 'scaledfont'=>'cairoscaledfont', 'context'=>'cairocontext'], 'CairoContext::setSource' => ['', 'pattern'=>'cairopattern', 'context'=>'cairocontext'], 'CairoContext::setSourceRGB' => ['', 'red'=>'string', 'green'=>'string', 'blue'=>'string', 'context'=>'cairocontext', 'pattern'=>'cairopattern'], 'CairoContext::setSourceRGBA' => ['', 'red'=>'string', 'green'=>'string', 'blue'=>'string', 'alpha'=>'string', 'context'=>'cairocontext', 'pattern'=>'cairopattern'], 'CairoContext::setSourceSurface' => ['', 'surface'=>'cairosurface', 'x='=>'string', 'y='=>'string', 'context='=>'cairocontext'], 'CairoContext::setTolerance' => ['', 'tolerance'=>'string', 'context'=>'cairocontext'], 'CairoContext::showPage' => ['', 'context'=>'cairocontext'], 'CairoContext::showText' => ['', 'text'=>'string', 'context'=>'cairocontext'], 'CairoContext::status' => ['int', 'context'=>'cairocontext'], 'CairoContext::stroke' => ['', 'context'=>'cairocontext'], 'CairoContext::strokeExtents' => ['array', 'context'=>'cairocontext'], 'CairoContext::strokePreserve' => ['', 'context'=>'cairocontext'], 'CairoContext::textExtents' => ['array', 'text'=>'string', 'context'=>'cairocontext'], 'CairoContext::textPath' => ['', 'string'=>'string', 'context'=>'cairocontext', 'text'=>'string'], 'CairoContext::transform' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'CairoContext::translate' => ['', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::userToDevice' => ['array', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoContext::userToDeviceDistance' => ['array', 'x'=>'string', 'y'=>'string', 'context'=>'cairocontext'], 'CairoFontFace::__construct' => ['void'], 'CairoFontFace::getType' => ['int'], 'CairoFontFace::status' => ['int', 'fontface'=>'cairofontface'], 'CairoFontOptions::__construct' => ['void'], 'CairoFontOptions::equal' => ['bool', 'other'=>'string'], 'CairoFontOptions::getAntialias' => ['int', 'context'=>'cairocontext'], 'CairoFontOptions::getHintMetrics' => ['int'], 'CairoFontOptions::getHintStyle' => ['int'], 'CairoFontOptions::getSubpixelOrder' => ['int'], 'CairoFontOptions::hash' => ['int'], 'CairoFontOptions::merge' => ['void', 'other'=>'string'], 'CairoFontOptions::setAntialias' => ['', 'antialias='=>'string', 'context='=>'cairocontext'], 'CairoFontOptions::setHintMetrics' => ['void', 'hint_metrics'=>'string'], 'CairoFontOptions::setHintStyle' => ['void', 'hint_style'=>'string'], 'CairoFontOptions::setSubpixelOrder' => ['void', 'subpixel_order'=>'string'], 'CairoFontOptions::status' => ['int', 'context'=>'cairocontext'], 'CairoFormat::strideForWidth' => ['int', 'format'=>'int', 'width'=>'int'], 'CairoGradientPattern::addColorStopRgb' => ['void', 'offset'=>'string', 'red'=>'string', 'green'=>'string', 'blue'=>'string'], 'CairoGradientPattern::addColorStopRgba' => ['void', 'offset'=>'string', 'red'=>'string', 'green'=>'string', 'blue'=>'string', 'alpha'=>'string'], 'CairoGradientPattern::getColorStopCount' => ['int'], 'CairoGradientPattern::getColorStopRgba' => ['array', 'index'=>'string'], 'CairoGradientPattern::getExtend' => ['int'], 'CairoGradientPattern::setExtend' => ['void', 'extend'=>'int'], 'CairoImageSurface::__construct' => ['void', 'format'=>'int', 'width'=>'int', 'height'=>'int'], 'CairoImageSurface::createForData' => ['void', 'data'=>'string', 'format'=>'int', 'width'=>'int', 'height'=>'int', 'stride='=>'int'], 'CairoImageSurface::createFromPng' => ['CairoImageSurface', 'file'=>'string'], 'CairoImageSurface::getData' => ['string'], 'CairoImageSurface::getFormat' => ['int'], 'CairoImageSurface::getHeight' => ['int'], 'CairoImageSurface::getStride' => ['int'], 'CairoImageSurface::getWidth' => ['int'], 'CairoLinearGradient::__construct' => ['void', 'x0'=>'float', 'y0'=>'float', 'x1'=>'float', 'y1'=>'float'], 'CairoLinearGradient::getPoints' => ['array'], 'CairoMatrix::__construct' => ['void', 'xx='=>'float', 'yx='=>'float', 'xy='=>'float', 'yy='=>'float', 'x0='=>'float', 'y0='=>'float'], 'CairoMatrix::initIdentity' => ['object'], 'CairoMatrix::initRotate' => ['object', 'radians'=>'float'], 'CairoMatrix::initScale' => ['object', 'sx'=>'float', 'sy'=>'float'], 'CairoMatrix::initTranslate' => ['object', 'tx'=>'float', 'ty'=>'float'], 'CairoMatrix::invert' => ['void'], 'CairoMatrix::multiply' => ['CairoMatrix', 'matrix1'=>'cairomatrix', 'matrix2'=>'cairomatrix'], 'CairoMatrix::rotate' => ['', 'sx'=>'string', 'sy'=>'string', 'context'=>'cairocontext', 'angle'=>'string'], 'CairoMatrix::scale' => ['', 'sx'=>'float', 'sy'=>'float', 'context'=>'cairocontext'], 'CairoMatrix::transformDistance' => ['array', 'dx'=>'string', 'dy'=>'string'], 'CairoMatrix::transformPoint' => ['array', 'dx'=>'string', 'dy'=>'string'], 'CairoMatrix::translate' => ['', 'tx'=>'string', 'ty'=>'string', 'context'=>'cairocontext', 'x'=>'string', 'y'=>'string'], 'CairoPattern::__construct' => ['void'], 'CairoPattern::getMatrix' => ['', 'context'=>'cairocontext'], 'CairoPattern::getType' => ['int'], 'CairoPattern::setMatrix' => ['', 'matrix'=>'cairomatrix', 'context'=>'cairocontext'], 'CairoPattern::status' => ['int', 'context'=>'cairocontext'], 'CairoPdfSurface::__construct' => ['void', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'CairoPdfSurface::setSize' => ['void', 'width'=>'string', 'height'=>'string'], 'CairoPsSurface::__construct' => ['void', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'CairoPsSurface::dscBeginPageSetup' => ['void'], 'CairoPsSurface::dscBeginSetup' => ['void'], 'CairoPsSurface::dscComment' => ['void', 'comment'=>'string'], 'CairoPsSurface::getEps' => ['bool'], 'CairoPsSurface::getLevels' => ['array'], 'CairoPsSurface::levelToString' => ['string', 'level'=>'int'], 'CairoPsSurface::restrictToLevel' => ['void', 'level'=>'string'], 'CairoPsSurface::setEps' => ['void', 'level'=>'string'], 'CairoPsSurface::setSize' => ['void', 'width'=>'string', 'height'=>'string'], 'CairoRadialGradient::__construct' => ['void', 'x0'=>'float', 'y0'=>'float', 'r0'=>'float', 'x1'=>'float', 'y1'=>'float', 'r1'=>'float'], 'CairoRadialGradient::getCircles' => ['array'], 'CairoScaledFont::__construct' => ['void', 'font_face'=>'CairoFontFace', 'matrix'=>'CairoMatrix', 'ctm'=>'CairoMatrix', 'options'=>'CairoFontOptions'], 'CairoScaledFont::extents' => ['array'], 'CairoScaledFont::getCtm' => ['CairoMatrix'], 'CairoScaledFont::getFontFace' => ['', 'context'=>'cairocontext'], 'CairoScaledFont::getFontMatrix' => ['', 'context'=>'cairocontext'], 'CairoScaledFont::getFontOptions' => ['', 'context'=>'cairocontext'], 'CairoScaledFont::getScaleMatrix' => ['void'], 'CairoScaledFont::getType' => ['int'], 'CairoScaledFont::glyphExtents' => ['array', 'glyphs'=>'string'], 'CairoScaledFont::status' => ['int', 'context'=>'cairocontext'], 'CairoScaledFont::textExtents' => ['array', 'text'=>'string', 'context'=>'cairocontext'], 'CairoSolidPattern::__construct' => ['void', 'red'=>'float', 'green'=>'float', 'blue'=>'float', 'alpha='=>'float'], 'CairoSolidPattern::getRgba' => ['array'], 'CairoSurface::__construct' => ['void'], 'CairoSurface::copyPage' => ['', 'context'=>'cairocontext'], 'CairoSurface::createSimilar' => ['void', 'other'=>'cairosurface', 'content'=>'int', 'width'=>'string', 'height'=>'string'], 'CairoSurface::finish' => ['void'], 'CairoSurface::flush' => ['void'], 'CairoSurface::getContent' => ['int'], 'CairoSurface::getDeviceOffset' => ['array'], 'CairoSurface::getFontOptions' => ['', 'context'=>'cairocontext'], 'CairoSurface::getType' => ['int'], 'CairoSurface::markDirty' => ['void'], 'CairoSurface::markDirtyRectangle' => ['void', 'x'=>'string', 'y'=>'string', 'width'=>'string', 'height'=>'string'], 'CairoSurface::setDeviceOffset' => ['void', 'x'=>'string', 'y'=>'string'], 'CairoSurface::setFallbackResolution' => ['void', 'x'=>'string', 'y'=>'string'], 'CairoSurface::showPage' => ['', 'context'=>'cairocontext'], 'CairoSurface::status' => ['int', 'context'=>'cairocontext'], 'CairoSurface::writeToPng' => ['void', 'file'=>'string'], 'CairoSurfacePattern::__construct' => ['void', 'surface'=>'CairoSurface'], 'CairoSurfacePattern::getExtend' => ['int'], 'CairoSurfacePattern::getFilter' => ['int'], 'CairoSurfacePattern::getSurface' => ['void'], 'CairoSurfacePattern::setExtend' => ['void', 'extend'=>'int'], 'CairoSurfacePattern::setFilter' => ['void', 'filter'=>'string'], 'CairoSvgSurface::__construct' => ['void', 'file'=>'string', 'width'=>'float', 'height'=>'float'], 'CairoSvgSurface::getVersions' => ['array'], 'CairoSvgSurface::restrictToVersion' => ['void', 'version'=>'string'], 'CairoSvgSurface::versionToString' => ['string', 'version'=>'int'], 'cal_days_in_month' => ['int', 'calendar'=>'int', 'month'=>'int', 'year'=>'int'], 'cal_from_jd' => ['array', 'jd'=>'int', 'calendar'=>'int'], 'cal_info' => ['array', 'calendar='=>'int'], 'cal_to_jd' => ['int', 'calendar'=>'int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'calcul_hmac' => ['string', 'clent'=>'string', 'siretcode'=>'string', 'price'=>'string', 'reference'=>'string', 'validity'=>'string', 'taxation'=>'string', 'devise'=>'string', 'language'=>'string'], 'calculhmac' => ['string', 'clent'=>'string', 'data'=>'string'], 'call_user_func' => ['mixed', 'function'=>'callable', '...parameters='=>'mixed'], 'call_user_func_array' => ['mixed', 'function'=>'callable', 'parameters'=>'array'], 'call_user_method' => ['mixed', 'method_name'=>'string', 'obj'=>'object', 'parameter='=>'mixed', '...args='=>'mixed'], 'call_user_method_array' => ['mixed', 'method_name'=>'string', 'obj'=>'object', 'params'=>'array'], 'CallbackFilterIterator::__construct' => ['void', 'iterator'=>'Iterator', 'func'=>'callable'], 'CallbackFilterIterator::accept' => ['bool'], 'CallbackFilterIterator::current' => ['mixed'], 'CallbackFilterIterator::getInnerIterator' => ['Iterator'], 'CallbackFilterIterator::key' => ['mixed'], 'CallbackFilterIterator::next' => ['void'], 'CallbackFilterIterator::rewind' => ['void'], 'CallbackFilterIterator::valid' => ['bool'], 'ceil' => ['__benevolent', 'number'=>'float'], 'chdb::__construct' => ['void', 'pathname'=>'string'], 'chdb::get' => ['string', 'key'=>'string'], 'chdb_create' => ['bool', 'pathname'=>'string', 'data'=>'array'], 'chdir' => ['bool', 'directory'=>'string'], 'checkdate' => ['bool', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'checkdnsrr' => ['bool', 'host'=>'string', 'type='=>'string'], 'chgrp' => ['bool', 'filename'=>'string', 'group'=>'string|int'], 'chmod' => ['bool', 'filename'=>'string', 'mode'=>'int'], 'chop' => ['string', 'str'=>'string', 'character_mask='=>'string'], 'chown' => ['bool', 'filename'=>'string', 'user'=>'string|int'], 'chr' => ['non-empty-string', 'ascii'=>'int'], 'chroot' => ['bool', 'directory'=>'string'], 'chunk_split' => ['string', 'str'=>'string', 'chunklen='=>'positive-int', 'ending='=>'string'], 'class_alias' => ['bool', 'user_class_name'=>'string', 'alias_name'=>'string', 'autoload='=>'bool'], 'class_exists' => ['bool', 'classname'=>'string', 'autoload='=>'bool'], 'class_implements' => ['array|false', 'what'=>'object|string', 'autoload='=>'bool'], 'class_parents' => ['array|false', 'instance'=>'object|string', 'autoload='=>'bool'], 'class_uses' => ['array|false', 'what'=>'object|string', 'autoload='=>'bool'], 'classkit_import' => ['array', 'filename'=>'string'], 'classkit_method_add' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'args'=>'string', 'code'=>'string', 'flags='=>'int'], 'classkit_method_copy' => ['bool', 'dclass'=>'string', 'dmethod'=>'string', 'sclass'=>'string', 'smethod='=>'string'], 'classkit_method_redefine' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'args'=>'string', 'code'=>'string', 'flags='=>'int'], 'classkit_method_remove' => ['bool', 'classname'=>'string', 'methodname'=>'string'], 'classkit_method_rename' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'newname'=>'string'], 'classObj::__construct' => ['void', 'layer'=>'layerObj', 'class'=>'classObj'], 'classObj::addLabel' => ['int', 'label'=>'labelObj'], 'classObj::convertToString' => ['string'], 'classObj::createLegendIcon' => ['imageObj', 'width'=>'int', 'height'=>'int'], 'classObj::deletestyle' => ['int', 'index'=>'int'], 'classObj::drawLegendIcon' => ['int', 'width'=>'int', 'height'=>'int', 'im'=>'imageObj', 'dstX'=>'int', 'dstY'=>'int'], 'classObj::free' => ['void'], 'classObj::getExpressionString' => ['string'], 'classObj::getLabel' => ['labelObj', 'index'=>'int'], 'classObj::getMetaData' => ['int', 'name'=>'string'], 'classObj::getStyle' => ['styleObj', 'index'=>'int'], 'classObj::getTextString' => ['string'], 'classObj::movestyledown' => ['int', 'index'=>'int'], 'classObj::movestyleup' => ['int', 'index'=>'int'], 'classObj::ms_newClassObj' => ['classObj', 'layer'=>'layerObj', 'class'=>'classObj'], 'classObj::removeLabel' => ['labelObj', 'index'=>'int'], 'classObj::removeMetaData' => ['int', 'name'=>'string'], 'classObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'classObj::setExpression' => ['int', 'expression'=>'string'], 'classObj::setMetaData' => ['int', 'name'=>'string', 'value'=>'string'], 'classObj::settext' => ['int', 'text'=>'string'], 'classObj::updateFromString' => ['int', 'snippet'=>'string'], 'clearstatcache' => ['void', 'clear_realpath_cache='=>'bool', 'filename='=>'string'], 'cli_get_process_title' => ['string'], 'cli_set_process_title' => ['bool', 'arg'=>'string'], 'ClosedGeneratorException::__clone' => ['void'], 'ClosedGeneratorException::__toString' => ['string'], 'ClosedGeneratorException::getCode' => ['int'], 'ClosedGeneratorException::getFile' => ['string'], 'ClosedGeneratorException::getLine' => ['int'], 'ClosedGeneratorException::getMessage' => ['string'], 'ClosedGeneratorException::getPrevious' => ['Throwable|ClosedGeneratorException|null'], 'ClosedGeneratorException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'ClosedGeneratorException::getTraceAsString' => ['string'], 'closedir' => ['void', 'dir_handle='=>'resource'], 'closelog' => ['bool'], 'Closure::__construct' => ['void'], 'Closure::__invoke' => ['', '...args='=>''], 'Closure::bind' => ['__benevolent', 'old'=>'Closure', 'to'=>'?object', 'scope='=>'object|string|null'], 'Closure::bindTo' => ['__benevolent', 'new'=>'?object', 'newscope='=>'object|string|null'], 'Closure::call' => ['', 'to'=>'object', '...parameters='=>''], 'Closure::fromCallable' => ['Closure', 'callable'=>'callable'], 'clusterObj::convertToString' => ['string'], 'clusterObj::getFilterString' => ['string'], 'clusterObj::getGroupString' => ['string'], 'clusterObj::setFilter' => ['int', 'expression'=>'string'], 'clusterObj::setGroup' => ['int', 'expression'=>'string'], 'Collator::__construct' => ['void', 'locale'=>'string'], 'Collator::asort' => ['bool', '&rw_arr'=>'array', 'sort_flag='=>'int'], 'Collator::compare' => ['int|false', 'str1'=>'string', 'str2'=>'string'], 'Collator::create' => ['?Collator', 'locale'=>'string'], 'Collator::getAttribute' => ['int', 'attr'=>'int'], 'Collator::getErrorCode' => ['int'], 'Collator::getErrorMessage' => ['string'], 'Collator::getLocale' => ['string', 'type'=>'int'], 'Collator::getSortKey' => ['string', 'str'=>'string'], 'Collator::getStrength' => ['int'], 'Collator::setAttribute' => ['bool', 'attr'=>'int', 'val'=>'int'], 'Collator::setStrength' => ['bool', 'strength'=>'int'], 'Collator::sort' => ['bool', '&rw_arr'=>'array', 'sort_flags='=>'int'], 'Collator::sortWithSortKeys' => ['bool', '&rw_arr'=>'array'], 'collator_asort' => ['bool', 'coll'=>'collator', '&rw_arr'=>'array', 'sort_flag='=>'int'], 'collator_compare' => ['int|false', 'coll'=>'collator', 'str1'=>'string', 'str2'=>'string'], 'collator_create' => ['?Collator', 'locale'=>'string'], 'collator_get_attribute' => ['int|false', 'coll'=>'collator', 'attr'=>'int'], 'collator_get_error_code' => ['int|false', 'coll'=>'collator'], 'collator_get_error_message' => ['string|false', 'coll'=>'collator'], 'collator_get_locale' => ['string|false', 'coll'=>'collator', 'type'=>'int'], 'collator_get_sort_key' => ['string|false', 'coll'=>'collator', 'str'=>'string'], 'collator_get_strength' => ['int', 'coll'=>'collator'], 'collator_set_attribute' => ['bool', 'coll'=>'collator', 'attr'=>'int', 'val'=>'int'], 'collator_set_strength' => ['bool', 'coll'=>'collator', 'strength'=>'int'], 'collator_sort' => ['bool', 'coll'=>'collator', '&rw_arr'=>'array', 'sort_flag='=>'int'], 'collator_sort_with_sort_keys' => ['bool', 'coll'=>'collator', '&rw_arr'=>'array'], 'Collectable::isGarbage' => ['bool'], 'colorObj::setHex' => ['int', 'hex'=>'string'], 'colorObj::toHex' => ['string'], 'COM::__call' => ['', 'name'=>'', 'args'=>''], 'COM::__construct' => ['void', 'module_name'=>'string', 'server_name='=>'mixed', 'codepage='=>'int', 'typelib='=>'string'], 'COM::__get' => ['', 'name'=>''], 'COM::__set' => ['', 'name'=>'', 'value'=>''], 'com_addref' => [''], 'com_create_guid' => ['string|false'], 'com_event_sink' => ['bool', 'comobject'=>'object', 'sinkobject'=>'object', 'sinkinterface='=>'mixed'], 'com_get_active_object' => ['object', 'progid'=>'string', 'code_page='=>'int'], 'com_isenum' => ['bool', 'com_module'=>'variant'], 'com_load_typelib' => ['bool', 'typelib_name'=>'string', 'case_insensitive='=>'int'], 'com_message_pump' => ['bool', 'timeoutms='=>'int'], 'com_print_typeinfo' => ['bool', 'comobject_or_typelib'=>'object', 'dispinterface='=>'string', 'wantsink='=>'bool'], 'com_release' => [''], 'compact' => ['array', '...var_names='=>'string|array'], 'COMPersistHelper::__construct' => ['void', 'com_object'=>'object'], 'COMPersistHelper::GetCurFile' => ['string'], 'COMPersistHelper::GetMaxStreamSize' => ['int'], 'COMPersistHelper::InitNew' => ['int'], 'COMPersistHelper::LoadFromFile' => ['bool', 'filename'=>'string', 'flags'=>'int'], 'COMPersistHelper::LoadFromStream' => ['', 'stream'=>''], 'COMPersistHelper::SaveToFile' => ['bool', 'filename'=>'string', 'remember'=>'bool'], 'COMPersistHelper::SaveToStream' => ['int', 'stream'=>''], 'componere\cast' => ['Type', 'arg1'=>'', 'object'=>''], 'componere\cast_by_ref' => ['Type', 'arg1'=>'', 'object'=>''], 'confirm_pdo_ibm_compiled' => [''], 'connection_aborted' => ['0|1'], 'connection_status' => ['int-mask'], 'connection_timeout' => ['int'], 'constant' => ['mixed', 'const_name'=>'string'], 'convert_cyr_string' => ['string', 'str'=>'string', 'from'=>'string', 'to'=>'string'], 'convert_uudecode' => ['string|false', 'data'=>'string'], 'convert_uuencode' => ['string', 'data'=>'string'], 'copy' => ['bool', 'source_file'=>'string', 'destination_file'=>'string', 'context='=>'resource'], 'cos' => ['float', 'number'=>'float'], 'cosh' => ['float', 'number'=>'float'], 'Couchbase\AnalyticsQuery::__construct' => ['void'], 'Couchbase\AnalyticsQuery::fromString' => ['Couchbase\AnalyticsQuery', 'statement'=>'string'], 'Couchbase\basicDecoderV1' => ['mixed', 'bytes'=>'string', 'flags'=>'int', 'datatype'=>'int', 'options'=>'array'], 'Couchbase\basicEncoderV1' => ['array', 'value'=>'mixed', 'options'=>'array'], 'Couchbase\BooleanFieldSearchQuery::__construct' => ['void'], 'Couchbase\BooleanFieldSearchQuery::boost' => ['Couchbase\BooleanFieldSearchQuery', 'boost'=>'float'], 'Couchbase\BooleanFieldSearchQuery::field' => ['Couchbase\BooleanFieldSearchQuery', 'field'=>'string'], 'Couchbase\BooleanFieldSearchQuery::jsonSerialize' => ['array'], 'Couchbase\BooleanSearchQuery::__construct' => ['void'], 'Couchbase\BooleanSearchQuery::boost' => ['Couchbase\BooleanSearchQuery', 'boost'=>'float'], 'Couchbase\BooleanSearchQuery::jsonSerialize' => ['array'], 'Couchbase\BooleanSearchQuery::must' => ['Couchbase\BooleanSearchQuery', '...queries='=>'array'], 'Couchbase\BooleanSearchQuery::mustNot' => ['Couchbase\BooleanSearchQuery', '...queries='=>'array'], 'Couchbase\BooleanSearchQuery::should' => ['Couchbase\BooleanSearchQuery', '...queries='=>'array'], 'Couchbase\Bucket::__construct' => ['void'], 'Couchbase\Bucket::__get' => ['int', 'name'=>'string'], 'Couchbase\Bucket::__set' => ['int', 'name'=>'string', 'value'=>'int'], 'Couchbase\Bucket::append' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\Bucket::counter' => ['Couchbase\Document|array', 'ids'=>'array|string', 'delta='=>'int', 'options='=>'array'], 'Couchbase\Bucket::diag' => ['array', 'reportId='=>'string'], 'Couchbase\Bucket::get' => ['Couchbase\Document|array', 'ids'=>'array|string', 'options='=>'array'], 'Couchbase\Bucket::getAndLock' => ['Couchbase\Document|array', 'ids'=>'array|string', 'lockTime'=>'int', 'options='=>'array'], 'Couchbase\Bucket::getAndTouch' => ['Couchbase\Document|array', 'ids'=>'array|string', 'expiry'=>'int', 'options='=>'array'], 'Couchbase\Bucket::getFromReplica' => ['Couchbase\Document|array', 'ids'=>'array|string', 'options='=>'array'], 'Couchbase\Bucket::insert' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\Bucket::listExists' => ['bool', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::listGet' => ['mixed', 'id'=>'string', 'index'=>'int'], 'Couchbase\Bucket::listPush' => ['', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::listRemove' => ['', 'id'=>'string', 'index'=>'int'], 'Couchbase\Bucket::listSet' => ['', 'id'=>'string', 'index'=>'int', 'value'=>'mixed'], 'Couchbase\Bucket::listShift' => ['', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::listSize' => ['int', 'id'=>'string'], 'Couchbase\Bucket::lookupIn' => ['Couchbase\LookupInBuilder', 'id'=>'string'], 'Couchbase\Bucket::manager' => ['Couchbase\BucketManager'], 'Couchbase\Bucket::mapAdd' => ['', 'id'=>'string', 'key'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::mapGet' => ['mixed', 'id'=>'string', 'key'=>'string'], 'Couchbase\Bucket::mapRemove' => ['', 'id'=>'string', 'key'=>'string'], 'Couchbase\Bucket::mapSize' => ['int', 'id'=>'string'], 'Couchbase\Bucket::mutateIn' => ['Couchbase\MutateInBuilder', 'id'=>'string', 'cas'=>'string'], 'Couchbase\Bucket::ping' => ['array', 'services='=>'int', 'reportId='=>'string'], 'Couchbase\Bucket::prepend' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\Bucket::query' => ['object', 'query'=>'Couchbase\AnalyticsQuery|Couchbase\N1qlQuery|Couchbase\SearchQuery|Couchbase\SpatialViewQuery|Couchbase\ViewQuery', 'jsonAsArray='=>'bool|false'], 'Couchbase\Bucket::queueAdd' => ['', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::queueExists' => ['bool', 'id'=>'string', 'value'=>'mixed'], 'Couchbase\Bucket::queueRemove' => ['mixed', 'id'=>'string'], 'Couchbase\Bucket::queueSize' => ['int', 'id'=>'string'], 'Couchbase\Bucket::remove' => ['Couchbase\Document|array', 'ids'=>'array|string', 'options='=>'array'], 'Couchbase\Bucket::replace' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\Bucket::retrieveIn' => ['Couchbase\DocumentFragment', 'id'=>'string', '...paths='=>'array'], 'Couchbase\Bucket::setAdd' => ['', 'id'=>'string', 'value'=>'bool|float|int|string'], 'Couchbase\Bucket::setExists' => ['bool', 'id'=>'string', 'value'=>'bool|float|int|string'], 'Couchbase\Bucket::setRemove' => ['', 'id'=>'string', 'value'=>'bool|float|int|string'], 'Couchbase\Bucket::setSize' => ['int', 'id'=>'string'], 'Couchbase\Bucket::setTranscoder' => ['', 'encoder'=>'callable', 'decoder'=>'callable'], 'Couchbase\Bucket::touch' => ['Couchbase\Document|array', 'ids'=>'array|string', 'expiry'=>'int', 'options='=>'array'], 'Couchbase\Bucket::unlock' => ['Couchbase\Document|array', 'ids'=>'array|string', 'options='=>'array'], 'Couchbase\Bucket::upsert' => ['Couchbase\Document|array', 'ids'=>'array|string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\BucketManager::__construct' => ['void'], 'Couchbase\BucketManager::createN1qlIndex' => ['', 'name'=>'string', 'fields'=>'array', 'whereClause='=>'string', 'ignoreIfExist='=>'bool|false', 'defer='=>'bool|false'], 'Couchbase\BucketManager::createN1qlPrimaryIndex' => ['', 'customName='=>'string', 'ignoreIfExist='=>'bool|false', 'defer='=>'bool|false'], 'Couchbase\BucketManager::dropN1qlIndex' => ['', 'name'=>'string', 'ignoreIfNotExist='=>'bool|false'], 'Couchbase\BucketManager::dropN1qlPrimaryIndex' => ['', 'customName='=>'string', 'ignoreIfNotExist='=>'bool|false'], 'Couchbase\BucketManager::flush' => [''], 'Couchbase\BucketManager::getDesignDocument' => ['array', 'name'=>'string'], 'Couchbase\BucketManager::info' => ['array'], 'Couchbase\BucketManager::insertDesignDocument' => ['', 'name'=>'string', 'document'=>'array'], 'Couchbase\BucketManager::listDesignDocuments' => ['array'], 'Couchbase\BucketManager::listN1qlIndexes' => ['array'], 'Couchbase\BucketManager::removeDesignDocument' => ['', 'name'=>'string'], 'Couchbase\BucketManager::upsertDesignDocument' => ['', 'name'=>'string', 'document'=>'array'], 'Couchbase\ClassicAuthenticator::bucket' => ['', 'name'=>'string', 'password'=>'string'], 'Couchbase\ClassicAuthenticator::cluster' => ['', 'username'=>'string', 'password'=>'string'], 'Couchbase\Cluster::__construct' => ['void', 'connstr'=>'string'], 'Couchbase\Cluster::authenticate' => ['null', 'authenticator'=>'Couchbase\Authenticator'], 'Couchbase\Cluster::authenticateAs' => ['null', 'username'=>'string', 'password'=>'string'], 'Couchbase\Cluster::manager' => ['Couchbase\ClusterManager', 'username='=>'string', 'password='=>'string'], 'Couchbase\Cluster::openBucket' => ['Couchbase\Bucket', 'name='=>'string', 'password='=>'string'], 'Couchbase\ClusterManager::__construct' => ['void'], 'Couchbase\ClusterManager::createBucket' => ['', 'name'=>'string', 'options='=>'array'], 'Couchbase\ClusterManager::getUser' => ['array', 'username'=>'string', 'domain='=>'int'], 'Couchbase\ClusterManager::info' => ['array'], 'Couchbase\ClusterManager::listBuckets' => ['array'], 'Couchbase\ClusterManager::listUsers' => ['array', 'domain='=>'int'], 'Couchbase\ClusterManager::removeBucket' => ['', 'name'=>'string'], 'Couchbase\ClusterManager::removeUser' => ['', 'name'=>'string', 'domain='=>'int'], 'Couchbase\ClusterManager::upsertUser' => ['', 'name'=>'string', 'settings'=>'Couchbase\UserSettings', 'domain='=>'int'], 'Couchbase\ConjunctionSearchQuery::__construct' => ['void'], 'Couchbase\ConjunctionSearchQuery::boost' => ['Couchbase\ConjunctionSearchQuery', 'boost'=>'float'], 'Couchbase\ConjunctionSearchQuery::every' => ['Couchbase\ConjunctionSearchQuery', '...queries='=>'array'], 'Couchbase\ConjunctionSearchQuery::jsonSerialize' => ['array'], 'Couchbase\DateRangeSearchFacet::__construct' => ['void'], 'Couchbase\DateRangeSearchFacet::addRange' => ['Couchbase\DateSearchFacet', 'name'=>'string', 'start'=>'int|string', 'end'=>'int|string'], 'Couchbase\DateRangeSearchFacet::jsonSerialize' => ['array'], 'Couchbase\DateRangeSearchQuery::__construct' => ['void'], 'Couchbase\DateRangeSearchQuery::boost' => ['Couchbase\DateRangeSearchQuery', 'boost'=>'float'], 'Couchbase\DateRangeSearchQuery::dateTimeParser' => ['Couchbase\DateRangeSearchQuery', 'dateTimeParser'=>'string'], 'Couchbase\DateRangeSearchQuery::end' => ['Couchbase\DateRangeSearchQuery', 'end'=>'int|string', 'inclusive='=>'bool|false'], 'Couchbase\DateRangeSearchQuery::field' => ['Couchbase\DateRangeSearchQuery', 'field'=>'string'], 'Couchbase\DateRangeSearchQuery::jsonSerialize' => ['array'], 'Couchbase\DateRangeSearchQuery::start' => ['Couchbase\DateRangeSearchQuery', 'start'=>'int|string', 'inclusive='=>'bool|true'], 'Couchbase\defaultDecoder' => ['mixed', 'bytes'=>'string', 'flags'=>'int', 'datatype'=>'int'], 'Couchbase\defaultEncoder' => ['array', 'value'=>'mixed'], 'Couchbase\DisjunctionSearchQuery::__construct' => ['void'], 'Couchbase\DisjunctionSearchQuery::boost' => ['Couchbase\DisjunctionSearchQuery', 'boost'=>'float'], 'Couchbase\DisjunctionSearchQuery::either' => ['Couchbase\DisjunctionSearchQuery', '...queries='=>'array'], 'Couchbase\DisjunctionSearchQuery::jsonSerialize' => ['array'], 'Couchbase\DisjunctionSearchQuery::min' => ['Couchbase\DisjunctionSearchQuery', 'min'=>'int'], 'Couchbase\DocIdSearchQuery::__construct' => ['void'], 'Couchbase\DocIdSearchQuery::boost' => ['Couchbase\DocIdSearchQuery', 'boost'=>'float'], 'Couchbase\DocIdSearchQuery::docIds' => ['Couchbase\DocIdSearchQuery', '...documentIds='=>'array'], 'Couchbase\DocIdSearchQuery::field' => ['Couchbase\DocIdSearchQuery', 'field'=>'string'], 'Couchbase\DocIdSearchQuery::jsonSerialize' => ['array'], 'Couchbase\fastlzCompress' => ['string', 'data'=>'string'], 'Couchbase\fastlzDecompress' => ['string', 'data'=>'string'], 'Couchbase\GeoBoundingBoxSearchQuery::__construct' => ['void'], 'Couchbase\GeoBoundingBoxSearchQuery::boost' => ['Couchbase\GeoBoundingBoxSearchQuery', 'boost'=>'float'], 'Couchbase\GeoBoundingBoxSearchQuery::field' => ['Couchbase\GeoBoundingBoxSearchQuery', 'field'=>'string'], 'Couchbase\GeoBoundingBoxSearchQuery::jsonSerialize' => ['array'], 'Couchbase\GeoDistanceSearchQuery::__construct' => ['void'], 'Couchbase\GeoDistanceSearchQuery::boost' => ['Couchbase\GeoDistanceSearchQuery', 'boost'=>'float'], 'Couchbase\GeoDistanceSearchQuery::field' => ['Couchbase\GeoDistanceSearchQuery', 'field'=>'string'], 'Couchbase\GeoDistanceSearchQuery::jsonSerialize' => ['array'], 'Couchbase\LookupInBuilder::__construct' => ['void'], 'Couchbase\LookupInBuilder::execute' => ['Couchbase\DocumentFragment'], 'Couchbase\LookupInBuilder::exists' => ['Couchbase\LookupInBuilder', 'path'=>'string', 'options='=>'array'], 'Couchbase\LookupInBuilder::get' => ['Couchbase\LookupInBuilder', 'path'=>'string', 'options='=>'array'], 'Couchbase\LookupInBuilder::getCount' => ['Couchbase\LookupInBuilder', 'path'=>'string', 'options='=>'array'], 'Couchbase\MatchAllSearchQuery::__construct' => ['void'], 'Couchbase\MatchAllSearchQuery::boost' => ['Couchbase\MatchAllSearchQuery', 'boost'=>'float'], 'Couchbase\MatchAllSearchQuery::jsonSerialize' => ['array'], 'Couchbase\MatchNoneSearchQuery::__construct' => ['void'], 'Couchbase\MatchNoneSearchQuery::boost' => ['Couchbase\MatchNoneSearchQuery', 'boost'=>'float'], 'Couchbase\MatchNoneSearchQuery::jsonSerialize' => ['array'], 'Couchbase\MatchPhraseSearchQuery::__construct' => ['void'], 'Couchbase\MatchPhraseSearchQuery::analyzer' => ['Couchbase\MatchPhraseSearchQuery', 'analyzer'=>'string'], 'Couchbase\MatchPhraseSearchQuery::boost' => ['Couchbase\MatchPhraseSearchQuery', 'boost'=>'float'], 'Couchbase\MatchPhraseSearchQuery::field' => ['Couchbase\MatchPhraseSearchQuery', 'field'=>'string'], 'Couchbase\MatchPhraseSearchQuery::jsonSerialize' => ['array'], 'Couchbase\MatchSearchQuery::__construct' => ['void'], 'Couchbase\MatchSearchQuery::analyzer' => ['Couchbase\MatchSearchQuery', 'analyzer'=>'string'], 'Couchbase\MatchSearchQuery::boost' => ['Couchbase\MatchSearchQuery', 'boost'=>'float'], 'Couchbase\MatchSearchQuery::field' => ['Couchbase\MatchSearchQuery', 'field'=>'string'], 'Couchbase\MatchSearchQuery::fuzziness' => ['Couchbase\MatchSearchQuery', 'fuzziness'=>'int'], 'Couchbase\MatchSearchQuery::jsonSerialize' => ['array'], 'Couchbase\MatchSearchQuery::prefixLength' => ['Couchbase\MatchSearchQuery', 'prefixLength'=>'int'], 'Couchbase\MutateInBuilder::__construct' => ['void'], 'Couchbase\MutateInBuilder::arrayAddUnique' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::arrayAppend' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::arrayAppendAll' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'values'=>'array', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::arrayInsert' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\MutateInBuilder::arrayInsertAll' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'values'=>'array', 'options='=>'array'], 'Couchbase\MutateInBuilder::arrayPrepend' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::arrayPrependAll' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'values'=>'array', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::counter' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'delta'=>'int', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::execute' => ['Couchbase\DocumentFragment'], 'Couchbase\MutateInBuilder::insert' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::modeDocument' => ['', 'mode'=>'int'], 'Couchbase\MutateInBuilder::remove' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'options='=>'array'], 'Couchbase\MutateInBuilder::replace' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array'], 'Couchbase\MutateInBuilder::upsert' => ['Couchbase\MutateInBuilder', 'path'=>'string', 'value'=>'mixed', 'options='=>'array|bool'], 'Couchbase\MutateInBuilder::withExpiry' => ['Couchbase\MutateInBuilder', 'expiry'=>'Couchbase\expiry'], 'Couchbase\MutationState::__construct' => ['void'], 'Couchbase\MutationState::add' => ['', 'source'=>'Couchbase\Document|Couchbase\DocumentFragment|array'], 'Couchbase\MutationState::from' => ['Couchbase\MutationState', 'source'=>'Couchbase\Document|Couchbase\DocumentFragment|array'], 'Couchbase\MutationToken::__construct' => ['void'], 'Couchbase\MutationToken::bucketName' => ['string'], 'Couchbase\MutationToken::from' => ['', 'bucketName'=>'string', 'vbucketId'=>'int', 'vbucketUuid'=>'string', 'sequenceNumber'=>'string'], 'Couchbase\MutationToken::sequenceNumber' => ['string'], 'Couchbase\MutationToken::vbucketId' => ['int'], 'Couchbase\MutationToken::vbucketUuid' => ['string'], 'Couchbase\N1qlIndex::__construct' => ['void'], 'Couchbase\N1qlQuery::__construct' => ['void'], 'Couchbase\N1qlQuery::adhoc' => ['Couchbase\N1qlQuery', 'adhoc'=>'bool'], 'Couchbase\N1qlQuery::consistency' => ['Couchbase\N1qlQuery', 'consistency'=>'int'], 'Couchbase\N1qlQuery::consistentWith' => ['Couchbase\N1qlQuery', 'state'=>'Couchbase\MutationState'], 'Couchbase\N1qlQuery::crossBucket' => ['Couchbase\N1qlQuery', 'crossBucket'=>'bool'], 'Couchbase\N1qlQuery::fromString' => ['Couchbase\N1qlQuery', 'statement'=>'string'], 'Couchbase\N1qlQuery::maxParallelism' => ['Couchbase\N1qlQuery', 'maxParallelism'=>'int'], 'Couchbase\N1qlQuery::namedParams' => ['Couchbase\N1qlQuery', 'params'=>'array'], 'Couchbase\N1qlQuery::pipelineBatch' => ['Couchbase\N1qlQuery', 'pipelineBatch'=>'int'], 'Couchbase\N1qlQuery::pipelineCap' => ['Couchbase\N1qlQuery', 'pipelineCap'=>'int'], 'Couchbase\N1qlQuery::positionalParams' => ['Couchbase\N1qlQuery', 'params'=>'array'], 'Couchbase\N1qlQuery::readonly' => ['Couchbase\N1qlQuery', 'readonly'=>'bool'], 'Couchbase\N1qlQuery::scanCap' => ['Couchbase\N1qlQuery', 'scanCap'=>'int'], 'Couchbase\NumericRangeSearchFacet::__construct' => ['void'], 'Couchbase\NumericRangeSearchFacet::addRange' => ['Couchbase\NumericSearchFacet', 'name'=>'string', 'min'=>'float', 'max'=>'float'], 'Couchbase\NumericRangeSearchFacet::jsonSerialize' => ['array'], 'Couchbase\NumericRangeSearchQuery::__construct' => ['void'], 'Couchbase\NumericRangeSearchQuery::boost' => ['Couchbase\NumericRangeSearchQuery', 'boost'=>'float'], 'Couchbase\NumericRangeSearchQuery::field' => ['Couchbase\NumericRangeSearchQuery', 'field'=>'string'], 'Couchbase\NumericRangeSearchQuery::jsonSerialize' => ['array'], 'Couchbase\NumericRangeSearchQuery::max' => ['Couchbase\NumericRangeSearchQuery', 'max'=>'float', 'inclusive='=>'bool|false'], 'Couchbase\NumericRangeSearchQuery::min' => ['Couchbase\NumericRangeSearchQuery', 'min'=>'float', 'inclusive='=>'bool|true'], 'Couchbase\passthruDecoder' => ['string', 'bytes'=>'string', 'flags'=>'int', 'datatype'=>'int'], 'Couchbase\passthruEncoder' => ['array', 'value'=>'string'], 'Couchbase\PasswordAuthenticator::password' => ['Couchbase\PasswordAuthenticator', 'password'=>'string'], 'Couchbase\PasswordAuthenticator::username' => ['Couchbase\PasswordAuthenticator', 'username'=>'string'], 'Couchbase\PhraseSearchQuery::__construct' => ['void'], 'Couchbase\PhraseSearchQuery::boost' => ['Couchbase\PhraseSearchQuery', 'boost'=>'float'], 'Couchbase\PhraseSearchQuery::field' => ['Couchbase\PhraseSearchQuery', 'field'=>'string'], 'Couchbase\PhraseSearchQuery::jsonSerialize' => ['array'], 'Couchbase\PrefixSearchQuery::__construct' => ['void'], 'Couchbase\PrefixSearchQuery::boost' => ['Couchbase\PrefixSearchQuery', 'boost'=>'float'], 'Couchbase\PrefixSearchQuery::field' => ['Couchbase\PrefixSearchQuery', 'field'=>'string'], 'Couchbase\PrefixSearchQuery::jsonSerialize' => ['array'], 'Couchbase\QueryStringSearchQuery::__construct' => ['void'], 'Couchbase\QueryStringSearchQuery::boost' => ['Couchbase\QueryStringSearchQuery', 'boost'=>'float'], 'Couchbase\QueryStringSearchQuery::jsonSerialize' => ['array'], 'Couchbase\RegexpSearchQuery::__construct' => ['void'], 'Couchbase\RegexpSearchQuery::boost' => ['Couchbase\RegexpSearchQuery', 'boost'=>'float'], 'Couchbase\RegexpSearchQuery::field' => ['Couchbase\RegexpSearchQuery', 'field'=>'string'], 'Couchbase\RegexpSearchQuery::jsonSerialize' => ['array'], 'Couchbase\SearchQuery::__construct' => ['void', 'indexName'=>'string', 'queryPart'=>'Couchbase\SearchQueryPart'], 'Couchbase\SearchQuery::addFacet' => ['Couchbase\SearchQuery', 'name'=>'string', 'facet'=>'Couchbase\SearchFacet'], 'Couchbase\SearchQuery::boolean' => ['Couchbase\BooleanSearchQuery'], 'Couchbase\SearchQuery::booleanField' => ['Couchbase\BooleanFieldSearchQuery', 'value'=>'bool'], 'Couchbase\SearchQuery::conjuncts' => ['Couchbase\ConjunctionSearchQuery', '...queries='=>'array'], 'Couchbase\SearchQuery::consistentWith' => ['Couchbase\SearchQuery', 'state'=>'Couchbase\MutationState'], 'Couchbase\SearchQuery::dateRange' => ['Couchbase\DateRangeSearchQuery'], 'Couchbase\SearchQuery::dateRangeFacet' => ['Couchbase\DateRangeSearchFacet', 'field'=>'string', 'limit'=>'int'], 'Couchbase\SearchQuery::disjuncts' => ['Couchbase\DisjunctionSearchQuery', '...queries='=>'array'], 'Couchbase\SearchQuery::docId' => ['Couchbase\DocIdSearchQuery', '...documentIds='=>'array'], 'Couchbase\SearchQuery::explain' => ['Couchbase\SearchQuery', 'explain'=>'bool'], 'Couchbase\SearchQuery::fields' => ['Couchbase\SearchQuery', '...fields='=>'array'], 'Couchbase\SearchQuery::geoBoundingBox' => ['Couchbase\GeoBoundingBoxSearchQuery', 'topLeftLongitude'=>'float', 'topLeftLatitude'=>'float', 'bottomRightLongitude'=>'float', 'bottomRightLatitude'=>'float'], 'Couchbase\SearchQuery::geoDistance' => ['Couchbase\GeoDistanceSearchQuery', 'longitude'=>'float', 'latitude'=>'float', 'distance'=>'string'], 'Couchbase\SearchQuery::highlight' => ['Couchbase\SearchQuery', 'style'=>'string', '...fields='=>'array'], 'Couchbase\SearchQuery::jsonSerialize' => ['array'], 'Couchbase\SearchQuery::limit' => ['Couchbase\SearchQuery', 'limit'=>'int'], 'Couchbase\SearchQuery::match' => ['Couchbase\MatchSearchQuery', 'match'=>'string'], 'Couchbase\SearchQuery::matchAll' => ['Couchbase\MatchAllSearchQuery'], 'Couchbase\SearchQuery::matchNone' => ['Couchbase\MatchNoneSearchQuery'], 'Couchbase\SearchQuery::matchPhrase' => ['Couchbase\MatchPhraseSearchQuery', '...terms='=>'array'], 'Couchbase\SearchQuery::numericRange' => ['Couchbase\NumericRangeSearchQuery'], 'Couchbase\SearchQuery::numericRangeFacet' => ['Couchbase\NumericRangeSearchFacet', 'field'=>'string', 'limit'=>'int'], 'Couchbase\SearchQuery::prefix' => ['Couchbase\PrefixSearchQuery', 'prefix'=>'string'], 'Couchbase\SearchQuery::queryString' => ['Couchbase\QueryStringSearchQuery', 'queryString'=>'string'], 'Couchbase\SearchQuery::regexp' => ['Couchbase\RegexpSearchQuery', 'regexp'=>'string'], 'Couchbase\SearchQuery::serverSideTimeout' => ['Couchbase\SearchQuery', 'serverSideTimeout'=>'int'], 'Couchbase\SearchQuery::skip' => ['Couchbase\SearchQuery', 'skip'=>'int'], 'Couchbase\SearchQuery::sort' => ['Couchbase\SearchQuery', '...sort='=>'array'], 'Couchbase\SearchQuery::term' => ['Couchbase\TermSearchQuery', 'term'=>'string'], 'Couchbase\SearchQuery::termFacet' => ['Couchbase\TermSearchFacet', 'field'=>'string', 'limit'=>'int'], 'Couchbase\SearchQuery::termRange' => ['Couchbase\TermRangeSearchQuery'], 'Couchbase\SearchQuery::wildcard' => ['Couchbase\WildcardSearchQuery', 'wildcard'=>'string'], 'Couchbase\SpatialViewQuery::__construct' => ['void'], 'Couchbase\SpatialViewQuery::bbox' => ['Couchbase\SpatialViewQuery', 'bbox'=>'array'], 'Couchbase\SpatialViewQuery::consistency' => ['Couchbase\SpatialViewQuery', 'consistency'=>'int'], 'Couchbase\SpatialViewQuery::custom' => ['', 'customParameters'=>'array'], 'Couchbase\SpatialViewQuery::encode' => ['array'], 'Couchbase\SpatialViewQuery::endRange' => ['Couchbase\SpatialViewQuery', 'range'=>'array'], 'Couchbase\SpatialViewQuery::limit' => ['Couchbase\SpatialViewQuery', 'limit'=>'int'], 'Couchbase\SpatialViewQuery::order' => ['Couchbase\SpatialViewQuery', 'order'=>'int'], 'Couchbase\SpatialViewQuery::skip' => ['Couchbase\SpatialViewQuery', 'skip'=>'int'], 'Couchbase\SpatialViewQuery::startRange' => ['Couchbase\SpatialViewQuery', 'range'=>'array'], 'Couchbase\TermRangeSearchQuery::__construct' => ['void'], 'Couchbase\TermRangeSearchQuery::boost' => ['Couchbase\TermRangeSearchQuery', 'boost'=>'float'], 'Couchbase\TermRangeSearchQuery::field' => ['Couchbase\TermRangeSearchQuery', 'field'=>'string'], 'Couchbase\TermRangeSearchQuery::jsonSerialize' => ['array'], 'Couchbase\TermRangeSearchQuery::max' => ['Couchbase\TermRangeSearchQuery', 'max'=>'string', 'inclusive='=>'bool|false'], 'Couchbase\TermRangeSearchQuery::min' => ['Couchbase\TermRangeSearchQuery', 'min'=>'string', 'inclusive='=>'bool|true'], 'Couchbase\TermSearchFacet::__construct' => ['void'], 'Couchbase\TermSearchFacet::jsonSerialize' => ['array'], 'Couchbase\TermSearchQuery::__construct' => ['void'], 'Couchbase\TermSearchQuery::boost' => ['Couchbase\TermSearchQuery', 'boost'=>'float'], 'Couchbase\TermSearchQuery::field' => ['Couchbase\TermSearchQuery', 'field'=>'string'], 'Couchbase\TermSearchQuery::fuzziness' => ['Couchbase\TermSearchQuery', 'fuzziness'=>'int'], 'Couchbase\TermSearchQuery::jsonSerialize' => ['array'], 'Couchbase\TermSearchQuery::prefixLength' => ['Couchbase\TermSearchQuery', 'prefixLength'=>'int'], 'Couchbase\UserSettings::fullName' => ['Couchbase\UserSettings', 'fullName'=>'string'], 'Couchbase\UserSettings::password' => ['Couchbase\UserSettings', 'password'=>'string'], 'Couchbase\UserSettings::role' => ['Couchbase\UserSettings', 'role'=>'string', 'bucket='=>'string'], 'Couchbase\ViewQuery::__construct' => ['void'], 'Couchbase\ViewQuery::consistency' => ['Couchbase\ViewQuery', 'consistency'=>'int'], 'Couchbase\ViewQuery::custom' => ['Couchbase\ViewQuery', 'customParameters'=>'array'], 'Couchbase\ViewQuery::encode' => ['array'], 'Couchbase\ViewQuery::from' => ['Couchbase\ViewQuery', 'designDocumentName'=>'string', 'viewName'=>'string'], 'Couchbase\ViewQuery::fromSpatial' => ['Couchbase\SpatialViewQuery', 'designDocumentName'=>'string', 'viewName'=>'string'], 'Couchbase\ViewQuery::group' => ['Couchbase\ViewQuery', 'group'=>'bool'], 'Couchbase\ViewQuery::groupLevel' => ['Couchbase\ViewQuery', 'groupLevel'=>'int'], 'Couchbase\ViewQuery::idRange' => ['Couchbase\ViewQuery', 'startKeyDocumentId'=>'string', 'endKeyDocumentId'=>'string'], 'Couchbase\ViewQuery::key' => ['Couchbase\ViewQuery', 'key'=>'mixed'], 'Couchbase\ViewQuery::keys' => ['Couchbase\ViewQuery', 'keys'=>'array'], 'Couchbase\ViewQuery::limit' => ['Couchbase\ViewQuery', 'limit'=>'int'], 'Couchbase\ViewQuery::order' => ['Couchbase\ViewQuery', 'order'=>'int'], 'Couchbase\ViewQuery::range' => ['Couchbase\ViewQuery', 'startKey'=>'mixed', 'endKey'=>'mixed', 'inclusiveEnd='=>'bool|false'], 'Couchbase\ViewQuery::reduce' => ['Couchbase\ViewQuery', 'reduce'=>'bool'], 'Couchbase\ViewQuery::skip' => ['Couchbase\ViewQuery', 'skip'=>'int'], 'Couchbase\ViewQueryEncodable::encode' => ['array'], 'Couchbase\WildcardSearchQuery::__construct' => ['void'], 'Couchbase\WildcardSearchQuery::boost' => ['Couchbase\WildcardSearchQuery', 'boost'=>'float'], 'Couchbase\WildcardSearchQuery::field' => ['Couchbase\WildcardSearchQuery', 'field'=>'string'], 'Couchbase\WildcardSearchQuery::jsonSerialize' => ['array'], 'Couchbase\zlibCompress' => ['string', 'data'=>'string'], 'Couchbase\zlibDecompress' => ['string', 'data'=>'string'], 'count' => ['0|positive-int', 'var'=>'Countable|array', 'mode='=>'int'], 'count_chars' => ['mixed', 'input'=>'string', 'mode='=>'0|1|2|3|4'], 'Countable::count' => ['0|positive-int'], 'crack_check' => ['bool', 'dictionary'=>'', 'password'=>'string'], 'crack_closedict' => ['bool', 'dictionary='=>'resource'], 'crack_getlastmessage' => ['string'], 'crack_opendict' => ['resource', 'dictionary'=>'string'], 'crash' => [''], 'crc32' => ['int', 'str'=>'string'], 'create_function' => ['string', 'args'=>'string', 'code'=>'string'], 'crypt' => ['non-empty-string', 'str'=>'string', 'salt='=>'string'], 'ctype_alnum' => ['bool', 'c'=>'mixed'], 'ctype_alpha' => ['bool', 'c'=>'mixed'], 'ctype_cntrl' => ['bool', 'c'=>'mixed'], 'ctype_digit' => ['bool', 'c'=>'mixed'], 'ctype_graph' => ['bool', 'c'=>'mixed'], 'ctype_lower' => ['bool', 'c'=>'mixed'], 'ctype_print' => ['bool', 'c'=>'mixed'], 'ctype_punct' => ['bool', 'c'=>'mixed'], 'ctype_space' => ['bool', 'c'=>'mixed'], 'ctype_upper' => ['bool', 'c'=>'mixed'], 'ctype_xdigit' => ['bool', 'c'=>'mixed'], 'cubrid_affected_rows' => ['int', 'req_identifier='=>''], 'cubrid_bind' => ['bool', 'req_identifier'=>'resource', 'bind_param'=>'int', 'bind_value'=>'mixed', 'bind_value_type='=>'string'], 'cubrid_client_encoding' => ['string', 'conn_identifier='=>''], 'cubrid_close' => ['bool', 'conn_identifier='=>''], 'cubrid_close_prepare' => ['bool', 'req_identifier'=>'resource'], 'cubrid_close_request' => ['bool', 'req_identifier'=>'resource'], 'cubrid_col_get' => ['array', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string'], 'cubrid_col_size' => ['int', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string'], 'cubrid_column_names' => ['array', 'req_identifier'=>'resource'], 'cubrid_column_types' => ['array', 'req_identifier'=>'resource'], 'cubrid_commit' => ['bool', 'conn_identifier'=>'resource'], 'cubrid_connect' => ['resource', 'host'=>'string', 'port'=>'int', 'dbname'=>'string', 'userid='=>'string', 'passwd='=>'string'], 'cubrid_connect_with_url' => ['resource', 'conn_url'=>'string', 'userid='=>'string', 'passwd='=>'string'], 'cubrid_current_oid' => ['string', 'req_identifier'=>'resource'], 'cubrid_data_seek' => ['bool', 'req_identifier'=>'', 'row_number'=>'int'], 'cubrid_db_name' => ['string', 'result'=>'array', 'index'=>'int'], 'cubrid_db_parameter' => ['array', 'conn_identifier'=>'resource'], 'cubrid_disconnect' => ['bool', 'conn_identifier'=>'resource'], 'cubrid_drop' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_errno' => ['int', 'conn_identifier='=>''], 'cubrid_error' => ['string', 'connection='=>''], 'cubrid_error_code' => ['int'], 'cubrid_error_code_facility' => ['int'], 'cubrid_error_msg' => ['string'], 'cubrid_execute' => ['bool', 'conn_identifier'=>'', 'sql'=>'string', 'option='=>'int', 'request_identifier='=>''], 'cubrid_fetch' => ['mixed', 'result'=>'resource', 'type='=>'int'], 'cubrid_fetch_array' => ['array', 'result'=>'', 'type='=>'int'], 'cubrid_fetch_assoc' => ['array', 'result'=>''], 'cubrid_fetch_field' => ['object', 'result'=>'', 'field_offset='=>'int'], 'cubrid_fetch_lengths' => ['array', 'result'=>''], 'cubrid_fetch_object' => ['object', 'result'=>'', 'class_name='=>'string', 'params='=>'array'], 'cubrid_fetch_row' => ['array', 'result'=>''], 'cubrid_field_flags' => ['string', 'result'=>'', 'field_offset'=>'int'], 'cubrid_field_len' => ['int', 'result'=>'', 'field_offset'=>'int'], 'cubrid_field_name' => ['string', 'result'=>'', 'field_offset'=>'int'], 'cubrid_field_seek' => ['bool', 'result'=>'', 'field_offset='=>'int'], 'cubrid_field_table' => ['string', 'result'=>'', 'field_offset'=>'int'], 'cubrid_field_type' => ['string', 'result'=>'', 'field_offset'=>'int'], 'cubrid_free_result' => ['bool', 'req_identifier'=>'resource'], 'cubrid_get' => ['mixed', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr='=>'mixed'], 'cubrid_get_autocommit' => ['bool', 'conn_identifier'=>'resource'], 'cubrid_get_charset' => ['string', 'conn_identifier'=>'resource'], 'cubrid_get_class_name' => ['string', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_get_client_info' => ['string'], 'cubrid_get_db_parameter' => ['array', 'conn_identifier'=>'resource'], 'cubrid_get_query_timeout' => ['int', 'req_identifier'=>'resource'], 'cubrid_get_server_info' => ['string', 'conn_identifier'=>'resource'], 'cubrid_insert_id' => ['string', 'conn_identifier='=>'resource'], 'cubrid_is_instance' => ['int', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_list_dbs' => ['array', 'conn_identifier'=>''], 'cubrid_load_from_glo' => ['int', 'conn_identifier'=>'', 'oid'=>'string', 'file_name'=>'string'], 'cubrid_lob2_bind' => ['bool', 'req_identifier'=>'resource', 'bind_index'=>'int', 'bind_value'=>'mixed', 'bind_value_type='=>'string'], 'cubrid_lob2_close' => ['bool', 'lob_identifier'=>'resource'], 'cubrid_lob2_export' => ['bool', 'lob_identifier'=>'resource', 'file_name'=>'string'], 'cubrid_lob2_import' => ['bool', 'lob_identifier'=>'resource', 'file_name'=>'string'], 'cubrid_lob2_new' => ['resource', 'conn_identifier='=>'resource', 'type='=>'string'], 'cubrid_lob2_read' => ['string', 'lob_identifier'=>'resource', 'len'=>'int'], 'cubrid_lob2_seek' => ['bool', 'lob_identifier'=>'resource', 'offset'=>'int', 'origin='=>'int'], 'cubrid_lob2_seek64' => ['bool', 'lob_identifier'=>'resource', 'offset'=>'string', 'origin='=>'int'], 'cubrid_lob2_size' => ['int', 'lob_identifier'=>'resource'], 'cubrid_lob2_size64' => ['string', 'lob_identifier'=>'resource'], 'cubrid_lob2_tell' => ['int', 'lob_identifier'=>'resource'], 'cubrid_lob2_tell64' => ['string', 'lob_identifier'=>'resource'], 'cubrid_lob2_write' => ['bool', 'lob_identifier'=>'resource', 'buf'=>'string'], 'cubrid_lob_close' => ['bool', 'lob_identifier_array'=>'array'], 'cubrid_lob_export' => ['bool', 'conn_identifier'=>'resource', 'lob_identifier'=>'resource', 'path_name'=>'string'], 'cubrid_lob_get' => ['array', 'conn_identifier'=>'resource', 'sql'=>'string'], 'cubrid_lob_send' => ['bool', 'conn_identifier'=>'resource', 'lob_identifier'=>'resource'], 'cubrid_lob_size' => ['string', 'lob_identifier'=>'resource'], 'cubrid_lock_read' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_lock_write' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string'], 'cubrid_move_cursor' => ['int', 'req_identifier'=>'resource', 'offset'=>'int', 'origin='=>'int'], 'cubrid_new_glo' => ['string', 'conn_identifier'=>'', 'class_name'=>'string', 'file_name'=>'string'], 'cubrid_next_result' => ['bool', 'result'=>'resource'], 'cubrid_num_cols' => ['int', 'req_identifier'=>'resource'], 'cubrid_num_fields' => ['int', 'result'=>''], 'cubrid_num_rows' => ['int', 'req_identifier'=>'resource'], 'cubrid_pconnect' => ['resource', 'host'=>'string', 'port'=>'int', 'dbname'=>'string', 'userid='=>'string', 'passwd='=>'string'], 'cubrid_pconnect_with_url' => ['resource', 'conn_url'=>'string', 'userid='=>'string', 'passwd='=>'string'], 'cubrid_ping' => ['bool', 'conn_identifier='=>''], 'cubrid_prepare' => ['resource', 'conn_identifier'=>'resource', 'prepare_stmt'=>'string', 'option='=>'int'], 'cubrid_put' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr='=>'string', 'value='=>'mixed'], 'cubrid_query' => ['resource', 'query'=>'string', 'conn_identifier='=>''], 'cubrid_real_escape_string' => ['string', 'unescaped_string'=>'string', 'conn_identifier='=>''], 'cubrid_result' => ['string', 'result'=>'', 'row'=>'int', 'field='=>''], 'cubrid_rollback' => ['bool', 'conn_identifier'=>'resource'], 'cubrid_save_to_glo' => ['int', 'conn_identifier'=>'', 'oid'=>'string', 'file_name'=>'string'], 'cubrid_schema' => ['array', 'conn_identifier'=>'resource', 'schema_type'=>'int', 'class_name='=>'string', 'attr_name='=>'string'], 'cubrid_send_glo' => ['int', 'conn_identifier'=>'', 'oid'=>'string'], 'cubrid_seq_drop' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'index'=>'int'], 'cubrid_seq_insert' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'index'=>'int', 'seq_element'=>'string'], 'cubrid_seq_put' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'index'=>'int', 'seq_element'=>'string'], 'cubrid_set_add' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'set_element'=>'string'], 'cubrid_set_autocommit' => ['bool', 'conn_identifier'=>'resource', 'mode'=>'bool'], 'cubrid_set_db_parameter' => ['bool', 'conn_identifier'=>'resource', 'param_type'=>'int', 'param_value'=>'int'], 'cubrid_set_drop' => ['bool', 'conn_identifier'=>'resource', 'oid'=>'string', 'attr_name'=>'string', 'set_element'=>'string'], 'cubrid_set_query_timeout' => ['bool', 'req_identifier'=>'resource', 'timeout'=>'int'], 'cubrid_unbuffered_query' => ['resource', 'query'=>'string', 'conn_identifier='=>''], 'cubrid_version' => ['string'], 'curl_close' => ['void', 'ch'=>'resource'], 'curl_copy_handle' => ['resource|false', 'ch'=>'resource'], 'curl_errno' => ['int', 'ch'=>'resource'], 'curl_error' => ['string', 'ch'=>'resource'], 'curl_escape' => ['string|false', 'ch'=>'resource', 'str'=>'string'], 'curl_exec' => ['bool|string', 'ch'=>'resource'], 'curl_file_create' => ['CURLFile', 'filename'=>'string', 'mimetype='=>'string', 'postfilename='=>'string'], 'curl_getinfo' => ['mixed', 'ch'=>'resource', 'option='=>'int'], 'curl_init' => ['__benevolent', 'url='=>'string'], 'curl_multi_add_handle' => ['int', 'mh'=>'resource', 'ch'=>'resource'], 'curl_multi_close' => ['void', 'mh'=>'resource'], 'curl_multi_errno' => ['int', 'mh'=>'resource'], 'curl_multi_exec' => ['int', 'mh'=>'resource', '&w_still_running'=>'int'], 'curl_multi_getcontent' => ['string|null', 'ch'=>'resource'], 'curl_multi_info_read' => ['array|false', 'mh'=>'resource', '&w_msgs_in_queue='=>'int'], 'curl_multi_init' => ['resource'], 'curl_multi_remove_handle' => ['int', 'mh'=>'resource', 'ch'=>'resource'], 'curl_multi_select' => ['int', 'mh'=>'resource', 'timeout='=>'float'], 'curl_multi_setopt' => ['bool', 'mh'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'curl_multi_strerror' => ['string', 'code'=>'int'], 'curl_pause' => ['int', 'ch'=>'resource', 'bitmask'=>'int'], 'curl_reset' => ['void', 'ch'=>'resource'], 'curl_setopt' => ['bool', 'ch'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'curl_setopt_array' => ['bool', 'ch'=>'resource', 'options'=>'array'], 'curl_share_close' => ['void', 'sh'=>'resource'], 'curl_share_errno' => ['int', 'sh'=>'resource'], 'curl_share_init' => ['resource'], 'curl_share_setopt' => ['bool', 'sh'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'curl_share_strerror' => ['string', 'code'=>'int'], 'curl_strerror' => ['string', 'code'=>'int'], 'curl_unescape' => ['string|false', 'ch'=>'resource', 'str'=>'string'], 'curl_version' => ['array|false', 'version='=>'int'], 'CURLFile::__construct' => ['void', 'filename'=>'string', 'mimetype='=>'string', 'postfilename='=>'string'], 'CURLFile::__wakeup' => ['void'], 'CURLFile::getFilename' => ['string'], 'CURLFile::getMimeType' => ['string'], 'CURLFile::getPostFilename' => ['string'], 'CURLFile::setMimeType' => ['void', 'mime'=>'string'], 'CURLFile::setPostFilename' => ['void', 'name'=>'string'], 'current' => ['mixed', 'array_arg'=>'array|object'], 'cyrus_authenticate' => ['void', 'connection'=>'resource', 'mechlist='=>'string', 'service='=>'string', 'user='=>'string', 'minssf='=>'int', 'maxssf='=>'int', 'authname='=>'string', 'password='=>'string'], 'cyrus_bind' => ['bool', 'connection'=>'resource', 'callbacks'=>'array'], 'cyrus_close' => ['bool', 'connection'=>'resource'], 'cyrus_connect' => ['resource', 'host='=>'string', 'port='=>'string', 'flags='=>'int'], 'cyrus_query' => ['array', 'connection'=>'resource', 'query'=>'string'], 'cyrus_unbind' => ['bool', 'connection'=>'resource', 'trigger_name'=>'string'], 'date' => ['string', 'format'=>'string', 'timestamp='=>'int'], 'date_add' => ['DateTime|false', 'object'=>'', 'interval'=>''], 'date_create' => ['DateTime|false', 'time='=>'string|null', 'timezone='=>'?DateTimeZone'], 'date_create_from_format' => ['DateTime|false', 'format'=>'string', 'time'=>'string', 'timezone='=>'?DateTimeZone'], 'date_create_immutable' => ['DateTimeImmutable|false', 'time='=>'string', 'timezone='=>'?DateTimeZone'], 'date_create_immutable_from_format' => ['DateTimeImmutable|false', 'format'=>'string', 'time'=>'string', 'timezone='=>'?DateTimeZone'], 'date_date_set' => ['DateTime|false', 'object'=>'', 'year'=>'', 'month'=>'', 'day'=>''], 'date_default_timezone_get' => ['string'], 'date_default_timezone_set' => ['bool', 'timezone_identifier'=>'string'], 'date_diff' => ['DateInterval', 'obj1'=>'DateTimeInterface', 'obj2'=>'DateTimeInterface', 'absolute='=>'bool'], 'date_format' => ['string', 'obj'=>'DateTimeInterface', 'format'=>'string'], 'date_get_last_errors' => ['array{warning_count: 0|positive-int, warnings: list, error_count: 0|positive-int, errors: list}|false'], 'date_interval_create_from_date_string' => ['DateInterval|false', 'time'=>'string'], 'date_interval_format' => ['string', 'object'=>'DateInterval', 'format'=>'string'], 'date_isodate_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'day='=>'int|mixed'], 'date_modify' => ['DateTime|false', 'object'=>'DateTime', 'modify'=>'string'], 'date_offset_get' => ['int', 'obj'=>'DateTimeInterface'], 'date_parse' => ['array{year: int|false, month: int|false, day: int|false, hour: int|false, minute: int|false, second: int|false, fraction: float|false, warning_count: int, warnings: string[], error_count: int, errors: string[], is_localtime: bool, zone_type?: int|bool, zone?: int|bool, is_dst?: bool, tz_abbr?: string, tz_id?: string, relative?: array{year: int, month: int, day: int, hour: int, minute: int, second: int, weekday?: int, weekdays?: int, first_day_of_month?: bool, last_day_of_month?: bool}}', 'date'=>'string'], 'date_parse_from_format' => ['array{year: int|false, month: int|false, day: int|false, hour: int|false, minute: int|false, second: int|false, fraction: float|false, warning_count: int, warnings: string[], error_count: int, errors: string[], is_localtime: bool, zone_type?: int|bool, zone?: int|bool, is_dst?: bool, tz_abbr?: string, tz_id?: string, relative?: array{year: int, month: int, day: int, hour: int, minute: int, second: int, weekday?: int, weekdays?: int, first_day_of_month?: bool, last_day_of_month?: bool}}', 'format'=>'string', 'date'=>'string'], 'date_sub' => ['DateTime|false', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_sun_info' => ['__benevolent', 'time'=>'int', 'latitude'=>'float', 'longitude'=>'float'], 'date_sunrise' => ['mixed', 'time'=>'int', 'format='=>'int', 'latitude='=>'float', 'longitude='=>'float', 'zenith='=>'float', 'gmt_offset='=>'float'], 'date_sunset' => ['mixed', 'time'=>'int', 'format='=>'int', 'latitude='=>'float', 'longitude='=>'float', 'zenith='=>'float', 'gmt_offset='=>'float'], 'date_time_set' => ['DateTime|false', 'object'=>'', 'hour'=>'', 'minute'=>'', 'second='=>'', 'microseconds='=>''], 'date_timestamp_get' => ['int', 'obj'=>'DateTimeInterface'], 'date_timestamp_set' => ['DateTime|false', 'object'=>'DateTime', 'unixtimestamp'=>'int'], 'date_timezone_get' => ['DateTimeZone|false', 'obj'=>'DateTimeInterface'], 'date_timezone_set' => ['DateTime|false', 'object'=>'DateTime', 'timezone'=>'DateTimeZone'], 'datefmt_create' => ['IntlDateFormatter|false', 'locale'=>'?string', 'datetype'=>'?int', 'timetype'=>'?int', 'timezone='=>'string|DateTimeZone|IntlTimeZone|null', 'calendar='=>'int|IntlCalendar|null', 'pattern='=>'string'], 'datefmt_format' => ['string|false', 'fmt'=>'IntlDateFormatter', 'value'=>'DateTime|IntlCalendar|array|int'], 'datefmt_format_object' => ['string|false', 'object'=>'object', 'format='=>'mixed', 'locale='=>'string'], 'datefmt_get_calendar' => ['int|false', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_calendar_object' => ['IntlCalendar|false|null', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_datetype' => ['int|false', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_error_code' => ['int', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_error_message' => ['string', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_locale' => ['string|false', 'fmt'=>'IntlDateFormatter', 'which='=>'int'], 'datefmt_get_pattern' => ['string|false', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_timetype' => ['int|false', 'fmt'=>'IntlDateFormatter'], 'datefmt_get_timezone' => ['IntlTimeZone|false'], 'datefmt_get_timezone_id' => ['string|false', 'fmt'=>'IntlDateFormatter'], 'datefmt_is_lenient' => ['bool', 'fmt'=>'IntlDateFormatter'], 'datefmt_localtime' => ['array|false', 'fmt'=>'IntlDateFormatter', 'text_to_parse='=>'string', '&rw_parse_pos='=>'int'], 'datefmt_parse' => ['int|float|false', 'fmt'=>'IntlDateFormatter', 'text_to_parse='=>'string', '&rw_parse_pos='=>'int'], 'datefmt_set_calendar' => ['bool', 'fmt'=>'IntlDateFormatter', 'which'=>'int'], 'datefmt_set_lenient' => ['void', 'fmt'=>'IntlDateFormatter', 'lenient'=>'bool'], 'datefmt_set_pattern' => ['bool', 'fmt'=>'IntlDateFormatter', 'pattern'=>'string'], 'datefmt_set_timezone' => ['bool', 'zone'=>'mixed'], 'datefmt_set_timezone_id' => ['bool', 'fmt'=>'IntlDateFormatter', 'zone'=>'string'], 'DateInterval::__construct' => ['void', 'spec'=>'string'], 'DateInterval::__set_state' => ['DateInterval', 'array'=>'array'], 'DateInterval::__wakeup' => ['void'], 'DateInterval::createFromDateString' => ['DateInterval|false', 'time'=>'string'], 'DateInterval::format' => ['string', 'format'=>'string'], 'DatePeriod::__construct' => ['void', 'start'=>'DateTimeInterface', 'interval'=>'DateInterval', 'recur'=>'int', 'options='=>'int'], 'DatePeriod::__construct\'1' => ['void', 'start'=>'DateTimeInterface', 'interval'=>'DateInterval', 'end'=>'DateTimeInterface', 'options='=>'int'], 'DatePeriod::__construct\'2' => ['void', 'iso'=>'string', 'options='=>'int'], 'DatePeriod::__wakeup' => ['void'], 'DatePeriod::getDateInterval' => ['DateInterval'], 'DatePeriod::getEndDate' => ['?DateTimeInterface'], 'DatePeriod::getStartDate' => ['DateTimeInterface'], 'DateTime::__construct' => ['void', 'time='=>'string', 'timezone='=>'?DateTimeZone'], 'DateTime::__set_state' => ['static', 'array'=>'array'], 'DateTime::__wakeup' => ['void'], 'DateTime::add' => ['static', 'interval'=>'DateInterval'], 'DateTime::createFromFormat' => ['static|false', 'format'=>'string', 'time'=>'string', 'timezone='=>'DateTimeZone|null'], 'DateTime::createFromImmutable' => ['static', 'object'=>'DateTimeImmutable'], 'DateTime::diff' => ['DateInterval', 'datetime2'=>'DateTimeInterface', 'absolute='=>'bool'], 'DateTime::format' => ['string', 'format'=>'string'], 'DateTime::getLastErrors' => ['array{warning_count: 0|positive-int, warnings: list, error_count: 0|positive-int, errors: list}|false'], 'DateTime::getOffset' => ['int'], 'DateTime::getTimestamp' => ['int'], 'DateTime::getTimezone' => ['DateTimeZone'], 'DateTime::modify' => ['__benevolent', 'modify'=>'string'], 'DateTime::setDate' => ['static', 'year'=>'int', 'month'=>'int', 'day'=>'int'], 'DateTime::setISODate' => ['static', 'year'=>'int', 'week'=>'int', 'day='=>'int'], 'DateTime::setTime' => ['static', 'hour'=>'int', 'minute'=>'int', 'second='=>'int', 'microseconds='=>'int'], 'DateTime::setTimestamp' => ['static', 'unixtimestamp'=>'int'], 'DateTime::setTimezone' => ['static', 'timezone'=>'DateTimeZone'], 'DateTime::sub' => ['static', 'interval'=>'DateInterval'], 'DateTimeImmutable::__construct' => ['void', 'time='=>'string', 'timezone='=>'?DateTimeZone'], 'DateTimeImmutable::__set_state' => ['static', 'array'=>'array'], 'DateTimeImmutable::__wakeup' => ['void'], 'DateTimeImmutable::add' => ['static', 'interval'=>'DateInterval'], 'DateTimeImmutable::createFromFormat' => ['static|false', 'format'=>'string', 'time'=>'string', 'timezone='=>'DateTimeZone|null'], 'DateTimeImmutable::createFromMutable' => ['static', 'datetime'=>'DateTime'], 'DateTimeImmutable::diff' => ['DateInterval', 'datetime2'=>'DateTimeInterface', 'absolute='=>'bool'], 'DateTimeImmutable::format' => ['string', 'format'=>'string'], 'DateTimeImmutable::getLastErrors' => ['array{warning_count: 0|positive-int, warnings: list, error_count: 0|positive-int, errors: list}|false'], 'DateTimeImmutable::getOffset' => ['int'], 'DateTimeImmutable::getTimestamp' => ['int'], 'DateTimeImmutable::getTimezone' => ['DateTimeZone'], 'DateTimeImmutable::modify' => ['__benevolent', 'modify'=>'string'], 'DateTimeImmutable::setDate' => ['static', 'year'=>'int', 'month'=>'int', 'day'=>'int'], 'DateTimeImmutable::setISODate' => ['static', 'year'=>'int', 'week'=>'int', 'day='=>'int'], 'DateTimeImmutable::setTime' => ['static', 'hour'=>'int', 'minute'=>'int', 'second='=>'int', 'microseconds='=>'int'], 'DateTimeImmutable::setTimestamp' => ['static', 'unixtimestamp'=>'int'], 'DateTimeImmutable::setTimezone' => ['static', 'timezone'=>'DateTimeZone'], 'DateTimeImmutable::sub' => ['static', 'interval'=>'DateInterval'], 'DateTimeInterface::diff' => ['DateInterval', 'datetime2'=>'DateTimeInterface', 'absolute='=>'bool'], 'DateTimeInterface::format' => ['string', 'format'=>'string'], 'DateTimeInterface::getOffset' => ['int'], 'DateTimeInterface::getTimestamp' => ['int'], 'DateTimeInterface::getTimezone' => ['DateTimeZone'], 'DateTimeZone::__construct' => ['void', 'timezone'=>'string'], 'DateTimeZone::__set_state' => ['DateTimeZone', 'array'=>'array'], 'DateTimeZone::__wakeup' => ['void'], 'DateTimeZone::getLocation' => ['array{country_code: string, latitude: float, longitude: float, comments: string}|false'], 'DateTimeZone::getName' => ['string'], 'DateTimeZone::getOffset' => ['int', 'datetime'=>'DateTimeInterface'], 'DateTimeZone::getTransitions' => ['list', 'timestamp_begin='=>'int', 'timestamp_end='=>'int'], 'DateTimeZone::listAbbreviations' => ['array>'], 'DateTimeZone::listIdentifiers' => ['list', 'what='=>'int', 'country='=>'string'], 'db2_autocommit' => ['DB2_AUTOCOMMIT_OFF|DB2_AUTOCOMMIT_ON|bool', 'connection'=>'resource', 'value='=>'DB2_AUTOCOMMIT_OFF|DB2_AUTOCOMMIT_ON'], 'db2_bind_param' => ['bool', 'stmt'=>'resource', 'parameter_number'=>'int', 'variable_name'=>'string', 'parameter_type='=>'int', 'data_type='=>'int', 'precision='=>'int', 'scale='=>'int'], 'db2_client_info' => ['stdClass|false', 'connection'=>'resource'], 'db2_close' => ['bool', 'connection'=>'resource'], 'db2_column_privileges' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'string', 'schema='=>'string', 'table_name='=>'string', 'column_name='=>'string'], 'db2_columns' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'string', 'schema='=>'string', 'table_name='=>'string', 'column_name='=>'string'], 'db2_commit' => ['bool', 'connection'=>'resource'], 'db2_conn_error' => ['string', 'connection='=>'resource'], 'db2_conn_errormsg' => ['string', 'connection='=>'resource'], 'db2_connect' => ['resource|false', 'database'=>'string', 'username'=>'string', 'password'=>'string', 'options='=>'array'], 'db2_cursor_type' => ['int', 'stmt'=>'resource'], 'db2_escape_string' => ['string', 'string_literal'=>'string'], 'db2_exec' => ['resource|false', 'connection'=>'resource', 'statement'=>'string', 'options='=>'array'], 'db2_execute' => ['bool', 'stmt'=>'resource', 'parameters='=>'array'], 'db2_fetch_array' => ['non-empty-list|false', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_fetch_assoc' => ['non-empty-array|false', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_fetch_both' => ['array|false', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_fetch_object' => ['stdClass|false', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_fetch_row' => ['bool', 'stmt'=>'resource', 'row_number='=>'int'], 'db2_field_display_size' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_name' => ['string|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_num' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_precision' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_scale' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_type' => ['string|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_field_width' => ['int|false', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_foreign_keys' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'table_name'=>'string'], 'db2_free_result' => ['bool', 'stmt'=>'resource'], 'db2_free_stmt' => ['bool', 'stmt'=>'resource'], 'db2_get_option' => ['string|false', 'resource'=>'resource', 'option'=>'string'], 'db2_last_insert_id' => ['string|null', 'resource'=>'resource'], 'db2_lob_read' => ['string|false', 'stmt'=>'resource', 'colnum'=>'int', 'length'=>'int'], 'db2_next_result' => ['resource|false', 'stmt'=>'resource'], 'db2_num_fields' => ['0|positive-int|false', 'stmt'=>'resource'], 'db2_num_rows' => ['0|positive-int|false', 'stmt'=>'resource'], 'db2_pclose' => ['bool', 'resource'=>'resource'], 'db2_pconnect' => ['resource|false', 'database'=>'string', 'username'=>'string', 'password'=>'string', 'options='=>'array'], 'db2_prepare' => ['resource|false', 'connection'=>'resource', 'statement'=>'string', 'options='=>'array'], 'db2_primary_keys' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'table_name'=>'string'], 'db2_primarykeys' => [''], 'db2_procedure_columns' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'procedure'=>'string', 'parameter'=>'string'], 'db2_procedurecolumns' => [''], 'db2_procedures' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'procedure'=>'string'], 'db2_result' => ['mixed', 'stmt'=>'resource', 'column'=>'mixed'], 'db2_rollback' => ['bool', 'connection'=>'resource'], 'db2_server_info' => ['stdClass|false', 'connection'=>'resource'], 'db2_set_option' => ['bool', 'resource'=>'resource', 'options'=>'array', 'type'=>'int'], 'db2_setoption' => [''], 'db2_special_columns' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'table_name'=>'string', 'scope'=>'int'], 'db2_specialcolumns' => [''], 'db2_statistics' => ['resource|false', 'connection'=>'resource', 'qualifier'=>'string', 'schema'=>'string', 'table_name'=>'string', 'unique'=>'bool'], 'db2_stmt_error' => ['string', 'stmt='=>'resource'], 'db2_stmt_errormsg' => ['string', 'stmt='=>'resource'], 'db2_table_privileges' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'string', 'schema='=>'string', 'table_name='=>'string'], 'db2_tableprivileges' => [''], 'db2_tables' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'string', 'schema='=>'string', 'table_name='=>'string', 'table_type='=>'string'], 'dba_close' => ['void', 'handle'=>'resource'], 'dba_delete' => ['bool', 'key'=>'string', 'handle'=>'resource'], 'dba_exists' => ['bool', 'key'=>'string', 'handle'=>'resource'], 'dba_fetch' => ['string|false', 'key'=>'string', 'skip'=>'int', 'handle'=>'resource'], 'dba_fetch\'1' => ['string|false', 'key'=>'string', 'handle'=>'resource'], 'dba_firstkey' => ['string|false', 'handle'=>'resource'], 'dba_handlers' => ['array', 'full_info='=>'bool'], 'dba_insert' => ['bool', 'key'=>'string', 'value'=>'string', 'handle'=>'resource'], 'dba_key_split' => ['array|false', 'key'=>'string'], 'dba_list' => ['array'], 'dba_nextkey' => ['string|false', 'handle'=>'resource'], 'dba_open' => ['resource|false', 'path'=>'string', 'mode'=>'string', 'handlername='=>'string', '...args='=>'string'], 'dba_optimize' => ['bool', 'handle'=>'resource'], 'dba_popen' => ['resource|false', 'path'=>'string', 'mode'=>'string', 'handlername='=>'string', '...args='=>'string'], 'dba_replace' => ['bool', 'key'=>'string', 'value'=>'string', 'handle'=>'resource'], 'dba_sync' => ['bool', 'handle'=>'resource'], 'dbase_add_record' => ['bool', 'dbase_identifier'=>'resource', 'record'=>'array'], 'dbase_close' => ['bool', 'dbase_identifier'=>'resource'], 'dbase_create' => ['resource|false', 'filename'=>'string', 'fields'=>'array'], 'dbase_delete_record' => ['bool', 'dbase_identifier'=>'resource', 'record_number'=>'int'], 'dbase_get_header_info' => ['array', 'dbase_identifier'=>'resource'], 'dbase_get_record' => ['array', 'dbase_identifier'=>'resource', 'record_number'=>'int'], 'dbase_get_record_with_names' => ['array', 'dbase_identifier'=>'resource', 'record_number'=>'int'], 'dbase_numfields' => ['int', 'dbase_identifier'=>'resource'], 'dbase_numrecords' => ['int', 'dbase_identifier'=>'resource'], 'dbase_open' => ['resource|false', 'filename'=>'string', 'mode'=>'int'], 'dbase_pack' => ['bool', 'dbase_identifier'=>'resource'], 'dbase_replace_record' => ['bool', 'dbase_identifier'=>'resource', 'record'=>'array', 'record_number'=>'int'], 'dbplus_add' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_aql' => ['resource', 'query'=>'string', 'server='=>'string', 'dbpath='=>'string'], 'dbplus_chdir' => ['string', 'newdir='=>'string'], 'dbplus_close' => ['mixed', 'relation'=>'resource'], 'dbplus_curr' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_errcode' => ['string', 'errno='=>'int'], 'dbplus_errno' => ['int'], 'dbplus_find' => ['int', 'relation'=>'resource', 'constraints'=>'array', 'tuple'=>'mixed'], 'dbplus_first' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_flush' => ['int', 'relation'=>'resource'], 'dbplus_freealllocks' => ['int'], 'dbplus_freelock' => ['int', 'relation'=>'resource', 'tuple'=>'string'], 'dbplus_freerlocks' => ['int', 'relation'=>'resource'], 'dbplus_getlock' => ['int', 'relation'=>'resource', 'tuple'=>'string'], 'dbplus_getunique' => ['int', 'relation'=>'resource', 'uniqueid'=>'int'], 'dbplus_info' => ['int', 'relation'=>'resource', 'key'=>'string', 'result'=>'array'], 'dbplus_last' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_lockrel' => ['int', 'relation'=>'resource'], 'dbplus_next' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_open' => ['resource', 'name'=>'string'], 'dbplus_prev' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_rchperm' => ['int', 'relation'=>'resource', 'mask'=>'int', 'user'=>'string', 'group'=>'string'], 'dbplus_rcreate' => ['resource', 'name'=>'string', 'domlist'=>'mixed', 'overwrite='=>'bool'], 'dbplus_rcrtexact' => ['mixed', 'name'=>'string', 'relation'=>'resource', 'overwrite='=>'bool'], 'dbplus_rcrtlike' => ['mixed', 'name'=>'string', 'relation'=>'resource', 'overwrite='=>'int'], 'dbplus_resolve' => ['array', 'relation_name'=>'string'], 'dbplus_restorepos' => ['int', 'relation'=>'resource', 'tuple'=>'array'], 'dbplus_rkeys' => ['mixed', 'relation'=>'resource', 'domlist'=>'mixed'], 'dbplus_ropen' => ['resource', 'name'=>'string'], 'dbplus_rquery' => ['resource', 'query'=>'string', 'dbpath='=>'string'], 'dbplus_rrename' => ['int', 'relation'=>'resource', 'name'=>'string'], 'dbplus_rsecindex' => ['mixed', 'relation'=>'resource', 'domlist'=>'mixed', 'type'=>'int'], 'dbplus_runlink' => ['int', 'relation'=>'resource'], 'dbplus_rzap' => ['int', 'relation'=>'resource'], 'dbplus_savepos' => ['int', 'relation'=>'resource'], 'dbplus_setindex' => ['int', 'relation'=>'resource', 'idx_name'=>'string'], 'dbplus_setindexbynumber' => ['int', 'relation'=>'resource', 'idx_number'=>'int'], 'dbplus_sql' => ['resource', 'query'=>'string', 'server='=>'string', 'dbpath='=>'string'], 'dbplus_tcl' => ['string', 'sid'=>'int', 'script'=>'string'], 'dbplus_tremove' => ['int', 'relation'=>'resource', 'tuple'=>'array', 'current='=>'array'], 'dbplus_undo' => ['int', 'relation'=>'resource'], 'dbplus_undoprepare' => ['int', 'relation'=>'resource'], 'dbplus_unlockrel' => ['int', 'relation'=>'resource'], 'dbplus_unselect' => ['int', 'relation'=>'resource'], 'dbplus_update' => ['int', 'relation'=>'resource', 'old'=>'array', 'new'=>'array'], 'dbplus_xlockrel' => ['int', 'relation'=>'resource'], 'dbplus_xunlockrel' => ['int', 'relation'=>'resource'], 'dbx_close' => ['int', 'link_identifier'=>'object'], 'dbx_compare' => ['int', 'row_a'=>'array', 'row_b'=>'array', 'column_key'=>'string', 'flags='=>'int'], 'dbx_connect' => ['object', 'module'=>'mixed', 'host'=>'string', 'database'=>'string', 'username'=>'string', 'password'=>'string', 'persistent='=>'int'], 'dbx_error' => ['string', 'link_identifier'=>'object'], 'dbx_escape_string' => ['string', 'link_identifier'=>'object', 'text'=>'string'], 'dbx_fetch_row' => ['mixed', 'result_identifier'=>'object'], 'dbx_query' => ['mixed', 'link_identifier'=>'object', 'sql_statement'=>'string', 'flags='=>'int'], 'dbx_sort' => ['bool', 'result'=>'object', 'user_compare_function'=>'string'], 'dcgettext' => ['string', 'domain_name'=>'string', 'msgid'=>'string', 'category'=>'int'], 'dcngettext' => ['string', 'domain'=>'string', 'msgid1'=>'string', 'msgid2'=>'string', 'n'=>'int', 'category'=>'int'], 'deaggregate' => ['', 'object'=>'object', 'class_name='=>'string'], 'debug_backtrace' => ['list\',args?:mixed[],object?:object}>', 'options='=>'int|bool', 'limit='=>'int'], 'debug_print_backtrace' => ['void', 'options='=>'int|bool', 'limit='=>'int'], 'debug_zval_dump' => ['void', '...var'=>'mixed'], 'debugger_connect' => [''], 'debugger_connector_pid' => [''], 'debugger_get_server_start_time' => [''], 'debugger_print' => [''], 'debugger_start_debug' => [''], 'decbin' => ['string', 'decimal_number'=>'int'], 'dechex' => ['string', 'num'=>'int'], 'decoct' => ['string', 'decimal_number'=>'int'], 'define' => ['bool', 'constant_name'=>'string', 'value'=>'mixed', 'case_insensitive='=>'bool'], 'define_syslog_variables' => ['void'], 'defined' => ['bool', 'name'=>'string'], 'deflate_add' => ['string|false', 'context'=>'resource', 'data'=>'string', 'flush_mode='=>'int'], 'deflate_init' => ['resource|false', 'encoding'=>'int', 'options='=>'array'], 'deg2rad' => ['float', 'number'=>'float'], 'dgettext' => ['string', 'domain_name'=>'string', 'msgid'=>'string'], 'dio_close' => ['void', 'fd'=>'resource'], 'dio_fcntl' => ['mixed', 'fd'=>'resource', 'cmd'=>'int', 'args='=>'mixed'], 'dio_open' => ['resource|false', 'filename'=>'string', 'flags'=>'int', 'mode='=>'int'], 'dio_read' => ['string', 'fd'=>'resource', 'len='=>'int'], 'dio_seek' => ['int', 'fd'=>'resource', 'pos'=>'int', 'whence='=>'int'], 'dio_stat' => ['array|null', 'fd'=>'resource'], 'dio_tcsetattr' => ['bool', 'fd'=>'resource', 'options'=>'array'], 'dio_truncate' => ['bool', 'fd'=>'resource', 'offset'=>'int'], 'dio_write' => ['int', 'fd'=>'resource', 'data'=>'string', 'len='=>'int'], 'dir' => ['Directory|false', 'directory'=>'string', 'context='=>'resource'], 'Directory::close' => ['void', 'dir_handle='=>'resource'], 'Directory::read' => ['string|false', 'dir_handle='=>'resource'], 'Directory::rewind' => ['void', 'dir_handle='=>'resource'], 'DirectoryIterator::__construct' => ['void', 'path'=>'string'], 'DirectoryIterator::__toString' => ['string'], 'DirectoryIterator::current' => ['DirectoryIterator'], 'DirectoryIterator::getATime' => ['int'], 'DirectoryIterator::getBasename' => ['string', 'suffix='=>'string'], 'DirectoryIterator::getChildren' => ['RecursiveDirectoryIterator'], 'DirectoryIterator::getCTime' => ['int'], 'DirectoryIterator::getExtension' => ['string'], 'DirectoryIterator::getFileInfo' => ['SplFileInfo', 'class_name='=>'string'], 'DirectoryIterator::getFilename' => ['string'], 'DirectoryIterator::getGroup' => ['int'], 'DirectoryIterator::getInode' => ['int'], 'DirectoryIterator::getLinkTarget' => ['string'], 'DirectoryIterator::getMTime' => ['int'], 'DirectoryIterator::getOwner' => ['int'], 'DirectoryIterator::getPath' => ['string'], 'DirectoryIterator::getPathInfo' => ['SplFileInfo', 'class_name='=>'string'], 'DirectoryIterator::getPathname' => ['string'], 'DirectoryIterator::getPerms' => ['int'], 'DirectoryIterator::getRealPath' => ['string'], 'DirectoryIterator::getSize' => ['int'], 'DirectoryIterator::getType' => ['string'], 'DirectoryIterator::isDir' => ['bool'], 'DirectoryIterator::isDot' => ['bool'], 'DirectoryIterator::isExecutable' => ['bool'], 'DirectoryIterator::isFile' => ['bool'], 'DirectoryIterator::isLink' => ['bool'], 'DirectoryIterator::isReadable' => ['bool'], 'DirectoryIterator::isWritable' => ['bool'], 'DirectoryIterator::key' => ['string'], 'DirectoryIterator::next' => ['void'], 'DirectoryIterator::openFile' => ['SplFileObject', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'DirectoryIterator::rewind' => ['void'], 'DirectoryIterator::seek' => ['void', 'position'=>'int'], 'DirectoryIterator::setFileClass' => ['void', 'class_name='=>'string'], 'DirectoryIterator::setInfoClass' => ['void', 'class_name='=>'string'], 'DirectoryIterator::valid' => ['bool'], 'dirname' => ['string', 'path'=>'string', 'levels='=>'positive-int'], 'disk_free_space' => ['float|false', 'path'=>'string'], 'disk_total_space' => ['float|false', 'path'=>'string'], 'diskfreespace' => ['float|false', 'path'=>'string'], 'display_disabled_function' => [''], 'dl' => ['bool', 'extension_filename'=>'string'], 'dngettext' => ['string', 'domain'=>'string', 'msgid1'=>'string', 'msgid2'=>'string', 'count'=>'int'], 'dns_check_record' => ['bool', 'host'=>'string', 'type='=>'string'], 'dns_get_mx' => ['bool', 'hostname'=>'string', '&w_mxhosts'=>'array', '&w_weight'=>'array'], 'dns_get_record' => ['list|false', 'hostname'=>'string', 'type='=>'int', '&w_authns='=>'array', '&w_addtl='=>'array', 'raw='=>'bool'], 'dom_document_relaxNG_validate_file' => ['bool', 'filename'=>'string'], 'dom_document_relaxNG_validate_xml' => ['bool', 'source'=>'string'], 'dom_document_schema_validate' => ['bool', 'source'=>'string', 'flags'=>'int'], 'dom_document_schema_validate_file' => ['bool', 'filename'=>'string', 'flags'=>'int'], 'dom_document_xinclude' => ['int', 'options'=>'int'], 'dom_import_simplexml' => ['DOMElement|false', 'node'=>'SimpleXMLElement'], 'dom_xpath_evaluate' => ['', 'expr'=>'string', 'context'=>'DOMNode', 'registernodens'=>'bool'], 'dom_xpath_query' => ['DOMNodeList', 'expr'=>'string', 'context'=>'DOMNode', 'registernodens'=>'bool'], 'dom_xpath_register_ns' => ['bool', 'prefix'=>'string', 'uri'=>'string'], 'dom_xpath_register_php_functions' => [''], 'DomainException::__clone' => ['void'], 'DomainException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?DomainException)'], 'DomainException::__toString' => ['string'], 'DomainException::__wakeup' => ['void'], 'DomainException::getCode' => ['int'], 'DomainException::getFile' => ['string'], 'DomainException::getLine' => ['int'], 'DomainException::getMessage' => ['string'], 'DomainException::getPrevious' => ['Throwable|DomainException|null'], 'DomainException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'DomainException::getTraceAsString' => ['string'], 'DOMAttr::__construct' => ['void', 'name'=>'string', 'value='=>'string'], 'DOMAttr::isId' => ['bool'], 'DomAttribute::name' => ['string'], 'DomAttribute::set_value' => ['bool', 'content'=>'string'], 'DomAttribute::specified' => ['bool'], 'DomAttribute::value' => ['string'], 'DOMCdataSection::__construct' => ['void', 'value'=>'string'], 'DOMCharacterData::appendData' => ['void', 'data'=>'string'], 'DOMCharacterData::deleteData' => ['void', 'offset'=>'int', 'count'=>'int'], 'DOMCharacterData::insertData' => ['void', 'offset'=>'int', 'data'=>'string'], 'DOMCharacterData::replaceData' => ['void', 'offset'=>'int', 'count'=>'int', 'data'=>'string'], 'DOMCharacterData::substringData' => ['string', 'offset'=>'int', 'count'=>'int'], 'DOMComment::__construct' => ['void', 'value='=>'string'], 'DOMDocument::__construct' => ['void', 'version='=>'string', 'encoding='=>'string'], 'DOMDocument::createAttribute' => ['__benevolent', 'name'=>'string'], 'DOMDocument::createAttributeNS' => ['__benevolent', 'namespaceuri'=>'string', 'qualifiedname'=>'string'], 'DOMDocument::createCDATASection' => ['__benevolent', 'data'=>'string'], 'DOMDocument::createComment' => ['DOMComment', 'data'=>'string'], 'DOMDocument::createDocumentFragment' => ['DOMDocumentFragment'], 'DOMDocument::createElement' => ['__benevolent', 'name'=>'string', 'value='=>'string'], 'DOMDocument::createElementNS' => ['__benevolent', 'namespaceuri'=>'string', 'qualifiedname'=>'string', 'value='=>'string'], 'DOMDocument::createEntityReference' => ['__benevolent', 'name'=>'string'], 'DOMDocument::createProcessingInstruction' => ['__benevolent', 'target'=>'string', 'data='=>'string'], 'DOMDocument::createTextNode' => ['DOMText', 'content'=>'string'], 'DOMDocument::getElementById' => ['DOMElement|null', 'elementid'=>'string'], 'DOMDocument::getElementsByTagName' => ['DOMNodeList', 'name'=>'string'], 'DOMDocument::getElementsByTagNameNS' => ['DOMNodeList', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMDocument::importNode' => ['DOMNode', 'importednode'=>'DOMNode', 'deep='=>'bool'], 'DOMDocument::load' => ['bool', 'filename'=>'string', 'options='=>'int'], 'DOMDocument::loadHTML' => ['bool', 'source'=>'string', 'options='=>'int'], 'DOMDocument::loadHTMLFile' => ['bool', 'filename'=>'string', 'options='=>'int'], 'DOMDocument::loadXML' => ['bool', 'source'=>'string', 'options='=>'int'], 'DOMDocument::normalizeDocument' => ['void'], 'DOMDocument::registerNodeClass' => ['bool', 'baseclass'=>'string', 'extendedclass'=>'string'], 'DOMDocument::relaxNGValidate' => ['bool', 'filename'=>'string'], 'DOMDocument::relaxNGValidateSource' => ['bool', 'source'=>'string'], 'DOMDocument::save' => ['int|false', 'filename'=>'string', 'options='=>'int'], 'DOMDocument::saveHTML' => ['string|false', 'node='=>'?DOMNode'], 'DOMDocument::saveHTMLFile' => ['int|false', 'filename'=>'string'], 'DOMDocument::saveXML' => ['string|false', 'node='=>'?DOMNode', 'options='=>'int'], 'DOMDocument::schemaValidate' => ['bool', 'filename'=>'string', 'flags='=>'int'], 'DOMDocument::schemaValidateSource' => ['bool', 'source'=>'string', 'flags='=>'int'], 'DOMDocument::validate' => ['bool'], 'DOMDocument::xinclude' => ['int', 'options='=>'int'], 'DOMDocumentFragment::__construct' => ['void'], 'DOMDocumentFragment::appendXML' => ['bool', 'data'=>'string'], 'DomDocumentType::entities' => ['array'], 'DomDocumentType::internal_subset' => ['bool'], 'DomDocumentType::name' => ['string'], 'DomDocumentType::notations' => ['array'], 'DomDocumentType::public_id' => ['string'], 'DomDocumentType::system_id' => ['string'], 'DOMElement::__construct' => ['void', 'name'=>'string', 'value='=>'string', 'uri='=>'string'], 'DOMElement::get_attribute' => ['string', 'name'=>'string'], 'DOMElement::get_attribute_node' => ['DomAttribute', 'name'=>'string'], 'DOMElement::get_elements_by_tagname' => ['array', 'name'=>'string'], 'DOMElement::getAttribute' => ['string', 'name'=>'string'], 'DOMElement::getAttributeNode' => ['DOMAttr', 'name'=>'string'], 'DOMElement::getAttributeNodeNS' => ['DOMAttr', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::getAttributeNS' => ['string', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::getElementsByTagName' => ['DOMNodeList', 'name'=>'string'], 'DOMElement::getElementsByTagNameNS' => ['DOMNodeList', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::has_attribute' => ['bool', 'name'=>'string'], 'DOMElement::hasAttribute' => ['bool', 'name'=>'string'], 'DOMElement::hasAttributeNS' => ['bool', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::remove_attribute' => ['bool', 'name'=>'string'], 'DOMElement::removeAttribute' => ['bool', 'name'=>'string'], 'DOMElement::removeAttributeNode' => ['bool', 'oldnode'=>'DOMAttr'], 'DOMElement::removeAttributeNS' => ['bool', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMElement::set_attribute' => ['DomAttribute', 'name'=>'string', 'value'=>'string'], 'DOMElement::set_attribute_node' => ['DomNode', 'attr'=>'DOMNode'], 'DOMElement::setAttribute' => ['DOMAttr', 'name'=>'string', 'value'=>'string'], 'DOMElement::setAttributeNode' => ['DOMAttr', 'attr'=>'DOMAttr'], 'DOMElement::setAttributeNodeNS' => ['DOMAttr', 'attr'=>'DOMAttr'], 'DOMElement::setAttributeNS' => ['void', 'namespaceuri'=>'string', 'qualifiedname'=>'string', 'value'=>'string'], 'DOMElement::setIdAttribute' => ['void', 'name'=>'string', 'isid'=>'bool'], 'DOMElement::setIdAttributeNode' => ['void', 'attr'=>'DOMAttr', 'isid'=>'bool'], 'DOMElement::setIdAttributeNS' => ['void', 'namespaceuri'=>'string', 'localname'=>'string', 'isid'=>'bool'], 'DOMElement::tagname' => ['string'], 'DOMEntityReference::__construct' => ['void', 'name'=>'string'], 'DOMImplementation::__construct' => ['void'], 'DOMImplementation::createDocument' => ['DOMDocument', 'namespaceuri='=>'string', 'qualifiedname='=>'string', 'doctype='=>'DOMDocumentType'], 'DOMImplementation::createDocumentType' => ['DOMDocumentType', 'qualifiedname='=>'string', 'publicid='=>'string', 'systemid='=>'string'], 'DOMImplementation::hasFeature' => ['bool', 'feature'=>'string', 'version'=>'string'], 'DOMNamedNodeMap::count' => ['0|positive-int'], 'DOMNamedNodeMap::getNamedItem' => ['?DOMNode', 'name'=>'string'], 'DOMNamedNodeMap::getNamedItemNS' => ['?DOMNode', 'namespaceuri'=>'string', 'localname'=>'string'], 'DOMNamedNodeMap::item' => ['?DOMNode', 'index'=>'int'], 'DomNode::add_namespace' => ['bool', 'uri'=>'string', 'prefix'=>'string'], 'DomNode::append_child' => ['DOMNode', 'newnode'=>'DOMNode'], 'DOMNode::appendChild' => ['DOMNode', 'newnode'=>'DOMNode'], 'DOMNode::C14N' => ['string', 'exclusive='=>'bool', 'with_comments='=>'bool', 'xpath='=>'array', 'ns_prefixes='=>'array'], 'DOMNode::C14NFile' => ['int', 'uri='=>'string', 'exclusive='=>'bool', 'with_comments='=>'bool', 'xpath='=>'array', 'ns_prefixes='=>'array'], 'DOMNode::cloneNode' => ['DOMNode', 'deep='=>'bool'], 'DOMNode::getLineNo' => ['int'], 'DOMNode::getNodePath' => ['?string'], 'DOMNode::hasAttributes' => ['bool'], 'DOMNode::hasChildNodes' => ['bool'], 'DOMNode::insertBefore' => ['DOMNode', 'newnode'=>'DOMNode', 'refnode='=>'DOMNode'], 'DOMNode::isDefaultNamespace' => ['bool', 'namespaceuri'=>'string'], 'DOMNode::isSameNode' => ['bool', 'node'=>'DOMNode'], 'DOMNode::isSupported' => ['bool', 'feature'=>'string', 'version'=>'string'], 'DOMNode::lookupNamespaceURI' => ['?string', 'prefix'=>'?string'], 'DOMNode::lookupPrefix' => ['string', 'namespaceuri'=>'string'], 'DOMNode::normalize' => ['void'], 'DOMNode::removeChild' => ['DOMNode', 'oldnode'=>'DOMNode'], 'DOMNode::replaceChild' => ['DOMNode', 'newnode'=>'DOMNode', 'oldnode'=>'DOMNode'], 'DOMNodeList::count' => ['0|positive-int'], 'DOMNodeList::item' => ['?DOMNode', 'index'=>'int'], 'DOMProcessingInstruction::__construct' => ['void', 'name'=>'string', 'value'=>'string'], 'DomProcessingInstruction::data' => ['string'], 'DomProcessingInstruction::target' => ['string'], 'DOMText::__construct' => ['void', 'value='=>'string'], 'DOMText::isElementContentWhitespace' => ['bool'], 'DOMText::isWhitespaceInElementContent' => ['bool'], 'DOMText::splitText' => ['DOMText|false', 'offset'=>'int'], 'domxml_new_doc' => ['DomDocument', 'version'=>'string'], 'domxml_open_file' => ['DomDocument', 'filename'=>'string', 'mode='=>'int', 'error='=>'array'], 'domxml_open_mem' => ['DomDocument', 'str'=>'string', 'mode='=>'int', 'error='=>'array'], 'domxml_version' => ['string'], 'domxml_xmltree' => ['DomDocument', 'str'=>'string'], 'domxml_xslt_stylesheet' => ['DomXsltStylesheet', 'xsl_buf'=>'string'], 'domxml_xslt_stylesheet_doc' => ['DomXsltStylesheet', 'xsl_doc'=>'DOMDocument'], 'domxml_xslt_stylesheet_file' => ['DomXsltStylesheet', 'xsl_file'=>'string'], 'domxml_xslt_version' => ['int'], 'DOMXPath::__construct' => ['void', 'doc'=>'DOMDocument'], 'DOMXPath::evaluate' => ['mixed', 'expression'=>'string', 'contextnode='=>'?DOMNode', 'registernodens='=>'bool'], 'DOMXPath::query' => ['DOMNodeList|false', 'expression'=>'string', 'contextnode='=>'?DOMNode', 'registernodens='=>'bool'], 'DOMXPath::registerNamespace' => ['bool', 'prefix'=>'string', 'namespaceuri'=>'string'], 'DOMXPath::registerPhpFunctions' => ['void', 'restrict='=>'mixed'], 'DomXsltStylesheet::process' => ['DomDocument', 'xml_doc'=>'DOMDocument', 'xslt_params='=>'array', 'is_xpath_param='=>'bool', 'profile_filename='=>'string'], 'DomXsltStylesheet::result_dump_file' => ['string', 'xmldoc'=>'DOMDocument', 'filename'=>'string'], 'DomXsltStylesheet::result_dump_mem' => ['string', 'xmldoc'=>'DOMDocument'], 'DOTNET::__construct' => ['void', 'assembly_name'=>'string', 'class_name'=>'string', 'codepage='=>'int'], 'dotnet_load' => ['int', 'assembly_name'=>'string', 'datatype_name='=>'string', 'codepage='=>'int'], 'doubleval' => ['float', 'var'=>'scalar|array|resource|null'], 'Ds\Collection::clear' => ['void'], 'Ds\Collection::copy' => ['Ds\Collection'], 'Ds\Collection::isEmpty' => ['bool'], 'Ds\Collection::toArray' => ['array'], 'Ds\Deque::__construct' => ['void', 'values='=>'mixed'], 'Ds\Deque::allocate' => ['void', 'capacity'=>'int'], 'Ds\Deque::apply' => ['void', 'callback'=>'callable'], 'Ds\Deque::capacity' => ['int'], 'Ds\Deque::clear' => ['void'], 'Ds\Deque::contains' => ['bool', '...values='=>'mixed'], 'Ds\Deque::copy' => ['Ds\Deque'], 'Ds\Deque::count' => ['0|positive-int'], 'Ds\Deque::filter' => ['Ds\Deque', 'callback='=>'callable'], 'Ds\Deque::find' => ['mixed', 'value'=>'mixed'], 'Ds\Deque::first' => ['mixed'], 'Ds\Deque::get' => ['void', 'index'=>'int'], 'Ds\Deque::insert' => ['void', 'index'=>'int', '...values='=>'mixed'], 'Ds\Deque::isEmpty' => ['bool'], 'Ds\Deque::join' => ['string', 'glue='=>'string'], 'Ds\Deque::jsonSerialize' => ['array'], 'Ds\Deque::last' => ['mixed'], 'Ds\Deque::map' => ['Ds\Deque', 'callback'=>'callable'], 'Ds\Deque::merge' => ['Ds\Deque', 'values'=>'mixed'], 'Ds\Deque::pop' => ['mixed'], 'Ds\Deque::push' => ['void', '...values='=>'mixed'], 'Ds\Deque::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Deque::remove' => ['mixed', 'index'=>'int'], 'Ds\Deque::reverse' => ['void'], 'Ds\Deque::reversed' => ['Ds\Deque'], 'Ds\Deque::rotate' => ['void', 'rotations'=>'int'], 'Ds\Deque::set' => ['void', 'index'=>'int', 'value'=>'mixed'], 'Ds\Deque::shift' => ['mixed'], 'Ds\Deque::slice' => ['Ds\Deque', 'index'=>'int', 'length='=>'?int'], 'Ds\Deque::sort' => ['void', 'comparator='=>'callable'], 'Ds\Deque::sorted' => ['Ds\Deque', 'comparator='=>'callable'], 'Ds\Deque::sum' => ['int|float'], 'Ds\Deque::toArray' => ['array'], 'Ds\Deque::unshift' => ['void', '...values='=>'mixed'], 'Ds\Hashable::equals' => ['bool', 'obj'=>'mixed'], 'Ds\Hashable::hash' => ['mixed'], 'Ds\Map::__construct' => ['void', 'values='=>'mixed'], 'Ds\Map::allocate' => ['void', 'capacity'=>'int'], 'Ds\Map::apply' => ['void', 'callback'=>'callable'], 'Ds\Map::capacity' => ['int'], 'Ds\Map::clear' => ['void'], 'Ds\Map::copy' => ['Ds\Map'], 'Ds\Map::count' => ['0|positive-int'], 'Ds\Map::diff' => ['Ds\Map', 'map'=>'Ds\Map'], 'Ds\Map::filter' => ['Ds\Map', 'callback='=>'callable'], 'Ds\Map::first' => ['Ds\Pair'], 'Ds\Map::get' => ['mixed', 'key'=>'mixed', 'default='=>'mixed'], 'Ds\Map::hasKey' => ['bool', 'key'=>'mixed'], 'Ds\Map::hasValue' => ['bool', 'value'=>'mixed'], 'Ds\Map::intersect' => ['Ds\Map', 'map'=>'Ds\Map'], 'Ds\Map::isEmpty' => ['bool'], 'Ds\Map::jsonSerialize' => ['array'], 'Ds\Map::keys' => ['Ds\Set'], 'Ds\Map::ksort' => ['void', 'comparator='=>'callable'], 'Ds\Map::ksorted' => ['Ds\Map', 'comparator='=>'callable'], 'Ds\Map::last' => ['Ds\Pair'], 'Ds\Map::map' => ['Ds\Map', 'callback'=>'callable'], 'Ds\Map::merge' => ['Ds\Map', 'values'=>'mixed'], 'Ds\Map::pairs' => ['Ds\Sequence'], 'Ds\Map::put' => ['void', 'key'=>'mixed', 'value'=>'mixed'], 'Ds\Map::putAll' => ['void', 'values'=>'mixed'], 'Ds\Map::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Map::remove' => ['mixed', 'key'=>'mixed', 'default='=>'mixed'], 'Ds\Map::reverse' => ['void'], 'Ds\Map::reversed' => ['Ds\Map'], 'Ds\Map::skip' => ['Ds\Pair', 'position'=>'int'], 'Ds\Map::slice' => ['Ds\Map', 'index'=>'int', 'length='=>'?int'], 'Ds\Map::sort' => ['void', 'comparator='=>'callable'], 'Ds\Map::sorted' => ['Ds\Map', 'comparator='=>'callable'], 'Ds\Map::sum' => ['int|float'], 'Ds\Map::toArray' => ['array'], 'Ds\Map::union' => ['Ds\Map', 'map'=>'Ds\Map'], 'Ds\Map::values' => ['Ds\Sequence'], 'Ds\Map::xor' => ['Ds\Map', 'map'=>'Ds\Map'], 'Ds\Pair::__construct' => ['void', 'key='=>'mixed', 'value='=>'mixed'], 'Ds\Pair::copy' => ['Ds\Pair'], 'Ds\Pair::jsonSerialize' => ['array'], 'Ds\Pair::toArray' => ['array'], 'Ds\PriorityQueue::__construct' => ['void'], 'Ds\PriorityQueue::allocate' => ['void', 'capacity'=>'int'], 'Ds\PriorityQueue::capacity' => ['int'], 'Ds\PriorityQueue::clear' => ['void'], 'Ds\PriorityQueue::copy' => ['Ds\PriorityQueue'], 'Ds\PriorityQueue::count' => ['0|positive-int'], 'Ds\PriorityQueue::isEmpty' => ['bool'], 'Ds\PriorityQueue::jsonSerialize' => ['array'], 'Ds\PriorityQueue::peek' => ['mixed'], 'Ds\PriorityQueue::pop' => ['mixed'], 'Ds\PriorityQueue::push' => ['void', 'value'=>'mixed', 'priority'=>'int'], 'Ds\PriorityQueue::toArray' => ['array'], 'Ds\Queue::__construct' => ['void', 'values='=>'mixed'], 'Ds\Queue::allocate' => ['void', 'capacity'=>'int'], 'Ds\Queue::capacity' => ['int'], 'Ds\Queue::clear' => ['void'], 'Ds\Queue::copy' => ['Ds\Queue'], 'Ds\Queue::count' => ['0|positive-int'], 'Ds\Queue::isEmpty' => ['bool'], 'Ds\Queue::jsonSerialize' => ['array'], 'Ds\Queue::peek' => ['mixed'], 'Ds\Queue::pop' => ['mixed'], 'Ds\Queue::push' => ['void', '...values='=>'mixed'], 'Ds\Queue::toArray' => ['array'], 'Ds\Sequence::allocate' => ['void', 'capacity'=>'int'], 'Ds\Sequence::apply' => ['void', 'callback'=>'callable'], 'Ds\Sequence::capacity' => ['int'], 'Ds\Sequence::contains' => ['bool', '...values='=>'mixed'], 'Ds\Sequence::filter' => ['Ds\Sequence', 'callback='=>'callable'], 'Ds\Sequence::find' => ['mixed', 'value'=>'mixed'], 'Ds\Sequence::first' => ['mixed'], 'Ds\Sequence::get' => ['mixed', 'index'=>'int'], 'Ds\Sequence::insert' => ['void', 'index'=>'int', '...values='=>'mixed'], 'Ds\Sequence::join' => ['string', 'glue='=>'string'], 'Ds\Sequence::last' => ['void'], 'Ds\Sequence::map' => ['Ds\Sequence', 'callback'=>'callable'], 'Ds\Sequence::merge' => ['Ds\Sequence', 'values'=>'mixed'], 'Ds\Sequence::pop' => ['mixed'], 'Ds\Sequence::push' => ['void', '...values='=>'mixed'], 'Ds\Sequence::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Sequence::remove' => ['mixed', 'index'=>'int'], 'Ds\Sequence::reverse' => ['void'], 'Ds\Sequence::reversed' => ['Ds\Sequence'], 'Ds\Sequence::rotate' => ['void', 'rotations'=>'int'], 'Ds\Sequence::set' => ['void', 'index'=>'int', 'value'=>'mixed'], 'Ds\Sequence::shift' => ['mixed'], 'Ds\Sequence::slice' => ['Ds\Sequence', 'index'=>'int', 'length='=>'?int'], 'Ds\Sequence::sort' => ['void', 'comparator='=>'callable'], 'Ds\Sequence::sorted' => ['Ds\Sequence', 'comparator='=>'callable'], 'Ds\Sequence::sum' => ['int|float'], 'Ds\Sequence::unshift' => ['void', '...values='=>'mixed'], 'Ds\Set::__construct' => ['void', 'values='=>'mixed'], 'Ds\Set::add' => ['void', '...values='=>'mixed'], 'Ds\Set::allocate' => ['void', 'capacity'=>'int'], 'Ds\Set::capacity' => ['int'], 'Ds\Set::clear' => ['void'], 'Ds\Set::contains' => ['bool', '...values='=>'mixed'], 'Ds\Set::copy' => ['Ds\Set'], 'Ds\Set::count' => ['0|positive-int'], 'Ds\Set::diff' => ['Ds\Set', 'set'=>'Ds\Set'], 'Ds\Set::filter' => ['Ds\Set', 'callback='=>'callable'], 'Ds\Set::first' => ['mixed'], 'Ds\Set::get' => ['mixed', 'index'=>'int'], 'Ds\Set::intersect' => ['Ds\Set', 'set'=>'Ds\Set'], 'Ds\Set::isEmpty' => ['bool'], 'Ds\Set::join' => ['string', 'glue='=>'string'], 'Ds\Set::jsonSerialize' => ['array'], 'Ds\Set::last' => ['mixed'], 'Ds\Set::map' => ['Ds\Set', 'callback='=>'callable'], 'Ds\Set::merge' => ['Ds\Set', 'values'=>'mixed'], 'Ds\Set::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Set::remove' => ['void', '...values='=>'mixed'], 'Ds\Set::reverse' => ['void'], 'Ds\Set::reversed' => ['Ds\Set'], 'Ds\Set::slice' => ['Ds\Set', 'index'=>'int', 'length='=>'?int'], 'Ds\Set::sort' => ['void', 'comparator='=>'callable'], 'Ds\Set::sorted' => ['Ds\Set', 'comparator='=>'callable'], 'Ds\Set::sum' => ['int|float'], 'Ds\Set::toArray' => ['array'], 'Ds\Set::union' => ['Ds\Set', 'set'=>'Ds\Set'], 'Ds\Set::xor' => ['Ds\Set', 'set'=>'Ds\Set'], 'Ds\Stack::__construct' => ['void', 'values='=>'mixed'], 'Ds\Stack::allocate' => ['void', 'capacity'=>'int'], 'Ds\Stack::capacity' => ['int'], 'Ds\Stack::clear' => ['void'], 'Ds\Stack::copy' => ['Ds\Stack'], 'Ds\Stack::count' => ['0|positive-int'], 'Ds\Stack::isEmpty' => ['bool'], 'Ds\Stack::jsonSerialize' => ['array'], 'Ds\Stack::peek' => ['mixed'], 'Ds\Stack::pop' => ['mixed'], 'Ds\Stack::push' => ['void', '...values='=>'mixed'], 'Ds\Stack::toArray' => ['array'], 'Ds\Vector::__construct' => ['void', 'values='=>'mixed'], 'Ds\Vector::allocate' => ['void', 'capacity'=>'int'], 'Ds\Vector::apply' => ['void', 'callback'=>'callable'], 'Ds\Vector::capacity' => ['int'], 'Ds\Vector::clear' => ['void'], 'Ds\Vector::contains' => ['bool', '...values='=>'mixed'], 'Ds\Vector::copy' => ['Ds\Vector'], 'Ds\Vector::count' => ['0|positive-int'], 'Ds\Vector::filter' => ['Ds\Vector', 'callback='=>'callable'], 'Ds\Vector::find' => ['mixed', 'value'=>'mixed'], 'Ds\Vector::first' => ['mixed'], 'Ds\Vector::get' => ['mixed', 'index'=>'int'], 'Ds\Vector::insert' => ['void', 'index'=>'int', '...values='=>'mixed'], 'Ds\Vector::isEmpty' => ['bool'], 'Ds\Vector::join' => ['string', 'glue='=>'string'], 'Ds\Vector::jsonSerialize' => ['array'], 'Ds\Vector::last' => ['mixed'], 'Ds\Vector::map' => ['Ds\Vector', 'callback'=>'callable'], 'Ds\Vector::merge' => ['Ds\Vector', 'values'=>'mixed'], 'Ds\Vector::pop' => ['mixed'], 'Ds\Vector::push' => ['void', '...values='=>'mixed'], 'Ds\Vector::reduce' => ['mixed', 'callback'=>'callable', 'initial='=>'mixed'], 'Ds\Vector::remove' => ['mixed', 'index'=>'int'], 'Ds\Vector::reverse' => ['void'], 'Ds\Vector::reversed' => ['Ds\Vector'], 'Ds\Vector::rotate' => ['void', 'rotations'=>'int'], 'Ds\Vector::set' => ['void', 'index'=>'int', 'value'=>'mixed'], 'Ds\Vector::shift' => ['mixed'], 'Ds\Vector::slice' => ['Ds\Vector', 'index'=>'int', 'length='=>'?int'], 'Ds\Vector::sort' => ['void', 'comparator='=>'callable'], 'Ds\Vector::sorted' => ['Ds\Vector', 'comparator='=>'callable'], 'Ds\Vector::sum' => ['int|float'], 'Ds\Vector::toArray' => ['array'], 'Ds\Vector::unshift' => ['void', '...values='=>'mixed'], 'each' => ['array', '&rw_arr'=>'array'], 'easter_date' => ['int', 'year='=>'int'], 'easter_days' => ['int', 'year='=>'int', 'method='=>'int'], 'eio_busy' => ['resource', 'delay'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_cancel' => ['void', 'req'=>'resource'], 'eio_chmod' => ['resource', 'path'=>'string', 'mode'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_chown' => ['resource', 'path'=>'string', 'uid'=>'int', 'gid='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_close' => ['resource', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_custom' => ['resource', 'execute'=>'callable', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_dup2' => ['resource', 'fd'=>'mixed', 'fd2'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_event_loop' => ['bool'], 'eio_fallocate' => ['resource', 'fd'=>'mixed', 'mode'=>'int', 'offset'=>'int', 'length'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fchmod' => ['resource', 'fd'=>'mixed', 'mode'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fchown' => ['resource', 'fd'=>'mixed', 'uid'=>'int', 'gid='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fdatasync' => ['resource', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_fstat' => ['resource', 'fd'=>'mixed', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_fstatvfs' => ['resource', 'fd'=>'mixed', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_fsync' => ['resource', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_ftruncate' => ['resource', 'fd'=>'mixed', 'offset='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_futime' => ['resource', 'fd'=>'mixed', 'atime'=>'float', 'mtime'=>'float', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_get_event_stream' => ['mixed'], 'eio_get_last_error' => ['string', 'req'=>'resource'], 'eio_grp' => ['resource', 'callback'=>'callable', 'data='=>'string'], 'eio_grp_add' => ['void', 'grp'=>'resource', 'req'=>'resource'], 'eio_grp_cancel' => ['void', 'grp'=>'resource'], 'eio_grp_limit' => ['void', 'grp'=>'resource', 'limit'=>'int'], 'eio_init' => ['void'], 'eio_link' => ['resource', 'path'=>'string', 'new_path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_lstat' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_mkdir' => ['resource', 'path'=>'string', 'mode'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_mknod' => ['resource', 'path'=>'string', 'mode'=>'int', 'dev'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_nop' => ['resource', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_npending' => ['int'], 'eio_nready' => ['int'], 'eio_nreqs' => ['int'], 'eio_nthreads' => ['int'], 'eio_open' => ['resource', 'path'=>'string', 'flags'=>'int', 'mode'=>'int', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_poll' => ['int'], 'eio_read' => ['resource', 'fd'=>'mixed', 'length'=>'int', 'offset'=>'int', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_readahead' => ['resource', 'fd'=>'mixed', 'offset'=>'int', 'length'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_readdir' => ['resource', 'path'=>'string', 'flags'=>'int', 'pri'=>'int', 'callback'=>'callable', 'data='=>'string'], 'eio_readlink' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'string'], 'eio_realpath' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'string'], 'eio_rename' => ['resource', 'path'=>'string', 'new_path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_rmdir' => ['resource', 'path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_seek' => ['resource', 'fd'=>'mixed', 'offset'=>'int', 'whence'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_sendfile' => ['resource', 'out_fd'=>'mixed', 'in_fd'=>'mixed', 'offset'=>'int', 'length'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'string'], 'eio_set_max_idle' => ['void', 'nthreads'=>'int'], 'eio_set_max_parallel' => ['void', 'nthreads'=>'int'], 'eio_set_max_poll_reqs' => ['void', 'nreqs'=>'int'], 'eio_set_max_poll_time' => ['void', 'nseconds'=>'float'], 'eio_set_min_parallel' => ['void', 'nthreads'=>'string'], 'eio_stat' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_statvfs' => ['resource', 'path'=>'string', 'pri'=>'int', 'callback'=>'callable', 'data='=>'mixed'], 'eio_symlink' => ['resource', 'path'=>'string', 'new_path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_sync' => ['resource', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_sync_file_range' => ['resource', 'fd'=>'mixed', 'offset'=>'int', 'nbytes'=>'int', 'flags'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_syncfs' => ['resource', 'fd'=>'mixed', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_truncate' => ['resource', 'path'=>'string', 'offset='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_unlink' => ['resource', 'path'=>'string', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_utime' => ['resource', 'path'=>'string', 'atime'=>'float', 'mtime'=>'float', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'eio_write' => ['resource', 'fd'=>'mixed', 'str'=>'string', 'length='=>'int', 'offset='=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'], 'EmptyIterator::current' => ['mixed'], 'EmptyIterator::key' => ['mixed'], 'EmptyIterator::next' => ['void'], 'EmptyIterator::rewind' => ['void'], 'EmptyIterator::valid' => ['bool'], 'enchant_broker_describe' => ['array', 'broker'=>'resource'], 'enchant_broker_dict_exists' => ['bool', 'broker'=>'resource', 'tag'=>'string'], 'enchant_broker_free' => ['bool', 'broker'=>'resource'], 'enchant_broker_free_dict' => ['bool', 'dict'=>'resource'], 'enchant_broker_get_dict_path' => ['string|false', 'broker'=>'resource', 'dict_type'=>'int'], 'enchant_broker_get_error' => ['string|false', 'broker'=>'resource'], 'enchant_broker_init' => ['resource|false'], 'enchant_broker_list_dicts' => ['array|false', 'broker'=>'resource'], 'enchant_broker_request_dict' => ['resource|false', 'broker'=>'resource', 'tag'=>'string'], 'enchant_broker_request_pwl_dict' => ['resource|false', 'broker'=>'resource', 'filename'=>'string'], 'enchant_broker_set_dict_path' => ['bool', 'broker'=>'resource', 'dict_type'=>'int', 'value'=>'string'], 'enchant_broker_set_ordering' => ['bool', 'broker'=>'resource', 'tag'=>'string', 'ordering'=>'string'], 'enchant_dict_add_to_personal' => ['void', 'dict'=>'resource', 'word'=>'string'], 'enchant_dict_add_to_session' => ['void', 'dict'=>'resource', 'word'=>'string'], 'enchant_dict_check' => ['bool', 'dict'=>'resource', 'word'=>'string'], 'enchant_dict_describe' => ['array', 'dict'=>'resource'], 'enchant_dict_get_error' => ['string|false', 'dict'=>'resource'], 'enchant_dict_is_in_session' => ['bool', 'dict'=>'resource', 'word'=>'string'], 'enchant_dict_quick_check' => ['bool', 'dict'=>'resource', 'word'=>'string', 'suggestions='=>'array'], 'enchant_dict_store_replacement' => ['void', 'dict'=>'resource', 'mis'=>'string', 'cor'=>'string'], 'enchant_dict_suggest' => ['array', 'dict'=>'resource', 'word'=>'string'], 'end' => ['mixed', '&rw_array_arg'=>'array|object'], 'ereg' => ['int', 'pattern'=>'string', 'string'=>'string', 'regs='=>'array'], 'ereg_replace' => ['string', 'pattern'=>'string', 'replacement'=>'string', 'string'=>'string'], 'eregi' => ['int', 'pattern'=>'string', 'string'=>'string', 'regs='=>'array'], 'eregi_replace' => ['string', 'pattern'=>'string', 'replacement'=>'string', 'string'=>'string'], 'Error::__clone' => ['void'], 'Error::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?Error)'], 'Error::__toString' => ['string'], 'Error::getCode' => ['int'], 'Error::getFile' => ['string'], 'Error::getLine' => ['int'], 'Error::getMessage' => ['string'], 'Error::getPrevious' => ['Throwable|Error|null'], 'Error::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'Error::getTraceAsString' => ['string'], 'error_clear_last' => ['void'], 'error_get_last' => ['?array{type:int,message:string,file:string,line:int}'], 'error_log' => ['bool', 'message'=>'string', 'message_type='=>'int', 'destination='=>'string', 'extra_headers='=>'string'], 'error_reporting' => ['int', 'new_error_level='=>'int'], 'ErrorException::__clone' => ['void'], 'ErrorException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'severity='=>'int', 'filename='=>'string', 'lineno='=>'int', 'previous='=>'(?Throwable)|(?ErrorException)'], 'ErrorException::__toString' => ['string'], 'ErrorException::getCode' => ['int'], 'ErrorException::getFile' => ['string'], 'ErrorException::getLine' => ['int'], 'ErrorException::getMessage' => ['string'], 'ErrorException::getPrevious' => ['Throwable|ErrorException|null'], 'ErrorException::getSeverity' => ['int'], 'ErrorException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'ErrorException::getTraceAsString' => ['string'], 'escapeshellarg' => ['string', 'arg'=>'string'], 'escapeshellcmd' => ['string', 'command'=>'string'], 'Ev::backend' => ['int'], 'Ev::depth' => ['int'], 'Ev::embeddableBackends' => ['int'], 'Ev::feedSignal' => ['void', 'signum'=>'int'], 'Ev::feedSignalEvent' => ['void', 'signum'=>'int'], 'Ev::iteration' => ['int'], 'Ev::now' => ['float'], 'Ev::nowUpdate' => ['void'], 'Ev::recommendedBackends' => ['int'], 'Ev::resume' => ['void'], 'Ev::run' => ['void', 'flags='=>'int'], 'Ev::sleep' => ['void', 'seconds'=>'float'], 'Ev::stop' => ['void', 'how='=>'int'], 'Ev::supportedBackends' => ['int'], 'Ev::suspend' => ['void'], 'Ev::time' => ['float'], 'Ev::verify' => ['void'], 'EvCheck::__construct' => ['void', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvCheck::createStopped' => ['object', 'callback'=>'string', 'data='=>'string', 'priority='=>'string'], 'EvChild::__construct' => ['void', 'pid'=>'int', 'trace'=>'bool', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvChild::createStopped' => ['object', 'pid'=>'int', 'trace'=>'bool', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvChild::set' => ['void', 'pid'=>'int', 'trace'=>'bool'], 'EvEmbed::__construct' => ['void', 'other'=>'object', 'callback='=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvEmbed::createStopped' => ['void', 'other'=>'object', 'callback='=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvEmbed::set' => ['void', 'other'=>'object'], 'EvEmbed::sweep' => ['void'], 'Event::__construct' => ['void', 'base'=>'EventBase', 'fd'=>'mixed', 'what'=>'int', 'cb'=>'callable', 'arg='=>'mixed'], 'Event::add' => ['bool', 'timeout='=>'float'], 'Event::addSignal' => ['bool', 'timeout='=>'float'], 'Event::addTimer' => ['bool', 'timeout='=>'float'], 'Event::del' => ['bool'], 'Event::delSignal' => ['bool'], 'Event::delTimer' => ['bool'], 'Event::free' => ['void'], 'Event::getSupportedMethods' => ['array'], 'Event::pending' => ['bool', 'flags'=>'int'], 'Event::set' => ['bool', 'base'=>'EventBase', 'fd'=>'mixed', 'what='=>'int', 'cb='=>'callable', 'arg='=>'mixed'], 'Event::setPriority' => ['bool', 'priority'=>'int'], 'Event::setTimer' => ['bool', 'base'=>'EventBase', 'cb'=>'callable', 'arg='=>'mixed'], 'Event::signal' => ['Event', 'base'=>'EventBase', 'signum'=>'int', 'cb'=>'callable', 'arg='=>'mixed'], 'Event::timer' => ['Event', 'base'=>'EventBase', 'cb'=>'callable', 'arg='=>'mixed'], 'event_add' => ['bool', 'event'=>'resource', 'timeout='=>'int'], 'event_base_free' => ['void', 'event_base'=>'resource'], 'event_base_loop' => ['int', 'event_base'=>'resource', 'flags='=>'int'], 'event_base_loopbreak' => ['bool', 'event_base'=>'resource'], 'event_base_loopexit' => ['bool', 'event_base'=>'resource', 'timeout='=>'int'], 'event_base_new' => ['resource'], 'event_base_priority_init' => ['bool', 'event_base'=>'resource', 'npriorities'=>'int'], 'event_base_reinit' => ['bool', 'event_base'=>'resource'], 'event_base_set' => ['bool', 'event'=>'resource', 'event_base'=>'resource'], 'event_buffer_base_set' => ['bool', 'bevent'=>'resource', 'event_base'=>'resource'], 'event_buffer_disable' => ['bool', 'bevent'=>'resource', 'events'=>'int'], 'event_buffer_enable' => ['bool', 'bevent'=>'resource', 'events'=>'int'], 'event_buffer_fd_set' => ['void', 'bevent'=>'resource', 'fd'=>'resource'], 'event_buffer_free' => ['void', 'bevent'=>'resource'], 'event_buffer_new' => ['resource', 'stream'=>'resource', 'readcb'=>'mixed', 'writecb'=>'mixed', 'errorcb'=>'mixed', 'arg='=>'mixed'], 'event_buffer_priority_set' => ['bool', 'bevent'=>'resource', 'priority'=>'int'], 'event_buffer_read' => ['string', 'bevent'=>'resource', 'data_size'=>'int'], 'event_buffer_set_callback' => ['bool', 'event'=>'resource', 'readcb'=>'mixed', 'writecb'=>'mixed', 'errorcb'=>'mixed', 'arg='=>'mixed'], 'event_buffer_timeout_set' => ['void', 'bevent'=>'resource', 'read_timeout'=>'int', 'write_timeout'=>'int'], 'event_buffer_watermark_set' => ['void', 'bevent'=>'resource', 'events'=>'int', 'lowmark'=>'int', 'highmark'=>'int'], 'event_buffer_write' => ['bool', 'bevent'=>'resource', 'data'=>'string', 'data_size='=>'int'], 'event_del' => ['bool', 'event'=>'resource'], 'event_free' => ['void', 'event'=>'resource'], 'event_new' => ['resource'], 'event_priority_set' => ['bool', 'event'=>'resource', 'priority'=>'int'], 'event_set' => ['bool', 'event'=>'resource', 'fd'=>'mixed', 'events'=>'int', 'callback'=>'mixed', 'arg='=>'mixed'], 'event_timer_add' => ['bool', 'event'=>'resource', 'timeout='=>'int'], 'event_timer_del' => ['bool', 'event'=>'resource'], 'event_timer_new' => ['bool|resource'], 'event_timer_pending' => ['bool', 'event'=>'resource', 'timeout='=>'int'], 'event_timer_set' => ['bool', 'event'=>'resource', 'callback'=>'callable', 'arg='=>'mixed'], 'EventBase::__construct' => ['void', 'cfg='=>'EventConfig'], 'EventBase::dispatch' => ['void'], 'EventBase::exit' => ['bool', 'timeout='=>'float'], 'EventBase::free' => ['void'], 'EventBase::getFeatures' => ['int'], 'EventBase::getMethod' => ['string', 'cfg='=>'EventConfig'], 'EventBase::getTimeOfDayCached' => ['float'], 'EventBase::gotExit' => ['bool'], 'EventBase::gotStop' => ['bool'], 'EventBase::loop' => ['bool', 'flags='=>'int'], 'EventBase::priorityInit' => ['bool', 'n_priorities'=>'int'], 'EventBase::reInit' => ['bool'], 'EventBase::stop' => ['bool'], 'EventBuffer::__construct' => ['void'], 'EventBuffer::add' => ['bool', 'data'=>'string'], 'EventBuffer::addBuffer' => ['bool', 'buf'=>'EventBuffer'], 'EventBuffer::appendFrom' => ['int', 'buf'=>'EventBuffer', 'len'=>'int'], 'EventBuffer::copyout' => ['int', '&w_data'=>'string', 'max_bytes'=>'int'], 'EventBuffer::drain' => ['bool', 'len'=>'int'], 'EventBuffer::enableLocking' => ['void'], 'EventBuffer::expand' => ['bool', 'len'=>'int'], 'EventBuffer::freeze' => ['bool', 'at_front'=>'bool'], 'EventBuffer::lock' => ['void'], 'EventBuffer::prepend' => ['bool', 'data'=>'string'], 'EventBuffer::prependBuffer' => ['bool', 'buf'=>'EventBuffer'], 'EventBuffer::pullup' => ['string', 'size'=>'int'], 'EventBuffer::read' => ['string', 'max_bytes'=>'int'], 'EventBuffer::readFrom' => ['int', 'fd'=>'mixed', 'howmuch'=>'int'], 'EventBuffer::readLine' => ['string', 'eol_style'=>'int'], 'EventBuffer::search' => ['mixed', 'what'=>'string', 'start='=>'int', 'end='=>'int'], 'EventBuffer::searchEol' => ['mixed', 'start='=>'int', 'eol_style='=>'int'], 'EventBuffer::substr' => ['string', 'start'=>'int', 'length='=>'int'], 'EventBuffer::unfreeze' => ['bool', 'at_front'=>'bool'], 'EventBuffer::unlock' => ['bool'], 'EventBuffer::write' => ['int', 'fd'=>'mixed', 'howmuch='=>'int'], 'EventBufferEvent::__construct' => ['void', 'base'=>'EventBase', 'socket='=>'mixed', 'options='=>'int', 'readcb='=>'callable', 'writecb='=>'callable', 'eventcb='=>'callable'], 'EventBufferEvent::close' => ['void'], 'EventBufferEvent::connect' => ['bool', 'addr'=>'string'], 'EventBufferEvent::connectHost' => ['bool', 'dns_base'=>'EventDnsBase', 'hostname'=>'string', 'port'=>'int', 'family='=>'int'], 'EventBufferEvent::createPair' => ['array', 'base'=>'EventBase', 'options='=>'int'], 'EventBufferEvent::disable' => ['bool', 'events'=>'int'], 'EventBufferEvent::enable' => ['bool', 'events'=>'int'], 'EventBufferEvent::free' => ['void'], 'EventBufferEvent::getDnsErrorString' => ['string'], 'EventBufferEvent::getEnabled' => ['int'], 'EventBufferEvent::getInput' => ['EventBuffer'], 'EventBufferEvent::getOutput' => ['EventBuffer'], 'EventBufferEvent::read' => ['string', 'size'=>'int'], 'EventBufferEvent::readBuffer' => ['bool', 'buf'=>'EventBuffer'], 'EventBufferEvent::setCallbacks' => ['void', 'readcb'=>'callable', 'writecb'=>'callable', 'eventcb'=>'callable', 'arg='=>'string'], 'EventBufferEvent::setPriority' => ['bool', 'priority'=>'int'], 'EventBufferEvent::setTimeouts' => ['bool', 'timeout_read'=>'float', 'timeout_write'=>'float'], 'EventBufferEvent::setWatermark' => ['void', 'events'=>'int', 'lowmark'=>'int', 'highmark'=>'int'], 'EventBufferEvent::sslError' => ['string'], 'EventBufferEvent::sslFilter' => ['EventBufferEvent', 'base'=>'EventBase', 'underlying'=>'EventBufferEvent', 'ctx'=>'EventSslContext', 'state'=>'int', 'options='=>'int'], 'EventBufferEvent::sslGetCipherInfo' => ['string'], 'EventBufferEvent::sslGetCipherName' => ['string'], 'EventBufferEvent::sslGetCipherVersion' => ['string'], 'EventBufferEvent::sslGetProtocol' => ['string'], 'EventBufferEvent::sslRenegotiate' => ['void'], 'EventBufferEvent::sslSocket' => ['EventBufferEvent', 'base'=>'EventBase', 'socket'=>'mixed', 'ctx'=>'EventSslContext', 'state'=>'int', 'options='=>'int'], 'EventBufferEvent::write' => ['bool', 'data'=>'string'], 'EventBufferEvent::writeBuffer' => ['bool', 'buf'=>'EventBuffer'], 'EventConfig::__construct' => ['void'], 'EventConfig::avoidMethod' => ['bool', 'method'=>'string'], 'EventConfig::requireFeatures' => ['bool', 'feature'=>'int'], 'EventConfig::setMaxDispatchInterval' => ['void', 'max_interval'=>'int', 'max_callbacks'=>'int', 'min_priority'=>'int'], 'EventDnsBase::__construct' => ['void', 'base'=>'EventBase', 'initialize'=>'bool'], 'EventDnsBase::addNameserverIp' => ['bool', 'ip'=>'string'], 'EventDnsBase::addSearch' => ['void', 'domain'=>'string'], 'EventDnsBase::clearSearch' => ['void'], 'EventDnsBase::countNameservers' => ['int'], 'EventDnsBase::loadHosts' => ['bool', 'hosts'=>'string'], 'EventDnsBase::parseResolvConf' => ['bool', 'flags'=>'int', 'filename'=>'string'], 'EventDnsBase::setOption' => ['bool', 'option'=>'string', 'value'=>'string'], 'EventDnsBase::setSearchNdots' => ['bool', 'ndots'=>'int'], 'EventHttp::__construct' => ['void', 'base'=>'EventBase', 'ctx='=>'EventSslContext'], 'EventHttp::accept' => ['bool', 'socket'=>'mixed'], 'EventHttp::addServerAlias' => ['bool', 'alias'=>'string'], 'EventHttp::bind' => ['void', 'address'=>'string', 'port'=>'int'], 'EventHttp::removeServerAlias' => ['bool', 'alias'=>'string'], 'EventHttp::setAllowedMethods' => ['void', 'methods'=>'int'], 'EventHttp::setCallback' => ['void', 'path'=>'string', 'cb'=>'string', 'arg='=>'string'], 'EventHttp::setDefaultCallback' => ['void', 'cb'=>'string', 'arg='=>'string'], 'EventHttp::setMaxBodySize' => ['void', 'value'=>'int'], 'EventHttp::setMaxHeadersSize' => ['void', 'value'=>'int'], 'EventHttp::setTimeout' => ['void', 'value'=>'int'], 'EventHttpConnection::__construct' => ['void', 'base'=>'EventBase', 'dns_base'=>'EventDnsBase', 'address'=>'string', 'port'=>'int', 'ctx='=>'EventSslContext'], 'EventHttpConnection::getBase' => ['EventBase'], 'EventHttpConnection::getPeer' => ['void', '&w_address'=>'string', '&w_port'=>'int'], 'EventHttpConnection::makeRequest' => ['bool', 'req'=>'EventHttpRequest', 'type'=>'int', 'uri'=>'string'], 'EventHttpConnection::setCloseCallback' => ['void', 'callback'=>'callable', 'data='=>'mixed'], 'EventHttpConnection::setLocalAddress' => ['void', 'address'=>'string'], 'EventHttpConnection::setLocalPort' => ['void', 'port'=>'int'], 'EventHttpConnection::setMaxBodySize' => ['void', 'max_size'=>'string'], 'EventHttpConnection::setMaxHeadersSize' => ['void', 'max_size'=>'string'], 'EventHttpConnection::setRetries' => ['void', 'retries'=>'int'], 'EventHttpConnection::setTimeout' => ['void', 'timeout'=>'int'], 'EventHttpRequest::__construct' => ['void', 'callback'=>'callable', 'data='=>'mixed'], 'EventHttpRequest::addHeader' => ['bool', 'key'=>'string', 'value'=>'string', 'type'=>'int'], 'EventHttpRequest::cancel' => ['void'], 'EventHttpRequest::clearHeaders' => ['void'], 'EventHttpRequest::closeConnection' => ['void'], 'EventHttpRequest::findHeader' => ['void', 'key'=>'string', 'type'=>'string'], 'EventHttpRequest::free' => ['void'], 'EventHttpRequest::getBufferEvent' => ['EventBufferEvent'], 'EventHttpRequest::getCommand' => ['void'], 'EventHttpRequest::getConnection' => ['EventHttpConnection'], 'EventHttpRequest::getHost' => ['string'], 'EventHttpRequest::getInputBuffer' => ['EventBuffer'], 'EventHttpRequest::getInputHeaders' => ['array'], 'EventHttpRequest::getOutputBuffer' => ['EventBuffer'], 'EventHttpRequest::getOutputHeaders' => ['void'], 'EventHttpRequest::getResponseCode' => ['int'], 'EventHttpRequest::getUri' => ['string'], 'EventHttpRequest::removeHeader' => ['void', 'key'=>'string', 'type'=>'string'], 'EventHttpRequest::sendError' => ['void', 'error'=>'int', 'reason='=>'string'], 'EventHttpRequest::sendReply' => ['void', 'code'=>'int', 'reason'=>'string', 'buf='=>'EventBuffer'], 'EventHttpRequest::sendReplyChunk' => ['void', 'buf'=>'EventBuffer'], 'EventHttpRequest::sendReplyEnd' => ['void'], 'EventHttpRequest::sendReplyStart' => ['void', 'code'=>'int', 'reason'=>'string'], 'EventListener::__construct' => ['void', 'base'=>'EventBase', 'cb'=>'callable', 'data'=>'mixed', 'flags'=>'int', 'backlog'=>'int', 'target'=>'mixed'], 'EventListener::disable' => ['bool'], 'EventListener::enable' => ['bool'], 'EventListener::getBase' => ['void'], 'EventListener::getSocketName' => ['bool', '&w_address'=>'string', '&w_port='=>'mixed'], 'EventListener::setCallback' => ['void', 'cb'=>'callable', 'arg='=>'mixed'], 'EventListener::setErrorCallback' => ['void', 'cb'=>'string'], 'EventSslContext::__construct' => ['void', 'method'=>'string', 'options'=>'string'], 'EventUtil::__construct' => ['void'], 'EventUtil::getLastSocketErrno' => ['int', 'socket='=>'mixed'], 'EventUtil::getLastSocketError' => ['string', 'socket='=>'mixed'], 'EventUtil::getSocketFd' => ['int', 'socket'=>'mixed'], 'EventUtil::getSocketName' => ['bool', 'socket'=>'mixed', '&w_address'=>'string', '&w_port='=>'mixed'], 'EventUtil::setSocketOption' => ['bool', 'socket'=>'mixed', 'level'=>'int', 'optname'=>'int', 'optval'=>'mixed'], 'EventUtil::sslRandPoll' => ['void'], 'EvFork::__construct' => ['void', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvFork::createStopped' => ['object', 'callback'=>'string', 'data='=>'string', 'priority='=>'string'], 'EvIdle::__construct' => ['void', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvIdle::createStopped' => ['object', 'callback'=>'string', 'data='=>'mixed', 'priority='=>'int'], 'EvIo::__construct' => ['void', 'fd'=>'mixed', 'events'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvIo::createStopped' => ['EvIo', 'fd'=>'mixed', 'events'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvIo::set' => ['void', 'fd'=>'mixed', 'events'=>'int'], 'EvLoop::__construct' => ['void', 'flags='=>'int', 'data='=>'mixed', 'io_interval='=>'float', 'timeout_interval='=>'float'], 'EvLoop::backend' => ['int'], 'EvLoop::check' => ['EvCheck', 'callback'=>'string', 'data='=>'string', 'priority='=>'string'], 'EvLoop::child' => ['EvChild', 'pid'=>'string', 'trace'=>'string', 'callback'=>'string', 'data='=>'string', 'priority='=>'string'], 'EvLoop::defaultLoop' => ['EvLoop', 'flags='=>'int', 'data='=>'mixed', 'io_interval='=>'float', 'timeout_interval='=>'float'], 'EvLoop::embed' => ['EvEmbed', 'other'=>'string', 'callback='=>'string', 'data='=>'string', 'priority='=>'string'], 'EvLoop::fork' => ['EvFork', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::idle' => ['EvIdle', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::invokePending' => ['void'], 'EvLoop::io' => ['EvIo', 'fd'=>'mixed', 'events'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::loopFork' => ['void'], 'EvLoop::now' => ['float'], 'EvLoop::nowUpdate' => ['void'], 'EvLoop::periodic' => ['EvPeriodic', 'offset'=>'float', 'interval'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::prepare' => ['EvPrepare', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::resume' => ['void'], 'EvLoop::run' => ['void', 'flags='=>'int'], 'EvLoop::signal' => ['EvSignal', 'signum'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::stat' => ['EvStat', 'path'=>'string', 'interval'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::stop' => ['void', 'how='=>'int'], 'EvLoop::suspend' => ['void'], 'EvLoop::timer' => ['EvTimer', 'after'=>'float', 'repeat'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvLoop::verify' => ['void'], 'EvPeriodic::__construct' => ['void', 'offset'=>'float', 'interval'=>'string', 'reschedule_cb'=>'callable', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvPeriodic::again' => ['void'], 'EvPeriodic::at' => ['float'], 'EvPeriodic::createStopped' => ['EvPeriodic', 'offset'=>'float', 'interval'=>'float', 'reschedule_cb'=>'callable', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvPeriodic::set' => ['void', 'offset'=>'float', 'interval'=>'float'], 'EvPrepare::__construct' => ['void', 'callback'=>'string', 'data='=>'string', 'priority='=>'string'], 'EvPrepare::createStopped' => ['EvPrepare', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvSignal::__construct' => ['void', 'signum'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvSignal::createStopped' => ['EvSignal', 'signum'=>'int', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvSignal::set' => ['void', 'signum'=>'int'], 'EvStat::__construct' => ['void', 'path'=>'string', 'interval'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvStat::attr' => ['array'], 'EvStat::createStopped' => ['void', 'path'=>'string', 'interval'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvStat::prev' => ['void'], 'EvStat::set' => ['void', 'path'=>'string', 'interval'=>'float'], 'EvStat::stat' => ['bool'], 'EvTimer::__construct' => ['void', 'after'=>'float', 'repeat'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvTimer::again' => ['void'], 'EvTimer::createStopped' => ['EvTimer', 'after'=>'float', 'repeat'=>'float', 'callback'=>'callable', 'data='=>'mixed', 'priority='=>'int'], 'EvTimer::set' => ['void', 'after'=>'float', 'repeat'=>'float'], 'EvWatcher::__construct' => ['void'], 'EvWatcher::clear' => ['int'], 'EvWatcher::feed' => ['void', 'revents'=>'int'], 'EvWatcher::getLoop' => ['EvLoop'], 'EvWatcher::invoke' => ['void', 'revents'=>'int'], 'EvWatcher::keepalive' => ['bool', 'value='=>'bool'], 'EvWatcher::setCallback' => ['void', 'callback'=>'callable'], 'EvWatcher::start' => ['void'], 'EvWatcher::stop' => ['void'], 'Exception::__clone' => ['void'], 'Exception::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?Exception)'], 'Exception::__toString' => ['string'], 'Exception::getCode' => ['mixed'], 'Exception::getFile' => ['string'], 'Exception::getLine' => ['int'], 'Exception::getMessage' => ['string'], 'Exception::getPrevious' => ['(?Throwable)|(?Exception)'], 'Exception::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'Exception::getTraceAsString' => ['string'], 'exec' => ['string|false', 'command'=>'string', '&w_output='=>'array', '&w_return_value='=>'int'], 'exif_imagetype' => ['int|false', 'imagefile'=>'string'], 'exif_read_data' => ['array|false', 'filename'=>'string|resource', 'sections_needed='=>'string', 'sub_arrays='=>'bool', 'read_thumbnail='=>'bool'], 'exif_tagname' => ['string|false', 'index'=>'int'], 'exif_thumbnail' => ['string|false', 'filename'=>'string', '&w_width='=>'int', '&w_height='=>'int', '&w_imagetype='=>'int'], 'exp' => ['float', 'number'=>'float'], 'expect_expectl' => ['int', 'expect'=>'resource', 'cases'=>'array', 'match='=>'array'], 'expect_popen' => ['resource|false', 'command'=>'string'], 'explode' => ['list|false', 'separator'=>'string', 'str'=>'string', 'limit='=>'int'], 'expm1' => ['float', 'number'=>'float'], 'extension_loaded' => ['bool', 'extension_name'=>'string'], 'extract' => ['0|positive-int', 'array'=>'array', 'flags='=>'int', 'prefix='=>'string|null'], 'ezmlm_hash' => ['int', 'addr'=>'string'], 'fam_cancel_monitor' => ['bool', 'fam'=>'resource', 'fam_monitor'=>'resource'], 'fam_close' => ['void', 'fam'=>'resource'], 'fam_monitor_collection' => ['resource', 'fam'=>'resource', 'dirname'=>'string', 'depth'=>'int', 'mask'=>'string'], 'fam_monitor_directory' => ['resource', 'fam'=>'resource', 'dirname'=>'string'], 'fam_monitor_file' => ['resource', 'fam'=>'resource', 'filename'=>'string'], 'fam_next_event' => ['array', 'fam'=>'resource'], 'fam_open' => ['resource|false', 'appname='=>'string'], 'fam_pending' => ['int', 'fam'=>'resource'], 'fam_resume_monitor' => ['bool', 'fam'=>'resource', 'fam_monitor'=>'resource'], 'fam_suspend_monitor' => ['bool', 'fam'=>'resource', 'fam_monitor'=>'resource'], 'fann_cascadetrain_on_data' => ['bool', 'ann'=>'resource', 'data'=>'resource', 'max_neurons'=>'int', 'neurons_between_reports'=>'int', 'desired_error'=>'float'], 'fann_cascadetrain_on_file' => ['bool', 'ann'=>'resource', 'filename'=>'string', 'max_neurons'=>'int', 'neurons_between_reports'=>'int', 'desired_error'=>'float'], 'fann_clear_scaling_params' => ['bool', 'ann'=>'resource'], 'fann_copy' => ['resource', 'ann'=>'resource'], 'fann_create_from_file' => ['resource', 'configuration_file'=>'string'], 'fann_create_shortcut' => ['reference', 'num_layers'=>'int', 'num_neurons1'=>'int', 'num_neurons2'=>'int', '...args='=>'int'], 'fann_create_shortcut_array' => ['resource', 'num_layers'=>'int', 'layers'=>'array'], 'fann_create_sparse' => ['resource|false', 'connection_rate'=>'float', 'num_layers'=>'int', 'num_neurons1'=>'int', 'num_neurons2'=>'int', '...args='=>'int'], 'fann_create_sparse_array' => ['resource|false', 'connection_rate'=>'float', 'num_layers'=>'int', 'layers'=>'array'], 'fann_create_standard' => ['resource', 'num_layers'=>'int', 'num_neurons1'=>'int', 'num_neurons2'=>'int', '...args='=>'int'], 'fann_create_standard_array' => ['resource', 'num_layers'=>'int', 'layers'=>'array'], 'fann_create_train' => ['resource', 'num_data'=>'int', 'num_input'=>'int', 'num_output'=>'int'], 'fann_create_train_from_callback' => ['resource', 'num_data'=>'int', 'num_input'=>'int', 'num_output'=>'int', 'user_function'=>'callable'], 'fann_descale_input' => ['bool', 'ann'=>'resource', 'input_vector'=>'array'], 'fann_descale_output' => ['bool', 'ann'=>'resource', 'output_vector'=>'array'], 'fann_descale_train' => ['bool', 'ann'=>'resource', 'train_data'=>'resource'], 'fann_destroy' => ['bool', 'ann'=>'resource'], 'fann_destroy_train' => ['bool', 'train_data'=>'resource'], 'fann_duplicate_train_data' => ['resource', 'data'=>'resource'], 'fann_get_activation_function' => ['int', 'ann'=>'resource', 'layer'=>'int', 'neuron'=>'int'], 'fann_get_activation_steepness' => ['float', 'ann'=>'resource', 'layer'=>'int', 'neuron'=>'int'], 'fann_get_bias_array' => ['array', 'ann'=>'resource'], 'fann_get_bit_fail' => ['int', 'ann'=>'resource'], 'fann_get_bit_fail_limit' => ['float', 'ann'=>'resource'], 'fann_get_cascade_activation_functions' => ['array', 'ann'=>'resource'], 'fann_get_cascade_activation_functions_count' => ['int', 'ann'=>'resource'], 'fann_get_cascade_activation_steepnesses' => ['array', 'ann'=>'resource'], 'fann_get_cascade_activation_steepnesses_count' => ['int', 'ann'=>'resource'], 'fann_get_cascade_candidate_change_fraction' => ['float', 'ann'=>'resource'], 'fann_get_cascade_candidate_limit' => ['float', 'ann'=>'resource'], 'fann_get_cascade_candidate_stagnation_epochs' => ['float', 'ann'=>'resource'], 'fann_get_cascade_max_cand_epochs' => ['int', 'ann'=>'resource'], 'fann_get_cascade_max_out_epochs' => ['int', 'ann'=>'resource'], 'fann_get_cascade_min_cand_epochs' => ['int', 'ann'=>'resource'], 'fann_get_cascade_min_out_epochs' => ['int', 'ann'=>'resource'], 'fann_get_cascade_num_candidate_groups' => ['int', 'ann'=>'resource'], 'fann_get_cascade_num_candidates' => ['int', 'ann'=>'resource'], 'fann_get_cascade_output_change_fraction' => ['float', 'ann'=>'resource'], 'fann_get_cascade_output_stagnation_epochs' => ['int', 'ann'=>'resource'], 'fann_get_cascade_weight_multiplier' => ['float', 'ann'=>'resource'], 'fann_get_connection_array' => ['array', 'ann'=>'resource'], 'fann_get_connection_rate' => ['float', 'ann'=>'resource'], 'fann_get_errno' => ['int', 'errdat'=>'resource'], 'fann_get_errstr' => ['string', 'errdat'=>'resource'], 'fann_get_layer_array' => ['array', 'ann'=>'resource'], 'fann_get_learning_momentum' => ['float', 'ann'=>'resource'], 'fann_get_learning_rate' => ['float', 'ann'=>'resource'], 'fann_get_MSE' => ['float', 'ann'=>'resource'], 'fann_get_network_type' => ['int', 'ann'=>'resource'], 'fann_get_num_input' => ['int', 'ann'=>'resource'], 'fann_get_num_layers' => ['int', 'ann'=>'resource'], 'fann_get_num_output' => ['int', 'ann'=>'resource'], 'fann_get_quickprop_decay' => ['float', 'ann'=>'resource'], 'fann_get_quickprop_mu' => ['float', 'ann'=>'resource'], 'fann_get_rprop_decrease_factor' => ['float', 'ann'=>'resource'], 'fann_get_rprop_delta_max' => ['float', 'ann'=>'resource'], 'fann_get_rprop_delta_min' => ['float', 'ann'=>'resource'], 'fann_get_rprop_delta_zero' => ['float|false', 'ann'=>'resource'], 'fann_get_rprop_increase_factor' => ['float', 'ann'=>'resource'], 'fann_get_sarprop_step_error_shift' => ['float', 'ann'=>'resource'], 'fann_get_sarprop_step_error_threshold_factor' => ['float', 'ann'=>'resource'], 'fann_get_sarprop_temperature' => ['float', 'ann'=>'resource'], 'fann_get_sarprop_weight_decay_shift' => ['float', 'ann'=>'resource'], 'fann_get_total_connections' => ['int', 'ann'=>'resource'], 'fann_get_total_neurons' => ['int', 'ann'=>'resource'], 'fann_get_train_error_function' => ['int', 'ann'=>'resource'], 'fann_get_train_stop_function' => ['int', 'ann'=>'resource'], 'fann_get_training_algorithm' => ['int', 'ann'=>'resource'], 'fann_init_weights' => ['bool', 'ann'=>'resource', 'train_data'=>'resource'], 'fann_length_train_data' => ['int', 'data'=>'resource'], 'fann_merge_train_data' => ['resource', 'data1'=>'resource', 'data2'=>'resource'], 'fann_num_input_train_data' => ['int', 'data'=>'resource'], 'fann_num_output_train_data' => ['int', 'data'=>'resource'], 'fann_print_error' => ['void', 'errdat'=>'string'], 'fann_randomize_weights' => ['bool', 'ann'=>'resource', 'min_weight'=>'float', 'max_weight'=>'float'], 'fann_read_train_from_file' => ['resource', 'filename'=>'string'], 'fann_reset_errno' => ['void', 'errdat'=>'resource'], 'fann_reset_errstr' => ['void', 'errdat'=>'resource'], 'fann_reset_MSE' => ['bool', 'ann'=>'string'], 'fann_run' => ['array', 'ann'=>'resource', 'input'=>'array'], 'fann_save' => ['bool', 'ann'=>'resource', 'configuration_file'=>'string'], 'fann_save_train' => ['bool', 'data'=>'resource', 'file_name'=>'string'], 'fann_scale_input' => ['bool', 'ann'=>'resource', 'input_vector'=>'array'], 'fann_scale_input_train_data' => ['bool', 'train_data'=>'resource', 'new_min'=>'float', 'new_max'=>'float'], 'fann_scale_output' => ['bool', 'ann'=>'resource', 'output_vector'=>'array'], 'fann_scale_output_train_data' => ['bool', 'train_data'=>'resource', 'new_min'=>'float', 'new_max'=>'float'], 'fann_scale_train' => ['bool', 'ann'=>'resource', 'train_data'=>'resource'], 'fann_scale_train_data' => ['bool', 'train_data'=>'resource', 'new_min'=>'float', 'new_max'=>'float'], 'fann_set_activation_function' => ['bool', 'ann'=>'resource', 'activation_function'=>'int', 'layer'=>'int', 'neuron'=>'int'], 'fann_set_activation_function_hidden' => ['bool', 'ann'=>'resource', 'activation_function'=>'int'], 'fann_set_activation_function_layer' => ['bool', 'ann'=>'resource', 'activation_function'=>'int', 'layer'=>'int'], 'fann_set_activation_function_output' => ['bool', 'ann'=>'resource', 'activation_function'=>'int'], 'fann_set_activation_steepness' => ['bool', 'ann'=>'resource', 'activation_steepness'=>'float', 'layer'=>'int', 'neuron'=>'int'], 'fann_set_activation_steepness_hidden' => ['bool', 'ann'=>'resource', 'activation_steepness'=>'float'], 'fann_set_activation_steepness_layer' => ['bool', 'ann'=>'resource', 'activation_steepness'=>'float', 'layer'=>'int'], 'fann_set_activation_steepness_output' => ['bool', 'ann'=>'resource', 'activation_steepness'=>'float'], 'fann_set_bit_fail_limit' => ['bool', 'ann'=>'resource', 'bit_fail_limit'=>'float'], 'fann_set_callback' => ['bool', 'ann'=>'resource', 'callback'=>'callable'], 'fann_set_cascade_activation_functions' => ['bool', 'ann'=>'resource', 'cascade_activation_functions'=>'array'], 'fann_set_cascade_activation_steepnesses' => ['bool', 'ann'=>'resource', 'cascade_activation_steepnesses_count'=>'array'], 'fann_set_cascade_candidate_change_fraction' => ['bool', 'ann'=>'resource', 'cascade_candidate_change_fraction'=>'float'], 'fann_set_cascade_candidate_limit' => ['bool', 'ann'=>'resource', 'cascade_candidate_limit'=>'float'], 'fann_set_cascade_candidate_stagnation_epochs' => ['bool', 'ann'=>'resource', 'cascade_candidate_stagnation_epochs'=>'int'], 'fann_set_cascade_max_cand_epochs' => ['bool', 'ann'=>'resource', 'cascade_max_cand_epochs'=>'int'], 'fann_set_cascade_max_out_epochs' => ['bool', 'ann'=>'resource', 'cascade_max_out_epochs'=>'int'], 'fann_set_cascade_min_cand_epochs' => ['bool', 'ann'=>'resource', 'cascade_min_cand_epochs'=>'int'], 'fann_set_cascade_min_out_epochs' => ['bool', 'ann'=>'resource', 'cascade_min_out_epochs'=>'int'], 'fann_set_cascade_num_candidate_groups' => ['bool', 'ann'=>'resource', 'cascade_num_candidate_groups'=>'int'], 'fann_set_cascade_output_change_fraction' => ['bool', 'ann'=>'resource', 'cascade_output_change_fraction'=>'float'], 'fann_set_cascade_output_stagnation_epochs' => ['bool', 'ann'=>'resource', 'cascade_output_stagnation_epochs'=>'int'], 'fann_set_cascade_weight_multiplier' => ['bool', 'ann'=>'resource', 'cascade_weight_multiplier'=>'float'], 'fann_set_error_log' => ['void', 'errdat'=>'resource', 'log_file'=>'string'], 'fann_set_input_scaling_params' => ['bool', 'ann'=>'resource', 'train_data'=>'resource', 'new_input_min'=>'float', 'new_input_max'=>'float'], 'fann_set_learning_momentum' => ['bool', 'ann'=>'resource', 'learning_momentum'=>'float'], 'fann_set_learning_rate' => ['bool', 'ann'=>'resource', 'learning_rate'=>'float'], 'fann_set_output_scaling_params' => ['bool', 'ann'=>'resource', 'train_data'=>'resource', 'new_output_min'=>'float', 'new_output_max'=>'float'], 'fann_set_quickprop_decay' => ['bool', 'ann'=>'resource', 'quickprop_decay'=>'float'], 'fann_set_quickprop_mu' => ['bool', 'ann'=>'resource', 'quickprop_mu'=>'float'], 'fann_set_rprop_decrease_factor' => ['bool', 'ann'=>'resource', 'rprop_decrease_factor'=>'float'], 'fann_set_rprop_delta_max' => ['bool', 'ann'=>'resource', 'rprop_delta_max'=>'float'], 'fann_set_rprop_delta_min' => ['bool', 'ann'=>'resource', 'rprop_delta_min'=>'float'], 'fann_set_rprop_delta_zero' => ['bool', 'ann'=>'resource', 'rprop_delta_zero'=>'float'], 'fann_set_rprop_increase_factor' => ['bool', 'ann'=>'resource', 'rprop_increase_factor'=>'float'], 'fann_set_sarprop_step_error_shift' => ['bool', 'ann'=>'resource', 'sarprop_step_error_shift'=>'float'], 'fann_set_sarprop_step_error_threshold_factor' => ['bool', 'ann'=>'resource', 'sarprop_step_error_threshold_factor'=>'float'], 'fann_set_sarprop_temperature' => ['bool', 'ann'=>'resource', 'sarprop_temperature'=>'float'], 'fann_set_sarprop_weight_decay_shift' => ['bool', 'ann'=>'resource', 'sarprop_weight_decay_shift'=>'float'], 'fann_set_scaling_params' => ['bool', 'ann'=>'resource', 'train_data'=>'resource', 'new_input_min'=>'float', 'new_input_max'=>'float', 'new_output_min'=>'float', 'new_output_max'=>'float'], 'fann_set_train_error_function' => ['bool', 'ann'=>'resource', 'error_function'=>'int'], 'fann_set_train_stop_function' => ['bool', 'ann'=>'resource', 'stop_function'=>'int'], 'fann_set_training_algorithm' => ['bool', 'ann'=>'resource', 'training_algorithm'=>'int'], 'fann_set_weight' => ['bool', 'ann'=>'resource', 'from_neuron'=>'int', 'to_neuron'=>'int', 'weight'=>'float'], 'fann_set_weight_array' => ['bool', 'ann'=>'resource', 'connections'=>'array'], 'fann_shuffle_train_data' => ['bool', 'train_data'=>'resource'], 'fann_subset_train_data' => ['resource', 'data'=>'resource', 'pos'=>'int', 'length'=>'int'], 'fann_test' => ['bool', 'ann'=>'resource', 'input'=>'array', 'desired_output'=>'array'], 'fann_test_data' => ['float', 'ann'=>'resource', 'data'=>'resource'], 'fann_train' => ['bool', 'ann'=>'resource', 'input'=>'array', 'desired_output'=>'array'], 'fann_train_epoch' => ['float', 'ann'=>'resource', 'data'=>'resource'], 'fann_train_on_data' => ['bool', 'ann'=>'resource', 'data'=>'resource', 'max_epochs'=>'int', 'epochs_between_reports'=>'int', 'desired_error'=>'float'], 'fann_train_on_file' => ['bool', 'ann'=>'resource', 'filename'=>'string', 'max_epochs'=>'int', 'epochs_between_reports'=>'int', 'desired_error'=>'float'], 'FANNConnection::__construct' => ['void', 'from_neuron'=>'int', 'to_neuron'=>'int', 'weight'=>'float'], 'FANNConnection::getFromNeuron' => ['int'], 'FANNConnection::getToNeuron' => ['int'], 'FANNConnection::getWeight' => ['void'], 'FANNConnection::setWeight' => ['bool', 'weight'=>'float'], 'fastcgi_finish_request' => ['bool'], 'fbsql_affected_rows' => ['int', 'link_identifier='=>'?resource'], 'fbsql_autocommit' => ['bool', 'link_identifier'=>'resource', 'onoff='=>'bool'], 'fbsql_blob_size' => ['int', 'blob_handle'=>'string', 'link_identifier='=>'?resource'], 'fbsql_change_user' => ['bool', 'user'=>'string', 'password'=>'string', 'database='=>'string', 'link_identifier='=>'?resource'], 'fbsql_clob_size' => ['int', 'clob_handle'=>'string', 'link_identifier='=>'?resource'], 'fbsql_close' => ['bool', 'link_identifier='=>'?resource'], 'fbsql_commit' => ['bool', 'link_identifier='=>'?resource'], 'fbsql_connect' => ['resource', 'hostname='=>'string', 'username='=>'string', 'password='=>'string'], 'fbsql_create_blob' => ['string', 'blob_data'=>'string', 'link_identifier='=>'?resource'], 'fbsql_create_clob' => ['string', 'clob_data'=>'string', 'link_identifier='=>'?resource'], 'fbsql_create_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource', 'database_options='=>'string'], 'fbsql_data_seek' => ['bool', 'result'=>'resource', 'row_number'=>'int'], 'fbsql_database' => ['string', 'link_identifier'=>'resource', 'database='=>'string'], 'fbsql_database_password' => ['string', 'link_identifier'=>'resource', 'database_password='=>'string'], 'fbsql_db_query' => ['resource', 'database'=>'string', 'query'=>'string', 'link_identifier='=>'?resource'], 'fbsql_db_status' => ['int', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'fbsql_drop_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'fbsql_errno' => ['int', 'link_identifier='=>'?resource'], 'fbsql_error' => ['string', 'link_identifier='=>'?resource'], 'fbsql_fetch_array' => ['array', 'result'=>'resource', 'result_type='=>'int'], 'fbsql_fetch_assoc' => ['array', 'result'=>'resource'], 'fbsql_fetch_field' => ['object', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_fetch_lengths' => ['array', 'result'=>'resource'], 'fbsql_fetch_object' => ['object', 'result'=>'resource'], 'fbsql_fetch_row' => ['array', 'result'=>'resource'], 'fbsql_field_flags' => ['string', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_field_len' => ['int', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_field_name' => ['string', 'result'=>'resource', 'field_index='=>'int'], 'fbsql_field_seek' => ['bool', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_field_table' => ['string', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_field_type' => ['string', 'result'=>'resource', 'field_offset='=>'int'], 'fbsql_free_result' => ['bool', 'result'=>'resource'], 'fbsql_get_autostart_info' => ['array', 'link_identifier='=>'?resource'], 'fbsql_hostname' => ['string', 'link_identifier'=>'resource', 'host_name='=>'string'], 'fbsql_insert_id' => ['int', 'link_identifier='=>'?resource'], 'fbsql_list_dbs' => ['resource', 'link_identifier='=>'?resource'], 'fbsql_list_fields' => ['resource', 'database_name'=>'string', 'table_name'=>'string', 'link_identifier='=>'?resource'], 'fbsql_list_tables' => ['resource', 'database'=>'string', 'link_identifier='=>'?resource'], 'fbsql_next_result' => ['bool', 'result'=>'resource'], 'fbsql_num_fields' => ['int', 'result'=>'resource'], 'fbsql_num_rows' => ['int', 'result'=>'resource'], 'fbsql_password' => ['string', 'link_identifier'=>'resource', 'password='=>'string'], 'fbsql_pconnect' => ['resource', 'hostname='=>'string', 'username='=>'string', 'password='=>'string'], 'fbsql_query' => ['resource', 'query'=>'string', 'link_identifier='=>'?resource', 'batch_size='=>'int'], 'fbsql_read_blob' => ['string', 'blob_handle'=>'string', 'link_identifier='=>'?resource'], 'fbsql_read_clob' => ['string', 'clob_handle'=>'string', 'link_identifier='=>'?resource'], 'fbsql_result' => ['mixed', 'result'=>'resource', 'row='=>'int', 'field='=>'mixed'], 'fbsql_rollback' => ['bool', 'link_identifier='=>'?resource'], 'fbsql_rows_fetched' => ['int', 'result'=>'resource'], 'fbsql_select_db' => ['bool', 'database_name='=>'string', 'link_identifier='=>'?resource'], 'fbsql_set_characterset' => ['void', 'link_identifier'=>'resource', 'characterset'=>'int', 'in_out_both='=>'int'], 'fbsql_set_lob_mode' => ['bool', 'result'=>'resource', 'lob_mode'=>'int'], 'fbsql_set_password' => ['bool', 'link_identifier'=>'resource', 'user'=>'string', 'password'=>'string', 'old_password'=>'string'], 'fbsql_set_transaction' => ['void', 'link_identifier'=>'resource', 'locking'=>'int', 'isolation'=>'int'], 'fbsql_start_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource', 'database_options='=>'string'], 'fbsql_stop_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'fbsql_table_name' => ['string', 'result'=>'resource', 'index'=>'int'], 'fbsql_username' => ['string', 'link_identifier'=>'resource', 'username='=>'string'], 'fbsql_warnings' => ['bool', 'onoff='=>'bool'], 'fclose' => ['bool', 'fp'=>'resource'], 'fdf_add_doc_javascript' => ['bool', 'fdf_document'=>'resource', 'script_name'=>'string', 'script_code'=>'string'], 'fdf_add_template' => ['bool', 'fdf_document'=>'resource', 'newpage'=>'int', 'filename'=>'string', 'template'=>'string', 'rename'=>'int'], 'fdf_close' => ['void', 'fdf_document'=>'resource'], 'fdf_create' => ['resource'], 'fdf_enum_values' => ['bool', 'fdf_document'=>'resource', 'function'=>'callable', 'userdata='=>'mixed'], 'fdf_errno' => ['int'], 'fdf_error' => ['string', 'error_code='=>'int'], 'fdf_get_ap' => ['bool', 'fdf_document'=>'resource', 'field'=>'string', 'face'=>'int', 'filename'=>'string'], 'fdf_get_attachment' => ['array', 'fdf_document'=>'resource', 'fieldname'=>'string', 'savepath'=>'string'], 'fdf_get_encoding' => ['string', 'fdf_document'=>'resource'], 'fdf_get_file' => ['string', 'fdf_document'=>'resource'], 'fdf_get_flags' => ['int', 'fdf_document'=>'resource', 'fieldname'=>'string', 'whichflags'=>'int'], 'fdf_get_opt' => ['mixed', 'fdf_document'=>'resource', 'fieldname'=>'string', 'element='=>'int'], 'fdf_get_status' => ['string', 'fdf_document'=>'resource'], 'fdf_get_value' => ['mixed', 'fdf_document'=>'resource', 'fieldname'=>'string', 'which='=>'int'], 'fdf_get_version' => ['string', 'fdf_document='=>'resource'], 'fdf_header' => ['void'], 'fdf_next_field_name' => ['string', 'fdf_document'=>'resource', 'fieldname='=>'string'], 'fdf_open' => ['resource|false', 'filename'=>'string'], 'fdf_open_string' => ['resource', 'fdf_data'=>'string'], 'fdf_remove_item' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'item'=>'int'], 'fdf_save' => ['bool', 'fdf_document'=>'resource', 'filename='=>'string'], 'fdf_save_string' => ['string', 'fdf_document'=>'resource'], 'fdf_set_ap' => ['bool', 'fdf_document'=>'resource', 'field_name'=>'string', 'face'=>'int', 'filename'=>'string', 'page_number'=>'int'], 'fdf_set_encoding' => ['bool', 'fdf_document'=>'resource', 'encoding'=>'string'], 'fdf_set_file' => ['bool', 'fdf_document'=>'resource', 'url'=>'string', 'target_frame='=>'string'], 'fdf_set_flags' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'whichflags'=>'int', 'newflags'=>'int'], 'fdf_set_javascript_action' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'trigger'=>'int', 'script'=>'string'], 'fdf_set_on_import_javascript' => ['bool', 'fdf_document'=>'resource', 'script'=>'string', 'before_data_import'=>'bool'], 'fdf_set_opt' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'element'=>'int', 'str1'=>'string', 'str2'=>'string'], 'fdf_set_status' => ['bool', 'fdf_document'=>'resource', 'status'=>'string'], 'fdf_set_submit_form_action' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'trigger'=>'int', 'script'=>'string', 'flags'=>'int'], 'fdf_set_target_frame' => ['bool', 'fdf_document'=>'resource', 'frame_name'=>'string'], 'fdf_set_value' => ['bool', 'fdf_document'=>'resource', 'fieldname'=>'string', 'value'=>'mixed', 'isname='=>'int'], 'fdf_set_version' => ['bool', 'fdf_document'=>'resource', 'version'=>'string'], 'feof' => ['bool', 'fp'=>'resource'], 'fflush' => ['bool', 'fp'=>'resource'], 'ffmpeg_animated_gif::__construct' => ['void', 'output_file_path'=>'string', 'width'=>'int', 'height'=>'int', 'frame_rate'=>'int', 'loop_count='=>'int'], 'ffmpeg_animated_gif::addFrame' => ['', 'frame_to_add'=>'ffmpeg_frame'], 'ffmpeg_frame::__construct' => ['void', 'gd_image'=>'resource'], 'ffmpeg_frame::crop' => ['', 'crop_top'=>'int', 'crop_bottom='=>'int', 'crop_left='=>'int', 'crop_right='=>'int'], 'ffmpeg_frame::getHeight' => ['int'], 'ffmpeg_frame::getPresentationTimestamp' => ['int'], 'ffmpeg_frame::getPTS' => ['int'], 'ffmpeg_frame::getWidth' => ['int'], 'ffmpeg_frame::resize' => ['', 'width'=>'int', 'height'=>'int', 'crop_top='=>'int', 'crop_bottom='=>'int', 'crop_left='=>'int', 'crop_right='=>'int'], 'ffmpeg_frame::toGDImage' => ['resource'], 'ffmpeg_movie::__construct' => ['void', 'path_to_media'=>'string', 'persistent'=>'bool'], 'ffmpeg_movie::getArtist' => ['string'], 'ffmpeg_movie::getAudioBitRate' => ['int'], 'ffmpeg_movie::getAudioChannels' => ['int'], 'ffmpeg_movie::getAudioCodec' => ['string'], 'ffmpeg_movie::getAudioSampleRate' => ['int'], 'ffmpeg_movie::getAuthor' => ['string'], 'ffmpeg_movie::getBitRate' => ['int'], 'ffmpeg_movie::getComment' => ['string'], 'ffmpeg_movie::getCopyright' => ['string'], 'ffmpeg_movie::getDuration' => ['int'], 'ffmpeg_movie::getFilename' => ['string'], 'ffmpeg_movie::getFrame' => ['ffmpeg_frame', 'framenumber'=>'int'], 'ffmpeg_movie::getFrameCount' => ['int'], 'ffmpeg_movie::getFrameHeight' => ['int'], 'ffmpeg_movie::getFrameNumber' => ['int'], 'ffmpeg_movie::getFrameRate' => ['int'], 'ffmpeg_movie::getFrameWidth' => ['int'], 'ffmpeg_movie::getGenre' => ['string'], 'ffmpeg_movie::getNextKeyFrame' => ['ffmpeg_frame'], 'ffmpeg_movie::getPixelFormat' => [''], 'ffmpeg_movie::getTitle' => ['string'], 'ffmpeg_movie::getTrackNumber' => ['int|string'], 'ffmpeg_movie::getVideoBitRate' => ['int'], 'ffmpeg_movie::getVideoCodec' => ['string'], 'ffmpeg_movie::getYear' => ['int|string'], 'ffmpeg_movie::hasAudio' => ['bool'], 'ffmpeg_movie::hasVideo' => ['bool'], 'fgetc' => ['string|false', 'fp'=>'resource'], 'fgetcsv' => ['list|array{0: null}|false|null', 'fp'=>'resource', 'length='=>'0|positive-int|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'fgets' => ['string|false', 'fp'=>'resource', 'length='=>'0|positive-int'], 'fgetss' => ['string|false', 'fp'=>'resource', 'length='=>'0|positive-int', 'allowable_tags='=>'string'], 'file' => ['list|false', 'filename'=>'string', 'flags='=>'int', 'context='=>'resource'], 'file_exists' => ['bool', 'filename'=>'string'], 'file_get_contents' => ['string|false', 'filename'=>'string', 'use_include_path='=>'bool', 'context='=>'?resource', 'offset='=>'int', 'maxlen='=>'0|positive-int'], 'file_put_contents' => ['0|positive-int|false', 'file'=>'string', 'data'=>'mixed', 'flags='=>'int', 'context='=>'?resource'], 'fileatime' => ['int|false', 'filename'=>'string'], 'filectime' => ['int|false', 'filename'=>'string'], 'filegroup' => ['int|false', 'filename'=>'string'], 'fileinode' => ['int|false', 'filename'=>'string'], 'filemtime' => ['int|false', 'filename'=>'string'], 'fileowner' => ['int|false', 'filename'=>'string'], 'fileperms' => ['int|false', 'filename'=>'string'], 'filepro' => ['bool', 'directory'=>'string'], 'filepro_fieldcount' => ['int'], 'filepro_fieldname' => ['string', 'field_number'=>'int'], 'filepro_fieldtype' => ['string', 'field_number'=>'int'], 'filepro_fieldwidth' => ['int', 'field_number'=>'int'], 'filepro_retrieve' => ['string', 'row_number'=>'int', 'field_number'=>'int'], 'filepro_rowcount' => ['int'], 'filesize' => ['0|positive-int|false', 'filename'=>'string'], 'FilesystemIterator::__construct' => ['void', 'path'=>'string', 'flags='=>'int'], 'FilesystemIterator::current' => ['string|SplFileInfo'], 'FilesystemIterator::getFlags' => ['int'], 'FilesystemIterator::key' => ['string'], 'FilesystemIterator::next' => ['void'], 'FilesystemIterator::rewind' => ['void'], 'FilesystemIterator::setFlags' => ['void', 'flags='=>'int'], 'filetype' => ['string|false', 'filename'=>'string'], 'filter_has_var' => ['bool', 'type'=>'int', 'variable_name'=>'string'], 'filter_id' => ['int|false', 'filtername'=>'string'], 'filter_input' => ['mixed', 'type'=>'int', 'variable_name'=>'string', 'filter='=>'int', 'options='=>'array|int'], 'filter_input_array' => ['array|false|null', 'type'=>'int', 'definition='=>'int|array', 'add_empty='=>'bool'], 'filter_list' => ['non-empty-list'], 'filter_var' => ['mixed', 'variable'=>'mixed', 'filter='=>'int', 'options='=>'mixed'], 'filter_var_array' => ['array|false|null', 'data'=>'array', 'definition='=>'mixed', 'add_empty='=>'bool'], 'FilterIterator::__construct' => ['void', 'iterator'=>'Iterator'], 'FilterIterator::accept' => ['bool'], 'FilterIterator::current' => ['mixed'], 'FilterIterator::getInnerIterator' => ['Iterator'], 'FilterIterator::key' => ['mixed'], 'FilterIterator::next' => ['void'], 'FilterIterator::rewind' => ['void'], 'FilterIterator::valid' => ['bool'], 'finfo::__construct' => ['void', 'options='=>'int', 'magic_file='=>'string'], 'finfo::finfo' => ['void', 'options='=>'int', 'magic_file='=>'string'], 'finfo::buffer' => ['string|false', 'string'=>'string', 'options='=>'int', 'context='=>'resource'], 'finfo::file' => ['string|false', 'file_name'=>'string', 'options='=>'int', 'context='=>'resource'], 'finfo::set_flags' => ['bool', 'options'=>'int'], 'finfo_buffer' => ['string|false', 'finfo'=>'resource', 'string'=>'string', 'options='=>'int', 'context='=>'resource'], 'finfo_close' => ['bool', 'finfo'=>'resource'], 'finfo_file' => ['string|false', 'finfo'=>'resource', 'file_name'=>'string', 'options='=>'int', 'context='=>'resource'], 'finfo_open' => ['resource|false', 'options='=>'int', 'arg='=>'string'], 'finfo_set_flags' => ['bool', 'finfo'=>'resource', 'options'=>'int'], 'floatval' => ['float', 'var'=>'scalar|array|resource|null'], 'flock' => ['bool', 'fp'=>'resource', 'operation'=>'int', '&w_wouldblock='=>'int'], 'floor' => ['__benevolent', 'number'=>'float'], 'flush' => ['void'], 'fmod' => ['float', 'x'=>'float', 'y'=>'float'], 'fnmatch' => ['bool', 'pattern'=>'string', 'filename'=>'string', 'flags='=>'int'], 'fopen' => ['resource|false', 'filename'=>'string', 'mode'=>'string', 'use_include_path='=>'bool', 'context='=>'resource|null'], 'forward_static_call' => ['mixed', 'function'=>'callable', '...parameters='=>'mixed'], 'forward_static_call_array' => ['mixed', 'function'=>'callable', 'parameters'=>'array'], 'fpassthru' => ['0|positive-int|false', 'fp'=>'resource'], 'fpm_get_status' => ['array{pool: string, process-manager: \'dynamic\'|\'ondemand\'|\'static\', start-time: int<0, max>, start-since: int<0, max>, accepted-conn: int<0, max>, listen-queue: int<0, max>, max-listen-queue: int<0, max>, listen-queue-len: int<0, max>, idle-processes: int<0, max>, active-processes: int<1, max>, total-processes: int<1, max>, max-active-processes: int<1, max>, max-children-reached: 0|1, slow-requests: int<0, max>, procs: array, state: \'Idle\'|\'Running\', start-time: int<0, max>, start-since: int<0, max>, requests: int<0, max>, request-duration: int<0, max>, request-method: string, request-uri: string, query-string: string, request-length: int<0, max>, user: string, script: string, last-request-cpu: float, last-request-memory: int<0, max>}>}|false'], 'fprintf' => ['int', 'stream'=>'resource', 'format'=>'string', '...values='=>'__stringAndStringable|int|float|null|bool'], 'fputcsv' => ['0|positive-int|false', 'fp'=>'resource', 'fields'=>'array', 'delimiter='=>'string', 'enclosure='=>'string', 'escape_char='=>'string'], 'fputs' => ['0|positive-int|false', 'fp'=>'resource', 'str'=>'string', 'length='=>'0|positive-int'], 'fread' => ['string', 'fp'=>'resource', 'length'=>'positive-int'], 'frenchtojd' => ['int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'fribidi_log2vis' => ['string', 'str'=>'string', 'direction'=>'string', 'charset'=>'int'], 'fscanf' => ['list|int|false', 'stream'=>'resource', 'format'=>'string', '&...w_vars='=>'string|int|float|null'], 'fseek' => ['0|-1', 'fp'=>'resource', 'offset'=>'int', 'whence='=>'int'], 'fsockopen' => ['resource|false', 'hostname'=>'string', 'port='=>'int', '&w_errno='=>'int', '&w_errstr='=>'string', 'timeout='=>'float'], 'fstat' => ['array|false', 'fp'=>'resource'], 'ftell' => ['int|false', 'fp'=>'resource'], 'ftok' => ['int', 'pathname'=>'string', 'proj'=>'string'], 'ftp_alloc' => ['bool', 'stream'=>'resource', 'size'=>'int', '&w_response='=>'string'], 'ftp_append' => ['bool', 'ftp'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int'], 'ftp_cdup' => ['bool', 'stream'=>'resource'], 'ftp_chdir' => ['bool', 'stream'=>'resource', 'directory'=>'string'], 'ftp_chmod' => ['int|false', 'stream'=>'resource', 'mode'=>'int', 'filename'=>'string'], 'ftp_close' => ['bool', 'stream'=>'resource'], 'ftp_connect' => ['resource|false', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'ftp_delete' => ['bool', 'stream'=>'resource', 'file'=>'string'], 'ftp_exec' => ['bool', 'stream'=>'resource', 'command'=>'string'], 'ftp_fget' => ['bool', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'int', 'resumepos='=>'int'], 'ftp_fput' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'int', 'startpos='=>'int'], 'ftp_get' => ['bool', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'int', 'resume_pos='=>'int'], 'ftp_get_option' => ['mixed', 'stream'=>'resource', 'option'=>'int'], 'ftp_login' => ['bool', 'stream'=>'resource', 'username'=>'string', 'password'=>'string'], 'ftp_mdtm' => ['int', 'stream'=>'resource', 'filename'=>'string'], 'ftp_mkdir' => ['string|false', 'stream'=>'resource', 'directory'=>'string'], 'ftp_mlsd' => ['array|false', 'ftp_stream'=>'resource', 'directory'=>'string'], 'ftp_nb_continue' => ['int', 'stream'=>'resource'], 'ftp_nb_fget' => ['int', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'int', 'resumepos='=>'int'], 'ftp_nb_fput' => ['int', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'int', 'startpos='=>'int'], 'ftp_nb_get' => ['int|false', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'int', 'resume_pos='=>'int'], 'ftp_nb_put' => ['int|false', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int', 'startpos='=>'int'], 'ftp_nlist' => ['array|false', 'stream'=>'resource', 'directory'=>'string'], 'ftp_pasv' => ['bool', 'stream'=>'resource', 'pasv'=>'bool'], 'ftp_put' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int', 'startpos='=>'int'], 'ftp_pwd' => ['string|false', 'stream'=>'resource'], 'ftp_raw' => ['array', 'stream'=>'resource', 'command'=>'string'], 'ftp_rawlist' => ['array|false', 'stream'=>'resource', 'directory'=>'string', 'recursive='=>'bool'], 'ftp_rename' => ['bool', 'stream'=>'resource', 'src'=>'string', 'dest'=>'string'], 'ftp_rmdir' => ['bool', 'stream'=>'resource', 'directory'=>'string'], 'ftp_set_option' => ['bool', 'stream'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'ftp_site' => ['bool', 'stream'=>'resource', 'cmd'=>'string'], 'ftp_size' => ['int', 'stream'=>'resource', 'filename'=>'string'], 'ftp_ssl_connect' => ['resource|false', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'ftp_systype' => ['string|false', 'stream'=>'resource'], 'ftruncate' => ['bool', 'fp'=>'resource', 'size'=>'0|positive-int'], 'func_get_arg' => ['mixed', 'arg_num'=>'0|positive-int'], 'func_get_args' => ['list'], 'func_num_args' => ['0|positive-int'], 'function_exists' => ['bool', 'function_name'=>'string'], 'fwrite' => ['0|positive-int|false', 'fp'=>'resource', 'str'=>'string', 'length='=>'0|positive-int'], 'gc_collect_cycles' => ['int'], 'gc_disable' => ['void'], 'gc_enable' => ['void'], 'gc_enabled' => ['bool'], 'gc_mem_caches' => ['int'], 'gc_status' => ['array{runs:int,collected:int,threshold:int,roots:int}'], 'gd_info' => ['array'], 'gearman_bugreport' => [''], 'gearman_client_add_options' => ['', 'client_object'=>'', 'option'=>''], 'gearman_client_add_server' => ['', 'client_object'=>'', 'host'=>'', 'port'=>''], 'gearman_client_add_servers' => ['', 'client_object'=>'', 'servers'=>''], 'gearman_client_add_task' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_high' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_high_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_low' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_low_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'context'=>'', 'unique'=>''], 'gearman_client_add_task_status' => ['', 'client_object'=>'', 'job_handle'=>'', 'context'=>''], 'gearman_client_clear_fn' => ['', 'client_object'=>''], 'gearman_client_clone' => ['', 'client_object'=>''], 'gearman_client_context' => ['', 'client_object'=>''], 'gearman_client_create' => ['', 'client_object'=>''], 'gearman_client_do' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_high' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_high_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_job_handle' => ['', 'client_object'=>''], 'gearman_client_do_low' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_low_background' => ['', 'client_object'=>'', 'function_name'=>'', 'workload'=>'', 'unique'=>''], 'gearman_client_do_normal' => ['', 'client_object'=>'', 'function_name'=>'string', 'workload'=>'string', 'unique'=>'string'], 'gearman_client_do_status' => ['', 'client_object'=>''], 'gearman_client_echo' => ['', 'client_object'=>'', 'workload'=>''], 'gearman_client_errno' => ['', 'client_object'=>''], 'gearman_client_error' => ['', 'client_object'=>''], 'gearman_client_job_status' => ['', 'client_object'=>'', 'job_handle'=>''], 'gearman_client_options' => ['', 'client_object'=>''], 'gearman_client_remove_options' => ['', 'client_object'=>'', 'option'=>''], 'gearman_client_return_code' => ['', 'client_object'=>''], 'gearman_client_run_tasks' => ['', 'data'=>''], 'gearman_client_set_complete_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_context' => ['', 'client_object'=>'', 'context'=>''], 'gearman_client_set_created_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_data_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_exception_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_fail_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_options' => ['', 'client_object'=>'', 'option'=>''], 'gearman_client_set_status_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_timeout' => ['', 'client_object'=>'', 'timeout'=>''], 'gearman_client_set_warning_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_set_workload_fn' => ['', 'client_object'=>'', 'callback'=>''], 'gearman_client_timeout' => ['', 'client_object'=>''], 'gearman_client_wait' => ['', 'client_object'=>''], 'gearman_job_function_name' => ['', 'job_object'=>''], 'gearman_job_handle' => ['string'], 'gearman_job_return_code' => ['', 'job_object'=>''], 'gearman_job_send_complete' => ['', 'job_object'=>'', 'result'=>''], 'gearman_job_send_data' => ['', 'job_object'=>'', 'data'=>''], 'gearman_job_send_exception' => ['', 'job_object'=>'', 'exception'=>''], 'gearman_job_send_fail' => ['', 'job_object'=>''], 'gearman_job_send_status' => ['', 'job_object'=>'', 'numerator'=>'', 'denominator'=>''], 'gearman_job_send_warning' => ['', 'job_object'=>'', 'warning'=>''], 'gearman_job_status' => ['array', 'job_handle'=>'string'], 'gearman_job_unique' => ['', 'job_object'=>''], 'gearman_job_workload' => ['', 'job_object'=>''], 'gearman_job_workload_size' => ['', 'job_object'=>''], 'gearman_task_data' => ['', 'task_object'=>''], 'gearman_task_data_size' => ['', 'task_object'=>''], 'gearman_task_denominator' => ['', 'task_object'=>''], 'gearman_task_function_name' => ['', 'task_object'=>''], 'gearman_task_is_known' => ['', 'task_object'=>''], 'gearman_task_is_running' => ['', 'task_object'=>''], 'gearman_task_job_handle' => ['', 'task_object'=>''], 'gearman_task_numerator' => ['', 'task_object'=>''], 'gearman_task_recv_data' => ['', 'task_object'=>'', 'data_len'=>''], 'gearman_task_return_code' => ['', 'task_object'=>''], 'gearman_task_send_workload' => ['', 'task_object'=>'', 'data'=>''], 'gearman_task_unique' => ['', 'task_object'=>''], 'gearman_verbose_name' => ['', 'verbose'=>''], 'gearman_version' => [''], 'gearman_worker_add_function' => ['', 'worker_object'=>'', 'function_name'=>'', 'function'=>'', 'data'=>'', 'timeout'=>''], 'gearman_worker_add_options' => ['', 'worker_object'=>'', 'option'=>''], 'gearman_worker_add_server' => ['', 'worker_object'=>'', 'host'=>'', 'port'=>''], 'gearman_worker_add_servers' => ['', 'worker_object'=>'', 'servers'=>''], 'gearman_worker_clone' => ['', 'worker_object'=>''], 'gearman_worker_create' => [''], 'gearman_worker_echo' => ['', 'worker_object'=>'', 'workload'=>''], 'gearman_worker_errno' => ['', 'worker_object'=>''], 'gearman_worker_error' => ['', 'worker_object'=>''], 'gearman_worker_grab_job' => ['', 'worker_object'=>''], 'gearman_worker_options' => ['', 'worker_object'=>''], 'gearman_worker_register' => ['', 'worker_object'=>'', 'function_name'=>'', 'timeout'=>''], 'gearman_worker_remove_options' => ['', 'worker_object'=>'', 'option'=>''], 'gearman_worker_return_code' => ['', 'worker_object'=>''], 'gearman_worker_set_options' => ['', 'worker_object'=>'', 'option'=>''], 'gearman_worker_set_timeout' => ['', 'worker_object'=>'', 'timeout'=>''], 'gearman_worker_timeout' => ['', 'worker_object'=>''], 'gearman_worker_unregister' => ['', 'worker_object'=>'', 'function_name'=>''], 'gearman_worker_unregister_all' => ['', 'worker_object'=>''], 'gearman_worker_wait' => ['', 'worker_object'=>''], 'gearman_worker_work' => ['', 'worker_object'=>''], 'GearmanClient::__construct' => ['void'], 'GearmanClient::addOptions' => ['bool', 'options'=>'int'], 'GearmanClient::addServer' => ['bool', 'host='=>'string', 'port='=>'int'], 'GearmanClient::addServers' => ['bool', 'servers='=>'string'], 'GearmanClient::addTask' => ['GearmanTask', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskBackground' => ['GearmanTask', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskHigh' => ['GearmanTask', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskHighBackground' => ['GearmanTask', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskLow' => ['GearmanTask', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskLowBackground' => ['GearmanTask', 'function_name'=>'string', 'workload'=>'string', 'context='=>'mixed', 'unique='=>'string'], 'GearmanClient::addTaskStatus' => ['GearmanTask', 'job_handle'=>'string', 'context='=>'string'], 'GearmanClient::clearCallbacks' => ['bool'], 'GearmanClient::clone' => ['GearmanClient'], 'GearmanClient::context' => ['string'], 'GearmanClient::data' => ['string'], 'GearmanClient::do' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doBackground' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doHigh' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doHighBackground' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doJobHandle' => ['string'], 'GearmanClient::doLow' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doLowBackground' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doNormal' => ['string', 'function_name'=>'string', 'workload'=>'string', 'unique='=>'string'], 'GearmanClient::doStatus' => ['array'], 'GearmanClient::echo' => ['bool', 'workload'=>'string'], 'GearmanClient::error' => ['string'], 'GearmanClient::getErrno' => ['int'], 'GearmanClient::jobStatus' => ['array', 'job_handle'=>'string'], 'GearmanClient::options' => [''], 'GearmanClient::ping' => ['bool', 'workload'=>'string'], 'GearmanClient::removeOptions' => ['bool', 'options'=>'int'], 'GearmanClient::returnCode' => ['int'], 'GearmanClient::runTasks' => ['bool'], 'GearmanClient::setClientCallback' => ['void', 'callback'=>'callable'], 'GearmanClient::setCompleteCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setContext' => ['bool', 'context'=>'string'], 'GearmanClient::setCreatedCallback' => ['bool', 'callback'=>'string'], 'GearmanClient::setData' => ['bool', 'data'=>'string'], 'GearmanClient::setDataCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setExceptionCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setFailCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setOptions' => ['bool', 'options'=>'int'], 'GearmanClient::setStatusCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setTimeout' => ['bool', 'timeout'=>'int'], 'GearmanClient::setWarningCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::setWorkloadCallback' => ['bool', 'callback'=>'callable'], 'GearmanClient::timeout' => ['int'], 'GearmanClient::wait' => [''], 'GearmanJob::__construct' => ['void'], 'GearmanJob::complete' => ['bool', 'result'=>'string'], 'GearmanJob::data' => ['bool', 'data'=>'string'], 'GearmanJob::exception' => ['bool', 'exception'=>'string'], 'GearmanJob::fail' => ['bool'], 'GearmanJob::functionName' => ['string'], 'GearmanJob::handle' => ['string'], 'GearmanJob::returnCode' => ['int'], 'GearmanJob::sendComplete' => ['bool', 'result'=>'string'], 'GearmanJob::sendData' => ['bool', 'data'=>'string'], 'GearmanJob::sendException' => ['bool', 'exception'=>'string'], 'GearmanJob::sendFail' => ['bool'], 'GearmanJob::sendStatus' => ['bool', 'numerator'=>'int', 'denominator'=>'int'], 'GearmanJob::sendWarning' => ['bool', 'warning'=>'string'], 'GearmanJob::setReturn' => ['bool', 'gearman_return_t'=>'string'], 'GearmanJob::status' => ['bool', 'numerator'=>'int', 'denominator'=>'int'], 'GearmanJob::unique' => ['string'], 'GearmanJob::warning' => ['bool', 'warning'=>'string'], 'GearmanJob::workload' => ['string'], 'GearmanJob::workloadSize' => ['int'], 'GearmanTask::__construct' => ['void'], 'GearmanTask::create' => ['GearmanTask'], 'GearmanTask::data' => ['string'], 'GearmanTask::dataSize' => ['int'], 'GearmanTask::function' => ['string'], 'GearmanTask::functionName' => ['string'], 'GearmanTask::isKnown' => ['bool'], 'GearmanTask::isRunning' => ['bool'], 'GearmanTask::jobHandle' => ['string'], 'GearmanTask::recvData' => ['array', 'data_len'=>'int'], 'GearmanTask::returnCode' => ['int'], 'GearmanTask::sendData' => ['int', 'data'=>'string'], 'GearmanTask::sendWorkload' => ['int', 'data'=>'string'], 'GearmanTask::taskDenominator' => ['int'], 'GearmanTask::taskNumerator' => ['int'], 'GearmanTask::unique' => ['string'], 'GearmanTask::uuid' => ['string'], 'GearmanWorker::__construct' => ['void'], 'GearmanWorker::addFunction' => ['bool', 'function_name'=>'string', 'function'=>'callable', 'context='=>'mixed', 'timeout='=>'int'], 'GearmanWorker::addOptions' => ['bool', 'option'=>'int'], 'GearmanWorker::addServer' => ['bool', 'host='=>'string', 'port='=>'int'], 'GearmanWorker::addServers' => ['bool', 'servers'=>'string'], 'GearmanWorker::clone' => ['void'], 'GearmanWorker::echo' => ['bool', 'workload'=>'string'], 'GearmanWorker::error' => ['string'], 'GearmanWorker::getErrno' => ['int'], 'GearmanWorker::grabJob' => [''], 'GearmanWorker::options' => ['int'], 'GearmanWorker::register' => ['bool', 'function_name'=>'string', 'timeout='=>'int'], 'GearmanWorker::removeOptions' => ['bool', 'option'=>'int'], 'GearmanWorker::returnCode' => ['int'], 'GearmanWorker::setId' => ['bool', 'id'=>'string'], 'GearmanWorker::setOptions' => ['bool', 'option'=>'int'], 'GearmanWorker::setTimeout' => ['bool', 'timeout'=>'int'], 'GearmanWorker::timeout' => ['int'], 'GearmanWorker::unregister' => ['bool', 'function_name'=>'string'], 'GearmanWorker::unregisterAll' => ['bool'], 'GearmanWorker::wait' => ['bool'], 'GearmanWorker::work' => ['bool'], 'Gender\Gender::__construct' => ['void', 'dsn='=>'string'], 'Gender\Gender::connect' => ['bool', 'dsn'=>'string'], 'Gender\Gender::country' => ['array', 'country'=>'int'], 'Gender\Gender::get' => ['int', 'name'=>'string', 'country='=>'int'], 'Gender\Gender::isNick' => ['array', 'name0'=>'string', 'name1'=>'string', 'country='=>'int'], 'Gender\Gender::similarNames' => ['array', 'name'=>'string', 'country='=>'int'], 'Generator::__wakeup' => ['void'], 'Generator::current' => ['mixed'], 'Generator::getReturn' => ['mixed'], 'Generator::key' => ['mixed'], 'Generator::next' => ['void'], 'Generator::rewind' => ['void'], 'Generator::send' => ['mixed', 'value'=>'mixed'], 'Generator::throw' => ['mixed', 'exception'=>'Exception|Throwable'], 'Generator::valid' => ['bool'], 'geoip_asnum_by_name' => ['string', 'hostname'=>'string'], 'geoip_continent_code_by_name' => ['string', 'hostname'=>'string'], 'geoip_country_code3_by_name' => ['string', 'hostname'=>'string'], 'geoip_country_code_by_name' => ['string', 'hostname'=>'string'], 'geoip_country_name_by_name' => ['string', 'hostname'=>'string'], 'geoip_database_info' => ['string', 'database='=>'int'], 'geoip_db_avail' => ['bool', 'database'=>'int'], 'geoip_db_filename' => ['string', 'database'=>'int'], 'geoip_db_get_all_info' => ['array'], 'geoip_domain_by_name' => ['string', 'hostname'=>'string'], 'geoip_id_by_name' => ['int', 'hostname'=>'string'], 'geoip_isp_by_name' => ['string', 'hostname'=>'string'], 'geoip_netspeedcell_by_name' => ['string', 'hostname'=>'string'], 'geoip_org_by_name' => ['string', 'hostname'=>'string'], 'geoip_record_by_name' => ['array', 'hostname'=>'string'], 'geoip_region_by_name' => ['array', 'hostname'=>'string'], 'geoip_region_name_by_code' => ['string', 'country_code'=>'string', 'region_code'=>'string'], 'geoip_setup_custom_directory' => ['void', 'path'=>'string'], 'geoip_time_zone_by_country_and_region' => ['string|false', 'country_code'=>'string', 'region_code='=>'string'], 'get_browser' => ['mixed', 'browser_name='=>'string', 'return_array='=>'bool'], 'get_call_stack' => [''], 'get_called_class' => ['class-string'], 'get_cfg_var' => ['mixed', 'option_name'=>'string'], 'get_class' => ['class-string', 'object='=>'object'], 'get_class_methods' => ['list', 'class'=>'mixed'], 'get_class_vars' => ['array', 'class_name'=>'string'], 'get_current_user' => ['string'], 'get_declared_classes' => ['list'], 'get_declared_interfaces' => ['list'], 'get_declared_traits' => ['list'], 'get_defined_constants' => ['array', 'categorize='=>'bool'], 'get_defined_functions' => ['array{internal:non-empty-list,user:list}', 'exclude_disabled='=>'bool'], 'get_defined_vars' => ['array'], 'get_extension_funcs' => ['list|false', 'extension_name'=>'string'], 'get_headers' => ['array|false', 'url'=>'string', 'format='=>'int', 'context='=>'resource'], 'get_html_translation_table' => ['array', 'table='=>'int', 'flags='=>'int', 'encoding='=>'string'], 'get_include_path' => ['__benevolent'], 'get_included_files' => ['list'], 'get_loaded_extensions' => ['list', 'zend_extensions='=>'bool'], 'get_magic_quotes_gpc' => ['false'], 'get_magic_quotes_runtime' => ['false'], 'get_meta_tags' => ['array|false', 'filename'=>'string', 'use_include_path='=>'bool'], 'get_object_vars' => ['array', 'obj'=>'object'], 'get_parent_class' => ['class-string|false', 'object='=>'mixed'], 'get_required_files' => ['list'], 'get_resource_type' => ['string', 'res'=>'resource'], 'get_resources' => ['array', 'type='=>'string'], 'getallheaders' => ['array'], 'getcwd' => ['non-empty-string|false'], 'getdate' => ['array{seconds: int<0, 59>, minutes: int<0, 59>, hours: int<0, 23>, mday: int<1, 31>, wday: int<0, 6>, mon: int<1, 12>, year: int, yday: int<0, 365>, weekday: "Monday"|"Tuesday"|"Wednesday"|"Thursday"|"Friday"|"Saturday"|"Sunday", month: "January"|"February"|"March"|"April"|"May"|"June"|"July"|"August"|"September"|"October"|"November"|"December", 0: int}', 'timestamp='=>'int'], 'getenv' => ['string|false', 'varname'=>'string', 'local_only='=>'bool'], 'getenv\'1' => ['array'], 'gethostbyaddr' => ['string|false', 'ip_address'=>'string'], 'gethostbyname' => ['string', 'hostname'=>'string'], 'gethostbynamel' => ['list|false', 'hostname'=>'string'], 'gethostname' => ['string|false'], 'getimagesize' => ['array{0: 0|positive-int, 1: 0|positive-int, 2: int, 3: string, mime: string, channels?: int, bits?: int}|false', 'imagefile'=>'string', '&w_info='=>'array'], 'getimagesizefromstring' => ['array{0: 0|positive-int, 1: 0|positive-int, 2: int, 3: string, mime: string, channels?: int, bits?: int}|false', 'data'=>'string', '&w_info='=>'array'], 'getlastmod' => ['int|false'], 'getmxrr' => ['bool', 'hostname'=>'string', '&w_mxhosts'=>'array', '&w_weight='=>'array'], 'getmygid' => ['int|false'], 'getmyinode' => ['int|false'], 'getmypid' => ['int|false'], 'getmyuid' => ['int|false'], 'getopt' => ['__benevolent|array|array>|false>', 'options'=>'string', 'longopts='=>'array', '&w_optind='=>'int'], 'getprotobyname' => ['int|false', 'name'=>'string'], 'getprotobynumber' => ['string|false', 'proto'=>'int'], 'getrandmax' => ['int'], 'getrusage' => ['array|false', 'who='=>'int'], 'getservbyname' => ['int|false', 'service'=>'string', 'protocol'=>'string'], 'getservbyport' => ['string|false', 'port'=>'int', 'protocol'=>'string'], 'gettext' => ['string', 'msgid'=>'string'], 'gettimeofday' => ['array|float', 'get_as_float='=>'bool'], 'gettype' => ['string', 'var'=>'mixed'], 'glob' => ['list|false', 'pattern'=>'string', 'flags='=>'int'], 'GlobIterator::__construct' => ['void', 'path'=>'string', 'flags='=>'int'], 'GlobIterator::cont' => ['int'], 'GlobIterator::count' => ['0|positive-int'], 'Gmagick::__construct' => ['void', 'filename='=>'string'], 'Gmagick::addimage' => ['Gmagick', 'gmagick'=>'gmagick'], 'Gmagick::addnoiseimage' => ['Gmagick', 'noise'=>'int'], 'Gmagick::annotateimage' => ['Gmagick', 'gmagickdraw'=>'gmagickdraw', 'x'=>'float', 'y'=>'float', 'angle'=>'float', 'text'=>'string'], 'Gmagick::blurimage' => ['Gmagick', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Gmagick::borderimage' => ['Gmagick', 'color'=>'gmagickpixel', 'width'=>'int', 'height'=>'int'], 'Gmagick::charcoalimage' => ['Gmagick', 'radius'=>'float', 'sigma'=>'float'], 'Gmagick::chopimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Gmagick::clear' => ['Gmagick'], 'Gmagick::commentimage' => ['Gmagick', 'comment'=>'string'], 'Gmagick::compositeimage' => ['Gmagick', 'source'=>'gmagick', 'compose'=>'int', 'x'=>'int', 'y'=>'int'], 'Gmagick::cropimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Gmagick::cropthumbnailimage' => ['Gmagick', 'width'=>'int', 'height'=>'int'], 'Gmagick::current' => ['Gmagick'], 'Gmagick::cyclecolormapimage' => ['Gmagick', 'displace'=>'int'], 'Gmagick::deconstructimages' => ['Gmagick'], 'Gmagick::despeckleimage' => ['Gmagick'], 'Gmagick::destroy' => ['bool'], 'Gmagick::drawimage' => ['Gmagick', 'gmagickdraw'=>'gmagickdraw'], 'Gmagick::edgeimage' => ['Gmagick', 'radius'=>'float'], 'Gmagick::embossimage' => ['Gmagick', 'radius'=>'float', 'sigma'=>'float'], 'Gmagick::enhanceimage' => ['Gmagick'], 'Gmagick::equalizeimage' => ['Gmagick'], 'Gmagick::flipimage' => ['Gmagick'], 'Gmagick::flopimage' => ['Gmagick'], 'Gmagick::frameimage' => ['Gmagick', 'color'=>'gmagickpixel', 'width'=>'int', 'height'=>'int', 'inner_bevel'=>'int', 'outer_bevel'=>'int'], 'Gmagick::gammaimage' => ['Gmagick', 'gamma'=>'float'], 'Gmagick::getcopyright' => ['string'], 'Gmagick::getfilename' => ['string'], 'Gmagick::getimagebackgroundcolor' => ['GmagickPixel'], 'Gmagick::getimageblueprimary' => ['array'], 'Gmagick::getimagebordercolor' => ['GmagickPixel'], 'Gmagick::getimagechanneldepth' => ['int', 'channel_type'=>'int'], 'Gmagick::getimagecolors' => ['int'], 'Gmagick::getimagecolorspace' => ['int'], 'Gmagick::getimagecompose' => ['int'], 'Gmagick::getimagedelay' => ['int'], 'Gmagick::getimagedepth' => ['int'], 'Gmagick::getimagedispose' => ['int'], 'Gmagick::getimageextrema' => ['array'], 'Gmagick::getimagefilename' => ['string'], 'Gmagick::getimageformat' => ['string'], 'Gmagick::getimagegamma' => ['float'], 'Gmagick::getimagegreenprimary' => ['array'], 'Gmagick::getimageheight' => ['int'], 'Gmagick::getimagehistogram' => ['array'], 'Gmagick::getimageindex' => ['int'], 'Gmagick::getimageinterlacescheme' => ['int'], 'Gmagick::getimageiterations' => ['int'], 'Gmagick::getimagematte' => ['int'], 'Gmagick::getimagemattecolor' => ['GmagickPixel'], 'Gmagick::getimageprofile' => ['string', 'name'=>'string'], 'Gmagick::getimageredprimary' => ['array'], 'Gmagick::getimagerenderingintent' => ['int'], 'Gmagick::getimageresolution' => ['array'], 'Gmagick::getimagescene' => ['int'], 'Gmagick::getimagesignature' => ['string'], 'Gmagick::getimagetype' => ['int'], 'Gmagick::getimageunits' => ['int'], 'Gmagick::getimagewhitepoint' => ['array'], 'Gmagick::getimagewidth' => ['int'], 'Gmagick::getpackagename' => ['string'], 'Gmagick::getquantumdepth' => ['array'], 'Gmagick::getreleasedate' => ['string'], 'Gmagick::getsamplingfactors' => ['array'], 'Gmagick::getsize' => ['array'], 'Gmagick::getversion' => ['array'], 'Gmagick::hasnextimage' => ['bool'], 'Gmagick::haspreviousimage' => ['bool'], 'Gmagick::implodeimage' => ['mixed', 'radius'=>'float'], 'Gmagick::labelimage' => ['mixed', 'label'=>'string'], 'Gmagick::levelimage' => ['mixed', 'blackpoint'=>'float', 'gamma'=>'float', 'whitepoint'=>'float', 'channel='=>'int'], 'Gmagick::magnifyimage' => ['mixed'], 'Gmagick::mapimage' => ['Gmagick', 'gmagick'=>'gmagick', 'dither'=>'bool'], 'Gmagick::medianfilterimage' => ['void', 'radius'=>'float'], 'Gmagick::minifyimage' => ['Gmagick'], 'Gmagick::modulateimage' => ['Gmagick', 'brightness'=>'float', 'saturation'=>'float', 'hue'=>'float'], 'Gmagick::motionblurimage' => ['Gmagick', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float'], 'Gmagick::newimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'background'=>'string', 'format='=>'string'], 'Gmagick::nextimage' => ['bool'], 'Gmagick::normalizeimage' => ['Gmagick', 'channel='=>'int'], 'Gmagick::oilpaintimage' => ['Gmagick', 'radius'=>'float'], 'Gmagick::previousimage' => ['bool'], 'Gmagick::profileimage' => ['Gmagick', 'name'=>'string', 'profile'=>'string'], 'Gmagick::quantizeimage' => ['Gmagick', 'numcolors'=>'int', 'colorspace'=>'int', 'treedepth'=>'int', 'dither'=>'bool', 'measureerror'=>'bool'], 'Gmagick::quantizeimages' => ['Gmagick', 'numcolors'=>'int', 'colorspace'=>'int', 'treedepth'=>'int', 'dither'=>'bool', 'measureerror'=>'bool'], 'Gmagick::queryfontmetrics' => ['array', 'draw'=>'gmagickdraw', 'text'=>'string'], 'Gmagick::queryfonts' => ['array', 'pattern='=>'string'], 'Gmagick::queryformats' => ['array', 'pattern='=>'string'], 'Gmagick::radialblurimage' => ['Gmagick', 'angle'=>'float', 'channel='=>'int'], 'Gmagick::raiseimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int', 'raise'=>'bool'], 'Gmagick::read' => ['Gmagick', 'filename'=>'string'], 'Gmagick::readimage' => ['Gmagick', 'filename'=>'string'], 'Gmagick::readimageblob' => ['Gmagick', 'imagecontents'=>'string', 'filename='=>'string'], 'Gmagick::readimagefile' => ['Gmagick', 'fp'=>'resource', 'filename='=>'string'], 'Gmagick::reducenoiseimage' => ['Gmagick', 'radius'=>'float'], 'Gmagick::removeimage' => ['Gmagick'], 'Gmagick::removeimageprofile' => ['string', 'name'=>'string'], 'Gmagick::resampleimage' => ['Gmagick', 'xresolution'=>'float', 'yresolution'=>'float', 'filter'=>'int', 'blur'=>'float'], 'Gmagick::resizeimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'filter'=>'int', 'blur'=>'float', 'fit='=>'bool'], 'Gmagick::rollimage' => ['Gmagick', 'x'=>'int', 'y'=>'int'], 'Gmagick::rotateimage' => ['Gmagick', 'color'=>'mixed', 'degrees'=>'float'], 'Gmagick::scaleimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'fit='=>'bool'], 'Gmagick::separateimagechannel' => ['Gmagick', 'channel'=>'int'], 'Gmagick::setCompressionQuality' => ['Gmagick', 'quality'=>'int'], 'Gmagick::setfilename' => ['Gmagick', 'filename'=>'string'], 'Gmagick::setimagebackgroundcolor' => ['Gmagick', 'color'=>'gmagickpixel'], 'Gmagick::setimageblueprimary' => ['Gmagick', 'x'=>'float', 'y'=>'float'], 'Gmagick::setimagebordercolor' => ['Gmagick', 'color'=>'gmagickpixel'], 'Gmagick::setimagechanneldepth' => ['Gmagick', 'channel'=>'int', 'depth'=>'int'], 'Gmagick::setimagecolorspace' => ['Gmagick', 'colorspace'=>'int'], 'Gmagick::setimagecompose' => ['Gmagick', 'composite'=>'int'], 'Gmagick::setimagedelay' => ['Gmagick', 'delay'=>'int'], 'Gmagick::setimagedepth' => ['Gmagick', 'depth'=>'int'], 'Gmagick::setimagedispose' => ['Gmagick', 'disposetype'=>'int'], 'Gmagick::setimagefilename' => ['Gmagick', 'filename'=>'string'], 'Gmagick::setimageformat' => ['Gmagick', 'imageformat'=>'string'], 'Gmagick::setimagegamma' => ['Gmagick', 'gamma'=>'float'], 'Gmagick::setimagegreenprimary' => ['Gmagick', 'x'=>'float', 'y'=>'float'], 'Gmagick::setimageindex' => ['Gmagick', 'index'=>'int'], 'Gmagick::setimageinterlacescheme' => ['Gmagick', 'interlace'=>'int'], 'Gmagick::setimageiterations' => ['Gmagick', 'iterations'=>'int'], 'Gmagick::setimageprofile' => ['Gmagick', 'name'=>'string', 'profile'=>'string'], 'Gmagick::setimageredprimary' => ['Gmagick', 'x'=>'float', 'y'=>'float'], 'Gmagick::setimagerenderingintent' => ['Gmagick', 'rendering_intent'=>'int'], 'Gmagick::setimageresolution' => ['Gmagick', 'xresolution'=>'float', 'yresolution'=>'float'], 'Gmagick::setimagescene' => ['Gmagick', 'scene'=>'int'], 'Gmagick::setimagetype' => ['Gmagick', 'imgtype'=>'int'], 'Gmagick::setimageunits' => ['Gmagick', 'resolution'=>'int'], 'Gmagick::setimagewhitepoint' => ['Gmagick', 'x'=>'float', 'y'=>'float'], 'Gmagick::setsamplingfactors' => ['Gmagick', 'factors'=>'array'], 'Gmagick::setsize' => ['Gmagick', 'columns'=>'int', 'rows'=>'int'], 'Gmagick::shearimage' => ['Gmagick', 'color'=>'mixed', 'xshear'=>'float', 'yshear'=>'float'], 'Gmagick::solarizeimage' => ['Gmagick', 'threshold'=>'int'], 'Gmagick::spreadimage' => ['Gmagick', 'radius'=>'float'], 'Gmagick::stripimage' => ['Gmagick'], 'Gmagick::swirlimage' => ['Gmagick', 'degrees'=>'float'], 'Gmagick::thumbnailimage' => ['Gmagick', 'width'=>'int', 'height'=>'int', 'fit='=>'bool'], 'Gmagick::trimimage' => ['Gmagick', 'fuzz'=>'float'], 'Gmagick::write' => ['', 'filename'=>'string'], 'Gmagick::writeimage' => ['Gmagick', 'filename'=>'string', 'all_frames='=>'bool'], 'GmagickDraw::annotate' => ['GmagickDraw', 'x'=>'float', 'y'=>'float', 'text'=>'string'], 'GmagickDraw::arc' => ['GmagickDraw', 'sx'=>'float', 'sy'=>'float', 'ex'=>'float', 'ey'=>'float', 'sd'=>'float', 'ed'=>'float'], 'GmagickDraw::bezier' => ['GmagickDraw', 'coordinate_array'=>'array'], 'GmagickDraw::ellipse' => ['GmagickDraw', 'ox'=>'float', 'oy'=>'float', 'rx'=>'float', 'ry'=>'float', 'start'=>'float', 'end'=>'float'], 'GmagickDraw::getfillcolor' => ['GmagickPixel'], 'GmagickDraw::getfillopacity' => ['float'], 'GmagickDraw::getfont' => ['string'], 'GmagickDraw::getfontsize' => ['float'], 'GmagickDraw::getfontstyle' => ['int'], 'GmagickDraw::getfontweight' => ['int'], 'GmagickDraw::getstrokecolor' => ['GmagickPixel'], 'GmagickDraw::getstrokeopacity' => ['float'], 'GmagickDraw::getstrokewidth' => ['float'], 'GmagickDraw::gettextdecoration' => ['int'], 'GmagickDraw::gettextencoding' => ['string'], 'GmagickDraw::line' => ['GmagickDraw', 'sx'=>'float', 'sy'=>'float', 'ex'=>'float', 'ey'=>'float'], 'GmagickDraw::point' => ['GmagickDraw', 'x'=>'float', 'y'=>'float'], 'GmagickDraw::polygon' => ['GmagickDraw', 'coordinates'=>'array'], 'GmagickDraw::polyline' => ['GmagickDraw', 'coordinate_array'=>'array'], 'GmagickDraw::rectangle' => ['GmagickDraw', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float'], 'GmagickDraw::rotate' => ['GmagickDraw', 'degrees'=>'float'], 'GmagickDraw::roundrectangle' => ['GmagickDraw', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'rx'=>'float', 'ry'=>'float'], 'GmagickDraw::scale' => ['GmagickDraw', 'x'=>'float', 'y'=>'float'], 'GmagickDraw::setfillcolor' => ['GmagickDraw', 'color'=>'string'], 'GmagickDraw::setfillopacity' => ['GmagickDraw', 'fill_opacity'=>'float'], 'GmagickDraw::setfont' => ['GmagickDraw', 'font'=>'string'], 'GmagickDraw::setfontsize' => ['GmagickDraw', 'pointsize'=>'float'], 'GmagickDraw::setfontstyle' => ['GmagickDraw', 'style'=>'int'], 'GmagickDraw::setfontweight' => ['GmagickDraw', 'weight'=>'int'], 'GmagickDraw::setstrokecolor' => ['GmagickDraw', 'color'=>'gmagickpixel'], 'GmagickDraw::setstrokeopacity' => ['GmagickDraw', 'stroke_opacity'=>'float'], 'GmagickDraw::setstrokewidth' => ['GmagickDraw', 'width'=>'float'], 'GmagickDraw::settextdecoration' => ['GmagickDraw', 'decoration'=>'int'], 'GmagickDraw::settextencoding' => ['GmagickDraw', 'encoding'=>'string'], 'GmagickPixel::__construct' => ['void', 'color='=>'string'], 'GmagickPixel::getcolor' => ['mixed', 'as_array='=>'bool', 'normalize_array='=>'bool'], 'GmagickPixel::getcolorcount' => ['int'], 'GmagickPixel::getcolorvalue' => ['float', 'color'=>'int'], 'GmagickPixel::setcolor' => ['GmagickPixel', 'color'=>'string'], 'GmagickPixel::setcolorvalue' => ['GmagickPixel', 'color'=>'int', 'value'=>'float'], 'gmdate' => ['string', 'format'=>'string', 'timestamp='=>'int'], 'gmmktime' => ['int|false', 'hour='=>'int', 'min='=>'int', 'sec='=>'int', 'mon='=>'int', 'day='=>'int', 'year='=>'int'], 'GMP::__construct' => ['void'], 'GMP::__toString' => ['string'], 'GMP::serialize' => ['string'], 'GMP::unserialize' => ['void', 'serialized'=>'string'], 'gmp_abs' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_add' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_and' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_binomial' => ['GMP|false', 'n'=>'GMP|string|int', 'k'=>'int'], 'gmp_clrbit' => ['void', 'a'=>'GMP|string|int', 'index'=>'int'], 'gmp_cmp' => ['int', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_com' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_div' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int', 'round='=>'int'], 'gmp_div_q' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int', 'round='=>'int'], 'gmp_div_qr' => ['array', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int', 'round='=>'int'], 'gmp_div_r' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int', 'round='=>'int'], 'gmp_divexact' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_export' => ['string', 'gmpnumber'=>'GMP|string|int', 'word_size='=>'int', 'options='=>'int'], 'gmp_fact' => ['GMP', 'a'=>'int'], 'gmp_gcd' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_gcdext' => ['array', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_hamdist' => ['int', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_import' => ['GMP', 'data'=>'string', 'word_size='=>'int', 'options='=>'int'], 'gmp_init' => ['GMP', 'number'=>'int|string', 'base='=>'int'], 'gmp_intval' => ['int', 'gmpnumber'=>'GMP|string|int'], 'gmp_invert' => ['GMP|false', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_jacobi' => ['int', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_kronecker' => ['int', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_lcm' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_legendre' => ['int', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_mod' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_mul' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_neg' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_nextprime' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_or' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_perfect_power' => ['bool', 'a'=>'GMP|string|int'], 'gmp_perfect_square' => ['bool', 'a'=>'GMP|string|int'], 'gmp_popcount' => ['int', 'a'=>'GMP|string|int'], 'gmp_pow' => ['GMP', 'base'=>'GMP|string|int', 'exp'=>'int'], 'gmp_powm' => ['GMP', 'base'=>'GMP|string|int', 'exp'=>'GMP|string|int', 'mod'=>'GMP|string|int'], 'gmp_prob_prime' => ['int', 'a'=>'GMP|string|int', 'reps='=>'int'], 'gmp_random' => ['GMP', 'limiter='=>'int'], 'gmp_random_bits' => ['GMP', 'bits'=>'int'], 'gmp_random_range' => ['GMP', 'min'=>'GMP|string|int', 'max'=>'GMP|string|int'], 'gmp_random_seed' => ['void', 'seed'=>'GMP|string|int'], 'gmp_root' => ['GMP', 'a'=>'GMP|string|int', 'nth'=>'int'], 'gmp_rootrem' => ['array', 'a'=>'GMP|string|int', 'nth'=>'int'], 'gmp_scan0' => ['int', 'a'=>'GMP|string|int', 'start'=>'int'], 'gmp_scan1' => ['int', 'a'=>'GMP|string|int', 'start'=>'int'], 'gmp_setbit' => ['void', 'a'=>'GMP|string|int', 'index'=>'int', 'set_clear='=>'bool'], 'gmp_sign' => ['int', 'a'=>'GMP|string|int'], 'gmp_sqrt' => ['GMP', 'a'=>'GMP|string|int'], 'gmp_sqrtrem' => ['array', 'a'=>'GMP|string|int'], 'gmp_strval' => ['string', 'gmpnumber'=>'GMP|string|int', 'base='=>'int'], 'gmp_sub' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmp_testbit' => ['bool', 'a'=>'GMP|string|int', 'index'=>'int'], 'gmp_xor' => ['GMP', 'a'=>'GMP|string|int', 'b'=>'GMP|string|int'], 'gmstrftime' => ['string|false', 'format'=>'string', 'timestamp='=>'int'], 'gnupg::adddecryptkey' => ['bool', 'fingerprint'=>'string', 'passphrase'=>'string'], 'gnupg::addencryptkey' => ['bool', 'fingerprint'=>'string'], 'gnupg::addsignkey' => ['bool', 'fingerprint'=>'string', 'passphrase='=>'string'], 'gnupg::cleardecryptkeys' => ['bool'], 'gnupg::clearencryptkeys' => ['bool'], 'gnupg::clearsignkeys' => ['bool'], 'gnupg::decrypt' => ['string|false', 'text'=>'string'], 'gnupg::deletekey' => ['bool', 'key'=>'string', 'allow_secret'=>'bool'], 'gnupg::decryptverify' => ['array|false', 'text'=>'string', '&plaintext'=>'string'], 'gnupg::encrypt' => ['string|false', 'plaintext'=>'string'], 'gnupg::encryptsign' => ['string|false', 'plaintext'=>'string'], 'gnupg::export' => ['string|false', 'fingerprint'=>'string'], 'gnupg::getengineinfo' => ['array'], 'gnupg::geterror' => ['string|false'], 'gnupg::getprotocol' => ['int'], 'gnupg::gettrustlist' => ['array', 'pattern'=>'string'], 'gnupg::import' => ['array|false', 'keydata'=>'string'], 'gnupg::init' => ['resource', 'options'=>'?array{file_name?:string,home_dir?:string}'], 'gnupg::keyinfo' => ['array|false', 'pattern'=>'string'], 'gnupg::listsignatures' => ['?array', 'keyid'=>'string'], 'gnupg::setarmor' => ['bool', 'armor'=>'int'], 'gnupg::seterrormode' => ['void', 'errormode'=>'int'], 'gnupg::setsignmode' => ['bool', 'signmode'=>'int'], 'gnupg::sign' => ['string|false', 'plaintext'=>'string'], 'gnupg::verify' => ['array|false', 'signed_text'=>'string', 'signature'=>'string|false', '&plaintext='=>'string'], 'gnupg_adddecryptkey' => ['bool', 'identifier'=>'resource', 'fingerprint'=>'string', 'passphrase'=>'string'], 'gnupg_addencryptkey' => ['bool', 'identifier'=>'resource', 'fingerprint'=>'string'], 'gnupg_addsignkey' => ['bool', 'identifier'=>'resource', 'fingerprint'=>'string', 'passphrase='=>'string'], 'gnupg_cleardecryptkeys' => ['bool', 'identifier'=>'resource'], 'gnupg_clearencryptkeys' => ['bool', 'identifier'=>'resource'], 'gnupg_clearsignkeys' => ['bool', 'identifier'=>'resource'], 'gnupg_decrypt' => ['string|false', 'identifier'=>'resource', 'text'=>'string'], 'gnupg_decryptverify' => ['array', 'identifier'=>'resource', 'text'=>'string', 'plaintext'=>'string'], 'gnupg_deletekey' => ['bool', 'identifier'=>'resource', 'key'=>'string', 'allow_secret'=>'bool'], 'gnupg_encrypt' => ['string|false', 'identifier'=>'resource', 'plaintext'=>'string'], 'gnupg_encryptsign' => ['string|false', 'identifier'=>'resource', 'plaintext'=>'string'], 'gnupg_export' => ['string|false', 'identifier'=>'resource', 'fingerprint'=>'string'], 'gnupg_getengineinfo' => ['array', 'identifier'=>'resource'], 'gnupg_geterror' => ['string|false', 'identifier'=>'resource'], 'gnupg_getprotocol' => ['int', 'identifier'=>'resource'], 'gnupg_gettrustlist' => ['array', 'identifier'=>'resource', 'pattern'=>'string'], 'gnupg_import' => ['array|false', 'identifier'=>'resource', 'keydata'=>'string'], 'gnupg_init' => ['resource', 'options='=>'?array{file_name?:string,home_dir?:string}'], 'gnupg_keyinfo' => ['array|false', 'identifier'=>'resource', 'pattern'=>'string'], 'gnupg_listsignatures' => ['?array', 'identifier'=>'resource', 'keyid'=>'string'], 'gnupg_setarmor' => ['bool', 'identifier'=>'resource', 'armor'=>'int'], 'gnupg_seterrormode' => ['void', 'identifier'=>'resource', 'errormode'=>'int'], 'gnupg_setsignmode' => ['bool', 'identifier'=>'resource', 'signmode'=>'int'], 'gnupg_sign' => ['string|false', 'identifier'=>'resource', 'plaintext'=>'string'], 'gnupg_verify' => ['array|false', 'identifier'=>'resource', 'signed_text'=>'string', 'signature'=>'string|false', '&plaintext='=>'string'], 'gopher_parsedir' => ['array', 'dirent'=>'string'], 'grapheme_extract' => ['string|false', 'str'=>'string', 'size'=>'int', 'extract_type='=>'int', 'start='=>'int', '&w_next='=>'int'], 'grapheme_stripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'grapheme_stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool'], 'grapheme_strlen' => ['0|positive-int|false', 'str'=>'string'], 'grapheme_strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'grapheme_strripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'grapheme_strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'grapheme_strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool'], 'grapheme_substr' => ['string|false', 'str'=>'string', 'start'=>'int', 'length='=>'int'], 'gregoriantojd' => ['int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'gridObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'Grpc\Call::__construct' => ['void', 'channel'=>'Grpc\Channel', 'method'=>'string', 'absolute_deadline'=>'Grpc\Timeval', 'host_override='=>'mixed'], 'Grpc\Call::cancel' => [''], 'Grpc\Call::getPeer' => ['string'], 'Grpc\Call::setCredentials' => ['int', 'creds_obj'=>'Grpc\CallCredentials'], 'Grpc\Call::startBatch' => ['object', 'batch'=>'array'], 'Grpc\CallCredentials::createComposite' => ['Grpc\CallCredentials', 'cred1'=>'Grpc\CallCredentials', 'cred2'=>'Grpc\CallCredentials'], 'Grpc\CallCredentials::createFromPlugin' => ['Grpc\CallCredentials', 'callback'=>'Closure'], 'Grpc\Channel::__construct' => ['void', 'target'=>'string', 'args='=>'array'], 'Grpc\Channel::close' => [''], 'Grpc\Channel::getConnectivityState' => ['int', 'try_to_connect='=>'bool|false'], 'Grpc\Channel::getTarget' => ['string'], 'Grpc\Channel::watchConnectivityState' => ['bool', 'last_state'=>'int', 'deadline_obj'=>'Grpc\Timeval'], 'Grpc\ChannelCredentials::createComposite' => ['Grpc\ChannelCredentials', 'cred1'=>'Grpc\ChannelCredentials', 'cred2'=>'Grpc\CallCredentials'], 'Grpc\ChannelCredentials::createDefault' => ['Grpc\ChannelCredentials'], 'Grpc\ChannelCredentials::createInsecure' => ['null'], 'Grpc\ChannelCredentials::createSsl' => ['Grpc\ChannelCredentials', 'pem_root_certs='=>'string|null', 'pem_private_key='=>'string|null', 'pem_cert_chain='=>'string|null'], 'Grpc\ChannelCredentials::setDefaultRootsPem' => ['', 'pem_roots'=>'string'], 'Grpc\Server::__construct' => ['void', 'args'=>'array'], 'Grpc\Server::addHttp2Port' => ['bool', 'addr'=>'string'], 'Grpc\Server::addSecureHttp2Port' => ['bool', 'addr'=>'string', 'creds_obj'=>'Grpc\ServerCredentials'], 'Grpc\Server::requestCall' => ['', 'tag_new'=>'int', 'tag_cancel'=>'int'], 'Grpc\Server::start' => [''], 'Grpc\ServerCredentials::createSsl' => ['object', 'pem_root_certs'=>'string', 'pem_private_key'=>'string', 'pem_cert_chain'=>'string'], 'Grpc\Timeval::__construct' => ['void', 'usec'=>'int'], 'Grpc\Timeval::add' => ['Grpc\Timeval', 'other'=>'Grpc\Timeval'], 'Grpc\Timeval::compare' => ['int', 'a'=>'Grpc\Timeval', 'b'=>'Grpc\Timeval'], 'Grpc\Timeval::infFuture' => ['Grpc\Timeval'], 'Grpc\Timeval::infPast' => ['Grpc\Timeval'], 'Grpc\Timeval::now' => ['Grpc\Timeval'], 'Grpc\Timeval::similar' => ['bool', 'a'=>'Grpc\Timeval', 'b'=>'Grpc\Timeval', 'threshold'=>'Grpc\Timeval'], 'Grpc\Timeval::sleepUntil' => [''], 'Grpc\Timeval::subtract' => ['Grpc\Timeval', 'other'=>'Grpc\Timeval'], 'Grpc\Timeval::zero' => ['Grpc\Timeval'], 'gupnp_context_get_host_ip' => ['string', 'context'=>'resource'], 'gupnp_context_get_port' => ['int', 'context'=>'resource'], 'gupnp_context_get_subscription_timeout' => ['int', 'context'=>'resource'], 'gupnp_context_host_path' => ['bool', 'context'=>'resource', 'local_path'=>'string', 'server_path'=>'string'], 'gupnp_context_new' => ['resource', 'host_ip='=>'string', 'port='=>'int'], 'gupnp_context_set_subscription_timeout' => ['void', 'context'=>'resource', 'timeout'=>'int'], 'gupnp_context_timeout_add' => ['bool', 'context'=>'resource', 'timeout'=>'int', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_context_unhost_path' => ['bool', 'context'=>'resource', 'server_path'=>'string'], 'gupnp_control_point_browse_start' => ['bool', 'cpoint'=>'resource'], 'gupnp_control_point_browse_stop' => ['bool', 'cpoint'=>'resource'], 'gupnp_control_point_callback_set' => ['bool', 'cpoint'=>'resource', 'signal'=>'int', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_control_point_new' => ['resource', 'context'=>'resource', 'target'=>'string'], 'gupnp_device_action_callback_set' => ['bool', 'root_device'=>'resource', 'signal'=>'int', 'action_name'=>'string', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_device_info_get' => ['array', 'root_device'=>'resource'], 'gupnp_device_info_get_service' => ['resource', 'root_device'=>'resource', 'type'=>'string'], 'gupnp_root_device_get_available' => ['bool', 'root_device'=>'resource'], 'gupnp_root_device_get_relative_location' => ['string', 'root_device'=>'resource'], 'gupnp_root_device_new' => ['resource', 'context'=>'resource', 'location'=>'string', 'description_dir'=>'string'], 'gupnp_root_device_set_available' => ['bool', 'root_device'=>'resource', 'available'=>'bool'], 'gupnp_root_device_start' => ['bool', 'root_device'=>'resource'], 'gupnp_root_device_stop' => ['bool', 'root_device'=>'resource'], 'gupnp_service_action_get' => ['mixed', 'action'=>'resource', 'name'=>'string', 'type'=>'int'], 'gupnp_service_action_return' => ['bool', 'action'=>'resource'], 'gupnp_service_action_return_error' => ['bool', 'action'=>'resource', 'error_code'=>'int', 'error_description='=>'string'], 'gupnp_service_action_set' => ['bool', 'action'=>'resource', 'name'=>'string', 'type'=>'int', 'value'=>'mixed'], 'gupnp_service_freeze_notify' => ['bool', 'service'=>'resource'], 'gupnp_service_info_get' => ['array', 'proxy'=>'resource'], 'gupnp_service_info_get_introspection' => ['mixed', 'proxy'=>'resource', 'callback='=>'mixed', 'arg='=>'mixed'], 'gupnp_service_introspection_get_state_variable' => ['array', 'introspection'=>'resource', 'variable_name'=>'string'], 'gupnp_service_notify' => ['bool', 'service'=>'resource', 'name'=>'string', 'type'=>'int', 'value'=>'mixed'], 'gupnp_service_proxy_action_get' => ['mixed', 'proxy'=>'resource', 'action'=>'string', 'name'=>'string', 'type'=>'int'], 'gupnp_service_proxy_action_set' => ['bool', 'proxy'=>'resource', 'action'=>'string', 'name'=>'string', 'value'=>'mixed', 'type'=>'int'], 'gupnp_service_proxy_add_notify' => ['bool', 'proxy'=>'resource', 'value'=>'string', 'type'=>'int', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_service_proxy_callback_set' => ['bool', 'proxy'=>'resource', 'signal'=>'int', 'callback'=>'mixed', 'arg='=>'mixed'], 'gupnp_service_proxy_get_subscribed' => ['bool', 'proxy'=>'resource'], 'gupnp_service_proxy_remove_notify' => ['bool', 'proxy'=>'resource', 'value'=>'string'], 'gupnp_service_proxy_send_action' => ['array', 'proxy'=>'resource', 'action'=>'string', 'in_params'=>'array', 'out_params'=>'array'], 'gupnp_service_proxy_set_subscribed' => ['bool', 'proxy'=>'resource', 'subscribed'=>'bool'], 'gupnp_service_thaw_notify' => ['bool', 'service'=>'resource'], 'gzclose' => ['bool', 'zp'=>'resource'], 'gzcompress' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'], 'gzdecode' => ['string|false', 'data'=>'string', 'length='=>'int'], 'gzdeflate' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'], 'gzencode' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding_mode='=>'int'], 'gzeof' => ['bool', 'zp'=>'resource'], 'gzfile' => ['list|false', 'filename'=>'string', 'use_include_path='=>'int'], 'gzgetc' => ['string|false', 'zp'=>'resource'], 'gzgets' => ['string|false', 'zp'=>'resource', 'length='=>'int'], 'gzgetss' => ['string|false', 'zp'=>'resource', 'length'=>'int', 'allowable_tags='=>'string'], 'gzinflate' => ['string|false', 'data'=>'string', 'length='=>'int'], 'gzopen' => ['resource|false', 'filename'=>'string', 'mode'=>'string', 'use_include_path='=>'int'], 'gzpassthru' => ['int|false', 'zp'=>'resource'], 'gzputs' => ['int|false', 'zp'=>'resource', 'string'=>'string', 'length='=>'int'], 'gzread' => ['string|false', 'zp'=>'resource', 'length'=>'int'], 'gzrewind' => ['bool', 'zp'=>'resource'], 'gzseek' => ['int', 'zp'=>'resource', 'offset'=>'int', 'whence='=>'int'], 'gztell' => ['int|false', 'zp'=>'resource'], 'gzuncompress' => ['string|false', 'data'=>'string', 'length='=>'int'], 'gzwrite' => ['int|false', 'zp'=>'resource', 'string'=>'string', 'length='=>'int'], 'HaruAnnotation::setBorderStyle' => ['bool', 'width'=>'float', 'dash_on'=>'int', 'dash_off'=>'int'], 'HaruAnnotation::setHighlightMode' => ['bool', 'mode'=>'int'], 'HaruAnnotation::setIcon' => ['bool', 'icon'=>'int'], 'HaruAnnotation::setOpened' => ['bool', 'opened'=>'bool'], 'HaruDestination::setFit' => ['bool'], 'HaruDestination::setFitB' => ['bool'], 'HaruDestination::setFitBH' => ['bool', 'top'=>'float'], 'HaruDestination::setFitBV' => ['bool', 'left'=>'float'], 'HaruDestination::setFitH' => ['bool', 'top'=>'float'], 'HaruDestination::setFitR' => ['bool', 'left'=>'float', 'bottom'=>'float', 'right'=>'float', 'top'=>'float'], 'HaruDestination::setFitV' => ['bool', 'left'=>'float'], 'HaruDestination::setXYZ' => ['bool', 'left'=>'float', 'top'=>'float', 'zoom'=>'float'], 'HaruDoc::__construct' => ['void'], 'HaruDoc::addPage' => ['object'], 'HaruDoc::addPageLabel' => ['bool', 'first_page'=>'int', 'style'=>'int', 'first_num'=>'int', 'prefix='=>'string'], 'HaruDoc::createOutline' => ['object', 'title'=>'string', 'parent_outline='=>'object', 'encoder='=>'object'], 'HaruDoc::getCurrentEncoder' => ['object'], 'HaruDoc::getCurrentPage' => ['object'], 'HaruDoc::getEncoder' => ['object', 'encoding'=>'string'], 'HaruDoc::getFont' => ['object', 'fontname'=>'string', 'encoding='=>'string'], 'HaruDoc::getInfoAttr' => ['string', 'type'=>'int'], 'HaruDoc::getPageLayout' => ['int'], 'HaruDoc::getPageMode' => ['int'], 'HaruDoc::getStreamSize' => ['int'], 'HaruDoc::insertPage' => ['object', 'page'=>'object'], 'HaruDoc::loadJPEG' => ['object', 'filename'=>'string'], 'HaruDoc::loadPNG' => ['object', 'filename'=>'string', 'deferred='=>'bool'], 'HaruDoc::loadRaw' => ['object', 'filename'=>'string', 'width'=>'int', 'height'=>'int', 'color_space'=>'int'], 'HaruDoc::loadTTC' => ['string', 'fontfile'=>'string', 'index'=>'int', 'embed='=>'bool'], 'HaruDoc::loadTTF' => ['string', 'fontfile'=>'string', 'embed='=>'bool'], 'HaruDoc::loadType1' => ['string', 'afmfile'=>'string', 'pfmfile='=>'string'], 'HaruDoc::output' => ['bool'], 'HaruDoc::readFromStream' => ['string', 'bytes'=>'int'], 'HaruDoc::resetError' => ['bool'], 'HaruDoc::resetStream' => ['bool'], 'HaruDoc::save' => ['bool', 'file'=>'string'], 'HaruDoc::saveToStream' => ['bool'], 'HaruDoc::setCompressionMode' => ['bool', 'mode'=>'int'], 'HaruDoc::setCurrentEncoder' => ['bool', 'encoding'=>'string'], 'HaruDoc::setEncryptionMode' => ['bool', 'mode'=>'int', 'key_len='=>'int'], 'HaruDoc::setInfoAttr' => ['bool', 'type'=>'int', 'info'=>'string'], 'HaruDoc::setInfoDateAttr' => ['bool', 'type'=>'int', 'year'=>'int', 'month'=>'int', 'day'=>'int', 'hour'=>'int', 'min'=>'int', 'sec'=>'int', 'ind'=>'string', 'off_hour'=>'int', 'off_min'=>'int'], 'HaruDoc::setOpenAction' => ['bool', 'destination'=>'object'], 'HaruDoc::setPageLayout' => ['bool', 'layout'=>'int'], 'HaruDoc::setPageMode' => ['bool', 'mode'=>'int'], 'HaruDoc::setPagesConfiguration' => ['bool', 'page_per_pages'=>'int'], 'HaruDoc::setPassword' => ['bool', 'owner_password'=>'string', 'user_password'=>'string'], 'HaruDoc::setPermission' => ['bool', 'permission'=>'int'], 'HaruDoc::useCNSEncodings' => ['bool'], 'HaruDoc::useCNSFonts' => ['bool'], 'HaruDoc::useCNTEncodings' => ['bool'], 'HaruDoc::useCNTFonts' => ['bool'], 'HaruDoc::useJPEncodings' => ['bool'], 'HaruDoc::useJPFonts' => ['bool'], 'HaruDoc::useKREncodings' => ['bool'], 'HaruDoc::useKRFonts' => ['bool'], 'HaruEncoder::getByteType' => ['int', 'text'=>'string', 'index'=>'int'], 'HaruEncoder::getType' => ['int'], 'HaruEncoder::getUnicode' => ['int', 'character'=>'int'], 'HaruEncoder::getWritingMode' => ['int'], 'HaruFont::getAscent' => ['int'], 'HaruFont::getCapHeight' => ['int'], 'HaruFont::getDescent' => ['int'], 'HaruFont::getEncodingName' => ['string'], 'HaruFont::getFontName' => ['string'], 'HaruFont::getTextWidth' => ['array', 'text'=>'string'], 'HaruFont::getUnicodeWidth' => ['int', 'character'=>'int'], 'HaruFont::getXHeight' => ['int'], 'HaruFont::measureText' => ['int', 'text'=>'string', 'width'=>'float', 'font_size'=>'float', 'char_space'=>'float', 'word_space'=>'float', 'word_wrap='=>'bool'], 'HaruImage::getBitsPerComponent' => ['int'], 'HaruImage::getColorSpace' => ['string'], 'HaruImage::getHeight' => ['int'], 'HaruImage::getSize' => ['array'], 'HaruImage::getWidth' => ['int'], 'HaruImage::setColorMask' => ['bool', 'rmin'=>'int', 'rmax'=>'int', 'gmin'=>'int', 'gmax'=>'int', 'bmin'=>'int', 'bmax'=>'int'], 'HaruImage::setMaskImage' => ['bool', 'mask_image'=>'object'], 'HaruOutline::setDestination' => ['bool', 'destination'=>'object'], 'HaruOutline::setOpened' => ['bool', 'opened'=>'bool'], 'HaruPage::arc' => ['bool', 'x'=>'float', 'y'=>'float', 'ray'=>'float', 'ang1'=>'float', 'ang2'=>'float'], 'HaruPage::beginText' => ['bool'], 'HaruPage::circle' => ['bool', 'x'=>'float', 'y'=>'float', 'ray'=>'float'], 'HaruPage::closePath' => ['bool'], 'HaruPage::concat' => ['bool', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'x'=>'float', 'y'=>'float'], 'HaruPage::createDestination' => ['object'], 'HaruPage::createLinkAnnotation' => ['object', 'rectangle'=>'array', 'destination'=>'object'], 'HaruPage::createTextAnnotation' => ['object', 'rectangle'=>'array', 'text'=>'string', 'encoder='=>'object'], 'HaruPage::createURLAnnotation' => ['object', 'rectangle'=>'array', 'url'=>'string'], 'HaruPage::curveTo' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'HaruPage::curveTo2' => ['bool', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'HaruPage::curveTo3' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x3'=>'float', 'y3'=>'float'], 'HaruPage::drawImage' => ['bool', 'image'=>'object', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'HaruPage::ellipse' => ['bool', 'x'=>'float', 'y'=>'float', 'xray'=>'float', 'yray'=>'float'], 'HaruPage::endPath' => ['bool'], 'HaruPage::endText' => ['bool'], 'HaruPage::eofill' => ['bool'], 'HaruPage::eoFillStroke' => ['bool', 'close_path='=>'bool'], 'HaruPage::fill' => ['bool'], 'HaruPage::fillStroke' => ['bool', 'close_path='=>'bool'], 'HaruPage::getCharSpace' => ['float'], 'HaruPage::getCMYKFill' => ['array'], 'HaruPage::getCMYKStroke' => ['array'], 'HaruPage::getCurrentFont' => ['object'], 'HaruPage::getCurrentFontSize' => ['float'], 'HaruPage::getCurrentPos' => ['array'], 'HaruPage::getCurrentTextPos' => ['array'], 'HaruPage::getDash' => ['array'], 'HaruPage::getFillingColorSpace' => ['int'], 'HaruPage::getFlatness' => ['float'], 'HaruPage::getGMode' => ['int'], 'HaruPage::getGrayFill' => ['float'], 'HaruPage::getGrayStroke' => ['float'], 'HaruPage::getHeight' => ['float'], 'HaruPage::getHorizontalScaling' => ['float'], 'HaruPage::getLineCap' => ['int'], 'HaruPage::getLineJoin' => ['int'], 'HaruPage::getLineWidth' => ['float'], 'HaruPage::getMiterLimit' => ['float'], 'HaruPage::getRGBFill' => ['array'], 'HaruPage::getRGBStroke' => ['array'], 'HaruPage::getStrokingColorSpace' => ['int'], 'HaruPage::getTextLeading' => ['float'], 'HaruPage::getTextMatrix' => ['array'], 'HaruPage::getTextRenderingMode' => ['int'], 'HaruPage::getTextRise' => ['float'], 'HaruPage::getTextWidth' => ['float', 'text'=>'string'], 'HaruPage::getTransMatrix' => ['array'], 'HaruPage::getWidth' => ['float'], 'HaruPage::getWordSpace' => ['float'], 'HaruPage::lineTo' => ['bool', 'x'=>'float', 'y'=>'float'], 'HaruPage::measureText' => ['int', 'text'=>'string', 'width'=>'float', 'wordwrap='=>'bool'], 'HaruPage::moveTextPos' => ['bool', 'x'=>'float', 'y'=>'float', 'set_leading='=>'bool'], 'HaruPage::moveTo' => ['bool', 'x'=>'float', 'y'=>'float'], 'HaruPage::moveToNextLine' => ['bool'], 'HaruPage::rectangle' => ['bool', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'HaruPage::setCharSpace' => ['bool', 'char_space'=>'float'], 'HaruPage::setCMYKFill' => ['bool', 'c'=>'float', 'm'=>'float', 'y'=>'float', 'k'=>'float'], 'HaruPage::setCMYKStroke' => ['bool', 'c'=>'float', 'm'=>'float', 'y'=>'float', 'k'=>'float'], 'HaruPage::setDash' => ['bool', 'pattern'=>'array', 'phase'=>'int'], 'HaruPage::setFlatness' => ['bool', 'flatness'=>'float'], 'HaruPage::setFontAndSize' => ['bool', 'font'=>'object', 'size'=>'float'], 'HaruPage::setGrayFill' => ['bool', 'value'=>'float'], 'HaruPage::setGrayStroke' => ['bool', 'value'=>'float'], 'HaruPage::setHeight' => ['bool', 'height'=>'float'], 'HaruPage::setHorizontalScaling' => ['bool', 'scaling'=>'float'], 'HaruPage::setLineCap' => ['bool', 'cap'=>'int'], 'HaruPage::setLineJoin' => ['bool', 'join'=>'int'], 'HaruPage::setLineWidth' => ['bool', 'width'=>'float'], 'HaruPage::setMiterLimit' => ['bool', 'limit'=>'float'], 'HaruPage::setRGBFill' => ['bool', 'r'=>'float', 'g'=>'float', 'b'=>'float'], 'HaruPage::setRGBStroke' => ['bool', 'r'=>'float', 'g'=>'float', 'b'=>'float'], 'HaruPage::setRotate' => ['bool', 'angle'=>'int'], 'HaruPage::setSize' => ['bool', 'size'=>'int', 'direction'=>'int'], 'HaruPage::setSlideShow' => ['bool', 'type'=>'int', 'disp_time'=>'float', 'trans_time'=>'float'], 'HaruPage::setTextLeading' => ['bool', 'text_leading'=>'float'], 'HaruPage::setTextMatrix' => ['bool', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'x'=>'float', 'y'=>'float'], 'HaruPage::setTextRenderingMode' => ['bool', 'mode'=>'int'], 'HaruPage::setTextRise' => ['bool', 'rise'=>'float'], 'HaruPage::setWidth' => ['bool', 'width'=>'float'], 'HaruPage::setWordSpace' => ['bool', 'word_space'=>'float'], 'HaruPage::showText' => ['bool', 'text'=>'string'], 'HaruPage::showTextNextLine' => ['bool', 'text'=>'string', 'word_space='=>'float', 'char_space='=>'float'], 'HaruPage::stroke' => ['bool', 'close_path='=>'bool'], 'HaruPage::textOut' => ['bool', 'x'=>'float', 'y'=>'float', 'text'=>'string'], 'HaruPage::textRect' => ['bool', 'left'=>'float', 'top'=>'float', 'right'=>'float', 'bottom'=>'float', 'text'=>'string', 'align='=>'int'], 'hash' => ['non-falsy-string|false', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'], 'hash_algos' => ['non-empty-list'], 'hash_copy' => ['HashContext', 'context'=>'HashContext'], 'hash_equals' => ['bool', 'known_string'=>'string', 'user_string'=>'string'], 'hash_file' => ['non-falsy-string|false', 'algo'=>'string', 'filename'=>'string', 'raw_output='=>'bool'], 'hash_final' => ['non-falsy-string', 'context'=>'HashContext', 'raw_output='=>'bool'], 'hash_hkdf' => ['non-falsy-string|false', 'algo'=>'string', 'key'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'], 'hash_hmac' => ['non-falsy-string|false', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'], 'hash_hmac_algos' => ['non-empty-list'], 'hash_hmac_file' => ['non-falsy-string|false', 'algo'=>'string', 'filename'=>'string', 'key'=>'string', 'raw_output='=>'bool'], 'hash_init' => ['HashContext', 'algo'=>'string', 'options='=>'int', 'key='=>'string'], 'hash_pbkdf2' => ['(non-falsy-string&lowercase-string)|false', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'], 'hash_update' => ['bool', 'context'=>'HashContext', 'data'=>'string'], 'hash_update_file' => ['bool', 'context'=>'HashContext', 'filename'=>'string', 'scontext='=>'?HashContext'], 'hash_update_stream' => ['int', 'context'=>'HashContext', 'handle'=>'resource', 'length='=>'int'], 'hashTableObj::clear' => ['void'], 'hashTableObj::get' => ['string', 'key'=>'string'], 'hashTableObj::nextkey' => ['string', 'previousKey'=>'string'], 'hashTableObj::remove' => ['int', 'key'=>'string'], 'hashTableObj::set' => ['int', 'key'=>'string', 'value'=>'string'], 'header' => ['void', 'header'=>'string', 'replace='=>'bool', 'http_response_code='=>'int'], 'header_register_callback' => ['bool', 'callback'=>'callable'], 'header_remove' => ['void', 'name='=>'string'], 'headers_list' => ['list'], 'headers_sent' => ['bool', '&w_file='=>'string', '&w_line='=>'int'], 'hebrev' => ['string', 'str'=>'string', 'max_chars_per_line='=>'int'], 'hebrevc' => ['string', 'str'=>'string', 'max_chars_per_line='=>'int'], 'hex2bin' => ['string|false', 'data'=>'string'], 'hexdec' => ['int|float', 'hexadecimal_number'=>'string'], 'highlight_file' => ['string|bool', 'file_name'=>'string', 'return='=>'bool'], 'highlight_string' => ['string|bool', 'string'=>'string', 'return='=>'bool'], 'hrtime' => ['array{0:int,1:int}|int|float|false', 'get_as_number='=>'bool'], 'HRTime\PerformanceCounter::getElapsedTicks' => ['int'], 'HRTime\PerformanceCounter::getFrequency' => ['int'], 'HRTime\PerformanceCounter::getLastElapsedTicks' => ['int'], 'HRTime\PerformanceCounter::getTicks' => ['int'], 'HRTime\PerformanceCounter::getTicksSince' => ['int', 'start'=>'int'], 'HRTime\PerformanceCounter::isRunning' => ['bool'], 'HRTime\PerformanceCounter::start' => ['void'], 'HRTime\PerformanceCounter::stop' => ['void'], 'HRTime\StopWatch::getElapsedTicks' => ['int'], 'HRTime\StopWatch::getElapsedTime' => ['float', 'unit='=>'int'], 'HRTime\StopWatch::getLastElapsedTicks' => ['int'], 'HRTime\StopWatch::getLastElapsedTime' => ['float', 'unit='=>'int'], 'HRTime\StopWatch::isRunning' => ['bool'], 'HRTime\StopWatch::start' => ['void'], 'HRTime\StopWatch::stop' => ['void'], 'html_entity_decode' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string'], 'htmlentities' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string', 'double_encode='=>'bool'], 'htmlspecialchars' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string', 'double_encode='=>'bool'], 'htmlspecialchars_decode' => ['string', 'string'=>'string', 'quote_style='=>'int'], 'http\Env\Request::__construct' => ['void'], 'http\Env\Request::getCookie' => ['mixed', 'name='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\Env\Request::getFiles' => ['array'], 'http\Env\Request::getForm' => ['mixed', 'name='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\Env\Request::getQuery' => ['mixed', 'name='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\Env\Response::__construct' => ['void'], 'http\Env\Response::__invoke' => ['bool', 'data'=>'string', 'ob_flags='=>'int'], 'http\Env\Response::isCachedByETag' => ['int', 'header_name='=>'string'], 'http\Env\Response::isCachedByLastModified' => ['int', 'header_name='=>'string'], 'http\Env\Response::send' => ['bool', 'stream='=>'resource'], 'http\Env\Response::setCacheControl' => ['http\Env\Response', 'cache_control'=>'string'], 'http\Env\Response::setContentDisposition' => ['http\Env\Response', 'disposition_params'=>'array'], 'http\Env\Response::setContentEncoding' => ['http\Env\Response', 'content_encoding'=>'int'], 'http\Env\Response::setContentType' => ['http\Env\Response', 'content_type'=>'string'], 'http\Env\Response::setCookie' => ['http\Env\Response', 'cookie'=>'mixed'], 'http\Env\Response::setEnvRequest' => ['http\Env\Response', 'env_request'=>'http\Message'], 'http\Env\Response::setEtag' => ['http\Env\Response', 'etag'=>'string'], 'http\Env\Response::setLastModified' => ['http\Env\Response', 'last_modified'=>'int'], 'http\Env\Response::setThrottleRate' => ['http\Env\Response', 'chunk_size'=>'int', 'delay='=>'float|int'], 'http\QueryString::__construct' => ['void', 'querystring'=>'string'], 'http\QueryString::__toString' => ['string'], 'http\QueryString::get' => ['', 'name='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getArray' => ['array', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getBool' => ['bool', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getFloat' => ['float', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getGlobalInstance' => ['http\QueryString'], 'http\QueryString::getInt' => ['int', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getIterator' => ['IteratorAggregate'], 'http\QueryString::getObject' => ['', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::getString' => ['string', 'name'=>'string', 'defval='=>'mixed', 'delete='=>'bool|false'], 'http\QueryString::mod' => ['http\QueryString', 'params='=>'mixed'], 'http\QueryString::offsetExists' => ['bool', 'offset'=>'mixed'], 'http\QueryString::offsetGet' => ['mixed', 'offset'=>'mixed'], 'http\QueryString::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'http\QueryString::offsetUnset' => ['void', 'offset'=>'mixed'], 'http\QueryString::serialize' => ['string'], 'http\QueryString::set' => ['http\QueryString', 'params'=>'mixed'], 'http\QueryString::toArray' => ['mixed[]'], 'http\QueryString::toString' => ['string'], 'http\QueryString::unserialize' => ['void', 'serialized'=>''], 'http\QueryString::xlate' => ['http\QueryString'], 'http\Url::__construct' => ['void', 'old_url='=>'mixed', 'new_url='=>'mixed', 'flags='=>'int'], 'http\Url::__toString' => [''], 'http\Url::mod' => ['http\Url', 'parts'=>'mixed', 'flags='=>'float|int|mixed'], 'http\Url::toArray' => ['string[]'], 'http\Url::toString' => ['string'], 'http_build_cookie' => ['string', 'cookie'=>'array'], 'http_build_query' => ['string', 'querydata'=>'array|object', 'prefix='=>'string', 'arg_separator='=>'string', 'enc_type='=>'int'], 'http_build_str' => ['string', 'query'=>'array', 'prefix='=>'?string', 'arg_separator='=>'string'], 'http_build_url' => ['string', 'url='=>'string|array', 'parts='=>'string|array', 'flags='=>'int', 'new_url='=>'array'], 'http_cache_etag' => ['bool', 'etag='=>'string'], 'http_cache_last_modified' => ['bool', 'timestamp_or_expires='=>'int'], 'http_chunked_decode' => ['string', 'encoded'=>'string'], 'http_date' => ['string', 'timestamp='=>'int'], 'http_deflate' => ['string', 'data'=>'string', 'flags='=>'int'], 'http_get' => ['string', 'url'=>'string', 'options='=>'array', 'info='=>'array'], 'http_get_request_body' => ['string'], 'http_get_request_body_stream' => ['resource'], 'http_get_request_headers' => ['array'], 'http_head' => ['string', 'url'=>'string', 'options='=>'array', 'info='=>'array'], 'http_inflate' => ['string', 'data'=>'string'], 'http_match_etag' => ['bool', 'etag'=>'string', 'for_range='=>'bool'], 'http_match_modified' => ['bool', 'timestamp='=>'int', 'for_range='=>'bool'], 'http_match_request_header' => ['bool', 'header'=>'string', 'value'=>'string', 'match_case='=>'bool'], 'http_negotiate_charset' => ['string', 'supported'=>'array', 'result='=>'array'], 'http_negotiate_content_type' => ['string', 'supported'=>'array', 'result='=>'array'], 'http_negotiate_language' => ['string', 'supported'=>'array', 'result='=>'array'], 'http_parse_cookie' => ['object', 'cookie'=>'string', 'flags='=>'int', 'allowed_extras='=>'array'], 'http_parse_headers' => ['array', 'header'=>'string'], 'http_parse_message' => ['object', 'message'=>'string'], 'http_parse_params' => ['object', 'param'=>'string', 'flags='=>'int'], 'http_persistent_handles_clean' => ['string', 'ident='=>'string'], 'http_persistent_handles_count' => ['object'], 'http_persistent_handles_ident' => ['string', 'ident='=>'string'], 'http_post_data' => ['string', 'url'=>'string', 'data'=>'string', 'options='=>'array', 'info='=>'array'], 'http_post_fields' => ['string', 'url'=>'string', 'data'=>'array', 'files='=>'array', 'options='=>'array', 'info='=>'array'], 'http_put_data' => ['string', 'url'=>'string', 'data'=>'string', 'options='=>'array', 'info='=>'array'], 'http_put_file' => ['string', 'url'=>'string', 'file'=>'string', 'options='=>'array', 'info='=>'array'], 'http_put_stream' => ['string', 'url'=>'string', 'stream'=>'', 'options='=>'array', 'info='=>'array'], 'http_redirect' => ['bool', 'url='=>'string', 'params='=>'array', 'session='=>'bool', 'status='=>'int'], 'http_request' => ['string', 'method'=>'int', 'url'=>'string', 'body='=>'string', 'options='=>'array', 'info='=>'array'], 'http_request_body_encode' => ['string', 'fields'=>'array', 'files'=>'array'], 'http_request_method_exists' => ['int', 'method'=>''], 'http_request_method_name' => ['string', 'method'=>'int'], 'http_request_method_register' => ['int', 'method'=>'string'], 'http_request_method_unregister' => ['bool', 'method'=>''], 'http_response_code' => ['int|bool', 'response_code='=>'int'], 'http_send_content_disposition' => ['bool', 'filename'=>'string', 'inline='=>'bool'], 'http_send_content_type' => ['bool', 'content_type='=>'string'], 'http_send_data' => ['bool', 'data'=>'string'], 'http_send_file' => ['bool', 'file'=>'string'], 'http_send_last_modified' => ['bool', 'timestamp='=>'int'], 'http_send_status' => ['bool', 'status'=>'int'], 'http_send_stream' => ['bool', 'stream'=>''], 'http_support' => ['int', 'feature='=>'int'], 'http_throttle' => ['', 'sec'=>'float', 'bytes='=>'int'], 'HttpDeflateStream::__construct' => ['void', 'flags='=>'int'], 'HttpDeflateStream::factory' => ['HttpDeflateStream', 'flags='=>'int', 'class_name='=>'string'], 'HttpDeflateStream::finish' => ['string', 'data='=>'string'], 'HttpDeflateStream::flush' => ['string', 'data='=>'string'], 'HttpDeflateStream::update' => ['string', 'data'=>'string'], 'HttpInflateStream::__construct' => ['void', 'flags='=>'int'], 'HttpInflateStream::factory' => ['HttpInflateStream', 'flags='=>'int', 'class_name='=>'string'], 'HttpInflateStream::finish' => ['string', 'data='=>'string'], 'HttpInflateStream::flush' => ['string', 'data='=>'string'], 'HttpInflateStream::update' => ['string', 'data'=>'string'], 'HttpMessage::__construct' => ['void', 'message='=>'string'], 'HttpMessage::__toString' => ['string'], 'HttpMessage::addHeaders' => ['', 'headers'=>'array', 'append='=>'bool'], 'HttpMessage::count' => ['0|positive-int'], 'HttpMessage::current' => ['mixed'], 'HttpMessage::detach' => ['HttpMessage'], 'HttpMessage::factory' => ['HttpMessage', 'raw_message='=>'string', 'class_name='=>'string'], 'HttpMessage::fromEnv' => ['HttpMessage', 'message_type'=>'int', 'class_name='=>'string'], 'HttpMessage::fromString' => ['HttpMessage', 'raw_message='=>'string', 'class_name='=>'string'], 'HttpMessage::getBody' => ['string'], 'HttpMessage::getHeader' => ['string', 'header'=>'string'], 'HttpMessage::getHeaders' => ['array'], 'HttpMessage::getHttpVersion' => ['string'], 'HttpMessage::getInfo' => [''], 'HttpMessage::getParentMessage' => ['HttpMessage'], 'HttpMessage::getRequestMethod' => ['string'], 'HttpMessage::getRequestUrl' => ['string'], 'HttpMessage::getResponseCode' => ['int'], 'HttpMessage::getResponseStatus' => ['string'], 'HttpMessage::getType' => ['int'], 'HttpMessage::guessContentType' => ['string', 'magic_file'=>'string', 'magic_mode='=>'int'], 'HttpMessage::key' => ['int|string'], 'HttpMessage::next' => ['void'], 'HttpMessage::prepend' => ['', 'message'=>'httpmessage', 'top='=>'bool'], 'HttpMessage::reverse' => ['HttpMessage'], 'HttpMessage::rewind' => ['void'], 'HttpMessage::send' => ['bool'], 'HttpMessage::serialize' => ['string'], 'HttpMessage::setBody' => ['', 'body'=>'string'], 'HttpMessage::setHeaders' => ['', 'headers'=>'array'], 'HttpMessage::setHttpVersion' => ['bool', 'version'=>'string'], 'HttpMessage::setInfo' => ['', 'http_info'=>''], 'HttpMessage::setRequestMethod' => ['bool', 'method'=>'string'], 'HttpMessage::setRequestUrl' => ['bool', 'url'=>'string'], 'HttpMessage::setResponseCode' => ['bool', 'code'=>'int'], 'HttpMessage::setResponseStatus' => ['bool', 'status'=>'string'], 'HttpMessage::setType' => ['', 'type'=>'int'], 'HttpMessage::toMessageTypeObject' => ['HttpRequest|HttpResponse'], 'HttpMessage::toString' => ['string', 'include_parent='=>'bool'], 'HttpMessage::unserialize' => ['void', 'serialized'=>''], 'HttpMessage::valid' => ['bool'], 'HttpQueryString::__construct' => ['void', 'global='=>'bool', 'add='=>''], 'HttpQueryString::__toString' => ['string'], 'HttpQueryString::factory' => ['', 'global'=>'', 'params'=>'', 'class_name'=>''], 'HttpQueryString::get' => ['', 'key='=>'string', 'type='=>'', 'defval='=>'', 'delete='=>'bool'], 'HttpQueryString::getArray' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getBool' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getFloat' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getInt' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getObject' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::getString' => ['', 'name'=>'', 'defval'=>'', 'delete'=>''], 'HttpQueryString::mod' => ['HttpQueryString', 'params'=>''], 'HttpQueryString::offsetExists' => ['bool', 'offset'=>'mixed'], 'HttpQueryString::offsetGet' => ['mixed', 'offset'=>'mixed'], 'HttpQueryString::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'HttpQueryString::offsetUnset' => ['void', 'offset'=>'mixed'], 'HttpQueryString::serialize' => ['string'], 'HttpQueryString::set' => ['string', 'params'=>''], 'HttpQueryString::singleton' => ['HttpQueryString', 'global='=>'bool'], 'HttpQueryString::toArray' => ['array'], 'HttpQueryString::toString' => ['string'], 'HttpQueryString::unserialize' => ['void', 'serialized'=>'string'], 'HttpQueryString::xlate' => ['bool', 'ie'=>'string', 'oe'=>'string'], 'HttpRequest::__construct' => ['void', 'url='=>'string', 'request_method='=>'int', 'options='=>'array'], 'HttpRequest::addBody' => ['', 'request_body_data'=>''], 'HttpRequest::addCookies' => ['bool', 'cookies'=>'array'], 'HttpRequest::addHeaders' => ['bool', 'headers'=>'array'], 'HttpRequest::addPostFields' => ['bool', 'post_data'=>'array'], 'HttpRequest::addPostFile' => ['bool', 'name'=>'string', 'file'=>'string', 'content_type='=>'string'], 'HttpRequest::addPutData' => ['bool', 'put_data'=>'string'], 'HttpRequest::addQueryData' => ['bool', 'query_params'=>'array'], 'HttpRequest::addRawPostData' => ['bool', 'raw_post_data'=>'string'], 'HttpRequest::addSslOptions' => ['bool', 'options'=>'array'], 'HttpRequest::clearHistory' => [''], 'HttpRequest::enableCookies' => ['bool'], 'HttpRequest::encodeBody' => ['', 'fields'=>'', 'files'=>''], 'HttpRequest::factory' => ['', 'url'=>'', 'method'=>'', 'options'=>'', 'class_name'=>''], 'HttpRequest::flushCookies' => [''], 'HttpRequest::get' => ['', 'url'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::getBody' => [''], 'HttpRequest::getContentType' => ['string'], 'HttpRequest::getCookies' => ['array'], 'HttpRequest::getHeaders' => ['array'], 'HttpRequest::getHistory' => ['HttpMessage'], 'HttpRequest::getMethod' => ['int'], 'HttpRequest::getOptions' => ['array'], 'HttpRequest::getPostFields' => ['array'], 'HttpRequest::getPostFiles' => ['array'], 'HttpRequest::getPutData' => ['string'], 'HttpRequest::getPutFile' => ['string'], 'HttpRequest::getQueryData' => ['string'], 'HttpRequest::getRawPostData' => ['string'], 'HttpRequest::getRawRequestMessage' => ['string'], 'HttpRequest::getRawResponseMessage' => ['string'], 'HttpRequest::getRequestMessage' => ['HttpMessage'], 'HttpRequest::getResponseBody' => ['string'], 'HttpRequest::getResponseCode' => ['int'], 'HttpRequest::getResponseCookies' => ['array', 'flags='=>'int', 'allowed_extras='=>'array'], 'HttpRequest::getResponseData' => ['array'], 'HttpRequest::getResponseHeader' => ['', 'name='=>'string'], 'HttpRequest::getResponseInfo' => ['', 'name='=>'string'], 'HttpRequest::getResponseMessage' => ['HttpMessage'], 'HttpRequest::getResponseStatus' => ['string'], 'HttpRequest::getSslOptions' => ['array'], 'HttpRequest::getUrl' => ['string'], 'HttpRequest::head' => ['', 'url'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::methodExists' => ['', 'method'=>''], 'HttpRequest::methodName' => ['', 'method_id'=>''], 'HttpRequest::methodRegister' => ['', 'method_name'=>''], 'HttpRequest::methodUnregister' => ['', 'method'=>''], 'HttpRequest::postData' => ['', 'url'=>'', 'data'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::postFields' => ['', 'url'=>'', 'data'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::putData' => ['', 'url'=>'', 'data'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::putFile' => ['', 'url'=>'', 'file'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::putStream' => ['', 'url'=>'', 'stream'=>'', 'options'=>'', '&info'=>''], 'HttpRequest::resetCookies' => ['bool', 'session_only='=>'bool'], 'HttpRequest::send' => ['HttpMessage'], 'HttpRequest::setBody' => ['bool', 'request_body_data='=>'string'], 'HttpRequest::setContentType' => ['bool', 'content_type'=>'string'], 'HttpRequest::setCookies' => ['bool', 'cookies='=>'array'], 'HttpRequest::setHeaders' => ['bool', 'headers='=>'array'], 'HttpRequest::setMethod' => ['bool', 'request_method'=>'int'], 'HttpRequest::setOptions' => ['bool', 'options='=>'array'], 'HttpRequest::setPostFields' => ['bool', 'post_data'=>'array'], 'HttpRequest::setPostFiles' => ['bool', 'post_files'=>'array'], 'HttpRequest::setPutData' => ['bool', 'put_data='=>'string'], 'HttpRequest::setPutFile' => ['bool', 'file='=>'string'], 'HttpRequest::setQueryData' => ['bool', 'query_data'=>''], 'HttpRequest::setRawPostData' => ['bool', 'raw_post_data='=>'string'], 'HttpRequest::setSslOptions' => ['bool', 'options='=>'array'], 'HttpRequest::setUrl' => ['bool', 'url'=>'string'], 'HttpRequestDataShare::__construct' => ['void'], 'HttpRequestDataShare::__destruct' => [''], 'HttpRequestDataShare::attach' => ['', 'request'=>'HttpRequest'], 'HttpRequestDataShare::count' => ['0|positive-int'], 'HttpRequestDataShare::detach' => ['', 'request'=>'HttpRequest'], 'HttpRequestDataShare::factory' => ['', 'global'=>'', 'class_name'=>''], 'HttpRequestDataShare::reset' => [''], 'HttpRequestDataShare::singleton' => ['', 'global'=>''], 'HttpRequestPool::__construct' => ['void', 'request='=>'httprequest'], 'HttpRequestPool::__destruct' => [''], 'HttpRequestPool::attach' => ['bool', 'request'=>'httprequest'], 'HttpRequestPool::count' => ['0|positive-int'], 'HttpRequestPool::current' => ['mixed'], 'HttpRequestPool::detach' => ['bool', 'request'=>'httprequest'], 'HttpRequestPool::enableEvents' => ['', 'enable'=>''], 'HttpRequestPool::enablePipelining' => ['', 'enable'=>''], 'HttpRequestPool::getAttachedRequests' => ['array'], 'HttpRequestPool::getFinishedRequests' => ['array'], 'HttpRequestPool::key' => ['int|string'], 'HttpRequestPool::next' => ['void'], 'HttpRequestPool::reset' => [''], 'HttpRequestPool::rewind' => ['void'], 'HttpRequestPool::send' => ['bool'], 'HttpRequestPool::socketPerform' => ['bool'], 'HttpRequestPool::socketSelect' => ['bool', 'timeout='=>'float'], 'HttpRequestPool::valid' => ['bool'], 'HttpResponse::capture' => [''], 'HttpResponse::getBufferSize' => ['int'], 'HttpResponse::getCache' => ['bool'], 'HttpResponse::getCacheControl' => ['string'], 'HttpResponse::getContentDisposition' => ['string'], 'HttpResponse::getContentType' => ['string'], 'HttpResponse::getData' => ['string'], 'HttpResponse::getETag' => ['string'], 'HttpResponse::getFile' => ['string'], 'HttpResponse::getGzip' => ['bool'], 'HttpResponse::getHeader' => ['', 'name='=>'string'], 'HttpResponse::getLastModified' => ['int'], 'HttpResponse::getRequestBody' => ['string'], 'HttpResponse::getRequestBodyStream' => ['resource'], 'HttpResponse::getRequestHeaders' => ['array'], 'HttpResponse::getStream' => ['resource'], 'HttpResponse::getThrottleDelay' => ['float'], 'HttpResponse::guessContentType' => ['string', 'magic_file'=>'string', 'magic_mode='=>'int'], 'HttpResponse::redirect' => ['', 'url='=>'string', 'params='=>'array', 'session='=>'bool', 'status='=>'int'], 'HttpResponse::send' => ['bool', 'clean_ob='=>'bool'], 'HttpResponse::setBufferSize' => ['bool', 'bytes'=>'int'], 'HttpResponse::setCache' => ['bool', 'cache'=>'bool'], 'HttpResponse::setCacheControl' => ['bool', 'control'=>'string', 'max_age='=>'int', 'must_revalidate='=>'bool'], 'HttpResponse::setContentDisposition' => ['bool', 'filename'=>'string', 'inline='=>'bool'], 'HttpResponse::setContentType' => ['bool', 'content_type'=>'string'], 'HttpResponse::setData' => ['bool', 'data'=>''], 'HttpResponse::setETag' => ['bool', 'etag'=>'string'], 'HttpResponse::setFile' => ['bool', 'file'=>'string'], 'HttpResponse::setGzip' => ['bool', 'gzip'=>'bool'], 'HttpResponse::setHeader' => ['bool', 'name'=>'string', 'value='=>'', 'replace='=>'bool'], 'HttpResponse::setLastModified' => ['bool', 'timestamp'=>'int'], 'HttpResponse::setStream' => ['bool', 'stream'=>''], 'HttpResponse::setThrottleDelay' => ['bool', 'seconds'=>'float'], 'HttpResponse::status' => ['bool', 'status'=>'int'], 'HttpUtil::buildCookie' => ['', 'cookie_array'=>''], 'HttpUtil::buildStr' => ['', 'query'=>'', 'prefix'=>'', 'arg_sep'=>''], 'HttpUtil::buildUrl' => ['', 'url'=>'', 'parts'=>'', 'flags'=>'', '&composed'=>''], 'HttpUtil::chunkedDecode' => ['', 'encoded_string'=>''], 'HttpUtil::date' => ['', 'timestamp'=>''], 'HttpUtil::deflate' => ['', 'plain'=>'', 'flags'=>''], 'HttpUtil::inflate' => ['', 'encoded'=>''], 'HttpUtil::matchEtag' => ['', 'plain_etag'=>'', 'for_range'=>''], 'HttpUtil::matchModified' => ['', 'last_modified'=>'', 'for_range'=>''], 'HttpUtil::matchRequestHeader' => ['', 'header_name'=>'', 'header_value'=>'', 'case_sensitive'=>''], 'HttpUtil::negotiateCharset' => ['', 'supported'=>'', '&result'=>''], 'HttpUtil::negotiateContentType' => ['', 'supported'=>'', '&result'=>''], 'HttpUtil::negotiateLanguage' => ['', 'supported'=>'', '&result'=>''], 'HttpUtil::parseCookie' => ['', 'cookie_string'=>''], 'HttpUtil::parseHeaders' => ['', 'headers_string'=>''], 'HttpUtil::parseMessage' => ['', 'message_string'=>''], 'HttpUtil::parseParams' => ['', 'param_string'=>'', 'flags'=>''], 'HttpUtil::support' => ['', 'feature'=>''], 'hw_api::checkin' => ['bool', 'parameter'=>'array'], 'hw_api::checkout' => ['bool', 'parameter'=>'array'], 'hw_api::children' => ['array', 'parameter'=>'array'], 'hw_api::content' => ['HW_API_Content', 'parameter'=>'array'], 'hw_api::copy' => ['hw_api_content', 'parameter'=>'array'], 'hw_api::dbstat' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::dcstat' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::dstanchors' => ['array', 'parameter'=>'array'], 'hw_api::dstofsrcanchor' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::find' => ['array', 'parameter'=>'array'], 'hw_api::ftstat' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::hwstat' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::identify' => ['bool', 'parameter'=>'array'], 'hw_api::info' => ['array', 'parameter'=>'array'], 'hw_api::insert' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::insertanchor' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::insertcollection' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::insertdocument' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::link' => ['bool', 'parameter'=>'array'], 'hw_api::lock' => ['bool', 'parameter'=>'array'], 'hw_api::move' => ['bool', 'parameter'=>'array'], 'hw_api::object' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::objectbyanchor' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::parents' => ['array', 'parameter'=>'array'], 'hw_api::remove' => ['bool', 'parameter'=>'array'], 'hw_api::replace' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::setcommittedversion' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::srcanchors' => ['array', 'parameter'=>'array'], 'hw_api::srcsofdst' => ['array', 'parameter'=>'array'], 'hw_api::unlock' => ['bool', 'parameter'=>'array'], 'hw_api::user' => ['hw_api_object', 'parameter'=>'array'], 'hw_api::userlist' => ['array', 'parameter'=>'array'], 'hw_api_attribute' => ['HW_API_Attribute', 'name='=>'string', 'value='=>'string'], 'hw_api_attribute::key' => ['string'], 'hw_api_attribute::langdepvalue' => ['string', 'language'=>'string'], 'hw_api_attribute::value' => ['string'], 'hw_api_attribute::values' => ['array'], 'hw_api_content' => ['HW_API_Content', 'content'=>'string', 'mimetype'=>'string'], 'hw_api_content::mimetype' => ['string'], 'hw_api_content::read' => ['string', 'buffer'=>'string', 'len'=>'int'], 'hw_api_error::count' => ['0|positive-int'], 'hw_api_error::reason' => ['HW_API_Reason'], 'hw_api_object' => ['hw_api_object', 'parameter'=>'array'], 'hw_api_object::assign' => ['bool', 'parameter'=>'array'], 'hw_api_object::attreditable' => ['bool', 'parameter'=>'array'], 'hw_api_object::count' => ['0|positive-int', 'parameter'=>'array'], 'hw_api_object::insert' => ['bool', 'attribute'=>'hw_api_attribute'], 'hw_api_object::remove' => ['bool', 'name'=>'string'], 'hw_api_object::title' => ['string', 'parameter'=>'array'], 'hw_api_object::value' => ['string', 'name'=>'string'], 'hw_api_reason::description' => ['string'], 'hw_api_reason::type' => ['HW_API_Reason'], 'hw_Array2Objrec' => ['string', 'object_array'=>'array'], 'hw_changeobject' => ['bool', 'link'=>'int', 'objid'=>'int', 'attributes'=>'array'], 'hw_Children' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_ChildrenObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_Close' => ['bool', 'connection'=>'int'], 'hw_Connect' => ['int', 'host'=>'string', 'port'=>'int', 'username='=>'string', 'password='=>'string'], 'hw_connection_info' => ['', 'link'=>'int'], 'hw_cp' => ['int', 'connection'=>'int', 'object_id_array'=>'array', 'destination_id'=>'int'], 'hw_Deleteobject' => ['bool', 'connection'=>'int', 'object_to_delete'=>'int'], 'hw_DocByAnchor' => ['int', 'connection'=>'int', 'anchorid'=>'int'], 'hw_DocByAnchorObj' => ['string', 'connection'=>'int', 'anchorid'=>'int'], 'hw_Document_Attributes' => ['string', 'hw_document'=>'int'], 'hw_Document_BodyTag' => ['string', 'hw_document'=>'int', 'prefix='=>'string'], 'hw_Document_Content' => ['string', 'hw_document'=>'int'], 'hw_Document_SetContent' => ['bool', 'hw_document'=>'int', 'content'=>'string'], 'hw_Document_Size' => ['int', 'hw_document'=>'int'], 'hw_dummy' => ['string', 'link'=>'int', 'id'=>'int', 'msgid'=>'int'], 'hw_EditText' => ['bool', 'connection'=>'int', 'hw_document'=>'int'], 'hw_Error' => ['int', 'connection'=>'int'], 'hw_ErrorMsg' => ['string', 'connection'=>'int'], 'hw_Free_Document' => ['bool', 'hw_document'=>'int'], 'hw_GetAnchors' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetAnchorsObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetAndLock' => ['string', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetChildColl' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetChildCollObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetChildDocColl' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetChildDocCollObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetObject' => ['', 'connection'=>'int', 'objectid'=>'', 'query='=>'string'], 'hw_GetObjectByQuery' => ['array', 'connection'=>'int', 'query'=>'string', 'max_hits'=>'int'], 'hw_GetObjectByQueryColl' => ['array', 'connection'=>'int', 'objectid'=>'int', 'query'=>'string', 'max_hits'=>'int'], 'hw_GetObjectByQueryCollObj' => ['array', 'connection'=>'int', 'objectid'=>'int', 'query'=>'string', 'max_hits'=>'int'], 'hw_GetObjectByQueryObj' => ['array', 'connection'=>'int', 'query'=>'string', 'max_hits'=>'int'], 'hw_GetParents' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetParentsObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_getrellink' => ['string', 'link'=>'int', 'rootid'=>'int', 'sourceid'=>'int', 'destid'=>'int'], 'hw_GetRemote' => ['int', 'connection'=>'int', 'objectid'=>'int'], 'hw_getremotechildren' => ['', 'connection'=>'int', 'object_record'=>'string'], 'hw_GetSrcByDestObj' => ['array', 'connection'=>'int', 'objectid'=>'int'], 'hw_GetText' => ['int', 'connection'=>'int', 'objectid'=>'int', 'prefix='=>''], 'hw_getusername' => ['string', 'connection'=>'int'], 'hw_Identify' => ['string', 'link'=>'int', 'username'=>'string', 'password'=>'string'], 'hw_InCollections' => ['array', 'connection'=>'int', 'object_id_array'=>'array', 'collection_id_array'=>'array', 'return_collections'=>'int'], 'hw_Info' => ['string', 'connection'=>'int'], 'hw_InsColl' => ['int', 'connection'=>'int', 'objectid'=>'int', 'object_array'=>'array'], 'hw_InsDoc' => ['int', 'connection'=>'', 'parentid'=>'int', 'object_record'=>'string', 'text='=>'string'], 'hw_insertanchors' => ['bool', 'hwdoc'=>'int', 'anchorecs'=>'array', 'dest'=>'array', 'urlprefixes='=>'array'], 'hw_InsertDocument' => ['int', 'connection'=>'int', 'parent_id'=>'int', 'hw_document'=>'int'], 'hw_InsertObject' => ['int', 'connection'=>'int', 'object_rec'=>'string', 'parameter'=>'string'], 'hw_mapid' => ['int', 'connection'=>'int', 'server_id'=>'int', 'object_id'=>'int'], 'hw_Modifyobject' => ['bool', 'connection'=>'int', 'object_to_change'=>'int', 'remove'=>'array', 'add'=>'array', 'mode='=>'int'], 'hw_mv' => ['int', 'connection'=>'int', 'object_id_array'=>'array', 'source_id'=>'int', 'destination_id'=>'int'], 'hw_New_Document' => ['int', 'object_record'=>'string', 'document_data'=>'string', 'document_size'=>'int'], 'hw_objrec2array' => ['array', 'object_record'=>'string', 'format='=>'array'], 'hw_Output_Document' => ['bool', 'hw_document'=>'int'], 'hw_pConnect' => ['int', 'host'=>'string', 'port'=>'int', 'username='=>'string', 'password='=>'string'], 'hw_PipeDocument' => ['int', 'connection'=>'int', 'objectid'=>'int', 'url_prefixes='=>'array'], 'hw_Root' => ['int'], 'hw_setlinkroot' => ['int', 'link'=>'int', 'rootid'=>'int'], 'hw_stat' => ['string', 'link'=>'int'], 'hw_Unlock' => ['bool', 'connection'=>'int', 'objectid'=>'int'], 'hw_Who' => ['array', 'connection'=>'int'], 'hwapi_attribute_new' => ['HW_API_Attribute', 'name='=>'string', 'value='=>'string'], 'hwapi_content_new' => ['HW_API_Content', 'content'=>'string', 'mimetype'=>'string'], 'hwapi_hgcsp' => ['HW_API', 'hostname'=>'string', 'port='=>'int'], 'hwapi_object_new' => ['hw_api_object', 'parameter'=>'array'], 'hypot' => ['float', 'num1'=>'float', 'num2'=>'float'], 'ibase_add_user' => ['bool', 'service_handle'=>'resource', 'user_name'=>'string', 'password'=>'string', 'first_name='=>'string', 'middle_name='=>'string', 'last_name='=>'string'], 'ibase_affected_rows' => ['int', 'link_identifier='=>'resource'], 'ibase_backup' => ['mixed', 'service_handle'=>'resource', 'source_db'=>'string', 'dest_file'=>'string', 'options='=>'int', 'verbose='=>'bool'], 'ibase_blob_add' => ['void', 'blob_handle'=>'resource', 'data'=>'string'], 'ibase_blob_cancel' => ['bool', 'blob_handle'=>'resource'], 'ibase_blob_close' => ['string', 'blob_handle'=>'resource'], 'ibase_blob_create' => ['resource', 'link_identifier='=>'resource'], 'ibase_blob_echo' => ['bool', 'link_identifier'=>'', 'blob_id'=>'string'], 'ibase_blob_echo\'1' => ['bool', 'blob_id'=>'string'], 'ibase_blob_get' => ['string', 'blob_handle'=>'resource', 'len'=>'int'], 'ibase_blob_import' => ['string', 'link_identifier'=>'', 'file_handle'=>''], 'ibase_blob_info' => ['array', 'link_identifier'=>'', 'blob_id'=>'string'], 'ibase_blob_info\'1' => ['array', 'blob_id'=>'string'], 'ibase_blob_open' => ['resource|false', 'link_identifier'=>'', 'blob_id'=>'string'], 'ibase_blob_open\'1' => ['resource', 'blob_id'=>'string'], 'ibase_close' => ['bool', 'link_identifier='=>'resource'], 'ibase_commit' => ['bool', 'link_identifier='=>'resource'], 'ibase_commit_ret' => ['bool', 'link_identifier='=>'resource'], 'ibase_connect' => ['resource', 'database='=>'string', 'username='=>'string', 'password='=>'string', 'charset='=>'string', 'buffers='=>'int', 'dialect='=>'int', 'role='=>'string'], 'ibase_db_info' => ['string', 'service_handle'=>'resource', 'db'=>'string', 'action'=>'int', 'argument='=>'int'], 'ibase_delete_user' => ['bool', 'service_handle'=>'resource', 'user_name'=>'string', 'password='=>'string', 'first_name='=>'string', 'middle_name='=>'string', 'last_name='=>'string'], 'ibase_drop_db' => ['bool', 'link_identifier='=>'resource'], 'ibase_errcode' => ['int'], 'ibase_errmsg' => ['string'], 'ibase_execute' => ['resource', 'query'=>'resource', 'bind_arg='=>'mixed', '...args='=>'mixed'], 'ibase_fetch_assoc' => ['array', 'result'=>'resource', 'fetch_flags='=>'int'], 'ibase_fetch_object' => ['object', 'result'=>'resource', 'fetch_flags='=>'int'], 'ibase_fetch_row' => ['array', 'result'=>'resource', 'fetch_flags='=>'int'], 'ibase_field_info' => ['array', 'query_result'=>'resource', 'field_number'=>'int'], 'ibase_free_event_handler' => ['bool', 'event'=>'resource'], 'ibase_free_query' => ['bool', 'query'=>'resource'], 'ibase_free_result' => ['bool', 'result'=>'resource'], 'ibase_gen_id' => ['int', 'generator'=>'string', 'increment='=>'int', 'link_identifier='=>'resource'], 'ibase_maintain_db' => ['bool', 'service_handle'=>'resource', 'db'=>'string', 'action'=>'int', 'argument='=>'int'], 'ibase_modify_user' => ['bool', 'service_handle'=>'resource', 'user_name'=>'string', 'password'=>'string', 'first_name='=>'string', 'middle_name='=>'string', 'last_name='=>'string'], 'ibase_name_result' => ['bool', 'result'=>'resource', 'name'=>'string'], 'ibase_num_fields' => ['int', 'query_result'=>'resource'], 'ibase_num_params' => ['int', 'query'=>'resource'], 'ibase_num_rows' => ['int', 'result_identifier'=>''], 'ibase_param_info' => ['array', 'query'=>'resource', 'field_number'=>'int'], 'ibase_pconnect' => ['resource', 'database='=>'string', 'username='=>'string', 'password='=>'string', 'charset='=>'string', 'buffers='=>'int', 'dialect='=>'int', 'role='=>'string'], 'ibase_prepare' => ['resource', 'link_identifier'=>'', 'query'=>'string', 'trans_identifier'=>''], 'ibase_query' => ['resource', 'link_identifier='=>'resource', 'string='=>'string', 'bind_arg='=>'int', '...args='=>''], 'ibase_restore' => ['mixed', 'service_handle'=>'resource', 'source_file'=>'string', 'dest_db'=>'string', 'options='=>'int', 'verbose='=>'bool'], 'ibase_rollback' => ['bool', 'link_identifier='=>'resource'], 'ibase_rollback_ret' => ['bool', 'link_identifier='=>'resource'], 'ibase_server_info' => ['string', 'service_handle'=>'resource', 'action'=>'int'], 'ibase_service_attach' => ['resource', 'host'=>'string', 'dba_username'=>'string', 'dba_password'=>'string'], 'ibase_service_detach' => ['bool', 'service_handle'=>'resource'], 'ibase_set_event_handler' => ['resource', 'link_identifier'=>'', 'callback'=>'callable', 'event='=>'string', '...args='=>''], 'ibase_set_event_handler\'1' => ['resource', 'callback'=>'callable', 'event'=>'string', '...args'=>''], 'ibase_timefmt' => ['bool', 'format'=>'string', 'columntype='=>'int'], 'ibase_trans' => ['resource', 'trans_args='=>'int', 'link_identifier='=>'', '...args='=>''], 'ibase_wait_event' => ['string', 'link_identifier'=>'', 'event='=>'string', '...args='=>''], 'ibase_wait_event\'1' => ['string', 'event'=>'string', '...args'=>''], 'iconv' => ['string|false', 'in_charset'=>'string', 'out_charset'=>'string', 'str'=>'string'], 'iconv_get_encoding' => ['mixed', 'type='=>'string'], 'iconv_mime_decode' => ['string|false', 'encoded_string'=>'string', 'mode='=>'int', 'charset='=>'string'], 'iconv_mime_decode_headers' => ['array|false', 'headers'=>'string', 'mode='=>'int', 'charset='=>'string'], 'iconv_mime_encode' => ['string|false', 'field_name'=>'string', 'field_value'=>'string', 'preference='=>'array'], 'iconv_set_encoding' => ['bool', 'type'=>'string', 'charset'=>'string'], 'iconv_strlen' => ['0|positive-int|false', 'str'=>'string', 'charset='=>'string'], 'iconv_strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'charset='=>'string'], 'iconv_strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'charset='=>'string'], 'iconv_substr' => ['string|false', 'str'=>'string', 'offset'=>'int', 'length='=>'int', 'charset='=>'string'], 'id3_get_frame_long_name' => ['string', 'frameid'=>'string'], 'id3_get_frame_short_name' => ['string', 'frameid'=>'string'], 'id3_get_genre_id' => ['int', 'genre'=>'string'], 'id3_get_genre_list' => ['array'], 'id3_get_genre_name' => ['string', 'genre_id'=>'int'], 'id3_get_tag' => ['array', 'filename'=>'string', 'version='=>'int'], 'id3_get_version' => ['int', 'filename'=>'string'], 'id3_remove_tag' => ['bool', 'filename'=>'string', 'version='=>'int'], 'id3_set_tag' => ['bool', 'filename'=>'string', 'tag'=>'array', 'version='=>'int'], 'idate' => ['int|false', 'format'=>'string', 'timestamp='=>'int'], 'idn_strerror' => ['string', 'errorcode'=>'int'], 'idn_to_ascii' => ['string|false', 'domain'=>'string', 'options='=>'int', 'variant='=>'int', '&w_idna_info='=>'array'], 'idn_to_utf8' => ['string|false', 'domain'=>'string', 'options='=>'int', 'variant='=>'int', '&w_idna_info='=>'array'], 'ifx_affected_rows' => ['int', 'result_id'=>'resource'], 'ifx_blobinfile_mode' => ['bool', 'mode'=>'int'], 'ifx_byteasvarchar' => ['bool', 'mode'=>'int'], 'ifx_close' => ['bool', 'link_identifier='=>'resource'], 'ifx_connect' => ['resource', 'database='=>'string', 'userid='=>'string', 'password='=>'string'], 'ifx_copy_blob' => ['int', 'bid'=>'int'], 'ifx_create_blob' => ['int', 'type'=>'int', 'mode'=>'int', 'param'=>'string'], 'ifx_create_char' => ['int', 'param'=>'string'], 'ifx_do' => ['bool', 'result_id'=>'resource'], 'ifx_error' => ['string', 'link_identifier='=>'resource'], 'ifx_errormsg' => ['string', 'errorcode='=>'int'], 'ifx_fetch_row' => ['array', 'result_id'=>'resource', 'position='=>'mixed'], 'ifx_fieldproperties' => ['array', 'result_id'=>'resource'], 'ifx_fieldtypes' => ['array', 'result_id'=>'resource'], 'ifx_free_blob' => ['bool', 'bid'=>'int'], 'ifx_free_char' => ['bool', 'bid'=>'int'], 'ifx_free_result' => ['bool', 'result_id'=>'resource'], 'ifx_get_blob' => ['string', 'bid'=>'int'], 'ifx_get_char' => ['string', 'bid'=>'int'], 'ifx_getsqlca' => ['array', 'result_id'=>'resource'], 'ifx_htmltbl_result' => ['int', 'result_id'=>'resource', 'html_table_options='=>'string'], 'ifx_nullformat' => ['bool', 'mode'=>'int'], 'ifx_num_fields' => ['int', 'result_id'=>'resource'], 'ifx_num_rows' => ['int', 'result_id'=>'resource'], 'ifx_pconnect' => ['resource', 'database='=>'string', 'userid='=>'string', 'password='=>'string'], 'ifx_prepare' => ['resource', 'query'=>'string', 'link_identifier'=>'resource', 'cursor_def='=>'int', 'blobidarray='=>'mixed'], 'ifx_query' => ['resource', 'query'=>'string', 'link_identifier'=>'resource', 'cursor_type='=>'int', 'blobidarray='=>'mixed'], 'ifx_textasvarchar' => ['bool', 'mode'=>'int'], 'ifx_update_blob' => ['bool', 'bid'=>'int', 'content'=>'string'], 'ifx_update_char' => ['bool', 'bid'=>'int', 'content'=>'string'], 'ifxus_close_slob' => ['bool', 'bid'=>'int'], 'ifxus_create_slob' => ['int', 'mode'=>'int'], 'ifxus_free_slob' => ['bool', 'bid'=>'int'], 'ifxus_open_slob' => ['int', 'bid'=>'int', 'mode'=>'int'], 'ifxus_read_slob' => ['string', 'bid'=>'int', 'nbytes'=>'int'], 'ifxus_seek_slob' => ['int', 'bid'=>'int', 'mode'=>'int', 'offset'=>'int'], 'ifxus_tell_slob' => ['int', 'bid'=>'int'], 'ifxus_write_slob' => ['int', 'bid'=>'int', 'content'=>'string'], 'igbinary_serialize' => ['string|null', 'value'=>'mixed'], 'igbinary_unserialize' => ['mixed', 'str'=>'string'], 'ignore_user_abort' => ['0|1', 'value='=>'bool'], 'iis_add_server' => ['int', 'path'=>'string', 'comment'=>'string', 'server_ip'=>'string', 'port'=>'int', 'host_name'=>'string', 'rights'=>'int', 'start_server'=>'int'], 'iis_get_dir_security' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string'], 'iis_get_script_map' => ['string', 'server_instance'=>'int', 'virtual_path'=>'string', 'script_extension'=>'string'], 'iis_get_server_by_comment' => ['int', 'comment'=>'string'], 'iis_get_server_by_path' => ['int', 'path'=>'string'], 'iis_get_server_rights' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string'], 'iis_get_service_state' => ['int', 'service_id'=>'string'], 'iis_remove_server' => ['int', 'server_instance'=>'int'], 'iis_set_app_settings' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string', 'application_scope'=>'string'], 'iis_set_dir_security' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string', 'directory_flags'=>'int'], 'iis_set_script_map' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string', 'script_extension'=>'string', 'engine_path'=>'string', 'allow_scripting'=>'int'], 'iis_set_server_rights' => ['int', 'server_instance'=>'int', 'virtual_path'=>'string', 'directory_flags'=>'int'], 'iis_start_server' => ['int', 'server_instance'=>'int'], 'iis_start_service' => ['int', 'service_id'=>'string'], 'iis_stop_server' => ['int', 'server_instance'=>'int'], 'iis_stop_service' => ['int', 'service_id'=>'string'], 'image2wbmp' => ['bool', 'im'=>'resource', 'filename='=>'?string', 'threshold='=>'int'], 'image_type_to_extension' => ['string|false', 'imagetype'=>'int', 'include_dot='=>'bool'], 'image_type_to_mime_type' => ['string', 'imagetype'=>'int'], 'imageaffine' => ['resource|false', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'], 'imageaffineconcat' => ['array', 'm1'=>'array', 'm2'=>'array'], 'imageaffinematrixconcat' => ['array{0:float,1:float,2:float,3:float,4:float,5:float}|false', 'm1'=>'array', 'm2'=>'array'], 'imageaffinematrixget' => ['array{0:float,1:float,2:float,3:float,4:float,5:float}|false', 'type'=>'int', 'options'=>'array|float'], 'imagealphablending' => ['bool', 'im'=>'resource', 'on'=>'bool'], 'imageantialias' => ['bool', 'im'=>'resource', 'on'=>'bool'], 'imagearc' => ['bool', 'im'=>'resource', 'cx'=>'int', 'cy'=>'int', 'w'=>'int', 'h'=>'int', 's'=>'int', 'e'=>'int', 'col'=>'int'], 'imagebmp' => ['bool', 'image'=>'resource', 'to='=>'string|resource|null', 'compressed='=>'bool'], 'imagechar' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'c'=>'string', 'col'=>'int'], 'imagecharup' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'c'=>'string', 'col'=>'int'], 'imagecolorallocate' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolorallocatealpha' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], 'imagecolorat' => ['int<0, max>|false', 'im'=>'resource', 'x'=>'int', 'y'=>'int'], 'imagecolorclosest' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolorclosestalpha' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], 'imagecolorclosesthwb' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolordeallocate' => ['bool', 'im'=>'resource', 'index'=>'int'], 'imagecolorexact' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolorexactalpha' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], 'imagecolormatch' => ['bool', 'im1'=>'resource', 'im2'=>'resource'], 'imagecolorresolve' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'imagecolorresolvealpha' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], 'imagecolorset' => ['void', 'im'=>'resource', 'col'=>'int', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha='=>'int'], 'imagecolorsforindex' => ['array{red: int<0, 255>, green: int<0, 255>, blue: int<0, 255>, alpha: int<0, 127>}', 'im'=>'resource', 'col'=>'int'], 'imagecolorstotal' => ['int<0, 256>', 'im'=>'resource'], 'imagecolortransparent' => ['int', 'im'=>'resource', 'col='=>'int'], 'imageconvolution' => ['bool', 'src_im'=>'resource', 'matrix3x3'=>'array', 'div'=>'float', 'offset'=>'float'], 'imagecopy' => ['bool', 'dst_im'=>'resource', 'src_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'src_w'=>'int', 'src_h'=>'int'], 'imagecopymerge' => ['bool', 'src_im'=>'resource', 'dst_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'src_w'=>'int', 'src_h'=>'int', 'pct'=>'int'], 'imagecopymergegray' => ['bool', 'src_im'=>'resource', 'dst_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'src_w'=>'int', 'src_h'=>'int', 'pct'=>'int'], 'imagecopyresampled' => ['bool', 'dst_im'=>'resource', 'src_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'dst_w'=>'int', 'dst_h'=>'int', 'src_w'=>'int', 'src_h'=>'int'], 'imagecopyresized' => ['bool', 'dst_im'=>'resource', 'src_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'dst_w'=>'int', 'dst_h'=>'int', 'src_w'=>'int', 'src_h'=>'int'], 'imagecreate' => ['__benevolent', 'x_size'=>'int', 'y_size'=>'int'], 'imagecreatefrombmp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd2' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd2part' => ['resource|false', 'filename'=>'string', 'srcx'=>'int', 'srcy'=>'int', 'width'=>'int', 'height'=>'int'], 'imagecreatefromgif' => ['resource|false', 'filename'=>'string'], 'imagecreatefromjpeg' => ['resource|false', 'filename'=>'string'], 'imagecreatefrompng' => ['resource|false', 'filename'=>'string'], 'imagecreatefromstring' => ['resource|false', 'image'=>'string'], 'imagecreatefromwbmp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromwebp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxbm' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxpm' => ['resource|false', 'filename'=>'string'], 'imagecreatetruecolor' => ['__benevolent', 'x_size'=>'int', 'y_size'=>'int'], 'imagecrop' => ['resource|false', 'im'=>'resource', 'rect'=>'array'], 'imagecropauto' => ['resource|false', 'im'=>'resource', 'mode='=>'int', 'threshold='=>'float', 'color='=>'int'], 'imagedashedline' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int', 'col'=>'int'], 'imagedestroy' => ['bool', 'im'=>'resource'], 'imageellipse' => ['bool', 'im'=>'resource', 'cx'=>'int', 'cy'=>'int', 'w'=>'int', 'h'=>'int', 'color'=>'int'], 'imagefill' => ['bool', 'im'=>'resource', 'x'=>'int', 'y'=>'int', 'col'=>'int'], 'imagefilledarc' => ['bool', 'im'=>'resource', 'cx'=>'int', 'cy'=>'int', 'w'=>'int', 'h'=>'int', 's'=>'int', 'e'=>'int', 'col'=>'int', 'style'=>'int'], 'imagefilledellipse' => ['bool', 'im'=>'resource', 'cx'=>'int', 'cy'=>'int', 'w'=>'int', 'h'=>'int', 'color'=>'int'], 'imagefilledpolygon' => ['bool', 'im'=>'resource', 'point'=>'array', 'num_points'=>'int', 'col'=>'int'], 'imagefilledrectangle' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int', 'col'=>'int'], 'imagefilltoborder' => ['bool', 'im'=>'resource', 'x'=>'int', 'y'=>'int', 'border'=>'int', 'col'=>'int'], 'imagefilter' => ['bool', 'src_im'=>'resource', 'filtertype'=>'int', 'arg1='=>'int', 'arg2='=>'int', 'arg3='=>'int', 'arg4='=>'int'], 'imageflip' => ['bool', 'im'=>'resource', 'mode'=>'int'], 'imagefontheight' => ['int', 'font'=>'int'], 'imagefontwidth' => ['int', 'font'=>'int'], 'imageftbbox' => ['array|false', 'size'=>'float', 'angle'=>'float', 'font_file'=>'string', 'text'=>'string', 'extrainfo='=>'array'], 'imagefttext' => ['array|false', 'im'=>'resource', 'size'=>'float', 'angle'=>'float', 'x'=>'int', 'y'=>'int', 'col'=>'int', 'font_file'=>'string', 'text'=>'string', 'extrainfo='=>'array'], 'imagegammacorrect' => ['bool', 'im'=>'resource', 'inputgamma'=>'float', 'outputgamma'=>'float'], 'imagegd' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null'], 'imagegd2' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null', 'chunk_size='=>'int', 'type='=>'int'], 'imagegetclip' => ['array', 'im'=>'resource'], 'imagegif' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null'], 'imagegrabscreen' => ['resource|false'], 'imagegrabwindow' => ['resource|false', 'window_handle'=>'int', 'client_area='=>'int'], 'imageinterlace' => ['int', 'im'=>'resource', 'interlace='=>'int'], 'imageistruecolor' => ['bool', 'im'=>'resource'], 'imagejpeg' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null', 'quality='=>'int'], 'imagelayereffect' => ['bool', 'im'=>'resource', 'effect'=>'int'], 'imageline' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int', 'col'=>'int'], 'imageloadfont' => ['int|false', 'filename'=>'string'], 'imageObj::pasteImage' => ['void', 'srcImg'=>'imageObj', 'transparentColorHex'=>'int', 'dstX'=>'int', 'dstY'=>'int', 'angle'=>'int'], 'imageObj::saveImage' => ['int', 'filename'=>'string', 'oMap'=>'mapObj'], 'imageObj::saveWebImage' => ['string'], 'imageopenpolygon' => ['bool', 'image'=>'resource', 'points'=>'array', 'num_points'=>'int', 'color'=>'int'], 'imagepalettecopy' => ['void', 'dst'=>'resource', 'src'=>'resource'], 'imagepalettetotruecolor' => ['bool', 'src'=>'resource'], 'imagepng' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null', 'quality='=>'int', 'filters='=>'int'], 'imagepolygon' => ['bool', 'im'=>'resource', 'point'=>'array', 'num_points'=>'int', 'col'=>'int'], 'imagepsbbox' => ['array', 'text'=>'string', 'font'=>'', 'size'=>'int', 'space'=>'int', 'tightness'=>'int', 'angle'=>'float'], 'imagepsencodefont' => ['bool', 'font_index'=>'resource', 'encodingfile'=>'string'], 'imagepsextendfont' => ['bool', 'font_index'=>'resource', 'extend'=>'float'], 'imagepsfreefont' => ['bool', 'font_index'=>'resource'], 'imagepsloadfont' => ['resource', 'filename'=>'string'], 'imagepsslantfont' => ['bool', 'font_index'=>'resource', 'slant'=>'float'], 'imagepstext' => ['array', 'image'=>'resource', 'text'=>'string', 'font_index'=>'resource', 'size'=>'int', 'foreground'=>'int', 'background'=>'int', 'x'=>'int', 'y'=>'int', 'space='=>'int', 'tightness='=>'int', 'angle='=>'float', 'antialias_steps='=>'int'], 'imagerectangle' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int', 'col'=>'int'], 'imageresolution' => ['mixed', 'image'=>'resource', 'res_x='=>'int', 'res_y='=>'int'], 'imagerotate' => ['resource|false', 'src_im'=>'resource', 'angle'=>'float', 'bgdcolor'=>'int', 'ignoretransparent='=>'int'], 'imagesavealpha' => ['bool', 'im'=>'resource', 'on'=>'bool'], 'imagescale' => ['resource|false', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'], 'imagesetbrush' => ['bool', 'image'=>'resource', 'brush'=>'resource'], 'imagesetclip' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int'], 'imagesetinterpolation' => ['bool', 'im'=>'resource', 'method'=>'int'], 'imagesetpixel' => ['bool', 'im'=>'resource', 'x'=>'int', 'y'=>'int', 'col'=>'int'], 'imagesetstyle' => ['bool', 'im'=>'resource', 'styles'=>'array'], 'imagesetthickness' => ['bool', 'im'=>'resource', 'thickness'=>'int'], 'imagesettile' => ['bool', 'image'=>'resource', 'tile'=>'resource'], 'imagestring' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'str'=>'string', 'col'=>'int'], 'imagestringup' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'str'=>'string', 'col'=>'int'], 'imagesx' => ['int<1, max>', 'im'=>'resource'], 'imagesy' => ['int<1, max>', 'im'=>'resource'], 'imagetruecolortopalette' => ['bool', 'im'=>'resource', 'ditherflag'=>'bool', 'colorswanted'=>'int'], 'imagettfbbox' => ['array|false', 'size'=>'float', 'angle'=>'float', 'font_file'=>'string', 'text'=>'string'], 'imagettftext' => ['array|false', 'im'=>'resource', 'size'=>'float', 'angle'=>'float', 'x'=>'int', 'y'=>'int', 'col'=>'int', 'font_file'=>'string', 'text'=>'string'], 'imagetypes' => ['int'], 'imagewbmp' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null', 'foreground='=>'int'], 'imagewebp' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null', 'quality='=>'int'], 'imagexbm' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null', 'foreground='=>'int'], 'Imagick::__construct' => ['void', 'files='=>''], 'Imagick::__toString' => ['string'], 'Imagick::adaptiveBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::adaptiveResizeImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'bestfit='=>'bool'], 'Imagick::adaptiveSharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::adaptiveThresholdImage' => ['bool', 'width'=>'int', 'height'=>'int', 'offset'=>'int'], 'Imagick::addImage' => ['bool', 'source'=>'imagick'], 'Imagick::addNoiseImage' => ['bool', 'noise_type'=>'int', 'channel='=>'int'], 'Imagick::affineTransformImage' => ['bool', 'matrix'=>'imagickdraw'], 'Imagick::animateImages' => ['bool', 'x_server'=>'string'], 'Imagick::annotateImage' => ['bool', 'draw_settings'=>'imagickdraw', 'x'=>'float', 'y'=>'float', 'angle'=>'float', 'text'=>'string'], 'Imagick::appendImages' => ['Imagick', 'stack'=>'bool'], 'Imagick::autoGammaImage' => ['bool', 'channel='=>'int'], 'Imagick::autoLevelImage' => ['bool', 'channel='=>'int'], 'Imagick::autoOrient' => ['bool'], 'Imagick::averageImages' => ['Imagick'], 'Imagick::blackThresholdImage' => ['bool', 'threshold'=>'mixed'], 'Imagick::blueShiftImage' => ['bool', 'factor='=>'float'], 'Imagick::blurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::borderImage' => ['bool', 'bordercolor'=>'mixed', 'width'=>'int', 'height'=>'int'], 'Imagick::brightnessContrastImage' => ['bool', 'brightness'=>'float', 'contrast'=>'float', 'channel='=>'int'], 'Imagick::charcoalImage' => ['bool', 'radius'=>'float', 'sigma'=>'float'], 'Imagick::chopImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::clampImage' => ['bool', 'channel='=>'int'], 'Imagick::clear' => ['bool'], 'Imagick::clipImage' => ['bool'], 'Imagick::clipImagePath' => ['void', 'pathname'=>'string', 'inside'=>'string'], 'Imagick::clipPathImage' => ['bool', 'pathname'=>'string', 'inside'=>'bool'], 'Imagick::clone' => ['Imagick'], 'Imagick::clutImage' => ['bool', 'lookup_table'=>'imagick', 'int='=>'float'], 'Imagick::coalesceImages' => ['Imagick'], 'Imagick::colorFloodfillImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int'], 'Imagick::colorizeImage' => ['bool', 'colorize'=>'mixed', 'opacity'=>'mixed'], 'Imagick::colorMatrixImage' => ['bool', 'color_matrix'=>'array'], 'Imagick::combineImages' => ['Imagick', 'channeltype'=>'int'], 'Imagick::commentImage' => ['bool', 'comment'=>'string'], 'Imagick::compareImageChannels' => ['array{Imagick,float}', 'image'=>'imagick', 'channeltype'=>'int', 'metrictype'=>'int'], 'Imagick::compareImageLayers' => ['Imagick', 'method'=>'int'], 'Imagick::compareImages' => ['array{Imagick,float}', 'compare'=>'imagick', 'metric'=>'int'], 'Imagick::compositeImage' => ['bool', 'composite_object'=>'imagick', 'composite'=>'int', 'x'=>'int', 'y'=>'int', 'channel='=>'int'], 'Imagick::compositeImageGravity' => ['bool', 'imagick'=>'Imagick', 'COMPOSITE_CONSTANT'=>'int', 'GRAVITY_CONSTANT'=>'int'], 'Imagick::contrastImage' => ['bool', 'sharpen'=>'bool'], 'Imagick::contrastStretchImage' => ['bool', 'black_point'=>'float', 'white_point'=>'float', 'channel='=>'int'], 'Imagick::convolveImage' => ['bool', 'kernel'=>'array', 'channel='=>'int'], 'Imagick::count' => ['0|positive-int', 'mode='=>'int'], 'Imagick::cropImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::cropThumbnailImage' => ['bool', 'width'=>'int', 'height'=>'int', 'legacy='=>'bool'], 'Imagick::current' => ['Imagick'], 'Imagick::cycleColormapImage' => ['bool', 'displace'=>'int'], 'Imagick::decipherImage' => ['bool', 'passphrase'=>'string'], 'Imagick::deconstructImages' => ['Imagick'], 'Imagick::deleteImageArtifact' => ['bool', 'artifact'=>'string'], 'Imagick::deleteImageProperty' => ['void', 'name'=>'string'], 'Imagick::deskewImage' => ['bool', 'threshold'=>'float'], 'Imagick::despeckleImage' => ['bool'], 'Imagick::destroy' => ['bool'], 'Imagick::displayImage' => ['bool', 'servername'=>'string'], 'Imagick::displayImages' => ['bool', 'servername'=>'string'], 'Imagick::distortImage' => ['bool', 'method'=>'int', 'arguments'=>'array', 'bestfit'=>'bool'], 'Imagick::drawImage' => ['bool', 'draw'=>'imagickdraw'], 'Imagick::edgeImage' => ['bool', 'radius'=>'float'], 'Imagick::embossImage' => ['bool', 'radius'=>'float', 'sigma'=>'float'], 'Imagick::encipherImage' => ['bool', 'passphrase'=>'string'], 'Imagick::enhanceImage' => ['bool'], 'Imagick::equalizeImage' => ['bool'], 'Imagick::evaluateImage' => ['bool', 'op'=>'int', 'constant'=>'float', 'channel='=>'int'], 'Imagick::evaluateImages' => ['bool', 'EVALUATE_CONSTANT'=>'int'], 'Imagick::exportImagePixels' => ['list', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'int'], 'Imagick::extentImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::filter' => ['bool', 'ImagickKernel'=>'ImagickKernel', 'CHANNEL='=>'int'], 'Imagick::flattenImages' => ['Imagick'], 'Imagick::flipImage' => ['bool'], 'Imagick::floodFillPaintImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'target'=>'mixed', 'x'=>'int', 'y'=>'int', 'invert'=>'bool', 'channel='=>'int'], 'Imagick::flopImage' => ['bool'], 'Imagick::forwardFourierTransformimage' => ['bool', 'magnitude'=>'bool'], 'Imagick::frameImage' => ['bool', 'matte_color'=>'mixed', 'width'=>'int', 'height'=>'int', 'inner_bevel'=>'int', 'outer_bevel'=>'int'], 'Imagick::functionImage' => ['bool', 'function'=>'int', 'arguments'=>'array', 'channel='=>'int'], 'Imagick::fxImage' => ['Imagick', 'expression'=>'string', 'channel='=>'int'], 'Imagick::gammaImage' => ['bool', 'gamma'=>'float', 'channel='=>'int'], 'Imagick::gaussianBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::getColorspace' => ['Imagick::COLORSPACE_*'], 'Imagick::getCompression' => ['Imagick::COMPRESSION_*'], 'Imagick::getCompressionQuality' => ['int'], 'Imagick::getConfigureOptions' => ['string'], 'Imagick::getCopyright' => ['string'], 'Imagick::getFeatures' => ['string'], 'Imagick::getFilename' => ['string'], 'Imagick::getFont' => ['string'], 'Imagick::getFormat' => ['string'], 'Imagick::getGravity' => ['Imagick::GRAVITY_*'], 'Imagick::getHDRIEnabled' => ['int'], 'Imagick::getHomeURL' => ['string'], 'Imagick::getImage' => ['Imagick'], 'Imagick::getImageAlphaChannel' => ['bool'], 'Imagick::getImageArtifact' => ['string', 'artifact'=>'string'], 'Imagick::getImageAttribute' => ['string', 'key'=>'string'], 'Imagick::getImageBackgroundColor' => ['ImagickPixel'], 'Imagick::getImageBlob' => ['string'], 'Imagick::getImageBluePrimary' => ['array{x:float,y:float}'], 'Imagick::getImageBorderColor' => ['ImagickPixel'], 'Imagick::getImageChannelDepth' => ['int', 'channel'=>'int'], 'Imagick::getImageChannelDistortion' => ['float', 'reference'=>'imagick', 'channel'=>'int', 'metric'=>'int'], 'Imagick::getImageChannelDistortions' => ['float', 'reference'=>'imagick', 'metric'=>'int', 'channel='=>'int'], 'Imagick::getImageChannelExtrema' => ['array{minima:0|positive-int,maxima:0|positive-int}', 'channel'=>'int'], 'Imagick::getImageChannelKurtosis' => ['array{kurtosis:float,skewness:float}', 'channel='=>'int'], 'Imagick::getImageChannelMean' => ['array{mean:float,standardDeviation:float}', 'channel'=>'int'], 'Imagick::getImageChannelRange' => ['array{minima:float,maxima:float}', 'channel'=>'int'], 'Imagick::getImageChannelStatistics' => ['array{mean:float,minima:float,maxima:float,standardDeviation:float,depth:int}'], 'Imagick::getImageClipMask' => ['Imagick'], 'Imagick::getImageColormapColor' => ['ImagickPixel', 'index'=>'int'], 'Imagick::getImageColors' => ['int'], 'Imagick::getImageColorspace' => ['Imagick::COLORSPACE_*'], 'Imagick::getImageCompose' => ['Imagick::COMPOSITE_*'], 'Imagick::getImageCompression' => ['Imagick::COMPRESSION_*'], 'Imagick::getImageCompressionQuality' => ['int'], 'Imagick::getImageDelay' => ['int'], 'Imagick::getImageDepth' => ['int'], 'Imagick::getImageDispose' => ['Imagick::DISPOSE_*'], 'Imagick::getImageDistortion' => ['float', 'reference'=>'magickwand', 'metric'=>'int'], 'Imagick::getImageExtrema' => ['array{min:0|positive-int,max:0|positive-int}'], 'Imagick::getImageFilename' => ['string'], 'Imagick::getImageFormat' => ['string'], 'Imagick::getImageGamma' => ['float'], 'Imagick::getImageGeometry' => ['array{width:int,height:int}'], 'Imagick::getImageGravity' => ['Imagick::GRAVITY_*'], 'Imagick::getImageGreenPrimary' => ['array{x:float,y:float}'], 'Imagick::getImageHeight' => ['int'], 'Imagick::getImageHistogram' => ['list'], 'Imagick::getImageIndex' => ['int'], 'Imagick::getImageInterlaceScheme' => ['Imagick::INTERLACE_*'], 'Imagick::getImageInterpolateMethod' => ['Imagick::INTERPOLATE_*'], 'Imagick::getImageIterations' => ['int'], 'Imagick::getImageLength' => ['0|positive-int'], 'Imagick::getImageMagickLicense' => ['string'], 'Imagick::getImageMatte' => ['bool'], 'Imagick::getImageMatteColor' => ['ImagickPixel'], 'Imagick::getImageMimeType' => ['non-empty-string'], 'Imagick::getImageOrientation' => ['Imagick::ORIENTATION_*'], 'Imagick::getImagePage' => ['array{width:int,height:int,x:int,y:int}'], 'Imagick::getImagePixelColor' => ['ImagickPixel', 'x'=>'int', 'y'=>'int'], 'Imagick::getImageProfile' => ['string', 'name'=>'string'], 'Imagick::getImageProfiles' => ['array', 'pattern='=>'string', 'only_names='=>'bool'], 'Imagick::getImageProperties' => ['array', 'pattern='=>'string', 'only_names='=>'bool'], 'Imagick::getImageProperty' => ['string', 'name'=>'string'], 'Imagick::getImageRedPrimary' => ['array{x:float,y:float}'], 'Imagick::getImageRegion' => ['Imagick', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::getImageRenderingIntent' => ['Imagick::RENDERINGINTENT_*'], 'Imagick::getImageResolution' => ['array{x:float,y:float}'], 'Imagick::getImagesBlob' => ['string'], 'Imagick::getImageScene' => ['0|positive-int'], 'Imagick::getImageSignature' => ['string'], 'Imagick::getImageSize' => ['0|positive-int'], 'Imagick::getImageTicksPerSecond' => ['0|positive-int'], 'Imagick::getImageTotalInkDensity' => ['float'], 'Imagick::getImageType' => ['Imagick::IMGTYPE_*'], 'Imagick::getImageUnits' => ['int'], 'Imagick::getImageVirtualPixelMethod' => ['int'], 'Imagick::getImageWhitePoint' => ['array{x:float,y:float}'], 'Imagick::getImageWidth' => ['0|positive-int'], 'Imagick::getInterlaceScheme' => ['Imagick::INTERLACE_*'], 'Imagick::getIteratorIndex' => ['int'], 'Imagick::getNumberImages' => ['0|positive-int'], 'Imagick::getOption' => ['string', 'key'=>'string'], 'Imagick::getPackageName' => ['string'], 'Imagick::getPage' => ['array{width:int,height:int,x:int,y:int}'], 'Imagick::getPixelIterator' => ['ImagickPixelIterator'], 'Imagick::getPixelRegionIterator' => ['ImagickPixelIterator', 'x'=>'int', 'y'=>'int', 'columns'=>'int', 'rows'=>'int'], 'Imagick::getPointSize' => ['float'], 'Imagick::getQuantum' => ['0|positive-int'], 'Imagick::getQuantumDepth' => ['array{quantumDepthLong:0|positive-int,quantumDepthString:numeric-string}'], 'Imagick::getQuantumRange' => ['array{quantumRangeLong:0|positive-int,quantumRangeString:numeric-string}'], 'Imagick::getRegistry' => ['string', 'key'=>'string'], 'Imagick::getReleaseDate' => ['string'], 'Imagick::getResource' => ['int', 'type'=>'int'], 'Imagick::getResourceLimit' => ['int', 'type'=>'int'], 'Imagick::getSamplingFactors' => ['list'], 'Imagick::getSize' => ['array{columns:0|positive-int,rows:0|positive-int}'], 'Imagick::getSizeOffset' => ['int'], 'Imagick::getVersion' => ['array{versionNumber:0|positive-int,versionString:non-falsy-string}'], 'Imagick::haldClutImage' => ['bool', 'clut'=>'imagick', 'channel='=>'int'], 'Imagick::hasNextImage' => ['bool'], 'Imagick::hasPreviousImage' => ['bool'], 'Imagick::identifyFormat' => ['string|false', 'embedText'=>'string'], 'Imagick::identifyImage' => ['array{imageName:string,mimetype:string,format:string,units:string,colorSpace:string,type:string,compression:string,fileSize:string,geometry:array{width:0|positive-int,height:0|positive-int},resolution:array{x:float,y:float},signature:string}', 'appendrawoutput='=>'bool'], 'Imagick::identifyImageType' => ['int'], 'Imagick::implodeImage' => ['bool', 'radius'=>'float'], 'Imagick::importImagePixels' => ['bool', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'int', 'pixels'=>'array'], 'Imagick::inverseFourierTransformImage' => ['bool', 'complement'=>'Imagick', 'magnitude'=>'bool'], 'Imagick::key' => ['int|string'], 'Imagick::labelImage' => ['bool', 'label'=>'string'], 'Imagick::levelImage' => ['bool', 'blackpoint'=>'float', 'gamma'=>'float', 'whitepoint'=>'float', 'channel='=>'int'], 'Imagick::linearStretchImage' => ['bool', 'blackpoint'=>'float', 'whitepoint'=>'float'], 'Imagick::liquidRescaleImage' => ['bool', 'width'=>'int', 'height'=>'int', 'delta_x'=>'float', 'rigidity'=>'float'], 'Imagick::listRegistry' => ['array'], 'Imagick::localContrastImage' => ['bool', 'radius'=>'float', 'strength'=>'float'], 'Imagick::magnifyImage' => ['bool'], 'Imagick::mapImage' => ['bool', 'map'=>'imagick', 'dither'=>'bool'], 'Imagick::matteFloodfillImage' => ['bool', 'alpha'=>'float', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int'], 'Imagick::medianFilterImage' => ['bool', 'radius'=>'float'], 'Imagick::mergeImageLayers' => ['Imagick', 'layer_method'=>'int'], 'Imagick::minifyImage' => ['bool'], 'Imagick::modulateImage' => ['bool', 'brightness'=>'float', 'saturation'=>'float', 'hue'=>'float'], 'Imagick::montageImage' => ['Imagick', 'draw'=>'imagickdraw', 'tile_geometry'=>'string', 'thumbnail_geometry'=>'string', 'mode'=>'int', 'frame'=>'string'], 'Imagick::morphImages' => ['Imagick', 'number_frames'=>'int'], 'Imagick::morphology' => ['bool', 'morphologyMethod'=>'int', 'iterations'=>'int', 'ImagickKernel'=>'ImagickKernel', 'channel='=>'int'], 'Imagick::mosaicImages' => ['Imagick'], 'Imagick::motionBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float', 'channel='=>'int'], 'Imagick::negateImage' => ['bool', 'gray'=>'bool', 'channel='=>'int'], 'Imagick::newImage' => ['bool', 'cols'=>'int', 'rows'=>'int', 'background'=>'mixed', 'format='=>'string'], 'Imagick::newPseudoImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'pseudostring'=>'string'], 'Imagick::next' => ['void'], 'Imagick::nextImage' => ['bool'], 'Imagick::normalizeImage' => ['bool', 'channel='=>'int'], 'Imagick::oilPaintImage' => ['bool', 'radius'=>'float'], 'Imagick::opaquePaintImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'invert'=>'bool', 'channel='=>'int'], 'Imagick::optimizeImageLayers' => ['bool'], 'Imagick::orderedPosterizeImage' => ['bool', 'threshold_map'=>'string', 'channel='=>'int'], 'Imagick::paintFloodfillImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int', 'channel='=>'int'], 'Imagick::paintOpaqueImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'channel='=>'int'], 'Imagick::paintTransparentImage' => ['bool', 'target'=>'mixed', 'alpha'=>'float', 'fuzz'=>'float'], 'Imagick::pingImage' => ['bool', 'filename'=>'string'], 'Imagick::pingImageBlob' => ['bool', 'image'=>'string'], 'Imagick::pingImageFile' => ['bool', 'filehandle'=>'resource', 'filename='=>'string'], 'Imagick::polaroidImage' => ['bool', 'properties'=>'imagickdraw', 'angle'=>'float'], 'Imagick::posterizeImage' => ['bool', 'levels'=>'int', 'dither'=>'bool'], 'Imagick::previewImages' => ['bool', 'preview'=>'int'], 'Imagick::previousImage' => ['bool'], 'Imagick::profileImage' => ['bool', 'name'=>'string', 'profile'=>'?string'], 'Imagick::quantizeImage' => ['bool', 'numbercolors'=>'int', 'colorspace'=>'int', 'treedepth'=>'int', 'dither'=>'bool', 'measureerror'=>'bool'], 'Imagick::quantizeImages' => ['bool', 'numbercolors'=>'int', 'colorspace'=>'int', 'treedepth'=>'int', 'dither'=>'bool', 'measureerror'=>'bool'], 'Imagick::queryFontMetrics' => ['array{characterWidth:float,characterHeight:float,ascender:float,descender:float,textWidth:float,textHeight:float,maxHorizontalAdvance:float,boundingBox:array{x1:float,x2:float,y1:float,y2:float},originX:float,originY:float}', 'properties'=>'imagickdraw', 'text'=>'string', 'multiline='=>'bool'], 'Imagick::queryFonts' => ['list', 'pattern='=>'string'], 'Imagick::queryFormats' => ['list', 'pattern='=>'string'], 'Imagick::radialBlurImage' => ['bool', 'angle'=>'float', 'channel='=>'int'], 'Imagick::raiseImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int', 'raise'=>'bool'], 'Imagick::randomThresholdImage' => ['bool', 'low'=>'float', 'high'=>'float', 'channel='=>'int'], 'Imagick::readImage' => ['bool', 'filename'=>'string'], 'Imagick::readImageBlob' => ['bool', 'image'=>'string', 'filename='=>'string'], 'Imagick::readImageFile' => ['bool', 'filehandle'=>'resource', 'filename='=>'string'], 'Imagick::readImages' => ['Imagick', 'filenames'=>'string'], 'Imagick::recolorImage' => ['bool', 'matrix'=>'array'], 'Imagick::reduceNoiseImage' => ['bool', 'radius'=>'float'], 'Imagick::remapImage' => ['bool', 'replacement'=>'imagick', 'dither'=>'int'], 'Imagick::removeImage' => ['bool'], 'Imagick::removeImageProfile' => ['string', 'name'=>'string'], 'Imagick::render' => ['bool'], 'Imagick::resampleImage' => ['bool', 'x_resolution'=>'float', 'y_resolution'=>'float', 'filter'=>'int', 'blur'=>'float'], 'Imagick::resetImagePage' => ['bool', 'page'=>'string'], 'Imagick::resetIterator' => [''], 'Imagick::resizeImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'filter'=>'int', 'blur'=>'float', 'bestfit='=>'bool'], 'Imagick::rewind' => ['void'], 'Imagick::rollImage' => ['bool', 'x'=>'int', 'y'=>'int'], 'Imagick::rotateImage' => ['bool', 'background'=>'mixed', 'degrees'=>'float'], 'Imagick::rotationalBlurImage' => ['bool', 'float'=>'string', 'channel='=>'int'], 'Imagick::roundCorners' => ['bool', 'x_rounding'=>'float', 'y_rounding'=>'float', 'stroke_width='=>'float', 'displace='=>'float', 'size_correction='=>'float'], 'Imagick::roundCornersImage' => ['bool', 'x_rounding'=>'', 'y_rounding'=>'', 'stroke_width='=>'', 'displace='=>'', 'size_correction='=>''], 'Imagick::sampleImage' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::scaleImage' => ['bool', 'cols'=>'int', 'rows'=>'int', 'bestfit='=>'bool', 'legacy='=>'bool'], 'Imagick::segmentImage' => ['bool', 'colorspace'=>'int', 'cluster_threshold'=>'float', 'smooth_threshold'=>'float', 'verbose='=>'bool'], 'Imagick::selectiveBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'threshold'=>'float', 'channel='=>'int'], 'Imagick::separateImageChannel' => ['bool', 'channel'=>'int'], 'Imagick::sepiaToneImage' => ['bool', 'threshold'=>'float'], 'Imagick::setAntiAlias' => ['int', 'antialias'=>'bool'], 'Imagick::setBackgroundColor' => ['bool', 'background'=>'mixed'], 'Imagick::setColorspace' => ['bool', 'colorspace'=>'int'], 'Imagick::setCompression' => ['bool', 'compression'=>'int'], 'Imagick::setCompressionQuality' => ['bool', 'quality'=>'int'], 'Imagick::setFilename' => ['bool', 'filename'=>'string'], 'Imagick::setFirstIterator' => ['bool'], 'Imagick::setFont' => ['bool', 'font'=>'string'], 'Imagick::setFormat' => ['bool', 'format'=>'string'], 'Imagick::setGravity' => ['bool', 'gravity'=>'int'], 'Imagick::setImage' => ['bool', 'replace'=>'imagick'], 'Imagick::setImageAlpha' => ['bool', 'alpha'=>'float'], 'Imagick::setImageAlphaChannel' => ['bool', 'mode'=>'int'], 'Imagick::setImageArtifact' => ['bool', 'artifact'=>'string', 'value'=>'string'], 'Imagick::setImageAttribute' => ['bool', 'key'=>'string', 'value'=>'string'], 'Imagick::setImageBackgroundColor' => ['bool', 'background'=>'mixed'], 'Imagick::setImageBias' => ['bool', 'bias'=>'float'], 'Imagick::setImageBiasQuantum' => ['void', 'bias'=>'string'], 'Imagick::setImageBluePrimary' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setImageBorderColor' => ['bool', 'border'=>'mixed'], 'Imagick::setImageChannelDepth' => ['bool', 'channel'=>'int', 'depth'=>'int'], 'Imagick::setImageChannelMask' => ['', 'channel'=>'int'], 'Imagick::setImageClipMask' => ['bool', 'clip_mask'=>'imagick'], 'Imagick::setImageColormapColor' => ['bool', 'index'=>'int', 'color'=>'imagickpixel'], 'Imagick::setImageColorspace' => ['bool', 'colorspace'=>'int'], 'Imagick::setImageCompose' => ['bool', 'compose'=>'int'], 'Imagick::setImageCompression' => ['bool', 'compression'=>'int'], 'Imagick::setImageCompressionQuality' => ['bool', 'quality'=>'int'], 'Imagick::setImageDelay' => ['bool', 'delay'=>'int'], 'Imagick::setImageDepth' => ['bool', 'depth'=>'int'], 'Imagick::setImageDispose' => ['bool', 'dispose'=>'int'], 'Imagick::setImageExtent' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::setImageFilename' => ['bool', 'filename'=>'string'], 'Imagick::setImageFormat' => ['bool', 'format'=>'string'], 'Imagick::setImageGamma' => ['bool', 'gamma'=>'float'], 'Imagick::setImageGravity' => ['bool', 'gravity'=>'int'], 'Imagick::setImageGreenPrimary' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setImageIndex' => ['bool', 'index'=>'int'], 'Imagick::setImageInterlaceScheme' => ['bool', 'interlace_scheme'=>'int'], 'Imagick::setImageInterpolateMethod' => ['bool', 'method'=>'int'], 'Imagick::setImageIterations' => ['bool', 'iterations'=>'int'], 'Imagick::setImageMatte' => ['bool', 'matte'=>'bool'], 'Imagick::setImageMatteColor' => ['bool', 'matte'=>'mixed'], 'Imagick::setImageOpacity' => ['bool', 'opacity'=>'float'], 'Imagick::setImageOrientation' => ['bool', 'orientation'=>'int'], 'Imagick::setImagePage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::setImageProfile' => ['bool', 'name'=>'string', 'profile'=>'string'], 'Imagick::setImageProgressMonitor' => ['', 'filename'=>''], 'Imagick::setImageProperty' => ['bool', 'name'=>'string', 'value'=>'string'], 'Imagick::setImageRedPrimary' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setImageRenderingIntent' => ['bool', 'rendering_intent'=>'int'], 'Imagick::setImageResolution' => ['bool', 'x_resolution'=>'float', 'y_resolution'=>'float'], 'Imagick::setImageScene' => ['bool', 'scene'=>'int'], 'Imagick::setImageTicksPerSecond' => ['bool', 'ticks_per_second'=>'int'], 'Imagick::setImageType' => ['bool', 'image_type'=>'int'], 'Imagick::setImageUnits' => ['bool', 'units'=>'int'], 'Imagick::setImageVirtualPixelMethod' => ['bool', 'method'=>'int'], 'Imagick::setImageWhitePoint' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setInterlaceScheme' => ['bool', 'interlace_scheme'=>'int'], 'Imagick::setIteratorIndex' => ['bool', 'index'=>'int'], 'Imagick::setLastIterator' => ['bool'], 'Imagick::setOption' => ['bool', 'key'=>'string', 'value'=>'string'], 'Imagick::setPage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::setPointSize' => ['bool', 'point_size'=>'float'], 'Imagick::setProgressMonitor' => ['bool', 'callback'=>'callable'], 'Imagick::setRegistry' => ['bool', 'key'=>'string', 'value'=>'string'], 'Imagick::setResolution' => ['bool', 'x_resolution'=>'float', 'y_resolution'=>'float'], 'Imagick::setResourceLimit' => ['bool', 'type'=>'int', 'limit'=>'int'], 'Imagick::setSamplingFactors' => ['bool', 'factors'=>'array'], 'Imagick::setSize' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::setSizeOffset' => ['bool', 'columns'=>'int', 'rows'=>'int', 'offset'=>'int'], 'Imagick::setType' => ['bool', 'image_type'=>'int'], 'Imagick::shadeImage' => ['bool', 'gray'=>'bool', 'azimuth'=>'float', 'elevation'=>'float'], 'Imagick::shadowImage' => ['bool', 'opacity'=>'float', 'sigma'=>'float', 'x'=>'int', 'y'=>'int'], 'Imagick::sharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], 'Imagick::shaveImage' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::shearImage' => ['bool', 'background'=>'mixed', 'x_shear'=>'float', 'y_shear'=>'float'], 'Imagick::sigmoidalContrastImage' => ['bool', 'sharpen'=>'bool', 'alpha'=>'float', 'beta'=>'float', 'channel='=>'int'], 'Imagick::similarityImage' => ['Imagick', 'imagick'=>'Imagick', '&bestMatch'=>'array', '&similarity'=>'float', 'similarity_threshold'=>'float', 'metric'=>'int'], 'Imagick::sketchImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float'], 'Imagick::smushImages' => ['Imagick', 'stack'=>'bool', 'offset'=>'int'], 'Imagick::solarizeImage' => ['bool', 'threshold'=>'0|positive-int'], 'Imagick::sparseColorImage' => ['bool', 'sparse_method'=>'int', 'arguments'=>'array', 'channel='=>'int'], 'Imagick::spliceImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::spreadImage' => ['bool', 'radius'=>'float'], 'Imagick::statisticImage' => ['bool', 'type'=>'int', 'width'=>'int', 'height'=>'int', 'channel='=>'int'], 'Imagick::steganoImage' => ['Imagick', 'watermark_wand'=>'imagick', 'offset'=>'int'], 'Imagick::stereoImage' => ['bool', 'offset_wand'=>'imagick'], 'Imagick::stripImage' => ['bool'], 'Imagick::subImageMatch' => ['Imagick', 'Imagick'=>'Imagick', '&w_offset='=>'array', '&w_similarity='=>'float'], 'Imagick::swirlImage' => ['bool', 'degrees'=>'float'], 'Imagick::textureImage' => ['Imagick', 'texture_wand'=>'imagick'], 'Imagick::thresholdImage' => ['bool', 'threshold'=>'float', 'channel='=>'int'], 'Imagick::thumbnailImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'bestfit='=>'bool', 'fill='=>'bool', 'legacy='=>'bool'], 'Imagick::tintImage' => ['bool', 'tint'=>'mixed', 'opacity'=>'mixed'], 'Imagick::transformImage' => ['Imagick', 'crop'=>'string', 'geometry'=>'string'], 'Imagick::transformImageColorspace' => ['bool', 'colorspace'=>'int'], 'Imagick::transparentPaintImage' => ['bool', 'target'=>'mixed', 'alpha'=>'float', 'fuzz'=>'float', 'invert'=>'bool'], 'Imagick::transposeImage' => ['bool'], 'Imagick::transverseImage' => ['bool'], 'Imagick::trimImage' => ['bool', 'fuzz'=>'float'], 'Imagick::uniqueImageColors' => ['bool'], 'Imagick::unsharpMaskImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'amount'=>'float', 'threshold'=>'float', 'channel='=>'int'], 'Imagick::valid' => ['bool'], 'Imagick::vignetteImage' => ['bool', 'blackpoint'=>'float', 'whitepoint'=>'float', 'x'=>'int', 'y'=>'int'], 'Imagick::waveImage' => ['bool', 'amplitude'=>'float', 'length'=>'float'], 'Imagick::whiteThresholdImage' => ['bool', 'threshold'=>'mixed'], 'Imagick::writeImage' => ['bool', 'filename='=>'string'], 'Imagick::writeImageFile' => ['bool', 'filehandle'=>'resource', 'format='=>'?string'], 'Imagick::writeImages' => ['bool', 'filename'=>'string', 'adjoin'=>'bool'], 'Imagick::writeImagesFile' => ['bool', 'filehandle'=>'resource', 'format='=>'?string'], 'ImagickDraw::__construct' => ['void'], 'ImagickDraw::affine' => ['bool', 'affine'=>'array'], 'ImagickDraw::annotation' => ['bool', 'x'=>'float', 'y'=>'float', 'text'=>'string'], 'ImagickDraw::arc' => ['bool', 'sx'=>'float', 'sy'=>'float', 'ex'=>'float', 'ey'=>'float', 'sd'=>'float', 'ed'=>'float'], 'ImagickDraw::bezier' => ['bool', 'coordinates'=>'array'], 'ImagickDraw::circle' => ['bool', 'ox'=>'float', 'oy'=>'float', 'px'=>'float', 'py'=>'float'], 'ImagickDraw::clear' => ['bool'], 'ImagickDraw::clone' => ['ImagickDraw'], 'ImagickDraw::color' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'int'], 'ImagickDraw::comment' => ['bool', 'comment'=>'string'], 'ImagickDraw::composite' => ['bool', 'compose'=>'int', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float', 'compositewand'=>'imagick'], 'ImagickDraw::destroy' => ['bool'], 'ImagickDraw::ellipse' => ['bool', 'ox'=>'float', 'oy'=>'float', 'rx'=>'float', 'ry'=>'float', 'start'=>'float', 'end'=>'float'], 'ImagickDraw::getBorderColor' => ['ImagickPixel'], 'ImagickDraw::getClipPath' => ['string'], 'ImagickDraw::getClipRule' => ['int'], 'ImagickDraw::getClipUnits' => ['int'], 'ImagickDraw::getDensity' => ['null|string'], 'ImagickDraw::getFillColor' => ['ImagickPixel'], 'ImagickDraw::getFillOpacity' => ['float'], 'ImagickDraw::getFillRule' => ['Imagick::FILLRULE_*'], 'ImagickDraw::getFont' => ['string'], 'ImagickDraw::getFontFamily' => ['string'], 'ImagickDraw::getFontResolution' => ['array'], 'ImagickDraw::getFontSize' => ['float'], 'ImagickDraw::getFontStretch' => ['Imagick::STRETCH_*'], 'ImagickDraw::getFontStyle' => ['Imagick::STYLE_*'], 'ImagickDraw::getFontWeight' => ['int'], 'ImagickDraw::getGravity' => ['Imagick::GRAVITY_*'], 'ImagickDraw::getOpacity' => ['float'], 'ImagickDraw::getStrokeAntialias' => ['bool'], 'ImagickDraw::getStrokeColor' => ['ImagickPixel'], 'ImagickDraw::getStrokeDashArray' => ['array'], 'ImagickDraw::getStrokeDashOffset' => ['float'], 'ImagickDraw::getStrokeLineCap' => ['Imagick::LINECAP_*'], 'ImagickDraw::getStrokeLineJoin' => ['Imagick::LINEJOIN_*'], 'ImagickDraw::getStrokeMiterLimit' => ['int'], 'ImagickDraw::getStrokeOpacity' => ['float'], 'ImagickDraw::getStrokeWidth' => ['float'], 'ImagickDraw::getTextAlignment' => ['Imagick::ALIGN_*'], 'ImagickDraw::getTextAntialias' => ['bool'], 'ImagickDraw::getTextDecoration' => ['Imagick::DECORATION_*'], 'ImagickDraw::getTextDirection' => ['bool'], 'ImagickDraw::getTextEncoding' => ['string'], 'ImagickDraw::getTextInterlineSpacing' => ['float'], 'ImagickDraw::getTextInterwordSpacing' => ['float'], 'ImagickDraw::getTextKerning' => ['float'], 'ImagickDraw::getTextUnderColor' => ['ImagickPixel'], 'ImagickDraw::getVectorGraphics' => ['string'], 'ImagickDraw::line' => ['bool', 'sx'=>'float', 'sy'=>'float', 'ex'=>'float', 'ey'=>'float'], 'ImagickDraw::matte' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'int'], 'ImagickDraw::pathClose' => ['bool'], 'ImagickDraw::pathCurveToAbsolute' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToQuadraticBezierAbsolute' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToQuadraticBezierRelative' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToQuadraticBezierSmoothAbsolute' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToQuadraticBezierSmoothRelative' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToRelative' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToSmoothAbsolute' => ['bool', 'x2'=>'float', 'y2'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToSmoothRelative' => ['bool', 'x2'=>'float', 'y2'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathEllipticArcAbsolute' => ['bool', 'rx'=>'float', 'ry'=>'float', 'x_axis_rotation'=>'float', 'large_arc_flag'=>'bool', 'sweep_flag'=>'bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathEllipticArcRelative' => ['bool', 'rx'=>'float', 'ry'=>'float', 'x_axis_rotation'=>'float', 'large_arc_flag'=>'bool', 'sweep_flag'=>'bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathFinish' => ['bool'], 'ImagickDraw::pathLineToAbsolute' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathLineToHorizontalAbsolute' => ['bool', 'x'=>'float'], 'ImagickDraw::pathLineToHorizontalRelative' => ['bool', 'x'=>'float'], 'ImagickDraw::pathLineToRelative' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathLineToVerticalAbsolute' => ['bool', 'y'=>'float'], 'ImagickDraw::pathLineToVerticalRelative' => ['bool', 'y'=>'float'], 'ImagickDraw::pathMoveToAbsolute' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathMoveToRelative' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathStart' => ['bool'], 'ImagickDraw::point' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::polygon' => ['bool', 'coordinates'=>'array'], 'ImagickDraw::polyline' => ['bool', 'coordinates'=>'array'], 'ImagickDraw::pop' => ['bool'], 'ImagickDraw::popClipPath' => ['bool'], 'ImagickDraw::popDefs' => ['bool'], 'ImagickDraw::popPattern' => ['bool'], 'ImagickDraw::push' => ['bool'], 'ImagickDraw::pushClipPath' => ['bool', 'clip_mask_id'=>'string'], 'ImagickDraw::pushDefs' => ['bool'], 'ImagickDraw::pushPattern' => ['bool', 'pattern_id'=>'string', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'ImagickDraw::rectangle' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float'], 'ImagickDraw::render' => ['bool'], 'ImagickDraw::resetVectorGraphics' => ['void'], 'ImagickDraw::rotate' => ['bool', 'degrees'=>'float'], 'ImagickDraw::roundRectangle' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'rx'=>'float', 'ry'=>'float'], 'ImagickDraw::scale' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::setBorderColor' => ['bool', 'color'=>'ImagickPixel|string'], 'ImagickDraw::setClipPath' => ['bool', 'clip_mask'=>'string'], 'ImagickDraw::setClipRule' => ['bool', 'fill_rule'=>'int'], 'ImagickDraw::setClipUnits' => ['bool', 'clip_units'=>'int'], 'ImagickDraw::setDensity' => ['bool', 'density_string'=>'string'], 'ImagickDraw::setFillAlpha' => ['bool', 'opacity'=>'float'], 'ImagickDraw::setFillColor' => ['bool', 'fill_pixel'=>'ImagickPixel|string'], 'ImagickDraw::setFillOpacity' => ['bool', 'fillopacity'=>'float'], 'ImagickDraw::setFillPatternURL' => ['bool', 'fill_url'=>'string'], 'ImagickDraw::setFillRule' => ['bool', 'fill_rule'=>'int'], 'ImagickDraw::setFont' => ['bool', 'font_name'=>'string'], 'ImagickDraw::setFontFamily' => ['bool', 'font_family'=>'string'], 'ImagickDraw::setFontResolution' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::setFontSize' => ['bool', 'pointsize'=>'float'], 'ImagickDraw::setFontStretch' => ['bool', 'fontstretch'=>'int'], 'ImagickDraw::setFontStyle' => ['bool', 'style'=>'int'], 'ImagickDraw::setFontWeight' => ['bool', 'font_weight'=>'int'], 'ImagickDraw::setGravity' => ['bool', 'gravity'=>'int'], 'ImagickDraw::setOpacity' => ['void', 'opacity'=>'float'], 'ImagickDraw::setResolution' => ['void', 'x_resolution'=>'float', 'y_resolution'=>'float'], 'ImagickDraw::setStrokeAlpha' => ['bool', 'opacity'=>'float'], 'ImagickDraw::setStrokeAntialias' => ['bool', 'stroke_antialias'=>'bool'], 'ImagickDraw::setStrokeColor' => ['bool', 'stroke_pixel'=>'ImagickPixel|string'], 'ImagickDraw::setStrokeDashArray' => ['bool', 'dasharray'=>'array'], 'ImagickDraw::setStrokeDashOffset' => ['bool', 'dash_offset'=>'float'], 'ImagickDraw::setStrokeLineCap' => ['bool', 'linecap'=>'int'], 'ImagickDraw::setStrokeLineJoin' => ['bool', 'linejoin'=>'int'], 'ImagickDraw::setStrokeMiterLimit' => ['bool', 'miterlimit'=>'int'], 'ImagickDraw::setStrokeOpacity' => ['bool', 'stroke_opacity'=>'float'], 'ImagickDraw::setStrokePatternURL' => ['bool', 'stroke_url'=>'string'], 'ImagickDraw::setStrokeWidth' => ['bool', 'stroke_width'=>'float'], 'ImagickDraw::setTextAlignment' => ['bool', 'alignment'=>'int'], 'ImagickDraw::setTextAntialias' => ['bool', 'antialias'=>'bool'], 'ImagickDraw::setTextDecoration' => ['bool', 'decoration'=>'int'], 'ImagickDraw::setTextDirection' => ['bool', 'direction'=>'int'], 'ImagickDraw::setTextEncoding' => ['bool', 'encoding'=>'string'], 'ImagickDraw::setTextInterlineSpacing' => ['void', 'spacing'=>'float'], 'ImagickDraw::setTextInterwordSpacing' => ['void', 'spacing'=>'float'], 'ImagickDraw::setTextKerning' => ['void', 'kerning'=>'float'], 'ImagickDraw::setTextUnderColor' => ['bool', 'under_color'=>'ImagickPixel|string'], 'ImagickDraw::setVectorGraphics' => ['bool', 'xml'=>'string'], 'ImagickDraw::setViewbox' => ['bool', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int'], 'ImagickDraw::skewX' => ['bool', 'degrees'=>'float'], 'ImagickDraw::skewY' => ['bool', 'degrees'=>'float'], 'ImagickDraw::translate' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickKernel::addKernel' => ['void', 'ImagickKernel'=>'ImagickKernel'], 'ImagickKernel::addUnityKernel' => ['void'], 'ImagickKernel::fromBuiltin' => ['ImagickKernel', 'kernelType'=>'int', 'kernelString'=>'string'], 'ImagickKernel::fromMatrix' => ['ImagickKernel', 'matrix'=>'array', 'origin='=>'array'], 'ImagickKernel::getMatrix' => ['list>'], 'ImagickKernel::scale' => ['void', 'scale'=>'float', 'normalizeFlag'=>'int'], 'ImagickKernel::separate' => ['array'], 'ImagickPixel::__construct' => ['void', 'color='=>'string'], 'ImagickPixel::clear' => ['bool'], 'ImagickPixel::clone' => ['void'], 'ImagickPixel::destroy' => ['bool'], 'ImagickPixel::getColor' => ['array{r: int|float, g: int|float, b: int|float, a: int|float}', 'normalized='=>'0|1|2'], 'ImagickPixel::getColorAsString' => ['string'], 'ImagickPixel::getColorCount' => ['int'], 'ImagickPixel::getColorQuantum' => ['mixed'], 'ImagickPixel::getColorValue' => ['float', 'color'=>'int'], 'ImagickPixel::getColorValueQuantum' => ['mixed'], 'ImagickPixel::getHSL' => ['array'], 'ImagickPixel::getIndex' => ['int'], 'ImagickPixel::isPixelSimilar' => ['bool', 'color'=>'ImagickPixel', 'fuzz'=>'float'], 'ImagickPixel::isPixelSimilarQuantum' => ['bool', 'color'=>'string', 'fuzz='=>'string'], 'ImagickPixel::isSimilar' => ['bool', 'color'=>'imagickpixel', 'fuzz'=>'float'], 'ImagickPixel::setColor' => ['bool', 'color'=>'string'], 'ImagickPixel::setcolorcount' => ['void', 'colorCount'=>'string'], 'ImagickPixel::setColorFromPixel' => ['bool', 'srcPixel'=>'ImagickPixel'], 'ImagickPixel::setColorValue' => ['bool', 'color'=>'int', 'value'=>'float'], 'ImagickPixel::setColorValueQuantum' => ['void', 'color'=>'int', 'value'=>'mixed'], 'ImagickPixel::setHSL' => ['bool', 'hue'=>'float', 'saturation'=>'float', 'luminosity'=>'float'], 'ImagickPixel::setIndex' => ['void', 'index'=>'int'], 'ImagickPixelIterator::__construct' => ['void', 'wand'=>'imagick'], 'ImagickPixelIterator::clear' => ['bool'], 'ImagickPixelIterator::current' => ['mixed'], 'ImagickPixelIterator::destroy' => ['bool'], 'ImagickPixelIterator::getCurrentIteratorRow' => ['array'], 'ImagickPixelIterator::getIteratorRow' => ['int'], 'ImagickPixelIterator::getNextIteratorRow' => ['array'], 'ImagickPixelIterator::getpixeliterator' => ['', 'Imagick'=>'Imagick'], 'ImagickPixelIterator::getpixelregioniterator' => ['', 'Imagick'=>'Imagick', 'x'=>'', 'y'=>'', 'columns'=>'', 'rows'=>''], 'ImagickPixelIterator::getPreviousIteratorRow' => ['array'], 'ImagickPixelIterator::key' => ['int|string'], 'ImagickPixelIterator::newPixelIterator' => ['bool', 'wand'=>'imagick'], 'ImagickPixelIterator::newPixelRegionIterator' => ['bool', 'wand'=>'imagick', 'x'=>'int', 'y'=>'int', 'columns'=>'int', 'rows'=>'int'], 'ImagickPixelIterator::next' => ['void'], 'ImagickPixelIterator::resetIterator' => ['bool'], 'ImagickPixelIterator::rewind' => ['void'], 'ImagickPixelIterator::setIteratorFirstRow' => ['bool'], 'ImagickPixelIterator::setIteratorLastRow' => ['bool'], 'ImagickPixelIterator::setIteratorRow' => ['bool', 'row'=>'int'], 'ImagickPixelIterator::syncIterator' => ['bool'], 'ImagickPixelIterator::valid' => ['bool'], 'imap_8bit' => ['string|false', 'text'=>'string'], 'imap_alerts' => ['array|false'], 'imap_append' => ['bool', 'stream_id'=>'resource', 'folder'=>'string', 'message'=>'string', 'options='=>'string', 'internal_date='=>'string'], 'imap_base64' => ['string|false', 'text'=>'string'], 'imap_binary' => ['string|false', 'text'=>'string'], 'imap_body' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'options='=>'int'], 'imap_bodystruct' => ['stdClass|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'section'=>'string'], 'imap_check' => ['stdClass|false', 'stream_id'=>'resource'], 'imap_clearflag_full' => ['bool', 'stream_id'=>'resource', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], 'imap_close' => ['bool', 'stream_id'=>'resource', 'options='=>'int'], 'imap_create' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_createmailbox' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_delete' => ['bool', 'stream_id'=>'resource', 'msg_no'=>'string', 'options='=>'int'], 'imap_deletemailbox' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_errors' => ['array|false'], 'imap_expunge' => ['bool', 'stream_id'=>'resource'], 'imap_fetch_overview' => ['array|false', 'stream_id'=>'resource', 'sequence'=>'string', 'options='=>'int'], 'imap_fetchbody' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'section'=>'string', 'options='=>'int'], 'imap_fetchheader' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'options='=>'int'], 'imap_fetchmime' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'section'=>'string', 'options='=>'int'], 'imap_fetchstructure' => ['stdClass|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'options='=>'int'], 'imap_fetchtext' => ['string|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'options='=>'int'], 'imap_gc' => ['bool', 'stream_id'=>'resource', 'flags'=>'int'], 'imap_get_quota' => ['array|false', 'stream_id'=>'resource', 'qroot'=>'string'], 'imap_get_quotaroot' => ['array|false', 'stream_id'=>'resource', 'mbox'=>'string'], 'imap_getacl' => ['array|false', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_getmailboxes' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_getsubscribed' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_header' => ['stdClass|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'from_length='=>'int', 'subject_length='=>'int', 'default_host='=>'string'], 'imap_headerinfo' => ['stdClass|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'from_length='=>'int', 'subject_length='=>'int', 'default_host='=>'string|null'], 'imap_headers' => ['array|false', 'stream_id'=>'resource'], 'imap_last_error' => ['string|false'], 'imap_list' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_listmailbox' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_listscan' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string', 'content'=>'string'], 'imap_listsubscribed' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_lsub' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string'], 'imap_mail' => ['bool', 'to'=>'string', 'subject'=>'string', 'message'=>'string', 'additional_headers='=>'string', 'cc='=>'string', 'bcc='=>'string', 'rpath='=>'string'], 'imap_mail_compose' => ['string|false', 'envelope'=>'array', 'body'=>'array'], 'imap_mail_copy' => ['bool', 'stream_id'=>'resource', 'msglist'=>'string', 'mailbox'=>'string', 'options='=>'int'], 'imap_mail_move' => ['bool', 'stream_id'=>'resource', 'sequence'=>'string', 'mailbox'=>'string', 'options='=>'int'], 'imap_mailboxmsginfo' => ['stdClass|false', 'stream_id'=>'resource'], 'imap_mime_header_decode' => ['array|false', 'str'=>'string'], 'imap_msgno' => ['int|false', 'stream_id'=>'resource', 'unique_msg_id'=>'int'], 'imap_mutf7_to_utf8' => ['string|false', 'in'=>'string'], 'imap_num_msg' => ['int|false', 'stream_id'=>'resource'], 'imap_num_recent' => ['int|false', 'stream_id'=>'resource'], 'imap_open' => ['resource|false', 'mailbox'=>'string', 'user'=>'string', 'password'=>'string', 'options='=>'int', 'n_retries='=>'int', 'params='=>'array|null'], 'imap_ping' => ['bool', 'stream_id'=>'resource'], 'imap_qprint' => ['string|false', 'text'=>'string'], 'imap_rename' => ['bool', 'stream_id'=>'resource', 'old_name'=>'string', 'new_name'=>'string'], 'imap_renamemailbox' => ['bool', 'stream_id'=>'resource', 'old_name'=>'string', 'new_name'=>'string'], 'imap_reopen' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string', 'options='=>'int', 'n_retries='=>'int'], 'imap_rfc822_parse_adrlist' => ['array', 'address_string'=>'string', 'default_host'=>'string'], 'imap_rfc822_parse_headers' => ['stdClass', 'headers'=>'string', 'default_host='=>'string'], 'imap_rfc822_write_address' => ['string|false', 'mailbox'=>'?string', 'host'=>'?string', 'personal'=>'?string'], 'imap_savebody' => ['bool', 'stream_id'=>'resource', 'file'=>'string|resource', 'msg_no'=>'int', 'section='=>'string', 'options='=>'int'], 'imap_scan' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string', 'content'=>'string'], 'imap_scanmailbox' => ['array|false', 'stream_id'=>'resource', 'ref'=>'string', 'pattern'=>'string', 'content'=>'string'], 'imap_search' => ['array|false', 'stream_id'=>'resource', 'criteria'=>'string', 'options='=>'int', 'charset='=>'string'], 'imap_set_quota' => ['bool', 'stream_id'=>'resource', 'qroot'=>'string', 'mailbox_size'=>'int'], 'imap_setacl' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string', 'id'=>'string', 'rights'=>'string'], 'imap_setflag_full' => ['bool', 'stream_id'=>'resource', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'], 'imap_sort' => ['array|false', 'stream_id'=>'resource', 'criteria'=>'int', 'reverse'=>'int', 'options='=>'int', 'search_criteria='=>'string', 'charset='=>'string'], 'imap_status' => ['stdClass|false', 'stream_id'=>'resource', 'mailbox'=>'string', 'options'=>'int'], 'imap_subscribe' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_thread' => ['array|false', 'stream_id'=>'resource', 'options='=>'int'], 'imap_timeout' => ['mixed', 'timeout_type'=>'int', 'timeout='=>'int'], 'imap_uid' => ['int|false', 'stream_id'=>'resource', 'msg_no'=>'int'], 'imap_undelete' => ['bool', 'stream_id'=>'resource', 'msg_no'=>'string', 'flags='=>'int'], 'imap_unsubscribe' => ['bool', 'stream_id'=>'resource', 'mailbox'=>'string'], 'imap_utf7_decode' => ['string|false', 'buf'=>'string'], 'imap_utf7_encode' => ['string', 'buf'=>'string'], 'imap_utf8' => ['string', 'mime_encoded_text'=>'string'], 'imap_utf8_to_mutf7' => ['string|false', 'in'=>'string'], 'implode' => ['string', 'glue'=>'string', 'pieces'=>'array'], 'implode\'1' => ['string', 'pieces'=>'array'], 'implode\'2' => ['string', 'pieces'=>'array', 'glue'=>'string'], 'import_request_variables' => ['bool', 'types'=>'string', 'prefix='=>'string'], 'in_array' => ['bool', 'needle'=>'mixed', 'haystack'=>'array', 'strict='=>'bool'], 'inclued_get_data' => ['array'], 'inet_ntop' => ['string|false', 'in_addr'=>'string'], 'inet_pton' => ['string|false', 'ip_address'=>'string'], 'InfiniteIterator::__construct' => ['void', 'iterator'=>'Iterator'], 'InfiniteIterator::next' => ['void'], 'inflate_add' => ['string|false', 'context'=>'resource', 'encoded_data'=>'string', 'flush_mode='=>'int'], 'inflate_get_read_len' => ['int|false', 'resource'=>'resource'], 'inflate_get_status' => ['int|false', 'resource'=>'resource'], 'inflate_init' => ['resource|false', 'encoding'=>'int', 'options='=>'array'], 'ingres_autocommit' => ['bool', 'link'=>'resource'], 'ingres_autocommit_state' => ['bool', 'link'=>'resource'], 'ingres_charset' => ['string', 'link'=>'resource'], 'ingres_close' => ['bool', 'link'=>'resource'], 'ingres_commit' => ['bool', 'link'=>'resource'], 'ingres_connect' => ['resource', 'database='=>'string', 'username='=>'string', 'password='=>'string', 'options='=>'array'], 'ingres_cursor' => ['string', 'result'=>'resource'], 'ingres_errno' => ['int', 'link='=>'resource'], 'ingres_error' => ['string', 'link='=>'resource'], 'ingres_errsqlstate' => ['string', 'link='=>'resource'], 'ingres_escape_string' => ['string', 'link'=>'resource', 'source_string'=>'string'], 'ingres_execute' => ['bool', 'result'=>'resource', 'params='=>'array', 'types='=>'string'], 'ingres_fetch_array' => ['array', 'result'=>'resource', 'result_type='=>'int'], 'ingres_fetch_assoc' => ['array', 'result'=>'resource'], 'ingres_fetch_object' => ['object', 'result'=>'resource', 'result_type='=>'int'], 'ingres_fetch_proc_return' => ['int', 'result'=>'resource'], 'ingres_fetch_row' => ['array', 'result'=>'resource'], 'ingres_field_length' => ['int', 'result'=>'resource', 'index'=>'int'], 'ingres_field_name' => ['string', 'result'=>'resource', 'index'=>'int'], 'ingres_field_nullable' => ['bool', 'result'=>'resource', 'index'=>'int'], 'ingres_field_precision' => ['int', 'result'=>'resource', 'index'=>'int'], 'ingres_field_scale' => ['int', 'result'=>'resource', 'index'=>'int'], 'ingres_field_type' => ['string', 'result'=>'resource', 'index'=>'int'], 'ingres_free_result' => ['bool', 'result'=>'resource'], 'ingres_next_error' => ['bool', 'link='=>'resource'], 'ingres_num_fields' => ['int', 'result'=>'resource'], 'ingres_num_rows' => ['int', 'result'=>'resource'], 'ingres_pconnect' => ['resource', 'database='=>'string', 'username='=>'string', 'password='=>'string', 'options='=>'array'], 'ingres_prepare' => ['mixed', 'link'=>'resource', 'query'=>'string'], 'ingres_query' => ['mixed', 'link'=>'resource', 'query'=>'string', 'params='=>'array', 'types='=>'string'], 'ingres_result_seek' => ['bool', 'result'=>'resource', 'position'=>'int'], 'ingres_rollback' => ['bool', 'link'=>'resource'], 'ingres_set_environment' => ['bool', 'link'=>'resource', 'options'=>'array'], 'ingres_unbuffered_query' => ['mixed', 'link'=>'resource', 'query'=>'string', 'params='=>'array', 'types='=>'string'], 'ini_alter' => ['string|false', 'varname'=>'string', 'newvalue'=>'string'], 'ini_get' => ['string|false', 'varname'=>'string'], 'ini_get_all' => ['array|false', 'extension='=>'?string', 'details='=>'bool'], 'ini_restore' => ['void', 'varname'=>'string'], 'ini_set' => ['string|false', 'varname'=>'string', 'newvalue'=>'string'], 'inotify_add_watch' => ['int<1,max>|false', 'inotify_instance'=>'resource', 'pathname'=>'string', 'mask'=>'int'], 'inotify_init' => ['resource'], 'inotify_queue_len' => ['int<0,max>', 'inotify_instance'=>'resource'], 'inotify_read' => ['list,mask:int<0,max>,cookie:int<0,max>,name:string}>|false', 'inotify_instance'=>'resource'], 'inotify_rm_watch' => ['bool', 'inotify_instance'=>'resource', 'watch_descriptor'=>'int'], 'intdiv' => ['int', 'numerator'=>'int', 'divisor'=>'int'], 'interface_exists' => ['bool', 'classname'=>'string', 'autoload='=>'bool'], 'intl_error_name' => ['string', 'error_code'=>'int'], 'intl_get_error_code' => ['int'], 'intl_get_error_message' => ['string'], 'intl_is_failure' => ['bool', 'error_code'=>'int'], 'IntlBreakIterator::__construct' => ['void'], 'IntlBreakIterator::createCharacterInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::createCodePointInstance' => ['IntlCodePointBreakIterator'], 'IntlBreakIterator::createLineInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::createSentenceInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::createTitleInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::createWordInstance' => ['IntlRuleBasedBreakIterator', 'locale='=>'string'], 'IntlBreakIterator::current' => ['int'], 'IntlBreakIterator::first' => ['int'], 'IntlBreakIterator::following' => ['int', 'offset'=>'int'], 'IntlBreakIterator::getErrorCode' => ['int'], 'IntlBreakIterator::getErrorMessage' => ['string'], 'IntlBreakIterator::getLocale' => ['string', 'locale_type'=>'string'], 'IntlBreakIterator::getPartsIterator' => ['IntlPartsIterator', 'key_type='=>'IntlPartsIterator::KEY_*'], 'IntlBreakIterator::getText' => ['string'], 'IntlBreakIterator::isBoundary' => ['bool', 'offset'=>'int'], 'IntlBreakIterator::last' => ['int'], 'IntlBreakIterator::next' => ['int', 'offset='=>'int'], 'IntlBreakIterator::preceding' => ['int', 'offset'=>'int'], 'IntlBreakIterator::previous' => ['int'], 'IntlBreakIterator::setText' => ['bool', 'text'=>'string'], 'intlcal_add' => ['bool', 'cal'=>'IntlCalendar', 'field'=>'int', 'amount'=>'int'], 'intlcal_after' => ['bool', 'cal'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_before' => ['bool', 'cal'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_clear' => ['bool', 'cal'=>'IntlCalendar', 'field='=>'int'], 'intlcal_create_instance' => ['IntlCalendar', 'timeZone='=>'mixed', 'locale='=>'string'], 'intlcal_equals' => ['bool', 'cal'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_field_difference' => ['int', 'cal'=>'IntlCalendar', 'when'=>'float', 'field'=>'int'], 'intlcal_from_date_time' => ['IntlCalendar', 'dateTime'=>'DateTime|string'], 'intlcal_get' => ['int', 'cal'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_actual_maximum' => ['int', 'cal'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_actual_minimum' => ['int', 'cal'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_available_locales' => ['array'], 'intlcal_get_day_of_week_type' => ['int', 'cal'=>'IntlCalendar', 'dayOfWeek'=>'int'], 'intlcal_get_first_day_of_week' => ['int', 'cal'=>'IntlCalendar'], 'intlcal_get_greatest_minimum' => ['int', 'cal'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_keyword_values_for_locale' => ['Iterator|false', 'key'=>'string', 'locale'=>'string', 'commonlyUsed'=>'bool'], 'intlcal_get_least_maximum' => ['int', 'cal'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_locale' => ['string', 'cal'=>'IntlCalendar', 'localeType'=>'int'], 'intlcal_get_maximum' => ['int', 'cal'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_minimal_days_in_first_week' => ['int', 'cal'=>'IntlCalendar'], 'intlcal_get_minimum' => ['int', 'cal'=>'IntlCalendar', 'field'=>'int'], 'intlcal_get_now' => ['float'], 'intlcal_get_repeated_wall_time_option' => ['int', 'cal'=>'IntlCalendar'], 'intlcal_get_skipped_wall_time_option' => ['int', 'cal'=>'IntlCalendar'], 'intlcal_get_time' => ['float', 'cal'=>'IntlCalendar'], 'intlcal_get_time_zone' => ['IntlTimeZone|false', 'cal'=>'IntlCalendar'], 'intlcal_get_type' => ['string', 'cal'=>'IntlCalendar'], 'intlcal_get_weekend_transition' => ['int', 'cal'=>'IntlCalendar', 'dayOfWeek'=>'string'], 'intlcal_in_daylight_time' => ['bool', 'cal'=>'IntlCalendar'], 'intlcal_is_equivalent_to' => ['bool', 'cal'=>'IntlCalendar', 'other'=>'IntlCalendar'], 'intlcal_is_lenient' => ['bool', 'cal'=>'IntlCalendar'], 'intlcal_is_set' => ['bool', 'cal'=>'IntlCalendar', 'field'=>'int'], 'intlcal_is_weekend' => ['bool', 'cal'=>'IntlCalendar', 'date='=>'float'], 'intlcal_roll' => ['bool', 'cal'=>'IntlCalendar', 'field'=>'int', 'amountOrUpOrDown'=>'mixed'], 'intlcal_set' => ['bool', 'cal'=>'IntlCalendar', 'field'=>'int', 'value'=>'int'], 'intlcal_set\'1' => ['bool', 'cal'=>'IntlCalendar', 'year'=>'int', 'month'=>'int', 'dayOfMonth='=>'int', 'hour='=>'int', 'minute='=>'int', 'second='=>'int'], 'intlcal_set_first_day_of_week' => ['bool', 'cal'=>'IntlCalendar', 'dayOfWeek'=>'int'], 'intlcal_set_lenient' => ['bool', 'cal'=>'IntlCalendar', 'isLenient'=>'bool'], 'intlcal_set_repeated_wall_time_option' => ['bool', 'cal'=>'IntlCalendar', 'wallTimeOption'=>'int'], 'intlcal_set_skipped_wall_time_option' => ['bool', 'cal'=>'IntlCalendar', 'wallTimeOption'=>'int'], 'intlcal_set_time' => ['bool', 'cal'=>'IntlCalendar', 'date'=>'float'], 'intlcal_set_time_zone' => ['bool', 'cal'=>'IntlCalendar', 'timeZone'=>'mixed'], 'intlcal_to_date_time' => ['DateTime|false', 'cal'=>'IntlCalendar'], 'IntlCalendar::__construct' => ['void'], 'IntlCalendar::add' => ['bool', 'field'=>'int', 'amount'=>'int'], 'IntlCalendar::after' => ['bool', 'other'=>'IntlCalendar'], 'IntlCalendar::before' => ['bool', 'other'=>'IntlCalendar'], 'IntlCalendar::clear' => ['bool', 'field='=>'int'], 'IntlCalendar::createInstance' => ['IntlCalendar', 'timeZone='=>'mixed', 'locale='=>'string'], 'IntlCalendar::equals' => ['bool', 'other'=>'IntlCalendar'], 'IntlCalendar::fieldDifference' => ['int', 'when'=>'float', 'field'=>'int'], 'IntlCalendar::fromDateTime' => ['IntlCalendar', 'dateTime'=>'DateTime|string'], 'IntlCalendar::get' => ['int', 'field'=>'int'], 'IntlCalendar::getActualMaximum' => ['int', 'field'=>'int'], 'IntlCalendar::getActualMinimum' => ['int', 'field'=>'int'], 'IntlCalendar::getAvailableLocales' => ['array'], 'IntlCalendar::getDayOfWeekType' => ['int', 'dayOfWeek'=>'int'], 'IntlCalendar::getErrorCode' => ['int'], 'IntlCalendar::getErrorMessage' => ['string'], 'IntlCalendar::getFirstDayOfWeek' => ['int'], 'IntlCalendar::getGreatestMinimum' => ['int', 'field'=>'int'], 'IntlCalendar::getKeywordValuesForLocale' => ['Iterator', 'key'=>'string', 'locale'=>'string', 'commonlyUsed'=>'bool'], 'IntlCalendar::getLeastMaximum' => ['int', 'field'=>'int'], 'IntlCalendar::getLocale' => ['string', 'localeType'=>'int'], 'IntlCalendar::getMaximum' => ['int', 'field'=>'int'], 'IntlCalendar::getMinimalDaysInFirstWeek' => ['int'], 'IntlCalendar::getMinimum' => ['int', 'field'=>'int'], 'IntlCalendar::getNow' => ['float'], 'IntlCalendar::getRepeatedWallTimeOption' => ['int'], 'IntlCalendar::getSkippedWallTimeOption' => ['int'], 'IntlCalendar::getTime' => ['float'], 'IntlCalendar::getTimeZone' => ['IntlTimeZone'], 'IntlCalendar::getType' => ['string'], 'IntlCalendar::getWeekendTransition' => ['int', 'dayOfWeek'=>'string'], 'IntlCalendar::inDaylightTime' => ['bool'], 'IntlCalendar::isEquivalentTo' => ['bool', 'other'=>'IntlCalendar'], 'IntlCalendar::isLenient' => ['bool'], 'IntlCalendar::isSet' => ['bool', 'field'=>'int'], 'IntlCalendar::isWeekend' => ['bool', 'date='=>'float'], 'IntlCalendar::roll' => ['bool', 'field'=>'int', 'amountOrUpOrDown'=>'mixed'], 'IntlCalendar::set' => ['bool', 'field'=>'int', 'value'=>'int'], 'IntlCalendar::set\'1' => ['bool', 'year'=>'int', 'month'=>'int', 'dayOfMonth='=>'int', 'hour='=>'int', 'minute='=>'int', 'second='=>'int'], 'IntlCalendar::setFirstDayOfWeek' => ['bool', 'dayOfWeek'=>'int'], 'IntlCalendar::setLenient' => ['bool', 'isLenient'=>'string'], 'IntlCalendar::setMinimalDaysInFirstWeek' => ['bool', 'minimalDays'=>'int'], 'IntlCalendar::setRepeatedWallTimeOption' => ['bool', 'wallTimeOption'=>'int'], 'IntlCalendar::setSkippedWallTimeOption' => ['bool', 'wallTimeOption'=>'int'], 'IntlCalendar::setTime' => ['bool', 'date'=>'float'], 'IntlCalendar::setTimeZone' => ['bool', 'timeZone'=>'mixed'], 'IntlCalendar::toDateTime' => ['DateTime'], 'IntlChar::charAge' => ['array', 'char'=>'int|string'], 'IntlChar::charDigitValue' => ['int', 'codepoint'=>'mixed'], 'IntlChar::charDirection' => ['int', 'codepoint'=>'mixed'], 'IntlChar::charFromName' => ['int', 'name'=>'string', 'namechoice='=>'int'], 'IntlChar::charMirror' => ['mixed', 'codepoint'=>'mixed'], 'IntlChar::charName' => ['string', 'char'=>'int|string', 'namechoice='=>'int'], 'IntlChar::charType' => ['int', 'codepoint'=>'mixed'], 'IntlChar::chr' => ['string', 'codepoint'=>'mixed'], 'IntlChar::digit' => ['int', 'char'=>'int|string', 'radix='=>'int'], 'IntlChar::enumCharNames' => ['void', 'start'=>'mixed', 'limit'=>'mixed', 'callback'=>'callable', 'nameChoice='=>'int'], 'IntlChar::enumCharTypes' => ['void', 'cb='=>'callable'], 'IntlChar::foldCase' => ['int|string', 'char'=>'int|string', 'options='=>'int'], 'IntlChar::forDigit' => ['int', 'digit'=>'int', 'radix'=>'int'], 'IntlChar::getBidiPairedBracket' => ['mixed', 'codepoint'=>'mixed'], 'IntlChar::getBlockCode' => ['int', 'char'=>'int|string'], 'IntlChar::getCombiningClass' => ['int', 'codepoint'=>'mixed'], 'IntlChar::getFC_NFKC_Closure' => ['string', 'char'=>'int|string'], 'IntlChar::getIntPropertyMaxValue' => ['int', 'property'=>'int'], 'IntlChar::getIntPropertyMinValue' => ['int', 'property'=>'int'], 'IntlChar::getIntPropertyMxValue' => ['int', 'property'=>'int'], 'IntlChar::getIntPropertyValue' => ['int', 'char'=>'int|string', 'property'=>'int'], 'IntlChar::getNumericValue' => ['float', 'char'=>'int|string'], 'IntlChar::getPropertyEnum' => ['int', 'alias'=>'string'], 'IntlChar::getPropertyName' => ['string', 'property'=>'int', 'namechoice='=>'int'], 'IntlChar::getPropertyValueEnum' => ['int', 'property'=>'int', 'name'=>'string'], 'IntlChar::getPropertyValueName' => ['string', 'prop'=>'int', 'val'=>'int', 'namechoice='=>'int'], 'IntlChar::getUnicodeVersion' => ['array'], 'IntlChar::hasBinaryProperty' => ['bool', 'char'=>'int|string', 'property'=>'int'], 'IntlChar::isalnum' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isalpha' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isbase' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isblank' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::iscntrl' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isdefined' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isdigit' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isgraph' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isIDIgnorable' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isIDPart' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isIDStart' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isISOControl' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isJavaIDPart' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isJavaIDStart' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isJavaSpaceChar' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::islower' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isMirrored' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isprint' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::ispunct' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isspace' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::istitle' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isUAlphabetic' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isULowercase' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isupper' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isUUppercase' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isUWhiteSpace' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isWhitespace' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::isxdigit' => ['bool', 'codepoint'=>'mixed'], 'IntlChar::ord' => ['int', 'character'=>'mixed'], 'IntlChar::tolower' => ['mixed', 'codepoint'=>'mixed'], 'IntlChar::totitle' => ['mixed', 'codepoint'=>'mixed'], 'IntlChar::toupper' => ['mixed', 'codepoint'=>'mixed'], 'IntlCodePointBreakIterator::getLastCodePoint' => ['int'], 'IntlDateFormatter::__construct' => ['void', 'locale'=>'?string', 'datetype'=>'?int', 'timetype'=>'?int', 'timezone='=>'null|string|IntlTimeZone|DateTimeZone', 'calendar='=>'null|int|IntlCalendar', 'pattern='=>'string'], 'IntlDateFormatter::create' => ['IntlDateFormatter|null', 'locale'=>'?string', 'datetype'=>'?int', 'timetype'=>'?int', 'timezone='=>'null|string|IntlTimeZone|DateTimeZone', 'calendar='=>'int|IntlCalendar', 'pattern='=>'string'], 'IntlDateFormatter::format' => ['string|false', 'args'=>''], 'IntlDateFormatter::formatObject' => ['string|false', 'object'=>'object', 'format='=>'mixed', 'locale='=>'string'], 'IntlDateFormatter::getCalendar' => ['int|false'], 'IntlDateFormatter::getCalendarObject' => ['IntlCalendar|false|null'], 'IntlDateFormatter::getDateType' => ['int|false'], 'IntlDateFormatter::getErrorCode' => ['int'], 'IntlDateFormatter::getErrorMessage' => ['string'], 'IntlDateFormatter::getLocale' => ['string|false'], 'IntlDateFormatter::getPattern' => ['string|false'], 'IntlDateFormatter::getTimeType' => ['int|false'], 'IntlDateFormatter::getTimeZone' => ['IntlTimeZone|false'], 'IntlDateFormatter::getTimeZoneId' => ['string|false'], 'IntlDateFormatter::isLenient' => ['bool'], 'IntlDateFormatter::localtime' => ['array|false', 'text_to_parse'=>'string', '&w_parse_pos='=>'int'], 'IntlDateFormatter::parse' => ['int|float|false', 'text_to_parse'=>'string', '&w_parse_pos='=>'int'], 'IntlDateFormatter::setCalendar' => ['bool', 'calendar'=>''], 'IntlDateFormatter::setLenient' => ['void', 'lenient'=>'bool'], 'IntlDateFormatter::setPattern' => ['bool', 'pattern'=>'string'], 'IntlDateFormatter::setTimeZone' => ['bool', 'timezone'=>''], 'IntlDateFormatter::setTimeZoneId' => ['bool', 'zone'=>'string', 'fmt='=>'IntlDateFormatter'], 'IntlGregorianCalendar::getGregorianChange' => ['float'], 'IntlGregorianCalendar::isLeapYear' => ['bool', 'year'=>'int'], 'IntlGregorianCalendar::setGregorianChange' => ['bool', 'date'=>'float'], 'IntlIterator::current' => ['mixed'], 'IntlIterator::key' => ['string'], 'IntlIterator::next' => ['void'], 'IntlIterator::rewind' => ['void'], 'IntlIterator::valid' => ['bool'], 'IntlPartsIterator::current' => ['non-empty-string'], 'IntlPartsIterator::getBreakIterator' => ['IntlBreakIterator'], 'IntlRuleBasedBreakIterator::__construct' => ['void', 'rules'=>'string', 'areCompiled='=>'string'], 'IntlRuleBasedBreakIterator::createCharacterInstance' => ['IntlRuleBasedBreakIterator', 'locale'=>'string'], 'IntlRuleBasedBreakIterator::createCodePointInstance' => ['IntlCodePointBreakIterator'], 'IntlRuleBasedBreakIterator::createLineInstance' => ['IntlRuleBasedBreakIterator', 'locale'=>'string'], 'IntlRuleBasedBreakIterator::createSentenceInstance' => ['IntlRuleBasedBreakIterator', 'locale'=>'string'], 'IntlRuleBasedBreakIterator::createTitleInstance' => ['IntlRuleBasedBreakIterator', 'locale'=>'string'], 'IntlRuleBasedBreakIterator::createWordInstance' => ['IntlRuleBasedBreakIterator', 'locale'=>'string'], 'IntlRuleBasedBreakIterator::current' => ['int'], 'IntlRuleBasedBreakIterator::first' => ['int'], 'IntlRuleBasedBreakIterator::following' => ['int', 'offset'=>'int'], 'IntlRuleBasedBreakIterator::getBinaryRules' => ['string'], 'IntlRuleBasedBreakIterator::getErrorCode' => ['int'], 'IntlRuleBasedBreakIterator::getErrorMessage' => ['string'], 'IntlRuleBasedBreakIterator::getLocale' => ['string', 'locale_type'=>'string'], 'IntlRuleBasedBreakIterator::getPartsIterator' => ['IntlPartsIterator', 'key_type='=>'int'], 'IntlRuleBasedBreakIterator::getRules' => ['string'], 'IntlRuleBasedBreakIterator::getRuleStatus' => ['int'], 'IntlRuleBasedBreakIterator::getRuleStatusVec' => ['array'], 'IntlRuleBasedBreakIterator::getText' => ['string'], 'IntlRuleBasedBreakIterator::isBoundary' => ['bool', 'offset'=>'int'], 'IntlRuleBasedBreakIterator::last' => ['int'], 'IntlRuleBasedBreakIterator::next' => ['int', 'offset='=>'int'], 'IntlRuleBasedBreakIterator::preceding' => ['int', 'offset'=>'int'], 'IntlRuleBasedBreakIterator::previous' => ['int'], 'IntlRuleBasedBreakIterator::setText' => ['bool', 'text'=>'string'], 'IntlTimeZone::countEquivalentIDs' => ['int', 'zoneId'=>'string'], 'IntlTimeZone::createDefault' => ['IntlTimeZone'], 'IntlTimeZone::createEnumeration' => ['IntlIterator', 'countryOrRawOffset='=>'mixed'], 'IntlTimeZone::createTimeZone' => ['IntlTimeZone', 'zoneId'=>'string'], 'IntlTimeZone::createTimeZoneIDEnumeration' => ['IntlIterator', 'zoneType'=>'int', 'region='=>'string', 'rawOffset='=>'int'], 'IntlTimeZone::fromDateTimeZone' => ['IntlTimeZone', 'zoneId'=>'DateTimeZone'], 'IntlTimeZone::getCanonicalID' => ['string', 'zoneId'=>'string', '&w_isSystemID='=>'bool'], 'IntlTimeZone::getDisplayName' => ['string', 'isDaylight='=>'bool', 'style='=>'int', 'locale='=>'string'], 'IntlTimeZone::getDSTSavings' => ['int'], 'IntlTimeZone::getEquivalentID' => ['string', 'zoneId'=>'string', 'index'=>'int'], 'IntlTimeZone::getErrorCode' => ['int'], 'IntlTimeZone::getErrorMessage' => ['string'], 'IntlTimeZone::getGMT' => ['IntlTimeZone'], 'IntlTimeZone::getID' => ['string'], 'IntlTimeZone::getIDForWindowsID' => ['string', 'timezone'=>'string', 'region='=>'string'], 'IntlTimeZone::getOffset' => ['int', 'date'=>'float', 'local'=>'bool', '&w_rawOffset'=>'int', '&w_dstOffset'=>'int'], 'IntlTimeZone::getRawOffset' => ['int'], 'IntlTimeZone::getRegion' => ['string', 'zoneId'=>'string'], 'IntlTimeZone::getTZDataVersion' => ['string'], 'IntlTimeZone::getUnknown' => ['IntlTimeZone'], 'IntlTimeZone::getWindowsID' => ['string', 'timezone'=>'string'], 'IntlTimeZone::hasSameRules' => ['bool', 'otherTimeZone'=>'IntlTimeZone'], 'IntlTimeZone::toDateTimeZone' => ['DateTimeZone'], 'IntlTimeZone::useDaylightTime' => ['bool'], 'intltz_count_equivalent_ids' => ['int|false', 'zoneId'=>'string'], 'intltz_create_enumeration' => ['IntlIterator', 'countryOrRawOffset'=>'mixed'], 'intltz_create_time_zone' => ['IntlTimeZone', 'zoneId'=>'string'], 'intltz_from_date_time_zone' => ['IntlTimeZone', 'zoneId'=>'DateTimeZone'], 'intltz_get_canonical_id' => ['string|false', 'zoneId'=>'string', '&isSystemID'=>'bool'], 'intltz_get_display_name' => ['string|false', 'obj'=>'IntlTimeZone', 'isDaylight'=>'bool', 'style'=>'int', 'locale'=>'string'], 'intltz_get_dst_savings' => ['int', 'obj'=>'IntlTimeZone'], 'intltz_get_equivalent_id' => ['string|false', 'zoneId'=>'string', 'index'=>'int'], 'intltz_get_error_code' => ['int|false', 'obj'=>'IntlTimeZone'], 'intltz_get_error_message' => ['string|false', 'obj'=>'IntlTimeZone'], 'intltz_get_id' => ['string|false', 'obj'=>'IntlTimeZone'], 'intltz_get_offset' => ['int', 'obj'=>'IntlTimeZone', 'date'=>'float', 'local'=>'bool', '&rawOffset'=>'int', '&dstOffset'=>'int'], 'intltz_get_raw_offset' => ['int', 'obj'=>'IntlTimeZone'], 'intltz_get_tz_data_version' => ['string|false', 'obj'=>'IntlTimeZone'], 'intltz_getGMT' => ['IntlTimeZone'], 'intltz_has_same_rules' => ['bool', 'obj'=>'IntlTimeZone', 'otherTimeZone'=>'IntlTimeZone'], 'intltz_to_date_time_zone' => ['DateTimeZone|false', 'obj'=>''], 'intltz_use_daylight_time' => ['bool', 'obj'=>''], 'intlz_create_default' => ['IntlTimeZone'], 'intval' => ['int', 'var'=>'scalar|array|resource|null', 'base='=>'int'], 'InvalidArgumentException::__clone' => ['void'], 'InvalidArgumentException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?InvalidArgumentException)'], 'InvalidArgumentException::__toString' => ['string'], 'InvalidArgumentException::getCode' => ['int'], 'InvalidArgumentException::getFile' => ['string'], 'InvalidArgumentException::getLine' => ['int'], 'InvalidArgumentException::getMessage' => ['string'], 'InvalidArgumentException::getPrevious' => ['Throwable|InvalidArgumentException|null'], 'InvalidArgumentException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'InvalidArgumentException::getTraceAsString' => ['string'], 'ip2long' => ['int|false', 'ip_address'=>'string'], 'iptcembed' => ['string|bool', 'iptcdata'=>'string', 'jpeg_file_name'=>'string', 'spool='=>'int'], 'iptcparse' => ['array>|false', 'iptcdata'=>'string'], 'is_a' => ['bool', 'object_or_string'=>'object|string', 'class_name'=>'string', 'allow_string='=>'bool'], 'is_array' => ['bool', 'var'=>'mixed'], 'is_bool' => ['bool', 'var'=>'mixed'], 'is_callable' => ['bool', 'var'=>'mixed', 'syntax_only='=>'bool', '&w_callable_name='=>'string'], 'is_countable' => ['bool', 'var'=>'mixed'], 'is_dir' => ['bool', 'filename'=>'string'], 'is_double' => ['bool', 'var'=>''], 'is_executable' => ['bool', 'filename'=>'string'], 'is_file' => ['bool', 'filename'=>'string'], 'is_finite' => ['bool', 'val'=>'float'], 'is_float' => ['bool', 'var'=>'mixed'], 'is_infinite' => ['bool', 'val'=>'float'], 'is_int' => ['bool', 'var'=>'mixed'], 'is_integer' => ['bool', 'var'=>''], 'is_iterable' => ['bool', 'var'=>'mixed'], 'is_link' => ['bool', 'filename'=>'string'], 'is_long' => ['bool', 'var'=>''], 'is_nan' => ['bool', 'val'=>'float'], 'is_null' => ['bool', 'var'=>'mixed'], 'is_numeric' => ['bool', 'value'=>'mixed'], 'is_object' => ['bool', 'var'=>'mixed'], 'is_readable' => ['bool', 'filename'=>'string'], 'is_real' => ['bool', 'var'=>''], 'is_resource' => ['bool', 'var'=>'mixed'], 'is_scalar' => ['bool', 'value'=>'mixed'], 'is_soap_fault' => ['bool', 'object'=>'mixed'], 'is_string' => ['bool', 'var'=>'mixed'], 'is_subclass_of' => ['bool', 'object_or_string'=>'object|string', 'class_name'=>'string', 'allow_string='=>'bool'], 'is_tainted' => ['bool', 'string'=>'string'], 'is_uploaded_file' => ['bool', 'path'=>'string'], 'is_writable' => ['bool', 'filename'=>'string'], 'is_writeable' => ['bool', 'filename'=>'string'], 'Iterator::current' => ['mixed'], 'Iterator::key' => ['mixed'], 'Iterator::next' => ['void'], 'Iterator::rewind' => ['void'], 'Iterator::valid' => ['bool'], 'iterator_apply' => ['0|positive-int', 'iterator'=>'Traversable', 'function'=>'callable', 'params='=>'array'], 'iterator_count' => ['0|positive-int', 'iterator'=>'Traversable'], 'iterator_to_array' => ['array', 'iterator'=>'Traversable', 'use_keys='=>'bool'], 'IteratorAggregate::getIterator' => ['Traversable'], 'IteratorIterator::__construct' => ['void', 'iterator'=>'Traversable'], 'IteratorIterator::current' => ['mixed'], 'IteratorIterator::getInnerIterator' => ['Traversable'], 'IteratorIterator::key' => ['mixed'], 'IteratorIterator::next' => ['void'], 'IteratorIterator::rewind' => ['void'], 'IteratorIterator::valid' => ['bool'], 'java_last_exception_clear' => [''], 'java_last_exception_get' => ['object'], 'java_reload' => ['array', 'new_jarpath'=>'new_jarpath'], 'java_require' => ['array', 'new_classpath'=>'new_classpath'], 'java_set_encoding' => ['array', 'encoding'=>'encoding'], 'java_set_ignore_case' => ['void', 'ignore'=>'ignore'], 'java_throw_exceptions' => ['void', 'throw'=>'throw'], 'JavaException::getCause' => ['object'], 'jddayofweek' => ['mixed', 'juliandaycount'=>'int', 'mode='=>'int'], 'jdmonthname' => ['string', 'juliandaycount'=>'int', 'mode'=>'int'], 'jdtofrench' => ['string', 'juliandaycount'=>'int'], 'jdtogregorian' => ['string', 'juliandaycount'=>'int'], 'jdtojewish' => ['string', 'juliandaycount'=>'int', 'hebrew='=>'bool', 'fl='=>'int'], 'jdtojulian' => ['string', 'juliandaycount'=>'int'], 'jdtounix' => ['int|false', 'jday'=>'int'], 'jewishtojd' => ['int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'jobqueue_license_info' => ['array'], 'join' => ['string', 'glue'=>'string', 'pieces'=>'array'], 'join\'1' => ['string', 'pieces'=>'array'], 'jpeg2wbmp' => ['bool', 'jpegname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'], 'json_decode' => ['mixed', 'json'=>'string', 'assoc='=>'bool|null', 'depth='=>'positive-int', 'options='=>'int'], 'json_encode' => ['non-empty-string|false', 'data'=>'mixed', 'options='=>'int', 'depth='=>'positive-int'], 'json_last_error' => ['JSON_ERROR_NONE|JSON_ERROR_DEPTH|JSON_ERROR_STATE_MISMATCH|JSON_ERROR_CTRL_CHAR|JSON_ERROR_SYNTAX|JSON_ERROR_UTF8|JSON_ERROR_RECURSION|JSON_ERROR_INF_OR_NAN|JSON_ERROR_UNSUPPORTED_TYPE|JSON_ERROR_INVALID_PROPERTY_NAME|JSON_ERROR_UTF16'], 'json_last_error_msg' => ['string'], 'JsonIncrementalParser::__construct' => ['void', 'depth'=>'', 'options'=>''], 'JsonIncrementalParser::get' => ['', 'options'=>''], 'JsonIncrementalParser::getError' => [''], 'JsonIncrementalParser::parse' => ['', 'json'=>''], 'JsonIncrementalParser::parseFile' => ['', 'filename'=>''], 'JsonIncrementalParser::reset' => [''], 'JsonSerializable::jsonSerialize' => ['mixed'], 'Judy::__construct' => ['void', 'judy_type'=>'int'], 'Judy::__destruct' => [''], 'Judy::byCount' => ['int', 'nth_index'=>'int'], 'Judy::count' => ['0|positive-int', 'index_start='=>'int', 'index_end='=>'int'], 'Judy::first' => ['mixed', 'index='=>'mixed'], 'Judy::firstEmpty' => ['int', 'index='=>'mixed'], 'Judy::free' => ['int'], 'Judy::getType' => ['int'], 'Judy::last' => ['void', 'index='=>'string'], 'Judy::lastEmpty' => ['int', 'index='=>'int'], 'Judy::memoryUsage' => ['int'], 'Judy::next' => ['mixed', 'index'=>'mixed'], 'Judy::nextEmpty' => ['int', 'index'=>'int'], 'Judy::offsetExists' => ['bool', 'offset'=>'mixed'], 'Judy::offsetGet' => ['mixed', 'offset'=>'mixed'], 'Judy::offsetSet' => ['bool', 'offset'=>'mixed', 'value'=>'mixed'], 'Judy::offsetUnset' => ['bool', 'offset'=>'mixed'], 'Judy::prev' => ['mixed', 'index'=>'mixed'], 'Judy::prevEmpty' => ['int', 'index'=>'mixed'], 'Judy::size' => ['void'], 'judy_type' => ['int', 'array'=>'judy'], 'judy_version' => ['string'], 'juliantojd' => ['int', 'month'=>'int', 'day'=>'int', 'year'=>'int'], 'kadm5_chpass_principal' => ['bool', 'handle'=>'resource', 'principal'=>'string', 'password'=>'string'], 'kadm5_create_principal' => ['bool', 'handle'=>'resource', 'principal'=>'string', 'password='=>'string', 'options='=>'array'], 'kadm5_delete_principal' => ['bool', 'handle'=>'resource', 'principal'=>'string'], 'kadm5_destroy' => ['bool', 'handle'=>'resource'], 'kadm5_flush' => ['bool', 'handle'=>'resource'], 'kadm5_get_policies' => ['array', 'handle'=>'resource'], 'kadm5_get_principal' => ['array', 'handle'=>'resource', 'principal'=>'string'], 'kadm5_get_principals' => ['array', 'handle'=>'resource'], 'kadm5_init_with_password' => ['resource', 'admin_server'=>'string', 'realm'=>'string', 'principal'=>'string', 'password'=>'string'], 'kadm5_modify_principal' => ['bool', 'handle'=>'resource', 'principal'=>'string', 'options'=>'array'], 'key' => ['int|string|null', 'array_arg'=>'array|object'], 'key_exists' => ['bool', 'key'=>'string|int', 'search'=>'array'], 'krsort' => ['bool', '&rw_array_arg'=>'array', 'sort_flags='=>'int'], 'ksort' => ['bool', '&rw_array_arg'=>'array', 'sort_flags='=>'int'], 'KTaglib_ID3v2_AttachedPictureFrame::getDescription' => ['string'], 'KTaglib_ID3v2_AttachedPictureFrame::getMimeType' => ['string'], 'KTaglib_ID3v2_AttachedPictureFrame::getType' => ['int'], 'KTaglib_ID3v2_AttachedPictureFrame::savePicture' => ['bool', 'filename'=>'string'], 'KTaglib_ID3v2_AttachedPictureFrame::setMimeType' => ['string', 'type'=>'string'], 'KTaglib_ID3v2_AttachedPictureFrame::setPicture' => ['', 'filename'=>'string'], 'KTaglib_ID3v2_AttachedPictureFrame::setType' => ['', 'type'=>'int'], 'KTaglib_ID3v2_Frame::__toString' => ['string'], 'KTaglib_ID3v2_Frame::getSize' => ['int'], 'KTaglib_ID3v2_Tag::addFrame' => ['bool', 'frame'=>'ktaglib_id3v2_frame'], 'KTaglib_ID3v2_Tag::getFrameList' => ['array'], 'KTaglib_MPEG_AudioProperties::getBitrate' => ['int'], 'KTaglib_MPEG_AudioProperties::getChannels' => ['int'], 'KTaglib_MPEG_AudioProperties::getLayer' => ['int'], 'KTaglib_MPEG_AudioProperties::getLength' => ['int'], 'KTaglib_MPEG_AudioProperties::getSampleBitrate' => ['int'], 'KTaglib_MPEG_AudioProperties::getVersion' => ['int'], 'KTaglib_MPEG_AudioProperties::isCopyrighted' => ['bool'], 'KTaglib_MPEG_AudioProperties::isOriginal' => ['bool'], 'KTaglib_MPEG_AudioProperties::isProtectionEnabled' => ['bool'], 'KTaglib_MPEG_File::getAudioProperties' => ['KTaglib_MPEG_File'], 'KTaglib_MPEG_File::getID3v1Tag' => ['KTaglib_ID3v1_Tag', 'create='=>'bool'], 'KTaglib_MPEG_File::getID3v2Tag' => ['KTaglib_ID3v2_Tag', 'create='=>'bool'], 'KTaglib_Tag::getAlbum' => ['string'], 'KTaglib_Tag::getArtist' => ['string'], 'KTaglib_Tag::getComment' => ['string'], 'KTaglib_Tag::getGenre' => ['string'], 'KTaglib_Tag::getTitle' => ['string'], 'KTaglib_Tag::getTrack' => ['int'], 'KTaglib_Tag::getYear' => ['int'], 'KTaglib_Tag::isEmpty' => ['bool'], 'labelcacheObj::freeCache' => ['bool'], 'labelObj::__construct' => ['void'], 'labelObj::convertToString' => ['string'], 'labelObj::deleteStyle' => ['int', 'index'=>'int'], 'labelObj::free' => ['void'], 'labelObj::getBinding' => ['string', 'labelbinding'=>'mixed'], 'labelObj::getExpressionString' => ['string'], 'labelObj::getStyle' => ['styleObj', 'index'=>'int'], 'labelObj::getTextString' => ['string'], 'labelObj::moveStyleDown' => ['int', 'index'=>'int'], 'labelObj::moveStyleUp' => ['int', 'index'=>'int'], 'labelObj::removeBinding' => ['int', 'labelbinding'=>'mixed'], 'labelObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'labelObj::setBinding' => ['int', 'labelbinding'=>'mixed', 'value'=>'string'], 'labelObj::setExpression' => ['int', 'expression'=>'string'], 'labelObj::setText' => ['int', 'text'=>'string'], 'labelObj::updateFromString' => ['int', 'snippet'=>'string'], 'Lapack::eigenValues' => ['array', 'a'=>'array', 'left='=>'array', 'right='=>'array'], 'Lapack::identity' => ['array', 'n'=>'int'], 'Lapack::leastSquaresByFactorisation' => ['array', 'a'=>'array', 'b'=>'array'], 'Lapack::leastSquaresBySVD' => ['array', 'a'=>'array', 'b'=>'array'], 'Lapack::pseudoInverse' => ['array', 'a'=>'array'], 'Lapack::singularValues' => ['array', 'a'=>'array'], 'Lapack::solveLinearEquation' => ['array', 'a'=>'array', 'b'=>'array'], 'layerObj::addFeature' => ['int', 'shape'=>'shapeObj'], 'layerObj::applySLD' => ['int', 'sldxml'=>'string', 'namedlayer'=>'string'], 'layerObj::applySLDURL' => ['int', 'sldurl'=>'string', 'namedlayer'=>'string'], 'layerObj::clearProcessing' => ['void'], 'layerObj::close' => ['void'], 'layerObj::convertToString' => ['string'], 'layerObj::draw' => ['int', 'image'=>'imageObj'], 'layerObj::drawQuery' => ['int', 'image'=>'imageObj'], 'layerObj::free' => ['void'], 'layerObj::generateSLD' => ['string'], 'layerObj::getClass' => ['classObj', 'classIndex'=>'int'], 'layerObj::getClassIndex' => ['int', 'shape'=>'', 'classgroup'=>'', 'numclasses'=>''], 'layerObj::getExtent' => ['rectObj'], 'layerObj::getFilterString' => ['string'], 'layerObj::getGridIntersectionCoordinates' => ['array'], 'layerObj::getItems' => ['array'], 'layerObj::getMetaData' => ['int', 'name'=>'string'], 'layerObj::getNumResults' => ['int'], 'layerObj::getProcessing' => ['array'], 'layerObj::getProjection' => ['string'], 'layerObj::getResult' => ['resultObj', 'index'=>'int'], 'layerObj::getResultsBounds' => ['rectObj'], 'layerObj::getShape' => ['shapeObj', 'result'=>'resultObj'], 'layerObj::getWMSFeatureInfoURL' => ['string', 'clickX'=>'int', 'clickY'=>'int', 'featureCount'=>'int', 'infoFormat'=>'string'], 'layerObj::isVisible' => ['bool'], 'layerObj::moveclassdown' => ['int', 'index'=>'int'], 'layerObj::moveclassup' => ['int', 'index'=>'int'], 'layerObj::ms_newLayerObj' => ['layerObj', 'map'=>'mapObj', 'layer'=>'layerObj'], 'layerObj::nextShape' => ['shapeObj'], 'layerObj::open' => ['int'], 'layerObj::queryByAttributes' => ['int', 'qitem'=>'string', 'qstring'=>'string', 'mode'=>'int'], 'layerObj::queryByFeatures' => ['int', 'slayer'=>'int'], 'layerObj::queryByPoint' => ['int', 'point'=>'pointObj', 'mode'=>'int', 'buffer'=>'float'], 'layerObj::queryByRect' => ['int', 'rect'=>'rectObj'], 'layerObj::queryByShape' => ['int', 'shape'=>'shapeObj'], 'layerObj::removeClass' => ['classObj', 'index'=>'int'], 'layerObj::removeMetaData' => ['int', 'name'=>'string'], 'layerObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'layerObj::setConnectionType' => ['int', 'connectiontype'=>'int', 'plugin_library'=>'string'], 'layerObj::setFilter' => ['int', 'expression'=>'string'], 'layerObj::setMetaData' => ['int', 'name'=>'string', 'value'=>'string'], 'layerObj::setProjection' => ['int', 'proj_params'=>'string'], 'layerObj::setWKTProjection' => ['int', 'proj_params'=>'string'], 'layerObj::updateFromString' => ['int', 'snippet'=>'string'], 'lcfirst' => ['string', 'str'=>'string'], 'lcg_value' => ['float'], 'lchgrp' => ['bool', 'filename'=>'string', 'group'=>'string|int'], 'lchown' => ['bool', 'filename'=>'string', 'user'=>'string|int'], 'ldap_8859_to_t61' => ['string|false', 'value'=>'string'], 'ldap_add' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'servercontrols='=>'array'], 'ldap_add_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'servercontrols='=>'array'], 'ldap_bind' => ['bool', 'link_identifier'=>'resource', 'bind_rdn='=>'string|null', 'bind_password='=>'string|null', 'serverctrls='=>'array'], 'ldap_bind_ext' => ['resource|false', 'link_identifier'=>'resource', 'bind_rdn='=>'string|null', 'bind_password='=>'string|null', 'serverctrls='=>'array'], 'ldap_close' => ['bool', 'link_identifier'=>'resource'], 'ldap_compare' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'attr'=>'string', 'value'=>'string', 'servercontrols='=>'array'], 'ldap_connect' => ['resource|false', 'host='=>'string', 'port='=>'int', 'wallet='=>'string', 'wallet_passwd='=>'string', 'authmode='=>'int'], 'ldap_control_paged_result' => ['bool', 'link_identifier'=>'resource', 'pagesize'=>'int', 'iscritical='=>'bool', 'cookie='=>'string'], 'ldap_control_paged_result_response' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', '&w_cookie='=>'string', '&w_estimated='=>'int'], 'ldap_count_entries' => ['int', 'link_identifier'=>'resource', 'result'=>'resource'], 'ldap_delete' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'servercontrols='=>'array'], 'ldap_delete_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'servercontrols='=>'array'], 'ldap_dn2ufn' => ['string|false', 'dn'=>'string'], 'ldap_err2str' => ['string', 'errno'=>'int'], 'ldap_errno' => ['int', 'link_identifier'=>'resource'], 'ldap_error' => ['string', 'link_identifier'=>'resource'], 'ldap_escape' => ['string', 'value'=>'string', 'ignore='=>'string', 'flags='=>'int'], 'ldap_exop' => ['resource|bool', 'link'=>'resource', 'reqoid'=>'string', 'reqdata='=>'string', 'serverctrls='=>'array|null', '&w_retdata='=>'string', '&w_retoid='=>'string'], 'ldap_exop_passwd' => ['string|bool', 'link'=>'resource', 'user='=>'string', 'oldpw='=>'string', 'newpw='=>'string', 'serverctrls='=>'array'], 'ldap_exop_refresh' => ['int|false', 'link'=>'resource', 'dn'=>'string', 'ttl'=>'int'], 'ldap_exop_whoami' => ['string|bool', 'link'=>'resource'], 'ldap_explode_dn' => ['array|false', 'dn'=>'string', 'with_attrib'=>'int'], 'ldap_first_attribute' => ['string|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_first_entry' => ['resource|false', 'link_identifier'=>'resource', 'result_identifier'=>'resource'], 'ldap_first_reference' => ['resource|false', 'link_identifier'=>'resource', 'result_identifier'=>'resource'], 'ldap_free_result' => ['bool', 'result_identifier'=>'resource'], 'ldap_get_attributes' => ['array', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_get_dn' => ['string|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_get_entries' => ['array|false', 'link_identifier'=>'resource', 'result_identifier'=>'resource'], 'ldap_get_option' => ['bool', 'link_identifier'=>'resource', 'option'=>'int', '&w_retval'=>'mixed'], 'ldap_get_values' => ['array|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource', 'attribute'=>'string'], 'ldap_get_values_len' => ['array|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource', 'attribute'=>'string'], 'ldap_list' => ['resource|false', 'link'=>'resource|array', 'base_dn'=>'string', 'filter'=>'string', 'attrs='=>'array', 'attrsonly='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'servercontrols='=>'array'], 'ldap_mod_add' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'servercontrols='=>'array'], 'ldap_mod_add_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'servercontrols='=>'array'], 'ldap_mod_del' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'servercontrols='=>'array'], 'ldap_mod_del_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'servercontrols='=>'array'], 'ldap_mod_replace' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'servercontrols='=>'array'], 'ldap_mod_replace_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array', 'servercontrols='=>'array'], 'ldap_modify' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'entry'=>'array'], 'ldap_modify_batch' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'modifs'=>'array', 'servercontrols='=>'array'], 'ldap_next_attribute' => ['string|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_next_entry' => ['resource|false', 'link_identifier'=>'resource', 'result_entry_identifier'=>'resource'], 'ldap_next_reference' => ['resource|false', 'link_identifier'=>'resource', 'reference_entry_identifier'=>'resource'], 'ldap_parse_exop' => ['bool', 'link'=>'resource', 'result'=>'resource', '&w_retdata='=>'string', '&w_retoid='=>'string'], 'ldap_parse_reference' => ['bool', 'link_identifier'=>'resource', 'reference_entry_identifier'=>'resource', 'referrals'=>'array'], 'ldap_parse_result' => ['bool', 'link_identifier'=>'resource', 'result'=>'resource', '&w_errcode'=>'int', '&w_matcheddn='=>'string', '&w_errmsg='=>'string', '&w_referrals='=>'array', '&w_serverctrls='=>'array'], 'ldap_read' => ['resource|false', 'link'=>'resource|array', 'base_dn'=>'string', 'filter'=>'string', 'attrs='=>'array', 'attrsonly='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'servercontrols='=>'array'], 'ldap_rename' => ['bool', 'link_identifier'=>'resource', 'dn'=>'string', 'newrdn'=>'string', 'newparent'=>'string', 'deleteoldrdn'=>'bool', 'servercontrols='=>'array'], 'ldap_rename_ext' => ['resource|false', 'link_identifier'=>'resource', 'dn'=>'string', 'newrdn'=>'string', 'newparent'=>'string', 'deleteoldrdn'=>'bool', 'servercontrols='=>'array'], 'ldap_sasl_bind' => ['bool', 'link_identifier'=>'resource', 'binddn='=>'string', 'password='=>'string', 'sasl_mech='=>'string', 'sasl_realm='=>'string', 'sasl_authc_id='=>'string', 'sasl_authz_id='=>'string', 'props='=>'string'], 'ldap_search' => ['resource|false', 'link_identifier'=>'resource|array', 'base_dn'=>'string', 'filter'=>'string', 'attrs='=>'array', 'attrsonly='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'servercontrols='=>'array'], 'ldap_set_option' => ['bool', 'link_identifier'=>'resource|null', 'option'=>'int', 'newval'=>'mixed'], 'ldap_set_rebind_proc' => ['bool', 'link_identifier'=>'resource', 'callback'=>'callable'], 'ldap_sort' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', 'sortfilter'=>'string'], 'ldap_start_tls' => ['bool', 'link_identifier'=>'resource'], 'ldap_t61_to_8859' => ['string|false', 'value'=>'string'], 'ldap_unbind' => ['bool', 'link_identifier'=>'resource'], 'leak' => ['', 'num_bytes'=>'int'], 'leak_variable' => ['', 'variable'=>'', 'leak_data'=>'bool'], 'legendObj::convertToString' => ['string'], 'legendObj::free' => ['void'], 'legendObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'legendObj::updateFromString' => ['int', 'snippet'=>'string'], 'LengthException::__clone' => ['void'], 'LengthException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?LengthException)'], 'LengthException::__toString' => ['string'], 'LengthException::getCode' => ['int'], 'LengthException::getFile' => ['string'], 'LengthException::getLine' => ['int'], 'LengthException::getMessage' => ['string'], 'LengthException::getPrevious' => ['Throwable|LengthException|null'], 'LengthException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'LengthException::getTraceAsString' => ['string'], 'levenshtein' => ['int', 'str1'=>'string', 'str2'=>'string'], 'levenshtein\'1' => ['int', 'str1'=>'string', 'str2'=>'string', 'cost_ins'=>'int', 'cost_rep'=>'int', 'cost_del'=>'int'], 'libxml_clear_errors' => ['void'], 'libxml_disable_entity_loader' => ['bool', 'disable='=>'bool'], 'libxml_get_errors' => ['array'], 'libxml_get_last_error' => ['LibXMLError|false'], 'libxml_set_external_entity_loader' => ['bool', 'resolver_function'=>'callable'], 'libxml_set_streams_context' => ['void', 'streams_context'=>'resource'], 'libxml_use_internal_errors' => ['bool', 'use_errors='=>'bool'], 'LimitIterator::__construct' => ['void', 'iterator'=>'Iterator', 'offset='=>'int', 'count='=>'int'], 'LimitIterator::current' => ['mixed'], 'LimitIterator::getInnerIterator' => ['Iterator'], 'LimitIterator::getPosition' => ['int'], 'LimitIterator::key' => ['mixed'], 'LimitIterator::next' => ['void'], 'LimitIterator::rewind' => ['void'], 'LimitIterator::seek' => ['int', 'position'=>'int'], 'LimitIterator::valid' => ['bool'], 'lineObj::__construct' => ['void'], 'lineObj::add' => ['int', 'point'=>'pointObj'], 'lineObj::addXY' => ['int', 'x'=>'float', 'y'=>'float', 'm'=>'float'], 'lineObj::addXYZ' => ['int', 'x'=>'float', 'y'=>'float', 'z'=>'float', 'm'=>'float'], 'lineObj::ms_newLineObj' => ['lineObj'], 'lineObj::point' => ['pointObj', 'i'=>'int'], 'lineObj::project' => ['int', 'in'=>'projectionObj', 'out'=>'projectionObj'], 'link' => ['bool', 'target'=>'string', 'link'=>'string'], 'linkinfo' => ['int|false', 'filename'=>'string'], 'litespeed_request_headers' => ['array'], 'litespeed_response_headers' => ['array|false'], 'Locale::acceptFromHttp' => ['non-empty-string|false', 'header'=>'string'], 'Locale::canonicalize' => ['non-empty-string|null', 'locale'=>'string'], 'Locale::composeLocale' => ['string|false', 'subtags'=>'array'], 'Locale::filterMatches' => ['bool|null', 'langtag'=>'string', 'locale'=>'string', 'canonicalize='=>'bool'], 'Locale::getAllVariants' => ['array|null', 'locale'=>'string'], 'Locale::getDefault' => ['non-empty-string'], 'Locale::getDisplayLanguage' => ['non-empty-string', 'locale'=>'string', 'displayLocale='=>'string'], 'Locale::getDisplayName' => ['non-empty-string', 'locale'=>'string', 'displayLocale='=>'string'], 'Locale::getDisplayRegion' => ['non-empty-string', 'locale'=>'string', 'displayLocale='=>'string'], 'Locale::getDisplayScript' => ['string', 'locale'=>'string', 'displayLocale='=>'string'], 'Locale::getDisplayVariant' => ['string', 'locale'=>'string', 'displayLocale='=>'string'], 'Locale::getKeywords' => ['array|null', 'locale'=>'string'], 'Locale::getPrimaryLanguage' => ['non-empty-string|null', 'locale'=>'string'], 'Locale::getRegion' => ['string|null', 'locale'=>'string'], 'Locale::getScript' => ['string|null', 'locale'=>'string'], 'Locale::lookup' => ['string|null', 'languageTag'=>'array', 'locale'=>'string', 'canonicalize='=>'bool', 'defaultLocale='=>'string'], 'Locale::parseLocale' => ['array|null', 'locale'=>'string'], 'Locale::setDefault' => ['bool', 'locale'=>'string'], 'locale_accept_from_http' => ['non-empty-string|false', 'header'=>'string'], 'locale_canonicalize' => ['non-empty-string|null', 'locale'=>'string'], 'locale_compose' => ['string|false', 'subtags'=>'array'], 'locale_filter_matches' => ['bool|null', 'langtag'=>'string', 'locale'=>'string', 'canonicalize='=>'bool'], 'locale_get_all_variants' => ['array|null', 'locale'=>'string'], 'locale_get_default' => ['non-empty-string'], 'locale_get_display_language' => ['non-empty-string', 'locale'=>'string', 'displayLocale='=>'string'], 'locale_get_display_name' => ['non-empty-string', 'locale'=>'string', 'displayLocale='=>'string'], 'locale_get_display_region' => ['non-empty-string', 'locale'=>'string', 'displayLocale='=>'string'], 'locale_get_display_script' => ['string', 'locale'=>'string', 'displayLocale='=>'string'], 'locale_get_display_variant' => ['string', 'locale'=>'string', 'displayLocale='=>'string'], 'locale_get_keywords' => ['array|null', 'locale'=>'string'], 'locale_get_primary_language' => ['non-empty-string|null', 'locale'=>'string'], 'locale_get_region' => ['string|null', 'locale'=>'string'], 'locale_get_script' => ['string|null', 'locale'=>'string'], 'locale_lookup' => ['string|null', 'langtag'=>'array', 'locale'=>'string', 'canonicalize='=>'bool', 'defaultLocale='=>'string'], 'locale_parse' => ['array|null', 'locale'=>'string'], 'locale_set_default' => ['bool', 'locale'=>'string'], 'localeconv' => ['array'], 'localtime' => ['array', 'timestamp='=>'int', 'associative_array='=>'bool'], 'log' => ['float', 'number'=>'float', 'base='=>'float'], 'log10' => ['float', 'number'=>'float'], 'log1p' => ['float', 'number'=>'float'], 'LogicException::__clone' => ['void'], 'LogicException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?LogicException)'], 'LogicException::__toString' => ['string'], 'LogicException::getCode' => ['int'], 'LogicException::getFile' => ['string'], 'LogicException::getLine' => ['int'], 'LogicException::getMessage' => ['string'], 'LogicException::getPrevious' => ['Throwable|LogicException|null'], 'LogicException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'LogicException::getTraceAsString' => ['string'], 'long2ip' => ['string|false', 'proper_address'=>'int'], 'lstat' => ['array|false', 'filename'=>'string'], 'ltrim' => ['string', 'str'=>'string', 'character_mask='=>'string'], 'Lua::__call' => ['mixed', 'lua_func'=>'callable', 'args='=>'array', 'use_self='=>'int'], 'Lua::__construct' => ['void', 'lua_script_file'=>'string'], 'Lua::assign' => ['mixed', 'name'=>'string', 'value'=>'string'], 'Lua::call' => ['mixed', 'lua_func'=>'callable', 'args='=>'array', 'use_self='=>'int'], 'Lua::eval' => ['mixed', 'statements'=>'string'], 'Lua::getVersion' => ['string'], 'Lua::include' => ['mixed', 'file'=>'string'], 'Lua::registerCallback' => ['mixed', 'name'=>'string', 'function'=>'callable'], 'LuaClosure::__invoke' => ['void', 'arg'=>'mixed', '...args='=>'mixed'], 'lzf_compress' => ['string', 'data'=>'string'], 'lzf_decompress' => ['string', 'data'=>'string'], 'lzf_optimized_for' => ['int'], 'm_checkstatus' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_completeauthorizations' => ['int', 'conn'=>'resource', 'array'=>'int'], 'm_connect' => ['int', 'conn'=>'resource'], 'm_connectionerror' => ['string', 'conn'=>'resource'], 'm_deletetrans' => ['bool', 'conn'=>'resource', 'identifier'=>'int'], 'm_destroyconn' => ['bool', 'conn'=>'resource'], 'm_destroyengine' => ['void'], 'm_getcell' => ['string', 'conn'=>'resource', 'identifier'=>'int', 'column'=>'string', 'row'=>'int'], 'm_getcellbynum' => ['string', 'conn'=>'resource', 'identifier'=>'int', 'column'=>'int', 'row'=>'int'], 'm_getcommadelimited' => ['string', 'conn'=>'resource', 'identifier'=>'int'], 'm_getheader' => ['string', 'conn'=>'resource', 'identifier'=>'int', 'column_num'=>'int'], 'm_initconn' => ['resource'], 'm_initengine' => ['int', 'location'=>'string'], 'm_iscommadelimited' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_maxconntimeout' => ['bool', 'conn'=>'resource', 'secs'=>'int'], 'm_monitor' => ['int', 'conn'=>'resource'], 'm_numcolumns' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_numrows' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_parsecommadelimited' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_responsekeys' => ['array', 'conn'=>'resource', 'identifier'=>'int'], 'm_responseparam' => ['string', 'conn'=>'resource', 'identifier'=>'int', 'key'=>'string'], 'm_returnstatus' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_setblocking' => ['int', 'conn'=>'resource', 'tf'=>'int'], 'm_setdropfile' => ['int', 'conn'=>'resource', 'directory'=>'string'], 'm_setip' => ['int', 'conn'=>'resource', 'host'=>'string', 'port'=>'int'], 'm_setssl' => ['int', 'conn'=>'resource', 'host'=>'string', 'port'=>'int'], 'm_setssl_cafile' => ['int', 'conn'=>'resource', 'cafile'=>'string'], 'm_setssl_files' => ['int', 'conn'=>'resource', 'sslkeyfile'=>'string', 'sslcertfile'=>'string'], 'm_settimeout' => ['int', 'conn'=>'resource', 'seconds'=>'int'], 'm_sslcert_gen_hash' => ['string', 'filename'=>'string'], 'm_transactionssent' => ['int', 'conn'=>'resource'], 'm_transinqueue' => ['int', 'conn'=>'resource'], 'm_transkeyval' => ['int', 'conn'=>'resource', 'identifier'=>'int', 'key'=>'string', 'value'=>'string'], 'm_transnew' => ['int', 'conn'=>'resource'], 'm_transsend' => ['int', 'conn'=>'resource', 'identifier'=>'int'], 'm_uwait' => ['int', 'microsecs'=>'int'], 'm_validateidentifier' => ['int', 'conn'=>'resource', 'tf'=>'int'], 'm_verifyconnection' => ['bool', 'conn'=>'resource', 'tf'=>'int'], 'm_verifysslcert' => ['bool', 'conn'=>'resource', 'tf'=>'int'], 'magic_quotes_runtime' => ['', 'new_setting'=>''], 'mail' => ['bool', 'to'=>'string', 'subject'=>'string', 'message'=>'string', 'additional_headers='=>'string|array|null', 'additional_parameters='=>'string'], 'mailparse_determine_best_xfer_encoding' => ['string', 'fp'=>'resource'], 'mailparse_msg_create' => ['resource'], 'mailparse_msg_extract_part' => ['void', 'mimemail'=>'resource', 'msgbody'=>'string', 'callbackfunc='=>'callable'], 'mailparse_msg_extract_part_file' => ['string', 'mimemail'=>'resource', 'filename'=>'mixed', 'callbackfunc='=>'callable'], 'mailparse_msg_extract_whole_part_file' => ['string', 'mimemail'=>'resource', 'filename'=>'string', 'callbackfunc='=>'callable'], 'mailparse_msg_free' => ['bool', 'mimemail'=>'resource'], 'mailparse_msg_get_part' => ['resource|false', 'mimemail'=>'resource', 'mimesection'=>'string'], 'mailparse_msg_get_part_data' => ['array', 'mimemail'=>'resource'], 'mailparse_msg_get_structure' => ['array', 'mimemail'=>'resource'], 'mailparse_msg_parse' => ['bool', 'mimemail'=>'resource', 'data'=>'string'], 'mailparse_msg_parse_file' => ['resource', 'filename'=>'string'], 'mailparse_rfc822_parse_addresses' => ['array', 'addresses'=>'string'], 'mailparse_stream_encode' => ['bool', 'sourcefp'=>'resource', 'destfp'=>'resource', 'encoding'=>'string'], 'mailparse_uudecode_all' => ['array', 'fp'=>'resource'], 'mapObj::__construct' => ['void', 'map_file_name'=>'string', 'new_map_path'=>'string'], 'mapObj::appendOutputFormat' => ['int', 'outputFormat'=>'outputformatObj'], 'mapObj::applyconfigoptions' => ['int'], 'mapObj::applySLD' => ['int', 'sldxml'=>'string'], 'mapObj::applySLDURL' => ['int', 'sldurl'=>'string'], 'mapObj::convertToString' => ['string'], 'mapObj::draw' => ['imageObj'], 'mapObj::drawLabelCache' => ['int', 'image'=>'imageObj'], 'mapObj::drawLegend' => ['imageObj'], 'mapObj::drawQuery' => ['imageObj'], 'mapObj::drawReferenceMap' => ['imageObj'], 'mapObj::drawScaleBar' => ['imageObj'], 'mapObj::embedLegend' => ['int', 'image'=>'imageObj'], 'mapObj::embedScalebar' => ['int', 'image'=>'imageObj'], 'mapObj::free' => ['void'], 'mapObj::generateSLD' => ['string'], 'mapObj::getAllGroupNames' => ['array'], 'mapObj::getAllLayerNames' => ['array'], 'mapObj::getColorbyIndex' => ['colorObj', 'iCloIndex'=>'int'], 'mapObj::getConfigOption' => ['string', 'key'=>'string'], 'mapObj::getLabel' => ['labelcacheMemberObj', 'index'=>'int'], 'mapObj::getLayer' => ['layerObj', 'index'=>'int'], 'mapObj::getLayerByName' => ['layerObj', 'layer_name'=>'string'], 'mapObj::getLayersDrawingOrder' => ['array'], 'mapObj::getLayersIndexByGroup' => ['array', 'groupname'=>'string'], 'mapObj::getMetaData' => ['int', 'name'=>'string'], 'mapObj::getNumSymbols' => ['int'], 'mapObj::getOutputFormat' => ['outputformatObj', 'index'=>'int'], 'mapObj::getProjection' => ['string'], 'mapObj::getSymbolByName' => ['int', 'symbol_name'=>'string'], 'mapObj::getSymbolObjectById' => ['symbolObj', 'symbolid'=>'int'], 'mapObj::loadMapContext' => ['int', 'filename'=>'string', 'unique_layer_name'=>'bool'], 'mapObj::loadOWSParameters' => ['int', 'request'=>'OwsrequestObj', 'version'=>'string'], 'mapObj::moveLayerDown' => ['int', 'layerindex'=>'int'], 'mapObj::moveLayerUp' => ['int', 'layerindex'=>'int'], 'mapObj::ms_newMapObjFromString' => ['mapObj', 'map_file_string'=>'string', 'new_map_path'=>'string'], 'mapObj::offsetExtent' => ['int', 'x'=>'float', 'y'=>'float'], 'mapObj::owsDispatch' => ['int', 'request'=>'OwsrequestObj'], 'mapObj::prepareImage' => ['imageObj'], 'mapObj::prepareQuery' => ['void'], 'mapObj::processLegendTemplate' => ['string', 'params'=>'array'], 'mapObj::processQueryTemplate' => ['string', 'params'=>'array', 'generateimages'=>'bool'], 'mapObj::processTemplate' => ['string', 'params'=>'array', 'generateimages'=>'bool'], 'mapObj::queryByFeatures' => ['int', 'slayer'=>'int'], 'mapObj::queryByIndex' => ['int', 'layerindex'=>'', 'tileindex'=>'', 'shapeindex'=>'', 'addtoquery'=>''], 'mapObj::queryByPoint' => ['int', 'point'=>'pointObj', 'mode'=>'int', 'buffer'=>'float'], 'mapObj::queryByRect' => ['int', 'rect'=>'rectObj'], 'mapObj::queryByShape' => ['int', 'shape'=>'shapeObj'], 'mapObj::removeLayer' => ['layerObj', 'nIndex'=>'int'], 'mapObj::removeMetaData' => ['int', 'name'=>'string'], 'mapObj::removeOutputFormat' => ['int', 'name'=>'string'], 'mapObj::save' => ['int', 'filename'=>'string'], 'mapObj::saveMapContext' => ['int', 'filename'=>'string'], 'mapObj::saveQuery' => ['int', 'filename'=>'string', 'results'=>'int'], 'mapObj::scaleExtent' => ['int', 'zoomfactor'=>'float', 'minscaledenom'=>'float', 'maxscaledenom'=>'float'], 'mapObj::selectOutputFormat' => ['int', 'type'=>'string'], 'mapObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'mapObj::setCenter' => ['int', 'center'=>'pointObj'], 'mapObj::setConfigOption' => ['int', 'key'=>'string', 'value'=>'string'], 'mapObj::setExtent' => ['void', 'minx'=>'float', 'miny'=>'float', 'maxx'=>'float', 'maxy'=>'float'], 'mapObj::setFontSet' => ['int', 'fileName'=>'string'], 'mapObj::setMetaData' => ['int', 'name'=>'string', 'value'=>'string'], 'mapObj::setProjection' => ['int', 'proj_params'=>'string', 'bSetUnitsAndExtents'=>'bool'], 'mapObj::setRotation' => ['int', 'rotation_angle'=>'float'], 'mapObj::setSize' => ['int', 'width'=>'int', 'height'=>'int'], 'mapObj::setSymbolSet' => ['int', 'fileName'=>'string'], 'mapObj::setWKTProjection' => ['int', 'proj_params'=>'string', 'bSetUnitsAndExtents'=>'bool'], 'mapObj::zoomPoint' => ['int', 'nZoomFactor'=>'int', 'oPixelPos'=>'pointObj', 'nImageWidth'=>'int', 'nImageHeight'=>'int', 'oGeorefExt'=>'rectObj'], 'mapObj::zoomRectangle' => ['int', 'oPixelExt'=>'rectObj', 'nImageWidth'=>'int', 'nImageHeight'=>'int', 'oGeorefExt'=>'rectObj'], 'mapObj::zoomScale' => ['int', 'nScaleDenom'=>'float', 'oPixelPos'=>'pointObj', 'nImageWidth'=>'int', 'nImageHeight'=>'int', 'oGeorefExt'=>'rectObj', 'oMaxGeorefExt'=>'rectObj'], 'max' => ['', '...arg1'=>'array'], 'max\'1' => ['', 'arg1'=>'', 'arg2'=>'', '...args='=>''], 'maxdb::__construct' => ['void', 'host='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'maxdb::affected_rows' => ['int', 'link'=>''], 'maxdb::auto_commit' => ['bool', 'link'=>'', 'mode'=>'bool'], 'maxdb::change_user' => ['bool', 'link'=>'', 'user'=>'string', 'password'=>'string', 'database'=>'string'], 'maxdb::character_set_name' => ['string', 'link'=>''], 'maxdb::close' => ['bool', 'link'=>''], 'maxdb::commit' => ['bool', 'link'=>''], 'maxdb::disable_reads_from_master' => ['', 'link'=>''], 'maxdb::errno' => ['int', 'link'=>''], 'maxdb::error' => ['string', 'link'=>''], 'maxdb::field_count' => ['int', 'link'=>''], 'maxdb::get_host_info' => ['string', 'link'=>''], 'maxdb::info' => ['string', 'link'=>''], 'maxdb::insert_id' => ['', 'link'=>''], 'maxdb::kill' => ['bool', 'link'=>'', 'processid'=>'int'], 'maxdb::more_results' => ['bool', 'link'=>''], 'maxdb::multi_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb::next_result' => ['bool', 'link'=>''], 'maxdb::num_rows' => ['int', 'result'=>''], 'maxdb::options' => ['bool', 'link'=>'', 'option'=>'int', 'value'=>''], 'maxdb::ping' => ['bool', 'link'=>''], 'maxdb::prepare' => ['maxdb_stmt', 'link'=>'', 'query'=>'string'], 'maxdb::protocol_version' => ['string', 'link'=>''], 'maxdb::query' => ['', 'link'=>'', 'query'=>'string', 'resultmode='=>'int'], 'maxdb::real_connect' => ['bool', 'link'=>'', 'hostname='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'maxdb::real_escape_string' => ['string', 'link'=>'', 'escapestr'=>'string'], 'maxdb::real_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb::rollback' => ['bool', 'link'=>''], 'maxdb::rpl_query_type' => ['int', 'link'=>''], 'maxdb::select_db' => ['bool', 'link'=>'', 'dbname'=>'string'], 'maxdb::send_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb::server_info' => ['string', 'link'=>''], 'maxdb::server_version' => ['int', 'link'=>''], 'maxdb::sqlstate' => ['string', 'link'=>''], 'maxdb::ssl_set' => ['bool', 'link'=>'', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'maxdb::stat' => ['string', 'link'=>''], 'maxdb::stmt_init' => ['object', 'link'=>''], 'maxdb::store_result' => ['bool', 'link'=>''], 'maxdb::thread_id' => ['int', 'link'=>''], 'maxdb::use_result' => ['resource', 'link'=>''], 'maxdb::warning_count' => ['int', 'link'=>''], 'maxdb_affected_rows' => ['int', 'link'=>'resource'], 'maxdb_autocommit' => ['bool', 'link'=>'', 'mode'=>'bool'], 'maxdb_change_user' => ['bool', 'link'=>'', 'user'=>'string', 'password'=>'string', 'database'=>'string'], 'maxdb_character_set_name' => ['string', 'link'=>''], 'maxdb_close' => ['bool', 'link'=>''], 'maxdb_commit' => ['bool', 'link'=>''], 'maxdb_connect' => ['resource', 'host='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'maxdb_connect_errno' => ['int'], 'maxdb_connect_error' => ['string'], 'maxdb_data_seek' => ['bool', 'result'=>'', 'offset'=>'int'], 'maxdb_debug' => ['void', 'debug'=>'string'], 'maxdb_disable_reads_from_master' => ['', 'link'=>''], 'maxdb_disable_rpl_parse' => ['bool', 'link'=>'resource'], 'maxdb_dump_debug_info' => ['bool', 'link'=>'resource'], 'maxdb_embedded_connect' => ['resource', 'dbname='=>'string'], 'maxdb_enable_reads_from_master' => ['bool', 'link'=>'resource'], 'maxdb_enable_rpl_parse' => ['bool', 'link'=>'resource'], 'maxdb_errno' => ['int', 'link'=>'resource'], 'maxdb_error' => ['string', 'link'=>'resource'], 'maxdb_fetch_array' => ['', 'result'=>'', 'resulttype='=>'int'], 'maxdb_fetch_assoc' => ['array', 'result'=>''], 'maxdb_fetch_field' => ['', 'result'=>''], 'maxdb_fetch_field_direct' => ['', 'result'=>'', 'fieldnr'=>'int'], 'maxdb_fetch_fields' => ['', 'result'=>''], 'maxdb_fetch_lengths' => ['array', 'result'=>'resource'], 'maxdb_fetch_object' => ['object', 'result'=>'object'], 'maxdb_fetch_row' => ['', 'result'=>''], 'maxdb_field_count' => ['int', 'link'=>''], 'maxdb_field_seek' => ['bool', 'result'=>'', 'fieldnr'=>'int'], 'maxdb_field_tell' => ['int', 'result'=>'resource'], 'maxdb_free_result' => ['', 'result'=>''], 'maxdb_get_client_info' => ['string'], 'maxdb_get_client_version' => ['int'], 'maxdb_get_host_info' => ['string', 'link'=>'resource'], 'maxdb_get_proto_info' => ['string', 'link'=>'resource'], 'maxdb_get_server_info' => ['string', 'link'=>'resource'], 'maxdb_get_server_version' => ['int', 'link'=>'resource'], 'maxdb_info' => ['string', 'link'=>'resource'], 'maxdb_init' => ['resource'], 'maxdb_insert_id' => ['mixed', 'link'=>'resource'], 'maxdb_kill' => ['bool', 'link'=>'', 'processid'=>'int'], 'maxdb_master_query' => ['bool', 'link'=>'resource', 'query'=>'string'], 'maxdb_more_results' => ['bool', 'link'=>'resource'], 'maxdb_multi_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb_next_result' => ['bool', 'link'=>'resource'], 'maxdb_num_fields' => ['int', 'result'=>'resource'], 'maxdb_num_rows' => ['int', 'result'=>'resource'], 'maxdb_options' => ['bool', 'link'=>'', 'option'=>'int', 'value'=>''], 'maxdb_ping' => ['bool', 'link'=>''], 'maxdb_prepare' => ['maxdb_stmt', 'link'=>'', 'query'=>'string'], 'maxdb_query' => ['', 'link'=>'', 'query'=>'string', 'resultmode='=>'int'], 'maxdb_real_connect' => ['bool', 'link'=>'', 'hostname='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'maxdb_real_escape_string' => ['string', 'link'=>'', 'escapestr'=>'string'], 'maxdb_real_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb_report' => ['bool', 'flags'=>'int'], 'maxdb_result::current_field' => ['int', 'result'=>''], 'maxdb_result::data_seek' => ['bool', 'result'=>'', 'offset'=>'int'], 'maxdb_result::fetch_array' => ['', 'result'=>'', 'resulttype='=>'int'], 'maxdb_result::fetch_assoc' => ['array', 'result'=>''], 'maxdb_result::fetch_field' => ['', 'result'=>''], 'maxdb_result::fetch_field_direct' => ['', 'result'=>'', 'fieldnr'=>'int'], 'maxdb_result::fetch_fields' => ['', 'result'=>''], 'maxdb_result::fetch_object' => ['object', 'result'=>'object'], 'maxdb_result::fetch_row' => ['', 'result'=>''], 'maxdb_result::field_count' => ['int', 'result'=>''], 'maxdb_result::field_seek' => ['bool', 'result'=>'', 'fieldnr'=>'int'], 'maxdb_result::free' => ['', 'result'=>''], 'maxdb_result::lengths' => ['array', 'result'=>''], 'maxdb_rollback' => ['bool', 'link'=>''], 'maxdb_rpl_parse_enabled' => ['int', 'link'=>'resource'], 'maxdb_rpl_probe' => ['bool', 'link'=>'resource'], 'maxdb_rpl_query_type' => ['int', 'link'=>''], 'maxdb_select_db' => ['bool', 'link'=>'resource', 'dbname'=>'string'], 'maxdb_send_query' => ['bool', 'link'=>'', 'query'=>'string'], 'maxdb_server_end' => ['void'], 'maxdb_server_init' => ['bool', 'server='=>'array', 'groups='=>'array'], 'maxdb_sqlstate' => ['string', 'link'=>'resource'], 'maxdb_ssl_set' => ['bool', 'link'=>'', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'maxdb_stat' => ['string', 'link'=>''], 'maxdb_stmt::affected_rows' => ['int', 'stmt'=>''], 'maxdb_stmt::bind_param' => ['bool', 'stmt'=>'', 'types'=>'string', '&...rw_var'=>''], 'maxdb_stmt::bind_param\'1' => ['bool', 'stmt'=>'', 'types'=>'string', '&rw_var'=>'array'], 'maxdb_stmt::bind_result' => ['bool', 'stmt'=>'', '&w_var1'=>'', '&...w_vars='=>''], 'maxdb_stmt::close' => ['bool', 'stmt'=>''], 'maxdb_stmt::close_long_data' => ['bool', 'stmt'=>'', 'param_nr'=>'int'], 'maxdb_stmt::data_seek' => ['bool', 'statement'=>'', 'offset'=>'int'], 'maxdb_stmt::errno' => ['int', 'stmt'=>''], 'maxdb_stmt::error' => ['string', 'stmt'=>''], 'maxdb_stmt::execute' => ['bool', 'stmt'=>''], 'maxdb_stmt::fetch' => ['bool', 'stmt'=>''], 'maxdb_stmt::free_result' => ['', 'stmt'=>''], 'maxdb_stmt::num_rows' => ['int', 'stmt'=>''], 'maxdb_stmt::param_count' => ['int', 'stmt'=>''], 'maxdb_stmt::prepare' => ['', 'stmt'=>'', 'query'=>'string'], 'maxdb_stmt::reset' => ['bool', 'stmt'=>''], 'maxdb_stmt::result_metadata' => ['resource', 'stmt'=>''], 'maxdb_stmt::send_long_data' => ['bool', 'stmt'=>'', 'param_nr'=>'int', 'data'=>'string'], 'maxdb_stmt::stmt_send_long_data' => ['bool', 'param_nr'=>'int', 'data'=>'string'], 'maxdb_stmt::store_result' => ['bool'], 'maxdb_stmt_affected_rows' => ['int', 'stmt'=>'resource'], 'maxdb_stmt_bind_param' => ['bool', 'stmt'=>'', 'types'=>'string', 'var1'=>'', '...args='=>'', 'var='=>'array'], 'maxdb_stmt_bind_result' => ['bool', 'stmt'=>'', '&w_var1'=>'', '&...w_vars='=>''], 'maxdb_stmt_close' => ['bool', 'stmt'=>''], 'maxdb_stmt_close_long_data' => ['bool', 'stmt'=>'', 'param_nr'=>'int'], 'maxdb_stmt_data_seek' => ['bool', 'statement'=>'', 'offset'=>'int'], 'maxdb_stmt_errno' => ['int', 'stmt'=>'resource'], 'maxdb_stmt_error' => ['string', 'stmt'=>'resource'], 'maxdb_stmt_execute' => ['bool', 'stmt'=>''], 'maxdb_stmt_fetch' => ['bool', 'stmt'=>''], 'maxdb_stmt_free_result' => ['', 'stmt'=>''], 'maxdb_stmt_init' => ['object', 'link'=>''], 'maxdb_stmt_num_rows' => ['int', 'stmt'=>'resource'], 'maxdb_stmt_param_count' => ['int', 'stmt'=>'resource'], 'maxdb_stmt_prepare' => ['', 'stmt'=>'', 'query'=>'string'], 'maxdb_stmt_reset' => ['bool', 'stmt'=>''], 'maxdb_stmt_result_metadata' => ['resource', 'stmt'=>''], 'maxdb_stmt_send_long_data' => ['bool', 'stmt'=>'', 'param_nr'=>'int', 'data'=>'string'], 'maxdb_stmt_sqlstate' => ['string', 'stmt'=>'resource'], 'maxdb_stmt_store_result' => ['bool', 'stmt'=>''], 'maxdb_store_result' => ['bool', 'link'=>''], 'maxdb_thread_id' => ['int', 'link'=>'resource'], 'maxdb_thread_safe' => ['bool'], 'maxdb_use_result' => ['resource', 'link'=>''], 'maxdb_warning_count' => ['int', 'link'=>'resource'], 'mb_check_encoding' => ['bool', 'var='=>'string|array', 'encoding='=>'string'], 'mb_chr' => ['string|false', 'cp'=>'int', 'encoding='=>'string'], 'mb_convert_case' => ['string', 'sourcestring'=>'string', 'mode'=>'int', 'encoding='=>'string'], 'mb_convert_encoding' => ['string|array|false', 'val'=>'string|array', 'to_encoding'=>'string', 'from_encoding='=>'mixed'], 'mb_convert_kana' => ['string', 'str'=>'string', 'option='=>'string', 'encoding='=>'string'], 'mb_convert_variables' => ['string|false', 'to_encoding'=>'string', 'from_encoding'=>'array|string', '&rw_vars'=>'string|array|object', '&...rw_vars='=>'string|array|object'], 'mb_decode_mimeheader' => ['string', 'string'=>'string'], 'mb_decode_numericentity' => ['string', 'string'=>'string', 'convmap'=>'array', 'encoding'=>'string'], 'mb_detect_encoding' => ['string|false', 'str'=>'string', 'encoding_list='=>'mixed', 'strict='=>'bool'], 'mb_detect_order' => ['bool|list', 'encoding_list='=>'mixed'], 'mb_encode_mimeheader' => ['string', 'str'=>'string', 'charset='=>'string', 'transfer_encoding='=>'string', 'linefeed='=>'string', 'indent='=>'int'], 'mb_encode_numericentity' => ['string', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string', 'is_hex='=>'bool'], 'mb_encoding_aliases' => ['list|false', 'encoding'=>'string'], 'mb_ereg' => ['int|false', 'pattern'=>'string', 'string'=>'string', '&w_registers='=>'array'], 'mb_ereg_match' => ['bool', 'pattern'=>'string', 'string'=>'string', 'option='=>'string'], 'mb_ereg_replace' => ['string|false|null', 'pattern'=>'string', 'replacement'=>'string', 'string'=>'string', 'option='=>'string'], 'mb_ereg_replace_callback' => ['string|false|null', 'pattern'=>'string', 'callback'=>'callable(array):string', 'string'=>'string', 'option='=>'string'], 'mb_ereg_search' => ['bool', 'pattern='=>'string', 'option='=>'string'], 'mb_ereg_search_getpos' => ['int'], 'mb_ereg_search_getregs' => ['array|false'], 'mb_ereg_search_init' => ['bool', 'string'=>'string', 'pattern='=>'string', 'option='=>'string'], 'mb_ereg_search_pos' => ['array|false', 'pattern='=>'string', 'option='=>'string'], 'mb_ereg_search_regs' => ['array|false', 'pattern='=>'string', 'option='=>'string'], 'mb_ereg_search_setpos' => ['bool', 'position'=>'int'], 'mb_eregi' => ['int', 'pattern'=>'string', 'string'=>'string', '&w_registers='=>'array'], 'mb_eregi_replace' => ['string|false', 'pattern'=>'string', 'replacement'=>'string', 'string'=>'string', 'option='=>'string'], 'mb_get_info' => ['mixed', 'type='=>'string'], 'mb_http_input' => ['mixed', 'type='=>'string'], 'mb_http_output' => ['string|bool', 'encoding='=>'string'], 'mb_internal_encoding' => ['string|bool', 'encoding='=>'string'], 'mb_language' => ['string|bool', 'language='=>'string'], 'mb_list_encodings' => ['non-empty-list'], 'mb_ord' => ['int|false', 'str'=>'string', 'enc='=>'string'], 'mb_output_handler' => ['string', 'contents'=>'string', 'status'=>'int'], 'mb_parse_str' => ['bool', 'encoded_string'=>'string', '&w_result='=>'array'], 'mb_preferred_mime_name' => ['string|false', 'encoding'=>'string'], 'mb_regex_encoding' => ['string|bool', 'encoding='=>'string'], 'mb_regex_set_options' => ['string', 'options='=>'string'], 'mb_scrub' => ['string', 'str'=>'string', 'enc='=>'string'], 'mb_send_mail' => ['bool', 'to'=>'string', 'subject'=>'string', 'message'=>'string', 'additional_headers='=>'string|array|null', 'additional_parameter='=>'string'], 'mb_split' => ['list|false', 'pattern'=>'string', 'string'=>'string', 'limit='=>'int'], 'mb_strcut' => ['string', 'str'=>'string', 'start'=>'int', 'length='=>'?int', 'encoding='=>'string'], 'mb_strimwidth' => ['string', 'str'=>'string', 'start'=>'int', 'width'=>'int', 'trimmarker='=>'string', 'encoding='=>'string'], 'mb_stripos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strlen' => ['0|positive-int|false', 'str'=>'string', 'encoding='=>'string'], 'mb_strpos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_strrchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strrichr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strripos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_strrpos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'encoding='=>'string'], 'mb_strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'part='=>'bool', 'encoding='=>'string'], 'mb_strtolower' => ['lowercase-string', 'str'=>'string', 'encoding='=>'string'], 'mb_strtoupper' => ['uppercase-string', 'str'=>'string', 'encoding='=>'string'], 'mb_strwidth' => ['0|positive-int', 'str'=>'string', 'encoding='=>'string'], 'mb_substitute_character' => ['mixed', 'substchar='=>'mixed'], 'mb_substr' => ['string', 'str'=>'string', 'start'=>'int', 'length='=>'?int', 'encoding='=>'string'], 'mb_substr_count' => ['0|positive-int', 'haystack'=>'string', 'needle'=>'string', 'encoding='=>'string'], 'mcrypt_cbc' => ['string', 'cipher'=>'string', 'key'=>'string', 'data'=>'string', 'mode'=>'int', 'iv='=>'string'], 'mcrypt_cfb' => ['string', 'cipher'=>'string', 'key'=>'string', 'data'=>'string', 'mode'=>'int', 'iv='=>'string'], 'mcrypt_create_iv' => ['string', 'size'=>'int', 'source='=>'int'], 'mcrypt_decrypt' => ['string', 'cipher'=>'string', 'key'=>'string', 'data'=>'string', 'mode'=>'string', 'iv='=>'string'], 'mcrypt_ecb' => ['string', 'cipher'=>'string', 'key'=>'string', 'data'=>'string', 'mode'=>'int', 'iv='=>'string'], 'mcrypt_enc_get_algorithms_name' => ['string', 'td'=>'resource'], 'mcrypt_enc_get_block_size' => ['int', 'td'=>'resource'], 'mcrypt_enc_get_iv_size' => ['int', 'td'=>'resource'], 'mcrypt_enc_get_key_size' => ['int', 'td'=>'resource'], 'mcrypt_enc_get_modes_name' => ['string', 'td'=>'resource'], 'mcrypt_enc_get_supported_key_sizes' => ['array', 'td'=>'resource'], 'mcrypt_enc_is_block_algorithm' => ['bool', 'td'=>'resource'], 'mcrypt_enc_is_block_algorithm_mode' => ['bool', 'td'=>'resource'], 'mcrypt_enc_is_block_mode' => ['bool', 'td'=>'resource'], 'mcrypt_enc_self_test' => ['int', 'td'=>'resource'], 'mcrypt_encrypt' => ['string', 'cipher'=>'string', 'key'=>'string', 'data'=>'string', 'mode'=>'string', 'iv='=>'string'], 'mcrypt_generic' => ['string', 'td'=>'resource', 'data'=>'string'], 'mcrypt_generic_deinit' => ['bool', 'td'=>'resource'], 'mcrypt_generic_end' => ['bool', 'td'=>'resource'], 'mcrypt_generic_init' => ['int', 'td'=>'resource', 'key'=>'string', 'iv'=>'string'], 'mcrypt_get_block_size' => ['int', 'cipher'=>'string', 'module'=>'string'], 'mcrypt_get_cipher_name' => ['string', 'cipher'=>'int|string'], 'mcrypt_get_iv_size' => ['int', 'cipher'=>'string', 'module'=>'string'], 'mcrypt_get_key_size' => ['int', 'cipher'=>'string', 'module'=>'string'], 'mcrypt_list_algorithms' => ['array', 'lib_dir='=>'string'], 'mcrypt_list_modes' => ['array', 'lib_dir='=>'string'], 'mcrypt_module_close' => ['bool', 'td'=>'resource'], 'mcrypt_module_get_algo_block_size' => ['int', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_get_algo_key_size' => ['int', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_get_supported_key_sizes' => ['array', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_is_block_algorithm' => ['bool', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_is_block_algorithm_mode' => ['bool', 'mode'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_is_block_mode' => ['bool', 'mode'=>'string', 'lib_dir='=>'string'], 'mcrypt_module_open' => ['resource|false', 'cipher'=>'string', 'cipher_directory'=>'string', 'mode'=>'string', 'mode_directory'=>'string'], 'mcrypt_module_self_test' => ['bool', 'algorithm'=>'string', 'lib_dir='=>'string'], 'mcrypt_ofb' => ['string', 'cipher'=>'string', 'key'=>'string', 'data'=>'string', 'mode'=>'int', 'iv='=>'string'], 'md5' => ['non-falsy-string&lowercase-string', 'str'=>'string', 'raw_output='=>'bool'], 'md5_file' => ['(non-falsy-string&lowercase-string)|false', 'filename'=>'string', 'raw_output='=>'bool'], 'mdecrypt_generic' => ['string', 'td'=>'resource', 'data'=>'string'], 'Memcache::add' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'Memcache::addServer' => ['bool', 'host'=>'string', 'port='=>'int', 'persistent='=>'bool', 'weight='=>'int', 'timeout='=>'int', 'retry_interval='=>'int', 'status='=>'bool', 'failure_callback='=>'callable', 'timeoutms='=>'int'], 'Memcache::close' => ['bool'], 'Memcache::connect' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'Memcache::decrement' => ['int', 'key'=>'string', 'value='=>'int'], 'Memcache::delete' => ['bool', 'key'=>'string', 'timeout='=>'int'], 'Memcache::flush' => ['bool'], 'Memcache::get' => ['mixed', 'key'=>'string', '&flags='=>'int'], 'Memcache::get\'1' => ['mixed[]|false', 'keys'=>'string[]', '&flags='=>'int[]'], 'Memcache::getExtendedStats' => ['array', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'Memcache::getServerStatus' => ['int', 'host'=>'string', 'port='=>'int'], 'Memcache::getStats' => ['array', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'Memcache::getVersion' => ['string'], 'Memcache::increment' => ['int', 'key'=>'string', 'value='=>'int'], 'Memcache::pconnect' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'Memcache::replace' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'Memcache::set' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'Memcache::setCompressThreshold' => ['bool', 'threshold'=>'int', 'min_savings='=>'float'], 'Memcache::setServerParams' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'int', 'retry_interval='=>'int', 'status='=>'bool', 'failure_callback='=>'callable'], 'memcache_debug' => ['bool', 'on_off'=>'bool'], 'Memcached::add' => ['bool', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::addByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::addServer' => ['bool', 'host'=>'string', 'port'=>'int', 'weight='=>'int'], 'Memcached::addServers' => ['bool', 'servers'=>'array'], 'Memcached::append' => ['bool', 'key'=>'string', 'value'=>'string'], 'Memcached::appendByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'string'], 'Memcached::cas' => ['bool', 'cas_token'=>'float', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::casByKey' => ['bool', 'cas_token'=>'float', 'server_key'=>'string', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::decrement' => ['int|false', 'key'=>'string', 'offset='=>'int', 'initial_value='=>'int', 'expiry='=>'int'], 'Memcached::decrementByKey' => ['int|false', 'server_key'=>'string', 'key'=>'string', 'offset='=>'int', 'initial_value='=>'int', 'expiry='=>'int'], 'Memcached::delete' => ['bool', 'key'=>'string', 'time='=>'int'], 'Memcached::deleteByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'time='=>'int'], 'Memcached::deleteMulti' => ['array', 'keys'=>'array', 'time='=>'int'], 'Memcached::deleteMultiByKey' => ['bool', 'server_key'=>'string', 'keys'=>'array', 'time='=>'int'], 'Memcached::fetch' => ['array'], 'Memcached::fetchAll' => ['array'], 'Memcached::flush' => ['bool', 'delay='=>'int'], 'Memcached::get' => ['mixed', 'key'=>'string', 'cache_cb='=>'?callable', 'flags='=>'int'], 'Memcached::getAllKeys' => ['array|false'], 'Memcached::getByKey' => ['mixed', 'server_key'=>'string', 'key'=>'string', 'value_cb='=>'?callable', 'flags='=>'int'], 'Memcached::getDelayed' => ['bool', 'keys'=>'array', 'with_cas='=>'bool', 'value_cb='=>'callable'], 'Memcached::getDelayedByKey' => ['bool', 'server_key'=>'string', 'keys'=>'array', 'with_cas='=>'bool', 'value_cb='=>'?callable'], 'Memcached::getMulti' => ['array|false', 'keys'=>'array', 'flags='=>'int'], 'Memcached::getMultiByKey' => ['array', 'server_key'=>'string', 'keys'=>'array', 'flags='=>'int'], 'Memcached::getOption' => ['mixed', 'option'=>'int'], 'Memcached::getResultCode' => ['int'], 'Memcached::getResultMessage' => ['string'], 'Memcached::getServerByKey' => ['array', 'server_key'=>'string'], 'Memcached::getServerList' => ['array'], 'Memcached::getStats' => ['array', 'type='=>'?string'], 'Memcached::getVersion' => ['array'], 'Memcached::increment' => ['int|false', 'key'=>'string', 'offset='=>'int', 'initial_value='=>'int', 'expiry='=>'int'], 'Memcached::incrementByKey' => ['int|false', 'server_key'=>'string', 'key'=>'string', 'offset='=>'int', 'initial_value='=>'int', 'expiry='=>'int'], 'Memcached::isPersistent' => ['bool'], 'Memcached::isPristine' => ['bool'], 'Memcached::prepend' => ['bool', 'key'=>'string', 'value'=>'string'], 'Memcached::prependByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'string'], 'Memcached::quit' => ['bool'], 'Memcached::replace' => ['bool', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::replaceByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::resetServerList' => ['bool'], 'Memcached::set' => ['bool', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::setByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'value'=>'mixed', 'expiration='=>'int'], 'Memcached::setMulti' => ['bool', 'items'=>'array', 'expiration='=>'int'], 'Memcached::setMultiByKey' => ['bool', 'server_key'=>'string', 'items'=>'array', 'expiration='=>'int'], 'Memcached::setOption' => ['bool', 'option'=>'int', 'value'=>'mixed'], 'Memcached::setOptions' => ['bool', 'options'=>'array'], 'Memcached::setSaslAuthData' => ['void', 'username'=>'string', 'password'=>'string'], 'Memcached::touch' => ['bool', 'key'=>'string', 'expiration'=>'int'], 'Memcached::touchByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'expiration'=>'int'], 'MemcachePool::add' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'MemcachePool::close' => ['bool'], 'MemcachePool::decrement' => ['int', 'key'=>'string', 'value='=>'int'], 'MemcachePool::delete' => ['bool', 'key'=>'string', 'timeout='=>'int'], 'MemcachePool::flush' => ['bool'], 'MemcachePool::get' => ['mixed', 'key'=>'string', '&flags='=>'int'], 'MemcachePool::get\'1' => ['mixed[]|false', 'keys'=>'string[]', '&flags='=>'int[]'], 'MemcachePool::getExtendedStats' => ['array', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'MemcachePool::getServerStatus' => ['int', 'host'=>'string', 'port='=>'int'], 'MemcachePool::getStats' => ['array', 'type='=>'string', 'slabid='=>'int', 'limit='=>'int'], 'MemcachePool::getVersion' => ['string'], 'MemcachePool::increment' => ['int', 'key'=>'string', 'value='=>'int'], 'MemcachePool::replace' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'MemcachePool::set' => ['bool', 'key'=>'string', 'var'=>'mixed', 'flag='=>'int', 'expire='=>'int'], 'MemcachePool::setCompressThreshold' => ['bool', 'threshold'=>'int', 'min_savings='=>'float'], 'MemcachePool::setServerParams' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'int', 'retry_interval='=>'int', 'status='=>'bool', 'failure_callback='=>'callable'], 'memory_get_peak_usage' => ['positive-int', 'real_usage='=>'bool'], 'memory_get_usage' => ['positive-int', 'real_usage='=>'bool'], 'MessageFormatter::__construct' => ['void', 'locale'=>'string', 'pattern'=>'string'], 'MessageFormatter::create' => ['MessageFormatter', 'locale'=>'string', 'pattern'=>'string'], 'MessageFormatter::format' => ['false|string', 'args'=>'array'], 'MessageFormatter::formatMessage' => ['false|string', 'locale'=>'string', 'pattern'=>'string', 'args'=>'array'], 'MessageFormatter::getErrorCode' => ['int'], 'MessageFormatter::getErrorMessage' => ['string'], 'MessageFormatter::getLocale' => ['string'], 'MessageFormatter::getPattern' => ['string'], 'MessageFormatter::parse' => ['array', 'value'=>'string'], 'MessageFormatter::parseMessage' => ['array', 'locale'=>'string', 'pattern'=>'string', 'source'=>'string'], 'MessageFormatter::setPattern' => ['bool', 'pattern'=>'string'], 'metaphone' => ['string', 'text'=>'string', 'phones='=>'int'], 'method_exists' => ['bool', 'object'=>'object|string', 'method'=>'string'], 'mhash' => ['string|false', 'hash'=>'int', 'data'=>'string', 'key='=>'string'], 'mhash_count' => ['int'], 'mhash_get_block_size' => ['int|false', 'hash'=>'int'], 'mhash_get_hash_name' => ['string|false', 'hash'=>'int'], 'mhash_keygen_s2k' => ['string|false', 'hash'=>'int', 'input_password'=>'string', 'salt'=>'string', 'bytes'=>'int'], 'microtime' => ['mixed', 'get_as_float='=>'bool'], 'mime_content_type' => ['string|false', 'filename_or_stream'=>'string|resource'], 'min' => ['', '...arg1'=>'array'], 'min\'1' => ['', 'arg1'=>'', 'arg2'=>'', '...args='=>''], 'ming_keypress' => ['int', 'char'=>'string'], 'ming_setcubicthreshold' => ['void', 'threshold'=>'int'], 'ming_setscale' => ['void', 'scale'=>'float'], 'ming_setswfcompression' => ['void', 'level'=>'int'], 'ming_useconstants' => ['void', 'use'=>'int'], 'ming_useswfversion' => ['void', 'version'=>'int'], 'mkdir' => ['bool', 'pathname'=>'string', 'mode='=>'int', 'recursive='=>'bool', 'context='=>'resource'], 'mktime' => ['__benevolent', 'hour='=>'int', 'min='=>'int', 'sec='=>'int', 'mon='=>'int', 'day='=>'int', 'year='=>'int'], 'money_format' => ['string', 'format'=>'string', 'value'=>'float'], 'Mongo::__construct' => ['void', 'server='=>'string', 'options='=>'array', 'driver_options='=>'array'], 'Mongo::__get' => ['MongoDB', 'dbname'=>'string'], 'Mongo::__toString' => ['string'], 'Mongo::close' => ['bool'], 'Mongo::connect' => ['bool'], 'Mongo::connectUtil' => ['bool'], 'Mongo::dropDB' => ['array', 'db'=>''], 'Mongo::forceError' => ['bool'], 'Mongo::getConnections' => ['array'], 'Mongo::getHosts' => ['array'], 'Mongo::getPoolSize' => ['int'], 'Mongo::getReadPreference' => ['array'], 'Mongo::getSlave' => ['string'], 'Mongo::getSlaveOkay' => ['bool'], 'Mongo::getWriteConcern' => ['array'], 'Mongo::killCursor' => ['', 'server_hash'=>'string', 'id'=>'MongoInt64|int'], 'Mongo::lastError' => ['array|null'], 'Mongo::listDBs' => ['array'], 'Mongo::pairConnect' => ['bool'], 'Mongo::pairPersistConnect' => ['bool', 'username='=>'string', 'password='=>'string'], 'Mongo::persistConnect' => ['bool', 'username='=>'string', 'password='=>'string'], 'Mongo::poolDebug' => ['array'], 'Mongo::prevError' => ['array'], 'Mongo::resetError' => ['array'], 'Mongo::selectCollection' => ['MongoCollection', 'db'=>'string', 'collection'=>'string'], 'Mongo::selectDB' => ['MongoDB', 'name'=>'string'], 'Mongo::setPoolSize' => ['bool', 'size'=>'int'], 'Mongo::setReadPreference' => ['bool', 'readPreference'=>'string', 'tags='=>'array'], 'Mongo::setSlaveOkay' => ['bool', 'ok='=>'bool'], 'Mongo::switchSlave' => ['string'], 'MongoBinData::__construct' => ['void', 'data'=>'string', 'type='=>'int'], 'MongoBinData::__toString' => ['string'], 'MongoClient::__construct' => ['void', 'server='=>'string', 'options='=>'array', 'driver_options='=>'array'], 'MongoClient::__get' => ['MongoDB', 'dbname'=>'string'], 'MongoClient::__toString' => ['string'], 'MongoClient::close' => ['bool', 'connection='=>'bool|string'], 'MongoClient::connect' => ['bool'], 'MongoClient::dropDB' => ['array', 'db'=>'mixed'], 'MongoClient::getConnections' => ['array'], 'MongoClient::getHosts' => ['array'], 'MongoClient::getReadPreference' => ['array'], 'MongoClient::getWriteConcern' => ['array'], 'MongoClient::killCursor' => ['bool', 'server_hash'=>'string', 'id'=>'int|MongoInt64'], 'MongoClient::listDBs' => ['array'], 'MongoClient::selectCollection' => ['MongoCollection', 'db'=>'string', 'collection'=>'string'], 'MongoClient::selectDB' => ['MongoDB', 'name'=>'string'], 'MongoClient::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags='=>'array'], 'MongoClient::setWriteConcern' => ['bool', 'w'=>'mixed', 'wtimeout='=>'int'], 'MongoClient::switchSlave' => ['string'], 'MongoCode::__construct' => ['void', 'code'=>'string', 'scope='=>'array'], 'MongoCode::__toString' => ['string'], 'MongoCollection::__construct' => ['void', 'db'=>'MongoDB', 'name'=>'string'], 'MongoCollection::__get' => ['MongoCollection', 'name'=>'string'], 'MongoCollection::__toString' => ['string'], 'MongoCollection::aggregate' => ['array', 'op'=>'array', 'op='=>'array', '...args='=>'array'], 'MongoCollection::aggregate\'1' => ['array', 'pipeline'=>'array', 'options='=>'array'], 'MongoCollection::aggregateCursor' => ['MongoCommandCursor', 'command'=>'array', 'options='=>'array'], 'MongoCollection::batchInsert' => ['mixed', 'a'=>'array', 'options='=>'array'], 'MongoCollection::count' => ['0|positive-int', 'query='=>'array', 'limit='=>'int', 'skip='=>'int'], 'MongoCollection::createDBRef' => ['array', 'a'=>'array'], 'MongoCollection::createIndex' => ['bool', 'keys'=>'array', 'options='=>'array'], 'MongoCollection::deleteIndex' => ['array', 'keys'=>'string|array'], 'MongoCollection::deleteIndexes' => ['array'], 'MongoCollection::distinct' => ['array', 'key'=>'string', 'query='=>'array'], 'MongoCollection::drop' => ['array'], 'MongoCollection::ensureIndex' => ['bool', 'keys'=>'array', 'options='=>'array'], 'MongoCollection::find' => ['MongoCursor', 'query='=>'array', 'fields='=>'array'], 'MongoCollection::findAndModify' => ['array', 'query'=>'array', 'update='=>'array', 'fields='=>'array', 'options='=>'array'], 'MongoCollection::findOne' => ['array|null', 'query='=>'array', 'fields='=>'array'], 'MongoCollection::getDBRef' => ['array', 'ref'=>'array'], 'MongoCollection::getIndexInfo' => ['array'], 'MongoCollection::getName' => ['string'], 'MongoCollection::getReadPreference' => ['array'], 'MongoCollection::getSlaveOkay' => ['bool'], 'MongoCollection::getWriteConcern' => ['array'], 'MongoCollection::group' => ['array', 'keys'=>'mixed', 'initial'=>'array', 'reduce'=>'mongocode', 'options='=>'array'], 'MongoCollection::insert' => ['bool|array', 'a'=>'array', 'options='=>'array'], 'MongoCollection::parallelCollectionScan' => ['MongoCommandCursor[]', 'num_cursors'=>'int'], 'MongoCollection::remove' => ['bool|array', 'criteria='=>'array', 'options='=>'array'], 'MongoCollection::save' => ['mixed', 'a'=>'array|object', 'options='=>'array'], 'MongoCollection::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags='=>'array'], 'MongoCollection::setSlaveOkay' => ['bool', 'ok='=>'bool'], 'MongoCollection::setWriteConcern' => ['bool', 'w'=>'mixed', 'wtimeout='=>'int'], 'MongoCollection::toIndexString' => ['string', 'keys'=>'mixed'], 'MongoCollection::update' => ['bool', 'criteria'=>'array', 'newobj'=>'array', 'options='=>'array'], 'MongoCollection::validate' => ['array', 'scan_data='=>'bool'], 'MongoCommandCursor::__construct' => ['void', 'connection'=>'MongoClient', 'ns'=>'string', 'command'=>'array'], 'MongoCommandCursor::batchSize' => ['MongoCommandCursor', 'batchSize'=>'int'], 'MongoCommandCursor::createFromDocument' => ['MongoCommandCursor', 'connection'=>'MongoClient', 'hash'=>'string', 'document'=>'array'], 'MongoCommandCursor::current' => ['array'], 'MongoCommandCursor::dead' => ['bool'], 'MongoCommandCursor::getReadPreference' => ['array'], 'MongoCommandCursor::info' => ['array'], 'MongoCommandCursor::key' => ['int'], 'MongoCommandCursor::next' => ['void'], 'MongoCommandCursor::rewind' => ['array'], 'MongoCommandCursor::setReadPreference' => ['MongoCommandCursor', 'read_preference'=>'string', 'tags='=>'array'], 'MongoCommandCursor::timeout' => ['MongoCommandCursor', 'ms'=>'int'], 'MongoCommandCursor::valid' => ['bool'], 'MongoCursor::__construct' => ['void', 'connection'=>'MongoClient', 'ns'=>'string', 'query='=>'array', 'fields='=>'array'], 'MongoCursor::addOption' => ['MongoCursor', 'key'=>'string', 'value'=>'mixed'], 'MongoCursor::awaitData' => ['MongoCursor', 'wait='=>'bool'], 'MongoCursor::batchSize' => ['MongoCursor', 'num'=>'int'], 'MongoCursor::count' => ['0|positive-int', 'foundonly='=>'bool'], 'MongoCursor::current' => ['array'], 'MongoCursor::dead' => ['bool'], 'MongoCursor::doQuery' => ['void'], 'MongoCursor::explain' => ['array'], 'MongoCursor::fields' => ['MongoCursor', 'f'=>'array'], 'MongoCursor::getNext' => ['array'], 'MongoCursor::getReadPreference' => ['array'], 'MongoCursor::hasNext' => ['bool'], 'MongoCursor::hint' => ['MongoCursor', 'key_pattern'=>'array'], 'MongoCursor::immortal' => ['MongoCursor', 'liveforever='=>'bool'], 'MongoCursor::info' => ['array'], 'MongoCursor::key' => ['string'], 'MongoCursor::limit' => ['MongoCursor', 'num'=>'int'], 'MongoCursor::maxTimeMS' => ['MongoCursor', 'ms'=>'int'], 'MongoCursor::next' => ['array'], 'MongoCursor::partial' => ['MongoCursor', 'okay='=>'bool'], 'MongoCursor::reset' => ['void'], 'MongoCursor::rewind' => ['void'], 'MongoCursor::setFlag' => ['MongoCursor', 'flag'=>'int', 'set='=>'bool'], 'MongoCursor::setReadPreference' => ['MongoCursor', 'read_preference'=>'string', 'tags='=>'array'], 'MongoCursor::skip' => ['MongoCursor', 'num'=>'int'], 'MongoCursor::slaveOkay' => ['MongoCursor', 'okay='=>'bool'], 'MongoCursor::snapshot' => ['MongoCursor'], 'MongoCursor::sort' => ['MongoCursor', 'fields'=>'array'], 'MongoCursor::tailable' => ['MongoCursor', 'tail='=>'bool'], 'MongoCursor::timeout' => ['MongoCursor', 'ms'=>'int'], 'MongoCursor::valid' => ['bool'], 'MongoCursorException::__clone' => ['void'], 'MongoCursorException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Exception)|(?Throwable)'], 'MongoCursorException::__toString' => ['string'], 'MongoCursorException::__wakeup' => ['void'], 'MongoCursorException::getCode' => ['int'], 'MongoCursorException::getFile' => ['string'], 'MongoCursorException::getHost' => ['string'], 'MongoCursorException::getLine' => ['int'], 'MongoCursorException::getMessage' => ['string'], 'MongoCursorException::getPrevious' => ['Exception|Throwable'], 'MongoCursorException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'MongoCursorException::getTraceAsString' => ['string'], 'MongoCursorInterface::__construct' => ['void'], 'MongoCursorInterface::batchSize' => ['MongoCursorInterface', 'batchSize'=>'int'], 'MongoCursorInterface::current' => ['mixed'], 'MongoCursorInterface::dead' => ['bool'], 'MongoCursorInterface::getReadPreference' => ['array'], 'MongoCursorInterface::info' => ['array'], 'MongoCursorInterface::key' => ['int|string'], 'MongoCursorInterface::next' => ['void'], 'MongoCursorInterface::rewind' => ['void'], 'MongoCursorInterface::setReadPreference' => ['MongoCursorInterface', 'read_preference'=>'string', 'tags='=>'array'], 'MongoCursorInterface::timeout' => ['MongoCursorInterface', 'ms'=>'int'], 'MongoCursorInterface::valid' => ['bool'], 'MongoDate::__construct' => ['void', 'sec='=>'int', 'usec='=>'int'], 'MongoDate::__toString' => ['string'], 'MongoDate::toDateTime' => ['DateTime'], 'MongoDB::__construct' => ['void', 'conn'=>'MongoClient', 'name'=>'string'], 'MongoDB::__get' => ['MongoCollection', 'name'=>'string'], 'MongoDB::__toString' => ['string'], 'MongoDB::authenticate' => ['array', 'username'=>'string', 'password'=>'string'], 'MongoDB::command' => ['array', 'command'=>'array'], 'MongoDB::createCollection' => ['MongoCollection', 'name'=>'string', 'capped='=>'bool', 'size='=>'int', 'max='=>'int'], 'MongoDB::createDBRef' => ['array', 'collection'=>'string', 'a'=>''], 'MongoDB::drop' => ['array'], 'MongoDB::dropCollection' => ['array', 'coll'=>''], 'MongoDB::execute' => ['array', 'code'=>'', 'args='=>'array'], 'MongoDB::forceError' => ['bool'], 'MongoDB::getCollectionInfo' => ['array', 'options='=>'array'], 'MongoDB::getCollectionNames' => ['array', 'options='=>'array'], 'MongoDB::getDBRef' => ['array', 'ref'=>'array'], 'MongoDB::getGridFS' => ['MongoGridFS', 'prefix='=>'string'], 'MongoDB::getProfilingLevel' => ['int'], 'MongoDB::getReadPreference' => ['array'], 'MongoDB::getSlaveOkay' => ['bool'], 'MongoDB::getWriteConcern' => ['array'], 'MongoDB::lastError' => ['array'], 'MongoDB::listCollections' => ['array'], 'MongoDB::prevError' => ['array'], 'MongoDB::repair' => ['array', 'preserve_cloned_files='=>'bool', 'backup_original_files='=>'bool'], 'MongoDB::resetError' => ['array'], 'MongoDB::selectCollection' => ['MongoCollection', 'name'=>'string'], 'MongoDB::setProfilingLevel' => ['int', 'level'=>'int'], 'MongoDB::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags='=>'array'], 'MongoDB::setSlaveOkay' => ['bool', 'ok='=>'bool'], 'MongoDB::setWriteConcern' => ['bool', 'w'=>'mixed', 'wtimeout='=>'int'], 'MongoDB\BSON\fromJSON' => ['string', 'json'=>'string'], 'MongoDB\BSON\fromPHP' => ['string', 'value'=>'object|array'], 'MongoDB\BSON\toCanonicalExtendedJSON' => ['string', 'bson'=>'string'], 'MongoDB\BSON\toJSON' => ['string', 'bson'=>'string'], 'MongoDB\BSON\toPHP' => ['object|array', 'bson'=>'string', 'typemap='=>'?array'], 'MongoDB\BSON\toRelaxedExtendedJSON' => ['string', 'bson'=>'string'], 'MongoDB\Driver\Monitoring\addSubscriber' => ['void', 'subscriber'=>'MongoDB\Driver\Monitoring\Subscriber'], 'MongoDB\Driver\Monitoring\removeSubscriber' => ['void', 'subscriber'=>'MongoDB\Driver\Monitoring\Subscriber'], 'MongoDB\BSON\Binary::__construct' => ['void', 'data'=>'string', 'type='=>'int'], 'MongoDB\BSON\Binary::getData' => ['string'], 'MongoDB\BSON\Binary::getType' => ['int'], 'MongoDB\BSON\Binary::__toString' => ['string'], 'MongoDB\BSON\Binary::serialize' => ['string'], 'MongoDB\BSON\Binary::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Binary::jsonSerialize' => ['mixed'], 'MongoDB\BSON\BinaryInterface::getData' => ['string'], 'MongoDB\BSON\BinaryInterface::getType' => ['int'], 'MongoDB\BSON\BinaryInterface::__toString' => ['string'], 'MongoDB\BSON\DBPointer::__toString' => ['string'], 'MongoDB\BSON\DBPointer::serialize' => ['string'], 'MongoDB\BSON\DBPointer::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\DBPointer::jsonSerialize' => ['mixed'], 'MongoDB\BSON\Decimal128::__construct' => ['void', 'value'=>'string'], 'MongoDB\BSON\Decimal128::__toString' => ['string'], 'MongoDB\BSON\Decimal128::serialize' => ['string'], 'MongoDB\BSON\Decimal128::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Decimal128::jsonSerialize' => ['mixed'], 'MongoDB\BSON\Decimal128Interface::__toString' => ['string'], 'MongoDB\BSON\Document::fromBSON' => ['MongoDB\BSON\Document', 'bson'=>'string'], 'MongoDB\BSON\Document::fromJSON' => ['MongoDB\BSON\Document', 'json'=>'string'], 'MongoDB\BSON\Document::fromPHP' => ['MongoDB\BSON\Document', 'value'=>'object|array'], 'MongoDB\BSON\Document::get' => ['mixed', 'key'=>'string'], 'MongoDB\BSON\Document::getIterator' => ['MongoDB\BSON\Iterator'], 'MongoDB\BSON\Document::has' => ['bool', 'key'=>'string'], 'MongoDB\BSON\Document::toPHP' => ['object|array', 'typeMap='=>'?array'], 'MongoDB\BSON\Document::toCanonicalExtendedJSON' => ['string'], 'MongoDB\BSON\Document::toRelaxedExtendedJSON' => ['string'], 'MongoDB\BSON\Document::offsetExists' => ['bool', 'offset'=>'mixed'], 'MongoDB\BSON\Document::offsetGet' => ['mixed', 'offset'=>'mixed'], 'MongoDB\BSON\Document::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'MongoDB\BSON\Document::offsetUnset' => ['void', 'offset'=>'mixed'], 'MongoDB\BSON\Document::__toString' => ['string'], 'MongoDB\BSON\Document::serialize' => ['string'], 'MongoDB\BSON\Document::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Int64::__construct' => ['void', 'value'=>'string|int'], 'MongoDB\BSON\Int64::__toString' => ['string'], 'MongoDB\BSON\Int64::serialize' => ['string'], 'MongoDB\BSON\Int64::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Int64::jsonSerialize' => ['mixed'], 'MongoDB\BSON\Iterator::current' => ['mixed'], 'MongoDB\BSON\Iterator::key' => ['string|int'], 'MongoDB\BSON\Iterator::next' => ['void'], 'MongoDB\BSON\Iterator::rewind' => ['void'], 'MongoDB\BSON\Iterator::valid' => ['bool'], 'MongoDB\BSON\Javascript::__construct' => ['void', 'code'=>'string', 'scope='=>'object|array|null'], 'MongoDB\BSON\Javascript::getCode' => ['string'], 'MongoDB\BSON\Javascript::getScope' => ['?object'], 'MongoDB\BSON\Javascript::__toString' => ['string'], 'MongoDB\BSON\Javascript::serialize' => ['string'], 'MongoDB\BSON\Javascript::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Javascript::jsonSerialize' => ['mixed'], 'MongoDB\BSON\JavascriptInterface::getCode' => ['string'], 'MongoDB\BSON\JavascriptInterface::getScope' => ['?object'], 'MongoDB\BSON\JavascriptInterface::__toString' => ['string'], 'MongoDB\BSON\MaxKey::serialize' => ['string'], 'MongoDB\BSON\MaxKey::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\MaxKey::jsonSerialize' => ['mixed'], 'MongoDB\BSON\MinKey::serialize' => ['string'], 'MongoDB\BSON\MinKey::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\MinKey::jsonSerialize' => ['mixed'], 'MongoDB\BSON\ObjectId::__construct' => ['void', 'id='=>'?string'], 'MongoDB\BSON\ObjectId::getTimestamp' => ['int'], 'MongoDB\BSON\ObjectId::__toString' => ['string'], 'MongoDB\BSON\ObjectId::serialize' => ['string'], 'MongoDB\BSON\ObjectId::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\ObjectId::jsonSerialize' => ['mixed'], 'MongoDB\BSON\ObjectIdInterface::getTimestamp' => ['int'], 'MongoDB\BSON\ObjectIdInterface::__toString' => ['string'], 'MongoDB\BSON\PackedArray::fromPHP' => ['MongoDB\BSON\PackedArray', 'value'=>'array'], 'MongoDB\BSON\PackedArray::get' => ['mixed', 'index'=>'int'], 'MongoDB\BSON\PackedArray::getIterator' => ['MongoDB\BSON\Iterator'], 'MongoDB\BSON\PackedArray::has' => ['bool', 'index'=>'int'], 'MongoDB\BSON\PackedArray::toPHP' => ['object|array', 'typeMap='=>'?array'], 'MongoDB\BSON\PackedArray::offsetExists' => ['bool', 'offset'=>'mixed'], 'MongoDB\BSON\PackedArray::offsetGet' => ['mixed', 'offset'=>'mixed'], 'MongoDB\BSON\PackedArray::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'MongoDB\BSON\PackedArray::offsetUnset' => ['void', 'offset'=>'mixed'], 'MongoDB\BSON\PackedArray::__toString' => ['string'], 'MongoDB\BSON\PackedArray::serialize' => ['string'], 'MongoDB\BSON\PackedArray::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Persistable::bsonSerialize' => ['stdClass|MongoDB\BSON\Document|array'], 'MongoDB\BSON\Regex::__construct' => ['void', 'pattern'=>'string', 'flags='=>'string'], 'MongoDB\BSON\Regex::getPattern' => ['string'], 'MongoDB\BSON\Regex::getFlags' => ['string'], 'MongoDB\BSON\Regex::__toString' => ['string'], 'MongoDB\BSON\Regex::serialize' => ['string'], 'MongoDB\BSON\Regex::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Regex::jsonSerialize' => ['mixed'], 'MongoDB\BSON\RegexInterface::getPattern' => ['string'], 'MongoDB\BSON\RegexInterface::getFlags' => ['string'], 'MongoDB\BSON\RegexInterface::__toString' => ['string'], 'MongoDB\BSON\Serializable::bsonSerialize' => ['stdClass|MongoDB\BSON\Document|MongoDB\BSON\PackedArray|array'], 'MongoDB\BSON\Symbol::__toString' => ['string'], 'MongoDB\BSON\Symbol::serialize' => ['string'], 'MongoDB\BSON\Symbol::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Symbol::jsonSerialize' => ['mixed'], 'MongoDB\BSON\Timestamp::__construct' => ['void', 'increment'=>'string|int', 'timestamp'=>'string|int'], 'MongoDB\BSON\Timestamp::getTimestamp' => ['int'], 'MongoDB\BSON\Timestamp::getIncrement' => ['int'], 'MongoDB\BSON\Timestamp::__toString' => ['string'], 'MongoDB\BSON\Timestamp::serialize' => ['string'], 'MongoDB\BSON\Timestamp::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Timestamp::jsonSerialize' => ['mixed'], 'MongoDB\BSON\TimestampInterface::getTimestamp' => ['int'], 'MongoDB\BSON\TimestampInterface::getIncrement' => ['int'], 'MongoDB\BSON\TimestampInterface::__toString' => ['string'], 'MongoDB\BSON\UTCDateTime::__construct' => ['void', 'milliseconds='=>'DateTimeInterface|string|int|float|null'], 'MongoDB\BSON\UTCDateTime::toDateTime' => ['DateTime'], 'MongoDB\BSON\UTCDateTime::__toString' => ['string'], 'MongoDB\BSON\UTCDateTime::serialize' => ['string'], 'MongoDB\BSON\UTCDateTime::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\UTCDateTime::jsonSerialize' => ['mixed'], 'MongoDB\BSON\UTCDateTimeInterface::toDateTime' => ['DateTime'], 'MongoDB\BSON\UTCDateTimeInterface::__toString' => ['string'], 'MongoDB\BSON\Undefined::__toString' => ['string'], 'MongoDB\BSON\Undefined::serialize' => ['string'], 'MongoDB\BSON\Undefined::unserialize' => ['void', 'data'=>'string'], 'MongoDB\BSON\Undefined::jsonSerialize' => ['mixed'], 'MongoDB\BSON\Unserializable::bsonUnserialize' => ['void', 'data'=>'array'], 'MongoDB\Driver\BulkWrite::__construct' => ['void', 'options='=>'?array'], 'MongoDB\Driver\BulkWrite::count' => ['int'], 'MongoDB\Driver\BulkWrite::delete' => ['void', 'filter'=>'object|array', 'deleteOptions='=>'?array'], 'MongoDB\Driver\BulkWrite::insert' => ['mixed', 'document'=>'object|array'], 'MongoDB\Driver\BulkWrite::update' => ['void', 'filter'=>'object|array', 'newObj'=>'object|array', 'updateOptions='=>'?array'], 'MongoDB\Driver\ClientEncryption::__construct' => ['void', 'options'=>'array'], 'MongoDB\Driver\ClientEncryption::addKeyAltName' => ['?object', 'keyId'=>'MongoDB\BSON\Binary', 'keyAltName'=>'string'], 'MongoDB\Driver\ClientEncryption::createDataKey' => ['MongoDB\BSON\Binary', 'kmsProvider'=>'string', 'options='=>'?array'], 'MongoDB\Driver\ClientEncryption::decrypt' => ['mixed', 'value'=>'MongoDB\BSON\Binary'], 'MongoDB\Driver\ClientEncryption::deleteKey' => ['object', 'keyId'=>'MongoDB\BSON\Binary'], 'MongoDB\Driver\ClientEncryption::encrypt' => ['MongoDB\BSON\Binary', 'value'=>'mixed', 'options='=>'?array'], 'MongoDB\Driver\ClientEncryption::encryptExpression' => ['object', 'expr'=>'object|array', 'options='=>'?array'], 'MongoDB\Driver\ClientEncryption::getKey' => ['?object', 'keyId'=>'MongoDB\BSON\Binary'], 'MongoDB\Driver\ClientEncryption::getKeyByAltName' => ['?object', 'keyAltName'=>'string'], 'MongoDB\Driver\ClientEncryption::getKeys' => ['MongoDB\Driver\Cursor'], 'MongoDB\Driver\ClientEncryption::removeKeyAltName' => ['?object', 'keyId'=>'MongoDB\BSON\Binary', 'keyAltName'=>'string'], 'MongoDB\Driver\ClientEncryption::rewrapManyDataKey' => ['object', 'filter'=>'object|array', 'options='=>'?array'], 'MongoDB\Driver\Command::__construct' => ['void', 'document'=>'object|array', 'commandOptions='=>'?array'], 'MongoDB\Driver\Cursor::current' => ['object|array|null'], 'MongoDB\Driver\Cursor::getId' => ['MongoDB\Driver\CursorId'], 'MongoDB\Driver\Cursor::getServer' => ['MongoDB\Driver\Server'], 'MongoDB\Driver\Cursor::isDead' => ['bool'], 'MongoDB\Driver\Cursor::key' => ['?int'], 'MongoDB\Driver\Cursor::next' => ['void'], 'MongoDB\Driver\Cursor::rewind' => ['void'], 'MongoDB\Driver\Cursor::setTypeMap' => ['void', 'typemap'=>'array'], 'MongoDB\Driver\Cursor::toArray' => ['array'], 'MongoDB\Driver\Cursor::valid' => ['bool'], 'MongoDB\Driver\CursorId::__toString' => ['string'], 'MongoDB\Driver\CursorId::serialize' => ['string'], 'MongoDB\Driver\CursorId::unserialize' => ['void', 'data'=>'string'], 'MongoDB\Driver\CursorInterface::getId' => ['MongoDB\Driver\CursorId'], 'MongoDB\Driver\CursorInterface::getServer' => ['MongoDB\Driver\Server'], 'MongoDB\Driver\CursorInterface::isDead' => ['bool'], 'MongoDB\Driver\CursorInterface::setTypeMap' => ['void', 'typemap'=>'array'], 'MongoDB\Driver\CursorInterface::toArray' => ['array'], 'MongoDB\Driver\Exception\AuthenticationException::__toString' => ['string'], 'MongoDB\Driver\Exception\BulkWriteException::__toString' => ['string'], 'MongoDB\Driver\Exception\CommandException::getResultDocument' => ['object'], 'MongoDB\Driver\Exception\CommandException::__toString' => ['string'], 'MongoDB\Driver\Exception\ConnectionException::__toString' => ['string'], 'MongoDB\Driver\Exception\ConnectionTimeoutException::__toString' => ['string'], 'MongoDB\Driver\Exception\EncryptionException::__toString' => ['string'], 'MongoDB\Driver\Exception\Exception::__toString' => ['string'], 'MongoDB\Driver\Exception\ExecutionTimeoutException::__toString' => ['string'], 'MongoDB\Driver\Exception\InvalidArgumentException::__toString' => ['string'], 'MongoDB\Driver\Exception\LogicException::__toString' => ['string'], 'MongoDB\Driver\Exception\RuntimeException::hasErrorLabel' => ['bool', 'errorLabel'=>'string'], 'MongoDB\Driver\Exception\RuntimeException::__toString' => ['string'], 'MongoDB\Driver\Exception\SSLConnectionException::__toString' => ['string'], 'MongoDB\Driver\Exception\ServerException::__toString' => ['string'], 'MongoDB\Driver\Exception\UnexpectedValueException::__toString' => ['string'], 'MongoDB\Driver\Exception\WriteException::getWriteResult' => ['MongoDB\Driver\WriteResult'], 'MongoDB\Driver\Exception\WriteException::__toString' => ['string'], 'MongoDB\Driver\Manager::__construct' => ['void', 'uri='=>'?string', 'uriOptions='=>'?array', 'driverOptions='=>'?array'], 'MongoDB\Driver\Manager::addSubscriber' => ['void', 'subscriber'=>'MongoDB\Driver\Monitoring\Subscriber'], 'MongoDB\Driver\Manager::createClientEncryption' => ['MongoDB\Driver\ClientEncryption', 'options'=>'array'], 'MongoDB\Driver\Manager::executeBulkWrite' => ['MongoDB\Driver\WriteResult', 'namespace'=>'string', 'bulk'=>'MongoDB\Driver\BulkWrite', 'options='=>'MongoDB\Driver\WriteConcern|array|null'], 'MongoDB\Driver\Manager::executeCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'MongoDB\Driver\ReadPreference|array|null'], 'MongoDB\Driver\Manager::executeQuery' => ['MongoDB\Driver\Cursor', 'namespace'=>'string', 'query'=>'MongoDB\Driver\Query', 'options='=>'MongoDB\Driver\ReadPreference|array|null'], 'MongoDB\Driver\Manager::executeReadCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'?array'], 'MongoDB\Driver\Manager::executeReadWriteCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'?array'], 'MongoDB\Driver\Manager::executeWriteCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'?array'], 'MongoDB\Driver\Manager::getEncryptedFieldsMap' => ['object|array|null'], 'MongoDB\Driver\Manager::getReadConcern' => ['MongoDB\Driver\ReadConcern'], 'MongoDB\Driver\Manager::getReadPreference' => ['MongoDB\Driver\ReadPreference'], 'MongoDB\Driver\Manager::getServers' => ['array'], 'MongoDB\Driver\Manager::getWriteConcern' => ['MongoDB\Driver\WriteConcern'], 'MongoDB\Driver\Manager::removeSubscriber' => ['void', 'subscriber'=>'MongoDB\Driver\Monitoring\Subscriber'], 'MongoDB\Driver\Manager::selectServer' => ['MongoDB\Driver\Server', 'readPreference='=>'?MongoDB\Driver\ReadPreference'], 'MongoDB\Driver\Manager::startSession' => ['MongoDB\Driver\Session', 'options='=>'?array'], 'MongoDB\Driver\Monitoring\CommandFailedEvent::getCommandName' => ['string'], 'MongoDB\Driver\Monitoring\CommandFailedEvent::getDurationMicros' => ['int'], 'MongoDB\Driver\Monitoring\CommandFailedEvent::getError' => ['Exception'], 'MongoDB\Driver\Monitoring\CommandFailedEvent::getOperationId' => ['string'], 'MongoDB\Driver\Monitoring\CommandFailedEvent::getReply' => ['object'], 'MongoDB\Driver\Monitoring\CommandFailedEvent::getRequestId' => ['string'], 'MongoDB\Driver\Monitoring\CommandFailedEvent::getServer' => ['MongoDB\Driver\Server'], 'MongoDB\Driver\Monitoring\CommandFailedEvent::getServiceId' => ['?MongoDB\BSON\ObjectId'], 'MongoDB\Driver\Monitoring\CommandFailedEvent::getServerConnectionId' => ['?int'], 'MongoDB\Driver\Monitoring\CommandStartedEvent::getCommand' => ['object'], 'MongoDB\Driver\Monitoring\CommandStartedEvent::getCommandName' => ['string'], 'MongoDB\Driver\Monitoring\CommandStartedEvent::getDatabaseName' => ['string'], 'MongoDB\Driver\Monitoring\CommandStartedEvent::getOperationId' => ['string'], 'MongoDB\Driver\Monitoring\CommandStartedEvent::getRequestId' => ['string'], 'MongoDB\Driver\Monitoring\CommandStartedEvent::getServer' => ['MongoDB\Driver\Server'], 'MongoDB\Driver\Monitoring\CommandStartedEvent::getServiceId' => ['?MongoDB\BSON\ObjectId'], 'MongoDB\Driver\Monitoring\CommandStartedEvent::getServerConnectionId' => ['?int'], 'MongoDB\Driver\Monitoring\CommandSubscriber::commandStarted' => ['void', 'event'=>'MongoDB\Driver\Monitoring\CommandStartedEvent'], 'MongoDB\Driver\Monitoring\CommandSubscriber::commandSucceeded' => ['void', 'event'=>'MongoDB\Driver\Monitoring\CommandSucceededEvent'], 'MongoDB\Driver\Monitoring\CommandSubscriber::commandFailed' => ['void', 'event'=>'MongoDB\Driver\Monitoring\CommandFailedEvent'], 'MongoDB\Driver\Monitoring\CommandSucceededEvent::getCommandName' => ['string'], 'MongoDB\Driver\Monitoring\CommandSucceededEvent::getDurationMicros' => ['int'], 'MongoDB\Driver\Monitoring\CommandSucceededEvent::getOperationId' => ['string'], 'MongoDB\Driver\Monitoring\CommandSucceededEvent::getReply' => ['object'], 'MongoDB\Driver\Monitoring\CommandSucceededEvent::getRequestId' => ['string'], 'MongoDB\Driver\Monitoring\CommandSucceededEvent::getServer' => ['MongoDB\Driver\Server'], 'MongoDB\Driver\Monitoring\CommandSucceededEvent::getServiceId' => ['?MongoDB\BSON\ObjectId'], 'MongoDB\Driver\Monitoring\CommandSucceededEvent::getServerConnectionId' => ['?int'], 'MongoDB\Driver\Monitoring\LogSubscriber::log' => ['void', 'level'=>'int', 'domain'=>'string', 'message'=>'string'], 'MongoDB\Driver\Monitoring\SDAMSubscriber::serverChanged' => ['void', 'event'=>'MongoDB\Driver\Monitoring\ServerChangedEvent'], 'MongoDB\Driver\Monitoring\SDAMSubscriber::serverClosed' => ['void', 'event'=>'MongoDB\Driver\Monitoring\ServerClosedEvent'], 'MongoDB\Driver\Monitoring\SDAMSubscriber::serverOpening' => ['void', 'event'=>'MongoDB\Driver\Monitoring\ServerOpeningEvent'], 'MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatFailed' => ['void', 'event'=>'MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent'], 'MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatStarted' => ['void', 'event'=>'MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent'], 'MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatSucceeded' => ['void', 'event'=>'MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent'], 'MongoDB\Driver\Monitoring\SDAMSubscriber::topologyChanged' => ['void', 'event'=>'MongoDB\Driver\Monitoring\TopologyChangedEvent'], 'MongoDB\Driver\Monitoring\SDAMSubscriber::topologyClosed' => ['void', 'event'=>'MongoDB\Driver\Monitoring\TopologyClosedEvent'], 'MongoDB\Driver\Monitoring\SDAMSubscriber::topologyOpening' => ['void', 'event'=>'MongoDB\Driver\Monitoring\TopologyOpeningEvent'], 'MongoDB\Driver\Monitoring\ServerChangedEvent::getPort' => ['int'], 'MongoDB\Driver\Monitoring\ServerChangedEvent::getHost' => ['string'], 'MongoDB\Driver\Monitoring\ServerChangedEvent::getNewDescription' => ['MongoDB\Driver\ServerDescription'], 'MongoDB\Driver\Monitoring\ServerChangedEvent::getPreviousDescription' => ['MongoDB\Driver\ServerDescription'], 'MongoDB\Driver\Monitoring\ServerChangedEvent::getTopologyId' => ['MongoDB\BSON\ObjectId'], 'MongoDB\Driver\Monitoring\ServerClosedEvent::getPort' => ['int'], 'MongoDB\Driver\Monitoring\ServerClosedEvent::getHost' => ['string'], 'MongoDB\Driver\Monitoring\ServerClosedEvent::getTopologyId' => ['MongoDB\BSON\ObjectId'], 'MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getDurationMicros' => ['int'], 'MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getError' => ['Exception'], 'MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getPort' => ['int'], 'MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getHost' => ['string'], 'MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::isAwaited' => ['bool'], 'MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent::getPort' => ['int'], 'MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent::getHost' => ['string'], 'MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent::isAwaited' => ['bool'], 'MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getDurationMicros' => ['int'], 'MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getReply' => ['object'], 'MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getPort' => ['int'], 'MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getHost' => ['string'], 'MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::isAwaited' => ['bool'], 'MongoDB\Driver\Monitoring\ServerOpeningEvent::getPort' => ['int'], 'MongoDB\Driver\Monitoring\ServerOpeningEvent::getHost' => ['string'], 'MongoDB\Driver\Monitoring\ServerOpeningEvent::getTopologyId' => ['MongoDB\BSON\ObjectId'], 'MongoDB\Driver\Monitoring\TopologyChangedEvent::getNewDescription' => ['MongoDB\Driver\TopologyDescription'], 'MongoDB\Driver\Monitoring\TopologyChangedEvent::getPreviousDescription' => ['MongoDB\Driver\TopologyDescription'], 'MongoDB\Driver\Monitoring\TopologyChangedEvent::getTopologyId' => ['MongoDB\BSON\ObjectId'], 'MongoDB\Driver\Monitoring\TopologyClosedEvent::getTopologyId' => ['MongoDB\BSON\ObjectId'], 'MongoDB\Driver\Monitoring\TopologyOpeningEvent::getTopologyId' => ['MongoDB\BSON\ObjectId'], 'MongoDB\Driver\Query::__construct' => ['void', 'filter'=>'object|array', 'queryOptions='=>'?array'], 'MongoDB\Driver\ReadConcern::__construct' => ['void', 'level='=>'?string'], 'MongoDB\Driver\ReadConcern::getLevel' => ['?string'], 'MongoDB\Driver\ReadConcern::isDefault' => ['bool'], 'MongoDB\Driver\ReadConcern::bsonSerialize' => ['stdClass'], 'MongoDB\Driver\ReadConcern::serialize' => ['string'], 'MongoDB\Driver\ReadConcern::unserialize' => ['void', 'data'=>'string'], 'MongoDB\Driver\ReadPreference::__construct' => ['void', 'mode'=>'string|int', 'tagSets='=>'?array', 'options='=>'?array'], 'MongoDB\Driver\ReadPreference::getHedge' => ['?object'], 'MongoDB\Driver\ReadPreference::getMaxStalenessSeconds' => ['int'], 'MongoDB\Driver\ReadPreference::getMode' => ['int'], 'MongoDB\Driver\ReadPreference::getModeString' => ['string'], 'MongoDB\Driver\ReadPreference::getTagSets' => ['array'], 'MongoDB\Driver\ReadPreference::bsonSerialize' => ['stdClass'], 'MongoDB\Driver\ReadPreference::serialize' => ['string'], 'MongoDB\Driver\ReadPreference::unserialize' => ['void', 'data'=>'string'], 'MongoDB\Driver\Server::executeBulkWrite' => ['MongoDB\Driver\WriteResult', 'namespace'=>'string', 'bulkWrite'=>'MongoDB\Driver\BulkWrite', 'options='=>'MongoDB\Driver\WriteConcern|array|null'], 'MongoDB\Driver\Server::executeCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'MongoDB\Driver\ReadPreference|array|null'], 'MongoDB\Driver\Server::executeQuery' => ['MongoDB\Driver\Cursor', 'namespace'=>'string', 'query'=>'MongoDB\Driver\Query', 'options='=>'MongoDB\Driver\ReadPreference|array|null'], 'MongoDB\Driver\Server::executeReadCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'?array'], 'MongoDB\Driver\Server::executeReadWriteCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'?array'], 'MongoDB\Driver\Server::executeWriteCommand' => ['MongoDB\Driver\Cursor', 'db'=>'string', 'command'=>'MongoDB\Driver\Command', 'options='=>'?array'], 'MongoDB\Driver\Server::getHost' => ['string'], 'MongoDB\Driver\Server::getInfo' => ['array'], 'MongoDB\Driver\Server::getLatency' => ['?int'], 'MongoDB\Driver\Server::getPort' => ['int'], 'MongoDB\Driver\Server::getServerDescription' => ['MongoDB\Driver\ServerDescription'], 'MongoDB\Driver\Server::getTags' => ['array'], 'MongoDB\Driver\Server::getType' => ['int'], 'MongoDB\Driver\Server::isArbiter' => ['bool'], 'MongoDB\Driver\Server::isHidden' => ['bool'], 'MongoDB\Driver\Server::isPassive' => ['bool'], 'MongoDB\Driver\Server::isPrimary' => ['bool'], 'MongoDB\Driver\Server::isSecondary' => ['bool'], 'MongoDB\Driver\ServerApi::__construct' => ['void', 'version'=>'string', 'strict='=>'?bool', 'deprecationErrors='=>'?bool'], 'MongoDB\Driver\ServerApi::bsonSerialize' => ['stdClass'], 'MongoDB\Driver\ServerApi::serialize' => ['string'], 'MongoDB\Driver\ServerApi::unserialize' => ['void', 'data'=>'string'], 'MongoDB\Driver\ServerDescription::getHelloResponse' => ['array'], 'MongoDB\Driver\ServerDescription::getHost' => ['string'], 'MongoDB\Driver\ServerDescription::getLastUpdateTime' => ['int'], 'MongoDB\Driver\ServerDescription::getPort' => ['int'], 'MongoDB\Driver\ServerDescription::getRoundTripTime' => ['?int'], 'MongoDB\Driver\ServerDescription::getType' => ['string'], 'MongoDB\Driver\Session::abortTransaction' => ['void'], 'MongoDB\Driver\Session::advanceClusterTime' => ['void', 'clusterTime'=>'object|array'], 'MongoDB\Driver\Session::advanceOperationTime' => ['void', 'operationTime'=>'MongoDB\BSON\TimestampInterface'], 'MongoDB\Driver\Session::commitTransaction' => ['void'], 'MongoDB\Driver\Session::endSession' => ['void'], 'MongoDB\Driver\Session::getClusterTime' => ['?object'], 'MongoDB\Driver\Session::getLogicalSessionId' => ['object'], 'MongoDB\Driver\Session::getOperationTime' => ['?MongoDB\BSON\Timestamp'], 'MongoDB\Driver\Session::getServer' => ['?MongoDB\Driver\Server'], 'MongoDB\Driver\Session::getTransactionOptions' => ['?array'], 'MongoDB\Driver\Session::getTransactionState' => ['string'], 'MongoDB\Driver\Session::isDirty' => ['bool'], 'MongoDB\Driver\Session::isInTransaction' => ['bool'], 'MongoDB\Driver\Session::startTransaction' => ['void', 'options='=>'?array'], 'MongoDB\Driver\TopologyDescription::getServers' => ['array'], 'MongoDB\Driver\TopologyDescription::getType' => ['string'], 'MongoDB\Driver\TopologyDescription::hasReadableServer' => ['bool', 'readPreference='=>'?MongoDB\Driver\ReadPreference'], 'MongoDB\Driver\TopologyDescription::hasWritableServer' => ['bool'], 'MongoDB\Driver\WriteConcern::__construct' => ['void', 'w'=>'string|int', 'wtimeout='=>'?int', 'journal='=>'?bool'], 'MongoDB\Driver\WriteConcern::getJournal' => ['?bool'], 'MongoDB\Driver\WriteConcern::getW' => ['string|int|null'], 'MongoDB\Driver\WriteConcern::getWtimeout' => ['int'], 'MongoDB\Driver\WriteConcern::isDefault' => ['bool'], 'MongoDB\Driver\WriteConcern::bsonSerialize' => ['stdClass'], 'MongoDB\Driver\WriteConcern::serialize' => ['string'], 'MongoDB\Driver\WriteConcern::unserialize' => ['void', 'data'=>'string'], 'MongoDB\Driver\WriteConcernError::getCode' => ['int'], 'MongoDB\Driver\WriteConcernError::getInfo' => ['?object'], 'MongoDB\Driver\WriteConcernError::getMessage' => ['string'], 'MongoDB\Driver\WriteError::getCode' => ['int'], 'MongoDB\Driver\WriteError::getIndex' => ['int'], 'MongoDB\Driver\WriteError::getInfo' => ['?object'], 'MongoDB\Driver\WriteError::getMessage' => ['string'], 'MongoDB\Driver\WriteResult::getInsertedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getMatchedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getModifiedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getDeletedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getUpsertedCount' => ['?int'], 'MongoDB\Driver\WriteResult::getServer' => ['MongoDB\Driver\Server'], 'MongoDB\Driver\WriteResult::getUpsertedIds' => ['array'], 'MongoDB\Driver\WriteResult::getWriteConcernError' => ['?MongoDB\Driver\WriteConcernError'], 'MongoDB\Driver\WriteResult::getWriteErrors' => ['array'], 'MongoDB\Driver\WriteResult::getErrorReplies' => ['array'], 'MongoDB\Driver\WriteResult::isAcknowledged' => ['bool'], 'MongoDBRef::create' => ['array', 'collection'=>'string', 'id'=>'mixed', 'database='=>'string'], 'MongoDBRef::get' => ['array', 'db'=>'mongodb', 'ref'=>'array'], 'MongoDBRef::isRef' => ['bool', 'ref'=>'mixed'], 'MongoDeleteBatch::__construct' => ['void', 'collection'=>'MongoCollection', 'write_options='=>'array'], 'MongoException::__clone' => ['void'], 'MongoException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Exception)|(?Throwable)'], 'MongoException::__toString' => ['string'], 'MongoException::__wakeup' => ['void'], 'MongoException::getCode' => ['int'], 'MongoException::getFile' => ['string'], 'MongoException::getLine' => ['int'], 'MongoException::getMessage' => ['string'], 'MongoException::getPrevious' => ['Exception|Throwable'], 'MongoException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'MongoException::getTraceAsString' => ['string'], 'MongoGridFS::__construct' => ['void', 'db'=>'MongoDB', 'prefix='=>'string', 'chunks='=>'mixed'], 'MongoGridFS::__get' => ['MongoCollection', 'name'=>'string'], 'MongoGridFS::__toString' => ['string'], 'MongoGridFS::aggregate' => ['array', 'pipeline'=>'array', 'op'=>'array', 'pipelineOperators'=>'array'], 'MongoGridFS::aggregateCursor' => ['MongoCommandCursor', 'pipeline'=>'array', 'options'=>'array'], 'MongoGridFS::batchInsert' => ['mixed', 'a'=>'array', 'options='=>'array'], 'MongoGridFS::count' => ['0|positive-int', 'query='=>'stdClass|array'], 'MongoGridFS::createDBRef' => ['array', 'a'=>'array'], 'MongoGridFS::createIndex' => ['array', 'keys'=>'array', 'options='=>'array'], 'MongoGridFS::delete' => ['bool', 'id'=>'mixed'], 'MongoGridFS::deleteIndex' => ['array', 'keys'=>'array|string'], 'MongoGridFS::deleteIndexes' => ['array'], 'MongoGridFS::distinct' => ['array|bool', 'key'=>'string', 'query='=>'?array'], 'MongoGridFS::drop' => ['array'], 'MongoGridFS::ensureIndex' => ['bool', 'keys'=>'array', 'options='=>'array'], 'MongoGridFS::find' => ['MongoGridFSCursor', 'query='=>'array', 'fields='=>'array'], 'MongoGridFS::findAndModify' => ['array', 'query'=>'array', 'update='=>'?array', 'fields='=>'?array', 'options='=>'?array'], 'MongoGridFS::findOne' => ['MongoGridFSFile', 'query='=>'mixed', 'fields='=>'mixed'], 'MongoGridFS::get' => ['MongoGridFSFile', 'id'=>'mixed'], 'MongoGridFS::getDBRef' => ['array', 'ref'=>'array'], 'MongoGridFS::getIndexInfo' => ['array'], 'MongoGridFS::getName' => ['string'], 'MongoGridFS::getReadPreference' => ['array'], 'MongoGridFS::getSlaveOkay' => ['bool'], 'MongoGridFS::group' => ['array', 'keys'=>'mixed', 'initial'=>'array', 'reduce'=>'MongoCode', 'condition='=>'array'], 'MongoGridFS::insert' => ['array|bool', 'a'=>'array|object', 'options='=>'array'], 'MongoGridFS::put' => ['mixed', 'filename'=>'string', 'extra='=>'array'], 'MongoGridFS::remove' => ['bool', 'criteria='=>'array', 'options='=>'array'], 'MongoGridFS::save' => ['array|bool', 'a'=>'array|object', 'options='=>'array'], 'MongoGridFS::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags'=>'array'], 'MongoGridFS::setSlaveOkay' => ['bool', 'ok='=>'bool|true'], 'MongoGridFS::storeBytes' => ['mixed', 'bytes'=>'string', 'extra='=>'array', 'options='=>'array'], 'MongoGridFS::storeFile' => ['mixed', 'filename'=>'string', 'extra='=>'array', 'options='=>'array'], 'MongoGridFS::storeUpload' => ['mixed', 'name'=>'string', 'filename='=>'string'], 'MongoGridFS::toIndexString' => ['string', 'keys'=>'mixed'], 'MongoGridFS::update' => ['bool', 'criteria'=>'array', 'newobj'=>'array', 'options='=>'array'], 'MongoGridFS::validate' => ['array', 'scan_data='=>'bool|false'], 'MongoGridFSCursor::__construct' => ['void', 'gridfs'=>'MongoGridFS', 'connection'=>'resource', 'ns'=>'string', 'query'=>'array', 'fields'=>'array'], 'MongoGridFSCursor::addOption' => ['MongoCursor', 'key'=>'string', 'value'=>'mixed'], 'MongoGridFSCursor::awaitData' => ['MongoCursor', 'wait='=>'bool|true'], 'MongoGridFSCursor::batchSize' => ['MongoCursor', 'batchSize'=>'int'], 'MongoGridFSCursor::count' => ['0|positive-int', 'all='=>'bool|false'], 'MongoGridFSCursor::current' => ['MongoGridFSFile'], 'MongoGridFSCursor::dead' => ['bool'], 'MongoGridFSCursor::doQuery' => ['void'], 'MongoGridFSCursor::explain' => ['array'], 'MongoGridFSCursor::fields' => ['MongoCursor', 'f'=>'array'], 'MongoGridFSCursor::getNext' => ['MongoGridFSFile'], 'MongoGridFSCursor::getReadPreference' => ['array'], 'MongoGridFSCursor::hasNext' => ['bool'], 'MongoGridFSCursor::hint' => ['MongoCursor', 'key_pattern'=>'mixed'], 'MongoGridFSCursor::immortal' => ['MongoCursor', 'liveForever='=>'bool|true'], 'MongoGridFSCursor::info' => ['array'], 'MongoGridFSCursor::key' => ['string'], 'MongoGridFSCursor::limit' => ['MongoCursor', 'num'=>'int'], 'MongoGridFSCursor::maxTimeMS' => ['MongoCursor', 'ms'=>'int'], 'MongoGridFSCursor::next' => ['void'], 'MongoGridFSCursor::partial' => ['MongoCursor', 'okay='=>'bool|true'], 'MongoGridFSCursor::reset' => ['void'], 'MongoGridFSCursor::rewind' => ['void'], 'MongoGridFSCursor::setFlag' => ['MongoCursor', 'flag'=>'int', 'set='=>'bool|true'], 'MongoGridFSCursor::setReadPreference' => ['MongoCursor', 'read_preference'=>'string', 'tags'=>'array'], 'MongoGridFSCursor::skip' => ['MongoCursor', 'num'=>'int'], 'MongoGridFSCursor::slaveOkay' => ['MongoCursor', 'okay='=>'bool|true'], 'MongoGridFSCursor::snapshot' => ['MongoCursor'], 'MongoGridFSCursor::sort' => ['MongoCursor', 'fields'=>'array'], 'MongoGridFSCursor::tailable' => ['MongoCursor', 'tail='=>'bool|true'], 'MongoGridFSCursor::timeout' => ['MongoCursor', 'ms'=>'int'], 'MongoGridFSCursor::valid' => ['bool'], 'MongoGridfsFile::__construct' => ['void', 'gridfs'=>'MongoGridFS', 'file'=>'array'], 'MongoGridFSFile::getBytes' => ['string'], 'MongoGridFSFile::getFilename' => ['string'], 'MongoGridFSFile::getResource' => ['resource'], 'MongoGridFSFile::getSize' => ['int'], 'MongoGridFSFile::write' => ['int', 'filename='=>'string'], 'MongoId::__construct' => ['void', 'id='=>'string|MongoId'], 'MongoId::__set_state' => ['MongoId', 'props'=>'array'], 'MongoId::__toString' => ['string'], 'MongoId::getHostname' => ['string'], 'MongoId::getInc' => ['int'], 'MongoId::getPID' => ['int'], 'MongoId::getTimestamp' => ['int'], 'MongoId::isValid' => ['bool', 'value'=>'mixed'], 'MongoInsertBatch::__construct' => ['void', 'collection'=>'MongoCollection', 'write_options='=>'array'], 'MongoInt32::__construct' => ['void', 'value'=>'string'], 'MongoInt32::__toString' => ['string'], 'MongoInt64::__construct' => ['void', 'value'=>'string'], 'MongoInt64::__toString' => ['string'], 'MongoLog::getCallback' => ['callable'], 'MongoLog::getLevel' => ['int'], 'MongoLog::getModule' => ['int'], 'MongoLog::setCallback' => ['bool', 'log_function'=>'callable'], 'MongoLog::setLevel' => ['void', 'level'=>'int'], 'MongoLog::setModule' => ['void', 'module'=>'int'], 'MongoPool::getSize' => ['int'], 'MongoPool::info' => ['array'], 'MongoPool::setSize' => ['bool', 'size'=>'int'], 'MongoRegex::__construct' => ['void', 'regex'=>'string'], 'MongoRegex::__toString' => ['string'], 'MongoResultException::__clone' => ['void'], 'MongoResultException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Exception)|(?Throwable)'], 'MongoResultException::__toString' => ['string'], 'MongoResultException::__wakeup' => ['void'], 'MongoResultException::getCode' => ['int'], 'MongoResultException::getDocument' => ['array'], 'MongoResultException::getFile' => ['string'], 'MongoResultException::getLine' => ['int'], 'MongoResultException::getMessage' => ['string'], 'MongoResultException::getPrevious' => ['Exception|Throwable'], 'MongoResultException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'MongoResultException::getTraceAsString' => ['string'], 'MongoTimestamp::__construct' => ['void', 'sec='=>'int', 'inc='=>'int'], 'MongoTimestamp::__toString' => ['string'], 'MongoUpdateBatch::__construct' => ['void', 'collection'=>'MongoCollection', 'write_options='=>'array'], 'MongoUpdateBatch::add' => ['bool', 'item'=>'array'], 'MongoUpdateBatch::execute' => ['array', 'write_options'=>'array'], 'MongoWriteBatch::__construct' => ['void', 'collection'=>'MongoCollection', 'batch_type'=>'string', 'write_options'=>'array'], 'MongoWriteBatch::add' => ['bool', 'item'=>'array'], 'MongoWriteBatch::execute' => ['array', 'write_options'=>'array'], 'MongoWriteConcernException::__clone' => ['void'], 'MongoWriteConcernException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Exception)|(?Throwable)'], 'MongoWriteConcernException::__toString' => ['string'], 'MongoWriteConcernException::__wakeup' => ['void'], 'MongoWriteConcernException::getCode' => ['int'], 'MongoWriteConcernException::getDocument' => ['array'], 'MongoWriteConcernException::getFile' => ['string'], 'MongoWriteConcernException::getLine' => ['int'], 'MongoWriteConcernException::getMessage' => ['string'], 'MongoWriteConcernException::getPrevious' => ['Exception|Throwable'], 'MongoWriteConcernException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'MongoWriteConcernException::getTraceAsString' => ['string'], 'monitor_custom_event' => ['void', 'class'=>'string', 'text'=>'string', 'severe='=>'int', 'user_data='=>'mixed'], 'monitor_httperror_event' => ['void', 'error_code'=>'int', 'url'=>'string', 'severe='=>'int'], 'monitor_license_info' => ['array'], 'monitor_pass_error' => ['void', 'errno'=>'int', 'errstr'=>'string', 'errfile'=>'string', 'errline'=>'int'], 'monitor_set_aggregation_hint' => ['void', 'hint'=>'string'], 'move_uploaded_file' => ['bool', 'path'=>'string', 'new_path'=>'string'], 'mqseries_back' => ['void', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_begin' => ['void', 'hconn'=>'resource', 'beginoptions'=>'array', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_close' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'options'=>'int', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_cmit' => ['void', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_conn' => ['void', 'qmanagername'=>'string', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_connx' => ['void', 'qmanagername'=>'string', 'connoptions'=>'array', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_disc' => ['void', 'hconn'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_get' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'md'=>'array', 'gmo'=>'array', 'bufferlength'=>'int', 'msg'=>'string', 'data_length'=>'int', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_inq' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'selectorcount'=>'int', 'selectors'=>'array', 'intattrcount'=>'int', 'intattr'=>'resource', 'charattrlength'=>'int', 'charattr'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_open' => ['void', 'hconn'=>'resource', 'objdesc'=>'array', 'option'=>'int', 'hobj'=>'resource', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_put' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'md'=>'array', 'pmo'=>'array', 'message'=>'string', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_put1' => ['void', 'hconn'=>'resource', 'objdesc'=>'resource', 'msgdesc'=>'resource', 'pmo'=>'resource', 'buffer'=>'string', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_set' => ['void', 'hconn'=>'resource', 'hobj'=>'resource', 'selectorcount'=>'int', 'selectors'=>'array', 'intattrcount'=>'int', 'intattrs'=>'array', 'charattrlength'=>'int', 'charattrs'=>'array', 'compcode'=>'resource', 'reason'=>'resource'], 'mqseries_strerror' => ['string', 'reason'=>'int'], 'ms_GetErrorObj' => ['errorObj'], 'ms_GetVersion' => ['string'], 'ms_GetVersionInt' => ['int'], 'ms_iogetStdoutBufferBytes' => ['int'], 'ms_iogetstdoutbufferstring' => ['void'], 'ms_ioinstallstdinfrombuffer' => ['void'], 'ms_ioinstallstdouttobuffer' => ['void'], 'ms_ioresethandlers' => ['void'], 'ms_iostripstdoutbuffercontentheaders' => ['void'], 'ms_iostripstdoutbuffercontenttype' => ['string'], 'ms_ResetErrorList' => ['void'], 'ms_TokenizeMap' => ['array', 'map_file_name'=>'string'], 'msession_connect' => ['bool', 'host'=>'string', 'port'=>'string'], 'msession_count' => ['int'], 'msession_create' => ['bool', 'session'=>'string', 'classname='=>'string', 'data='=>'string'], 'msession_destroy' => ['bool', 'name'=>'string'], 'msession_disconnect' => ['void'], 'msession_find' => ['array', 'name'=>'string', 'value'=>'string'], 'msession_get' => ['string', 'session'=>'string', 'name'=>'string', 'value'=>'string'], 'msession_get_array' => ['array', 'session'=>'string'], 'msession_get_data' => ['string', 'session'=>'string'], 'msession_inc' => ['string', 'session'=>'string', 'name'=>'string'], 'msession_list' => ['array'], 'msession_listvar' => ['array', 'name'=>'string'], 'msession_lock' => ['int', 'name'=>'string'], 'msession_plugin' => ['string', 'session'=>'string', 'val'=>'string', 'param='=>'string'], 'msession_randstr' => ['string', 'param'=>'int'], 'msession_set' => ['bool', 'session'=>'string', 'name'=>'string', 'value'=>'string'], 'msession_set_array' => ['void', 'session'=>'string', 'tuples'=>'array'], 'msession_set_data' => ['bool', 'session'=>'string', 'value'=>'string'], 'msession_timeout' => ['int', 'session'=>'string', 'param='=>'int'], 'msession_uniq' => ['string', 'param'=>'int', 'classname='=>'string', 'data='=>'string'], 'msession_unlock' => ['int', 'session'=>'string', 'key'=>'int'], 'msg_get_queue' => ['resource|false', 'key'=>'int', 'perms='=>'int'], 'msg_queue_exists' => ['bool', 'key'=>'int'], 'msg_receive' => ['bool', 'queue'=>'resource', 'desiredmsgtype'=>'int', '&w_msgtype'=>'int', 'maxsize'=>'int', '&w_message'=>'mixed', 'unserialize='=>'bool', 'flags='=>'int', '&w_errorcode='=>'int'], 'msg_remove_queue' => ['bool', 'queue'=>'resource'], 'msg_send' => ['bool', 'queue'=>'resource', 'msgtype'=>'int', 'message'=>'mixed', 'serialize='=>'bool', 'blocking='=>'bool', '&w_errorcode='=>'int'], 'msg_set_queue' => ['bool', 'queue'=>'resource', 'data'=>'array'], 'msg_stat_queue' => ['array|false', 'queue'=>'resource'], 'msgfmt_create' => ['MessageFormatter', 'locale'=>'string', 'pattern'=>'string'], 'msgfmt_format' => ['string|false', 'fmt'=>'messageformatter', 'args'=>'array'], 'msgfmt_format_message' => ['string|false', 'locale'=>'string', 'pattern'=>'string', 'args'=>'array'], 'msgfmt_get_error_code' => ['int', 'fmt'=>'messageformatter'], 'msgfmt_get_error_message' => ['string', 'fmt'=>'messageformatter'], 'msgfmt_get_locale' => ['string', 'formatter'=>'messageformatter'], 'msgfmt_get_pattern' => ['string|false', 'fmt'=>'messageformatter'], 'msgfmt_parse' => ['array|false', 'fmt'=>'messageformatter', 'value'=>'string'], 'msgfmt_parse_message' => ['array|false', 'locale'=>'string', 'pattern'=>'string', 'source'=>'string'], 'msgfmt_set_pattern' => ['bool', 'fmt'=>'messageformatter', 'pattern'=>'string'], 'msql_affected_rows' => ['int', 'result'=>'resource'], 'msql_close' => ['bool', 'link_identifier='=>'?resource'], 'msql_connect' => ['resource', 'hostname='=>'string'], 'msql_create_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'msql_data_seek' => ['bool', 'result'=>'resource', 'row_number'=>'int'], 'msql_db_query' => ['resource', 'database'=>'string', 'query'=>'string', 'link_identifier='=>'?resource'], 'msql_drop_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'msql_error' => ['string'], 'msql_fetch_array' => ['array', 'result'=>'resource', 'result_type='=>'int'], 'msql_fetch_field' => ['object', 'result'=>'resource', 'field_offset='=>'int'], 'msql_fetch_object' => ['object', 'result'=>'resource'], 'msql_fetch_row' => ['array', 'result'=>'resource'], 'msql_field_flags' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_len' => ['int', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_name' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_seek' => ['bool', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_table' => ['int', 'result'=>'resource', 'field_offset'=>'int'], 'msql_field_type' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'msql_free_result' => ['bool', 'result'=>'resource'], 'msql_list_dbs' => ['resource', 'link_identifier='=>'?resource'], 'msql_list_fields' => ['resource', 'database'=>'string', 'tablename'=>'string', 'link_identifier='=>'?resource'], 'msql_list_tables' => ['resource', 'database'=>'string', 'link_identifier='=>'?resource'], 'msql_num_fields' => ['int', 'result'=>'resource'], 'msql_num_rows' => ['int', 'query_identifier'=>'resource'], 'msql_pconnect' => ['resource', 'hostname='=>'string'], 'msql_query' => ['resource', 'query'=>'string', 'link_identifier='=>'?resource'], 'msql_result' => ['string', 'result'=>'resource', 'row'=>'int', 'field='=>'mixed'], 'msql_select_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'?resource'], 'mssql_bind' => ['bool', 'stmt'=>'resource', 'param_name'=>'string', 'var'=>'mixed', 'type'=>'int', 'is_output='=>'bool', 'is_null='=>'bool', 'maxlen='=>'int'], 'mssql_close' => ['bool', 'link_identifier='=>'resource'], 'mssql_connect' => ['resource', 'servername='=>'string', 'username='=>'string', 'password='=>'string', 'new_link='=>'bool'], 'mssql_data_seek' => ['bool', 'result_identifier'=>'resource', 'row_number'=>'int'], 'mssql_execute' => ['mixed', 'stmt'=>'resource', 'skip_results='=>'bool'], 'mssql_fetch_array' => ['array', 'result'=>'resource', 'result_type='=>'int'], 'mssql_fetch_assoc' => ['array', 'result_id'=>'resource'], 'mssql_fetch_batch' => ['int', 'result'=>'resource'], 'mssql_fetch_field' => ['object', 'result'=>'resource', 'field_offset='=>'int'], 'mssql_fetch_object' => ['object', 'result'=>'resource'], 'mssql_fetch_row' => ['array', 'result'=>'resource'], 'mssql_field_length' => ['int', 'result'=>'resource', 'offset='=>'int'], 'mssql_field_name' => ['string', 'result'=>'resource', 'offset='=>'int'], 'mssql_field_seek' => ['bool', 'result'=>'resource', 'field_offset'=>'int'], 'mssql_field_type' => ['string', 'result'=>'resource', 'offset='=>'int'], 'mssql_free_result' => ['bool', 'result'=>'resource'], 'mssql_free_statement' => ['bool', 'stmt'=>'resource'], 'mssql_get_last_message' => ['string'], 'mssql_guid_string' => ['string', 'binary'=>'string', 'short_format='=>'bool'], 'mssql_init' => ['resource', 'sp_name'=>'string', 'link_identifier='=>'resource'], 'mssql_min_error_severity' => ['void', 'severity'=>'int'], 'mssql_min_message_severity' => ['void', 'severity'=>'int'], 'mssql_next_result' => ['bool', 'result_id'=>'resource'], 'mssql_num_fields' => ['int', 'result'=>'resource'], 'mssql_num_rows' => ['int', 'result'=>'resource'], 'mssql_pconnect' => ['resource', 'servername='=>'string', 'username='=>'string', 'password='=>'string', 'new_link='=>'bool'], 'mssql_query' => ['mixed', 'query'=>'string', 'link_identifier='=>'resource', 'batch_size='=>'int'], 'mssql_result' => ['string', 'result'=>'resource', 'row'=>'int', 'field'=>'mixed'], 'mssql_rows_affected' => ['int', 'link_identifier'=>'resource'], 'mssql_select_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'resource'], 'mt_getrandmax' => ['int'], 'mt_rand' => ['int', 'min'=>'int', 'max'=>'int'], 'mt_rand\'1' => ['int'], 'mt_srand' => ['void', 'seed='=>'int', 'mode='=>'int'], 'MultipleIterator::__construct' => ['void', 'flags='=>'int'], 'MultipleIterator::attachIterator' => ['void', 'iterator'=>'Iterator', 'infos='=>'string'], 'MultipleIterator::containsIterator' => ['bool', 'iterator'=>'Iterator'], 'MultipleIterator::countIterators' => ['int'], 'MultipleIterator::current' => ['array'], 'MultipleIterator::detachIterator' => ['void', 'iterator'=>'Iterator'], 'MultipleIterator::getFlags' => ['int'], 'MultipleIterator::key' => ['array'], 'MultipleIterator::next' => ['void'], 'MultipleIterator::rewind' => ['void'], 'MultipleIterator::setFlags' => ['int', 'flags'=>'int'], 'MultipleIterator::valid' => ['bool'], 'mysql_affected_rows' => ['int', 'link_identifier='=>'resource'], 'mysql_client_encoding' => ['string', 'link_identifier='=>'resource'], 'mysql_close' => ['bool', 'link_identifier='=>'resource'], 'mysql_connect' => ['resource|false', 'server='=>'string', 'username='=>'string', 'password='=>'string', 'new_link='=>'bool', 'client_flags='=>'int'], 'mysql_create_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'resource'], 'mysql_data_seek' => ['bool', 'result'=>'resource', 'row_number'=>'int'], 'mysql_db_name' => ['string|false', 'result'=>'resource', 'row'=>'int', 'field='=>'mixed'], 'mysql_db_query' => ['resource|bool', 'database'=>'string', 'query'=>'string', 'link_identifier='=>'resource'], 'mysql_drop_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'resource'], 'mysql_errno' => ['int', 'link_identifier='=>'resource'], 'mysql_error' => ['string', 'link_identifier='=>'resource'], 'mysql_escape_string' => ['string', 'unescaped_string'=>'string'], 'mysql_fetch_array' => ['array|false', 'result'=>'resource', 'result_type='=>'int'], 'mysql_fetch_assoc' => ['array|false', 'result'=>'resource'], 'mysql_fetch_field' => ['object', 'result'=>'resource', 'field_offset='=>'int'], 'mysql_fetch_lengths' => ['array|false', 'result'=>'resource'], 'mysql_fetch_object' => ['object|false', 'result'=>'resource', 'class_name='=>'string', 'params='=>'array'], 'mysql_fetch_row' => ['array|false', 'result'=>'resource'], 'mysql_field_flags' => ['string|false', 'result'=>'resource', 'field_offset'=>'int'], 'mysql_field_len' => ['int|false', 'result'=>'resource', 'field_offset'=>'int'], 'mysql_field_name' => ['string|false', 'result'=>'resource', 'field_offset'=>'int'], 'mysql_field_seek' => ['bool', 'result'=>'resource', 'field_offset'=>'int'], 'mysql_field_table' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'mysql_field_type' => ['string', 'result'=>'resource', 'field_offset'=>'int'], 'mysql_free_result' => ['bool', 'result'=>'resource'], 'mysql_get_client_info' => ['string'], 'mysql_get_host_info' => ['string|false', 'link_identifier='=>'resource'], 'mysql_get_proto_info' => ['int|false', 'link_identifier='=>'resource'], 'mysql_get_server_info' => ['string|false', 'link_identifier='=>'resource'], 'mysql_info' => ['string|false', 'link_identifier='=>'resource'], 'mysql_insert_id' => ['int|false', 'link_identifier='=>'resource'], 'mysql_list_dbs' => ['resource|false', 'link_identifier='=>'resource'], 'mysql_list_fields' => ['resource|false', 'database_name'=>'string', 'table_name'=>'string', 'link_identifier='=>'resource'], 'mysql_list_processes' => ['resource|false', 'link_identifier='=>'resource'], 'mysql_list_tables' => ['resource', 'database'=>'string', 'link_identifier='=>'resource'], 'mysql_num_fields' => ['int|false', 'result'=>'resource'], 'mysql_num_rows' => ['int|false', 'result'=>'resource'], 'mysql_pconnect' => ['resource|false', 'server='=>'string', 'username='=>'string', 'password='=>'string', 'client_flags='=>'int'], 'mysql_ping' => ['bool', 'link_identifier='=>'resource'], 'mysql_query' => ['resource|bool', 'query'=>'string', 'link_identifier='=>'resource'], 'mysql_real_escape_string' => ['string|false', 'unescaped_string'=>'string', 'link_identifier='=>'resource'], 'mysql_result' => ['string|false', 'result'=>'resource', 'row'=>'int', 'field='=>'mixed'], 'mysql_select_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'resource'], 'mysql_set_charset' => ['bool', 'charset'=>'string', 'link_identifier='=>'resource'], 'mysql_stat' => ['string|null', 'link_identifier='=>'resource'], 'mysql_tablename' => ['string|false', 'result'=>'resource', 'i'=>'int'], 'mysql_thread_id' => ['int|false', 'link_identifier='=>'resource'], 'mysql_unbuffered_query' => ['resource|bool', 'query'=>'string', 'link_identifier='=>'resource'], 'mysqli::__construct' => ['void', 'host='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'mysqli::autocommit' => ['bool', 'mode'=>'bool'], 'mysqli::begin_transaction' => ['bool', 'flags='=>'int', 'name='=>'string'], 'mysqli::change_user' => ['bool', 'user'=>'string', 'password'=>'string', 'database'=>'string'], 'mysqli::character_set_name' => ['string'], 'mysqli::close' => ['bool'], 'mysqli::commit' => ['bool', 'flags='=>'int', 'name='=>'string'], 'mysqli::debug' => ['bool', 'message'=>'string'], 'mysqli::disable_reads_from_master' => ['bool'], 'mysqli::dump_debug_info' => ['bool'], 'mysqli::get_charset' => ['object'], 'mysqli::get_client_info' => ['string'], 'mysqli::get_connection_stats' => ['array|false'], 'mysqli::get_warnings' => ['mysqli_warning|false'], 'mysqli::init' => ['mysqli'], 'mysqli::kill' => ['bool', 'processid'=>'int'], 'mysqli::more_results' => ['bool'], 'mysqli::multi_query' => ['bool', 'query'=>'string'], 'mysqli::next_result' => ['bool'], 'mysqli::options' => ['bool', 'option'=>'int', 'value'=>'mixed'], 'mysqli::ping' => ['bool'], 'mysqli::poll' => ['int|false', '&w_read'=>'array', '&w_error'=>'array', '&w_reject'=>'array', 'sec'=>'int', 'usec='=>'int'], 'mysqli::prepare' => ['mysqli_stmt|false', 'query'=>'string'], 'mysqli::query' => ['bool|mysqli_result', 'query'=>'string', 'resultmode='=>'int'], 'mysqli::real_connect' => ['bool', 'host='=>'?string', 'username='=>'?string', 'passwd='=>'?string', 'dbname='=>'?string', 'port='=>'?int', 'socket='=>'?string', 'flags='=>'int'], 'mysqli::real_escape_string' => ['string', 'escapestr'=>'string'], 'mysqli::real_query' => ['bool', 'query'=>'string'], 'mysqli::reap_async_query' => ['mysqli_result|false'], 'mysqli::refresh' => ['bool', 'options'=>'int'], 'mysqli::release_savepoint' => ['bool', 'name'=>'string'], 'mysqli::rollback' => ['bool', 'flags='=>'int', 'name='=>'string'], 'mysqli::rpl_query_type' => ['int', 'query'=>'string'], 'mysqli::savepoint' => ['bool', 'name'=>'string'], 'mysqli::select_db' => ['bool', 'dbname'=>'string'], 'mysqli::send_query' => ['bool', 'query'=>'string'], 'mysqli::set_charset' => ['bool', 'charset'=>'string'], 'mysqli::set_local_infile_default' => ['void'], 'mysqli::set_local_infile_handler' => ['bool', 'read_func='=>'callable'], 'mysqli::ssl_set' => ['bool', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'mysqli::stat' => ['string|false'], 'mysqli::stmt_init' => ['mysqli_stmt'], 'mysqli::store_result' => ['mysqli_result|false', 'option='=>'int'], 'mysqli::thread_safe' => ['bool'], 'mysqli::use_result' => ['mysqli_result|false'], 'mysqli_affected_rows' => ['int<-1,max>|numeric-string', 'link'=>'mysqli'], 'mysqli_autocommit' => ['bool', 'link'=>'mysqli', 'mode'=>'bool'], 'mysqli_begin_transaction' => ['bool', 'link'=>'mysqli', 'flags='=>'int', 'name='=>'string'], 'mysqli_change_user' => ['bool', 'link'=>'mysqli', 'user'=>'string', 'password'=>'string', 'database'=>'string'], 'mysqli_character_set_name' => ['string', 'link'=>'mysqli'], 'mysqli_close' => ['bool', 'link'=>'mysqli'], 'mysqli_commit' => ['bool', 'link'=>'mysqli', 'flags='=>'int', 'name='=>'string'], 'mysqli_connect' => ['mysqli|false|null', 'host='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'mysqli_connect_errno' => ['int'], 'mysqli_connect_error' => ['string|null'], 'mysqli_data_seek' => ['bool', 'result'=>'mysqli_result', 'offset'=>'int'], 'mysqli_debug' => ['bool', 'message'=>'string'], 'mysqli_disable_reads_from_master' => ['bool', 'link'=>'mysqli'], 'mysqli_disable_rpl_parse' => ['bool', 'link'=>'mysqli'], 'mysqli_driver::embedded_server_end' => ['void'], 'mysqli_driver::embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'], 'mysqli_dump_debug_info' => ['bool', 'link'=>'mysqli'], 'mysqli_embedded_server_end' => ['void'], 'mysqli_embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'], 'mysqli_enable_reads_from_master' => ['bool', 'link'=>'mysqli'], 'mysqli_enable_rpl_parse' => ['bool', 'link'=>'mysqli'], 'mysqli_errno' => ['int', 'link'=>'mysqli'], 'mysqli_error' => ['string|null', 'link'=>'mysqli'], 'mysqli_error_list' => ['array', 'connection'=>'mysqli'], 'mysqli_fetch_all' => ['array', 'result'=>'mysqli_result', 'resulttype='=>'int'], 'mysqli_fetch_array' => ['array|null|false', 'result'=>'mysqli_result', 'resulttype='=>'int'], 'mysqli_fetch_assoc' => ['array|null|false', 'result'=>'mysqli_result'], 'mysqli_fetch_column' => ['null|int|float|string|false', 'result' => 'mysqli_result', 'column'=>'int'], 'mysqli_fetch_field' => ['(stdClass&object{name: string, orgname: string, table: string, orgtable: string, def: string, db: string, catalog: "def", max_length: int, length: int, charsetnr: string, flags: int, type: int, decimals: int})|false', 'result'=>'mysqli_result'], 'mysqli_fetch_field_direct' => ['(stdClass&object{name: string, orgname: string, table: string, orgtable: string, def: string, db: string, catalog: "def", max_length: int, length: int, charsetnr: string, flags: int, type: int, decimals: int})|false', 'result'=>'mysqli_result', 'fieldnr'=>'int'], 'mysqli_fetch_fields' => ['list', 'result'=>'mysqli_result'], 'mysqli_fetch_lengths' => ['array|false', 'result'=>'mysqli_result'], 'mysqli_fetch_object' => ['object|false|null', 'result'=>'mysqli_result', 'class_name='=>'string', 'params='=>'?array'], 'mysqli_fetch_row' => ['array|null', 'result'=>'mysqli_result'], 'mysqli_field_count' => ['int', 'link'=>'mysqli'], 'mysqli_field_seek' => ['bool', 'result'=>'mysqli_result', 'fieldnr'=>'int'], 'mysqli_field_tell' => ['int', 'result'=>'mysqli_result'], 'mysqli_free_result' => ['void', 'link'=>'mysqli_result'], 'mysqli_get_cache_stats' => ['array'], 'mysqli_get_charset' => ['object', 'link'=>'mysqli'], 'mysqli_get_client_info' => ['string', 'link='=>'mysqli'], 'mysqli_get_client_stats' => ['array|false'], 'mysqli_get_client_version' => ['int'], 'mysqli_get_connection_stats' => ['array|false', 'link'=>'mysqli'], 'mysqli_get_host_info' => ['string', 'link'=>'mysqli'], 'mysqli_get_links_stats' => ['array'], 'mysqli_get_proto_info' => ['int', 'link'=>'mysqli'], 'mysqli_get_server_info' => ['string', 'link'=>'mysqli'], 'mysqli_get_server_version' => ['int', 'link'=>'mysqli'], 'mysqli_get_warnings' => ['mysqli_warning|false', 'link'=>'mysqli'], 'mysqli_info' => ['?string', 'link'=>'mysqli'], 'mysqli_init' => ['mysqli|false'], 'mysqli_insert_id' => ['int|string', 'link'=>'mysqli'], 'mysqli_kill' => ['bool', 'link'=>'mysqli', 'processid'=>'int'], 'mysqli_link_construct' => ['object'], 'mysqli_master_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_more_results' => ['bool', 'link'=>'mysqli'], 'mysqli_multi_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_next_result' => ['bool', 'link'=>'mysqli'], 'mysqli_num_fields' => ['int', 'link'=>'mysqli_result'], 'mysqli_num_rows' => ['int<0,max>|numeric-string', 'link'=>'mysqli_result'], 'mysqli_options' => ['bool', 'link'=>'mysqli', 'option'=>'int', 'value'=>'mixed'], 'mysqli_ping' => ['bool', 'link'=>'mysqli'], 'mysqli_poll' => ['int|false', 'read'=>'array', 'error'=>'array', 'reject'=>'array', 'sec'=>'int', 'usec='=>'int'], 'mysqli_prepare' => ['mysqli_stmt|false', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_query' => ['mysqli_result|bool', 'link'=>'mysqli', 'query'=>'string', 'resultmode='=>'int'], 'mysqli_real_connect' => ['bool', 'link='=>'mysqli', 'host='=>'?string', 'username='=>'?string', 'passwd='=>'?string', 'dbname='=>'?string', 'port='=>'?int', 'socket='=>'?string', 'flags='=>'int'], 'mysqli_real_escape_string' => ['string', 'link'=>'mysqli', 'escapestr'=>'string'], 'mysqli_real_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_reap_async_query' => ['mysqli_result|false', 'link'=>'mysqli'], 'mysqli_refresh' => ['bool', 'link'=>'mysqli', 'options'=>'int'], 'mysqli_release_savepoint' => ['bool', 'link'=>'mysqli', 'name'=>'string'], 'mysqli_report' => ['bool', 'flags'=>'int'], 'mysqli_result::__construct' => ['void', 'link'=>'mysqli', 'resultmode='=>'int'], 'mysqli_result::close' => ['void'], 'mysqli_result::data_seek' => ['bool', 'offset'=>'int'], 'mysqli_result::fetch_all' => ['array', 'resulttype='=>'int'], 'mysqli_result::fetch_array' => ['array|null|false', 'resulttype='=>'int'], 'mysqli_result::fetch_assoc' => ['array|null|false'], 'mysqli_result::fetch_column' => ['null|int|float|string|false', 'column'=>'int'], 'mysqli_result::fetch_field' => ['(stdClass&object{name: string, orgname: string, table: string, orgtable: string, def: string, db: string, catalog: "def", max_length: int, length: int, charsetnr: string, flags: int, type: int, decimals: int})|false'], 'mysqli_result::fetch_field_direct' => ['(stdClass&object{name: string, orgname: string, table: string, orgtable: string, def: string, db: string, catalog: "def", max_length: int, length: int, charsetnr: string, flags: int, type: int, decimals: int})|false', 'fieldnr'=>'int'], 'mysqli_result::fetch_fields' => ['list'], 'mysqli_result::fetch_object' => ['object|null', 'class_name='=>'string', 'params='=>'array'], 'mysqli_result::fetch_row' => ['array|null'], 'mysqli_result::field_seek' => ['bool', 'fieldnr'=>'int'], 'mysqli_result::free' => ['void'], 'mysqli_result::free_result' => ['void'], 'mysqli_rollback' => ['bool', 'link'=>'mysqli', 'flags='=>'int', 'name='=>'string'], 'mysqli_rpl_parse_enabled' => ['int', 'link'=>'mysqli'], 'mysqli_rpl_probe' => ['bool', 'link'=>'mysqli'], 'mysqli_rpl_query_type' => ['int', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_savepoint' => ['bool', 'link'=>'mysqli', 'name'=>'string'], 'mysqli_savepoint_libmysql' => ['bool'], 'mysqli_select_db' => ['bool', 'link'=>'mysqli', 'dbname'=>'string'], 'mysqli_send_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_set_charset' => ['bool', 'link'=>'mysqli', 'charset'=>'string'], 'mysqli_set_local_infile_default' => ['void', 'link'=>'mysqli'], 'mysqli_set_local_infile_handler' => ['bool', 'link'=>'mysqli', 'read_func'=>'callable'], 'mysqli_slave_query' => ['bool', 'link'=>'mysqli', 'query'=>'string'], 'mysqli_sqlstate' => ['string', 'link'=>'mysqli'], 'mysqli_ssl_set' => ['bool', 'link'=>'mysqli', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'mysqli_stat' => ['string|false', 'link'=>'mysqli'], 'mysqli_stmt::__construct' => ['void', 'link'=>'mysqli', 'query='=>'string'], 'mysqli_stmt::attr_get' => ['false|int', 'attr'=>'int'], 'mysqli_stmt::attr_set' => ['bool', 'attr'=>'int', 'mode'=>'int'], 'mysqli_stmt::bind_param' => ['bool', 'types'=>'string', 'var1'=>'mixed', '...args='=>'mixed'], 'mysqli_stmt::bind_result' => ['bool', '&w_var1'=>'', '&...w_vars='=>''], 'mysqli_stmt::close' => ['bool'], 'mysqli_stmt::data_seek' => ['void', 'offset'=>'int'], 'mysqli_stmt::execute' => ['bool'], 'mysqli_stmt::fetch' => ['bool|null'], 'mysqli_stmt::free_result' => ['void'], 'mysqli_stmt::get_result' => ['mysqli_result|false'], 'mysqli_stmt::get_warnings' => ['mysqli_warning|false'], 'mysqli_stmt::more_results' => ['bool'], 'mysqli_stmt::next_result' => ['bool'], 'mysqli_stmt::num_rows' => ['int<0,max>|numeric-string'], 'mysqli_stmt::prepare' => ['bool', 'query'=>'string'], 'mysqli_stmt::reset' => ['bool'], 'mysqli_stmt::result_metadata' => ['mysqli_result|false'], 'mysqli_stmt::send_long_data' => ['bool', 'param_nr'=>'int', 'data'=>'string'], 'mysqli_stmt::store_result' => ['bool'], 'mysqli_stmt_affected_rows' => ['int<-1,max>|numeric-string', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_attr_get' => ['int|false', 'stmt'=>'mysqli_stmt', 'attr'=>'int'], 'mysqli_stmt_attr_set' => ['bool', 'stmt'=>'mysqli_stmt', 'attr'=>'int', 'mode'=>'int'], 'mysqli_stmt_bind_param' => ['bool', 'stmt'=>'mysqli_stmt', 'types'=>'string', 'var1'=>'mixed', '...args='=>'mixed'], 'mysqli_stmt_bind_result' => ['bool', 'stmt'=>'mysqli_stmt', '&w_var1'=>'', '&...w_vars='=>''], 'mysqli_stmt_close' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_data_seek' => ['void', 'stmt'=>'mysqli_stmt', 'offset'=>'int'], 'mysqli_stmt_errno' => ['int', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_error' => ['string', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_error_list' => ['list', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_execute' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_fetch' => ['bool|null', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_field_count' => ['0|positive-int', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_free_result' => ['void', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_get_result' => ['mysqli_result|false', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_get_warnings' => ['mysqli_warning|false', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_init' => ['mysqli_stmt|false', 'link'=>'mysqli'], 'mysqli_stmt_insert_id' => ['', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_more_results' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_next_result' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_num_rows' => ['0|positive-int', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_param_count' => ['0|positive-int', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_prepare' => ['bool', 'stmt'=>'mysqli_stmt', 'query'=>'string'], 'mysqli_stmt_reset' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_result_metadata' => ['mysqli_result|false', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_send_long_data' => ['bool', 'stmt'=>'mysqli_stmt', 'param_nr'=>'int', 'data'=>'string'], 'mysqli_stmt_sqlstate' => ['non-empty-string', 'stmt'=>'mysqli_stmt'], 'mysqli_stmt_store_result' => ['bool', 'stmt'=>'mysqli_stmt'], 'mysqli_store_result' => ['mysqli_result|false', 'link'=>'mysqli', 'option='=>'int'], 'mysqli_thread_id' => ['int', 'link'=>'mysqli'], 'mysqli_thread_safe' => ['bool'], 'mysqli_use_result' => ['mysqli_result|false', 'link'=>'mysqli'], 'mysqli_warning::__construct' => ['void'], 'mysqli_warning::next' => ['bool'], 'mysqli_warning_count' => ['int', 'link'=>'mysqli'], 'mysqlnd_memcache_get_config' => ['array', 'connection'=>'mixed'], 'mysqlnd_memcache_set' => ['bool', 'mysql_connection'=>'mixed', 'memcache_connection='=>'Memcached', 'pattern='=>'string', 'callback='=>'callable'], 'mysqlnd_ms_dump_servers' => ['array', 'connection'=>'mixed'], 'mysqlnd_ms_fabric_select_global' => ['array', 'connection'=>'mixed', 'table_name'=>'mixed'], 'mysqlnd_ms_fabric_select_shard' => ['array', 'connection'=>'mixed', 'table_name'=>'mixed', 'shard_key'=>'mixed'], 'mysqlnd_ms_get_last_gtid' => ['string', 'connection'=>'mixed'], 'mysqlnd_ms_get_last_used_connection' => ['array', 'connection'=>'mixed'], 'mysqlnd_ms_get_stats' => ['array'], 'mysqlnd_ms_match_wild' => ['bool', 'table_name'=>'string', 'wildcard'=>'string'], 'mysqlnd_ms_query_is_select' => ['int', 'query'=>'string'], 'mysqlnd_ms_set_qos' => ['bool', 'connection'=>'mixed', 'service_level'=>'int', 'service_level_option='=>'int', 'option_value='=>'mixed'], 'mysqlnd_ms_set_user_pick_server' => ['bool', 'function'=>'string'], 'mysqlnd_ms_xa_begin' => ['int', 'connection'=>'mixed', 'gtrid'=>'string', 'timeout='=>'int'], 'mysqlnd_ms_xa_commit' => ['int', 'connection'=>'mixed', 'gtrid'=>'string'], 'mysqlnd_ms_xa_gc' => ['int', 'connection'=>'mixed', 'gtrid='=>'string', 'ignore_max_retries='=>'bool'], 'mysqlnd_ms_xa_rollback' => ['int', 'connection'=>'mixed', 'gtrid'=>'string'], 'mysqlnd_qc_change_handler' => ['bool', 'handler'=>''], 'mysqlnd_qc_clear_cache' => ['bool'], 'mysqlnd_qc_get_available_handlers' => ['array'], 'mysqlnd_qc_get_cache_info' => ['array'], 'mysqlnd_qc_get_core_stats' => ['array'], 'mysqlnd_qc_get_handler' => ['array'], 'mysqlnd_qc_get_normalized_query_trace_log' => ['array'], 'mysqlnd_qc_get_query_trace_log' => ['array'], 'mysqlnd_qc_set_cache_condition' => ['bool', 'condition_type'=>'int', 'condition'=>'mixed', 'condition_option'=>'mixed'], 'mysqlnd_qc_set_is_select' => ['mixed', 'callback'=>'string'], 'mysqlnd_qc_set_storage_handler' => ['bool', 'handler'=>'string'], 'mysqlnd_qc_set_user_handlers' => ['bool', 'get_hash'=>'string', 'find_query_in_cache'=>'string', 'return_to_cache'=>'string', 'add_query_to_cache_if_not_exists'=>'string', 'query_is_select'=>'string', 'update_query_run_time_stats'=>'string', 'get_stats'=>'string', 'clear_cache'=>'string'], 'mysqlnd_uh_convert_to_mysqlnd' => ['resource', '&rw_mysql_connection'=>'mysqli'], 'mysqlnd_uh_set_connection_proxy' => ['bool', '&rw_connection_proxy'=>'MysqlndUhConnection', '&rw_mysqli_connection='=>'mysqli'], 'mysqlnd_uh_set_statement_proxy' => ['bool', '&rw_statement_proxy'=>'MysqlndUhStatement'], 'MysqlndUhConnection::__construct' => ['void'], 'MysqlndUhConnection::changeUser' => ['bool', 'connection'=>'mysqlnd_connection', 'user'=>'string', 'password'=>'string', 'database'=>'string', 'silent'=>'bool', 'passwd_len'=>'int'], 'MysqlndUhConnection::charsetName' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::close' => ['bool', 'connection'=>'mysqlnd_connection', 'close_type'=>'int'], 'MysqlndUhConnection::connect' => ['bool', 'connection'=>'mysqlnd_connection', 'host'=>'string', 'use'=>'string', 'password'=>'string', 'database'=>'string', 'port'=>'int', 'socket'=>'string', 'mysql_flags'=>'int'], 'MysqlndUhConnection::endPSession' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::escapeString' => ['string', 'connection'=>'mysqlnd_connection', 'escape_string'=>'string'], 'MysqlndUhConnection::getAffectedRows' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getErrorNumber' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getErrorString' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getFieldCount' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getHostInformation' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getLastInsertId' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getLastMessage' => ['void', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getProtocolInformation' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getServerInformation' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getServerStatistics' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getServerVersion' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getSqlstate' => ['string', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getStatistics' => ['array', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getThreadId' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::getWarningCount' => ['int', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::init' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::killConnection' => ['bool', 'connection'=>'mysqlnd_connection', 'pid'=>'int'], 'MysqlndUhConnection::listFields' => ['array', 'connection'=>'mysqlnd_connection', 'table'=>'string', 'achtung_wild'=>'string'], 'MysqlndUhConnection::listMethod' => ['void', 'connection'=>'mysqlnd_connection', 'query'=>'string', 'achtung_wild'=>'string', 'par1'=>'string'], 'MysqlndUhConnection::moreResults' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::nextResult' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::ping' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::query' => ['bool', 'connection'=>'mysqlnd_connection', 'query'=>'string'], 'MysqlndUhConnection::queryReadResultsetHeader' => ['bool', 'connection'=>'mysqlnd_connection', 'mysqlnd_stmt'=>'mysqlnd_statement'], 'MysqlndUhConnection::reapQuery' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::refreshServer' => ['bool', 'connection'=>'mysqlnd_connection', 'options'=>'int'], 'MysqlndUhConnection::restartPSession' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::selectDb' => ['bool', 'connection'=>'mysqlnd_connection', 'database'=>'string'], 'MysqlndUhConnection::sendClose' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::sendQuery' => ['bool', 'connection'=>'mysqlnd_connection', 'query'=>'string'], 'MysqlndUhConnection::serverDumpDebugInformation' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::setAutocommit' => ['bool', 'connection'=>'mysqlnd_connection', 'mode'=>'int'], 'MysqlndUhConnection::setCharset' => ['bool', 'connection'=>'mysqlnd_connection', 'charset'=>'string'], 'MysqlndUhConnection::setClientOption' => ['bool', 'connection'=>'mysqlnd_connection', 'option'=>'int', 'value'=>'int'], 'MysqlndUhConnection::setServerOption' => ['void', 'connection'=>'mysqlnd_connection', 'option'=>'int'], 'MysqlndUhConnection::shutdownServer' => ['void', 'MYSQLND_UH_RES_MYSQLND_NAME'=>'string', 'level'=>'string'], 'MysqlndUhConnection::simpleCommand' => ['bool', 'connection'=>'mysqlnd_connection', 'command'=>'int', 'arg'=>'string', 'ok_packet'=>'int', 'silent'=>'bool', 'ignore_upsert_status'=>'bool'], 'MysqlndUhConnection::simpleCommandHandleResponse' => ['bool', 'connection'=>'mysqlnd_connection', 'ok_packet'=>'int', 'silent'=>'bool', 'command'=>'int', 'ignore_upsert_status'=>'bool'], 'MysqlndUhConnection::sslSet' => ['bool', 'connection'=>'mysqlnd_connection', 'key'=>'string', 'cert'=>'string', 'ca'=>'string', 'capath'=>'string', 'cipher'=>'string'], 'MysqlndUhConnection::stmtInit' => ['resource', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::storeResult' => ['resource', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::txCommit' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::txRollback' => ['bool', 'connection'=>'mysqlnd_connection'], 'MysqlndUhConnection::useResult' => ['resource', 'connection'=>'mysqlnd_connection'], 'MysqlndUhPreparedStatement::__construct' => ['void'], 'MysqlndUhPreparedStatement::execute' => ['bool', 'statement'=>'mysqlnd_prepared_statement'], 'MysqlndUhPreparedStatement::prepare' => ['bool', 'statement'=>'mysqlnd_prepared_statement', 'query'=>'string'], 'natcasesort' => ['bool', '&rw_array_arg'=>'array'], 'natsort' => ['bool', '&rw_array_arg'=>'array'], 'ncurses_addch' => ['int', 'ch'=>'int'], 'ncurses_addchnstr' => ['int', 's'=>'string', 'n'=>'int'], 'ncurses_addchstr' => ['int', 's'=>'string'], 'ncurses_addnstr' => ['int', 's'=>'string', 'n'=>'int'], 'ncurses_addstr' => ['int', 'text'=>'string'], 'ncurses_assume_default_colors' => ['int', 'fg'=>'int', 'bg'=>'int'], 'ncurses_attroff' => ['int', 'attributes'=>'int'], 'ncurses_attron' => ['int', 'attributes'=>'int'], 'ncurses_attrset' => ['int', 'attributes'=>'int'], 'ncurses_baudrate' => ['int'], 'ncurses_beep' => ['int'], 'ncurses_bkgd' => ['int', 'attrchar'=>'int'], 'ncurses_bkgdset' => ['void', 'attrchar'=>'int'], 'ncurses_border' => ['int', 'left'=>'int', 'right'=>'int', 'top'=>'int', 'bottom'=>'int', 'tl_corner'=>'int', 'tr_corner'=>'int', 'bl_corner'=>'int', 'br_corner'=>'int'], 'ncurses_bottom_panel' => ['int', 'panel'=>'resource'], 'ncurses_can_change_color' => ['bool'], 'ncurses_cbreak' => ['bool'], 'ncurses_clear' => ['bool'], 'ncurses_clrtobot' => ['bool'], 'ncurses_clrtoeol' => ['bool'], 'ncurses_color_content' => ['int', 'color'=>'int', 'r'=>'int', 'g'=>'int', 'b'=>'int'], 'ncurses_color_set' => ['int', 'pair'=>'int'], 'ncurses_curs_set' => ['int', 'visibility'=>'int'], 'ncurses_def_prog_mode' => ['bool'], 'ncurses_def_shell_mode' => ['bool'], 'ncurses_define_key' => ['int', 'definition'=>'string', 'keycode'=>'int'], 'ncurses_del_panel' => ['bool', 'panel'=>'resource'], 'ncurses_delay_output' => ['int', 'milliseconds'=>'int'], 'ncurses_delch' => ['bool'], 'ncurses_deleteln' => ['bool'], 'ncurses_delwin' => ['bool', 'window'=>'resource'], 'ncurses_doupdate' => ['bool'], 'ncurses_echo' => ['bool'], 'ncurses_echochar' => ['int', 'character'=>'int'], 'ncurses_end' => ['int'], 'ncurses_erase' => ['bool'], 'ncurses_erasechar' => ['string'], 'ncurses_filter' => ['void'], 'ncurses_flash' => ['bool'], 'ncurses_flushinp' => ['bool'], 'ncurses_getch' => ['int'], 'ncurses_getmaxyx' => ['void', 'window'=>'resource', 'y'=>'int', 'x'=>'int'], 'ncurses_getmouse' => ['bool', 'mevent'=>'array'], 'ncurses_getyx' => ['void', 'window'=>'resource', 'y'=>'int', 'x'=>'int'], 'ncurses_halfdelay' => ['int', 'tenth'=>'int'], 'ncurses_has_colors' => ['bool'], 'ncurses_has_ic' => ['bool'], 'ncurses_has_il' => ['bool'], 'ncurses_has_key' => ['int', 'keycode'=>'int'], 'ncurses_hide_panel' => ['int', 'panel'=>'resource'], 'ncurses_hline' => ['int', 'charattr'=>'int', 'n'=>'int'], 'ncurses_inch' => ['string'], 'ncurses_init' => ['void'], 'ncurses_init_color' => ['int', 'color'=>'int', 'r'=>'int', 'g'=>'int', 'b'=>'int'], 'ncurses_init_pair' => ['int', 'pair'=>'int', 'fg'=>'int', 'bg'=>'int'], 'ncurses_insch' => ['int', 'character'=>'int'], 'ncurses_insdelln' => ['int', 'count'=>'int'], 'ncurses_insertln' => ['int'], 'ncurses_insstr' => ['int', 'text'=>'string'], 'ncurses_instr' => ['int', 'buffer'=>'string'], 'ncurses_isendwin' => ['bool'], 'ncurses_keyok' => ['int', 'keycode'=>'int', 'enable'=>'bool'], 'ncurses_keypad' => ['int', 'window'=>'resource', 'bf'=>'bool'], 'ncurses_killchar' => ['string'], 'ncurses_longname' => ['string'], 'ncurses_meta' => ['int', 'window'=>'resource', '_8bit'=>'bool'], 'ncurses_mouse_trafo' => ['bool', 'y'=>'int', 'x'=>'int', 'toscreen'=>'bool'], 'ncurses_mouseinterval' => ['int', 'milliseconds'=>'int'], 'ncurses_mousemask' => ['int', 'newmask'=>'int', 'oldmask'=>'int'], 'ncurses_move' => ['int', 'y'=>'int', 'x'=>'int'], 'ncurses_move_panel' => ['int', 'panel'=>'resource', 'startx'=>'int', 'starty'=>'int'], 'ncurses_mvaddch' => ['int', 'y'=>'int', 'x'=>'int', 'c'=>'int'], 'ncurses_mvaddchnstr' => ['int', 'y'=>'int', 'x'=>'int', 's'=>'string', 'n'=>'int'], 'ncurses_mvaddchstr' => ['int', 'y'=>'int', 'x'=>'int', 's'=>'string'], 'ncurses_mvaddnstr' => ['int', 'y'=>'int', 'x'=>'int', 's'=>'string', 'n'=>'int'], 'ncurses_mvaddstr' => ['int', 'y'=>'int', 'x'=>'int', 's'=>'string'], 'ncurses_mvcur' => ['int', 'old_y'=>'int', 'old_x'=>'int', 'new_y'=>'int', 'new_x'=>'int'], 'ncurses_mvdelch' => ['int', 'y'=>'int', 'x'=>'int'], 'ncurses_mvgetch' => ['int', 'y'=>'int', 'x'=>'int'], 'ncurses_mvhline' => ['int', 'y'=>'int', 'x'=>'int', 'attrchar'=>'int', 'n'=>'int'], 'ncurses_mvinch' => ['int', 'y'=>'int', 'x'=>'int'], 'ncurses_mvvline' => ['int', 'y'=>'int', 'x'=>'int', 'attrchar'=>'int', 'n'=>'int'], 'ncurses_mvwaddstr' => ['int', 'window'=>'resource', 'y'=>'int', 'x'=>'int', 'text'=>'string'], 'ncurses_napms' => ['int', 'milliseconds'=>'int'], 'ncurses_new_panel' => ['resource', 'window'=>'resource'], 'ncurses_newpad' => ['resource', 'rows'=>'int', 'cols'=>'int'], 'ncurses_newwin' => ['resource', 'rows'=>'int', 'cols'=>'int', 'y'=>'int', 'x'=>'int'], 'ncurses_nl' => ['bool'], 'ncurses_nocbreak' => ['bool'], 'ncurses_noecho' => ['bool'], 'ncurses_nonl' => ['bool'], 'ncurses_noqiflush' => ['void'], 'ncurses_noraw' => ['bool'], 'ncurses_pair_content' => ['int', 'pair'=>'int', 'f'=>'int', 'b'=>'int'], 'ncurses_panel_above' => ['resource', 'panel'=>'resource'], 'ncurses_panel_below' => ['resource', 'panel'=>'resource'], 'ncurses_panel_window' => ['resource', 'panel'=>'resource'], 'ncurses_pnoutrefresh' => ['int', 'pad'=>'resource', 'pminrow'=>'int', 'pmincol'=>'int', 'sminrow'=>'int', 'smincol'=>'int', 'smaxrow'=>'int', 'smaxcol'=>'int'], 'ncurses_prefresh' => ['int', 'pad'=>'resource', 'pminrow'=>'int', 'pmincol'=>'int', 'sminrow'=>'int', 'smincol'=>'int', 'smaxrow'=>'int', 'smaxcol'=>'int'], 'ncurses_putp' => ['int', 'text'=>'string'], 'ncurses_qiflush' => ['void'], 'ncurses_raw' => ['bool'], 'ncurses_refresh' => ['int', 'ch'=>'int'], 'ncurses_replace_panel' => ['int', 'panel'=>'resource', 'window'=>'resource'], 'ncurses_reset_prog_mode' => ['int'], 'ncurses_reset_shell_mode' => ['int'], 'ncurses_resetty' => ['bool'], 'ncurses_savetty' => ['bool'], 'ncurses_scr_dump' => ['int', 'filename'=>'string'], 'ncurses_scr_init' => ['int', 'filename'=>'string'], 'ncurses_scr_restore' => ['int', 'filename'=>'string'], 'ncurses_scr_set' => ['int', 'filename'=>'string'], 'ncurses_scrl' => ['int', 'count'=>'int'], 'ncurses_show_panel' => ['int', 'panel'=>'resource'], 'ncurses_slk_attr' => ['int'], 'ncurses_slk_attroff' => ['int', 'intarg'=>'int'], 'ncurses_slk_attron' => ['int', 'intarg'=>'int'], 'ncurses_slk_attrset' => ['int', 'intarg'=>'int'], 'ncurses_slk_clear' => ['bool'], 'ncurses_slk_color' => ['int', 'intarg'=>'int'], 'ncurses_slk_init' => ['bool', 'format'=>'int'], 'ncurses_slk_noutrefresh' => ['bool'], 'ncurses_slk_refresh' => ['int'], 'ncurses_slk_restore' => ['int'], 'ncurses_slk_set' => ['bool', 'labelnr'=>'int', 'label'=>'string', 'format'=>'int'], 'ncurses_slk_touch' => ['int'], 'ncurses_standend' => ['int'], 'ncurses_standout' => ['int'], 'ncurses_start_color' => ['int'], 'ncurses_termattrs' => ['bool'], 'ncurses_termname' => ['string'], 'ncurses_timeout' => ['void', 'millisec'=>'int'], 'ncurses_top_panel' => ['int', 'panel'=>'resource'], 'ncurses_typeahead' => ['int', 'fd'=>'int'], 'ncurses_ungetch' => ['int', 'keycode'=>'int'], 'ncurses_ungetmouse' => ['bool', 'mevent'=>'array'], 'ncurses_update_panels' => ['void'], 'ncurses_use_default_colors' => ['bool'], 'ncurses_use_env' => ['void', 'flag'=>'bool'], 'ncurses_use_extended_names' => ['int', 'flag'=>'bool'], 'ncurses_vidattr' => ['int', 'intarg'=>'int'], 'ncurses_vline' => ['int', 'charattr'=>'int', 'n'=>'int'], 'ncurses_waddch' => ['int', 'window'=>'resource', 'ch'=>'int'], 'ncurses_waddstr' => ['int', 'window'=>'resource', 'str'=>'string', 'n='=>'int'], 'ncurses_wattroff' => ['int', 'window'=>'resource', 'attrs'=>'int'], 'ncurses_wattron' => ['int', 'window'=>'resource', 'attrs'=>'int'], 'ncurses_wattrset' => ['int', 'window'=>'resource', 'attrs'=>'int'], 'ncurses_wborder' => ['int', 'window'=>'resource', 'left'=>'int', 'right'=>'int', 'top'=>'int', 'bottom'=>'int', 'tl_corner'=>'int', 'tr_corner'=>'int', 'bl_corner'=>'int', 'br_corner'=>'int'], 'ncurses_wclear' => ['int', 'window'=>'resource'], 'ncurses_wcolor_set' => ['int', 'window'=>'resource', 'color_pair'=>'int'], 'ncurses_werase' => ['int', 'window'=>'resource'], 'ncurses_wgetch' => ['int', 'window'=>'resource'], 'ncurses_whline' => ['int', 'window'=>'resource', 'charattr'=>'int', 'n'=>'int'], 'ncurses_wmouse_trafo' => ['bool', 'window'=>'resource', 'y'=>'int', 'x'=>'int', 'toscreen'=>'bool'], 'ncurses_wmove' => ['int', 'window'=>'resource', 'y'=>'int', 'x'=>'int'], 'ncurses_wnoutrefresh' => ['int', 'window'=>'resource'], 'ncurses_wrefresh' => ['int', 'window'=>'resource'], 'ncurses_wstandend' => ['int', 'window'=>'resource'], 'ncurses_wstandout' => ['int', 'window'=>'resource'], 'ncurses_wvline' => ['int', 'window'=>'resource', 'charattr'=>'int', 'n'=>'int'], 'net_get_interfaces' => ['array|false'], 'newrelic_add_custom_parameter' => ['bool', 'key'=>'string', 'value'=>''], 'newrelic_add_custom_tracer' => ['bool', 'function_name'=>'string'], 'newrelic_background_job' => ['void', 'flag='=>'bool'], 'newrelic_capture_params' => ['void', 'enable='=>'bool'], 'newrelic_custom_metric' => ['bool', 'metric_name'=>'string', 'value'=>'float'], 'newrelic_disable_autorum' => ['bool'], 'newrelic_end_of_transaction' => ['void'], 'newrelic_end_transaction' => ['bool', 'ignore='=>'bool'], 'newrelic_get_browser_timing_footer' => ['string', 'include_tags='=>'bool'], 'newrelic_get_browser_timing_header' => ['string', 'include_tags='=>'bool'], 'newrelic_ignore_apdex' => ['void'], 'newrelic_ignore_transaction' => ['void'], 'newrelic_name_transaction' => ['bool', 'name'=>'string'], 'newrelic_notice_error' => ['void', 'message'=>'string', 'exception='=>'Exception|Throwable'], 'newrelic_notice_error\'1' => ['void', 'unused_1'=>'string', 'message'=>'string', 'unused_2'=>'string', 'unused_3'=>'int', 'unused_4='=>''], 'newrelic_record_custom_event' => ['void', 'name'=>'string', 'attributes'=>'array'], 'newrelic_record_datastore_segment' => ['mixed', 'func'=>'callable', 'parameters'=>'array'], 'newrelic_set_appname' => ['bool', 'name'=>'string', 'license='=>'string', 'xmit='=>'bool'], 'newrelic_set_user_attributes' => ['bool', 'user'=>'string', 'account'=>'string', 'product'=>'string'], 'newrelic_start_transaction' => ['bool', 'appname'=>'string', 'license='=>'string'], 'newt_bell' => ['void'], 'newt_button' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string'], 'newt_button_bar' => ['resource', 'buttons'=>'array'], 'newt_centered_window' => ['int', 'width'=>'int', 'height'=>'int', 'title='=>'string'], 'newt_checkbox' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string', 'def_value'=>'string', 'seq='=>'string'], 'newt_checkbox_get_value' => ['string', 'checkbox'=>'resource'], 'newt_checkbox_set_flags' => ['void', 'checkbox'=>'resource', 'flags'=>'int', 'sense'=>'int'], 'newt_checkbox_set_value' => ['void', 'checkbox'=>'resource', 'value'=>'string'], 'newt_checkbox_tree' => ['resource', 'left'=>'int', 'top'=>'int', 'height'=>'int', 'flags='=>'int'], 'newt_checkbox_tree_add_item' => ['void', 'checkboxtree'=>'resource', 'text'=>'string', 'data'=>'mixed', 'flags'=>'int', 'index'=>'int', '...args='=>'int'], 'newt_checkbox_tree_find_item' => ['array', 'checkboxtree'=>'resource', 'data'=>'mixed'], 'newt_checkbox_tree_get_current' => ['mixed', 'checkboxtree'=>'resource'], 'newt_checkbox_tree_get_entry_value' => ['string', 'checkboxtree'=>'resource', 'data'=>'mixed'], 'newt_checkbox_tree_get_multi_selection' => ['array', 'checkboxtree'=>'resource', 'seqnum'=>'string'], 'newt_checkbox_tree_get_selection' => ['array', 'checkboxtree'=>'resource'], 'newt_checkbox_tree_multi' => ['resource', 'left'=>'int', 'top'=>'int', 'height'=>'int', 'seq'=>'string', 'flags='=>'int'], 'newt_checkbox_tree_set_current' => ['void', 'checkboxtree'=>'resource', 'data'=>'mixed'], 'newt_checkbox_tree_set_entry' => ['void', 'checkboxtree'=>'resource', 'data'=>'mixed', 'text'=>'string'], 'newt_checkbox_tree_set_entry_value' => ['void', 'checkboxtree'=>'resource', 'data'=>'mixed', 'value'=>'string'], 'newt_checkbox_tree_set_width' => ['void', 'checkbox_tree'=>'resource', 'width'=>'int'], 'newt_clear_key_buffer' => ['void'], 'newt_cls' => ['void'], 'newt_compact_button' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string'], 'newt_component_add_callback' => ['void', 'component'=>'resource', 'func_name'=>'mixed', 'data'=>'mixed'], 'newt_component_takes_focus' => ['void', 'component'=>'resource', 'takes_focus'=>'bool'], 'newt_create_grid' => ['resource', 'cols'=>'int', 'rows'=>'int'], 'newt_cursor_off' => ['void'], 'newt_cursor_on' => ['void'], 'newt_delay' => ['void', 'microseconds'=>'int'], 'newt_draw_form' => ['void', 'form'=>'resource'], 'newt_draw_root_text' => ['void', 'left'=>'int', 'top'=>'int', 'text'=>'string'], 'newt_entry' => ['resource', 'left'=>'int', 'top'=>'int', 'width'=>'int', 'init_value='=>'string', 'flags='=>'int'], 'newt_entry_get_value' => ['string', 'entry'=>'resource'], 'newt_entry_set' => ['void', 'entry'=>'resource', 'value'=>'string', 'cursor_at_end='=>'bool'], 'newt_entry_set_filter' => ['void', 'entry'=>'resource', 'filter'=>'callable', 'data'=>'mixed'], 'newt_entry_set_flags' => ['void', 'entry'=>'resource', 'flags'=>'int', 'sense'=>'int'], 'newt_finished' => ['int'], 'newt_form' => ['resource', 'vert_bar='=>'resource', 'help='=>'string', 'flags='=>'int'], 'newt_form_add_component' => ['void', 'form'=>'resource', 'component'=>'resource'], 'newt_form_add_components' => ['void', 'form'=>'resource', 'components'=>'array'], 'newt_form_add_hot_key' => ['void', 'form'=>'resource', 'key'=>'int'], 'newt_form_destroy' => ['void', 'form'=>'resource'], 'newt_form_get_current' => ['resource', 'form'=>'resource'], 'newt_form_run' => ['void', 'form'=>'resource', 'exit_struct'=>'array'], 'newt_form_set_background' => ['void', 'from'=>'resource', 'background'=>'int'], 'newt_form_set_height' => ['void', 'form'=>'resource', 'height'=>'int'], 'newt_form_set_size' => ['void', 'form'=>'resource'], 'newt_form_set_timer' => ['void', 'form'=>'resource', 'milliseconds'=>'int'], 'newt_form_set_width' => ['void', 'form'=>'resource', 'width'=>'int'], 'newt_form_watch_fd' => ['void', 'form'=>'resource', 'stream'=>'resource', 'flags='=>'int'], 'newt_get_screen_size' => ['void', 'cols'=>'int', 'rows'=>'int'], 'newt_grid_add_components_to_form' => ['void', 'grid'=>'resource', 'form'=>'resource', 'recurse'=>'bool'], 'newt_grid_basic_window' => ['resource', 'text'=>'resource', 'middle'=>'resource', 'buttons'=>'resource'], 'newt_grid_free' => ['void', 'grid'=>'resource', 'recurse'=>'bool'], 'newt_grid_get_size' => ['void', 'grid'=>'resource', 'width'=>'int', 'height'=>'int'], 'newt_grid_h_close_stacked' => ['resource', 'element1_type'=>'int', 'element1'=>'resource', '...args='=>'resource'], 'newt_grid_h_stacked' => ['resource', 'element1_type'=>'int', 'element1'=>'resource', '...args='=>'resource'], 'newt_grid_place' => ['void', 'grid'=>'resource', 'left'=>'int', 'top'=>'int'], 'newt_grid_set_field' => ['void', 'grid'=>'resource', 'col'=>'int', 'row'=>'int', 'type'=>'int', 'val'=>'resource', 'pad_left'=>'int', 'pad_top'=>'int', 'pad_right'=>'int', 'pad_bottom'=>'int', 'anchor'=>'int', 'flags='=>'int'], 'newt_grid_simple_window' => ['resource', 'text'=>'resource', 'middle'=>'resource', 'buttons'=>'resource'], 'newt_grid_v_close_stacked' => ['resource', 'element1_type'=>'int', 'element1'=>'resource', '...args='=>'resource'], 'newt_grid_v_stacked' => ['resource', 'element1_type'=>'int', 'element1'=>'resource', '...args='=>'resource'], 'newt_grid_wrapped_window' => ['void', 'grid'=>'resource', 'title'=>'string'], 'newt_grid_wrapped_window_at' => ['void', 'grid'=>'resource', 'title'=>'string', 'left'=>'int', 'top'=>'int'], 'newt_init' => ['int'], 'newt_label' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string'], 'newt_label_set_text' => ['void', 'label'=>'resource', 'text'=>'string'], 'newt_listbox' => ['resource', 'left'=>'int', 'top'=>'int', 'height'=>'int', 'flags='=>'int'], 'newt_listbox_append_entry' => ['void', 'listbox'=>'resource', 'text'=>'string', 'data'=>'mixed'], 'newt_listbox_clear' => ['void', 'listobx'=>'resource'], 'newt_listbox_clear_selection' => ['void', 'listbox'=>'resource'], 'newt_listbox_delete_entry' => ['void', 'listbox'=>'resource', 'key'=>'mixed'], 'newt_listbox_get_current' => ['string', 'listbox'=>'resource'], 'newt_listbox_get_selection' => ['array', 'listbox'=>'resource'], 'newt_listbox_insert_entry' => ['void', 'listbox'=>'resource', 'text'=>'string', 'data'=>'mixed', 'key'=>'mixed'], 'newt_listbox_item_count' => ['int', 'listbox'=>'resource'], 'newt_listbox_select_item' => ['void', 'listbox'=>'resource', 'key'=>'mixed', 'sense'=>'int'], 'newt_listbox_set_current' => ['void', 'listbox'=>'resource', 'num'=>'int'], 'newt_listbox_set_current_by_key' => ['void', 'listbox'=>'resource', 'key'=>'mixed'], 'newt_listbox_set_data' => ['void', 'listbox'=>'resource', 'num'=>'int', 'data'=>'mixed'], 'newt_listbox_set_entry' => ['void', 'listbox'=>'resource', 'num'=>'int', 'text'=>'string'], 'newt_listbox_set_width' => ['void', 'listbox'=>'resource', 'width'=>'int'], 'newt_listitem' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string', 'is_default'=>'bool', 'prev_item'=>'resource', 'data'=>'mixed', 'flags='=>'int'], 'newt_listitem_get_data' => ['mixed', 'item'=>'resource'], 'newt_listitem_set' => ['void', 'item'=>'resource', 'text'=>'string'], 'newt_open_window' => ['int', 'left'=>'int', 'top'=>'int', 'width'=>'int', 'height'=>'int', 'title='=>'string'], 'newt_pop_help_line' => ['void'], 'newt_pop_window' => ['void'], 'newt_push_help_line' => ['void', 'text='=>'string'], 'newt_radio_get_current' => ['resource', 'set_member'=>'resource'], 'newt_radiobutton' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'string', 'is_default'=>'bool', 'prev_button='=>'resource'], 'newt_redraw_help_line' => ['void'], 'newt_reflow_text' => ['string', 'text'=>'string', 'width'=>'int', 'flex_down'=>'int', 'flex_up'=>'int', 'actual_width'=>'int', 'actual_height'=>'int'], 'newt_refresh' => ['void'], 'newt_resize_screen' => ['void', 'redraw='=>'bool'], 'newt_resume' => ['void'], 'newt_run_form' => ['resource', 'form'=>'resource'], 'newt_scale' => ['resource', 'left'=>'int', 'top'=>'int', 'width'=>'int', 'full_value'=>'int'], 'newt_scale_set' => ['void', 'scale'=>'resource', 'amount'=>'int'], 'newt_scrollbar_set' => ['void', 'scrollbar'=>'resource', 'where'=>'int', 'total'=>'int'], 'newt_set_help_callback' => ['void', 'function'=>'mixed'], 'newt_set_suspend_callback' => ['void', 'function'=>'callable', 'data'=>'mixed'], 'newt_suspend' => ['void'], 'newt_textbox' => ['resource', 'left'=>'int', 'top'=>'int', 'width'=>'int', 'height'=>'int', 'flags='=>'int'], 'newt_textbox_get_num_lines' => ['int', 'textbox'=>'resource'], 'newt_textbox_reflowed' => ['resource', 'left'=>'int', 'top'=>'int', 'text'=>'char', 'width'=>'int', 'flex_down'=>'int', 'flex_up'=>'int', 'flags='=>'int'], 'newt_textbox_set_height' => ['void', 'textbox'=>'resource', 'height'=>'int'], 'newt_textbox_set_text' => ['void', 'textbox'=>'resource', 'text'=>'string'], 'newt_vertical_scrollbar' => ['resource', 'left'=>'int', 'top'=>'int', 'height'=>'int', 'normal_colorset='=>'int', 'thumb_colorset='=>'int'], 'newt_wait_for_key' => ['void'], 'newt_win_choice' => ['int', 'title'=>'string', 'button1_text'=>'string', 'button2_text'=>'string', 'format'=>'string', 'args='=>'mixed', '...args='=>'mixed'], 'newt_win_entries' => ['int', 'title'=>'string', 'text'=>'string', 'suggested_width'=>'int', 'flex_down'=>'int', 'flex_up'=>'int', 'data_width'=>'int', 'items'=>'array', 'button1'=>'string', '...args='=>'string'], 'newt_win_menu' => ['int', 'title'=>'string', 'text'=>'string', 'suggestedwidth'=>'int', 'flexdown'=>'int', 'flexup'=>'int', 'maxlistheight'=>'int', 'items'=>'array', 'listitem'=>'int', 'button1='=>'string', '...args='=>'string'], 'newt_win_message' => ['void', 'title'=>'string', 'button_text'=>'string', 'format'=>'string', 'args='=>'mixed', '...args='=>'mixed'], 'newt_win_messagev' => ['void', 'title'=>'string', 'button_text'=>'string', 'format'=>'string', 'args'=>'array'], 'newt_win_ternary' => ['int', 'title'=>'string', 'button1_text'=>'string', 'button2_text'=>'string', 'button3_text'=>'string', 'format'=>'string', 'args='=>'mixed', '...args='=>'mixed'], 'next' => ['mixed', '&rw_array_arg'=>'array|object'], 'ngettext' => ['string', 'msgid1'=>'string', 'msgid2'=>'string', 'n'=>'int'], 'nl2br' => ['string', 'str'=>'string', 'is_xhtml='=>'bool'], 'nl_langinfo' => ['string|false', 'item'=>'int'], 'NoRewindIterator::__construct' => ['void', 'iterator'=>'Iterator'], 'NoRewindIterator::current' => ['mixed'], 'NoRewindIterator::getInnerIterator' => ['Iterator'], 'NoRewindIterator::key' => ['mixed'], 'NoRewindIterator::next' => ['void'], 'NoRewindIterator::rewind' => ['void'], 'NoRewindIterator::valid' => ['bool'], 'Normalizer::getRawDecomposition' => ['string|null', 'input'=>'string'], 'Normalizer::isNormalized' => ['bool', 'input'=>'string', 'form='=>'int'], 'Normalizer::normalize' => ['string|false', 'input'=>'string', 'form='=>'int'], 'normalizer_get_raw_decomposition' => ['string|null', 'input'=>'string'], 'normalizer_is_normalized' => ['bool', 'input'=>'string', 'form='=>'int'], 'normalizer_normalize' => ['string|false', 'input'=>'string', 'form='=>'int'], 'notes_body' => ['array', 'server'=>'string', 'mailbox'=>'string', 'msg_number'=>'int'], 'notes_copy_db' => ['bool', 'from_database_name'=>'string', 'to_database_name'=>'string'], 'notes_create_db' => ['bool', 'database_name'=>'string'], 'notes_create_note' => ['bool', 'database_name'=>'string', 'form_name'=>'string'], 'notes_drop_db' => ['bool', 'database_name'=>'string'], 'notes_find_note' => ['int', 'database_name'=>'string', 'name'=>'string', 'type='=>'string'], 'notes_header_info' => ['object', 'server'=>'string', 'mailbox'=>'string', 'msg_number'=>'int'], 'notes_list_msgs' => ['bool', 'db'=>'string'], 'notes_mark_read' => ['bool', 'database_name'=>'string', 'user_name'=>'string', 'note_id'=>'string'], 'notes_mark_unread' => ['bool', 'database_name'=>'string', 'user_name'=>'string', 'note_id'=>'string'], 'notes_nav_create' => ['bool', 'database_name'=>'string', 'name'=>'string'], 'notes_search' => ['array', 'database_name'=>'string', 'keywords'=>'string'], 'notes_unread' => ['array', 'database_name'=>'string', 'user_name'=>'string'], 'notes_version' => ['float', 'database_name'=>'string'], 'nsapi_request_headers' => ['array'], 'nsapi_response_headers' => ['array'], 'nsapi_virtual' => ['bool', 'uri'=>'string'], 'nthmac' => ['string', 'clent'=>'string', 'data'=>'string'], 'number_format' => ['non-empty-string', 'number'=>'float', 'num_decimal_places='=>'int', 'dec_separator='=>'string|null', 'thousands_separator='=>'string|null'], 'NumberFormatter::__construct' => ['void', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'], 'NumberFormatter::create' => ['NumberFormatter', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'], 'NumberFormatter::format' => ['string|false', 'num'=>'', 'type='=>'int'], 'NumberFormatter::formatCurrency' => ['string|false', 'num'=>'float', 'currency'=>'string'], 'NumberFormatter::getAttribute' => ['int', 'attr'=>'int'], 'NumberFormatter::getErrorCode' => ['int'], 'NumberFormatter::getErrorMessage' => ['string'], 'NumberFormatter::getLocale' => ['string', 'type='=>'int'], 'NumberFormatter::getPattern' => ['string'], 'NumberFormatter::getSymbol' => ['string', 'attr'=>'int'], 'NumberFormatter::getTextAttribute' => ['string', 'attr'=>'int'], 'NumberFormatter::parse' => ['float|false', 'str'=>'string', 'type='=>'int', '&rw_position='=>'int'], 'NumberFormatter::parseCurrency' => ['float|false', 'str'=>'string', '&w_currency'=>'string', '&rw_position='=>'int'], 'NumberFormatter::setAttribute' => ['bool', 'attr'=>'int', 'value'=>''], 'NumberFormatter::setPattern' => ['bool', 'pattern'=>'string'], 'NumberFormatter::setSymbol' => ['bool', 'attr'=>'int', 'symbol'=>'string'], 'NumberFormatter::setTextAttribute' => ['bool', 'attr'=>'int', 'value'=>'string'], 'numfmt_create' => ['NumberFormatter', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'], 'numfmt_format' => ['string|false', 'fmt'=>'numberformatter', 'value='=>'float', 'type='=>'int'], 'numfmt_format_currency' => ['string|false', 'fmt'=>'numberformatter', 'value'=>'float', 'currency'=>'string'], 'numfmt_get_attribute' => ['int|false', 'fmt'=>'numberformatter', 'attr'=>'int'], 'numfmt_get_error_code' => ['int', 'fmt'=>'numberformatter'], 'numfmt_get_error_message' => ['string', 'fmt'=>'numberformatter'], 'numfmt_get_locale' => ['string|false', 'fmt'=>'numberformatter', 'type='=>'int'], 'numfmt_get_pattern' => ['string|false', 'fmt'=>'numberformatter'], 'numfmt_get_symbol' => ['string|false', 'fmt'=>'numberformatter', 'attr'=>'int'], 'numfmt_get_text_attribute' => ['string|false', 'fmt'=>'numberformatter', 'attr'=>'int'], 'numfmt_parse' => ['float|false', 'fmt'=>'numberformatter', 'value'=>'string', 'type='=>'int', '&rw_position='=>'int'], 'numfmt_parse_currency' => ['float|false', 'fmt'=>'numberformatter', 'value'=>'string', '&w_currency'=>'string', '&rw_position='=>'int'], 'numfmt_set_attribute' => ['bool', 'fmt'=>'numberformatter', 'attr'=>'int', 'value'=>'int'], 'numfmt_set_pattern' => ['bool', 'fmt'=>'numberformatter', 'pattern'=>'string'], 'numfmt_set_symbol' => ['bool', 'fmt'=>'numberformatter', 'attr'=>'int', 'value'=>'string'], 'numfmt_set_text_attribute' => ['bool', 'fmt'=>'numberformatter', 'attr'=>'int', 'value'=>'string'], 'OAuth::__construct' => ['void', 'consumer_key'=>'string', 'consumer_secret'=>'string', 'signature_method='=>'string', 'auth_type='=>'int'], 'OAuth::__destruct' => [''], 'OAuth::disableDebug' => ['bool'], 'OAuth::disableRedirects' => ['bool'], 'OAuth::disableSSLChecks' => ['bool'], 'OAuth::enableDebug' => ['bool'], 'OAuth::enableRedirects' => ['bool'], 'OAuth::enableSSLChecks' => ['bool'], 'OAuth::fetch' => ['mixed', 'protected_resource_url'=>'string', 'extra_parameters='=>'array', 'http_method='=>'string', 'http_headers='=>'array'], 'OAuth::generateSignature' => ['string', 'http_method'=>'string', 'url'=>'string', 'extra_parameters='=>'mixed'], 'OAuth::getAccessToken' => ['array|false', 'access_token_url'=>'string', 'auth_session_handle='=>'string', 'verifier_token='=>'string'], 'OAuth::getCAPath' => ['array'], 'OAuth::getLastResponse' => ['string'], 'OAuth::getLastResponseHeaders' => ['string|false'], 'OAuth::getLastResponseInfo' => ['array'], 'OAuth::getRequestHeader' => ['string|false', 'http_method'=>'string', 'url'=>'string', 'extra_parameters='=>'mixed'], 'OAuth::getRequestToken' => ['array|false', 'request_token_url'=>'string', 'callback_url='=>'string'], 'OAuth::setAuthType' => ['bool', 'auth_type'=>'int'], 'OAuth::setCAPath' => ['mixed', 'ca_path='=>'string', 'ca_info='=>'string'], 'OAuth::setNonce' => ['mixed', 'nonce'=>'string'], 'OAuth::setRequestEngine' => ['void', 'reqengine'=>'int'], 'OAuth::setRSACertificate' => ['mixed', 'cert'=>'string'], 'OAuth::setSSLChecks' => ['bool', 'sslcheck'=>'int'], 'OAuth::setTimestamp' => ['mixed', 'timestamp'=>'string'], 'OAuth::setToken' => ['bool', 'token'=>'string', 'token_secret'=>'string'], 'OAuth::setVersion' => ['bool', 'version'=>'string'], 'oauth_get_sbs' => ['string', 'http_method'=>'string', 'uri'=>'string', 'request_parameters='=>'array'], 'oauth_urlencode' => ['string', 'uri'=>'string'], 'OAuthProvider::__construct' => ['void', 'params_array='=>'array'], 'OAuthProvider::addRequiredParameter' => ['bool', 'req_params'=>'string'], 'OAuthProvider::callconsumerHandler' => ['void'], 'OAuthProvider::callTimestampNonceHandler' => ['void'], 'OAuthProvider::calltokenHandler' => ['void'], 'OAuthProvider::checkOAuthRequest' => ['void', 'uri='=>'string', 'method='=>'string'], 'OAuthProvider::consumerHandler' => ['void', 'callback_function'=>'callable'], 'OAuthProvider::generateToken' => ['string', 'size'=>'int', 'strong='=>'bool'], 'OAuthProvider::is2LeggedEndpoint' => ['void', 'params_array'=>'mixed'], 'OAuthProvider::isRequestTokenEndpoint' => ['void', 'will_issue_request_token'=>'bool'], 'OAuthProvider::removeRequiredParameter' => ['bool', 'req_params'=>'string'], 'OAuthProvider::reportProblem' => ['string', 'oauthexception'=>'string', 'send_headers='=>'bool'], 'OAuthProvider::setParam' => ['bool', 'param_key'=>'string', 'param_val='=>'mixed'], 'OAuthProvider::setRequestTokenPath' => ['bool', 'path'=>'string'], 'OAuthProvider::timestampNonceHandler' => ['void', 'callback_function'=>'callable'], 'OAuthProvider::tokenHandler' => ['void', 'callback_function'=>'callable'], 'ob_clean' => ['bool'], 'ob_deflatehandler' => ['string', 'data'=>'string', 'mode'=>'int'], 'ob_end_clean' => ['bool'], 'ob_end_flush' => ['bool'], 'ob_etaghandler' => ['string', 'data'=>'string', 'mode'=>'int'], 'ob_flush' => ['bool'], 'ob_get_clean' => ['string|false'], 'ob_get_contents' => ['string|false'], 'ob_get_flush' => ['string|false'], 'ob_get_length' => ['int|false'], 'ob_get_level' => ['int'], 'ob_get_status' => ['array', 'full_status='=>'bool'], 'ob_gzhandler' => ['string|false', 'data'=>'string', 'flags'=>'int'], 'ob_iconv_handler' => ['string', 'contents'=>'string', 'status'=>'int'], 'ob_implicit_flush' => ['void', 'flag='=>'int'], 'ob_inflatehandler' => ['string', 'data'=>'string', 'mode'=>'int'], 'ob_list_handlers' => ['false|list'], 'ob_start' => ['bool', 'user_function='=>'string|array|callable|null', 'chunk_size='=>'int', 'flags='=>'int'], 'ob_tidyhandler' => ['string', 'input'=>'string', 'mode='=>'int'], 'OCI-Collection::append' => ['bool', 'value'=>'mixed'], 'OCI-Collection::assign' => ['bool', 'from'=>'OCI-Collection'], 'OCI-Collection::assignElem' => ['bool', 'index'=>'int', 'value'=>''], 'OCI-Collection::assignelem' => ['bool', 'index'=>'int', 'value'=>'mixed'], 'OCI-Collection::free' => ['bool'], 'OCI-Collection::getElem' => ['', 'index'=>'int'], 'OCI-Collection::getelem' => ['mixed', 'index'=>'int'], 'OCI-Collection::max' => ['int'], 'OCI-Collection::size' => ['int'], 'OCI-Collection::trim' => ['bool', 'num'=>'int'], 'OCI-Lob::append' => ['bool', 'lob_from'=>'OCI-Lob'], 'OCI-Lob::close' => ['bool'], 'OCI-Lob::eof' => ['bool'], 'OCI-Lob::erase' => ['int', 'offset='=>'int', 'length='=>'int'], 'OCI-Lob::export' => ['bool', 'filename'=>'string', 'start='=>'int', 'length='=>'int'], 'OCI-Lob::flush' => ['bool', 'flag='=>'int'], 'OCI-Lob::free' => ['bool'], 'OCI-Lob::getBuffering' => ['bool'], 'OCI-Lob::getbuffering' => ['bool'], 'OCI-Lob::import' => ['bool', 'filename'=>'string'], 'OCI-Lob::load' => ['string'], 'OCI-Lob::read' => ['string', 'length'=>'int'], 'OCI-Lob::rewind' => ['bool'], 'OCI-Lob::save' => ['bool', 'data'=>'string', 'offset='=>'int'], 'OCI-Lob::savefile' => ['bool', 'filename'=>''], 'OCI-Lob::seek' => ['bool', 'offset'=>'int', 'whence='=>'int'], 'OCI-Lob::setBuffering' => ['bool', 'on_off'=>'bool'], 'OCI-Lob::setbuffering' => ['bool', 'on_off'=>'bool'], 'OCI-Lob::size' => ['int'], 'OCI-Lob::tell' => ['int'], 'OCI-Lob::truncate' => ['bool', 'length='=>'int'], 'OCI-Lob::write' => ['int', 'data'=>'string', 'length='=>'int'], 'OCI-Lob::writeTemporary' => ['bool', 'data'=>'string', 'lob_type='=>'int'], 'OCI-Lob::writetofile' => ['bool', 'filename'=>'', 'start'=>'', 'length'=>''], 'oci_bind_array_by_name' => ['bool', 'stmt'=>'resource', 'name'=>'string', '&rw_var'=>'array', 'max_table_length'=>'int', 'max_item_length='=>'int', 'type='=>'int'], 'oci_bind_by_name' => ['bool', 'stmt'=>'resource', 'name'=>'string', '&rw_var'=>'mixed', 'maxlength='=>'int', 'type='=>'int'], 'oci_cancel' => ['bool', 'stmt'=>'resource'], 'oci_client_version' => ['string'], 'oci_close' => ['bool', 'connection'=>'resource'], 'oci_collection_append' => ['bool', 'value'=>'string'], 'oci_collection_assign' => ['bool', 'from'=>'OCI-Collection'], 'oci_collection_element_assign' => ['bool', 'index'=>'int', 'val'=>'string'], 'oci_collection_element_get' => ['string|false', 'ndx'=>'int'], 'oci_collection_max' => ['int|false'], 'oci_collection_size' => ['int|false'], 'oci_collection_trim' => ['bool', 'num'=>'int'], 'oci_commit' => ['bool', 'connection'=>'resource'], 'oci_connect' => ['resource|false', 'user'=>'string', 'pass'=>'string', 'db='=>'string', 'charset='=>'string', 'session_mode='=>'int'], 'oci_define_by_name' => ['bool', 'stmt'=>'resource', 'name'=>'string', '&w_var'=>'mixed', 'type='=>'int'], 'oci_error' => ['array|false', 'resource='=>'resource'], 'oci_execute' => ['bool', 'stmt'=>'resource', 'mode='=>'int'], 'oci_fetch' => ['bool', 'stmt'=>'resource'], 'oci_fetch_all' => ['int|false', 'stmt'=>'resource', '&w_output'=>'array', 'skip='=>'int', 'maxrows='=>'int', 'flags='=>'int'], 'oci_fetch_array' => ['array|false', 'stmt'=>'resource', 'mode='=>'int'], 'oci_fetch_assoc' => ['array|false', 'stmt'=>'resource'], 'oci_fetch_object' => ['object|false', 'stmt'=>'resource'], 'oci_fetch_row' => ['array|false', 'stmt'=>'resource'], 'oci_field_is_null' => ['bool', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_name' => ['string|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_precision' => ['int|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_scale' => ['int|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_size' => ['int|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_type' => ['mixed', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_field_type_raw' => ['int|false', 'stmt'=>'resource', 'col'=>'mixed'], 'oci_free_collection' => ['bool'], 'oci_free_cursor' => ['bool', 'stmt'=>'resource'], 'oci_free_descriptor' => ['bool'], 'oci_free_statement' => ['bool', 'stmt'=>'resource'], 'oci_get_implicit' => ['bool', 'stmt'=>''], 'oci_get_implicit_resultset' => ['resource|false', 'statement'=>'resource'], 'oci_internal_debug' => ['void', 'onoff'=>'bool'], 'oci_lob_append' => ['bool', 'lob'=>'OCI-Lob'], 'oci_lob_close' => ['bool'], 'oci_lob_copy' => ['bool', 'lob_to'=>'OCI-Lob', 'lob_from'=>'OCI-Lob', 'length='=>'int'], 'oci_lob_eof' => ['bool'], 'oci_lob_erase' => ['int|false', 'offset'=>'int', 'length'=>'int'], 'oci_lob_export' => ['bool', 'filename'=>'string', 'start'=>'int', 'length'=>'int'], 'oci_lob_flush' => ['bool', 'flag'=>'int'], 'oci_lob_import' => ['bool', 'filename'=>'string'], 'oci_lob_is_equal' => ['bool', 'lob1'=>'OCI-Lob', 'lob2'=>'OCI-Lob'], 'oci_lob_load' => ['string|false'], 'oci_lob_read' => ['string|false', 'length'=>'int'], 'oci_lob_rewind' => ['bool'], 'oci_lob_save' => ['bool', 'data'=>'string', 'offset'=>'int'], 'oci_lob_seek' => ['bool', 'offset'=>'int', 'whence'=>'int'], 'oci_lob_size' => ['int|false'], 'oci_lob_tell' => ['int|false'], 'oci_lob_truncate' => ['bool', 'length'=>'int'], 'oci_lob_write' => ['int|false', 'string'=>'string', 'length'=>'int'], 'oci_lob_write_temporary' => ['bool', 'var'=>'string', 'lob_type'=>'int'], 'oci_new_collection' => ['OCI-Collection|false', 'connection'=>'resource', 'tdo'=>'string', 'schema='=>'string'], 'oci_new_connect' => ['resource|false', 'user'=>'string', 'pass'=>'string', 'db='=>'string', 'charset='=>'string', 'session_mode='=>'int'], 'oci_new_cursor' => ['resource|false', 'connection'=>'resource'], 'oci_new_descriptor' => ['OCI-Lob|false', 'connection'=>'resource', 'type='=>'int'], 'oci_num_fields' => ['0|positive-int|false', 'stmt'=>'resource'], 'oci_num_rows' => ['0|positive-int|false', 'stmt'=>'resource'], 'oci_parse' => ['resource|false', 'connection'=>'resource', 'statement'=>'string'], 'oci_password_change' => ['bool', 'connection'=>'', 'username'=>'string', 'old_password'=>'string', 'new_password'=>'string'], 'oci_pconnect' => ['resource|false', 'user'=>'string', 'pass'=>'string', 'db='=>'string', 'charset='=>'string', 'session_mode='=>'int'], 'oci_register_taf_callback' => ['bool', 'connection'=>'resource', 'callback='=>'callable'], 'oci_result' => ['string|false', 'stmt'=>'resource', 'column'=>'mixed'], 'oci_rollback' => ['bool', 'connection'=>'resource'], 'oci_server_version' => ['string|false', 'connection'=>'resource'], 'oci_set_action' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_client_identifier' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_client_info' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_db_operation' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_edition' => ['bool', 'value'=>'string'], 'oci_set_module_name' => ['bool', 'connection'=>'resource', 'value'=>'string'], 'oci_set_prefetch' => ['bool', 'stmt'=>'resource', 'prefetch_rows'=>'int'], 'oci_statement_type' => ['string|false', 'stmt'=>'resource'], 'oci_unregister_taf_callback' => ['bool', 'connection'=>'resource'], 'ocifetchinto' => ['int|false', 'stmt'=>'', '&w_output'=>'array', 'mode='=>'int'], 'ocigetbufferinglob' => ['bool'], 'ocisetbufferinglob' => ['bool', 'flag'=>'bool'], 'octdec' => ['int|float', 'octal_number'=>'string'], 'odbc_autocommit' => ['mixed', 'connection_id'=>'resource', 'onoff='=>'bool'], 'odbc_binmode' => ['bool', 'result_id'=>'int', 'mode'=>'int'], 'odbc_close' => ['void', 'connection_id'=>'resource'], 'odbc_close_all' => ['void'], 'odbc_columnprivileges' => ['resource', 'connection_id'=>'resource', 'catalog'=>'string', 'schema'=>'string', 'table'=>'string', 'column'=>'string'], 'odbc_columns' => ['resource', 'connection_id'=>'resource', 'qualifier='=>'string', 'owner='=>'string', 'table_name='=>'string', 'column_name='=>'string'], 'odbc_commit' => ['bool', 'connection_id'=>'resource'], 'odbc_connect' => ['resource|false', 'dsn'=>'string', 'user'=>'string', 'password'=>'string', 'cursor_option='=>'int'], 'odbc_cursor' => ['string|false', 'result_id'=>'resource'], 'odbc_data_source' => ['array|false', 'connection_id'=>'resource', 'fetch_type'=>'int'], 'odbc_do' => ['resource', 'connection_id'=>'resource', 'query'=>'string', 'flags='=>'int'], 'odbc_error' => ['string', 'connection_id='=>'resource'], 'odbc_errormsg' => ['string', 'connection_id='=>'resource'], 'odbc_exec' => ['resource|false', 'connection_id'=>'resource', 'query'=>'string', 'flags='=>'int'], 'odbc_execute' => ['bool', 'result_id'=>'resource', 'parameters_array='=>'array'], 'odbc_fetch_array' => ['array|false', 'result'=>'resource', 'rownumber='=>'int'], 'odbc_fetch_into' => ['int|false', 'result_id'=>'resource', '&w_result_array'=>'array', 'rownumber='=>'int'], 'odbc_fetch_object' => ['object|false', 'result'=>'int', 'rownumber='=>'int'], 'odbc_fetch_row' => ['bool', 'result_id'=>'resource', 'row_number='=>'int'], 'odbc_field_len' => ['int|false', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_field_name' => ['string|false', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_field_num' => ['int|false', 'result_id'=>'resource', 'field_name'=>'string'], 'odbc_field_precision' => ['int|false', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_field_scale' => ['int|false', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_field_type' => ['string|false', 'result_id'=>'resource', 'field_number'=>'int'], 'odbc_foreignkeys' => ['resource', 'connection_id'=>'resource', 'pk_qualifier'=>'string', 'pk_owner'=>'string', 'pk_table'=>'string', 'fk_qualifier'=>'string', 'fk_owner'=>'string', 'fk_table'=>'string'], 'odbc_free_result' => ['bool', 'result_id'=>'resource'], 'odbc_gettypeinfo' => ['resource', 'connection_id'=>'resource', 'data_type='=>'int'], 'odbc_longreadlen' => ['bool', 'result_id'=>'resource', 'length'=>'int'], 'odbc_next_result' => ['bool', 'result_id'=>'resource'], 'odbc_num_fields' => ['int', 'result_id'=>'resource'], 'odbc_num_rows' => ['int', 'result_id'=>'resource'], 'odbc_pconnect' => ['resource', 'dsn'=>'string', 'user'=>'string', 'password'=>'string', 'cursor_option='=>'int'], 'odbc_prepare' => ['resource|false', 'connection_id'=>'resource', 'query'=>'string'], 'odbc_primarykeys' => ['resource', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'table'=>'string'], 'odbc_procedurecolumns' => ['resource', 'connection_id'=>'', 'qualifier'=>'string', 'owner'=>'string', 'proc'=>'string', 'column'=>'string'], 'odbc_procedures' => ['resource', 'connection_id'=>'', 'qualifier'=>'string', 'owner'=>'string', 'name'=>'string'], 'odbc_result' => ['mixed', 'result_id'=>'resource', 'field'=>'mixed'], 'odbc_result_all' => ['int|false', 'result_id'=>'resource', 'format='=>'string'], 'odbc_rollback' => ['bool', 'connection_id'=>'resource'], 'odbc_setoption' => ['bool', 'result_id'=>'resource', 'which'=>'int', 'option'=>'int', 'value'=>'int'], 'odbc_specialcolumns' => ['resource', 'connection_id'=>'resource', 'type'=>'int', 'qualifier'=>'string', 'owner'=>'string', 'table'=>'string', 'scope'=>'int', 'nullable'=>'int'], 'odbc_statistics' => ['resource', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'name'=>'string', 'unique'=>'int', 'accuracy'=>'int'], 'odbc_tableprivileges' => ['resource', 'connection_id'=>'resource', 'qualifier'=>'string', 'owner'=>'string', 'name'=>'string'], 'odbc_tables' => ['resource', 'connection_id'=>'resource', 'qualifier='=>'string', 'owner='=>'string', 'name='=>'string', 'table_types='=>'string'], 'opcache_compile_file' => ['bool', 'file'=>'string'], 'opcache_get_configuration' => ['array|false'], 'opcache_get_status' => ['array|false', 'get_scripts='=>'bool'], 'opcache_invalidate' => ['bool', 'script'=>'string', 'force='=>'bool'], 'opcache_is_script_cached' => ['bool', 'script'=>'string'], 'opcache_reset' => ['bool'], 'openal_buffer_create' => ['resource'], 'openal_buffer_data' => ['bool', 'buffer'=>'resource', 'format'=>'int', 'data'=>'string', 'freq'=>'int'], 'openal_buffer_destroy' => ['bool', 'buffer'=>'resource'], 'openal_buffer_get' => ['int', 'buffer'=>'resource', 'property'=>'int'], 'openal_buffer_loadwav' => ['bool', 'buffer'=>'resource', 'wavfile'=>'string'], 'openal_context_create' => ['resource', 'device'=>'resource'], 'openal_context_current' => ['bool', 'context'=>'resource'], 'openal_context_destroy' => ['bool', 'context'=>'resource'], 'openal_context_process' => ['bool', 'context'=>'resource'], 'openal_context_suspend' => ['bool', 'context'=>'resource'], 'openal_device_close' => ['bool', 'device'=>'resource'], 'openal_device_open' => ['resource|false', 'device_desc='=>'string'], 'openal_listener_get' => ['mixed', 'property'=>'int'], 'openal_listener_set' => ['bool', 'property'=>'int', 'setting'=>'mixed'], 'openal_source_create' => ['resource'], 'openal_source_destroy' => ['bool', 'source'=>'resource'], 'openal_source_get' => ['mixed', 'source'=>'resource', 'property'=>'int'], 'openal_source_pause' => ['bool', 'source'=>'resource'], 'openal_source_play' => ['bool', 'source'=>'resource'], 'openal_source_rewind' => ['bool', 'source'=>'resource'], 'openal_source_set' => ['bool', 'source'=>'resource', 'property'=>'int', 'setting'=>'mixed'], 'openal_source_stop' => ['bool', 'source'=>'resource'], 'openal_stream' => ['resource', 'source'=>'resource', 'format'=>'int', 'rate'=>'int'], 'opendir' => ['resource|false', 'path'=>'string', 'context='=>'resource'], 'openlog' => ['bool', 'ident'=>'string', 'option'=>'int', 'facility'=>'int'], 'openssl_cipher_iv_length' => ['int|false', 'method'=>'string'], 'openssl_csr_export' => ['bool', 'csr'=>'string|resource', '&w_out'=>'string', 'notext='=>'bool'], 'openssl_csr_export_to_file' => ['bool', 'csr'=>'string|resource', 'outfilename'=>'string', 'notext='=>'bool'], 'openssl_csr_get_public_key' => ['resource|false', 'csr'=>'string|resource', 'use_shortnames='=>'bool'], 'openssl_csr_get_subject' => ['array|false', 'csr'=>'string|resource', 'use_shortnames='=>'bool'], 'openssl_csr_new' => ['resource|false', 'dn'=>'array', '&w_privkey'=>'resource', 'configargs='=>'array', 'extraattribs='=>'array'], 'openssl_csr_sign' => ['resource|false', 'csr'=>'string|resource', 'x509'=>'string|resource|null', 'priv_key'=>'string|resource|array', 'days'=>'int', 'config_args='=>'array', 'serial='=>'int'], 'openssl_decrypt' => ['string|false', 'data'=>'string', 'method'=>'string', 'key'=>'string', 'options='=>'int', 'iv='=>'string', 'tag='=>'string', 'aad='=>'string'], 'openssl_dh_compute_key' => ['string|false', 'pub_key'=>'string', 'dh_key'=>'resource'], 'openssl_digest' => ['string|false', 'data'=>'string', 'method'=>'string', 'raw_output='=>'bool'], 'openssl_encrypt' => ['string|false', 'data'=>'string', 'method'=>'string', 'key'=>'string', 'options='=>'int', 'iv='=>'string', '&w_tag='=>'string', 'aad='=>'string', 'tag_length='=>'int'], 'openssl_error_string' => ['string|false'], 'openssl_free_key' => ['void', 'key_identifier'=>'resource'], 'openssl_get_cert_locations' => ['array'], 'openssl_get_cipher_methods' => ['list', 'aliases='=>'bool'], 'openssl_get_curve_names' => ['list|false'], 'openssl_get_md_methods' => ['list', 'aliases='=>'bool'], 'openssl_get_privatekey' => ['resource|false', 'key'=>'string', 'passphrase='=>'string'], 'openssl_get_publickey' => ['resource|false', 'cert'=>'resource|string'], 'openssl_open' => ['bool', 'sealed_data'=>'string', '&w_open_data'=>'string', 'env_key'=>'string', 'priv_key_id'=>'string|array|resource', 'method='=>'string', 'iv='=>'string'], 'openssl_pbkdf2' => ['string|false', 'password'=>'string', 'salt'=>'string', 'key_length'=>'int', 'iterations'=>'int', 'digest_algorithm'=>'string'], 'openssl_pkcs12_export' => ['bool', 'x509'=>'string|resource', '&w_out'=>'string', 'priv_key'=>'string|array|resource', 'pass'=>'string', 'args='=>'array'], 'openssl_pkcs12_export_to_file' => ['bool', 'x509'=>'string|resource', 'filename'=>'string', 'priv_key'=>'string|array|resource', 'pass'=>'string', 'args='=>'array'], 'openssl_pkcs12_read' => ['bool', 'pkcs12'=>'string', '&w_certs'=>'array', 'pass'=>'string'], 'openssl_pkcs7_decrypt' => ['bool', 'infilename'=>'string', 'outfilename'=>'string', 'recipcert'=>'string|resource', 'recipkey='=>'string|resource|array'], 'openssl_pkcs7_encrypt' => ['bool', 'infile'=>'string', 'outfile'=>'string', 'recipcerts'=>'string|resource|array', 'headers'=>'array', 'flags='=>'int', 'cipherid='=>'int'], 'openssl_pkcs7_read' => ['bool', 'infilename'=>'string', '&w_certs'=>'array'], 'openssl_pkcs7_sign' => ['bool', 'infile'=>'string', 'outfile'=>'string', 'signcert'=>'string|resource', 'privkey'=>'string|resource|array', 'headers'=>'array', 'flags='=>'int', 'extracerts='=>'string'], 'openssl_pkcs7_verify' => ['bool|int', 'filename'=>'string', 'flags'=>'int', 'outfilename='=>'string', 'cainfo='=>'array', 'extracerts='=>'string', 'content='=>'string', 'p7bfilename='=>'string'], 'openssl_pkey_derive' => ['string|false', 'pub_key'=>'resource', 'priv_key'=>'resource', 'keylen='=>'int'], 'openssl_pkey_export' => ['bool', 'key'=>'resource', '&w_out'=>'string', 'passphrase='=>'string|null', 'configargs='=>'array'], 'openssl_pkey_export_to_file' => ['bool', 'key'=>'resource|string|array', 'outfilename'=>'string', 'passphrase='=>'string|null', 'configargs='=>'array'], 'openssl_pkey_free' => ['void', 'key'=>'resource'], 'openssl_pkey_get_details' => ['array|false', 'key'=>'resource'], 'openssl_pkey_get_private' => ['resource|false', 'key'=>'string', 'passphrase='=>'string'], 'openssl_pkey_get_public' => ['resource|false', 'certificate'=>'resource|string'], 'openssl_pkey_new' => ['resource|false', 'configargs='=>'array'], 'openssl_private_decrypt' => ['bool', 'data'=>'string', '&w_decrypted'=>'string', 'key'=>'string|resource|array', 'padding='=>'int'], 'openssl_private_encrypt' => ['bool', 'data'=>'string', '&w_crypted'=>'string', 'key'=>'string|resource|array', 'padding='=>'int'], 'openssl_public_decrypt' => ['bool', 'data'=>'string', '&w_decrypted'=>'string', 'key'=>'string|resource', 'padding='=>'int'], 'openssl_public_encrypt' => ['bool', 'data'=>'string', '&w_crypted'=>'string', 'key'=>'string|resource', 'padding='=>'int'], 'openssl_random_pseudo_bytes' => ['string|false', 'length'=>'int', '&w_crypto_strong='=>'bool'], 'openssl_seal' => ['int|false', 'data'=>'string', '&w_sealed_data'=>'string', '&w_env_keys'=>'array', 'pub_key_ids'=>'array', 'method='=>'string', '&w_iv='=>'string'], 'openssl_sign' => ['bool', 'data'=>'string', '&w_signature'=>'string', 'priv_key_id'=>'resource|string', 'signature_alg='=>'int|string'], 'openssl_spki_export' => ['string|null|false', 'spkac'=>'string'], 'openssl_spki_export_challenge' => ['string|null|false', 'spkac'=>'string'], 'openssl_spki_new' => ['string|null|false', 'privkey'=>'resource', 'challenge'=>'string', 'algorithm='=>'int'], 'openssl_spki_verify' => ['bool', 'spkac'=>'string'], 'openssl_verify' => ['-1|0|1|false', 'data'=>'string', 'signature'=>'string', 'pub_key_id'=>'resource|string', 'signature_alg='=>'int|string'], 'openssl_x509_check_private_key' => ['bool', 'cert'=>'string|resource', 'key'=>'string|resource|array'], 'openssl_x509_checkpurpose' => ['bool|int', 'x509cert'=>'string|resource', 'purpose'=>'int', 'cainfo='=>'array', 'untrustedfile='=>'string'], 'openssl_x509_export' => ['bool', 'x509'=>'string|resource', '&w_output'=>'string', 'notext='=>'bool'], 'openssl_x509_export_to_file' => ['bool', 'x509'=>'string|resource', 'outfilename'=>'string', 'notext='=>'bool'], 'openssl_x509_fingerprint' => ['string|false', 'x509'=>'string|resource', 'hash_algorithm='=>'string', 'raw_output='=>'bool'], 'openssl_x509_free' => ['void', 'x509'=>'resource'], 'openssl_x509_parse' => ['array|false', 'x509cert'=>'string|resource', 'shortnames='=>'bool'], 'openssl_x509_read' => ['resource|false', 'x509certdata'=>'string|resource'], 'ord' => ['int<0, 255>', 'character'=>'string'], 'OuterIterator::getInnerIterator' => ['Iterator'], 'OutOfBoundsException::__clone' => ['void'], 'OutOfBoundsException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?OutOfBoundsException)'], 'OutOfBoundsException::__toString' => ['string'], 'OutOfBoundsException::getCode' => ['int'], 'OutOfBoundsException::getFile' => ['string'], 'OutOfBoundsException::getLine' => ['int'], 'OutOfBoundsException::getMessage' => ['string'], 'OutOfBoundsException::getPrevious' => ['Throwable|OutOfBoundsException|null'], 'OutOfBoundsException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'OutOfBoundsException::getTraceAsString' => ['string'], 'OutOfRangeException::__clone' => ['void'], 'OutOfRangeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?OutOfRangeException)'], 'OutOfRangeException::__toString' => ['string'], 'OutOfRangeException::getCode' => ['int'], 'OutOfRangeException::getFile' => ['string'], 'OutOfRangeException::getLine' => ['int'], 'OutOfRangeException::getMessage' => ['string'], 'OutOfRangeException::getPrevious' => ['Throwable|OutOfRangeException|null'], 'OutOfRangeException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'OutOfRangeException::getTraceAsString' => ['string'], 'output_add_rewrite_var' => ['bool', 'name'=>'string', 'value'=>'string'], 'output_reset_rewrite_vars' => ['bool'], 'OverflowException::__clone' => ['void'], 'OverflowException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?OverflowException)'], 'OverflowException::__toString' => ['string'], 'OverflowException::getCode' => ['int'], 'OverflowException::getFile' => ['string'], 'OverflowException::getLine' => ['int'], 'OverflowException::getMessage' => ['string'], 'OverflowException::getPrevious' => ['Throwable|OverflowException|null'], 'OverflowException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'OverflowException::getTraceAsString' => ['string'], 'overload' => ['', 'class_name'=>'string'], 'override_function' => ['bool', 'function_name'=>'string', 'function_args'=>'string', 'function_code'=>'string'], 'pack' => ['string', 'format'=>'string', '...args='=>'mixed'], 'ParentIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator'], 'ParentIterator::accept' => ['bool'], 'ParentIterator::getChildren' => ['ParentIterator'], 'ParentIterator::hasChildren' => ['bool'], 'ParentIterator::next' => ['void'], 'ParentIterator::rewind' => ['void'], 'ParentIterator::valid' => [''], 'Parle\Lexer::advance' => ['void'], 'Parle\Lexer::build' => ['void'], 'Parle\Lexer::callout' => ['void', 'id'=>'int', 'callback'=>'callable'], 'Parle\Lexer::consume' => ['void', 'data'=>'string'], 'Parle\Lexer::dump' => ['void'], 'Parle\Lexer::getToken' => ['Parle\Token'], 'Parle\Lexer::insertMacro' => ['void', 'name'=>'string', 'regex'=>'string'], 'Parle\Lexer::push' => ['void', 'regex'=>'string', 'id'=>'int'], 'Parle\Lexer::reset' => ['void', 'pos'=>'int'], 'Parle\Parser::advance' => ['void'], 'Parle\Parser::build' => ['void'], 'Parle\Parser::consume' => ['void', 'data'=>'string', 'lexer'=>'Parle\Lexer'], 'Parle\Parser::dump' => ['void'], 'Parle\Parser::errorInfo' => ['Parle\ErrorInfo'], 'Parle\Parser::left' => ['void', 'token'=>'string'], 'Parle\Parser::nonassoc' => ['void', 'token'=>'string'], 'Parle\Parser::precedence' => ['void', 'token'=>'string'], 'Parle\Parser::push' => ['int', 'name'=>'string', 'rule'=>'string'], 'Parle\Parser::reset' => ['void', 'tokenId'=>'int'], 'Parle\Parser::right' => ['void', 'token'=>'string'], 'Parle\Parser::sigil' => ['string', 'idx'=>'array'], 'Parle\Parser::token' => ['void', 'token'=>'string'], 'Parle\Parser::tokenId' => ['int', 'token'=>'string'], 'Parle\Parser::trace' => ['string'], 'Parle\Parser::validate' => ['bool', 'data'=>'string', 'lexer'=>'Parle\Lexer'], 'Parle\RLexer::advance' => ['void'], 'Parle\RLexer::build' => ['void'], 'Parle\RLexer::callout' => ['void', 'id'=>'int', 'callback'=>'callable'], 'Parle\RLexer::consume' => ['void', 'data'=>'string'], 'Parle\RLexer::dump' => ['void'], 'Parle\RLexer::getToken' => ['Parle\Token'], 'Parle\RLexer::push' => ['void', 'state'=>'string', 'regex'=>'string', 'newState'=>'string'], 'Parle\RLexer::pushState' => ['int', 'state'=>'string'], 'Parle\RLexer::reset' => ['void', 'pos'=>'int'], 'Parle\RParser::advance' => ['void'], 'Parle\RParser::build' => ['void'], 'Parle\RParser::consume' => ['void', 'data'=>'string', 'lexer'=>'Parle\Lexer'], 'Parle\RParser::dump' => ['void'], 'Parle\RParser::errorInfo' => ['Parle\ErrorInfo'], 'Parle\RParser::left' => ['void', 'token'=>'string'], 'Parle\RParser::nonassoc' => ['void', 'token'=>'string'], 'Parle\RParser::precedence' => ['void', 'token'=>'string'], 'Parle\RParser::push' => ['int', 'name'=>'string', 'rule'=>'string'], 'Parle\RParser::reset' => ['void', 'tokenId'=>'int'], 'Parle\RParser::right' => ['void', 'token'=>'string'], 'Parle\RParser::sigil' => ['string', 'idx'=>'array'], 'Parle\RParser::token' => ['void', 'token'=>'string'], 'Parle\RParser::tokenId' => ['int', 'token'=>'string'], 'Parle\RParser::trace' => ['string'], 'Parle\RParser::validate' => ['bool', 'data'=>'string', 'lexer'=>'Parle\Lexer'], 'Parle\Stack::pop' => ['void'], 'Parle\Stack::push' => ['void', 'item'=>''], 'parse_ini_file' => ['array|false', 'filename'=>'string', 'process_sections='=>'bool', 'scanner_mode='=>'int'], 'parse_ini_string' => ['array|false', 'ini_string'=>'string', 'process_sections='=>'bool', 'scanner_mode='=>'int'], 'parse_str' => ['void', 'encoded_string'=>'string', '&w_result='=>'array'], 'parse_url' => ['array|int|string|false|null', 'url'=>'string', 'url_component='=>'int'], 'ParseError::__clone' => ['void'], 'ParseError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?ParseError)'], 'ParseError::__toString' => ['string'], 'ParseError::getCode' => ['int'], 'ParseError::getFile' => ['string'], 'ParseError::getLine' => ['int'], 'ParseError::getMessage' => ['string'], 'ParseError::getPrevious' => ['Throwable|ParseError|null'], 'ParseError::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'ParseError::getTraceAsString' => ['string'], 'parsekit_compile_file' => ['array', 'filename'=>'string', 'errors='=>'array', 'options='=>'int'], 'parsekit_compile_string' => ['array', 'phpcode'=>'string', 'errors='=>'array', 'options='=>'int'], 'parsekit_func_arginfo' => ['array', 'function'=>'mixed'], 'passthru' => ['void', 'command'=>'string', '&w_return_value='=>'int'], 'password_get_info' => ['array', 'hash'=>'string'], 'password_hash' => ['__benevolent', 'password'=>'string', 'algo'=>'string|int', 'options='=>'array'], 'password_make_salt' => ['bool', 'password'=>'string', 'hash'=>'string'], 'password_needs_rehash' => ['bool', 'hash'=>'string', 'algo'=>'int', 'options='=>'array'], 'password_verify' => ['bool', 'password'=>'string', 'hash'=>'string'], 'pathinfo' => ['array|string', 'path'=>'string', 'options='=>'int'], 'pclose' => ['int', 'fp'=>'resource'], 'pcnlt_sigwaitinfo' => ['int', 'set'=>'array', '&w_siginfo'=>'array'], 'pcntl_alarm' => ['int', 'seconds'=>'int'], 'pcntl_async_signals' => ['bool', 'on='=>'bool'], 'pcntl_errno' => ['int'], 'pcntl_exec' => ['bool', 'path'=>'string', 'args='=>'array', 'envs='=>'array'], 'pcntl_fork' => ['int'], 'pcntl_get_last_error' => ['int'], 'pcntl_getpriority' => ['int|false', 'pid='=>'int', 'process_identifier='=>'int'], 'pcntl_setpriority' => ['bool', 'priority'=>'int', 'pid='=>'int', 'process_identifier='=>'int'], 'pcntl_signal' => ['bool', 'signo'=>'int', 'handle'=>'callable|int', 'restart_syscalls='=>'bool'], 'pcntl_signal_dispatch' => ['bool'], 'pcntl_signal_get_handler' => ['int|string', 'signo'=>'int'], 'pcntl_sigprocmask' => ['bool', 'how'=>'int', 'set'=>'array', '&w_oldset='=>'array'], 'pcntl_sigtimedwait' => ['int|false', 'set'=>'array', '&w_siginfo='=>'array', 'seconds='=>'int', 'nanoseconds='=>'int'], 'pcntl_sigwaitinfo' => ['int|false', 'set'=>'array', '&w_siginfo='=>'array'], 'pcntl_strerror' => ['string', 'errno'=>'int'], 'pcntl_wait' => ['int', '&w_status'=>'int', 'options='=>'int', '&w_rusage='=>'array'], 'pcntl_waitpid' => ['int', 'pid'=>'int', '&w_status'=>'int', 'options='=>'int', '&w_rusage='=>'array'], 'pcntl_wexitstatus' => ['int|false', 'status'=>'int'], 'pcntl_wifcontinued' => ['bool', 'status'=>'int'], 'pcntl_wifexited' => ['bool', 'status'=>'int'], 'pcntl_wifsignaled' => ['bool', 'status'=>'int'], 'pcntl_wifstopped' => ['bool', 'status'=>'int'], 'pcntl_wstopsig' => ['int|false', 'status'=>'int'], 'pcntl_wtermsig' => ['int|false', 'status'=>'int'], 'PDF_activate_item' => ['bool', 'pdfdoc'=>'resource', 'id'=>'int'], 'PDF_add_launchlink' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string'], 'PDF_add_locallink' => ['bool', 'pdfdoc'=>'resource', 'lowerleftx'=>'float', 'lowerlefty'=>'float', 'upperrightx'=>'float', 'upperrighty'=>'float', 'page'=>'int', 'dest'=>'string'], 'PDF_add_nameddest' => ['bool', 'pdfdoc'=>'resource', 'name'=>'string', 'optlist'=>'string'], 'PDF_add_note' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'contents'=>'string', 'title'=>'string', 'icon'=>'string', 'open'=>'int'], 'PDF_add_pdflink' => ['bool', 'pdfdoc'=>'resource', 'bottom_left_x'=>'float', 'bottom_left_y'=>'float', 'up_right_x'=>'float', 'up_right_y'=>'float', 'filename'=>'string', 'page'=>'int', 'dest'=>'string'], 'PDF_add_table_cell' => ['int', 'pdfdoc'=>'resource', 'table'=>'int', 'column'=>'int', 'row'=>'int', 'text'=>'string', 'optlist'=>'string'], 'PDF_add_textflow' => ['int', 'pdfdoc'=>'resource', 'textflow'=>'int', 'text'=>'string', 'optlist'=>'string'], 'PDF_add_thumbnail' => ['bool', 'pdfdoc'=>'resource', 'image'=>'int'], 'PDF_add_weblink' => ['bool', 'pdfdoc'=>'resource', 'lowerleftx'=>'float', 'lowerlefty'=>'float', 'upperrightx'=>'float', 'upperrighty'=>'float', 'url'=>'string'], 'PDF_arc' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float', 'r'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'PDF_arcn' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float', 'r'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'PDF_attach_file' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string', 'description'=>'string', 'author'=>'string', 'mimetype'=>'string', 'icon'=>'string'], 'PDF_begin_document' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string', 'optlist'=>'string'], 'PDF_begin_font' => ['bool', 'pdfdoc'=>'resource', 'filename'=>'string', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'e'=>'float', 'f'=>'float', 'optlist'=>'string'], 'PDF_begin_glyph' => ['bool', 'pdfdoc'=>'resource', 'glyphname'=>'string', 'wx'=>'float', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float'], 'PDF_begin_item' => ['int', 'pdfdoc'=>'resource', 'tag'=>'string', 'optlist'=>'string'], 'PDF_begin_layer' => ['bool', 'pdfdoc'=>'resource', 'layer'=>'int'], 'PDF_begin_page' => ['bool', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float'], 'PDF_begin_page_ext' => ['bool', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float', 'optlist'=>'string'], 'PDF_begin_pattern' => ['int', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float', 'xstep'=>'float', 'ystep'=>'float', 'painttype'=>'int'], 'PDF_begin_template' => ['int', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float'], 'PDF_begin_template_ext' => ['int', 'pdfdoc'=>'resource', 'width'=>'float', 'height'=>'float', 'optlist'=>'string'], 'PDF_circle' => ['bool', 'pdfdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'r'=>'float'], 'PDF_clip' => ['bool', 'p'=>'resource'], 'PDF_close' => ['bool', 'p'=>'resource'], 'PDF_close_image' => ['bool', 'p'=>'resource', 'image'=>'int'], 'PDF_close_pdi' => ['bool', 'p'=>'resource', 'doc'=>'int'], 'PDF_close_pdi_page' => ['bool', 'p'=>'resource', 'page'=>'int'], 'PDF_closepath' => ['bool', 'p'=>'resource'], 'PDF_closepath_fill_stroke' => ['bool', 'p'=>'resource'], 'PDF_closepath_stroke' => ['bool', 'p'=>'resource'], 'PDF_concat' => ['bool', 'p'=>'resource', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'e'=>'float', 'f'=>'float'], 'PDF_continue_text' => ['bool', 'p'=>'resource', 'text'=>'string'], 'PDF_create_3dview' => ['int', 'pdfdoc'=>'resource', 'username'=>'string', 'optlist'=>'string'], 'PDF_create_action' => ['int', 'pdfdoc'=>'resource', 'type'=>'string', 'optlist'=>'string'], 'PDF_create_annotation' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'type'=>'string', 'optlist'=>'string'], 'PDF_create_bookmark' => ['int', 'pdfdoc'=>'resource', 'text'=>'string', 'optlist'=>'string'], 'PDF_create_field' => ['bool', 'pdfdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'name'=>'string', 'type'=>'string', 'optlist'=>'string'], 'PDF_create_fieldgroup' => ['bool', 'pdfdoc'=>'resource', 'name'=>'string', 'optlist'=>'string'], 'PDF_create_gstate' => ['int', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_create_pvf' => ['bool', 'pdfdoc'=>'resource', 'filename'=>'string', 'data'=>'string', 'optlist'=>'string'], 'PDF_create_textflow' => ['int', 'pdfdoc'=>'resource', 'text'=>'string', 'optlist'=>'string'], 'PDF_curveto' => ['bool', 'p'=>'resource', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'PDF_define_layer' => ['int', 'pdfdoc'=>'resource', 'name'=>'string', 'optlist'=>'string'], 'PDF_delete' => ['bool', 'pdfdoc'=>'resource'], 'PDF_delete_pvf' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string'], 'PDF_delete_table' => ['bool', 'pdfdoc'=>'resource', 'table'=>'int', 'optlist'=>'string'], 'PDF_delete_textflow' => ['bool', 'pdfdoc'=>'resource', 'textflow'=>'int'], 'PDF_encoding_set_char' => ['bool', 'pdfdoc'=>'resource', 'encoding'=>'string', 'slot'=>'int', 'glyphname'=>'string', 'uv'=>'int'], 'PDF_end_document' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_end_font' => ['bool', 'pdfdoc'=>'resource'], 'PDF_end_glyph' => ['bool', 'pdfdoc'=>'resource'], 'PDF_end_item' => ['bool', 'pdfdoc'=>'resource', 'id'=>'int'], 'PDF_end_layer' => ['bool', 'pdfdoc'=>'resource'], 'PDF_end_page' => ['bool', 'p'=>'resource'], 'PDF_end_page_ext' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_end_pattern' => ['bool', 'p'=>'resource'], 'PDF_end_template' => ['bool', 'p'=>'resource'], 'PDF_endpath' => ['bool', 'p'=>'resource'], 'PDF_fill' => ['bool', 'p'=>'resource'], 'PDF_fill_imageblock' => ['int', 'pdfdoc'=>'resource', 'page'=>'int', 'blockname'=>'string', 'image'=>'int', 'optlist'=>'string'], 'PDF_fill_pdfblock' => ['int', 'pdfdoc'=>'resource', 'page'=>'int', 'blockname'=>'string', 'contents'=>'int', 'optlist'=>'string'], 'PDF_fill_stroke' => ['bool', 'p'=>'resource'], 'PDF_fill_textblock' => ['int', 'pdfdoc'=>'resource', 'page'=>'int', 'blockname'=>'string', 'text'=>'string', 'optlist'=>'string'], 'PDF_findfont' => ['int', 'p'=>'resource', 'fontname'=>'string', 'encoding'=>'string', 'embed'=>'int'], 'PDF_fit_image' => ['bool', 'pdfdoc'=>'resource', 'image'=>'int', 'x'=>'float', 'y'=>'float', 'optlist'=>'string'], 'PDF_fit_pdi_page' => ['bool', 'pdfdoc'=>'resource', 'page'=>'int', 'x'=>'float', 'y'=>'float', 'optlist'=>'string'], 'PDF_fit_table' => ['string', 'pdfdoc'=>'resource', 'table'=>'int', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'optlist'=>'string'], 'PDF_fit_textflow' => ['string', 'pdfdoc'=>'resource', 'textflow'=>'int', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'optlist'=>'string'], 'PDF_fit_textline' => ['bool', 'pdfdoc'=>'resource', 'text'=>'string', 'x'=>'float', 'y'=>'float', 'optlist'=>'string'], 'PDF_get_apiname' => ['string', 'pdfdoc'=>'resource'], 'PDF_get_buffer' => ['string', 'p'=>'resource'], 'PDF_get_errmsg' => ['string', 'pdfdoc'=>'resource'], 'PDF_get_errnum' => ['int', 'pdfdoc'=>'resource'], 'PDF_get_majorversion' => ['int'], 'PDF_get_minorversion' => ['int'], 'PDF_get_parameter' => ['string', 'p'=>'resource', 'key'=>'string', 'modifier'=>'float'], 'PDF_get_pdi_parameter' => ['string', 'p'=>'resource', 'key'=>'string', 'doc'=>'int', 'page'=>'int', 'reserved'=>'int'], 'PDF_get_pdi_value' => ['float', 'p'=>'resource', 'key'=>'string', 'doc'=>'int', 'page'=>'int', 'reserved'=>'int'], 'PDF_get_value' => ['float', 'p'=>'resource', 'key'=>'string', 'modifier'=>'float'], 'PDF_info_font' => ['float', 'pdfdoc'=>'resource', 'font'=>'int', 'keyword'=>'string', 'optlist'=>'string'], 'PDF_info_matchbox' => ['float', 'pdfdoc'=>'resource', 'boxname'=>'string', 'num'=>'int', 'keyword'=>'string'], 'PDF_info_table' => ['float', 'pdfdoc'=>'resource', 'table'=>'int', 'keyword'=>'string'], 'PDF_info_textflow' => ['float', 'pdfdoc'=>'resource', 'textflow'=>'int', 'keyword'=>'string'], 'PDF_info_textline' => ['float', 'pdfdoc'=>'resource', 'text'=>'string', 'keyword'=>'string', 'optlist'=>'string'], 'PDF_initgraphics' => ['bool', 'p'=>'resource'], 'PDF_lineto' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float'], 'PDF_load_3ddata' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string', 'optlist'=>'string'], 'PDF_load_font' => ['int', 'pdfdoc'=>'resource', 'fontname'=>'string', 'encoding'=>'string', 'optlist'=>'string'], 'PDF_load_iccprofile' => ['int', 'pdfdoc'=>'resource', 'profilename'=>'string', 'optlist'=>'string'], 'PDF_load_image' => ['int', 'pdfdoc'=>'resource', 'imagetype'=>'string', 'filename'=>'string', 'optlist'=>'string'], 'PDF_makespotcolor' => ['int', 'p'=>'resource', 'spotname'=>'string'], 'PDF_moveto' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float'], 'PDF_new' => ['resource'], 'PDF_open_ccitt' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string', 'width'=>'int', 'height'=>'int', 'bitreverse'=>'int', 'k'=>'int', 'blackls1'=>'int'], 'PDF_open_file' => ['bool', 'p'=>'resource', 'filename'=>'string'], 'PDF_open_image' => ['int', 'p'=>'resource', 'imagetype'=>'string', 'source'=>'string', 'data'=>'string', 'length'=>'int', 'width'=>'int', 'height'=>'int', 'components'=>'int', 'bpc'=>'int', 'params'=>'string'], 'PDF_open_image_file' => ['int', 'p'=>'resource', 'imagetype'=>'string', 'filename'=>'string', 'stringparam'=>'string', 'intparam'=>'int'], 'PDF_open_memory_image' => ['int', 'p'=>'resource', 'image'=>'resource'], 'PDF_open_pdi' => ['int', 'pdfdoc'=>'resource', 'filename'=>'string', 'optlist'=>'string', 'len'=>'int'], 'PDF_open_pdi_document' => ['int', 'p'=>'resource', 'filename'=>'string', 'optlist'=>'string'], 'PDF_open_pdi_page' => ['int', 'p'=>'resource', 'doc'=>'int', 'pagenumber'=>'int', 'optlist'=>'string'], 'PDF_pcos_get_number' => ['float', 'p'=>'resource', 'doc'=>'int', 'path'=>'string'], 'PDF_pcos_get_stream' => ['string', 'p'=>'resource', 'doc'=>'int', 'optlist'=>'string', 'path'=>'string'], 'PDF_pcos_get_string' => ['string', 'p'=>'resource', 'doc'=>'int', 'path'=>'string'], 'PDF_place_image' => ['bool', 'pdfdoc'=>'resource', 'image'=>'int', 'x'=>'float', 'y'=>'float', 'scale'=>'float'], 'PDF_place_pdi_page' => ['bool', 'pdfdoc'=>'resource', 'page'=>'int', 'x'=>'float', 'y'=>'float', 'sx'=>'float', 'sy'=>'float'], 'PDF_process_pdi' => ['int', 'pdfdoc'=>'resource', 'doc'=>'int', 'page'=>'int', 'optlist'=>'string'], 'PDF_rect' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'PDF_restore' => ['bool', 'p'=>'resource'], 'PDF_resume_page' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_rotate' => ['bool', 'p'=>'resource', 'phi'=>'float'], 'PDF_save' => ['bool', 'p'=>'resource'], 'PDF_scale' => ['bool', 'p'=>'resource', 'sx'=>'float', 'sy'=>'float'], 'PDF_set_border_color' => ['bool', 'p'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDF_set_border_dash' => ['bool', 'pdfdoc'=>'resource', 'black'=>'float', 'white'=>'float'], 'PDF_set_border_style' => ['bool', 'pdfdoc'=>'resource', 'style'=>'string', 'width'=>'float'], 'PDF_set_gstate' => ['bool', 'pdfdoc'=>'resource', 'gstate'=>'int'], 'PDF_set_info' => ['bool', 'p'=>'resource', 'key'=>'string', 'value'=>'string'], 'PDF_set_layer_dependency' => ['bool', 'pdfdoc'=>'resource', 'type'=>'string', 'optlist'=>'string'], 'PDF_set_parameter' => ['bool', 'p'=>'resource', 'key'=>'string', 'value'=>'string'], 'PDF_set_text_pos' => ['bool', 'p'=>'resource', 'x'=>'float', 'y'=>'float'], 'PDF_set_value' => ['bool', 'p'=>'resource', 'key'=>'string', 'value'=>'float'], 'PDF_setcolor' => ['bool', 'p'=>'resource', 'fstype'=>'string', 'colorspace'=>'string', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float'], 'PDF_setdash' => ['bool', 'pdfdoc'=>'resource', 'b'=>'float', 'w'=>'float'], 'PDF_setdashpattern' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_setflat' => ['bool', 'pdfdoc'=>'resource', 'flatness'=>'float'], 'PDF_setfont' => ['bool', 'pdfdoc'=>'resource', 'font'=>'int', 'fontsize'=>'float'], 'PDF_setgray' => ['bool', 'p'=>'resource', 'g'=>'float'], 'PDF_setgray_fill' => ['bool', 'p'=>'resource', 'g'=>'float'], 'PDF_setgray_stroke' => ['bool', 'p'=>'resource', 'g'=>'float'], 'PDF_setlinecap' => ['bool', 'p'=>'resource', 'linecap'=>'int'], 'PDF_setlinejoin' => ['bool', 'p'=>'resource', 'value'=>'int'], 'PDF_setlinewidth' => ['bool', 'p'=>'resource', 'width'=>'float'], 'PDF_setmatrix' => ['bool', 'p'=>'resource', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'e'=>'float', 'f'=>'float'], 'PDF_setmiterlimit' => ['bool', 'pdfdoc'=>'resource', 'miter'=>'float'], 'PDF_setrgbcolor' => ['bool', 'p'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDF_setrgbcolor_fill' => ['bool', 'p'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDF_setrgbcolor_stroke' => ['bool', 'p'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'PDF_shading' => ['int', 'pdfdoc'=>'resource', 'shtype'=>'string', 'x0'=>'float', 'y0'=>'float', 'x1'=>'float', 'y1'=>'float', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float', 'optlist'=>'string'], 'PDF_shading_pattern' => ['int', 'pdfdoc'=>'resource', 'shading'=>'int', 'optlist'=>'string'], 'PDF_shfill' => ['bool', 'pdfdoc'=>'resource', 'shading'=>'int'], 'PDF_show' => ['bool', 'pdfdoc'=>'resource', 'text'=>'string'], 'PDF_show_boxed' => ['int', 'p'=>'resource', 'text'=>'string', 'left'=>'float', 'top'=>'float', 'width'=>'float', 'height'=>'float', 'mode'=>'string', 'feature'=>'string'], 'PDF_show_xy' => ['bool', 'p'=>'resource', 'text'=>'string', 'x'=>'float', 'y'=>'float'], 'PDF_skew' => ['bool', 'p'=>'resource', 'alpha'=>'float', 'beta'=>'float'], 'PDF_stringwidth' => ['float', 'p'=>'resource', 'text'=>'string', 'font'=>'int', 'fontsize'=>'float'], 'PDF_stroke' => ['bool', 'p'=>'resource'], 'PDF_suspend_page' => ['bool', 'pdfdoc'=>'resource', 'optlist'=>'string'], 'PDF_translate' => ['bool', 'p'=>'resource', 'tx'=>'float', 'ty'=>'float'], 'PDF_utf16_to_utf8' => ['string', 'pdfdoc'=>'resource', 'utf16string'=>'string'], 'PDF_utf32_to_utf16' => ['string', 'pdfdoc'=>'resource', 'utf32string'=>'string', 'ordering'=>'string'], 'PDF_utf8_to_utf16' => ['string', 'pdfdoc'=>'resource', 'utf8string'=>'string', 'ordering'=>'string'], 'PDO::__construct' => ['void', 'dsn'=>'string', 'username='=>'?string', 'passwd='=>'?string', 'options='=>'?array'], 'PDO::__sleep' => ['list'], 'PDO::__wakeup' => ['void'], 'PDO::beginTransaction' => ['bool'], 'PDO::commit' => ['bool'], 'PDO::cubrid_schema' => ['array', 'schema_type'=>'int', 'table_name='=>'string', 'col_name='=>'string'], 'PDO::errorCode' => ['string|null'], 'PDO::errorInfo' => ['array'], 'PDO::exec' => ['int|false', 'query'=>'string'], 'PDO::getAttribute' => ['', 'attribute'=>'int'], 'PDO::getAvailableDrivers' => ['array'], 'PDO::inTransaction' => ['bool'], 'PDO::lastInsertId' => ['string|false', 'seqname='=>'string'], 'PDO::pgsqlCopyFromArray' => ['bool', 'table_name'=>'string', 'rows'=>'array', 'delimiter='=>'string', 'null_as='=>'string', 'fields='=>'string'], 'PDO::pgsqlCopyFromFile' => ['bool', 'table_name'=>'string', 'filename'=>'string', 'delimiter='=>'string', 'null_as='=>'string', 'fields='=>'string'], 'PDO::pgsqlCopyToArray' => ['array', 'table_name'=>'string', 'delimiter='=>'string', 'null_as='=>'string', 'fields='=>'string'], 'PDO::pgsqlCopyToFile' => ['bool', 'table_name'=>'string', 'filename'=>'string', 'delimiter='=>'string', 'null_as='=>'string', 'fields='=>'string'], 'PDO::pgsqlGetNotify' => ['array', 'result_type='=>'int', 'ms_timeout='=>'int'], 'PDO::pgsqlGetPid' => ['int'], 'PDO::pgsqlLOBCreate' => ['string'], 'PDO::pgsqlLOBOpen' => ['resource', 'oid'=>'string', 'mode='=>'string'], 'PDO::pgsqlLOBUnlink' => ['bool', 'oid'=>'string'], 'PDO::prepare' => ['__benevolent', 'statement'=>'string', 'options='=>'array'], 'PDO::query' => ['PDOStatement|false', 'sql'=>'string'], 'PDO::query\'1' => ['PDOStatement|false', 'sql'=>'string', 'fetch_column'=>'int', 'colno'=>'int'], 'PDO::query\'2' => ['PDOStatement|false', 'sql'=>'string', 'fetch_class'=>'int', 'classname'=>'string', 'ctorargs'=>'array'], 'PDO::query\'3' => ['PDOStatement|false', 'sql'=>'string', 'fetch_into'=>'int', 'object'=>'object'], 'PDO::quote' => ['string', 'string'=>'string', 'paramtype='=>'int'], 'PDO::rollBack' => ['bool'], 'PDO::setAttribute' => ['bool', 'attribute'=>'int', 'value'=>''], 'PDO::sqliteCreateAggregate' => ['bool', 'function_name'=>'string', 'step_func'=>'callable', 'finalize_func'=>'callable', 'num_args='=>'int'], 'PDO::sqliteCreateCollation' => ['bool', 'name'=>'string', 'callback'=>'callable'], 'PDO::sqliteCreateFunction' => ['bool', 'function_name'=>'string', 'callback'=>'callable', 'num_args='=>'int', 'flags='=>'int'], 'pdo_drivers' => ['array'], 'PDOException::getCode' => [''], 'PDOException::getFile' => [''], 'PDOException::getLine' => [''], 'PDOException::getMessage' => [''], 'PDOException::getPrevious' => [''], 'PDOException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'PDOException::getTraceAsString' => [''], 'PDOStatement::__sleep' => ['list'], 'PDOStatement::__wakeup' => ['void'], 'PDOStatement::bindColumn' => ['bool', 'column'=>'mixed', '&w_param'=>'mixed', 'type='=>'int', 'maxlen='=>'int', 'driverdata='=>'mixed'], 'PDOStatement::bindParam' => ['bool', 'parameter'=>'mixed', '&w_variable'=>'mixed', 'data_type='=>'int', 'length='=>'int', 'driver_options='=>'mixed'], 'PDOStatement::bindValue' => ['bool', 'parameter'=>'mixed', 'value'=>'mixed', 'data_type='=>'int'], 'PDOStatement::closeCursor' => ['bool'], 'PDOStatement::columnCount' => ['0|positive-int'], 'PDOStatement::debugDumpParams' => ['void'], 'PDOStatement::errorCode' => ['string|null'], 'PDOStatement::errorInfo' => ['array'], 'PDOStatement::execute' => ['bool', 'bound_input_params='=>'?array'], 'PDOStatement::fetch' => ['mixed', 'how='=>'int', 'orientation='=>'int', 'offset='=>'int'], 'PDOStatement::fetchAll' => ['array|false', 'how='=>'int', 'fetch_argument='=>'int|string|callable', 'ctor_args='=>'?array'], 'PDOStatement::fetchColumn' => ['string|null|false|int', 'column_number='=>'int'], 'PDOStatement::fetchObject' => ['mixed', 'class_name='=>'string', 'ctor_args='=>'?array'], 'PDOStatement::getAttribute' => ['mixed', 'attribute'=>'int'], 'PDOStatement::getColumnMeta' => ['array|false', 'column'=>'int'], 'PDOStatement::nextRowset' => ['bool'], 'PDOStatement::rowCount' => ['0|positive-int'], 'PDOStatement::setAttribute' => ['bool', 'attribute'=>'int', 'value'=>'mixed'], 'PDOStatement::setFetchMode' => ['bool', 'mode'=>'int'], 'PDOStatement::setFetchMode\'1' => ['bool', 'fetch_column'=>'int', 'colno'=>'int'], 'PDOStatement::setFetchMode\'2' => ['bool', 'fetch_class'=>'int', 'classname'=>'string', 'ctorargs='=>'?array'], 'PDOStatement::setFetchMode\'3' => ['bool', 'fetch_into'=>'int', 'object'=>'object'], 'pfsockopen' => ['resource|false', 'hostname'=>'string', 'port='=>'int', '&w_errno='=>'int', '&w_errstr='=>'string', 'timeout='=>'float'], 'pg_affected_rows' => ['int', 'result'=>'resource'], 'pg_cancel_query' => ['bool', 'connection'=>'resource'], 'pg_client_encoding' => ['string', 'connection='=>'resource'], 'pg_close' => ['bool', 'connection='=>'resource'], 'pg_connect' => ['resource|false', 'connection_string'=>'string', 'connect_type='=>'int'], 'pg_connect_poll' => ['int', 'connection'=>'resource'], 'pg_connection_busy' => ['bool', 'connection'=>'resource'], 'pg_connection_reset' => ['bool', 'connection'=>'resource'], 'pg_connection_status' => ['int', 'connection'=>'resource'], 'pg_consume_input' => ['bool', 'connection'=>'resource'], 'pg_convert' => ['array|false', 'db'=>'resource', 'table'=>'string', 'values'=>'array', 'options='=>'int'], 'pg_copy_from' => ['bool', 'connection'=>'resource', 'table_name'=>'string', 'rows'=>'array', 'delimiter='=>'string', 'null_as='=>'string'], 'pg_copy_to' => ['array|false', 'connection'=>'resource', 'table_name'=>'string', 'delimiter='=>'string', 'null_as='=>'string'], 'pg_dbname' => ['string', 'connection='=>'resource'], 'pg_delete' => ['mixed', 'db'=>'resource', 'table'=>'string', 'ids'=>'array', 'options='=>'int'], 'pg_end_copy' => ['bool', 'connection='=>'resource'], 'pg_escape_bytea' => ['string', 'connection'=>'resource', 'data'=>'string'], 'pg_escape_bytea\'1' => ['string', 'data'=>'string'], 'pg_escape_identifier' => ['string|false', 'connection'=>'resource', 'data'=>'string'], 'pg_escape_identifier\'1' => ['string', 'data'=>'string'], 'pg_escape_literal' => ['string|false', 'connection'=>'resource', 'data'=>'string'], 'pg_escape_literal\'1' => ['string', 'data'=>'string'], 'pg_escape_string' => ['string', 'connection'=>'resource', 'data'=>'string'], 'pg_escape_string\'1' => ['string', 'data'=>'string'], 'pg_execute' => ['resource|false', 'connection'=>'resource', 'stmtname'=>'string', 'params'=>'array'], 'pg_execute\'1' => ['resource|false', 'stmtname'=>'string', 'params'=>'array'], 'pg_fetch_all' => ['array>', 'result'=>'resource', 'result_type='=>'int'], 'pg_fetch_all_columns' => ['array|false', 'result'=>'resource', 'column_number='=>'int'], 'pg_fetch_array' => ['array|false', 'result'=>'resource', 'row='=>'?int', 'result_type='=>'int'], 'pg_fetch_assoc' => ['non-empty-array|false', 'result'=>'resource', 'row='=>'?int'], 'pg_fetch_object' => ['object|false', 'result'=>'', 'row='=>'?int', 'result_type='=>'int'], 'pg_fetch_object\'1' => ['object', 'result'=>'', 'row='=>'?int', 'class_name='=>'string', 'ctor_params='=>'array'], 'pg_fetch_result' => ['', 'result'=>'', 'field_name'=>'string|int'], 'pg_fetch_result\'1' => ['', 'result'=>'', 'row_number'=>'int', 'field_name'=>'string|int'], 'pg_fetch_row' => ['non-empty-list|false', 'result'=>'resource', 'row='=>'?int', 'result_type='=>'int'], 'pg_field_is_null' => ['int|false', 'result'=>'', 'field_name_or_number'=>'string|int'], 'pg_field_is_null\'1' => ['int', 'result'=>'', 'row'=>'int', 'field_name_or_number'=>'string|int'], 'pg_field_name' => ['string|false', 'result'=>'resource', 'field_number'=>'int'], 'pg_field_num' => ['int', 'result'=>'resource', 'field_name'=>'string'], 'pg_field_prtlen' => ['int|false', 'result'=>'', 'field_name_or_number'=>''], 'pg_field_prtlen\'1' => ['int', 'result'=>'', 'row'=>'int', 'field_name_or_number'=>'string|int'], 'pg_field_size' => ['int', 'result'=>'resource', 'field_number'=>'int'], 'pg_field_table' => ['mixed', 'result'=>'resource', 'field_number'=>'int', 'oid_only='=>'bool'], 'pg_field_type' => ['string', 'result'=>'resource', 'field_number'=>'int'], 'pg_field_type_oid' => ['int|false', 'result'=>'resource', 'field_number'=>'int'], 'pg_flush' => ['mixed', 'connection'=>'resource'], 'pg_free_result' => ['bool', 'result'=>'resource'], 'pg_get_notify' => ['array|false', 'connection'=>'resource', 'result_type='=>'int'], 'pg_get_pid' => ['int|false', 'connection'=>'resource'], 'pg_get_result' => ['resource|false', 'connection='=>'resource'], 'pg_host' => ['string', 'connection='=>'resource'], 'pg_insert' => ['mixed', 'db'=>'resource', 'table'=>'string', 'values'=>'array', 'options='=>'int'], 'pg_last_error' => ['string', 'connection='=>'resource', 'operation='=>'int'], 'pg_last_notice' => ['string', 'connection'=>'resource', 'option='=>'int'], 'pg_last_oid' => ['string|false', 'result'=>'resource'], 'pg_lo_close' => ['bool', 'large_object'=>'resource'], 'pg_lo_create' => ['int|false', 'connection='=>'resource', 'large_object_oid='=>''], 'pg_lo_export' => ['bool', 'connection'=>'resource', 'oid'=>'int', 'filename'=>'string'], 'pg_lo_export\'1' => ['bool', 'oid'=>'int', 'pathname'=>'string'], 'pg_lo_import' => ['int|false', 'connection'=>'resource', 'pathname'=>'string', 'oid'=>''], 'pg_lo_import\'1' => ['int', 'pathname'=>'string', 'oid'=>''], 'pg_lo_open' => ['resource|false', 'connection'=>'resource', 'oid'=>'int', 'mode'=>'string'], 'pg_lo_read' => ['string|false', 'large_object'=>'resource', 'len='=>'int'], 'pg_lo_read_all' => ['int', 'large_object'=>'resource'], 'pg_lo_seek' => ['bool', 'large_object'=>'resource', 'offset'=>'int', 'whence='=>'int'], 'pg_lo_tell' => ['int', 'large_object'=>'resource'], 'pg_lo_truncate' => ['bool', 'large_object'=>'resource', 'size'=>'int'], 'pg_lo_unlink' => ['bool', 'connection'=>'resource', 'oid'=>'int'], 'pg_lo_write' => ['int|false', 'large_object'=>'resource', 'data'=>'string', 'len='=>'int'], 'pg_meta_data' => ['array|false', 'db'=>'resource', 'table'=>'string', 'extended='=>'bool'], 'pg_num_fields' => ['int', 'result'=>'resource'], 'pg_num_rows' => ['int', 'result'=>'resource'], 'pg_options' => ['string', 'connection='=>'resource'], 'pg_parameter_status' => ['string|false', 'connection'=>'resource', 'param_name'=>'string'], 'pg_parameter_status\'1' => ['string|false', 'param_name'=>'string'], 'pg_pconnect' => ['resource|false', 'connection_string'=>'string', 'connect_type='=>'int'], 'pg_ping' => ['bool', 'connection='=>'resource'], 'pg_port' => ['int', 'connection='=>'resource'], 'pg_prepare' => ['resource|false', 'connection'=>'resource', 'stmtname'=>'string', 'query'=>'string'], 'pg_prepare\'1' => ['resource|false', 'stmtname'=>'string', 'query'=>'string'], 'pg_put_line' => ['bool', 'connection'=>'resource', 'data'=>'string'], 'pg_put_line\'1' => ['bool', 'data'=>'string'], 'pg_query' => ['resource|false', 'connection'=>'resource', 'query'=>'string'], 'pg_query\'1' => ['resource|false', 'query'=>'string'], 'pg_query_params' => ['resource|false', 'connection'=>'resource', 'query'=>'string', 'params'=>'array'], 'pg_query_params\'1' => ['resource|false', 'query'=>'string', 'params'=>'array'], 'pg_result_error' => ['string|false', 'result'=>'resource'], 'pg_result_error_field' => ['string|false|null', 'result'=>'resource', 'fieldcode'=>'int'], 'pg_result_seek' => ['bool', 'result'=>'resource', 'offset'=>'int'], 'pg_result_status' => ['mixed', 'result'=>'resource', 'result_type='=>'int'], 'pg_select' => ['mixed', 'db'=>'resource', 'table'=>'string', 'ids'=>'array', 'options='=>'int', 'result_type='=>'int'], 'pg_send_execute' => ['bool', 'connection'=>'resource', 'stmtname'=>'string', 'params'=>'array'], 'pg_send_prepare' => ['bool', 'connection'=>'resource', 'stmtname'=>'string', 'query'=>'string'], 'pg_send_query' => ['bool', 'connection'=>'resource', 'query'=>'string'], 'pg_send_query_params' => ['bool', 'connection'=>'resource', 'query'=>'string', 'params'=>'array'], 'pg_set_client_encoding' => ['int', 'connection'=>'resource', 'encoding'=>'string'], 'pg_set_client_encoding\'1' => ['int', 'encoding'=>'string'], 'pg_set_error_verbosity' => ['int|false', 'connection'=>'resource', 'verbosity'=>'int'], 'pg_set_error_verbosity\'1' => ['int', 'verbosity'=>'int'], 'pg_socket' => ['resource|false', 'connection'=>'resource'], 'pg_trace' => ['bool', 'filename'=>'string', 'mode='=>'string', 'connection='=>'resource'], 'pg_transaction_status' => ['int', 'connection'=>'resource'], 'pg_tty' => ['string', 'connection='=>'resource'], 'pg_tty\'1' => ['string'], 'pg_unescape_bytea' => ['string', 'data'=>'string'], 'pg_untrace' => ['bool', 'connection='=>'resource'], 'pg_untrace\'1' => ['bool'], 'pg_update' => ['mixed', 'db'=>'resource', 'table'=>'string', 'fields'=>'array', 'ids'=>'array', 'options='=>'int'], 'pg_version' => ['array', 'connection='=>'resource'], 'Phar::__construct' => ['void', 'fname'=>'string', 'flags='=>'int', 'alias='=>'string'], 'Phar::addEmptyDir' => ['', 'dirname'=>'string'], 'Phar::addFile' => ['', 'file'=>'string', 'localname='=>'string'], 'Phar::addFromString' => ['', 'localname'=>'string', 'contents'=>'string'], 'Phar::apiVersion' => ['string'], 'Phar::buildFromDirectory' => ['array', 'base_dir'=>'string', 'regex='=>'string'], 'Phar::buildFromIterator' => ['array', 'iter'=>'Iterator', 'base_directory='=>'string'], 'Phar::canCompress' => ['bool', 'method='=>'int'], 'Phar::canWrite' => ['bool'], 'Phar::compress' => ['Phar', 'compression'=>'int', 'extension='=>'string'], 'Phar::compressAllFilesBZIP2' => ['bool'], 'Phar::compressAllFilesGZ' => ['bool'], 'Phar::compressFiles' => ['', 'compression'=>'int'], 'Phar::convertToData' => ['PharData', 'format='=>'int', 'compression='=>'int', 'extension='=>'string'], 'Phar::convertToExecutable' => ['Phar', 'format='=>'int', 'compression='=>'int', 'extension='=>'string'], 'Phar::copy' => ['bool', 'oldfile'=>'string', 'newfile'=>'string'], 'Phar::count' => ['0|positive-int'], 'Phar::createDefaultStub' => ['string', 'indexfile='=>'string', 'webindexfile='=>'string'], 'Phar::decompress' => ['Phar', 'extension='=>'string'], 'Phar::decompressFiles' => ['bool'], 'Phar::delete' => ['bool', 'entry'=>'string'], 'Phar::delMetadata' => ['bool'], 'Phar::extractTo' => ['bool', 'pathto'=>'string', 'files='=>'string|array|null', 'overwrite='=>'bool'], 'Phar::getAlias' => ['string'], 'Phar::getMetadata' => ['mixed'], 'Phar::getModified' => ['bool'], 'Phar::getPath' => ['string'], 'Phar::getSignature' => ['array{hash:string, hash_type:string}'], 'Phar::getStub' => ['string'], 'Phar::getSupportedCompression' => ['array'], 'Phar::getSupportedSignatures' => ['array'], 'Phar::getVersion' => ['string'], 'Phar::hasMetadata' => ['bool'], 'Phar::interceptFileFuncs' => [''], 'Phar::isBuffering' => ['bool'], 'Phar::isCompressed' => [''], 'Phar::isFileFormat' => ['bool', 'format'=>'int'], 'Phar::isValidPharFilename' => ['bool', 'filename'=>'string', 'executable='=>'bool'], 'Phar::isWritable' => ['bool'], 'Phar::loadPhar' => ['bool', 'filename'=>'string', 'alias='=>'string'], 'Phar::mapPhar' => ['bool', 'alias='=>'string', 'dataoffset='=>'int'], 'Phar::mount' => ['void', 'pharpath'=>'string', 'externalpath'=>'string'], 'Phar::mungServer' => ['', 'munglist'=>'array'], 'Phar::offsetExists' => ['bool', 'offset'=>'string'], 'Phar::offsetGet' => ['PharFileInfo', 'offset'=>'string'], 'Phar::offsetSet' => ['', 'offset'=>'string', 'value'=>'string'], 'Phar::offsetUnset' => ['bool', 'offset'=>'string'], 'Phar::running' => ['string', 'retphar='=>'bool'], 'Phar::setAlias' => ['bool', 'alias'=>'string'], 'Phar::setDefaultStub' => ['bool', 'index='=>'string', 'webindex='=>'string'], 'Phar::setMetadata' => ['', 'metadata'=>''], 'Phar::setSignatureAlgorithm' => ['', 'sigtype'=>'int', 'privatekey='=>'string'], 'Phar::setStub' => ['bool', 'stub'=>'string', 'len='=>'int'], 'Phar::startBuffering' => [''], 'Phar::stopBuffering' => [''], 'Phar::uncompressAllFiles' => ['bool'], 'Phar::unlinkArchive' => ['bool', 'archive'=>'string'], 'Phar::webPhar' => ['', 'alias='=>'string', 'index='=>'string', 'f404='=>'string', 'mimetypes='=>'array', 'rewrites='=>'array'], 'PharData::__construct' => ['void', 'fname'=>'string', 'flags='=>'int', 'alias='=>'string', 'format='=>'int'], 'PharData::addEmptyDir' => ['bool', 'dirname'=>'string'], 'PharData::addFile' => ['', 'file'=>'string', 'localname='=>'string'], 'PharData::addFromString' => ['bool', 'localname'=>'string', 'contents'=>'string'], 'PharData::buildFromDirectory' => ['array', 'base_dir'=>'string', 'regex='=>'string'], 'PharData::buildFromIterator' => ['array', 'iter'=>'Iterator', 'base_directory='=>'string'], 'PharData::compress' => ['PharData', 'compression'=>'int', 'extension='=>'string'], 'PharData::compressFiles' => ['bool', 'compression'=>'int'], 'PharData::convertToData' => ['PharData', 'format='=>'int', 'compression='=>'int', 'extension='=>'string'], 'PharData::convertToExecutable' => ['Phar', 'format='=>'int', 'compression='=>'int', 'extension='=>'string'], 'PharData::copy' => ['bool', 'oldfile'=>'string', 'newfile'=>'string'], 'PharData::decompress' => ['PharData', 'extension='=>'string'], 'PharData::decompressFiles' => ['bool'], 'PharData::delete' => ['bool', 'entry'=>'string'], 'PharData::delMetadata' => ['bool'], 'PharData::extractTo' => ['bool', 'pathto'=>'string', 'files='=>'string|array|null', 'overwrite='=>'bool'], 'PharData::isWritable' => ['bool'], 'PharData::offsetGet' => ['PharFileInfo', 'offset'=>'string'], 'PharData::offsetSet' => ['', 'offset'=>'string', 'value'=>'string'], 'PharData::offsetUnset' => ['bool', 'offset'=>'string'], 'PharData::setAlias' => ['bool', 'alias'=>'string'], 'PharData::setDefaultStub' => ['bool', 'index='=>'string', 'webindex='=>'string'], 'PharData::setStub' => ['bool', 'stub'=>'string'], 'PharFileInfo::__construct' => ['void', 'entry'=>'string'], 'PharFileInfo::chmod' => ['void', 'permissions'=>'int'], 'PharFileInfo::compress' => ['bool', 'compression'=>'int'], 'PharFileInfo::decompress' => ['bool'], 'PharFileInfo::delMetadata' => ['bool'], 'PharFileInfo::getCompressedSize' => ['int'], 'PharFileInfo::getContent' => ['string'], 'PharFileInfo::getCRC32' => ['int'], 'PharFileInfo::getMetadata' => ['mixed'], 'PharFileInfo::getPharFlags' => ['int'], 'PharFileInfo::hasMetadata' => ['bool'], 'PharFileInfo::isCompressed' => ['bool', 'compression_type='=>'int'], 'PharFileInfo::isCompressedBZIP2' => ['bool'], 'PharFileInfo::isCompressedGZ' => ['bool'], 'PharFileInfo::isCRCChecked' => ['bool'], 'PharFileInfo::setCompressedBZIP2' => ['bool'], 'PharFileInfo::setCompressedGZ' => ['bool'], 'PharFileInfo::setMetadata' => ['void', 'metadata'=>'mixed'], 'PharFileInfo::setUncompressed' => ['bool'], 'phdfs::__construct' => ['void', 'ip'=>'string', 'port'=>'string'], 'phdfs::__destruct' => [''], 'phdfs::connect' => ['bool'], 'phdfs::copy' => ['bool', 'source_file'=>'string', 'destination_file'=>'string'], 'phdfs::create_directory' => ['bool', 'path'=>'string'], 'phdfs::delete' => ['bool', 'path'=>'string'], 'phdfs::disconnect' => ['bool'], 'phdfs::exists' => ['bool', 'path'=>'string'], 'phdfs::file_info' => ['array', 'path'=>'string'], 'phdfs::list_directory' => ['array', 'path'=>'string'], 'phdfs::read' => ['string', 'path'=>'string', 'length='=>'string'], 'phdfs::rename' => ['bool', 'old_path'=>'string', 'new_path'=>'string'], 'phdfs::tell' => ['int', 'path'=>'string'], 'phdfs::write' => ['bool', 'path'=>'string', 'buffer'=>'string', 'mode='=>'string'], 'php_check_syntax' => ['bool', 'filename'=>'string', 'error_message='=>'string'], 'php_ini_loaded_file' => ['non-empty-string|false'], 'php_ini_scanned_files' => ['string|false'], 'php_logo_guid' => ['string'], 'php_sapi_name' => ['__benevolent'], 'php_strip_whitespace' => ['string', 'file_name'=>'string'], 'php_uname' => ['string', 'mode='=>'string'], 'php_user_filter::filter' => ['int', 'in'=>'resource', 'out'=>'resource', '&rw_consumed'=>'int', 'closing'=>'bool'], 'php_user_filter::onClose' => ['void'], 'php_user_filter::onCreate' => ['bool'], 'phpcredits' => ['bool', 'flag='=>'int'], 'phpdbg_break_file' => ['', 'file'=>'string', 'line'=>'int'], 'phpdbg_break_function' => ['', 'function'=>'string'], 'phpdbg_break_method' => ['', 'class'=>'string', 'method'=>'string'], 'phpdbg_break_next' => [''], 'phpdbg_clear' => [''], 'phpdbg_color' => ['', 'element'=>'int', 'color'=>'string'], 'phpdbg_end_oplog' => ['array', 'options='=>'array'], 'phpdbg_prompt' => ['', 'prompt'=>'string'], 'phpdbg_start_oplog' => [''], 'phpinfo' => ['bool', 'what='=>'int'], 'phpversion' => ['string'], 'phpversion\'1' => ['string|false', 'extension'=>'string'], 'pht\AtomicInteger::__construct' => ['void', 'value='=>'int'], 'pht\AtomicInteger::dec' => ['void'], 'pht\AtomicInteger::get' => ['int'], 'pht\AtomicInteger::inc' => ['void'], 'pht\AtomicInteger::lock' => ['void'], 'pht\AtomicInteger::set' => ['void', 'value'=>'int'], 'pht\AtomicInteger::unlock' => ['void'], 'pht\HashTable::lock' => ['void'], 'pht\HashTable::size' => ['int'], 'pht\HashTable::unlock' => ['void'], 'pht\Queue::front' => ['mixed'], 'pht\Queue::lock' => ['void'], 'pht\Queue::pop' => ['mixed'], 'pht\Queue::push' => ['void', 'value'=>'mixed'], 'pht\Queue::size' => ['int'], 'pht\Queue::unlock' => ['void'], 'pht\Runnable::run' => ['void'], 'pht\Vector::__construct' => ['void', 'size='=>'int', 'value='=>'mixed'], 'pht\Vector::deleteAt' => ['void', 'offset'=>'int'], 'pht\Vector::insertAt' => ['void', 'value'=>'mixed', 'offset'=>'int'], 'pht\Vector::lock' => ['void'], 'pht\Vector::pop' => ['mixed'], 'pht\Vector::push' => ['void', 'value'=>'mixed'], 'pht\Vector::resize' => ['void', 'size'=>'int', 'value='=>'mixed'], 'pht\Vector::shift' => ['mixed'], 'pht\Vector::size' => ['int'], 'pht\Vector::unlock' => ['void'], 'pht\Vector::unshift' => ['void', 'value'=>'mixed'], 'pht\Vector::updateAt' => ['void', 'value'=>'mixed', 'offset'=>'int'], 'pi' => ['float'], 'png2wbmp' => ['bool', 'pngname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'], 'pointObj::__construct' => ['void'], 'pointObj::distanceToLine' => ['float', 'p1'=>'pointObj', 'p2'=>'pointObj'], 'pointObj::distanceToPoint' => ['float', 'poPoint'=>'pointObj'], 'pointObj::distanceToShape' => ['float', 'shape'=>'shapeObj'], 'pointObj::draw' => ['int', 'map'=>'mapObj', 'layer'=>'layerObj', 'img'=>'imageObj', 'class_index'=>'int', 'text'=>'string'], 'pointObj::ms_newPointObj' => ['pointObj'], 'pointObj::project' => ['int', 'in'=>'projectionObj', 'out'=>'projectionObj'], 'pointObj::setXY' => ['int', 'x'=>'float', 'y'=>'float', 'm'=>'float'], 'pointObj::setXYZ' => ['int', 'x'=>'float', 'y'=>'float', 'z'=>'float', 'm'=>'float'], 'Pool::__construct' => ['void', 'size'=>'int', 'class'=>'string', 'ctor='=>'array'], 'Pool::collect' => ['int', 'collector'=>'Callable'], 'Pool::resize' => ['void', 'size'=>'int'], 'Pool::shutdown' => ['void'], 'Pool::submit' => ['int', 'task'=>'Threaded'], 'Pool::submitTo' => ['int', 'worker'=>'int', 'task'=>'Threaded'], 'popen' => ['resource|false', 'command'=>'string', 'mode'=>'string'], 'pos' => ['mixed', 'array_arg'=>'array'], 'posix_access' => ['bool', 'file'=>'string', 'mode='=>'int'], 'posix_ctermid' => ['string|false'], 'posix_errno' => ['int'], 'posix_get_last_error' => ['int'], 'posix_getcwd' => ['string|false'], 'posix_getegid' => ['int'], 'posix_geteuid' => ['int'], 'posix_getgid' => ['int'], 'posix_getgrgid' => ['array{name: string, passwd: string, gid: int, members: list}|false', 'gid'=>'int'], 'posix_getgrnam' => ['array{name: string, passwd: string, gid: int, members: list}|false', 'groupname'=>'string'], 'posix_getgroups' => ['list|false'], 'posix_getlogin' => ['string|false'], 'posix_getpgid' => ['int|false', 'pid'=>'int'], 'posix_getpgrp' => ['int'], 'posix_getpid' => ['int'], 'posix_getppid' => ['int'], 'posix_getpwnam' => ['array|false', 'groupname'=>'string'], 'posix_getpwuid' => ['array{name: string, passwd: string, uid: int, gid: int, gecos: string, dir: string, shell: string}|false', 'uid'=>'int'], 'posix_getrlimit' => ['array|false'], 'posix_getsid' => ['int|false', 'pid'=>'int'], 'posix_getuid' => ['int'], 'posix_initgroups' => ['bool', 'name'=>'string', 'base_group_id'=>'int'], 'posix_isatty' => ['bool', 'fd'=>'resource|int'], 'posix_kill' => ['bool', 'pid'=>'int', 'sig'=>'int'], 'posix_mkfifo' => ['bool', 'pathname'=>'string', 'mode'=>'int'], 'posix_mknod' => ['bool', 'pathname'=>'string', 'mode'=>'int', 'major='=>'int', 'minor='=>'int'], 'posix_setegid' => ['bool', 'uid'=>'int'], 'posix_seteuid' => ['bool', 'uid'=>'int'], 'posix_setgid' => ['bool', 'uid'=>'int'], 'posix_setpgid' => ['bool', 'pid'=>'int', 'pgid'=>'int'], 'posix_setrlimit' => ['bool', 'resource'=>'int', 'softlimit'=>'int', 'hardlimit'=>'int'], 'posix_setsid' => ['int'], 'posix_setuid' => ['bool', 'uid'=>'int'], 'posix_strerror' => ['string', 'errno'=>'int'], 'posix_times' => ['array|false'], 'posix_ttyname' => ['string|false', 'fd'=>'resource|int'], 'posix_uname' => ['array|false'], 'Postal\Expand::expand_address' => ['string[]', 'address'=>'string', 'options='=>'array'], 'Postal\Parser::parse_address' => ['array', 'address'=>'string', 'options='=>'array'], 'pow' => ['float|int', 'base'=>'int|float', 'exponent'=>'int|float'], 'preg_filter' => ['string|array|null', 'regex'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_grep' => ['array|false', 'regex'=>'string', 'input'=>'array', 'flags='=>'int'], 'preg_last_error' => ['int'], 'preg_match' => ['0|1|false', 'pattern'=>'string', 'subject'=>'string', '&w_subpatterns='=>'string[]', 'flags='=>'int', 'offset='=>'int'], 'preg_match_all' => ['0|positive-int|false|null', 'pattern'=>'string', 'subject'=>'string', '&w_subpatterns='=>'array', 'flags='=>'int', 'offset='=>'int'], 'preg_quote' => ['string', 'str'=>'string', 'delim_char='=>'string'], 'preg_replace' => ['string|array|null', 'regex'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_replace_callback' => ['string|array|null', 'regex'=>'string|array', 'callback'=>'callable(array):string', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_replace_callback_array' => ['string|array|null', 'pattern'=>'array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_split' => ['list|false', 'pattern'=>'string', 'subject'=>'string', 'limit='=>'?int', 'flags='=>'int'], 'prev' => ['mixed', '&rw_array_arg'=>'array|object'], 'print_r' => ['string|true', 'var'=>'mixed', 'return='=>'bool'], 'printf' => ['int', 'format'=>'string', '...values='=>'__stringAndStringable|int|float|null|bool'], 'proc_close' => ['int', 'process'=>'resource'], 'proc_get_status' => ['array{command: string, pid: int, running: bool, signaled: bool, stopped: bool, exitcode: int, termsig: int, stopsig: int}|false', 'process'=>'resource'], 'proc_nice' => ['bool', 'priority'=>'int'], 'proc_open' => ['resource|false', 'command'=>'string', 'descriptorspec'=>'array', '&w_pipes'=>'resource[]', 'cwd='=>'?string', 'env='=>'?array', 'other_options='=>'array'], 'proc_terminate' => ['bool', 'process'=>'resource', 'signal='=>'int'], 'projectionObj::__construct' => ['void', 'projectionString'=>'string'], 'projectionObj::getUnits' => ['int'], 'projectionObj::ms_newProjectionObj' => ['projectionObj', 'projectionString'=>'string'], 'property_exists' => ['bool', 'object_or_class'=>'object|string', 'property_name'=>'string'], 'ps_add_bookmark' => ['int', 'psdoc'=>'resource', 'text'=>'string', 'parent='=>'int', 'open='=>'int'], 'ps_add_launchlink' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string'], 'ps_add_locallink' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'page'=>'int', 'dest'=>'string'], 'ps_add_note' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'contents'=>'string', 'title'=>'string', 'icon'=>'string', 'open'=>'int'], 'ps_add_pdflink' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'filename'=>'string', 'page'=>'int', 'dest'=>'string'], 'ps_add_weblink' => ['bool', 'psdoc'=>'resource', 'llx'=>'float', 'lly'=>'float', 'urx'=>'float', 'ury'=>'float', 'url'=>'string'], 'ps_arc' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'ps_arcn' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'radius'=>'float', 'alpha'=>'float', 'beta'=>'float'], 'ps_begin_page' => ['bool', 'psdoc'=>'resource', 'width'=>'float', 'height'=>'float'], 'ps_begin_pattern' => ['int', 'psdoc'=>'resource', 'width'=>'float', 'height'=>'float', 'xstep'=>'float', 'ystep'=>'float', 'painttype'=>'int'], 'ps_begin_template' => ['int', 'psdoc'=>'resource', 'width'=>'float', 'height'=>'float'], 'ps_circle' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'radius'=>'float'], 'ps_clip' => ['bool', 'psdoc'=>'resource'], 'ps_close' => ['bool', 'psdoc'=>'resource'], 'ps_close_image' => ['void', 'psdoc'=>'resource', 'imageid'=>'int'], 'ps_closepath' => ['bool', 'psdoc'=>'resource'], 'ps_closepath_stroke' => ['bool', 'psdoc'=>'resource'], 'ps_continue_text' => ['bool', 'psdoc'=>'resource', 'text'=>'string'], 'ps_curveto' => ['bool', 'psdoc'=>'resource', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'ps_delete' => ['bool', 'psdoc'=>'resource'], 'ps_end_page' => ['bool', 'psdoc'=>'resource'], 'ps_end_pattern' => ['bool', 'psdoc'=>'resource'], 'ps_end_template' => ['bool', 'psdoc'=>'resource'], 'ps_fill' => ['bool', 'psdoc'=>'resource'], 'ps_fill_stroke' => ['bool', 'psdoc'=>'resource'], 'ps_findfont' => ['int', 'psdoc'=>'resource', 'fontname'=>'string', 'encoding'=>'string', 'embed='=>'bool'], 'ps_get_buffer' => ['string', 'psdoc'=>'resource'], 'ps_get_parameter' => ['string', 'psdoc'=>'resource', 'name'=>'string', 'modifier='=>'float'], 'ps_get_value' => ['float', 'psdoc'=>'resource', 'name'=>'string', 'modifier='=>'float'], 'ps_hyphenate' => ['array', 'psdoc'=>'resource', 'text'=>'string'], 'ps_include_file' => ['bool', 'psdoc'=>'resource', 'file'=>'string'], 'ps_lineto' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'ps_makespotcolor' => ['int', 'psdoc'=>'resource', 'name'=>'string', 'reserved='=>'int'], 'ps_moveto' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'ps_new' => ['resource'], 'ps_open_file' => ['bool', 'psdoc'=>'resource', 'filename='=>'string'], 'ps_open_image' => ['int', 'psdoc'=>'resource', 'type'=>'string', 'source'=>'string', 'data'=>'string', 'length'=>'int', 'width'=>'int', 'height'=>'int', 'components'=>'int', 'bpc'=>'int', 'params'=>'string'], 'ps_open_image_file' => ['int', 'psdoc'=>'resource', 'type'=>'string', 'filename'=>'string', 'stringparam='=>'string', 'intparam='=>'int'], 'ps_open_memory_image' => ['int', 'psdoc'=>'resource', 'gd'=>'int'], 'ps_place_image' => ['bool', 'psdoc'=>'resource', 'imageid'=>'int', 'x'=>'float', 'y'=>'float', 'scale'=>'float'], 'ps_rect' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float'], 'ps_restore' => ['bool', 'psdoc'=>'resource'], 'ps_rotate' => ['bool', 'psdoc'=>'resource', 'rot'=>'float'], 'ps_save' => ['bool', 'psdoc'=>'resource'], 'ps_scale' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'ps_set_border_color' => ['bool', 'psdoc'=>'resource', 'red'=>'float', 'green'=>'float', 'blue'=>'float'], 'ps_set_border_dash' => ['bool', 'psdoc'=>'resource', 'black'=>'float', 'white'=>'float'], 'ps_set_border_style' => ['bool', 'psdoc'=>'resource', 'style'=>'string', 'width'=>'float'], 'ps_set_info' => ['bool', 'p'=>'resource', 'key'=>'string', 'val'=>'string'], 'ps_set_parameter' => ['bool', 'psdoc'=>'resource', 'name'=>'string', 'value'=>'string'], 'ps_set_text_pos' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'ps_set_value' => ['bool', 'psdoc'=>'resource', 'name'=>'string', 'value'=>'float'], 'ps_setcolor' => ['bool', 'psdoc'=>'resource', 'type'=>'string', 'colorspace'=>'string', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float'], 'ps_setdash' => ['bool', 'psdoc'=>'resource', 'on'=>'float', 'off'=>'float'], 'ps_setflat' => ['bool', 'psdoc'=>'resource', 'value'=>'float'], 'ps_setfont' => ['bool', 'psdoc'=>'resource', 'fontid'=>'int', 'size'=>'float'], 'ps_setgray' => ['bool', 'psdoc'=>'resource', 'gray'=>'float'], 'ps_setlinecap' => ['bool', 'psdoc'=>'resource', 'type'=>'int'], 'ps_setlinejoin' => ['bool', 'psdoc'=>'resource', 'type'=>'int'], 'ps_setlinewidth' => ['bool', 'psdoc'=>'resource', 'width'=>'float'], 'ps_setmiterlimit' => ['bool', 'psdoc'=>'resource', 'value'=>'float'], 'ps_setoverprintmode' => ['bool', 'psdoc'=>'resource', 'mode'=>'int'], 'ps_setpolydash' => ['bool', 'psdoc'=>'resource', 'arr'=>'float'], 'ps_shading' => ['int', 'psdoc'=>'resource', 'type'=>'string', 'x0'=>'float', 'y0'=>'float', 'x1'=>'float', 'y1'=>'float', 'c1'=>'float', 'c2'=>'float', 'c3'=>'float', 'c4'=>'float', 'optlist'=>'string'], 'ps_shading_pattern' => ['int', 'psdoc'=>'resource', 'shadingid'=>'int', 'optlist'=>'string'], 'ps_shfill' => ['bool', 'psdoc'=>'resource', 'shadingid'=>'int'], 'ps_show' => ['bool', 'psdoc'=>'resource', 'text'=>'string'], 'ps_show2' => ['bool', 'psdoc'=>'resource', 'text'=>'string', 'len'=>'int'], 'ps_show_boxed' => ['int', 'psdoc'=>'resource', 'text'=>'string', 'left'=>'float', 'bottom'=>'float', 'width'=>'float', 'height'=>'float', 'hmode'=>'string', 'feature='=>'string'], 'ps_show_xy' => ['bool', 'psdoc'=>'resource', 'text'=>'string', 'x'=>'float', 'y'=>'float'], 'ps_show_xy2' => ['bool', 'psdoc'=>'resource', 'text'=>'string', 'len'=>'int', 'xcoor'=>'float', 'ycoor'=>'float'], 'ps_string_geometry' => ['array', 'psdoc'=>'resource', 'text'=>'string', 'fontid='=>'int', 'size='=>'float'], 'ps_stringwidth' => ['float', 'psdoc'=>'resource', 'text'=>'string', 'fontid='=>'int', 'size='=>'float'], 'ps_stroke' => ['bool', 'psdoc'=>'resource'], 'ps_symbol' => ['bool', 'psdoc'=>'resource', 'ord'=>'int'], 'ps_symbol_name' => ['string', 'psdoc'=>'resource', 'ord'=>'int', 'fontid='=>'int'], 'ps_symbol_width' => ['float', 'psdoc'=>'resource', 'ord'=>'int', 'fontid='=>'int', 'size='=>'float'], 'ps_translate' => ['bool', 'psdoc'=>'resource', 'x'=>'float', 'y'=>'float'], 'pspell_add_to_personal' => ['bool', 'pspell'=>'int', 'word'=>'string'], 'pspell_add_to_session' => ['bool', 'pspell'=>'int', 'word'=>'string'], 'pspell_check' => ['bool', 'pspell'=>'int', 'word'=>'string'], 'pspell_clear_session' => ['bool', 'pspell'=>'int'], 'pspell_config_create' => ['int|false', 'language'=>'string', 'spelling='=>'string', 'jargon='=>'string', 'encoding='=>'string'], 'pspell_config_data_dir' => ['bool', 'conf'=>'int', 'directory'=>'string'], 'pspell_config_dict_dir' => ['bool', 'conf'=>'int', 'directory'=>'string'], 'pspell_config_ignore' => ['bool', 'conf'=>'int', 'ignore'=>'int'], 'pspell_config_mode' => ['bool', 'conf'=>'int', 'mode'=>'int'], 'pspell_config_personal' => ['bool', 'conf'=>'int', 'personal'=>'string'], 'pspell_config_repl' => ['bool', 'conf'=>'int', 'repl'=>'string'], 'pspell_config_runtogether' => ['bool', 'conf'=>'int', 'runtogether'=>'bool'], 'pspell_config_save_repl' => ['bool', 'conf'=>'int', 'save'=>'bool'], 'pspell_new' => ['int|false', 'language'=>'string', 'spelling='=>'string', 'jargon='=>'string', 'encoding='=>'string', 'mode='=>'int'], 'pspell_new_config' => ['int|false', 'config'=>'int'], 'pspell_new_personal' => ['int|false', 'personal'=>'string', 'language'=>'string', 'spelling='=>'string', 'jargon='=>'string', 'encoding='=>'string', 'mode='=>'int'], 'pspell_save_wordlist' => ['bool', 'pspell'=>'int'], 'pspell_store_replacement' => ['bool', 'pspell'=>'int', 'misspell'=>'string', 'correct'=>'string'], 'pspell_suggest' => ['array|false', 'pspell'=>'int', 'word'=>'string'], 'putenv' => ['bool', 'setting'=>'string'], 'px_close' => ['bool', 'pxdoc'=>'resource'], 'px_create_fp' => ['bool', 'pxdoc'=>'resource', 'file'=>'resource', 'fielddesc'=>'array'], 'px_date2string' => ['string', 'pxdoc'=>'resource', 'value'=>'int', 'format'=>'string'], 'px_delete' => ['bool', 'pxdoc'=>'resource'], 'px_delete_record' => ['bool', 'pxdoc'=>'resource', 'num'=>'int'], 'px_get_field' => ['array', 'pxdoc'=>'resource', 'fieldno'=>'int'], 'px_get_info' => ['array', 'pxdoc'=>'resource'], 'px_get_parameter' => ['string', 'pxdoc'=>'resource', 'name'=>'string'], 'px_get_record' => ['array', 'pxdoc'=>'resource', 'num'=>'int', 'mode='=>'int'], 'px_get_schema' => ['array', 'pxdoc'=>'resource', 'mode='=>'int'], 'px_get_value' => ['float', 'pxdoc'=>'resource', 'name'=>'string'], 'px_insert_record' => ['int', 'pxdoc'=>'resource', 'data'=>'array'], 'px_new' => ['resource'], 'px_numfields' => ['int', 'pxdoc'=>'resource'], 'px_numrecords' => ['int', 'pxdoc'=>'resource'], 'px_open_fp' => ['bool', 'pxdoc'=>'resource', 'file'=>'resource'], 'px_put_record' => ['bool', 'pxdoc'=>'resource', 'record'=>'array', 'recpos='=>'int'], 'px_retrieve_record' => ['array', 'pxdoc'=>'resource', 'num'=>'int', 'mode='=>'int'], 'px_set_blob_file' => ['bool', 'pxdoc'=>'resource', 'filename'=>'string'], 'px_set_parameter' => ['bool', 'pxdoc'=>'resource', 'name'=>'string', 'value'=>'string'], 'px_set_tablename' => ['void', 'pxdoc'=>'resource', 'name'=>'string'], 'px_set_targetencoding' => ['bool', 'pxdoc'=>'resource', 'encoding'=>'string'], 'px_set_value' => ['bool', 'pxdoc'=>'resource', 'name'=>'string', 'value'=>'float'], 'px_timestamp2string' => ['string', 'pxdoc'=>'resource', 'value'=>'float', 'format'=>'string'], 'px_update_record' => ['bool', 'pxdoc'=>'resource', 'data'=>'array', 'num'=>'int'], 'qdom_error' => ['string'], 'qdom_tree' => ['QDomDocument', 'doc'=>'string'], 'querymapObj::convertToString' => ['string'], 'querymapObj::free' => ['void'], 'querymapObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'querymapObj::updateFromString' => ['int', 'snippet'=>'string'], 'QuickHashIntHash::__construct' => ['void', 'size'=>'int', 'options='=>'int'], 'QuickHashIntHash::add' => ['bool', 'key'=>'int', 'value='=>'int'], 'QuickHashIntHash::delete' => ['bool', 'key'=>'int'], 'QuickHashIntHash::exists' => ['bool', 'key'=>'int'], 'QuickHashIntHash::get' => ['int', 'key'=>'int'], 'QuickHashIntHash::getSize' => ['int'], 'QuickHashIntHash::loadFromFile' => ['QuickHashIntHash', 'filename'=>'string', 'options='=>'int'], 'QuickHashIntHash::loadFromString' => ['QuickHashIntHash', 'contents'=>'string', 'options='=>'int'], 'QuickHashIntHash::saveToFile' => ['void', 'filename'=>'string'], 'QuickHashIntHash::saveToString' => ['string'], 'QuickHashIntHash::set' => ['bool', 'key'=>'int', 'value'=>'int'], 'QuickHashIntHash::update' => ['bool', 'key'=>'int', 'value'=>'int'], 'QuickHashIntSet::__construct' => ['void', 'size'=>'int', 'options='=>'int'], 'QuickHashIntSet::add' => ['bool', 'key'=>'int'], 'QuickHashIntSet::delete' => ['bool', 'key'=>'int'], 'QuickHashIntSet::exists' => ['bool', 'key'=>'int'], 'QuickHashIntSet::getSize' => ['int'], 'QuickHashIntSet::loadFromFile' => ['QuickHashIntSet', 'filename'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashIntSet::loadFromString' => ['QuickHashIntSet', 'contents'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashIntSet::saveToFile' => ['void', 'filename'=>'string'], 'QuickHashIntSet::saveToString' => ['string'], 'QuickHashIntStringHash::__construct' => ['void', 'size'=>'int', 'options='=>'int'], 'QuickHashIntStringHash::add' => ['bool', 'key'=>'int', 'value'=>'string'], 'QuickHashIntStringHash::delete' => ['bool', 'key'=>'int'], 'QuickHashIntStringHash::exists' => ['bool', 'key'=>'int'], 'QuickHashIntStringHash::get' => ['mixed', 'key'=>'int'], 'QuickHashIntStringHash::getSize' => ['int'], 'QuickHashIntStringHash::loadFromFile' => ['QuickHashIntStringHash', 'filename'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashIntStringHash::loadFromString' => ['QuickHashIntStringHash', 'contents'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashIntStringHash::saveToFile' => ['void', 'filename'=>'string'], 'QuickHashIntStringHash::saveToString' => ['string'], 'QuickHashIntStringHash::set' => ['int', 'key'=>'int', 'value'=>'string'], 'QuickHashIntStringHash::update' => ['bool', 'key'=>'int', 'value'=>'string'], 'QuickHashStringIntHash::__construct' => ['void', 'size'=>'int', 'options='=>'int'], 'QuickHashStringIntHash::add' => ['bool', 'key'=>'string', 'value'=>'int'], 'QuickHashStringIntHash::delete' => ['bool', 'key'=>'string'], 'QuickHashStringIntHash::exists' => ['bool', 'key'=>'string'], 'QuickHashStringIntHash::get' => ['mixed', 'key'=>'string'], 'QuickHashStringIntHash::getSize' => ['int'], 'QuickHashStringIntHash::loadFromFile' => ['QuickHashStringIntHash', 'filename'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashStringIntHash::loadFromString' => ['QuickHashStringIntHash', 'contents'=>'string', 'size='=>'int', 'options='=>'int'], 'QuickHashStringIntHash::saveToFile' => ['void', 'filename'=>'string'], 'QuickHashStringIntHash::saveToString' => ['string'], 'QuickHashStringIntHash::set' => ['int', 'key'=>'string', 'value'=>'int'], 'QuickHashStringIntHash::update' => ['bool', 'key'=>'string', 'value'=>'int'], 'quoted_printable_decode' => ['string', 'str'=>'string'], 'quoted_printable_encode' => ['string', 'str'=>'string'], 'quotemeta' => ['string', 'str'=>'string'], 'rad2deg' => ['float', 'number'=>'float'], 'radius_acct_open' => ['resource|false'], 'radius_add_server' => ['bool', 'radius_handle'=>'resource', 'hostname'=>'string', 'port'=>'int', 'secret'=>'string', 'timeout'=>'int', 'max_tries'=>'int'], 'radius_auth_open' => ['resource|false'], 'radius_close' => ['bool', 'radius_handle'=>'resource'], 'radius_config' => ['bool', 'radius_handle'=>'resource', 'file'=>'string'], 'radius_create_request' => ['bool', 'radius_handle'=>'resource', 'type'=>'int'], 'radius_cvt_addr' => ['string', 'data'=>'string'], 'radius_cvt_int' => ['int', 'data'=>'string'], 'radius_cvt_string' => ['string', 'data'=>'string'], 'radius_demangle' => ['string', 'radius_handle'=>'resource', 'mangled'=>'string'], 'radius_demangle_mppe_key' => ['string', 'radius_handle'=>'resource', 'mangled'=>'string'], 'radius_get_attr' => ['mixed', 'radius_handle'=>'resource'], 'radius_get_tagged_attr_data' => ['string', 'data'=>'string'], 'radius_get_tagged_attr_tag' => ['int', 'data'=>'string'], 'radius_get_vendor_attr' => ['array', 'data'=>'string'], 'radius_put_addr' => ['bool', 'radius_handle'=>'resource', 'type'=>'int', 'addr'=>'string'], 'radius_put_attr' => ['bool', 'radius_handle'=>'resource', 'type'=>'int', 'value'=>'string'], 'radius_put_int' => ['bool', 'radius_handle'=>'resource', 'type'=>'int', 'value'=>'int'], 'radius_put_string' => ['bool', 'radius_handle'=>'resource', 'type'=>'int', 'value'=>'string'], 'radius_put_vendor_addr' => ['bool', 'radius_handle'=>'resource', 'vendor'=>'int', 'type'=>'int', 'addr'=>'string'], 'radius_put_vendor_attr' => ['bool', 'radius_handle'=>'resource', 'vendor'=>'int', 'type'=>'int', 'value'=>'string'], 'radius_put_vendor_int' => ['bool', 'radius_handle'=>'resource', 'vendor'=>'int', 'type'=>'int', 'value'=>'int'], 'radius_put_vendor_string' => ['bool', 'radius_handle'=>'resource', 'vendor'=>'int', 'type'=>'int', 'value'=>'string'], 'radius_request_authenticator' => ['string', 'radius_handle'=>'resource'], 'radius_salt_encrypt_attr' => ['string', 'radius_handle'=>'resource', 'data'=>'string'], 'radius_send_request' => ['int', 'radius_handle'=>'resource'], 'radius_server_secret' => ['string', 'radius_handle'=>'resource'], 'radius_strerror' => ['string', 'radius_handle'=>'resource'], 'rand' => ['int', 'min'=>'int', 'max'=>'int'], 'rand\'1' => ['int'], 'random_bytes' => ['non-empty-string', 'length'=>'positive-int'], 'random_int' => ['int', 'min'=>'int', 'max'=>'int'], 'range' => ['array', 'low'=>'int|float|string', 'high'=>'int|float|string', 'step='=>'int|float'], 'RangeException::__clone' => ['void'], 'RangeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?RangeException)'], 'RangeException::__toString' => ['string'], 'RangeException::getCode' => ['int'], 'RangeException::getFile' => ['string'], 'RangeException::getLine' => ['int'], 'RangeException::getMessage' => ['string'], 'RangeException::getPrevious' => ['Throwable|RangeException|null'], 'RangeException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'RangeException::getTraceAsString' => ['string'], 'rar_allow_broken_set' => ['bool', 'rarfile'=>'RarArchive', 'allow_broken'=>'bool'], 'rar_broken_is' => ['bool', 'rarfile'=>'RarArchive'], 'rar_close' => ['bool', 'rarfile'=>'RarArchive'], 'rar_comment_get' => ['string|null', 'rarfile'=>'RarArchive'], 'rar_entry_get' => ['RarEntry|false', 'rarfile'=>'RarArchive', 'entryname'=>'string'], 'rar_list' => ['RarEntry[]|false', 'rarfile'=>'RarArchive'], 'rar_open' => ['RarArchive|false', 'filename'=>'string', 'password='=>'string', 'volume_callback='=>'callable'], 'rar_solid_is' => ['bool', 'rarfile'=>'RarArchive'], 'rar_wrapper_cache_stats' => ['string'], 'RarArchive::__toString' => ['string'], 'RarArchive::close' => ['bool'], 'RarArchive::getComment' => ['string|null'], 'RarArchive::getEntries' => ['RarEntry[]|false'], 'RarArchive::getEntry' => ['RarEntry|false', 'entryname'=>'string'], 'RarArchive::isBroken' => ['bool'], 'RarArchive::isSolid' => ['bool'], 'RarArchive::open' => ['RarArchive|false', 'filename'=>'string', 'password='=>'string', 'volume_callback='=>'callable'], 'RarArchive::setAllowBroken' => ['bool', 'allow_broken'=>'bool'], 'RarEntry::__toString' => ['string'], 'RarEntry::extract' => ['bool', 'dir'=>'string', 'filepath='=>'string', 'password='=>'string', 'extended_data='=>'bool'], 'RarEntry::getAttr' => ['int'], 'RarEntry::getCrc' => ['string'], 'RarEntry::getFileTime' => ['string'], 'RarEntry::getHostOs' => ['int'], 'RarEntry::getMethod' => ['int'], 'RarEntry::getName' => ['string'], 'RarEntry::getPackedSize' => ['int'], 'RarEntry::getPosition' => ['int'], 'RarEntry::getRedirTarget' => ['string|bool'], 'RarEntry::getRedirType' => ['int|false|null'], 'RarEntry::getStream' => ['resource|false', 'password='=>'string'], 'RarEntry::getUnpackedSize' => ['int'], 'RarEntry::getVersion' => ['int'], 'RarEntry::isDirectory' => ['bool'], 'RarEntry::isEncrypted' => ['bool'], 'RarEntry::isRedirectToDirectory' => ['bool|null'], 'RarException::getCode' => ['int'], 'RarException::getFile' => ['string'], 'RarException::getLine' => ['int'], 'RarException::getMessage' => ['string'], 'RarException::getPrevious' => ['Exception|Throwable'], 'RarException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'RarException::getTraceAsString' => ['string'], 'RarException::isUsingExceptions' => ['bool'], 'RarException::setUsingExceptions' => ['void', 'using_exceptions'=>'bool'], 'rawurldecode' => ['string', 'str'=>'string'], 'rawurlencode' => ['string', 'str'=>'string'], 'read_exif_data' => ['array', 'filename'=>'string|resource', 'sections_needed='=>'string', 'sub_arrays='=>'bool', 'read_thumbnail='=>'bool'], 'readdir' => ['non-empty-string|false', 'dir_handle='=>'resource'], 'readfile' => ['0|positive-int|false', 'filename'=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'readgzfile' => ['0|positive-int|false', 'filename'=>'string', 'use_include_path='=>'int'], 'readline' => ['string|false', 'prompt='=>'?string'], 'readline_add_history' => ['bool', 'prompt'=>'string'], 'readline_callback_handler_install' => ['bool', 'prompt'=>'string', 'callback'=>'callable'], 'readline_callback_handler_remove' => ['bool'], 'readline_callback_read_char' => ['void'], 'readline_clear_history' => ['bool'], 'readline_completion_function' => ['bool', 'funcname'=>'callable'], 'readline_info' => ['mixed', 'varname='=>'string', 'newvalue='=>'string'], 'readline_list_history' => ['array'], 'readline_on_new_line' => ['void'], 'readline_read_history' => ['bool', 'filename='=>'string'], 'readline_redisplay' => ['void'], 'readline_write_history' => ['bool', 'filename='=>'string'], 'readlink' => ['string|false', 'filename'=>'string'], 'realpath' => ['non-empty-string|false', 'path'=>'string'], 'realpath_cache_get' => ['array'], 'realpath_cache_size' => ['int'], 'recode' => ['string', 'request'=>'string', 'str'=>'string'], 'recode_file' => ['bool', 'request'=>'string', 'input'=>'resource', 'output'=>'resource'], 'recode_string' => ['string', 'request'=>'string', 'str'=>'string'], 'rectObj::__construct' => ['void'], 'rectObj::draw' => ['int', 'map'=>'mapObj', 'layer'=>'layerObj', 'img'=>'imageObj', 'class_index'=>'int', 'text'=>'string'], 'rectObj::fit' => ['float', 'width'=>'int', 'height'=>'int'], 'rectObj::ms_newRectObj' => ['rectObj'], 'rectObj::project' => ['int', 'in'=>'projectionObj', 'out'=>'projectionObj'], 'rectObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'rectObj::setextent' => ['void', 'minx'=>'float', 'miny'=>'float', 'maxx'=>'float', 'maxy'=>'float'], 'RecursiveArrayIterator::__construct' => ['void', 'array='=>'array|object', 'flags='=>'int'], 'RecursiveArrayIterator::append' => ['void', 'value'=>'mixed'], 'RecursiveArrayIterator::asort' => ['void'], 'RecursiveArrayIterator::count' => ['0|positive-int'], 'RecursiveArrayIterator::current' => ['mixed'], 'RecursiveArrayIterator::getArrayCopy' => ['array'], 'RecursiveArrayIterator::getChildren' => ['RecursiveArrayIterator'], 'RecursiveArrayIterator::getFlags' => ['void'], 'RecursiveArrayIterator::hasChildren' => ['bool'], 'RecursiveArrayIterator::key' => ['false|int|string'], 'RecursiveArrayIterator::ksort' => ['void'], 'RecursiveArrayIterator::natcasesort' => ['void'], 'RecursiveArrayIterator::natsort' => ['void'], 'RecursiveArrayIterator::next' => ['void'], 'RecursiveArrayIterator::offsetExists' => ['void', 'index'=>'string'], 'RecursiveArrayIterator::offsetGet' => ['mixed', 'index'=>'string'], 'RecursiveArrayIterator::offsetSet' => ['void', 'index'=>'string', 'newval'=>'string'], 'RecursiveArrayIterator::offsetUnset' => ['void', 'index'=>'string'], 'RecursiveArrayIterator::rewind' => ['void'], 'RecursiveArrayIterator::seek' => ['void', 'position'=>'int'], 'RecursiveArrayIterator::serialize' => ['string'], 'RecursiveArrayIterator::setFlags' => ['void', 'flags'=>'string'], 'RecursiveArrayIterator::uasort' => ['void', 'callback'=>'callable(mixed,mixed):int'], 'RecursiveArrayIterator::uksort' => ['void', 'callback'=>'callable(array-key,array-key):int'], 'RecursiveArrayIterator::unserialize' => ['string', 'serialized'=>'string'], 'RecursiveArrayIterator::valid' => ['bool'], 'RecursiveCachingIterator::__construct' => ['void', 'iterator'=>'Iterator', 'flags'=>''], 'RecursiveCachingIterator::getChildren' => ['RecursiveCachingIterator'], 'RecursiveCachingIterator::hasChildren' => ['bool'], 'RecursiveCallbackFilterIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator', 'func'=>'callable'], 'RecursiveCallbackFilterIterator::getChildren' => ['RecursiveCallbackFilterIterator'], 'RecursiveCallbackFilterIterator::hasChildren' => ['void'], 'RecursiveDirectoryIterator::__construct' => ['void', 'path'=>'string', 'flags='=>'int'], 'RecursiveDirectoryIterator::getChildren' => ['object'], 'RecursiveDirectoryIterator::getSubPath' => ['string'], 'RecursiveDirectoryIterator::getSubPathname' => ['string'], 'RecursiveDirectoryIterator::hasChildren' => ['bool', 'allow_links='=>'bool'], 'RecursiveDirectoryIterator::key' => ['string'], 'RecursiveDirectoryIterator::next' => ['void'], 'RecursiveDirectoryIterator::rewind' => ['void'], 'RecursiveFilterIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator'], 'RecursiveFilterIterator::getChildren' => ['RecursiveFilterIterator'], 'RecursiveFilterIterator::hasChildren' => ['bool'], 'RecursiveIterator::getChildren' => ['RecursiveIterator'], 'RecursiveIterator::hasChildren' => ['bool'], 'RecursiveIteratorIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator|IteratorAggregate', 'mode='=>'int', 'flags='=>'int'], 'RecursiveIteratorIterator::beginChildren' => ['void'], 'RecursiveIteratorIterator::beginIteration' => ['RecursiveIterator'], 'RecursiveIteratorIterator::callGetChildren' => ['RecursiveIterator'], 'RecursiveIteratorIterator::callHasChildren' => ['bool'], 'RecursiveIteratorIterator::current' => ['mixed'], 'RecursiveIteratorIterator::endChildren' => ['void'], 'RecursiveIteratorIterator::endIteration' => ['RecursiveIterator'], 'RecursiveIteratorIterator::getDepth' => ['int'], 'RecursiveIteratorIterator::getInnerIterator' => ['RecursiveIterator'], 'RecursiveIteratorIterator::getMaxDepth' => ['int|false'], 'RecursiveIteratorIterator::getSubIterator' => ['RecursiveIterator', 'level='=>'int'], 'RecursiveIteratorIterator::key' => ['mixed'], 'RecursiveIteratorIterator::next' => ['void'], 'RecursiveIteratorIterator::nextElement' => ['void'], 'RecursiveIteratorIterator::rewind' => ['void'], 'RecursiveIteratorIterator::setMaxDepth' => ['void', 'max_depth='=>'int'], 'RecursiveIteratorIterator::valid' => ['bool'], 'RecursiveRegexIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator', 'regex='=>'string', 'mode='=>'int', 'flags='=>'int', 'preg_flags='=>'int'], 'RecursiveRegexIterator::getChildren' => ['RecursiveRegexIterator'], 'RecursiveRegexIterator::hasChildren' => ['bool'], 'RecursiveTreeIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator|IteratorAggregate', 'flags='=>'int', 'cit_flags='=>'int', 'mode='=>'int'], 'RecursiveTreeIterator::beginChildren' => ['void'], 'RecursiveTreeIterator::beginIteration' => ['RecursiveIterator'], 'RecursiveTreeIterator::callGetChildren' => ['RecursiveIterator'], 'RecursiveTreeIterator::callHasChildren' => ['bool'], 'RecursiveTreeIterator::current' => ['string'], 'RecursiveTreeIterator::endChildren' => ['void'], 'RecursiveTreeIterator::endIteration' => ['void'], 'RecursiveTreeIterator::getEntry' => ['string'], 'RecursiveTreeIterator::getPostfix' => ['string'], 'RecursiveTreeIterator::getPrefix' => ['string'], 'RecursiveTreeIterator::key' => ['string'], 'RecursiveTreeIterator::next' => ['void'], 'RecursiveTreeIterator::nextElement' => ['void'], 'RecursiveTreeIterator::rewind' => ['void'], 'RecursiveTreeIterator::setPostfix' => ['void', 'prefix'=>'string'], 'RecursiveTreeIterator::setPrefixPart' => ['void', 'part'=>'int', 'prefix'=>'string'], 'RecursiveTreeIterator::valid' => ['bool'], 'Redis::__construct' => ['void', 'options='=>'?array{host?:string,port?:int,connectTimeout?:float,auth?:list{string|null|false,string}|list{string},ssl?:array,backoff?:array}'], 'Redis::_compress' => ['string', 'value'=>'string'], 'Redis::_uncompress' => ['string', 'value'=>'string'], 'Redis::_prefix' => ['string', 'key'=>'mixed'], 'Redis::_serialize' => ['mixed', 'value'=>'string'], 'Redis::_unserialize' => ['string', 'value'=>'mixed'], 'Redis::_pack' => ['mixed', 'value'=>'string'], 'Redis::_unpack' => ['string', 'value'=>'mixed'], 'Redis::acl' => ['mixed', 'subcmd'=>'string', '...args='=>'string'], 'Redis::append' => ['__benevolent', 'key'=>'string', 'value'=>'string'], 'Redis::auth' => ['__benevolent', 'credentials'=>'string|string[]'], 'Redis::bgrewriteaof' => ['__benevolent'], 'Redis::bgSave' => ['__benevolent'], 'Redis::bitcount' => ['__benevolent', 'key'=>'string', 'start='=>'int', 'end='=>'int', 'bybit='=>'bool'], 'Redis::bitop' => ['__benevolent', 'operation'=>'string', 'deskey'=>'string', 'srckey'=>'string', '...other_keys'=>'string'], 'Redis::bitpos' => ['__benevolent', 'key'=>'string', 'bit'=>'bool', 'start='=>'int', 'end='=>'int', 'bybit='=>'bool'], 'Redis::blmove' => ['__benevolent', 'src'=>'string', 'dst'=>'string', 'wherefrom'=>'string', 'whereto'=>'string', 'timeout'=>'float'], 'Redis::blmpop' => ['__benevolent', 'timeout'=>'float', 'keys'=>'string[]', 'from'=>'string', 'count='=>'int'], 'Redis::blPop' => ['__benevolent', 'key_or_keys'=>'string|string[]', 'timeout_or_key'=>'string|float|int', '...extra_args'=>'mixed'], 'Redis::blPop\'1' => ['array', 'key'=>'string', 'timeout_or_key'=>'int|string', '...extra_args'=>'int|string'], 'Redis::brPop' => ['__benevolent', 'key_or_keys'=>'string|string[]', 'timeout_or_key'=>'string|float|int', '...extra_args'=>'mixed'], 'Redis::brPop\'1' => ['array', 'key'=>'string', 'timeout_or_key'=>'int|string', '...extra_args'=>'int|string'], 'Redis::brpoplpush' => ['__benevolent', 'src'=>'string', 'dst'=>'string', 'timeout'=>'int|float'], 'Redis::bzPopMax' => ['__benevolent', 'key'=>'string|string[]', 'timeout_or_key'=>'string|int', '...extra_args'=>'mixed'], 'Redis::bzPopMin' => ['__benevolent', 'key'=>'string|string[]', 'timeout_or_key'=>'string|int', '...extra_args'=>'mixed'], 'Redis::bzmpop' => ['__benevolent', 'timeout'=>'float', 'keys'=>'string[]', 'from'=>'string', 'count='=>'int'], 'Redis::clearLastError' => ['bool'], 'Redis::clearTransferredBytes' => ['void'], 'Redis::client' => ['mixed', 'opt'=>'string', '...args='=>'mixed'], 'Redis::close' => ['bool'], 'Redis::command' => ['mixed', 'opt='=>'?string', '...args'=>'mixed'], 'Redis::config' => ['mixed', 'operation'=>'string', 'key_or_settings='=>'array|string[]|string|null', 'value='=>'?string'], 'Redis::connect' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'float', 'persistent_id='=>'?string', 'retry_interval='=>'int', 'read_timeout='=>'float', 'context='=>'?array{auth?:list{string|null|false,string}|list{string},stream?:array}'], 'Redis::copy' => ['__benevolent', 'src'=>'string', 'dst'=>'string', 'options='=>'?array'], 'Redis::dbSize' => ['__benevolent'], 'Redis::debug' => ['__benevolent', 'key'=>'string'], 'Redis::decr' => ['__benevolent', 'key'=>'string', 'by='=>'int'], 'Redis::decrBy' => ['__benevolent', 'key'=>'string', 'value'=>'int'], 'Redis::decrByFloat' => ['float', 'key'=>'string', 'value'=>'float'], 'Redis::del' => ['__benevolent', 'key'=>'string[]|string', '...other_keys='=>'string'], 'Redis::del\'1' => ['int', 'key'=>'string[]'], 'Redis::delete' => ['__benevolent', 'key'=>'string[]|string', '...other_keys='=>'string'], 'Redis::delete\'1' => ['int', 'key'=>'string[]'], 'Redis::discard' => ['__benevolent'], 'Redis::dump' => ['__benevolent', 'key'=>'string'], 'Redis::echo' => ['__benevolent', 'str'=>'string'], 'Redis::eval' => ['mixed', 'script'=>'string', 'args='=>'array', 'num_keys='=>'int'], 'Redis::eval_ro' => ['mixed', 'script'=>'string', 'args='=>'array', 'num_keys='=>'int'], 'Redis::evalsha' => ['mixed', 'sha1'=>'string', 'args='=>'array', 'num_keys='=>'int'], 'Redis::evalsha_ro' => ['mixed', 'sha1'=>'string', 'args='=>'array', 'num_keys='=>'int'], 'Redis::evaluate' => ['mixed', 'script'=>'string', 'args='=>'array', 'numKeys='=>'int'], 'Redis::exec' => ['__benevolent'], 'Redis::exists' => ['__benevolent', 'keys'=>'string|string[]', '...other_keys='=>'string'], 'Redis::exists\'1' => ['int', '...keys'=>'string'], 'Redis::expire' => ['__benevolent', 'key'=>'string', 'timeout'=>'int', 'mode='=>'?string'], 'Redis::expireAt' => ['__benevolent', 'key'=>'string', 'timeout'=>'int', 'mode='=>'?string'], 'Redis::expiretime' => ['__benevolent', 'key'=>'string'], 'Redis::failover' => ['__benevolent', 'to='=>'?array', 'abort='=>'bool', 'timeout='=>'int'], 'Redis::fcall' => ['mixed', 'fn'=>'string', 'keys='=>'string[]', 'args='=>'array'], 'Redis::fcall_ro' => ['mixed', 'fn'=>'string', 'keys='=>'string[]', 'args='=>'array'], 'Redis::flushAll' => ['__benevolent', 'sync='=>'?bool'], 'Redis::flushDb' => ['__benevolent', 'sync='=>'?bool'], 'Redis::function' => ['__benevolent', 'operation'=>'string', '...args='=>'mixed'], 'Redis::geoadd' => ['__benevolent', 'key'=>'string', 'lng'=>'float', 'lat'=>'float', 'member'=>'string', '...other_triples_and_options='=>'mixed'], 'Redis::geodist' => ['__benevolent', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::geohash' => ['__benevolent|false>', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::geopos' => ['__benevolent|false>', 'key'=>'string', 'member'=>'string', '...other_members'=>'string'], 'Redis::georadius' => ['__benevolent>', 'key'=>'string', 'lng'=>'float', 'lat'=>'float', 'radius'=>'float', 'unit'=>'string', 'options='=>'array'], 'Redis::georadiusbymember' => ['__benevolent>', 'key'=>'string', 'lng'=>'float', 'lat'=>'float', 'radius'=>'float', 'unit'=>'string', 'options='=>'array'], 'Redis::georadiusbymember_ro' => ['__benevolent>', 'key'=>'string', 'lng'=>'float', 'lat'=>'float', 'radius'=>'float', 'unit'=>'string', 'options='=>'array'], 'Redis::geosearch' => ['__benevolent>', 'key'=>'string', 'position'=>'array|string', 'shape'=>'array|int|float', 'unit'=>'string', 'options='=>'array'], 'Redis::geosearchstore' => ['__benevolent|int|false>', 'dst'=>'string', 'src'=>'string', 'position'=>'array|string', 'shape'=>'array|int|float', 'unit'=>'string', 'options='=>'array'], 'Redis::get' => ['mixed', 'key'=>'string'], 'Redis::getAuth' => ['string|false|null'], 'Redis::getBit' => ['__benevolent', 'key'=>'string', 'idx'=>'int'], 'Redis::getEx' => ['__benevolent', 'key'=>'string', 'options'=>'?array{EX?:int,PX?:int,EXAT?:int,PXAT?:int,PERSIST?:bool}'], 'Redis::getDBNum' => ['int'], 'Redis::getDel' => ['__benevolent', 'key'=>'string'], 'Redis::getHost' => ['string'], 'Redis::getKeys' => ['array', 'pattern'=>'string'], 'Redis::getLastError' => ['?string'], 'Redis::getMode' => ['int'], 'Redis::getMultiple' => ['array', 'keys'=>'string[]'], 'Redis::getOption' => ['int', 'name'=>'int'], 'Redis::getPersistentID' => ['?string'], 'Redis::getPort' => ['int'], 'Redis::getRange' => ['__benevolent', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::getReadTimeout' => ['float'], 'Redis::getset' => ['__benevolent', 'key'=>'string', 'value'=>'mixed'], 'Redis::getTimeout' => ['float|false'], 'Redis::getTransferredBytes' => ['array'], 'Redis::hDel' => ['__benevolent', 'key'=>'string', 'field'=>'string', '...other_fields='=>'string'], 'Redis::hExists' => ['__benevolent', 'key'=>'string', 'field'=>'string'], 'Redis::hGet' => ['__benevolent', 'key'=>'string', 'member'=>'string'], 'Redis::hGetAll' => ['__benevolent', 'key'=>'string'], 'Redis::hIncrBy' => ['__benevolent', 'key'=>'string', 'field'=>'string', 'value'=>'int'], 'Redis::hIncrByFloat' => ['__benevolent', 'key'=>'string', 'field'=>'string', 'value'=>'float'], 'Redis::hKeys' => ['__benevolent', 'key'=>'string'], 'Redis::hLen' => ['__benevolent', 'key'=>'string'], 'Redis::hMget' => ['__benevolent|false>', 'key'=>'string', 'fields'=>'string[]'], 'Redis::hMset' => ['__benevolent', 'key'=>'string', 'fieldvals'=>'array'], 'Redis::hRandField' => ['__benevolent>', 'key'=>'string', 'options'=>'?array{COUNT?:int,WITHVALUES?:bool}'], 'Redis::hscan' => ['__benevolent|bool>', 'key'=>'string', '&iterator'=>'?int', 'pattern='=>'?string', 'count='=>'int'], 'Redis::hSet' => ['__benevolent', 'key'=>'string', 'member'=>'string', 'value'=>'mixed'], 'Redis::hSetNx' => ['__benevolent', 'key'=>'string', 'field'=>'string', 'value'=>'string'], 'Redis::hStrLen' => ['__benevolent', 'key'=>'string', 'field'=>'string'], 'Redis::hVals' => ['__benevolent', 'key'=>'string'], 'Redis::incr' => ['__benevolent', 'key'=>'string', 'by='=>'int'], 'Redis::incrBy' => ['__benevolent', 'key'=>'string', 'value'=>'int'], 'Redis::incrByFloat' => ['__benevolent', 'key'=>'string', 'value'=>'float'], 'Redis::info' => ['__benevolent|false>', '...sections='=>'string'], 'Redis::isConnected' => ['bool'], 'Redis::keys' => ['__benevolent|false>', 'pattern'=>'string'], 'Redis::lastSave' => ['int'], 'Redis::lcs' => ['__benevolent', 'key1'=>'string', 'key2'=>'string', 'options'=>'?array{MINMATCHLEN?:int,WITHMATCHLEN?:bool,LEN?:bool,IDX?:bool}'], 'Redis::lGet' => ['', 'key'=>'string', 'index'=>'int'], 'Redis::lGetRange' => ['', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::lindex' => ['null|string|false', 'key'=>'string', 'index'=>'int'], 'Redis::lInsert' => ['__benevolent', 'key'=>'string', 'pos'=>'int', 'pivot'=>'mixed', 'value'=>'mixed'], 'Redis::listTrim' => ['', 'key'=>'string', 'start'=>'int', 'stop'=>'int'], 'Redis::lLen' => ['__benevolent', 'key'=>'string'], 'Redis::lMove' => ['__benevolent', 'src'=>'string', 'dst'=>'string', 'wherefrom'=>'string', 'whereto'=>'string'], 'Redis::lmpop' => ['__benevolent|null|false>', 'keys'=>'string[]', 'from'=>'string', 'count='=>'int'], 'Redis::lPop' => ['__benevolent', 'key'=>'string', 'count='=>'int'], 'Redis::lPos' => ['__benevolent', 'key'=>'string', 'value'=>'mixed', 'options'=>'?array{COUNT?:int,RANK?:int,MAXLEN?:int}'], 'Redis::lPush' => ['__benevolent', 'key'=>'string', '...elements='=>'mixed'], 'Redis::lPushx' => ['__benevolent', 'key'=>'string', 'value'=>'mixed'], 'Redis::lrange' => ['__benevolent', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::lrem' => ['__benevolent', 'key'=>'string', 'value'=>'mixed', 'count='=>'int'], 'Redis::lSet' => ['__benevolent', 'key'=>'string', 'index'=>'int', 'value'=>'mixed'], 'Redis::lSize' => ['', 'key'=>'string'], 'Redis::ltrim' => ['__benevolent', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::mget' => ['__benevolent>', 'keys'=>'string[]'], 'Redis::migrate' => ['__benevolent', 'host'=>'string', 'port'=>'int', 'key'=>'string|string[]', 'dstdb'=>'int', 'timeout'=>'int', 'copy='=>'bool', 'replace='=>'bool', 'credentials='=>'mixed'], 'Redis::move' => ['__benevolent', 'key'=>'string', 'index'=>'int'], 'Redis::mset' => ['__benevolent', 'key_values'=>'array'], 'Redis::msetnx' => ['__benevolent', 'key_values'=>'array'], 'Redis::multi' => ['__benevolent', 'value='=>'int'], 'Redis::object' => ['__benevolent', 'subcommand'=>'string', 'key'=>'string'], 'Redis::open' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'float', 'persistent_id='=>'?string', 'retry_interval='=>'int', 'read_timeout='=>'float', 'context='=>'?array{auth?:list{string|null|false,string}|list{string},stream?:array}'], 'Redis::pconnect' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'float', 'persistent_id='=>'?string', 'retry_interval='=>'int', 'read_timeout='=>'float', 'context='=>'?array{auth?:list{string|null|false,string}|list{string},stream?:array}'], 'Redis::persist' => ['__benevolent', 'key'=>'string'], 'Redis::pexpire' => ['bool', 'key'=>'string', 'timeout'=>'int', 'mode='=>'?string'], 'Redis::pexpireAt' => ['__benevolent', 'key'=>'string', 'timestamp'=>'int', 'mode='=>'?string'], 'Redis::pexpiretime' => ['__benevolent', 'key'=>'string'], 'Redis::pfadd' => ['__benevolent', 'key'=>'string', 'elements'=>'array'], 'Redis::pfcount' => ['__benevolent', 'key_or_keys'=>'string[]|string'], 'Redis::pfmerge' => ['__benevolent', 'dst'=>'string', 'srckeys'=>'string[]'], 'Redis::ping' => ['__benevolent', 'message='=>'?string'], 'Redis::pipeline' => ['__benevolent'], 'Redis::popen' => ['bool', 'host'=>'string', 'port='=>'int', 'timeout='=>'float', 'persistent_id='=>'?string', 'retry_interval='=>'int', 'read_timeout='=>'float', 'context='=>'?array{auth?:list{string|null|false,string}|list{string},stream?:array}'], 'Redis::psetex' => ['__benevolent', 'key'=>'string', 'expire'=>'int', 'value'=>'mixed'], 'Redis::psubscribe' => ['bool', 'patterns'=>'string[]', 'cb'=>'callable'], 'Redis::pttl' => ['__benevolent', 'key'=>'string'], 'Redis::publish' => ['__benevolent', 'channel'=>'string', 'message'=>'string'], 'Redis::pubsub' => ['array|int', 'command'=>'string', 'arg'=>'array|string'], 'Redis::punsubscribe' => ['__benevolent', 'patterns='=>'string[]'], 'Redis::randomKey' => ['__benevolent'], 'Redis::rawcommand' => ['mixed', 'command'=>'string', '...args='=>'mixed'], 'Redis::rename' => ['__benevolent', 'old_name'=>'string', 'new_name'=>'string'], 'Redis::renameKey' => ['bool', 'srckey'=>'string', 'dstkey'=>'string'], 'Redis::renameNx' => ['__benevolent', 'old_name'=>'string', 'new_name'=>'string'], 'Redis::reset' => ['__benevolent'], 'Redis::resetStat' => ['bool'], 'Redis::restore' => ['__benevolent', 'key'=>'string', 'ttl'=>'int', 'value'=>'string', 'options='=>'?array{ABSTTL?:bool,REPLACE?:bool,IDLETIME?:int,FREQ?:int}'], 'Redis::role' => ['mixed'], 'Redis::rPop' => ['__benevolent|string|bool>', 'key'=>'string', 'count='=>'int'], 'Redis::rpoplpush' => ['__benevolent', 'srckey'=>'string', 'dstkey'=>'string'], 'Redis::rPush' => ['__benevolent', 'key'=>'string', '...elements='=>'mixed'], 'Redis::rPushx' => ['__benevolent', 'key'=>'string', 'value'=>'mixed'], 'Redis::sAdd' => ['__benevolent', 'key'=>'string', 'value'=>'mixed', '...other_values='=>'string'], 'Redis::sAddArray' => ['int', 'key'=>'string', 'values'=>'array'], 'Redis::save' => ['__benevolent'], 'Redis::scan' => ['array|false', '&iterator'=>'?int', 'pattern='=>'?string', 'count='=>'?int', 'type='=>'?string'], 'Redis::scard' => ['__benevolent', 'key'=>'string'], 'Redis::sContains' => ['', 'key'=>'string', 'value'=>'string'], 'Redis::script' => ['mixed', 'command'=>'string', '...args='=>'mixed'], 'Redis::sDiff' => ['__benevolent|false>', 'key'=>'string', '...other_keys='=>'string'], 'Redis::sDiffStore' => ['__benevolent', 'dst'=>'string', 'key'=>'string', '...other_keys='=>'string'], 'Redis::select' => ['__benevolent', 'db'=>'int'], 'Redis::set' => ['__benevolent', 'key'=>'string', 'value'=>'mixed', 'options='=>'array'], 'Redis::set\'1' => ['bool', 'key'=>'string', 'value'=>'mixed', 'timeout='=>'int'], 'Redis::setBit' => ['__benevolent', 'key'=>'string', 'idx'=>'int', 'value'=>'bool'], 'Redis::setex' => ['__benevolent', 'key'=>'string', 'expire'=>'int', 'value'=>'mixed'], 'Redis::setnx' => ['__benevolent', 'key'=>'string', 'value'=>'mixed'], 'Redis::setOption' => ['bool', 'option'=>'int', 'value'=>'mixed'], 'Redis::setRange' => ['__benevolent', 'key'=>'string', 'index'=>'int', 'value'=>'string'], 'Redis::setTimeout' => ['bool', 'key'=>'string', 'ttl'=>'int'], 'Redis::sGetMembers' => ['array', 'key'=>'string'], 'Redis::sInter' => ['__benevolent|false>', 'key'=>'string', '...other_keys='=>'string'], 'Redis::sintercard' => ['__benevolent', 'keys'=>'string[]', 'limit='=>'int'], 'Redis::sInterStore' => ['__benevolent', 'key'=>'string[]|string', '...other_keys='=>'string'], 'Redis::sismember' => ['__benevolent', 'key'=>'string', 'value'=>'mixed'], 'Redis::slave' => ['bool', 'host'=>'string', 'port'=>'int'], 'Redis::slave\'1' => ['bool', 'host'=>'string', 'port'=>'int'], 'Redis::slaveof' => ['__benevolent', 'host='=>'?string', 'port='=>'int'], 'Redis::slowlog' => ['mixed', 'operation'=>'string', 'length='=>'int'], 'Redis::sMembers' => ['__benevolent|false>', 'key'=>'string'], 'Redis::sMisMember' => ['__benevolent', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::sMove' => ['__benevolent', 'src'=>'string', 'dst'=>'string', 'value'=>'mixed'], 'Redis::sort' => ['array|int', 'key'=>'string', 'options='=>'?array{SORT?:string,ALPHA?:bool,LIMIT?:array{0:int,1:int},BY?:string,GET?:string}'], 'Redis::sort_ro' => ['array|int', 'key'=>'string', 'options='=>'?array{SORT?:string,ALPHA?:bool,LIMIT?:array{0:int,1:int},BY?:string,GET?:string}'], 'Redis::sPop' => ['__benevolent', 'key'=>'string', 'count='=>'int'], 'Redis::sRandMember' => ['__benevolent', 'key'=>'string', 'count='=>'int'], 'Redis::srem' => ['__benevolent', 'key'=>'string', 'value'=>'mixed', '...other_values='=>'mixed'], 'Redis::sRemove' => ['int', 'key'=>'string', 'member1'=>'string', '...other_members='=>'string'], 'Redis::sscan' => ['__benevolent', 'key'=>'string', '&iterator'=>'?int', 'pattern='=>'?string', 'count='=>'int'], 'Redis::ssubscribe' => ['bool', 'channels'=>'string[]', 'cb'=>'callable'], 'Redis::strlen' => ['__benevolent', 'key'=>'string'], 'Redis::subscribe' => ['bool', 'channels'=>'string[]', 'cb'=>'callable'], 'Redis::substr' => ['', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::unlink\'1' => ['int', 'key'=>'string[]'], 'Redis::sUnion' => ['__benevolent|false>', 'key'=>'string', '...other_keys='=>'string'], 'Redis::sUnionStore' => ['__benevolent', 'dst'=>'string', 'key'=>'string', '...other_keys='=>'string'], 'Redis::sunsubscribe' => ['__benevolent', 'channels'=>'string[]'], 'Redis::swapdb' => ['__benevolent', 'src'=>'int', 'dst'=>'int'], 'Redis::time' => ['__benevolent'], 'Redis::ttl' => ['__benevolent', 'key'=>'string'], 'Redis::type' => ['__benevolent', 'key'=>'string'], 'Redis::unlink' => ['__benevolent', 'key'=>'string[]|string', '...other_keys'=>'string'], 'Redis::unsubscribe' => ['__benevolent', 'channels'=>'string[]'], 'Redis::unwatch' => ['__benevolent'], 'Redis::wait' => ['int|false', 'numreplicas'=>'int', 'timeout'=>'int'], 'Redis::watch' => ['__benevolent', 'key'=>'string[]|string', '...other_keys='=>'string'], 'Redis::xack' => ['int|false', 'key'=>'string', 'group'=>'string', 'ids'=>'array'], 'Redis::xadd' => ['__benevolent', 'key'=>'string', 'id'=>'string', 'values'=>'array', 'maxlen='=>'int', 'approx='=>'bool', 'nomkstream='=>'bool'], 'Redis::xclaim' => ['__benevolent', 'key'=>'string', 'group'=>'string', 'consumer'=>'string', 'min_idle'=>'int', 'ids'=>'array', 'options='=>'array'], 'Redis::xdel' => ['__benevolent', 'key'=>'string', 'ids'=>'array'], 'Redis::xgroup' => ['mixed', 'operation'=>'string', 'key='=>'?string', 'group='=>'?string', 'id_or_consumer='=>'?string', 'mkstream='=>'bool', 'entries_read='=>'int'], 'Redis::xinfo' => ['mixed', 'operation'=>'string', 'arg1='=>'?string', 'arg2='=>'?string', 'count='=>'int'], 'Redis::xlen' => ['__benevolent', 'key'=>'string'], 'Redis::xpending' => ['__benevolent', 'key'=>'string', 'group'=>'string', 'start='=>'?string', 'end='=>'?string', 'count='=>'int', 'consumer='=>'?string'], 'Redis::xrange' => ['__benevolent', 'key'=>'string', 'start'=>'string', 'end'=>'string', 'count='=>'int'], 'Redis::xread' => ['__benevolent', 'streams'=>'array', 'count='=>'int', 'block='=>'int'], 'Redis::xreadgroup' => ['__benevolent', 'group'=>'string', 'consumer'=>'string', 'streams'=>'array', 'count='=>'int', 'block='=>'int'], 'Redis::xrevrange' => ['__benevolent', 'key'=>'string', 'end'=>'string', 'start'=>'string', 'count='=>'int'], 'Redis::xtrim' => ['__benevolent', 'key'=>'string', 'threshold'=>'string', 'approx='=>'bool', 'minid='=>'bool', 'limit='=>'int'], 'Redis::zAdd' => ['__benevolent', 'key'=>'string', 'score_or_options'=>'array|float', '...more_scores_and_mems='=>'mixed'], 'Redis::zAdd\'1' => ['int', 'key'=>'string', 'options'=>'array', 'score1'=>'float', 'value1'=>'string', 'score2='=>'float', 'value2='=>'string', 'scoreN='=>'float', 'valueN='=>'string'], 'Redis::zCard' => ['__benevolent', 'key'=>'string'], 'Redis::zCount' => ['__benevolent', 'key'=>'string', 'start'=>'string', 'end'=>'string'], 'Redis::zDelete' => ['int', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::zDeleteRangeByRank' => ['', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::zDeleteRangeByScore' => ['', 'key'=>'string', 'start'=>'float', 'end'=>'float'], 'Redis::zIncrBy' => ['__benevolent', 'key'=>'string', 'value'=>'float', 'member'=>'mixed'], 'Redis::zInter' => ['__benevolent', 'keys'=>'string[]', 'weights='=>'?array', 'options='=>'?array'], 'Redis::zmpop' => ['__benevolent', 'keys'=>'string[]', 'from'=>'string', 'count='=>'int'], 'Redis::zRange' => ['__benevolent', 'key'=>'string', 'start'=>'string|int', 'end'=>'string|int', 'options='=>'array|bool|null'], 'Redis::zRangeByLex' => ['__benevolent', 'key'=>'string', 'min'=>'string', 'max'=>'string', 'offset='=>'int', 'limit='=>'int'], 'Redis::zRangeByScore' => ['__benevolent', 'key'=>'string', 'start'=>'string', 'end'=>'string', 'options='=>'array'], 'Redis::zRank' => ['__benevolent', 'key'=>'string', 'member'=>'mixed'], 'Redis::zRem' => ['__benevolent', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::zRemove' => ['int', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::zRemRangeByRank' => ['__benevolent', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::zRemRangeByScore' => ['__benevolent', 'key'=>'string', 'start'=>'string', 'end'=>'string'], 'Redis::zRevRange' => ['__benevolent', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'scores='=>'bool|array{withscores:bool}|null'], 'Redis::zRevRangeByLex' => ['__benevolent', 'key'=>'string', 'max'=>'string', 'min'=>'string', 'offset='=>'int', 'limit='=>'int'], 'Redis::zRevRangeByScore' => ['__benevolent', 'key'=>'string', 'max'=>'string', 'min'=>'string', 'options='=>'array|bool'], 'Redis::zRevRank' => ['__benevolent', 'key'=>'string', 'member'=>'mixed'], 'Redis::zscan' => ['__benevolent', 'key'=>'string', '&iterator'=>'?int', 'pattern='=>'?string', 'count='=>'int'], 'Redis::zScore' => ['__benevolent', 'key'=>'string', 'member'=>'mixed'], 'Redis::zSize' => ['', 'key'=>'string'], 'Redis::zUnion' => ['__benevolent', 'keys'=>'string[]', 'weights'=>'?array', 'options='=>'?array'], 'RedisArray::__construct' => ['void', 'name'=>'string'], 'RedisArray::__construct\'1' => ['void', 'hosts'=>'array', 'opts='=>'array'], 'RedisArray::_function' => ['string'], 'RedisArray::_hosts' => ['array'], 'RedisArray::_rehash' => ['', 'callable='=>'callable'], 'RedisArray::_target' => ['string', 'key'=>'string'], 'RedisCluster::__construct' => ['void', 'name'=>'string|null', 'seeds='=>'string[]|null', 'timeout='=>'int|float', 'read_timeout='=>'int|float', 'persistent='=>'bool', 'auth='=>'mixed', 'context='=>'array|null'], 'RedisCluster::_masters' => ['array'], 'RedisCluster::_prefix' => ['string', 'value'=>'mixed'], 'RedisCluster::_serialize' => ['mixed', 'value'=>'mixed'], 'RedisCluster::_unserialize' => ['mixed', 'value'=>'string'], 'RedisCluster::append' => ['int', 'key'=>'string', 'value'=>'string'], 'RedisCluster::bgrewriteaof' => ['bool', 'nodeParams'=>'string'], 'RedisCluster::bgsave' => ['bool', 'nodeParams'=>'string'], 'RedisCluster::bitCount' => ['int', 'key'=>'string'], 'RedisCluster::bitOp' => ['int', 'operation'=>'string', 'retKey'=>'string', 'key1'=>'string', 'key2'=>'string', 'key3='=>'string'], 'RedisCluster::bitpos' => ['int', 'key'=>'string', 'bit'=>'int', 'start='=>'int', 'end='=>'int'], 'RedisCluster::blPop' => ['array', 'keys'=>'array', 'timeout'=>'int'], 'RedisCluster::brPop' => ['array', 'keys'=>'array', 'timeout'=>'int'], 'RedisCluster::brpoplpush' => ['string', 'srcKey'=>'string', 'dstKey'=>'string', 'timeout'=>'int'], 'RedisCluster::clearLastError' => ['bool'], 'RedisCluster::client' => ['', 'nodeParams'=>'string', 'subCmd'=>'', 'args'=>''], 'RedisCluster::close' => [''], 'RedisCluster::cluster' => ['mixed', 'nodeParams'=>'string', 'command'=>'string', 'arguments'=>'mixed'], 'RedisCluster::command' => ['mixed'], 'RedisCluster::config' => ['array', 'nodeParams'=>'string', 'operation'=>'string', 'key'=>'string', 'value'=>'string'], 'RedisCluster::dbSize' => ['int', 'nodeParams'=>'string'], 'RedisCluster::decr' => ['int', 'key'=>'string'], 'RedisCluster::decrBy' => ['int', 'key'=>'string', 'value'=>'int'], 'RedisCluster::del' => ['int', 'key1'=>'int|string', 'key2='=>'int|string', 'key3='=>'int|string'], 'RedisCluster::discard' => [''], 'RedisCluster::dump' => ['string', 'key'=>'string'], 'RedisCluster::echo' => ['mixed', 'nodeParams'=>'string', 'msg'=>'string'], 'RedisCluster::eval' => ['mixed', 'script'=>'', 'args='=>'', 'numKeys='=>''], 'RedisCluster::evalSha' => ['mixed', 'scriptSha'=>'string', 'args='=>'array', 'numKeys='=>'int'], 'RedisCluster::exec' => ['array|void'], 'RedisCluster::exists' => ['bool', 'key'=>'string'], 'RedisCluster::expire' => ['bool', 'key'=>'string', 'ttl'=>'int'], 'RedisCluster::expireAt' => ['bool', 'key'=>'string', 'timestamp'=>'int'], 'RedisCluster::flushAll' => ['bool', 'nodeParams'=>'string'], 'RedisCluster::flushDB' => ['bool', 'nodeParams'=>'string'], 'RedisCluster::geoAdd' => ['', 'key'=>'string', 'longitude'=>'float', 'latitude'=>'float', 'member'=>'string'], 'RedisCluster::geoDist' => ['', 'key'=>'string', 'member1'=>'string', 'member2'=>'string', 'unit='=>'string'], 'RedisCluster::geohash' => ['', 'key'=>'', 'member1'=>'', 'member2='=>'mixed', 'memberN='=>'mixed'], 'RedisCluster::geopos' => ['', 'key'=>'', 'member1'=>'', 'member2='=>'mixed', 'memberN='=>'mixed'], 'RedisCluster::geoRadius' => ['', 'key'=>'string', 'longitude'=>'float', 'latitude'=>'float', 'radius'=>'float', 'radiusUnit'=>'string', 'options'=>'array'], 'RedisCluster::geoRadiusByMember' => ['', 'key'=>'string', 'member'=>'string', 'radius'=>'float', 'radiusUnit'=>'string', 'options'=>'array'], 'RedisCluster::get' => ['bool|string', 'key'=>'string'], 'RedisCluster::getBit' => ['int', 'key'=>'string', 'offset'=>'int'], 'RedisCluster::getLastError' => ['string'], 'RedisCluster::getMode' => ['int'], 'RedisCluster::getOption' => ['int', 'name'=>'int'], 'RedisCluster::getRange' => ['string', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'RedisCluster::getSet' => ['string', 'key'=>'string', 'value'=>'string'], 'RedisCluster::hDel' => ['int', 'key'=>'string', 'hashKey1'=>'string', 'hashKey2='=>'string', 'hashKeyN='=>'string'], 'RedisCluster::hExists' => ['bool', 'key'=>'string', 'hashKey'=>'string'], 'RedisCluster::hGet' => ['string', 'key'=>'string', 'hashKey'=>'string'], 'RedisCluster::hGetAll' => ['array', 'key'=>'string'], 'RedisCluster::hIncrBy' => ['int', 'key'=>'string', 'hashKey'=>'string', 'value'=>'int'], 'RedisCluster::hIncrByFloat' => ['float', 'key'=>'string', 'field'=>'string', 'increment'=>'float'], 'RedisCluster::hKeys' => ['array', 'key'=>'string'], 'RedisCluster::hLen' => ['int', 'key'=>'string'], 'RedisCluster::hMGet' => ['array', 'key'=>'string', 'hashKeys'=>'array'], 'RedisCluster::hMSet' => ['bool', 'key'=>'string', 'hashKeys'=>'array'], 'RedisCluster::hScan' => ['array', 'key'=>'string', '&iterator'=>'int', 'pattern='=>'string', 'count='=>'int'], 'RedisCluster::hSet' => ['int', 'key'=>'string', 'hashKey'=>'string', 'value'=>'string'], 'RedisCluster::hSetNx' => ['bool', 'key'=>'string', 'hashKey'=>'string', 'value'=>'string'], 'RedisCluster::hVals' => ['array', 'key'=>'string'], 'RedisCluster::incr' => ['int', 'key'=>'string'], 'RedisCluster::incrBy' => ['int', 'key'=>'string', 'value'=>'int'], 'RedisCluster::incrByFloat' => ['float', 'key'=>'string', 'increment'=>'float'], 'RedisCluster::info' => ['string', 'option='=>'string'], 'RedisCluster::keys' => ['array', 'pattern'=>'string'], 'RedisCluster::lastSave' => ['int', 'nodeParams'=>'string'], 'RedisCluster::lGet' => ['', 'key'=>'string', 'index'=>'int'], 'RedisCluster::lIndex' => ['string', 'key'=>'string', 'index'=>'int'], 'RedisCluster::lInsert' => ['int', 'key'=>'string', 'position'=>'int', 'pivot'=>'string', 'value'=>'string'], 'RedisCluster::lLen' => ['int', 'key'=>'string'], 'RedisCluster::lPop' => ['string', 'key'=>'string'], 'RedisCluster::lPush' => ['int', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string'], 'RedisCluster::lPushx' => ['int', 'key'=>'string', 'value'=>'string'], 'RedisCluster::lRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'RedisCluster::lRem' => ['int', 'key'=>'string', 'value'=>'string', 'count'=>'int'], 'RedisCluster::lSet' => ['bool', 'key'=>'string', 'index'=>'int', 'value'=>'string'], 'RedisCluster::lTrim' => ['array', 'key'=>'string', 'start'=>'int', 'stop'=>'int'], 'RedisCluster::mget' => ['array', 'array'=>'array'], 'RedisCluster::mset' => ['bool', 'array'=>'array'], 'RedisCluster::msetnx' => ['int', 'array'=>'array'], 'RedisCluster::multi' => ['Redis', 'mode='=>'int'], 'RedisCluster::object' => ['string', 'string='=>'string', 'key='=>'string'], 'RedisCluster::persist' => ['bool', 'key'=>'string'], 'RedisCluster::pExpire' => ['bool', 'key'=>'string', 'ttl'=>'int'], 'RedisCluster::pExpireAt' => ['bool', 'key'=>'string', 'timestamp'=>'int'], 'RedisCluster::pfAdd' => ['bool', 'key'=>'string', 'elements'=>'array'], 'RedisCluster::pfCount' => ['int', 'key'=>'string'], 'RedisCluster::pfMerge' => ['bool', 'destKey'=>'string', 'sourceKeys'=>'array'], 'RedisCluster::ping' => ['string', 'nodeParams'=>'string'], 'RedisCluster::psetex' => ['bool', 'key'=>'string', 'ttl'=>'int', 'value'=>'string'], 'RedisCluster::psubscribe' => ['mixed', 'patterns'=>'array', 'callback'=>'string'], 'RedisCluster::pttl' => ['int', 'key'=>'string'], 'RedisCluster::publish' => ['int', 'channel'=>'string', 'message'=>'string'], 'RedisCluster::pubsub' => ['array', 'nodeParams'=>'string', 'keyword'=>'string', '...argument='=>'string'], 'RedisCluster::punSubscribe' => ['', 'channels'=>'', 'callback'=>''], 'RedisCluster::randomKey' => ['string', 'nodeParams'=>'string'], 'RedisCluster::rawCommand' => ['mixed', 'nodeParams'=>'string', 'command'=>'string', 'arguments'=>'mixed'], 'RedisCluster::rename' => ['bool', 'srcKey'=>'string', 'dstKey'=>'string'], 'RedisCluster::renameNx' => ['bool', 'srcKey'=>'string', 'dstKey'=>'string'], 'RedisCluster::restore' => ['bool', 'key'=>'string', 'ttl'=>'int', 'value'=>'string'], 'RedisCluster::role' => ['array', 'nodeParams'=>'string'], 'RedisCluster::rPop' => ['string', 'key'=>'string'], 'RedisCluster::rpoplpush' => ['string', 'srcKey'=>'string', 'dstKey'=>'string'], 'RedisCluster::rPush' => ['int', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string'], 'RedisCluster::rPushx' => ['int', 'key'=>'string', 'value'=>'string'], 'RedisCluster::sAdd' => ['int', 'key'=>'string', 'value1'=>'string', 'value2='=>'string', 'valueN='=>'string'], 'RedisCluster::sAddArray' => ['int', 'key'=>'string', 'valueArray'=>'array'], 'RedisCluster::save' => ['bool', 'nodeParams'=>'string'], 'RedisCluster::scan' => ['array', '&iterator'=>'int', 'pattern='=>'string', 'count='=>'int'], 'RedisCluster::sCard' => ['int', 'key'=>'string'], 'RedisCluster::script' => ['mixed', 'nodeParams'=>'string', 'command'=>'string', 'script'=>'string'], 'RedisCluster::sDiff' => ['list', 'key1'=>'string', 'key2'=>'string', '...other_keys='=>'string'], 'RedisCluster::sDiffStore' => ['int', 'dstKey'=>'string', 'key1'=>'string', '...other_keys='=>'string'], 'RedisCluster::set' => ['bool', 'key'=>'string', 'value'=>'string', 'timeout='=>'array|int'], 'RedisCluster::setBit' => ['int', 'key'=>'string', 'offset'=>'int', 'value'=>'bool|int'], 'RedisCluster::setex' => ['bool', 'key'=>'string', 'ttl'=>'int', 'value'=>'string'], 'RedisCluster::setnx' => ['bool', 'key'=>'string', 'value'=>'string'], 'RedisCluster::setOption' => ['bool', 'name'=>'int', 'value'=>'mixed'], 'RedisCluster::setRange' => ['string', 'key'=>'string', 'offset'=>'int', 'value'=>'string'], 'RedisCluster::sInter' => ['list', 'key'=>'string', '...other_keys='=>'string'], 'RedisCluster::sInterStore' => ['int', 'dstKey'=>'string', 'key'=>'string', '...other_keys='=>'string'], 'RedisCluster::sIsMember' => ['bool', 'key'=>'string', 'value'=>'string'], 'RedisCluster::slowLog' => ['', 'nodeParams'=>'string', 'command'=>'string', 'argument'=>'mixed', '...other_arguments='=>'mixed'], 'RedisCluster::sMembers' => ['list', 'key'=>'string'], 'RedisCluster::sMove' => ['bool', 'srcKey'=>'string', 'dstKey'=>'string', 'member'=>'string'], 'RedisCluster::sort' => ['array', 'key'=>'string', 'option='=>'array'], 'RedisCluster::sPop' => ['string', 'key'=>'string'], 'RedisCluster::sRandMember' => ['array|string', 'key'=>'string', 'count='=>'int'], 'RedisCluster::sRem' => ['int', 'key'=>'string', 'member1'=>'string', '...other_members='=>'string'], 'RedisCluster::sScan' => ['array', 'key'=>'string', '&iterator'=>'int', 'pattern='=>'null', 'count='=>'int'], 'RedisCluster::strlen' => ['0|positive-int', 'key'=>'string'], 'RedisCluster::subscribe' => ['mixed', 'channels'=>'array', 'callback'=>'string'], 'RedisCluster::sUnion' => ['array', 'key1'=>'string', '...other_keys='=>'string'], 'RedisCluster::sUnionStore' => ['int', 'dstKey'=>'string', 'key1'=>'string', '...other_keys='=>'string'], 'RedisCluster::time' => ['array', 'nodeParams'=>'string'], 'RedisCluster::ttl' => ['int', 'key'=>'string'], 'RedisCluster::type' => ['int', 'key'=>'string'], 'RedisCluster::unlink' => ['int', 'key'=>'string', '...other_keys='=>'string'], 'RedisCluster::unSubscribe' => ['', 'channels'=>'', '...other_channels='=>''], 'RedisCluster::unwatch' => [''], 'RedisCluster::watch' => ['void', 'key'=>'string', '...other_keys='=>'string'], 'RedisCluster::xack' => ['', 'str_key'=>'string', 'str_group'=>'string', 'arr_ids'=>'array'], 'RedisCluster::xadd' => ['', 'str_key'=>'string', 'str_id'=>'string', 'arr_fields'=>'array', 'i_maxlen='=>'', 'boo_approximate='=>''], 'RedisCluster::xclaim' => ['', 'str_key'=>'string', 'str_group'=>'string', 'str_consumer'=>'string', 'i_min_idle'=>'', 'arr_ids'=>'array', 'arr_opts='=>'array'], 'RedisCluster::xdel' => ['', 'str_key'=>'string', 'arr_ids'=>'array'], 'RedisCluster::xgroup' => ['', 'str_operation'=>'string', 'str_key='=>'string', 'str_arg1='=>'', 'str_arg2='=>'', 'str_arg3='=>''], 'RedisCluster::xinfo' => ['', 'str_cmd'=>'string', 'str_key='=>'string', 'str_group='=>'string'], 'RedisCluster::xlen' => ['', 'key'=>''], 'RedisCluster::xpending' => ['', 'str_key'=>'string', 'str_group'=>'string', 'str_start='=>'', 'str_end='=>'', 'i_count='=>'', 'str_consumer='=>'string'], 'RedisCluster::xrange' => ['', 'str_key'=>'string', 'str_start'=>'', 'str_end'=>'', 'i_count='=>''], 'RedisCluster::xread' => ['', 'arr_streams'=>'array', 'i_count='=>'', 'i_block='=>''], 'RedisCluster::xreadgroup' => ['', 'str_group'=>'string', 'str_consumer'=>'string', 'arr_streams'=>'array', 'i_count='=>'', 'i_block='=>''], 'RedisCluster::xrevrange' => ['', 'str_key'=>'string', 'str_start'=>'', 'str_end'=>'', 'i_count='=>''], 'RedisCluster::xtrim' => ['', 'str_key'=>'string', 'i_maxlen'=>'', 'boo_approximate='=>''], 'RedisCluster::zAdd' => ['int', 'key'=>'string', 'score1'=>'float', 'value1'=>'string', 'score2='=>'float', 'value2='=>'string', 'scoreN='=>'float', 'valueN='=>'string'], 'RedisCluster::zCard' => ['int', 'key'=>'string'], 'RedisCluster::zCount' => ['int', 'key'=>'string', 'start'=>'string', 'end'=>'string'], 'RedisCluster::zIncrBy' => ['float', 'key'=>'string', 'value'=>'float', 'member'=>'string'], 'RedisCluster::zInterStore' => ['int', 'Output'=>'string', 'ZSetKeys'=>'array', 'Weights='=>'?array', 'aggregateFunction='=>'string'], 'RedisCluster::zLexCount' => ['int', 'key'=>'string', 'min'=>'int', 'max'=>'int'], 'RedisCluster::zRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'withscores='=>'bool'], 'RedisCluster::zRangeByLex' => ['array', 'key'=>'string', 'min'=>'int', 'max'=>'int', 'offset='=>'int', 'limit='=>'int'], 'RedisCluster::zRangeByScore' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'options='=>'array'], 'RedisCluster::zRank' => ['int', 'key'=>'string', 'member'=>'string'], 'RedisCluster::zRem' => ['int', 'key'=>'string', 'member1'=>'string', '...other_members='=>'string'], 'RedisCluster::zRemRangeByLex' => ['array', 'key'=>'string', 'min'=>'int', 'max'=>'int'], 'RedisCluster::zRemRangeByRank' => ['int', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'RedisCluster::zRemRangeByScore' => ['int', 'key'=>'string', 'start'=>'float|string', 'end'=>'float|string'], 'RedisCluster::zRevRange' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'withscore='=>'bool'], 'RedisCluster::zRevRangeByLex' => ['array', 'key'=>'string', 'min'=>'int', 'max'=>'int', 'offset='=>'int', 'limit='=>'int'], 'RedisCluster::zRevRangeByScore' => ['array', 'key'=>'string', 'start'=>'int', 'end'=>'int', 'options='=>'array'], 'RedisCluster::zRevRank' => ['int', 'key'=>'string', 'member'=>'string'], 'RedisCluster::zScan' => ['array', 'key'=>'string', '&iterator'=>'int', 'pattern='=>'string', 'count='=>'int'], 'RedisCluster::zScore' => ['float', 'key'=>'string', 'member'=>'string'], 'RedisCluster::zUnionStore' => ['int', 'Output'=>'string', 'ZSetKeys'=>'array', 'Weights='=>'?array', 'aggregateFunction='=>'string'], 'Reflection::export' => ['string|null', 'r'=>'reflector', 'return='=>'bool'], 'Reflection::getModifierNames' => ['array', 'modifiers'=>'int'], 'ReflectionClass::__clone' => ['void'], 'ReflectionClass::__construct' => ['void', 'argument'=>'object|string'], 'ReflectionClass::__toString' => ['string'], 'ReflectionClass::export' => ['string|null', 'argument'=>'string|object', 'return='=>'bool'], 'ReflectionClass::getConstant' => ['mixed', 'name'=>'string'], 'ReflectionClass::getConstants' => ['array'], 'ReflectionClass::getConstructor' => ['ReflectionMethod|null'], 'ReflectionClass::getDefaultProperties' => ['array'], 'ReflectionClass::getDocComment' => ['string|false'], 'ReflectionClass::getEndLine' => ['positive-int|false'], 'ReflectionClass::getExtension' => ['ReflectionExtension|null'], 'ReflectionClass::getExtensionName' => ['string|false'], 'ReflectionClass::getFileName' => ['non-empty-string|false'], 'ReflectionClass::getInterfaceNames' => ['list'], 'ReflectionClass::getInterfaces' => ['array'], 'ReflectionClass::getMethod' => ['ReflectionMethod', 'name'=>'string'], 'ReflectionClass::getMethods' => ['list', 'filter='=>'int'], 'ReflectionClass::getModifiers' => ['int'], 'ReflectionClass::getName' => ['class-string'], 'ReflectionClass::getNamespaceName' => ['string'], 'ReflectionClass::getParentClass' => ['ReflectionClass|false'], 'ReflectionClass::getProperties' => ['list', 'filter='=>'int'], 'ReflectionClass::getProperty' => ['ReflectionProperty', 'name'=>'string'], 'ReflectionClass::getReflectionConstant' => ['ReflectionClassConstant|false', 'name'=>'string'], 'ReflectionClass::getReflectionConstants' => ['list'], 'ReflectionClass::getShortName' => ['string'], 'ReflectionClass::getStartLine' => ['positive-int|false'], 'ReflectionClass::getStaticProperties' => ['array'], 'ReflectionClass::getStaticPropertyValue' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'ReflectionClass::getTraitAliases' => ['array'], 'ReflectionClass::getTraitNames' => ['list'], 'ReflectionClass::getTraits' => ['array'], 'ReflectionClass::hasConstant' => ['bool', 'name'=>'string'], 'ReflectionClass::hasMethod' => ['bool', 'name'=>'string'], 'ReflectionClass::hasProperty' => ['bool', 'name'=>'string'], 'ReflectionClass::implementsInterface' => ['bool', 'interface_name'=>'string|ReflectionClass'], 'ReflectionClass::inNamespace' => ['bool'], 'ReflectionClass::isAbstract' => ['bool'], 'ReflectionClass::isAnonymous' => ['bool'], 'ReflectionClass::isCloneable' => ['bool'], 'ReflectionClass::isFinal' => ['bool'], 'ReflectionClass::isInstance' => ['bool', 'object'=>'object'], 'ReflectionClass::isInstantiable' => ['bool'], 'ReflectionClass::isInterface' => ['bool'], 'ReflectionClass::isInternal' => ['bool'], 'ReflectionClass::isIterable' => ['bool'], 'ReflectionClass::isIterateable' => ['bool'], 'ReflectionClass::isSubclassOf' => ['bool', 'class'=>'string|ReflectionClass'], 'ReflectionClass::isTrait' => ['bool'], 'ReflectionClass::isUserDefined' => ['bool'], 'ReflectionClass::newInstance' => ['object', 'args='=>'mixed', '...args='=>'mixed'], 'ReflectionClass::newInstanceArgs' => ['object', 'args='=>'array'], 'ReflectionClass::newInstanceWithoutConstructor' => ['object'], 'ReflectionClass::setStaticPropertyValue' => ['void', 'name'=>'string', 'value'=>'mixed'], 'ReflectionClassConstant::__construct' => ['void', 'class'=>'mixed', 'name'=>'string'], 'ReflectionClassConstant::__toString' => ['string'], 'ReflectionClassConstant::export' => ['string', 'class'=>'mixed', 'name'=>'string', 'return='=>'bool'], 'ReflectionClassConstant::getDeclaringClass' => ['ReflectionClass'], 'ReflectionClassConstant::getDocComment' => ['string|false'], 'ReflectionClassConstant::getModifiers' => ['int'], 'ReflectionClassConstant::getName' => ['string'], 'ReflectionClassConstant::getValue' => ['mixed'], 'ReflectionClassConstant::isPrivate' => ['bool'], 'ReflectionClassConstant::isProtected' => ['bool'], 'ReflectionClassConstant::isPublic' => ['bool'], 'ReflectionExtension::__clone' => ['void'], 'ReflectionExtension::__construct' => ['void', 'name'=>'string'], 'ReflectionExtension::__toString' => ['string'], 'ReflectionExtension::export' => ['string|null', 'name'=>'string', 'return='=>'bool'], 'ReflectionExtension::getClasses' => ['array'], 'ReflectionExtension::getClassNames' => ['list'], 'ReflectionExtension::getConstants' => ['array'], 'ReflectionExtension::getDependencies' => ['array'], 'ReflectionExtension::getFunctions' => ['array'], 'ReflectionExtension::getINIEntries' => ['array'], 'ReflectionExtension::getName' => ['string'], 'ReflectionExtension::getVersion' => ['string'], 'ReflectionExtension::info' => ['void'], 'ReflectionExtension::isPersistent' => ['void'], 'ReflectionExtension::isTemporary' => ['bool'], 'ReflectionFunction::__construct' => ['void', 'name'=>'string|Closure'], 'ReflectionFunction::__toString' => ['string'], 'ReflectionFunction::export' => ['string|null', 'name'=>'string', 'return='=>'bool'], 'ReflectionFunction::getClosure' => ['Closure'], 'ReflectionFunction::getClosureScopeClass' => ['ReflectionClass'], 'ReflectionFunction::getClosureThis' => ['bool'], 'ReflectionFunction::getDocComment' => ['string|false'], 'ReflectionFunction::getEndLine' => ['positive-int|false'], 'ReflectionFunction::getExtension' => ['ReflectionExtension|null'], 'ReflectionFunction::getExtensionName' => ['string|false'], 'ReflectionFunction::getFileName' => ['non-empty-string|false'], 'ReflectionFunction::getName' => ['non-empty-string'], 'ReflectionFunction::getNamespaceName' => ['string'], 'ReflectionFunction::getNumberOfParameters' => ['int'], 'ReflectionFunction::getNumberOfRequiredParameters' => ['int'], 'ReflectionFunction::getParameters' => ['list'], 'ReflectionFunction::getReturnType' => ['?ReflectionType'], 'ReflectionFunction::getShortName' => ['string'], 'ReflectionFunction::getStartLine' => ['positive-int|false'], 'ReflectionFunction::getStaticVariables' => ['array'], 'ReflectionFunction::inNamespace' => ['bool'], 'ReflectionFunction::invoke' => ['mixed', '...args='=>'mixed'], 'ReflectionFunction::invokeArgs' => ['mixed', 'args'=>'array'], 'ReflectionFunction::isClosure' => ['bool'], 'ReflectionFunction::isDeprecated' => ['bool'], 'ReflectionFunction::isDisabled' => ['bool'], 'ReflectionFunction::isGenerator' => ['bool'], 'ReflectionFunction::isInternal' => ['bool'], 'ReflectionFunction::isUserDefined' => ['bool'], 'ReflectionFunction::isVariadic' => ['bool'], 'ReflectionFunction::returnsReference' => ['bool'], 'ReflectionFunctionAbstract::__clone' => ['void'], 'ReflectionFunctionAbstract::__toString' => ['string'], 'ReflectionFunctionAbstract::getClosureScopeClass' => ['ReflectionClass|null'], 'ReflectionFunctionAbstract::getClosureThis' => ['object|null'], 'ReflectionFunctionAbstract::getDocComment' => ['string|false'], 'ReflectionFunctionAbstract::getEndLine' => ['positive-int|false'], 'ReflectionFunctionAbstract::getExtension' => ['ReflectionExtension|null'], 'ReflectionFunctionAbstract::getExtensionName' => ['string|false'], 'ReflectionFunctionAbstract::getFileName' => ['non-empty-string|false'], 'ReflectionFunctionAbstract::getName' => ['non-empty-string'], 'ReflectionFunctionAbstract::getNamespaceName' => ['string'], 'ReflectionFunctionAbstract::getNumberOfParameters' => ['int'], 'ReflectionFunctionAbstract::getNumberOfRequiredParameters' => ['int'], 'ReflectionFunctionAbstract::getParameters' => ['list'], 'ReflectionFunctionAbstract::getReturnType' => ['?ReflectionType'], 'ReflectionFunctionAbstract::getShortName' => ['string'], 'ReflectionFunctionAbstract::getStartLine' => ['positive-int|false'], 'ReflectionFunctionAbstract::getStaticVariables' => ['array'], 'ReflectionFunctionAbstract::hasReturnType' => ['bool'], 'ReflectionFunctionAbstract::inNamespace' => ['bool'], 'ReflectionFunctionAbstract::isClosure' => ['bool'], 'ReflectionFunctionAbstract::isDeprecated' => ['bool'], 'ReflectionFunctionAbstract::isGenerator' => ['bool'], 'ReflectionFunctionAbstract::isInternal' => ['bool'], 'ReflectionFunctionAbstract::isUserDefined' => ['bool'], 'ReflectionFunctionAbstract::isVariadic' => ['bool'], 'ReflectionFunctionAbstract::returnsReference' => ['bool'], 'ReflectionGenerator::__construct' => ['void', 'generator'=>'object'], 'ReflectionGenerator::getExecutingFile' => ['string'], 'ReflectionGenerator::getExecutingGenerator' => ['Generator'], 'ReflectionGenerator::getExecutingLine' => ['int'], 'ReflectionGenerator::getFunction' => ['ReflectionFunctionAbstract'], 'ReflectionGenerator::getThis' => ['object'], 'ReflectionGenerator::getTrace' => ['list\',args?:mixed[],object?:object}>', 'options'=>'int'], 'ReflectionMethod::__construct' => ['void', 'class'=>'string|object', 'name'=>'string'], 'ReflectionMethod::__construct\'1' => ['void', 'class_method'=>'string'], 'ReflectionMethod::__toString' => ['string'], 'ReflectionMethod::export' => ['string|null', 'class'=>'string', 'name'=>'string', 'return='=>'bool'], 'ReflectionMethod::getClosure' => ['Closure', 'object'=>'?object'], 'ReflectionMethod::getDeclaringClass' => ['ReflectionClass'], 'ReflectionMethod::getModifiers' => ['int'], 'ReflectionMethod::getPrototype' => ['ReflectionMethod'], 'ReflectionMethod::invoke' => ['mixed', 'object'=>'?object', '...args='=>'mixed'], 'ReflectionMethod::invokeArgs' => ['mixed', 'object'=>'?object', 'args'=>'array'], 'ReflectionMethod::isAbstract' => ['bool'], 'ReflectionMethod::isConstructor' => ['bool'], 'ReflectionMethod::isDestructor' => ['bool'], 'ReflectionMethod::isFinal' => ['bool'], 'ReflectionMethod::isPrivate' => ['bool'], 'ReflectionMethod::isProtected' => ['bool'], 'ReflectionMethod::isPublic' => ['bool'], 'ReflectionMethod::isStatic' => ['bool'], 'ReflectionMethod::setAccessible' => ['void', 'visible'=>'bool'], 'ReflectionNamedType::__toString' => ['string'], 'ReflectionNamedType::allowsNull' => ['bool'], 'ReflectionNamedType::getName' => ['string'], 'ReflectionNamedType::isBuiltin' => ['bool'], 'ReflectionObject::__construct' => ['void', 'argument'=>'object'], 'ReflectionObject::export' => ['string|null', 'argument'=>'object', 'return='=>'bool'], 'ReflectionParameter::__clone' => ['void'], 'ReflectionParameter::__construct' => ['void', 'function'=>'', 'parameter'=>''], 'ReflectionParameter::__toString' => ['string'], 'ReflectionParameter::allowsNull' => ['bool'], 'ReflectionParameter::canBePassedByValue' => ['bool'], 'ReflectionParameter::export' => ['string|null', 'function'=>'string', 'parameter'=>'string', 'return='=>'bool'], 'ReflectionParameter::getClass' => ['ReflectionClass|null'], 'ReflectionParameter::getDeclaringClass' => ['ReflectionClass|null'], 'ReflectionParameter::getDeclaringFunction' => ['ReflectionFunctionAbstract'], 'ReflectionParameter::getDefaultValue' => ['mixed'], 'ReflectionParameter::getDefaultValueConstantName' => ['?string'], 'ReflectionParameter::getName' => ['non-empty-string'], 'ReflectionParameter::getPosition' => ['int'], 'ReflectionParameter::getType' => ['ReflectionType|null'], 'ReflectionParameter::hasType' => ['bool'], 'ReflectionParameter::isArray' => ['bool'], 'ReflectionParameter::isCallable' => ['bool'], 'ReflectionParameter::isDefaultValueAvailable' => ['bool'], 'ReflectionParameter::isDefaultValueConstant' => ['bool'], 'ReflectionParameter::isOptional' => ['bool'], 'ReflectionParameter::isPassedByReference' => ['bool'], 'ReflectionParameter::isVariadic' => ['bool'], 'ReflectionProperty::__clone' => ['void'], 'ReflectionProperty::__construct' => ['void', 'class'=>'', 'name'=>'string'], 'ReflectionProperty::__toString' => ['string'], 'ReflectionProperty::export' => ['string|null', 'class'=>'mixed', 'name'=>'string', 'return='=>'bool'], 'ReflectionProperty::getDeclaringClass' => ['ReflectionClass'], 'ReflectionProperty::getDocComment' => ['string|false'], 'ReflectionProperty::getModifiers' => ['int'], 'ReflectionProperty::getName' => ['non-empty-string'], 'ReflectionProperty::getValue' => ['mixed', 'object='=>'object'], 'ReflectionProperty::isDefault' => ['bool'], 'ReflectionProperty::isPrivate' => ['bool'], 'ReflectionProperty::isProtected' => ['bool'], 'ReflectionProperty::isPublic' => ['bool'], 'ReflectionProperty::isStatic' => ['bool'], 'ReflectionProperty::setAccessible' => ['void', 'visible'=>'bool'], 'ReflectionProperty::setValue' => ['void', 'object'=>'null|object', 'value'=>''], 'ReflectionProperty::setValue\'1' => ['void', 'value'=>''], 'ReflectionType::__toString' => ['string'], 'ReflectionType::allowsNull' => ['bool'], 'ReflectionType::isBuiltin' => ['bool'], 'ReflectionZendExtension::__clone' => ['void'], 'ReflectionZendExtension::__construct' => ['void', 'name'=>'string'], 'ReflectionZendExtension::__toString' => ['string'], 'ReflectionZendExtension::export' => ['string|null', 'name'=>'string', 'return='=>'bool'], 'ReflectionZendExtension::getAuthor' => ['string'], 'ReflectionZendExtension::getCopyright' => ['string'], 'ReflectionZendExtension::getName' => ['string'], 'ReflectionZendExtension::getURL' => ['string'], 'ReflectionZendExtension::getVersion' => ['string'], 'Reflector::__toString' => ['string'], 'Reflector::export' => ['?string'], 'RegexIterator::__construct' => ['void', 'iterator'=>'Iterator', 'regex'=>'string', 'mode='=>'int', 'flags='=>'int', 'preg_flags='=>'int'], 'RegexIterator::accept' => ['bool'], 'RegexIterator::getFlags' => ['int'], 'RegexIterator::getMode' => ['int'], 'RegexIterator::getPregFlags' => ['int'], 'RegexIterator::getRegex' => ['string'], 'RegexIterator::setFlags' => ['bool', 'new_flags'=>'int'], 'RegexIterator::setMode' => ['bool', 'new_mode'=>'int'], 'RegexIterator::setPregFlags' => ['bool', 'new_flags'=>'int'], 'register_event_handler' => ['bool', 'event_handler_func'=>'event_handler_func', 'handler_register_name'=>'handler_register_name', 'event_type_mask'=>'event_type_mask'], 'register_shutdown_function' => ['void', 'function'=>'callable', '...parameter='=>'mixed'], 'register_tick_function' => ['bool', 'function'=>'callable(): void', '...args='=>'mixed'], 'rename' => ['bool', 'old_name'=>'string', 'new_name'=>'string', 'context='=>'resource'], 'rename_function' => ['bool', 'original_name'=>'string', 'new_name'=>'string'], 'reset' => ['mixed', '&rw_array'=>'array|object'], 'ResourceBundle::__construct' => ['void', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'], 'ResourceBundle::count' => ['0|positive-int'], 'ResourceBundle::create' => ['?ResourceBundle', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'], 'ResourceBundle::get' => ['', 'index'=>'string|int', 'fallback='=>'bool'], 'ResourceBundle::getErrorCode' => ['int'], 'ResourceBundle::getErrorMessage' => ['string'], 'ResourceBundle::getLocales' => ['array', 'bundlename'=>'string'], 'resourcebundle_count' => ['int', 'r'=>'resourcebundle'], 'resourcebundle_create' => ['?ResourceBundle', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'], 'resourcebundle_get' => ['', 'r'=>'resourcebundle', 'index'=>'string|int', 'fallback='=>'bool'], 'resourcebundle_get_error_code' => ['int', 'r'=>'resourcebundle'], 'resourcebundle_get_error_message' => ['string', 'r'=>'resourcebundle'], 'resourcebundle_locales' => ['array|false', 'bundlename'=>'string'], 'restore_error_handler' => ['true'], 'restore_exception_handler' => ['true'], 'restore_include_path' => ['void'], 'rewind' => ['bool', 'fp'=>'resource'], 'rewinddir' => ['null|false', 'dir_handle='=>'resource'], 'rmdir' => ['bool', 'dirname'=>'string', 'context='=>'resource'], 'round' => ['__benevolent', 'number'=>'float', 'precision='=>'int', 'mode='=>'1|2|3|4'], 'rpm_close' => ['bool', 'rpmr'=>'resource'], 'rpm_get_tag' => ['mixed', 'rpmr'=>'resource', 'tagnum'=>'int'], 'rpm_is_valid' => ['bool', 'filename'=>'string'], 'rpm_open' => ['resource|false', 'filename'=>'string'], 'rpm_version' => ['string'], 'rrd_create' => ['bool', 'filename'=>'string', 'options'=>'array'], 'rrd_error' => ['string'], 'rrd_fetch' => ['array', 'filename'=>'string', 'options'=>'array'], 'rrd_first' => ['int', 'file'=>'string', 'raaindex='=>'int'], 'rrd_graph' => ['array', 'filename'=>'string', 'options'=>'array'], 'rrd_info' => ['array', 'filename'=>'string'], 'rrd_last' => ['int', 'filename'=>'string'], 'rrd_lastupdate' => ['array', 'filename'=>'string'], 'rrd_restore' => ['bool', 'xml_file'=>'string', 'rrd_file'=>'string', 'options='=>'array'], 'rrd_tune' => ['bool', 'filename'=>'string', 'options'=>'array'], 'rrd_update' => ['bool', 'filename'=>'string', 'options'=>'array'], 'rrd_version' => ['string'], 'rrd_xport' => ['array', 'options'=>'array'], 'rrdc_disconnect' => ['void'], 'RRDCreator::__construct' => ['void', 'path'=>'string', 'starttime='=>'string', 'step='=>'int'], 'RRDCreator::addArchive' => ['void', 'description'=>'string'], 'RRDCreator::addDataSource' => ['void', 'description'=>'string'], 'RRDCreator::save' => ['bool'], 'RRDGraph::__construct' => ['void', 'path'=>'string'], 'RRDGraph::save' => ['array'], 'RRDGraph::saveVerbose' => ['array'], 'RRDGraph::setOptions' => ['void', 'options'=>'array'], 'RRDUpdater::__construct' => ['void', 'path'=>'string'], 'RRDUpdater::update' => ['bool', 'values'=>'array', 'time='=>'string'], 'rsort' => ['bool', '&rw_array_arg'=>'array', 'sort_flags='=>'int'], 'rtrim' => ['string', 'str'=>'string', 'character_mask='=>'string'], 'runkit_class_adopt' => ['bool', 'classname'=>'string', 'parentname'=>'string'], 'runkit_class_emancipate' => ['bool', 'classname'=>'string'], 'runkit_constant_add' => ['bool', 'constname'=>'string', 'value'=>'mixed'], 'runkit_constant_redefine' => ['bool', 'constname'=>'string', 'newvalue'=>'mixed'], 'runkit_constant_remove' => ['bool', 'constname'=>'string'], 'runkit_function_add' => ['bool', 'funcname'=>'string', 'arglist'=>'string', 'code'=>'string', 'doccomment='=>'?string'], 'runkit_function_add\'1' => ['bool', 'funcname'=>'string', 'closure'=>'Closure', 'doccomment='=>'?string'], 'runkit_function_copy' => ['bool', 'funcname'=>'string', 'targetname'=>'string'], 'runkit_function_redefine' => ['bool', 'funcname'=>'string', 'arglist'=>'string', 'code'=>'string', 'doccomment='=>'?string'], 'runkit_function_redefine\'1' => ['bool', 'funcname'=>'string', 'closure'=>'Closure', 'doccomment='=>'?string'], 'runkit_function_remove' => ['bool', 'funcname'=>'string'], 'runkit_function_rename' => ['bool', 'funcname'=>'string', 'newname'=>'string'], 'runkit_import' => ['bool', 'filename'=>'string', 'flags='=>'int'], 'runkit_lint' => ['bool', 'code'=>'string'], 'runkit_lint_file' => ['bool', 'filename'=>'string'], 'runkit_method_add' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'args'=>'string', 'code'=>'string', 'flags='=>'int', 'doccomment='=>'?string'], 'runkit_method_add\'1' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'closure'=>'Closure', 'flags='=>'int', 'doccomment='=>'?string'], 'runkit_method_copy' => ['bool', 'dclass'=>'string', 'dmethod'=>'string', 'sclass'=>'string', 'smethod='=>'string'], 'runkit_method_redefine' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'args'=>'string', 'code'=>'string', 'flags='=>'int', 'doccomment='=>'?string'], 'runkit_method_redefine\'1' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'closure'=>'Closure', 'flags='=>'int', 'doccomment='=>'?string'], 'runkit_method_remove' => ['bool', 'classname'=>'string', 'methodname'=>'string'], 'runkit_method_rename' => ['bool', 'classname'=>'string', 'methodname'=>'string', 'newname'=>'string'], 'runkit_return_value_used' => ['bool'], 'Runkit_Sandbox::__construct' => ['void', 'options='=>'array'], 'runkit_sandbox_output_handler' => ['mixed', 'sandbox'=>'object', 'callback='=>'mixed'], 'Runkit_Sandbox_Parent' => [''], 'Runkit_Sandbox_Parent::__construct' => ['void'], 'runkit_superglobals' => ['array'], 'RuntimeException::__clone' => ['void'], 'RuntimeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?RuntimeException)'], 'RuntimeException::__toString' => ['string'], 'RuntimeException::getCode' => ['int'], 'RuntimeException::getFile' => ['string'], 'RuntimeException::getLine' => ['int'], 'RuntimeException::getMessage' => ['string'], 'RuntimeException::getPrevious' => ['Throwable|RuntimeException|null'], 'RuntimeException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'RuntimeException::getTraceAsString' => ['string'], 'SAMConnection::commit' => ['bool'], 'SAMConnection::connect' => ['bool', 'protocol'=>'string', 'properties='=>'array'], 'SAMConnection::disconnect' => ['bool'], 'SAMConnection::errno' => ['int'], 'SAMConnection::error' => ['string'], 'SAMConnection::isConnected' => ['bool'], 'SAMConnection::peek' => ['SAMMessage', 'target'=>'string', 'properties='=>'array'], 'SAMConnection::peekAll' => ['array', 'target'=>'string', 'properties='=>'array'], 'SAMConnection::receive' => ['SAMMessage', 'target'=>'string', 'properties='=>'array'], 'SAMConnection::remove' => ['SAMMessage', 'target'=>'string', 'properties='=>'array'], 'SAMConnection::rollback' => ['bool'], 'SAMConnection::send' => ['string', 'target'=>'string', 'msg'=>'sammessage', 'properties='=>'array'], 'SAMConnection::setDebug' => ['', 'switch'=>'bool'], 'SAMConnection::subscribe' => ['string', 'targettopic'=>'string'], 'SAMConnection::unsubscribe' => ['bool', 'subscriptionid'=>'string', 'targettopic='=>'string'], 'SAMMessage::body' => ['string'], 'SAMMessage::header' => ['object'], 'sapi_windows_cp_conv' => ['string', 'in_codepage'=>'int|string', 'out_codepage'=>'int|string', 'subject'=>'string'], 'sapi_windows_cp_get' => ['int'], 'sapi_windows_cp_is_utf8' => ['bool'], 'sapi_windows_cp_set' => ['bool', 'code_page'=>'int'], 'sapi_windows_vt100_support' => ['bool', 'stream'=>'resource', 'enable='=>'bool'], 'SCA::createDataObject' => ['SDO_DataObject', 'type_namespace_uri'=>'string', 'type_name'=>'string'], 'SCA::getService' => ['', 'target'=>'string', 'binding='=>'string', 'config='=>'array'], 'SCA_LocalProxy::createDataObject' => ['SDO_DataObject', 'type_namespace_uri'=>'string', 'type_name'=>'string'], 'SCA_SoapProxy::createDataObject' => ['SDO_DataObject', 'type_namespace_uri'=>'string', 'type_name'=>'string'], 'scalebarObj::convertToString' => ['string'], 'scalebarObj::free' => ['void'], 'scalebarObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'scalebarObj::setImageColor' => ['int', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'scalebarObj::updateFromString' => ['int', 'snippet'=>'string'], 'scandir' => ['list|false', 'dir'=>'string', 'sorting_order='=>'int', 'context='=>'resource'], 'SDO_DAS_ChangeSummary::beginLogging' => [''], 'SDO_DAS_ChangeSummary::endLogging' => [''], 'SDO_DAS_ChangeSummary::getChangedDataObjects' => ['SDO_List'], 'SDO_DAS_ChangeSummary::getChangeType' => ['int', 'dataobject'=>'sdo_dataobject'], 'SDO_DAS_ChangeSummary::getOldContainer' => ['SDO_DataObject', 'data_object'=>'sdo_dataobject'], 'SDO_DAS_ChangeSummary::getOldValues' => ['SDO_List', 'data_object'=>'sdo_dataobject'], 'SDO_DAS_ChangeSummary::isLogging' => ['bool'], 'SDO_DAS_DataFactory::addPropertyToType' => ['', 'parent_type_namespace_uri'=>'string', 'parent_type_name'=>'string', 'property_name'=>'string', 'type_namespace_uri'=>'string', 'type_name'=>'string', 'options='=>'array'], 'SDO_DAS_DataFactory::addType' => ['', 'type_namespace_uri'=>'string', 'type_name'=>'string', 'options='=>'array'], 'SDO_DAS_DataFactory::getDataFactory' => ['SDO_DAS_DataFactory'], 'SDO_DAS_DataObject::getChangeSummary' => ['SDO_DAS_ChangeSummary'], 'SDO_DAS_Relational::__construct' => ['void', 'database_metadata'=>'array', 'application_root_type='=>'string', 'sdo_containment_references_metadata='=>'array'], 'SDO_DAS_Relational::applyChanges' => ['', 'database_handle'=>'pdo', 'root_data_object'=>'sdodataobject'], 'SDO_DAS_Relational::createRootDataObject' => ['SDODataObject'], 'SDO_DAS_Relational::executePreparedQuery' => ['SDODataObject', 'database_handle'=>'pdo', 'prepared_statement'=>'pdostatement', 'value_list'=>'array', 'column_specifier='=>'array'], 'SDO_DAS_Relational::executeQuery' => ['SDODataObject', 'database_handle'=>'pdo', 'sql_statement'=>'string', 'column_specifier='=>'array'], 'SDO_DAS_Setting::getListIndex' => ['int'], 'SDO_DAS_Setting::getPropertyIndex' => ['int'], 'SDO_DAS_Setting::getPropertyName' => ['string'], 'SDO_DAS_Setting::getValue' => [''], 'SDO_DAS_Setting::isSet' => ['bool'], 'SDO_DAS_XML::addTypes' => ['', 'xsd_file'=>'string'], 'SDO_DAS_XML::create' => ['SDO_DAS_XML', 'xsd_file='=>'mixed', 'key='=>'string'], 'SDO_DAS_XML::createDataObject' => ['SDO_DataObject', 'namespace_uri'=>'string', 'type_name'=>'string'], 'SDO_DAS_XML::createDocument' => ['SDO_DAS_XML_Document', 'document_element_name'=>'string', 'document_element_namespace_uri'=>'string', 'dataobject='=>'sdo_dataobject'], 'SDO_DAS_XML::loadFile' => ['SDO_XMLDocument', 'xml_file'=>'string'], 'SDO_DAS_XML::loadString' => ['SDO_DAS_XML_Document', 'xml_string'=>'string'], 'SDO_DAS_XML::saveFile' => ['', 'xdoc'=>'sdo_xmldocument', 'xml_file'=>'string', 'indent='=>'int'], 'SDO_DAS_XML::saveString' => ['string', 'xdoc'=>'sdo_xmldocument', 'indent='=>'int'], 'SDO_DAS_XML_Document::getRootDataObject' => ['SDO_DataObject'], 'SDO_DAS_XML_Document::getRootElementName' => ['string'], 'SDO_DAS_XML_Document::getRootElementURI' => ['string'], 'SDO_DAS_XML_Document::setEncoding' => ['', 'encoding'=>'string'], 'SDO_DAS_XML_Document::setXMLDeclaration' => ['', 'xmldeclatation'=>'bool'], 'SDO_DAS_XML_Document::setXMLVersion' => ['', 'xmlversion'=>'string'], 'SDO_DataFactory::create' => ['void', 'type_namespace_uri'=>'string', 'type_name'=>'string'], 'SDO_DataObject::clear' => ['void'], 'SDO_DataObject::createDataObject' => ['SDO_DataObject', 'identifier'=>''], 'SDO_DataObject::getContainer' => ['SDO_DataObject'], 'SDO_DataObject::getSequence' => ['SDO_Sequence'], 'SDO_DataObject::getTypeName' => ['string'], 'SDO_DataObject::getTypeNamespaceURI' => ['string'], 'SDO_Exception::getCause' => [''], 'SDO_List::insert' => ['void', 'value'=>'mixed', 'index='=>'int'], 'SDO_Model_Property::getContainingType' => ['SDO_Model_Type'], 'SDO_Model_Property::getDefault' => [''], 'SDO_Model_Property::getName' => ['string'], 'SDO_Model_Property::getType' => ['SDO_Model_Type'], 'SDO_Model_Property::isContainment' => ['bool'], 'SDO_Model_Property::isMany' => ['bool'], 'SDO_Model_ReflectionDataObject::__construct' => ['void', 'data_object'=>'sdo_dataobject'], 'SDO_Model_ReflectionDataObject::export' => ['mixed', 'rdo'=>'sdo_model_reflectiondataobject', 'return='=>'bool'], 'SDO_Model_ReflectionDataObject::getContainmentProperty' => ['SDO_Model_Property'], 'SDO_Model_ReflectionDataObject::getInstanceProperties' => ['array'], 'SDO_Model_ReflectionDataObject::getType' => ['SDO_Model_Type'], 'SDO_Model_Type::getBaseType' => ['SDO_Model_Type'], 'SDO_Model_Type::getName' => ['string'], 'SDO_Model_Type::getNamespaceURI' => ['string'], 'SDO_Model_Type::getProperties' => ['array'], 'SDO_Model_Type::getProperty' => ['SDO_Model_Property', 'identifier'=>''], 'SDO_Model_Type::isAbstractType' => ['bool'], 'SDO_Model_Type::isDataType' => ['bool'], 'SDO_Model_Type::isInstance' => ['bool', 'data_object'=>'sdo_dataobject'], 'SDO_Model_Type::isOpenType' => ['bool'], 'SDO_Model_Type::isSequencedType' => ['bool'], 'SDO_Sequence::getProperty' => ['SDO_Model_Property', 'sequence_index'=>'int'], 'SDO_Sequence::insert' => ['void', 'value'=>'mixed', 'sequenceindex='=>'int', 'propertyidentifier='=>'mixed'], 'SDO_Sequence::move' => ['void', 'toindex'=>'int', 'fromindex'=>'int'], 'SeekableIterator::seek' => ['void', 'position'=>'int'], 'sem_acquire' => ['bool', 'sem_identifier'=>'resource', 'nowait='=>'bool'], 'sem_get' => ['resource|false', 'key'=>'int', 'max_acquire='=>'int', 'perm='=>'int', 'auto_release='=>'int'], 'sem_release' => ['bool', 'sem_identifier'=>'resource'], 'sem_remove' => ['bool', 'sem_identifier'=>'resource'], 'Serializable::serialize' => ['string'], 'Serializable::unserialize' => ['void', 'serialized'=>'string'], 'serialize' => ['string', 'variable'=>'mixed'], 'ServerRequest::withInput' => ['ServerRequest', 'input'=>'mixed'], 'ServerRequest::withoutParams' => ['ServerRequest', 'params'=>'int|string'], 'ServerRequest::withParam' => ['ServerRequest', 'key'=>'int|string', 'val'=>'mixed'], 'ServerRequest::withParams' => ['ServerRequest', 'params'=>'mixed'], 'ServerRequest::withUrl' => ['ServerRequest', 'url'=>'array'], 'ServerResponse::addHeader' => ['void', 'label'=>'string', 'value'=>'string'], 'ServerResponse::date' => ['string', 'date'=>'string|DateTimeInterface'], 'ServerResponse::getHeader' => ['string', 'label'=>'string'], 'ServerResponse::getHeaders' => ['string[]'], 'ServerResponse::getStatus' => ['int'], 'ServerResponse::getVersion' => ['string'], 'ServerResponse::setHeader' => ['void', 'label'=>'string', 'value'=>'string'], 'ServerResponse::setStatus' => ['void', 'status'=>'int'], 'ServerResponse::setVersion' => ['void', 'version'=>'string'], 'session_abort' => ['bool'], 'session_cache_expire' => ['int|false', 'new_cache_expire='=>'int'], 'session_cache_limiter' => ['string|false', 'new_cache_limiter='=>'string'], 'session_commit' => ['bool'], 'session_create_id' => ['string|false', 'prefix='=>'string'], 'session_decode' => ['bool', 'data'=>'string'], 'session_destroy' => ['bool'], 'session_encode' => ['string|false'], 'session_gc' => ['int|false'], 'session_get_cookie_params' => ['array{lifetime:0|positive-int,path:non-falsy-string,domain:string,secure:bool,httponly:bool,samesite:string}'], 'session_id' => ['string|false', 'newid='=>'string'], 'session_is_registered' => ['bool', 'name'=>'string'], 'session_module_name' => ['string|false', 'newname='=>'string'], 'session_name' => ['non-falsy-string|false', 'newname='=>'string'], 'session_pgsql_add_error' => ['bool', 'error_level'=>'int', 'error_message='=>'string'], 'session_pgsql_get_error' => ['array', 'with_error_message='=>'bool'], 'session_pgsql_get_field' => ['string'], 'session_pgsql_reset' => ['bool'], 'session_pgsql_set_field' => ['bool', 'value'=>'string'], 'session_pgsql_status' => ['array'], 'session_regenerate_id' => ['bool', 'delete_old_session='=>'bool'], 'session_register' => ['bool', 'name'=>'mixed', '...args='=>'mixed'], 'session_register_shutdown' => ['void'], 'session_reset' => ['bool'], 'session_save_path' => ['string|false', 'newname='=>'string'], 'session_set_cookie_params' => ['bool', 'lifetime'=>'int', 'path='=>'string', 'domain='=>'?string', 'secure='=>'bool', 'httponly='=>'bool'], 'session_set_cookie_params\'1' => ['bool', 'options'=>'array{lifetime?:int,path?:string,domain?:?string,secure?:bool,httponly?:bool,samesite?:string}'], 'session_set_save_handler' => ['bool', 'open'=>'callable(string,string):bool', 'close'=>'callable():bool', 'read'=>'callable(string):string', 'write'=>'callable(string,string):bool', 'destroy'=>'callable(string):bool', 'gc'=>'callable(string):bool', 'create_sid='=>'callable():string', 'validate_sid='=>'callable(string):bool', 'update_timestamp='=>'callable(string):bool'], 'session_set_save_handler\'1' => ['bool', 'sessionhandler'=>'SessionHandlerInterface', 'register_shutdown='=>'bool'], 'session_start' => ['bool', 'options='=>'array'], 'session_status' => ['PHP_SESSION_NONE|PHP_SESSION_DISABLED|PHP_SESSION_ACTIVE'], 'session_unregister' => ['bool', 'name'=>'string'], 'session_unset' => ['bool'], 'session_write_close' => ['bool'], 'SessionHandler::close' => ['bool'], 'SessionHandler::create_sid' => ['char'], 'SessionHandler::destroy' => ['bool', 'id'=>'string'], 'SessionHandler::gc' => ['int|false', 'maxlifetime'=>'int'], 'SessionHandler::open' => ['bool', 'save_path'=>'string', 'session_name'=>'string'], 'SessionHandler::read' => ['string', 'id'=>'string'], 'SessionHandler::updateTimestamp' => ['bool', 'session_id'=>'string', 'session_data'=>'string'], 'SessionHandler::validateId' => ['bool', 'session_id'=>'string'], 'SessionHandler::write' => ['bool', 'id'=>'string', 'data'=>'string'], 'SessionHandlerInterface::close' => ['bool'], 'SessionHandlerInterface::destroy' => ['bool', 'session_id'=>'string'], 'SessionHandlerInterface::gc' => ['int|false', 'maxlifetime'=>'int'], 'SessionHandlerInterface::open' => ['bool', 'save_path'=>'string', 'name'=>'string'], 'SessionHandlerInterface::read' => ['string', 'session_id'=>'string'], 'SessionHandlerInterface::write' => ['bool', 'session_id'=>'string', 'session_data'=>'string'], 'SessionIdInterface::create_sid' => ['string'], 'SessionUpdateTimestampHandler::updateTimestamp' => ['bool', 'id'=>'string', 'data'=>'string'], 'SessionUpdateTimestampHandler::validateId' => ['char', 'id'=>'string'], 'SessionUpdateTimestampHandlerInterface::updateTimestamp' => ['bool', 'key'=>'string', 'val'=>'string'], 'SessionUpdateTimestampHandlerInterface::validateId' => ['bool', 'key'=>'string'], 'set_error_handler' => ['?callable', 'callback'=>'null|callable(int,string,string,int,array):bool', 'error_types='=>'int'], 'set_exception_handler' => ['null|callable(Throwable):void', 'exception_handler'=>'null|callable(Throwable):void'], 'set_file_buffer' => ['int', 'fp'=>'resource', 'buffer'=>'int'], 'set_include_path' => ['string|false', 'new_include_path'=>'string'], 'set_magic_quotes_runtime' => ['bool', 'new_setting'=>'bool'], 'set_time_limit' => ['bool', 'seconds'=>'int'], 'setcookie' => ['bool', 'name'=>'string', 'value='=>'string', 'expires='=>'int', 'path='=>'string', 'domain='=>'string', 'secure='=>'bool', 'httponly='=>'bool'], 'setcookie\'1' => ['bool', 'name'=>'string', 'value='=>'string', 'options='=>'array{ expires?:int, path?:string, domain?:string, secure?:bool, httponly?:bool, samesite?:\'None\'|\'Lax\'|\'Strict\'|\'none\'|\'lax\'|\'strict\'}'], 'setLeftFill' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'setLine' => ['void', 'width'=>'int', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'setlocale' => ['string|false', 'category'=>'int', 'locale'=>'string|null', '...args='=>'string'], 'setlocale\'1' => ['string|false', 'category'=>'int', 'locale'=>'?array'], 'setrawcookie' => ['bool', 'name'=>'string', 'value='=>'string', 'expires='=>'int', 'path='=>'string', 'domain='=>'string', 'secure='=>'bool', 'httponly='=>'bool'], 'setrawcookie\'1' => ['bool', 'name'=>'string', 'value='=>'string', 'options='=>'array{ expires?:int, path?:string, domain?:string, secure?:bool, httponly?:bool, samesite?:\'None\'|\'Lax\'|\'Strict\'|\'none\'|\'lax\'|\'strict\'}'], 'setRightFill' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'setthreadtitle' => ['bool', 'title'=>'string'], 'settype' => ['bool', '&rw_var'=>'mixed', 'type'=>'string'], 'sha1' => ['non-falsy-string&lowercase-string', 'str'=>'string', 'raw_output='=>'bool'], 'sha1_file' => ['(non-falsy-string&lowercase-string)|false', 'filename'=>'string', 'raw_output='=>'bool'], 'shapefileObj::__construct' => ['void', 'filename'=>'string', 'type'=>'int'], 'shapefileObj::addPoint' => ['int', 'point'=>'pointObj'], 'shapefileObj::addShape' => ['int', 'shape'=>'shapeObj'], 'shapefileObj::free' => ['void'], 'shapefileObj::getExtent' => ['rectObj', 'i'=>'int'], 'shapefileObj::getPoint' => ['shapeObj', 'i'=>'int'], 'shapefileObj::getShape' => ['shapeObj', 'i'=>'int'], 'shapefileObj::getTransformed' => ['shapeObj', 'map'=>'mapObj', 'i'=>'int'], 'shapefileObj::ms_newShapefileObj' => ['shapefileObj', 'filename'=>'string', 'type'=>'int'], 'shapeObj::__construct' => ['void', 'type'=>'int'], 'shapeObj::add' => ['int', 'line'=>'lineObj'], 'shapeObj::boundary' => ['shapeObj'], 'shapeObj::contains' => ['bool', 'point'=>'pointObj'], 'shapeObj::containsShape' => ['int', 'shape2'=>'shapeObj'], 'shapeObj::convexhull' => ['shapeObj'], 'shapeObj::crosses' => ['int', 'shape'=>'shapeObj'], 'shapeObj::difference' => ['shapeObj', 'shape'=>'shapeObj'], 'shapeObj::disjoint' => ['int', 'shape'=>'shapeObj'], 'shapeObj::draw' => ['int', 'map'=>'mapObj', 'layer'=>'layerObj', 'img'=>'imageObj'], 'shapeObj::equals' => ['int', 'shape'=>'shapeObj'], 'shapeObj::free' => ['void'], 'shapeObj::getArea' => ['float'], 'shapeObj::getCentroid' => ['pointObj'], 'shapeObj::getLabelPoint' => ['pointObj'], 'shapeObj::getLength' => ['float'], 'shapeObj::getPointUsingMeasure' => ['pointObj', 'm'=>'float'], 'shapeObj::getValue' => ['string', 'layer'=>'layerObj', 'filedname'=>'string'], 'shapeObj::intersection' => ['shapeObj', 'shape'=>'shapeObj'], 'shapeObj::intersects' => ['bool', 'shape'=>'shapeObj'], 'shapeObj::line' => ['lineObj', 'i'=>'int'], 'shapeObj::ms_shapeObjFromWkt' => ['shapeObj', 'wkt'=>'string'], 'shapeObj::overlaps' => ['int', 'shape'=>'shapeObj'], 'shapeObj::project' => ['int', 'in'=>'projectionObj', 'out'=>'projectionObj'], 'shapeObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'shapeObj::setBounds' => ['int'], 'shapeObj::simplify' => ['shapeObj', 'tolerance'=>'float'], 'shapeObj::symdifference' => ['shapeObj', 'shape'=>'shapeObj'], 'shapeObj::topologyPreservingSimplify' => ['shapeObj', 'tolerance'=>'float'], 'shapeObj::touches' => ['int', 'shape'=>'shapeObj'], 'shapeObj::toWkt' => ['string'], 'shapeObj::union' => ['shapeObj', 'shape'=>'shapeObj'], 'shapeObj::within' => ['int', 'shape2'=>'shapeObj'], 'shell_exec' => ['?string', 'cmd'=>'string'], 'shm_attach' => ['resource|false', 'key'=>'int', 'memsize='=>'int', 'perm='=>'int'], 'shm_detach' => ['bool', 'shm_identifier'=>'resource'], 'shm_get_var' => ['mixed', 'id'=>'resource', 'variable_key'=>'int'], 'shm_has_var' => ['bool', 'shm_identifier'=>'resource', 'variable_key'=>'int'], 'shm_put_var' => ['bool', 'shm_identifier'=>'resource', 'variable_key'=>'int', 'variable'=>'mixed'], 'shm_remove' => ['bool', 'shm_identifier'=>'resource'], 'shm_remove_var' => ['bool', 'shm_identifier'=>'resource', 'variable_key'=>'int'], 'shmop_close' => ['void', 'shmid'=>'resource'], 'shmop_delete' => ['bool', 'shmid'=>'resource'], 'shmop_open' => ['resource|false', 'key'=>'int', 'flags'=>'string', 'mode'=>'int', 'size'=>'int'], 'shmop_read' => ['string', 'shmid'=>'resource', 'start'=>'int', 'count'=>'int'], 'shmop_size' => ['int', 'shmid'=>'resource'], 'shmop_write' => ['int', 'shmid'=>'resource', 'data'=>'string', 'offset'=>'int'], 'show_source' => ['', 'file_name'=>'', 'return'=>''], 'shuffle' => ['bool', '&rw_array_arg'=>'array'], 'signeurlpaiement' => ['string', 'clent'=>'string', 'data'=>'string'], 'similar_text' => ['int', 'str1'=>'string', 'str2'=>'string', '&w_percent='=>'float'], 'simplexml_import_dom' => ['SimpleXMLElement|null', 'node'=>'DOMNode', 'class_name='=>'string'], 'simplexml_load_file' => ['SimpleXMLElement|false', 'filename'=>'string', 'class_name='=>'string', 'options='=>'int', 'ns='=>'string', 'is_prefix='=>'bool'], 'simplexml_load_string' => ['SimpleXMLElement|false', 'data'=>'string', 'class_name='=>'string', 'options='=>'int', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLElement::__construct' => ['void', 'data'=>'string', 'options='=>'int', 'data_is_url='=>'bool', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLElement::__get' => ['static', 'name'=>'string'], 'SimpleXMLElement::__toString' => ['string'], 'SimpleXMLElement::addAttribute' => ['void', 'name'=>'string', 'value='=>'string', 'ns='=>'string'], 'SimpleXMLElement::addChild' => ['__benevolent', 'name'=>'string', 'value='=>'string|null', 'ns='=>'string|null'], 'SimpleXMLElement::asXML' => ['string|bool', 'filename='=>'string'], 'SimpleXMLElement::attributes' => ['__benevolent', 'ns='=>'string', 'is_prefix='=>'bool'], 'SimpleXMLElement::children' => ['__benevolent', 'namespaceOrPrefix='=>'string|null', 'is_prefix='=>'bool'], 'SimpleXMLElement::count' => ['0|positive-int'], 'SimpleXMLElement::getDocNamespaces' => ['string[]|false', 'recursive='=>'bool', 'from_root='=>'bool'], 'SimpleXMLElement::getName' => ['string'], 'SimpleXMLElement::getNamespaces' => ['string[]', 'recursive='=>'bool'], 'SimpleXMLElement::registerXPathNamespace' => ['bool', 'prefix'=>'string', 'ns'=>'string'], 'SimpleXMLElement::xpath' => ['static[]|false|null', 'path'=>'string'], 'SimpleXMLIterator::current' => ['SimpleXMLIterator'], 'SimpleXMLIterator::getChildren' => ['SimpleXMLIterator'], 'SimpleXMLIterator::hasChildren' => ['bool'], 'SimpleXMLIterator::key' => ['string|false'], 'SimpleXMLIterator::next' => ['void'], 'SimpleXMLIterator::rewind' => ['void'], 'SimpleXMLIterator::valid' => ['bool'], 'sin' => ['float', 'number'=>'float'], 'sinh' => ['float', 'number'=>'float'], 'sizeof' => ['int', 'var'=>'Countable|array', 'mode='=>'int'], 'sleep' => ['int|false', 'seconds'=>'int'], 'snmp2_get' => ['string|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp2_getnext' => ['string|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp2_real_walk' => ['array|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp2_set' => ['bool', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp2_walk' => ['array|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_get' => ['string|false', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_getnext' => ['string|false', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_real_walk' => ['array|false', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_set' => ['bool', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmp3_walk' => ['array|false', 'host'=>'string', 'sec_name'=>'string', 'sec_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'priv_protocol'=>'string', 'priv_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'SNMP::__construct' => ['void', 'version'=>'int', 'hostname'=>'string', 'community'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'SNMP::close' => ['bool'], 'SNMP::get' => ['array|string|false', 'object_id'=>'string|array', 'preserve_keys='=>'bool'], 'SNMP::getErrno' => ['int'], 'SNMP::getError' => ['string'], 'SNMP::getnext' => ['string|array|false', 'object_id'=>'string|array'], 'SNMP::set' => ['bool', 'object_id'=>'string|array', 'type'=>'string|array', 'value'=>'mixed'], 'SNMP::setSecurity' => ['bool', 'sec_level'=>'string', 'auth_protocol='=>'string', 'auth_passphrase='=>'string', 'priv_protocol='=>'string', 'priv_passphrase='=>'string', 'contextname='=>'string', 'contextengineid='=>'string'], 'SNMP::walk' => ['array|false', 'object_id'=>'string', 'suffix_as_key='=>'bool', 'non_repeaters='=>'int', 'max_repetitions='=>'int'], 'snmp_get_quick_print' => ['bool'], 'snmp_get_valueretrieval' => ['int'], 'snmp_read_mib' => ['bool', 'filename'=>'string'], 'snmp_set_enum_print' => ['bool', 'enum_print'=>'int'], 'snmp_set_oid_numeric_print' => ['void', 'oid_format'=>'int'], 'snmp_set_oid_output_format' => ['bool', 'oid_format'=>'int'], 'snmp_set_quick_print' => ['bool', 'quick_print'=>'int'], 'snmp_set_valueretrieval' => ['bool', 'method='=>'int'], 'snmpget' => ['string|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmpgetnext' => ['string|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmprealwalk' => ['array|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmpset' => ['bool', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'mixed', 'timeout='=>'int', 'retries='=>'int'], 'snmpwalk' => ['array|false', 'host'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'snmpwalkoid' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'], 'SoapClient::__call' => ['mixed', 'function_name'=>'string', 'arguments'=>'array'], 'SoapClient::__construct' => ['void', 'wsdl'=>'mixed', 'options='=>'array|null'], 'SoapClient::__doRequest' => ['string|null', 'request'=>'string', 'location'=>'string', 'action'=>'string', 'version'=>'int', 'one_way='=>'int'], 'SoapClient::__getCookies' => ['array'], 'SoapClient::__getFunctions' => ['array|null'], 'SoapClient::__getLastRequest' => ['string|null'], 'SoapClient::__getLastRequestHeaders' => ['string|null'], 'SoapClient::__getLastResponse' => ['string|null'], 'SoapClient::__getLastResponseHeaders' => ['string|null'], 'SoapClient::__getTypes' => ['array|null'], 'SoapClient::__setCookie' => ['', 'name'=>'string', 'value='=>'string'], 'SoapClient::__setLocation' => ['string|null', 'new_location='=>'string'], 'SoapClient::__setSoapHeaders' => ['bool', 'soapheaders='=>''], 'SoapClient::__soapCall' => ['mixed', 'function_name'=>'string', 'arguments'=>'array', 'options='=>'array', 'input_headers='=>'SoapHeader|array', '&w_output_headers='=>'array'], 'SoapClient::SoapClient' => ['object', 'wsdl'=>'mixed', 'options='=>'array|null'], 'SoapFault::__construct' => ['void', 'faultcode'=>'string', 'string'=>'string', 'faultactor='=>'string', 'detail='=>'mixed', 'faultname='=>'string', 'headerfault='=>'mixed'], 'SoapFault::__toString' => ['string'], 'SoapFault::SoapFault' => ['object', 'faultcode'=>'string', 'string'=>'string', 'faultactor='=>'string', 'detail='=>'string', 'faultname='=>'string', 'headerfault='=>'string'], 'SoapHeader::__construct' => ['void', 'namespace'=>'string', 'name'=>'string', 'data='=>'mixed', 'mustunderstand='=>'bool', 'actor='=>'string'], 'SoapHeader::SoapHeader' => ['object', 'namespace'=>'string', 'name'=>'string', 'data='=>'mixed', 'mustunderstand='=>'bool', 'actor='=>'string'], 'SoapParam::__construct' => ['void', 'data'=>'mixed', 'name'=>'string'], 'SoapParam::SoapParam' => ['object', 'data'=>'mixed', 'name'=>'string'], 'SoapServer::__construct' => ['void', 'wsdl'=>'?string', 'options='=>'array'], 'SoapServer::addFunction' => ['void', 'functions'=>'mixed'], 'SoapServer::addSoapHeader' => ['void', 'object'=>'soapheader'], 'SoapServer::fault' => ['void', 'code'=>'string', 'string'=>'string', 'actor='=>'string', 'details='=>'string', 'name='=>'string'], 'SoapServer::getFunctions' => ['array'], 'SoapServer::handle' => ['void', 'soap_request='=>'string'], 'SoapServer::setClass' => ['void', 'class_name'=>'string', '...args='=>'mixed'], 'SoapServer::setObject' => ['void', 'obj'=>'object'], 'SoapServer::setPersistence' => ['void', 'mode'=>'int'], 'SoapServer::SoapServer' => ['object', 'wsdl'=>'?string', 'options='=>'array'], 'SoapVar::__construct' => ['void', 'data'=>'mixed', 'encoding'=>'int', 'type_name='=>'string|null', 'type_namespace='=>'string|null', 'node_name='=>'string|null', 'node_namespace='=>'string|null'], 'SoapVar::SoapVar' => ['object', 'data'=>'mixed', 'encoding'=>'int', 'type_name='=>'string|null', 'type_namespace='=>'string|null', 'node_name='=>'string|null', 'node_namespace='=>'string|null'], 'socket_accept' => ['resource|false', 'socket'=>'resource'], 'socket_addrinfo_bind' => ['resource|null|false', 'addrinfo'=>'resource'], 'socket_addrinfo_connect' => ['resource|null|false', 'addrinfo'=>'resource'], 'socket_addrinfo_explain' => ['array', 'addrinfo'=>'resource'], 'socket_addrinfo_lookup' => ['resource[]|false', 'node'=>'string', 'service='=>'mixed', 'hints='=>'array'], 'socket_bind' => ['bool', 'socket'=>'resource', 'addr'=>'string', 'port='=>'int'], 'socket_clear_error' => ['void', 'socket='=>'resource'], 'socket_close' => ['void', 'socket'=>'resource'], 'socket_cmsg_space' => ['int', 'level'=>'int', 'type'=>'int'], 'socket_connect' => ['bool', 'socket'=>'resource', 'addr'=>'string', 'port='=>'int'], 'socket_create' => ['resource|false', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int'], 'socket_create_listen' => ['resource|false', 'port'=>'int', 'backlog='=>'int'], 'socket_create_pair' => ['bool', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int', '&w_fd'=>'resource[]'], 'socket_export_stream' => ['resource|false', 'socket'=>'resource'], 'socket_get_option' => ['mixed', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int'], 'socket_getopt' => ['mixed', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int'], 'socket_getpeername' => ['bool', 'socket'=>'resource', '&w_addr'=>'string', '&w_port='=>'int'], 'socket_getsockname' => ['bool', 'socket'=>'resource', '&w_addr'=>'string', '&w_port='=>'int'], 'socket_import_stream' => ['resource|false', 'stream'=>'resource'], 'socket_last_error' => ['int', 'socket='=>'resource'], 'socket_listen' => ['bool', 'socket'=>'resource', 'backlog='=>'int'], 'socket_read' => ['string|false', 'socket'=>'resource', 'length'=>'int', 'type='=>'int'], 'socket_recv' => ['int|false', 'socket'=>'resource', '&w_buf'=>'string', 'len'=>'int', 'flags'=>'int'], 'socket_recvfrom' => ['int|false', 'socket'=>'resource', '&w_buf'=>'string', 'len'=>'int', 'flags'=>'int', '&w_name'=>'string', '&w_port='=>'int'], 'socket_recvmsg' => ['int|false', 'socket'=>'resource', '&w_message'=>'string', 'flags='=>'int'], 'socket_select' => ['int|false', '&w_read_fds'=>'resource[]|null', '&w_write_fds'=>'resource[]|null', '&w_except_fds'=>'resource[]|null', 'tv_sec'=>'int|null', 'tv_usec='=>'int|null'], 'socket_send' => ['int|false', 'socket'=>'resource', 'buf'=>'string', 'len'=>'int', 'flags'=>'int'], 'socket_sendmsg' => ['int|false', 'socket'=>'resource', 'message'=>'array', 'flags'=>'int'], 'socket_sendto' => ['int|false', 'socket'=>'resource', 'buf'=>'string', 'len'=>'int', 'flags'=>'int', 'addr'=>'string', 'port='=>'int'], 'socket_set_block' => ['bool', 'socket'=>'resource'], 'socket_set_nonblock' => ['bool', 'socket'=>'resource'], 'socket_set_option' => ['bool', 'socket'=>'resource', 'level'=>'int', 'optname'=>'int', 'optval'=>'int|string|array'], 'socket_shutdown' => ['bool', 'socket'=>'resource', 'how='=>'int'], 'socket_strerror' => ['string', 'errno'=>'int'], 'socket_write' => ['int|false', 'socket'=>'resource', 'buf'=>'string', 'length='=>'int'], 'socket_wsaprotocol_info_export' => ['string|false', 'stream'=>'resource', 'target_pid'=>'int'], 'socket_wsaprotocol_info_import' => ['resource|false', 'id'=>'string'], 'socket_wsaprotocol_info_release' => ['bool', 'id'=>'string'], 'Sodium\add' => ['', '&left'=>'string', 'right'=>'string'], 'Sodium\bin2hex' => ['string', 'binary'=>'string'], 'Sodium\compare' => ['int', 'left'=>'string', 'right'=>'string'], 'Sodium\crypto_aead_aes256gcm_decrypt' => ['string', 'msg'=>'string', 'nonce'=>'string', 'key'=>'string', 'ad='=>'string'], 'Sodium\crypto_aead_aes256gcm_encrypt' => ['string', 'msg'=>'string', 'nonce'=>'string', 'key'=>'string', 'ad='=>'string'], 'Sodium\crypto_aead_aes256gcm_is_available' => ['bool'], 'Sodium\crypto_aead_chacha20poly1305_decrypt' => ['string', 'msg'=>'string', 'nonce'=>'string', 'key'=>'string', 'ad='=>'string'], 'Sodium\crypto_aead_chacha20poly1305_encrypt' => ['string', 'msg'=>'string', 'nonce'=>'string', 'key'=>'string', 'ad='=>'string'], 'Sodium\crypto_auth' => ['string', 'msg'=>'string', 'key'=>'string'], 'Sodium\crypto_auth_verify' => ['bool', 'mac'=>'string', 'msg'=>'string', 'key'=>'string'], 'Sodium\crypto_box' => ['string', 'msg'=>'string', 'nonce'=>'string', 'keypair'=>'string'], 'Sodium\crypto_box_keypair' => ['string'], 'Sodium\crypto_box_keypair_from_secretkey_and_publickey' => ['string', 'secretkey'=>'string', 'publickey'=>'string'], 'Sodium\crypto_box_open' => ['string', 'msg'=>'string', 'nonce'=>'string', 'keypair'=>'string'], 'Sodium\crypto_box_publickey' => ['string', 'keypair'=>'string'], 'Sodium\crypto_box_publickey_from_secretkey' => ['string', 'secretkey'=>'string'], 'Sodium\crypto_box_seal' => ['string', 'message'=>'string', 'publickey'=>'string'], 'Sodium\crypto_box_seal_open' => ['string', 'encrypted'=>'string', 'keypair'=>'string'], 'Sodium\crypto_box_secretkey' => ['string', 'keypair'=>'string'], 'Sodium\crypto_box_seed_keypair' => ['string', 'seed'=>'string'], 'Sodium\crypto_generichash' => ['string', 'input'=>'string', 'key='=>'string', 'length='=>'int'], 'Sodium\crypto_generichash_final' => ['string', 'state'=>'string', 'length='=>'int'], 'Sodium\crypto_generichash_init' => ['string', 'key='=>'string', 'length='=>'int'], 'Sodium\crypto_generichash_update' => ['bool', '&hashState'=>'string', 'append'=>'string'], 'Sodium\crypto_kx' => ['string', 'secretkey'=>'string', 'publickey'=>'string', 'client_publickey'=>'string', 'server_publickey'=>'string'], 'Sodium\crypto_pwhash' => ['string', 'out_len'=>'int', 'passwd'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'Sodium\crypto_pwhash_scryptsalsa208sha256' => ['string', 'out_len'=>'int', 'passwd'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'Sodium\crypto_pwhash_scryptsalsa208sha256_str' => ['string', 'passwd'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'Sodium\crypto_pwhash_scryptsalsa208sha256_str_verify' => ['bool', 'hash'=>'string', 'passwd'=>'string'], 'Sodium\crypto_pwhash_str' => ['string', 'passwd'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'Sodium\crypto_pwhash_str_verify' => ['bool', 'hash'=>'string', 'passwd'=>'string'], 'Sodium\crypto_scalarmult' => ['string', 'ecdhA'=>'string', 'ecdhB'=>'string'], 'Sodium\crypto_scalarmult_base' => ['string', 'sk'=>'string'], 'Sodium\crypto_secretbox' => ['string', 'plaintext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'Sodium\crypto_secretbox_open' => ['string', 'ciphertext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'Sodium\crypto_shorthash' => ['string', 'message'=>'string', 'key'=>'string'], 'Sodium\crypto_sign' => ['string', 'message'=>'string', 'secretkey'=>'string'], 'Sodium\crypto_sign_detached' => ['string', 'message'=>'string', 'secretkey'=>'string'], 'Sodium\crypto_sign_ed25519_pk_to_curve25519' => ['string', 'sign_pk'=>'string'], 'Sodium\crypto_sign_ed25519_sk_to_curve25519' => ['string', 'sign_sk'=>'string'], 'Sodium\crypto_sign_keypair' => ['string'], 'Sodium\crypto_sign_keypair_from_secretkey_and_publickey' => ['string', 'secretkey'=>'string', 'publickey'=>'string'], 'Sodium\crypto_sign_open' => ['string|false', 'signed_message'=>'string', 'publickey'=>'string'], 'Sodium\crypto_sign_publickey' => ['string', 'keypair'=>'string'], 'Sodium\crypto_sign_publickey_from_secretkey' => ['string', 'secretkey'=>'string'], 'Sodium\crypto_sign_secretkey' => ['string', 'keypair'=>'string'], 'Sodium\crypto_sign_seed_keypair' => ['string', 'seed'=>'string'], 'Sodium\crypto_sign_verify_detached' => ['bool', 'signature'=>'string', 'msg'=>'string', 'publickey'=>'string'], 'Sodium\crypto_stream' => ['string', 'length'=>'int', 'nonce'=>'string', 'key'=>'string'], 'Sodium\crypto_stream_xor' => ['string', 'plaintext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'Sodium\hex2bin' => ['string', 'hex'=>'string'], 'Sodium\increment' => ['string', '&nonce'=>'string'], 'Sodium\library_version_major' => ['int'], 'Sodium\library_version_minor' => ['int'], 'Sodium\memcmp' => ['int', 'left'=>'string', 'right'=>'string'], 'Sodium\memzero' => ['', '&target'=>'string'], 'Sodium\randombytes_buf' => ['string', 'length'=>'int'], 'Sodium\randombytes_random16' => ['int|string'], 'Sodium\randombytes_uniform' => ['int', 'upperBoundNonInclusive'=>'int'], 'Sodium\version_string' => ['string'], 'sodium_add' => ['string', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_base642bin' => ['string', 'base64'=>'string', 'variant'=>'int', 'ignore='=>'string'], 'sodium_bin2base64' => ['string', 'binary'=>'string', 'variant'=>'int'], 'sodium_bin2hex' => ['string', 'binary'=>'string'], 'sodium_compare' => ['int', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_crypto_aead_aes256gcm_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_aes256gcm_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_aes256gcm_is_available' => ['bool'], 'sodium_crypto_aead_aes256gcm_keygen' => ['string'], 'sodium_crypto_aead_chacha20poly1305_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_chacha20poly1305_ietf_keygen' => ['string'], 'sodium_crypto_aead_chacha20poly1305_keygen' => ['string'], 'sodium_crypto_aead_xchacha20poly1305_ietf_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_xchacha20poly1305_ietf_encrypt' => ['string', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_aead_xchacha20poly1305_ietf_keygen' => ['string'], 'sodium_crypto_auth' => ['string', 'message'=>'string', 'key'=>'string'], 'sodium_crypto_auth_keygen' => ['string'], 'sodium_crypto_auth_verify' => ['bool', 'mac'=>'string', 'message'=>'string', 'key'=>'string'], 'sodium_crypto_box' => ['string', 'string'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_box_keypair' => ['string'], 'sodium_crypto_box_keypair_from_secretkey_and_publickey' => ['string', 'secret_key'=>'string', 'public_key'=>'string'], 'sodium_crypto_box_open' => ['string|false', 'message'=>'string', 'nonce'=>'string', 'message_keypair'=>'string'], 'sodium_crypto_box_publickey' => ['string', 'keypair'=>'string'], 'sodium_crypto_box_publickey_from_secretkey' => ['string', 'secretkey'=>'string'], 'sodium_crypto_box_seal' => ['string', 'message'=>'string', 'publickey'=>'string'], 'sodium_crypto_box_seal_open' => ['string|false', 'message'=>'string', 'recipient_keypair'=>'string'], 'sodium_crypto_box_secretkey' => ['string', 'keypair'=>'string'], 'sodium_crypto_box_seed_keypair' => ['string', 'seed'=>'string'], 'sodium_crypto_generichash' => ['non-empty-string', 'msg'=>'string', 'key='=>'?string', 'length='=>'?int'], 'sodium_crypto_generichash_final' => ['non-empty-string', 'state'=>'non-empty-string', 'length='=>'?int'], 'sodium_crypto_generichash_init' => ['non-empty-string', 'key='=>'?string', 'length='=>'?int'], 'sodium_crypto_generichash_keygen' => ['non-empty-string'], 'sodium_crypto_generichash_update' => ['bool', 'state'=>'non-empty-string', 'string'=>'string'], 'sodium_crypto_kdf_derive_from_key' => ['string', 'subkey_len'=>'int', 'subkey_id'=>'int', 'context'=>'string', 'key'=>'string'], 'sodium_crypto_kdf_keygen' => ['string'], 'sodium_crypto_kx' => ['string', 'secretkey'=>'string', 'publickey'=>'string', 'client_publickey'=>'string', 'server_publickey'=>'string'], 'sodium_crypto_kx_client_session_keys' => ['array', 'client_keypair'=>'string', 'server_key'=>'string'], 'sodium_crypto_kx_keypair' => ['string'], 'sodium_crypto_kx_publickey' => ['string', 'keypair'=>'string'], 'sodium_crypto_kx_secretkey' => ['string', 'keypair'=>'string'], 'sodium_crypto_kx_seed_keypair' => ['string', 'seed'=>'string'], 'sodium_crypto_kx_server_session_keys' => ['array', 'server_keypair'=>'string', 'client_key'=>'string'], 'sodium_crypto_pwhash' => ['string', 'length'=>'int', 'password'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int', 'alg='=>'int'], 'sodium_crypto_pwhash_scryptsalsa208sha256' => ['string', 'length'=>'int', 'password'=>'string', 'salt'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_scryptsalsa208sha256_str' => ['string', 'password'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_scryptsalsa208sha256_str_verify' => ['bool', 'hash'=>'string', 'password'=>'string'], 'sodium_crypto_pwhash_str' => ['string', 'password'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_str_needs_rehash' => ['bool', 'password'=>'string', 'opslimit'=>'int', 'memlimit'=>'int'], 'sodium_crypto_pwhash_str_verify' => ['bool', 'hash'=>'string', 'password'=>'string'], 'sodium_crypto_scalarmult' => ['string', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_crypto_scalarmult_base' => ['string', 'key'=>'string'], 'sodium_crypto_secretbox' => ['string', 'plaintext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_secretbox_keygen' => ['string'], 'sodium_crypto_secretbox_open' => ['string|false', 'ciphertext'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_init_pull' => ['string', 'header'=>'string', 'key'=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_init_push' => ['array', 'key'=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_keygen' => ['string'], 'sodium_crypto_secretstream_xchacha20poly1305_pull' => ['array|false', 'state'=>'string', 'c'=>'string', 'ad='=>'string'], 'sodium_crypto_secretstream_xchacha20poly1305_push' => ['string', 'state'=>'string', 'msg'=>'string', 'ad='=>'string', 'tag='=>'int'], 'sodium_crypto_secretstream_xchacha20poly1305_rekey' => ['void', 'state'=>'string'], 'sodium_crypto_shorthash' => ['string', 'message'=>'string', 'key'=>'string'], 'sodium_crypto_shorthash_keygen' => ['string'], 'sodium_crypto_sign' => ['non-empty-string', 'message'=>'string', 'secretkey'=>'non-empty-string'], 'sodium_crypto_sign_detached' => ['non-empty-string', 'message'=>'string', 'secretkey'=>'non-empty-string'], 'sodium_crypto_sign_ed25519_pk_to_curve25519' => ['non-empty-string', 'ed25519pk'=>'non-empty-string'], 'sodium_crypto_sign_ed25519_sk_to_curve25519' => ['non-empty-string', 'ed25519sk'=>'non-empty-string'], 'sodium_crypto_sign_keypair' => ['non-empty-string'], 'sodium_crypto_sign_keypair_from_secretkey_and_publickey' => ['non-empty-string', 'secret_key'=>'non-empty-string', 'public_key'=>'non-empty-string'], 'sodium_crypto_sign_open' => ['string|false', 'message'=>'string', 'publickey'=>'non-empty-string'], 'sodium_crypto_sign_publickey' => ['non-empty-string', 'keypair'=>'non-empty-string'], 'sodium_crypto_sign_publickey_from_secretkey' => ['non-empty-string', 'secretkey'=>'non-empty-string'], 'sodium_crypto_sign_secretkey' => ['non-empty-string', 'keypair'=>'non-empty-string'], 'sodium_crypto_sign_seed_keypair' => ['non-empty-string', 'seed'=>'non-empty-string'], 'sodium_crypto_sign_verify_detached' => ['bool', 'signature'=>'non-empty-string', 'message'=>'string', 'publickey'=>'non-empty-string'], 'sodium_crypto_stream' => ['string', 'length'=>'int', 'nonce'=>'string', 'key'=>'string'], 'sodium_crypto_stream_keygen' => ['string'], 'sodium_crypto_stream_xor' => ['string', 'message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'sodium_hex2bin' => ['string', 'hex'=>'string', 'ignore='=>'string'], 'sodium_increment' => ['string', '&binary_string'=>'string'], 'sodium_library_version_major' => ['int'], 'sodium_library_version_minor' => ['int'], 'sodium_memcmp' => ['int', 'string_1'=>'string', 'string_2'=>'string'], 'sodium_memzero' => ['void', '&secret'=>'string'], 'sodium_pad' => ['string', 'unpadded'=>'string', 'length'=>'int'], 'sodium_randombytes_buf' => ['string', 'length'=>'int'], 'sodium_randombytes_random16' => ['int|string'], 'sodium_randombytes_uniform' => ['int', 'upperBoundNonInclusive'=>'int'], 'sodium_unpad' => ['string', 'padded'=>'string', 'length'=>'int'], 'sodium_version_string' => ['string'], 'solid_fetch_prev' => ['bool', 'result_id'=>''], 'solr_get_version' => ['string'], 'SolrClient::__construct' => ['void', 'clientOptions'=>'array'], 'SolrClient::__destruct' => [''], 'SolrClient::addDocument' => ['SolrUpdateResponse', 'doc'=>'solrinputdocument', 'allowdups='=>'bool', 'commitwithin='=>'int'], 'SolrClient::addDocuments' => ['SolrUpdateResponse', 'docs'=>'array', 'allowdups='=>'bool', 'commitwithin='=>'int'], 'SolrClient::commit' => ['SolrUpdateResponse', 'maxsegments='=>'int', 'waitflush='=>'bool', 'waitsearcher='=>'bool'], 'SolrClient::deleteById' => ['SolrUpdateResponse', 'id'=>'string'], 'SolrClient::deleteByIds' => ['SolrUpdateResponse', 'ids'=>'array'], 'SolrClient::deleteByQueries' => ['SolrUpdateResponse', 'queries'=>'array'], 'SolrClient::deleteByQuery' => ['SolrUpdateResponse', 'query'=>'string'], 'SolrClient::getById' => ['SolrQueryResponse', 'id'=>'string'], 'SolrClient::getByIds' => ['SolrQueryResponse', 'ids'=>'array'], 'SolrClient::getDebug' => ['string'], 'SolrClient::getOptions' => ['array'], 'SolrClient::optimize' => ['SolrUpdateResponse', 'maxsegments='=>'int', 'waitflush='=>'bool', 'waitsearcher='=>'bool'], 'SolrClient::ping' => ['SolrPingResponse'], 'SolrClient::query' => ['SolrQueryResponse', 'query'=>'solrparams'], 'SolrClient::request' => ['SolrUpdateResponse', 'raw_request'=>'string'], 'SolrClient::rollback' => ['SolrUpdateResponse'], 'SolrClient::setResponseWriter' => ['void', 'responsewriter'=>'string'], 'SolrClient::setServlet' => ['bool', 'type'=>'int', 'value'=>'string'], 'SolrClient::system' => ['void'], 'SolrClient::threads' => ['void'], 'SolrClientException::getInternalInfo' => ['array'], 'SolrCollapseFunction::__toString' => ['string'], 'SolrCollapseFunction::getField' => ['string'], 'SolrCollapseFunction::getHint' => ['string'], 'SolrCollapseFunction::getMax' => ['string'], 'SolrCollapseFunction::getMin' => ['string'], 'SolrCollapseFunction::getNullPolicy' => ['string'], 'SolrCollapseFunction::getSize' => ['int'], 'SolrCollapseFunction::setField' => ['SolrCollapseFunction', 'fieldName'=>'string'], 'SolrCollapseFunction::setHint' => ['SolrCollapseFunction', 'hint'=>'string'], 'SolrCollapseFunction::setMax' => ['SolrCollapseFunction', 'max'=>'string'], 'SolrCollapseFunction::setMin' => ['SolrCollapseFunction', 'min'=>'string'], 'SolrCollapseFunction::setNullPolicy' => ['SolrCollapseFunction', 'nullPolicy'=>'string'], 'SolrCollapseFunction::setSize' => ['SolrCollapseFunction', 'size'=>'int'], 'SolrDisMaxQuery::__construct' => ['void', 'q='=>'string'], 'SolrDisMaxQuery::addBigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost'=>'string', 'slop='=>'string'], 'SolrDisMaxQuery::addBoostQuery' => ['SolrDisMaxQuery', 'field'=>'string', 'value'=>'string', 'boost='=>'string'], 'SolrDisMaxQuery::addExpandFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrDisMaxQuery::addExpandSortField' => ['SolrQuery', 'field'=>'string', 'order'=>'string'], 'SolrDisMaxQuery::addFacetDateField' => ['SolrQuery', 'dateField'=>'string'], 'SolrDisMaxQuery::addFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::addFacetField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addFacetQuery' => ['SolrQuery', 'facetQuery'=>'string'], 'SolrDisMaxQuery::addField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrDisMaxQuery::addGroupField' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::addGroupFunction' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::addGroupQuery' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::addGroupSortField' => ['SolrQuery', 'field'=>'string', 'order'=>'int'], 'SolrDisMaxQuery::addHighlightField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addMltField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addMltQueryField' => ['SolrQuery', 'field'=>'string', 'boost'=>'float'], 'SolrDisMaxQuery::addParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrDisMaxQuery::addPhraseField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost'=>'string', 'slop='=>'string'], 'SolrDisMaxQuery::addQueryField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost='=>'string'], 'SolrDisMaxQuery::addSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'int'], 'SolrDisMaxQuery::addStatsFacet' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addStatsField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::addTrigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string', 'boost'=>'string', 'slop='=>'string'], 'SolrDisMaxQuery::addUserField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::collapse' => ['SolrQuery', 'collapseFunction'=>'SolrCollapseFunction'], 'SolrDisMaxQuery::get' => ['mixed', 'param_name'=>'string'], 'SolrDisMaxQuery::getExpand' => ['bool'], 'SolrDisMaxQuery::getExpandFilterQueries' => ['array'], 'SolrDisMaxQuery::getExpandQuery' => ['array'], 'SolrDisMaxQuery::getExpandRows' => ['int'], 'SolrDisMaxQuery::getExpandSortFields' => ['array'], 'SolrDisMaxQuery::getFacet' => ['bool'], 'SolrDisMaxQuery::getFacetDateEnd' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetDateFields' => ['array'], 'SolrDisMaxQuery::getFacetDateGap' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetDateHardEnd' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetDateOther' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetDateStart' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetFields' => ['array'], 'SolrDisMaxQuery::getFacetLimit' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetMethod' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetMinCount' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetMissing' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetOffset' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetPrefix' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getFacetQueries' => ['string'], 'SolrDisMaxQuery::getFacetSort' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getFields' => ['string'], 'SolrDisMaxQuery::getFilterQueries' => ['string'], 'SolrDisMaxQuery::getGroup' => ['bool'], 'SolrDisMaxQuery::getGroupCachePercent' => ['int'], 'SolrDisMaxQuery::getGroupFacet' => ['bool'], 'SolrDisMaxQuery::getGroupFields' => ['array'], 'SolrDisMaxQuery::getGroupFormat' => ['string'], 'SolrDisMaxQuery::getGroupFunctions' => ['array'], 'SolrDisMaxQuery::getGroupLimit' => ['int'], 'SolrDisMaxQuery::getGroupMain' => ['bool'], 'SolrDisMaxQuery::getGroupNGroups' => ['bool'], 'SolrDisMaxQuery::getGroupOffset' => ['bool'], 'SolrDisMaxQuery::getGroupQueries' => ['array'], 'SolrDisMaxQuery::getGroupSortFields' => ['array'], 'SolrDisMaxQuery::getGroupTruncate' => ['bool'], 'SolrDisMaxQuery::getHighlight' => ['bool'], 'SolrDisMaxQuery::getHighlightAlternateField' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightFields' => ['array'], 'SolrDisMaxQuery::getHighlightFormatter' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightFragmenter' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightFragsize' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightHighlightMultiTerm' => ['bool'], 'SolrDisMaxQuery::getHighlightMaxAlternateFieldLength' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightMaxAnalyzedChars' => ['int'], 'SolrDisMaxQuery::getHighlightMergeContiguous' => ['bool', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightRegexMaxAnalyzedChars' => ['int'], 'SolrDisMaxQuery::getHighlightRegexPattern' => ['string'], 'SolrDisMaxQuery::getHighlightRegexSlop' => ['float'], 'SolrDisMaxQuery::getHighlightRequireFieldMatch' => ['bool'], 'SolrDisMaxQuery::getHighlightSimplePost' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightSimplePre' => ['string', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightSnippets' => ['int', 'field_override'=>'string'], 'SolrDisMaxQuery::getHighlightUsePhraseHighlighter' => ['bool'], 'SolrDisMaxQuery::getMlt' => ['bool'], 'SolrDisMaxQuery::getMltBoost' => ['bool'], 'SolrDisMaxQuery::getMltCount' => ['int'], 'SolrDisMaxQuery::getMltFields' => ['array'], 'SolrDisMaxQuery::getMltMaxNumQueryTerms' => ['int'], 'SolrDisMaxQuery::getMltMaxNumTokens' => ['int'], 'SolrDisMaxQuery::getMltMaxWordLength' => ['int'], 'SolrDisMaxQuery::getMltMinDocFrequency' => ['int'], 'SolrDisMaxQuery::getMltMinTermFrequency' => ['int'], 'SolrDisMaxQuery::getMltMinWordLength' => ['int'], 'SolrDisMaxQuery::getMltQueryFields' => ['array'], 'SolrDisMaxQuery::getParam' => ['mixed', 'param_name'=>'string'], 'SolrDisMaxQuery::getParams' => ['array'], 'SolrDisMaxQuery::getPreparedParams' => ['array'], 'SolrDisMaxQuery::getQuery' => ['string'], 'SolrDisMaxQuery::getRows' => ['int'], 'SolrDisMaxQuery::getSortFields' => ['array'], 'SolrDisMaxQuery::getStart' => ['int'], 'SolrDisMaxQuery::getStats' => ['bool'], 'SolrDisMaxQuery::getStatsFacets' => ['array'], 'SolrDisMaxQuery::getStatsFields' => ['array'], 'SolrDisMaxQuery::getTerms' => ['bool'], 'SolrDisMaxQuery::getTermsField' => ['string'], 'SolrDisMaxQuery::getTermsIncludeLowerBound' => ['bool'], 'SolrDisMaxQuery::getTermsIncludeUpperBound' => ['bool'], 'SolrDisMaxQuery::getTermsLimit' => ['int'], 'SolrDisMaxQuery::getTermsLowerBound' => ['string'], 'SolrDisMaxQuery::getTermsMaxCount' => ['int'], 'SolrDisMaxQuery::getTermsMinCount' => ['int'], 'SolrDisMaxQuery::getTermsPrefix' => ['string'], 'SolrDisMaxQuery::getTermsReturnRaw' => ['bool'], 'SolrDisMaxQuery::getTermsSort' => ['int'], 'SolrDisMaxQuery::getTermsUpperBound' => ['string'], 'SolrDisMaxQuery::getTimeAllowed' => ['int'], 'SolrDisMaxQuery::removeBigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeBoostQuery' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeExpandFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrDisMaxQuery::removeExpandSortField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeFacetDateField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::removeFacetField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeFacetQuery' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::removeField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrDisMaxQuery::removeHighlightField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeMltField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeMltQueryField' => ['SolrQuery', 'queryField'=>'string'], 'SolrDisMaxQuery::removePhraseField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeQueryField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeSortField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeStatsFacet' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::removeStatsField' => ['SolrQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeTrigramPhraseField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::removeUserField' => ['SolrDisMaxQuery', 'field'=>'string'], 'SolrDisMaxQuery::serialize' => ['string'], 'SolrDisMaxQuery::set' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrDisMaxQuery::setBigramPhraseFields' => ['SolrDisMaxQuery', 'fields'=>'string'], 'SolrDisMaxQuery::setBigramPhraseSlop' => ['SolrDisMaxQuery', 'slop'=>'string'], 'SolrDisMaxQuery::setBoostFunction' => ['SolrDisMaxQuery', 'function'=>'string'], 'SolrDisMaxQuery::setBoostQuery' => ['SolrDisMaxQuery', 'q'=>'string'], 'SolrDisMaxQuery::setEchoHandler' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setEchoParams' => ['SolrQuery', 'type'=>'string'], 'SolrDisMaxQuery::setExpand' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setExpandQuery' => ['SolrQuery', 'q'=>'string'], 'SolrDisMaxQuery::setExpandRows' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setExplainOther' => ['SolrQuery', 'query'=>'string'], 'SolrDisMaxQuery::setFacet' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setFacetDateEnd' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetDateGap' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetDateHardEnd' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetDateStart' => ['SolrQuery', 'value'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetEnumCacheMinDefaultFrequency' => ['SolrQuery', 'frequency'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetLimit' => ['SolrQuery', 'limit'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetMethod' => ['SolrQuery', 'method'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetMinCount' => ['SolrQuery', 'mincount'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetMissing' => ['SolrQuery', 'flag'=>'bool', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetOffset' => ['SolrQuery', 'offset'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetPrefix' => ['SolrQuery', 'prefix'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setFacetSort' => ['SolrQuery', 'facetSort'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setGroup' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setGroupCachePercent' => ['SolrQuery', 'percent'=>'int'], 'SolrDisMaxQuery::setGroupFacet' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setGroupFormat' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::setGroupLimit' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setGroupMain' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::setGroupNGroups' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setGroupOffset' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setGroupTruncate' => ['SolrQuery', 'value'=>'bool'], 'SolrDisMaxQuery::setHighlight' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setHighlightAlternateField' => ['SolrQuery', 'field'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightFormatter' => ['SolrQuery', 'formatter'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightFragmenter' => ['SolrQuery', 'fragmenter'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightFragsize' => ['SolrQuery', 'size'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightHighlightMultiTerm' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setHighlightMaxAlternateFieldLength' => ['SolrQuery', 'fieldLength'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightMaxAnalyzedChars' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setHighlightMergeContiguous' => ['SolrQuery', 'flag'=>'bool', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightRegexMaxAnalyzedChars' => ['SolrQuery', 'maxAnalyzedChars'=>'int'], 'SolrDisMaxQuery::setHighlightRegexPattern' => ['SolrQuery', 'value'=>'string'], 'SolrDisMaxQuery::setHighlightRegexSlop' => ['SolrQuery', 'factor'=>'float'], 'SolrDisMaxQuery::setHighlightRequireFieldMatch' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setHighlightSimplePost' => ['SolrQuery', 'simplePost'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightSimplePre' => ['SolrQuery', 'simplePre'=>'string', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightSnippets' => ['SolrQuery', 'value'=>'int', 'field_override'=>'string'], 'SolrDisMaxQuery::setHighlightUsePhraseHighlighter' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setMinimumMatch' => ['SolrDisMaxQuery', 'value'=>'string'], 'SolrDisMaxQuery::setMlt' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setMltBoost' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setMltCount' => ['SolrQuery', 'count'=>'int'], 'SolrDisMaxQuery::setMltMaxNumQueryTerms' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setMltMaxNumTokens' => ['SolrQuery', 'value'=>'int'], 'SolrDisMaxQuery::setMltMaxWordLength' => ['SolrQuery', 'maxWordLength'=>'int'], 'SolrDisMaxQuery::setMltMinDocFrequency' => ['SolrQuery', 'minDocFrequency'=>'int'], 'SolrDisMaxQuery::setMltMinTermFrequency' => ['SolrQuery', 'minTermFrequency'=>'int'], 'SolrDisMaxQuery::setMltMinWordLength' => ['SolrQuery', 'minWordLength'=>'int'], 'SolrDisMaxQuery::setOmitHeader' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setParam' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrDisMaxQuery::setPhraseFields' => ['SolrDisMaxQuery', 'fields'=>'string'], 'SolrDisMaxQuery::setPhraseSlop' => ['SolrDisMaxQuery', 'slop'=>'string'], 'SolrDisMaxQuery::setQuery' => ['SolrQuery', 'query'=>'string'], 'SolrDisMaxQuery::setQueryAlt' => ['SolrDisMaxQuery', 'q'=>'string'], 'SolrDisMaxQuery::setQueryPhraseSlop' => ['SolrDisMaxQuery', 'slop'=>'string'], 'SolrDisMaxQuery::setRows' => ['SolrQuery', 'rows'=>'int'], 'SolrDisMaxQuery::setShowDebugInfo' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setStart' => ['SolrQuery', 'start'=>'int'], 'SolrDisMaxQuery::setStats' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTerms' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTermsField' => ['SolrQuery', 'fieldname'=>'string'], 'SolrDisMaxQuery::setTermsIncludeLowerBound' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTermsIncludeUpperBound' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTermsLimit' => ['SolrQuery', 'limit'=>'int'], 'SolrDisMaxQuery::setTermsLowerBound' => ['SolrQuery', 'lowerBound'=>'string'], 'SolrDisMaxQuery::setTermsMaxCount' => ['SolrQuery', 'frequency'=>'int'], 'SolrDisMaxQuery::setTermsMinCount' => ['SolrQuery', 'frequency'=>'int'], 'SolrDisMaxQuery::setTermsPrefix' => ['SolrQuery', 'prefix'=>'string'], 'SolrDisMaxQuery::setTermsReturnRaw' => ['SolrQuery', 'flag'=>'bool'], 'SolrDisMaxQuery::setTermsSort' => ['SolrQuery', 'sortType'=>'int'], 'SolrDisMaxQuery::setTermsUpperBound' => ['SolrQuery', 'upperBound'=>'string'], 'SolrDisMaxQuery::setTieBreaker' => ['SolrDisMaxQuery', 'tieBreaker'=>'string'], 'SolrDisMaxQuery::setTimeAllowed' => ['SolrQuery', 'timeAllowed'=>'int'], 'SolrDisMaxQuery::setTrigramPhraseFields' => ['SolrDisMaxQuery', 'fields'=>'string'], 'SolrDisMaxQuery::setTrigramPhraseSlop' => ['SolrDisMaxQuery', 'slop'=>'string'], 'SolrDisMaxQuery::setUserFields' => ['SolrDisMaxQuery', 'fields'=>'string'], 'SolrDisMaxQuery::toString' => ['string', 'url_encode='=>'bool|false'], 'SolrDisMaxQuery::unserialize' => ['void', 'serialized'=>'string'], 'SolrDisMaxQuery::useDisMaxQueryParser' => ['SolrDisMaxQuery'], 'SolrDisMaxQuery::useEDisMaxQueryParser' => ['SolrDisMaxQuery'], 'SolrDocument::__clone' => ['void'], 'SolrDocument::__construct' => ['void'], 'SolrDocument::__destruct' => [''], 'SolrDocument::__get' => ['SolrDocumentField', 'fieldname'=>'string'], 'SolrDocument::__isset' => ['bool', 'fieldname'=>'string'], 'SolrDocument::__set' => ['bool', 'fieldname'=>'string', 'fieldvalue'=>'string'], 'SolrDocument::__unset' => ['bool', 'fieldname'=>'string'], 'SolrDocument::addField' => ['bool', 'fieldname'=>'string', 'fieldvalue'=>'string'], 'SolrDocument::clear' => ['bool'], 'SolrDocument::current' => ['SolrDocumentField'], 'SolrDocument::deleteField' => ['bool', 'fieldname'=>'string'], 'SolrDocument::fieldExists' => ['bool', 'fieldname'=>'string'], 'SolrDocument::getChildDocuments' => ['array'], 'SolrDocument::getChildDocumentsCount' => ['int'], 'SolrDocument::getField' => ['SolrDocumentField', 'fieldname'=>'string'], 'SolrDocument::getFieldCount' => ['int'], 'SolrDocument::getFieldNames' => ['array'], 'SolrDocument::getInputDocument' => ['SolrInputDocument'], 'SolrDocument::hasChildDocuments' => ['bool'], 'SolrDocument::key' => ['string'], 'SolrDocument::merge' => ['bool', 'sourcedoc'=>'solrdocument', 'overwrite='=>'bool'], 'SolrDocument::next' => ['void'], 'SolrDocument::offsetExists' => ['bool', 'fieldname'=>'string'], 'SolrDocument::offsetGet' => ['SolrDocumentField', 'fieldname'=>'string'], 'SolrDocument::offsetSet' => ['void', 'fieldname'=>'string', 'fieldvalue'=>'string'], 'SolrDocument::offsetUnset' => ['void', 'fieldname'=>'string'], 'SolrDocument::reset' => ['bool'], 'SolrDocument::rewind' => ['void'], 'SolrDocument::serialize' => ['string'], 'SolrDocument::sort' => ['bool', 'sortorderby'=>'int', 'sortdirection='=>'int'], 'SolrDocument::toArray' => ['array'], 'SolrDocument::unserialize' => ['void', 'serialized'=>'string'], 'SolrDocument::valid' => ['bool'], 'SolrDocumentField::__construct' => ['void'], 'SolrDocumentField::__destruct' => [''], 'SolrException::__clone' => ['void'], 'SolrException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Exception)|(?Throwable)'], 'SolrException::__toString' => ['string'], 'SolrException::__wakeup' => ['void'], 'SolrException::getCode' => ['int'], 'SolrException::getFile' => ['string'], 'SolrException::getInternalInfo' => ['array'], 'SolrException::getLine' => ['int'], 'SolrException::getMessage' => ['string'], 'SolrException::getPrevious' => ['Exception|Throwable'], 'SolrException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'SolrException::getTraceAsString' => ['string'], 'SolrGenericResponse::__construct' => ['void'], 'SolrGenericResponse::__destruct' => [''], 'SolrGenericResponse::getDigestedResponse' => ['string'], 'SolrGenericResponse::getHttpStatus' => ['int'], 'SolrGenericResponse::getHttpStatusMessage' => ['string'], 'SolrGenericResponse::getRawRequest' => ['string'], 'SolrGenericResponse::getRawRequestHeaders' => ['string'], 'SolrGenericResponse::getRawResponse' => ['string'], 'SolrGenericResponse::getRawResponseHeaders' => ['string'], 'SolrGenericResponse::getRequestUrl' => ['string'], 'SolrGenericResponse::getResponse' => ['SolrObject'], 'SolrGenericResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrGenericResponse::success' => ['bool'], 'SolrIllegalArgumentException::__clone' => ['void'], 'SolrIllegalArgumentException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Exception)|(?Throwable)'], 'SolrIllegalArgumentException::__toString' => ['string'], 'SolrIllegalArgumentException::__wakeup' => ['void'], 'SolrIllegalArgumentException::getCode' => ['int'], 'SolrIllegalArgumentException::getFile' => ['string'], 'SolrIllegalArgumentException::getInternalInfo' => ['array'], 'SolrIllegalArgumentException::getLine' => ['int'], 'SolrIllegalArgumentException::getMessage' => ['string'], 'SolrIllegalArgumentException::getPrevious' => ['Exception|Throwable'], 'SolrIllegalArgumentException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'SolrIllegalArgumentException::getTraceAsString' => ['string'], 'SolrIllegalOperationException::__clone' => ['void'], 'SolrIllegalOperationException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Exception)|(?Throwable)'], 'SolrIllegalOperationException::__toString' => ['string'], 'SolrIllegalOperationException::__wakeup' => ['void'], 'SolrIllegalOperationException::getCode' => ['int'], 'SolrIllegalOperationException::getFile' => ['string'], 'SolrIllegalOperationException::getInternalInfo' => ['array'], 'SolrIllegalOperationException::getLine' => ['int'], 'SolrIllegalOperationException::getMessage' => ['string'], 'SolrIllegalOperationException::getPrevious' => ['Exception|Throwable'], 'SolrIllegalOperationException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'SolrIllegalOperationException::getTraceAsString' => ['string'], 'SolrInputDocument::__clone' => ['void'], 'SolrInputDocument::__construct' => ['void'], 'SolrInputDocument::__destruct' => [''], 'SolrInputDocument::addChildDocument' => ['void', 'child'=>'SolrInputDocument'], 'SolrInputDocument::addChildDocuments' => ['void', 'docs'=>'array'], 'SolrInputDocument::addField' => ['bool', 'fieldname'=>'string', 'fieldvalue'=>'string', 'fieldboostvalue='=>'float'], 'SolrInputDocument::clear' => ['bool'], 'SolrInputDocument::deleteField' => ['bool', 'fieldname'=>'string'], 'SolrInputDocument::fieldExists' => ['bool', 'fieldname'=>'string'], 'SolrInputDocument::getBoost' => ['float'], 'SolrInputDocument::getChildDocuments' => ['array'], 'SolrInputDocument::getChildDocumentsCount' => ['int'], 'SolrInputDocument::getField' => ['SolrDocumentField', 'fieldname'=>'string'], 'SolrInputDocument::getFieldBoost' => ['float', 'fieldname'=>'string'], 'SolrInputDocument::getFieldCount' => ['int'], 'SolrInputDocument::getFieldNames' => ['array'], 'SolrInputDocument::hasChildDocuments' => ['bool'], 'SolrInputDocument::merge' => ['bool', 'sourcedoc'=>'solrinputdocument', 'overwrite='=>'bool'], 'SolrInputDocument::reset' => ['bool'], 'SolrInputDocument::setBoost' => ['bool', 'documentboostvalue'=>'float'], 'SolrInputDocument::setFieldBoost' => ['bool', 'fieldname'=>'string', 'fieldboostvalue'=>'float'], 'SolrInputDocument::sort' => ['bool', 'sortorderby'=>'int', 'sortdirection='=>'int'], 'SolrInputDocument::toArray' => ['array'], 'SolrModifiableParams::__construct' => ['void'], 'SolrModifiableParams::__destruct' => [''], 'SolrModifiableParams::add' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrModifiableParams::addParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrModifiableParams::get' => ['mixed', 'param_name'=>'string'], 'SolrModifiableParams::getParam' => ['mixed', 'param_name'=>'string'], 'SolrModifiableParams::getParams' => ['array'], 'SolrModifiableParams::getPreparedParams' => ['array'], 'SolrModifiableParams::serialize' => ['string'], 'SolrModifiableParams::set' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrModifiableParams::setParam' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrModifiableParams::toString' => ['string', 'url_encode='=>'bool|false'], 'SolrModifiableParams::unserialize' => ['void', 'serialized'=>'string'], 'SolrObject::__construct' => ['void'], 'SolrObject::__destruct' => [''], 'SolrObject::getPropertyNames' => ['array'], 'SolrObject::offsetExists' => ['bool', 'property_name'=>'string'], 'SolrObject::offsetGet' => ['mixed', 'property_name'=>'string'], 'SolrObject::offsetSet' => ['void', 'property_name'=>'string', 'property_value'=>'string'], 'SolrObject::offsetUnset' => ['void', 'property_name'=>'string'], 'SolrParams::__construct' => ['void'], 'SolrParams::add' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrParams::addParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrParams::get' => ['mixed', 'param_name'=>'string'], 'SolrParams::getParam' => ['mixed', 'param_name='=>'string'], 'SolrParams::getParams' => ['array'], 'SolrParams::getPreparedParams' => ['array'], 'SolrParams::serialize' => ['string'], 'SolrParams::set' => ['void', 'name'=>'string', 'value'=>'string'], 'SolrParams::setParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrParams::toString' => ['string', 'url_encode='=>'bool'], 'SolrParams::unserialize' => ['void', 'serialized'=>'string'], 'SolrPingResponse::__construct' => ['void'], 'SolrPingResponse::__destruct' => [''], 'SolrPingResponse::getDigestedResponse' => ['string'], 'SolrPingResponse::getHttpStatus' => ['int'], 'SolrPingResponse::getHttpStatusMessage' => ['string'], 'SolrPingResponse::getRawRequest' => ['string'], 'SolrPingResponse::getRawRequestHeaders' => ['string'], 'SolrPingResponse::getRawResponse' => ['string'], 'SolrPingResponse::getRawResponseHeaders' => ['string'], 'SolrPingResponse::getRequestUrl' => ['string'], 'SolrPingResponse::getResponse' => ['string'], 'SolrPingResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrPingResponse::success' => ['bool'], 'SolrQuery::__construct' => ['void', 'q='=>'string'], 'SolrQuery::__destruct' => [''], 'SolrQuery::add' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrQuery::addExpandFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrQuery::addExpandSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'string'], 'SolrQuery::addFacetDateField' => ['SolrQuery', 'datefield'=>'string'], 'SolrQuery::addFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::addFacetField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addFacetQuery' => ['SolrQuery', 'facetquery'=>'string'], 'SolrQuery::addField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrQuery::addGroupField' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::addGroupFunction' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::addGroupQuery' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::addGroupSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'int'], 'SolrQuery::addHighlightField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addMltField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addMltQueryField' => ['SolrQuery', 'field'=>'string', 'boost'=>'float'], 'SolrQuery::addParam' => ['SolrParams', 'name'=>'string', 'value'=>'string'], 'SolrQuery::addSortField' => ['SolrQuery', 'field'=>'string', 'order='=>'int'], 'SolrQuery::addStatsFacet' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::addStatsField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::collapse' => ['SolrQuery', 'collapseFunction'=>'SolrCollapseFunction'], 'SolrQuery::get' => ['mixed', 'param_name'=>'string'], 'SolrQuery::getExpand' => ['bool'], 'SolrQuery::getExpandFilterQueries' => ['array'], 'SolrQuery::getExpandQuery' => ['array'], 'SolrQuery::getExpandRows' => ['int'], 'SolrQuery::getExpandSortFields' => ['array'], 'SolrQuery::getFacet' => ['bool'], 'SolrQuery::getFacetDateEnd' => ['string', 'field_override='=>'string'], 'SolrQuery::getFacetDateFields' => ['array'], 'SolrQuery::getFacetDateGap' => ['string', 'field_override='=>'string'], 'SolrQuery::getFacetDateHardEnd' => ['string', 'field_override='=>'string'], 'SolrQuery::getFacetDateOther' => ['?string', 'field_override='=>'string'], 'SolrQuery::getFacetDateStart' => ['string', 'field_override='=>'string'], 'SolrQuery::getFacetFields' => ['array'], 'SolrQuery::getFacetLimit' => ['int', 'field_override='=>'string'], 'SolrQuery::getFacetMethod' => ['string', 'field_override='=>'string'], 'SolrQuery::getFacetMinCount' => ['int', 'field_override='=>'string'], 'SolrQuery::getFacetMissing' => ['bool', 'field_override='=>'string'], 'SolrQuery::getFacetOffset' => ['int', 'field_override='=>'string'], 'SolrQuery::getFacetPrefix' => ['string', 'field_override='=>'string'], 'SolrQuery::getFacetQueries' => ['array'], 'SolrQuery::getFacetSort' => ['int', 'field_override='=>'string'], 'SolrQuery::getFields' => ['array'], 'SolrQuery::getFilterQueries' => ['array'], 'SolrQuery::getGroup' => ['bool'], 'SolrQuery::getGroupCachePercent' => ['int'], 'SolrQuery::getGroupFacet' => ['bool'], 'SolrQuery::getGroupFields' => ['array'], 'SolrQuery::getGroupFormat' => ['string'], 'SolrQuery::getGroupFunctions' => ['array'], 'SolrQuery::getGroupLimit' => ['int'], 'SolrQuery::getGroupMain' => ['bool'], 'SolrQuery::getGroupNGroups' => ['bool'], 'SolrQuery::getGroupOffset' => ['int'], 'SolrQuery::getGroupQueries' => ['array'], 'SolrQuery::getGroupSortFields' => ['array'], 'SolrQuery::getGroupTruncate' => ['bool'], 'SolrQuery::getHighlight' => ['bool'], 'SolrQuery::getHighlightAlternateField' => ['string', 'field_override='=>'string'], 'SolrQuery::getHighlightFields' => ['array'], 'SolrQuery::getHighlightFormatter' => ['string', 'field_override='=>'string'], 'SolrQuery::getHighlightFragmenter' => ['string', 'field_override='=>'string'], 'SolrQuery::getHighlightFragsize' => ['int', 'field_override='=>'string'], 'SolrQuery::getHighlightHighlightMultiTerm' => ['bool'], 'SolrQuery::getHighlightMaxAlternateFieldLength' => ['int', 'field_override='=>'string'], 'SolrQuery::getHighlightMaxAnalyzedChars' => ['int'], 'SolrQuery::getHighlightMergeContiguous' => ['bool', 'field_override='=>'string'], 'SolrQuery::getHighlightRegexMaxAnalyzedChars' => ['int'], 'SolrQuery::getHighlightRegexPattern' => ['string'], 'SolrQuery::getHighlightRegexSlop' => ['float'], 'SolrQuery::getHighlightRequireFieldMatch' => ['bool'], 'SolrQuery::getHighlightSimplePost' => ['string', 'field_override='=>'string'], 'SolrQuery::getHighlightSimplePre' => ['string', 'field_override='=>'string'], 'SolrQuery::getHighlightSnippets' => ['int', 'field_override='=>'string'], 'SolrQuery::getHighlightUsePhraseHighlighter' => ['bool'], 'SolrQuery::getMlt' => ['bool'], 'SolrQuery::getMltBoost' => ['bool'], 'SolrQuery::getMltCount' => ['int'], 'SolrQuery::getMltFields' => ['array'], 'SolrQuery::getMltMaxNumQueryTerms' => ['int'], 'SolrQuery::getMltMaxNumTokens' => ['int'], 'SolrQuery::getMltMaxWordLength' => ['int'], 'SolrQuery::getMltMinDocFrequency' => ['int'], 'SolrQuery::getMltMinTermFrequency' => ['int'], 'SolrQuery::getMltMinWordLength' => ['int'], 'SolrQuery::getMltQueryFields' => ['array'], 'SolrQuery::getParam' => ['mixed', 'param_name'=>'string'], 'SolrQuery::getParams' => ['array'], 'SolrQuery::getPreparedParams' => ['array'], 'SolrQuery::getQuery' => ['string'], 'SolrQuery::getRows' => ['int'], 'SolrQuery::getSortFields' => ['array'], 'SolrQuery::getStart' => ['int'], 'SolrQuery::getStats' => ['bool'], 'SolrQuery::getStatsFacets' => ['array'], 'SolrQuery::getStatsFields' => ['array'], 'SolrQuery::getTerms' => ['bool'], 'SolrQuery::getTermsField' => ['string'], 'SolrQuery::getTermsIncludeLowerBound' => ['bool'], 'SolrQuery::getTermsIncludeUpperBound' => ['bool'], 'SolrQuery::getTermsLimit' => ['int'], 'SolrQuery::getTermsLowerBound' => ['string'], 'SolrQuery::getTermsMaxCount' => ['int'], 'SolrQuery::getTermsMinCount' => ['int'], 'SolrQuery::getTermsPrefix' => ['string'], 'SolrQuery::getTermsReturnRaw' => ['bool'], 'SolrQuery::getTermsSort' => ['int'], 'SolrQuery::getTermsUpperBound' => ['string'], 'SolrQuery::getTimeAllowed' => ['int'], 'SolrQuery::removeExpandFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrQuery::removeExpandSortField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeFacetDateField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeFacetDateOther' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::removeFacetField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeFacetQuery' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::removeField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeFilterQuery' => ['SolrQuery', 'fq'=>'string'], 'SolrQuery::removeHighlightField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeMltField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeMltQueryField' => ['SolrQuery', 'queryfield'=>'string'], 'SolrQuery::removeSortField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::removeStatsFacet' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::removeStatsField' => ['SolrQuery', 'field'=>'string'], 'SolrQuery::serialize' => ['string'], 'SolrQuery::set' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrQuery::setEchoHandler' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setEchoParams' => ['SolrQuery', 'type'=>'string'], 'SolrQuery::setExpand' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setExpandQuery' => ['SolrQuery', 'q'=>'string'], 'SolrQuery::setExpandRows' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setExplainOther' => ['SolrQuery', 'query'=>'string'], 'SolrQuery::setFacet' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setFacetDateEnd' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetDateGap' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetDateHardEnd' => ['SolrQuery', 'value'=>'bool', 'field_override='=>'string'], 'SolrQuery::setFacetDateStart' => ['SolrQuery', 'value'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetEnumCacheMinDefaultFrequency' => ['SolrQuery', 'frequency'=>'int', 'field_override='=>'string'], 'SolrQuery::setFacetLimit' => ['SolrQuery', 'limit'=>'int', 'field_override='=>'string'], 'SolrQuery::setFacetMethod' => ['SolrQuery', 'method'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetMinCount' => ['SolrQuery', 'mincount'=>'int', 'field_override='=>'string'], 'SolrQuery::setFacetMissing' => ['SolrQuery', 'flag'=>'bool', 'field_override='=>'string'], 'SolrQuery::setFacetOffset' => ['SolrQuery', 'offset'=>'int', 'field_override='=>'string'], 'SolrQuery::setFacetPrefix' => ['SolrQuery', 'prefix'=>'string', 'field_override='=>'string'], 'SolrQuery::setFacetSort' => ['SolrQuery', 'facetsort'=>'int', 'field_override='=>'string'], 'SolrQuery::setGroup' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setGroupCachePercent' => ['SolrQuery', 'percent'=>'int'], 'SolrQuery::setGroupFacet' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setGroupFormat' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::setGroupLimit' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setGroupMain' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::setGroupNGroups' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setGroupOffset' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setGroupTruncate' => ['SolrQuery', 'value'=>'bool'], 'SolrQuery::setHighlight' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setHighlightAlternateField' => ['SolrQuery', 'field'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightFormatter' => ['SolrQuery', 'formatter'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightFragmenter' => ['SolrQuery', 'fragmenter'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightFragsize' => ['SolrQuery', 'size'=>'int', 'field_override='=>'string'], 'SolrQuery::setHighlightHighlightMultiTerm' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setHighlightMaxAlternateFieldLength' => ['SolrQuery', 'fieldlength'=>'int', 'field_override='=>'string'], 'SolrQuery::setHighlightMaxAnalyzedChars' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setHighlightMergeContiguous' => ['SolrQuery', 'flag'=>'bool', 'field_override='=>'string'], 'SolrQuery::setHighlightRegexMaxAnalyzedChars' => ['SolrQuery', 'maxanalyzedchars'=>'int'], 'SolrQuery::setHighlightRegexPattern' => ['SolrQuery', 'value'=>'string'], 'SolrQuery::setHighlightRegexSlop' => ['SolrQuery', 'factor'=>'float'], 'SolrQuery::setHighlightRequireFieldMatch' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setHighlightSimplePost' => ['SolrQuery', 'simplepost'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightSimplePre' => ['SolrQuery', 'simplepre'=>'string', 'field_override='=>'string'], 'SolrQuery::setHighlightSnippets' => ['SolrQuery', 'value'=>'int', 'field_override='=>'string'], 'SolrQuery::setHighlightUsePhraseHighlighter' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setMlt' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setMltBoost' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setMltCount' => ['SolrQuery', 'count'=>'int'], 'SolrQuery::setMltMaxNumQueryTerms' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setMltMaxNumTokens' => ['SolrQuery', 'value'=>'int'], 'SolrQuery::setMltMaxWordLength' => ['SolrQuery', 'maxwordlength'=>'int'], 'SolrQuery::setMltMinDocFrequency' => ['SolrQuery', 'mindocfrequency'=>'int'], 'SolrQuery::setMltMinTermFrequency' => ['SolrQuery', 'mintermfrequency'=>'int'], 'SolrQuery::setMltMinWordLength' => ['SolrQuery', 'minwordlength'=>'int'], 'SolrQuery::setOmitHeader' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setParam' => ['SolrParams', 'name'=>'string', 'value'=>''], 'SolrQuery::setQuery' => ['SolrQuery', 'query'=>'string'], 'SolrQuery::setRows' => ['SolrQuery', 'rows'=>'int'], 'SolrQuery::setShowDebugInfo' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setStart' => ['SolrQuery', 'start'=>'int'], 'SolrQuery::setStats' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTerms' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTermsField' => ['SolrQuery', 'fieldname'=>'string'], 'SolrQuery::setTermsIncludeLowerBound' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTermsIncludeUpperBound' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTermsLimit' => ['SolrQuery', 'limit'=>'int'], 'SolrQuery::setTermsLowerBound' => ['SolrQuery', 'lowerbound'=>'string'], 'SolrQuery::setTermsMaxCount' => ['SolrQuery', 'frequency'=>'int'], 'SolrQuery::setTermsMinCount' => ['SolrQuery', 'frequency'=>'int'], 'SolrQuery::setTermsPrefix' => ['SolrQuery', 'prefix'=>'string'], 'SolrQuery::setTermsReturnRaw' => ['SolrQuery', 'flag'=>'bool'], 'SolrQuery::setTermsSort' => ['SolrQuery', 'sorttype'=>'int'], 'SolrQuery::setTermsUpperBound' => ['SolrQuery', 'upperbound'=>'string'], 'SolrQuery::setTimeAllowed' => ['SolrQuery', 'timeallowed'=>'int'], 'SolrQuery::toString' => ['string', 'url_encode='=>'bool|false'], 'SolrQuery::unserialize' => ['void', 'serialized'=>'string'], 'SolrQueryResponse::__construct' => ['void'], 'SolrQueryResponse::__destruct' => [''], 'SolrQueryResponse::getDigestedResponse' => ['string'], 'SolrQueryResponse::getHttpStatus' => ['int'], 'SolrQueryResponse::getHttpStatusMessage' => ['string'], 'SolrQueryResponse::getRawRequest' => ['string'], 'SolrQueryResponse::getRawRequestHeaders' => ['string'], 'SolrQueryResponse::getRawResponse' => ['string'], 'SolrQueryResponse::getRawResponseHeaders' => ['string'], 'SolrQueryResponse::getRequestUrl' => ['string'], 'SolrQueryResponse::getResponse' => ['SolrObject'], 'SolrQueryResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrQueryResponse::success' => ['bool'], 'SolrResponse::getDigestedResponse' => ['string'], 'SolrResponse::getHttpStatus' => ['int'], 'SolrResponse::getHttpStatusMessage' => ['string'], 'SolrResponse::getRawRequest' => ['string'], 'SolrResponse::getRawRequestHeaders' => ['string'], 'SolrResponse::getRawResponse' => ['string'], 'SolrResponse::getRawResponseHeaders' => ['string'], 'SolrResponse::getRequestUrl' => ['string'], 'SolrResponse::getResponse' => ['SolrObject'], 'SolrResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrResponse::success' => ['bool'], 'SolrServerException::__clone' => ['void'], 'SolrServerException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Exception)|(?Throwable)'], 'SolrServerException::__toString' => ['string'], 'SolrServerException::__wakeup' => ['void'], 'SolrServerException::getCode' => ['int'], 'SolrServerException::getFile' => ['string'], 'SolrServerException::getInternalInfo' => ['array'], 'SolrServerException::getLine' => ['int'], 'SolrServerException::getMessage' => ['string'], 'SolrServerException::getPrevious' => ['Exception|Throwable'], 'SolrServerException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'SolrServerException::getTraceAsString' => ['string'], 'SolrUpdateResponse::__construct' => ['void'], 'SolrUpdateResponse::__destruct' => [''], 'SolrUpdateResponse::getDigestedResponse' => ['string'], 'SolrUpdateResponse::getHttpStatus' => ['int'], 'SolrUpdateResponse::getHttpStatusMessage' => ['string'], 'SolrUpdateResponse::getRawRequest' => ['string'], 'SolrUpdateResponse::getRawRequestHeaders' => ['string'], 'SolrUpdateResponse::getRawResponse' => ['string'], 'SolrUpdateResponse::getRawResponseHeaders' => ['string'], 'SolrUpdateResponse::getRequestUrl' => ['string'], 'SolrUpdateResponse::getResponse' => ['SolrObject'], 'SolrUpdateResponse::setParseMode' => ['bool', 'parser_mode='=>'int'], 'SolrUpdateResponse::success' => ['bool'], 'SolrUtils::digestXmlResponse' => ['SolrObject', 'xmlresponse'=>'string', 'parse_mode='=>'int'], 'SolrUtils::escapeQueryChars' => ['string|false', 'str'=>'string'], 'SolrUtils::getSolrVersion' => ['string'], 'SolrUtils::queryPhrase' => ['string', 'str'=>'string'], 'sort' => ['bool', '&rw_array_arg'=>'array', 'sort_flags='=>'int'], 'soundex' => ['string', 'str'=>'string'], 'SphinxClient::__construct' => ['void'], 'SphinxClient::addQuery' => ['int', 'query'=>'string', 'index='=>'string', 'comment='=>'string'], 'SphinxClient::buildExcerpts' => ['array', 'docs'=>'array', 'index'=>'string', 'words'=>'string', 'opts='=>'array'], 'SphinxClient::buildKeywords' => ['array', 'query'=>'string', 'index'=>'string', 'hits'=>'bool'], 'SphinxClient::close' => ['bool'], 'SphinxClient::escapeString' => ['string', 'string'=>'string'], 'SphinxClient::getLastError' => ['string'], 'SphinxClient::getLastWarning' => ['string'], 'SphinxClient::open' => ['bool'], 'SphinxClient::query' => ['array', 'query'=>'string', 'index='=>'string', 'comment='=>'string'], 'SphinxClient::resetFilters' => ['void'], 'SphinxClient::resetGroupBy' => ['void'], 'SphinxClient::runQueries' => ['array'], 'SphinxClient::setArrayResult' => ['bool', 'array_result'=>'bool'], 'SphinxClient::setConnectTimeout' => ['bool', 'timeout'=>'float'], 'SphinxClient::setFieldWeights' => ['bool', 'weights'=>'array'], 'SphinxClient::setFilter' => ['bool', 'attribute'=>'string', 'values'=>'array', 'exclude='=>'bool'], 'SphinxClient::setFilterFloatRange' => ['bool', 'attribute'=>'string', 'min'=>'float', 'max'=>'float', 'exclude='=>'bool'], 'SphinxClient::setFilterRange' => ['bool', 'attribute'=>'string', 'min'=>'int', 'max'=>'int', 'exclude='=>'bool'], 'SphinxClient::setGeoAnchor' => ['bool', 'attrlat'=>'string', 'attrlong'=>'string', 'latitude'=>'float', 'longitude'=>'float'], 'SphinxClient::setGroupBy' => ['bool', 'attribute'=>'string', 'func'=>'int', 'groupsort='=>'string'], 'SphinxClient::setGroupDistinct' => ['bool', 'attribute'=>'string'], 'SphinxClient::setIDRange' => ['bool', 'min'=>'int', 'max'=>'int'], 'SphinxClient::setIndexWeights' => ['bool', 'weights'=>'array'], 'SphinxClient::setLimits' => ['bool', 'offset'=>'int', 'limit'=>'int', 'max_matches='=>'int', 'cutoff='=>'int'], 'SphinxClient::setMatchMode' => ['bool', 'mode'=>'int'], 'SphinxClient::setMaxQueryTime' => ['bool', 'qtime'=>'int'], 'SphinxClient::setOverride' => ['bool', 'attribute'=>'string', 'type'=>'int', 'values'=>'array'], 'SphinxClient::setRankingMode' => ['bool', 'ranker'=>'int'], 'SphinxClient::setRetries' => ['bool', 'count'=>'int', 'delay='=>'int'], 'SphinxClient::setSelect' => ['bool', 'clause'=>'string'], 'SphinxClient::setServer' => ['bool', 'server'=>'string', 'port'=>'int'], 'SphinxClient::setSortMode' => ['bool', 'mode'=>'int', 'sortby='=>'string'], 'SphinxClient::status' => ['array'], 'SphinxClient::updateAttributes' => ['int', 'index'=>'string', 'attributes'=>'array', 'values'=>'array', 'mva='=>'bool'], 'spl_autoload' => ['void', 'class_name'=>'string', 'file_extensions='=>'string'], 'spl_autoload_call' => ['void', 'class_name'=>'string'], 'spl_autoload_extensions' => ['string', 'file_extensions='=>'string'], 'spl_autoload_functions' => ['false|list'], 'spl_autoload_register' => ['bool', 'autoload_function='=>'callable(string):void', 'throw='=>'bool', 'prepend='=>'bool'], 'spl_autoload_unregister' => ['bool', 'autoload_function'=>'mixed'], 'spl_classes' => ['array'], 'spl_object_hash' => ['string', 'obj'=>'object'], 'spl_object_id' => ['int', 'obj'=>'object'], 'SplDoublyLinkedList::add' => ['void', 'index'=>'mixed', 'newval'=>'mixed'], 'SplDoublyLinkedList::bottom' => ['mixed'], 'SplDoublyLinkedList::count' => ['0|positive-int'], 'SplDoublyLinkedList::current' => ['mixed'], 'SplDoublyLinkedList::getIteratorMode' => ['int'], 'SplDoublyLinkedList::isEmpty' => ['bool'], 'SplDoublyLinkedList::key' => ['mixed'], 'SplDoublyLinkedList::next' => ['void'], 'SplDoublyLinkedList::offsetExists' => ['bool', 'index'=>'mixed'], 'SplDoublyLinkedList::offsetGet' => ['mixed', 'index'=>'mixed'], 'SplDoublyLinkedList::offsetSet' => ['void', 'index'=>'mixed', 'newval'=>'mixed'], 'SplDoublyLinkedList::offsetUnset' => ['void', 'index'=>'mixed'], 'SplDoublyLinkedList::pop' => ['mixed'], 'SplDoublyLinkedList::prev' => ['void'], 'SplDoublyLinkedList::push' => ['void', 'value'=>'mixed'], 'SplDoublyLinkedList::rewind' => ['void'], 'SplDoublyLinkedList::serialize' => ['string'], 'SplDoublyLinkedList::setIteratorMode' => ['int', 'flags'=>'int'], 'SplDoublyLinkedList::shift' => ['mixed'], 'SplDoublyLinkedList::top' => ['mixed'], 'SplDoublyLinkedList::unserialize' => ['void', 'serialized'=>'string'], 'SplDoublyLinkedList::unshift' => ['bool', 'value'=>'mixed'], 'SplDoublyLinkedList::valid' => ['bool'], 'SplEnum::__construct' => ['void', 'initial_value='=>'mixed', 'strict='=>'bool|true'], 'SplEnum::getConstList' => ['array', 'include_default='=>'bool'], 'SplFileInfo::__construct' => ['void', 'file_name'=>'string'], 'SplFileInfo::__toString' => ['string'], 'SplFileInfo::getATime' => ['__benevolent'], 'SplFileInfo::getBasename' => ['string', 'suffix='=>'string'], 'SplFileInfo::getCTime' => ['int'], 'SplFileInfo::getExtension' => ['string'], 'SplFileInfo::getFileInfo' => ['SplFileInfo', 'class_name='=>'string'], 'SplFileInfo::getFilename' => ['string'], 'SplFileInfo::getGroup' => ['__benevolent'], 'SplFileInfo::getInode' => ['__benevolent'], 'SplFileInfo::getLinkTarget' => ['__benevolent'], 'SplFileInfo::getMTime' => ['__benevolent'], 'SplFileInfo::getOwner' => ['__benevolent'], 'SplFileInfo::getPath' => ['string'], 'SplFileInfo::getPathInfo' => ['__benevolent', 'class_name='=>'string'], 'SplFileInfo::getPathname' => ['string'], 'SplFileInfo::getPerms' => ['__benevolent'], 'SplFileInfo::getRealPath' => ['__benevolent'], 'SplFileInfo::getSize' => ['__benevolent'], 'SplFileInfo::getType' => ['__benevolent'], 'SplFileInfo::isDir' => ['bool'], 'SplFileInfo::isExecutable' => ['bool'], 'SplFileInfo::isFile' => ['bool'], 'SplFileInfo::isLink' => ['bool'], 'SplFileInfo::isReadable' => ['bool'], 'SplFileInfo::isWritable' => ['bool'], 'SplFileInfo::openFile' => ['SplFileObject', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>'resource'], 'SplFileInfo::setFileClass' => ['void', 'class_name='=>'string'], 'SplFileInfo::setInfoClass' => ['void', 'class_name='=>'string'], 'SplFileObject::__construct' => ['void', 'filename'=>'string', 'mode='=>'string', 'use_include_path='=>'bool', 'context='=>''], 'SplFileObject::__toString' => ['string'], 'SplFileObject::current' => ['string|array|false'], 'SplFileObject::eof' => ['bool'], 'SplFileObject::fflush' => ['bool'], 'SplFileObject::fgetc' => ['string|false'], // Do not believe https://www.php.net/manual/en/splfileobject.fgetcsv#refsect1-splfileobject.fgetcsv-returnvalues 'SplFileObject::fgetcsv' => ['list|array{0: null}|false|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplFileObject::fgets' => ['string'], 'SplFileObject::fgetss' => ['string|false', 'allowable_tags='=>'string'], 'SplFileObject::flock' => ['bool', 'operation'=>'int', '&w_wouldblock='=>'int'], 'SplFileObject::fpassthru' => ['int'], 'SplFileObject::fputcsv' => ['int|false', 'fields'=>'array', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplFileObject::fread' => ['string|false', 'length'=>'int'], 'SplFileObject::fscanf' => ['bool', 'format'=>'string', '&...w_vars='=>'string|int|float'], 'SplFileObject::fseek' => ['int', 'pos'=>'int', 'whence='=>'int'], 'SplFileObject::fstat' => ['array'], 'SplFileObject::ftell' => ['int|false'], 'SplFileObject::ftruncate' => ['bool', 'size'=>'int'], 'SplFileObject::fwrite' => ['int', 'str'=>'string', 'length='=>'int'], 'SplFileObject::getChildren' => ['null'], 'SplFileObject::getCsvControl' => ['array'], 'SplFileObject::getCurrentLine' => ['string'], 'SplFileObject::getFlags' => ['int'], 'SplFileObject::getMaxLineLen' => ['int'], 'SplFileObject::hasChildren' => ['false'], 'SplFileObject::key' => ['int'], 'SplFileObject::next' => ['void'], 'SplFileObject::rewind' => ['void'], 'SplFileObject::seek' => ['void', 'line_pos'=>'int'], 'SplFileObject::setCsvControl' => ['void', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplFileObject::setFlags' => ['void', 'flags'=>'int'], 'SplFileObject::setMaxLineLen' => ['void', 'max_len'=>'int'], 'SplFileObject::valid' => ['bool'], 'SplFixedArray::__construct' => ['void', 'size='=>'int'], 'SplFixedArray::__wakeup' => ['void'], 'SplFixedArray::count' => ['0|positive-int'], 'SplFixedArray::current' => ['mixed'], 'SplFixedArray::fromArray' => ['SplFixedArray', 'data'=>'array', 'save_indexes='=>'bool'], 'SplFixedArray::getSize' => ['int'], 'SplFixedArray::key' => ['int'], 'SplFixedArray::next' => ['void'], 'SplFixedArray::offsetExists' => ['bool', 'index'=>'int'], 'SplFixedArray::offsetGet' => ['mixed', 'index'=>'int'], 'SplFixedArray::offsetSet' => ['void', 'index'=>'int', 'newval'=>'mixed'], 'SplFixedArray::offsetUnset' => ['void', 'index'=>'int'], 'SplFixedArray::rewind' => ['void'], 'SplFixedArray::setSize' => ['bool', 'size'=>'int'], 'SplFixedArray::toArray' => ['array'], 'SplFixedArray::valid' => ['bool'], 'SplHeap::compare' => ['int', 'value1'=>'mixed', 'value2'=>'mixed'], 'SplHeap::count' => ['0|positive-int'], 'SplHeap::current' => ['mixed'], 'SplHeap::extract' => ['mixed'], 'SplHeap::insert' => ['bool', 'value'=>'mixed'], 'SplHeap::isCorrupted' => ['int'], 'SplHeap::isEmpty' => ['bool'], 'SplHeap::key' => ['int'], 'SplHeap::next' => ['void'], 'SplHeap::recoverFromCorruption' => ['int'], 'SplHeap::rewind' => ['void'], 'SplHeap::top' => ['mixed'], 'SplHeap::valid' => ['bool'], 'split' => ['array', 'pattern'=>'string', 'string'=>'string', 'limit='=>'int'], 'spliti' => ['array', 'pattern'=>'string', 'string'=>'string', 'limit='=>'int'], 'SplMaxHeap::compare' => ['int', 'a'=>'mixed', 'b'=>'mixed'], 'SplMinHeap::compare' => ['int', 'a'=>'mixed', 'b'=>'mixed'], 'SplObjectStorage::addAll' => ['0|positive-int', 'os'=>'SplObjectStorage'], 'SplObjectStorage::attach' => ['void', 'obj'=>'object', 'inf='=>'mixed'], 'SplObjectStorage::contains' => ['bool', 'obj'=>'object'], 'SplObjectStorage::count' => ['0|positive-int'], 'SplObjectStorage::current' => ['object'], 'SplObjectStorage::detach' => ['void', 'obj'=>'object'], 'SplObjectStorage::getHash' => ['string', 'obj'=>'object'], 'SplObjectStorage::getInfo' => ['mixed'], 'SplObjectStorage::key' => ['int'], 'SplObjectStorage::next' => ['void'], 'SplObjectStorage::offsetExists' => ['bool', 'object'=>'object'], 'SplObjectStorage::offsetGet' => ['mixed', 'obj'=>'object'], 'SplObjectStorage::offsetSet' => ['object', 'object'=>'object', 'data='=>'mixed'], 'SplObjectStorage::offsetUnset' => ['object', 'object'=>'object'], 'SplObjectStorage::removeAll' => ['0|positive-int', 'os'=>'SplObjectStorage'], 'SplObjectStorage::removeAllExcept' => ['0|positive-int', 'os'=>'SplObjectStorage'], 'SplObjectStorage::rewind' => ['void'], 'SplObjectStorage::serialize' => ['string'], 'SplObjectStorage::setInfo' => ['void', 'inf'=>'mixed'], 'SplObjectStorage::unserialize' => ['void', 'serialized'=>'string'], 'SplObjectStorage::valid' => ['bool'], 'SplObserver::update' => ['void', 'subject'=>'SplSubject'], 'SplPriorityQueue::compare' => ['int', 'a'=>'mixed', 'b'=>'mixed'], 'SplPriorityQueue::count' => ['0|positive-int'], 'SplPriorityQueue::current' => ['mixed'], 'SplPriorityQueue::extract' => ['mixed'], 'SplPriorityQueue::getExtractFlags' => ['int'], 'SplPriorityQueue::insert' => ['bool', 'value'=>'mixed', 'priority'=>'mixed'], 'SplPriorityQueue::isEmpty' => ['bool'], 'SplPriorityQueue::key' => ['mixed'], 'SplPriorityQueue::next' => ['void'], 'SplPriorityQueue::recoverFromCorruption' => ['void'], 'SplPriorityQueue::rewind' => ['void'], 'SplPriorityQueue::setExtractFlags' => ['void', 'flags'=>'int'], 'SplPriorityQueue::top' => ['mixed'], 'SplPriorityQueue::valid' => ['bool'], 'SplQueue::dequeue' => ['mixed'], 'SplQueue::enqueue' => ['void', 'value'=>'mixed'], 'SplQueue::setIteratorMode' => ['void', 'mode'=>'int'], 'SplStack::setIteratorMode' => ['void', 'mode'=>'int'], 'SplSubject::attach' => ['void', 'observer'=>'SplObserver'], 'SplSubject::detach' => ['void', 'observer'=>'SplObserver'], 'SplSubject::notify' => ['void'], 'SplTempFileObject::__construct' => ['void', 'max_memory='=>'int'], 'SplType::__construct' => ['void', 'initial_value='=>'mixed', 'strict='=>'bool'], 'Spoofchecker::__construct' => ['void'], 'Spoofchecker::areConfusable' => ['bool', 's1'=>'string', 's2'=>'string', '&w_error='=>'string'], 'Spoofchecker::isSuspicious' => ['bool', 'text'=>'string', '&w_error='=>'string'], 'Spoofchecker::setAllowedLocales' => ['void', 'locale_list'=>'string'], 'Spoofchecker::setChecks' => ['void', 'checks'=>'long'], 'Spoofchecker::setRestrictionLevel' => ['void', 'restriction_level'=>'int'], 'sprintf' => ['string', 'format'=>'string', '...values='=>'__stringAndStringable|int|float|null|bool'], 'sql_regcase' => ['string', 'string'=>'string'], 'SQLite3::__construct' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryption_key='=>'string|null'], 'SQLite3::busyTimeout' => ['bool', 'msecs'=>'int'], 'SQLite3::changes' => ['int'], 'SQLite3::close' => ['bool'], 'SQLite3::createAggregate' => ['bool', 'name'=>'string', 'step_callback'=>'callable', 'final_callback'=>'callable', 'argument_count='=>'int'], 'SQLite3::createCollation' => ['bool', 'name'=>'string', 'callback'=>'callable'], 'SQLite3::createFunction' => ['bool', 'name'=>'string', 'callback'=>'callable', 'argument_count='=>'int', 'flags='=>'int'], 'SQLite3::enableExceptions' => ['bool', 'enableexceptions='=>'bool'], 'SQLite3::escapeString' => ['string', 'value'=>'string'], 'SQLite3::exec' => ['bool', 'query'=>'string'], 'SQLite3::lastErrorCode' => ['int'], 'SQLite3::lastErrorMsg' => ['string'], 'SQLite3::lastInsertRowID' => ['int'], 'SQLite3::loadExtension' => ['bool', 'shared_library'=>'string'], 'SQLite3::open' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryption_key='=>'string|null'], 'SQLite3::openBlob' => ['resource|false', 'table'=>'string', 'column'=>'string', 'rowid'=>'int', 'dbname='=>'string', 'flags='=>'int'], 'SQLite3::prepare' => ['SQLite3Stmt|false', 'query'=>'string'], 'SQLite3::query' => ['SQLite3Result|false', 'query'=>'string'], 'SQLite3::querySingle' => ['array|int|string|bool|float|null|false', 'query'=>'string', 'entire_row='=>'bool'], 'SQLite3::version' => ['array'], 'SQLite3Result::__construct' => ['void'], 'SQLite3Result::columnName' => ['string', 'column_number'=>'int'], 'SQLite3Result::columnType' => ['int', 'column_number'=>'int'], 'SQLite3Result::fetchArray' => ['array|false', 'mode='=>'int'], 'SQLite3Result::finalize' => ['bool'], 'SQLite3Result::numColumns' => ['int'], 'SQLite3Result::reset' => ['bool'], 'SQLite3Stmt::__construct' => ['void', 'dbobject'=>'sqlite3', 'statement'=>'string'], 'SQLite3Stmt::bindParam' => ['bool', 'parameter_name_or_number'=>'string|int', '&rw_parameter'=>'mixed', 'type='=>'int'], 'SQLite3Stmt::bindValue' => ['bool', 'parameter_name_or_number'=>'string|int', 'parameter'=>'mixed', 'type='=>'int'], 'SQLite3Stmt::clear' => ['bool'], 'SQLite3Stmt::close' => ['bool'], 'SQLite3Stmt::execute' => ['false|SQLite3Result'], 'SQLite3Stmt::paramCount' => ['int'], 'SQLite3Stmt::readOnly' => ['bool'], 'SQLite3Stmt::reset' => ['bool'], 'sqlite_array_query' => ['array', 'dbhandle'=>'', 'query'=>'string', 'result_type='=>'int', 'decode_binary='=>'bool'], 'sqlite_busy_timeout' => ['', 'dbhandle'=>'', 'milliseconds'=>'int'], 'sqlite_changes' => ['int', 'dbhandle'=>''], 'sqlite_close' => ['void', 'dbhandle'=>'resource'], 'sqlite_column' => ['', 'result'=>'', 'index_or_name'=>'', 'decode_binary='=>'bool'], 'sqlite_create_aggregate' => ['', 'dbhandle'=>'', 'function_name'=>'string', 'step_func'=>'callable', 'finalize_func'=>'callable', 'num_args='=>'int'], 'sqlite_create_function' => ['', 'dbhandle'=>'', 'function_name'=>'string', 'callback'=>'callable', 'num_args='=>'int'], 'sqlite_current' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'], 'sqlite_error_string' => ['string', 'error_code'=>'int'], 'sqlite_escape_string' => ['string', 'item'=>'string'], 'sqlite_exec' => ['bool', 'dbhandle'=>'', 'query'=>'string', 'error_msg='=>'string'], 'sqlite_factory' => ['SQLiteDatabase', 'filename'=>'string', 'mode='=>'int', 'error_message='=>'string'], 'sqlite_fetch_all' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'], 'sqlite_fetch_array' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'], 'sqlite_fetch_column_types' => ['array', 'table_name'=>'string', 'dbhandle'=>'', 'result_type='=>'int'], 'sqlite_fetch_object' => ['object', 'result'=>'', 'class_name='=>'string', 'ctor_params='=>'array', 'decode_binary='=>'bool'], 'sqlite_fetch_single' => ['string', 'result'=>'', 'decode_binary='=>'bool'], 'sqlite_field_name' => ['string', 'result'=>'', 'field_index'=>'int'], 'sqlite_has_more' => ['bool', 'result'=>'resource'], 'sqlite_has_prev' => ['bool', 'result'=>''], 'sqlite_key' => ['int', 'result'=>''], 'sqlite_last_error' => ['int', 'dbhandle'=>''], 'sqlite_last_insert_rowid' => ['int', 'dbhandle'=>''], 'sqlite_libencoding' => ['string'], 'sqlite_libversion' => ['string'], 'sqlite_next' => ['bool', 'result'=>''], 'sqlite_num_fields' => ['int', 'result'=>''], 'sqlite_num_rows' => ['int', 'result'=>''], 'sqlite_open' => ['resource|false', 'filename'=>'string', 'mode='=>'int', 'error_message='=>'string'], 'sqlite_popen' => ['resource|false', 'filename'=>'string', 'mode='=>'int', 'error_message='=>'string'], 'sqlite_prev' => ['bool', 'result'=>''], 'sqlite_query' => ['SQLiteResult', 'dbhandle'=>'', 'query'=>'string', 'result_type='=>'int', 'error_msg='=>'string'], 'sqlite_rewind' => ['bool', 'result'=>''], 'sqlite_seek' => ['bool', 'result'=>'', 'rownum'=>'int'], 'sqlite_single_query' => ['array', 'db'=>'', 'query'=>'string', 'first_row_only='=>'bool', 'decode_binary='=>'bool'], 'sqlite_udf_decode_binary' => ['string', 'data'=>'string'], 'sqlite_udf_encode_binary' => ['string', 'data'=>'string'], 'sqlite_unbuffered_query' => ['SQLiteUnbuffered', 'dbhandle'=>'', 'query'=>'string', 'result_type='=>'int', 'error_msg='=>'string'], 'sqlite_valid' => ['bool', 'result'=>''], 'SQLiteDatabase::arrayQuery' => ['array', 'dbhandle'=>'', 'query'=>'string', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteDatabase::busyTimeout' => ['', 'dbhandle'=>'', 'milliseconds'=>'int'], 'SQLiteDatabase::changes' => ['int', 'dbhandle'=>''], 'SQLiteDatabase::createAggregate' => ['', 'dbhandle'=>'', 'function_name'=>'string', 'step_func'=>'callable', 'finalize_func'=>'callable', 'num_args='=>'int'], 'SQLiteDatabase::createFunction' => ['', 'dbhandle'=>'', 'function_name'=>'string', 'callback'=>'callable', 'num_args='=>'int'], 'SQLiteDatabase::exec' => ['bool', 'dbhandle'=>'', 'query'=>'string', 'error_msg='=>'string'], 'SQLiteDatabase::fetchColumnTypes' => ['array', 'table_name'=>'string', 'dbhandle'=>'', 'result_type='=>'int'], 'SQLiteDatabase::lastError' => ['int', 'dbhandle'=>''], 'SQLiteDatabase::lastInsertRowid' => ['int', 'dbhandle'=>''], 'SQLiteDatabase::query' => ['SQLiteResult', 'dbhandle'=>'', 'query'=>'string', 'result_type='=>'int', 'error_msg='=>'string'], 'SQLiteDatabase::queryExec' => ['bool', 'query'=>'string', '&w_error_msg='=>'string'], 'SQLiteDatabase::singleQuery' => ['array', 'db'=>'', 'query'=>'string', 'first_row_only='=>'bool', 'decode_binary='=>'bool'], 'SQLiteDatabase::unbufferedQuery' => ['SQLiteUnbuffered', 'dbhandle'=>'', 'query'=>'string', 'result_type='=>'int', 'error_msg='=>'string'], 'SQLiteResult::column' => ['', 'result'=>'', 'index_or_name'=>'', 'decode_binary='=>'bool'], 'SQLiteResult::current' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteResult::fetch' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteResult::fetchAll' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteResult::fetchObject' => ['object', 'result'=>'', 'class_name='=>'string', 'ctor_params='=>'array', 'decode_binary='=>'bool'], 'SQLiteResult::fetchSingle' => ['string', 'result'=>'', 'decode_binary='=>'bool'], 'SQLiteResult::fieldName' => ['string', 'result'=>'', 'field_index'=>'int'], 'SQLiteResult::hasPrev' => ['bool', 'result'=>''], 'SQLiteResult::key' => ['int', 'result'=>''], 'SQLiteResult::next' => ['bool', 'result'=>''], 'SQLiteResult::numFields' => ['int', 'result'=>''], 'SQLiteResult::numRows' => ['int', 'result'=>''], 'SQLiteResult::prev' => ['bool', 'result'=>''], 'SQLiteResult::rewind' => ['bool', 'result'=>''], 'SQLiteResult::seek' => ['bool', 'result'=>'', 'rownum'=>'int'], 'SQLiteResult::valid' => ['bool', 'result'=>''], 'SQLiteUnbuffered::column' => ['', 'result'=>'', 'index_or_name'=>'', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::current' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fetch' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fetchAll' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fetchObject' => ['object', 'result'=>'', 'class_name='=>'string', 'ctor_params='=>'array', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fetchSingle' => ['string', 'result'=>'', 'decode_binary='=>'bool'], 'SQLiteUnbuffered::fieldName' => ['string', 'result'=>'', 'field_index'=>'int'], 'SQLiteUnbuffered::next' => ['bool', 'result'=>''], 'SQLiteUnbuffered::numFields' => ['int', 'result'=>''], 'SQLiteUnbuffered::valid' => ['bool', 'result'=>''], 'sqlsrv_begin_transaction' => ['bool', 'conn'=>'resource'], 'sqlsrv_cancel' => ['bool', 'stmt'=>'resource'], 'sqlsrv_client_info' => ['array|false', 'conn'=>'resource'], 'sqlsrv_close' => ['bool', 'conn'=>'resource'], 'sqlsrv_commit' => ['bool', 'conn'=>'resource'], 'sqlsrv_configure' => ['bool', 'setting'=>'string', 'value'=>'mixed'], 'sqlsrv_connect' => ['resource|false', 'serverName'=>'string', 'connectionInfo='=>'array'], 'sqlsrv_errors' => ['array|null', 'errorsOrWarnings='=>'int'], 'sqlsrv_execute' => ['bool', 'stmt'=>'resource'], 'sqlsrv_fetch' => ['bool|null', 'stmt'=>'resource', 'row='=>'int', 'offset='=>'int'], 'sqlsrv_fetch_array' => ['array|null|false', 'stmt'=>'resource', 'fetchType='=>'int', 'row='=>'int', 'offset='=>'int'], 'sqlsrv_fetch_object' => ['object|null|false', 'stmt'=>'resource', 'className='=>'string', 'ctorParams='=>'array', 'row='=>'int', 'offset='=>'int'], 'sqlsrv_field_metadata' => ['array|false', 'stmt'=>'resource'], 'sqlsrv_free_stmt' => ['bool', 'stmt'=>'resource'], 'sqlsrv_get_config' => ['mixed', 'setting'=>'string'], 'sqlsrv_get_field' => ['mixed', 'stmt'=>'resource', 'fieldIndex'=>'int', 'getAsType='=>'int'], 'sqlsrv_has_rows' => ['bool', 'stmt'=>'resource'], 'sqlsrv_next_result' => ['bool|null', 'stmt'=>'resource'], 'sqlsrv_num_fields' => ['int|false', 'stmt'=>'resource'], 'sqlsrv_num_rows' => ['int|false', 'stmt'=>'resource'], 'sqlsrv_prepare' => ['resource|false', 'conn'=>'resource', 'sql'=>'string', 'params='=>'array', 'options='=>'array'], 'sqlsrv_query' => ['resource|false', 'conn'=>'resource', 'sql'=>'string', 'params='=>'array', 'options='=>'array'], 'sqlsrv_rollback' => ['bool', 'conn'=>'resource'], 'sqlsrv_rows_affected' => ['int<-1,max>|false', 'stmt'=>'resource'], 'sqlsrv_send_stream_data' => ['bool', 'stmt'=>'resource'], 'sqlsrv_server_info' => ['array', 'conn'=>'resource'], 'sqrt' => ['float', 'number'=>'float'], 'srand' => ['void', 'seed='=>'int', 'mode='=>'int'], 'sscanf' => ['int|null', 'str'=>'string', 'format'=>'string', '&w_war'=>'string|int|float|null', '&...w_vars='=>'string|int|float|null'], 'sscanf\'1' => ['array|null', 'str'=>'string', 'format'=>'string'], 'ssdeep_fuzzy_compare' => ['int', 'signature1'=>'string', 'signature2'=>'string'], 'ssdeep_fuzzy_hash' => ['string', 'to_hash'=>'string'], 'ssdeep_fuzzy_hash_filename' => ['string', 'file_name'=>'string'], 'ssh2_auth_agent' => ['bool', 'session'=>'resource', 'username'=>'string'], 'ssh2_auth_hostbased_file' => ['bool', 'session'=>'resource', 'username'=>'string', 'hostname'=>'string', 'pubkeyfile'=>'string', 'privkeyfile'=>'string', 'passphrase='=>'string', 'local_username='=>'string'], 'ssh2_auth_none' => ['bool|string[]', 'session'=>'resource', 'username'=>'string'], 'ssh2_auth_password' => ['bool', 'session'=>'resource', 'username'=>'string', 'password'=>'string'], 'ssh2_auth_pubkey_file' => ['bool', 'session'=>'resource', 'username'=>'string', 'pubkeyfile'=>'string', 'privkeyfile'=>'string', 'passphrase='=>'string'], 'ssh2_connect' => ['resource|false', 'host'=>'string', 'port='=>'int', 'methods='=>'array', 'callbacks='=>'array'], 'ssh2_disconnect' => ['bool', 'session'=>'resource'], 'ssh2_exec' => ['resource|false', 'session'=>'resource', 'command'=>'string', 'pty='=>'string', 'env='=>'array', 'width='=>'int', 'height='=>'int', 'width_height_type='=>'int'], 'ssh2_fetch_stream' => ['resource|false', 'channel'=>'resource', 'streamid'=>'int'], 'ssh2_fingerprint' => ['string|false', 'session'=>'resource', 'flags='=>'int'], 'ssh2_methods_negotiated' => ['array|false', 'session'=>'resource'], 'ssh2_publickey_add' => ['bool', 'pkey'=>'resource', 'algoname'=>'string', 'blob'=>'string', 'overwrite='=>'bool', 'attributes='=>'array'], 'ssh2_publickey_init' => ['resource|false', 'session'=>'resource'], 'ssh2_publickey_list' => ['array|false', 'pkey'=>'resource'], 'ssh2_publickey_remove' => ['bool', 'pkey'=>'resource', 'algoname'=>'string', 'blob'=>'string'], 'ssh2_scp_recv' => ['bool', 'session'=>'resource', 'remote_file'=>'string', 'local_file'=>'string'], 'ssh2_scp_send' => ['bool', 'session'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'create_mode='=>'int'], 'ssh2_sftp' => ['resource|false', 'session'=>'resource'], 'ssh2_sftp_chmod' => ['bool', 'sftp'=>'resource', 'filename'=>'string', 'mode'=>'int'], 'ssh2_sftp_lstat' => ['array|false', 'sftp'=>'resource', 'path'=>'string'], 'ssh2_sftp_mkdir' => ['bool', 'sftp'=>'resource', 'dirname'=>'string', 'mode='=>'int', 'recursive='=>'bool'], 'ssh2_sftp_readlink' => ['string|false', 'sftp'=>'resource', 'link'=>'string'], 'ssh2_sftp_realpath' => ['string|false', 'sftp'=>'resource', 'filename'=>'string'], 'ssh2_sftp_rename' => ['bool', 'sftp'=>'resource', 'from'=>'string', 'to'=>'string'], 'ssh2_sftp_rmdir' => ['bool', 'sftp'=>'resource', 'dirname'=>'string'], 'ssh2_sftp_stat' => ['array|false', 'sftp'=>'resource', 'path'=>'string'], 'ssh2_sftp_symlink' => ['bool', 'sftp'=>'resource', 'target'=>'string', 'link'=>'string'], 'ssh2_sftp_unlink' => ['bool', 'sftp'=>'resource', 'filename'=>'string'], 'ssh2_shell' => ['resource|false', 'session'=>'resource', 'term_type='=>'string', 'env='=>'array', 'width='=>'int', 'height='=>'int', 'width_height_type='=>'int'], 'ssh2_tunnel' => ['resource|false', 'session'=>'resource', 'host'=>'string', 'port'=>'int'], 'stat' => ['array|false', 'filename'=>'string'], 'stats_absolute_deviation' => ['float', 'a'=>'array'], 'stats_cdf_beta' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_binomial' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_cauchy' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_chisquare' => ['float', 'par1'=>'float', 'par2'=>'float', 'which'=>'int'], 'stats_cdf_exponential' => ['float', 'par1'=>'float', 'par2'=>'float', 'which'=>'int'], 'stats_cdf_f' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_gamma' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_laplace' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_logistic' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_negative_binomial' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_noncentral_chisquare' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_noncentral_f' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'par4'=>'float', 'which'=>'int'], 'stats_cdf_noncentral_t' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_normal' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_poisson' => ['float', 'par1'=>'float', 'par2'=>'float', 'which'=>'int'], 'stats_cdf_t' => ['float', 'par1'=>'float', 'par2'=>'float', 'which'=>'int'], 'stats_cdf_uniform' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_cdf_weibull' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_covariance' => ['float', 'a'=>'array', 'b'=>'array'], 'stats_den_uniform' => ['float', 'x'=>'float', 'a'=>'float', 'b'=>'float'], 'stats_dens_beta' => ['float', 'x'=>'float', 'a'=>'float', 'b'=>'float'], 'stats_dens_cauchy' => ['float', 'x'=>'float', 'ave'=>'float', 'stdev'=>'float'], 'stats_dens_chisquare' => ['float', 'x'=>'float', 'dfr'=>'float'], 'stats_dens_exponential' => ['float', 'x'=>'float', 'scale'=>'float'], 'stats_dens_f' => ['float', 'x'=>'float', 'dfr1'=>'float', 'dfr2'=>'float'], 'stats_dens_gamma' => ['float', 'x'=>'float', 'shape'=>'float', 'scale'=>'float'], 'stats_dens_laplace' => ['float', 'x'=>'float', 'ave'=>'float', 'stdev'=>'float'], 'stats_dens_logistic' => ['float', 'x'=>'float', 'ave'=>'float', 'stdev'=>'float'], 'stats_dens_negative_binomial' => ['float', 'x'=>'float', 'n'=>'float', 'pi'=>'float'], 'stats_dens_normal' => ['float', 'x'=>'float', 'ave'=>'float', 'stdev'=>'float'], 'stats_dens_pmf_binomial' => ['float', 'x'=>'float', 'n'=>'float', 'pi'=>'float'], 'stats_dens_pmf_hypergeometric' => ['float', 'n1'=>'float', 'n2'=>'float', 'N1'=>'float', 'N2'=>'float'], 'stats_dens_pmf_negative_binomial' => ['float', 'x'=>'float', 'n'=>'float', 'pi'=>'float'], 'stats_dens_pmf_poisson' => ['float', 'x'=>'float', 'lb'=>'float'], 'stats_dens_t' => ['float', 'x'=>'float', 'dfr'=>'float'], 'stats_dens_uniform' => ['float', 'x'=>'float', 'a'=>'float', 'b'=>'float'], 'stats_dens_weibull' => ['float', 'x'=>'float', 'a'=>'float', 'b'=>'float'], 'stats_harmonic_mean' => ['float', 'a'=>'array'], 'stats_kurtosis' => ['float', 'a'=>'array'], 'stats_rand_gen_beta' => ['float', 'a'=>'float', 'b'=>'float'], 'stats_rand_gen_chisquare' => ['float', 'df'=>'float'], 'stats_rand_gen_exponential' => ['float', 'av'=>'float'], 'stats_rand_gen_f' => ['float', 'dfn'=>'float', 'dfd'=>'float'], 'stats_rand_gen_funiform' => ['float', 'low'=>'float', 'high'=>'float'], 'stats_rand_gen_gamma' => ['float', 'a'=>'float', 'r'=>'float'], 'stats_rand_gen_ibinomial' => ['int', 'n'=>'int', 'pp'=>'float'], 'stats_rand_gen_ibinomial_negative' => ['int', 'n'=>'int', 'p'=>'float'], 'stats_rand_gen_int' => ['int'], 'stats_rand_gen_ipoisson' => ['int', 'mu'=>'float'], 'stats_rand_gen_iuniform' => ['int', 'low'=>'int', 'high'=>'int'], 'stats_rand_gen_noncenral_chisquare' => ['float', 'df'=>'float', 'xnonc'=>'float'], 'stats_rand_gen_noncentral_chisquare' => ['float', 'df'=>'float', 'xnonc'=>'float'], 'stats_rand_gen_noncentral_f' => ['float', 'dfn'=>'float', 'dfd'=>'float', 'xnonc'=>'float'], 'stats_rand_gen_noncentral_t' => ['float', 'df'=>'float', 'xnonc'=>'float'], 'stats_rand_gen_normal' => ['float', 'av'=>'float', 'sd'=>'float'], 'stats_rand_gen_t' => ['float', 'df'=>'float'], 'stats_rand_get_seeds' => ['array'], 'stats_rand_phrase_to_seeds' => ['array', 'phrase'=>'string'], 'stats_rand_ranf' => ['float'], 'stats_rand_setall' => ['void', 'iseed1'=>'int', 'iseed2'=>'int'], 'stats_skew' => ['float', 'a'=>'array'], 'stats_standard_deviation' => ['float', 'a'=>'array', 'sample='=>'bool'], 'stats_stat_binomial_coef' => ['float', 'x'=>'int', 'n'=>'int'], 'stats_stat_correlation' => ['float', 'arr1'=>'array', 'arr2'=>'array'], 'stats_stat_factorial' => ['float', 'n'=>'int'], 'stats_stat_gennch' => ['float', 'n'=>'int'], 'stats_stat_independent_t' => ['float', 'arr1'=>'array', 'arr2'=>'array'], 'stats_stat_innerproduct' => ['float', 'arr1'=>'array', 'arr2'=>'array'], 'stats_stat_noncentral_t' => ['float', 'par1'=>'float', 'par2'=>'float', 'par3'=>'float', 'which'=>'int'], 'stats_stat_paired_t' => ['float', 'arr1'=>'array', 'arr2'=>'array'], 'stats_stat_percentile' => ['float', 'df'=>'float', 'xnonc'=>'float'], 'stats_stat_powersum' => ['float', 'arr'=>'array', 'power'=>'float'], 'stats_variance' => ['float', 'a'=>'array', 'sample='=>'bool'], 'Stomp::__construct' => ['void', 'broker='=>'string', 'username='=>'string', 'password='=>'string', 'headers='=>'array'], 'Stomp::__destruct' => ['bool', 'link'=>''], 'Stomp::abort' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'Stomp::ack' => ['bool', 'msg'=>'', 'headers='=>'array', 'link='=>''], 'Stomp::begin' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'Stomp::commit' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'Stomp::error' => ['string', 'link'=>''], 'Stomp::getReadTimeout' => ['array', 'link'=>''], 'Stomp::getSessionId' => ['string', 'link'=>''], 'Stomp::hasFrame' => ['bool', 'link'=>''], 'Stomp::readFrame' => ['array', 'class_name='=>'string', 'link='=>''], 'Stomp::send' => ['bool', 'destination'=>'string', 'msg'=>'', 'headers='=>'array', 'link='=>''], 'Stomp::setReadTimeout' => ['', 'seconds'=>'int', 'microseconds='=>'int', 'link='=>''], 'Stomp::subscribe' => ['bool', 'destination'=>'string', 'headers='=>'array', 'link='=>''], 'Stomp::unsubscribe' => ['bool', 'destination'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_abort' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_ack' => ['bool', 'msg'=>'', 'headers='=>'array', 'link='=>''], 'stomp_begin' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_close' => ['bool', 'link'=>''], 'stomp_commit' => ['bool', 'transaction_id'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_connect' => ['resource', 'broker='=>'string', 'username='=>'string', 'password='=>'string', 'headers='=>'array'], 'stomp_connect_error' => ['string'], 'stomp_error' => ['string', 'link'=>''], 'stomp_get_read_timeout' => ['array', 'link'=>''], 'stomp_get_session_id' => ['string', 'link'=>''], 'stomp_has_frame' => ['bool', 'link'=>''], 'stomp_read_frame' => ['array', 'class_name='=>'string', 'link='=>''], 'stomp_send' => ['bool', 'destination'=>'string', 'msg'=>'', 'headers='=>'array', 'link='=>''], 'stomp_set_read_timeout' => ['', 'seconds'=>'int', 'microseconds='=>'int', 'link='=>''], 'stomp_subscribe' => ['bool', 'destination'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_unsubscribe' => ['bool', 'destination'=>'string', 'headers='=>'array', 'link='=>''], 'stomp_version' => ['string'], 'StompException::getDetails' => ['string'], 'StompFrame::__construct' => ['void', 'command='=>'string', 'headers='=>'array', 'body='=>'string'], 'str_getcsv' => ['non-empty-list', 'input'=>'string', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'str_ireplace' => ['string|string[]', 'search'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', '&w_replace_count='=>'int'], 'str_pad' => ['string', 'input'=>'string', 'pad_length'=>'int', 'pad_string='=>'string', 'pad_type='=>'int'], 'str_repeat' => ['string', 'input'=>'string', 'multiplier'=>'int'], 'str_replace' => ['string|array', 'search'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', '&w_replace_count='=>'int'], 'str_rot13' => ['string', 'str'=>'string'], 'str_shuffle' => ['string', 'str'=>'string'], 'str_split' => ['non-empty-list|false', 'str'=>'string', 'split_length='=>'positive-int'], 'str_word_count' => ['array|int|false', 'string'=>'string', 'format='=>'int', 'charlist='=>'string'], 'strcasecmp' => ['int<-1, 1>', 'str1'=>'string', 'str2'=>'string'], 'strchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'before_needle='=>'bool'], 'strcmp' => ['int<-1, 1>', 'str1'=>'string', 'str2'=>'string'], 'strcoll' => ['int<-1, 1>', 'str1'=>'string', 'str2'=>'string'], 'strcspn' => ['int', 'str'=>'string', 'mask'=>'string', 'start='=>'int', 'length='=>'int'], 'stream_bucket_append' => ['void', 'brigade'=>'resource', 'bucket'=>'object'], 'stream_bucket_make_writeable' => ['stdClass|null', 'brigade'=>'resource'], 'stream_bucket_new' => ['object', 'stream'=>'resource', 'buffer'=>'string'], 'stream_bucket_prepend' => ['void', 'brigade'=>'resource', 'bucket'=>'object'], 'stream_context_create' => ['resource', 'options='=>'array', 'params='=>'array'], 'stream_context_get_default' => ['resource', 'options='=>'array'], 'stream_context_get_options' => ['array', 'context'=>'resource'], 'stream_context_get_params' => ['array{notification:string, options:array}', 'context'=>'resource'], 'stream_context_set_default' => ['resource', 'options'=>'array'], 'stream_context_set_option' => ['bool', 'context'=>'', 'wrappername'=>'string', 'optionname'=>'string', 'value'=>''], 'stream_context_set_option\'1' => ['bool', 'context'=>'', 'options'=>'array'], 'stream_context_set_params' => ['bool', 'context'=>'resource', 'options'=>'array'], 'stream_copy_to_stream' => ['int|false', 'source'=>'resource', 'dest'=>'resource', 'maxlen='=>'int', 'pos='=>'int'], 'stream_encoding' => ['bool', 'stream'=>'resource', 'encoding='=>'string'], 'stream_filter_append' => ['resource|false', 'stream'=>'resource', 'filtername'=>'string', 'read_write='=>'int', 'filterparams='=>'array'], 'stream_filter_prepend' => ['resource|false', 'stream'=>'resource', 'filtername'=>'string', 'read_write='=>'int', 'filterparams='=>'array'], 'stream_filter_register' => ['bool', 'filtername'=>'string', 'classname'=>'string'], 'stream_filter_remove' => ['bool', 'stream_filter'=>'resource'], 'stream_get_contents' => ['string|false', 'source'=>'resource', 'maxlen='=>'int', 'offset='=>'int'], 'stream_get_filters' => ['list'], 'stream_get_line' => ['string|false', 'stream'=>'resource', 'maxlen'=>'int', 'ending='=>'string'], 'stream_get_meta_data' => ['array{timed_out:bool,blocked:bool,eof:bool,unread_bytes:int,stream_type:string,wrapper_type:string,wrapper_data:mixed,mode:string,seekable:bool,uri?:string,mediatype?:string,base64?:bool}', 'fp'=>'resource'], 'stream_get_transports' => ['list'], 'stream_get_wrappers' => ['list'], 'stream_is_local' => ['bool', 'stream'=>'resource|string'], 'stream_isatty' => ['bool', 'stream'=>'resource'], 'stream_notification_callback' => ['callback', 'notification_code'=>'int', 'severity'=>'int', 'message'=>'string', 'message_code'=>'int', 'bytes_transferred'=>'int', 'bytes_max'=>'int'], 'stream_resolve_include_path' => ['string|false', 'filename'=>'string'], 'stream_select' => ['int|false', '&rw_read_streams'=>'resource[]|null', '&rw_write_streams'=>'resource[]|null', '&rw_except_streams'=>'resource[]|null', 'tv_sec'=>'?int', 'tv_usec='=>'?int'], 'stream_set_blocking' => ['bool', 'socket'=>'resource', 'mode'=>'bool'], 'stream_set_chunk_size' => ['int|false', 'fp'=>'resource', 'chunk_size'=>'int'], 'stream_set_read_buffer' => ['int', 'fp'=>'resource', 'buffer'=>'int'], 'stream_set_timeout' => ['bool', 'stream'=>'resource', 'seconds'=>'int', 'microseconds='=>'int'], 'stream_set_write_buffer' => ['int', 'fp'=>'resource', 'buffer'=>'int'], 'stream_socket_accept' => ['resource|false', 'serverstream'=>'resource', 'timeout='=>'float', '&w_peername='=>'string'], 'stream_socket_client' => ['resource|false', 'remoteaddress'=>'string', '&w_errcode='=>'int', '&w_errstring='=>'string', 'timeout='=>'float', 'flags='=>'int', 'context='=>'resource'], 'stream_socket_enable_crypto' => ['0|bool', 'stream'=>'resource', 'enable'=>'bool', 'cryptokind='=>'int', 'sessionstream='=>'resource'], 'stream_socket_get_name' => ['string|false', 'stream'=>'resource', 'want_peer'=>'bool'], 'stream_socket_pair' => ['resource[]|false', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int'], 'stream_socket_recvfrom' => ['string|false', 'stream'=>'resource', 'amount'=>'int', 'flags='=>'int', '&w_remote_addr='=>'string'], 'stream_socket_sendto' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'flags='=>'int', 'target_addr='=>'string'], 'stream_socket_server' => ['resource|false', 'localaddress'=>'string', '&w_errcode='=>'int', '&w_errstring='=>'string', 'flags='=>'int', 'context='=>'resource'], 'stream_socket_shutdown' => ['bool', 'stream'=>'resource', 'how'=>'int'], 'stream_supports_lock' => ['bool', 'stream'=>'resource'], 'stream_wrapper_register' => ['bool', 'protocol'=>'string', 'classname'=>'string', 'flags='=>'int'], 'stream_wrapper_restore' => ['bool', 'protocol'=>'string'], 'stream_wrapper_unregister' => ['bool', 'protocol'=>'string'], 'streamWrapper::__construct' => ['void'], 'streamWrapper::__destruct' => [''], 'streamWrapper::dir_closedir' => ['bool'], 'streamWrapper::dir_opendir' => ['bool', 'path'=>'string', 'options'=>'int'], 'streamWrapper::dir_readdir' => ['string'], 'streamWrapper::dir_rewinddir' => ['bool'], 'streamWrapper::mkdir' => ['bool', 'path'=>'string', 'mode'=>'int', 'options'=>'int'], 'streamWrapper::rename' => ['bool', 'path_from'=>'string', 'path_to'=>'string'], 'streamWrapper::rmdir' => ['bool', 'path'=>'string', 'options'=>'int'], 'streamWrapper::stream_cast' => ['resource', 'cast_as'=>'int'], 'streamWrapper::stream_close' => ['void'], 'streamWrapper::stream_eof' => ['bool'], 'streamWrapper::stream_flush' => ['bool'], 'streamWrapper::stream_lock' => ['bool', 'operation'=>'mode'], 'streamWrapper::stream_metadata' => ['bool', 'path'=>'string', 'option'=>'int', 'value'=>'mixed'], 'streamWrapper::stream_open' => ['bool', 'path'=>'string', 'mode'=>'string', 'options'=>'int', 'opened_path'=>'string'], 'streamWrapper::stream_read' => ['string', 'count'=>'int'], 'streamWrapper::stream_seek' => ['bool', 'offset'=>'int', 'whence'=>'int'], 'streamWrapper::stream_set_option' => ['bool', 'option'=>'int', 'arg1'=>'int', 'arg2'=>'int'], 'streamWrapper::stream_stat' => ['array'], 'streamWrapper::stream_tell' => ['int'], 'streamWrapper::stream_truncate' => ['bool', 'new_size'=>'int'], 'streamWrapper::stream_write' => ['int', 'data'=>'string'], 'streamWrapper::unlink' => ['bool', 'path'=>'string'], 'streamWrapper::url_stat' => ['array', 'path'=>'string', 'flags'=>'int'], 'strftime' => ['string|false', 'format'=>'string', 'timestamp='=>'int'], 'strip_tags' => ['string', 'str'=>'string', 'allowable_tags='=>'string'], 'stripcslashes' => ['string', 'str'=>'string'], 'stripos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'stripslashes' => ['string', 'str'=>'string'], 'stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'mixed', 'before_needle='=>'bool'], 'strlen' => ['0|positive-int', 'string'=>'string'], 'strnatcasecmp' => ['int<-1, 1>', 's1'=>'string', 's2'=>'string'], 'strnatcmp' => ['int<-1, 1>', 's1'=>'string', 's2'=>'string'], 'strncasecmp' => ['int<-1, 1>', 'str1'=>'string', 'str2'=>'string', 'len'=>'int'], 'strncmp' => ['int<-1, 1>', 'str1'=>'string', 'str2'=>'string', 'len'=>'int'], 'strpbrk' => ['string|false', 'haystack'=>'string', 'char_list'=>'string'], 'strpos' => ['positive-int|0|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strptime' => ['array|false', 'datestr'=>'string', 'format'=>'string'], 'strrchr' => ['string|false', 'haystack'=>'string', 'needle'=>'mixed'], 'strrev' => ['string', 'str'=>'string'], 'strripos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strrpos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strspn' => ['int', 'str'=>'string', 'mask'=>'string', 'start='=>'int', 'len='=>'int'], 'strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'mixed', 'before_needle='=>'bool'], 'strtok' => ['non-empty-string|false', 'str'=>'string', 'token'=>'string'], 'strtok\'1' => ['non-empty-string|false', 'token'=>'string'], 'strtolower' => ['lowercase-string', 'str'=>'string'], 'strtotime' => ['int|false', 'time'=>'string', 'now='=>'int'], 'strtoupper' => ['uppercase-string', 'str'=>'string'], 'strtr' => ['string', 'str'=>'string', 'from'=>'string', 'to'=>'string'], 'strtr\'1' => ['string', 'str'=>'string', 'replace_pairs'=>'array'], 'strval' => ['string', 'var'=>'__stringAndStringable|int|float|bool|resource|null'], 'substr' => ['__benevolent', 'string'=>'string', 'start'=>'int', 'length='=>'int'], 'substr_compare' => ['int<-1, 1>|false', 'main_str'=>'string', 'str'=>'string', 'offset'=>'int', 'length='=>'int', 'case_sensitivity='=>'bool'], 'substr_count' => ['0|positive-int', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int', 'length='=>'int'], 'substr_replace' => ['string|array', 'str'=>'string|array', 'repl'=>'mixed', 'start'=>'mixed', 'length='=>'mixed'], 'suhosin_encrypt_cookie' => ['string', 'name'=>'string', 'value'=>'string'], 'suhosin_get_raw_cookies' => ['array'], 'SVM::__construct' => ['void'], 'svm::crossvalidate' => ['float', 'problem'=>'array', 'number_of_folds'=>'int'], 'SVM::getOptions' => ['array'], 'SVM::setOptions' => ['bool', 'params'=>'array'], 'svm::train' => ['SVMModel', 'problem'=>'array', 'weights='=>'array'], 'SVMModel::__construct' => ['void', 'filename='=>'string'], 'SVMModel::checkProbabilityModel' => ['bool'], 'SVMModel::getLabels' => ['array'], 'SVMModel::getNrClass' => ['int'], 'SVMModel::getSvmType' => ['int'], 'SVMModel::getSvrProbability' => ['float'], 'SVMModel::load' => ['bool', 'filename'=>'string'], 'SVMModel::predict' => ['float', 'data'=>'array'], 'SVMModel::predict_probability' => ['float', 'data'=>'array'], 'SVMModel::save' => ['bool', 'filename'=>'string'], 'svn_add' => ['bool', 'path'=>'string', 'recursive='=>'bool', 'force='=>'bool'], 'svn_auth_get_parameter' => ['string', 'key'=>'string'], 'svn_auth_set_parameter' => ['void', 'key'=>'string', 'value'=>'string'], 'svn_blame' => ['array', 'repository_url'=>'string', 'revision_no='=>'int'], 'svn_cat' => ['string', 'repos_url'=>'string', 'revision_no='=>'int'], 'svn_checkout' => ['bool', 'repos'=>'string', 'targetpath'=>'string', 'revision='=>'int', 'flags='=>'int'], 'svn_cleanup' => ['bool', 'workingdir'=>'string'], 'svn_client_version' => ['string'], 'svn_commit' => ['array', 'log'=>'string', 'targets'=>'array', 'dontrecurse='=>'bool'], 'svn_delete' => ['bool', 'path'=>'string', 'force='=>'bool'], 'svn_diff' => ['array', 'path1'=>'string', 'rev1'=>'int', 'path2'=>'string', 'rev2'=>'int'], 'svn_export' => ['bool', 'frompath'=>'string', 'topath'=>'string', 'working_copy='=>'bool', 'revision_no='=>'int'], 'svn_fs_abort_txn' => ['bool', 'txn'=>'resource'], 'svn_fs_apply_text' => ['resource', 'root'=>'resource', 'path'=>'string'], 'svn_fs_begin_txn2' => ['resource', 'repos'=>'resource', 'rev'=>'int'], 'svn_fs_change_node_prop' => ['bool', 'root'=>'resource', 'path'=>'string', 'name'=>'string', 'value'=>'string'], 'svn_fs_check_path' => ['int', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_contents_changed' => ['bool', 'root1'=>'resource', 'path1'=>'string', 'root2'=>'resource', 'path2'=>'string'], 'svn_fs_copy' => ['bool', 'from_root'=>'resource', 'from_path'=>'string', 'to_root'=>'resource', 'to_path'=>'string'], 'svn_fs_delete' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_dir_entries' => ['array', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_file_contents' => ['resource', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_file_length' => ['int', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_is_dir' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_is_file' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_make_dir' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_make_file' => ['bool', 'root'=>'resource', 'path'=>'string'], 'svn_fs_node_created_rev' => ['int', 'fsroot'=>'resource', 'path'=>'string'], 'svn_fs_node_prop' => ['string', 'fsroot'=>'resource', 'path'=>'string', 'propname'=>'string'], 'svn_fs_props_changed' => ['bool', 'root1'=>'resource', 'path1'=>'string', 'root2'=>'resource', 'path2'=>'string'], 'svn_fs_revision_prop' => ['string', 'fs'=>'resource', 'revnum'=>'int', 'propname'=>'string'], 'svn_fs_revision_root' => ['resource', 'fs'=>'resource', 'revnum'=>'int'], 'svn_fs_txn_root' => ['resource', 'txn'=>'resource'], 'svn_fs_youngest_rev' => ['int', 'fs'=>'resource'], 'svn_import' => ['bool', 'path'=>'string', 'url'=>'string', 'nonrecursive'=>'bool'], 'svn_log' => ['array', 'repos_url'=>'string', 'start_revision='=>'int', 'end_revision='=>'int', 'limit='=>'int', 'flags='=>'int'], 'svn_ls' => ['array', 'repos_url'=>'string', 'revision_no='=>'int', 'recurse='=>'bool', 'peg='=>'bool'], 'svn_mkdir' => ['bool', 'path'=>'string', 'log_message='=>'string'], 'svn_move' => ['mixed', 'src_path'=>'string', 'dst_path'=>'string', 'force='=>'bool|false'], 'svn_propget' => ['mixed', 'path'=>'string', 'property_name'=>'string', 'recurse='=>'bool|false', 'revision='=>'int'], 'svn_proplist' => ['mixed', 'path'=>'string', 'recurse='=>'bool|false', 'revision='=>'int'], 'svn_repos_create' => ['resource', 'path'=>'string', 'config='=>'array', 'fsconfig='=>'array'], 'svn_repos_fs' => ['resource', 'repos'=>'resource'], 'svn_repos_fs_begin_txn_for_commit' => ['resource', 'repos'=>'resource', 'rev'=>'int', 'author'=>'string', 'log_msg'=>'string'], 'svn_repos_fs_commit_txn' => ['int', 'txn'=>'resource'], 'svn_repos_hotcopy' => ['bool', 'repospath'=>'string', 'destpath'=>'string', 'cleanlogs'=>'bool'], 'svn_repos_open' => ['resource', 'path'=>'string'], 'svn_repos_recover' => ['bool', 'path'=>'string'], 'svn_revert' => ['bool', 'path'=>'string', 'recursive='=>'bool'], 'svn_status' => ['array', 'path'=>'string', 'flags='=>'int'], 'svn_update' => ['int', 'path'=>'string', 'revno='=>'int', 'recurse='=>'bool'], 'swf_actiongeturl' => ['', 'url'=>'string', 'target'=>'string'], 'swf_actiongotoframe' => ['', 'framenumber'=>'int'], 'swf_actiongotolabel' => ['', 'label'=>'string'], 'swf_actionnextframe' => [''], 'swf_actionplay' => [''], 'swf_actionprevframe' => [''], 'swf_actionsettarget' => ['', 'target'=>'string'], 'swf_actionstop' => [''], 'swf_actiontogglequality' => [''], 'swf_actionwaitforframe' => ['', 'framenumber'=>'int', 'skipcount'=>'int'], 'swf_addbuttonrecord' => ['', 'states'=>'int', 'shapeid'=>'int', 'depth'=>'int'], 'swf_addcolor' => ['', 'r'=>'float', 'g'=>'float', 'b'=>'float', 'a'=>'float'], 'swf_closefile' => ['', 'return_file='=>'int'], 'swf_definebitmap' => ['', 'objid'=>'int', 'image_name'=>'string'], 'swf_definefont' => ['', 'fontid'=>'int', 'fontname'=>'string'], 'swf_defineline' => ['', 'objid'=>'int', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'width'=>'float'], 'swf_definepoly' => ['', 'objid'=>'int', 'coords'=>'array', 'npoints'=>'int', 'width'=>'float'], 'swf_definerect' => ['', 'objid'=>'int', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'width'=>'float'], 'swf_definetext' => ['', 'objid'=>'int', 'str'=>'string', 'docenter'=>'int'], 'swf_endbutton' => [''], 'swf_enddoaction' => [''], 'swf_endshape' => [''], 'swf_endsymbol' => [''], 'swf_fontsize' => ['', 'size'=>'float'], 'swf_fontslant' => ['', 'slant'=>'float'], 'swf_fonttracking' => ['', 'tracking'=>'float'], 'swf_getbitmapinfo' => ['array', 'bitmapid'=>'int'], 'swf_getfontinfo' => ['array'], 'swf_getframe' => ['int'], 'swf_labelframe' => ['', 'name'=>'string'], 'swf_lookat' => ['', 'view_x'=>'float', 'view_y'=>'float', 'view_z'=>'float', 'reference_x'=>'float', 'reference_y'=>'float', 'reference_z'=>'float', 'twist'=>'float'], 'swf_modifyobject' => ['', 'depth'=>'int', 'how'=>'int'], 'swf_mulcolor' => ['', 'r'=>'float', 'g'=>'float', 'b'=>'float', 'a'=>'float'], 'swf_nextid' => ['int'], 'swf_oncondition' => ['', 'transition'=>'int'], 'swf_openfile' => ['', 'filename'=>'string', 'width'=>'float', 'height'=>'float', 'framerate'=>'float', 'r'=>'float', 'g'=>'float', 'b'=>'float'], 'swf_ortho' => ['', 'xmin'=>'float', 'xmax'=>'float', 'ymin'=>'float', 'ymax'=>'float', 'zmin'=>'float', 'zmax'=>'float'], 'swf_ortho2' => ['', 'xmin'=>'float', 'xmax'=>'float', 'ymin'=>'float', 'ymax'=>'float'], 'swf_perspective' => ['', 'fovy'=>'float', 'aspect'=>'float', 'near'=>'float', 'far'=>'float'], 'swf_placeobject' => ['', 'objid'=>'int', 'depth'=>'int'], 'swf_polarview' => ['', 'dist'=>'float', 'azimuth'=>'float', 'incidence'=>'float', 'twist'=>'float'], 'swf_popmatrix' => [''], 'swf_posround' => ['', 'round'=>'int'], 'swf_pushmatrix' => [''], 'swf_removeobject' => ['', 'depth'=>'int'], 'swf_rotate' => ['', 'angle'=>'float', 'axis'=>'string'], 'swf_scale' => ['', 'x'=>'float', 'y'=>'float', 'z'=>'float'], 'swf_setfont' => ['', 'fontid'=>'int'], 'swf_setframe' => ['', 'framenumber'=>'int'], 'swf_shapearc' => ['', 'x'=>'float', 'y'=>'float', 'r'=>'float', 'ang1'=>'float', 'ang2'=>'float'], 'swf_shapecurveto' => ['', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float'], 'swf_shapecurveto3' => ['', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x3'=>'float', 'y3'=>'float'], 'swf_shapefillbitmapclip' => ['', 'bitmapid'=>'int'], 'swf_shapefillbitmaptile' => ['', 'bitmapid'=>'int'], 'swf_shapefilloff' => [''], 'swf_shapefillsolid' => ['', 'r'=>'float', 'g'=>'float', 'b'=>'float', 'a'=>'float'], 'swf_shapelinesolid' => ['', 'r'=>'float', 'g'=>'float', 'b'=>'float', 'a'=>'float', 'width'=>'float'], 'swf_shapelineto' => ['', 'x'=>'float', 'y'=>'float'], 'swf_shapemoveto' => ['', 'x'=>'float', 'y'=>'float'], 'swf_showframe' => [''], 'swf_startbutton' => ['', 'objid'=>'int', 'type'=>'int'], 'swf_startdoaction' => [''], 'swf_startshape' => ['', 'objid'=>'int'], 'swf_startsymbol' => ['', 'objid'=>'int'], 'swf_textwidth' => ['float', 'str'=>'string'], 'swf_translate' => ['', 'x'=>'float', 'y'=>'float', 'z'=>'float'], 'swf_viewport' => ['', 'xmin'=>'float', 'xmax'=>'float', 'ymin'=>'float', 'ymax'=>'float'], 'SWFAction::__construct' => ['void', 'script'=>'string'], 'SWFBitmap::__construct' => ['void', 'file'=>'', 'alphafile='=>''], 'SWFBitmap::getHeight' => ['float'], 'SWFBitmap::getWidth' => ['float'], 'SWFButton::__construct' => ['void'], 'SWFButton::addAction' => ['void', 'action'=>'swfaction', 'flags'=>'int'], 'SWFButton::addASound' => ['SWFSoundInstance', 'sound'=>'swfsound', 'flags'=>'int'], 'SWFButton::addShape' => ['void', 'shape'=>'swfshape', 'flags'=>'int'], 'SWFButton::setAction' => ['void', 'action'=>'swfaction'], 'SWFButton::setDown' => ['void', 'shape'=>'swfshape'], 'SWFButton::setHit' => ['void', 'shape'=>'swfshape'], 'SWFButton::setMenu' => ['void', 'flag'=>'int'], 'SWFButton::setOver' => ['void', 'shape'=>'swfshape'], 'SWFButton::setUp' => ['void', 'shape'=>'swfshape'], 'SWFDisplayItem::addAction' => ['void', 'action'=>'swfaction', 'flags'=>'int'], 'SWFDisplayItem::addColor' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFDisplayItem::endMask' => ['void'], 'SWFDisplayItem::getRot' => ['float'], 'SWFDisplayItem::getX' => ['float'], 'SWFDisplayItem::getXScale' => ['float'], 'SWFDisplayItem::getXSkew' => ['float'], 'SWFDisplayItem::getY' => ['float'], 'SWFDisplayItem::getYScale' => ['float'], 'SWFDisplayItem::getYSkew' => ['float'], 'SWFDisplayItem::move' => ['void', 'dx'=>'float', 'dy'=>'float'], 'SWFDisplayItem::moveTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFDisplayItem::multColor' => ['void', 'red'=>'float', 'green'=>'float', 'blue'=>'float', 'a='=>'float'], 'SWFDisplayItem::remove' => ['void'], 'SWFDisplayItem::rotate' => ['void', 'angle'=>'float'], 'SWFDisplayItem::rotateTo' => ['void', 'angle'=>'float'], 'SWFDisplayItem::scale' => ['void', 'dx'=>'float', 'dy'=>'float'], 'SWFDisplayItem::scaleTo' => ['void', 'x'=>'float', 'y='=>'float'], 'SWFDisplayItem::setDepth' => ['void', 'depth'=>'int'], 'SWFDisplayItem::setMaskLevel' => ['void', 'level'=>'int'], 'SWFDisplayItem::setMatrix' => ['void', 'a'=>'float', 'b'=>'float', 'c'=>'float', 'd'=>'float', 'x'=>'float', 'y'=>'float'], 'SWFDisplayItem::setName' => ['void', 'name'=>'string'], 'SWFDisplayItem::setRatio' => ['void', 'ratio'=>'float'], 'SWFDisplayItem::skewX' => ['void', 'ddegrees'=>'float'], 'SWFDisplayItem::skewXTo' => ['void', 'degrees'=>'float'], 'SWFDisplayItem::skewY' => ['void', 'ddegrees'=>'float'], 'SWFDisplayItem::skewYTo' => ['void', 'degrees'=>'float'], 'SWFFill::moveTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFFill::rotateTo' => ['void', 'angle'=>'float'], 'SWFFill::scaleTo' => ['void', 'x'=>'float', 'y='=>'float'], 'SWFFill::skewXTo' => ['void', 'x'=>'float'], 'SWFFill::skewYTo' => ['void', 'y'=>'float'], 'SWFFont::__construct' => ['void', 'filename'=>'string'], 'SWFFont::getAscent' => ['float'], 'SWFFont::getDescent' => ['float'], 'SWFFont::getLeading' => ['float'], 'SWFFont::getShape' => ['string', 'code'=>'int'], 'SWFFont::getUTF8Width' => ['float', 'string'=>'string'], 'SWFFont::getWidth' => ['float', 'string'=>'string'], 'SWFFontChar::addChars' => ['void', 'char'=>'string'], 'SWFFontChar::addUTF8Chars' => ['void', 'char'=>'string'], 'SWFGradient::__construct' => ['void'], 'SWFGradient::addEntry' => ['void', 'ratio'=>'float', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha='=>'int'], 'SWFMorph::__construct' => ['void'], 'SWFMorph::getShape1' => ['SWFShape'], 'SWFMorph::getShape2' => ['SWFShape'], 'SWFMovie::__construct' => ['void', 'version='=>'int'], 'SWFMovie::add' => ['mixed', 'instance'=>'object'], 'SWFMovie::addExport' => ['void', 'char'=>'swfcharacter', 'name'=>'string'], 'SWFMovie::addFont' => ['mixed', 'font'=>'swffont'], 'SWFMovie::importChar' => ['SWFSprite', 'libswf'=>'string', 'name'=>'string'], 'SWFMovie::importFont' => ['SWFFontChar', 'libswf'=>'string', 'name'=>'string'], 'SWFMovie::labelFrame' => ['void', 'label'=>'string'], 'SWFMovie::nextFrame' => ['void'], 'SWFMovie::output' => ['int', 'compression='=>'int'], 'SWFMovie::remove' => ['void', 'instance'=>'object'], 'SWFMovie::save' => ['int', 'filename'=>'string', 'compression='=>'int'], 'SWFMovie::saveToFile' => ['int', 'x'=>'resource', 'compression='=>'int'], 'SWFMovie::setbackground' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'SWFMovie::setDimension' => ['void', 'width'=>'float', 'height'=>'float'], 'SWFMovie::setFrames' => ['void', 'number'=>'int'], 'SWFMovie::setRate' => ['void', 'rate'=>'float'], 'SWFMovie::startSound' => ['SWFSoundInstance', 'sound'=>'swfsound'], 'SWFMovie::stopSound' => ['void', 'sound'=>'swfsound'], 'SWFMovie::streamMP3' => ['int', 'mp3file'=>'mixed', 'skip='=>'float'], 'SWFMovie::writeExports' => ['void'], 'SWFPrebuiltClip::__construct' => ['void', 'file'=>''], 'SWFShape::__construct' => ['void'], 'SWFShape::addFill' => ['SWFFill', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha='=>'int', 'bitmap='=>'swfbitmap', 'flags='=>'int', 'gradient='=>'swfgradient'], 'SWFShape::addFill\'1' => ['SWFFill', 'bitmap'=>'SWFBitmap', 'flags='=>'int'], 'SWFShape::addFill\'2' => ['SWFFill', 'gradient'=>'SWFGradient', 'flags='=>'int'], 'SWFShape::drawArc' => ['void', 'r'=>'float', 'startangle'=>'float', 'endangle'=>'float'], 'SWFShape::drawCircle' => ['void', 'r'=>'float'], 'SWFShape::drawCubic' => ['int', 'bx'=>'float', 'by'=>'float', 'cx'=>'float', 'cy'=>'float', 'dx'=>'float', 'dy'=>'float'], 'SWFShape::drawCubicTo' => ['int', 'bx'=>'float', 'by'=>'float', 'cx'=>'float', 'cy'=>'float', 'dx'=>'float', 'dy'=>'float'], 'SWFShape::drawCurve' => ['int', 'controldx'=>'float', 'controldy'=>'float', 'anchordx'=>'float', 'anchordy'=>'float', 'targetdx='=>'float', 'targetdy='=>'float'], 'SWFShape::drawCurveTo' => ['int', 'controlx'=>'float', 'controly'=>'float', 'anchorx'=>'float', 'anchory'=>'float', 'targetx='=>'float', 'targety='=>'float'], 'SWFShape::drawGlyph' => ['void', 'font'=>'swffont', 'character'=>'string', 'size='=>'int'], 'SWFShape::drawLine' => ['void', 'dx'=>'float', 'dy'=>'float'], 'SWFShape::drawLineTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFShape::movePen' => ['void', 'dx'=>'float', 'dy'=>'float'], 'SWFShape::movePenTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFShape::setLeftFill' => ['', 'fill'=>'swfgradient', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFShape::setLine' => ['', 'shape'=>'swfshape', 'width'=>'int', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFShape::setRightFill' => ['', 'fill'=>'swfgradient', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFSound' => ['SWFSound', 'filename'=>'string', 'flags='=>'int'], 'SWFSound::__construct' => ['void', 'filename'=>'string', 'flags='=>'int'], 'SWFSoundInstance::loopCount' => ['void', 'point'=>'int'], 'SWFSoundInstance::loopInPoint' => ['void', 'point'=>'int'], 'SWFSoundInstance::loopOutPoint' => ['void', 'point'=>'int'], 'SWFSoundInstance::noMultiple' => ['void'], 'SWFSprite::__construct' => ['void'], 'SWFSprite::add' => ['void', 'object'=>'object'], 'SWFSprite::labelFrame' => ['void', 'label'=>'string'], 'SWFSprite::nextFrame' => ['void'], 'SWFSprite::remove' => ['void', 'object'=>'object'], 'SWFSprite::setFrames' => ['void', 'number'=>'int'], 'SWFSprite::startSound' => ['SWFSoundInstance', 'sount'=>'swfsound'], 'SWFSprite::stopSound' => ['void', 'sount'=>'swfsound'], 'SWFText::__construct' => ['void'], 'SWFText::addString' => ['void', 'string'=>'string'], 'SWFText::addUTF8String' => ['void', 'text'=>'string'], 'SWFText::getAscent' => ['float'], 'SWFText::getDescent' => ['float'], 'SWFText::getLeading' => ['float'], 'SWFText::getUTF8Width' => ['float', 'string'=>'string'], 'SWFText::getWidth' => ['float', 'string'=>'string'], 'SWFText::moveTo' => ['void', 'x'=>'float', 'y'=>'float'], 'SWFText::setColor' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFText::setFont' => ['void', 'font'=>'swffont'], 'SWFText::setHeight' => ['void', 'height'=>'float'], 'SWFText::setSpacing' => ['void', 'spacing'=>'float'], 'SWFTextField::__construct' => ['void', 'flags='=>'int'], 'SWFTextField::addChars' => ['void', 'chars'=>'string'], 'SWFTextField::addString' => ['void', 'string'=>'string'], 'SWFTextField::align' => ['void', 'alignement'=>'int'], 'SWFTextField::setBounds' => ['void', 'width'=>'float', 'height'=>'float'], 'SWFTextField::setColor' => ['void', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'a='=>'int'], 'SWFTextField::setFont' => ['void', 'font'=>'swffont'], 'SWFTextField::setHeight' => ['void', 'height'=>'float'], 'SWFTextField::setIndentation' => ['void', 'width'=>'float'], 'SWFTextField::setLeftMargin' => ['void', 'width'=>'float'], 'SWFTextField::setLineSpacing' => ['void', 'height'=>'float'], 'SWFTextField::setMargins' => ['void', 'left'=>'float', 'right'=>'float'], 'SWFTextField::setName' => ['void', 'name'=>'string'], 'SWFTextField::setPadding' => ['void', 'padding'=>'float'], 'SWFTextField::setRightMargin' => ['void', 'width'=>'float'], 'SWFVideoStream::__construct' => ['void', 'file='=>'string'], 'SWFVideoStream::getNumFrames' => ['int'], 'SWFVideoStream::setDimension' => ['void', 'x'=>'int', 'y'=>'int'], 'Swish::__construct' => ['void', 'index_names'=>'string'], 'Swish::getMetaList' => ['array', 'index_name'=>'string'], 'Swish::getPropertyList' => ['array', 'index_name'=>'string'], 'Swish::prepare' => ['object', 'query='=>'string'], 'Swish::query' => ['object', 'query'=>'string'], 'SwishResult::getMetaList' => ['array'], 'SwishResult::stem' => ['array', 'word'=>'string'], 'SwishResults::getParsedWords' => ['array', 'index_name'=>'string'], 'SwishResults::getRemovedStopwords' => ['array', 'index_name'=>'string'], 'SwishResults::nextResult' => ['object'], 'SwishResults::seekResult' => ['int', 'position'=>'int'], 'SwishSearch::execute' => ['object', 'query='=>'string'], 'SwishSearch::resetLimit' => [''], 'SwishSearch::setLimit' => ['', 'property'=>'string', 'low'=>'string', 'high'=>'string'], 'SwishSearch::setPhraseDelimiter' => ['', 'delimiter'=>'string'], 'SwishSearch::setSort' => ['', 'sort'=>'string'], 'SwishSearch::setStructure' => ['', 'structure'=>'int'], 'swoole_async_dns_lookup' => ['bool', 'hostname'=>'string', 'callback'=>'callable'], 'swoole_async_read' => ['bool', 'filename'=>'string', 'callback'=>'callable', 'chunk_size='=>'int', 'offset='=>'int'], 'swoole_async_readfile' => ['bool', 'filename'=>'string', 'callback'=>'string'], 'swoole_async_set' => ['void', 'settings'=>'array'], 'swoole_async_write' => ['bool', 'filename'=>'string', 'content'=>'string', 'offset='=>'int', 'callback='=>'callable'], 'swoole_async_writefile' => ['bool', 'filename'=>'string', 'content'=>'string', 'callback='=>'callable', 'flags='=>'int'], 'swoole_client_select' => ['int', 'read_array'=>'array', 'write_array'=>'array', 'error_array'=>'array', 'timeout='=>'float'], 'swoole_cpu_num' => ['int'], 'swoole_errno' => ['int'], 'swoole_event_add' => ['int', 'fd'=>'int', 'read_callback='=>'callable', 'write_callback='=>'callable', 'events='=>'int'], 'swoole_event_defer' => ['bool', 'callback'=>'callable'], 'swoole_event_del' => ['bool', 'fd'=>'int'], 'swoole_event_exit' => ['void'], 'swoole_event_set' => ['bool', 'fd'=>'int', 'read_callback='=>'callable', 'write_callback='=>'callable', 'events='=>'int'], 'swoole_event_wait' => ['void'], 'swoole_event_write' => ['bool', 'fd'=>'int', 'data'=>'string'], 'swoole_get_local_ip' => ['array'], 'swoole_last_error' => ['int'], 'swoole_load_module' => ['mixed', 'filename'=>'string'], 'swoole_select' => ['int', 'read_array'=>'array', 'write_array'=>'array', 'error_array'=>'array', 'timeout='=>'float'], 'swoole_set_process_name' => ['void', 'process_name'=>'string', 'size='=>'int'], 'swoole_strerror' => ['string', 'errno'=>'int', 'error_type='=>'int'], 'swoole_timer_after' => ['int', 'ms'=>'int', 'callback'=>'callable', 'param='=>'mixed'], 'swoole_timer_exists' => ['bool', 'timer_id'=>'int'], 'swoole_timer_tick' => ['int', 'ms'=>'int', 'callback'=>'callable', 'param='=>'mixed'], 'swoole_version' => ['string'], 'sybase_affected_rows' => ['int', 'link_identifier='=>'resource'], 'sybase_close' => ['bool', 'link_identifier='=>'resource'], 'sybase_connect' => ['resource', 'servername='=>'string', 'username='=>'string', 'password='=>'string', 'charset='=>'string', 'appname='=>'string', 'new='=>'bool'], 'sybase_data_seek' => ['bool', 'result_identifier'=>'resource', 'row_number'=>'int'], 'sybase_deadlock_retry_count' => ['void', 'retry_count'=>'int'], 'sybase_fetch_array' => ['array', 'result'=>'resource'], 'sybase_fetch_assoc' => ['array', 'result'=>'resource'], 'sybase_fetch_field' => ['object', 'result'=>'resource', 'field_offset='=>'int'], 'sybase_fetch_object' => ['object', 'result'=>'resource', 'object='=>'mixed'], 'sybase_fetch_row' => ['array|false', 'result'=>'resource'], 'sybase_field_seek' => ['bool', 'result'=>'resource', 'field_offset'=>'int'], 'sybase_free_result' => ['bool', 'result'=>'resource'], 'sybase_get_last_message' => ['string'], 'sybase_min_client_severity' => ['void', 'severity'=>'int'], 'sybase_min_error_severity' => ['void', 'severity'=>'int'], 'sybase_min_message_severity' => ['void', 'severity'=>'int'], 'sybase_min_server_severity' => ['void', 'severity'=>'int'], 'sybase_num_fields' => ['int', 'result'=>'resource'], 'sybase_num_rows' => ['int', 'result'=>'resource'], 'sybase_pconnect' => ['resource|false', 'servername='=>'string', 'username='=>'string', 'password='=>'string', 'charset='=>'string', 'appname='=>'string'], 'sybase_query' => ['mixed', 'query'=>'string', 'link_identifier='=>'resource'], 'sybase_result' => ['string', 'result'=>'resource', 'row'=>'int', 'field'=>'mixed'], 'sybase_select_db' => ['bool', 'database_name'=>'string', 'link_identifier='=>'resource'], 'sybase_set_message_handler' => ['bool', 'handler'=>'callable', 'connection='=>'resource'], 'sybase_unbuffered_query' => ['resource|false', 'query'=>'string', 'link_identifier'=>'resource', 'store_result='=>'bool'], 'symbolObj::__construct' => ['void', 'map'=>'mapObj', 'symbolname'=>'string'], 'symbolObj::free' => ['void'], 'symbolObj::getPatternArray' => ['array'], 'symbolObj::getPointsArray' => ['array'], 'symbolObj::ms_newSymbolObj' => ['int', 'map'=>'mapObj', 'symbolname'=>'string'], 'symbolObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'symbolObj::setImagePath' => ['int', 'filename'=>'string'], 'symbolObj::setPattern' => ['int', 'int'=>'array'], 'symbolObj::setPoints' => ['int', 'double'=>'array'], 'symlink' => ['bool', 'target'=>'string', 'link'=>'string'], 'SyncEvent::__construct' => ['void', 'name='=>'string', 'manual='=>'bool'], 'SyncEvent::fire' => ['bool'], 'SyncEvent::reset' => ['bool'], 'SyncEvent::wait' => ['bool', 'wait='=>'int'], 'SyncMutex::__construct' => ['void', 'name='=>'string'], 'SyncMutex::lock' => ['bool', 'wait='=>'int'], 'SyncMutex::unlock' => ['bool', 'all='=>'bool'], 'SyncReaderWriter::__construct' => ['void', 'name='=>'string', 'autounlock='=>'bool'], 'SyncReaderWriter::readlock' => ['bool', 'wait='=>'int'], 'SyncReaderWriter::readunlock' => ['bool'], 'SyncReaderWriter::writelock' => ['bool', 'wait='=>'int'], 'SyncReaderWriter::writeunlock' => ['bool'], 'SyncSemaphore::__construct' => ['void', 'name='=>'string', 'initialval='=>'int', 'autounlock='=>'bool'], 'SyncSemaphore::lock' => ['bool', 'wait='=>'int'], 'SyncSemaphore::unlock' => ['bool', '&w_prevcount='=>'int'], 'SyncSharedMemory::__construct' => ['void', 'name'=>'string', 'size'=>'int'], 'SyncSharedMemory::first' => ['bool'], 'SyncSharedMemory::read' => ['', 'start='=>'int', 'length='=>'int'], 'SyncSharedMemory::size' => ['bool'], 'SyncSharedMemory::write' => ['', 'string='=>'string', 'start='=>'int'], 'sys_get_temp_dir' => ['string'], 'sys_getloadavg' => ['array|false'], 'syslog' => ['bool', 'priority'=>'int', 'message'=>'string'], 'system' => ['string|false', 'command'=>'string', '&w_return_value='=>'int'], 'taint' => ['bool', '&rw_string'=>'string', '&...w_other_strings='=>'string'], 'tan' => ['float', 'number'=>'float'], 'tanh' => ['float', 'number'=>'float'], 'tcpwrap_check' => ['bool', 'daemon'=>'string', 'address'=>'string', 'user='=>'string', 'nodns='=>'bool'], 'tempnam' => ['__benevolent', 'dir'=>'string', 'prefix'=>'string'], 'textdomain' => ['string', 'domain'=>'string'], 'Thread::__construct' => ['void'], 'Thread::chunk' => ['array', 'size'=>'int', 'preserve'=>'bool'], 'Thread::count' => ['0|positive-int'], 'Thread::getCreatorId' => ['int'], 'Thread::getCurrentThread' => ['Thread|null'], 'Thread::getCurrentThreadId' => ['int'], 'Thread::getThreadId' => ['int'], 'Thread::isJoined' => ['bool'], 'Thread::isRunning' => ['bool'], 'Thread::isStarted' => ['bool'], 'Thread::isTerminated' => ['bool'], 'Thread::join' => ['bool'], 'Thread::merge' => ['bool', 'from'=>'', 'overwrite='=>'mixed'], 'Thread::notify' => ['bool'], 'Thread::notifyOne' => ['bool'], 'Thread::offsetExists' => ['bool', 'offset'=>'mixed'], 'Thread::offsetGet' => ['mixed', 'offset'=>'mixed'], 'Thread::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'Thread::offsetUnset' => ['void', 'offset'=>'mixed'], 'Thread::pop' => ['bool'], 'Thread::run' => ['void'], 'Thread::shift' => ['bool'], 'Thread::start' => ['bool', 'options='=>'int'], 'Thread::synchronized' => ['mixed', 'block'=>'Closure', '_='=>'mixed'], 'Thread::wait' => ['bool', 'timeout='=>'int'], 'Threaded::__construct' => ['void'], 'Threaded::chunk' => ['array', 'size'=>'int', 'preserve'=>'bool'], 'Threaded::count' => ['0|positive-int'], 'Threaded::extend' => ['bool', 'class'=>'string'], 'Threaded::isRunning' => ['bool'], 'Threaded::isTerminated' => ['bool'], 'Threaded::merge' => ['bool', 'from'=>'mixed', 'overwrite='=>'bool'], 'Threaded::notify' => ['bool'], 'Threaded::notifyOne' => ['bool'], 'Threaded::offsetExists' => ['bool', 'offset'=>'mixed'], 'Threaded::offsetGet' => ['mixed', 'offset'=>'mixed'], 'Threaded::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'Threaded::offsetUnset' => ['void', 'offset'=>'mixed'], 'Threaded::pop' => ['bool'], 'Threaded::run' => ['void'], 'Threaded::shift' => ['mixed'], 'Threaded::synchronized' => ['mixed', 'block'=>'Closure', '...args='=>'mixed'], 'Threaded::wait' => ['bool', 'timeout='=>'int'], 'Throwable::__toString' => ['string'], 'Throwable::getCode' => ['mixed'], 'Throwable::getFile' => ['string'], 'Throwable::getLine' => ['int'], 'Throwable::getMessage' => ['string'], 'Throwable::getPrevious' => ['Throwable|null'], 'Throwable::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'Throwable::getTraceAsString' => ['string'], 'tidy::__construct' => ['void', 'filename='=>'string', 'config='=>'', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy::body' => ['tidyNode'], 'tidy::cleanRepair' => ['bool'], 'tidy::diagnose' => ['bool'], 'tidy::getConfig' => ['array'], 'tidy::getHtmlVer' => ['int'], 'tidy::getOpt' => ['', 'option'=>'string'], 'tidy::getOptDoc' => ['string', 'optname'=>'string'], 'tidy::getRelease' => ['string'], 'tidy::getStatus' => ['int'], 'tidy::head' => ['tidyNode'], 'tidy::html' => ['tidyNode'], 'tidy::htmlver' => ['int'], 'tidy::isXhtml' => ['bool'], 'tidy::isXml' => ['bool'], 'tidy::parseFile' => ['bool', 'filename'=>'string', 'config='=>'mixed', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy::parseString' => ['bool', 'input'=>'string', 'config='=>'mixed', 'encoding='=>'string'], 'tidy::repairFile' => ['string', 'filename'=>'string', 'config='=>'mixed', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy::repairString' => ['string', 'data'=>'string', 'config='=>'mixed', 'encoding='=>'string'], 'tidy::root' => ['tidyNode'], 'tidy_access_count' => ['int', 'obj'=>'tidy'], 'tidy_clean_repair' => ['bool', 'obj'=>'tidy'], 'tidy_config_count' => ['int', 'obj'=>'tidy'], 'tidy_diagnose' => ['bool', 'obj'=>'tidy'], 'tidy_error_count' => ['int', 'obj'=>'tidy'], 'tidy_get_body' => ['tidyNode', 'obj'=>'tidy'], 'tidy_get_config' => ['array', 'obj'=>'tidy'], 'tidy_get_error_buffer' => ['string|false', 'obj'=>'tidy'], 'tidy_get_head' => ['tidyNode', 'obj'=>'tidy'], 'tidy_get_html' => ['tidyNode', 'obj'=>'tidy'], 'tidy_get_html_ver' => ['int', 'obj'=>'tidy'], 'tidy_get_opt_doc' => ['string|false', 'obj'=>'tidy', 'optname'=>'string'], 'tidy_get_output' => ['string', 'obj'=>'tidy'], 'tidy_get_release' => ['string'], 'tidy_get_root' => ['tidyNode', 'obj'=>'tidy'], 'tidy_get_status' => ['int', 'obj'=>'tidy'], 'tidy_getopt' => ['mixed', 'option'=>'string', 'obj'=>'tidy'], 'tidy_is_xhtml' => ['bool', 'obj'=>'tidy'], 'tidy_is_xml' => ['bool', 'obj'=>'tidy'], 'tidy_load_config' => ['void', 'filename'=>'string', 'encoding'=>'string'], 'tidy_parse_file' => ['tidy|false', 'file'=>'string', 'config_options='=>'', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy_parse_string' => ['tidy|false', 'input'=>'string', 'config_options='=>'', 'encoding='=>'string'], 'tidy_repair_file' => ['string|false', 'filename'=>'string', 'config_file='=>'', 'encoding='=>'string', 'use_include_path='=>'bool'], 'tidy_repair_string' => ['string|false', 'data'=>'string', 'config_file='=>'', 'encoding='=>'string'], 'tidy_reset_config' => ['bool'], 'tidy_save_config' => ['bool', 'filename'=>'string'], 'tidy_set_encoding' => ['bool', 'encoding'=>'string'], 'tidy_setopt' => ['bool', 'option'=>'string', 'value'=>'mixed'], 'tidy_warning_count' => ['int', 'obj'=>'tidy'], 'tidyNode::__construct' => ['void'], 'tidyNode::getParent' => ['tidyNode'], 'tidyNode::hasChildren' => ['bool'], 'tidyNode::hasSiblings' => ['bool'], 'tidyNode::isAsp' => ['bool'], 'tidyNode::isComment' => ['bool'], 'tidyNode::isHtml' => ['bool'], 'tidyNode::isJste' => ['bool'], 'tidyNode::isPhp' => ['bool'], 'tidyNode::isText' => ['bool'], 'time' => ['positive-int'], 'time_nanosleep' => ['array{seconds:0|positive-int,nanoseconds:0|positive-int}|bool', 'seconds'=>'int', 'nanoseconds'=>'int'], 'time_sleep_until' => ['bool', 'timestamp'=>'float'], 'timezone_abbreviations_list' => ['array>'], 'timezone_identifiers_list' => ['list', 'what='=>'int', 'country='=>'?string'], 'timezone_location_get' => ['array{country_code: string, latitude: float, longitude: float, comments: string}|false', 'object'=>'DateTimeZone'], 'timezone_name_from_abbr' => ['string|false', 'abbr'=>'string', 'gmtoffset='=>'int', 'isdst='=>'int'], 'timezone_name_get' => ['string', 'object'=>'DateTimeZone'], 'timezone_offset_get' => ['int', 'object'=>'DateTimeZone', 'datetime'=>'DateTime'], 'timezone_open' => ['DateTimeZone|false', 'timezone'=>'string'], 'timezone_transitions_get' => ['list|false', 'object'=>'DateTimeZone', 'timestamp_begin='=>'int', 'timestamp_end='=>'int'], 'timezone_version_get' => ['string'], 'tmpfile' => ['__benevolent'], 'token_get_all' => ['list', 'source'=>'string', 'flags='=>'int'], 'token_name' => ['non-falsy-string', 'type'=>'int'], 'TokyoTyrant::__construct' => ['void', 'host='=>'string', 'port='=>'int', 'options='=>'array'], 'TokyoTyrant::add' => ['int|float', 'key'=>'string', 'increment'=>'float', 'type='=>'int'], 'TokyoTyrant::connect' => ['TokyoTyrant', 'host'=>'string', 'port='=>'int', 'options='=>'array'], 'TokyoTyrant::connectUri' => ['TokyoTyrant', 'uri'=>'string'], 'TokyoTyrant::copy' => ['TokyoTyrant', 'path'=>'string'], 'TokyoTyrant::ext' => ['string', 'name'=>'string', 'options'=>'int', 'key'=>'string', 'value'=>'string'], 'TokyoTyrant::fwmKeys' => ['array', 'prefix'=>'string', 'max_recs'=>'int'], 'TokyoTyrant::get' => ['array', 'keys'=>'mixed'], 'TokyoTyrant::getIterator' => ['TokyoTyrantIterator'], 'TokyoTyrant::num' => ['int'], 'TokyoTyrant::out' => ['string', 'keys'=>'mixed'], 'TokyoTyrant::put' => ['TokyoTyrant', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrant::putCat' => ['TokyoTyrant', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrant::putKeep' => ['TokyoTyrant', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrant::putNr' => ['TokyoTyrant', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrant::putShl' => ['mixed', 'key'=>'string', 'value'=>'string', 'width'=>'int'], 'TokyoTyrant::restore' => ['mixed', 'log_dir'=>'string', 'timestamp'=>'int', 'check_consistency='=>'bool'], 'TokyoTyrant::setMaster' => ['mixed', 'host'=>'string', 'port'=>'int', 'timestamp'=>'int', 'check_consistency='=>'bool'], 'TokyoTyrant::size' => ['int', 'key'=>'string'], 'TokyoTyrant::stat' => ['array'], 'TokyoTyrant::sync' => ['mixed'], 'TokyoTyrant::tune' => ['TokyoTyrant', 'timeout'=>'float', 'options='=>'int'], 'TokyoTyrant::vanish' => ['mixed'], 'TokyoTyrantIterator::__construct' => ['void', 'object'=>'mixed'], 'TokyoTyrantIterator::current' => ['mixed'], 'TokyoTyrantIterator::key' => ['mixed'], 'TokyoTyrantIterator::next' => ['mixed'], 'TokyoTyrantIterator::rewind' => ['void'], 'TokyoTyrantIterator::valid' => ['bool'], 'TokyoTyrantQuery::__construct' => ['void', 'table'=>'TokyoTyrantTable'], 'TokyoTyrantQuery::addCond' => ['mixed', 'name'=>'string', 'op'=>'int', 'expr'=>'string'], 'TokyoTyrantQuery::count' => ['0|positive-int'], 'TokyoTyrantQuery::current' => ['array'], 'TokyoTyrantQuery::hint' => ['string'], 'TokyoTyrantQuery::key' => ['string'], 'TokyoTyrantQuery::metaSearch' => ['array', 'queries'=>'array', 'type'=>'int'], 'TokyoTyrantQuery::next' => ['array'], 'TokyoTyrantQuery::out' => ['TokyoTyrantQuery'], 'TokyoTyrantQuery::rewind' => ['bool'], 'TokyoTyrantQuery::search' => ['array'], 'TokyoTyrantQuery::setLimit' => ['mixed', 'max='=>'int', 'skip='=>'int'], 'TokyoTyrantQuery::setOrder' => ['mixed', 'name'=>'string', 'type'=>'int'], 'TokyoTyrantQuery::valid' => ['bool'], 'TokyoTyrantTable::add' => ['void', 'key'=>'string', 'increment'=>'mixed', 'type='=>'string'], 'TokyoTyrantTable::genUid' => ['int'], 'TokyoTyrantTable::get' => ['array', 'keys'=>'mixed'], 'TokyoTyrantTable::getIterator' => ['TokyoTyrantIterator'], 'TokyoTyrantTable::getQuery' => ['TokyoTyrantQuery'], 'TokyoTyrantTable::out' => ['void', 'keys'=>'mixed'], 'TokyoTyrantTable::put' => ['int', 'key'=>'string', 'columns'=>'array'], 'TokyoTyrantTable::putCat' => ['void', 'key'=>'string', 'columns'=>'array'], 'TokyoTyrantTable::putKeep' => ['void', 'key'=>'string', 'columns'=>'array'], 'TokyoTyrantTable::putNr' => ['void', 'keys'=>'mixed', 'value='=>'string'], 'TokyoTyrantTable::putShl' => ['void', 'key'=>'string', 'value'=>'string', 'width'=>'int'], 'TokyoTyrantTable::setIndex' => ['mixed', 'column'=>'string', 'type'=>'int'], 'touch' => ['bool', 'filename'=>'string', 'time='=>'int', 'atime='=>'int'], 'trader_acos' => ['array', 'real'=>'array'], 'trader_ad' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'volume'=>'array'], 'trader_add' => ['array', 'real0'=>'array', 'real1'=>'array'], 'trader_adosc' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'volume'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int'], 'trader_adx' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_adxr' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_apo' => ['array', 'real'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int', 'mAType='=>'int'], 'trader_aroon' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_aroonosc' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_asin' => ['array', 'real'=>'array'], 'trader_atan' => ['array', 'real'=>'array'], 'trader_atr' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_avgprice' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_bbands' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'nbDevUp='=>'float', 'nbDevDn='=>'float', 'mAType='=>'int'], 'trader_beta' => ['array', 'real0'=>'array', 'real1'=>'array', 'timePeriod='=>'int'], 'trader_bop' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cci' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_cdl2crows' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3blackcrows' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3inside' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3linestrike' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3outside' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3starsinsouth' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdl3whitesoldiers' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlabandonedbaby' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdladvanceblock' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlbelthold' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlbreakaway' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlclosingmarubozu' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlconcealbabyswall' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlcounterattack' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdldarkcloudcover' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdldoji' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdldojistar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdldragonflydoji' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlengulfing' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdleveningdojistar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdleveningstar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlgapsidesidewhite' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlgravestonedoji' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhammer' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhangingman' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlharami' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlharamicross' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhighwave' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhikkake' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhikkakemod' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlhomingpigeon' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlidentical3crows' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlinneck' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlinvertedhammer' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlkicking' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlkickingbylength' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlladderbottom' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdllongleggeddoji' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdllongline' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlmarubozu' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlmatchinglow' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlmathold' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlmorningdojistar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlmorningstar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'penetration='=>'float'], 'trader_cdlonneck' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlpiercing' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlrickshawman' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlrisefall3methods' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlseparatinglines' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlshootingstar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlshortline' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlspinningtop' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlstalledpattern' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlsticksandwich' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdltakuri' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdltasukigap' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlthrusting' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdltristar' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlunique3river' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlupsidegap2crows' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_cdlxsidegap3methods' => ['array', 'open'=>'array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_ceil' => ['array', 'real'=>'array'], 'trader_cmo' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_correl' => ['array', 'real0'=>'array', 'real1'=>'array', 'timePeriod='=>'int'], 'trader_cos' => ['array', 'real'=>'array'], 'trader_cosh' => ['array', 'real'=>'array'], 'trader_dema' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_div' => ['array', 'real0'=>'array', 'real1'=>'array'], 'trader_dx' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_ema' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_errno' => ['int'], 'trader_exp' => ['array', 'real'=>'array'], 'trader_floor' => ['array', 'real'=>'array'], 'trader_get_compat' => ['int'], 'trader_get_unstable_period' => ['int', 'functionId'=>'int'], 'trader_ht_dcperiod' => ['array', 'real'=>'array'], 'trader_ht_dcphase' => ['array', 'real'=>'array'], 'trader_ht_phasor' => ['array', 'real'=>'array'], 'trader_ht_sine' => ['array', 'real'=>'array'], 'trader_ht_trendline' => ['array', 'real'=>'array'], 'trader_ht_trendmode' => ['array', 'real'=>'array'], 'trader_kama' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg_angle' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg_intercept' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_linearreg_slope' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_ln' => ['array', 'real'=>'array'], 'trader_log10' => ['array', 'real'=>'array'], 'trader_ma' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'mAType='=>'int'], 'trader_macd' => ['array', 'real'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int', 'signalPeriod='=>'int'], 'trader_macdext' => ['array', 'real'=>'array', 'fastPeriod='=>'int', 'fastMAType='=>'int', 'slowPeriod='=>'int', 'slowMAType='=>'int', 'signalPeriod='=>'int', 'signalMAType='=>'int'], 'trader_macdfix' => ['array', 'real'=>'array', 'signalPeriod='=>'int'], 'trader_mama' => ['array', 'real'=>'array', 'fastLimit='=>'float', 'slowLimit='=>'float'], 'trader_mavp' => ['array', 'real'=>'array', 'periods'=>'array', 'minPeriod='=>'int', 'maxPeriod='=>'int', 'mAType='=>'int'], 'trader_max' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_maxindex' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_medprice' => ['array', 'high'=>'array', 'low'=>'array'], 'trader_mfi' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'volume'=>'array', 'timePeriod='=>'int'], 'trader_midpoint' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_midprice' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_min' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minindex' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minmax' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minmaxindex' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_minus_di' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_minus_dm' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_mom' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_mult' => ['array', 'real0'=>'array', 'real1'=>'array'], 'trader_natr' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_obv' => ['array', 'real'=>'array', 'volume'=>'array'], 'trader_plus_di' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_plus_dm' => ['array', 'high'=>'array', 'low'=>'array', 'timePeriod='=>'int'], 'trader_ppo' => ['array', 'real'=>'array', 'fastPeriod='=>'int', 'slowPeriod='=>'int', 'mAType='=>'int'], 'trader_roc' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rocp' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rocr' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rocr100' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_rsi' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_sar' => ['array', 'high'=>'array', 'low'=>'array', 'acceleration='=>'float', 'maximum='=>'float'], 'trader_sarext' => ['array', 'high'=>'array', 'low'=>'array', 'startValue='=>'float', 'offsetOnReverse='=>'float', 'accelerationInitLong='=>'float', 'accelerationLong='=>'float', 'accelerationMaxLong='=>'float', 'accelerationInitShort='=>'float', 'accelerationShort='=>'float', 'accelerationMaxShort='=>'float'], 'trader_set_compat' => ['void', 'compatId'=>'int'], 'trader_set_unstable_period' => ['void', 'functionId'=>'int', 'timePeriod'=>'int'], 'trader_sin' => ['array', 'real'=>'array'], 'trader_sinh' => ['array', 'real'=>'array'], 'trader_sma' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_sqrt' => ['array', 'real'=>'array'], 'trader_stddev' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'nbDev='=>'float'], 'trader_stoch' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'fastK_Period='=>'int', 'slowK_Period='=>'int', 'slowK_MAType='=>'int', 'slowD_Period='=>'int', 'slowD_MAType='=>'int'], 'trader_stochf' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'fastK_Period='=>'int', 'fastD_Period='=>'int', 'fastD_MAType='=>'int'], 'trader_stochrsi' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'fastK_Period='=>'int', 'fastD_Period='=>'int', 'fastD_MAType='=>'int'], 'trader_sub' => ['array', 'real0'=>'array', 'real1'=>'array'], 'trader_sum' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_t3' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'vFactor='=>'float'], 'trader_tan' => ['array', 'real'=>'array'], 'trader_tanh' => ['array', 'real'=>'array'], 'trader_tema' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_trange' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_trima' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_trix' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_tsf' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trader_typprice' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_ultosc' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod1='=>'int', 'timePeriod2='=>'int', 'timePeriod3='=>'int'], 'trader_var' => ['array', 'real'=>'array', 'timePeriod='=>'int', 'nbDev='=>'float'], 'trader_wclprice' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array'], 'trader_willr' => ['array', 'high'=>'array', 'low'=>'array', 'close'=>'array', 'timePeriod='=>'int'], 'trader_wma' => ['array', 'real'=>'array', 'timePeriod='=>'int'], 'trait_exists' => ['bool', 'traitname'=>'string', 'autoload='=>'bool'], 'Transliterator::create' => ['?Transliterator', 'id'=>'string', 'direction='=>'int'], 'Transliterator::createFromRules' => ['?Transliterator', 'rules'=>'string', 'direction='=>'int'], 'Transliterator::createInverse' => ['?Transliterator'], 'Transliterator::getErrorCode' => ['int|false'], 'Transliterator::getErrorMessage' => ['string|false'], 'Transliterator::listIDs' => ['list|false'], 'Transliterator::transliterate' => ['string|false', 'subject'=>'string', 'start='=>'int', 'end='=>'int'], 'transliterator_create' => ['?Transliterator', 'id'=>'string', 'direction='=>'int'], 'transliterator_create_from_rules' => ['?Transliterator', 'rules'=>'string', 'direction='=>'int'], 'transliterator_create_inverse' => ['?Transliterator', 'obj'=>'Transliterator'], 'transliterator_get_error_code' => ['int|false', 'obj'=>'Transliterator'], 'transliterator_get_error_message' => ['string|false', 'obj'=>'Transliterator'], 'transliterator_list_ids' => ['list|false'], 'transliterator_transliterate' => ['string|false', 'obj'=>'Transliterator|string', 'subject'=>'string', 'start='=>'int', 'end='=>'int'], 'trigger_error' => ['bool', 'message'=>'string', 'error_type='=>'int'], 'trim' => ['string', 'str'=>'string', 'character_mask='=>'string'], 'TypeError::__clone' => ['void'], 'TypeError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?TypeError)'], 'TypeError::__toString' => ['string'], 'TypeError::getCode' => ['int'], 'TypeError::getFile' => ['string'], 'TypeError::getLine' => ['int'], 'TypeError::getMessage' => ['string'], 'TypeError::getPrevious' => ['Throwable|TypeError|null'], 'TypeError::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'TypeError::getTraceAsString' => ['string'], 'uasort' => ['bool', '&rw_array_arg'=>'array', 'callback'=>'callable(mixed,mixed):int'], 'ucfirst' => ['string', 'str'=>'string'], 'UConverter::__construct' => ['void', 'destination_encoding'=>'string', 'source_encoding='=>'string'], 'UConverter::convert' => ['string', 'str'=>'string', 'reverse='=>'bool'], 'UConverter::fromUCallback' => ['mixed', 'reason'=>'int', 'source'=>'string', 'codePoint'=>'string', '&w_error'=>'int'], 'UConverter::getAliases' => ['array', 'name='=>'string'], 'UConverter::getAvailable' => ['array'], 'UConverter::getDestinationEncoding' => ['string'], 'UConverter::getDestinationType' => ['int'], 'UConverter::getErrorCode' => ['int'], 'UConverter::getErrorMessage' => ['string'], 'UConverter::getSourceEncoding' => ['string'], 'UConverter::getSourceType' => ['int'], 'UConverter::getStandards' => ['array'], 'UConverter::getSubstChars' => ['string'], 'UConverter::reasonText' => ['string', 'reason='=>'int'], 'UConverter::setDestinationEncoding' => ['bool', 'encoding'=>'string'], 'UConverter::setSourceEncoding' => ['bool', 'encoding'=>'string'], 'UConverter::setSubstChars' => ['bool', 'chars'=>'string'], 'UConverter::toUCallback' => ['mixed', 'reason'=>'int', 'source'=>'string', 'codeUnits'=>'string', '&w_error'=>'int'], 'UConverter::transcode' => ['string', 'str'=>'string', 'toEncoding'=>'string', 'fromEncoding'=>'string', 'options='=>'array'], 'ucwords' => ['string', 'str'=>'string', 'delims='=>'string'], 'udm_add_search_limit' => ['bool', 'agent'=>'resource', 'var'=>'int', 'val'=>'string'], 'udm_alloc_agent' => ['resource', 'dbaddr'=>'string', 'dbmode='=>'string'], 'udm_alloc_agent_array' => ['resource', 'databases'=>'array'], 'udm_api_version' => ['int'], 'udm_cat_list' => ['array', 'agent'=>'resource', 'category'=>'string'], 'udm_cat_path' => ['array', 'agent'=>'resource', 'category'=>'string'], 'udm_check_charset' => ['bool', 'agent'=>'resource', 'charset'=>'string'], 'udm_check_stored' => ['int', 'agent'=>'', 'link'=>'int', 'doc_id'=>'string'], 'udm_clear_search_limits' => ['bool', 'agent'=>'resource'], 'udm_close_stored' => ['int', 'agent'=>'', 'link'=>'int'], 'udm_crc32' => ['int', 'agent'=>'resource', 'str'=>'string'], 'udm_errno' => ['int', 'agent'=>'resource'], 'udm_error' => ['string', 'agent'=>'resource'], 'udm_find' => ['resource', 'agent'=>'resource', 'query'=>'string'], 'udm_free_agent' => ['int', 'agent'=>'resource'], 'udm_free_ispell_data' => ['bool', 'agent'=>'int'], 'udm_free_res' => ['bool', 'res'=>'resource'], 'udm_get_doc_count' => ['int', 'agent'=>'resource'], 'udm_get_res_field' => ['string', 'res'=>'resource', 'row'=>'int', 'field'=>'int'], 'udm_get_res_param' => ['string', 'res'=>'resource', 'param'=>'int'], 'udm_hash32' => ['int', 'agent'=>'resource', 'str'=>'string'], 'udm_load_ispell_data' => ['bool', 'agent'=>'resource', 'var'=>'int', 'val1'=>'string', 'val2'=>'string', 'flag'=>'int'], 'udm_open_stored' => ['int', 'agent'=>'', 'storedaddr'=>'string'], 'udm_set_agent_param' => ['bool', 'agent'=>'resource', 'var'=>'int', 'val'=>'string'], 'ui\draw\text\font\fontfamilies' => ['array'], 'ui\quit' => ['void'], 'ui\run' => ['void', 'flags='=>'int'], 'uksort' => ['bool', '&rw_array_arg'=>'array', 'callback'=>'callable(array-key,array-key):int'], 'umask' => ['int', 'mask='=>'int'], 'UnderflowException::__clone' => ['void'], 'UnderflowException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?UnderflowException)'], 'UnderflowException::__toString' => ['string'], 'UnderflowException::getCode' => ['int'], 'UnderflowException::getFile' => ['string'], 'UnderflowException::getLine' => ['int'], 'UnderflowException::getMessage' => ['string'], 'UnderflowException::getPrevious' => ['Throwable|UnderflowException|null'], 'UnderflowException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'UnderflowException::getTraceAsString' => ['string'], 'UnexpectedValueException::__clone' => ['void'], 'UnexpectedValueException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?UnexpectedValueException)'], 'UnexpectedValueException::__toString' => ['string'], 'UnexpectedValueException::getCode' => ['int'], 'UnexpectedValueException::getFile' => ['string'], 'UnexpectedValueException::getLine' => ['int'], 'UnexpectedValueException::getMessage' => ['string'], 'UnexpectedValueException::getPrevious' => ['Throwable|UnexpectedValueException|null'], 'UnexpectedValueException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'UnexpectedValueException::getTraceAsString' => ['string'], 'uniqid' => ['non-empty-string', 'prefix='=>'string', 'more_entropy='=>'bool'], 'unixtojd' => ['int|false', 'timestamp='=>'int'], 'unlink' => ['bool', 'filename'=>'string', 'context='=>'resource'], 'unpack' => ['array|false', 'format'=>'string', 'data'=>'string', 'offset='=>'int'], 'unregister_tick_function' => ['void', 'function_name'=>'callable'], 'unserialize' => ['mixed', 'variable_representation'=>'string', 'allowed_classes='=>'array{allowed_classes?:string[]|bool}'], 'untaint' => ['bool', '&rw_string'=>'string', '&...rw_strings='=>'string'], 'uopz_add_function' => ['bool', 'class'=>'string', 'function'=>'string', 'handler'=>'Closure', '$flags'=>'bool', '$all'=>'bool'], 'uopz_add_function\'1' => ['bool', 'function'=>'string', 'handler'=>'Closure', '$flags'=>'bool'], 'uopz_allow_exit' => ['void', 'allow'=>'bool'], 'uopz_backup' => ['void', 'class'=>'string', 'function'=>'string'], 'uopz_backup\'1' => ['void', 'function'=>'string'], 'uopz_compose' => ['void', 'name'=>'string', 'classes'=>'array', 'methods='=>'array', 'properties='=>'array', 'flags='=>'int'], 'uopz_copy' => ['Closure', 'class'=>'string', 'function'=>'string'], 'uopz_copy\'1' => ['Closure', 'function'=>'string'], 'uopz_del_function' => ['bool', 'class'=>'string', 'function'=>'string', '$all'=>'bool'], 'uopz_del_function\'1' => ['bool', 'function'=>'string'], 'uopz_delete' => ['void', 'class'=>'string', 'function'=>'string'], 'uopz_delete\'1' => ['void', 'function'=>'string'], 'uopz_extend' => ['void', 'class'=>'string', 'parent'=>'string'], 'uopz_flags' => ['int', 'class'=>'string', 'function'=>'string', 'flags='=>'int'], 'uopz_flags\'1' => ['int', 'function'=>'string', 'flags='=>'int'], 'uopz_function' => ['void', 'class'=>'string', 'function'=>'string', 'handler'=>'Closure', 'modifiers='=>'int'], 'uopz_function\'1' => ['void', 'function'=>'string', 'handler'=>'Closure', 'modifiers='=>'int'], 'uopz_get_exit_status' => ['mixed'], 'uopz_get_hook' => ['Closure', 'class'=>'string', 'function'=>'string'], 'uopz_get_hook\'1' => ['Closure', 'function'=>'string'], 'uopz_get_mock' => ['mixed', 'class'=>'string'], 'uopz_get_property' => ['mixed', 'class'=>'string', 'property'=>'string'], 'uopz_get_property\'1' => ['mixed', 'instance'=>'object', 'property'=>'string'], 'uopz_get_return' => ['mixed', 'class='=>'string', 'function='=>'string'], 'uopz_get_static' => ['array', 'class='=>'string', 'function='=>'string'], 'uopz_get_static\'1' => ['array', 'function='=>'string'], 'uopz_implement' => ['void', 'class'=>'string', 'interface'=>'string'], 'uopz_overload' => ['void', 'opcode'=>'int', 'callable'=>'Callable'], 'uopz_redefine' => ['void', 'class'=>'string', 'constant'=>'string', 'value'=>'mixed'], 'uopz_redefine\'1' => ['void', 'constant'=>'string', 'value'=>'mixed'], 'uopz_rename' => ['void', 'class'=>'string', 'function'=>'string', 'rename'=>'string'], 'uopz_rename\'1' => ['void', 'function'=>'string', 'rename'=>'string'], 'uopz_restore' => ['void', 'class'=>'string', 'function'=>'string'], 'uopz_restore\'1' => ['void', 'function'=>'string'], 'uopz_set_mock' => ['void', 'class'=>'string', 'mock'=>'object|string'], 'uopz_set_property' => ['void', 'class'=>'string', 'property'=>'string', 'value'=>'mixed'], 'uopz_set_property\'1' => ['void', 'instance'=>'object', 'property'=>'string', 'value'=>'mixed'], 'uopz_set_return' => ['bool', 'class'=>'string', 'function'=>'string', 'value'=>'mixed', 'execute='=>'bool'], 'uopz_set_return\'1' => ['bool', 'function'=>'string', 'value'=>'mixed', 'execute='=>'bool'], 'uopz_undefine' => ['void', 'class'=>'string', 'constant'=>'string'], 'uopz_undefine\'1' => ['void', 'constant'=>'string'], 'uopz_set_hook' => ['bool', 'class'=>'string', 'function'=>'string', 'hook'=>'Closure'], 'uopz_set_hook\'1' => ['bool', 'function'=>'string', 'hook'=>'Closure'], 'uopz_unset_mock' => ['void', 'class'=>'string'], 'uopz_unset_return' => ['bool', 'class='=>'string', 'function='=>'string'], 'uopz_unset_return\'1' => ['bool', 'function'=>'string'], 'urldecode' => ['string', 'str'=>'string'], 'urlencode' => ['string', 'str'=>'string'], 'use_soap_error_handler' => ['bool', 'handler='=>'bool'], 'usleep' => ['void', 'micro_seconds'=>'int'], 'usort' => ['bool', '&rw_array_arg'=>'array', 'callback'=>'callable(mixed,mixed):int'], 'utf8_decode' => ['string', 'data'=>'string'], 'utf8_encode' => ['string', 'data'=>'string'], 'V8Js::__construct' => ['void', 'object_name='=>'string', 'variables='=>'array', 'extensions='=>'array', 'report_uncaught_exceptions='=>'bool', 'snapshot_blob='=>'string'], 'V8Js::clearPendingException' => [''], 'V8Js::compileString' => ['resource', 'script'=>'', 'identifier='=>'string'], 'V8Js::createSnapshot' => ['false|string', 'embed_source'=>'string'], 'V8Js::executeScript' => ['', 'script'=>'resource', 'flags='=>'int', 'time_limit='=>'int', 'memory_limit='=>'int'], 'V8Js::executeString' => ['mixed', 'script'=>'string', 'identifier='=>'string', 'flags='=>'int'], 'V8Js::getExtensions' => ['array'], 'V8Js::getPendingException' => ['V8JsException'], 'V8Js::registerExtension' => ['bool', 'extension_name'=>'string', 'script'=>'string', 'dependencies='=>'array', 'auto_enable='=>'bool'], 'V8Js::setAverageObjectSize' => ['', 'average_object_size'=>'int'], 'V8Js::setMemoryLimit' => ['', 'limit'=>'int'], 'V8Js::setModuleLoader' => ['', 'loader'=>'callable'], 'V8Js::setModuleNormaliser' => ['', 'normaliser'=>'callable'], 'V8Js::setTimeLimit' => ['', 'limit'=>'int'], 'V8JsException::getJsFileName' => ['string'], 'V8JsException::getJsLineNumber' => ['int'], 'V8JsException::getJsSourceLine' => ['int'], 'V8JsException::getJsTrace' => ['string'], 'V8JsScriptException::__clone' => ['void'], 'V8JsScriptException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Exception)|(?Throwable)'], 'V8JsScriptException::__toString' => ['string'], 'V8JsScriptException::__wakeup' => ['void'], 'V8JsScriptException::getCode' => ['int'], 'V8JsScriptException::getFile' => ['string'], 'V8JsScriptException::getJsEndColumn' => ['int'], 'V8JsScriptException::getJsFileName' => ['string'], 'V8JsScriptException::getJsLineNumber' => ['int'], 'V8JsScriptException::getJsSourceLine' => ['string'], 'V8JsScriptException::getJsStartColumn' => ['int'], 'V8JsScriptException::getJsTrace' => ['string'], 'V8JsScriptException::getLine' => ['int'], 'V8JsScriptException::getMessage' => ['string'], 'V8JsScriptException::getPrevious' => ['Exception|Throwable'], 'V8JsScriptException::getTrace' => ['list\',args?:mixed[],object?:object}>'], 'V8JsScriptException::getTraceAsString' => ['string'], 'var_dump' => ['void', 'var'=>'mixed', '...args='=>'mixed'], 'var_export' => ['string|null', 'var'=>'mixed', 'return='=>'bool'], 'VARIANT::__construct' => ['void', 'value='=>'mixed', 'type='=>'int', 'codepage='=>'int'], 'variant_abs' => ['mixed', 'left'=>'mixed'], 'variant_add' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_and' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_cast' => ['object', 'variant'=>'object', 'type'=>'int'], 'variant_cat' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_cmp' => ['int', 'left'=>'mixed', 'right'=>'mixed', 'lcid='=>'int', 'flags='=>'int'], 'variant_date_from_timestamp' => ['object', 'timestamp'=>'int'], 'variant_date_to_timestamp' => ['int', 'variant'=>'object'], 'variant_div' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_eqv' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_fix' => ['mixed', 'left'=>'mixed'], 'variant_get_type' => ['int', 'variant'=>'object'], 'variant_idiv' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_imp' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_int' => ['mixed', 'left'=>'mixed'], 'variant_mod' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_mul' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_neg' => ['mixed', 'left'=>'mixed'], 'variant_not' => ['mixed', 'left'=>'mixed'], 'variant_or' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_pow' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_round' => ['mixed', 'left'=>'mixed', 'decimals'=>'int'], 'variant_set' => ['void', 'variant'=>'object', 'value'=>'mixed'], 'variant_set_type' => ['void', 'variant'=>'object', 'type'=>'int'], 'variant_sub' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'variant_xor' => ['mixed', 'left'=>'mixed', 'right'=>'mixed'], 'VarnishAdmin::__construct' => ['void', 'args='=>'array'], 'VarnishAdmin::auth' => ['bool'], 'VarnishAdmin::ban' => ['int', 'vcl_regex'=>'string'], 'VarnishAdmin::banUrl' => ['int', 'vcl_regex'=>'string'], 'VarnishAdmin::clearPanic' => ['int'], 'VarnishAdmin::connect' => ['bool'], 'VarnishAdmin::disconnect' => ['bool'], 'VarnishAdmin::getPanic' => ['string'], 'VarnishAdmin::getParams' => ['array'], 'VarnishAdmin::isRunning' => ['bool'], 'VarnishAdmin::setCompat' => ['void', 'compat'=>'int'], 'VarnishAdmin::setHost' => ['void', 'host'=>'string'], 'VarnishAdmin::setIdent' => ['void', 'ident'=>'string'], 'VarnishAdmin::setParam' => ['int', 'name'=>'string', 'value'=>'string|int'], 'VarnishAdmin::setPort' => ['void', 'port'=>'int'], 'VarnishAdmin::setSecret' => ['void', 'secret'=>'string'], 'VarnishAdmin::setTimeout' => ['void', 'timeout'=>'int'], 'VarnishAdmin::start' => ['int'], 'VarnishAdmin::stop' => ['int'], 'VarnishLog::__construct' => ['void', 'args='=>'array'], 'VarnishLog::getLine' => ['array'], 'VarnishLog::getTagName' => ['string', 'index'=>'int'], 'VarnishStat::__construct' => ['void', 'args='=>'array'], 'VarnishStat::getSnapshot' => ['array'], 'version_compare' => ['int', 'version1'=>'string', 'version2'=>'string'], 'version_compare\'1' => ['bool', 'version1'=>'string', 'version2'=>'string', 'operator'=>'string|null'], 'vfprintf' => ['int', 'stream'=>'resource', 'format'=>'string', 'args'=>'array<__stringAndStringable|int|float|null|bool>'], 'virtual' => ['bool', 'uri'=>'string'], 'Volatile::__construct' => ['void'], 'Volatile::chunk' => ['array', 'size'=>'int', 'preserve'=>'bool'], 'Volatile::count' => ['0|positive-int'], 'Volatile::extend' => ['bool', 'class'=>'string'], 'Volatile::isRunning' => ['bool'], 'Volatile::isTerminated' => ['bool'], 'Volatile::merge' => ['bool', 'from'=>'mixed', 'overwrite='=>'bool'], 'Volatile::notify' => ['bool'], 'Volatile::notifyOne' => ['bool'], 'Volatile::offsetExists' => ['bool', 'offset'=>'mixed'], 'Volatile::offsetGet' => ['mixed', 'offset'=>'mixed'], 'Volatile::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'Volatile::offsetUnset' => ['void', 'offset'=>'mixed'], 'Volatile::pop' => ['bool'], 'Volatile::run' => ['void'], 'Volatile::shift' => ['mixed'], 'Volatile::synchronized' => ['mixed', 'block'=>'Closure', '...args='=>'mixed'], 'Volatile::wait' => ['bool', 'timeout='=>'int'], 'vpopmail_add_alias_domain' => ['bool', 'domain'=>'string', 'aliasdomain'=>'string'], 'vpopmail_add_alias_domain_ex' => ['bool', 'olddomain'=>'string', 'newdomain'=>'string'], 'vpopmail_add_domain' => ['bool', 'domain'=>'string', 'dir'=>'string', 'uid'=>'int', 'gid'=>'int'], 'vpopmail_add_domain_ex' => ['bool', 'domain'=>'string', 'passwd'=>'string', 'quota='=>'string', 'bounce='=>'string', 'apop='=>'bool'], 'vpopmail_add_user' => ['bool', 'user'=>'string', 'domain'=>'string', 'password'=>'string', 'gecos='=>'string', 'apop='=>'bool'], 'vpopmail_alias_add' => ['bool', 'user'=>'string', 'domain'=>'string', 'alias'=>'string'], 'vpopmail_alias_del' => ['bool', 'user'=>'string', 'domain'=>'string'], 'vpopmail_alias_del_domain' => ['bool', 'domain'=>'string'], 'vpopmail_alias_get' => ['array', 'alias'=>'string', 'domain'=>'string'], 'vpopmail_alias_get_all' => ['array', 'domain'=>'string'], 'vpopmail_auth_user' => ['bool', 'user'=>'string', 'domain'=>'string', 'password'=>'string', 'apop='=>'string'], 'vpopmail_del_domain' => ['bool', 'domain'=>'string'], 'vpopmail_del_domain_ex' => ['bool', 'domain'=>'string'], 'vpopmail_del_user' => ['bool', 'user'=>'string', 'domain'=>'string'], 'vpopmail_error' => ['string'], 'vpopmail_passwd' => ['bool', 'user'=>'string', 'domain'=>'string', 'password'=>'string', 'apop='=>'bool'], 'vpopmail_set_user_quota' => ['bool', 'user'=>'string', 'domain'=>'string', 'quota'=>'string'], 'vprintf' => ['int', 'format'=>'string', 'args'=>'array<__stringAndStringable|int|float|null|bool>'], 'vsprintf' => ['string', 'format'=>'string', 'args'=>'array<__stringAndStringable|int|float|null|bool>'], 'w32api_deftype' => ['bool', 'typename'=>'string', 'member1_type'=>'string', 'member1_name'=>'string', '...args='=>'string'], 'w32api_init_dtype' => ['resource', 'typename'=>'string', 'value'=>'', '...args='=>''], 'w32api_invoke_function' => ['', 'funcname'=>'string', 'argument'=>'', '...args='=>''], 'w32api_register_function' => ['bool', 'library'=>'string', 'function_name'=>'string', 'return_type'=>'string'], 'w32api_set_call_method' => ['', 'method'=>'int'], 'wddx_add_vars' => ['bool', 'packet_id'=>'resource', 'var_names'=>'mixed', '...vars='=>'mixed'], 'wddx_deserialize' => ['mixed', 'packet'=>'string'], 'wddx_packet_end' => ['string', 'packet_id'=>'resource'], 'wddx_packet_start' => ['resource', 'comment='=>'string'], 'wddx_serialize_value' => ['string', 'var'=>'mixed', 'comment='=>'string'], 'wddx_serialize_vars' => ['string', 'var_name'=>'mixed', '...vars='=>'mixed'], 'WeakMap::__construct' => ['void'], 'WeakMap::count' => ['0|positive-int'], 'WeakMap::current' => ['mixed'], 'WeakMap::key' => ['object'], 'WeakMap::next' => ['void'], 'WeakMap::offsetExists' => ['bool', 'object'=>'object'], 'WeakMap::offsetGet' => ['mixed', 'object'=>'object'], 'WeakMap::offsetSet' => ['void', 'object'=>'object', 'value'=>'mixed'], 'WeakMap::offsetUnset' => ['void', 'object'=>'object'], 'WeakMap::rewind' => ['void'], 'WeakMap::valid' => ['bool'], 'Weakref::acquire' => ['bool'], 'Weakref::get' => ['object'], 'Weakref::release' => ['bool'], 'Weakref::valid' => ['bool'], 'webObj::convertToString' => ['string'], 'webObj::free' => ['void'], 'webObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'webObj::updateFromString' => ['int', 'snippet'=>'string'], 'win32_continue_service' => ['int', 'servicename'=>'string', 'machine='=>'string'], 'win32_create_service' => ['mixed', 'details'=>'array', 'machine='=>'string'], 'win32_delete_service' => ['mixed', 'servicename'=>'string', 'machine='=>'string'], 'win32_get_last_control_message' => ['int'], 'win32_pause_service' => ['int', 'servicename'=>'string', 'machine='=>'string'], 'win32_ps_list_procs' => ['array'], 'win32_ps_stat_mem' => ['array'], 'win32_ps_stat_proc' => ['array', 'pid='=>'int'], 'win32_query_service_status' => ['mixed', 'servicename'=>'string', 'machine='=>'string'], 'win32_set_service_status' => ['bool', 'status'=>'int', 'checkpoint='=>'int'], 'win32_start_service' => ['int', 'servicename'=>'string', 'machine='=>'string'], 'win32_start_service_ctrl_dispatcher' => ['mixed', 'name'=>'string'], 'win32_stop_service' => ['int', 'servicename'=>'string', 'machine='=>'string'], 'wincache_fcache_fileinfo' => ['array', 'summaryonly='=>'bool'], 'wincache_fcache_meminfo' => ['array'], 'wincache_lock' => ['bool', 'key'=>'string', 'isglobal='=>'bool'], 'wincache_ocache_fileinfo' => ['array', 'summaryonly='=>'bool'], 'wincache_ocache_meminfo' => ['array'], 'wincache_refresh_if_changed' => ['bool', 'files='=>'array'], 'wincache_rplist_fileinfo' => ['array', 'summaryonly='=>'bool'], 'wincache_rplist_meminfo' => ['array'], 'wincache_scache_info' => ['array|false', 'summaryonly='=>'bool'], 'wincache_scache_meminfo' => ['array|false'], 'wincache_ucache_add' => ['bool', 'key'=>'string', 'value'=>'', 'ttl='=>'int'], 'wincache_ucache_add\'1' => ['bool', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'wincache_ucache_cas' => ['bool', 'key'=>'string', 'old_value'=>'int', 'new_value'=>'int'], 'wincache_ucache_clear' => ['bool'], 'wincache_ucache_dec' => ['mixed', 'key'=>'string', 'dec_by='=>'int', '&w_success='=>'bool'], 'wincache_ucache_delete' => ['bool', 'key'=>'mixed'], 'wincache_ucache_exists' => ['bool', 'key'=>'string'], 'wincache_ucache_get' => ['mixed', 'key'=>'mixed', '&w_success='=>'bool'], 'wincache_ucache_inc' => ['int|false', 'key'=>'string', 'inc_by='=>'int', '&w_success='=>'bool'], 'wincache_ucache_info' => ['array|false', 'summaryonly='=>'bool', 'key='=>'string'], 'wincache_ucache_meminfo' => ['array'], 'wincache_ucache_set' => ['bool', 'key'=>'', 'value'=>'', 'ttl='=>'int'], 'wincache_ucache_set\'1' => ['bool', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'wincache_unlock' => ['bool', 'key'=>'string'], 'wordwrap' => ['string', 'str'=>'string', 'width='=>'int', 'break='=>'string', 'cut='=>'bool'], 'Worker::__construct' => ['void'], 'Worker::chunk' => ['array', 'size'=>'int', 'preserve'=>'bool'], 'Worker::collect' => ['int', 'collector='=>'Callable'], 'Worker::count' => ['0|positive-int'], 'Worker::getCreatorId' => ['int'], 'Worker::getCurrentThread' => ['Thread'], 'Worker::getCurrentThreadId' => ['int'], 'Worker::getStacked' => ['int'], 'Worker::getThreadId' => ['int'], 'Worker::isJoined' => ['bool'], 'Worker::isRunning' => ['bool'], 'Worker::isShutdown' => ['bool'], 'Worker::isStarted' => ['bool'], 'Worker::isTerminated' => ['bool'], 'Worker::join' => ['bool'], 'Worker::merge' => ['bool', 'from'=>'', 'overwrite='=>'mixed'], 'Worker::notify' => ['bool'], 'Worker::notifyOne' => ['bool'], 'Worker::offsetExists' => ['bool', 'offset'=>'mixed'], 'Worker::offsetGet' => ['mixed', 'offset'=>'mixed'], 'Worker::offsetSet' => ['void', 'offset'=>'mixed', 'value'=>'mixed'], 'Worker::offsetUnset' => ['void', 'offset'=>'mixed'], 'Worker::pop' => ['bool'], 'Worker::run' => ['void'], 'Worker::shift' => ['bool'], 'Worker::shutdown' => ['bool'], 'Worker::stack' => ['int', 'work'=>'Threaded'], 'Worker::start' => ['bool', 'options='=>'int'], 'Worker::synchronized' => ['mixed', 'block'=>'Closure', '_='=>'mixed'], 'Worker::unstack' => ['Collectable|null'], 'Worker::wait' => ['bool', 'timeout='=>'int'], 'xattr_get' => ['string', 'filename'=>'string', 'name'=>'string', 'flags='=>'int'], 'xattr_list' => ['array', 'filename'=>'string', 'flags='=>'int'], 'xattr_remove' => ['bool', 'filename'=>'string', 'name'=>'string', 'flags='=>'int'], 'xattr_set' => ['bool', 'filename'=>'string', 'name'=>'string', 'value'=>'string', 'flags='=>'int'], 'xattr_supported' => ['bool', 'filename'=>'string', 'flags='=>'int'], 'xcache_asm' => ['string', 'filename'=>'string'], 'xcache_clear_cache' => ['void', 'type'=>'int', 'id='=>'int'], 'xcache_coredump' => ['string', 'op_type'=>'int'], 'xcache_count' => ['int', 'type'=>'int'], 'xcache_coverager_decode' => ['array', 'data'=>'string'], 'xcache_coverager_get' => ['array', 'clean='=>'bool|false'], 'xcache_coverager_start' => ['void', 'clean='=>'bool|true'], 'xcache_coverager_stop' => ['void', 'clean='=>'bool|false'], 'xcache_dasm_file' => ['string', 'filename'=>'string'], 'xcache_dasm_string' => ['string', 'code'=>'string'], 'xcache_dec' => ['int', 'name'=>'string', 'value='=>'int|mixed', 'ttl='=>'int'], 'xcache_decode' => ['bool', 'filename'=>'string'], 'xcache_encode' => ['string', 'filename'=>'string'], 'xcache_get' => ['mixed', 'name'=>'string'], 'xcache_get_data_type' => ['string', 'type'=>'int'], 'xcache_get_op_spec' => ['string', 'op_type'=>'int'], 'xcache_get_op_type' => ['string', 'op_type'=>'int'], 'xcache_get_opcode' => ['string', 'opcode'=>'int'], 'xcache_get_opcode_spec' => ['string', 'opcode'=>'int'], 'xcache_inc' => ['int', 'name'=>'string', 'value='=>'int|mixed', 'ttl='=>'int'], 'xcache_info' => ['array', 'type'=>'int', 'id'=>'int'], 'xcache_is_autoglobal' => ['string', 'name'=>'string'], 'xcache_isset' => ['bool', 'name'=>'string'], 'xcache_list' => ['array', 'type'=>'int', 'id'=>'int'], 'xcache_set' => ['bool', 'name'=>'string', 'value'=>'mixed', 'ttl='=>'int'], 'xcache_unset' => ['bool', 'name'=>'string'], 'xcache_unset_by_prefix' => ['bool', 'prefix'=>'string'], 'Xcom::__construct' => ['void', 'fabric_url='=>'string', 'fabric_token='=>'string', 'capability_token='=>'string'], 'Xcom::decode' => ['object', 'avro_msg'=>'string', 'json_schema'=>'string'], 'Xcom::encode' => ['string', 'data'=>'stdClass', 'avro_schema'=>'string'], 'Xcom::getDebugOutput' => ['string'], 'Xcom::getLastResponse' => ['string'], 'Xcom::getLastResponseInfo' => ['array'], 'Xcom::getOnboardingURL' => ['string', 'capability_name'=>'string', 'agreement_url'=>'string'], 'Xcom::send' => ['int', 'topic'=>'string', 'data'=>'mixed', 'json_schema='=>'string', 'http_headers='=>'array'], 'Xcom::sendAsync' => ['int', 'topic'=>'string', 'data'=>'mixed', 'json_schema='=>'string', 'http_headers='=>'array'], 'xdebug_break' => ['bool'], 'xdebug_call_class' => ['string', 'depth='=>'int'], 'xdebug_call_file' => ['string', 'depth='=>'int'], 'xdebug_call_function' => ['string', 'depth='=>'int'], 'xdebug_call_line' => ['int', 'depth='=>'int'], 'xdebug_clear_aggr_profiling_data' => ['bool'], 'xdebug_code_coverage_started' => ['bool'], 'xdebug_connect_to_client' => ['bool'], 'xdebug_debug_zval' => ['void', '...varName'=>'string'], 'xdebug_debug_zval_stdout' => ['void', '...varName'=>'string'], 'xdebug_disable' => ['void'], 'xdebug_dump_aggr_profiling_data' => ['bool'], 'xdebug_dump_superglobals' => ['void'], 'xdebug_enable' => ['void'], 'xdebug_get_code_coverage' => ['array'], 'xdebug_get_collected_errors' => ['string', 'clean='=>'bool|false'], 'xdebug_get_declared_vars' => ['array'], 'xdebug_get_formatted_function_stack' => [''], 'xdebug_get_function_count' => ['int'], 'xdebug_get_function_stack' => ['array', 'message='=>'string', 'options='=>'int'], 'xdebug_get_headers' => ['array'], 'xdebug_get_monitored_functions' => ['array'], 'xdebug_get_profiler_filename' => ['string'], 'xdebug_get_stack_depth' => ['int'], 'xdebug_get_tracefile_name' => ['string'], 'xdebug_is_debugger_active' => ['bool'], 'xdebug_is_enabled' => ['bool'], 'xdebug_memory_usage' => ['int'], 'xdebug_notify' => ['bool', 'data'=>'mixed'], 'xdebug_peak_memory_usage' => ['int'], 'xdebug_print_function_stack' => ['array', 'message='=>'string', 'options='=>'int'], 'xdebug_set_filter' => ['void', 'group'=>'int', 'list_type'=>'int', 'configuration'=>'array'], 'xdebug_start_code_coverage' => ['void', 'options='=>'int'], 'xdebug_start_error_collection' => ['void'], 'xdebug_start_function_monitor' => ['void', 'list_of_functions_to_monitor'=>'string[]'], 'xdebug_start_trace' => ['void', 'trace_file'=>'', 'options='=>'int|mixed'], 'xdebug_stop_code_coverage' => ['void', 'cleanup='=>'bool|true'], 'xdebug_stop_error_collection' => ['void'], 'xdebug_stop_function_monitor' => ['void'], 'xdebug_stop_trace' => ['void'], 'xdebug_time_index' => ['float'], 'xdebug_var_dump' => ['void', '...var'=>''], 'xdiff_file_bdiff' => ['bool', 'old_file'=>'string', 'new_file'=>'string', 'dest'=>'string'], 'xdiff_file_bdiff_size' => ['int', 'file'=>'string'], 'xdiff_file_bpatch' => ['bool', 'file'=>'string', 'patch'=>'string', 'dest'=>'string'], 'xdiff_file_diff' => ['bool', 'old_file'=>'string', 'new_file'=>'string', 'dest'=>'string', 'context='=>'int', 'minimal='=>'bool'], 'xdiff_file_diff_binary' => ['bool', 'old_file'=>'string', 'new_file'=>'string', 'dest'=>'string'], 'xdiff_file_merge3' => ['mixed', 'old_file'=>'string', 'new_file1'=>'string', 'new_file2'=>'string', 'dest'=>'string'], 'xdiff_file_patch' => ['mixed', 'file'=>'string', 'patch'=>'string', 'dest'=>'string', 'flags='=>'int'], 'xdiff_file_patch_binary' => ['bool', 'file'=>'string', 'patch'=>'string', 'dest'=>'string'], 'xdiff_file_rabdiff' => ['bool', 'old_file'=>'string', 'new_file'=>'string', 'dest'=>'string'], 'xdiff_string_bdiff' => ['string', 'old_data'=>'string', 'new_data'=>'string'], 'xdiff_string_bdiff_size' => ['int', 'patch'=>'string'], 'xdiff_string_bpatch' => ['string', 'str'=>'string', 'patch'=>'string'], 'xdiff_string_diff' => ['string', 'old_data'=>'string', 'new_data'=>'string', 'context='=>'int', 'minimal='=>'bool'], 'xdiff_string_diff_binary' => ['string', 'old_data'=>'string', 'new_data'=>'string'], 'xdiff_string_merge3' => ['mixed', 'old_data'=>'string', 'new_data1'=>'string', 'new_data2'=>'string', 'error='=>'string'], 'xdiff_string_patch' => ['string', 'str'=>'string', 'patch'=>'string', 'flags='=>'int', '&w_error='=>'string'], 'xdiff_string_patch_binary' => ['string', 'str'=>'string', 'patch'=>'string'], 'xdiff_string_rabdiff' => ['string', 'old_data'=>'string', 'new_data'=>'string'], 'xhprof_disable' => ['array'], 'xhprof_enable' => ['void', 'flags='=>'int', 'options='=>'array'], 'xhprof_sample_disable' => ['array'], 'xhprof_sample_enable' => ['void'], 'xml_error_string' => ['string', 'code'=>'int'], 'xml_get_current_byte_index' => ['int', 'parser'=>'resource'], 'xml_get_current_column_number' => ['int', 'parser'=>'resource'], 'xml_get_current_line_number' => ['int', 'parser'=>'resource'], 'xml_get_error_code' => ['int', 'parser'=>'resource'], 'xml_parse' => ['int', 'parser'=>'resource', 'data'=>'string', 'isfinal='=>'bool'], 'xml_parse_into_struct' => ['int', 'parser'=>'resource', 'data'=>'string', '&w_values'=>'array', '&w_index='=>'array'], 'xml_parser_create' => ['resource', 'encoding='=>'string'], 'xml_parser_create_ns' => ['resource', 'encoding='=>'string', 'sep='=>'string'], 'xml_parser_free' => ['bool', 'parser'=>'resource'], 'xml_parser_get_option' => ['mixed', 'parser'=>'resource', 'option'=>'int'], 'xml_parser_set_option' => ['bool', 'parser'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'xml_set_character_data_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_default_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_element_handler' => ['bool', 'parser'=>'resource', 'shdl'=>'callable', 'ehdl'=>'callable'], 'xml_set_end_namespace_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_external_entity_ref_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_notation_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_object' => ['bool', 'parser'=>'resource', 'obj'=>'object'], 'xml_set_processing_instruction_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_start_namespace_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'xml_set_unparsed_entity_decl_handler' => ['bool', 'parser'=>'resource', 'hdl'=>'callable'], 'XMLDiff\Base::__construct' => ['void', 'nsname'=>'string'], 'XMLDiff\Base::diff' => ['mixed', 'from'=>'mixed', 'to'=>'mixed'], 'XMLDiff\Base::merge' => ['mixed', 'src'=>'mixed', 'diff'=>'mixed'], 'XMLDiff\DOM::diff' => ['DOMDocument', 'from'=>'DOMDocument', 'to'=>'DOMDocument'], 'XMLDiff\DOM::merge' => ['DOMDocument', 'src'=>'DOMDocument', 'diff'=>'DOMDocument'], 'XMLDiff\File::diff' => ['string', 'from'=>'string', 'to'=>'string'], 'XMLDiff\File::merge' => ['string', 'src'=>'string', 'diff'=>'string'], 'XMLDiff\Memory::diff' => ['string', 'from'=>'string', 'to'=>'string'], 'XMLDiff\Memory::merge' => ['string', 'src'=>'string', 'diff'=>'string'], 'XMLReader::close' => ['bool'], 'XMLReader::expand' => ['DOMNode|false', 'basenode='=>'DOMNode'], 'XMLReader::getAttribute' => ['string|null', 'name'=>'string'], 'XMLReader::getAttributeNo' => ['string|null', 'index'=>'int'], 'XMLReader::getAttributeNs' => ['string|null', 'name'=>'string', 'namespaceuri'=>'string'], 'XMLReader::getParserProperty' => ['bool', 'property'=>'int'], 'XMLReader::isValid' => ['bool'], 'XMLReader::lookupNamespace' => ['?string', 'prefix'=>'string'], 'XMLReader::moveToAttribute' => ['bool', 'name'=>'string'], 'XMLReader::moveToAttributeNo' => ['bool', 'index'=>'int'], 'XMLReader::moveToAttributeNs' => ['bool', 'localname'=>'string', 'namespaceuri'=>'string'], 'XMLReader::moveToElement' => ['bool'], 'XMLReader::moveToFirstAttribute' => ['bool'], 'XMLReader::moveToNextAttribute' => ['bool'], 'XMLReader::next' => ['bool', 'localname='=>'string'], 'XMLReader::open' => ['bool|XMLReader', 'uri'=>'string', 'encoding='=>'?string', 'options='=>'int'], 'XMLReader::read' => ['bool'], 'XMLReader::readInnerXML' => ['string'], 'XMLReader::readOuterXML' => ['string'], 'XMLReader::readString' => ['string'], 'XMLReader::setParserProperty' => ['bool', 'property'=>'int', 'value'=>'bool'], 'XMLReader::setRelaxNGSchema' => ['bool', 'filename'=>'string'], 'XMLReader::setRelaxNGSchemaSource' => ['bool', 'source'=>'string'], 'XMLReader::setSchema' => ['bool', 'filename'=>'string'], 'XMLReader::XML' => ['bool|XMLReader', 'source'=>'string', 'encoding='=>'?string', 'options='=>'int'], 'xmlrpc_decode' => ['?array', 'xml'=>'string', 'encoding='=>'string'], 'xmlrpc_decode_request' => ['?array', 'xml'=>'string', '&w_method'=>'string', 'encoding='=>'string'], 'xmlrpc_encode' => ['string', 'value'=>'mixed'], 'xmlrpc_encode_request' => ['string', 'method'=>'string', 'params'=>'mixed', 'output_options='=>'array'], 'xmlrpc_get_type' => ['string', 'value'=>'mixed'], 'xmlrpc_is_fault' => ['bool', 'arg'=>'array'], 'xmlrpc_parse_method_descriptions' => ['array', 'xml'=>'string'], 'xmlrpc_server_add_introspection_data' => ['int', 'server'=>'resource', 'desc'=>'array'], 'xmlrpc_server_call_method' => ['string', 'server'=>'resource', 'xml'=>'string', 'user_data'=>'mixed', 'output_options='=>'array'], 'xmlrpc_server_create' => ['resource'], 'xmlrpc_server_destroy' => ['int', 'server'=>'resource'], 'xmlrpc_server_register_introspection_callback' => ['bool', 'server'=>'resource', 'function'=>'string'], 'xmlrpc_server_register_method' => ['bool', 'server'=>'resource', 'method_name'=>'string', 'function'=>'string'], 'xmlrpc_set_type' => ['bool', '&rw_value'=>'string|DateTime', 'type'=>'string'], 'XMLWriter::endAttribute' => ['bool'], 'XMLWriter::endCData' => ['bool'], 'XMLWriter::endComment' => ['bool'], 'XMLWriter::endDocument' => ['bool'], 'XMLWriter::endDTD' => ['bool', 'xmlwriter='=>''], 'XMLWriter::endDTDAttlist' => ['bool'], 'XMLWriter::endDTDElement' => ['bool'], 'XMLWriter::endDTDEntity' => ['bool'], 'XMLWriter::endElement' => ['bool'], 'XMLWriter::endPI' => ['bool'], 'XMLWriter::flush' => ['', 'empty='=>'bool', 'xmlwriter='=>''], 'XMLWriter::fullEndElement' => ['bool'], 'XMLWriter::openMemory' => ['bool'], 'XMLWriter::openURI' => ['bool', 'uri'=>'string'], 'XMLWriter::outputMemory' => ['string', 'flush='=>'bool', 'xmlwriter='=>''], 'XMLWriter::setIndent' => ['bool', 'indent'=>'bool'], 'XMLWriter::setIndentString' => ['bool', 'indentstring'=>'string'], 'XMLWriter::startAttribute' => ['bool', 'name'=>'string'], 'XMLWriter::startAttributeNS' => ['bool', 'prefix'=>'string|null', 'name'=>'string', 'uri'=>'string'], 'XMLWriter::startCData' => ['bool'], 'XMLWriter::startComment' => ['bool'], 'XMLWriter::startDocument' => ['bool', 'version='=>'string', 'encoding='=>'string', 'standalone='=>'string'], 'XMLWriter::startDTD' => ['bool', 'qualifiedname'=>'string', 'publicid='=>'string', 'systemid='=>'string'], 'XMLWriter::startDTDAttlist' => ['bool', 'name'=>'string'], 'XMLWriter::startDTDElement' => ['bool', 'qualifiedname'=>'string'], 'XMLWriter::startDTDEntity' => ['bool', 'name'=>'string', 'isparam'=>'bool'], 'XMLWriter::startElement' => ['bool', 'name'=>'string'], 'XMLWriter::startElementNS' => ['bool', 'prefix'=>'string|null', 'name'=>'string', 'uri'=>'string|null'], 'XMLWriter::startPI' => ['bool', 'target'=>'string'], 'XMLWriter::text' => ['bool', 'content'=>'string'], 'XMLWriter::writeAttribute' => ['bool', 'name'=>'string', 'value'=>'string'], 'XMLWriter::writeAttributeNS' => ['bool', 'prefix'=>'string|null', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'XMLWriter::writeCData' => ['bool', 'content'=>'string'], 'XMLWriter::writeComment' => ['bool', 'content'=>'string'], 'XMLWriter::writeDTD' => ['bool', 'name'=>'string', 'publicid='=>'string', 'systemid='=>'string', 'subset='=>'string'], 'XMLWriter::writeDTDAttlist' => ['bool', 'name'=>'string', 'content'=>'string'], 'XMLWriter::writeDTDElement' => ['bool', 'name'=>'string', 'content'=>'string'], 'XMLWriter::writeDTDEntity' => ['bool', 'name'=>'string', 'content'=>'string', 'pe'=>'bool', 'pubid'=>'string', 'sysid'=>'string', 'ndataid'=>'string'], 'XMLWriter::writeElement' => ['bool', 'name'=>'string', 'content='=>'string|null'], 'XMLWriter::writeElementNS' => ['bool', 'prefix'=>'string|null', 'name'=>'string', 'uri'=>'string', 'content='=>'string|null'], 'XMLWriter::writePI' => ['bool', 'target'=>'string', 'content'=>'string'], 'XMLWriter::writeRaw' => ['bool', 'content'=>'string'], 'xmlwriter_end_attribute' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_cdata' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_comment' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_document' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_attlist' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_entity' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_pi' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_flush' => ['', 'xmlwriter'=>'resource', 'empty='=>'bool'], 'xmlwriter_full_end_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_open_memory' => ['resource|false'], 'xmlwriter_open_uri' => ['resource|false', 'source'=>'string'], 'xmlwriter_output_memory' => ['string', 'xmlwriter'=>'resource', 'flush='=>'bool'], 'xmlwriter_set_indent' => ['bool', 'xmlwriter'=>'resource', 'indent'=>'bool'], 'xmlwriter_set_indent_string' => ['bool', 'xmlwriter'=>'resource', 'indentstring'=>'string'], 'xmlwriter_start_attribute' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_attribute_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string|null', 'name'=>'string', 'uri'=>'string'], 'xmlwriter_start_cdata' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_start_comment' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_start_document' => ['bool', 'xmlwriter'=>'resource', 'version'=>'string', 'encoding'=>'string', 'standalone'=>'string'], 'xmlwriter_start_dtd' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'pubid'=>'string', 'sysid'=>'string'], 'xmlwriter_start_dtd_attlist' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_dtd_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_dtd_entity' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'isparam'=>'bool'], 'xmlwriter_start_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_element_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string|null', 'name'=>'string', 'uri'=>'string|null'], 'xmlwriter_start_pi' => ['bool', 'xmlwriter'=>'resource', 'target'=>'string'], 'xmlwriter_text' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_attribute' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_attribute_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string|null', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_cdata' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_comment' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_dtd' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'pubid'=>'string', 'sysid'=>'string', 'subset'=>'string'], 'xmlwriter_write_dtd_attlist' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_entity' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string', 'pe'=>'int', 'pubid'=>'string', 'sysid'=>'string', 'ndataid'=>'string'], 'xmlwriter_write_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_element_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string|null', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_pi' => ['bool', 'xmlwriter'=>'resource', 'target'=>'string', 'content'=>'string'], 'xmlwriter_write_raw' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xpath_new_context' => ['XPathContext', 'dom_document'=>'DOMDocument'], 'xpath_register_ns' => ['bool', 'xpath_context'=>'xpathcontext', 'prefix'=>'string', 'uri'=>'string'], 'xpath_register_ns_auto' => ['bool', 'xpath_context'=>'xpathcontext', 'context_node='=>'object'], 'xptr_new_context' => ['XPathContext'], 'xsl_xsltprocessor_get_parameter' => ['string', 'namespace'=>'string', 'name'=>'string'], 'xsl_xsltprocessor_get_security_prefs' => ['int'], 'xsl_xsltprocessor_has_exslt_support' => ['bool'], 'xsl_xsltprocessor_register_php_functions' => ['', 'restrict'=>''], 'xsl_xsltprocessor_remove_parameter' => ['bool', 'namespace'=>'string', 'name'=>'string'], 'xsl_xsltprocessor_set_parameter' => ['bool', 'namespace'=>'string', 'name'=>'', 'value'=>'string'], 'xsl_xsltprocessor_set_profiling' => ['bool', 'filename'=>'string'], 'xsl_xsltprocessor_set_security_prefs' => ['int', 'securityprefs'=>'int'], 'xsl_xsltprocessor_transform_to_uri' => ['int', 'doc'=>'DOMDocument', 'uri'=>'string'], 'xsl_xsltprocessor_transform_to_xml' => ['string', 'doc'=>'DOMDocument'], 'xslt_backend_info' => ['string'], 'xslt_backend_name' => ['string'], 'xslt_backend_version' => ['string'], 'xslt_create' => ['resource'], 'xslt_errno' => ['int', 'xh'=>''], 'xslt_error' => ['string', 'xh'=>''], 'xslt_free' => ['', 'xh'=>''], 'xslt_getopt' => ['int', 'processor'=>''], 'xslt_process' => ['', 'xh'=>'', 'xmlcontainer'=>'string', 'xslcontainer'=>'string', 'resultcontainer='=>'string', 'arguments='=>'array', 'parameters='=>'array'], 'xslt_set_base' => ['', 'xh'=>'', 'uri'=>'string'], 'xslt_set_encoding' => ['', 'xh'=>'', 'encoding'=>'string'], 'xslt_set_error_handler' => ['', 'xh'=>'', 'handler'=>''], 'xslt_set_log' => ['', 'xh'=>'', 'log='=>''], 'xslt_set_object' => ['bool', 'processor'=>'', 'obj'=>'object'], 'xslt_set_sax_handler' => ['', 'xh'=>'', 'handlers'=>'array'], 'xslt_set_sax_handlers' => ['', 'processor'=>'', 'handlers'=>'array'], 'xslt_set_scheme_handler' => ['', 'xh'=>'', 'handlers'=>'array'], 'xslt_set_scheme_handlers' => ['', 'xh'=>'', 'handlers'=>'array'], 'xslt_setopt' => ['', 'processor'=>'', 'newmask'=>'int'], 'XSLTProcessor::getParameter' => ['string|false', 'namespaceuri'=>'string', 'localname'=>'string'], 'XsltProcessor::getSecurityPrefs' => ['int'], 'XSLTProcessor::hasExsltSupport' => ['bool'], 'XSLTProcessor::importStylesheet' => ['bool', 'stylesheet'=>'object'], 'XSLTProcessor::registerPHPFunctions' => ['void', 'restrict='=>'mixed'], 'XSLTProcessor::removeParameter' => ['bool', 'namespaceuri'=>'string', 'localname'=>'string'], 'XSLTProcessor::setParameter' => ['bool', 'namespace'=>'string', 'name'=>'string', 'value'=>'string'], 'XSLTProcessor::setParameter\'1' => ['bool', 'namespace'=>'string', 'options'=>'array'], 'XSLTProcessor::setProfiling' => ['bool', 'filename'=>'string'], 'XsltProcessor::setSecurityPrefs' => ['int', 'securityPrefs'=>'int'], 'XSLTProcessor::transformToDoc' => ['DOMDocument|false', 'doc'=>'DOMNode'], 'XSLTProcessor::transformToURI' => ['int', 'doc'=>'DOMDocument', 'uri'=>'string'], 'XSLTProcessor::transformToXML' => ['string|false|null', 'doc'=>'DOMDocument|SimpleXMLElement'], 'Yaconf::get' => ['mixed', 'name'=>'string', 'default_value='=>'mixed'], 'Yaconf::has' => ['bool', 'name'=>'string'], 'Yaf_Action_Abstract::__construct' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract', 'view'=>'Yaf_View_Interface', 'invokeArgs='=>'?array'], 'Yaf_Action_Abstract::display' => ['bool', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf_Action_Abstract::execute' => ['mixed', 'arg='=>'mixed', '...args='=>'mixed'], 'Yaf_Action_Abstract::forward' => ['bool', 'module'=>'string', 'controller='=>'string', 'action='=>'string', 'parameters='=>'?array'], 'Yaf_Action_Abstract::getController' => ['Yaf_Controller_Abstract'], 'Yaf_Action_Abstract::getInvokeArg' => ['mixed|null', 'name'=>'string'], 'Yaf_Action_Abstract::getInvokeArgs' => ['array'], 'Yaf_Action_Abstract::getModuleName' => ['string'], 'Yaf_Action_Abstract::getRequest' => ['Yaf_Request_Abstract'], 'Yaf_Action_Abstract::getResponse' => ['Yaf_Response_Abstract'], 'Yaf_Action_Abstract::getView' => ['Yaf_View_Interface'], 'Yaf_Action_Abstract::getViewpath' => ['string'], 'Yaf_Action_Abstract::init' => [''], 'Yaf_Action_Abstract::initView' => ['Yaf_Response_Abstract', 'options='=>'?array'], 'Yaf_Action_Abstract::redirect' => ['bool', 'url'=>'string'], 'Yaf_Action_Abstract::render' => ['string', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf_Action_Abstract::setViewpath' => ['bool', 'view_directory'=>'string'], 'Yaf_Application::__clone' => ['void'], 'Yaf_Application::__construct' => ['void', 'config'=>'mixed', 'envrion='=>'string'], 'Yaf_Application::__destruct' => ['void'], 'Yaf_Application::__sleep' => ['list'], 'Yaf_Application::__wakeup' => ['void'], 'Yaf_Application::app' => ['void'], 'Yaf_Application::bootstrap' => ['void', 'bootstrap='=>'Yaf_Bootstrap_Abstract'], 'Yaf_Application::clearLastError' => ['Yaf_Application'], 'Yaf_Application::environ' => ['void'], 'Yaf_Application::execute' => ['void', 'entry'=>'callable', '...args'=>'string'], 'Yaf_Application::getAppDirectory' => ['Yaf_Application'], 'Yaf_Application::getConfig' => ['Yaf_Config_Abstract'], 'Yaf_Application::getDispatcher' => ['Yaf_Dispatcher'], 'Yaf_Application::getLastErrorMsg' => ['string'], 'Yaf_Application::getLastErrorNo' => ['int'], 'Yaf_Application::getModules' => ['array'], 'Yaf_Application::run' => ['void'], 'Yaf_Application::setAppDirectory' => ['Yaf_Application', 'directory'=>'string'], 'Yaf_Config_Abstract::__get' => ['mixed', 'name'=>'string'], 'Yaf_Config_Abstract::__isset' => ['bool', 'name'=>'string'], 'Yaf_Config_Abstract::count' => ['0|positive-int'], 'Yaf_Config_Abstract::current' => ['mixed'], 'Yaf_Config_Abstract::get' => ['mixed', 'name'=>'?string'], 'Yaf_Config_Abstract::key' => ['int|string|null|bool'], 'Yaf_Config_Abstract::next' => ['void'], 'Yaf_Config_Abstract::offsetExists' => ['bool', 'name'=>'mixed'], 'Yaf_Config_Abstract::offsetGet' => ['mixed', 'name'=>'mixed'], 'Yaf_Config_Abstract::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], 'Yaf_Config_Abstract::offsetUnset' => ['void', 'name'=>'mixed'], 'Yaf_Config_Abstract::readonly' => ['bool'], 'Yaf_Config_Abstract::rewind' => ['void'], 'Yaf_Config_Abstract::set' => ['bool', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Config_Abstract::toArray' => ['array'], 'Yaf_Config_Abstract::valid' => ['bool'], 'Yaf_Config_Ini::__construct' => ['void', 'config_file'=>'array|string', 'section='=>'?string'], 'Yaf_Config_Ini::__isset' => ['bool', 'name'=>'string'], 'Yaf_Config_Ini::__set' => ['void', 'name'=>'mixed', 'value'=>'mixed'], 'Yaf_Config_Ini::count' => ['0|positive-int'], 'Yaf_Config_Ini::current' => ['mixed'], 'Yaf_Config_Ini::get' => ['mixed', 'name='=>'?string'], 'Yaf_Config_Ini::key' => ['int|string|null|bool'], 'Yaf_Config_Ini::next' => ['void'], 'Yaf_Config_Ini::offsetExists' => ['bool', 'name'=>'mixed'], 'Yaf_Config_Ini::offsetGet' => ['mixed', 'name'=>'mixed'], 'Yaf_Config_Ini::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], 'Yaf_Config_Ini::offsetUnset' => ['void', 'name'=>'mixed'], 'Yaf_Config_Ini::readonly' => ['bool'], 'Yaf_Config_Ini::rewind' => ['void'], 'Yaf_Config_Ini::set' => ['bool', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Config_Ini::toArray' => ['array'], 'Yaf_Config_Ini::valid' => ['bool'], 'Yaf_Config_Simple::__construct' => ['void', 'config_file'=>'array|string', 'section='=>'string'], 'Yaf_Config_Simple::__get' => ['void', 'name='=>'string'], 'Yaf_Config_Simple::__isset' => ['bool', 'name'=>'string'], 'Yaf_Config_Simple::__set' => ['void', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Config_Simple::count' => ['0|positive-int'], 'Yaf_Config_Simple::current' => ['mixed'], 'Yaf_Config_Simple::get' => ['mixed', 'name='=>'?string'], 'Yaf_Config_Simple::key' => ['int|string|null|bool'], 'Yaf_Config_Simple::next' => ['void'], 'Yaf_Config_Simple::offsetExists' => ['bool', 'name'=>'mixed'], 'Yaf_Config_Simple::offsetGet' => ['mixed', 'name'=>'mixed'], 'Yaf_Config_Simple::offsetSet' => ['void', 'name'=>'mixed', 'value'=>'mixed'], 'Yaf_Config_Simple::offsetUnset' => ['void', 'name'=>'mixed'], 'Yaf_Config_Simple::readonly' => ['bool'], 'Yaf_Config_Simple::rewind' => ['void'], 'Yaf_Config_Simple::set' => ['bool', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Config_Simple::toArray' => ['array'], 'Yaf_Config_Simple::valid' => ['bool'], 'Yaf_Controller_Abstract::__clone' => ['void'], 'Yaf_Controller_Abstract::__construct' => ['void'], 'Yaf_Controller_Abstract::display' => ['?bool', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf_Controller_Abstract::forward' => ['?bool', 'action'=>'string'], 'Yaf_Controller_Abstract::forward\'1' => ['?bool', 'controller'=>'string', 'action'=>'string'], 'Yaf_Controller_Abstract::forward\'2' => ['?bool', 'action'=>'string', 'invoke_args'=>'array'], 'Yaf_Controller_Abstract::forward\'3' => ['?bool', 'module'=>'string', 'controller'=>'string', 'action'=>'string'], 'Yaf_Controller_Abstract::forward\'4' => ['?bool', 'controller'=>'string', 'action'=>'string', 'invoke_args'=>'array'], 'Yaf_Controller_Abstract::forward\'5' => ['?bool', 'module'=>'string', 'controller'=>'string', 'action'=>'string', 'invoke_args'=>'array'], 'Yaf_Controller_Abstract::getInvokeArg' => ['?string', 'name'=>'string'], 'Yaf_Controller_Abstract::getInvokeArgs' => ['?array'], 'Yaf_Controller_Abstract::getModuleName' => ['?string'], 'Yaf_Controller_Abstract::getName' => ['?string'], 'Yaf_Controller_Abstract::getRequest' => ['?Yaf_Request_Abstract'], 'Yaf_Controller_Abstract::getResponse' => ['?Yaf_Response_Abstract'], 'Yaf_Controller_Abstract::getView' => ['?Yaf_View_Interface'], 'Yaf_Controller_Abstract::getViewpath' => ['?string'], 'Yaf_Controller_Abstract::init' => ['void'], 'Yaf_Controller_Abstract::initView' => ['?Yaf_View_Interface', 'options='=>'?array'], 'Yaf_Controller_Abstract::redirect' => ['?bool', 'url'=>'string'], 'Yaf_Controller_Abstract::render' => ['string|null|bool', 'tpl'=>'string', 'parameters='=>'?array'], 'Yaf_Controller_Abstract::setViewpath' => ['?bool', 'view_directory'=>'string'], 'Yaf_Dispatcher::__clone' => ['void'], 'Yaf_Dispatcher::__construct' => ['void'], 'Yaf_Dispatcher::__sleep' => ['list'], 'Yaf_Dispatcher::__wakeup' => ['void'], 'Yaf_Dispatcher::autoRender' => ['Yaf_Dispatcher|false|null', 'flag='=>'?bool'], 'Yaf_Dispatcher::catchException' => ['Yaf_Dispatcher|false|null', 'flag='=>'?bool'], 'Yaf_Dispatcher::disableView' => ['?Yaf_Dispatcher'], 'Yaf_Dispatcher::dispatch' => ['Yaf_Response_Abstract|false|null', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Dispatcher::enableView' => ['?Yaf_Dispatcher'], 'Yaf_Dispatcher::flushInstantly' => ['Yaf_Dispatcher|false|null', 'flag='=>'?bool'], 'Yaf_Dispatcher::getApplication' => ['?Yaf_Application'], 'Yaf_Dispatcher::getDefaultAction' => ['?string'], 'Yaf_Dispatcher::getDefaultController' => ['?string'], 'Yaf_Dispatcher::getDefaultModule' => ['?string'], 'Yaf_Dispatcher::getInstance' => ['?Yaf_Dispatcher'], 'Yaf_Dispatcher::getRequest' => ['?Yaf_Request_Abstract'], 'Yaf_Dispatcher::getResponse' => ['?Yaf_Response_Abstract'], 'Yaf_Dispatcher::getRouter' => ['?Yaf_Router'], 'Yaf_Dispatcher::initView' => ['Yaf_View_Interface|null|false', 'templates_dir'=>'string', 'options='=>'?array'], 'Yaf_Dispatcher::registerPlugin' => ['Yaf_Dispatcher|false|null', 'plugin'=>'Yaf_Plugin_Abstract'], 'Yaf_Dispatcher::returnResponse' => ['Yaf_Dispatcher|false|null', 'flag='=>'bool'], 'Yaf_Dispatcher::setDefaultAction' => ['Yaf_Dispatcher|false|null', 'action'=>'string'], 'Yaf_Dispatcher::setDefaultController' => ['Yaf_Dispatcher|false|null', 'controller'=>'string'], 'Yaf_Dispatcher::setDefaultModule' => ['Yaf_Dispatcher|false|null', 'module'=>'string'], 'Yaf_Dispatcher::setErrorHandler' => ['Yaf_Dispatcher|false|null', 'callback'=>'mixed', 'error_types'=>'int'], 'Yaf_Dispatcher::setRequest' => ['?Yaf_Dispatcher', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Dispatcher::setResponse' => ['?Yaf_Dispatcher', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Dispatcher::setView' => ['?Yaf_Dispatcher', 'view'=>'Yaf_View_Interface'], 'Yaf_Dispatcher::throwException' => ['Yaf_Dispatcher|false|null', 'flag='=>'?bool'], 'Yaf_Exception::__construct' => ['void'], 'Yaf_Exception::getPrevious' => ['void'], 'Yaf_Loader::__clone' => ['void'], 'Yaf_Loader::__construct' => ['void'], 'Yaf_Loader::__sleep' => ['list'], 'Yaf_Loader::__wakeup' => ['void'], 'Yaf_Loader::autoload' => ['void'], 'Yaf_Loader::clearLocalNamespace' => ['void'], 'Yaf_Loader::getInstance' => ['void'], 'Yaf_Loader::getLibraryPath' => ['Yaf_Loader', 'is_global='=>'bool'], 'Yaf_Loader::getLocalNamespace' => ['void'], 'Yaf_Loader::import' => ['void'], 'Yaf_Loader::isLocalName' => ['void'], 'Yaf_Loader::registerLocalNamespace' => ['void', 'prefix'=>'mixed'], 'Yaf_Loader::setLibraryPath' => ['Yaf_Loader', 'directory'=>'string', 'is_global='=>'bool'], 'Yaf_Plugin_Abstract::dispatchLoopShutdown' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::dispatchLoopStartup' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::postDispatch' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::preDispatch' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::preResponse' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::routerShutdown' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Plugin_Abstract::routerStartup' => ['void', 'request'=>'Yaf_Request_Abstract', 'response'=>'Yaf_Response_Abstract'], 'Yaf_Registry::__clone' => ['void'], 'Yaf_Registry::__construct' => ['void'], 'Yaf_Registry::del' => ['void', 'name'=>'string'], 'Yaf_Registry::get' => ['mixed', 'name'=>'string'], 'Yaf_Registry::has' => ['bool', 'name'=>'string'], 'Yaf_Registry::set' => ['bool', 'name'=>'string', 'value'=>'string'], 'Yaf_Request_Abstract::get' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Abstract::getActionName' => ['?string'], 'Yaf_Request_Abstract::getBaseUri' => ['?string'], 'Yaf_Request_Abstract::getCookie' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Abstract::getControllerName' => ['?string'], 'Yaf_Request_Abstract::getEnv' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Abstract::getException' => ['?Exception'], 'Yaf_Request_Abstract::getFiles' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Abstract::getLanguage' => ['?string'], 'Yaf_Request_Abstract::getMethod' => ['?string'], 'Yaf_Request_Abstract::getModuleName' => ['?string'], 'Yaf_Request_Abstract::getParam' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'Yaf_Request_Abstract::getParams' => ['?array'], 'Yaf_Request_Abstract::getPost' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Abstract::getQuery' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Abstract::getRaw' => ['?string'], 'Yaf_Request_Abstract::getRequest' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Abstract::getRequestUri' => ['?string'], 'Yaf_Request_Abstract::getServer' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Abstract::cleanParams' => ['?Yaf_Request_Abstract'], 'Yaf_Request_Abstract::isCli' => ['bool'], 'Yaf_Request_Abstract::isDelete' => ['bool'], 'Yaf_Request_Abstract::isDispatched' => ['bool'], 'Yaf_Request_Abstract::isGet' => ['bool'], 'Yaf_Request_Abstract::isHead' => ['bool'], 'Yaf_Request_Abstract::isOptions' => ['bool'], 'Yaf_Request_Abstract::isPatch' => ['bool'], 'Yaf_Request_Abstract::isPost' => ['bool'], 'Yaf_Request_Abstract::isPut' => ['bool'], 'Yaf_Request_Abstract::isRouted' => ['bool'], 'Yaf_Request_Abstract::isXmlHttpRequest' => ['bool'], 'Yaf_Request_Abstract::setActionName' => ['?Yaf_Request_Abstract', 'action'=>'string', 'format_name='=>'bool|true'], 'Yaf_Request_Abstract::setBaseUri' => ['Yaf_Request_Abstract|false', 'uir'=>'string'], 'Yaf_Request_Abstract::setControllerName' => ['?Yaf_Request_Abstract', 'controller'=>'string', 'format_name='=>'bool|true'], 'Yaf_Request_Abstract::setDispatched' => ['?Yaf_Request_Abstract', 'flag='=>'bool|true'], 'Yaf_Request_Abstract::setModuleName' => ['?Yaf_Request_Abstract', 'module'=>'string', 'format_name='=>'bool|true'], 'Yaf_Request_Abstract::setParam' => ['Yaf_Request_Abstract|false|null', 'name'=>'mixed', 'value='=>'?mixed'], 'Yaf_Request_Abstract::setRequestUri' => ['?Yaf_Request_Abstract', 'uir'=>'string'], 'Yaf_Request_Abstract::setRouted' => ['?Yaf_Request_Abstract', 'flag='=>'bool|true'], 'Yaf_Request_Http::__clone' => ['void'], 'Yaf_Request_Http::__construct' => ['void', 'requestUri='=>'?string', 'baseUri='=>'?string'], 'Yaf_Request_Http::get' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Http::getActionName' => ['?string'], 'Yaf_Request_Http::getBaseUri' => ['?string'], 'Yaf_Request_Http::getCookie' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Http::getControllerName' => ['?string'], 'Yaf_Request_Http::getEnv' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Http::getException' => ['?Exception'], 'Yaf_Request_Http::getFiles' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Http::getLanguage' => ['?string'], 'Yaf_Request_Http::getMethod' => ['?string'], 'Yaf_Request_Http::getModuleName' => ['?string'], 'Yaf_Request_Http::getParam' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'Yaf_Request_Http::getParams' => ['?array'], 'Yaf_Request_Http::getPost' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Http::getQuery' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Http::getRaw' => ['?string'], 'Yaf_Request_Http::getRequest' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Http::getRequestUri' => ['?string'], 'Yaf_Request_Http::getServer' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Http::cleanParams' => ['?Yaf_Request_Http'], 'Yaf_Request_Http::isCli' => ['bool'], 'Yaf_Request_Http::isDelete' => ['bool'], 'Yaf_Request_Http::isDispatched' => ['bool'], 'Yaf_Request_Http::isGet' => ['bool'], 'Yaf_Request_Http::isHead' => ['bool'], 'Yaf_Request_Http::isOptions' => ['bool'], 'Yaf_Request_Http::isPatch' => ['bool'], 'Yaf_Request_Http::isPost' => ['bool'], 'Yaf_Request_Http::isPut' => ['bool'], 'Yaf_Request_Http::isRouted' => ['bool'], 'Yaf_Request_Http::isXmlHttpRequest' => ['bool'], 'Yaf_Request_Http::setActionName' => ['?Yaf_Request_Http', 'action'=>'string', 'format_name='=>'bool|true'], 'Yaf_Request_Http::setBaseUri' => ['Yaf_Request_Http|false', 'uir'=>'string'], 'Yaf_Request_Http::setControllerName' => ['?Yaf_Request_Http', 'controller'=>'string', 'format_name='=>'bool|true'], 'Yaf_Request_Http::setDispatched' => ['?Yaf_Request_Http', 'flag='=>'bool|true'], 'Yaf_Request_Http::setModuleName' => ['?Yaf_Request_Http', 'module'=>'string', 'format_name='=>'bool|true'], 'Yaf_Request_Http::setParam' => ['Yaf_Request_Http|false|null', 'name'=>'mixed', 'value='=>'?mixed'], 'Yaf_Request_Http::setRequestUri' => ['?Yaf_Request_Http', 'uir'=>'string'], 'Yaf_Request_Http::setRouted' => ['?Yaf_Request_Http', 'flag='=>'bool|true'], 'Yaf_Request_Simple::__construct' => ['void', 'method='=>'?string', 'module='=>'?string', 'controller='=>'?string', 'action='=>'?string', 'params='=>'?array'], 'Yaf_Request_Simple::get' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Simple::getActionName' => ['?string'], 'Yaf_Request_Simple::getBaseUri' => ['?string'], 'Yaf_Request_Simple::getCookie' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Simple::getControllerName' => ['?string'], 'Yaf_Request_Simple::getEnv' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Simple::getException' => ['?Exception'], 'Yaf_Request_Simple::getFiles' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Simple::getLanguage' => ['?string'], 'Yaf_Request_Simple::getMethod' => ['?string'], 'Yaf_Request_Simple::getModuleName' => ['?string'], 'Yaf_Request_Simple::getParam' => ['mixed', 'name'=>'string', 'default='=>'mixed'], 'Yaf_Request_Simple::getParams' => ['?array'], 'Yaf_Request_Simple::getPost' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Simple::getQuery' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Simple::getRaw' => ['?string'], 'Yaf_Request_Simple::getRequest' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Simple::getRequestUri' => ['?string'], 'Yaf_Request_Simple::getServer' => ['mixed', 'name='=>'?string', 'default='=>'?mixed'], 'Yaf_Request_Simple::cleanParams' => ['?Yaf_Request_Simple'], 'Yaf_Request_Simple::isCli' => ['bool'], 'Yaf_Request_Simple::isDelete' => ['bool'], 'Yaf_Request_Simple::isDispatched' => ['bool'], 'Yaf_Request_Simple::isGet' => ['bool'], 'Yaf_Request_Simple::isHead' => ['bool'], 'Yaf_Request_Simple::isOptions' => ['bool'], 'Yaf_Request_Simple::isPatch' => ['bool'], 'Yaf_Request_Simple::isPost' => ['bool'], 'Yaf_Request_Simple::isPut' => ['bool'], 'Yaf_Request_Simple::isRouted' => ['bool'], 'Yaf_Request_Simple::isXmlHttpRequest' => ['bool'], 'Yaf_Request_Simple::setActionName' => ['?Yaf_Request_Simple', 'action'=>'string', 'format_name='=>'bool|true'], 'Yaf_Request_Simple::setBaseUri' => ['Yaf_Request_Simple|false', 'uir'=>'string'], 'Yaf_Request_Simple::setControllerName' => ['?Yaf_Request_Simple', 'controller'=>'string', 'format_name='=>'bool|true'], 'Yaf_Request_Simple::setDispatched' => ['?Yaf_Request_Simple', 'flag='=>'bool|true'], 'Yaf_Request_Simple::setModuleName' => ['?Yaf_Request_Simple', 'module'=>'string', 'format_name='=>'bool|true'], 'Yaf_Request_Simple::setParam' => ['Yaf_Request_Simple|bool|null', 'name'=>'mixed', 'value='=>'?mixed'], 'Yaf_Request_Simple::setRequestUri' => ['?Yaf_Request_Simple', 'uir'=>'string'], 'Yaf_Request_Simple::setRouted' => ['?Yaf_Request_Simple', 'flag='=>'bool|true'], 'Yaf_Response_Abstract::__clone' => ['void'], 'Yaf_Response_Abstract::__construct' => ['void'], 'Yaf_Response_Abstract::__destruct' => ['void'], 'Yaf_Response_Abstract::__toString' => ['string'], 'Yaf_Response_Abstract::appendBody' => ['Yaf_Response_Abstract|false|null', 'body'=>'string', 'name='=>'?string'], 'Yaf_Response_Abstract::clearBody' => ['?Yaf_Response_Abstract', 'name='=>'?string'], 'Yaf_Response_Abstract::getBody' => ['mixed', 'name='=>'string'], 'Yaf_Response_Abstract::prependBody' => ['Yaf_Response_Abstract|false|null', 'body'=>'string', 'name='=>'?string'], 'Yaf_Response_Abstract::response' => ['bool'], 'Yaf_Response_Abstract::setBody' => ['Yaf_Response_Abstract|false|null', 'body'=>'string', 'name='=>'?string'], 'Yaf_Response_Abstract::setRedirect' => ['?bool', 'url'=>'string'], 'Yaf_Response_Cli::__clone' => ['void'], 'Yaf_Response_Cli::__construct' => ['void'], 'Yaf_Response_Cli::__destruct' => ['void'], 'Yaf_Response_Cli::__toString' => ['string'], 'Yaf_Response_Cli::appendBody' => ['Yaf_Response_Cli|false|null', 'body'=>'string', 'name='=>'?string'], 'Yaf_Response_Cli::clearBody' => ['?Yaf_Response_Cli', 'name='=>'?string'], 'Yaf_Response_Cli::getBody' => ['mixed', 'name='=>'string'], 'Yaf_Response_Cli::prependBody' => ['Yaf_Response_Cli|false|null', 'body'=>'string', 'name='=>'?string'], 'Yaf_Response_Cli::response' => ['bool'], 'Yaf_Response_Cli::setBody' => ['Yaf_Response_Cli|false|null', 'body'=>'string', 'name='=>'?string'], 'Yaf_Response_Cli::setRedirect' => ['?bool', 'url'=>'string'], 'Yaf_Response_Http::__clone' => ['void'], 'Yaf_Response_Http::__construct' => ['void'], 'Yaf_Response_Http::__destruct' => ['void'], 'Yaf_Response_Http::__toString' => ['string'], 'Yaf_Response_Http::appendBody' => ['Yaf_Response_Http|false|null', 'body'=>'string', 'name='=>'?string'], 'Yaf_Response_Http::clearHeaders' => ['Yaf_Response_Http|false|null'], 'Yaf_Response_Http::clearBody' => ['?Yaf_Response_Http', 'name='=>'?string'], 'Yaf_Response_Http::getBody' => ['mixed', 'name='=>'string'], 'Yaf_Response_Http::getHeader' => ['mixed', 'name='=>'string'], 'Yaf_Response_Http::prependBody' => ['Yaf_Response_Http|false|null', 'body'=>'string', 'name='=>'?string'], 'Yaf_Response_Http::response' => ['?bool'], 'Yaf_Response_Http::setAllHeaders' => ['bool', 'headers'=>'array'], 'Yaf_Response_Http::setBody' => ['Yaf_Response_Http|false|null', 'body'=>'string', 'name='=>'?string'], 'Yaf_Response_Http::setHeader' => ['?bool', 'name'=>'string', 'value'=>'string', 'replace='=>'bool|false', 'response_code='=>'int'], 'Yaf_Response_Http::setRedirect' => ['?bool', 'url'=>'string'], 'Yaf_Route_Interface::__construct' => ['void'], 'Yaf_Route_Interface::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Interface::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Map::__construct' => ['void', 'controller_prefer='=>'string', 'delimiter='=>'string'], 'Yaf_Route_Map::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Map::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Regex::__construct' => ['void', 'match'=>'string', 'route'=>'array', 'map='=>'array', 'verify='=>'array', 'reverse='=>'string'], 'Yaf_Route_Regex::addConfig' => ['Yaf_Router|bool', 'config'=>'Yaf_Config_Abstract'], 'Yaf_Route_Regex::addRoute' => ['Yaf_Router|bool', 'name'=>'string', 'route'=>'Yaf_Route_Interface'], 'Yaf_Route_Regex::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Regex::getCurrentRoute' => ['string'], 'Yaf_Route_Regex::getRoute' => ['Yaf_Route_Interface', 'name'=>'string'], 'Yaf_Route_Regex::getRoutes' => ['Yaf_Route_Interface[]'], 'Yaf_Route_Regex::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Rewrite::__construct' => ['void', 'match'=>'string', 'route'=>'array', 'verify='=>'array'], 'Yaf_Route_Rewrite::addConfig' => ['Yaf_Router|bool', 'config'=>'Yaf_Config_Abstract'], 'Yaf_Route_Rewrite::addRoute' => ['Yaf_Router|bool', 'name'=>'string', 'route'=>'Yaf_Route_Interface'], 'Yaf_Route_Rewrite::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Rewrite::getCurrentRoute' => ['string'], 'Yaf_Route_Rewrite::getRoute' => ['Yaf_Route_Interface', 'name'=>'string'], 'Yaf_Route_Rewrite::getRoutes' => ['Yaf_Route_Interface[]'], 'Yaf_Route_Rewrite::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Simple::__construct' => ['void', 'module_name'=>'string', 'controller_name'=>'string', 'action_name'=>'string'], 'Yaf_Route_Simple::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Simple::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Static::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Static::match' => ['void', 'uri'=>'string'], 'Yaf_Route_Static::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Route_Supervar::__construct' => ['void', 'supervar_name'=>'string'], 'Yaf_Route_Supervar::assemble' => ['string', 'info'=>'array', 'query='=>'array'], 'Yaf_Route_Supervar::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Router::__construct' => ['void'], 'Yaf_Router::addConfig' => ['bool', 'config'=>'Yaf_Config_Abstract'], 'Yaf_Router::addRoute' => ['bool', 'name'=>'string', 'route'=>'Yaf_Route_Abstract'], 'Yaf_Router::getCurrentRoute' => ['string'], 'Yaf_Router::getRoute' => ['Yaf_Route_Interface', 'name'=>'string'], 'Yaf_Router::getRoutes' => ['mixed'], 'Yaf_Router::route' => ['bool', 'request'=>'Yaf_Request_Abstract'], 'Yaf_Session::__clone' => ['void'], 'Yaf_Session::__construct' => ['void'], 'Yaf_Session::__get' => ['void', 'name'=>'string'], 'Yaf_Session::__isset' => ['void', 'name'=>'string'], 'Yaf_Session::__set' => ['void', 'name'=>'string', 'value'=>'string'], 'Yaf_Session::__sleep' => ['list'], 'Yaf_Session::__unset' => ['void', 'name'=>'string'], 'Yaf_Session::__wakeup' => ['void'], 'Yaf_Session::count' => ['0|positive-int'], 'Yaf_Session::current' => ['void'], 'Yaf_Session::del' => ['void', 'name'=>'string'], 'Yaf_Session::get' => ['mixed', 'name'=>'string'], 'Yaf_Session::getInstance' => ['void'], 'Yaf_Session::has' => ['void', 'name'=>'string'], 'Yaf_Session::key' => ['void'], 'Yaf_Session::next' => ['void'], 'Yaf_Session::offsetExists' => ['void', 'name'=>'string'], 'Yaf_Session::offsetGet' => ['void', 'name'=>'string'], 'Yaf_Session::offsetSet' => ['void', 'name'=>'string', 'value'=>'string'], 'Yaf_Session::offsetUnset' => ['void', 'name'=>'string'], 'Yaf_Session::rewind' => ['void'], 'Yaf_Session::set' => ['Yaf_Session|bool', 'name'=>'string', 'value'=>'mixed'], 'Yaf_Session::start' => ['void'], 'Yaf_Session::valid' => ['void'], 'Yaf_View_Interface::assign' => ['Yaf_View_Interface|bool', 'name'=>'string', 'value='=>'?mixed'], 'Yaf_View_Interface::display' => ['Yaf_View_Interface|bool', 'tpl'=>'string', 'tpl_vars='=>'?array'], 'Yaf_View_Interface::getScriptPath' => ['string'], 'Yaf_View_Interface::render' => ['string|bool', 'tpl'=>'string', 'tpl_vars='=>'?array'], 'Yaf_View_Interface::setScriptPath' => ['bool', 'template_dir'=>'string'], 'Yaf_View_Simple::__construct' => ['void', 'tempalte_dir'=>'string', 'options='=>'?array'], 'Yaf_View_Simple::__get' => ['mixed', 'name='=>'?string'], 'Yaf_View_Simple::__isset' => ['bool', 'name'=>'string'], 'Yaf_View_Simple::__set' => ['void', 'name'=>'string', 'value'=>'mixed'], 'Yaf_View_Simple::assign' => ['Yaf_View_Simple|false|null', 'name='=>'?mixed', 'default='=>'?mixed'], 'Yaf_View_Simple::assignRef' => ['?Yaf_View_Simple', 'name'=>'string', '&value'=>'mixed'], 'Yaf_View_Simple::clear' => ['?Yaf_View_Simple', 'name='=>'string'], 'Yaf_View_Simple::display' => ['?bool', 'tpl'=>'string', 'tpl_vars='=>'?array'], 'Yaf_View_Simple::eval' => ['string|null|false', 'tpl_str'=>'string', 'vars='=>'?array'], 'Yaf_View_Simple::get' => ['mixed', 'name='=>'?string'], 'Yaf_View_Simple::getScriptPath' => ['?string'], 'Yaf_View_Simple::render' => ['string|null|false', 'tpl'=>'string', 'tpl_vars='=>'?array'], 'Yaf_View_Simple::setScriptPath' => ['Yaf_View_Simple|false|null', 'template_dir'=>'string'], 'yaml_emit' => ['string', 'data'=>'mixed', 'encoding='=>'int', 'linebreak='=>'int'], 'yaml_emit_file' => ['bool', 'filename'=>'string', 'data'=>'mixed', 'encoding='=>'int', 'linebreak='=>'int'], 'yaml_parse' => ['mixed', 'input'=>'string', 'pos='=>'int', '&w_ndocs='=>'int', 'callbacks='=>'array'], 'yaml_parse_file' => ['mixed', 'filename'=>'string', 'pos='=>'int', '&w_ndocs='=>'int', 'callbacks='=>'array'], 'yaml_parse_url' => ['mixed', 'url'=>'string', 'pos='=>'int', '&w_ndocs='=>'int', 'callbacks='=>'array'], 'Yar_Client::__call' => ['void', 'method'=>'string', 'parameters'=>'array'], 'Yar_Client::__construct' => ['void', 'url'=>'string'], 'Yar_Client::setOpt' => ['bool', 'name'=>'int', 'value'=>'mixed'], 'Yar_Client_Exception::getType' => ['void'], 'Yar_Concurrent_Client::call' => ['int', 'uri'=>'string', 'method'=>'string', 'parameters'=>'array', 'callback='=>'callable'], 'Yar_Concurrent_Client::loop' => ['bool', 'callback='=>'callable', 'error_callback='=>'callable'], 'Yar_Concurrent_Client::reset' => ['bool'], 'Yar_Server::__construct' => ['void', 'obj'=>'Object'], 'Yar_Server::handle' => ['bool'], 'Yar_Server_Exception::getType' => ['string'], 'yaz_addinfo' => ['string', 'id'=>'resource'], 'yaz_ccl_conf' => ['void', 'id'=>'resource', 'config'=>'array'], 'yaz_ccl_parse' => ['bool', 'id'=>'resource', 'query'=>'string', '&w_result'=>'array'], 'yaz_close' => ['bool', 'id'=>'resource'], 'yaz_connect' => ['mixed', 'zurl'=>'string', 'options='=>'mixed'], 'yaz_database' => ['bool', 'id'=>'resource', 'databases'=>'string'], 'yaz_element' => ['bool', 'id'=>'resource', 'elementset'=>'string'], 'yaz_errno' => ['int', 'id'=>'resource'], 'yaz_error' => ['string', 'id'=>'resource'], 'yaz_es' => ['void', 'id'=>'resource', 'type'=>'string', 'args'=>'array'], 'yaz_es_result' => ['array', 'id'=>'resource'], 'yaz_get_option' => ['string', 'id'=>'resource', 'name'=>'string'], 'yaz_hits' => ['int', 'id'=>'resource', 'searchresult='=>'array'], 'yaz_itemorder' => ['void', 'id'=>'resource', 'args'=>'array'], 'yaz_present' => ['bool', 'id'=>'resource'], 'yaz_range' => ['void', 'id'=>'resource', 'start'=>'int', 'number'=>'int'], 'yaz_record' => ['string', 'id'=>'resource', 'pos'=>'int', 'type'=>'string'], 'yaz_scan' => ['void', 'id'=>'resource', 'type'=>'string', 'startterm'=>'string', 'flags='=>'array'], 'yaz_scan_result' => ['array', 'id'=>'resource', 'result='=>'array'], 'yaz_schema' => ['void', 'id'=>'resource', 'schema'=>'string'], 'yaz_search' => ['bool', 'id'=>'resource', 'type'=>'string', 'query'=>'string'], 'yaz_set_option' => ['', 'id'=>'', 'name'=>'string', 'value'=>'string', 'options'=>'array'], 'yaz_sort' => ['void', 'id'=>'resource', 'criteria'=>'string'], 'yaz_syntax' => ['void', 'id'=>'resource', 'syntax'=>'string'], 'yaz_wait' => ['mixed', '&rw_options='=>'array'], 'yp_all' => ['void', 'domain'=>'string', 'map'=>'string', 'callback'=>'string'], 'yp_cat' => ['array', 'domain'=>'string', 'map'=>'string'], 'yp_err_string' => ['string', 'errorcode'=>'int'], 'yp_errno' => ['int'], 'yp_first' => ['array', 'domain'=>'string', 'map'=>'string'], 'yp_get_default_domain' => ['string'], 'yp_master' => ['string', 'domain'=>'string', 'map'=>'string'], 'yp_match' => ['string', 'domain'=>'string', 'map'=>'string', 'key'=>'string'], 'yp_next' => ['array', 'domain'=>'string', 'map'=>'string', 'key'=>'string'], 'yp_order' => ['int', 'domain'=>'string', 'map'=>'string'], 'zem_get_extension_info_by_id' => [''], 'zem_get_extension_info_by_name' => [''], 'zem_get_extensions_info' => [''], 'zem_get_license_info' => [''], 'zend_current_obfuscation_level' => ['int'], 'zend_disk_cache_clear' => ['bool', 'namespace='=>'mixed|string'], 'zend_disk_cache_delete' => ['mixed|null', 'key'=>''], 'zend_disk_cache_fetch' => ['mixed|null', 'key'=>''], 'zend_disk_cache_store' => ['bool', 'key'=>'', 'value'=>'', 'ttl='=>'int|mixed'], 'zend_get_id' => ['array', 'all_ids='=>'all_ids|false'], 'zend_is_configuration_changed' => [''], 'zend_loader_current_file' => ['string'], 'zend_loader_enabled' => ['bool'], 'zend_loader_file_encoded' => ['bool'], 'zend_loader_file_licensed' => ['array'], 'zend_loader_install_license' => ['bool', 'license_file'=>'license_file', 'override'=>'override'], 'zend_logo_guid' => ['string'], 'zend_obfuscate_class_name' => ['string', 'class_name'=>'class_name'], 'zend_obfuscate_function_name' => ['string', 'function_name'=>'function_name'], 'zend_optimizer_version' => ['string'], 'zend_runtime_obfuscate' => ['void'], 'zend_send_buffer' => ['null|false', 'buffer'=>'string', 'mime_type='=>'string', 'custom_headers='=>'string'], 'zend_send_file' => ['null|false', 'filename'=>'string', 'mime_type='=>'string', 'custom_headers='=>'string'], 'zend_set_configuration_changed' => [''], 'zend_shm_cache_clear' => ['bool', 'namespace='=>'mixed|string'], 'zend_shm_cache_delete' => ['mixed|null', 'key'=>''], 'zend_shm_cache_fetch' => ['mixed|null', 'key'=>''], 'zend_shm_cache_store' => ['bool', 'key'=>'', 'value'=>'', 'ttl='=>'int|mixed'], 'zend_thread_id' => ['int'], 'zend_version' => ['string'], 'ZendAPI_Job::addJobToQueue' => ['int', 'jobqueue_url'=>'string', 'password'=>'string'], 'ZendAPI_Job::getApplicationID' => [''], 'ZendAPI_Job::getEndTime' => [''], 'ZendAPI_Job::getGlobalVariables' => [''], 'ZendAPI_Job::getHost' => [''], 'ZendAPI_Job::getID' => [''], 'ZendAPI_Job::getInterval' => [''], 'ZendAPI_Job::getJobDependency' => [''], 'ZendAPI_Job::getJobName' => [''], 'ZendAPI_Job::getJobPriority' => [''], 'ZendAPI_Job::getJobStatus' => ['int'], 'ZendAPI_Job::getLastPerformedStatus' => ['int'], 'ZendAPI_Job::getOutput' => ['An'], 'ZendAPI_Job::getPreserved' => [''], 'ZendAPI_Job::getProperties' => ['array'], 'ZendAPI_Job::getScheduledTime' => [''], 'ZendAPI_Job::getScript' => [''], 'ZendAPI_Job::getTimeToNextRepeat' => ['int'], 'ZendAPI_Job::getUserVariables' => [''], 'ZendAPI_Job::setApplicationID' => ['', 'app_id'=>''], 'ZendAPI_Job::setGlobalVariables' => ['', 'vars'=>''], 'ZendAPI_Job::setJobDependency' => ['', 'job_id'=>''], 'ZendAPI_Job::setJobName' => ['', 'name'=>''], 'ZendAPI_Job::setJobPriority' => ['', 'priority'=>'int'], 'ZendAPI_Job::setPreserved' => ['', 'preserved'=>''], 'ZendAPI_Job::setRecurrenceData' => ['', 'interval'=>'', 'end_time='=>'mixed'], 'ZendAPI_Job::setScheduledTime' => ['', 'timestamp'=>''], 'ZendAPI_Job::setScript' => ['', 'script'=>''], 'ZendAPI_Job::setUserVariables' => ['', 'vars'=>''], 'ZendAPI_Job::ZendAPI_Job' => ['Job', 'script'=>'script'], 'ZendAPI_Queue::addJob' => ['int', '&job'=>'Job'], 'ZendAPI_Queue::getAllApplicationIDs' => ['array'], 'ZendAPI_Queue::getAllhosts' => ['array'], 'ZendAPI_Queue::getHistoricJobs' => ['array', 'status'=>'int', 'start_time'=>'', 'end_time'=>'', 'index'=>'int', 'count'=>'int', '&total'=>'int'], 'ZendAPI_Queue::getJob' => ['Job', 'job_id'=>'int'], 'ZendAPI_Queue::getJobsInQueue' => ['array', 'filter_options='=>'array', 'max_jobs='=>'int', 'with_globals_and_output='=>'bool|false'], 'ZendAPI_Queue::getLastError' => ['string'], 'ZendAPI_Queue::getNumOfJobsInQueue' => ['int', 'filter_options='=>'array'], 'ZendAPI_Queue::getStatistics' => ['array'], 'ZendAPI_Queue::isScriptExists' => ['bool', 'path'=>'string'], 'ZendAPI_Queue::isSuspend' => ['bool'], 'ZendAPI_Queue::login' => ['bool', 'password'=>'string', 'application_id='=>'int'], 'ZendAPI_Queue::removeJob' => ['bool', 'job_id'=>'array|int'], 'ZendAPI_Queue::requeueJob' => ['bool', 'job'=>'Job'], 'ZendAPI_Queue::resumeJob' => ['bool', 'job_id'=>'array|int'], 'ZendAPI_Queue::resumeQueue' => ['bool'], 'ZendAPI_Queue::setMaxHistoryTime' => ['bool'], 'ZendAPI_Queue::suspendJob' => ['bool', 'job_id'=>'array|int'], 'ZendAPI_Queue::suspendQueue' => ['bool'], 'ZendAPI_Queue::updateJob' => ['int', '&job'=>'Job'], 'ZendAPI_Queue::zendapi_queue' => ['ZendAPI_Queue', 'queue_url'=>'string'], 'zip_close' => ['void', 'zip'=>'resource'], 'zip_entry_close' => ['bool', 'zip_ent'=>'resource'], 'zip_entry_compressedsize' => ['int|false', 'zip_entry'=>'resource'], 'zip_entry_compressionmethod' => ['string|false', 'zip_entry'=>'resource'], 'zip_entry_filesize' => ['int|false', 'zip_entry'=>'resource'], 'zip_entry_name' => ['string|false', 'zip_entry'=>'resource'], 'zip_entry_open' => ['bool', 'zip_dp'=>'resource', 'zip_entry'=>'resource', 'mode='=>'string'], 'zip_entry_read' => ['string|false', 'zip_entry'=>'resource', 'len='=>'int'], 'zip_open' => ['resource|false|int', 'filename'=>'string'], 'zip_read' => ['resource|false|int', 'zip'=>'resource'], 'ZipArchive::addEmptyDir' => ['bool', 'dirname'=>'string'], 'ZipArchive::addFile' => ['bool', 'filepath'=>'string', 'entryname='=>'string', 'start='=>'int', 'length='=>'int'], 'ZipArchive::addFromString' => ['bool', 'entryname'=>'string', 'content'=>'string'], 'ZipArchive::addGlob' => ['bool', 'pattern'=>'string', 'flags='=>'int', 'options='=>'array'], 'ZipArchive::addPattern' => ['bool', 'pattern'=>'string', 'path='=>'string', 'options='=>'array'], 'ZipArchive::close' => ['bool'], 'ZipArchive::count' => ['0|positive-int'], 'ZipArchive::createEmptyDir' => ['bool', 'dirname'=>'string'], 'ZipArchive::deleteIndex' => ['bool', 'index'=>'int'], 'ZipArchive::deleteName' => ['bool', 'name'=>'string'], 'ZipArchive::extractTo' => ['bool', 'pathto'=>'string', 'files='=>'string[]|string'], 'ZipArchive::getArchiveComment' => ['string', 'flags='=>'int'], 'ZipArchive::getCommentIndex' => ['string', 'index'=>'int', 'flags='=>'int'], 'ZipArchive::getCommentName' => ['string', 'name'=>'string', 'flags='=>'int'], 'ZipArchive::getExternalAttributesIndex' => ['bool', 'index'=>'int', '&w_opsys'=>'int', '&w_attr'=>'int', 'flags='=>'int'], 'ZipArchive::getExternalAttributesName' => ['bool', 'name'=>'string', '&w_opsys'=>'int', '&w_attr'=>'int', 'flags='=>'int'], 'ZipArchive::getFromIndex' => ['string|false', 'index'=>'int', 'len='=>'int', 'flags='=>'int'], 'ZipArchive::getFromName' => ['string|false', 'entryname'=>'string', 'len='=>'int', 'flags='=>'int'], 'ZipArchive::getNameIndex' => ['string|false', 'index'=>'int', 'flags='=>'int'], 'ZipArchive::getStatusString' => ['string'], 'ZipArchive::getStream' => ['resource|false', 'entryname'=>'string'], 'ZipArchive::locateName' => ['int|false', 'filename'=>'string', 'flags='=>'int'], 'ZipArchive::open' => ['ZipArchive::ER_*|true', 'source'=>'string', 'flags='=>'int'], 'ZipArchive::renameIndex' => ['bool', 'index'=>'int', 'new_name'=>'string'], 'ZipArchive::renameName' => ['bool', 'name'=>'string', 'new_name'=>'string'], 'ZipArchive::setArchiveComment' => ['bool', 'comment'=>'string'], 'ZipArchive::setCommentIndex' => ['bool', 'index'=>'int', 'comment'=>'string'], 'ZipArchive::setCommentName' => ['bool', 'name'=>'string', 'comment'=>'string'], 'ZipArchive::setCompressionIndex' => ['bool', 'index'=>'int', 'comp_method'=>'int', 'comp_flags='=>'int'], 'ZipArchive::setCompressionName' => ['bool', 'name'=>'string', 'comp_method'=>'int', 'comp_flags='=>'int'], 'ZipArchive::setEncryptionIndex' => ['bool', 'index'=>'int', 'method'=>'string', 'password='=>'string'], 'ZipArchive::setEncryptionName' => ['bool', 'name'=>'string', 'method'=>'int', 'password='=>'string'], 'ZipArchive::setExternalAttributesIndex' => ['bool', 'index'=>'int', 'opsys'=>'int', 'attr'=>'int', 'flags='=>'int'], 'ZipArchive::setExternalAttributesName' => ['bool', 'name'=>'string', 'opsys'=>'int', 'attr'=>'int', 'flags='=>'int'], 'ZipArchive::setPassword' => ['bool', 'password'=>'string'], 'ZipArchive::statIndex' => ['array|false', 'index'=>'int', 'flags='=>'int'], 'ZipArchive::statName' => ['array|false', 'filename'=>'string', 'flags='=>'int'], 'ZipArchive::unchangeAll' => ['bool'], 'ZipArchive::unchangeArchive' => ['bool'], 'ZipArchive::unchangeIndex' => ['bool', 'index'=>'int'], 'ZipArchive::unchangeName' => ['bool', 'name'=>'string'], 'zlib_decode' => ['string|false', 'data'=>'string', 'max_decoded_len='=>'int'], 'zlib_encode' => ['string|false', 'data'=>'string', 'encoding'=>'int', 'level='=>'string|int'], 'zlib_get_coding_type' => ['string|false'], 'ZMQ::__construct' => ['void'], 'ZMQContext::__construct' => ['void', 'io_threads='=>'int', 'is_persistent='=>'bool'], 'ZMQContext::getOpt' => ['mixed', 'key'=>'string'], 'ZMQContext::getSocket' => ['ZMQSocket', 'type'=>'int', 'persistent_id='=>'string', 'on_new_socket='=>'callable'], 'ZMQContext::isPersistent' => ['bool'], 'ZMQContext::setOpt' => ['ZMQContext', 'key'=>'int', 'value'=>'mixed'], 'ZMQDevice::__construct' => ['void', 'frontend'=>'ZMQSocket', 'backend'=>'ZMQSocket', 'listener='=>'ZMQSocket'], 'ZMQDevice::getIdleTimeout' => ['ZMQDevice'], 'ZMQDevice::getTimerTimeout' => ['ZMQDevice'], 'ZMQDevice::run' => ['void'], 'ZMQDevice::setIdleCallback' => ['ZMQDevice', 'cb_func'=>'callable', 'timeout'=>'int', 'user_data='=>'mixed'], 'ZMQDevice::setIdleTimeout' => ['ZMQDevice', 'timeout'=>'int'], 'ZMQDevice::setTimerCallback' => ['ZMQDevice', 'cb_func'=>'callable', 'timeout'=>'int', 'user_data='=>'mixed'], 'ZMQDevice::setTimerTimeout' => ['ZMQDevice', 'timeout'=>'int'], 'ZMQPoll::add' => ['string', 'entry'=>'mixed', 'type'=>'int'], 'ZMQPoll::clear' => ['ZMQPoll'], 'ZMQPoll::count' => ['0|positive-int'], 'ZMQPoll::getLastErrors' => ['array'], 'ZMQPoll::poll' => ['int', '&w_readable'=>'array', '&w_writable'=>'array', 'timeout='=>'int'], 'ZMQPoll::remove' => ['bool', 'item'=>'mixed'], 'ZMQSocket::__construct' => ['void', 'context'=>'ZMQContext', 'type'=>'int', 'persistent_id='=>'string', 'on_new_socket='=>'callable'], 'ZMQSocket::bind' => ['ZMQSocket', 'dsn'=>'string', 'force='=>'bool'], 'ZMQSocket::connect' => ['ZMQSocket', 'dsn'=>'string', 'force='=>'bool'], 'ZMQSocket::disconnect' => ['ZMQSocket', 'dsn'=>'string'], 'ZMQSocket::getEndpoints' => ['array'], 'ZMQSocket::getPersistentId' => ['string'], 'ZMQSocket::getSocketType' => ['int'], 'ZMQSocket::getSockOpt' => ['mixed', 'key'=>'string'], 'ZMQSocket::isPersistent' => ['bool'], 'ZMQSocket::recv' => ['string', 'mode='=>'int'], 'ZMQSocket::recvMulti' => ['string[]', 'mode='=>'int'], 'ZMQSocket::send' => ['ZMQSocket', 'message'=>'array', 'mode='=>'int'], 'ZMQSocket::send\'1' => ['ZMQSocket', 'message'=>'string', 'mode='=>'int'], 'ZMQSocket::sendmulti' => ['ZMQSocket', 'message'=>'array', 'mode='=>'int'], 'ZMQSocket::setSockOpt' => ['ZMQSocket', 'key'=>'int', 'value'=>'mixed'], 'ZMQSocket::unbind' => ['ZMQSocket', 'dsn'=>'string'], 'Zookeeper::addAuth' => ['bool', 'scheme'=>'string', 'cert'=>'string', 'completion_cb='=>'callable'], 'Zookeeper::connect' => ['void', 'host'=>'string', 'watcher_cb='=>'callable', 'recv_timeout='=>'int'], 'Zookeeper::create' => ['string', 'path'=>'string', 'value'=>'string', 'acls'=>'array', 'flags='=>'int'], 'Zookeeper::delete' => ['bool', 'path'=>'string', 'version='=>'int'], 'Zookeeper::exists' => ['bool', 'path'=>'string', 'watcher_cb='=>'callable'], 'Zookeeper::get' => ['string', 'path'=>'string', 'watcher_cb='=>'callable', 'stat='=>'array', 'max_size='=>'int'], 'Zookeeper::getAcl' => ['array', 'path'=>'string'], 'Zookeeper::getChildren' => ['array', 'path'=>'string', 'watcher_cb='=>'callable'], 'Zookeeper::getClientId' => ['int'], 'Zookeeper::getRecvTimeout' => ['int'], 'Zookeeper::getState' => ['int'], 'Zookeeper::isRecoverable' => ['bool'], 'Zookeeper::set' => ['bool', 'path'=>'string', 'value'=>'string', 'version='=>'int', 'stat='=>'array'], 'Zookeeper::setAcl' => ['bool', 'path'=>'string', 'version'=>'int', 'acl'=>'array'], 'Zookeeper::setDebugLevel' => ['bool', 'logLevel'=>'int'], 'Zookeeper::setDeterministicConnOrder' => ['bool', 'yesOrNo'=>'bool'], 'Zookeeper::setLogStream' => ['bool', 'stream'=>'resource'], 'Zookeeper::setWatcher' => ['bool', 'watcher_cb'=>'callable'], 'zookeeper_dispatch' => ['void'], ]; // // Hoa // // // @license // // New BSD License // // Copyright © 2007-2017, Hoa community. 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 Hoa 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 HOLDERS AND 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. // // Grammar \Hoa\Regex\Grammar. // // Provide grammar of PCRE (Perl Compatible Regular Expression)for the LL(k) // parser. More informations at http://pcre.org/pcre.txt, sections pcrepattern & // pcresyntax. // // @copyright Copyright © 2007-2017 Hoa community. // @license New BSD License // // Character classes. // tokens suffixed with "fc_" are the same as without such suffix but followed by "class:_class" %token negative_class_fc_ \[\^(?=\]) -> class_fc %token class_fc_ \[(?=\]) -> class_fc %token class_fc:_class \] -> class %token negative_class_ \[\^ -> class %token class_ \[ -> class %token class:posix_class \[:\^?[a-z]+:\] %token class:class_ \[ %token class:_class \] -> default %token class:range \- // taken over from literals but class:character has \b support on top (backspace in character classes) %token class:character \\([aefnrtb]|c[\x00-\x7f]) %token class:dynamic_character \\([0-7]{3}|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}) %token class:character_type \\([CdDhHNRsSvVwWX]|[pP]{[^}]+}) %token class:literal \\.|.|\n // Internal options. // See https://www.regular-expressions.info/refmodifiers.html // and https://www.php.net/manual/en/regexp.reference.internal-options.php %token internal_option \(\?[imsxnJUX^]*-?[imsxnJUX^]+\) // Lookahead and lookbehind assertions. %token lookahead_ \(\?= %token negative_lookahead_ \(\?! %token lookbehind_ \(\?<= %token negative_lookbehind_ \(\? nc %token absolute_reference_ \(\?\((?=\d) -> c %token relative_reference_ \(\?\((?=[\+\-]) -> c %token c:index [\+\-]?\d+ -> default %token assertion_reference_ \(\?\( // Comments. %token comment_ \(\?# -> co %token co:_comment \) -> default %token co:comment .*?(?=(? mark %token mark:name [^)]+ %token mark:_marker \) -> default // Capturing group. %token named_capturing_ \(\?P?< -> nc %token nc:_named_capturing > -> default %token nc:capturing_name .+?(?=(?) %token non_capturing_ \(\?: %token non_capturing_internal_option \(\?[imsxnJUX^]*-?[imsxnJUX^]+: %token non_capturing_reset_ \(\?\| %token atomic_group_ \(\?> %token capturing_ \( %token _capturing \) // Quantifiers (by default, greedy). %token zero_or_one_possessive \?\+ %token zero_or_one_lazy \?\? %token zero_or_one \? %token zero_or_more_possessive \*\+ %token zero_or_more_lazy \*\? %token zero_or_more \* %token one_or_more_possessive \+\+ %token one_or_more_lazy \+\? %token one_or_more \+ %token exactly_n \{[0-9]+\} %token n_to_m_possessive \{[0-9]+,[0-9]+\}\+ %token n_to_m_lazy \{[0-9]+,[0-9]+\}\? %token n_to_m \{[0-9]+,[0-9]+\} %token n_or_more_possessive \{[0-9]+,\}\+ %token n_or_more_lazy \{[0-9]+,\}\? %token n_or_more \{[0-9]+,\} // Alternation. %token alternation \| // Literal. %token character \\([aefnrt]|c[\x00-\x7f]) %token dynamic_character \\([0-7]{3}|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}) // Please, see PCRESYNTAX(3), General Category properties, PCRE special category // properties and script names for \p{} and \P{}. %token character_type \\([CdDhHNRsSvVwWX]|[pP]{[^}]+}) %token anchor \\([bBAZzG])|\^|\$ %token match_point_reset \\K %token literal \\.|.|\n // Rules. #expression: alternation() alternation: concatenation()? ( concatenation()? #alternation )* concatenation: ( internal_options() | assertion() | quantification() | condition() ) ( ( internal_options() | assertion() | quantification() | condition() ) #concatenation )* #internal_options: #condition: ( ::named_reference_:: ::_named_capturing:: #namedcondition | ( ::relative_reference_:: #relativecondition | ::absolute_reference_:: #absolutecondition ) | ::assertion_reference_:: alternation() #assertioncondition ) ::_capturing:: alternation() ::_capturing:: assertion: ( ::lookahead_:: #lookahead | ::negative_lookahead_:: #negativelookahead | ::lookbehind_:: #lookbehind | ::negative_lookbehind_:: #negativelookbehind ) alternation() ::_capturing:: quantification: ( class() | simple() ) ( quantifier() #quantification )? quantifier: | | | | | | | | | | | | | | | #class: ( ::negative_class_fc_:: #negativeclass <_class> | ::class_fc_:: <_class> | ::negative_class_:: #negativeclass | ::class_:: ) ? ( | | range() ? | literal() )* ? ::_class:: #range: literal() ::range:: literal() simple: capturing() | literal() #capturing: ::marker_:: ::_marker:: #mark | ::comment_:: ? ::_comment:: #comment | ( ::named_capturing_:: ::_named_capturing:: #namedcapturing | ::non_capturing_:: #noncapturing | non_capturing_internal_options() #noncapturing | ::non_capturing_reset_:: #noncapturingreset | ::atomic_group_:: #atomicgroup | ::capturing_:: ) alternation() ::_capturing:: non_capturing_internal_options: literal: | | | | | ['http_get_last_response_headers' => ['list|null'], 'http_clear_last_response_headers' => ['void'], 'mb_lcfirst' => ['string', 'string' => 'string', 'encoding=' => 'string'], 'mb_ucfirst' => ['string', 'string' => 'string', 'encoding=' => 'string']], 'old' => []]; [ 'array_combine' => ['associative-array', 'keys'=>'string[]|int[]', 'values'=>'array'], 'base64_decode' => ['string', 'string'=>'string', 'strict='=>'false'], 'base64_decode\'1' => ['string|false', 'string'=>'string', 'strict='=>'true'], 'bcdiv' => ['string', 'dividend'=>'string', 'divisor'=>'string', 'scale='=>'int'], 'bcmod' => ['string', 'dividend'=>'string', 'divisor'=>'string', 'scale='=>'int'], 'bcpowmod' => ['string', 'base'=>'string', 'exponent'=>'string', 'modulus'=>'string', 'scale='=>'int'], 'call_user_func_array' => ['mixed', 'function'=>'callable', 'parameters'=>'array'], 'ceil' => ['float', 'number'=>'float'], 'com_load_typelib' => ['bool', 'typelib_name'=>'string', 'case_insensitive='=>'true'], 'count_chars' => ['array|string', 'input'=>'string', 'mode='=>'int'], 'curl_init' => ['__benevolent', 'url='=>'string'], 'date_add' => ['DateTime', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_date_set' => ['DateTime', 'object'=>'DateTime', 'year'=>'int', 'month'=>'int', 'day'=>'int'], 'date_diff' => ['DateInterval', 'obj1'=>'DateTimeInterface', 'obj2'=>'DateTimeInterface', 'absolute='=>'bool'], 'date_format' => ['string', 'object'=>'DateTimeInterface', 'format'=>'string'], 'date_isodate_set' => ['DateTime', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'day='=>'int|mixed'], 'date_parse' => ['array', 'date'=>'string'], 'date_sub' => ['DateTime', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_sun_info' => ['array{sunrise: int|bool,sunset: int|bool,transit: int|bool,civil_twilight_begin: int|bool,civil_twilight_end: int|bool,nautical_twilight_begin: int|bool,nautical_twilight_end: int|bool,astronomical_twilight_begin: int|bool,astronomical_twilight_end: int|bool}', 'time'=>'int', 'latitude'=>'float', 'longitude'=>'float'], 'date_time_set' => ['DateTime', 'object'=>'DateTime', 'hour'=>'int', 'minute'=>'int', 'second='=>'int', 'microseconds='=>'int'], 'date_timestamp_set' => ['DateTime', 'object'=>'DateTime', 'unixtimestamp'=>'int'], 'date_timezone_set' => ['DateTime', 'object'=>'DateTime', 'timezone'=>'DateTimeZone'], 'explode' => ['list', 'separator'=>'non-empty-string', 'str'=>'string', 'limit='=>'int'], 'fdiv' => ['float', 'dividend'=>'float', 'divisor'=>'float'], 'floor' => ['float', 'number'=>'float'], 'forward_static_call_array' => ['mixed', 'function'=>'callable', 'parameters'=>'array'], 'get_debug_type' => ['string', 'var'=>'mixed'], 'get_resource_id' => ['int', 'res'=>'resource'], 'gmdate' => ['string', 'format'=>'string', 'timestamp='=>'int'], 'gmmktime' => ['int|false', 'hour'=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'hash' => ['non-falsy-string', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'], 'hash_hkdf' => ['non-falsy-string', 'algo'=>'string', 'key'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'], 'hash_hmac' => ['non-falsy-string', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'], 'hash_pbkdf2' => ['non-falsy-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'], 'imageaffine' => ['false|object', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'], 'imagecreate' => ['__benevolent', 'width'=>'int', 'height'=>'int'], 'imagecreatefrombmp' => ['false|object', 'filename'=>'string'], 'imagecreatefromgd' => ['false|object', 'filename'=>'string'], 'imagecreatefromgd2' => ['false|object', 'filename'=>'string'], 'imagecreatefromgd2part' => ['false|object', 'filename'=>'string', 'srcx'=>'int', 'srcy'=>'int', 'width'=>'int', 'height'=>'int'], 'imagecreatefromgif' => ['false|object', 'filename'=>'string'], 'imagecreatefromjpeg' => ['false|object', 'filename'=>'string'], 'imagecreatefrompng' => ['false|object', 'filename'=>'string'], 'imagecreatefromstring' => ['false|object', 'image'=>'string'], 'imagecreatefromwbmp' => ['false|object', 'filename'=>'string'], 'imagecreatefromwebp' => ['false|object', 'filename'=>'string'], 'imagecreatefromxbm' => ['false|object', 'filename'=>'string'], 'imagecreatefromxpm' => ['false|object', 'filename'=>'string'], 'imagecreatetruecolor' => ['__benevolent', 'width'=>'int', 'height'=>'int'], 'imagecrop' => ['false|object', 'im'=>'resource', 'rect'=>'array'], 'imagecropauto' => ['false|object', 'im'=>'resource', 'mode'=>'int', 'threshold'=>'float', 'color'=>'int'], 'imagegetclip' => ['array', 'im'=>'resource'], 'imagegrabscreen' => ['false|object'], 'imagegrabwindow' => ['false|object', 'window_handle'=>'int', 'client_area='=>'int'], 'imagejpeg' => ['bool', 'im'=>'GdImage', 'filename='=>'string|resource|null', 'quality='=>'int'], 'imagerotate' => ['false|object', 'src_im'=>'resource', 'angle'=>'float', 'bgdcolor'=>'int', 'ignoretransparent='=>'int'], 'imagescale' => ['false|object', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'], 'getenv' => ['string|false', 'varname'=>'string', 'local_only='=>'bool'], 'getenv\'1' => ['array', 'varname='=>'null', 'local_only='=>'bool'], 'ldap_set_rebind_proc' => ['bool', 'ldap'=>'resource', 'callback'=>'?callable'], 'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string'], 'mb_encoding_aliases' => ['list', 'encoding'=>'string'], 'mb_str_split' => ['list', 'str'=>'string', 'split_length='=>'positive-int', 'encoding='=>'string'], 'mb_strlen' => ['0|positive-int', 'str'=>'string', 'encoding='=>'string'], 'mktime' => ['int|false', 'hour'=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'odbc_exec' => ['resource|false', 'connection_id'=>'resource', 'query'=>'string'], 'parse_str' => ['void', 'encoded_string'=>'string', '&w_result'=>'array'], 'password_hash' => ['non-empty-string', 'password'=>'string', 'algo'=>'string|int|null', 'options='=>'array'], 'PDOStatement::fetchAll' => ['array', 'how='=>'int', 'fetch_argument='=>'int|string|callable', 'ctor_args='=>'?array'], 'PhpToken::tokenize' => ['list', 'code'=>'string', 'flags='=>'int'], 'PhpToken::is' => ['bool', 'kind'=>'string|int|string[]|int[]'], 'PhpToken::isIgnorable' => ['bool'], 'PhpToken::getTokenName' => ['non-falsy-string'], 'preg_match_all' => ['0|positive-int|false', 'pattern'=>'string', 'subject'=>'string', '&w_subpatterns='=>'array', 'flags='=>'int', 'offset='=>'int'], 'proc_get_status' => ['array{command: string, pid: int, running: bool, signaled: bool, stopped: bool, exitcode: int, termsig: int, stopsig: int}', 'process'=>'resource'], 'set_error_handler' => ['?callable', 'callback'=>'null|callable(int,string,string,int):bool', 'error_types='=>'int'], 'socket_addrinfo_lookup' => ['AddressInfo[]', 'node'=>'string', 'service='=>'mixed', 'hints='=>'array'], 'socket_select' => ['int|false', '&w_read'=>'Socket[]|null', '&w_write'=>'Socket[]|null', '&w_except'=>'Socket[]|null', 'seconds'=>'int|null', 'microseconds='=>'int'], 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => ['string|false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'spl_autoload_functions' => ['list'], 'str_contains' => ['bool', 'haystack'=>'string', 'needle'=>'string'], 'str_split' => ['non-empty-list', 'str'=>'string', 'split_length='=>'positive-int'], 'str_ends_with' => ['bool', 'haystack'=>'string', 'needle'=>'string'], 'str_starts_with' => ['bool', 'haystack'=>'string', 'needle'=>'string'], 'strchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'before_needle='=>'bool'], 'stripos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'before_needle='=>'bool'], 'strpos' => ['positive-int|0|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'strrchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string'], 'strripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string', 'offset='=>'int'], 'strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'before_needle='=>'bool'], 'substr' => ['string', 'string'=>'string', 'start'=>'int', 'length='=>'int'], 'round' => ['float', 'number'=>'float', 'precision='=>'int', 'mode='=>'1|2|3|4'], 'version_compare' => ['int|bool', 'version1'=>'string', 'version2'=>'string', 'operator='=>'string|null'], 'xml_parser_create' => ['XMLParser', 'encoding='=>'string'], 'xml_parser_create_ns' => ['XMLParser', 'encoding='=>'string', 'sep='=>'string'], 'xml_parser_free' => ['bool', 'parser'=>'XMLParser'], 'xml_parser_get_option' => ['mixed|false', 'parser'=>'XMLParser', 'option'=>'int'], 'xml_parser_set_option' => ['bool', 'parser'=>'XMLParser', 'option'=>'int', 'value'=>'mixed'], 'xmlwriter_end_attribute' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_cdata' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_comment' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_document' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_dtd' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_dtd_attlist' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_dtd_element' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_dtd_entity' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_element' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_end_pi' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_flush' => ['mixed', 'xmlwriter'=>'XMLWriter', 'empty='=>'bool'], 'xmlwriter_full_end_element' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_open_memory' => ['XMLWriter'], 'xmlwriter_open_uri' => ['XMLWriter', 'source'=>'string'], 'xmlwriter_output_memory' => ['string', 'xmlwriter'=>'XMLWriter', 'flush='=>'bool'], 'xmlwriter_set_indent' => ['bool', 'xmlwriter'=>'XMLWriter', 'indent'=>'bool'], 'xmlwriter_set_indent_string' => ['bool', 'xmlwriter'=>'XMLWriter', 'indentstring'=>'string'], 'xmlwriter_start_attribute' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string'], 'xmlwriter_start_attribute_ns' => ['bool', 'xmlwriter'=>'XMLWriter', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'xmlwriter_start_cdata' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_start_comment' => ['bool', 'xmlwriter'=>'XMLWriter'], 'xmlwriter_start_document' => ['bool', 'xmlwriter'=>'XMLWriter', 'version='=>'string', 'encoding='=>'string', 'standalone='=>'string'], 'xmlwriter_start_dtd' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string'], 'xmlwriter_start_dtd_attlist' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string'], 'xmlwriter_start_dtd_element' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string'], 'xmlwriter_start_dtd_entity' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'isparam'=>'bool'], 'xmlwriter_start_element' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string'], 'xmlwriter_start_element_ns' => ['bool', 'xmlwriter'=>'XMLWriter', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string|null'], 'xmlwriter_start_pi' => ['bool', 'xmlwriter'=>'XMLWriter', 'target'=>'string'], 'xmlwriter_text' => ['bool', 'xmlwriter'=>'XMLWriter', 'content'=>'string'], 'xmlwriter_write_attribute' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_attribute_ns' => ['bool', 'xmlwriter'=>'XMLWriter', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_cdata' => ['bool', 'xmlwriter'=>'XMLWriter', 'content'=>'string'], 'xmlwriter_write_comment' => ['bool', 'xmlwriter'=>'XMLWriter', 'content'=>'string'], 'xmlwriter_write_dtd' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string', 'subset='=>'string'], 'xmlwriter_write_dtd_attlist' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_element' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_entity' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string', 'pe'=>'bool', 'publicid'=>'string', 'sysid'=>'string', 'ndataid'=>'string'], 'xmlwriter_write_element' => ['bool', 'xmlwriter'=>'XMLWriter', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_element_ns' => ['bool', 'xmlwriter'=>'XMLWriter', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_pi' => ['bool', 'xmlwriter'=>'XMLWriter', 'target'=>'string', 'content'=>'string'], 'xmlwriter_write_raw' => ['bool', 'xmlwriter'=>'XMLWriter', 'content'=>'string'], ], 'old' => [ 'array_combine' => ['associative-array|false', 'keys'=>'string[]|int[]', 'values'=>'array'], 'bcdiv' => ['?string', 'dividend'=>'string', 'divisor'=>'string', 'scale='=>'int'], 'bcmod' => ['?string', 'dividend'=>'string', 'divisor'=>'string', 'scale='=>'int'], 'bcpowmod' => ['?string', 'base'=>'string', 'exponent'=>'string', 'modulus'=>'string', 'scale='=>'int'], 'ceil' => ['__benevolent', 'number'=>'float'], 'convert_cyr_string' => ['string', 'str'=>'string', 'from'=>'string', 'to'=>'string'], 'com_load_typelib' => ['bool', 'typelib_name'=>'string', 'case_insensitive='=>'bool'], 'count_chars' => ['array|false|string', 'input'=>'string', 'mode='=>'int'], 'curl_init' => ['__benevolent', 'url='=>'string'], 'date_add' => ['DateTime|false', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_date_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'month'=>'int', 'day'=>'int'], 'date_diff' => ['DateInterval|false', 'obj1'=>'DateTimeInterface', 'obj2'=>'DateTimeInterface', 'absolute='=>'bool'], 'date_format' => ['string|false', 'object'=>'DateTimeInterface', 'format'=>'string'], 'date_isodate_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'day='=>'int|mixed'], 'date_parse' => ['array|false', 'date'=>'string'], 'date_sub' => ['DateTime|false', 'object'=>'DateTime', 'interval'=>'DateInterval'], 'date_sun_info' => ['__benevolent', 'time'=>'int', 'latitude'=>'float', 'longitude'=>'float'], 'date_time_set' => ['DateTime|false', 'object'=>'DateTime', 'hour'=>'int', 'minute'=>'int', 'second='=>'int', 'microseconds='=>'int'], 'date_timestamp_set' => ['DateTime|false', 'object'=>'DateTime', 'unixtimestamp'=>'int'], 'date_timezone_set' => ['DateTime|false', 'object'=>'DateTime', 'timezone'=>'DateTimeZone'], 'each' => ['array{0:int|string,key:int|string,1:mixed,value:mixed}', '&r_arr'=>'array'], 'ezmlm_hash' => ['int', 'addr'=>'string'], 'fgetss' => ['string|false', 'fp'=>'resource', 'length='=>'0|positive-int', 'allowable_tags='=>'string'], 'floor' => ['__benevolent', 'number'=>'float'], 'get_magic_quotes_gpc' => ['false'], 'gmdate' => ['string|false', 'format'=>'string', 'timestamp='=>'int'], 'gmmktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'gmp_random' => ['GMP', 'limiter='=>'int'], 'gzgetss' => ['string|false', 'zp'=>'resource', 'length'=>'int', 'allowable_tags='=>'string'], 'hash' => ['non-falsy-string|false', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'], 'hash_hkdf' => ['non-falsy-string|false', 'algo'=>'string', 'key'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'], 'hash_hmac' => ['non-falsy-string|false', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'], 'hash_pbkdf2' => ['non-falsy-string|false', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'], 'hebrevc' => ['string', 'str'=>'string', 'max_chars_per_line='=>'int'], 'image2wbmp' => ['bool', 'im'=>'resource', 'filename='=>'?string', 'threshold='=>'int'], 'imageaffine' => ['resource|false', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'], 'imagecreate' => ['resource|false', 'x_size'=>'int', 'y_size'=>'int'], 'imagecreatefrombmp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd2' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd2part' => ['resource|false', 'filename'=>'string', 'srcx'=>'int', 'srcy'=>'int', 'width'=>'int', 'height'=>'int'], 'imagecreatefromgif' => ['resource|false', 'filename'=>'string'], 'imagecreatefromjpeg' => ['resource|false', 'filename'=>'string'], 'imagecreatefrompng' => ['resource|false', 'filename'=>'string'], 'imagecreatefromstring' => ['resource|false', 'image'=>'string'], 'imagecreatefromwbmp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromwebp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxbm' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxpm' => ['resource|false', 'filename'=>'string'], 'imagecreatetruecolor' => ['resource|false', 'x_size'=>'int', 'y_size'=>'int'], 'imagecrop' => ['resource|false', 'im'=>'resource', 'rect'=>'array'], 'imagecropauto' => ['resource|false', 'im'=>'resource', 'mode'=>'int', 'threshold'=>'float', 'color'=>'int'], 'imagegetclip' => ['array|false', 'im'=>'resource'], 'imagegrabscreen' => ['false|resource'], 'imagegrabwindow' => ['false|resource', 'window_handle'=>'int', 'client_area='=>'int'], 'imagejpeg' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null', 'quality='=>'int'], 'imagerotate' => ['resource|false', 'src_im'=>'resource', 'angle'=>'float', 'bgdcolor'=>'int', 'ignoretransparent='=>'int'], 'imagescale' => ['resource|false', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'], 'imap_header' => ['stdClass|false', 'stream_id'=>'resource', 'msg_no'=>'int', 'from_length='=>'int', 'subject_length='=>'int', 'default_host='=>'string'], 'implode\'1' => ['string', 'pieces'=>'array'], 'jpeg2wbmp' => ['bool', 'jpegname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'], 'ldap_control_paged_result' => ['bool', 'link_identifier'=>'resource', 'pagesize'=>'int', 'iscritical='=>'bool', 'cookie='=>'string'], 'ldap_control_paged_result_response' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', '&w_cookie='=>'string', '&w_estimated='=>'int'], 'ldap_set_rebind_proc' => ['bool', 'link_identifier'=>'resource', 'callback'=>'callable'], 'ldap_sort' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', 'sortfilter'=>'string'], 'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string', 'is_hex='=>'bool'], 'mb_strlen' => ['0|positive-int', 'str'=>'string', 'encoding='=>'string'], 'mktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'money_format' => ['string', 'format'=>'string', 'value'=>'float'], 'odbc_exec' => ['resource|false', 'connection_id'=>'resource', 'query'=>'string', 'flags='=>'int'], 'parse_str' => ['void', 'encoded_string'=>'string', '&w_result='=>'array'], 'password_hash' => ['__benevolent', 'password'=>'string', 'algo'=>'string|int', 'options='=>'array'], 'png2wbmp' => ['bool', 'pngname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'], 'proc_get_status' => ['array{command: string, pid: int, running: bool, signaled: bool, stopped: bool, exitcode: int, termsig: int, stopsig: int}|false', 'process'=>'resource'], 'read_exif_data' => ['array', 'filename'=>'string', 'sections_needed='=>'string', 'sub_arrays='=>'bool', 'read_thumbnail='=>'bool'], 'restore_include_path' => ['void'], 'round' => ['__benevolent', 'number'=>'float', 'precision='=>'int', 'mode='=>'1|2|3|4'], 'socket_select' => ['int|false', '&w_read_fds'=>'resource[]|null', '&w_write_fds'=>'resource[]|null', '&w_except_fds'=>'resource[]|null', 'tv_sec'=>'int|null', 'tv_usec='=>'int|null'], 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => ['?string|?false', 'confidential_message'=>'string', 'public_message'=>'string', 'nonce'=>'string', 'key'=>'string'], 'SplFileObject::fgetss' => ['string|false', 'allowable_tags='=>'string'], 'strchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string|int', 'before_needle='=>'bool'], 'stripos' => ['0|positive-int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'stristr' => ['string|false', 'haystack'=>'string', 'needle'=>'string|int', 'before_needle='=>'bool'], 'strpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strrchr' => ['string|false', 'haystack'=>'string', 'needle'=>'string|int'], 'strripos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strrpos' => ['int|false', 'haystack'=>'string', 'needle'=>'string|int', 'offset='=>'int'], 'strstr' => ['string|false', 'haystack'=>'string', 'needle'=>'string|int', 'before_needle='=>'bool'], 'substr' => ['__benevolent', 'string'=>'string', 'start'=>'int', 'length='=>'int'], 'version_compare' => ['int|bool', 'version1'=>'string', 'version2'=>'string', 'operator='=>'string|null'], 'xml_parser_create' => ['resource', 'encoding='=>'string'], 'xml_parser_create_ns' => ['resource', 'encoding='=>'string', 'sep='=>'string'], 'xml_parser_free' => ['bool', 'parser'=>'resource'], 'xml_parser_get_option' => ['mixed|false', 'parser'=>'resource', 'option'=>'int'], 'xml_parser_set_option' => ['bool', 'parser'=>'resource', 'option'=>'int', 'value'=>'mixed'], 'xmlwriter_end_attribute' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_cdata' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_comment' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_document' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_attlist' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_dtd_entity' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_end_pi' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_flush' => ['mixed', 'xmlwriter'=>'resource', 'empty='=>'bool'], 'xmlwriter_full_end_element' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_open_memory' => ['resource'], 'xmlwriter_open_uri' => ['resource', 'source'=>'string'], 'xmlwriter_output_memory' => ['string', 'xmlwriter'=>'resource', 'flush='=>'bool'], 'xmlwriter_set_indent' => ['bool', 'xmlwriter'=>'resource', 'indent'=>'bool'], 'xmlwriter_set_indent_string' => ['bool', 'xmlwriter'=>'resource', 'indentstring'=>'string'], 'xmlwriter_start_attribute' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_attribute_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string'], 'xmlwriter_start_cdata' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_start_comment' => ['bool', 'xmlwriter'=>'resource'], 'xmlwriter_start_document' => ['bool', 'xmlwriter'=>'resource', 'version='=>'string', 'encoding='=>'string', 'standalone='=>'string'], 'xmlwriter_start_dtd' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string'], 'xmlwriter_start_dtd_attlist' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_dtd_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_dtd_entity' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'isparam'=>'bool'], 'xmlwriter_start_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string'], 'xmlwriter_start_element_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string|null'], 'xmlwriter_start_pi' => ['bool', 'xmlwriter'=>'resource', 'target'=>'string'], 'xmlwriter_text' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_attribute' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_attribute_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_cdata' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_comment' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], 'xmlwriter_write_dtd' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'publicid='=>'string', 'sysid='=>'string', 'subset='=>'string'], 'xmlwriter_write_dtd_attlist' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_dtd_entity' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string', 'pe'=>'bool', 'publicid'=>'string', 'sysid'=>'string', 'ndataid'=>'string'], 'xmlwriter_write_element' => ['bool', 'xmlwriter'=>'resource', 'name'=>'string', 'content'=>'string'], 'xmlwriter_write_element_ns' => ['bool', 'xmlwriter'=>'resource', 'prefix'=>'string', 'name'=>'string', 'uri'=>'string', 'content'=>'string'], 'xmlwriter_write_pi' => ['bool', 'xmlwriter'=>'resource', 'target'=>'string', 'content'=>'string'], 'xmlwriter_write_raw' => ['bool', 'xmlwriter'=>'resource', 'content'=>'string'], ] ]; ['DateTime::modify' => ['static', 'modify' => 'string'], 'DateTimeImmutable::modify' => ['static', 'modify' => 'string'], 'str_decrement' => ['non-empty-string', 'string' => 'non-empty-string'], 'str_increment' => ['non-falsy-string', 'string' => 'non-empty-string'], 'gc_status' => ['array{running:bool,protected:bool,full:bool,runs:int,collected:int,threshold:int,buffer_size:int,roots:int,application_time:float,collector_time:float,destructor_time:float,free_time:float}'], 'stream_get_meta_data' => ['array{timed_out:bool,blocked:bool,eof:bool,unread_bytes:int,stream_type:string,wrapper_type:string,wrapper_data:mixed,mode:string,seekable:bool,uri:string,mediatype?:string,base64?:bool}', 'fp' => 'resource']], 'old' => []]; ['iterator_count' => ['0|positive-int', 'iterator' => 'iterable'], 'iterator_to_array' => ['array', 'iterator' => 'iterable', 'use_keys=' => 'bool'], 'str_split' => ['list', 'str' => 'string', 'split_length=' => 'positive-int']], 'old' => []]; ['error_log' => ['bool', 'message' => 'string', 'message_type=' => '0|1|3|4', 'destination=' => 'string', 'extra_headers=' => 'string'], 'filter_input' => ['mixed', 'type' => 'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'variable_name' => 'string', 'filter=' => 'int', 'options=' => 'array|int'], 'filter_input_array' => ['array|false|null', 'type' => 'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'definition=' => 'int|array', 'add_empty=' => 'bool'], 'hash_hkdf' => ['non-falsy-string', 'algo' => 'non-falsy-string', 'key' => 'string', 'length=' => '0|positive-int', 'info=' => 'string', 'salt=' => 'string'], 'hash_pbkdf2' => ['non-empty-string', 'algo' => 'non-falsy-string', 'password' => 'string', 'salt' => 'string', 'iterations' => 'positive-int', 'length=' => '0|positive-int', 'raw_output=' => 'bool'], 'imagecreate' => ['__benevolent', 'width' => 'int<1, max>', 'height' => 'int<1, max>'], 'imagecreatetruecolor' => ['__benevolent', 'width' => 'int<1, max>', 'height' => 'int<1, max>'], 'mb_detect_order' => ['bool|list', 'encoding_list=' => 'non-empty-list|non-falsy-string|null']], 'old' => []]; true as a modification to bin/functionMetadata_original.php. * 3) Contribute the #[Pure] functions without side effects to https://github.com/JetBrains/phpstorm-stubs * 4) Once the PR from 3) is merged, please update the package here and run ./bin/generate-function-metadata.php. */ return [ 'BackedEnum::from' => ['hasSideEffects' => false], 'BackedEnum::tryFrom' => ['hasSideEffects' => false], 'CURLFile::getFilename' => ['hasSideEffects' => false], 'CURLFile::getMimeType' => ['hasSideEffects' => false], 'CURLFile::getPostFilename' => ['hasSideEffects' => false], 'Cassandra\\Exception\\AlreadyExistsException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\AuthenticationException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\ConfigurationException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\DivideByZeroException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\DomainException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\ExecutionException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\InvalidArgumentException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\InvalidQueryException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\InvalidSyntaxException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\IsBootstrappingException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\LogicException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\OverloadedException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\ProtocolException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\RangeException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\ReadTimeoutException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\RuntimeException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\ServerException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\TimeoutException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\TruncateException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\UnauthorizedException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\UnavailableException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\UnpreparedException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\ValidationException::__construct' => ['hasSideEffects' => false], 'Cassandra\\Exception\\WriteTimeoutException::__construct' => ['hasSideEffects' => false], 'Closure::bind' => ['hasSideEffects' => false], 'Closure::bindTo' => ['hasSideEffects' => false], 'Collator::__construct' => ['hasSideEffects' => false], 'Collator::compare' => ['hasSideEffects' => false], 'Collator::getAttribute' => ['hasSideEffects' => false], 'Collator::getErrorCode' => ['hasSideEffects' => false], 'Collator::getErrorMessage' => ['hasSideEffects' => false], 'Collator::getLocale' => ['hasSideEffects' => false], 'Collator::getSortKey' => ['hasSideEffects' => false], 'Collator::getStrength' => ['hasSideEffects' => false], 'DateTime::add' => ['hasSideEffects' => true], 'DateTime::createFromFormat' => ['hasSideEffects' => false], 'DateTime::createFromImmutable' => ['hasSideEffects' => false], 'DateTime::diff' => ['hasSideEffects' => false], 'DateTime::format' => ['hasSideEffects' => false], 'DateTime::getLastErrors' => ['hasSideEffects' => false], 'DateTime::getOffset' => ['hasSideEffects' => false], 'DateTime::getTimestamp' => ['hasSideEffects' => false], 'DateTime::getTimezone' => ['hasSideEffects' => false], 'DateTime::modify' => ['hasSideEffects' => true], 'DateTime::setDate' => ['hasSideEffects' => true], 'DateTime::setISODate' => ['hasSideEffects' => true], 'DateTime::setTime' => ['hasSideEffects' => true], 'DateTime::setTimestamp' => ['hasSideEffects' => true], 'DateTime::setTimezone' => ['hasSideEffects' => true], 'DateTime::sub' => ['hasSideEffects' => true], 'DateTimeImmutable::add' => ['hasSideEffects' => false], 'DateTimeImmutable::createFromFormat' => ['hasSideEffects' => false], 'DateTimeImmutable::createFromMutable' => ['hasSideEffects' => false], 'DateTimeImmutable::diff' => ['hasSideEffects' => false], 'DateTimeImmutable::format' => ['hasSideEffects' => false], 'DateTimeImmutable::getLastErrors' => ['hasSideEffects' => false], 'DateTimeImmutable::getOffset' => ['hasSideEffects' => false], 'DateTimeImmutable::getTimestamp' => ['hasSideEffects' => false], 'DateTimeImmutable::getTimezone' => ['hasSideEffects' => false], 'DateTimeImmutable::modify' => ['hasSideEffects' => false], 'DateTimeImmutable::setDate' => ['hasSideEffects' => false], 'DateTimeImmutable::setISODate' => ['hasSideEffects' => false], 'DateTimeImmutable::setTime' => ['hasSideEffects' => false], 'DateTimeImmutable::setTimestamp' => ['hasSideEffects' => false], 'DateTimeImmutable::setTimezone' => ['hasSideEffects' => false], 'DateTimeImmutable::sub' => ['hasSideEffects' => false], 'Error::__construct' => ['hasSideEffects' => false], 'ErrorException::__construct' => ['hasSideEffects' => false], 'Event::__construct' => ['hasSideEffects' => false], 'EventBase::getFeatures' => ['hasSideEffects' => false], 'EventBase::getMethod' => ['hasSideEffects' => false], 'EventBase::getTimeOfDayCached' => ['hasSideEffects' => false], 'EventBase::gotExit' => ['hasSideEffects' => false], 'EventBase::gotStop' => ['hasSideEffects' => false], 'EventBuffer::__construct' => ['hasSideEffects' => false], 'EventBufferEvent::__construct' => ['hasSideEffects' => false], 'EventBufferEvent::getDnsErrorString' => ['hasSideEffects' => false], 'EventBufferEvent::getEnabled' => ['hasSideEffects' => false], 'EventBufferEvent::getInput' => ['hasSideEffects' => false], 'EventBufferEvent::getOutput' => ['hasSideEffects' => false], 'EventConfig::__construct' => ['hasSideEffects' => false], 'EventDnsBase::__construct' => ['hasSideEffects' => false], 'EventHttpConnection::__construct' => ['hasSideEffects' => false], 'EventHttpRequest::__construct' => ['hasSideEffects' => false], 'EventHttpRequest::getCommand' => ['hasSideEffects' => false], 'EventHttpRequest::getConnection' => ['hasSideEffects' => false], 'EventHttpRequest::getHost' => ['hasSideEffects' => false], 'EventHttpRequest::getInputBuffer' => ['hasSideEffects' => false], 'EventHttpRequest::getInputHeaders' => ['hasSideEffects' => false], 'EventHttpRequest::getOutputBuffer' => ['hasSideEffects' => false], 'EventHttpRequest::getOutputHeaders' => ['hasSideEffects' => false], 'EventHttpRequest::getResponseCode' => ['hasSideEffects' => false], 'EventHttpRequest::getUri' => ['hasSideEffects' => false], 'EventSslContext::__construct' => ['hasSideEffects' => false], 'Exception::__construct' => ['hasSideEffects' => false], 'Exception::getCode' => ['hasSideEffects' => false], 'Exception::getFile' => ['hasSideEffects' => false], 'Exception::getLine' => ['hasSideEffects' => false], 'Exception::getMessage' => ['hasSideEffects' => false], 'Exception::getPrevious' => ['hasSideEffects' => false], 'Exception::getTrace' => ['hasSideEffects' => false], 'Exception::getTraceAsString' => ['hasSideEffects' => false], 'Gmagick::getcopyright' => ['hasSideEffects' => false], 'Gmagick::getfilename' => ['hasSideEffects' => false], 'Gmagick::getimagebackgroundcolor' => ['hasSideEffects' => false], 'Gmagick::getimageblueprimary' => ['hasSideEffects' => false], 'Gmagick::getimagebordercolor' => ['hasSideEffects' => false], 'Gmagick::getimagechanneldepth' => ['hasSideEffects' => false], 'Gmagick::getimagecolors' => ['hasSideEffects' => false], 'Gmagick::getimagecolorspace' => ['hasSideEffects' => false], 'Gmagick::getimagecompose' => ['hasSideEffects' => false], 'Gmagick::getimagedelay' => ['hasSideEffects' => false], 'Gmagick::getimagedepth' => ['hasSideEffects' => false], 'Gmagick::getimagedispose' => ['hasSideEffects' => false], 'Gmagick::getimageextrema' => ['hasSideEffects' => false], 'Gmagick::getimagefilename' => ['hasSideEffects' => false], 'Gmagick::getimageformat' => ['hasSideEffects' => false], 'Gmagick::getimagegamma' => ['hasSideEffects' => false], 'Gmagick::getimagegreenprimary' => ['hasSideEffects' => false], 'Gmagick::getimageheight' => ['hasSideEffects' => false], 'Gmagick::getimagehistogram' => ['hasSideEffects' => false], 'Gmagick::getimageindex' => ['hasSideEffects' => false], 'Gmagick::getimageinterlacescheme' => ['hasSideEffects' => false], 'Gmagick::getimageiterations' => ['hasSideEffects' => false], 'Gmagick::getimagematte' => ['hasSideEffects' => false], 'Gmagick::getimagemattecolor' => ['hasSideEffects' => false], 'Gmagick::getimageprofile' => ['hasSideEffects' => false], 'Gmagick::getimageredprimary' => ['hasSideEffects' => false], 'Gmagick::getimagerenderingintent' => ['hasSideEffects' => false], 'Gmagick::getimageresolution' => ['hasSideEffects' => false], 'Gmagick::getimagescene' => ['hasSideEffects' => false], 'Gmagick::getimagesignature' => ['hasSideEffects' => false], 'Gmagick::getimagetype' => ['hasSideEffects' => false], 'Gmagick::getimageunits' => ['hasSideEffects' => false], 'Gmagick::getimagewhitepoint' => ['hasSideEffects' => false], 'Gmagick::getimagewidth' => ['hasSideEffects' => false], 'Gmagick::getpackagename' => ['hasSideEffects' => false], 'Gmagick::getquantumdepth' => ['hasSideEffects' => false], 'Gmagick::getreleasedate' => ['hasSideEffects' => false], 'Gmagick::getsamplingfactors' => ['hasSideEffects' => false], 'Gmagick::getsize' => ['hasSideEffects' => false], 'Gmagick::getversion' => ['hasSideEffects' => false], 'GmagickDraw::getfillcolor' => ['hasSideEffects' => false], 'GmagickDraw::getfillopacity' => ['hasSideEffects' => false], 'GmagickDraw::getfont' => ['hasSideEffects' => false], 'GmagickDraw::getfontsize' => ['hasSideEffects' => false], 'GmagickDraw::getfontstyle' => ['hasSideEffects' => false], 'GmagickDraw::getfontweight' => ['hasSideEffects' => false], 'GmagickDraw::getstrokecolor' => ['hasSideEffects' => false], 'GmagickDraw::getstrokeopacity' => ['hasSideEffects' => false], 'GmagickDraw::getstrokewidth' => ['hasSideEffects' => false], 'GmagickDraw::gettextdecoration' => ['hasSideEffects' => false], 'GmagickDraw::gettextencoding' => ['hasSideEffects' => false], 'GmagickPixel::getcolor' => ['hasSideEffects' => false], 'GmagickPixel::getcolorcount' => ['hasSideEffects' => false], 'GmagickPixel::getcolorvalue' => ['hasSideEffects' => false], 'HttpMessage::getBody' => ['hasSideEffects' => false], 'HttpMessage::getHeader' => ['hasSideEffects' => false], 'HttpMessage::getHeaders' => ['hasSideEffects' => false], 'HttpMessage::getHttpVersion' => ['hasSideEffects' => false], 'HttpMessage::getInfo' => ['hasSideEffects' => false], 'HttpMessage::getParentMessage' => ['hasSideEffects' => false], 'HttpMessage::getRequestMethod' => ['hasSideEffects' => false], 'HttpMessage::getRequestUrl' => ['hasSideEffects' => false], 'HttpMessage::getResponseCode' => ['hasSideEffects' => false], 'HttpMessage::getResponseStatus' => ['hasSideEffects' => false], 'HttpMessage::getType' => ['hasSideEffects' => false], 'HttpQueryString::get' => ['hasSideEffects' => false], 'HttpQueryString::getArray' => ['hasSideEffects' => false], 'HttpQueryString::getBool' => ['hasSideEffects' => false], 'HttpQueryString::getFloat' => ['hasSideEffects' => false], 'HttpQueryString::getInt' => ['hasSideEffects' => false], 'HttpQueryString::getObject' => ['hasSideEffects' => false], 'HttpQueryString::getString' => ['hasSideEffects' => false], 'HttpRequest::getBody' => ['hasSideEffects' => false], 'HttpRequest::getContentType' => ['hasSideEffects' => false], 'HttpRequest::getCookies' => ['hasSideEffects' => false], 'HttpRequest::getHeaders' => ['hasSideEffects' => false], 'HttpRequest::getHistory' => ['hasSideEffects' => false], 'HttpRequest::getMethod' => ['hasSideEffects' => false], 'HttpRequest::getOptions' => ['hasSideEffects' => false], 'HttpRequest::getPostFields' => ['hasSideEffects' => false], 'HttpRequest::getPostFiles' => ['hasSideEffects' => false], 'HttpRequest::getPutData' => ['hasSideEffects' => false], 'HttpRequest::getPutFile' => ['hasSideEffects' => false], 'HttpRequest::getQueryData' => ['hasSideEffects' => false], 'HttpRequest::getRawPostData' => ['hasSideEffects' => false], 'HttpRequest::getRawRequestMessage' => ['hasSideEffects' => false], 'HttpRequest::getRawResponseMessage' => ['hasSideEffects' => false], 'HttpRequest::getRequestMessage' => ['hasSideEffects' => false], 'HttpRequest::getResponseBody' => ['hasSideEffects' => false], 'HttpRequest::getResponseCode' => ['hasSideEffects' => false], 'HttpRequest::getResponseCookies' => ['hasSideEffects' => false], 'HttpRequest::getResponseData' => ['hasSideEffects' => false], 'HttpRequest::getResponseHeader' => ['hasSideEffects' => false], 'HttpRequest::getResponseInfo' => ['hasSideEffects' => false], 'HttpRequest::getResponseMessage' => ['hasSideEffects' => false], 'HttpRequest::getResponseStatus' => ['hasSideEffects' => false], 'HttpRequest::getSslOptions' => ['hasSideEffects' => false], 'HttpRequest::getUrl' => ['hasSideEffects' => false], 'HttpRequestPool::getAttachedRequests' => ['hasSideEffects' => false], 'HttpRequestPool::getFinishedRequests' => ['hasSideEffects' => false], 'Imagick::getColorspace' => ['hasSideEffects' => false], 'Imagick::getCompression' => ['hasSideEffects' => false], 'Imagick::getCompressionQuality' => ['hasSideEffects' => false], 'Imagick::getConfigureOptions' => ['hasSideEffects' => false], 'Imagick::getFeatures' => ['hasSideEffects' => false], 'Imagick::getFilename' => ['hasSideEffects' => false], 'Imagick::getFont' => ['hasSideEffects' => false], 'Imagick::getFormat' => ['hasSideEffects' => false], 'Imagick::getGravity' => ['hasSideEffects' => false], 'Imagick::getHDRIEnabled' => ['hasSideEffects' => false], 'Imagick::getImage' => ['hasSideEffects' => false], 'Imagick::getImageAlphaChannel' => ['hasSideEffects' => false], 'Imagick::getImageArtifact' => ['hasSideEffects' => false], 'Imagick::getImageAttribute' => ['hasSideEffects' => false], 'Imagick::getImageBackgroundColor' => ['hasSideEffects' => false], 'Imagick::getImageBlob' => ['hasSideEffects' => false], 'Imagick::getImageBluePrimary' => ['hasSideEffects' => false], 'Imagick::getImageBorderColor' => ['hasSideEffects' => false], 'Imagick::getImageChannelDepth' => ['hasSideEffects' => false], 'Imagick::getImageChannelDistortion' => ['hasSideEffects' => false], 'Imagick::getImageChannelDistortions' => ['hasSideEffects' => false], 'Imagick::getImageChannelExtrema' => ['hasSideEffects' => false], 'Imagick::getImageChannelKurtosis' => ['hasSideEffects' => false], 'Imagick::getImageChannelMean' => ['hasSideEffects' => false], 'Imagick::getImageChannelRange' => ['hasSideEffects' => false], 'Imagick::getImageChannelStatistics' => ['hasSideEffects' => false], 'Imagick::getImageClipMask' => ['hasSideEffects' => false], 'Imagick::getImageColormapColor' => ['hasSideEffects' => false], 'Imagick::getImageColors' => ['hasSideEffects' => false], 'Imagick::getImageColorspace' => ['hasSideEffects' => false], 'Imagick::getImageCompose' => ['hasSideEffects' => false], 'Imagick::getImageCompression' => ['hasSideEffects' => false], 'Imagick::getImageCompressionQuality' => ['hasSideEffects' => false], 'Imagick::getImageDelay' => ['hasSideEffects' => false], 'Imagick::getImageDepth' => ['hasSideEffects' => false], 'Imagick::getImageDispose' => ['hasSideEffects' => false], 'Imagick::getImageDistortion' => ['hasSideEffects' => false], 'Imagick::getImageExtrema' => ['hasSideEffects' => false], 'Imagick::getImageFilename' => ['hasSideEffects' => false], 'Imagick::getImageFormat' => ['hasSideEffects' => false], 'Imagick::getImageGamma' => ['hasSideEffects' => false], 'Imagick::getImageGeometry' => ['hasSideEffects' => false], 'Imagick::getImageGravity' => ['hasSideEffects' => false], 'Imagick::getImageGreenPrimary' => ['hasSideEffects' => false], 'Imagick::getImageHeight' => ['hasSideEffects' => false], 'Imagick::getImageHistogram' => ['hasSideEffects' => false], 'Imagick::getImageIndex' => ['hasSideEffects' => false], 'Imagick::getImageInterlaceScheme' => ['hasSideEffects' => false], 'Imagick::getImageInterpolateMethod' => ['hasSideEffects' => false], 'Imagick::getImageIterations' => ['hasSideEffects' => false], 'Imagick::getImageLength' => ['hasSideEffects' => false], 'Imagick::getImageMatte' => ['hasSideEffects' => false], 'Imagick::getImageMatteColor' => ['hasSideEffects' => false], 'Imagick::getImageMimeType' => ['hasSideEffects' => false], 'Imagick::getImageOrientation' => ['hasSideEffects' => false], 'Imagick::getImagePage' => ['hasSideEffects' => false], 'Imagick::getImagePixelColor' => ['hasSideEffects' => false], 'Imagick::getImageProfile' => ['hasSideEffects' => false], 'Imagick::getImageProfiles' => ['hasSideEffects' => false], 'Imagick::getImageProperties' => ['hasSideEffects' => false], 'Imagick::getImageProperty' => ['hasSideEffects' => false], 'Imagick::getImageRedPrimary' => ['hasSideEffects' => false], 'Imagick::getImageRegion' => ['hasSideEffects' => false], 'Imagick::getImageRenderingIntent' => ['hasSideEffects' => false], 'Imagick::getImageResolution' => ['hasSideEffects' => false], 'Imagick::getImageScene' => ['hasSideEffects' => false], 'Imagick::getImageSignature' => ['hasSideEffects' => false], 'Imagick::getImageSize' => ['hasSideEffects' => false], 'Imagick::getImageTicksPerSecond' => ['hasSideEffects' => false], 'Imagick::getImageTotalInkDensity' => ['hasSideEffects' => false], 'Imagick::getImageType' => ['hasSideEffects' => false], 'Imagick::getImageUnits' => ['hasSideEffects' => false], 'Imagick::getImageVirtualPixelMethod' => ['hasSideEffects' => false], 'Imagick::getImageWhitePoint' => ['hasSideEffects' => false], 'Imagick::getImageWidth' => ['hasSideEffects' => false], 'Imagick::getImagesBlob' => ['hasSideEffects' => false], 'Imagick::getInterlaceScheme' => ['hasSideEffects' => false], 'Imagick::getIteratorIndex' => ['hasSideEffects' => false], 'Imagick::getNumberImages' => ['hasSideEffects' => false], 'Imagick::getOption' => ['hasSideEffects' => false], 'Imagick::getPage' => ['hasSideEffects' => false], 'Imagick::getPixelIterator' => ['hasSideEffects' => false], 'Imagick::getPixelRegionIterator' => ['hasSideEffects' => false], 'Imagick::getPointSize' => ['hasSideEffects' => false], 'Imagick::getSamplingFactors' => ['hasSideEffects' => false], 'Imagick::getSize' => ['hasSideEffects' => false], 'Imagick::getSizeOffset' => ['hasSideEffects' => false], 'ImagickDraw::getBorderColor' => ['hasSideEffects' => false], 'ImagickDraw::getClipPath' => ['hasSideEffects' => false], 'ImagickDraw::getClipRule' => ['hasSideEffects' => false], 'ImagickDraw::getClipUnits' => ['hasSideEffects' => false], 'ImagickDraw::getDensity' => ['hasSideEffects' => false], 'ImagickDraw::getFillColor' => ['hasSideEffects' => false], 'ImagickDraw::getFillOpacity' => ['hasSideEffects' => false], 'ImagickDraw::getFillRule' => ['hasSideEffects' => false], 'ImagickDraw::getFont' => ['hasSideEffects' => false], 'ImagickDraw::getFontFamily' => ['hasSideEffects' => false], 'ImagickDraw::getFontResolution' => ['hasSideEffects' => false], 'ImagickDraw::getFontSize' => ['hasSideEffects' => false], 'ImagickDraw::getFontStretch' => ['hasSideEffects' => false], 'ImagickDraw::getFontStyle' => ['hasSideEffects' => false], 'ImagickDraw::getFontWeight' => ['hasSideEffects' => false], 'ImagickDraw::getGravity' => ['hasSideEffects' => false], 'ImagickDraw::getOpacity' => ['hasSideEffects' => false], 'ImagickDraw::getStrokeAntialias' => ['hasSideEffects' => false], 'ImagickDraw::getStrokeColor' => ['hasSideEffects' => false], 'ImagickDraw::getStrokeDashArray' => ['hasSideEffects' => false], 'ImagickDraw::getStrokeDashOffset' => ['hasSideEffects' => false], 'ImagickDraw::getStrokeLineCap' => ['hasSideEffects' => false], 'ImagickDraw::getStrokeLineJoin' => ['hasSideEffects' => false], 'ImagickDraw::getStrokeMiterLimit' => ['hasSideEffects' => false], 'ImagickDraw::getStrokeOpacity' => ['hasSideEffects' => false], 'ImagickDraw::getStrokeWidth' => ['hasSideEffects' => false], 'ImagickDraw::getTextAlignment' => ['hasSideEffects' => false], 'ImagickDraw::getTextAntialias' => ['hasSideEffects' => false], 'ImagickDraw::getTextDecoration' => ['hasSideEffects' => false], 'ImagickDraw::getTextDirection' => ['hasSideEffects' => false], 'ImagickDraw::getTextEncoding' => ['hasSideEffects' => false], 'ImagickDraw::getTextInterLineSpacing' => ['hasSideEffects' => false], 'ImagickDraw::getTextInterWordSpacing' => ['hasSideEffects' => false], 'ImagickDraw::getTextKerning' => ['hasSideEffects' => false], 'ImagickDraw::getTextUnderColor' => ['hasSideEffects' => false], 'ImagickDraw::getVectorGraphics' => ['hasSideEffects' => false], 'ImagickKernel::getMatrix' => ['hasSideEffects' => false], 'ImagickPixel::getColor' => ['hasSideEffects' => false], 'ImagickPixel::getColorAsString' => ['hasSideEffects' => false], 'ImagickPixel::getColorCount' => ['hasSideEffects' => false], 'ImagickPixel::getColorQuantum' => ['hasSideEffects' => false], 'ImagickPixel::getColorValue' => ['hasSideEffects' => false], 'ImagickPixel::getColorValueQuantum' => ['hasSideEffects' => false], 'ImagickPixel::getHSL' => ['hasSideEffects' => false], 'ImagickPixel::getIndex' => ['hasSideEffects' => false], 'ImagickPixelIterator::getCurrentIteratorRow' => ['hasSideEffects' => false], 'ImagickPixelIterator::getIteratorRow' => ['hasSideEffects' => false], 'ImagickPixelIterator::getNextIteratorRow' => ['hasSideEffects' => false], 'ImagickPixelIterator::getPreviousIteratorRow' => ['hasSideEffects' => false], 'IntBackedEnum::from' => ['hasSideEffects' => false], 'IntBackedEnum::tryFrom' => ['hasSideEffects' => false], 'IntlBreakIterator::current' => ['hasSideEffects' => false], 'IntlBreakIterator::getErrorCode' => ['hasSideEffects' => false], 'IntlBreakIterator::getErrorMessage' => ['hasSideEffects' => false], 'IntlBreakIterator::getIterator' => ['hasSideEffects' => false], 'IntlBreakIterator::getLocale' => ['hasSideEffects' => false], 'IntlBreakIterator::getPartsIterator' => ['hasSideEffects' => false], 'IntlBreakIterator::getText' => ['hasSideEffects' => false], 'IntlBreakIterator::isBoundary' => ['hasSideEffects' => false], 'IntlCalendar::after' => ['hasSideEffects' => false], 'IntlCalendar::before' => ['hasSideEffects' => false], 'IntlCalendar::equals' => ['hasSideEffects' => false], 'IntlCalendar::fieldDifference' => ['hasSideEffects' => false], 'IntlCalendar::get' => ['hasSideEffects' => false], 'IntlCalendar::getActualMaximum' => ['hasSideEffects' => false], 'IntlCalendar::getActualMinimum' => ['hasSideEffects' => false], 'IntlCalendar::getDayOfWeekType' => ['hasSideEffects' => false], 'IntlCalendar::getErrorCode' => ['hasSideEffects' => false], 'IntlCalendar::getErrorMessage' => ['hasSideEffects' => false], 'IntlCalendar::getFirstDayOfWeek' => ['hasSideEffects' => false], 'IntlCalendar::getGreatestMinimum' => ['hasSideEffects' => false], 'IntlCalendar::getLeastMaximum' => ['hasSideEffects' => false], 'IntlCalendar::getLocale' => ['hasSideEffects' => false], 'IntlCalendar::getMaximum' => ['hasSideEffects' => false], 'IntlCalendar::getMinimalDaysInFirstWeek' => ['hasSideEffects' => false], 'IntlCalendar::getMinimum' => ['hasSideEffects' => false], 'IntlCalendar::getRepeatedWallTimeOption' => ['hasSideEffects' => false], 'IntlCalendar::getSkippedWallTimeOption' => ['hasSideEffects' => false], 'IntlCalendar::getTime' => ['hasSideEffects' => false], 'IntlCalendar::getTimeZone' => ['hasSideEffects' => false], 'IntlCalendar::getType' => ['hasSideEffects' => false], 'IntlCalendar::getWeekendTransition' => ['hasSideEffects' => false], 'IntlCalendar::inDaylightTime' => ['hasSideEffects' => false], 'IntlCalendar::isEquivalentTo' => ['hasSideEffects' => false], 'IntlCalendar::isLenient' => ['hasSideEffects' => false], 'IntlCalendar::isWeekend' => ['hasSideEffects' => false], 'IntlCalendar::toDateTime' => ['hasSideEffects' => false], 'IntlChar::hasBinaryProperty' => ['hasSideEffects' => false], 'IntlCodePointBreakIterator::getLastCodePoint' => ['hasSideEffects' => false], 'IntlDateFormatter::__construct' => ['hasSideEffects' => false], 'IntlDateFormatter::getCalendar' => ['hasSideEffects' => false], 'IntlDateFormatter::getCalendarObject' => ['hasSideEffects' => false], 'IntlDateFormatter::getDateType' => ['hasSideEffects' => false], 'IntlDateFormatter::getErrorCode' => ['hasSideEffects' => false], 'IntlDateFormatter::getErrorMessage' => ['hasSideEffects' => false], 'IntlDateFormatter::getLocale' => ['hasSideEffects' => false], 'IntlDateFormatter::getPattern' => ['hasSideEffects' => false], 'IntlDateFormatter::getTimeType' => ['hasSideEffects' => false], 'IntlDateFormatter::getTimeZone' => ['hasSideEffects' => false], 'IntlDateFormatter::getTimeZoneId' => ['hasSideEffects' => false], 'IntlDateFormatter::isLenient' => ['hasSideEffects' => false], 'IntlGregorianCalendar::getGregorianChange' => ['hasSideEffects' => false], 'IntlGregorianCalendar::isLeapYear' => ['hasSideEffects' => false], 'IntlPartsIterator::getBreakIterator' => ['hasSideEffects' => false], 'IntlRuleBasedBreakIterator::__construct' => ['hasSideEffects' => false], 'IntlRuleBasedBreakIterator::getBinaryRules' => ['hasSideEffects' => false], 'IntlRuleBasedBreakIterator::getRuleStatus' => ['hasSideEffects' => false], 'IntlRuleBasedBreakIterator::getRuleStatusVec' => ['hasSideEffects' => false], 'IntlRuleBasedBreakIterator::getRules' => ['hasSideEffects' => false], 'IntlTimeZone::getDSTSavings' => ['hasSideEffects' => false], 'IntlTimeZone::getDisplayName' => ['hasSideEffects' => false], 'IntlTimeZone::getErrorCode' => ['hasSideEffects' => false], 'IntlTimeZone::getErrorMessage' => ['hasSideEffects' => false], 'IntlTimeZone::getID' => ['hasSideEffects' => false], 'IntlTimeZone::getRawOffset' => ['hasSideEffects' => false], 'IntlTimeZone::hasSameRules' => ['hasSideEffects' => false], 'IntlTimeZone::toDateTimeZone' => ['hasSideEffects' => false], 'JsonIncrementalParser::__construct' => ['hasSideEffects' => false], 'JsonIncrementalParser::get' => ['hasSideEffects' => false], 'JsonIncrementalParser::getError' => ['hasSideEffects' => false], 'MemcachedException::__construct' => ['hasSideEffects' => false], 'MessageFormatter::__construct' => ['hasSideEffects' => false], 'MessageFormatter::format' => ['hasSideEffects' => false], 'MessageFormatter::getErrorCode' => ['hasSideEffects' => false], 'MessageFormatter::getErrorMessage' => ['hasSideEffects' => false], 'MessageFormatter::getLocale' => ['hasSideEffects' => false], 'MessageFormatter::getPattern' => ['hasSideEffects' => false], 'MessageFormatter::parse' => ['hasSideEffects' => false], 'NumberFormatter::__construct' => ['hasSideEffects' => false], 'NumberFormatter::format' => ['hasSideEffects' => false], 'NumberFormatter::formatCurrency' => ['hasSideEffects' => false], 'NumberFormatter::getAttribute' => ['hasSideEffects' => false], 'NumberFormatter::getErrorCode' => ['hasSideEffects' => false], 'NumberFormatter::getErrorMessage' => ['hasSideEffects' => false], 'NumberFormatter::getLocale' => ['hasSideEffects' => false], 'NumberFormatter::getPattern' => ['hasSideEffects' => false], 'NumberFormatter::getSymbol' => ['hasSideEffects' => false], 'NumberFormatter::getTextAttribute' => ['hasSideEffects' => false], 'ReflectionAttribute::getArguments' => ['hasSideEffects' => false], 'ReflectionAttribute::getName' => ['hasSideEffects' => false], 'ReflectionAttribute::getTarget' => ['hasSideEffects' => false], 'ReflectionAttribute::isRepeated' => ['hasSideEffects' => false], 'ReflectionClass::getAttributes' => ['hasSideEffects' => false], 'ReflectionClass::getConstant' => ['hasSideEffects' => false], 'ReflectionClass::getConstants' => ['hasSideEffects' => false], 'ReflectionClass::getConstructor' => ['hasSideEffects' => false], 'ReflectionClass::getDefaultProperties' => ['hasSideEffects' => false], 'ReflectionClass::getDocComment' => ['hasSideEffects' => false], 'ReflectionClass::getEndLine' => ['hasSideEffects' => false], 'ReflectionClass::getExtension' => ['hasSideEffects' => false], 'ReflectionClass::getExtensionName' => ['hasSideEffects' => false], 'ReflectionClass::getFileName' => ['hasSideEffects' => false], 'ReflectionClass::getInterfaceNames' => ['hasSideEffects' => false], 'ReflectionClass::getInterfaces' => ['hasSideEffects' => false], 'ReflectionClass::getMethod' => ['hasSideEffects' => false], 'ReflectionClass::getMethods' => ['hasSideEffects' => false], 'ReflectionClass::getModifiers' => ['hasSideEffects' => false], 'ReflectionClass::getName' => ['hasSideEffects' => false], 'ReflectionClass::getNamespaceName' => ['hasSideEffects' => false], 'ReflectionClass::getParentClass' => ['hasSideEffects' => false], 'ReflectionClass::getProperties' => ['hasSideEffects' => false], 'ReflectionClass::getProperty' => ['hasSideEffects' => false], 'ReflectionClass::getReflectionConstant' => ['hasSideEffects' => false], 'ReflectionClass::getReflectionConstants' => ['hasSideEffects' => false], 'ReflectionClass::getShortName' => ['hasSideEffects' => false], 'ReflectionClass::getStartLine' => ['hasSideEffects' => false], 'ReflectionClass::getStaticProperties' => ['hasSideEffects' => false], 'ReflectionClass::getStaticPropertyValue' => ['hasSideEffects' => false], 'ReflectionClass::getTraitAliases' => ['hasSideEffects' => false], 'ReflectionClass::getTraitNames' => ['hasSideEffects' => false], 'ReflectionClass::getTraits' => ['hasSideEffects' => false], 'ReflectionClass::isAbstract' => ['hasSideEffects' => false], 'ReflectionClass::isAnonymous' => ['hasSideEffects' => false], 'ReflectionClass::isCloneable' => ['hasSideEffects' => false], 'ReflectionClass::isFinal' => ['hasSideEffects' => false], 'ReflectionClass::isInstance' => ['hasSideEffects' => false], 'ReflectionClass::isInstantiable' => ['hasSideEffects' => false], 'ReflectionClass::isInterface' => ['hasSideEffects' => false], 'ReflectionClass::isInternal' => ['hasSideEffects' => false], 'ReflectionClass::isIterable' => ['hasSideEffects' => false], 'ReflectionClass::isIterateable' => ['hasSideEffects' => false], 'ReflectionClass::isReadOnly' => ['hasSideEffects' => false], 'ReflectionClass::isSubclassOf' => ['hasSideEffects' => false], 'ReflectionClass::isTrait' => ['hasSideEffects' => false], 'ReflectionClass::isUserDefined' => ['hasSideEffects' => false], 'ReflectionClassConstant::getAttributes' => ['hasSideEffects' => false], 'ReflectionClassConstant::getDeclaringClass' => ['hasSideEffects' => false], 'ReflectionClassConstant::getDocComment' => ['hasSideEffects' => false], 'ReflectionClassConstant::getModifiers' => ['hasSideEffects' => false], 'ReflectionClassConstant::getName' => ['hasSideEffects' => false], 'ReflectionClassConstant::getValue' => ['hasSideEffects' => false], 'ReflectionClassConstant::isPrivate' => ['hasSideEffects' => false], 'ReflectionClassConstant::isProtected' => ['hasSideEffects' => false], 'ReflectionClassConstant::isPublic' => ['hasSideEffects' => false], 'ReflectionEnumBackedCase::getBackingValue' => ['hasSideEffects' => false], 'ReflectionEnumUnitCase::getEnum' => ['hasSideEffects' => false], 'ReflectionEnumUnitCase::getValue' => ['hasSideEffects' => false], 'ReflectionExtension::getClassNames' => ['hasSideEffects' => false], 'ReflectionExtension::getClasses' => ['hasSideEffects' => false], 'ReflectionExtension::getConstants' => ['hasSideEffects' => false], 'ReflectionExtension::getDependencies' => ['hasSideEffects' => false], 'ReflectionExtension::getFunctions' => ['hasSideEffects' => false], 'ReflectionExtension::getINIEntries' => ['hasSideEffects' => false], 'ReflectionExtension::getName' => ['hasSideEffects' => false], 'ReflectionExtension::getVersion' => ['hasSideEffects' => false], 'ReflectionExtension::isPersistent' => ['hasSideEffects' => false], 'ReflectionExtension::isTemporary' => ['hasSideEffects' => false], 'ReflectionFunction::getClosure' => ['hasSideEffects' => false], 'ReflectionFunction::isDisabled' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getAttributes' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getClosureCalledClass' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getClosureScopeClass' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getClosureThis' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getClosureUsedVariables' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getDocComment' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getEndLine' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getExtension' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getExtensionName' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getFileName' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getName' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getNamespaceName' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getNumberOfParameters' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getNumberOfRequiredParameters' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getParameters' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getReturnType' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getShortName' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getStartLine' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getStaticVariables' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::getTentativeReturnType' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::hasTentativeReturnType' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::isClosure' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::isDeprecated' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::isGenerator' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::isInternal' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::isStatic' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::isUserDefined' => ['hasSideEffects' => false], 'ReflectionFunctionAbstract::isVariadic' => ['hasSideEffects' => false], 'ReflectionGenerator::getExecutingFile' => ['hasSideEffects' => false], 'ReflectionGenerator::getExecutingGenerator' => ['hasSideEffects' => false], 'ReflectionGenerator::getExecutingLine' => ['hasSideEffects' => false], 'ReflectionGenerator::getFunction' => ['hasSideEffects' => false], 'ReflectionGenerator::getThis' => ['hasSideEffects' => false], 'ReflectionGenerator::getTrace' => ['hasSideEffects' => false], 'ReflectionIntersectionType::getTypes' => ['hasSideEffects' => false], 'ReflectionMethod::getClosure' => ['hasSideEffects' => false], 'ReflectionMethod::getDeclaringClass' => ['hasSideEffects' => false], 'ReflectionMethod::getModifiers' => ['hasSideEffects' => false], 'ReflectionMethod::getPrototype' => ['hasSideEffects' => false], 'ReflectionMethod::isAbstract' => ['hasSideEffects' => false], 'ReflectionMethod::isConstructor' => ['hasSideEffects' => false], 'ReflectionMethod::isDestructor' => ['hasSideEffects' => false], 'ReflectionMethod::isFinal' => ['hasSideEffects' => false], 'ReflectionMethod::isPrivate' => ['hasSideEffects' => false], 'ReflectionMethod::isProtected' => ['hasSideEffects' => false], 'ReflectionMethod::isPublic' => ['hasSideEffects' => false], 'ReflectionMethod::isStatic' => ['hasSideEffects' => false], 'ReflectionMethod::setAccessible' => ['hasSideEffects' => false], 'ReflectionNamedType::getName' => ['hasSideEffects' => false], 'ReflectionNamedType::isBuiltin' => ['hasSideEffects' => false], 'ReflectionParameter::getAttributes' => ['hasSideEffects' => false], 'ReflectionParameter::getClass' => ['hasSideEffects' => false], 'ReflectionParameter::getDeclaringClass' => ['hasSideEffects' => false], 'ReflectionParameter::getDeclaringFunction' => ['hasSideEffects' => false], 'ReflectionParameter::getDefaultValue' => ['hasSideEffects' => false], 'ReflectionParameter::getDefaultValueConstantName' => ['hasSideEffects' => false], 'ReflectionParameter::getName' => ['hasSideEffects' => false], 'ReflectionParameter::getPosition' => ['hasSideEffects' => false], 'ReflectionParameter::getType' => ['hasSideEffects' => false], 'ReflectionParameter::isArray' => ['hasSideEffects' => false], 'ReflectionParameter::isCallable' => ['hasSideEffects' => false], 'ReflectionParameter::isDefaultValueAvailable' => ['hasSideEffects' => false], 'ReflectionParameter::isDefaultValueConstant' => ['hasSideEffects' => false], 'ReflectionParameter::isOptional' => ['hasSideEffects' => false], 'ReflectionParameter::isPassedByReference' => ['hasSideEffects' => false], 'ReflectionParameter::isPromoted' => ['hasSideEffects' => false], 'ReflectionParameter::isVariadic' => ['hasSideEffects' => false], 'ReflectionProperty::getAttributes' => ['hasSideEffects' => false], 'ReflectionProperty::getDeclaringClass' => ['hasSideEffects' => false], 'ReflectionProperty::getDefaultValue' => ['hasSideEffects' => false], 'ReflectionProperty::getDocComment' => ['hasSideEffects' => false], 'ReflectionProperty::getModifiers' => ['hasSideEffects' => false], 'ReflectionProperty::getName' => ['hasSideEffects' => false], 'ReflectionProperty::getType' => ['hasSideEffects' => false], 'ReflectionProperty::getValue' => ['hasSideEffects' => false], 'ReflectionProperty::isDefault' => ['hasSideEffects' => false], 'ReflectionProperty::isInitialized' => ['hasSideEffects' => false], 'ReflectionProperty::isPrivate' => ['hasSideEffects' => false], 'ReflectionProperty::isPromoted' => ['hasSideEffects' => false], 'ReflectionProperty::isProtected' => ['hasSideEffects' => false], 'ReflectionProperty::isPublic' => ['hasSideEffects' => false], 'ReflectionProperty::isStatic' => ['hasSideEffects' => false], 'ReflectionProperty::setAccessible' => ['hasSideEffects' => false], 'ReflectionReference::getId' => ['hasSideEffects' => false], 'ReflectionType::isBuiltin' => ['hasSideEffects' => false], 'ReflectionUnionType::getTypes' => ['hasSideEffects' => false], 'ReflectionZendExtension::getAuthor' => ['hasSideEffects' => false], 'ReflectionZendExtension::getCopyright' => ['hasSideEffects' => false], 'ReflectionZendExtension::getName' => ['hasSideEffects' => false], 'ReflectionZendExtension::getURL' => ['hasSideEffects' => false], 'ReflectionZendExtension::getVersion' => ['hasSideEffects' => false], 'ResourceBundle::__construct' => ['hasSideEffects' => false], 'ResourceBundle::count' => ['hasSideEffects' => false], 'ResourceBundle::get' => ['hasSideEffects' => false], 'ResourceBundle::getErrorCode' => ['hasSideEffects' => false], 'ResourceBundle::getErrorMessage' => ['hasSideEffects' => false], 'ResourceBundle::getIterator' => ['hasSideEffects' => false], 'SQLiteException::__construct' => ['hasSideEffects' => false], 'SimpleXMLElement::__construct' => ['hasSideEffects' => false], 'SimpleXMLElement::children' => ['hasSideEffects' => false], 'SimpleXMLElement::count' => ['hasSideEffects' => false], 'SimpleXMLElement::current' => ['hasSideEffects' => false], 'SimpleXMLElement::getChildren' => ['hasSideEffects' => false], 'SimpleXMLElement::getDocNamespaces' => ['hasSideEffects' => false], 'SimpleXMLElement::getName' => ['hasSideEffects' => false], 'SimpleXMLElement::getNamespaces' => ['hasSideEffects' => false], 'SimpleXMLElement::hasChildren' => ['hasSideEffects' => false], 'SimpleXMLElement::offsetExists' => ['hasSideEffects' => false], 'SimpleXMLElement::offsetGet' => ['hasSideEffects' => false], 'SimpleXMLElement::valid' => ['hasSideEffects' => false], 'SimpleXMLIterator::count' => ['hasSideEffects' => false], 'SimpleXMLIterator::current' => ['hasSideEffects' => false], 'SimpleXMLIterator::getChildren' => ['hasSideEffects' => false], 'SimpleXMLIterator::hasChildren' => ['hasSideEffects' => false], 'SimpleXMLIterator::valid' => ['hasSideEffects' => false], 'SoapFault::__construct' => ['hasSideEffects' => false], 'SplFileObject::fflush' => ['hasSideEffects' => true], 'SplFileObject::fgetc' => ['hasSideEffects' => true], 'SplFileObject::fgetcsv' => ['hasSideEffects' => true], 'SplFileObject::fgets' => ['hasSideEffects' => true], 'SplFileObject::fgetss' => ['hasSideEffects' => true], 'SplFileObject::fpassthru' => ['hasSideEffects' => true], 'SplFileObject::fputcsv' => ['hasSideEffects' => true], 'SplFileObject::fread' => ['hasSideEffects' => true], 'SplFileObject::fscanf' => ['hasSideEffects' => true], 'SplFileObject::fseek' => ['hasSideEffects' => true], 'SplFileObject::ftruncate' => ['hasSideEffects' => true], 'SplFileObject::fwrite' => ['hasSideEffects' => true], 'Spoofchecker::__construct' => ['hasSideEffects' => false], 'StringBackedEnum::from' => ['hasSideEffects' => false], 'StringBackedEnum::tryFrom' => ['hasSideEffects' => false], 'StubTests\\CodeStyle\\BracesOneLineFixer::getDefinition' => ['hasSideEffects' => false], 'StubTests\\Parsers\\ExpectedFunctionArgumentsInfo::__toString' => ['hasSideEffects' => false], 'StubTests\\Parsers\\Visitors\\CoreStubASTVisitor::__construct' => ['hasSideEffects' => false], 'StubTests\\StubsMetaExpectedArgumentsTest::getClassMemberFqn' => ['hasSideEffects' => false], 'StubTests\\StubsParameterNamesTest::printParameters' => ['hasSideEffects' => false], 'Transliterator::createInverse' => ['hasSideEffects' => false], 'Transliterator::getErrorCode' => ['hasSideEffects' => false], 'Transliterator::getErrorMessage' => ['hasSideEffects' => false], 'Transliterator::transliterate' => ['hasSideEffects' => false], 'UConverter::__construct' => ['hasSideEffects' => false], 'UConverter::convert' => ['hasSideEffects' => false], 'UConverter::getDestinationEncoding' => ['hasSideEffects' => false], 'UConverter::getDestinationType' => ['hasSideEffects' => false], 'UConverter::getErrorCode' => ['hasSideEffects' => false], 'UConverter::getErrorMessage' => ['hasSideEffects' => false], 'UConverter::getSourceEncoding' => ['hasSideEffects' => false], 'UConverter::getSourceType' => ['hasSideEffects' => false], 'UConverter::getStandards' => ['hasSideEffects' => false], 'UConverter::getSubstChars' => ['hasSideEffects' => false], 'UConverter::reasonText' => ['hasSideEffects' => false], 'UnitEnum::cases' => ['hasSideEffects' => false], 'WeakMap::count' => ['hasSideEffects' => false], 'WeakMap::getIterator' => ['hasSideEffects' => false], 'WeakMap::offsetExists' => ['hasSideEffects' => false], 'WeakMap::offsetGet' => ['hasSideEffects' => false], 'WeakReference::create' => ['hasSideEffects' => false], 'WeakReference::get' => ['hasSideEffects' => false], 'XmlReader::next' => ['hasSideEffects' => true], 'XmlReader::read' => ['hasSideEffects' => true], 'Zookeeper::getAcl' => ['hasSideEffects' => false], 'Zookeeper::getChildren' => ['hasSideEffects' => false], 'Zookeeper::getClientId' => ['hasSideEffects' => false], 'Zookeeper::getRecvTimeout' => ['hasSideEffects' => false], 'Zookeeper::getState' => ['hasSideEffects' => false], '_' => ['hasSideEffects' => false], 'abs' => ['hasSideEffects' => false], 'acos' => ['hasSideEffects' => false], 'acosh' => ['hasSideEffects' => false], 'addcslashes' => ['hasSideEffects' => false], 'addslashes' => ['hasSideEffects' => false], 'apache_get_modules' => ['hasSideEffects' => false], 'apache_get_version' => ['hasSideEffects' => false], 'apache_getenv' => ['hasSideEffects' => false], 'apache_request_headers' => ['hasSideEffects' => false], 'array_change_key_case' => ['hasSideEffects' => false], 'array_chunk' => ['hasSideEffects' => false], 'array_column' => ['hasSideEffects' => false], 'array_combine' => ['hasSideEffects' => false], 'array_count_values' => ['hasSideEffects' => false], 'array_diff' => ['hasSideEffects' => false], 'array_diff_assoc' => ['hasSideEffects' => false], 'array_diff_key' => ['hasSideEffects' => false], 'array_diff_uassoc' => ['hasSideEffects' => false], 'array_diff_ukey' => ['hasSideEffects' => false], 'array_fill' => ['hasSideEffects' => false], 'array_fill_keys' => ['hasSideEffects' => false], 'array_flip' => ['hasSideEffects' => false], 'array_intersect' => ['hasSideEffects' => false], 'array_intersect_assoc' => ['hasSideEffects' => false], 'array_intersect_key' => ['hasSideEffects' => false], 'array_intersect_uassoc' => ['hasSideEffects' => false], 'array_intersect_ukey' => ['hasSideEffects' => false], 'array_is_list' => ['hasSideEffects' => false], 'array_key_exists' => ['hasSideEffects' => false], 'array_key_first' => ['hasSideEffects' => false], 'array_key_last' => ['hasSideEffects' => false], 'array_keys' => ['hasSideEffects' => false], 'array_merge' => ['hasSideEffects' => false], 'array_merge_recursive' => ['hasSideEffects' => false], 'array_pad' => ['hasSideEffects' => false], 'array_pop' => ['hasSideEffects' => true], 'array_product' => ['hasSideEffects' => false], 'array_push' => ['hasSideEffects' => true], 'array_rand' => ['hasSideEffects' => false], 'array_replace' => ['hasSideEffects' => false], 'array_replace_recursive' => ['hasSideEffects' => false], 'array_reverse' => ['hasSideEffects' => false], 'array_search' => ['hasSideEffects' => false], 'array_shift' => ['hasSideEffects' => true], 'array_slice' => ['hasSideEffects' => false], 'array_sum' => ['hasSideEffects' => false], 'array_udiff' => ['hasSideEffects' => false], 'array_udiff_assoc' => ['hasSideEffects' => false], 'array_udiff_uassoc' => ['hasSideEffects' => false], 'array_uintersect' => ['hasSideEffects' => false], 'array_uintersect_assoc' => ['hasSideEffects' => false], 'array_uintersect_uassoc' => ['hasSideEffects' => false], 'array_unique' => ['hasSideEffects' => false], 'array_unshift' => ['hasSideEffects' => true], 'array_values' => ['hasSideEffects' => false], 'asin' => ['hasSideEffects' => false], 'asinh' => ['hasSideEffects' => false], 'atan' => ['hasSideEffects' => false], 'atan2' => ['hasSideEffects' => false], 'atanh' => ['hasSideEffects' => false], 'base64_decode' => ['hasSideEffects' => false], 'base64_encode' => ['hasSideEffects' => false], 'base_convert' => ['hasSideEffects' => false], 'basename' => ['hasSideEffects' => false], 'bcadd' => ['hasSideEffects' => false], 'bccomp' => ['hasSideEffects' => false], 'bcdiv' => ['hasSideEffects' => false], 'bcmod' => ['hasSideEffects' => false], 'bcmul' => ['hasSideEffects' => false], 'bcpow' => ['hasSideEffects' => false], 'bcpowmod' => ['hasSideEffects' => false], 'bcsqrt' => ['hasSideEffects' => false], 'bcsub' => ['hasSideEffects' => false], 'bin2hex' => ['hasSideEffects' => false], 'bindec' => ['hasSideEffects' => false], 'boolval' => ['hasSideEffects' => false], 'bzcompress' => ['hasSideEffects' => false], 'bzdecompress' => ['hasSideEffects' => false], 'bzerrno' => ['hasSideEffects' => false], 'bzerror' => ['hasSideEffects' => false], 'bzerrstr' => ['hasSideEffects' => false], 'bzopen' => ['hasSideEffects' => false], 'ceil' => ['hasSideEffects' => false], 'checkdate' => ['hasSideEffects' => false], 'checkdnsrr' => ['hasSideEffects' => false], 'chgrp' => ['hasSideEffects' => true], 'chmod' => ['hasSideEffects' => true], 'chop' => ['hasSideEffects' => false], 'chown' => ['hasSideEffects' => true], 'chr' => ['hasSideEffects' => false], 'chunk_split' => ['hasSideEffects' => false], 'class_implements' => ['hasSideEffects' => false], 'class_parents' => ['hasSideEffects' => false], 'cli_get_process_title' => ['hasSideEffects' => false], 'collator_compare' => ['hasSideEffects' => false], 'collator_create' => ['hasSideEffects' => false], 'collator_get_attribute' => ['hasSideEffects' => false], 'collator_get_error_code' => ['hasSideEffects' => false], 'collator_get_error_message' => ['hasSideEffects' => false], 'collator_get_locale' => ['hasSideEffects' => false], 'collator_get_sort_key' => ['hasSideEffects' => false], 'collator_get_strength' => ['hasSideEffects' => false], 'compact' => ['hasSideEffects' => false], 'connection_aborted' => ['hasSideEffects' => true], 'connection_status' => ['hasSideEffects' => true], 'constant' => ['hasSideEffects' => false], 'convert_cyr_string' => ['hasSideEffects' => false], 'convert_uudecode' => ['hasSideEffects' => false], 'convert_uuencode' => ['hasSideEffects' => false], 'copy' => ['hasSideEffects' => true], 'cos' => ['hasSideEffects' => false], 'cosh' => ['hasSideEffects' => false], 'count' => ['hasSideEffects' => false], 'count_chars' => ['hasSideEffects' => false], 'crc32' => ['hasSideEffects' => false], 'crypt' => ['hasSideEffects' => false], 'ctype_alnum' => ['hasSideEffects' => false], 'ctype_alpha' => ['hasSideEffects' => false], 'ctype_cntrl' => ['hasSideEffects' => false], 'ctype_digit' => ['hasSideEffects' => false], 'ctype_graph' => ['hasSideEffects' => false], 'ctype_lower' => ['hasSideEffects' => false], 'ctype_print' => ['hasSideEffects' => false], 'ctype_punct' => ['hasSideEffects' => false], 'ctype_space' => ['hasSideEffects' => false], 'ctype_upper' => ['hasSideEffects' => false], 'ctype_xdigit' => ['hasSideEffects' => false], 'curl_copy_handle' => ['hasSideEffects' => false], 'curl_errno' => ['hasSideEffects' => false], 'curl_error' => ['hasSideEffects' => false], 'curl_escape' => ['hasSideEffects' => false], 'curl_file_create' => ['hasSideEffects' => false], 'curl_getinfo' => ['hasSideEffects' => false], 'curl_multi_errno' => ['hasSideEffects' => false], 'curl_multi_getcontent' => ['hasSideEffects' => false], 'curl_multi_info_read' => ['hasSideEffects' => false], 'curl_share_errno' => ['hasSideEffects' => false], 'curl_share_strerror' => ['hasSideEffects' => false], 'curl_strerror' => ['hasSideEffects' => false], 'curl_unescape' => ['hasSideEffects' => false], 'curl_version' => ['hasSideEffects' => false], 'current' => ['hasSideEffects' => false], 'date' => ['hasSideEffects' => false], 'date_create' => ['hasSideEffects' => false], 'date_create_from_format' => ['hasSideEffects' => false], 'date_create_immutable' => ['hasSideEffects' => false], 'date_create_immutable_from_format' => ['hasSideEffects' => false], 'date_default_timezone_get' => ['hasSideEffects' => false], 'date_diff' => ['hasSideEffects' => false], 'date_format' => ['hasSideEffects' => false], 'date_get_last_errors' => ['hasSideEffects' => false], 'date_interval_create_from_date_string' => ['hasSideEffects' => false], 'date_interval_format' => ['hasSideEffects' => false], 'date_offset_get' => ['hasSideEffects' => false], 'date_parse' => ['hasSideEffects' => false], 'date_parse_from_format' => ['hasSideEffects' => false], 'date_sun_info' => ['hasSideEffects' => false], 'date_sunrise' => ['hasSideEffects' => false], 'date_sunset' => ['hasSideEffects' => false], 'date_timestamp_get' => ['hasSideEffects' => false], 'date_timezone_get' => ['hasSideEffects' => false], 'datefmt_create' => ['hasSideEffects' => false], 'datefmt_format' => ['hasSideEffects' => false], 'datefmt_format_object' => ['hasSideEffects' => false], 'datefmt_get_calendar' => ['hasSideEffects' => false], 'datefmt_get_calendar_object' => ['hasSideEffects' => false], 'datefmt_get_datetype' => ['hasSideEffects' => false], 'datefmt_get_error_code' => ['hasSideEffects' => false], 'datefmt_get_error_message' => ['hasSideEffects' => false], 'datefmt_get_locale' => ['hasSideEffects' => false], 'datefmt_get_pattern' => ['hasSideEffects' => false], 'datefmt_get_timetype' => ['hasSideEffects' => false], 'datefmt_get_timezone' => ['hasSideEffects' => false], 'datefmt_get_timezone_id' => ['hasSideEffects' => false], 'datefmt_is_lenient' => ['hasSideEffects' => false], 'dcngettext' => ['hasSideEffects' => false], 'decbin' => ['hasSideEffects' => false], 'dechex' => ['hasSideEffects' => false], 'decoct' => ['hasSideEffects' => false], 'defined' => ['hasSideEffects' => false], 'deflate_init' => ['hasSideEffects' => false], 'deg2rad' => ['hasSideEffects' => false], 'dirname' => ['hasSideEffects' => false], 'disk_free_space' => ['hasSideEffects' => false], 'disk_total_space' => ['hasSideEffects' => false], 'diskfreespace' => ['hasSideEffects' => false], 'dngettext' => ['hasSideEffects' => false], 'doubleval' => ['hasSideEffects' => false], 'error_get_last' => ['hasSideEffects' => false], 'error_log' => ['hasSideEffects' => true], 'escapeshellarg' => ['hasSideEffects' => false], 'escapeshellcmd' => ['hasSideEffects' => false], 'exp' => ['hasSideEffects' => false], 'explode' => ['hasSideEffects' => false], 'expm1' => ['hasSideEffects' => false], 'extension_loaded' => ['hasSideEffects' => false], 'fclose' => ['hasSideEffects' => true], 'fdiv' => ['hasSideEffects' => false], 'feof' => ['hasSideEffects' => false], 'fflush' => ['hasSideEffects' => true], 'fgetc' => ['hasSideEffects' => true], 'fgetcsv' => ['hasSideEffects' => true], 'fgets' => ['hasSideEffects' => true], 'fgetss' => ['hasSideEffects' => true], 'file' => ['hasSideEffects' => false], 'file_exists' => ['hasSideEffects' => false], 'file_get_contents' => ['hasSideEffects' => true], 'file_put_contents' => ['hasSideEffects' => true], 'fileatime' => ['hasSideEffects' => false], 'filectime' => ['hasSideEffects' => false], 'filegroup' => ['hasSideEffects' => false], 'fileinode' => ['hasSideEffects' => false], 'filemtime' => ['hasSideEffects' => false], 'fileowner' => ['hasSideEffects' => false], 'fileperms' => ['hasSideEffects' => false], 'filesize' => ['hasSideEffects' => false], 'filetype' => ['hasSideEffects' => false], 'filter_has_var' => ['hasSideEffects' => false], 'filter_id' => ['hasSideEffects' => false], 'filter_input' => ['hasSideEffects' => false], 'filter_input_array' => ['hasSideEffects' => false], 'filter_list' => ['hasSideEffects' => false], 'filter_var' => ['hasSideEffects' => false], 'filter_var_array' => ['hasSideEffects' => false], 'finfo::buffer' => ['hasSideEffects' => false], 'finfo::file' => ['hasSideEffects' => false], 'floatval' => ['hasSideEffects' => false], 'flock' => ['hasSideEffects' => true], 'floor' => ['hasSideEffects' => false], 'fmod' => ['hasSideEffects' => false], 'fnmatch' => ['hasSideEffects' => false], 'fopen' => ['hasSideEffects' => true], 'fpassthru' => ['hasSideEffects' => true], 'fputcsv' => ['hasSideEffects' => true], 'fputs' => ['hasSideEffects' => true], 'fread' => ['hasSideEffects' => true], 'fscanf' => ['hasSideEffects' => true], 'fseek' => ['hasSideEffects' => true], 'fstat' => ['hasSideEffects' => false], 'ftell' => ['hasSideEffects' => false], 'ftok' => ['hasSideEffects' => false], 'ftruncate' => ['hasSideEffects' => true], 'func_get_arg' => ['hasSideEffects' => false], 'func_get_args' => ['hasSideEffects' => false], 'func_num_args' => ['hasSideEffects' => false], 'function_exists' => ['hasSideEffects' => false], 'fwrite' => ['hasSideEffects' => true], 'gc_enabled' => ['hasSideEffects' => false], 'gc_status' => ['hasSideEffects' => false], 'gd_info' => ['hasSideEffects' => false], 'geoip_continent_code_by_name' => ['hasSideEffects' => false], 'geoip_country_code3_by_name' => ['hasSideEffects' => false], 'geoip_country_code_by_name' => ['hasSideEffects' => false], 'geoip_country_name_by_name' => ['hasSideEffects' => false], 'geoip_database_info' => ['hasSideEffects' => false], 'geoip_db_avail' => ['hasSideEffects' => false], 'geoip_db_filename' => ['hasSideEffects' => false], 'geoip_db_get_all_info' => ['hasSideEffects' => false], 'geoip_id_by_name' => ['hasSideEffects' => false], 'geoip_isp_by_name' => ['hasSideEffects' => false], 'geoip_org_by_name' => ['hasSideEffects' => false], 'geoip_record_by_name' => ['hasSideEffects' => false], 'geoip_region_by_name' => ['hasSideEffects' => false], 'geoip_region_name_by_code' => ['hasSideEffects' => false], 'geoip_time_zone_by_country_and_region' => ['hasSideEffects' => false], 'get_browser' => ['hasSideEffects' => false], 'get_called_class' => ['hasSideEffects' => false], 'get_cfg_var' => ['hasSideEffects' => false], 'get_class' => ['hasSideEffects' => false], 'get_class_methods' => ['hasSideEffects' => false], 'get_class_vars' => ['hasSideEffects' => false], 'get_current_user' => ['hasSideEffects' => false], 'get_debug_type' => ['hasSideEffects' => false], 'get_declared_classes' => ['hasSideEffects' => false], 'get_declared_interfaces' => ['hasSideEffects' => false], 'get_declared_traits' => ['hasSideEffects' => false], 'get_defined_constants' => ['hasSideEffects' => false], 'get_defined_functions' => ['hasSideEffects' => false], 'get_defined_vars' => ['hasSideEffects' => false], 'get_extension_funcs' => ['hasSideEffects' => false], 'get_headers' => ['hasSideEffects' => false], 'get_html_translation_table' => ['hasSideEffects' => false], 'get_include_path' => ['hasSideEffects' => false], 'get_included_files' => ['hasSideEffects' => false], 'get_loaded_extensions' => ['hasSideEffects' => false], 'get_meta_tags' => ['hasSideEffects' => false], 'get_object_vars' => ['hasSideEffects' => false], 'get_parent_class' => ['hasSideEffects' => false], 'get_required_files' => ['hasSideEffects' => false], 'get_resource_id' => ['hasSideEffects' => false], 'get_resources' => ['hasSideEffects' => false], 'getallheaders' => ['hasSideEffects' => false], 'getcwd' => ['hasSideEffects' => false], 'getdate' => ['hasSideEffects' => false], 'getenv' => ['hasSideEffects' => false], 'gethostbyaddr' => ['hasSideEffects' => false], 'gethostbyname' => ['hasSideEffects' => false], 'gethostbynamel' => ['hasSideEffects' => false], 'gethostname' => ['hasSideEffects' => false], 'getlastmod' => ['hasSideEffects' => false], 'getmygid' => ['hasSideEffects' => false], 'getmyinode' => ['hasSideEffects' => false], 'getmypid' => ['hasSideEffects' => false], 'getmyuid' => ['hasSideEffects' => false], 'getprotobyname' => ['hasSideEffects' => false], 'getprotobynumber' => ['hasSideEffects' => false], 'getrandmax' => ['hasSideEffects' => false], 'getrusage' => ['hasSideEffects' => false], 'getservbyname' => ['hasSideEffects' => false], 'getservbyport' => ['hasSideEffects' => false], 'gettext' => ['hasSideEffects' => false], 'gettimeofday' => ['hasSideEffects' => false], 'gettype' => ['hasSideEffects' => false], 'glob' => ['hasSideEffects' => false], 'gmdate' => ['hasSideEffects' => false], 'gmmktime' => ['hasSideEffects' => false], 'gmp_abs' => ['hasSideEffects' => false], 'gmp_add' => ['hasSideEffects' => false], 'gmp_and' => ['hasSideEffects' => false], 'gmp_binomial' => ['hasSideEffects' => false], 'gmp_cmp' => ['hasSideEffects' => false], 'gmp_com' => ['hasSideEffects' => false], 'gmp_div' => ['hasSideEffects' => false], 'gmp_div_q' => ['hasSideEffects' => false], 'gmp_div_qr' => ['hasSideEffects' => false], 'gmp_div_r' => ['hasSideEffects' => false], 'gmp_divexact' => ['hasSideEffects' => false], 'gmp_export' => ['hasSideEffects' => false], 'gmp_fact' => ['hasSideEffects' => false], 'gmp_gcd' => ['hasSideEffects' => false], 'gmp_gcdext' => ['hasSideEffects' => false], 'gmp_hamdist' => ['hasSideEffects' => false], 'gmp_import' => ['hasSideEffects' => false], 'gmp_init' => ['hasSideEffects' => false], 'gmp_intval' => ['hasSideEffects' => false], 'gmp_invert' => ['hasSideEffects' => false], 'gmp_jacobi' => ['hasSideEffects' => false], 'gmp_kronecker' => ['hasSideEffects' => false], 'gmp_lcm' => ['hasSideEffects' => false], 'gmp_legendre' => ['hasSideEffects' => false], 'gmp_mod' => ['hasSideEffects' => false], 'gmp_mul' => ['hasSideEffects' => false], 'gmp_neg' => ['hasSideEffects' => false], 'gmp_nextprime' => ['hasSideEffects' => false], 'gmp_or' => ['hasSideEffects' => false], 'gmp_perfect_power' => ['hasSideEffects' => false], 'gmp_perfect_square' => ['hasSideEffects' => false], 'gmp_popcount' => ['hasSideEffects' => false], 'gmp_pow' => ['hasSideEffects' => false], 'gmp_powm' => ['hasSideEffects' => false], 'gmp_prob_prime' => ['hasSideEffects' => false], 'gmp_root' => ['hasSideEffects' => false], 'gmp_rootrem' => ['hasSideEffects' => false], 'gmp_scan0' => ['hasSideEffects' => false], 'gmp_scan1' => ['hasSideEffects' => false], 'gmp_sign' => ['hasSideEffects' => false], 'gmp_sqrt' => ['hasSideEffects' => false], 'gmp_sqrtrem' => ['hasSideEffects' => false], 'gmp_strval' => ['hasSideEffects' => false], 'gmp_sub' => ['hasSideEffects' => false], 'gmp_testbit' => ['hasSideEffects' => false], 'gmp_xor' => ['hasSideEffects' => false], 'grapheme_stripos' => ['hasSideEffects' => false], 'grapheme_stristr' => ['hasSideEffects' => false], 'grapheme_strlen' => ['hasSideEffects' => false], 'grapheme_strpos' => ['hasSideEffects' => false], 'grapheme_strripos' => ['hasSideEffects' => false], 'grapheme_strrpos' => ['hasSideEffects' => false], 'grapheme_strstr' => ['hasSideEffects' => false], 'grapheme_substr' => ['hasSideEffects' => false], 'gzcompress' => ['hasSideEffects' => false], 'gzdecode' => ['hasSideEffects' => false], 'gzdeflate' => ['hasSideEffects' => false], 'gzencode' => ['hasSideEffects' => false], 'gzinflate' => ['hasSideEffects' => false], 'gzuncompress' => ['hasSideEffects' => false], 'hash' => ['hasSideEffects' => false], 'hash_algos' => ['hasSideEffects' => false], 'hash_copy' => ['hasSideEffects' => false], 'hash_equals' => ['hasSideEffects' => false], 'hash_file' => ['hasSideEffects' => false], 'hash_hkdf' => ['hasSideEffects' => false], 'hash_hmac' => ['hasSideEffects' => false], 'hash_hmac_algos' => ['hasSideEffects' => false], 'hash_hmac_file' => ['hasSideEffects' => false], 'hash_init' => ['hasSideEffects' => false], 'hash_pbkdf2' => ['hasSideEffects' => false], 'headers_list' => ['hasSideEffects' => false], 'hebrev' => ['hasSideEffects' => false], 'hexdec' => ['hasSideEffects' => false], 'hrtime' => ['hasSideEffects' => false], 'html_entity_decode' => ['hasSideEffects' => false], 'htmlentities' => ['hasSideEffects' => false], 'htmlspecialchars' => ['hasSideEffects' => false], 'htmlspecialchars_decode' => ['hasSideEffects' => false], 'http_build_cookie' => ['hasSideEffects' => false], 'http_build_query' => ['hasSideEffects' => false], 'http_build_str' => ['hasSideEffects' => false], 'http_cache_etag' => ['hasSideEffects' => false], 'http_cache_last_modified' => ['hasSideEffects' => false], 'http_chunked_decode' => ['hasSideEffects' => false], 'http_date' => ['hasSideEffects' => false], 'http_deflate' => ['hasSideEffects' => false], 'http_get_request_body' => ['hasSideEffects' => false], 'http_get_request_body_stream' => ['hasSideEffects' => false], 'http_get_request_headers' => ['hasSideEffects' => false], 'http_inflate' => ['hasSideEffects' => false], 'http_match_etag' => ['hasSideEffects' => false], 'http_match_modified' => ['hasSideEffects' => false], 'http_match_request_header' => ['hasSideEffects' => false], 'http_parse_cookie' => ['hasSideEffects' => false], 'http_parse_headers' => ['hasSideEffects' => false], 'http_parse_message' => ['hasSideEffects' => false], 'http_parse_params' => ['hasSideEffects' => false], 'http_request_body_encode' => ['hasSideEffects' => false], 'http_request_method_exists' => ['hasSideEffects' => false], 'http_request_method_name' => ['hasSideEffects' => false], 'http_support' => ['hasSideEffects' => false], 'hypot' => ['hasSideEffects' => false], 'iconv' => ['hasSideEffects' => false], 'iconv_get_encoding' => ['hasSideEffects' => false], 'iconv_mime_decode' => ['hasSideEffects' => false], 'iconv_mime_decode_headers' => ['hasSideEffects' => false], 'iconv_mime_encode' => ['hasSideEffects' => false], 'iconv_strlen' => ['hasSideEffects' => false], 'iconv_strpos' => ['hasSideEffects' => false], 'iconv_strrpos' => ['hasSideEffects' => false], 'iconv_substr' => ['hasSideEffects' => false], 'idate' => ['hasSideEffects' => false], 'image_type_to_extension' => ['hasSideEffects' => false], 'image_type_to_mime_type' => ['hasSideEffects' => false], 'imagecolorat' => ['hasSideEffects' => false], 'imagecolorclosest' => ['hasSideEffects' => false], 'imagecolorclosestalpha' => ['hasSideEffects' => false], 'imagecolorclosesthwb' => ['hasSideEffects' => false], 'imagecolorexact' => ['hasSideEffects' => false], 'imagecolorexactalpha' => ['hasSideEffects' => false], 'imagecolorresolve' => ['hasSideEffects' => false], 'imagecolorresolvealpha' => ['hasSideEffects' => false], 'imagecolorsforindex' => ['hasSideEffects' => false], 'imagecolorstotal' => ['hasSideEffects' => false], 'imagecreate' => ['hasSideEffects' => false], 'imagecreatefromstring' => ['hasSideEffects' => false], 'imagecreatetruecolor' => ['hasSideEffects' => false], 'imagefontheight' => ['hasSideEffects' => false], 'imagefontwidth' => ['hasSideEffects' => false], 'imageftbbox' => ['hasSideEffects' => false], 'imagegetinterpolation' => ['hasSideEffects' => false], 'imagegrabscreen' => ['hasSideEffects' => false], 'imagegrabwindow' => ['hasSideEffects' => false], 'imageistruecolor' => ['hasSideEffects' => false], 'imagesx' => ['hasSideEffects' => false], 'imagesy' => ['hasSideEffects' => false], 'imagettfbbox' => ['hasSideEffects' => false], 'imagetypes' => ['hasSideEffects' => false], 'implode' => ['hasSideEffects' => false], 'in_array' => ['hasSideEffects' => false], 'inet_ntop' => ['hasSideEffects' => false], 'inet_pton' => ['hasSideEffects' => false], 'inflate_get_read_len' => ['hasSideEffects' => false], 'inflate_get_status' => ['hasSideEffects' => false], 'inflate_init' => ['hasSideEffects' => false], 'ini_get' => ['hasSideEffects' => false], 'ini_get_all' => ['hasSideEffects' => false], 'intcal_get_maximum' => ['hasSideEffects' => false], 'intdiv' => ['hasSideEffects' => false], 'intl_error_name' => ['hasSideEffects' => false], 'intl_get' => ['hasSideEffects' => false], 'intl_get_error_code' => ['hasSideEffects' => false], 'intl_get_error_message' => ['hasSideEffects' => false], 'intl_is_failure' => ['hasSideEffects' => false], 'intlcal_after' => ['hasSideEffects' => false], 'intlcal_before' => ['hasSideEffects' => false], 'intlcal_create_instance' => ['hasSideEffects' => false], 'intlcal_equals' => ['hasSideEffects' => false], 'intlcal_field_difference' => ['hasSideEffects' => false], 'intlcal_from_date_time' => ['hasSideEffects' => false], 'intlcal_get' => ['hasSideEffects' => false], 'intlcal_get_actual_maximum' => ['hasSideEffects' => false], 'intlcal_get_actual_minimum' => ['hasSideEffects' => false], 'intlcal_get_available_locales' => ['hasSideEffects' => false], 'intlcal_get_day_of_week_type' => ['hasSideEffects' => false], 'intlcal_get_error_code' => ['hasSideEffects' => false], 'intlcal_get_error_message' => ['hasSideEffects' => false], 'intlcal_get_first_day_of_week' => ['hasSideEffects' => false], 'intlcal_get_greatest_minimum' => ['hasSideEffects' => false], 'intlcal_get_keyword_values_for_locale' => ['hasSideEffects' => false], 'intlcal_get_least_maximum' => ['hasSideEffects' => false], 'intlcal_get_locale' => ['hasSideEffects' => false], 'intlcal_get_maximum' => ['hasSideEffects' => false], 'intlcal_get_minimal_days_in_first_week' => ['hasSideEffects' => false], 'intlcal_get_minimum' => ['hasSideEffects' => false], 'intlcal_get_now' => ['hasSideEffects' => false], 'intlcal_get_repeated_wall_time_option' => ['hasSideEffects' => false], 'intlcal_get_skipped_wall_time_option' => ['hasSideEffects' => false], 'intlcal_get_time' => ['hasSideEffects' => false], 'intlcal_get_time_zone' => ['hasSideEffects' => false], 'intlcal_get_type' => ['hasSideEffects' => false], 'intlcal_get_weekend_transition' => ['hasSideEffects' => false], 'intlcal_greates_minimum' => ['hasSideEffects' => false], 'intlcal_in_daylight_time' => ['hasSideEffects' => false], 'intlcal_is_equivalent_to' => ['hasSideEffects' => false], 'intlcal_is_lenient' => ['hasSideEffects' => false], 'intlcal_is_set' => ['hasSideEffects' => false], 'intlcal_is_weekend' => ['hasSideEffects' => false], 'intlcal_to_date_time' => ['hasSideEffects' => false], 'intlgregcal_create_instance' => ['hasSideEffects' => false], 'intlgregcal_get_gregorian_change' => ['hasSideEffects' => false], 'intlgregcal_is_leap_year' => ['hasSideEffects' => false], 'intltz_count_equivalent_ids' => ['hasSideEffects' => false], 'intltz_create_default' => ['hasSideEffects' => false], 'intltz_create_enumeration' => ['hasSideEffects' => false], 'intltz_create_time_zone' => ['hasSideEffects' => false], 'intltz_create_time_zone_id_enumeration' => ['hasSideEffects' => false], 'intltz_from_date_time_zone' => ['hasSideEffects' => false], 'intltz_get_canonical_id' => ['hasSideEffects' => false], 'intltz_get_display_name' => ['hasSideEffects' => false], 'intltz_get_dst_savings' => ['hasSideEffects' => false], 'intltz_get_equivalent_id' => ['hasSideEffects' => false], 'intltz_get_error_code' => ['hasSideEffects' => false], 'intltz_get_error_message' => ['hasSideEffects' => false], 'intltz_get_gmt' => ['hasSideEffects' => false], 'intltz_get_id' => ['hasSideEffects' => false], 'intltz_get_offset' => ['hasSideEffects' => false], 'intltz_get_raw_offset' => ['hasSideEffects' => false], 'intltz_get_region' => ['hasSideEffects' => false], 'intltz_get_tz_data_version' => ['hasSideEffects' => false], 'intltz_get_unknown' => ['hasSideEffects' => false], 'intltz_getgmt' => ['hasSideEffects' => false], 'intltz_has_same_rules' => ['hasSideEffects' => false], 'intltz_to_date_time_zone' => ['hasSideEffects' => false], 'intltz_use_daylight_time' => ['hasSideEffects' => false], 'intlz_create_default' => ['hasSideEffects' => false], 'intval' => ['hasSideEffects' => false], 'ip2long' => ['hasSideEffects' => false], 'iptcparse' => ['hasSideEffects' => false], 'is_a' => ['hasSideEffects' => false], 'is_array' => ['hasSideEffects' => false], 'is_bool' => ['hasSideEffects' => false], 'is_countable' => ['hasSideEffects' => false], 'is_dir' => ['hasSideEffects' => false], 'is_double' => ['hasSideEffects' => false], 'is_executable' => ['hasSideEffects' => false], 'is_file' => ['hasSideEffects' => false], 'is_finite' => ['hasSideEffects' => false], 'is_float' => ['hasSideEffects' => false], 'is_infinite' => ['hasSideEffects' => false], 'is_int' => ['hasSideEffects' => false], 'is_integer' => ['hasSideEffects' => false], 'is_iterable' => ['hasSideEffects' => false], 'is_link' => ['hasSideEffects' => false], 'is_long' => ['hasSideEffects' => false], 'is_nan' => ['hasSideEffects' => false], 'is_null' => ['hasSideEffects' => false], 'is_numeric' => ['hasSideEffects' => false], 'is_object' => ['hasSideEffects' => false], 'is_readable' => ['hasSideEffects' => false], 'is_real' => ['hasSideEffects' => false], 'is_resource' => ['hasSideEffects' => false], 'is_scalar' => ['hasSideEffects' => false], 'is_string' => ['hasSideEffects' => false], 'is_subclass_of' => ['hasSideEffects' => false], 'is_uploaded_file' => ['hasSideEffects' => false], 'is_writable' => ['hasSideEffects' => false], 'is_writeable' => ['hasSideEffects' => false], 'iterator_count' => ['hasSideEffects' => false], 'join' => ['hasSideEffects' => false], 'json_last_error' => ['hasSideEffects' => false], 'json_last_error_msg' => ['hasSideEffects' => false], 'json_validate' => ['hasSideEffects' => false], 'key' => ['hasSideEffects' => false], 'key_exists' => ['hasSideEffects' => false], 'lcfirst' => ['hasSideEffects' => false], 'lchgrp' => ['hasSideEffects' => true], 'lchown' => ['hasSideEffects' => true], 'libxml_get_errors' => ['hasSideEffects' => false], 'libxml_get_last_error' => ['hasSideEffects' => false], 'link' => ['hasSideEffects' => true], 'linkinfo' => ['hasSideEffects' => false], 'locale_accept_from_http' => ['hasSideEffects' => false], 'locale_canonicalize' => ['hasSideEffects' => false], 'locale_compose' => ['hasSideEffects' => false], 'locale_filter_matches' => ['hasSideEffects' => false], 'locale_get_all_variants' => ['hasSideEffects' => false], 'locale_get_default' => ['hasSideEffects' => false], 'locale_get_display_language' => ['hasSideEffects' => false], 'locale_get_display_name' => ['hasSideEffects' => false], 'locale_get_display_region' => ['hasSideEffects' => false], 'locale_get_display_script' => ['hasSideEffects' => false], 'locale_get_display_variant' => ['hasSideEffects' => false], 'locale_get_keywords' => ['hasSideEffects' => false], 'locale_get_primary_language' => ['hasSideEffects' => false], 'locale_get_region' => ['hasSideEffects' => false], 'locale_get_script' => ['hasSideEffects' => false], 'locale_lookup' => ['hasSideEffects' => false], 'locale_parse' => ['hasSideEffects' => false], 'localeconv' => ['hasSideEffects' => false], 'localtime' => ['hasSideEffects' => false], 'log' => ['hasSideEffects' => false], 'log10' => ['hasSideEffects' => false], 'log1p' => ['hasSideEffects' => false], 'long2ip' => ['hasSideEffects' => false], 'lstat' => ['hasSideEffects' => false], 'ltrim' => ['hasSideEffects' => false], 'max' => ['hasSideEffects' => false], 'mb_check_encoding' => ['hasSideEffects' => false], 'mb_chr' => ['hasSideEffects' => false], 'mb_convert_case' => ['hasSideEffects' => false], 'mb_convert_encoding' => ['hasSideEffects' => false], 'mb_convert_kana' => ['hasSideEffects' => false], 'mb_decode_mimeheader' => ['hasSideEffects' => false], 'mb_decode_numericentity' => ['hasSideEffects' => false], 'mb_detect_encoding' => ['hasSideEffects' => false], 'mb_encode_mimeheader' => ['hasSideEffects' => false], 'mb_encode_numericentity' => ['hasSideEffects' => false], 'mb_encoding_aliases' => ['hasSideEffects' => false], 'mb_ereg_match' => ['hasSideEffects' => false], 'mb_ereg_replace' => ['hasSideEffects' => false], 'mb_ereg_search' => ['hasSideEffects' => false], 'mb_ereg_search_getpos' => ['hasSideEffects' => false], 'mb_ereg_search_getregs' => ['hasSideEffects' => false], 'mb_ereg_search_pos' => ['hasSideEffects' => false], 'mb_ereg_search_regs' => ['hasSideEffects' => false], 'mb_ereg_search_setpos' => ['hasSideEffects' => false], 'mb_eregi_replace' => ['hasSideEffects' => false], 'mb_get_info' => ['hasSideEffects' => false], 'mb_http_input' => ['hasSideEffects' => false], 'mb_list_encodings' => ['hasSideEffects' => false], 'mb_ord' => ['hasSideEffects' => false], 'mb_output_handler' => ['hasSideEffects' => false], 'mb_preferred_mime_name' => ['hasSideEffects' => false], 'mb_scrub' => ['hasSideEffects' => false], 'mb_split' => ['hasSideEffects' => false], 'mb_str_pad' => ['hasSideEffects' => false], 'mb_str_split' => ['hasSideEffects' => false], 'mb_strcut' => ['hasSideEffects' => false], 'mb_strimwidth' => ['hasSideEffects' => false], 'mb_stripos' => ['hasSideEffects' => false], 'mb_stristr' => ['hasSideEffects' => false], 'mb_strlen' => ['hasSideEffects' => false], 'mb_strpos' => ['hasSideEffects' => false], 'mb_strrchr' => ['hasSideEffects' => false], 'mb_strrichr' => ['hasSideEffects' => false], 'mb_strripos' => ['hasSideEffects' => false], 'mb_strrpos' => ['hasSideEffects' => false], 'mb_strstr' => ['hasSideEffects' => false], 'mb_strtolower' => ['hasSideEffects' => false], 'mb_strtoupper' => ['hasSideEffects' => false], 'mb_strwidth' => ['hasSideEffects' => false], 'mb_substr' => ['hasSideEffects' => false], 'mb_substr_count' => ['hasSideEffects' => false], 'mbereg_search_setpos' => ['hasSideEffects' => false], 'md5' => ['hasSideEffects' => false], 'md5_file' => ['hasSideEffects' => false], 'memory_get_peak_usage' => ['hasSideEffects' => false], 'memory_get_usage' => ['hasSideEffects' => false], 'metaphone' => ['hasSideEffects' => false], 'method_exists' => ['hasSideEffects' => false], 'mhash' => ['hasSideEffects' => false], 'mhash_count' => ['hasSideEffects' => false], 'mhash_get_block_size' => ['hasSideEffects' => false], 'mhash_get_hash_name' => ['hasSideEffects' => false], 'mhash_keygen_s2k' => ['hasSideEffects' => false], 'microtime' => ['hasSideEffects' => false], 'min' => ['hasSideEffects' => false], 'mkdir' => ['hasSideEffects' => true], 'mktime' => ['hasSideEffects' => false], 'move_uploaded_file' => ['hasSideEffects' => true], 'msgfmt_create' => ['hasSideEffects' => false], 'msgfmt_format' => ['hasSideEffects' => false], 'msgfmt_format_message' => ['hasSideEffects' => false], 'msgfmt_get_error_code' => ['hasSideEffects' => false], 'msgfmt_get_error_message' => ['hasSideEffects' => false], 'msgfmt_get_locale' => ['hasSideEffects' => false], 'msgfmt_get_pattern' => ['hasSideEffects' => false], 'msgfmt_parse' => ['hasSideEffects' => false], 'msgfmt_parse_message' => ['hasSideEffects' => false], 'mt_getrandmax' => ['hasSideEffects' => false], 'mt_rand' => ['hasSideEffects' => true], 'net_get_interfaces' => ['hasSideEffects' => false], 'ngettext' => ['hasSideEffects' => false], 'nl2br' => ['hasSideEffects' => false], 'nl_langinfo' => ['hasSideEffects' => false], 'normalizer_get_raw_decomposition' => ['hasSideEffects' => false], 'normalizer_is_normalized' => ['hasSideEffects' => false], 'normalizer_normalize' => ['hasSideEffects' => false], 'number_format' => ['hasSideEffects' => false], 'numfmt_create' => ['hasSideEffects' => false], 'numfmt_format' => ['hasSideEffects' => false], 'numfmt_format_currency' => ['hasSideEffects' => false], 'numfmt_get_attribute' => ['hasSideEffects' => false], 'numfmt_get_error_code' => ['hasSideEffects' => false], 'numfmt_get_error_message' => ['hasSideEffects' => false], 'numfmt_get_locale' => ['hasSideEffects' => false], 'numfmt_get_pattern' => ['hasSideEffects' => false], 'numfmt_get_symbol' => ['hasSideEffects' => false], 'numfmt_get_text_attribute' => ['hasSideEffects' => false], 'numfmt_parse' => ['hasSideEffects' => false], 'ob_etaghandler' => ['hasSideEffects' => false], 'ob_get_contents' => ['hasSideEffects' => false], 'ob_iconv_handler' => ['hasSideEffects' => false], 'octdec' => ['hasSideEffects' => false], 'ord' => ['hasSideEffects' => false], 'pack' => ['hasSideEffects' => false], 'pam_auth' => ['hasSideEffects' => false], 'pam_chpass' => ['hasSideEffects' => false], 'parse_ini_file' => ['hasSideEffects' => false], 'parse_ini_string' => ['hasSideEffects' => false], 'parse_url' => ['hasSideEffects' => false], 'pathinfo' => ['hasSideEffects' => false], 'pclose' => ['hasSideEffects' => true], 'pcntl_errno' => ['hasSideEffects' => false], 'pcntl_get_last_error' => ['hasSideEffects' => false], 'pcntl_getpriority' => ['hasSideEffects' => false], 'pcntl_strerror' => ['hasSideEffects' => false], 'pcntl_wexitstatus' => ['hasSideEffects' => false], 'pcntl_wifcontinued' => ['hasSideEffects' => false], 'pcntl_wifexited' => ['hasSideEffects' => false], 'pcntl_wifsignaled' => ['hasSideEffects' => false], 'pcntl_wifstopped' => ['hasSideEffects' => false], 'pcntl_wstopsig' => ['hasSideEffects' => false], 'pcntl_wtermsig' => ['hasSideEffects' => false], 'pdo_drivers' => ['hasSideEffects' => false], 'php_ini_loaded_file' => ['hasSideEffects' => false], 'php_ini_scanned_files' => ['hasSideEffects' => false], 'php_logo_guid' => ['hasSideEffects' => false], 'php_sapi_name' => ['hasSideEffects' => false], 'php_strip_whitespace' => ['hasSideEffects' => false], 'php_uname' => ['hasSideEffects' => false], 'phpversion' => ['hasSideEffects' => false], 'pi' => ['hasSideEffects' => false], 'popen' => ['hasSideEffects' => true], 'pos' => ['hasSideEffects' => false], 'posix_ctermid' => ['hasSideEffects' => false], 'posix_errno' => ['hasSideEffects' => false], 'posix_get_last_error' => ['hasSideEffects' => false], 'posix_getcwd' => ['hasSideEffects' => false], 'posix_getegid' => ['hasSideEffects' => false], 'posix_geteuid' => ['hasSideEffects' => false], 'posix_getgid' => ['hasSideEffects' => false], 'posix_getgrgid' => ['hasSideEffects' => false], 'posix_getgrnam' => ['hasSideEffects' => false], 'posix_getgroups' => ['hasSideEffects' => false], 'posix_getlogin' => ['hasSideEffects' => false], 'posix_getpgid' => ['hasSideEffects' => false], 'posix_getpgrp' => ['hasSideEffects' => false], 'posix_getpid' => ['hasSideEffects' => false], 'posix_getppid' => ['hasSideEffects' => false], 'posix_getpwnam' => ['hasSideEffects' => false], 'posix_getpwuid' => ['hasSideEffects' => false], 'posix_getrlimit' => ['hasSideEffects' => false], 'posix_getsid' => ['hasSideEffects' => false], 'posix_getuid' => ['hasSideEffects' => false], 'posix_initgroups' => ['hasSideEffects' => false], 'posix_isatty' => ['hasSideEffects' => false], 'posix_strerror' => ['hasSideEffects' => false], 'posix_times' => ['hasSideEffects' => false], 'posix_ttyname' => ['hasSideEffects' => false], 'posix_uname' => ['hasSideEffects' => false], 'pow' => ['hasSideEffects' => false], 'preg_grep' => ['hasSideEffects' => false], 'preg_last_error' => ['hasSideEffects' => false], 'preg_last_error_msg' => ['hasSideEffects' => false], 'preg_quote' => ['hasSideEffects' => false], 'preg_split' => ['hasSideEffects' => false], 'property_exists' => ['hasSideEffects' => false], 'quoted_printable_decode' => ['hasSideEffects' => false], 'quoted_printable_encode' => ['hasSideEffects' => false], 'quotemeta' => ['hasSideEffects' => false], 'rad2deg' => ['hasSideEffects' => false], 'rand' => ['hasSideEffects' => true], 'random_bytes' => ['hasSideEffects' => true], 'random_int' => ['hasSideEffects' => true], 'range' => ['hasSideEffects' => false], 'rawurldecode' => ['hasSideEffects' => false], 'rawurlencode' => ['hasSideEffects' => false], 'readfile' => ['hasSideEffects' => true], 'readlink' => ['hasSideEffects' => false], 'realpath' => ['hasSideEffects' => false], 'realpath_cache_get' => ['hasSideEffects' => false], 'realpath_cache_size' => ['hasSideEffects' => false], 'rename' => ['hasSideEffects' => true], 'resourcebundle_count' => ['hasSideEffects' => false], 'resourcebundle_create' => ['hasSideEffects' => false], 'resourcebundle_get' => ['hasSideEffects' => false], 'resourcebundle_get_error_code' => ['hasSideEffects' => false], 'resourcebundle_get_error_message' => ['hasSideEffects' => false], 'resourcebundle_locales' => ['hasSideEffects' => false], 'rewind' => ['hasSideEffects' => true], 'rmdir' => ['hasSideEffects' => true], 'round' => ['hasSideEffects' => false], 'rtrim' => ['hasSideEffects' => false], 'sha1' => ['hasSideEffects' => false], 'sha1_file' => ['hasSideEffects' => false], 'sin' => ['hasSideEffects' => false], 'sinh' => ['hasSideEffects' => false], 'sizeof' => ['hasSideEffects' => false], 'soundex' => ['hasSideEffects' => false], 'spl_classes' => ['hasSideEffects' => false], 'spl_object_hash' => ['hasSideEffects' => false], 'sprintf' => ['hasSideEffects' => false], 'sqrt' => ['hasSideEffects' => false], 'stat' => ['hasSideEffects' => false], 'str_contains' => ['hasSideEffects' => false], 'str_decrement' => ['hasSideEffects' => false], 'str_ends_with' => ['hasSideEffects' => false], 'str_getcsv' => ['hasSideEffects' => false], 'str_increment' => ['hasSideEffects' => false], 'str_pad' => ['hasSideEffects' => false], 'str_repeat' => ['hasSideEffects' => false], 'str_rot13' => ['hasSideEffects' => false], 'str_split' => ['hasSideEffects' => false], 'str_starts_with' => ['hasSideEffects' => false], 'str_word_count' => ['hasSideEffects' => false], 'strcasecmp' => ['hasSideEffects' => false], 'strchr' => ['hasSideEffects' => false], 'strcmp' => ['hasSideEffects' => false], 'strcoll' => ['hasSideEffects' => false], 'strcspn' => ['hasSideEffects' => false], 'stream_get_filters' => ['hasSideEffects' => false], 'stream_get_transports' => ['hasSideEffects' => false], 'stream_get_wrappers' => ['hasSideEffects' => false], 'stream_is_local' => ['hasSideEffects' => false], 'stream_isatty' => ['hasSideEffects' => false], 'strip_tags' => ['hasSideEffects' => false], 'stripcslashes' => ['hasSideEffects' => false], 'stripos' => ['hasSideEffects' => false], 'stripslashes' => ['hasSideEffects' => false], 'stristr' => ['hasSideEffects' => false], 'strlen' => ['hasSideEffects' => false], 'strnatcasecmp' => ['hasSideEffects' => false], 'strnatcmp' => ['hasSideEffects' => false], 'strncasecmp' => ['hasSideEffects' => false], 'strncmp' => ['hasSideEffects' => false], 'strpbrk' => ['hasSideEffects' => false], 'strpos' => ['hasSideEffects' => false], 'strptime' => ['hasSideEffects' => false], 'strrchr' => ['hasSideEffects' => false], 'strrev' => ['hasSideEffects' => false], 'strripos' => ['hasSideEffects' => false], 'strrpos' => ['hasSideEffects' => false], 'strspn' => ['hasSideEffects' => false], 'strstr' => ['hasSideEffects' => false], 'strtolower' => ['hasSideEffects' => false], 'strtotime' => ['hasSideEffects' => false], 'strtoupper' => ['hasSideEffects' => false], 'strtr' => ['hasSideEffects' => false], 'strval' => ['hasSideEffects' => false], 'substr' => ['hasSideEffects' => false], 'substr_compare' => ['hasSideEffects' => false], 'substr_count' => ['hasSideEffects' => false], 'substr_replace' => ['hasSideEffects' => false], 'symlink' => ['hasSideEffects' => true], 'sys_getloadavg' => ['hasSideEffects' => false], 'tan' => ['hasSideEffects' => false], 'tanh' => ['hasSideEffects' => false], 'tempnam' => ['hasSideEffects' => true], 'timezone_abbreviations_list' => ['hasSideEffects' => false], 'timezone_identifiers_list' => ['hasSideEffects' => false], 'timezone_location_get' => ['hasSideEffects' => false], 'timezone_name_from_abbr' => ['hasSideEffects' => false], 'timezone_name_get' => ['hasSideEffects' => false], 'timezone_offset_get' => ['hasSideEffects' => false], 'timezone_open' => ['hasSideEffects' => false], 'timezone_transitions_get' => ['hasSideEffects' => false], 'timezone_version_get' => ['hasSideEffects' => false], 'tmpfile' => ['hasSideEffects' => true], 'token_get_all' => ['hasSideEffects' => false], 'token_name' => ['hasSideEffects' => false], 'touch' => ['hasSideEffects' => true], 'transliterator_create' => ['hasSideEffects' => false], 'transliterator_create_from_rules' => ['hasSideEffects' => false], 'transliterator_create_inverse' => ['hasSideEffects' => false], 'transliterator_get_error_code' => ['hasSideEffects' => false], 'transliterator_get_error_message' => ['hasSideEffects' => false], 'transliterator_list_ids' => ['hasSideEffects' => false], 'transliterator_transliterate' => ['hasSideEffects' => false], 'trim' => ['hasSideEffects' => false], 'ucfirst' => ['hasSideEffects' => false], 'ucwords' => ['hasSideEffects' => false], 'umask' => ['hasSideEffects' => true], 'unlink' => ['hasSideEffects' => true], 'unpack' => ['hasSideEffects' => false], 'urldecode' => ['hasSideEffects' => false], 'urlencode' => ['hasSideEffects' => false], 'utf8_decode' => ['hasSideEffects' => false], 'utf8_encode' => ['hasSideEffects' => false], 'vsprintf' => ['hasSideEffects' => false], 'wordwrap' => ['hasSideEffects' => false], 'xml_error_string' => ['hasSideEffects' => false], 'xml_get_current_byte_index' => ['hasSideEffects' => false], 'xml_get_current_column_number' => ['hasSideEffects' => false], 'xml_get_current_line_number' => ['hasSideEffects' => false], 'xml_get_error_code' => ['hasSideEffects' => false], 'xml_parser_create' => ['hasSideEffects' => false], 'xml_parser_create_ns' => ['hasSideEffects' => false], 'xml_parser_get_option' => ['hasSideEffects' => false], 'zend_version' => ['hasSideEffects' => false], 'zlib_decode' => ['hasSideEffects' => false], 'zlib_encode' => ['hasSideEffects' => false], 'zlib_get_coding_type' => ['hasSideEffects' => false], ]; ['bcadd' => ['numeric-string', 'left_operand' => 'numeric-string', 'right_operand' => 'numeric-string', 'scale=' => 'int'], 'bccomp' => ['int', 'left_operand' => 'numeric-string', 'right_operand' => 'numeric-string', 'scale=' => 'int'], 'bcdiv' => ['numeric-string|null', 'left_operand' => 'numeric-string', 'right_operand' => 'numeric-string', 'scale=' => 'int'], 'bcmod' => ['numeric-string|null', 'left_operand' => 'string', 'right_operand' => 'numeric-string', 'scale=' => 'int'], 'bcmul' => ['numeric-string', 'left_operand' => 'numeric-string', 'right_operand' => 'numeric-string', 'scale=' => 'int'], 'bcpow' => ['numeric-string', 'base' => 'numeric-string', 'exponent' => 'numeric-string', 'scale=' => 'int'], 'bcpowmod' => ['numeric-string|null', 'base' => 'numeric-string', 'exponent' => 'numeric-string', 'modulus' => 'string', 'scale=' => 'int'], 'bcsqrt' => ['numeric-string', 'operand' => 'numeric-string', 'scale=' => 'int'], 'bcsub' => ['numeric-string', 'left_operand' => 'numeric-string', 'right_operand' => 'numeric-string', 'scale=' => 'int'], 'Closure::bind' => ['Closure', 'old' => 'Closure', 'to' => '?object', 'scope=' => 'object|class-string|\'static\'|null'], 'Closure::bindTo' => ['Closure', 'new' => '?object', 'newscope=' => 'object|class-string|\'static\'|null'], 'error_log' => ['bool', 'message' => 'string', 'message_type=' => '0|1|2|3|4', 'destination=' => 'string', 'extra_headers=' => 'string'], 'SplFileObject::flock' => ['bool', 'operation' => 'int-mask', '&w_wouldblock=' => '0|1'], 'Imagick::adaptiveBlurImage' => ['bool', 'radius' => 'float', 'sigma' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::adaptiveSharpenImage' => ['bool', 'radius' => 'float', 'sigma' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::addNoiseImage' => ['bool', 'noise_type' => 'Imagick::NOISE_*', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::autoGammaImage' => ['bool', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::autoLevelImage' => ['bool', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::blurImage' => ['bool', 'radius' => 'float', 'sigma' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::brightnessContrastImage' => ['bool', 'brightness' => 'float', 'contrast' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::clampImage' => ['bool', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::combineImages' => ['Imagick', 'channeltype' => 'Imagick::CHANNEL_*'], 'Imagick::compareImageChannels' => ['array{Imagick,float}', 'image' => 'imagick', 'channeltype' => 'Imagick::CHANNEL_*', 'metrictype' => 'Imagick::METRIC_*'], 'Imagick::compareImageLayers' => ['Imagick', 'method' => 'Imagick::LAYERMETHOD_*'], 'Imagick::compareImages' => ['array{Imagick,float}', 'compare' => 'imagick', 'metric' => 'Imagick::METRIC_*'], 'Imagick::compositeImage' => ['bool', 'composite_object' => 'imagick', 'composite' => 'Imagick::COMPOSITE_*', 'x' => 'int', 'y' => 'int', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::contrastStretchImage' => ['bool', 'black_point' => 'float', 'white_point' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::convolveImage' => ['bool', 'kernel' => 'array', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::distortImage' => ['bool', 'method' => 'Imagick::DISTORTION_*', 'arguments' => 'array', 'bestfit' => 'bool'], 'Imagick::evaluateImage' => ['bool', 'op' => 'Imagick::EVALUATE_*', 'constant' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::exportImagePixels' => ['list', 'x' => 'int', 'y' => 'int', 'width' => 'int', 'height' => 'int', 'map' => 'string', 'storage' => 'Imagick::PIXEL_*'], 'Imagick::floodFillPaintImage' => ['bool', 'fill' => 'mixed', 'fuzz' => 'float', 'target' => 'mixed', 'x' => 'int', 'y' => 'int', 'invert' => 'bool', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::functionImage' => ['bool', 'function' => 'Imagick::FUNCTION_*', 'arguments' => 'array', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::fxImage' => ['Imagick', 'expression' => 'string', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::gammaImage' => ['bool', 'gamma' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::gaussianBlurImage' => ['bool', 'radius' => 'float', 'sigma' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::getImageChannelDepth' => ['int', 'channel' => 'Imagick::CHANNEL_*'], 'Imagick::getImageChannelDistortion' => ['float', 'reference' => 'imagick', 'channel' => 'Imagick::CHANNEL_*', 'metric' => 'Imagick::METRIC_*'], 'Imagick::getImageChannelDistortions' => ['float', 'reference' => 'imagick', 'metric' => 'Imagick::METRIC_*', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::getImageChannelExtrema' => ['array{minima:0|positive-int,maxima:0|positive-int}', 'channel' => 'Imagick::CHANNEL_*'], 'Imagick::getImageChannelKurtosis' => ['array{kurtosis:float,skewness:float}', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::getImageChannelMean' => ['array{mean:float,standardDeviation:float}', 'channel' => 'Imagick::CHANNEL_*'], 'Imagick::getImageChannelRange' => ['array{minima:float,maxima:float}', 'channel' => 'Imagick::CHANNEL_*'], 'Imagick::getImageDistortion' => ['float', 'reference' => 'magickwand', 'metric' => 'Imagick::METRIC_*'], 'Imagick::getResource' => ['int', 'type' => 'Imagick::RESOURCETYPE_*'], 'Imagick::getResourceLimit' => ['int', 'type' => 'Imagick::RESOURCETYPE_*'], 'Imagick::importImagePixels' => ['bool', 'x' => 'int', 'y' => 'int', 'width' => 'int', 'height' => 'int', 'map' => 'string', 'storage' => 'Imagick::PIXEL_*', 'pixels' => 'array'], 'Imagick::levelImage' => ['bool', 'blackpoint' => 'float', 'gamma' => 'float', 'whitepoint' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::mergeImageLayers' => ['Imagick', 'layer_method' => 'Imagick::LAYERMETHOD_*'], 'Imagick::montageImage' => ['Imagick', 'draw' => 'imagickdraw', 'tile_geometry' => 'string', 'thumbnail_geometry' => 'string', 'mode' => 'Imagick::MONTAGEMODE_*', 'frame' => 'string'], 'Imagick::morphology' => ['bool', 'morphologyMethod' => 'Imagick::MORPHOLOGY_*', 'iterations' => 'int', 'ImagickKernel' => 'ImagickKernel', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::motionBlurImage' => ['bool', 'radius' => 'float', 'sigma' => 'float', 'angle' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::negateImage' => ['bool', 'gray' => 'bool', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::normalizeImage' => ['bool', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::opaquePaintImage' => ['bool', 'target' => 'mixed', 'fill' => 'mixed', 'fuzz' => 'float', 'invert' => 'bool', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::orderedPosterizeImage' => ['bool', 'threshold_map' => 'string', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::paintFloodfillImage' => ['bool', 'fill' => 'mixed', 'fuzz' => 'float', 'bordercolor' => 'mixed', 'x' => 'int', 'y' => 'int', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::paintOpaqueImage' => ['bool', 'target' => 'mixed', 'fill' => 'mixed', 'fuzz' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::radialBlurImage' => ['bool', 'angle' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::randomThresholdImage' => ['bool', 'low' => 'float', 'high' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::remapImage' => ['bool', 'replacement' => 'imagick', 'dither' => 'Imagick::DITHERMETHOD_*'], 'Imagick::rotationalBlurImage' => ['bool', 'float' => 'string', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::segmentImage' => ['bool', 'colorspace' => 'Imagick::COLORSPACE_*', 'cluster_threshold' => 'float', 'smooth_threshold' => 'float', 'verbose=' => 'bool'], 'Imagick::selectiveBlurImage' => ['bool', 'radius' => 'float', 'sigma' => 'float', 'threshold' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::separateImageChannel' => ['bool', 'channel' => 'Imagick::CHANNEL_*'], 'Imagick::setColorspace' => ['bool', 'colorspace' => 'Imagick::COLORSPACE_*'], 'Imagick::setCompression' => ['bool', 'compression' => 'Imagick::COMPRESSION_*'], 'Imagick::setGravity' => ['bool', 'gravity' => 'Imagick::GRAVITY_*'], 'Imagick::setImageAlphaChannel' => ['bool', 'mode' => 'Imagick::ALPHACHANNEL_*'], 'Imagick::setImageChannelDepth' => ['bool', 'channel' => 'Imagick::CHANNEL_*', 'depth' => 'int'], 'Imagick::setImageChannelMask' => ['', 'channel' => 'Imagick::CHANNEL_*'], 'Imagick::setImageClipMask' => ['bool', 'clip_mask' => 'imagick'], 'Imagick::setImageColormapColor' => ['bool', 'index' => 'int', 'color' => 'imagickpixel'], 'Imagick::setImageColorspace' => ['bool', 'colorspace' => 'Imagick::COLORSPACE_*'], 'Imagick::setImageCompose' => ['bool', 'compose' => 'Imagick::COMPOSITE_*'], 'Imagick::setImageCompression' => ['bool', 'compression' => 'Imagick::COMPRESSION_*'], 'Imagick::setImageDispose' => ['bool', 'dispose' => 'Imagick::DISPOSE_*'], 'Imagick::setImageGravity' => ['bool', 'gravity' => 'Imagick::GRAVITY_*'], 'Imagick::setImageInterlaceScheme' => ['bool', 'interlace_scheme' => 'Imagick::INTERLACE_*'], 'Imagick::setImageInterpolateMethod' => ['bool', 'method' => 'Imagick::INTERPOLATE_*'], 'Imagick::setImageOrientation' => ['bool', 'orientation' => 'Imagick::ORIENTATION_*'], 'Imagick::setImageRenderingIntent' => ['bool', 'rendering_intent' => 'Imagick::RENDERINGINTENT_*'], 'Imagick::setImageType' => ['bool', 'image_type' => 'Imagick::IMGTYPE_*'], 'Imagick::setType' => ['bool', 'image_type' => 'Imagick::IMGTYPE_*'], 'Imagick::sharpenImage' => ['bool', 'radius' => 'float', 'sigma' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::sigmoidalContrastImage' => ['bool', 'sharpen' => 'bool', 'alpha' => 'float', 'beta' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::similarityImage' => ['Imagick', 'imagick' => 'Imagick', '&bestMatch' => 'array', '&similarity' => 'float', 'similarity_threshold' => 'float', 'metric' => 'Imagick::METRIC_*'], 'Imagick::sparseColorImage' => ['bool', 'sparse_method' => 'Imagick::SPARSECOLORMETHOD_*', 'arguments' => 'array', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::statisticImage' => ['bool', 'type' => 'Imagick::STATISTIC_*', 'width' => 'int', 'height' => 'int', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::thresholdImage' => ['bool', 'threshold' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'Imagick::transformImageColorspace' => ['bool', 'colorspace' => 'Imagick::COLORSPACE_*'], 'Imagick::unsharpMaskImage' => ['bool', 'radius' => 'float', 'sigma' => 'float', 'amount' => 'float', 'threshold' => 'float', 'channel=' => 'Imagick::CHANNEL_*'], 'ImagickDraw::color' => ['bool', 'x' => 'float', 'y' => 'float', 'paintmethod' => 'Imagick::PAINT_*'], 'ImagickDraw::composite' => ['bool', 'compose' => 'Imagick::COMPOSITE_*', 'x' => 'float', 'y' => 'float', 'width' => 'float', 'height' => 'float', 'compositewand' => 'imagick'], 'ImagickDraw::getFillRule' => ['Imagick::FILLRULE_*'], 'ImagickDraw::getFontStretch' => ['Imagick::STRETCH_*'], 'ImagickDraw::getFontStyle' => ['Imagick::STYLE_*'], 'ImagickDraw::getGravity' => ['Imagick::GRAVITY_*'], 'ImagickDraw::getStrokeLineCap' => ['Imagick::LINECAP_*'], 'ImagickDraw::getStrokeLineJoin' => ['Imagick::LINEJOIN_*'], 'ImagickDraw::getTextAlignment' => ['Imagick::ALIGN_*'], 'ImagickDraw::getTextDecoration' => ['Imagick::DECORATION_*'], 'ImagickDraw::matte' => ['bool', 'x' => 'float', 'y' => 'float', 'paintmethod' => 'Imagick::PAINT_*'], 'ImagickDraw::setClipRule' => ['bool', 'fill_rule' => 'Imagick::FILLRULE_*'], 'ImagickDraw::setFillRule' => ['bool', 'fill_rule' => 'Imagick::FILLRULE_*'], 'ImagickDraw::setFontStretch' => ['bool', 'fontstretch' => 'Imagick::STRETCH_*'], 'ImagickDraw::setFontStyle' => ['bool', 'style' => 'Imagick::STYLE_*'], 'ImagickDraw::setGravity' => ['bool', 'gravity' => 'Imagick::GRAVITY_*'], 'ImagickDraw::setStrokeLineCap' => ['bool', 'linecap' => 'Imagick::LINECAP_*'], 'ImagickDraw::setStrokeLineJoin' => ['bool', 'linejoin' => 'Imagick::LINEJOIN_*'], 'ImagickDraw::setTextAlignment' => ['bool', 'alignment' => 'Imagick::ALIGN_*'], 'ImagickDraw::setTextAntialias' => ['bool', 'antialias' => 'bool'], 'ImagickDraw::setTextDecoration' => ['bool', 'decoration' => 'Imagick::DECORATION_*'], 'ImagickKernel::fromBuiltin' => ['ImagickKernel', 'kernelType' => 'Imagick::KERNEL_*', 'kernelString' => 'string'], 'ImagickKernel::scale' => ['void', 'scale' => 'float', 'normalizeFlag' => 'Imagick::NORMALIZE_KERNEL_*'], 'imagecolorallocate' => ['int<0, max>|false', 'im' => 'resource', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>'], 'imagecolorallocatealpha' => ['int<0, max>|false', 'im' => 'resource', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>', 'alpha' => 'int<0, 127>'], 'imagecolorclosest' => ['int<0, max>', 'im' => 'resource', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>'], 'imagecolorclosestalpha' => ['int<0, max>', 'im' => 'resource', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>', 'alpha' => 'int<0, 127>'], 'imagecolorclosesthwb' => ['int<0, max>', 'im' => 'resource', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>'], 'imagecolorexact' => ['int<0, max>|false', 'im' => 'resource', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>'], 'imagecolorexactalpha' => ['int<0, max>|false', 'im' => 'resource', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>', 'alpha' => 'int<0, 127>'], 'imagecolorresolve' => ['int<0, max>', 'im' => 'resource', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>'], 'imagecolorresolvealpha' => ['int<0, max>', 'im' => 'resource', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>', 'alpha' => 'int<0, 127>'], 'imagecolorset' => ['void', 'im' => 'resource', 'col' => 'int', 'red' => 'int<0, 255>', 'green' => 'int<0, 255>', 'blue' => 'int<0, 255>', 'alpha=' => 'int<0, 127>'], 'imagecreate' => ['__benevolent', 'x_size' => 'int<1, max>', 'y_size' => 'int<1, max>'], 'imagecreatetruecolor' => ['__benevolent', 'x_size' => 'int<1, max>', 'y_size' => 'int<1, max>'], 'max' => ['', '...arg1' => 'non-empty-array'], 'mb_detect_order' => ['bool|list', 'encoding_list=' => 'non-empty-list|non-falsy-string'], 'min' => ['', '...arg1' => 'non-empty-array'], 'file' => ['list|false', 'filename' => 'string', 'flags=' => 'int-mask', 'context=' => 'resource'], 'flock' => ['bool', 'fp' => 'resource', 'operation' => 'int-mask', '&w_wouldblock=' => '0|1'], 'ftp_append' => ['bool', 'ftp' => 'resource', 'remote_file' => 'string', 'local_file' => 'string', 'mode=' => 'FTP_ASCII|FTP_BINARY'], 'ftp_fget' => ['bool', 'stream' => 'resource', 'fp' => 'resource', 'remote_file' => 'string', 'mode=' => 'FTP_ASCII|FTP_BINARY', 'resumepos=' => 'int'], 'ftp_fput' => ['bool', 'stream' => 'resource', 'remote_file' => 'string', 'fp' => 'resource', 'mode=' => 'FTP_ASCII|FTP_BINARY', 'startpos=' => 'int'], 'ftp_get' => ['bool', 'stream' => 'resource', 'local_file' => 'string', 'remote_file' => 'string', 'mode=' => 'FTP_ASCII|FTP_BINARY', 'resume_pos=' => 'int'], 'ftp_nb_fget' => ['int', 'stream' => 'resource', 'fp' => 'resource', 'remote_file' => 'string', 'mode=' => 'FTP_ASCII|FTP_BINARY', 'resumepos=' => 'int'], 'ftp_nb_fput' => ['int', 'stream' => 'resource', 'remote_file' => 'string', 'fp' => 'resource', 'mode=' => 'FTP_ASCII|FTP_BINARY', 'startpos=' => 'int'], 'ftp_nb_get' => ['int|false', 'stream' => 'resource', 'local_file' => 'string', 'remote_file' => 'string', 'mode=' => 'FTP_ASCII|FTP_BINARY', 'resume_pos=' => 'int'], 'ftp_nb_put' => ['int|false', 'stream' => 'resource', 'remote_file' => 'string', 'local_file' => 'string', 'mode=' => 'FTP_ASCII|FTP_BINARY', 'startpos=' => 'int'], 'ftp_put' => ['bool', 'stream' => 'resource', 'remote_file' => 'string', 'local_file' => 'string', 'mode=' => 'FTP_ASCII|FTP_BINARY', 'startpos=' => 'int'], 'scandir' => ['list|false', 'dir' => 'string', 'sorting_order=' => 'SCANDIR_SORT_ASCENDING|SCANDIR_SORT_DESCENDING| SCANDIR_SORT_NONE', 'context=' => 'resource'], 'stream_socket_client' => ['resource|false', 'remoteaddress' => 'string', '&w_errcode=' => 'int', '&w_errstring=' => 'string', 'timeout=' => 'float', 'flags=' => 'int-mask', 'context=' => 'resource'], 'stream_socket_enable_crypto' => ['0|bool', 'stream' => 'resource', 'enable' => 'bool', 'crypto_method=' => 'STREAM_CRYPTO_METHOD_SSLv2_CLIENT|STREAM_CRYPTO_METHOD_SSLv3_CLIENT|STREAM_CRYPTO_METHOD_SSLv23_CLIENT|STREAM_CRYPTO_METHOD_ANY_CLIENT|STREAM_CRYPTO_METHOD_TLS_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT|STREAM_CRYPTO_METHOD_SSLv2_SERVER|STREAM_CRYPTO_METHOD_SSLv3_SERVER|STREAM_CRYPTO_METHOD_SSLv23_SERVER|STREAM_CRYPTO_METHOD_ANY_SERVER|STREAM_CRYPTO_METHOD_TLS_SERVER|STREAM_CRYPTO_METHOD_TLSv1_0_SERVER|STREAM_CRYPTO_METHOD_TLSv1_1_SERVER|STREAM_CRYPTO_METHOD_TLSv1_2_SERVER|STREAM_CRYPTO_METHOD_TLSv1_3_SERVER', 'session_stream=' => 'resource'], 'extract' => ['0|positive-int', 'array' => 'array', 'flags=' => 'EXTR_OVERWRITE|EXTR_SKIP|EXTR_PREFIX_SAME|EXTR_PREFIX_ALL|EXTR_PREFIX_INVALID|EXTR_IF_EXISTS|EXTR_PREFIX_IF_EXISTS|EXTR_REFS', 'prefix=' => 'string|null'], 'RecursiveIteratorIterator::__construct' => ['void', 'iterator' => 'RecursiveIterator|IteratorAggregate', 'mode=' => 'RecursiveIteratorIterator::LEAVES_ONLY|RecursiveIteratorIterator::SELF_FIRST|RecursiveIteratorIterator::CHILD_FIRST', 'flags=' => '0|RecursiveIteratorIterator::CATCH_GET_CHILD'], 'Locale::composeLocale' => ['string|false', 'subtags' => 'array{language:string, script?:string, region?:string, variant?:array, private?:array, extlang?:array, variant0?:string, variant1?:string, variant2?:string, variant3?:string, variant4?:string, variant5?:string, variant6?:string, variant7?:string, variant8?:string, variant9?:string, variant10?:string, variant11?:string, variant12?:string, variant13?:string, variant14?:string, private0?:string, private1?:string, private2?:string, private3?:string, private4?:string, private5?:string, private6?:string, private7?:string, private8?:string, private9?:string, private10?:string, private11?:string, private12?:string, private13?:string, private14?:string, extlang0?:string, extlang1?:string, extlang2?:string}'], 'locale_compose' => ['string|false', 'subtags' => 'array{language:string, script?:string, region?:string, variant?:array, private?:array, extlang?:array, variant0?:string, variant1?:string, variant2?:string, variant3?:string, variant4?:string, variant5?:string, variant6?:string, variant7?:string, variant8?:string, variant9?:string, variant10?:string, variant11?:string, variant12?:string, variant13?:string, variant14?:string, private0?:string, private1?:string, private2?:string, private3?:string, private4?:string, private5?:string, private6?:string, private7?:string, private8?:string, private9?:string, private10?:string, private11?:string, private12?:string, private13?:string, private14?:string, extlang0?:string, extlang1?:string, extlang2?:string}'], 'count' => ['0|positive-int', 'var' => 'Countable|array', 'mode=' => '0|1']], 'old' => []]; ['mysqli_fetch_field' => ['(stdClass&object{name: string, orgname: string, table: string, orgtable: string, def: string, db: string, catalog: "def", max_length: 0, length: int, charsetnr: string, flags: int, type: int, decimals: int})|false', 'result' => 'mysqli_result'], 'mysqli_fetch_field_direct' => ['(stdClass&object{name: string, orgname: string, table: string, orgtable: string, def: string, db: string, catalog: "def", max_length: 0, length: int, charsetnr: string, flags: int, type: int, decimals: int})|false', 'result' => 'mysqli_result', 'fieldnr' => 'int'], 'mysqli_fetch_fields' => ['list', 'result' => 'mysqli_result'], 'mysqli_result::fetch_field' => ['(stdClass&object{name: string, orgname: string, table: string, orgtable: string, def: string, db: string, catalog: "def", max_length: 0, length: int, charsetnr: string, flags: int, type: int, decimals: int})|false'], 'mysqli_result::fetch_field_direct' => ['(stdClass&object{name: string, orgname: string, table: string, orgtable: string, def: string, db: string, catalog: "def", max_length: 0, length: int, charsetnr: string, flags: int, type: int, decimals: int})|false', 'fieldnr' => 'int'], 'mysqli_result::fetch_fields' => ['list'], 'UnitEnum::cases' => ['list']], 'old' => ['pg_escape_bytea' => ['string', 'connection' => 'resource', 'data' => 'string'], 'pg_escape_bytea\'1' => ['string', 'data' => 'string'], 'pg_escape_identifier' => ['string|false', 'connection' => 'resource', 'data' => 'string'], 'pg_escape_identifier\'1' => ['string', 'data' => 'string'], 'pg_escape_literal' => ['string|false', 'connection' => 'resource', 'data' => 'string'], 'pg_escape_literal\'1' => ['string', 'data' => 'string'], 'pg_escape_string' => ['string', 'connection' => 'resource', 'data' => 'string'], 'pg_escape_string\'1' => ['string', 'data' => 'string'], 'pg_execute' => ['resource|false', 'connection' => 'resource', 'stmtname' => 'string', 'params' => 'array'], 'pg_execute\'1' => ['resource|false', 'stmtname' => 'string', 'params' => 'array'], 'pg_fetch_object' => ['object|false', 'result' => '', 'row=' => '?int', 'result_type=' => 'int'], 'pg_fetch_object\'1' => ['object', 'result' => '', 'row=' => '?int', 'class_name=' => 'string', 'ctor_params=' => 'array'], 'pg_fetch_result' => ['', 'result' => '', 'field_name' => 'string|int'], 'pg_fetch_result\'1' => ['', 'result' => '', 'row_number' => 'int', 'field_name' => 'string|int'], 'pg_field_is_null' => ['int|false', 'result' => '', 'field_name_or_number' => 'string|int'], 'pg_field_is_null\'1' => ['int', 'result' => '', 'row' => 'int', 'field_name_or_number' => 'string|int'], 'pg_field_prtlen' => ['int|false', 'result' => '', 'field_name_or_number' => ''], 'pg_field_prtlen\'1' => ['int', 'result' => '', 'row' => 'int', 'field_name_or_number' => 'string|int'], 'pg_lo_export' => ['bool', 'connection' => 'resource', 'oid' => 'int', 'filename' => 'string'], 'pg_lo_export\'1' => ['bool', 'oid' => 'int', 'pathname' => 'string'], 'pg_lo_import' => ['int|false', 'connection' => 'resource', 'pathname' => 'string', 'oid' => ''], 'pg_lo_import\'1' => ['int', 'pathname' => 'string', 'oid' => ''], 'pg_parameter_status' => ['string|false', 'connection' => 'resource', 'param_name' => 'string'], 'pg_parameter_status\'1' => ['string|false', 'param_name' => 'string'], 'pg_prepare' => ['resource|false', 'connection' => 'resource', 'stmtname' => 'string', 'query' => 'string'], 'pg_prepare\'1' => ['resource|false', 'stmtname' => 'string', 'query' => 'string'], 'pg_put_line' => ['bool', 'connection' => 'resource', 'data' => 'string'], 'pg_put_line\'1' => ['bool', 'data' => 'string'], 'pg_query' => ['resource|false', 'connection' => 'resource', 'query' => 'string'], 'pg_query\'1' => ['resource|false', 'query' => 'string'], 'pg_query_params' => ['resource|false', 'connection' => 'resource', 'query' => 'string', 'params' => 'array'], 'pg_query_params\'1' => ['resource|false', 'query' => 'string', 'params' => 'array'], 'pg_set_client_encoding' => ['int', 'connection' => 'resource', 'encoding' => 'string'], 'pg_set_client_encoding\'1' => ['int', 'encoding' => 'string'], 'pg_set_error_verbosity' => ['int|false', 'connection' => 'resource', 'verbosity' => 'int'], 'pg_set_error_verbosity\'1' => ['int', 'verbosity' => 'int'], 'pg_tty' => ['string', 'connection=' => 'resource'], 'pg_tty\'1' => ['string'], 'pg_untrace' => ['bool', 'connection=' => 'resource'], 'pg_untrace\'1' => ['bool']]]; path = $path; } } container = $container; } public function getRegistry() : OperatorTypeSpecifyingExtensionRegistry { if ($this->registry === null) { $this->registry = new OperatorTypeSpecifyingExtensionRegistry($this->container->getByType(Broker::class), $this->container->getServicesByTag(BrokerFactory::OPERATOR_TYPE_SPECIFYING_EXTENSION_TAG)); } return $this->registry; } } container = $container; } public function getFunctionParameterClosureTypeExtensions() : array { return $this->container->getServicesByTag(self::FUNCTION_TAG); } public function getMethodParameterClosureTypeExtensions() : array { return $this->container->getServicesByTag(self::METHOD_TAG); } public function getStaticMethodParameterClosureTypeExtensions() : array { return $this->container->getServicesByTag(self::STATIC_METHOD_TAG); } } container = $container; } public function getDynamicFunctionThrowTypeExtensions() : array { return $this->container->getServicesByTag(self::FUNCTION_TAG); } public function getDynamicMethodThrowTypeExtensions() : array { return $this->container->getServicesByTag(self::METHOD_TAG); } public function getDynamicStaticMethodThrowTypeExtensions() : array { return $this->container->getServicesByTag(self::STATIC_METHOD_TAG); } } container = $container; } public function getFunctionParameterOutTypeExtensions() : array { return $this->container->getServicesByTag(self::FUNCTION_TAG); } public function getMethodParameterOutTypeExtensions() : array { return $this->container->getServicesByTag(self::METHOD_TAG); } public function getStaticMethodParameterOutTypeExtensions() : array { return $this->container->getServicesByTag(self::STATIC_METHOD_TAG); } } container = $container; } public function getRegistry() : ExpressionTypeResolverExtensionRegistry { if ($this->registry === null) { $this->registry = new ExpressionTypeResolverExtensionRegistry($this->container->getServicesByTag(BrokerFactory::EXPRESSION_TYPE_RESOLVER_EXTENSION_TAG)); } return $this->registry; } } container = $container; } public function getRegistry() : DynamicReturnTypeExtensionRegistry { if ($this->registry === null) { $this->registry = new DynamicReturnTypeExtensionRegistry($this->container->getByType(Broker::class), $this->container->getByType(ReflectionProvider::class), $this->container->getServicesByTag(BrokerFactory::DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG), $this->container->getServicesByTag(BrokerFactory::DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG), $this->container->getServicesByTag(BrokerFactory::DYNAMIC_FUNCTION_RETURN_TYPE_EXTENSION_TAG)); } return $this->registry; } } process((array) Neon::decode($contents), '', $file); } catch (Exception $e) { throw new Exception(sprintf('Error while loading %s: %s', $file, $e->getMessage())); } } /** * @param mixed[] $arr * @return mixed[] */ public function process(array $arr, string $fileKey, string $file) : array { $res = []; foreach ($arr as $key => $val) { if (is_string($key) && substr($key, -1) === self::PREVENT_MERGING_SUFFIX) { if (!is_array($val) && $val !== null) { throw new InvalidConfigurationException(sprintf('Replacing operator is available only for arrays, item \'%s\' is not array.', $key)); } $key = substr($key, 0, -1); $val[Helpers::PREVENT_MERGING] = \true; } $keyToResolve = $fileKey; if (is_int($key)) { $keyToResolve .= '[]'; } else { $keyToResolve .= '[' . $key . ']'; } if (is_array($val)) { if (!is_int($key)) { $fileKeyToPass = $fileKey . '[' . $key . ']'; } else { $fileKeyToPass = $fileKey . '[]'; } $val = $this->process($val, $fileKeyToPass, $file); } elseif ($val instanceof Entity) { if (!is_int($key)) { $fileKeyToPass = $fileKey . '(' . $key . ')'; } else { $fileKeyToPass = $fileKey . '()'; } if ($val->value === Neon::CHAIN) { $tmp = null; foreach ($this->process($val->attributes, $fileKeyToPass, $file) as $st) { $tmp = new Statement($tmp === null ? $st->getEntity() : [$tmp, ltrim(implode('::', (array) $st->getEntity()), ':')], $st->arguments); } $val = $tmp; } else { if (in_array($keyToResolve, ['[parameters][excludePaths][]', '[parameters][excludePaths][analyse][]', '[parameters][excludePaths][analyseAndScan][]'], \true) && count($val->attributes) === 1 && $val->attributes[0] === '?' && is_string($val->value) && !str_contains($val->value, '%') && !str_starts_with($val->value, '*')) { $fileHelper = $this->createFileHelperByFile($file); $val = new OptionalPath($fileHelper->normalizePath($fileHelper->absolutizePath($val->value))); } else { $tmp = $this->process([$val->value], $fileKeyToPass, $file); $val = new Statement($tmp[0], $this->process($val->attributes, $fileKeyToPass, $file)); } } } if (in_array($keyToResolve, ['[parameters][paths][]', '[parameters][excludes_analyse][]', '[parameters][excludePaths][]', '[parameters][excludePaths][analyse][]', '[parameters][excludePaths][analyseAndScan][]', '[parameters][ignoreErrors][][paths][]', '[parameters][ignoreErrors][][path]', '[parameters][bootstrapFiles][]', '[parameters][scanFiles][]', '[parameters][scanDirectories][]', '[parameters][tmpDir]', '[parameters][pro][tmpDir]', '[parameters][memoryLimitFile]', '[parameters][benchmarkFile]', '[parameters][stubFiles][]', '[parameters][symfony][console_application_loader]', '[parameters][symfony][consoleApplicationLoader]', '[parameters][symfony][container_xml_path]', '[parameters][symfony][containerXmlPath]', '[parameters][doctrine][objectManagerLoader]'], \true) && is_string($val) && !str_contains($val, '%') && !str_starts_with($val, '*')) { $fileHelper = $this->createFileHelperByFile($file); $val = $fileHelper->normalizePath($fileHelper->absolutizePath($val)); } if ($keyToResolve === '[parameters][excludePaths]' && $val !== null && array_values($val) === $val) { $val = ['analyseAndScan' => $val, 'analyse' => []]; } $res[$key] = $val; } return $res; } /** * @param mixed[] $data */ public function dump(array $data) : string { array_walk_recursive($data, static function (&$val) : void { if (!$val instanceof Statement) { return; } $val = self::statementToEntity($val); }); return "# generated by Nette\n\n" . Neon::encode($data, Neon::BLOCK); } private static function statementToEntity(Statement $val) : Entity { array_walk_recursive($val->arguments, static function (&$val) : void { if ($val instanceof Statement) { $val = self::statementToEntity($val); } elseif ($val instanceof Reference) { $val = '@' . $val->getValue(); } }); $entity = $val->getEntity(); if ($entity instanceof Reference) { $entity = '@' . $entity->getValue(); } elseif (is_array($entity)) { if ($entity[0] instanceof Statement) { return new Entity(Neon::CHAIN, [self::statementToEntity($entity[0]), new Entity('::' . $entity[1], $val->arguments)]); } elseif ($entity[0] instanceof Reference) { $entity = '@' . $entity[0]->getValue() . '::' . $entity[1]; } elseif (is_string($entity[0])) { $entity = $entity[0] . '::' . $entity[1]; } } return new Entity($entity, $val->arguments); } private function createFileHelperByFile(string $file) : FileHelper { $dir = dirname($file); if (!isset($this->fileHelpers[$dir])) { $this->fileHelpers[$dir] = new FileHelper($dir); } return $this->fileHelpers[$dir]; } } $bool, BrokerFactory::METHODS_CLASS_REFLECTION_EXTENSION_TAG => $bool, BrokerFactory::DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG => $bool, BrokerFactory::DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG => $bool, BrokerFactory::DYNAMIC_FUNCTION_RETURN_TYPE_EXTENSION_TAG => $bool, BrokerFactory::EXPRESSION_TYPE_RESOLVER_EXTENSION_TAG => $bool, BrokerFactory::OPERATOR_TYPE_SPECIFYING_EXTENSION_TAG => $bool, BrokerFactory::ALLOWED_SUB_TYPES_CLASS_REFLECTION_EXTENSION_TAG => $bool, LazyRegistry::RULE_TAG => $bool, TypeNodeResolverExtension::EXTENSION_TAG => $bool, StubFilesExtension::EXTENSION_TAG => $bool, AlwaysUsedClassConstantsExtensionProvider::EXTENSION_TAG => $bool, ReadWritePropertiesExtensionProvider::EXTENSION_TAG => $bool, TypeSpecifierFactory::FUNCTION_TYPE_SPECIFYING_EXTENSION_TAG => $bool, TypeSpecifierFactory::METHOD_TYPE_SPECIFYING_EXTENSION_TAG => $bool, TypeSpecifierFactory::STATIC_METHOD_TYPE_SPECIFYING_EXTENSION_TAG => $bool, RichParser::VISITOR_SERVICE_TAG => $bool, CollectorRegistryFactory::COLLECTOR_TAG => $bool, LazyDynamicThrowTypeExtensionProvider::FUNCTION_TAG => $bool, LazyDynamicThrowTypeExtensionProvider::METHOD_TAG => $bool, LazyDynamicThrowTypeExtensionProvider::STATIC_METHOD_TAG => $bool, LazyParameterClosureTypeExtensionProvider::FUNCTION_TAG => $bool, LazyParameterClosureTypeExtensionProvider::METHOD_TAG => $bool, LazyParameterClosureTypeExtensionProvider::STATIC_METHOD_TAG => $bool, LazyParameterOutTypeExtensionProvider::FUNCTION_TAG => $bool, LazyParameterOutTypeExtensionProvider::METHOD_TAG => $bool, LazyParameterOutTypeExtensionProvider::STATIC_METHOD_TAG => $bool, DiagnoseExtension::EXTENSION_TAG => $bool])->min(1)); } public function beforeCompile() : void { /** @var mixed[] $config */ $config = $this->config; $builder = $this->getContainerBuilder(); foreach ($config as $type => $tags) { $services = $builder->findByType($type); if (count($services) === 0) { throw new ShouldNotHappenException(sprintf('No services of type "%s" found.', $type)); } foreach ($services as $service) { foreach ($tags as $tag => $parameter) { if (is_array($parameter)) { $parameter = array_reduce($parameter, static function ($carry, $item) { return $carry && (bool) $item; }, \true); } if ((bool) $parameter) { $service->addTag($tag); continue; } } } } } } currentWorkingDirectory = $currentWorkingDirectory; $this->tempDirectory = $tempDirectory; $this->additionalConfigFiles = $additionalConfigFiles; $this->analysedPaths = $analysedPaths; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; $this->analysedPathsFromConfig = $analysedPathsFromConfig; $this->usedLevel = $usedLevel; $this->generateBaselineFile = $generateBaselineFile; $this->cliAutoloadFile = $cliAutoloadFile; $this->singleReflectionFile = $singleReflectionFile; $this->singleReflectionInsteadOfFile = $singleReflectionInsteadOfFile; } /** * @param string[] $additionalConfigFiles */ public function create(array $additionalConfigFiles) : \PHPStan\DependencyInjection\Container { $containerFactory = new \PHPStan\DependencyInjection\ContainerFactory($this->currentWorkingDirectory); return $containerFactory->create($this->tempDirectory, array_merge($this->additionalConfigFiles, $additionalConfigFiles), $this->analysedPaths, $this->composerAutoloaderProjectPaths, $this->analysedPathsFromConfig, $this->usedLevel, $this->generateBaselineFile, $this->cliAutoloadFile, $this->singleReflectionFile, $this->singleReflectionInsteadOfFile); } } container = $container; } public function hasService(string $serviceName) : bool { return $this->container->hasService($serviceName); } /** * @return mixed */ public function getService(string $serviceName) { return $this->container->getService($serviceName); } /** * @template T of object * @param class-string $className * @return T */ public function getByType(string $className) { return $this->container->getByType($className); } /** * @param class-string $className * @return string[] */ public function findServiceNamesByType(string $className) : array { return $this->container->findByType($className); } /** * @return mixed[] */ public function getServicesByTag(string $tagName) : array { return $this->tagsToServices($this->container->findByTag($tagName)); } /** * @return mixed[] */ public function getParameters() : array { return $this->container->getParameters(); } public function hasParameter(string $parameterName) : bool { return array_key_exists($parameterName, $this->container->getParameters()); } /** * @return mixed */ public function getParameter(string $parameterName) { if (!$this->hasParameter($parameterName)) { throw new ParameterNotFoundException($parameterName); } return $this->container->getParameter($parameterName); } /** * @param mixed[] $tags * @return mixed[] */ private function tagsToServices(array $tags) : array { return array_map(function (string $serviceName) { return $this->getService($serviceName); }, array_keys($tags)); } } fileHelper = $fileHelper; $this->rootDir = $rootDir; $this->currentWorkingDirectory = $currentWorkingDirectory; $this->generateBaselineFile = $generateBaselineFile; } public function createLoader() : Loader { $loader = new \PHPStan\DependencyInjection\NeonLoader($this->fileHelper, $this->generateBaselineFile); $loader->addAdapter('dist', \PHPStan\DependencyInjection\NeonAdapter::class); $loader->addAdapter('neon', \PHPStan\DependencyInjection\NeonAdapter::class); $loader->setParameters(['rootDir' => $this->rootDir, 'currentWorkingDirectory' => $this->currentWorkingDirectory, 'env' => getenv()]); return $loader; } } files = $files; parent::__construct(sprintf('These files are included multiple times: %s', implode(', ', $this->files))); } /** * @return string[] */ public function getFiles() : array { return $this->files; } } container = $container; } public function getRegistry() : ClassReflectionExtensionRegistry { if ($this->registry === null) { $phpClassReflectionExtension = $this->container->getByType(PhpClassReflectionExtension::class); $annotationsMethodsClassReflectionExtension = $this->container->getByType(AnnotationsMethodsClassReflectionExtension::class); $annotationsPropertiesClassReflectionExtension = $this->container->getByType(AnnotationsPropertiesClassReflectionExtension::class); $mixinMethodsClassReflectionExtension = $this->container->getByType(MixinMethodsClassReflectionExtension::class); $mixinPropertiesClassReflectionExtension = $this->container->getByType(MixinPropertiesClassReflectionExtension::class); $soapClientMethodsClassReflectionExtension = $this->container->getByType(SoapClientMethodsClassReflectionExtension::class); $this->registry = new ClassReflectionExtensionRegistry($this->container->getByType(Broker::class), array_merge([$phpClassReflectionExtension], $this->container->getServicesByTag(BrokerFactory::PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG), [$annotationsPropertiesClassReflectionExtension, $mixinPropertiesClassReflectionExtension]), array_merge([$phpClassReflectionExtension], $this->container->getServicesByTag(BrokerFactory::METHODS_CLASS_REFLECTION_EXTENSION_TAG), [$annotationsMethodsClassReflectionExtension, $mixinMethodsClassReflectionExtension, $soapClientMethodsClassReflectionExtension]), $this->container->getServicesByTag(BrokerFactory::ALLOWED_SUB_TYPES_CLASS_REFLECTION_EXTENSION_TAG), $this->container->getByType(RequireExtendsPropertiesClassReflectionExtension::class), $this->container->getByType(RequireExtendsMethodsClassReflectionExtension::class)); } return $this->registry; } } min(1); } } currentWorkingDirectory = $currentWorkingDirectory; $this->checkDuplicateFiles = $checkDuplicateFiles; $this->fileHelper = new FileHelper($currentWorkingDirectory); $rootDir = __DIR__ . '/../..'; $originalRootDir = $this->fileHelper->normalizePath($rootDir); if (extension_loaded('phar')) { $pharPath = Phar::running(\false); if ($pharPath !== '') { $rootDir = dirname($pharPath); } } $this->rootDirectory = $this->fileHelper->normalizePath($rootDir); $this->configDirectory = $originalRootDir . '/conf'; } /** * @param string[] $additionalConfigFiles * @param string[] $analysedPaths * @param string[] $composerAutoloaderProjectPaths * @param string[] $analysedPathsFromConfig */ public function create(string $tempDirectory, array $additionalConfigFiles, array $analysedPaths, array $composerAutoloaderProjectPaths = [], array $analysedPathsFromConfig = [], string $usedLevel = CommandHelper::DEFAULT_LEVEL, ?string $generateBaselineFile = null, ?string $cliAutoloadFile = null, ?string $singleReflectionFile = null, ?string $singleReflectionInsteadOfFile = null) : \PHPStan\DependencyInjection\Container { [$allConfigFiles, $projectConfig] = $this->detectDuplicateIncludedFiles(array_merge([__DIR__ . '/../../conf/parametersSchema.neon'], $additionalConfigFiles), ['rootDir' => $this->rootDirectory, 'currentWorkingDirectory' => $this->currentWorkingDirectory, 'env' => getenv()]); $configurator = new \PHPStan\DependencyInjection\Configurator(new \PHPStan\DependencyInjection\LoaderFactory($this->fileHelper, $this->rootDirectory, $this->currentWorkingDirectory, $generateBaselineFile)); $configurator->defaultExtensions = ['php' => PhpExtension::class, 'extensions' => ExtensionsExtension::class]; $configurator->setDebugMode(\true); $configurator->setTempDirectory($tempDirectory); $configurator->addParameters(['rootDir' => $this->rootDirectory, 'currentWorkingDirectory' => $this->currentWorkingDirectory, 'cliArgumentsVariablesRegistered' => ini_get('register_argc_argv') === '1', 'tmpDir' => $tempDirectory, 'additionalConfigFiles' => $additionalConfigFiles, 'allConfigFiles' => $allConfigFiles, 'composerAutoloaderProjectPaths' => $composerAutoloaderProjectPaths, 'generateBaselineFile' => $generateBaselineFile, 'usedLevel' => $usedLevel, 'cliAutoloadFile' => $cliAutoloadFile]); $configurator->addDynamicParameters(['singleReflectionFile' => $singleReflectionFile, 'singleReflectionInsteadOfFile' => $singleReflectionInsteadOfFile, 'analysedPaths' => $analysedPaths, 'analysedPathsFromConfig' => $analysedPathsFromConfig, 'env' => getenv()]); $configurator->addConfig($this->configDirectory . '/config.neon'); foreach ($additionalConfigFiles as $additionalConfigFile) { $configurator->addConfig($additionalConfigFile); } $configurator->setAllConfigFiles($allConfigFiles); $container = $configurator->createContainer()->getByType(\PHPStan\DependencyInjection\Container::class); $this->validateParameters($container->getParameters(), $projectConfig['parametersSchema']); self::postInitializeContainer($container); return $container; } /** @internal */ public static function postInitializeContainer(\PHPStan\DependencyInjection\Container $container) : void { $containerId = spl_object_id($container); if ($containerId === self::$lastInitializedContainerId) { return; } self::$lastInitializedContainerId = $containerId; /** @var SourceLocator $sourceLocator */ $sourceLocator = $container->getService('betterReflectionSourceLocator'); /** @var Reflector $reflector */ $reflector = $container->getService('betterReflectionReflector'); /** @var Parser $phpParser */ $phpParser = $container->getService('phpParserDecorator'); BetterReflection::populate($container->getByType(PhpVersion::class)->getVersionId(), $sourceLocator, $reflector, $phpParser, $container->getByType(PhpStormStubsSourceStubber::class), $container->getByType(Printer::class)); $broker = $container->getByType(Broker::class); Broker::registerInstance($broker); ReflectionProviderStaticAccessor::registerInstance($container->getByType(ReflectionProvider::class)); PhpVersionStaticAccessor::registerInstance($container->getByType(PhpVersion::class)); ObjectType::resetCaches(); $container->getService('typeSpecifier'); \PHPStan\DependencyInjection\BleedingEdgeToggle::setBleedingEdge($container->getParameter('featureToggles')['bleedingEdge']); AccessoryArrayListType::setListTypeEnabled($container->getParameter('featureToggles')['listType']); TemplateTypeVariance::setInvarianceCompositionEnabled($container->getParameter('featureToggles')['invarianceComposition']); } public function clearOldContainers(string $tempDirectory) : void { $configurator = new \PHPStan\DependencyInjection\Configurator(new \PHPStan\DependencyInjection\LoaderFactory($this->fileHelper, $this->rootDirectory, $this->currentWorkingDirectory, null)); $configurator->setDebugMode(\true); $configurator->setTempDirectory($tempDirectory); $containerDirectory = $configurator->getContainerCacheDirectory(); if (!is_dir($containerDirectory)) { return; } $finder = new Finder(); $finder->name('Container_*')->in($containerDirectory); $twoDaysAgo = time() - 24 * 60 * 60 * 2; foreach ($finder as $containerFile) { $path = $containerFile->getRealPath(); if ($path === \false) { continue; } if ($containerFile->getATime() > $twoDaysAgo) { continue; } if ($containerFile->getCTime() > $twoDaysAgo) { continue; } @unlink($path); } } public function getCurrentWorkingDirectory() : string { return $this->currentWorkingDirectory; } public function getRootDirectory() : string { return $this->rootDirectory; } public function getConfigDirectory() : string { return $this->configDirectory; } /** * @param string[] $configFiles * @param array $loaderParameters * @return array{list, array} * @throws DuplicateIncludedFilesException */ private function detectDuplicateIncludedFiles(array $configFiles, array $loaderParameters) : array { $neonAdapter = new \PHPStan\DependencyInjection\NeonAdapter(); $phpAdapter = new PhpAdapter(); $allConfigFiles = []; $configArray = []; foreach ($configFiles as $configFile) { [$tmpConfigFiles, $tmpConfigArray] = self::getConfigFiles($this->fileHelper, $neonAdapter, $phpAdapter, $configFile, $loaderParameters, null); $allConfigFiles = array_merge($allConfigFiles, $tmpConfigFiles); /** @var array $configArray */ $configArray = \_PHPStan_c2fbb2235\Nette\Schema\Helpers::merge($tmpConfigArray, $configArray); } $normalized = array_map(function (string $file) : string { return $this->fileHelper->normalizePath($file); }, $allConfigFiles); $deduplicated = array_unique($normalized); if (count($normalized) <= count($deduplicated)) { return [$normalized, $configArray]; } if (!$this->checkDuplicateFiles) { return [$normalized, $configArray]; } $duplicateFiles = array_unique(array_diff_key($normalized, $deduplicated)); throw new \PHPStan\DependencyInjection\DuplicateIncludedFilesException($duplicateFiles); } /** * @param array $loaderParameters * @return array{list, array} */ private static function getConfigFiles(FileHelper $fileHelper, \PHPStan\DependencyInjection\NeonAdapter $neonAdapter, PhpAdapter $phpAdapter, string $configFile, array $loaderParameters, ?string $generateBaselineFile) : array { if ($generateBaselineFile === $fileHelper->normalizePath($configFile)) { return [[], []]; } if (!is_file($configFile) || !is_readable($configFile)) { return [[], []]; } if (str_ends_with($configFile, '.php')) { $data = $phpAdapter->load($configFile); } else { $data = $neonAdapter->load($configFile); } $allConfigFiles = [$configFile]; if (isset($data['includes'])) { Validators::assert($data['includes'], 'list', sprintf("section 'includes' in file '%s'", $configFile)); $includes = Helpers::expand($data['includes'], $loaderParameters); foreach ($includes as $include) { $include = self::expandIncludedFile($include, $configFile); [$tmpConfigFiles, $tmpConfigArray] = self::getConfigFiles($fileHelper, $neonAdapter, $phpAdapter, $include, $loaderParameters, $generateBaselineFile); $allConfigFiles = array_merge($allConfigFiles, $tmpConfigFiles); /** @var array $data */ $data = \_PHPStan_c2fbb2235\Nette\Schema\Helpers::merge($tmpConfigArray, $data); } } return [$allConfigFiles, $data]; } private static function expandIncludedFile(string $includedFile, string $mainFile) : string { return Strings::match($includedFile, '#([a-z]+:)?[/\\\\]#Ai') !== null ? $includedFile : dirname($mainFile) . '/' . $includedFile; } /** * @param array $parameters * @param array $parametersSchema */ private function validateParameters(array $parameters, array $parametersSchema) : void { if (!(bool) $parameters['__validate']) { return; } $schema = $this->processArgument(new Statement('schema', [new Statement('structure', [$parametersSchema])])); $processor = new Processor(); $processor->onNewContext[] = static function (SchemaContext $context) : void { $context->path = ['parameters']; }; $processor->process($schema, $parameters); } /** * @param Statement[] $statements */ private function processSchema(array $statements, bool $required = \true) : Schema { if (count($statements) === 0) { throw new ShouldNotHappenException(); } $parameterSchema = null; foreach ($statements as $statement) { $processedArguments = array_map(function ($argument) { return $this->processArgument($argument); }, $statement->arguments); if ($parameterSchema === null) { /** @var Type|AnyOf|Structure $parameterSchema */ $parameterSchema = Expect::{$statement->getEntity()}(...$processedArguments); } else { $parameterSchema->{$statement->getEntity()}(...$processedArguments); } } if ($required) { $parameterSchema->required(); } return $parameterSchema; } /** * @param mixed $argument * @return mixed */ private function processArgument($argument, bool $required = \true) { if ($argument instanceof Statement) { if ($argument->entity === 'schema') { $arguments = []; foreach ($argument->arguments as $schemaArgument) { if (!$schemaArgument instanceof Statement) { throw new ShouldNotHappenException('schema() should contain another statement().'); } $arguments[] = $schemaArgument; } if (count($arguments) === 0) { throw new ShouldNotHappenException('schema() should have at least one argument.'); } return $this->processSchema($arguments, $required); } return $this->processSchema([$argument], $required); } elseif (is_array($argument)) { $processedArray = []; foreach ($argument as $key => $val) { $required = $key[0] !== '?'; $key = $required ? $key : substr($key, 1); $processedArray[$key] = $this->processArgument($val, $required); } return $processedArray; } return $argument; } } fileHelper = $fileHelper; $this->generateBaselineFile = $generateBaselineFile; } /** * @return mixed[] */ public function load(string $file, ?bool $merge = \true) : array { if ($this->generateBaselineFile === null) { return parent::load($file, $merge); } $normalizedFile = $this->fileHelper->normalizePath($file); if ($this->generateBaselineFile === $normalizedFile) { return []; } return parent::load($file, $merge); } } $projectConfig * @return list */ public static function getServiceClassNames(array $projectConfig) : array { $services = array_merge($projectConfig['services'] ?? [], $projectConfig['rules'] ?? []); $classes = []; foreach ($services as $service) { $classes = array_merge($classes, self::getClassesFromConfigDefinition($service)); if (!is_array($service)) { continue; } foreach (['class', 'factory', 'implement'] as $key) { if (!isset($service[$key])) { continue; } $classes = array_merge($classes, self::getClassesFromConfigDefinition($service[$key])); } } return array_values(array_unique($classes)); } /** * @param mixed $definition * @return string[] */ private static function getClassesFromConfigDefinition($definition) : array { if (is_string($definition)) { return [$definition]; } if ($definition instanceof Statement) { $entity = $definition->entity; if (is_string($entity)) { return [$entity]; } elseif (is_array($entity) && isset($entity[0]) && is_string($entity[0])) { return [$entity[0]]; } } return []; } } errors = $errors; parent::__construct(implode("\n", $this->errors)); } /** * @return string[] */ public function getErrors() : array { return $this->errors; } } */ private $servicesByType = []; public function __construct(\PHPStan\DependencyInjection\Container $originalContainer) { $this->originalContainer = $originalContainer; } public function hasService(string $serviceName) : bool { return $this->originalContainer->hasService($serviceName); } public function getService(string $serviceName) { return $this->originalContainer->getService($serviceName); } public function getByType(string $className) { if (array_key_exists($className, $this->servicesByType)) { return $this->servicesByType[$className]; } $service = $this->originalContainer->getByType($className); $this->servicesByType[$className] = $service; return $service; } public function findServiceNamesByType(string $className) : array { return $this->originalContainer->findServiceNamesByType($className); } public function getServicesByTag(string $tagName) : array { return $this->originalContainer->getServicesByTag($tagName); } public function getParameters() : array { return $this->originalContainer->getParameters(); } public function hasParameter(string $parameterName) : bool { return $this->originalContainer->hasParameter($parameterName); } public function getParameter(string $parameterName) { return $this->originalContainer->getParameter($parameterName); } } loaderFactory = $loaderFactory; parent::__construct(); } protected function createLoader() : Loader { return $this->loaderFactory->createLoader(); } /** * @param string[] $allConfigFiles */ public function setAllConfigFiles(array $allConfigFiles) : void { $this->allConfigFiles = $allConfigFiles; } /** * @return mixed[] */ protected function getDefaultParameters() : array { return []; } public function getContainerCacheDirectory() : string { return $this->getCacheDirectory() . '/nette.configurator'; } public function loadContainer() : string { $loader = new ContainerLoader($this->getContainerCacheDirectory(), $this->staticParameters['debugMode']); return $loader->load([$this, 'generateContainer'], [$this->staticParameters, array_keys($this->dynamicParameters), $this->configs, PHP_VERSION_ID - PHP_RELEASE_VERSION, \PHPStan\DependencyInjection\NeonAdapter::CACHE_KEY, $this->getAllConfigFilesHashes()]); } public function createContainer(bool $initialize = \true) : OriginalNetteContainer { set_error_handler(static function (int $errno) : bool { if ((error_reporting() & $errno) === 0) { // silence @ operator return \true; } return $errno === E_USER_DEPRECATED; }); try { $container = parent::createContainer($initialize); } finally { restore_error_handler(); } return $container; } /** * @return string[] */ private function getAllConfigFilesHashes() : array { $hashes = []; foreach ($this->allConfigFiles as $file) { $hash = sha1_file($file); if ($hash === \false) { throw new CouldNotReadFileException($file); } $hashes[$file] = $hash; } return $hashes; } } errors = $errors; parent::__construct(implode("\n", $this->errors)); } /** * @return string[] */ public function getErrors() : array { return $this->errors; } } getContainerBuilder(); if (!$builder->parameters['__validate']) { return; } $ignoreErrors = $builder->parameters['ignoreErrors']; if (count($ignoreErrors) === 0) { return; } $noImplicitWildcard = $builder->parameters['featureToggles']['noImplicitWildcard']; /** @throws void */ $parser = Llk::load(new Read(__DIR__ . '/../../resources/RegexGrammar.pp')); $reflectionProvider = new DummyReflectionProvider(); $reflectionProviderProvider = new DirectReflectionProviderProvider($reflectionProvider); ReflectionProviderStaticAccessor::registerInstance($reflectionProvider); PhpVersionStaticAccessor::registerInstance(new PhpVersion(PHP_VERSION_ID)); $constantResolver = new ConstantResolver($reflectionProviderProvider, []); $ignoredRegexValidator = new IgnoredRegexValidator($parser, new TypeStringResolver(new Lexer(), new TypeParser(new ConstExprParser($builder->parameters['featureToggles']['unescapeStrings'])), new TypeNodeResolver(new DirectTypeNodeResolverExtensionRegistryProvider(new class implements TypeNodeResolverExtensionRegistry { public function getExtensions() : array { return []; } }), $reflectionProviderProvider, new DirectTypeAliasResolverProvider(new class implements TypeAliasResolver { public function hasTypeAlias(string $aliasName, ?string $classNameScope) : bool { return \false; } public function resolveTypeAlias(string $aliasName, NameScope $nameScope) : ?Type { return null; } }), $constantResolver, new InitializerExprTypeResolver($constantResolver, $reflectionProviderProvider, new PhpVersion(PHP_VERSION_ID), new class implements OperatorTypeSpecifyingExtensionRegistryProvider { public function getRegistry() : OperatorTypeSpecifyingExtensionRegistry { return new OperatorTypeSpecifyingExtensionRegistry(null, []); } }, new OversizedArrayBuilder())))); $errors = []; foreach ($ignoreErrors as $ignoreError) { if (is_array($ignoreError)) { if (isset($ignoreError['count'])) { continue; // ignoreError coming from baseline will be correct } if (isset($ignoreError['messages'])) { $ignoreMessages = $ignoreError['messages']; } elseif (isset($ignoreError['message'])) { $ignoreMessages = [$ignoreError['message']]; } else { continue; } } else { $ignoreMessages = [$ignoreError]; } foreach ($ignoreMessages as $ignoreMessage) { $error = $this->validateMessage($ignoredRegexValidator, $ignoreMessage); if ($error === null) { continue; } $errors[] = $error; } } $reportUnmatched = (bool) $builder->parameters['reportUnmatchedIgnoredErrors']; if ($noImplicitWildcard && $reportUnmatched) { foreach ($ignoreErrors as $ignoreError) { if (!is_array($ignoreError)) { continue; } if (isset($ignoreError['path'])) { $ignorePaths = [$ignoreError['path']]; } elseif (isset($ignoreError['paths'])) { $ignorePaths = $ignoreError['paths']; } else { continue; } foreach ($ignorePaths as $ignorePath) { if (FileExcluder::isAbsolutePath($ignorePath)) { if (is_dir($ignorePath)) { continue; } if (is_file($ignorePath)) { continue; } } if (FileExcluder::isFnmatchPattern($ignorePath)) { continue; } $errors[] = sprintf('Path %s is neither a directory, nor a file path, nor a fnmatch pattern.', $ignorePath); } } } if (count($errors) === 0) { return; } throw new \PHPStan\DependencyInjection\InvalidIgnoredErrorPatternsException($errors); } private function validateMessage(IgnoredRegexValidator $ignoredRegexValidator, string $ignoreMessage) : ?string { try { Strings::match('', $ignoreMessage); $validationResult = $ignoredRegexValidator->validate($ignoreMessage); $ignoredTypes = $validationResult->getIgnoredTypes(); if (count($ignoredTypes) > 0) { return $this->createIgnoredTypesError($ignoreMessage, $ignoredTypes); } if ($validationResult->hasAnchorsInTheMiddle()) { return $this->createAnchorInTheMiddleError($ignoreMessage); } if ($validationResult->areAllErrorsIgnored()) { return sprintf("Ignored error %s has an unescaped '%s' which leads to ignoring all errors. Use '%s' instead.", $ignoreMessage, $validationResult->getWrongSequence(), $validationResult->getEscapedWrongSequence()); } } catch (RegexpException $e) { return $e->getMessage(); } return null; } /** * @param array $ignoredTypes */ private function createIgnoredTypesError(string $regex, array $ignoredTypes) : string { return sprintf("Ignored error %s has an unescaped '|' which leads to ignoring more errors than intended. Use '\\|' instead.\n%s", $regex, sprintf("It ignores all errors containing the following types:\n%s", implode("\n", array_map(static function (string $typeDescription) : string { return sprintf('* %s', $typeDescription); }, array_keys($ignoredTypes))))); } private function createAnchorInTheMiddleError(string $regex) : string { return sprintf("Ignored error %s has an unescaped anchor '\$' in the middle. This leads to unintended behavior. Use '\\\$' instead.", $regex); } } $className * @return T */ public function getByType(string $className); /** * @param class-string $className * @return string[] */ public function findServiceNamesByType(string $className) : array; /** * @return mixed[] */ public function getServicesByTag(string $tagName) : array; /** * @return mixed[] */ public function getParameters() : array; public function hasParameter(string $parameterName) : bool; /** * @return mixed * @throws ParameterNotFoundException */ public function getParameter(string $parameterName); } getContainerBuilder(); $excludePaths = $builder->parameters['excludePaths']; if ($excludePaths === null) { return; } $errors = []; $noImplicitWildcard = $builder->parameters['featureToggles']['noImplicitWildcard']; if ($builder->parameters['__validate'] && $noImplicitWildcard) { $paths = []; if (array_key_exists('analyse', $excludePaths)) { $paths = $excludePaths['analyse']; } if (array_key_exists('analyseAndScan', $excludePaths)) { $paths = array_merge($paths, $excludePaths['analyseAndScan']); } foreach ($paths as $path) { if ($path instanceof OptionalPath) { continue; } if (FileExcluder::isAbsolutePath($path)) { if (is_dir($path)) { continue; } if (is_file($path)) { continue; } } if (FileExcluder::isFnmatchPattern($path)) { continue; } $errors[] = sprintf('Path %s is neither a directory, nor a file path, nor a fnmatch pattern.', $path); } } $newExcludePaths = []; if (array_key_exists('analyseAndScan', $excludePaths)) { $newExcludePaths['analyseAndScan'] = $excludePaths['analyseAndScan']; } if (array_key_exists('analyse', $excludePaths)) { $newExcludePaths['analyse'] = $excludePaths['analyse']; } foreach ($newExcludePaths as $key => $p) { $newExcludePaths[$key] = array_map(static function ($path) { return $path instanceof OptionalPath ? $path->path : $path; }, $p); } $builder->parameters['excludePaths'] = $newExcludePaths; if (count($errors) === 0) { return; } throw new \PHPStan\DependencyInjection\InvalidExcludePathsException($errors); } } config; $builder = $this->getContainerBuilder(); foreach ($config as $key => $rule) { $builder->addDefinition($this->prefix((string) $key))->setFactory($rule)->setAutowired($rule)->addTag(LazyRegistry::RULE_TAG); } } } parser = $parser; $this->visitor = $visitor; } /** * @return RootExportedNode[] */ public function fetchNodes(string $fileName) : array { $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor($this->visitor); try { $ast = $this->parser->parseFile($fileName); } catch (ParserErrorsException $e) { return []; } $this->visitor->reset($fileName); $nodeTraverser->traverse($ast); return $this->visitor->getExportedNodes(); } } exportedNodeResolver = $exportedNodeResolver; } public function reset(string $fileName) : void { $this->fileName = $fileName; $this->currentNodes = []; } /** * @return RootExportedNode[] */ public function getExportedNodes() : array { return $this->currentNodes; } public function enterNode(Node $node) : ?int { if ($this->fileName === null) { throw new ShouldNotHappenException(); } $exportedNode = $this->exportedNodeResolver->resolve($this->fileName, $node); if ($exportedNode !== null) { $this->currentNodes[] = $exportedNode; } if ($node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\Trait_) { return NodeTraverser::DONT_TRAVERSE_CHILDREN; } return null; } } name = $name; $this->phpDoc = $phpDoc; $this->extends = $extends; $this->statements = $statements; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if ($this->phpDoc === null) { if ($node->phpDoc !== null) { return \false; } } elseif ($node->phpDoc !== null) { if (!$this->phpDoc->equals($node->phpDoc)) { return \false; } } else { return \false; } if (count($this->statements) !== count($node->statements)) { return \false; } foreach ($this->statements as $i => $statement) { if ($statement->equals($node->statements[$i])) { continue; } return \false; } return $this->name === $node->name && $this->extends === $node->extends; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['phpDoc'], $properties['extends'], $properties['statements']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'phpDoc' => $this->phpDoc, 'extends' => $this->extends, 'statements' => $this->statements]]; } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null, $data['extends'], array_map(static function (array $node) : ExportedNode { $nodeType = $node['type']; return $nodeType::decode($node['data']); }, $data['statements'])); } /** * @return self::TYPE_INTERFACE */ public function getType() : string { return self::TYPE_INTERFACE; } public function getName() : string { return $this->name; } } name = $name; $this->phpDoc = $phpDoc; $this->abstract = $abstract; $this->final = $final; $this->extends = $extends; $this->implements = $implements; $this->usedTraits = $usedTraits; $this->traitUseAdaptations = $traitUseAdaptations; $this->statements = $statements; $this->attributes = $attributes; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if ($this->phpDoc === null) { if ($node->phpDoc !== null) { return \false; } } elseif ($node->phpDoc !== null) { if (!$this->phpDoc->equals($node->phpDoc)) { return \false; } } else { return \false; } if (count($this->attributes) !== count($node->attributes)) { return \false; } foreach ($this->attributes as $i => $attribute) { if (!$attribute->equals($node->attributes[$i])) { return \false; } } if (count($this->traitUseAdaptations) !== count($node->traitUseAdaptations)) { return \false; } foreach ($this->traitUseAdaptations as $i => $ourTraitUseAdaptation) { $theirTraitUseAdaptation = $node->traitUseAdaptations[$i]; if (!$ourTraitUseAdaptation->equals($theirTraitUseAdaptation)) { return \false; } } if (count($this->statements) !== count($node->statements)) { return \false; } foreach ($this->statements as $i => $statement) { if ($statement->equals($node->statements[$i])) { continue; } return \false; } return $this->name === $node->name && $this->abstract === $node->abstract && $this->final === $node->final && $this->extends === $node->extends && $this->implements === $node->implements && $this->usedTraits === $node->usedTraits; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['phpDoc'], $properties['abstract'], $properties['final'], $properties['extends'], $properties['implements'], $properties['usedTraits'], $properties['traitUseAdaptations'], $properties['statements'], $properties['attributes']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'phpDoc' => $this->phpDoc, 'abstract' => $this->abstract, 'final' => $this->final, 'extends' => $this->extends, 'implements' => $this->implements, 'usedTraits' => $this->usedTraits, 'traitUseAdaptations' => $this->traitUseAdaptations, 'statements' => $this->statements, 'attributes' => $this->attributes]]; } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null, $data['abstract'], $data['final'], $data['extends'], $data['implements'], $data['usedTraits'], array_map(static function (array $traitUseAdaptationData) : \PHPStan\Dependency\ExportedNode\ExportedTraitUseAdaptation { if ($traitUseAdaptationData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedTraitUseAdaptation::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedTraitUseAdaptation::decode($traitUseAdaptationData['data']); }, $data['traitUseAdaptations']), array_map(static function (array $node) : ExportedNode { $nodeType = $node['type']; return $nodeType::decode($node['data']); }, $data['statements']), array_map(static function (array $attributeData) : \PHPStan\Dependency\ExportedNode\ExportedAttributeNode { if ($attributeData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::decode($attributeData['data']); }, $data['attributes'])); } /** * @return self::TYPE_CLASS */ public function getType() : string { return self::TYPE_CLASS; } public function getName() : string { return $this->name; } } name = $name; $this->value = $value; $this->attributes = $attributes; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if (count($this->attributes) !== count($node->attributes)) { return \false; } foreach ($this->attributes as $i => $attribute) { if (!$attribute->equals($node->attributes[$i])) { return \false; } } return $this->name === $node->name && $this->value === $node->value; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['value'], $properties['attributes']); } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['value'], array_map(static function (array $attributeData) : \PHPStan\Dependency\ExportedNode\ExportedAttributeNode { if ($attributeData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::decode($attributeData['data']); }, $data['attributes'])); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'value' => $this->value, 'attributes' => $this->attributes]]; } } name = $name; $this->value = $value; $this->phpDoc = $phpDoc; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if ($this->phpDoc === null) { if ($node->phpDoc !== null) { return \false; } } elseif ($node->phpDoc !== null) { if (!$this->phpDoc->equals($node->phpDoc)) { return \false; } } else { return \false; } return $this->name === $node->name && $this->value === $node->value; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['value'], $properties['phpDoc']); } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['value'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'value' => $this->value, 'phpDoc' => $this->phpDoc]]; } } name = $name; $this->type = $type; $this->byRef = $byRef; $this->variadic = $variadic; $this->hasDefault = $hasDefault; $this->attributes = $attributes; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if (count($this->attributes) !== count($node->attributes)) { return \false; } foreach ($this->attributes as $i => $attribute) { if (!$attribute->equals($node->attributes[$i])) { return \false; } } return $this->name === $node->name && $this->type === $node->type && $this->byRef === $node->byRef && $this->variadic === $node->variadic && $this->hasDefault === $node->hasDefault; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['type'], $properties['byRef'], $properties['variadic'], $properties['hasDefault'], $properties['attributes']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'type' => $this->type, 'byRef' => $this->byRef, 'variadic' => $this->variadic, 'hasDefault' => $this->hasDefault, 'attributes' => $this->attributes]]; } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['type'], $data['byRef'], $data['variadic'], $data['hasDefault'], array_map(static function (array $attributeData) : \PHPStan\Dependency\ExportedNode\ExportedAttributeNode { if ($attributeData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::decode($attributeData['data']); }, $data['attributes'])); } } */ private $args; /** * @param array $args argument name or index(string|int) => value expression (string) */ public function __construct(string $name, array $args) { $this->name = $name; $this->args = $args; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if ($this->name !== $node->name) { return \false; } if (count($this->args) !== count($node->args)) { return \false; } foreach ($this->args as $argName => $argValue) { if (!isset($node->args[$argName]) || $argValue !== $node->args[$argName]) { return \false; } } return \true; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['args']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'args' => $this->args]]; } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['args']); } } name = $name; $this->phpDoc = $phpDoc; $this->usedTraits = $usedTraits; $this->traitUseAdaptations = $traitUseAdaptations; $this->statements = $statements; $this->attributes = $attributes; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if ($this->phpDoc === null) { if ($node->phpDoc !== null) { return \false; } } elseif ($node->phpDoc !== null) { if (!$this->phpDoc->equals($node->phpDoc)) { return \false; } } else { return \false; } if (count($this->attributes) !== count($node->attributes)) { return \false; } foreach ($this->attributes as $i => $attribute) { if (!$attribute->equals($node->attributes[$i])) { return \false; } } if (count($this->traitUseAdaptations) !== count($node->traitUseAdaptations)) { return \false; } foreach ($this->traitUseAdaptations as $i => $ourTraitUseAdaptation) { $theirTraitUseAdaptation = $node->traitUseAdaptations[$i]; if (!$ourTraitUseAdaptation->equals($theirTraitUseAdaptation)) { return \false; } } if (count($this->statements) !== count($node->statements)) { return \false; } foreach ($this->statements as $i => $statement) { if ($statement->equals($node->statements[$i])) { continue; } return \false; } return $this->name === $node->name && $this->usedTraits === $node->usedTraits; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['phpDoc'], $properties['usedTraits'], $properties['traitUseAdaptations'], $properties['statements'], $properties['attributes']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'phpDoc' => $this->phpDoc, 'usedTraits' => $this->usedTraits, 'traitUseAdaptations' => $this->traitUseAdaptations, 'statements' => $this->statements, 'attributes' => $this->attributes]]; } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null, $data['usedTraits'], array_map(static function (array $traitUseAdaptationData) : \PHPStan\Dependency\ExportedNode\ExportedTraitUseAdaptation { if ($traitUseAdaptationData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedTraitUseAdaptation::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedTraitUseAdaptation::decode($traitUseAdaptationData['data']); }, $data['traitUseAdaptations']), array_map(static function (array $node) : ExportedNode { $nodeType = $node['type']; return $nodeType::decode($node['data']); }, $data['statements']), array_map(static function (array $attributeData) : \PHPStan\Dependency\ExportedNode\ExportedAttributeNode { if ($attributeData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::decode($attributeData['data']); }, $data['attributes'])); } /** * @return self::TYPE_TRAIT */ public function getType() : string { return self::TYPE_TRAIT; } public function getName() : string { return $this->name; } } name = $name; $this->phpDoc = $phpDoc; $this->byRef = $byRef; $this->returnType = $returnType; $this->parameters = $parameters; $this->attributes = $attributes; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if (count($this->parameters) !== count($node->parameters)) { return \false; } foreach ($this->parameters as $i => $ourParameter) { $theirParameter = $node->parameters[$i]; if (!$ourParameter->equals($theirParameter)) { return \false; } } if ($this->phpDoc === null) { if ($node->phpDoc !== null) { return \false; } } elseif ($node->phpDoc !== null) { if (!$this->phpDoc->equals($node->phpDoc)) { return \false; } } else { return \false; } if (count($this->attributes) !== count($node->attributes)) { return \false; } foreach ($this->attributes as $i => $attribute) { if (!$attribute->equals($node->attributes[$i])) { return \false; } } return $this->name === $node->name && $this->byRef === $node->byRef && $this->returnType === $node->returnType; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['phpDoc'], $properties['byRef'], $properties['returnType'], $properties['parameters'], $properties['attributes']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'phpDoc' => $this->phpDoc, 'byRef' => $this->byRef, 'returnType' => $this->returnType, 'parameters' => $this->parameters, 'attributes' => $this->attributes]]; } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null, $data['byRef'], $data['returnType'], array_map(static function (array $parameterData) : \PHPStan\Dependency\ExportedNode\ExportedParameterNode { if ($parameterData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedParameterNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedParameterNode::decode($parameterData['data']); }, $data['parameters']), array_map(static function (array $attributeData) : \PHPStan\Dependency\ExportedNode\ExportedAttributeNode { if ($attributeData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::decode($attributeData['data']); }, $data['attributes'])); } /** * @return self::TYPE_FUNCTION */ public function getType() : string { return self::TYPE_FUNCTION; } public function getName() : string { return $this->name; } } constants = $constants; $this->public = $public; $this->private = $private; $this->final = $final; $this->phpDoc = $phpDoc; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if ($this->phpDoc === null) { if ($node->phpDoc !== null) { return \false; } } elseif ($node->phpDoc !== null) { if (!$this->phpDoc->equals($node->phpDoc)) { return \false; } } else { return \false; } if (count($this->constants) !== count($node->constants)) { return \false; } foreach ($this->constants as $i => $constant) { if (!$constant->equals($node->constants[$i])) { return \false; } } return $this->public === $node->public && $this->private === $node->private && $this->final === $node->final; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['constants'], $properties['public'], $properties['private'], $properties['final'], $properties['phpDoc']); } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self(array_map(static function (array $constantData) : \PHPStan\Dependency\ExportedNode\ExportedClassConstantNode { if ($constantData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedClassConstantNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedClassConstantNode::decode($constantData['data']); }, $data['constants']), $data['public'], $data['private'], $data['final'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['constants' => $this->constants, 'public' => $this->public, 'private' => $this->private, 'final' => $this->final, 'phpDoc' => $this->phpDoc]]; } } traitName = $traitName; $this->method = $method; $this->newModifier = $newModifier; $this->newName = $newName; $this->insteadOfs = $insteadOfs; } public static function createAlias(?string $traitName, string $method, ?int $newModifier, ?string $newName) : self { return new self($traitName, $method, $newModifier, $newName, null); } /** * @param string[] $insteadOfs */ public static function createPrecedence(?string $traitName, string $method, array $insteadOfs) : self { return new self($traitName, $method, null, null, $insteadOfs); } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } return $this->traitName === $node->traitName && $this->method === $node->method && $this->newModifier === $node->newModifier && $this->newName === $node->newName && $this->insteadOfs === $node->insteadOfs; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['traitName'], $properties['method'], $properties['newModifier'], $properties['newName'], $properties['insteadOfs']); } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['traitName'], $data['method'], $data['newModifier'], $data['newName'], $data['insteadOfs']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['traitName' => $this->traitName, 'method' => $this->method, 'newModifier' => $this->newModifier, 'newName' => $this->newName, 'insteadOfs' => $this->insteadOfs]]; } } */ private $uses; /** * @var array */ private $constUses; /** * @param array $uses alias(string) => fullName(string) * @param array $constUses alias(string) => fullName(string) */ public function __construct(string $phpDocString, ?string $namespace, array $uses, array $constUses) { $this->phpDocString = $phpDocString; $this->namespace = $namespace; $this->uses = $uses; $this->constUses = $constUses; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } return $this->phpDocString === $node->phpDocString && $this->namespace === $node->namespace && $this->uses === $node->uses && $this->constUses === $node->constUses; } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['phpDocString' => $this->phpDocString, 'namespace' => $this->namespace, 'uses' => $this->uses, 'constUses' => $this->constUses]]; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['phpDocString'], $properties['namespace'], $properties['uses'], $properties['constUses'] ?? []); } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['phpDocString'], $data['namespace'], $data['uses'], $data['constUses'] ?? []); } } name = $name; $this->phpDoc = $phpDoc; $this->byRef = $byRef; $this->public = $public; $this->private = $private; $this->abstract = $abstract; $this->final = $final; $this->static = $static; $this->returnType = $returnType; $this->parameters = $parameters; $this->attributes = $attributes; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if (count($this->parameters) !== count($node->parameters)) { return \false; } foreach ($this->parameters as $i => $ourParameter) { $theirParameter = $node->parameters[$i]; if (!$ourParameter->equals($theirParameter)) { return \false; } } if ($this->phpDoc === null) { if ($node->phpDoc !== null) { return \false; } } elseif ($node->phpDoc !== null) { if (!$this->phpDoc->equals($node->phpDoc)) { return \false; } } else { return \false; } if (count($this->attributes) !== count($node->attributes)) { return \false; } foreach ($this->attributes as $i => $attribute) { if (!$attribute->equals($node->attributes[$i])) { return \false; } } return $this->name === $node->name && $this->byRef === $node->byRef && $this->public === $node->public && $this->private === $node->private && $this->abstract === $node->abstract && $this->final === $node->final && $this->static === $node->static && $this->returnType === $node->returnType; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['phpDoc'], $properties['byRef'], $properties['public'], $properties['private'], $properties['abstract'], $properties['final'], $properties['static'], $properties['returnType'], $properties['parameters'], $properties['attributes']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'phpDoc' => $this->phpDoc, 'byRef' => $this->byRef, 'public' => $this->public, 'private' => $this->private, 'abstract' => $this->abstract, 'final' => $this->final, 'static' => $this->static, 'returnType' => $this->returnType, 'parameters' => $this->parameters, 'attributes' => $this->attributes]]; } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null, $data['byRef'], $data['public'], $data['private'], $data['abstract'], $data['final'], $data['static'], $data['returnType'], array_map(static function (array $parameterData) : \PHPStan\Dependency\ExportedNode\ExportedParameterNode { if ($parameterData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedParameterNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedParameterNode::decode($parameterData['data']); }, $data['parameters']), array_map(static function (array $attributeData) : \PHPStan\Dependency\ExportedNode\ExportedAttributeNode { if ($attributeData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::decode($attributeData['data']); }, $data['attributes'])); } } names = $names; $this->phpDoc = $phpDoc; $this->type = $type; $this->public = $public; $this->private = $private; $this->static = $static; $this->readonly = $readonly; $this->attributes = $attributes; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if ($this->phpDoc === null) { if ($node->phpDoc !== null) { return \false; } } elseif ($node->phpDoc !== null) { if (!$this->phpDoc->equals($node->phpDoc)) { return \false; } } else { return \false; } if (count($this->names) !== count($node->names)) { return \false; } foreach ($this->names as $i => $name) { if ($name !== $node->names[$i]) { return \false; } } if (count($this->attributes) !== count($node->attributes)) { return \false; } foreach ($this->attributes as $i => $attribute) { if (!$attribute->equals($node->attributes[$i])) { return \false; } } return $this->type === $node->type && $this->public === $node->public && $this->private === $node->private && $this->static === $node->static && $this->readonly === $node->readonly; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['names'], $properties['phpDoc'], $properties['type'], $properties['public'], $properties['private'], $properties['static'], $properties['readonly'], $properties['attributes']); } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['names'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null, $data['type'], $data['public'], $data['private'], $data['static'], $data['readonly'], array_map(static function (array $attributeData) : \PHPStan\Dependency\ExportedNode\ExportedAttributeNode { if ($attributeData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::decode($attributeData['data']); }, $data['attributes'])); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['names' => $this->names, 'phpDoc' => $this->phpDoc, 'type' => $this->type, 'public' => $this->public, 'private' => $this->private, 'static' => $this->static, 'readonly' => $this->readonly, 'attributes' => $this->attributes]]; } } name = $name; $this->scalarType = $scalarType; $this->phpDoc = $phpDoc; $this->implements = $implements; $this->statements = $statements; $this->attributes = $attributes; } public function equals(ExportedNode $node) : bool { if (!$node instanceof self) { return \false; } if ($this->phpDoc === null) { if ($node->phpDoc !== null) { return \false; } } elseif ($node->phpDoc !== null) { if (!$this->phpDoc->equals($node->phpDoc)) { return \false; } } else { return \false; } if (count($this->statements) !== count($node->statements)) { return \false; } foreach ($this->statements as $i => $statement) { if ($statement->equals($node->statements[$i])) { continue; } return \false; } if (count($this->attributes) !== count($node->attributes)) { return \false; } foreach ($this->attributes as $i => $attribute) { if (!$attribute->equals($node->attributes[$i])) { return \false; } } return $this->name === $node->name && $this->scalarType === $node->scalarType && $this->implements === $node->implements; } /** * @param mixed[] $properties * @return self */ public static function __set_state(array $properties) : ExportedNode { return new self($properties['name'], $properties['scalarType'], $properties['phpDoc'], $properties['implements'], $properties['statements'], $properties['attributes']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['type' => self::class, 'data' => ['name' => $this->name, 'scalarType' => $this->scalarType, 'phpDoc' => $this->phpDoc, 'implements' => $this->implements, 'statements' => $this->statements, 'attributes' => $this->attributes]]; } /** * @param mixed[] $data * @return self */ public static function decode(array $data) : ExportedNode { return new self($data['name'], $data['scalarType'], $data['phpDoc'] !== null ? \PHPStan\Dependency\ExportedNode\ExportedPhpDocNode::decode($data['phpDoc']['data']) : null, $data['implements'], array_map(static function (array $node) : ExportedNode { $nodeType = $node['type']; return $nodeType::decode($node['data']); }, $data['statements']), array_map(static function (array $attributeData) : \PHPStan\Dependency\ExportedNode\ExportedAttributeNode { if ($attributeData['type'] !== \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::class) { throw new ShouldNotHappenException(); } return \PHPStan\Dependency\ExportedNode\ExportedAttributeNode::decode($attributeData['data']); }, $data['attributes'])); } /** * @return self::TYPE_ENUM */ public function getType() : string { return self::TYPE_ENUM; } public function getName() : string { return $this->name; } } fileHelper = $fileHelper; $this->reflectionProvider = $reflectionProvider; $this->exportedNodeResolver = $exportedNodeResolver; $this->fileTypeMapper = $fileTypeMapper; } public function resolveDependencies(Node $node, Scope $scope) : \PHPStan\Dependency\NodeDependencies { $dependenciesReflections = []; if ($node instanceof Node\Stmt\Class_) { if ($node->namespacedName !== null) { $this->addClassToDependencies($node->namespacedName->toString(), $dependenciesReflections); } if ($node->extends !== null) { $this->addClassToDependencies($node->extends->toString(), $dependenciesReflections); } foreach ($node->implements as $className) { $this->addClassToDependencies($className->toString(), $dependenciesReflections); } } elseif ($node instanceof Node\Stmt\Interface_) { if ($node->namespacedName !== null) { $this->addClassToDependencies($node->namespacedName->toString(), $dependenciesReflections); } foreach ($node->extends as $className) { $this->addClassToDependencies($className->toString(), $dependenciesReflections); } } elseif ($node instanceof Node\Stmt\Enum_) { if ($node->namespacedName !== null) { $this->addClassToDependencies($node->namespacedName->toString(), $dependenciesReflections); } foreach ($node->implements as $className) { $this->addClassToDependencies($className->toString(), $dependenciesReflections); } } elseif ($node instanceof InClassMethodNode) { $nativeMethod = $node->getMethodReflection(); $this->extractThrowType($nativeMethod->getThrowType(), $dependenciesReflections); $this->extractFromParametersAcceptor($nativeMethod, $dependenciesReflections); foreach ($nativeMethod->getAsserts()->getAll() as $assertTag) { foreach ($assertTag->getType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } foreach ($assertTag->getOriginalType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } if ($nativeMethod->getSelfOutType() !== null) { foreach ($nativeMethod->getSelfOutType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } elseif ($node instanceof ClassPropertyNode) { $nativeTypeNode = $node->getNativeType(); if ($nativeTypeNode !== null) { $nativeType = ParserNodeTypeToPHPStanType::resolve($nativeTypeNode, $node->getClassReflection()); foreach ($nativeType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } $phpDocType = $node->getPhpDocType(); if ($phpDocType !== null) { foreach ($phpDocType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } elseif ($node instanceof InFunctionNode) { $functionReflection = $node->getFunctionReflection(); $this->extractThrowType($functionReflection->getThrowType(), $dependenciesReflections); $this->extractFromParametersAcceptor($functionReflection, $dependenciesReflections); foreach ($functionReflection->getAsserts()->getAll() as $assertTag) { foreach ($assertTag->getType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } foreach ($assertTag->getOriginalType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } elseif ($node instanceof Closure || $node instanceof Node\Expr\ArrowFunction) { $closureType = $scope->getType($node); if ($closureType instanceof ClosureType) { foreach ($closureType->getParameters() as $parameter) { $referencedClasses = $parameter->getType()->getReferencedClasses(); foreach ($referencedClasses as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } $returnTypeReferencedClasses = $closureType->getReturnType()->getReferencedClasses(); foreach ($returnTypeReferencedClasses as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } elseif ($node instanceof Node\Expr\FuncCall) { $functionName = $node->name; if ($functionName instanceof Node\Name) { try { $functionReflection = $this->getFunctionReflection($functionName, $scope); $dependenciesReflections[] = $functionReflection; foreach ($functionReflection->getVariants() as $functionVariant) { foreach ($functionVariant->getParameters() as $parameter) { if ($parameter->getOutType() !== null) { foreach ($parameter->getOutType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } if ($parameter->getClosureThisType() === null) { continue; } foreach ($parameter->getClosureThisType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } foreach ($functionReflection->getAsserts()->getAll() as $assertTag) { foreach ($assertTag->getType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } foreach ($assertTag->getOriginalType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } catch (FunctionNotFoundException $e) { // pass } } else { $calledType = $scope->getType($functionName); if ($calledType->isCallable()->yes()) { $variants = $calledType->getCallableParametersAcceptors($scope); foreach ($variants as $variant) { $referencedClasses = $variant->getReturnType()->getReferencedClasses(); foreach ($referencedClasses as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } foreach ($variant->getParameters() as $parameter) { if (!$parameter instanceof ParameterReflectionWithPhpDocs) { continue; } if ($parameter->getOutType() !== null) { foreach ($parameter->getOutType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } if ($parameter->getClosureThisType() === null) { continue; } foreach ($parameter->getClosureThisType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } } } $returnType = $scope->getType($node); foreach ($returnType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } elseif ($node instanceof Node\Expr\MethodCall) { $calledOnType = $scope->getType($node->var); $classNames = $calledOnType->getReferencedClasses(); foreach ($classNames as $className) { $this->addClassToDependencies($className, $dependenciesReflections); } $returnType = $scope->getType($node); foreach ($returnType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } if ($node->name instanceof Node\Identifier) { $methodReflection = $scope->getMethodReflection($calledOnType, $node->name->toString()); if ($methodReflection !== null) { $this->addClassToDependencies($methodReflection->getDeclaringClass()->getName(), $dependenciesReflections); foreach ($methodReflection->getVariants() as $methodVariant) { foreach ($methodVariant->getParameters() as $parameter) { if ($parameter->getOutType() !== null) { foreach ($parameter->getOutType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } if ($parameter->getClosureThisType() === null) { continue; } foreach ($parameter->getClosureThisType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } foreach ($methodReflection->getAsserts()->getAll() as $assertTag) { foreach ($assertTag->getType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } foreach ($assertTag->getOriginalType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } if ($methodReflection->getSelfOutType() !== null) { foreach ($methodReflection->getSelfOutType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } } } elseif ($node instanceof Node\Expr\PropertyFetch) { $fetchedOnType = $scope->getType($node->var); $classNames = $fetchedOnType->getReferencedClasses(); foreach ($classNames as $className) { $this->addClassToDependencies($className, $dependenciesReflections); } $propertyType = $scope->getType($node); foreach ($propertyType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } if ($node->name instanceof Node\Identifier) { $propertyReflection = $scope->getPropertyReflection($fetchedOnType, $node->name->toString()); if ($propertyReflection !== null) { $this->addClassToDependencies($propertyReflection->getDeclaringClass()->getName(), $dependenciesReflections); } } } elseif ($node instanceof Node\Expr\StaticCall) { if ($node->class instanceof Node\Name) { $this->addClassToDependencies($scope->resolveName($node->class), $dependenciesReflections); } else { foreach ($scope->getType($node->class)->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } $returnType = $scope->getType($node); foreach ($returnType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } if ($node->name instanceof Node\Identifier) { if ($node->class instanceof Node\Name) { $className = $scope->resolveName($node->class); if ($this->reflectionProvider->hasClass($className)) { $methodClassReflection = $this->reflectionProvider->getClass($className); if ($methodClassReflection->hasMethod($node->name->toString())) { $methodReflection = $methodClassReflection->getMethod($node->name->toString(), $scope); $this->addClassToDependencies($methodReflection->getDeclaringClass()->getName(), $dependenciesReflections); foreach ($methodReflection->getVariants() as $methodVariant) { foreach ($methodVariant->getParameters() as $parameter) { if ($parameter->getOutType() !== null) { foreach ($parameter->getOutType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } if ($parameter->getClosureThisType() === null) { continue; } foreach ($parameter->getClosureThisType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } } } } else { $methodReflection = $scope->getMethodReflection($scope->getType($node->class), $node->name->toString()); if ($methodReflection !== null) { $this->addClassToDependencies($methodReflection->getDeclaringClass()->getName(), $dependenciesReflections); foreach ($methodReflection->getVariants() as $methodVariant) { foreach ($methodVariant->getParameters() as $parameter) { if ($parameter->getOutType() !== null) { foreach ($parameter->getOutType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } if ($parameter->getClosureThisType() === null) { continue; } foreach ($parameter->getClosureThisType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } } } } } elseif ($node instanceof Node\Expr\ClassConstFetch) { if ($node->class instanceof Node\Name) { $this->addClassToDependencies($scope->resolveName($node->class), $dependenciesReflections); } else { foreach ($scope->getType($node->class)->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } $returnType = $scope->getType($node); foreach ($returnType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } if ($node->name instanceof Node\Identifier && $node->name->toLowerString() !== 'class') { if ($node->class instanceof Node\Name) { $className = $scope->resolveName($node->class); if ($this->reflectionProvider->hasClass($className)) { $constantClassReflection = $this->reflectionProvider->getClass($className); if ($constantClassReflection->hasConstant($node->name->toString())) { $constantReflection = $constantClassReflection->getConstant($node->name->toString()); $this->addClassToDependencies($constantReflection->getDeclaringClass()->getName(), $dependenciesReflections); } } } else { $constantReflection = $scope->getConstantReflection($scope->getType($node->class), $node->name->toString()); if ($constantReflection !== null) { $this->addClassToDependencies($constantReflection->getDeclaringClass()->getName(), $dependenciesReflections); } } } } elseif ($node instanceof Node\Expr\StaticPropertyFetch) { if ($node->class instanceof Node\Name) { $this->addClassToDependencies($scope->resolveName($node->class), $dependenciesReflections); } else { foreach ($scope->getType($node->class)->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } $returnType = $scope->getType($node); foreach ($returnType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } if ($node->name instanceof Node\Identifier) { if ($node->class instanceof Node\Name) { $className = $scope->resolveName($node->class); if ($this->reflectionProvider->hasClass($className)) { $propertyClassReflection = $this->reflectionProvider->getClass($className); if ($propertyClassReflection->hasProperty($node->name->toString())) { $propertyReflection = $propertyClassReflection->getProperty($node->name->toString(), $scope); $this->addClassToDependencies($propertyReflection->getDeclaringClass()->getName(), $dependenciesReflections); } } } else { $propertyReflection = $scope->getPropertyReflection($scope->getType($node->class), $node->name->toString()); if ($propertyReflection !== null) { $this->addClassToDependencies($propertyReflection->getDeclaringClass()->getName(), $dependenciesReflections); } } } } elseif ($node instanceof Node\Expr\New_ && $node->class instanceof Node\Name) { $this->addClassToDependencies($scope->resolveName($node->class), $dependenciesReflections); } elseif ($node instanceof Node\Stmt\Trait_ && $node->namespacedName !== null) { try { $classReflection = $this->reflectionProvider->getClass($node->namespacedName->toString()); foreach ($classReflection->getRequireImplementsTags() as $implementsTag) { foreach ($implementsTag->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } catch (ClassNotFoundException $e) { // pass } } elseif ($node instanceof Node\Stmt\TraitUse) { foreach ($node->traits as $traitName) { $this->addClassToDependencies($traitName->toString(), $dependenciesReflections); } $docComment = $node->getDocComment(); if ($docComment !== null) { $usesTags = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, null, $docComment->getText())->getUsesTags(); foreach ($usesTags as $usesTag) { foreach ($usesTag->getType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } } elseif ($node instanceof Node\Expr\Instanceof_) { if ($node->class instanceof Name) { $this->addClassToDependencies($scope->resolveName($node->class), $dependenciesReflections); } } elseif ($node instanceof Node\Stmt\Catch_) { foreach ($node->types as $type) { $this->addClassToDependencies($scope->resolveName($type), $dependenciesReflections); } } elseif ($node instanceof ArrayDimFetch && $node->dim !== null) { $varType = $scope->getType($node->var); $dimType = $scope->getType($node->dim); foreach ($varType->getOffsetValueType($dimType)->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } elseif ($node instanceof Foreach_) { $exprType = $scope->getType($node->expr); if ($node->keyVar !== null) { foreach ($scope->getIterableKeyType($exprType)->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } foreach ($scope->getIterableValueType($exprType)->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } elseif ($node instanceof Array_ && $this->considerArrayForCallableTest($scope, $node)) { $arrayType = $scope->getType($node); if (!$arrayType->isCallable()->no()) { foreach ($arrayType->getCallableParametersAcceptors($scope) as $variant) { $referencedClasses = $variant->getReturnType()->getReferencedClasses(); foreach ($referencedClasses as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } } return new \PHPStan\Dependency\NodeDependencies($this->fileHelper, $dependenciesReflections, $this->exportedNodeResolver->resolve($scope->getFile(), $node)); } public function resolveUsedTraitDependencies(InClassNode $inClassNode) : \PHPStan\Dependency\NodeDependencies { $dependenciesReflections = []; foreach ($inClassNode->getClassReflection()->getTraits(\true) as $trait) { $dependenciesReflections[] = $trait; } return new \PHPStan\Dependency\NodeDependencies($this->fileHelper, $dependenciesReflections, null); } private function considerArrayForCallableTest(Scope $scope, Array_ $arrayNode) : bool { $items = $arrayNode->items; if (count($items) !== 2) { return \false; } if ($items[0] === null) { return \false; } $itemType = $scope->getType($items[0]->value); return $itemType->isClassStringType()->yes(); } /** * @param array $dependenciesReflections */ private function addClassToDependencies(string $className, array &$dependenciesReflections) : void { try { $classReflection = $this->reflectionProvider->getClass($className); } catch (ClassNotFoundException $e) { return; } do { $dependenciesReflections[] = $classReflection; foreach ($classReflection->getInterfaces() as $interface) { $dependenciesReflections[] = $interface; } foreach ($classReflection->getTraits(\true) as $trait) { $dependenciesReflections[] = $trait; } foreach ($classReflection->getResolvedMixinTypes() as $mixinType) { foreach ($mixinType->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getRequireExtendsTags() as $extendsTag) { foreach ($extendsTag->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getTemplateTags() as $templateTag) { foreach ($templateTag->getBound()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } $default = $templateTag->getDefault(); if ($default === null) { continue; } foreach ($default->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getPropertyTags() as $propertyTag) { if ($propertyTag->isReadable()) { foreach ($propertyTag->getReadableType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } } if (!$propertyTag->isWritable()) { continue; } foreach ($propertyTag->getWritableType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getMethodTags() as $methodTag) { foreach ($methodTag->getReturnType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } foreach ($methodTag->getParameters() as $parameter) { foreach ($parameter->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } if ($parameter->getDefaultValue() === null) { continue; } foreach ($parameter->getDefaultValue()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } } } foreach ($classReflection->getExtendsTags() as $extendsTag) { foreach ($extendsTag->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } } foreach ($classReflection->getImplementsTags() as $implementsTag) { foreach ($implementsTag->getType()->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $dependenciesReflections[] = $this->reflectionProvider->getClass($referencedClass); } } $phpDoc = $classReflection->getResolvedPhpDoc(); if ($phpDoc !== null) { foreach ($phpDoc->getTypeAliasImportTags() as $importTag) { $dependenciesReflections[] = $this->reflectionProvider->getClass($importTag->getImportedFrom()); } } $classReflection = $classReflection->getParentClass(); } while ($classReflection !== null); } private function getFunctionReflection(Node\Name $nameNode, ?Scope $scope) : FunctionReflection { return $this->reflectionProvider->getFunction($nameNode, $scope); } /** * @param array $dependenciesReflections */ private function extractFromParametersAcceptor(ParametersAcceptorWithPhpDocs $parametersAcceptor, array &$dependenciesReflections) : void { foreach ($parametersAcceptor->getParameters() as $parameter) { $referencedClasses = array_merge($parameter->getNativeType()->getReferencedClasses(), $parameter->getPhpDocType()->getReferencedClasses()); foreach ($referencedClasses as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } if ($parameter->getOutType() !== null) { foreach ($parameter->getOutType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } if ($parameter->getClosureThisType() === null) { continue; } foreach ($parameter->getClosureThisType()->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } $returnTypeReferencedClasses = array_merge($parametersAcceptor->getNativeReturnType()->getReferencedClasses(), $parametersAcceptor->getPhpDocReturnType()->getReferencedClasses()); foreach ($returnTypeReferencedClasses as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } /** * @param array $dependenciesReflections */ private function extractThrowType(?Type $throwType, array &$dependenciesReflections) : void { if ($throwType === null) { return; } foreach ($throwType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } } } */ private $reflections; /** * @var ?RootExportedNode */ private $exportedNode; /** * @param array $reflections */ public function __construct(FileHelper $fileHelper, array $reflections, ?\PHPStan\Dependency\RootExportedNode $exportedNode) { $this->fileHelper = $fileHelper; $this->reflections = $reflections; $this->exportedNode = $exportedNode; } /** * @param array $analysedFiles * @return string[] */ public function getFileDependencies(string $currentFile, array $analysedFiles) : array { $dependencies = []; foreach ($this->reflections as $dependencyReflection) { $dependencyFile = $dependencyReflection->getFileName(); if ($dependencyFile === null) { continue; } $dependencyFile = $this->fileHelper->normalizePath($dependencyFile); if ($currentFile === $dependencyFile) { continue; } if (!isset($analysedFiles[$dependencyFile])) { continue; } $dependencies[$dependencyFile] = $dependencyFile; } return array_values($dependencies); } public function getExportedNode() : ?\PHPStan\Dependency\RootExportedNode { return $this->exportedNode; } } fileTypeMapper = $fileTypeMapper; $this->exprPrinter = $exprPrinter; } public function resolve(string $fileName, Node $node) : ?\PHPStan\Dependency\RootExportedNode { if ($node instanceof Class_ && isset($node->namespacedName)) { $docComment = $node->getDocComment(); $extendsName = null; if ($node->extends !== null) { $extendsName = $node->extends->toString(); } $implementsNames = []; foreach ($node->implements as $className) { $implementsNames[] = $className->toString(); } $usedTraits = []; $adaptations = []; foreach ($node->getTraitUses() as $traitUse) { foreach ($traitUse->traits as $usedTraitName) { $usedTraits[] = $usedTraitName->toString(); } foreach ($traitUse->adaptations as $adaptation) { $adaptations[] = $adaptation; } } $className = $node->namespacedName->toString(); return new ExportedClassNode($className, $this->exportPhpDocNode($fileName, $className, null, $docComment !== null ? $docComment->getText() : null), $node->isAbstract(), $node->isFinal(), $extendsName, $implementsNames, $usedTraits, array_map(static function (Node\Stmt\TraitUseAdaptation $adaptation) : ExportedTraitUseAdaptation { if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) { return ExportedTraitUseAdaptation::createAlias($adaptation->trait !== null ? $adaptation->trait->toString() : null, $adaptation->method->toString(), $adaptation->newModifier, $adaptation->newName !== null ? $adaptation->newName->toString() : null); } if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Precedence) { return ExportedTraitUseAdaptation::createPrecedence($adaptation->trait !== null ? $adaptation->trait->toString() : null, $adaptation->method->toString(), array_map(static function (Name $name) : string { return $name->toString(); }, $adaptation->insteadof)); } throw new ShouldNotHappenException(); }, $adaptations), $this->exportClassStatements($node->stmts, $fileName, $className), $this->exportAttributeNodes($node->attrGroups)); } if ($node instanceof Node\Stmt\Interface_ && isset($node->namespacedName)) { $extendsNames = array_map(static function (Name $name) : string { return (string) $name; }, $node->extends); $docComment = $node->getDocComment(); $interfaceName = $node->namespacedName->toString(); return new ExportedInterfaceNode($interfaceName, $this->exportPhpDocNode($fileName, $interfaceName, null, $docComment !== null ? $docComment->getText() : null), $extendsNames, $this->exportClassStatements($node->stmts, $fileName, $interfaceName)); } if ($node instanceof Node\Stmt\Enum_ && $node->namespacedName !== null) { $implementsNames = array_map(static function (Name $name) : string { return (string) $name; }, $node->implements); $docComment = $node->getDocComment(); $enumName = $node->namespacedName->toString(); $scalarType = null; if ($node->scalarType !== null) { $scalarType = $node->scalarType->toString(); } return new ExportedEnumNode($enumName, $scalarType, $this->exportPhpDocNode($fileName, $enumName, null, $docComment !== null ? $docComment->getText() : null), $implementsNames, $this->exportClassStatements($node->stmts, $fileName, $enumName), $this->exportAttributeNodes($node->attrGroups)); } if ($node instanceof Node\Stmt\Trait_ && isset($node->namespacedName)) { $docComment = $node->getDocComment(); $usedTraits = []; $adaptations = []; foreach ($node->getTraitUses() as $traitUse) { foreach ($traitUse->traits as $usedTraitName) { $usedTraits[] = $usedTraitName->toString(); } foreach ($traitUse->adaptations as $adaptation) { $adaptations[] = $adaptation; } } $className = $node->namespacedName->toString(); return new ExportedTraitNode($className, $this->exportPhpDocNode($fileName, $className, null, $docComment !== null ? $docComment->getText() : null), $usedTraits, array_map(static function (Node\Stmt\TraitUseAdaptation $adaptation) : ExportedTraitUseAdaptation { if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) { return ExportedTraitUseAdaptation::createAlias($adaptation->trait !== null ? $adaptation->trait->toString() : null, $adaptation->method->toString(), $adaptation->newModifier, $adaptation->newName !== null ? $adaptation->newName->toString() : null); } if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Precedence) { return ExportedTraitUseAdaptation::createPrecedence($adaptation->trait !== null ? $adaptation->trait->toString() : null, $adaptation->method->toString(), array_map(static function (Name $name) : string { return $name->toString(); }, $adaptation->insteadof)); } throw new ShouldNotHappenException(); }, $adaptations), $this->exportClassStatements($node->stmts, $fileName, $className), $this->exportAttributeNodes($node->attrGroups)); } if ($node instanceof Function_) { $functionName = $node->name->name; if (isset($node->namespacedName)) { $functionName = (string) $node->namespacedName; } $docComment = $node->getDocComment(); return new ExportedFunctionNode($functionName, $this->exportPhpDocNode($fileName, null, $functionName, $docComment !== null ? $docComment->getText() : null), $node->byRef, NodeTypePrinter::printType($node->returnType), $this->exportParameterNodes($node->params), $this->exportAttributeNodes($node->attrGroups)); } return null; } /** * @param Node\Param[] $params * @return ExportedParameterNode[] */ private function exportParameterNodes(array $params) : array { $nodes = []; foreach ($params as $param) { if (!$param->var instanceof Node\Expr\Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $type = $param->type; if ($type !== null && $param->default instanceof Node\Expr\ConstFetch && $param->default->name->toLowerString() === 'null') { if ($type instanceof Node\UnionType) { $innerTypes = $type->types; $innerTypes[] = new Name('null'); $type = new Node\UnionType($innerTypes); } elseif ($type instanceof Node\Identifier || $type instanceof Name) { $type = new Node\NullableType($type); } } $nodes[] = new ExportedParameterNode($param->var->name, NodeTypePrinter::printType($type), $param->byRef, $param->variadic, $param->default !== null, $this->exportAttributeNodes($param->attrGroups)); } return $nodes; } private function exportPhpDocNode(string $file, ?string $className, ?string $functionName, ?string $text) : ?ExportedPhpDocNode { if ($text === null) { return null; } $resolvedPhpDocBlock = $this->fileTypeMapper->getResolvedPhpDoc($file, $className, null, $functionName, $text); $nameScope = $resolvedPhpDocBlock->getNullableNameScope(); if ($nameScope === null) { return null; } return new ExportedPhpDocNode($text, $nameScope->getNamespace(), $nameScope->getUses(), $nameScope->getConstUses()); } /** * @param Node\Stmt[] $statements * @return ExportedNode[] */ private function exportClassStatements(array $statements, string $fileName, string $namespacedName) : array { $exportedNodes = []; foreach ($statements as $statement) { $exportedNode = $this->exportClassStatement($statement, $fileName, $namespacedName); if ($exportedNode === null) { continue; } $exportedNodes[] = $exportedNode; } return $exportedNodes; } private function exportClassStatement(Node\Stmt $node, string $fileName, string $namespacedName) : ?\PHPStan\Dependency\ExportedNode { if ($node instanceof ClassMethod) { if ($node->isAbstract() || $node->isFinal() || !$node->isPrivate()) { $methodName = $node->name->toString(); $docComment = $node->getDocComment(); return new ExportedMethodNode($methodName, $this->exportPhpDocNode($fileName, $namespacedName, $methodName, $docComment !== null ? $docComment->getText() : null), $node->byRef, $node->isPublic(), $node->isPrivate(), $node->isAbstract(), $node->isFinal(), $node->isStatic(), NodeTypePrinter::printType($node->returnType), $this->exportParameterNodes($node->params), $this->exportAttributeNodes($node->attrGroups)); } } if ($node instanceof Node\Stmt\Property) { if ($node->isPrivate()) { return null; } $docComment = $node->getDocComment(); return new ExportedPropertiesNode(array_map(static function (Node\Stmt\PropertyProperty $prop) : string { return $prop->name->toString(); }, $node->props), $this->exportPhpDocNode($fileName, $namespacedName, null, $docComment !== null ? $docComment->getText() : null), NodeTypePrinter::printType($node->type), $node->isPublic(), $node->isPrivate(), $node->isStatic(), $node->isReadonly(), $this->exportAttributeNodes($node->attrGroups)); } if ($node instanceof Node\Stmt\ClassConst) { if ($node->isPrivate()) { return null; } $docComment = $node->getDocComment(); $constants = []; foreach ($node->consts as $const) { $constants[] = new ExportedClassConstantNode($const->name->toString(), $this->exprPrinter->printExpr($const->value), $this->exportAttributeNodes($node->attrGroups)); } return new ExportedClassConstantsNode($constants, $node->isPublic(), $node->isPrivate(), $node->isFinal(), $this->exportPhpDocNode($fileName, $namespacedName, null, $docComment !== null ? $docComment->getText() : null)); } if ($node instanceof Node\Stmt\EnumCase) { $docComment = $node->getDocComment(); return new ExportedEnumCaseNode($node->name->toString(), $node->expr !== null ? $this->exprPrinter->printExpr($node->expr) : null, $this->exportPhpDocNode($fileName, $namespacedName, null, $docComment !== null ? $docComment->getText() : null)); } return null; } /** * @param Node\AttributeGroup[] $attributeGroups * @return ExportedAttributeNode[] */ private function exportAttributeNodes(array $attributeGroups) : array { $nodes = []; foreach ($attributeGroups as $attributeGroup) { foreach ($attributeGroup->attrs as $attribute) { $args = []; foreach ($attribute->args as $i => $arg) { $args[$arg->name->name ?? $i] = $this->exprPrinter->printExpr($arg->value); } $nodes[] = new ExportedAttributeNode($attribute->name->toString(), $args); } } return $nodes; } } */ private static $containers = []; /** @api */ public static function getContainer() : Container { $additionalConfigFiles = static::getAdditionalConfigFiles(); $additionalConfigFiles[] = __DIR__ . '/TestCase.neon'; $cacheKey = sha1(implode("\n", $additionalConfigFiles)); if (!isset(self::$containers[$cacheKey])) { $tmpDir = sys_get_temp_dir() . '/phpstan-tests'; try { DirectoryCreator::ensureDirectoryExists($tmpDir, 0777); } catch (DirectoryCreatorException $e) { self::fail($e->getMessage()); } $rootDir = __DIR__ . '/../..'; $fileHelper = new FileHelper($rootDir); $rootDir = $fileHelper->normalizePath($rootDir, '/'); $containerFactory = new ContainerFactory($rootDir); $container = $containerFactory->create($tmpDir, array_merge([$containerFactory->getConfigDirectory() . '/config.level8.neon'], $additionalConfigFiles), []); self::$containers[$cacheKey] = $container; foreach ($container->getParameter('bootstrapFiles') as $bootstrapFile) { (static function (string $file) use($container) : void { require_once $file; })($bootstrapFile); } if (PHP_VERSION_ID >= 80000) { require_once __DIR__ . '/../../stubs/runtime/Enum/UnitEnum.php'; require_once __DIR__ . '/../../stubs/runtime/Enum/BackedEnum.php'; require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnum.php'; require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnumUnitCase.php'; require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnumBackedCase.php'; } } else { ContainerFactory::postInitializeContainer(self::$containers[$cacheKey]); } return self::$containers[$cacheKey]; } /** * @return string[] */ public static function getAdditionalConfigFiles() : array { return []; } public static function getParser() : Parser { /** @var Parser $parser */ $parser = self::getContainer()->getService('defaultAnalysisParser'); return $parser; } /** * @api * @deprecated Use createReflectionProvider() instead */ public function createBroker() : Broker { return self::getContainer()->getByType(Broker::class); } /** @api */ public static function createReflectionProvider() : ReflectionProvider { return self::getContainer()->getByType(ReflectionProvider::class); } public static function getReflector() : Reflector { return self::getContainer()->getService('betterReflectionReflector'); } /** * @deprecated Use getReflector() instead. * @return array{ClassReflector, FunctionReflector, ConstantReflector} */ public static function getReflectors() : array { return [self::getContainer()->getService('betterReflectionClassReflector'), self::getContainer()->getService('betterReflectionFunctionReflector'), self::getContainer()->getService('betterReflectionConstantReflector')]; } public static function getClassReflectionExtensionRegistryProvider() : ClassReflectionExtensionRegistryProvider { return self::getContainer()->getByType(ClassReflectionExtensionRegistryProvider::class); } /** * @param string[] $dynamicConstantNames */ public static function createScopeFactory(ReflectionProvider $reflectionProvider, TypeSpecifier $typeSpecifier, array $dynamicConstantNames = []) : ScopeFactory { $container = self::getContainer(); if (count($dynamicConstantNames) === 0) { $dynamicConstantNames = $container->getParameter('dynamicConstantNames'); } $reflectionProviderProvider = new DirectReflectionProviderProvider($reflectionProvider); $constantResolver = new ConstantResolver($reflectionProviderProvider, $dynamicConstantNames); $initializerExprTypeResolver = new InitializerExprTypeResolver($constantResolver, $reflectionProviderProvider, $container->getByType(PhpVersion::class), $container->getByType(OperatorTypeSpecifyingExtensionRegistryProvider::class), new OversizedArrayBuilder(), $container->getParameter('usePathConstantsAsConstantString')); return new ScopeFactory(new DirectInternalScopeFactory(MutatingScope::class, $reflectionProvider, $initializerExprTypeResolver, $container->getByType(DynamicReturnTypeExtensionRegistryProvider::class), $container->getByType(ExpressionTypeResolverExtensionRegistryProvider::class), $container->getByType(ExprPrinter::class), $typeSpecifier, new PropertyReflectionFinder(), self::getParser(), $container->getByType(NodeScopeResolver::class), new RicherScopeGetTypeHelper($initializerExprTypeResolver), $container->getByType(PhpVersion::class), $container->getParameter('featureToggles')['explicitMixedInUnknownGenericNew'], $container->getParameter('featureToggles')['explicitMixedForGlobalVariables'], $constantResolver)); } /** * @param array $globalTypeAliases */ public static function createTypeAliasResolver(array $globalTypeAliases, ReflectionProvider $reflectionProvider) : TypeAliasResolver { $container = self::getContainer(); return new UsefulTypeAliasResolver($globalTypeAliases, $container->getByType(TypeStringResolver::class), $container->getByType(TypeNodeResolver::class), $reflectionProvider); } protected function shouldTreatPhpDocTypesAsCertain() : bool { return \true; } public static function getFileHelper() : FileHelper { return self::getContainer()->getByType(FileHelper::class); } /** * Provides a DIRECTORY_SEPARATOR agnostic assertion helper, to compare file paths. * */ protected function assertSamePaths(string $expected, string $actual, string $message = '') : void { $expected = $this->getFileHelper()->normalizePath($expected); $actual = $this->getFileHelper()->normalizePath($actual); $this->assertSame($expected, $actual, $message); } /** * @param Error[]|string[] $errors */ protected function assertNoErrors(array $errors) : void { try { $this->assertCount(0, $errors); } catch (ExpectationFailedException $e) { $messages = []; foreach ($errors as $error) { if ($error instanceof Error) { $messages[] = sprintf("- %s\n in %s on line %d\n", rtrim($error->getMessage(), '.'), $error->getFile(), $error->getLine()); } else { $messages[] = $error; } } $this->fail($e->getMessage() . "\n\nEmitted errors:\n" . implode("\n", $messages)); } } protected function skipIfNotOnWindows() : void { if (DIRECTORY_SEPARATOR === '\\') { return; } self::markTestSkipped(); } protected function skipIfNotOnUnix() : void { if (DIRECTORY_SEPARATOR === '/') { return; } self::markTestSkipped(); } } */ private $outputStream = []; /** @var array */ private $output = []; private function getOutputStream(bool $decorated = \false, bool $verbose = \false) : StreamOutput { $kind = $decorated ? self::KIND_DECORATED : self::KIND_PLAIN; $kind .= $verbose ? self::KIND_VERBOSE : self::KIND_NOT_VERBOSE; if (!isset($this->outputStream[$kind])) { $resource = fopen('php://memory', 'w', \false); if ($resource === \false) { throw new ShouldNotHappenException(); } $verbosity = $verbose ? StreamOutput::VERBOSITY_VERBOSE : StreamOutput::VERBOSITY_NORMAL; $this->outputStream[$kind] = new StreamOutput($resource, $verbosity, $decorated); } return $this->outputStream[$kind]; } protected function getOutput(bool $decorated = \false, bool $verbose = \false) : Output { $kind = $decorated ? self::KIND_DECORATED : self::KIND_PLAIN; $kind .= $verbose ? self::KIND_VERBOSE : self::KIND_NOT_VERBOSE; if (!isset($this->output[$kind])) { $outputStream = $this->getOutputStream($decorated, $verbose); $errorConsoleStyle = new ErrorsConsoleStyle(new StringInput(''), $outputStream); $this->output[$kind] = new SymfonyOutput($outputStream, new SymfonyStyle($errorConsoleStyle)); } return $this->output[$kind]; } protected function getOutputContent(bool $decorated = \false, bool $verbose = \false) : string { rewind($this->getOutputStream($decorated, $verbose)->getStream()); $contents = stream_get_contents($this->getOutputStream($decorated, $verbose)->getStream()); if ($contents === \false) { throw new ShouldNotHappenException(); } return $this->rtrimMultiline($contents); } /** * @param array{int, int}|int $numFileErrors */ protected function getAnalysisResult($numFileErrors, int $numGenericErrors) : AnalysisResult { if (is_int($numFileErrors)) { $offsetFileErrors = 0; } else { [$offsetFileErrors, $numFileErrors] = $numFileErrors; } if (!in_array($numFileErrors, range(0, 6), \true) || !in_array($offsetFileErrors, range(0, 6), \true) || !in_array($numGenericErrors, range(0, 2), \true)) { throw new ShouldNotHappenException(); } $fileErrors = array_slice([new Error('Foo', self::DIRECTORY_PATH . '/folder with unicode 😃/file name with "spaces" and unicode 😃.php', 4), new Error('Foo', self::DIRECTORY_PATH . '/foo.php', 1), new Error("Bar\nBar2", self::DIRECTORY_PATH . '/foo.php', 5, \true, null, null, 'a tip'), new Error("Bar\nBar2", self::DIRECTORY_PATH . '/folder with unicode 😃/file name with "spaces" and unicode 😃.php', 2), new Error("Bar\nBar2", self::DIRECTORY_PATH . '/foo.php', null), new Error('Foobar\\Buz', self::DIRECTORY_PATH . '/foo.php', 5, \true, null, null, 'a tip', null, null, 'foobar.buz')], $offsetFileErrors, $numFileErrors); $genericErrors = array_slice(['first generic error', 'second generic'], 0, $numGenericErrors); return new AnalysisResult($fileErrors, $genericErrors, [], [], [], \false, null, \true, 0, \false, []); } private function rtrimMultiline(string $output) : string { $result = array_map(static function (string $line) : string { return rtrim($line, " \r\n"); }, explode("\n", $output)); return implode("\n", $result); } } , analyseAndScan?: array}|null */ private $excludePaths; /** @var array> */ private static $composerSourceLocatorsCache = []; /** * @param string[] $fileExtensions * @param string[] $obsoleteExcludesAnalyse * @param array{analyse?: array, analyseAndScan?: array}|null $excludePaths */ public function __construct(ComposerJsonAndInstalledJsonSourceLocatorMaker $composerJsonAndInstalledJsonSourceLocatorMaker, Parser $phpParser, Parser $php8Parser, FileNodesFetcher $fileNodesFetcher, PhpStormStubsSourceStubber $phpstormStubsSourceStubber, ReflectionSourceStubber $reflectionSourceStubber, PhpVersion $phpVersion, array $fileExtensions, array $obsoleteExcludesAnalyse, ?array $excludePaths) { $this->composerJsonAndInstalledJsonSourceLocatorMaker = $composerJsonAndInstalledJsonSourceLocatorMaker; $this->phpParser = $phpParser; $this->php8Parser = $php8Parser; $this->fileNodesFetcher = $fileNodesFetcher; $this->phpstormStubsSourceStubber = $phpstormStubsSourceStubber; $this->reflectionSourceStubber = $reflectionSourceStubber; $this->phpVersion = $phpVersion; $this->fileExtensions = $fileExtensions; $this->obsoleteExcludesAnalyse = $obsoleteExcludesAnalyse; $this->excludePaths = $excludePaths; } public function create() : SourceLocator { $classLoaders = ClassLoader::getRegisteredLoaders(); $classLoaderReflection = new ReflectionClass(ClassLoader::class); $cacheKey = sha1(serialize([$this->phpVersion->getVersionId(), $this->fileExtensions, $this->obsoleteExcludesAnalyse, $this->excludePaths])); if ($classLoaderReflection->hasProperty('vendorDir') && !isset(self::$composerSourceLocatorsCache[$cacheKey])) { $composerLocators = []; $vendorDirProperty = $classLoaderReflection->getProperty('vendorDir'); $vendorDirProperty->setAccessible(\true); foreach ($classLoaders as $classLoader) { $composerProjectPath = dirname($vendorDirProperty->getValue($classLoader)); if (!is_file($composerProjectPath . '/composer.json')) { continue; } $composerSourceLocator = $this->composerJsonAndInstalledJsonSourceLocatorMaker->create($composerProjectPath); if ($composerSourceLocator === null) { continue; } $composerLocators[] = $composerSourceLocator; } self::$composerSourceLocatorsCache[$cacheKey] = $composerLocators; } $locators = self::$composerSourceLocatorsCache[$cacheKey] ?? []; $astLocator = new Locator($this->phpParser); $astPhp8Locator = new Locator($this->php8Parser); $locators[] = new PhpInternalSourceLocator($astPhp8Locator, $this->phpstormStubsSourceStubber); $locators[] = new AutoloadSourceLocator($this->fileNodesFetcher, \true); $locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber); $locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber); return new MemoizingSourceLocator(new AggregateSourceLocator($locators)); } } getService('typeSpecifier'); $fileHelper = self::getContainer()->getByType(FileHelper::class); $resolver = new NodeScopeResolver($reflectionProvider, self::getContainer()->getByType(InitializerExprTypeResolver::class), self::getReflector(), self::getClassReflectionExtensionRegistryProvider(), self::getContainer()->getByType(ParameterOutTypeExtensionProvider::class), self::getParser(), self::getContainer()->getByType(FileTypeMapper::class), self::getContainer()->getByType(StubPhpDocProvider::class), self::getContainer()->getByType(PhpVersion::class), self::getContainer()->getByType(SignatureMapProvider::class), self::getContainer()->getByType(PhpDocInheritanceResolver::class), self::getContainer()->getByType(FileHelper::class), $typeSpecifier, self::getContainer()->getByType(DynamicThrowTypeExtensionProvider::class), self::getContainer()->getByType(ReadWritePropertiesExtensionProvider::class), self::getContainer()->getByType(ParameterClosureTypeExtensionProvider::class), self::createScopeFactory($reflectionProvider, $typeSpecifier), self::getContainer()->getParameter('polluteScopeWithLoopInitialAssignments'), self::getContainer()->getParameter('polluteScopeWithAlwaysIterableForeach'), static::getEarlyTerminatingMethodCalls(), static::getEarlyTerminatingFunctionCalls(), self::getContainer()->getParameter('universalObjectCratesClasses'), self::getContainer()->getParameter('exceptions')['implicitThrows'], self::getContainer()->getParameter('treatPhpDocTypesAsCertain'), self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], self::getContainer()->getParameter('featureToggles')['paramOutType'], self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], self::getContainer()->getParameter('featureToggles')['explicitThrow']); $resolver->setAnalysedFiles(array_map(static function (string $file) use($fileHelper) : string { return $fileHelper->normalizePath($file); }, array_merge([$file], static::getAdditionalAnalysedFiles()))); $scopeFactory = self::createScopeFactory($reflectionProvider, $typeSpecifier, $dynamicConstantNames); $scope = $scopeFactory->create(ScopeContext::create($file)); $resolver->processNodes(self::getParser()->parseFile($file), $scope, $callback); } /** * @api * @param mixed ...$args */ public function assertFileAsserts(string $assertType, string $file, ...$args) : void { if ($assertType === 'type') { if ($args[0] instanceof Type) { // backward compatibility $expectedType = $args[0]; $this->assertInstanceOf(ConstantScalarType::class, $expectedType); $expected = $expectedType->getValue(); $actualType = $args[1]; $actual = $actualType->describe(VerbosityLevel::precise()); } else { $expected = $args[0]; $actual = $args[1]; } $this->assertSame($expected, $actual, sprintf('Expected type %s, got type %s in %s on line %d.', $expected, $actual, $file, $args[2])); } elseif ($assertType === 'variableCertainty') { $expectedCertainty = $args[0]; $actualCertainty = $args[1]; $variableName = $args[2]; $this->assertTrue($expectedCertainty->equals($actualCertainty), sprintf('Expected %s, actual certainty of %s is %s in %s on line %d.', $expectedCertainty->describe(), $variableName, $actualCertainty->describe(), $file, $args[3])); } } /** * @api * @return array */ public static function gatherAssertTypes(string $file) : array { $fileHelper = self::getContainer()->getByType(FileHelper::class); $relativePathHelper = new SystemAgnosticSimpleRelativePathHelper($fileHelper); $file = $fileHelper->normalizePath($file); $asserts = []; self::processFile($file, static function (Node $node, Scope $scope) use(&$asserts, $file, $relativePathHelper) : void { if (!$node instanceof Node\Expr\FuncCall) { return; } $nameNode = $node->name; if (!$nameNode instanceof Name) { return; } $functionName = $nameNode->toString(); if (in_array(strtolower($functionName), ['asserttype', 'assertnativetype', 'assertvariablecertainty'], \true)) { self::fail(sprintf('Missing use statement for %s() in %s on line %d.', $functionName, $relativePathHelper->getRelativePath($file), $node->getStartLine())); } elseif ($functionName === 'PHPStan\\Testing\\assertType') { $expectedType = $scope->getType($node->getArgs()[0]->value); if (!$expectedType instanceof ConstantScalarType) { self::fail(sprintf('Expected type must be a literal string, %s given in %s on line %d.', $expectedType->describe(VerbosityLevel::precise()), $relativePathHelper->getRelativePath($file), $node->getLine())); } $actualType = $scope->getType($node->getArgs()[1]->value); $assert = ['type', $file, $expectedType->getValue(), $actualType->describe(VerbosityLevel::precise()), $node->getStartLine()]; } elseif ($functionName === 'PHPStan\\Testing\\assertNativeType') { $expectedType = $scope->getType($node->getArgs()[0]->value); if (!$expectedType instanceof ConstantScalarType) { self::fail(sprintf('Expected type must be a literal string, %s given in %s on line %d.', $expectedType->describe(VerbosityLevel::precise()), $relativePathHelper->getRelativePath($file), $node->getLine())); } $actualType = $scope->getNativeType($node->getArgs()[1]->value); $assert = ['type', $file, $expectedType->getValue(), $actualType->describe(VerbosityLevel::precise()), $node->getStartLine()]; } elseif ($functionName === 'PHPStan\\Testing\\assertVariableCertainty') { $certainty = $node->getArgs()[0]->value; if (!$certainty instanceof StaticCall) { self::fail(sprintf('First argument of %s() must be TrinaryLogic call', $functionName)); } if (!$certainty->class instanceof Node\Name) { self::fail(sprintf('ERROR: Invalid TrinaryLogic call.')); } if ($certainty->class->toString() !== 'PHPStan\\TrinaryLogic') { self::fail(sprintf('ERROR: Invalid TrinaryLogic call.')); } if (!$certainty->name instanceof Node\Identifier) { self::fail(sprintf('ERROR: Invalid TrinaryLogic call.')); } // @phpstan-ignore staticMethod.dynamicName $expectedertaintyValue = TrinaryLogic::{$certainty->name->toString()}(); $variable = $node->getArgs()[1]->value; if ($variable instanceof Node\Expr\Variable && is_string($variable->name)) { $actualCertaintyValue = $scope->hasVariableType($variable->name); $variableDescription = sprintf('variable $%s', $variable->name); } elseif ($variable instanceof Node\Expr\ArrayDimFetch && $variable->dim !== null) { $offset = $scope->getType($variable->dim); $actualCertaintyValue = $scope->getType($variable->var)->hasOffsetValueType($offset); $variableDescription = sprintf('offset %s', $offset->describe(VerbosityLevel::precise())); } else { self::fail(sprintf('ERROR: Invalid assertVariableCertainty call.')); } $assert = ['variableCertainty', $file, $expectedertaintyValue, $actualCertaintyValue, $variableDescription, $node->getStartLine()]; } else { $correctFunction = null; $assertFunctions = ['assertType' => 'PHPStan\\Testing\\assertType', 'assertNativeType' => 'PHPStan\\Testing\\assertNativeType', 'assertVariableCertainty' => 'PHPStan\\Testing\\assertVariableCertainty']; foreach ($assertFunctions as $assertFn => $fqFunctionName) { if (stripos($functionName, $assertFn) === \false) { continue; } $correctFunction = $fqFunctionName; } if ($correctFunction === null) { return; } self::fail(sprintf('Function %s imported with wrong namespace %s called in %s on line %d.', $correctFunction, $functionName, $relativePathHelper->getRelativePath($file), $node->getStartLine())); } if (count($node->getArgs()) !== 2) { self::fail(sprintf('ERROR: Wrong %s() call in %s on line %d.', $functionName, $relativePathHelper->getRelativePath($file), $node->getStartLine())); } $asserts[$file . ':' . $node->getStartLine()] = $assert; }); if (count($asserts) === 0) { self::fail(sprintf('File %s does not contain any asserts', $file)); } return $asserts; } /** * @api * @return array */ public static function gatherAssertTypesFromDirectory(string $directory) : array { $asserts = []; foreach (self::findTestDataFilesFromDirectory($directory) as $path) { foreach (self::gatherAssertTypes($path) as $key => $assert) { $asserts[$key] = $assert; } } return $asserts; } /** * @return list */ public static function findTestDataFilesFromDirectory(string $directory) : array { if (!is_dir($directory)) { self::fail(sprintf('Directory %s does not exist.', $directory)); } $finder = new Finder(); $finder->followLinks(); $files = []; foreach ($finder->files()->name('*.php')->in($directory) as $fileInfo) { $path = $fileInfo->getPathname(); if (self::isFileLintSkipped($path)) { continue; } $files[] = $path; } return $files; } /** * From https://github.com/php-parallel-lint/PHP-Parallel-Lint/blob/0c2706086ac36dce31967cb36062ff8915fe03f7/bin/skip-linting.php * * Copyright (c) 2012, Jakub Onderka */ private static function isFileLintSkipped(string $file) : bool { $f = @fopen($file, 'r'); if ($f !== \false) { $firstLine = fgets($f); if ($firstLine === \false) { return \false; } // ignore shebang line if (strpos($firstLine, '#!') === 0) { $firstLine = fgets($f); if ($firstLine === \false) { return \false; } } @fclose($f); if (preg_match('~> */ protected function getCollectors() : array { return []; } /** * @return ReadWritePropertiesExtension[] */ protected function getReadWritePropertiesExtensions() : array { return []; } protected function getTypeSpecifier() : TypeSpecifier { return self::getContainer()->getService('typeSpecifier'); } private function getAnalyser(DirectRuleRegistry $ruleRegistry) : Analyser { if ($this->analyser === null) { $collectorRegistry = new CollectorRegistry($this->getCollectors()); $reflectionProvider = $this->createReflectionProvider(); $typeSpecifier = $this->getTypeSpecifier(); $readWritePropertiesExtensions = $this->getReadWritePropertiesExtensions(); $nodeScopeResolver = new NodeScopeResolver($reflectionProvider, self::getContainer()->getByType(InitializerExprTypeResolver::class), self::getReflector(), self::getClassReflectionExtensionRegistryProvider(), self::getContainer()->getByType(ParameterOutTypeExtensionProvider::class), $this->getParser(), self::getContainer()->getByType(FileTypeMapper::class), self::getContainer()->getByType(StubPhpDocProvider::class), self::getContainer()->getByType(PhpVersion::class), self::getContainer()->getByType(SignatureMapProvider::class), self::getContainer()->getByType(PhpDocInheritanceResolver::class), self::getContainer()->getByType(FileHelper::class), $typeSpecifier, self::getContainer()->getByType(DynamicThrowTypeExtensionProvider::class), $readWritePropertiesExtensions !== [] ? new DirectReadWritePropertiesExtensionProvider($readWritePropertiesExtensions) : self::getContainer()->getByType(ReadWritePropertiesExtensionProvider::class), self::getContainer()->getByType(ParameterClosureTypeExtensionProvider::class), self::createScopeFactory($reflectionProvider, $typeSpecifier), $this->shouldPolluteScopeWithLoopInitialAssignments(), $this->shouldPolluteScopeWithAlwaysIterableForeach(), [], [], self::getContainer()->getParameter('universalObjectCratesClasses'), self::getContainer()->getParameter('exceptions')['implicitThrows'], $this->shouldTreatPhpDocTypesAsCertain(), self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], self::getContainer()->getParameter('featureToggles')['paramOutType'], self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], self::getContainer()->getParameter('featureToggles')['explicitThrow']); $fileAnalyser = new FileAnalyser($this->createScopeFactory($reflectionProvider, $typeSpecifier), $nodeScopeResolver, $this->getParser(), self::getContainer()->getByType(DependencyResolver::class), new RuleErrorTransformer(), new LocalIgnoresProcessor()); $this->analyser = new Analyser($fileAnalyser, $ruleRegistry, $collectorRegistry, $nodeScopeResolver, 50); } return $this->analyser; } /** * @param string[] $files * @param list $expectedErrors */ public function analyse(array $files, array $expectedErrors) : void { $actualErrors = $this->gatherAnalyserErrors($files); $strictlyTypedSprintf = static function (int $line, string $message, ?string $tip) : string { $message = sprintf('%02d: %s', $line, $message); if ($tip !== null) { $message .= "\n 💡 " . $tip; } return $message; }; $expectedErrors = array_map(static function (array $error) use($strictlyTypedSprintf) : string { return $strictlyTypedSprintf($error[1], $error[0], $error[2] ?? null); }, $expectedErrors); $actualErrors = array_map(static function (Error $error) use($strictlyTypedSprintf) : string { $line = $error->getLine(); if ($line === null) { return $strictlyTypedSprintf(-1, $error->getMessage(), $error->getTip()); } return $strictlyTypedSprintf($line, $error->getMessage(), $error->getTip()); }, $actualErrors); $this->assertSame(implode("\n", $expectedErrors) . "\n", implode("\n", $actualErrors) . "\n"); } /** * @param string[] $files * @return list */ public function gatherAnalyserErrors(array $files) : array { $ruleRegistry = new DirectRuleRegistry([$this->getRule()]); $files = array_map([$this->getFileHelper(), 'normalizePath'], $files); $analyserResult = $this->getAnalyser($ruleRegistry)->analyse($files, null, null, \true); if (count($analyserResult->getInternalErrors()) > 0) { $this->fail(implode("\n", array_map(static function (InternalError $internalError) { return $internalError->getMessage(); }, $analyserResult->getInternalErrors()))); } if ($this->shouldFailOnPhpErrors() && count($analyserResult->getAllPhpErrors()) > 0) { $this->fail(implode("\n", array_map(static function (Error $error) : string { return sprintf('%s on %s:%d', $error->getMessage(), $error->getFile(), $error->getLine()); }, $analyserResult->getAllPhpErrors()))); } $finalizer = new AnalyserResultFinalizer($ruleRegistry, new RuleErrorTransformer(), $this->createScopeFactory($this->createReflectionProvider(), $this->getTypeSpecifier()), new LocalIgnoresProcessor(), \true); return $finalizer->finalize($analyserResult, \false, \true)->getAnalyserResult()->getUnorderedErrors(); } protected function shouldPolluteScopeWithLoopInitialAssignments() : bool { return \false; } protected function shouldPolluteScopeWithAlwaysIterableForeach() : bool { return \true; } protected function shouldFailOnPhpErrors() : bool { return \true; } public static function getAdditionalConfigFiles() : array { return [__DIR__ . '/../../conf/bleedingEdge.neon']; } } > */ public abstract function dataTopics() : array; public abstract function getDataPath() : string; public abstract function getPhpStanExecutablePath() : string; public abstract function getPhpStanConfigPath() : ?string; protected function getResultSuffix() : string { return ''; } protected function shouldAutoloadAnalysedFile() : bool { return \true; } /** * @dataProvider dataTopics */ public function testLevels(string $topic) : void { $file = sprintf('%s' . DIRECTORY_SEPARATOR . '%s.php', $this->getDataPath(), $topic); $command = escapeshellcmd($this->getPhpStanExecutablePath()); $configPath = $this->getPhpStanConfigPath(); $fileHelper = new FileHelper(__DIR__ . '/../..'); $previousMessages = []; $exceptions = []; exec(sprintf('%s %s clear-result-cache %s 2>&1', escapeshellarg(PHP_BINARY), $command, $configPath !== null ? '--configuration ' . escapeshellarg($configPath) : ''), $clearResultCacheOutputLines, $clearResultCacheExitCode); if ($clearResultCacheExitCode !== 0) { throw new ShouldNotHappenException('Could not clear result cache: ' . implode("\n", $clearResultCacheOutputLines)); } putenv('__PHPSTAN_FORCE_VALIDATE_STUB_FILES=1'); foreach (range(0, 9) as $level) { unset($outputLines); exec(sprintf('%s %s analyse --no-progress --error-format=prettyJson --level=%d %s %s %s', escapeshellarg(PHP_BINARY), $command, $level, $configPath !== null ? '--configuration ' . escapeshellarg($configPath) : '', $this->shouldAutoloadAnalysedFile() ? sprintf('--autoload-file %s', escapeshellarg($file)) : '', escapeshellarg($file)), $outputLines); $output = implode("\n", $outputLines); try { $actualJson = Json::decode($output, Json::FORCE_ARRAY); } catch (JsonException $e) { throw new JsonException(sprintf('Cannot decode: %s', $output)); } if (count($actualJson['files']) > 0) { $normalizedFilePath = $fileHelper->normalizePath($file); if (!isset($actualJson['files'][$normalizedFilePath])) { $messagesBeforeDiffing = []; } else { $messagesBeforeDiffing = $actualJson['files'][$normalizedFilePath]['messages']; } foreach ($this->getAdditionalAnalysedFiles() as $additionalAnalysedFile) { $normalizedAdditionalFilePath = $fileHelper->normalizePath($additionalAnalysedFile); if (!isset($actualJson['files'][$normalizedAdditionalFilePath])) { continue; } $messagesBeforeDiffing = array_merge($messagesBeforeDiffing, $actualJson['files'][$normalizedAdditionalFilePath]['messages']); } } else { $messagesBeforeDiffing = []; } $messages = []; foreach ($messagesBeforeDiffing as $message) { foreach ($previousMessages as $lastMessage) { if ($message['message'] === $lastMessage['message'] && $message['line'] === $lastMessage['line']) { continue 2; } } unset($message['tip']); unset($message['identifier']); $messages[] = $message; } $missingMessages = []; foreach ($previousMessages as $previousMessage) { foreach ($messagesBeforeDiffing as $message) { if ($previousMessage['message'] === $message['message'] && $previousMessage['line'] === $message['line']) { continue 2; } } unset($previousMessage['tip']); $missingMessages[] = $previousMessage; } $previousMessages = array_merge($previousMessages, $messages); $expectedJsonFile = sprintf('%s/%s-%d%s.json', $this->getDataPath(), $topic, $level, $this->getResultSuffix()); $exception = $this->compareFiles($expectedJsonFile, $messages); if ($exception !== null) { $exceptions[] = $exception; } $expectedJsonMissingFile = sprintf('%s/%s-%d-missing%s.json', $this->getDataPath(), $topic, $level, $this->getResultSuffix()); $exception = $this->compareFiles($expectedJsonMissingFile, $missingMessages); if ($exception === null) { continue; } $exceptions[] = $exception; } if (count($exceptions) > 0) { throw $exceptions[0]; } } /** * @return string[] */ public function getAdditionalAnalysedFiles() : array { return []; } /** * @param string[] $expectedMessages */ private function compareFiles(string $expectedJsonFile, array $expectedMessages) : ?AssertionFailedError { if (count($expectedMessages) === 0) { try { self::ourCustomAssertFileDoesNotExist($expectedJsonFile); return null; } catch (AssertionFailedError $e) { unlink($expectedJsonFile); return $e; } } $actualOutput = Json::encode($expectedMessages, Json::PRETTY); try { $this->assertJsonStringEqualsJsonFile($expectedJsonFile, $actualOutput); } catch (AssertionFailedError $e) { FileWriter::write($expectedJsonFile, $actualOutput); return $e; } return null; } public static function ourCustomAssertFileDoesNotExist(string $filename, string $message = '') : void { // this method is no longer called assertFileDoesNotExist because this method is final in PHPUnit 10 if (!method_exists(parent::class, 'assertFileDoesNotExist')) { parent::assertFileNotExists($filename, $message); return; } parent::assertFileDoesNotExist($filename, $message); } } parameters: inferPrivatePropertyTypeFromConstructor: true featureToggles: checkUnresolvableParameterTypes: true services: - class: PHPStan\Testing\TestCaseSourceLocatorFactory arguments: phpParser: @phpParserDecorator php8Parser: @php8PhpParser fileExtensions: %fileExtensions% obsoleteExcludesAnalyse: %excludes_analyse% excludePaths: %excludePaths% cacheStorage: class: PHPStan\Cache\MemoryCacheStorage arguments!: [] currentPhpVersionSimpleParser!: factory: @currentPhpVersionRichParser currentPhpVersionLexer: class: PhpParser\Lexer factory: @PHPStan\Parser\LexerFactory::createEmulative() betterReflectionSourceLocator: class: PHPStan\BetterReflection\SourceLocator\Type\SourceLocator factory: @PHPStan\Testing\TestCaseSourceLocatorFactory::create() autowired: false reflectionProvider: factory: @betterReflectionProvider arguments!: [] autowired: - PHPStan\Reflection\ReflectionProvider keyType = $keyType; $this->itemType = $itemType; } public function getKeyType() : \PHPStan\Type\Type { return $this->keyType; } public function getItemType() : \PHPStan\Type\Type { return $this->itemType; } /** * @return string[] */ public function getReferencedClasses() : array { return array_merge($this->keyType->getReferencedClasses(), $this->getItemType()->getReferencedClasses()); } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function getConstantStrings() : array { return []; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type->isConstantArray()->yes() && $type->isIterableAtLeastOnce()->no()) { return \PHPStan\Type\AcceptsResult::createYes(); } if ($type->isIterable()->yes()) { return $this->getIterableValueType()->acceptsWithReason($type->getIterableValueType(), $strictTypes)->and($this->getIterableKeyType()->acceptsWithReason($type->getIterableKeyType(), $strictTypes)); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return (new \PHPStan\Type\IsSuperTypeOfResult($type->isIterable(), []))->and($this->getIterableValueType()->isSuperTypeOfWithReason($type->getIterableValueType()))->and($this->getIterableKeyType()->isSuperTypeOfWithReason($type->getIterableKeyType())); } public function isSuperTypeOfMixed(\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isIterable()->and($this->isNestedTypeSuperTypeOf($this->getIterableValueType(), $type->getIterableValueType()))->and($this->isNestedTypeSuperTypeOf($this->getIterableKeyType(), $type->getIterableKeyType())); } private function isNestedTypeSuperTypeOf(\PHPStan\Type\Type $a, \PHPStan\Type\Type $b) : TrinaryLogic { if (!$a instanceof \PHPStan\Type\MixedType || !$b instanceof \PHPStan\Type\MixedType) { return $a->isSuperTypeOf($b); } if ($a instanceof TemplateMixedType || $b instanceof TemplateMixedType) { return $a->isSuperTypeOf($b); } if ($a->isExplicitMixed()) { if ($b->isExplicitMixed()) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } return TrinaryLogic::createYes(); } public function isSubTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof \PHPStan\Type\IntersectionType || $otherType instanceof \PHPStan\Type\UnionType) { return $otherType->isSuperTypeOfWithReason(new \PHPStan\Type\UnionType([new \PHPStan\Type\ArrayType($this->keyType, $this->itemType), new \PHPStan\Type\IntersectionType([new \PHPStan\Type\ObjectType(Traversable::class), $this])])); } if ($otherType instanceof self) { $limit = \PHPStan\Type\IsSuperTypeOfResult::createYes(); } else { $limit = \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($otherType->isConstantArray()->yes() && $otherType->isIterableAtLeastOnce()->no()) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } return $limit->and(new \PHPStan\Type\IsSuperTypeOfResult($otherType->isIterable(), []), $otherType->getIterableValueType()->isSuperTypeOfWithReason($this->itemType), $otherType->getIterableKeyType()->isSuperTypeOfWithReason($this->keyType)); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(\PHPStan\Type\Type $type) : bool { if (!$type instanceof self) { return \false; } return $this->keyType->equals($type->keyType) && $this->itemType->equals($type->itemType); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { $isMixedKeyType = $this->keyType instanceof \PHPStan\Type\MixedType && $this->keyType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed'; $isMixedItemType = $this->itemType instanceof \PHPStan\Type\MixedType && $this->itemType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed'; if ($isMixedKeyType) { if ($isMixedItemType) { return 'iterable'; } return sprintf('iterable<%s>', $this->itemType->describe($level)); } return sprintf('iterable<%s, %s>', $this->keyType->describe($level), $this->itemType->describe($level)); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { if ($this->getIterableKeyType()->isSuperTypeOf($offsetType)->no()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function toNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toString() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toInteger() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toFloat() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toArray() : \PHPStan\Type\Type { return new \PHPStan\Type\ArrayType($this->keyType, $this->getItemType()); } public function toArrayKey() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isIterable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getArraySize() : \PHPStan\Type\Type { return \PHPStan\Type\IntegerRangeType::fromInterval(0, null); } public function getIterableKeyType() : \PHPStan\Type\Type { return $this->keyType; } public function getFirstIterableKeyType() : \PHPStan\Type\Type { return $this->keyType; } public function getLastIterableKeyType() : \PHPStan\Type\Type { return $this->keyType; } public function getIterableValueType() : \PHPStan\Type\Type { return $this->getItemType(); } public function getFirstIterableValueType() : \PHPStan\Type\Type { return $this->getItemType(); } public function getLastIterableValueType() : \PHPStan\Type\Type { return $this->getItemType(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ObjectWithoutClassType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function getEnumCases() : array { return []; } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap { if ($receivedType instanceof \PHPStan\Type\UnionType || $receivedType instanceof \PHPStan\Type\IntersectionType) { return $receivedType->inferTemplateTypesOn($this); } if (!$receivedType->isIterable()->yes()) { return TemplateTypeMap::createEmpty(); } $keyTypeMap = $this->getIterableKeyType()->inferTemplateTypes($receivedType->getIterableKeyType()); $valueTypeMap = $this->getIterableValueType()->inferTemplateTypes($receivedType->getIterableValueType()); return $keyTypeMap->union($valueTypeMap); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { $variance = $positionVariance->compose(TemplateTypeVariance::createCovariant()); return array_merge($this->getIterableKeyType()->getReferencedTemplateTypes($variance), $this->getIterableValueType()->getReferencedTemplateTypes($variance)); } public function traverse(callable $cb) : \PHPStan\Type\Type { $keyType = $cb($this->keyType); $itemType = $cb($this->itemType); if ($keyType !== $this->keyType || $itemType !== $this->itemType) { return new self($keyType, $itemType); } return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { $keyType = $cb($this->keyType, $right->getIterableKeyType()); $itemType = $cb($this->itemType, $right->getIterableValueType()); if ($keyType !== $this->keyType || $itemType !== $this->itemType) { return new self($keyType, $itemType); } return $this; } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { $arrayType = new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()); if ($typeToRemove->isSuperTypeOf($arrayType)->yes()) { return new GenericObjectType(Traversable::class, [$this->getIterableKeyType(), $this->getIterableValueType()]); } $traversableType = new \PHPStan\Type\ObjectType(Traversable::class); if ($typeToRemove->isSuperTypeOf($traversableType)->yes()) { return new \PHPStan\Type\ArrayType($this->getIterableKeyType(), $this->getIterableValueType()); } return null; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { $isMixedKeyType = $this->keyType instanceof \PHPStan\Type\MixedType && $this->keyType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed'; $isMixedItemType = $this->itemType instanceof \PHPStan\Type\MixedType && $this->itemType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed'; if ($isMixedKeyType) { if ($isMixedItemType) { return new IdentifierTypeNode('iterable'); } return new GenericTypeNode(new IdentifierTypeNode('iterable'), [$this->itemType->toPhpDocNode()]); } return new GenericTypeNode(new IdentifierTypeNode('iterable'), [$this->keyType->toPhpDocNode(), $this->itemType->toPhpDocNode()]); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['keyType'], $properties['itemType']); } } min = $min; $this->max = $max; parent::__construct(); assert($min === null || $max === null || $min <= $max); assert($min !== null || $max !== null); } public static function fromInterval(?int $min, ?int $max, int $shift = 0) : \PHPStan\Type\Type { if ($min !== null && $max !== null) { if ($min > $max) { return new \PHPStan\Type\NeverType(); } if ($min === $max) { return new ConstantIntegerType($min + $shift); } } if ($min === null && $max === null) { return new \PHPStan\Type\IntegerType(); } return (new self($min, $max))->shift($shift); } protected static function isDisjoint(?int $minA, ?int $maxA, ?int $minB, ?int $maxB, bool $touchingIsDisjoint = \true) : bool { $offset = $touchingIsDisjoint ? 0 : 1; return $minA !== null && $maxB !== null && $minA > $maxB + $offset || $maxA !== null && $minB !== null && $maxA + $offset < $minB; } /** * Return the range of integers smaller than the given value * * @param int|float $value */ public static function createAllSmallerThan($value) : \PHPStan\Type\Type { if (is_int($value)) { return self::fromInterval(null, $value, -1); } if ($value > PHP_INT_MAX) { return new \PHPStan\Type\IntegerType(); } if ($value <= PHP_INT_MIN) { return new \PHPStan\Type\NeverType(); } return self::fromInterval(null, (int) ceil($value), -1); } /** * Return the range of integers smaller than or equal to the given value * * @param int|float $value */ public static function createAllSmallerThanOrEqualTo($value) : \PHPStan\Type\Type { if (is_int($value)) { return self::fromInterval(null, $value); } if ($value >= PHP_INT_MAX) { return new \PHPStan\Type\IntegerType(); } if ($value < PHP_INT_MIN) { return new \PHPStan\Type\NeverType(); } return self::fromInterval(null, (int) floor($value)); } /** * Return the range of integers greater than the given value * * @param int|float $value */ public static function createAllGreaterThan($value) : \PHPStan\Type\Type { if (is_int($value)) { return self::fromInterval($value, null, 1); } if ($value < PHP_INT_MIN) { return new \PHPStan\Type\IntegerType(); } if ($value >= PHP_INT_MAX) { return new \PHPStan\Type\NeverType(); } return self::fromInterval((int) floor($value), null, 1); } /** * Return the range of integers greater than or equal to the given value * * @param int|float $value */ public static function createAllGreaterThanOrEqualTo($value) : \PHPStan\Type\Type { if (is_int($value)) { return self::fromInterval($value, null); } if ($value <= PHP_INT_MIN) { return new \PHPStan\Type\IntegerType(); } if ($value > PHP_INT_MAX) { return new \PHPStan\Type\NeverType(); } return self::fromInterval((int) ceil($value), null); } public function getMin() : ?int { return $this->min; } public function getMax() : ?int { return $this->max; } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return sprintf('int<%s, %s>', $this->min ?? 'min', $this->max ?? 'max'); } public function shift(int $amount) : \PHPStan\Type\Type { if ($amount === 0) { return $this; } $min = $this->min; $max = $this->max; if ($amount < 0) { if ($max !== null) { if ($max < PHP_INT_MIN - $amount) { return new \PHPStan\Type\NeverType(); } $max += $amount; } if ($min !== null) { $min = $min < PHP_INT_MIN - $amount ? null : $min + $amount; } } else { if ($min !== null) { if ($min > PHP_INT_MAX - $amount) { return new \PHPStan\Type\NeverType(); } $min += $amount; } if ($max !== null) { $max = $max > PHP_INT_MAX - $amount ? null : $max + $amount; } } return self::fromInterval($min, $max); } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof parent) { return $this->isSuperTypeOfWithReason($type)->toAcceptsResult(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self || $type instanceof ConstantIntegerType) { if ($type instanceof self) { $typeMin = $type->min; $typeMax = $type->max; } else { $typeMin = $type->getValue(); $typeMax = $type->getValue(); } if (self::isDisjoint($this->min, $this->max, $typeMin, $typeMax)) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } if (($this->min === null || $typeMin !== null && $this->min <= $typeMin) && ($this->max === null || $typeMax !== null && $this->max >= $typeMax)) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($type instanceof parent) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function isSubTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof parent) { return $otherType->isSuperTypeOfWithReason($this); } if ($otherType instanceof \PHPStan\Type\UnionType) { return $this->isSubTypeOfUnionWithReason($otherType); } if ($otherType instanceof \PHPStan\Type\IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } private function isSubTypeOfUnionWithReason(\PHPStan\Type\UnionType $otherType) : \PHPStan\Type\IsSuperTypeOfResult { if ($this->min !== null && $this->max !== null) { $matchingConstantIntegers = array_filter($otherType->getTypes(), function (\PHPStan\Type\Type $type) : bool { return $type instanceof ConstantIntegerType && $type->getValue() >= $this->min && $type->getValue() <= $this->max; }); if (count($matchingConstantIntegers) === $this->max - $this->min + 1) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } } return \PHPStan\Type\IsSuperTypeOfResult::createNo()->or(...array_map(function (\PHPStan\Type\Type $innerType) { return $this->isSubTypeOfWithReason($innerType); }, $otherType->getTypes())); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self && $this->min === $type->min && $this->max === $type->max; } public function generalize(\PHPStan\Type\GeneralizePrecision $precision) : \PHPStan\Type\Type { return new \PHPStan\Type\IntegerType(); } public function isSmallerThan(\PHPStan\Type\Type $otherType) : TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createYes(); } else { $minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThan($otherType); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createNo(); } else { $maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThan($otherType); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType) : TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createYes(); } else { $minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThanOrEqual($otherType); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createNo(); } else { $maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThanOrEqual($otherType); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } public function isGreaterThan(\PHPStan\Type\Type $otherType) : TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createNo(); } else { $minIsSmaller = $otherType->isSmallerThan(new ConstantIntegerType($this->min)); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createYes(); } else { $maxIsSmaller = $otherType->isSmallerThan(new ConstantIntegerType($this->max)); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } public function isGreaterThanOrEqual(\PHPStan\Type\Type $otherType) : TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createNo(); } else { $minIsSmaller = $otherType->isSmallerThanOrEqual(new ConstantIntegerType($this->min)); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createYes(); } else { $maxIsSmaller = $otherType->isSmallerThanOrEqual(new ConstantIntegerType($this->max)); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } public function getSmallerType() : \PHPStan\Type\Type { $subtractedTypes = [new ConstantBooleanType(\true)]; if ($this->max !== null) { $subtractedTypes[] = self::createAllGreaterThanOrEqualTo($this->max); } return \PHPStan\Type\TypeCombinator::remove(new \PHPStan\Type\MixedType(), \PHPStan\Type\TypeCombinator::union(...$subtractedTypes)); } public function getSmallerOrEqualType() : \PHPStan\Type\Type { $subtractedTypes = []; if ($this->max !== null) { $subtractedTypes[] = self::createAllGreaterThan($this->max); } return \PHPStan\Type\TypeCombinator::remove(new \PHPStan\Type\MixedType(), \PHPStan\Type\TypeCombinator::union(...$subtractedTypes)); } public function getGreaterType() : \PHPStan\Type\Type { $subtractedTypes = [new \PHPStan\Type\NullType(), new ConstantBooleanType(\false)]; if ($this->min !== null) { $subtractedTypes[] = self::createAllSmallerThanOrEqualTo($this->min); } if ($this->min !== null && $this->min > 0 || $this->max !== null && $this->max < 0) { $subtractedTypes[] = new ConstantBooleanType(\true); } return \PHPStan\Type\TypeCombinator::remove(new \PHPStan\Type\MixedType(), \PHPStan\Type\TypeCombinator::union(...$subtractedTypes)); } public function getGreaterOrEqualType() : \PHPStan\Type\Type { $subtractedTypes = []; if ($this->min !== null) { $subtractedTypes[] = self::createAllSmallerThan($this->min); } if ($this->min !== null && $this->min > 0 || $this->max !== null && $this->max < 0) { $subtractedTypes[] = new \PHPStan\Type\NullType(); $subtractedTypes[] = new ConstantBooleanType(\false); } return \PHPStan\Type\TypeCombinator::remove(new \PHPStan\Type\MixedType(), \PHPStan\Type\TypeCombinator::union(...$subtractedTypes)); } public function toBoolean() : \PHPStan\Type\BooleanType { $isZero = (new ConstantIntegerType(0))->isSuperTypeOf($this); if ($isZero->no()) { return new ConstantBooleanType(\true); } if ($isZero->maybe()) { return new \PHPStan\Type\BooleanType(); } return new ConstantBooleanType(\false); } public function toAbsoluteNumber() : \PHPStan\Type\Type { if ($this->min !== null && $this->min >= 0) { return $this; } if ($this->max === null || $this->max >= 0) { $inversedMin = $this->min !== null ? $this->min * -1 : null; return self::fromInterval(0, $inversedMin !== null && $this->max !== null ? max($inversedMin, $this->max) : null); } return self::fromInterval($this->max * -1, $this->min !== null ? $this->min * -1 : null); } public function toString() : \PHPStan\Type\Type { $finiteTypes = $this->getFiniteTypes(); if ($finiteTypes !== []) { return \PHPStan\Type\TypeCombinator::union(...$finiteTypes)->toString(); } $isZero = (new ConstantIntegerType(0))->isSuperTypeOf($this); if ($isZero->no()) { return new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryLowercaseStringType(), new AccessoryUppercaseStringType(), new AccessoryNumericStringType(), new AccessoryNonFalsyStringType()]); } return new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryLowercaseStringType(), new AccessoryUppercaseStringType(), new AccessoryNumericStringType()]); } /** * Return the union with another type, but only if it can be expressed in a simpler way than using UnionType * */ public function tryUnion(\PHPStan\Type\Type $otherType) : ?\PHPStan\Type\Type { if ($otherType instanceof self || $otherType instanceof ConstantIntegerType) { if ($otherType instanceof self) { $otherMin = $otherType->min; $otherMax = $otherType->max; } else { $otherMin = $otherType->getValue(); $otherMax = $otherType->getValue(); } if (self::isDisjoint($this->min, $this->max, $otherMin, $otherMax, \false)) { return null; } return self::fromInterval($this->min !== null && $otherMin !== null ? min($this->min, $otherMin) : null, $this->max !== null && $otherMax !== null ? max($this->max, $otherMax) : null); } if (get_class($otherType) === parent::class) { return $otherType; } return null; } /** * Return the intersection with another type, but only if it can be expressed in a simpler way than using * IntersectionType * */ public function tryIntersect(\PHPStan\Type\Type $otherType) : ?\PHPStan\Type\Type { if ($otherType instanceof self || $otherType instanceof ConstantIntegerType) { if ($otherType instanceof self) { $otherMin = $otherType->min; $otherMax = $otherType->max; } else { $otherMin = $otherType->getValue(); $otherMax = $otherType->getValue(); } if (self::isDisjoint($this->min, $this->max, $otherMin, $otherMax, \false)) { return new \PHPStan\Type\NeverType(); } if ($this->min === null) { $newMin = $otherMin; } elseif ($otherMin === null) { $newMin = $this->min; } else { $newMin = max($this->min, $otherMin); } if ($this->max === null) { $newMax = $otherMax; } elseif ($otherMax === null) { $newMax = $this->max; } else { $newMax = min($this->max, $otherMax); } return self::fromInterval($newMin, $newMax); } if (get_class($otherType) === parent::class) { return $this; } return null; } /** * Return the different with another type, or null if it cannot be represented. * */ public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { if (get_class($typeToRemove) === parent::class) { return new \PHPStan\Type\NeverType(); } if ($typeToRemove instanceof self || $typeToRemove instanceof ConstantIntegerType) { if ($typeToRemove instanceof self) { $removeMin = $typeToRemove->min; $removeMax = $typeToRemove->max; } else { $removeMin = $typeToRemove->getValue(); $removeMax = $typeToRemove->getValue(); } if ($this->min !== null && $removeMax !== null && $removeMax < $this->min || $this->max !== null && $removeMin !== null && $this->max < $removeMin) { return $this; } if ($removeMin !== null && $removeMin !== PHP_INT_MIN) { $lowerPart = self::fromInterval($this->min, $removeMin - 1); } else { $lowerPart = null; } if ($removeMax !== null && $removeMax !== PHP_INT_MAX) { $upperPart = self::fromInterval($removeMax + 1, $this->max); } else { $upperPart = null; } if ($lowerPart !== null && $upperPart !== null) { return \PHPStan\Type\TypeCombinator::union($lowerPart, $upperPart); } return $lowerPart ?? $upperPart; } return null; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { if ($exponent instanceof \PHPStan\Type\UnionType) { $results = []; foreach ($exponent->getTypes() as $unionType) { $results[] = $this->exponentiate($unionType); } return \PHPStan\Type\TypeCombinator::union(...$results); } if ($exponent instanceof \PHPStan\Type\IntegerRangeType) { $min = null; $max = null; if ($this->getMin() !== null && $exponent->getMin() !== null) { $min = $this->getMin() ** $exponent->getMin(); } if ($this->getMax() !== null && $exponent->getMax() !== null) { $max = $this->getMax() ** $exponent->getMax(); } if (($min !== null || $max !== null) && !is_float($min) && !is_float($max)) { return self::fromInterval($min, $max); } } if ($exponent instanceof \PHPStan\Type\ConstantScalarType) { $exponentValue = $exponent->getValue(); if (is_int($exponentValue)) { $min = null; $max = null; if ($this->getMin() !== null) { $min = $this->getMin() ** $exponentValue; } if ($this->getMax() !== null) { $max = $this->getMax() ** $exponentValue; } if (!is_float($min) && !is_float($max)) { return self::fromInterval($min, $max); } } } return parent::exponentiate($exponent); } /** * @return list */ public function getFiniteTypes() : array { if ($this->min === null || $this->max === null) { return []; } $size = $this->max - $this->min; if ($size > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return []; } $types = []; for ($i = $this->min; $i <= $this->max; $i++) { $types[] = new ConstantIntegerType($i); } return $types; } public function toPhpDocNode() : TypeNode { if ($this->min === null) { $min = new IdentifierTypeNode('min'); } else { $min = new ConstTypeNode(new ConstExprIntegerNode((string) $this->min)); } if ($this->max === null) { $max = new IdentifierTypeNode('max'); } else { $max = new ConstTypeNode(new ConstExprIntegerNode((string) $this->max)); } return new GenericTypeNode(new IdentifierTypeNode('int'), [$min, $max]); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { if ($this->isSmallerThan($type)->yes() || $this->isGreaterThan($type)->yes()) { return new ConstantBooleanType(\false); } return parent::looseCompare($type, $phpVersion); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['min'], $properties['max']); } } subject = $subject; $this->target = $target; $this->if = $if; $this->else = $else; $this->negated = $negated; } public function getSubject() : \PHPStan\Type\Type { return $this->subject; } public function getTarget() : \PHPStan\Type\Type { return $this->target; } public function getIf() : \PHPStan\Type\Type { return $this->if; } public function getElse() : \PHPStan\Type\Type { return $this->else; } public function isNegated() : bool { return $this->negated; } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return $this->if->isSuperTypeOfWithReason($type->if)->and($this->else->isSuperTypeOfWithReason($type->else)); } return $this->isSuperTypeOfDefault($type); } public function getReferencedClasses() : array { return array_merge($this->subject->getReferencedClasses(), $this->target->getReferencedClasses(), $this->if->getReferencedClasses(), $this->else->getReferencedClasses()); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { return array_merge($this->subject->getReferencedTemplateTypes($positionVariance), $this->target->getReferencedTemplateTypes($positionVariance), $this->if->getReferencedTemplateTypes($positionVariance), $this->else->getReferencedTemplateTypes($positionVariance)); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self && $this->subject->equals($type->subject) && $this->target->equals($type->target) && $this->if->equals($type->if) && $this->else->equals($type->else); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return sprintf('(%s %s %s ? %s : %s)', $this->subject->describe($level), $this->negated ? 'is not' : 'is', $this->target->describe($level), $this->if->describe($level), $this->else->describe($level)); } public function isResolvable() : bool { return !\PHPStan\Type\TypeUtils::containsTemplateType($this->subject) && !\PHPStan\Type\TypeUtils::containsTemplateType($this->target); } protected function getResult() : \PHPStan\Type\Type { $isSuperType = $this->target->isSuperTypeOf($this->subject); if ($isSuperType->yes()) { return !$this->negated ? $this->getNormalizedIf() : $this->getNormalizedElse(); } if ($isSuperType->no()) { return !$this->negated ? $this->getNormalizedElse() : $this->getNormalizedIf(); } return \PHPStan\Type\TypeCombinator::union($this->getNormalizedIf(), $this->getNormalizedElse()); } public function traverse(callable $cb) : \PHPStan\Type\Type { $subject = $cb($this->subject); $target = $cb($this->target); $if = $cb($this->getNormalizedIf()); $else = $cb($this->getNormalizedElse()); if ($this->subject === $subject && $this->target === $target && $this->getNormalizedIf() === $if && $this->getNormalizedElse() === $else) { return $this; } return new self($subject, $target, $if, $else, $this->negated); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if (!$right instanceof self) { return $this; } $subject = $cb($this->subject, $right->subject); $target = $cb($this->target, $right->target); $if = $cb($this->getNormalizedIf(), $right->getNormalizedIf()); $else = $cb($this->getNormalizedElse(), $right->getNormalizedElse()); if ($this->subject === $subject && $this->target === $target && $this->getNormalizedIf() === $if && $this->getNormalizedElse() === $else) { return $this; } return new self($subject, $target, $if, $else, $this->negated); } public function toPhpDocNode() : TypeNode { return new ConditionalTypeNode($this->subject->toPhpDocNode(), $this->target->toPhpDocNode(), $this->if->toPhpDocNode(), $this->else->toPhpDocNode(), $this->negated); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['subject'], $properties['target'], $properties['if'], $properties['else'], $properties['negated']); } private function getNormalizedIf() : \PHPStan\Type\Type { return $this->normalizedIf = $this->normalizedIf ?? \PHPStan\Type\TypeTraverser::map($this->if, function (\PHPStan\Type\Type $type, callable $traverse) { return $type === $this->subject ? !$this->negated ? $this->getSubjectWithTargetIntersectedType() : $this->getSubjectWithTargetRemovedType() : $traverse($type); }); } private function getNormalizedElse() : \PHPStan\Type\Type { return $this->normalizedElse = $this->normalizedElse ?? \PHPStan\Type\TypeTraverser::map($this->else, function (\PHPStan\Type\Type $type, callable $traverse) { return $type === $this->subject ? !$this->negated ? $this->getSubjectWithTargetRemovedType() : $this->getSubjectWithTargetIntersectedType() : $traverse($type); }); } private function getSubjectWithTargetIntersectedType() : \PHPStan\Type\Type { return $this->subjectWithTargetIntersectedType = $this->subjectWithTargetIntersectedType ?? \PHPStan\Type\TypeCombinator::intersect($this->subject, $this->target); } private function getSubjectWithTargetRemovedType() : \PHPStan\Type\Type { return $this->subjectWithTargetRemovedType = $this->subjectWithTargetRemovedType ?? \PHPStan\Type\TypeCombinator::remove($this->subject, $this->target); } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new \PHPStan\Type\AcceptsResult($type->isVoid()->or($type->isNull()), []); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self; } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return 'void'; } public function toNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toString() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toInteger() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toFloat() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toArray() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toArrayKey() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function traverse(callable $cb) : \PHPStan\Type\Type { return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { return $this; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('void'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self(); } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { return \PHPStan\Type\AcceptsResult::createYes(); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($acceptingType instanceof self) { return \PHPStan\Type\AcceptsResult::createYes(); } if ($acceptingType instanceof \PHPStan\Type\MixedType && !$acceptingType instanceof TemplateMixedType) { return \PHPStan\Type\AcceptsResult::createYes(); } return \PHPStan\Type\AcceptsResult::createMaybe(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } public function isSubTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($otherType instanceof \PHPStan\Type\MixedType && !$otherType instanceof TemplateMixedType) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self; } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return $level->handle(static function () { return 'mixed'; }, static function () { return 'mixed'; }, static function () { return 'mixed'; }, static function () { return 'strict-mixed'; }); } public function getTemplateType(string $ancestorClassName, string $templateTypeName) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isObject() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isEnum() : TrinaryLogic { return TrinaryLogic::createNo(); } public function canAccessProperties() : TrinaryLogic { return TrinaryLogic::createNo(); } public function hasProperty(string $propertyName) : TrinaryLogic { return TrinaryLogic::createNo(); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { throw new ShouldNotHappenException(); } public function canCallMethods() : TrinaryLogic { return TrinaryLogic::createNo(); } public function hasMethod(string $methodName) : TrinaryLogic { return TrinaryLogic::createNo(); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { throw new ShouldNotHappenException(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { throw new ShouldNotHappenException(); } public function canAccessConstants() : TrinaryLogic { return TrinaryLogic::createNo(); } public function hasConstant(string $constantName) : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstant(string $constantName) : ConstantReflection { throw new ShouldNotHappenException(); } public function isIterable() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getIterableKeyType() : \PHPStan\Type\Type { return $this; } public function getIterableValueType() : \PHPStan\Type\Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { return TrinaryLogic::createNo(); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isCallable() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { return []; } public function isCloneable() : TrinaryLogic { return TrinaryLogic::createNo(); } public function toBoolean() : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function toNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toInteger() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toFloat() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toString() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toArray() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toArrayKey() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap { return TemplateTypeMap::createEmpty(); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { return []; } public function getEnumCases() : array { return []; } public function traverse(callable $cb) : \PHPStan\Type\Type { return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { return $this; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('mixed'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self(); } } */ private $templateTags; use MaybeArrayTypeTrait; use MaybeIterableTypeTrait; use MaybeObjectTypeTrait; use MaybeOffsetAccessibleTypeTrait; use TruthyBooleanTypeTrait; use UndecidedComparisonCompoundTypeTrait; use NonRemoveableTypeTrait; use NonGeneralizableTypeTrait; /** @var array */ private $parameters; /** * @var Type */ private $returnType; /** * @var bool */ private $isCommonCallable; /** * @var TemplateTypeMap */ private $templateTypeMap; /** * @var TemplateTypeMap */ private $resolvedTemplateTypeMap; /** * @var TrinaryLogic */ private $isPure; /** * @api * @param array|null $parameters * @param array $templateTags */ public function __construct(?array $parameters = null, ?\PHPStan\Type\Type $returnType = null, bool $variadic = \true, ?TemplateTypeMap $templateTypeMap = null, ?TemplateTypeMap $resolvedTemplateTypeMap = null, array $templateTags = [], ?TrinaryLogic $isPure = null) { $this->variadic = $variadic; $this->templateTags = $templateTags; $this->parameters = $parameters ?? []; $this->returnType = $returnType ?? new \PHPStan\Type\MixedType(); $this->isCommonCallable = $parameters === null && $returnType === null; $this->templateTypeMap = $templateTypeMap ?? TemplateTypeMap::createEmpty(); $this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap ?? TemplateTypeMap::createEmpty(); $this->isPure = $isPure ?? TrinaryLogic::createMaybe(); } /** * @return array */ public function getTemplateTags() : array { return $this->templateTags; } public function isPure() : TrinaryLogic { return $this->isPure; } /** * @return string[] */ public function getReferencedClasses() : array { $classes = []; foreach ($this->parameters as $parameter) { $classes = array_merge($classes, $parameter->getType()->getReferencedClasses()); } return array_merge($classes, $this->returnType->getReferencedClasses()); } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function getConstantStrings() : array { return []; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType && !$type instanceof self) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return $this->isSuperTypeOfInternal($type, \true)->toAcceptsResult(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType && !$type instanceof self) { return $type->isSubTypeOfWithReason($this); } return $this->isSuperTypeOfInternal($type, \false); } private function isSuperTypeOfInternal(\PHPStan\Type\Type $type, bool $treatMixedAsAny) : \PHPStan\Type\IsSuperTypeOfResult { $isCallable = new \PHPStan\Type\IsSuperTypeOfResult($type->isCallable(), []); if ($isCallable->no()) { return $isCallable; } static $scope; if ($scope === null) { $scope = new OutOfClassScope(); } if ($this->isCommonCallable) { if ($this->isPure()->yes()) { $typePure = TrinaryLogic::createYes(); foreach ($type->getCallableParametersAcceptors($scope) as $variant) { $typePure = $typePure->and($variant->isPure()); } return $isCallable->and(new \PHPStan\Type\IsSuperTypeOfResult($typePure, [])); } return $isCallable; } $parameterTypes = array_map(static function ($parameter) { return $parameter->getType(); }, $this->getParameters()); $variantsResult = null; foreach ($type->getCallableParametersAcceptors($scope) as $variant) { $variant = ParametersAcceptorSelector::selectFromTypes($parameterTypes, [$variant], \false); if (!$variant instanceof CallableParametersAcceptor) { return \PHPStan\Type\IsSuperTypeOfResult::createNo([]); } $isSuperType = \PHPStan\Type\CallableTypeHelper::isParametersAcceptorSuperTypeOf($this, $variant, $treatMixedAsAny); if ($variantsResult === null) { $variantsResult = $isSuperType; } else { $variantsResult = $variantsResult->or($isSuperType); } } if ($variantsResult === null) { throw new ShouldNotHappenException(); } return $isCallable->and($variantsResult); } public function isSubTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof \PHPStan\Type\IntersectionType || $otherType instanceof \PHPStan\Type\UnionType) { return $otherType->isSuperTypeOfWithReason($this); } return (new \PHPStan\Type\IsSuperTypeOfResult($otherType->isCallable(), []))->and($otherType instanceof self ? \PHPStan\Type\IsSuperTypeOfResult::createYes() : \PHPStan\Type\IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(\PHPStan\Type\Type $type) : bool { if (!$type instanceof self) { return \false; } return $this->describe(\PHPStan\Type\VerbosityLevel::precise()) === $type->describe(\PHPStan\Type\VerbosityLevel::precise()); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return $level->handle(static function () : string { return 'callable'; }, function () : string { $printer = new Printer(); $selfWithoutParameterNames = new self(array_map(static function (ParameterReflection $p) : ParameterReflection { return new DummyParameter('', $p->getType(), $p->isOptional() && !$p->isVariadic(), PassedByReference::createNo(), $p->isVariadic(), $p->getDefaultValue()); }, $this->parameters), $this->returnType, $this->variadic, $this->templateTypeMap, $this->resolvedTemplateTypeMap, $this->templateTags, $this->isPure); return $printer->print($selfWithoutParameterNames->toPhpDocNode()); }); } public function isCallable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { return [$this]; } public function getThrowPoints() : array { return [SimpleThrowPoint::createImplicit()]; } public function getImpurePoints() : array { $pure = $this->isPure(); if ($pure->yes()) { return []; } return [new SimpleImpurePoint('functionCall', 'call to a callable', $pure->no())]; } public function getInvalidateExpressions() : array { return []; } public function getUsedVariables() : array { return []; } public function acceptsNamedArguments() : bool { return \true; } public function toNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toString() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toInteger() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toFloat() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toArray() : \PHPStan\Type\Type { return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()); } public function toArrayKey() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getTemplateTypeMap() : TemplateTypeMap { return $this->templateTypeMap; } public function getResolvedTemplateTypeMap() : TemplateTypeMap { return $this->resolvedTemplateTypeMap; } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return TemplateTypeVarianceMap::createEmpty(); } /** * @return array */ public function getParameters() : array { return $this->parameters; } public function isVariadic() : bool { return $this->variadic; } public function getReturnType() : \PHPStan\Type\Type { return $this->returnType; } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap { if ($receivedType instanceof \PHPStan\Type\UnionType || $receivedType instanceof \PHPStan\Type\IntersectionType) { return $receivedType->inferTemplateTypesOn($this); } if (!$receivedType->isCallable()->yes()) { return TemplateTypeMap::createEmpty(); } $parametersAcceptors = $receivedType->getCallableParametersAcceptors(new OutOfClassScope()); $typeMap = TemplateTypeMap::createEmpty(); foreach ($parametersAcceptors as $parametersAcceptor) { $typeMap = $typeMap->union($this->inferTemplateTypesOnParametersAcceptor($parametersAcceptor)); } return $typeMap; } private function inferTemplateTypesOnParametersAcceptor(ParametersAcceptor $parametersAcceptor) : TemplateTypeMap { $parameterTypes = array_map(static function ($parameter) { return $parameter->getType(); }, $this->getParameters()); $parametersAcceptor = ParametersAcceptorSelector::selectFromTypes($parameterTypes, [$parametersAcceptor], \false); $args = $parametersAcceptor->getParameters(); $returnType = $parametersAcceptor->getReturnType(); $typeMap = TemplateTypeMap::createEmpty(); foreach ($this->getParameters() as $i => $param) { $paramType = $param->getType(); if (isset($args[$i])) { $argType = $args[$i]->getType(); } elseif ($paramType instanceof TemplateType) { $argType = TemplateTypeHelper::resolveToBounds($paramType); } else { $argType = new \PHPStan\Type\NeverType(); } $typeMap = $typeMap->union($paramType->inferTemplateTypes($argType)->convertToLowerBoundTypes()); } return $typeMap->union($this->getReturnType()->inferTemplateTypes($returnType)); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { $references = $this->getReturnType()->getReferencedTemplateTypes($positionVariance->compose(TemplateTypeVariance::createCovariant())); $paramVariance = $positionVariance->compose(TemplateTypeVariance::createContravariant()); foreach ($this->getParameters() as $param) { foreach ($param->getType()->getReferencedTemplateTypes($paramVariance) as $reference) { $references[] = $reference; } } return $references; } public function traverse(callable $cb) : \PHPStan\Type\Type { if ($this->isCommonCallable) { return $this; } $parameters = array_map(static function (ParameterReflection $param) use($cb) : NativeParameterReflection { $defaultValue = $param->getDefaultValue(); return new NativeParameterReflection($param->getName(), $param->isOptional(), $cb($param->getType()), $param->passedByReference(), $param->isVariadic(), $defaultValue !== null ? $cb($defaultValue) : null); }, $this->getParameters()); return new self($parameters, $cb($this->getReturnType()), $this->isVariadic(), $this->templateTypeMap, $this->resolvedTemplateTypeMap, $this->templateTags, $this->isPure); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if ($this->isCommonCallable) { return $this; } if (!$right->isCallable()->yes()) { return $this; } $rightAcceptors = $right->getCallableParametersAcceptors(new OutOfClassScope()); if (count($rightAcceptors) !== 1) { return $this; } $rightParameters = $rightAcceptors[0]->getParameters(); if (count($this->getParameters()) !== count($rightParameters)) { return $this; } $parameters = []; foreach ($this->getParameters() as $i => $leftParam) { $rightParam = $rightParameters[$i]; $leftDefaultValue = $leftParam->getDefaultValue(); $rightDefaultValue = $rightParam->getDefaultValue(); $defaultValue = $leftDefaultValue; if ($leftDefaultValue !== null && $rightDefaultValue !== null) { $defaultValue = $cb($leftDefaultValue, $rightDefaultValue); } $parameters[] = new NativeParameterReflection($leftParam->getName(), $leftParam->isOptional(), $cb($leftParam->getType(), $rightParam->getType()), $leftParam->passedByReference(), $leftParam->isVariadic(), $defaultValue); } return new self($parameters, $cb($this->getReturnType(), $rightAcceptors[0]->getReturnType()), $this->isVariadic(), $this->templateTypeMap, $this->resolvedTemplateTypeMap, $this->templateTags, $this->isPure); } public function isOversizedArray() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ObjectWithoutClassType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function getEnumCases() : array { return []; } public function isCommonCallable() : bool { return $this->isCommonCallable; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { if ($this->isCommonCallable) { return new IdentifierTypeNode($this->isPure()->yes() ? 'pure-callable' : 'callable'); } $parameters = []; foreach ($this->parameters as $parameter) { $parameters[] = new CallableTypeParameterNode($parameter->getType()->toPhpDocNode(), !$parameter->passedByReference()->no(), $parameter->isVariadic(), $parameter->getName() === '' ? '' : '$' . $parameter->getName(), $parameter->isOptional()); } $templateTags = []; foreach ($this->templateTags as $templateName => $templateTag) { $templateTags[] = new TemplateTagValueNode($templateName, $templateTag->getBound()->toPhpDocNode(), ''); } return new CallableTypeNode(new IdentifierTypeNode($this->isPure->yes() ? 'pure-callable' : 'callable'), $parameters, $this->returnType->toPhpDocNode(), $templateTags); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self((bool) $properties['isCommonCallable'] ? null : $properties['parameters'], (bool) $properties['isCommonCallable'] ? null : $properties['returnType'], $properties['variadic'], $properties['templateTypeMap'], $properties['resolvedTemplateTypeMap'], $properties['templateTags'], $properties['isPure']); } } subtractedType = $subtractedType; } /** * @return string[] */ public function getReferencedClasses() : array { return []; } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createFromBoolean($type instanceof self || $type instanceof \PHPStan\Type\ObjectShapeType || $type->getObjectClassNames() !== []); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($type instanceof self) { if ($this->subtractedType === null) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type->subtractedType !== null) { $isSuperType = $type->subtractedType->isSuperTypeOfWithReason($this->subtractedType); if ($isSuperType->yes()) { return $isSuperType; } } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($type instanceof \PHPStan\Type\ObjectShapeType) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type->getObjectClassNames() === []) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } if ($this->subtractedType === null) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return $this->subtractedType->isSuperTypeOfWithReason($type)->negate(); } public function equals(\PHPStan\Type\Type $type) : bool { if (!$type instanceof self) { return \false; } if ($this->subtractedType === null) { if ($type->subtractedType === null) { return \true; } return \false; } if ($type->subtractedType === null) { return \false; } return $this->subtractedType->equals($type->subtractedType); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return $level->handle(static function () : string { return 'object'; }, static function () : string { return 'object'; }, function () use($level) : string { $description = 'object'; if ($this->subtractedType !== null) { $description .= $this->subtractedType instanceof \PHPStan\Type\UnionType ? sprintf('~(%s)', $this->subtractedType->describe($level)) : sprintf('~%s', $this->subtractedType->describe($level)); } return $description; }); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getEnumCases() : array { return []; } public function subtract(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { if ($type instanceof self) { return new \PHPStan\Type\NeverType(); } if ($this->subtractedType !== null) { $type = \PHPStan\Type\TypeCombinator::union($this->subtractedType, $type); } return new self($type); } public function getTypeWithoutSubtractedType() : \PHPStan\Type\Type { return new self(); } public function changeSubtractedType(?\PHPStan\Type\Type $subtractedType) : \PHPStan\Type\Type { return new self($subtractedType); } public function getSubtractedType() : ?\PHPStan\Type\Type { return $this->subtractedType; } public function traverse(callable $cb) : \PHPStan\Type\Type { $subtractedType = $this->subtractedType !== null ? $cb($this->subtractedType) : null; if ($subtractedType !== $this->subtractedType) { return new self($subtractedType); } return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if ($this->subtractedType === null) { return $this; } return new self(); } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { if ($this->isSuperTypeOf($typeToRemove)->yes()) { return $this->subtract($typeToRemove); } return null; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { if (!$exponent instanceof \PHPStan\Type\NeverType && !$this->isSuperTypeOf($exponent)->no()) { return \PHPStan\Type\TypeCombinator::union($this, $exponent); } return new \PHPStan\Type\BenevolentUnionType([new \PHPStan\Type\FloatType(), new \PHPStan\Type\IntegerType()]); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('object'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['subtractedType'] ?? null); } } itemType = $itemType; if ($keyType->describe(\PHPStan\Type\VerbosityLevel::value()) === '(int|string)') { $keyType = new \PHPStan\Type\MixedType(); } if ($keyType instanceof \PHPStan\Type\StrictMixedType && !$keyType instanceof TemplateStrictMixedType) { $keyType = new \PHPStan\Type\UnionType([new \PHPStan\Type\StringType(), new \PHPStan\Type\IntegerType()]); } $this->keyType = $keyType; } public function getKeyType() : \PHPStan\Type\Type { return $this->keyType; } public function getItemType() : \PHPStan\Type\Type { return $this->itemType; } /** * @return string[] */ public function getReferencedClasses() : array { return array_merge($this->keyType->getReferencedClasses(), $this->getItemType()->getReferencedClasses()); } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function getArrays() : array { return [$this]; } public function getConstantArrays() : array { return []; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } if ($type instanceof ConstantArrayType) { $result = \PHPStan\Type\AcceptsResult::createYes(); $thisKeyType = $this->keyType; $itemType = $this->getItemType(); foreach ($type->getKeyTypes() as $i => $keyType) { $valueType = $type->getValueTypes()[$i]; $acceptsKey = $thisKeyType->acceptsWithReason($keyType, $strictTypes); $acceptsValue = $itemType->acceptsWithReason($valueType, $strictTypes); $result = $result->and($acceptsKey)->and($acceptsValue); } return $result; } if ($type instanceof \PHPStan\Type\ArrayType) { return $this->getItemType()->acceptsWithReason($type->getItemType(), $strictTypes)->and($this->keyType->acceptsWithReason($type->keyType, $strictTypes)); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return $this->getItemType()->isSuperTypeOfWithReason($type->getItemType())->and($this->getIterableKeyType()->isSuperTypeOfWithReason($type->getIterableKeyType())); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self && $type->isConstantArray()->no() && $this->getItemType()->equals($type->getIterableValueType()) && $this->keyType->equals($type->keyType); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { $isMixedKeyType = $this->keyType instanceof \PHPStan\Type\MixedType && $this->keyType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed'; $isMixedItemType = $this->itemType instanceof \PHPStan\Type\MixedType && $this->itemType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed'; $valueHandler = function () use($level, $isMixedKeyType, $isMixedItemType) : string { if ($isMixedKeyType || $this->keyType instanceof \PHPStan\Type\NeverType) { if ($isMixedItemType || $this->itemType instanceof \PHPStan\Type\NeverType) { return 'array'; } return sprintf('array<%s>', $this->itemType->describe($level)); } return sprintf('array<%s, %s>', $this->keyType->describe($level), $this->itemType->describe($level)); }; return $level->handle($valueHandler, $valueHandler, function () use($level, $isMixedKeyType, $isMixedItemType) : string { if ($isMixedKeyType) { if ($isMixedItemType) { return 'array'; } return sprintf('array<%s>', $this->itemType->describe($level)); } return sprintf('array<%s, %s>', $this->keyType->describe($level), $this->itemType->describe($level)); }); } /** * @deprecated */ public function generalizeKeys() : self { return new self($this->keyType->generalize(\PHPStan\Type\GeneralizePrecision::lessSpecific()), $this->itemType); } public function generalizeValues() : self { return new self($this->keyType, $this->itemType->generalize(\PHPStan\Type\GeneralizePrecision::lessSpecific())); } public function getKeysArray() : \PHPStan\Type\Type { return AccessoryArrayListType::intersectWith(new self(new \PHPStan\Type\IntegerType(), $this->getIterableKeyType())); } public function getValuesArray() : \PHPStan\Type\Type { return AccessoryArrayListType::intersectWith(new self(new \PHPStan\Type\IntegerType(), $this->itemType)); } public function isIterable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getArraySize() : \PHPStan\Type\Type { return \PHPStan\Type\IntegerRangeType::fromInterval(0, null); } public function getIterableKeyType() : \PHPStan\Type\Type { $keyType = $this->keyType; if ($keyType instanceof \PHPStan\Type\MixedType && !$keyType instanceof TemplateMixedType) { return new \PHPStan\Type\BenevolentUnionType([new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType()]); } if ($keyType instanceof \PHPStan\Type\StrictMixedType) { return new \PHPStan\Type\BenevolentUnionType([new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType()]); } return $keyType; } public function getFirstIterableKeyType() : \PHPStan\Type\Type { return $this->getIterableKeyType(); } public function getLastIterableKeyType() : \PHPStan\Type\Type { return $this->getIterableKeyType(); } public function getIterableValueType() : \PHPStan\Type\Type { return $this->getItemType(); } public function getFirstIterableValueType() : \PHPStan\Type\Type { return $this->getItemType(); } public function getLastIterableValueType() : \PHPStan\Type\Type { return $this->getItemType(); } public function isArray() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isConstantArray() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isOversizedArray() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isList() : TrinaryLogic { if (\PHPStan\Type\IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($this->getKeyType())->no()) { return TrinaryLogic::createNo(); } if ($this->getKeyType()->isSuperTypeOf(new ConstantIntegerType(0))->no()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { $offsetType = $offsetType->toArrayKey(); if ($this->getKeyType()->isSuperTypeOf($offsetType)->no() && ($offsetType->isString()->no() || !$offsetType->isConstantScalarValue()->no())) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { $offsetType = $offsetType->toArrayKey(); if ($this->getKeyType()->isSuperTypeOf($offsetType)->no() && ($offsetType->isString()->no() || !$offsetType->isConstantScalarValue()->no())) { return new \PHPStan\Type\ErrorType(); } $type = $this->getItemType(); if ($type instanceof \PHPStan\Type\ErrorType) { return new \PHPStan\Type\MixedType(); } return $type; } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { if ($offsetType === null) { $isKeyTypeInteger = $this->keyType->isInteger(); if ($isKeyTypeInteger->no()) { $offsetType = new \PHPStan\Type\IntegerType(); } elseif ($isKeyTypeInteger->yes()) { /** @var list $constantScalars */ $constantScalars = $this->keyType->getConstantScalarTypes(); if (count($constantScalars) > 0) { foreach ($constantScalars as $constantScalar) { $constantScalars[] = \PHPStan\Type\ConstantTypeHelper::getTypeFromValue($constantScalar->getValue() + 1); } $offsetType = \PHPStan\Type\TypeCombinator::union(...$constantScalars); } else { $offsetType = $this->keyType; } } else { $integerTypes = []; \PHPStan\Type\TypeTraverser::map($this->keyType, static function (\PHPStan\Type\Type $type, callable $traverse) use(&$integerTypes) : \PHPStan\Type\Type { if ($type instanceof \PHPStan\Type\UnionType) { return $traverse($type); } $isInteger = $type->isInteger(); if ($isInteger->yes()) { $integerTypes[] = $type; } return $type; }); if (count($integerTypes) === 0) { $offsetType = $this->keyType; } else { $offsetType = \PHPStan\Type\TypeCombinator::union(...$integerTypes); } } } else { $offsetType = $offsetType->toArrayKey(); } if ($offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType) { if ($offsetType->isSuperTypeOf($this->keyType)->yes()) { $builder = ConstantArrayTypeBuilder::createEmpty(); $builder->setOffsetValueType($offsetType, $valueType); return $builder->getArray(); } return \PHPStan\Type\TypeCombinator::intersect(new self(\PHPStan\Type\TypeCombinator::union($this->keyType, $offsetType), \PHPStan\Type\TypeCombinator::union($this->itemType, $valueType)), new HasOffsetValueType($offsetType, $valueType), new NonEmptyArrayType()); } return \PHPStan\Type\TypeCombinator::intersect(new self(\PHPStan\Type\TypeCombinator::union($this->keyType, $offsetType), $unionValues ? \PHPStan\Type\TypeCombinator::union($this->itemType, $valueType) : $valueType), new NonEmptyArrayType()); } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return new self($this->keyType, \PHPStan\Type\TypeCombinator::union($this->itemType, $valueType)); } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { $offsetType = $offsetType->toArrayKey(); if (($offsetType instanceof ConstantIntegerType || $offsetType instanceof ConstantStringType) && !$this->keyType->isSuperTypeOf($offsetType)->no()) { $keyType = \PHPStan\Type\TypeCombinator::remove($this->keyType, $offsetType); if ($keyType instanceof \PHPStan\Type\NeverType) { return new ConstantArrayType([], []); } return new self($keyType, $this->itemType); } return $this; } public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { $chunkType = $preserveKeys->yes() ? $this : AccessoryArrayListType::intersectWith(new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), $this->getIterableValueType())); $chunkType = \PHPStan\Type\TypeCombinator::intersect($chunkType, new NonEmptyArrayType()); $arrayType = AccessoryArrayListType::intersectWith(new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), $chunkType)); return $this->isIterableAtLeastOnce()->yes() ? \PHPStan\Type\TypeCombinator::intersect($arrayType, new NonEmptyArrayType()) : $arrayType; } public function fillKeysArray(\PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { $itemType = $this->getItemType(); if ($itemType->isInteger()->no()) { $stringKeyType = $itemType->toString(); if ($stringKeyType instanceof \PHPStan\Type\ErrorType) { return $stringKeyType; } return new \PHPStan\Type\ArrayType($stringKeyType, $valueType); } return new \PHPStan\Type\ArrayType($itemType, $valueType); } public function flipArray() : \PHPStan\Type\Type { return new self($this->getIterableValueType()->toArrayKey(), $this->getIterableKeyType()); } public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType) : \PHPStan\Type\Type { $isKeySuperType = $otherArraysType->getIterableKeyType()->isSuperTypeOf($this->getIterableKeyType()); if ($isKeySuperType->no()) { return ConstantArrayTypeBuilder::createEmpty()->getArray(); } if ($isKeySuperType->yes()) { return $this; } return new self($otherArraysType->getIterableKeyType(), $this->getIterableValueType()); } public function popArray() : \PHPStan\Type\Type { return $this; } public function reverseArray(TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this; } public function searchArray(\PHPStan\Type\Type $needleType) : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union($this->getIterableKeyType(), new ConstantBooleanType(\false)); } public function shiftArray() : \PHPStan\Type\Type { return $this; } public function shuffleArray() : \PHPStan\Type\Type { return AccessoryArrayListType::intersectWith(new self(new \PHPStan\Type\IntegerType(), $this->itemType)); } public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this; } public function isCallable() : TrinaryLogic { return TrinaryLogic::createMaybe()->and($this->itemType->isString()); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { if ($this->isCallable()->no()) { throw new ShouldNotHappenException(); } return [new TrivialParametersAcceptor()]; } public function toNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toString() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toInteger() : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union(new ConstantIntegerType(0), new ConstantIntegerType(1)); } public function toFloat() : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union(new ConstantFloatType(0.0), new ConstantFloatType(1.0)); } public function toArray() : \PHPStan\Type\Type { return $this; } public function toArrayKey() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } /** @deprecated Use getArraySize() instead */ public function count() : \PHPStan\Type\Type { return $this->getArraySize(); } /** @deprecated Use $offsetType->toArrayKey() instead */ public static function castToArrayKeyType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return $offsetType->toArrayKey(); } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap { if ($receivedType instanceof \PHPStan\Type\UnionType || $receivedType instanceof \PHPStan\Type\IntersectionType) { return $receivedType->inferTemplateTypesOn($this); } if ($receivedType->isArray()->yes()) { $keyTypeMap = $this->getIterableKeyType()->inferTemplateTypes($receivedType->getIterableKeyType()); $itemTypeMap = $this->getItemType()->inferTemplateTypes($receivedType->getIterableValueType()); return $keyTypeMap->union($itemTypeMap); } return TemplateTypeMap::createEmpty(); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { $variance = $positionVariance->compose(TemplateTypeVariance::createCovariant()); return array_merge($this->getIterableKeyType()->getReferencedTemplateTypes($variance), $this->getItemType()->getReferencedTemplateTypes($variance)); } public function traverse(callable $cb) : \PHPStan\Type\Type { $keyType = $cb($this->keyType); $itemType = $cb($this->itemType); if ($keyType !== $this->keyType || $itemType !== $this->itemType) { if ($keyType instanceof \PHPStan\Type\NeverType && $itemType instanceof \PHPStan\Type\NeverType) { return new ConstantArrayType([], []); } return new self($keyType, $itemType); } return $this; } public function toPhpDocNode() : TypeNode { $isMixedKeyType = $this->keyType instanceof \PHPStan\Type\MixedType && $this->keyType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed'; $isMixedItemType = $this->itemType instanceof \PHPStan\Type\MixedType && $this->itemType->describe(\PHPStan\Type\VerbosityLevel::precise()) === 'mixed'; if ($isMixedKeyType) { if ($isMixedItemType) { return new IdentifierTypeNode('array'); } return new GenericTypeNode(new IdentifierTypeNode('array'), [$this->itemType->toPhpDocNode()]); } return new GenericTypeNode(new IdentifierTypeNode('array'), [$this->keyType->toPhpDocNode(), $this->itemType->toPhpDocNode()]); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { $keyType = $cb($this->keyType, $right->getIterableKeyType()); $itemType = $cb($this->itemType, $right->getIterableValueType()); if ($keyType !== $this->keyType || $itemType !== $this->itemType) { if ($keyType instanceof \PHPStan\Type\NeverType && $itemType instanceof \PHPStan\Type\NeverType) { return new ConstantArrayType([], []); } return new self($keyType, $itemType); } return $this; } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { if ($typeToRemove->isConstantArray()->yes() && $typeToRemove->isIterableAtLeastOnce()->no()) { return \PHPStan\Type\TypeCombinator::intersect($this, new NonEmptyArrayType()); } if ($typeToRemove instanceof NonEmptyArrayType) { return new ConstantArrayType([], []); } if ($this->isConstantArray()->yes() && $typeToRemove instanceof HasOffsetType) { return $this->unsetOffset($typeToRemove->getOffsetType()); } if ($this->isConstantArray()->yes() && $typeToRemove instanceof HasOffsetValueType) { return $this->unsetOffset($typeToRemove->getOffsetType()); } return null; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getFiniteTypes() : array { return []; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['keyType'], $properties['itemType']); } } type = $type; } public function getType() : \PHPStan\Type\Type { return $this->type; } public function getReferencedClasses() : array { return $this->type->getReferencedClasses(); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { return $this->type->getReferencedTemplateTypes($positionVariance); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self && $this->type->equals($type->type); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return sprintf('new<%s>', $this->type->describe($level)); } public function isResolvable() : bool { return !\PHPStan\Type\TypeUtils::containsTemplateType($this->type); } protected function getResult() : \PHPStan\Type\Type { return $this->type->getObjectTypeOrClassStringObjectType(); } /** * @param callable(Type): Type $cb */ public function traverse(callable $cb) : \PHPStan\Type\Type { $type = $cb($this->type); if ($this->type === $type) { return $this; } return new self($type); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if (!$right instanceof self) { return $this; } $type = $cb($this->type, $right->type); if ($this->type === $type) { return $this; } return new self($type); } public function toPhpDocNode() : TypeNode { return new GenericTypeNode(new IdentifierTypeNode('new'), [$this->type->toPhpDocNode()]); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['type']); } } value = $value; parent::__construct(); } public function getValue() : int { return $this->value; } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof self) { return $this->value === $type->value ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createNo(); } if ($type instanceof IntegerRangeType) { $min = $type->getMin(); $max = $type->getMax(); if (($min === null || $min <= $this->value) && ($max === null || $this->value <= $max)) { return IsSuperTypeOfResult::createMaybe(); } return IsSuperTypeOfResult::createNo(); } if ($type instanceof parent) { return IsSuperTypeOfResult::createMaybe(); } if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } return IsSuperTypeOfResult::createNo(); } public function describe(VerbosityLevel $level) : string { return $level->handle(static function () : string { return 'int'; }, function () : string { return sprintf('%s', $this->value); }); } public function toFloat() : Type { return new \PHPStan\Type\Constant\ConstantFloatType($this->value); } public function toAbsoluteNumber() : Type { return new self(abs($this->value)); } public function toString() : Type { return new \PHPStan\Type\Constant\ConstantStringType((string) $this->value); } public function toArrayKey() : Type { return $this; } public function generalize(GeneralizePrecision $precision) : Type { return new IntegerType(); } /** * @return ConstTypeNode */ public function toPhpDocNode() : TypeNode { return new ConstTypeNode(new ConstExprIntegerNode((string) $this->value)); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['value']); } } value = $value; parent::__construct(); } public function getValue() : bool { return $this->value; } public function describe(VerbosityLevel $level) : string { return $this->value ? 'true' : 'false'; } public function getSmallerType() : Type { if ($this->value) { return StaticTypeFactory::falsey(); } return new NeverType(); } public function getSmallerOrEqualType() : Type { if ($this->value) { return new MixedType(); } return StaticTypeFactory::falsey(); } public function getGreaterType() : Type { if ($this->value) { return new NeverType(); } return StaticTypeFactory::truthy(); } public function getGreaterOrEqualType() : Type { if ($this->value) { return StaticTypeFactory::truthy(); } return new MixedType(); } public function toBoolean() : BooleanType { return $this; } public function toNumber() : Type { return new \PHPStan\Type\Constant\ConstantIntegerType((int) $this->value); } public function toAbsoluteNumber() : Type { return $this->toNumber()->toAbsoluteNumber(); } public function toString() : Type { return new \PHPStan\Type\Constant\ConstantStringType((string) $this->value); } public function toInteger() : Type { return new \PHPStan\Type\Constant\ConstantIntegerType((int) $this->value); } public function toFloat() : Type { return new \PHPStan\Type\Constant\ConstantFloatType((float) $this->value); } public function toArrayKey() : Type { return new \PHPStan\Type\Constant\ConstantIntegerType((int) $this->value); } public function isTrue() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->value === \true); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->value === \false); } public function generalize(GeneralizePrecision $precision) : Type { return new BooleanType(); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode($this->value ? 'true' : 'false'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['value']); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { if ($type->isObject()->yes()) { return $this; } return $this->scalarLooseCompare($type, $phpVersion); } } value = $value; $this->isClassString = $isClassString; parent::__construct(); } public function getValue() : string { return $this->value; } public function getConstantStrings() : array { return [$this]; } public function isClassStringType() : TrinaryLogic { if ($this->isClassString) { return TrinaryLogic::createYes(); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); return TrinaryLogic::createFromBoolean($reflectionProvider->hasClass($this->value)); } public function getClassStringObjectType() : Type { if ($this->isClassStringType()->yes()) { return new ObjectType($this->value); } return new ErrorType(); } public function getObjectTypeOrClassStringObjectType() : Type { return $this->getClassStringObjectType(); } /** * @deprecated use isClassStringType() instead */ public function isClassString() : bool { return $this->isClassStringType()->yes(); } public function describe(VerbosityLevel $level) : string { return $level->handle(static function () : string { return 'string'; }, function () : string { $value = $this->value; if (!$this->isClassString) { try { $value = Strings::truncate($value, self::DESCRIBE_LIMIT); } catch (RegexpException $e) { $value = substr($value, 0, self::DESCRIBE_LIMIT) . "…"; } } return self::export($value); }, function () : string { return self::export($this->value); }); } private function export(string $value) : string { $escapedValue = addcslashes($value, "\x00..\x1f"); if ($escapedValue !== $value) { return '"' . addcslashes($value, "\x00..\x1f\\\"") . '"'; } return "'" . addcslashes($value, '\\\'') . "'"; } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof GenericClassStringType) { $genericType = $type->getGenericType(); if ($genericType instanceof MixedType) { return IsSuperTypeOfResult::createMaybe(); } if ($genericType instanceof StaticType) { $genericType = $genericType->getStaticObjectType(); } // We are transforming constant class-string to ObjectType. But we need to filter out // an uncertainty originating in possible ObjectType's class subtypes. $objectType = $this->getObjectType(); // Do not use TemplateType's isSuperTypeOf handling directly because it takes ObjectType // uncertainty into account. if ($genericType instanceof TemplateType) { $isSuperType = $genericType->getBound()->isSuperTypeOfWithReason($objectType); } else { $isSuperType = $genericType->isSuperTypeOfWithReason($objectType); } // Explicitly handle the uncertainty for Yes & Maybe. if ($isSuperType->yes()) { return IsSuperTypeOfResult::createMaybe(); } return IsSuperTypeOfResult::createNo(); } if ($type instanceof ClassStringType) { return $this->isClassStringType()->yes() ? IsSuperTypeOfResult::createMaybe() : IsSuperTypeOfResult::createNo(); } if ($type instanceof self) { return $this->value === $type->value ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createNo(); } if ($type instanceof parent) { return IsSuperTypeOfResult::createMaybe(); } if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } return IsSuperTypeOfResult::createNo(); } public function isCallable() : TrinaryLogic { if ($this->value === '') { return TrinaryLogic::createNo(); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); // 'my_function' if ($reflectionProvider->hasFunction(new Name($this->value), null)) { return TrinaryLogic::createYes(); } // 'MyClass::myStaticFunction' $matches = Strings::match($this->value, '#^([a-zA-Z_\\x7f-\\xff\\\\][a-zA-Z0-9_\\x7f-\\xff\\\\]*)::([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)\\z#'); if ($matches !== null) { if (!$reflectionProvider->hasClass($matches[1])) { return TrinaryLogic::createMaybe(); } $phpVersion = PhpVersionStaticAccessor::getInstance(); $classRef = $reflectionProvider->getClass($matches[1]); if ($classRef->hasMethod($matches[2])) { $method = $classRef->getMethod($matches[2], new OutOfClassScope()); if (BleedingEdgeToggle::isBleedingEdge() && !$phpVersion->supportsCallableInstanceMethods() && !$method->isStatic()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createYes(); } if (!$classRef->getNativeReflection()->isFinal()) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); } return TrinaryLogic::createNo(); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { if ($this->value === '') { return []; } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); // 'my_function' $functionName = new Name($this->value); if ($reflectionProvider->hasFunction($functionName, null)) { $function = $reflectionProvider->getFunction($functionName, null); return FunctionCallableVariant::createFromVariants($function, $function->getVariants()); } // 'MyClass::myStaticFunction' $matches = Strings::match($this->value, '#^([a-zA-Z_\\x7f-\\xff\\\\][a-zA-Z0-9_\\x7f-\\xff\\\\]*)::([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)\\z#'); if ($matches !== null) { if (!$reflectionProvider->hasClass($matches[1])) { return [new TrivialParametersAcceptor()]; } $classReflection = $reflectionProvider->getClass($matches[1]); if ($classReflection->hasMethod($matches[2])) { $method = $classReflection->getMethod($matches[2], $scope); if (!$scope->canCallMethod($method)) { return [new InaccessibleMethod($method)]; } return FunctionCallableVariant::createFromVariants($method, $method->getVariants()); } if (!$classReflection->getNativeReflection()->isFinal()) { return [new TrivialParametersAcceptor()]; } } throw new ShouldNotHappenException(); } public function toNumber() : Type { if (is_numeric($this->value)) { $value = $this->value; $value = +$value; if (is_float($value)) { return new \PHPStan\Type\Constant\ConstantFloatType($value); } return new \PHPStan\Type\Constant\ConstantIntegerType($value); } return new ErrorType(); } public function toAbsoluteNumber() : Type { return $this->toNumber()->toAbsoluteNumber(); } public function toInteger() : Type { return new \PHPStan\Type\Constant\ConstantIntegerType((int) $this->value); } public function toFloat() : Type { return new \PHPStan\Type\Constant\ConstantFloatType((float) $this->value); } public function toArrayKey() : Type { if ($this->arrayKeyType !== null) { return $this->arrayKeyType; } /** @var int|string $offsetValue */ $offsetValue = key([$this->value => null]); return $this->arrayKeyType = is_int($offsetValue) ? new \PHPStan\Type\Constant\ConstantIntegerType($offsetValue) : new \PHPStan\Type\Constant\ConstantStringType($offsetValue); } public function isString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createFromBoolean(is_numeric($this->getValue())); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->getValue() !== ''); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createFromBoolean(!in_array($this->getValue(), ['', '0'], \true)); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createFromBoolean(strtolower($this->value) === $this->value); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createFromBoolean(strtoupper($this->value) === $this->value); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { if ($offsetType->isInteger()->yes()) { $strlen = strlen($this->value); $strLenType = IntegerRangeType::fromInterval(-$strlen, $strlen - 1); return $strLenType->isSuperTypeOf($offsetType); } return parent::hasOffsetValueType($offsetType); } public function getOffsetValueType(Type $offsetType) : Type { if ($offsetType->isInteger()->yes()) { $strlen = strlen($this->value); $strLenType = IntegerRangeType::fromInterval(-$strlen, $strlen - 1); if ($offsetType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { if ($strLenType->isSuperTypeOf($offsetType)->yes()) { return new self($this->value[$offsetType->getValue()]); } return new ErrorType(); } $intersected = TypeCombinator::intersect($strLenType, $offsetType); if ($intersected instanceof IntegerRangeType) { $finiteTypes = $intersected->getFiniteTypes(); if ($finiteTypes === []) { return parent::getOffsetValueType($offsetType); } $chars = []; foreach ($finiteTypes as $constantInteger) { $chars[] = new self($this->value[$constantInteger->getValue()]); } if (!$strLenType->isSuperTypeOf($offsetType)->yes()) { $chars[] = new self(''); } return TypeCombinator::union(...$chars); } } return parent::getOffsetValueType($offsetType); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { $valueStringType = $valueType->toString(); if ($valueStringType instanceof ErrorType) { return new ErrorType(); } if ($offsetType instanceof \PHPStan\Type\Constant\ConstantIntegerType && $valueStringType instanceof \PHPStan\Type\Constant\ConstantStringType) { $value = $this->value; $offsetValue = $offsetType->getValue(); if ($offsetValue < 0) { return new ErrorType(); } $stringValue = $valueStringType->getValue(); if (strlen($stringValue) !== 1) { return new ErrorType(); } $value[$offsetValue] = $stringValue; return new self($value); } return parent::setOffsetValueType($offsetType, $valueType); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return parent::setOffsetValueType($offsetType, $valueType); } public function append(self $otherString) : self { return new self($this->getValue() . $otherString->getValue()); } public function generalize(GeneralizePrecision $precision) : Type { if ($this->isClassString) { if ($precision->isMoreSpecific()) { return new ClassStringType(); } return new StringType(); } if ($this->getValue() !== '' && $precision->isMoreSpecific()) { $accessories = [new StringType(), new AccessoryLiteralStringType()]; if (is_numeric($this->getValue())) { $accessories[] = new AccessoryNumericStringType(); } if ($this->getValue() !== '0') { $accessories[] = new AccessoryNonFalsyStringType(); } else { $accessories[] = new AccessoryNonEmptyStringType(); } if (strtolower($this->getValue()) === $this->getValue()) { $accessories[] = new AccessoryLowercaseStringType(); } if (strtoupper($this->getValue()) === $this->getValue()) { $accessories[] = new AccessoryUppercaseStringType(); } return new IntersectionType($accessories); } if ($precision->isMoreSpecific()) { return new IntersectionType([new StringType(), new AccessoryLiteralStringType()]); } return new StringType(); } public function getSmallerType() : Type { $subtractedTypes = [new \PHPStan\Type\Constant\ConstantBooleanType(\true), IntegerRangeType::createAllGreaterThanOrEqualTo((float) $this->value)]; if ($this->value === '') { $subtractedTypes[] = new NullType(); $subtractedTypes[] = new StringType(); } if (!(bool) $this->value) { $subtractedTypes[] = new \PHPStan\Type\Constant\ConstantBooleanType(\false); } return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } public function getSmallerOrEqualType() : Type { $subtractedTypes = [IntegerRangeType::createAllGreaterThan((float) $this->value)]; if (!(bool) $this->value) { $subtractedTypes[] = new \PHPStan\Type\Constant\ConstantBooleanType(\true); } return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } public function getGreaterType() : Type { $subtractedTypes = [new \PHPStan\Type\Constant\ConstantBooleanType(\false), IntegerRangeType::createAllSmallerThanOrEqualTo((float) $this->value)]; if ((bool) $this->value) { $subtractedTypes[] = new \PHPStan\Type\Constant\ConstantBooleanType(\true); } return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } public function getGreaterOrEqualType() : Type { $subtractedTypes = [IntegerRangeType::createAllSmallerThan((float) $this->value)]; if ((bool) $this->value) { $subtractedTypes[] = new \PHPStan\Type\Constant\ConstantBooleanType(\false); } return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } public function canAccessConstants() : TrinaryLogic { return $this->isClassStringType(); } public function hasConstant(string $constantName) : TrinaryLogic { return $this->getObjectType()->hasConstant($constantName); } public function getConstant(string $constantName) : ConstantReflection { return $this->getObjectType()->getConstant($constantName); } private function getObjectType() : ObjectType { return $this->objectType = $this->objectType ?? new ObjectType($this->value); } public function toPhpDocNode() : TypeNode { if (substr_count($this->value, "\n") > 0) { return $this->generalize(GeneralizePrecision::moreSpecific())->toPhpDocNode(); } return new ConstTypeNode(new QuoteAwareConstExprStringNode($this->value, QuoteAwareConstExprStringNode::SINGLE_QUOTED)); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['value'], $properties['isClassString'] ?? \false); } } value); } } items; for ($i = 0; $i < count($items); $i++) { $item = $items[$i]; if ($item === null) { continue; } if (!$item->unpack) { continue; } $valueType = $getTypeCallback($item->value); if ($valueType instanceof \PHPStan\Type\Constant\ConstantArrayType) { array_splice($items, $i, 1); foreach ($valueType->getKeyTypes() as $j => $innerKeyType) { $innerValueType = $valueType->getValueTypes()[$j]; if ($innerKeyType->isString()->no()) { $keyExpr = null; } else { $keyExpr = new TypeExpr($innerKeyType); } array_splice($items, $i++, 0, [new Expr\ArrayItem(new TypeExpr($innerValueType), $keyExpr)]); } } else { array_splice($items, $i, 1, [new Expr\ArrayItem(new TypeExpr($valueType->getIterableValueType()), new TypeExpr($valueType->getIterableKeyType()))]); } } foreach ($items as $item) { if ($item === null) { continue; } if ($item->unpack) { throw new ShouldNotHappenException(); } if ($item->key !== null) { $itemKeyType = $getTypeCallback($item->key); if (!$itemKeyType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { $isList = \false; } elseif ($itemKeyType->getValue() !== $nextAutoIndex) { $isList = \false; $nextAutoIndex = $itemKeyType->getValue() + 1; } else { $nextAutoIndex++; } } else { $itemKeyType = new \PHPStan\Type\Constant\ConstantIntegerType($nextAutoIndex); $nextAutoIndex++; } $generalizedKeyType = $itemKeyType->generalize(GeneralizePrecision::moreSpecific()); $keyTypes[$generalizedKeyType->describe(VerbosityLevel::precise())] = $generalizedKeyType; $itemValueType = $getTypeCallback($item->value); $generalizedValueType = $itemValueType->generalize(GeneralizePrecision::moreSpecific()); $valueTypes[$generalizedValueType->describe(VerbosityLevel::precise())] = $generalizedValueType; } $keyType = TypeCombinator::union(...array_values($keyTypes)); $valueType = TypeCombinator::union(...array_values($valueTypes)); $arrayType = new ArrayType($keyType, $valueType); if ($isList) { $arrayType = AccessoryArrayListType::intersectWith($arrayType); } return TypeCombinator::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType()); } } value = $value; parent::__construct(); } public function getValue() : float { return $this->value; } public function equals(Type $type) : bool { return $type instanceof self && ($this->value === $type->value || is_nan($this->value) && is_nan($type->value)); } private function castFloatToString(float $value) : string { $precisionBackup = ini_get('precision'); ini_set('precision', '-1'); try { $valueStr = (string) $value; if (is_finite($value) && !str_contains($valueStr, '.')) { $valueStr .= '.0'; } return $valueStr; } finally { ini_set('precision', $precisionBackup); } } public function describe(VerbosityLevel $level) : string { return $level->handle(static function () : string { return 'float'; }, function () : string { return $this->castFloatToString($this->value); }); } public function toString() : Type { return new \PHPStan\Type\Constant\ConstantStringType((string) $this->value); } public function toInteger() : Type { return new \PHPStan\Type\Constant\ConstantIntegerType((int) $this->value); } public function toAbsoluteNumber() : Type { return new self(abs($this->value)); } public function toArrayKey() : Type { return new \PHPStan\Type\Constant\ConstantIntegerType((int) $this->value); } public function generalize(GeneralizePrecision $precision) : Type { return new FloatType(); } /** * @return ConstTypeNode */ public function toPhpDocNode() : TypeNode { return new ConstTypeNode(new ConstExprFloatNode($this->castFloatToString($this->value))); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['value']); } } */ private $keyTypes; /** * @var array */ private $valueTypes; /** * @var int[] */ private $optionalKeys; private const DESCRIBE_LIMIT = 8; private const CHUNK_FINITE_TYPES_LIMIT = 5; /** * @var TrinaryLogic */ private $isList; /** @var self[]|null */ private $allArrays = null; /** @var non-empty-list */ private $nextAutoIndexes; /** * @api * @param array $keyTypes * @param array $valueTypes * @param non-empty-list|int $nextAutoIndexes * @param int[] $optionalKeys * @param bool|TrinaryLogic $isList */ public function __construct(array $keyTypes, array $valueTypes, $nextAutoIndexes = [0], array $optionalKeys = [], $isList = \false) { $this->keyTypes = $keyTypes; $this->valueTypes = $valueTypes; $this->optionalKeys = $optionalKeys; assert(count($keyTypes) === count($valueTypes)); if (is_int($nextAutoIndexes)) { $nextAutoIndexes = [$nextAutoIndexes]; } $this->nextAutoIndexes = $nextAutoIndexes; $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { $keyType = new NeverType(\true); $isList = TrinaryLogic::createYes(); } elseif ($keyTypesCount === 1) { $keyType = $this->keyTypes[0]; } else { $keyType = new UnionType($this->keyTypes); } if (is_bool($isList)) { $isList = TrinaryLogic::createFromBoolean($isList); } $this->isList = $isList; parent::__construct($keyType, count($valueTypes) > 0 ? TypeCombinator::union(...$valueTypes) : new NeverType(\true)); } public function getConstantArrays() : array { return [$this]; } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createYes(); } /** @deprecated Use isIterableAtLeastOnce()->no() instead */ public function isEmpty() : bool { return count($this->keyTypes) === 0; } /** * @return non-empty-list */ public function getNextAutoIndexes() : array { return $this->nextAutoIndexes; } /** * @deprecated */ public function getNextAutoIndex() : int { return $this->nextAutoIndexes[count($this->nextAutoIndexes) - 1]; } /** * @return int[] */ public function getOptionalKeys() : array { return $this->optionalKeys; } /** * @return self[] */ public function getAllArrays() : array { if ($this->allArrays !== null) { return $this->allArrays; } if (count($this->optionalKeys) <= 10) { $optionalKeysCombinations = $this->powerSet($this->optionalKeys); } else { $optionalKeysCombinations = [[], $this->optionalKeys]; } $requiredKeys = []; foreach (array_keys($this->keyTypes) as $i) { if (in_array($i, $this->optionalKeys, \true)) { continue; } $requiredKeys[] = $i; } $arrays = []; foreach ($optionalKeysCombinations as $combination) { $keys = array_merge($requiredKeys, $combination); sort($keys); if ($this->isList->yes() && array_keys($keys) !== $keys) { continue; } $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); foreach ($keys as $i) { $builder->setOffsetValueType($this->keyTypes[$i], $this->valueTypes[$i]); } $array = $builder->getArray(); if (!$array instanceof \PHPStan\Type\Constant\ConstantArrayType) { throw new ShouldNotHappenException(); } $arrays[] = $array; } return $this->allArrays = $arrays; } /** * @template T * @param T[] $in * @return T[][] */ private function powerSet(array $in) : array { $count = count($in); $members = pow(2, $count); $return = []; for ($i = 0; $i < $members; $i++) { $b = sprintf('%0' . $count . 'b', $i); $out = []; for ($j = 0; $j < $count; $j++) { if ($b[$j] !== '1') { continue; } $out[] = $in[$j]; } $return[] = $out; } return $return; } /** * @return array */ public function getKeyTypes() : array { return $this->keyTypes; } /** @deprecated Use getFirstIterableKeyType() instead */ public function getFirstKeyType() : Type { return $this->getFirstIterableKeyType(); } /** @deprecated Use getLastIterableKeyType() instead */ public function getLastKeyType() : Type { return $this->getLastIterableKeyType(); } /** * @return array */ public function getValueTypes() : array { return $this->valueTypes; } /** @deprecated Use getFirstIterableValueType() instead */ public function getFirstValueType() : Type { return $this->getFirstIterableValueType(); } /** @deprecated Use getLastIterableValueType() instead */ public function getLastValueType() : Type { return $this->getLastIterableValueType(); } public function isOptionalKey(int $i) : bool { return in_array($i, $this->optionalKeys, \true); } public function accepts(Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType && !$type instanceof IntersectionType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } if ($type instanceof self && count($this->keyTypes) === 0) { return AcceptsResult::createFromBoolean(count($type->keyTypes) === 0); } $result = AcceptsResult::createYes(); foreach ($this->keyTypes as $i => $keyType) { $valueType = $this->valueTypes[$i]; $hasOffsetValueType = $type->hasOffsetValueType($keyType); $hasOffset = new AcceptsResult($hasOffsetValueType, $hasOffsetValueType->yes() || !$type->isConstantArray()->yes() ? [] : [sprintf('Array %s have offset %s.', $hasOffsetValueType->no() ? 'does not' : 'might not', $keyType->describe(VerbosityLevel::value()))]); if ($hasOffset->no()) { if ($this->isOptionalKey($i)) { continue; } return $hasOffset; } if ($hasOffset->maybe() && $this->isOptionalKey($i)) { $hasOffset = AcceptsResult::createYes(); } $result = $result->and($hasOffset); $otherValueType = $type->getOffsetValueType($keyType); $verbosity = VerbosityLevel::getRecommendedLevelByType($valueType, $otherValueType); $acceptsValue = $valueType->acceptsWithReason($otherValueType, $strictTypes)->decorateReasons(static function (string $reason) use($keyType, $valueType, $verbosity, $otherValueType) { return sprintf('Offset %s (%s) does not accept type %s: %s', $keyType->describe(VerbosityLevel::precise()), $valueType->describe($verbosity), $otherValueType->describe($verbosity), $reason); }); if (!$acceptsValue->yes() && count($acceptsValue->reasons) === 0 && $type->isConstantArray()->yes()) { $acceptsValue = new AcceptsResult($acceptsValue->result, [sprintf('Offset %s (%s) does not accept type %s.', $keyType->describe(VerbosityLevel::precise()), $valueType->describe($verbosity), $otherValueType->describe($verbosity))]); } if ($acceptsValue->no()) { return $acceptsValue; } $result = $result->and($acceptsValue); } $result = $result->and(new AcceptsResult($type->isArray(), [])); if ($type->isOversizedArray()->yes()) { if (!$result->no()) { return AcceptsResult::createYes(); } } return $result; } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof self) { if (count($this->keyTypes) === 0) { return new IsSuperTypeOfResult($type->isIterableAtLeastOnce()->negate(), []); } $results = []; foreach ($this->keyTypes as $i => $keyType) { $hasOffset = $type->hasOffsetValueType($keyType); if ($hasOffset->no()) { if (!$this->isOptionalKey($i)) { return IsSuperTypeOfResult::createNo(); } $results[] = IsSuperTypeOfResult::createYes(); continue; } elseif ($hasOffset->maybe() && !$this->isOptionalKey($i)) { $results[] = IsSuperTypeOfResult::createMaybe(); } $isValueSuperType = $this->valueTypes[$i]->isSuperTypeOfWithReason($type->getOffsetValueType($keyType)); if ($isValueSuperType->no()) { return $isValueSuperType->decorateReasons(static function (string $reason) use($keyType) { return sprintf('Offset %s: %s', $keyType->describe(VerbosityLevel::value()), $reason); }); } $results[] = $isValueSuperType; } return IsSuperTypeOfResult::createYes()->and(...$results); } if ($type instanceof ArrayType) { $result = IsSuperTypeOfResult::createMaybe(); if (count($this->keyTypes) === 0) { return $result; } $isKeySuperType = $this->getKeyType()->isSuperTypeOfWithReason($type->getKeyType()); if ($isKeySuperType->no()) { return $isKeySuperType; } return $result->and($isKeySuperType, $this->getItemType()->isSuperTypeOfWithReason($type->getItemType())); } if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } return IsSuperTypeOfResult::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { if ($this->isIterableAtLeastOnce()->no() && count($type->getConstantScalarValues()) === 1) { // @phpstan-ignore equal.invalid, equal.notAllowed return new \PHPStan\Type\Constant\ConstantBooleanType($type->getConstantScalarValues()[0] == []); // phpcs:ignore } return new BooleanType(); } public function equals(Type $type) : bool { if (!$type instanceof self) { return \false; } if (count($this->keyTypes) !== count($type->keyTypes)) { return \false; } foreach ($this->keyTypes as $i => $keyType) { $valueType = $this->valueTypes[$i]; if (!$valueType->equals($type->valueTypes[$i])) { return \false; } if (!$keyType->equals($type->keyTypes[$i])) { return \false; } } if ($this->optionalKeys !== $type->optionalKeys) { return \false; } return \true; } public function isCallable() : TrinaryLogic { $typeAndMethods = $this->findTypeAndMethodNames(); if ($typeAndMethods === []) { return TrinaryLogic::createNo(); } $results = array_map(static function (\PHPStan\Type\Constant\ConstantArrayTypeAndMethod $typeAndMethod) : TrinaryLogic { return $typeAndMethod->getCertainty(); }, $typeAndMethods); return TrinaryLogic::createYes()->and(...$results); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { $typeAndMethodNames = $this->findTypeAndMethodNames(); if ($typeAndMethodNames === []) { throw new ShouldNotHappenException(); } $acceptors = []; foreach ($typeAndMethodNames as $typeAndMethodName) { if ($typeAndMethodName->isUnknown() || !$typeAndMethodName->getCertainty()->yes()) { $acceptors[] = new TrivialParametersAcceptor(); continue; } $method = $typeAndMethodName->getType()->getMethod($typeAndMethodName->getMethod(), $scope); if (!$scope->canCallMethod($method)) { $acceptors[] = new InaccessibleMethod($method); continue; } array_push($acceptors, ...FunctionCallableVariant::createFromVariants($method, $method->getVariants())); } return $acceptors; } /** * @return array{Type, Type}|array{} */ private function getClassOrObjectAndMethods() : array { if (count($this->keyTypes) !== 2) { return []; } $classOrObject = null; $method = null; foreach ($this->keyTypes as $i => $keyType) { if ($keyType->isSuperTypeOf(new \PHPStan\Type\Constant\ConstantIntegerType(0))->yes()) { $classOrObject = $this->valueTypes[$i]; continue; } if (!$keyType->isSuperTypeOf(new \PHPStan\Type\Constant\ConstantIntegerType(1))->yes()) { continue; } $method = $this->valueTypes[$i]; } if ($classOrObject === null || $method === null) { return []; } return [$classOrObject, $method]; } /** @deprecated Use findTypeAndMethodNames() instead */ public function findTypeAndMethodName() : ?\PHPStan\Type\Constant\ConstantArrayTypeAndMethod { $callableArray = $this->getClassOrObjectAndMethods(); if ($callableArray === []) { return null; } [$classOrObject, $method] = $callableArray; if (!$method instanceof \PHPStan\Type\Constant\ConstantStringType) { return \PHPStan\Type\Constant\ConstantArrayTypeAndMethod::createUnknown(); } $type = $classOrObject->getObjectTypeOrClassStringObjectType(); if (!$type->isObject()->yes()) { return \PHPStan\Type\Constant\ConstantArrayTypeAndMethod::createUnknown(); } $has = $type->hasMethod($method->getValue()); if (!$has->no()) { if ($this->isOptionalKey(0) || $this->isOptionalKey(1)) { $has = $has->and(TrinaryLogic::createMaybe()); } return \PHPStan\Type\Constant\ConstantArrayTypeAndMethod::createConcrete($type, $method->getValue(), $has); } return null; } /** @return ConstantArrayTypeAndMethod[] */ public function findTypeAndMethodNames() : array { $callableArray = $this->getClassOrObjectAndMethods(); if ($callableArray === []) { return []; } [$classOrObject, $methods] = $callableArray; if (count($methods->getConstantStrings()) === 0) { return [\PHPStan\Type\Constant\ConstantArrayTypeAndMethod::createUnknown()]; } $type = $classOrObject->getObjectTypeOrClassStringObjectType(); if (!$type->isObject()->yes()) { return [\PHPStan\Type\Constant\ConstantArrayTypeAndMethod::createUnknown()]; } $typeAndMethods = []; $phpVersion = PhpVersionStaticAccessor::getInstance(); foreach ($methods->getConstantStrings() as $method) { $has = $type->hasMethod($method->getValue()); if ($has->no()) { continue; } if (BleedingEdgeToggle::isBleedingEdge() && $has->yes() && !$phpVersion->supportsCallableInstanceMethods()) { $methodReflection = $type->getMethod($method->getValue(), new OutOfClassScope()); if ($classOrObject->isString()->yes() && !$methodReflection->isStatic()) { continue; } } if ($this->isOptionalKey(0) || $this->isOptionalKey(1)) { $has = $has->and(TrinaryLogic::createMaybe()); } $typeAndMethods[] = \PHPStan\Type\Constant\ConstantArrayTypeAndMethod::createConcrete($type, $method->getValue(), $has); } return $typeAndMethods; } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { $offsetArrayKeyType = $offsetType->toArrayKey(); return $this->recursiveHasOffsetValueType($offsetArrayKeyType); } private function recursiveHasOffsetValueType(Type $offsetType) : TrinaryLogic { if ($offsetType instanceof UnionType) { $results = []; foreach ($offsetType->getTypes() as $innerType) { $results[] = $this->recursiveHasOffsetValueType($innerType); } return TrinaryLogic::extremeIdentity(...$results); } if ($offsetType instanceof IntegerRangeType) { $finiteTypes = $offsetType->getFiniteTypes(); if ($finiteTypes !== []) { $results = []; foreach ($finiteTypes as $innerType) { $results[] = $this->recursiveHasOffsetValueType($innerType); } return TrinaryLogic::extremeIdentity(...$results); } } $result = TrinaryLogic::createNo(); foreach ($this->keyTypes as $i => $keyType) { if ($keyType instanceof \PHPStan\Type\Constant\ConstantIntegerType && !$offsetType->isString()->no() && $offsetType->isConstantScalarValue()->no()) { return TrinaryLogic::createMaybe(); } $has = $keyType->isSuperTypeOf($offsetType); if ($has->yes()) { if ($this->isOptionalKey($i)) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createYes(); } if (!$has->maybe()) { continue; } $result = TrinaryLogic::createMaybe(); } return $result; } public function getOffsetValueType(Type $offsetType) : Type { if (count($this->keyTypes) === 0) { return new ErrorType(); } $offsetType = $offsetType->toArrayKey(); $matchingValueTypes = []; $all = \true; $maybeAll = \true; foreach ($this->keyTypes as $i => $keyType) { if ($keyType->isSuperTypeOf($offsetType)->no()) { $all = \false; if ($keyType instanceof \PHPStan\Type\Constant\ConstantIntegerType && !$offsetType->isString()->no() && $offsetType->isConstantScalarValue()->no()) { continue; } $maybeAll = \false; continue; } $matchingValueTypes[] = $this->valueTypes[$i]; } if ($all) { return $this->getIterableValueType(); } if (count($matchingValueTypes) > 0) { $type = TypeCombinator::union(...$matchingValueTypes); if ($type instanceof ErrorType) { return new MixedType(); } return $type; } if ($maybeAll) { return $this->getIterableValueType(); } return new ErrorType(); // undefined offset } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createFromConstantArray($this); $builder->setOffsetValueType($offsetType, $valueType); return $builder->getArray(); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { $offsetType = $offsetType->toArrayKey(); $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createFromConstantArray($this); foreach ($this->keyTypes as $keyType) { if ($offsetType->isSuperTypeOf($keyType)->no()) { continue; } $builder->setOffsetValueType($keyType, $valueType); } return $builder->getArray(); } public function unsetOffset(Type $offsetType) : Type { $offsetType = $offsetType->toArrayKey(); if ($offsetType instanceof \PHPStan\Type\Constant\ConstantIntegerType || $offsetType instanceof \PHPStan\Type\Constant\ConstantStringType) { foreach ($this->keyTypes as $i => $keyType) { if ($keyType->getValue() !== $offsetType->getValue()) { continue; } $keyTypes = $this->keyTypes; unset($keyTypes[$i]); $valueTypes = $this->valueTypes; unset($valueTypes[$i]); $newKeyTypes = []; $newValueTypes = []; $newOptionalKeys = []; $k = 0; foreach ($keyTypes as $j => $newKeyType) { $newKeyTypes[] = $newKeyType; $newValueTypes[] = $valueTypes[$j]; if (in_array($j, $this->optionalKeys, \true)) { $newOptionalKeys[] = $k; } $k++; } return new self($newKeyTypes, $newValueTypes, $this->nextAutoIndexes, $newOptionalKeys, TrinaryLogic::createNo()); } return $this; } $constantScalars = $offsetType->getConstantScalarTypes(); if (count($constantScalars) > 0) { $optionalKeys = $this->optionalKeys; foreach ($constantScalars as $constantScalar) { $constantScalar = $constantScalar->toArrayKey(); if (!$constantScalar instanceof \PHPStan\Type\Constant\ConstantIntegerType && !$constantScalar instanceof \PHPStan\Type\Constant\ConstantStringType) { continue; } foreach ($this->keyTypes as $i => $keyType) { if ($keyType->getValue() !== $constantScalar->getValue()) { continue; } if (in_array($i, $optionalKeys, \true)) { continue 2; } $optionalKeys[] = $i; } } return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, $optionalKeys, TrinaryLogic::createNo()); } $optionalKeys = $this->optionalKeys; $isList = $this->isList; foreach ($this->keyTypes as $i => $keyType) { if (!$offsetType->isSuperTypeOf($keyType)->yes()) { continue; } $optionalKeys[] = $i; $isList = TrinaryLogic::createNo(); } $optionalKeys = array_values(array_unique($optionalKeys)); return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, $optionalKeys, $isList); } public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys) : Type { $biggerOne = IntegerRangeType::fromInterval(1, null); $finiteTypes = $lengthType->getFiniteTypes(); if ($biggerOne->isSuperTypeOf($lengthType)->yes() && count($finiteTypes) < self::CHUNK_FINITE_TYPES_LIMIT) { $results = []; foreach ($finiteTypes as $finiteType) { if (!$finiteType instanceof \PHPStan\Type\Constant\ConstantIntegerType || $finiteType->getValue() < 1) { return parent::chunkArray($lengthType, $preserveKeys); } $length = $finiteType->getValue(); $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); $keyTypesCount = count($this->keyTypes); for ($i = 0; $i < $keyTypesCount; $i += $length) { $chunk = $this->sliceArray(new \PHPStan\Type\Constant\ConstantIntegerType($i), new \PHPStan\Type\Constant\ConstantIntegerType($length), TrinaryLogic::createYes()); $builder->setOffsetValueType(null, $preserveKeys->yes() ? $chunk : $chunk->getValuesArray()); } $results[] = $builder->getArray(); } return TypeCombinator::union(...$results); } return parent::chunkArray($lengthType, $preserveKeys); } public function fillKeysArray(Type $valueType) : Type { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); foreach ($this->valueTypes as $i => $keyType) { if ($keyType->isInteger()->no()) { $stringKeyType = $keyType->toString(); if ($stringKeyType instanceof ErrorType) { return $stringKeyType; } $builder->setOffsetValueType($stringKeyType, $valueType, $this->isOptionalKey($i)); } else { $builder->setOffsetValueType($keyType, $valueType, $this->isOptionalKey($i)); } } return $builder->getArray(); } public function flipArray() : Type { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); foreach ($this->keyTypes as $i => $keyType) { $valueType = $this->valueTypes[$i]; $builder->setOffsetValueType($valueType->toArrayKey(), $keyType, $this->isOptionalKey($i)); } return $builder->getArray(); } public function intersectKeyArray(Type $otherArraysType) : Type { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); foreach ($this->keyTypes as $i => $keyType) { $valueType = $this->valueTypes[$i]; $has = $otherArraysType->hasOffsetValueType($keyType); if ($has->no()) { continue; } $builder->setOffsetValueType($keyType, $valueType, $this->isOptionalKey($i) || !$has->yes()); } return $builder->getArray(); } public function popArray() : Type { return $this->removeLastElements(1); } public function reverseArray(TrinaryLogic $preserveKeys) : Type { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); for ($i = count($this->keyTypes) - 1; $i >= 0; $i--) { $offsetType = $preserveKeys->yes() || $this->keyTypes[$i]->isInteger()->no() ? $this->keyTypes[$i] : null; $builder->setOffsetValueType($offsetType, $this->valueTypes[$i], $this->isOptionalKey($i)); } return $builder->getArray(); } public function searchArray(Type $needleType) : Type { $matches = []; $hasIdenticalValue = \false; foreach ($this->valueTypes as $index => $valueType) { $isNeedleSuperType = $valueType->isSuperTypeOf($needleType); if ($isNeedleSuperType->no()) { continue; } if ($needleType instanceof ConstantScalarType && $valueType instanceof ConstantScalarType && $needleType->getValue() === $valueType->getValue() && !$this->isOptionalKey($index)) { $hasIdenticalValue = \true; } $matches[] = $this->keyTypes[$index]; } if (count($matches) > 0) { if ($hasIdenticalValue) { return TypeCombinator::union(...$matches); } return TypeCombinator::union(new \PHPStan\Type\Constant\ConstantBooleanType(\false), ...$matches); } return new \PHPStan\Type\Constant\ConstantBooleanType(\false); } public function shiftArray() : Type { return $this->removeFirstElements(1); } public function shuffleArray() : Type { $valuesArray = $this->getValuesArray(); $isIterableAtLeastOnce = $valuesArray->isIterableAtLeastOnce(); if ($isIterableAtLeastOnce->no()) { return $valuesArray; } $generalizedArray = new ArrayType($valuesArray->getIterableKeyType(), $valuesArray->getItemType()); if ($isIterableAtLeastOnce->yes()) { $generalizedArray = TypeCombinator::intersect($generalizedArray, new NonEmptyArrayType()); } if ($valuesArray->isList->yes()) { $generalizedArray = AccessoryArrayListType::intersectWith($generalizedArray); } return $generalizedArray; } public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys) : Type { $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { return $this; } $offset = $offsetType instanceof \PHPStan\Type\Constant\ConstantIntegerType ? $offsetType->getValue() : 0; $length = $lengthType instanceof \PHPStan\Type\Constant\ConstantIntegerType ? $lengthType->getValue() : $keyTypesCount; if ($length < 0) { // Negative lengths prevent access to the most right n elements return $this->removeLastElements($length * -1)->sliceArray($offsetType, new NullType(), $preserveKeys); } if ($keyTypesCount + $offset <= 0) { // A negative offset cannot reach left outside the array $offset = 0; } if ($offset < 0) { /* * Transforms the problem with the negative offset in one with a positive offset using array reversion. * The reason is belows handling of optional keys which works only from left to right. * * e.g. * array{a: 0, b: 1, c: 2, d: 3, e: 4} * with offset -4 and length 2 (which would be sliced to array{b: 1, c: 2}) * * is transformed via reversion to * * array{e: 4, d: 3, c: 2, b: 1, a: 0} * with offset 2 and length 2 (which will be sliced to array{c: 2, b: 1} and then reversed again) */ $offset *= -1; $reversedLength = min($length, $offset); $reversedOffset = $offset - $reversedLength; return $this->reverseArray(TrinaryLogic::createYes())->sliceArray(new \PHPStan\Type\Constant\ConstantIntegerType($reversedOffset), new \PHPStan\Type\Constant\ConstantIntegerType($reversedLength), $preserveKeys)->reverseArray(TrinaryLogic::createYes()); } if ($offset > 0) { return $this->removeFirstElements($offset, \false)->sliceArray(new \PHPStan\Type\Constant\ConstantIntegerType(0), $lengthType, $preserveKeys); } $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); $nonOptionalElementsCount = 0; $hasOptional = \false; for ($i = 0; $nonOptionalElementsCount < $length && $i < $keyTypesCount; $i++) { $isOptional = $this->isOptionalKey($i); if (!$isOptional) { $nonOptionalElementsCount++; } else { $hasOptional = \true; } $isLastElement = $nonOptionalElementsCount >= $length || $i + 1 >= $keyTypesCount; if ($isLastElement && $length < $keyTypesCount && $hasOptional) { // If the slice is not full yet, but has at least one optional key // the last non-optional element is going to be optional. // Otherwise, it would not fit into the slice if previous non-optional keys are there. $isOptional = \true; } $builder->setOffsetValueType($this->keyTypes[$i], $this->valueTypes[$i], $isOptional); } $slice = $builder->getArray(); if (!$slice instanceof self) { throw new ShouldNotHappenException(); } return $preserveKeys->yes() ? $slice : $slice->reindex(); } public function isIterableAtLeastOnce() : TrinaryLogic { $keysCount = count($this->keyTypes); if ($keysCount === 0) { return TrinaryLogic::createNo(); } $optionalKeysCount = count($this->optionalKeys); if ($optionalKeysCount < $keysCount) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function getArraySize() : Type { $optionalKeysCount = count($this->optionalKeys); $totalKeysCount = count($this->getKeyTypes()); if ($optionalKeysCount === 0) { return new \PHPStan\Type\Constant\ConstantIntegerType($totalKeysCount); } return IntegerRangeType::fromInterval($totalKeysCount - $optionalKeysCount, $totalKeysCount); } public function getFirstIterableKeyType() : Type { $keyTypes = []; foreach ($this->keyTypes as $i => $keyType) { $keyTypes[] = $keyType; if (!$this->isOptionalKey($i)) { break; } } return TypeCombinator::union(...$keyTypes); } public function getLastIterableKeyType() : Type { $keyTypes = []; for ($i = count($this->keyTypes) - 1; $i >= 0; $i--) { $keyTypes[] = $this->keyTypes[$i]; if (!$this->isOptionalKey($i)) { break; } } return TypeCombinator::union(...$keyTypes); } public function getFirstIterableValueType() : Type { $valueTypes = []; foreach ($this->valueTypes as $i => $valueType) { $valueTypes[] = $valueType; if (!$this->isOptionalKey($i)) { break; } } return TypeCombinator::union(...$valueTypes); } public function getLastIterableValueType() : Type { $valueTypes = []; for ($i = count($this->keyTypes) - 1; $i >= 0; $i--) { $valueTypes[] = $this->valueTypes[$i]; if (!$this->isOptionalKey($i)) { break; } } return TypeCombinator::union(...$valueTypes); } public function isConstantArray() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isList() : TrinaryLogic { return $this->isList; } /** @deprecated Use popArray() instead */ public function removeLast() : self { return $this->removeLastElements(1); } /** @param positive-int $length */ private function removeLastElements(int $length) : self { $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { return $this; } $keyTypes = $this->keyTypes; $valueTypes = $this->valueTypes; $optionalKeys = $this->optionalKeys; $nextAutoindex = $this->nextAutoIndexes; $optionalKeysRemoved = 0; $newLength = $keyTypesCount - $length; for ($i = $keyTypesCount - 1; $i >= 0; $i--) { $isOptional = $this->isOptionalKey($i); if ($i >= $newLength) { if ($isOptional) { $optionalKeysRemoved++; foreach ($optionalKeys as $key => $value) { if ($value === $i) { unset($optionalKeys[$key]); break; } } } $removedKeyType = array_pop($keyTypes); array_pop($valueTypes); $nextAutoindex = $removedKeyType instanceof \PHPStan\Type\Constant\ConstantIntegerType ? $removedKeyType->getValue() : $this->getNextAutoIndex(); // @phpstan-ignore method.deprecated continue; } if ($isOptional || $optionalKeysRemoved <= 0) { continue; } $optionalKeys[] = $i; $optionalKeysRemoved--; } return new self($keyTypes, $valueTypes, $nextAutoindex, array_values($optionalKeys), $this->isList); } /** @deprecated Use shiftArray() instead */ public function removeFirst() : self { return $this->removeFirstElements(1); } /** @param positive-int $length */ private function removeFirstElements(int $length, bool $reindex = \true) : self { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); $optionalKeysIgnored = 0; foreach ($this->keyTypes as $i => $keyType) { $isOptional = $this->isOptionalKey($i); if ($i <= $length - 1) { if ($isOptional) { $optionalKeysIgnored++; } continue; } if (!$isOptional && $optionalKeysIgnored > 0) { $isOptional = \true; $optionalKeysIgnored--; } $valueType = $this->valueTypes[$i]; if ($reindex && $keyType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { $keyType = null; } $builder->setOffsetValueType($keyType, $valueType, $isOptional); } $array = $builder->getArray(); if (!$array instanceof self) { throw new ShouldNotHappenException(); } return $array; } /** @deprecated Use sliceArray() instead */ public function slice(int $offset, ?int $limit, bool $preserveKeys = \false) : self { $array = $this->sliceArray(ConstantTypeHelper::getTypeFromValue($offset), ConstantTypeHelper::getTypeFromValue($limit), TrinaryLogic::createFromBoolean($preserveKeys)); if (!$array instanceof self) { throw new ShouldNotHappenException(); } return $array; } /** @deprecated Use reverseArray() instead */ public function reverse(bool $preserveKeys = \false) : self { $array = $this->reverseArray(TrinaryLogic::createFromBoolean($preserveKeys)); if (!$array instanceof self) { throw new ShouldNotHappenException(); } return $array; } /** * @deprecated Use chunkArray() instead * @param positive-int $length */ public function chunk(int $length, bool $preserveKeys = \false) : self { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); $keyTypesCount = count($this->keyTypes); for ($i = 0; $i < $keyTypesCount; $i += $length) { $chunk = $this->slice($i, $length, \true); $builder->setOffsetValueType(null, $preserveKeys ? $chunk : $chunk->getValuesArray()); } $chunks = $builder->getArray(); if (!$chunks instanceof self) { throw new ShouldNotHappenException(); } return $chunks; } private function reindex() : self { $keyTypes = []; $autoIndex = 0; foreach ($this->keyTypes as $keyType) { if (!$keyType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { $keyTypes[] = $keyType; continue; } $keyTypes[] = new \PHPStan\Type\Constant\ConstantIntegerType($autoIndex); $autoIndex++; } return new self($keyTypes, $this->valueTypes, [$autoIndex], $this->optionalKeys, TrinaryLogic::createYes()); } public function toBoolean() : BooleanType { return $this->getArraySize()->toBoolean(); } public function toInteger() : Type { return $this->toBoolean()->toInteger(); } public function toFloat() : Type { return $this->toBoolean()->toFloat(); } public function generalize(GeneralizePrecision $precision) : Type { if (count($this->keyTypes) === 0) { return $this; } if ($precision->isTemplateArgument()) { return $this->traverse(static function (Type $type) use($precision) { return $type->generalize($precision); }); } $arrayType = new ArrayType($this->getIterableKeyType()->generalize($precision), $this->getItemType()->generalize($precision)); $keyTypesCount = count($this->keyTypes); $optionalKeysCount = count($this->optionalKeys); $accessoryTypes = []; if ($precision->isMoreSpecific() && $keyTypesCount - $optionalKeysCount < 32) { foreach ($this->keyTypes as $i => $keyType) { if ($this->isOptionalKey($i)) { continue; } $accessoryTypes[] = new HasOffsetValueType($keyType, $this->valueTypes[$i]->generalize($precision)); } } elseif ($keyTypesCount > $optionalKeysCount) { $accessoryTypes[] = new NonEmptyArrayType(); } if ($this->isList()->yes()) { $arrayType = AccessoryArrayListType::intersectWith($arrayType); } if (count($accessoryTypes) > 0) { return TypeCombinator::intersect($arrayType, ...$accessoryTypes); } return $arrayType; } /** * @return self */ public function generalizeValues() : ArrayType { $valueTypes = []; foreach ($this->valueTypes as $valueType) { $valueTypes[] = $valueType->generalize(GeneralizePrecision::lessSpecific()); } return new self($this->keyTypes, $valueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList); } /** @deprecated */ public function generalizeToArray() : Type { $isIterableAtLeastOnce = $this->isIterableAtLeastOnce(); if ($isIterableAtLeastOnce->no()) { return $this; } $arrayType = new ArrayType($this->getIterableKeyType(), $this->getItemType()); if ($isIterableAtLeastOnce->yes()) { $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } if ($this->isList->yes()) { $arrayType = AccessoryArrayListType::intersectWith($arrayType); } return $arrayType; } /** * @return self */ public function getKeysArray() : Type { return $this->getKeysOrValuesArray($this->keyTypes); } /** * @return self */ public function getValuesArray() : Type { return $this->getKeysOrValuesArray($this->valueTypes); } /** * @param array $types */ private function getKeysOrValuesArray(array $types) : self { $count = count($types); $autoIndexes = range($count - count($this->optionalKeys), $count); assert($autoIndexes !== []); if ($this->isList->yes()) { // Optimized version for lists: Assume that if a later key exists, then earlier keys also exist. $keyTypes = array_map(static function (int $i) : \PHPStan\Type\Constant\ConstantIntegerType { return new \PHPStan\Type\Constant\ConstantIntegerType($i); }, array_keys($types)); return new self($keyTypes, $types, $autoIndexes, $this->optionalKeys, TrinaryLogic::createYes()); } $keyTypes = []; $valueTypes = []; $optionalKeys = []; $maxIndex = 0; foreach ($types as $i => $type) { $keyTypes[] = new \PHPStan\Type\Constant\ConstantIntegerType($i); if ($this->isOptionalKey($maxIndex)) { // move $maxIndex to next non-optional key do { $maxIndex++; } while ($maxIndex < $count && $this->isOptionalKey($maxIndex)); } if ($i === $maxIndex) { $valueTypes[] = $type; } else { $valueTypes[] = TypeCombinator::union(...array_slice($types, $i, $maxIndex - $i + 1)); if ($maxIndex >= $count) { $optionalKeys[] = $i; } } $maxIndex++; } return new self($keyTypes, $valueTypes, $autoIndexes, $optionalKeys, TrinaryLogic::createYes()); } /** @deprecated Use getArraySize() instead */ public function count() : Type { return $this->getArraySize(); } public function describe(VerbosityLevel $level) : string { $describeValue = function (bool $truncate) use($level) : string { $items = []; $values = []; $exportValuesOnly = \true; foreach ($this->keyTypes as $i => $keyType) { $valueType = $this->valueTypes[$i]; if ($keyType->getValue() !== $i) { $exportValuesOnly = \false; } $isOptional = $this->isOptionalKey($i); if ($isOptional) { $exportValuesOnly = \false; } $keyDescription = $keyType->getValue(); if (is_string($keyDescription)) { if (str_contains($keyDescription, '"')) { $keyDescription = sprintf('\'%s\'', $keyDescription); } elseif (str_contains($keyDescription, '\'')) { $keyDescription = sprintf('"%s"', $keyDescription); } } $valueTypeDescription = $valueType->describe($level); $items[] = sprintf('%s%s: %s', $keyDescription, $isOptional ? '?' : '', $valueTypeDescription); $values[] = $valueTypeDescription; } $append = ''; if ($truncate && count($items) > self::DESCRIBE_LIMIT) { $items = array_slice($items, 0, self::DESCRIBE_LIMIT); $values = array_slice($values, 0, self::DESCRIBE_LIMIT); $append = ', ...'; } return sprintf('array{%s%s}', implode(', ', $exportValuesOnly ? $values : $items), $append); }; return $level->handle(function () use($level) : string { return parent::describe($level); }, static function () use($describeValue) : string { return $describeValue(\true); }, static function () use($describeValue) : string { return $describeValue(\false); }); } public function inferTemplateTypes(Type $receivedType) : TemplateTypeMap { if ($receivedType instanceof UnionType || $receivedType instanceof IntersectionType) { return $receivedType->inferTemplateTypesOn($this); } if ($receivedType instanceof self) { $typeMap = TemplateTypeMap::createEmpty(); foreach ($this->keyTypes as $i => $keyType) { $valueType = $this->valueTypes[$i]; if ($receivedType->hasOffsetValueType($keyType)->no()) { continue; } $receivedValueType = $receivedType->getOffsetValueType($keyType); $typeMap = $typeMap->union($valueType->inferTemplateTypes($receivedValueType)); } return $typeMap; } return parent::inferTemplateTypes($receivedType); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { $variance = $positionVariance->compose(TemplateTypeVariance::createCovariant()); $references = []; foreach ($this->keyTypes as $type) { foreach ($type->getReferencedTemplateTypes($variance) as $reference) { $references[] = $reference; } } foreach ($this->valueTypes as $type) { foreach ($type->getReferencedTemplateTypes($variance) as $reference) { $references[] = $reference; } } return $references; } public function traverse(callable $cb) : Type { $valueTypes = []; $stillOriginal = \true; foreach ($this->valueTypes as $valueType) { $transformedValueType = $cb($valueType); if ($transformedValueType !== $valueType) { $stillOriginal = \false; } $valueTypes[] = $transformedValueType; } if ($stillOriginal) { return $this; } return new self($this->keyTypes, $valueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList); } public function traverseSimultaneously(Type $right, callable $cb) : Type { if (!$right->isArray()->yes()) { return $this; } $valueTypes = []; $stillOriginal = \true; foreach ($this->valueTypes as $i => $valueType) { $keyType = $this->keyTypes[$i]; $transformedValueType = $cb($valueType, $right->getOffsetValueType($keyType)); if ($transformedValueType !== $valueType) { $stillOriginal = \false; } $valueTypes[] = $transformedValueType; } if ($stillOriginal) { return $this; } return new self($this->keyTypes, $valueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList); } public function isKeysSupersetOf(self $otherArray) : bool { $keyTypesCount = count($this->keyTypes); $otherKeyTypesCount = count($otherArray->keyTypes); if ($keyTypesCount < $otherKeyTypesCount) { return \false; } if ($otherKeyTypesCount === 0) { return $keyTypesCount === 0; } $failOnDifferentValueType = $keyTypesCount !== $otherKeyTypesCount || $keyTypesCount < 2; $keyTypes = $this->keyTypes; foreach ($otherArray->keyTypes as $j => $keyType) { $i = self::findKeyIndex($keyType, $keyTypes); if ($i === null) { return \false; } unset($keyTypes[$i]); $valueType = $this->valueTypes[$i]; $otherValueType = $otherArray->valueTypes[$j]; if (!$otherValueType->isSuperTypeOf($valueType)->no()) { continue; } if ($failOnDifferentValueType) { return \false; } $failOnDifferentValueType = \true; } $requiredKeyCount = 0; foreach (array_keys($keyTypes) as $i) { if ($this->isOptionalKey($i)) { continue; } $requiredKeyCount++; if ($requiredKeyCount > 1) { return \false; } } return \true; } public function mergeWith(self $otherArray) : self { // only call this after verifying isKeysSupersetOf, or if losing tagged unions is not an issue $valueTypes = $this->valueTypes; $optionalKeys = $this->optionalKeys; foreach ($this->keyTypes as $i => $keyType) { $otherIndex = $otherArray->getKeyIndex($keyType); if ($otherIndex === null) { $optionalKeys[] = $i; continue; } if ($otherArray->isOptionalKey($otherIndex)) { $optionalKeys[] = $i; } $otherValueType = $otherArray->valueTypes[$otherIndex]; $valueTypes[$i] = TypeCombinator::union($valueTypes[$i], $otherValueType); } $optionalKeys = array_values(array_unique($optionalKeys)); $nextAutoIndexes = array_values(array_unique(array_merge($this->nextAutoIndexes, $otherArray->nextAutoIndexes))); sort($nextAutoIndexes); return new self($this->keyTypes, $valueTypes, $nextAutoIndexes, $optionalKeys, $this->isList->and($otherArray->isList)); } /** * @param ConstantIntegerType|ConstantStringType $otherKeyType */ private function getKeyIndex($otherKeyType) : ?int { return self::findKeyIndex($otherKeyType, $this->keyTypes); } /** * @param ConstantIntegerType|ConstantStringType $otherKeyType * @param array $keyTypes */ private static function findKeyIndex($otherKeyType, array $keyTypes) : ?int { foreach ($keyTypes as $i => $keyType) { if ($keyType->equals($otherKeyType)) { return $i; } } return null; } public function makeOffsetRequired(Type $offsetType) : self { $offsetType = $offsetType->toArrayKey(); $optionalKeys = $this->optionalKeys; foreach ($this->keyTypes as $i => $keyType) { if (!$keyType->equals($offsetType)) { continue; } foreach ($optionalKeys as $j => $key) { if ($i === $key) { unset($optionalKeys[$j]); return new self($this->keyTypes, $this->valueTypes, $this->nextAutoIndexes, array_values($optionalKeys), $this->isList); } } break; } return $this; } public function toPhpDocNode() : TypeNode { $items = []; $values = []; $exportValuesOnly = \true; foreach ($this->keyTypes as $i => $keyType) { if ($keyType->getValue() !== $i) { $exportValuesOnly = \false; } $keyPhpDocNode = $keyType->toPhpDocNode(); if (!$keyPhpDocNode instanceof ConstTypeNode) { continue; } $valueType = $this->valueTypes[$i]; /** @var ConstExprStringNode|ConstExprIntegerNode $keyNode */ $keyNode = $keyPhpDocNode->constExpr; if ($keyNode instanceof ConstExprStringNode) { $value = $keyNode->value; if (self::isValidIdentifier($value)) { $keyNode = new IdentifierTypeNode($value); } } $isOptional = $this->isOptionalKey($i); if ($isOptional) { $exportValuesOnly = \false; } $items[] = new ArrayShapeItemNode($keyNode, $isOptional, $valueType->toPhpDocNode()); $values[] = new ArrayShapeItemNode(null, $isOptional, $valueType->toPhpDocNode()); } return new ArrayShapeNode($exportValuesOnly ? $values : $items); } public static function isValidIdentifier(string $value) : bool { $result = Strings::match($value, '~^(?:[\\\\]?+[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF-]*+)++$~si'); return $result !== null; } public function getFiniteTypes() : array { $arraysArraysForCombinations = []; $count = 0; foreach ($this->getAllArrays() as $array) { $values = $array->getValueTypes(); $arraysForCombinations = []; $combinationCount = 1; foreach ($values as $valueType) { $finiteTypes = $valueType->getFiniteTypes(); if ($finiteTypes === []) { return []; } $arraysForCombinations[] = $finiteTypes; $combinationCount *= count($finiteTypes); } $arraysArraysForCombinations[] = $arraysForCombinations; $count += $combinationCount; } if ($count > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return []; } $finiteTypes = []; foreach ($arraysArraysForCombinations as $arraysForCombinations) { $combinations = CombinationsHelper::combinations($arraysForCombinations); foreach ($combinations as $combination) { $builder = \PHPStan\Type\Constant\ConstantArrayTypeBuilder::createEmpty(); foreach ($combination as $i => $v) { $builder->setOffsetValueType($this->keyTypes[$i], $v); } $finiteTypes[] = $builder->getArray(); } } return $finiteTypes; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['keyTypes'], $properties['valueTypes'], $properties['nextAutoIndexes'] ?? $properties['nextAutoIndex'], $properties['optionalKeys'] ?? [], $properties['isList'] ?? TrinaryLogic::createNo()); } } type = $type; $this->method = $method; $this->certainty = $certainty; } public static function createConcrete(Type $type, string $method, TrinaryLogic $certainty) : self { if ($certainty->no()) { throw new ShouldNotHappenException(); } return new self($type, $method, $certainty); } public static function createUnknown() : self { return new self(null, null, TrinaryLogic::createMaybe()); } public function isUnknown() : bool { return $this->type === null; } public function getType() : Type { if ($this->type === null) { throw new ShouldNotHappenException(); } return $this->type; } public function getMethod() : string { if ($this->method === null) { throw new ShouldNotHappenException(); } return $this->method; } public function getCertainty() : TrinaryLogic { return $this->certainty; } } */ private $keyTypes; /** * @var array */ private $valueTypes; /** * @var non-empty-list */ private $nextAutoIndexes; /** * @var array */ private $optionalKeys; /** * @var TrinaryLogic */ private $isList; public const ARRAY_COUNT_LIMIT = 256; /** * @var bool */ private $degradeToGeneralArray = \false; /** * @var bool */ private $oversized = \false; /** * @param array $keyTypes * @param array $valueTypes * @param non-empty-list $nextAutoIndexes * @param array $optionalKeys */ private function __construct(array $keyTypes, array $valueTypes, array $nextAutoIndexes, array $optionalKeys, TrinaryLogic $isList) { $this->keyTypes = $keyTypes; $this->valueTypes = $valueTypes; $this->nextAutoIndexes = $nextAutoIndexes; $this->optionalKeys = $optionalKeys; $this->isList = $isList; } public static function createEmpty() : self { return new self([], [], [0], [], TrinaryLogic::createYes()); } public static function createFromConstantArray(\PHPStan\Type\Constant\ConstantArrayType $startArrayType) : self { $builder = new self($startArrayType->getKeyTypes(), $startArrayType->getValueTypes(), $startArrayType->getNextAutoIndexes(), $startArrayType->getOptionalKeys(), $startArrayType->isList()); if (count($startArrayType->getKeyTypes()) > self::ARRAY_COUNT_LIMIT) { $builder->degradeToGeneralArray(\true); } return $builder; } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $optional = \false) : void { if ($offsetType !== null) { $offsetType = $offsetType->toArrayKey(); } if (!$this->degradeToGeneralArray) { if ($offsetType === null) { $newAutoIndexes = $optional ? $this->nextAutoIndexes : []; $hasOptional = \false; foreach ($this->keyTypes as $i => $keyType) { if (!$keyType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { continue; } if (!in_array($keyType->getValue(), $this->nextAutoIndexes, \true)) { continue; } $this->valueTypes[$i] = TypeCombinator::union($this->valueTypes[$i], $valueType); if (!$hasOptional && !$optional) { $this->optionalKeys = array_values(array_filter($this->optionalKeys, static function (int $index) use($i) : bool { return $index !== $i; })); } /** @var int|float $newAutoIndex */ $newAutoIndex = $keyType->getValue() + 1; if (is_float($newAutoIndex)) { $newAutoIndex = $keyType->getValue(); } $newAutoIndexes[] = $newAutoIndex; $hasOptional = \true; } $max = max($this->nextAutoIndexes); $this->keyTypes[] = new \PHPStan\Type\Constant\ConstantIntegerType($max); $this->valueTypes[] = $valueType; /** @var int|float $newAutoIndex */ $newAutoIndex = $max + 1; if (is_float($newAutoIndex)) { $newAutoIndex = $max; } $newAutoIndexes[] = $newAutoIndex; $this->nextAutoIndexes = array_values(array_unique($newAutoIndexes)); if ($optional || $hasOptional) { $this->optionalKeys[] = count($this->keyTypes) - 1; } if (count($this->keyTypes) > self::ARRAY_COUNT_LIMIT) { $this->degradeToGeneralArray = \true; $this->oversized = \true; } return; } if ($offsetType instanceof \PHPStan\Type\Constant\ConstantIntegerType || $offsetType instanceof \PHPStan\Type\Constant\ConstantStringType) { /** @var ConstantIntegerType|ConstantStringType $keyType */ foreach ($this->keyTypes as $i => $keyType) { if ($keyType->getValue() !== $offsetType->getValue()) { continue; } if ($optional) { $valueType = TypeCombinator::union($valueType, $this->valueTypes[$i]); } $this->valueTypes[$i] = $valueType; if (!$optional) { $this->optionalKeys = array_values(array_filter($this->optionalKeys, static function (int $index) use($i) : bool { return $index !== $i; })); if ($keyType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { $nextAutoIndexes = array_values(array_filter($this->nextAutoIndexes, static function (int $index) use($keyType) { return $index > $keyType->getValue(); })); if (count($nextAutoIndexes) === 0) { throw new ShouldNotHappenException(); } $this->nextAutoIndexes = $nextAutoIndexes; } } return; } $this->keyTypes[] = $offsetType; $this->valueTypes[] = $valueType; if ($offsetType instanceof \PHPStan\Type\Constant\ConstantIntegerType) { $min = min($this->nextAutoIndexes); $max = max($this->nextAutoIndexes); if ($offsetType->getValue() > $min) { if ($offsetType->getValue() <= $max) { $this->isList = $this->isList->and(TrinaryLogic::createMaybe()); } else { $this->isList = TrinaryLogic::createNo(); } } if ($offsetType->getValue() >= $max) { /** @var int|float $newAutoIndex */ $newAutoIndex = $offsetType->getValue() + 1; if (is_float($newAutoIndex)) { $newAutoIndex = $max; } if (!$optional) { $this->nextAutoIndexes = [$newAutoIndex]; } else { $this->nextAutoIndexes[] = $newAutoIndex; } } } else { $this->isList = TrinaryLogic::createNo(); } if ($optional) { $this->optionalKeys[] = count($this->keyTypes) - 1; } if (count($this->keyTypes) > self::ARRAY_COUNT_LIMIT) { $this->degradeToGeneralArray = \true; $this->oversized = \true; } return; } $scalarTypes = $offsetType->getConstantScalarTypes(); if (count($scalarTypes) === 0) { $integerRanges = TypeUtils::getIntegerRanges($offsetType); if (count($integerRanges) > 0) { foreach ($integerRanges as $integerRange) { if ($integerRange->getMin() === null) { break; } if ($integerRange->getMax() === null) { break; } $rangeLength = $integerRange->getMax() - $integerRange->getMin(); if ($rangeLength >= self::ARRAY_COUNT_LIMIT) { $scalarTypes = []; break; } foreach (range($integerRange->getMin(), $integerRange->getMax()) as $rangeValue) { $scalarTypes[] = new \PHPStan\Type\Constant\ConstantIntegerType($rangeValue); } } } } if (count($scalarTypes) > 0 && count($scalarTypes) < self::ARRAY_COUNT_LIMIT) { $match = \true; $valueTypes = $this->valueTypes; foreach ($scalarTypes as $scalarType) { $scalarOffsetType = $scalarType->toArrayKey(); if (!$scalarOffsetType instanceof \PHPStan\Type\Constant\ConstantIntegerType && !$scalarOffsetType instanceof \PHPStan\Type\Constant\ConstantStringType) { throw new ShouldNotHappenException(); } $offsetMatch = \false; /** @var ConstantIntegerType|ConstantStringType $keyType */ foreach ($this->keyTypes as $i => $keyType) { if ($keyType->getValue() !== $scalarOffsetType->getValue()) { continue; } $valueTypes[$i] = TypeCombinator::union($valueTypes[$i], $valueType); $offsetMatch = \true; } if ($offsetMatch) { continue; } $match = \false; } if ($match) { $this->valueTypes = $valueTypes; return; } } $this->isList = TrinaryLogic::createNo(); } if ($offsetType === null) { $offsetType = TypeCombinator::union(...array_map(static function (int $index) { return new \PHPStan\Type\Constant\ConstantIntegerType($index); }, $this->nextAutoIndexes)); } else { $this->isList = TrinaryLogic::createNo(); } $this->keyTypes[] = $offsetType; $this->valueTypes[] = $valueType; if ($optional) { $this->optionalKeys[] = count($this->keyTypes) - 1; } $this->degradeToGeneralArray = \true; } public function degradeToGeneralArray(bool $oversized = \false) : void { $this->degradeToGeneralArray = \true; $this->oversized = $this->oversized || $oversized; } public function getArray() : Type { $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { return new \PHPStan\Type\Constant\ConstantArrayType([], []); } if (!$this->degradeToGeneralArray) { /** @var array $keyTypes */ $keyTypes = $this->keyTypes; return new \PHPStan\Type\Constant\ConstantArrayType($keyTypes, $this->valueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList); } $array = new ArrayType(TypeCombinator::union(...$this->keyTypes), TypeCombinator::union(...$this->valueTypes)); if (count($this->optionalKeys) < $keyTypesCount) { $array = TypeCombinator::intersect($array, new NonEmptyArrayType()); } if ($this->oversized) { $array = TypeCombinator::intersect($array, new OversizedArrayType()); } if ($this->isList->yes()) { $array = AccessoryArrayListType::intersectWith($array); } return $array; } public function isList() : bool { return $this->isList->yes(); } } value = $value; } /** * @param self::* $value */ private static function create(int $value) : self { self::$registry[$value] = self::$registry[$value] ?? new self($value); return self::$registry[$value]; } /** @return self::* */ public function getLevelValue() : int { return $this->value; } /** @api */ public static function typeOnly() : self { return self::create(self::TYPE_ONLY); } /** @api */ public static function value() : self { return self::create(self::VALUE); } /** @api */ public static function precise() : self { return self::create(self::PRECISE); } /** @api */ public static function cache() : self { return self::create(self::CACHE); } public function isTypeOnly() : bool { return $this->value === self::TYPE_ONLY; } public function isValue() : bool { return $this->value === self::VALUE; } public function isPrecise() : bool { return $this->value === self::PRECISE; } /** @api */ public static function getRecommendedLevelByType(\PHPStan\Type\Type $acceptingType, ?\PHPStan\Type\Type $acceptedType = null) : self { $moreVerboseCallback = static function (\PHPStan\Type\Type $type, callable $traverse) use(&$moreVerbose, &$veryVerbose) : \PHPStan\Type\Type { if ($type->isCallable()->yes()) { $moreVerbose = \true; // Keep checking if we need to be very verbose. return $traverse($type); } if ($type->isConstantValue()->yes() && $type->isNull()->no()) { $moreVerbose = \true; // For ConstantArrayType we need to keep checking if we need to be very verbose. if (!$type->isArray()->no()) { return $traverse($type); } return $type; } if ($type instanceof AccessoryNonEmptyStringType || $type instanceof AccessoryNonFalsyStringType || $type instanceof AccessoryLiteralStringType || $type instanceof AccessoryNumericStringType || $type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) { $moreVerbose = \true; return $type; } if ($type instanceof AccessoryLowercaseStringType || $type instanceof AccessoryUppercaseStringType) { $moreVerbose = \true; $veryVerbose = \true; return $type; } if ($type instanceof \PHPStan\Type\IntegerRangeType) { $moreVerbose = \true; return $type; } return $traverse($type); }; /** @var bool $moreVerbose */ $moreVerbose = \false; /** @var bool $veryVerbose */ $veryVerbose = \false; \PHPStan\Type\TypeTraverser::map($acceptingType, $moreVerboseCallback); if ($veryVerbose) { return self::precise(); } if ($moreVerbose) { $verbosity = self::value(); } if ($acceptedType === null) { return $verbosity ?? self::typeOnly(); } $containsInvariantTemplateType = \false; \PHPStan\Type\TypeTraverser::map($acceptingType, static function (\PHPStan\Type\Type $type, callable $traverse) use(&$containsInvariantTemplateType) : \PHPStan\Type\Type { if ($type instanceof GenericObjectType || $type instanceof GenericStaticType) { $reflection = $type->getClassReflection(); if ($reflection !== null) { $templateTypeMap = $reflection->getTemplateTypeMap(); foreach ($templateTypeMap->getTypes() as $templateType) { if (!$templateType instanceof TemplateType) { continue; } if (!$templateType->getVariance()->invariant()) { continue; } $containsInvariantTemplateType = \true; return $type; } } } return $traverse($type); }); if (!$containsInvariantTemplateType) { return $verbosity ?? self::typeOnly(); } /** @var bool $moreVerbose */ $moreVerbose = \false; /** @var bool $veryVerbose */ $veryVerbose = \false; \PHPStan\Type\TypeTraverser::map($acceptedType, $moreVerboseCallback); if ($veryVerbose) { return self::precise(); } return $moreVerbose ? self::value() : $verbosity ?? self::typeOnly(); } /** * @param callable(): string $typeOnlyCallback * @param callable(): string $valueCallback * @param callable(): string|null $preciseCallback * @param callable(): string|null $cacheCallback */ public function handle(callable $typeOnlyCallback, callable $valueCallback, ?callable $preciseCallback = null, ?callable $cacheCallback = null) : string { if ($this->value === self::TYPE_ONLY) { return $typeOnlyCallback(); } if ($this->value === self::VALUE) { return $valueCallback(); } if ($this->value === self::PRECISE) { if ($preciseCallback !== null) { return $preciseCallback(); } return $valueCallback(); } if ($cacheCallback !== null) { return $cacheCallback(); } if ($preciseCallback !== null) { return $preciseCallback(); } return $valueCallback(); } } 1024) { return $types; } usort($types, static function (\PHPStan\Type\Type $a, \PHPStan\Type\Type $b) : int { if ($a instanceof \PHPStan\Type\NullType) { return 1; } elseif ($b instanceof \PHPStan\Type\NullType) { return -1; } if ($a instanceof AccessoryType) { if ($b instanceof AccessoryType) { return self::compareStrings($a->describe(\PHPStan\Type\VerbosityLevel::value()), $b->describe(\PHPStan\Type\VerbosityLevel::value())); } return 1; } if ($b instanceof AccessoryType) { return -1; } $aIsBool = $a instanceof ConstantBooleanType; $bIsBool = $b instanceof ConstantBooleanType; if ($aIsBool && !$bIsBool) { return 1; } elseif ($bIsBool && !$aIsBool) { return -1; } if ($a instanceof \PHPStan\Type\ConstantScalarType && !$b instanceof \PHPStan\Type\ConstantScalarType) { return -1; } elseif (!$a instanceof \PHPStan\Type\ConstantScalarType && $b instanceof \PHPStan\Type\ConstantScalarType) { return 1; } if (($a instanceof ConstantIntegerType || $a instanceof ConstantFloatType) && ($b instanceof ConstantIntegerType || $b instanceof ConstantFloatType)) { $cmp = $a->getValue() <=> $b->getValue(); if ($cmp !== 0) { return $cmp; } if ($a instanceof ConstantIntegerType && $b instanceof ConstantFloatType) { return -1; } if ($b instanceof ConstantIntegerType && $a instanceof ConstantFloatType) { return 1; } return 0; } if ($a instanceof \PHPStan\Type\IntegerRangeType && $b instanceof \PHPStan\Type\IntegerRangeType) { return ($a->getMin() ?? PHP_INT_MIN) <=> ($b->getMin() ?? PHP_INT_MIN); } if ($a instanceof \PHPStan\Type\IntegerRangeType && $b instanceof \PHPStan\Type\IntegerType) { return 1; } if ($b instanceof \PHPStan\Type\IntegerRangeType && $a instanceof \PHPStan\Type\IntegerType) { return -1; } if ($a instanceof ConstantStringType && $b instanceof ConstantStringType) { return self::compareStrings($a->getValue(), $b->getValue()); } if ($a->isConstantArray()->yes() && $b->isConstantArray()->yes()) { if ($a->isIterableAtLeastOnce()->no()) { if ($b->isIterableAtLeastOnce()->no()) { return 0; } return -1; } elseif ($b->isIterableAtLeastOnce()->no()) { return 1; } return self::compareStrings($a->describe(\PHPStan\Type\VerbosityLevel::value()), $b->describe(\PHPStan\Type\VerbosityLevel::value())); } if (($a instanceof \PHPStan\Type\CallableType || $a instanceof \PHPStan\Type\ClosureType) && ($b instanceof \PHPStan\Type\CallableType || $b instanceof \PHPStan\Type\ClosureType)) { return self::compareStrings($a->describe(\PHPStan\Type\VerbosityLevel::value()), $b->describe(\PHPStan\Type\VerbosityLevel::value())); } if ($a->isString()->yes() && $b->isString()->yes()) { return self::compareStrings($a->describe(\PHPStan\Type\VerbosityLevel::precise()), $b->describe(\PHPStan\Type\VerbosityLevel::precise())); } return self::compareStrings($a->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $b->describe(\PHPStan\Type\VerbosityLevel::typeOnly())); }); return $types; } private static function compareStrings(string $a, string $b) : int { $cmp = strcasecmp($a, $b); if ($cmp !== 0) { return $cmp; } return $a <=> $b; } } */ private $resolvedPhpDocBlockCache = []; /** * @var int */ private $resolvedPhpDocBlockCacheCount = 0; public function __construct(ReflectionProviderProvider $reflectionProviderProvider, Parser $phpParser, PhpDocStringResolver $phpDocStringResolver, PhpDocNodeResolver $phpDocNodeResolver, AnonymousClassNameHelper $anonymousClassNameHelper, FileHelper $fileHelper) { $this->reflectionProviderProvider = $reflectionProviderProvider; $this->phpParser = $phpParser; $this->phpDocStringResolver = $phpDocStringResolver; $this->phpDocNodeResolver = $phpDocNodeResolver; $this->anonymousClassNameHelper = $anonymousClassNameHelper; $this->fileHelper = $fileHelper; } /** @api */ public function getResolvedPhpDoc(?string $fileName, ?string $className, ?string $traitName, ?string $functionName, string $docComment) : ResolvedPhpDocBlock { if ($className === null && $traitName !== null) { throw new ShouldNotHappenException(); } if ($docComment === '') { return ResolvedPhpDocBlock::createEmpty(); } if ($fileName !== null) { $fileName = $this->fileHelper->normalizePath($fileName); } $nameScopeKey = $this->getNameScopeKey($fileName, $className, $traitName, $functionName); $phpDocKey = md5(sprintf('%s-%s', $nameScopeKey, $docComment)); if (isset($this->resolvedPhpDocBlockCache[$phpDocKey])) { return $this->resolvedPhpDocBlockCache[$phpDocKey]; } if ($fileName === null) { return $this->createResolvedPhpDocBlock($phpDocKey, new NameScope(null, []), $docComment, null); } try { $nameScope = $this->getNameScope($fileName, $className, $traitName, $functionName); } catch (NameScopeAlreadyBeingCreatedException $e) { return ResolvedPhpDocBlock::createEmpty(); } return $this->createResolvedPhpDocBlock($phpDocKey, $nameScope, $docComment, $fileName); } /** * @throws NameScopeAlreadyBeingCreatedException */ public function getNameScope(string $fileName, ?string $className, ?string $traitName, ?string $functionName) : NameScope { $nameScopeKey = $this->getNameScopeKey($fileName, $className, $traitName, $functionName); $nameScopeMap = []; if (!isset($this->inProcess[$fileName])) { $nameScopeMap = $this->getNameScopeMap($fileName); } if (isset($nameScopeMap[$nameScopeKey])) { return $nameScopeMap[$nameScopeKey]; } if (!isset($this->inProcess[$fileName][$nameScopeKey])) { // wrong $fileName due to traits throw new NameScopeAlreadyBeingCreatedException(); } if ($this->inProcess[$fileName][$nameScopeKey] === \true) { // PHPDoc has cyclic dependency throw new NameScopeAlreadyBeingCreatedException(); } if (is_callable($this->inProcess[$fileName][$nameScopeKey])) { $resolveCallback = $this->inProcess[$fileName][$nameScopeKey]; $this->inProcess[$fileName][$nameScopeKey] = \true; $this->inProcess[$fileName][$nameScopeKey] = $resolveCallback(); } return $this->inProcess[$fileName][$nameScopeKey]; } private function createResolvedPhpDocBlock(string $phpDocKey, NameScope $nameScope, string $phpDocString, ?string $fileName) : ResolvedPhpDocBlock { $phpDocNode = $this->phpDocStringResolver->resolve($phpDocString); if ($this->resolvedPhpDocBlockCacheCount >= 2048) { $this->resolvedPhpDocBlockCache = array_slice($this->resolvedPhpDocBlockCache, 1, null, \true); $this->resolvedPhpDocBlockCacheCount--; } $templateTypeMap = $nameScope->getTemplateTypeMap(); $phpDocTemplateTypes = []; $templateTags = $this->phpDocNodeResolver->resolveTemplateTags($phpDocNode, $nameScope); foreach (array_keys($templateTags) as $name) { $templateType = $templateTypeMap->getType($name); if ($templateType === null) { continue; } $phpDocTemplateTypes[$name] = $templateType; } $this->resolvedPhpDocBlockCache[$phpDocKey] = ResolvedPhpDocBlock::create($phpDocNode, $phpDocString, $fileName, $nameScope, new TemplateTypeMap($phpDocTemplateTypes), $templateTags, $this->phpDocNodeResolver, $this->reflectionProviderProvider->getReflectionProvider()); $this->resolvedPhpDocBlockCacheCount++; return $this->resolvedPhpDocBlockCache[$phpDocKey]; } /** * @return NameScope[] */ private function getNameScopeMap(string $fileName) : array { if (!isset($this->memoryCache[$fileName])) { $map = $this->createResolvedPhpDocMap($fileName); if ($this->memoryCacheCount >= 2048) { $this->memoryCache = array_slice($this->memoryCache, 1, null, \true); $this->memoryCacheCount--; } $this->memoryCache[$fileName] = $map; $this->memoryCacheCount++; } return $this->memoryCache[$fileName]; } /** * @return NameScope[] */ private function createResolvedPhpDocMap(string $fileName) : array { $phpDocNodeMap = $this->createPhpDocNodeMap($fileName, null, $fileName, [], $fileName); $nameScopeMap = $this->createNameScopeMap($fileName, null, null, [], $fileName, $phpDocNodeMap); $resolvedNameScopeMap = []; try { $this->inProcess[$fileName] = $nameScopeMap; foreach ($nameScopeMap as $nameScopeKey => $resolveCallback) { $this->inProcess[$fileName][$nameScopeKey] = \true; $this->inProcess[$fileName][$nameScopeKey] = $data = $resolveCallback(); $resolvedNameScopeMap[$nameScopeKey] = $data; } } finally { unset($this->inProcess[$fileName]); } return $resolvedNameScopeMap; } /** * @param array $traitMethodAliases * @return array */ private function createPhpDocNodeMap(string $fileName, ?string $lookForTrait, ?string $traitUseClass, array $traitMethodAliases, string $originalClassFileName) : array { /** @var array $phpDocNodeMap */ $phpDocNodeMap = []; /** @var string[] $classStack */ $classStack = []; if ($lookForTrait !== null && $traitUseClass !== null) { $classStack[] = $traitUseClass; } $namespace = null; $traitFound = \false; /** @var array $functionStack */ $functionStack = []; $this->processNodes($this->phpParser->parseFile($fileName), function (Node $node) use($fileName, $lookForTrait, &$traitFound, $traitMethodAliases, $originalClassFileName, &$phpDocNodeMap, &$classStack, &$namespace, &$functionStack) : ?int { if ($node instanceof Node\Stmt\ClassLike) { if ($traitFound && $fileName === $originalClassFileName) { return self::SKIP_NODE; } if ($lookForTrait !== null && !$traitFound) { if (!$node instanceof Node\Stmt\Trait_) { return self::SKIP_NODE; } if ((string) $node->namespacedName !== $lookForTrait) { return self::SKIP_NODE; } $traitFound = \true; $functionStack[] = null; } else { if ($node->name === null) { if (!$node instanceof Node\Stmt\Class_) { throw new ShouldNotHappenException(); } $className = $this->anonymousClassNameHelper->getAnonymousClassName($node, $fileName); } elseif ($node instanceof Node\Stmt\Class_ && $node->isAnonymous()) { $className = $node->name->name; } else { if ($traitFound) { return self::SKIP_NODE; } $className = ltrim(sprintf('%s\\%s', $namespace, $node->name->name), '\\'); } $classStack[] = $className; $functionStack[] = null; } } elseif ($node instanceof Node\Stmt\ClassMethod) { if (array_key_exists($node->name->name, $traitMethodAliases)) { $functionStack[] = $traitMethodAliases[$node->name->name]; } else { $functionStack[] = $node->name->name; } } elseif ($node instanceof Node\Stmt\Function_) { $functionStack[] = ltrim(sprintf('%s\\%s', $namespace, $node->name->name), '\\'); } $className = $classStack[count($classStack) - 1] ?? null; $functionName = $functionStack[count($functionStack) - 1] ?? null; if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) { $docComment = GetLastDocComment::forNode($node); if ($docComment !== null) { $nameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, $functionName); $phpDocNodeMap[$nameScopeKey] = $this->phpDocStringResolver->resolve($docComment); } return null; } if ($node instanceof Node\Stmt\Namespace_) { $namespace = $node->name !== null ? (string) $node->name : null; } elseif ($node instanceof Node\Stmt\TraitUse) { $traitMethodAliases = []; foreach ($node->adaptations as $traitUseAdaptation) { if (!$traitUseAdaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) { continue; } if ($traitUseAdaptation->newName === null) { continue; } $methodName = $traitUseAdaptation->method->toString(); $newTraitName = $traitUseAdaptation->newName->toString(); if ($traitUseAdaptation->trait === null) { foreach ($node->traits as $traitName) { $traitMethodAliases[$traitName->toString()][$methodName] = $newTraitName; } continue; } $traitMethodAliases[$traitUseAdaptation->trait->toString()][$methodName] = $newTraitName; } foreach ($node->traits as $traitName) { /** @var class-string $traitName */ $traitName = (string) $traitName; $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); if (!$reflectionProvider->hasClass($traitName)) { continue; } $traitReflection = $reflectionProvider->getClass($traitName); if (!$traitReflection->isTrait()) { continue; } if ($traitReflection->getFileName() === null) { continue; } if (!is_file($traitReflection->getFileName())) { continue; } $className = $classStack[count($classStack) - 1] ?? null; if ($className === null) { throw new ShouldNotHappenException(); } $phpDocNodeMap = array_merge($phpDocNodeMap, $this->createPhpDocNodeMap($traitReflection->getFileName(), $traitName, $className, $traitMethodAliases[$traitName] ?? [], $originalClassFileName)); } } return null; }, static function (Node $node) use(&$namespace, &$functionStack, &$classStack) : void { if ($node instanceof Node\Stmt\ClassLike) { if (count($classStack) === 0) { throw new ShouldNotHappenException(); } array_pop($classStack); if (count($functionStack) === 0) { throw new ShouldNotHappenException(); } array_pop($functionStack); } elseif ($node instanceof Node\Stmt\Namespace_) { $namespace = null; } elseif ($node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) { if (count($functionStack) === 0) { throw new ShouldNotHappenException(); } array_pop($functionStack); } }); return $phpDocNodeMap; } /** * @param array $traitMethodAliases * @param array $phpDocNodeMap * @return (callable(): NameScope)[] */ private function createNameScopeMap(string $fileName, ?string $lookForTrait, ?string $traitUseClass, array $traitMethodAliases, string $originalClassFileName, array $phpDocNodeMap) : array { /** @var (callable(): NameScope)[] $nameScopeMap */ $nameScopeMap = []; /** @var (callable(): TemplateTypeMap)[] $typeMapStack */ $typeMapStack = []; /** @var array> $typeAliasStack */ $typeAliasStack = []; /** @var string[] $classStack */ $classStack = []; if ($lookForTrait !== null && $traitUseClass !== null) { $classStack[] = $traitUseClass; $typeAliasStack[] = []; } $namespace = null; $traitFound = \false; /** @var array $functionStack */ $functionStack = []; $uses = []; $constUses = []; $this->processNodes($this->phpParser->parseFile($fileName), function (Node $node) use($fileName, $lookForTrait, $phpDocNodeMap, &$traitFound, $traitMethodAliases, $originalClassFileName, &$nameScopeMap, &$classStack, &$typeAliasStack, &$namespace, &$functionStack, &$uses, &$typeMapStack, &$constUses) : ?int { if ($node instanceof Node\Stmt\ClassLike) { if ($traitFound && $fileName === $originalClassFileName) { return self::SKIP_NODE; } if ($lookForTrait !== null && !$traitFound) { if (!$node instanceof Node\Stmt\Trait_) { return self::SKIP_NODE; } if ((string) $node->namespacedName !== $lookForTrait) { return self::SKIP_NODE; } $traitFound = \true; $traitNameScopeKey = $this->getNameScopeKey($originalClassFileName, $classStack[count($classStack) - 1] ?? null, $lookForTrait, null); if (array_key_exists($traitNameScopeKey, $phpDocNodeMap)) { $typeAliasStack[] = $this->getTypeAliasesMap($phpDocNodeMap[$traitNameScopeKey]); } else { $typeAliasStack[] = []; } $functionStack[] = null; } else { if ($node->name === null) { if (!$node instanceof Node\Stmt\Class_) { throw new ShouldNotHappenException(); } $className = $this->anonymousClassNameHelper->getAnonymousClassName($node, $fileName); } elseif ($node instanceof Node\Stmt\Class_ && $node->isAnonymous()) { $className = $node->name->name; } else { if ($traitFound) { return self::SKIP_NODE; } $className = ltrim(sprintf('%s\\%s', $namespace, $node->name->name), '\\'); } $classStack[] = $className; $classNameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, null); if (array_key_exists($classNameScopeKey, $phpDocNodeMap)) { $typeAliasStack[] = $this->getTypeAliasesMap($phpDocNodeMap[$classNameScopeKey]); } else { $typeAliasStack[] = []; } $functionStack[] = null; } } elseif ($node instanceof Node\Stmt\ClassMethod) { if (array_key_exists($node->name->name, $traitMethodAliases)) { $functionStack[] = $traitMethodAliases[$node->name->name]; } else { $functionStack[] = $node->name->name; } } elseif ($node instanceof Node\Stmt\Function_) { $functionStack[] = ltrim(sprintf('%s\\%s', $namespace, $node->name->name), '\\'); } $className = $classStack[count($classStack) - 1] ?? null; $functionName = $functionStack[count($functionStack) - 1] ?? null; $nameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, $functionName); if ($namespace === '') { throw new ShouldNotHappenException('Namespace cannot be empty.'); } if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) { if (array_key_exists($nameScopeKey, $phpDocNodeMap)) { $phpDocNode = $phpDocNodeMap[$nameScopeKey]; $typeMapStack[] = function () use($namespace, $uses, $className, $lookForTrait, $functionName, $phpDocNode, $typeMapStack, $typeAliasStack, $constUses) : TemplateTypeMap { $typeMapCb = $typeMapStack[count($typeMapStack) - 1] ?? null; $currentTypeMap = $typeMapCb !== null ? $typeMapCb() : null; $typeAliasesMap = $typeAliasStack[count($typeAliasStack) - 1] ?? []; $nameScope = new NameScope($namespace, $uses, $className, $functionName, $currentTypeMap, $typeAliasesMap, \false, $constUses, $lookForTrait); $templateTags = $this->phpDocNodeResolver->resolveTemplateTags($phpDocNode, $nameScope); $templateTypeScope = $nameScope->getTemplateTypeScope(); if ($templateTypeScope === null) { throw new ShouldNotHappenException(); } $templateTypeMap = new TemplateTypeMap(array_map(static function (TemplateTag $tag) use($templateTypeScope) : \PHPStan\Type\Type { return TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag); }, $templateTags)); $nameScope = $nameScope->withTemplateTypeMap($templateTypeMap); $templateTags = $this->phpDocNodeResolver->resolveTemplateTags($phpDocNode, $nameScope); $templateTypeMap = new TemplateTypeMap(array_map(static function (TemplateTag $tag) use($templateTypeScope) : \PHPStan\Type\Type { return TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag); }, $templateTags)); return new TemplateTypeMap(array_merge($currentTypeMap !== null ? $currentTypeMap->getTypes() : [], $templateTypeMap->getTypes())); }; } } $typeMapCb = $typeMapStack[count($typeMapStack) - 1] ?? null; $typeAliasesMap = $typeAliasStack[count($typeAliasStack) - 1] ?? []; if ($node instanceof Node\Stmt && !$node instanceof Node\Stmt\Namespace_ && !$node instanceof Node\Stmt\Declare_ && !$node instanceof Node\Stmt\DeclareDeclare && !$node instanceof Node\Stmt\Use_ && !$node instanceof Node\Stmt\UseUse && !$node instanceof Node\Stmt\GroupUse && !$node instanceof Node\Stmt\TraitUse && !$node instanceof Node\Stmt\TraitUseAdaptation && !$node instanceof Node\Stmt\InlineHTML && !($node instanceof Node\Stmt\Expression && $node->expr instanceof Node\Expr\Include_) && !array_key_exists($nameScopeKey, $nameScopeMap)) { $nameScopeMap[$nameScopeKey] = static function () use($namespace, $uses, $className, $functionName, $typeMapCb, $typeAliasesMap, $constUses, $lookForTrait) : NameScope { return new NameScope($namespace, $uses, $className, $functionName, $typeMapCb !== null ? $typeMapCb() : TemplateTypeMap::createEmpty(), $typeAliasesMap, \false, $constUses, $lookForTrait); }; } if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) { if (array_key_exists($nameScopeKey, $phpDocNodeMap)) { return self::POP_TYPE_MAP_STACK; } return null; } if ($node instanceof Node\Stmt\Namespace_) { $namespace = $node->name !== null ? (string) $node->name : null; } elseif ($node instanceof Node\Stmt\Use_) { if ($node->type === Node\Stmt\Use_::TYPE_NORMAL) { foreach ($node->uses as $use) { $uses[strtolower($use->getAlias()->name)] = (string) $use->name; } } elseif ($node->type === Node\Stmt\Use_::TYPE_CONSTANT) { foreach ($node->uses as $use) { $constUses[strtolower($use->getAlias()->name)] = (string) $use->name; } } } elseif ($node instanceof Node\Stmt\GroupUse) { $prefix = (string) $node->prefix; foreach ($node->uses as $use) { if ($node->type === Node\Stmt\Use_::TYPE_NORMAL || $use->type === Node\Stmt\Use_::TYPE_NORMAL) { $uses[strtolower($use->getAlias()->name)] = sprintf('%s\\%s', $prefix, (string) $use->name); } elseif ($node->type === Node\Stmt\Use_::TYPE_CONSTANT || $use->type === Node\Stmt\Use_::TYPE_CONSTANT) { $constUses[strtolower($use->getAlias()->name)] = sprintf('%s\\%s', $prefix, (string) $use->name); } } } elseif ($node instanceof Node\Stmt\TraitUse) { $traitMethodAliases = []; foreach ($node->adaptations as $traitUseAdaptation) { if (!$traitUseAdaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) { continue; } if ($traitUseAdaptation->newName === null) { continue; } $methodName = $traitUseAdaptation->method->toString(); $newTraitName = $traitUseAdaptation->newName->toString(); if ($traitUseAdaptation->trait === null) { foreach ($node->traits as $traitName) { $traitMethodAliases[$traitName->toString()][$methodName] = $newTraitName; } continue; } $traitMethodAliases[$traitUseAdaptation->trait->toString()][$methodName] = $newTraitName; } $useDocComment = null; if ($node->getDocComment() !== null) { $useDocComment = $node->getDocComment()->getText(); } foreach ($node->traits as $traitName) { /** @var class-string $traitName */ $traitName = (string) $traitName; $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); if (!$reflectionProvider->hasClass($traitName)) { continue; } $traitReflection = $reflectionProvider->getClass($traitName); if (!$traitReflection->isTrait()) { continue; } if ($traitReflection->getFileName() === null) { continue; } if (!is_file($traitReflection->getFileName())) { continue; } $className = $classStack[count($classStack) - 1] ?? null; if ($className === null) { throw new ShouldNotHappenException(); } $traitPhpDocMap = $this->createNameScopeMap($traitReflection->getFileName(), $traitName, $className, $traitMethodAliases[$traitName] ?? [], $originalClassFileName, $phpDocNodeMap); $finalTraitPhpDocMap = []; foreach ($traitPhpDocMap as $nameScopeTraitKey => $callback) { $finalTraitPhpDocMap[$nameScopeTraitKey] = function () use($callback, $traitReflection, $fileName, $className, $lookForTrait, $useDocComment) : NameScope { /** @var NameScope $original */ $original = $callback(); if (!$traitReflection->isGeneric()) { return $original; } $traitTemplateTypeMap = $traitReflection->getTemplateTypeMap(); $useType = null; if ($useDocComment !== null) { $useTags = $this->getResolvedPhpDoc($fileName, $className, $lookForTrait, null, $useDocComment)->getUsesTags(); foreach ($useTags as $useTag) { $useTagType = $useTag->getType(); if (!$useTagType instanceof GenericObjectType) { continue; } if ($useTagType->getClassName() !== $traitReflection->getName()) { continue; } $useType = $useTagType; break; } } if ($useType === null) { return $original->withTemplateTypeMap($traitTemplateTypeMap->resolveToBounds()); } $transformedTraitTypeMap = $traitReflection->typeMapFromList($useType->getTypes()); return $original->withTemplateTypeMap($traitTemplateTypeMap->map(static function (string $name, \PHPStan\Type\Type $type) use($transformedTraitTypeMap) : \PHPStan\Type\Type { return TemplateTypeHelper::resolveTemplateTypes($type, $transformedTraitTypeMap, TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createStatic()); })); }; } $nameScopeMap = array_merge($nameScopeMap, $finalTraitPhpDocMap); } } return null; }, static function (Node $node, $callbackResult) use(&$namespace, &$functionStack, &$classStack, &$typeAliasStack, &$uses, &$typeMapStack, &$constUses) : void { if ($node instanceof Node\Stmt\ClassLike) { if (count($classStack) === 0) { throw new ShouldNotHappenException(); } array_pop($classStack); if (count($typeAliasStack) === 0) { throw new ShouldNotHappenException(); } array_pop($typeAliasStack); if (count($functionStack) === 0) { throw new ShouldNotHappenException(); } array_pop($functionStack); } elseif ($node instanceof Node\Stmt\Namespace_) { $namespace = null; $uses = []; $constUses = []; } elseif ($node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) { if (count($functionStack) === 0) { throw new ShouldNotHappenException(); } array_pop($functionStack); } if ($callbackResult !== self::POP_TYPE_MAP_STACK) { return; } if (count($typeMapStack) === 0) { throw new ShouldNotHappenException(); } array_pop($typeMapStack); }); if (count($typeMapStack) > 0) { throw new ShouldNotHappenException(); } return $nameScopeMap; } /** * @return array */ private function getTypeAliasesMap(PhpDocNode $phpDocNode) : array { $nameScope = new NameScope(null, []); $aliasesMap = []; foreach (array_keys($this->phpDocNodeResolver->resolveTypeAliasImportTags($phpDocNode, $nameScope)) as $key) { $aliasesMap[$key] = \true; } foreach (array_keys($this->phpDocNodeResolver->resolveTypeAliasTags($phpDocNode, $nameScope)) as $key) { $aliasesMap[$key] = \true; } return $aliasesMap; } /** * @param Node[]|Node|scalar|null $node * @param Closure(Node $node): mixed $nodeCallback * @param Closure(Node $node, mixed $callbackResult): void $endNodeCallback */ private function processNodes($node, Closure $nodeCallback, Closure $endNodeCallback) : void { if ($node instanceof Node) { $callbackResult = $nodeCallback($node); if ($callbackResult === self::SKIP_NODE) { return; } foreach ($node->getSubNodeNames() as $subNodeName) { $subNode = $node->{$subNodeName}; $this->processNodes($subNode, $nodeCallback, $endNodeCallback); } $endNodeCallback($node, $callbackResult); } elseif (is_array($node)) { foreach ($node as $subNode) { $this->processNodes($subNode, $nodeCallback, $endNodeCallback); } } } private function getNameScopeKey(?string $file, ?string $class, ?string $trait, ?string $function) : string { if ($class === null && $trait === null && $function === null) { return md5(sprintf('%s', $file ?? 'no-file')); } if ($class !== null && str_contains($class, 'class@anonymous')) { throw new ShouldNotHappenException('Wrong anonymous class name, FilTypeMapper should be called with ClassReflection::getName().'); } return md5(sprintf('%s-%s-%s-%s', $file ?? 'no-file', $class, $trait, $function)); } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new \PHPStan\Type\AcceptsResult($type->isClassStringType(), []); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return new \PHPStan\Type\IsSuperTypeOfResult($type->isClassStringType(), []); } public function isString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createYes(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ObjectWithoutClassType(); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('class-string'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self(); } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof self || $type->isInteger()->yes()) { return \PHPStan\Type\AcceptsResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type) : bool { return get_class($type) === static::class; } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return 'float'; } public function toNumber() : \PHPStan\Type\Type { return $this; } public function toAbsoluteNumber() : \PHPStan\Type\Type { return $this; } public function toFloat() : \PHPStan\Type\Type { return $this; } public function toInteger() : \PHPStan\Type\Type { return new \PHPStan\Type\IntegerType(); } public function toString() : \PHPStan\Type\Type { return new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryUppercaseStringType(), new AccessoryNumericStringType()]); } public function toArray() : \PHPStan\Type\Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : \PHPStan\Type\Type { return new \PHPStan\Type\IntegerType(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function traverse(callable $cb) : \PHPStan\Type\Type { return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { return $this; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return \PHPStan\Type\ExponentiateHelper::exponentiate($this, $exponent); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('float'); } public function getFiniteTypes() : array { return []; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self(); } } reflectionProvider = $reflectionProvider; } /** * @param non-empty-string $constName */ public function bitwiseOrContainsConstant(Expr $expr, Scope $scope, string $constName) : TrinaryLogic { if ($expr instanceof ConstFetch) { if ((string) $expr->name === $constName) { return TrinaryLogic::createYes(); } $resolveConstantName = $this->reflectionProvider->resolveConstantName($expr->name, $scope); if ($resolveConstantName !== null) { if ($resolveConstantName === $constName) { return TrinaryLogic::createYes(); } return TrinaryLogic::createNo(); } } if ($expr instanceof BitwiseOr) { return TrinaryLogic::createFromBoolean($this->bitwiseOrContainsConstant($expr->left, $scope, $constName)->yes() || $this->bitwiseOrContainsConstant($expr->right, $scope, $constName)->yes()); } $fqcn = new FullyQualified($constName); if ($this->reflectionProvider->hasConstant($fqcn, $scope)) { $constant = $this->reflectionProvider->getConstant($fqcn, $scope); $valueType = $constant->getValueType(); if ($valueType instanceof ConstantIntegerType) { return $this->exprContainsIntFlag($expr, $scope, $valueType->getValue()); } } return TrinaryLogic::createNo(); } private function exprContainsIntFlag(Expr $expr, Scope $scope, int $flag) : TrinaryLogic { $exprType = $scope->getType($expr); if ($exprType instanceof \PHPStan\Type\UnionType) { $allTypesContainFlag = \true; $someTypesContainFlag = \false; foreach ($exprType->getTypes() as $type) { $containsFlag = $this->typeContainsIntFlag($type, $flag); if (!$containsFlag->yes()) { $allTypesContainFlag = \false; } if (!$containsFlag->yes() && !$containsFlag->maybe()) { continue; } $someTypesContainFlag = \true; } if ($allTypesContainFlag) { return TrinaryLogic::createYes(); } if ($someTypesContainFlag) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); } return $this->typeContainsIntFlag($exprType, $flag); } private function typeContainsIntFlag(\PHPStan\Type\Type $type, int $flag) : TrinaryLogic { if ($type instanceof ConstantIntegerType) { if (($type->getValue() & $flag) === $flag) { return TrinaryLogic::createYes(); } return TrinaryLogic::createNo(); } if ($type->isInteger()->yes() || $type instanceof \PHPStan\Type\MixedType) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); } } type = $type; } public function getType() : \PHPStan\Type\Type { return $this->type; } public function getReferencedClasses() : array { return $this->type->getReferencedClasses(); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { return $this->type->getReferencedTemplateTypes($positionVariance); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self && $this->type->equals($type->type); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return sprintf('key-of<%s>', $this->type->describe($level)); } public function isResolvable() : bool { return !\PHPStan\Type\TypeUtils::containsTemplateType($this->type); } protected function getResult() : \PHPStan\Type\Type { return $this->type->getIterableKeyType(); } /** * @param callable(Type): Type $cb */ public function traverse(callable $cb) : \PHPStan\Type\Type { $type = $cb($this->type); if ($this->type === $type) { return $this; } return new self($type); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if (!$right instanceof self) { return $this; } $type = $cb($this->type, $right->type); if ($this->type === $type) { return $this; } return new self($type); } public function toPhpDocNode() : TypeNode { return new GenericTypeNode(new IdentifierTypeNode('key-of'), [$this->type->toPhpDocNode()]); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['type']); } } container = $container; } public function getTypeAliasResolver() : \PHPStan\Type\TypeAliasResolver { return $this->container->getByType(\PHPStan\Type\TypeAliasResolver::class); } } typeNode = $typeNode; $this->nameScope = $nameScope; } public static function invalid() : self { $self = new self(new IdentifierTypeNode('*ERROR*'), new NameScope(null, [])); $self->resolvedType = new \PHPStan\Type\CircularTypeAliasErrorType(); return $self; } public function resolve(TypeNodeResolver $typeNodeResolver) : \PHPStan\Type\Type { if ($this->resolvedType === null) { $this->resolvedType = $typeNodeResolver->resolve($this->typeNode, $this->nameScope); } return $this->resolvedType; } } getMin(); $removeValueMax = $typeToRemove->getMax(); } else { $removeValueMin = $typeToRemove->getValue(); $removeValueMax = $typeToRemove->getValue(); } $lowerPart = $removeValueMin !== null ? \PHPStan\Type\IntegerRangeType::fromInterval(null, $removeValueMin, -1) : null; $upperPart = $removeValueMax !== null ? \PHPStan\Type\IntegerRangeType::fromInterval($removeValueMax, null, +1) : null; if ($lowerPart !== null && $upperPart !== null) { return new \PHPStan\Type\UnionType([$lowerPart, $upperPart]); } return $lowerPart ?? $upperPart ?? new \PHPStan\Type\NeverType(); } return null; } public function getFiniteTypes() : array { return []; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return \PHPStan\Type\ExponentiateHelper::exponentiate($this, $exponent); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('int'); } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof self) { return \PHPStan\Type\AcceptsResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self; } public function isSmallerThan(\PHPStan\Type\Type $otherType) : TrinaryLogic { if ($otherType instanceof \PHPStan\Type\ConstantScalarType) { return TrinaryLogic::createFromBoolean(null < $otherType->getValue()); } if ($otherType instanceof \PHPStan\Type\CompoundType) { return $otherType->isGreaterThan($this); } return TrinaryLogic::createMaybe(); } public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType) : TrinaryLogic { if ($otherType instanceof \PHPStan\Type\ConstantScalarType) { return TrinaryLogic::createFromBoolean(null <= $otherType->getValue()); } if ($otherType instanceof \PHPStan\Type\CompoundType) { return $otherType->isGreaterThanOrEqual($this); } return TrinaryLogic::createMaybe(); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return 'null'; } public function toNumber() : \PHPStan\Type\Type { return new ConstantIntegerType(0); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return $this->toNumber()->toAbsoluteNumber(); } public function toString() : \PHPStan\Type\Type { return new ConstantStringType(''); } public function toInteger() : \PHPStan\Type\Type { return $this->toNumber(); } public function toFloat() : \PHPStan\Type\Type { return $this->toNumber()->toFloat(); } public function toArray() : \PHPStan\Type\Type { return new ConstantArrayType([], []); } public function toArrayKey() : \PHPStan\Type\Type { return new ConstantStringType(''); } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { return TrinaryLogic::createNo(); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { $array = new ConstantArrayType([], []); return $array->setOffsetValueType($offsetType, $valueType, $unionValues); } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return $this; } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return $this; } public function traverse(callable $cb) : \PHPStan\Type\Type { return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createYes(); } public function getConstantScalarTypes() : array { return [$this]; } public function getConstantScalarValues() : array { return [$this->getValue()]; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { if ($type instanceof \PHPStan\Type\ConstantScalarType) { return \PHPStan\Type\LooseComparisonHelper::compareConstantScalars($this, $type, $phpVersion); } if ($type->isConstantArray()->yes() && $type->isIterableAtLeastOnce()->no()) { // @phpstan-ignore equal.alwaysTrue, equal.notAllowed return new ConstantBooleanType($this->getValue() == []); // phpcs:ignore } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->looseCompare($this, $phpVersion); } return new \PHPStan\Type\BooleanType(); } public function getSmallerType() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getSmallerOrEqualType() : \PHPStan\Type\Type { // All falsey types except '0' return new \PHPStan\Type\UnionType([new \PHPStan\Type\NullType(), new ConstantBooleanType(\false), new ConstantIntegerType(0), new ConstantFloatType(0.0), new ConstantStringType(''), new ConstantArrayType([], [])]); } public function getGreaterType() : \PHPStan\Type\Type { // All truthy types, but also '0' return new \PHPStan\Type\MixedType(\false, new \PHPStan\Type\UnionType([new \PHPStan\Type\NullType(), new ConstantBooleanType(\false), new ConstantIntegerType(0), new ConstantFloatType(0.0), new ConstantStringType(''), new ConstantArrayType([], [])])); } public function getGreaterOrEqualType() : \PHPStan\Type\Type { return new \PHPStan\Type\MixedType(); } public function getFiniteTypes() : array { return [$this]; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return new \PHPStan\Type\UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('null'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self(); } } enumCaseName = $enumCaseName; parent::__construct($className, null, $classReflection); } public function getEnumCaseName() : string { return $this->enumCaseName; } public function describe(VerbosityLevel $level) : string { $parent = parent::describe($level); return sprintf('%s::%s', $parent, $this->enumCaseName); } public function equals(Type $type) : bool { if (!$type instanceof self) { return \false; } return $this->enumCaseName === $type->enumCaseName && $this->getClassName() === $type->getClassName(); } public function accepts(Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { return $this->isSuperTypeOfWithReason($type)->toAcceptsResult(); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createFromBoolean($this->enumCaseName === $type->enumCaseName && $this->getClassName() === $type->getClassName()); } if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($type instanceof SubtractableType && $type->getSubtractedType() !== null) { $isSuperType = $type->getSubtractedType()->isSuperTypeOfWithReason($this); if ($isSuperType->yes()) { return IsSuperTypeOfResult::createNo(); } } $parent = new parent($this->getClassName(), $this->getSubtractedType(), $this->getClassReflection()); return $parent->isSuperTypeOfWithReason($type)->and(IsSuperTypeOfResult::createMaybe()); } public function subtract(Type $type) : Type { return $this; } public function getTypeWithoutSubtractedType() : Type { return $this; } public function changeSubtractedType(?Type $subtractedType) : Type { return $this; } public function getSubtractedType() : ?Type { return null; } public function tryRemove(Type $typeToRemove) : ?Type { if ($this->isSuperTypeOf($typeToRemove)->yes()) { return $this->subtract($typeToRemove); } return null; } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return parent::getUnresolvedPropertyPrototype($propertyName, $scope); } if ($propertyName === 'name') { return new EnumUnresolvedPropertyPrototypeReflection(new EnumPropertyReflection($classReflection, new ConstantStringType($this->enumCaseName))); } if ($classReflection->isBackedEnum() && $propertyName === 'value') { if ($classReflection->hasEnumCase($this->enumCaseName)) { $enumCase = $classReflection->getEnumCase($this->enumCaseName); $valueType = $enumCase->getBackingValueType(); if ($valueType === null) { throw new ShouldNotHappenException(); } return new EnumUnresolvedPropertyPrototypeReflection(new EnumPropertyReflection($classReflection, $valueType)); } } return parent::getUnresolvedPropertyPrototype($propertyName, $scope); } public function getBackingValueType() : ?Type { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return null; } if (!$classReflection->isBackedEnum()) { return null; } if ($classReflection->hasEnumCase($this->enumCaseName)) { $enumCase = $classReflection->getEnumCase($this->enumCaseName); return $enumCase->getBackingValueType(); } return null; } public function generalize(GeneralizePrecision $precision) : Type { return new parent($this->getClassName(), null, $this->getClassReflection()); } public function isSmallerThan(Type $otherType) : TrinaryLogic { return TrinaryLogic::createNo(); } public function isSmallerThanOrEqual(Type $otherType) : TrinaryLogic { return TrinaryLogic::createNo(); } public function getEnumCases() : array { return [$this]; } public function toPhpDocNode() : TypeNode { return new ConstTypeNode(new ConstFetchNode($this->getClassName(), $this->getEnumCaseName())); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['className'], $properties['enumCaseName'], null); } } getTypes() as $unionType) { $results[] = self::exponentiate($base, $unionType); } return \PHPStan\Type\TypeCombinator::union(...$results); } if ($exponent instanceof \PHPStan\Type\NeverType) { return new \PHPStan\Type\NeverType(); } $allowedExponentTypes = new \PHPStan\Type\UnionType([new \PHPStan\Type\IntegerType(), new \PHPStan\Type\FloatType(), new \PHPStan\Type\StringType(), new \PHPStan\Type\BooleanType(), new \PHPStan\Type\NullType()]); if (!$allowedExponentTypes->isSuperTypeOf($exponent)->yes()) { return new \PHPStan\Type\ErrorType(); } if ($base instanceof \PHPStan\Type\ConstantScalarType) { $result = self::exponentiateConstantScalar($base, $exponent); if ($result !== null) { return $result; } } // exponentiation of a float, stays a float $isFloatBase = $base->isFloat()->yes(); $isLooseZero = (new ConstantIntegerType(0))->isSuperTypeOf($exponent->toNumber()); if ($isLooseZero->yes()) { if ($isFloatBase) { return new ConstantFloatType(1); } return new ConstantIntegerType(1); } $isLooseOne = (new ConstantIntegerType(1))->isSuperTypeOf($exponent->toNumber()); if ($isLooseOne->yes()) { $possibleResults = new \PHPStan\Type\UnionType([new \PHPStan\Type\FloatType(), new \PHPStan\Type\IntegerType()]); if ($possibleResults->isSuperTypeOf($base)->yes()) { return $base; } } if ($isFloatBase) { return new \PHPStan\Type\FloatType(); } return new \PHPStan\Type\BenevolentUnionType([new \PHPStan\Type\FloatType(), new \PHPStan\Type\IntegerType()]); } private static function exponentiateConstantScalar(\PHPStan\Type\ConstantScalarType $base, \PHPStan\Type\Type $exponent) : ?\PHPStan\Type\Type { if ($exponent instanceof \PHPStan\Type\IntegerRangeType) { $min = null; $max = null; if ($exponent->getMin() !== null) { $min = self::pow($base->getValue(), $exponent->getMin()); if ($min === null) { return new \PHPStan\Type\ErrorType(); } } if ($exponent->getMax() !== null) { $max = self::pow($base->getValue(), $exponent->getMax()); if ($max === null) { return new \PHPStan\Type\ErrorType(); } } if (!is_float($min) && !is_float($max)) { return \PHPStan\Type\IntegerRangeType::fromInterval($min, $max); } } if ($exponent instanceof \PHPStan\Type\ConstantScalarType) { $result = self::pow($base->getValue(), $exponent->getValue()); if ($result === null) { return new \PHPStan\Type\ErrorType(); } if (is_int($result)) { return new ConstantIntegerType($result); } return new ConstantFloatType($result); } return null; } /** * @return float|int|null * @param mixed $base * @param mixed $exp */ private static function pow($base, $exp) { if (is_string($base) && !is_numeric($base)) { return null; } if (is_string($exp) && !is_numeric($exp)) { return null; } return pow($base, $exp); } } typeAliasResolver = $typeAliasResolver; } public function getTypeAliasResolver() : \PHPStan\Type\TypeAliasResolver { return $this->typeAliasResolver; } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof static) { return \PHPStan\Type\AcceptsResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return \PHPStan\Type\AcceptsResult::createNo(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type) : bool { return get_class($type) === static::class; } public function traverse(callable $cb) : \PHPStan\Type\Type { return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } } *@readonly */ public $reasons; /** * @param T $type * @param list $reasons */ public function __construct(\PHPStan\Type\Type $type, array $reasons) { $this->type = $type; $this->reasons = $reasons; } } value = $value; } private static function create(int $value) : self { self::$registry[$value] = self::$registry[$value] ?? new self($value); return self::$registry[$value]; } /** @api */ public static function lessSpecific() : self { return self::create(self::LESS_SPECIFIC); } /** @api */ public static function moreSpecific() : self { return self::create(self::MORE_SPECIFIC); } /** @api */ public static function templateArgument() : self { return self::create(self::TEMPLATE_ARGUMENT); } public function isLessSpecific() : bool { return $this->value === self::LESS_SPECIFIC; } public function isMoreSpecific() : bool { return $this->value === self::MORE_SPECIFIC; } public function isTemplateArgument() : bool { return $this->value === self::TEMPLATE_ARGUMENT; } } isSuperTypeOf($type)->no()) { return self::union($type, $nullType); } return $type; } public static function remove(\PHPStan\Type\Type $fromType, \PHPStan\Type\Type $typeToRemove) : \PHPStan\Type\Type { if ($typeToRemove instanceof \PHPStan\Type\UnionType) { foreach ($typeToRemove->getTypes() as $unionTypeToRemove) { $fromType = self::remove($fromType, $unionTypeToRemove); } return $fromType; } $isSuperType = $typeToRemove->isSuperTypeOf($fromType); if ($isSuperType->yes()) { return new \PHPStan\Type\NeverType(); } if ($isSuperType->no()) { return $fromType; } if ($typeToRemove instanceof \PHPStan\Type\MixedType) { $typeToRemoveSubtractedType = $typeToRemove->getSubtractedType(); if ($typeToRemoveSubtractedType !== null) { return self::intersect($fromType, $typeToRemoveSubtractedType); } } $removed = $fromType->tryRemove($typeToRemove); if ($removed !== null) { return $removed; } $fromFiniteTypes = $fromType->getFiniteTypes(); if (count($fromFiniteTypes) > 0) { $finiteTypesToRemove = $typeToRemove->getFiniteTypes(); if (count($finiteTypesToRemove) === 1) { $result = []; foreach ($fromFiniteTypes as $finiteType) { if ($finiteType->equals($finiteTypesToRemove[0])) { continue; } $result[] = $finiteType; } if (count($result) === count($fromFiniteTypes)) { return $fromType; } if (count($result) === 0) { return new \PHPStan\Type\NeverType(); } if (count($result) === 1) { return $result[0]; } return new \PHPStan\Type\UnionType($result); } } return $fromType; } public static function removeNull(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { if (self::containsNull($type)) { return self::remove($type, new \PHPStan\Type\NullType()); } return $type; } public static function containsNull(\PHPStan\Type\Type $type) : bool { if ($type instanceof \PHPStan\Type\UnionType) { foreach ($type->getTypes() as $innerType) { if ($innerType instanceof \PHPStan\Type\NullType) { return \true; } } return \false; } return $type instanceof \PHPStan\Type\NullType; } public static function union(\PHPStan\Type\Type ...$types) : \PHPStan\Type\Type { $typesCount = count($types); if ($typesCount === 0) { return new \PHPStan\Type\NeverType(); } $benevolentTypes = []; $benevolentUnionObject = null; // transform A | (B | C) to A | B | C for ($i = 0; $i < $typesCount; $i++) { if ($types[$i] instanceof \PHPStan\Type\BenevolentUnionType) { if ($types[$i] instanceof TemplateBenevolentUnionType && $benevolentUnionObject === null) { $benevolentUnionObject = $types[$i]; } $benevolentTypesCount = 0; $typesInner = $types[$i]->getTypes(); foreach ($typesInner as $benevolentInnerType) { $benevolentTypesCount++; $benevolentTypes[$benevolentInnerType->describe(\PHPStan\Type\VerbosityLevel::value())] = $benevolentInnerType; } array_splice($types, $i, 1, $typesInner); $typesCount += $benevolentTypesCount - 1; continue; } if (!$types[$i] instanceof \PHPStan\Type\UnionType) { continue; } if ($types[$i] instanceof TemplateType) { continue; } $typesInner = $types[$i]->getTypes(); array_splice($types, $i, 1, $typesInner); $typesCount += count($typesInner) - 1; } if ($typesCount === 1) { return $types[0]; } $arrayTypes = []; $scalarTypes = []; $hasGenericScalarTypes = []; $enumCaseTypes = []; for ($i = 0; $i < $typesCount; $i++) { if ($types[$i] instanceof \PHPStan\Type\ConstantScalarType) { $type = $types[$i]; $scalarTypes[get_class($type)][md5($type->describe(\PHPStan\Type\VerbosityLevel::cache()))] = $type; unset($types[$i]); continue; } if ($types[$i] instanceof \PHPStan\Type\BooleanType) { $hasGenericScalarTypes[ConstantBooleanType::class] = \true; } if ($types[$i] instanceof \PHPStan\Type\FloatType) { $hasGenericScalarTypes[ConstantFloatType::class] = \true; } if ($types[$i] instanceof \PHPStan\Type\IntegerType && !$types[$i] instanceof \PHPStan\Type\IntegerRangeType) { $hasGenericScalarTypes[ConstantIntegerType::class] = \true; } if ($types[$i] instanceof \PHPStan\Type\StringType && !$types[$i] instanceof \PHPStan\Type\ClassStringType) { $hasGenericScalarTypes[ConstantStringType::class] = \true; } $enumCases = $types[$i]->getEnumCases(); if (count($enumCases) === 1) { $enumCaseTypes[$types[$i]->describe(\PHPStan\Type\VerbosityLevel::cache())] = $types[$i]; unset($types[$i]); continue; } if (!$types[$i]->isArray()->yes()) { continue; } $arrayTypes[] = $types[$i]; unset($types[$i]); } foreach ($scalarTypes as $classType => $scalarTypeItems) { $scalarTypes[$classType] = array_values($scalarTypeItems); } $enumCaseTypes = array_values($enumCaseTypes); $types = array_values($types); $typesCount = count($types); foreach ($scalarTypes as $classType => $scalarTypeItems) { if (isset($hasGenericScalarTypes[$classType])) { unset($scalarTypes[$classType]); continue; } if ($classType === ConstantBooleanType::class && count($scalarTypeItems) === 2) { $types[] = new \PHPStan\Type\BooleanType(); $typesCount++; unset($scalarTypes[$classType]); continue; } $scalarTypeItemsCount = count($scalarTypeItems); for ($i = 0; $i < $typesCount; $i++) { for ($j = 0; $j < $scalarTypeItemsCount; $j++) { $compareResult = self::compareTypesInUnion($types[$i], $scalarTypeItems[$j]); if ($compareResult === null) { continue; } [$a, $b] = $compareResult; if ($a !== null) { $types[$i] = $a; array_splice($scalarTypeItems, $j--, 1); $scalarTypeItemsCount--; continue 1; } if ($b !== null) { $scalarTypeItems[$j] = $b; array_splice($types, $i--, 1); $typesCount--; continue 2; } } } $scalarTypes[$classType] = $scalarTypeItems; } if (count($types) > 16) { $newTypes = []; foreach ($types as $type) { $newTypes[$type->describe(\PHPStan\Type\VerbosityLevel::cache())] = $type; } $types = array_values($newTypes); } $types = array_merge($types, self::processArrayTypes($arrayTypes)); $typesCount = count($types); // transform A | A to A // transform A | never to A for ($i = 0; $i < $typesCount; $i++) { for ($j = $i + 1; $j < $typesCount; $j++) { $compareResult = self::compareTypesInUnion($types[$i], $types[$j]); if ($compareResult === null) { continue; } [$a, $b] = $compareResult; if ($a !== null) { $types[$i] = $a; array_splice($types, $j--, 1); $typesCount--; continue 1; } if ($b !== null) { $types[$j] = $b; array_splice($types, $i--, 1); $typesCount--; continue 2; } } } $enumCasesCount = count($enumCaseTypes); for ($i = 0; $i < $typesCount; $i++) { for ($j = 0; $j < $enumCasesCount; $j++) { $compareResult = self::compareTypesInUnion($types[$i], $enumCaseTypes[$j]); if ($compareResult === null) { continue; } [$a, $b] = $compareResult; if ($a !== null) { $types[$i] = $a; array_splice($enumCaseTypes, $j--, 1); $enumCasesCount--; continue 1; } if ($b !== null) { $enumCaseTypes[$j] = $b; array_splice($types, $i--, 1); $typesCount--; continue 2; } } } foreach ($enumCaseTypes as $enumCaseType) { $types[] = $enumCaseType; $typesCount++; } foreach ($scalarTypes as $scalarTypeItems) { foreach ($scalarTypeItems as $scalarType) { $types[] = $scalarType; $typesCount++; } } if ($typesCount === 0) { return new \PHPStan\Type\NeverType(); } if ($typesCount === 1) { return $types[0]; } if ($benevolentTypes !== []) { $tempTypes = $types; foreach ($tempTypes as $i => $type) { if (!isset($benevolentTypes[$type->describe(\PHPStan\Type\VerbosityLevel::value())])) { break; } unset($tempTypes[$i]); } if ($tempTypes === []) { if ($benevolentUnionObject instanceof TemplateBenevolentUnionType) { return $benevolentUnionObject->withTypes($types); } return new \PHPStan\Type\BenevolentUnionType($types, \true); } } return new \PHPStan\Type\UnionType($types, \true); } /** * @return array{Type, null}|array{null, Type}|null */ private static function compareTypesInUnion(\PHPStan\Type\Type $a, \PHPStan\Type\Type $b) : ?array { if ($a instanceof \PHPStan\Type\IntegerRangeType) { $type = $a->tryUnion($b); if ($type !== null) { $a = $type; return [$a, null]; } } if ($b instanceof \PHPStan\Type\IntegerRangeType) { $type = $b->tryUnion($a); if ($type !== null) { $b = $type; return [null, $b]; } } if ($a instanceof \PHPStan\Type\IntegerRangeType && $b instanceof \PHPStan\Type\IntegerRangeType) { return null; } if ($a instanceof HasOffsetValueType && $b instanceof HasOffsetValueType) { if ($a->getOffsetType()->equals($b->getOffsetType())) { return [new HasOffsetValueType($a->getOffsetType(), self::union($a->getValueType(), $b->getValueType())), null]; } } if ($a->isConstantArray()->yes() && $b->isConstantArray()->yes()) { return null; } // simplify string[] | int[] to (string|int)[] if ($a instanceof \PHPStan\Type\IterableType && $b instanceof \PHPStan\Type\IterableType) { return [new \PHPStan\Type\IterableType(self::union($a->getIterableKeyType(), $b->getIterableKeyType()), self::union($a->getIterableValueType(), $b->getIterableValueType())), null]; } if ($a instanceof \PHPStan\Type\SubtractableType) { $typeWithoutSubtractedTypeA = $a->getTypeWithoutSubtractedType(); if ($typeWithoutSubtractedTypeA instanceof \PHPStan\Type\MixedType && $b instanceof \PHPStan\Type\MixedType) { $isSuperType = $typeWithoutSubtractedTypeA->isSuperTypeOfMixed($b); } else { $isSuperType = $typeWithoutSubtractedTypeA->isSuperTypeOf($b); } if ($isSuperType->yes()) { $a = self::intersectWithSubtractedType($a, $b); return [$a, null]; } } if ($b instanceof \PHPStan\Type\SubtractableType) { $typeWithoutSubtractedTypeB = $b->getTypeWithoutSubtractedType(); if ($typeWithoutSubtractedTypeB instanceof \PHPStan\Type\MixedType && $a instanceof \PHPStan\Type\MixedType) { $isSuperType = $typeWithoutSubtractedTypeB->isSuperTypeOfMixed($a); } else { $isSuperType = $typeWithoutSubtractedTypeB->isSuperTypeOf($a); } if ($isSuperType->yes()) { $b = self::intersectWithSubtractedType($b, $a); return [null, $b]; } } if ($b->isSuperTypeOf($a)->yes()) { return [null, $b]; } if ($a->isSuperTypeOf($b)->yes()) { return [$a, null]; } if ($a instanceof ConstantStringType && $a->getValue() === '' && ($b->describe(\PHPStan\Type\VerbosityLevel::value()) === 'non-empty-string' || $b->describe(\PHPStan\Type\VerbosityLevel::value()) === 'non-falsy-string')) { return [null, self::intersect(new \PHPStan\Type\StringType(), ...self::getAccessoryCaseStringTypes($b))]; } if ($b instanceof ConstantStringType && $b->getValue() === '' && ($a->describe(\PHPStan\Type\VerbosityLevel::value()) === 'non-empty-string' || $a->describe(\PHPStan\Type\VerbosityLevel::value()) === 'non-falsy-string')) { return [self::intersect(new \PHPStan\Type\StringType(), ...self::getAccessoryCaseStringTypes($a)), null]; } if ($a instanceof ConstantStringType && $a->getValue() === '0' && $b->describe(\PHPStan\Type\VerbosityLevel::value()) === 'non-falsy-string') { return [null, self::intersect(new \PHPStan\Type\StringType(), new AccessoryNonEmptyStringType(), ...self::getAccessoryCaseStringTypes($b))]; } if ($b instanceof ConstantStringType && $b->getValue() === '0' && $a->describe(\PHPStan\Type\VerbosityLevel::value()) === 'non-falsy-string') { return [self::intersect(new \PHPStan\Type\StringType(), new AccessoryNonEmptyStringType(), ...self::getAccessoryCaseStringTypes($a)), null]; } return null; } /** * @return array */ private static function getAccessoryCaseStringTypes(\PHPStan\Type\Type $type) : array { $accessory = []; if ($type->isLowercaseString()->yes()) { $accessory[] = new AccessoryLowercaseStringType(); } if ($type->isUppercaseString()->yes()) { $accessory[] = new AccessoryUppercaseStringType(); } return $accessory; } private static function unionWithSubtractedType(\PHPStan\Type\Type $type, ?\PHPStan\Type\Type $subtractedType) : \PHPStan\Type\Type { if ($subtractedType === null) { return $type; } if ($type instanceof \PHPStan\Type\SubtractableType) { $subtractedType = $type->getSubtractedType() === null ? $subtractedType : self::union($type->getSubtractedType(), $subtractedType); if ($subtractedType instanceof \PHPStan\Type\NeverType) { $subtractedType = null; } return $type->changeSubtractedType($subtractedType); } if ($subtractedType->isSuperTypeOf($type)->yes()) { return new \PHPStan\Type\NeverType(); } return self::remove($type, $subtractedType); } private static function intersectWithSubtractedType(\PHPStan\Type\SubtractableType $a, \PHPStan\Type\Type $b) : \PHPStan\Type\Type { if ($a->getSubtractedType() === null) { return $a; } if ($b instanceof \PHPStan\Type\IntersectionType) { $subtractableTypes = []; foreach ($b->getTypes() as $innerType) { if (!$innerType instanceof \PHPStan\Type\SubtractableType) { continue; } $subtractableTypes[] = $innerType; } if (count($subtractableTypes) === 0) { return $a->getTypeWithoutSubtractedType(); } $subtractedTypes = []; foreach ($subtractableTypes as $subtractableType) { if ($subtractableType->getSubtractedType() === null) { continue; } $subtractedTypes[] = $subtractableType->getSubtractedType(); } if (count($subtractedTypes) === 0) { return $a->getTypeWithoutSubtractedType(); } $subtractedType = self::union(...$subtractedTypes); } elseif ($b instanceof \PHPStan\Type\SubtractableType) { $subtractedType = $b->getSubtractedType(); if ($subtractedType === null) { return $a->getTypeWithoutSubtractedType(); } } else { $subtractedTypeTmp = self::intersect($a->getTypeWithoutSubtractedType(), $a->getSubtractedType()); if ($b->isSuperTypeOf($subtractedTypeTmp)->yes()) { return $a->getTypeWithoutSubtractedType(); } $subtractedType = new \PHPStan\Type\MixedType(\false, $b); } $subtractedType = self::intersect($a->getSubtractedType(), $subtractedType); if ($subtractedType instanceof \PHPStan\Type\NeverType) { $subtractedType = null; } return $a->changeSubtractedType($subtractedType); } /** * @param Type[] $arrayTypes * @return Type[] */ private static function processArrayAccessoryTypes(array $arrayTypes) : array { $accessoryTypes = []; foreach ($arrayTypes as $i => $arrayType) { if ($arrayType instanceof \PHPStan\Type\IntersectionType) { foreach ($arrayType->getTypes() as $innerType) { if ($innerType instanceof TemplateType) { break; } if (!$innerType instanceof AccessoryType && !$innerType instanceof \PHPStan\Type\CallableType) { continue; } if ($innerType instanceof HasOffsetType) { $offset = $innerType->getOffsetType(); if ($offset instanceof ConstantStringType || $offset instanceof ConstantIntegerType) { $innerType = new HasOffsetValueType($offset, $arrayType->getIterableValueType()); } } if ($innerType instanceof HasOffsetValueType) { $accessoryTypes[sprintf('hasOffsetValue(%s)', $innerType->getOffsetType()->describe(\PHPStan\Type\VerbosityLevel::cache()))][$i] = $innerType; continue; } $accessoryTypes[$innerType->describe(\PHPStan\Type\VerbosityLevel::cache())][$i] = $innerType; } } if (!$arrayType->isConstantArray()->yes()) { continue; } $constantArrays = $arrayType->getConstantArrays(); foreach ($constantArrays as $constantArray) { if ($constantArray->isList()->yes() && AccessoryArrayListType::isListTypeEnabled()) { $list = new AccessoryArrayListType(); $accessoryTypes[$list->describe(\PHPStan\Type\VerbosityLevel::cache())][$i] = $list; } if (!$constantArray->isIterableAtLeastOnce()->yes()) { continue; } $nonEmpty = new NonEmptyArrayType(); $accessoryTypes[$nonEmpty->describe(\PHPStan\Type\VerbosityLevel::cache())][$i] = $nonEmpty; } } $commonAccessoryTypes = []; $arrayTypeCount = count($arrayTypes); foreach ($accessoryTypes as $accessoryType) { if (count($accessoryType) !== $arrayTypeCount) { $firstKey = array_key_first($accessoryType); if ($accessoryType[$firstKey] instanceof OversizedArrayType) { $commonAccessoryTypes[] = $accessoryType[$firstKey]; } continue; } if ($accessoryType[0] instanceof HasOffsetValueType) { $commonAccessoryTypes[] = self::union(...$accessoryType); continue; } $commonAccessoryTypes[] = $accessoryType[0]; } return $commonAccessoryTypes; } /** * @param list $arrayTypes * @return Type[] */ private static function processArrayTypes(array $arrayTypes) : array { if ($arrayTypes === []) { return []; } $accessoryTypes = self::processArrayAccessoryTypes($arrayTypes); if (count($arrayTypes) === 1) { return [self::intersect(...$arrayTypes, ...$accessoryTypes)]; } $keyTypesForGeneralArray = []; $valueTypesForGeneralArray = []; $generalArrayOccurred = \false; $constantKeyTypesNumbered = []; $filledArrays = 0; $overflowed = \false; /** @var int|float $nextConstantKeyTypeIndex */ $nextConstantKeyTypeIndex = 1; $constantArraysMap = array_map(static function (\PHPStan\Type\Type $t) { return $t->getConstantArrays(); }, $arrayTypes); foreach ($arrayTypes as $arrayIdx => $arrayType) { $constantArrays = $constantArraysMap[$arrayIdx]; $isConstantArray = $constantArrays !== []; if (!$isConstantArray || !$arrayType->isIterableAtLeastOnce()->no()) { $filledArrays++; } if ($generalArrayOccurred || !$isConstantArray) { foreach ($arrayType->getArrays() as $type) { $keyTypesForGeneralArray[] = $type->getIterableKeyType(); $valueTypesForGeneralArray[] = $type->getItemType(); $generalArrayOccurred = \true; } continue; } $constantArrays = $arrayType->getConstantArrays(); foreach ($constantArrays as $constantArray) { foreach ($constantArray->getKeyTypes() as $i => $keyType) { $keyTypesForGeneralArray[] = $keyType; $valueTypesForGeneralArray[] = $constantArray->getValueTypes()[$i]; $keyTypeValue = $keyType->getValue(); if (array_key_exists($keyTypeValue, $constantKeyTypesNumbered)) { continue; } $constantKeyTypesNumbered[$keyTypeValue] = $nextConstantKeyTypeIndex; $nextConstantKeyTypeIndex *= 2; if (!is_int($nextConstantKeyTypeIndex)) { $generalArrayOccurred = \true; $overflowed = \true; continue 2; } } } } if ($generalArrayOccurred && (!$overflowed || $filledArrays > 1)) { $reducedArrayTypes = self::reduceArrays($arrayTypes, \false); if (count($reducedArrayTypes) === 1) { return [self::intersect($reducedArrayTypes[0], ...$accessoryTypes)]; } $scopes = []; $useTemplateArray = \true; foreach ($arrayTypes as $arrayType) { if (!$arrayType instanceof TemplateArrayType) { $useTemplateArray = \false; break; } $scopes[$arrayType->getScope()->describe()] = $arrayType; } $arrayType = new \PHPStan\Type\ArrayType(self::union(...$keyTypesForGeneralArray), self::union(...self::optimizeConstantArrays($valueTypesForGeneralArray))); if ($useTemplateArray && count($scopes) === 1) { $templateArray = array_values($scopes)[0]; $arrayType = new TemplateArrayType($templateArray->getScope(), $templateArray->getStrategy(), $templateArray->getVariance(), $templateArray->getName(), $arrayType, $templateArray->getDefault()); } return [self::intersect($arrayType, ...$accessoryTypes)]; } $reducedArrayTypes = self::reduceArrays($arrayTypes, \true); return array_map(static function (\PHPStan\Type\Type $arrayType) use($accessoryTypes) { return self::intersect($arrayType, ...$accessoryTypes); }, self::optimizeConstantArrays($reducedArrayTypes)); } /** * @param Type[] $types * @return Type[] */ private static function optimizeConstantArrays(array $types) : array { $constantArrayValuesCount = self::countConstantArrayValueTypes($types); if ($constantArrayValuesCount <= ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { return $types; } $results = []; $eachIsOversized = \true; foreach ($types as $type) { $isOversized = \false; $result = \PHPStan\Type\TypeTraverser::map($type, static function (\PHPStan\Type\Type $type, callable $traverse) use(&$isOversized) : \PHPStan\Type\Type { if (!$type instanceof ConstantArrayType) { return $traverse($type); } if ($type->isIterableAtLeastOnce()->no()) { return $type; } $isOversized = \true; $isList = \true; $valueTypes = []; $keyTypes = []; $nextAutoIndex = 0; foreach ($type->getKeyTypes() as $i => $innerKeyType) { if (!$innerKeyType instanceof ConstantIntegerType) { $isList = \false; } elseif ($innerKeyType->getValue() !== $nextAutoIndex) { $isList = \false; $nextAutoIndex = $innerKeyType->getValue() + 1; } else { $nextAutoIndex++; } $generalizedKeyType = $innerKeyType->generalize(\PHPStan\Type\GeneralizePrecision::moreSpecific()); $keyTypes[$generalizedKeyType->describe(\PHPStan\Type\VerbosityLevel::precise())] = $generalizedKeyType; $innerValueType = $type->getValueTypes()[$i]; $generalizedValueType = \PHPStan\Type\TypeTraverser::map($innerValueType, static function (\PHPStan\Type\Type $type) use($traverse) : \PHPStan\Type\Type { if ($type instanceof \PHPStan\Type\ArrayType) { return \PHPStan\Type\TypeCombinator::intersect($type, new OversizedArrayType()); } if ($type instanceof \PHPStan\Type\ConstantScalarType) { return $type->generalize(\PHPStan\Type\GeneralizePrecision::moreSpecific()); } return $traverse($type); }); $valueTypes[$generalizedValueType->describe(\PHPStan\Type\VerbosityLevel::precise())] = $generalizedValueType; } $keyType = \PHPStan\Type\TypeCombinator::union(...array_values($keyTypes)); $valueType = \PHPStan\Type\TypeCombinator::union(...array_values($valueTypes)); $arrayType = new \PHPStan\Type\ArrayType($keyType, $valueType); if ($isList) { $arrayType = AccessoryArrayListType::intersectWith($arrayType); } return \PHPStan\Type\TypeCombinator::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType()); }); if (!$isOversized) { $eachIsOversized = \false; } $results[] = $result; } if ($eachIsOversized) { $eachIsList = \true; $keyTypes = []; $valueTypes = []; foreach ($results as $result) { $keyTypes[] = $result->getIterableKeyType(); $valueTypes[] = $result->getLastIterableValueType(); if ($result->isList()->yes()) { continue; } $eachIsList = \false; } $keyType = self::union(...$keyTypes); $valueType = self::union(...$valueTypes); $arrayType = new \PHPStan\Type\ArrayType($keyType, $valueType); if ($eachIsList) { $arrayType = self::intersect($arrayType, new AccessoryArrayListType()); } return [self::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType())]; } return $results; } /** * @param Type[] $types */ public static function countConstantArrayValueTypes(array $types) : int { $constantArrayValuesCount = 0; foreach ($types as $type) { \PHPStan\Type\TypeTraverser::map($type, static function (\PHPStan\Type\Type $type, callable $traverse) use(&$constantArrayValuesCount) : \PHPStan\Type\Type { if ($type instanceof ConstantArrayType) { $constantArrayValuesCount += count($type->getValueTypes()); } return $traverse($type); }); } return $constantArrayValuesCount; } /** * @param list $constantArrays * @return list */ private static function reduceArrays(array $constantArrays, bool $preserveTaggedUnions) : array { $newArrays = []; $arraysToProcess = []; $emptyArray = null; foreach ($constantArrays as $constantArray) { if (!$constantArray->isConstantArray()->yes()) { // This is an optimization for current use-case of $preserveTaggedUnions=false, where we need // one constant array as a result, or we generalize the $constantArrays. if (!$preserveTaggedUnions) { return $constantArrays; } $newArrays[] = $constantArray; continue; } if ($constantArray->isIterableAtLeastOnce()->no()) { $emptyArray = $constantArray; continue; } $arraysToProcess = array_merge($arraysToProcess, $constantArray->getConstantArrays()); } if ($emptyArray !== null) { $newArrays[] = $emptyArray; } $arraysToProcessPerKey = []; foreach ($arraysToProcess as $i => $arrayToProcess) { foreach ($arrayToProcess->getKeyTypes() as $keyType) { $arraysToProcessPerKey[$keyType->getValue()][] = $i; } } $eligibleCombinations = []; foreach ($arraysToProcessPerKey as $arrays) { for ($i = 0, $arraysCount = count($arrays); $i < $arraysCount - 1; $i++) { for ($j = $i + 1; $j < $arraysCount; $j++) { $eligibleCombinations[$arrays[$i]][$arrays[$j]] = $eligibleCombinations[$arrays[$i]][$arrays[$j]] ?? 0; $eligibleCombinations[$arrays[$i]][$arrays[$j]]++; } } } foreach ($eligibleCombinations as $i => $other) { if (!array_key_exists($i, $arraysToProcess)) { continue; } foreach ($other as $j => $overlappingKeysCount) { if (!array_key_exists($j, $arraysToProcess)) { continue; } if ($preserveTaggedUnions && $overlappingKeysCount === count($arraysToProcess[$i]->getKeyTypes()) && $arraysToProcess[$j]->isKeysSupersetOf($arraysToProcess[$i])) { $arraysToProcess[$j] = $arraysToProcess[$j]->mergeWith($arraysToProcess[$i]); unset($arraysToProcess[$i]); continue 2; } if ($preserveTaggedUnions && $overlappingKeysCount === count($arraysToProcess[$j]->getKeyTypes()) && $arraysToProcess[$i]->isKeysSupersetOf($arraysToProcess[$j])) { $arraysToProcess[$i] = $arraysToProcess[$i]->mergeWith($arraysToProcess[$j]); unset($arraysToProcess[$j]); continue 1; } if (!$preserveTaggedUnions && $overlappingKeysCount === count($arraysToProcess[$i]->getKeyTypes()) && $overlappingKeysCount === count($arraysToProcess[$j]->getKeyTypes())) { $arraysToProcess[$j] = $arraysToProcess[$j]->mergeWith($arraysToProcess[$i]); unset($arraysToProcess[$i]); continue 2; } } } return array_merge($newArrays, $arraysToProcess); } public static function intersect(\PHPStan\Type\Type ...$types) : \PHPStan\Type\Type { $types = array_values($types); $typesCount = count($types); if ($typesCount === 0) { return new \PHPStan\Type\NeverType(); } if ($typesCount === 1) { return $types[0]; } $sortTypes = static function (\PHPStan\Type\Type $a, \PHPStan\Type\Type $b) : int { if (!$a instanceof \PHPStan\Type\UnionType || !$b instanceof \PHPStan\Type\UnionType) { return 0; } if ($a instanceof TemplateType) { return -1; } if ($b instanceof TemplateType) { return 1; } if ($a instanceof \PHPStan\Type\BenevolentUnionType) { return -1; } if ($b instanceof \PHPStan\Type\BenevolentUnionType) { return 1; } return 0; }; usort($types, $sortTypes); // transform A & (B | C) to (A & B) | (A & C) foreach ($types as $i => $type) { if (!$type instanceof \PHPStan\Type\UnionType) { continue; } $topLevelUnionSubTypes = []; $innerTypes = $type->getTypes(); usort($innerTypes, $sortTypes); $slice1 = array_slice($types, 0, $i); $slice2 = array_slice($types, $i + 1); foreach ($innerTypes as $innerUnionSubType) { $topLevelUnionSubTypes[] = self::intersect($innerUnionSubType, ...$slice1, ...$slice2); } $union = self::union(...$topLevelUnionSubTypes); if ($union instanceof \PHPStan\Type\NeverType) { return $union; } if ($type instanceof \PHPStan\Type\BenevolentUnionType) { $union = \PHPStan\Type\TypeUtils::toBenevolentUnion($union); } if ($type instanceof TemplateUnionType || $type instanceof TemplateBenevolentUnionType) { $union = TemplateTypeFactory::create($type->getScope(), $type->getName(), $union, $type->getVariance(), $type->getStrategy(), $type->getDefault()); } return $union; } $typesCount = count($types); // transform A & (B & C) to A & B & C for ($i = 0; $i < $typesCount; $i++) { $type = $types[$i]; if (!$type instanceof \PHPStan\Type\IntersectionType) { continue; } array_splice($types, $i--, 1, $type->getTypes()); $typesCount = count($types); } $hasOffsetValueTypeCount = 0; $newTypes = []; foreach ($types as $type) { if (!$type instanceof HasOffsetValueType) { $newTypes[] = $type; continue; } $hasOffsetValueTypeCount++; } if ($hasOffsetValueTypeCount > 32) { $newTypes[] = new OversizedArrayType(); $types = $newTypes; $typesCount = count($types); } usort($types, static function (\PHPStan\Type\Type $a, \PHPStan\Type\Type $b) : int { // move subtractables with subtracts before those without to avoid loosing them in the union logic if ($a instanceof \PHPStan\Type\SubtractableType && $a->getSubtractedType() !== null) { return -1; } if ($b instanceof \PHPStan\Type\SubtractableType && $b->getSubtractedType() !== null) { return 1; } if ($a instanceof ConstantArrayType && !$b instanceof ConstantArrayType) { return -1; } if ($b instanceof ConstantArrayType && !$a instanceof ConstantArrayType) { return 1; } return 0; }); // transform IntegerType & ConstantIntegerType to ConstantIntegerType // transform Child & Parent to Child // transform Object & ~null to Object // transform A & A to A // transform int[] & string to never // transform callable & int to never // transform A & ~A to never // transform int & string to never for ($i = 0; $i < $typesCount; $i++) { for ($j = $i + 1; $j < $typesCount; $j++) { if ($types[$j] instanceof \PHPStan\Type\SubtractableType) { $typeWithoutSubtractedTypeA = $types[$j]->getTypeWithoutSubtractedType(); if ($typeWithoutSubtractedTypeA instanceof \PHPStan\Type\MixedType && $types[$i] instanceof \PHPStan\Type\MixedType) { $isSuperTypeSubtractableA = $typeWithoutSubtractedTypeA->isSuperTypeOfMixed($types[$i]); } else { $isSuperTypeSubtractableA = $typeWithoutSubtractedTypeA->isSuperTypeOf($types[$i]); } if ($isSuperTypeSubtractableA->yes()) { $types[$i] = self::unionWithSubtractedType($types[$i], $types[$j]->getSubtractedType()); array_splice($types, $j--, 1); $typesCount--; continue 1; } } if ($types[$i] instanceof \PHPStan\Type\SubtractableType) { $typeWithoutSubtractedTypeB = $types[$i]->getTypeWithoutSubtractedType(); if ($typeWithoutSubtractedTypeB instanceof \PHPStan\Type\MixedType && $types[$j] instanceof \PHPStan\Type\MixedType) { $isSuperTypeSubtractableB = $typeWithoutSubtractedTypeB->isSuperTypeOfMixed($types[$j]); } else { $isSuperTypeSubtractableB = $typeWithoutSubtractedTypeB->isSuperTypeOf($types[$j]); } if ($isSuperTypeSubtractableB->yes()) { $types[$j] = self::unionWithSubtractedType($types[$j], $types[$i]->getSubtractedType()); array_splice($types, $i--, 1); $typesCount--; continue 2; } } if ($types[$i] instanceof \PHPStan\Type\IntegerRangeType) { $intersectionType = $types[$i]->tryIntersect($types[$j]); if ($intersectionType !== null) { $types[$j] = $intersectionType; array_splice($types, $i--, 1); $typesCount--; continue 2; } } if ($types[$j] instanceof \PHPStan\Type\IterableType) { $isSuperTypeA = $types[$j]->isSuperTypeOfMixed($types[$i]); } else { $isSuperTypeA = $types[$j]->isSuperTypeOf($types[$i]); } if ($isSuperTypeA->yes()) { array_splice($types, $j--, 1); $typesCount--; continue; } if ($types[$i] instanceof \PHPStan\Type\IterableType) { $isSuperTypeB = $types[$i]->isSuperTypeOfMixed($types[$j]); } else { $isSuperTypeB = $types[$i]->isSuperTypeOf($types[$j]); } if ($isSuperTypeB->maybe()) { if ($types[$i] instanceof ConstantArrayType && $types[$j] instanceof HasOffsetType) { $types[$i] = $types[$i]->makeOffsetRequired($types[$j]->getOffsetType()); array_splice($types, $j--, 1); $typesCount--; continue; } if ($types[$j] instanceof ConstantArrayType && $types[$i] instanceof HasOffsetType) { $types[$j] = $types[$j]->makeOffsetRequired($types[$i]->getOffsetType()); array_splice($types, $i--, 1); $typesCount--; continue 2; } if ($types[$i] instanceof ConstantArrayType && $types[$j] instanceof HasOffsetValueType) { $offsetType = $types[$j]->getOffsetType(); $valueType = $types[$j]->getValueType(); $newValueType = self::intersect($types[$i]->getOffsetValueType($offsetType), $valueType); if ($newValueType instanceof \PHPStan\Type\NeverType) { return $newValueType; } $types[$i] = $types[$i]->setOffsetValueType($offsetType, $newValueType); array_splice($types, $j--, 1); $typesCount--; continue; } if ($types[$j] instanceof ConstantArrayType && $types[$i] instanceof HasOffsetValueType) { $offsetType = $types[$i]->getOffsetType(); $valueType = $types[$i]->getValueType(); $newValueType = self::intersect($types[$j]->getOffsetValueType($offsetType), $valueType); if ($newValueType instanceof \PHPStan\Type\NeverType) { return $newValueType; } $types[$j] = $types[$j]->setOffsetValueType($offsetType, $newValueType); array_splice($types, $i--, 1); $typesCount--; continue 2; } if ($types[$i] instanceof OversizedArrayType && $types[$j] instanceof HasOffsetValueType) { array_splice($types, $j--, 1); $typesCount--; continue; } if ($types[$j] instanceof OversizedArrayType && $types[$i] instanceof HasOffsetValueType) { array_splice($types, $i--, 1); $typesCount--; continue 2; } if ($types[$i] instanceof \PHPStan\Type\ObjectShapeType && $types[$j] instanceof HasPropertyType) { $types[$i] = $types[$i]->makePropertyRequired($types[$j]->getPropertyName()); array_splice($types, $j--, 1); $typesCount--; continue; } if ($types[$j] instanceof \PHPStan\Type\ObjectShapeType && $types[$i] instanceof HasPropertyType) { $types[$j] = $types[$j]->makePropertyRequired($types[$i]->getPropertyName()); array_splice($types, $i--, 1); $typesCount--; continue 2; } if ($types[$i] instanceof ConstantArrayType && $types[$j] instanceof \PHPStan\Type\ArrayType) { $newArray = ConstantArrayTypeBuilder::createEmpty(); $valueTypes = $types[$i]->getValueTypes(); foreach ($types[$i]->getKeyTypes() as $k => $keyType) { $newArray->setOffsetValueType(self::intersect($keyType, $types[$j]->getIterableKeyType()), self::intersect($valueTypes[$k], $types[$j]->getIterableValueType()), $types[$i]->isOptionalKey($k) && !$types[$j]->hasOffsetValueType($keyType)->yes()); } $types[$i] = $newArray->getArray(); array_splice($types, $j--, 1); $typesCount--; continue 2; } if ($types[$j] instanceof ConstantArrayType && $types[$i] instanceof \PHPStan\Type\ArrayType) { $newArray = ConstantArrayTypeBuilder::createEmpty(); $valueTypes = $types[$j]->getValueTypes(); foreach ($types[$j]->getKeyTypes() as $k => $keyType) { $newArray->setOffsetValueType(self::intersect($keyType, $types[$i]->getIterableKeyType()), self::intersect($valueTypes[$k], $types[$i]->getIterableValueType()), $types[$j]->isOptionalKey($k) && !$types[$i]->hasOffsetValueType($keyType)->yes()); } $types[$j] = $newArray->getArray(); array_splice($types, $i--, 1); $typesCount--; continue 2; } if (($types[$i] instanceof \PHPStan\Type\ArrayType || $types[$i] instanceof \PHPStan\Type\IterableType) && ($types[$j] instanceof \PHPStan\Type\ArrayType || $types[$j] instanceof \PHPStan\Type\IterableType)) { $keyType = self::intersect($types[$i]->getIterableKeyType(), $types[$j]->getKeyType()); $itemType = self::intersect($types[$i]->getItemType(), $types[$j]->getItemType()); if ($types[$i] instanceof \PHPStan\Type\IterableType && $types[$j] instanceof \PHPStan\Type\IterableType) { $types[$j] = new \PHPStan\Type\IterableType($keyType, $itemType); } else { $types[$j] = new \PHPStan\Type\ArrayType($keyType, $itemType); } array_splice($types, $i--, 1); $typesCount--; continue 2; } if ($types[$i] instanceof GenericClassStringType && $types[$j] instanceof GenericClassStringType) { $genericType = self::intersect($types[$i]->getGenericType(), $types[$j]->getGenericType()); $types[$i] = new GenericClassStringType($genericType); array_splice($types, $j--, 1); $typesCount--; continue; } if ($types[$i] instanceof \PHPStan\Type\ArrayType && get_class($types[$i]) === \PHPStan\Type\ArrayType::class && $types[$j] instanceof AccessoryArrayListType && !$types[$j]->getIterableKeyType()->isSuperTypeOf($types[$i]->getIterableKeyType())->yes()) { $keyType = self::intersect($types[$i]->getIterableKeyType(), $types[$j]->getIterableKeyType()); if ($keyType instanceof \PHPStan\Type\NeverType) { return $keyType; } $types[$i] = new \PHPStan\Type\ArrayType($keyType, $types[$i]->getItemType()); continue; } continue; } if ($isSuperTypeB->yes()) { array_splice($types, $i--, 1); $typesCount--; continue 2; } if ($isSuperTypeA->no()) { return new \PHPStan\Type\NeverType(); } } } if ($typesCount === 1) { return $types[0]; } return new \PHPStan\Type\IntersectionType($types); } public static function removeFalsey(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return self::remove($type, \PHPStan\Type\StaticTypeFactory::falsey()); } public static function removeTruthy(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return self::remove($type, \PHPStan\Type\StaticTypeFactory::truthy()); } } toInteger(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return $this->toNumber()->toAbsoluteNumber(); } public function toString() : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union(new ConstantStringType(''), new ConstantStringType('1')); } public function toInteger() : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union(new ConstantIntegerType(0), new ConstantIntegerType(1)); } public function toFloat() : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union(new ConstantFloatType(0.0), new ConstantFloatType(1.0)); } public function toArray() : \PHPStan\Type\Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : \PHPStan\Type\Type { return new \PHPStan\Type\UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isTrue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { if ($typeToRemove instanceof ConstantBooleanType) { return new ConstantBooleanType(!$typeToRemove->getValue()); } return null; } public function getFiniteTypes() : array { return [new ConstantBooleanType(\true), new ConstantBooleanType(\false)]; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return \PHPStan\Type\ExponentiateHelper::exponentiate($this, $exponent); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('bool'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self(); } } phpVersion = $phpVersion; $this->regexExpressionHelper = $regexExpressionHelper; } /** * @return array{array, list}|null */ public function parseGroups(string $regex) : ?array { if (self::$parser === null) { /** @throws void */ self::$parser = Llk::load(new Read(__DIR__ . '/../../../resources/RegexGrammar.pp')); } try { Strings::match('', $regex); } catch (RegexpException $e) { // pattern is invalid, so let the RegularExpressionPatternRule report it return null; } $modifiers = $this->regexExpressionHelper->getPatternModifiers($regex) ?? ''; foreach (self::NOT_SUPPORTED_MODIFIERS as $notSupportedModifier) { if (str_contains($modifiers, $notSupportedModifier)) { return null; } } if (str_contains($modifiers, 'x')) { // in freespacing mode the # character starts a comment and runs until the end of the line $regex = preg_replace('/(?regexExpressionHelper->removeDelimitersAndModifiers($regex); try { $ast = self::$parser->parse($rawRegex); } catch (Exception $e) { return null; } $this->updateAlternationAstRemoveVerticalBarsAndAddEmptyToken($ast); $this->updateCapturingAstAddEmptyToken($ast); $captureOnlyNamed = \false; if ($this->phpVersion->supportsPregCaptureOnlyNamedGroups()) { $captureOnlyNamed = str_contains($modifiers, 'n'); } $astWalkResult = $this->walkRegexAst($ast, null, 0, \false, null, $captureOnlyNamed, \false, $modifiers, \PHPStan\Type\Regex\RegexAstWalkResult::createEmpty()); return [$astWalkResult->getCapturingGroups(), $astWalkResult->getMarkVerbs()]; } private function createEmptyTokenTreeNode(TreeNode $parentAst) : TreeNode { return new TreeNode('token', ['token' => 'literal', 'value' => '', 'namespace' => 'default'], [], $parentAst); } private function updateAlternationAstRemoveVerticalBarsAndAddEmptyToken(TreeNode $ast) : void { $children = $ast->getChildren(); foreach ($children as $i => $child) { $this->updateAlternationAstRemoveVerticalBarsAndAddEmptyToken($child); if ($ast->getId() !== '#alternation' || $child->getValueToken() !== 'alternation') { continue; } unset($children[$i]); if ($i !== 0 && isset($children[$i + 1]) && $children[$i + 1]->getValueToken() !== 'alternation') { continue; } $children[$i] = $this->createEmptyTokenTreeNode($ast); } $ast->setChildren(array_values($children)); } private function updateCapturingAstAddEmptyToken(TreeNode $ast) : void { foreach ($ast->getChildren() as $child) { $this->updateCapturingAstAddEmptyToken($child); } if ($ast->getId() !== '#capturing' || $ast->getChildren() !== []) { return; } $emptyAlternationAst = new TreeNode('#alternation', null, [], $ast); $emptyAlternationAst->setChildren([$this->createEmptyTokenTreeNode($emptyAlternationAst)]); $ast->setChildren([$emptyAlternationAst]); } /** * @param RegexCapturingGroup|RegexNonCapturingGroup|null $parentGroup */ private function walkRegexAst(TreeNode $ast, ?\PHPStan\Type\Regex\RegexAlternation $alternation, int $combinationIndex, bool $inOptionalQuantification, $parentGroup, bool $captureOnlyNamed, bool $repeatedMoreThanOnce, string $patternModifiers, \PHPStan\Type\Regex\RegexAstWalkResult $astWalkResult) : \PHPStan\Type\Regex\RegexAstWalkResult { $group = null; if ($ast->getId() === '#capturing') { $astWalkResult = $astWalkResult->nextCaptureGroupId(); $group = new \PHPStan\Type\Regex\RegexCapturingGroup($astWalkResult->getCaptureGroupId(), null, $alternation, $inOptionalQuantification, $parentGroup, $this->createGroupType($ast, $this->allowConstantTypes($patternModifiers, $repeatedMoreThanOnce, $parentGroup), $patternModifiers)); $parentGroup = $group; } elseif ($ast->getId() === '#namedcapturing') { $astWalkResult = $astWalkResult->nextCaptureGroupId(); $name = $ast->getChild(0)->getValueValue(); $group = new \PHPStan\Type\Regex\RegexCapturingGroup($astWalkResult->getCaptureGroupId(), $name, $alternation, $inOptionalQuantification, $parentGroup, $this->createGroupType($ast, $this->allowConstantTypes($patternModifiers, $repeatedMoreThanOnce, $parentGroup), $patternModifiers)); $parentGroup = $group; } elseif ($ast->getId() === '#noncapturing') { $group = new \PHPStan\Type\Regex\RegexNonCapturingGroup($alternation, $inOptionalQuantification, $parentGroup, \false); $parentGroup = $group; } elseif ($ast->getId() === '#noncapturingreset') { $group = new \PHPStan\Type\Regex\RegexNonCapturingGroup($alternation, $inOptionalQuantification, $parentGroup, \true); $parentGroup = $group; } $inOptionalQuantification = \false; if ($ast->getId() === '#quantification') { [$min, $max] = $this->getQuantificationRange($ast); if ($min === 0) { $inOptionalQuantification = \true; } if ($max === null || $max > 1) { $repeatedMoreThanOnce = \true; } } if ($ast->getId() === '#alternation') { $astWalkResult = $astWalkResult->nextAlternationId(); $alternation = new \PHPStan\Type\Regex\RegexAlternation($astWalkResult->getAlternationId(), count($ast->getChildren())); } if ($ast->getId() === '#mark') { return $astWalkResult->markVerb($ast->getChild(0)->getValueValue()); } if ($group instanceof \PHPStan\Type\Regex\RegexCapturingGroup && (!$captureOnlyNamed || $group->isNamed())) { $astWalkResult = $astWalkResult->addCapturingGroup($group); if ($alternation !== null) { $alternation->pushGroup($combinationIndex, $group); } } foreach ($ast->getChildren() as $child) { $astWalkResult = $this->walkRegexAst($child, $alternation, $combinationIndex, $inOptionalQuantification, $parentGroup, $captureOnlyNamed, $repeatedMoreThanOnce, $patternModifiers, $astWalkResult); if ($ast->getId() !== '#alternation') { continue; } $combinationIndex++; } return $astWalkResult; } /** * @param RegexCapturingGroup|RegexNonCapturingGroup|null $parentGroup */ private function allowConstantTypes(string $patternModifiers, bool $repeatedMoreThanOnce, $parentGroup) : bool { if (str_contains($patternModifiers, 'i')) { // if caseless, we don't use constant types // because it likely yields too many combinations return \false; } if ($repeatedMoreThanOnce) { return \false; } if ($parentGroup !== null && $parentGroup->resetsGroupCounter()) { return \false; } return \true; } /** @return array{?int, ?int} */ private function getQuantificationRange(TreeNode $node) : array { if ($node->getId() !== '#quantification') { throw new ShouldNotHappenException(); } $min = null; $max = null; $lastChild = $node->getChild($node->getChildrenNumber() - 1); $value = $lastChild->getValue(); // normalize away possessive and lazy quantifier-modifiers $token = str_replace(['_possessive', '_lazy'], '', $value['token']); $value = rtrim($value['value'], '+?'); if ($token === 'n_to_m') { if (sscanf($value, '{%d,%d}', $n, $m) !== 2 || !is_int($n) || !is_int($m)) { throw new ShouldNotHappenException(); } $min = $n; $max = $m; } elseif ($token === 'n_or_more') { if (sscanf($value, '{%d,}', $n) !== 1 || !is_int($n)) { throw new ShouldNotHappenException(); } $min = $n; } elseif ($token === 'exactly_n') { if (sscanf($value, '{%d}', $n) !== 1 || !is_int($n)) { throw new ShouldNotHappenException(); } $min = $n; $max = $n; } elseif ($token === 'zero_or_one') { $min = 0; $max = 1; } elseif ($token === 'zero_or_more') { $min = 0; } elseif ($token === 'one_or_more') { $min = 1; } return [$min, $max]; } private function createGroupType(TreeNode $group, bool $maybeConstant, string $patternModifiers) : Type { $rootAlternation = $this->getRootAlternation($group); if ($rootAlternation !== null) { $types = []; foreach ($rootAlternation->getChildren() as $alternative) { $types[] = $this->createGroupType($alternative, $maybeConstant, $patternModifiers); } return TypeCombinator::union(...$types); } $walkResult = $this->walkGroupAst($group, \false, \false, $patternModifiers, \PHPStan\Type\Regex\RegexGroupWalkResult::createEmpty()); if ($maybeConstant && $walkResult->getOnlyLiterals() !== null && $walkResult->getOnlyLiterals() !== []) { $result = []; foreach ($walkResult->getOnlyLiterals() as $literal) { $result[] = new ConstantStringType($literal); } return TypeCombinator::union(...$result); } if ($walkResult->isNumeric()->yes()) { if ($walkResult->isNonFalsy()->yes()) { return new IntersectionType([new StringType(), new AccessoryNumericStringType(), new AccessoryNonFalsyStringType()]); } $result = new IntersectionType([new StringType(), new AccessoryNumericStringType()]); if (!$walkResult->isNonEmpty()->yes()) { return TypeCombinator::union(new ConstantStringType(''), $result); } return $result; } elseif ($walkResult->isNonFalsy()->yes()) { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } elseif ($walkResult->isNonEmpty()->yes()) { return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]); } return new StringType(); } private function getRootAlternation(TreeNode $group) : ?TreeNode { if ($group->getId() === '#capturing' && count($group->getChildren()) === 1 && $group->getChild(0)->getId() === '#alternation') { return $group->getChild(0); } // 1st token within a named capturing group is a token holding the group-name if ($group->getId() === '#namedcapturing' && count($group->getChildren()) === 2 && $group->getChild(1)->getId() === '#alternation') { return $group->getChild(1); } return null; } private function walkGroupAst(TreeNode $ast, bool $inAlternation, bool $inClass, string $patternModifiers, \PHPStan\Type\Regex\RegexGroupWalkResult $walkResult) : \PHPStan\Type\Regex\RegexGroupWalkResult { $children = $ast->getChildren(); if ($ast->getId() === '#concatenation' && count($children) > 0 && !$walkResult->isInOptionalQuantification()) { $meaningfulTokens = 0; foreach ($children as $child) { $nonFalsy = \false; if ($this->isMaybeEmptyNode($child, $patternModifiers, $nonFalsy)) { continue; } $meaningfulTokens++; if (!$nonFalsy || $inAlternation) { continue; } // a single token non-falsy on its own $walkResult = $walkResult->nonFalsy(TrinaryLogic::createYes()); break; } if ($meaningfulTokens > 0) { $walkResult = $walkResult->nonEmpty(TrinaryLogic::createYes()); // two non-empty tokens concatenated results in a non-falsy string if ($meaningfulTokens > 1 && !$inAlternation) { $walkResult = $walkResult->nonFalsy(TrinaryLogic::createYes()); } } } elseif ($ast->getId() === '#quantification') { [$min] = $this->getQuantificationRange($ast); if ($min === 0) { $walkResult = $walkResult->inOptionalQuantification(\true); } if (!$walkResult->isInOptionalQuantification()) { if ($min >= 1) { $walkResult = $walkResult->nonEmpty(TrinaryLogic::createYes()); } if ($min >= 2 && !$inAlternation) { $walkResult = $walkResult->nonFalsy(TrinaryLogic::createYes()); } } $walkResult = $walkResult->onlyLiterals(null); } elseif ($ast->getId() === '#class' && $walkResult->getOnlyLiterals() !== null) { $inClass = \true; $newLiterals = []; foreach ($children as $child) { $oldLiterals = $walkResult->getOnlyLiterals(); $this->getLiteralValue($child, $oldLiterals, \true, $patternModifiers, \true); foreach ($oldLiterals ?? [] as $oldLiteral) { $newLiterals[] = $oldLiteral; } } $walkResult = $walkResult->onlyLiterals($newLiterals); } elseif ($ast->getId() === 'token') { $onlyLiterals = $walkResult->getOnlyLiterals(); $literalValue = $this->getLiteralValue($ast, $onlyLiterals, !$inClass, $patternModifiers, \false); $walkResult = $walkResult->onlyLiterals($onlyLiterals); if ($literalValue !== null) { if (Strings::match($literalValue, '/^\\d+$/') === null) { $walkResult = $walkResult->numeric(TrinaryLogic::createNo()); } elseif ($walkResult->isNumeric()->maybe()) { $walkResult = $walkResult->numeric(TrinaryLogic::createYes()); } if (!$walkResult->isInOptionalQuantification() && $literalValue !== '') { $walkResult = $walkResult->nonEmpty(TrinaryLogic::createYes()); } } } elseif (!in_array($ast->getId(), ['#capturing', '#namedcapturing', '#alternation'], \true)) { $walkResult = $walkResult->onlyLiterals(null); } if ($ast->getId() === '#alternation') { $newLiterals = []; foreach ($children as $child) { $walkResult = $this->walkGroupAst($child, \true, $inClass, $patternModifiers, $walkResult->onlyLiterals([])); if ($newLiterals === null) { continue; } if (count($walkResult->getOnlyLiterals() ?? []) > 0) { foreach ($walkResult->getOnlyLiterals() as $alternationLiterals) { $newLiterals[] = $alternationLiterals; } } else { $newLiterals = null; } } return $walkResult->onlyLiterals($newLiterals); } // [^0-9] should not parse as numeric-string, and [^list-everything-but-numbers] is technically // doable but really silly compared to just \d so we can safely assume the string is not numeric // for negative classes if ($ast->getId() === '#negativeclass') { $walkResult = $walkResult->numeric(TrinaryLogic::createNo()); } foreach ($children as $child) { $walkResult = $this->walkGroupAst($child, $inAlternation, $inClass, $patternModifiers, $walkResult); } return $walkResult; } private function isMaybeEmptyNode(TreeNode $node, string $patternModifiers, bool &$isNonFalsy) : bool { if ($node->getId() === '#quantification') { [$min] = $this->getQuantificationRange($node); if ($min > 0) { return \false; } if ($min === 0) { return \true; } } $literal = $this->getLiteralValue($node, $onlyLiterals, \false, $patternModifiers, \false); if ($literal !== null) { if ($literal !== '' && $literal !== '0') { $isNonFalsy = \true; } return $literal === ''; } foreach ($node->getChildren() as $child) { if (!$this->isMaybeEmptyNode($child, $patternModifiers, $isNonFalsy)) { return \false; } } return \true; } /** * @param array|null $onlyLiterals */ private function getLiteralValue(TreeNode $node, ?array &$onlyLiterals, bool $appendLiterals, string $patternModifiers, bool $inCharacterClass) : ?string { if ($node->getId() !== 'token') { return null; } // token is the token name from grammar without the namespace so literal and class:literal are both called literal here $token = $node->getValueToken(); $value = $node->getValueValue(); if (in_array($token, [ 'literal', // literal "-" in front/back of a character class like '[-a-z]' or '[abc-]', not forming a range 'range', // literal "[" or "]" inside character classes '[[]' or '[]]' 'class_', '_class', ], \true)) { if (str_contains($patternModifiers, 'x') && trim($value) === '') { return null; } $isEscaped = \false; if (strlen($value) > 1 && $value[0] === '\\') { $value = substr($value, 1) ?: ''; $isEscaped = \true; } if ($appendLiterals && $onlyLiterals !== null) { if (in_array($value, ['.'], \true) && !($isEscaped || $inCharacterClass)) { $onlyLiterals = null; } else { if ($onlyLiterals === []) { $onlyLiterals = [$value]; } else { foreach ($onlyLiterals as &$literal) { $literal .= $value; } } } } return $value; } if (!in_array($token, ['capturing_name'], \true)) { $onlyLiterals = null; } // character escape sequences, just return a fixed string if (in_array($token, ['character', 'dynamic_character', 'character_type'], \true)) { if ($token === 'character_type' && $value === '\\d') { return '0'; } return $value; } // [:digit:] and the like, more support coming later if ($token === 'posix_class') { if ($value === '[:digit:]') { return '0'; } if (in_array($value, ['[:alpha:]', '[:alnum:]', '[:upper:]', '[:lower:]', '[:word:]', '[:ascii:]', '[:print:]', '[:xdigit:]', '[:graph:]'], \true)) { return 'a'; } if ($value === '[:blank:]') { return " \t"; } if ($value === '[:cntrl:]') { return "\x00\x1f"; } if ($value === '[:space:]') { return " \t\r\n\v\f"; } if ($value === '[:punct:]') { return '!"#$%&\'()*+,\\-./:;<=>?@[\\]^_`{|}~'; } } if ($token === 'anchor' || $token === 'match_point_reset') { return ''; } return null; } } |null */ private $onlyLiterals; /** * @var TrinaryLogic */ private $isNonEmpty; /** * @var TrinaryLogic */ private $isNonFalsy; /** * @var TrinaryLogic */ private $isNumeric; /** * @param array|null $onlyLiterals */ public function __construct(bool $inOptionalQuantification, ?array $onlyLiterals, TrinaryLogic $isNonEmpty, TrinaryLogic $isNonFalsy, TrinaryLogic $isNumeric) { $this->inOptionalQuantification = $inOptionalQuantification; $this->onlyLiterals = $onlyLiterals; $this->isNonEmpty = $isNonEmpty; $this->isNonFalsy = $isNonFalsy; $this->isNumeric = $isNumeric; } public static function createEmpty() : self { return new self(\false, [], TrinaryLogic::createMaybe(), TrinaryLogic::createMaybe(), TrinaryLogic::createMaybe()); } public function inOptionalQuantification(bool $inOptionalQuantification) : self { return new self($inOptionalQuantification, $this->onlyLiterals, $this->isNonEmpty, $this->isNonFalsy, $this->isNumeric); } /** * @param array|null $onlyLiterals */ public function onlyLiterals(?array $onlyLiterals) : self { return new self($this->inOptionalQuantification, $onlyLiterals, $this->isNonEmpty, $this->isNonFalsy, $this->isNumeric); } public function nonEmpty(TrinaryLogic $nonEmpty) : self { return new self($this->inOptionalQuantification, $this->onlyLiterals, $nonEmpty, $this->isNonFalsy, $this->isNumeric); } public function nonFalsy(TrinaryLogic $nonFalsy) : self { return new self($this->inOptionalQuantification, $this->onlyLiterals, $this->isNonEmpty, $nonFalsy, $this->isNumeric); } public function numeric(TrinaryLogic $numeric) : self { return new self($this->inOptionalQuantification, $this->onlyLiterals, $this->isNonEmpty, $this->isNonFalsy, $numeric); } public function isInOptionalQuantification() : bool { return $this->inOptionalQuantification; } /** * @return array|null */ public function getOnlyLiterals() : ?array { return $this->onlyLiterals; } public function isNonEmpty() : TrinaryLogic { return $this->isNonEmpty; } public function isNonFalsy() : TrinaryLogic { return $this->isNonFalsy; } public function isNumeric() : TrinaryLogic { return $this->isNumeric; } } alternation = $alternation; $this->inOptionalQuantification = $inOptionalQuantification; $this->parent = $parent; $this->resetGroupCounter = $resetGroupCounter; } /** @phpstan-assert-if-true !null $this->getAlternationId() */ public function inAlternation() : bool { return $this->alternation !== null; } public function getAlternationId() : ?int { if ($this->alternation === null) { return null; } return $this->alternation->getId(); } public function isOptional() : bool { return $this->inAlternation() || $this->inOptionalQuantification || $this->parent !== null && $this->parent->isOptional(); } public function isTopLevel() : bool { return $this->parent === null || $this->parent instanceof \PHPStan\Type\Regex\RegexNonCapturingGroup && $this->parent->isTopLevel(); } /** * @return RegexCapturingGroup|RegexNonCapturingGroup|null */ public function getParent() { return $this->parent; } public function resetsGroupCounter() : bool { return $this->resetGroupCounter; } } */ private $capturingGroups; /** * @var list */ private $markVerbs; /** * @param array $capturingGroups * @param list $markVerbs */ public function __construct(int $alternationId, int $captureGroupId, array $capturingGroups, array $markVerbs) { $this->alternationId = $alternationId; $this->captureGroupId = $captureGroupId; $this->capturingGroups = $capturingGroups; $this->markVerbs = $markVerbs; } public static function createEmpty() : self { return new self( -1, // use different start-index for groups to make it easier to distinguish groupids from other ids 100, [], [] ); } public function nextAlternationId() : self { return new self($this->alternationId + 1, $this->captureGroupId, $this->capturingGroups, $this->markVerbs); } public function nextCaptureGroupId() : self { return new self($this->alternationId, $this->captureGroupId + 1, $this->capturingGroups, $this->markVerbs); } public function addCapturingGroup(\PHPStan\Type\Regex\RegexCapturingGroup $group) : self { $capturingGroups = $this->capturingGroups; $capturingGroups[$group->getId()] = $group; return new self($this->alternationId, $this->captureGroupId, $capturingGroups, $this->markVerbs); } public function markVerb(string $markVerb) : self { $verbs = $this->markVerbs; $verbs[] = $markVerb; return new self($this->alternationId, $this->captureGroupId, $this->capturingGroups, $verbs); } public function getAlternationId() : int { return $this->alternationId; } public function getCaptureGroupId() : int { return $this->captureGroupId; } /** * @return array */ public function getCapturingGroups() : array { return $this->capturingGroups; } /** * @return list */ public function getMarkVerbs() : array { return $this->markVerbs; } } initializerExprTypeResolver = $initializerExprTypeResolver; } /** * Ignores preg_quote() calls in the concatenation as these are not relevant for array-shape matching. * * This assumption only works for the ArrayShapeMatcher therefore it is not implemented for the common case in Scope. * * see https://github.com/phpstan/phpstan-src/pull/3233#discussion_r1676938085 */ public function resolvePatternConcat(Concat $concat, Scope $scope) : Type { $resolver = new class($scope) { /** * @var Scope */ private $scope; public function __construct(Scope $scope) { $this->scope = $scope; } public function resolve(Expr $expr) : Type { // assume preg_quote() cannot create capturing groups or contain meta characters. // replace it with a pattern which matches anything, does not affect $matches results // and does not produce regex errors when followed by a quantifier. // this allows us to turn string concatenations with preg_quote() into static analyzable strings. if ($expr instanceof Expr\FuncCall && $expr->name instanceof Name && $expr->name->toLowerString() === 'preg_quote') { return new ConstantStringType('(?:.*)'); } if ($expr instanceof Concat) { $left = $this->resolve($expr->left); $right = $this->resolve($expr->right); $strings = []; foreach ($left->toString()->getConstantStrings() as $leftString) { foreach ($right->toString()->getConstantStrings() as $rightString) { $strings[] = new ConstantStringType($leftString->getValue() . $rightString->getValue()); } } return TypeCombinator::union(...$strings); } return $this->scope->getType($expr); } }; return $this->initializerExprTypeResolver->getConcatType($concat->left, $concat->right, static function (Expr $expr) use($resolver) : Type { return $resolver->resolve($expr); }); } public function getPatternModifiers(string $pattern) : ?string { $endDelimiterPos = $this->getEndDelimiterPos($pattern); if ($endDelimiterPos === \false) { return null; } return substr($pattern, $endDelimiterPos + 1); } public function removeDelimitersAndModifiers(string $pattern) : string { $pattern = ltrim($pattern); $endDelimiterPos = $this->getEndDelimiterPos($pattern); if ($endDelimiterPos === \false) { return $pattern; } return substr($pattern, 1, $endDelimiterPos - 1); } /** * @return false|int */ private function getEndDelimiterPos(string $pattern) { $startDelimiter = $this->getPatternDelimiter($pattern); if ($startDelimiter === null) { return \false; } // delimiter variants, see https://www.php.net/manual/en/regexp.reference.delimiters.php $bracketStyleDelimiters = ['{' => '}', '(' => ')', '[' => ']', '<' => '>']; if (array_key_exists($startDelimiter, $bracketStyleDelimiters)) { $endDelimiterPos = strrpos($pattern, $bracketStyleDelimiters[$startDelimiter]); } else { // same start and end delimiter $endDelimiterPos = strrpos($pattern, $startDelimiter); } return $endDelimiterPos; } /** * Get delimiters from non-constant patterns, if possible. * * @return string[] */ public function getPatternDelimiters(Concat $concat, Scope $scope) : array { if ($concat->left instanceof Concat) { return $this->getPatternDelimiters($concat->left, $scope); } $left = $scope->getType($concat->left); $delimiters = []; foreach ($left->getConstantStrings() as $leftString) { $delimiter = $this->getPatternDelimiter($leftString->getValue()); if ($delimiter === null) { continue; } $delimiters[] = $delimiter; } return $delimiters; } private function getPatternDelimiter(string $regex) : ?string { $regex = ltrim($regex); if ($regex === '') { return null; } return substr($regex, 0, 1); } } > */ private $groupCombinations = []; public function __construct(int $alternationId, int $alternationsCount) { $this->alternationId = $alternationId; $this->alternationsCount = $alternationsCount; } public function getId() : int { return $this->alternationId; } public function pushGroup(int $combinationIndex, \PHPStan\Type\Regex\RegexCapturingGroup $group) : void { if (!array_key_exists($combinationIndex, $this->groupCombinations)) { $this->groupCombinations[$combinationIndex] = []; } $this->groupCombinations[$combinationIndex][] = $group->getId(); } public function getAlternationsCount() : int { return $this->alternationsCount; } /** * @return array> */ public function getGroupCombinations() : array { return $this->groupCombinations; } } id = $id; $this->name = $name; $this->alternation = $alternation; $this->inOptionalQuantification = $inOptionalQuantification; $this->parent = $parent; $this->type = $type; } public function getId() : int { return $this->id; } public function forceNonOptional() : void { $this->forceNonOptional = \true; } public function forceType(Type $type) : void { $this->forceType = $type; } public function clearOverrides() : void { $this->forceNonOptional = \false; $this->forceType = null; } public function resetsGroupCounter() : bool { return $this->parent instanceof \PHPStan\Type\Regex\RegexNonCapturingGroup && $this->parent->resetsGroupCounter(); } /** * @phpstan-assert-if-true !null $this->getAlternationId() * @phpstan-assert-if-true !null $this->getAlternation() */ public function inAlternation() : bool { return $this->alternation !== null; } public function getAlternation() : ?\PHPStan\Type\Regex\RegexAlternation { return $this->alternation; } public function getAlternationId() : ?int { if ($this->alternation === null) { return null; } return $this->alternation->getId(); } public function isOptional() : bool { if ($this->forceNonOptional) { return \false; } return $this->inAlternation() || $this->inOptionalQuantification || $this->parent !== null && $this->parent->isOptional(); } public function inOptionalQuantification() : bool { return $this->inOptionalQuantification; } public function inOptionalAlternation() : bool { if (!$this->inAlternation()) { return \false; } $parent = $this->parent; while ($parent !== null && $parent->getAlternationId() === $this->getAlternationId()) { if (!$parent instanceof \PHPStan\Type\Regex\RegexNonCapturingGroup) { return \false; } $parent = $parent->getParent(); } return $parent !== null && $parent->isOptional(); } public function isTopLevel() : bool { return $this->parent === null || $this->parent instanceof \PHPStan\Type\Regex\RegexNonCapturingGroup && $this->parent->isTopLevel(); } /** @phpstan-assert-if-true !null $this->getName() */ public function isNamed() : bool { return $this->name !== null; } public function getName() : ?string { return $this->name; } public function getType() : Type { if ($this->forceType !== null) { return $this->forceType; } return $this->type; } } handle(function () use($level) : string { return parent::describe($level); }, function () use($level) : string { return parent::describe($level); }, static function () : string { return '*ERROR*'; }); } public function getIterableKeyType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getIterableValueType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function subtract(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return new self(); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self(); } } reflectionProvider = $reflectionProvider; $this->dynamicMethodReturnTypeExtensions = $dynamicMethodReturnTypeExtensions; $this->dynamicStaticMethodReturnTypeExtensions = $dynamicStaticMethodReturnTypeExtensions; $this->dynamicFunctionReturnTypeExtensions = $dynamicFunctionReturnTypeExtensions; foreach (array_merge($dynamicMethodReturnTypeExtensions, $dynamicStaticMethodReturnTypeExtensions, $dynamicFunctionReturnTypeExtensions) as $extension) { if (!$extension instanceof BrokerAwareExtension) { continue; } $extension->setBroker($broker); } } /** * @return DynamicMethodReturnTypeExtension[] */ public function getDynamicMethodReturnTypeExtensionsForClass(string $className) : array { if ($this->dynamicMethodReturnTypeExtensionsByClass === null) { $byClass = []; foreach ($this->dynamicMethodReturnTypeExtensions as $extension) { $byClass[strtolower($extension->getClass())][] = $extension; } $this->dynamicMethodReturnTypeExtensionsByClass = $byClass; } return $this->getDynamicExtensionsForType($this->dynamicMethodReturnTypeExtensionsByClass, $className); } /** * @return DynamicStaticMethodReturnTypeExtension[] */ public function getDynamicStaticMethodReturnTypeExtensionsForClass(string $className) : array { if ($this->dynamicStaticMethodReturnTypeExtensionsByClass === null) { $byClass = []; foreach ($this->dynamicStaticMethodReturnTypeExtensions as $extension) { $byClass[strtolower($extension->getClass())][] = $extension; } $this->dynamicStaticMethodReturnTypeExtensionsByClass = $byClass; } return $this->getDynamicExtensionsForType($this->dynamicStaticMethodReturnTypeExtensionsByClass, $className); } /** * @param DynamicMethodReturnTypeExtension[][]|DynamicStaticMethodReturnTypeExtension[][] $extensions * @return mixed[] */ private function getDynamicExtensionsForType(array $extensions, string $className) : array { if (!$this->reflectionProvider->hasClass($className)) { return []; } $extensionsForClass = [[]]; $class = $this->reflectionProvider->getClass($className); foreach (array_merge([$className], $class->getParentClassesNames(), $class->getNativeReflection()->getInterfaceNames()) as $extensionClassName) { $extensionClassName = strtolower($extensionClassName); if (!isset($extensions[$extensionClassName])) { continue; } $extensionsForClass[] = $extensions[$extensionClassName]; } return array_merge(...$extensionsForClass); } /** * @return DynamicFunctionReturnTypeExtension[] */ public function getDynamicFunctionReturnTypeExtensions() : array { return $this->dynamicFunctionReturnTypeExtensions; } } type = $type; $this->ancestorClassName = $ancestorClassName; $this->templateTypeName = $templateTypeName; } public function getReferencedClasses() : array { return $this->type->getReferencedClasses(); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { return $this->type->getReferencedTemplateTypes($positionVariance); } public function equals(Type $type) : bool { return $type instanceof self && $this->type->equals($type->type); } public function describe(VerbosityLevel $level) : string { return sprintf('template-type<%s, %s, %s>', $this->type->describe($level), $this->ancestorClassName, $this->templateTypeName); } public function isResolvable() : bool { return !TypeUtils::containsTemplateType($this->type); } protected function getResult() : Type { return $this->type->getTemplateType($this->ancestorClassName, $this->templateTypeName); } /** * @param callable(Type): Type $cb */ public function traverse(callable $cb) : Type { $type = $cb($this->type); if ($this->type === $type) { return $this; } return new self($type, $this->ancestorClassName, $this->templateTypeName); } public function traverseSimultaneously(Type $right, callable $cb) : Type { if (!$right instanceof self) { return $this; } $type = $cb($this->type, $right->type); if ($this->type === $type) { return $this; } return new self($type, $this->ancestorClassName, $this->templateTypeName); } public function toPhpDocNode() : TypeNode { return new GenericTypeNode(new IdentifierTypeNode('template-type'), [$this->type->toPhpDocNode(), new IdentifierTypeNode($this->ancestorClassName), new ConstTypeNode(new QuoteAwareConstExprStringNode($this->templateTypeName, QuoteAwareConstExprStringNode::SINGLE_QUOTED))]); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['type'], $properties['ancestorClassName'], $properties['templateTypeName']); } } describe(\PHPStan\Type\VerbosityLevel::value()); if (isset(self::$context[$key])) { return new \PHPStan\Type\ErrorType(); } try { self::$context[$key] = \true; return $callback(); } finally { unset(self::$context[$key]); } } } isInteger()->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { if ($this->hasOffsetValueType($offsetType)->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryNonEmptyStringType()]); } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { if ($offsetType === null) { return new \PHPStan\Type\ErrorType(); } $valueStringType = $valueType->toString(); if ($valueStringType instanceof \PHPStan\Type\ErrorType) { return new \PHPStan\Type\ErrorType(); } if ($offsetType->isInteger()->yes() || $offsetType instanceof \PHPStan\Type\MixedType) { return new \PHPStan\Type\IntersectionType([new \PHPStan\Type\StringType(), new AccessoryNonEmptyStringType()]); } return new \PHPStan\Type\ErrorType(); } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return $this; } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof self) { return \PHPStan\Type\AcceptsResult::createYes(); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } $thatClassNames = $type->getObjectClassNames(); if (count($thatClassNames) > 1) { throw new ShouldNotHappenException(); } if ($thatClassNames === [] || $strictTypes) { return \PHPStan\Type\AcceptsResult::createNo(); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (!$reflectionProvider->hasClass($thatClassNames[0])) { return \PHPStan\Type\AcceptsResult::createNo(); } $typeClass = $reflectionProvider->getClass($thatClassNames[0]); return \PHPStan\Type\AcceptsResult::createFromBoolean($typeClass->hasNativeMethod('__toString')); } public function toNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toInteger() : \PHPStan\Type\Type { return new \PHPStan\Type\IntegerType(); } public function toFloat() : \PHPStan\Type\Type { return new \PHPStan\Type\FloatType(); } public function toString() : \PHPStan\Type\Type { return $this; } public function toArray() : \PHPStan\Type\Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : \PHPStan\Type\Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ObjectWithoutClassType(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function hasMethod(string $methodName) : TrinaryLogic { if ($this->isClassStringType()->yes()) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { if ($typeToRemove instanceof ConstantStringType && $typeToRemove->getValue() === '') { return \PHPStan\Type\TypeCombinator::intersect($this, new AccessoryNonEmptyStringType()); } if ($typeToRemove instanceof AccessoryNonEmptyStringType) { return new ConstantStringType(''); } return null; } public function getFiniteTypes() : array { return []; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return \PHPStan\Type\ExponentiateHelper::exponentiate($this, $exponent); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('string'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self(); } } type = $type; } public function getReferencedClasses() : array { return $this->type->getReferencedClasses(); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { return $this->type->getReferencedTemplateTypes($positionVariance); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self && $this->type->equals($type->type); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return sprintf('value-of<%s>', $this->type->describe($level)); } public function isResolvable() : bool { return !\PHPStan\Type\TypeUtils::containsTemplateType($this->type); } protected function getResult() : \PHPStan\Type\Type { if ($this->type->isEnum()->yes()) { $valueTypes = []; foreach ($this->type->getEnumCases() as $enumCase) { $valueType = $enumCase->getBackingValueType(); if ($valueType === null) { continue; } $valueTypes[] = $valueType; } return \PHPStan\Type\TypeCombinator::union(...$valueTypes); } return $this->type->getIterableValueType(); } /** * @param callable(Type): Type $cb */ public function traverse(callable $cb) : \PHPStan\Type\Type { $type = $cb($this->type); if ($this->type === $type) { return $this; } return new self($type); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if (!$right instanceof self) { return $this; } $type = $cb($this->type, $right->type); if ($this->type === $type) { return $this; } return new self($type); } public function toPhpDocNode() : TypeNode { return new GenericTypeNode(new IdentifierTypeNode('value-of'), [$this->type->toPhpDocNode()]); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['type']); } } getAllArrays(); } if ($type instanceof \PHPStan\Type\ArrayType) { return [$type]; } if ($type instanceof \PHPStan\Type\UnionType) { $matchingTypes = []; foreach ($type->getTypes() as $innerType) { if (!$innerType instanceof \PHPStan\Type\ArrayType) { return []; } foreach (self::getArrays($innerType) as $innerInnerType) { $matchingTypes[] = $innerInnerType; } } return $matchingTypes; } if ($type instanceof \PHPStan\Type\IntersectionType) { $matchingTypes = []; foreach ($type->getTypes() as $innerType) { if (!$innerType instanceof \PHPStan\Type\ArrayType) { continue; } foreach (self::getArrays($innerType) as $innerInnerType) { $matchingTypes[] = $innerInnerType; } } return $matchingTypes; } return []; } /** * @return ConstantArrayType[] * * @deprecated Use PHPStan\Type\Type::getConstantArrays() instead and handle optional keys if necessary. */ public static function getConstantArrays(\PHPStan\Type\Type $type) : array { if ($type instanceof ConstantArrayType) { return $type->getAllArrays(); } if ($type instanceof \PHPStan\Type\UnionType) { $matchingTypes = []; foreach ($type->getTypes() as $innerType) { if (!$innerType instanceof ConstantArrayType) { return []; } foreach (self::getConstantArrays($innerType) as $innerInnerType) { $matchingTypes[] = $innerInnerType; } } return $matchingTypes; } return []; } /** * @return ConstantStringType[] * * @deprecated Use PHPStan\Type\Type::getConstantStrings() instead */ public static function getConstantStrings(\PHPStan\Type\Type $type) : array { return self::map(ConstantStringType::class, $type, \false); } /** * @return ConstantIntegerType[] */ public static function getConstantIntegers(\PHPStan\Type\Type $type) : array { return self::map(ConstantIntegerType::class, $type, \false); } /** * @deprecated Use Type::isConstantValue() or Type::generalize() * @return ConstantType[] */ public static function getConstantTypes(\PHPStan\Type\Type $type) : array { return self::map(\PHPStan\Type\ConstantType::class, $type, \false); } /** * @deprecated Use Type::isConstantValue() or Type::generalize() * @return ConstantType[] */ public static function getAnyConstantTypes(\PHPStan\Type\Type $type) : array { return self::map(\PHPStan\Type\ConstantType::class, $type, \false, \false); } /** * @return ArrayType[] * * @deprecated Use PHPStan\Type\Type::getArrays() instead. */ public static function getAnyArrays(\PHPStan\Type\Type $type) : array { return self::map(\PHPStan\Type\ArrayType::class, $type, \true, \false); } /** * @deprecated Use PHPStan\Type\Type::generalize() instead. */ public static function generalizeType(\PHPStan\Type\Type $type, \PHPStan\Type\GeneralizePrecision $precision) : \PHPStan\Type\Type { return $type->generalize($precision); } /** * @return list * * @deprecated Use Type::getObjectClassNames() instead. */ public static function getDirectClassNames(\PHPStan\Type\Type $type) : array { if ($type instanceof \PHPStan\Type\TypeWithClassName) { return [$type->getClassName()]; } if ($type instanceof \PHPStan\Type\UnionType || $type instanceof \PHPStan\Type\IntersectionType) { $classNames = []; foreach ($type->getTypes() as $innerType) { foreach (self::getDirectClassNames($innerType) as $n) { $classNames[] = $n; } } return array_values(array_unique($classNames)); } return []; } /** * @return IntegerRangeType[] */ public static function getIntegerRanges(\PHPStan\Type\Type $type) : array { return self::map(\PHPStan\Type\IntegerRangeType::class, $type, \false); } /** * @deprecated Use Type::isConstantScalarValue() or Type::getConstantScalarTypes() or Type::getConstantScalarValues() * @return ConstantScalarType[] */ public static function getConstantScalars(\PHPStan\Type\Type $type) : array { return self::map(\PHPStan\Type\ConstantScalarType::class, $type, \false); } /** * @deprecated Use Type::getEnumCases() * @return EnumCaseObjectType[] */ public static function getEnumCaseObjects(\PHPStan\Type\Type $type) : array { return self::map(EnumCaseObjectType::class, $type, \false); } /** * @internal * @return ConstantArrayType[] * * @deprecated Use PHPStan\Type\Type::getConstantArrays(). */ public static function getOldConstantArrays(\PHPStan\Type\Type $type) : array { return self::map(ConstantArrayType::class, $type, \false); } /** * @return mixed[] */ private static function map(string $typeClass, \PHPStan\Type\Type $type, bool $inspectIntersections, bool $stopOnUnmatched = \true) : array { if ($type instanceof $typeClass) { return [$type]; } if ($type instanceof \PHPStan\Type\UnionType) { $matchingTypes = []; foreach ($type->getTypes() as $innerType) { $matchingInner = self::map($typeClass, $innerType, $inspectIntersections, $stopOnUnmatched); if ($matchingInner === []) { if ($stopOnUnmatched) { return []; } continue; } foreach ($matchingInner as $innerMapped) { $matchingTypes[] = $innerMapped; } } return $matchingTypes; } if ($inspectIntersections && $type instanceof \PHPStan\Type\IntersectionType) { $matchingTypes = []; foreach ($type->getTypes() as $innerType) { if (!$innerType instanceof $typeClass) { if ($stopOnUnmatched) { return []; } continue; } $matchingTypes[] = $innerType; } return $matchingTypes; } return []; } public static function toBenevolentUnion(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { if ($type instanceof \PHPStan\Type\BenevolentUnionType) { return $type; } if ($type instanceof \PHPStan\Type\UnionType) { return new \PHPStan\Type\BenevolentUnionType($type->getTypes()); } return $type; } /** * @return ($type is UnionType ? UnionType : Type) */ public static function toStrictUnion(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { if ($type instanceof TemplateBenevolentUnionType) { return new TemplateUnionType($type->getScope(), $type->getStrategy(), $type->getVariance(), $type->getName(), static::toStrictUnion($type->getBound()), $type->getDefault()); } if ($type instanceof \PHPStan\Type\BenevolentUnionType) { return new \PHPStan\Type\UnionType($type->getTypes()); } return $type; } /** * @return Type[] */ public static function flattenTypes(\PHPStan\Type\Type $type) : array { if ($type instanceof ConstantArrayType) { return $type->getAllArrays(); } if ($type instanceof \PHPStan\Type\UnionType) { $types = []; foreach ($type->getTypes() as $innerType) { if ($innerType instanceof ConstantArrayType) { foreach ($innerType->getAllArrays() as $array) { $types[] = $array; } continue; } $types[] = $innerType; } return $types; } return [$type]; } public static function findThisType(\PHPStan\Type\Type $type) : ?\PHPStan\Type\ThisType { if ($type instanceof \PHPStan\Type\ThisType) { return $type; } if ($type instanceof \PHPStan\Type\UnionType || $type instanceof \PHPStan\Type\IntersectionType) { foreach ($type->getTypes() as $innerType) { $thisType = self::findThisType($innerType); if ($thisType !== null) { return $thisType; } } } return null; } /** * @return HasPropertyType[] */ public static function getHasPropertyTypes(\PHPStan\Type\Type $type) : array { if ($type instanceof HasPropertyType) { return [$type]; } if ($type instanceof \PHPStan\Type\UnionType || $type instanceof \PHPStan\Type\IntersectionType) { $hasPropertyTypes = [[]]; foreach ($type->getTypes() as $innerType) { $hasPropertyTypes[] = self::getHasPropertyTypes($innerType); } return array_merge(...$hasPropertyTypes); } return []; } /** * @return AccessoryType[] */ public static function getAccessoryTypes(\PHPStan\Type\Type $type) : array { return self::map(AccessoryType::class, $type, \true, \false); } /** @deprecated Use PHPStan\Type\Type::isCallable() instead. */ public static function containsCallable(\PHPStan\Type\Type $type) : bool { if ($type->isCallable()->yes()) { return \true; } if ($type instanceof \PHPStan\Type\UnionType) { foreach ($type->getTypes() as $innerType) { if ($innerType->isCallable()->yes()) { return \true; } } } return \false; } public static function containsTemplateType(\PHPStan\Type\Type $type) : bool { $containsTemplateType = \false; \PHPStan\Type\TypeTraverser::map($type, static function (\PHPStan\Type\Type $type, callable $traverse) use(&$containsTemplateType) : \PHPStan\Type\Type { if ($type instanceof TemplateType) { $containsTemplateType = \true; } return $containsTemplateType ? $type : $traverse($type); }); return $containsTemplateType; } public static function resolveLateResolvableTypes(\PHPStan\Type\Type $type, bool $resolveUnresolvableTypes = \true) : \PHPStan\Type\Type { /** @var int $ignoreResolveUnresolvableTypesLevel */ $ignoreResolveUnresolvableTypesLevel = 0; return \PHPStan\Type\TypeTraverser::map($type, static function (\PHPStan\Type\Type $type, callable $traverse) use($resolveUnresolvableTypes, &$ignoreResolveUnresolvableTypesLevel) : \PHPStan\Type\Type { while ($type instanceof \PHPStan\Type\LateResolvableType && ($resolveUnresolvableTypes && $ignoreResolveUnresolvableTypesLevel === 0 || $type->isResolvable())) { $type = $type->resolve(); } if ($type instanceof \PHPStan\Type\CallableType || $type instanceof \PHPStan\Type\ClosureType) { $ignoreResolveUnresolvableTypesLevel++; $result = $traverse($type); $ignoreResolveUnresolvableTypesLevel--; return $result; } return $traverse($type); }); } } */ private $templateTags; /** * @var SimpleThrowPoint[] */ private $throwPoints; /** * @var InvalidateExprNode[] */ private $invalidateExpressions; /** * @var string[] */ private $usedVariables; /** * @var bool */ private $acceptsNamedArguments; use NonArrayTypeTrait; use NonIterableTypeTrait; use UndecidedComparisonTypeTrait; use NonOffsetAccessibleTypeTrait; use NonRemoveableTypeTrait; use NonGeneralizableTypeTrait; /** @var array */ private $parameters; /** * @var Type */ private $returnType; /** * @var bool */ private $isCommonCallable; /** * @var ObjectType */ private $objectType; /** * @var TemplateTypeMap */ private $templateTypeMap; /** * @var TemplateTypeMap */ private $resolvedTemplateTypeMap; /** * @var TemplateTypeVarianceMap */ private $callSiteVarianceMap; /** @var SimpleImpurePoint[] */ private $impurePoints; /** * @api * @param array|null $parameters * @param array $templateTags * @param SimpleThrowPoint[] $throwPoints * @param ?SimpleImpurePoint[] $impurePoints * @param InvalidateExprNode[] $invalidateExpressions * @param string[] $usedVariables */ public function __construct(?array $parameters = null, ?\PHPStan\Type\Type $returnType = null, bool $variadic = \true, ?TemplateTypeMap $templateTypeMap = null, ?TemplateTypeMap $resolvedTemplateTypeMap = null, ?TemplateTypeVarianceMap $callSiteVarianceMap = null, array $templateTags = [], array $throwPoints = [], ?array $impurePoints = null, array $invalidateExpressions = [], array $usedVariables = [], bool $acceptsNamedArguments = \true) { $this->variadic = $variadic; $this->templateTags = $templateTags; $this->throwPoints = $throwPoints; $this->invalidateExpressions = $invalidateExpressions; $this->usedVariables = $usedVariables; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->parameters = $parameters ?? []; $this->returnType = $returnType ?? new \PHPStan\Type\MixedType(); $this->isCommonCallable = $parameters === null && $returnType === null; $this->objectType = new \PHPStan\Type\ObjectType(Closure::class); $this->templateTypeMap = $templateTypeMap ?? TemplateTypeMap::createEmpty(); $this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap ?? TemplateTypeMap::createEmpty(); $this->callSiteVarianceMap = $callSiteVarianceMap ?? TemplateTypeVarianceMap::createEmpty(); $this->impurePoints = $impurePoints ?? [new SimpleImpurePoint('functionCall', 'call to an unknown Closure', \false)]; } /** * @return array */ public function getTemplateTags() : array { return $this->templateTags; } public static function createPure() : self { return new self(null, null, \true, null, null, null, [], [], []); } public function isPure() : TrinaryLogic { $impurePoints = $this->getImpurePoints(); if (count($impurePoints) === 0) { return TrinaryLogic::createYes(); } $certainCount = 0; foreach ($impurePoints as $impurePoint) { if (!$impurePoint->isCertain()) { continue; } $certainCount++; } return $certainCount > 0 ? TrinaryLogic::createNo() : TrinaryLogic::createMaybe(); } public function getClassName() : string { return $this->objectType->getClassName(); } public function getClassReflection() : ?ClassReflection { return $this->objectType->getClassReflection(); } public function getAncestorWithClassName(string $className) : ?\PHPStan\Type\TypeWithClassName { return $this->objectType->getAncestorWithClassName($className); } /** * @return string[] */ public function getReferencedClasses() : array { $classes = $this->objectType->getReferencedClasses(); foreach ($this->parameters as $parameter) { $classes = array_merge($classes, $parameter->getType()->getReferencedClasses()); } return array_merge($classes, $this->returnType->getReferencedClasses()); } public function getObjectClassNames() : array { return $this->objectType->getObjectClassNames(); } public function getObjectClassReflections() : array { return $this->objectType->getObjectClassReflections(); } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } if (!$type instanceof \PHPStan\Type\ClosureType) { return $this->objectType->acceptsWithReason($type, $strictTypes); } return $this->isSuperTypeOfInternal($type, \true)->toAcceptsResult(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return $this->isSuperTypeOfInternal($type, \false); } private function isSuperTypeOfInternal(\PHPStan\Type\Type $type, bool $treatMixedAsAny) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { $parameterTypes = array_map(static function ($parameter) { return $parameter->getType(); }, $this->getParameters()); $variant = ParametersAcceptorSelector::selectFromTypes($parameterTypes, [$type], \false); if (!$variant instanceof CallableParametersAcceptor) { return \PHPStan\Type\IsSuperTypeOfResult::createNo([]); } return \PHPStan\Type\CallableTypeHelper::isParametersAcceptorSuperTypeOf($this, $variant, $treatMixedAsAny); } if ($type->getObjectClassNames() === [Closure::class]) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } return $this->objectType->isSuperTypeOfWithReason($type); } public function equals(\PHPStan\Type\Type $type) : bool { if (!$type instanceof self) { return \false; } return $this->describe(\PHPStan\Type\VerbosityLevel::precise()) === $type->describe(\PHPStan\Type\VerbosityLevel::precise()); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return $level->handle(static function () : string { return 'Closure'; }, function () : string { if ($this->isCommonCallable) { return $this->isPure()->yes() ? 'pure-Closure' : 'Closure'; } $printer = new Printer(); $selfWithoutParameterNames = new self(array_map(static function (ParameterReflection $p) : ParameterReflection { return new DummyParameter('', $p->getType(), $p->isOptional() && !$p->isVariadic(), PassedByReference::createNo(), $p->isVariadic(), $p->getDefaultValue()); }, $this->parameters), $this->returnType, $this->variadic, $this->templateTypeMap, $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, $this->templateTags, $this->throwPoints, $this->impurePoints, $this->invalidateExpressions, $this->usedVariables); return $printer->print($selfWithoutParameterNames->toPhpDocNode()); }); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isObject() : TrinaryLogic { return $this->objectType->isObject(); } public function isEnum() : TrinaryLogic { return $this->objectType->isEnum(); } public function getTemplateType(string $ancestorClassName, string $templateTypeName) : \PHPStan\Type\Type { return $this->objectType->getTemplateType($ancestorClassName, $templateTypeName); } public function canAccessProperties() : TrinaryLogic { return $this->objectType->canAccessProperties(); } public function hasProperty(string $propertyName) : TrinaryLogic { return $this->objectType->hasProperty($propertyName); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { return $this->objectType->getProperty($propertyName, $scope); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { return $this->objectType->getUnresolvedPropertyPrototype($propertyName, $scope); } public function canCallMethods() : TrinaryLogic { return $this->objectType->canCallMethods(); } public function hasMethod(string $methodName) : TrinaryLogic { return $this->objectType->hasMethod($methodName); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { if ($methodName === 'call') { return new ClosureCallUnresolvedMethodPrototypeReflection($this->objectType->getUnresolvedMethodPrototype($methodName, $scope), $this); } return $this->objectType->getUnresolvedMethodPrototype($methodName, $scope); } public function canAccessConstants() : TrinaryLogic { return $this->objectType->canAccessConstants(); } public function hasConstant(string $constantName) : TrinaryLogic { return $this->objectType->hasConstant($constantName); } public function getConstant(string $constantName) : ConstantReflection { return $this->objectType->getConstant($constantName); } public function getConstantStrings() : array { return []; } public function isIterable() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isCallable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function getEnumCases() : array { return []; } public function isCommonCallable() : bool { return $this->isCommonCallable; } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { return [$this]; } public function getThrowPoints() : array { return $this->throwPoints; } public function getImpurePoints() : array { return $this->impurePoints; } public function getInvalidateExpressions() : array { return $this->invalidateExpressions; } public function getUsedVariables() : array { return $this->usedVariables; } public function acceptsNamedArguments() : bool { return $this->acceptsNamedArguments; } public function isCloneable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function toBoolean() : \PHPStan\Type\BooleanType { return new ConstantBooleanType(\true); } public function toNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toInteger() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toFloat() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toString() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toArray() : \PHPStan\Type\Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getTemplateTypeMap() : TemplateTypeMap { return $this->templateTypeMap; } public function getResolvedTemplateTypeMap() : TemplateTypeMap { return $this->resolvedTemplateTypeMap; } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return $this->callSiteVarianceMap; } /** * @return array */ public function getParameters() : array { return $this->parameters; } public function isVariadic() : bool { return $this->variadic; } public function getReturnType() : \PHPStan\Type\Type { return $this->returnType; } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap { if ($receivedType instanceof \PHPStan\Type\UnionType || $receivedType instanceof \PHPStan\Type\IntersectionType) { return $receivedType->inferTemplateTypesOn($this); } if ($receivedType->isCallable()->no() || !$receivedType instanceof self) { return TemplateTypeMap::createEmpty(); } $parametersAcceptors = $receivedType->getCallableParametersAcceptors(new OutOfClassScope()); $typeMap = TemplateTypeMap::createEmpty(); foreach ($parametersAcceptors as $parametersAcceptor) { $typeMap = $typeMap->union($this->inferTemplateTypesOnParametersAcceptor($parametersAcceptor)); } return $typeMap; } private function inferTemplateTypesOnParametersAcceptor(ParametersAcceptor $parametersAcceptor) : TemplateTypeMap { $parameterTypes = array_map(static function ($parameter) { return $parameter->getType(); }, $this->getParameters()); $parametersAcceptor = ParametersAcceptorSelector::selectFromTypes($parameterTypes, [$parametersAcceptor], \false); $args = $parametersAcceptor->getParameters(); $returnType = $parametersAcceptor->getReturnType(); $typeMap = TemplateTypeMap::createEmpty(); foreach ($this->getParameters() as $i => $param) { $paramType = $param->getType(); if (isset($args[$i])) { $argType = $args[$i]->getType(); } elseif ($paramType instanceof TemplateType) { $argType = TemplateTypeHelper::resolveToBounds($paramType); } else { $argType = new \PHPStan\Type\NeverType(); } $typeMap = $typeMap->union($paramType->inferTemplateTypes($argType)->convertToLowerBoundTypes()); } return $typeMap->union($this->getReturnType()->inferTemplateTypes($returnType)); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { $references = $this->getReturnType()->getReferencedTemplateTypes($positionVariance->compose(TemplateTypeVariance::createCovariant())); $paramVariance = $positionVariance->compose(TemplateTypeVariance::createContravariant()); foreach ($this->getParameters() as $param) { foreach ($param->getType()->getReferencedTemplateTypes($paramVariance) as $reference) { $references[] = $reference; } } return $references; } public function traverse(callable $cb) : \PHPStan\Type\Type { if ($this->isCommonCallable) { return $this; } return new self(array_map(static function (ParameterReflection $param) use($cb) : NativeParameterReflection { $defaultValue = $param->getDefaultValue(); return new NativeParameterReflection($param->getName(), $param->isOptional(), $cb($param->getType()), $param->passedByReference(), $param->isVariadic(), $defaultValue !== null ? $cb($defaultValue) : null); }, $this->getParameters()), $cb($this->getReturnType()), $this->isVariadic(), $this->templateTypeMap, $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, $this->templateTags, $this->throwPoints, $this->impurePoints, $this->invalidateExpressions, $this->usedVariables, $this->acceptsNamedArguments); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if ($this->isCommonCallable) { return $this; } if (!$right instanceof self) { return $this; } $rightParameters = $right->getParameters(); if (count($this->getParameters()) !== count($rightParameters)) { return $this; } $parameters = []; foreach ($this->getParameters() as $i => $leftParam) { $rightParam = $rightParameters[$i]; $leftDefaultValue = $leftParam->getDefaultValue(); $rightDefaultValue = $rightParam->getDefaultValue(); $defaultValue = $leftDefaultValue; if ($leftDefaultValue !== null && $rightDefaultValue !== null) { $defaultValue = $cb($leftDefaultValue, $rightDefaultValue); } $parameters[] = new NativeParameterReflection($leftParam->getName(), $leftParam->isOptional(), $cb($leftParam->getType(), $rightParam->getType()), $leftParam->passedByReference(), $leftParam->isVariadic(), $defaultValue); } return new self($parameters, $cb($this->getReturnType(), $right->getReturnType()), $this->isVariadic(), $this->templateTypeMap, $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, $this->templateTags, $this->throwPoints, $this->impurePoints, $this->invalidateExpressions, $this->usedVariables, $this->acceptsNamedArguments); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return $this; } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { if ($this->isCommonCallable) { return new IdentifierTypeNode($this->isPure()->yes() ? 'pure-Closure' : 'Closure'); } $parameters = []; foreach ($this->parameters as $parameter) { $parameters[] = new CallableTypeParameterNode($parameter->getType()->toPhpDocNode(), !$parameter->passedByReference()->no(), $parameter->isVariadic(), $parameter->getName() === '' ? '' : '$' . $parameter->getName(), $parameter->isOptional()); } $templateTags = []; foreach ($this->templateTags as $templateName => $templateTag) { $templateTags[] = new TemplateTagValueNode($templateName, $templateTag->getBound()->toPhpDocNode(), ''); } return new CallableTypeNode(new IdentifierTypeNode('Closure'), $parameters, $this->returnType->toPhpDocNode(), $templateTags); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['parameters'], $properties['returnType'], $properties['variadic'], $properties['templateTypeMap'], $properties['resolvedTemplateTypeMap'], $properties['callSiteVarianceMap'], $properties['templateTags'], $properties['throwPoints'], $properties['impurePoints'], $properties['invalidateExpressions'], $properties['usedVariables'], $properties['acceptsNamedArguments']); } } */ private $globalTypeAliases; /** * @var TypeStringResolver */ private $typeStringResolver; /** * @var TypeNodeResolver */ private $typeNodeResolver; /** * @var ReflectionProvider */ private $reflectionProvider; /** @var array */ private $resolvedGlobalTypeAliases = []; /** @var array */ private $resolvedLocalTypeAliases = []; /** @var array */ private $resolvingClassTypeAliases = []; /** @var array */ private $inProcess = []; /** * @param array $globalTypeAliases */ public function __construct(array $globalTypeAliases, TypeStringResolver $typeStringResolver, TypeNodeResolver $typeNodeResolver, ReflectionProvider $reflectionProvider) { $this->globalTypeAliases = $globalTypeAliases; $this->typeStringResolver = $typeStringResolver; $this->typeNodeResolver = $typeNodeResolver; $this->reflectionProvider = $reflectionProvider; } public function hasTypeAlias(string $aliasName, ?string $classNameScope) : bool { $hasGlobalTypeAlias = array_key_exists($aliasName, $this->globalTypeAliases); if ($hasGlobalTypeAlias) { return \true; } if ($classNameScope === null || !$this->reflectionProvider->hasClass($classNameScope)) { return \false; } $classReflection = $this->reflectionProvider->getClass($classNameScope); $localTypeAliases = $classReflection->getTypeAliases(); return array_key_exists($aliasName, $localTypeAliases); } public function resolveTypeAlias(string $aliasName, NameScope $nameScope) : ?\PHPStan\Type\Type { return $this->resolveLocalTypeAlias($aliasName, $nameScope) ?? $this->resolveGlobalTypeAlias($aliasName, $nameScope); } private function resolveLocalTypeAlias(string $aliasName, NameScope $nameScope) : ?\PHPStan\Type\Type { if (array_key_exists($aliasName, $this->globalTypeAliases)) { return null; } if (!$nameScope->hasTypeAlias($aliasName)) { return null; } $className = $nameScope->getClassNameForTypeAlias(); if ($className === null) { return null; } $aliasNameInClassScope = $className . '::' . $aliasName; if (array_key_exists($aliasNameInClassScope, $this->resolvedLocalTypeAliases)) { return $this->resolvedLocalTypeAliases[$aliasNameInClassScope]; } // prevent infinite recursion if (array_key_exists($className, $this->resolvingClassTypeAliases)) { return null; } $this->resolvingClassTypeAliases[$className] = \true; if (!$this->reflectionProvider->hasClass($className)) { unset($this->resolvingClassTypeAliases[$className]); return null; } $classReflection = $this->reflectionProvider->getClass($className); $localTypeAliases = $classReflection->getTypeAliases(); unset($this->resolvingClassTypeAliases[$className]); if (!array_key_exists($aliasName, $localTypeAliases)) { return null; } if (array_key_exists($aliasNameInClassScope, $this->inProcess)) { // resolve circular reference as ErrorType to make it easier to detect throw new \PHPStan\Type\CircularTypeAliasDefinitionException(); } $this->inProcess[$aliasNameInClassScope] = \true; try { $unresolvedAlias = $localTypeAliases[$aliasName]; $resolvedAliasType = $unresolvedAlias->resolve($this->typeNodeResolver); } catch (\PHPStan\Type\CircularTypeAliasDefinitionException $e) { $resolvedAliasType = new \PHPStan\Type\CircularTypeAliasErrorType(); } $this->resolvedLocalTypeAliases[$aliasNameInClassScope] = $resolvedAliasType; unset($this->inProcess[$aliasNameInClassScope]); return $resolvedAliasType; } private function resolveGlobalTypeAlias(string $aliasName, NameScope $nameScope) : ?\PHPStan\Type\Type { if (!array_key_exists($aliasName, $this->globalTypeAliases)) { return null; } if (array_key_exists($aliasName, $this->resolvedGlobalTypeAliases)) { return $this->resolvedGlobalTypeAliases[$aliasName]; } if ($this->reflectionProvider->hasClass($nameScope->resolveStringName($aliasName))) { throw new ShouldNotHappenException(sprintf('Type alias %s already exists as a class.', $aliasName)); } if (array_key_exists($aliasName, $this->inProcess)) { throw new ShouldNotHappenException(sprintf('Circular definition for type alias %s.', $aliasName)); } $this->inProcess[$aliasName] = \true; $aliasTypeString = $this->globalTypeAliases[$aliasName]; $aliasType = $this->typeStringResolver->resolve($aliasTypeString); $this->resolvedGlobalTypeAliases[$aliasName] = $aliasType; unset($this->inProcess[$aliasName]); return $aliasType; } } */ private $cachedDescriptions = []; /** * @api * @param Type[] $types */ public function __construct(array $types, bool $normalized = \false) { $this->types = $types; $this->normalized = $normalized; $throwException = static function () use($types) : void { throw new ShouldNotHappenException(sprintf('Cannot create %s with: %s', self::class, implode(', ', array_map(static function (\PHPStan\Type\Type $type) : string { return $type->describe(\PHPStan\Type\VerbosityLevel::value()); }, $types)))); }; if (count($types) < 2) { $throwException(); } foreach ($types as $type) { if (!$type instanceof \PHPStan\Type\UnionType) { continue; } if ($type instanceof TemplateType) { continue; } $throwException(); } } /** * @return Type[] */ public function getTypes() : array { return $this->types; } /** * @param callable(Type $type): bool $filterCb */ public function filterTypes(callable $filterCb) : \PHPStan\Type\Type { $newTypes = []; $changed = \false; foreach ($this->getTypes() as $innerType) { if (!$filterCb($innerType)) { $changed = \true; continue; } $newTypes[] = $innerType; } if (!$changed) { return $this; } return \PHPStan\Type\TypeCombinator::union(...$newTypes); } public function isNormalized() : bool { return $this->normalized; } /** * @return Type[] */ protected function getSortedTypes() : array { if ($this->sortedTypes) { return $this->types; } $this->types = \PHPStan\Type\UnionTypeHelper::sortTypes($this->types); $this->sortedTypes = \true; return $this->types; } /** * @return string[] */ public function getReferencedClasses() : array { $classes = []; foreach ($this->types as $type) { foreach ($type->getReferencedClasses() as $className) { $classes[] = $className; } } return $classes; } public function getObjectClassNames() : array { return array_values(array_unique($this->pickFromTypes(static function (\PHPStan\Type\Type $type) { return $type->getObjectClassNames(); }, static function (\PHPStan\Type\Type $type) { return $type->isObject()->yes(); }))); } public function getObjectClassReflections() : array { return $this->pickFromTypes(static function (\PHPStan\Type\Type $type) { return $type->getObjectClassReflections(); }, static function (\PHPStan\Type\Type $type) { return $type->isObject()->yes(); }); } public function getArrays() : array { return $this->pickFromTypes(static function (\PHPStan\Type\Type $type) { return $type->getArrays(); }, static function (\PHPStan\Type\Type $type) { return $type->isArray()->yes(); }); } public function getConstantArrays() : array { return $this->pickFromTypes(static function (\PHPStan\Type\Type $type) { return $type->getConstantArrays(); }, static function (\PHPStan\Type\Type $type) { return $type->isArray()->yes(); }); } public function getConstantStrings() : array { return $this->pickFromTypes(static function (\PHPStan\Type\Type $type) { return $type->getConstantStrings(); }, static function (\PHPStan\Type\Type $type) { return $type->isString()->yes(); }); } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type->equals(new \PHPStan\Type\ObjectType(DateTimeInterface::class)) && $this->accepts(new \PHPStan\Type\UnionType([new \PHPStan\Type\ObjectType(DateTime::class), new \PHPStan\Type\ObjectType(DateTimeImmutable::class)]), $strictTypes)->yes()) { return \PHPStan\Type\AcceptsResult::createYes(); } $result = \PHPStan\Type\AcceptsResult::createNo(); foreach ($this->getSortedTypes() as $i => $innerType) { $result = $result->or($innerType->acceptsWithReason($type, $strictTypes)->decorateReasons(static function (string $reason) use($i) { return sprintf('Type #%d from the union: %s', $i + 1, $reason); })); } if ($result->yes()) { return $result; } if ($type instanceof \PHPStan\Type\CompoundType && !$type instanceof \PHPStan\Type\CallableType && !$type instanceof TemplateType && !$type instanceof \PHPStan\Type\IntersectionType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } if ($type instanceof TemplateUnionType) { return $result->or($type->isAcceptedWithReasonBy($this, $strictTypes)); } if ($type->isEnum()->yes() && !$this->isEnum()->no()) { $enumCasesUnion = \PHPStan\Type\TypeCombinator::union(...$type->getEnumCases()); if (!$type->equals($enumCasesUnion)) { return $this->acceptsWithReason($enumCasesUnion, $strictTypes); } } return $result; } public function isSuperTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSuperTypeOfWithReason($otherType)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof self && !$otherType instanceof TemplateUnionType || $otherType instanceof \PHPStan\Type\IterableType && !$otherType instanceof TemplateIterableType || $otherType instanceof \PHPStan\Type\NeverType || $otherType instanceof \PHPStan\Type\ConditionalType || $otherType instanceof \PHPStan\Type\ConditionalTypeForParameter || $otherType instanceof \PHPStan\Type\IntegerRangeType) { return $otherType->isSubTypeOfWithReason($this); } $results = []; foreach ($this->types as $innerType) { $result = $innerType->isSuperTypeOfWithReason($otherType); if ($result->yes()) { return $result; } $results[] = $result; } $result = \PHPStan\Type\IsSuperTypeOfResult::createNo()->or(...$results); if ($otherType instanceof TemplateUnionType) { return $result->or($otherType->isSubTypeOfWithReason($this)); } return $result; } public function isSubTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { return \PHPStan\Type\IsSuperTypeOfResult::extremeIdentity(...array_map(static function (\PHPStan\Type\Type $innerType) use($otherType) { return $otherType->isSuperTypeOfWithReason($innerType); }, $this->types)); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { return \PHPStan\Type\AcceptsResult::extremeIdentity(...array_map(static function (\PHPStan\Type\Type $innerType) use($acceptingType, $strictTypes) { return $acceptingType->acceptsWithReason($innerType, $strictTypes); }, $this->types)); } public function equals(\PHPStan\Type\Type $type) : bool { if (!$type instanceof static) { return \false; } if (count($this->types) !== count($type->types)) { return \false; } $otherTypes = $type->types; foreach ($this->types as $innerType) { $match = \false; foreach ($otherTypes as $i => $otherType) { if (!$innerType->equals($otherType)) { continue; } $match = \true; unset($otherTypes[$i]); break; } if (!$match) { return \false; } } return count($otherTypes) === 0; } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { if (isset($this->cachedDescriptions[$level->getLevelValue()])) { return $this->cachedDescriptions[$level->getLevelValue()]; } $joinTypes = static function (array $types) use($level) : string { $typeNames = []; foreach ($types as $i => $type) { if ($type instanceof \PHPStan\Type\ClosureType || $type instanceof \PHPStan\Type\CallableType || $type instanceof TemplateUnionType) { $typeNames[] = sprintf('(%s)', $type->describe($level)); } elseif ($type instanceof TemplateType) { $isLast = $i >= count($types) - 1; $bound = $type->getBound(); if (!$isLast && ($level->isTypeOnly() || $level->isValue()) && !($bound instanceof \PHPStan\Type\MixedType && $bound->getSubtractedType() === null && !$bound instanceof TemplateMixedType)) { $typeNames[] = sprintf('(%s)', $type->describe($level)); } else { $typeNames[] = $type->describe($level); } } elseif ($type instanceof \PHPStan\Type\IntersectionType) { $intersectionDescription = $type->describe($level); if (str_contains($intersectionDescription, '&')) { $typeNames[] = sprintf('(%s)', $type->describe($level)); } else { $typeNames[] = $intersectionDescription; } } else { $typeNames[] = $type->describe($level); } } if ($level->isPrecise()) { $duplicates = array_diff_assoc($typeNames, array_unique($typeNames)); if (count($duplicates) > 0) { $indexByDuplicate = array_fill_keys($duplicates, 0); foreach ($typeNames as $key => $typeName) { if (!isset($indexByDuplicate[$typeName])) { continue; } $typeNames[$key] = $typeName . '#' . ++$indexByDuplicate[$typeName]; } } } else { $typeNames = array_unique($typeNames); } if (count($typeNames) > 1024) { return implode('|', array_slice($typeNames, 0, 1024)) . "|…"; } return implode('|', $typeNames); }; return $this->cachedDescriptions[$level->getLevelValue()] = $level->handle(function () use($joinTypes) : string { $types = \PHPStan\Type\TypeCombinator::union(...array_map(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { if ($type->isConstantValue()->yes() && $type->isTrue()->or($type->isFalse())->no()) { return $type->generalize(\PHPStan\Type\GeneralizePrecision::lessSpecific()); } return $type; }, $this->getSortedTypes())); if ($types instanceof \PHPStan\Type\UnionType) { return $joinTypes($types->getSortedTypes()); } return $joinTypes([$types]); }, function () use($joinTypes) : string { return $joinTypes($this->getSortedTypes()); }); } /** * @param callable(Type $type): TrinaryLogic $canCallback * @param callable(Type $type): TrinaryLogic $hasCallback */ private function hasInternal(callable $canCallback, callable $hasCallback) : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->types, static function (\PHPStan\Type\Type $type) use($canCallback, $hasCallback) : TrinaryLogic { if ($canCallback($type)->no()) { return TrinaryLogic::createNo(); } return $hasCallback($type); }); } /** * @template TObject of object * @param callable(Type $type): TrinaryLogic $hasCallback * @param callable(Type $type): TObject $getCallback * @return TObject */ private function getInternal(callable $hasCallback, callable $getCallback) : object { /** @var TrinaryLogic|null $result */ $result = null; /** @var TObject|null $object */ $object = null; foreach ($this->types as $type) { $has = $hasCallback($type); if (!$has->yes()) { continue; } if ($result !== null && $result->compareTo($has) !== $has) { continue; } $get = $getCallback($type); $result = $has; $object = $get; } if ($object === null) { throw new ShouldNotHappenException(); } return $object; } public function getTemplateType(string $ancestorClassName, string $templateTypeName) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($ancestorClassName, $templateTypeName) : \PHPStan\Type\Type { return $type->getTemplateType($ancestorClassName, $templateTypeName); }); } public function isObject() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isObject(); }); } public function isEnum() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isEnum(); }); } public function canAccessProperties() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->canAccessProperties(); }); } public function hasProperty(string $propertyName) : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) use($propertyName) : TrinaryLogic { return $type->hasProperty($propertyName); }); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { $propertyPrototypes = []; foreach ($this->types as $type) { if (!$type->hasProperty($propertyName)->yes()) { continue; } $propertyPrototypes[] = $type->getUnresolvedPropertyPrototype($propertyName, $scope)->withFechedOnType($this); } $propertiesCount = count($propertyPrototypes); if ($propertiesCount === 0) { throw new ShouldNotHappenException(); } if ($propertiesCount === 1) { return $propertyPrototypes[0]; } return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes); } public function canCallMethods() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->canCallMethods(); }); } public function hasMethod(string $methodName) : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) use($methodName) : TrinaryLogic { return $type->hasMethod($methodName); }); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { $methodPrototypes = []; foreach ($this->types as $type) { if (!$type->hasMethod($methodName)->yes()) { continue; } $methodPrototypes[] = $type->getUnresolvedMethodPrototype($methodName, $scope)->withCalledOnType($this); } $methodsCount = count($methodPrototypes); if ($methodsCount === 0) { throw new ShouldNotHappenException(); } if ($methodsCount === 1) { return $methodPrototypes[0]; } return new UnionTypeUnresolvedMethodPrototypeReflection($methodName, $methodPrototypes); } public function canAccessConstants() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->canAccessConstants(); }); } public function hasConstant(string $constantName) : TrinaryLogic { return $this->hasInternal(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->canAccessConstants(); }, static function (\PHPStan\Type\Type $type) use($constantName) : TrinaryLogic { return $type->hasConstant($constantName); }); } public function getConstant(string $constantName) : ConstantReflection { return $this->getInternal(static function (\PHPStan\Type\Type $type) use($constantName) : TrinaryLogic { return $type->hasConstant($constantName); }, static function (\PHPStan\Type\Type $type) use($constantName) : ConstantReflection { return $type->getConstant($constantName); }); } public function isIterable() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isIterable(); }); } public function isIterableAtLeastOnce() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isIterableAtLeastOnce(); }); } public function getArraySize() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getArraySize(); }); } public function getIterableKeyType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getIterableKeyType(); }); } public function getFirstIterableKeyType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getFirstIterableKeyType(); }); } public function getLastIterableKeyType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getLastIterableKeyType(); }); } public function getIterableValueType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getIterableValueType(); }); } public function getFirstIterableValueType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getFirstIterableValueType(); }); } public function getLastIterableValueType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getLastIterableValueType(); }); } public function isArray() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isArray(); }); } public function isConstantArray() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isConstantArray(); }); } public function isOversizedArray() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isOversizedArray(); }); } public function isList() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isList(); }); } public function isString() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isString(); }); } public function isNumericString() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isNumericString(); }); } public function isNonEmptyString() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isNonEmptyString(); }); } public function isNonFalsyString() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isNonFalsyString(); }); } public function isLiteralString() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isLiteralString(); }); } public function isLowercaseString() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isLowercaseString(); }); } public function isUppercaseString() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isUppercaseString(); }); } public function isClassStringType() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isClassStringType(); }); } public function getClassStringObjectType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getClassStringObjectType(); }); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getObjectTypeOrClassStringObjectType(); }); } public function isVoid() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isVoid(); }); } public function isScalar() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isScalar(); }); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function isOffsetAccessible() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isOffsetAccessible(); }); } public function isOffsetAccessLegal() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isOffsetAccessLegal(); }); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) use($offsetType) : TrinaryLogic { return $type->hasOffsetValueType($offsetType); }); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { $types = []; foreach ($this->types as $innerType) { $valueType = $innerType->getOffsetValueType($offsetType); if ($valueType instanceof \PHPStan\Type\ErrorType) { continue; } $types[] = $valueType; } if (count($types) === 0) { return new \PHPStan\Type\ErrorType(); } return \PHPStan\Type\TypeCombinator::union(...$types); } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($offsetType, $valueType, $unionValues) : \PHPStan\Type\Type { return $type->setOffsetValueType($offsetType, $valueType, $unionValues); }); } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($offsetType, $valueType) : \PHPStan\Type\Type { return $type->setExistingOffsetValueType($offsetType, $valueType); }); } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($offsetType) : \PHPStan\Type\Type { return $type->unsetOffset($offsetType); }); } public function getKeysArray() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getKeysArray(); }); } public function getValuesArray() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getValuesArray(); }); } public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($lengthType, $preserveKeys) : \PHPStan\Type\Type { return $type->chunkArray($lengthType, $preserveKeys); }); } public function fillKeysArray(\PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($valueType) : \PHPStan\Type\Type { return $type->fillKeysArray($valueType); }); } public function flipArray() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->flipArray(); }); } public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($otherArraysType) : \PHPStan\Type\Type { return $type->intersectKeyArray($otherArraysType); }); } public function popArray() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->popArray(); }); } public function reverseArray(TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($preserveKeys) : \PHPStan\Type\Type { return $type->reverseArray($preserveKeys); }); } public function searchArray(\PHPStan\Type\Type $needleType) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($needleType) : \PHPStan\Type\Type { return $type->searchArray($needleType); }); } public function shiftArray() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->shiftArray(); }); } public function shuffleArray() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->shuffleArray(); }); } public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($offsetType, $lengthType, $preserveKeys) : \PHPStan\Type\Type { return $type->sliceArray($offsetType, $lengthType, $preserveKeys); }); } public function getEnumCases() : array { return $this->pickFromTypes(static function (\PHPStan\Type\Type $type) { return $type->getEnumCases(); }, static function (\PHPStan\Type\Type $type) { return $type->isObject()->yes(); }); } public function isCallable() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isCallable(); }); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { $acceptors = []; foreach ($this->types as $type) { if ($type->isCallable()->no()) { continue; } $acceptors = array_merge($acceptors, $type->getCallableParametersAcceptors($scope)); } if (count($acceptors) === 0) { throw new ShouldNotHappenException(); } return $acceptors; } public function isCloneable() : TrinaryLogic { return $this->unionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isCloneable(); }); } public function isSmallerThan(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) use($otherType) : TrinaryLogic { return $type->isSmallerThan($otherType); }); } public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) use($otherType) : TrinaryLogic { return $type->isSmallerThanOrEqual($otherType); }); } public function isNull() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isNull(); }); } public function isConstantValue() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isConstantValue(); }); } public function isConstantScalarValue() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isConstantScalarValue(); }); } public function getConstantScalarTypes() : array { return $this->notBenevolentPickFromTypes(static function (\PHPStan\Type\Type $type) { return $type->getConstantScalarTypes(); }); } public function getConstantScalarValues() : array { return $this->notBenevolentPickFromTypes(static function (\PHPStan\Type\Type $type) { return $type->getConstantScalarValues(); }); } public function isTrue() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isTrue(); }); } public function isFalse() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isFalse(); }); } public function isBoolean() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isBoolean(); }); } public function isFloat() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isFloat(); }); } public function isInteger() : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isInteger(); }); } public function getSmallerType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getSmallerType(); }); } public function getSmallerOrEqualType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getSmallerOrEqualType(); }); } public function getGreaterType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getGreaterType(); }); } public function getGreaterOrEqualType() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getGreaterOrEqualType(); }); } public function isGreaterThan(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) use($otherType) : TrinaryLogic { return $otherType->isSmallerThan($type); }); } public function isGreaterThanOrEqual(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->notBenevolentUnionResults(static function (\PHPStan\Type\Type $type) use($otherType) : TrinaryLogic { return $otherType->isSmallerThanOrEqual($type); }); } public function toBoolean() : \PHPStan\Type\BooleanType { /** @var BooleanType $type */ $type = $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\BooleanType { return $type->toBoolean(); }); return $type; } public function toNumber() : \PHPStan\Type\Type { $type = $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toNumber(); }); return $type; } public function toAbsoluteNumber() : \PHPStan\Type\Type { $type = $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toAbsoluteNumber(); }); return $type; } public function toString() : \PHPStan\Type\Type { $type = $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toString(); }); return $type; } public function toInteger() : \PHPStan\Type\Type { $type = $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toInteger(); }); return $type; } public function toFloat() : \PHPStan\Type\Type { $type = $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toFloat(); }); return $type; } public function toArray() : \PHPStan\Type\Type { $type = $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toArray(); }); return $type; } public function toArrayKey() : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toArrayKey(); }); } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap { $types = TemplateTypeMap::createEmpty(); if ($receivedType instanceof \PHPStan\Type\UnionType) { $myTypes = []; $remainingReceivedTypes = []; foreach ($receivedType->getTypes() as $receivedInnerType) { foreach ($this->types as $type) { if ($type->isSuperTypeOf($receivedInnerType)->yes()) { $types = $types->union($type->inferTemplateTypes($receivedInnerType)); continue 2; } $myTypes[] = $type; } $remainingReceivedTypes[] = $receivedInnerType; } if (count($remainingReceivedTypes) === 0) { return $types; } $receivedType = \PHPStan\Type\TypeCombinator::union(...$remainingReceivedTypes); } else { $myTypes = $this->types; } foreach ($myTypes as $type) { if ($type instanceof TemplateType || $type instanceof GenericClassStringType && $type->getGenericType() instanceof TemplateType) { continue; } $types = $types->union($type->inferTemplateTypes($receivedType)); } if (!$types->isEmpty()) { return $types; } foreach ($myTypes as $type) { $types = $types->union($type->inferTemplateTypes($receivedType)); } return $types; } public function inferTemplateTypesOn(\PHPStan\Type\Type $templateType) : TemplateTypeMap { $types = TemplateTypeMap::createEmpty(); foreach ($this->types as $type) { $types = $types->union($templateType->inferTemplateTypes($type)); } return $types; } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { $references = []; foreach ($this->types as $type) { foreach ($type->getReferencedTemplateTypes($positionVariance) as $reference) { $references[] = $reference; } } return $references; } public function traverse(callable $cb) : \PHPStan\Type\Type { $types = []; $changed = \false; foreach ($this->types as $type) { $newType = $cb($type); if ($type !== $newType) { $changed = \true; } $types[] = $newType; } if ($changed) { return \PHPStan\Type\TypeCombinator::union(...$types); } return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { $types = []; $changed = \false; if (!$right instanceof self) { return $this; } if (count($this->getTypes()) !== count($right->getTypes())) { return $this; } foreach ($this->getSortedTypes() as $i => $leftType) { $rightType = $right->getSortedTypes()[$i]; $newType = $cb($leftType, $rightType); if ($leftType !== $newType) { $changed = \true; } $types[] = $newType; } if ($changed) { return \PHPStan\Type\TypeCombinator::union(...$types); } return $this; } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($typeToRemove) : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::remove($type, $typeToRemove); }); } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return $this->unionTypes(static function (\PHPStan\Type\Type $type) use($exponent) : \PHPStan\Type\Type { return $type->exponentiate($exponent); }); } public function getFiniteTypes() : array { $types = $this->notBenevolentPickFromTypes(static function (\PHPStan\Type\Type $type) { return $type->getFiniteTypes(); }); $uniquedTypes = []; foreach ($types as $type) { $uniquedTypes[md5($type->describe(\PHPStan\Type\VerbosityLevel::cache()))] = $type; } if (count($uniquedTypes) > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return []; } return array_values($uniquedTypes); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['types'], $properties['normalized']); } /** * @param callable(Type $type): TrinaryLogic $getResult */ protected function unionResults(callable $getResult) : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->types, $getResult); } /** * @param callable(Type $type): TrinaryLogic $getResult */ private function notBenevolentUnionResults(callable $getResult) : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->types, $getResult); } /** * @param callable(Type $type): Type $getType */ protected function unionTypes(callable $getType) : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union(...array_map($getType, $this->types)); } /** * @template T of Type * @param callable(Type $type): list $getTypes * @return list * * @deprecated Use pickFromTypes() instead. */ protected function pickTypes(callable $getTypes) : array { return $this->pickFromTypes($getTypes, static function () { return \false; }); } /** * @template T * @param callable(Type $type): list $getValues * @param callable(Type $type): bool $criteria * @return list */ protected function pickFromTypes(callable $getValues, callable $criteria) : array { $values = []; foreach ($this->types as $type) { $innerValues = $getValues($type); if ($innerValues === []) { return []; } foreach ($innerValues as $innerType) { $values[] = $innerType; } } return $values; } public function toPhpDocNode() : TypeNode { return new UnionTypeNode(array_map(static function (\PHPStan\Type\Type $type) { return $type->toPhpDocNode(); }, $this->getSortedTypes())); } /** * @template T * @param callable(Type $type): list $getValues * @return list */ private function notBenevolentPickFromTypes(callable $getValues) : array { $values = []; foreach ($this->types as $type) { $innerValues = $getValues($type); if ($innerValues === []) { return []; } foreach ($innerValues as $innerType) { $values[] = $innerType; } } return $values; } } > */ private static $superTypes = []; /** * @var ?self */ private $cachedParent = null; /** @var self[]|null */ private $cachedInterfaces = null; /** @var array>> */ private static $methods = []; /** @var array>> */ private static $properties = []; /** @var array> */ private static $ancestors = []; /** @var array */ private $currentAncestors = []; /** * @var ?string */ private $cachedDescription = null; /** @var array> */ private static $enumCases = []; /** @api */ public function __construct(string $className, ?\PHPStan\Type\Type $subtractedType = null, ?ClassReflection $classReflection = null) { $this->className = $className; $this->classReflection = $classReflection; if ($subtractedType instanceof \PHPStan\Type\NeverType) { $subtractedType = null; } $this->subtractedType = $subtractedType; } public static function resetCaches() : void { self::$superTypes = []; self::$methods = []; self::$properties = []; self::$ancestors = []; self::$enumCases = []; } private static function createFromReflection(ClassReflection $reflection) : self { if (!$reflection->isGeneric()) { return new \PHPStan\Type\ObjectType($reflection->getName()); } return new GenericObjectType($reflection->getName(), $reflection->typeMapToList($reflection->getActiveTemplateTypeMap()), null, null, $reflection->varianceMapToList($reflection->getCallSiteVarianceMap())); } public function getClassName() : string { return $this->className; } public function hasProperty(string $propertyName) : TrinaryLogic { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } $classHasProperty = \PHPStan\Type\RecursionGuard::run($this, static function () use($classReflection, $propertyName) : bool { return $classReflection->hasProperty($propertyName); }); if ($classHasProperty === \true || $classHasProperty instanceof \PHPStan\Type\ErrorType) { return TrinaryLogic::createYes(); } if ($classReflection->allowsDynamicProperties()) { return TrinaryLogic::createMaybe(); } if (!$classReflection->isFinal()) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { if (!$scope->isInClass()) { $canAccessProperty = 'no'; } else { $canAccessProperty = $scope->getClassReflection()->getName(); } $description = $this->describeCache(); if (isset(self::$properties[$description][$propertyName][$canAccessProperty])) { return self::$properties[$description][$propertyName][$canAccessProperty]; } $nakedClassReflection = $this->getNakedClassReflection(); if ($nakedClassReflection === null) { throw new ClassNotFoundException($this->className); } if ($nakedClassReflection->isEnum()) { if ($propertyName === 'name' || $propertyName === 'value' && $nakedClassReflection->isBackedEnum()) { $properties = []; foreach ($this->getEnumCases() as $enumCase) { $properties[] = $enumCase->getUnresolvedPropertyPrototype($propertyName, $scope); } if (count($properties) > 0) { if (count($properties) === 1) { return $properties[0]; } return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $properties); } } } if (!$nakedClassReflection->hasNativeProperty($propertyName)) { $nakedClassReflection = $this->getClassReflection(); } if ($nakedClassReflection === null) { throw new ClassNotFoundException($this->className); } $property = \PHPStan\Type\RecursionGuard::run($this, static function () use($nakedClassReflection, $propertyName, $scope) { return $nakedClassReflection->getProperty($propertyName, $scope); }); if ($property instanceof \PHPStan\Type\ErrorType) { $property = new DummyPropertyReflection(); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type; }); } $ancestor = $this->getAncestorWithClassName($property->getDeclaringClass()->getName()); $resolvedClassReflection = null; if ($ancestor !== null && $ancestor->hasProperty($propertyName)->yes()) { $resolvedClassReflection = $ancestor->getClassReflection(); if ($ancestor !== $this) { $property = $ancestor->getUnresolvedPropertyPrototype($propertyName, $scope)->getNakedProperty(); } } if ($resolvedClassReflection === null) { $resolvedClassReflection = $property->getDeclaringClass(); } return self::$properties[$description][$propertyName][$canAccessProperty] = new CalledOnTypeUnresolvedPropertyPrototypeReflection($property, $resolvedClassReflection, \true, $this); } /** * @deprecated Not in use anymore. */ public function getPropertyWithoutTransformingStatic(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { $classReflection = $this->getNakedClassReflection(); if ($classReflection === null) { throw new ClassNotFoundException($this->className); } if (!$classReflection->hasProperty($propertyName)) { $classReflection = $this->getClassReflection(); } if ($classReflection === null) { throw new ClassNotFoundException($this->className); } return $classReflection->getProperty($propertyName, $scope); } /** * @return string[] */ public function getReferencedClasses() : array { return [$this->className]; } public function getObjectClassNames() : array { if ($this->className === '') { return []; } return [$this->className]; } public function getObjectClassReflections() : array { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return []; } return [$classReflection]; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\StaticType) { return $this->checkSubclassAcceptability($type->getClassName()); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } if ($type instanceof \PHPStan\Type\ClosureType) { return new \PHPStan\Type\AcceptsResult($this->isInstanceOf(Closure::class), []); } if ($type instanceof \PHPStan\Type\ObjectWithoutClassType) { return \PHPStan\Type\AcceptsResult::createMaybe(); } $thatClassNames = $type->getObjectClassNames(); if (count($thatClassNames) > 1) { throw new ShouldNotHappenException(); } if ($thatClassNames === []) { return \PHPStan\Type\AcceptsResult::createNo(); } return $this->checkSubclassAcceptability($thatClassNames[0]); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { $thatClassNames = $type->getObjectClassNames(); if (!$type instanceof \PHPStan\Type\CompoundType && $thatClassNames === [] && !$type instanceof \PHPStan\Type\ObjectWithoutClassType) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } $thisDescription = $this->describeCache(); if ($type instanceof self) { $description = $type->describeCache(); } else { $description = $type->describe(\PHPStan\Type\VerbosityLevel::cache()); } if (isset(self::$superTypes[$thisDescription][$description])) { return self::$superTypes[$thisDescription][$description]; } if ($type instanceof \PHPStan\Type\CompoundType) { return self::$superTypes[$thisDescription][$description] = $type->isSubTypeOfWithReason($this); } if ($type instanceof \PHPStan\Type\ClosureType) { return self::$superTypes[$thisDescription][$description] = new \PHPStan\Type\IsSuperTypeOfResult($this->isInstanceOf(Closure::class), []); } if ($type instanceof \PHPStan\Type\ObjectWithoutClassType) { if ($type->getSubtractedType() !== null) { $isSuperType = $type->getSubtractedType()->isSuperTypeOf($this); if ($isSuperType->yes()) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createNo(); } } return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } $transformResult = static function (\PHPStan\Type\IsSuperTypeOfResult $result) { return $result; }; if ($this->subtractedType !== null) { $isSuperType = $this->subtractedType->isSuperTypeOfWithReason($type); if ($isSuperType->yes()) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createNo(); } if ($isSuperType->maybe()) { $transformResult = static function (\PHPStan\Type\IsSuperTypeOfResult $result) { return $result->and(\PHPStan\Type\IsSuperTypeOfResult::createMaybe()); }; } } if ($type instanceof \PHPStan\Type\SubtractableType && $type->getSubtractedType() !== null) { $isSuperType = $type->getSubtractedType()->isSuperTypeOfWithReason($this); if ($isSuperType->yes()) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createNo(); } } $thisClassName = $this->className; if (count($thatClassNames) > 1) { throw new ShouldNotHappenException(); } if ($thatClassNames[0] === $thisClassName) { return $transformResult(\PHPStan\Type\IsSuperTypeOfResult::createYes()); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); $thisClassReflection = $this->getClassReflection(); if ($thisClassReflection === null || !$reflectionProvider->hasClass($thatClassNames[0])) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } $thatClassReflection = $reflectionProvider->getClass($thatClassNames[0]); if ($thisClassReflection->isTrait() || $thatClassReflection->isTrait()) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } if ($thisClassReflection->getName() === $thatClassReflection->getName()) { return self::$superTypes[$thisDescription][$description] = $transformResult(\PHPStan\Type\IsSuperTypeOfResult::createYes()); } if ($thatClassReflection->isSubclassOf($thisClassName)) { return self::$superTypes[$thisDescription][$description] = $transformResult(\PHPStan\Type\IsSuperTypeOfResult::createYes()); } if ($thisClassReflection->isSubclassOf($thatClassNames[0])) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($thisClassReflection->isInterface() && !$thatClassReflection->getNativeReflection()->isFinal()) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($thatClassReflection->isInterface() && !$thisClassReflection->getNativeReflection()->isFinal()) { return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } return self::$superTypes[$thisDescription][$description] = \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type) : bool { if (!$type instanceof self) { return \false; } if ($type instanceof EnumCaseObjectType) { return \false; } if ($this->className !== $type->className) { return \false; } if ($this->subtractedType === null) { return $type->subtractedType === null; } if ($type->subtractedType === null) { return \false; } return $this->subtractedType->equals($type->subtractedType); } private function checkSubclassAcceptability(string $thatClass) : \PHPStan\Type\AcceptsResult { if ($this->className === $thatClass) { return \PHPStan\Type\AcceptsResult::createYes(); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if ($this->getClassReflection() === null || !$reflectionProvider->hasClass($thatClass)) { return \PHPStan\Type\AcceptsResult::createNo(); } $thisReflection = $this->getClassReflection(); $thatReflection = $reflectionProvider->getClass($thatClass); if ($thisReflection->getName() === $thatReflection->getName()) { // class alias return \PHPStan\Type\AcceptsResult::createYes(); } if ($thisReflection->isInterface() && $thatReflection->isInterface()) { return \PHPStan\Type\AcceptsResult::createFromBoolean($thatReflection->implementsInterface($thisReflection->getName())); } return \PHPStan\Type\AcceptsResult::createFromBoolean($thatReflection->isSubclassOf($thisReflection->getName())); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { $preciseNameCallback = function () : string { $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (!$reflectionProvider->hasClass($this->className)) { return $this->className; } return $reflectionProvider->getClassName($this->className); }; $preciseWithSubtracted = function () use($level) : string { $description = $this->className; if ($this->subtractedType !== null) { $description .= $this->subtractedType instanceof \PHPStan\Type\UnionType ? sprintf('~(%s)', $this->subtractedType->describe($level)) : sprintf('~%s', $this->subtractedType->describe($level)); } return $description; }; return $level->handle($preciseNameCallback, $preciseNameCallback, $preciseWithSubtracted, function () use($preciseWithSubtracted) : string { $reflection = $this->classReflection; $line = ''; if ($reflection !== null) { $line .= '-'; $line .= (string) $reflection->getNativeReflection()->getStartLine(); $line .= '-'; } return $preciseWithSubtracted() . '-' . static::class . '-' . $line . $this->describeAdditionalCacheKey(); }); } protected function describeAdditionalCacheKey() : string { return ''; } private function describeCache() : string { if ($this->cachedDescription !== null) { return $this->cachedDescription; } if (static::class !== self::class) { return $this->cachedDescription = $this->describe(\PHPStan\Type\VerbosityLevel::cache()); } $description = $this->className; if ($this instanceof GenericObjectType) { $description .= '<'; $typeDescriptions = []; foreach ($this->getTypes() as $type) { $typeDescriptions[] = $type->describe(\PHPStan\Type\VerbosityLevel::cache()); } $description .= '<' . implode(', ', $typeDescriptions) . '>'; } if ($this->subtractedType !== null) { $description .= $this->subtractedType instanceof \PHPStan\Type\UnionType ? sprintf('~(%s)', $this->subtractedType->describe(\PHPStan\Type\VerbosityLevel::cache())) : sprintf('~%s', $this->subtractedType->describe(\PHPStan\Type\VerbosityLevel::cache())); } $reflection = $this->classReflection; if ($reflection !== null) { $description .= '-'; $description .= (string) $reflection->getNativeReflection()->getStartLine(); $description .= '-'; } return $this->cachedDescription = $description; } public function toNumber() : \PHPStan\Type\Type { if ($this->isInstanceOf('SimpleXMLElement')->yes()) { return new \PHPStan\Type\UnionType([new \PHPStan\Type\FloatType(), new \PHPStan\Type\IntegerType()]); } return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return $this->toNumber()->toAbsoluteNumber(); } public function toInteger() : \PHPStan\Type\Type { if ($this->isInstanceOf('SimpleXMLElement')->yes()) { return new \PHPStan\Type\IntegerType(); } if (in_array($this->getClassName(), ['CurlHandle', 'CurlMultiHandle'], \true)) { return new \PHPStan\Type\IntegerType(); } return new \PHPStan\Type\ErrorType(); } public function toFloat() : \PHPStan\Type\Type { if ($this->isInstanceOf('SimpleXMLElement')->yes()) { return new \PHPStan\Type\FloatType(); } return new \PHPStan\Type\ErrorType(); } public function toString() : \PHPStan\Type\Type { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return new \PHPStan\Type\ErrorType(); } if ($classReflection->hasNativeMethod('__toString')) { return $this->getMethod('__toString', new OutOfClassScope())->getOnlyVariant()->getReturnType(); } return new \PHPStan\Type\ErrorType(); } public function toArray() : \PHPStan\Type\Type { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (!$classReflection->getNativeReflection()->isUserDefined() || $classReflection->is(ArrayObject::class) || UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate($reflectionProvider, Broker::getInstance()->getUniversalObjectCratesClasses(), $classReflection)) { return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()); } $arrayKeys = []; $arrayValues = []; $isFinal = $classReflection->isFinal(); do { foreach ($classReflection->getNativeReflection()->getProperties() as $nativeProperty) { if ($nativeProperty->isStatic()) { continue; } $declaringClass = $reflectionProvider->getClass($nativeProperty->getDeclaringClass()->getName()); $property = $declaringClass->getNativeProperty($nativeProperty->getName()); $keyName = $nativeProperty->getName(); if ($nativeProperty->isPrivate()) { $keyName = sprintf("\x00%s\x00%s", $declaringClass->getName(), $keyName); } elseif ($nativeProperty->isProtected()) { $keyName = sprintf("\x00*\x00%s", $keyName); } $arrayKeys[] = new ConstantStringType($keyName); $arrayValues[] = $property->getReadableType(); } $classReflection = $classReflection->getParentClass(); } while ($classReflection !== null); if (!$isFinal && count($arrayKeys) === 0) { return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()); } return new ConstantArrayType($arrayKeys, $arrayValues); } public function toArrayKey() : \PHPStan\Type\Type { return $this->toString(); } public function toBoolean() : \PHPStan\Type\BooleanType { if ($this->isInstanceOf('SimpleXMLElement')->yes()) { return new \PHPStan\Type\BooleanType(); } return new ConstantBooleanType(\true); } public function isObject() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isEnum() : TrinaryLogic { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createFromBoolean($classReflection->isEnum()); } public function canAccessProperties() : TrinaryLogic { return TrinaryLogic::createYes(); } public function canCallMethods() : TrinaryLogic { if (strtolower($this->className) === 'stdclass') { return TrinaryLogic::createNo(); } return TrinaryLogic::createYes(); } public function hasMethod(string $methodName) : TrinaryLogic { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } if ($classReflection->hasMethod($methodName)) { return TrinaryLogic::createYes(); } if ($classReflection->isFinal()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { if (!$scope->isInClass()) { $canCallMethod = 'no'; } else { $canCallMethod = $scope->getClassReflection()->getName(); } $description = $this->describeCache(); if (isset(self::$methods[$description][$methodName][$canCallMethod])) { return self::$methods[$description][$methodName][$canCallMethod]; } $nakedClassReflection = $this->getNakedClassReflection(); if ($nakedClassReflection === null) { throw new ClassNotFoundException($this->className); } if (!$nakedClassReflection->hasNativeMethod($methodName)) { $nakedClassReflection = $this->getClassReflection(); } if ($nakedClassReflection === null) { throw new ClassNotFoundException($this->className); } $method = $nakedClassReflection->getMethod($methodName, $scope); $ancestor = $this->getAncestorWithClassName($method->getDeclaringClass()->getName()); $resolvedClassReflection = null; if ($ancestor !== null) { $resolvedClassReflection = $ancestor->getClassReflection(); if ($ancestor !== $this) { $method = $ancestor->getUnresolvedMethodPrototype($methodName, $scope)->getNakedMethod(); } } if ($resolvedClassReflection === null) { $resolvedClassReflection = $method->getDeclaringClass(); } return self::$methods[$description][$methodName][$canCallMethod] = new CalledOnTypeUnresolvedMethodPrototypeReflection($method, $resolvedClassReflection, \true, $this); } public function canAccessConstants() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasConstant(string $constantName) : TrinaryLogic { $class = $this->getClassReflection(); if ($class === null) { return TrinaryLogic::createNo(); } return TrinaryLogic::createFromBoolean($class->hasConstant($constantName)); } public function getConstant(string $constantName) : ConstantReflection { $class = $this->getClassReflection(); if ($class === null) { throw new ClassNotFoundException($this->className); } return $class->getConstant($constantName); } public function getTemplateType(string $ancestorClassName, string $templateTypeName) : \PHPStan\Type\Type { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return new \PHPStan\Type\ErrorType(); } $ancestorClassReflection = $classReflection->getAncestorWithClassName($ancestorClassName); if ($ancestorClassReflection === null) { return new \PHPStan\Type\ErrorType(); } $activeTemplateTypeMap = $ancestorClassReflection->getPossiblyIncompleteActiveTemplateTypeMap(); $type = $activeTemplateTypeMap->getType($templateTypeName); if ($type === null) { return new \PHPStan\Type\ErrorType(); } if ($type instanceof \PHPStan\Type\ErrorType) { $templateTypeMap = $ancestorClassReflection->getTemplateTypeMap(); $templateType = $templateTypeMap->getType($templateTypeName); if ($templateType === null) { return $type; } $bound = TemplateTypeHelper::resolveToBounds($templateType); if ($bound instanceof \PHPStan\Type\MixedType && $bound->isExplicitMixed()) { return new \PHPStan\Type\MixedType(\false); } return TemplateTypeHelper::resolveToDefaults($templateType); } return $type; } public function getConstantStrings() : array { return []; } public function isIterable() : TrinaryLogic { return $this->isInstanceOf(Traversable::class); } public function isIterableAtLeastOnce() : TrinaryLogic { return $this->isInstanceOf(Traversable::class)->and(TrinaryLogic::createMaybe()); } public function getArraySize() : \PHPStan\Type\Type { if ($this->isInstanceOf(Countable::class)->no()) { return new \PHPStan\Type\ErrorType(); } return \PHPStan\Type\IntegerRangeType::fromInterval(0, null); } public function getIterableKeyType() : \PHPStan\Type\Type { $isTraversable = \false; if ($this->isInstanceOf(IteratorAggregate::class)->yes()) { $keyType = \PHPStan\Type\RecursionGuard::run($this, function () : \PHPStan\Type\Type { return $this->getMethod('getIterator', new OutOfClassScope())->getOnlyVariant()->getReturnType()->getIterableKeyType(); }); $isTraversable = \true; if (!$keyType instanceof \PHPStan\Type\MixedType || $keyType->isExplicitMixed()) { return $keyType; } } $extraOffsetAccessible = $this->isExtraOffsetAccessibleClass()->yes(); if (!$extraOffsetAccessible && $this->isInstanceOf(Traversable::class)->yes()) { $isTraversable = \true; $tKey = $this->getTemplateType(Traversable::class, 'TKey'); if (!$tKey instanceof \PHPStan\Type\ErrorType) { if (!$tKey instanceof \PHPStan\Type\MixedType || $tKey->isExplicitMixed()) { return $tKey; } } } if ($this->isInstanceOf(Iterator::class)->yes()) { return \PHPStan\Type\RecursionGuard::run($this, function () : \PHPStan\Type\Type { return $this->getMethod('key', new OutOfClassScope())->getOnlyVariant()->getReturnType(); }); } if ($extraOffsetAccessible) { return new \PHPStan\Type\MixedType(\true); } if ($isTraversable) { return new \PHPStan\Type\MixedType(); } return new \PHPStan\Type\ErrorType(); } public function getFirstIterableKeyType() : \PHPStan\Type\Type { return $this->getIterableKeyType(); } public function getLastIterableKeyType() : \PHPStan\Type\Type { return $this->getIterableKeyType(); } public function getIterableValueType() : \PHPStan\Type\Type { $isTraversable = \false; if ($this->isInstanceOf(IteratorAggregate::class)->yes()) { $valueType = \PHPStan\Type\RecursionGuard::run($this, function () : \PHPStan\Type\Type { return $this->getMethod('getIterator', new OutOfClassScope())->getOnlyVariant()->getReturnType()->getIterableValueType(); }); $isTraversable = \true; if (!$valueType instanceof \PHPStan\Type\MixedType || $valueType->isExplicitMixed()) { return $valueType; } } $extraOffsetAccessible = $this->isExtraOffsetAccessibleClass()->yes(); if (!$extraOffsetAccessible && $this->isInstanceOf(Traversable::class)->yes()) { $isTraversable = \true; $tValue = $this->getTemplateType(Traversable::class, 'TValue'); if (!$tValue instanceof \PHPStan\Type\ErrorType) { if (!$tValue instanceof \PHPStan\Type\MixedType || $tValue->isExplicitMixed()) { return $tValue; } } } if ($this->isInstanceOf(Iterator::class)->yes()) { return \PHPStan\Type\RecursionGuard::run($this, function () : \PHPStan\Type\Type { return $this->getMethod('current', new OutOfClassScope())->getOnlyVariant()->getReturnType(); }); } if ($extraOffsetAccessible) { return new \PHPStan\Type\MixedType(\true); } if ($isTraversable) { return new \PHPStan\Type\MixedType(); } return new \PHPStan\Type\ErrorType(); } public function getFirstIterableValueType() : \PHPStan\Type\Type { return $this->getIterableValueType(); } public function getLastIterableValueType() : \PHPStan\Type\Type { return $this->getIterableValueType(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return $this; } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { if ($type->isTrue()->yes()) { return new ConstantBooleanType(\true); } return $type->isFalse()->yes() ? new ConstantBooleanType(\false) : new \PHPStan\Type\BooleanType(); } private function isExtraOffsetAccessibleClass() : TrinaryLogic { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } foreach (self::EXTRA_OFFSET_CLASSES as $extraOffsetClass) { if ($classReflection->getName() === $extraOffsetClass) { return TrinaryLogic::createYes(); } if ($classReflection->isSubclassOf($extraOffsetClass)) { return TrinaryLogic::createYes(); } } if ($classReflection->isInterface()) { return TrinaryLogic::createMaybe(); } if ($classReflection->isFinal()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function isOffsetAccessible() : TrinaryLogic { return $this->isInstanceOf(ArrayAccess::class)->or($this->isExtraOffsetAccessibleClass()); } public function isOffsetAccessLegal() : TrinaryLogic { return $this->isOffsetAccessible(); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { if ($this->isInstanceOf(ArrayAccess::class)->yes()) { $acceptedOffsetType = \PHPStan\Type\RecursionGuard::run($this, function () : \PHPStan\Type\Type { $parameters = $this->getMethod('offsetSet', new OutOfClassScope())->getOnlyVariant()->getParameters(); if (count($parameters) < 2) { throw new ShouldNotHappenException(sprintf('Method %s::%s() has less than 2 parameters.', $this->className, 'offsetSet')); } $offsetParameter = $parameters[0]; return $offsetParameter->getType(); }); if ($acceptedOffsetType->isSuperTypeOf($offsetType)->no()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } return $this->isExtraOffsetAccessibleClass()->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { if (!$this->isExtraOffsetAccessibleClass()->no()) { return new \PHPStan\Type\MixedType(); } if ($this->isInstanceOf(ArrayAccess::class)->yes()) { return \PHPStan\Type\RecursionGuard::run($this, function () : \PHPStan\Type\Type { return $this->getMethod('offsetGet', new OutOfClassScope())->getOnlyVariant()->getReturnType(); }); } return new \PHPStan\Type\ErrorType(); } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { if ($this->isOffsetAccessible()->no()) { return new \PHPStan\Type\ErrorType(); } if ($this->isInstanceOf(ArrayAccess::class)->yes()) { $acceptedValueType = new \PHPStan\Type\NeverType(); $acceptedOffsetType = \PHPStan\Type\RecursionGuard::run($this, function () use(&$acceptedValueType) : \PHPStan\Type\Type { $parameters = $this->getMethod('offsetSet', new OutOfClassScope())->getOnlyVariant()->getParameters(); if (count($parameters) < 2) { throw new ShouldNotHappenException(sprintf('Method %s::%s() has less than 2 parameters.', $this->className, 'offsetSet')); } $offsetParameter = $parameters[0]; $acceptedValueType = $parameters[1]->getType(); return $offsetParameter->getType(); }); if ($offsetType === null) { $offsetType = new \PHPStan\Type\NullType(); } if (!$offsetType instanceof \PHPStan\Type\MixedType && !$acceptedOffsetType->isSuperTypeOf($offsetType)->yes() || !$valueType instanceof \PHPStan\Type\MixedType && !$acceptedValueType->isSuperTypeOf($valueType)->yes()) { return new \PHPStan\Type\ErrorType(); } } // in the future we may return intersection of $this and OffsetAccessibleType() return $this; } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { if ($this->isOffsetAccessible()->no()) { return new \PHPStan\Type\ErrorType(); } return $this; } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { if ($this->isOffsetAccessible()->no()) { return new \PHPStan\Type\ErrorType(); } return $this; } public function getEnumCases() : array { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return []; } if (!$classReflection->isEnum()) { return []; } $cacheKey = $this->describeCache(); if (array_key_exists($cacheKey, self::$enumCases)) { return self::$enumCases[$cacheKey]; } $className = $classReflection->getName(); if ($this->subtractedType !== null) { $subtractedEnumCaseNames = []; foreach ($this->subtractedType->getEnumCases() as $subtractedCase) { $subtractedEnumCaseNames[$subtractedCase->getEnumCaseName()] = \true; } $cases = []; foreach ($classReflection->getEnumCases() as $enumCase) { if (array_key_exists($enumCase->getName(), $subtractedEnumCaseNames)) { continue; } $cases[] = new EnumCaseObjectType($className, $enumCase->getName(), $classReflection); } } else { $cases = []; foreach ($classReflection->getEnumCases() as $enumCase) { $cases[] = new EnumCaseObjectType($className, $enumCase->getName(), $classReflection); } } return self::$enumCases[$cacheKey] = $cases; } public function isCallable() : TrinaryLogic { $parametersAcceptors = \PHPStan\Type\RecursionGuard::run($this, function () { return $this->findCallableParametersAcceptors(); }); if ($parametersAcceptors === null) { return TrinaryLogic::createNo(); } if ($parametersAcceptors instanceof \PHPStan\Type\ErrorType) { return TrinaryLogic::createNo(); } if (count($parametersAcceptors) === 1 && $parametersAcceptors[0] instanceof TrivialParametersAcceptor) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createYes(); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { if ($this->className === Closure::class) { return [new TrivialParametersAcceptor('Closure')]; } $parametersAcceptors = $this->findCallableParametersAcceptors(); if ($parametersAcceptors === null) { throw new ShouldNotHappenException(); } return $parametersAcceptors; } /** * @return CallableParametersAcceptor[]|null */ private function findCallableParametersAcceptors() : ?array { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return [new TrivialParametersAcceptor()]; } if ($classReflection->hasNativeMethod('__invoke')) { $method = $this->getMethod('__invoke', new OutOfClassScope()); return FunctionCallableVariant::createFromVariants($method, $method->getVariants()); } if (!$classReflection->getNativeReflection()->isFinal()) { return [new TrivialParametersAcceptor()]; } return null; } public function isCloneable() : TrinaryLogic { return TrinaryLogic::createYes(); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['className'], $properties['subtractedType'] ?? null); } public function isInstanceOf(string $className) : TrinaryLogic { $classReflection = $this->getClassReflection(); if ($classReflection === null) { return TrinaryLogic::createMaybe(); } if ($classReflection->getName() === $className || $classReflection->isSubclassOf($className)) { return TrinaryLogic::createYes(); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if ($reflectionProvider->hasClass($className)) { $thatClassReflection = $reflectionProvider->getClass($className); if ($thatClassReflection->isFinal()) { return TrinaryLogic::createNo(); } } if ($classReflection->isInterface()) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); } public function subtract(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { if ($this->subtractedType !== null) { $type = \PHPStan\Type\TypeCombinator::union($this->subtractedType, $type); } return $this->changeSubtractedType($type); } public function getTypeWithoutSubtractedType() : \PHPStan\Type\Type { return $this->changeSubtractedType(null); } public function changeSubtractedType(?\PHPStan\Type\Type $subtractedType) : \PHPStan\Type\Type { if ($subtractedType !== null) { $classReflection = $this->getClassReflection(); $allowedSubTypes = $classReflection !== null ? $classReflection->getAllowedSubTypes() : null; if ($allowedSubTypes !== null) { $preciseVerbosity = \PHPStan\Type\VerbosityLevel::precise(); $originalAllowedSubTypes = $allowedSubTypes; $subtractedSubTypes = []; $subtractedTypes = \PHPStan\Type\TypeUtils::flattenTypes($subtractedType); foreach ($subtractedTypes as $subType) { foreach ($allowedSubTypes as $key => $allowedSubType) { if ($subType->equals($allowedSubType)) { $description = $allowedSubType->describe($preciseVerbosity); $subtractedSubTypes[$description] = $subType; unset($allowedSubTypes[$key]); continue 2; } } return new self($this->className, $subtractedType); } if (count($allowedSubTypes) === 1) { return array_values($allowedSubTypes)[0]; } $subtractedSubTypes = array_values($subtractedSubTypes); $subtractedSubTypesCount = count($subtractedSubTypes); if ($subtractedSubTypesCount === count($originalAllowedSubTypes)) { return new \PHPStan\Type\NeverType(); } if ($subtractedSubTypesCount === 0) { return new self($this->className); } if ($subtractedSubTypesCount === 1) { return new self($this->className, $subtractedSubTypes[0]); } return new self($this->className, new \PHPStan\Type\UnionType($subtractedSubTypes)); } } if ($this->subtractedType === null && $subtractedType === null) { return $this; } return new self($this->className, $subtractedType); } public function getSubtractedType() : ?\PHPStan\Type\Type { return $this->subtractedType; } public function traverse(callable $cb) : \PHPStan\Type\Type { $subtractedType = $this->subtractedType !== null ? $cb($this->subtractedType) : null; if ($subtractedType !== $this->subtractedType) { return new self($this->className, $subtractedType); } return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if ($this->subtractedType === null) { return $this; } return new self($this->className); } public function getNakedClassReflection() : ?ClassReflection { if ($this->classReflection !== null) { return $this->classReflection; } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (!$reflectionProvider->hasClass($this->className)) { return null; } return $reflectionProvider->getClass($this->className); } public function getClassReflection() : ?ClassReflection { if ($this->classReflection !== null) { return $this->classReflection; } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (!$reflectionProvider->hasClass($this->className)) { return null; } $classReflection = $reflectionProvider->getClass($this->className); if ($classReflection->isGeneric()) { return $classReflection->withTypes(array_values($classReflection->getTemplateTypeMap()->map(static function () : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); })->getTypes())); } return $classReflection; } /** * @return self|null */ public function getAncestorWithClassName(string $className) : ?\PHPStan\Type\TypeWithClassName { if ($this->className === $className) { return $this; } if ($this->classReflection !== null && $className === $this->classReflection->getName()) { return $this; } if (array_key_exists($className, $this->currentAncestors)) { return $this->currentAncestors[$className]; } $description = $this->describeCache(); if (array_key_exists($description, self::$ancestors) && array_key_exists($className, self::$ancestors[$description])) { return self::$ancestors[$description][$className]; } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (!$reflectionProvider->hasClass($className)) { return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = null; } $theirReflection = $reflectionProvider->getClass($className); $thisReflection = $this->getClassReflection(); if ($thisReflection === null) { return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = null; } if ($theirReflection->getName() === $thisReflection->getName()) { return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = $this; } foreach ($this->getInterfaces() as $interface) { $ancestor = $interface->getAncestorWithClassName($className); if ($ancestor !== null) { return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = $ancestor; } } $parent = $this->getParent(); if ($parent !== null) { $ancestor = $parent->getAncestorWithClassName($className); if ($ancestor !== null) { return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = $ancestor; } } return self::$ancestors[$description][$className] = $this->currentAncestors[$className] = null; } private function getParent() : ?\PHPStan\Type\ObjectType { if ($this->cachedParent !== null) { return $this->cachedParent; } $thisReflection = $this->getClassReflection(); if ($thisReflection === null) { return null; } $parentReflection = $thisReflection->getParentClass(); if ($parentReflection === null) { return null; } return $this->cachedParent = self::createFromReflection($parentReflection); } /** @return ObjectType[] */ private function getInterfaces() : array { if ($this->cachedInterfaces !== null) { return $this->cachedInterfaces; } $thisReflection = $this->getClassReflection(); if ($thisReflection === null) { return $this->cachedInterfaces = []; } return $this->cachedInterfaces = array_map(static function (ClassReflection $interfaceReflection) : self { return self::createFromReflection($interfaceReflection); }, $thisReflection->getInterfaces()); } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { if ($this->getClassName() === DateTimeInterface::class) { if ($typeToRemove instanceof \PHPStan\Type\ObjectType && $typeToRemove->getClassName() === DateTimeImmutable::class) { return new \PHPStan\Type\ObjectType(DateTime::class); } if ($typeToRemove instanceof \PHPStan\Type\ObjectType && $typeToRemove->getClassName() === DateTime::class) { return new \PHPStan\Type\ObjectType(DateTimeImmutable::class); } } if ($this->getClassName() === Throwable::class) { if ($typeToRemove instanceof \PHPStan\Type\ObjectType && $typeToRemove->getClassName() === Error::class) { return new \PHPStan\Type\ObjectType(Exception::class); // phpcs:ignore SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException } if ($typeToRemove instanceof \PHPStan\Type\ObjectType && $typeToRemove->getClassName() === Exception::class) { // phpcs:ignore SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException return new \PHPStan\Type\ObjectType(Error::class); } } if ($this->isSuperTypeOf($typeToRemove)->yes()) { return $this->subtract($typeToRemove); } return null; } public function getFiniteTypes() : array { return $this->getEnumCases(); } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { $object = new \PHPStan\Type\ObjectWithoutClassType(); if (!$exponent instanceof \PHPStan\Type\NeverType && !$object->isSuperTypeOf($this)->no() && !$object->isSuperTypeOf($exponent)->no()) { return \PHPStan\Type\TypeCombinator::union($this, $exponent); } return new \PHPStan\Type\ErrorType(); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode($this->getClassName()); } } parameterName = $parameterName; $this->target = $target; $this->if = $if; $this->else = $else; $this->negated = $negated; } public function getParameterName() : string { return $this->parameterName; } public function getTarget() : \PHPStan\Type\Type { return $this->target; } public function getIf() : \PHPStan\Type\Type { return $this->if; } public function getElse() : \PHPStan\Type\Type { return $this->else; } public function isNegated() : bool { return $this->negated; } public function changeParameterName(string $parameterName) : self { return new self($parameterName, $this->target, $this->if, $this->else, $this->negated); } public function toConditional(\PHPStan\Type\Type $subject) : \PHPStan\Type\Type { return new \PHPStan\Type\ConditionalType($subject, $this->target, $this->if, $this->else, $this->negated); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return $this->if->isSuperTypeOfWithReason($type->if)->and($this->else->isSuperTypeOfWithReason($type->else)); } return $this->isSuperTypeOfDefault($type); } public function getReferencedClasses() : array { return array_merge($this->target->getReferencedClasses(), $this->if->getReferencedClasses(), $this->else->getReferencedClasses()); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { return array_merge($this->target->getReferencedTemplateTypes($positionVariance), $this->if->getReferencedTemplateTypes($positionVariance), $this->else->getReferencedTemplateTypes($positionVariance)); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self && $this->parameterName === $type->parameterName && $this->target->equals($type->target) && $this->if->equals($type->if) && $this->else->equals($type->else); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return sprintf('(%s %s %s ? %s : %s)', $this->parameterName, $this->negated ? 'is not' : 'is', $this->target->describe($level), $this->if->describe($level), $this->else->describe($level)); } public function isResolvable() : bool { return \false; } protected function getResult() : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union($this->if, $this->else); } public function traverse(callable $cb) : \PHPStan\Type\Type { $target = $cb($this->target); $if = $cb($this->if); $else = $cb($this->else); if ($this->target === $target && $this->if === $if && $this->else === $else) { return $this; } return new self($this->parameterName, $target, $if, $else, $this->negated); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if (!$right instanceof self) { return $this; } $target = $cb($this->target, $right->target); $if = $cb($this->if, $right->if); $else = $cb($this->else, $right->else); if ($this->target === $target && $this->if === $if && $this->else === $else) { return $this; } return new self($this->parameterName, $target, $if, $else, $this->negated); } public function toPhpDocNode() : TypeNode { return new ConditionalTypeForParameterNode($this->parameterName, $this->target->toPhpDocNode(), $this->if->toPhpDocNode(), $this->else->toPhpDocNode(), $this->negated); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['parameterName'], $properties['target'], $properties['if'], $properties['else'], $properties['negated']); } } type = $type; } public function getDeclaringClass() : ClassReflection { $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); return $reflectionProvider->getClass(stdClass::class); } public function isStatic() : bool { return \false; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getDocComment() : ?string { return null; } public function getReadableType() : \PHPStan\Type\Type { return $this->type; } public function getWritableType() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function canChangeTypeAfterAssignment() : bool { return \false; } public function isReadable() : bool { return \true; } public function isWritable() : bool { return \false; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription() : ?string { return null; } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } } castsNumbersToStringsOnLooseComparison()) { $isNumber = new \PHPStan\Type\UnionType([new \PHPStan\Type\IntegerType(), new \PHPStan\Type\FloatType()]); if ($leftType->isString()->yes() && $leftType->isNumericString()->no() && $isNumber->isSuperTypeOf($rightType)->yes()) { $stringValue = (string) $rightType->getValue(); return new ConstantBooleanType($stringValue === $leftType->getValue()); } if ($rightType->isString()->yes() && $rightType->isNumericString()->no() && $isNumber->isSuperTypeOf($leftType)->yes()) { $stringValue = (string) $leftType->getValue(); return new ConstantBooleanType($stringValue === $rightType->getValue()); } } else { if ($leftType->isString()->yes() && $leftType->isNumericString()->no() && $rightType->isFloat()->yes()) { $numericPart = (float) $leftType->getValue(); return new ConstantBooleanType($numericPart === $rightType->getValue()); } if ($rightType->isString()->yes() && $rightType->isNumericString()->no() && $leftType->isFloat()->yes()) { $numericPart = (float) $rightType->getValue(); return new ConstantBooleanType($numericPart === $leftType->getValue()); } if ($leftType->isString()->yes() && $leftType->isNumericString()->no() && $rightType->isInteger()->yes()) { $numericPart = (int) $leftType->getValue(); return new ConstantBooleanType($numericPart === $rightType->getValue()); } if ($rightType->isString()->yes() && $rightType->isNumericString()->no() && $leftType->isInteger()->yes()) { $numericPart = (int) $rightType->getValue(); return new ConstantBooleanType($numericPart === $leftType->getValue()); } } // @phpstan-ignore equal.notAllowed return new ConstantBooleanType($leftType->getValue() == $rightType->getValue()); // phpcs:ignore } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } $isArray = $type->isArray(); $isList = $type->isList(); return new AcceptsResult($isArray->and($isList), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } return new IsSuperTypeOfResult($type->isArray()->and($type->isList()), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } return (new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isList()), []))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self; } public function describe(VerbosityLevel $level) : string { return 'list'; } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return $this->getIterableKeyType()->isSuperTypeOf($offsetType)->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(Type $offsetType) : Type { return new MixedType(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { if ($offsetType === null || (new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()) { return $this; } return new ErrorType(); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { if ((new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()) { return $this; } return new ErrorType(); } public function unsetOffset(Type $offsetType) : Type { if ($this->hasOffsetValueType($offsetType)->no()) { return $this; } return new ErrorType(); } public function getKeysArray() : Type { return $this; } public function getValuesArray() : Type { return $this; } public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys) : Type { return $this; } public function fillKeysArray(Type $valueType) : Type { return new MixedType(); } public function flipArray() : Type { return new MixedType(); } public function intersectKeyArray(Type $otherArraysType) : Type { if ($otherArraysType->isList()->yes()) { return $this; } return new MixedType(); } public function popArray() : Type { return $this; } public function reverseArray(TrinaryLogic $preserveKeys) : Type { if ($preserveKeys->no()) { return $this; } return new MixedType(); } public function searchArray(Type $needleType) : Type { return new MixedType(); } public function shiftArray() : Type { return $this; } public function shuffleArray() : Type { return $this; } public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys) : Type { if ($preserveKeys->no()) { return $this; } if ((new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()) { return $this; } return new MixedType(); } public function isIterable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getArraySize() : Type { return IntegerRangeType::fromInterval(0, null); } public function getIterableKeyType() : Type { return IntegerRangeType::fromInterval(0, null); } public function getFirstIterableKeyType() : Type { return new ConstantIntegerType(0); } public function getLastIterableKeyType() : Type { return $this->getIterableKeyType(); } public function getIterableValueType() : Type { return new MixedType(); } public function getFirstIterableValueType() : Type { return new MixedType(); } public function getLastIterableValueType() : Type { return new MixedType(); } public function isArray() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isConstantArray() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isOversizedArray() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isList() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : Type { return new ErrorType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return TypeCombinator::union(new ConstantIntegerType(0), new ConstantIntegerType(1)); } public function toFloat() : Type { return TypeCombinator::union(new ConstantFloatType(0.0), new ConstantFloatType(1.0)); } public function toString() : Type { return new ErrorType(); } public function toArray() : Type { return $this; } public function toArrayKey() : Type { return new ErrorType(); } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public static function __set_state(array $properties) : Type { return new self(); } public static function setListTypeEnabled(bool $enabled) : void { self::$enabled = $enabled; } public static function isListTypeEnabled() : bool { return self::$enabled; } public static function intersectWith(Type $type) : Type { if (self::$enabled) { return TypeCombinator::intersect($type, new self()); } return $type; } public function exponentiate(Type $exponent) : Type { return new ErrorType(); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('list'); } } methodName = $methodName; } public function getReferencedClasses() : array { return []; } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } private function getCanonicalMethodName() : string { return strtolower($this->methodName); } public function accepts(Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return AcceptsResult::createFromBoolean($this->equals($type)); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { return new IsSuperTypeOfResult($type->hasMethod($this->methodName), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } if ($this->isCallable()->yes() && $otherType->isCallable()->yes()) { return IsSuperTypeOfResult::createYes(); } if ($otherType instanceof self) { $limit = IsSuperTypeOfResult::createYes(); } else { $limit = IsSuperTypeOfResult::createMaybe(); } return $limit->and(new IsSuperTypeOfResult($otherType->hasMethod($this->methodName), [])); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self && $this->getCanonicalMethodName() === $type->getCanonicalMethodName(); } public function describe(VerbosityLevel $level) : string { return sprintf('hasMethod(%s)', $this->methodName); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function hasMethod(string $methodName) : TrinaryLogic { if ($this->getCanonicalMethodName() === strtolower($methodName)) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { $method = new DummyMethodReflection($this->methodName); return new CallbackUnresolvedMethodPrototypeReflection($method, $method->getDeclaringClass(), \false, static function (Type $type) : Type { return $type; }); } public function isCallable() : TrinaryLogic { if ($this->getCanonicalMethodName() === '__invoke') { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function toString() : Type { if ($this->getCanonicalMethodName() === '__tostring') { return new StringType(); } return new ErrorType(); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { return [new TrivialParametersAcceptor()]; } public function getEnumCases() : array { return []; } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function exponentiate(Type $exponent) : Type { return new ErrorType(); } public function getFiniteTypes() : array { return []; } public static function __set_state(array $properties) : Type { return new self($properties['methodName']); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } $isArray = $type->isArray(); $isIterableAtLeastOnce = $type->isIterableAtLeastOnce(); return new AcceptsResult($isArray->and($isIterableAtLeastOnce), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } return new IsSuperTypeOfResult($type->isArray()->and($type->isIterableAtLeastOnce()), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } return (new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isIterableAtLeastOnce()), []))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self; } public function describe(VerbosityLevel $level) : string { return 'non-empty-array'; } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getOffsetValueType(Type $offsetType) : Type { return new MixedType(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { return $this; } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this; } public function unsetOffset(Type $offsetType) : Type { return new ErrorType(); } public function getKeysArray() : Type { return $this; } public function getValuesArray() : Type { return $this; } public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys) : Type { return $this; } public function fillKeysArray(Type $valueType) : Type { return $this; } public function flipArray() : Type { return $this; } public function intersectKeyArray(Type $otherArraysType) : Type { return new MixedType(); } public function popArray() : Type { return new MixedType(); } public function reverseArray(TrinaryLogic $preserveKeys) : Type { return $this; } public function searchArray(Type $needleType) : Type { return new MixedType(); } public function shiftArray() : Type { return new MixedType(); } public function shuffleArray() : Type { return $this; } public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys) : Type { if ((new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes() && ($lengthType->isNull()->yes() || IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($lengthType)->yes())) { return $this; } return new MixedType(); } public function isIterable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createYes(); } public function getArraySize() : Type { return IntegerRangeType::fromInterval(1, null); } public function getIterableKeyType() : Type { return new MixedType(); } public function getFirstIterableKeyType() : Type { return new MixedType(); } public function getLastIterableKeyType() : Type { return new MixedType(); } public function getIterableValueType() : Type { return new MixedType(); } public function getFirstIterableValueType() : Type { return new MixedType(); } public function getLastIterableValueType() : Type { return new MixedType(); } public function isArray() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isConstantArray() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isOversizedArray() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isList() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : Type { return new ErrorType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return new ConstantIntegerType(1); } public function toFloat() : Type { return new ConstantFloatType(1.0); } public function toString() : Type { return new ErrorType(); } public function toArray() : Type { return $this; } public function toArrayKey() : Type { return new ErrorType(); } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function exponentiate(Type $exponent) : Type { return new ErrorType(); } public function getFiniteTypes() : array { return []; } public static function __set_state(array $properties) : Type { return new self(); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('non-empty-array'); } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof MixedType) { return AcceptsResult::createNo(); } if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new AcceptsResult($type->isLiteralString(), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isLiteralString(), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } return (new IsSuperTypeOfResult($otherType->isLiteralString(), []))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self; } public function describe(VerbosityLevel $level) : string { return 'literal-string'; } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return $offsetType->isInteger()->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(Type $offsetType) : Type { if ($this->hasOffsetValueType($offsetType)->no()) { return new ErrorType(); } return new StringType(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { $stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues); if ($stringOffset instanceof ErrorType) { return $stringOffset; } if ($valueType->isLiteralString()->yes()) { return $this; } return new StringType(); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this; } public function unsetOffset(Type $offsetType) : Type { return new ErrorType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return new IntegerType(); } public function toFloat() : Type { return new FloatType(); } public function toString() : Type { return $this; } public function toBoolean() : BooleanType { return new BooleanType(); } public function toArray() : Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function hasMethod(string $methodName) : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function generalize(GeneralizePrecision $precision) : Type { return new StringType(); } public static function __set_state(array $properties) : Type { return new self(); } public function exponentiate(Type $exponent) : Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('literal-string'); } } offsetType = $offsetType; $this->valueType = $valueType; } /** * @return ConstantStringType|ConstantIntegerType */ public function getOffsetType() { return $this->offsetType; } public function getValueType() : Type { return $this->valueType; } public function getReferencedClasses() : array { return []; } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function getConstantStrings() : array { return []; } public function accepts(Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } $result = new AcceptsResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); return $result->and($this->valueType->acceptsWithReason($type->getOffsetValueType($this->offsetType), $strictTypes)); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } $result = new IsSuperTypeOfResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); return $result->and($this->valueType->isSuperTypeOfWithReason($type->getOffsetValueType($this->offsetType))); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } $result = new IsSuperTypeOfResult($otherType->isOffsetAccessible()->and($otherType->hasOffsetValueType($this->offsetType)), []); return $result->and($otherType->getOffsetValueType($this->offsetType)->isSuperTypeOfWithReason($this->valueType))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self && $this->offsetType->equals($type->offsetType) && $this->valueType->equals($type->valueType); } public function describe(VerbosityLevel $level) : string { return sprintf('hasOffsetValue(%s, %s)', $this->offsetType->describe($level), $this->valueType->describe($level)); } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { if ($offsetType->isConstantScalarValue()->yes() && $offsetType->equals($this->offsetType)) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function getOffsetValueType(Type $offsetType) : Type { if ($offsetType->isConstantScalarValue()->yes() && $offsetType->equals($this->offsetType)) { return $this->valueType; } return new MixedType(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { if ($offsetType === null) { return $this; } if (!$offsetType->equals($this->offsetType)) { return $this; } if (!$offsetType instanceof ConstantIntegerType && !$offsetType instanceof ConstantStringType) { throw new ShouldNotHappenException(); } return new self($offsetType, $valueType); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return new self($this->offsetType, $valueType); } public function unsetOffset(Type $offsetType) : Type { if ($this->offsetType->isSuperTypeOf($offsetType)->yes()) { return new ErrorType(); } return $this; } public function getKeysArray() : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function getValuesArray() : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys) : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function fillKeysArray(Type $valueType) : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function flipArray() : Type { $valueType = $this->valueType->toArrayKey(); if ($valueType instanceof ConstantIntegerType || $valueType instanceof ConstantStringType) { return new self($valueType, $this->offsetType); } return new MixedType(); } public function intersectKeyArray(Type $otherArraysType) : Type { if ($otherArraysType->hasOffsetValueType($this->offsetType)->yes()) { return $this; } return new MixedType(); } public function reverseArray(TrinaryLogic $preserveKeys) : Type { if ($preserveKeys->yes()) { return $this; } return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function searchArray(Type $needleType) : Type { if ($needleType instanceof ConstantScalarType && $this->valueType instanceof ConstantScalarType && $needleType->getValue() === $this->valueType->getValue()) { return new UnionType([new IntegerType(), new StringType()]); } return new MixedType(); } public function shuffleArray() : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys) : Type { if ($this->offsetType->isSuperTypeOf($offsetType)->yes() && ($lengthType->isNull()->yes() || IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($lengthType)->yes())) { return $preserveKeys->yes() ? TypeCombinator::intersect($this, new \PHPStan\Type\Accessory\NonEmptyArrayType()) : new \PHPStan\Type\Accessory\NonEmptyArrayType(); } return new MixedType(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isList() : TrinaryLogic { if ($this->offsetType->isString()->yes()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return new ErrorType(); } public function toFloat() : Type { return new ErrorType(); } public function toString() : Type { return new ErrorType(); } public function toArray() : Type { return new MixedType(); } public function toArrayKey() : Type { return new ErrorType(); } public function getEnumCases() : array { return []; } public function traverse(callable $cb) : Type { $newValueType = $cb($this->valueType); if ($newValueType === $this->valueType) { return $this; } return new self($this->offsetType, $newValueType); } public function traverseSimultaneously(Type $right, callable $cb) : Type { $newValueType = $cb($this->valueType, $right->getOffsetValueType($this->offsetType)); if ($newValueType === $this->valueType) { return $this; } return new self($this->offsetType, $newValueType); } public function exponentiate(Type $exponent) : Type { return new ErrorType(); } public function getFiniteTypes() : array { return []; } public static function __set_state(array $properties) : Type { return new self($properties['offsetType'], $properties['valueType']); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new AcceptsResult($type->isUppercaseString(), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isUppercaseString(), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } return (new IsSuperTypeOfResult($otherType->isUppercaseString(), []))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self; } public function describe(VerbosityLevel $level) : string { return 'uppercase-string'; } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return $offsetType->isInteger()->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(Type $offsetType) : Type { if ($this->hasOffsetValueType($offsetType)->no()) { return new ErrorType(); } return new IntersectionType([new StringType(), new \PHPStan\Type\Accessory\AccessoryUppercaseStringType()]); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { $stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues); if ($stringOffset instanceof ErrorType) { return $stringOffset; } if ($valueType->isUppercaseString()->yes()) { return $this; } return new StringType(); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this; } public function unsetOffset(Type $offsetType) : Type { return new ErrorType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return new IntegerType(); } public function toFloat() : Type { return new FloatType(); } public function toString() : Type { return $this; } public function toBoolean() : BooleanType { return new BooleanType(); } public function toArray() : Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function hasMethod(string $methodName) : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function generalize(GeneralizePrecision $precision) : Type { return new StringType(); } public static function __set_state(array $properties) : Type { return new self(); } public function exponentiate(Type $exponent) : Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('uppercase-string'); } } propertyName = $propertyName; } /** * @return string[] */ public function getReferencedClasses() : array { return []; } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function getConstantStrings() : array { return []; } public function getPropertyName() : string { return $this->propertyName; } public function accepts(Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return AcceptsResult::createFromBoolean($this->equals($type)); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { return new IsSuperTypeOfResult($type->hasProperty($this->propertyName), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } if ($otherType instanceof self) { $limit = IsSuperTypeOfResult::createYes(); } else { $limit = IsSuperTypeOfResult::createMaybe(); } return $limit->and(new IsSuperTypeOfResult($otherType->hasProperty($this->propertyName), [])); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self && $this->propertyName === $type->propertyName; } public function describe(VerbosityLevel $level) : string { return sprintf('hasProperty(%s)', $this->propertyName); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function hasProperty(string $propertyName) : TrinaryLogic { if ($this->propertyName === $propertyName) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { return [new TrivialParametersAcceptor()]; } public function getEnumCases() : array { return []; } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function exponentiate(Type $exponent) : Type { return new ErrorType(); } public function getFiniteTypes() : array { return []; } public static function __set_state(array $properties) : Type { return new self($properties['propertyName']); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new AcceptsResult($type->isNonFalsyString(), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isNonFalsyString(), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } if ($otherType instanceof \PHPStan\Type\Accessory\AccessoryNonEmptyStringType) { return IsSuperTypeOfResult::createYes(); } return (new IsSuperTypeOfResult($otherType->isNonFalsyString(), []))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self; } public function describe(VerbosityLevel $level) : string { return 'non-falsy-string'; } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return $offsetType->isInteger()->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(Type $offsetType) : Type { if ($this->hasOffsetValueType($offsetType)->no()) { return new ErrorType(); } return new StringType(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { $stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues); if ($stringOffset instanceof ErrorType) { return $stringOffset; } if ($valueType->isNonFalsyString()->yes()) { return $this; } return new StringType(); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this; } public function unsetOffset(Type $offsetType) : Type { return new ErrorType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return new IntegerType(); } public function toFloat() : Type { return new FloatType(); } public function toString() : Type { return $this; } public function toArray() : Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function generalize(GeneralizePrecision $precision) : Type { return new StringType(); } public static function __set_state(array $properties) : Type { return new self(); } public function exponentiate(Type $exponent) : Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('non-falsy-string'); } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new AcceptsResult($type->isNumericString(), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isNumericString(), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } return (new IsSuperTypeOfResult($otherType->isNumericString(), []))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { if ($acceptingType->isNonFalsyString()->yes()) { return AcceptsResult::createMaybe(); } if ($acceptingType->isNonEmptyString()->yes()) { return AcceptsResult::createYes(); } return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self; } public function describe(VerbosityLevel $level) : string { return 'numeric-string'; } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return $offsetType->isInteger()->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(Type $offsetType) : Type { if ($this->hasOffsetValueType($offsetType)->no()) { return new ErrorType(); } return new StringType(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { $stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues); if ($stringOffset instanceof ErrorType) { return $stringOffset; } return $this; } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this; } public function unsetOffset(Type $offsetType) : Type { return new ErrorType(); } public function toNumber() : Type { return new UnionType([$this->toInteger(), $this->toFloat()]); } public function toAbsoluteNumber() : Type { return $this->toNumber()->toAbsoluteNumber(); } public function toInteger() : Type { return new IntegerType(); } public function toFloat() : Type { return new FloatType(); } public function toString() : Type { return $this; } public function toArray() : Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : Type { return new UnionType([new IntegerType(), new IntersectionType([new StringType(), new \PHPStan\Type\Accessory\AccessoryNumericStringType()])]); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : Type { return new ErrorType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function generalize(GeneralizePrecision $precision) : Type { return new StringType(); } public static function __set_state(array $properties) : Type { return new self(); } public function tryRemove(Type $typeToRemove) : ?Type { if ($typeToRemove instanceof ConstantStringType && $typeToRemove->getValue() === '0') { return TypeCombinator::intersect($this, new \PHPStan\Type\Accessory\AccessoryNonFalsyStringType()); } return null; } public function exponentiate(Type $exponent) : Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('numeric-string'); } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type->isNonEmptyString()->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new AcceptsResult($type->isNonEmptyString(), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type->isNonFalsyString()->yes()) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isNonEmptyString(), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } return (new IsSuperTypeOfResult($otherType->isNonEmptyString(), []))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self; } public function describe(VerbosityLevel $level) : string { return 'non-empty-string'; } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return $offsetType->isInteger()->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(Type $offsetType) : Type { if ($this->hasOffsetValueType($offsetType)->no()) { return new ErrorType(); } if ((new ConstantIntegerType(0))->isSuperTypeOf($offsetType)->yes()) { return new IntersectionType([new StringType(), new \PHPStan\Type\Accessory\AccessoryNonEmptyStringType()]); } return new StringType(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { $stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues); if ($stringOffset instanceof ErrorType) { return $stringOffset; } return $this; } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this; } public function unsetOffset(Type $offsetType) : Type { return new ErrorType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return new IntegerType(); } public function toFloat() : Type { return new FloatType(); } public function toString() : Type { return $this; } public function toArray() : Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function generalize(GeneralizePrecision $precision) : Type { return new StringType(); } public static function __set_state(array $properties) : Type { return new self(); } public function tryRemove(Type $typeToRemove) : ?Type { if ($typeToRemove instanceof ConstantStringType && $typeToRemove->getValue() === '0') { return TypeCombinator::intersect($this, new \PHPStan\Type\Accessory\AccessoryNonFalsyStringType()); } return null; } public function exponentiate(Type $exponent) : Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('non-empty-string'); } } offsetType = $offsetType; } /** * @return ConstantStringType|ConstantIntegerType */ public function getOffsetType() : Type { return $this->offsetType; } public function getReferencedClasses() : array { return []; } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function getConstantStrings() : array { return []; } public function accepts(Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new AcceptsResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } $result = new IsSuperTypeOfResult($otherType->isOffsetAccessible()->and($otherType->hasOffsetValueType($this->offsetType)), []); return $result->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self && $this->offsetType->equals($type->offsetType); } public function describe(VerbosityLevel $level) : string { return sprintf('hasOffset(%s)', $this->offsetType->describe($level)); } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { if ($offsetType->isConstantScalarValue()->yes() && $offsetType->equals($this->offsetType)) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function getOffsetValueType(Type $offsetType) : Type { return new MixedType(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { return $this; } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this; } public function unsetOffset(Type $offsetType) : Type { if ($this->offsetType->isSuperTypeOf($offsetType)->yes()) { return new ErrorType(); } return $this; } public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys) : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function fillKeysArray(Type $valueType) : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function intersectKeyArray(Type $otherArraysType) : Type { if ($otherArraysType->hasOffsetValueType($this->offsetType)->yes()) { return $this; } return new MixedType(); } public function reverseArray(TrinaryLogic $preserveKeys) : Type { if ($preserveKeys->yes()) { return $this; } return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function shuffleArray() : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys) : Type { if ($this->offsetType->isSuperTypeOf($offsetType)->yes() && ($lengthType->isNull()->yes() || IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($lengthType)->yes())) { return $preserveKeys->yes() ? TypeCombinator::intersect($this, new \PHPStan\Type\Accessory\NonEmptyArrayType()) : new \PHPStan\Type\Accessory\NonEmptyArrayType(); } return new MixedType(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isList() : TrinaryLogic { if ($this->offsetType->isString()->yes()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function getKeysArray() : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function getValuesArray() : Type { return new \PHPStan\Type\Accessory\NonEmptyArrayType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return new ErrorType(); } public function toFloat() : Type { return new ErrorType(); } public function toString() : Type { return new ErrorType(); } public function toArray() : Type { return new MixedType(); } public function toArrayKey() : Type { return new ErrorType(); } public function getEnumCases() : array { return []; } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function exponentiate(Type $exponent) : Type { return new ErrorType(); } public function getFiniteTypes() : array { return []; } public static function __set_state(array $properties) : Type { return new self($properties['offsetType']); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new AcceptsResult($type->isArray()->and($type->isIterableAtLeastOnce()), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } return new IsSuperTypeOfResult($type->isArray()->and($type->isOversizedArray()), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } return (new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isOversizedArray()), []))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self; } public function describe(VerbosityLevel $level) : string { return 'oversized-array'; } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getOffsetValueType(Type $offsetType) : Type { return new MixedType(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { return $this; } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this; } public function unsetOffset(Type $offsetType) : Type { return new ErrorType(); } public function getKeysArray() : Type { return $this; } public function getValuesArray() : Type { return $this; } public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys) : Type { return $this; } public function fillKeysArray(Type $valueType) : Type { return $this; } public function flipArray() : Type { return $this; } public function intersectKeyArray(Type $otherArraysType) : Type { return $this; } public function popArray() : Type { return $this; } public function reverseArray(TrinaryLogic $preserveKeys) : Type { return $this; } public function searchArray(Type $needleType) : Type { return new MixedType(); } public function shiftArray() : Type { return $this; } public function shuffleArray() : Type { return $this; } public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys) : Type { return $this; } public function isIterable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getArraySize() : Type { return IntegerRangeType::fromInterval(0, null); } public function getIterableKeyType() : Type { return new MixedType(); } public function getFirstIterableKeyType() : Type { return new MixedType(); } public function getLastIterableKeyType() : Type { return new MixedType(); } public function getIterableValueType() : Type { return new MixedType(); } public function getFirstIterableValueType() : Type { return new MixedType(); } public function getLastIterableValueType() : Type { return new MixedType(); } public function isArray() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isConstantArray() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isOversizedArray() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isList() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : Type { return new ErrorType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return new ConstantIntegerType(1); } public function toFloat() : Type { return new ConstantFloatType(1.0); } public function toString() : Type { return new ErrorType(); } public function toArray() : Type { return new MixedType(); } public function toArrayKey() : Type { return new ErrorType(); } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function exponentiate(Type $exponent) : Type { return new ErrorType(); } public function getFiniteTypes() : array { return []; } public static function __set_state(array $properties) : Type { return new self(); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return new AcceptsResult($type->isLowercaseString(), []); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } return new IsSuperTypeOfResult($type->isLowercaseString(), []); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { return $otherType->isSuperTypeOfWithReason($this); } return (new IsSuperTypeOfResult($otherType->isLowercaseString(), []))->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function equals(Type $type) : bool { return $type instanceof self; } public function describe(VerbosityLevel $level) : string { return 'lowercase-string'; } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return $offsetType->isInteger()->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(Type $offsetType) : Type { if ($this->hasOffsetValueType($offsetType)->no()) { return new ErrorType(); } return new IntersectionType([new StringType(), new \PHPStan\Type\Accessory\AccessoryLowercaseStringType()]); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { $stringOffset = (new StringType())->setOffsetValueType($offsetType, $valueType, $unionValues); if ($stringOffset instanceof ErrorType) { return $stringOffset; } if ($valueType->isLowercaseString()->yes()) { return $this; } return new StringType(); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this; } public function unsetOffset(Type $offsetType) : Type { return new ErrorType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toInteger() : Type { return new IntegerType(); } public function toFloat() : Type { return new FloatType(); } public function toString() : Type { return $this; } public function toBoolean() : BooleanType { return new BooleanType(); } public function toArray() : Type { return new ConstantArrayType([new ConstantIntegerType(0)], [$this], [1], [], TrinaryLogic::createYes()); } public function toArrayKey() : Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function getObjectTypeOrClassStringObjectType() : Type { return new ObjectWithoutClassType(); } public function hasMethod(string $methodName) : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createYes(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function traverse(callable $cb) : Type { return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { return $this; } public function generalize(GeneralizePrecision $precision) : Type { return new StringType(); } public static function __set_state(array $properties) : Type { return new self(); } public function exponentiate(Type $exponent) : Type { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('lowercase-string'); } } classReflection = $classReflection; if ($subtractedType instanceof \PHPStan\Type\NeverType) { $subtractedType = null; } $this->subtractedType = $subtractedType; $this->baseClass = $classReflection->getName(); } public function getClassName() : string { return $this->baseClass; } public function getClassReflection() : ClassReflection { return $this->classReflection; } public function getAncestorWithClassName(string $className) : ?\PHPStan\Type\TypeWithClassName { $ancestor = $this->getStaticObjectType()->getAncestorWithClassName($className); if ($ancestor === null) { return null; } $classReflection = $ancestor->getClassReflection(); if ($classReflection !== null) { return $this->changeBaseClass($classReflection); } return null; } public function getStaticObjectType() : \PHPStan\Type\ObjectType { if ($this->staticObjectType === null) { if ($this->classReflection->isGeneric()) { $typeMap = $this->classReflection->getActiveTemplateTypeMap()->map(static function (string $name, \PHPStan\Type\Type $type) : \PHPStan\Type\Type { return TemplateTypeHelper::toArgument($type); }); $varianceMap = $this->classReflection->getCallSiteVarianceMap(); return $this->staticObjectType = new GenericObjectType($this->classReflection->getName(), $this->classReflection->typeMapToList($typeMap), $this->subtractedType, null, $this->classReflection->varianceMapToList($varianceMap)); } return $this->staticObjectType = new \PHPStan\Type\ObjectType($this->classReflection->getName(), $this->subtractedType, $this->classReflection); } return $this->staticObjectType; } /** * @return string[] */ public function getReferencedClasses() : array { return $this->getStaticObjectType()->getReferencedClasses(); } public function getObjectClassNames() : array { return $this->getStaticObjectType()->getObjectClassNames(); } public function getObjectClassReflections() : array { return $this->getStaticObjectType()->getObjectClassReflections(); } public function getArrays() : array { return $this->getStaticObjectType()->getArrays(); } public function getConstantArrays() : array { return $this->getStaticObjectType()->getConstantArrays(); } public function getConstantStrings() : array { return $this->getStaticObjectType()->getConstantStrings(); } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } if (!$type instanceof static) { return \PHPStan\Type\AcceptsResult::createNo(); } return $this->getStaticObjectType()->acceptsWithReason($type->getStaticObjectType(), $strictTypes); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return $this->getStaticObjectType()->isSuperTypeOfWithReason($type); } if ($type instanceof \PHPStan\Type\ObjectWithoutClassType) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } if ($type instanceof \PHPStan\Type\ObjectType) { $result = $this->getStaticObjectType()->isSuperTypeOfWithReason($type); if ($result->yes()) { $classReflection = $type->getClassReflection(); if ($classReflection !== null && $classReflection->isFinal()) { return $result; } } return $result->and(\PHPStan\Type\IsSuperTypeOfResult::createMaybe()); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type) : bool { if (get_class($type) !== static::class) { return \false; } return $this->getStaticObjectType()->equals($type->getStaticObjectType()); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return sprintf('static(%s)', $this->getStaticObjectType()->describe($level)); } public function getTemplateType(string $ancestorClassName, string $templateTypeName) : \PHPStan\Type\Type { return $this->getStaticObjectType()->getTemplateType($ancestorClassName, $templateTypeName); } public function isObject() : TrinaryLogic { return $this->getStaticObjectType()->isObject(); } public function isEnum() : TrinaryLogic { return $this->getStaticObjectType()->isEnum(); } public function canAccessProperties() : TrinaryLogic { return $this->getStaticObjectType()->canAccessProperties(); } public function hasProperty(string $propertyName) : TrinaryLogic { return $this->getStaticObjectType()->hasProperty($propertyName); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { $staticObject = $this->getStaticObjectType(); $nakedProperty = $staticObject->getUnresolvedPropertyPrototype($propertyName, $scope)->getNakedProperty(); $ancestor = $this->getAncestorWithClassName($nakedProperty->getDeclaringClass()->getName()); $classReflection = null; if ($ancestor !== null) { $classReflection = $ancestor->getClassReflection(); } if ($classReflection === null) { $classReflection = $nakedProperty->getDeclaringClass(); } return new CallbackUnresolvedPropertyPrototypeReflection($nakedProperty, $classReflection, \false, function (\PHPStan\Type\Type $type) use($scope) : \PHPStan\Type\Type { return $this->transformStaticType($type, $scope); }); } public function canCallMethods() : TrinaryLogic { return $this->getStaticObjectType()->canCallMethods(); } public function hasMethod(string $methodName) : TrinaryLogic { return $this->getStaticObjectType()->hasMethod($methodName); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { $staticObject = $this->getStaticObjectType(); $nakedMethod = $staticObject->getUnresolvedMethodPrototype($methodName, $scope)->getNakedMethod(); $ancestor = $this->getAncestorWithClassName($nakedMethod->getDeclaringClass()->getName()); $classReflection = null; if ($ancestor !== null) { $classReflection = $ancestor->getClassReflection(); } if ($classReflection === null) { $classReflection = $nakedMethod->getDeclaringClass(); } return new CallbackUnresolvedMethodPrototypeReflection($nakedMethod, $classReflection, \false, function (\PHPStan\Type\Type $type) use($scope) : \PHPStan\Type\Type { return $this->transformStaticType($type, $scope); }); } private function transformStaticType(\PHPStan\Type\Type $type, ClassMemberAccessAnswerer $scope) : \PHPStan\Type\Type { return \PHPStan\Type\TypeTraverser::map($type, function (\PHPStan\Type\Type $type, callable $traverse) use($scope) : \PHPStan\Type\Type { if ($type instanceof \PHPStan\Type\StaticType) { $classReflection = $this->classReflection; $isFinal = \false; if ($scope->isInClass()) { $classReflection = $scope->getClassReflection(); $isFinal = $classReflection->isFinal(); } $type = $type->changeBaseClass($classReflection); if (!$isFinal || $type instanceof \PHPStan\Type\ThisType) { return $traverse($type); } return $traverse($type->getStaticObjectType()); } return $traverse($type); }); } public function canAccessConstants() : TrinaryLogic { return $this->getStaticObjectType()->canAccessConstants(); } public function hasConstant(string $constantName) : TrinaryLogic { return $this->getStaticObjectType()->hasConstant($constantName); } public function getConstant(string $constantName) : ConstantReflection { return $this->getStaticObjectType()->getConstant($constantName); } public function changeBaseClass(ClassReflection $classReflection) : self { return new self($classReflection, $this->subtractedType); } public function isIterable() : TrinaryLogic { return $this->getStaticObjectType()->isIterable(); } public function isIterableAtLeastOnce() : TrinaryLogic { return $this->getStaticObjectType()->isIterableAtLeastOnce(); } public function getArraySize() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getArraySize(); } public function getIterableKeyType() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getIterableKeyType(); } public function getFirstIterableKeyType() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getFirstIterableKeyType(); } public function getLastIterableKeyType() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getLastIterableKeyType(); } public function getIterableValueType() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getIterableValueType(); } public function getFirstIterableValueType() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getFirstIterableValueType(); } public function getLastIterableValueType() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getLastIterableValueType(); } public function isOffsetAccessible() : TrinaryLogic { return $this->getStaticObjectType()->isOffsetAccessible(); } public function isOffsetAccessLegal() : TrinaryLogic { return $this->getStaticObjectType()->isOffsetAccessLegal(); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { return $this->getStaticObjectType()->hasOffsetValueType($offsetType); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return $this->getStaticObjectType()->getOffsetValueType($offsetType); } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { return $this->getStaticObjectType()->setOffsetValueType($offsetType, $valueType, $unionValues); } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return $this->getStaticObjectType()->setExistingOffsetValueType($offsetType, $valueType); } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return $this->getStaticObjectType()->unsetOffset($offsetType); } public function getKeysArray() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getKeysArray(); } public function getValuesArray() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getValuesArray(); } public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this->getStaticObjectType()->chunkArray($lengthType, $preserveKeys); } public function fillKeysArray(\PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return $this->getStaticObjectType()->fillKeysArray($valueType); } public function flipArray() : \PHPStan\Type\Type { return $this->getStaticObjectType()->flipArray(); } public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType) : \PHPStan\Type\Type { return $this->getStaticObjectType()->intersectKeyArray($otherArraysType); } public function popArray() : \PHPStan\Type\Type { return $this->getStaticObjectType()->popArray(); } public function reverseArray(TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this->getStaticObjectType()->reverseArray($preserveKeys); } public function searchArray(\PHPStan\Type\Type $needleType) : \PHPStan\Type\Type { return $this->getStaticObjectType()->searchArray($needleType); } public function shiftArray() : \PHPStan\Type\Type { return $this->getStaticObjectType()->shiftArray(); } public function shuffleArray() : \PHPStan\Type\Type { return $this->getStaticObjectType()->shuffleArray(); } public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this->getStaticObjectType()->sliceArray($offsetType, $lengthType, $preserveKeys); } public function isCallable() : TrinaryLogic { return $this->getStaticObjectType()->isCallable(); } public function getEnumCases() : array { return $this->getStaticObjectType()->getEnumCases(); } public function isArray() : TrinaryLogic { return $this->getStaticObjectType()->isArray(); } public function isConstantArray() : TrinaryLogic { return $this->getStaticObjectType()->isConstantArray(); } public function isOversizedArray() : TrinaryLogic { return $this->getStaticObjectType()->isOversizedArray(); } public function isList() : TrinaryLogic { return $this->getStaticObjectType()->isList(); } public function isNull() : TrinaryLogic { return $this->getStaticObjectType()->isNull(); } public function isConstantValue() : TrinaryLogic { return $this->getStaticObjectType()->isConstantValue(); } public function isConstantScalarValue() : TrinaryLogic { return $this->getStaticObjectType()->isConstantScalarValue(); } public function getConstantScalarTypes() : array { return $this->getStaticObjectType()->getConstantScalarTypes(); } public function getConstantScalarValues() : array { return $this->getStaticObjectType()->getConstantScalarValues(); } public function isTrue() : TrinaryLogic { return $this->getStaticObjectType()->isTrue(); } public function isFalse() : TrinaryLogic { return $this->getStaticObjectType()->isFalse(); } public function isBoolean() : TrinaryLogic { return $this->getStaticObjectType()->isBoolean(); } public function isFloat() : TrinaryLogic { return $this->getStaticObjectType()->isFloat(); } public function isInteger() : TrinaryLogic { return $this->getStaticObjectType()->isInteger(); } public function isString() : TrinaryLogic { return $this->getStaticObjectType()->isString(); } public function isNumericString() : TrinaryLogic { return $this->getStaticObjectType()->isNumericString(); } public function isNonEmptyString() : TrinaryLogic { return $this->getStaticObjectType()->isNonEmptyString(); } public function isNonFalsyString() : TrinaryLogic { return $this->getStaticObjectType()->isNonFalsyString(); } public function isLiteralString() : TrinaryLogic { return $this->getStaticObjectType()->isLiteralString(); } public function isLowercaseString() : TrinaryLogic { return $this->getStaticObjectType()->isLowercaseString(); } public function isUppercaseString() : TrinaryLogic { return $this->getStaticObjectType()->isUppercaseString(); } public function isClassStringType() : TrinaryLogic { return $this->getStaticObjectType()->isClassStringType(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return $this->getStaticObjectType()->getClassStringObjectType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return $this; } public function isVoid() : TrinaryLogic { return $this->getStaticObjectType()->isVoid(); } public function isScalar() : TrinaryLogic { return $this->getStaticObjectType()->isScalar(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { return $this->getStaticObjectType()->getCallableParametersAcceptors($scope); } public function isCloneable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function toNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toString() : \PHPStan\Type\Type { return $this->getStaticObjectType()->toString(); } public function toInteger() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toFloat() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function toArray() : \PHPStan\Type\Type { return $this->getStaticObjectType()->toArray(); } public function toArrayKey() : \PHPStan\Type\Type { return $this->getStaticObjectType()->toArrayKey(); } public function toBoolean() : \PHPStan\Type\BooleanType { return $this->getStaticObjectType()->toBoolean(); } public function traverse(callable $cb) : \PHPStan\Type\Type { $subtractedType = $this->subtractedType !== null ? $cb($this->subtractedType) : null; if ($subtractedType !== $this->subtractedType) { return new self($this->classReflection, $subtractedType); } return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if ($this->subtractedType === null) { return $this; } return new self($this->classReflection); } public function subtract(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { if ($this->subtractedType !== null) { $type = \PHPStan\Type\TypeCombinator::union($this->subtractedType, $type); } return $this->changeSubtractedType($type); } public function getTypeWithoutSubtractedType() : \PHPStan\Type\Type { return $this->changeSubtractedType(null); } public function changeSubtractedType(?\PHPStan\Type\Type $subtractedType) : \PHPStan\Type\Type { if ($subtractedType !== null) { $classReflection = $this->getClassReflection(); if ($classReflection->getAllowedSubTypes() !== null) { $objectType = $this->getStaticObjectType()->changeSubtractedType($subtractedType); if ($objectType instanceof \PHPStan\Type\NeverType) { return $objectType; } if ($objectType instanceof \PHPStan\Type\ObjectType && $objectType->getSubtractedType() !== null) { return new self($classReflection, $objectType->getSubtractedType()); } return \PHPStan\Type\TypeCombinator::intersect($this, $objectType); } } return new self($this->classReflection, $subtractedType); } public function getSubtractedType() : ?\PHPStan\Type\Type { return $this->subtractedType; } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { if ($this->getStaticObjectType()->isSuperTypeOf($typeToRemove)->yes()) { return $this->subtract($typeToRemove); } return null; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return $this->getStaticObjectType()->exponentiate($exponent); } public function getFiniteTypes() : array { return $this->getStaticObjectType()->getFiniteTypes(); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('static'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if ($reflectionProvider->hasClass($properties['baseClass'])) { return new self($reflectionProvider->getClass($properties['baseClass']), $properties['subtractedType'] ?? null); } return new \PHPStan\Type\ErrorType(); } } */ public $reasons; /** * @api * @param list $reasons */ public function __construct(TrinaryLogic $result, array $reasons) { $this->result = $result; $this->reasons = $reasons; } public function yes() : bool { return $this->result->yes(); } public function maybe() : bool { return $this->result->maybe(); } public function no() : bool { return $this->result->no(); } public static function createYes() : self { return new self(TrinaryLogic::createYes(), []); } /** * @param list $reasons */ public static function createNo(array $reasons = []) : self { return new self(TrinaryLogic::createNo(), $reasons); } public static function createMaybe() : self { return new self(TrinaryLogic::createMaybe(), []); } public static function createFromBoolean(bool $value) : self { return new self(TrinaryLogic::createFromBoolean($value), []); } public function toAcceptsResult() : \PHPStan\Type\AcceptsResult { return new \PHPStan\Type\AcceptsResult($this->result, $this->reasons); } public function and(self ...$others) : self { $results = []; $reasons = []; foreach ($others as $other) { $results[] = $other->result; $reasons[] = $other->reasons; } return new self($this->result->and(...$results), array_values(array_unique(array_merge($this->reasons, ...$reasons)))); } public function or(self ...$others) : self { $results = []; $reasons = []; foreach ($others as $other) { $results[] = $other->result; $reasons[] = $other->reasons; } return new self($this->result->or(...$results), array_values(array_unique(array_merge($this->reasons, ...$reasons)))); } /** * @param callable(string): string $cb */ public function decorateReasons(callable $cb) : self { $reasons = []; foreach ($this->reasons as $reason) { $reasons[] = $cb($reason); } return new self($this->result, $reasons); } public static function extremeIdentity(self ...$operands) : self { if ($operands === []) { throw new ShouldNotHappenException(); } $result = TrinaryLogic::extremeIdentity(...array_map(static function (self $result) { return $result->result; }, $operands)); return new self($result, self::mergeReasons($operands)); } public static function maxMin(self ...$operands) : self { if ($operands === []) { throw new ShouldNotHappenException(); } $result = TrinaryLogic::maxMin(...array_map(static function (self $result) { return $result->result; }, $operands)); return new self($result, self::mergeReasons($operands)); } public function negate() : self { return new self($this->result->negate(), $this->reasons); } /** * @param array $operands * * @return list */ private static function mergeReasons(array $operands) : array { $reasons = []; foreach ($operands as $operand) { foreach ($operand->reasons as $reason) { $reasons[] = $reason; } } return array_values(array_unique($reasons)); } } */ private $properties; /** * @var list */ private $optionalProperties; use ObjectTypeTrait; use UndecidedComparisonTypeTrait; use NonGeneralizableTypeTrait; /** * @api * @param array $properties * @param list $optionalProperties */ public function __construct(array $properties, array $optionalProperties) { $this->properties = $properties; $this->optionalProperties = $optionalProperties; } /** * @return array */ public function getProperties() : array { return $this->properties; } /** * @return list */ public function getOptionalProperties() : array { return $this->optionalProperties; } public function getReferencedClasses() : array { $classes = []; foreach ($this->properties as $propertyType) { foreach ($propertyType->getReferencedClasses() as $referencedClass) { $classes[] = $referencedClass; } } return $classes; } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function hasProperty(string $propertyName) : TrinaryLogic { if (!array_key_exists($propertyName, $this->properties)) { return TrinaryLogic::createNo(); } if (in_array($propertyName, $this->optionalProperties, \true)) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createYes(); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { if (!array_key_exists($propertyName, $this->properties)) { throw new ShouldNotHappenException(); } $property = new \PHPStan\Type\ObjectShapePropertyReflection($this->properties[$propertyName]); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type; }); } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); foreach ($type->getObjectClassReflections() as $classReflection) { if (!UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate($reflectionProvider, Broker::getInstance()->getUniversalObjectCratesClasses(), $classReflection)) { continue; } return \PHPStan\Type\AcceptsResult::createMaybe(); } $result = \PHPStan\Type\AcceptsResult::createYes(); $scope = new OutOfClassScope(); foreach ($this->properties as $propertyName => $propertyType) { $typeHasProperty = $type->hasProperty($propertyName); $hasProperty = new \PHPStan\Type\AcceptsResult($typeHasProperty, $typeHasProperty->yes() ? [] : [sprintf('%s %s have property $%s.', $type->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $typeHasProperty->no() ? 'does not' : 'might not', $propertyName)]); if ($hasProperty->no()) { if (in_array($propertyName, $this->optionalProperties, \true)) { continue; } return $hasProperty; } if ($hasProperty->maybe() && in_array($propertyName, $this->optionalProperties, \true)) { $hasProperty = \PHPStan\Type\AcceptsResult::createYes(); } $result = $result->and($hasProperty); try { $otherProperty = $type->getProperty($propertyName, $scope); } catch (MissingPropertyFromReflectionException $e) { return new \PHPStan\Type\AcceptsResult($result->result, [sprintf('%s %s not have property $%s.', $type->describe(\PHPStan\Type\VerbosityLevel::typeOnly()), $result->no() ? 'does' : 'might', $propertyName)]); } if (!$otherProperty->isPublic()) { return new \PHPStan\Type\AcceptsResult(TrinaryLogic::createNo(), [sprintf('Property %s::$%s is not public.', $otherProperty->getDeclaringClass()->getDisplayName(), $propertyName)]); } if ($otherProperty->isStatic()) { return new \PHPStan\Type\AcceptsResult(TrinaryLogic::createNo(), [sprintf('Property %s::$%s is static.', $otherProperty->getDeclaringClass()->getDisplayName(), $propertyName)]); } if (!$otherProperty->isReadable()) { return new \PHPStan\Type\AcceptsResult(TrinaryLogic::createNo(), [sprintf('Property %s::$%s is not readable.', $otherProperty->getDeclaringClass()->getDisplayName(), $propertyName)]); } $otherPropertyType = $otherProperty->getReadableType(); $verbosity = \PHPStan\Type\VerbosityLevel::getRecommendedLevelByType($propertyType, $otherPropertyType); $acceptsValue = $propertyType->acceptsWithReason($otherPropertyType, $strictTypes)->decorateReasons(static function (string $reason) use($propertyName, $propertyType, $verbosity, $otherPropertyType) { return sprintf('Property ($%s) type %s does not accept type %s: %s', $propertyName, $propertyType->describe($verbosity), $otherPropertyType->describe($verbosity), $reason); }); if (!$acceptsValue->yes() && count($acceptsValue->reasons) === 0) { $acceptsValue = new \PHPStan\Type\AcceptsResult($acceptsValue->result, [sprintf('Property ($%s) type %s does not accept type %s.', $propertyName, $propertyType->describe($verbosity), $otherPropertyType->describe($verbosity))]); } if ($acceptsValue->no()) { return $acceptsValue; } $result = $result->and($acceptsValue); } return $result->and(new \PHPStan\Type\AcceptsResult($type->isObject(), [])); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($type instanceof \PHPStan\Type\ObjectWithoutClassType) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); foreach ($type->getObjectClassReflections() as $classReflection) { if (!UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate($reflectionProvider, Broker::getInstance()->getUniversalObjectCratesClasses(), $classReflection)) { continue; } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } $result = \PHPStan\Type\IsSuperTypeOfResult::createYes(); $scope = new OutOfClassScope(); foreach ($this->properties as $propertyName => $propertyType) { $hasProperty = new \PHPStan\Type\IsSuperTypeOfResult($type->hasProperty($propertyName), []); if ($hasProperty->no()) { if (in_array($propertyName, $this->optionalProperties, \true)) { continue; } return $hasProperty; } if ($hasProperty->maybe() && in_array($propertyName, $this->optionalProperties, \true)) { $hasProperty = \PHPStan\Type\IsSuperTypeOfResult::createYes(); } $result = $result->and($hasProperty); try { $otherProperty = $type->getProperty($propertyName, $scope); } catch (MissingPropertyFromReflectionException $e) { return $result; } if (!$otherProperty->isPublic()) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } if ($otherProperty->isStatic()) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } if (!$otherProperty->isReadable()) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } $otherPropertyType = $otherProperty->getReadableType(); $isSuperType = $propertyType->isSuperTypeOfWithReason($otherPropertyType); if ($isSuperType->no()) { return $isSuperType; } $result = $result->and($isSuperType); } return $result->and(new \PHPStan\Type\IsSuperTypeOfResult($type->isObject(), [])); } public function equals(\PHPStan\Type\Type $type) : bool { if (!$type instanceof self) { return \false; } if (count($this->properties) !== count($type->properties)) { return \false; } foreach ($this->properties as $name => $propertyType) { if (!array_key_exists($name, $type->properties)) { return \false; } if (!$propertyType->equals($type->properties[$name])) { return \false; } } if (count($this->optionalProperties) !== count($type->optionalProperties)) { return \false; } foreach ($this->optionalProperties as $name) { if (in_array($name, $type->optionalProperties, \true)) { continue; } return \false; } return \true; } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { if ($typeToRemove instanceof HasPropertyType) { $properties = $this->properties; unset($properties[$typeToRemove->getPropertyName()]); $optionalProperties = array_values(array_filter($this->optionalProperties, static function (string $propertyName) use($typeToRemove) { return $propertyName !== $typeToRemove->getPropertyName(); })); return new self($properties, $optionalProperties); } return null; } public function makePropertyRequired(string $propertyName) : self { if (array_key_exists($propertyName, $this->properties)) { $optionalProperties = array_values(array_filter($this->optionalProperties, static function (string $currentPropertyName) use($propertyName) { return $currentPropertyName !== $propertyName; })); return new self($this->properties, $optionalProperties); } return $this; } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap { if ($receivedType instanceof \PHPStan\Type\UnionType || $receivedType instanceof \PHPStan\Type\IntersectionType) { return $receivedType->inferTemplateTypesOn($this); } if ($receivedType instanceof self) { $typeMap = TemplateTypeMap::createEmpty(); $scope = new OutOfClassScope(); foreach ($this->properties as $name => $propertyType) { if ($receivedType->hasProperty($name)->no()) { continue; } try { $receivedProperty = $receivedType->getProperty($name, $scope); } catch (MissingPropertyFromReflectionException $e) { continue; } if (!$receivedProperty->isPublic()) { continue; } if ($receivedProperty->isStatic()) { continue; } $receivedPropertyType = $receivedProperty->getReadableType(); $typeMap = $typeMap->union($propertyType->inferTemplateTypes($receivedPropertyType)); } return $typeMap; } return TemplateTypeMap::createEmpty(); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { $variance = $positionVariance->compose(TemplateTypeVariance::createCovariant()); $references = []; foreach ($this->properties as $propertyType) { foreach ($propertyType->getReferencedTemplateTypes($variance) as $reference) { $references[] = $reference; } } return $references; } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { $callback = function () use($level) : string { $items = []; foreach ($this->properties as $name => $propertyType) { $optional = in_array($name, $this->optionalProperties, \true); $items[] = sprintf('%s%s: %s', $name, $optional ? '?' : '', $propertyType->describe($level)); } return sprintf('object{%s}', implode(', ', $items)); }; return $level->handle($callback, $callback); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getEnumCases() : array { return []; } public function traverse(callable $cb) : \PHPStan\Type\Type { $properties = []; $stillOriginal = \true; foreach ($this->properties as $name => $propertyType) { $transformed = $cb($propertyType); if ($transformed !== $propertyType) { $stillOriginal = \false; } $properties[$name] = $transformed; } if ($stillOriginal) { return $this; } return new self($properties, $this->optionalProperties); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if (!$right->isObject()->yes()) { return $this; } $properties = []; $stillOriginal = \true; $scope = new OutOfClassScope(); foreach ($this->properties as $name => $propertyType) { if (!$right->hasProperty($name)->yes()) { return $this; } $transformed = $cb($propertyType, $right->getProperty($name, $scope)->getReadableType()); if ($transformed !== $propertyType) { $stillOriginal = \false; } $properties[$name] = $transformed; } if ($stillOriginal) { return $this; } return new self($properties, $this->optionalProperties); } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { if (!$exponent instanceof \PHPStan\Type\NeverType && !$this->isSuperTypeOf($exponent)->no()) { return \PHPStan\Type\TypeCombinator::union($this, $exponent); } return new \PHPStan\Type\BenevolentUnionType([new \PHPStan\Type\FloatType(), new \PHPStan\Type\IntegerType()]); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { $items = []; foreach ($this->properties as $name => $type) { if (ConstantArrayType::isValidIdentifier($name)) { $keyNode = new IdentifierTypeNode($name); } else { $keyPhpDocNode = (new ConstantStringType($name))->toPhpDocNode(); if (!$keyPhpDocNode instanceof ConstTypeNode) { continue; } /** @var ConstExprStringNode $keyNode */ $keyNode = $keyPhpDocNode->constExpr; } $items[] = new ObjectShapeItemNode($keyNode, in_array($name, $this->optionalProperties, \true), $type->toPhpDocNode()); } return new ObjectShapeNode($items); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['properties'], $properties['optionalProperties']); } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, StrictMixedType $bound, ?Type $default) { $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } public function isSuperTypeOfMixed(MixedType $type) : TrinaryLogic { return $this->isSuperTypeOf($type); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, ArrayType $bound, ?Type $default) { parent::__construct($bound->getKeyType(), $bound->getItemType()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function shouldGeneralizeInferredType() : bool { return \false; } } */ private $types; /** * @var ?ClassReflection */ private $classReflection; /** * @var array */ private $variances; /** * @api * @param array $types * @param array $variances */ public function __construct(string $mainType, array $types, ?Type $subtractedType = null, ?ClassReflection $classReflection = null, array $variances = []) { $this->types = $types; $this->classReflection = $classReflection; $this->variances = $variances; parent::__construct($mainType, $subtractedType, $classReflection); } public function describe(VerbosityLevel $level) : string { return sprintf('%s<%s>', parent::describe($level), implode(', ', array_map(static function (Type $type, ?\PHPStan\Type\Generic\TemplateTypeVariance $variance = null) use($level) : string { return \PHPStan\Type\Generic\TypeProjectionHelper::describe($type, $variance, $level); }, $this->types, $this->variances))); } public function equals(Type $type) : bool { if (!$type instanceof self) { return \false; } if (!parent::equals($type)) { return \false; } if (count($this->types) !== count($type->types)) { return \false; } foreach ($this->types as $i => $genericType) { $otherGenericType = $type->types[$i]; if (!$genericType->equals($otherGenericType)) { return \false; } $variance = $this->variances[$i] ?? \PHPStan\Type\Generic\TemplateTypeVariance::createInvariant(); $otherVariance = $type->variances[$i] ?? \PHPStan\Type\Generic\TemplateTypeVariance::createInvariant(); if (!$variance->equals($otherVariance)) { return \false; } } return \true; } /** * @return string[] */ public function getReferencedClasses() : array { $classes = parent::getReferencedClasses(); foreach ($this->types as $type) { foreach ($type->getReferencedClasses() as $referencedClass) { $classes[] = $referencedClass; } } return $classes; } /** @return array */ public function getTypes() : array { return $this->types; } /** @return array */ public function getVariances() : array { return $this->variances; } public function accepts(Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return $this->isSuperTypeOfInternal($type, \true)->toAcceptsResult(); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } return $this->isSuperTypeOfInternal($type, \false); } private function isSuperTypeOfInternal(Type $type, bool $acceptsContext) : IsSuperTypeOfResult { $nakedSuperTypeOf = parent::isSuperTypeOfWithReason($type); if ($nakedSuperTypeOf->no()) { return $nakedSuperTypeOf; } if (!$type instanceof ObjectType) { return $nakedSuperTypeOf; } $ancestor = $type->getAncestorWithClassName($this->getClassName()); if ($ancestor === null) { return $nakedSuperTypeOf; } if (!$ancestor instanceof self) { if ($acceptsContext) { return $nakedSuperTypeOf; } return $nakedSuperTypeOf->and(IsSuperTypeOfResult::createMaybe()); } if (count($this->types) !== count($ancestor->types)) { return IsSuperTypeOfResult::createNo(); } $classReflection = $this->getClassReflection(); if ($classReflection === null) { return $nakedSuperTypeOf; } $typeList = $classReflection->typeMapToList($classReflection->getTemplateTypeMap()); $results = []; foreach ($typeList as $i => $templateType) { if (!isset($ancestor->types[$i])) { continue; } if (!isset($this->types[$i])) { continue; } if ($templateType instanceof ErrorType) { continue; } if (!$templateType instanceof \PHPStan\Type\Generic\TemplateType) { throw new ShouldNotHappenException(); } $thisVariance = $this->variances[$i] ?? \PHPStan\Type\Generic\TemplateTypeVariance::createInvariant(); $ancestorVariance = $ancestor->variances[$i] ?? \PHPStan\Type\Generic\TemplateTypeVariance::createInvariant(); if (!$thisVariance->invariant()) { $result = $thisVariance->isValidVarianceWithReason($templateType, $this->types[$i], $ancestor->types[$i]); $results[] = new IsSuperTypeOfResult($result->result, $result->reasons); } else { $result = $templateType->isValidVarianceWithReason($this->types[$i], $ancestor->types[$i]); $results[] = new IsSuperTypeOfResult($result->result, $result->reasons); } $results[] = IsSuperTypeOfResult::createFromBoolean($thisVariance->validPosition($ancestorVariance)); } if (count($results) === 0) { return $nakedSuperTypeOf; } $result = IsSuperTypeOfResult::createYes(); foreach ($results as $innerResult) { $result = $result->and($innerResult); } return $result; } public function getClassReflection() : ?ClassReflection { if ($this->classReflection !== null) { return $this->classReflection; } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (!$reflectionProvider->hasClass($this->getClassName())) { return null; } return $this->classReflection = $reflectionProvider->getClass($this->getClassName())->withTypes($this->types)->withVariances($this->variances); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { $prototype = parent::getUnresolvedPropertyPrototype($propertyName, $scope); return $prototype->doNotResolveTemplateTypeMapToBounds(); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { $prototype = parent::getUnresolvedMethodPrototype($methodName, $scope); return $prototype->doNotResolveTemplateTypeMapToBounds(); } public function inferTemplateTypes(Type $receivedType) : \PHPStan\Type\Generic\TemplateTypeMap { if ($receivedType instanceof UnionType || $receivedType instanceof IntersectionType) { return $receivedType->inferTemplateTypesOn($this); } if (!$receivedType instanceof TypeWithClassName) { return \PHPStan\Type\Generic\TemplateTypeMap::createEmpty(); } $ancestor = $receivedType->getAncestorWithClassName($this->getClassName()); if ($ancestor === null) { return \PHPStan\Type\Generic\TemplateTypeMap::createEmpty(); } $ancestorClassReflection = $ancestor->getClassReflection(); if ($ancestorClassReflection === null) { return \PHPStan\Type\Generic\TemplateTypeMap::createEmpty(); } $otherTypes = $ancestorClassReflection->typeMapToList($ancestorClassReflection->getActiveTemplateTypeMap()); $typeMap = \PHPStan\Type\Generic\TemplateTypeMap::createEmpty(); foreach ($this->getTypes() as $i => $type) { $other = $otherTypes[$i] ?? new ErrorType(); $typeMap = $typeMap->union($type->inferTemplateTypes($other)); } return $typeMap; } public function getReferencedTemplateTypes(\PHPStan\Type\Generic\TemplateTypeVariance $positionVariance) : array { $classReflection = $this->getClassReflection(); if ($classReflection !== null) { $typeList = $classReflection->typeMapToList($classReflection->getTemplateTypeMap()); } else { $typeList = []; } $references = []; foreach ($this->types as $i => $type) { $effectiveVariance = $this->variances[$i] ?? \PHPStan\Type\Generic\TemplateTypeVariance::createInvariant(); if ($effectiveVariance->invariant() && isset($typeList[$i]) && $typeList[$i] instanceof \PHPStan\Type\Generic\TemplateType) { $effectiveVariance = $typeList[$i]->getVariance(); } $variance = $positionVariance->compose($effectiveVariance); foreach ($type->getReferencedTemplateTypes($variance) as $reference) { $references[] = $reference; } } return $references; } public function traverse(callable $cb) : Type { $subtractedType = $this->getSubtractedType() !== null ? $cb($this->getSubtractedType()) : null; $typesChanged = \false; $types = []; foreach ($this->types as $type) { $newType = $cb($type); $types[] = $newType; if ($newType === $type) { continue; } $typesChanged = \true; } if ($subtractedType !== $this->getSubtractedType() || $typesChanged) { return $this->recreate($this->getClassName(), $types, $subtractedType, $this->variances); } return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { if (!$right instanceof TypeWithClassName) { return $this; } $ancestor = $right->getAncestorWithClassName($this->getClassName()); if (!$ancestor instanceof self) { return $this; } if (count($this->types) !== count($ancestor->types)) { return $this; } $typesChanged = \false; $types = []; foreach ($this->types as $i => $leftType) { $rightType = $ancestor->types[$i]; $newType = $cb($leftType, $rightType); $types[] = $newType; if ($newType === $leftType) { continue; } $typesChanged = \true; } if ($typesChanged) { return $this->recreate($this->getClassName(), $types, null); } return $this; } /** * @param Type[] $types * @param TemplateTypeVariance[] $variances */ protected function recreate(string $className, array $types, ?Type $subtractedType, array $variances = []) : self { return new self($className, $types, $subtractedType, null, $variances); } public function changeSubtractedType(?Type $subtractedType) : Type { return new self($this->getClassName(), $this->types, $subtractedType, null, $this->variances); } public function toPhpDocNode() : TypeNode { /** @var IdentifierTypeNode $parent */ $parent = parent::toPhpDocNode(); return new GenericTypeNode($parent, array_map(static function (Type $type) { return $type->toPhpDocNode(); }, $this->types), array_map(static function (\PHPStan\Type\Generic\TemplateTypeVariance $variance) { return $variance->toPhpDocNodeVariance(); }, $this->variances)); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['className'], $properties['types'], $properties['subtractedType'] ?? null, null, $properties['variances'] ?? []); } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, UnionType $bound, ?Type $default) { parent::__construct($bound->getTypes()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } public function filterTypes(callable $filterCb) : Type { $result = parent::filterTypes($filterCb); if (!$result instanceof \PHPStan\Type\Generic\TemplateType) { return \PHPStan\Type\Generic\TemplateTypeFactory::create($this->getScope(), $this->getName(), $result, $this->getVariance(), $this->getStrategy(), $this->getDefault()); } return $result; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, IntersectionType $bound, ?Type $default) { parent::__construct($bound->getTypes()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } } */ private $types; /** * @var array */ private $lowerBoundTypes; /** * @var ?TemplateTypeMap */ private static $empty = null; /** * @var ?TemplateTypeMap */ private $resolvedToBounds = null; /** * @api * @param array $types * @param array $lowerBoundTypes */ public function __construct(array $types, array $lowerBoundTypes = []) { $this->types = $types; $this->lowerBoundTypes = $lowerBoundTypes; } public function convertToLowerBoundTypes() : self { $lowerBoundTypes = $this->types; foreach ($this->lowerBoundTypes as $name => $type) { if (isset($lowerBoundTypes[$name])) { $intersection = TypeCombinator::intersect($lowerBoundTypes[$name], $type); if ($intersection instanceof NeverType) { continue; } $lowerBoundTypes[$name] = $intersection; } else { $lowerBoundTypes[$name] = $type; } } return new self([], $lowerBoundTypes); } public static function createEmpty() : self { $empty = self::$empty; if ($empty !== null) { return $empty; } $empty = new self([], []); self::$empty = $empty; return $empty; } public function isEmpty() : bool { return $this->count() === 0; } public function count() : int { return count($this->types + $this->lowerBoundTypes); } /** @return array */ public function getTypes() : array { $types = $this->types; foreach ($this->lowerBoundTypes as $name => $type) { if (array_key_exists($name, $types)) { continue; } $types[$name] = $type; } return $types; } public function hasType(string $name) : bool { return array_key_exists($name, $this->getTypes()); } public function getType(string $name) : ?Type { return $this->getTypes()[$name] ?? null; } public function unsetType(string $name) : self { if (!$this->hasType($name)) { return $this; } $types = $this->types; $lowerBoundTypes = $this->lowerBoundTypes; unset($types[$name]); unset($lowerBoundTypes[$name]); if (count($types) === 0 && count($lowerBoundTypes) === 0) { return self::createEmpty(); } return new self($types, $lowerBoundTypes); } public function union(self $other) : self { $result = $this->types; foreach ($other->types as $name => $type) { if (isset($result[$name])) { $result[$name] = TypeCombinator::union($result[$name], $type); } else { $result[$name] = $type; } } $resultLowerBoundTypes = $this->lowerBoundTypes; foreach ($other->lowerBoundTypes as $name => $type) { if (isset($resultLowerBoundTypes[$name])) { $intersection = TypeCombinator::intersect($resultLowerBoundTypes[$name], $type); if ($intersection instanceof NeverType) { continue; } $resultLowerBoundTypes[$name] = $intersection; } else { $resultLowerBoundTypes[$name] = $type; } } return new self($result, $resultLowerBoundTypes); } public function benevolentUnion(self $other) : self { $result = $this->types; foreach ($other->types as $name => $type) { if (isset($result[$name])) { $result[$name] = TypeUtils::toBenevolentUnion(TypeCombinator::union($result[$name], $type)); } else { $result[$name] = $type; } } $resultLowerBoundTypes = $this->lowerBoundTypes; foreach ($other->lowerBoundTypes as $name => $type) { if (isset($resultLowerBoundTypes[$name])) { $intersection = TypeCombinator::intersect($resultLowerBoundTypes[$name], $type); if ($intersection instanceof NeverType) { continue; } $resultLowerBoundTypes[$name] = $intersection; } else { $resultLowerBoundTypes[$name] = $type; } } return new self($result, $resultLowerBoundTypes); } public function intersect(self $other) : self { $result = $this->types; foreach ($other->types as $name => $type) { if (isset($result[$name])) { $result[$name] = TypeCombinator::intersect($result[$name], $type); } else { $result[$name] = $type; } } $resultLowerBoundTypes = $this->lowerBoundTypes; foreach ($other->lowerBoundTypes as $name => $type) { if (isset($resultLowerBoundTypes[$name])) { $resultLowerBoundTypes[$name] = TypeCombinator::union($resultLowerBoundTypes[$name], $type); } else { $resultLowerBoundTypes[$name] = $type; } } return new self($result, $resultLowerBoundTypes); } /** @param callable(string,Type):Type $cb */ public function map(callable $cb) : self { $types = []; foreach ($this->getTypes() as $name => $type) { $types[$name] = $cb($name, $type); } return new self($types); } public function resolveToBounds() : self { if ($this->resolvedToBounds !== null) { return $this->resolvedToBounds; } return $this->resolvedToBounds = $this->map(static function (string $name, Type $type) : Type { return TypeTraverser::map($type, static function (Type $type, callable $traverse) : Type { return $type instanceof \PHPStan\Type\Generic\TemplateType ? $traverse($type->getDefault() ?? $type->getBound()) : $traverse($type); }); }); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self($properties['types'], $properties['lowerBoundTypes'] ?? []); } } getReferencedTemplateTypes($positionVariance); return TypeTraverser::map($type, static function (Type $type, callable $traverse) use($standins, $references, $callSiteVariances, $keepErrorTypes) : Type { if ($type instanceof \PHPStan\Type\Generic\TemplateType && !$type->isArgument()) { $newType = $standins->getType($type->getName()); $variance = \PHPStan\Type\Generic\TemplateTypeVariance::createInvariant(); foreach ($references as $reference) { // this uses identity to distinguish between different occurrences of the same template type // see https://github.com/phpstan/phpstan-src/pull/2485#discussion_r1328555397 for details if ($reference->getType() === $type) { $variance = $reference->getPositionVariance(); break; } } if ($newType === null) { return $traverse($type); } if ($newType instanceof ErrorType && !$keepErrorTypes) { return $traverse($type->getDefault() ?? $type->getBound()); } $callSiteVariance = $callSiteVariances->getVariance($type->getName()); if ($callSiteVariance === null || $callSiteVariance->invariant()) { return $newType; } if (!$callSiteVariance->covariant() && $variance->covariant()) { return $traverse($type->getBound()); } if (!$callSiteVariance->contravariant() && $variance->contravariant()) { return new NonAcceptingNeverType(); } return $newType; } return $traverse($type); }); } public static function resolveToDefaults(Type $type) : Type { return TypeTraverser::map($type, static function (Type $type, callable $traverse) : Type { if ($type instanceof \PHPStan\Type\Generic\TemplateType) { return $traverse($type->getDefault() ?? $type->getBound()); } return $traverse($type); }); } public static function resolveToBounds(Type $type) : Type { return TypeTraverser::map($type, static function (Type $type, callable $traverse) : Type { if ($type instanceof \PHPStan\Type\Generic\TemplateType) { return $traverse($type->getBound()); } return $traverse($type); }); } /** * @template T of Type * @param T $type * @return T */ public static function toArgument(Type $type) : Type { $ownedTemplates = []; /** @var T */ return TypeTraverser::map($type, static function (Type $type, callable $traverse) use(&$ownedTemplates) : Type { if ($type instanceof ParametersAcceptor) { $templateTypeMap = $type->getTemplateTypeMap(); foreach ($type->getParameters() as $parameter) { $parameterType = $parameter->getType(); if (!$parameterType instanceof \PHPStan\Type\Generic\TemplateType || !$templateTypeMap->hasType($parameterType->getName())) { continue; } $ownedTemplates[] = $parameterType; } $returnType = $type->getReturnType(); if ($returnType instanceof \PHPStan\Type\Generic\TemplateType && $templateTypeMap->hasType($returnType->getName())) { $ownedTemplates[] = $returnType; } } foreach ($ownedTemplates as $ownedTemplate) { if ($ownedTemplate === $type) { return $traverse($type); } } if ($type instanceof \PHPStan\Type\Generic\TemplateType) { return $traverse($type->toArgument()); } return $traverse($type); }); } public static function generalizeInferredTemplateType(\PHPStan\Type\Generic\TemplateType $templateType, Type $type) : Type { if (!$templateType->getVariance()->covariant()) { $isArrayKey = $templateType->getBound()->describe(VerbosityLevel::precise()) === '(int|string)'; if ($type->isScalar()->yes() && $isArrayKey) { $type = $type->generalize(GeneralizePrecision::templateArgument()); } elseif ($type->isConstantValue()->yes() && (!$templateType->getBound()->isScalar()->yes() || $isArrayKey)) { $type = $type->generalize(GeneralizePrecision::templateArgument()); } } return $type; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, KeyOfType $bound, ?Type $default) { parent::__construct($bound->getType()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function getResult() : Type { $result = $this->getBound()->getResult(); return \PHPStan\Type\Generic\TemplateTypeFactory::create($this->getScope(), $this->getName(), $result, $this->getVariance(), $this->getStrategy(), $this->getDefault()); } protected function shouldGeneralizeInferredType() : bool { return \false; } } isAcceptedWithReasonBy($left, $strictTypes); } else { $accepts = $left->getBound()->acceptsWithReason($right, $strictTypes)->and(AcceptsResult::createMaybe()); if ($accepts->maybe()) { $verbosity = VerbosityLevel::getRecommendedLevelByType($left, $right); return new AcceptsResult($accepts->result, array_merge($accepts->reasons, [sprintf('Type %s is not always the same as %s. It breaks the contract for some argument types, typically subtypes.', $right->describe($verbosity), $left->getName())])); } } return $accepts; } public function isArgument() : bool { return \true; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self(); } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, ObjectType $bound, ?Type $default) { parent::__construct($bound->getClassName()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } } */ private $types; /** * @var ?Type */ private $subtractedType; /** * @var array */ private $variances; /** * @var ?ObjectType */ private $staticObjectType = null; /** * @var string */ private $baseClass; /** * @api * @param array $types * @param array $variances */ public function __construct(ClassReflection $classReflection, array $types, ?Type $subtractedType, array $variances) { $this->classReflection = $classReflection; $this->types = $types; $this->subtractedType = $subtractedType; $this->variances = $variances; if (count($this->types) === 0) { throw new ShouldNotHappenException('Cannot create GenericStaticType with zero types.'); } parent::__construct($classReflection, $subtractedType); $this->baseClass = $classReflection->getName(); } public function getClassName() : string { return $this->baseClass; } /** * @return array */ public function getTypes() : array { return $this->types; } /** @return array */ public function getVariances() : array { return $this->variances; } public function getStaticObjectType() : ObjectType { if ($this->staticObjectType === null) { if ($this->classReflection->isGeneric()) { return $this->staticObjectType = new \PHPStan\Type\Generic\GenericObjectType($this->classReflection->getName(), $this->types, $this->subtractedType, $this->classReflection, $this->variances); } return $this->staticObjectType = parent::getStaticObjectType(); } return $this->staticObjectType; } public function changeBaseClass(ClassReflection $classReflection) : StaticType { if ($classReflection->getName() === $this->getClassName()) { return $this; } if (!$classReflection->isGeneric()) { return new StaticType($classReflection); } $templateTags = $this->getClassReflection()->getTemplateTags(); $i = 0; $indexedTypes = []; $indexedVariances = []; foreach ($templateTags as $typeName => $tag) { if (!array_key_exists($i, $this->types)) { break; } if (!array_key_exists($i, $this->variances)) { break; } $indexedTypes[$typeName] = $this->types[$i]; $indexedVariances[$typeName] = $this->variances[$i]; $i++; } $newType = new \PHPStan\Type\Generic\GenericObjectType($classReflection->getName(), $classReflection->typeMapToList($classReflection->getTemplateTypeMap())); $ancestorType = $newType->getAncestorWithClassName($this->getClassName()); if ($ancestorType === null) { return new self($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), $this->subtractedType, $classReflection->varianceMapToList($classReflection->getCallSiteVarianceMap())); } $ancestorClassReflection = $ancestorType->getClassReflection(); if ($ancestorClassReflection === null) { return new self($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), $this->subtractedType, $classReflection->varianceMapToList($classReflection->getCallSiteVarianceMap())); } $newClassTypes = []; $newClassVariances = []; foreach ($ancestorClassReflection->getActiveTemplateTypeMap()->getTypes() as $typeName => $templateType) { if (!$templateType instanceof \PHPStan\Type\Generic\TemplateType) { continue; } if (!array_key_exists($typeName, $indexedTypes)) { continue; } $newClassTypes[$templateType->getName()] = $indexedTypes[$typeName]; $newClassVariances[$templateType->getName()] = $indexedVariances[$typeName]; } return new self($classReflection, $classReflection->typeMapToList(new \PHPStan\Type\Generic\TemplateTypeMap($newClassTypes)), $this->subtractedType, $classReflection->varianceMapToList(new \PHPStan\Type\Generic\TemplateTypeVarianceMap($newClassVariances))); } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($type instanceof self) { return $this->getStaticObjectType()->isSuperTypeOfWithReason($type->getStaticObjectType()); } return parent::isSuperTypeOfWithReason($type)->and(IsSuperTypeOfResult::createMaybe()); } public function traverse(callable $cb) : Type { $subtractedType = $this->getSubtractedType() !== null ? $cb($this->getSubtractedType()) : null; $typesChanged = \false; $types = []; foreach ($this->types as $type) { $newType = $cb($type); $types[] = $newType; if ($newType === $type) { continue; } $typesChanged = \true; } if ($subtractedType !== $this->getSubtractedType() || $typesChanged) { return new self($this->classReflection, $types, $subtractedType, $this->variances); } return $this; } public function traverseSimultaneously(Type $right, callable $cb) : Type { if (!$right instanceof TypeWithClassName) { return $this; } $ancestor = $right->getAncestorWithClassName($this->getClassName()); if (!$ancestor instanceof self) { return $this; } if (count($this->types) !== count($ancestor->types)) { return $this; } $typesChanged = \false; $types = []; foreach ($this->types as $i => $leftType) { $rightType = $ancestor->types[$i]; $newType = $cb($leftType, $rightType); $types[] = $newType; if ($newType === $leftType) { continue; } $typesChanged = \true; } if ($typesChanged) { return new self($this->classReflection, $types, null, $this->variances); } return $this; } public function changeSubtractedType(?Type $subtractedType) : Type { if ($subtractedType !== null) { $classReflection = $this->getClassReflection(); if ($classReflection->getAllowedSubTypes() !== null) { $objectType = $this->getStaticObjectType()->changeSubtractedType($subtractedType); if ($objectType instanceof NeverType) { return $objectType; } if ($objectType instanceof ObjectType && $objectType->getSubtractedType() !== null) { return new self($classReflection, $this->types, $objectType->getSubtractedType(), $this->variances); } return TypeCombinator::intersect($this, $objectType); } } return new self($this->classReflection, $this->types, $subtractedType, $this->variances); } public function inferTemplateTypes(Type $receivedType) : \PHPStan\Type\Generic\TemplateTypeMap { return $this->getStaticObjectType()->inferTemplateTypes($receivedType); } public function getReferencedTemplateTypes(\PHPStan\Type\Generic\TemplateTypeVariance $positionVariance) : array { return $this->getStaticObjectType()->getReferencedTemplateTypes($positionVariance); } public function toPhpDocNode() : TypeNode { /** @var IdentifierTypeNode $parent */ $parent = parent::toPhpDocNode(); return new GenericTypeNode($parent, array_map(static function (Type $type) { return $type->toPhpDocNode(); }, $this->types), array_map(static function (\PHPStan\Type\Generic\TemplateTypeVariance $variance) { return $variance->toPhpDocNodeVariance(); }, $this->variances)); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if ($reflectionProvider->hasClass($properties['baseClass'])) { return new self($reflectionProvider->getClass($properties['baseClass']), $properties['types'], $properties['subtractedType'], $properties['variances']); } return new ErrorType(); } } describe($level); if ($variance === null || $variance->invariant()) { return $describedType; } if ($variance->bivariant()) { return '*'; } return sprintf('%s %s', $variance->describe(), $describedType); } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, IterableType $bound, ?Type $default) { parent::__construct($bound->getKeyType(), $bound->getItemType()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } } isAcceptedWithReasonBy($left, $strictTypes); } return $left->getBound()->acceptsWithReason($right, $strictTypes); } public function isArgument() : bool { return \false; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self(); } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, StringType $bound, ?Type $default) { parent::__construct(); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function shouldGeneralizeInferredType() : bool { return \false; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, ObjectWithoutClassType $bound, ?Type $default) { parent::__construct(); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, ConstantStringType $bound, ?Type $default) { parent::__construct($bound->getValue()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function shouldGeneralizeInferredType() : bool { return \false; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, ObjectShapeType $bound, ?Type $default) { parent::__construct($bound->getProperties(), $bound->getOptionalProperties()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function shouldGeneralizeInferredType() : bool { return \false; } } name; } public function getScope() : \PHPStan\Type\Generic\TemplateTypeScope { return $this->scope; } /** @return TBound */ public function getBound() : Type { return $this->bound; } public function getDefault() : ?Type { return $this->default; } public function describe(VerbosityLevel $level) : string { $basicDescription = function () use($level) : string { // @phpstan-ignore booleanAnd.alwaysFalse, instanceof.alwaysFalse, booleanAnd.alwaysFalse, instanceof.alwaysFalse, instanceof.alwaysTrue if ($this->bound instanceof MixedType && $this->bound->getSubtractedType() === null && !$this->bound instanceof \PHPStan\Type\Generic\TemplateMixedType) { $boundDescription = ''; } else { $boundDescription = sprintf(' of %s', $this->bound->describe($level)); } $defaultDescription = $this->default !== null ? sprintf(' = %s', $this->default->describe($level)) : ''; return sprintf('%s%s%s', $this->name, $boundDescription, $defaultDescription); }; return $level->handle($basicDescription, $basicDescription, function () use($basicDescription) : string { return sprintf('%s (%s, %s)', $basicDescription(), $this->scope->describe(), $this->isArgument() ? 'argument' : 'parameter'); }); } public function isArgument() : bool { return $this->strategy->isArgument(); } public function toArgument() : \PHPStan\Type\Generic\TemplateType { return new self($this->scope, new \PHPStan\Type\Generic\TemplateTypeArgumentStrategy(), $this->variance, $this->name, \PHPStan\Type\Generic\TemplateTypeHelper::toArgument($this->getBound()), $this->default !== null ? \PHPStan\Type\Generic\TemplateTypeHelper::toArgument($this->default) : null); } public function isValidVariance(Type $a, Type $b) : TrinaryLogic { return $this->isValidVarianceWithReason($a, $b)->result; } public function isValidVarianceWithReason(Type $a, Type $b) : AcceptsResult { return $this->variance->isValidVarianceWithReason($this, $a, $b); } public function subtract(Type $typeToRemove) : Type { $removedBound = TypeCombinator::remove($this->getBound(), $typeToRemove); return \PHPStan\Type\Generic\TemplateTypeFactory::create($this->getScope(), $this->getName(), $removedBound, $this->getVariance(), $this->getStrategy(), $this->getDefault()); } public function getTypeWithoutSubtractedType() : Type { $bound = $this->getBound(); if (!$bound instanceof SubtractableType) { // @phpstan-ignore instanceof.alwaysTrue return $this; } return \PHPStan\Type\Generic\TemplateTypeFactory::create($this->getScope(), $this->getName(), $bound->getTypeWithoutSubtractedType(), $this->getVariance(), $this->getStrategy(), $this->getDefault()); } public function changeSubtractedType(?Type $subtractedType) : Type { $bound = $this->getBound(); if (!$bound instanceof SubtractableType) { // @phpstan-ignore instanceof.alwaysTrue return $this; } return \PHPStan\Type\Generic\TemplateTypeFactory::create($this->getScope(), $this->getName(), $bound->changeSubtractedType($subtractedType), $this->getVariance(), $this->getStrategy(), $this->getDefault()); } public function getSubtractedType() : ?Type { $bound = $this->getBound(); if (!$bound instanceof SubtractableType) { // @phpstan-ignore instanceof.alwaysTrue return null; } return $bound->getSubtractedType(); } public function equals(Type $type) : bool { return $type instanceof self && $type->scope->equals($this->scope) && $type->name === $this->name && $this->bound->equals($type->bound) && ($this->default === null && $type->default === null || $this->default !== null && $type->default !== null && $this->default->equals($type->default)); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { /** @var TBound $bound */ $bound = $this->getBound(); if (!$acceptingType instanceof $bound && !$this instanceof $acceptingType && !$acceptingType instanceof \PHPStan\Type\Generic\TemplateType && ($acceptingType instanceof UnionType || $acceptingType instanceof IntersectionType)) { return $acceptingType->acceptsWithReason($this, $strictTypes); } if (!$acceptingType instanceof \PHPStan\Type\Generic\TemplateType) { return $acceptingType->acceptsWithReason($this->getBound(), $strictTypes); } if ($this->getScope()->equals($acceptingType->getScope()) && $this->getName() === $acceptingType->getName()) { return $acceptingType->getBound()->acceptsWithReason($this->getBound(), $strictTypes); } return $acceptingType->getBound()->acceptsWithReason($this->getBound(), $strictTypes)->and(new AcceptsResult(TrinaryLogic::createMaybe(), [])); } public function accepts(Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { return $this->strategy->accepts($this, $type, $strictTypes); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\Generic\TemplateType || $type instanceof IntersectionType) { return $type->isSubTypeOfWithReason($this); } if ($type instanceof NeverType) { return IsSuperTypeOfResult::createYes(); } return $this->getBound()->isSuperTypeOfWithReason($type)->and(IsSuperTypeOfResult::createMaybe()); } public function isSubTypeOf(Type $type) : TrinaryLogic { return $this->isSubTypeOfWithReason($type)->result; } public function isSubTypeOfWithReason(Type $type) : IsSuperTypeOfResult { /** @var TBound $bound */ $bound = $this->getBound(); if (!$type instanceof $bound && !$this instanceof $type && !$type instanceof \PHPStan\Type\Generic\TemplateType && ($type instanceof UnionType || $type instanceof IntersectionType)) { return $type->isSuperTypeOfWithReason($this); } if (!$type instanceof \PHPStan\Type\Generic\TemplateType) { return $type->isSuperTypeOfWithReason($this->getBound()); } if ($this->getScope()->equals($type->getScope()) && $this->getName() === $type->getName()) { return $type->getBound()->isSuperTypeOfWithReason($this->getBound()); } return $type->getBound()->isSuperTypeOfWithReason($this->getBound())->and(IsSuperTypeOfResult::createMaybe()); } public function toArrayKey() : Type { return $this; } public function inferTemplateTypes(Type $receivedType) : \PHPStan\Type\Generic\TemplateTypeMap { if ($receivedType instanceof \PHPStan\Type\Generic\TemplateType && $this->getBound()->isSuperTypeOf($receivedType->getBound())->yes()) { return new \PHPStan\Type\Generic\TemplateTypeMap([$this->name => $receivedType]); } $map = $this->getBound()->inferTemplateTypes($receivedType); $resolvedBound = TypeUtils::resolveLateResolvableTypes(\PHPStan\Type\Generic\TemplateTypeHelper::resolveTemplateTypes($this->getBound(), $map, \PHPStan\Type\Generic\TemplateTypeVarianceMap::createEmpty(), \PHPStan\Type\Generic\TemplateTypeVariance::createStatic())); if ($resolvedBound->isSuperTypeOf($receivedType)->yes()) { if (!BleedingEdgeToggle::isBleedingEdge() && $this->shouldGeneralizeInferredType()) { $generalizedType = $receivedType->generalize(GeneralizePrecision::templateArgument()); if ($resolvedBound->isSuperTypeOf($generalizedType)->yes()) { $receivedType = $generalizedType; } } return (new \PHPStan\Type\Generic\TemplateTypeMap([$this->name => $receivedType]))->union($map); } return $map; } public function getReferencedTemplateTypes(\PHPStan\Type\Generic\TemplateTypeVariance $positionVariance) : array { return [new \PHPStan\Type\Generic\TemplateTypeReference($this, $positionVariance)]; } public function getVariance() : \PHPStan\Type\Generic\TemplateTypeVariance { return $this->variance; } public function getStrategy() : \PHPStan\Type\Generic\TemplateTypeStrategy { return $this->strategy; } protected function shouldGeneralizeInferredType() : bool { return \true; } public function traverse(callable $cb) : Type { $bound = $cb($this->getBound()); $default = $this->getDefault() !== null ? $cb($this->getDefault()) : null; if ($this->getBound() === $bound && $this->getDefault() === $default) { return $this; } return \PHPStan\Type\Generic\TemplateTypeFactory::create($this->getScope(), $this->getName(), $bound, $this->getVariance(), $this->getStrategy(), $default); } public function traverseSimultaneously(Type $right, callable $cb) : Type { if (!$right instanceof \PHPStan\Type\Generic\TemplateType) { return $this; } $bound = $cb($this->getBound(), $right->getBound()); $default = $this->getDefault() !== null && $right->getDefault() !== null ? $cb($this->getDefault(), $right->getDefault()) : null; if ($this->getBound() === $bound && $this->getDefault() === $default) { return $this; } return \PHPStan\Type\Generic\TemplateTypeFactory::create($this->getScope(), $this->getName(), $bound, $this->getVariance(), $this->getStrategy(), $default); } public function tryRemove(Type $typeToRemove) : ?Type { $bound = TypeCombinator::remove($this->getBound(), $typeToRemove); if ($this->getBound() === $bound) { return null; } return \PHPStan\Type\Generic\TemplateTypeFactory::create($this->getScope(), $this->getName(), $bound, $this->getVariance(), $this->getStrategy(), $this->getDefault()); } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode($this->name); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['scope'], $properties['strategy'], $properties['variance'], $properties['name'], $properties['bound'], $properties['default'] ?? null); } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, BooleanType $bound, ?Type $default) { parent::__construct(); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function shouldGeneralizeInferredType() : bool { return \false; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, \PHPStan\Type\Generic\GenericObjectType $bound, ?Type $default) { parent::__construct($bound->getClassName(), $bound->getTypes(), null, null, $bound->getVariances()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function recreate(string $className, array $types, ?Type $subtractedType, array $variances = []) : \PHPStan\Type\Generic\GenericObjectType { return new self($this->scope, $this->strategy, $this->variance, $this->name, $this->getBound(), $this->default); } } type = $type; $this->positionVariance = $positionVariance; } public function getType() : \PHPStan\Type\Generic\TemplateType { return $this->type; } public function getPositionVariance() : \PHPStan\Type\Generic\TemplateTypeVariance { return $this->positionVariance; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, IntegerType $bound, ?Type $default) { parent::__construct(); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function shouldGeneralizeInferredType() : bool { return \false; } } type = $type; parent::__construct(); } public function getReferencedClasses() : array { return $this->type->getReferencedClasses(); } public function getGenericType() : Type { return $this->type; } public function getClassStringObjectType() : Type { return $this->getGenericType(); } public function getObjectTypeOrClassStringObjectType() : Type { return $this->getClassStringObjectType(); } public function describe(VerbosityLevel $level) : string { return sprintf('%s<%s>', parent::describe($level), $this->type->describe($level)); } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } if ($type instanceof ConstantStringType) { if (!$type->isClassStringType()->yes()) { return AcceptsResult::createNo(); } $objectType = new ObjectType($type->getValue()); } elseif ($type instanceof self) { $objectType = $type->type; } elseif ($type instanceof ClassStringType) { $objectType = new ObjectWithoutClassType(); } elseif ($type instanceof StringType) { return AcceptsResult::createMaybe(); } else { return AcceptsResult::createNo(); } return $this->type->acceptsWithReason($objectType, $strictTypes); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } if ($type instanceof ConstantStringType) { $genericType = $this->type; if ($genericType instanceof MixedType) { return IsSuperTypeOfResult::createYes(); } if ($genericType instanceof StaticType) { $genericType = $genericType->getStaticObjectType(); } // We are transforming constant class-string to ObjectType. But we need to filter out // an uncertainty originating in possible ObjectType's class subtypes. $objectType = new ObjectType($type->getValue()); // Do not use TemplateType's isSuperTypeOf handling directly because it takes ObjectType // uncertainty into account. if ($genericType instanceof \PHPStan\Type\Generic\TemplateType) { $isSuperType = $genericType->getBound()->isSuperTypeOfWithReason($objectType); } else { $isSuperType = $genericType->isSuperTypeOfWithReason($objectType); } if (!$type->isClassStringType()->yes()) { $isSuperType = $isSuperType->and(IsSuperTypeOfResult::createMaybe()); } return $isSuperType; } elseif ($type instanceof self) { return $this->type->isSuperTypeOfWithReason($type->type); } elseif ($type instanceof StringType) { return IsSuperTypeOfResult::createMaybe(); } return IsSuperTypeOfResult::createNo(); } public function traverse(callable $cb) : Type { $newType = $cb($this->type); if ($newType === $this->type) { return $this; } return new self($newType); } public function traverseSimultaneously(Type $right, callable $cb) : Type { $newType = $cb($this->type, $right->getClassStringObjectType()); if ($newType === $this->type) { return $this; } return new self($newType); } public function inferTemplateTypes(Type $receivedType) : \PHPStan\Type\Generic\TemplateTypeMap { if ($receivedType instanceof UnionType || $receivedType instanceof IntersectionType) { return $receivedType->inferTemplateTypesOn($this); } if ($receivedType instanceof ConstantStringType) { $typeToInfer = new ObjectType($receivedType->getValue()); } elseif ($receivedType instanceof self) { $typeToInfer = $receivedType->type; } elseif ($receivedType->isClassStringType()->yes()) { $typeToInfer = $this->type; if ($typeToInfer instanceof \PHPStan\Type\Generic\TemplateType) { $typeToInfer = $typeToInfer->getBound(); } $typeToInfer = TypeCombinator::intersect($typeToInfer, new ObjectWithoutClassType()); } else { return \PHPStan\Type\Generic\TemplateTypeMap::createEmpty(); } return $this->type->inferTemplateTypes($typeToInfer); } public function getReferencedTemplateTypes(\PHPStan\Type\Generic\TemplateTypeVariance $positionVariance) : array { $variance = $positionVariance->compose(\PHPStan\Type\Generic\TemplateTypeVariance::createCovariant()); return $this->type->getReferencedTemplateTypes($variance); } public function equals(Type $type) : bool { if (!$type instanceof self) { return \false; } if (!parent::equals($type)) { return \false; } if (!$this->type->equals($type->type)) { return \false; } return \true; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : Type { return new self($properties['type']); } public function toPhpDocNode() : TypeNode { return new GenericTypeNode(new IdentifierTypeNode('class-string'), [$this->type->toPhpDocNode()]); } public function tryRemove(Type $typeToRemove) : ?Type { if ($typeToRemove instanceof ConstantStringType && $typeToRemove->isClassStringType()->yes()) { $generic = $this->getGenericType(); $genericObjectClassNames = $generic->getObjectClassNames(); if (count($genericObjectClassNames) === 1) { $classReflection = ReflectionProviderStaticAccessor::getInstance()->getClass($genericObjectClassNames[0]); if ($classReflection->isFinal() && $genericObjectClassNames[0] === $typeToRemove->getValue()) { return new NeverType(); } } } return parent::tryRemove($typeToRemove); } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, ConstantIntegerType $bound, ?Type $default) { parent::__construct($bound->getValue()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function shouldGeneralizeInferredType() : bool { return \false; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, ConstantArrayType $bound, ?Type $default) { parent::__construct($bound->getKeyTypes(), $bound->getValueTypes(), $bound->getNextAutoIndexes(), $bound->getOptionalKeys(), $bound->isList()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function shouldGeneralizeInferredType() : bool { return \false; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; use UndecidedComparisonCompoundTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, FloatType $bound, ?Type $default) { parent::__construct(); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } protected function shouldGeneralizeInferredType() : bool { return \false; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, BenevolentUnionType $bound, ?Type $default) { parent::__construct($bound->getTypes()); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } /** @param Type[] $types */ public function withTypes(array $types) : self { return new self($this->scope, $this->strategy, $this->variance, $this->name, new BenevolentUnionType($types), $this->default); } public function filterTypes(callable $filterCb) : Type { $result = parent::filterTypes($filterCb); if (!$result instanceof \PHPStan\Type\Generic\TemplateType) { return \PHPStan\Type\Generic\TemplateTypeFactory::create($this->getScope(), $this->getName(), $result, $this->getVariance(), $this->getStrategy(), $this->getDefault()); } return $result; } } value = $value; } private static function create(int $value) : self { self::$registry[$value] = self::$registry[$value] ?? new self($value); return self::$registry[$value]; } public static function createInvariant() : self { return self::create(self::INVARIANT); } public static function createCovariant() : self { return self::create(self::COVARIANT); } public static function createContravariant() : self { return self::create(self::CONTRAVARIANT); } public static function createStatic() : self { return self::create(self::STATIC); } public static function createBivariant() : self { return self::create(self::BIVARIANT); } public function invariant() : bool { return $this->value === self::INVARIANT; } public function covariant() : bool { return $this->value === self::COVARIANT; } public function contravariant() : bool { return $this->value === self::CONTRAVARIANT; } public function static() : bool { return $this->value === self::STATIC; } public function bivariant() : bool { return $this->value === self::BIVARIANT; } public function compose(self $other) : self { if ($this->contravariant()) { if ($other->contravariant()) { return self::createCovariant(); } if ($other->covariant()) { return self::createContravariant(); } if ($other->bivariant()) { return self::createBivariant(); } return self::createInvariant(); } if ($this->covariant()) { if ($other->contravariant()) { return self::createContravariant(); } if ($other->covariant()) { return self::createCovariant(); } if ($other->bivariant()) { return self::createBivariant(); } return self::createInvariant(); } if (self::$invarianceCompositionEnabled && $this->invariant()) { return self::createInvariant(); } if ($this->bivariant()) { return self::createBivariant(); } return $other; } public function isValidVariance(Type $a, Type $b) : TrinaryLogic { return $this->isValidVarianceWithReason(null, $a, $b)->result; } public function isValidVarianceWithReason(?\PHPStan\Type\Generic\TemplateType $templateType, Type $a, Type $b) : AcceptsResult { if ($b instanceof NeverType) { return AcceptsResult::createYes(); } if ($a instanceof MixedType && !$a instanceof \PHPStan\Type\Generic\TemplateType) { return AcceptsResult::createYes(); } if ($a instanceof BenevolentUnionType) { if (!$a->isSuperTypeOf($b)->no()) { return AcceptsResult::createYes(); } } if ($b instanceof BenevolentUnionType) { if (!$b->isSuperTypeOf($a)->no()) { return AcceptsResult::createYes(); } } if ($b instanceof MixedType && !$b instanceof \PHPStan\Type\Generic\TemplateType) { return AcceptsResult::createYes(); } if ($this->invariant()) { $result = $a->equals($b); $reasons = []; if (!$result) { if ($templateType !== null && $templateType->getScope()->getClassName() !== null && $a->isSuperTypeOf($b)->yes()) { $reasons[] = sprintf('Template type %s on class %s is not covariant. Learn more: https://phpstan.org/blog/whats-up-with-template-covariant', $templateType->getName(), $templateType->getScope()->getClassName()); } } return new AcceptsResult(TrinaryLogic::createFromBoolean($result), $reasons); } if ($this->covariant()) { return $a->isSuperTypeOfWithReason($b)->toAcceptsResult(); } if ($this->contravariant()) { return $b->isSuperTypeOfWithReason($a)->toAcceptsResult(); } if ($this->bivariant()) { return AcceptsResult::createYes(); } throw new ShouldNotHappenException(); } public function equals(self $other) : bool { return $other->value === $this->value; } public function validPosition(self $other) : bool { return $other->value === $this->value || $other->invariant() || $this->bivariant() || $this->static(); } public function describe() : string { switch ($this->value) { case self::INVARIANT: return 'invariant'; case self::COVARIANT: return 'covariant'; case self::CONTRAVARIANT: return 'contravariant'; case self::STATIC: return 'static'; case self::BIVARIANT: return 'bivariant'; } throw new ShouldNotHappenException(); } /** * @return GenericTypeNode::VARIANCE_* */ public function toPhpDocNodeVariance() : string { switch ($this->value) { case self::INVARIANT: return GenericTypeNode::VARIANCE_INVARIANT; case self::COVARIANT: return GenericTypeNode::VARIANCE_COVARIANT; case self::CONTRAVARIANT: return GenericTypeNode::VARIANCE_CONTRAVARIANT; case self::BIVARIANT: return GenericTypeNode::VARIANCE_BIVARIANT; } throw new ShouldNotHappenException(); } /** * @param array{value: int} $properties */ public static function __set_state(array $properties) : self { return new self($properties['value']); } public static function setInvarianceCompositionEnabled(bool $enabled) : void { self::$invarianceCompositionEnabled = $enabled; } } getName(), $tag->getBound(), $tag->getVariance(), null, $tag->getDefault()); } } className = $className; $this->functionName = $functionName; } /** @api */ public function getClassName() : ?string { return $this->className; } /** @api */ public function getFunctionName() : ?string { return $this->functionName; } /** @api */ public function equals(self $other) : bool { return $this->className === $other->className && $this->functionName === $other->functionName; } /** @api */ public function describe() : string { if ($this->className === null && $this->functionName === null) { return 'anonymous function'; } if ($this->className === null) { return sprintf('function %s()', $this->functionName); } if ($this->functionName === null) { return sprintf('class %s', $this->className); } return sprintf('method %s::%s()', $this->className, $this->functionName); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self($properties['className'], $properties['functionName']); } } */ private $variances; /** * @var ?TemplateTypeVarianceMap */ private static $empty = null; /** * @api * @param array $variances */ public function __construct(array $variances) { $this->variances = $variances; } public static function createEmpty() : self { $empty = self::$empty; if ($empty !== null) { return $empty; } $empty = new self([]); self::$empty = $empty; return $empty; } /** @return array */ public function getVariances() : array { return $this->variances; } public function hasVariance(string $name) : bool { return array_key_exists($name, $this->getVariances()); } public function getVariance(string $name) : ?\PHPStan\Type\Generic\TemplateTypeVariance { return $this->getVariances()[$name] ?? null; } } */ use \PHPStan\Type\Generic\TemplateTypeTrait; /** * @param non-empty-string $name */ public function __construct(\PHPStan\Type\Generic\TemplateTypeScope $scope, \PHPStan\Type\Generic\TemplateTypeStrategy $templateTypeStrategy, \PHPStan\Type\Generic\TemplateTypeVariance $templateTypeVariance, string $name, MixedType $bound, ?Type $default) { parent::__construct(\true); $this->scope = $scope; $this->strategy = $templateTypeStrategy; $this->variance = $templateTypeVariance; $this->name = $name; $this->bound = $bound; $this->default = $default; } public function isSuperTypeOfMixed(MixedType $type) : TrinaryLogic { return $this->isSuperTypeOf($type); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { $isSuperType = $this->isSuperTypeOfWithReason($acceptingType)->toAcceptsResult(); if ($isSuperType->no()) { return $isSuperType; } return AcceptsResult::createYes(); } public function toStrictMixedType() : \PHPStan\Type\Generic\TemplateStrictMixedType { return new \PHPStan\Type\Generic\TemplateStrictMixedType($this->scope, $this->strategy, $this->variance, $this->name, new StrictMixedType(), $this->default); } } getValue()); * } * // Replaces the current type, and don't traverse * return new MixedType(); * }); * * @api * @param callable(Type $type, callable(Type): Type $traverse): Type $cb */ public static function map(\PHPStan\Type\Type $type, callable $cb) : \PHPStan\Type\Type { $self = new self($cb); return $self->mapInternal($type); } /** @param callable(Type $type, callable(Type): Type $traverse): Type $cb */ private function __construct(callable $cb) { $this->cb = $cb; } /** @internal */ public function mapInternal(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return ($this->cb)($type, [$this, 'traverseInternal']); } /** @internal */ public function traverseInternal(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->traverse([$this, 'mapInternal']); } } isExplicit = $isExplicit; } public function isExplicit() : bool { return $this->isExplicit; } /** * @return string[] */ public function getReferencedClasses() : array { return []; } public function getArrays() : array { return []; } public function getConstantArrays() : array { return []; } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function getConstantStrings() : array { return []; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { return \PHPStan\Type\AcceptsResult::createYes(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self; } public function isSubTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return '*NEVER*'; } public function getTemplateType(string $ancestorClassName, string $templateTypeName) : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function isObject() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isEnum() : TrinaryLogic { return TrinaryLogic::createNo(); } public function canAccessProperties() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasProperty(string $propertyName) : TrinaryLogic { return TrinaryLogic::createNo(); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { throw new ShouldNotHappenException(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { throw new ShouldNotHappenException(); } public function canCallMethods() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasMethod(string $methodName) : TrinaryLogic { return TrinaryLogic::createNo(); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { throw new ShouldNotHappenException(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { throw new ShouldNotHappenException(); } public function canAccessConstants() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasConstant(string $constantName) : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstant(string $constantName) : ConstantReflection { throw new ShouldNotHappenException(); } public function isIterable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isIterableAtLeastOnce() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getArraySize() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getIterableKeyType() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getFirstIterableKeyType() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getLastIterableKeyType() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getIterableValueType() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getFirstIterableValueType() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getLastIterableValueType() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function isArray() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantArray() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isOversizedArray() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isList() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isOffsetAccessible() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isOffsetAccessLegal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { return TrinaryLogic::createYes(); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getKeysArray() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function getValuesArray() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function fillKeysArray(\PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function flipArray() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType) : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function popArray() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function reverseArray(TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function searchArray(\PHPStan\Type\Type $needleType) : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function shiftArray() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function shuffleArray() : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return new \PHPStan\Type\NeverType(); } public function isCallable() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { throw new ShouldNotHappenException(); } public function isCloneable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function toNumber() : \PHPStan\Type\Type { return $this; } public function toAbsoluteNumber() : \PHPStan\Type\Type { return $this; } public function toString() : \PHPStan\Type\Type { return $this; } public function toInteger() : \PHPStan\Type\Type { return $this; } public function toFloat() : \PHPStan\Type\Type { return $this; } public function toArray() : \PHPStan\Type\Type { return $this; } public function toArrayKey() : \PHPStan\Type\Type { return $this; } public function traverse(callable $cb) : \PHPStan\Type\Type { return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { return $this; } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return new \PHPStan\Type\ErrorType(); } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function getEnumCases() : array { return []; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return $this; } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('never'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['isExplicit']); } } isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof parent) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { if ($type instanceof \PHPStan\Type\NeverType) { return \PHPStan\Type\AcceptsResult::createYes(); } return \PHPStan\Type\AcceptsResult::createNo(); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return 'never'; } } ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { $arrayBuilder->degradeToGeneralArray(\true); } foreach ($value as $k => $v) { $arrayBuilder->setOffsetValueType(self::getTypeFromValue($k), self::getTypeFromValue($v)); } return $arrayBuilder->getArray(); } elseif (is_object($value)) { $class = get_class($value); /** phpcs:disable SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName */ if (function_exists('enum_exists') && \enum_exists($class)) { /** @var UnitEnum $value */ return new EnumCaseObjectType($class, $value->name); } /** phpcs:enable */ return new \PHPStan\Type\ObjectType(get_class($value)); } return new \PHPStan\Type\MixedType(); } } isExplicitMixed = $isExplicitMixed; if ($subtractedType instanceof \PHPStan\Type\NeverType) { $subtractedType = null; } $this->subtractedType = $subtractedType; } /** * @return string[] */ public function getReferencedClasses() : array { return []; } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function getArrays() : array { return []; } public function getConstantArrays() : array { return []; } public function getConstantStrings() : array { return []; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { return \PHPStan\Type\AcceptsResult::createYes(); } public function isSuperTypeOfMixed(\PHPStan\Type\MixedType $type) : TrinaryLogic { if ($this->subtractedType === null) { if ($this->isExplicitMixed) { if ($type->isExplicitMixed) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } return TrinaryLogic::createYes(); } if ($type->subtractedType === null) { return TrinaryLogic::createMaybe(); } $isSuperType = $type->subtractedType->isSuperTypeOf($this->subtractedType); if ($isSuperType->yes()) { if ($this->isExplicitMixed) { if ($type->isExplicitMixed) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($this->subtractedType === null || $type instanceof \PHPStan\Type\NeverType) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($type instanceof self) { if ($type->subtractedType === null) { return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } $isSuperType = $type->subtractedType->isSuperTypeOfWithReason($this->subtractedType); if ($isSuperType->yes()) { return $isSuperType; } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } $result = $this->subtractedType->isSuperTypeOfWithReason($type)->negate(); if ($result->no()) { return \PHPStan\Type\IsSuperTypeOfResult::createNo([sprintf('Type %s has already been eliminated from %s.', $this->subtractedType->describe(\PHPStan\Type\VerbosityLevel::precise()), $this->describe(\PHPStan\Type\VerbosityLevel::typeOnly()))]); } return $result; } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { if ($this->subtractedType !== null) { return new self($this->isExplicitMixed, \PHPStan\Type\TypeCombinator::remove($this->subtractedType, new ConstantArrayType([], []))); } return $this; } public function getKeysArray() : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return AccessoryArrayListType::intersectWith(new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), new \PHPStan\Type\UnionType([new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType()]))); } public function getValuesArray() : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return AccessoryArrayListType::intersectWith(new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), new \PHPStan\Type\MixedType($this->isExplicitMixed))); } public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return AccessoryArrayListType::intersectWith(new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), new \PHPStan\Type\MixedType($this->isExplicitMixed))); } public function fillKeysArray(\PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\ArrayType($this->getIterableValueType(), $valueType); } public function flipArray() : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType($this->isExplicitMixed), new \PHPStan\Type\MixedType($this->isExplicitMixed)); } public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType) : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType($this->isExplicitMixed), new \PHPStan\Type\MixedType($this->isExplicitMixed)); } public function popArray() : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType($this->isExplicitMixed), new \PHPStan\Type\MixedType($this->isExplicitMixed)); } public function reverseArray(TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType($this->isExplicitMixed), new \PHPStan\Type\MixedType($this->isExplicitMixed)); } public function searchArray(\PHPStan\Type\Type $needleType) : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return \PHPStan\Type\TypeCombinator::union(new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType(), new ConstantBooleanType(\false)); } public function shiftArray() : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType($this->isExplicitMixed), new \PHPStan\Type\MixedType($this->isExplicitMixed)); } public function shuffleArray() : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return AccessoryArrayListType::intersectWith(new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), new \PHPStan\Type\MixedType($this->isExplicitMixed))); } public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { if ($this->isArray()->no()) { return new \PHPStan\Type\ErrorType(); } return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType($this->isExplicitMixed), new \PHPStan\Type\MixedType($this->isExplicitMixed)); } public function isCallable() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\CallableType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function getEnumCases() : array { return []; } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { return [new TrivialParametersAcceptor()]; } public function equals(\PHPStan\Type\Type $type) : bool { if (!$type instanceof self) { return \false; } if ($this->subtractedType === null) { if ($type->subtractedType === null) { return \true; } return \false; } if ($type->subtractedType === null) { return \false; } return $this->subtractedType->equals($type->subtractedType); } public function isSubTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof self && !$otherType instanceof TemplateMixedType) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($this->subtractedType !== null) { $isSuperType = $this->subtractedType->isSuperTypeOfWithReason($otherType); if ($isSuperType->yes()) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } } return \PHPStan\Type\IsSuperTypeOfResult::createMaybe(); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { $isSuperType = $this->isSuperTypeOfWithReason($acceptingType)->toAcceptsResult(); if ($isSuperType->no()) { return $isSuperType; } return \PHPStan\Type\AcceptsResult::createYes(); } public function getTemplateType(string $ancestorClassName, string $templateTypeName) : \PHPStan\Type\Type { return new self(); } public function isObject() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\ObjectWithoutClassType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isEnum() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\ObjectWithoutClassType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function canAccessProperties() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasProperty(string $propertyName) : TrinaryLogic { return TrinaryLogic::createYes(); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection(); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type; }); } public function canCallMethods() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasMethod(string $methodName) : TrinaryLogic { return TrinaryLogic::createYes(); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { $method = new DummyMethodReflection($methodName); return new CallbackUnresolvedMethodPrototypeReflection($method, $method->getDeclaringClass(), \false, static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type; }); } public function canAccessConstants() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasConstant(string $constantName) : TrinaryLogic { return TrinaryLogic::createYes(); } public function getConstant(string $constantName) : ConstantReflection { return new DummyConstantReflection($constantName); } public function isCloneable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return $level->handle(static function () : string { return 'mixed'; }, static function () : string { return 'mixed'; }, function () use($level) : string { $description = 'mixed'; if ($this->subtractedType !== null) { $description .= $this->subtractedType instanceof \PHPStan\Type\UnionType ? sprintf('~(%s)', $this->subtractedType->describe($level)) : sprintf('~%s', $this->subtractedType->describe($level)); } return $description; }, function () use($level) : string { $description = 'mixed'; if ($this->subtractedType !== null) { $description .= $this->subtractedType instanceof \PHPStan\Type\UnionType ? sprintf('~(%s)', $this->subtractedType->describe($level)) : sprintf('~%s', $this->subtractedType->describe($level)); } if ($this->isExplicitMixed) { $description .= '=explicit'; } else { $description .= '=implicit'; } return $description; }); } public function toBoolean() : \PHPStan\Type\BooleanType { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(\PHPStan\Type\StaticTypeFactory::falsey())->yes()) { return new ConstantBooleanType(\true); } } return new \PHPStan\Type\BooleanType(); } public function toNumber() : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::union($this->toInteger(), $this->toFloat()); } public function toAbsoluteNumber() : \PHPStan\Type\Type { return $this->toNumber()->toAbsoluteNumber(); } public function toInteger() : \PHPStan\Type\Type { $castsToZero = new \PHPStan\Type\UnionType([new \PHPStan\Type\NullType(), new ConstantBooleanType(\false), new ConstantIntegerType(0), new ConstantArrayType([], []), new \PHPStan\Type\StringType(), new \PHPStan\Type\FloatType()]); if ($this->subtractedType !== null && $this->subtractedType->isSuperTypeOf($castsToZero)->yes()) { return new \PHPStan\Type\UnionType([\PHPStan\Type\IntegerRangeType::fromInterval(null, -1), \PHPStan\Type\IntegerRangeType::fromInterval(1, null)]); } return new \PHPStan\Type\IntegerType(); } public function toFloat() : \PHPStan\Type\Type { return new \PHPStan\Type\FloatType(); } public function toString() : \PHPStan\Type\Type { if ($this->subtractedType !== null) { $castsToEmptyString = new \PHPStan\Type\UnionType([new \PHPStan\Type\NullType(), new ConstantBooleanType(\false), new ConstantStringType('')]); if ($this->subtractedType->isSuperTypeOf($castsToEmptyString)->yes()) { $accessories = [new \PHPStan\Type\StringType(), new AccessoryNonEmptyStringType()]; $castsToZeroString = new \PHPStan\Type\UnionType([new ConstantFloatType(0.0), new ConstantStringType('0'), new ConstantIntegerType(0)]); if ($this->subtractedType->isSuperTypeOf($castsToZeroString)->yes()) { $accessories[] = new AccessoryNonFalsyStringType(); } return new \PHPStan\Type\IntersectionType($accessories); } } return new \PHPStan\Type\StringType(); } public function toArray() : \PHPStan\Type\Type { $mixed = new self($this->isExplicitMixed); return new \PHPStan\Type\ArrayType($mixed, $mixed); } public function toArrayKey() : \PHPStan\Type\Type { return new \PHPStan\Type\BenevolentUnionType([new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType()]); } public function isIterable() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\IterableType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()))->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isIterableAtLeastOnce() : TrinaryLogic { return $this->isIterable(); } public function getArraySize() : \PHPStan\Type\Type { if ($this->isIterable()->no()) { return new \PHPStan\Type\ErrorType(); } return \PHPStan\Type\IntegerRangeType::fromInterval(0, null); } public function getIterableKeyType() : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function getFirstIterableKeyType() : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function getLastIterableKeyType() : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function getIterableValueType() : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function getFirstIterableValueType() : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function getLastIterableValueType() : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function isOffsetAccessible() : TrinaryLogic { if ($this->subtractedType !== null) { $offsetAccessibles = new \PHPStan\Type\UnionType([new \PHPStan\Type\StringType(), new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()), new \PHPStan\Type\ObjectType(ArrayAccess::class)]); if ($this->subtractedType->isSuperTypeOf($offsetAccessibles)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isOffsetAccessLegal() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\ObjectWithoutClassType())->yes()) { return TrinaryLogic::createYes(); } } return TrinaryLogic::createMaybe(); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { if ($this->isOffsetAccessible()->no()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function isExplicitMixed() : bool { return $this->isExplicitMixed; } public function subtract(\PHPStan\Type\Type $type) : \PHPStan\Type\Type { if ($type instanceof self && !$type instanceof TemplateType) { return new \PHPStan\Type\NeverType(); } if ($this->subtractedType !== null) { $type = \PHPStan\Type\TypeCombinator::union($this->subtractedType, $type); } return new self($this->isExplicitMixed, $type); } public function getTypeWithoutSubtractedType() : \PHPStan\Type\Type { return new self($this->isExplicitMixed); } public function changeSubtractedType(?\PHPStan\Type\Type $subtractedType) : \PHPStan\Type\Type { return new self($this->isExplicitMixed, $subtractedType); } public function getSubtractedType() : ?\PHPStan\Type\Type { return $this->subtractedType; } public function traverse(callable $cb) : \PHPStan\Type\Type { return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { return $this; } public function isArray() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()))->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isConstantArray() : TrinaryLogic { return $this->isArray(); } public function isOversizedArray() : TrinaryLogic { if ($this->subtractedType !== null) { $oversizedArray = \PHPStan\Type\TypeCombinator::intersect(new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()), new OversizedArrayType()); if ($this->subtractedType->isSuperTypeOf($oversizedArray)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isList() : TrinaryLogic { if ($this->subtractedType !== null) { $list = \PHPStan\Type\TypeCombinator::intersect(new \PHPStan\Type\ArrayType(new \PHPStan\Type\IntegerType(), new \PHPStan\Type\MixedType()), new AccessoryArrayListType()); if ($this->subtractedType->isSuperTypeOf($list)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isNull() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\NullType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new ConstantBooleanType(\true))->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isFalse() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new ConstantBooleanType(\false))->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isBoolean() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\BooleanType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isFloat() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\FloatType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isInteger() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\IntegerType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isString() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\StringType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isNumericString() : TrinaryLogic { if ($this->subtractedType !== null) { $numericString = \PHPStan\Type\TypeCombinator::intersect(new \PHPStan\Type\StringType(), new AccessoryNumericStringType()); if ($this->subtractedType->isSuperTypeOf($numericString)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isNonEmptyString() : TrinaryLogic { if ($this->subtractedType !== null) { $nonEmptyString = \PHPStan\Type\TypeCombinator::intersect(new \PHPStan\Type\StringType(), new AccessoryNonEmptyStringType()); if ($this->subtractedType->isSuperTypeOf($nonEmptyString)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isNonFalsyString() : TrinaryLogic { if ($this->subtractedType !== null) { $nonFalsyString = \PHPStan\Type\TypeCombinator::intersect(new \PHPStan\Type\StringType(), new AccessoryNonFalsyStringType()); if ($this->subtractedType->isSuperTypeOf($nonFalsyString)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isLiteralString() : TrinaryLogic { if ($this->subtractedType !== null) { $literalString = \PHPStan\Type\TypeCombinator::intersect(new \PHPStan\Type\StringType(), new AccessoryLiteralStringType()); if ($this->subtractedType->isSuperTypeOf($literalString)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isLowercaseString() : TrinaryLogic { if ($this->subtractedType !== null) { $lowercaseString = \PHPStan\Type\TypeCombinator::intersect(new \PHPStan\Type\StringType(), new AccessoryLowercaseStringType()); if ($this->subtractedType->isSuperTypeOf($lowercaseString)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isUppercaseString() : TrinaryLogic { if ($this->subtractedType !== null) { $uppercaseString = \PHPStan\Type\TypeCombinator::intersect(new \PHPStan\Type\StringType(), new AccessoryUppercaseStringType()); if ($this->subtractedType->isSuperTypeOf($uppercaseString)->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isClassStringType() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\StringType())->yes()) { return TrinaryLogic::createNo(); } if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\ClassStringType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function getClassStringObjectType() : \PHPStan\Type\Type { if (!$this->isClassStringType()->no()) { return new \PHPStan\Type\ObjectWithoutClassType(); } return new \PHPStan\Type\ErrorType(); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { $objectOrClass = new \PHPStan\Type\UnionType([new \PHPStan\Type\ObjectWithoutClassType(), new \PHPStan\Type\ClassStringType()]); if (!$this->isSuperTypeOf($objectOrClass)->no()) { return new \PHPStan\Type\ObjectWithoutClassType(); } return new \PHPStan\Type\ErrorType(); } public function isVoid() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\VoidType())->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function isScalar() : TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new \PHPStan\Type\UnionType([new \PHPStan\Type\BooleanType(), new \PHPStan\Type\FloatType(), new \PHPStan\Type\IntegerType(), new \PHPStan\Type\StringType()]))->yes()) { return TrinaryLogic::createNo(); } } return TrinaryLogic::createMaybe(); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { if ($this->isSuperTypeOf($typeToRemove)->yes()) { return $this->subtract($typeToRemove); } return null; } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return new \PHPStan\Type\BenevolentUnionType([new \PHPStan\Type\FloatType(), new \PHPStan\Type\IntegerType()]); } public function getFiniteTypes() : array { return []; } public function toPhpDocNode() : TypeNode { return new IdentifierTypeNode('mixed'); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['isExplicitMixed'], $properties['subtractedType'] ?? null); } } type = $type; $this->offset = $offset; } public function getReferencedClasses() : array { return array_merge($this->type->getReferencedClasses(), $this->offset->getReferencedClasses()); } public function getObjectClassNames() : array { return []; } public function getObjectClassReflections() : array { return []; } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { return array_merge($this->type->getReferencedTemplateTypes($positionVariance), $this->offset->getReferencedTemplateTypes($positionVariance)); } public function equals(\PHPStan\Type\Type $type) : bool { return $type instanceof self && $this->type->equals($type->type) && $this->offset->equals($type->offset); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { $printer = new Printer(); return $printer->print($this->toPhpDocNode()); } public function isResolvable() : bool { return !\PHPStan\Type\TypeUtils::containsTemplateType($this->type) && !\PHPStan\Type\TypeUtils::containsTemplateType($this->offset); } protected function getResult() : \PHPStan\Type\Type { return $this->type->getOffsetValueType($this->offset); } /** * @param callable(Type): Type $cb */ public function traverse(callable $cb) : \PHPStan\Type\Type { $type = $cb($this->type); $offset = $cb($this->offset); if ($this->type === $type && $this->offset === $offset) { return $this; } return new self($type, $offset); } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if (!$right instanceof self) { return $this; } $type = $cb($this->type, $right->type); $offset = $cb($this->offset, $right->offset); if ($this->type === $type && $this->offset === $offset) { return $this; } return new self($type, $offset); } public function toPhpDocNode() : TypeNode { return new OffsetAccessTypeNode($this->type->toPhpDocNode(), $this->offset->toPhpDocNode()); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['type'], $properties['offset']); } } getClassReflection(); if ($classReflection === null) { return null; } $ancestorClassReflection = $classReflection->getAncestorWithClassName($genericClassName); if ($ancestorClassReflection === null) { return null; } $activeTemplateTypeMap = $ancestorClassReflection->getPossiblyIncompleteActiveTemplateTypeMap(); $type = $activeTemplateTypeMap->getType($typeVariableName); if ($type instanceof \PHPStan\Type\ErrorType) { $templateTypeMap = $ancestorClassReflection->getTemplateTypeMap(); $templateType = $templateTypeMap->getType($typeVariableName); if ($templateType === null) { return $type; } $bound = TemplateTypeHelper::resolveToBounds($templateType); if ($bound instanceof \PHPStan\Type\MixedType && $bound->isExplicitMixed()) { return new \PHPStan\Type\MixedType(\false); } return TemplateTypeHelper::resolveToDefaults($templateType); } return $type; } } getName(); } elseif ($lowercasedClassName === 'parent' && $classReflection !== null && $classReflection->getParentClass() !== null) { $typeClassName = $classReflection->getParentClass()->getName(); } return new \PHPStan\Type\ObjectType($typeClassName); } elseif ($type instanceof NullableType) { return \PHPStan\Type\TypeCombinator::addNull(self::resolve($type->type, $classReflection)); } elseif ($type instanceof Node\UnionType) { $types = []; foreach ($type->types as $unionTypeType) { $types[] = self::resolve($unionTypeType, $classReflection); } return \PHPStan\Type\TypeCombinator::union(...$types); } elseif ($type instanceof Node\IntersectionType) { $types = []; foreach ($type->types as $intersectionTypeType) { $innerType = self::resolve($intersectionTypeType, $classReflection); if (!$innerType->isObject()->yes()) { return new \PHPStan\Type\NeverType(); } $types[] = $innerType; } return \PHPStan\Type\TypeCombinator::intersect(...$types); } elseif (!$type instanceof Identifier) { throw new ShouldNotHappenException(get_class($type)); } $type = $type->name; if ($type === 'string') { return new \PHPStan\Type\StringType(); } elseif ($type === 'int') { return new \PHPStan\Type\IntegerType(); } elseif ($type === 'bool') { return new \PHPStan\Type\BooleanType(); } elseif ($type === 'float') { return new \PHPStan\Type\FloatType(); } elseif ($type === 'callable') { return new \PHPStan\Type\CallableType(); } elseif ($type === 'array') { return new \PHPStan\Type\ArrayType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()); } elseif ($type === 'iterable') { return new \PHPStan\Type\IterableType(new \PHPStan\Type\MixedType(), new \PHPStan\Type\MixedType()); } elseif ($type === 'void') { return new \PHPStan\Type\VoidType(); } elseif ($type === 'object') { return new \PHPStan\Type\ObjectWithoutClassType(); } elseif ($type === 'true') { return new ConstantBooleanType(\true); } elseif ($type === 'false') { return new ConstantBooleanType(\false); } elseif ($type === 'null') { return new \PHPStan\Type\NullType(); } elseif ($type === 'mixed') { return new \PHPStan\Type\MixedType(\true); } elseif ($type === 'never') { return new \PHPStan\Type\NonAcceptingNeverType(); } return new \PHPStan\Type\MixedType(); } } */ public $reasons; /** * @api * @param list $reasons */ public function __construct(TrinaryLogic $result, array $reasons) { $this->result = $result; $this->reasons = $reasons; } public function yes() : bool { return $this->result->yes(); } public function maybe() : bool { return $this->result->maybe(); } public function no() : bool { return $this->result->no(); } public static function createYes() : self { return new self(TrinaryLogic::createYes(), []); } /** * @param list $reasons */ public static function createNo(array $reasons = []) : self { return new self(TrinaryLogic::createNo(), $reasons); } public static function createMaybe() : self { return new self(TrinaryLogic::createMaybe(), []); } public static function createFromBoolean(bool $value) : self { return new self(TrinaryLogic::createFromBoolean($value), []); } public function and(self $other) : self { return new self($this->result->and($other->result), array_values(array_unique(array_merge($this->reasons, $other->reasons)))); } public function or(self $other) : self { return new self($this->result->or($other->result), array_values(array_unique(array_merge($this->reasons, $other->reasons)))); } /** * @param callable(string): string $cb */ public function decorateReasons(callable $cb) : self { $reasons = []; foreach ($this->reasons as $reason) { $reasons[] = $cb($reason); } return new self($this->result, $reasons); } public static function extremeIdentity(self ...$operands) : self { if ($operands === []) { throw new ShouldNotHappenException(); } $result = TrinaryLogic::extremeIdentity(...array_map(static function (self $result) { return $result->result; }, $operands)); $reasons = []; foreach ($operands as $operand) { foreach ($operand->reasons as $reason) { $reasons[] = $reason; } } return new self($result, array_values(array_unique($reasons))); } public static function maxMin(self ...$operands) : self { if ($operands === []) { throw new ShouldNotHappenException(); } $result = TrinaryLogic::maxMin(...array_map(static function (self $result) { return $result->result; }, $operands)); $reasons = []; foreach ($operands as $operand) { foreach ($operand->reasons as $reason) { $reasons[] = $reason; } } return new self($result, array_values(array_unique($reasons))); } } getName() === 'preg_filter'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $defaultReturn = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants())->getReturnType(); $argsCount = count($functionCall->getArgs()); if ($argsCount < 3) { return $defaultReturn; } $subjectType = $scope->getType($functionCall->getArgs()[2]->value); if ($subjectType->isArray()->yes()) { return new ArrayType(new IntegerType(), new StringType()); } if ($subjectType->isString()->yes()) { return new UnionType([new StringType(), new NullType()]); } return $defaultReturn; } } explicitMixed = $explicitMixed; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return strtolower($functionReflection->getName()) === 'is_array' && !$context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { if (!isset($node->getArgs()[0])) { return new SpecifiedTypes(); } if ($context->null()) { throw new ShouldNotHappenException(); } return $this->typeSpecifier->create($node->getArgs()[0]->value, new ArrayType(new MixedType($this->explicitMixed), new MixedType($this->explicitMixed)), $context, \false, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } bitwiseFlagAnalyser = $bitwiseFlagAnalyser; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return strtolower($functionReflection->getName()) === 'preg_split'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $flagsArg = $functionCall->getArgs()[3] ?? null; if ($flagsArg !== null && $this->bitwiseFlagAnalyser->bitwiseOrContainsConstant($flagsArg->value, $scope, 'PREG_SPLIT_OFFSET_CAPTURE')->yes()) { $type = new ArrayType(new IntegerType(), new ConstantArrayType([new ConstantIntegerType(0), new ConstantIntegerType(1)], [new StringType(), IntegerRangeType::fromInterval(0, null)], [2], [], TrinaryLogic::createYes())); return TypeCombinator::union(AccessoryArrayListType::intersectWith($type), new ConstantBooleanType(\false)); } return null; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return in_array($functionReflection->getName(), ['round', 'ceil', 'floor'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { // PHP 7 can return either a float or false. // PHP 8 can either return a float or fatal. $defaultReturnType = null; if ($this->phpVersion->hasStricterRoundFunctions()) { // PHP 8 fatals with a missing parameter. $noArgsReturnType = new NeverType(\true); } else { // PHP 7 returns null with a missing parameter. $noArgsReturnType = new NullType(); } if (count($functionCall->getArgs()) < 1) { return $noArgsReturnType; } $firstArgType = $scope->getType($functionCall->getArgs()[0]->value); if ($firstArgType instanceof MixedType) { return $defaultReturnType; } if ($this->phpVersion->hasStricterRoundFunctions()) { $allowed = TypeCombinator::union(new IntegerType(), new FloatType()); if (!$scope->isDeclareStrictTypes()) { $allowed = TypeCombinator::union($allowed, new IntersectionType([new StringType(), new AccessoryNumericStringType()]), new NullType(), new BooleanType()); } if ($allowed->isSuperTypeOf($firstArgType)->no()) { // PHP 8 fatals if the parameter is not an integer or float. return new NeverType(\true); } } elseif ($firstArgType->isArray()->yes()) { // PHP 7 returns false if the parameter is an array. return new ConstantBooleanType(\false); } return new FloatType(); } } getName(), ['date_create', 'date_create_immutable'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 1) { return null; } $datetimes = $scope->getType($functionCall->getArgs()[0]->value)->getConstantStrings(); if (count($datetimes) === 0) { return null; } $types = []; $className = $functionReflection->getName() === 'date_create' ? DateTime::class : DateTimeImmutable::class; foreach ($datetimes as $constantString) { $isValid = date_create($constantString->getValue()) !== \false; $types[] = $isValid ? new ObjectType($className) : new ConstantBooleanType(\false); } return TypeCombinator::union(...$types); } } getName()) === 'is_iterable' && !$context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { if ($context->null()) { throw new ShouldNotHappenException(); } if (!isset($node->getArgs()[0])) { return new SpecifiedTypes(); } return $this->typeSpecifier->create($node->getArgs()[0]->value, new IterableType(new MixedType(), new MixedType()), $context, \false, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } getName() === 'get_defined_vars'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { if ($scope->canAnyVariableExist()) { return new ArrayType(new StringType(), new MixedType()); } $typeBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach ($scope->getDefinedVariables() as $variable) { $typeBuilder->setOffsetValueType(new ConstantStringType($variable), $scope->getVariableType($variable), \false); } foreach ($scope->getMaybeDefinedVariables() as $variable) { $typeBuilder->setOffsetValueType(new ConstantStringType($variable), $scope->getVariableType($variable), \true); } return $typeBuilder->getArray(); } } getName() === 'getCode'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : Type { $type = $scope->getType($methodCall->var); $types = []; $pdoException = new ObjectType('PDOException'); foreach ($type->getObjectClassNames() as $class) { $classType = new ObjectType($class); if ($classType->getClassReflection() !== null) { $classReflection = $classType->getClassReflection(); foreach ($classReflection->getMethodTags() as $methodName => $methodTag) { if (strtolower($methodName) !== 'getcode') { continue; } $types[] = $methodTag->getReturnType(); continue 2; } } if ($pdoException->isSuperTypeOf($classType)->yes()) { $types[] = new BenevolentUnionType([new IntegerType(), new StringType()]); continue; } if (in_array(strtolower($class), ['throwable', 'exception', 'runtimeexception'], \true)) { $types[] = new BenevolentUnionType([new IntegerType(), new StringType()]); continue; } $types[] = new IntegerType(); } if (count($types) === 0) { return new ErrorType(); } return TypeCombinator::union(...$types); } } getName(), $this->functions, \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) === 0) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new ConstantBooleanType(\false); } $itemType = $functionReflection->getName() === 'reset' ? $argType->getFirstIterableValueType() : $argType->getLastIterableValueType(); if ($iterableAtLeastOnce->yes()) { return $itemType; } return TypeCombinator::union($itemType, new ConstantBooleanType(\false)); } } methodExistsExtension = $methodExistsExtension; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return strtolower($functionReflection->getName()) === 'is_callable' && !$context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { if ($context->null()) { throw new ShouldNotHappenException(); } if (!isset($node->getArgs()[0])) { return new SpecifiedTypes(); } $value = $node->getArgs()[0]->value; $valueType = $scope->getType($value); if ($value instanceof Array_ && count($value->items) === 2 && $valueType->isConstantArray()->yes() && !$valueType->isCallable()->no()) { if ($value->items[0] === null || $value->items[1] === null) { throw new ShouldNotHappenException(); } $functionCall = new FuncCall(new Name('method_exists'), [new Arg($value->items[0]->value), new Arg($value->items[1]->value)]); return $this->methodExistsExtension->specifyTypes($functionReflection, $functionCall, $scope, $context); } return $this->typeSpecifier->create($value, new CallableType(), $context, \false, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'trigger_error'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) === 0) { return null; } if (count($args) === 1) { return new ConstantBooleanType(\true); } $errorType = $scope->getType($args[1]->value); if ($errorType instanceof ConstantIntegerType) { $errorLevel = $errorType->getValue(); if ($errorLevel === E_USER_ERROR) { return new NeverType(\true); } if (!in_array($errorLevel, [E_USER_WARNING, E_USER_NOTICE, E_USER_DEPRECATED], \true)) { if ($this->phpVersion->throwsValueErrorForInternalFunctions()) { return new NeverType(\true); } return new ConstantBooleanType(\false); } return new ConstantBooleanType(\true); } return null; } } getName() === 'array_merge'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $argTypes = []; $optionalArgTypes = []; foreach ($args as $arg) { $argType = $scope->getType($arg->value); if ($arg->unpack) { if ($argType->isConstantArray()->yes()) { foreach ($argType->getConstantArrays() as $constantArray) { foreach ($constantArray->getValueTypes() as $valueType) { $argTypes[] = $valueType; } } } else { $argTypes[] = $argType->getIterableValueType(); } if (!$argType->isIterableAtLeastOnce()->yes()) { // unpacked params can be empty, making them optional $optionalArgTypesOffset = count($argTypes) - 1; foreach (array_keys($argTypes) as $key) { $optionalArgTypes[] = $optionalArgTypesOffset + $key; } } } else { $argTypes[] = $argType; } } $allConstant = TrinaryLogic::createYes()->lazyAnd($argTypes, static function (Type $argType) { return $argType->isConstantArray(); }); if ($allConstant->yes()) { $newArrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach ($argTypes as $argType) { /** @var array $keyTypes */ $keyTypes = []; foreach ($argType->getConstantArrays() as $constantArray) { foreach ($constantArray->getKeyTypes() as $keyType) { $keyTypes[$keyType->getValue()] = $keyType; } } foreach ($keyTypes as $keyType) { $newArrayBuilder->setOffsetValueType($keyType instanceof ConstantIntegerType ? null : $keyType, $argType->getOffsetValueType($keyType), !$argType->hasOffsetValueType($keyType)->yes()); } } return $newArrayBuilder->getArray(); } $keyTypes = []; $valueTypes = []; $nonEmpty = \false; $isList = \true; foreach ($argTypes as $key => $argType) { $keyType = $argType->getIterableKeyType(); $keyTypes[] = $keyType; $valueTypes[] = $argType->getIterableValueType(); if (!(new IntegerType())->isSuperTypeOf($keyType)->yes()) { $isList = \false; } if (in_array($key, $optionalArgTypes, \true) || !$argType->isIterableAtLeastOnce()->yes()) { continue; } $nonEmpty = \true; } $keyType = TypeCombinator::union(...$keyTypes); if ($keyType instanceof NeverType) { return new ConstantArrayType([], []); } $arrayType = new ArrayType($keyType, TypeCombinator::union(...$valueTypes)); if ($nonEmpty) { $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } if ($isList) { $arrayType = AccessoryArrayListType::intersectWith($arrayType); } return $arrayType; } } reflectionProvider = $reflectionProvider; } public function isStaticMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === '__construct' && $methodReflection->getDeclaringClass()->getName() === ReflectionFunction::class; } public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) < 1) { return $methodReflection->getThrowType(); } $valueType = $scope->getType($methodCall->getArgs()[0]->value); foreach ($valueType->getConstantStrings() as $constantString) { if ($constantString->getValue() === '') { return null; } if (!$this->reflectionProvider->hasFunction(new Name($constantString->getValue()), $scope)) { return $methodReflection->getThrowType(); } $valueType = TypeCombinator::remove($valueType, $constantString); } if (!$valueType instanceof NeverType) { return $methodReflection->getThrowType(); } return null; } } getName(), ['date_create_from_format', 'date_create_immutable_from_format'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } $formats = $scope->getType($functionCall->getArgs()[0]->value)->getConstantStrings(); $datetimes = $scope->getType($functionCall->getArgs()[1]->value)->getConstantStrings(); if (count($formats) === 0 || count($datetimes) === 0) { return null; } $types = []; $className = $functionReflection->getName() === 'date_create_from_format' ? DateTime::class : DateTimeImmutable::class; foreach ($formats as $formatConstantString) { foreach ($datetimes as $datetimeConstantString) { $isValid = DateTime::createFromFormat($formatConstantString->getValue(), $datetimeConstantString->getValue()) !== \false; $types[] = $isValid ? new ObjectType($className) : new ConstantBooleanType(\false); } } return TypeCombinator::union(...$types); } } getName() === 'ini_get'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $numericString = TypeCombinator::intersect(new StringType(), new AccessoryNumericStringType()); $types = ['date.timezone' => new StringType(), 'memory_limit' => new StringType(), 'max_execution_time' => $numericString, 'max_input_time' => $numericString, 'default_socket_timeout' => $numericString, 'precision' => $numericString]; $argType = $scope->getType($args[0]->value); $results = []; foreach ($argType->getConstantStrings() as $constantString) { if (!array_key_exists($constantString->getValue(), $types)) { return null; } $results[] = $types[$constantString->getValue()]; } if (count($results) > 0) { return TypeCombinator::union(...$results); } return null; } } getName() === 'array_change_key_case'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $arrayType = $scope->getType($functionCall->getArgs()[0]->value); if (!isset($functionCall->getArgs()[1])) { $case = CASE_LOWER; } else { $caseType = $scope->getType($functionCall->getArgs()[1]->value); $scalarValues = $caseType->getConstantScalarValues(); if (count($scalarValues) === 1) { $case = (int) $scalarValues[0]; } else { $case = null; } } $constantArrays = $arrayType->getConstantArrays(); if (count($constantArrays) > 0) { $arrayTypes = []; foreach ($constantArrays as $constantArray) { $newConstantArrayBuilder = ConstantArrayTypeBuilder::createEmpty(); $valueTypes = $constantArray->getValueTypes(); foreach ($constantArray->getKeyTypes() as $i => $keyType) { $valueType = $valueTypes[$i]; $constantStrings = $keyType->getConstantStrings(); if (count($constantStrings) > 0) { $keyType = TypeCombinator::union(...array_map(function (ConstantStringType $type) use($case) : Type { return $this->mapConstantString($type, $case); }, $constantStrings)); } $newConstantArrayBuilder->setOffsetValueType($keyType, $valueType, $constantArray->isOptionalKey($i)); } $newConstantArrayType = $newConstantArrayBuilder->getArray(); if ($constantArray->isList()->yes()) { $newConstantArrayType = AccessoryArrayListType::intersectWith($newConstantArrayType); } $arrayTypes[] = $newConstantArrayType; } $newArrayType = TypeCombinator::union(...$arrayTypes); } else { $keysType = $arrayType->getIterableKeyType(); $keysType = TypeTraverser::map($keysType, function (Type $type, callable $traverse) use($case) : Type { if ($type instanceof UnionType) { return $traverse($type); } $constantStrings = $type->getConstantStrings(); if (count($constantStrings) > 0) { return TypeCombinator::union(...array_map(function (ConstantStringType $type) use($case) : Type { return $this->mapConstantString($type, $case); }, $constantStrings)); } if ($type->isString()->yes()) { $types = [new StringType()]; if ($type->isNonFalsyString()->yes()) { $types[] = new AccessoryNonFalsyStringType(); } elseif ($type->isNonEmptyString()->yes()) { $types[] = new AccessoryNonEmptyStringType(); } if ($type->isNumericString()->yes()) { $types[] = new AccessoryNumericStringType(); } if ($case === CASE_LOWER) { $types[] = new AccessoryLowercaseStringType(); } elseif ($case === CASE_UPPER) { $types[] = new AccessoryUppercaseStringType(); } return TypeCombinator::intersect(...$types); } return $type; }); $newArrayType = TypeCombinator::intersect(new ArrayType($keysType, $arrayType->getIterableValueType()), ...TypeUtils::getAccessoryTypes($arrayType)); } if ($arrayType->isIterableAtLeastOnce()->yes()) { $newArrayType = TypeCombinator::intersect($newArrayType, new NonEmptyArrayType()); } return $newArrayType; } private function mapConstantString(ConstantStringType $type, ?int $case) : Type { if ($case === CASE_LOWER) { return new ConstantStringType(strtolower($type->getValue())); } elseif ($case === CASE_UPPER) { return new ConstantStringType(strtoupper($type->getValue())); } return TypeCombinator::union(new ConstantStringType(strtolower($type->getValue())), new ConstantStringType(strtoupper($type->getValue()))); } } getName() === 'str_word_count'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, Node\Expr\FuncCall $functionCall, Scope $scope) : Type { $argsCount = count($functionCall->getArgs()); if ($argsCount === 1) { return new IntegerType(); } elseif ($argsCount === 2 || $argsCount === 3) { $formatType = $scope->getType($functionCall->getArgs()[1]->value); if ($formatType instanceof ConstantIntegerType) { $val = $formatType->getValue(); if ($val === 0) { // return word count return new IntegerType(); } elseif ($val === 1 || $val === 2) { // return [word] or [offset => word] return new ArrayType(new IntegerType(), new StringType()); } // return false, invalid format value specified return new ConstantBooleanType(\false); } // Could be invalid format type as well, but parameter type checks will catch that. return new UnionType([new IntegerType(), new ArrayType(new IntegerType(), new StringType()), new ConstantBooleanType(\false)]); } // else fatal error; too many or too few arguments return new ErrorType(); } } arrayFilterFunctionReturnTypeHelper = $arrayFilterFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_find'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } $arrayType = $scope->getType($functionCall->getArgs()[0]->value); if (count($arrayType->getArrays()) < 1) { return null; } $arrayArg = $functionCall->getArgs()[0]->value ?? null; $callbackArg = $functionCall->getArgs()[1]->value ?? null; $resultTypes = $this->arrayFilterFunctionReturnTypeHelper->getType($scope, $arrayArg, $callbackArg, null); $resultType = TypeCombinator::union(...array_map(static function ($type) { return $type->getIterableValueType(); }, $resultTypes->getArrays())); return $resultTypes->isIterableAtLeastOnce()->yes() ? $resultType : TypeCombinator::addNull($resultType); } } getConstantStrings() as $formatString) { $types[] = $this->buildReturnTypeFromFormat($formatString->getValue(), $useMicrosec); } if (count($types) === 0) { $types[] = $formatType->isNonEmptyString()->yes() ? new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]) : new StringType(); } $type = TypeCombinator::union(...$types); if ($type->isNumericString()->no() && $formatType->isNonEmptyString()->yes()) { $type = TypeCombinator::union($type, new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()])); } return $type; } public function buildReturnTypeFromFormat(string $formatString, bool $useMicrosec) : Type { // see see https://www.php.net/manual/en/datetime.format.php switch ($formatString) { case 'd': return $this->buildNumericRangeType(1, 31, \true); case 'j': return $this->buildNumericRangeType(1, 31, \false); case 'N': return $this->buildNumericRangeType(1, 7, \false); case 'w': return $this->buildNumericRangeType(0, 6, \false); case 'm': return $this->buildNumericRangeType(1, 12, \true); case 'n': return $this->buildNumericRangeType(1, 12, \false); case 't': return $this->buildNumericRangeType(28, 31, \false); case 'L': return $this->buildNumericRangeType(0, 1, \false); case 'g': return $this->buildNumericRangeType(1, 12, \false); case 'G': return $this->buildNumericRangeType(0, 23, \false); case 'h': return $this->buildNumericRangeType(1, 12, \true); case 'H': return $this->buildNumericRangeType(0, 23, \true); case 'I': return $this->buildNumericRangeType(0, 1, \false); case 'u': return $useMicrosec ? new IntersectionType([new StringType(), new AccessoryNonFalsyStringType(), new AccessoryNumericStringType()]) : new ConstantStringType('000000'); case 'v': return $useMicrosec ? new IntersectionType([new StringType(), new AccessoryNonFalsyStringType(), new AccessoryNumericStringType()]) : new ConstantStringType('000'); } $date = date($formatString); // If parameter string is not included, returned as ConstantStringType if ($date === $formatString) { return new ConstantStringType($date); } if (is_numeric($date)) { return new IntersectionType([new StringType(), new AccessoryNumericStringType()]); } return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } private function buildNumericRangeType(int $min, int $max, bool $zeroPad) : Type { $types = []; for ($i = $min; $i <= $max; $i++) { $string = (string) $i; if ($zeroPad) { $string = str_pad($string, 2, '0', STR_PAD_LEFT); } $types[] = new ConstantStringType($string); } return new UnionType($types); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'mb_substitute_character'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $minCodePoint = $this->phpVersion->getVersionId() < 80000 ? 1 : 0; $maxCodePoint = $this->phpVersion->supportsAllUnicodeScalarCodePointsInMbSubstituteCharacter() ? 0x10ffff : 0xfffe; $ranges = []; if ($this->phpVersion->supportsAllUnicodeScalarCodePointsInMbSubstituteCharacter()) { // Surrogates aren't valid in PHP 7.2+ $ranges[] = IntegerRangeType::fromInterval($minCodePoint, 0xd7ff); $ranges[] = IntegerRangeType::fromInterval(0xe000, $maxCodePoint); } else { $ranges[] = IntegerRangeType::fromInterval($minCodePoint, $maxCodePoint); } if (!isset($functionCall->getArgs()[0])) { return TypeCombinator::union(new ConstantStringType('none'), new ConstantStringType('long'), new ConstantStringType('entity'), ...$ranges); } $argType = $scope->getType($functionCall->getArgs()[0]->value); $isString = $argType->isString(); $isNull = $argType->isNull(); $isInteger = $argType->isInteger(); if ($isString->no() && $isNull->no() && $isInteger->no()) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new BooleanType(); } if ($isInteger->yes()) { $invalidRanges = []; foreach ($ranges as $range) { $isInRange = $range->isSuperTypeOf($argType); if ($isInRange->yes()) { return new ConstantBooleanType(\true); } $invalidRanges[] = $isInRange->no(); } if ($argType instanceof ConstantIntegerType || !in_array(\false, $invalidRanges, \true)) { if ($this->phpVersion->throwsValueErrorForInternalFunctions()) { return new NeverType(); } return new ConstantBooleanType(\false); } } elseif ($isString->yes()) { if ($argType->isNonEmptyString()->no()) { // The empty string was a valid alias for "none" in PHP < 8. if ($this->phpVersion->isEmptyStringValidAliasForNoneInMbSubstituteCharacter()) { return new ConstantBooleanType(\true); } return new NeverType(); } if (!$this->phpVersion->isNumericStringValidArgInMbSubstituteCharacter() && $argType->isNumericString()->yes()) { return new NeverType(); } if ($argType instanceof ConstantStringType) { $value = strtolower($argType->getValue()); if (in_array($value, ['none', 'long', 'entity'], \true)) { return new ConstantBooleanType(\true); } if ($argType->isNumericString()->yes()) { $codePoint = (int) $value; $isValid = $codePoint >= $minCodePoint && $codePoint <= $maxCodePoint; if ($this->phpVersion->supportsAllUnicodeScalarCodePointsInMbSubstituteCharacter()) { $isValid = $isValid && ($codePoint < 0xd800 || $codePoint > 0xdfff); } return new ConstantBooleanType($isValid); } if ($this->phpVersion->throwsValueErrorForInternalFunctions()) { return new NeverType(); } return new ConstantBooleanType(\false); } } elseif ($isNull->yes()) { // The $substitute_character arg is nullable in PHP 8+ return new ConstantBooleanType($this->phpVersion->isNullValidArgInMbSubstituteCharacter()); } return new BooleanType(); } } typeSpecifier = $typeSpecifier; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return $functionReflection->getName() === 'define' && $context->null() && count($node->getArgs()) >= 2; } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $constantName = $scope->getType($node->getArgs()[0]->value); if (!$constantName instanceof ConstantStringType || $constantName->getValue() === '') { return new SpecifiedTypes([], []); } return $this->typeSpecifier->create(new Node\Expr\ConstFetch(new Node\Name\FullyQualified($constantName->getValue())), $scope->getType($node->getArgs()[1]->value), TypeSpecifierContext::createTruthy(), \true, $scope); } } getName() === 'pow'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } return $scope->getType(new Pow($functionCall->getArgs()[0]->value, $functionCall->getArgs()[1]->value)); } } 0, 'array_diff_assoc' => 0, 'array_diff_key' => 0, 'array_diff_uassoc' => 0, 'array_diff_ukey' => 0, 'array_diff' => 0, 'array_udiff_assoc' => 0, 'array_udiff_uassoc' => 0, 'array_udiff' => 0, 'array_intersect_assoc' => 0, 'array_intersect_uassoc' => 0, 'array_intersect_ukey' => 0, 'array_intersect' => 0, 'array_uintersect_assoc' => 0, 'array_uintersect_uassoc' => 0, 'array_uintersect' => 0]; public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return array_key_exists($functionReflection->getName(), self::FUNCTION_NAMES); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $argumentPosition = self::FUNCTION_NAMES[$functionReflection->getName()]; if (!isset($functionCall->getArgs()[$argumentPosition])) { return null; } $argument = $functionCall->getArgs()[$argumentPosition]; $argumentType = $scope->getType($argument->value); $argumentKeyType = $argumentType->getIterableKeyType(); $argumentValueType = $argumentType->getIterableValueType(); if ($argument->unpack) { $argumentKeyType = $argumentKeyType->generalize(GeneralizePrecision::moreSpecific()); $argumentValueType = $argumentValueType->getIterableValueType()->generalize(GeneralizePrecision::moreSpecific()); } $array = new ArrayType($argumentKeyType, $argumentValueType); if ($functionReflection->getName() === 'array_unique' && $argumentType->isIterableAtLeastOnce()->yes()) { $array = TypeCombinator::intersect($array, new NonEmptyArrayType()); } return $array; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'highlight_string'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $args = $functionCall->getArgs(); if (count($args) < 2) { if ($this->phpVersion->highlightStringDoesNotReturnFalse()) { return new ConstantBooleanType(\true); } return new BooleanType(); } $returnType = $scope->getType($args[1]->value); if ($returnType->isTrue()->yes()) { return new StringType(); } if ($this->phpVersion->highlightStringDoesNotReturnFalse()) { return new ConstantBooleanType(\true); } return new BooleanType(); } } getName() === 'version_compare'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } $version1Strings = $scope->getType($functionCall->getArgs()[0]->value)->getConstantStrings(); $version2Strings = $scope->getType($functionCall->getArgs()[1]->value)->getConstantStrings(); $counts = [count($version1Strings), count($version2Strings)]; if (isset($functionCall->getArgs()[2])) { $operatorStrings = $scope->getType($functionCall->getArgs()[2]->value)->getConstantStrings(); $counts[] = count($operatorStrings); $returnType = new BooleanType(); } else { $returnType = TypeCombinator::union(new ConstantIntegerType(-1), new ConstantIntegerType(0), new ConstantIntegerType(1)); } if (count(array_filter($counts, static function (int $count) : bool { return $count === 0; })) > 0) { return $returnType; // one of the arguments is not a constant string } if (count(array_filter($counts, static function (int $count) : bool { return $count > 1; })) > 1) { return $returnType; // more than one argument can have multiple possibilities, avoid combinatorial explosion } $types = []; foreach ($version1Strings as $version1String) { foreach ($version2Strings as $version2String) { if (isset($operatorStrings)) { foreach ($operatorStrings as $operatorString) { $value = version_compare($version1String->getValue(), $version2String->getValue(), $operatorString->getValue()); $types[$value] = new ConstantBooleanType($value); } } else { $value = version_compare($version1String->getValue(), $version2String->getValue()); $types[$value] = new ConstantIntegerType($value); } } } return TypeCombinator::union(...$types); } } constantHelper = $constantHelper; } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return $functionReflection->getName() === 'defined' && count($node->getArgs()) >= 1 && $context->true(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $constantName = $scope->getType($node->getArgs()[0]->value); if (!$constantName instanceof ConstantStringType || $constantName->getValue() === '') { return new SpecifiedTypes([], []); } $expr = $this->constantHelper->createExprFromConstantName($constantName->getValue()); if ($expr === null) { return new SpecifiedTypes([], []); } return $this->typeSpecifier->create($expr, new MixedType(), $context, \false, $scope); } } getName() === 'get_class'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $args = $functionCall->getArgs(); if (count($args) === 0) { if ($scope->isInTrait()) { return new ClassStringType(); } if ($scope->isInClass()) { return new ConstantStringType($scope->getClassReflection()->getName(), \true); } return new ConstantBooleanType(\false); } $argType = $scope->getType($args[0]->value); if ($scope->isInTrait() && TypeUtils::findThisType($argType) !== null) { return new ClassStringType(); } return TypeTraverser::map($argType, static function (Type $type, callable $traverse) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type instanceof EnumCaseObjectType) { return new GenericClassStringType(new ObjectType($type->getClassName())); } $objectClassNames = $type->getObjectClassNames(); if ($type instanceof TemplateType && $objectClassNames === []) { if ($type instanceof ObjectWithoutClassType) { return new GenericClassStringType($type); } return new UnionType([new GenericClassStringType($type), new ConstantBooleanType(\false)]); } elseif ($type instanceof MixedType) { return new UnionType([new ClassStringType(), new ConstantBooleanType(\false)]); } elseif ($type instanceof StaticType) { return new GenericClassStringType($type->getStaticObjectType()); } elseif ($objectClassNames !== []) { return new GenericClassStringType($type); } elseif ($type instanceof ObjectWithoutClassType) { return new ClassStringType(); } return new ConstantBooleanType(\false); }); } } phpVersion = $phpVersion; } public function isStaticMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === '__construct' && $methodReflection->getDeclaringClass()->getName() === DateInterval::class; } public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) === 0) { return $methodReflection->getThrowType(); } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $constantStrings = $valueType->getConstantStrings(); foreach ($constantStrings as $constantString) { try { new DateInterval($constantString->getValue()); } catch (\Exception $e) { // phpcs:ignore return $this->exceptionType(); } $valueType = TypeCombinator::remove($valueType, $constantString); } if (!$valueType instanceof NeverType) { return $this->exceptionType(); } return null; } private function exceptionType() : Type { if ($this->phpVersion->hasDateTimeExceptions()) { return new ObjectType('DateMalformedIntervalStringException'); } return new ObjectType('Exception'); } } getName() === 'bind'; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { $closureType = $scope->getType($methodCall->getArgs()[0]->value); if (!$closureType instanceof ClosureType) { return null; } return $closureType; } } getName() === 'get_called_class'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { if ($scope->isInClass()) { return $scope->getType(new ClassConstFetch(new Name('static'), 'class')); } return new ConstantBooleanType(\false); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return in_array($functionReflection->getName(), ['substr', 'mb_substr'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $string = $scope->getType($args[0]->value); $offset = $scope->getType($args[1]->value); $negativeOffset = IntegerRangeType::fromInterval(null, -1)->isSuperTypeOf($offset)->yes(); $zeroOffset = (new ConstantIntegerType(0))->isSuperTypeOf($offset)->yes(); $length = null; $positiveLength = \false; $maybeOneLength = \false; if (count($args) === 3) { $length = $scope->getType($args[2]->value); $positiveLength = IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($length)->yes(); $maybeOneLength = !(new ConstantIntegerType(1))->isSuperTypeOf($length)->no(); } $constantStrings = $string->getConstantStrings(); if (count($constantStrings) > 0 && $offset instanceof ConstantIntegerType && ($length === null || $length instanceof ConstantIntegerType)) { $results = []; foreach ($constantStrings as $constantString) { if ($length !== null) { if ($functionReflection->getName() === 'mb_substr') { $substr = mb_substr($constantString->getValue(), $offset->getValue(), $length->getValue()); } else { $substr = substr($constantString->getValue(), $offset->getValue(), $length->getValue()); } } else { if ($functionReflection->getName() === 'mb_substr') { $substr = mb_substr($constantString->getValue(), $offset->getValue()); } else { $substr = substr($constantString->getValue(), $offset->getValue()); } } if (is_bool($substr)) { $results[] = new ConstantBooleanType($substr); } else { $results[] = new ConstantStringType($substr); } } return TypeCombinator::union(...$results); } $accessoryTypes = []; $isNotEmpty = \false; if ($string->isLowercaseString()->yes()) { $accessoryTypes[] = new AccessoryLowercaseStringType(); } if ($string->isUppercaseString()->yes()) { $accessoryTypes[] = new AccessoryUppercaseStringType(); } if ($string->isNonEmptyString()->yes() && ($negativeOffset || $zeroOffset && $positiveLength)) { $isNotEmpty = \true; if ($string->isNonFalsyString()->yes() && !$maybeOneLength) { $accessoryTypes[] = new AccessoryNonFalsyStringType(); } else { $accessoryTypes[] = new AccessoryNonEmptyStringType(); } } if (count($accessoryTypes) > 0) { $accessoryTypes[] = new StringType(); if (!$isNotEmpty && $this->phpVersion->substrReturnFalseInsteadOfEmptyString()) { return TypeCombinator::union(new ConstantBooleanType(\false), new IntersectionType($accessoryTypes)); } return new IntersectionType($accessoryTypes); } return null; } } typeSpecifier = $typeSpecifier; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return in_array($functionReflection->getName(), ['array_key_exists', 'key_exists'], \true) && !$context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { if (count($node->getArgs()) < 2) { return new SpecifiedTypes(); } $key = $node->getArgs()[0]->value; $array = $node->getArgs()[1]->value; $keyType = $scope->getType($key); $arrayType = $scope->getType($array); if (!$keyType instanceof ConstantIntegerType && !$keyType instanceof ConstantStringType && !$arrayType->isIterableAtLeastOnce()->no()) { if ($context->true()) { $arrayKeyType = $arrayType->getIterableKeyType(); if ($keyType->isString()->yes()) { $arrayKeyType = $arrayKeyType->toString(); } elseif ($keyType->isString()->maybe()) { $arrayKeyType = TypeCombinator::union($arrayKeyType, $arrayKeyType->toString()); } $specifiedTypes = $this->typeSpecifier->create($key, $arrayKeyType, $context, \false, $scope); $arrayDimFetch = new ArrayDimFetch($array, $key); return $specifiedTypes->unionWith($this->typeSpecifier->create($arrayDimFetch, $arrayType->getIterableValueType(), $context, \false, $scope, new Identical($arrayDimFetch, new ConstFetch(new Name('__PHPSTAN_FAUX_CONSTANT'))))); } return new SpecifiedTypes(); } if ($context->true()) { $type = TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new HasOffsetType($keyType)); } else { $type = new HasOffsetType($keyType); } return $this->typeSpecifier->create($array, $type, $context, \false, $scope); } } regexShapeMatcher = $regexShapeMatcher; } public function isFunctionSupported(FunctionReflection $functionReflection, ParameterReflection $parameter) : bool { return in_array(strtolower($functionReflection->getName()), ['preg_match', 'preg_match_all'], \true) && in_array($parameter->getName(), ['subpatterns', 'matches'], \true); } public function getParameterOutTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, ParameterReflection $parameter, Scope $scope) : ?Type { $args = $funcCall->getArgs(); $patternArg = $args[0] ?? null; $matchesArg = $args[2] ?? null; $flagsArg = $args[3] ?? null; if ($patternArg === null || $matchesArg === null) { return null; } $flagsType = null; if ($flagsArg !== null) { $flagsType = $scope->getType($flagsArg->value); } if ($functionReflection->getName() === 'preg_match') { return $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createMaybe(), $scope); } return $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, TrinaryLogic::createMaybe(), $scope); } } getName() === 'ltrim'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) !== 2) { return null; } $string = $scope->getType($functionCall->getArgs()[0]->value); $trimChars = $scope->getType($functionCall->getArgs()[1]->value); if ($trimChars instanceof ConstantStringType && $trimChars->getValue() === '\\' && $string->isClassStringType()->yes()) { if ($string instanceof ConstantStringType) { return new ConstantStringType(ltrim($string->getValue(), $trimChars->getValue()), \true); } return new ClassStringType(); } return null; } } |null */ private $componentTypesPairedConstants = null; /** @var array|null */ private $componentTypesPairedStrings = null; /** @var array|null */ private $componentTypesPairedConstantsForLowercaseString = null; /** @var array|null */ private $componentTypesPairedStringsForLowercaseString = null; /** * @var ?Type */ private $allComponentsTogetherType = null; /** * @var ?Type */ private $allComponentsTogetherTypeForLowercaseString = null; public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'parse_url'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 1) { return null; } $this->cacheReturnTypes(); $urlType = $scope->getType($functionCall->getArgs()[0]->value); if (count($functionCall->getArgs()) > 1) { $componentType = $scope->getType($functionCall->getArgs()[1]->value); if (!$componentType->isConstantValue()->yes()) { return $this->createAllComponentsReturnType($urlType->isLowercaseString()->yes()); } $componentType = $componentType->toInteger(); if (!$componentType instanceof ConstantIntegerType) { return $this->createAllComponentsReturnType($urlType->isLowercaseString()->yes()); } } else { $componentType = new ConstantIntegerType(-1); } if (count($urlType->getConstantStrings()) > 0) { $types = []; foreach ($urlType->getConstantStrings() as $constantString) { try { $result = @parse_url($constantString->getValue(), $componentType->getValue()); } catch (ValueError $e) { $types[] = new ConstantBooleanType(\false); continue; } $types[] = $scope->getTypeFromValue($result); } return TypeCombinator::union(...$types); } if ($componentType->getValue() === -1) { return TypeCombinator::union($this->createComponentsArray($urlType->isLowercaseString()->yes()), new ConstantBooleanType(\false)); } if ($urlType->isLowercaseString()->yes()) { return $this->componentTypesPairedConstantsForLowercaseString[$componentType->getValue()] ?? new ConstantBooleanType(\false); } return $this->componentTypesPairedConstants[$componentType->getValue()] ?? new ConstantBooleanType(\false); } private function createAllComponentsReturnType(bool $urlIsLowercase) : Type { if ($urlIsLowercase) { if ($this->allComponentsTogetherTypeForLowercaseString === null) { $returnTypes = [new ConstantBooleanType(\false), new NullType(), IntegerRangeType::fromInterval(0, 65535), new IntersectionType([new StringType(), new AccessoryLowercaseStringType()]), $this->createComponentsArray(\true)]; $this->allComponentsTogetherTypeForLowercaseString = TypeCombinator::union(...$returnTypes); } return $this->allComponentsTogetherTypeForLowercaseString; } if ($this->allComponentsTogetherType === null) { $returnTypes = [new ConstantBooleanType(\false), new NullType(), IntegerRangeType::fromInterval(0, 65535), new StringType(), $this->createComponentsArray(\false)]; $this->allComponentsTogetherType = TypeCombinator::union(...$returnTypes); } return $this->allComponentsTogetherType; } private function createComponentsArray(bool $urlIsLowercase) : Type { $builder = ConstantArrayTypeBuilder::createEmpty(); if ($urlIsLowercase) { if ($this->componentTypesPairedStringsForLowercaseString === null) { throw new ShouldNotHappenException(); } foreach ($this->componentTypesPairedStringsForLowercaseString as $componentName => $componentValueType) { $builder->setOffsetValueType(new ConstantStringType($componentName), $componentValueType, \true); } } else { if ($this->componentTypesPairedStrings === null) { throw new ShouldNotHappenException(); } foreach ($this->componentTypesPairedStrings as $componentName => $componentValueType) { $builder->setOffsetValueType(new ConstantStringType($componentName), $componentValueType, \true); } } return $builder->getArray(); } private function cacheReturnTypes() : void { if ($this->componentTypesPairedConstants !== null) { return; } $string = new StringType(); $lowercaseString = new IntersectionType([new StringType(), new AccessoryLowercaseStringType()]); $port = IntegerRangeType::fromInterval(0, 65535); $false = new ConstantBooleanType(\false); $null = new NullType(); $stringOrFalseOrNull = TypeCombinator::union($string, $false, $null); $lowercaseStringOrFalseOrNull = TypeCombinator::union($lowercaseString, $false, $null); $portOrFalseOrNull = TypeCombinator::union($port, $false, $null); $this->componentTypesPairedConstants = [PHP_URL_SCHEME => $stringOrFalseOrNull, PHP_URL_HOST => $stringOrFalseOrNull, PHP_URL_PORT => $portOrFalseOrNull, PHP_URL_USER => $stringOrFalseOrNull, PHP_URL_PASS => $stringOrFalseOrNull, PHP_URL_PATH => $stringOrFalseOrNull, PHP_URL_QUERY => $stringOrFalseOrNull, PHP_URL_FRAGMENT => $stringOrFalseOrNull]; $this->componentTypesPairedConstantsForLowercaseString = [PHP_URL_SCHEME => $lowercaseStringOrFalseOrNull, PHP_URL_HOST => $lowercaseStringOrFalseOrNull, PHP_URL_PORT => $portOrFalseOrNull, PHP_URL_USER => $lowercaseStringOrFalseOrNull, PHP_URL_PASS => $lowercaseStringOrFalseOrNull, PHP_URL_PATH => $lowercaseStringOrFalseOrNull, PHP_URL_QUERY => $lowercaseStringOrFalseOrNull, PHP_URL_FRAGMENT => $lowercaseStringOrFalseOrNull]; $this->componentTypesPairedStrings = ['scheme' => $string, 'host' => $string, 'port' => $port, 'user' => $string, 'pass' => $string, 'path' => $string, 'query' => $string, 'fragment' => $string]; $this->componentTypesPairedStringsForLowercaseString = ['scheme' => $lowercaseString, 'host' => $lowercaseString, 'port' => $port, 'user' => $lowercaseString, 'pass' => $lowercaseString, 'path' => $lowercaseString, 'query' => $lowercaseString, 'fragment' => $lowercaseString]; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return strtolower($functionReflection->getName()) === 'array_keys'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) !== 1) { return null; } $arrayType = $scope->getType($functionCall->getArgs()[0]->value); if ($arrayType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } return $arrayType->getKeysArray(); } } getName() === 'array_key_first'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new NullType(); } $keyType = $argType->getFirstIterableKeyType(); if ($iterableAtLeastOnce->yes()) { return $keyType; } return TypeCombinator::union($keyType, new NullType()); } } getName() === '__construct'; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : Type { if (!isset($methodCall->getArgs()[0])) { return new ObjectType(DatePeriod::class); } if (!$methodCall->class instanceof Name) { return new ObjectType(DatePeriod::class); } $className = $scope->resolveName($methodCall->class); if (strtolower($className) !== 'dateperiod') { return new ObjectType($className); } $firstArgType = $scope->getType($methodCall->getArgs()[0]->value); if ($firstArgType->isString()->yes()) { $firstArgType = new ObjectType(DateTime::class); } $thirdArgType = null; if (isset($methodCall->getArgs()[2])) { $thirdArgType = $scope->getType($methodCall->getArgs()[2]->value); } if (!$thirdArgType instanceof Type) { return new GenericObjectType(DatePeriod::class, [$firstArgType, new NullType(), new IntegerType()]); } if ((new ObjectType(DateTimeInterface::class))->isSuperTypeOf($thirdArgType)->yes()) { return new GenericObjectType(DatePeriod::class, [$firstArgType, $thirdArgType, new NullType()]); } if ($thirdArgType->isInteger()->yes()) { return new GenericObjectType(DatePeriod::class, [$firstArgType, new NullType(), $thirdArgType]); } return new ObjectType(DatePeriod::class); } } getName() === 'array_map'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $numArgs = count($functionCall->getArgs()); if ($numArgs < 2) { return null; } $singleArrayArgument = !isset($functionCall->getArgs()[2]); $callableType = $scope->getType($functionCall->getArgs()[0]->value); $callableIsNull = $callableType->isNull()->yes(); $callableParametersAcceptors = null; if ($callableType->isCallable()->yes()) { $callableParametersAcceptors = $callableType->getCallableParametersAcceptors($scope); $valueType = ParametersAcceptorSelector::selectFromTypes(array_map(static function (Node\Arg $arg) use($scope) { return $scope->getType($arg->value)->getIterableValueType(); }, array_slice($functionCall->getArgs(), 1)), $callableParametersAcceptors, \false)->getReturnType(); } elseif ($callableIsNull) { $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); $argTypes = []; $areAllSameSize = \true; $expectedSize = null; foreach (array_slice($functionCall->getArgs(), 1) as $index => $arg) { $argTypes[$index] = $argType = $scope->getType($arg->value); if (!$areAllSameSize || $numArgs === 2) { continue; } $arraySizes = $argType->getArraySize()->getConstantScalarValues(); if ($arraySizes === []) { $areAllSameSize = \false; continue; } foreach ($arraySizes as $size) { $expectedSize = $expectedSize ?? $size; if ($expectedSize === $size) { continue; } $areAllSameSize = \false; continue 2; } } if (!$areAllSameSize) { $firstArr = $functionCall->getArgs()[1]->value; $identities = []; foreach (array_slice($functionCall->getArgs(), 2) as $arg) { $identities[] = new Node\Expr\BinaryOp\Identical($firstArr, $arg->value); } $and = array_reduce($identities, static function (Node\Expr $a, Node\Expr $b) { return new Node\Expr\BinaryOp\BooleanAnd($a, $b); }, new Node\Expr\ConstFetch(new Node\Name('true'))); $areAllSameSize = $scope->getType($and)->isTrue()->yes(); } $addNull = !$areAllSameSize; foreach ($argTypes as $index => $argType) { $offsetValueType = $argType->getIterableValueType(); if ($addNull) { $offsetValueType = TypeCombinator::addNull($offsetValueType); } $arrayBuilder->setOffsetValueType(new ConstantIntegerType($index), $offsetValueType); } $valueType = $arrayBuilder->getArray(); } else { $valueType = new MixedType(); } $arrayType = $scope->getType($functionCall->getArgs()[1]->value); if ($singleArrayArgument) { if ($callableIsNull) { return $arrayType; } $constantArrays = $arrayType->getConstantArrays(); if (count($constantArrays) > 0) { $arrayTypes = []; $totalCount = TypeCombinator::countConstantArrayValueTypes($constantArrays) * TypeCombinator::countConstantArrayValueTypes([$valueType]); if ($totalCount < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { foreach ($constantArrays as $constantArray) { $returnedArrayBuilder = ConstantArrayTypeBuilder::createEmpty(); $valueTypes = $constantArray->getValueTypes(); foreach ($constantArray->getKeyTypes() as $i => $keyType) { $returnedArrayBuilder->setOffsetValueType($keyType, $callableParametersAcceptors !== null ? ParametersAcceptorSelector::selectFromTypes([$valueTypes[$i]], $callableParametersAcceptors, \false)->getReturnType() : $valueType, $constantArray->isOptionalKey($i)); } $returnedArray = $returnedArrayBuilder->getArray(); if ($constantArray->isList()->yes()) { $returnedArray = AccessoryArrayListType::intersectWith($returnedArray); } $arrayTypes[] = $returnedArray; } $mappedArrayType = TypeCombinator::union(...$arrayTypes); } else { $mappedArrayType = TypeCombinator::intersect(new ArrayType($arrayType->getIterableKeyType(), $valueType), ...TypeUtils::getAccessoryTypes($arrayType)); } } elseif ($arrayType->isArray()->yes()) { $mappedArrayType = TypeCombinator::intersect(new ArrayType($arrayType->getIterableKeyType(), $valueType), ...TypeUtils::getAccessoryTypes($arrayType)); } else { $mappedArrayType = new ArrayType(new MixedType(), $valueType); } } else { $mappedArrayType = AccessoryArrayListType::intersectWith(TypeCombinator::intersect(new ArrayType(new IntegerType(), $valueType), ...TypeUtils::getAccessoryTypes($arrayType))); } if ($arrayType->isIterableAtLeastOnce()->yes()) { $mappedArrayType = TypeCombinator::intersect($mappedArrayType, new NonEmptyArrayType()); } return $mappedArrayType; } } reflectionProvider = $reflectionProvider; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'get_parent_class'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) === 0) { if ($scope->isInTrait()) { return null; } if ($scope->isInClass()) { return $this->findParentClassType($scope->getClassReflection()); } return new ConstantBooleanType(\false); } $argType = $scope->getType($functionCall->getArgs()[0]->value); if ($scope->isInTrait() && TypeUtils::findThisType($argType) !== null) { return null; } $constantStrings = $argType->getConstantStrings(); if (count($constantStrings) > 0) { return TypeCombinator::union(...array_map(function (ConstantStringType $stringType) : Type { return $this->findParentClassNameType($stringType->getValue()); }, $constantStrings)); } $classNames = $argType->getObjectClassNames(); if (count($classNames) > 0) { return TypeCombinator::union(...array_map(function (string $classNames) : Type { return $this->findParentClassNameType($classNames); }, $classNames)); } return null; } private function findParentClassNameType(string $className) : Type { if (!$this->reflectionProvider->hasClass($className)) { return new UnionType([new ClassStringType(), new ConstantBooleanType(\false)]); } $classReflection = $this->reflectionProvider->getClass($className); if ($classReflection->isInterface()) { return new UnionType([new ClassStringType(), new ConstantBooleanType(\false)]); } return $this->findParentClassType($classReflection); } private function findParentClassType(ClassReflection $classReflection) : Type { $parentClass = $classReflection->getParentClass(); if ($parentClass === null) { return new ConstantBooleanType(\false); } return new ConstantStringType($parentClass->getName(), \true); } } filterFunctionReturnTypeHelper = $filterFunctionReturnTypeHelper; $this->reflectionProvider = $reflectionProvider; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return in_array(strtolower($functionReflection->getName()), ['filter_var_array', 'filter_input_array'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } $functionName = strtolower($functionReflection->getName()); $inputArgType = $scope->getType($functionCall->getArgs()[0]->value); $inputConstantArrayType = null; if ($functionName === 'filter_var_array') { if ($inputArgType->isArray()->no()) { return new NeverType(); } $inputConstantArrayType = $inputArgType->getConstantArrays()[0] ?? null; } elseif ($functionName === 'filter_input_array') { $supportedTypes = TypeCombinator::union($this->reflectionProvider->getConstant(new Node\Name('INPUT_GET'), null)->getValueType(), $this->reflectionProvider->getConstant(new Node\Name('INPUT_POST'), null)->getValueType(), $this->reflectionProvider->getConstant(new Node\Name('INPUT_COOKIE'), null)->getValueType(), $this->reflectionProvider->getConstant(new Node\Name('INPUT_SERVER'), null)->getValueType(), $this->reflectionProvider->getConstant(new Node\Name('INPUT_ENV'), null)->getValueType()); if (!$inputArgType->isInteger()->yes() || $supportedTypes->isSuperTypeOf($inputArgType)->no()) { return null; } // Pragmatical solution since global expressions are not passed through the scope for performance reasons // See https://github.com/phpstan/phpstan-src/pull/2012 for details $inputArgType = new ArrayType(new StringType(), new MixedType()); } $filterArgType = $scope->getType($functionCall->getArgs()[1]->value); $filterConstantArrayType = $filterArgType->getConstantArrays()[0] ?? null; $addEmptyType = isset($functionCall->getArgs()[2]) ? $scope->getType($functionCall->getArgs()[2]->value) : null; $addEmpty = $addEmptyType === null || $addEmptyType->isTrue()->yes(); $valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty(); if ($filterArgType instanceof ConstantIntegerType) { if ($inputConstantArrayType === null) { $isList = $inputArgType->isList()->yes(); $valueType = $this->filterFunctionReturnTypeHelper->getType($inputArgType->getIterableValueType(), $filterArgType, null); $arrayType = new ArrayType($inputArgType->getIterableKeyType(), $valueType); return $isList ? AccessoryArrayListType::intersectWith($arrayType) : $arrayType; } // Override $add_empty option $addEmpty = \false; $keysType = $inputConstantArrayType; $inputKeysList = array_map(static function ($type) { return $type->getValue(); }, $inputConstantArrayType->getKeyTypes()); $filterTypesMap = array_fill_keys($inputKeysList, $filterArgType); $inputTypesMap = array_combine($inputKeysList, $inputConstantArrayType->getValueTypes()); $optionalKeys = []; foreach ($inputConstantArrayType->getOptionalKeys() as $index) { if (!isset($inputKeysList[$index])) { continue; } $optionalKeys[] = $inputKeysList[$index]; } } elseif ($filterConstantArrayType === null) { if ($inputConstantArrayType === null) { $isList = $inputArgType->isList()->yes(); $valueType = $this->filterFunctionReturnTypeHelper->getType($inputArgType, $filterArgType, null); $arrayType = new ArrayType($inputArgType->getIterableKeyType(), $addEmpty ? TypeCombinator::addNull($valueType) : $valueType); return $isList ? AccessoryArrayListType::intersectWith($arrayType) : $arrayType; } return null; } else { $keysType = $filterConstantArrayType; $filterKeyTypes = $filterConstantArrayType->getKeyTypes(); $filterKeysList = array_map(static function ($type) { return $type->getValue(); }, $filterKeyTypes); $filterTypesMap = array_combine($filterKeysList, $keysType->getValueTypes()); if ($inputConstantArrayType !== null) { $inputKeysList = array_map(static function ($type) { return $type->getValue(); }, $inputConstantArrayType->getKeyTypes()); $inputTypesMap = array_combine($inputKeysList, $inputConstantArrayType->getValueTypes()); $optionalKeys = []; foreach ($inputConstantArrayType->getOptionalKeys() as $index) { if (!isset($inputKeysList[$index])) { continue; } $optionalKeys[] = $inputKeysList[$index]; } } else { $optionalKeys = $filterKeysList; $inputTypesMap = array_fill_keys($optionalKeys, $inputArgType->getIterableValueType()); } } foreach ($keysType->getKeyTypes() as $keyType) { $optional = \false; $key = $keyType->getValue(); $inputType = $inputTypesMap[$key] ?? null; if ($inputType === null) { if ($addEmpty) { $valueTypesBuilder->setOffsetValueType($keyType, new NullType()); } continue; } [$filterType, $flagsType] = $this->fetchFilter($filterTypesMap[$key] ?? new MixedType()); $valueType = $this->filterFunctionReturnTypeHelper->getType($inputType, $filterType, $flagsType); if (in_array($key, $optionalKeys, \true)) { if ($addEmpty) { $valueType = TypeCombinator::addNull($valueType); } else { $optional = \true; } } $valueTypesBuilder->setOffsetValueType($keyType, $valueType, $optional); } return $valueTypesBuilder->getArray(); } /** @return array{?Type, ?Type} */ public function fetchFilter(Type $type) : array { if (!$type->isArray()->yes()) { return [$type, null]; } $filterKey = new ConstantStringType('filter'); if (!$type->hasOffsetValueType($filterKey)->yes()) { return [$type, null]; } $filterOffsetType = $type->getOffsetValueType($filterKey); $filterType = null; if (count($filterOffsetType->getConstantScalarTypes()) > 0) { $filterType = TypeCombinator::union(...$filterOffsetType->getConstantScalarTypes()); } return [$filterType, $type]; } } getName() === 'bindTo'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { $closureType = $scope->getType($methodCall->var); if (!$closureType instanceof ClosureType) { return null; } return $closureType; } } getName() === 'strlen'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) === 0) { return null; } $argType = $scope->getType($args[0]->value); if ($argType->isSuperTypeOf(new BooleanType())->yes()) { $constantScalars = TypeCombinator::remove($argType, new BooleanType())->getConstantScalarTypes(); if (count($constantScalars) > 0) { $constantScalars[] = new ConstantBooleanType(\true); $constantScalars[] = new ConstantBooleanType(\false); } } else { $constantScalars = $argType->getConstantScalarTypes(); } $lengths = []; foreach ($constantScalars as $constantScalar) { $stringScalar = $constantScalar->toString(); if (!$stringScalar instanceof ConstantStringType) { $lengths = []; break; } $length = strlen($stringScalar->getValue()); $lengths[] = $length; } $isNonEmpty = $argType->isNonEmptyString(); $numeric = TypeCombinator::union(new IntegerType(), new FloatType()); $range = null; if (count($lengths) > 0) { $lengths = array_unique($lengths); sort($lengths); if ($lengths === range(min($lengths), max($lengths))) { $range = IntegerRangeType::fromInterval(min($lengths), max($lengths)); } else { $range = TypeCombinator::union(...array_map(static function ($l) { return new ConstantIntegerType($l); }, $lengths)); } } elseif ($argType->isBoolean()->yes()) { $range = IntegerRangeType::fromInterval(0, 1); } elseif ($isNonEmpty->yes() || $numeric->isSuperTypeOf($argType)->yes() || TypeCombinator::remove($argType, $numeric)->isNonEmptyString()->yes()) { $range = IntegerRangeType::fromInterval(1, null); } elseif ($argType->isString()->yes() && $isNonEmpty->no()) { $range = new ConstantIntegerType(0); } return $range; } } typeSpecifier = $typeSpecifier; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return $functionReflection->getName() === 'method_exists' && $context->true() && count($node->getArgs()) >= 2; } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $methodNameType = $scope->getType($node->getArgs()[1]->value); if (!$methodNameType instanceof ConstantStringType) { return new SpecifiedTypes([], []); } $objectType = $scope->getType($node->getArgs()[0]->value); if ($objectType->isString()->yes()) { if ($objectType->isClassStringType()->yes()) { return $this->typeSpecifier->create($node->getArgs()[0]->value, new IntersectionType([$objectType, new HasMethodType($methodNameType->getValue())]), $context, \false, $scope); } return new SpecifiedTypes([], []); } return $this->typeSpecifier->create($node->getArgs()[0]->value, new UnionType([new IntersectionType([new ObjectWithoutClassType(), new HasMethodType($methodNameType->getValue())]), new ClassStringType()]), $context, \false, $scope); } } getName(), self::FUNCTIONS, \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { if (count($functionCall->getArgs()) === 0) { return new NullType(); } $argType = $scope->getType($functionCall->getArgs()[0]->value); switch ($functionReflection->getName()) { case 'strval': return $argType->toString(); case 'intval': $type = $argType->toInteger(); return $type instanceof ErrorType ? new IntegerType() : $type; case 'boolval': return $argType->toBoolean(); case 'floatval': case 'doubleval': $type = $argType->toFloat(); return $type instanceof ErrorType ? new FloatType() : $type; default: throw new ShouldNotHappenException(); } } } getName() === 'assert' && isset($node->getArgs()[0]); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { return $this->typeSpecifier->specifyTypesInCondition($scope, $node->getArgs()[0]->value, TypeSpecifierContext::createTruthy()); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } dateFunctionReturnTypeHelper = $dateFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'date_format'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { if (count($functionCall->getArgs()) < 2) { return new StringType(); } return $this->dateFunctionReturnTypeHelper->getTypeFromFormatType($scope->getType($functionCall->getArgs()[1]->value), \true); } } filterFunctionReturnTypeHelper = $filterFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return strtolower($functionReflection->getName()) === 'filter_var'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 1) { return null; } $inputType = $scope->getType($functionCall->getArgs()[0]->value); $filterType = isset($functionCall->getArgs()[1]) ? $scope->getType($functionCall->getArgs()[1]->value) : null; $flagsType = isset($functionCall->getArgs()[2]) ? $scope->getType($functionCall->getArgs()[2]->value) : null; return $this->filterFunctionReturnTypeHelper->getType($inputType, $filterType, $flagsType); } } getName() === 'array_pop'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new NullType(); } $itemType = $argType->getLastIterableValueType(); if ($iterableAtLeastOnce->yes()) { return $itemType; } return TypeCombinator::union($itemType, new NullType()); } } getObjectClassNames(); if ($allowString) { foreach ($objectOrClassType->getConstantStrings() as $constantString) { $objectOrClassTypeClassNames[] = $constantString->getValue(); } $objectOrClassTypeClassNames = array_values(array_unique($objectOrClassTypeClassNames)); } return TypeTraverser::map($classType, static function (Type $type, callable $traverse) use($objectOrClassTypeClassNames, $allowString, $allowSameClass) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type instanceof ConstantStringType) { if (!$allowSameClass && $objectOrClassTypeClassNames === [$type->getValue()]) { return new NeverType(); } if ($allowString) { return TypeCombinator::union(new ObjectType($type->getValue()), new GenericClassStringType(new ObjectType($type->getValue()))); } return new ObjectType($type->getValue()); } if ($type instanceof GenericClassStringType) { if ($allowString) { return TypeCombinator::union($type->getGenericType(), $type); } return $type->getGenericType(); } if ($allowString) { return TypeCombinator::union(new ObjectWithoutClassType(), new ClassStringType()); } return new ObjectWithoutClassType(); }); } } getName() === 'str_pad'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return new StringType(); } $inputType = $scope->getType($args[0]->value); $lengthType = $scope->getType($args[1]->value); $accessoryTypes = []; if ($inputType->isNonFalsyString()->yes()) { $accessoryTypes[] = new AccessoryNonFalsyStringType(); } elseif ($inputType->isNonEmptyString()->yes() || IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($lengthType)->yes()) { $accessoryTypes[] = new AccessoryNonEmptyStringType(); } if (count($args) < 3) { $padStringType = null; } else { $padStringType = $scope->getType($args[2]->value); } if ($inputType->isLiteralString()->yes() && ($padStringType === null || $padStringType->isLiteralString()->yes())) { $accessoryTypes[] = new AccessoryLiteralStringType(); } if ($inputType->isLowercaseString()->yes() && ($padStringType === null || $padStringType->isLowercaseString()->yes())) { $accessoryTypes[] = new AccessoryLowercaseStringType(); } if ($inputType->isUppercaseString()->yes() && ($padStringType === null || $padStringType->isUppercaseString()->yes())) { $accessoryTypes[] = new AccessoryUppercaseStringType(); } if (count($accessoryTypes) > 0) { $accessoryTypes[] = new StringType(); return new IntersectionType($accessoryTypes); } return new StringType(); } } getName(), ['str_increment', 'str_decrement'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $fnName = $functionReflection->getName(); $args = $functionCall->getArgs(); if (count($args) !== 1) { return null; } $argType = $scope->getType($args[0]->value); if (count($argType->getConstantScalarValues()) === 0) { return null; } $types = []; foreach ($argType->getConstantScalarValues() as $value) { if (!(is_string($value) || is_int($value) || is_float($value))) { continue; } $string = (string) $value; if (preg_match('/\\A(?:0|[1-9A-Za-z][0-9A-Za-z]*)+\\z/', $string) < 1) { continue; } $result = null; if ($fnName === 'str_increment') { $result = $this->increment($string); } elseif ($fnName === 'str_decrement') { $result = $this->decrement($string); } if ($result === null) { continue; } $types[] = new ConstantStringType($result); } return count($types) === 0 ? new ErrorType() : TypeCombinator::union(...$types); } private function increment(string $s) : string { if (is_numeric($s)) { $offset = stripos($s, 'e'); if ($offset !== \false) { // Using increment operator would cast the string to float // Therefore we manually increment it to convert it to an "f"/"F" that doesn't get affected $c = $s[$offset]; $c++; $s[$offset] = $c; $s++; $s[$offset] = ['f' => 'e', 'F' => 'E', 'g' => 'f', 'G' => 'F'][$s[$offset]]; return $s; } } return (string) ++$s; } private function decrement(string $s) : ?string { if (in_array($s, ['a', 'A', '0'], \true)) { return null; } $decremented = str_split($s, 1); $position = count($decremented) - 1; $carry = \false; $map = ['0' => '9', 'A' => 'Z', 'a' => 'z']; do { $c = $decremented[$position]; if (!in_array($c, ['a', 'A', '0'], \true)) { $carry = \false; $decremented[$position] = chr(ord($c) - 1); } else { $carry = \true; $decremented[$position] = $map[$c]; } } while ($carry && $position-- > 0); if ($carry || count($decremented) > 1 && $decremented[0] === '0') { if (count($decremented) === 1) { return null; } unset($decremented[0]); } return implode($decremented); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_search'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $argsCount = count($functionCall->getArgs()); if ($argsCount < 2) { return null; } $haystackArgType = $scope->getType($functionCall->getArgs()[1]->value); if ($haystackArgType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } if ($argsCount < 3) { return TypeCombinator::union($haystackArgType->getIterableKeyType(), new ConstantBooleanType(\false)); } $strictArgType = $scope->getType($functionCall->getArgs()[2]->value); if (!$strictArgType->isTrue()->yes()) { return TypeCombinator::union($haystackArgType->getIterableKeyType(), new ConstantBooleanType(\false)); } $needleArgType = $scope->getType($functionCall->getArgs()[0]->value); if ($haystackArgType->getIterableValueType()->isSuperTypeOf($needleArgType)->no()) { return new ConstantBooleanType(\false); } return $haystackArgType->searchArray($needleArgType); } } getName() === 'array_reduce'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[1])) { return null; } $callbackType = $scope->getType($functionCall->getArgs()[1]->value); if ($callbackType->isCallable()->no()) { return null; } $callbackReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $callbackType->getCallableParametersAcceptors($scope))->getReturnType(); if (isset($functionCall->getArgs()[2])) { $initialType = $scope->getType($functionCall->getArgs()[2]->value); } else { $initialType = new NullType(); } $arraysType = $scope->getType($functionCall->getArgs()[0]->value); $constantArrays = $arraysType->getConstantArrays(); if (count($constantArrays) > 0) { $onlyEmpty = TrinaryLogic::createYes(); $onlyNonEmpty = TrinaryLogic::createYes(); foreach ($constantArrays as $constantArray) { $iterableAtLeastOnce = $constantArray->isIterableAtLeastOnce(); $onlyEmpty = $onlyEmpty->and($iterableAtLeastOnce->negate()); $onlyNonEmpty = $onlyNonEmpty->and($iterableAtLeastOnce); } if ($onlyEmpty->yes()) { return $initialType; } if ($onlyNonEmpty->yes()) { return $callbackReturnType; } } return TypeCombinator::union($callbackReturnType, $initialType); } } className = $className; } public function getClass() : string { return $this->className; } public function isMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getDeclaringClass()->getName() === $this->className && $methodReflection->getName() === 'getAttributes'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) === 0) { return null; } $argType = $scope->getType($methodCall->getArgs()[0]->value); $classType = $argType->getClassStringObjectType(); return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new GenericObjectType(ReflectionAttribute::class, [$classType]))); } } regexGroupParser = $regexGroupParser; $this->regexExpressionHelper = $regexExpressionHelper; $this->phpVersion = $phpVersion; } public function matchAllExpr(Expr $patternExpr, ?Type $flagsType, TrinaryLogic $wasMatched, Scope $scope) : ?Type { return $this->matchPatternType($this->getPatternType($patternExpr, $scope), $flagsType, $wasMatched, \true); } public function matchExpr(Expr $patternExpr, ?Type $flagsType, TrinaryLogic $wasMatched, Scope $scope) : ?Type { return $this->matchPatternType($this->getPatternType($patternExpr, $scope), $flagsType, $wasMatched, \false); } /** * @deprecated use matchExpr() instead for a more precise result */ public function matchType(Type $patternType, ?Type $flagsType, TrinaryLogic $wasMatched) : ?Type { return $this->matchPatternType($patternType, $flagsType, $wasMatched, \false); } private function matchPatternType(Type $patternType, ?Type $flagsType, TrinaryLogic $wasMatched, bool $matchesAll) : ?Type { if ($wasMatched->no()) { return new ConstantArrayType([], []); } $constantStrings = $patternType->getConstantStrings(); if (count($constantStrings) === 0) { return null; } $flags = null; if ($flagsType !== null) { if (!$flagsType instanceof ConstantIntegerType) { return null; } /** @var int-mask $flags */ $flags = $flagsType->getValue() & (PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER | PREG_SET_ORDER | PREG_UNMATCHED_AS_NULL | self::PREG_UNMATCHED_AS_NULL_ON_72_73); // some other unsupported/unexpected flag was passed in if ($flags !== $flagsType->getValue()) { return null; } } $matchedTypes = []; foreach ($constantStrings as $constantString) { $matched = $this->matchRegex($constantString->getValue(), $flags, $wasMatched, $matchesAll); if ($matched === null) { return null; } $matchedTypes[] = $matched; } if (count($matchedTypes) === 1) { return $matchedTypes[0]; } return TypeCombinator::union(...$matchedTypes); } /** * @param int-mask|null $flags */ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched, bool $matchesAll) : ?Type { $parseResult = $this->regexGroupParser->parseGroups($regex); if ($parseResult === null) { // regex could not be parsed by Hoa/Regex return null; } [$groupList, $markVerbs] = $parseResult; $trailingOptionals = 0; foreach (array_reverse($groupList) as $captureGroup) { if (!$captureGroup->isOptional()) { break; } $trailingOptionals++; } $onlyOptionalTopLevelGroup = $this->getOnlyOptionalTopLevelGroup($groupList); $onlyTopLevelAlternation = $this->getOnlyTopLevelAlternation($groupList); $flags = $flags ?? 0; if (!$matchesAll && $wasMatched->yes() && $onlyOptionalTopLevelGroup !== null) { // if only one top level capturing optional group exists // we build a more precise tagged union of a empty-match and a match with the group $onlyOptionalTopLevelGroup->forceNonOptional(); $combiType = $this->buildArrayType($groupList, $wasMatched, $trailingOptionals, $flags, $markVerbs, $matchesAll); if (!$this->containsUnmatchedAsNull($flags, $matchesAll)) { // positive match has a subject but not any capturing group $combiType = TypeCombinator::union(new ConstantArrayType([new ConstantIntegerType(0)], [$this->createSubjectValueType($flags, $matchesAll)], [1], [], \true), $combiType); } $onlyOptionalTopLevelGroup->clearOverrides(); return $combiType; } elseif (!$matchesAll && $onlyOptionalTopLevelGroup === null && $onlyTopLevelAlternation !== null && !$wasMatched->no()) { // if only a single top level alternation exist built a more precise tagged union $combiTypes = []; $isOptionalAlternation = \false; foreach ($onlyTopLevelAlternation->getGroupCombinations() as $groupCombo) { $comboList = $groupList; $beforeCurrentCombo = \true; foreach ($comboList as $groupId => $group) { if (in_array($groupId, $groupCombo, \true)) { $isOptionalAlternation = $group->inOptionalAlternation(); $group->forceNonOptional(); $beforeCurrentCombo = \false; } elseif ($beforeCurrentCombo && !$group->resetsGroupCounter()) { $group->forceNonOptional(); $group->forceType($this->containsUnmatchedAsNull($flags, $matchesAll) ? new NullType() : new ConstantStringType('')); } elseif ($group->getAlternationId() === $onlyTopLevelAlternation->getId() && !$this->containsUnmatchedAsNull($flags, $matchesAll)) { unset($comboList[$groupId]); } } $combiType = $this->buildArrayType($comboList, $wasMatched, $trailingOptionals, $flags, $markVerbs, $matchesAll); $combiTypes[] = $combiType; foreach ($groupCombo as $groupId) { $group = $comboList[$groupId]; $group->clearOverrides(); } } if (!$this->containsUnmatchedAsNull($flags, $matchesAll) && ($onlyTopLevelAlternation->getAlternationsCount() !== count($onlyTopLevelAlternation->getGroupCombinations()) || $isOptionalAlternation)) { // positive match has a subject but not any capturing group $combiTypes[] = new ConstantArrayType([new ConstantIntegerType(0)], [$this->createSubjectValueType($flags, $matchesAll)], [1], [], \true); } return TypeCombinator::union(...$combiTypes); } // the general case, which should work in all cases but does not yield the most // precise result possible in some cases return $this->buildArrayType($groupList, $wasMatched, $trailingOptionals, $flags, $markVerbs, $matchesAll); } /** * @param array $captureGroups */ private function getOnlyOptionalTopLevelGroup(array $captureGroups) : ?RegexCapturingGroup { $group = null; foreach ($captureGroups as $captureGroup) { if (!$captureGroup->isTopLevel()) { continue; } if (!$captureGroup->isOptional()) { return null; } if ($group !== null) { return null; } $group = $captureGroup; } return $group; } /** * @param array $captureGroups */ private function getOnlyTopLevelAlternation(array $captureGroups) : ?RegexAlternation { $alternation = null; foreach ($captureGroups as $captureGroup) { if (!$captureGroup->isTopLevel()) { continue; } if (!$captureGroup->inAlternation()) { return null; } if ($captureGroup->inOptionalQuantification()) { return null; } if ($alternation === null) { $alternation = $captureGroup->getAlternation(); } elseif ($alternation->getId() !== $captureGroup->getAlternation()->getId()) { return null; } } return $alternation; } /** * @param array $captureGroups * @param list $markVerbs */ private function buildArrayType(array $captureGroups, TrinaryLogic $wasMatched, int $trailingOptionals, int $flags, array $markVerbs, bool $matchesAll) : Type { $builder = ConstantArrayTypeBuilder::createEmpty(); // first item in matches contains the overall match. $builder->setOffsetValueType($this->getKeyType(0), $this->createSubjectValueType($flags, $matchesAll), $this->isSubjectOptional($wasMatched, $matchesAll)); $countGroups = count($captureGroups); $i = 0; foreach ($captureGroups as $captureGroup) { $isTrailingOptional = $i >= $countGroups - $trailingOptionals; $isLastGroup = $i === $countGroups - 1; $groupValueType = $this->createGroupValueType($captureGroup, $wasMatched, $flags, $isTrailingOptional, $isLastGroup, $matchesAll); $optional = $this->isGroupOptional($captureGroup, $wasMatched, $flags, $isTrailingOptional, $matchesAll); if ($captureGroup->isNamed()) { $builder->setOffsetValueType($this->getKeyType($captureGroup->getName()), $groupValueType, $optional); } $builder->setOffsetValueType($this->getKeyType($i + 1), $groupValueType, $optional); $i++; } if (count($markVerbs) > 0) { $markTypes = []; foreach ($markVerbs as $mark) { $markTypes[] = new ConstantStringType($mark); } $builder->setOffsetValueType($this->getKeyType('MARK'), TypeCombinator::union(...$markTypes), \true); } if ($matchesAll && $this->containsSetOrder($flags)) { $arrayType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $builder->getArray())); if (!$wasMatched->yes()) { $arrayType = TypeCombinator::union(new ConstantArrayType([], []), $arrayType); } return $arrayType; } return $builder->getArray(); } private function isSubjectOptional(TrinaryLogic $wasMatched, bool $matchesAll) : bool { if ($matchesAll) { return \false; } return !$wasMatched->yes(); } private function createSubjectValueType(int $flags, bool $matchesAll) : Type { $subjectValueType = TypeCombinator::removeNull($this->getValueType(new StringType(), $flags, $matchesAll)); if ($matchesAll) { if ($this->containsPatternOrder($flags)) { $subjectValueType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $subjectValueType)); } } return $subjectValueType; } private function isGroupOptional(RegexCapturingGroup $captureGroup, TrinaryLogic $wasMatched, int $flags, bool $isTrailingOptional, bool $matchesAll) : bool { if ($matchesAll) { if ($isTrailingOptional && !$this->containsUnmatchedAsNull($flags, $matchesAll) && $this->containsSetOrder($flags)) { return \true; } return \false; } if (!$wasMatched->yes()) { $optional = \true; } else { if (!$isTrailingOptional) { $optional = \false; } elseif ($this->containsUnmatchedAsNull($flags, $matchesAll)) { $optional = \false; } else { $optional = $captureGroup->isOptional(); } } return $optional; } private function createGroupValueType(RegexCapturingGroup $captureGroup, TrinaryLogic $wasMatched, int $flags, bool $isTrailingOptional, bool $isLastGroup, bool $matchesAll) : Type { if ($matchesAll) { if (!$this->containsSetOrder($flags) && !$this->containsUnmatchedAsNull($flags, $matchesAll) && $captureGroup->isOptional() || $this->containsSetOrder($flags) && !$this->containsUnmatchedAsNull($flags, $matchesAll) && $captureGroup->isOptional() && !$isTrailingOptional) { $groupValueType = $this->getValueType(TypeCombinator::union($captureGroup->getType(), new ConstantStringType('')), $flags, $matchesAll); $groupValueType = TypeCombinator::removeNull($groupValueType); } else { $groupValueType = $this->getValueType($captureGroup->getType(), $flags, $matchesAll); } if (!$isTrailingOptional && $this->containsUnmatchedAsNull($flags, $matchesAll) && !$captureGroup->isOptional()) { $groupValueType = TypeCombinator::removeNull($groupValueType); } if ($this->containsPatternOrder($flags)) { $groupValueType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $groupValueType)); } return $groupValueType; } if (!$isLastGroup && !$this->containsUnmatchedAsNull($flags, $matchesAll) && $captureGroup->isOptional()) { $groupValueType = $this->getValueType(TypeCombinator::union($captureGroup->getType(), new ConstantStringType('')), $flags, $matchesAll); } else { $groupValueType = $this->getValueType($captureGroup->getType(), $flags, $matchesAll); } if ($wasMatched->yes()) { if (!$isTrailingOptional && $this->containsUnmatchedAsNull($flags, $matchesAll) && !$captureGroup->isOptional()) { $groupValueType = TypeCombinator::removeNull($groupValueType); } } return $groupValueType; } private function containsOffsetCapture(int $flags) : bool { return ($flags & PREG_OFFSET_CAPTURE) !== 0; } private function containsPatternOrder(int $flags) : bool { // If no order flag is given, PREG_PATTERN_ORDER is assumed. return !$this->containsSetOrder($flags); } private function containsSetOrder(int $flags) : bool { return ($flags & PREG_SET_ORDER) !== 0; } private function containsUnmatchedAsNull(int $flags, bool $matchesAll) : bool { if ($matchesAll) { // preg_match_all() with PREG_UNMATCHED_AS_NULL works consistently across php-versions // https://3v4l.org/tKmPn return ($flags & PREG_UNMATCHED_AS_NULL) !== 0; } return ($flags & PREG_UNMATCHED_AS_NULL) !== 0 && (($flags & self::PREG_UNMATCHED_AS_NULL_ON_72_73) !== 0 || $this->phpVersion->supportsPregUnmatchedAsNull()); } /** * @param int|string $key */ private function getKeyType($key) : Type { if (is_string($key)) { return new ConstantStringType($key); } return new ConstantIntegerType($key); } private function getValueType(Type $baseType, int $flags, bool $matchesAll) : Type { $valueType = $baseType; // unmatched groups return -1 as offset $offsetType = IntegerRangeType::fromInterval(-1, null); if ($this->containsUnmatchedAsNull($flags, $matchesAll)) { $valueType = TypeCombinator::addNull($valueType); } if ($this->containsOffsetCapture($flags)) { $builder = ConstantArrayTypeBuilder::createEmpty(); $builder->setOffsetValueType(new ConstantIntegerType(0), $valueType); $builder->setOffsetValueType(new ConstantIntegerType(1), $offsetType); return $builder->getArray(); } return $valueType; } private function getPatternType(Expr $patternExpr, Scope $scope) : Type { if ($patternExpr instanceof Expr\BinaryOp\Concat) { return $this->regexExpressionHelper->resolvePatternConcat($patternExpr, $scope); } return $scope->getType($patternExpr); } } reflectionProvider = $reflectionProvider; } public function isStaticMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === '__construct' && $methodReflection->getDeclaringClass()->getName() === ReflectionMethod::class; } public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) < 2) { return $methodReflection->getThrowType(); } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $propertyType = $scope->getType($methodCall->getArgs()[1]->value); foreach (TypeUtils::flattenTypes($valueType) as $type) { if ($type instanceof GenericClassStringType) { $classes = $type->getGenericType()->getObjectClassNames(); } elseif ($type instanceof ConstantStringType && $this->reflectionProvider->hasClass($type->getValue())) { $classes = [$type->getValue()]; } else { return $methodReflection->getThrowType(); } foreach ($classes as $class) { $classReflection = $this->reflectionProvider->getClass($class); foreach ($propertyType->getConstantStrings() as $constantPropertyString) { if (!$classReflection->hasMethod($constantPropertyString->getValue())) { return $methodReflection->getThrowType(); } } } $valueType = TypeCombinator::remove($valueType, $type); } if (!$valueType instanceof NeverType) { return $methodReflection->getThrowType(); } // Look for non constantStrings value. foreach ($propertyType->getConstantStrings() as $constantPropertyString) { $propertyType = TypeCombinator::remove($propertyType, $constantPropertyString); } if (!$propertyType instanceof NeverType) { return $methodReflection->getThrowType(); } return null; } } phpVersion = $phpVersion; } public function isStaticMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === '__construct' && in_array($methodReflection->getDeclaringClass()->getName(), [DateTime::class, DateTimeImmutable::class], \true); } public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) === 0) { return null; } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $constantStrings = $valueType->getConstantStrings(); foreach ($constantStrings as $constantString) { try { new DateTime($constantString->getValue()); } catch (\Exception $e) { // phpcs:ignore return $this->exceptionType(); } $valueType = TypeCombinator::remove($valueType, $constantString); } if (!$valueType instanceof NeverType) { return $this->exceptionType(); } return null; } private function exceptionType() : Type { if ($this->phpVersion->hasDateTimeExceptions()) { return new ObjectType('DateMalformedStringException'); } return new ObjectType('Exception'); } } constantHelper = $constantHelper; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'constant'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 1) { return null; } $nameType = $scope->getType($functionCall->getArgs()[0]->value); $results = []; foreach ($nameType->getConstantStrings() as $constantName) { $expr = $this->constantHelper->createExprFromConstantName($constantName->getValue()); if ($expr === null) { return new ErrorType(); } $results[] = $scope->getType($expr); } if (count($results) > 0) { return TypeCombinator::union(...$results); } return null; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return strtolower($functionReflection->getName()) === 'array_values'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) !== 1) { return null; } $arrayType = $scope->getType($functionCall->getArgs()[0]->value); if ($arrayType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } return $arrayType->getValuesArray(); } } getName() === '__construct' && $methodReflection->getDeclaringClass()->getName() === ReflectionClass::class; } public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) < 1) { return $methodReflection->getThrowType(); } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $classOrString = new UnionType([new ClassStringType(), new ObjectWithoutClassType()]); if ($classOrString->isSuperTypeOf($valueType)->yes()) { return null; } return $methodReflection->getThrowType(); } } */ private $argumentPositions = ['json_encode' => 1, 'json_decode' => 3]; public function __construct(ReflectionProvider $reflectionProvider, BitwiseFlagHelper $bitwiseFlagAnalyser) { $this->reflectionProvider = $reflectionProvider; $this->bitwiseFlagAnalyser = $bitwiseFlagAnalyser; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { if ($functionReflection->getName() === 'json_decode') { return \true; } return $functionReflection->getName() === 'json_encode' && $this->reflectionProvider->hasConstant(new FullyQualified('JSON_THROW_ON_ERROR'), null); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $argumentPosition = $this->argumentPositions[$functionReflection->getName()]; $defaultReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants())->getReturnType(); if ($functionReflection->getName() === 'json_decode') { $defaultReturnType = $this->narrowTypeForJsonDecode($functionCall, $scope, $defaultReturnType); } if (!isset($functionCall->getArgs()[$argumentPosition])) { return $defaultReturnType; } $optionsExpr = $functionCall->getArgs()[$argumentPosition]->value; if ($functionReflection->getName() === 'json_encode' && $this->bitwiseFlagAnalyser->bitwiseOrContainsConstant($optionsExpr, $scope, 'JSON_THROW_ON_ERROR')->yes()) { return TypeCombinator::remove($defaultReturnType, new ConstantBooleanType(\false)); } return $defaultReturnType; } private function narrowTypeForJsonDecode(FuncCall $funcCall, Scope $scope, Type $fallbackType) : Type { $args = $funcCall->getArgs(); $isForceArray = $this->isForceArray($funcCall, $scope); if (!isset($args[0])) { return $fallbackType; } $firstValueType = $scope->getType($args[0]->value); if ($firstValueType instanceof ConstantStringType) { return $this->resolveConstantStringType($firstValueType, $isForceArray); } if ($isForceArray) { return TypeCombinator::remove($fallbackType, new ObjectWithoutClassType()); } return $fallbackType; } /** * Is "json_decode(..., true)"? */ private function isForceArray(FuncCall $funcCall, Scope $scope) : bool { $args = $funcCall->getArgs(); if (!isset($args[1])) { return \false; } $secondArgType = $scope->getType($args[1]->value); $secondArgValue = $secondArgType instanceof ConstantScalarType ? $secondArgType->getValue() : null; if (is_bool($secondArgValue)) { return $secondArgValue; } if ($secondArgValue !== null || !isset($args[3])) { return \false; } // depends on used constants, @see https://www.php.net/manual/en/json.constants.php#constant.json-object-as-array return $this->bitwiseFlagAnalyser->bitwiseOrContainsConstant($args[3]->value, $scope, 'JSON_OBJECT_AS_ARRAY')->yes(); } private function resolveConstantStringType(ConstantStringType $constantStringType, bool $isForceArray) : Type { $decodedValue = json_decode($constantStringType->getValue(), $isForceArray); return ConstantTypeHelper::getTypeFromValue($decodedValue); } } getName() === 'base64_decode'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { if (!isset($functionCall->getArgs()[1])) { return new StringType(); } $argType = $scope->getType($functionCall->getArgs()[1]->value); if ($argType instanceof MixedType) { return new BenevolentUnionType([new StringType(), new ConstantBooleanType(\false)]); } $isTrueType = $argType->isTrue(); $isFalseType = $argType->isFalse(); $compareTypes = $isTrueType->compareTo($isFalseType); if ($compareTypes === $isTrueType) { return new UnionType([new StringType(), new ConstantBooleanType(\false)]); } if ($compareTypes === $isFalseType) { return new StringType(); } // second argument could be interpreted as true if (!$isTrueType->no()) { return new UnionType([new StringType(), new ConstantBooleanType(\false)]); } return new StringType(); } } getName() === 'get_debug_type'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 1) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); if ($argType instanceof UnionType) { return new UnionType(array_map(Closure::fromCallable([self::class, 'resolveOneType']), $argType->getTypes())); } return self::resolveOneType($argType); } /** * @see https://www.php.net/manual/en/function.get-debug-type.php#refsect1-function.get-debug-type-returnvalues * @see https://github.com/php/php-src/commit/ef0e4478c51540510b67f7781ad240f5e0592ee4 */ private static function resolveOneType(Type $type) : Type { if ($type->isNull()->yes()) { return new ConstantStringType('null'); } if ($type->isBoolean()->yes()) { return new ConstantStringType('bool'); } if ($type->isInteger()->yes()) { return new ConstantStringType('int'); } if ($type->isFloat()->yes()) { return new ConstantStringType('float'); } if ($type->isString()->yes()) { return new ConstantStringType('string'); } if ($type->isArray()->yes()) { return new ConstantStringType('array'); } // "resources" type+state is skipped since we cannot infer the state if ($type->isObject()->yes()) { $reflections = $type->getObjectClassReflections(); $types = []; foreach ($reflections as $reflection) { // if the class is not final, the actual returned string might be of a child class if ($reflection->isFinal() && !$reflection->isAnonymous()) { $types[] = new ConstantStringType($reflection->getName()); } if ($reflection->isAnonymous()) { // phpcs:ignore $parentClass = $reflection->getParentClass(); $implementedInterfaces = $reflection->getImmediateInterfaces(); if ($parentClass !== null) { $types[] = new ConstantStringType($parentClass->getName() . '@anonymous'); } elseif ($implementedInterfaces !== []) { $firstInterface = $implementedInterfaces[array_key_first($implementedInterfaces)]; $types[] = new ConstantStringType($firstInterface->getName() . '@anonymous'); } else { $types[] = new ConstantStringType('class@anonymous'); } } } switch (count($types)) { case 0: return new StringType(); case 1: return $types[0]; default: return new UnionType($types); } } return new StringType(); } } getName() === 'str_repeat'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return new StringType(); } $multiplierType = $scope->getType($args[1]->value); if ((new ConstantIntegerType(0))->isSuperTypeOf($multiplierType)->yes()) { return new ConstantStringType(''); } if (IntegerRangeType::fromInterval(null, 0)->isSuperTypeOf($multiplierType)->yes()) { return new NeverType(); } $inputType = $scope->getType($args[0]->value); if ($inputType instanceof ConstantStringType && $multiplierType instanceof ConstantIntegerType && strlen($inputType->getValue()) * $multiplierType->getValue() < 100) { return new ConstantStringType(str_repeat($inputType->getValue(), $multiplierType->getValue())); } $accessoryTypes = []; if ($inputType->isNonEmptyString()->yes()) { if (IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($multiplierType)->yes()) { if ($inputType->isNonFalsyString()->yes()) { $accessoryTypes[] = new AccessoryNonFalsyStringType(); } else { $accessoryTypes[] = new AccessoryNonEmptyStringType(); } } } if ($inputType->isLiteralString()->yes()) { $accessoryTypes[] = new AccessoryLiteralStringType(); if ($inputType->isNumericString()->yes() && IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($multiplierType)->yes()) { $onlyNumbers = \true; foreach ($inputType->getConstantStrings() as $constantString) { if (Strings::match($constantString->getValue(), '#^[0-9]+$#') === null) { $onlyNumbers = \false; break; } } if ($onlyNumbers) { $accessoryTypes[] = new AccessoryNumericStringType(); } } } if ($inputType->isLowercaseString()->yes()) { $accessoryTypes[] = new AccessoryLowercaseStringType(); } if ($inputType->isUppercaseString()->yes()) { $accessoryTypes[] = new AccessoryUppercaseStringType(); } if (count($accessoryTypes) > 0) { $accessoryTypes[] = new StringType(); return new IntersectionType($accessoryTypes); } return new StringType(); } } phpVersion = $phpVersion; } public function isMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === 'modify' && in_array($methodReflection->getDeclaringClass()->getName(), [DateTime::class, DateTimeImmutable::class], \true); } public function getThrowTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) === 0) { return null; } if (!$this->phpVersion->hasDateTimeExceptions()) { return null; } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $constantStrings = $valueType->getConstantStrings(); foreach ($constantStrings as $constantString) { try { $dateTime = new DateTime(); $dateTime->modify($constantString->getValue()); } catch (\Exception $e) { // phpcs:ignore return $this->exceptionType(); } $valueType = TypeCombinator::remove($valueType, $constantString); } if (!$valueType instanceof NeverType) { return $this->exceptionType(); } return null; } private function exceptionType() : Type { if ($this->phpVersion->hasDateTimeExceptions()) { return new ObjectType('DateMalformedStringException'); } return new ObjectType('Exception'); } } checkMaybeUndefinedVariables = $checkMaybeUndefinedVariables; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'compact'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) === 0) { return null; } if ($scope->canAnyVariableExist() && !$this->checkMaybeUndefinedVariables) { return null; } $array = ConstantArrayTypeBuilder::createEmpty(); foreach ($functionCall->getArgs() as $arg) { $type = $scope->getType($arg->value); $constantStrings = $this->findConstantStrings($type); if ($constantStrings === null) { return null; } foreach ($constantStrings as $constantString) { $has = $scope->hasVariableType($constantString->getValue()); if ($has->no()) { continue; } $array->setOffsetValueType($constantString, $scope->getVariableType($constantString->getValue()), $has->maybe()); } } return $array->getArray(); } /** * @return array|null */ private function findConstantStrings(Type $type) : ?array { if ($type instanceof ConstantStringType) { return [$type]; } if ($type instanceof ConstantArrayType) { $result = []; foreach ($type->getValueTypes() as $valueType) { $constantStrings = $this->findConstantStrings($valueType); if ($constantStrings === null) { return null; } $result = array_merge($result, $constantStrings); } return $result; } return null; } } */ private $dateTimeClass; /** @param class-string $dateTimeClass */ public function __construct(PhpVersion $phpVersion, string $dateTimeClass = DateTime::class) { $this->phpVersion = $phpVersion; $this->dateTimeClass = $dateTimeClass; } public function getClass() : string { return $this->dateTimeClass; } public function isMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === 'modify'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) < 1) { return null; } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $constantStrings = $valueType->getConstantStrings(); $hasFalse = \false; $hasDateTime = \false; foreach ($constantStrings as $constantString) { try { $result = @(new DateTime())->modify($constantString->getValue()); } catch (Throwable $e) { $valueType = TypeCombinator::remove($valueType, $constantString); continue; } if ($result === \false) { $hasFalse = \true; } else { $hasDateTime = \true; } $valueType = TypeCombinator::remove($valueType, $constantString); } if (!$valueType instanceof NeverType) { return null; } if ($hasFalse) { if (!$hasDateTime) { return new ConstantBooleanType(\false); } return null; } elseif ($hasDateTime) { return $scope->getType($methodCall->var); } if ($this->phpVersion->hasDateTimeExceptions()) { return new NeverType(); } return null; } } getName()) === 'iterator_to_array'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $arguments = $functionCall->getArgs(); if ($arguments === []) { return null; } $traversableType = $scope->getType($arguments[0]->value); if (isset($arguments[1])) { $preserveKeysType = $scope->getType($arguments[1]->value); if ($preserveKeysType->isFalse()->yes()) { return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $traversableType->getIterableValueType())); } } $arrayKeyType = $traversableType->getIterableKeyType()->toArrayKey(); if ($arrayKeyType instanceof ErrorType) { return new NeverType(\true); } return new ArrayType($arrayKeyType, $traversableType->getIterableValueType()); } } getName() === 'array_find_key'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } $arrayType = $scope->getType($functionCall->getArgs()[0]->value); if (count($arrayType->getArrays()) < 1) { return null; } return TypeCombinator::union($arrayType->getIterableKeyType(), new NullType()); } } getName() === 'dio_stat'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $valueType = new IntegerType(); $builder = ConstantArrayTypeBuilder::createEmpty(); $keys = ['device', 'inode', 'mode', 'nlink', 'uid', 'gid', 'device_type', 'size', 'blocksize', 'blocks', 'atime', 'mtime', 'ctime']; foreach ($keys as $key) { $builder->setOffsetValueType(new ConstantStringType($key), $valueType); } return TypeCombinator::addNull($builder->getArray()); } } getName() === 'assert'; } public function getThrowTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, Scope $scope) : ?Type { if (count($funcCall->getArgs()) < 2) { return $functionReflection->getThrowType(); } $customThrow = $scope->getType($funcCall->getArgs()[1]->value); if ((new ObjectType(Throwable::class))->isSuperTypeOf($customThrow)->yes()) { return $customThrow; } return $functionReflection->getThrowType(); } } getName() === 'fromCallable'; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (!isset($methodCall->getArgs()[0])) { return null; } $callableType = $scope->getType($methodCall->getArgs()[0]->value); if ($callableType->isCallable()->no()) { return new ErrorType(); } $closureTypes = []; foreach ($callableType->getCallableParametersAcceptors($scope) as $variant) { $parameters = $variant->getParameters(); $closureTypes[] = new ClosureType($parameters, $variant->getReturnType(), $variant->isVariadic(), $variant->getTemplateTypeMap(), $variant->getResolvedTemplateTypeMap(), $variant instanceof ParametersAcceptorWithPhpDocs ? $variant->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), [], $variant->getThrowPoints(), $variant->getImpurePoints(), $variant->getInvalidateExpressions(), $variant->getUsedVariables(), $variant->acceptsNamedArguments()); } return TypeCombinator::union(...$closureTypes); } } getName(), ['next', 'prev'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new ConstantBooleanType(\false); } $valueType = $argType->getIterableValueType(); return TypeCombinator::union($valueType, new ConstantBooleanType(\false)); } } getName() === 'openssl_encrypt' && $parameter->getName() === 'tag'; } public function getParameterOutTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, ParameterReflection $parameter, Scope $scope) : ?Type { $args = $funcCall->getArgs(); $cipherArg = $args[1] ?? null; if ($cipherArg === null) { return null; } $tagTypes = []; foreach ($scope->getType($cipherArg->value)->getConstantStrings() as $cipherType) { $cipher = strtolower($cipherType->getValue()); $mode = substr($cipher, -3); if (!in_array($cipher, openssl_get_cipher_methods(), \true)) { $tagTypes[] = new NullType(); continue; } if (in_array($mode, ['gcm', 'ccm'], \true)) { $tagTypes[] = TypeCombinator::intersect(new StringType(), new AccessoryNonEmptyStringType()); continue; } $tagTypes[] = new NullType(); } if ($tagTypes === []) { return TypeCombinator::addNull(TypeCombinator::intersect(new StringType(), new AccessoryNonEmptyStringType())); } return TypeCombinator::union(...$tagTypes); } } getName() === 'gettype'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 1) { return null; } $valueType = $scope->getType($functionCall->getArgs()[0]->value); return TypeTraverser::map($valueType, static function (Type $valueType, callable $traverse) : Type { if ($valueType instanceof UnionType || $valueType instanceof IntersectionType) { return $traverse($valueType); } if ($valueType->isString()->yes()) { return new ConstantStringType('string'); } if ($valueType->isArray()->yes()) { return new ConstantStringType('array'); } if ($valueType->isBoolean()->yes()) { return new ConstantStringType('boolean'); } $resource = new ResourceType(); if ($resource->isSuperTypeOf($valueType)->yes()) { return new UnionType([new ConstantStringType('resource'), new ConstantStringType('resource (closed)')]); } if ($valueType->isInteger()->yes()) { return new ConstantStringType('integer'); } if ($valueType->isFloat()->yes()) { // for historical reasons "double" is returned in case of a float, and not simply "float" return new ConstantStringType('double'); } if ($valueType->isNull()->yes()) { return new ConstantStringType('NULL'); } if ($valueType->isObject()->yes()) { return new ConstantStringType('object'); } return TypeCombinator::union(new ConstantStringType('string'), new ConstantStringType('array'), new ConstantStringType('boolean'), new ConstantStringType('resource'), new ConstantStringType('resource (closed)'), new ConstantStringType('integer'), new ConstantStringType('double'), new ConstantStringType('NULL'), new ConstantStringType('object'), new ConstantStringType('unknown type')); }); } } getName() === 'array_shift'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new NullType(); } $itemType = $argType->getFirstIterableValueType(); if ($iterableAtLeastOnce->yes()) { return $itemType; } return TypeCombinator::union($itemType, new NullType()); } } getName() === 'createFromDateString'; } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { $arguments = $methodCall->getArgs(); if (!isset($arguments[0])) { return null; } $strings = $scope->getType($arguments[0]->value)->getConstantStrings(); $possibleReturnTypes = []; foreach ($strings as $string) { try { $result = @DateInterval::createFromDateString($string->getValue()); } catch (Throwable $e) { $possibleReturnTypes[] = \false; continue; } $possibleReturnTypes[] = $result instanceof DateInterval ? DateInterval::class : \false; } // the error case, when wrong types are passed if (count($possibleReturnTypes) === 0) { return null; } if (in_array(\false, $possibleReturnTypes, \true) && in_array(DateInterval::class, $possibleReturnTypes, \true)) { return null; } if (in_array(\false, $possibleReturnTypes, \true)) { return new ConstantBooleanType(\false); } return new ObjectType(DateInterval::class); } } reflectionProvider = $reflectionProvider; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'pathinfo'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, Node\Expr\FuncCall $functionCall, Scope $scope) : ?Type { $argsCount = count($functionCall->getArgs()); if ($argsCount === 0) { return null; } $pathType = $scope->getType($functionCall->getArgs()[0]->value); $builder = ConstantArrayTypeBuilder::createEmpty(); $builder->setOffsetValueType(new ConstantStringType('dirname'), new StringType(), !$pathType->isNonEmptyString()->yes()); $builder->setOffsetValueType(new ConstantStringType('basename'), new StringType()); $builder->setOffsetValueType(new ConstantStringType('extension'), new StringType(), \true); $builder->setOffsetValueType(new ConstantStringType('filename'), new StringType()); $arrayType = $builder->getArray(); if ($argsCount === 1) { return $arrayType; } $flagsType = $scope->getType($functionCall->getArgs()[1]->value); $scalarValues = $flagsType->getConstantScalarValues(); if ($scalarValues !== []) { $pathInfoAll = $this->getConstant('PATHINFO_ALL'); if ($pathInfoAll === null) { return null; } $result = []; foreach ($scalarValues as $scalarValue) { if ($scalarValue === $pathInfoAll) { $result[] = $arrayType; } else { $result[] = new StringType(); } } return TypeCombinator::union(...$result); } return TypeCombinator::union($arrayType, new StringType()); } /** * @param non-empty-string $constantName */ private function getConstant(string $constantName) : ?int { if (!$this->reflectionProvider->hasConstant(new Node\Name($constantName), null)) { return null; } $constant = $this->reflectionProvider->getConstant(new Node\Name($constantName), null); $valueType = $constant->getValueType(); if (!$valueType instanceof ConstantIntegerType) { throw new ShouldNotHappenException(sprintf('Constant %s does not have integer type.', $constantName)); } return $valueType->getValue(); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_reverse'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $type = $scope->getType($functionCall->getArgs()[0]->value); if ($type->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } $preserveKeysType = isset($functionCall->getArgs()[1]) ? $scope->getType($functionCall->getArgs()[1]->value) : new ConstantBooleanType(\false); return $type->reverseArray($preserveKeysType->isTrue()); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'explode'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $delimiterType = $scope->getType($args[0]->value); $isEmptyString = (new ConstantStringType(''))->isSuperTypeOf($delimiterType); if ($isEmptyString->yes()) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new ConstantBooleanType(\false); } $stringType = $scope->getType($args[1]->value); $accessory = []; if ($stringType->isLowercaseString()->yes()) { $accessory[] = new AccessoryLowercaseStringType(); } if ($stringType->isUppercaseString()->yes()) { $accessory[] = new AccessoryUppercaseStringType(); } if (count($accessory) > 0) { $accessory[] = new StringType(); $returnValueType = new IntersectionType($accessory); } else { $returnValueType = new StringType(); } $returnType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $returnValueType)); if (!isset($args[2]) || IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($scope->getType($args[2]->value))->yes()) { $returnType = TypeCombinator::intersect($returnType, new NonEmptyArrayType()); } if (!$this->phpVersion->throwsValueErrorForInternalFunctions() && $isEmptyString->maybe()) { $returnType = TypeCombinator::union($returnType, new ConstantBooleanType(\false)); } if ($delimiterType instanceof MixedType) { $returnType = TypeUtils::toBenevolentUnion($returnType); } return $returnType; } } reflectionProvider = $reflectionProvider; } public function isStaticMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === '__construct' && $methodReflection->getDeclaringClass()->getName() === ReflectionProperty::class; } public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) < 2) { return $methodReflection->getThrowType(); } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $propertyType = $scope->getType($methodCall->getArgs()[1]->value); foreach ($valueType->getConstantStrings() as $constantString) { if (!$this->reflectionProvider->hasClass($constantString->getValue())) { return $methodReflection->getThrowType(); } $classReflection = $this->reflectionProvider->getClass($constantString->getValue()); foreach ($propertyType->getConstantStrings() as $constantPropertyString) { if (!$classReflection->hasProperty($constantPropertyString->getValue())) { return $methodReflection->getThrowType(); } } $valueType = TypeCombinator::remove($valueType, $constantString); } if (!$valueType instanceof NeverType) { return $methodReflection->getThrowType(); } // Look for non constantStrings value. foreach ($propertyType->getConstantStrings() as $constantPropertyString) { $propertyType = TypeCombinator::remove($propertyType, $constantPropertyString); } if (!$propertyType instanceof NeverType) { return $methodReflection->getThrowType(); } return null; } } getName() === 'array_splice'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $arrayArg = $scope->getType($functionCall->getArgs()[0]->value); return new ArrayType($arrayArg->getIterableKeyType(), $arrayArg->getIterableValueType()); } } reflectionProvider = $reflectionProvider; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'curl_getinfo'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 1) { return null; } if (count($functionCall->getArgs()) <= 1) { return $this->createAllComponentsReturnType(); } $componentType = $scope->getType($functionCall->getArgs()[1]->value); if (!$componentType->isNull()->no()) { return $this->createAllComponentsReturnType(); } $componentType = $componentType->toInteger(); if (!$componentType instanceof ConstantIntegerType) { return $this->createAllComponentsReturnType(); } $stringType = new StringType(); $integerType = new IntegerType(); $floatType = new FloatType(); $falseType = new ConstantBooleanType(\false); $stringFalseType = TypeCombinator::union($stringType, $falseType); $integerStringArrayType = new ArrayType($integerType, $stringType); $nestedStringStringArrayType = new ArrayType($integerType, new ArrayType($stringType, $stringType)); $componentTypesPairedConstants = ['CURLINFO_EFFECTIVE_URL' => $stringType, 'CURLINFO_FILETIME' => $integerType, 'CURLINFO_TOTAL_TIME' => $floatType, 'CURLINFO_NAMELOOKUP_TIME' => $floatType, 'CURLINFO_CONNECT_TIME' => $floatType, 'CURLINFO_PRETRANSFER_TIME' => $floatType, 'CURLINFO_STARTTRANSFER_TIME' => $floatType, 'CURLINFO_REDIRECT_COUNT' => $integerType, 'CURLINFO_REDIRECT_TIME' => $floatType, 'CURLINFO_REDIRECT_URL' => $stringType, 'CURLINFO_PRIMARY_IP' => $stringType, 'CURLINFO_PRIMARY_PORT' => $integerType, 'CURLINFO_LOCAL_IP' => $stringType, 'CURLINFO_LOCAL_PORT' => $integerType, 'CURLINFO_SIZE_UPLOAD' => $integerType, 'CURLINFO_SIZE_DOWNLOAD' => $integerType, 'CURLINFO_SPEED_DOWNLOAD' => $integerType, 'CURLINFO_SPEED_UPLOAD' => $integerType, 'CURLINFO_HEADER_SIZE' => $integerType, 'CURLINFO_HEADER_OUT' => $stringFalseType, 'CURLINFO_REQUEST_SIZE' => $integerType, 'CURLINFO_SSL_VERIFYRESULT' => $integerType, 'CURLINFO_CONTENT_LENGTH_DOWNLOAD' => $floatType, 'CURLINFO_CONTENT_LENGTH_UPLOAD' => $floatType, 'CURLINFO_CONTENT_TYPE' => $stringFalseType, 'CURLINFO_PRIVATE' => $stringFalseType, 'CURLINFO_RESPONSE_CODE' => $integerType, 'CURLINFO_HTTP_CONNECTCODE' => $integerType, 'CURLINFO_HTTPAUTH_AVAIL' => $integerType, 'CURLINFO_PROXYAUTH_AVAIL' => $integerType, 'CURLINFO_OS_ERRNO' => $integerType, 'CURLINFO_NUM_CONNECTS' => $integerType, 'CURLINFO_SSL_ENGINES' => $integerStringArrayType, 'CURLINFO_COOKIELIST' => $integerStringArrayType, 'CURLINFO_FTP_ENTRY_PATH' => $stringFalseType, 'CURLINFO_APPCONNECT_TIME' => $floatType, 'CURLINFO_CERTINFO' => $nestedStringStringArrayType, 'CURLINFO_CONDITION_UNMET' => $integerType, 'CURLINFO_RTSP_CLIENT_CSEQ' => $integerType, 'CURLINFO_RTSP_CSEQ_RECV' => $integerType, 'CURLINFO_RTSP_SERVER_CSEQ' => $integerType, 'CURLINFO_RTSP_SESSION_ID' => $integerType, 'CURLINFO_HTTP_VERSION' => $integerType, 'CURLINFO_PROTOCOL' => $stringType, 'CURLINFO_PROXY_SSL_VERIFYRESULT' => $integerType, 'CURLINFO_SCHEME' => $stringType, 'CURLINFO_CONTENT_LENGTH_DOWNLOAD_T' => $integerType, 'CURLINFO_CONTENT_LENGTH_UPLOAD_T' => $integerType, 'CURLINFO_SIZE_DOWNLOAD_T' => $integerType, 'CURLINFO_SIZE_UPLOAD_T' => $integerType, 'CURLINFO_SPEED_DOWNLOAD_T' => $integerType, 'CURLINFO_SPEED_UPLOAD_T' => $integerType, 'CURLINFO_APPCONNECT_TIME_T' => $integerType, 'CURLINFO_CONNECT_TIME_T' => $integerType, 'CURLINFO_FILETIME_T' => $integerType, 'CURLINFO_NAMELOOKUP_TIME_T' => $integerType, 'CURLINFO_PRETRANSFER_TIME_T' => $integerType, 'CURLINFO_REDIRECT_TIME_T' => $integerType, 'CURLINFO_STARTTRANSFER_TIME_T' => $integerType, 'CURLINFO_TOTAL_TIME_T' => $integerType]; foreach ($componentTypesPairedConstants as $constantName => $type) { $constantNameNode = new Name($constantName); if ($this->reflectionProvider->hasConstant($constantNameNode, $scope) === \false) { continue; } $valueType = $this->reflectionProvider->getConstant($constantNameNode, $scope)->getValueType(); if ($componentType->isSuperTypeOf($valueType)->yes()) { return $type; } } return $falseType; } private function createAllComponentsReturnType() : Type { $returnTypes = [new ConstantBooleanType(\false)]; $builder = ConstantArrayTypeBuilder::createEmpty(); $stringType = new StringType(); $integerType = new IntegerType(); $floatType = new FloatType(); $stringOrNullType = TypeCombinator::union($stringType, new NullType()); $nestedStringStringArrayType = new ArrayType($integerType, new ArrayType($stringType, $stringType)); $componentTypesPairedStrings = ['url' => $stringType, 'content_type' => $stringOrNullType, 'http_code' => $integerType, 'header_size' => $integerType, 'request_size' => $integerType, 'filetime' => $integerType, 'ssl_verify_result' => $integerType, 'redirect_count' => $integerType, 'total_time' => $floatType, 'namelookup_time' => $floatType, 'connect_time' => $floatType, 'pretransfer_time' => $floatType, 'size_upload' => $floatType, 'size_download' => $floatType, 'speed_download' => $floatType, 'speed_upload' => $floatType, 'download_content_length' => $floatType, 'upload_content_length' => $floatType, 'starttransfer_time' => $floatType, 'redirect_time' => $floatType, 'redirect_url' => $stringType, 'primary_ip' => $stringType, 'certinfo' => $nestedStringStringArrayType, 'primary_port' => $integerType, 'local_ip' => $stringType, 'local_port' => $integerType, 'http_version' => $integerType, 'protocol' => $integerType, 'ssl_verifyresult' => $integerType, 'scheme' => $stringType]; foreach ($componentTypesPairedStrings as $componentName => $componentValueType) { $builder->setOffsetValueType(new ConstantStringType($componentName), $componentValueType); } $returnTypes[] = $builder->getArray(); return TypeUtils::toBenevolentUnion(TypeCombinator::union(...$returnTypes)); } } getName() === 'strtotime'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $defaultReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants())->getReturnType(); if (count($functionCall->getArgs()) === 0) { return $defaultReturnType; } $argType = $scope->getType($functionCall->getArgs()[0]->value); if ($argType instanceof MixedType) { return TypeUtils::toBenevolentUnion($defaultReturnType); } $results = array_unique(array_map(static function (ConstantStringType $string) { return strtotime($string->getValue()); }, $argType->getConstantStrings())); $resultTypes = array_unique(array_map(static function ($value) : string { return gettype($value); }, $results)); if (count($resultTypes) !== 1 || count($results) === 0) { return $defaultReturnType; } if ($results[0] === \false) { return new ConstantBooleanType(\false); } // 2nd param $baseTimestamp is too non-deterministic so simply return int if (count($functionCall->getArgs()) > 1) { return new IntegerType(); } // if it is positive we can narrow down to positive-int as long as time flows forward if (min(array_map('intval', $results)) > 0) { return IntegerRangeType::createAllGreaterThan(0); } return new IntegerType(); } } getName() === 'hrtime'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $arrayType = new ConstantArrayType([new ConstantIntegerType(0), new ConstantIntegerType(1)], [new IntegerType(), new IntegerType()], [2], [], TrinaryLogic::createYes()); $numberType = TypeUtils::toBenevolentUnion(TypeCombinator::union(new IntegerType(), new FloatType())); if (count($functionCall->getArgs()) < 1) { return $arrayType; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $isTrueType = $argType->isTrue(); $isFalseType = $argType->isFalse(); $compareTypes = $isTrueType->compareTo($isFalseType); if ($compareTypes === $isTrueType) { return $numberType; } if ($compareTypes === $isFalseType) { return $arrayType; } return TypeCombinator::union($arrayType, $numberType); } } getName() === '__construct' && $methodReflection->getDeclaringClass()->getName() === SimpleXMLElement::class; } public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) === 0) { return $methodReflection->getThrowType(); } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $constantStrings = $valueType->getConstantStrings(); $internalErrorsOld = libxml_use_internal_errors(\true); try { foreach ($constantStrings as $constantString) { try { new SimpleXMLElement($constantString->getValue()); } catch (\Exception $e) { // phpcs:ignore return $methodReflection->getThrowType(); } $valueType = TypeCombinator::remove($valueType, $constantString); } } finally { libxml_use_internal_errors($internalErrorsOld); } if (!$valueType instanceof NeverType) { return $methodReflection->getThrowType(); } return null; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_slice'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) < 2) { return null; } $arrayType = $scope->getType($args[0]->value); if ($arrayType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } $offsetType = $scope->getType($args[1]->value); $lengthType = isset($args[2]) ? $scope->getType($args[2]->value) : new NullType(); $preserveKeysType = isset($args[3]) ? $scope->getType($args[3]->value) : new ConstantBooleanType(\false); return $arrayType->sliceArray($offsetType, $lengthType, $preserveKeysType->isTrue()); } } getName(), ['sscanf', 'fscanf'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) !== 2) { return null; } $formatType = $scope->getType($args[1]->value); if (!$formatType instanceof ConstantStringType) { return null; } if (preg_match_all('/%(\\d*)(\\[[^\\]]+\\]|[cdeEfosux]{1})/', $formatType->getValue(), $matches) > 0) { $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); for ($i = 0; $i < count($matches[0]); $i++) { $length = $matches[1][$i]; $specifier = $matches[2][$i]; $type = new StringType(); if ($length !== '') { if ((int) $length > 1) { $type = new IntersectionType([$type, new AccessoryNonFalsyStringType()]); } else { $type = new IntersectionType([$type, new AccessoryNonEmptyStringType()]); } } if (in_array($specifier, ['d', 'o', 'u', 'x'], \true)) { $type = new IntegerType(); } if (in_array($specifier, ['e', 'E', 'f'], \true)) { $type = new FloatType(); } $type = TypeCombinator::addNull($type); $arrayBuilder->setOffsetValueType(new ConstantIntegerType($i), $type); } return TypeCombinator::addNull($arrayBuilder->getArray()); } return null; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_fill'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 3) { return null; } $numberType = $scope->getType($functionCall->getArgs()[1]->value); $isValidNumberType = IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($numberType); // check against negative-int, which is not allowed if ($isValidNumberType->no()) { if ($this->phpVersion->throwsValueErrorForInternalFunctions()) { return new NeverType(); } return new ConstantBooleanType(\false); } $startIndexType = $scope->getType($functionCall->getArgs()[0]->value); $valueType = $scope->getType($functionCall->getArgs()[2]->value); if ($startIndexType instanceof ConstantIntegerType && $numberType instanceof ConstantIntegerType && $numberType->getValue() <= self::MAX_SIZE_USE_CONSTANT_ARRAY) { $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); $nextIndex = $startIndexType->getValue(); for ($i = 0; $i < $numberType->getValue(); $i++) { $arrayBuilder->setOffsetValueType(new ConstantIntegerType($nextIndex), $valueType); if ($nextIndex < 0) { $nextIndex = 0; } else { $nextIndex++; } } return $arrayBuilder->getArray(); } $resultType = new ArrayType(new IntegerType(), $valueType); if ((new ConstantIntegerType(0))->isSuperTypeOf($startIndexType)->yes()) { $resultType = AccessoryArrayListType::intersectWith($resultType); } if (IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($numberType)->yes()) { $resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType()); } if (!$isValidNumberType->yes() && !$this->phpVersion->throwsValueErrorForInternalFunctions()) { $resultType = TypeCombinator::union($resultType, new ConstantBooleanType(\false)); } return $resultType; } } getName() === 'open'; } public function isStaticMethodSupported(MethodReflection $methodReflection) : bool { return $this->isMethodSupported($methodReflection); } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : Type { return new BooleanType(); } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : Type { return new UnionType([new ObjectType(self::XML_READER_CLASS), new ConstantBooleanType(\false)]); } } getName() === 'strrev'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $inputType = $scope->getType($args[0]->value); $constantStrings = $inputType->getConstantStrings(); if (count($constantStrings) > 0) { $resultTypes = []; foreach ($constantStrings as $constantString) { $resultTypes[] = new ConstantStringType(strrev($constantString->getValue())); } return TypeCombinator::union(...$resultTypes); } $accessoryTypes = []; if ($inputType->isNonFalsyString()->yes()) { $accessoryTypes[] = new AccessoryNonFalsyStringType(); } elseif ($inputType->isNonEmptyString()->yes()) { $accessoryTypes[] = new AccessoryNonEmptyStringType(); } if ($inputType->isLowercaseString()->yes()) { $accessoryTypes[] = new AccessoryLowercaseStringType(); } if ($inputType->isUppercaseString()->yes()) { $accessoryTypes[] = new AccessoryUppercaseStringType(); } if (count($accessoryTypes) > 0) { $accessoryTypes[] = new StringType(); return new IntersectionType($accessoryTypes); } return null; } } [1, 0], 'str_contains' => [0, 1], 'str_starts_with' => [0, 1], 'str_ends_with' => [0, 1], 'strpos' => [0, 1], 'strrpos' => [0, 1], 'stripos' => [0, 1], 'strripos' => [0, 1], 'strstr' => [0, 1], 'mb_strpos' => [0, 1], 'mb_strrpos' => [0, 1], 'mb_stripos' => [0, 1], 'mb_strripos' => [0, 1], 'mb_strstr' => [0, 1]]; /** * @var TypeSpecifier */ private $typeSpecifier; public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return array_key_exists(strtolower($functionReflection->getName()), self::STR_CONTAINING_FUNCTIONS) && $context->true(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $args = $node->getArgs(); if (count($args) >= 2) { [$hackstackArg, $needleArg] = self::STR_CONTAINING_FUNCTIONS[strtolower($functionReflection->getName())]; $haystackType = $scope->getType($args[$hackstackArg]->value); $needleType = $scope->getType($args[$needleArg]->value)->toString(); if ($needleType->isNonEmptyString()->yes() && $haystackType->isString()->yes()) { $accessories = [new StringType()]; if ($needleType->isNonFalsyString()->yes()) { $accessories[] = new AccessoryNonFalsyStringType(); } else { $accessories[] = new AccessoryNonEmptyStringType(); } if ($haystackType->isLiteralString()->yes()) { $accessories[] = new AccessoryLiteralStringType(); } if ($haystackType->isNumericString()->yes()) { $accessories[] = new AccessoryNumericStringType(); } return $this->typeSpecifier->create($args[$hackstackArg]->value, new IntersectionType($accessories), $context, \false, $scope, new BooleanAnd(new NotIdentical($args[$needleArg]->value, new String_('')), new FuncCall(new Name('FAUX_FUNCTION'), [new Arg($args[$needleArg]->value)]))); } } return new SpecifiedTypes(); } } getName(), ['get', 'remove'], \true); } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { $argsCount = count($methodCall->getArgs()); if ($argsCount > 1) { return null; } if ($argsCount === 0) { return null; } $mapType = $scope->getType($methodCall->var); if (!$mapType instanceof TypeWithClassName) { return null; } $mapAncestor = $mapType->getAncestorWithClassName('Ds\\Map'); if ($mapAncestor === null) { return null; } $mapAncestorClass = $mapAncestor->getClassReflection(); if ($mapAncestorClass === null) { return null; } $valueType = $mapAncestorClass->getActiveTemplateTypeMap()->getType('TValue'); if ($valueType === null) { return null; } return $valueType; } } regexShapeMatcher = $regexShapeMatcher; } public function isFunctionSupported(FunctionReflection $functionReflection, ParameterReflection $parameter) : bool { return $functionReflection->getName() === 'preg_replace_callback' && $parameter->getName() === 'callback'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, ParameterReflection $parameter, Scope $scope) : ?Type { $args = $functionCall->getArgs(); $patternArg = $args[0] ?? null; $flagsArg = $args[5] ?? null; if ($patternArg === null) { return null; } $flagsType = null; if ($flagsArg !== null) { $flagsType = $scope->getType($flagsArg->value); } $matchesType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createYes(), $scope); if ($matchesType === null) { return null; } return new ClosureType([new NativeParameterReflection($parameter->getName(), $parameter->isOptional(), $matchesType, $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue())], new StringType()); } } getName() === 'gettimeofday'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $arrayType = new ConstantArrayType([new ConstantStringType('sec'), new ConstantStringType('usec'), new ConstantStringType('minuteswest'), new ConstantStringType('dsttime')], [new IntegerType(), new IntegerType(), new IntegerType(), new IntegerType()]); $floatType = new FloatType(); if (!isset($functionCall->getArgs()[0])) { return $arrayType; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $isTrueType = $argType->isTrue(); $isFalseType = $argType->isFalse(); $compareTypes = $isTrueType->compareTo($isFalseType); if ($compareTypes === $isTrueType) { return $floatType; } if ($compareTypes === $isFalseType) { return $arrayType; } if ($argType instanceof MixedType) { return new BenevolentUnionType([$arrayType, $floatType]); } return new UnionType([$arrayType, $floatType]); } } getName(), ['trim', 'rtrim', 'ltrim'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $stringType = $scope->getType($args[0]->value); $accessory = []; if ($stringType->isLowercaseString()->yes()) { $accessory[] = new AccessoryLowercaseStringType(); } if ($stringType->isUppercaseString()->yes()) { $accessory[] = new AccessoryUppercaseStringType(); } if (count($accessory) > 0) { $accessory[] = new StringType(); return new IntersectionType($accessory); } return new StringType(); } } getName(), ['random_int', 'rand', 'mt_rand'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (in_array($functionReflection->getName(), ['rand', 'mt_rand'], \true) && count($functionCall->getArgs()) === 0) { return IntegerRangeType::fromInterval(0, null); } if (count($functionCall->getArgs()) < 2) { return null; } $minType = $scope->getType($functionCall->getArgs()[0]->value)->toInteger(); $maxType = $scope->getType($functionCall->getArgs()[1]->value)->toInteger(); return $this->createRange($minType, $maxType); } private function createRange(Type $minType, Type $maxType) : Type { $minValues = array_map(static function (Type $type) : ?int { if ($type instanceof IntegerRangeType) { return $type->getMin(); } if ($type instanceof ConstantIntegerType) { return $type->getValue(); } return null; }, $minType instanceof UnionType ? $minType->getTypes() : [$minType]); $maxValues = array_map(static function (Type $type) : ?int { if ($type instanceof IntegerRangeType) { return $type->getMax(); } if ($type instanceof ConstantIntegerType) { return $type->getValue(); } return null; }, $maxType instanceof UnionType ? $maxType->getTypes() : [$maxType]); assert(count($minValues) > 0); assert(count($maxValues) > 0); return IntegerRangeType::fromInterval(in_array(null, $minValues, \true) ? null : min($minValues), in_array(null, $maxValues, \true) ? null : max($maxValues)); } } getName() === 'SimpleXMLElement' || $classReflection->isSubclassOf('SimpleXMLElement'); } public function getProperty(ClassReflection $classReflection, string $propertyName) : PropertyReflection { return new SimpleXMLElementProperty($classReflection, new BenevolentUnionType([new ObjectType($classReflection->getName()), new NullType()])); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return in_array($functionReflection->getName(), ['bcdiv', 'bcmod', 'bcpowmod', 'bcsqrt'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { if ($functionReflection->getName() === 'bcsqrt') { return $this->getTypeForBcSqrt($functionCall, $scope); } if ($functionReflection->getName() === 'bcpowmod') { return $this->getTypeForBcPowMod($functionCall, $scope); } $stringAndNumericStringType = TypeCombinator::intersect(new StringType(), new AccessoryNumericStringType()); if (isset($functionCall->getArgs()[1]) === \false) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new NullType(); } if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { $defaultReturnType = $stringAndNumericStringType; } else { $defaultReturnType = new UnionType([$stringAndNumericStringType, new NullType()]); } $secondArgument = $scope->getType($functionCall->getArgs()[1]->value); $secondArgumentIsNumeric = $secondArgument instanceof ConstantScalarType && is_numeric($secondArgument->getValue()) || $secondArgument->isInteger()->yes(); if ($secondArgument instanceof ConstantScalarType && ($this->isZero($secondArgument->getValue()) || !$secondArgumentIsNumeric)) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new NullType(); } if (isset($functionCall->getArgs()[2]) === \false) { if ($secondArgument instanceof ConstantScalarType || $secondArgumentIsNumeric) { return $stringAndNumericStringType; } return $defaultReturnType; } $thirdArgument = $scope->getType($functionCall->getArgs()[2]->value); $thirdArgumentIsNumeric = \false; $thirdArgumentIsNegative = \false; if ($thirdArgument instanceof ConstantScalarType && is_numeric($thirdArgument->getValue())) { $thirdArgumentIsNumeric = \true; $thirdArgumentIsNegative = $thirdArgument->getValue() < 0; } elseif ($thirdArgument->isInteger()->yes()) { $thirdArgumentIsNumeric = \true; if (IntegerRangeType::fromInterval(null, -1)->isSuperTypeOf($thirdArgument)->yes()) { $thirdArgumentIsNegative = \true; } } if ($thirdArgument instanceof ConstantScalarType && !is_numeric($thirdArgument->getValue())) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new NullType(); } if ($this->phpVersion->throwsTypeErrorForInternalFunctions() && $thirdArgumentIsNegative) { return new NeverType(); } if (($secondArgument instanceof ConstantScalarType || $secondArgumentIsNumeric) && $thirdArgumentIsNumeric) { return $stringAndNumericStringType; } return $defaultReturnType; } /** * bcsqrt * https://www.php.net/manual/en/function.bcsqrt.php * > Returns the square root as a string, or NULL if operand is negative. * */ private function getTypeForBcSqrt(FuncCall $functionCall, Scope $scope) : Type { $stringAndNumericStringType = TypeCombinator::intersect(new StringType(), new AccessoryNumericStringType()); if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { $defaultReturnType = $stringAndNumericStringType; } else { $defaultReturnType = new UnionType([$stringAndNumericStringType, new NullType()]); } if (isset($functionCall->getArgs()[0]) === \false) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return $defaultReturnType; } $firstArgument = $scope->getType($functionCall->getArgs()[0]->value); $firstArgumentIsPositive = $firstArgument instanceof ConstantScalarType && is_numeric($firstArgument->getValue()) && $firstArgument->getValue() >= 0; $firstArgumentIsNegative = $firstArgument instanceof ConstantScalarType && is_numeric($firstArgument->getValue()) && $firstArgument->getValue() < 0; if ($firstArgument instanceof UnaryMinus || $firstArgumentIsNegative) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new NullType(); } if (isset($functionCall->getArgs()[1]) === \false) { if ($firstArgumentIsPositive) { return $stringAndNumericStringType; } return $defaultReturnType; } $secondArgument = $scope->getType($functionCall->getArgs()[1]->value); $secondArgumentIsValid = $secondArgument instanceof ConstantScalarType && is_numeric($secondArgument->getValue()) && !$this->isZero($secondArgument->getValue()); $secondArgumentIsNonNumeric = $secondArgument instanceof ConstantScalarType && !is_numeric($secondArgument->getValue()); $secondArgumentIsNegative = $secondArgument instanceof ConstantScalarType && is_numeric($secondArgument->getValue()) && $secondArgument->getValue() < 0; if ($secondArgumentIsNonNumeric) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new NullType(); } if ($secondArgument instanceof UnaryMinus || $secondArgumentIsNegative) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } } if ($firstArgumentIsPositive && $secondArgumentIsValid) { return $stringAndNumericStringType; } return $defaultReturnType; } /** * bcpowmod() * https://www.php.net/manual/en/function.bcpowmod.php * > Returns the result as a string, or FALSE if modulus is 0 or exponent is negative. */ private function getTypeForBcPowMod(FuncCall $functionCall, Scope $scope) : Type { if ($this->phpVersion->throwsTypeErrorForInternalFunctions() && isset($functionCall->getArgs()[0]) === \false) { return new NeverType(); } $stringAndNumericStringType = TypeCombinator::intersect(new StringType(), new AccessoryNumericStringType()); if (isset($functionCall->getArgs()[1]) === \false) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new UnionType([$stringAndNumericStringType, new ConstantBooleanType(\false)]); } $exponent = $scope->getType($functionCall->getArgs()[1]->value); // Expontent is non numeric if ($this->phpVersion->throwsTypeErrorForInternalFunctions() && $exponent instanceof ConstantScalarType && !is_numeric($exponent->getValue())) { return new NeverType(); } $exponentIsNegative = IntegerRangeType::fromInterval(null, 0)->isSuperTypeOf($exponent)->yes(); if ($exponent instanceof ConstantScalarType) { $exponentIsNegative = is_numeric($exponent->getValue()) && $exponent->getValue() < 0; } if ($exponentIsNegative) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new ConstantBooleanType(\false); } if (isset($functionCall->getArgs()[2])) { $modulus = $scope->getType($functionCall->getArgs()[2]->value); $modulusIsZero = $modulus instanceof ConstantScalarType && $this->isZero($modulus->getValue()); $modulusIsNonNumeric = $modulus instanceof ConstantScalarType && !is_numeric($modulus->getValue()); if ($modulusIsZero || $modulusIsNonNumeric) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new ConstantBooleanType(\false); } if ($modulus instanceof ConstantScalarType) { return $stringAndNumericStringType; } } else { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } } if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return $stringAndNumericStringType; } return new UnionType([$stringAndNumericStringType, new ConstantBooleanType(\false)]); } /** * Utility to help us determine if value is zero. Handles cases where we pass "0.000" too. * * @param mixed $value */ private function isZero($value) : bool { if (is_numeric($value) === \false) { return \false; } if ($value > 0 || $value < 0) { return \false; } return \true; } } getName() === 'array_key_last'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new NullType(); } $keyType = $argType->getLastIterableKeyType(); if ($iterableAtLeastOnce->yes()) { return $keyType; } return TypeCombinator::union($keyType, new NullType()); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_chunk'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } $arrayType = $scope->getType($functionCall->getArgs()[0]->value); if ($arrayType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } $lengthType = $scope->getType($functionCall->getArgs()[1]->value); $negativeOrZero = IntegerRangeType::fromInterval(null, 0); if ($negativeOrZero->isSuperTypeOf($lengthType)->yes()) { return $this->phpVersion->throwsValueErrorForInternalFunctions() ? new NeverType() : new NullType(); } $preserveKeysType = isset($functionCall->getArgs()[2]) ? $scope->getType($functionCall->getArgs()[2]->value) : new ConstantBooleanType(\false); return $arrayType->chunkArray($lengthType, $preserveKeysType->isTrue()); } } getName(), ['sprintf', 'vsprintf'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) === 0) { return null; } $constantType = $this->getConstantType($args, $functionReflection, $scope); if ($constantType !== null) { return $constantType; } $formatType = $scope->getType($args[0]->value); $formatStrings = $formatType->getConstantStrings(); $isLowercase = $formatType->isLowercaseString()->yes() && $this->allValuesSatisfies($functionReflection, $scope, $args, static function (Type $type) : bool { return $type->toString()->isLowercaseString()->yes(); }); $singlePlaceholderEarlyReturn = []; $allPatternsNonEmpty = count($formatStrings) !== 0; $allPatternsNonFalsy = count($formatStrings) !== 0; foreach ($formatStrings as $constantString) { $constantParts = $this->getFormatConstantParts($constantString->getValue(), $functionReflection, $functionCall, $scope); if ($constantParts !== null) { if ($constantParts->isNonFalsyString()->yes()) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf // keep all bool flags as is } elseif ($constantParts->isNonEmptyString()->yes()) { $allPatternsNonFalsy = \false; } else { $allPatternsNonEmpty = \false; $allPatternsNonFalsy = \false; } } else { $allPatternsNonEmpty = \false; $allPatternsNonFalsy = \false; } if (is_array($singlePlaceholderEarlyReturn) && preg_match('/^%(?P[0-9]*\\$)?(?P[0-9]*)\\.?[0-9]*(?P[sbdeEfFgGhHouxX])$/', $constantString->getValue(), $matches) === 1) { if ($matches['argnum'] !== '') { // invalid positional argument if ($matches['argnum'] === '0$') { return null; } $checkArg = intval(substr($matches['argnum'], 0, -1)); } else { $checkArg = 1; } $checkArgType = $this->getValueType($functionReflection, $scope, $args, $checkArg); if ($checkArgType === null) { return null; } // if the format string is just a placeholder and specified an argument // of stringy type, then the return value will be of the same type if ($matches['specifier'] === 's' && ($checkArgType->isString()->yes() || $checkArgType->isInteger()->yes())) { if ($checkArgType instanceof IntegerRangeType) { $constArgTypes = $checkArgType->getFiniteTypes(); } else { $constArgTypes = $checkArgType->getConstantScalarTypes(); } if ($constArgTypes !== []) { $printfArgs = array_fill(0, count($args) - 1, ''); foreach ($constArgTypes as $constArgType) { $printfArgs[$checkArg - 1] = $constArgType->getValue(); try { $singlePlaceholderEarlyReturn[] = new ConstantStringType(@sprintf($constantString->getValue(), ...$printfArgs)); } catch (Throwable $e) { continue 2; } } continue; } $singlePlaceholderEarlyReturn[] = $checkArgType->toString(); } elseif ($matches['specifier'] !== 's') { $singlePlaceholderEarlyReturn[] = $this->getStringReturnType(new AccessoryNumericStringType(), $isLowercase); } continue; } $singlePlaceholderEarlyReturn = null; } if (is_array($singlePlaceholderEarlyReturn) && count($singlePlaceholderEarlyReturn) > 0) { return TypeCombinator::union(...$singlePlaceholderEarlyReturn); } if ($allPatternsNonFalsy) { return $this->getStringReturnType(new AccessoryNonFalsyStringType(), $isLowercase); } $isNonEmpty = $allPatternsNonEmpty; if (!$isNonEmpty && $formatType->isNonEmptyString()->yes()) { $isNonEmpty = $this->allValuesSatisfies($functionReflection, $scope, $args, static function (Type $type) : bool { return $type->toString()->isNonEmptyString()->yes(); }); } if ($isNonEmpty) { return $this->getStringReturnType(new AccessoryNonEmptyStringType(), $isLowercase); } return $this->getStringReturnType(null, $isLowercase); } /** * @param array $args * @param callable(Type): bool $cb */ private function allValuesSatisfies(FunctionReflection $functionReflection, Scope $scope, array $args, callable $cb) : bool { if ($functionReflection->getName() === 'sprintf' && count($args) >= 2) { foreach ($args as $key => $arg) { if ($key === 0) { continue; } if (!$cb($scope->getType($arg->value))) { return \false; } } return \true; } if ($functionReflection->getName() === 'vsprintf' && count($args) >= 2) { return $cb($scope->getType($args[1]->value)->getIterableValueType()); } return \false; } /** * @param Arg[] $args */ private function getValueType(FunctionReflection $functionReflection, Scope $scope, array $args, int $argNumber) : ?Type { if ($functionReflection->getName() === 'sprintf') { // constant string specifies a numbered argument that does not exist if (!array_key_exists($argNumber, $args)) { return null; } return $scope->getType($args[$argNumber]->value); } if ($functionReflection->getName() === 'vsprintf') { if (!array_key_exists(1, $args)) { return null; } $valuesType = $scope->getType($args[1]->value); $resultTypes = []; $valuesConstantArrays = $valuesType->getConstantArrays(); foreach ($valuesConstantArrays as $valuesConstantArray) { // vsprintf does not care about the keys of the array, only the order $types = array_values($valuesConstantArray->getValueTypes()); if (!array_key_exists($argNumber - 1, $types)) { return null; } $resultTypes[] = $types[$argNumber - 1]; } if (count($resultTypes) === 0) { return $valuesType->getIterableValueType(); } return TypeCombinator::union(...$resultTypes); } return null; } /** * Detect constant strings in the format which neither depend on placeholders nor on given value arguments. */ private function getFormatConstantParts(string $format, FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?ConstantStringType { $args = $functionCall->getArgs(); if ($functionReflection->getName() === 'sprintf') { $valuesCount = count($args) - 1; } elseif ($functionReflection->getName() === 'vsprintf' && count($args) >= 2) { $arraySize = $scope->getType($args[1]->value)->getArraySize(); if (!$arraySize instanceof ConstantIntegerType) { return null; } $valuesCount = $arraySize->getValue(); } else { return null; } if ($valuesCount <= 0) { return null; } $dummyValues = array_fill(0, $valuesCount, ''); try { $formatted = @vsprintf($format, $dummyValues); if ($formatted === \false) { // @phpstan-ignore identical.alwaysFalse (PHP7.2 compat) return null; } return new ConstantStringType($formatted); } catch (Throwable $e) { return null; } } /** * @param Arg[] $args */ private function getConstantType(array $args, FunctionReflection $functionReflection, Scope $scope) : ?Type { $values = []; $combinationsCount = 1; foreach ($args as $arg) { if ($arg->unpack) { return null; } $argType = $scope->getType($arg->value); $constantScalarValues = $argType->getConstantScalarValues(); if (count($constantScalarValues) === 0) { if ($argType instanceof IntegerRangeType) { foreach ($argType->getFiniteTypes() as $finiteType) { $constantScalarValues[] = $finiteType->getValue(); } } } if (count($constantScalarValues) === 0) { return null; } $values[] = $constantScalarValues; $combinationsCount *= count($constantScalarValues); } if ($combinationsCount > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return null; } $combinations = CombinationsHelper::combinations($values); $returnTypes = []; foreach ($combinations as $combination) { $format = array_shift($combination); if (!is_string($format)) { return null; } try { if ($functionReflection->getName() === 'sprintf') { $returnTypes[] = $scope->getTypeFromValue(@sprintf($format, ...$combination)); } else { $returnTypes[] = $scope->getTypeFromValue(@vsprintf($format, $combination)); } } catch (Throwable $e) { return null; } } if (count($returnTypes) > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return null; } return TypeCombinator::union(...$returnTypes); } private function getStringReturnType(?AccessoryType $accessoryType, bool $isLowercase) : Type { $accessoryTypes = []; if ($accessoryType !== null) { $accessoryTypes[] = $accessoryType; } if ($isLowercase) { $accessoryTypes[] = new AccessoryLowercaseStringType(); } if (count($accessoryTypes) === 0) { return new StringType(); } $accessoryTypes[] = new StringType(); return new IntersectionType($accessoryTypes); } } getName() === 'current'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new ConstantBooleanType(\false); } $keyType = $argType->getIterableValueType(); if ($iterableAtLeastOnce->yes()) { return $keyType; } return TypeCombinator::union($keyType, new ConstantBooleanType(\false)); } } getName() === 'strtok'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) !== 2) { return null; } $delimiterType = $scope->getType($functionCall->getArgs()[0]->value); $isEmptyString = (new ConstantStringType(''))->isSuperTypeOf($delimiterType); if ($isEmptyString->yes()) { return new ConstantBooleanType(\false); } if ($isEmptyString->no()) { return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]); } return null; } } phpVersion = $phpVersion; } public function isStaticMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === '__construct' && $methodReflection->getDeclaringClass()->getName() === DateTimeZone::class; } public function getThrowTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) === 0) { return null; } $valueType = $scope->getType($methodCall->getArgs()[0]->value); $constantStrings = $valueType->getConstantStrings(); foreach ($constantStrings as $constantString) { try { new DateTimeZone($constantString->getValue()); } catch (\Exception $e) { // phpcs:ignore return $this->exceptionType(); } $valueType = TypeCombinator::remove($valueType, $constantString); } if (!$valueType instanceof NeverType) { return $this->exceptionType(); } return null; } private function exceptionType() : Type { if ($this->phpVersion->hasDateTimeExceptions()) { return new ObjectType('DateInvalidTimeZoneException'); } return new ObjectType('Exception'); } } typeSpecifier = $typeSpecifier; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return strtolower($functionReflection->getName()) === 'in_array' && !$context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $argsCount = count($node->getArgs()); if ($argsCount < 2) { return new SpecifiedTypes(); } $isStrictComparison = \false; if ($argsCount >= 3) { $strictNodeType = $scope->getType($node->getArgs()[2]->value); $isStrictComparison = $strictNodeType->isTrue()->yes(); } $needleExpr = $node->getArgs()[0]->value; $arrayExpr = $node->getArgs()[1]->value; $needleType = $scope->getType($needleExpr); $arrayType = $scope->getType($arrayExpr); $arrayValueType = $arrayType->getIterableValueType(); $isStrictComparison = $isStrictComparison || $needleType->isEnum()->yes() || $arrayValueType->isEnum()->yes() || $needleType->isString()->yes() && $arrayValueType->isString()->yes() || $needleType->isInteger()->yes() && $arrayValueType->isInteger()->yes() || $needleType->isFloat()->yes() && $arrayValueType->isFloat()->yes() || $needleType->isBoolean()->yes() && $arrayValueType->isBoolean()->yes(); if ($arrayExpr instanceof Array_) { $types = null; foreach ($arrayExpr->items as $item) { if ($item === null) { continue; } if ($item->unpack) { $types = null; break; } if ($isStrictComparison) { $itemTypes = $this->typeSpecifier->resolveIdentical(new Identical($needleExpr, $item->value), $scope, $context, null); } else { $itemTypes = $this->typeSpecifier->resolveEqual(new Equal($needleExpr, $item->value), $scope, $context, null); } if ($types === null) { $types = $itemTypes; continue; } $types = $context->true() ? $types->normalize($scope)->intersectWith($itemTypes->normalize($scope)) : $types->unionWith($itemTypes); } if ($types !== null) { return $types; } } if (!$isStrictComparison) { if ($context->true() && $arrayType->isArray()->yes() && $arrayType->getIterableValueType()->isSuperTypeOf($needleType)->yes()) { return $this->typeSpecifier->create($node->getArgs()[1]->value, TypeCombinator::intersect($arrayType, new NonEmptyArrayType()), $context, \false, $scope); } return new SpecifiedTypes(); } $specifiedTypes = new SpecifiedTypes(); if ($context->true() || $context->false() && (count(TypeUtils::getConstantScalars($arrayValueType)) > 0 || count(TypeUtils::getEnumCaseObjects($arrayValueType)) > 0)) { $specifiedTypes = $this->typeSpecifier->create($needleExpr, $arrayValueType, $context, \false, $scope); if ($needleExpr instanceof AlwaysRememberedExpr) { $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create($needleExpr->getExpr(), $arrayValueType, $context, \false, $scope)); } } if ($context->true() || $context->false() && (count(TypeUtils::getConstantScalars($needleType)) === 1 || count(TypeUtils::getEnumCaseObjects($needleType)) === 1)) { if ($context->true()) { $arrayValueType = TypeCombinator::union($arrayValueType, $needleType); } else { $arrayValueType = TypeCombinator::remove($arrayValueType, $needleType); } $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create($node->getArgs()[1]->value, new ArrayType(new MixedType(), $arrayValueType), TypeSpecifierContext::createTrue(), \false, $scope)); } if ($context->true() && $arrayType->isArray()->yes()) { $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create($node->getArgs()[1]->value, TypeCombinator::intersect($arrayType, new NonEmptyArrayType()), $context, \false, $scope)); } return $specifiedTypes; } } 2, 'preg_replace_callback' => 2, 'preg_replace_callback_array' => 1, 'str_replace' => 2, 'str_ireplace' => 2, 'substr_replace' => 0, 'strtr' => 0]; private const FUNCTIONS_REPLACE_POSITION = ['preg_replace' => 1, 'str_replace' => 1, 'str_ireplace' => 1, 'substr_replace' => 1, 'strtr' => 2]; public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return array_key_exists($functionReflection->getName(), self::FUNCTIONS_SUBJECT_POSITION); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $type = $this->getPreliminarilyResolvedTypeFromFunctionCall($functionReflection, $functionCall, $scope); if ($this->canReturnNull($functionReflection, $functionCall, $scope)) { $type = TypeCombinator::addNull($type); } return $type; } private function getPreliminarilyResolvedTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $subjectArgumentType = $this->getSubjectType($functionReflection, $functionCall, $scope); $defaultReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants())->getReturnType(); if ($subjectArgumentType === null) { return $defaultReturnType; } if ($subjectArgumentType instanceof MixedType) { return TypeUtils::toBenevolentUnion($defaultReturnType); } if (array_key_exists($functionReflection->getName(), self::FUNCTIONS_REPLACE_POSITION)) { $replaceArgumentPosition = self::FUNCTIONS_REPLACE_POSITION[$functionReflection->getName()]; if (count($functionCall->getArgs()) > $replaceArgumentPosition) { $replaceArgumentType = $scope->getType($functionCall->getArgs()[$replaceArgumentPosition]->value); $accessories = []; if ($subjectArgumentType->isNonFalsyString()->yes() && $replaceArgumentType->isNonFalsyString()->yes()) { $accessories[] = new AccessoryNonFalsyStringType(); } elseif ($subjectArgumentType->isNonEmptyString()->yes() && $replaceArgumentType->isNonEmptyString()->yes()) { $accessories[] = new AccessoryNonEmptyStringType(); } if ($subjectArgumentType->isLowercaseString()->yes() && $replaceArgumentType->isLowercaseString()->yes()) { $accessories[] = new AccessoryLowercaseStringType(); } if ($subjectArgumentType->isUppercaseString()->yes() && $replaceArgumentType->isUppercaseString()->yes()) { $accessories[] = new AccessoryUppercaseStringType(); } if (count($accessories) > 0) { $accessories[] = new StringType(); return new IntersectionType($accessories); } } } $isStringSuperType = $subjectArgumentType->isString(); $isArraySuperType = $subjectArgumentType->isArray(); $compareSuperTypes = $isStringSuperType->compareTo($isArraySuperType); if ($compareSuperTypes === $isStringSuperType) { return new StringType(); } elseif ($compareSuperTypes === $isArraySuperType) { $subjectArrays = $subjectArgumentType->getArrays(); if (count($subjectArrays) > 0) { $result = []; foreach ($subjectArrays as $arrayType) { $constantArrays = $arrayType->getConstantArrays(); if ($constantArrays !== [] && in_array($functionReflection->getName(), ['preg_replace', 'preg_replace_callback', 'preg_replace_callback_array'], \true)) { foreach ($constantArrays as $constantArray) { $generalizedArray = $constantArray->generalizeValues(); $builder = ConstantArrayTypeBuilder::createEmpty(); // turn all keys optional foreach ($constantArray->getKeyTypes() as $keyType) { $builder->setOffsetValueType($keyType, $generalizedArray->getOffsetValueType($keyType), \true); } $result[] = $builder->getArray(); } continue; } $result[] = $arrayType->generalizeValues(); } return TypeCombinator::union(...$result); } return $subjectArgumentType; } return $defaultReturnType; } private function getSubjectType(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $argumentPosition = self::FUNCTIONS_SUBJECT_POSITION[$functionReflection->getName()]; if (count($functionCall->getArgs()) <= $argumentPosition) { return null; } return $scope->getType($functionCall->getArgs()[$argumentPosition]->value); } private function canReturnNull(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : bool { if (in_array($functionReflection->getName(), ['preg_replace', 'preg_replace_callback', 'preg_replace_callback_array'], \true) && count($functionCall->getArgs()) > 0) { $subjectArgumentType = $this->getSubjectType($functionReflection, $functionCall, $scope); if ($subjectArgumentType !== null && $subjectArgumentType->isArray()->yes()) { return \false; } } $possibleTypes = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants())->getReturnType(); // resolve conditional return types $possibleTypes = TypeUtils::resolveLateResolvableTypes($possibleTypes); return TypeCombinator::containsNull($possibleTypes); } } |null */ private $filterTypeMap = null; /** @var array>|null */ private $filterTypeOptions = null; /** * @var ?Type */ private $supportedFilterInputTypes = null; public function __construct(ReflectionProvider $reflectionProvider, PhpVersion $phpVersion) { $this->reflectionProvider = $reflectionProvider; $this->phpVersion = $phpVersion; $this->flagsString = new ConstantStringType('flags'); } public function getOffsetValueType(Type $inputType, Type $offsetType, ?Type $filterType, ?Type $flagsType) : Type { $inexistentOffsetType = $this->hasFlag($this->getConstant('FILTER_NULL_ON_FAILURE'), $flagsType) ? new ConstantBooleanType(\false) : new NullType(); $hasOffsetValueType = $inputType->hasOffsetValueType($offsetType); if ($hasOffsetValueType->no()) { return $inexistentOffsetType; } $filteredType = $this->getType($inputType->getOffsetValueType($offsetType), $filterType, $flagsType); return $hasOffsetValueType->maybe() ? TypeCombinator::union($filteredType, $inexistentOffsetType) : $filteredType; } public function getInputType(Type $typeType, Type $varNameType, ?Type $filterType, ?Type $flagsType) : Type { $this->supportedFilterInputTypes = $this->supportedFilterInputTypes ?? TypeCombinator::union($this->reflectionProvider->getConstant(new Node\Name('INPUT_GET'), null)->getValueType(), $this->reflectionProvider->getConstant(new Node\Name('INPUT_POST'), null)->getValueType(), $this->reflectionProvider->getConstant(new Node\Name('INPUT_COOKIE'), null)->getValueType(), $this->reflectionProvider->getConstant(new Node\Name('INPUT_SERVER'), null)->getValueType(), $this->reflectionProvider->getConstant(new Node\Name('INPUT_ENV'), null)->getValueType()); if (!$typeType->isInteger()->yes() || $this->supportedFilterInputTypes->isSuperTypeOf($typeType)->no()) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } // Using a null as input mimics pre PHP 8 behaviour where filter_input // would return the same as if the offset does not exist $inputType = new NullType(); } else { // Pragmatical solution since global expressions are not passed through the scope for performance reasons // See https://github.com/phpstan/phpstan-src/pull/2012 for details $inputType = new ArrayType(new StringType(), new MixedType()); } return $this->getOffsetValueType($inputType, $varNameType, $filterType, $flagsType); } public function getType(Type $inputType, ?Type $filterType, ?Type $flagsType) : Type { $mixedType = new MixedType(); if ($filterType === null) { $filterValue = $this->getConstant('FILTER_DEFAULT'); } else { if (!$filterType instanceof ConstantIntegerType) { return $mixedType; } $filterValue = $filterType->getValue(); } if ($flagsType === null) { $flagsType = new ConstantIntegerType(0); } $hasOptions = $this->hasOptions($flagsType); $options = $hasOptions->yes() ? $this->getOptions($flagsType, $filterValue) : []; $defaultType = $options['default'] ?? ($this->hasFlag($this->getConstant('FILTER_NULL_ON_FAILURE'), $flagsType) ? new NullType() : new ConstantBooleanType(\false)); $inputIsArray = $inputType->isArray(); $hasRequireArrayFlag = $this->hasFlag($this->getConstant('FILTER_REQUIRE_ARRAY'), $flagsType); if ($inputIsArray->no() && $hasRequireArrayFlag) { return $defaultType; } $hasForceArrayFlag = $this->hasFlag($this->getConstant('FILTER_FORCE_ARRAY'), $flagsType); if ($inputIsArray->yes() && ($hasRequireArrayFlag || $hasForceArrayFlag)) { $inputArrayKeyType = $inputType->getIterableKeyType(); $inputType = $inputType->getIterableValueType(); } if ($inputType->isScalar()->no() && $inputType->isNull()->no()) { return $defaultType; } $exactType = $this->determineExactType($inputType, $filterValue, $defaultType, $flagsType); $type = $exactType ?? $this->getFilterTypeMap()[$filterValue] ?? $mixedType; $type = $this->applyRangeOptions($type, $options, $defaultType); if ($inputType->isNonEmptyString()->yes() && $type->isString()->yes() && !$this->canStringBeSanitized($filterValue, $flagsType)) { $accessory = new AccessoryNonEmptyStringType(); if ($inputType->isNonFalsyString()->yes()) { $accessory = new AccessoryNonFalsyStringType(); } $type = TypeCombinator::intersect($type, $accessory); } if ($hasRequireArrayFlag) { $type = new ArrayType($inputArrayKeyType ?? $mixedType, $type); } if ($exactType === null || $hasOptions->maybe() || !$inputType->equals($type) && $inputType->isSuperTypeOf($type)->yes()) { if ($defaultType->isSuperTypeOf($type)->no()) { $type = TypeCombinator::union($type, $defaultType); } } if (!$hasRequireArrayFlag && $hasForceArrayFlag) { return new ArrayType($inputArrayKeyType ?? $mixedType, $type); } return $type; } /** * @return array */ private function getFilterTypeMap() : array { if ($this->filterTypeMap !== null) { return $this->filterTypeMap; } $booleanType = new BooleanType(); $floatType = new FloatType(); $intType = new IntegerType(); $stringType = new StringType(); $nonFalsyStringType = TypeCombinator::intersect($stringType, new AccessoryNonFalsyStringType()); $this->filterTypeMap = [$this->getConstant('FILTER_UNSAFE_RAW') => $stringType, $this->getConstant('FILTER_SANITIZE_EMAIL') => $stringType, $this->getConstant('FILTER_SANITIZE_ENCODED') => $stringType, $this->getConstant('FILTER_SANITIZE_NUMBER_FLOAT') => $stringType, $this->getConstant('FILTER_SANITIZE_NUMBER_INT') => $stringType, $this->getConstant('FILTER_SANITIZE_SPECIAL_CHARS') => $stringType, $this->getConstant('FILTER_SANITIZE_STRING') => $stringType, $this->getConstant('FILTER_SANITIZE_URL') => $stringType, $this->getConstant('FILTER_VALIDATE_BOOLEAN') => $booleanType, $this->getConstant('FILTER_VALIDATE_DOMAIN') => $stringType, $this->getConstant('FILTER_VALIDATE_EMAIL') => $nonFalsyStringType, $this->getConstant('FILTER_VALIDATE_FLOAT') => $floatType, $this->getConstant('FILTER_VALIDATE_INT') => $intType, $this->getConstant('FILTER_VALIDATE_IP') => $nonFalsyStringType, $this->getConstant('FILTER_VALIDATE_MAC') => $nonFalsyStringType, $this->getConstant('FILTER_VALIDATE_REGEXP') => $stringType, $this->getConstant('FILTER_VALIDATE_URL') => $nonFalsyStringType]; if ($this->reflectionProvider->hasConstant(new Node\Name('FILTER_SANITIZE_MAGIC_QUOTES'), null)) { $this->filterTypeMap[$this->getConstant('FILTER_SANITIZE_MAGIC_QUOTES')] = $stringType; } if ($this->reflectionProvider->hasConstant(new Node\Name('FILTER_SANITIZE_ADD_SLASHES'), null)) { $this->filterTypeMap[$this->getConstant('FILTER_SANITIZE_ADD_SLASHES')] = $stringType; } return $this->filterTypeMap; } /** * @return array> */ private function getFilterTypeOptions() : array { if ($this->filterTypeOptions !== null) { return $this->filterTypeOptions; } $this->filterTypeOptions = [$this->getConstant('FILTER_VALIDATE_INT') => ['min_range', 'max_range']]; return $this->filterTypeOptions; } /** * @param non-empty-string $constantName */ private function getConstant(string $constantName) : int { $constant = $this->reflectionProvider->getConstant(new Node\Name($constantName), null); $valueType = $constant->getValueType(); if (!$valueType instanceof ConstantIntegerType) { throw new ShouldNotHappenException(sprintf('Constant %s does not have integer type.', $constantName)); } return $valueType->getValue(); } private function determineExactType(Type $in, int $filterValue, Type $defaultType, ?Type $flagsType) : ?Type { if ($filterValue === $this->getConstant('FILTER_VALIDATE_BOOLEAN')) { if ($in->isBoolean()->yes()) { return $in; } if ($in->isNull()->yes()) { return $defaultType; } } if ($filterValue === $this->getConstant('FILTER_VALIDATE_FLOAT')) { if ($in->isFloat()->yes()) { return $in; } if ($in->isInteger()->yes()) { return $in->toFloat(); } if ($in->isTrue()->yes()) { return new ConstantFloatType(1); } if ($in->isFalse()->yes() || $in->isNull()->yes()) { return $defaultType; } } if ($filterValue === $this->getConstant('FILTER_VALIDATE_INT')) { if ($in->isInteger()->yes()) { return $in; } if ($in->isTrue()->yes()) { return new ConstantIntegerType(1); } if ($in->isFalse()->yes() || $in->isNull()->yes()) { return $defaultType; } if ($in instanceof ConstantFloatType) { return $in->getValue() - (int) $in->getValue() === 0.0 ? $in->toInteger() : $defaultType; } if ($in instanceof ConstantStringType) { $value = $in->getValue(); $allowOctal = $this->hasFlag($this->getConstant('FILTER_FLAG_ALLOW_OCTAL'), $flagsType); $allowHex = $this->hasFlag($this->getConstant('FILTER_FLAG_ALLOW_HEX'), $flagsType); if ($allowOctal && preg_match('/\\A0[oO][0-7]+\\z/', $value) === 1) { $octalValue = octdec($value); return is_int($octalValue) ? new ConstantIntegerType($octalValue) : $defaultType; } if ($allowHex && preg_match('/\\A0[xX][0-9A-Fa-f]+\\z/', $value) === 1) { $hexValue = hexdec($value); return is_int($hexValue) ? new ConstantIntegerType($hexValue) : $defaultType; } return preg_match('/\\A[+-]?(?:0|[1-9][0-9]*)\\z/', $value) === 1 ? $in->toInteger() : $defaultType; } } if ($filterValue === $this->getConstant('FILTER_DEFAULT')) { if (!$this->canStringBeSanitized($filterValue, $flagsType) && $in->isString()->yes()) { return $in; } if ($in->isBoolean()->yes() || $in->isFloat()->yes() || $in->isInteger()->yes() || $in->isNull()->yes()) { return $in->toString(); } } return null; } /** @param array $typeOptions */ private function applyRangeOptions(Type $type, array $typeOptions, Type $defaultType) : Type { if (!$type->isInteger()->yes()) { return $type; } $range = []; if (isset($typeOptions['min_range'])) { if ($typeOptions['min_range'] instanceof ConstantScalarType) { $range['min'] = (int) $typeOptions['min_range']->getValue(); } elseif ($typeOptions['min_range'] instanceof IntegerRangeType) { $range['min'] = $typeOptions['min_range']->getMin(); } else { $range['min'] = null; } } if (isset($typeOptions['max_range'])) { if ($typeOptions['max_range'] instanceof ConstantScalarType) { $range['max'] = (int) $typeOptions['max_range']->getValue(); } elseif ($typeOptions['max_range'] instanceof IntegerRangeType) { $range['max'] = $typeOptions['max_range']->getMax(); } else { $range['max'] = null; } } if (array_key_exists('min', $range) || array_key_exists('max', $range)) { $min = $range['min'] ?? null; $max = $range['max'] ?? null; $rangeType = IntegerRangeType::fromInterval($min, $max); $rangeTypeIsSuperType = $rangeType->isSuperTypeOf($type); if ($rangeTypeIsSuperType->no()) { // e.g. if 9 is filtered with a range of int<17, 19> return $defaultType; } if ($rangeTypeIsSuperType->yes() && !$rangeType->equals($type)) { // e.g. if 18 or int<18, 19> are filtered with a range of int<17, 19> return $type; } // Open ranges on either side means that the input is potentially not part of the range return $min === null || $max === null ? TypeCombinator::union($rangeType, $defaultType) : $rangeType; } return $type; } private function hasOptions(Type $flagsType) : TrinaryLogic { return $flagsType->isArray()->and($flagsType->hasOffsetValueType(new ConstantStringType('options'))); } /** @return array */ private function getOptions(Type $flagsType, int $filterValue) : array { $options = []; $optionsType = $flagsType->getOffsetValueType(new ConstantStringType('options')); if (!$optionsType->isConstantArray()->yes()) { return $options; } $optionNames = array_merge(['default'], $this->getFilterTypeOptions()[$filterValue] ?? []); foreach ($optionNames as $optionName) { $optionalNameType = new ConstantStringType($optionName); if (!$optionsType->hasOffsetValueType($optionalNameType)->yes()) { $options[$optionName] = null; continue; } $options[$optionName] = $optionsType->getOffsetValueType($optionalNameType); } return $options; } private function hasFlag(int $flag, ?Type $flagsType) : bool { if ($flagsType === null) { return \false; } $type = $this->getFlagsValue($flagsType); return $type instanceof ConstantIntegerType && ($type->getValue() & $flag) === $flag; } private function getFlagsValue(Type $exprType) : Type { if (!$exprType->isConstantArray()->yes()) { return $exprType; } return $exprType->getOffsetValueType($this->flagsString); } private function canStringBeSanitized(int $filterValue, ?Type $flagsType) : bool { // If it is a validation filter, the string will not be changed if (($filterValue & self::VALIDATION_FILTER_BITMASK) !== 0) { return \false; } // FILTER_DEFAULT will not sanitize, unless it has FILTER_FLAG_STRIP_LOW, // FILTER_FLAG_STRIP_HIGH, or FILTER_FLAG_STRIP_BACKTICK if ($filterValue === $this->getConstant('FILTER_DEFAULT')) { return $this->hasFlag($this->getConstant('FILTER_FLAG_STRIP_LOW'), $flagsType) || $this->hasFlag($this->getConstant('FILTER_FLAG_STRIP_HIGH'), $flagsType) || $this->hasFlag($this->getConstant('FILTER_FLAG_STRIP_BACKTICK'), $flagsType); } return \true; } } reflectionProvider = $reflectionProvider; } public function getType(Scope $scope, ?Expr $arrayArg, ?Expr $callbackArg, ?Expr $flagArg) : Type { if ($arrayArg === null) { return new ArrayType(new MixedType(), new MixedType()); } $arrayArgType = $scope->getType($arrayArg); $arrayArgType = TypeUtils::toBenevolentUnion($arrayArgType); $keyType = $arrayArgType->getIterableKeyType(); $itemType = $arrayArgType->getIterableValueType(); if ($itemType instanceof NeverType || $keyType instanceof NeverType) { return new ConstantArrayType([], []); } if ($arrayArgType instanceof MixedType) { return new BenevolentUnionType([new ArrayType(new MixedType(), new MixedType()), new NullType()]); } if ($callbackArg === null || $scope->getType($callbackArg)->isNull()->yes()) { return TypeCombinator::union(...array_map([$this, 'removeFalsey'], $arrayArgType->getArrays())); } $mode = $this->determineMode($flagArg, $scope); if ($mode === null) { return new ArrayType($keyType, $itemType); } if ($callbackArg instanceof Closure && count($callbackArg->stmts) === 1 && count($callbackArg->params) > 0) { $statement = $callbackArg->stmts[0]; if ($statement instanceof Return_ && $statement->expr !== null) { if ($mode === self::USE_ITEM) { $keyVar = null; $itemVar = $callbackArg->params[0]->var; } elseif ($mode === self::USE_KEY) { $keyVar = $callbackArg->params[0]->var; $itemVar = null; } elseif ($mode === self::USE_BOTH) { $keyVar = $callbackArg->params[1]->var ?? null; $itemVar = $callbackArg->params[0]->var; } return $this->filterByTruthyValue($scope, $itemVar, $arrayArgType, $keyVar, $statement->expr); } } elseif ($callbackArg instanceof ArrowFunction && count($callbackArg->params) > 0) { if ($mode === self::USE_ITEM) { $keyVar = null; $itemVar = $callbackArg->params[0]->var; } elseif ($mode === self::USE_KEY) { $keyVar = $callbackArg->params[0]->var; $itemVar = null; } elseif ($mode === self::USE_BOTH) { $keyVar = $callbackArg->params[1]->var ?? null; $itemVar = $callbackArg->params[0]->var; } return $this->filterByTruthyValue($scope, $itemVar, $arrayArgType, $keyVar, $callbackArg->expr); } elseif (($callbackArg instanceof FuncCall || $callbackArg instanceof MethodCall || $callbackArg instanceof StaticCall) && $callbackArg->isFirstClassCallable()) { [$args, $itemVar, $keyVar] = $this->createDummyArgs($mode); $expr = clone $callbackArg; $expr->args = $args; return $this->filterByTruthyValue($scope, $itemVar, $arrayArgType, $keyVar, $expr); } else { $constantStrings = $scope->getType($callbackArg)->getConstantStrings(); if (count($constantStrings) > 0) { $results = []; [$args, $itemVar, $keyVar] = $this->createDummyArgs($mode); foreach ($constantStrings as $constantString) { $funcName = self::createFunctionName($constantString->getValue()); if ($funcName === null) { $results[] = new ErrorType(); continue; } $expr = new FuncCall($funcName, $args); $results[] = $this->filterByTruthyValue($scope, $itemVar, $arrayArgType, $keyVar, $expr); } return TypeCombinator::union(...$results); } } return new ArrayType($keyType, $itemType); } private function removeFalsey(Type $type) : Type { $falseyTypes = StaticTypeFactory::falsey(); if (count($type->getConstantArrays()) > 0) { $result = []; foreach ($type->getConstantArrays() as $constantArray) { $keys = $constantArray->getKeyTypes(); $values = $constantArray->getValueTypes(); $builder = ConstantArrayTypeBuilder::createEmpty(); foreach ($values as $offset => $value) { $isFalsey = $falseyTypes->isSuperTypeOf($value); if ($isFalsey->maybe()) { $builder->setOffsetValueType($keys[$offset], TypeCombinator::remove($value, $falseyTypes), \true); } elseif ($isFalsey->no()) { $builder->setOffsetValueType($keys[$offset], $value, $constantArray->isOptionalKey($offset)); } } $result[] = $builder->getArray(); } return TypeCombinator::union(...$result); } $keyType = $type->getIterableKeyType(); $valueType = $type->getIterableValueType(); $valueType = TypeCombinator::remove($valueType, $falseyTypes); if ($valueType instanceof NeverType) { return new ConstantArrayType([], []); } return new ArrayType($keyType, $valueType); } /** * @param Error|Variable|null $itemVar * @param Error|Variable|null $keyVar */ private function filterByTruthyValue(Scope $scope, $itemVar, Type $arrayType, $keyVar, Expr $expr) : Type { if (!$scope instanceof MutatingScope) { throw new ShouldNotHappenException(); } $constantArrays = $arrayType->getConstantArrays(); if (count($constantArrays) > 0) { $results = []; foreach ($constantArrays as $constantArray) { $builder = ConstantArrayTypeBuilder::createEmpty(); $optionalKeys = $constantArray->getOptionalKeys(); foreach ($constantArray->getKeyTypes() as $i => $keyType) { $itemType = $constantArray->getValueTypes()[$i]; [$newKeyType, $newItemType, $optional] = $this->processKeyAndItemType($scope, $keyType, $itemType, $itemVar, $keyVar, $expr); $optional = $optional || in_array($i, $optionalKeys, \true); if ($newKeyType instanceof NeverType || $newItemType instanceof NeverType) { continue; } if ($itemType->equals($newItemType) && $keyType->equals($newKeyType)) { $builder->setOffsetValueType($keyType, $itemType, $optional); continue; } $builder->setOffsetValueType($newKeyType, $newItemType, \true); } $results[] = $builder->getArray(); } return TypeCombinator::union(...$results); } [$newKeyType, $newItemType] = $this->processKeyAndItemType($scope, $arrayType->getIterableKeyType(), $arrayType->getIterableValueType(), $itemVar, $keyVar, $expr); if ($newItemType instanceof NeverType || $newKeyType instanceof NeverType) { return new ConstantArrayType([], []); } return new ArrayType($newKeyType, $newItemType); } /** * @return array{Type, Type, bool} * @param Error|Variable|null $itemVar * @param Error|Variable|null $keyVar */ private function processKeyAndItemType(MutatingScope $scope, Type $keyType, Type $itemType, $itemVar, $keyVar, Expr $expr) : array { $itemVarName = null; if ($itemVar !== null) { if (!$itemVar instanceof Variable || !is_string($itemVar->name)) { throw new ShouldNotHappenException(); } $itemVarName = $itemVar->name; $scope = $scope->assignVariable($itemVarName, $itemType, new MixedType()); } $keyVarName = null; if ($keyVar !== null) { if (!$keyVar instanceof Variable || !is_string($keyVar->name)) { throw new ShouldNotHappenException(); } $keyVarName = $keyVar->name; $scope = $scope->assignVariable($keyVarName, $keyType, new MixedType()); } $booleanResult = $scope->getType($expr)->toBoolean(); if ($booleanResult->isFalse()->yes()) { return [new NeverType(), new NeverType(), \false]; } $scope = $scope->filterByTruthyValue($expr); return [$keyVarName !== null ? $scope->getVariableType($keyVarName) : $keyType, $itemVarName !== null ? $scope->getVariableType($itemVarName) : $itemType, !$booleanResult->isTrue()->yes()]; } private static function createFunctionName(string $funcName) : ?Name { if ($funcName === '') { return null; } if ($funcName[0] === '\\') { $funcName = substr($funcName, 1); if ($funcName === '') { return null; } return new Name\FullyQualified($funcName); } return new Name($funcName); } /** * @param self::USE_* $mode * @return array{list, ?Variable, ?Variable} */ private function createDummyArgs(int $mode) : array { if ($mode === self::USE_ITEM) { $itemVar = new Variable('item'); $keyVar = null; $args = [new Arg($itemVar)]; } elseif ($mode === self::USE_KEY) { $itemVar = null; $keyVar = new Variable('key'); $args = [new Arg($keyVar)]; } elseif ($mode === self::USE_BOTH) { $itemVar = new Variable('item'); $keyVar = new Variable('key'); $args = [new Arg($itemVar), new Arg($keyVar)]; } return [$args, $itemVar, $keyVar]; } /** * @param non-empty-string $constantName */ private function getConstant(string $constantName) : int { $constant = $this->reflectionProvider->getConstant(new Name($constantName), null); $valueType = $constant->getValueType(); if (!$valueType instanceof ConstantIntegerType) { throw new ShouldNotHappenException(sprintf('Constant %s does not have integer type.', $constantName)); } return $valueType->getValue(); } /** * @return self::USE_*|null */ private function determineMode(?Expr $flagArg, Scope $scope) : ?int { if ($flagArg === null) { return self::USE_ITEM; } $flagValues = $scope->getType($flagArg)->getConstantScalarValues(); if (count($flagValues) !== 1) { return null; } if ($flagValues[0] === $this->getConstant('ARRAY_FILTER_USE_KEY')) { return self::USE_KEY; } elseif ($flagValues[0] === $this->getConstant('ARRAY_FILTER_USE_BOTH')) { return self::USE_BOTH; } return null; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'mb_strlen'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) === 0) { return null; } $encodings = []; if (count($functionCall->getArgs()) === 1) { // there is a chance to get an unsupported encoding 'pass' or 'none' here on PHP 7.3-7.4 $encodings = [mb_internal_encoding()]; } elseif (count($functionCall->getArgs()) === 2) { // custom encoding is specified $encodings = array_map(static function (ConstantStringType $t) { return $t->getValue(); }, $scope->getType($functionCall->getArgs()[1]->value)->getConstantStrings()); } if (count($encodings) > 0) { for ($i = 0; $i < count($encodings); $i++) { if ($this->isSupportedEncoding($encodings[$i])) { continue; } $encodings[$i] = self::UNSUPPORTED_ENCODING; } $encodings = array_unique($encodings); if (in_array(self::UNSUPPORTED_ENCODING, $encodings, \true) && count($encodings) === 1) { if ($this->phpVersion->throwsOnInvalidMbStringEncoding()) { return new NeverType(); } return new ConstantBooleanType(\false); } } else { // if there aren't encoding constants, use all available encodings $encodings = array_merge($this->getSupportedEncodings(), [self::UNSUPPORTED_ENCODING]); } $argType = $scope->getType($args[0]->value); if ($argType->isSuperTypeOf(new BooleanType())->yes()) { $constantScalars = TypeCombinator::remove($argType, new BooleanType())->getConstantScalarTypes(); if (count($constantScalars) > 0) { $constantScalars[] = new ConstantBooleanType(\true); $constantScalars[] = new ConstantBooleanType(\false); } } else { $constantScalars = $argType->getConstantScalarTypes(); } $lengths = []; foreach ($constantScalars as $constantScalar) { $stringScalar = $constantScalar->toString(); if (!$stringScalar instanceof ConstantStringType) { $lengths = []; break; } foreach ($encodings as $encoding) { if (!$this->isSupportedEncoding($encoding)) { continue; } $length = @mb_strlen($stringScalar->getValue(), $encoding); if ($length === \false) { throw new ShouldNotHappenException(sprintf('Got false on a supported encoding %s and value %s', $encoding, var_export($stringScalar->getValue(), \true))); } $lengths[] = $length; } } $isNonEmpty = $argType->isNonEmptyString(); $numeric = TypeCombinator::union(new IntegerType(), new FloatType()); if (count($lengths) > 0) { $lengths = array_unique($lengths); sort($lengths); if ($lengths === range(min($lengths), max($lengths))) { $range = IntegerRangeType::fromInterval(min($lengths), max($lengths)); } else { $range = TypeCombinator::union(...array_map(static function ($l) { return new ConstantIntegerType($l); }, $lengths)); } } elseif ($argType->isBoolean()->yes()) { $range = IntegerRangeType::fromInterval(0, 1); } elseif ($isNonEmpty->yes() || $numeric->isSuperTypeOf($argType)->yes() || TypeCombinator::remove($argType, $numeric)->isNonEmptyString()->yes()) { $range = IntegerRangeType::fromInterval(1, null); } elseif ($argType->isString()->yes() && $isNonEmpty->no()) { $range = new ConstantIntegerType(0); } else { $range = TypeCombinator::remove(ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants())->getReturnType(), new ConstantBooleanType(\false)); } if (!$this->phpVersion->throwsOnInvalidMbStringEncoding() && in_array(self::UNSUPPORTED_ENCODING, $encodings, \true)) { return TypeCombinator::union($range, new ConstantBooleanType(\false)); } return $range; } } propertyReflectionFinder = $propertyReflectionFinder; } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return $functionReflection->getName() === 'property_exists' && $context->true() && count($node->getArgs()) >= 2; } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $propertyNameType = $scope->getType($node->getArgs()[1]->value); if (!$propertyNameType instanceof ConstantStringType) { return new SpecifiedTypes([], []); } $objectType = $scope->getType($node->getArgs()[0]->value); if ($objectType instanceof ConstantStringType) { return new SpecifiedTypes([], []); } elseif ($objectType->isObject()->yes()) { $propertyNode = new PropertyFetch($node->getArgs()[0]->value, new Identifier($propertyNameType->getValue())); } else { return new SpecifiedTypes([], []); } $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($propertyNode, $scope); if ($propertyReflection !== null) { if (!$propertyReflection->isNative()) { return new SpecifiedTypes([], []); } } return $this->typeSpecifier->create($node->getArgs()[0]->value, new IntersectionType([new ObjectWithoutClassType(), new HasPropertyType($propertyNameType->getValue())]), $context, \false, $scope); } } getName() === 'microtime'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { if (count($functionCall->getArgs()) < 1) { return new StringType(); } $argType = $scope->getType($functionCall->getArgs()[0]->value); $isTrueType = $argType->isTrue(); $isFalseType = $argType->isFalse(); $compareTypes = $isTrueType->compareTo($isFalseType); if ($compareTypes === $isTrueType) { return new FloatType(); } if ($compareTypes === $isFalseType) { return new StringType(); } if ($argType instanceof MixedType) { return new BenevolentUnionType([new StringType(), new FloatType()]); } return new UnionType([new StringType(), new FloatType()]); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_flip'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) !== 1) { return null; } $arrayType = $scope->getType($functionCall->getArgs()[0]->value); if ($arrayType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } return $arrayType->flipArray(); } } getName() === 'abs'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $inputType = $scope->getType($args[0]->value); $outputType = $inputType->toAbsoluteNumber(); if ($outputType instanceof ErrorType) { return null; } return $outputType; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return in_array($functionReflection->getName(), ['min', 'max'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } if (count($functionCall->getArgs()) === 1) { $argType = $scope->getType($functionCall->getArgs()[0]->value); if ($argType->isArray()->yes()) { return $this->processArrayType($functionReflection->getName(), $argType); } return new ErrorType(); } // rewrite min($x, $y) as $x < $y ? $x : $y // we don't handle arrays, which have different semantics $functionName = $functionReflection->getName(); $args = $functionCall->getArgs(); if (count($functionCall->getArgs()) === 2) { $argType0 = $scope->getType($args[0]->value); $argType1 = $scope->getType($args[1]->value); if ($argType0->isArray()->no() && $argType1->isArray()->no()) { if ($functionName === 'min') { return $scope->getType(new Ternary(new Smaller($args[0]->value, $args[1]->value), $args[0]->value, $args[1]->value)); } elseif ($functionName === 'max') { return $scope->getType(new Ternary(new Smaller($args[0]->value, $args[1]->value), $args[1]->value, $args[0]->value)); } } } $argumentTypes = []; foreach ($functionCall->getArgs() as $arg) { $argType = $scope->getType($arg->value); if ($arg->unpack) { $iterableValueType = $argType->getIterableValueType(); if ($iterableValueType instanceof UnionType) { foreach ($iterableValueType->getTypes() as $innerType) { $argumentTypes[] = $innerType; } } else { $argumentTypes[] = $iterableValueType; } continue; } $argumentTypes[] = $argType; } return $this->processType($functionName, $argumentTypes); } private function processArrayType(string $functionName, Type $argType) : Type { $constArrayTypes = $argType->getConstantArrays(); if (count($constArrayTypes) > 0) { $resultTypes = []; foreach ($constArrayTypes as $constArrayType) { $isIterable = $constArrayType->isIterableAtLeastOnce(); if ($isIterable->no() && !$this->phpVersion->throwsValueErrorForInternalFunctions()) { $resultTypes[] = new ConstantBooleanType(\false); continue; } $argumentTypes = []; if (!$isIterable->yes() && !$this->phpVersion->throwsValueErrorForInternalFunctions()) { $argumentTypes[] = new ConstantBooleanType(\false); } foreach ($constArrayType->getValueTypes() as $innerType) { $argumentTypes[] = $innerType; } $resultTypes[] = $this->processType($functionName, $argumentTypes); } return TypeCombinator::union(...$resultTypes); } $isIterable = $argType->isIterableAtLeastOnce(); if ($isIterable->no() && !$this->phpVersion->throwsValueErrorForInternalFunctions()) { return new ConstantBooleanType(\false); } $iterableValueType = $argType->getIterableValueType(); $argumentTypes = []; if (!$isIterable->yes() && !$this->phpVersion->throwsValueErrorForInternalFunctions()) { $argumentTypes[] = new ConstantBooleanType(\false); } $argumentTypes[] = $iterableValueType; return $this->processType($functionName, $argumentTypes); } /** * @param Type[] $types */ private function processType(string $functionName, array $types) : Type { $resultType = null; foreach ($types as $type) { if ($resultType === null) { $resultType = $type; continue; } $compareResult = $this->compareTypes($resultType, $type); if ($compareResult === null) { return TypeCombinator::union(...$types); } if ($functionName === 'min') { if ($compareResult === $type) { $resultType = $type; } } elseif ($functionName === 'max') { if ($compareResult === $resultType) { $resultType = $type; } } } if ($resultType === null) { return new ErrorType(); } return $resultType; } private function compareTypes(Type $firstType, Type $secondType) : ?Type { if ($firstType->isArray()->yes() && $secondType->isConstantScalarValue()->yes()) { return $secondType; } if ($firstType->isConstantScalarValue()->yes() && $secondType->isArray()->yes()) { return $firstType; } if ($firstType instanceof ConstantArrayType && $secondType instanceof ConstantArrayType) { if ($secondType->getArraySize() < $firstType->getArraySize()) { return $secondType; } elseif ($firstType->getArraySize() < $secondType->getArraySize()) { return $firstType; } foreach ($firstType->getValueTypes() as $i => $firstValueType) { $secondValueType = $secondType->getValueTypes()[$i]; $compareResult = $this->compareTypes($firstValueType, $secondValueType); if ($compareResult === $firstValueType) { return $firstType; } if ($compareResult === $secondValueType) { return $secondType; } } return null; } if ($firstType instanceof ConstantScalarType && $secondType instanceof ConstantScalarType) { if ($secondType->getValue() < $firstType->getValue()) { return $secondType; } if ($firstType->getValue() < $secondType->getValue()) { return $firstType; } } return null; } } getName() === 'xpath'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { if (!isset($methodCall->getArgs()[0])) { return null; } $argType = $scope->getType($methodCall->getArgs()[0]->value); $xmlElement = new SimpleXMLElement(''); foreach ($argType->getConstantStrings() as $constantString) { $result = @$xmlElement->xpath($constantString->getValue()); if ($result === \false) { // We can't be sure since it's maybe a namespaced xpath return null; } $argType = TypeCombinator::remove($argType, $constantString); } if (!$argType instanceof NeverType) { return null; } return new ArrayType(new MixedType(), $scope->getType($methodCall->var)); } } isAFunctionTypeSpecifyingHelper = $isAFunctionTypeSpecifyingHelper; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return strtolower($functionReflection->getName()) === 'is_a' && !$context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { if (count($node->getArgs()) < 2) { return new SpecifiedTypes(); } $classType = $scope->getType($node->getArgs()[1]->value); if (!$classType instanceof ConstantStringType && !$context->true()) { return new SpecifiedTypes([], []); } $objectOrClassType = $scope->getType($node->getArgs()[0]->value); $allowStringType = isset($node->getArgs()[2]) ? $scope->getType($node->getArgs()[2]->value) : new ConstantBooleanType(\false); $allowString = !$allowStringType->equals(new ConstantBooleanType(\false)); $resultType = $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, \true); // prevent false-positives in IsAFunctionTypeSpecifyingHelper if ($classType->getConstantStrings() === [] && $resultType->isSuperTypeOf($objectOrClassType)->yes()) { return new SpecifiedTypes([], []); } return $this->typeSpecifier->create($node->getArgs()[0]->value, $resultType, $context, \false, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } typeSpecifier = $typeSpecifier; } public function getClass() : string { return ReflectionClass::class; } public function isMethodSupported(MethodReflection $methodReflection, MethodCall $node, TypeSpecifierContext $context) : bool { return $methodReflection->getName() === 'isSubclassOf' && isset($node->getArgs()[0]) && $context->true(); } public function specifyTypes(MethodReflection $methodReflection, MethodCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $valueType = $scope->getType($node->getArgs()[0]->value); if (!$valueType instanceof ConstantStringType) { return new SpecifiedTypes([], []); } return $this->typeSpecifier->create($node->var, new GenericObjectType(ReflectionClass::class, [new ObjectType($valueType->getValue())]), $context, \false, $scope); } } getName() === 'array_sum'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $resultTypes = []; if (count($argType->getConstantArrays()) > 0) { foreach ($argType->getConstantArrays() as $constantArray) { $node = new LNumber(0); foreach ($constantArray->getValueTypes() as $i => $type) { if ($constantArray->isOptionalKey($i)) { $node = new Plus($node, new TypeExpr(TypeCombinator::union($type, new ConstantIntegerType(0)))); } else { $node = new Plus($node, new TypeExpr($type)); } } $resultTypes[] = $scope->getType($node); } } else { $itemType = $argType->getIterableValueType(); $mulNode = new Mul(new TypeExpr($itemType), new TypeExpr(IntegerRangeType::fromInterval(0, null))); $resultTypes[] = $scope->getType(new Plus(new TypeExpr($itemType), $mulNode)); } if (!$argType->isIterableAtLeastOnce()->yes()) { $resultTypes[] = new ConstantIntegerType(0); } return TypeCombinator::union(...$resultTypes)->toNumber(); } } null() && count($node->getArgs()) >= 1 && in_array($functionReflection->getName(), ['sizeof', 'count'], \true); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { if (!$scope->getType($node->getArgs()[0]->value)->isArray()->yes()) { return new SpecifiedTypes([], []); } return $this->typeSpecifier->create($node->getArgs()[0]->value, new NonEmptyArrayType(), $context, \false, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } 1, 'mb_regex_encoding' => 1, 'mb_internal_encoding' => 1, 'mb_encoding_aliases' => 1, 'mb_chr' => 2, 'mb_ord' => 2]; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return array_key_exists($functionReflection->getName(), $this->encodingPositionMap); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $returnType = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants())->getReturnType(); $positionEncodingParam = $this->encodingPositionMap[$functionReflection->getName()]; if (count($functionCall->getArgs()) < $positionEncodingParam) { return TypeCombinator::remove($returnType, new BooleanType()); } $strings = $scope->getType($functionCall->getArgs()[$positionEncodingParam - 1]->value)->getConstantStrings(); $results = array_unique(array_map(function (ConstantStringType $encoding) : bool { return $this->isSupportedEncoding($encoding->getValue()); }, $strings)); if ($returnType->equals(new UnionType([new StringType(), new BooleanType()]))) { return count($results) === 1 ? new ConstantBooleanType($results[0]) : new BooleanType(); } if (count($results) === 1) { $invalidEncodingReturn = new ConstantBooleanType(\false); if ($this->phpVersion->throwsOnInvalidMbStringEncoding()) { $invalidEncodingReturn = new NeverType(); } return $results[0] ? TypeCombinator::remove($returnType, new ConstantBooleanType(\false)) : $invalidEncodingReturn; } return $returnType; } } dateFunctionReturnTypeHelper = $dateFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'date'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) === 0) { return null; } return $this->dateFunctionReturnTypeHelper->getTypeFromFormatType($scope->getType($functionCall->getArgs()[0]->value), \false); } } minimum arity] */ private const FUNCTIONS = ['strtoupper' => 1, 'strtolower' => 1, 'mb_strtoupper' => 1, 'mb_strtolower' => 1, 'lcfirst' => 1, 'ucfirst' => 1, 'mb_lcfirst' => 1, 'mb_ucfirst' => 1, 'ucwords' => 1, 'mb_convert_case' => 2, 'mb_convert_kana' => 1]; public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return isset(self::FUNCTIONS[$functionReflection->getName()]); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $fnName = $functionReflection->getName(); $args = $functionCall->getArgs(); if (count($args) < self::FUNCTIONS[$fnName]) { return null; } $argType = $scope->getType($args[0]->value); if (!is_callable($fnName)) { return null; } $modes = []; $keepLowercase = \false; $forceLowercase = \false; $keepUppercase = \false; $forceUppercase = \false; if ($fnName === 'mb_convert_case') { $modeType = $scope->getType($args[1]->value); $modes = array_map(static function ($mode) { return $mode->getValue(); }, TypeUtils::getConstantIntegers($modeType)); if (count($modes) > 0) { $forceLowercase = count(array_diff($modes, [MB_CASE_LOWER, 5])) === 0; $keepLowercase = count(array_diff($modes, [ MB_CASE_LOWER, 5, // MB_CASE_LOWER_SIMPLE 3, // MB_CASE_FOLD, 7, ])) === 0; $forceUppercase = count(array_diff($modes, [MB_CASE_UPPER, 4])) === 0; $keepUppercase = count(array_diff($modes, [ MB_CASE_UPPER, 4, // MB_CASE_UPPER_SIMPLE 3, // MB_CASE_FOLD, 7, ])) === 0; } } elseif (in_array($fnName, ['ucwords', 'mb_convert_kana'], \true)) { if (count($args) >= 2) { $modeType = $scope->getType($args[1]->value); $modes = array_map(static function ($mode) { return $mode->getValue(); }, $modeType->getConstantStrings()); } else { $modes = $fnName === 'mb_convert_kana' ? ['KV'] : [" \t\r\n\f\v"]; } } elseif (in_array($fnName, ['strtolower', 'mb_strtolower'], \true)) { $forceLowercase = \true; } elseif (in_array($fnName, ['lcfirst', 'mb_lcfirst'], \true)) { $keepLowercase = \true; } elseif (in_array($fnName, ['strtoupper', 'mb_strtoupper'], \true)) { $forceUppercase = \true; } elseif (in_array($fnName, ['ucfirst', 'mb_ucfirst'], \true)) { $keepUppercase = \true; } $constantStrings = array_map(static function ($type) { return $type->getValue(); }, $argType->getConstantStrings()); if (count($constantStrings) > 0 && mb_check_encoding($constantStrings, 'UTF-8')) { $strings = []; $parameters = []; if (in_array($fnName, ['ucwords', 'mb_convert_case', 'mb_convert_kana'], \true)) { foreach ($modes as $mode) { foreach ($constantStrings as $constantString) { $parameters[] = [$constantString, $mode]; } } } else { $parameters = array_map(static function ($s) { return [$s]; }, $constantStrings); } foreach ($parameters as $parameter) { $strings[] = $fnName(...$parameter); } if (count($strings) !== 0 && mb_check_encoding($strings, 'UTF-8')) { return TypeCombinator::union(...array_map(static function ($s) { return new ConstantStringType($s); }, $strings)); } } $accessoryTypes = []; $argStringType = $argType->toString(); if ($forceLowercase || $keepLowercase && $argStringType->isLowercaseString()->yes()) { $accessoryTypes[] = new AccessoryLowercaseStringType(); } if ($forceUppercase || $keepUppercase && $argStringType->isUppercaseString()->yes()) { $accessoryTypes[] = new AccessoryUppercaseStringType(); } if ($argStringType->isNumericString()->yes()) { $accessoryTypes[] = new AccessoryNumericStringType(); } elseif ($argStringType->isNonFalsyString()->yes()) { $accessoryTypes[] = new AccessoryNonFalsyStringType(); } elseif ($argStringType->isNonEmptyString()->yes()) { $accessoryTypes[] = new AccessoryNonEmptyStringType(); } if (count($accessoryTypes) > 0) { $accessoryTypes[] = new StringType(); return new IntersectionType($accessoryTypes); } return new StringType(); } } reflectionProvider = $reflectionProvider; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->universalObjectCratesClasses = $universalObjectCratesClasses; $this->nullContextForVoidReturningFunctions = $nullContextForVoidReturningFunctions; } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return in_array($functionReflection->getName(), ['array_key_exists', 'key_exists', 'in_array', 'is_subclass_of'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) === 0) { return null; } $isAlways = $this->getHelper()->findSpecifiedType($scope, $functionCall); if ($isAlways === null) { return null; } return new ConstantBooleanType($isAlways); } private function getHelper() : ImpossibleCheckTypeHelper { if ($this->helper === null) { $this->helper = new ImpossibleCheckTypeHelper($this->reflectionProvider, $this->typeSpecifier, $this->universalObjectCratesClasses, $this->treatPhpDocTypesAsCertain, $this->nullContextForVoidReturningFunctions); } return $this->helper; } } getName(), ['class_exists', 'interface_exists', 'trait_exists', 'enum_exists'], \true) && isset($node->getArgs()[0]) && $context->true(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $argType = $scope->getType($node->getArgs()[0]->value); if ($argType instanceof ConstantStringType) { return $this->typeSpecifier->create(new FuncCall(new FullyQualified('class_exists'), [new Arg(new String_(ltrim($argType->getValue(), '\\')))]), new ConstantBooleanType(\true), $context, \false, $scope); } $narrowedType = new ClassStringType(); if ($functionReflection->getName() === 'enum_exists') { $narrowedType = new GenericClassStringType(new ObjectType('UnitEnum')); } return $this->typeSpecifier->create($node->getArgs()[0]->value, $narrowedType, $context, \false, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } getName()) === 'array_replace'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (!isset($args[0])) { return null; } $argTypes = []; $optionalArgTypes = []; foreach ($args as $arg) { $argType = $scope->getType($arg->value); if ($arg->unpack) { if ($argType->isConstantArray()->yes()) { foreach ($argType->getConstantArrays() as $constantArray) { foreach ($constantArray->getValueTypes() as $valueType) { $argTypes[] = $valueType; } } } else { $argTypes[] = $argType->getIterableValueType(); } if (!$argType->isIterableAtLeastOnce()->yes()) { // unpacked params can be empty, making them optional $optionalArgTypesOffset = count($argTypes) - 1; foreach (array_keys($argTypes) as $key) { $optionalArgTypes[] = $optionalArgTypesOffset + $key; } } } else { $argTypes[] = $argType; } } $allConstant = TrinaryLogic::createYes()->lazyAnd($argTypes, static function (Type $argType) { return $argType->isConstantArray(); }); if ($allConstant->yes()) { $newArrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach ($argTypes as $argType) { /** @var array $keyTypes */ $keyTypes = []; foreach ($argType->getConstantArrays() as $constantArray) { foreach ($constantArray->getKeyTypes() as $keyType) { $keyTypes[$keyType->getValue()] = $keyType; } } foreach ($keyTypes as $keyType) { $newArrayBuilder->setOffsetValueType($keyType, $argType->getOffsetValueType($keyType), !$argType->hasOffsetValueType($keyType)->yes()); } } return $newArrayBuilder->getArray(); } $keyTypes = []; $valueTypes = []; $nonEmpty = \false; $isList = \true; foreach ($argTypes as $key => $argType) { $keyType = $argType->getIterableKeyType(); $keyTypes[] = $keyType; $valueTypes[] = $argType->getIterableValueType(); if (!$argType->isList()->yes()) { $isList = \false; } if (in_array($key, $optionalArgTypes, \true) || !$argType->isIterableAtLeastOnce()->yes()) { continue; } $nonEmpty = \true; } $keyType = TypeCombinator::union(...$keyTypes); if ($keyType instanceof NeverType) { return new ConstantArrayType([], []); } $arrayType = new ArrayType($keyType, TypeCombinator::union(...$valueTypes)); if ($nonEmpty) { $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } if ($isList) { $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } return $arrayType; } } getName()) === 'ctype_digit' && !$context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { if (!isset($node->getArgs()[0])) { return new SpecifiedTypes(); } if ($context->null()) { throw new ShouldNotHappenException(); } $exprArg = $node->getArgs()[0]->value; if ($context->true() && $scope->getType($exprArg)->isNumericString()->yes()) { return new SpecifiedTypes(); } $types = [ IntegerRangeType::fromInterval(48, 57), // ASCII-codes for 0-9 IntegerRangeType::createAllGreaterThanOrEqualTo(256), ]; if ($context->true()) { $types[] = new IntersectionType([new StringType(), new AccessoryNumericStringType()]); } $unionType = TypeCombinator::union(...$types); $specifiedTypes = $this->typeSpecifier->create($exprArg, $unionType, $context, \false, $scope); if ($exprArg instanceof Cast\String_) { $castedType = new UnionType([IntegerRangeType::fromInterval(0, null), new IntersectionType([new StringType(), new AccessoryNumericStringType()]), new ConstantBooleanType(\true)]); $specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create($exprArg->expr, $castedType, $context, \false, $scope)); } return $specifiedTypes; } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } getSupportedEncodings(), \true); } /** @return string[] */ private function getSupportedEncodings() : array { if (!is_null($this->supportedEncodings)) { return $this->supportedEncodings; } $supportedEncodings = []; if (function_exists('mb_list_encodings')) { foreach (mb_list_encodings() as $encoding) { $aliases = @mb_encoding_aliases($encoding); if ($aliases === \false) { throw new ShouldNotHappenException(); } $supportedEncodings = array_merge($supportedEncodings, $aliases, [$encoding]); } } $this->supportedEncodings = array_map('strtoupper', $supportedEncodings); // PHP 7.3 and 7.4 claims 'pass' and its alias 'none' to be supported, but actually 'pass' was removed in 7.3 if (!$this->phpVersion->supportsPassNoneEncodings()) { $this->supportedEncodings = array_filter($this->supportedEncodings, static function (string $enc) { return !in_array($enc, ['PASS', 'NONE'], \true); }); } return $this->supportedEncodings; } } getName() === 'number_format'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $stringType = new StringType(); if (!isset($functionCall->getArgs()[3])) { return $stringType; } $thousandsType = $scope->getType($functionCall->getArgs()[3]->value); $decimalType = $scope->getType($functionCall->getArgs()[2]->value); if (!$thousandsType instanceof ConstantStringType || $thousandsType->getValue() !== '') { return $stringType; } if (!$decimalType instanceof ConstantScalarType || !in_array($decimalType->getValue(), [null, '.', ''], \true)) { return $stringType; } return new IntersectionType([$stringType, new AccessoryNumericStringType()]); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return in_array($functionReflection->getName(), ['str_split', 'mb_str_split'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 1) { return null; } if (count($functionCall->getArgs()) >= 2) { $splitLengthType = $scope->getType($functionCall->getArgs()[1]->value); if ($splitLengthType instanceof ConstantIntegerType) { $splitLength = $splitLengthType->getValue(); if ($splitLength < 1) { return new ConstantBooleanType(\false); } } } else { $splitLength = 1; } $encoding = null; if ($functionReflection->getName() === 'mb_str_split') { if (count($functionCall->getArgs()) >= 3) { $strings = $scope->getType($functionCall->getArgs()[2]->value)->getConstantStrings(); $values = array_unique(array_map(static function (ConstantStringType $encoding) : string { return $encoding->getValue(); }, $strings)); if (count($values) !== 1) { return null; } $encoding = $values[0]; if (!$this->isSupportedEncoding($encoding)) { return new ConstantBooleanType(\false); } } else { $encoding = mb_internal_encoding(); } } if (!isset($splitLength)) { return null; } $stringType = $scope->getType($functionCall->getArgs()[0]->value); $constantStrings = $stringType->getConstantStrings(); if (count($constantStrings) > 0) { $results = []; foreach ($constantStrings as $constantString) { $items = $encoding === null ? str_split($constantString->getValue(), $splitLength) : @mb_str_split($constantString->getValue(), $splitLength, $encoding); if ($items === \false) { throw new ShouldNotHappenException(); } $results[] = self::createConstantArrayFrom($items, $scope); } return TypeCombinator::union(...$results); } $returnType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())); return $encoding === null && !$this->phpVersion->strSplitReturnsEmptyArray() ? TypeCombinator::intersect($returnType, new NonEmptyArrayType()) : $returnType; } /** * @param string[] $constantArray */ private static function createConstantArrayFrom(array $constantArray, Scope $scope) : ConstantArrayType { $keyTypes = []; $valueTypes = []; $isList = \true; $i = 0; foreach ($constantArray as $key => $value) { $keyType = $scope->getTypeFromValue($key); if (!$keyType instanceof ConstantIntegerType) { throw new ShouldNotHappenException(); } $keyTypes[] = $keyType; $valueTypes[] = $scope->getTypeFromValue($value); $isList = $isList && $key === $i; $i++; } return new ConstantArrayType($keyTypes, $valueTypes, $isList ? [$i] : [0], [], TrinaryLogic::createFromBoolean(array_is_list($constantArray))); } } dateFunctionReturnTypeHelper = $dateFunctionReturnTypeHelper; } public function getClass() : string { return DateTimeInterface::class; } public function isMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === 'format'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : Type { if (count($methodCall->getArgs()) === 0) { return new StringType(); } return $this->dateFunctionReturnTypeHelper->getTypeFromFormatType($scope->getType($methodCall->getArgs()[0]->value), \true); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_fill_keys'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } $keysType = $scope->getType($functionCall->getArgs()[0]->value); if ($keysType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } return $keysType->fillKeysArray($scope->getType($functionCall->getArgs()[1]->value)); } } getDeclaringClass()->getName() === 'Ds\\Map' && ($methodReflection->getName() === 'get' || $methodReflection->getName() === 'remove'); } public function getThrowTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->args) < 2) { return $methodReflection->getThrowType(); } return new VoidType(); } } getName() === 'asXML'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : Type { if (count($methodCall->getArgs()) === 1) { return new BooleanType(); } return new UnionType([new StringType(), new ConstantBooleanType(\false)]); } } getName(), ['from', 'tryFrom'], \true); } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope) : ?Type { if (!$methodReflection->getDeclaringClass()->isBackedEnum()) { return null; } $arguments = $methodCall->getArgs(); if (count($arguments) < 1) { return null; } $valueType = $scope->getType($arguments[0]->value); $enumCases = $methodReflection->getDeclaringClass()->getEnumCases(); if (count($enumCases) === 0) { if ($methodReflection->getName() === 'tryFrom') { return new NullType(); } return null; } if (count($valueType->getConstantScalarValues()) === 0) { return null; } $resultEnumCases = []; $addNull = \false; foreach ($valueType->getConstantScalarValues() as $value) { $hasMatching = \false; foreach ($enumCases as $enumCase) { if ($enumCase->getBackingValueType() === null) { continue; } $enumCaseValues = $enumCase->getBackingValueType()->getConstantScalarValues(); if (count($enumCaseValues) !== 1) { continue; } if ($value === $enumCaseValues[0]) { $resultEnumCases[] = new EnumCaseObjectType($enumCase->getDeclaringEnum()->getName(), $enumCase->getName(), $enumCase->getDeclaringEnum()); $hasMatching = \true; break; } } if ($hasMatching) { continue; } $addNull = \true; } if (count($resultEnumCases) === 0) { if ($methodReflection->getName() === 'tryFrom') { return new NullType(); } return null; } $result = TypeCombinator::union(...$resultEnumCases); if ($addNull && $methodReflection->getName() === 'tryFrom') { return TypeCombinator::addNull($result); } return $result; } } getName() === 'array_rand'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $argsCount = count($functionCall->getArgs()); if ($argsCount < 1) { return null; } $firstArgType = $scope->getType($functionCall->getArgs()[0]->value); $isInteger = $firstArgType->getIterableKeyType()->isInteger(); $isString = $firstArgType->getIterableKeyType()->isString(); if ($isInteger->yes()) { $valueType = new IntegerType(); } elseif ($isString->yes()) { $valueType = new StringType(); } else { $valueType = new UnionType([new IntegerType(), new StringType()]); } if ($argsCount < 2) { return $valueType; } $secondArgType = $scope->getType($functionCall->getArgs()[1]->value); $one = new ConstantIntegerType(1); if ($one->isSuperTypeOf($secondArgType)->yes()) { return $valueType; } $bigger2 = IntegerRangeType::fromInterval(2, null); if ($bigger2->isSuperTypeOf($secondArgType)->yes()) { return new ArrayType(new IntegerType(), $valueType); } return TypeCombinator::union($valueType, new ArrayType(new IntegerType(), $valueType)); } } getName() === 'function_exists' && isset($node->getArgs()[0]) && $context->true(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $argType = $scope->getType($node->getArgs()[0]->value); if ($argType instanceof ConstantStringType) { return $this->typeSpecifier->create(new FuncCall(new FullyQualified('function_exists'), [new Arg(new String_(ltrim($argType->getValue(), '\\')))]), new ConstantBooleanType(\true), $context, \false, $scope); } return $this->typeSpecifier->create($node->getArgs()[0]->value, new CallableType(), $context, \false, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } getName(), ['stat', 'lstat', 'fstat', 'ssh2_sftp_stat'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { return TypeCombinator::union($this->getReturnType(), new ConstantBooleanType(\false)); } public function getClass() : string { return SplFileObject::class; } public function isMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === 'fstat'; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : Type { return $this->getReturnType(); } private function getReturnType() : Type { $valueType = new IntegerType(); $builder = ConstantArrayTypeBuilder::createEmpty(); $keys = ['dev', 'ino', 'mode', 'nlink', 'uid', 'gid', 'rdev', 'size', 'atime', 'mtime', 'ctime', 'blksize', 'blocks']; foreach ($keys as $key) { $builder->setOffsetValueType(null, $valueType); } foreach ($keys as $key) { $builder->setOffsetValueType(new ConstantStringType($key), $valueType); } return $builder->getArray(); } } 1, 'json_decode' => 3]; public function __construct(ReflectionProvider $reflectionProvider, BitwiseFlagHelper $bitwiseFlagAnalyser) { $this->reflectionProvider = $reflectionProvider; $this->bitwiseFlagAnalyser = $bitwiseFlagAnalyser; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return in_array($functionReflection->getName(), ['json_encode', 'json_decode'], \true) && $this->reflectionProvider->hasConstant(new Name\FullyQualified('JSON_THROW_ON_ERROR'), null); } public function getThrowTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $argumentPosition = self::ARGUMENTS_POSITIONS[$functionReflection->getName()]; if (!isset($functionCall->getArgs()[$argumentPosition])) { return null; } $optionsExpr = $functionCall->getArgs()[$argumentPosition]->value; if (!$this->bitwiseFlagAnalyser->bitwiseOrContainsConstant($optionsExpr, $scope, 'JSON_THROW_ON_ERROR')->no()) { return new ObjectType('JsonException'); } return null; } } filterFunctionReturnTypeHelper = $filterFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'filter_input'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } return $this->filterFunctionReturnTypeHelper->getInputType($scope->getType($functionCall->getArgs()[0]->value), $scope->getType($functionCall->getArgs()[1]->value), isset($functionCall->getArgs()[2]) ? $scope->getType($functionCall->getArgs()[2]->value) : null, isset($functionCall->getArgs()[3]) ? $scope->getType($functionCall->getArgs()[3]->value) : null); } } getName()) === 'settype' && count($node->getArgs()) > 1 && $context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $value = $node->getArgs()[0]->value; $valueType = $scope->getType($value); $castType = $scope->getType($node->getArgs()[1]->value); $constantStrings = $castType->getConstantStrings(); if (count($constantStrings) < 1) { return new SpecifiedTypes(); } $types = []; foreach ($constantStrings as $constantString) { switch ($constantString->getValue()) { case 'bool': case 'boolean': $types[] = $valueType->toBoolean(); break; case 'int': case 'integer': $types[] = $valueType->toInteger(); break; case 'float': case 'double': $types[] = $valueType->toFloat(); break; case 'string': $types[] = $valueType->toString(); break; case 'array': $types[] = $valueType->toArray(); break; case 'object': $types[] = new ObjectType(stdClass::class); break; case 'null': $types[] = new NullType(); break; default: $types[] = new ErrorType(); } } return $this->typeSpecifier->create($value, TypeCombinator::union(...$types), TypeSpecifierContext::createTruthy(), \true, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } getName(), ['sizeof', 'count'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 1) { return null; } if (count($functionCall->getArgs()) > 1) { $mode = $scope->getType($functionCall->getArgs()[1]->value); if ($mode->isSuperTypeOf(new ConstantIntegerType(COUNT_RECURSIVE))->yes()) { return null; } } return $scope->getType($functionCall->getArgs()[0]->value)->getArraySize(); } } getName() === 'intdiv'; } public function getThrowTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, Scope $scope) : ?Type { if (count($funcCall->getArgs()) < 2) { return $functionReflection->getThrowType(); } $valueType = $scope->getType($funcCall->getArgs()[0]->value)->toInteger(); $containsMin = $valueType->isSuperTypeOf(new ConstantIntegerType(PHP_INT_MIN)); $divisorType = $scope->getType($funcCall->getArgs()[1]->value)->toInteger(); if (!$containsMin->no()) { $divisionByMinusOne = $divisorType->isSuperTypeOf(new ConstantIntegerType(-1)); if (!$divisionByMinusOne->no()) { return new ObjectType(ArithmeticError::class); } } $divisionByZero = $divisorType->isSuperTypeOf(new ConstantIntegerType(0)); if (!$divisionByZero->no()) { return new ObjectType(DivisionByZeroError::class); } return null; } } getName(), ['addslashes', 'addcslashes', 'escapeshellarg', 'escapeshellcmd', 'htmlspecialchars', 'htmlentities', 'urlencode', 'urldecode', 'preg_quote', 'rawurlencode', 'rawurldecode'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) === 0) { return null; } $argType = $scope->getType($args[0]->value); if ($argType->isNonFalsyString()->yes()) { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($argType->isNonEmptyString()->yes()) { return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]); } return new StringType(); } } getName(), ['class_implements', 'class_uses', 'class_parents'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) < 1) { return null; } $firstArgType = $scope->getType($args[0]->value); $autoload = TrinaryLogic::createYes(); if (isset($args[1])) { $autoload = $scope->getType($args[1]->value)->isTrue(); } $isObject = $firstArgType->isObject(); $variant = ParametersAcceptorSelector::selectFromArgs($scope, $args, $functionReflection->getVariants()); if ($isObject->yes()) { return TypeCombinator::remove($variant->getReturnType(), new ConstantBooleanType(\false)); } $isClassStringOrObject = (new UnionType([new ObjectWithoutClassType(), new ClassStringType()]))->isSuperTypeOf($firstArgType); if ($isClassStringOrObject->yes()) { if ($autoload->yes()) { return TypeUtils::toBenevolentUnion($variant->getReturnType()); } return $variant->getReturnType(); } if ($firstArgType->isClassStringType()->no()) { return new ConstantBooleanType(\false); } return null; } } arrayFilterFunctionReturnTypeHelper = $arrayFilterFunctionReturnTypeHelper; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_filter'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $arrayArg = $functionCall->getArgs()[0]->value ?? null; $callbackArg = $functionCall->getArgs()[1]->value ?? null; $flagArg = $functionCall->getArgs()[2]->value ?? null; return $this->arrayFilterFunctionReturnTypeHelper->getType($scope, $arrayArg, $callbackArg, $flagArg); } } getName() === 'range'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } $startType = $scope->getType($functionCall->getArgs()[0]->value); $endType = $scope->getType($functionCall->getArgs()[1]->value); $stepType = count($functionCall->getArgs()) >= 3 ? $scope->getType($functionCall->getArgs()[2]->value) : new ConstantIntegerType(1); $constantReturnTypes = []; $startConstants = $startType->getConstantScalarTypes(); foreach ($startConstants as $startConstant) { if (!$startConstant instanceof ConstantIntegerType && !$startConstant instanceof ConstantFloatType && !$startConstant instanceof ConstantStringType) { continue; } $endConstants = $endType->getConstantScalarTypes(); foreach ($endConstants as $endConstant) { if (!$endConstant instanceof ConstantIntegerType && !$endConstant instanceof ConstantFloatType && !$endConstant instanceof ConstantStringType) { continue; } $stepConstants = $stepType->getConstantScalarTypes(); foreach ($stepConstants as $stepConstant) { if (!$stepConstant instanceof ConstantIntegerType && !$stepConstant instanceof ConstantFloatType) { continue; } try { $rangeValues = @range($startConstant->getValue(), $endConstant->getValue(), $stepConstant->getValue()); } catch (ValueError $e) { continue; } // @phpstan-ignore function.alreadyNarrowedType if (!is_array($rangeValues)) { continue; } if (count($rangeValues) > self::RANGE_LENGTH_THRESHOLD) { if ($startConstant instanceof ConstantIntegerType && $endConstant instanceof ConstantIntegerType && $stepConstant instanceof ConstantIntegerType) { if ($startConstant->getValue() > $endConstant->getValue()) { $tmp = $startConstant; $startConstant = $endConstant; $endConstant = $tmp; } return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(new ArrayType(new IntegerType(), IntegerRangeType::fromInterval($startConstant->getValue(), $endConstant->getValue())), new NonEmptyArrayType())); } if ($stepType->isFloat()->yes()) { return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(new ArrayType(new IntegerType(), new FloatType()), new NonEmptyArrayType())); } return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(new ArrayType(new IntegerType(), TypeCombinator::union($startConstant->generalize(GeneralizePrecision::moreSpecific()), $endConstant->generalize(GeneralizePrecision::moreSpecific()), $stepType->generalize(GeneralizePrecision::moreSpecific()))), new NonEmptyArrayType())); } $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach ($rangeValues as $value) { $arrayBuilder->setOffsetValueType(null, $scope->getTypeFromValue($value)); } $constantReturnTypes[] = $arrayBuilder->getArray(); } } } if (count($constantReturnTypes) > 0) { return TypeCombinator::union(...$constantReturnTypes); } $argType = TypeCombinator::union($startType, $endType); $isInteger = $argType->isInteger()->yes(); $isStepInteger = $stepType->isInteger()->yes(); if ($isInteger && $isStepInteger) { if ($argType instanceof IntegerRangeType) { return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $argType)); } return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new IntegerType())); } if ($argType->isFloat()->yes()) { return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new FloatType())); } $numberType = new UnionType([new IntegerType(), new FloatType()]); $isNumber = $numberType->isSuperTypeOf($argType)->yes(); $isNumericString = $argType->isNumericString()->yes(); if ($isNumber || $isNumericString) { return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $numberType)); } if ($argType->isString()->yes()) { return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())); } return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new BenevolentUnionType([new IntegerType(), new FloatType(), new StringType()]))); } } getName(), ['implode', 'join'], \true); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : Type { $args = $functionCall->getArgs(); if (count($args) === 1) { $argType = $scope->getType($args[0]->value); if ($argType->isArray()->yes()) { return $this->implode($argType, new ConstantStringType('')); } } if (count($args) !== 2) { return new StringType(); } $separatorType = $scope->getType($args[0]->value); $arrayType = $scope->getType($args[1]->value); return $this->implode($arrayType, $separatorType); } private function implode(Type $arrayType, Type $separatorType) : Type { if (count($arrayType->getConstantArrays()) > 0 && count($separatorType->getConstantStrings()) > 0) { $result = []; foreach ($separatorType->getConstantStrings() as $separator) { foreach ($arrayType->getConstantArrays() as $constantArray) { $constantType = $this->inferConstantType($constantArray, $separator); if ($constantType !== null) { $result[] = $constantType; continue; } $result = []; break 2; } } if (count($result) > 0) { return TypeCombinator::union(...$result); } } $accessoryTypes = []; $valueTypeAsString = $arrayType->getIterableValueType()->toString(); if ($arrayType->isIterableAtLeastOnce()->yes()) { if ($valueTypeAsString->isNonFalsyString()->yes() || $separatorType->isNonFalsyString()->yes()) { $accessoryTypes[] = new AccessoryNonFalsyStringType(); } elseif ($valueTypeAsString->isNonEmptyString()->yes() || $separatorType->isNonEmptyString()->yes()) { $accessoryTypes[] = new AccessoryNonEmptyStringType(); } } // implode is one of the four functions that can produce literal strings as blessed by the original RFC: wiki.php.net/rfc/is_literal if ($arrayType->getIterableValueType()->isLiteralString()->yes() && $separatorType->isLiteralString()->yes()) { $accessoryTypes[] = new AccessoryLiteralStringType(); } if ($valueTypeAsString->isLowercaseString()->yes() && $separatorType->isLowercaseString()->yes()) { $accessoryTypes[] = new AccessoryLowercaseStringType(); } if ($valueTypeAsString->isUppercaseString()->yes() && $separatorType->isUppercaseString()->yes()) { $accessoryTypes[] = new AccessoryUppercaseStringType(); } if (count($accessoryTypes) > 0) { $accessoryTypes[] = new StringType(); return new IntersectionType($accessoryTypes); } return new StringType(); } private function inferConstantType(ConstantArrayType $arrayType, ConstantStringType $separatorType) : ?Type { $strings = []; foreach ($arrayType->getAllArrays() as $array) { $valueTypes = $array->getValueTypes(); $arrayValues = []; $combinationsCount = 1; foreach ($valueTypes as $valueType) { $constScalars = $valueType->getConstantScalarValues(); if (count($constScalars) === 0) { return null; } $arrayValues[] = $constScalars; $combinationsCount *= count($constScalars); } if ($combinationsCount > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return null; } $combinations = CombinationsHelper::combinations($arrayValues); foreach ($combinations as $combination) { $strings[] = new ConstantStringType(implode($separatorType->getValue(), $combination)); } } if (count($strings) > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return null; } return TypeCombinator::union(...$strings); } } phpVersion = $phpVersion; } public function isMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === 'sub' && in_array($methodReflection->getDeclaringClass()->getName(), [DateTime::class, DateTimeImmutable::class], \true); } public function getThrowTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { if (count($methodCall->getArgs()) === 0) { return null; } if (!$this->phpVersion->hasDateTimeExceptions()) { return null; } return new ObjectType('DateInvalidOperationException'); } } ['cryptographic' => \false, 'possiblyFalse' => \false, 'binary' => 2], 'hash_file' => ['cryptographic' => \false, 'possiblyFalse' => \true, 'binary' => 2], 'hash_hkdf' => ['cryptographic' => \true, 'possiblyFalse' => \false, 'binary' => \true], 'hash_hmac' => ['cryptographic' => \true, 'possiblyFalse' => \false, 'binary' => 3], 'hash_hmac_file' => ['cryptographic' => \true, 'possiblyFalse' => \true, 'binary' => 3], 'hash_pbkdf2' => ['cryptographic' => \true, 'possiblyFalse' => \false, 'binary' => 5]]; private const NON_CRYPTOGRAPHIC_ALGORITHMS = ['adler32', 'crc32', 'crc32b', 'crc32c', 'fnv132', 'fnv1a32', 'fnv164', 'fnv1a64', 'joaat', 'murmur3a', 'murmur3c', 'murmur3f', 'xxh32', 'xxh64', 'xxh3', 'xxh128']; /** @var array */ private $hashAlgorithms; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; $this->hashAlgorithms = hash_algos(); } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { $name = strtolower($functionReflection->getName()); return isset(self::SUPPORTED_FUNCTIONS[$name]); } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $functionData = self::SUPPORTED_FUNCTIONS[strtolower($functionReflection->getName())]; if (is_bool($functionData['binary'])) { $binaryType = new ConstantBooleanType($functionData['binary']); } elseif (isset($functionCall->getArgs()[$functionData['binary']])) { $binaryType = $scope->getType($functionCall->getArgs()[$functionData['binary']]->value); } else { $binaryType = new ConstantBooleanType(\false); } $stringTypes = [new StringType(), new AccessoryNonFalsyStringType()]; if ($binaryType->isFalse()->yes()) { $stringTypes[] = new AccessoryLowercaseStringType(); } $stringReturnType = new IntersectionType($stringTypes); $algorithmType = $scope->getType($functionCall->getArgs()[0]->value); $constantAlgorithmTypes = $algorithmType->getConstantStrings(); if (count($constantAlgorithmTypes) === 0) { if ($functionData['possiblyFalse'] || !$this->phpVersion->throwsValueErrorForInternalFunctions()) { return TypeUtils::toBenevolentUnion(TypeCombinator::union($stringReturnType, new ConstantBooleanType(\false))); } return $stringReturnType; } $neverType = new NeverType(); $falseType = new ConstantBooleanType(\false); $invalidAlgorithmType = $this->phpVersion->throwsValueErrorForInternalFunctions() ? $neverType : $falseType; $returnTypes = array_map(function (ConstantStringType $type) use($functionData, $stringReturnType, $invalidAlgorithmType) { $algorithm = strtolower($type->getValue()); if (!in_array($algorithm, $this->hashAlgorithms, \true)) { return $invalidAlgorithmType; } if ($functionData['cryptographic'] && in_array($algorithm, self::NON_CRYPTOGRAPHIC_ALGORITHMS, \true)) { return $invalidAlgorithmType; } return $stringReturnType; }, $constantAlgorithmTypes); $returnType = TypeCombinator::union(...$returnTypes); if ($functionData['possiblyFalse'] && !$neverType->isSuperTypeOf($returnType)->yes()) { $returnType = TypeCombinator::union($returnType, $falseType); } return $returnType; } } getName() === 'key'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $iterableAtLeastOnce = $argType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new NullType(); } $keyType = $argType->getIterableKeyType(); if ($iterableAtLeastOnce->yes()) { return $keyType; } return TypeCombinator::union($keyType, new NullType()); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'mb_convert_encoding'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (!isset($functionCall->getArgs()[0])) { return null; } $argType = $scope->getType($functionCall->getArgs()[0]->value); $initialReturnType = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants())->getReturnType(); $result = TypeCombinator::intersect($initialReturnType, $this->generalizeStringType($argType)); if ($result instanceof NeverType) { $result = $initialReturnType; } if ($this->phpVersion->throwsValueErrorForInternalFunctions()) { if (!isset($functionCall->getArgs()[2])) { return TypeCombinator::remove($result, new ConstantBooleanType(\false)); } $fromEncodingArgType = $scope->getType($functionCall->getArgs()[2]->value); $returnFalseIfCannotDetectEncoding = \false; if (!$fromEncodingArgType->isArray()->no()) { $constantArrays = $fromEncodingArgType->getConstantArrays(); if (count($constantArrays) > 0) { foreach ($constantArrays as $constantArray) { if (count($constantArray->getValueTypes()) > 1) { $returnFalseIfCannotDetectEncoding = \true; break; } } } else { $returnFalseIfCannotDetectEncoding = \true; } } if (!$returnFalseIfCannotDetectEncoding && !$fromEncodingArgType->isString()->no()) { $constantStrings = $fromEncodingArgType->getConstantStrings(); if (count($constantStrings) > 0) { foreach ($constantStrings as $constantString) { if (str_contains($constantString->getValue(), ',')) { $returnFalseIfCannotDetectEncoding = \true; break; } } } else { $returnFalseIfCannotDetectEncoding = \true; } } if (!$returnFalseIfCannotDetectEncoding) { return TypeCombinator::remove($result, new ConstantBooleanType(\false)); } } return TypeCombinator::union($result, new ConstantBooleanType(\false)); } public function generalizeStringType(Type $type) : Type { if ($type instanceof UnionType) { return $type->traverse([$this, 'generalizeStringType']); } if ($type->isString()->yes()) { return new StringType(); } $constantArrays = $type->getConstantArrays(); if (count($constantArrays) > 0) { $types = []; foreach ($constantArrays as $constantArray) { $types[] = $constantArray->traverse([$this, 'generalizeStringType']); } return TypeCombinator::union(...$types); } if ($type->isArray()->yes()) { $newArrayType = new ArrayType($type->getIterableKeyType(), $this->generalizeStringType($type->getIterableValueType())); if ($type->isIterableAtLeastOnce()->yes()) { $newArrayType = TypeCombinator::intersect($newArrayType, new NonEmptyArrayType()); } if ($type->isList()->yes()) { $newArrayType = TypeCombinator::intersect($newArrayType, new AccessoryArrayListType()); } return $newArrayType; } return $type; } } getName()), ['parse_str', 'mb_parse_str'], \true) && $parameter->getName() === 'result'; } public function getParameterOutTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, ParameterReflection $parameter, Scope $scope) : ?Type { $args = $funcCall->getArgs(); if (count($args) < 1) { return null; } $stringType = $scope->getType($args[0]->value); $accessory = []; if ($stringType->isLowercaseString()->yes()) { $accessory[] = new AccessoryLowercaseStringType(); } if ($stringType->isUppercaseString()->yes()) { $accessory[] = new AccessoryUppercaseStringType(); } if (count($accessory) > 0) { $accessory[] = new StringType(); $valueType = new IntersectionType($accessory); } else { $valueType = new StringType(); } return new ArrayType(new UnionType([new StringType(), new IntegerType()]), new UnionType([new ArrayType(new MixedType(), new MixedType(\true)), $valueType])); } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_column'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $numArgs = count($functionCall->getArgs()); if ($numArgs < 2) { return null; } $arrayType = $scope->getType($functionCall->getArgs()[0]->value); $columnType = $scope->getType($functionCall->getArgs()[1]->value); $indexType = $numArgs >= 3 ? $scope->getType($functionCall->getArgs()[2]->value) : null; $constantArrayTypes = $arrayType->getConstantArrays(); if (count($constantArrayTypes) === 1) { $type = $this->handleConstantArray($constantArrayTypes[0], $columnType, $indexType, $scope); if ($type !== null) { return $type; } } return $this->handleAnyArray($arrayType, $columnType, $indexType, $scope); } private function handleAnyArray(Type $arrayType, Type $columnType, ?Type $indexType, Scope $scope) : Type { $iterableAtLeastOnce = $arrayType->isIterableAtLeastOnce(); if ($iterableAtLeastOnce->no()) { return new ConstantArrayType([], []); } $iterableValueType = $arrayType->getIterableValueType(); $returnValueType = $this->getOffsetOrProperty($iterableValueType, $columnType, $scope, \false); if ($returnValueType === null) { $returnValueType = $this->getOffsetOrProperty($iterableValueType, $columnType, $scope, \true); $iterableAtLeastOnce = TrinaryLogic::createMaybe(); if ($returnValueType === null) { throw new ShouldNotHappenException(); } } if ($returnValueType instanceof NeverType) { return new ConstantArrayType([], []); } if ($indexType !== null) { $type = $this->getOffsetOrProperty($iterableValueType, $indexType, $scope, \false); if ($type !== null) { $returnKeyType = $type; } else { $type = $this->getOffsetOrProperty($iterableValueType, $indexType, $scope, \true); if ($type !== null) { $returnKeyType = TypeCombinator::union($type, new IntegerType()); } else { $returnKeyType = new IntegerType(); } } } else { $returnKeyType = new IntegerType(); } $returnType = new ArrayType($this->castToArrayKeyType($returnKeyType), $returnValueType); if ($iterableAtLeastOnce->yes()) { $returnType = TypeCombinator::intersect($returnType, new NonEmptyArrayType()); } if ($indexType === null) { $returnType = AccessoryArrayListType::intersectWith($returnType); } return $returnType; } private function handleConstantArray(ConstantArrayType $arrayType, Type $columnType, ?Type $indexType, Scope $scope) : ?Type { $builder = ConstantArrayTypeBuilder::createEmpty(); foreach ($arrayType->getValueTypes() as $i => $iterableValueType) { $valueType = $this->getOffsetOrProperty($iterableValueType, $columnType, $scope, \false); if ($valueType === null) { return null; } if ($valueType instanceof NeverType) { continue; } if ($indexType !== null) { $type = $this->getOffsetOrProperty($iterableValueType, $indexType, $scope, \false); if ($type !== null) { $keyType = $type; } else { $type = $this->getOffsetOrProperty($iterableValueType, $indexType, $scope, \true); if ($type !== null) { $keyType = TypeCombinator::union($type, new IntegerType()); } else { $keyType = null; } } } else { $keyType = null; } if ($keyType !== null) { $keyType = $this->castToArrayKeyType($keyType); } $builder->setOffsetValueType($keyType, $valueType, $arrayType->isOptionalKey($i)); } return $builder->getArray(); } private function getOffsetOrProperty(Type $type, Type $offsetOrProperty, Scope $scope, bool $allowMaybe) : ?Type { $offsetIsNull = $offsetOrProperty->isNull(); if ($offsetIsNull->yes()) { return $type; } $returnTypes = []; if ($offsetIsNull->maybe()) { $returnTypes[] = $type; } if (!$type->canAccessProperties()->no()) { $propertyTypes = $offsetOrProperty->getConstantStrings(); if ($propertyTypes === []) { return new MixedType(); } foreach ($propertyTypes as $propertyType) { $propertyName = $propertyType->getValue(); $hasProperty = $type->hasProperty($propertyName); if ($hasProperty->maybe()) { return $allowMaybe ? new MixedType() : null; } if (!$hasProperty->yes()) { continue; } $returnTypes[] = $type->getProperty($propertyName, $scope)->getReadableType(); } } if ($type->isOffsetAccessible()->yes()) { $hasOffset = $type->hasOffsetValueType($offsetOrProperty); if (!$allowMaybe && $hasOffset->maybe()) { return null; } if (!$hasOffset->no()) { $returnTypes[] = $type->getOffsetValueType($offsetOrProperty); } } if ($returnTypes === []) { return new NeverType(); } return TypeCombinator::union(...$returnTypes); } private function castToArrayKeyType(Type $type) : Type { $isArray = $type->isArray(); if ($isArray->yes()) { return $this->phpVersion->throwsTypeErrorForInternalFunctions() ? new NeverType() : new IntegerType(); } if ($isArray->no()) { return $type->toArrayKey(); } $withoutArrayType = TypeCombinator::remove($type, new ArrayType(new MixedType(), new MixedType())); $keyType = $withoutArrayType->toArrayKey(); if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return $keyType; } return TypeCombinator::union($keyType, new IntegerType()); } } isAFunctionTypeSpecifyingHelper = $isAFunctionTypeSpecifyingHelper; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return strtolower($functionReflection->getName()) === 'is_subclass_of' && !$context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { if (!$context->true() || count($node->getArgs()) < 2) { return new SpecifiedTypes(); } $objectOrClassType = $scope->getType($node->getArgs()[0]->value); $classType = $scope->getType($node->getArgs()[1]->value); $allowStringType = isset($node->getArgs()[2]) ? $scope->getType($node->getArgs()[2]->value) : new ConstantBooleanType(\true); $allowString = !$allowStringType->equals(new ConstantBooleanType(\false)); // prevent false-positives in IsAFunctionTypeSpecifyingHelper if ($objectOrClassType instanceof GenericClassStringType && $classType instanceof GenericClassStringType) { return new SpecifiedTypes([], []); } $resultType = $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, \false); // prevent false-positives in IsAFunctionTypeSpecifyingHelper if ($classType->getConstantStrings() === [] && $resultType->isSuperTypeOf($objectOrClassType)->yes()) { return new SpecifiedTypes([], []); } return $this->typeSpecifier->create($node->getArgs()[0]->value, $resultType, $context, \false, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_combine'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { if (count($functionCall->getArgs()) < 2) { return null; } $firstArg = $functionCall->getArgs()[0]->value; $secondArg = $functionCall->getArgs()[1]->value; $keysParamType = $scope->getType($firstArg); $valuesParamType = $scope->getType($secondArg); if ($keysParamType instanceof ConstantArrayType && $valuesParamType instanceof ConstantArrayType) { $keyTypes = $keysParamType->getValueTypes(); $valueTypes = $valuesParamType->getValueTypes(); if (count($keyTypes) !== count($valueTypes)) { if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return new NeverType(); } return new ConstantBooleanType(\false); } $keyTypes = $this->sanitizeConstantArrayKeyTypes($keyTypes); if ($keyTypes !== null) { $builder = ConstantArrayTypeBuilder::createEmpty(); foreach ($keyTypes as $i => $keyType) { $valueType = $valueTypes[$i]; $builder->setOffsetValueType($keyType, $valueType); } return $builder->getArray(); } } if ($keysParamType->isArray()->yes()) { $itemType = $keysParamType->getIterableValueType(); if ($itemType->isInteger()->no()) { if ($itemType->toString() instanceof ErrorType) { return new NeverType(); } $keyType = $itemType->toString(); } else { $keyType = $itemType; } } else { $keyType = new MixedType(); } $arrayType = new ArrayType($keyType, $valuesParamType->isArray()->yes() ? $valuesParamType->getIterableValueType() : new MixedType()); if ($keysParamType->isIterableAtLeastOnce()->yes() && $valuesParamType->isIterableAtLeastOnce()->yes()) { $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } if ($this->phpVersion->throwsTypeErrorForInternalFunctions()) { return $arrayType; } if ($firstArg instanceof Variable && $secondArg instanceof Variable && $firstArg->name === $secondArg->name) { return $arrayType; } return new UnionType([$arrayType, new ConstantBooleanType(\false)]); } /** * @param array $types * * @return array|null */ private function sanitizeConstantArrayKeyTypes(array $types) : ?array { $sanitizedTypes = []; foreach ($types as $type) { if ($type->isInteger()->no() && !$type->toString() instanceof ErrorType) { $type = $type->toString(); } if (!$type instanceof ConstantIntegerType && !$type instanceof ConstantStringType) { return null; } $sanitizedTypes[] = $type; } return $sanitizedTypes; } } phpVersion = $phpVersion; } public function isFunctionSupported(FunctionReflection $functionReflection) : bool { return $functionReflection->getName() === 'array_intersect_key'; } public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope) : ?Type { $args = $functionCall->getArgs(); if (count($args) === 0) { return null; } $argTypes = []; foreach ($args as $arg) { $argType = $scope->getType($arg->value); if ($arg->unpack) { $argTypes[] = $argType->getIterableValueType(); continue; } $argTypes[] = $argType; } $firstArrayType = $argTypes[0]; $otherArraysType = TypeCombinator::union(...array_slice($argTypes, 1)); $onlyOneArrayGiven = count($argTypes) === 1; if ($firstArrayType->isArray()->no() || !$onlyOneArrayGiven && $otherArraysType->isArray()->no()) { return $this->phpVersion->arrayFunctionsReturnNullWithNonArray() ? new NullType() : new NeverType(); } if ($onlyOneArrayGiven) { return $firstArrayType; } return $firstArrayType->intersectKeyArray($otherArraysType); } } = 2) { $fqcn = ltrim($classConstParts[0], '\\'); if ($fqcn === '') { return null; } $classConstName = new FullyQualified($fqcn); if ($classConstName->isSpecialClassName()) { $classConstName = new Name($classConstName->toString()); } return new ClassConstFetch($classConstName, new Identifier($classConstParts[1])); } return new ConstFetch(new FullyQualified($constantName)); } } getName()) === 'array_search' && $context->true(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context) : SpecifiedTypes { $arrayArg = $node->getArgs()[1]->value ?? null; if ($arrayArg === null) { return new SpecifiedTypes(); } return $this->typeSpecifier->create($arrayArg, TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new NonEmptyArrayType()), $context, \false, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } } regexShapeMatcher = $regexShapeMatcher; } public function setTypeSpecifier(TypeSpecifier $typeSpecifier) : void { $this->typeSpecifier = $typeSpecifier; } public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context) : bool { return in_array(strtolower($functionReflection->getName()), ['preg_match', 'preg_match_all'], \true) && !$context->null(); } public function specifyTypes(FunctionReflection $functionReflection, FuncCall $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 = null; if ($flagsArg !== null) { $flagsType = $scope->getType($flagsArg->value); } if ($functionReflection->getName() === 'preg_match') { $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createFromBoolean($context->true()), $scope); } else { $matchedType = $this->regexShapeMatcher->matchAllExpr($patternArg->value, $flagsType, TrinaryLogic::createFromBoolean($context->true()), $scope); } if ($matchedType === null) { return new SpecifiedTypes(); } $overwrite = \false; if ($context->false()) { $overwrite = \true; $context = $context->negate(); } return $this->typeSpecifier->create($matchesArg->value, $matchedType, $context, $overwrite, $scope, $node); } } getSubtractedType()); } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return sprintf('$this(%s)', $this->getStaticObjectType()->describe($level)); } public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof self) { return $this->getStaticObjectType()->isSuperTypeOfWithReason($type); } if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } $parent = new parent($this->getClassReflection(), $this->getSubtractedType()); return $parent->isSuperTypeOfWithReason($type)->and(\PHPStan\Type\IsSuperTypeOfResult::createMaybe()); } public function changeSubtractedType(?\PHPStan\Type\Type $subtractedType) : \PHPStan\Type\Type { $type = parent::changeSubtractedType($subtractedType); if ($type instanceof parent) { return new self($type->getClassReflection(), $subtractedType); } return $type; } public function traverse(callable $cb) : \PHPStan\Type\Type { $subtractedType = $this->getSubtractedType() !== null ? $cb($this->getSubtractedType()) : null; if ($subtractedType !== $this->getSubtractedType()) { return new self($this->getClassReflection(), $subtractedType); } return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { if ($this->getSubtractedType() === null) { return $this; } return new self($this->getClassReflection()); } public function toPhpDocNode() : TypeNode { return new ThisTypeNode(); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if ($reflectionProvider->hasClass($properties['baseClass'])) { return new self($reflectionProvider->getClass($properties['baseClass']), $properties['subtractedType'] ?? null); } return new \PHPStan\Type\ErrorType(); } } getTypes() as $type) { $result = $getType($type); if ($result instanceof \PHPStan\Type\ErrorType) { continue; } $resultTypes[] = $result; } if (count($resultTypes) === 0) { return new \PHPStan\Type\ErrorType(); } return \PHPStan\Type\TypeUtils::toBenevolentUnion(\PHPStan\Type\TypeCombinator::union(...$resultTypes)); } protected function pickFromTypes(callable $getValues, callable $criteria) : array { $values = []; foreach ($this->getTypes() as $type) { $innerValues = $getValues($type); if ($innerValues === [] && $criteria($type)) { return []; } foreach ($innerValues as $innerType) { $values[] = $innerType; } } return $values; } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { $types = []; foreach ($this->getTypes() as $innerType) { $valueType = $innerType->getOffsetValueType($offsetType); if ($valueType instanceof \PHPStan\Type\ErrorType) { continue; } $types[] = $valueType; } if (count($types) === 0) { return new \PHPStan\Type\ErrorType(); } return \PHPStan\Type\TypeUtils::toBenevolentUnion(\PHPStan\Type\TypeCombinator::union(...$types)); } protected function unionResults(callable $getResult) : TrinaryLogic { return TrinaryLogic::createNo()->lazyOr($this->getTypes(), $getResult); } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { $result = \PHPStan\Type\AcceptsResult::createNo(); foreach ($this->getTypes() as $innerType) { $result = $result->or($acceptingType->acceptsWithReason($innerType, $strictTypes)); } return $result; } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap { $types = TemplateTypeMap::createEmpty(); foreach ($this->getTypes() as $type) { $types = $types->benevolentUnion($type->inferTemplateTypes($receivedType)); } return $types; } public function inferTemplateTypesOn(\PHPStan\Type\Type $templateType) : TemplateTypeMap { $types = TemplateTypeMap::createEmpty(); foreach ($this->getTypes() as $type) { $types = $types->benevolentUnion($templateType->inferTemplateTypes($type)); } return $types; } public function traverse(callable $cb) : \PHPStan\Type\Type { $types = []; $changed = \false; foreach ($this->getTypes() as $type) { $newType = $cb($type); if ($type !== $newType) { $changed = \true; } $types[] = $newType; } if ($changed) { return \PHPStan\Type\TypeUtils::toBenevolentUnion(\PHPStan\Type\TypeCombinator::union(...$types)); } return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { $types = []; $changed = \false; if (!$right instanceof \PHPStan\Type\UnionType) { return $this; } if (count($this->getTypes()) !== count($right->getTypes())) { return $this; } foreach ($this->getSortedTypes() as $i => $leftType) { $rightType = $right->getSortedTypes()[$i]; $newType = $cb($leftType, $rightType); if ($leftType !== $newType) { $changed = \true; } $types[] = $newType; } if ($changed) { return \PHPStan\Type\TypeUtils::toBenevolentUnion(\PHPStan\Type\TypeCombinator::union(...$types)); } return $this; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['types']); } } */ private $extensions; /** * @param array $extensions */ public function __construct(array $extensions) { $this->extensions = $extensions; } /** * @return array */ public function getExtensions() : array { return $this->extensions; } } getName(); } return $selfClass !== null ? new \PHPStan\Type\ObjectType($selfClass) : new \PHPStan\Type\ErrorType(); case 'parent': $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (is_string($selfClass)) { if ($reflectionProvider->hasClass($selfClass)) { $selfClass = $reflectionProvider->getClass($selfClass); } else { $selfClass = null; } } if ($selfClass !== null) { if ($selfClass->getParentClass() !== null) { return new \PHPStan\Type\ObjectType($selfClass->getParentClass()->getName()); } } return new \PHPStan\Type\NonexistentParentClassType(); case 'static': $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); if (is_string($selfClass)) { if ($reflectionProvider->hasClass($selfClass)) { $selfClass = $reflectionProvider->getClass($selfClass); } else { $selfClass = null; } } if ($selfClass !== null) { return new \PHPStan\Type\StaticType($selfClass); } return new \PHPStan\Type\ErrorType(); case 'null': return new \PHPStan\Type\NullType(); case 'never': return new \PHPStan\Type\NonAcceptingNeverType(); default: return new \PHPStan\Type\ObjectType($typeString); } } /** @api *@param ClassReflection|string|null $selfClass */ public static function decideTypeFromReflection(?ReflectionType $reflectionType, ?\PHPStan\Type\Type $phpDocType = null, $selfClass = null, bool $isVariadic = \false) : \PHPStan\Type\Type { if ($reflectionType === null) { if ($isVariadic && $phpDocType instanceof \PHPStan\Type\ArrayType) { $phpDocType = $phpDocType->getItemType(); } return $phpDocType ?? new \PHPStan\Type\MixedType(); } if ($reflectionType instanceof ReflectionUnionType) { $type = \PHPStan\Type\TypeCombinator::union(...array_map(static function (ReflectionType $type) use($selfClass) : \PHPStan\Type\Type { return self::decideTypeFromReflection($type, null, $selfClass, \false); }, $reflectionType->getTypes())); return self::decideType($type, $phpDocType); } if ($reflectionType instanceof ReflectionIntersectionType) { $types = []; foreach ($reflectionType->getTypes() as $innerReflectionType) { $innerType = self::decideTypeFromReflection($innerReflectionType, null, $selfClass, \false); if (!$innerType->isObject()->yes()) { return new \PHPStan\Type\NeverType(); } $types[] = $innerType; } return self::decideType(\PHPStan\Type\TypeCombinator::intersect(...$types), $phpDocType); } if (!$reflectionType instanceof ReflectionNamedType) { throw new ShouldNotHappenException(sprintf('Unexpected type: %s', get_class($reflectionType))); } $reflectionTypeString = $reflectionType->getName(); $loweredReflectionTypeString = strtolower($reflectionTypeString); if (str_ends_with($loweredReflectionTypeString, '\\object')) { $reflectionTypeString = 'object'; } elseif (str_ends_with($loweredReflectionTypeString, '\\mixed')) { $reflectionTypeString = 'mixed'; } elseif (str_ends_with($loweredReflectionTypeString, '\\true')) { $reflectionTypeString = 'true'; } elseif (str_ends_with($loweredReflectionTypeString, '\\false')) { $reflectionTypeString = 'false'; } elseif (str_ends_with($loweredReflectionTypeString, '\\null')) { $reflectionTypeString = 'null'; } elseif (str_ends_with($loweredReflectionTypeString, '\\never')) { $reflectionTypeString = 'never'; } $type = self::getTypeObjectFromTypehint($reflectionTypeString, $selfClass); if ($reflectionType->allowsNull()) { $type = \PHPStan\Type\TypeCombinator::addNull($type); } elseif ($phpDocType !== null) { $phpDocType = \PHPStan\Type\TypeCombinator::removeNull($phpDocType); } return self::decideType($type, $phpDocType); } public static function decideType(\PHPStan\Type\Type $type, ?\PHPStan\Type\Type $phpDocType = null) : \PHPStan\Type\Type { if ($type instanceof \PHPStan\Type\BenevolentUnionType) { return $type; } if ($phpDocType !== null && !$phpDocType instanceof \PHPStan\Type\ErrorType) { if ($phpDocType instanceof \PHPStan\Type\NeverType && $phpDocType->isExplicit()) { return $phpDocType; } if ($type instanceof \PHPStan\Type\MixedType && !$type->isExplicitMixed() && $phpDocType->isVoid()->yes()) { return $phpDocType; } if (\PHPStan\Type\TypeCombinator::removeNull($type) instanceof \PHPStan\Type\IterableType) { if ($phpDocType instanceof \PHPStan\Type\UnionType) { $innerTypes = []; foreach ($phpDocType->getTypes() as $innerType) { if ($innerType instanceof \PHPStan\Type\ArrayType) { $innerTypes[] = new \PHPStan\Type\IterableType($innerType->getIterableKeyType(), $innerType->getItemType()); } else { $innerTypes[] = $innerType; } } $phpDocType = new \PHPStan\Type\UnionType($innerTypes); } elseif ($phpDocType instanceof \PHPStan\Type\ArrayType) { $phpDocType = new \PHPStan\Type\IterableType($phpDocType->getKeyType(), $phpDocType->getItemType()); } } if ($type->isCallable()->yes() && $phpDocType->isCallable()->yes() || (!$phpDocType instanceof \PHPStan\Type\NeverType || $type instanceof \PHPStan\Type\MixedType && !$type->isExplicitMixed()) && $type->isSuperTypeOf(TemplateTypeHelper::resolveToBounds($phpDocType))->yes()) { $resultType = $phpDocType; } else { $resultType = $type; } if ($type instanceof \PHPStan\Type\UnionType) { $addToUnionTypes = []; foreach ($type->getTypes() as $innerType) { if (!$innerType->isSuperTypeOf($resultType)->no()) { continue; } $addToUnionTypes[] = $innerType; } if (count($addToUnionTypes) > 0) { $type = \PHPStan\Type\TypeCombinator::union($resultType, ...$addToUnionTypes); } else { $type = $resultType; } } elseif (\PHPStan\Type\TypeCombinator::containsNull($type)) { $type = \PHPStan\Type\TypeCombinator::addNull($resultType); } else { $type = $resultType; } } return $type; } } initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflectionSourceStubber = $reflectionSourceStubber; $this->reflector = $reflector; $this->parser = $parser; } /** * @param Closure(): mixed $closure */ public function fromClosureObject(Closure $closure) : \PHPStan\Type\ClosureType { $stubData = $this->reflectionSourceStubber->generateFunctionStubFromReflection(new ReflectionFunction($closure)); if ($stubData === null) { throw new ShouldNotHappenException('Closure reflection not found.'); } $source = $stubData->getStub(); $source = str_replace('{closure}', 'foo', $source); $locatedSource = new LocatedSource($source, '{closure}', $stubData->getFileName()); $find = new FindReflectionsInTree(new NodeToReflection()); $ast = $this->parser->parse($locatedSource->getSource()); if ($ast === null) { throw new ShouldNotHappenException('Closure reflection not found.'); } /** @var list<\PHPStan\BetterReflection\Reflection\ReflectionFunction> $reflections */ $reflections = $find($this->reflector, $ast, new IdentifierType(IdentifierType::IDENTIFIER_FUNCTION), $locatedSource); if (count($reflections) !== 1) { throw new ShouldNotHappenException('Closure reflection not found.'); } $betterReflectionFunction = $reflections[0]; $parameters = array_map(function (BetterReflectionParameter $parameter) { return new class($parameter, $this->initializerExprTypeResolver) implements ParameterReflection { /** * @var BetterReflectionParameter */ private $reflection; /** * @var InitializerExprTypeResolver */ private $initializerExprTypeResolver; public function __construct(BetterReflectionParameter $reflection, InitializerExprTypeResolver $initializerExprTypeResolver) { $this->reflection = $reflection; $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function getName() : string { return $this->reflection->getName(); } public function isOptional() : bool { return $this->reflection->isOptional(); } public function getType() : \PHPStan\Type\Type { return \PHPStan\Type\TypehintHelper::decideTypeFromReflection(ReflectionType::fromTypeOrNull($this->reflection->getType()), null, null, $this->reflection->isVariadic()); } public function passedByReference() : PassedByReference { return $this->reflection->isPassedByReference() ? PassedByReference::createCreatesNewVariable() : PassedByReference::createNo(); } public function isVariadic() : bool { return $this->reflection->isVariadic(); } public function getDefaultValue() : ?\PHPStan\Type\Type { if (!$this->reflection->isDefaultValueAvailable()) { return null; } $defaultExpr = $this->reflection->getDefaultValueExpression(); if ($defaultExpr === null) { return null; } return $this->initializerExprTypeResolver->getType($defaultExpr, InitializerExprContext::fromReflectionParameter(new ReflectionParameter($this->reflection))); } }; }, $betterReflectionFunction->getParameters()); return new \PHPStan\Type\ClosureType($parameters, \PHPStan\Type\TypehintHelper::decideTypeFromReflection(ReflectionType::fromTypeOrNull($betterReflectionFunction->getReturnType())), $betterReflectionFunction->isVariadic()); } } isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult { if ($type instanceof \PHPStan\Type\CompoundType) { return $type->isSubTypeOfWithReason($this); } $thatClassNames = $type->getObjectClassNames(); if ($thatClassNames === []) { return parent::isSuperTypeOfWithReason($type); } $result = \PHPStan\Type\IsSuperTypeOfResult::createNo(); $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); foreach ($thatClassNames as $thatClassName) { if (!$reflectionProvider->hasClass($thatClassName)) { return \PHPStan\Type\IsSuperTypeOfResult::createNo(); } $typeClass = $reflectionProvider->getClass($thatClassName); $result = $result->or(\PHPStan\Type\IsSuperTypeOfResult::createFromBoolean($typeClass->hasNativeMethod('__toString'))); } return $result; } public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult { $thatClassNames = $type->getObjectClassNames(); if ($thatClassNames === []) { return parent::acceptsWithReason($type, $strictTypes); } $result = \PHPStan\Type\AcceptsResult::createNo(); $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); foreach ($thatClassNames as $thatClassName) { if (!$reflectionProvider->hasClass($thatClassName)) { return \PHPStan\Type\AcceptsResult::createNo(); } $typeClass = $reflectionProvider->getClass($thatClassName); $result = $result->or(\PHPStan\Type\AcceptsResult::createFromBoolean($typeClass->hasNativeMethod('__toString'))); } return $result; } } getParameters(); $ourParameters = $ours->getParameters(); $lastParameter = null; foreach ($theirParameters as $theirParameter) { $lastParameter = $theirParameter; } $theirParameterCount = count($theirParameters); $ourParameterCount = count($ourParameters); if ($lastParameter !== null && $lastParameter->isVariadic() && $theirParameterCount < $ourParameterCount) { foreach ($ourParameters as $i => $ourParameter) { if (array_key_exists($i, $theirParameters)) { continue; } $theirParameters[] = $lastParameter; } } $result = \PHPStan\Type\IsSuperTypeOfResult::createYes(); foreach ($theirParameters as $i => $theirParameter) { $parameterDescription = $theirParameter->getName() === '' ? sprintf('#%d', $i + 1) : sprintf('#%d $%s', $i + 1, $theirParameter->getName()); if (!isset($ourParameters[$i])) { if ($theirParameter->isOptional()) { continue; } $accepts = new \PHPStan\Type\IsSuperTypeOfResult(TrinaryLogic::createNo(), [sprintf('Parameter %s of passed callable is required but accepting callable does not have that parameter. It will be called without it.', $parameterDescription)]); $result = $result->and($accepts); continue; } $ourParameter = $ourParameters[$i]; $ourParameterType = $ourParameter->getType(); if ($ourParameter->isOptional() && !$theirParameter->isOptional()) { $accepts = new \PHPStan\Type\IsSuperTypeOfResult(TrinaryLogic::createNo(), [sprintf('Parameter %s of passed callable is required but the parameter of accepting callable is optional. It might be called without it.', $parameterDescription)]); $result = $result->and($accepts); } if ($treatMixedAsAny) { $isSuperType = $theirParameter->getType()->acceptsWithReason($ourParameterType, \true); $isSuperType = new \PHPStan\Type\IsSuperTypeOfResult($isSuperType->result, $isSuperType->reasons); } else { $isSuperType = $theirParameter->getType()->isSuperTypeOfWithReason($ourParameterType); } if ($isSuperType->maybe()) { $verbosity = \PHPStan\Type\VerbosityLevel::getRecommendedLevelByType($theirParameter->getType(), $ourParameterType); $isSuperType = new \PHPStan\Type\IsSuperTypeOfResult($isSuperType->result, array_merge($isSuperType->reasons, [sprintf('Type %s of parameter %s of passed callable needs to be same or wider than parameter type %s of accepting callable.', $theirParameter->getType()->describe($verbosity), $parameterDescription, $ourParameterType->describe($verbosity))])); } $result = $result->and($isSuperType); } if (!$treatMixedAsAny && $theirParameterCount < $ourParameterCount) { $result = $result->and(\PHPStan\Type\IsSuperTypeOfResult::createMaybe()); } $theirReturnType = $theirs->getReturnType(); if ($treatMixedAsAny) { $isReturnTypeSuperType = $ours->getReturnType()->acceptsWithReason($theirReturnType, \true); $isReturnTypeSuperType = new \PHPStan\Type\IsSuperTypeOfResult($isReturnTypeSuperType->result, $isReturnTypeSuperType->reasons); } else { $isReturnTypeSuperType = $ours->getReturnType()->isSuperTypeOfWithReason($theirReturnType); } $pure = $ours->isPure(); if ($pure->yes()) { $result = $result->and(new \PHPStan\Type\IsSuperTypeOfResult($theirs->isPure(), [])); } elseif ($pure->no()) { $result = $result->and(new \PHPStan\Type\IsSuperTypeOfResult($theirs->isPure()->negate(), [])); } return $result->and($isReturnTypeSuperType); } } */ public function getObjectClassNames() : array; /** * @return list */ public function getObjectClassReflections() : array; /** * Returns object type Foo for class-string and 'Foo' (if Foo is a valid class). */ public function getClassStringObjectType() : \PHPStan\Type\Type; /** * Returns object type Foo for class-string, 'Foo' (if Foo is a valid class), * and object type Foo. */ public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type; public function isObject() : TrinaryLogic; public function isEnum() : TrinaryLogic; /** @return list */ public function getArrays() : array; /** @return list */ public function getConstantArrays() : array; /** @return list */ public function getConstantStrings() : array; public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic; /** * This is like accepts() but gives reasons * why the type was not/might not be accepted in some non-intuitive scenarios. * * In PHPStan 2.0 this method will be removed and the return type of accepts() * will change to AcceptsResult. */ public function acceptsWithReason(\PHPStan\Type\Type $type, bool $strictTypes) : \PHPStan\Type\AcceptsResult; public function isSuperTypeOf(\PHPStan\Type\Type $type) : TrinaryLogic; /** * This is like isSuperTypeOf() but gives reasons * why the type was not/might not be accepted in some non-intuitive scenarios. * * In PHPStan 2.0 this method will be removed and the return type of isSuperTypeOf() * will change to IsSuperTypeOfResult. */ public function isSuperTypeOfWithReason(\PHPStan\Type\Type $type) : \PHPStan\Type\IsSuperTypeOfResult; public function equals(\PHPStan\Type\Type $type) : bool; public function describe(\PHPStan\Type\VerbosityLevel $level) : string; public function canAccessProperties() : TrinaryLogic; public function hasProperty(string $propertyName) : TrinaryLogic; /** * @return ExtendedPropertyReflection */ public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection; public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection; public function canCallMethods() : TrinaryLogic; public function hasMethod(string $methodName) : TrinaryLogic; public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection; public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection; public function canAccessConstants() : TrinaryLogic; public function hasConstant(string $constantName) : TrinaryLogic; public function getConstant(string $constantName) : ConstantReflection; public function isIterable() : TrinaryLogic; public function isIterableAtLeastOnce() : TrinaryLogic; public function getArraySize() : \PHPStan\Type\Type; public function getIterableKeyType() : \PHPStan\Type\Type; public function getFirstIterableKeyType() : \PHPStan\Type\Type; public function getLastIterableKeyType() : \PHPStan\Type\Type; public function getIterableValueType() : \PHPStan\Type\Type; public function getFirstIterableValueType() : \PHPStan\Type\Type; public function getLastIterableValueType() : \PHPStan\Type\Type; public function isArray() : TrinaryLogic; public function isConstantArray() : TrinaryLogic; public function isOversizedArray() : TrinaryLogic; public function isList() : TrinaryLogic; public function isOffsetAccessible() : TrinaryLogic; public function isOffsetAccessLegal() : TrinaryLogic; public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic; public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type; public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type; public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type; public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type; public function getKeysArray() : \PHPStan\Type\Type; public function getValuesArray() : \PHPStan\Type\Type; public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type; public function fillKeysArray(\PHPStan\Type\Type $valueType) : \PHPStan\Type\Type; public function flipArray() : \PHPStan\Type\Type; public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType) : \PHPStan\Type\Type; public function popArray() : \PHPStan\Type\Type; public function reverseArray(TrinaryLogic $preserveKeys) : \PHPStan\Type\Type; public function searchArray(\PHPStan\Type\Type $needleType) : \PHPStan\Type\Type; public function shiftArray() : \PHPStan\Type\Type; public function shuffleArray() : \PHPStan\Type\Type; public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type; /** * @return list */ public function getEnumCases() : array; /** * Returns a list of finite values. * * Examples: * * - for bool: [true, false] * - for int<0, 3>: [0, 1, 2, 3] * - for enums: list of enum cases * - for scalars: the scalar itself * * For infinite types it returns an empty array. * * @return list */ public function getFiniteTypes() : array; public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type; public function isCallable() : TrinaryLogic; /** * @return CallableParametersAcceptor[] */ public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array; public function isCloneable() : TrinaryLogic; public function toBoolean() : \PHPStan\Type\BooleanType; public function toNumber() : \PHPStan\Type\Type; public function toInteger() : \PHPStan\Type\Type; public function toFloat() : \PHPStan\Type\Type; public function toString() : \PHPStan\Type\Type; public function toArray() : \PHPStan\Type\Type; public function toArrayKey() : \PHPStan\Type\Type; public function isSmallerThan(\PHPStan\Type\Type $otherType) : TrinaryLogic; public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType) : TrinaryLogic; /** * Is Type of a known constant value? Includes literal strings, integers, floats, true, false, null, and array shapes. */ public function isConstantValue() : TrinaryLogic; /** * Is Type of a known constant scalar value? Includes literal strings, integers, floats, true, false, and null. */ public function isConstantScalarValue() : TrinaryLogic; /** * @return list */ public function getConstantScalarTypes() : array; /** * @return list */ public function getConstantScalarValues() : array; public function isNull() : TrinaryLogic; public function isTrue() : TrinaryLogic; public function isFalse() : TrinaryLogic; public function isBoolean() : TrinaryLogic; public function isFloat() : TrinaryLogic; public function isInteger() : TrinaryLogic; public function isString() : TrinaryLogic; public function isNumericString() : TrinaryLogic; public function isNonEmptyString() : TrinaryLogic; public function isNonFalsyString() : TrinaryLogic; public function isLiteralString() : TrinaryLogic; public function isLowercaseString() : TrinaryLogic; public function isUppercaseString() : TrinaryLogic; public function isClassStringType() : TrinaryLogic; public function isVoid() : TrinaryLogic; public function isScalar() : TrinaryLogic; public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType; public function getSmallerType() : \PHPStan\Type\Type; public function getSmallerOrEqualType() : \PHPStan\Type\Type; public function getGreaterType() : \PHPStan\Type\Type; public function getGreaterOrEqualType() : \PHPStan\Type\Type; /** * Returns actual template type for a given object. * * Example: * * @-template T * class Foo {} * * // $fooType is Foo * $t = $fooType->getTemplateType(Foo::class, 'T'); * $t->isInteger(); // yes * * Returns ErrorType in case of a missing type. * * @param class-string $ancestorClassName */ public function getTemplateType(string $ancestorClassName, string $templateTypeName) : \PHPStan\Type\Type; /** * Infers template types * * Infers the real Type of the TemplateTypes found in $this, based on * the received Type. */ public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap; /** * Returns the template types referenced by this Type, recursively * * The return value is a list of TemplateTypeReferences, who contain the * referenced template type as well as the variance position in which it was * found. * * For example, calling this on array,Bar> (with T a template type) * will return one TemplateTypeReference for the type T. * * @param TemplateTypeVariance $positionVariance The variance position in * which the receiver type was * found. * * @return TemplateTypeReference[] */ public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array; public function toAbsoluteNumber() : \PHPStan\Type\Type; /** * Traverses inner types * * Returns a new instance with all inner types mapped through $cb. Might * return the same instance if inner types did not change. * * @param callable(Type):Type $cb */ public function traverse(callable $cb) : \PHPStan\Type\Type; /** * Traverses inner types while keeping the same context in another type. * * @param callable(Type $left, Type $right): Type $cb */ public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type; public function toPhpDocNode() : TypeNode; /** * Return the difference with another type, or null if it cannot be represented. * * @see TypeCombinator::remove() */ public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type; public function generalize(\PHPStan\Type\GeneralizePrecision $precision) : \PHPStan\Type\Type; /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self; } extensions = $extensions; if ($broker === null) { return; } foreach ($extensions as $extension) { if (!$extension instanceof BrokerAwareExtension) { continue; } $extension->setBroker($broker); } } /** * @return OperatorTypeSpecifyingExtension[] */ public function getOperatorTypeSpecifyingExtensions(string $operator, \PHPStan\Type\Type $leftType, \PHPStan\Type\Type $rightType) : array { return array_values(array_filter($this->extensions, static function (\PHPStan\Type\OperatorTypeSpecifyingExtension $extension) use($operator, $leftType, $rightType) : bool { return $extension->isOperatorSupported($operator, $leftType, $rightType); })); } } resolve()->getObjectClassNames(); } public function getObjectClassReflections() : array { return $this->resolve()->getObjectClassReflections(); } public function getArrays() : array { return $this->resolve()->getArrays(); } public function getConstantArrays() : array { return $this->resolve()->getConstantArrays(); } public function getConstantStrings() : array { return $this->resolve()->getConstantStrings(); } public function accepts(Type $type, bool $strictTypes) : TrinaryLogic { return $this->resolve()->accepts($type, $strictTypes); } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { return $this->resolve()->acceptsWithReason($type, $strictTypes); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { return $this->isSuperTypeOfDefault($type); } private function isSuperTypeOfDefault(Type $type) : IsSuperTypeOfResult { if ($type instanceof NeverType) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof LateResolvableType) { $type = $type->resolve(); } $isSuperType = $this->resolve()->isSuperTypeOfWithReason($type); if (!$this->isResolvable()) { $isSuperType = $isSuperType->and(IsSuperTypeOfResult::createMaybe()); } return $isSuperType; } public function getTemplateType(string $ancestorClassName, string $templateTypeName) : Type { return $this->resolve()->getTemplateType($ancestorClassName, $templateTypeName); } public function isObject() : TrinaryLogic { return $this->resolve()->isObject(); } public function isEnum() : TrinaryLogic { return $this->resolve()->isEnum(); } public function canAccessProperties() : TrinaryLogic { return $this->resolve()->canAccessProperties(); } public function hasProperty(string $propertyName) : TrinaryLogic { return $this->resolve()->hasProperty($propertyName); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { return $this->resolve()->getProperty($propertyName, $scope); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { return $this->resolve()->getUnresolvedPropertyPrototype($propertyName, $scope); } public function canCallMethods() : TrinaryLogic { return $this->resolve()->canCallMethods(); } public function hasMethod(string $methodName) : TrinaryLogic { return $this->resolve()->hasMethod($methodName); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->resolve()->getMethod($methodName, $scope); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { return $this->resolve()->getUnresolvedMethodPrototype($methodName, $scope); } public function canAccessConstants() : TrinaryLogic { return $this->resolve()->canAccessConstants(); } public function hasConstant(string $constantName) : TrinaryLogic { return $this->resolve()->hasConstant($constantName); } public function getConstant(string $constantName) : ConstantReflection { return $this->resolve()->getConstant($constantName); } public function isIterable() : TrinaryLogic { return $this->resolve()->isIterable(); } public function isIterableAtLeastOnce() : TrinaryLogic { return $this->resolve()->isIterableAtLeastOnce(); } public function getArraySize() : Type { return $this->resolve()->getArraySize(); } public function getIterableKeyType() : Type { return $this->resolve()->getIterableKeyType(); } public function getFirstIterableKeyType() : Type { return $this->resolve()->getFirstIterableKeyType(); } public function getLastIterableKeyType() : Type { return $this->resolve()->getLastIterableKeyType(); } public function getIterableValueType() : Type { return $this->resolve()->getIterableValueType(); } public function getFirstIterableValueType() : Type { return $this->resolve()->getFirstIterableValueType(); } public function getLastIterableValueType() : Type { return $this->resolve()->getLastIterableValueType(); } public function isArray() : TrinaryLogic { return $this->resolve()->isArray(); } public function isConstantArray() : TrinaryLogic { return $this->resolve()->isConstantArray(); } public function isOversizedArray() : TrinaryLogic { return $this->resolve()->isOversizedArray(); } public function isList() : TrinaryLogic { return $this->resolve()->isList(); } public function isOffsetAccessible() : TrinaryLogic { return $this->resolve()->isOffsetAccessible(); } public function isOffsetAccessLegal() : TrinaryLogic { return $this->resolve()->isOffsetAccessLegal(); } public function hasOffsetValueType(Type $offsetType) : TrinaryLogic { return $this->resolve()->hasOffsetValueType($offsetType); } public function getOffsetValueType(Type $offsetType) : Type { return $this->resolve()->getOffsetValueType($offsetType); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = \true) : Type { return $this->resolve()->setOffsetValueType($offsetType, $valueType, $unionValues); } public function setExistingOffsetValueType(Type $offsetType, Type $valueType) : Type { return $this->resolve()->setExistingOffsetValueType($offsetType, $valueType); } public function unsetOffset(Type $offsetType) : Type { return $this->resolve()->unsetOffset($offsetType); } public function getKeysArray() : Type { return $this->resolve()->getKeysArray(); } public function getValuesArray() : Type { return $this->resolve()->getValuesArray(); } public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys) : Type { return $this->resolve()->chunkArray($lengthType, $preserveKeys); } public function fillKeysArray(Type $valueType) : Type { return $this->resolve()->fillKeysArray($valueType); } public function flipArray() : Type { return $this->resolve()->flipArray(); } public function intersectKeyArray(Type $otherArraysType) : Type { return $this->resolve()->intersectKeyArray($otherArraysType); } public function popArray() : Type { return $this->resolve()->popArray(); } public function reverseArray(TrinaryLogic $preserveKeys) : Type { return $this->resolve()->reverseArray($preserveKeys); } public function searchArray(Type $needleType) : Type { return $this->resolve()->searchArray($needleType); } public function shiftArray() : Type { return $this->resolve()->shiftArray(); } public function shuffleArray() : Type { return $this->resolve()->shuffleArray(); } public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $preserveKeys) : Type { return $this->resolve()->sliceArray($offsetType, $lengthType, $preserveKeys); } public function isCallable() : TrinaryLogic { return $this->resolve()->isCallable(); } public function getEnumCases() : array { return $this->resolve()->getEnumCases(); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { return $this->resolve()->getCallableParametersAcceptors($scope); } public function isCloneable() : TrinaryLogic { return $this->resolve()->isCloneable(); } public function toBoolean() : BooleanType { return $this->resolve()->toBoolean(); } public function toNumber() : Type { return $this->resolve()->toNumber(); } public function toAbsoluteNumber() : Type { return $this->resolve()->toAbsoluteNumber(); } public function toInteger() : Type { return $this->resolve()->toInteger(); } public function toFloat() : Type { return $this->resolve()->toFloat(); } public function toString() : Type { return $this->resolve()->toString(); } public function toArray() : Type { return $this->resolve()->toArray(); } public function toArrayKey() : Type { return $this->resolve()->toArrayKey(); } public function isSmallerThan(Type $otherType) : TrinaryLogic { return $this->resolve()->isSmallerThan($otherType); } public function isSmallerThanOrEqual(Type $otherType) : TrinaryLogic { return $this->resolve()->isSmallerThanOrEqual($otherType); } public function isNull() : TrinaryLogic { return $this->resolve()->isNull(); } public function isConstantValue() : TrinaryLogic { return $this->resolve()->isConstantValue(); } public function isConstantScalarValue() : TrinaryLogic { return $this->resolve()->isConstantScalarValue(); } public function getConstantScalarTypes() : array { return $this->resolve()->getConstantScalarTypes(); } public function getConstantScalarValues() : array { return $this->resolve()->getConstantScalarValues(); } public function isTrue() : TrinaryLogic { return $this->resolve()->isTrue(); } public function isFalse() : TrinaryLogic { return $this->resolve()->isFalse(); } public function isBoolean() : TrinaryLogic { return $this->resolve()->isBoolean(); } public function isFloat() : TrinaryLogic { return $this->resolve()->isFloat(); } public function isInteger() : TrinaryLogic { return $this->resolve()->isInteger(); } public function isString() : TrinaryLogic { return $this->resolve()->isString(); } public function isNumericString() : TrinaryLogic { return $this->resolve()->isNumericString(); } public function isNonEmptyString() : TrinaryLogic { return $this->resolve()->isNonEmptyString(); } public function isNonFalsyString() : TrinaryLogic { return $this->resolve()->isNonFalsyString(); } public function isLiteralString() : TrinaryLogic { return $this->resolve()->isLiteralString(); } public function isLowercaseString() : TrinaryLogic { return $this->resolve()->isLowercaseString(); } public function isUppercaseString() : TrinaryLogic { return $this->resolve()->isUppercaseString(); } public function isClassStringType() : TrinaryLogic { return $this->resolve()->isClassStringType(); } public function getClassStringObjectType() : Type { return $this->resolve()->getClassStringObjectType(); } public function getObjectTypeOrClassStringObjectType() : Type { return $this->resolve()->getObjectTypeOrClassStringObjectType(); } public function isVoid() : TrinaryLogic { return $this->resolve()->isVoid(); } public function isScalar() : TrinaryLogic { return $this->resolve()->isScalar(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function getSmallerType() : Type { return $this->resolve()->getSmallerType(); } public function getSmallerOrEqualType() : Type { return $this->resolve()->getSmallerOrEqualType(); } public function getGreaterType() : Type { return $this->resolve()->getGreaterType(); } public function getGreaterOrEqualType() : Type { return $this->resolve()->getGreaterOrEqualType(); } public function inferTemplateTypes(Type $receivedType) : TemplateTypeMap { return $this->resolve()->inferTemplateTypes($receivedType); } public function tryRemove(Type $typeToRemove) : ?Type { return $this->resolve()->tryRemove($typeToRemove); } public function isSubTypeOf(Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(Type $otherType) : IsSuperTypeOfResult { $result = $this->resolve(); if ($result instanceof CompoundType) { return $result->isSubTypeOfWithReason($otherType); } return $otherType->isSuperTypeOfWithReason($result); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes) : AcceptsResult { $result = $this->resolve(); if ($result instanceof CompoundType) { return $result->isAcceptedWithReasonBy($acceptingType, $strictTypes); } return $acceptingType->acceptsWithReason($result, $strictTypes); } public function isGreaterThan(Type $otherType) : TrinaryLogic { $result = $this->resolve(); if ($result instanceof CompoundType) { return $result->isGreaterThan($otherType); } return $otherType->isSmallerThan($result); } public function isGreaterThanOrEqual(Type $otherType) : TrinaryLogic { $result = $this->resolve(); if ($result instanceof CompoundType) { return $result->isGreaterThanOrEqual($otherType); } return $otherType->isSmallerThanOrEqual($result); } public function exponentiate(Type $exponent) : Type { return $this->resolve()->exponentiate($exponent); } public function getFiniteTypes() : array { return $this->resolve()->getFiniteTypes(); } public function resolve() : Type { if ($this->result === null) { return $this->result = $this->getResult(); } return $this->result; } protected abstract function getResult() : Type; } isIterable()->no()) { return new ErrorType(); } if ($this->isIterableAtLeastOnce()->yes()) { return IntegerRangeType::fromInterval(1, null); } return IntegerRangeType::fromInterval(0, null); } public function getIterableKeyType() : Type { return new MixedType(); } public function getFirstIterableKeyType() : Type { return new MixedType(); } public function getLastIterableKeyType() : Type { return new MixedType(); } public function getIterableValueType() : Type { return new MixedType(); } public function getFirstIterableValueType() : Type { return new MixedType(); } public function getLastIterableValueType() : Type { return new MixedType(); } } traverse(static function (Type $type) use($precision) { return $type->generalize($precision); }); } } acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(Type $type, bool $strictTypes) : AcceptsResult { if ($type instanceof self) { return AcceptsResult::createFromBoolean($this->equals($type)); } if ($type instanceof CompoundType) { return $type->isAcceptedWithReasonBy($this, $strictTypes); } return parent::acceptsWithReason($type, $strictTypes)->and(AcceptsResult::createMaybe()); } public function isSuperTypeOf(Type $type) : TrinaryLogic { return $this->isSuperTypeOfWithReason($type)->result; } public function isSuperTypeOfWithReason(Type $type) : IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createFromBoolean($this->equals($type)); } if ($type instanceof parent) { return IsSuperTypeOfResult::createMaybe(); } if ($type instanceof CompoundType) { return $type->isSubTypeOfWithReason($this); } return IsSuperTypeOfResult::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { if (!$this instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } if ($type instanceof ConstantScalarType) { return LooseComparisonHelper::compareConstantScalars($this, $type, $phpVersion); } if ($type->isConstantArray()->yes() && $type->isIterableAtLeastOnce()->no()) { // @phpstan-ignore equal.notAllowed, equal.invalid return new ConstantBooleanType($this->getValue() == []); // phpcs:ignore } if ($type instanceof CompoundType) { return $type->looseCompare($this, $phpVersion); } return parent::looseCompare($type, $phpVersion); } public function equals(Type $type) : bool { return $type instanceof self && $this->value === $type->value; } public function isSmallerThan(Type $otherType) : TrinaryLogic { if ($otherType instanceof ConstantScalarType) { return TrinaryLogic::createFromBoolean($this->value < $otherType->getValue()); } if ($otherType instanceof CompoundType) { return $otherType->isGreaterThan($this); } return TrinaryLogic::createMaybe(); } public function isSmallerThanOrEqual(Type $otherType) : TrinaryLogic { if ($otherType instanceof ConstantScalarType) { return TrinaryLogic::createFromBoolean($this->value <= $otherType->getValue()); } if ($otherType instanceof CompoundType) { return $otherType->isGreaterThanOrEqual($this); } return TrinaryLogic::createMaybe(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createYes(); } public function getConstantScalarTypes() : array { return [$this]; } public function getConstantScalarValues() : array { return [$this->getValue()]; } public function getFiniteTypes() : array { return [$this]; } } value)]; if (!(bool) $this->value) { $subtractedTypes[] = new NullType(); $subtractedTypes[] = new ConstantBooleanType(\false); $subtractedTypes[] = new ConstantFloatType(0.0); // subtract range when we support float-ranges } return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } public function getSmallerOrEqualType() : Type { $subtractedTypes = [IntegerRangeType::createAllGreaterThan($this->value)]; if (!(bool) $this->value) { $subtractedTypes[] = new ConstantBooleanType(\true); } return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } public function getGreaterType() : Type { $subtractedTypes = [ new NullType(), new ConstantBooleanType(\false), new ConstantFloatType(0.0), // subtract range when we support float-ranges IntegerRangeType::createAllSmallerThanOrEqualTo($this->value), ]; if ((bool) $this->value) { $subtractedTypes[] = new ConstantBooleanType(\true); } return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } public function getGreaterOrEqualType() : Type { $subtractedTypes = [IntegerRangeType::createAllSmallerThan($this->value)]; if ((bool) $this->value) { $subtractedTypes[] = new NullType(); $subtractedTypes[] = new ConstantBooleanType(\false); $subtractedTypes[] = new ConstantFloatType(0.0); // subtract range when we support float-ranges } return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } } getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection(); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static function (Type $type) : Type { return $type; }); } public function canCallMethods() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasMethod(string $methodName) : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { $method = new DummyMethodReflection($methodName); return new CallbackUnresolvedMethodPrototypeReflection($method, $method->getDeclaringClass(), \false, static function (Type $type) : Type { return $type; }); } public function canAccessConstants() : TrinaryLogic { return TrinaryLogic::createYes(); } public function hasConstant(string $constantName) : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstant(string $constantName) : ConstantReflection { return new DummyConstantReflection($constantName); } public function getConstantStrings() : array { return []; } public function isCloneable() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isNull() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isConstantScalarValue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getConstantScalarTypes() : array { return []; } public function getConstantScalarValues() : array { return []; } public function isTrue() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFalse() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isBoolean() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFloat() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInteger() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNumericString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonEmptyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isNonFalsyString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLiteralString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isLowercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isUppercaseString() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isClassStringType() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getClassStringObjectType() : Type { return new ErrorType(); } public function getObjectTypeOrClassStringObjectType() : Type { return $this; } public function isVoid() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isScalar() : TrinaryLogic { return TrinaryLogic::createNo(); } public function looseCompare(Type $type, PhpVersion $phpVersion) : BooleanType { return new BooleanType(); } public function toNumber() : Type { return new ErrorType(); } public function toAbsoluteNumber() : Type { return new ErrorType(); } public function toString() : Type { return new ErrorType(); } public function toInteger() : Type { return new ErrorType(); } public function toFloat() : Type { return new ErrorType(); } public function toArray() : Type { return new ArrayType(new MixedType(), new MixedType()); } public function toArrayKey() : Type { return new StringType(); } } getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { $property = new DummyPropertyReflection(); return new CallbackUnresolvedPropertyPrototypeReflection($property, $property->getDeclaringClass(), \false, static function (Type $type) : Type { return $type; }); } public function canCallMethods() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function hasMethod(string $methodName) : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { $method = new DummyMethodReflection($methodName); return new CallbackUnresolvedMethodPrototypeReflection($method, $method->getDeclaringClass(), \false, static function (Type $type) : Type { return $type; }); } public function canAccessConstants() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function hasConstant(string $constantName) : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getConstant(string $constantName) : ConstantReflection { return new DummyConstantReflection($constantName); } public function isCloneable() : TrinaryLogic { return TrinaryLogic::createMaybe(); } } types = $types; if (count($types) < 2) { throw new ShouldNotHappenException(sprintf('Cannot create %s with: %s', self::class, implode(', ', array_map(static function (\PHPStan\Type\Type $type) : string { return $type->describe(\PHPStan\Type\VerbosityLevel::value()); }, $types)))); } } /** * @return Type[] */ public function getTypes() : array { return $this->types; } /** * @return Type[] */ private function getSortedTypes() : array { if ($this->sortedTypes) { return $this->types; } $this->types = \PHPStan\Type\UnionTypeHelper::sortTypes($this->types); $this->sortedTypes = \true; return $this->types; } public function inferTemplateTypesOn(\PHPStan\Type\Type $templateType) : TemplateTypeMap { $types = TemplateTypeMap::createEmpty(); foreach ($this->types as $type) { $types = $types->intersect($templateType->inferTemplateTypes($type)); } return $types; } public function getReferencedClasses() : array { $classes = []; foreach ($this->types as $type) { foreach ($type->getReferencedClasses() as $className) { $classes[] = $className; } } return $classes; } public function getObjectClassNames() : array { $objectClassNames = []; foreach ($this->types as $type) { $innerObjectClassNames = $type->getObjectClassNames(); foreach ($innerObjectClassNames as $innerObjectClassName) { $objectClassNames[] = $innerObjectClassName; } } return array_values(array_unique($objectClassNames)); } public function getObjectClassReflections() : array { $reflections = []; foreach ($this->types as $type) { foreach ($type->getObjectClassReflections() as $reflection) { $reflections[] = $reflection; } } return $reflections; } public function getArrays() : array { $arrays = []; foreach ($this->types as $type) { foreach ($type->getArrays() as $array) { $arrays[] = $array; } } return $arrays; } public function getConstantArrays() : array { $constantArrays = []; foreach ($this->types as $type) { foreach ($type->getConstantArrays() as $constantArray) { $constantArrays[] = $constantArray; } } return $constantArrays; } public function getConstantStrings() : array { $strings = []; foreach ($this->types as $type) { foreach ($type->getConstantStrings() as $string) { $strings[] = $string; } } return $strings; } public function accepts(\PHPStan\Type\Type $type, bool $strictTypes) : TrinaryLogic { return $this->acceptsWithReason($type, $strictTypes)->result; } public function acceptsWithReason(\PHPStan\Type\Type $otherType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { $result = \PHPStan\Type\AcceptsResult::createYes(); foreach ($this->types as $type) { $result = $result->and($type->acceptsWithReason($otherType, $strictTypes)); } if (!$result->yes()) { $isList = $otherType->isList(); $reasons = $result->reasons; $verbosity = \PHPStan\Type\VerbosityLevel::getRecommendedLevelByType($this, $otherType); if ($this->isList()->yes() && !$isList->yes()) { $reasons[] = sprintf('%s %s a list.', $otherType->describe($verbosity), $isList->no() ? 'is not' : 'might not be'); } $isNonEmpty = $otherType->isIterableAtLeastOnce(); if ($this->isIterableAtLeastOnce()->yes() && !$isNonEmpty->yes()) { $reasons[] = sprintf('%s %s empty.', $otherType->describe($verbosity), $isNonEmpty->no() ? 'is' : 'might be'); } if (count($reasons) > 0) { return new \PHPStan\Type\AcceptsResult($result->result, $reasons); } } return $result; } public function isSuperTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSuperTypeOfWithReason($otherType)->result; } public function isSuperTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { if ($otherType instanceof \PHPStan\Type\IntersectionType && $this->equals($otherType)) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } if ($otherType instanceof \PHPStan\Type\NeverType) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } return \PHPStan\Type\IsSuperTypeOfResult::createYes()->and(...array_map(static function (\PHPStan\Type\Type $innerType) use($otherType) { return $innerType->isSuperTypeOfWithReason($otherType); }, $this->types)); } public function isSubTypeOf(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->isSubTypeOfWithReason($otherType)->result; } public function isSubTypeOfWithReason(\PHPStan\Type\Type $otherType) : \PHPStan\Type\IsSuperTypeOfResult { if (($otherType instanceof self || $otherType instanceof \PHPStan\Type\UnionType) && !$otherType instanceof TemplateType) { return $otherType->isSuperTypeOfWithReason($this); } $result = \PHPStan\Type\IsSuperTypeOfResult::maxMin(...array_map(static function (\PHPStan\Type\Type $innerType) use($otherType) { return $otherType->isSuperTypeOfWithReason($innerType); }, $this->types)); if ($this->isOversizedArray()->yes()) { if (!$result->no()) { return \PHPStan\Type\IsSuperTypeOfResult::createYes(); } } return $result; } public function isAcceptedBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : TrinaryLogic { return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; } public function isAcceptedWithReasonBy(\PHPStan\Type\Type $acceptingType, bool $strictTypes) : \PHPStan\Type\AcceptsResult { $result = \PHPStan\Type\AcceptsResult::maxMin(...array_map(static function (\PHPStan\Type\Type $innerType) use($acceptingType, $strictTypes) { return $acceptingType->acceptsWithReason($innerType, $strictTypes); }, $this->types)); if ($this->isOversizedArray()->yes()) { if (!$result->no()) { return \PHPStan\Type\AcceptsResult::createYes(); } } return $result; } public function equals(\PHPStan\Type\Type $type) : bool { if (!$type instanceof static) { return \false; } if (count($this->types) !== count($type->types)) { return \false; } $otherTypes = $type->types; foreach ($this->types as $innerType) { $match = \false; foreach ($otherTypes as $i => $otherType) { if (!$innerType->equals($otherType)) { continue; } $match = \true; unset($otherTypes[$i]); break; } if (!$match) { return \false; } } return count($otherTypes) === 0; } public function describe(\PHPStan\Type\VerbosityLevel $level) : string { return $level->handle(function () use($level) : string { $typeNames = []; foreach ($this->getSortedTypes() as $type) { if ($type instanceof AccessoryType) { continue; } $typeNames[] = $type->generalize(\PHPStan\Type\GeneralizePrecision::lessSpecific())->describe($level); } return implode('&', $typeNames); }, function () use($level) : string { return $this->describeItself($level, \true); }, function () use($level) : string { return $this->describeItself($level, \false); }); } private function describeItself(\PHPStan\Type\VerbosityLevel $level, bool $skipAccessoryTypes) : string { $baseTypes = []; $typesToDescribe = []; $skipTypeNames = []; $nonEmptyStr = \false; $nonFalsyStr = \false; foreach ($this->getSortedTypes() as $i => $type) { if ($type instanceof AccessoryNonEmptyStringType || $type instanceof AccessoryLiteralStringType || $type instanceof AccessoryNumericStringType || $type instanceof AccessoryNonFalsyStringType || $type instanceof AccessoryLowercaseStringType || $type instanceof AccessoryUppercaseStringType) { if (($type instanceof AccessoryLowercaseStringType || $type instanceof AccessoryUppercaseStringType) && !$level->isPrecise()) { continue; } if ($type instanceof AccessoryNonFalsyStringType) { $nonFalsyStr = \true; } if ($type instanceof AccessoryNonEmptyStringType) { $nonEmptyStr = \true; } if ($nonEmptyStr && $nonFalsyStr) { // prevent redundant 'non-empty-string&non-falsy-string' foreach ($typesToDescribe as $key => $typeToDescribe) { if (!$typeToDescribe instanceof AccessoryNonEmptyStringType) { continue; } unset($typesToDescribe[$key]); } } $typesToDescribe[$i] = $type; $skipTypeNames[] = 'string'; continue; } if ($type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) { $typesToDescribe[$i] = $type; $skipTypeNames[] = 'array'; continue; } if ($type instanceof \PHPStan\Type\CallableType && $type->isCommonCallable()) { $typesToDescribe[$i] = $type; $skipTypeNames[] = 'object'; $skipTypeNames[] = 'string'; continue; } if (!$type instanceof AccessoryType) { $baseTypes[$i] = $type; continue; } if ($skipAccessoryTypes) { continue; } $typesToDescribe[$i] = $type; } $describedTypes = []; foreach ($baseTypes as $i => $type) { $typeDescription = $type->describe($level); if (in_array($typeDescription, ['object', 'string'], \true) && in_array($typeDescription, $skipTypeNames, \true)) { foreach ($typesToDescribe as $j => $typeToDescribe) { if ($typeToDescribe instanceof \PHPStan\Type\CallableType && $typeToDescribe->isCommonCallable()) { $describedTypes[$i] = 'callable-' . $typeDescription; unset($typesToDescribe[$j]); continue 2; } } } if (str_starts_with($typeDescription, 'array<') && in_array('array', $skipTypeNames, \true)) { $nonEmpty = \false; $typeName = 'array'; foreach ($typesToDescribe as $j => $typeToDescribe) { if ($typeToDescribe instanceof AccessoryArrayListType && substr($typeDescription, 0, strlen('array, ')) === 'array, ') { $typeName = 'list'; $typeDescription = 'array<' . substr($typeDescription, strlen('array, ')); } elseif ($typeToDescribe instanceof NonEmptyArrayType) { $nonEmpty = \true; } else { continue; } unset($typesToDescribe[$j]); } if ($nonEmpty) { $typeName = 'non-empty-' . $typeName; } $describedTypes[$i] = $typeName . '<' . substr($typeDescription, strlen('array<')); continue; } if (in_array($typeDescription, $skipTypeNames, \true)) { continue; } $describedTypes[$i] = $type->describe($level); } foreach ($typesToDescribe as $i => $typeToDescribe) { $describedTypes[$i] = $typeToDescribe->describe($level); } ksort($describedTypes); return implode('&', $describedTypes); } public function getTemplateType(string $ancestorClassName, string $templateTypeName) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($ancestorClassName, $templateTypeName) : \PHPStan\Type\Type { return $type->getTemplateType($ancestorClassName, $templateTypeName); }); } public function isObject() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isObject(); }); } public function isEnum() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isEnum(); }); } public function canAccessProperties() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->canAccessProperties(); }); } public function hasProperty(string $propertyName) : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) use($propertyName) : TrinaryLogic { return $type->hasProperty($propertyName); }); } public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope) : PropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope) : UnresolvedPropertyPrototypeReflection { $propertyPrototypes = []; foreach ($this->types as $type) { if (!$type->hasProperty($propertyName)->yes()) { continue; } $propertyPrototypes[] = $type->getUnresolvedPropertyPrototype($propertyName, $scope)->withFechedOnType($this); } $propertiesCount = count($propertyPrototypes); if ($propertiesCount === 0) { throw new ShouldNotHappenException(); } if ($propertiesCount === 1) { return $propertyPrototypes[0]; } return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes); } public function canCallMethods() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->canCallMethods(); }); } public function hasMethod(string $methodName) : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) use($methodName) : TrinaryLogic { return $type->hasMethod($methodName); }); } public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope) : ExtendedMethodReflection { return $this->getUnresolvedMethodPrototype($methodName, $scope)->getTransformedMethod(); } public function getUnresolvedMethodPrototype(string $methodName, ClassMemberAccessAnswerer $scope) : UnresolvedMethodPrototypeReflection { $methodPrototypes = []; foreach ($this->types as $type) { if (!$type->hasMethod($methodName)->yes()) { continue; } $methodPrototypes[] = $type->getUnresolvedMethodPrototype($methodName, $scope)->withCalledOnType($this); } $methodsCount = count($methodPrototypes); if ($methodsCount === 0) { throw new ShouldNotHappenException(); } if ($methodsCount === 1) { return $methodPrototypes[0]; } return new IntersectionTypeUnresolvedMethodPrototypeReflection($methodName, $methodPrototypes); } public function canAccessConstants() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->canAccessConstants(); }); } public function hasConstant(string $constantName) : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) use($constantName) : TrinaryLogic { return $type->hasConstant($constantName); }); } public function getConstant(string $constantName) : ConstantReflection { foreach ($this->types as $type) { if ($type->hasConstant($constantName)->yes()) { return $type->getConstant($constantName); } } throw new ShouldNotHappenException(); } public function isIterable() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isIterable(); }); } public function isIterableAtLeastOnce() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isIterableAtLeastOnce(); }); } public function getArraySize() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getArraySize(); }); } public function getIterableKeyType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getIterableKeyType(); }); } public function getFirstIterableKeyType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getFirstIterableKeyType(); }); } public function getLastIterableKeyType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getLastIterableKeyType(); }); } public function getIterableValueType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getIterableValueType(); }); } public function getFirstIterableValueType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getFirstIterableValueType(); }); } public function getLastIterableValueType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getLastIterableValueType(); }); } public function isArray() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isArray(); }); } public function isConstantArray() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isConstantArray(); }); } public function isOversizedArray() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isOversizedArray(); }); } public function isList() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isList(); }); } public function isString() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isString(); }); } public function isNumericString() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isNumericString(); }); } public function isNonEmptyString() : TrinaryLogic { if ($this->isCallable()->yes() && $this->isString()->yes()) { return TrinaryLogic::createYes(); } return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isNonEmptyString(); }); } public function isNonFalsyString() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isNonFalsyString(); }); } public function isLiteralString() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isLiteralString(); }); } public function isLowercaseString() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isLowercaseString(); }); } public function isUppercaseString() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isUppercaseString(); }); } public function isClassStringType() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isClassStringType(); }); } public function getClassStringObjectType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getClassStringObjectType(); }); } public function getObjectTypeOrClassStringObjectType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getObjectTypeOrClassStringObjectType(); }); } public function isVoid() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isVoid(); }); } public function isScalar() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isScalar(); }); } public function looseCompare(\PHPStan\Type\Type $type, PhpVersion $phpVersion) : \PHPStan\Type\BooleanType { return new \PHPStan\Type\BooleanType(); } public function isOffsetAccessible() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isOffsetAccessible(); }); } public function isOffsetAccessLegal() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isOffsetAccessLegal(); }); } public function hasOffsetValueType(\PHPStan\Type\Type $offsetType) : TrinaryLogic { if ($this->isList()->yes() && $this->isIterableAtLeastOnce()->yes()) { $arrayKeyOffsetType = $offsetType->toArrayKey(); if ((new ConstantIntegerType(0))->isSuperTypeOf($arrayKeyOffsetType)->yes()) { return TrinaryLogic::createYes(); } } return $this->intersectResults(static function (\PHPStan\Type\Type $type) use($offsetType) : TrinaryLogic { return $type->hasOffsetValueType($offsetType); }); } public function getOffsetValueType(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { $result = $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($offsetType) : \PHPStan\Type\Type { return $type->getOffsetValueType($offsetType); }); if ($this->isOversizedArray()->yes()) { return \PHPStan\Type\TypeUtils::toBenevolentUnion($result); } return $result; } public function setOffsetValueType(?\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType, bool $unionValues = \true) : \PHPStan\Type\Type { if ($this->isOversizedArray()->yes()) { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($offsetType, $valueType, $unionValues) : \PHPStan\Type\Type { // avoid new HasOffsetValueType being intersected with oversized array if (!$type instanceof \PHPStan\Type\ArrayType) { return $type->setOffsetValueType($offsetType, $valueType, $unionValues); } if (!$offsetType instanceof ConstantStringType && !$offsetType instanceof ConstantIntegerType) { return $type->setOffsetValueType($offsetType, $valueType, $unionValues); } if (!$offsetType->isSuperTypeOf($type->getKeyType())->yes()) { return $type->setOffsetValueType($offsetType, $valueType, $unionValues); } return \PHPStan\Type\TypeCombinator::intersect(new \PHPStan\Type\ArrayType(\PHPStan\Type\TypeCombinator::union($type->getKeyType(), $offsetType), \PHPStan\Type\TypeCombinator::union($type->getItemType(), $valueType)), new NonEmptyArrayType()); }); } $result = $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($offsetType, $valueType, $unionValues) : \PHPStan\Type\Type { return $type->setOffsetValueType($offsetType, $valueType, $unionValues); }); if ($offsetType !== null && $this->isList()->yes() && $this->isIterableAtLeastOnce()->yes() && (new ConstantIntegerType(1))->isSuperTypeOf($offsetType)->yes()) { $result = AccessoryArrayListType::intersectWith($result); } return $result; } public function setExistingOffsetValueType(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($offsetType, $valueType) : \PHPStan\Type\Type { return $type->setExistingOffsetValueType($offsetType, $valueType); }); } public function unsetOffset(\PHPStan\Type\Type $offsetType) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($offsetType) : \PHPStan\Type\Type { return $type->unsetOffset($offsetType); }); } public function getKeysArray() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getKeysArray(); }); } public function getValuesArray() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getValuesArray(); }); } public function chunkArray(\PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($lengthType, $preserveKeys) : \PHPStan\Type\Type { return $type->chunkArray($lengthType, $preserveKeys); }); } public function fillKeysArray(\PHPStan\Type\Type $valueType) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($valueType) : \PHPStan\Type\Type { return $type->fillKeysArray($valueType); }); } public function flipArray() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->flipArray(); }); } public function intersectKeyArray(\PHPStan\Type\Type $otherArraysType) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($otherArraysType) : \PHPStan\Type\Type { return $type->intersectKeyArray($otherArraysType); }); } public function popArray() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->popArray(); }); } public function reverseArray(TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($preserveKeys) : \PHPStan\Type\Type { return $type->reverseArray($preserveKeys); }); } public function searchArray(\PHPStan\Type\Type $needleType) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($needleType) : \PHPStan\Type\Type { return $type->searchArray($needleType); }); } public function shiftArray() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->shiftArray(); }); } public function shuffleArray() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->shuffleArray(); }); } public function sliceArray(\PHPStan\Type\Type $offsetType, \PHPStan\Type\Type $lengthType, TrinaryLogic $preserveKeys) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($offsetType, $lengthType, $preserveKeys) : \PHPStan\Type\Type { return $type->sliceArray($offsetType, $lengthType, $preserveKeys); }); } public function getEnumCases() : array { $compare = []; foreach ($this->types as $type) { $oneType = []; foreach ($type->getEnumCases() as $enumCase) { $oneType[$enumCase->getClassName() . '::' . $enumCase->getEnumCaseName()] = $enumCase; } $compare[] = $oneType; } return array_values(array_intersect_key(...$compare)); } public function isCallable() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isCallable(); }); } public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) : array { if ($this->isCallable()->no()) { throw new ShouldNotHappenException(); } return [new TrivialParametersAcceptor()]; } public function isCloneable() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isCloneable(); }); } public function isSmallerThan(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) use($otherType) : TrinaryLogic { return $type->isSmallerThan($otherType); }); } public function isSmallerThanOrEqual(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) use($otherType) : TrinaryLogic { return $type->isSmallerThanOrEqual($otherType); }); } public function isNull() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isNull(); }); } public function isConstantValue() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isConstantValue(); }); } public function isConstantScalarValue() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isConstantScalarValue(); }); } public function getConstantScalarTypes() : array { $scalarTypes = []; foreach ($this->types as $type) { foreach ($type->getConstantScalarTypes() as $scalarType) { $scalarTypes[] = $scalarType; } } return $scalarTypes; } public function getConstantScalarValues() : array { $values = []; foreach ($this->types as $type) { foreach ($type->getConstantScalarValues() as $value) { $values[] = $value; } } return $values; } public function isTrue() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isTrue(); }); } public function isFalse() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isFalse(); }); } public function isBoolean() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isBoolean(); }); } public function isFloat() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isFloat(); }); } public function isInteger() : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) : TrinaryLogic { return $type->isInteger(); }); } public function isGreaterThan(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) use($otherType) : TrinaryLogic { return $otherType->isSmallerThan($type); }); } public function isGreaterThanOrEqual(\PHPStan\Type\Type $otherType) : TrinaryLogic { return $this->intersectResults(static function (\PHPStan\Type\Type $type) use($otherType) : TrinaryLogic { return $otherType->isSmallerThanOrEqual($type); }); } public function getSmallerType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getSmallerType(); }); } public function getSmallerOrEqualType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getSmallerOrEqualType(); }); } public function getGreaterType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getGreaterType(); }); } public function getGreaterOrEqualType() : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->getGreaterOrEqualType(); }); } public function toBoolean() : \PHPStan\Type\BooleanType { $type = $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\BooleanType { return $type->toBoolean(); }); if (!$type instanceof \PHPStan\Type\BooleanType) { return new \PHPStan\Type\BooleanType(); } return $type; } public function toNumber() : \PHPStan\Type\Type { $type = $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toNumber(); }); return $type; } public function toAbsoluteNumber() : \PHPStan\Type\Type { $type = $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toAbsoluteNumber(); }); return $type; } public function toString() : \PHPStan\Type\Type { $type = $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toString(); }); return $type; } public function toInteger() : \PHPStan\Type\Type { $type = $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toInteger(); }); return $type; } public function toFloat() : \PHPStan\Type\Type { $type = $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toFloat(); }); return $type; } public function toArray() : \PHPStan\Type\Type { $type = $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toArray(); }); return $type; } public function toArrayKey() : \PHPStan\Type\Type { if ($this->isNumericString()->yes()) { return \PHPStan\Type\TypeCombinator::union(new \PHPStan\Type\IntegerType(), $this); } if ($this->isString()->yes()) { return $this; } return $this->intersectTypes(static function (\PHPStan\Type\Type $type) : \PHPStan\Type\Type { return $type->toArrayKey(); }); } public function inferTemplateTypes(\PHPStan\Type\Type $receivedType) : TemplateTypeMap { $types = TemplateTypeMap::createEmpty(); foreach ($this->types as $type) { $types = $types->intersect($type->inferTemplateTypes($receivedType)); } return $types; } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance) : array { $references = []; foreach ($this->types as $type) { foreach ($type->getReferencedTemplateTypes($positionVariance) as $reference) { $references[] = $reference; } } return $references; } public function traverse(callable $cb) : \PHPStan\Type\Type { $types = []; $changed = \false; foreach ($this->types as $type) { $newType = $cb($type); if ($type !== $newType) { $changed = \true; } $types[] = $newType; } if ($changed) { return \PHPStan\Type\TypeCombinator::intersect(...$types); } return $this; } public function traverseSimultaneously(\PHPStan\Type\Type $right, callable $cb) : \PHPStan\Type\Type { $types = []; $changed = \false; if (!$right instanceof self) { return $this; } if (count($this->getTypes()) !== count($right->getTypes())) { return $this; } foreach ($this->getSortedTypes() as $i => $leftType) { $rightType = $right->getSortedTypes()[$i]; $newType = $cb($leftType, $rightType); if ($leftType !== $newType) { $changed = \true; } $types[] = $newType; } if ($changed) { return \PHPStan\Type\TypeCombinator::intersect(...$types); } return $this; } public function tryRemove(\PHPStan\Type\Type $typeToRemove) : ?\PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($typeToRemove) : \PHPStan\Type\Type { return \PHPStan\Type\TypeCombinator::remove($type, $typeToRemove); }); } public function exponentiate(\PHPStan\Type\Type $exponent) : \PHPStan\Type\Type { return $this->intersectTypes(static function (\PHPStan\Type\Type $type) use($exponent) : \PHPStan\Type\Type { return $type->exponentiate($exponent); }); } public function getFiniteTypes() : array { $compare = []; foreach ($this->types as $type) { $oneType = []; foreach ($type->getFiniteTypes() as $finiteType) { $oneType[md5($finiteType->describe(\PHPStan\Type\VerbosityLevel::typeOnly()))] = $finiteType; } $compare[] = $oneType; } $result = array_values(array_intersect_key(...$compare)); if (count($result) > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return []; } return $result; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : \PHPStan\Type\Type { return new self($properties['types']); } /** * @param callable(Type $type): TrinaryLogic $getResult */ private function intersectResults(callable $getResult) : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->types, $getResult); } /** * @param callable(Type $type): Type $getType */ private function intersectTypes(callable $getType) : \PHPStan\Type\Type { $operands = array_map($getType, $this->types); return \PHPStan\Type\TypeCombinator::intersect(...$operands); } public function toPhpDocNode() : TypeNode { $baseTypes = []; $typesToDescribe = []; $skipTypeNames = []; $nonEmptyStr = \false; $nonFalsyStr = \false; foreach ($this->getSortedTypes() as $i => $type) { if ($type instanceof AccessoryNonEmptyStringType || $type instanceof AccessoryLiteralStringType || $type instanceof AccessoryNumericStringType || $type instanceof AccessoryNonFalsyStringType || $type instanceof AccessoryLowercaseStringType || $type instanceof AccessoryUppercaseStringType) { if ($type instanceof AccessoryNonFalsyStringType) { $nonFalsyStr = \true; } if ($type instanceof AccessoryNonEmptyStringType) { $nonEmptyStr = \true; } if ($nonEmptyStr && $nonFalsyStr) { // prevent redundant 'non-empty-string&non-falsy-string' foreach ($typesToDescribe as $key => $typeToDescribe) { if (!$typeToDescribe instanceof AccessoryNonEmptyStringType) { continue; } unset($typesToDescribe[$key]); } } $typesToDescribe[$i] = $type; $skipTypeNames[] = 'string'; continue; } if ($type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) { $typesToDescribe[$i] = $type; $skipTypeNames[] = 'array'; continue; } if (!$type instanceof AccessoryType) { $baseTypes[$i] = $type; continue; } $accessoryPhpDocNode = $type->toPhpDocNode(); if ($accessoryPhpDocNode instanceof IdentifierTypeNode && $accessoryPhpDocNode->name === '') { continue; } $typesToDescribe[$i] = $type; } $describedTypes = []; foreach ($baseTypes as $i => $type) { $typeNode = $type->toPhpDocNode(); if ($typeNode instanceof GenericTypeNode && $typeNode->type->name === 'array') { $nonEmpty = \false; $typeName = 'array'; foreach ($typesToDescribe as $j => $typeToDescribe) { if ($typeToDescribe instanceof AccessoryArrayListType) { $typeName = 'list'; if (count($typeNode->genericTypes) > 1) { array_shift($typeNode->genericTypes); } } elseif ($typeToDescribe instanceof NonEmptyArrayType) { $nonEmpty = \true; } else { continue; } unset($typesToDescribe[$j]); } if ($nonEmpty) { $typeName = 'non-empty-' . $typeName; } $describedTypes[$i] = new GenericTypeNode(new IdentifierTypeNode($typeName), $typeNode->genericTypes); continue; } if ($typeNode instanceof IdentifierTypeNode && in_array($typeNode->name, $skipTypeNames, \true)) { continue; } $describedTypes[$i] = $typeNode; } foreach ($typesToDescribe as $i => $typeToDescribe) { $describedTypes[$i] = $typeToDescribe->toPhpDocNode(); } ksort($describedTypes); $describedTypes = array_values($describedTypes); if (count($describedTypes) === 1) { return $describedTypes[0]; } return new IntersectionTypeNode($describedTypes); } } mapInternal($left, $right); } /** @param callable(Type $left, Type $right, callable(Type, Type): Type $traverse): Type $cb */ private function __construct(callable $cb) { $this->cb = $cb; } /** @internal */ public function mapInternal(\PHPStan\Type\Type $left, \PHPStan\Type\Type $right) : \PHPStan\Type\Type { return ($this->cb)($left, $right, [$this, 'traverseInternal']); } /** @internal */ public function traverseInternal(\PHPStan\Type\Type $left, \PHPStan\Type\Type $right) : \PHPStan\Type\Type { return $left->traverseSimultaneously($right, [$this, 'mapInternal']); } } className = $className; parent::__construct(sprintf('Class %s was not found while trying to analyse it - discovering symbols is probably not configured properly.', $className)); } public function getClassName() : string { return $this->className; } public function getTip() : string { return 'Learn more at https://phpstan.org/user-guide/discovering-symbols'; } } fileHelper = $fileHelper; $this->relativePathHelper = $relativePathHelper; } public function getAnonymousClassName(Node\Stmt\Class_ $classNode, string $filename) : string { if (isset($classNode->namespacedName)) { throw new ShouldNotHappenException(); } $filename = $this->relativePathHelper->getRelativePath($this->fileHelper->normalizePath($filename, '/')); /** @var int|null $lineIndex */ $lineIndex = $classNode->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX); if ($lineIndex === null) { $hash = md5(sprintf('%s:%s', $filename, $classNode->getStartLine())); } else { $hash = md5(sprintf('%s:%s:%d', $filename, $classNode->getStartLine(), $lineIndex)); } return sprintf('AnonymousClass%s', $hash); } } getMessage(), $functionName), 0, $previous); } else { parent::__construct(sprintf('Class %s not found.', $functionName), 0); } $this->className = $functionName; } public function getClassName() : string { return $this->className; } public function getTip() : string { return 'Learn more at https://phpstan.org/user-guide/discovering-symbols'; } } constantName = $constantName; parent::__construct(sprintf('Constant %s not found.', $constantName)); } public function getConstantName() : string { return $this->constantName; } public function getTip() : string { return 'Learn more at https://phpstan.org/user-guide/discovering-symbols'; } } functionName = $functionName; parent::__construct(sprintf('Function %s not found while trying to analyse it - discovering symbols is probably not configured properly.', $functionName)); } public function getFunctionName() : string { return $this->functionName; } public function getTip() : string { return 'Learn more at https://phpstan.org/user-guide/discovering-symbols'; } } reflectionProvider = $reflectionProvider; $this->universalObjectCratesClasses = $universalObjectCratesClasses; } public static function registerInstance(\PHPStan\Broker\Broker $broker) : void { self::$instance = $broker; } /** * @deprecated Use PHPStan\Reflection\ReflectionProviderStaticAccessor instead */ public static function getInstance() : \PHPStan\Broker\Broker { if (self::$instance === null) { throw new ShouldNotHappenException(); } return self::$instance; } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function hasClass(string $className) : bool { return $this->reflectionProvider->hasClass($className); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function getClass(string $className) : ClassReflection { return $this->reflectionProvider->getClass($className); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function getClassName(string $className) : string { return $this->reflectionProvider->getClassName($className); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function supportsAnonymousClasses() : bool { return $this->reflectionProvider->supportsAnonymousClasses(); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $scope) : ClassReflection { return $this->reflectionProvider->getAnonymousClassReflection($classNode, $scope); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function hasFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : bool { return $this->reflectionProvider->hasFunction($nameNode, $namespaceAnswerer); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function getFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : FunctionReflection { return $this->reflectionProvider->getFunction($nameNode, $namespaceAnswerer); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function resolveFunctionName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : ?string { return $this->reflectionProvider->resolveFunctionName($nameNode, $namespaceAnswerer); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function hasConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : bool { return $this->reflectionProvider->hasConstant($nameNode, $namespaceAnswerer); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : GlobalConstantReflection { return $this->reflectionProvider->getConstant($nameNode, $namespaceAnswerer); } /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ public function resolveConstantName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : ?string { return $this->reflectionProvider->resolveConstantName($nameNode, $namespaceAnswerer); } /** * @deprecated Inject %universalObjectCratesClasses% parameter instead. * * @return string[] */ public function getUniversalObjectCratesClasses() : array { return $this->universalObjectCratesClasses; } } container = $container; } public function create() : \PHPStan\Broker\Broker { return new \PHPStan\Broker\Broker($this->container->getByType(ReflectionProvider::class), $this->container->getParameter('universalObjectCratesClasses')); } } registry = $registry; } public function getRegistry() : \PHPStan\PhpDoc\TypeNodeResolverExtensionRegistry { return $this->registry; } } */ private $genericTypeResolvingStack = []; public function __construct(\PHPStan\PhpDoc\TypeNodeResolverExtensionRegistryProvider $extensionRegistryProvider, ReflectionProvider\ReflectionProviderProvider $reflectionProviderProvider, TypeAliasResolverProvider $typeAliasResolverProvider, ConstantResolver $constantResolver, InitializerExprTypeResolver $initializerExprTypeResolver) { $this->extensionRegistryProvider = $extensionRegistryProvider; $this->reflectionProviderProvider = $reflectionProviderProvider; $this->typeAliasResolverProvider = $typeAliasResolverProvider; $this->constantResolver = $constantResolver; $this->initializerExprTypeResolver = $initializerExprTypeResolver; } /** @api */ public function resolve(TypeNode $typeNode, NameScope $nameScope) : Type { foreach ($this->extensionRegistryProvider->getRegistry()->getExtensions() as $extension) { $type = $extension->resolve($typeNode, $nameScope); if ($type !== null) { return $type; } } if ($typeNode instanceof IdentifierTypeNode) { return $this->resolveIdentifierTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof ThisTypeNode) { return $this->resolveThisTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof NullableTypeNode) { return $this->resolveNullableTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof UnionTypeNode) { return $this->resolveUnionTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof IntersectionTypeNode) { return $this->resolveIntersectionTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof ConditionalTypeNode) { return $this->resolveConditionalTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof ConditionalTypeForParameterNode) { return $this->resolveConditionalTypeForParameterNode($typeNode, $nameScope); } elseif ($typeNode instanceof ArrayTypeNode) { return $this->resolveArrayTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof GenericTypeNode) { return $this->resolveGenericTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof CallableTypeNode) { return $this->resolveCallableTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof ArrayShapeNode) { return $this->resolveArrayShapeNode($typeNode, $nameScope); } elseif ($typeNode instanceof ObjectShapeNode) { return $this->resolveObjectShapeNode($typeNode, $nameScope); } elseif ($typeNode instanceof ConstTypeNode) { return $this->resolveConstTypeNode($typeNode, $nameScope); } elseif ($typeNode instanceof OffsetAccessTypeNode) { return $this->resolveOffsetAccessNode($typeNode, $nameScope); } elseif ($typeNode instanceof InvalidTypeNode) { return new MixedType(\true); } return new ErrorType(); } private function resolveIdentifierTypeNode(IdentifierTypeNode $typeNode, NameScope $nameScope) : Type { switch (strtolower($typeNode->name)) { case 'int': case 'integer': return new IntegerType(); case 'positive-int': return IntegerRangeType::fromInterval(1, null); case 'negative-int': return IntegerRangeType::fromInterval(null, -1); case 'non-positive-int': return IntegerRangeType::fromInterval(null, 0); case 'non-negative-int': return IntegerRangeType::fromInterval(0, null); case 'non-zero-int': return new UnionType([IntegerRangeType::fromInterval(null, -1), IntegerRangeType::fromInterval(1, null)]); case 'string': return new StringType(); case 'lowercase-string': return new IntersectionType([new StringType(), new AccessoryLowercaseStringType()]); case 'uppercase-string': return new IntersectionType([new StringType(), new AccessoryUppercaseStringType()]); case 'literal-string': return new IntersectionType([new StringType(), new AccessoryLiteralStringType()]); case 'class-string': case 'interface-string': case 'trait-string': case 'enum-string': return new ClassStringType(); case 'callable-string': return new IntersectionType([new StringType(), new CallableType()]); case 'array-key': return new BenevolentUnionType([new IntegerType(), new StringType()]); case 'scalar': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } return new UnionType([new IntegerType(), new FloatType(), new StringType(), new BooleanType()]); case 'empty-scalar': return TypeCombinator::intersect(new UnionType([new IntegerType(), new FloatType(), new StringType(), new BooleanType()]), StaticTypeFactory::falsey()); case 'non-empty-scalar': return TypeCombinator::remove(new UnionType([new IntegerType(), new FloatType(), new StringType(), new BooleanType()]), StaticTypeFactory::falsey()); case 'number': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } return new UnionType([new IntegerType(), new FloatType()]); case 'numeric': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } return new UnionType([new IntegerType(), new FloatType(), new IntersectionType([new StringType(), new AccessoryNumericStringType()])]); case 'numeric-string': return new IntersectionType([new StringType(), new AccessoryNumericStringType()]); case 'non-empty-string': return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()]); case 'non-empty-lowercase-string': return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType(), new AccessoryLowercaseStringType()]); case 'non-empty-uppercase-string': return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType(), new AccessoryUppercaseStringType()]); case 'truthy-string': case 'non-falsy-string': return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); case 'non-empty-literal-string': return new IntersectionType([new StringType(), new AccessoryNonEmptyStringType(), new AccessoryLiteralStringType()]); case 'bool': return new BooleanType(); case 'boolean': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } return new BooleanType(); case 'true': return new ConstantBooleanType(\true); case 'false': return new ConstantBooleanType(\false); case 'null': return new NullType(); case 'float': return new FloatType(); case 'double': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } return new FloatType(); case 'array': case 'associative-array': return new ArrayType(new MixedType(), new MixedType()); case 'non-empty-array': return TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new NonEmptyArrayType()); case 'iterable': return new IterableType(new MixedType(), new MixedType()); case 'callable': return new CallableType(); case 'pure-callable': return new CallableType(null, null, \true, null, null, [], TrinaryLogic::createYes()); case 'pure-closure': return ClosureType::createPure(); case 'resource': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } return new ResourceType(); case 'open-resource': case 'closed-resource': return new ResourceType(); case 'mixed': return new MixedType(\true); case 'non-empty-mixed': return new MixedType(\true, StaticTypeFactory::falsey()); case 'void': return new VoidType(); case 'object': return new ObjectWithoutClassType(); case 'callable-object': return new IntersectionType([new ObjectWithoutClassType(), new CallableType()]); case 'callable-array': return new IntersectionType([new ArrayType(new MixedType(), new MixedType()), new CallableType()]); case 'never': case 'noreturn': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } return new NonAcceptingNeverType(); case 'never-return': case 'never-returns': case 'no-return': return new NonAcceptingNeverType(); case 'list': return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new MixedType())); case 'non-empty-list': return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(new ArrayType(new IntegerType(), new MixedType()), new NonEmptyArrayType())); case '__always-list': return TypeCombinator::intersect(new ArrayType(new IntegerType(), new MixedType()), new AccessoryArrayListType()); case 'empty': $type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope); if ($type !== null) { return $type; } return StaticTypeFactory::falsey(); case '__stringandstringable': return new StringAlwaysAcceptingObjectWithToStringType(); } if ($nameScope->getClassName() !== null) { switch (strtolower($typeNode->name)) { case 'self': return new ObjectType($nameScope->getClassName()); case 'static': if ($this->getReflectionProvider()->hasClass($nameScope->getClassName())) { $classReflection = $this->getReflectionProvider()->getClass($nameScope->getClassName()); return new StaticType($classReflection); } return new ErrorType(); case 'parent': if ($this->getReflectionProvider()->hasClass($nameScope->getClassName())) { $classReflection = $this->getReflectionProvider()->getClass($nameScope->getClassName()); if ($classReflection->getParentClass() !== null) { return new ObjectType($classReflection->getParentClass()->getName()); } } return new NonexistentParentClassType(); } } if (!$nameScope->shouldBypassTypeAliases()) { $typeAlias = $this->getTypeAliasResolver()->resolveTypeAlias($typeNode->name, $nameScope); if ($typeAlias !== null) { return $typeAlias; } } $templateType = $nameScope->resolveTemplateTypeName($typeNode->name); if ($templateType !== null) { return $templateType; } $stringName = $nameScope->resolveStringName($typeNode->name); if (str_contains($stringName, '-') && !str_starts_with($stringName, 'OCI-')) { return new ErrorType(); } if ($this->mightBeConstant($typeNode->name) && !$this->getReflectionProvider()->hasClass($stringName)) { $constType = $this->tryResolveConstant($typeNode->name, $nameScope); if ($constType !== null) { return $constType; } } return new ObjectType($stringName); } private function mightBeConstant(string $name) : bool { return preg_match('((?:^|\\\\)[A-Z_][A-Z0-9_]*$)', $name) > 0; } private function tryResolveConstant(string $name, NameScope $nameScope) : ?Type { foreach ($nameScope->resolveConstantNames($name) as $constName) { $nameNode = new Name\FullyQualified(explode('\\', $constName)); $constType = $this->constantResolver->resolveConstant($nameNode, null); if ($constType !== null) { return $constType; } } return null; } private function tryResolvePseudoTypeClassType(IdentifierTypeNode $typeNode, NameScope $nameScope) : ?Type { if ($nameScope->hasUseAlias($typeNode->name)) { return new ObjectType($nameScope->resolveStringName($typeNode->name)); } if ($nameScope->getNamespace() === null) { return null; } $className = $nameScope->resolveStringName($typeNode->name); if ($this->getReflectionProvider()->hasClass($className)) { return new ObjectType($className); } return null; } private function resolveThisTypeNode(ThisTypeNode $typeNode, NameScope $nameScope) : Type { $className = $nameScope->getClassName(); if ($className !== null) { if ($this->getReflectionProvider()->hasClass($className)) { return new ThisType($this->getReflectionProvider()->getClass($className)); } } return new ErrorType(); } private function resolveNullableTypeNode(NullableTypeNode $typeNode, NameScope $nameScope) : Type { return TypeCombinator::union($this->resolve($typeNode->type, $nameScope), new NullType()); } private function resolveUnionTypeNode(UnionTypeNode $typeNode, NameScope $nameScope) : Type { $iterableTypeNodes = []; $otherTypeNodes = []; foreach ($typeNode->types as $innerTypeNode) { if ($innerTypeNode instanceof ArrayTypeNode) { $iterableTypeNodes[] = $innerTypeNode->type; } else { $otherTypeNodes[] = $innerTypeNode; } } $otherTypeTypes = $this->resolveMultiple($otherTypeNodes, $nameScope); if (count($iterableTypeNodes) > 0) { $arrayTypeTypes = $this->resolveMultiple($iterableTypeNodes, $nameScope); $arrayTypeType = TypeCombinator::union(...$arrayTypeTypes); $addArray = \true; foreach ($otherTypeTypes as &$type) { if (!$type->isIterable()->yes() || !$type->getIterableValueType()->isSuperTypeOf($arrayTypeType)->yes()) { continue; } if ($type instanceof ObjectType) { $type = new IntersectionType([$type, new IterableType(new MixedType(), $arrayTypeType)]); } elseif ($type instanceof ArrayType) { $type = new ArrayType(new MixedType(), $arrayTypeType); } elseif ($type instanceof IterableType) { $type = new IterableType(new MixedType(), $arrayTypeType); } else { continue; } $addArray = \false; } if ($addArray) { $otherTypeTypes[] = new ArrayType(new MixedType(), $arrayTypeType); } } return TypeCombinator::union(...$otherTypeTypes); } private function resolveIntersectionTypeNode(IntersectionTypeNode $typeNode, NameScope $nameScope) : Type { $types = $this->resolveMultiple($typeNode->types, $nameScope); return TypeCombinator::intersect(...$types); } private function resolveConditionalTypeNode(ConditionalTypeNode $typeNode, NameScope $nameScope) : Type { return new ConditionalType($this->resolve($typeNode->subjectType, $nameScope), $this->resolve($typeNode->targetType, $nameScope), $this->resolve($typeNode->if, $nameScope), $this->resolve($typeNode->else, $nameScope), $typeNode->negated); } private function resolveConditionalTypeForParameterNode(ConditionalTypeForParameterNode $typeNode, NameScope $nameScope) : Type { return new ConditionalTypeForParameter($typeNode->parameterName, $this->resolve($typeNode->targetType, $nameScope), $this->resolve($typeNode->if, $nameScope), $this->resolve($typeNode->else, $nameScope), $typeNode->negated); } private function resolveArrayTypeNode(ArrayTypeNode $typeNode, NameScope $nameScope) : Type { $itemType = $this->resolve($typeNode->type, $nameScope); return new ArrayType(new BenevolentUnionType([new IntegerType(), new StringType()]), $itemType); } private function resolveGenericTypeNode(GenericTypeNode $typeNode, NameScope $nameScope) : Type { $mainTypeName = strtolower($typeNode->type->name); $genericTypes = $this->resolveMultiple($typeNode->genericTypes, $nameScope); $variances = array_map(static function (string $variance) : TemplateTypeVariance { switch ($variance) { case GenericTypeNode::VARIANCE_INVARIANT: return TemplateTypeVariance::createInvariant(); case GenericTypeNode::VARIANCE_COVARIANT: return TemplateTypeVariance::createCovariant(); case GenericTypeNode::VARIANCE_CONTRAVARIANT: return TemplateTypeVariance::createContravariant(); case GenericTypeNode::VARIANCE_BIVARIANT: return TemplateTypeVariance::createBivariant(); } }, $typeNode->variances); if (in_array($mainTypeName, ['array', 'non-empty-array'], \true)) { if (count($genericTypes) === 1) { // array $arrayType = new ArrayType(new BenevolentUnionType([new IntegerType(), new StringType()]), $genericTypes[0]); } elseif (count($genericTypes) === 2) { // array $keyType = TypeCombinator::intersect($genericTypes[0], new UnionType([new IntegerType(), new StringType()])); $arrayType = new ArrayType($keyType->toArrayKey(), $genericTypes[1]); } else { return new ErrorType(); } if ($mainTypeName === 'non-empty-array') { return TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } return $arrayType; } elseif (in_array($mainTypeName, ['list', 'non-empty-list'], \true)) { if (count($genericTypes) === 1) { // list $listType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $genericTypes[0])); if ($mainTypeName === 'non-empty-list') { return TypeCombinator::intersect($listType, new NonEmptyArrayType()); } return $listType; } return new ErrorType(); } elseif ($mainTypeName === 'iterable') { if (count($genericTypes) === 1) { // iterable return new IterableType(new MixedType(\true), $genericTypes[0]); } if (count($genericTypes) === 2) { // iterable return new IterableType($genericTypes[0], $genericTypes[1]); } } elseif (in_array($mainTypeName, ['class-string', 'interface-string'], \true)) { if (count($genericTypes) === 1) { $genericType = $genericTypes[0]; if ($genericType->isObject()->yes() || $genericType instanceof MixedType) { return new GenericClassStringType($genericType); } } return new ErrorType(); } elseif ($mainTypeName === 'int') { if (count($genericTypes) === 2) { // int, int<1, 3> if ($genericTypes[0] instanceof ConstantIntegerType) { $min = $genericTypes[0]->getValue(); } elseif ($typeNode->genericTypes[0] instanceof IdentifierTypeNode && $typeNode->genericTypes[0]->name === 'min') { $min = null; } else { return new ErrorType(); } if ($genericTypes[1] instanceof ConstantIntegerType) { $max = $genericTypes[1]->getValue(); } elseif ($typeNode->genericTypes[1] instanceof IdentifierTypeNode && $typeNode->genericTypes[1]->name === 'max') { $max = null; } else { return new ErrorType(); } return IntegerRangeType::fromInterval($min, $max); } } elseif ($mainTypeName === 'key-of') { if (count($genericTypes) === 1) { // key-of $type = new KeyOfType($genericTypes[0]); return $type->isResolvable() ? $type->resolve() : $type; } return new ErrorType(); } elseif ($mainTypeName === 'value-of') { if (count($genericTypes) === 1) { // value-of $type = new ValueOfType($genericTypes[0]); return $type->isResolvable() ? $type->resolve() : $type; } return new ErrorType(); } elseif ($mainTypeName === 'int-mask-of') { if (count($genericTypes) === 1) { // int-mask-of $maskType = $this->expandIntMaskToType($genericTypes[0]); if ($maskType !== null) { return $maskType; } } return new ErrorType(); } elseif ($mainTypeName === 'int-mask') { if (count($genericTypes) > 0) { // int-mask<1, 2, 4> $maskType = $this->expandIntMaskToType(TypeCombinator::union(...$genericTypes)); if ($maskType !== null) { return $maskType; } } return new ErrorType(); } elseif ($mainTypeName === '__benevolent') { if (count($genericTypes) === 1) { return TypeUtils::toBenevolentUnion($genericTypes[0]); } return new ErrorType(); } elseif ($mainTypeName === 'template-type') { if (count($genericTypes) === 3) { $result = []; /** @var class-string $ancestorClassName */ foreach ($genericTypes[1]->getObjectClassNames() as $ancestorClassName) { foreach ($genericTypes[2]->getConstantStrings() as $templateTypeName) { $result[] = new GetTemplateTypeType($genericTypes[0], $ancestorClassName, $templateTypeName->getValue()); } } return TypeCombinator::union(...$result); } return new ErrorType(); } elseif ($mainTypeName === 'new') { if (count($genericTypes) === 1) { $type = new NewObjectType($genericTypes[0]); return $type->isResolvable() ? $type->resolve() : $type; } return new ErrorType(); } elseif ($mainTypeName === 'static') { if ($nameScope->getClassName() !== null && $this->getReflectionProvider()->hasClass($nameScope->getClassName())) { $classReflection = $this->getReflectionProvider()->getClass($nameScope->getClassName()); return new GenericStaticType($classReflection, $genericTypes, null, $variances); } return new ErrorType(); } $mainType = $this->resolveIdentifierTypeNode($typeNode->type, $nameScope); $mainTypeObjectClassNames = $mainType->getObjectClassNames(); if (count($mainTypeObjectClassNames) > 1) { if ($mainType instanceof TemplateType) { return new ErrorType(); } throw new ShouldNotHappenException(); } $mainTypeClassName = $mainTypeObjectClassNames[0] ?? null; if ($mainTypeClassName !== null) { if (!$this->getReflectionProvider()->hasClass($mainTypeClassName)) { return new GenericObjectType($mainTypeClassName, $genericTypes, null, null, $variances); } $classReflection = $this->getReflectionProvider()->getClass($mainTypeClassName); if ($classReflection->isGeneric()) { $templateTypes = array_values($classReflection->getTemplateTypeMap()->getTypes()); for ($i = count($genericTypes), $templateTypesCount = count($templateTypes); $i < $templateTypesCount; $i++) { $templateType = $templateTypes[$i]; if (!$templateType instanceof TemplateType || $templateType->getDefault() === null) { continue; } $genericTypes[] = $templateType->getDefault(); } if (in_array($mainTypeClassName, [Traversable::class, IteratorAggregate::class, Iterator::class], \true)) { if (count($genericTypes) === 1) { return new GenericObjectType($mainTypeClassName, [new MixedType(\true), $genericTypes[0]], null, null, [TemplateTypeVariance::createInvariant(), $variances[0]]); } if (count($genericTypes) === 2) { return new GenericObjectType($mainTypeClassName, [$genericTypes[0], $genericTypes[1]], null, null, [$variances[0], $variances[1]]); } } if ($mainTypeClassName === Generator::class) { if (count($genericTypes) === 1) { $mixed = new MixedType(\true); return new GenericObjectType($mainTypeClassName, [$mixed, $genericTypes[0], $mixed, $mixed], null, null, [TemplateTypeVariance::createInvariant(), $variances[0], TemplateTypeVariance::createInvariant(), TemplateTypeVariance::createInvariant()]); } if (count($genericTypes) === 2) { $mixed = new MixedType(\true); return new GenericObjectType($mainTypeClassName, [$genericTypes[0], $genericTypes[1], $mixed, $mixed], null, null, [$variances[0], $variances[1], TemplateTypeVariance::createInvariant(), TemplateTypeVariance::createInvariant()]); } } if (!$mainType->isIterable()->yes()) { return new GenericObjectType($mainTypeClassName, $genericTypes, null, null, $variances); } if (count($genericTypes) !== 1 || $classReflection->getTemplateTypeMap()->count() === 1) { return new GenericObjectType($mainTypeClassName, $genericTypes, null, null, $variances); } } } if ($mainType->isIterable()->yes()) { if ($mainTypeClassName !== null) { if (isset($this->genericTypeResolvingStack[$mainTypeClassName])) { return new ErrorType(); } $this->genericTypeResolvingStack[$mainTypeClassName] = \true; } try { if (count($genericTypes) === 1) { // Foo return TypeCombinator::intersect($mainType, new IterableType(new MixedType(\true), $genericTypes[0])); } if (count($genericTypes) === 2) { // Foo return TypeCombinator::intersect($mainType, new IterableType($genericTypes[0], $genericTypes[1])); } } finally { if ($mainTypeClassName !== null) { unset($this->genericTypeResolvingStack[$mainTypeClassName]); } } } if ($mainTypeClassName !== null) { return new GenericObjectType($mainTypeClassName, $genericTypes, null, null, $variances); } return new ErrorType(); } private function resolveCallableTypeNode(CallableTypeNode $typeNode, NameScope $nameScope) : Type { $templateTags = []; if (count($typeNode->templateTypes ?? []) > 0) { foreach ($typeNode->templateTypes as $templateType) { $templateTags[$templateType->name] = new TemplateTag($templateType->name, $templateType->bound !== null ? $this->resolve($templateType->bound, $nameScope) : new MixedType(), $templateType->default !== null ? $this->resolve($templateType->default, $nameScope) : null, TemplateTypeVariance::createInvariant()); } $templateTypeScope = TemplateTypeScope::createWithAnonymousFunction(); $templateTypeMap = new TemplateTypeMap(array_map(static function (TemplateTag $tag) use($templateTypeScope) : Type { return TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag); }, $templateTags)); $nameScope = $nameScope->withTemplateTypeMap($templateTypeMap); } else { $templateTypeMap = TemplateTypeMap::createEmpty(); } $mainType = $this->resolve($typeNode->identifier, $nameScope); $isVariadic = \false; $parameters = array_map(function (CallableTypeParameterNode $parameterNode) use($nameScope, &$isVariadic) : NativeParameterReflection { $isVariadic = $isVariadic || $parameterNode->isVariadic; $parameterName = $parameterNode->parameterName; if (str_starts_with($parameterName, '$')) { $parameterName = substr($parameterName, 1); } return new NativeParameterReflection($parameterName, $parameterNode->isOptional || $parameterNode->isVariadic, $this->resolve($parameterNode->type, $nameScope), $parameterNode->isReference ? PassedByReference::createCreatesNewVariable() : PassedByReference::createNo(), $parameterNode->isVariadic, null); }, $typeNode->parameters); $returnType = $this->resolve($typeNode->returnType, $nameScope); if ($mainType instanceof CallableType) { $pure = $mainType->isPure(); if ($pure->yes() && $returnType->isVoid()->yes()) { return new ErrorType(); } return new CallableType($parameters, $returnType, $isVariadic, $templateTypeMap, null, $templateTags, $pure); } elseif ($mainType instanceof ObjectType && $mainType->getClassName() === Closure::class) { return new ClosureType($parameters, $returnType, $isVariadic, $templateTypeMap, null, null, $templateTags, [], [new SimpleImpurePoint('functionCall', 'call to a Closure', \false)]); } elseif ($mainType instanceof ClosureType) { $closure = new ClosureType($parameters, $returnType, $isVariadic, $templateTypeMap, null, null, $templateTags, [], $mainType->getImpurePoints(), $mainType->getInvalidateExpressions(), $mainType->getUsedVariables(), $mainType->acceptsNamedArguments()); if ($closure->isPure()->yes() && $returnType->isVoid()->yes()) { return new ErrorType(); } return $closure; } return new ErrorType(); } private function resolveArrayShapeNode(ArrayShapeNode $typeNode, NameScope $nameScope) : Type { $builder = ConstantArrayTypeBuilder::createEmpty(); if (count($typeNode->items) > ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { $builder->degradeToGeneralArray(\true); } foreach ($typeNode->items as $itemNode) { $offsetType = null; if ($itemNode->keyName instanceof ConstExprIntegerNode) { $offsetType = new ConstantIntegerType((int) $itemNode->keyName->value); } elseif ($itemNode->keyName instanceof IdentifierTypeNode) { $offsetType = new ConstantStringType($itemNode->keyName->name); } elseif ($itemNode->keyName instanceof ConstExprStringNode) { $offsetType = new ConstantStringType($itemNode->keyName->value); } elseif ($itemNode->keyName !== null) { throw new ShouldNotHappenException('Unsupported key node type: ' . get_class($itemNode->keyName)); } $builder->setOffsetValueType($offsetType, $this->resolve($itemNode->valueType, $nameScope), $itemNode->optional); } $arrayType = $builder->getArray(); if (in_array($typeNode->kind, [ArrayShapeNode::KIND_LIST, ArrayShapeNode::KIND_NON_EMPTY_LIST], \true)) { $arrayType = AccessoryArrayListType::intersectWith($arrayType); } if (in_array($typeNode->kind, [ArrayShapeNode::KIND_NON_EMPTY_ARRAY, ArrayShapeNode::KIND_NON_EMPTY_LIST], \true)) { $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } return $arrayType; } private function resolveObjectShapeNode(ObjectShapeNode $typeNode, NameScope $nameScope) : Type { $properties = []; $optionalProperties = []; foreach ($typeNode->items as $itemNode) { if ($itemNode->keyName instanceof IdentifierTypeNode) { $propertyName = $itemNode->keyName->name; } elseif ($itemNode->keyName instanceof ConstExprStringNode) { $propertyName = $itemNode->keyName->value; } if ($itemNode->optional) { $optionalProperties[] = $propertyName; } $properties[$propertyName] = $this->resolve($itemNode->valueType, $nameScope); } return new ObjectShapeType($properties, $optionalProperties); } private function resolveConstTypeNode(ConstTypeNode $typeNode, NameScope $nameScope) : Type { $constExpr = $typeNode->constExpr; if ($constExpr instanceof ConstExprArrayNode) { throw new ShouldNotHappenException(); // we prefer array shapes } if ($constExpr instanceof ConstExprFalseNode || $constExpr instanceof ConstExprTrueNode || $constExpr instanceof ConstExprNullNode) { throw new ShouldNotHappenException(); // we prefer IdentifierTypeNode } if ($constExpr instanceof ConstFetchNode) { if ($constExpr->className === '') { throw new ShouldNotHappenException(); // global constant should get parsed as class name in IdentifierTypeNode } if ($nameScope->getClassName() !== null) { switch (strtolower($constExpr->className)) { case 'static': case 'self': $className = $nameScope->getClassName(); break; case 'parent': if ($this->getReflectionProvider()->hasClass($nameScope->getClassName())) { $classReflection = $this->getReflectionProvider()->getClass($nameScope->getClassName()); if ($classReflection->getParentClass() === null) { return new ErrorType(); } $className = $classReflection->getParentClass()->getName(); } break; } } if (!isset($className)) { $className = $nameScope->resolveStringName($constExpr->className); } if (!$this->getReflectionProvider()->hasClass($className)) { return new ErrorType(); } $classReflection = $this->getReflectionProvider()->getClass($className); $constantName = $constExpr->name; if (Strings::contains($constantName, '*')) { // convert * into .*? and escape everything else so the constants can be matched against the pattern $pattern = '{^' . str_replace('\\*', '.*?', preg_quote($constantName)) . '$}D'; $constantTypes = []; foreach ($classReflection->getNativeReflection()->getReflectionConstants() as $reflectionConstant) { $classConstantName = $reflectionConstant->getName(); if (Strings::match($classConstantName, $pattern) === null) { continue; } if ($classReflection->isEnum() && $classReflection->hasEnumCase($classConstantName)) { $constantTypes[] = new EnumCaseObjectType($classReflection->getName(), $classConstantName); continue; } $declaringClassName = $reflectionConstant->getDeclaringClass()->getName(); if (!$this->getReflectionProvider()->hasClass($declaringClassName)) { continue; } $constantTypes[] = $this->initializerExprTypeResolver->getType($reflectionConstant->getValueExpression(), InitializerExprContext::fromClassReflection($this->getReflectionProvider()->getClass($declaringClassName))); } if (count($constantTypes) === 0) { return new ErrorType(); } return TypeCombinator::union(...$constantTypes); } if (!$classReflection->hasConstant($constantName)) { return new ErrorType(); } if ($classReflection->isEnum() && $classReflection->hasEnumCase($constantName)) { return new EnumCaseObjectType($classReflection->getName(), $constantName); } $reflectionConstant = $classReflection->getNativeReflection()->getReflectionConstant($constantName); if ($reflectionConstant === \false) { return new ErrorType(); } $declaringClass = $reflectionConstant->getDeclaringClass(); return $this->initializerExprTypeResolver->getType($reflectionConstant->getValueExpression(), InitializerExprContext::fromClass($declaringClass->getName(), $declaringClass->getFileName() ?: null)); } if ($constExpr instanceof ConstExprFloatNode) { return new ConstantFloatType((float) $constExpr->value); } if ($constExpr instanceof ConstExprIntegerNode) { return new ConstantIntegerType((int) $constExpr->value); } if ($constExpr instanceof ConstExprStringNode) { return new ConstantStringType($constExpr->value); } return new ErrorType(); } private function resolveOffsetAccessNode(OffsetAccessTypeNode $typeNode, NameScope $nameScope) : Type { $type = $this->resolve($typeNode->type, $nameScope); $offset = $this->resolve($typeNode->offset, $nameScope); if ($type->isOffsetAccessible()->no() || $type->hasOffsetValueType($offset)->no()) { return new ErrorType(); } return new OffsetAccessType($type, $offset); } private function expandIntMaskToType(Type $type) : ?Type { $ints = array_map(static function (ConstantIntegerType $type) { return $type->getValue(); }, TypeUtils::getConstantIntegers($type)); if (count($ints) === 0) { return null; } $values = []; foreach ($ints as $int) { if ($int !== 0 && !array_key_exists($int, $values)) { foreach ($values as $value) { $computedValue = $value | $int; $values[$computedValue] = $computedValue; } } $values[$int] = $int; } $values[0] = 0; $min = min($values); $max = max($values); if ($max - $min === count($values) - 1) { return IntegerRangeType::fromInterval($min, $max); } if (count($values) > InitializerExprTypeResolver::CALCULATE_SCALARS_LIMIT) { return IntegerRangeType::fromInterval($min, $max); } return TypeCombinator::union(...array_map(static function ($value) { return new ConstantIntegerType($value); }, $values)); } /** * @api * @param TypeNode[] $typeNodes * @return Type[] */ public function resolveMultiple(array $typeNodes, NameScope $nameScope) : array { $types = []; foreach ($typeNodes as $typeNode) { $types[] = $this->resolve($typeNode, $nameScope); } return $types; } private function getReflectionProvider() : ReflectionProvider { return $this->reflectionProviderProvider->getReflectionProvider(); } private function getTypeAliasResolver() : TypeAliasResolver { return $this->typeAliasResolverProvider->getTypeAliasResolver(); } } */ private $templateTags; /** * @var PhpDocNodeResolver */ private $phpDocNodeResolver; /** * @var ReflectionProvider */ private $reflectionProvider; /** @var array<(string|int), VarTag>|false */ private $varTags = \false; /** @var array|false */ private $methodTags = \false; /** @var array|false */ private $propertyTags = \false; /** @var array|false */ private $extendsTags = \false; /** @var array|false */ private $implementsTags = \false; /** @var array|false */ private $usesTags = \false; /** @var array|false */ private $paramTags = \false; /** @var array|false */ private $paramOutTags = \false; /** @var array|false */ private $paramsImmediatelyInvokedCallable = \false; /** @var array|false */ private $paramClosureThisTags = \false; /** * @var ReturnTag|false|null */ private $returnTag = \false; /** * @var ThrowsTag|false|null */ private $throwsTag = \false; /** @var array|false */ private $mixinTags = \false; /** @var array|false */ private $requireExtendsTags = \false; /** @var array|false */ private $requireImplementsTags = \false; /** @var array|false */ private $typeAliasTags = \false; /** @var array|false */ private $typeAliasImportTags = \false; /** @var array|false */ private $assertTags = \false; /** * @var SelfOutTypeTag|false|null */ private $selfOutTypeTag = \false; /** * @var DeprecatedTag|false|null */ private $deprecatedTag = \false; /** * @var ?bool */ private $isDeprecated = null; /** * @var ?bool */ private $isNotDeprecated = null; /** * @var ?bool */ private $isInternal = null; /** * @var ?bool */ private $isFinal = null; /** @var bool|'notLoaded'|null */ private $isPure = 'notLoaded'; /** * @var ?bool */ private $isReadOnly = null; /** * @var ?bool */ private $isImmutable = null; /** * @var ?bool */ private $isAllowedPrivateMutation = null; /** * @var ?bool */ private $hasConsistentConstructor = null; /** * @var ?bool */ private $acceptsNamedArguments = null; private function __construct() { } /** * @param TemplateTag[] $templateTags */ public static function create(PhpDocNode $phpDocNode, string $phpDocString, ?string $filename, NameScope $nameScope, TemplateTypeMap $templateTypeMap, array $templateTags, \PHPStan\PhpDoc\PhpDocNodeResolver $phpDocNodeResolver, ReflectionProvider $reflectionProvider) : self { // new property also needs to be added to withNameScope(), createEmpty() and merge() $self = new self(); $self->phpDocNode = $phpDocNode; $self->phpDocNodes = [$phpDocNode]; $self->phpDocString = $phpDocString; $self->filename = $filename; $self->nameScope = $nameScope; $self->templateTypeMap = $templateTypeMap; $self->templateTags = $templateTags; $self->phpDocNodeResolver = $phpDocNodeResolver; $self->reflectionProvider = $reflectionProvider; return $self; } public function withNameScope(NameScope $nameScope) : self { $self = new self(); $self->phpDocNode = $this->phpDocNode; $self->phpDocNodes = $this->phpDocNodes; $self->phpDocString = $this->phpDocString; $self->filename = $this->filename; $self->nameScope = $nameScope; $self->templateTypeMap = $this->templateTypeMap; $self->templateTags = $this->templateTags; $self->phpDocNodeResolver = $this->phpDocNodeResolver; $self->reflectionProvider = $this->reflectionProvider; return $self; } public static function createEmpty() : self { // new property also needs to be added to merge() $self = new self(); $self->phpDocString = self::EMPTY_DOC_STRING; $self->phpDocNodes = []; $self->filename = null; $self->templateTypeMap = TemplateTypeMap::createEmpty(); $self->templateTags = []; $self->varTags = []; $self->methodTags = []; $self->propertyTags = []; $self->extendsTags = []; $self->implementsTags = []; $self->usesTags = []; $self->paramTags = []; $self->paramOutTags = []; $self->paramsImmediatelyInvokedCallable = []; $self->paramClosureThisTags = []; $self->returnTag = null; $self->throwsTag = null; $self->mixinTags = []; $self->requireExtendsTags = []; $self->requireImplementsTags = []; $self->typeAliasTags = []; $self->typeAliasImportTags = []; $self->assertTags = []; $self->selfOutTypeTag = null; $self->deprecatedTag = null; $self->isDeprecated = \false; $self->isNotDeprecated = \false; $self->isInternal = \false; $self->isFinal = \false; $self->isPure = null; $self->isReadOnly = \false; $self->isImmutable = \false; $self->isAllowedPrivateMutation = \false; $self->hasConsistentConstructor = \false; $self->acceptsNamedArguments = \true; return $self; } /** * @param array $parents * @param array $parentPhpDocBlocks */ public function merge(array $parents, array $parentPhpDocBlocks) : self { $className = $this->nameScope !== null ? $this->nameScope->getClassName() : null; $classReflection = $className !== null && $this->reflectionProvider->hasClass($className) ? $this->reflectionProvider->getClass($className) : null; // new property also needs to be added to createEmpty() $result = new self(); // we will resolve everything on $this here so these properties don't have to be populated // skip $result->phpDocNode $phpDocNodes = $this->phpDocNodes; $acceptsNamedArguments = $this->acceptsNamedArguments(); foreach ($parents as $parent) { foreach ($parent->phpDocNodes as $phpDocNode) { $phpDocNodes[] = $phpDocNode; $acceptsNamedArguments = $acceptsNamedArguments && $parent->acceptsNamedArguments(); } } $result->phpDocNodes = $phpDocNodes; $result->phpDocString = $this->phpDocString; $result->filename = $this->filename; // skip $result->nameScope $result->templateTypeMap = $this->templateTypeMap; $result->templateTags = $this->templateTags; // skip $result->phpDocNodeResolver $result->varTags = self::mergeVarTags($this->getVarTags(), $parents, $parentPhpDocBlocks); $result->methodTags = $this->getMethodTags(); $result->propertyTags = $this->getPropertyTags(); $result->extendsTags = $this->getExtendsTags(); $result->implementsTags = $this->getImplementsTags(); $result->usesTags = $this->getUsesTags(); $result->paramTags = self::mergeParamTags($this->getParamTags(), $parents, $parentPhpDocBlocks); $result->paramOutTags = self::mergeParamOutTags($this->getParamOutTags(), $parents, $parentPhpDocBlocks); $result->paramsImmediatelyInvokedCallable = self::mergeParamsImmediatelyInvokedCallable($this->getParamsImmediatelyInvokedCallable(), $parents, $parentPhpDocBlocks); $result->paramClosureThisTags = self::mergeParamClosureThisTags($this->getParamClosureThisTags(), $parents, $parentPhpDocBlocks); $result->returnTag = self::mergeReturnTags($this->getReturnTag(), $classReflection, $parents, $parentPhpDocBlocks); $result->throwsTag = self::mergeThrowsTags($this->getThrowsTag(), $parents); $result->mixinTags = $this->getMixinTags(); $result->requireExtendsTags = $this->getRequireExtendsTags(); $result->requireImplementsTags = $this->getRequireImplementsTags(); $result->typeAliasTags = $this->getTypeAliasTags(); $result->typeAliasImportTags = $this->getTypeAliasImportTags(); $result->assertTags = self::mergeAssertTags($this->getAssertTags(), $parents, $parentPhpDocBlocks); $result->selfOutTypeTag = self::mergeSelfOutTypeTags($this->getSelfOutTag(), $parents); $result->deprecatedTag = self::mergeDeprecatedTags($this->getDeprecatedTag(), $this->isNotDeprecated(), $parents); $result->isDeprecated = $result->deprecatedTag !== null; $result->isNotDeprecated = $this->isNotDeprecated(); $result->isInternal = $this->isInternal(); $result->isFinal = $this->isFinal(); $result->isPure = self::mergePureTags($this->isPure(), $parents); $result->isReadOnly = $this->isReadOnly(); $result->isImmutable = $this->isImmutable(); $result->isAllowedPrivateMutation = $this->isAllowedPrivateMutation(); $result->hasConsistentConstructor = $this->hasConsistentConstructor(); $result->acceptsNamedArguments = $acceptsNamedArguments; return $result; } /** * @param array $parameterNameMapping */ public function changeParameterNamesByMapping(array $parameterNameMapping) : self { if (count($this->phpDocNodes) === 0) { return $this; } $mapParameterCb = static function (Type $type, callable $traverse) use($parameterNameMapping) : Type { if ($type instanceof ConditionalTypeForParameter) { $parameterName = substr($type->getParameterName(), 1); if (array_key_exists($parameterName, $parameterNameMapping)) { $type = $type->changeParameterName('$' . $parameterNameMapping[$parameterName]); } } return $traverse($type); }; $newParamTags = []; foreach ($this->getParamTags() as $key => $paramTag) { if (!array_key_exists($key, $parameterNameMapping)) { continue; } $transformedType = TypeTraverser::map($paramTag->getType(), $mapParameterCb); $newParamTags[$parameterNameMapping[$key]] = $paramTag->withType($transformedType); } $newParamOutTags = []; foreach ($this->getParamOutTags() as $key => $paramOutTag) { if (!array_key_exists($key, $parameterNameMapping)) { continue; } $transformedType = TypeTraverser::map($paramOutTag->getType(), $mapParameterCb); $newParamOutTags[$parameterNameMapping[$key]] = $paramOutTag->withType($transformedType); } $newParamsImmediatelyInvokedCallable = []; foreach ($this->getParamsImmediatelyInvokedCallable() as $key => $immediatelyInvokedCallable) { if (!array_key_exists($key, $parameterNameMapping)) { continue; } $newParamsImmediatelyInvokedCallable[$parameterNameMapping[$key]] = $immediatelyInvokedCallable; } $paramClosureThisTags = $this->getParamClosureThisTags(); $newParamClosureThisTags = []; foreach ($paramClosureThisTags as $key => $paramClosureThisTag) { if (!array_key_exists($key, $parameterNameMapping)) { continue; } $transformedType = TypeTraverser::map($paramClosureThisTag->getType(), $mapParameterCb); $newParamClosureThisTags[$parameterNameMapping[$key]] = $paramClosureThisTag->withType($transformedType); } $returnTag = $this->getReturnTag(); if ($returnTag !== null) { $transformedType = TypeTraverser::map($returnTag->getType(), $mapParameterCb); $returnTag = $returnTag->withType($transformedType); } $assertTags = $this->getAssertTags(); if (count($assertTags) > 0) { $assertTags = array_map(static function (AssertTag $tag) use($parameterNameMapping) : AssertTag { $parameterName = substr($tag->getParameter()->getParameterName(), 1); if (array_key_exists($parameterName, $parameterNameMapping)) { $tag = $tag->withParameter($tag->getParameter()->changeParameterName('$' . $parameterNameMapping[$parameterName])); } return $tag; }, $assertTags); } $self = new self(); $self->phpDocNode = $this->phpDocNode; $self->phpDocNodes = $this->phpDocNodes; $self->phpDocString = $this->phpDocString; $self->filename = $this->filename; $self->nameScope = $this->nameScope; $self->templateTypeMap = $this->templateTypeMap; $self->templateTags = $this->templateTags; $self->phpDocNodeResolver = $this->phpDocNodeResolver; $self->reflectionProvider = $this->reflectionProvider; $self->varTags = $this->varTags; $self->methodTags = $this->methodTags; $self->propertyTags = $this->propertyTags; $self->extendsTags = $this->extendsTags; $self->implementsTags = $this->implementsTags; $self->usesTags = $this->usesTags; $self->paramTags = $newParamTags; $self->paramOutTags = $newParamOutTags; $self->paramsImmediatelyInvokedCallable = $newParamsImmediatelyInvokedCallable; $self->paramClosureThisTags = $newParamClosureThisTags; $self->returnTag = $returnTag; $self->throwsTag = $this->throwsTag; $self->mixinTags = $this->mixinTags; $self->requireImplementsTags = $this->requireImplementsTags; $self->requireExtendsTags = $this->requireExtendsTags; $self->typeAliasTags = $this->typeAliasTags; $self->typeAliasImportTags = $this->typeAliasImportTags; $self->assertTags = $assertTags; $self->selfOutTypeTag = $this->selfOutTypeTag; $self->deprecatedTag = $this->deprecatedTag; $self->isDeprecated = $this->isDeprecated; $self->isNotDeprecated = $this->isNotDeprecated; $self->isInternal = $this->isInternal; $self->isFinal = $this->isFinal; $self->isPure = $this->isPure; return $self; } public function hasPhpDocString() : bool { return $this->phpDocString !== self::EMPTY_DOC_STRING; } public function getPhpDocString() : string { return $this->phpDocString; } /** * @return PhpDocNode[] */ public function getPhpDocNodes() : array { return $this->phpDocNodes; } public function getFilename() : ?string { return $this->filename; } private function getNameScope() : NameScope { return $this->nameScope; } public function getNullableNameScope() : ?NameScope { return $this->nameScope; } /** * @return array<(string|int), VarTag> */ public function getVarTags() : array { if ($this->varTags === \false) { $this->varTags = $this->phpDocNodeResolver->resolveVarTags($this->phpDocNode, $this->getNameScope()); } return $this->varTags; } /** * @return array */ public function getMethodTags() : array { if ($this->methodTags === \false) { $this->methodTags = $this->phpDocNodeResolver->resolveMethodTags($this->phpDocNode, $this->getNameScope()); } return $this->methodTags; } /** * @return array */ public function getPropertyTags() : array { if ($this->propertyTags === \false) { $this->propertyTags = $this->phpDocNodeResolver->resolvePropertyTags($this->phpDocNode, $this->getNameScope()); } return $this->propertyTags; } /** * @return array */ public function getTemplateTags() : array { return $this->templateTags; } /** * @return array */ public function getExtendsTags() : array { if ($this->extendsTags === \false) { $this->extendsTags = $this->phpDocNodeResolver->resolveExtendsTags($this->phpDocNode, $this->getNameScope()); } return $this->extendsTags; } /** * @return array */ public function getImplementsTags() : array { if ($this->implementsTags === \false) { $this->implementsTags = $this->phpDocNodeResolver->resolveImplementsTags($this->phpDocNode, $this->getNameScope()); } return $this->implementsTags; } /** * @return array */ public function getUsesTags() : array { if ($this->usesTags === \false) { $this->usesTags = $this->phpDocNodeResolver->resolveUsesTags($this->phpDocNode, $this->getNameScope()); } return $this->usesTags; } /** * @return array */ public function getParamTags() : array { if ($this->paramTags === \false) { $this->paramTags = $this->phpDocNodeResolver->resolveParamTags($this->phpDocNode, $this->getNameScope()); } return $this->paramTags; } /** * @return array */ public function getParamOutTags() : array { if ($this->paramOutTags === \false) { $this->paramOutTags = $this->phpDocNodeResolver->resolveParamOutTags($this->phpDocNode, $this->getNameScope()); } return $this->paramOutTags; } /** * @return array */ public function getParamsImmediatelyInvokedCallable() : array { if ($this->paramsImmediatelyInvokedCallable === \false) { $this->paramsImmediatelyInvokedCallable = $this->phpDocNodeResolver->resolveParamImmediatelyInvokedCallable($this->phpDocNode); } return $this->paramsImmediatelyInvokedCallable; } /** * @return array */ public function getParamClosureThisTags() : array { if ($this->paramClosureThisTags === \false) { $this->paramClosureThisTags = $this->phpDocNodeResolver->resolveParamClosureThisTags($this->phpDocNode, $this->getNameScope()); } return $this->paramClosureThisTags; } public function getReturnTag() : ?ReturnTag { if (is_bool($this->returnTag)) { $this->returnTag = $this->phpDocNodeResolver->resolveReturnTag($this->phpDocNode, $this->getNameScope()); } return $this->returnTag; } public function getThrowsTag() : ?ThrowsTag { if (is_bool($this->throwsTag)) { $this->throwsTag = $this->phpDocNodeResolver->resolveThrowsTags($this->phpDocNode, $this->getNameScope()); } return $this->throwsTag; } /** * @return array */ public function getMixinTags() : array { if ($this->mixinTags === \false) { $this->mixinTags = $this->phpDocNodeResolver->resolveMixinTags($this->phpDocNode, $this->getNameScope()); } return $this->mixinTags; } /** * @return array */ public function getRequireExtendsTags() : array { if ($this->requireExtendsTags === \false) { $this->requireExtendsTags = $this->phpDocNodeResolver->resolveRequireExtendsTags($this->phpDocNode, $this->getNameScope()); } return $this->requireExtendsTags; } /** * @return array */ public function getRequireImplementsTags() : array { if ($this->requireImplementsTags === \false) { $this->requireImplementsTags = $this->phpDocNodeResolver->resolveRequireImplementsTags($this->phpDocNode, $this->getNameScope()); } return $this->requireImplementsTags; } /** * @return array */ public function getTypeAliasTags() : array { if ($this->typeAliasTags === \false) { $this->typeAliasTags = $this->phpDocNodeResolver->resolveTypeAliasTags($this->phpDocNode, $this->getNameScope()); } return $this->typeAliasTags; } /** * @return array */ public function getTypeAliasImportTags() : array { if ($this->typeAliasImportTags === \false) { $this->typeAliasImportTags = $this->phpDocNodeResolver->resolveTypeAliasImportTags($this->phpDocNode, $this->getNameScope()); } return $this->typeAliasImportTags; } /** * @return array */ public function getAssertTags() : array { if ($this->assertTags === \false) { $this->assertTags = $this->phpDocNodeResolver->resolveAssertTags($this->phpDocNode, $this->getNameScope()); } return $this->assertTags; } public function getSelfOutTag() : ?SelfOutTypeTag { if ($this->selfOutTypeTag === \false) { $this->selfOutTypeTag = $this->phpDocNodeResolver->resolveSelfOutTypeTag($this->phpDocNode, $this->getNameScope()); } return $this->selfOutTypeTag; } public function getDeprecatedTag() : ?DeprecatedTag { if (is_bool($this->deprecatedTag)) { $this->deprecatedTag = $this->phpDocNodeResolver->resolveDeprecatedTag($this->phpDocNode, $this->getNameScope()); } return $this->deprecatedTag; } public function isDeprecated() : bool { if ($this->isDeprecated === null) { $this->isDeprecated = $this->phpDocNodeResolver->resolveIsDeprecated($this->phpDocNode); } return $this->isDeprecated; } /** * @internal */ public function isNotDeprecated() : bool { if ($this->isNotDeprecated === null) { $this->isNotDeprecated = $this->phpDocNodeResolver->resolveIsNotDeprecated($this->phpDocNode); } return $this->isNotDeprecated; } public function isInternal() : bool { if ($this->isInternal === null) { $this->isInternal = $this->phpDocNodeResolver->resolveIsInternal($this->phpDocNode); } return $this->isInternal; } public function isFinal() : bool { if ($this->isFinal === null) { $this->isFinal = $this->phpDocNodeResolver->resolveIsFinal($this->phpDocNode); } return $this->isFinal; } public function hasConsistentConstructor() : bool { if ($this->hasConsistentConstructor === null) { $this->hasConsistentConstructor = $this->phpDocNodeResolver->resolveHasConsistentConstructor($this->phpDocNode); } return $this->hasConsistentConstructor; } public function acceptsNamedArguments() : bool { if ($this->acceptsNamedArguments === null) { $this->acceptsNamedArguments = $this->phpDocNodeResolver->resolveAcceptsNamedArguments($this->phpDocNode); } return $this->acceptsNamedArguments; } public function getTemplateTypeMap() : TemplateTypeMap { return $this->templateTypeMap; } public function isPure() : ?bool { if ($this->isPure === 'notLoaded') { $pure = $this->phpDocNodeResolver->resolveIsPure($this->phpDocNode); if ($pure) { $this->isPure = \true; return $this->isPure; } $impure = $this->phpDocNodeResolver->resolveIsImpure($this->phpDocNode); if ($impure) { $this->isPure = \false; return $this->isPure; } $this->isPure = null; } return $this->isPure; } public function isReadOnly() : bool { if ($this->isReadOnly === null) { $this->isReadOnly = $this->phpDocNodeResolver->resolveIsReadOnly($this->phpDocNode); } return $this->isReadOnly; } public function isImmutable() : bool { if ($this->isImmutable === null) { $this->isImmutable = $this->phpDocNodeResolver->resolveIsImmutable($this->phpDocNode); } return $this->isImmutable; } public function isAllowedPrivateMutation() : bool { if ($this->isAllowedPrivateMutation === null) { $this->isAllowedPrivateMutation = $this->phpDocNodeResolver->resolveAllowPrivateMutation($this->phpDocNode); } return $this->isAllowedPrivateMutation; } /** * @param array $varTags * @param array $parents * @param array $parentPhpDocBlocks * @return array */ private static function mergeVarTags(array $varTags, array $parents, array $parentPhpDocBlocks) : array { // Only allow one var tag per comment. Check the parent if child does not have this tag. if (count($varTags) > 0) { return $varTags; } foreach ($parents as $i => $parent) { $result = self::mergeOneParentVarTags($parent, $parentPhpDocBlocks[$i]); if ($result === null) { continue; } return $result; } return []; } /** * @return array|null */ private static function mergeOneParentVarTags(self $parent, \PHPStan\PhpDoc\PhpDocBlock $phpDocBlock) : ?array { foreach ($parent->getVarTags() as $key => $parentVarTag) { return [$key => self::resolveTemplateTypeInTag($parentVarTag->toImplicit(), $phpDocBlock, TemplateTypeVariance::createInvariant())]; } return null; } /** * @param array $paramTags * @param array $parents * @param array $parentPhpDocBlocks * @return array */ private static function mergeParamTags(array $paramTags, array $parents, array $parentPhpDocBlocks) : array { foreach ($parents as $i => $parent) { $paramTags = self::mergeOneParentParamTags($paramTags, $parent, $parentPhpDocBlocks[$i]); } return $paramTags; } /** * @param array $paramTags * @return array */ private static function mergeOneParentParamTags(array $paramTags, self $parent, \PHPStan\PhpDoc\PhpDocBlock $phpDocBlock) : array { $parentParamTags = $phpDocBlock->transformArrayKeysWithParameterNameMapping($parent->getParamTags()); foreach ($parentParamTags as $name => $parentParamTag) { if (array_key_exists($name, $paramTags)) { continue; } $paramTags[$name] = self::resolveTemplateTypeInTag($parentParamTag->withType($phpDocBlock->transformConditionalReturnTypeWithParameterNameMapping($parentParamTag->getType())), $phpDocBlock, TemplateTypeVariance::createContravariant()); } return $paramTags; } /** * @param array $parents * @param array $parentPhpDocBlocks * @return ReturnTag|Null */ private static function mergeReturnTags(?ReturnTag $returnTag, ?ClassReflection $classReflection, array $parents, array $parentPhpDocBlocks) : ?ReturnTag { if ($returnTag !== null) { return $returnTag; } foreach ($parents as $i => $parent) { $result = self::mergeOneParentReturnTag($returnTag, $classReflection, $parent, $parentPhpDocBlocks[$i]); if ($result === null) { continue; } return $result; } return null; } private static function mergeOneParentReturnTag(?ReturnTag $returnTag, ?ClassReflection $classReflection, self $parent, \PHPStan\PhpDoc\PhpDocBlock $phpDocBlock) : ?ReturnTag { $parentReturnTag = $parent->getReturnTag(); if ($parentReturnTag === null) { return $returnTag; } $parentType = $parentReturnTag->getType(); if ($classReflection !== null) { $parentType = TypeTraverser::map($parentType, static function (Type $type, callable $traverse) use($classReflection) : Type { if ($type instanceof StaticType) { return $type->changeBaseClass($classReflection); } return $traverse($type); }); $parentReturnTag = $parentReturnTag->withType($parentType); } // Each parent would overwrite the previous one except if it returns a less specific type. // Do not care for incompatible types as there is a separate rule for that. if ($returnTag !== null && $parentType->isSuperTypeOf($returnTag->getType())->yes()) { return null; } return self::resolveTemplateTypeInTag($parentReturnTag->withType($phpDocBlock->transformConditionalReturnTypeWithParameterNameMapping($parentReturnTag->getType()))->toImplicit(), $phpDocBlock, TemplateTypeVariance::createCovariant()); } /** * @param array $assertTags * @param array $parents * @param array $parentPhpDocBlocks * @return array */ private static function mergeAssertTags(array $assertTags, array $parents, array $parentPhpDocBlocks) : array { if (count($assertTags) > 0) { return $assertTags; } foreach ($parents as $i => $parent) { $result = $parent->getAssertTags(); if (count($result) === 0) { continue; } $phpDocBlock = $parentPhpDocBlocks[$i]; return array_map(static function (AssertTag $assertTag) use($phpDocBlock) { return self::resolveTemplateTypeInTag($assertTag->withParameter($phpDocBlock->transformAssertTagParameterWithParameterNameMapping($assertTag->getParameter()))->toImplicit(), $phpDocBlock, TemplateTypeVariance::createCovariant()); }, $result); } return $assertTags; } /** * @param array $parents */ private static function mergeSelfOutTypeTags(?SelfOutTypeTag $selfOutTypeTag, array $parents) : ?SelfOutTypeTag { if ($selfOutTypeTag !== null) { return $selfOutTypeTag; } foreach ($parents as $parent) { $result = $parent->getSelfOutTag(); if ($result === null) { continue; } return $result; } return null; } /** * @param array $parents */ private static function mergeDeprecatedTags(?DeprecatedTag $deprecatedTag, bool $hasNotDeprecatedTag, array $parents) : ?DeprecatedTag { if ($deprecatedTag !== null) { return $deprecatedTag; } if ($hasNotDeprecatedTag) { return null; } foreach ($parents as $parent) { $result = $parent->getDeprecatedTag(); if ($result === null && !$parent->isNotDeprecated()) { continue; } return $result; } return null; } /** * @param array $parents */ private static function mergeThrowsTags(?ThrowsTag $throwsTag, array $parents) : ?ThrowsTag { if ($throwsTag !== null) { return $throwsTag; } foreach ($parents as $parent) { $result = $parent->getThrowsTag(); if ($result === null) { continue; } return $result; } return null; } /** * @param array $paramOutTags * @param array $parents * @param array $parentPhpDocBlocks * @return array */ private static function mergeParamOutTags(array $paramOutTags, array $parents, array $parentPhpDocBlocks) : array { foreach ($parents as $i => $parent) { $paramOutTags = self::mergeOneParentParamOutTags($paramOutTags, $parent, $parentPhpDocBlocks[$i]); } return $paramOutTags; } /** * @param array $paramOutTags * @return array */ private static function mergeOneParentParamOutTags(array $paramOutTags, self $parent, \PHPStan\PhpDoc\PhpDocBlock $phpDocBlock) : array { $parentParamOutTags = $phpDocBlock->transformArrayKeysWithParameterNameMapping($parent->getParamOutTags()); foreach ($parentParamOutTags as $name => $parentParamTag) { if (array_key_exists($name, $paramOutTags)) { continue; } $paramOutTags[$name] = self::resolveTemplateTypeInTag($parentParamTag->withType($phpDocBlock->transformConditionalReturnTypeWithParameterNameMapping($parentParamTag->getType())), $phpDocBlock, TemplateTypeVariance::createCovariant()); } return $paramOutTags; } /** * @param array $paramsImmediatelyInvokedCallable * @param array $parents * @param array $parentPhpDocBlocks * @return array */ private static function mergeParamsImmediatelyInvokedCallable(array $paramsImmediatelyInvokedCallable, array $parents, array $parentPhpDocBlocks) : array { foreach ($parents as $i => $parent) { $paramsImmediatelyInvokedCallable = self::mergeOneParentParamImmediatelyInvokedCallable($paramsImmediatelyInvokedCallable, $parent, $parentPhpDocBlocks[$i]); } return $paramsImmediatelyInvokedCallable; } /** * @param array $paramsImmediatelyInvokedCallable * @return array */ private static function mergeOneParentParamImmediatelyInvokedCallable(array $paramsImmediatelyInvokedCallable, self $parent, \PHPStan\PhpDoc\PhpDocBlock $phpDocBlock) : array { $parentImmediatelyInvokedCallable = $phpDocBlock->transformArrayKeysWithParameterNameMapping($parent->getParamsImmediatelyInvokedCallable()); foreach ($parentImmediatelyInvokedCallable as $name => $parentIsImmediatelyInvokedCallable) { if (array_key_exists($name, $paramsImmediatelyInvokedCallable)) { continue; } $paramsImmediatelyInvokedCallable[$name] = $parentIsImmediatelyInvokedCallable; } return $paramsImmediatelyInvokedCallable; } /** * @param array $paramsClosureThisTags * @param array $parents * @param array $parentPhpDocBlocks * @return array */ private static function mergeParamClosureThisTags(array $paramsClosureThisTags, array $parents, array $parentPhpDocBlocks) : array { foreach ($parents as $i => $parent) { $paramsClosureThisTags = self::mergeOneParentParamClosureThisTag($paramsClosureThisTags, $parent, $parentPhpDocBlocks[$i]); } return $paramsClosureThisTags; } /** * @param array $paramsClosureThisTags * @return array */ private static function mergeOneParentParamClosureThisTag(array $paramsClosureThisTags, self $parent, \PHPStan\PhpDoc\PhpDocBlock $phpDocBlock) : array { $parentClosureThisTags = $phpDocBlock->transformArrayKeysWithParameterNameMapping($parent->getParamClosureThisTags()); foreach ($parentClosureThisTags as $name => $parentParamClosureThisTag) { if (array_key_exists($name, $paramsClosureThisTags)) { continue; } $paramsClosureThisTags[$name] = self::resolveTemplateTypeInTag($parentParamClosureThisTag->withType($phpDocBlock->transformConditionalReturnTypeWithParameterNameMapping($parentParamClosureThisTag->getType())), $phpDocBlock, TemplateTypeVariance::createContravariant()); } return $paramsClosureThisTags; } /** * @param array $parents */ private static function mergePureTags(?bool $isPure, array $parents) : ?bool { if ($isPure !== null) { return $isPure; } foreach ($parents as $parent) { $parentIsPure = $parent->isPure(); if ($parentIsPure === null) { continue; } return $parentIsPure; } return null; } /** * @template T of TypedTag * @param T $tag * @return T */ private static function resolveTemplateTypeInTag(TypedTag $tag, \PHPStan\PhpDoc\PhpDocBlock $phpDocBlock, TemplateTypeVariance $positionVariance) : TypedTag { $type = TemplateTypeHelper::resolveTemplateTypes($tag->getType(), $phpDocBlock->getClassReflection()->getActiveTemplateTypeMap(), $phpDocBlock->getClassReflection()->getCallSiteVarianceMap(), $positionVariance); return $tag->withType($type); } } container = $container; $this->stubFiles = $stubFiles; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; } public function getStubFiles() : array { if ($this->cachedFiles !== null) { return $this->cachedFiles; } $files = $this->stubFiles; $extensions = $this->container->getServicesByTag(\PHPStan\PhpDoc\StubFilesExtension::EXTENSION_TAG); foreach ($extensions as $extension) { foreach ($extension->getFiles() as $extensionFile) { $files[] = $extensionFile; } } return $this->cachedFiles = $files; } public function getProjectStubFiles() : array { if ($this->cachedProjectFiles !== null) { return $this->cachedProjectFiles; } $filteredStubFiles = $this->getStubFiles(); foreach ($this->composerAutoloaderProjectPaths as $composerAutoloaderProjectPath) { $composerConfig = ComposerHelper::getComposerConfig($composerAutoloaderProjectPath); if ($composerConfig === null) { continue; } $vendorDir = ComposerHelper::getVendorDirFromComposerConfig($composerAutoloaderProjectPath, $composerConfig); $vendorDir = strtr($vendorDir, '\\', '/'); $filteredStubFiles = array_filter($filteredStubFiles, static function (string $file) use($vendorDir) : bool { return !str_contains(strtr($file, '\\', '/'), $vendorDir); }); } return $this->cachedProjectFiles = array_values($filteredStubFiles); } } type = $type; $this->readableType = $readableType; $this->writableType = $writableType; } /** * @deprecated Use getReadableType() / getWritableType() */ public function getType() : Type { return $this->type; } public function getReadableType() : ?Type { return $this->readableType; } public function getWritableType() : ?Type { return $this->writableType; } /** * @phpstan-assert-if-true !null $this->getReadableType() */ public function isReadable() : bool { return $this->readableType !== null; } /** * @phpstan-assert-if-true !null $this->getWritableType() */ public function isWritable() : bool { return $this->writableType !== null; } } importedAlias = $importedAlias; $this->importedFrom = $importedFrom; $this->importedAs = $importedAs; } public function getImportedAlias() : string { return $this->importedAlias; } public function getImportedFrom() : string { return $this->importedFrom; } public function getImportedAs() : ?string { return $this->importedAs; } } type = $type; } public function getType() : Type { return $this->type; } } if = $if; $this->type = $type; $this->parameter = $parameter; $this->negated = $negated; $this->equality = $equality; $this->isExplicit = $isExplicit; } /** * @return self::NULL|self::IF_TRUE|self::IF_FALSE */ public function getIf() : string { return $this->if; } public function getType() : Type { return $this->type; } public function getOriginalType() : Type { return $this->originalType = $this->originalType ?? $this->type; } public function getParameter() : \PHPStan\PhpDoc\Tag\AssertTagParameter { return $this->parameter; } public function isNegated() : bool { return $this->negated; } public function isEquality() : bool { return $this->equality; } /** * @return static */ public function withType(Type $type) : \PHPStan\PhpDoc\Tag\TypedTag { $tag = new self($this->if, $type, $this->parameter, $this->negated, $this->equality, $this->isExplicit); $tag->originalType = $this->getOriginalType(); return $tag; } public function withParameter(\PHPStan\PhpDoc\Tag\AssertTagParameter $parameter) : self { $tag = new self($this->if, $this->type, $parameter, $this->negated, $this->equality, $this->isExplicit); $tag->originalType = $this->getOriginalType(); return $tag; } public function negate() : self { if ($this->isEquality()) { throw new ShouldNotHappenException(); } $tag = new self($this->if, $this->type, $this->parameter, !$this->negated, $this->equality, $this->isExplicit); $tag->originalType = $this->getOriginalType(); return $tag; } public function isExplicit() : bool { return $this->isExplicit; } public function toImplicit() : self { return new self($this->if, $this->type, $this->parameter, $this->negated, $this->equality, \false); } } type = $type; } public function getType() : Type { return $this->type; } /** * @return self */ public function withType(Type $type) : \PHPStan\PhpDoc\Tag\TypedTag { return new self($type); } } type = $type; } public function getType() : Type { return $this->type; } } type = $type; } public function getType() : Type { return $this->type; } /** * @return self */ public function withType(Type $type) : \PHPStan\PhpDoc\Tag\TypedTag { return new self($type); } } name = $name; $this->bound = $bound; $this->default = $default; $this->variance = $variance; } /** * @return non-empty-string */ public function getName() : string { return $this->name; } public function getBound() : Type { return $this->bound; } public function getDefault() : ?Type { return $this->default; } public function getVariance() : TemplateTypeVariance { return $this->variance; } } aliasName = $aliasName; $this->typeNode = $typeNode; $this->nameScope = $nameScope; } public function getAliasName() : string { return $this->aliasName; } public function getTypeAlias() : TypeAlias { return new TypeAlias($this->typeNode, $this->nameScope); } } type = $type; $this->passedByReference = $passedByReference; $this->isOptional = $isOptional; $this->isVariadic = $isVariadic; $this->defaultValue = $defaultValue; } public function getType() : Type { return $this->type; } public function passedByReference() : PassedByReference { return $this->passedByReference; } public function isOptional() : bool { return $this->isOptional; } public function isVariadic() : bool { return $this->isVariadic; } public function getDefaultValue() : ?Type { return $this->defaultValue; } } message = $message; } public function getMessage() : ?string { return $this->message; } } type = $type; $this->isExplicit = $isExplicit; } public function getType() : Type { return $this->type; } public function isExplicit() : bool { return $this->isExplicit; } /** * @return self */ public function withType(Type $type) : \PHPStan\PhpDoc\Tag\TypedTag { return new self($type, $this->isExplicit); } public function toImplicit() : self { return new self($this->type, \false); } } type = $type; } public function getType() : Type { return $this->type; } /** * @return self */ public function withType(Type $type) : \PHPStan\PhpDoc\Tag\TypedTag { return new self($type); } } */ private $parameters; /** * @var array */ private $templateTags; /** * @param array $parameters * @param array $templateTags */ public function __construct(Type $returnType, bool $isStatic, array $parameters, array $templateTags = []) { $this->returnType = $returnType; $this->isStatic = $isStatic; $this->parameters = $parameters; $this->templateTags = $templateTags; } public function getReturnType() : Type { return $this->returnType; } public function isStatic() : bool { return $this->isStatic; } /** * @return array */ public function getParameters() : array { return $this->parameters; } /** * @return array */ public function getTemplateTags() : array { return $this->templateTags; } } parameterName = $parameterName; $this->property = $property; $this->method = $method; } public function getParameterName() : string { return $this->parameterName; } public function changeParameterName(string $parameterName) : self { return new self($parameterName, $this->property, $this->method); } public function describe() : string { if ($this->property !== null) { return sprintf('%s->%s', $this->parameterName, $this->property); } if ($this->method !== null) { return sprintf('%s->%s()', $this->parameterName, $this->method); } return $this->parameterName; } public function getExpr(Expr $parameter) : Expr { if ($this->property !== null) { return new Expr\PropertyFetch($parameter, $this->property); } if ($this->method !== null) { return new Expr\MethodCall($parameter, $this->method); } return $parameter; } } type = $type; } public function getType() : Type { return $this->type; } } type = $type; $this->isVariadic = $isVariadic; } public function getType() : Type { return $this->type; } public function isVariadic() : bool { return $this->isVariadic; } /** * @return self */ public function withType(Type $type) : \PHPStan\PhpDoc\Tag\TypedTag { return new self($type, $this->isVariadic); } } type = $type; } public function getType() : Type { return $this->type; } } type = $type; } public function getType() : Type { return $this->type; } } type = $type; } public function getType() : Type { return $this->type; } } type = $type; $this->isExplicit = $isExplicit; } public function getType() : Type { return $this->type; } /** * @return self */ public function withType(Type $type) : \PHPStan\PhpDoc\Tag\TypedTag { return new self($type, $this->isExplicit); } public function isExplicit() : bool { return $this->isExplicit; } public function toImplicit() : self { return new self($this->type, \false); } } type = $type; } public function getType() : Type { return $this->type; } } */ private $parameterNameMapping; /** * @var array */ private $parents; /** * @param array $parameterNameMapping * @param array $parents */ private function __construct(string $docComment, ?string $file, ClassReflection $classReflection, ?string $trait, bool $explicit, array $parameterNameMapping, array $parents) { $this->docComment = $docComment; $this->file = $file; $this->classReflection = $classReflection; $this->trait = $trait; $this->explicit = $explicit; $this->parameterNameMapping = $parameterNameMapping; $this->parents = $parents; } public function getDocComment() : string { return $this->docComment; } public function getFile() : ?string { return $this->file; } public function getClassReflection() : ClassReflection { return $this->classReflection; } public function getTrait() : ?string { return $this->trait; } public function isExplicit() : bool { return $this->explicit; } /** * @return array */ public function getParents() : array { return $this->parents; } /** * @template T * @param array $array * @return array */ public function transformArrayKeysWithParameterNameMapping(array $array) : array { $newArray = []; foreach ($array as $key => $value) { if (!array_key_exists($key, $this->parameterNameMapping)) { continue; } $newArray[$this->parameterNameMapping[$key]] = $value; } return $newArray; } public function transformConditionalReturnTypeWithParameterNameMapping(Type $type) : Type { return TypeTraverser::map($type, function (Type $type, callable $traverse) : Type { if ($type instanceof ConditionalTypeForParameter) { $parameterName = substr($type->getParameterName(), 1); if (array_key_exists($parameterName, $this->parameterNameMapping)) { $type = $type->changeParameterName('$' . $this->parameterNameMapping[$parameterName]); } } return $traverse($type); }); } public function transformAssertTagParameterWithParameterNameMapping(AssertTagParameter $parameter) : AssertTagParameter { $parameterName = substr($parameter->getParameterName(), 1); if (array_key_exists($parameterName, $this->parameterNameMapping)) { $parameter = $parameter->changeParameterName('$' . $this->parameterNameMapping[$parameterName]); } return $parameter; } public static function resolvePhpDocBlockForProperty(?string $docComment, ClassReflection $classReflection, ?string $trait, string $propertyName, ?string $file, ?bool $explicit) : self { $docBlocksFromParents = []; foreach (self::getParentReflections($classReflection) as $parentReflection) { $oneResult = self::resolvePropertyPhpDocBlockFromClass($parentReflection, $propertyName, $explicit ?? $docComment !== null); if ($oneResult === null) { // Null if it is private or from a wrong trait. continue; } $docBlocksFromParents[] = $oneResult; } return new self($docComment ?? \PHPStan\PhpDoc\ResolvedPhpDocBlock::EMPTY_DOC_STRING, $file, $classReflection, $trait, $explicit ?? \true, [], $docBlocksFromParents); } public static function resolvePhpDocBlockForConstant(?string $docComment, ClassReflection $classReflection, string $constantName, ?string $file, ?bool $explicit) : self { $docBlocksFromParents = []; foreach (self::getParentReflections($classReflection) as $parentReflection) { $oneResult = self::resolveConstantPhpDocBlockFromClass($parentReflection, $constantName, $explicit ?? $docComment !== null); if ($oneResult === null) { // Null if it is private or from a wrong trait. continue; } $docBlocksFromParents[] = $oneResult; } return new self($docComment ?? \PHPStan\PhpDoc\ResolvedPhpDocBlock::EMPTY_DOC_STRING, $file, $classReflection, null, $explicit ?? \true, [], $docBlocksFromParents); } /** * @param array $originalPositionalParameterNames * @param array $newPositionalParameterNames */ public static function resolvePhpDocBlockForMethod(?string $docComment, ClassReflection $classReflection, ?string $trait, string $methodName, ?string $file, ?bool $explicit, array $originalPositionalParameterNames, array $newPositionalParameterNames) : self { $docBlocksFromParents = []; foreach (self::getParentReflections($classReflection) as $parentReflection) { $oneResult = self::resolveMethodPhpDocBlockFromClass($parentReflection, $methodName, $explicit ?? $docComment !== null, $newPositionalParameterNames); if ($oneResult === null) { // Null if it is private or from a wrong trait. continue; } $docBlocksFromParents[] = $oneResult; } foreach ($classReflection->getTraits(\true) as $traitReflection) { if (!$traitReflection->hasNativeMethod($methodName)) { continue; } $traitMethod = $traitReflection->getNativeMethod($methodName); $abstract = $traitMethod->isAbstract(); if (is_bool($abstract)) { if (!$abstract) { continue; } } elseif (!$abstract->yes()) { continue; } $methodVariant = $traitMethod->getOnlyVariant(); $positionalMethodParameterNames = []; foreach ($methodVariant->getParameters() as $methodParameter) { $positionalMethodParameterNames[] = $methodParameter->getName(); } $docBlocksFromParents[] = new self($traitMethod->getDocComment() ?? \PHPStan\PhpDoc\ResolvedPhpDocBlock::EMPTY_DOC_STRING, $classReflection->getFileName(), $classReflection, $traitReflection->getName(), $explicit ?? $traitMethod->getDocComment() !== null, self::remapParameterNames($newPositionalParameterNames, $positionalMethodParameterNames), []); } return new self($docComment ?? \PHPStan\PhpDoc\ResolvedPhpDocBlock::EMPTY_DOC_STRING, $file, $classReflection, $trait, $explicit ?? \true, self::remapParameterNames($originalPositionalParameterNames, $newPositionalParameterNames), $docBlocksFromParents); } /** * @param array $originalPositionalParameterNames * @param array $newPositionalParameterNames * @return array */ private static function remapParameterNames(array $originalPositionalParameterNames, array $newPositionalParameterNames) : array { $parameterNameMapping = []; foreach ($originalPositionalParameterNames as $i => $parameterName) { if (!array_key_exists($i, $newPositionalParameterNames)) { continue; } $parameterNameMapping[$newPositionalParameterNames[$i]] = $parameterName; } return $parameterNameMapping; } /** * @return array */ private static function getParentReflections(ClassReflection $classReflection) : array { $result = []; $parent = $classReflection->getParentClass(); if ($parent !== null) { $result[] = $parent; } foreach ($classReflection->getInterfaces() as $interface) { $result[] = $interface; } return $result; } private static function resolveConstantPhpDocBlockFromClass(ClassReflection $classReflection, string $name, bool $explicit) : ?self { if ($classReflection->hasConstant($name)) { $parentReflection = $classReflection->getConstant($name); if ($parentReflection->isPrivate()) { return null; } $classReflection = $parentReflection->getDeclaringClass(); return self::resolvePhpDocBlockForConstant($parentReflection->getDocComment() ?? \PHPStan\PhpDoc\ResolvedPhpDocBlock::EMPTY_DOC_STRING, $classReflection, $name, $classReflection->getFileName(), $explicit); } return null; } private static function resolvePropertyPhpDocBlockFromClass(ClassReflection $classReflection, string $name, bool $explicit) : ?self { if ($classReflection->hasNativeProperty($name)) { $parentReflection = $classReflection->getNativeProperty($name); if ($parentReflection->isPrivate()) { return null; } $classReflection = $parentReflection->getDeclaringClass(); $traitReflection = $parentReflection->getDeclaringTrait(); $trait = $traitReflection !== null ? $traitReflection->getName() : null; return self::resolvePhpDocBlockForProperty($parentReflection->getDocComment() ?? \PHPStan\PhpDoc\ResolvedPhpDocBlock::EMPTY_DOC_STRING, $classReflection, $trait, $name, $classReflection->getFileName(), $explicit); } return null; } /** * @param array $positionalParameterNames */ private static function resolveMethodPhpDocBlockFromClass(ClassReflection $classReflection, string $name, bool $explicit, array $positionalParameterNames) : ?self { if ($classReflection->hasNativeMethod($name)) { $parentReflection = $classReflection->getNativeMethod($name); if ($parentReflection->isPrivate()) { return null; } $classReflection = $parentReflection->getDeclaringClass(); $traitReflection = null; if ($parentReflection instanceof PhpMethodReflection || $parentReflection instanceof ResolvedMethodReflection) { $traitReflection = $parentReflection->getDeclaringTrait(); } $methodVariants = $parentReflection->getVariants(); $positionalMethodParameterNames = []; $lowercaseMethodName = strtolower($parentReflection->getName()); if (count($methodVariants) === 1 && $lowercaseMethodName !== '__construct' && $lowercaseMethodName !== strtolower($parentReflection->getDeclaringClass()->getName())) { $methodParameters = $methodVariants[0]->getParameters(); foreach ($methodParameters as $methodParameter) { $positionalMethodParameterNames[] = $methodParameter->getName(); } } else { $positionalMethodParameterNames = $positionalParameterNames; } $trait = $traitReflection !== null ? $traitReflection->getName() : null; return self::resolvePhpDocBlockForMethod($parentReflection->getDocComment() ?? \PHPStan\PhpDoc\ResolvedPhpDocBlock::EMPTY_DOC_STRING, $classReflection, $trait, $name, $classReflection->getFileName(), $explicit, $positionalParameterNames, $positionalMethodParameterNames); } return null; } } phpVersion = $phpVersion; } public function getFiles() : array { if (!$this->phpVersion->supportsEnums()) { return []; } return [__DIR__ . '/../../stubs/ReflectionEnum.stub']; } } typeLexer = $typeLexer; $this->typeParser = $typeParser; $this->typeNodeResolver = $typeNodeResolver; } /** @api */ public function resolve(string $typeString, ?NameScope $nameScope = null) : Type { $tokens = new TokenIterator($this->typeLexer->tokenize($typeString)); $typeNode = $this->typeParser->parse($tokens); $tokens->consumeTokenType(Lexer::TOKEN_END); // @phpstan-ignore missingType.checkedException return $this->typeNodeResolver->resolve($typeNode, $nameScope ?? new NameScope(null, [])); } } */ private $classMap = []; /** @var array> */ private $propertyMap = []; /** @var array> */ private $constantMap = []; /** @var array> */ private $methodMap = []; /** @var array */ private $functionMap = []; /** * @var bool */ private $initialized = \false; /** * @var bool */ private $initializing = \false; /** @var array */ private $knownClassesDocComments = []; /** @var array */ private $knownFunctionsDocComments = []; /** @var array> */ private $knownPropertiesDocComments = []; /** @var array> */ private $knownConstantsDocComments = []; /** @var array> */ private $knownMethodsDocComments = []; /** @var array>> */ private $knownMethodsParameterNames = []; /** @var array> */ private $knownFunctionParameterNames = []; public function __construct(Parser $parser, FileTypeMapper $fileTypeMapper, \PHPStan\PhpDoc\StubFilesProvider $stubFilesProvider) { $this->parser = $parser; $this->fileTypeMapper = $fileTypeMapper; $this->stubFilesProvider = $stubFilesProvider; } public function findClassPhpDoc(string $className) : ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { if (!$this->isKnownClass($className)) { return null; } if (array_key_exists($className, $this->classMap)) { return $this->classMap[$className]; } if (array_key_exists($className, $this->knownClassesDocComments)) { [$file, $docComment] = $this->knownClassesDocComments[$className]; $this->classMap[$className] = $this->fileTypeMapper->getResolvedPhpDoc($file, $className, null, null, $docComment); return $this->classMap[$className]; } return null; } public function findPropertyPhpDoc(string $className, string $propertyName) : ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { if (!$this->isKnownClass($className)) { return null; } if (array_key_exists($propertyName, $this->propertyMap[$className])) { return $this->propertyMap[$className][$propertyName]; } if (array_key_exists($propertyName, $this->knownPropertiesDocComments[$className])) { [$file, $docComment] = $this->knownPropertiesDocComments[$className][$propertyName]; $this->propertyMap[$className][$propertyName] = $this->fileTypeMapper->getResolvedPhpDoc($file, $className, null, null, $docComment); return $this->propertyMap[$className][$propertyName]; } return null; } public function findClassConstantPhpDoc(string $className, string $constantName) : ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { if (!$this->isKnownClass($className)) { return null; } if (array_key_exists($constantName, $this->constantMap[$className])) { return $this->constantMap[$className][$constantName]; } if (array_key_exists($constantName, $this->knownConstantsDocComments[$className])) { [$file, $docComment] = $this->knownConstantsDocComments[$className][$constantName]; $this->constantMap[$className][$constantName] = $this->fileTypeMapper->getResolvedPhpDoc($file, $className, null, null, $docComment); return $this->constantMap[$className][$constantName]; } return null; } /** * @param array $positionalParameterNames */ public function findMethodPhpDoc(string $className, string $implementingClassName, string $methodName, array $positionalParameterNames) : ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { if (!$this->isKnownClass($className)) { return null; } if (array_key_exists($methodName, $this->methodMap[$className])) { return $this->methodMap[$className][$methodName]; } if (array_key_exists($methodName, $this->knownMethodsDocComments[$className])) { [$file, $docComment] = $this->knownMethodsDocComments[$className][$methodName]; $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($file, $className, null, $methodName, $docComment); if (!isset($this->knownMethodsParameterNames[$className][$methodName])) { throw new ShouldNotHappenException(); } if ($className !== $implementingClassName && $resolvedPhpDoc->getNullableNameScope() !== null) { $resolvedPhpDoc = $resolvedPhpDoc->withNameScope($resolvedPhpDoc->getNullableNameScope()->withClassName($implementingClassName)); } $methodParameterNames = $this->knownMethodsParameterNames[$className][$methodName]; $parameterNameMapping = []; foreach ($positionalParameterNames as $i => $parameterName) { if (!array_key_exists($i, $methodParameterNames)) { continue; } $parameterNameMapping[$methodParameterNames[$i]] = $parameterName; } return $resolvedPhpDoc->changeParameterNamesByMapping($parameterNameMapping); } return null; } /** * @param array $positionalParameterNames * @throws ShouldNotHappenException */ public function findFunctionPhpDoc(string $functionName, array $positionalParameterNames) : ?\PHPStan\PhpDoc\ResolvedPhpDocBlock { if (!$this->isKnownFunction($functionName)) { return null; } if (array_key_exists($functionName, $this->functionMap)) { return $this->functionMap[$functionName]; } if (array_key_exists($functionName, $this->knownFunctionsDocComments)) { [$file, $docComment] = $this->knownFunctionsDocComments[$functionName]; $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($file, null, null, $functionName, $docComment); if (!isset($this->knownFunctionParameterNames[$functionName])) { throw new ShouldNotHappenException(); } $functionParameterNames = $this->knownFunctionParameterNames[$functionName]; $parameterNameMapping = []; foreach ($positionalParameterNames as $i => $parameterName) { if (!array_key_exists($i, $functionParameterNames)) { continue; } $parameterNameMapping[$functionParameterNames[$i]] = $parameterName; } $this->functionMap[$functionName] = $resolvedPhpDoc->changeParameterNamesByMapping($parameterNameMapping); return $this->functionMap[$functionName]; } return null; } public function isKnownClass(string $className) : bool { $this->initializeKnownElements(); if (array_key_exists($className, $this->classMap)) { return \true; } return array_key_exists($className, $this->knownClassesDocComments); } private function isKnownFunction(string $functionName) : bool { $this->initializeKnownElements(); if (array_key_exists($functionName, $this->functionMap)) { return \true; } return array_key_exists($functionName, $this->knownFunctionsDocComments); } private function initializeKnownElements() : void { if ($this->initializing) { throw new ShouldNotHappenException(); } if ($this->initialized) { return; } $this->initializing = \true; try { foreach ($this->stubFilesProvider->getStubFiles() as $stubFile) { $nodes = $this->parser->parseFile($stubFile); foreach ($nodes as $node) { $this->initializeKnownElementNode($stubFile, $node); } } } finally { $this->initializing = \false; $this->initialized = \true; } } private function initializeKnownElementNode(string $stubFile, Node $node) : void { if ($node instanceof Node\Stmt\Namespace_) { foreach ($node->stmts as $stmt) { $this->initializeKnownElementNode($stubFile, $stmt); } return; } if ($node instanceof Node\Stmt\Function_) { $functionName = (string) $node->namespacedName; $docComment = $node->getDocComment(); if ($docComment === null) { $this->functionMap[$functionName] = null; return; } $this->knownFunctionParameterNames[$functionName] = array_map(static function (Node\Param $param) : string { if (!$param->var instanceof Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } return $param->var->name; }, $node->getParams()); $this->knownFunctionsDocComments[$functionName] = [$stubFile, $docComment->getText()]; return; } if (!$node instanceof Class_ && !$node instanceof Interface_ && !$node instanceof Trait_ && !$node instanceof Node\Stmt\Enum_) { return; } if (!isset($node->namespacedName)) { return; } $className = (string) $node->namespacedName; $docComment = $node->getDocComment(); if ($docComment === null) { $this->classMap[$className] = null; } else { $this->knownClassesDocComments[$className] = [$stubFile, $docComment->getText()]; } $this->methodMap[$className] = []; $this->propertyMap[$className] = []; $this->constantMap[$className] = []; $this->knownPropertiesDocComments[$className] = []; $this->knownConstantsDocComments[$className] = []; $this->knownMethodsDocComments[$className] = []; foreach ($node->stmts as $stmt) { $docComment = $stmt->getDocComment(); if ($stmt instanceof Node\Stmt\Property) { foreach ($stmt->props as $property) { if ($docComment === null) { $this->propertyMap[$className][$property->name->toString()] = null; continue; } $this->knownPropertiesDocComments[$className][$property->name->toString()] = [$stubFile, $docComment->getText()]; } } elseif ($stmt instanceof Node\Stmt\ClassConst) { foreach ($stmt->consts as $const) { if ($docComment === null) { $this->constantMap[$className][$const->name->toString()] = null; continue; } $this->knownConstantsDocComments[$className][$const->name->toString()] = [$stubFile, $docComment->getText()]; } } elseif ($stmt instanceof Node\Stmt\ClassMethod) { if ($docComment === null) { $this->methodMap[$className][$stmt->name->toString()] = null; continue; } $methodName = $stmt->name->toString(); $this->knownMethodsDocComments[$className][$methodName] = [$stubFile, $docComment->getText()]; $this->knownMethodsParameterNames[$className][$methodName] = array_map(static function (Node\Param $param) : string { if (!$param->var instanceof Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } return $param->var->name; }, $stmt->getParams()); } } } } unescapeStrings = $unescapeStrings; } public function create() : ConstExprParser { return new ConstExprParser($this->unescapeStrings, $this->unescapeStrings); } } container = $container; } public function getRegistry() : \PHPStan\PhpDoc\TypeNodeResolverExtensionRegistry { if ($this->registry === null) { $this->registry = new \PHPStan\PhpDoc\TypeNodeResolverExtensionAwareRegistry($this->container->getByType(\PHPStan\PhpDoc\TypeNodeResolver::class), $this->container->getServicesByTag(\PHPStan\PhpDoc\TypeNodeResolverExtension::EXTENSION_TAG)); } return $this->registry; } } phpDocLexer = $phpDocLexer; $this->phpDocParser = $phpDocParser; } public function resolve(string $phpDocString) : PhpDocNode { $tokens = new TokenIterator($this->phpDocLexer->tokenize($phpDocString)); $phpDocNode = $this->phpDocParser->parse($tokens); $tokens->consumeTokenType(Lexer::TOKEN_END); // @phpstan-ignore missingType.checkedException return $phpDocNode; } } php8Parser = $php8Parser; $this->phpStormStubsSourceStubber = $phpStormStubsSourceStubber; $this->optimizedSingleFileSourceLocatorRepository = $optimizedSingleFileSourceLocatorRepository; $this->optimizedPsrAutoloaderLocatorFactory = $optimizedPsrAutoloaderLocatorFactory; $this->stubFilesProvider = $stubFilesProvider; } public function create() : SourceLocator { $locators = []; $astPhp8Locator = new Locator($this->php8Parser); foreach ($this->stubFilesProvider->getStubFiles() as $stubFile) { $locators[] = $this->optimizedSingleFileSourceLocatorRepository->getOrCreate($stubFile); } $locators[] = $this->optimizedPsrAutoloaderLocatorFactory->create(Psr4Mapping::fromArrayMappings(['PHPStan\\' => [dirname(__DIR__) . '/']])); $locators[] = $this->optimizedPsrAutoloaderLocatorFactory->create(Psr4Mapping::fromArrayMappings(['PhpParser\\' => [dirname(__DIR__, 2) . '/vendor/nikic/php-parser/lib/PhpParser/']])); $locators[] = new PhpInternalSourceLocator($astPhp8Locator, $this->phpStormStubsSourceStubber); return new MemoizingSourceLocator(new AggregateSourceLocator($locators)); } } phpVersion = $phpVersion; } public function getFiles() : array { if (!$this->phpVersion->supportsJsonValidate()) { return []; } return [__DIR__ . '/../../stubs/json_validate.stub']; } } derivativeContainerFactory = $derivativeContainerFactory; $this->duplicateStubs = $duplicateStubs; } /** * @param string[] $stubFiles * @return list */ public function validate(array $stubFiles, bool $debug) : array { if (count($stubFiles) === 0) { return []; } $originalBroker = Broker::getInstance(); $originalReflectionProvider = ReflectionProviderStaticAccessor::getInstance(); $originalPhpVersion = PhpVersionStaticAccessor::getInstance(); $container = $this->derivativeContainerFactory->create([__DIR__ . '/../../conf/config.stubValidator.neon']); $ruleRegistry = $this->getRuleRegistry($container); $collectorRegistry = $this->getCollectorRegistry($container); $fileAnalyser = $container->getByType(FileAnalyser::class); $nodeScopeResolver = $container->getByType(NodeScopeResolver::class); $nodeScopeResolver->setAnalysedFiles($stubFiles); $pathRoutingParser = $container->getService('pathRoutingParser'); $pathRoutingParser->setAnalysedFiles($stubFiles); $analysedFiles = array_fill_keys($stubFiles, \true); $errors = []; foreach ($stubFiles as $stubFile) { try { $tmpErrors = $fileAnalyser->analyseFile($stubFile, $analysedFiles, $ruleRegistry, $collectorRegistry, static function () : void { })->getErrors(); foreach ($tmpErrors as $tmpError) { $errors[] = $tmpError->withoutTip()->doNotIgnore(); } } catch (Throwable $e) { if ($debug) { throw $e; } $internalErrorMessage = sprintf('Internal error: %s', $e->getMessage()); $errors[] = (new Error($internalErrorMessage, $stubFile, null, $e))->withIdentifier('phpstan.internal')->withMetadata([InternalError::STACK_TRACE_METADATA_KEY => InternalError::prepareTrace($e), InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); } } Broker::registerInstance($originalBroker); ReflectionProviderStaticAccessor::registerInstance($originalReflectionProvider); PhpVersionStaticAccessor::registerInstance($originalPhpVersion); ObjectType::resetCaches(); return $errors; } private function getRuleRegistry(Container $container) : RuleRegistry { $fileTypeMapper = $container->getByType(FileTypeMapper::class); $genericObjectTypeCheck = $container->getByType(GenericObjectTypeCheck::class); $genericAncestorsCheck = $container->getByType(GenericAncestorsCheck::class); $templateTypeCheck = $container->getByType(TemplateTypeCheck::class); $varianceCheck = $container->getByType(VarianceCheck::class); $reflectionProvider = $container->getByType(ReflectionProvider::class); $classNameCheck = $container->getByType(ClassNameCheck::class); $functionDefinitionCheck = $container->getByType(FunctionDefinitionCheck::class); $missingTypehintCheck = $container->getByType(MissingTypehintCheck::class); $unresolvableTypeHelper = $container->getByType(UnresolvableTypeHelper::class); $crossCheckInterfacesHelper = $container->getByType(CrossCheckInterfacesHelper::class); $phpVersion = $container->getByType(PhpVersion::class); $localTypeAliasesCheck = $container->getByType(LocalTypeAliasesCheck::class); $phpClassReflectionExtension = $container->getByType(PhpClassReflectionExtension::class); $genericCallableRuleHelper = $container->getByType(GenericCallableRuleHelper::class); $methodTagTemplateTypeCheck = $container->getByType(MethodTagTemplateTypeCheck::class); $mixinCheck = $container->getByType(MixinCheck::class); $rules = [ // level 0 new ExistingClassesInClassImplementsRule($classNameCheck, $reflectionProvider), new ExistingClassesInInterfaceExtendsRule($classNameCheck, $reflectionProvider), new ExistingClassInClassExtendsRule($classNameCheck, $reflectionProvider), new ExistingClassInTraitUseRule($classNameCheck, $reflectionProvider), new ExistingClassesInTypehintsRule($functionDefinitionCheck), new \PHPStan\Rules\Functions\ExistingClassesInTypehintsRule($functionDefinitionCheck), new ExistingClassesInPropertiesRule($reflectionProvider, $classNameCheck, $unresolvableTypeHelper, $phpVersion, \true, \false), new OverridingMethodRule($phpVersion, new MethodSignatureRule($phpClassReflectionExtension, \true, \true, $container->getParameter('featureToggles')['abstractTraitMethod']), \true, new MethodParameterComparisonHelper($phpVersion, $container->getParameter('featureToggles')['genericPrototypeMessage']), $phpClassReflectionExtension, $container->getParameter('featureToggles')['genericPrototypeMessage'], $container->getParameter('featureToggles')['finalByPhpDoc'], $container->getParameter('checkMissingOverrideMethodAttribute')), new DuplicateDeclarationRule(), new LocalTypeAliasesRule($localTypeAliasesCheck), new LocalTypeTraitAliasesRule($localTypeAliasesCheck, $reflectionProvider), // level 2 new ClassAncestorsRule($genericAncestorsCheck, $crossCheckInterfacesHelper), new ClassTemplateTypeRule($templateTypeCheck), new FunctionTemplateTypeRule($fileTypeMapper, $templateTypeCheck), new FunctionSignatureVarianceRule($varianceCheck), new InterfaceAncestorsRule($genericAncestorsCheck, $crossCheckInterfacesHelper), new InterfaceTemplateTypeRule($templateTypeCheck), new MethodTemplateTypeRule($fileTypeMapper, $templateTypeCheck), new MethodTagTemplateTypeRule($methodTagTemplateTypeCheck), new MethodSignatureVarianceRule($varianceCheck), new TraitTemplateTypeRule($fileTypeMapper, $templateTypeCheck), new IncompatiblePhpDocTypeRule($fileTypeMapper, $genericObjectTypeCheck, $unresolvableTypeHelper, $genericCallableRuleHelper), new IncompatiblePropertyPhpDocTypeRule($genericObjectTypeCheck, $unresolvableTypeHelper, $genericCallableRuleHelper), new InvalidPhpDocTagValueRule($container->getByType(Lexer::class), $container->getByType(PhpDocParser::class), $container->getParameter('featureToggles')['allInvalidPhpDocs'], $container->getParameter('featureToggles')['invalidPhpDocTagLine']), new IncompatibleParamImmediatelyInvokedCallableRule($fileTypeMapper), new IncompatibleSelfOutTypeRule($unresolvableTypeHelper, $genericObjectTypeCheck), new IncompatibleClassConstantPhpDocTypeRule($genericObjectTypeCheck, $unresolvableTypeHelper), new InvalidThrowsPhpDocValueRule($fileTypeMapper), // level 6 new MissingFunctionParameterTypehintRule($missingTypehintCheck, $container->getParameter('featureToggles')['paramOutType']), new MissingFunctionReturnTypehintRule($missingTypehintCheck), new MissingMethodParameterTypehintRule($missingTypehintCheck, $container->getParameter('featureToggles')['paramOutType']), new MissingMethodReturnTypehintRule($missingTypehintCheck), new MissingPropertyTypehintRule($missingTypehintCheck), ]; if ($this->duplicateStubs) { $reflector = $container->getService('stubReflector'); $relativePathHelper = $container->getService('simpleRelativePathHelper'); $rules[] = new DuplicateClassDeclarationRule($reflector, $relativePathHelper); $rules[] = new DuplicateFunctionDeclarationRule($reflector, $relativePathHelper); } if ((bool) $container->getParameter('featureToggles')['allInvalidPhpDocs']) { $rules[] = new InvalidPHPStanDocTagRule($container->getByType(Lexer::class), $container->getByType(PhpDocParser::class), \true); } if ((bool) $container->getParameter('featureToggles')['absentTypeChecks']) { $rules[] = new MissingMethodSelfOutTypeRule($missingTypehintCheck); $methodTagCheck = new MethodTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, \true, \true); $rules[] = new MethodTagRule($methodTagCheck); $rules[] = new MethodTagTraitRule($methodTagCheck, $reflectionProvider); $rules[] = new MethodTagTraitUseRule($methodTagCheck); $propertyTagCheck = new PropertyTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, \true, \true); $rules[] = new PropertyTagRule($propertyTagCheck); $rules[] = new PropertyTagTraitRule($propertyTagCheck, $reflectionProvider); $rules[] = new PropertyTagTraitUseRule($propertyTagCheck); $rules[] = new MixinRule($mixinCheck); $rules[] = new MixinTraitRule($mixinCheck, $reflectionProvider); $rules[] = new MixinTraitUseRule($mixinCheck); $rules[] = new LocalTypeTraitUseAliasesRule($localTypeAliasesCheck); $rules[] = new MethodTagTemplateTypeTraitRule($methodTagTemplateTypeCheck, $reflectionProvider); } return new DirectRuleRegistry($rules); } private function getCollectorRegistry(Container $container) : CollectorRegistry { return new CollectorRegistry([]); } } fileTypeMapper = $fileTypeMapper; $this->stubPhpDocProvider = $stubPhpDocProvider; } public function resolvePhpDocForProperty(?string $docComment, ClassReflection $classReflection, ?string $classReflectionFileName, ?string $declaringTraitName, string $propertyName) : \PHPStan\PhpDoc\ResolvedPhpDocBlock { $phpDocBlock = \PHPStan\PhpDoc\PhpDocBlock::resolvePhpDocBlockForProperty($docComment, $classReflection, null, $propertyName, $classReflectionFileName, null); return $this->docBlockTreeToResolvedDocBlock($phpDocBlock, $declaringTraitName, null, $propertyName, null); } public function resolvePhpDocForConstant(?string $docComment, ClassReflection $classReflection, ?string $classReflectionFileName, string $constantName) : \PHPStan\PhpDoc\ResolvedPhpDocBlock { $phpDocBlock = \PHPStan\PhpDoc\PhpDocBlock::resolvePhpDocBlockForConstant($docComment, $classReflection, $constantName, $classReflectionFileName, null); return $this->docBlockTreeToResolvedDocBlock($phpDocBlock, null, null, null, $constantName); } /** * @param array $positionalParameterNames */ public function resolvePhpDocForMethod(?string $docComment, ?string $fileName, ClassReflection $classReflection, ?string $declaringTraitName, string $methodName, array $positionalParameterNames) : \PHPStan\PhpDoc\ResolvedPhpDocBlock { $phpDocBlock = \PHPStan\PhpDoc\PhpDocBlock::resolvePhpDocBlockForMethod($docComment, $classReflection, $declaringTraitName, $methodName, $fileName, null, $positionalParameterNames, $positionalParameterNames); return $this->docBlockTreeToResolvedDocBlock($phpDocBlock, $phpDocBlock->getTrait(), $methodName, null, null); } private function docBlockTreeToResolvedDocBlock(\PHPStan\PhpDoc\PhpDocBlock $phpDocBlock, ?string $traitName, ?string $functionName, ?string $propertyName, ?string $constantName) : \PHPStan\PhpDoc\ResolvedPhpDocBlock { $parents = []; $parentPhpDocBlocks = []; foreach ($phpDocBlock->getParents() as $parentPhpDocBlock) { if ($functionName !== null && strtolower($functionName) === '__construct' && $parentPhpDocBlock->getClassReflection()->isBuiltin()) { continue; } $parents[] = $this->docBlockTreeToResolvedDocBlock($parentPhpDocBlock, $parentPhpDocBlock->getTrait(), $functionName, $propertyName, $constantName); $parentPhpDocBlocks[] = $parentPhpDocBlock; } $oneResolvedDockBlock = $this->docBlockToResolvedDocBlock($phpDocBlock, $traitName, $functionName, $propertyName, $constantName); return $oneResolvedDockBlock->merge($parents, $parentPhpDocBlocks); } private function docBlockToResolvedDocBlock(\PHPStan\PhpDoc\PhpDocBlock $phpDocBlock, ?string $traitName, ?string $functionName, ?string $propertyName, ?string $constantName) : \PHPStan\PhpDoc\ResolvedPhpDocBlock { $classReflection = $phpDocBlock->getClassReflection(); if ($functionName !== null && $classReflection->getNativeReflection()->hasMethod($functionName)) { $methodReflection = $classReflection->getNativeReflection()->getMethod($functionName); $stub = $this->stubPhpDocProvider->findMethodPhpDoc($classReflection->getName(), $classReflection->getName(), $functionName, array_map(static function (ReflectionParameter $parameter) : string { return $parameter->getName(); }, $methodReflection->getParameters())); if ($stub !== null) { return $stub; } } if ($propertyName !== null && $classReflection->getNativeReflection()->hasProperty($propertyName)) { $stub = $this->stubPhpDocProvider->findPropertyPhpDoc($classReflection->getName(), $propertyName); if ($stub === null) { $propertyReflection = $classReflection->getNativeReflection()->getProperty($propertyName); $propertyDeclaringClass = $propertyReflection->getBetterReflection()->getDeclaringClass(); if ($propertyDeclaringClass->isTrait() && (!$propertyReflection->getDeclaringClass()->isTrait() || $propertyReflection->getDeclaringClass()->getName() !== $propertyDeclaringClass->getName())) { $stub = $this->stubPhpDocProvider->findPropertyPhpDoc($propertyDeclaringClass->getName(), $propertyName); } } if ($stub !== null) { return $stub; } } if ($constantName !== null && $classReflection->getNativeReflection()->hasConstant($constantName)) { $stub = $this->stubPhpDocProvider->findClassConstantPhpDoc($classReflection->getName(), $constantName); if ($stub !== null) { return $stub; } } return $this->fileTypeMapper->getResolvedPhpDoc($phpDocBlock->getFile(), $classReflection->getName(), $traitName, $functionName, $phpDocBlock->getDocComment()); } } bleedingEdge = $bleedingEdge; } public function getFiles() : array { if ($this->bleedingEdge) { return [__DIR__ . '/../../stubs/bleedingEdge/Countable.stub']; } return [__DIR__ . '/../../stubs/Countable.stub']; } } extensions = $extensions; foreach ($extensions as $extension) { if (!$extension instanceof \PHPStan\PhpDoc\TypeNodeResolverAwareExtension) { continue; } $extension->setTypeNodeResolver($typeNodeResolver); } } /** * @return TypeNodeResolverExtension[] */ public function getExtensions() : array { return $this->extensions; } } reflectionProviderProvider = $reflectionProviderProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function resolve(ConstExprNode $node, NameScope $nameScope) : Type { if ($node instanceof ConstExprArrayNode) { return $this->resolveArrayNode($node, $nameScope); } if ($node instanceof ConstExprFalseNode) { return new ConstantBooleanType(\false); } if ($node instanceof ConstExprTrueNode) { return new ConstantBooleanType(\true); } if ($node instanceof ConstExprFloatNode) { return new ConstantFloatType((float) $node->value); } if ($node instanceof ConstExprIntegerNode) { return new ConstantIntegerType((int) $node->value); } if ($node instanceof ConstExprNullNode) { return new NullType(); } if ($node instanceof ConstExprStringNode) { return new ConstantStringType($node->value); } if ($node instanceof ConstFetchNode) { if ($nameScope->getClassName() !== null) { switch (strtolower($node->className)) { case 'static': case 'self': $className = $nameScope->getClassName(); break; case 'parent': if ($this->getReflectionProvider()->hasClass($nameScope->getClassName())) { $classReflection = $this->getReflectionProvider()->getClass($nameScope->getClassName()); if ($classReflection->getParentClass() === null) { return new ErrorType(); } $className = $classReflection->getParentClass()->getName(); } break; } } if (!isset($className)) { $className = $nameScope->resolveStringName($node->className); } if (!$this->getReflectionProvider()->hasClass($className)) { return new ErrorType(); } $classReflection = $this->getReflectionProvider()->getClass($className); if (!$classReflection->hasConstant($node->name)) { return new ErrorType(); } if ($classReflection->isEnum() && $classReflection->hasEnumCase($node->name)) { return new EnumCaseObjectType($classReflection->getName(), $node->name); } $reflectionConstant = $classReflection->getNativeReflection()->getReflectionConstant($node->name); if ($reflectionConstant === \false) { return new ErrorType(); } $declaringClass = $reflectionConstant->getDeclaringClass(); return $this->initializerExprTypeResolver->getType($reflectionConstant->getValueExpression(), InitializerExprContext::fromClass($declaringClass->getName(), $declaringClass->getFileName() ?: null)); } return new ErrorType(); } private function resolveArrayNode(ConstExprArrayNode $node, NameScope $nameScope) : Type { $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach ($node->items as $item) { if ($item->key === null) { $key = null; } else { $key = $this->resolve($item->key, $nameScope); } $arrayBuilder->setOffsetValueType($key, $this->resolve($item->value, $nameScope)); } return $arrayBuilder->getArray(); } private function getReflectionProvider() : ReflectionProvider { return $this->reflectionProviderProvider->getReflectionProvider(); } } typeNodeResolver = $typeNodeResolver; $this->constExprNodeResolver = $constExprNodeResolver; $this->unresolvableTypeHelper = $unresolvableTypeHelper; } /** * @return array<(string|int), VarTag> */ public function resolveVarTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; $resolvedByTag = []; foreach (['@var', '@phan-var', '@psalm-var', '@phpstan-var'] as $tagName) { $tagResolved = []; foreach ($phpDocNode->getVarTagValues($tagName) as $tagValue) { $type = $this->typeNodeResolver->resolve($tagValue->type, $nameScope); if ($this->shouldSkipType($tagName, $type)) { continue; } if ($tagValue->variableName !== '') { $variableName = substr($tagValue->variableName, 1); $resolved[$variableName] = new VarTag($type, \true); } else { $varTag = new VarTag($type, \true); $tagResolved[] = $varTag; } } if (count($tagResolved) === 0) { continue; } $resolvedByTag[] = $tagResolved; } if (count($resolvedByTag) > 0) { return array_reverse($resolvedByTag)[0]; } return $resolved; } /** * @return array */ public function resolvePropertyTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; foreach (['@property', '@phpstan-property'] as $tagName) { foreach ($phpDocNode->getPropertyTagValues($tagName) as $tagValue) { $propertyName = substr($tagValue->propertyName, 1); $propertyType = $this->typeNodeResolver->resolve($tagValue->type, $nameScope); $resolved[$propertyName] = new PropertyTag($propertyType, $propertyType, $propertyType); } } foreach (['@property-read', '@phpstan-property-read'] as $tagName) { foreach ($phpDocNode->getPropertyReadTagValues($tagName) as $tagValue) { $propertyName = substr($tagValue->propertyName, 1); $propertyType = $this->typeNodeResolver->resolve($tagValue->type, $nameScope); $writableType = null; if (array_key_exists($propertyName, $resolved)) { $writableType = $resolved[$propertyName]->getWritableType(); } $resolved[$propertyName] = new PropertyTag($propertyType, $propertyType, $writableType); } } foreach (['@property-write', '@phpstan-property-write'] as $tagName) { foreach ($phpDocNode->getPropertyWriteTagValues($tagName) as $tagValue) { $propertyName = substr($tagValue->propertyName, 1); $propertyType = $this->typeNodeResolver->resolve($tagValue->type, $nameScope); $readableType = null; if (array_key_exists($propertyName, $resolved)) { $readableType = $resolved[$propertyName]->getReadableType(); } $resolved[$propertyName] = new PropertyTag($readableType ?? $propertyType, $readableType, $propertyType); } } return $resolved; } /** * @return array */ public function resolveMethodTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; $originalNameScope = $nameScope; foreach (['@method', '@phan-method', '@psalm-method', '@phpstan-method'] as $tagName) { foreach ($phpDocNode->getMethodTagValues($tagName) as $tagValue) { $nameScope = $originalNameScope; $templateTags = []; if (count($tagValue->templateTypes) > 0 && $nameScope->getClassName() !== null) { foreach ($tagValue->templateTypes as $templateType) { $templateTags[$templateType->name] = new TemplateTag($templateType->name, $templateType->bound !== null ? $this->typeNodeResolver->resolve($templateType->bound, $nameScope) : new MixedType(), $templateType->default !== null ? $this->typeNodeResolver->resolve($templateType->default, $nameScope) : null, TemplateTypeVariance::createInvariant()); } $templateTypeScope = TemplateTypeScope::createWithMethod($nameScope->getClassName(), $tagValue->methodName); $templateTypeMap = new TemplateTypeMap(array_map(static function (TemplateTag $tag) use($templateTypeScope) : Type { return TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag); }, $templateTags)); $nameScope = $nameScope->withTemplateTypeMap($templateTypeMap); } $parameters = []; foreach ($tagValue->parameters as $parameterNode) { $parameterName = substr($parameterNode->parameterName, 1); $type = $parameterNode->type !== null ? $this->typeNodeResolver->resolve($parameterNode->type, $nameScope) : new MixedType(); if ($parameterNode->defaultValue instanceof ConstExprNullNode) { $type = TypeCombinator::addNull($type); } $defaultValue = null; if ($parameterNode->defaultValue !== null) { $defaultValue = $this->constExprNodeResolver->resolve($parameterNode->defaultValue, $nameScope); } $parameters[$parameterName] = new MethodTagParameter($type, $parameterNode->isReference ? PassedByReference::createCreatesNewVariable() : PassedByReference::createNo(), $parameterNode->isVariadic || $parameterNode->defaultValue !== null, $parameterNode->isVariadic, $defaultValue); } $resolved[$tagValue->methodName] = new MethodTag($tagValue->returnType !== null ? $this->typeNodeResolver->resolve($tagValue->returnType, $nameScope) : new MixedType(), $tagValue->isStatic, $parameters, $templateTags); } } return $resolved; } /** * @return array */ public function resolveExtendsTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; foreach (['@extends', '@phan-extends', '@phan-inherits', '@template-extends', '@phpstan-extends'] as $tagName) { foreach ($phpDocNode->getExtendsTagValues($tagName) as $tagValue) { $resolved[$nameScope->resolveStringName($tagValue->type->type->name)] = new ExtendsTag($this->typeNodeResolver->resolve($tagValue->type, $nameScope)); } } return $resolved; } /** * @return array */ public function resolveImplementsTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; foreach (['@implements', '@template-implements', '@phpstan-implements'] as $tagName) { foreach ($phpDocNode->getImplementsTagValues($tagName) as $tagValue) { $resolved[$nameScope->resolveStringName($tagValue->type->type->name)] = new ImplementsTag($this->typeNodeResolver->resolve($tagValue->type, $nameScope)); } } return $resolved; } /** * @return array */ public function resolveUsesTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; foreach (['@use', '@template-use', '@phpstan-use'] as $tagName) { foreach ($phpDocNode->getUsesTagValues($tagName) as $tagValue) { $resolved[$nameScope->resolveStringName($tagValue->type->type->name)] = new UsesTag($this->typeNodeResolver->resolve($tagValue->type, $nameScope)); } } return $resolved; } /** * @return array */ public function resolveTemplateTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; $resolvedPrefix = []; $prefixPriority = ['' => 0, 'phan' => 1, 'psalm' => 2, 'phpstan' => 3]; foreach ($phpDocNode->getTags() as $phpDocTagNode) { $valueNode = $phpDocTagNode->value; if (!$valueNode instanceof TemplateTagValueNode) { continue; } $tagName = $phpDocTagNode->name; if (in_array($tagName, ['@template', '@phan-template', '@psalm-template', '@phpstan-template'], \true)) { $variance = TemplateTypeVariance::createInvariant(); } elseif (in_array($tagName, ['@template-covariant', '@psalm-template-covariant', '@phpstan-template-covariant'], \true)) { $variance = TemplateTypeVariance::createCovariant(); } elseif (in_array($tagName, ['@template-contravariant', '@psalm-template-contravariant', '@phpstan-template-contravariant'], \true)) { $variance = TemplateTypeVariance::createContravariant(); } else { continue; } if (str_starts_with($tagName, '@phan-')) { $prefix = 'phan'; } elseif (str_starts_with($tagName, '@psalm-')) { $prefix = 'psalm'; } elseif (str_starts_with($tagName, '@phpstan-')) { $prefix = 'phpstan'; } else { $prefix = ''; } if (isset($resolved[$valueNode->name])) { $setPrefix = $resolvedPrefix[$valueNode->name]; if ($prefixPriority[$prefix] <= $prefixPriority[$setPrefix]) { continue; } } $nameScopeWithoutCurrent = $nameScope->unsetTemplateType($valueNode->name); $resolved[$valueNode->name] = new TemplateTag($valueNode->name, $valueNode->bound !== null ? $this->typeNodeResolver->resolve($valueNode->bound, $nameScopeWithoutCurrent) : new MixedType(\true), $valueNode->default !== null ? $this->typeNodeResolver->resolve($valueNode->default, $nameScopeWithoutCurrent) : null, $variance); $resolvedPrefix[$valueNode->name] = $prefix; } return $resolved; } /** * @return array */ public function resolveParamTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; foreach (['@param', '@phan-param', '@psalm-param', '@phpstan-param'] as $tagName) { foreach ($phpDocNode->getParamTagValues($tagName) as $tagValue) { $parameterName = substr($tagValue->parameterName, 1); $parameterType = $this->typeNodeResolver->resolve($tagValue->type, $nameScope); if ($this->shouldSkipType($tagName, $parameterType)) { continue; } $resolved[$parameterName] = new ParamTag($parameterType, $tagValue->isVariadic); } } return $resolved; } /** * @return array */ public function resolveParamOutTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { if (!method_exists($phpDocNode, 'getParamOutTypeTagValues')) { return []; } $resolved = []; foreach (['@param-out', '@psalm-param-out', '@phpstan-param-out'] as $tagName) { foreach ($phpDocNode->getParamOutTypeTagValues($tagName) as $tagValue) { $parameterName = substr($tagValue->parameterName, 1); $parameterType = $this->typeNodeResolver->resolve($tagValue->type, $nameScope); if ($this->shouldSkipType($tagName, $parameterType)) { continue; } $resolved[$parameterName] = new ParamOutTag($parameterType); } } return $resolved; } /** * @return array */ public function resolveParamImmediatelyInvokedCallable(PhpDocNode $phpDocNode) : array { $parameters = []; foreach (['@param-immediately-invoked-callable', '@phpstan-param-immediately-invoked-callable'] as $tagName) { foreach ($phpDocNode->getParamImmediatelyInvokedCallableTagValues($tagName) as $tagValue) { $parameterName = substr($tagValue->parameterName, 1); $parameters[$parameterName] = \true; } } foreach (['@param-later-invoked-callable', '@phpstan-param-later-invoked-callable'] as $tagName) { foreach ($phpDocNode->getParamLaterInvokedCallableTagValues($tagName) as $tagValue) { $parameterName = substr($tagValue->parameterName, 1); $parameters[$parameterName] = \false; } } return $parameters; } /** * @return array */ public function resolveParamClosureThisTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $closureThisTypes = []; foreach (['@param-closure-this', '@phpstan-param-closure-this'] as $tagName) { foreach ($phpDocNode->getParamClosureThisTagValues($tagName) as $tagValue) { $parameterName = substr($tagValue->parameterName, 1); $closureThisTypes[$parameterName] = new ParamClosureThisTag(TypeCombinator::intersect($this->typeNodeResolver->resolve($tagValue->type, $nameScope), new ObjectWithoutClassType())); } } return $closureThisTypes; } public function resolveReturnTag(PhpDocNode $phpDocNode, NameScope $nameScope) : ?ReturnTag { $resolved = null; foreach (['@return', '@phan-return', '@phan-real-return', '@psalm-return', '@phpstan-return'] as $tagName) { foreach ($phpDocNode->getReturnTagValues($tagName) as $tagValue) { $type = $this->typeNodeResolver->resolve($tagValue->type, $nameScope); if ($this->shouldSkipType($tagName, $type)) { continue; } $resolved = new ReturnTag($type, \true); } } return $resolved; } public function resolveThrowsTags(PhpDocNode $phpDocNode, NameScope $nameScope) : ?ThrowsTag { foreach (['@phpstan-throws', '@throws'] as $tagName) { $types = []; foreach ($phpDocNode->getThrowsTagValues($tagName) as $tagValue) { $type = $this->typeNodeResolver->resolve($tagValue->type, $nameScope); if ($this->shouldSkipType($tagName, $type)) { continue; } $types[] = $type; } if (count($types) > 0) { return new ThrowsTag(TypeCombinator::union(...$types)); } } return null; } /** * @return array */ public function resolveMixinTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { return array_map(function (MixinTagValueNode $mixinTagValueNode) use($nameScope) : MixinTag { return new MixinTag($this->typeNodeResolver->resolve($mixinTagValueNode->type, $nameScope)); }, $phpDocNode->getMixinTagValues()); } /** * @return array */ public function resolveRequireExtendsTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; foreach (['@psalm-require-extends', '@phpstan-require-extends'] as $tagName) { foreach ($phpDocNode->getRequireExtendsTagValues($tagName) as $tagValue) { $resolved[] = new RequireExtendsTag($this->typeNodeResolver->resolve($tagValue->type, $nameScope)); } } return $resolved; } /** * @return array */ public function resolveRequireImplementsTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; foreach (['@psalm-require-implements', '@phpstan-require-implements'] as $tagName) { foreach ($phpDocNode->getRequireImplementsTagValues($tagName) as $tagValue) { $resolved[] = new RequireImplementsTag($this->typeNodeResolver->resolve($tagValue->type, $nameScope)); } } return $resolved; } /** * @return array */ public function resolveTypeAliasTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; foreach (['@phan-type', '@psalm-type', '@phpstan-type'] as $tagName) { foreach ($phpDocNode->getTypeAliasTagValues($tagName) as $typeAliasTagValue) { $alias = $typeAliasTagValue->alias; $typeNode = $typeAliasTagValue->type; $resolved[$alias] = new TypeAliasTag($alias, $typeNode, $nameScope); } } return $resolved; } /** * @return array */ public function resolveTypeAliasImportTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { $resolved = []; foreach (['@psalm-import-type', '@phpstan-import-type'] as $tagName) { foreach ($phpDocNode->getTypeAliasImportTagValues($tagName) as $typeAliasImportTagValue) { $importedAlias = $typeAliasImportTagValue->importedAlias; $importedFrom = $nameScope->resolveStringName($typeAliasImportTagValue->importedFrom->name); $importedAs = $typeAliasImportTagValue->importedAs; $resolved[$importedAs ?? $importedAlias] = new TypeAliasImportTag($importedAlias, $importedFrom, $importedAs); } } return $resolved; } /** * @return AssertTag[] */ public function resolveAssertTags(PhpDocNode $phpDocNode, NameScope $nameScope) : array { foreach (['@phpstan', '@psalm', '@phan'] as $prefix) { $resolved = array_merge($this->resolveAssertTagsFor($phpDocNode, $nameScope, $prefix . '-assert', AssertTag::NULL), $this->resolveAssertTagsFor($phpDocNode, $nameScope, $prefix . '-assert-if-true', AssertTag::IF_TRUE), $this->resolveAssertTagsFor($phpDocNode, $nameScope, $prefix . '-assert-if-false', AssertTag::IF_FALSE)); if (count($resolved) > 0) { return $resolved; } } return []; } /** * @param AssertTag::NULL|AssertTag::IF_TRUE|AssertTag::IF_FALSE $if * @return AssertTag[] */ private function resolveAssertTagsFor(PhpDocNode $phpDocNode, NameScope $nameScope, string $tagName, string $if) : array { $resolved = []; foreach ($phpDocNode->getAssertTagValues($tagName) as $assertTagValue) { $type = $this->typeNodeResolver->resolve($assertTagValue->type, $nameScope); $parameter = new AssertTagParameter($assertTagValue->parameter, null, null); $resolved[] = new AssertTag($if, $type, $parameter, $assertTagValue->isNegated, $assertTagValue->isEquality ?? \false, \true); } foreach ($phpDocNode->getAssertPropertyTagValues($tagName) as $assertTagValue) { $type = $this->typeNodeResolver->resolve($assertTagValue->type, $nameScope); $parameter = new AssertTagParameter($assertTagValue->parameter, $assertTagValue->property, null); $resolved[] = new AssertTag($if, $type, $parameter, $assertTagValue->isNegated, $assertTagValue->isEquality ?? \false, \true); } foreach ($phpDocNode->getAssertMethodTagValues($tagName) as $assertTagValue) { $type = $this->typeNodeResolver->resolve($assertTagValue->type, $nameScope); $parameter = new AssertTagParameter($assertTagValue->parameter, null, $assertTagValue->method); $resolved[] = new AssertTag($if, $type, $parameter, $assertTagValue->isNegated, $assertTagValue->isEquality ?? \false, \true); } return $resolved; } public function resolveSelfOutTypeTag(PhpDocNode $phpDocNode, NameScope $nameScope) : ?SelfOutTypeTag { if (!method_exists($phpDocNode, 'getSelfOutTypeTagValues')) { return null; } foreach (['@phpstan-this-out', '@phpstan-self-out', '@psalm-this-out', '@psalm-self-out'] as $tagName) { foreach ($phpDocNode->getSelfOutTypeTagValues($tagName) as $selfOutTypeTagValue) { $type = $this->typeNodeResolver->resolve($selfOutTypeTagValue->type, $nameScope); return new SelfOutTypeTag($type); } } return null; } public function resolveDeprecatedTag(PhpDocNode $phpDocNode, NameScope $nameScope) : ?DeprecatedTag { foreach ($phpDocNode->getDeprecatedTagValues() as $deprecatedTagValue) { $description = (string) $deprecatedTagValue; return new DeprecatedTag($description === '' ? null : $description); } return null; } public function resolveIsDeprecated(PhpDocNode $phpDocNode) : bool { $deprecatedTags = $phpDocNode->getTagsByName('@deprecated'); return count($deprecatedTags) > 0; } public function resolveIsNotDeprecated(PhpDocNode $phpDocNode) : bool { $notDeprecatedTags = $phpDocNode->getTagsByName('@not-deprecated'); return count($notDeprecatedTags) > 0; } public function resolveIsInternal(PhpDocNode $phpDocNode) : bool { $internalTags = $phpDocNode->getTagsByName('@internal'); return count($internalTags) > 0; } public function resolveIsFinal(PhpDocNode $phpDocNode) : bool { $finalTags = $phpDocNode->getTagsByName('@final'); return count($finalTags) > 0; } public function resolveIsPure(PhpDocNode $phpDocNode) : bool { foreach ($phpDocNode->getTags() as $phpDocTagNode) { if (in_array($phpDocTagNode->name, ['@pure', '@phan-pure', '@phan-side-effect-free', '@psalm-pure', '@phpstan-pure'], \true)) { return \true; } } return \false; } public function resolveIsImpure(PhpDocNode $phpDocNode) : bool { foreach ($phpDocNode->getTags() as $phpDocTagNode) { if (in_array($phpDocTagNode->name, ['@impure', '@phpstan-impure'], \true)) { return \true; } } return \false; } public function resolveIsReadOnly(PhpDocNode $phpDocNode) : bool { foreach (['@readonly', '@phan-read-only', '@psalm-readonly', '@phpstan-readonly', '@phpstan-readonly-allow-private-mutation', '@psalm-readonly-allow-private-mutation'] as $tagName) { $tags = $phpDocNode->getTagsByName($tagName); if (count($tags) > 0) { return \true; } } return \false; } public function resolveIsImmutable(PhpDocNode $phpDocNode) : bool { foreach (['@immutable', '@phan-immutable', '@psalm-immutable', '@phpstan-immutable'] as $tagName) { $tags = $phpDocNode->getTagsByName($tagName); if (count($tags) > 0) { return \true; } } return \false; } public function resolveHasConsistentConstructor(PhpDocNode $phpDocNode) : bool { foreach (['@consistent-constructor', '@phpstan-consistent-constructor', '@psalm-consistent-constructor'] as $tagName) { $tags = $phpDocNode->getTagsByName($tagName); if (count($tags) > 0) { return \true; } } return \false; } public function resolveAcceptsNamedArguments(PhpDocNode $phpDocNode) : bool { return count($phpDocNode->getTagsByName('@no-named-arguments')) === 0; } private function shouldSkipType(string $tagName, Type $type) : bool { if (!str_starts_with($tagName, '@psalm-')) { return \false; } return $this->unresolvableTypeHelper->containsUnresolvableType($type); } public function resolveAllowPrivateMutation(PhpDocNode $phpDocNode) : bool { foreach (['@phpstan-readonly-allow-private-mutation', '@phpstan-allow-private-mutation', '@psalm-readonly-allow-private-mutation', '@psalm-allow-private-mutation'] as $tagName) { $tags = $phpDocNode->getTagsByName($tagName); if (count($tags) > 0) { return \true; } } return \false; } } phpVersion = $phpVersion; } public function getFiles() : array { if ($this->phpVersion->getVersionId() >= 80000) { return [__DIR__ . '/../../stubs/socket_select_php8.stub']; } return [__DIR__ . '/../../stubs/socket_select.stub']; } } $arrays * @return iterable */ public static function combinations(array $arrays) : iterable { // from https://stackoverflow.com/a/70800936/565782 by Arnaud Le Blanc if ($arrays === []) { (yield []); return; } $head = array_shift($arrays); foreach ($head as $elem) { foreach (self::combinations($arrays) as $combination) { $comb = [$elem]; foreach ($combination as $c) { $comb[] = $c; } (yield $comb); } } } } getName(), ['getByType'], \true); } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : Type { if (count($methodCall->getArgs()) === 0) { return ParametersAcceptorSelector::selectFromArgs($scope, $methodCall->getArgs(), $methodReflection->getVariants())->getReturnType(); } $argType = $scope->getType($methodCall->getArgs()[0]->value); if (!$argType instanceof ConstantStringType) { return ParametersAcceptorSelector::selectFromArgs($scope, $methodCall->getArgs(), $methodReflection->getVariants())->getReturnType(); } $type = new ObjectType($argType->getValue()); if ($methodReflection->getName() === 'getByType' && count($methodCall->getArgs()) >= 2) { $argType = $scope->getType($methodCall->getArgs()[1]->value); if ($argType->isTrue()->yes()) { $type = TypeCombinator::addNull($type); } } return $type; } } |null */ public static function getComposerConfig(string $root) : ?array { $composerJsonPath = self::getComposerJsonPath($root); if (!is_file($composerJsonPath)) { return null; } try { $composerJsonContents = FileReader::read($composerJsonPath); return Json::decode($composerJsonContents, Json::FORCE_ARRAY); } catch (CouldNotReadFileException|JsonException $e) { return null; } } private static function getComposerJsonPath(string $root) : string { $envComposer = getenv('COMPOSER'); $fileName = is_string($envComposer) ? $envComposer : 'composer.json'; $fileName = basename(trim($fileName)); return $root . '/' . $fileName; } /** * @param array $composerConfig */ public static function getVendorDirFromComposerConfig(string $root, array $composerConfig) : string { $vendorDirectory = $composerConfig['config']['vendor-dir'] ?? 'vendor'; return $root . '/' . trim($vendorDirectory, '/'); } /** * @param array $composerConfig */ public static function getBinDirFromComposerConfig(string $root, array $composerConfig) : string { $vendorDirectory = $composerConfig['config']['bin-dir'] ?? 'vendor/bin'; return $root . '/' . trim($vendorDirectory, '/'); } public static function getPhpStanVersion() : string { if (self::$phpstanVersion !== null) { return self::$phpstanVersion; } $installed = (require __DIR__ . '/../../vendor/composer/installed.php'); $rootPackage = $installed['root'] ?? null; if ($rootPackage === null) { return self::$phpstanVersion = self::UNKNOWN_VERSION; } if (preg_match('/[^v\\d.]/', $rootPackage['pretty_version']) === 0) { // Handles tagged versions, see https://github.com/Jean85/pretty-package-versions/blob/2.0.5/src/Version.php#L31 return self::$phpstanVersion = $rootPackage['pretty_version']; } return self::$phpstanVersion = $rootPackage['pretty_version'] . '@' . substr((string) $rootPackage['reference'], 0, 7); } } directory = $directory; $error = error_get_last(); parent::__construct(sprintf('Failed to create directory "%s" (%s).', $directory, is_null($error) ? 'unknown cause' : $error['message'])); } } body = $body; $this->conditions = $conditions; $this->line = $line; } public function getBody() : \PHPStan\Node\MatchExpressionArmBody { return $this->body; } /** * @return MatchExpressionArmCondition[] */ public function getConditions() : array { return $this->conditions; } public function getLine() : int { return $this->line; } } */ private $propertyUsages; /** * @var array */ private $methodCalls; /** * @var array */ private $returnStatementNodes; /** * @var list */ private $propertyAssigns; /** * @var ClassReflection */ private $classReflection; /** * @param ClassPropertyNode[] $properties * @param array $propertyUsages * @param array $methodCalls * @param array $returnStatementNodes * @param list $propertyAssigns */ public function __construct(ClassLike $class, ReadWritePropertiesExtensionProvider $readWritePropertiesExtensionProvider, array $properties, array $propertyUsages, array $methodCalls, array $returnStatementNodes, array $propertyAssigns, ClassReflection $classReflection) { $this->class = $class; $this->readWritePropertiesExtensionProvider = $readWritePropertiesExtensionProvider; $this->properties = $properties; $this->propertyUsages = $propertyUsages; $this->methodCalls = $methodCalls; $this->returnStatementNodes = $returnStatementNodes; $this->propertyAssigns = $propertyAssigns; $this->classReflection = $classReflection; parent::__construct($class->getAttributes()); } public function getClass() : ClassLike { return $this->class; } /** * @return ClassPropertyNode[] */ public function getProperties() : array { return $this->properties; } /** * @return array */ public function getPropertyUsages() : array { return $this->propertyUsages; } public function getType() : string { return 'PHPStan_Node_ClassPropertiesNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } public function getClassReflection() : ClassReflection { return $this->classReflection; } /** * @param string[] $constructors * @param ReadWritePropertiesExtension[]|null $extensions * @return array{array, array, array} */ public function getUninitializedProperties(Scope $scope, array $constructors, ?array $extensions = null) : array { if (!$this->getClass() instanceof Class_) { return [[], [], []]; } $classReflection = $this->getClassReflection(); $uninitializedProperties = []; $originalProperties = []; $initialInitializedProperties = []; $initializedProperties = []; if ($extensions === null) { $extensions = $this->readWritePropertiesExtensionProvider->getExtensions(); } $initializedViaExtension = []; foreach ($this->getProperties() as $property) { if ($property->isStatic()) { continue; } if ($property->getNativeType() === null) { continue; } if ($property->getDefault() !== null) { continue; } $originalProperties[$property->getName()] = $property; $is = TrinaryLogic::createFromBoolean($property->isPromoted() && !$property->isPromotedFromTrait()); if (!$is->yes() && $classReflection->hasNativeProperty($property->getName())) { $propertyReflection = $classReflection->getNativeProperty($property->getName()); foreach ($extensions as $extension) { if (!$extension->isInitialized($propertyReflection, $property->getName())) { continue; } $is = TrinaryLogic::createYes(); $initializedViaExtension[$property->getName()] = \true; break; } } $initialInitializedProperties[$property->getName()] = $is; foreach ($constructors as $constructor) { $initializedProperties[$constructor][$property->getName()] = $is; } if ($is->yes()) { continue; } $uninitializedProperties[$property->getName()] = $property; } if ($constructors === []) { return [$uninitializedProperties, [], []]; } $initializedInConstructor = []; if ($classReflection->hasConstructor()) { $initializedInConstructor = array_diff_key($uninitializedProperties, $this->collectUninitializedProperties([$classReflection->getConstructor()->getName()], $uninitializedProperties)); } $methodsCalledFromConstructor = $this->getMethodsCalledFromConstructor($classReflection, $initialInitializedProperties, $initializedProperties, $constructors, $initializedInConstructor); $prematureAccess = []; $additionalAssigns = []; foreach ($this->getPropertyUsages() as $usage) { $fetch = $usage->getFetch(); if (!$fetch instanceof PropertyFetch) { continue; } $usageScope = $usage->getScope(); if ($usageScope->getFunction() === null) { continue; } $function = $usageScope->getFunction(); if (!$function instanceof MethodReflection) { continue; } if ($function->getDeclaringClass()->getName() !== $classReflection->getName()) { continue; } if (!array_key_exists($function->getName(), $methodsCalledFromConstructor)) { continue; } $initializedPropertiesMap = $methodsCalledFromConstructor[$function->getName()]; if (!$fetch->name instanceof Identifier) { continue; } $propertyName = $fetch->name->toString(); $fetchedOnType = $usageScope->getType($fetch->var); if (TypeUtils::findThisType($fetchedOnType) === null) { continue; } $propertyReflection = $usageScope->getPropertyReflection($fetchedOnType, $propertyName); if ($propertyReflection === null) { continue; } if ($propertyReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { continue; } if ($usage instanceof PropertyWrite) { if (array_key_exists($propertyName, $initializedPropertiesMap)) { $hasInitialization = $initializedPropertiesMap[$propertyName]->or($usageScope->hasExpressionType(new PropertyInitializationExpr($propertyName))); if (!$hasInitialization->no() && !$usage->isPromotedPropertyWrite() && !array_key_exists($propertyName, $initializedViaExtension)) { $additionalAssigns[] = [$propertyName, $fetch->getStartLine(), $originalProperties[$propertyName]]; } } } elseif (array_key_exists($propertyName, $initializedPropertiesMap)) { if (strtolower($function->getName()) !== '__construct' && array_key_exists($propertyName, $initializedInConstructor) && in_array($function->getName(), $constructors, \true)) { continue; } $hasInitialization = $initializedPropertiesMap[$propertyName]->or($usageScope->hasExpressionType(new PropertyInitializationExpr($propertyName))); if (!$hasInitialization->yes() && $usageScope->isInAnonymousFunction() && $usageScope->getParentScope() !== null) { $hasInitialization = $hasInitialization->or($usageScope->getParentScope()->hasExpressionType(new PropertyInitializationExpr($propertyName))); } if (!$hasInitialization->yes()) { $prematureAccess[] = [$propertyName, $fetch->getStartLine(), $originalProperties[$propertyName], $usageScope->getFile(), $usageScope->getFileDescription()]; } } } return [$this->collectUninitializedProperties(array_keys($methodsCalledFromConstructor), $uninitializedProperties), $prematureAccess, $additionalAssigns]; } /** * @param list $constructors * @param array $uninitializedProperties * @return array */ private function collectUninitializedProperties(array $constructors, array $uninitializedProperties) : array { foreach ($constructors as $constructor) { $lowerConstructorName = strtolower($constructor); if (!array_key_exists($lowerConstructorName, $this->returnStatementNodes)) { continue; } $returnStatementsNode = $this->returnStatementNodes[$lowerConstructorName]; $methodScope = null; foreach ($returnStatementsNode->getExecutionEnds() as $executionEnd) { $statementResult = $executionEnd->getStatementResult(); $endNode = $executionEnd->getNode(); if ($statementResult->isAlwaysTerminating()) { if ($endNode instanceof Node\Stmt\Throw_) { continue; } if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); if ($exprType instanceof NeverType && $exprType->isExplicit()) { continue; } } } if ($methodScope === null) { $methodScope = $statementResult->getScope(); continue; } $methodScope = $methodScope->mergeWith($statementResult->getScope()); } foreach ($returnStatementsNode->getReturnStatements() as $returnStatement) { if ($methodScope === null) { $methodScope = $returnStatement->getScope(); continue; } $methodScope = $methodScope->mergeWith($returnStatement->getScope()); } if ($methodScope === null) { continue; } foreach (array_keys($uninitializedProperties) as $propertyName) { if (!$methodScope->hasExpressionType(new PropertyInitializationExpr($propertyName))->yes()) { continue; } unset($uninitializedProperties[$propertyName]); } } return $uninitializedProperties; } /** * @param string[] $methods * @param array $initialInitializedProperties * @param array> $initializedProperties * @param array $initializedInConstructorProperties * * @return array> */ private function getMethodsCalledFromConstructor(ClassReflection $classReflection, array $initialInitializedProperties, array $initializedProperties, array $methods, array $initializedInConstructorProperties) : array { $originalMap = $initializedProperties; $originalMethods = $methods; foreach ($this->methodCalls as $methodCall) { $methodCallNode = $methodCall->getNode(); if ($methodCallNode instanceof Array_) { continue; } if (!$methodCallNode->name instanceof Identifier) { continue; } $callScope = $methodCall->getScope(); if ($methodCallNode instanceof Node\Expr\MethodCall) { $calledOnType = $callScope->getType($methodCallNode->var); } else { if (!$methodCallNode->class instanceof Name) { continue; } $calledOnType = $callScope->resolveTypeByName($methodCallNode->class); } if (TypeUtils::findThisType($calledOnType) === null) { continue; } $inMethod = $callScope->getFunction(); if (!$inMethod instanceof MethodReflection) { continue; } if (!in_array($inMethod->getName(), $methods, \true)) { continue; } if ($inMethod->getName() !== '__construct') { foreach ($initializedInConstructorProperties as $propertyName => $propertyNode) { $initializedProperties[$inMethod->getName()][$propertyName] = TrinaryLogic::createYes(); } } $methodName = $methodCallNode->name->toString(); if (array_key_exists($methodName, $initializedProperties)) { foreach ($this->getInitializedProperties($callScope, $initializedProperties[$inMethod->getName()] ?? $initialInitializedProperties) as $propertyName => $isInitialized) { $initializedProperties[$methodName][$propertyName] = $initializedProperties[$methodName][$propertyName]->and($isInitialized); } continue; } $methodReflection = $callScope->getMethodReflection($calledOnType, $methodName); if ($methodReflection === null) { continue; } if ($methodReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { continue; } $initializedProperties[$methodName] = $this->getInitializedProperties($callScope, $initializedProperties[$inMethod->getName()] ?? $initialInitializedProperties); $methods[] = $methodName; } if ($originalMap === $initializedProperties && $originalMethods === $methods) { return $initializedProperties; } return $this->getMethodsCalledFromConstructor($classReflection, $initialInitializedProperties, $initializedProperties, $methods, $initializedInConstructorProperties); } /** * @param array $initialInitializedProperties * @return array */ private function getInitializedProperties(Scope $scope, array $initialInitializedProperties) : array { foreach ($initialInitializedProperties as $propertyName => $isInitialized) { $initialInitializedProperties[$propertyName] = $isInitialized->or($scope->hasExpressionType(new PropertyInitializationExpr($propertyName))); } return $initialInitializedProperties; } /** * @return list */ public function getPropertyAssigns() : array { return $this->propertyAssigns; } } class = $class; $this->originalNode = $originalNode; parent::__construct($this->originalNode->getAttributes()); } /** * @return Expr|Name */ public function getClass() { return $this->class; } public function getOriginalNode() : Expr\New_ { return $this->originalNode; } public function getType() : string { return 'PHPStan_Node_InstantiationCallableNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } functionReflection = $functionReflection; $this->originalNode = $originalNode; parent::__construct($originalNode->getAttributes()); } public function getFunctionReflection() : PhpFunctionFromParserNodeReflection { return $this->functionReflection; } public function getOriginalNode() : Node\Stmt\Function_ { return $this->originalNode; } public function getType() : string { return 'PHPStan_Stmt_InFunctionNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } originalNode = $originalNode; $this->caughtType = $caughtType; $this->originalCaughtType = $originalCaughtType; parent::__construct($originalNode->getAttributes()); } public function getOriginalNode() : Catch_ { return $this->originalNode; } public function getCaughtType() : Type { return $this->caughtType; } public function getOriginalCaughtType() : Type { return $this->originalCaughtType; } public function getType() : string { return 'PHPStan_Node_CatchWithUnthrownExceptionNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } scope = $scope; $this->body = $body; } public function getScope() : Scope { return $this->scope; } public function getBody() : Expr { return $this->body; } } collectedData = $collectedData; $this->onlyFiles = $onlyFiles; parent::__construct([]); } /** * @template TCollector of Collector * @template TValue * @param class-string $collectorType * @return array> */ public function get(string $collectorType) : array { $result = []; foreach ($this->collectedData as $collectedData) { if ($collectedData->getCollectorType() !== $collectorType) { continue; } $filePath = $collectedData->getFilePath(); if (!array_key_exists($filePath, $result)) { $result[$filePath] = []; } $result[$filePath][] = $collectedData->getData(); } return $result; } /** * Indicates that only files were passed to the analyser, not directory paths. * * True being returned strongly suggests that it's a partial analysis, not full project analysis. */ public function isOnlyFilesAnalysis() : bool { return $this->onlyFiles; } public function getType() : string { return 'PHPStan_Node_CollectedDataNode'; } /** * @return array{} */ public function getSubNodeNames() : array { return []; } } node = $node; $this->scope = $scope; } public function getNode() : ClassConstFetch { return $this->node; } public function getScope() : Scope { return $this->scope; } } isDeclaredInTrait = $isDeclaredInTrait; parent::__construct($node->name, ['flags' => $node->flags, 'byRef' => $node->byRef, 'params' => $node->params, 'returnType' => $node->returnType, 'stmts' => $node->stmts, 'attrGroups' => $node->attrGroups], $node->attributes); } public function getNode() : PhpParserClassMethod { return $this; } public function isDeclaredInTrait() : bool { return $this->isDeclaredInTrait; } } name = $name; $this->flags = $flags; $this->type = $type; $this->default = $default; $this->phpDoc = $phpDoc; $this->phpDocType = $phpDocType; $this->isPromoted = $isPromoted; $this->isPromotedFromTrait = $isPromotedFromTrait; $this->isReadonlyByPhpDoc = $isReadonlyByPhpDoc; $this->isDeclaredInTrait = $isDeclaredInTrait; $this->isReadonlyClass = $isReadonlyClass; $this->isAllowedPrivateMutation = $isAllowedPrivateMutation; $this->classReflection = $classReflection; parent::__construct($originalNode->getAttributes()); } public function getName() : string { return $this->name; } public function getFlags() : int { return $this->flags; } public function getDefault() : ?Expr { return $this->default; } public function isPromoted() : bool { return $this->isPromoted; } public function isPromotedFromTrait() : bool { return $this->isPromotedFromTrait; } public function getPhpDoc() : ?string { return $this->phpDoc; } public function getPhpDocType() : ?Type { return $this->phpDocType; } public function isPublic() : bool { return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; } public function isProtected() : bool { return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); } public function isPrivate() : bool { return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); } public function isStatic() : bool { return (bool) ($this->flags & Class_::MODIFIER_STATIC); } public function isReadOnly() : bool { return (bool) ($this->flags & Class_::MODIFIER_READONLY) || $this->isReadonlyClass; } public function isReadOnlyByPhpDoc() : bool { return $this->isReadonlyByPhpDoc; } public function isDeclaredInTrait() : bool { return $this->isDeclaredInTrait; } public function isAllowedPrivateMutation() : bool { return $this->isAllowedPrivateMutation; } /** * @return Identifier|Name|Node\ComplexType|null */ public function getNativeType() { return $this->type; } public function getClassReflection() : ClassReflection { return $this->classReflection; } public function getType() : string { return 'PHPStan_Node_ClassPropertyNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } node = $node; $this->statementResult = $statementResult; $this->hasNativeReturnTypehint = $hasNativeReturnTypehint; parent::__construct($node->getAttributes()); } public function getNode() : Node\Stmt { return $this->node; } public function getStatementResult() : StatementResult { return $this->statementResult; } public function hasNativeReturnTypehint() : bool { return $this->hasNativeReturnTypehint; } public function getType() : string { return 'PHPStan_Node_ExecutionEndNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } assign = $assign; $this->scope = $scope; } public function getAssign() : PropertyAssignNode { return $this->assign; } public function getScope() : Scope { return $this->scope; } } fetch = $fetch; $this->scope = $scope; $this->promotedPropertyWrite = $promotedPropertyWrite; } /** * @return PropertyFetch|StaticPropertyFetch */ public function getFetch() { return $this->fetch; } public function getScope() : Scope { return $this->scope; } public function isPromotedPropertyWrite() : bool { return $this->promotedPropertyWrite; } } fetch = $fetch; $this->scope = $scope; } /** * @return PropertyFetch|StaticPropertyFetch */ public function getFetch() { return $this->fetch; } public function getScope() : Scope { return $this->scope; } } class = $class; $this->name = $name; $this->originalNode = $originalNode; parent::__construct($originalNode->getAttributes()); } /** * @return Expr|Name */ public function getClass() { return $this->class; } /** * @return Identifier|Expr */ public function getName() { return $this->name; } public function getOriginalNode() : Expr\StaticCall { return $this->originalNode; } public function getType() : string { return 'PHPStan_Node_StaticMethodCallableNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } getSubNodeNames() as $subNodeName) { $subNodes[$subNodeName] = $node->{$subNodeName}; } return new \PHPStan\Node\AnonymousClassNode($node->name, $subNodes, $node->getAttributes()); } public function isAnonymous() : bool { return \true; } } expr = $expr; parent::__construct($expr->getAttributes()); } public function getExpr() : Expr { return $this->expr; } public function getType() : string { return 'PHPStan_Node_InvalidateExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } closureType = $closureType; parent::__construct($originalNode->getAttributes()); $this->originalNode = $originalNode; } public function getClosureType() : ClosureType { return $this->closureType; } public function getOriginalNode() : Node\Expr\ArrowFunction { return $this->originalNode; } public function getType() : string { return 'PHPStan_Node_InArrowFunctionNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } scope = $scope; $this->arrayItem = $arrayItem; } public function getScope() : Scope { return $this->scope; } public function getArrayItem() : ?ArrayItem { return $this->arrayItem; } } */ private $returnStatements; /** * @var list */ private $yieldStatements; /** * @var StatementResult */ private $statementResult; /** * @var list */ private $executionEnds; /** * @var ImpurePoint[] */ private $impurePoints; /** * @var PhpFunctionFromParserNodeReflection */ private $functionReflection; /** * @param list $returnStatements * @param list $yieldStatements * @param list $executionEnds * @param ImpurePoint[] $impurePoints */ public function __construct(Function_ $function, array $returnStatements, array $yieldStatements, StatementResult $statementResult, array $executionEnds, array $impurePoints, PhpFunctionFromParserNodeReflection $functionReflection) { $this->function = $function; $this->returnStatements = $returnStatements; $this->yieldStatements = $yieldStatements; $this->statementResult = $statementResult; $this->executionEnds = $executionEnds; $this->impurePoints = $impurePoints; $this->functionReflection = $functionReflection; parent::__construct($function->getAttributes()); } public function getReturnStatements() : array { return $this->returnStatements; } public function getStatementResult() : StatementResult { return $this->statementResult; } public function getExecutionEnds() : array { return $this->executionEnds; } public function getImpurePoints() : array { return $this->impurePoints; } public function returnsByRef() : bool { return $this->function->byRef; } public function hasNativeReturnTypehint() : bool { return $this->function->returnType !== null; } public function getYieldStatements() : array { return $this->yieldStatements; } public function isGenerator() : bool { return count($this->yieldStatements) > 0; } public function getType() : string { return 'PHPStan_Node_FunctionReturnStatementsNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } public function getFunctionReflection() : PhpFunctionFromParserNodeReflection { return $this->functionReflection; } /** * @return Stmt[] */ public function getStatements() : array { return $this->function->getStmts(); } } classReflection = $classReflection; $this->methodReflection = $methodReflection; $this->originalNode = $originalNode; parent::__construct($originalNode->getAttributes()); } public function getClassReflection() : ClassReflection { return $this->classReflection; } public function getMethodReflection() : PhpMethodFromParserNodeReflection { return $this->methodReflection; } public function getOriginalNode() : Node\Stmt\ClassMethod { return $this->originalNode; } public function getType() : string { return 'PHPStan_Stmt_InClassMethodNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } originalExpr = $originalExpr; $this->hasAssign = $hasAssign; parent::__construct($this->originalExpr->getAttributes()); } public function getOriginalExpr() : Expr { return $this->originalExpr; } public function hasAssign() : bool { return $this->hasAssign; } public function getType() : string { return 'PHPStan_Node_NoopExpressionNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } condition = $condition; $this->scope = $scope; $this->line = $line; } public function getCondition() : Expr { return $this->condition; } public function getScope() : Scope { return $this->scope; } public function getLine() : int { return $this->line; } } propertyFetch = $propertyFetch; $this->assignedExpr = $assignedExpr; $this->assignOp = $assignOp; parent::__construct($propertyFetch->getAttributes()); } /** * @return Expr\PropertyFetch|Expr\StaticPropertyFetch */ public function getPropertyFetch() { return $this->propertyFetch; } public function getAssignedExpr() : Expr { return $this->assignedExpr; } public function isAssignOp() : bool { return $this->assignOp; } public function getType() : string { return 'PHPStan_Node_PropertyAssignNodeNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } */ private $returnStatements; /** * @var list */ private $yieldStatements; /** * @var StatementResult */ private $statementResult; /** * @var list */ private $executionEnds; /** * @var ImpurePoint[] */ private $impurePoints; /** * @var ClassReflection */ private $classReflection; /** * @var PhpMethodFromParserNodeReflection */ private $methodReflection; /** * @var ClassMethod */ private $classMethod; /** * @param list $returnStatements * @param list $yieldStatements * @param list $executionEnds * @param ImpurePoint[] $impurePoints */ public function __construct(ClassMethod $method, array $returnStatements, array $yieldStatements, StatementResult $statementResult, array $executionEnds, array $impurePoints, ClassReflection $classReflection, PhpMethodFromParserNodeReflection $methodReflection) { $this->returnStatements = $returnStatements; $this->yieldStatements = $yieldStatements; $this->statementResult = $statementResult; $this->executionEnds = $executionEnds; $this->impurePoints = $impurePoints; $this->classReflection = $classReflection; $this->methodReflection = $methodReflection; parent::__construct($method->getAttributes()); $this->classMethod = $method; } public function getReturnStatements() : array { return $this->returnStatements; } public function getStatementResult() : StatementResult { return $this->statementResult; } public function getExecutionEnds() : array { return $this->executionEnds; } public function getImpurePoints() : array { return $this->impurePoints; } public function returnsByRef() : bool { return $this->classMethod->byRef; } public function hasNativeReturnTypehint() : bool { return $this->classMethod->returnType !== null; } public function getMethodName() : string { return $this->classMethod->name->toString(); } public function getYieldStatements() : array { return $this->yieldStatements; } public function getClassReflection() : ClassReflection { return $this->classReflection; } public function getMethodReflection() : PhpMethodFromParserNodeReflection { return $this->methodReflection; } /** * @return Stmt[] */ public function getStatements() : array { $stmts = $this->classMethod->getStmts(); if ($stmts === null) { return []; } return $stmts; } public function isGenerator() : bool { return count($this->yieldStatements) > 0; } public function getType() : string { return 'PHPStan_Node_MethodReturnStatementsNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } originalNode = $originalNode; parent::__construct($originalNode->getAttributes()); } public function getOriginalNode() : Foreach_ { return $this->originalNode; } public function getType() : string { return 'PHPStan_Node_InForeachNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } expr = $expr; parent::__construct([]); } public function getExpr() : Expr { return $this->expr; } public function getType() : string { return 'PHPStan_Node_IssetExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } originalNode = $originalNode; $this->classReflection = $classReflection; parent::__construct($originalNode->getAttributes()); } public function getOriginalNode() : ClassLike { return $this->originalNode; } public function getClassReflection() : ClassReflection { return $this->classReflection; } public function getType() : string { return 'PHPStan_Stmt_InClassNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } name = $name; $this->originalNode = $originalNode; parent::__construct($this->originalNode->getAttributes()); } /** * @return Expr|Name */ public function getName() { return $this->name; } public function getOriginalNode() : Expr\FuncCall { return $this->originalNode; } public function getType() : string { return 'PHPStan_Node_FunctionCallableNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } cond = $cond; $this->exitPoints = $exitPoints; parent::__construct($cond->getAttributes()); } public function getCond() : Expr { return $this->cond; } /** * @return StatementExitPoint[] */ public function getExitPoints() : array { return $this->exitPoints; } public function getType() : string { return 'PHPStan_Node_ClosureReturnStatementsNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } node = $node; $this->scope = $scope; } /** * @return Node\Expr\MethodCall|StaticCall|Array_ */ public function getNode() { return $this->node; } public function getScope() : Scope { return $this->scope; } } */ public function getReturnStatements() : array; public function getStatementResult() : StatementResult; /** * @return list */ public function getExecutionEnds() : array; /** * @return ImpurePoint[] */ public function getImpurePoints() : array; public function returnsByRef() : bool; public function hasNativeReturnTypehint() : bool; /** * @return list */ public function getYieldStatements() : array; public function isGenerator() : bool; } */ private $methodCalls; /** * @var ClassReflection */ private $classReflection; /** * @param ClassMethod[] $methods * @param array $methodCalls */ public function __construct(ClassLike $class, array $methods, array $methodCalls, ClassReflection $classReflection) { $this->class = $class; $this->methods = $methods; $this->methodCalls = $methodCalls; $this->classReflection = $classReflection; parent::__construct($class->getAttributes()); } public function getClass() : ClassLike { return $this->class; } /** * @return ClassMethod[] */ public function getMethods() : array { return $this->methods; } /** * @return array */ public function getMethodCalls() : array { return $this->methodCalls; } public function getType() : string { return 'PHPStan_Node_ClassMethodsNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } public function getClassReflection() : ClassReflection { return $this->classReflection; } } originalNode = $originalNode; $this->exitPoints = $exitPoints; parent::__construct($originalNode->getAttributes()); } public function getOriginalNode() : While_ { return $this->originalNode; } /** * @return StatementExitPoint[] */ public function getExitPoints() : array { return $this->exitPoints; } public function getType() : string { return 'PHPStan_Node_BreaklessWhileLoop'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } var = $var; $this->name = $name; $this->originalNode = $originalNode; parent::__construct($originalNode->getAttributes()); } public function getVar() : Expr { return $this->var; } /** * @return Expr|Identifier */ public function getName() { return $this->name; } public function getOriginalNode() : Expr\MethodCall { return $this->originalNode; } public function getType() : string { return 'PHPStan_Node_MethodCallableNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } closureType = $closureType; parent::__construct($originalNode->getAttributes()); $this->originalNode = $originalNode; } public function getClosureType() : ClosureType { return $this->closureType; } public function getOriginalNode() : Closure { return $this->originalNode; } public function getType() : string { return 'PHPStan_Node_InClosureNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } condition = $condition; $this->arms = $arms; $this->endScope = $endScope; parent::__construct($originalNode->getAttributes()); } public function getCondition() : Expr { return $this->condition; } /** * @return MatchExpressionArm[] */ public function getArms() : array { return $this->arms; } public function getEndScope() : Scope { return $this->endScope; } public function getType() : string { return 'PHPStan_Node_MatchExpression'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } nodes = $nodes; $firstNode = $nodes[0] ?? null; parent::__construct($firstNode !== null ? $firstNode->getAttributes() : []); } /** * @return Node[] */ public function getNodes() : array { return $this->nodes; } public function getType() : string { return 'PHPStan_Node_FileNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } originalNode = $originalNode; $this->rightScope = $rightScope; parent::__construct($originalNode->getAttributes()); } /** * @return BooleanAnd|LogicalAnd */ public function getOriginalNode() { return $this->originalNode; } public function getRightScope() : Scope { return $this->rightScope; } public function getType() : string { return 'PHPStan_Node_BooleanAndNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } */ private $propertyUsages = []; /** @var Node\Stmt\ClassConst[] */ private $constants = []; /** @var ClassConstantFetch[] */ private $constantFetches = []; /** @var array */ private $returnStatementNodes = []; /** @var list */ private $propertyAssigns = []; /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function __construct(ClassReflection $classReflection, callable $nodeCallback) { $this->classReflection = $classReflection; $this->nodeCallback = $nodeCallback; } /** * @return ClassPropertyNode[] */ public function getProperties() : array { return $this->properties; } /** * @return ClassMethod[] */ public function getMethods() : array { return $this->methods; } /** * @return Method\MethodCall[] */ public function getMethodCalls() : array { return $this->methodCalls; } /** * @return array */ public function getPropertyUsages() : array { return $this->propertyUsages; } /** * @return Node\Stmt\ClassConst[] */ public function getConstants() : array { return $this->constants; } /** * @return ClassConstantFetch[] */ public function getConstantFetches() : array { return $this->constantFetches; } /** * @return array */ public function getReturnStatementsNodes() : array { return $this->returnStatementNodes; } /** * @return list */ public function getPropertyAssigns() : array { return $this->propertyAssigns; } public function __invoke(Node $node, Scope $scope) : void { $nodeCallback = $this->nodeCallback; $nodeCallback($node, $scope); $this->gatherNodes($node, $scope); } private function gatherNodes(Node $node, Scope $scope) : void { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } if ($scope->getClassReflection()->getName() !== $this->classReflection->getName()) { return; } if ($node instanceof \PHPStan\Node\ClassPropertyNode) { $this->properties[] = $node; if ($node->isPromoted()) { $this->propertyUsages[] = new PropertyWrite(new PropertyFetch(new Expr\Variable('this'), new Identifier($node->getName())), $scope, \true); } return; } if ($node instanceof Node\Stmt\ClassMethod) { $this->methods[] = new \PHPStan\Node\ClassMethod($node, $scope->isInTrait()); return; } if ($node instanceof Node\Stmt\ClassConst) { $this->constants[] = $node; return; } if ($node instanceof MethodCall || $node instanceof StaticCall) { $this->methodCalls[] = new \PHPStan\Node\Method\MethodCall($node, $scope); if ($node instanceof StaticCall && $node->name instanceof Identifier && $node->name->toLowerString() === '__construct') { $this->tryToApplyPropertyWritesFromAncestorConstructor($node, $scope); } return; } if ($node instanceof \PHPStan\Node\MethodCallableNode || $node instanceof \PHPStan\Node\StaticMethodCallableNode) { $this->methodCalls[] = new \PHPStan\Node\Method\MethodCall($node->getOriginalNode(), $scope); return; } if ($node instanceof \PHPStan\Node\MethodReturnStatementsNode) { $this->returnStatementNodes[strtolower($node->getMethodName())] = $node; return; } if ($node instanceof Expr\FuncCall && $node->name instanceof Node\Name && in_array($node->name->toLowerString(), self::PROPERTY_ENUMERATING_FUNCTIONS, \true)) { $this->tryToApplyPropertyReads($node, $scope); return; } if ($node instanceof Array_ && count($node->items) === 2) { $this->methodCalls[] = new \PHPStan\Node\Method\MethodCall($node, $scope); return; } if ($node instanceof Expr\ClassConstFetch) { $this->constantFetches[] = new ClassConstantFetch($node, $scope); return; } if ($node instanceof \PHPStan\Node\PropertyAssignNode) { $this->propertyUsages[] = new PropertyWrite($node->getPropertyFetch(), $scope, \false); $this->propertyAssigns[] = new PropertyAssign($node, $scope); return; } if (!$node instanceof Expr) { return; } if ($node instanceof Expr\AssignOp\Coalesce) { $this->gatherNodes($node->var, $scope); return; } if ($node instanceof Expr\AssignRef) { if (!$node->expr instanceof PropertyFetch && !$node->expr instanceof StaticPropertyFetch) { $this->gatherNodes($node->expr, $scope); return; } $this->propertyUsages[] = new PropertyRead($node->expr, $scope); $this->propertyUsages[] = new PropertyWrite($node->expr, $scope, \false); return; } if ($node instanceof Node\Scalar\EncapsedStringPart) { return; } if ($node instanceof \PHPStan\Node\FunctionCallableNode) { $node = $node->getOriginalNode(); } elseif ($node instanceof \PHPStan\Node\InstantiationCallableNode) { $node = $node->getOriginalNode(); } $inAssign = $scope->isInExpressionAssign($node); if ($inAssign) { return; } while ($node instanceof ArrayDimFetch) { $node = $node->var; } if (!$node instanceof PropertyFetch && !$node instanceof StaticPropertyFetch) { return; } $this->propertyUsages[] = new PropertyRead($node, $scope); } private function tryToApplyPropertyReads(Expr\FuncCall $node, Scope $scope) : void { $args = $node->getArgs(); if (count($args) === 0) { return; } $firstArgValue = $args[0]->value; if (TypeUtils::findThisType($scope->getType($firstArgValue)) === null) { return; } $classProperties = $this->classReflection->getNativeReflection()->getProperties(); foreach ($classProperties as $property) { if ($property->isStatic()) { continue; } $this->propertyUsages[] = new PropertyRead(new PropertyFetch(new Expr\Variable('this'), new Identifier($property->getName())), $scope); } } private function tryToApplyPropertyWritesFromAncestorConstructor(StaticCall $ancestorConstructorCall, Scope $scope) : void { if (!$ancestorConstructorCall->class instanceof Node\Name) { return; } $calledOnType = $scope->resolveTypeByName($ancestorConstructorCall->class); if ($calledOnType->getClassReflection() === null || TypeUtils::findThisType($calledOnType) === null) { return; } $classReflection = $calledOnType->getClassReflection()->getNativeReflection(); foreach ($classReflection->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED) as $property) { if (!$property->isPromoted() || $property->getDeclaringClass()->getName() !== $classReflection->getName()) { continue; } $this->propertyUsages[] = new PropertyWrite(new PropertyFetch(new Expr\Variable('this'), new Identifier($property->getName()), $ancestorConstructorCall->getAttributes()), $scope, \false); } } } */ private $returnStatements; /** * @var list */ private $yieldStatements; /** * @var StatementResult */ private $statementResult; /** * @var list */ private $executionEnds; /** * @var ImpurePoint[] */ private $impurePoints; /** * @var Node\Expr\Closure */ private $closureExpr; /** * @param list $returnStatements * @param list $yieldStatements * @param list $executionEnds * @param ImpurePoint[] $impurePoints */ public function __construct(Closure $closureExpr, array $returnStatements, array $yieldStatements, StatementResult $statementResult, array $executionEnds, array $impurePoints) { $this->returnStatements = $returnStatements; $this->yieldStatements = $yieldStatements; $this->statementResult = $statementResult; $this->executionEnds = $executionEnds; $this->impurePoints = $impurePoints; parent::__construct($closureExpr->getAttributes()); $this->closureExpr = $closureExpr; } public function getClosureExpr() : Closure { return $this->closureExpr; } public function hasNativeReturnTypehint() : bool { return $this->closureExpr->returnType !== null; } public function getReturnStatements() : array { return $this->returnStatements; } public function getExecutionEnds() : array { return $this->executionEnds; } public function getImpurePoints() : array { return $this->impurePoints; } public function getYieldStatements() : array { return $this->yieldStatements; } public function isGenerator() : bool { return count($this->yieldStatements) > 0; } public function getStatementResult() : StatementResult { return $this->statementResult; } public function returnsByRef() : bool { return $this->closureExpr->byRef; } public function getType() : string { return 'PHPStan_Node_ClosureReturnStatementsNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } varTag = $varTag; $this->expr = $expr; parent::__construct($expr->getAttributes()); } public function getVarTag() : VarTag { return $this->varTag; } public function getExpr() : Expr { return $this->expr; } public function getType() : string { return 'PHPStan_Node_VarTagChangedExpressionType'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } originalStatement = $originalStatement; parent::__construct($originalStatement->getAttributes()); } public function getOriginalStatement() : Stmt { return $this->originalStatement; } public function getType() : string { return 'PHPStan_Stmt_UnreachableStatementNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } originalNode = $originalNode; $this->rightScope = $rightScope; parent::__construct($originalNode->getAttributes()); } /** * @return BooleanOr|LogicalOr */ public function getOriginalNode() { return $this->originalNode; } public function getRightScope() : Scope { return $this->rightScope; } public function getType() : string { return 'PHPStan_Node_BooleanOrNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } itemNodes = $itemNodes; parent::__construct($originalNode->getAttributes()); } /** * @return LiteralArrayItem[] */ public function getItemNodes() : array { return $this->itemNodes; } public function getType() : string { return 'PHPStan_Node_LiteralArray'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } var = $var; $this->dim = $dim; parent::__construct([]); } public function getVar() : Expr { return $this->var; } public function getDim() : Expr { return $this->dim; } public function getType() : string { return 'PHPStan_Node_UnsetOffsetExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } var = $var; $this->dim = $dim; $this->value = $value; parent::__construct([]); } public function getVar() : Expr { return $this->var; } public function getDim() : Expr { return $this->dim; } public function getValue() : Expr { return $this->value; } public function getType() : string { return 'PHPStan_Node_SetExistingOffsetValueTypeExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } var = $var; $this->dim = $dim; parent::__construct([]); } public function getVar() : Expr { return $this->var; } public function getDim() : Expr { return $this->dim; } public function getType() : string { return 'PHPStan_Node_ExistingArrayDimFetch'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } expr = $expr; $this->type = $type; $this->nativeType = $nativeType; parent::__construct([]); } public function getExpr() : Expr { return $this->expr; } public function getExprType() : Type { return $this->type; } public function getNativeExprType() : Type { return $this->nativeType; } public function getType() : string { return 'PHPStan_Node_AlwaysRememberedExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return ['expr']; } } exprType = $exprType; parent::__construct(); } public function getExprType() : Type { return $this->exprType; } public function getType() : string { return 'PHPStan_Node_TypeExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } var = $var; $this->dim = $dim; parent::__construct([]); } public function getVar() : Expr { return $this->var; } public function getDim() : Expr { return $this->dim; } public function getType() : string { return 'PHPStan_Node_GetOffsetValueTypeExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } propertyName = $propertyName; parent::__construct([]); } public function getPropertyName() : string { return $this->propertyName; } public function getType() : string { return 'PHPStan_Node_PropertyInitializationExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } variableName = $variableName; parent::__construct([]); } public function getVariableName() : string { return $this->variableName; } public function getType() : string { return 'PHPStan_Node_ParameterVariableOriginalValueExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } var = $var; $this->dim = $dim; $this->value = $value; parent::__construct([]); } public function getVar() : Expr { return $this->var; } public function getDim() : ?Expr { return $this->dim; } public function getValue() : Expr { return $this->value; } public function getType() : string { return 'PHPStan_Node_SetOffsetValueTypeExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } expr = $expr; parent::__construct([]); } public function getExpr() : Expr { return $this->expr; } public function getType() : string { return 'PHPStan_Node_GetIterableValueTypeExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } expr = $expr; parent::__construct([]); } public function getExpr() : Expr { return $this->expr; } public function getType() : string { return 'PHPStan_Node_GetIterableKeyTypeExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } propertyFetch = $propertyFetch; parent::__construct([]); } /** * @return Expr\PropertyFetch|Expr\StaticPropertyFetch */ public function getPropertyFetch() { return $this->propertyFetch; } public function getType() : string { return 'PHPStan_Node_OriginalPropertyTypeExpr'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } finallyExitPoints = $finallyExitPoints; $this->tryCatchExitPoints = $tryCatchExitPoints; parent::__construct([]); } /** * @return StatementExitPoint[] */ public function getFinallyExitPoints() : array { return $this->finallyExitPoints; } /** * @return StatementExitPoint[] */ public function getTryCatchExitPoints() : array { return $this->tryCatchExitPoints; } public function getType() : string { return 'PHPStan_Node_FinallyExitPointsNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } scope = $scope; $this->returnNode = $returnNode; } public function getScope() : Scope { return $this->scope; } public function getReturnNode() : Return_ { return $this->returnNode; } } class = $class; $this->constants = $constants; $this->fetches = $fetches; $this->classReflection = $classReflection; parent::__construct($class->getAttributes()); } public function getClass() : ClassLike { return $this->class; } /** * @return ClassConst[] */ public function getConstants() : array { return $this->constants; } /** * @return ClassConstantFetch[] */ public function getFetches() : array { return $this->fetches; } public function getType() : string { return 'PHPStan_Node_ClassConstantsNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } public function getClassReflection() : ClassReflection { return $this->classReflection; } } originalNode = $originalNode; $this->traitReflection = $traitReflection; $this->implementingClassReflection = $implementingClassReflection; parent::__construct($originalNode->getAttributes()); } public function getOriginalNode() : Node\Stmt\Trait_ { return $this->originalNode; } public function getTraitReflection() : ClassReflection { return $this->traitReflection; } public function getImplementingClassReflection() : ClassReflection { return $this->implementingClassReflection; } public function getType() : string { return 'PHPStan_Stmt_InTraitNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } variable = $variable; $this->assignedExpr = $assignedExpr; $this->assignOp = $assignOp; parent::__construct($variable->getAttributes()); } public function getVariable() : Expr\Variable { return $this->variable; } public function getAssignedExpr() : Expr { return $this->assignedExpr; } public function isAssignOp() : bool { return $this->assignOp; } public function getType() : string { return 'PHPStan_Node_VariableAssignNodeNode'; } /** * @return string[] */ public function getSubNodeNames() : array { return []; } } \true]); } protected function pPHPStan_Node_TypeExpr(TypeExpr $expr) : string { return sprintf('__phpstanType(%s)', $expr->getExprType()->describe(VerbosityLevel::precise())); } protected function pPHPStan_Node_GetOffsetValueTypeExpr(GetOffsetValueTypeExpr $expr) : string { return sprintf('__phpstanGetOffsetValueType(%s, %s)', $this->p($expr->getVar()), $this->p($expr->getDim())); } protected function pPHPStan_Node_UnsetOffsetExpr(UnsetOffsetExpr $expr) : string { return sprintf('__phpstanUnsetOffset(%s, %s)', $this->p($expr->getVar()), $this->p($expr->getDim())); } protected function pPHPStan_Node_GetIterableValueTypeExpr(GetIterableValueTypeExpr $expr) : string { return sprintf('__phpstanGetIterableValueType(%s)', $this->p($expr->getExpr())); } protected function pPHPStan_Node_GetIterableKeyTypeExpr(GetIterableKeyTypeExpr $expr) : string { return sprintf('__phpstanGetIterableKeyType(%s)', $this->p($expr->getExpr())); } protected function pPHPStan_Node_ExistingArrayDimFetch(ExistingArrayDimFetch $expr) : string { return sprintf('__phpstanExistingArrayDimFetch(%s, %s)', $this->p($expr->getVar()), $this->p($expr->getDim())); } protected function pPHPStan_Node_OriginalPropertyTypeExpr(OriginalPropertyTypeExpr $expr) : string { return sprintf('__phpstanOriginalPropertyType(%s)', $this->p($expr->getPropertyFetch())); } protected function pPHPStan_Node_SetOffsetValueTypeExpr(SetOffsetValueTypeExpr $expr) : string { return sprintf('__phpstanSetOffsetValueType(%s, %s, %s)', $this->p($expr->getVar()), $expr->getDim() !== null ? $this->p($expr->getDim()) : 'null', $this->p($expr->getValue())); } protected function pPHPStan_Node_SetExistingOffsetValueTypeExpr(SetExistingOffsetValueTypeExpr $expr) : string { return sprintf('__phpstanSetExistingOffsetValueType(%s, %s, %s)', $this->p($expr->getVar()), $this->p($expr->getDim()), $this->p($expr->getValue())); } protected function pPHPStan_Node_AlwaysRememberedExpr(AlwaysRememberedExpr $expr) : string { return sprintf('__phpstanRembered(%s)', $this->p($expr->getExpr())); } protected function pPHPStan_Node_PropertyInitializationExpr(PropertyInitializationExpr $expr) : string { return sprintf('__phpstanPropertyInitialization(%s)', $expr->getPropertyName()); } protected function pPHPStan_Node_ParameterVariableOriginalValueExpr(ParameterVariableOriginalValueExpr $expr) : string { return sprintf('__phpstanParameterVariableOriginalValue(%s)', $expr->getVariableName()); } protected function pPHPStan_Node_IssetExpr(IssetExpr $expr) : string { return sprintf('__phpstanIssetExpr(%s)', $this->p($expr->getExpr())); } } printer = $printer; } public function printExpr(Expr $expr) : string { /** @var string|null $exprString */ $exprString = $expr->getAttribute('phpstan_cache_printer'); if ($exprString === null) { $exprString = $this->printer->prettyPrintExpr($expr); $expr->setAttribute('phpstan_cache_printer', $exprString); } return $exprString; } } type); } if ($type instanceof Node\UnionType) { return implode('|', array_map(static function ($innerType) : string { $printedType = self::printType($innerType); if ($printedType === null) { throw new ShouldNotHappenException(); } return $printedType; }, $type->types)); } if ($type instanceof Node\IntersectionType) { return implode('&', array_map(static function ($innerType) : string { $printedType = self::printType($innerType); if ($printedType === null) { throw new ShouldNotHappenException(); } return $printedType; }, $type->types)); } if ($type instanceof Node\Identifier || $type instanceof Node\Name) { return $type->toString(); } throw new ShouldNotHappenException(); } } count !== null) { return $this->count; } try { $this->count = (new FidryCpuCoreCounter())->getCount(); } catch (NumberOfCpuCoreNotFound $e) { $this->count = 1; } return $this->count; } } getOption('memory-limit') === null) { $processCommandArray[] = '-d'; $processCommandArray[] = 'memory_limit=' . ini_get('memory_limit'); } foreach ([$mainScript, $commandName] as $arg) { $processCommandArray[] = escapeshellarg($arg); } if ($projectConfigFile !== null) { $processCommandArray[] = '--configuration'; $processCommandArray[] = escapeshellarg($projectConfigFile); } $options = [AnalyseCommand::OPTION_LEVEL, 'autoload-file', 'memory-limit', 'xdebug', 'verbose']; foreach ($options as $optionName) { /** @var bool|string|null $optionValue */ $optionValue = $input->getOption($optionName); if (is_bool($optionValue)) { if ($optionValue === \true) { $processCommandArray[] = sprintf('--%s', $optionName); } continue; } if ($optionValue === null) { continue; } $processCommandArray[] = sprintf('--%s=%s', $optionName, escapeshellarg($optionValue)); } $processCommandArray = array_merge($processCommandArray, $additionalItems); $processCommandArray[] = '--'; /** @var string[] $paths */ $paths = $input->getArgument('paths'); foreach ($paths as $path) { $processCommandArray[] = escapeshellarg($path); } return implode(' ', $processCommandArray); } } */ private $deferred; /** * @var ?Process */ private $process = null; /** * @var bool */ private $canceled = \false; public function __construct(LoopInterface $loop, string $name, string $command) { $this->loop = $loop; $this->name = $name; $this->command = $command; $this->deferred = new Deferred(); } public function getName() : string { return $this->name; } /** * @return PromiseInterface */ public function run() : PromiseInterface { $tmpStdOutResource = tmpfile(); if ($tmpStdOutResource === \false) { throw new ShouldNotHappenException('Failed creating temp file for stdout.'); } $tmpStdErrResource = tmpfile(); if ($tmpStdErrResource === \false) { throw new ShouldNotHappenException('Failed creating temp file for stderr.'); } $this->process = new Process($this->command, null, null, [1 => $tmpStdOutResource, 2 => $tmpStdErrResource]); $this->process->start($this->loop); $this->process->on('exit', function ($exitCode) use($tmpStdOutResource, $tmpStdErrResource) : void { if ($this->canceled) { fclose($tmpStdOutResource); fclose($tmpStdErrResource); return; } rewind($tmpStdOutResource); $stdOut = stream_get_contents($tmpStdOutResource); fclose($tmpStdOutResource); rewind($tmpStdErrResource); $stdErr = stream_get_contents($tmpStdErrResource); fclose($tmpStdErrResource); if ($exitCode === null) { $this->deferred->reject(new \PHPStan\Process\ProcessCrashedException($stdOut . $stdErr)); return; } if ($exitCode === 0) { if ($stdOut === \false) { $stdOut = ''; } $this->deferred->resolve($stdOut); return; } $this->deferred->reject(new \PHPStan\Process\ProcessCrashedException($stdOut . $stdErr)); }); return $this->deferred->promise(); } public function cancel() : void { if ($this->process === null) { throw new ShouldNotHappenException('Cancelling process before running'); } $this->canceled = \true; $this->process->terminate(); $this->deferred->reject(new \PHPStan\Process\ProcessCanceledException()); } } */ public function getClassPrefixes() : array; } reflectionProvider = $reflectionProvider; $this->functionCallParametersCheck = $functionCallParametersCheck; $this->classCheck = $classCheck; $this->deprecationRulesInstalled = $deprecationRulesInstalled; } /** * @param AttributeGroup[] $attrGroups * @param int-mask-of $requiredTarget * @return list */ public function check(Scope $scope, array $attrGroups, int $requiredTarget, string $targetName) : array { $errors = []; $alreadyPresent = []; foreach ($attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attribute) { $name = $attribute->name->toString(); if (!$this->reflectionProvider->hasClass($name)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Attribute class %s does not exist.', $name))->line($attribute->getStartLine())->identifier('attribute.notFound')->build(); continue; } $attributeClass = $this->reflectionProvider->getClass($name); if (!$attributeClass->isAttributeClass()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('%s %s is not an Attribute class.', $attributeClass->getClassTypeDescription(), $attributeClass->getDisplayName()))->identifier('attribute.notAttribute')->line($attribute->getStartLine())->build(); continue; } if ($attributeClass->isAbstract()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Attribute class %s is abstract.', $name))->identifier('attribute.abstract')->line($attribute->getStartLine())->build(); } foreach ($this->classCheck->checkClassNames([new \PHPStan\Rules\ClassNameNodePair($name, $attribute)]) as $caseSensitivityError) { $errors[] = $caseSensitivityError; } $flags = $attributeClass->getAttributeClassFlags(); if (($flags & $requiredTarget) === 0) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Attribute class %s does not have the %s target.', $name, $targetName))->identifier('attribute.target')->line($attribute->getStartLine())->build(); } if (($flags & Attribute::IS_REPEATABLE) === 0) { $loweredName = strtolower($name); if (array_key_exists($loweredName, $alreadyPresent)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Attribute class %s is not repeatable but is already present above the %s.', $name, $targetName))->identifier('attribute.nonRepeatable')->line($attribute->getStartLine())->build(); } $alreadyPresent[$loweredName] = \true; } if ($this->deprecationRulesInstalled && $attributeClass->isDeprecated()) { if ($attributeClass->getDeprecatedDescription() !== null) { $deprecatedError = sprintf('Attribute class %s is deprecated: %s', $name, $attributeClass->getDeprecatedDescription()); } else { $deprecatedError = sprintf('Attribute class %s is deprecated.', $name); } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($deprecatedError)->identifier('attribute.deprecated')->line($attribute->getStartLine())->build(); } if (!$attributeClass->hasConstructor()) { if (count($attribute->args) > 0) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Attribute class %s does not have a constructor and must be instantiated without any parameters.', $name))->identifier('attribute.noConstructor')->line($attribute->getStartLine())->build(); } continue; } $attributeConstructor = $attributeClass->getConstructor(); if (!$attributeConstructor->isPublic()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Constructor of attribute class %s is not public.', $name))->identifier('attribute.constructorNotPublic')->line($attribute->getStartLine())->build(); } $attributeClassName = SprintfHelper::escapeFormatString($attributeClass->getDisplayName()); $nodeAttributes = $attribute->getAttributes(); $nodeAttributes['isAttribute'] = \true; $parameterErrors = $this->functionCallParametersCheck->check(ParametersAcceptorSelector::selectFromArgs($scope, $attribute->args, $attributeConstructor->getVariants(), $attributeConstructor->getNamedArgumentsVariants()), $scope, $attributeConstructor->getDeclaringClass()->isBuiltin(), new New_($attribute->name, $attribute->args, $nodeAttributes), [ 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, %d required.', 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, %d required.', 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, at least %d required.', 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, at least %d required.', 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, %d-%d required.', 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, %d-%d required.', 'Parameter %s of attribute class ' . $attributeClassName . ' constructor expects %s, %s given.', '', // constructor does not have a return type 'Parameter %s of attribute class ' . $attributeClassName . ' constructor is passed by reference, so it expects variables only', 'Unable to resolve the template type %s in instantiation of attribute class ' . $attributeClassName, 'Missing parameter $%s in call to ' . $attributeClassName . ' constructor.', 'Unknown parameter $%s in call to ' . $attributeClassName . ' constructor.', 'Return type of call to ' . $attributeClassName . ' constructor contains unresolvable type.', 'Parameter %s of attribute class ' . $attributeClassName . ' constructor contains unresolvable type.', 'Attribute class ' . $attributeClassName . ' constructor invoked with %s, but it\'s not allowed because of @no-named-arguments.', ], 'attribute', $attributeConstructor->acceptsNamedArguments()); foreach ($parameterErrors as $error) { $errors[] = $error; } } } return $errors; } } */ final class ApiInterfaceExtendsRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper, ReflectionProvider $reflectionProvider) { $this->apiRuleHelper = $apiRuleHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Interface_::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; foreach ($node->extends as $extends) { $errors = array_merge($errors, $this->checkName($scope, $extends)); } return $errors; } /** * @return list */ private function checkName(Scope $scope, Node\Name $name) : array { $extendedInterface = (string) $name; if (!$this->reflectionProvider->hasClass($extendedInterface)) { return []; } $extendedInterfaceReflection = $this->reflectionProvider->getClass($extendedInterface); if (!$this->apiRuleHelper->isPhpStanCode($scope, $extendedInterfaceReflection->getName(), $extendedInterfaceReflection->getFileName())) { return []; } $ruleError = RuleErrorBuilder::message(sprintf('Extending %s is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', $extendedInterfaceReflection->getDisplayName()))->identifier('phpstanApi.interface')->tip(sprintf("If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'))->build(); if (in_array($extendedInterfaceReflection->getName(), \PHPStan\Rules\Api\BcUncoveredInterface::CLASSES, \true)) { return [$ruleError]; } $docBlock = $extendedInterfaceReflection->getResolvedPhpDoc(); if ($docBlock === null) { return [$ruleError]; } foreach ($docBlock->getPhpDocNodes() as $phpDocNode) { $apiTags = $phpDocNode->getTagsByName('@api'); if (count($apiTags) > 0) { return []; } } return [$ruleError]; } } */ final class ApiClassExtendsRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper, ReflectionProvider $reflectionProvider) { $this->apiRuleHelper = $apiRuleHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Class_::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->extends === null) { return []; } $extendedClassName = (string) $node->extends; if (!$this->reflectionProvider->hasClass($extendedClassName)) { return []; } $extendedClassReflection = $this->reflectionProvider->getClass($extendedClassName); if (!$this->apiRuleHelper->isPhpStanCode($scope, $extendedClassReflection->getName(), $extendedClassReflection->getFileName())) { return []; } if ($extendedClassReflection->getName() === MutatingScope::class) { return []; } $ruleError = RuleErrorBuilder::message(sprintf('Extending %s is not covered by backward compatibility promise. The class might change in a minor PHPStan version.', $extendedClassReflection->getDisplayName()))->identifier('phpstanApi.class')->tip(sprintf("If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'))->build(); $docBlock = $extendedClassReflection->getResolvedPhpDoc(); if ($docBlock === null) { return [$ruleError]; } foreach ($docBlock->getPhpDocNodes() as $phpDocNode) { $apiTags = $phpDocNode->getTagsByName('@api'); if (count($apiTags) > 0) { return []; } } return [$ruleError]; } } */ final class RuntimeReflectionInstantiationRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Expr\New_::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->class instanceof Node\Name) { return []; } $className = $scope->resolveName($node->class); if (!$this->reflectionProvider->hasClass($className)) { return []; } $classReflection = $this->reflectionProvider->getClass($className); if (!in_array($classReflection->getName(), [ReflectionMethod::class, ReflectionClass::class, ReflectionClassConstant::class, 'ReflectionEnum', 'ReflectionEnumBackedCase', ReflectionZendExtension::class, ReflectionExtension::class, ReflectionFunction::class, ReflectionObject::class, ReflectionParameter::class, ReflectionProperty::class, ReflectionGenerator::class, 'ReflectionFiber'], \true)) { return []; } if (!$scope->isInClass()) { return []; } $scopeClassReflection = $scope->getClassReflection(); $hasPhpStanInterface = \false; foreach (array_keys($scopeClassReflection->getInterfaces()) as $interfaceName) { if (!str_starts_with($interfaceName, 'PHPStan\\')) { continue; } $hasPhpStanInterface = \true; } if (!$hasPhpStanInterface) { return []; } return [RuleErrorBuilder::message(sprintf('Creating new %s is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine. Use objects retrieved from ReflectionProvider instead.', $classReflection->getName()))->identifier('phpstanApi.runtimeReflection')->build()]; } } */ final class ApiClassConstFetchRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper, ReflectionProvider $reflectionProvider) { $this->apiRuleHelper = $apiRuleHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Expr\ClassConstFetch::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } if (!$node->class instanceof Node\Name) { return []; } $className = $scope->resolveName($node->class); if (!$this->reflectionProvider->hasClass($className)) { return []; } $classReflection = $this->reflectionProvider->getClass($className); if (!$this->apiRuleHelper->isPhpStanCode($scope, $classReflection->getName(), $classReflection->getFileName())) { return []; } $ruleError = RuleErrorBuilder::message(sprintf('Accessing %s::%s is not covered by backward compatibility promise. The class might change in a minor PHPStan version.', $classReflection->getDisplayName(), $node->name->toString()))->identifier('phpstanApi.classConstant')->tip(sprintf("If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'))->build(); $docBlock = $classReflection->getResolvedPhpDoc(); if ($docBlock !== null) { foreach ($docBlock->getPhpDocNodes() as $phpDocNode) { $apiTags = $phpDocNode->getTagsByName('@api'); if (count($apiTags) > 0) { return []; } } } if ($node->name->toLowerString() === 'class') { foreach ($classReflection->getNativeReflection()->getMethods() as $methodReflection) { $methodDocComment = $methodReflection->getDocComment(); if ($methodDocComment === \false) { continue; } if (!str_contains($methodDocComment, '@api')) { continue; } return []; } } return [$ruleError]; } } */ final class ApiTraitUseRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper, ReflectionProvider $reflectionProvider) { $this->apiRuleHelper = $apiRuleHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\TraitUse::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; $tip = sprintf("If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'); foreach ($node->traits as $traitName) { $traitName = $traitName->toString(); if (!$this->reflectionProvider->hasClass($traitName)) { continue; } $traitReflection = $this->reflectionProvider->getClass($traitName); if (!$this->apiRuleHelper->isPhpStanCode($scope, $traitReflection->getName(), $traitReflection->getFileName())) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Using %s is not covered by backward compatibility promise. The trait might change in a minor PHPStan version.', $traitReflection->getDisplayName()))->identifier('phpstanApi.trait')->tip($tip)->build(); } return $errors; } } */ final class NodeConnectingVisitorAttributesRule implements Rule { /** * @var Container */ private $container; public function __construct(Container $container) { $this->container = $container; } public function getNodeType() : string { return MethodCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } if ($node->name->toLowerString() !== 'getattribute') { return []; } $calledOnType = $scope->getType($node->var); if (!(new ObjectType(Node::class))->isSuperTypeOf($calledOnType)->yes()) { return []; } $args = $node->getArgs(); if (!isset($args[0])) { return []; } $argType = $scope->getType($args[0]->value); if (!$argType instanceof ConstantStringType) { return []; } if (!in_array($argType->getValue(), ['parent', 'previous', 'next'], \true)) { return []; } if (!$scope->isInClass()) { return []; } $classReflection = $scope->getClassReflection(); $hasPhpStanInterface = \false; foreach (array_keys($classReflection->getInterfaces()) as $interfaceName) { if (!str_starts_with($interfaceName, 'PHPStan\\')) { continue; } $hasPhpStanInterface = \true; } if (!$hasPhpStanInterface) { return []; } $isVisitorRegistered = \false; foreach ($this->container->getServicesByTag(RichParser::VISITOR_SERVICE_TAG) as $service) { if (get_class($service) !== NodeConnectingVisitor::class) { continue; } $isVisitorRegistered = \true; break; } if ($isVisitorRegistered) { return []; } return [RuleErrorBuilder::message(sprintf('Node attribute \'%s\' is no longer available.', $argType->getValue()))->identifier('phpParser.nodeConnectingAttribute')->tip('See: https://phpstan.org/blog/preprocessing-ast-for-custom-rules')->build()]; } } */ final class PhpStanNamespaceIn3rdPartyPackageRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper) { $this->apiRuleHelper = $apiRuleHelper; } public function getNodeType() : string { return Node\Stmt\Namespace_::class; } public function processNode(Node $node, Scope $scope) : array { $namespace = null; if ($node->name !== null) { $namespace = $node->name->toString(); } if ($namespace === null || !$this->apiRuleHelper->isPhpStanName($namespace)) { return []; } $composerJson = $this->findComposerJsonContents(dirname($scope->getFile())); if ($composerJson === null) { return []; } $packageName = $composerJson['name'] ?? null; if ($packageName !== null && str_starts_with($packageName, 'phpstan/')) { return []; } return [RuleErrorBuilder::message('Declaring PHPStan namespace is not allowed in 3rd party packages.')->identifier('phpstanApi.phpstanNamespace')->tip("See:\n https://phpstan.org/developing-extensions/backward-compatibility-promise")->build()]; } /** * @return mixed[]|null */ private function findComposerJsonContents(string $fromDirectory) : ?array { if (!is_dir($fromDirectory)) { return null; } $composerJsonPath = $fromDirectory . '/composer.json'; if (!is_file($composerJsonPath)) { $dirName = dirname($fromDirectory); if ($dirName !== $fromDirectory) { return $this->findComposerJsonContents($dirName); } return null; } try { return Json::decode(FileReader::read($composerJsonPath), Json::FORCE_ARRAY); } catch (JsonException $e) { return null; } catch (CouldNotReadFileException $e) { return null; } } } */ final class ApiMethodCallRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper) { $this->apiRuleHelper = $apiRuleHelper; } public function getNodeType() : string { return Node\Expr\MethodCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } $methodReflection = $scope->getMethodReflection($scope->getType($node->var), $node->name->toString()); if ($methodReflection === null) { return []; } $declaringClass = $methodReflection->getDeclaringClass(); if (!$this->apiRuleHelper->isPhpStanCode($scope, $declaringClass->getName(), $declaringClass->getFileName())) { return []; } if ($this->isCovered($methodReflection)) { return []; } $ruleError = RuleErrorBuilder::message(sprintf('Calling %s::%s() is not covered by backward compatibility promise. The method might change in a minor PHPStan version.', $declaringClass->getDisplayName(), $methodReflection->getName()))->identifier('phpstanApi.method')->tip(sprintf("If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'))->build(); return [$ruleError]; } private function isCovered(MethodReflection $methodReflection) : bool { $declaringClass = $methodReflection->getDeclaringClass(); $classDocBlock = $declaringClass->getResolvedPhpDoc(); if ($classDocBlock !== null) { foreach ($classDocBlock->getPhpDocNodes() as $phpDocNode) { $apiTags = $phpDocNode->getTagsByName('@api'); if (count($apiTags) > 0) { return \true; } } } $methodDocComment = $methodReflection->getDocComment(); if ($methodDocComment === null) { return \false; } return str_contains($methodDocComment, '@api'); } } */ final class ApiStaticCallRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper, ReflectionProvider $reflectionProvider) { $this->apiRuleHelper = $apiRuleHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Expr\StaticCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } if (!$node->class instanceof Node\Name) { return []; } $className = $scope->resolveName($node->class); if (!$this->reflectionProvider->hasClass($className)) { return []; } $classReflection = $this->reflectionProvider->getClass($className); $methodName = $node->name->toString(); if (!$classReflection->hasNativeMethod($methodName)) { return []; } $methodReflection = $classReflection->getNativeMethod($methodName); $declaringClass = $methodReflection->getDeclaringClass(); if (!$this->apiRuleHelper->isPhpStanCode($scope, $declaringClass->getName(), $declaringClass->getFileName())) { return []; } if ($this->isCovered($methodReflection)) { return []; } $ruleError = RuleErrorBuilder::message(sprintf('Calling %s::%s() is not covered by backward compatibility promise. The method might change in a minor PHPStan version.', $declaringClass->getDisplayName(), $methodReflection->getName()))->identifier('phpstanApi.method')->tip(sprintf("If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'))->build(); return [$ruleError]; } private function isCovered(MethodReflection $methodReflection) : bool { $declaringClass = $methodReflection->getDeclaringClass(); $classDocBlock = $declaringClass->getResolvedPhpDoc(); if ($methodReflection->getName() !== '__construct' && $classDocBlock !== null) { foreach ($classDocBlock->getPhpDocNodes() as $phpDocNode) { $apiTags = $phpDocNode->getTagsByName('@api'); if (count($apiTags) > 0) { return \true; } } } $methodDocComment = $methodReflection->getDocComment(); if ($methodDocComment === null) { return \false; } return str_contains($methodDocComment, '@api'); } } */ final class ApiClassImplementsRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper, ReflectionProvider $reflectionProvider) { $this->apiRuleHelper = $apiRuleHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Class_::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; foreach ($node->implements as $implements) { $errors = array_merge($errors, $this->checkName($scope, $implements)); } return $errors; } /** * @return list */ private function checkName(Scope $scope, Node\Name $name) : array { $implementedClassName = (string) $name; if (!$this->reflectionProvider->hasClass($implementedClassName)) { return []; } $implementedClassReflection = $this->reflectionProvider->getClass($implementedClassName); if (!$this->apiRuleHelper->isPhpStanCode($scope, $implementedClassReflection->getName(), $implementedClassReflection->getFileName())) { return []; } $ruleError = RuleErrorBuilder::message(sprintf('Implementing %s is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', $implementedClassReflection->getDisplayName()))->identifier('phpstanApi.interface')->tip(sprintf("If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'))->build(); if (in_array($implementedClassReflection->getName(), \PHPStan\Rules\Api\BcUncoveredInterface::CLASSES, \true)) { return [$ruleError]; } $docBlock = $implementedClassReflection->getResolvedPhpDoc(); if ($docBlock === null) { return [$ruleError]; } foreach ($docBlock->getPhpDocNodes() as $phpDocNode) { $apiTags = $phpDocNode->getTagsByName('@api'); if (count($apiTags) > 0) { return []; } } return [$ruleError]; } } */ final class RuntimeReflectionFunctionRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Expr\FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); if (!in_array($functionReflection->getName(), ['is_a', 'is_subclass_of', 'class_parents', 'class_implements', 'class_uses'], \true)) { return []; } if (!$scope->isInClass()) { return []; } $classReflection = $scope->getClassReflection(); $hasPhpStanInterface = \false; foreach (array_keys($classReflection->getInterfaces()) as $interfaceName) { if (!str_starts_with($interfaceName, 'PHPStan\\')) { continue; } $hasPhpStanInterface = \true; } if (!$hasPhpStanInterface) { return []; } return [RuleErrorBuilder::message(sprintf('Function %s() is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine. Use objects retrieved from ReflectionProvider instead.', $functionReflection->getName()))->identifier('phpstanApi.runtimeReflection')->build()]; } } getNamespace(); if ($scopeNamespace === null) { return $this->isPhpStanName($namespace); } if ($this->isPhpStanName($scopeNamespace)) { if (!$this->isPhpStanName($namespace)) { return \false; } if ($declaringFile !== null) { $scopeFile = $scope->getFile(); $dir = dirname($scopeFile); $helper = new ParentDirectoryRelativePathHelper($dir); $pathParts = $helper->getFilenameParts($declaringFile); $directories = $this->createAbsoluteDirectories($dir, $pathParts); foreach ($directories as $directory) { if (pathinfo($directory, PATHINFO_BASENAME) === 'vendor') { return \true; } } } return \false; } return $this->isPhpStanName($namespace); } /** * @param string[] $parts * @return string[] */ private function createAbsoluteDirectories(string $currentDirectory, array $parts) : array { $directories = []; foreach ($parts as $part) { if ($part === '..') { $currentDirectory = dirname($currentDirectory); $directories[] = $currentDirectory; continue; } $currentDirectory .= '/' . $part; $directories[] = $currentDirectory; } return $directories; } public function isPhpStanName(string $namespace) : bool { if (strtolower($namespace) === 'phpstan') { return \true; } if (str_starts_with($namespace, 'PHPStan\\PhpDocParser\\')) { return \false; } if (str_starts_with($namespace, 'PHPStan\\BetterReflection\\')) { return \false; } return stripos($namespace, 'PHPStan\\') === 0; } } */ final class ApiInstanceofTypeRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var bool */ private $enabled; /** * @var bool */ private $deprecationRulesInstalled; private const MAP = [ TypeWithClassName::class => 'Type::getObjectClassNames() or Type::getObjectClassReflections()', EnumCaseObjectType::class => 'Type::getEnumCases()', ConstantArrayType::class => 'Type::getConstantArrays()', ArrayType::class => 'Type::isArray() or Type::getArrays()', ConstantStringType::class => 'Type::getConstantStrings()', StringType::class => 'Type::isString()', ClassStringType::class => 'Type::isClassStringType()', IntegerType::class => 'Type::isInteger()', FloatType::class => 'Type::isFloat()', NullType::class => 'Type::isNull()', VoidType::class => 'Type::isVoid()', BooleanType::class => 'Type::isBoolean()', ConstantBooleanType::class => 'Type::isTrue() or Type::isFalse()', CallableType::class => 'Type::isCallable() and Type::getCallableParametersAcceptors()', IterableType::class => 'Type::isIterable()', ObjectWithoutClassType::class => 'Type::isObject()', ObjectType::class => 'Type::isObject() or Type::getObjectClassNames()', GenericClassStringType::class => 'Type::isClassStringType() and Type::getClassStringObjectType()', GenericObjectType::class => null, IntersectionType::class => null, ConstantType::class => 'Type::isConstantValue() or Type::generalize()', ConstantScalarType::class => 'Type::isConstantScalarValue() or Type::getConstantScalarTypes() or Type::getConstantScalarValues()', ObjectShapeType::class => 'Type::isObject() and Type::hasProperty()', // accessory types NonEmptyArrayType::class => 'Type::isIterableAtLeastOnce()', OversizedArrayType::class => 'Type::isOversizedArray()', AccessoryArrayListType::class => 'Type::isList()', AccessoryNumericStringType::class => 'Type::isNumericString()', AccessoryLiteralStringType::class => 'Type::isLiteralString()', AccessoryLowercaseStringType::class => 'Type::isLowercaseString()', AccessoryUppercaseStringType::class => 'Type::isUppercaseString()', AccessoryNonEmptyStringType::class => 'Type::isNonEmptyString()', AccessoryNonFalsyStringType::class => 'Type::isNonFalsyString()', HasMethodType::class => 'Type::hasMethod()', HasPropertyType::class => 'Type::hasProperty()', HasOffsetType::class => 'Type::hasOffsetValueType()', AccessoryType::class => 'methods on PHPStan\\Type\\Type', ]; public function __construct(ReflectionProvider $reflectionProvider, bool $enabled, bool $deprecationRulesInstalled) { $this->reflectionProvider = $reflectionProvider; $this->enabled = $enabled; $this->deprecationRulesInstalled = $deprecationRulesInstalled; } public function getNodeType() : string { return Instanceof_::class; } public function processNode(Node $node, Scope $scope) : array { if (!$this->enabled && !$this->deprecationRulesInstalled) { return []; } if (!$node->class instanceof Node\Name) { return []; } if ($node->getAttribute(TypeTraverserInstanceofVisitor::ATTRIBUTE_NAME, \false) === \true) { return []; } $lowerMap = []; foreach (self::MAP as $className => $method) { $lowerMap[strtolower($className)] = $method; } $className = $scope->resolveName($node->class); $lowerClassName = strtolower($className); if (!array_key_exists($lowerClassName, $lowerMap)) { return []; } if ($this->reflectionProvider->hasClass($className)) { $classReflection = $this->reflectionProvider->getClass($className); if ($classReflection->isSubclassOf(AccessoryType::class)) { if ($className === $classReflection->getName()) { return []; } } } $tip = 'Learn more: https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated'; if ($lowerMap[$lowerClassName] === null) { return [RuleErrorBuilder::message(sprintf('Doing instanceof %s is error-prone and deprecated.', $className))->identifier('phpstanApi.instanceofType')->tip($tip)->build()]; } return [RuleErrorBuilder::message(sprintf('Doing instanceof %s is error-prone and deprecated. Use %s instead.', $className, $lowerMap[$lowerClassName]))->identifier('phpstanApi.instanceofType')->tip($tip)->build()]; } } */ final class ApiInstantiationRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper, ReflectionProvider $reflectionProvider) { $this->apiRuleHelper = $apiRuleHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Expr\New_::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->class instanceof Node\Name) { return []; } $className = $scope->resolveName($node->class); if (!$this->reflectionProvider->hasClass($className)) { return []; } $classReflection = $this->reflectionProvider->getClass($className); if (!$this->apiRuleHelper->isPhpStanCode($scope, $classReflection->getName(), $classReflection->getFileName())) { return []; } $ruleError = RuleErrorBuilder::message(sprintf('Creating new %s is not covered by backward compatibility promise. The class might change in a minor PHPStan version.', $classReflection->getDisplayName()))->identifier('phpstanApi.constructor')->tip(sprintf("If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'))->build(); if (!$classReflection->hasConstructor()) { return [$ruleError]; } $constructor = $classReflection->getConstructor(); $docComment = $constructor->getDocComment(); if ($docComment === null) { return [$ruleError]; } if (!str_contains($docComment, '@api')) { return [$ruleError]; } if ($constructor->getDeclaringClass()->getName() !== $classReflection->getName()) { return [$ruleError]; } return []; } } */ final class ApiInstanceofRule implements Rule { /** * @var ApiRuleHelper */ private $apiRuleHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Api\ApiRuleHelper $apiRuleHelper, ReflectionProvider $reflectionProvider) { $this->apiRuleHelper = $apiRuleHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Expr\Instanceof_::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->class instanceof Node\Name) { return []; } $className = $scope->resolveName($node->class); if (!$this->reflectionProvider->hasClass($className)) { return []; } $classReflection = $this->reflectionProvider->getClass($className); if (!$this->apiRuleHelper->isPhpStanCode($scope, $classReflection->getName(), $classReflection->getFileName())) { return []; } $ruleError = RuleErrorBuilder::message(sprintf('Asking about instanceof %s is not covered by backward compatibility promise. The %s might change in a minor PHPStan version.', $classReflection->getDisplayName(), strtolower($classReflection->getClassTypeDescription())))->identifier(sprintf('phpstanApi.%s', strtolower($classReflection->getClassTypeDescription())))->tip(sprintf("If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'))->build(); $docBlock = $classReflection->getResolvedPhpDoc(); if ($docBlock === null) { return [$ruleError]; } foreach ($docBlock->getPhpDocNodes() as $phpDocNode) { $apiTags = $phpDocNode->getTagsByName('@api'); if (count($apiTags) > 0) { return $this->processCoveredClass($node, $scope, $classReflection); } } return [$ruleError]; } /** * @return list */ private function processCoveredClass(Node\Expr\Instanceof_ $node, Scope $scope, ClassReflection $classReflection) : array { if ($classReflection->getName() === Type::class || $classReflection->isSubclassOf(Type::class)) { return []; } if ($classReflection->isInterface()) { return []; } $instanceofType = $scope->getType($node); if ($instanceofType->isTrue()->or($instanceofType->isFalse())->yes()) { return []; } $classType = new ObjectType($classReflection->getName(), null, $classReflection); $exprType = $scope->getType($node->expr); if ($exprType instanceof UnionType) { foreach ($exprType->getTypes() as $innerType) { if ($innerType->getObjectClassNames() !== [] && $classType->isSuperTypeOf($innerType)->yes()) { return []; } } } return [RuleErrorBuilder::message(sprintf('Although %s is covered by backward compatibility promise, this instanceof assumption might break because it\'s not guaranteed to always stay the same.', $classReflection->getDisplayName()))->identifier('phpstanApi.instanceofAssumption')->tip(sprintf("In case of questions how to solve this correctly, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise", 'https://github.com/phpstan/phpstan/discussions'))->build()]; } } */ final class GetTemplateTypeRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return MethodCall::class; } public function processNode(Node $node, Scope $scope) : array { $args = $node->getArgs(); if (count($args) < 2) { return []; } if (!$node->name instanceof Node\Identifier) { return []; } if ($node->name->toLowerString() !== 'gettemplatetype') { return []; } $calledOnType = $scope->getType($node->var); $methodReflection = $scope->getMethodReflection($calledOnType, $node->name->toString()); if ($methodReflection === null) { return []; } if (!$methodReflection->getDeclaringClass()->is(Type::class)) { return []; } $classType = $scope->getType($args[0]->value); $templateType = $scope->getType($args[1]->value); $errors = []; foreach ($classType->getConstantStrings() as $classNameType) { if (!$this->reflectionProvider->hasClass($classNameType->getValue())) { continue; } $classReflection = $this->reflectionProvider->getClass($classNameType->getValue()); $templateTypeMap = $classReflection->getTemplateTypeMap(); foreach ($templateType->getConstantStrings() as $templateTypeName) { if ($templateTypeMap->hasType($templateTypeName->getValue())) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Call to %s::%s() references unknown template type %s on class %s.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $templateTypeName->getValue(), $classReflection->getDisplayName()))->identifier('phpstanApi.getTemplateType')->build(); } } return $errors; } } */ final class IgnoreParseErrorRule implements Rule { public function getNodeType() : string { return FileNode::class; } public function processNode(Node $node, Scope $scope) : array { $nodes = $node->getNodes(); if (count($nodes) === 0) { return []; } $firstNode = $nodes[0]; $parseErrors = $firstNode->getAttribute('linesToIgnoreParseErrors', []); $errors = []; foreach ($parseErrors as $line => $lineParseErrors) { foreach ($lineParseErrors as $parseError) { $errors[] = RuleErrorBuilder::message(sprintf('Parse error in @phpstan-ignore: %s', $parseError))->line($line)->identifier('ignore.parseError')->nonIgnorable()->build(); } } return $errors; } } rules[$rule->getNodeType()][] = $rule; } } /** * @template TNodeType of Node * @param class-string $nodeType * @return array> */ public function getRules(string $nodeType) : array { if (!isset($this->cache[$nodeType])) { $parentNodeTypes = [$nodeType] + class_parents($nodeType) + class_implements($nodeType); $rules = []; foreach ($parentNodeTypes as $parentNodeType) { foreach ($this->rules[$parentNodeType] ?? [] as $rule) { $rules[] = $rule; } } $this->cache[$nodeType] = $rules; } /** * @var array> $selectedRules */ $selectedRules = $this->cache[$nodeType]; return $selectedRules; } } */ final class TypesAssignedToPropertiesRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; public function __construct(RuleLevelHelper $ruleLevelHelper, \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder) { $this->ruleLevelHelper = $ruleLevelHelper; $this->propertyReflectionFinder = $propertyReflectionFinder; } public function getNodeType() : string { return PropertyAssignNode::class; } public function processNode(Node $node, Scope $scope) : array { $propertyReflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($node->getPropertyFetch(), $scope); $errors = []; foreach ($propertyReflections as $propertyReflection) { $errors = array_merge($errors, $this->processSingleProperty($propertyReflection, $node->getAssignedExpr())); } return $errors; } /** * @return list */ private function processSingleProperty(\PHPStan\Rules\Properties\FoundPropertyReflection $propertyReflection, Node\Expr $assignedExpr) : array { if (!$propertyReflection->isWritable()) { return []; } $propertyType = $propertyReflection->getWritableType(); $scope = $propertyReflection->getScope(); $assignedValueType = $scope->getType($assignedExpr); $accepts = $this->ruleLevelHelper->acceptsWithReason($propertyType, $assignedValueType, $scope->isDeclareStrictTypes()); if (!$accepts->result) { $propertyDescription = $this->describePropertyByName($propertyReflection, $propertyReflection->getName()); $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($propertyType, $assignedValueType); return [RuleErrorBuilder::message(sprintf('%s (%s) does not accept %s.', $propertyDescription, $propertyType->describe($verbosityLevel), $assignedValueType->describe($verbosityLevel)))->identifier('assign.propertyType')->acceptsReasonsTip($accepts->reasons)->build()]; } return []; } private function describePropertyByName(PropertyReflection $property, string $propertyName) : string { if (!$property->isStatic()) { return sprintf('Property %s::$%s', $property->getDeclaringClass()->getDisplayName(), $propertyName); } return sprintf('Static property %s::$%s', $property->getDeclaringClass()->getDisplayName(), $propertyName); } } name instanceof Node\Identifier) { $names = [$propertyFetch->name->name]; } else { $names = array_map(static function (ConstantStringType $name) : string { return $name->getValue(); }, $scope->getType($propertyFetch->name)->getConstantStrings()); } $reflections = []; $propertyHolderType = $scope->getType($propertyFetch->var); foreach ($names as $name) { $reflection = $this->findPropertyReflection($propertyHolderType, $name, $propertyFetch->name instanceof Expr ? $scope->filterByTruthyValue(new Expr\BinaryOp\Identical($propertyFetch->name, new String_($name))) : $scope); if ($reflection === null) { continue; } $reflections[] = $reflection; } return $reflections; } if ($propertyFetch->class instanceof Node\Name) { $propertyHolderType = $scope->resolveTypeByName($propertyFetch->class); } else { $propertyHolderType = $scope->getType($propertyFetch->class); } if ($propertyFetch->name instanceof VarLikeIdentifier) { $names = [$propertyFetch->name->name]; } else { $names = array_map(static function (ConstantStringType $name) : string { return $name->getValue(); }, $scope->getType($propertyFetch->name)->getConstantStrings()); } $reflections = []; foreach ($names as $name) { $reflection = $this->findPropertyReflection($propertyHolderType, $name, $propertyFetch->name instanceof Expr ? $scope->filterByTruthyValue(new Expr\BinaryOp\Identical($propertyFetch->name, new String_($name))) : $scope); if ($reflection === null) { continue; } $reflections[] = $reflection; } return $reflections; } /** * @param Node\Expr\PropertyFetch|Node\Expr\StaticPropertyFetch $propertyFetch */ public function findPropertyReflectionFromNode($propertyFetch, Scope $scope) : ?\PHPStan\Rules\Properties\FoundPropertyReflection { if ($propertyFetch instanceof Node\Expr\PropertyFetch) { if (!$propertyFetch->name instanceof Node\Identifier) { return null; } $propertyHolderType = $scope->getType($propertyFetch->var); return $this->findPropertyReflection($propertyHolderType, $propertyFetch->name->name, $scope); } if (!$propertyFetch->name instanceof Node\Identifier) { return null; } if ($propertyFetch->class instanceof Node\Name) { $propertyHolderType = $scope->resolveTypeByName($propertyFetch->class); } else { $propertyHolderType = $scope->getType($propertyFetch->class); } return $this->findPropertyReflection($propertyHolderType, $propertyFetch->name->name, $scope); } private function findPropertyReflection(Type $propertyHolderType, string $propertyName, Scope $scope) : ?\PHPStan\Rules\Properties\FoundPropertyReflection { if (!$propertyHolderType->hasProperty($propertyName)->yes()) { return null; } $originalProperty = $propertyHolderType->getProperty($propertyName, $scope); return new \PHPStan\Rules\Properties\FoundPropertyReflection($originalProperty, $scope, $propertyName, $originalProperty->getReadableType(), $originalProperty->getWritableType()); } } originalPropertyReflection = $originalPropertyReflection; $this->scope = $scope; $this->propertyName = $propertyName; $this->readableType = $readableType; $this->writableType = $writableType; } public function getScope() : Scope { return $this->scope; } public function getDeclaringClass() : ClassReflection { return $this->originalPropertyReflection->getDeclaringClass(); } public function getName() : string { return $this->propertyName; } public function isStatic() : bool { return $this->originalPropertyReflection->isStatic(); } public function isPrivate() : bool { return $this->originalPropertyReflection->isPrivate(); } public function isPublic() : bool { return $this->originalPropertyReflection->isPublic(); } public function getDocComment() : ?string { return $this->originalPropertyReflection->getDocComment(); } public function getReadableType() : Type { return $this->readableType; } public function getWritableType() : Type { return $this->writableType; } public function canChangeTypeAfterAssignment() : bool { return $this->originalPropertyReflection->canChangeTypeAfterAssignment(); } public function isReadable() : bool { return $this->originalPropertyReflection->isReadable(); } public function isWritable() : bool { return $this->originalPropertyReflection->isWritable(); } public function isDeprecated() : TrinaryLogic { return $this->originalPropertyReflection->isDeprecated(); } public function getDeprecatedDescription() : ?string { return $this->originalPropertyReflection->getDeprecatedDescription(); } public function isInternal() : TrinaryLogic { return $this->originalPropertyReflection->isInternal(); } public function isNative() : bool { return $this->getNativeReflection() !== null; } public function getNativeType() : ?Type { $reflection = $this->getNativeReflection(); if ($reflection === null) { return null; } return $reflection->getNativeType(); } public function getNativeReflection() : ?PhpPropertyReflection { $reflection = $this->originalPropertyReflection; while ($reflection instanceof WrapperPropertyReflection) { $reflection = $reflection->getOriginalReflection(); } if (!$reflection instanceof PhpPropertyReflection) { return null; } return $reflection; } } */ final class ReadOnlyByPhpDocPropertyAssignRule implements Rule { /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; /** * @var ConstructorsHelper */ private $constructorsHelper; public function __construct(\PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder, ConstructorsHelper $constructorsHelper) { $this->propertyReflectionFinder = $propertyReflectionFinder; $this->constructorsHelper = $constructorsHelper; } public function getNodeType() : string { return PropertyAssignNode::class; } public function processNode(Node $node, Scope $scope) : array { $propertyFetch = $node->getPropertyFetch(); if (!$propertyFetch instanceof Node\Expr\PropertyFetch) { return []; } $errors = []; $reflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($propertyFetch, $scope); foreach ($reflections as $propertyReflection) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection === null) { continue; } if (!$scope->canAccessProperty($propertyReflection)) { continue; } if (!$nativeReflection->isReadOnlyByPhpDoc() || $nativeReflection->isReadOnly()) { continue; } $declaringClass = $nativeReflection->getDeclaringClass(); if (!$scope->isInClass()) { $errors[] = RuleErrorBuilder::message(sprintf('@readonly property %s::$%s is assigned outside of its declaring class.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyByPhpDocAssignOutOfClass')->build(); continue; } $scopeClassReflection = $scope->getClassReflection(); if ($scopeClassReflection->getName() !== $declaringClass->getName()) { $errors[] = RuleErrorBuilder::message(sprintf('@readonly property %s::$%s is assigned outside of its declaring class.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyByPhpDocAssignOutOfClass')->build(); continue; } $scopeMethod = $scope->getFunction(); if (!$scopeMethod instanceof MethodReflection) { throw new ShouldNotHappenException(); } if (in_array($scopeMethod->getName(), $this->constructorsHelper->getConstructors($scopeClassReflection), \true) || strtolower($scopeMethod->getName()) === '__unserialize') { if (TypeUtils::findThisType($scope->getType($propertyFetch->var)) === null) { $errors[] = RuleErrorBuilder::message(sprintf('@readonly property %s::$%s is not assigned on $this.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyByPhpDocAssignNotOnThis')->build(); } continue; } if ($nativeReflection->isAllowedPrivateMutation()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('@readonly property %s::$%s is assigned outside of the constructor.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyByPhpDocAssignNotInConstructor')->build(); } return $errors; } } container = $container; } public function getExtensions() : array { if ($this->extensions === null) { $this->extensions = $this->container->getServicesByTag(\PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider::EXTENSION_TAG); } return $this->extensions; } } */ final class MissingReadOnlyPropertyAssignRule implements Rule { /** * @var ConstructorsHelper */ private $constructorsHelper; public function __construct(ConstructorsHelper $constructorsHelper) { $this->constructorsHelper = $constructorsHelper; } public function getNodeType() : string { return ClassPropertiesNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); [$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection)); $errors = []; foreach ($properties as $propertyName => $propertyNode) { if (!$propertyNode->isReadOnly()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Class %s has an uninitialized readonly property $%s. Assign it in the constructor.', $classReflection->getDisplayName(), $propertyName))->line($propertyNode->getStartLine())->identifier('property.uninitializedReadonly')->build(); } foreach ($prematureAccess as [$propertyName, $line, $propertyNode, $file, $fileDescription]) { if (!$propertyNode->isReadOnly()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Access to an uninitialized readonly property %s::$%s.', $classReflection->getDisplayName(), $propertyName))->line($line)->file($file, $fileDescription)->identifier('property.uninitializedReadonly')->build(); } foreach ($additionalAssigns as [$propertyName, $line, $propertyNode]) { if (!$propertyNode->isReadOnly()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s is already assigned.', $classReflection->getDisplayName(), $propertyName))->line($line)->identifier('assign.readOnlyProperty')->build(); } return $errors; } } */ final class ExistingClassesInPropertiesRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ClassNameCheck */ private $classCheck; /** * @var UnresolvableTypeHelper */ private $unresolvableTypeHelper; /** * @var PhpVersion */ private $phpVersion; /** * @var bool */ private $checkClassCaseSensitivity; /** * @var bool */ private $checkThisOnly; public function __construct(ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, UnresolvableTypeHelper $unresolvableTypeHelper, PhpVersion $phpVersion, bool $checkClassCaseSensitivity, bool $checkThisOnly) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->phpVersion = $phpVersion; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkThisOnly = $checkThisOnly; } public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { $propertyReflection = $node->getClassReflection()->getNativeProperty($node->getName()); if ($this->checkThisOnly) { $referencedClasses = $propertyReflection->getNativeType()->getReferencedClasses(); } else { $referencedClasses = array_merge($propertyReflection->getNativeType()->getReferencedClasses(), $propertyReflection->getPhpDocType()->getReferencedClasses()); } $errors = []; foreach ($referencedClasses as $referencedClass) { if ($this->reflectionProvider->hasClass($referencedClass)) { if ($this->reflectionProvider->getClass($referencedClass)->isTrait()) { $errors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s has invalid type %s.', $propertyReflection->getDeclaringClass()->getDisplayName(), $node->getName(), $referencedClass))->identifier('property.trait')->build(); } continue; } $errors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s has unknown class %s as its type.', $propertyReflection->getDeclaringClass()->getDisplayName(), $node->getName(), $referencedClass))->identifier('class.notFound')->discoveringSymbolsTip()->build(); } $errors = array_merge($errors, $this->classCheck->checkClassNames(array_map(static function (string $class) use($node) : ClassNameNodePair { return new ClassNameNodePair($class, $node); }, $referencedClasses), $this->checkClassCaseSensitivity)); if ($this->phpVersion->supportsPureIntersectionTypes() && $this->unresolvableTypeHelper->containsUnresolvableType($propertyReflection->getNativeType())) { $errors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s has unresolvable native type.', $propertyReflection->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.unresolvableNativeType')->build(); } return $errors; } } */ final class UninitializedPropertyRule implements Rule { /** * @var ConstructorsHelper */ private $constructorsHelper; public function __construct(ConstructorsHelper $constructorsHelper) { $this->constructorsHelper = $constructorsHelper; } public function getNodeType() : string { return ClassPropertiesNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); [$properties, $prematureAccess] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection)); $errors = []; foreach ($properties as $propertyName => $propertyNode) { if ($propertyNode->isReadOnly() || $propertyNode->isReadOnlyByPhpDoc()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Class %s has an uninitialized property $%s. Give it default value or assign it in the constructor.', $classReflection->getDisplayName(), $propertyName))->line($propertyNode->getStartLine())->identifier('property.uninitialized')->build(); } foreach ($prematureAccess as [$propertyName, $line, $propertyNode, $file, $fileDescription]) { if ($propertyNode->isReadOnly() || $propertyNode->isReadOnlyByPhpDoc()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Access to an uninitialized property %s::$%s.', $classReflection->getDisplayName(), $propertyName))->line($line)->file($file, $fileDescription)->identifier('property.uninitialized')->build(); } return $errors; } } */ final class NullsafePropertyFetchRule implements Rule { public function __construct() { } public function getNodeType() : string { return Node\Expr\NullsafePropertyFetch::class; } public function processNode(Node $node, Scope $scope) : array { $calledOnType = $scope->getType($node->var); if (!$calledOnType->isNull()->no()) { return []; } if ($scope->isUndefinedExpressionAllowed($node)) { return []; } return [RuleErrorBuilder::message(sprintf('Using nullsafe property access on non-nullable type %s. Use -> instead.', $calledOnType->describe(VerbosityLevel::typeOnly())))->identifier('nullsafe.neverNull')->build()]; } } */ final class AccessPropertiesRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var bool */ private $reportMagicProperties; /** * @var bool */ private $checkDynamicProperties; public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper, bool $reportMagicProperties, bool $checkDynamicProperties) { $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->reportMagicProperties = $reportMagicProperties; $this->checkDynamicProperties = $checkDynamicProperties; } public function getNodeType() : string { return PropertyFetch::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->name instanceof Identifier) { $names = [$node->name->name]; } else { $names = array_map(static function (ConstantStringType $type) : string { return $type->getValue(); }, $scope->getType($node->name)->getConstantStrings()); } $errors = []; foreach ($names as $name) { $errors = array_merge($errors, $this->processSingleProperty($scope, $node, $name)); } return $errors; } /** * @return list */ private function processSingleProperty(Scope $scope, PropertyFetch $node, string $name) : array { $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $node->var), sprintf('Access to property $%s on an unknown class %%s.', SprintfHelper::escapeFormatString($name)), static function (Type $type) use($name) : bool { return $type->canAccessProperties()->yes() && $type->hasProperty($name)->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } if ($scope->isInExpressionAssign($node)) { return []; } $typeForDescribe = $type; if ($type instanceof StaticType) { $typeForDescribe = $type->getStaticObjectType(); } if ($type->canAccessProperties()->no() || $type->canAccessProperties()->maybe() && !$scope->isUndefinedExpressionAllowed($node)) { return [RuleErrorBuilder::message(sprintf('Cannot access property $%s on %s.', $name, $typeForDescribe->describe(VerbosityLevel::typeOnly())))->identifier('property.nonObject')->build()]; } $has = $type->hasProperty($name); if (!$has->no() && $this->canAccessUndefinedProperties($scope, $node)) { return []; } if (!$has->yes()) { if ($scope->hasExpressionType($node)->yes()) { return []; } $classNames = $type->getObjectClassNames(); if (!$this->reportMagicProperties) { foreach ($classNames as $className) { if (!$this->reflectionProvider->hasClass($className)) { continue; } $classReflection = $this->reflectionProvider->getClass($className); if ($classReflection->hasNativeMethod('__get') || $classReflection->hasNativeMethod('__set')) { return []; } } } if (count($classNames) === 1) { $propertyClassReflection = $this->reflectionProvider->getClass($classNames[0]); $parentClassReflection = $propertyClassReflection->getParentClass(); while ($parentClassReflection !== null) { if ($parentClassReflection->hasProperty($name)) { if ($scope->canAccessProperty($parentClassReflection->getProperty($name, $scope))) { return []; } return [RuleErrorBuilder::message(sprintf('Access to private property $%s of parent class %s.', $name, $parentClassReflection->getDisplayName()))->identifier('property.private')->build()]; } $parentClassReflection = $parentClassReflection->getParentClass(); } } $ruleErrorBuilder = RuleErrorBuilder::message(sprintf('Access to an undefined property %s::$%s.', $typeForDescribe->describe(VerbosityLevel::typeOnly()), $name))->identifier('property.notFound'); if ($typeResult->getTip() !== null) { $ruleErrorBuilder->tip($typeResult->getTip()); } else { $ruleErrorBuilder->tip('Learn more: https://phpstan.org/blog/solving-phpstan-access-to-undefined-property'); } return [$ruleErrorBuilder->build()]; } $propertyReflection = $type->getProperty($name, $scope); if (!$scope->canAccessProperty($propertyReflection)) { return [RuleErrorBuilder::message(sprintf('Access to %s property %s::$%s.', $propertyReflection->isPrivate() ? 'private' : 'protected', $type->describe(VerbosityLevel::typeOnly()), $name))->identifier(sprintf('property.%s', $propertyReflection->isPrivate() ? 'private' : 'protected'))->build()]; } return []; } private function canAccessUndefinedProperties(Scope $scope, Node\Expr $node) : bool { return $scope->isUndefinedExpressionAllowed($node) && !$this->checkDynamicProperties; } } */ final class ReadOnlyPropertyAssignRefRule implements Rule { /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; public function __construct(\PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder) { $this->propertyReflectionFinder = $propertyReflectionFinder; } public function getNodeType() : string { return Node\Expr\AssignRef::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->expr instanceof Node\Expr\PropertyFetch && !$node->expr instanceof Node\Expr\StaticPropertyFetch) { return []; } $propertyFetch = $node->expr; $errors = []; $reflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($propertyFetch, $scope); foreach ($reflections as $propertyReflection) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection === null) { continue; } if (!$scope->canAccessProperty($propertyReflection)) { continue; } if (!$nativeReflection->isReadOnly()) { continue; } $declaringClass = $nativeReflection->getDeclaringClass(); $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s is assigned by reference.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyAssignByRef')->build(); } return $errors; } } */ final class DefaultValueTypesAssignedToPropertiesRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { $default = $node->getDefault(); if ($default === null) { return []; } $classReflection = $node->getClassReflection(); $propertyReflection = $classReflection->getNativeProperty($node->getName()); $propertyType = $propertyReflection->getWritableType(); if ($propertyReflection->getNativeType() instanceof MixedType) { if ($default instanceof Node\Expr\ConstFetch && $default->name->toLowerString() === 'null') { return []; } } $defaultValueType = $scope->getType($default); $accepts = $this->ruleLevelHelper->acceptsWithReason($propertyType, $defaultValueType, \true); if ($accepts->result) { return []; } $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($propertyType, $defaultValueType); return [RuleErrorBuilder::message(sprintf('%s %s::$%s (%s) does not accept default value of type %s.', $node->isStatic() ? 'Static property' : 'Property', $classReflection->getDisplayName(), $node->getName(), $propertyType->describe($verbosityLevel), $defaultValueType->describe($verbosityLevel)))->identifier('property.defaultValue')->acceptsReasonsTip($accepts->reasons)->build()]; } } */ final class ReadOnlyPropertyRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->isReadOnly()) { return []; } $errors = []; if (!$this->phpVersion->supportsReadOnlyProperties()) { $errors[] = RuleErrorBuilder::message('Readonly properties are supported only on PHP 8.1 and later.')->nonIgnorable()->identifier('property.readOnlyNotSupported')->build(); } if ($node->getNativeType() === null) { $errors[] = RuleErrorBuilder::message('Readonly property must have a native type.')->identifier('property.readOnlyNoNativeType')->nonIgnorable()->build(); } if ($node->getDefault() !== null) { $errors[] = RuleErrorBuilder::message('Readonly property cannot have a default value.')->nonIgnorable()->identifier('property.readOnlyDefaultValue')->build(); } if ($node->isStatic()) { $errors[] = RuleErrorBuilder::message('Readonly property cannot be static.')->nonIgnorable()->identifier('property.readOnlyStatic')->build(); } return $errors; } } */ final class MissingPropertyTypehintRule implements Rule { /** * @var MissingTypehintCheck */ private $missingTypehintCheck; public function __construct(MissingTypehintCheck $missingTypehintCheck) { $this->missingTypehintCheck = $missingTypehintCheck; } public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { $propertyReflection = $node->getClassReflection()->getNativeProperty($node->getName()); if ($propertyReflection->isPromoted()) { return []; } $propertyType = $propertyReflection->getReadableType(); if ($propertyType instanceof MixedType && !$propertyType->isExplicitMixed()) { return [RuleErrorBuilder::message(sprintf('Property %s::$%s has no type specified.', $propertyReflection->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('missingType.property')->build()]; } $messages = []; foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($propertyType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $messages[] = RuleErrorBuilder::message(sprintf('Property %s::$%s type has no value type specified in iterable type %s.', $propertyReflection->getDeclaringClass()->getDisplayName(), $node->getName(), $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($propertyType) as [$name, $genericTypeNames]) { $messages[] = RuleErrorBuilder::message(sprintf('Property %s::$%s with generic %s does not specify its types: %s', $propertyReflection->getDeclaringClass()->getDisplayName(), $node->getName(), $name, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($propertyType) as $callableType) { $messages[] = RuleErrorBuilder::message(sprintf('Property %s::$%s type has no signature specified for %s.', $propertyReflection->getDeclaringClass()->getDisplayName(), $node->getName(), $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $messages; } } */ final class AccessStaticPropertiesInAssignRule implements Rule { /** * @var AccessStaticPropertiesRule */ private $accessStaticPropertiesRule; public function __construct(\PHPStan\Rules\Properties\AccessStaticPropertiesRule $accessStaticPropertiesRule) { $this->accessStaticPropertiesRule = $accessStaticPropertiesRule; } public function getNodeType() : string { return PropertyAssignNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->getPropertyFetch() instanceof Node\Expr\StaticPropertyFetch) { return []; } if ($node->isAssignOp()) { return []; } return $this->accessStaticPropertiesRule->processNode($node->getPropertyFetch(), $scope); } } */ final class ReadOnlyByPhpDocPropertyRule implements Rule { public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!($node->isReadOnlyByPhpDoc() && !$node->isAllowedPrivateMutation()) || $node->isReadOnly()) { return []; } $errors = []; if ($node->getDefault() !== null) { $errors[] = RuleErrorBuilder::message('@readonly property cannot have a default value.')->identifier('property.readOnlyByPhpDocDefaultValue')->build(); } return $errors; } } */ final class ReadOnlyPropertyAssignRule implements Rule { /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; /** * @var ConstructorsHelper */ private $constructorsHelper; public function __construct(\PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder, ConstructorsHelper $constructorsHelper) { $this->propertyReflectionFinder = $propertyReflectionFinder; $this->constructorsHelper = $constructorsHelper; } public function getNodeType() : string { return PropertyAssignNode::class; } public function processNode(Node $node, Scope $scope) : array { $propertyFetch = $node->getPropertyFetch(); if (!$propertyFetch instanceof Node\Expr\PropertyFetch) { return []; } $errors = []; $reflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($propertyFetch, $scope); foreach ($reflections as $propertyReflection) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection === null) { continue; } if (!$scope->canAccessProperty($propertyReflection)) { continue; } if (!$nativeReflection->isReadOnly()) { continue; } $declaringClass = $nativeReflection->getDeclaringClass(); if (!$scope->isInClass()) { $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s is assigned outside of its declaring class.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyAssignOutOfClass')->build(); continue; } $scopeClassReflection = $scope->getClassReflection(); if ($scopeClassReflection->getName() !== $declaringClass->getName()) { $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s is assigned outside of its declaring class.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyAssignOutOfClass')->build(); continue; } $scopeMethod = $scope->getFunction(); if (!$scopeMethod instanceof MethodReflection) { throw new ShouldNotHappenException(); } if (in_array($scopeMethod->getName(), $this->constructorsHelper->getConstructors($scopeClassReflection), \true) || strtolower($scopeMethod->getName()) === '__unserialize') { if (TypeUtils::findThisType($scope->getType($propertyFetch->var)) === null) { $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s is not assigned on $this.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyAssignNotOnThis')->build(); } continue; } $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s is assigned outside of the constructor.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyAssignNotInConstructor')->build(); } return $errors; } } */ final class AccessPropertiesInAssignRule implements Rule { /** * @var AccessPropertiesRule */ private $accessPropertiesRule; public function __construct(\PHPStan\Rules\Properties\AccessPropertiesRule $accessPropertiesRule) { $this->accessPropertiesRule = $accessPropertiesRule; } public function getNodeType() : string { return PropertyAssignNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->getPropertyFetch() instanceof Node\Expr\PropertyFetch) { return []; } if ($node->isAssignOp()) { return []; } return $this->accessPropertiesRule->processNode($node->getPropertyFetch(), $scope); } } */ final class MissingReadOnlyByPhpDocPropertyAssignRule implements Rule { /** * @var ConstructorsHelper */ private $constructorsHelper; public function __construct(ConstructorsHelper $constructorsHelper) { $this->constructorsHelper = $constructorsHelper; } public function getNodeType() : string { return ClassPropertiesNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); [$properties, $prematureAccess, $additionalAssigns] = $node->getUninitializedProperties($scope, $this->constructorsHelper->getConstructors($classReflection)); $errors = []; foreach ($properties as $propertyName => $propertyNode) { if (!$propertyNode->isReadOnlyByPhpDoc() || $propertyNode->isReadOnly()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Class %s has an uninitialized @readonly property $%s. Assign it in the constructor.', $classReflection->getDisplayName(), $propertyName))->line($propertyNode->getStartLine())->identifier('property.uninitializedReadonlyByPhpDoc')->build(); } foreach ($prematureAccess as [$propertyName, $line, $propertyNode, $file, $fileDescription]) { if (!$propertyNode->isReadOnlyByPhpDoc() || $propertyNode->isReadOnly()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Access to an uninitialized @readonly property %s::$%s.', $classReflection->getDisplayName(), $propertyName))->identifier('property.uninitializedReadonlyByPhpDoc')->line($line)->file($file, $fileDescription)->build(); } foreach ($additionalAssigns as [$propertyName, $line, $propertyNode]) { if (!$propertyNode->isReadOnlyByPhpDoc() || $propertyNode->isReadOnly()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('@readonly property %s::$%s is already assigned.', $classReflection->getDisplayName(), $propertyName))->identifier('assign.readOnlyPropertyByPhpDoc')->line($line)->build(); } return $errors; } } */ final class PropertyAttributesRule implements Rule { /** * @var AttributesCheck */ private $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType() : string { return Node\Stmt\Property::class; } public function processNode(Node $node, Scope $scope) : array { return $this->attributesCheck->check($scope, $node->attrGroups, Attribute::TARGET_PROPERTY, 'property'); } } */ final class InvalidCallablePropertyTypeRule implements Rule { public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); $propertyReflection = $classReflection->getNativeProperty($node->getName()); if (!$propertyReflection->hasNativeType()) { return []; } $nativeType = $propertyReflection->getNativeType(); $callableTypes = []; TypeTraverser::map($nativeType, static function (Type $type, callable $traverse) use(&$callableTypes) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type instanceof CallableType) { $callableTypes[] = $type; } return $type; }); if ($callableTypes === []) { return []; } return [RuleErrorBuilder::message(sprintf('Property %s::$%s cannot have callable in its type declaration.', $classReflection->getDisplayName(), $node->getName()))->identifier('property.callableType')->nonIgnorable()->build()]; } } */ final class OverridingPropertyRule implements Rule { /** * @var bool */ private $checkPhpDocMethodSignatures; /** * @var bool */ private $reportMaybes; public function __construct(bool $checkPhpDocMethodSignatures, bool $reportMaybes) { $this->checkPhpDocMethodSignatures = $checkPhpDocMethodSignatures; $this->reportMaybes = $reportMaybes; } public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); $prototype = $this->findPrototype($classReflection, $node->getName()); if ($prototype === null) { return []; } $errors = []; if ($prototype->isStatic()) { if (!$node->isStatic()) { $errors[] = RuleErrorBuilder::message(sprintf('Non-static property %s::$%s overrides static property %s::$%s.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.nonStatic')->nonIgnorable()->build(); } } elseif ($node->isStatic()) { $errors[] = RuleErrorBuilder::message(sprintf('Static property %s::$%s overrides non-static property %s::$%s.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.static')->nonIgnorable()->build(); } if ($prototype->isReadOnly()) { if (!$node->isReadOnly()) { $errors[] = RuleErrorBuilder::message(sprintf('Readwrite property %s::$%s overrides readonly property %s::$%s.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.readWrite')->nonIgnorable()->build(); } } elseif ($node->isReadOnly()) { $errors[] = RuleErrorBuilder::message(sprintf('Readonly property %s::$%s overrides readwrite property %s::$%s.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.readOnly')->nonIgnorable()->build(); } if ($prototype->isPublic()) { if (!$node->isPublic()) { $errors[] = RuleErrorBuilder::message(sprintf('%s property %s::$%s overriding public property %s::$%s should also be public.', $node->isPrivate() ? 'Private' : 'Protected', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.visibility')->nonIgnorable()->build(); } } elseif ($node->isPrivate()) { $errors[] = RuleErrorBuilder::message(sprintf('Private property %s::$%s overriding protected property %s::$%s should be protected or public.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.visibility')->nonIgnorable()->build(); } $typeErrors = []; if ($prototype->hasNativeType()) { if ($node->getNativeType() === null) { $typeErrors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s overriding property %s::$%s (%s) should also have native type %s.', $classReflection->getDisplayName(), $node->getName(), $prototype->getDeclaringClass()->getDisplayName(), $node->getName(), $prototype->getNativeType()->describe(VerbosityLevel::typeOnly()), $prototype->getNativeType()->describe(VerbosityLevel::typeOnly())))->identifier('property.missingNativeType')->nonIgnorable()->build(); } else { $nativeType = ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection); if (!$prototype->getNativeType()->equals($nativeType)) { $typeErrors[] = RuleErrorBuilder::message(sprintf('Type %s of property %s::$%s is not the same as type %s of overridden property %s::$%s.', $nativeType->describe(VerbosityLevel::typeOnly()), $classReflection->getDisplayName(), $node->getName(), $prototype->getNativeType()->describe(VerbosityLevel::typeOnly()), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.nativeType')->nonIgnorable()->build(); } } } elseif ($node->getNativeType() !== null) { $typeErrors[] = RuleErrorBuilder::message(sprintf('Property %s::$%s (%s) overriding property %s::$%s should not have a native type.', $classReflection->getDisplayName(), $node->getName(), ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection)->describe(VerbosityLevel::typeOnly()), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.extraNativeType')->nonIgnorable()->build(); } $errors = array_merge($errors, $typeErrors); if (!$this->checkPhpDocMethodSignatures) { return $errors; } if (count($typeErrors) > 0) { return $errors; } $propertyReflection = $classReflection->getNativeProperty($node->getName()); if ($prototype->getReadableType()->equals($propertyReflection->getReadableType())) { return $errors; } $verbosity = VerbosityLevel::getRecommendedLevelByType($prototype->getReadableType(), $propertyReflection->getReadableType()); $isSuperType = $prototype->getReadableType()->isSuperTypeOf($propertyReflection->getReadableType()); $canBeTurnedOffError = RuleErrorBuilder::message(sprintf('PHPDoc type %s of property %s::$%s is not the same as PHPDoc type %s of overridden property %s::$%s.', $propertyReflection->getReadableType()->describe($verbosity), $classReflection->getDisplayName(), $node->getName(), $prototype->getReadableType()->describe($verbosity), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.phpDocType')->tip(sprintf("You can fix 3rd party PHPDoc types with stub files:\n %s\n This error can be turned off by setting\n %s", 'https://phpstan.org/user-guide/stub-files', 'reportMaybesInPropertyPhpDocTypes: false in your %configurationFile%.'))->build(); $cannotBeTurnedOffError = RuleErrorBuilder::message(sprintf('PHPDoc type %s of property %s::$%s is %s PHPDoc type %s of overridden property %s::$%s.', $propertyReflection->getReadableType()->describe($verbosity), $classReflection->getDisplayName(), $node->getName(), $this->reportMaybes ? 'not the same as' : 'not covariant with', $prototype->getReadableType()->describe($verbosity), $prototype->getDeclaringClass()->getDisplayName(), $node->getName()))->identifier('property.phpDocType')->tip(sprintf("You can fix 3rd party PHPDoc types with stub files:\n %s", 'https://phpstan.org/user-guide/stub-files'))->build(); if ($this->reportMaybes) { if (!$isSuperType->yes()) { $errors[] = $cannotBeTurnedOffError; } else { $errors[] = $canBeTurnedOffError; } } else { if (!$isSuperType->yes()) { $errors[] = $cannotBeTurnedOffError; } } return $errors; } private function findPrototype(ClassReflection $classReflection, string $propertyName) : ?PhpPropertyReflection { $parentClass = $classReflection->getParentClass(); if ($parentClass === null) { return null; } if (!$parentClass->hasNativeProperty($propertyName)) { return null; } $property = $parentClass->getNativeProperty($propertyName); if ($property->isPrivate()) { return null; } return $property; } } getType($propertyFetch->var); $declaringClassType = new ObjectType($property->getDeclaringClass()->getName()); if ($declaringClassType->isSuperTypeOf($fetchedOnType)->yes()) { $classDescription = $property->getDeclaringClass()->getDisplayName(); } else { $classDescription = $fetchedOnType->describe(VerbosityLevel::typeOnly()); } } else { $classDescription = $property->getDeclaringClass()->getDisplayName(); } /** @var Node\Identifier $name */ $name = $propertyFetch->name; if (!$property->isStatic()) { return sprintf('Property %s::$%s', $classDescription, $name->name); } return sprintf('Static property %s::$%s', $classDescription, $name->name); } } */ final class PropertiesInInterfaceRule implements Rule { public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->getClassReflection()->isInterface()) { return []; } return [RuleErrorBuilder::message('Interfaces may not include properties.')->nonIgnorable()->identifier('property.inInterface')->build()]; } } */ final class WritingToReadOnlyPropertiesRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var PropertyDescriptor */ private $propertyDescriptor; /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; /** * @var bool */ private $checkThisOnly; public function __construct(RuleLevelHelper $ruleLevelHelper, \PHPStan\Rules\Properties\PropertyDescriptor $propertyDescriptor, \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder, bool $checkThisOnly) { $this->ruleLevelHelper = $ruleLevelHelper; $this->propertyDescriptor = $propertyDescriptor; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->checkThisOnly = $checkThisOnly; } public function getNodeType() : string { return PropertyAssignNode::class; } public function processNode(Node $node, Scope $scope) : array { $propertyFetch = $node->getPropertyFetch(); if ($propertyFetch instanceof Node\Expr\PropertyFetch && $this->checkThisOnly && !$this->ruleLevelHelper->isThis($propertyFetch->var)) { return []; } $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($propertyFetch, $scope); if ($propertyReflection === null) { return []; } if (!$scope->canAccessProperty($propertyReflection)) { return []; } if (!$propertyReflection->isWritable()) { $propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $scope, $propertyFetch); return [RuleErrorBuilder::message(sprintf('%s is not writable.', $propertyDescription))->identifier('assign.propertyReadOnly')->build()]; } return []; } } */ final class AccessStaticPropertiesRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var ClassNameCheck */ private $classCheck; public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper, ClassNameCheck $classCheck) { $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->classCheck = $classCheck; } public function getNodeType() : string { return StaticPropertyFetch::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->name instanceof Node\VarLikeIdentifier) { $names = [$node->name->name]; } else { $names = array_map(static function (ConstantStringType $type) : string { return $type->getValue(); }, $scope->getType($node->name)->getConstantStrings()); } $errors = []; foreach ($names as $name) { $errors = array_merge($errors, $this->processSingleProperty($scope, $node, $name)); } return $errors; } /** * @return list */ private function processSingleProperty(Scope $scope, StaticPropertyFetch $node, string $name) : array { $messages = []; if ($node->class instanceof Name) { $class = (string) $node->class; $lowercasedClass = strtolower($class); if (in_array($lowercasedClass, ['self', 'static'], \true)) { if (!$scope->isInClass()) { return [RuleErrorBuilder::message(sprintf('Accessing %s::$%s outside of class scope.', $class, $name))->identifier(sprintf('outOfClass.%s', $lowercasedClass))->build()]; } $classType = $scope->resolveTypeByName($node->class); } elseif ($lowercasedClass === 'parent') { if (!$scope->isInClass()) { return [RuleErrorBuilder::message(sprintf('Accessing %s::$%s outside of class scope.', $class, $name))->identifier('outOfClass.parent')->build()]; } if ($scope->getClassReflection()->getParentClass() === null) { return [RuleErrorBuilder::message(sprintf('%s::%s() accesses parent::$%s but %s does not extend any class.', $scope->getClassReflection()->getDisplayName(), $scope->getFunctionName(), $name, $scope->getClassReflection()->getDisplayName()))->identifier('class.noParent')->build()]; } if ($scope->getFunctionName() === null) { throw new ShouldNotHappenException(); } $currentMethodReflection = $scope->getClassReflection()->getNativeMethod($scope->getFunctionName()); if (!$currentMethodReflection->isStatic()) { // calling parent::method() from instance method return []; } $classType = $scope->resolveTypeByName($node->class); } else { if (!$this->reflectionProvider->hasClass($class)) { if ($scope->isInClassExists($class)) { return []; } return [RuleErrorBuilder::message(sprintf('Access to static property $%s on an unknown class %s.', $name, $class))->discoveringSymbolsTip()->identifier('class.notFound')->build()]; } $messages = $this->classCheck->checkClassNames([new ClassNameNodePair($class, $node->class)]); $classType = $scope->resolveTypeByName($node->class); } } else { $classTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $node->class), sprintf('Access to static property $%s on an unknown class %%s.', SprintfHelper::escapeFormatString($name)), static function (Type $type) use($name) : bool { return $type->canAccessProperties()->yes() && $type->hasProperty($name)->yes(); }); $classType = $classTypeResult->getType(); if ($classType instanceof ErrorType) { return $classTypeResult->getUnknownClassErrors(); } } if ($classType->isString()->yes()) { return []; } $typeForDescribe = $classType; if ($classType instanceof ThisType) { $typeForDescribe = $classType->getStaticObjectType(); } $classType = TypeCombinator::remove($classType, new StringType()); if ($scope->isInExpressionAssign($node)) { return []; } if ($classType->canAccessProperties()->no() || $classType->canAccessProperties()->maybe() && !$scope->isUndefinedExpressionAllowed($node)) { return array_merge($messages, [RuleErrorBuilder::message(sprintf('Cannot access static property $%s on %s.', $name, $typeForDescribe->describe(VerbosityLevel::typeOnly())))->identifier('staticProperty.nonObject')->build()]); } $has = $classType->hasProperty($name); if (!$has->no() && $scope->isUndefinedExpressionAllowed($node)) { return []; } if (!$has->yes()) { if ($scope->hasExpressionType($node)->yes()) { return $messages; } $classNames = $classType->getObjectClassNames(); if (count($classNames) === 1) { $propertyClassReflection = $this->reflectionProvider->getClass($classNames[0]); $parentClassReflection = $propertyClassReflection->getParentClass(); while ($parentClassReflection !== null) { if ($parentClassReflection->hasProperty($name)) { if ($scope->canAccessProperty($parentClassReflection->getProperty($name, $scope))) { return []; } return [RuleErrorBuilder::message(sprintf('Access to private static property $%s of parent class %s.', $name, $parentClassReflection->getDisplayName()))->identifier('staticProperty.private')->build()]; } $parentClassReflection = $parentClassReflection->getParentClass(); } } return array_merge($messages, [RuleErrorBuilder::message(sprintf('Access to an undefined static property %s::$%s.', $typeForDescribe->describe(VerbosityLevel::typeOnly()), $name))->identifier('staticProperty.notFound')->build()]); } $property = $classType->getProperty($name, $scope); if (!$property->isStatic()) { $hasPropertyTypes = TypeUtils::getHasPropertyTypes($classType); foreach ($hasPropertyTypes as $hasPropertyType) { if ($hasPropertyType->getPropertyName() === $name) { return []; } } return array_merge($messages, [RuleErrorBuilder::message(sprintf('Static access to instance property %s::$%s.', $property->getDeclaringClass()->getDisplayName(), $name))->identifier('property.staticAccess')->build()]); } if (!$scope->canAccessProperty($property)) { return array_merge($messages, [RuleErrorBuilder::message(sprintf('Access to %s property $%s of class %s.', $property->isPrivate() ? 'private' : 'protected', $name, $property->getDeclaringClass()->getDisplayName()))->identifier(sprintf('staticProperty.%s', $property->isPrivate() ? 'private' : 'protected'))->build()]); } return $messages; } } */ final class ReadingWriteOnlyPropertiesRule implements Rule { /** * @var PropertyDescriptor */ private $propertyDescriptor; /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var bool */ private $checkThisOnly; public function __construct(\PHPStan\Rules\Properties\PropertyDescriptor $propertyDescriptor, \PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder, RuleLevelHelper $ruleLevelHelper, bool $checkThisOnly) { $this->propertyDescriptor = $propertyDescriptor; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->ruleLevelHelper = $ruleLevelHelper; $this->checkThisOnly = $checkThisOnly; } public function getNodeType() : string { return Node\Expr::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Node\Expr\PropertyFetch && !$node instanceof Node\Expr\StaticPropertyFetch) { return []; } if ($node instanceof Node\Expr\PropertyFetch && $this->checkThisOnly && !$this->ruleLevelHelper->isThis($node->var)) { return []; } if ($scope->isInExpressionAssign($node)) { return []; } $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($node, $scope); if ($propertyReflection === null) { return []; } if (!$scope->canAccessProperty($propertyReflection)) { return []; } if (!$propertyReflection->isReadable()) { $propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $scope, $node); return [RuleErrorBuilder::message(sprintf('%s is not readable.', $propertyDescription))->identifier('property.writeOnly')->build()]; } return []; } } extensions = $extensions; } /** * @return ReadWritePropertiesExtension[] */ public function getExtensions() : array { return $this->extensions; } } */ final class ReadOnlyByPhpDocPropertyAssignRefRule implements Rule { /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; public function __construct(\PHPStan\Rules\Properties\PropertyReflectionFinder $propertyReflectionFinder) { $this->propertyReflectionFinder = $propertyReflectionFinder; } public function getNodeType() : string { return Node\Expr\AssignRef::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->expr instanceof Node\Expr\PropertyFetch && !$node->expr instanceof Node\Expr\StaticPropertyFetch) { return []; } $propertyFetch = $node->expr; $errors = []; $reflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($propertyFetch, $scope); foreach ($reflections as $propertyReflection) { $nativeReflection = $propertyReflection->getNativeReflection(); if ($nativeReflection === null) { continue; } if (!$scope->canAccessProperty($propertyReflection)) { continue; } if (!$nativeReflection->isReadOnlyByPhpDoc() || $nativeReflection->isReadOnly()) { continue; } $declaringClass = $nativeReflection->getDeclaringClass(); $errors[] = RuleErrorBuilder::message(sprintf('@readonly property %s::$%s is assigned by reference.', $declaringClass->getDisplayName(), $propertyReflection->getName()))->identifier('property.readOnlyByPhpDocAssignByRef')->build(); } return $errors; } } */ final class AccessPrivatePropertyThroughStaticRule implements Rule { public function getNodeType() : string { return Node\Expr\StaticPropertyFetch::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\VarLikeIdentifier) { return []; } if (!$node->class instanceof Name) { return []; } $propertyName = $node->name->name; $className = $node->class; if ($className->toLowerString() !== 'static') { return []; } $classType = $scope->resolveTypeByName($className); if (!$classType->hasProperty($propertyName)->yes()) { return []; } $property = $classType->getProperty($propertyName, $scope); if (!$property->isPrivate()) { return []; } if (!$property->isStatic()) { return []; } if ($scope->isInClass() && $scope->getClassReflection()->isFinal()) { return []; } return [RuleErrorBuilder::message(sprintf('Unsafe access to private property %s::$%s through static::.', $property->getDeclaringClass()->getDisplayName(), $propertyName))->identifier('staticClassAccess.privateProperty')->build()]; } } classCheck = $classCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; } /** * @param array $extendsTags * @return list */ public function checkExtendsTags(Node $node, array $extendsTags) : array { $errors = []; if (count($extendsTags) > 1) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends can only be used once.'))->identifier('requireExtends.duplicate')->build(); } foreach ($extendsTags as $extendsTag) { $type = $extendsTag->getType(); if (!$type instanceof ObjectType) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))->identifier('requireExtends.nonObject')->build(); continue; } $class = $type->getClassName(); $referencedClassReflection = $type->getClassReflection(); if ($referencedClassReflection === null) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends contains unknown class %s.', $class))->discoveringSymbolsTip()->identifier('class.notFound')->build(); continue; } if (!$referencedClassReflection->isClass()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends cannot contain non-class type %s.', $class))->identifier(sprintf('requireExtends.%s', strtolower($referencedClassReflection->getClassTypeDescription())))->build(); } elseif ($referencedClassReflection->isFinal()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends cannot contain final class %s.', $class))->identifier('requireExtends.finalClass')->build(); } else { $errors = array_merge($errors, $this->classCheck->checkClassNames([new ClassNameNodePair($class, $node)], $this->checkClassCaseSensitivity)); } } return $errors; } } */ final class InvalidPhpDocTagValueRule implements Rule { /** * @var Lexer */ private $phpDocLexer; /** * @var PhpDocParser */ private $phpDocParser; /** * @var bool */ private $checkAllInvalidPhpDocs; /** * @var bool */ private $invalidPhpDocTagLine; public function __construct(Lexer $phpDocLexer, PhpDocParser $phpDocParser, bool $checkAllInvalidPhpDocs, bool $invalidPhpDocTagLine) { $this->phpDocLexer = $phpDocLexer; $this->phpDocParser = $phpDocParser; $this->checkAllInvalidPhpDocs = $checkAllInvalidPhpDocs; $this->invalidPhpDocTagLine = $invalidPhpDocTagLine; } public function getNodeType() : string { return Node::class; } public function processNode(Node $node, Scope $scope) : array { if (!$this->checkAllInvalidPhpDocs) { if (!$node instanceof Node\Stmt\ClassLike && !$node instanceof Node\FunctionLike && !$node instanceof Node\Stmt\Foreach_ && !$node instanceof Node\Stmt\Property && !$node instanceof Node\Expr\Assign && !$node instanceof Node\Expr\AssignRef && !$node instanceof Node\Stmt\ClassConst) { return []; } } else { // mirrored with InvalidPHPStanDocTagRule if ($node instanceof VirtualNode) { return []; } if ($node instanceof Node\Stmt\Expression) { return []; } if ($node instanceof Node\Expr && !$node instanceof Node\Expr\Assign && !$node instanceof Node\Expr\AssignRef) { return []; } } $docComment = $node->getDocComment(); if ($docComment === null) { return []; } $phpDocString = $docComment->getText(); $tokens = new TokenIterator($this->phpDocLexer->tokenize($phpDocString)); $phpDocNode = $this->phpDocParser->parse($tokens); $errors = []; foreach ($phpDocNode->getTags() as $phpDocTag) { if (str_starts_with($phpDocTag->name, '@phan-') || str_starts_with($phpDocTag->name, '@psalm-')) { continue; } if ($phpDocTag->value instanceof TypeAliasTagValueNode) { if (!$phpDocTag->value->type instanceof InvalidTypeNode) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s %s has invalid value: %s', $phpDocTag->name, $phpDocTag->value->alias, $this->trimExceptionMessage($phpDocTag->value->type->getException()->getMessage())))->line(\PHPStan\Rules\PhpDoc\PhpDocLineHelper::detectLine($node, $phpDocTag))->identifier('phpDoc.parseError')->build(); continue; } elseif (!$phpDocTag->value instanceof InvalidTagValueNode) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s has invalid value (%s): %s', $phpDocTag->name, $phpDocTag->value->value, $this->trimExceptionMessage($phpDocTag->value->exception->getMessage())))->line(\PHPStan\Rules\PhpDoc\PhpDocLineHelper::detectLine($node, $phpDocTag))->identifier('phpDoc.parseError')->build(); } return $errors; } private function trimExceptionMessage(string $message) : string { if ($this->invalidPhpDocTagLine) { return $message; } return Strings::replace($message, '~( on line \\d+)$~', ''); } } */ final class IncompatiblePhpDocTypeRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; /** * @var GenericObjectTypeCheck */ private $genericObjectTypeCheck; /** * @var UnresolvableTypeHelper */ private $unresolvableTypeHelper; /** * @var GenericCallableRuleHelper */ private $genericCallableRuleHelper; public function __construct(FileTypeMapper $fileTypeMapper, GenericObjectTypeCheck $genericObjectTypeCheck, \PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $unresolvableTypeHelper, \PHPStan\Rules\PhpDoc\GenericCallableRuleHelper $genericCallableRuleHelper) { $this->fileTypeMapper = $fileTypeMapper; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->genericCallableRuleHelper = $genericCallableRuleHelper; } public function getNodeType() : string { return Node\FunctionLike::class; } public function processNode(Node $node, Scope $scope) : array { if ($node instanceof Node\Stmt\ClassMethod) { $functionName = $node->name->name; } elseif ($node instanceof Node\Stmt\Function_) { $functionName = trim($scope->getNamespace() . '\\' . $node->name->name, '\\'); } else { return []; } $docComment = $node->getDocComment(); if ($docComment === null) { return []; } $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $functionName, $docComment->getText()); $nativeParameterTypes = $this->getNativeParameterTypes($node, $scope); $byRefParameters = $this->getByRefParameters($node); $errors = []; foreach (['@param' => $resolvedPhpDoc->getParamTags(), '@param-out' => $resolvedPhpDoc->getParamOutTags(), '@param-closure-this' => $resolvedPhpDoc->getParamClosureThisTags()] as $tagName => $parameters) { foreach ($parameters as $parameterName => $phpDocParamTag) { $phpDocParamType = $phpDocParamTag->getType(); if (!isset($nativeParameterTypes[$parameterName])) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s references unknown parameter: $%s', $tagName, $parameterName))->identifier('parameter.notFound')->build(); } elseif ($this->unresolvableTypeHelper->containsUnresolvableType($phpDocParamType)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for parameter $%s contains unresolvable type.', $tagName, $parameterName))->identifier('parameter.unresolvableType')->build(); } else { $nativeParamType = $nativeParameterTypes[$parameterName]; if ($phpDocParamTag instanceof ParamTag && $phpDocParamTag->isVariadic() && $phpDocParamType->isArray()->yes() && $nativeParamType->isArray()->no()) { $phpDocParamType = $phpDocParamType->getIterableValueType(); } $escapedParameterName = SprintfHelper::escapeFormatString($parameterName); $escapedTagName = SprintfHelper::escapeFormatString($tagName); $errors = array_merge($errors, $this->genericObjectTypeCheck->check($phpDocParamType, sprintf('PHPDoc tag %s for parameter $%s contains generic type %%s but %%s %%s is not generic.', $escapedTagName, $escapedParameterName), sprintf('Generic type %%s in PHPDoc tag %s for parameter $%s does not specify all template types of %%s %%s: %%s', $escapedTagName, $escapedParameterName), sprintf('Generic type %%s in PHPDoc tag %s for parameter $%s specifies %%d template types, but %%s %%s supports only %%d: %%s', $escapedTagName, $escapedParameterName), sprintf('Type %%s in generic type %%s in PHPDoc tag %s for parameter $%s is not subtype of template type %%s of %%s %%s.', $escapedTagName, $escapedParameterName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag %s for parameter $%s is in conflict with %%s template type %%s of %%s %%s.', $escapedTagName, $escapedParameterName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag %s for parameter $%s is redundant, template type %%s of %%s %%s has the same variance.', $escapedTagName, $escapedParameterName))); $errors = array_merge($errors, $this->genericCallableRuleHelper->check($node, $scope, sprintf('%s for parameter $%s', $escapedTagName, $escapedParameterName), $phpDocParamType, $functionName, $resolvedPhpDoc->getTemplateTags(), $scope->isInClass() ? $scope->getClassReflection() : null)); if ($phpDocParamTag instanceof ParamOutTag) { if (!$byRefParameters[$parameterName]) { $errors[] = RuleErrorBuilder::message(sprintf('Parameter $%s for PHPDoc tag %s is not passed by reference.', $parameterName, $tagName))->identifier('parameter.notByRef')->build(); } continue; } if (in_array($tagName, ['@param', '@param-out'], \true)) { $isParamSuperType = $nativeParamType->isSuperTypeOf($phpDocParamType); if ($isParamSuperType->no()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for parameter $%s with type %s is incompatible with native type %s.', $tagName, $parameterName, $phpDocParamType->describe(VerbosityLevel::typeOnly()), $nativeParamType->describe(VerbosityLevel::typeOnly())))->identifier('parameter.phpDocType')->build(); } elseif ($isParamSuperType->maybe()) { $errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for parameter $%s with type %s is not subtype of native type %s.', $tagName, $parameterName, $phpDocParamType->describe(VerbosityLevel::typeOnly()), $nativeParamType->describe(VerbosityLevel::typeOnly())))->identifier('parameter.phpDocType'); if ($phpDocParamType instanceof TemplateType) { $errorBuilder->tip(sprintf('Write @template %s of %s to fix this.', $phpDocParamType->getName(), $nativeParamType->describe(VerbosityLevel::typeOnly()))); } $errors[] = $errorBuilder->build(); } } if ($tagName === '@param-closure-this') { $isNonClosure = (new ClosureType())->isSuperTypeOf($nativeParamType)->no(); if ($isNonClosure) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s is for parameter $%s with non-Closure type %s.', $tagName, $parameterName, $nativeParamType->describe(VerbosityLevel::typeOnly())))->identifier('paramClosureThis.nonClosure')->build(); } } } } } if ($resolvedPhpDoc->getReturnTag() !== null) { $phpDocReturnType = $resolvedPhpDoc->getReturnTag()->getType(); if ($this->unresolvableTypeHelper->containsUnresolvableType($phpDocReturnType)) { $errors[] = RuleErrorBuilder::message('PHPDoc tag @return contains unresolvable type.')->identifier('return.unresolvableType')->build(); } else { $nativeReturnType = $this->getNativeReturnType($node, $scope); $isReturnSuperType = $nativeReturnType->isSuperTypeOf($phpDocReturnType); $errors = array_merge($errors, $this->genericObjectTypeCheck->check($phpDocReturnType, 'PHPDoc tag @return contains generic type %s but %s %s is not generic.', 'Generic type %s in PHPDoc tag @return does not specify all template types of %s %s: %s', 'Generic type %s in PHPDoc tag @return specifies %d template types, but %s %s supports only %d: %s', 'Type %s in generic type %s in PHPDoc tag @return is not subtype of template type %s of %s %s.', 'Call-site variance of %s in generic type %s in PHPDoc tag @return is in conflict with %s template type %s of %s %s.', 'Call-site variance of %s in generic type %s in PHPDoc tag @return is redundant, template type %s of %s %s has the same variance.')); if ($isReturnSuperType->no()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @return with type %s is incompatible with native type %s.', $phpDocReturnType->describe(VerbosityLevel::typeOnly()), $nativeReturnType->describe(VerbosityLevel::typeOnly())))->identifier('return.phpDocType')->build(); } elseif ($isReturnSuperType->maybe()) { $errorBuilder = RuleErrorBuilder::message(sprintf('PHPDoc tag @return with type %s is not subtype of native type %s.', $phpDocReturnType->describe(VerbosityLevel::typeOnly()), $nativeReturnType->describe(VerbosityLevel::typeOnly())))->identifier('return.phpDocType'); if ($phpDocReturnType instanceof TemplateType) { $errorBuilder->tip(sprintf('Write @template %s of %s to fix this.', $phpDocReturnType->getName(), $nativeReturnType->describe(VerbosityLevel::typeOnly()))); } $errors[] = $errorBuilder->build(); } $errors = array_merge($errors, $this->genericCallableRuleHelper->check($node, $scope, '@return', $phpDocReturnType, $functionName, $resolvedPhpDoc->getTemplateTags(), $scope->isInClass() ? $scope->getClassReflection() : null)); } } return $errors; } /** * @return Type[] */ private function getNativeParameterTypes(Node\FunctionLike $node, Scope $scope) : array { $nativeParameterTypes = []; foreach ($node->getParams() as $parameter) { $isNullable = $scope->isParameterValueNullable($parameter); if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } $nativeParameterTypes[$parameter->var->name] = $scope->getFunctionType($parameter->type, $isNullable, \false); } return $nativeParameterTypes; } /** * @return array */ private function getByRefParameters(Node\FunctionLike $node) : array { $nativeParameterTypes = []; foreach ($node->getParams() as $parameter) { if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } $nativeParameterTypes[$parameter->var->name] = $parameter->byRef; } return $nativeParameterTypes; } private function getNativeReturnType(Node\FunctionLike $node, Scope $scope) : Type { return $scope->getFunctionType($node->getReturnType(), \false, \false); } } */ final class RequireImplementsDefinitionTraitRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ClassNameCheck */ private $classCheck; /** * @var bool */ private $checkClassCaseSensitivity; public function __construct(ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, bool $checkClassCaseSensitivity) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; } public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->namespacedName === null || !$this->reflectionProvider->hasClass($node->namespacedName->toString())) { return []; } $traitReflection = $this->reflectionProvider->getClass($node->namespacedName->toString()); $implementsTags = $traitReflection->getRequireImplementsTags(); $errors = []; foreach ($implementsTags as $implementsTag) { $type = $implementsTag->getType(); if (!$type instanceof ObjectType) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))->identifier('requireImplements.nonObject')->build(); continue; } $class = $type->getClassName(); $referencedClassReflection = $type->getClassReflection(); if ($referencedClassReflection === null) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains unknown class %s.', $class))->discoveringSymbolsTip()->identifier('class.notFound')->build(); continue; } if (!$referencedClassReflection->isInterface()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements cannot contain non-interface type %s.', $class))->identifier(sprintf('requireImplements.%s', strtolower($referencedClassReflection->getClassTypeDescription())))->build(); } else { $errors = array_merge($errors, $this->classCheck->checkClassNames([new ClassNameNodePair($class, $node)], $this->checkClassCaseSensitivity)); } } return $errors; } } */ final class IncompatibleClassConstantPhpDocTypeRule implements Rule { /** * @var GenericObjectTypeCheck */ private $genericObjectTypeCheck; /** * @var UnresolvableTypeHelper */ private $unresolvableTypeHelper; public function __construct(GenericObjectTypeCheck $genericObjectTypeCheck, \PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $unresolvableTypeHelper) { $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; } public function getNodeType() : string { return Node\Stmt\ClassConst::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $nativeType = null; if ($node->type !== null) { $nativeType = ParserNodeTypeToPHPStanType::resolve($node->type, $scope->getClassReflection()); } $errors = []; foreach ($node->consts as $const) { $constantName = $const->name->toString(); $errors = array_merge($errors, $this->processSingleConstant($scope->getClassReflection(), $nativeType, $constantName)); } return $errors; } /** * @return list */ private function processSingleConstant(ClassReflection $classReflection, ?Type $nativeType, string $constantName) : array { $constantReflection = $classReflection->getConstant($constantName); $phpDocType = $constantReflection->getPhpDocType(); if ($phpDocType === null) { return []; } $errors = []; if ($this->unresolvableTypeHelper->containsUnresolvableType($phpDocType)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @var for constant %s::%s contains unresolvable type.', $constantReflection->getDeclaringClass()->getName(), $constantName))->identifier('classConstant.unresolvableType')->build(); } elseif ($nativeType !== null) { $isSuperType = $nativeType->isSuperTypeOf($phpDocType); if ($isSuperType->no()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @var for constant %s::%s with type %s is incompatible with native type %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $phpDocType->describe(VerbosityLevel::typeOnly()), $nativeType->describe(VerbosityLevel::typeOnly())))->identifier('classConstant.phpDocType')->build(); } elseif ($isSuperType->maybe()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @var for constant %s::%s with type %s is not subtype of native type %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $phpDocType->describe(VerbosityLevel::typeOnly()), $nativeType->describe(VerbosityLevel::typeOnly())))->identifier('classConstant.phpDocType')->build(); } } $className = SprintfHelper::escapeFormatString($constantReflection->getDeclaringClass()->getDisplayName()); $escapedConstantName = SprintfHelper::escapeFormatString($constantName); return array_merge($errors, $this->genericObjectTypeCheck->check($phpDocType, sprintf('PHPDoc tag @var for constant %s::%s contains generic type %%s but %%s %%s is not generic.', $className, $escapedConstantName), sprintf('Generic type %%s in PHPDoc tag @var for constant %s::%s does not specify all template types of %%s %%s: %%s', $className, $escapedConstantName), sprintf('Generic type %%s in PHPDoc tag @var for constant %s::%s specifies %%d template types, but %%s %%s supports only %%d: %%s', $className, $escapedConstantName), sprintf('Type %%s in generic type %%s in PHPDoc tag @var for constant %s::%s is not subtype of template type %%s of %%s %%s.', $className, $escapedConstantName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag @var for constant %s::%s is in conflict with %%s template type %%s of %%s %%s.', $className, $escapedConstantName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag @var for constant %s::%s is redundant, template type %%s of %%s %%s has the same variance.', $className, $escapedConstantName))); } } */ final class FunctionConditionalReturnTypeRule implements Rule { /** * @var ConditionalReturnTypeRuleHelper */ private $helper; public function __construct(\PHPStan\Rules\PhpDoc\ConditionalReturnTypeRuleHelper $helper) { $this->helper = $helper; } public function getNodeType() : string { return InFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $function = $node->getFunctionReflection(); $variants = $function->getVariants(); if (count($variants) !== 1) { return []; } return $this->helper->check($variants[0]); } } */ final class RequireImplementsDefinitionClassRule implements Rule { public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); $implementsTags = $classReflection->getRequireImplementsTags(); if (count($implementsTags) === 0) { return []; } return [RuleErrorBuilder::message('PHPDoc tag @phpstan-require-implements is only valid on trait.')->identifier(sprintf('requireImplements.on%s', $classReflection->getClassTypeDescription()))->build()]; } } typeNodeResolver = $typeNodeResolver; $this->fileTypeMapper = $fileTypeMapper; $this->checkTypeAgainstPhpDocType = $checkTypeAgainstPhpDocType; $this->strictWideningCheck = $strictWideningCheck; } /** * @param VarTag[] $varTags * @param string[] $assignedVariables * @return list */ public function checkVarType(Scope $scope, Node\Expr $var, Node\Expr $expr, array $varTags, array $assignedVariables) : array { $errors = []; if ($var instanceof Expr\Variable && is_string($var->name)) { if (array_key_exists($var->name, $varTags)) { $varTagType = $varTags[$var->name]->getType(); } elseif (count($assignedVariables) === 1 && array_key_exists(0, $varTags)) { $varTagType = $varTags[0]->getType(); } else { return []; } return $this->checkExprType($scope, $expr, $varTagType); } elseif ($var instanceof Expr\List_ || $var instanceof Expr\Array_) { foreach ($var->items as $i => $arrayItem) { if ($arrayItem === null) { continue; } if ($arrayItem->key === null) { $dimExpr = new Node\Scalar\LNumber($i); } else { $dimExpr = $arrayItem->key; } $itemErrors = $this->checkVarType($scope, $arrayItem->value, new GetOffsetValueTypeExpr($expr, $dimExpr), $varTags, $assignedVariables); foreach ($itemErrors as $error) { $errors[] = $error; } } } return $errors; } /** * @return list */ public function checkExprType(Scope $scope, Node\Expr $expr, Type $varTagType) : array { $errors = []; $exprNativeType = $scope->getNativeType($expr); $containsPhpStanType = $this->containsPhpStanType($varTagType); if ($this->shouldVarTagTypeBeReported($scope, $expr, $exprNativeType, $varTagType)) { $verbosity = VerbosityLevel::getRecommendedLevelByType($exprNativeType, $varTagType); $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @var with type %s is not subtype of native type %s.', $varTagType->describe($verbosity), $exprNativeType->describe($verbosity)))->identifier('varTag.nativeType')->build(); } else { $exprType = $scope->getType($expr); if ($this->shouldVarTagTypeBeReported($scope, $expr, $exprType, $varTagType) && ($this->checkTypeAgainstPhpDocType || $containsPhpStanType)) { $verbosity = VerbosityLevel::getRecommendedLevelByType($exprType, $varTagType); $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @var with type %s is not subtype of type %s.', $varTagType->describe($verbosity), $exprType->describe($verbosity)))->identifier('varTag.type')->build(); } } if (count($errors) === 0 && $containsPhpStanType) { $exprType = $scope->getType($expr); if (!$exprType->equals($varTagType)) { $verbosity = VerbosityLevel::getRecommendedLevelByType($exprType, $varTagType); $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @var assumes the expression with type %s is always %s but it\'s error-prone and dangerous.', $exprType->describe($verbosity), $varTagType->describe($verbosity)))->identifier('phpstanApi.varTagAssumption')->build(); } } return $errors; } private function containsPhpStanType(Type $type) : bool { $classReflections = TypeUtils::toBenevolentUnion($type)->getObjectClassReflections(); foreach ($classReflections as $classReflection) { if (!$classReflection->isSubclassOf(Type::class)) { continue; } return \true; } return \false; } private function shouldVarTagTypeBeReported(Scope $scope, Node\Expr $expr, Type $type, Type $varTagType) : bool { if ($expr instanceof Expr\Array_) { if ($expr->items === []) { $type = new ArrayType(new MixedType(), new MixedType()); } return !$this->isAtLeastMaybeSuperTypeOfVarType($scope, $type, $varTagType); } if ($expr instanceof Expr\ConstFetch) { return !$this->isAtLeastMaybeSuperTypeOfVarType($scope, $type, $varTagType); } if ($expr instanceof Node\Scalar) { return !$this->isAtLeastMaybeSuperTypeOfVarType($scope, $type, $varTagType); } if ($expr instanceof Expr\New_) { if ($type instanceof GenericObjectType) { $type = new ObjectType($type->getClassName()); } } return $this->checkType($scope, $type, $varTagType); } private function checkType(Scope $scope, Type $type, Type $varTagType, int $depth = 0) : bool { if ($this->strictWideningCheck) { return !$this->isSuperTypeOfVarType($scope, $type, $varTagType); } if ($type->isConstantArray()->yes()) { if ($type->isIterableAtLeastOnce()->no()) { $type = new ArrayType(new MixedType(), new MixedType()); return !$this->isAtLeastMaybeSuperTypeOfVarType($scope, $type, $varTagType); } } if ($type->isIterable()->yes() && $varTagType->isIterable()->yes()) { if (!$this->isAtLeastMaybeSuperTypeOfVarType($scope, $type, $varTagType)) { return \true; } $innerType = $type->getIterableValueType(); $innerVarTagType = $varTagType->getIterableValueType(); if ($type->equals($innerType) || $varTagType->equals($innerVarTagType)) { return !$this->isSuperTypeOfVarType($scope, $innerType, $innerVarTagType); } return $this->checkType($scope, $innerType, $innerVarTagType, $depth + 1); } if ($depth === 0 && $type->isConstantValue()->yes()) { return !$this->isAtLeastMaybeSuperTypeOfVarType($scope, $type, $varTagType); } return !$this->isSuperTypeOfVarType($scope, $type, $varTagType); } private function isSuperTypeOfVarType(Scope $scope, Type $type, Type $varTagType) : bool { if ($type->isSuperTypeOf($varTagType)->yes()) { return \true; } try { $type = $this->typeNodeResolver->resolve($type->toPhpDocNode(), $this->createNameScope($scope)); } catch (NameScopeAlreadyBeingCreatedException $e) { return \true; } return $type->isSuperTypeOf($varTagType)->yes(); } private function isAtLeastMaybeSuperTypeOfVarType(Scope $scope, Type $type, Type $varTagType) : bool { if (!$type->isSuperTypeOf($varTagType)->no()) { return \true; } try { $type = $this->typeNodeResolver->resolve($type->toPhpDocNode(), $this->createNameScope($scope)); } catch (NameScopeAlreadyBeingCreatedException $e) { return \true; } return !$type->isSuperTypeOf($varTagType)->no(); } /** * @throws NameScopeAlreadyBeingCreatedException */ private function createNameScope(Scope $scope) : NameScope { $function = $scope->getFunction(); return $this->fileTypeMapper->getNameScope($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $function !== null ? $function->getName() : null)->withoutNamespaceAndUses(); } } */ public function check(ParametersAcceptorWithPhpDocs $acceptor) : array { $conditionalTypes = []; $parametersByName = []; foreach ($acceptor->getParameters() as $parameter) { TypeTraverser::map($parameter->getType(), static function (Type $type, callable $traverse) use(&$conditionalTypes) : Type { if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { $conditionalTypes[] = $type; } return $traverse($type); }); if ($parameter->getOutType() !== null) { TypeTraverser::map($parameter->getOutType(), static function (Type $type, callable $traverse) use(&$conditionalTypes) : Type { if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { $conditionalTypes[] = $type; } return $traverse($type); }); } if ($parameter->getClosureThisType() !== null) { TypeTraverser::map($parameter->getClosureThisType(), static function (Type $type, callable $traverse) use(&$conditionalTypes) : Type { if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { $conditionalTypes[] = $type; } return $traverse($type); }); } $parametersByName[$parameter->getName()] = $parameter; } TypeTraverser::map($acceptor->getReturnType(), static function (Type $type, callable $traverse) use(&$conditionalTypes) : Type { if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { $conditionalTypes[] = $type; } return $traverse($type); }); $errors = []; foreach ($conditionalTypes as $conditionalType) { if ($conditionalType instanceof ConditionalType) { $subjectType = $conditionalType->getSubject(); if ($subjectType instanceof StaticType) { continue; } $templateTypes = []; TypeTraverser::map($subjectType, static function (Type $type, callable $traverse) use(&$templateTypes) : Type { if ($type instanceof TemplateType) { $templateTypes[] = $type; return $type; } return $traverse($type); }); if (count($templateTypes) === 0) { $errors[] = RuleErrorBuilder::message(sprintf('Conditional return type uses subject type %s which is not part of PHPDoc @template tags.', $subjectType->describe(VerbosityLevel::typeOnly())))->identifier('conditionalType.subjectNotFound')->build(); continue; } } else { $parameterName = substr($conditionalType->getParameterName(), 1); if (!array_key_exists($parameterName, $parametersByName)) { $errors[] = RuleErrorBuilder::message(sprintf('Conditional return type references unknown parameter $%s.', $parameterName))->identifier('parameter.notFound')->build(); continue; } $subjectType = $parametersByName[$parameterName]->getType(); } $targetType = $conditionalType->getTarget(); $isTargetSuperType = $targetType->isSuperTypeOf($subjectType); if ($isTargetSuperType->maybe()) { continue; } $verbosity = VerbosityLevel::getRecommendedLevelByType($subjectType, $targetType); $errors[] = RuleErrorBuilder::message(sprintf('Condition "%s" in conditional return type is always %s.', sprintf('%s %s %s', $subjectType->describe($verbosity), $conditionalType->isNegated() ? 'is not' : 'is', $targetType->describe($verbosity)), $conditionalType->isNegated() ? $isTargetSuperType->yes() ? 'false' : 'true' : ($isTargetSuperType->yes() ? 'true' : 'false')))->identifier(sprintf('conditionalType.always%s', $conditionalType->isNegated() ? $isTargetSuperType->yes() ? 'False' : 'True' : ($isTargetSuperType->yes() ? 'True' : 'False')))->build(); } return $errors; } } */ final class RequireExtendsDefinitionTraitRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var RequireExtendsCheck */ private $requireExtendsCheck; public function __construct(ReflectionProvider $reflectionProvider, \PHPStan\Rules\PhpDoc\RequireExtendsCheck $requireExtendsCheck) { $this->reflectionProvider = $reflectionProvider; $this->requireExtendsCheck = $requireExtendsCheck; } public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->namespacedName === null || !$this->reflectionProvider->hasClass($node->namespacedName->toString())) { return []; } $traitReflection = $this->reflectionProvider->getClass($node->namespacedName->toString()); $extendsTags = $traitReflection->getRequireExtendsTags(); return $this->requireExtendsCheck->checkExtendsTags($node, $extendsTags); } } templateTypeCheck = $templateTypeCheck; } /** * @param array $functionTemplateTags * * @return list */ public function check(Node $node, Scope $scope, string $location, Type $callableType, ?string $functionName, array $functionTemplateTags, ?ClassReflection $classReflection) : array { $errors = []; TypeTraverser::map($callableType, function (Type $type, callable $traverse) use(&$errors, $node, $scope, $location, $functionName, $functionTemplateTags, $classReflection) { if (!($type instanceof CallableType || $type instanceof ClosureType)) { return $traverse($type); } $typeDescription = $type->describe(VerbosityLevel::precise()); $errors = $this->templateTypeCheck->check($scope, $node, TemplateTypeScope::createWithAnonymousFunction(), $type->getTemplateTags(), sprintf('PHPDoc tag %s template of %s cannot have existing class %%s as its name.', $location, $typeDescription), sprintf('PHPDoc tag %s template of %s cannot have existing type alias %%s as its name.', $location, $typeDescription), sprintf('PHPDoc tag %s template %%s of %s has invalid bound type %%s.', $location, $typeDescription), sprintf('PHPDoc tag %s template %%s of %s with bound type %%s is not supported.', $location, $typeDescription), sprintf('PHPDoc tag %s template %%s of %s has invalid default type %%s.', $location, $typeDescription), sprintf('Default type %%s in PHPDoc tag %s template %%s of %s is not subtype of bound type %%s.', $location, $typeDescription), sprintf('PHPDoc tag %s template %%s of %s does not have a default type but follows an optional template %%s.', $location, $typeDescription)); $templateTags = $type->getTemplateTags(); $classDescription = null; if ($classReflection !== null) { $classDescription = $classReflection->getDisplayName(); } if ($functionName !== null) { $functionDescription = sprintf('function %s', $functionName); if ($classReflection !== null) { $functionDescription = sprintf('method %s::%s', $classDescription, $functionName); } foreach (array_keys($functionTemplateTags) as $name) { if (!isset($templateTags[$name])) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s template %s of %s shadows @template %s for %s.', $location, $name, $typeDescription, $name, $functionDescription))->identifier('callable.shadowTemplate')->build(); } } if ($classReflection !== null) { foreach (array_keys($classReflection->getTemplateTags()) as $name) { if (!isset($templateTags[$name])) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s template %s of %s shadows @template %s for class %s.', $location, $name, $typeDescription, $name, $classDescription))->identifier('callable.shadowTemplate')->build(); } } return $traverse($type); }); return $errors; } } */ final class InvalidPHPStanDocTagRule implements Rule { /** * @var Lexer */ private $phpDocLexer; /** * @var PhpDocParser */ private $phpDocParser; /** * @var bool */ private $checkAllInvalidPhpDocs; private const POSSIBLE_PHPSTAN_TAGS = ['@phpstan-param', '@phpstan-param-out', '@phpstan-var', '@phpstan-extends', '@phpstan-implements', '@phpstan-use', '@phpstan-template', '@phpstan-template-contravariant', '@phpstan-template-covariant', '@phpstan-return', '@phpstan-throws', '@phpstan-ignore', '@phpstan-ignore-next-line', '@phpstan-ignore-line', '@phpstan-method', '@phpstan-pure', '@phpstan-impure', '@phpstan-immutable', '@phpstan-type', '@phpstan-import-type', '@phpstan-property', '@phpstan-property-read', '@phpstan-property-write', '@phpstan-consistent-constructor', '@phpstan-assert', '@phpstan-assert-if-true', '@phpstan-assert-if-false', '@phpstan-self-out', '@phpstan-this-out', '@phpstan-allow-private-mutation', '@phpstan-readonly', '@phpstan-readonly-allow-private-mutation', '@phpstan-require-extends', '@phpstan-require-implements', '@phpstan-param-immediately-invoked-callable', '@phpstan-param-later-invoked-callable', '@phpstan-param-closure-this']; public function __construct(Lexer $phpDocLexer, PhpDocParser $phpDocParser, bool $checkAllInvalidPhpDocs) { $this->phpDocLexer = $phpDocLexer; $this->phpDocParser = $phpDocParser; $this->checkAllInvalidPhpDocs = $checkAllInvalidPhpDocs; } public function getNodeType() : string { return Node::class; } public function processNode(Node $node, Scope $scope) : array { if (!$this->checkAllInvalidPhpDocs) { if (!$node instanceof Node\Stmt\ClassLike && !$node instanceof Node\FunctionLike && !$node instanceof Node\Stmt\Foreach_ && !$node instanceof Node\Stmt\Property && !$node instanceof Node\Expr\Assign && !$node instanceof Node\Expr\AssignRef && !$node instanceof Node\Stmt\ClassConst) { return []; } } else { // mirrored with InvalidPhpDocTagValueRule if ($node instanceof VirtualNode) { return []; } if ($node instanceof Node\Stmt\Expression) { return []; } if ($node instanceof Node\Expr && !$node instanceof Node\Expr\Assign && !$node instanceof Node\Expr\AssignRef) { return []; } } $docComment = $node->getDocComment(); if ($docComment === null) { return []; } $phpDocString = $docComment->getText(); $tokens = new TokenIterator($this->phpDocLexer->tokenize($phpDocString)); $phpDocNode = $this->phpDocParser->parse($tokens); $errors = []; foreach ($phpDocNode->getTags() as $phpDocTag) { if (!str_starts_with($phpDocTag->name, '@phpstan-') || in_array($phpDocTag->name, self::POSSIBLE_PHPSTAN_TAGS, \true)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Unknown PHPDoc tag: %s', $phpDocTag->name))->line(\PHPStan\Rules\PhpDoc\PhpDocLineHelper::detectLine($node, $phpDocTag))->identifier('phpDoc.phpstanTag')->build(); } return $errors; } } */ final class RequireExtendsDefinitionClassRule implements Rule { /** * @var RequireExtendsCheck */ private $requireExtendsCheck; public function __construct(\PHPStan\Rules\PhpDoc\RequireExtendsCheck $requireExtendsCheck) { $this->requireExtendsCheck = $requireExtendsCheck; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); $extendsTags = $classReflection->getRequireExtendsTags(); if (count($extendsTags) === 0) { return []; } if (!$classReflection->isInterface()) { return [RuleErrorBuilder::message('PHPDoc tag @phpstan-require-extends is only valid on trait or interface.')->identifier(sprintf('requireExtends.on%s', $classReflection->getClassTypeDescription()))->build()]; } return $this->requireExtendsCheck->checkExtendsTags($node, $extendsTags); } } */ final class InvalidThrowsPhpDocValueRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; public function __construct(FileTypeMapper $fileTypeMapper) { $this->fileTypeMapper = $fileTypeMapper; } public function getNodeType() : string { return Node\Stmt::class; } public function processNode(Node $node, Scope $scope) : array { if ($node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\ClassMethod) { return []; // is handled by virtual nodes } $docComment = $node->getDocComment(); if ($docComment === null) { return []; } $functionName = null; if ($scope->getFunction() !== null) { $functionName = $scope->getFunction()->getName(); } $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $functionName, $docComment->getText()); if ($resolvedPhpDoc->getThrowsTag() === null) { return []; } $phpDocThrowsType = $resolvedPhpDoc->getThrowsTag()->getType(); if ($phpDocThrowsType->isVoid()->yes()) { return []; } if ($this->isThrowsValid($phpDocThrowsType)) { return []; } return [RuleErrorBuilder::message(sprintf('PHPDoc tag @throws with type %s is not subtype of Throwable', $phpDocThrowsType->describe(VerbosityLevel::typeOnly())))->identifier('throws.notThrowable')->build()]; } private function isThrowsValid(Type $phpDocThrowsType) : bool { $throwType = new ObjectType(Throwable::class); if ($phpDocThrowsType instanceof UnionType) { foreach ($phpDocThrowsType->getTypes() as $innerType) { if (!$this->isThrowsValid($innerType)) { return \false; } } return \true; } $toIntersectWith = []; foreach ($phpDocThrowsType->getObjectClassReflections() as $classReflection) { if (!$classReflection->isInterface()) { continue; } foreach ($classReflection->getRequireExtendsTags() as $requireExtendsTag) { $toIntersectWith[] = $requireExtendsTag->getType(); } } return $throwType->isSuperTypeOf(TypeCombinator::intersect($phpDocThrowsType, ...$toIntersectWith))->yes(); } } isExplicit()) { $containsUnresolvable = \true; return $type; } return $traverse($type); }); return $containsUnresolvable; } } getAttribute('startLine'); $phpDoc = $node->getDocComment(); if ($phpDocTagLine === null || $phpDoc === null) { return $node->getLine(); } return $phpDoc->getStartLine() + $phpDocTagLine - 1; } } */ final class VarTagChangedExpressionTypeRule implements Rule { /** * @var VarTagTypeRuleHelper */ private $varTagTypeRuleHelper; public function __construct(\PHPStan\Rules\PhpDoc\VarTagTypeRuleHelper $varTagTypeRuleHelper) { $this->varTagTypeRuleHelper = $varTagTypeRuleHelper; } public function getNodeType() : string { return VarTagChangedExpressionTypeNode::class; } public function processNode(Node $node, Scope $scope) : array { return $this->varTagTypeRuleHelper->checkExprType($scope, $node->getExpr(), $node->getVarTag()->getType()); } } */ final class IncompatibleSelfOutTypeRule implements Rule { /** * @var UnresolvableTypeHelper */ private $unresolvableTypeHelper; /** * @var GenericObjectTypeCheck */ private $genericObjectTypeCheck; public function __construct(\PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $unresolvableTypeHelper, GenericObjectTypeCheck $genericObjectTypeCheck) { $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->genericObjectTypeCheck = $genericObjectTypeCheck; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); $selfOutType = $method->getSelfOutType(); if ($selfOutType === null) { return []; } $classReflection = $method->getDeclaringClass(); $classType = new ObjectType($classReflection->getName(), null, $classReflection); $errors = []; if (!$classType->isSuperTypeOf($selfOutType)->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('Self-out type %s of method %s::%s is not subtype of %s.', $selfOutType->describe(VerbosityLevel::precise()), $classReflection->getDisplayName(), $method->getName(), $classType->describe(VerbosityLevel::precise())))->identifier('selfOut.type')->build(); } if ($method->isStatic()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-self-out is not supported above static method %s::%s().', $classReflection->getName(), $method->getName()))->identifier('selfOut.static')->build(); } if ($this->unresolvableTypeHelper->containsUnresolvableType($selfOutType)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-self-out for method %s::%s() contains unresolvable type.', $classReflection->getDisplayName(), $method->getName()))->identifier('selfOut.unresolvableType')->build(); } $escapedTagName = SprintfHelper::escapeFormatString('@phpstan-self-out'); return array_merge($errors, $this->genericObjectTypeCheck->check($selfOutType, sprintf('PHPDoc tag %s contains generic type %%s but %%s %%s is not generic.', $escapedTagName), sprintf('Generic type %%s in PHPDoc tag %s does not specify all template types of %%s %%s: %%s', $escapedTagName), sprintf('Generic type %%s in PHPDoc tag %s specifies %%d template types, but %%s %%s supports only %%d: %%s', $escapedTagName), sprintf('Type %%s in generic type %%s in PHPDoc tag %s is not subtype of template type %%s of %%s %%s.', $escapedTagName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag %s is in conflict with %%s template type %%s of %%s %%s.', $escapedTagName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag %s is redundant, template type %%s of %%s %%s has the same variance.', $escapedTagName))); } } */ final class FunctionAssertRule implements Rule { /** * @var AssertRuleHelper */ private $helper; public function __construct(\PHPStan\Rules\PhpDoc\AssertRuleHelper $helper) { $this->helper = $helper; } public function getNodeType() : string { return InFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $function = $node->getFunctionReflection(); $variants = $function->getVariants(); if (count($variants) !== 1) { return []; } return $this->helper->check($node->getOriginalNode(), $function, $variants[0]); } } */ final class InvalidPhpDocVarTagTypeRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ClassNameCheck */ private $classCheck; /** * @var GenericObjectTypeCheck */ private $genericObjectTypeCheck; /** * @var MissingTypehintCheck */ private $missingTypehintCheck; /** * @var UnresolvableTypeHelper */ private $unresolvableTypeHelper; /** * @var bool */ private $checkClassCaseSensitivity; /** * @var bool */ private $checkMissingVarTagTypehint; public function __construct(FileTypeMapper $fileTypeMapper, ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, GenericObjectTypeCheck $genericObjectTypeCheck, MissingTypehintCheck $missingTypehintCheck, \PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $unresolvableTypeHelper, bool $checkClassCaseSensitivity, bool $checkMissingVarTagTypehint) { $this->fileTypeMapper = $fileTypeMapper; $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkMissingVarTagTypehint = $checkMissingVarTagTypehint; } public function getNodeType() : string { return Node\Stmt::class; } public function processNode(Node $node, Scope $scope) : array { if ($node instanceof Node\Stmt\Property || $node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Stmt\ClassConst || $node instanceof Node\Stmt\Const_) { return []; } $docComment = $node->getDocComment(); if ($docComment === null) { return []; } $function = $scope->getFunction(); $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $function !== null ? $function->getName() : null, $docComment->getText()); $errors = []; foreach ($resolvedPhpDoc->getVarTags() as $name => $varTag) { $varTagType = $varTag->getType(); $identifier = 'PHPDoc tag @var'; if (is_string($name)) { $identifier .= sprintf(' for variable $%s', $name); } if ($this->unresolvableTypeHelper->containsUnresolvableType($varTagType)) { $errors[] = RuleErrorBuilder::message(sprintf('%s contains unresolvable type.', $identifier))->line($docComment->getStartLine())->identifier('varTag.unresolvableType')->build(); continue; } if ($this->checkMissingVarTagTypehint) { foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($varTagType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('%s has no value type specified in iterable type %s.', $identifier, $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } } $escapedIdentifier = SprintfHelper::escapeFormatString($identifier); $errors = array_merge($errors, $this->genericObjectTypeCheck->check($varTagType, sprintf('%s contains generic type %%s but %%s %%s is not generic.', $escapedIdentifier), sprintf('Generic type %%s in %s does not specify all template types of %%s %%s: %%s', $escapedIdentifier), sprintf('Generic type %%s in %s specifies %%d template types, but %%s %%s supports only %%d: %%s', $escapedIdentifier), sprintf('Type %%s in generic type %%s in %s is not subtype of template type %%s of %%s %%s.', $escapedIdentifier), sprintf('Call-site variance of %%s in generic type %%s in %s is in conflict with %%s template type %%s of %%s %%s.', $escapedIdentifier), sprintf('Call-site variance of %%s in generic type %%s in %s is redundant, template type %%s of %%s %%s has the same variance.', $escapedIdentifier))); foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($varTagType) as [$innerName, $genericTypeNames]) { $errors[] = RuleErrorBuilder::message(sprintf('%s contains generic %s but does not specify its types: %s', $identifier, $innerName, $genericTypeNames))->identifier('missingType.generics')->build(); } $referencedClasses = $varTagType->getReferencedClasses(); foreach ($referencedClasses as $referencedClass) { if ($this->reflectionProvider->hasClass($referencedClass)) { if ($this->reflectionProvider->getClass($referencedClass)->isTrait()) { $errors[] = RuleErrorBuilder::message(sprintf(sprintf('%s has invalid type %%s.', $identifier), $referencedClass))->identifier('varTag.trait')->build(); } continue; } if ($scope->isInClassExists($referencedClass)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf(sprintf('%s contains unknown class %%s.', $identifier), $referencedClass))->identifier('class.notFound')->discoveringSymbolsTip()->build(); } $errors = array_merge($errors, $this->classCheck->checkClassNames(array_map(static function (string $class) use($node) : ClassNameNodePair { return new ClassNameNodePair($class, $node); }, $referencedClasses), $this->checkClassCaseSensitivity)); } return $errors; } } */ final class WrongVariableNameInVarTagRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; /** * @var VarTagTypeRuleHelper */ private $varTagTypeRuleHelper; /** * @var bool */ private $checkTypeAgainstNativeType; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\PhpDoc\VarTagTypeRuleHelper $varTagTypeRuleHelper, bool $checkTypeAgainstNativeType) { $this->fileTypeMapper = $fileTypeMapper; $this->varTagTypeRuleHelper = $varTagTypeRuleHelper; $this->checkTypeAgainstNativeType = $checkTypeAgainstNativeType; } public function getNodeType() : string { return Node\Stmt::class; } public function processNode(Node $node, Scope $scope) : array { if ($node instanceof Node\Stmt\Property || $node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Stmt\ClassConst || $node instanceof Node\Stmt\Const_ || $node instanceof VirtualNode && !$node instanceof InFunctionNode && !$node instanceof InClassMethodNode && !$node instanceof InClassNode) { return []; } $varTags = []; $function = $scope->getFunction(); foreach ($node->getComments() as $comment) { if (!$comment instanceof Doc) { continue; } $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $function !== null ? $function->getName() : null, $comment->getText()); foreach ($resolvedPhpDoc->getVarTags() as $key => $varTag) { $varTags[$key] = $varTag; } } if (count($varTags) === 0) { return []; } if ($node instanceof Node\Stmt\Foreach_) { return $this->processForeach($scope, $node->expr, $node->keyVar, $node->valueVar, $varTags); } if ($node instanceof Node\Stmt\Static_) { return $this->processStatic($scope, $node->vars, $varTags); } if ($node instanceof Node\Stmt\Expression) { return $this->processExpression($scope, $node->expr, $varTags); } if ($node instanceof Node\Stmt\Throw_ || $node instanceof Node\Stmt\Return_) { return $this->processStmt($scope, $varTags, $node->expr); } if ($node instanceof Node\Stmt\Global_) { return $this->processGlobal($scope, $node, $varTags); } if ($node instanceof InClassNode || $node instanceof InClassMethodNode || $node instanceof InFunctionNode) { $description = 'a function'; $originalNode = $node->getOriginalNode(); if ($originalNode instanceof Node\Stmt\Interface_) { $description = 'an interface'; } elseif ($originalNode instanceof Node\Stmt\Class_) { $description = 'a class'; } elseif ($originalNode instanceof Node\Stmt\Enum_) { $description = 'an enum'; } elseif ($originalNode instanceof Node\Stmt\Trait_) { throw new ShouldNotHappenException(); } elseif ($originalNode instanceof Node\Stmt\ClassMethod) { $description = 'a method'; } return [RuleErrorBuilder::message(sprintf('PHPDoc tag @var above %s has no effect.', $description))->identifier('varTag.misplaced')->build()]; } return $this->processStmt($scope, $varTags, null); } /** * @param VarTag[] $varTags * @return list */ private function processAssign(Scope $scope, Node\Expr $var, Node\Expr $expr, array $varTags) : array { $errors = []; $hasMultipleMessage = \false; $assignedVariables = $this->getAssignedVariables($var); if ($this->checkTypeAgainstNativeType) { foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $var, $expr, $varTags, $assignedVariables) as $error) { $errors[] = $error; } } foreach (array_keys($varTags) as $key) { if (is_int($key)) { if (count($varTags) !== 1) { if (!$hasMultipleMessage) { $errors[] = RuleErrorBuilder::message('Multiple PHPDoc @var tags above single variable assignment are not supported.')->identifier('varTag.multipleTags')->build(); $hasMultipleMessage = \true; } } elseif (count($assignedVariables) !== 1) { $errors[] = RuleErrorBuilder::message('PHPDoc tag @var above assignment does not specify variable name.')->identifier('varTag.noVariable')->build(); } continue; } if (!$scope->hasVariableType($key)->no()) { continue; } if (in_array($key, $assignedVariables, \true)) { continue; } if (count($assignedVariables) === 1 && count($varTags) === 1) { $errors[] = RuleErrorBuilder::message(sprintf('Variable $%s in PHPDoc tag @var does not match assigned variable $%s.', $key, $assignedVariables[0]))->identifier('varTag.differentVariable')->build(); } else { $errors[] = RuleErrorBuilder::message(sprintf('Variable $%s in PHPDoc tag @var does not exist.', $key))->identifier('varTag.variableNotFound')->build(); } } return $errors; } /** * @return string[] */ private function getAssignedVariables(Expr $expr) : array { if ($expr instanceof Expr\Variable) { if (is_string($expr->name)) { return [$expr->name]; } return []; } if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) { $names = []; foreach ($expr->items as $item) { if ($item === null) { continue; } $names = array_merge($names, $this->getAssignedVariables($item->value)); } return $names; } return []; } /** * @param VarTag[] $varTags * @return list */ private function processForeach(Scope $scope, Node\Expr $iterateeExpr, ?Node\Expr $keyVar, Node\Expr $valueVar, array $varTags) : array { $variableNames = []; if ($iterateeExpr instanceof Node\Expr\Variable && is_string($iterateeExpr->name)) { $variableNames[] = $iterateeExpr->name; } if ($keyVar instanceof Node\Expr\Variable && is_string($keyVar->name)) { $variableNames[] = $keyVar->name; } $variableNames = array_merge($variableNames, $this->getAssignedVariables($valueVar)); $errors = []; foreach (array_keys($varTags) as $name) { if (is_int($name)) { if (count($variableNames) === 1) { continue; } $errors[] = RuleErrorBuilder::message('PHPDoc tag @var above foreach loop does not specify variable name.')->identifier('varTag.noVariable')->build(); continue; } if (in_array($name, $variableNames, \true)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Variable $%s in PHPDoc tag @var does not match any variable in the foreach loop: %s', $name, implode(', ', array_map(static function (string $name) : string { return sprintf('$%s', $name); }, $variableNames))))->identifier('varTag.differentVariable')->build(); } if ($this->checkTypeAgainstNativeType) { foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $iterateeExpr, $iterateeExpr, $varTags, $variableNames) as $error) { $errors[] = $error; } if ($keyVar !== null) { foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $keyVar, new GetIterableKeyTypeExpr($iterateeExpr), $varTags, $variableNames) as $error) { $errors[] = $error; } } foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $valueVar, new GetIterableValueTypeExpr($iterateeExpr), $varTags, $variableNames) as $error) { $errors[] = $error; } } return $errors; } /** * @param VarTag[] $varTags * @return list */ private function processExpression(Scope $scope, Expr $expr, array $varTags) : array { if ($expr instanceof Node\Expr\Assign || $expr instanceof Node\Expr\AssignRef) { return $this->processAssign($scope, $expr->var, $expr->expr, $varTags); } return $this->processStmt($scope, $varTags, null); } /** * @param Node\Stmt\StaticVar[] $vars * @param VarTag[] $varTags * @return list */ private function processStatic(Scope $scope, array $vars, array $varTags) : array { $variableNames = []; foreach ($vars as $var) { if (!is_string($var->var->name)) { continue; } $variableNames[] = $var->var->name; } $errors = []; foreach (array_keys($varTags) as $name) { if (is_int($name)) { if (count($vars) === 1) { continue; } $errors[] = RuleErrorBuilder::message('PHPDoc tag @var above multiple static variables does not specify variable name.')->identifier('varTag.noVariable')->build(); continue; } if (in_array($name, $variableNames, \true)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Variable $%s in PHPDoc tag @var does not match any static variable: %s', $name, implode(', ', array_map(static function (string $name) : string { return sprintf('$%s', $name); }, $variableNames))))->identifier('varTag.differentVariable')->build(); } if ($this->checkTypeAgainstNativeType) { foreach ($vars as $var) { if ($var->default === null) { continue; } foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $var->var, $var->default, $varTags, $variableNames) as $error) { $errors[] = $error; } } } return $errors; } /** * @param VarTag[] $varTags * @return list */ private function processStmt(Scope $scope, array $varTags, ?Expr $defaultExpr) : array { $errors = []; $variableLessVarTags = []; foreach ($varTags as $name => $varTag) { if (is_int($name)) { $variableLessVarTags[] = $varTag; continue; } if (!$scope->hasVariableType($name)->no()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Variable $%s in PHPDoc tag @var does not exist.', $name))->identifier('varTag.variableNotFound')->build(); } if (count($variableLessVarTags) !== 1 || $defaultExpr === null) { if (count($variableLessVarTags) > 0) { $errors[] = RuleErrorBuilder::message('PHPDoc tag @var does not specify variable name.')->identifier('varTag.noVariable')->build(); } } return $errors; } /** * @param VarTag[] $varTags * @return list */ private function processGlobal(Scope $scope, Node\Stmt\Global_ $node, array $varTags) : array { $variableNames = []; foreach ($node->vars as $var) { if (!$var instanceof Expr\Variable) { continue; } if (!is_string($var->name)) { continue; } $variableNames[$var->name] = \true; } $errors = []; foreach (array_keys($varTags) as $name) { if (is_int($name)) { if (count($variableNames) === 1) { continue; } $errors[] = RuleErrorBuilder::message('PHPDoc tag @var above multiple global variables does not specify variable name.')->identifier('varTag.noVariable')->build(); continue; } if (isset($variableNames[$name])) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Variable $%s in PHPDoc tag @var does not match any global variable: %s', $name, implode(', ', array_map(static function (string $name) : string { return sprintf('$%s', $name); }, array_keys($variableNames)))))->identifier('varTag.differentVariable')->build(); } return $errors; } } */ final class IncompatibleParamImmediatelyInvokedCallableRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; public function __construct(FileTypeMapper $fileTypeMapper) { $this->fileTypeMapper = $fileTypeMapper; } public function getNodeType() : string { return FunctionLike::class; } public function processNode(Node $node, Scope $scope) : array { if ($node instanceof Node\Stmt\ClassMethod) { $functionName = $node->name->name; } elseif ($node instanceof Node\Stmt\Function_) { $functionName = trim($scope->getNamespace() . '\\' . $node->name->name, '\\'); } else { return []; } $docComment = $node->getDocComment(); if ($docComment === null) { return []; } $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $functionName, $docComment->getText()); $nativeParameterTypes = []; foreach ($node->getParams() as $parameter) { if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } $nativeParameterTypes[$parameter->var->name] = $scope->getFunctionType($parameter->type, $scope->isParameterValueNullable($parameter), \false); } $errors = []; foreach ($resolvedPhpDoc->getParamsImmediatelyInvokedCallable() as $parameterName => $immediately) { $tagName = $immediately ? '@param-immediately-invoked-callable' : '@param-later-invoked-callable'; if (!isset($nativeParameterTypes[$parameterName])) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s references unknown parameter: $%s', $tagName, $parameterName))->identifier('parameter.notFound')->build(); } elseif ($nativeParameterTypes[$parameterName]->isCallable()->no()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s is for parameter $%s with non-callable type %s.', $tagName, $parameterName, $nativeParameterTypes[$parameterName]->describe(VerbosityLevel::typeOnly())))->identifier(sprintf('%s.nonCallable', $immediately ? 'paramImmediatelyInvokedCallable' : 'paramLaterInvokedCallable'))->build(); } } return $errors; } } initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflectionProvider = $reflectionProvider; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->classCheck = $classCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->absentTypeChecks = $absentTypeChecks; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkMissingTypehints = $checkMissingTypehints; } /** * @return list * @param Function_|ClassMethod $node * @param ExtendedMethodReflection|FunctionReflection $reflection */ public function check($node, $reflection, ParametersAcceptor $acceptor) : array { $parametersByName = []; foreach ($acceptor->getParameters() as $parameter) { $parametersByName[$parameter->getName()] = $parameter->getType(); } if ($reflection instanceof ExtendedMethodReflection && !$reflection->isStatic()) { $class = $reflection->getDeclaringClass(); $parametersByName['this'] = new ObjectType($class->getName(), null, $class); } $context = InitializerExprContext::createEmpty(); $errors = []; foreach ($reflection->getAsserts()->getAll() as $assert) { $parameterName = substr($assert->getParameter()->getParameterName(), 1); if (!array_key_exists($parameterName, $parametersByName)) { $errors[] = RuleErrorBuilder::message(sprintf('Assert references unknown parameter $%s.', $parameterName))->identifier('parameter.notFound')->build(); continue; } if (!$assert->isExplicit()) { continue; } $assertedExpr = $assert->getParameter()->getExpr(new TypeExpr($parametersByName[$parameterName])); $assertedExprType = $this->initializerExprTypeResolver->getType($assertedExpr, $context); $assertedExprString = $assert->getParameter()->describe(); if ($assertedExprType instanceof ErrorType) { if ($this->absentTypeChecks) { $errors[] = RuleErrorBuilder::message(sprintf('Assert references unknown %s.', $assertedExprString))->identifier('assert.unknownExpr')->build(); } continue; } $assertedType = $assert->getType(); $tagName = [AssertTag::NULL => '@phpstan-assert', AssertTag::IF_TRUE => '@phpstan-assert-if-true', AssertTag::IF_FALSE => '@phpstan-assert-if-false'][$assert->getIf()]; if ($this->absentTypeChecks) { if ($this->unresolvableTypeHelper->containsUnresolvableType($assertedType)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for %s contains unresolvable type.', $tagName, $assertedExprString))->identifier('assert.unresolvableType')->build(); continue; } } $isSuperType = $assertedType->isSuperTypeOf($assertedExprType); if (!$isSuperType->maybe()) { if ($assert->isNegated() ? $isSuperType->yes() : $isSuperType->no()) { $errors[] = RuleErrorBuilder::message(sprintf('Asserted %stype %s for %s with type %s can never happen.', $assert->isNegated() ? 'negated ' : '', $assertedType->describe(VerbosityLevel::precise()), $assertedExprString, $assertedExprType->describe(VerbosityLevel::precise())))->identifier('assert.impossibleType')->build(); } elseif ($assert->isNegated() ? $isSuperType->no() : $isSuperType->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('Asserted %stype %s for %s with type %s does not narrow down the type.', $assert->isNegated() ? 'negated ' : '', $assertedType->describe(VerbosityLevel::precise()), $assertedExprString, $assertedExprType->describe(VerbosityLevel::precise())))->identifier('assert.alreadyNarrowedType')->build(); } } if (!$this->absentTypeChecks) { continue; } foreach ($assertedType->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for %s contains unknown class %s.', $tagName, $assertedExprString, $class))->identifier('class.notFound')->build(); continue; } $classReflection = $this->reflectionProvider->getClass($class); if ($classReflection->isTrait()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for %s contains invalid type %s.', $tagName, $assertedExprString, $class))->identifier('assert.trait')->build(); continue; } $errors = array_merge($errors, $this->classCheck->checkClassNames([new ClassNameNodePair($class, $node)], $this->checkClassCaseSensitivity)); } $errors = array_merge($errors, $this->genericObjectTypeCheck->check($assertedType, sprintf('PHPDoc tag %s for %s contains generic type %%s but %%s %%s is not generic.', $tagName, $assertedExprString), sprintf('Generic type %%s in PHPDoc tag %s for %s does not specify all template types of %%s %%s: %%s', $tagName, $assertedExprString), sprintf('Generic type %%s in PHPDoc tag %s for %s specifies %%d template types, but %%s %%s supports only %%d: %%s', $tagName, $assertedExprString), sprintf('Type %%s in generic type %%s in PHPDoc tag %s for %s is not subtype of template type %%s of %%s %%s.', $tagName, $assertedExprString), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag %s for %s is in conflict with %%s template type %%s of %%s %%s.', $tagName, $assertedExprString), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag %s for %s is redundant, template type %%s of %%s %%s has the same variance.', $tagName, $assertedExprString))); if (!$this->checkMissingTypehints) { continue; } foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($assertedType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for %s has no value type specified in iterable type %s.', $tagName, $assertedExprString, $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($assertedType) as [$innerName, $genericTypeNames]) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for %s contains generic %s but does not specify its types: %s', $tagName, $assertedExprString, $innerName, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($assertedType) as $callableType) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for %s has no signature specified for %s.', $tagName, $assertedExprString, $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } } return $errors; } } */ final class MethodAssertRule implements Rule { /** * @var AssertRuleHelper */ private $helper; public function __construct(\PHPStan\Rules\PhpDoc\AssertRuleHelper $helper) { $this->helper = $helper; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); $variants = $method->getVariants(); if (count($variants) !== 1) { return []; } return $this->helper->check($node->getOriginalNode(), $method, $variants[0]); } } */ final class MethodConditionalReturnTypeRule implements Rule { /** * @var ConditionalReturnTypeRuleHelper */ private $helper; public function __construct(\PHPStan\Rules\PhpDoc\ConditionalReturnTypeRuleHelper $helper) { $this->helper = $helper; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); $variants = $method->getVariants(); if (count($variants) !== 1) { return []; } return $this->helper->check($variants[0]); } } */ final class IncompatiblePropertyPhpDocTypeRule implements Rule { /** * @var GenericObjectTypeCheck */ private $genericObjectTypeCheck; /** * @var UnresolvableTypeHelper */ private $unresolvableTypeHelper; /** * @var GenericCallableRuleHelper */ private $genericCallableRuleHelper; public function __construct(GenericObjectTypeCheck $genericObjectTypeCheck, \PHPStan\Rules\PhpDoc\UnresolvableTypeHelper $unresolvableTypeHelper, \PHPStan\Rules\PhpDoc\GenericCallableRuleHelper $genericCallableRuleHelper) { $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->genericCallableRuleHelper = $genericCallableRuleHelper; } public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { $phpDocType = $node->getPhpDocType(); if ($phpDocType === null) { return []; } $propertyName = $node->getName(); $description = 'PHPDoc tag @var'; if ($node->isPromoted()) { $description = 'PHPDoc type'; } $classReflection = $node->getClassReflection(); $messages = []; if ($this->unresolvableTypeHelper->containsUnresolvableType($phpDocType)) { $messages[] = RuleErrorBuilder::message(sprintf('%s for property %s::$%s contains unresolvable type.', $description, $classReflection->getDisplayName(), $propertyName))->identifier('property.unresolvableType')->build(); } $nativeType = ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection); $isSuperType = $nativeType->isSuperTypeOf($phpDocType); if ($isSuperType->no()) { $messages[] = RuleErrorBuilder::message(sprintf('%s for property %s::$%s with type %s is incompatible with native type %s.', $description, $classReflection->getDisplayName(), $propertyName, $phpDocType->describe(VerbosityLevel::typeOnly()), $nativeType->describe(VerbosityLevel::typeOnly())))->identifier('property.phpDocType')->build(); } elseif ($isSuperType->maybe()) { $errorBuilder = RuleErrorBuilder::message(sprintf('%s for property %s::$%s with type %s is not subtype of native type %s.', $description, $classReflection->getDisplayName(), $propertyName, $phpDocType->describe(VerbosityLevel::typeOnly()), $nativeType->describe(VerbosityLevel::typeOnly())))->identifier('property.phpDocType'); if ($phpDocType instanceof TemplateType) { $errorBuilder->tip(sprintf('Write @template %s of %s to fix this.', $phpDocType->getName(), $nativeType->describe(VerbosityLevel::typeOnly()))); } $messages[] = $errorBuilder->build(); } $className = SprintfHelper::escapeFormatString($classReflection->getDisplayName()); $escapedPropertyName = SprintfHelper::escapeFormatString($propertyName); if ($node->isPromoted() === \false) { $messages = array_merge($messages, $this->genericCallableRuleHelper->check($node, $scope, '@var', $phpDocType, null, [], $classReflection)); } $messages = array_merge($messages, $this->genericObjectTypeCheck->check($phpDocType, sprintf('%s for property %s::$%s contains generic type %%s but %%s %%s is not generic.', $description, $className, $escapedPropertyName), sprintf('Generic type %%s in %s for property %s::$%s does not specify all template types of %%s %%s: %%s', $description, $className, $escapedPropertyName), sprintf('Generic type %%s in %s for property %s::$%s specifies %%d template types, but %%s %%s supports only %%d: %%s', $description, $className, $escapedPropertyName), sprintf('Type %%s in generic type %%s in %s for property %s::$%s is not subtype of template type %%s of %%s %%s.', $description, $className, $escapedPropertyName), sprintf('Call-site variance of %%s in generic type %%s in %s for property %s::$%s is in conflict with %%s template type %%s of %%s %%s.', $description, $className, $escapedPropertyName), sprintf('Call-site variance of %%s in generic type %%s in %s for property %s::$%s is redundant, template type %%s of %%s %%s has the same variance.', $description, $className, $escapedPropertyName))); return $messages; } } message; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } } message; } public function getLine() : int { return $this->line; } public function getTip() : string { return $this->tip; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } } message; } public function getLine() : int { return $this->line; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getTip() : string { return $this->tip; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getTip() : string { return $this->tip; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getTip() : string { return $this->tip; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } } message; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } } message; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } } message; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } } message; } public function getLine() : int { return $this->line; } public function getTip() : string { return $this->tip; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } } message; } public function getLine() : int { return $this->line; } public function getTip() : string { return $this->tip; } } message; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getIdentifier() : string { return $this->identifier; } } message; } public function getLine() : int { return $this->line; } public function getTip() : string { return $this->tip; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getIdentifier() : string { return $this->identifier; } } message; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getLine() : int { return $this->line; } public function getTip() : string { return $this->tip; } public function getIdentifier() : string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } } message; } public function getTip() : string { return $this->tip; } } message; } public function getFile() : string { return $this->file; } public function getFileDescription() : string { return $this->fileDescription; } public function getTip() : string { return $this->tip; } } message; } public function getIdentifier() : string { return $this->identifier; } } */ public function getNodeType() : string; /** * @param TNodeType $node * @return (string|RuleError)[] errors */ public function processNode(Node $node, Scope $scope) : array; } */ final class EnumCaseAttributesRule implements Rule { /** * @var AttributesCheck */ private $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType() : string { return Node\Stmt\EnumCase::class; } public function processNode(Node $node, Scope $scope) : array { return $this->attributesCheck->check($scope, $node->attrGroups, Attribute::TARGET_CLASS_CONSTANT, 'class constant'); } } */ final class AllowedSubTypesRule implements Rule { public function getNodeType() : string { return InClassNode::class; } /** * @param InClassNode $node */ public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); $className = $classReflection->getName(); $parents = array_values($classReflection->getImmediateInterfaces()); $parentClass = $classReflection->getParentClass(); if ($parentClass !== null) { $parents[] = $parentClass; } $messages = []; foreach ($parents as $parentReflection) { $allowedSubTypes = $parentReflection->getAllowedSubTypes(); if ($allowedSubTypes === null) { continue; } foreach ($allowedSubTypes as $allowedSubType) { if (!$allowedSubType->isObject()->yes()) { continue; } if ($allowedSubType->getObjectClassNames() === [$className]) { continue 2; } } $identifierType = strtolower($classReflection->getClassTypeDescription()); $messages[] = RuleErrorBuilder::message(sprintf('Type %s is not allowed to be a subtype of %s.', $className, $parentReflection->getName()))->identifier(sprintf('%s.disallowedSubtype', $identifierType))->build(); } return $messages; } } */ final class DuplicateClassDeclarationRule implements Rule { /** * @var Reflector */ private $reflector; /** * @var RelativePathHelper */ private $relativePathHelper; public function __construct(Reflector $reflector, RelativePathHelper $relativePathHelper) { $this->reflector = $reflector; $this->relativePathHelper = $relativePathHelper; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $thisClass = $node->getClassReflection(); $className = $thisClass->getName(); $allClasses = $this->reflector->reflectAllClasses(); $filteredClasses = []; foreach ($allClasses as $reflectionClass) { if ($reflectionClass->getName() !== $className) { continue; } $filteredClasses[] = $reflectionClass; } if (count($filteredClasses) < 2) { return []; } $filteredClasses = array_filter($filteredClasses, static function (ReflectionClass $class) use($thisClass) { return $class->getStartLine() !== $thisClass->getNativeReflection()->getStartLine(); }); $identifierType = strtolower($thisClass->getClassTypeDescription()); return [RuleErrorBuilder::message(sprintf("Class %s declared multiple times:\n%s", $thisClass->getDisplayName(), implode("\n", array_map(function (ReflectionClass $class) { return sprintf('- %s:%d', $this->relativePathHelper->getRelativePath($class->getFileName() ?? 'unknown'), $class->getStartLine()); }, $filteredClasses))))->identifier(sprintf('%s.duplicate', $identifierType))->build()]; } } */ final class ExistingClassesInInterfaceExtendsRule implements Rule { /** * @var ClassNameCheck */ private $classCheck; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Interface_::class; } public function processNode(Node $node, Scope $scope) : array { $messages = $this->classCheck->checkClassNames(array_map(static function (Node\Name $interfaceName) : ClassNameNodePair { return new ClassNameNodePair((string) $interfaceName, $interfaceName); }, $node->extends)); $currentInterfaceName = (string) $node->namespacedName; foreach ($node->extends as $extends) { $extendedInterfaceName = (string) $extends; if (!$this->reflectionProvider->hasClass($extendedInterfaceName)) { if (!$scope->isInClassExists($extendedInterfaceName)) { $messages[] = RuleErrorBuilder::message(sprintf('Interface %s extends unknown interface %s.', $currentInterfaceName, $extendedInterfaceName))->identifier('interface.notFound')->nonIgnorable()->discoveringSymbolsTip()->build(); } } else { $reflection = $this->reflectionProvider->getClass($extendedInterfaceName); if ($reflection->isClass()) { $messages[] = RuleErrorBuilder::message(sprintf('Interface %s extends class %s.', $currentInterfaceName, $reflection->getDisplayName()))->identifier('interfaceExtends.class')->nonIgnorable()->build(); } elseif ($reflection->isTrait()) { $messages[] = RuleErrorBuilder::message(sprintf('Interface %s extends trait %s.', $currentInterfaceName, $reflection->getDisplayName()))->identifier('interfaceExtends.trait')->nonIgnorable()->build(); } elseif ($reflection->isEnum()) { $messages[] = RuleErrorBuilder::message(sprintf('Interface %s extends enum %s.', $currentInterfaceName, $reflection->getDisplayName()))->identifier('interfaceExtends.enum')->nonIgnorable()->build(); } } return $messages; } return $messages; } } */ final class NewStaticRule implements Rule { public function getNodeType() : string { return Node\Expr\New_::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->class instanceof Node\Name) { return []; } if (!$scope->isInClass()) { return []; } if (strtolower($node->class->toString()) !== 'static') { return []; } $classReflection = $scope->getClassReflection(); if ($classReflection->isFinal()) { return []; } $messages = [RuleErrorBuilder::message('Unsafe usage of new static().')->identifier('new.static')->tip('See: https://phpstan.org/blog/solving-phpstan-error-unsafe-usage-of-new-static')->build()]; if (!$classReflection->hasConstructor()) { return $messages; } $constructor = $classReflection->getConstructor(); if ($constructor->getPrototype()->getDeclaringClass()->isInterface()) { return []; } if ($constructor->getDeclaringClass()->hasConsistentConstructor()) { return []; } foreach ($classReflection->getImmediateInterfaces() as $interface) { if ($interface->hasConstructor()) { return []; } } if ($constructor instanceof PhpMethodReflection) { if ($constructor->isFinal()->yes()) { return []; } $prototype = $constructor->getPrototype(); if ($prototype->isAbstract()) { return []; } } return $messages; } } */ final class PropertyTagRule implements Rule { /** * @var PropertyTagCheck */ private $check; public function __construct(\PHPStan\Rules\Classes\PropertyTagCheck $check) { $this->check = $check; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { return $this->check->check($node->getClassReflection(), $node->getOriginalNode()); } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkMissingTypehints = $checkMissingTypehints; } /** * @return list */ public function check(ClassReflection $classReflection, ClassLike $node) : array { $errors = []; foreach ($classReflection->getPropertyTags() as $propertyName => $propertyTag) { [$types, $tagName] = $this->getTypesAndTagName($propertyTag); foreach ($types as $type) { foreach ($this->checkPropertyTypeInTraitDefinitionContext($classReflection, $propertyName, $tagName, $type) as $error) { $errors[] = $error; } foreach ($this->checkPropertyTypeInTraitUseContext($classReflection, $propertyName, $tagName, $type, $node) as $error) { $errors[] = $error; } } } return $errors; } /** * @return list */ public function checkInTraitDefinitionContext(ClassReflection $classReflection) : array { $errors = []; foreach ($classReflection->getPropertyTags() as $propertyName => $propertyTag) { [$types, $tagName] = $this->getTypesAndTagName($propertyTag); foreach ($types as $type) { foreach ($this->checkPropertyTypeInTraitDefinitionContext($classReflection, $propertyName, $tagName, $type) as $error) { $errors[] = $error; } } } return $errors; } /** * @return list */ public function checkInTraitUseContext(ClassReflection $classReflection, ClassReflection $implementingClass, ClassLike $node) : array { $phpDoc = $classReflection->getTraitContextResolvedPhpDoc($implementingClass); if ($phpDoc === null) { return []; } $errors = []; foreach ($phpDoc->getPropertyTags() as $propertyName => $propertyTag) { [$types, $tagName] = $this->getTypesAndTagName($propertyTag); foreach ($types as $type) { foreach ($this->checkPropertyTypeInTraitUseContext($classReflection, $propertyName, $tagName, $type, $node) as $error) { $errors[] = $error; } } } return $errors; } /** * @return array{list, string} */ private function getTypesAndTagName(PropertyTag $propertyTag) : array { $readableType = $propertyTag->getReadableType(); $writableType = $propertyTag->getWritableType(); $types = []; $tagName = '@property'; if ($readableType !== null) { if ($writableType !== null) { if ($writableType->equals($readableType)) { $types[] = $readableType; } else { $types[] = $readableType; $types[] = $writableType; } } else { $tagName = '@property-read'; $types[] = $readableType; } } elseif ($writableType !== null) { $tagName = '@property-write'; $types[] = $writableType; } else { throw new ShouldNotHappenException(); } return [$types, $tagName]; } /** * @return list */ private function checkPropertyTypeInTraitDefinitionContext(ClassReflection $classReflection, string $propertyName, string $tagName, Type $type) : array { if (!$this->checkMissingTypehints) { return []; } $errors = []; foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($type) as [$innerName, $genericTypeNames]) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for property %s::$%s contains generic %s but does not specify its types: %s', $tagName, $classReflection->getDisplayName(), $propertyName, $innerName, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($type) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('%s %s has PHPDoc tag %s for property $%s with no value type specified in iterable type %s.', $classReflection->getClassTypeDescription(), $classReflection->getDisplayName(), $tagName, $propertyName, $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($type) as $callableType) { $errors[] = RuleErrorBuilder::message(sprintf('%s %s has PHPDoc tag %s for property $%s with no signature specified for %s.', $classReflection->getClassTypeDescription(), $classReflection->getDisplayName(), $tagName, $propertyName, $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $errors; } /** * @return list */ private function checkPropertyTypeInTraitUseContext(ClassReflection $classReflection, string $propertyName, string $tagName, Type $type, ClassLike $node) : array { $errors = []; foreach ($type->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for property %s::$%s contains unknown class %s.', $tagName, $classReflection->getDisplayName(), $propertyName, $class))->identifier('class.notFound')->discoveringSymbolsTip()->build(); } elseif ($this->reflectionProvider->getClass($class)->isTrait()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for property %s::$%s contains invalid type %s.', $tagName, $classReflection->getDisplayName(), $propertyName, $class))->identifier('propertyTag.trait')->build(); } else { $errors = array_merge($errors, $this->classCheck->checkClassNames([new ClassNameNodePair($class, $node)], $this->checkClassCaseSensitivity)); } } if ($this->unresolvableTypeHelper->containsUnresolvableType($type)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag %s for property %s::$%s contains unresolvable type.', $tagName, $classReflection->getDisplayName(), $propertyName))->identifier('propertyTag.unresolvableType')->build(); } $escapedClassName = SprintfHelper::escapeFormatString($classReflection->getDisplayName()); $escapedPropertyName = SprintfHelper::escapeFormatString($propertyName); $escapedTagName = SprintfHelper::escapeFormatString($tagName); return array_merge($errors, $this->genericObjectTypeCheck->check($type, sprintf('PHPDoc tag %s for property %s::$%s contains generic type %%s but %%s %%s is not generic.', $escapedTagName, $escapedClassName, $escapedPropertyName), sprintf('Generic type %%s in PHPDoc tag %s for property %s::$%s does not specify all template types of %%s %%s: %%s', $escapedTagName, $escapedClassName, $escapedPropertyName), sprintf('Generic type %%s in PHPDoc tag %s for property %s::$%s specifies %%d template types, but %%s %%s supports only %%d: %%s', $escapedTagName, $escapedClassName, $escapedPropertyName), sprintf('Type %%s in generic type %%s in PHPDoc tag %s for property %s::$%s is not subtype of template type %%s of %%s %%s.', $escapedTagName, $escapedClassName, $escapedPropertyName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag %s for property %s::$%s is in conflict with %%s template type %%s of %%s %%s.', $escapedTagName, $escapedClassName, $escapedPropertyName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag %s for property %s::$%s is redundant, template type %%s of %%s %%s has the same variance.', $escapedTagName, $escapedClassName, $escapedPropertyName))); } } */ final class MixinTraitRule implements Rule { /** * @var MixinCheck */ private $check; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Classes\MixinCheck $check, ReflectionProvider $reflectionProvider) { $this->check = $check; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) : array { $traitName = $node->namespacedName; if ($traitName === null) { return []; } if (!$this->reflectionProvider->hasClass($traitName->toString())) { return []; } return $this->check->checkInTraitDefinitionContext($this->reflectionProvider->getClass($traitName->toString())); } } */ final class UnusedConstructorParametersRule implements Rule { /** * @var UnusedFunctionParametersCheck */ private $check; public function __construct(UnusedFunctionParametersCheck $check) { $this->check = $check; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); $originalNode = $node->getOriginalNode(); if (strtolower($method->getName()) !== '__construct' || $originalNode->stmts === null) { return []; } if (count($originalNode->params) === 0) { return []; } $message = sprintf('Constructor of class %s has an unused parameter $%%s.', SprintfHelper::escapeFormatString($node->getClassReflection()->getDisplayName())); if ($node->getClassReflection()->isAnonymous()) { $message = 'Constructor of an anonymous class has an unused parameter $%s.'; } return $this->check->getUnusedParameters($scope, array_map(static function (Param $parameter) : string { if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } return $parameter->var->name; }, array_values(array_filter($originalNode->params, static function (Param $parameter) : bool { return $parameter->flags === 0; }))), $originalNode->stmts, $message, 'constructor.unusedParameter'); } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->absentTypeChecks = $absentTypeChecks; $this->checkMissingTypehints = $checkMissingTypehints; } /** * @return list */ public function check(ClassReflection $classReflection, ClassLike $node) : array { $errors = []; foreach ($this->checkInTraitDefinitionContext($classReflection) as $error) { $errors[] = $error; } foreach ($this->checkInTraitUseContext($classReflection, $classReflection, $node) as $error) { $errors[] = $error; } return $errors; } /** * @return list */ public function checkInTraitDefinitionContext(ClassReflection $classReflection) : array { $errors = []; foreach ($classReflection->getMixinTags() as $mixinTag) { $type = $mixinTag->getType(); if (!$type->canCallMethods()->yes() || !$type->canAccessProperties()->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @mixin contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))->identifier('mixin.nonObject')->build(); continue; } if (!$this->absentTypeChecks) { continue; } if (!$this->checkMissingTypehints) { continue; } foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($type) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('%s %s has PHPDoc tag @mixin with no value type specified in iterable type %s.', $classReflection->getClassTypeDescription(), $classReflection->getDisplayName(), $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($type) as [$innerName, $genericTypeNames]) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @mixin contains generic %s but does not specify its types: %s', $innerName, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($type) as $callableType) { $errors[] = RuleErrorBuilder::message(sprintf('%s %s has PHPDoc tag @mixin with no signature specified for %s.', $classReflection->getClassTypeDescription(), $classReflection->getDisplayName(), $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } } return $errors; } /** * @return list */ public function checkInTraitUseContext(ClassReflection $reflection, ClassReflection $implementingClassReflection, ClassLike $node) : array { if ($reflection->getNativeReflection()->getName() === $implementingClassReflection->getName()) { $phpDoc = $reflection->getResolvedPhpDoc(); } else { $phpDoc = $reflection->getTraitContextResolvedPhpDoc($implementingClassReflection); } if ($phpDoc === null) { return []; } $errors = []; foreach ($phpDoc->getMixinTags() as $mixinTag) { $type = $mixinTag->getType(); if ($this->unresolvableTypeHelper->containsUnresolvableType($type)) { $errors[] = RuleErrorBuilder::message('PHPDoc tag @mixin contains unresolvable type.')->identifier('mixin.unresolvableType')->build(); continue; } $errors = array_merge($errors, $this->genericObjectTypeCheck->check($type, 'PHPDoc tag @mixin contains generic type %s but %s %s is not generic.', 'Generic type %s in PHPDoc tag @mixin does not specify all template types of %s %s: %s', 'Generic type %s in PHPDoc tag @mixin specifies %d template types, but %s %s supports only %d: %s', 'Type %s in generic type %s in PHPDoc tag @mixin is not subtype of template type %s of %s %s.', 'Call-site variance of %s in generic type %s in PHPDoc tag @mixin is in conflict with %s template type %s of %s %s.', 'Call-site variance of %s in generic type %s in PHPDoc tag @mixin is redundant, template type %s of %s %s has the same variance.')); foreach ($type->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @mixin contains unknown class %s.', $class))->identifier('class.notFound')->discoveringSymbolsTip()->build(); } elseif ($this->reflectionProvider->getClass($class)->isTrait()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @mixin contains invalid type %s.', $class))->identifier('mixin.trait')->build(); } else { $errors = array_merge($errors, $this->classCheck->checkClassNames([new ClassNameNodePair($class, $node)], $this->checkClassCaseSensitivity)); } } } return $errors; } } */ final class ImpossibleInstanceOfRule implements Rule { /** * @var bool */ private $checkAlwaysTrueInstanceof; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(bool $checkAlwaysTrueInstanceof, bool $treatPhpDocTypesAsCertain, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->checkAlwaysTrueInstanceof = $checkAlwaysTrueInstanceof; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Expr\Instanceof_::class; } public function processNode(Node $node, Scope $scope) : array { $instanceofType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node) : $scope->getNativeType($node); if (!$instanceofType instanceof ConstantBooleanType) { return []; } if ($node->class instanceof Node\Name) { $className = $scope->resolveName($node->class); $classType = new ObjectType($className); } else { $classType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node->class) : $scope->getNativeType($node->class); $allowed = TypeCombinator::union(new StringType(), new ObjectWithoutClassType()); if (!$allowed->isSuperTypeOf($classType)->yes()) { return [RuleErrorBuilder::message(sprintf('Instanceof between %s and %s results in an error.', $scope->getType($node->expr)->describe(VerbosityLevel::typeOnly()), $classType->describe(VerbosityLevel::typeOnly())))->identifier('instanceof.invalidExprType')->build()]; } } $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $instanceofTypeWithoutPhpDocs = $scope->getNativeType($node); if ($instanceofTypeWithoutPhpDocs instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; if (!$instanceofType->getValue()) { $exprType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node->expr) : $scope->getNativeType($node->expr); return [$addTip(RuleErrorBuilder::message(sprintf('Instanceof between %s and %s will always evaluate to false.', $exprType->describe(VerbosityLevel::typeOnly()), $classType->describe(VerbosityLevel::getRecommendedLevelByType($classType)))))->identifier('instanceof.alwaysFalse')->build()]; } elseif ($this->checkAlwaysTrueInstanceof) { $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if ($isLast === \true && !$this->reportAlwaysTrueInLastCondition) { return []; } $exprType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node->expr) : $scope->getNativeType($node->expr); $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Instanceof between %s and %s will always evaluate to true.', $exprType->describe(VerbosityLevel::typeOnly()), $classType->describe(VerbosityLevel::getRecommendedLevelByType($classType))))); if ($isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier('instanceof.alwaysTrue'); return [$errorBuilder->build()]; } return []; } } */ final class ExistingClassInInstanceOfRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ClassNameCheck */ private $classCheck; /** * @var bool */ private $checkClassCaseSensitivity; public function __construct(ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, bool $checkClassCaseSensitivity) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; } public function getNodeType() : string { return Instanceof_::class; } public function processNode(Node $node, Scope $scope) : array { $class = $node->class; if (!$class instanceof Node\Name) { return []; } $name = (string) $class; $lowercaseName = strtolower($name); if (in_array($lowercaseName, ['self', 'static', 'parent'], \true)) { if (!$scope->isInClass()) { return [RuleErrorBuilder::message(sprintf('Using %s outside of class scope.', $lowercaseName))->identifier(sprintf('outOfClass.%s', $lowercaseName))->line($class->getStartLine())->build()]; } return []; } $errors = []; if (!$this->reflectionProvider->hasClass($name)) { if ($scope->isInClassExists($name)) { return []; } return [RuleErrorBuilder::message(sprintf('Class %s not found.', $name))->identifier('class.notFound')->line($class->getStartLine())->discoveringSymbolsTip()->build()]; } $errors = array_merge($errors, $this->classCheck->checkClassNames([new ClassNameNodePair($name, $class)], $this->checkClassCaseSensitivity)); $classReflection = $this->reflectionProvider->getClass($name); if ($classReflection->isTrait()) { $expressionType = $scope->getType($node->expr); $errors[] = RuleErrorBuilder::message(sprintf('Instanceof between %s and trait %s will always evaluate to false.', $expressionType->describe(VerbosityLevel::typeOnly()), $name))->identifier('instanceof.trait')->build(); } return $errors; } } */ final class ClassConstantRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var ClassNameCheck */ private $classCheck; /** * @var PhpVersion */ private $phpVersion; public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper, ClassNameCheck $classCheck, PhpVersion $phpVersion) { $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->classCheck = $classCheck; $this->phpVersion = $phpVersion; } public function getNodeType() : string { return ClassConstFetch::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } $constantName = $node->name->name; $class = $node->class; $messages = []; if ($class instanceof Node\Name) { $className = (string) $class; $lowercasedClassName = strtolower($className); if (in_array($lowercasedClassName, ['self', 'static'], \true)) { if (!$scope->isInClass()) { return [RuleErrorBuilder::message(sprintf('Using %s outside of class scope.', $className))->identifier(sprintf('outOfClass.%s', $lowercasedClassName))->build()]; } $classType = $scope->resolveTypeByName($class); } elseif ($lowercasedClassName === 'parent') { if (!$scope->isInClass()) { return [RuleErrorBuilder::message(sprintf('Using %s outside of class scope.', $className))->identifier(sprintf('outOfClass.%s', $lowercasedClassName))->build()]; } $currentClassReflection = $scope->getClassReflection(); if ($currentClassReflection->getParentClass() === null) { return [RuleErrorBuilder::message(sprintf('Access to parent::%s but %s does not extend any class.', $constantName, $currentClassReflection->getDisplayName()))->identifier('class.noParent')->build()]; } $classType = $scope->resolveTypeByName($class); } else { if (!$this->reflectionProvider->hasClass($className)) { if ($scope->isInClassExists($className)) { return []; } if (strtolower($constantName) === 'class') { return [RuleErrorBuilder::message(sprintf('Class %s not found.', $className))->identifier('class.notFound')->discoveringSymbolsTip()->build()]; } return [RuleErrorBuilder::message(sprintf('Access to constant %s on an unknown class %s.', $constantName, $className))->identifier('class.notFound')->discoveringSymbolsTip()->build()]; } $messages = $this->classCheck->checkClassNames([new ClassNameNodePair($className, $class)]); $classType = $scope->resolveTypeByName($class); } if (strtolower($constantName) === 'class') { return $messages; } } else { $classTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $class), sprintf('Access to constant %s on an unknown class %%s.', SprintfHelper::escapeFormatString($constantName)), static function (Type $type) use($constantName) : bool { return $type->canAccessConstants()->yes() && $type->hasConstant($constantName)->yes(); }); $classType = $classTypeResult->getType(); if ($classType instanceof ErrorType) { return $classTypeResult->getUnknownClassErrors(); } if (strtolower($constantName) === 'class') { if (!$this->phpVersion->supportsClassConstantOnExpression()) { return [RuleErrorBuilder::message('Accessing ::class constant on an expression is supported only on PHP 8.0 and later.')->identifier('classConstant.notSupported')->nonIgnorable()->build()]; } if (!$class instanceof Node\Scalar\String_ && $classType->isString()->yes()) { return [RuleErrorBuilder::message('Accessing ::class constant on a dynamic string is not supported in PHP.')->identifier('classConstant.dynamicString')->nonIgnorable()->build()]; } } } if ($classType->isString()->yes()) { return $messages; } $typeForDescribe = $classType; if ($classType instanceof ThisType) { $typeForDescribe = $classType->getStaticObjectType(); } $classType = TypeCombinator::remove($classType, new StringType()); if (!$classType->canAccessConstants()->yes()) { return array_merge($messages, [RuleErrorBuilder::message(sprintf('Cannot access constant %s on %s.', $constantName, $typeForDescribe->describe(VerbosityLevel::typeOnly())))->identifier('classConstant.nonObject')->build()]); } if (strtolower($constantName) === 'class' || $scope->hasExpressionType($node)->yes()) { return $messages; } if (!$classType->hasConstant($constantName)->yes()) { return array_merge($messages, [RuleErrorBuilder::message(sprintf('Access to undefined constant %s::%s.', $typeForDescribe->describe(VerbosityLevel::typeOnly()), $constantName))->identifier('classConstant.notFound')->build()]); } $constantReflection = $classType->getConstant($constantName); if (!$scope->canAccessConstant($constantReflection)) { return array_merge($messages, [RuleErrorBuilder::message(sprintf('Access to %s constant %s of class %s.', $constantReflection->isPrivate() ? 'private' : 'protected', $constantName, $constantReflection->getDeclaringClass()->getDisplayName()))->identifier(sprintf('classConstant.%s', $constantReflection->isPrivate() ? 'private' : 'protected'))->build()]); } return $messages; } } */ final class PropertyTagTraitRule implements Rule { /** * @var PropertyTagCheck */ private $check; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Classes\PropertyTagCheck $check, ReflectionProvider $reflectionProvider) { $this->check = $check; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) : array { $traitName = $node->namespacedName; if ($traitName === null) { return []; } if (!$this->reflectionProvider->hasClass($traitName->toString())) { return []; } return $this->check->checkInTraitDefinitionContext($this->reflectionProvider->getClass($traitName->toString())); } } */ final class ReadOnlyClassRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); if (!$classReflection->isReadOnly()) { return []; } if ($classReflection->isAnonymous()) { if ($this->phpVersion->supportsReadOnlyAnonymousClasses()) { return []; } return [RuleErrorBuilder::message('Anonymous readonly classes are supported only on PHP 8.3 and later.')->identifier('classConstant.nativeTypeNotSupported')->nonIgnorable()->build()]; } if ($this->phpVersion->supportsReadOnlyClasses()) { return []; } return [RuleErrorBuilder::message('Readonly classes are supported only on PHP 8.2 and later.')->identifier('classConstant.nativeTypeNotSupported')->nonIgnorable()->build()]; } } */ final class PropertyTagTraitUseRule implements Rule { /** * @var PropertyTagCheck */ private $check; public function __construct(\PHPStan\Rules\Classes\PropertyTagCheck $check) { $this->check = $check; } public function getNodeType() : string { return InTraitNode::class; } public function processNode(Node $node, Scope $scope) : array { return $this->check->checkInTraitUseContext($node->getTraitReflection(), $node->getImplementingClassReflection(), $node->getOriginalNode()); } } */ final class MethodTagTraitRule implements Rule { /** * @var MethodTagCheck */ private $check; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Classes\MethodTagCheck $check, ReflectionProvider $reflectionProvider) { $this->check = $check; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) : array { $traitName = $node->namespacedName; if ($traitName === null) { return []; } if (!$this->reflectionProvider->hasClass($traitName->toString())) { return []; } return $this->check->checkInTraitDefinitionContext($this->reflectionProvider->getClass($traitName->toString())); } } */ final class LocalTypeTraitUseAliasesRule implements Rule { /** * @var LocalTypeAliasesCheck */ private $check; public function __construct(\PHPStan\Rules\Classes\LocalTypeAliasesCheck $check) { $this->check = $check; } public function getNodeType() : string { return InTraitNode::class; } public function processNode(Node $node, Scope $scope) : array { return $this->check->checkInTraitUseContext($node->getTraitReflection(), $node->getImplementingClassReflection(), $node->getOriginalNode()); } } */ final class AccessPrivateConstantThroughStaticRule implements Rule { public function getNodeType() : string { return Node\Expr\ClassConstFetch::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } if (!$node->class instanceof Name) { return []; } $constantName = $node->name->name; $className = $node->class; if ($className->toLowerString() !== 'static') { return []; } $classType = $scope->resolveTypeByName($className); if (!$classType->hasConstant($constantName)->yes()) { return []; } $constant = $classType->getConstant($constantName); if (!$constant->isPrivate()) { return []; } if ($scope->isInClass() && $scope->getClassReflection()->isFinal()) { return []; } return [RuleErrorBuilder::message(sprintf('Unsafe access to private constant %s::%s through static::.', $constant->getDeclaringClass()->getDisplayName(), $constantName))->identifier('staticClassAccess.privateConstant')->build()]; } } */ final class ClassConstantAttributesRule implements Rule { /** * @var AttributesCheck */ private $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType() : string { return Node\Stmt\ClassConst::class; } public function processNode(Node $node, Scope $scope) : array { return $this->attributesCheck->check($scope, $node->attrGroups, Attribute::TARGET_CLASS_CONSTANT, 'class constant'); } } */ final class NonClassAttributeClassRule implements Rule { public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $originalNode = $node->getOriginalNode(); foreach ($originalNode->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { $name = $attr->name->toLowerString(); if ($name === 'attribute') { return $this->check($scope); } } } return []; } /** * @return list */ private function check(Scope $scope) : array { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $classReflection = $scope->getClassReflection(); if (!$classReflection->isClass()) { return [RuleErrorBuilder::message(sprintf('%s cannot be an Attribute class.', $classReflection->getClassTypeDescription()))->identifier(sprintf('attribute.%s', strtolower($classReflection->getClassTypeDescription())))->build()]; } if ($classReflection->isAbstract()) { return [RuleErrorBuilder::message(sprintf('Abstract class %s cannot be an Attribute class.', $classReflection->getDisplayName()))->identifier('attribute.abstract')->build()]; } if (!$classReflection->hasConstructor()) { return []; } if (!$classReflection->getConstructor()->isPublic()) { return [RuleErrorBuilder::message(sprintf('Attribute class %s constructor must be public.', $classReflection->getDisplayName()))->identifier('attribute.constructorNotPublic')->build()]; } return []; } } */ final class MethodTagRule implements Rule { /** * @var MethodTagCheck */ private $check; public function __construct(\PHPStan\Rules\Classes\MethodTagCheck $check) { $this->check = $check; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { return $this->check->check($node->getClassReflection(), $node->getOriginalNode()); } } */ final class ClassAttributesRule implements Rule { /** * @var AttributesCheck */ private $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classLikeNode = $node->getOriginalNode(); return $this->attributesCheck->check($scope, $classLikeNode->attrGroups, Attribute::TARGET_CLASS, 'class'); } } */ final class TraitAttributeClassRule implements Rule { public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) : array { foreach ($node->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { $name = $attr->name->toLowerString(); if ($name === 'attribute') { return [RuleErrorBuilder::message('Trait cannot be an Attribute class.')->identifier('attribute.trait')->build()]; } } } return []; } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->missingTypehintCheck = $missingTypehintCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkMissingTypehints = $checkMissingTypehints; } /** * @return list */ public function check(ClassReflection $classReflection, ClassLike $node) : array { $errors = []; foreach ($classReflection->getMethodTags() as $methodName => $methodTag) { $i = 0; foreach ($methodTag->getParameters() as $parameterName => $parameterTag) { $i++; $parameterDescription = sprintf('parameter #%d $%s', $i, $parameterName); foreach ($this->checkMethodTypeInTraitDefinitionContext($classReflection, $methodName, $parameterDescription, $parameterTag->getType()) as $error) { $errors[] = $error; } foreach ($this->checkMethodTypeInTraitUseContext($classReflection, $methodName, $parameterDescription, $parameterTag->getType(), $node) as $error) { $errors[] = $error; } if ($parameterTag->getDefaultValue() === null) { continue; } $defaultValueDescription = sprintf('%s default value', $parameterDescription); foreach ($this->checkMethodTypeInTraitDefinitionContext($classReflection, $methodName, $defaultValueDescription, $parameterTag->getDefaultValue()) as $error) { $errors[] = $error; } foreach ($this->checkMethodTypeInTraitUseContext($classReflection, $methodName, $defaultValueDescription, $parameterTag->getDefaultValue(), $node) as $error) { $errors[] = $error; } } $returnTypeDescription = 'return type'; foreach ($this->checkMethodTypeInTraitDefinitionContext($classReflection, $methodName, $returnTypeDescription, $methodTag->getReturnType()) as $error) { $errors[] = $error; } foreach ($this->checkMethodTypeInTraitUseContext($classReflection, $methodName, $returnTypeDescription, $methodTag->getReturnType(), $node) as $error) { $errors[] = $error; } } return $errors; } /** * @return list */ public function checkInTraitDefinitionContext(ClassReflection $classReflection) : array { $errors = []; foreach ($classReflection->getMethodTags() as $methodName => $methodTag) { $i = 0; foreach ($methodTag->getParameters() as $parameterName => $parameterTag) { $i++; $parameterDescription = sprintf('parameter #%d $%s', $i, $parameterName); foreach ($this->checkMethodTypeInTraitDefinitionContext($classReflection, $methodName, $parameterDescription, $parameterTag->getType()) as $error) { $errors[] = $error; } if ($parameterTag->getDefaultValue() === null) { continue; } $defaultValueDescription = sprintf('%s default value', $parameterDescription); foreach ($this->checkMethodTypeInTraitDefinitionContext($classReflection, $methodName, $defaultValueDescription, $parameterTag->getDefaultValue()) as $error) { $errors[] = $error; } } $returnTypeDescription = 'return type'; foreach ($this->checkMethodTypeInTraitDefinitionContext($classReflection, $methodName, $returnTypeDescription, $methodTag->getReturnType()) as $error) { $errors[] = $error; } } return $errors; } /** * @return list */ public function checkInTraitUseContext(ClassReflection $classReflection, ClassReflection $implementingClass, ClassLike $node) : array { $phpDoc = $classReflection->getTraitContextResolvedPhpDoc($implementingClass); if ($phpDoc === null) { return []; } $errors = []; foreach ($phpDoc->getMethodTags() as $methodName => $methodTag) { $i = 0; foreach ($methodTag->getParameters() as $parameterName => $parameterTag) { $i++; $parameterDescription = sprintf('parameter #%d $%s', $i, $parameterName); foreach ($this->checkMethodTypeInTraitUseContext($classReflection, $methodName, $parameterDescription, $parameterTag->getType(), $node) as $error) { $errors[] = $error; } if ($parameterTag->getDefaultValue() === null) { continue; } $defaultValueDescription = sprintf('%s default value', $parameterDescription); foreach ($this->checkMethodTypeInTraitUseContext($classReflection, $methodName, $defaultValueDescription, $parameterTag->getDefaultValue(), $node) as $error) { $errors[] = $error; } } $returnTypeDescription = 'return type'; foreach ($this->checkMethodTypeInTraitUseContext($classReflection, $methodName, $returnTypeDescription, $methodTag->getReturnType(), $node) as $error) { $errors[] = $error; } } return $errors; } /** * @return list */ private function checkMethodTypeInTraitDefinitionContext(ClassReflection $classReflection, string $methodName, string $description, Type $type) : array { if (!$this->checkMissingTypehints) { return []; } $errors = []; foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($type) as [$innerName, $genericTypeNames]) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @method for method %s::%s() %s contains generic %s but does not specify its types: %s', $classReflection->getDisplayName(), $methodName, $description, $innerName, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($type) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('%s %s has PHPDoc tag @method for method %s() %s with no value type specified in iterable type %s.', $classReflection->getClassTypeDescription(), $classReflection->getDisplayName(), $methodName, $description, $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($type) as $callableType) { $errors[] = RuleErrorBuilder::message(sprintf('%s %s has PHPDoc tag @method for method %s() %s with no signature specified for %s.', $classReflection->getClassTypeDescription(), $classReflection->getDisplayName(), $methodName, $description, $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $errors; } /** * @return list */ private function checkMethodTypeInTraitUseContext(ClassReflection $classReflection, string $methodName, string $description, Type $type, ClassLike $node) : array { $errors = []; foreach ($type->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @method for method %s::%s() %s contains unknown class %s.', $classReflection->getDisplayName(), $methodName, $description, $class))->identifier('class.notFound')->discoveringSymbolsTip()->build(); } elseif ($this->reflectionProvider->getClass($class)->isTrait()) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @method for method %s::%s() %s contains invalid type %s.', $classReflection->getDisplayName(), $methodName, $description, $class))->identifier('methodTag.trait')->build(); } else { $errors = array_merge($errors, $this->classCheck->checkClassNames([new ClassNameNodePair($class, $node)], $this->checkClassCaseSensitivity)); } } if ($this->unresolvableTypeHelper->containsUnresolvableType($type)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @method for method %s::%s() %s contains unresolvable type.', $classReflection->getDisplayName(), $methodName, $description))->identifier('methodTag.unresolvableType')->build(); } $escapedClassName = SprintfHelper::escapeFormatString($classReflection->getDisplayName()); $escapedMethodName = SprintfHelper::escapeFormatString($methodName); $escapedDescription = SprintfHelper::escapeFormatString($description); return array_merge($errors, $this->genericObjectTypeCheck->check($type, sprintf('PHPDoc tag @method for method %s::%s() %s contains generic type %%s but %%s %%s is not generic.', $escapedClassName, $escapedMethodName, $escapedDescription), sprintf('Generic type %%s in PHPDoc tag @method for method %s::%s() %s does not specify all template types of %%s %%s: %%s', $escapedClassName, $escapedMethodName, $escapedDescription), sprintf('Generic type %%s in PHPDoc tag @method for method %s::%s() %s specifies %%d template types, but %%s %%s supports only %%d: %%s', $escapedClassName, $escapedMethodName, $escapedDescription), sprintf('Type %%s in generic type %%s in PHPDoc tag @method for method %s::%s() %s is not subtype of template type %%s of %%s %%s.', $escapedClassName, $escapedMethodName, $escapedDescription), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag @method for method %s::%s() %s is in conflict with %%s template type %%s of %%s %%s.', $escapedClassName, $escapedMethodName, $escapedDescription), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag @method for method %s::%s() %s is redundant, template type %%s of %%s %%s has the same variance.', $escapedClassName, $escapedMethodName, $escapedDescription))); } } */ final class RequireExtendsRule implements Rule { public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); if ($classReflection->isInterface()) { return []; } $errors = []; foreach ($classReflection->getInterfaces() as $interface) { $extendsTags = $interface->getRequireExtendsTags(); foreach ($extendsTags as $extendsTag) { $type = $extendsTag->getType(); if (!$type instanceof ObjectType) { continue; } if ($classReflection->is($type->getClassName())) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Interface %s requires implementing class to extend %s, but %s does not.', $interface->getDisplayName(), $type->describe(VerbosityLevel::typeOnly()), $classReflection->getDisplayName()))->identifier('class.missingExtends')->build(); } } foreach ($classReflection->getTraits(\true) as $trait) { $extendsTags = $trait->getRequireExtendsTags(); foreach ($extendsTags as $extendsTag) { $type = $extendsTag->getType(); if (!$type instanceof ObjectType) { continue; } if ($classReflection->is($type->getClassName())) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Trait %s requires using class to extend %s, but %s does not.', $trait->getDisplayName(), $type->describe(VerbosityLevel::typeOnly()), $classReflection->getDisplayName()))->identifier('class.missingExtends')->build(); } } return $errors; } } */ final class InstantiationCallableRule implements Rule { public function getNodeType() : string { return InstantiationCallableNode::class; } public function processNode(Node $node, Scope $scope) : array { return [RuleErrorBuilder::message('Cannot create callable from the new operator.')->identifier('callable.notSupported')->nonIgnorable()->build()]; } } */ final class InvalidPromotedPropertiesRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return Node\FunctionLike::class; } public function processNode(Node $node, Scope $scope) : array { $hasPromotedProperties = \false; foreach ($node->getParams() as $param) { if ($param->flags === 0) { continue; } $hasPromotedProperties = \true; break; } if (!$hasPromotedProperties) { return []; } if (!$this->phpVersion->supportsPromotedProperties()) { return [RuleErrorBuilder::message('Promoted properties are supported only on PHP 8.0 and later.')->identifier('property.promotedNotSupported')->nonIgnorable()->build()]; } if (!$node instanceof Node\Stmt\ClassMethod || $node->name->toLowerString() !== '__construct' && $node->getAttribute('originalTraitMethodName') !== '__construct') { return [RuleErrorBuilder::message('Promoted properties can be in constructor only.')->identifier('property.invalidPromoted')->nonIgnorable()->build()]; } if ($node->getStmts() === null) { return [RuleErrorBuilder::message('Promoted properties are not allowed in abstract constructors.')->identifier('property.invalidPromoted')->nonIgnorable()->build()]; } $errors = []; foreach ($node->getParams() as $param) { if ($param->flags === 0) { continue; } if (!$param->var instanceof Node\Expr\Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } if (!$param->variadic) { continue; } $propertyName = $param->var->name; $errors[] = RuleErrorBuilder::message(sprintf('Promoted property parameter $%s can not be variadic.', $propertyName))->identifier('property.invalidPromoted')->nonIgnorable()->line($param->getStartLine())->build(); } return $errors; } } */ final class InstantiationRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var FunctionCallParametersCheck */ private $check; /** * @var ClassNameCheck */ private $classCheck; public function __construct(ReflectionProvider $reflectionProvider, FunctionCallParametersCheck $check, ClassNameCheck $classCheck) { $this->reflectionProvider = $reflectionProvider; $this->check = $check; $this->classCheck = $classCheck; } public function getNodeType() : string { return New_::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; foreach ($this->getClassNames($node, $scope) as [$class, $isName]) { $errors = array_merge($errors, $this->checkClassName($class, $isName, $node, $scope)); } return $errors; } /** * @param Node\Expr\New_ $node * @return list */ private function checkClassName(string $class, bool $isName, Node $node, Scope $scope) : array { $lowercasedClass = strtolower($class); $messages = []; $isStatic = \false; if ($lowercasedClass === 'static') { if (!$scope->isInClass()) { return [RuleErrorBuilder::message(sprintf('Using %s outside of class scope.', $class))->identifier('outOfClass.static')->build()]; } $isStatic = \true; $classReflection = $scope->getClassReflection(); if (!$classReflection->isFinal()) { if (!$classReflection->hasConstructor()) { return []; } $constructor = $classReflection->getConstructor(); if (!$constructor->getPrototype()->getDeclaringClass()->isInterface() && $constructor instanceof PhpMethodReflection && !$constructor->isFinal()->yes() && !$constructor->getPrototype()->isAbstract()) { return []; } } } elseif ($lowercasedClass === 'self') { if (!$scope->isInClass()) { return [RuleErrorBuilder::message(sprintf('Using %s outside of class scope.', $class))->identifier('outOfClass.self')->build()]; } $classReflection = $scope->getClassReflection(); } elseif ($lowercasedClass === 'parent') { if (!$scope->isInClass()) { return [RuleErrorBuilder::message(sprintf('Using %s outside of class scope.', $class))->identifier('outOfClass.parent')->build()]; } if ($scope->getClassReflection()->getParentClass() === null) { return [RuleErrorBuilder::message(sprintf('%s::%s() calls new parent but %s does not extend any class.', $scope->getClassReflection()->getDisplayName(), $scope->getFunctionName(), $scope->getClassReflection()->getDisplayName()))->identifier('class.noParent')->build()]; } $classReflection = $scope->getClassReflection()->getParentClass(); } else { if (!$this->reflectionProvider->hasClass($class)) { if ($scope->isInClassExists($class)) { return []; } return [RuleErrorBuilder::message(sprintf('Instantiated class %s not found.', $class))->identifier('class.notFound')->discoveringSymbolsTip()->build()]; } $messages = $this->classCheck->checkClassNames([new ClassNameNodePair($class, $node->class)]); $classReflection = $this->reflectionProvider->getClass($class); } if ($classReflection->isEnum() && $isName) { return [RuleErrorBuilder::message(sprintf('Cannot instantiate enum %s.', $classReflection->getDisplayName()))->identifier('new.enum')->build()]; } if (!$isStatic && $classReflection->isInterface() && $isName) { return [RuleErrorBuilder::message(sprintf('Cannot instantiate interface %s.', $classReflection->getDisplayName()))->identifier('new.interface')->build()]; } if (!$isStatic && $classReflection->isAbstract() && $isName) { return [RuleErrorBuilder::message(sprintf('Instantiated class %s is abstract.', $classReflection->getDisplayName()))->identifier('new.abstract')->build()]; } if (!$isName) { return []; } if (!$classReflection->hasConstructor()) { if (count($node->getArgs()) > 0) { return array_merge($messages, [RuleErrorBuilder::message(sprintf('Class %s does not have a constructor and must be instantiated without any parameters.', $classReflection->getDisplayName()))->identifier('new.noConstructor')->build()]); } return $messages; } $constructorReflection = $classReflection->getConstructor(); if (!$scope->canCallMethod($constructorReflection)) { $messages[] = RuleErrorBuilder::message(sprintf('Cannot instantiate class %s via %s constructor %s::%s().', $classReflection->getDisplayName(), $constructorReflection->isPrivate() ? 'private' : 'protected', $constructorReflection->getDeclaringClass()->getDisplayName(), $constructorReflection->getName()))->identifier(sprintf('new.%sConstructor', $constructorReflection->isPrivate() ? 'private' : 'protected'))->build(); } $classDisplayName = SprintfHelper::escapeFormatString($classReflection->getDisplayName()); return array_merge($messages, $this->check->check(ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $constructorReflection->getVariants(), $constructorReflection->getNamedArgumentsVariants()), $scope, $constructorReflection->getDeclaringClass()->isBuiltin(), $node, [ 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, %d required.', 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, %d required.', 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, at least %d required.', 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, at least %d required.', 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, %d-%d required.', 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, %d-%d required.', 'Parameter %s of class ' . $classDisplayName . ' constructor expects %s, %s given.', '', // constructor does not have a return type 'Parameter %s of class ' . $classDisplayName . ' constructor is passed by reference, so it expects variables only', 'Unable to resolve the template type %s in instantiation of class ' . $classDisplayName, 'Missing parameter $%s in call to ' . $classDisplayName . ' constructor.', 'Unknown parameter $%s in call to ' . $classDisplayName . ' constructor.', 'Return type of call to ' . $classDisplayName . ' constructor contains unresolvable type.', 'Parameter %s of class ' . $classDisplayName . ' constructor contains unresolvable type.', 'Class ' . $classDisplayName . ' constructor invoked with %s, but it\'s not allowed because of @no-named-arguments.', ], 'new', $constructorReflection->acceptsNamedArguments())); } /** * @param Node\Expr\New_ $node * @return array */ private function getClassNames(Node $node, Scope $scope) : array { if ($node->class instanceof Node\Name) { return [[(string) $node->class, \true]]; } if ($node->class instanceof Node\Stmt\Class_) { $classNames = $scope->getType($node)->getObjectClassNames(); if ($classNames === []) { throw new ShouldNotHappenException(); } return array_map(static function (string $className) { return [$className, \true]; }, $classNames); } $type = $scope->getType($node->class); return array_merge(array_map(static function (ConstantStringType $type) : array { return [$type->getValue(), \true]; }, $type->getConstantStrings()), array_map(static function (string $name) : array { return [$name, \false]; }, $type->getObjectClassNames())); } } */ final class ExistingClassesInClassImplementsRule implements Rule { /** * @var ClassNameCheck */ private $classCheck; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Class_::class; } public function processNode(Node $node, Scope $scope) : array { $messages = $this->classCheck->checkClassNames(array_map(static function (Node\Name $interfaceName) : ClassNameNodePair { return new ClassNameNodePair((string) $interfaceName, $interfaceName); }, $node->implements)); $currentClassName = null; if (isset($node->namespacedName)) { $currentClassName = (string) $node->namespacedName; } foreach ($node->implements as $implements) { $implementedClassName = (string) $implements; if (!$this->reflectionProvider->hasClass($implementedClassName)) { if (!$scope->isInClassExists($implementedClassName)) { $messages[] = RuleErrorBuilder::message(sprintf('%s implements unknown interface %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $implementedClassName))->identifier('interface.notFound')->nonIgnorable()->discoveringSymbolsTip()->build(); } } else { $reflection = $this->reflectionProvider->getClass($implementedClassName); if ($reflection->isClass()) { $messages[] = RuleErrorBuilder::message(sprintf('%s implements class %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $reflection->getDisplayName()))->identifier('classImplements.class')->nonIgnorable()->build(); } elseif ($reflection->isTrait()) { $messages[] = RuleErrorBuilder::message(sprintf('%s implements trait %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $reflection->getDisplayName()))->identifier('classImplements.trait')->nonIgnorable()->build(); } elseif ($reflection->isEnum()) { $messages[] = RuleErrorBuilder::message(sprintf('%s implements enum %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $reflection->getDisplayName()))->identifier('classImplements.enum')->nonIgnorable()->build(); } } } return $messages; } } */ final class RequireImplementsRule implements Rule { public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); $errors = []; foreach ($classReflection->getTraits(\true) as $trait) { $implementsTags = $trait->getRequireImplementsTags(); foreach ($implementsTags as $implementsTag) { $type = $implementsTag->getType(); if (!$type instanceof ObjectType) { continue; } if ($classReflection->implementsInterface($type->getClassName())) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Trait %s requires using class to implement %s, but %s does not.', $trait->getDisplayName(), $type->describe(VerbosityLevel::typeOnly()), $classReflection->getDisplayName()))->identifier('class.missingImplements')->build(); } } return $errors; } } */ final class ExistingClassesInEnumImplementsRule implements Rule { /** * @var ClassNameCheck */ private $classCheck; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Enum_::class; } public function processNode(Node $node, Scope $scope) : array { $messages = $this->classCheck->checkClassNames(array_map(static function (Node\Name $interfaceName) : ClassNameNodePair { return new ClassNameNodePair((string) $interfaceName, $interfaceName); }, $node->implements)); $currentEnumName = (string) $node->namespacedName; foreach ($node->implements as $implements) { $implementedClassName = (string) $implements; if (!$this->reflectionProvider->hasClass($implementedClassName)) { if (!$scope->isInClassExists($implementedClassName)) { $messages[] = RuleErrorBuilder::message(sprintf('Enum %s implements unknown interface %s.', $currentEnumName, $implementedClassName))->identifier('interface.notFound')->nonIgnorable()->discoveringSymbolsTip()->build(); } } else { $reflection = $this->reflectionProvider->getClass($implementedClassName); if ($reflection->isClass()) { $messages[] = RuleErrorBuilder::message(sprintf('Enum %s implements class %s.', $currentEnumName, $reflection->getDisplayName()))->identifier('enumImplements.class')->nonIgnorable()->build(); } elseif ($reflection->isTrait()) { $messages[] = RuleErrorBuilder::message(sprintf('Enum %s implements trait %s.', $currentEnumName, $reflection->getDisplayName()))->identifier('enumImplements.trait')->nonIgnorable()->build(); } elseif ($reflection->isEnum()) { $messages[] = RuleErrorBuilder::message(sprintf('Enum %s implements enum %s.', $currentEnumName, $reflection->getDisplayName()))->identifier('enumImplements.enum')->nonIgnorable()->build(); } } } return $messages; } } */ final class LocalTypeAliasesRule implements Rule { /** * @var LocalTypeAliasesCheck */ private $check; public function __construct(\PHPStan\Rules\Classes\LocalTypeAliasesCheck $check) { $this->check = $check; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { return $this->check->check($node->getClassReflection(), $node->getOriginalNode()); } } */ final class DuplicateDeclarationRule implements Rule { public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); $identifierType = strtolower($classReflection->getClassTypeDescription()); $errors = []; $declaredClassConstantsOrEnumCases = []; foreach ($node->getOriginalNode()->stmts as $stmtNode) { if ($stmtNode instanceof EnumCase) { if (array_key_exists($stmtNode->name->name, $declaredClassConstantsOrEnumCases)) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot redeclare enum case %s::%s.', $classReflection->getDisplayName(), $stmtNode->name->name))->identifier(sprintf('%s.duplicateEnumCase', $identifierType))->line($stmtNode->getStartLine())->nonIgnorable()->build(); } else { $declaredClassConstantsOrEnumCases[$stmtNode->name->name] = \true; } } elseif ($stmtNode instanceof ClassConst) { foreach ($stmtNode->consts as $classConstNode) { if (array_key_exists($classConstNode->name->name, $declaredClassConstantsOrEnumCases)) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot redeclare constant %s::%s.', $classReflection->getDisplayName(), $classConstNode->name->name))->identifier(sprintf('%s.duplicateConstant', $identifierType))->line($classConstNode->getStartLine())->nonIgnorable()->build(); } else { $declaredClassConstantsOrEnumCases[$classConstNode->name->name] = \true; } } } } $declaredProperties = []; foreach ($node->getOriginalNode()->getProperties() as $propertyDecl) { foreach ($propertyDecl->props as $property) { if (array_key_exists($property->name->name, $declaredProperties)) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot redeclare property %s::$%s.', $classReflection->getDisplayName(), $property->name->name))->identifier(sprintf('%s.duplicateProperty', $identifierType))->line($property->getStartLine())->nonIgnorable()->build(); } else { $declaredProperties[$property->name->name] = \true; } } } $declaredFunctions = []; foreach ($node->getOriginalNode()->getMethods() as $method) { if ($method->name->toLowerString() === '__construct') { foreach ($method->params as $param) { if ($param->flags === 0) { continue; } if (!$param->var instanceof Node\Expr\Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $propertyName = $param->var->name; if (array_key_exists($propertyName, $declaredProperties)) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot redeclare property %s::$%s.', $classReflection->getDisplayName(), $propertyName))->identifier(sprintf('%s.duplicateProperty', $identifierType))->line($param->getStartLine())->nonIgnorable()->build(); } else { $declaredProperties[$propertyName] = \true; } } } if (array_key_exists(strtolower($method->name->name), $declaredFunctions)) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot redeclare method %s::%s().', $classReflection->getDisplayName(), $method->name->name))->identifier(sprintf('%s.duplicateMethod', $identifierType))->line($method->getStartLine())->nonIgnorable()->build(); } else { $declaredFunctions[strtolower($method->name->name)] = \true; } } return $errors; } } */ final class ExistingClassInTraitUseRule implements Rule { /** * @var ClassNameCheck */ private $classCheck; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\TraitUse::class; } public function processNode(Node $node, Scope $scope) : array { $messages = $this->classCheck->checkClassNames(array_map(static function (Node\Name $traitName) : ClassNameNodePair { return new ClassNameNodePair((string) $traitName, $traitName); }, $node->traits)); if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $classReflection = $scope->getClassReflection(); if ($classReflection->isInterface()) { if (!$scope->isInTrait()) { foreach ($node->traits as $trait) { $messages[] = RuleErrorBuilder::message(sprintf('Interface %s uses trait %s.', $classReflection->getName(), (string) $trait))->identifier('interface.traitUse')->nonIgnorable()->build(); } } } else { if ($scope->isInTrait()) { $currentName = sprintf('Trait %s', $scope->getTraitReflection()->getName()); } else { if ($classReflection->isAnonymous()) { $currentName = 'Anonymous class'; } else { $currentName = sprintf('Class %s', $classReflection->getName()); } } foreach ($node->traits as $trait) { $traitName = (string) $trait; if (!$this->reflectionProvider->hasClass($traitName)) { $messages[] = RuleErrorBuilder::message(sprintf('%s uses unknown trait %s.', $currentName, $traitName))->identifier('trait.notFound')->nonIgnorable()->discoveringSymbolsTip()->build(); } else { $reflection = $this->reflectionProvider->getClass($traitName); if ($reflection->isClass()) { $messages[] = RuleErrorBuilder::message(sprintf('%s uses class %s.', $currentName, $reflection->getDisplayName()))->identifier('traitUse.class')->nonIgnorable()->build(); } elseif ($reflection->isInterface()) { $messages[] = RuleErrorBuilder::message(sprintf('%s uses interface %s.', $currentName, $reflection->getDisplayName()))->identifier('traitUse.interface')->nonIgnorable()->build(); } elseif ($reflection->isEnum()) { $messages[] = RuleErrorBuilder::message(sprintf('%s uses enum %s.', $currentName, $reflection->getDisplayName()))->identifier('traitUse.enum')->nonIgnorable()->build(); } } } } return $messages; } } */ final class EnumSanityRule implements Rule { private const ALLOWED_MAGIC_METHODS = ['__call' => \true, '__callstatic' => \true, '__invoke' => \true]; public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); if (!$classReflection->isEnum()) { return []; } /** @var Node\Stmt\Enum_ $enumNode */ $enumNode = $node->getOriginalNode(); $errors = []; foreach ($enumNode->getMethods() as $methodNode) { $lowercasedMethodName = $methodNode->name->toLowerString(); if ($methodNode->isMagic()) { if ($lowercasedMethodName === '__construct') { $errors[] = RuleErrorBuilder::message(sprintf('Enum %s contains constructor.', $classReflection->getDisplayName()))->identifier('enum.constructor')->line($methodNode->getStartLine())->nonIgnorable()->build(); } elseif ($lowercasedMethodName === '__destruct') { $errors[] = RuleErrorBuilder::message(sprintf('Enum %s contains destructor.', $classReflection->getDisplayName()))->identifier('enum.destructor')->line($methodNode->getStartLine())->nonIgnorable()->build(); } elseif (!array_key_exists($lowercasedMethodName, self::ALLOWED_MAGIC_METHODS)) { $errors[] = RuleErrorBuilder::message(sprintf('Enum %s contains magic method %s().', $classReflection->getDisplayName(), $methodNode->name->name))->identifier('enum.magicMethod')->line($methodNode->getStartLine())->nonIgnorable()->build(); } } if ($lowercasedMethodName === 'cases') { $errors[] = RuleErrorBuilder::message(sprintf('Enum %s cannot redeclare native method %s().', $classReflection->getDisplayName(), $methodNode->name->name))->identifier('enum.methodRedeclaration')->line($methodNode->getStartLine())->nonIgnorable()->build(); } if ($enumNode->scalarType === null) { continue; } if (!in_array($lowercasedMethodName, ['from', 'tryfrom'], \true)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Enum %s cannot redeclare native method %s().', $classReflection->getDisplayName(), $methodNode->name->name))->identifier('enum.methodRedeclaration')->line($methodNode->getStartLine())->nonIgnorable()->build(); } if ($enumNode->scalarType !== null && !in_array($enumNode->scalarType->name, ['int', 'string'], \true)) { $errors[] = RuleErrorBuilder::message(sprintf('Backed enum %s can have only "int" or "string" type.', $classReflection->getDisplayName()))->identifier('enum.backingType')->line($enumNode->scalarType->getStartLine())->nonIgnorable()->build(); } if ($classReflection->implementsInterface(Serializable::class)) { $errors[] = RuleErrorBuilder::message(sprintf('Enum %s cannot implement the Serializable interface.', $classReflection->getDisplayName()))->identifier('enum.serializable')->line($enumNode->getStartLine())->nonIgnorable()->build(); } $enumCases = []; foreach ($enumNode->stmts as $stmt) { if (!$stmt instanceof Node\Stmt\EnumCase) { continue; } $caseName = $stmt->name->name; if ($stmt->expr instanceof Node\Scalar\LNumber || $stmt->expr instanceof Node\Scalar\String_) { if ($enumNode->scalarType === null) { $errors[] = RuleErrorBuilder::message(sprintf('Enum %s is not backed, but case %s has value %s.', $classReflection->getDisplayName(), $caseName, $stmt->expr->value))->identifier('enum.caseWithValue')->line($stmt->getStartLine())->nonIgnorable()->build(); } else { $caseValue = $stmt->expr->value; if (!isset($enumCases[$caseValue])) { $enumCases[$caseValue] = []; } $enumCases[$caseValue][] = $caseName; } } if ($enumNode->scalarType === null) { continue; } if ($stmt->expr === null) { $errors[] = RuleErrorBuilder::message(sprintf('Enum case %s::%s does not have a value but the enum is backed with the "%s" type.', $classReflection->getDisplayName(), $caseName, $enumNode->scalarType->name))->identifier('enum.missingCase')->line($stmt->getStartLine())->nonIgnorable()->build(); continue; } $exprType = $scope->getType($stmt->expr); $scalarType = $enumNode->scalarType->toLowerString() === 'int' ? new IntegerType() : new StringType(); if ($scalarType->isSuperTypeOf($exprType)->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Enum case %s::%s value %s does not match the "%s" type.', $classReflection->getDisplayName(), $caseName, $exprType->describe(VerbosityLevel::value()), $scalarType->describe(VerbosityLevel::typeOnly())))->identifier('enum.caseType')->line($stmt->getStartLine())->nonIgnorable()->build(); } foreach ($enumCases as $caseValue => $caseNames) { if (count($caseNames) <= 1) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Enum %s has duplicate value %s for cases %s.', $classReflection->getDisplayName(), $caseValue, implode(', ', $caseNames)))->identifier('enum.duplicateValue')->line($enumNode->getStartLine())->nonIgnorable()->build(); } return $errors; } } */ final class ExistingClassInClassExtendsRule implements Rule { /** * @var ClassNameCheck */ private $classCheck; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ClassNameCheck $classCheck, ReflectionProvider $reflectionProvider) { $this->classCheck = $classCheck; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Class_::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->extends === null) { return []; } $extendedClassName = (string) $node->extends; $messages = $this->classCheck->checkClassNames([new ClassNameNodePair($extendedClassName, $node->extends)]); $currentClassName = null; if (isset($node->namespacedName)) { $currentClassName = (string) $node->namespacedName; } if (!$this->reflectionProvider->hasClass($extendedClassName)) { if (!$scope->isInClassExists($extendedClassName)) { $messages[] = RuleErrorBuilder::message(sprintf('%s extends unknown class %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $extendedClassName))->identifier('class.notFound')->nonIgnorable()->discoveringSymbolsTip()->build(); } } else { $reflection = $this->reflectionProvider->getClass($extendedClassName); if ($reflection->isInterface()) { $messages[] = RuleErrorBuilder::message(sprintf('%s extends interface %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $reflection->getDisplayName()))->identifier('class.extendsInterface')->nonIgnorable()->build(); } elseif ($reflection->isTrait()) { $messages[] = RuleErrorBuilder::message(sprintf('%s extends trait %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $reflection->getDisplayName()))->identifier('class.extendsTrait')->nonIgnorable()->build(); } elseif ($reflection->isEnum()) { $messages[] = RuleErrorBuilder::message(sprintf('%s extends enum %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $reflection->getDisplayName()))->identifier('class.extendsEnum')->nonIgnorable()->build(); } elseif ($reflection->isFinalByKeyword()) { $messages[] = RuleErrorBuilder::message(sprintf('%s extends final class %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $reflection->getDisplayName()))->identifier('class.extendsFinal')->nonIgnorable()->build(); } elseif ($reflection->isFinal()) { $messages[] = RuleErrorBuilder::message(sprintf('%s extends @final class %s.', $currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class', $reflection->getDisplayName()))->identifier('class.extendsFinalByPhpDoc')->build(); } if ($reflection->isClass()) { if ($node->isReadonly()) { if (!$reflection->isReadOnly()) { $messages[] = RuleErrorBuilder::message(sprintf('%s extends non-readonly class %s.', $currentClassName !== null ? sprintf('Readonly class %s', $currentClassName) : 'Anonymous readonly class', $reflection->getDisplayName()))->identifier('class.readOnly')->nonIgnorable()->build(); } } elseif ($reflection->isReadOnly()) { $messages[] = RuleErrorBuilder::message(sprintf('%s extends readonly class %s.', $currentClassName !== null ? sprintf('Non-readonly class %s', $currentClassName) : 'Anonymous non-readonly class', $reflection->getDisplayName()))->identifier('class.nonReadOnly')->nonIgnorable()->build(); } } } return $messages; } } */ final class MethodTagTraitUseRule implements Rule { /** * @var MethodTagCheck */ private $check; public function __construct(\PHPStan\Rules\Classes\MethodTagCheck $check) { $this->check = $check; } public function getNodeType() : string { return InTraitNode::class; } public function processNode(Node $node, Scope $scope) : array { return $this->check->checkInTraitUseContext($node->getTraitReflection(), $node->getImplementingClassReflection(), $node->getOriginalNode()); } } */ final class MixinTraitUseRule implements Rule { /** * @var MixinCheck */ private $check; public function __construct(\PHPStan\Rules\Classes\MixinCheck $check) { $this->check = $check; } public function getNodeType() : string { return InTraitNode::class; } public function processNode(Node $node, Scope $scope) : array { return $this->check->checkInTraitUseContext($node->getTraitReflection(), $node->getImplementingClassReflection(), $node->getOriginalNode()); } } */ private $globalTypeAliases; /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var TypeNodeResolver */ private $typeNodeResolver; /** * @var MissingTypehintCheck */ private $missingTypehintCheck; /** * @var ClassNameCheck */ private $classCheck; /** * @var UnresolvableTypeHelper */ private $unresolvableTypeHelper; /** * @var GenericObjectTypeCheck */ private $genericObjectTypeCheck; /** * @var bool */ private $checkMissingTypehints; /** * @var bool */ private $checkClassCaseSensitivity; /** * @var bool */ private $absentTypeChecks; /** * @param array $globalTypeAliases */ public function __construct(array $globalTypeAliases, ReflectionProvider $reflectionProvider, TypeNodeResolver $typeNodeResolver, MissingTypehintCheck $missingTypehintCheck, ClassNameCheck $classCheck, UnresolvableTypeHelper $unresolvableTypeHelper, GenericObjectTypeCheck $genericObjectTypeCheck, bool $checkMissingTypehints, bool $checkClassCaseSensitivity, bool $absentTypeChecks) { $this->globalTypeAliases = $globalTypeAliases; $this->reflectionProvider = $reflectionProvider; $this->typeNodeResolver = $typeNodeResolver; $this->missingTypehintCheck = $missingTypehintCheck; $this->classCheck = $classCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->checkMissingTypehints = $checkMissingTypehints; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->absentTypeChecks = $absentTypeChecks; } /** * @return list */ public function check(ClassReflection $reflection, ClassLike $node) : array { $errors = []; foreach ($this->checkInTraitDefinitionContext($reflection) as $error) { $errors[] = $error; } foreach ($this->checkInTraitUseContext($reflection, $reflection, $node) as $error) { $errors[] = $error; } return $errors; } /** * @return list */ public function checkInTraitDefinitionContext(ClassReflection $reflection) : array { $phpDoc = $reflection->getResolvedPhpDoc(); if ($phpDoc === null) { return []; } $nameScope = $phpDoc->getNullableNameScope(); $resolveName = static function (string $name) use($nameScope) : string { if ($nameScope === null) { return $name; } return $nameScope->resolveStringName($name); }; $errors = []; $className = $reflection->getDisplayName(); $importedAliases = []; foreach ($phpDoc->getTypeAliasImportTags() as $typeAliasImportTag) { $aliasName = $typeAliasImportTag->getImportedAs() ?? $typeAliasImportTag->getImportedAlias(); $importedAlias = $typeAliasImportTag->getImportedAlias(); $importedFromClassName = $typeAliasImportTag->getImportedFrom(); if (!$this->reflectionProvider->hasClass($importedFromClassName)) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot import type alias %s: class %s does not exist.', $importedAlias, $importedFromClassName))->identifier('class.notFound')->build(); continue; } $importedFromReflection = $this->reflectionProvider->getClass($importedFromClassName); $typeAliases = $importedFromReflection->getTypeAliases(); if (!array_key_exists($importedAlias, $typeAliases)) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot import type alias %s: type alias does not exist in %s.', $importedAlias, $importedFromClassName))->identifier('typeAlias.notFound')->build(); continue; } $resolvedName = $resolveName($aliasName); if ($this->reflectionProvider->hasClass($resolveName($aliasName))) { $classReflection = $this->reflectionProvider->getClass($resolvedName); $classLikeDescription = 'a class'; if ($classReflection->isInterface()) { $classLikeDescription = 'an interface'; } elseif ($classReflection->isTrait()) { $classLikeDescription = 'a trait'; } elseif ($classReflection->isEnum()) { $classLikeDescription = 'an enum'; } $errors[] = RuleErrorBuilder::message(sprintf('Type alias %s already exists as %s in scope of %s.', $aliasName, $classLikeDescription, $className))->identifier('typeAlias.duplicate')->build(); continue; } if (array_key_exists($aliasName, $this->globalTypeAliases)) { $errors[] = RuleErrorBuilder::message(sprintf('Type alias %s already exists as a global type alias.', $aliasName))->identifier('typeAlias.duplicate')->build(); continue; } $importedAs = $typeAliasImportTag->getImportedAs(); if ($importedAs !== null && !$this->isAliasNameValid($importedAs, $nameScope)) { $errors[] = RuleErrorBuilder::message(sprintf('Imported type alias %s has an invalid name: %s.', $importedAlias, $importedAs))->identifier('typeAlias.invalidName')->build(); continue; } $importedAliases[] = $aliasName; } foreach ($phpDoc->getTypeAliasTags() as $typeAliasTag) { $aliasName = $typeAliasTag->getAliasName(); if (in_array($aliasName, $importedAliases, \true)) { $errors[] = RuleErrorBuilder::message(sprintf('Type alias %s overwrites an imported type alias of the same name.', $aliasName))->identifier('typeAlias.duplicate')->build(); continue; } $resolvedName = $resolveName($aliasName); if ($this->reflectionProvider->hasClass($resolvedName)) { $classReflection = $this->reflectionProvider->getClass($resolvedName); $classLikeDescription = 'a class'; if ($classReflection->isInterface()) { $classLikeDescription = 'an interface'; } elseif ($classReflection->isTrait()) { $classLikeDescription = 'a trait'; } elseif ($classReflection->isEnum()) { $classLikeDescription = 'an enum'; } $errors[] = RuleErrorBuilder::message(sprintf('Type alias %s already exists as %s in scope of %s.', $aliasName, $classLikeDescription, $className))->identifier('typeAlias.duplicate')->build(); continue; } if (array_key_exists($aliasName, $this->globalTypeAliases)) { $errors[] = RuleErrorBuilder::message(sprintf('Type alias %s already exists as a global type alias.', $aliasName))->identifier('typeAlias.duplicate')->build(); continue; } if (!$this->isAliasNameValid($aliasName, $nameScope)) { $errors[] = RuleErrorBuilder::message(sprintf('Type alias has an invalid name: %s.', $aliasName))->identifier('typeAlias.invalidName')->build(); continue; } $resolvedType = $typeAliasTag->getTypeAlias()->resolve($this->typeNodeResolver); if ($this->hasErrorType($resolvedType, $aliasName, $errors)) { continue; } if (!$this->absentTypeChecks) { continue; } if (!$this->checkMissingTypehints) { continue; } foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($resolvedType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('%s %s has type alias %s with no value type specified in iterable type %s.', $reflection->getClassTypeDescription(), $reflection->getDisplayName(), $aliasName, $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($resolvedType) as [$name, $genericTypeNames]) { $errors[] = RuleErrorBuilder::message(sprintf('%s %s has type alias %s with generic %s but does not specify its types: %s', $reflection->getClassTypeDescription(), $reflection->getDisplayName(), $aliasName, $name, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($resolvedType) as $callableType) { $errors[] = RuleErrorBuilder::message(sprintf('%s %s has type alias %s with no signature specified for %s.', $reflection->getClassTypeDescription(), $reflection->getDisplayName(), $aliasName, $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } } return $errors; } /** * @return list */ public function checkInTraitUseContext(ClassReflection $reflection, ClassReflection $implementingClassReflection, ClassLike $node) : array { if ($reflection->getNativeReflection()->getName() === $implementingClassReflection->getName()) { $phpDoc = $reflection->getResolvedPhpDoc(); } else { $phpDoc = $reflection->getTraitContextResolvedPhpDoc($implementingClassReflection); } if ($phpDoc === null) { return []; } $errors = []; foreach ($phpDoc->getTypeAliasTags() as $typeAliasTag) { $aliasName = $typeAliasTag->getAliasName(); $resolvedType = $typeAliasTag->getTypeAlias()->resolve($this->typeNodeResolver); $throwawayErrors = []; if ($this->hasErrorType($resolvedType, $aliasName, $throwawayErrors)) { continue; } foreach ($resolvedType->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = RuleErrorBuilder::message(sprintf('Type alias %s contains unknown class %s.', $aliasName, $class))->identifier('class.notFound')->discoveringSymbolsTip()->build(); } elseif ($this->reflectionProvider->getClass($class)->isTrait()) { $errors[] = RuleErrorBuilder::message(sprintf('Type alias %s contains invalid type %s.', $aliasName, $class))->identifier('typeAlias.trait')->build(); } else { $errors = array_merge($errors, $this->classCheck->checkClassNames([new ClassNameNodePair($class, $node)], $this->checkClassCaseSensitivity)); } } if ($this->unresolvableTypeHelper->containsUnresolvableType($resolvedType)) { $errors[] = RuleErrorBuilder::message(sprintf('Type alias %s contains unresolvable type.', $aliasName))->identifier('typeAlias.unresolvableType')->build(); } $escapedTypeAlias = SprintfHelper::escapeFormatString($aliasName); $errors = array_merge($errors, $this->genericObjectTypeCheck->check($resolvedType, sprintf('Type alias %s contains generic type %%s but %%s %%s is not generic.', $escapedTypeAlias), sprintf('Generic type %%s in type alias %s does not specify all template types of %%s %%s: %%s', $escapedTypeAlias), sprintf('Generic type %%s in type alias %s specifies %%d template types, but %%s %%s supports only %%d: %%s', $escapedTypeAlias), sprintf('Type %%s in generic type %%s in type alias %s is not subtype of template type %%s of %%s %%s.', $escapedTypeAlias), sprintf('Call-site variance of %%s in generic type %%s in type alias %s is in conflict with %%s template type %%s of %%s %%s.', $escapedTypeAlias), sprintf('Call-site variance of %%s in generic type %%s in type alias %s is redundant, template type %%s of %%s %%s has the same variance.', $escapedTypeAlias))); } return $errors; } private function isAliasNameValid(string $aliasName, ?NameScope $nameScope) : bool { if ($nameScope === null) { return \true; } $aliasNameResolvedType = $this->typeNodeResolver->resolve(new IdentifierTypeNode($aliasName), $nameScope->bypassTypeAliases()); return $aliasNameResolvedType->isObject()->yes() && !in_array($aliasName, ['self', 'parent'], \true) || $aliasNameResolvedType instanceof TemplateType; // aliases take precedence over type parameters, this is reported by other rules using TemplateTypeCheck } /** * @param list $errors * @param-out list $errors */ private function hasErrorType(Type $type, string $aliasName, array &$errors) : bool { $foundError = \false; TypeTraverser::map($type, static function (Type $type, callable $traverse) use(&$errors, &$foundError, $aliasName) : Type { if ($foundError) { return $type; } if ($type instanceof CircularTypeAliasErrorType) { $errors[] = RuleErrorBuilder::message(sprintf('Circular definition detected in type alias %s.', $aliasName))->identifier('typeAlias.circular')->build(); $foundError = \true; return $type; } if ($type instanceof ErrorType) { $errors[] = RuleErrorBuilder::message(sprintf('Invalid type definition detected in type alias %s.', $aliasName))->identifier('typeAlias.invalidType')->build(); $foundError = \true; return $type; } return $traverse($type); }); return $foundError; } } */ final class MixinRule implements Rule { /** * @var MixinCheck */ private $check; public function __construct(\PHPStan\Rules\Classes\MixinCheck $check) { $this->check = $check; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { return $this->check->check($node->getClassReflection(), $node->getOriginalNode()); } } */ final class LocalTypeTraitAliasesRule implements Rule { /** * @var LocalTypeAliasesCheck */ private $check; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Classes\LocalTypeAliasesCheck $check, ReflectionProvider $reflectionProvider) { $this->check = $check; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) : array { $traitName = $node->namespacedName; if ($traitName === null) { return []; } if (!$this->reflectionProvider->hasClass($traitName->toString())) { return []; } return $this->check->checkInTraitDefinitionContext($this->reflectionProvider->getClass($traitName->toString())); } } */ final class InvalidTypesInUnionRule implements Rule { private const ONLY_STANDALONE_TYPES = ['mixed', 'never', 'void']; public function getNodeType() : string { return Node::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Node\FunctionLike && !$node instanceof ClassPropertyNode) { return []; } if ($node instanceof Node\FunctionLike) { return $this->processFunctionLikeNode($node); } return $this->processClassPropertyNode($node); } /** * @return list */ private function processFunctionLikeNode(Node\FunctionLike $functionLike) : array { $errors = []; foreach ($functionLike->getParams() as $param) { if (!$param->type instanceof Node\ComplexType) { continue; } $errors = array_merge($errors, $this->processComplexType($param->type)); } if ($functionLike->getReturnType() instanceof Node\ComplexType) { $errors = array_merge($errors, $this->processComplexType($functionLike->getReturnType())); } return $errors; } /** * @return list */ private function processClassPropertyNode(ClassPropertyNode $classPropertyNode) : array { if (!$classPropertyNode->getNativeType() instanceof Node\ComplexType) { return []; } return $this->processComplexType($classPropertyNode->getNativeType()); } /** * @return list */ private function processComplexType(Node\ComplexType $complexType) : array { if (!$complexType instanceof Node\UnionType && !$complexType instanceof Node\NullableType) { return []; } if ($complexType instanceof Node\UnionType) { foreach ($complexType->types as $type) { if (!$type instanceof Node\Identifier) { continue; } $typeString = $type->toLowerString(); if (in_array($typeString, self::ONLY_STANDALONE_TYPES, \true)) { return [RuleErrorBuilder::message(sprintf('Type %s cannot be part of a union type declaration.', $type->toString()))->line($complexType->getStartLine())->identifier(sprintf('unionType.%s', $typeString))->nonIgnorable()->build()]; } } return []; } if ($complexType->type instanceof Node\Identifier) { $complexTypeString = $complexType->type->toLowerString(); if (in_array($complexTypeString, self::ONLY_STANDALONE_TYPES, \true)) { return [RuleErrorBuilder::message(sprintf('Type %s cannot be part of a nullable type declaration.', $complexType->type->toString()))->line($complexType->getStartLine())->identifier(sprintf('nullableType.%s', $complexTypeString))->nonIgnorable()->build()]; } } return []; } } */ final class YieldFromTypeRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var bool */ private $reportMaybes; public function __construct(RuleLevelHelper $ruleLevelHelper, bool $reportMaybes) { $this->ruleLevelHelper = $ruleLevelHelper; $this->reportMaybes = $reportMaybes; } public function getNodeType() : string { return YieldFrom::class; } public function processNode(Node $node, Scope $scope) : array { $exprType = $scope->getType($node->expr); $isIterable = $exprType->isIterable(); $messagePattern = 'Argument of an invalid type %s passed to yield from, only iterables are supported.'; if ($isIterable->no()) { return [RuleErrorBuilder::message(sprintf($messagePattern, $exprType->describe(VerbosityLevel::typeOnly())))->line($node->expr->getStartLine())->identifier('generator.nonIterable')->build()]; } elseif (!$exprType instanceof MixedType && $this->reportMaybes && $isIterable->maybe()) { return [RuleErrorBuilder::message(sprintf($messagePattern, $exprType->describe(VerbosityLevel::typeOnly())))->line($node->expr->getStartLine())->identifier('generator.nonIterable')->build()]; } $anonymousFunctionReturnType = $scope->getAnonymousFunctionReturnType(); $scopeFunction = $scope->getFunction(); if ($anonymousFunctionReturnType !== null) { $returnType = $anonymousFunctionReturnType; } elseif ($scopeFunction !== null) { $returnType = $scopeFunction->getReturnType(); } else { return []; // already reported by YieldInGeneratorRule } if ($returnType instanceof MixedType) { return []; } $messages = []; $acceptsKey = $this->ruleLevelHelper->acceptsWithReason($returnType->getIterableKeyType(), $exprType->getIterableKeyType(), $scope->isDeclareStrictTypes()); if (!$acceptsKey->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType->getIterableKeyType(), $exprType->getIterableKeyType()); $messages[] = RuleErrorBuilder::message(sprintf('Generator expects key type %s, %s given.', $returnType->getIterableKeyType()->describe($verbosityLevel), $exprType->getIterableKeyType()->describe($verbosityLevel)))->line($node->expr->getStartLine())->identifier('generator.keyType')->acceptsReasonsTip($acceptsKey->reasons)->build(); } $acceptsValue = $this->ruleLevelHelper->acceptsWithReason($returnType->getIterableValueType(), $exprType->getIterableValueType(), $scope->isDeclareStrictTypes()); if (!$acceptsValue->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType->getIterableValueType(), $exprType->getIterableValueType()); $messages[] = RuleErrorBuilder::message(sprintf('Generator expects value type %s, %s given.', $returnType->getIterableValueType()->describe($verbosityLevel), $exprType->getIterableValueType()->describe($verbosityLevel)))->line($node->expr->getStartLine())->identifier('generator.valueType')->acceptsReasonsTip($acceptsValue->reasons)->build(); } $scopeFunction = $scope->getFunction(); if ($scopeFunction === null) { return $messages; } $currentReturnType = $scopeFunction->getReturnType(); $exprSendType = $exprType->getTemplateType(Generator::class, 'TSend'); $thisSendType = $currentReturnType->getTemplateType(Generator::class, 'TSend'); if ($exprSendType instanceof ErrorType || $thisSendType instanceof ErrorType) { return $messages; } $isSuperType = $exprSendType->isSuperTypeOf($thisSendType); if ($isSuperType->no()) { $messages[] = RuleErrorBuilder::message(sprintf('Generator expects delegated TSend type %s, %s given.', $exprSendType->describe(VerbosityLevel::typeOnly()), $thisSendType->describe(VerbosityLevel::typeOnly())))->identifier('generator.sendType')->build(); } elseif ($this->reportMaybes && !$isSuperType->yes()) { $messages[] = RuleErrorBuilder::message(sprintf('Generator expects delegated TSend type %s, %s given.', $exprSendType->describe(VerbosityLevel::typeOnly()), $thisSendType->describe(VerbosityLevel::typeOnly())))->identifier('generator.sendType')->build(); } if (!$scope->isInFirstLevelStatement() && $scope->getType($node)->isVoid()->yes()) { $messages[] = RuleErrorBuilder::message('Result of yield from (void) is used.')->identifier('generator.void')->build(); } return $messages; } } */ final class YieldTypeRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Expr\Yield_::class; } public function processNode(Node $node, Scope $scope) : array { $anonymousFunctionReturnType = $scope->getAnonymousFunctionReturnType(); $scopeFunction = $scope->getFunction(); if ($anonymousFunctionReturnType !== null) { $returnType = $anonymousFunctionReturnType; } elseif ($scopeFunction !== null) { $returnType = $scopeFunction->getReturnType(); } else { return []; // already reported by YieldInGeneratorRule } if ($returnType instanceof MixedType) { return []; } if ($node->key === null) { $keyType = new IntegerType(); } else { $keyType = $scope->getType($node->key); } $messages = []; $acceptsKey = $this->ruleLevelHelper->acceptsWithReason($returnType->getIterableKeyType(), $keyType, $scope->isDeclareStrictTypes()); if (!$acceptsKey->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType->getIterableKeyType(), $keyType); $messages[] = RuleErrorBuilder::message(sprintf('Generator expects key type %s, %s given.', $returnType->getIterableKeyType()->describe($verbosityLevel), $keyType->describe($verbosityLevel)))->acceptsReasonsTip($acceptsKey->reasons)->identifier('generator.keyType')->build(); } if ($node->value === null) { $valueType = new NullType(); } else { $valueType = $scope->getType($node->value); } $acceptsValue = $this->ruleLevelHelper->acceptsWithReason($returnType->getIterableValueType(), $valueType, $scope->isDeclareStrictTypes()); if (!$acceptsValue->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType->getIterableValueType(), $valueType); $messages[] = RuleErrorBuilder::message(sprintf('Generator expects value type %s, %s given.', $returnType->getIterableValueType()->describe($verbosityLevel), $valueType->describe($verbosityLevel)))->acceptsReasonsTip($acceptsValue->reasons)->identifier('generator.valueType')->build(); } if (!$scope->isInFirstLevelStatement() && $scope->getType($node)->isVoid()->yes()) { $messages[] = RuleErrorBuilder::message('Result of yield (void) is used.')->identifier('generator.void')->build(); } return $messages; } } */ final class YieldInGeneratorRule implements Rule { /** * @var bool */ private $reportMaybes; public function __construct(bool $reportMaybes) { $this->reportMaybes = $reportMaybes; } public function getNodeType() : string { return Node\Expr::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Node\Expr\Yield_ && !$node instanceof Node\Expr\YieldFrom) { return []; } $anonymousFunctionReturnType = $scope->getAnonymousFunctionReturnType(); $scopeFunction = $scope->getFunction(); if ($anonymousFunctionReturnType !== null) { $returnType = $anonymousFunctionReturnType; } elseif ($scopeFunction !== null) { $returnType = $scopeFunction->getReturnType(); } else { return [RuleErrorBuilder::message('Yield can be used only inside a function.')->identifier('generator.outOfFunction')->nonIgnorable()->build()]; } if ($returnType instanceof MixedType) { return []; } if ($returnType instanceof NeverType && $returnType->isExplicit()) { $isSuperType = TrinaryLogic::createNo(); } else { $isSuperType = $returnType->isIterable()->and(TrinaryLogic::createFromBoolean(!$returnType->isArray()->yes())); } if ($isSuperType->yes()) { return []; } if ($isSuperType->maybe() && !$this->reportMaybes) { return []; } return [RuleErrorBuilder::message(sprintf('Yield can be used only with these return types: %s.', 'Generator, Iterator, Traversable, iterable'))->identifier('generator.returnType')->build()]; } } */ final class FinalPrivateMethodRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); if (!$this->phpVersion->producesWarningForFinalPrivateMethods()) { return []; } if ($method->getName() === '__construct') { return []; } if (!$method->isFinal()->yes() || !$method->isPrivate()) { return []; } return [RuleErrorBuilder::message(sprintf('Private method %s::%s() cannot be final as it is never overridden by other classes.', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('method.finalPrivate')->build()]; } } container = $container; } public function getExtensions() : array { return $this->extensions = $this->extensions ?? $this->container->getServicesByTag(static::EXTENSION_TAG); } } extensions = $extensions; } public function getExtensions() : array { return $this->extensions; } } */ final class ConstructorReturnTypeRule implements Rule { public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); $methodNode = $node->getOriginalNode(); if ($scope->isInTrait()) { $originalMethodName = $methodNode->getAttribute('originalTraitMethodName'); if ($originalMethodName === '__construct' && $methodNode->returnType !== null) { return [RuleErrorBuilder::message(sprintf('Original constructor of trait %s has a return type.', $scope->getTraitReflection()->getDisplayName()))->identifier('constructor.returnType')->nonIgnorable()->build()]; } } if (!$classReflection->hasConstructor()) { return []; } $constructorReflection = $classReflection->getConstructor(); $methodReflection = $node->getMethodReflection(); if ($methodReflection->getName() !== $constructorReflection->getName()) { return []; } if ($methodNode->returnType === null) { return []; } return [RuleErrorBuilder::message(sprintf('Constructor of class %s has a return type.', $classReflection->getDisplayName()))->identifier('constructor.returnType')->nonIgnorable()->build()]; } } */ final class IllegalConstructorMethodCallRule implements Rule { public function getNodeType() : string { return Node\Expr\MethodCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier || $node->name->toLowerString() !== '__construct') { return []; } return [RuleErrorBuilder::message('Call to __construct() on an existing object is not allowed.')->identifier('constructor.call')->build()]; } } */ final class ConsistentConstructorRule implements Rule { /** * @var MethodParameterComparisonHelper */ private $methodParameterComparisonHelper; public function __construct(\PHPStan\Rules\Methods\MethodParameterComparisonHelper $methodParameterComparisonHelper) { $this->methodParameterComparisonHelper = $methodParameterComparisonHelper; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); if (strtolower($method->getName()) !== '__construct') { return []; } $parent = $method->getDeclaringClass()->getParentClass(); if ($parent === null) { return []; } if ($parent->hasConstructor()) { $parentConstructor = $parent->getConstructor(); } else { $parentConstructor = new DummyConstructorReflection($parent); } if (!$parentConstructor->getDeclaringClass()->hasConsistentConstructor()) { return []; } return $this->methodParameterComparisonHelper->compare($parentConstructor, $parentConstructor->getDeclaringClass(), $method, \true); } } */ final class StaticMethodCallableRule implements Rule { /** * @var StaticMethodCallCheck */ private $methodCallCheck; /** * @var PhpVersion */ private $phpVersion; public function __construct(\PHPStan\Rules\Methods\StaticMethodCallCheck $methodCallCheck, PhpVersion $phpVersion) { $this->methodCallCheck = $methodCallCheck; $this->phpVersion = $phpVersion; } public function getNodeType() : string { return StaticMethodCallableNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$this->phpVersion->supportsFirstClassCallables()) { return [RuleErrorBuilder::message('First-class callables are supported only on PHP 8.1 and later.')->nonIgnorable()->identifier('callable.notSupported')->build()]; } $methodName = $node->getName(); if (!$methodName instanceof Node\Identifier) { return []; } $methodNameName = $methodName->toString(); [$errors, $methodReflection] = $this->methodCallCheck->check($scope, $methodNameName, $node->getClass()); if ($methodReflection === null) { return $errors; } $declaringClass = $methodReflection->getDeclaringClass(); if ($declaringClass->hasNativeMethod($methodNameName)) { return $errors; } $messagesMethodName = SprintfHelper::escapeFormatString($declaringClass->getDisplayName() . '::' . $methodReflection->getName() . '()'); $errors[] = RuleErrorBuilder::message(sprintf('Creating callable from a non-native static method %s.', $messagesMethodName))->identifier('callable.nonNativeMethod')->build(); return $errors; } } */ final class NullsafeMethodCallRule implements Rule { public function getNodeType() : string { return Node\Expr\NullsafeMethodCall::class; } public function processNode(Node $node, Scope $scope) : array { $calledOnType = $scope->getType($node->var); if (!$calledOnType->isNull()->no()) { return []; } return [RuleErrorBuilder::message(sprintf('Using nullsafe method call on non-nullable type %s. Use -> instead.', $calledOnType->describe(VerbosityLevel::typeOnly())))->identifier('nullsafe.neverNull')->build()]; } } */ final class MissingMagicSerializationMethodsRule implements Rule { /** * @var PhpVersion */ private $phpversion; public function __construct(PhpVersion $phpversion) { $this->phpversion = $phpversion; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); if (!$this->phpversion->serializableRequiresMagicMethods()) { return []; } if (!$classReflection->implementsInterface(Serializable::class)) { return []; } if ($classReflection->isAbstract() || $classReflection->isInterface() || $classReflection->isEnum()) { return []; } $messages = []; try { $nativeMethods = $classReflection->getNativeReflection()->getMethods(); } catch (IdentifierNotFound $e) { return []; } $missingMagicSerialize = \true; $missingMagicUnserialize = \true; foreach ($nativeMethods as $method) { if (strtolower($method->getName()) === '__serialize') { $missingMagicSerialize = \false; } if (strtolower($method->getName()) !== '__unserialize') { continue; } $missingMagicUnserialize = \false; } if ($missingMagicSerialize) { $messages[] = RuleErrorBuilder::message(sprintf('Non-abstract class %s implements the Serializable interface, but does not implement __serialize().', $classReflection->getDisplayName()))->tip('See https://wiki.php.net/rfc/phase_out_serializable')->identifier('class.serializable')->build(); } if ($missingMagicUnserialize) { $messages[] = RuleErrorBuilder::message(sprintf('Non-abstract class %s implements the Serializable interface, but does not implement __unserialize().', $classReflection->getDisplayName()))->tip('See https://wiki.php.net/rfc/phase_out_serializable')->identifier('class.serializable')->build(); } return $messages; } } */ final class CallToConstructorStatementWithoutSideEffectsRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var bool */ private $reportNoConstructor; public function __construct(ReflectionProvider $reflectionProvider, bool $reportNoConstructor) { $this->reflectionProvider = $reflectionProvider; $this->reportNoConstructor = $reportNoConstructor; } public function getNodeType() : string { return NoopExpressionNode::class; } public function processNode(Node $node, Scope $scope) : array { $instantiation = $node->getOriginalExpr(); if (!$instantiation instanceof Node\Expr\New_) { return []; } if (!$instantiation->class instanceof Node\Name) { return []; } $className = $scope->resolveName($instantiation->class); if (!$this->reflectionProvider->hasClass($className)) { return []; } $classReflection = $this->reflectionProvider->getClass($className); if (!$classReflection->hasConstructor()) { if ($this->reportNoConstructor) { return [RuleErrorBuilder::message(sprintf('Call to new %s() on a separate line has no effect.', $classReflection->getDisplayName()))->identifier('new.resultUnused')->build()]; } return []; } $constructor = $classReflection->getConstructor(); $methodResult = $scope->getType($instantiation); if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { return []; } return [RuleErrorBuilder::message(sprintf('Call to %s::%s() on a separate line has no effect.', $classReflection->getDisplayName(), $constructor->getName()))->identifier('new.resultUnused')->build()]; } } */ final class CallPrivateMethodThroughStaticRule implements Rule { public function getNodeType() : string { return StaticCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } if (!$node->class instanceof Name) { return []; } $methodName = $node->name->name; $className = $node->class; if ($className->toLowerString() !== 'static') { return []; } $classType = $scope->resolveTypeByName($className); if (!$classType->hasMethod($methodName)->yes()) { return []; } $method = $classType->getMethod($methodName, $scope); if (!$method->isPrivate()) { return []; } if ($scope->isInClass() && $scope->getClassReflection()->isFinal()) { return []; } return [RuleErrorBuilder::message(sprintf('Unsafe call to private method %s::%s() through static::.', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('staticClassAccess.privateMethod')->build()]; } } */ final class ReturnTypeRule implements Rule { /** * @var FunctionReturnTypeCheck */ private $returnTypeCheck; public function __construct(FunctionReturnTypeCheck $returnTypeCheck) { $this->returnTypeCheck = $returnTypeCheck; } public function getNodeType() : string { return Return_::class; } public function processNode(Node $node, Scope $scope) : array { if ($scope->getFunction() === null) { return []; } if ($scope->isInAnonymousFunction()) { return []; } $method = $scope->getFunction(); if (!$method instanceof PhpMethodFromParserNodeReflection) { return []; } $returnType = $method->getReturnType(); $errors = $this->returnTypeCheck->checkReturnType($scope, $returnType, $node->expr, $node, sprintf('Method %s::%s() should return %%s but empty return statement found.', $method->getDeclaringClass()->getDisplayName(), $method->getName()), sprintf('Method %s::%s() with return type void returns %%s but should not return anything.', $method->getDeclaringClass()->getDisplayName(), $method->getName()), sprintf('Method %s::%s() should return %%s but returns %%s.', $method->getDeclaringClass()->getDisplayName(), $method->getName()), sprintf('Method %s::%s() should never return but return statement found.', $method->getDeclaringClass()->getDisplayName(), $method->getName()), $method->isGenerator()); if (count($errors) === 1 && $errors[0]->getIdentifier() === 'return.type' && !$errors[0] instanceof TipRuleError && $errors[0] instanceof LineRuleError && $method->getDeclaringClass()->isSubclassOf(Rule::class) && strtolower($method->getName()) === 'processnode' && $node->expr !== null) { $ruleErrorType = new ObjectType(RuleError::class); $identifierRuleErrorType = new ObjectType(IdentifierRuleError::class); $listOfIdentifierRuleErrors = new IntersectionType([new ArrayType(IntegerRangeType::fromInterval(0, null), $identifierRuleErrorType), new AccessoryArrayListType()]); if (!$listOfIdentifierRuleErrors->isSuperTypeOf($returnType)->yes()) { return $errors; } $returnValueType = $scope->getType($node->expr)->getIterableValueType(); $builder = RuleErrorBuilder::message($errors[0]->getMessage())->line($errors[0]->getLine())->identifier($errors[0]->getIdentifier()); if (!$returnValueType->isString()->no()) { $builder->tip('Rules can no longer return plain strings. See: https://phpstan.org/blog/using-rule-error-builder'); } elseif ($ruleErrorType->isSuperTypeOf($returnValueType)->yes() && !$identifierRuleErrorType->isSuperTypeOf($returnValueType)->yes()) { $builder->tip('Error is missing an identifier. See: https://phpstan.org/blog/using-rule-error-builder'); } $errors = [$builder->build()]; } return $errors; } } */ final class MethodAttributesRule implements Rule { /** * @var AttributesCheck */ private $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType() : string { return Node\Stmt\ClassMethod::class; } public function processNode(Node $node, Scope $scope) : array { return $this->attributesCheck->check($scope, $node->attrGroups, Attribute::TARGET_METHOD, 'method'); } } */ final class MissingMethodReturnTypehintRule implements Rule { /** * @var MissingTypehintCheck */ private $missingTypehintCheck; public function __construct(MissingTypehintCheck $missingTypehintCheck) { $this->missingTypehintCheck = $missingTypehintCheck; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $methodReflection = $node->getMethodReflection(); if ($scope->isInTrait()) { $methodNode = $node->getOriginalNode(); $originalMethodName = $methodNode->getAttribute('originalTraitMethodName'); if ($originalMethodName === '__construct') { return []; } } $returnType = $methodReflection->getReturnType(); if ($returnType instanceof MixedType && !$returnType->isExplicitMixed()) { return [RuleErrorBuilder::message(sprintf('Method %s::%s() has no return type specified.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName()))->identifier('missingType.return')->build()]; } $messages = []; foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($returnType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() return type has no value type specified in iterable type %s.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($returnType) as [$name, $genericTypeNames]) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() return type with generic %s does not specify its types: %s', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $name, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($returnType) as $callableType) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() return type has no signature specified for %s.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $messages; } } */ final class CallToStaticMethodStatementWithoutSideEffectsRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(RuleLevelHelper $ruleLevelHelper, ReflectionProvider $reflectionProvider) { $this->ruleLevelHelper = $ruleLevelHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return NoopExpressionNode::class; } public function processNode(Node $node, Scope $scope) : array { $staticCall = $node->getOriginalExpr(); if (!$staticCall instanceof Node\Expr\StaticCall) { return []; } if (!$staticCall->name instanceof Node\Identifier) { return []; } $methodName = $staticCall->name->toString(); if ($staticCall->class instanceof Node\Name) { $className = $scope->resolveName($staticCall->class); if (!$this->reflectionProvider->hasClass($className)) { return []; } $calledOnType = new ObjectType($className); } else { $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $staticCall->class), '', static function (Type $type) use($methodName) : bool { return $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes(); }); $calledOnType = $typeResult->getType(); if ($calledOnType instanceof ErrorType) { return []; } } if (!$calledOnType->canCallMethods()->yes()) { return []; } if (!$calledOnType->hasMethod($methodName)->yes()) { return []; } $method = $calledOnType->getMethod($methodName, $scope); if (strtolower($method->getName()) === '__construct' || strtolower($method->getName()) === strtolower($method->getDeclaringClass()->getName())) { return []; } $methodResult = $scope->getType($staticCall); if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { return []; } return [RuleErrorBuilder::message(sprintf('Call to %s %s::%s() on a separate line has no effect.', $method->isStatic() ? 'static method' : 'method', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('staticMethod.resultUnused')->build()]; } } */ final class CallStaticMethodsRule implements Rule { /** * @var StaticMethodCallCheck */ private $methodCallCheck; /** * @var FunctionCallParametersCheck */ private $parametersCheck; public function __construct(\PHPStan\Rules\Methods\StaticMethodCallCheck $methodCallCheck, FunctionCallParametersCheck $parametersCheck) { $this->methodCallCheck = $methodCallCheck; $this->parametersCheck = $parametersCheck; } public function getNodeType() : string { return StaticCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } $methodName = $node->name->name; [$errors, $method] = $this->methodCallCheck->check($scope, $methodName, $node->class); if ($method === null) { return $errors; } $displayMethodName = SprintfHelper::escapeFormatString(sprintf('%s %s', $method->isStatic() ? 'Static method' : 'Method', $method->getDeclaringClass()->getDisplayName() . '::' . $method->getName() . '()')); $lowercasedMethodName = SprintfHelper::escapeFormatString(sprintf('%s %s', $method->isStatic() ? 'static method' : 'method', $method->getDeclaringClass()->getDisplayName() . '::' . $method->getName() . '()')); $errors = array_merge($errors, $this->parametersCheck->check(ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $method->getVariants(), $method->getNamedArgumentsVariants()), $scope, $method->getDeclaringClass()->isBuiltin(), $node, [$displayMethodName . ' invoked with %d parameter, %d required.', $displayMethodName . ' invoked with %d parameters, %d required.', $displayMethodName . ' invoked with %d parameter, at least %d required.', $displayMethodName . ' invoked with %d parameters, at least %d required.', $displayMethodName . ' invoked with %d parameter, %d-%d required.', $displayMethodName . ' invoked with %d parameters, %d-%d required.', 'Parameter %s of ' . $lowercasedMethodName . ' expects %s, %s given.', 'Result of ' . $lowercasedMethodName . ' (void) is used.', 'Parameter %s of ' . $lowercasedMethodName . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to method ' . $lowercasedMethodName, 'Missing parameter $%s in call to ' . $lowercasedMethodName . '.', 'Unknown parameter $%s in call to ' . $lowercasedMethodName . '.', 'Return type of call to ' . $lowercasedMethodName . ' contains unresolvable type.', 'Parameter %s of ' . $lowercasedMethodName . ' contains unresolvable type.', $displayMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.'], 'staticMethod', $method->acceptsNamedArguments())); return $errors; } } */ final class MissingMethodImplementationRule implements Rule { public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); if ($classReflection->isInterface()) { return []; } if ($classReflection->isAbstract()) { return []; } $messages = []; try { $nativeMethods = $classReflection->getNativeReflection()->getMethods(); } catch (IdentifierNotFound $e) { return []; } foreach ($nativeMethods as $method) { if (!$method->isAbstract()) { continue; } $declaringClass = $method->getDeclaringClass(); $classLikeDescription = 'Non-abstract class'; if ($classReflection->isEnum()) { $classLikeDescription = 'Enum'; } $messages[] = RuleErrorBuilder::message(sprintf('%s %s contains abstract method %s() from %s %s.', $classLikeDescription, $classReflection->getDisplayName(), $method->getName(), $declaringClass->isInterface() ? 'interface' : 'class', $declaringClass->getName()))->nonIgnorable()->identifier('method.abstract')->build(); } return $messages; } } */ final class MethodSignatureRule implements Rule { /** * @var PhpClassReflectionExtension */ private $phpClassReflectionExtension; /** * @var bool */ private $reportMaybes; /** * @var bool */ private $reportStatic; /** * @var bool */ private $abstractTraitMethod; public function __construct(PhpClassReflectionExtension $phpClassReflectionExtension, bool $reportMaybes, bool $reportStatic, bool $abstractTraitMethod) { $this->phpClassReflectionExtension = $phpClassReflectionExtension; $this->reportMaybes = $reportMaybes; $this->reportStatic = $reportStatic; $this->abstractTraitMethod = $abstractTraitMethod; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); $methodName = $method->getName(); if ($methodName === '__construct') { return []; } if (!$this->reportStatic && $method->isStatic()) { return []; } if ($method->isPrivate()) { return []; } $errors = []; $declaringClass = $method->getDeclaringClass(); foreach ($this->collectParentMethods($methodName, $method->getDeclaringClass()) as [$parentMethod, $parentMethodDeclaringClass]) { $parentVariants = $parentMethod->getVariants(); if (count($parentVariants) !== 1) { continue; } $parentVariant = $parentVariants[0]; [$returnTypeCompatibility, $returnType, $parentReturnType] = $this->checkReturnTypeCompatibility($declaringClass, $method, $parentVariant); if ($returnTypeCompatibility->no() || !$returnTypeCompatibility->yes() && $this->reportMaybes) { $builder = RuleErrorBuilder::message(sprintf('Return type (%s) of method %s::%s() should be %s with return type (%s) of method %s::%s()', $returnType->describe(VerbosityLevel::value()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $returnTypeCompatibility->no() ? 'compatible' : 'covariant', $parentReturnType->describe(VerbosityLevel::value()), $parentMethodDeclaringClass->getDisplayName(), $parentMethod->getName()))->identifier('method.childReturnType'); if ($parentMethod->getDeclaringClass()->getName() === Rule::class && strtolower($methodName) === 'processnode') { $ruleErrorType = new ObjectType(RuleError::class); $identifierRuleErrorType = new ObjectType(IdentifierRuleError::class); $listOfIdentifierRuleErrors = new IntersectionType([new ArrayType(IntegerRangeType::fromInterval(0, null), $identifierRuleErrorType), new AccessoryArrayListType()]); if ($listOfIdentifierRuleErrors->isSuperTypeOf($parentReturnType)->yes()) { $returnValueType = $returnType->getIterableValueType(); if (!$returnValueType->isString()->no()) { $builder->tip('Rules can no longer return plain strings. See: https://phpstan.org/blog/using-rule-error-builder'); } elseif ($ruleErrorType->isSuperTypeOf($returnValueType)->yes() && !$identifierRuleErrorType->isSuperTypeOf($returnValueType)->yes()) { $builder->tip('Errors are missing identifiers. See: https://phpstan.org/blog/using-rule-error-builder'); } elseif (!$returnType->isList()->yes()) { $builder->tip('Return type must be a list. See: https://phpstan.org/blog/using-rule-error-builder'); } } } $errors[] = $builder->build(); } $parameterResults = $this->checkParameterTypeCompatibility($declaringClass, $method->getParameters(), $parentVariant->getParameters()); foreach ($parameterResults as $parameterIndex => [$parameterResult, $parameterType, $parentParameterType]) { if ($parameterResult->yes()) { continue; } if (!$parameterResult->no() && !$this->reportMaybes) { continue; } $parameter = $method->getParameters()[$parameterIndex]; $parentParameter = $parentVariant->getParameters()[$parameterIndex]; $errors[] = RuleErrorBuilder::message(sprintf('Parameter #%d $%s (%s) of method %s::%s() should be %s with parameter $%s (%s) of method %s::%s()', $parameterIndex + 1, $parameter->getName(), $parameterType->describe(VerbosityLevel::value()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $parameterResult->no() ? 'compatible' : 'contravariant', $parentParameter->getName(), $parentParameterType->describe(VerbosityLevel::value()), $parentMethodDeclaringClass->getDisplayName(), $parentMethod->getName()))->identifier('method.childParameterType')->build(); } } return $errors; } /** * @return list */ private function collectParentMethods(string $methodName, ClassReflection $class) : array { $parentMethods = []; $parentClass = $class->getParentClass(); if ($parentClass !== null && $parentClass->hasNativeMethod($methodName)) { $parentMethod = $parentClass->getNativeMethod($methodName); if (!$parentMethod->isPrivate()) { $parentMethods[] = [$parentMethod, $parentMethod->getDeclaringClass()]; } } foreach ($class->getInterfaces() as $interface) { if (!$interface->hasNativeMethod($methodName)) { continue; } $method = $interface->getNativeMethod($methodName); $parentMethods[] = [$method, $method->getDeclaringClass()]; } if ($this->abstractTraitMethod) { foreach ($class->getTraits(\true) as $trait) { $nativeTraitReflection = $trait->getNativeReflection(); if (!$nativeTraitReflection->hasMethod($methodName)) { continue; } $methodReflection = $nativeTraitReflection->getMethod($methodName); $isAbstract = $methodReflection->isAbstract(); if (!$isAbstract) { continue; } $declaringTrait = $trait->getNativeMethod($methodName)->getDeclaringClass(); $parentMethods[] = [$this->phpClassReflectionExtension->createUserlandMethodReflection($trait, $class, new NativeBuiltinMethodReflection($methodReflection), $declaringTrait->getName()), $declaringTrait]; } } return $parentMethods; } /** * @return array{TrinaryLogic, Type, Type} */ private function checkReturnTypeCompatibility(ClassReflection $declaringClass, ParametersAcceptorWithPhpDocs $currentVariant, ParametersAcceptorWithPhpDocs $parentVariant) : array { $returnType = TypehintHelper::decideType($currentVariant->getNativeReturnType(), TemplateTypeHelper::resolveToBounds($currentVariant->getPhpDocReturnType())); $originalParentReturnType = TypehintHelper::decideType($parentVariant->getNativeReturnType(), TemplateTypeHelper::resolveToBounds($parentVariant->getPhpDocReturnType())); $parentReturnType = $this->transformStaticType($declaringClass, $originalParentReturnType); // Allow adding `void` return type hints when the parent defines no return type if ($returnType->isVoid()->yes() && $parentReturnType instanceof MixedType) { return [TrinaryLogic::createYes(), $returnType, $parentReturnType]; } // We can return anything if ($parentReturnType->isVoid()->yes()) { return [TrinaryLogic::createYes(), $returnType, $parentReturnType]; } return [$parentReturnType->isSuperTypeOf($returnType), TypehintHelper::decideType($currentVariant->getNativeReturnType(), $currentVariant->getPhpDocReturnType()), $originalParentReturnType]; } /** * @param ParameterReflectionWithPhpDocs[] $parameters * @param ParameterReflectionWithPhpDocs[] $parentParameters * @return array */ private function checkParameterTypeCompatibility(ClassReflection $declaringClass, array $parameters, array $parentParameters) : array { $parameterResults = []; $numberOfParameters = min(count($parameters), count($parentParameters)); for ($i = 0; $i < $numberOfParameters; $i++) { $parameter = $parameters[$i]; $parentParameter = $parentParameters[$i]; $parameterType = TypehintHelper::decideType($parameter->getNativeType(), TemplateTypeHelper::resolveToBounds($parameter->getPhpDocType())); $originalParameterType = TypehintHelper::decideType($parentParameter->getNativeType(), TemplateTypeHelper::resolveToBounds($parentParameter->getPhpDocType())); $parentParameterType = $this->transformStaticType($declaringClass, $originalParameterType); $parameterResults[] = [$parameterType->isSuperTypeOf($parentParameterType), TypehintHelper::decideType($parameter->getNativeType(), $parameter->getPhpDocType()), $originalParameterType]; } return $parameterResults; } private function transformStaticType(ClassReflection $declaringClass, Type $type) : Type { return TypeTraverser::map($type, static function (Type $type, callable $traverse) use($declaringClass) : Type { if ($type instanceof GenericStaticType) { if ($declaringClass->isFinal()) { $changedType = $type->changeBaseClass($declaringClass)->getStaticObjectType(); } else { $changedType = $type->changeBaseClass($declaringClass); } return $traverse($changedType); } if ($type instanceof StaticType) { if ($declaringClass->isFinal()) { $changedType = new ObjectType($declaringClass->getName()); } else { $changedType = $type->changeBaseClass($declaringClass); } return $traverse($changedType); } return $traverse($type); }); } } */ final class MissingMethodSelfOutTypeRule implements Rule { /** * @var MissingTypehintCheck */ private $missingTypehintCheck; public function __construct(MissingTypehintCheck $missingTypehintCheck) { $this->missingTypehintCheck = $missingTypehintCheck; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $methodReflection = $node->getMethodReflection(); $selfOutType = $methodReflection->getSelfOutType(); if ($selfOutType === null) { return []; } $classReflection = $methodReflection->getDeclaringClass(); $phpDocTagMessage = 'PHPDoc tag @phpstan-self-out'; $messages = []; foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($selfOutType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() has %s with no value type specified in iterable type %s.', $classReflection->getDisplayName(), $methodReflection->getName(), $phpDocTagMessage, $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($selfOutType) as [$name, $genericTypeNames]) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() has %s with generic %s but does not specify its types: %s', $classReflection->getDisplayName(), $methodReflection->getName(), $phpDocTagMessage, $name, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($selfOutType) as $callableType) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() has %s with no signature specified for %s.', $classReflection->getDisplayName(), $methodReflection->getName(), $phpDocTagMessage, $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $messages; } } */ final class ExistingClassesInTypehintsRule implements Rule { /** * @var FunctionDefinitionCheck */ private $check; public function __construct(FunctionDefinitionCheck $check) { $this->check = $check; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $methodReflection = $node->getMethodReflection(); $className = SprintfHelper::escapeFormatString($node->getClassReflection()->getDisplayName()); $methodName = SprintfHelper::escapeFormatString($methodReflection->getName()); return $this->check->checkClassMethod($methodReflection, $node->getOriginalNode(), sprintf('Parameter $%%s of method %s::%s() has invalid type %%s.', $className, $methodName), sprintf('Method %s::%s() has invalid return type %%s.', $className, $methodName), sprintf('Method %s::%s() uses native union types but they\'re supported only on PHP 8.0 and later.', $className, $methodName), sprintf('Template type %%s of method %s::%s() is not referenced in a parameter.', $className, $methodName), sprintf('Parameter $%%s of method %s::%s() has unresolvable native type.', $className, $methodName), sprintf('Method %s::%s() has unresolvable native return type.', $className, $methodName), sprintf('Method %s::%s() has invalid @phpstan-self-out type %%s.', $className, $methodName)); } } */ final class MethodCallableRule implements Rule { /** * @var MethodCallCheck */ private $methodCallCheck; /** * @var PhpVersion */ private $phpVersion; public function __construct(\PHPStan\Rules\Methods\MethodCallCheck $methodCallCheck, PhpVersion $phpVersion) { $this->methodCallCheck = $methodCallCheck; $this->phpVersion = $phpVersion; } public function getNodeType() : string { return MethodCallableNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$this->phpVersion->supportsFirstClassCallables()) { return [RuleErrorBuilder::message('First-class callables are supported only on PHP 8.1 and later.')->nonIgnorable()->identifier('callable.notSupported')->build()]; } $methodName = $node->getName(); if (!$methodName instanceof Node\Identifier) { return []; } $methodNameName = $methodName->toString(); [$errors, $methodReflection] = $this->methodCallCheck->check($scope, $methodNameName, $node->getVar()); if ($methodReflection === null) { return $errors; } $declaringClass = $methodReflection->getDeclaringClass(); if ($declaringClass->hasNativeMethod($methodNameName)) { return $errors; } $messagesMethodName = SprintfHelper::escapeFormatString($declaringClass->getDisplayName() . '::' . $methodReflection->getName() . '()'); $errors[] = RuleErrorBuilder::message(sprintf('Creating callable from a non-native method %s.', $messagesMethodName))->identifier('callable.nonNativeMethod')->build(); return $errors; } } */ final class MethodVisibilityInInterfaceRule implements Rule { public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); if ($method->isPublic()) { return []; } $classReflection = $scope->getClassReflection(); if ($classReflection === null) { return []; } if (!$classReflection->isInterface()) { return []; } return [RuleErrorBuilder::message(sprintf('Method %s::%s() cannot use non-public visibility in interface.', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('method.visibility')->nonIgnorable()->build()]; } } */ final class AbstractPrivateMethodRule implements Rule { public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); if (!$method->isPrivate()) { return []; } if (!$method->isAbstract()->yes()) { return []; } if ($scope->isInTrait()) { return []; } $classReflection = $scope->getClassReflection(); if ($classReflection === null) { return []; } if (!$classReflection->isAbstract() && !$classReflection->isInterface()) { return []; } return [RuleErrorBuilder::message(sprintf('Private method %s::%s() cannot be abstract.', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('method.abstractPrivate')->nonIgnorable()->build()]; } } */ final class OverridingMethodRule implements Rule { /** * @var PhpVersion */ private $phpVersion; /** * @var MethodSignatureRule */ private $methodSignatureRule; /** * @var bool */ private $checkPhpDocMethodSignatures; /** * @var MethodParameterComparisonHelper */ private $methodParameterComparisonHelper; /** * @var PhpClassReflectionExtension */ private $phpClassReflectionExtension; /** * @var bool */ private $genericPrototypeMessage; /** * @var bool */ private $finalByPhpDoc; /** * @var bool */ private $checkMissingOverrideMethodAttribute; public function __construct(PhpVersion $phpVersion, \PHPStan\Rules\Methods\MethodSignatureRule $methodSignatureRule, bool $checkPhpDocMethodSignatures, \PHPStan\Rules\Methods\MethodParameterComparisonHelper $methodParameterComparisonHelper, PhpClassReflectionExtension $phpClassReflectionExtension, bool $genericPrototypeMessage, bool $finalByPhpDoc, bool $checkMissingOverrideMethodAttribute) { $this->phpVersion = $phpVersion; $this->methodSignatureRule = $methodSignatureRule; $this->checkPhpDocMethodSignatures = $checkPhpDocMethodSignatures; $this->methodParameterComparisonHelper = $methodParameterComparisonHelper; $this->phpClassReflectionExtension = $phpClassReflectionExtension; $this->genericPrototypeMessage = $genericPrototypeMessage; $this->finalByPhpDoc = $finalByPhpDoc; $this->checkMissingOverrideMethodAttribute = $checkMissingOverrideMethodAttribute; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); $prototypeData = $this->findPrototype($node->getClassReflection(), $method->getName()); if ($prototypeData === null) { if (strtolower($method->getName()) === '__construct') { $parent = $method->getDeclaringClass()->getParentClass(); if ($parent !== null && $parent->hasConstructor()) { $parentConstructor = $parent->getConstructor(); if ($parentConstructor->isFinalByKeyword()->yes()) { return $this->addErrors([RuleErrorBuilder::message(sprintf('Method %s::%s() overrides final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $parent->getDisplayName($this->genericPrototypeMessage), $parentConstructor->getName()))->nonIgnorable()->identifier('method.parentMethodFinal')->build()], $node, $scope); } if ($parentConstructor->isFinal()->yes() && $this->finalByPhpDoc) { return $this->addErrors([RuleErrorBuilder::message(sprintf('Method %s::%s() overrides @final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $parent->getDisplayName($this->genericPrototypeMessage), $parentConstructor->getName()))->identifier('method.parentMethodFinalByPhpDoc')->build()], $node, $scope); } } } if ($this->phpVersion->supportsOverrideAttribute() && $this->hasOverrideAttribute($node->getOriginalNode())) { return [RuleErrorBuilder::message(sprintf('Method %s::%s() has #[\\Override] attribute but does not override any method.', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->nonIgnorable()->identifier('method.override')->build()]; } return []; } [$prototype, $prototypeDeclaringClass, $checkVisibility] = $prototypeData; $messages = []; if ($this->phpVersion->supportsOverrideAttribute() && $this->checkMissingOverrideMethodAttribute && !$scope->isInTrait() && !$this->hasOverrideAttribute($node->getOriginalNode())) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() overrides method %s::%s() but is missing the #[\\Override] attribute.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('method.missingOverride')->build(); } if ($prototype->isFinalByKeyword()->yes()) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() overrides final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->nonIgnorable()->identifier('method.parentMethodFinal')->build(); } elseif ($prototype->isFinal()->yes() && $this->finalByPhpDoc) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() overrides @final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('method.parentMethodFinalByPhpDoc')->build(); } if ($prototype->isStatic()) { if (!$method->isStatic()) { $messages[] = RuleErrorBuilder::message(sprintf('Non-static method %s::%s() overrides static method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->nonIgnorable()->identifier('method.nonStatic')->build(); } } elseif ($method->isStatic()) { $messages[] = RuleErrorBuilder::message(sprintf('Static method %s::%s() overrides non-static method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->nonIgnorable()->identifier('method.static')->build(); } if ($checkVisibility) { if ($prototype->isPublic()) { if (!$method->isPublic()) { $messages[] = RuleErrorBuilder::message(sprintf('%s method %s::%s() overriding public method %s::%s() should also be public.', $method->isPrivate() ? 'Private' : 'Protected', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->nonIgnorable()->identifier('method.visibility')->build(); } } elseif ($method->isPrivate()) { $messages[] = RuleErrorBuilder::message(sprintf('Private method %s::%s() overriding protected method %s::%s() should be protected or public.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->nonIgnorable()->identifier('method.visibility')->build(); } } $prototypeVariants = $prototype->getVariants(); if (count($prototypeVariants) !== 1) { return $this->addErrors($messages, $node, $scope); } $prototypeVariant = $prototypeVariants[0]; $methodReturnType = $method->getNativeReturnType(); $realPrototype = $method->getPrototype(); if ($realPrototype instanceof MethodPrototypeReflection && $this->phpVersion->hasTentativeReturnTypes() && $realPrototype->getTentativeReturnType() !== null && !$this->hasReturnTypeWillChangeAttribute($node->getOriginalNode()) && count($prototypeDeclaringClass->getNativeReflection()->getMethod($prototype->getName())->getAttributes('ReturnTypeWillChange')) === 0) { if (!$this->methodParameterComparisonHelper->isReturnTypeCompatible($realPrototype->getTentativeReturnType(), $method->getNativeReturnType(), \true)) { $messages[] = RuleErrorBuilder::message(sprintf('Return type %s of method %s::%s() is not covariant with tentative return type %s of method %s::%s().', $methodReturnType->describe(VerbosityLevel::typeOnly()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $realPrototype->getTentativeReturnType()->describe(VerbosityLevel::typeOnly()), $realPrototype->getDeclaringClass()->getDisplayName($this->genericPrototypeMessage), $realPrototype->getName()))->tip('Make it covariant, or use the #[\\ReturnTypeWillChange] attribute to temporarily suppress the error.')->nonIgnorable()->identifier('method.tentativeReturnType')->build(); } } $messages = array_merge($messages, $this->methodParameterComparisonHelper->compare($prototype, $prototypeDeclaringClass, $method)); if (!$prototypeVariant instanceof FunctionVariantWithPhpDocs) { return $this->addErrors($messages, $node, $scope); } $prototypeReturnType = $prototypeVariant->getNativeReturnType(); $reportReturnType = \true; if ($this->phpVersion->hasTentativeReturnTypes()) { $reportReturnType = !$realPrototype instanceof MethodPrototypeReflection || $realPrototype->getTentativeReturnType() === null || $prototype->isInternal()->no(); } else { if ($realPrototype instanceof MethodPrototypeReflection && $realPrototype->isInternal()) { if ($prototype->isInternal()->yes() && $prototypeDeclaringClass->getName() !== $realPrototype->getDeclaringClass()->getName()) { $realPrototypeVariant = $realPrototype->getVariants()[0]; if ($prototypeReturnType instanceof MixedType && !$prototypeReturnType->isExplicitMixed() && (!$realPrototypeVariant->getReturnType() instanceof MixedType || $realPrototypeVariant->getReturnType()->isExplicitMixed())) { $reportReturnType = \false; } } if ($reportReturnType && $prototype->isInternal()->yes()) { $reportReturnType = !$this->hasReturnTypeWillChangeAttribute($node->getOriginalNode()); } } } if ($reportReturnType && !$this->methodParameterComparisonHelper->isReturnTypeCompatible($prototypeReturnType, $methodReturnType, $this->phpVersion->supportsReturnCovariance())) { if ($this->phpVersion->supportsReturnCovariance()) { $messages[] = RuleErrorBuilder::message(sprintf('Return type %s of method %s::%s() is not covariant with return type %s of method %s::%s().', $methodReturnType->describe(VerbosityLevel::typeOnly()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeReturnType->describe(VerbosityLevel::typeOnly()), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->nonIgnorable()->identifier('method.childReturnType')->build(); } else { $messages[] = RuleErrorBuilder::message(sprintf('Return type %s of method %s::%s() is not compatible with return type %s of method %s::%s().', $methodReturnType->describe(VerbosityLevel::typeOnly()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeReturnType->describe(VerbosityLevel::typeOnly()), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->nonIgnorable()->identifier('method.childReturnType')->build(); } } return $this->addErrors($messages, $node, $scope); } /** * @param list $errors * @return list */ private function addErrors(array $errors, InClassMethodNode $classMethod, Scope $scope) : array { if (count($errors) > 0) { return $errors; } if (!$this->checkPhpDocMethodSignatures) { return $errors; } return $this->methodSignatureRule->processNode($classMethod, $scope); } private function hasReturnTypeWillChangeAttribute(Node\Stmt\ClassMethod $method) : bool { foreach ($method->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { if ($attr->name->toLowerString() === 'returntypewillchange') { return \true; } } } return \false; } private function hasOverrideAttribute(Node\Stmt\ClassMethod $method) : bool { foreach ($method->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { if ($attr->name->toLowerString() === 'override') { return \true; } } } return \false; } /** * @return array{ExtendedMethodReflection, ClassReflection, bool}|null */ private function findPrototype(ClassReflection $classReflection, string $methodName) : ?array { foreach ($classReflection->getImmediateInterfaces() as $immediateInterface) { if ($immediateInterface->hasNativeMethod($methodName)) { $method = $immediateInterface->getNativeMethod($methodName); return [$method, $method->getDeclaringClass(), \true]; } } if ($this->phpVersion->supportsAbstractTraitMethods()) { foreach ($classReflection->getTraits(\true) as $trait) { $nativeTraitReflection = $trait->getNativeReflection(); if (!$nativeTraitReflection->hasMethod($methodName)) { continue; } $methodReflection = $nativeTraitReflection->getMethod($methodName); $isAbstract = $methodReflection->isAbstract(); if ($isAbstract) { $declaringTrait = $trait->getNativeMethod($methodName)->getDeclaringClass(); return [$this->phpClassReflectionExtension->createUserlandMethodReflection($trait, $classReflection, new NativeBuiltinMethodReflection($methodReflection), $declaringTrait->getName()), $declaringTrait, \false]; } } } $parentClass = $classReflection->getParentClass(); if ($parentClass === null) { return null; } if (!$parentClass->hasNativeMethod($methodName)) { return null; } $method = $parentClass->getNativeMethod($methodName); if ($method->isPrivate()) { return null; } $declaringClass = $method->getDeclaringClass(); if ($declaringClass->hasConstructor()) { if ($method->getName() === $declaringClass->getConstructor()->getName()) { $prototype = $method->getPrototype(); if ($prototype instanceof PhpMethodReflection || $prototype instanceof MethodPrototypeReflection || $prototype instanceof NativeMethodReflection) { $abstract = $prototype->isAbstract(); if (is_bool($abstract)) { if (!$abstract) { return null; } } elseif (!$abstract->yes()) { return null; } } } elseif (strtolower($methodName) === '__construct') { return null; } } return [$method, $method->getDeclaringClass(), \true]; } } reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->checkFunctionNameCase = $checkFunctionNameCase; $this->reportMagicMethods = $reportMagicMethods; } /** * @return array{list, ExtendedMethodReflection|null} */ public function check(Scope $scope, string $methodName, Expr $var) : array { $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $var), sprintf('Call to method %s() on an unknown class %%s.', SprintfHelper::escapeFormatString($methodName)), static function (Type $type) use($methodName) : bool { return $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return [$typeResult->getUnknownClassErrors(), null]; } $typeForDescribe = $type; if ($type instanceof StaticType) { $typeForDescribe = $type->getStaticObjectType(); } if (!$type->canCallMethods()->yes() || $type->isClassStringType()->yes()) { return [[RuleErrorBuilder::message(sprintf('Cannot call method %s() on %s.', $methodName, $typeForDescribe->describe(VerbosityLevel::typeOnly())))->identifier('method.nonObject')->build()], null]; } if (!$type->hasMethod($methodName)->yes()) { $directClassNames = $typeResult->getReferencedClasses(); if (!$this->reportMagicMethods) { foreach ($directClassNames as $className) { if (!$this->reflectionProvider->hasClass($className)) { continue; } $classReflection = $this->reflectionProvider->getClass($className); if ($classReflection->hasNativeMethod('__call')) { return [[], null]; } } } if (count($directClassNames) === 1) { $referencedClass = $directClassNames[0]; $methodClassReflection = $this->reflectionProvider->getClass($referencedClass); $parentClassReflection = $methodClassReflection->getParentClass(); while ($parentClassReflection !== null) { if ($parentClassReflection->hasMethod($methodName)) { $methodReflection = $parentClassReflection->getMethod($methodName, $scope); return [[RuleErrorBuilder::message(sprintf('Call to private method %s() of parent class %s.', $methodReflection->getName(), $parentClassReflection->getDisplayName()))->identifier('method.private')->build()], $methodReflection]; } $parentClassReflection = $parentClassReflection->getParentClass(); } } return [[RuleErrorBuilder::message(sprintf('Call to an undefined method %s::%s().', $typeForDescribe->describe(VerbosityLevel::typeOnly()), $methodName))->identifier('method.notFound')->build()], null]; } $methodReflection = $type->getMethod($methodName, $scope); $declaringClass = $methodReflection->getDeclaringClass(); $messagesMethodName = SprintfHelper::escapeFormatString($declaringClass->getDisplayName() . '::' . $methodReflection->getName() . '()'); $errors = []; if (!$scope->canCallMethod($methodReflection)) { $errors[] = RuleErrorBuilder::message(sprintf('Call to %s method %s() of class %s.', $methodReflection->isPrivate() ? 'private' : 'protected', $methodReflection->getName(), $declaringClass->getDisplayName()))->identifier(sprintf('method.%s', $methodReflection->isPrivate() ? 'private' : 'protected'))->build(); } if ($this->checkFunctionNameCase && strtolower($methodReflection->getName()) === strtolower($methodName) && $methodReflection->getName() !== $methodName) { $errors[] = RuleErrorBuilder::message(sprintf('Call to method %s with incorrect case: %s', $messagesMethodName, $methodName))->identifier('method.nameCase')->build(); } return [$errors, $methodReflection]; } } */ final class AbstractMethodInNonAbstractClassRule implements Rule { public function getNodeType() : string { return Node\Stmt\ClassMethod::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $class = $scope->getClassReflection(); if (!$class->isAbstract() && $node->isAbstract()) { if ($class->isEnum()) { $lowercasedMethodName = $node->name->toLowerString(); if ($lowercasedMethodName === 'cases') { return []; } if ($class->isBackedEnum()) { if (in_array($lowercasedMethodName, ['from', 'tryfrom'], \true)) { return []; } } } $description = $class->getClassTypeDescription(); return [RuleErrorBuilder::message(sprintf('%s %s contains abstract method %s().', $description === 'Class' ? 'Non-abstract class' : $description, $class->getDisplayName(), $node->name->toString()))->nonIgnorable()->identifier('method.abstract')->build()]; } if (!$class->isAbstract() && !$class->isInterface() && $node->getStmts() === null) { return [RuleErrorBuilder::message(sprintf('Non-abstract method %s::%s() must contain a body.', $class->getDisplayName(), $node->name->toString()))->nonIgnorable()->identifier('method.nonAbstract')->build()]; } return []; } } */ final class CallToMethodStatementWithoutSideEffectsRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return NoopExpressionNode::class; } public function processNode(Node $node, Scope $scope) : array { $methodCall = $node->getOriginalExpr(); if ($methodCall instanceof Node\Expr\NullsafeMethodCall) { $scope = $scope->filterByTruthyValue(new Node\Expr\BinaryOp\NotIdentical($methodCall->var, new Node\Expr\ConstFetch(new Node\Name('null')))); } elseif (!$methodCall instanceof Node\Expr\MethodCall) { return []; } if (!$methodCall->name instanceof Node\Identifier) { return []; } $methodName = $methodCall->name->toString(); $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $methodCall->var), '', static function (Type $type) use($methodName) : bool { return $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes(); }); $calledOnType = $typeResult->getType(); if ($calledOnType instanceof ErrorType) { return []; } if (!$calledOnType->canCallMethods()->yes()) { return []; } if (!$calledOnType->hasMethod($methodName)->yes()) { return []; } $methodResult = $scope->getType($methodCall); if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { return []; } $method = $calledOnType->getMethod($methodName, $scope); return [RuleErrorBuilder::message(sprintf('Call to %s %s::%s() on a separate line has no effect.', $method->isStatic() ? 'static method' : 'method', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('method.resultUnused')->build()]; } } reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->classCheck = $classCheck; $this->checkFunctionNameCase = $checkFunctionNameCase; $this->reportMagicMethods = $reportMagicMethods; } /** * @param Name|Expr $class * @return array{list, ExtendedMethodReflection|null} */ public function check(Scope $scope, string $methodName, $class) : array { $errors = []; $isAbstract = \false; if ($class instanceof Name) { $classStringType = $scope->getType(new Expr\ClassConstFetch($class, 'class')); if ($classStringType->hasMethod($methodName)->yes()) { return [[], null]; } $className = (string) $class; $lowercasedClassName = strtolower($className); if (in_array($lowercasedClassName, ['self', 'static'], \true)) { if (!$scope->isInClass()) { return [[RuleErrorBuilder::message(sprintf('Calling %s::%s() outside of class scope.', $className, $methodName))->identifier(sprintf('outOfClass.%s', $lowercasedClassName))->build()], null]; } $classType = $scope->resolveTypeByName($class); } elseif ($lowercasedClassName === 'parent') { if (!$scope->isInClass()) { return [[RuleErrorBuilder::message(sprintf('Calling %s::%s() outside of class scope.', $className, $methodName))->identifier(sprintf('outOfClass.parent'))->build()], null]; } $currentClassReflection = $scope->getClassReflection(); if ($currentClassReflection->getParentClass() === null) { return [[RuleErrorBuilder::message(sprintf('%s::%s() calls parent::%s() but %s does not extend any class.', $scope->getClassReflection()->getDisplayName(), $scope->getFunctionName(), $methodName, $scope->getClassReflection()->getDisplayName()))->identifier('class.noParent')->build()], null]; } if ($scope->getFunctionName() === null) { throw new ShouldNotHappenException(); } $classType = $scope->resolveTypeByName($class); } else { if (!$this->reflectionProvider->hasClass($className)) { if ($scope->isInClassExists($className)) { return [[], null]; } return [[RuleErrorBuilder::message(sprintf('Call to static method %s() on an unknown class %s.', $methodName, $className))->identifier('class.notFound')->discoveringSymbolsTip()->build()], null]; } $errors = $this->classCheck->checkClassNames([new ClassNameNodePair($className, $class)]); $classType = $scope->resolveTypeByName($class); } $classReflection = $classType->getClassReflection(); if ($classReflection !== null && $classReflection->hasNativeMethod($methodName) && $lowercasedClassName !== 'static') { $nativeMethodReflection = $classReflection->getNativeMethod($methodName); if ($nativeMethodReflection instanceof PhpMethodReflection || $nativeMethodReflection instanceof NativeMethodReflection) { $isAbstract = $nativeMethodReflection->isAbstract(); if ($isAbstract instanceof TrinaryLogic) { $isAbstract = $isAbstract->yes(); } } } } else { $classTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $class), sprintf('Call to static method %s() on an unknown class %%s.', SprintfHelper::escapeFormatString($methodName)), static function (Type $type) use($methodName) : bool { return $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes(); }); $classType = $classTypeResult->getType(); if ($classType instanceof ErrorType) { return [$classTypeResult->getUnknownClassErrors(), null]; } } if ($classType instanceof GenericClassStringType) { $classType = $classType->getGenericType(); if (!$classType->isObject()->yes()) { return [[], null]; } } elseif ($classType->isString()->yes()) { return [[], null]; } $typeForDescribe = $classType; if ($classType instanceof StaticType) { $typeForDescribe = $classType->getStaticObjectType(); } $classType = TypeCombinator::remove($classType, new StringType()); if (!$classType->canCallMethods()->yes()) { return [array_merge($errors, [RuleErrorBuilder::message(sprintf('Cannot call static method %s() on %s.', $methodName, $typeForDescribe->describe(VerbosityLevel::typeOnly())))->identifier('staticMethod.nonObject')->build()]), null]; } if (!$classType->hasMethod($methodName)->yes()) { if (!$this->reportMagicMethods) { foreach ($classType->getObjectClassNames() as $className) { if (!$this->reflectionProvider->hasClass($className)) { continue; } $classReflection = $this->reflectionProvider->getClass($className); if ($classReflection->hasNativeMethod('__callStatic')) { return [[], null]; } } } return [array_merge($errors, [RuleErrorBuilder::message(sprintf('Call to an undefined static method %s::%s().', $typeForDescribe->describe(VerbosityLevel::typeOnly()), $methodName))->identifier('staticMethod.notFound')->build()]), null]; } $method = $classType->getMethod($methodName, $scope); if (!$method->isStatic()) { $function = $scope->getFunction(); $scopeIsInMethodClassOrSubClass = TrinaryLogic::createFromBoolean($scope->isInClass())->lazyAnd($classType->getObjectClassNames(), static function (string $objectClassName) use($scope) { return TrinaryLogic::createFromBoolean($scope->isInClass() && ($scope->getClassReflection()->getName() === $objectClassName || $scope->getClassReflection()->isSubclassOf($objectClassName))); }); if (!$function instanceof MethodReflection || $function->isStatic() || $scopeIsInMethodClassOrSubClass->no()) { // per php-src docs, this method can be called statically, even if declared non-static if (strtolower($method->getName()) === 'loadhtml' && $method->getDeclaringClass()->getName() === DOMDocument::class) { return [[], null]; } return [array_merge($errors, [RuleErrorBuilder::message(sprintf('Static call to instance method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('method.staticCall')->build()]), $method]; } } if (!$scope->canCallMethod($method)) { $errors = array_merge($errors, [RuleErrorBuilder::message(sprintf('Call to %s %s %s() of class %s.', $method->isPrivate() ? 'private' : 'protected', $method->isStatic() ? 'static method' : 'method', $method->getName(), $method->getDeclaringClass()->getDisplayName()))->identifier(sprintf('staticMethod.%s', $method->isPrivate() ? 'private' : 'protected'))->build()]); } if ($isAbstract) { return [[RuleErrorBuilder::message(sprintf('Cannot call abstract%s method %s::%s().', $method->isStatic() ? ' static' : '', $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier(sprintf('%s.callToAbstract', $method->isStatic() ? 'staticMethod' : 'method'))->build()], $method]; } $lowercasedMethodName = SprintfHelper::escapeFormatString(sprintf('%s %s', $method->isStatic() ? 'static method' : 'method', $method->getDeclaringClass()->getDisplayName() . '::' . $method->getName() . '()')); if ($this->checkFunctionNameCase && $method->getName() !== $methodName) { $errors[] = RuleErrorBuilder::message(sprintf('Call to %s with incorrect case: %s', $lowercasedMethodName, $methodName))->identifier('staticMethod.nameCase')->build(); } return [$errors, $method]; } } phpVersion = $phpVersion; $this->genericPrototypeMessage = $genericPrototypeMessage; } /** * @return list */ public function compare(ExtendedMethodReflection $prototype, ClassReflection $prototypeDeclaringClass, PhpMethodFromParserNodeReflection $method, bool $ignorable = \false) : array { /** @var list $messages */ $messages = []; $prototypeVariant = $prototype->getVariants()[0]; $methodParameters = $method->getParameters(); $prototypeAfterVariadic = \false; foreach ($prototypeVariant->getParameters() as $i => $prototypeParameter) { if (!array_key_exists($i, $methodParameters)) { $error = RuleErrorBuilder::message(sprintf('Method %s::%s() overrides method %s::%s() but misses parameter #%d $%s.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName(), $i + 1, $prototypeParameter->getName()))->identifier('parameter.missing'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); continue; } $methodParameter = $methodParameters[$i]; if ($prototypeParameter->passedByReference()->no()) { if (!$methodParameter->passedByReference()->no()) { $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s of method %s::%s() is passed by reference but parameter #%d $%s of method %s::%s() is not passed by reference.', $i + 1, $methodParameter->getName(), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $i + 1, $prototypeParameter->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('parameter.byRef'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); } } elseif ($methodParameter->passedByReference()->no()) { $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s of method %s::%s() is not passed by reference but parameter #%d $%s of method %s::%s() is passed by reference.', $i + 1, $methodParameter->getName(), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $i + 1, $prototypeParameter->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('parameter.notByRef'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); } if ($prototypeParameter->isVariadic()) { $prototypeAfterVariadic = \true; if (!$methodParameter->isVariadic()) { if (!$methodParameter->isOptional()) { if (count($methodParameters) !== $i + 1) { $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s of method %s::%s() is not optional.', $i + 1, $methodParameter->getName(), $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('parameter.notOptional'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); continue; } $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s of method %s::%s() is not variadic but parameter #%d $%s of method %s::%s() is variadic.', $i + 1, $methodParameter->getName(), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $i + 1, $prototypeParameter->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('parameter.notVariadic'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); continue; } elseif (count($methodParameters) === $i + 1) { $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s of method %s::%s() is not variadic.', $i + 1, $methodParameter->getName(), $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('parameter.notVariadic'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); } } } elseif ($methodParameter->isVariadic()) { if ($this->phpVersion->supportsLessOverridenParametersWithVariadic()) { $remainingPrototypeParameters = array_slice($prototypeVariant->getParameters(), $i); foreach ($remainingPrototypeParameters as $j => $remainingPrototypeParameter) { if ($methodParameter->getNativeType()->isSuperTypeOf($remainingPrototypeParameter->getNativeType())->yes()) { continue; } $error = RuleErrorBuilder::message(sprintf('Parameter #%d ...$%s (%s) of method %s::%s() is not contravariant with parameter #%d $%s (%s) of method %s::%s().', $i + 1, $methodParameter->getName(), $methodParameter->getNativeType()->describe(VerbosityLevel::typeOnly()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $i + $j + 1, $remainingPrototypeParameter->getName(), $remainingPrototypeParameter->getNativeType()->describe(VerbosityLevel::typeOnly()), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('method.childParameterType'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); } break; } $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s of method %s::%s() is variadic but parameter #%d $%s of method %s::%s() is not variadic.', $i + 1, $methodParameter->getName(), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $i + 1, $prototypeParameter->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('parameter.variadic'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); continue; } if ($prototypeParameter->isOptional() && !$methodParameter->isOptional()) { $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s of method %s::%s() is required but parameter #%d $%s of method %s::%s() is optional.', $i + 1, $methodParameter->getName(), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $i + 1, $prototypeParameter->getName(), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('parameter.notOptional'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); } $methodParameterType = $methodParameter->getNativeType(); $prototypeParameterType = $prototypeParameter->getNativeType(); if (!$this->phpVersion->supportsParameterTypeWidening()) { if (!$methodParameterType->equals($prototypeParameterType)) { $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s (%s) of method %s::%s() does not match parameter #%d $%s (%s) of method %s::%s().', $i + 1, $methodParameter->getName(), $methodParameterType->describe(VerbosityLevel::typeOnly()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $i + 1, $prototypeParameter->getName(), $prototypeParameterType->describe(VerbosityLevel::typeOnly()), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('method.childParameterType'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); } continue; } if ($this->isParameterTypeCompatible($methodParameterType, $prototypeParameterType, $this->phpVersion->supportsParameterContravariance())) { continue; } if ($this->phpVersion->supportsParameterContravariance()) { $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s (%s) of method %s::%s() is not contravariant with parameter #%d $%s (%s) of method %s::%s().', $i + 1, $methodParameter->getName(), $methodParameterType->describe(VerbosityLevel::typeOnly()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $i + 1, $prototypeParameter->getName(), $prototypeParameterType->describe(VerbosityLevel::typeOnly()), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('method.childParameterType'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); } else { $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s (%s) of method %s::%s() is not compatible with parameter #%d $%s (%s) of method %s::%s().', $i + 1, $methodParameter->getName(), $methodParameterType->describe(VerbosityLevel::typeOnly()), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $i + 1, $prototypeParameter->getName(), $prototypeParameterType->describe(VerbosityLevel::typeOnly()), $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), $prototype->getName()))->identifier('method.childParameterType'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); } } if (!isset($i)) { $i = -1; } foreach ($methodParameters as $j => $methodParameter) { if ($j <= $i) { continue; } if ($j === count($methodParameters) - 1 && $prototypeAfterVariadic && !$methodParameter->isVariadic()) { $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s of method %s::%s() is not variadic.', $j + 1, $methodParameter->getName(), $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('parameter.notVariadic'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); continue; } if ($methodParameter->isOptional()) { continue; } $error = RuleErrorBuilder::message(sprintf('Parameter #%d $%s of method %s::%s() is not optional.', $j + 1, $methodParameter->getName(), $method->getDeclaringClass()->getDisplayName(), $method->getName()))->identifier('parameter.notOptional'); if (!$ignorable) { $error->nonIgnorable(); } $messages[] = $error->build(); continue; } return $messages; } public function isParameterTypeCompatible(Type $methodParameterType, Type $prototypeParameterType, bool $supportsContravariance) : bool { return $this->isTypeCompatible($methodParameterType, $prototypeParameterType, $supportsContravariance, \false); } public function isReturnTypeCompatible(Type $methodParameterType, Type $prototypeParameterType, bool $supportsCovariance) : bool { return $this->isTypeCompatible($methodParameterType, $prototypeParameterType, $supportsCovariance, \true); } private function isTypeCompatible(Type $methodParameterType, Type $prototypeParameterType, bool $supportsContravariance, bool $considerMixedExplicitness) : bool { if ($methodParameterType instanceof MixedType) { if ($considerMixedExplicitness && $prototypeParameterType instanceof MixedType) { return !$methodParameterType->isExplicitMixed() || $prototypeParameterType->isExplicitMixed(); } return \true; } if (!$supportsContravariance) { if (TypeCombinator::containsNull($methodParameterType)) { $prototypeParameterType = TypeCombinator::removeNull($prototypeParameterType); } $methodParameterType = TypeCombinator::removeNull($methodParameterType); if ($methodParameterType->equals($prototypeParameterType)) { return \true; } if ($methodParameterType instanceof IterableType) { if ($prototypeParameterType instanceof ArrayType) { return \true; } if ($prototypeParameterType->isObject()->yes() && $prototypeParameterType->getObjectClassNames() === [Traversable::class]) { return \true; } } return \false; } return $methodParameterType->isSuperTypeOf($prototypeParameterType)->yes(); } } */ final class IncompatibleDefaultParameterTypeRule implements Rule { public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); $errors = []; foreach ($node->getOriginalNode()->getParams() as $paramI => $param) { if ($param->default === null) { continue; } if ($param->var instanceof Node\Expr\Error || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $defaultValueType = $scope->getType($param->default); $parameter = $method->getParameters()[$paramI]; $parameterType = $parameter->getType(); $parameterType = TemplateTypeHelper::resolveToBounds($parameterType); $accepts = $parameterType->acceptsWithReason($defaultValueType, \true); if ($accepts->yes()) { continue; } $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $defaultValueType); $errors[] = RuleErrorBuilder::message(sprintf('Default value of the parameter #%d $%s (%s) of method %s::%s() is incompatible with type %s.', $paramI + 1, $param->var->name, $defaultValueType->describe($verbosityLevel), $method->getDeclaringClass()->getDisplayName(), $method->getName(), $parameterType->describe($verbosityLevel)))->line($param->getStartLine())->identifier('parameter.defaultValue')->acceptsReasonsTip($accepts->reasons)->build(); } return $errors; } } */ final class CallMethodsRule implements Rule { /** * @var MethodCallCheck */ private $methodCallCheck; /** * @var FunctionCallParametersCheck */ private $parametersCheck; public function __construct(\PHPStan\Rules\Methods\MethodCallCheck $methodCallCheck, FunctionCallParametersCheck $parametersCheck) { $this->methodCallCheck = $methodCallCheck; $this->parametersCheck = $parametersCheck; } public function getNodeType() : string { return MethodCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } $methodName = $node->name->name; [$errors, $methodReflection] = $this->methodCallCheck->check($scope, $methodName, $node->var); if ($methodReflection === null) { return $errors; } $declaringClass = $methodReflection->getDeclaringClass(); $messagesMethodName = SprintfHelper::escapeFormatString($declaringClass->getDisplayName() . '::' . $methodReflection->getName() . '()'); return array_merge($errors, $this->parametersCheck->check(ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()), $scope, $declaringClass->isBuiltin(), $node, ['Method ' . $messagesMethodName . ' invoked with %d parameter, %d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameters, %d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameter, at least %d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameters, at least %d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameter, %d-%d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameters, %d-%d required.', 'Parameter %s of method ' . $messagesMethodName . ' expects %s, %s given.', 'Result of method ' . $messagesMethodName . ' (void) is used.', 'Parameter %s of method ' . $messagesMethodName . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to method ' . $messagesMethodName, 'Missing parameter $%s in call to method ' . $messagesMethodName . '.', 'Unknown parameter $%s in call to method ' . $messagesMethodName . '.', 'Return type of call to method ' . $messagesMethodName . ' contains unresolvable type.', 'Parameter %s of method ' . $messagesMethodName . ' contains unresolvable type.', 'Method ' . $messagesMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.'], 'method', $methodReflection->acceptsNamedArguments())); } } */ final class MissingMethodParameterTypehintRule implements Rule { /** * @var MissingTypehintCheck */ private $missingTypehintCheck; /** * @var bool */ private $paramOut; public function __construct(MissingTypehintCheck $missingTypehintCheck, bool $paramOut) { $this->missingTypehintCheck = $missingTypehintCheck; $this->paramOut = $paramOut; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $methodReflection = $node->getMethodReflection(); $messages = []; foreach ($methodReflection->getParameters() as $parameterReflection) { foreach ($this->checkMethodParameter($methodReflection, sprintf('parameter $%s', $parameterReflection->getName()), $parameterReflection->getType()) as $parameterMessage) { $messages[] = $parameterMessage; } if ($parameterReflection->getClosureThisType() !== null) { foreach ($this->checkMethodParameter($methodReflection, sprintf('@param-closure-this PHPDoc tag for parameter $%s', $parameterReflection->getName()), $parameterReflection->getClosureThisType()) as $parameterMessage) { $messages[] = $parameterMessage; } } if (!$this->paramOut) { continue; } if ($parameterReflection->getOutType() === null) { continue; } foreach ($this->checkMethodParameter($methodReflection, sprintf('@param-out PHPDoc tag for parameter $%s', $parameterReflection->getName()), $parameterReflection->getOutType()) as $parameterMessage) { $messages[] = $parameterMessage; } } return $messages; } /** * @return list */ private function checkMethodParameter(MethodReflection $methodReflection, string $parameterMessage, Type $parameterType) : array { if ($parameterType instanceof MixedType && !$parameterType->isExplicitMixed()) { return [RuleErrorBuilder::message(sprintf('Method %s::%s() has %s with no type specified.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $parameterMessage))->identifier('missingType.parameter')->build()]; } $messages = []; foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($parameterType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() has %s with no value type specified in iterable type %s.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $parameterMessage, $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($parameterType) as [$name, $genericTypeNames]) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() has %s with generic %s but does not specify its types: %s', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $parameterMessage, $name, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($parameterType) as $callableType) { $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() has %s with no signature specified for %s.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $parameterMessage, $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $messages; } } */ final class IllegalConstructorStaticCallRule implements Rule { public function getNodeType() : string { return Node\Expr\StaticCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier || $node->name->toLowerString() !== '__construct') { return []; } if ($this->isCollectCallingConstructor($node, $scope)) { return []; } return [RuleErrorBuilder::message('Static call to __construct() is only allowed on a parent class in the constructor.')->identifier('constructor.call')->build()]; } private function isCollectCallingConstructor(Node\Expr\StaticCall $node, Scope $scope) : bool { // __construct should be called from inside constructor if ($scope->getFunction() === null) { return \false; } if ($scope->getFunction()->getName() !== '__construct') { if (!$this->isInRenamedTraitConstructor($scope)) { return \false; } } if (!$scope->isInClass()) { return \false; } if (!$node->class instanceof Node\Name) { return \false; } $parentClasses = array_map(static function (string $name) { return strtolower($name); }, $scope->getClassReflection()->getParentClassesNames()); return in_array(strtolower($scope->resolveName($node->class)), $parentClasses, \true); } private function isInRenamedTraitConstructor(Scope $scope) : bool { if (!$scope->isInClass()) { return \false; } if (!$scope->isInTrait()) { return \false; } if ($scope->getFunction() === null) { return \false; } $traitAliases = $scope->getClassReflection()->getNativeReflection()->getTraitAliases(); $functionName = $scope->getFunction()->getName(); if (!array_key_exists($functionName, $traitAliases)) { return \false; } return $traitAliases[$functionName] === sprintf('%s::%s', $scope->getTraitReflection()->getName(), '__construct'); } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->phpVersion = $phpVersion; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; $this->checkThisOnly = $checkThisOnly; $this->absentTypeChecks = $absentTypeChecks; } /** * @return list */ public function checkFunction(Function_ $function, PhpFunctionFromParserNodeReflection $functionReflection, string $parameterMessage, string $returnMessage, string $unionTypesMessage, string $templateTypeMissingInParameterMessage, string $unresolvableParameterTypeMessage, string $unresolvableReturnTypeMessage) : array { return $this->checkParametersAcceptor($functionReflection, $function, $parameterMessage, $returnMessage, $unionTypesMessage, $templateTypeMissingInParameterMessage, $unresolvableParameterTypeMessage, $unresolvableReturnTypeMessage); } /** * @param Node\Param[] $parameters * @param Node\Identifier|Node\Name|Node\ComplexType|null $returnTypeNode * @return list */ public function checkAnonymousFunction(Scope $scope, array $parameters, $returnTypeNode, string $parameterMessage, string $returnMessage, string $unionTypesMessage, string $unresolvableParameterTypeMessage, string $unresolvableReturnTypeMessage) : array { $errors = []; $unionTypeReported = \false; foreach ($parameters as $i => $param) { if ($param->type === null) { continue; } if (!$unionTypeReported && $param->type instanceof UnionType && !$this->phpVersion->supportsNativeUnionTypes()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($unionTypesMessage)->line($param->getStartLine())->identifier('parameter.unionTypeNotSupported')->nonIgnorable()->build(); $unionTypeReported = \true; } if (!$param->var instanceof Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $implicitlyNullableTypeError = $this->checkImplicitlyNullableType($param->type, $param->default, $i + 1, $param->getStartLine(), $param->var->name); if ($implicitlyNullableTypeError !== null) { $errors[] = $implicitlyNullableTypeError; } $type = $scope->getFunctionType($param->type, \false, \false); if ($type->isVoid()->yes()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($parameterMessage, $param->var->name, 'void'))->line($param->type->getStartLine())->identifier('parameter.void')->nonIgnorable()->build(); } if ($this->phpVersion->supportsPureIntersectionTypes() && $this->unresolvableTypeHelper->containsUnresolvableType($type)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($unresolvableParameterTypeMessage, $param->var->name))->line($param->type->getStartLine())->identifier('parameter.unresolvableNativeType')->nonIgnorable()->build(); } foreach ($type->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($parameterMessage, $param->var->name, $class))->line($param->type->getStartLine())->identifier('class.notFound')->build(); continue; } $classReflection = $this->reflectionProvider->getClass($class); if ($classReflection->isTrait()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($parameterMessage, $param->var->name, $class))->line($param->type->getStartLine())->identifier('parameter.trait')->build(); continue; } $errors = array_merge($errors, $this->classCheck->checkClassNames([new \PHPStan\Rules\ClassNameNodePair($class, $param->type)], $this->checkClassCaseSensitivity)); } } if ($this->phpVersion->deprecatesRequiredParameterAfterOptional()) { $errors = array_merge($errors, $this->checkRequiredParameterAfterOptional($parameters)); } if ($returnTypeNode === null) { return $errors; } if (!$unionTypeReported && $returnTypeNode instanceof UnionType && !$this->phpVersion->supportsNativeUnionTypes()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($unionTypesMessage)->line($returnTypeNode->getStartLine())->identifier('return.unionTypeNotSupported')->nonIgnorable()->build(); } $returnType = $scope->getFunctionType($returnTypeNode, \false, \false); if ($this->phpVersion->supportsPureIntersectionTypes() && $this->unresolvableTypeHelper->containsUnresolvableType($returnType)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($unresolvableReturnTypeMessage)->line($returnTypeNode->getStartLine())->identifier('return.unresolvableNativeType')->nonIgnorable()->build(); } foreach ($returnType->getReferencedClasses() as $returnTypeClass) { if (!$this->reflectionProvider->hasClass($returnTypeClass)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($returnMessage, $returnTypeClass))->line($returnTypeNode->getLine())->identifier('class.notFound')->build(); continue; } if ($this->reflectionProvider->getClass($returnTypeClass)->isTrait()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($returnMessage, $returnTypeClass))->line($returnTypeNode->getStartLine())->identifier('return.trait')->build(); continue; } $errors = array_merge($errors, $this->classCheck->checkClassNames([new \PHPStan\Rules\ClassNameNodePair($returnTypeClass, $returnTypeNode)], $this->checkClassCaseSensitivity)); } return $errors; } /** * @return list */ public function checkClassMethod(PhpMethodFromParserNodeReflection $methodReflection, ClassMethod $methodNode, string $parameterMessage, string $returnMessage, string $unionTypesMessage, string $templateTypeMissingInParameterMessage, string $unresolvableParameterTypeMessage, string $unresolvableReturnTypeMessage, string $selfOutMessage) : array { $errors = $this->checkParametersAcceptor($methodReflection, $methodNode, $parameterMessage, $returnMessage, $unionTypesMessage, $templateTypeMissingInParameterMessage, $unresolvableParameterTypeMessage, $unresolvableReturnTypeMessage); $selfOutType = $methodReflection->getSelfOutType(); if ($selfOutType !== null && $this->absentTypeChecks) { $selfOutTypeReferencedClasses = $selfOutType->getReferencedClasses(); foreach ($selfOutTypeReferencedClasses as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($selfOutMessage, $class))->line($methodNode->getStartLine())->identifier('class.notFound')->build(); continue; } if (!$this->reflectionProvider->getClass($class)->isTrait()) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($selfOutMessage, $class))->line($methodNode->getStartLine())->identifier('selfOut.trait')->build(); } $errors = array_merge($errors, $this->classCheck->checkClassNames(array_map(static function (string $class) use($methodNode) : \PHPStan\Rules\ClassNameNodePair { return new \PHPStan\Rules\ClassNameNodePair($class, $methodNode); }, $selfOutTypeReferencedClasses), $this->checkClassCaseSensitivity)); } return $errors; } /** * @return list */ private function checkParametersAcceptor(ParametersAcceptor $parametersAcceptor, FunctionLike $functionNode, string $parameterMessage, string $returnMessage, string $unionTypesMessage, string $templateTypeMissingInParameterMessage, string $unresolvableParameterTypeMessage, string $unresolvableReturnTypeMessage) : array { $errors = []; $parameterNodes = $functionNode->getParams(); if (!$this->phpVersion->supportsNativeUnionTypes()) { $unionTypeReported = \false; foreach ($parameterNodes as $parameterNode) { if (!$parameterNode->type instanceof UnionType) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($unionTypesMessage)->line($parameterNode->getStartLine())->identifier('parameter.unionTypeNotSupported')->nonIgnorable()->build(); $unionTypeReported = \true; break; } if (!$unionTypeReported && $functionNode->getReturnType() instanceof UnionType) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($unionTypesMessage)->line($functionNode->getReturnType()->getStartLine())->identifier('return.unionTypeNotSupported')->nonIgnorable()->build(); } } foreach ($parameterNodes as $i => $parameterNode) { if (!$parameterNode->var instanceof Variable || !is_string($parameterNode->var->name)) { throw new ShouldNotHappenException(); } $implicitlyNullableTypeError = $this->checkImplicitlyNullableType($parameterNode->type, $parameterNode->default, $i + 1, $parameterNode->getStartLine(), $parameterNode->var->name); if ($implicitlyNullableTypeError === null) { continue; } $errors[] = $implicitlyNullableTypeError; } if ($this->phpVersion->deprecatesRequiredParameterAfterOptional()) { $errors = array_merge($errors, $this->checkRequiredParameterAfterOptional($parameterNodes)); } $returnTypeNode = $functionNode->getReturnType() ?? $functionNode; foreach ($parametersAcceptor->getParameters() as $parameter) { $referencedClasses = $this->getParameterReferencedClasses($parameter); $parameterNode = null; $parameterNodeCallback = function () use($parameter, $parameterNodes, &$parameterNode) : Param { if ($parameterNode === null) { $parameterNode = $this->getParameterNode($parameter->getName(), $parameterNodes); } return $parameterNode; }; if ($parameter instanceof ParameterReflectionWithPhpDocs) { $parameterVar = $parameterNodeCallback()->var; if (!$parameterVar instanceof Variable || !is_string($parameterVar->name)) { throw new ShouldNotHappenException(); } if ($parameter->getNativeType()->isVoid()->yes()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($parameterMessage, $parameterVar->name, 'void'))->line($parameterNodeCallback()->getStartLine())->identifier('parameter.void')->nonIgnorable()->build(); } if ($this->phpVersion->supportsPureIntersectionTypes() && $this->unresolvableTypeHelper->containsUnresolvableType($parameter->getNativeType())) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($unresolvableParameterTypeMessage, $parameterVar->name))->line($parameterNodeCallback()->getStartLine())->identifier('parameter.unresolvableNativeType')->nonIgnorable()->build(); } } foreach ($referencedClasses as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($parameterMessage, $parameter->getName(), $class))->line($parameterNodeCallback()->getStartLine())->identifier('class.notFound')->build(); continue; } if (!$this->reflectionProvider->getClass($class)->isTrait()) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($parameterMessage, $parameter->getName(), $class))->line($parameterNodeCallback()->getStartLine())->identifier('parameter.trait')->build(); } $errors = array_merge($errors, $this->classCheck->checkClassNames(array_map(static function (string $class) use($parameterNodeCallback) : \PHPStan\Rules\ClassNameNodePair { return new \PHPStan\Rules\ClassNameNodePair($class, $parameterNodeCallback()); }, $referencedClasses), $this->checkClassCaseSensitivity)); if (!$parameter->getType() instanceof NonexistentParentClassType) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($parameterMessage, $parameter->getName(), $parameter->getType()->describe(VerbosityLevel::typeOnly())))->line($parameterNodeCallback()->getStartLine())->identifier('parameter.noParent')->build(); } if ($this->phpVersion->supportsPureIntersectionTypes() && $functionNode->getReturnType() !== null) { $nativeReturnType = ParserNodeTypeToPHPStanType::resolve($functionNode->getReturnType(), null); if ($this->unresolvableTypeHelper->containsUnresolvableType($nativeReturnType)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($unresolvableReturnTypeMessage)->nonIgnorable()->line($returnTypeNode->getStartLine())->identifier('return.unresolvableNativeType')->build(); } } $returnTypeReferencedClasses = $this->getReturnTypeReferencedClasses($parametersAcceptor); foreach ($returnTypeReferencedClasses as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($returnMessage, $class))->line($returnTypeNode->getStartLine())->identifier('class.notFound')->build(); continue; } if (!$this->reflectionProvider->getClass($class)->isTrait()) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($returnMessage, $class))->line($returnTypeNode->getStartLine())->identifier('return.trait')->build(); } $errors = array_merge($errors, $this->classCheck->checkClassNames(array_map(static function (string $class) use($returnTypeNode) : \PHPStan\Rules\ClassNameNodePair { return new \PHPStan\Rules\ClassNameNodePair($class, $returnTypeNode); }, $returnTypeReferencedClasses), $this->checkClassCaseSensitivity)); if ($parametersAcceptor->getReturnType() instanceof NonexistentParentClassType) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($returnMessage, $parametersAcceptor->getReturnType()->describe(VerbosityLevel::typeOnly())))->line($returnTypeNode->getStartLine())->identifier('return.noParent')->build(); } $templateTypeMap = $parametersAcceptor->getTemplateTypeMap(); $templateTypes = $templateTypeMap->getTypes(); if (count($templateTypes) > 0) { foreach ($parametersAcceptor->getParameters() as $parameter) { TypeTraverser::map($parameter->getType(), static function (Type $type, callable $traverse) use(&$templateTypes) : Type { if ($type instanceof TemplateType) { unset($templateTypes[$type->getName()]); return $traverse($type); } return $traverse($type); }); } $returnType = $parametersAcceptor->getReturnType(); if ($returnType instanceof ConditionalTypeForParameter && !$returnType->isNegated()) { TypeTraverser::map($returnType, static function (Type $type, callable $traverse) use(&$templateTypes) : Type { if ($type instanceof TemplateType) { unset($templateTypes[$type->getName()]); return $traverse($type); } return $traverse($type); }); } foreach (array_keys($templateTypes) as $templateTypeName) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($templateTypeMissingInParameterMessage, $templateTypeName))->identifier('method.templateTypeNotInParameter')->build(); } } return $errors; } /** * @param Param[] $parameterNodes * @return list */ private function checkRequiredParameterAfterOptional(array $parameterNodes) : array { /** @var string|null $optionalParameter */ $optionalParameter = null; $errors = []; $targetPhpVersion = null; foreach ($parameterNodes as $parameterNode) { if (!$parameterNode->var instanceof Variable) { throw new ShouldNotHappenException(); } if (!is_string($parameterNode->var->name)) { throw new ShouldNotHappenException(); } $parameterName = $parameterNode->var->name; if ($optionalParameter !== null && $parameterNode->default === null && !$parameterNode->variadic) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Deprecated in PHP %s: Required parameter $%s follows optional parameter $%s.', $targetPhpVersion ?? '8.0', $parameterName, $optionalParameter))->line($parameterNode->getStartLine())->identifier('parameter.requiredAfterOptional')->build(); $targetPhpVersion = null; continue; } if ($parameterNode->default === null) { continue; } if ($parameterNode->type === null) { $optionalParameter = $parameterName; continue; } $defaultValue = $parameterNode->default; if (!$defaultValue instanceof ConstFetch) { $optionalParameter = $parameterName; continue; } $constantName = $defaultValue->name->toLowerString(); if ($constantName === 'null') { if (!$this->phpVersion->deprecatesRequiredParameterAfterOptionalNullableAndDefaultNull()) { continue; } $parameterNodeType = $parameterNode->type; if ($parameterNodeType instanceof NullableType) { $targetPhpVersion = '8.1'; } if ($this->phpVersion->deprecatesRequiredParameterAfterOptionalUnionOrMixed()) { $types = []; if ($parameterNodeType instanceof UnionType) { $types = $parameterNodeType->types; } elseif ($parameterNodeType instanceof Identifier) { $types = [$parameterNodeType]; } $nullOrMixed = array_filter($types, static function ($type) : bool { return $type instanceof Identifier && in_array($type->name, ['null', 'mixed'], \true); }); if (0 < count($nullOrMixed)) { $targetPhpVersion = '8.3'; } } if ($targetPhpVersion === null) { continue; } } $optionalParameter = $parameterName; } return $errors; } /** * @param Param[] $parameterNodes */ private function getParameterNode(string $parameterName, array $parameterNodes) : Param { foreach ($parameterNodes as $param) { if ($param->var instanceof Node\Expr\Error) { continue; } if (!is_string($param->var->name)) { continue; } if ($param->var->name === $parameterName) { return $param; } } throw new ShouldNotHappenException(sprintf('Parameter %s not found.', $parameterName)); } /** * @return string[] */ private function getParameterReferencedClasses(ParameterReflection $parameter) : array { if (!$parameter instanceof ParameterReflectionWithPhpDocs) { return $parameter->getType()->getReferencedClasses(); } if ($this->checkThisOnly) { return $parameter->getNativeType()->getReferencedClasses(); } $moreClasses = []; if ($this->absentTypeChecks) { if ($parameter->getOutType() !== null) { $moreClasses = array_merge($moreClasses, $parameter->getOutType()->getReferencedClasses()); } if ($parameter->getClosureThisType() !== null) { $moreClasses = array_merge($moreClasses, $parameter->getClosureThisType()->getReferencedClasses()); } } return array_merge($parameter->getNativeType()->getReferencedClasses(), $parameter->getPhpDocType()->getReferencedClasses(), $moreClasses); } /** * @return string[] */ private function getReturnTypeReferencedClasses(ParametersAcceptor $parametersAcceptor) : array { if (!$parametersAcceptor instanceof ParametersAcceptorWithPhpDocs) { return $parametersAcceptor->getReturnType()->getReferencedClasses(); } if ($this->checkThisOnly) { return $parametersAcceptor->getNativeReturnType()->getReferencedClasses(); } return array_merge($parametersAcceptor->getNativeReturnType()->getReferencedClasses(), $parametersAcceptor->getPhpDocReturnType()->getReferencedClasses()); } /** * @param Identifier|Name|ComplexType|null $type */ private function checkImplicitlyNullableType($type, ?Node\Expr $default, int $order, int $line, string $name) : ?\PHPStan\Rules\IdentifierRuleError { if (!$default instanceof ConstFetch) { return null; } if ($default->name->toLowerString() !== 'null') { return null; } if ($type === null) { return null; } if ($type instanceof NullableType || $type instanceof IntersectionType) { return null; } if (!$this->phpVersion->deprecatesImplicitlyNullableParameterTypes()) { return null; } if ($type instanceof Identifier && strtolower($type->name) === 'mixed') { return null; } if ($type instanceof Name && $type->toLowerString() === 'mixed') { return null; } if ($type instanceof Identifier && strtolower($type->name) === 'null') { return null; } if ($type instanceof Name && $type->toLowerString() === 'null') { return null; } if ($type instanceof UnionType) { foreach ($type->types as $innerType) { if ($innerType instanceof Identifier && strtolower($innerType->name) === 'null') { return null; } if ($innerType instanceof Name && $innerType->toLowerString() === 'null') { return null; } } } return \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Deprecated in PHP 8.4: Parameter #%d $%s (%s) is implicitly nullable via default value null.', $order, $name, NodeTypePrinter::printType($type)))->line($line)->identifier('parameter.implicitlyNullable')->build(); } } container = $container; } /** * @template TNodeType of Node * @param class-string $nodeType * @return array> */ public function getRules(string $nodeType) : array { if (!isset($this->cache[$nodeType])) { $parentNodeTypes = [$nodeType] + class_parents($nodeType) + class_implements($nodeType); $rules = []; $rulesFromContainer = $this->getRulesFromContainer(); foreach ($parentNodeTypes as $parentNodeType) { foreach ($rulesFromContainer[$parentNodeType] ?? [] as $rule) { $rules[] = $rule; } } $this->cache[$nodeType] = $rules; } /** * @var array> $selectedRules */ $selectedRules = $this->cache[$nodeType]; return $selectedRules; } /** * @return Rule[][] */ private function getRulesFromContainer() : array { if ($this->rules !== null) { return $this->rules; } $rules = []; foreach ($this->container->getServicesByTag(self::RULE_TAG) as $rule) { $rules[$rule->getNodeType()][] = $rule; } return $this->rules = $rules; } } */ final class InterfaceTemplateTypeRule implements Rule { /** * @var TemplateTypeCheck */ private $templateTypeCheck; public function __construct(\PHPStan\Rules\Generics\TemplateTypeCheck $templateTypeCheck) { $this->templateTypeCheck = $templateTypeCheck; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); if (!$classReflection->isInterface()) { return []; } $interfaceName = $classReflection->getName(); $escapadInterfaceName = SprintfHelper::escapeFormatString($interfaceName); return $this->templateTypeCheck->check($scope, $node, TemplateTypeScope::createWithClass($interfaceName), $classReflection->getTemplateTags(), sprintf('PHPDoc tag @template for interface %s cannot have existing class %%s as its name.', $escapadInterfaceName), sprintf('PHPDoc tag @template for interface %s cannot have existing type alias %%s as its name.', $escapadInterfaceName), sprintf('PHPDoc tag @template %%s for interface %s has invalid bound type %%s.', $escapadInterfaceName), sprintf('PHPDoc tag @template %%s for interface %s with bound type %%s is not supported.', $escapadInterfaceName), sprintf('PHPDoc tag @template %%s for interface %s has invalid default type %%s.', $escapadInterfaceName), sprintf('Default type %%s in PHPDoc tag @template %%s for interface %s is not subtype of bound type %%s.', $escapadInterfaceName), sprintf('PHPDoc tag @template %%s for interface %s does not have a default type but follows an optional @template %%s.', $escapadInterfaceName)); } } reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->typeAliasResolver = $typeAliasResolver; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; } /** * @param array $templateTags * @return list */ public function check(Scope $scope, Node $node, TemplateTypeScope $templateTypeScope, array $templateTags, string $sameTemplateTypeNameAsClassMessage, string $sameTemplateTypeNameAsTypeMessage, string $invalidBoundTypeMessage, string $notSupportedBoundMessage, string $invalidDefaultTypeMessage, string $defaultNotSubtypeOfBoundMessage, string $requiredTypeAfterOptionalMessage) : array { $messages = []; $templateTagWithDefaultType = null; foreach ($templateTags as $templateTag) { $templateTagName = $scope->resolveName(new Node\Name($templateTag->getName())); if ($this->reflectionProvider->hasClass($templateTagName)) { $messages[] = RuleErrorBuilder::message(sprintf($sameTemplateTypeNameAsClassMessage, $templateTagName))->identifier('generics.existingClass')->build(); } if ($this->typeAliasResolver->hasTypeAlias($templateTagName, $templateTypeScope->getClassName())) { $messages[] = RuleErrorBuilder::message(sprintf($sameTemplateTypeNameAsTypeMessage, $templateTagName))->identifier('generics.existingTypeAlias')->build(); } $boundType = $templateTag->getBound(); foreach ($boundType->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { $messages[] = RuleErrorBuilder::message(sprintf($invalidBoundTypeMessage, $templateTagName, $referencedClass))->identifier('class.notFound')->build(); continue; } if (!$this->reflectionProvider->getClass($referencedClass)->isTrait()) { continue; } $messages[] = RuleErrorBuilder::message(sprintf($invalidBoundTypeMessage, $templateTagName, $referencedClass))->identifier('generics.traitBound')->build(); } $classNameNodePairs = array_map(static function (string $referencedClass) use($node) : ClassNameNodePair { return new ClassNameNodePair($referencedClass, $node); }, $boundType->getReferencedClasses()); $messages = array_merge($messages, $this->classCheck->checkClassNames($classNameNodePairs, $this->checkClassCaseSensitivity)); $boundTypeClass = get_class($boundType); if ($boundTypeClass !== MixedType::class && $boundTypeClass !== ConstantArrayType::class && $boundTypeClass !== ArrayType::class && $boundTypeClass !== ConstantStringType::class && $boundTypeClass !== StringType::class && $boundTypeClass !== ConstantIntegerType::class && $boundTypeClass !== IntegerType::class && $boundTypeClass !== FloatType::class && $boundTypeClass !== BooleanType::class && $boundTypeClass !== ObjectWithoutClassType::class && $boundTypeClass !== ObjectType::class && $boundTypeClass !== ObjectShapeType::class && $boundTypeClass !== GenericObjectType::class && $boundTypeClass !== KeyOfType::class && $boundTypeClass !== IterableType::class && !$boundType instanceof UnionType && !$boundType instanceof IntersectionType && !$boundType instanceof TemplateType) { $messages[] = RuleErrorBuilder::message(sprintf($notSupportedBoundMessage, $templateTagName, $boundType->describe(VerbosityLevel::typeOnly())))->identifier('generics.notSupportedBound')->build(); } $escapedTemplateTagName = SprintfHelper::escapeFormatString($templateTagName); $genericObjectErrors = $this->genericObjectTypeCheck->check($boundType, sprintf('PHPDoc tag @template %s bound contains generic type %%s but %%s %%s is not generic.', $escapedTemplateTagName), sprintf('PHPDoc tag @template %s bound has type %%s which does not specify all template types of %%s %%s: %%s', $escapedTemplateTagName), sprintf('PHPDoc tag @template %s bound has type %%s which specifies %%d template types, but %%s %%s supports only %%d: %%s', $escapedTemplateTagName), sprintf('Type %%s in generic type %%s in PHPDoc tag @template %s is not subtype of template type %%s of %%s %%s.', $escapedTemplateTagName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag @template %s is in conflict with %%s template type %%s of %%s %%s.', $escapedTemplateTagName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag @template %s is redundant, template type %%s of %%s %%s has the same variance.', $escapedTemplateTagName)); foreach ($genericObjectErrors as $genericObjectError) { $messages[] = $genericObjectError; } $defaultType = $templateTag->getDefault(); if ($defaultType === null) { if ($templateTagWithDefaultType !== null) { $messages[] = RuleErrorBuilder::message(sprintf($requiredTypeAfterOptionalMessage, $templateTagName, $templateTagWithDefaultType))->identifier('generics.requiredTypeAfterOptional')->build(); } continue; } $templateTagWithDefaultType = $templateTagName; foreach ($defaultType->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { $messages[] = RuleErrorBuilder::message(sprintf($invalidDefaultTypeMessage, $templateTagName, $referencedClass))->identifier('class.notFound')->build(); continue; } if (!$this->reflectionProvider->getClass($referencedClass)->isTrait()) { continue; } $messages[] = RuleErrorBuilder::message(sprintf($invalidDefaultTypeMessage, $templateTagName, $referencedClass))->identifier('generics.traitBound')->build(); } $classNameNodePairs = array_map(static function (string $referencedClass) use($node) : ClassNameNodePair { return new ClassNameNodePair($referencedClass, $node); }, $defaultType->getReferencedClasses()); $messages = array_merge($messages, $this->classCheck->checkClassNames($classNameNodePairs, $this->checkClassCaseSensitivity)); $genericDefaultErrors = $this->genericObjectTypeCheck->check($defaultType, sprintf('PHPDoc tag @template %s default contains generic type %%s but class %%s is not generic.', $escapedTemplateTagName), sprintf('PHPDoc tag @template %s default has type %%s which does not specify all template types of class %%s: %%s', $escapedTemplateTagName), sprintf('PHPDoc tag @template %s default has type %%s which specifies %%d template types, but class %%s supports only %%d: %%s', $escapedTemplateTagName), sprintf('Type %%s in generic type %%s in PHPDoc tag @template %s default is not subtype of template type %%s of class %%s.', $escapedTemplateTagName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag @template %s default is in conflict with %%s template type %%s of %%s %%s.', $escapedTemplateTagName), sprintf('Call-site variance of %%s in generic type %%s in PHPDoc tag @template %s default is redundant, template type %%s of %%s %%s has the same variance.', $escapedTemplateTagName)); foreach ($genericDefaultErrors as $genericDefaultError) { $messages[] = $genericDefaultError; } if (!$boundType->accepts($defaultType, $scope->isDeclareStrictTypes())->no()) { continue; } $messages[] = RuleErrorBuilder::message(sprintf($defaultNotSubtypeOfBoundMessage, $defaultType->describe(VerbosityLevel::typeOnly()), $templateTagName, $boundType->describe(VerbosityLevel::typeOnly())))->identifier('generics.templateDefaultOutOfBounds')->build(); } return $messages; } } */ final class ClassTemplateTypeRule implements Rule { /** * @var TemplateTypeCheck */ private $templateTypeCheck; public function __construct(\PHPStan\Rules\Generics\TemplateTypeCheck $templateTypeCheck) { $this->templateTypeCheck = $templateTypeCheck; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); if (!$classReflection->isClass()) { return []; } $className = $classReflection->getName(); if ($classReflection->isAnonymous()) { $displayName = 'anonymous class'; } else { $displayName = 'class ' . SprintfHelper::escapeFormatString($classReflection->getDisplayName()); } return $this->templateTypeCheck->check($scope, $node, TemplateTypeScope::createWithClass($className), $classReflection->getTemplateTags(), sprintf('PHPDoc tag @template for %s cannot have existing class %%s as its name.', $displayName), sprintf('PHPDoc tag @template for %s cannot have existing type alias %%s as its name.', $displayName), sprintf('PHPDoc tag @template %%s for %s has invalid bound type %%s.', $displayName), sprintf('PHPDoc tag @template %%s for %s with bound type %%s is not supported.', $displayName), sprintf('PHPDoc tag @template %%s for %s has invalid default type %%s.', $displayName), sprintf('Default type %%s in PHPDoc tag @template %%s for %s is not subtype of bound type %%s.', $displayName), sprintf('PHPDoc tag @template %%s for %s does not have a default type but follows an optional @template %%s.', $displayName)); } } */ final class FunctionSignatureVarianceRule implements Rule { /** * @var VarianceCheck */ private $varianceCheck; public function __construct(\PHPStan\Rules\Generics\VarianceCheck $varianceCheck) { $this->varianceCheck = $varianceCheck; } public function getNodeType() : string { return InFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $functionReflection = $node->getFunctionReflection(); $functionName = $functionReflection->getName(); return $this->varianceCheck->checkParametersAcceptor($functionReflection, sprintf('in parameter %%s of function %s()', SprintfHelper::escapeFormatString($functionName)), sprintf('in param-out type of parameter %%s of function %s()', SprintfHelper::escapeFormatString($functionName)), sprintf('in return type of function %s()', $functionName), sprintf('in function %s()', $functionName), \false, \false, 'function'); } } */ final class PropertyVarianceRule implements Rule { /** * @var VarianceCheck */ private $varianceCheck; /** * @var bool */ private $readOnlyByPhpDoc; public function __construct(\PHPStan\Rules\Generics\VarianceCheck $varianceCheck, bool $readOnlyByPhpDoc) { $this->varianceCheck = $varianceCheck; $this->readOnlyByPhpDoc = $readOnlyByPhpDoc; } public function getNodeType() : string { return ClassPropertyNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); if (!$classReflection->hasNativeProperty($node->getName())) { return []; } $propertyReflection = $classReflection->getNativeProperty($node->getName()); if ($propertyReflection->isPrivate()) { return []; } $variance = $node->isReadOnly() || $this->readOnlyByPhpDoc && $node->isReadOnlyByPhpDoc() ? TemplateTypeVariance::createCovariant() : TemplateTypeVariance::createInvariant(); return $this->varianceCheck->check($variance, $propertyReflection->getReadableType(), sprintf('in property %s::$%s', SprintfHelper::escapeFormatString($classReflection->getDisplayName()), SprintfHelper::escapeFormatString($node->getName()))); } } reflectionProvider = $reflectionProvider; $this->genericObjectTypeCheck = $genericObjectTypeCheck; $this->varianceCheck = $varianceCheck; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->checkGenericClassInNonGenericObjectType = $checkGenericClassInNonGenericObjectType; $this->skipCheckGenericClasses = $skipCheckGenericClasses; $this->absentTypeChecks = $absentTypeChecks; } /** * @param array $nameNodes * @param array $ancestorTypes * @return list */ public function check(array $nameNodes, array $ancestorTypes, string $incompatibleTypeMessage, string $unresolvableTypeMessage, string $noNamesMessage, string $noRelatedNameMessage, string $classNotGenericMessage, string $notEnoughTypesMessage, string $extraTypesMessage, string $typeIsNotSubtypeMessage, string $typeProjectionIsNotAllowedMessage, string $invalidTypeMessage, string $genericClassInNonGenericObjectType, string $invalidVarianceMessage) : array { $names = array_fill_keys(array_map(static function (Name $nameNode) : string { return $nameNode->toString(); }, $nameNodes), \true); $unusedNames = $names; $messages = []; foreach ($ancestorTypes as $ancestorType) { if (!$ancestorType instanceof GenericObjectType) { $messages[] = RuleErrorBuilder::message(sprintf($incompatibleTypeMessage, $ancestorType->describe(VerbosityLevel::typeOnly())))->identifier('generics.notCompatible')->build(); continue; } $ancestorTypeClassName = $ancestorType->getClassName(); if (!isset($names[$ancestorTypeClassName])) { if (count($names) === 0) { $messages[] = RuleErrorBuilder::message($noNamesMessage)->identifier('generics.noParent')->build(); } else { $messages[] = RuleErrorBuilder::message(sprintf($noRelatedNameMessage, $ancestorTypeClassName, implode(', ', array_keys($names))))->identifier('generics.wrongParent')->build(); } continue; } unset($unusedNames[$ancestorTypeClassName]); $genericObjectTypeCheckMessages = $this->genericObjectTypeCheck->check($ancestorType, $classNotGenericMessage, $notEnoughTypesMessage, $extraTypesMessage, $typeIsNotSubtypeMessage, '', ''); $messages = array_merge($messages, $genericObjectTypeCheckMessages); if ($this->absentTypeChecks) { if ($this->unresolvableTypeHelper->containsUnresolvableType($ancestorType)) { $messages[] = RuleErrorBuilder::message($unresolvableTypeMessage)->identifier('generics.unresolvable')->build(); } } foreach ($ancestorType->getReferencedClasses() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { $messages[] = RuleErrorBuilder::message(sprintf($invalidTypeMessage, $referencedClass))->identifier('class.notFound')->build(); continue; } if (!$this->absentTypeChecks) { continue; } if ($referencedClass === $ancestorType->getClassName()) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->isTrait()) { continue; } $messages[] = RuleErrorBuilder::message(sprintf($invalidTypeMessage, $referencedClass))->identifier('generics.trait')->build(); } $variance = TemplateTypeVariance::createStatic(); $messageContext = sprintf($invalidVarianceMessage, $ancestorType->describe(VerbosityLevel::typeOnly())); foreach ($this->varianceCheck->check($variance, $ancestorType, $messageContext) as $message) { $messages[] = $message; } foreach ($ancestorType->getVariances() as $index => $typeVariance) { if ($typeVariance->invariant()) { continue; } $messages[] = RuleErrorBuilder::message(sprintf($typeProjectionIsNotAllowedMessage, TypeProjectionHelper::describe($ancestorType->getTypes()[$index], $typeVariance, VerbosityLevel::typeOnly()), $ancestorType->describe(VerbosityLevel::typeOnly())))->identifier('generics.callSiteVarianceNotAllowed')->build(); } } if ($this->checkGenericClassInNonGenericObjectType) { foreach (array_keys($unusedNames) as $unusedName) { if (!$this->reflectionProvider->hasClass($unusedName)) { continue; } $unusedNameClassReflection = $this->reflectionProvider->getClass($unusedName); if (in_array($unusedNameClassReflection->getName(), $this->skipCheckGenericClasses, \true)) { continue; } if (!$unusedNameClassReflection->isGeneric()) { continue; } $templateTypes = $unusedNameClassReflection->getTemplateTypeMap()->getTypes(); $templateTypesCount = count($templateTypes); $requiredTemplateTypesCount = count(array_filter($templateTypes, static function (Type $type) { return $type instanceof TemplateType && $type->getDefault() === null; })); if ($requiredTemplateTypesCount === 0) { continue; } $templateTypesList = implode(', ', array_keys($templateTypes)); if ($requiredTemplateTypesCount !== $templateTypesCount) { $templateTypesList .= sprintf(' (%d-%d required)', $requiredTemplateTypesCount, $templateTypesCount); } $messages[] = RuleErrorBuilder::message(sprintf($genericClassInNonGenericObjectType, $unusedName, $templateTypesList))->identifier('missingType.generics')->build(); } } return $messages; } } */ final class FunctionTemplateTypeRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; /** * @var TemplateTypeCheck */ private $templateTypeCheck; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\Generics\TemplateTypeCheck $templateTypeCheck) { $this->fileTypeMapper = $fileTypeMapper; $this->templateTypeCheck = $templateTypeCheck; } public function getNodeType() : string { return Node\Stmt\Function_::class; } public function processNode(Node $node, Scope $scope) : array { $docComment = $node->getDocComment(); if ($docComment === null) { return []; } if (!isset($node->namespacedName)) { throw new ShouldNotHappenException(); } $functionName = (string) $node->namespacedName; $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), null, null, $functionName, $docComment->getText()); $escapedFunctionName = SprintfHelper::escapeFormatString($functionName); return $this->templateTypeCheck->check($scope, $node, TemplateTypeScope::createWithFunction($functionName), $resolvedPhpDoc->getTemplateTags(), sprintf('PHPDoc tag @template for function %s() cannot have existing class %%s as its name.', $escapedFunctionName), sprintf('PHPDoc tag @template for function %s() cannot have existing type alias %%s as its name.', $escapedFunctionName), sprintf('PHPDoc tag @template %%s for function %s() has invalid bound type %%s.', $escapedFunctionName), sprintf('PHPDoc tag @template %%s for function %s() with bound type %%s is not supported.', $escapedFunctionName), sprintf('PHPDoc tag @template %%s for function %s() has invalid default type %%s.', $escapedFunctionName), sprintf('Default type %%s in PHPDoc tag @template %%s for function %s() is not subtype of bound type %%s.', $escapedFunctionName), sprintf('PHPDoc tag @template %%s for function %s() does not have a default type but follows an optional @template %%s.', $escapedFunctionName)); } } */ public function check(ClassReflection $classReflection) : array { $interfaceTemplateTypeMaps = []; $errors = []; $check = static function (ClassReflection $classReflection, bool $first) use(&$interfaceTemplateTypeMaps, &$check, &$errors) : void { foreach ($classReflection->getInterfaces() as $interface) { if (!$interface->isGeneric()) { continue; } if (array_key_exists($interface->getName(), $interfaceTemplateTypeMaps)) { $otherMap = $interfaceTemplateTypeMaps[$interface->getName()]; foreach ($interface->getActiveTemplateTypeMap()->getTypes() as $name => $type) { $otherType = $otherMap->getType($name); if ($otherType === null) { continue; } if ($type->equals($otherType)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('%s specifies template type %s of interface %s as %s but it\'s already specified as %s.', $classReflection->isInterface() ? sprintf('Interface %s', $classReflection->getName()) : sprintf('Class %s', $classReflection->getName()), $name, $interface->getName(), $type->describe(VerbosityLevel::value()), $otherType->describe(VerbosityLevel::value())))->identifier('generics.interfaceConflict')->build(); } continue; } $interfaceTemplateTypeMaps[$interface->getName()] = $interface->getActiveTemplateTypeMap(); } $parent = $classReflection->getParentClass(); $checkParents = \true; if ($first && $parent !== null) { $extendsTags = $classReflection->getExtendsTags(); if (!array_key_exists($parent->getName(), $extendsTags)) { $checkParents = \false; } } if ($checkParents) { while ($parent !== null) { $check($parent, \false); $parent = $parent->getParentClass(); } } $interfaceTags = []; if ($first) { if ($classReflection->isInterface()) { $interfaceTags = $classReflection->getExtendsTags(); } else { $interfaceTags = $classReflection->getImplementsTags(); } } foreach ($classReflection->getInterfaces() as $interface) { if ($first) { if (!array_key_exists($interface->getName(), $interfaceTags)) { continue; } } $check($interface, \false); } }; $check($classReflection, \true); return $errors; } } */ final class InterfaceAncestorsRule implements Rule { /** * @var GenericAncestorsCheck */ private $genericAncestorsCheck; /** * @var CrossCheckInterfacesHelper */ private $crossCheckInterfacesHelper; public function __construct(\PHPStan\Rules\Generics\GenericAncestorsCheck $genericAncestorsCheck, \PHPStan\Rules\Generics\CrossCheckInterfacesHelper $crossCheckInterfacesHelper) { $this->genericAncestorsCheck = $genericAncestorsCheck; $this->crossCheckInterfacesHelper = $crossCheckInterfacesHelper; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $originalNode = $node->getOriginalNode(); if (!$originalNode instanceof Node\Stmt\Interface_) { return []; } $classReflection = $node->getClassReflection(); $interfaceName = $classReflection->getName(); $escapedInterfaceName = SprintfHelper::escapeFormatString($interfaceName); $extendsErrors = $this->genericAncestorsCheck->check($originalNode->extends, array_map(static function (ExtendsTag $tag) : Type { return $tag->getType(); }, $classReflection->getExtendsTags()), sprintf('Interface %s @extends tag contains incompatible type %%s.', $escapedInterfaceName), sprintf('Interface %s @extends tag contains unresolvable type.', $interfaceName), sprintf('Interface %s has @extends tag, but does not extend any interface.', $escapedInterfaceName), sprintf('The @extends tag of interface %s describes %%s but the interface extends: %%s', $escapedInterfaceName), 'PHPDoc tag @extends contains generic type %s but %s %s is not generic.', 'Generic type %s in PHPDoc tag @extends does not specify all template types of %s %s: %s', 'Generic type %s in PHPDoc tag @extends specifies %d template types, but %s %s supports only %d: %s', 'Type %s in generic type %s in PHPDoc tag @extends is not subtype of template type %s of %s %s.', 'Call-site variance annotation of %s in generic type %s in PHPDoc tag @extends is not allowed.', 'PHPDoc tag @extends has invalid type %s.', sprintf('Interface %s extends generic interface %%s but does not specify its types: %%s', $escapedInterfaceName), sprintf('in extended type %%s of interface %s', $escapedInterfaceName)); $implementsErrors = $this->genericAncestorsCheck->check([], array_map(static function (ImplementsTag $tag) : Type { return $tag->getType(); }, $classReflection->getImplementsTags()), sprintf('Interface %s @implements tag contains incompatible type %%s.', $escapedInterfaceName), sprintf('Interface %s @implements tag contains unresolvable type.', $interfaceName), sprintf('Interface %s has @implements tag, but can not implement any interface, must extend from it.', $escapedInterfaceName), '', '', '', '', '', '', '', '', ''); foreach ($this->crossCheckInterfacesHelper->check($classReflection) as $error) { $implementsErrors[] = $error; } return array_merge($extendsErrors, $implementsErrors); } } */ final class UsedTraitsRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; /** * @var GenericAncestorsCheck */ private $genericAncestorsCheck; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\Generics\GenericAncestorsCheck $genericAncestorsCheck) { $this->fileTypeMapper = $fileTypeMapper; $this->genericAncestorsCheck = $genericAncestorsCheck; } public function getNodeType() : string { return Node\Stmt\TraitUse::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $className = $scope->getClassReflection()->getName(); $traitName = null; if ($scope->isInTrait()) { $traitName = $scope->getTraitReflection()->getName(); } $useTags = []; $docComment = $node->getDocComment(); if ($docComment !== null) { $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $className, $traitName, null, $docComment->getText()); $useTags = $resolvedPhpDoc->getUsesTags(); } $typeDescription = strtolower($scope->getClassReflection()->getClassTypeDescription()); $description = sprintf('%s %s', $typeDescription, SprintfHelper::escapeFormatString($className)); if ($traitName !== null) { $typeDescription = 'trait'; $description = sprintf('%s %s', $typeDescription, SprintfHelper::escapeFormatString($traitName)); } $escapedDescription = SprintfHelper::escapeFormatString($description); $upperCaseDescription = ucfirst($description); $escapedUpperCaseDescription = SprintfHelper::escapeFormatString($upperCaseDescription); return $this->genericAncestorsCheck->check($node->traits, array_map(static function (UsesTag $tag) : Type { return $tag->getType(); }, $useTags), sprintf('%s @use tag contains incompatible type %%s.', $escapedUpperCaseDescription), sprintf('%s @use tag contains unresolvable type.', $upperCaseDescription), sprintf('%s has @use tag, but does not use any trait.', $upperCaseDescription), sprintf('The @use tag of %s describes %%s but the %s uses %%s.', $escapedDescription, $typeDescription), 'PHPDoc tag @use contains generic type %s but %s %s is not generic.', 'Generic type %s in PHPDoc tag @use does not specify all template types of %s %s: %s', 'Generic type %s in PHPDoc tag @use specifies %d template types, but %s %s supports only %d: %s', 'Type %s in generic type %s in PHPDoc tag @use is not subtype of template type %s of %s %s.', 'Call-site variance annotation of %s in generic type %s in PHPDoc tag @use is not allowed.', 'PHPDoc tag @use has invalid type %s.', sprintf('%s uses generic trait %%s but does not specify its types: %%s', $escapedUpperCaseDescription), sprintf('in used type %%s of %s', $escapedDescription)); } } */ final class TraitTemplateTypeRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; /** * @var TemplateTypeCheck */ private $templateTypeCheck; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\Generics\TemplateTypeCheck $templateTypeCheck) { $this->fileTypeMapper = $fileTypeMapper; $this->templateTypeCheck = $templateTypeCheck; } public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) : array { $docComment = $node->getDocComment(); if ($docComment === null) { return []; } if (!isset($node->namespacedName)) { throw new ShouldNotHappenException(); } $traitName = (string) $node->namespacedName; $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $traitName, null, null, $docComment->getText()); $escapedTraitName = SprintfHelper::escapeFormatString($traitName); return $this->templateTypeCheck->check($scope, $node, TemplateTypeScope::createWithClass($traitName), $resolvedPhpDoc->getTemplateTags(), sprintf('PHPDoc tag @template for trait %s cannot have existing class %%s as its name.', $escapedTraitName), sprintf('PHPDoc tag @template for trait %s cannot have existing type alias %%s as its name.', $escapedTraitName), sprintf('PHPDoc tag @template %%s for trait %s has invalid bound type %%s.', $escapedTraitName), sprintf('PHPDoc tag @template %%s for trait %s with bound type %%s is not supported.', $escapedTraitName), sprintf('PHPDoc tag @template %%s for trait %s has invalid default type %%s.', $escapedTraitName), sprintf('Default type %%s in PHPDoc tag @template %%s for trait %s is not subtype of bound type %%s.', $escapedTraitName), sprintf('PHPDoc tag @template %%s for trait %s does not have a default type but follows an optional @template %%s.', $escapedTraitName)); } } */ final class MethodTemplateTypeRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; /** * @var TemplateTypeCheck */ private $templateTypeCheck; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\Generics\TemplateTypeCheck $templateTypeCheck) { $this->fileTypeMapper = $fileTypeMapper; $this->templateTypeCheck = $templateTypeCheck; } public function getNodeType() : string { return Node\Stmt\ClassMethod::class; } public function processNode(Node $node, Scope $scope) : array { $docComment = $node->getDocComment(); if ($docComment === null) { return []; } if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $classReflection = $scope->getClassReflection(); $className = $classReflection->getDisplayName(); $methodName = $node->name->toString(); $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $classReflection->getName(), $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $methodName, $docComment->getText()); $methodTemplateTags = $resolvedPhpDoc->getTemplateTags(); $escapedClassName = SprintfHelper::escapeFormatString($className); $escapedMethodName = SprintfHelper::escapeFormatString($methodName); $messages = $this->templateTypeCheck->check($scope, $node, TemplateTypeScope::createWithMethod($className, $methodName), $methodTemplateTags, sprintf('PHPDoc tag @template for method %s::%s() cannot have existing class %%s as its name.', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @template for method %s::%s() cannot have existing type alias %%s as its name.', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @template %%s for method %s::%s() has invalid bound type %%s.', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @template %%s for method %s::%s() with bound type %%s is not supported.', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @template %%s for method %s::%s() has invalid default type %%s.', $escapedClassName, $escapedMethodName), sprintf('Default type %%s in PHPDoc tag @template %%s for method %s::%s() is not subtype of bound type %%s.', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @template %%s for method %s::%s() does not have a default type but follows an optional @template %%s.', $escapedClassName, $escapedMethodName)); $classTemplateTypes = $classReflection->getTemplateTypeMap()->getTypes(); foreach (array_keys($methodTemplateTags) as $name) { if (!isset($classTemplateTypes[$name])) { continue; } $messages[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @template %s for method %s::%s() shadows @template %s for class %s.', $name, $className, $methodName, $classTemplateTypes[$name]->describe(VerbosityLevel::typeOnly()), $classReflection->getDisplayName(\false)))->identifier('method.shadowTemplate')->build(); } return $messages; } } */ final class ClassAncestorsRule implements Rule { /** * @var GenericAncestorsCheck */ private $genericAncestorsCheck; /** * @var CrossCheckInterfacesHelper */ private $crossCheckInterfacesHelper; public function __construct(\PHPStan\Rules\Generics\GenericAncestorsCheck $genericAncestorsCheck, \PHPStan\Rules\Generics\CrossCheckInterfacesHelper $crossCheckInterfacesHelper) { $this->genericAncestorsCheck = $genericAncestorsCheck; $this->crossCheckInterfacesHelper = $crossCheckInterfacesHelper; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $originalNode = $node->getOriginalNode(); if (!$originalNode instanceof Node\Stmt\Class_) { return []; } $classReflection = $node->getClassReflection(); if ($classReflection->isAnonymous()) { return []; } $className = $classReflection->getName(); $escapedClassName = SprintfHelper::escapeFormatString($className); $extendsErrors = $this->genericAncestorsCheck->check($originalNode->extends !== null ? [$originalNode->extends] : [], array_map(static function (ExtendsTag $tag) : Type { return $tag->getType(); }, $classReflection->getExtendsTags()), sprintf('Class %s @extends tag contains incompatible type %%s.', $escapedClassName), sprintf('Class %s @extends tag contains unresolvable type.', $className), sprintf('Class %s has @extends tag, but does not extend any class.', $escapedClassName), sprintf('The @extends tag of class %s describes %%s but the class extends %%s.', $escapedClassName), 'PHPDoc tag @extends contains generic type %s but %s %s is not generic.', 'Generic type %s in PHPDoc tag @extends does not specify all template types of %s %s: %s', 'Generic type %s in PHPDoc tag @extends specifies %d template types, but %s %s supports only %d: %s', 'Type %s in generic type %s in PHPDoc tag @extends is not subtype of template type %s of %s %s.', 'Call-site variance annotation of %s in generic type %s in PHPDoc tag @extends is not allowed.', 'PHPDoc tag @extends has invalid type %s.', sprintf('Class %s extends generic class %%s but does not specify its types: %%s', $escapedClassName), sprintf('in extended type %%s of class %s', $escapedClassName)); $implementsErrors = $this->genericAncestorsCheck->check($originalNode->implements, array_map(static function (ImplementsTag $tag) : Type { return $tag->getType(); }, $classReflection->getImplementsTags()), sprintf('Class %s @implements tag contains incompatible type %%s.', $escapedClassName), sprintf('Class %s @implements tag contains unresolvable type.', $className), sprintf('Class %s has @implements tag, but does not implement any interface.', $escapedClassName), sprintf('The @implements tag of class %s describes %%s but the class implements: %%s', $escapedClassName), 'PHPDoc tag @implements contains generic type %s but %s %s is not generic.', 'Generic type %s in PHPDoc tag @implements does not specify all template types of %s %s: %s', 'Generic type %s in PHPDoc tag @implements specifies %d template types, but %s %s supports only %d: %s', 'Type %s in generic type %s in PHPDoc tag @implements is not subtype of template type %s of %s %s.', 'Call-site variance annotation of %s in generic type %s in PHPDoc tag @implements is not allowed.', 'PHPDoc tag @implements has invalid type %s.', sprintf('Class %s implements generic interface %%s but does not specify its types: %%s', $escapedClassName), sprintf('in implemented type %%s of class %s', $escapedClassName)); foreach ($this->crossCheckInterfacesHelper->check($classReflection) as $error) { $implementsErrors[] = $error; } return array_merge($extendsErrors, $implementsErrors); } } */ public function check(Type $phpDocType, string $classNotGenericMessage, string $notEnoughTypesMessage, string $extraTypesMessage, string $typeIsNotSubtypeMessage, string $typeProjectionHasConflictingVarianceMessage, string $typeProjectionIsRedundantMessage) : array { $genericTypes = $this->getGenericTypes($phpDocType); $messages = []; foreach ($genericTypes as $genericType) { $classReflection = $genericType->getClassReflection(); if ($classReflection === null) { continue; } $classLikeDescription = strtolower($classReflection->getClassTypeDescription()); if (!$classReflection->isGeneric()) { $messages[] = RuleErrorBuilder::message(sprintf($classNotGenericMessage, $genericType->describe(VerbosityLevel::typeOnly()), $classLikeDescription, $classReflection->getDisplayName()))->identifier('generics.notGeneric')->build(); continue; } $templateTypes = array_values($classReflection->getTemplateTypeMap()->getTypes()); $genericTypeTypes = $genericType->getTypes(); $genericTypeVariances = $genericType->getVariances(); $templateTypesCount = count($templateTypes); $genericTypeTypesCount = count($genericTypeTypes); $requiredTemplateTypesCount = count(array_filter($templateTypes, static function (Type $type) { return $type instanceof TemplateType && $type->getDefault() === null; })); if ($requiredTemplateTypesCount > $genericTypeTypesCount) { $templateTypesList = implode(', ', array_keys($classReflection->getTemplateTypeMap()->getTypes())); if ($requiredTemplateTypesCount !== $templateTypesCount) { $templateTypesList .= sprintf(' (%d-%d required).', $requiredTemplateTypesCount, $templateTypesCount); } $messages[] = RuleErrorBuilder::message(sprintf($notEnoughTypesMessage, $genericType->describe(VerbosityLevel::typeOnly()), $classLikeDescription, $classReflection->getDisplayName(\false), $templateTypesList))->identifier('generics.lessTypes')->build(); } elseif ($templateTypesCount < $genericTypeTypesCount) { $templateTypesList = implode(', ', array_keys($classReflection->getTemplateTypeMap()->getTypes())); if ($requiredTemplateTypesCount !== $templateTypesCount) { $templateTypesList .= sprintf(' (%d-%d required)', $requiredTemplateTypesCount, $templateTypesCount); } $messages[] = RuleErrorBuilder::message(sprintf($extraTypesMessage, $genericType->describe(VerbosityLevel::typeOnly()), $genericTypeTypesCount, $classLikeDescription, $classReflection->getDisplayName(\false), $templateTypesCount, $templateTypesList))->identifier('generics.moreTypes')->build(); } for ($i = 0; $i < $templateTypesCount; $i++) { if (!isset($genericTypeTypes[$i])) { continue; } $templateType = $templateTypes[$i]; $genericTypeType = $genericTypeTypes[$i]; $genericTypeVariance = $genericTypeVariances[$i] ?? TemplateTypeVariance::createInvariant(); if ($templateType instanceof TemplateType && !$genericTypeVariance->invariant()) { if ($genericTypeVariance->equals($templateType->getVariance())) { $messages[] = RuleErrorBuilder::message(sprintf($typeProjectionIsRedundantMessage, TypeProjectionHelper::describe($genericTypeType, $genericTypeVariance, VerbosityLevel::typeOnly()), $genericType->describe(VerbosityLevel::typeOnly()), $templateType->describe(VerbosityLevel::typeOnly()), $classLikeDescription, $classReflection->getDisplayName(\false)))->identifier('generics.callSiteVarianceRedundant')->tip('You can safely remove the call-site variance annotation.')->build(); } elseif (!$genericTypeVariance->validPosition($templateType->getVariance())) { $messages[] = RuleErrorBuilder::message(sprintf($typeProjectionHasConflictingVarianceMessage, TypeProjectionHelper::describe($genericTypeType, $genericTypeVariance, VerbosityLevel::typeOnly()), $genericType->describe(VerbosityLevel::typeOnly()), $templateType->getVariance()->describe(), $templateType->describe(VerbosityLevel::typeOnly()), $classLikeDescription, $classReflection->getDisplayName(\false)))->identifier('generics.callSiteVarianceConflict')->build(); } } $boundType = TemplateTypeHelper::resolveToBounds($templateType); if ($boundType->isSuperTypeOf($genericTypeType)->yes()) { if (!$templateType instanceof TemplateType) { continue; } $map = $templateType->inferTemplateTypes($genericTypeType); for ($j = 0; $j < $templateTypesCount; $j++) { if ($i === $j) { continue; } $templateTypes[$j] = TemplateTypeHelper::resolveTemplateTypes($templateTypes[$j], $map, TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createStatic()); } continue; } if ($genericTypeVariance->bivariant()) { continue; } $messages[] = RuleErrorBuilder::message(sprintf($typeIsNotSubtypeMessage, $genericTypeType->describe(VerbosityLevel::typeOnly()), $genericType->describe(VerbosityLevel::typeOnly()), $templateType->describe(VerbosityLevel::typeOnly()), $classLikeDescription, $classReflection->getDisplayName(\false)))->identifier('generics.notSubtype')->build(); } } return $messages; } /** * @return list */ private function getGenericTypes(Type $phpDocType) : array { $genericObjectTypes = []; TypeTraverser::map($phpDocType, static function (Type $type, callable $traverse) use(&$genericObjectTypes) : Type { if ($type instanceof GenericObjectType || $type instanceof GenericStaticType) { $resolvedType = TemplateTypeHelper::resolveToBounds($type); if (!$resolvedType instanceof GenericObjectType && !$resolvedType instanceof GenericStaticType) { throw new ShouldNotHappenException(); } $genericObjectTypes[] = $resolvedType; $traverse($type); return $type; } $traverse($type); return $type; }); return $genericObjectTypes; } } checkParamOutVariance = $checkParamOutVariance; $this->strictStaticVariance = $strictStaticVariance; } /** * @param 'function'|'method' $identifier * @return list */ public function checkParametersAcceptor(ParametersAcceptorWithPhpDocs $parametersAcceptor, string $parameterTypeMessage, string $parameterOutTypeMessage, string $returnTypeMessage, string $generalMessage, bool $isStatic, bool $isPrivate, string $identifier) : array { $errors = []; foreach ($parametersAcceptor->getTemplateTypeMap()->getTypes() as $templateType) { if (!$templateType instanceof TemplateType || $templateType->getScope()->getFunctionName() === null || $templateType->getVariance()->invariant()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Variance annotation is only allowed for type parameters of classes and interfaces, but occurs in template type %s in %s.', $templateType->getName(), $generalMessage))->identifier(sprintf('%s.variance', $identifier))->build(); } if ($isPrivate) { return $errors; } $covariant = TemplateTypeVariance::createCovariant(); $parameterVariance = $isStatic && !$this->strictStaticVariance ? TemplateTypeVariance::createStatic() : TemplateTypeVariance::createContravariant(); foreach ($parametersAcceptor->getParameters() as $parameterReflection) { $type = $parameterReflection->getType(); $message = sprintf($parameterTypeMessage, $parameterReflection->getName()); foreach ($this->check($parameterVariance, $type, $message) as $error) { $errors[] = $error; } if (!$this->checkParamOutVariance) { continue; } $paramOutType = $parameterReflection->getOutType(); if ($paramOutType === null) { continue; } $outMessage = sprintf($parameterOutTypeMessage, $parameterReflection->getName()); foreach ($this->check($covariant, $paramOutType, $outMessage) as $error) { $errors[] = $error; } } $type = $parametersAcceptor->getReturnType(); foreach ($this->check($covariant, $type, $returnTypeMessage) as $error) { $errors[] = $error; } return $errors; } /** @return list */ public function check(TemplateTypeVariance $positionVariance, Type $type, string $messageContext) : array { $errors = []; foreach ($type->getReferencedTemplateTypes($positionVariance) as $reference) { $referredType = $reference->getType(); if ($referredType->getScope()->getFunctionName() !== null && !$referredType->getVariance()->invariant() || $this->isTemplateTypeVarianceValid($reference->getPositionVariance(), $referredType)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Template type %s is declared as %s, but occurs in %s position %s.', $referredType->getName(), $referredType->getVariance()->describe(), $reference->getPositionVariance()->describe(), $messageContext))->identifier('generics.variance')->build(); } return $errors; } private function isTemplateTypeVarianceValid(TemplateTypeVariance $positionVariance, TemplateType $type) : bool { return $positionVariance->validPosition($type->getVariance()); } } fileTypeMapper = $fileTypeMapper; $this->templateTypeCheck = $templateTypeCheck; } /** * @return list */ public function check(ClassReflection $classReflection, Scope $scope, ClassLike $node, string $docComment) : array { $className = $classReflection->getDisplayName(); $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $classReflection->getName(), $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, null, $docComment); $messages = []; $escapedClassName = SprintfHelper::escapeFormatString($className); $classTemplateTypes = $classReflection->getTemplateTypeMap()->getTypes(); foreach ($resolvedPhpDoc->getMethodTags() as $methodName => $methodTag) { $methodTemplateTags = $methodTag->getTemplateTags(); $escapedMethodName = SprintfHelper::escapeFormatString($methodName); $messages = array_merge($messages, $this->templateTypeCheck->check($scope, $node, TemplateTypeScope::createWithMethod($className, $methodName), $methodTemplateTags, sprintf('PHPDoc tag @method template for method %s::%s() cannot have existing class %%s as its name.', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @method template for method %s::%s() cannot have existing type alias %%s as its name.', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @method template %%s for method %s::%s() has invalid bound type %%s.', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @method template %%s for method %s::%s() with bound type %%s is not supported.', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @method template %%s for method %s::%s() has invalid default type %%s', $escapedClassName, $escapedMethodName), sprintf('Default type %%s in PHPDoc tag @method template %%s for method %s::%s() is not subtype of bound type %%s', $escapedClassName, $escapedMethodName), sprintf('PHPDoc tag @template %%s for method %s::%s() does not have a default type but follows an optional @template %%s.', $escapedClassName, $escapedMethodName))); foreach (array_keys($methodTemplateTags) as $name) { if (!isset($classTemplateTypes[$name])) { continue; } $messages[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @method template %s for method %s::%s() shadows @template %s for class %s.', $name, $className, $methodName, $classTemplateTypes[$name]->describe(VerbosityLevel::typeOnly()), $classReflection->getDisplayName(\false)))->identifier('methodTag.shadowTemplate')->build(); } } return $messages; } } */ final class MethodTagTemplateTypeRule implements Rule { /** * @var MethodTagTemplateTypeCheck */ private $check; public function __construct(\PHPStan\Rules\Generics\MethodTagTemplateTypeCheck $check) { $this->check = $check; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $docComment = $node->getDocComment(); if ($docComment === null) { return []; } return $this->check->check($node->getClassReflection(), $scope, $node->getOriginalNode(), $docComment->getText()); } } */ final class EnumTemplateTypeRule implements Rule { public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $classReflection = $node->getClassReflection(); if (!$classReflection->isEnum()) { return []; } $templateTagsCount = count($classReflection->getTemplateTags()); if ($templateTagsCount === 0) { return []; } $className = $classReflection->getDisplayName(); return [RuleErrorBuilder::message(sprintf('Enum %s has PHPDoc @template tag%s but enums cannot be generic.', $className, $templateTagsCount === 1 ? '' : 's'))->identifier('enum.generic')->build()]; } } */ final class MethodTagTemplateTypeTraitRule implements Rule { /** * @var MethodTagTemplateTypeCheck */ private $check; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Generics\MethodTagTemplateTypeCheck $check, ReflectionProvider $reflectionProvider) { $this->check = $check; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) : array { $docComment = $node->getDocComment(); if ($docComment === null) { return []; } $traitName = $node->namespacedName; if ($traitName === null) { return []; } if (!$this->reflectionProvider->hasClass($traitName->toString())) { return []; } return $this->check->check($this->reflectionProvider->getClass($traitName->toString()), $scope, $node, $docComment->getText()); } } */ final class EnumAncestorsRule implements Rule { /** * @var GenericAncestorsCheck */ private $genericAncestorsCheck; /** * @var CrossCheckInterfacesHelper */ private $crossCheckInterfacesHelper; public function __construct(\PHPStan\Rules\Generics\GenericAncestorsCheck $genericAncestorsCheck, \PHPStan\Rules\Generics\CrossCheckInterfacesHelper $crossCheckInterfacesHelper) { $this->genericAncestorsCheck = $genericAncestorsCheck; $this->crossCheckInterfacesHelper = $crossCheckInterfacesHelper; } public function getNodeType() : string { return InClassNode::class; } public function processNode(Node $node, Scope $scope) : array { $originalNode = $node->getOriginalNode(); if (!$originalNode instanceof Node\Stmt\Enum_) { return []; } $classReflection = $node->getClassReflection(); $enumName = $classReflection->getName(); $escapedEnumName = SprintfHelper::escapeFormatString($enumName); $extendsErrors = $this->genericAncestorsCheck->check([], array_map(static function (ExtendsTag $tag) : Type { return $tag->getType(); }, $classReflection->getExtendsTags()), sprintf('Enum %s @extends tag contains incompatible type %%s.', $escapedEnumName), sprintf('Enum %s @extends tag contains unresolvable type.', $enumName), sprintf('Enum %s has @extends tag, but cannot extend anything.', $escapedEnumName), '', '', '', '', '', '', '', '', ''); $implementsErrors = $this->genericAncestorsCheck->check($originalNode->implements, array_map(static function (ImplementsTag $tag) : Type { return $tag->getType(); }, $classReflection->getImplementsTags()), sprintf('Enum %s @implements tag contains incompatible type %%s.', $escapedEnumName), sprintf('Enum %s @implements tag contains unresolvable type.', $enumName), sprintf('Enum %s has @implements tag, but does not implement any interface.', $escapedEnumName), sprintf('The @implements tag of eunm %s describes %%s but the enum implements: %%s', $escapedEnumName), 'PHPDoc tag @implements contains generic type %s but %s %s is not generic.', 'Generic type %s in PHPDoc tag @implements does not specify all template types of %s %s: %s', 'Generic type %s in PHPDoc tag @implements specifies %d template types, but %s %s supports only %d: %s', 'Type %s in generic type %s in PHPDoc tag @implements is not subtype of template type %s of %s %s.', 'Call-site variance annotation of %s in generic type %s in PHPDoc tag @implements is not allowed.', 'PHPDoc tag @implements has invalid type %s.', sprintf('Enum %s implements generic interface %%s but does not specify its types: %%s', $escapedEnumName), sprintf('in implemented type %%s of enum %s', $escapedEnumName)); foreach ($this->crossCheckInterfacesHelper->check($classReflection) as $error) { $implementsErrors[] = $error; } return array_merge($extendsErrors, $implementsErrors); } } */ final class MethodSignatureVarianceRule implements Rule { /** * @var VarianceCheck */ private $varianceCheck; public function __construct(\PHPStan\Rules\Generics\VarianceCheck $varianceCheck) { $this->varianceCheck = $varianceCheck; } public function getNodeType() : string { return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); return $this->varianceCheck->checkParametersAcceptor($method, sprintf('in parameter %%s of method %s::%s()', SprintfHelper::escapeFormatString($method->getDeclaringClass()->getDisplayName()), SprintfHelper::escapeFormatString($method->getName())), sprintf('in param-out type of parameter %%s of method %s::%s()', SprintfHelper::escapeFormatString($method->getDeclaringClass()->getDisplayName()), SprintfHelper::escapeFormatString($method->getName())), sprintf('in return type of method %s::%s()', $method->getDeclaringClass()->getDisplayName(), $method->getName()), sprintf('in method %s::%s()', $method->getDeclaringClass()->getDisplayName(), $method->getName()), $method->isStatic(), $method->isPrivate() || $method->getName() === '__construct', 'method'); } } */ final class DumpPhpDocTypeRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var Printer */ private $printer; public function __construct(ReflectionProvider $reflectionProvider, Printer $printer) { $this->reflectionProvider = $reflectionProvider; $this->printer = $printer; } public function getNodeType() : string { return Node\Expr\FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if ($functionName === null) { return []; } if (strtolower($functionName) !== 'phpstan\\dumpphpdoctype') { return []; } if (count($node->getArgs()) === 0) { return []; } return [RuleErrorBuilder::message(sprintf('Dumped type: %s', $this->printer->print($scope->getType($node->getArgs()[0]->value)->toPhpDocNode())))->nonIgnorable()->identifier('phpstan.dumpPhpDocType')->build()]; } } */ final class DebugScopeRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Expr\FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if ($functionName === null) { return []; } if (strtolower($functionName) !== 'phpstan\\debugscope') { return []; } if (!$scope instanceof MutatingScope) { return []; } $parts = []; foreach ($scope->debug() as $key => $row) { $parts[] = sprintf('%s: %s', $key, $row); } if (count($parts) === 0) { $parts[] = 'Scope is empty'; } return [RuleErrorBuilder::message(implode("\n", $parts))->nonIgnorable()->identifier('phpstan.debugScope')->build()]; } } */ final class DumpTypeRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Expr\FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if ($functionName === null) { return []; } if (strtolower($functionName) !== 'phpstan\\dumptype') { return []; } if (count($node->getArgs()) === 0) { return []; } return [RuleErrorBuilder::message(sprintf('Dumped type: %s', $scope->getType($node->getArgs()[0]->value)->describe(VerbosityLevel::precise())))->nonIgnorable()->identifier('phpstan.dumpType')->build()]; } } */ final class FileAssertRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Expr\FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $function = $this->reflectionProvider->getFunction($node->name, $scope); if ($function->getName() === 'PHPStan\\Testing\\assertType') { return $this->processAssertType($node->getArgs(), $scope); } if ($function->getName() === 'PHPStan\\Testing\\assertNativeType') { return $this->processAssertNativeType($node->getArgs(), $scope); } if ($function->getName() === 'PHPStan\\Testing\\assertVariableCertainty') { return $this->processAssertVariableCertainty($node->getArgs(), $scope); } return []; } /** * @param Node\Arg[] $args * @return list */ private function processAssertType(array $args, Scope $scope) : array { if (count($args) !== 2) { return []; } $expectedTypeStrings = $scope->getType($args[0]->value)->getConstantStrings(); if (count($expectedTypeStrings) !== 1) { return [RuleErrorBuilder::message('Expected type must be a literal string.')->nonIgnorable()->identifier('phpstan.unknownExpectation')->build()]; } $expressionType = $scope->getType($args[1]->value)->describe(VerbosityLevel::precise()); if ($expectedTypeStrings[0]->getValue() === $expressionType) { return []; } return [RuleErrorBuilder::message(sprintf('Expected type %s, actual: %s', $expectedTypeStrings[0]->getValue(), $expressionType))->nonIgnorable()->identifier('phpstan.type')->build()]; } /** * @param Node\Arg[] $args * @return list */ private function processAssertNativeType(array $args, Scope $scope) : array { if (count($args) !== 2) { return []; } $expectedTypeStrings = $scope->getNativeType($args[0]->value)->getConstantStrings(); if (count($expectedTypeStrings) !== 1) { return [RuleErrorBuilder::message('Expected native type must be a literal string.')->nonIgnorable()->identifier('phpstan.unknownExpectation')->build()]; } $expressionType = $scope->getNativeType($args[1]->value)->describe(VerbosityLevel::precise()); if ($expectedTypeStrings[0]->getValue() === $expressionType) { return []; } return [RuleErrorBuilder::message(sprintf('Expected native type %s, actual: %s', $expectedTypeStrings[0]->getValue(), $expressionType))->nonIgnorable()->identifier('phpstan.nativeType')->build()]; } /** * @param Node\Arg[] $args * @return list */ private function processAssertVariableCertainty(array $args, Scope $scope) : array { if (count($args) !== 2) { return []; } $certainty = $args[0]->value; if (!$certainty instanceof StaticCall) { return [RuleErrorBuilder::message('First argument of %s() must be TrinaryLogic call')->nonIgnorable()->identifier('phpstan.unknownExpectation')->build()]; } if (!$certainty->class instanceof Node\Name) { return [RuleErrorBuilder::message('Invalid TrinaryLogic call.')->nonIgnorable()->identifier('phpstan.unknownExpectation')->build()]; } if ($certainty->class->toString() !== 'PHPStan\\TrinaryLogic') { return [RuleErrorBuilder::message('Invalid TrinaryLogic call.')->nonIgnorable()->identifier('phpstan.unknownExpectation')->build()]; } if (!$certainty->name instanceof Node\Identifier) { return [RuleErrorBuilder::message('Invalid TrinaryLogic call.')->nonIgnorable()->identifier('phpstan.unknownExpectation')->build()]; } // @phpstan-ignore staticMethod.dynamicName $expectedCertaintyValue = TrinaryLogic::{$certainty->name->toString()}(); $variable = $args[1]->value; if ($variable instanceof Node\Expr\Variable && is_string($variable->name)) { $actualCertaintyValue = $scope->hasVariableType($variable->name); $variableDescription = sprintf('variable $%s', $variable->name); } elseif ($variable instanceof Node\Expr\ArrayDimFetch && $variable->dim !== null) { $offset = $scope->getType($variable->dim); $actualCertaintyValue = $scope->getType($variable->var)->hasOffsetValueType($offset); $variableDescription = sprintf('offset %s', $offset->describe(VerbosityLevel::precise())); } else { return [RuleErrorBuilder::message('Invalid assertVariableCertainty call.')->nonIgnorable()->identifier('phpstan.unknownExpectation')->build()]; } if ($expectedCertaintyValue->equals($actualCertaintyValue)) { return []; } return [RuleErrorBuilder::message(sprintf('Expected %s certainty %s, actual: %s', $variableDescription, $expectedCertaintyValue->describe(), $actualCertaintyValue->describe()))->nonIgnorable()->identifier('phpstan.variable')->build()]; } } propertyDescriptor = $propertyDescriptor; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->checkAdvancedIsset = $checkAdvancedIsset; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->strictUnnecessaryNullsafePropertyFetch = $strictUnnecessaryNullsafePropertyFetch; } /** * @param ErrorIdentifier $identifier * @param callable(Type): ?string $typeMessageCallback */ public function check(Expr $expr, Scope $scope, string $operatorDescription, string $identifier, callable $typeMessageCallback, ?\PHPStan\Rules\IdentifierRuleError $error = null) : ?\PHPStan\Rules\IdentifierRuleError { // mirrored in PHPStan\Analyser\MutatingScope::issetCheck() if ($expr instanceof Node\Expr\Variable && is_string($expr->name)) { $hasVariable = $scope->hasVariableType($expr->name); if ($hasVariable->maybe()) { return null; } if ($error === null) { if ($hasVariable->yes()) { if ($expr->name === '_SESSION') { return null; } $type = $this->treatPhpDocTypesAsCertain ? $scope->getType($expr) : $scope->getNativeType($expr); if (!$type instanceof NeverType) { return $this->generateError($type, sprintf('Variable $%s %s always exists and', $expr->name, $operatorDescription), $typeMessageCallback, $identifier, 'variable'); } } return \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Variable $%s %s is never defined.', $expr->name, $operatorDescription))->identifier(sprintf('%s.variable', $identifier))->build(); } return $error; } elseif ($expr instanceof Node\Expr\ArrayDimFetch && $expr->dim !== null) { $type = $this->treatPhpDocTypesAsCertain ? $scope->getType($expr->var) : $scope->getNativeType($expr->var); if (!$type->isOffsetAccessible()->yes()) { return $error ?? $this->checkUndefined($expr->var, $scope, $operatorDescription, $identifier); } $dimType = $this->treatPhpDocTypesAsCertain ? $scope->getType($expr->dim) : $scope->getNativeType($expr->dim); $hasOffsetValue = $type->hasOffsetValueType($dimType); if ($hasOffsetValue->no()) { if (!$this->checkAdvancedIsset) { return null; } return \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Offset %s on %s %s does not exist.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value()), $operatorDescription))->identifier(sprintf('%s.offset', $identifier))->build(); } // If offset cannot be null, store this error message and see if one of the earlier offsets is. // E.g. $array['a']['b']['c'] ?? null; is a valid coalesce if a OR b or C might be null. if ($hasOffsetValue->yes() || $scope->hasExpressionType($expr)->yes()) { if (!$this->checkAdvancedIsset) { return null; } $error = $error ?? $this->generateError($type->getOffsetValueType($dimType), sprintf('Offset %s on %s %s always exists and', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value()), $operatorDescription), $typeMessageCallback, $identifier, 'offset'); if ($error !== null) { return $this->check($expr->var, $scope, $operatorDescription, $identifier, $typeMessageCallback, $error); } } // Has offset, it is nullable return null; } elseif ($expr instanceof Node\Expr\PropertyFetch || $expr instanceof Node\Expr\StaticPropertyFetch) { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $scope); if ($propertyReflection === null) { if ($expr instanceof Node\Expr\PropertyFetch) { return $this->checkUndefined($expr->var, $scope, $operatorDescription, $identifier); } if ($expr->class instanceof Expr) { return $this->checkUndefined($expr->class, $scope, $operatorDescription, $identifier); } return null; } if (!$propertyReflection->isNative()) { if ($expr instanceof Node\Expr\PropertyFetch) { return $this->checkUndefined($expr->var, $scope, $operatorDescription, $identifier); } if ($expr->class instanceof Expr) { return $this->checkUndefined($expr->class, $scope, $operatorDescription, $identifier); } return null; } $nativeType = $propertyReflection->getNativeType(); if (!$nativeType instanceof MixedType) { if (!$scope->hasExpressionType($expr)->yes()) { if ($expr instanceof Node\Expr\PropertyFetch) { return $this->checkUndefined($expr->var, $scope, $operatorDescription, $identifier); } if ($expr->class instanceof Expr) { return $this->checkUndefined($expr->class, $scope, $operatorDescription, $identifier); } return null; } } $propertyDescription = $this->propertyDescriptor->describeProperty($propertyReflection, $scope, $expr); $propertyType = $propertyReflection->getWritableType(); if ($error !== null) { return $error; } if (!$this->checkAdvancedIsset) { if ($expr instanceof Node\Expr\PropertyFetch) { return $this->checkUndefined($expr->var, $scope, $operatorDescription, $identifier); } if ($expr->class instanceof Expr) { return $this->checkUndefined($expr->class, $scope, $operatorDescription, $identifier); } return null; } $error = $this->generateError($propertyReflection->getWritableType(), sprintf('%s (%s) %s', $propertyDescription, $propertyType->describe(VerbosityLevel::typeOnly()), $operatorDescription), $typeMessageCallback, $identifier, 'property'); if ($error !== null) { if ($expr instanceof Node\Expr\PropertyFetch) { return $this->check($expr->var, $scope, $operatorDescription, $identifier, $typeMessageCallback, $error); } if ($expr->class instanceof Expr) { return $this->check($expr->class, $scope, $operatorDescription, $identifier, $typeMessageCallback, $error); } } return $error; } if ($error !== null) { return $error; } if (!$this->checkAdvancedIsset) { return null; } $error = $this->generateError($this->treatPhpDocTypesAsCertain ? $scope->getType($expr) : $scope->getNativeType($expr), sprintf('Expression %s', $operatorDescription), $typeMessageCallback, $identifier, 'expr'); if ($error !== null) { return $error; } if ($expr instanceof Expr\NullsafePropertyFetch) { if (!$this->strictUnnecessaryNullsafePropertyFetch) { return null; } if ($expr->name instanceof Node\Identifier) { return \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Using nullsafe property access "?->%s" %s is unnecessary. Use -> instead.', $expr->name->name, $operatorDescription))->identifier('nullsafe.neverNull')->build(); } return \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Using nullsafe property access "?->(Expression)" %s is unnecessary. Use -> instead.', $operatorDescription))->identifier('nullsafe.neverNull')->build(); } return null; } /** * @param ErrorIdentifier $identifier */ private function checkUndefined(Expr $expr, Scope $scope, string $operatorDescription, string $identifier) : ?\PHPStan\Rules\IdentifierRuleError { if ($expr instanceof Node\Expr\Variable && is_string($expr->name)) { $hasVariable = $scope->hasVariableType($expr->name); if (!$hasVariable->no()) { return null; } return \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Variable $%s %s is never defined.', $expr->name, $operatorDescription))->identifier(sprintf('%s.variable', $identifier))->build(); } if ($expr instanceof Node\Expr\ArrayDimFetch && $expr->dim !== null) { $type = $this->treatPhpDocTypesAsCertain ? $scope->getType($expr->var) : $scope->getNativeType($expr->var); $dimType = $this->treatPhpDocTypesAsCertain ? $scope->getType($expr->dim) : $scope->getNativeType($expr->dim); $hasOffsetValue = $type->hasOffsetValueType($dimType); if (!$type->isOffsetAccessible()->yes()) { return $this->checkUndefined($expr->var, $scope, $operatorDescription, $identifier); } if (!$hasOffsetValue->no()) { return $this->checkUndefined($expr->var, $scope, $operatorDescription, $identifier); } return \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Offset %s on %s %s does not exist.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value()), $operatorDescription))->identifier(sprintf('%s.offset', $identifier))->build(); } if ($expr instanceof Expr\PropertyFetch) { return $this->checkUndefined($expr->var, $scope, $operatorDescription, $identifier); } if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) { return $this->checkUndefined($expr->class, $scope, $operatorDescription, $identifier); } return null; } /** * @param callable(Type): ?string $typeMessageCallback * @param ErrorIdentifier $identifier * @param 'variable'|'offset'|'property'|'expr' $identifierSecondPart */ private function generateError(Type $type, string $message, callable $typeMessageCallback, string $identifier, string $identifierSecondPart) : ?\PHPStan\Rules\IdentifierRuleError { $typeMessage = $typeMessageCallback($type); if ($typeMessage === null) { return null; } return \PHPStan\Rules\RuleErrorBuilder::message(sprintf('%s %s.', $message, $typeMessage))->identifier(sprintf('%s.%s', $identifier, $identifierSecondPart))->build(); } } */ final class RegularExpressionPatternRule implements Rule { /** * @var RegexExpressionHelper */ private $regexExpressionHelper; public function __construct(RegexExpressionHelper $regexExpressionHelper) { $this->regexExpressionHelper = $regexExpressionHelper; } public function getNodeType() : string { return FuncCall::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(FuncCall $functionCall, Scope $scope) : array { if (!$functionCall->name instanceof Node\Name) { return []; } $functionName = strtolower((string) $functionCall->name); if (!str_starts_with($functionName, 'preg_')) { return []; } if (!isset($functionCall->getArgs()[0])) { return []; } $patternNode = $functionCall->getArgs()[0]->value; $patternType = $scope->getType($patternNode); $patternStrings = []; if (in_array($functionName, ['preg_match', 'preg_match_all', 'preg_split', 'preg_grep', 'preg_replace', 'preg_replace_callback', 'preg_filter'], \true)) { if ($patternNode instanceof Node\Expr\BinaryOp\Concat) { $patternType = $this->regexExpressionHelper->resolvePatternConcat($patternNode, $scope); } foreach ($patternType->getConstantStrings() as $constantStringType) { $patternStrings[] = $constantStringType->getValue(); } } if (in_array($functionName, ['preg_replace', 'preg_replace_callback', 'preg_filter'], \true)) { foreach ($patternType->getConstantArrays() as $constantArrayType) { foreach ($constantArrayType->getValueTypes() as $arrayKeyType) { foreach ($arrayKeyType->getConstantStrings() as $constantString) { $patternStrings[] = $constantString->getValue(); } } } } if ($functionName === 'preg_replace_callback_array') { foreach ($patternType->getConstantArrays() as $constantArrayType) { foreach ($constantArrayType->getKeyTypes() as $arrayKeyType) { foreach ($arrayKeyType->getConstantStrings() as $constantString) { $patternStrings[] = $constantString->getValue(); } } } } return $patternStrings; } private function validatePattern(string $pattern) : ?string { try { Strings::match('', $pattern); } catch (RegexpException $e) { return $e->getMessage(); } return null; } } */ final class RegularExpressionQuotingRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var RegexExpressionHelper */ private $regexExpressionHelper; public function __construct(ReflectionProvider $reflectionProvider, RegexExpressionHelper $regexExpressionHelper) { $this->reflectionProvider = $reflectionProvider; $this->regexExpressionHelper = $regexExpressionHelper; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); if (!in_array($functionReflection->getName(), ['preg_match', 'preg_match_all', 'preg_filter', 'preg_grep', 'preg_replace', 'preg_replace_callback', 'preg_split'], \true)) { return []; } $normalizedArgs = $this->getNormalizedArgs($node, $scope, $functionReflection); if ($normalizedArgs === null) { return []; } if (!isset($normalizedArgs[0])) { return []; } if (!$normalizedArgs[0]->value instanceof Concat) { return []; } $patternDelimiters = $this->regexExpressionHelper->getPatternDelimiters($normalizedArgs[0]->value, $scope); return $this->validateQuoteDelimiters($normalizedArgs[0]->value, $scope, $patternDelimiters); } /** * @param string[] $patternDelimiters * * @return list */ private function validateQuoteDelimiters(Concat $concat, Scope $scope, array $patternDelimiters) : array { if ($patternDelimiters === []) { return []; } $errors = []; if ($concat->left instanceof FuncCall && $concat->left->name instanceof Name && $concat->left->name->toLowerString() === 'preg_quote') { $pregError = $this->validatePregQuote($concat->left, $scope, $patternDelimiters); if ($pregError !== null) { $errors[] = $pregError; } } elseif ($concat->left instanceof Concat) { $errors = array_merge($errors, $this->validateQuoteDelimiters($concat->left, $scope, $patternDelimiters)); } if ($concat->right instanceof FuncCall && $concat->right->name instanceof Name && $concat->right->name->toLowerString() === 'preg_quote') { $pregError = $this->validatePregQuote($concat->right, $scope, $patternDelimiters); if ($pregError !== null) { $errors[] = $pregError; } } elseif ($concat->right instanceof Concat) { $errors = array_merge($errors, $this->validateQuoteDelimiters($concat->right, $scope, $patternDelimiters)); } return $errors; } /** * @param string[] $patternDelimiters */ private function validatePregQuote(FuncCall $pregQuote, Scope $scope, array $patternDelimiters) : ?IdentifierRuleError { if (!$pregQuote->name instanceof Node\Name) { return null; } if (!$this->reflectionProvider->hasFunction($pregQuote->name, $scope)) { return null; } $functionReflection = $this->reflectionProvider->getFunction($pregQuote->name, $scope); $args = $this->getNormalizedArgs($pregQuote, $scope, $functionReflection); if ($args === null) { return null; } $patternDelimiters = $this->removeDefaultEscapedDelimiters($patternDelimiters); if ($patternDelimiters === []) { return null; } if (count($args) === 1) { if (count($patternDelimiters) === 1) { return RuleErrorBuilder::message(sprintf('Call to preg_quote() is missing delimiter %s to be effective.', $patternDelimiters[0]))->line($pregQuote->getStartLine())->identifier('argument.invalidPregQuote')->build(); } return RuleErrorBuilder::message('Call to preg_quote() is missing delimiter parameter to be effective.')->line($pregQuote->getStartLine())->identifier('argument.invalidPregQuote')->build(); } if (count($args) >= 2) { foreach ($scope->getType($args[1]->value)->getConstantStrings() as $quoteDelimiterType) { $quoteDelimiter = $quoteDelimiterType->getValue(); $quoteDelimiters = $this->removeDefaultEscapedDelimiters([$quoteDelimiter]); if ($quoteDelimiters === []) { continue; } if (count($quoteDelimiters) !== 1) { throw new ShouldNotHappenException(); } $quoteDelimiter = $quoteDelimiters[0]; if (!in_array($quoteDelimiter, $patternDelimiters, \true)) { if (count($patternDelimiters) === 1) { return RuleErrorBuilder::message(sprintf('Call to preg_quote() uses invalid delimiter %s while pattern uses %s.', $quoteDelimiter, $patternDelimiters[0]))->line($pregQuote->getStartLine())->identifier('argument.invalidPregQuote')->build(); } return RuleErrorBuilder::message(sprintf('Call to preg_quote() uses invalid delimiter %s.', $quoteDelimiter))->line($pregQuote->getStartLine())->identifier('argument.invalidPregQuote')->build(); } } } return null; } /** * @param string[] $delimiters * * @return list */ private function removeDefaultEscapedDelimiters(array $delimiters) : array { return array_values(array_filter($delimiters, function (string $delimiter) : bool { return !$this->isDefaultEscaped($delimiter); })); } private function isDefaultEscaped(string $delimiter) : bool { if (strlen($delimiter) !== 1) { return \false; } return in_array( $delimiter, // these delimiters are escaped, no matter what preg_quote() 2nd arg looks like ['.', '\\', '+', '*', '?', '[', '^', ']', '$', '(', ')', '{', '}', '=', '!', '<', '>', '|', ':', '-', '#'], \true ); } /** * @return Node\Arg[]|null */ private function getNormalizedArgs(FuncCall $functionCall, Scope $scope, FunctionReflection $functionReflection) : ?array { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $functionCall->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $normalizedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $functionCall); if ($normalizedFuncCall === null) { return null; } return $normalizedFuncCall->getArgs(); } } */ final class ExistingNamesInGroupUseRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ClassNameCheck */ private $classCheck; /** * @var bool */ private $checkFunctionNameCase; public function __construct(ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, bool $checkFunctionNameCase) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkFunctionNameCase = $checkFunctionNameCase; } public function getNodeType() : string { return Node\Stmt\GroupUse::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; foreach ($node->uses as $use) { $error = null; /** @var Node\Name $name */ $name = Node\Name::concat($node->prefix, $use->name, ['startLine' => $use->getStartLine()]); if ($node->type === Use_::TYPE_CONSTANT || $use->type === Use_::TYPE_CONSTANT) { $error = $this->checkConstant($name); } elseif ($node->type === Use_::TYPE_FUNCTION || $use->type === Use_::TYPE_FUNCTION) { $error = $this->checkFunction($name); } elseif ($use->type === Use_::TYPE_NORMAL) { $error = $this->checkClass($name); } else { throw new ShouldNotHappenException(); } if ($error === null) { continue; } $errors[] = $error; } return $errors; } private function checkConstant(Node\Name $name) : ?IdentifierRuleError { if (!$this->reflectionProvider->hasConstant($name, null)) { return RuleErrorBuilder::message(sprintf('Used constant %s not found.', (string) $name))->discoveringSymbolsTip()->line($name->getStartLine())->identifier('constant.notFound')->build(); } return null; } private function checkFunction(Node\Name $name) : ?IdentifierRuleError { if (!$this->reflectionProvider->hasFunction($name, null)) { return RuleErrorBuilder::message(sprintf('Used function %s not found.', (string) $name))->discoveringSymbolsTip()->line($name->getStartLine())->identifier('function.notFound')->build(); } if ($this->checkFunctionNameCase) { $functionReflection = $this->reflectionProvider->getFunction($name, null); $realName = $functionReflection->getName(); $usedName = (string) $name; if (strtolower($realName) === strtolower($usedName) && $realName !== $usedName) { return RuleErrorBuilder::message(sprintf('Function %s used with incorrect case: %s.', $realName, $usedName))->line($name->getStartLine())->identifier('function.nameCase')->build(); } } return null; } private function checkClass(Node\Name $name) : ?IdentifierRuleError { $errors = $this->classCheck->checkClassNames([new ClassNameNodePair((string) $name, $name)]); if (count($errors) === 0) { return null; } elseif (count($errors) === 1) { return $errors[0]; } throw new ShouldNotHappenException(); } } */ final class ExistingNamesInUseRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ClassNameCheck */ private $classCheck; /** * @var bool */ private $checkFunctionNameCase; public function __construct(ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, bool $checkFunctionNameCase) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkFunctionNameCase = $checkFunctionNameCase; } public function getNodeType() : string { return Node\Stmt\Use_::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->type === Node\Stmt\Use_::TYPE_UNKNOWN) { throw new ShouldNotHappenException(); } foreach ($node->uses as $use) { if ($use->type !== Node\Stmt\Use_::TYPE_UNKNOWN) { throw new ShouldNotHappenException(); } } if ($node->type === Node\Stmt\Use_::TYPE_CONSTANT) { return $this->checkConstants($node->uses); } if ($node->type === Node\Stmt\Use_::TYPE_FUNCTION) { return $this->checkFunctions($node->uses); } return $this->checkClasses($node->uses); } /** * @param Node\Stmt\UseUse[] $uses * @return list */ private function checkConstants(array $uses) : array { $errors = []; foreach ($uses as $use) { if ($this->reflectionProvider->hasConstant($use->name, null)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Used constant %s not found.', (string) $use->name))->line($use->name->getStartLine())->identifier('constant.notFound')->discoveringSymbolsTip()->build(); } return $errors; } /** * @param Node\Stmt\UseUse[] $uses * @return list */ private function checkFunctions(array $uses) : array { $errors = []; foreach ($uses as $use) { if (!$this->reflectionProvider->hasFunction($use->name, null)) { $errors[] = RuleErrorBuilder::message(sprintf('Used function %s not found.', (string) $use->name))->line($use->name->getStartLine())->identifier('function.notFound')->discoveringSymbolsTip()->build(); } elseif ($this->checkFunctionNameCase) { $functionReflection = $this->reflectionProvider->getFunction($use->name, null); $realName = $functionReflection->getName(); $usedName = (string) $use->name; if (strtolower($realName) === strtolower($usedName) && $realName !== $usedName) { $errors[] = RuleErrorBuilder::message(sprintf('Function %s used with incorrect case: %s.', $realName, $usedName))->line($use->name->getStartLine())->identifier('function.nameCase')->build(); } } } return $errors; } /** * @param Node\Stmt\UseUse[] $uses * @return list */ private function checkClasses(array $uses) : array { return $this->classCheck->checkClassNames(array_map(static function (Node\Stmt\UseUse $use) : ClassNameNodePair { return new ClassNameNodePair((string) $use->name, $use->name); }, $uses)); } } */ final class MissingReturnRule implements Rule { /** * @var bool */ private $checkExplicitMixedMissingReturn; /** * @var bool */ private $checkPhpDocMissingReturn; public function __construct(bool $checkExplicitMixedMissingReturn, bool $checkPhpDocMissingReturn) { $this->checkExplicitMixedMissingReturn = $checkExplicitMixedMissingReturn; $this->checkPhpDocMissingReturn = $checkPhpDocMissingReturn; } public function getNodeType() : string { return ExecutionEndNode::class; } public function processNode(Node $node, Scope $scope) : array { $statementResult = $node->getStatementResult(); if ($statementResult->isAlwaysTerminating()) { return []; } $anonymousFunctionReturnType = $scope->getAnonymousFunctionReturnType(); $scopeFunction = $scope->getFunction(); if ($anonymousFunctionReturnType !== null) { $returnType = $anonymousFunctionReturnType; $description = 'Anonymous function'; if (!$node->hasNativeReturnTypehint()) { return []; } } elseif ($scopeFunction !== null) { $returnType = $scopeFunction->getReturnType(); if ($scopeFunction instanceof MethodReflection) { $description = sprintf('Method %s::%s()', $scopeFunction->getDeclaringClass()->getDisplayName(), $scopeFunction->getName()); } else { $description = sprintf('Function %s()', $scopeFunction->getName()); } } else { throw new ShouldNotHappenException(); } $returnType = TypeUtils::resolveLateResolvableTypes($returnType); $isVoidSuperType = $returnType->isSuperTypeOf(new VoidType()); if ($isVoidSuperType->yes() && !$returnType instanceof MixedType) { return []; } if ($statementResult->hasYield()) { if ($this->checkPhpDocMissingReturn) { $generatorReturnType = $returnType->getTemplateType(Generator::class, 'TReturn'); if (!$generatorReturnType instanceof ErrorType) { $returnType = $generatorReturnType; if ($returnType->isVoid()->yes()) { return []; } if (!$returnType instanceof MixedType) { return [RuleErrorBuilder::message(sprintf('%s should return %s but return statement is missing.', $description, $returnType->describe(VerbosityLevel::typeOnly())))->line($node->getNode()->getStartLine())->identifier('return.missing')->build()]; } } } return []; } if (!$node->hasNativeReturnTypehint() && !$this->checkPhpDocMissingReturn && TypeCombinator::containsNull($returnType)) { return []; } if ($returnType instanceof NeverType && $returnType->isExplicit()) { $errorBuilder = RuleErrorBuilder::message(sprintf('%s should always throw an exception or terminate script execution but doesn\'t do that.', $description))->line($node->getNode()->getStartLine()); if ($node->hasNativeReturnTypehint()) { $errorBuilder->nonIgnorable(); } $errorBuilder->identifier('return.never'); return [$errorBuilder->build()]; } if ($returnType instanceof MixedType && !$returnType instanceof TemplateMixedType && !$node->hasNativeReturnTypehint() && (!$returnType->isExplicitMixed() || !$this->checkExplicitMixedMissingReturn)) { return []; } $errorBuilder = RuleErrorBuilder::message(sprintf('%s should return %s but return statement is missing.', $description, $returnType->describe(VerbosityLevel::typeOnly())))->line($node->getNode()->getStartLine()); if ($node->hasNativeReturnTypehint()) { $errorBuilder->nonIgnorable(); } $errorBuilder->identifier('return.missing'); return [$errorBuilder->build()]; } } */ final class FileWhitespaceRule implements Rule { public function getNodeType() : string { return FileNode::class; } public function processNode(Node $node, Scope $scope) : array { $nodes = $node->getNodes(); if (count($nodes) === 0) { return []; } $firstNode = $nodes[0]; $messages = []; if ($firstNode instanceof Node\Stmt\InlineHTML && $firstNode->value === "") { $messages[] = RuleErrorBuilder::message('File begins with UTF-8 BOM character. This may cause problems when running the code in the web browser.')->identifier('whitespace.bom')->build(); } $nodeTraverser = new NodeTraverser(); $visitor = new class extends NodeVisitorAbstract { /** @var Node[] */ private $lastNodes = []; /** * @return int|null */ public function enterNode(Node $node) { if ($node instanceof Node\Stmt\Declare_) { if ($node->stmts !== null && count($node->stmts) > 0) { $this->lastNodes[] = $node->stmts[count($node->stmts) - 1]; } return null; } if ($node instanceof Node\Stmt\Namespace_) { if (count($node->stmts) > 0) { $this->lastNodes[] = $node->stmts[count($node->stmts) - 1]; } return null; } return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; } /** * @return Node[] */ public function getLastNodes() : array { return $this->lastNodes; } }; $nodeTraverser->addVisitor($visitor); $nodeTraverser->traverse($nodes); $lastNodes = $visitor->getLastNodes(); $lastNodes[] = $nodes[count($nodes) - 1]; foreach ($lastNodes as $lastNode) { if (!$lastNode instanceof Node\Stmt\InlineHTML || Strings::match($lastNode->value, '#^(\\s+)$#') === null) { continue; } $messages[] = RuleErrorBuilder::message('File ends with a trailing whitespace. This may cause problems when running the code in the web browser. Remove the closing ?> mark or remove the whitespace.')->line($lastNode->getStartLine())->identifier('whitespace.fileEnd')->build(); } return $messages; } } */ final class CallToFunctionStatementWithoutImpurePointsRule implements Rule { public function getNodeType() : string { return CollectedDataNode::class; } public function processNode(Node $node, Scope $scope) : array { $functions = []; foreach ($node->get(\PHPStan\Rules\DeadCode\FunctionWithoutImpurePointsCollector::class) as [$functionName]) { $functions[strtolower($functionName)] = $functionName; } $errors = []; foreach ($node->get(\PHPStan\Rules\DeadCode\PossiblyPureFuncCallCollector::class) as $filePath => $data) { foreach ($data as [$func, $line]) { $lowerFunc = strtolower($func); if (!array_key_exists($lowerFunc, $functions)) { continue; } $originalFunctionName = $functions[$lowerFunc]; $errors[] = RuleErrorBuilder::message(sprintf('Call to function %s() on a separate line has no effect.', $originalFunctionName))->file($filePath)->line($line)->identifier('function.resultUnused')->build(); } } return $errors; } } */ final class UnreachableStatementRule implements Rule { public function getNodeType() : string { return UnreachableStatementNode::class; } public function processNode(Node $node, Scope $scope) : array { return [RuleErrorBuilder::message('Unreachable statement - code above always terminates.')->identifier('deadCode.unreachable')->build()]; } } */ final class UnusedPrivateConstantRule implements Rule { /** * @var AlwaysUsedClassConstantsExtensionProvider */ private $extensionProvider; public function __construct(AlwaysUsedClassConstantsExtensionProvider $extensionProvider) { $this->extensionProvider = $extensionProvider; } public function getNodeType() : string { return ClassConstantsNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->getClass() instanceof Node\Stmt\Class_ && !$node->getClass() instanceof Node\Stmt\Enum_) { return []; } $classReflection = $node->getClassReflection(); $classType = new ObjectType($classReflection->getName(), null, $classReflection); $constants = []; foreach ($node->getConstants() as $constant) { if (!$constant->isPrivate()) { continue; } foreach ($constant->consts as $const) { $constantName = $const->name->toString(); $constantReflection = $classReflection->getConstant($constantName); foreach ($this->extensionProvider->getExtensions() as $extension) { if ($extension->isAlwaysUsed($constantReflection)) { continue 2; } } $constants[$constantName] = $const; } } foreach ($node->getFetches() as $fetch) { $fetchNode = $fetch->getNode(); $fetchScope = $fetch->getScope(); if ($fetchNode->class instanceof Node\Name) { $fetchedOnClass = $fetchScope->resolveTypeByName($fetchNode->class); } else { $fetchedOnClass = $fetchScope->getType($fetchNode->class); } if (!$fetchNode->name instanceof Node\Identifier) { if (!$classType->isSuperTypeOf($fetchedOnClass)->no()) { $constants = []; break; } continue; } $constantReflection = $fetchScope->getConstantReflection($fetchedOnClass, $fetchNode->name->toString()); if ($constantReflection === null) { if (!$classType->isSuperTypeOf($fetchedOnClass)->no()) { unset($constants[$fetchNode->name->toString()]); } continue; } if ($constantReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { if (!$classType->isSuperTypeOf($fetchedOnClass)->no()) { unset($constants[$fetchNode->name->toString()]); } continue; } unset($constants[$fetchNode->name->toString()]); } $errors = []; foreach ($constants as $constantName => $constantNode) { $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s is unused.', $classReflection->getDisplayName(), $constantName))->line($constantNode->getStartLine())->identifier('classConstant.unused')->tip(sprintf('See: %s', 'https://phpstan.org/developing-extensions/always-used-class-constants'))->build(); } return $errors; } } */ final class CallToConstructorStatementWithoutImpurePointsRule implements Rule { public function getNodeType() : string { return CollectedDataNode::class; } public function processNode(Node $node, Scope $scope) : array { $classesWithConstructors = []; foreach ($node->get(\PHPStan\Rules\DeadCode\ConstructorWithoutImpurePointsCollector::class) as [$class]) { $classesWithConstructors[strtolower($class)] = $class; } $errors = []; foreach ($node->get(\PHPStan\Rules\DeadCode\PossiblyPureNewCollector::class) as $filePath => $data) { foreach ($data as [$class, $line]) { $lowerClass = strtolower($class); if (!array_key_exists($lowerClass, $classesWithConstructors)) { continue; } $originalClassName = $classesWithConstructors[$lowerClass]; $errors[] = RuleErrorBuilder::message(sprintf('Call to new %s() on a separate line has no effect.', $originalClassName))->file($filePath)->line($line)->identifier('new.resultUnused')->build(); } } return $errors; } } */ final class NoopRule implements Rule { /** * @var ExprPrinter */ private $exprPrinter; /** * @var bool */ private $better; public function __construct(ExprPrinter $exprPrinter, bool $better) { $this->exprPrinter = $exprPrinter; $this->better = $better; } public function getNodeType() : string { return Node\Stmt\Expression::class; } public function processNode(Node $node, Scope $scope) : array { if ($this->better) { // disabled in bleeding edge return []; } $originalExpr = $node->expr; $expr = $originalExpr; if ($expr instanceof Node\Expr\Cast || $expr instanceof Node\Expr\UnaryMinus || $expr instanceof Node\Expr\UnaryPlus || $expr instanceof Node\Expr\ErrorSuppress) { $expr = $expr->expr; } if (!$this->isNoopExpr($expr)) { return []; } return [RuleErrorBuilder::message(sprintf('Expression "%s" on a separate line does not do anything.', $this->exprPrinter->printExpr($originalExpr)))->line($expr->getStartLine())->identifier('expr.resultUnused')->build()]; } public function isNoopExpr(Node\Expr $expr) : bool { return $expr instanceof Node\Expr\Variable || $expr instanceof Node\Expr\PropertyFetch || $expr instanceof Node\Expr\StaticPropertyFetch || $expr instanceof Node\Expr\NullsafePropertyFetch || $expr instanceof Node\Expr\ArrayDimFetch || $expr instanceof Node\Scalar || $expr instanceof Node\Expr\Isset_ || $expr instanceof Node\Expr\Empty_ || $expr instanceof Node\Expr\ConstFetch || $expr instanceof Node\Expr\ClassConstFetch; } } */ final class PossiblyPureStaticCallCollector implements Collector { public function __construct() { } public function getNodeType() : string { return Expression::class; } public function processNode(Node $node, Scope $scope) { if (!$node->expr instanceof Node\Expr\StaticCall) { return null; } if (!$node->expr->name instanceof Node\Identifier) { return null; } if (!$node->expr->class instanceof Node\Name) { return null; } $methodName = $node->expr->name->toString(); $calledOnType = $scope->resolveTypeByName($node->expr->class); $methodReflection = $scope->getMethodReflection($calledOnType, $methodName); if ($methodReflection === null) { return null; } if (!$methodReflection->isPure()->maybe()) { return null; } if (!$methodReflection->hasSideEffects()->maybe()) { return null; } return [$methodReflection->getDeclaringClass()->getName(), $methodReflection->getName(), $node->getStartLine()]; } } */ final class PossiblyPureNewCollector implements Collector { /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Expression::class; } public function processNode(Node $node, Scope $scope) { if (!$node->expr instanceof Node\Expr\New_) { return null; } if (!$node->expr->class instanceof Node\Name) { return null; } $className = $node->expr->class->toString(); if (!$this->reflectionProvider->hasClass($className)) { return null; } $classReflection = $this->reflectionProvider->getClass($className); if (!$classReflection->hasConstructor()) { return null; } $constructor = $classReflection->getConstructor(); if (strtolower($constructor->getName()) !== '__construct') { return null; } if (!$constructor->isPure()->maybe()) { return null; } return [$constructor->getDeclaringClass()->getName(), $node->getStartLine()]; } } */ final class UnusedPrivatePropertyRule implements Rule { /** * @var ReadWritePropertiesExtensionProvider */ private $extensionProvider; /** * @var string[] */ private $alwaysWrittenTags; /** * @var string[] */ private $alwaysReadTags; /** * @var bool */ private $checkUninitializedProperties; /** * @param string[] $alwaysWrittenTags * @param string[] $alwaysReadTags */ public function __construct(ReadWritePropertiesExtensionProvider $extensionProvider, array $alwaysWrittenTags, array $alwaysReadTags, bool $checkUninitializedProperties) { $this->extensionProvider = $extensionProvider; $this->alwaysWrittenTags = $alwaysWrittenTags; $this->alwaysReadTags = $alwaysReadTags; $this->checkUninitializedProperties = $checkUninitializedProperties; } public function getNodeType() : string { return ClassPropertiesNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->getClass() instanceof Node\Stmt\Class_) { return []; } $classReflection = $node->getClassReflection(); $classType = new ObjectType($classReflection->getName(), null, $classReflection); $properties = []; foreach ($node->getProperties() as $property) { if (!$property->isPrivate()) { continue; } if ($property->isDeclaredInTrait()) { continue; } $alwaysRead = \false; $alwaysWritten = \false; if ($property->getPhpDoc() !== null) { $text = $property->getPhpDoc(); foreach ($this->alwaysReadTags as $tag) { if (!str_contains($text, $tag)) { continue; } $alwaysRead = \true; break; } foreach ($this->alwaysWrittenTags as $tag) { if (!str_contains($text, $tag)) { continue; } $alwaysWritten = \true; break; } } $propertyName = $property->getName(); if (!$alwaysRead || !$alwaysWritten) { if (!$classReflection->hasNativeProperty($propertyName)) { continue; } $propertyReflection = $classReflection->getNativeProperty($propertyName); foreach ($this->extensionProvider->getExtensions() as $extension) { if ($alwaysRead && $alwaysWritten) { break; } if (!$alwaysRead && $extension->isAlwaysRead($propertyReflection, $propertyName)) { $alwaysRead = \true; } if ($alwaysWritten || !$extension->isAlwaysWritten($propertyReflection, $propertyName)) { continue; } $alwaysWritten = \true; } } $read = $alwaysRead; $written = $alwaysWritten || $property->getDefault() !== null; $properties[$propertyName] = ['read' => $read, 'written' => $written, 'node' => $property]; } foreach ($node->getPropertyUsages() as $usage) { $fetch = $usage->getFetch(); if ($fetch->name instanceof Node\Identifier) { $propertyNames = [$fetch->name->toString()]; } else { $propertyNameType = $usage->getScope()->getType($fetch->name); $strings = $propertyNameType->getConstantStrings(); if (count($strings) === 0) { // handle subtractions of a dynamic property fetch foreach ($properties as $propertyName => $data) { if ((new ConstantStringType($propertyName))->isSuperTypeOf($propertyNameType)->no()) { continue; } unset($properties[$propertyName]); } continue; } $propertyNames = array_map(static function (ConstantStringType $type) : string { return $type->getValue(); }, $strings); } if ($fetch instanceof Node\Expr\PropertyFetch) { $fetchedOnType = $usage->getScope()->getType($fetch->var); } else { if ($fetch->class instanceof Node\Name) { $fetchedOnType = $usage->getScope()->resolveTypeByName($fetch->class); } else { $fetchedOnType = $usage->getScope()->getType($fetch->class); } } foreach ($propertyNames as $propertyName) { if (!array_key_exists($propertyName, $properties)) { continue; } $propertyReflection = $usage->getScope()->getPropertyReflection($fetchedOnType, $propertyName); if ($propertyReflection === null) { if (!$classType->isSuperTypeOf($fetchedOnType)->no()) { if ($usage instanceof PropertyRead) { $properties[$propertyName]['read'] = \true; } else { $properties[$propertyName]['written'] = \true; } } continue; } if ($propertyReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { if (!$classType->isSuperTypeOf($fetchedOnType)->no()) { if ($usage instanceof PropertyRead) { $properties[$propertyName]['read'] = \true; } else { $properties[$propertyName]['written'] = \true; } } continue; } if ($usage instanceof PropertyRead) { $properties[$propertyName]['read'] = \true; } else { $properties[$propertyName]['written'] = \true; } } } [$uninitializedProperties] = $node->getUninitializedProperties($scope, []); $errors = []; foreach ($properties as $name => $data) { $propertyNode = $data['node']; if ($propertyNode->isStatic()) { $propertyName = sprintf('Static property %s::$%s', $classReflection->getDisplayName(), $name); } else { $propertyName = sprintf('Property %s::$%s', $classReflection->getDisplayName(), $name); } $tip = sprintf('See: %s', 'https://phpstan.org/developing-extensions/always-read-written-properties'); if (!$data['read']) { if (!$data['written']) { $errors[] = RuleErrorBuilder::message(sprintf('%s is unused.', $propertyName))->line($propertyNode->getStartLine())->tip($tip)->identifier('property.unused')->build(); } else { $errors[] = RuleErrorBuilder::message(sprintf('%s is never read, only written.', $propertyName))->line($propertyNode->getStartLine())->identifier('property.onlyWritten')->tip($tip)->build(); } } elseif (!$data['written'] && (!array_key_exists($name, $uninitializedProperties) || !$this->checkUninitializedProperties)) { $errors[] = RuleErrorBuilder::message(sprintf('%s is never written, only read.', $propertyName))->line($propertyNode->getStartLine())->identifier('property.onlyRead')->tip($tip)->build(); } } return $errors; } } */ final class UnusedPrivateMethodRule implements Rule { /** * @var AlwaysUsedMethodExtensionProvider */ private $extensionProvider; public function __construct(AlwaysUsedMethodExtensionProvider $extensionProvider) { $this->extensionProvider = $extensionProvider; } public function getNodeType() : string { return ClassMethodsNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->getClass() instanceof Node\Stmt\Class_ && !$node->getClass() instanceof Node\Stmt\Enum_) { return []; } $classReflection = $node->getClassReflection(); $classType = new ObjectType($classReflection->getName(), null, $classReflection); $constructor = null; if ($classReflection->hasConstructor()) { $constructor = $classReflection->getConstructor(); } $methods = []; foreach ($node->getMethods() as $method) { if (!$method->getNode()->isPrivate()) { continue; } if ($method->isDeclaredInTrait()) { continue; } $methodName = $method->getNode()->name->toString(); if ($constructor !== null && $constructor->getName() === $methodName) { continue; } if (strtolower($methodName) === '__clone') { continue; } $methodReflection = $classReflection->getNativeMethod($methodName); foreach ($this->extensionProvider->getExtensions() as $extension) { if ($extension->isAlwaysUsed($methodReflection)) { continue 2; } } $methods[strtolower($methodName)] = $method; } $arrayCalls = []; foreach ($node->getMethodCalls() as $methodCall) { $methodCallNode = $methodCall->getNode(); if ($methodCallNode instanceof Node\Expr\Array_) { $arrayCalls[] = $methodCall; continue; } $callScope = $methodCall->getScope(); if ($methodCallNode->name instanceof Identifier) { $methodNames = [$methodCallNode->name->toString()]; } else { $methodNameType = $callScope->getType($methodCallNode->name); $strings = $methodNameType->getConstantStrings(); if (count($strings) === 0) { // handle subtractions of a dynamic method call foreach ($methods as $lowerMethodName => $method) { if ((new ConstantStringType($method->getNode()->name->toString()))->isSuperTypeOf($methodNameType)->no()) { continue; } unset($methods[$lowerMethodName]); } continue; } $methodNames = array_map(static function (ConstantStringType $type) : string { return $type->getValue(); }, $strings); } if ($methodCallNode instanceof Node\Expr\MethodCall) { $calledOnType = $callScope->getType($methodCallNode->var); } else { if ($methodCallNode->class instanceof Node\Name) { $calledOnType = $callScope->resolveTypeByName($methodCallNode->class); } else { $calledOnType = $callScope->getType($methodCallNode->class); } } $inMethod = $callScope->getFunction(); if (!$inMethod instanceof MethodReflection) { continue; } foreach ($methodNames as $methodName) { $methodReflection = $callScope->getMethodReflection($calledOnType, $methodName); if ($methodReflection === null) { if (!$classType->isSuperTypeOf($calledOnType)->no()) { unset($methods[strtolower($methodName)]); } continue; } if ($methodReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { if (!$classType->isSuperTypeOf($calledOnType)->no()) { unset($methods[strtolower($methodName)]); } continue; } if ($inMethod->getName() === $methodName) { continue; } unset($methods[strtolower($methodName)]); } } if (count($methods) > 0) { foreach ($arrayCalls as $arrayCall) { /** @var Node\Expr\Array_ $array */ $array = $arrayCall->getNode(); $arrayScope = $arrayCall->getScope(); $arrayType = $arrayScope->getType($array); if (!$arrayType->isCallable()->yes()) { continue; } foreach ($arrayType->getConstantArrays() as $constantArray) { foreach ($constantArray->findTypeAndMethodNames() as $typeAndMethod) { if ($typeAndMethod->isUnknown()) { return []; } if (!$typeAndMethod->getCertainty()->yes()) { return []; } $calledOnType = $typeAndMethod->getType(); $methodReflection = $arrayScope->getMethodReflection($calledOnType, $typeAndMethod->getMethod()); if ($methodReflection === null) { continue; } if ($methodReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { continue; } $inMethod = $arrayScope->getFunction(); if (!$inMethod instanceof MethodReflection) { continue; } if ($inMethod->getName() === $typeAndMethod->getMethod()) { continue; } unset($methods[strtolower($typeAndMethod->getMethod())]); } } } } $errors = []; foreach ($methods as $method) { $originalMethodName = $method->getNode()->name->toString(); $methodType = 'Method'; if ($method->getNode()->isStatic()) { $methodType = 'Static method'; } $errors[] = RuleErrorBuilder::message(sprintf('%s %s::%s() is unused.', $methodType, $classReflection->getDisplayName(), $originalMethodName))->line($method->getNode()->getStartLine())->identifier('method.unused')->build(); } return $errors; } } */ final class ConstructorWithoutImpurePointsCollector implements Collector { public function getNodeType() : string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) { $method = $node->getMethodReflection(); if (!$method->isConstructor()) { return null; } if (!$method->isPure()->maybe()) { return null; } if (count($node->getImpurePoints()) !== 0) { return null; } if (count($node->getStatementResult()->getThrowPoints()) !== 0) { return null; } foreach ($method->getParameters() as $parameter) { if (!$parameter->passedByReference()->createsNewVariable()) { continue; } return null; } if (count($method->getAsserts()->getAll()) !== 0) { return null; } return $method->getDeclaringClass()->getName(); } } */ final class FunctionWithoutImpurePointsCollector implements Collector { public function getNodeType() : string { return FunctionReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) { $function = $node->getFunctionReflection(); if (!$function->isPure()->maybe()) { return null; } if (!$function->hasSideEffects()->maybe()) { return null; } if (count($node->getImpurePoints()) !== 0) { return null; } if (count($node->getStatementResult()->getThrowPoints()) !== 0) { return null; } foreach ($function->getParameters() as $parameter) { if (!$parameter->passedByReference()->createsNewVariable()) { continue; } return null; } if (count($function->getAsserts()->getAll()) !== 0) { return null; } return $function->getName(); } } */ final class CallToStaticMethodStatementWithoutImpurePointsRule implements Rule { public function getNodeType() : string { return CollectedDataNode::class; } public function processNode(Node $node, Scope $scope) : array { $methods = []; foreach ($node->get(\PHPStan\Rules\DeadCode\MethodWithoutImpurePointsCollector::class) as $collected) { foreach ($collected as [$className, $methodName, $classDisplayName]) { $lowerClassName = strtolower($className); if (!array_key_exists($lowerClassName, $methods)) { $methods[$lowerClassName] = []; } $methods[$lowerClassName][strtolower($methodName)] = $classDisplayName . '::' . $methodName; } } $errors = []; foreach ($node->get(\PHPStan\Rules\DeadCode\PossiblyPureStaticCallCollector::class) as $filePath => $data) { foreach ($data as [$className, $method, $line]) { $lowerClassName = strtolower($className); if (!array_key_exists($lowerClassName, $methods)) { continue; } $lowerMethod = strtolower($method); if (!array_key_exists($lowerMethod, $methods[$lowerClassName])) { continue; } $originalMethodName = $methods[$lowerClassName][$lowerMethod]; $errors[] = RuleErrorBuilder::message(sprintf('Call to %s() on a separate line has no effect.', $originalMethodName))->file($filePath)->line($line)->identifier('staticMethod.resultUnused')->build(); } } return $errors; } } */ final class MethodWithoutImpurePointsCollector implements Collector { public function getNodeType() : string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) { $method = $node->getMethodReflection(); if (!$method->isPure()->maybe()) { return null; } if (!$method->hasSideEffects()->maybe()) { return null; } if (count($node->getImpurePoints()) !== 0) { return null; } if (count($node->getStatementResult()->getThrowPoints()) !== 0) { return null; } foreach ($method->getParameters() as $parameter) { if (!$parameter->passedByReference()->createsNewVariable()) { continue; } return null; } if (count($method->getAsserts()->getAll()) !== 0) { return null; } if ($method->isConstructor()) { return null; } return [$method->getDeclaringClass()->getName(), $method->getName(), $method->getDeclaringClass()->getDisplayName()]; } } */ final class CallToMethodStatementWithoutImpurePointsRule implements Rule { public function getNodeType() : string { return CollectedDataNode::class; } public function processNode(Node $node, Scope $scope) : array { $methods = []; foreach ($node->get(\PHPStan\Rules\DeadCode\MethodWithoutImpurePointsCollector::class) as $collected) { foreach ($collected as [$className, $methodName, $classDisplayName]) { $className = strtolower($className); if (!array_key_exists($className, $methods)) { $methods[$className] = []; } $methods[$className][strtolower($methodName)] = $classDisplayName . '::' . $methodName; } } $errors = []; foreach ($node->get(\PHPStan\Rules\DeadCode\PossiblyPureMethodCallCollector::class) as $filePath => $data) { foreach ($data as [$classNames, $method, $line]) { $originalMethodName = null; foreach ($classNames as $className) { $className = strtolower($className); if (!array_key_exists($className, $methods)) { continue 2; } $lowerMethod = strtolower($method); if (!array_key_exists($lowerMethod, $methods[$className])) { continue 2; } $originalMethodName = $methods[$className][$lowerMethod]; } $errors[] = RuleErrorBuilder::message(sprintf('Call to method %s() on a separate line has no effect.', $originalMethodName))->file($filePath)->line($line)->identifier('method.resultUnused')->build(); } } return $errors; } } */ final class BetterNoopRule implements Rule { /** * @var ExprPrinter */ private $exprPrinter; public function __construct(ExprPrinter $exprPrinter) { $this->exprPrinter = $exprPrinter; } public function getNodeType() : string { return NoopExpressionNode::class; } public function processNode(Node $node, Scope $scope) : array { $expr = $node->getOriginalExpr(); if ($expr instanceof Node\Expr\BinaryOp\LogicalXor) { return [RuleErrorBuilder::message('Unused result of "xor" operator.')->line($expr->getStartLine())->tip('This operator has unexpected precedence, try disambiguating the logic with parentheses ().')->identifier('logicalXor.resultUnused')->build()]; } if ($expr instanceof Node\Expr\BinaryOp\LogicalAnd || $expr instanceof Node\Expr\BinaryOp\LogicalOr) { $identifierType = $expr instanceof Node\Expr\BinaryOp\LogicalAnd ? 'logicalAnd' : 'logicalOr'; return [RuleErrorBuilder::message(sprintf('Unused result of "%s" operator.', $expr->getOperatorSigil()))->line($expr->getStartLine())->tip('This operator has unexpected precedence, try disambiguating the logic with parentheses ().')->identifier(sprintf('%s.resultUnused', $identifierType))->build()]; } if ($node->hasAssign()) { return []; } if ($expr instanceof Node\Expr\BinaryOp\BooleanAnd || $expr instanceof Node\Expr\BinaryOp\BooleanOr) { $identifierType = $expr instanceof Node\Expr\BinaryOp\BooleanAnd ? 'booleanAnd' : 'booleanOr'; return [RuleErrorBuilder::message(sprintf('Unused result of "%s" operator.', $expr->getOperatorSigil()))->line($expr->getStartLine())->identifier(sprintf('%s.resultUnused', $identifierType))->build()]; } if ($expr instanceof Node\Expr\Ternary) { return [RuleErrorBuilder::message('Unused result of ternary operator.')->line($expr->getStartLine())->identifier('ternary.resultUnused')->build()]; } if ($expr instanceof Node\Expr\FuncCall) { if ($expr->name instanceof Node\Name) { // handled by CallToFunctionStatementWithoutSideEffectsRule return []; } $nameType = $scope->getType($expr->name); if (!$nameType->isCallable()->yes()) { return []; } } if ($expr instanceof Node\Expr\New_ && $expr->class instanceof Node\Name) { // handled by CallToConstructorStatementWithoutSideEffectsRule return []; } if ($expr instanceof Node\Expr\NullsafeMethodCall || $expr instanceof Node\Expr\MethodCall || $expr instanceof Node\Expr\StaticCall) { // handled by *WithoutSideEffectsRule rules return []; } if ($expr instanceof Node\Expr\Assign || $expr instanceof Node\Expr\AssignOp || $expr instanceof Node\Expr\AssignRef) { return []; } if ($expr instanceof Node\Expr\Closure) { return []; } $exprString = $this->exprPrinter->printExpr($expr); $exprStringLines = preg_split('~\\R~', $exprString, 2); if ($exprStringLines !== \false && count($exprStringLines) > 1) { $exprString = $exprStringLines[0] . '…'; } return [RuleErrorBuilder::message(sprintf('Expression "%s" on a separate line does not do anything.', $exprString))->line($expr->getStartLine())->identifier('expr.resultUnused')->build()]; } } , string, int}> */ final class PossiblyPureMethodCallCollector implements Collector { public function __construct() { } public function getNodeType() : string { return Expression::class; } public function processNode(Node $node, Scope $scope) { if (!$node->expr instanceof Node\Expr\MethodCall) { return null; } if (!$node->expr->name instanceof Node\Identifier) { return null; } $methodName = $node->expr->name->toString(); $calledOnType = $scope->getType($node->expr->var); if (!$calledOnType->hasMethod($methodName)->yes()) { return null; } $classNames = []; $methodReflection = null; foreach ($calledOnType->getObjectClassReflections() as $classReflection) { if (!$classReflection->hasMethod($methodName)) { return null; } $methodReflection = $classReflection->getMethod($methodName, $scope); if (!$methodReflection->isPrivate() && !$methodReflection->isFinal()->yes() && !$methodReflection->getDeclaringClass()->isFinal()) { if (!$classReflection->isFinal()) { return null; } } if (!$methodReflection->isPure()->maybe()) { return null; } if (!$methodReflection->hasSideEffects()->maybe()) { return null; } $classNames[] = $methodReflection->getDeclaringClass()->getName(); } if ($methodReflection === null) { return null; } return [$classNames, $methodReflection->getName(), $node->getStartLine()]; } } */ final class PossiblyPureFuncCallCollector implements Collector { /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Expression::class; } public function processNode(Node $node, Scope $scope) { if (!$node->expr instanceof Node\Expr\FuncCall) { return null; } if (!$node->expr->name instanceof Node\Name) { return null; } if (!$this->reflectionProvider->hasFunction($node->expr->name, $scope)) { return null; } $functionReflection = $this->reflectionProvider->getFunction($node->expr->name, $scope); if (!$functionReflection->isPure()->maybe()) { return null; } if (!$functionReflection->hasSideEffects()->maybe()) { return null; } return [$functionReflection->getName(), $node->getStartLine()]; } } */ final class TooWideFunctionReturnTypehintRule implements Rule { public function getNodeType() : string { return FunctionReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $function = $node->getFunctionReflection(); $functionReturnType = $function->getReturnType(); $functionReturnType = TypeUtils::resolveLateResolvableTypes($functionReturnType); if (!$functionReturnType instanceof UnionType) { return []; } $statementResult = $node->getStatementResult(); if ($statementResult->hasYield()) { return []; } $returnStatements = $node->getReturnStatements(); if (count($returnStatements) === 0) { return []; } $returnTypes = []; foreach ($returnStatements as $returnStatement) { $returnNode = $returnStatement->getReturnNode(); if ($returnNode->expr === null) { $returnTypes[] = new VoidType(); continue; } $returnTypes[] = $returnStatement->getScope()->getType($returnNode->expr); } if (!$statementResult->isAlwaysTerminating()) { $returnTypes[] = new VoidType(); } $returnType = TypeCombinator::union(...$returnTypes); $messages = []; foreach ($functionReturnType->getTypes() as $type) { if (!$type->isSuperTypeOf($returnType)->no()) { continue; } if ($type->isNull()->yes() && !$node->hasNativeReturnTypehint()) { foreach ($node->getExecutionEnds() as $executionEnd) { if ($executionEnd->getStatementResult()->isAlwaysTerminating()) { continue; } continue 2; } } $messages[] = RuleErrorBuilder::message(sprintf('Function %s() never returns %s so it can be removed from the return type.', $function->getName(), $type->describe(VerbosityLevel::getRecommendedLevelByType($type))))->identifier('return.unusedType')->build(); } return $messages; } } */ final class TooWideMethodReturnTypehintRule implements Rule { /** * @var bool */ private $checkProtectedAndPublicMethods; /** * @var bool */ private $alwaysCheckFinal; public function __construct(bool $checkProtectedAndPublicMethods, bool $alwaysCheckFinal) { $this->checkProtectedAndPublicMethods = $checkProtectedAndPublicMethods; $this->alwaysCheckFinal = $alwaysCheckFinal; } public function getNodeType() : string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { if ($scope->isInTrait()) { return []; } $method = $node->getMethodReflection(); $isFirstDeclaration = $method->getPrototype()->getDeclaringClass() === $method->getDeclaringClass(); if (!$method->isPrivate()) { if ($this->alwaysCheckFinal) { if (!$method->getDeclaringClass()->isFinal() && !$method->isFinal()->yes()) { if (!$this->checkProtectedAndPublicMethods) { return []; } if ($isFirstDeclaration) { return []; } } } elseif (!$this->checkProtectedAndPublicMethods) { return []; } elseif ($isFirstDeclaration && !$method->getDeclaringClass()->isFinal() && !$method->isFinal()->yes()) { return []; } } $methodReturnType = $method->getReturnType(); $methodReturnType = TypeUtils::resolveLateResolvableTypes($methodReturnType); if (!$methodReturnType instanceof UnionType) { return []; } $statementResult = $node->getStatementResult(); if ($statementResult->hasYield()) { return []; } $returnStatements = $node->getReturnStatements(); if (count($returnStatements) === 0) { return []; } $returnTypes = []; foreach ($returnStatements as $returnStatement) { $returnNode = $returnStatement->getReturnNode(); if ($returnNode->expr === null) { $returnTypes[] = new VoidType(); continue; } $returnTypes[] = $returnStatement->getScope()->getType($returnNode->expr); } if (!$statementResult->isAlwaysTerminating()) { $returnTypes[] = new VoidType(); } $returnType = TypeCombinator::union(...$returnTypes); if (!$method->isPrivate() && ($returnType->isNull()->yes() || $returnType instanceof ConstantBooleanType) && !$isFirstDeclaration) { return []; } $messages = []; foreach ($methodReturnType->getTypes() as $type) { if (!$type->isSuperTypeOf($returnType)->no()) { continue; } if ($type->isNull()->yes() && !$node->hasNativeReturnTypehint()) { foreach ($node->getExecutionEnds() as $executionEnd) { if ($executionEnd->getStatementResult()->isAlwaysTerminating()) { continue; } continue 2; } } $messages[] = RuleErrorBuilder::message(sprintf('Method %s::%s() never returns %s so it can be removed from the return type.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $type->describe(VerbosityLevel::getRecommendedLevelByType($type))))->identifier('return.unusedType')->build(); } return $messages; } } */ final class TooWideArrowFunctionReturnTypehintRule implements Rule { public function getNodeType() : string { return InArrowFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $arrowFunction = $node->getOriginalNode(); if ($arrowFunction->returnType === null) { return []; } $expr = $arrowFunction->expr; if ($expr instanceof Node\Expr\YieldFrom || $expr instanceof Node\Expr\Yield_) { return []; } $functionReturnType = $scope->getFunctionType($arrowFunction->returnType, \false, \false); if (!$functionReturnType instanceof UnionType) { return []; } $returnType = $scope->getType($expr); if ($returnType->isNull()->yes()) { return []; } $messages = []; foreach ($functionReturnType->getTypes() as $type) { if (!$type->isSuperTypeOf($returnType)->no()) { continue; } $messages[] = RuleErrorBuilder::message(sprintf('Anonymous function never returns %s so it can be removed from the return type.', $type->describe(VerbosityLevel::getRecommendedLevelByType($type))))->identifier('return.unusedType')->build(); } return $messages; } } */ final class TooWideFunctionParameterOutTypeRule implements Rule { /** * @var TooWideParameterOutTypeCheck */ private $check; public function __construct(\PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck $check) { $this->check = $check; } public function getNodeType() : string { return FunctionReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $inFunction = $node->getFunctionReflection(); return $this->check->check($node->getExecutionEnds(), $node->getReturnStatements(), $inFunction->getParameters(), sprintf('Function %s()', $inFunction->getName())); } } $executionEnds * @param list $returnStatements * @param ParameterReflectionWithPhpDocs[] $parameters * @return list */ public function check(array $executionEnds, array $returnStatements, array $parameters, string $functionDescription) : array { $finalScope = null; foreach ($executionEnds as $executionEnd) { $endScope = $executionEnd->getStatementResult()->getScope(); if ($finalScope === null) { $finalScope = $endScope; continue; } $finalScope = $finalScope->mergeWith($endScope); } foreach ($returnStatements as $statement) { if ($finalScope === null) { $finalScope = $statement->getScope(); continue; } $finalScope = $finalScope->mergeWith($statement->getScope()); } if ($finalScope === null) { return []; } $errors = []; foreach ($parameters as $parameter) { if (!$parameter->passedByReference()->createsNewVariable()) { continue; } foreach ($this->processSingleParameter($finalScope, $functionDescription, $parameter) as $error) { $errors[] = $error; } } return $errors; } /** * @return list */ private function processSingleParameter(Scope $scope, string $functionDescription, ParameterReflectionWithPhpDocs $parameter) : array { $isParamOutType = \true; $outType = $parameter->getOutType(); if ($outType === null) { $isParamOutType = \false; $outType = $parameter->getType(); } $outType = TypeUtils::resolveLateResolvableTypes($outType); if (!$outType instanceof UnionType) { return []; } $variableExpr = new Variable($parameter->getName()); $variableType = $scope->getType($variableExpr); $messages = []; foreach ($outType->getTypes() as $type) { if (!$type->isSuperTypeOf($variableType)->no()) { continue; } $errorBuilder = RuleErrorBuilder::message(sprintf('%s never assigns %s to &$%s so it can be removed from the %s.', $functionDescription, $type->describe(VerbosityLevel::getRecommendedLevelByType($type)), $parameter->getName(), $isParamOutType ? '@param-out type' : 'by-ref type'))->identifier(sprintf('%s.unusedType', $isParamOutType ? 'paramOut' : 'parameterByRef')); if (!$isParamOutType) { $errorBuilder->tip('You can narrow the parameter out type with @param-out PHPDoc tag.'); } $messages[] = $errorBuilder->build(); } return $messages; } } */ final class TooWideClosureReturnTypehintRule implements Rule { public function getNodeType() : string { return ClosureReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $closureExpr = $node->getClosureExpr(); if ($closureExpr->returnType === null) { return []; } $statementResult = $node->getStatementResult(); if ($statementResult->hasYield()) { return []; } $returnStatements = $node->getReturnStatements(); if (count($returnStatements) === 0) { return []; } $closureReturnType = $scope->getFunctionType($closureExpr->returnType, \false, \false); if (!$closureReturnType instanceof UnionType) { return []; } $returnTypes = []; foreach ($returnStatements as $returnStatement) { $returnNode = $returnStatement->getReturnNode(); if ($returnNode->expr === null) { continue; } $returnTypes[] = $returnStatement->getScope()->getType($returnNode->expr); } if (count($returnTypes) === 0) { return []; } $returnType = TypeCombinator::union(...$returnTypes); if ($returnType->isNull()->yes()) { return []; } $messages = []; foreach ($closureReturnType->getTypes() as $type) { if (!$type->isSuperTypeOf($returnType)->no()) { continue; } $messages[] = RuleErrorBuilder::message(sprintf('Anonymous function never returns %s so it can be removed from the return type.', $type->describe(VerbosityLevel::getRecommendedLevelByType($type))))->identifier('return.unusedType')->build(); } return $messages; } } */ final class TooWideMethodParameterOutTypeRule implements Rule { /** * @var TooWideParameterOutTypeCheck */ private $check; public function __construct(\PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck $check) { $this->check = $check; } public function getNodeType() : string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $inMethod = $node->getMethodReflection(); return $this->check->check($node->getExecutionEnds(), $node->getReturnStatements(), $inMethod->getParameters(), sprintf('Method %s::%s()', $inMethod->getDeclaringClass()->getDisplayName(), $inMethod->getName())); } } */ final class TooWidePropertyTypeRule implements Rule { /** * @var ReadWritePropertiesExtensionProvider */ private $extensionProvider; /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; public function __construct(ReadWritePropertiesExtensionProvider $extensionProvider, PropertyReflectionFinder $propertyReflectionFinder) { $this->extensionProvider = $extensionProvider; $this->propertyReflectionFinder = $propertyReflectionFinder; } public function getNodeType() : string { return ClassPropertiesNode::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; $classReflection = $node->getClassReflection(); foreach ($node->getProperties() as $property) { if (!$property->isPrivate()) { continue; } if ($property->isDeclaredInTrait()) { continue; } if ($property->isPromoted()) { continue; } $propertyName = $property->getName(); if (!$classReflection->hasNativeProperty($propertyName)) { continue; } $propertyReflection = $classReflection->getNativeProperty($propertyName); $propertyType = $propertyReflection->getWritableType(); if (!$propertyType instanceof UnionType) { continue; } foreach ($this->extensionProvider->getExtensions() as $extension) { if ($extension->isAlwaysRead($propertyReflection, $propertyName)) { continue 2; } if ($extension->isAlwaysWritten($propertyReflection, $propertyName)) { continue 2; } if ($extension->isInitialized($propertyReflection, $propertyName)) { continue 2; } } $assignedTypes = []; foreach ($node->getPropertyAssigns() as $assign) { $assignNode = $assign->getAssign(); $assignPropertyReflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($assignNode->getPropertyFetch(), $assign->getScope()); foreach ($assignPropertyReflections as $assignPropertyReflection) { if ($propertyName !== $assignPropertyReflection->getName()) { continue; } if ($propertyReflection->getDeclaringClass()->getName() !== $assignPropertyReflection->getDeclaringClass()->getName()) { continue; } $assignedTypes[] = $assignPropertyReflection->getScope()->getType($assignNode->getAssignedExpr()); } } if ($property->getDefault() !== null) { $assignedTypes[] = $scope->getType($property->getDefault()); } if (count($assignedTypes) === 0) { continue; } $assignedType = TypeCombinator::union(...$assignedTypes); $propertyDescription = $this->describePropertyByName($propertyReflection, $propertyName); $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($propertyType, $assignedType); foreach ($propertyType->getTypes() as $type) { if (!$type->isSuperTypeOf($assignedType)->no()) { continue; } if ($property->getNativeType() === null && (new NullType())->isSuperTypeOf($type)->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('%s (%s) is never assigned %s so it can be removed from the property type.', $propertyDescription, $propertyType->describe($verbosityLevel), $type->describe($verbosityLevel)))->identifier('property.unusedType')->line($property->getStartLine())->build(); } } return $errors; } private function describePropertyByName(PropertyReflection $property, string $propertyName) : string { if (!$property->isStatic()) { return sprintf('Property %s::$%s', $property->getDeclaringClass()->getDisplayName(), $propertyName); } return sprintf('Static property %s::$%s', $property->getDeclaringClass()->getDisplayName(), $propertyName); } } */ final class InvalidComparisonOperationRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Expr\BinaryOp::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Node\Expr\BinaryOp\Equal && !$node instanceof Node\Expr\BinaryOp\NotEqual && !$node instanceof Node\Expr\BinaryOp\Smaller && !$node instanceof Node\Expr\BinaryOp\SmallerOrEqual && !$node instanceof Node\Expr\BinaryOp\Greater && !$node instanceof Node\Expr\BinaryOp\GreaterOrEqual && !$node instanceof Node\Expr\BinaryOp\Spaceship) { return []; } if ($this->isNumberType($scope, $node->left) && $this->isNumberType($scope, $node->right)) { return []; } if ($this->isNumberType($scope, $node->left) && ($this->isPossiblyNullableObjectType($scope, $node->right) || $this->isPossiblyNullableArrayType($scope, $node->right)) || $this->isNumberType($scope, $node->right) && ($this->isPossiblyNullableObjectType($scope, $node->left) || $this->isPossiblyNullableArrayType($scope, $node->left))) { switch (get_class($node)) { case Node\Expr\BinaryOp\Equal::class: $nodeType = 'equal'; break; case Node\Expr\BinaryOp\NotEqual::class: $nodeType = 'notEqual'; break; case Node\Expr\BinaryOp\Greater::class: $nodeType = 'greater'; break; case Node\Expr\BinaryOp\GreaterOrEqual::class: $nodeType = 'greaterOrEqual'; break; case Node\Expr\BinaryOp\Smaller::class: $nodeType = 'smaller'; break; case Node\Expr\BinaryOp\SmallerOrEqual::class: $nodeType = 'smallerOrEqual'; break; case Node\Expr\BinaryOp\Spaceship::class: $nodeType = 'spaceship'; break; default: throw new ShouldNotHappenException(); } return [RuleErrorBuilder::message(sprintf('Comparison operation "%s" between %s and %s results in an error.', $node->getOperatorSigil(), $scope->getType($node->left)->describe(VerbosityLevel::value()), $scope->getType($node->right)->describe(VerbosityLevel::value())))->line($node->left->getStartLine())->identifier(sprintf('%s.invalid', $nodeType))->build()]; } return []; } private function isNumberType(Scope $scope, Node\Expr $expr) : bool { $acceptedType = new UnionType([new IntegerType(), new FloatType()]); $onlyNumber = static function (Type $type) use($acceptedType) : bool { return $acceptedType->isSuperTypeOf($type)->yes(); }; $type = $this->ruleLevelHelper->findTypeToCheck($scope, $expr, '', $onlyNumber)->getType(); if ($type instanceof ErrorType || !$type->equals($scope->getType($expr))) { return \false; } // SimpleXMLElement can be cast to number union type return !$acceptedType->isSuperTypeOf($type)->no() || $acceptedType->equals($type->toNumber()); } private function isPossiblyNullableObjectType(Scope $scope, Node\Expr $expr) : bool { $acceptedType = new ObjectWithoutClassType(); $type = $this->ruleLevelHelper->findTypeToCheck($scope, $expr, '', static function (Type $type) use($acceptedType) : bool { return $acceptedType->isSuperTypeOf($type)->yes(); })->getType(); if ($type instanceof ErrorType) { return \false; } if (TypeCombinator::containsNull($type) && !$type->isNull()->yes()) { $type = TypeCombinator::removeNull($type); } $isSuperType = $acceptedType->isSuperTypeOf($type); if ($type instanceof BenevolentUnionType) { return !$isSuperType->no(); } return $isSuperType->yes(); } private function isPossiblyNullableArrayType(Scope $scope, Node\Expr $expr) : bool { $type = $this->ruleLevelHelper->findTypeToCheck($scope, $expr, '', static function (Type $type) : bool { return $type->isArray()->yes(); })->getType(); if (TypeCombinator::containsNull($type) && !$type->isNull()->yes()) { $type = TypeCombinator::removeNull($type); } return !$type instanceof ErrorType && $type->isArray()->yes(); } } */ final class InvalidUnaryOperationRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var bool */ private $bleedingEdge; public function __construct(RuleLevelHelper $ruleLevelHelper, bool $bleedingEdge) { $this->ruleLevelHelper = $ruleLevelHelper; $this->bleedingEdge = $bleedingEdge; } public function getNodeType() : string { return Node\Expr::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Node\Expr\UnaryPlus && !$node instanceof Node\Expr\UnaryMinus && !$node instanceof Node\Expr\BitwiseNot) { return []; } if ($this->bleedingEdge) { $varName = '__PHPSTAN__LEFT__'; $variable = new Node\Expr\Variable($varName); $newNode = clone $node; $newNode->setAttribute('phpstan_cache_printer', null); $newNode->expr = $variable; if ($node instanceof Node\Expr\BitwiseNot) { $callback = static function (Type $type) : bool { return $type->isString()->yes() || $type->isInteger()->yes() || $type->isFloat()->yes(); }; } else { $callback = static function (Type $type) : bool { return !$type->toNumber() instanceof ErrorType; }; } $exprType = $this->ruleLevelHelper->findTypeToCheck($scope, $node->expr, '', $callback)->getType(); if ($exprType instanceof ErrorType) { return []; } if (!$scope instanceof MutatingScope) { throw new ShouldNotHappenException(); } $scope = $scope->assignVariable($varName, $exprType, $exprType); if (!$scope->getType($newNode) instanceof ErrorType) { return []; } } elseif (!$scope->getType($node) instanceof ErrorType) { return []; } if ($node instanceof Node\Expr\UnaryPlus) { $operator = '+'; } elseif ($node instanceof Node\Expr\UnaryMinus) { $operator = '-'; } else { $operator = '~'; } return [RuleErrorBuilder::message(sprintf('Unary operation "%s" on %s results in an error.', $operator, $scope->getType($node->expr)->describe(VerbosityLevel::value())))->line($node->expr->getStartLine())->identifier('unaryOp.invalid')->build()]; } } */ final class InvalidAssignVarRule implements Rule { /** * @var NullsafeCheck */ private $nullsafeCheck; public function __construct(NullsafeCheck $nullsafeCheck) { $this->nullsafeCheck = $nullsafeCheck; } public function getNodeType() : string { return Expr::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Assign && !$node instanceof AssignOp && !$node instanceof AssignRef) { return []; } if ($this->nullsafeCheck->containsNullSafe($node->var)) { return [RuleErrorBuilder::message('Nullsafe operator cannot be on left side of assignment.')->identifier('nullsafe.assign')->nonIgnorable()->build()]; } if ($node instanceof AssignRef && $this->nullsafeCheck->containsNullSafe($node->expr)) { return [RuleErrorBuilder::message('Nullsafe operator cannot be on right side of assignment by reference.')->identifier('nullsafe.byRef')->nonIgnorable()->build()]; } if ($this->containsNonAssignableExpression($node->var)) { return [RuleErrorBuilder::message('Expression on left side of assignment is not assignable.')->identifier('assign.invalidExpr')->nonIgnorable()->build()]; } return []; } private function containsNonAssignableExpression(Expr $expr) : bool { if ($expr instanceof Expr\Variable) { return \false; } if ($expr instanceof Expr\PropertyFetch) { return \false; } if ($expr instanceof Expr\ArrayDimFetch) { return \false; } if ($expr instanceof Expr\StaticPropertyFetch) { return \false; } if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) { foreach ($expr->items as $item) { if ($item === null) { continue; } if (!$this->containsNonAssignableExpression($item->value)) { continue; } return \true; } return \false; } return \true; } } */ final class InvalidBinaryOperationRule implements Rule { /** * @var ExprPrinter */ private $exprPrinter; /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var bool */ private $bleedingEdge; public function __construct(ExprPrinter $exprPrinter, RuleLevelHelper $ruleLevelHelper, bool $bleedingEdge) { $this->exprPrinter = $exprPrinter; $this->ruleLevelHelper = $ruleLevelHelper; $this->bleedingEdge = $bleedingEdge; } public function getNodeType() : string { return Node\Expr::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Node\Expr\BinaryOp && !$node instanceof Node\Expr\AssignOp) { return []; } if (!$scope->getType($node) instanceof ErrorType && !$this->bleedingEdge) { return []; } $leftName = '__PHPSTAN__LEFT__'; $rightName = '__PHPSTAN__RIGHT__'; $leftVariable = new Node\Expr\Variable($leftName); $rightVariable = new Node\Expr\Variable($rightName); if ($node instanceof Node\Expr\AssignOp) { $identifier = 'assignOp'; $newNode = clone $node; $newNode->setAttribute('phpstan_cache_printer', null); $left = $node->var; $right = $node->expr; $newNode->var = $leftVariable; $newNode->expr = $rightVariable; } else { $identifier = 'binaryOp'; $newNode = clone $node; $newNode->setAttribute('phpstan_cache_printer', null); $left = $node->left; $right = $node->right; $newNode->left = $leftVariable; $newNode->right = $rightVariable; } if ($node instanceof Node\Expr\AssignOp\Concat || $node instanceof Node\Expr\BinaryOp\Concat) { $callback = static function (Type $type) : bool { return !$type->toString() instanceof ErrorType; }; } elseif ($node instanceof Node\Expr\AssignOp\Plus || $node instanceof Node\Expr\BinaryOp\Plus) { $callback = static function (Type $type) : bool { return !$type->toNumber() instanceof ErrorType || $type->isArray()->yes(); }; } else { $callback = static function (Type $type) : bool { return !$type->toNumber() instanceof ErrorType; }; } $leftType = $this->ruleLevelHelper->findTypeToCheck($scope, $left, '', $callback)->getType(); if ($leftType instanceof ErrorType) { return []; } $rightType = $this->ruleLevelHelper->findTypeToCheck($scope, $right, '', $callback)->getType(); if ($rightType instanceof ErrorType) { return []; } if (!$scope instanceof MutatingScope) { throw new ShouldNotHappenException(); } $scope = $scope->assignVariable($leftName, $leftType, $leftType)->assignVariable($rightName, $rightType, $rightType); if (!$scope->getType($newNode) instanceof ErrorType) { return []; } return [RuleErrorBuilder::message(sprintf('Binary operation "%s" between %s and %s results in an error.', substr(substr($this->exprPrinter->printExpr($newNode), strlen($leftName) + 2), 0, -(strlen($rightName) + 2)), $scope->getType($left)->describe(VerbosityLevel::value()), $scope->getType($right)->describe(VerbosityLevel::value())))->line($left->getStartLine())->identifier(sprintf('%s.invalid', $identifier))->build()]; } } */ final class InvalidIncDecOperationRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var bool */ private $bleedingEdge; /** * @var bool */ private $checkThisOnly; public function __construct(RuleLevelHelper $ruleLevelHelper, bool $bleedingEdge, bool $checkThisOnly) { $this->ruleLevelHelper = $ruleLevelHelper; $this->bleedingEdge = $bleedingEdge; $this->checkThisOnly = $checkThisOnly; } public function getNodeType() : string { return Node\Expr::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Node\Expr\PreInc && !$node instanceof Node\Expr\PostInc && !$node instanceof Node\Expr\PreDec && !$node instanceof Node\Expr\PostDec) { return []; } switch (get_class($node)) { case Node\Expr\PreInc::class: $nodeType = 'preInc'; break; case Node\Expr\PostInc::class: $nodeType = 'postInc'; break; case Node\Expr\PreDec::class: $nodeType = 'preDec'; break; case Node\Expr\PostDec::class: $nodeType = 'postDec'; break; default: throw new ShouldNotHappenException(); } $operatorString = $node instanceof Node\Expr\PreInc || $node instanceof Node\Expr\PostInc ? '++' : '--'; if (!$node->var instanceof Node\Expr\Variable && !$node->var instanceof Node\Expr\ArrayDimFetch && !$node->var instanceof Node\Expr\PropertyFetch && !$node->var instanceof Node\Expr\StaticPropertyFetch) { return [RuleErrorBuilder::message(sprintf('Cannot use %s on a non-variable.', $operatorString))->line($node->var->getStartLine())->identifier(sprintf('%s.expr', $nodeType))->build()]; } if (!$this->bleedingEdge) { if ($this->checkThisOnly) { return []; } $varType = $scope->getType($node->var); if (!$varType->toString() instanceof ErrorType) { return []; } if (!$varType->toNumber() instanceof ErrorType) { return []; } } else { $allowedTypes = new UnionType([new BooleanType(), new FloatType(), new IntegerType(), new StringType(), new NullType(), new ObjectType('SimpleXMLElement')]); $varType = $this->ruleLevelHelper->findTypeToCheck($scope, $node->var, '', static function (Type $type) use($allowedTypes) : bool { return $allowedTypes->isSuperTypeOf($type)->yes(); })->getType(); if ($varType instanceof ErrorType || $allowedTypes->isSuperTypeOf($varType)->yes()) { return []; } } return [RuleErrorBuilder::message(sprintf('Cannot use %s on %s.', $operatorString, $varType->describe(VerbosityLevel::value())))->line($node->var->getStartLine())->identifier(sprintf('%s.type', $nodeType))->build()]; } } ruleLevelHelper = $ruleLevelHelper; } /** @param callable(Type): Type $castFn */ public function checkParameter(Arg $parameter, Scope $scope, string $errorMessageTemplate, callable $castFn, string $functionName, string $parameterName) : ?\PHPStan\Rules\IdentifierRuleError { if ($parameter->unpack) { return null; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $parameter->value, '', static function (Type $type) use($castFn) : bool { return !$castFn($type->getIterableValueType()) instanceof ErrorType; }); if ($typeResult->getType() instanceof ErrorType || !$castFn($typeResult->getType()->getIterableValueType()) instanceof ErrorType) { return null; } return \PHPStan\Rules\RuleErrorBuilder::message(sprintf($errorMessageTemplate, $parameterName, $functionName, $typeResult->getType()->describe(VerbosityLevel::typeOnly())))->identifier('argument.type')->build(); } public function getParameterName(Arg $parameter, int $parameterIdx, ?ParameterReflection $parameterReflection) : string { if ($parameterReflection === null) { return sprintf('#%d', $parameterIdx + 1); } $paramName = $parameterReflection->getName(); $origParameter = $parameter->getAttributes()[ArgumentsNormalizer::ORIGINAL_ARG_ATTRIBUTE] ?? null; if (!$origParameter instanceof Arg) { $origParameter = $parameter; } return $origParameter->name !== null ? sprintf('$%s', $paramName) : sprintf('#%d $%s', $parameterIdx + 1, $paramName); } } containsNullSafe($expr->var); } if ($expr instanceof Expr\PropertyFetch) { return $this->containsNullSafe($expr->var); } if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) { return $this->containsNullSafe($expr->class); } if ($expr instanceof Expr\MethodCall) { return $this->containsNullSafe($expr->var); } if ($expr instanceof Expr\StaticCall && $expr->class instanceof Expr) { return $this->containsNullSafe($expr->class); } if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) { foreach ($expr->items as $item) { if ($item === null) { continue; } if ($item->key !== null && $this->containsNullSafe($item->key)) { return \true; } if ($this->containsNullSafe($item->value)) { return \true; } } } return \false; } } classCaseSensitivityCheck = $classCaseSensitivityCheck; $this->classForbiddenNameCheck = $classForbiddenNameCheck; } /** * @param ClassNameNodePair[] $pairs * @return list */ public function checkClassNames(array $pairs, bool $checkClassCaseSensitivity = \true) : array { $errors = []; if ($checkClassCaseSensitivity) { foreach ($this->classCaseSensitivityCheck->checkClassNames($pairs) as $error) { $errors[] = $error; } } foreach ($this->classForbiddenNameCheck->checkClassNames($pairs) as $error) { $errors[] = $error; } return $errors; } } $nodeType * @return array> */ public function getRules(string $nodeType) : array; } */ public $reasons; /** * @param list $reasons */ public function __construct(bool $result, array $reasons) { $this->result = $result; $this->reasons = $reasons; } public function and(self $other) : self { return new self($this->result && $other->result, array_merge($this->reasons, $other->reasons)); } /** * @param callable(string): string $cb */ public function decorateReasons(callable $cb) : self { $reasons = []; foreach ($this->reasons as $reason) { $reasons[] = $cb($reason); } return new self($this->result, $reasons); } } */ final class MissingCheckedExceptionInMethodThrowsRule implements Rule { /** * @var MissingCheckedExceptionInThrowsCheck */ private $check; public function __construct(\PHPStan\Rules\Exceptions\MissingCheckedExceptionInThrowsCheck $check) { $this->check = $check; } public function getNodeType() : string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $statementResult = $node->getStatementResult(); $methodReflection = $node->getMethodReflection(); $errors = []; foreach ($this->check->check($methodReflection->getThrowType(), $statementResult->getThrowPoints()) as [$className, $throwPointNode]) { $errors[] = RuleErrorBuilder::message(sprintf('Method %s::%s() throws checked exception %s but it\'s missing from the PHPDoc @throws tag.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $className))->line($throwPointNode->getStartLine())->identifier('missingType.checkedException')->build(); } return $errors; } } isVoid()->yes()) { return []; } $throwPointType = TypeCombinator::union(...array_map(static function (ThrowPoint $throwPoint) : Type { if (!$throwPoint->isExplicit()) { return new NeverType(); } return $throwPoint->getType(); }, $throwPoints)); $throwClasses = []; foreach (TypeUtils::flattenTypes($throwType) as $type) { if (!$throwPointType instanceof NeverType && !$type->isSuperTypeOf($throwPointType)->no()) { continue; } $throwClasses[] = $type->describe(VerbosityLevel::typeOnly()); } return $throwClasses; } } */ final class ThrowExpressionRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return Node\Expr\Throw_::class; } public function processNode(Node $node, Scope $scope) : array { if ($this->phpVersion->supportsThrowExpression()) { return []; } return [RuleErrorBuilder::message('Throw expression is supported only on PHP 8.0 and later.')->nonIgnorable()->identifier('throw.notSupported')->build()]; } } reflectionProvider = $reflectionProvider; $this->uncheckedExceptionRegexes = $uncheckedExceptionRegexes; $this->uncheckedExceptionClasses = $uncheckedExceptionClasses; $this->checkedExceptionRegexes = $checkedExceptionRegexes; $this->checkedExceptionClasses = $checkedExceptionClasses; } public function isCheckedException(string $className, Scope $scope) : bool { foreach ($this->uncheckedExceptionRegexes as $regex) { if (Strings::match($className, $regex) !== null) { return \false; } } foreach ($this->uncheckedExceptionClasses as $uncheckedExceptionClass) { if ($className === $uncheckedExceptionClass) { return \false; } } if (!$this->reflectionProvider->hasClass($className)) { return $this->isCheckedExceptionInternal($className); } $classReflection = $this->reflectionProvider->getClass($className); foreach ($this->uncheckedExceptionClasses as $uncheckedExceptionClass) { if ($classReflection->getName() === $uncheckedExceptionClass) { return \false; } if (!$classReflection->isSubclassOf($uncheckedExceptionClass)) { continue; } return \false; } return $this->isCheckedExceptionInternal($className); } private function isCheckedExceptionInternal(string $className) : bool { foreach ($this->checkedExceptionRegexes as $regex) { if (Strings::match($className, $regex) !== null) { return \true; } } foreach ($this->checkedExceptionClasses as $checkedExceptionClass) { if ($className === $checkedExceptionClass) { return \true; } } if (!$this->reflectionProvider->hasClass($className)) { return count($this->checkedExceptionRegexes) === 0 && count($this->checkedExceptionClasses) === 0; } $classReflection = $this->reflectionProvider->getClass($className); foreach ($this->checkedExceptionClasses as $checkedExceptionClass) { if ($classReflection->getName() === $checkedExceptionClass) { return \true; } if (!$classReflection->isSubclassOf($checkedExceptionClass)) { continue; } return \true; } return count($this->checkedExceptionRegexes) === 0 && count($this->checkedExceptionClasses) === 0; } } */ final class CaughtExceptionExistenceRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ClassNameCheck */ private $classCheck; /** * @var bool */ private $checkClassCaseSensitivity; public function __construct(ReflectionProvider $reflectionProvider, ClassNameCheck $classCheck, bool $checkClassCaseSensitivity) { $this->reflectionProvider = $reflectionProvider; $this->classCheck = $classCheck; $this->checkClassCaseSensitivity = $checkClassCaseSensitivity; } public function getNodeType() : string { return Catch_::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; foreach ($node->types as $class) { $className = (string) $class; if (!$this->reflectionProvider->hasClass($className)) { if ($scope->isInClassExists($className)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Caught class %s not found.', $className))->line($class->getStartLine())->identifier('class.notFound')->discoveringSymbolsTip()->build(); continue; } $classReflection = $this->reflectionProvider->getClass($className); if (!$classReflection->isInterface() && !$classReflection->implementsInterface(Throwable::class)) { $errors[] = RuleErrorBuilder::message(sprintf('Caught class %s is not an exception.', $classReflection->getDisplayName()))->line($class->getStartLine())->identifier('catch.notThrowable')->build(); } $errors = array_merge($errors, $this->classCheck->checkClassNames([new ClassNameNodePair($className, $class)], $this->checkClassCaseSensitivity)); } return $errors; } } exceptionTypeResolver = $exceptionTypeResolver; } /** * @param ThrowPoint[] $throwPoints * @return array */ public function check(?Type $throwType, array $throwPoints) : array { if ($throwType === null) { $throwType = new NeverType(); } $classes = []; foreach ($throwPoints as $throwPoint) { if (!$throwPoint->isExplicit()) { continue; } foreach (TypeUtils::flattenTypes($throwPoint->getType()) as $throwPointType) { if ($throwPointType->isSuperTypeOf(new ObjectType(Throwable::class))->yes()) { continue; } if ($throwType->isSuperTypeOf($throwPointType)->yes()) { continue; } $isCheckedException = TrinaryLogic::createNo()->lazyOr($throwPointType->getObjectClassNames(), function (string $objectClassName) use($throwPoint) { return TrinaryLogic::createFromBoolean($this->exceptionTypeResolver->isCheckedException($objectClassName, $throwPoint->getScope())); }); if ($isCheckedException->no()) { continue; } $classes[] = [$throwPointType->describe(VerbosityLevel::typeOnly()), $throwPoint->getNode()]; } } return $classes; } } */ final class MissingCheckedExceptionInFunctionThrowsRule implements Rule { /** * @var MissingCheckedExceptionInThrowsCheck */ private $check; public function __construct(\PHPStan\Rules\Exceptions\MissingCheckedExceptionInThrowsCheck $check) { $this->check = $check; } public function getNodeType() : string { return FunctionReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $statementResult = $node->getStatementResult(); $functionReflection = $node->getFunctionReflection(); $errors = []; foreach ($this->check->check($functionReflection->getThrowType(), $statementResult->getThrowPoints()) as [$className, $throwPointNode]) { $errors[] = RuleErrorBuilder::message(sprintf('Function %s() throws checked exception %s but it\'s missing from the PHPDoc @throws tag.', $functionReflection->getName(), $className))->line($throwPointNode->getStartLine())->identifier('missingType.checkedException')->build(); } return $errors; } } */ final class ThrowExprTypeRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Expr\Throw_::class; } public function processNode(Node $node, Scope $scope) : array { $throwableType = new ObjectType(Throwable::class); $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->expr, 'Throwing object of an unknown class %s.', static function (Type $type) use($throwableType) : bool { return $throwableType->isSuperTypeOf($type)->yes(); }); $foundType = $typeResult->getType(); if ($foundType instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } $isSuperType = $throwableType->isSuperTypeOf($foundType); if ($isSuperType->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Invalid type %s to throw.', $foundType->describe(VerbosityLevel::typeOnly())))->identifier('throw.notThrowable')->build()]; } } */ final class NoncapturingCatchRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return Node\Stmt\Catch_::class; } /** * @param Node\Stmt\Catch_ $node */ public function processNode(Node $node, Scope $scope) : array { if ($this->phpVersion->supportsNoncapturingCatches()) { return []; } if ($node->var !== null) { return []; } return [RuleErrorBuilder::message('Non-capturing catch is supported only on PHP 8.0 and later.')->nonIgnorable()->identifier('catch.nonCapturingNotSupported')->build()]; } } */ final class TooWideFunctionThrowTypeRule implements Rule { /** * @var TooWideThrowTypeCheck */ private $check; public function __construct(\PHPStan\Rules\Exceptions\TooWideThrowTypeCheck $check) { $this->check = $check; } public function getNodeType() : string { return FunctionReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $statementResult = $node->getStatementResult(); $functionReflection = $node->getFunctionReflection(); $throwType = $functionReflection->getThrowType(); if ($throwType === null) { return []; } $errors = []; foreach ($this->check->check($throwType, $statementResult->getThrowPoints()) as $throwClass) { $errors[] = RuleErrorBuilder::message(sprintf('Function %s() has %s in PHPDoc @throws tag but it\'s not thrown.', $functionReflection->getName(), $throwClass))->identifier('throws.unusedType')->build(); } return $errors; } } */ final class CatchWithUnthrownExceptionRule implements Rule { /** * @var ExceptionTypeResolver */ private $exceptionTypeResolver; /** * @var bool */ private $reportUncheckedExceptionDeadCatch; public function __construct(\PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver, bool $reportUncheckedExceptionDeadCatch) { $this->exceptionTypeResolver = $exceptionTypeResolver; $this->reportUncheckedExceptionDeadCatch = $reportUncheckedExceptionDeadCatch; } public function getNodeType() : string { return CatchWithUnthrownExceptionNode::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->getCaughtType() instanceof NeverType) { return [RuleErrorBuilder::message(sprintf('Dead catch - %s is already caught above.', $node->getOriginalCaughtType()->describe(VerbosityLevel::typeOnly())))->line($node->getStartLine())->identifier('catch.alreadyCaught')->build()]; } if (!$this->reportUncheckedExceptionDeadCatch) { $isCheckedException = \false; foreach ($node->getCaughtType()->getObjectClassNames() as $objectClassName) { if ($this->exceptionTypeResolver->isCheckedException($objectClassName, $scope)) { $isCheckedException = \true; break; } } if (!$isCheckedException) { return []; } } return [RuleErrorBuilder::message(sprintf('Dead catch - %s is never thrown in the try block.', $node->getCaughtType()->describe(VerbosityLevel::typeOnly())))->line($node->getStartLine())->identifier('catch.neverThrown')->build()]; } } */ final class OverwrittenExitPointByFinallyRule implements Rule { public function getNodeType() : string { return FinallyExitPointsNode::class; } public function processNode(Node $node, Scope $scope) : array { if (count($node->getTryCatchExitPoints()) === 0) { return []; } $errors = []; foreach ($node->getTryCatchExitPoints() as $exitPoint) { $errors[] = RuleErrorBuilder::message(sprintf('This %s is overwritten by a different one in the finally block below.', $this->describeExitPoint($exitPoint->getStatement())))->line($exitPoint->getStatement()->getStartLine())->identifier('finally.exitPoint')->build(); } foreach ($node->getFinallyExitPoints() as $exitPoint) { $errors[] = RuleErrorBuilder::message(sprintf('The overwriting %s is on this line.', $this->describeExitPoint($exitPoint->getStatement())))->line($exitPoint->getStatement()->getStartLine())->identifier('finally.exitPoint')->build(); } return $errors; } private function describeExitPoint(Node\Stmt $stmt) : string { if ($stmt instanceof Node\Stmt\Return_) { return 'return'; } if ($stmt instanceof Node\Stmt\Throw_) { return 'throw'; } if ($stmt instanceof Node\Stmt\Continue_) { return 'continue'; } if ($stmt instanceof Node\Stmt\Break_) { return 'break'; } return 'exit point'; } } */ final class ThrowsVoidFunctionWithExplicitThrowPointRule implements Rule { /** * @var ExceptionTypeResolver */ private $exceptionTypeResolver; /** * @var bool */ private $missingCheckedExceptionInThrows; public function __construct(\PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver, bool $missingCheckedExceptionInThrows) { $this->exceptionTypeResolver = $exceptionTypeResolver; $this->missingCheckedExceptionInThrows = $missingCheckedExceptionInThrows; } public function getNodeType() : string { return FunctionReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $statementResult = $node->getStatementResult(); $functionReflection = $node->getFunctionReflection(); if ($functionReflection->getThrowType() === null || !$functionReflection->getThrowType()->isVoid()->yes()) { return []; } $errors = []; foreach ($statementResult->getThrowPoints() as $throwPoint) { if (!$throwPoint->isExplicit()) { continue; } foreach (TypeUtils::flattenTypes($throwPoint->getType()) as $throwPointType) { $isCheckedException = TrinaryLogic::createFromBoolean($this->missingCheckedExceptionInThrows)->lazyAnd($throwPointType->getObjectClassNames(), function (string $objectClassName) use($throwPoint) { return TrinaryLogic::createFromBoolean($this->exceptionTypeResolver->isCheckedException($objectClassName, $throwPoint->getScope())); }); if ($isCheckedException->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Function %s() throws exception %s but the PHPDoc contains @throws void.', $functionReflection->getName(), $throwPointType->describe(VerbosityLevel::typeOnly())))->line($throwPoint->getNode()->getStartLine())->identifier('throws.void')->build(); } } return $errors; } } */ final class ThrowsVoidMethodWithExplicitThrowPointRule implements Rule { /** * @var ExceptionTypeResolver */ private $exceptionTypeResolver; /** * @var bool */ private $missingCheckedExceptionInThrows; public function __construct(\PHPStan\Rules\Exceptions\ExceptionTypeResolver $exceptionTypeResolver, bool $missingCheckedExceptionInThrows) { $this->exceptionTypeResolver = $exceptionTypeResolver; $this->missingCheckedExceptionInThrows = $missingCheckedExceptionInThrows; } public function getNodeType() : string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $statementResult = $node->getStatementResult(); $methodReflection = $node->getMethodReflection(); if ($methodReflection->getThrowType() === null || !$methodReflection->getThrowType()->isVoid()->yes()) { return []; } $errors = []; foreach ($statementResult->getThrowPoints() as $throwPoint) { if (!$throwPoint->isExplicit()) { continue; } foreach (TypeUtils::flattenTypes($throwPoint->getType()) as $throwPointType) { $isCheckedException = TrinaryLogic::createFromBoolean($this->missingCheckedExceptionInThrows)->lazyAnd($throwPointType->getObjectClassNames(), function (string $objectClassName) use($throwPoint) { return TrinaryLogic::createFromBoolean($this->exceptionTypeResolver->isCheckedException($objectClassName, $throwPoint->getScope())); }); if ($isCheckedException->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Method %s::%s() throws exception %s but the PHPDoc contains @throws void.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $throwPointType->describe(VerbosityLevel::typeOnly())))->line($throwPoint->getNode()->getStartLine())->identifier('throws.void')->build(); } } return $errors; } } */ final class TooWideMethodThrowTypeRule implements Rule { /** * @var FileTypeMapper */ private $fileTypeMapper; /** * @var TooWideThrowTypeCheck */ private $check; public function __construct(FileTypeMapper $fileTypeMapper, \PHPStan\Rules\Exceptions\TooWideThrowTypeCheck $check) { $this->fileTypeMapper = $fileTypeMapper; $this->check = $check; } public function getNodeType() : string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $docComment = $node->getDocComment(); if ($docComment === null) { return []; } $statementResult = $node->getStatementResult(); $methodReflection = $node->getMethodReflection(); $classReflection = $node->getClassReflection(); $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $classReflection->getName(), $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $methodReflection->getName(), $docComment->getText()); if ($resolvedPhpDoc->getThrowsTag() === null) { return []; } $throwType = $resolvedPhpDoc->getThrowsTag()->getType(); $errors = []; foreach ($this->check->check($throwType, $statementResult->getThrowPoints()) as $throwClass) { $errors[] = RuleErrorBuilder::message(sprintf('Method %s::%s() has %s in PHPDoc @throws tag but it\'s not thrown.', $methodReflection->getDeclaringClass()->getDisplayName(), $methodReflection->getName(), $throwClass))->identifier('throws.unusedType')->build(); } return $errors; } } */ final class RequireFileExistsRule implements Rule { /** * @var string */ private $currentWorkingDirectory; public function __construct(string $currentWorkingDirectory) { $this->currentWorkingDirectory = $currentWorkingDirectory; } public function getNodeType() : string { return Include_::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; $paths = $this->resolveFilePaths($node, $scope); foreach ($paths as $path) { if ($this->doesFileExist($path, $scope)) { continue; } $errors[] = $this->getErrorMessage($node, $path); } return $errors; } /** * We cannot use `stream_resolve_include_path` as it works based on the calling script. * This method simulates the behavior of `stream_resolve_include_path` but for the given scope. * The priority order is the following: * 1. The current working directory. * 2. The include path. * 3. The path of the script that is being executed. */ private function doesFileExist(string $path, Scope $scope) : bool { $directories = array_merge([$this->currentWorkingDirectory], explode(PATH_SEPARATOR, get_include_path()), [dirname($scope->getFile())]); foreach ($directories as $directory) { if ($this->doesFileExistForDirectory($path, $directory)) { return \true; } } return \false; } private function doesFileExistForDirectory(string $path, string $workingDirectory) : bool { $fileHelper = new FileHelper($workingDirectory); $absolutePath = $fileHelper->absolutizePath($path); return is_file($absolutePath); } private function getErrorMessage(Include_ $node, string $filePath) : IdentifierRuleError { $message = 'Path in %s() "%s" is not a file or it does not exist.'; switch ($node->type) { case Include_::TYPE_REQUIRE: $type = 'require'; $identifierType = 'require'; break; case Include_::TYPE_REQUIRE_ONCE: $type = 'require_once'; $identifierType = 'requireOnce'; break; case Include_::TYPE_INCLUDE: $type = 'include'; $identifierType = 'include'; break; case Include_::TYPE_INCLUDE_ONCE: $type = 'include_once'; $identifierType = 'includeOnce'; break; default: throw new ShouldNotHappenException('Rule should have already validated the node type.'); } $identifier = sprintf('%s.fileNotFound', $identifierType); return RuleErrorBuilder::message(sprintf($message, $type, $filePath))->identifier($identifier)->build(); } /** * @return array */ private function resolveFilePaths(Include_ $node, Scope $scope) : array { $paths = []; $type = $scope->getType($node->expr); $constantStrings = $type->getConstantStrings(); foreach ($constantStrings as $constantString) { $paths[] = $constantString->getValue(); } return $paths; } } */ final class ContinueBreakInLoopRule implements Rule { public function getNodeType() : string { return Stmt::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Stmt\Continue_ && !$node instanceof Stmt\Break_) { return []; } if (!$node->num instanceof Node\Scalar\LNumber) { $value = 1; } else { $value = $node->num->value; } $parentStmtTypes = array_reverse($node->getAttribute(ParentStmtTypesVisitor::ATTRIBUTE_NAME)); foreach ($parentStmtTypes as $parentStmtType) { if ($parentStmtType === Stmt\Case_::class) { continue; } if ($parentStmtType === Stmt\Function_::class || $parentStmtType === Stmt\ClassMethod::class || $parentStmtType === Node\Expr\Closure::class) { return [RuleErrorBuilder::message(sprintf('Keyword %s used outside of a loop or a switch statement.', $node instanceof Stmt\Continue_ ? 'continue' : 'break'))->nonIgnorable()->identifier(sprintf('%s.outOfLoop', $node instanceof Stmt\Continue_ ? 'continue' : 'break'))->build()]; } if ($parentStmtType === Stmt\For_::class || $parentStmtType === Stmt\Foreach_::class || $parentStmtType === Stmt\Do_::class || $parentStmtType === Stmt\While_::class || $parentStmtType === Stmt\Switch_::class) { $value--; } if ($value === 0) { break; } } if ($value > 0) { return [RuleErrorBuilder::message(sprintf('Keyword %s used outside of a loop or a switch statement.', $node instanceof Stmt\Continue_ ? 'continue' : 'break'))->nonIgnorable()->identifier(sprintf('%s.outOfLoop', $node instanceof Stmt\Continue_ ? 'continue' : 'break'))->build()]; } return []; } } */ final class DeclareStrictTypesRule implements Rule { /** * @readonly * @var ExprPrinter */ private $exprPrinter; public function __construct(ExprPrinter $exprPrinter) { $this->exprPrinter = $exprPrinter; } public function getNodeType() : string { return Stmt\Declare_::class; } public function processNode(Node $node, Scope $scope) : array { $declaresStrictTypes = \false; foreach ($node->declares as $declare) { if ($declare->key->name !== 'strict_types') { continue; } if (!$declare->value instanceof Node\Scalar\LNumber || !in_array($declare->value->value, [0, 1], \true)) { return [RuleErrorBuilder::message(sprintf(sprintf('Declare strict_types must have 0 or 1 as its value, %s given.', $this->exprPrinter->printExpr($declare->value))))->identifier('declareStrictTypes.value')->nonIgnorable()->build()]; } $declaresStrictTypes = \true; break; } if ($declaresStrictTypes === \false) { return []; } if (!$node->hasAttribute(DeclarePositionVisitor::ATTRIBUTE_NAME)) { return []; } $isFirstStatement = (bool) $node->getAttribute(DeclarePositionVisitor::ATTRIBUTE_NAME); if ($isFirstStatement) { return []; } return [RuleErrorBuilder::message(sprintf('Declare strict_types must be the very first statement.'))->identifier('declareStrictTypes.notFirst')->nonIgnorable()->build()]; } } */ final class NoPhpCodeRule implements Rule { public function getNodeType() : string { return FileNode::class; } public function processNode(Node $node, Scope $scope) : array { if (count($node->getNodes()) !== 1) { return []; } $html = $node->getNodes()[0]; if (!$html instanceof Node\Stmt\InlineHTML) { return []; } return [RuleErrorBuilder::message('The example does not contain any PHP code. Did you forget the opening identifier('phpstanPlayground.noPhp')->build()]; } } */ final class NotAnalysedTraitRule implements Rule { public function getNodeType() : string { return CollectedDataNode::class; } public function processNode(Node $node, Scope $scope) : array { $traitDeclarationData = $node->get(TraitDeclarationCollector::class); $traitUseData = $node->get(TraitUseCollector::class); $declaredTraits = []; foreach ($traitDeclarationData as $file => $declaration) { foreach ($declaration as [$name, $line]) { $declaredTraits[strtolower($name)] = [$file, $name, $line]; } } foreach ($traitUseData as $usedNamesData) { foreach ($usedNamesData as $usedNames) { foreach ($usedNames as $usedName) { unset($declaredTraits[strtolower($usedName)]); } } } $errors = []; foreach ($declaredTraits as [$file, $name, $line]) { $errors[] = RuleErrorBuilder::message(sprintf('Trait %s is used zero times and is not analysed.', $name))->identifier('phpstanPlayground.traitUnused')->file($file)->line($line)->tip('See: https://phpstan.org/blog/how-phpstan-analyses-traits')->build(); } return $errors; } } */ final class FunctionNeverRule implements Rule { /** * @var NeverRuleHelper */ private $helper; public function __construct(\PHPStan\Rules\Playground\NeverRuleHelper $helper) { $this->helper = $helper; } public function getNodeType() : string { return FunctionReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { if (count($node->getReturnStatements()) > 0) { return []; } $function = $node->getFunctionReflection(); $returnType = $function->getReturnType(); $helperResult = $this->helper->shouldReturnNever($node, $returnType); if ($helperResult === \false) { return []; } return [RuleErrorBuilder::message(sprintf('Function %s() always %s, it should have return type "never".', $function->getName(), count($helperResult) === 0 ? 'throws an exception' : 'terminates script execution'))->identifier('phpstanPlayground.never')->build()]; } } |false */ public function shouldReturnNever(ReturnStatementsNode $node, Type $returnType) { if ($returnType instanceof NeverType && $returnType->isExplicit()) { return \false; } if ($node->isGenerator()) { return \false; } $other = []; foreach ($node->getExecutionEnds() as $executionEnd) { if ($executionEnd->getStatementResult()->isAlwaysTerminating()) { if (!$executionEnd->getNode() instanceof Node\Stmt\Throw_) { $other[] = $executionEnd->getNode(); } continue; } return \false; } return $other; } } */ final class MethodNeverRule implements Rule { /** * @var NeverRuleHelper */ private $helper; public function __construct(\PHPStan\Rules\Playground\NeverRuleHelper $helper) { $this->helper = $helper; } public function getNodeType() : string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { if (count($node->getReturnStatements()) > 0) { return []; } $method = $node->getMethodReflection(); $returnType = $method->getReturnType(); $helperResult = $this->helper->shouldReturnNever($node, $returnType); if ($helperResult === \false) { return []; } return [RuleErrorBuilder::message(sprintf('Method %s::%s() always %s, it should have return type "never".', $method->getDeclaringClass()->getDisplayName(), $method->getName(), count($helperResult) === 0 ? 'throws an exception' : 'terminates script execution'))->identifier('phpstanPlayground.never')->build()]; } } ruleLevelHelper = $ruleLevelHelper; } /** * @return list */ public function checkReturnType(Scope $scope, Type $returnType, ?Expr $returnValue, Node $returnNode, string $emptyReturnStatementMessage, string $voidMessage, string $typeMismatchMessage, string $neverMessage, bool $isGenerator) : array { $returnType = TypeUtils::resolveLateResolvableTypes($returnType); if ($returnType instanceof NeverType && $returnType->isExplicit()) { return [\PHPStan\Rules\RuleErrorBuilder::message($neverMessage)->line($returnNode->getStartLine())->identifier('return.never')->build()]; } if ($isGenerator) { $returnType = $returnType->getTemplateType(Generator::class, 'TReturn'); if ($returnType instanceof ErrorType) { return []; } } $isVoidSuperType = $returnType->isVoid(); $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType, null); if ($returnValue === null) { if (!$isVoidSuperType->no()) { return []; } return [\PHPStan\Rules\RuleErrorBuilder::message(sprintf($emptyReturnStatementMessage, $returnType->describe($verbosityLevel)))->line($returnNode->getStartLine())->identifier('return.empty')->build()]; } if ($returnNode instanceof Expr\Yield_ || $returnNode instanceof Expr\YieldFrom) { return []; } $returnValueType = $scope->getType($returnValue); $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType, $returnValueType); if ($isVoidSuperType->yes()) { return [\PHPStan\Rules\RuleErrorBuilder::message(sprintf($voidMessage, $returnValueType->describe($verbosityLevel)))->line($returnNode->getStartLine())->identifier('return.void')->build()]; } $accepts = $this->ruleLevelHelper->acceptsWithReason($returnType, $returnValueType, $scope->isDeclareStrictTypes()); if (!$accepts->result) { return [\PHPStan\Rules\RuleErrorBuilder::message(sprintf($typeMismatchMessage, $returnType->describe($verbosityLevel), $returnValueType->describe($verbosityLevel)))->line($returnNode->getStartLine())->identifier('return.type')->acceptsReasonsTip($accepts->reasons)->build()]; } return []; } } reflectionProvider = $reflectionProvider; $this->checkInternalClassCaseSensitivity = $checkInternalClassCaseSensitivity; } /** * @param ClassNameNodePair[] $pairs * @return list */ public function checkClassNames(array $pairs) : array { $errors = []; foreach ($pairs as $pair) { $className = $pair->getClassName(); if (!$this->reflectionProvider->hasClass($className)) { continue; } $classReflection = $this->reflectionProvider->getClass($className); if (!$this->checkInternalClassCaseSensitivity && $classReflection->isBuiltin()) { continue; // skip built-in classes } $realClassName = $classReflection->getName(); if (strtolower($realClassName) !== strtolower($className)) { continue; // skip class alias } if ($realClassName === $className) { continue; } $typeName = $classReflection->getClassTypeDescription(); $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('%s %s referenced with incorrect case: %s.', $typeName, $realClassName, $className))->identifier(sprintf('%s.nameCase', strtolower($typeName)))->line($pair->getNode()->getStartLine())->build(); } return $errors; } } '_PHPStan_', 'Rector' => 'RectorPrefix', 'PHP-Scoper' => '_PhpScoper', 'PHPUnit' => 'PHPUnitPHAR', 'Box' => '_HumbugBox']; public function __construct(Container $container) { $this->container = $container; } /** * @param ClassNameNodePair[] $pairs * @return list */ public function checkClassNames(array $pairs) : array { $extensions = $this->container->getServicesByTag(ForbiddenClassNameExtension::EXTENSION_TAG); $classPrefixes = array_merge(self::INTERNAL_CLASS_PREFIXES, ...array_map(static function (ForbiddenClassNameExtension $extension) : array { return $extension->getClassPrefixes(); }, $extensions)); $errors = []; foreach ($pairs as $pair) { $className = $pair->getClassName(); $projectName = null; $withoutPrefixClassName = null; foreach ($classPrefixes as $project => $prefix) { if (!str_starts_with($className, $prefix)) { continue; } $projectName = $project; $withoutPrefixClassName = substr($className, strlen($prefix)); if (strpos($withoutPrefixClassName, '\\') === \false) { continue; } $withoutPrefixClassName = substr($withoutPrefixClassName, strpos($withoutPrefixClassName, '\\')); } if ($projectName === null) { continue; } $error = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Referencing prefixed %s class: %s.', $projectName, $className))->line($pair->getNode()->getLine())->identifier('class.prefixed')->nonIgnorable(); if ($withoutPrefixClassName !== null) { $error->tip(sprintf('This is most likely unintentional. Did you mean to type %s?', $withoutPrefixClassName)); } $errors[] = $error->build(); } return $errors; } } ruleLevelHelper = $ruleLevelHelper; $this->reportMaybes = $reportMaybes; $this->bleedingEdge = $bleedingEdge; $this->reportPossiblyNonexistentGeneralArrayOffset = $reportPossiblyNonexistentGeneralArrayOffset; $this->reportPossiblyNonexistentConstantArrayOffset = $reportPossiblyNonexistentConstantArrayOffset; } /** * @return list */ public function check(Scope $scope, Expr $var, string $unknownClassPattern, Type $dimType) : array { $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $var), $unknownClassPattern, static function (Type $type) use($dimType) : bool { return $type->hasOffsetValueType($dimType)->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } if ($scope->isInExpressionAssign($var) || $scope->isUndefinedExpressionAllowed($var)) { return []; } if ($type->hasOffsetValueType($dimType)->no()) { return [RuleErrorBuilder::message(sprintf('Offset %s does not exist on %s.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value())))->identifier('offsetAccess.notFound')->build()]; } if ($this->reportMaybes) { $report = \false; if ($type instanceof BenevolentUnionType) { $flattenedTypes = [$type]; } else { $flattenedTypes = TypeUtils::flattenTypes($type); } foreach ($flattenedTypes as $innerType) { if ($this->reportPossiblyNonexistentGeneralArrayOffset && $innerType->isArray()->yes() && !$innerType->isConstantArray()->yes() && !$innerType->hasOffsetValueType($dimType)->yes()) { $report = \true; break; } if ($this->reportPossiblyNonexistentConstantArrayOffset && $innerType->isConstantArray()->yes() && !$innerType->hasOffsetValueType($dimType)->yes()) { $report = \true; break; } if ($dimType instanceof UnionType) { if ($innerType->hasOffsetValueType($dimType)->no()) { $report = \true; break; } continue; } foreach (TypeUtils::flattenTypes($dimType) as $innerDimType) { if ($innerType->hasOffsetValueType($innerDimType)->no()) { $report = \true; break 2; } } } if ($report) { if ($this->bleedingEdge || $this->reportPossiblyNonexistentGeneralArrayOffset || $this->reportPossiblyNonexistentConstantArrayOffset) { return [RuleErrorBuilder::message(sprintf('Offset %s might not exist on %s.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value())))->identifier('offsetAccess.notFound')->build()]; } return [RuleErrorBuilder::message(sprintf('Offset %s does not exist on %s.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value())))->identifier('offsetAccess.notFound')->build()]; } } return []; } } */ final class InvalidKeyInArrayItemRule implements Rule { /** * @var bool */ private $reportMaybes; public function __construct(bool $reportMaybes) { $this->reportMaybes = $reportMaybes; } public function getNodeType() : string { return Node\Expr\ArrayItem::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->key === null) { return []; } $dimensionType = $scope->getType($node->key); $isSuperType = \PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType()->isSuperTypeOf($dimensionType); if ($isSuperType->no()) { return [RuleErrorBuilder::message(sprintf('Invalid array key type %s.', $dimensionType->describe(VerbosityLevel::typeOnly())))->identifier('array.invalidKey')->build()]; } elseif ($this->reportMaybes && $isSuperType->maybe() && !$dimensionType instanceof MixedType) { return [RuleErrorBuilder::message(sprintf('Possibly invalid array key type %s.', $dimensionType->describe(VerbosityLevel::typeOnly())))->identifier('array.invalidKey')->build()]; } return []; } } */ final class EmptyArrayItemRule implements Rule { public function getNodeType() : string { return LiteralArrayNode::class; } public function processNode(Node $node, Scope $scope) : array { foreach ($node->getItemNodes() as $itemNode) { $item = $itemNode->getArrayItem(); if ($item !== null) { continue; } return [RuleErrorBuilder::message('Literal array contains empty item.')->nonIgnorable()->identifier('array.emptyItem')->build()]; } return []; } } */ final class DuplicateKeysInLiteralArraysRule implements Rule { /** * @var ExprPrinter */ private $exprPrinter; public function __construct(ExprPrinter $exprPrinter) { $this->exprPrinter = $exprPrinter; } public function getNodeType() : string { return LiteralArrayNode::class; } public function processNode(Node $node, Scope $scope) : array { $values = []; $duplicateKeys = []; $printedValues = []; $valueLines = []; /** * @var int|false|null $autoGeneratedIndex * - An int value represent the biggest integer used as array key. * When no key is provided this value + 1 will be used. * - Null is used as initializer instead of 0 to avoid issue with negative keys. * - False means a non-scalar value was encountered and we cannot be sure of the next keys. */ $autoGeneratedIndex = null; foreach ($node->getItemNodes() as $itemNode) { $item = $itemNode->getArrayItem(); if ($item === null) { $autoGeneratedIndex = \false; continue; } $key = $item->key; if ($key === null) { if ($autoGeneratedIndex === \false) { continue; } if ($autoGeneratedIndex === null) { $autoGeneratedIndex = 0; $keyType = new ConstantIntegerType(0); } else { $keyType = new ConstantIntegerType(++$autoGeneratedIndex); } } else { $keyType = $itemNode->getScope()->getType($key); $arrayKeyValue = $keyType->toArrayKey(); if ($arrayKeyValue instanceof ConstantIntegerType) { $autoGeneratedIndex = $autoGeneratedIndex === null ? $arrayKeyValue->getValue() : max($autoGeneratedIndex, $arrayKeyValue->getValue()); } } if (!$keyType instanceof ConstantScalarType) { $autoGeneratedIndex = \false; continue; } $value = $keyType->getValue(); $printedValue = $key !== null ? $this->exprPrinter->printExpr($key) : $value; $printedValues[$value][] = $printedValue; if (!isset($valueLines[$value])) { $valueLines[$value] = $item->getStartLine(); } $previousCount = count($values); $values[$value] = $printedValue; if ($previousCount !== count($values)) { continue; } $duplicateKeys[$value] = \true; } $messages = []; foreach (array_keys($duplicateKeys) as $value) { $messages[] = RuleErrorBuilder::message(sprintf('Array has %d %s with value %s (%s).', count($printedValues[$value]), count($printedValues[$value]) === 1 ? 'duplicate key' : 'duplicate keys', var_export($value, \true), implode(', ', $printedValues[$value])))->identifier('array.duplicateKey')->line($valueLines[$value])->build(); } return $messages; } } */ final class OffsetAccessAssignOpRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Expr\AssignOp::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->var instanceof ArrayDimFetch) { return []; } $arrayDimFetch = $node->var; $potentialDimType = null; if ($arrayDimFetch->dim !== null) { $potentialDimType = $scope->getType($arrayDimFetch->dim); } $varTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $arrayDimFetch->var, '', static function (Type $varType) use($potentialDimType) : bool { $arrayDimType = $varType->setOffsetValueType($potentialDimType, new MixedType()); return !$arrayDimType instanceof ErrorType; }); $varType = $varTypeResult->getType(); if ($arrayDimFetch->dim !== null) { $dimTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $arrayDimFetch->dim, '', static function (Type $dimType) use($varType) : bool { $arrayDimType = $varType->setOffsetValueType($dimType, new MixedType()); return !$arrayDimType instanceof ErrorType; }); $dimType = $dimTypeResult->getType(); if ($varType->hasOffsetValueType($dimType)->no()) { return []; } } else { $dimType = $potentialDimType; } $resultType = $varType->setOffsetValueType($dimType, new MixedType()); if (!$resultType instanceof ErrorType) { return []; } if ($dimType === null) { return [RuleErrorBuilder::message(sprintf('Cannot assign new offset to %s.', $varType->describe(VerbosityLevel::typeOnly())))->identifier('offsetAssign.dimType')->build()]; } return [RuleErrorBuilder::message(sprintf('Cannot assign offset %s to %s.', $dimType->describe(VerbosityLevel::value()), $varType->describe(VerbosityLevel::typeOnly())))->identifier('offsetAssign.dimType')->build()]; } } */ final class DeadForeachRule implements Rule { public function getNodeType() : string { return Node\Stmt\Foreach_::class; } public function processNode(Node $node, Scope $scope) : array { $iterableType = $scope->getType($node->expr); if ($iterableType->isIterable()->no()) { return []; } if (!$iterableType->isIterableAtLeastOnce()->no()) { return []; } return [RuleErrorBuilder::message('Empty array passed to foreach.')->identifier('foreach.emptyArray')->build()]; } } */ final class ArrayDestructuringRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var NonexistentOffsetInArrayDimFetchCheck */ private $nonexistentOffsetInArrayDimFetchCheck; public function __construct(RuleLevelHelper $ruleLevelHelper, \PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck $nonexistentOffsetInArrayDimFetchCheck) { $this->ruleLevelHelper = $ruleLevelHelper; $this->nonexistentOffsetInArrayDimFetchCheck = $nonexistentOffsetInArrayDimFetchCheck; } public function getNodeType() : string { return Assign::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->var instanceof Node\Expr\List_ && !$node->var instanceof Node\Expr\Array_) { return []; } return $this->getErrors($scope, $node->var, $node->expr); } /** * @param Node\Expr\List_|Node\Expr\Array_ $var * @return list */ private function getErrors(Scope $scope, Expr $var, Expr $expr) : array { $exprTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $expr, '', static function (Type $varType) : bool { return $varType->isArray()->yes() || (new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->yes(); }); $exprType = $exprTypeResult->getType(); if ($exprType instanceof ErrorType) { return []; } if (!$exprType->isArray()->yes() && !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($exprType)->yes()) { return [RuleErrorBuilder::message(sprintf('Cannot use array destructuring on %s.', $exprType->describe(VerbosityLevel::typeOnly())))->identifier('offsetAccess.nonArray')->build()]; } $errors = []; $i = 0; foreach ($var->items as $item) { if ($item === null) { $i++; continue; } $keyExpr = null; if ($item->key === null) { $keyType = new ConstantIntegerType($i); $keyExpr = new Node\Scalar\LNumber($i); } else { $keyType = $scope->getType($item->key); $keyExpr = new TypeExpr($keyType); } $itemErrors = $this->nonexistentOffsetInArrayDimFetchCheck->check($scope, $expr, '', $keyType); $errors = array_merge($errors, $itemErrors); if (!$item->value instanceof Node\Expr\List_ && !$item->value instanceof Node\Expr\Array_) { $i++; continue; } $errors = array_merge($errors, $this->getErrors($scope, $item->value, new Expr\ArrayDimFetch($expr, $keyExpr))); } return $errors; } } */ final class IterableInForeachRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return InForeachNode::class; } public function processNode(Node $node, Scope $scope) : array { $originalNode = $node->getOriginalNode(); $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $originalNode->expr, 'Iterating over an object of an unknown class %s.', static function (Type $type) : bool { return $type->isIterable()->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } if ($type->isIterable()->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Argument of an invalid type %s supplied for foreach, only iterables are supported.', $type->describe(VerbosityLevel::typeOnly())))->identifier('foreach.nonIterable')->line($originalNode->expr->getStartLine())->build()]; } } */ final class NonexistentOffsetInArrayDimFetchRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var NonexistentOffsetInArrayDimFetchCheck */ private $nonexistentOffsetInArrayDimFetchCheck; /** * @var bool */ private $reportMaybes; public function __construct(RuleLevelHelper $ruleLevelHelper, \PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck $nonexistentOffsetInArrayDimFetchCheck, bool $reportMaybes) { $this->ruleLevelHelper = $ruleLevelHelper; $this->nonexistentOffsetInArrayDimFetchCheck = $nonexistentOffsetInArrayDimFetchCheck; $this->reportMaybes = $reportMaybes; } public function getNodeType() : string { return Node\Expr\ArrayDimFetch::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->dim !== null) { $dimType = $scope->getType($node->dim); $unknownClassPattern = sprintf('Access to offset %s on an unknown class %%s.', SprintfHelper::escapeFormatString($dimType->describe(VerbosityLevel::value()))); } else { $dimType = null; $unknownClassPattern = 'Access to an offset on an unknown class %s.'; } $isOffsetAccessibleTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $node->var), $unknownClassPattern, static function (Type $type) : bool { return $type->isOffsetAccessible()->yes(); }); $isOffsetAccessibleType = $isOffsetAccessibleTypeResult->getType(); if ($isOffsetAccessibleType instanceof ErrorType) { return $isOffsetAccessibleTypeResult->getUnknownClassErrors(); } if ($scope->hasExpressionType($node)->yes()) { return []; } $isOffsetAccessible = $isOffsetAccessibleType->isOffsetAccessible(); if ($scope->isInExpressionAssign($node) && $isOffsetAccessible->yes()) { return []; } if ($scope->isUndefinedExpressionAllowed($node) && $isOffsetAccessibleType->isOffsetAccessLegal()->yes()) { return []; } if (!$isOffsetAccessible->yes()) { if ($isOffsetAccessible->no() || $this->reportMaybes) { if ($dimType !== null) { return [RuleErrorBuilder::message(sprintf('Cannot access offset %s on %s.', $dimType->describe(VerbosityLevel::value()), $isOffsetAccessibleType->describe(VerbosityLevel::value())))->identifier('offsetAccess.nonOffsetAccessible')->build()]; } return [RuleErrorBuilder::message(sprintf('Cannot access an offset on %s.', $isOffsetAccessibleType->describe(VerbosityLevel::typeOnly())))->identifier('offsetAccess.nonOffsetAccessible')->build()]; } return []; } if ($dimType === null) { return []; } return $this->nonexistentOffsetInArrayDimFetchCheck->check($scope, $node->var, $unknownClassPattern, $dimType); } } isArray()->yes() || $varType->isIterableAtLeastOnce()->no()) { return null; } $varIterableKeyType = $varType->getIterableKeyType(); if ($varIterableKeyType->isConstantScalarValue()->yes()) { $narrowedKey = TypeCombinator::union($varIterableKeyType, TypeCombinator::remove($varIterableKeyType->toString(), new ConstantStringType(''))); if (!$varType->hasOffsetValueType(new ConstantIntegerType(0))->no()) { $narrowedKey = TypeCombinator::union($narrowedKey, new ConstantBooleanType(\false)); } if (!$varType->hasOffsetValueType(new ConstantIntegerType(1))->no()) { $narrowedKey = TypeCombinator::union($narrowedKey, new ConstantBooleanType(\true)); } if (!$varType->hasOffsetValueType(new ConstantStringType(''))->no()) { $narrowedKey = TypeCombinator::addNull($narrowedKey); } if (!$varIterableKeyType->isNumericString()->no() || !$varIterableKeyType->isInteger()->no()) { $narrowedKey = TypeCombinator::union($narrowedKey, new FloatType()); } return $narrowedKey; } elseif ($varIterableKeyType->isInteger()->yes() && $keyType->isString()->yes()) { return TypeCombinator::intersect($varIterableKeyType->toString(), $keyType); } return new MixedType(\false, new UnionType([new ArrayType(new MixedType(), new MixedType()), new ObjectWithoutClassType(), new ResourceType()])); } } */ final class UnpackIterableInArrayRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return LiteralArrayNode::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; foreach ($node->getItemNodes() as $itemNode) { $item = $itemNode->getArrayItem(); if ($item === null) { continue; } if (!$item->unpack) { continue; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $item->value, '', static function (Type $type) : bool { return $type->isIterable()->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { continue; } if ($type->isIterable()->yes()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Only iterables can be unpacked, %s given.', $type->describe(VerbosityLevel::typeOnly())))->identifier('arrayUnpacking.nonIterable')->line($item->getStartLine())->build(); } return $errors; } } */ final class AppendedArrayKeyTypeRule implements Rule { /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; /** * @var bool */ private $checkUnionTypes; public function __construct(PropertyReflectionFinder $propertyReflectionFinder, bool $checkUnionTypes) { $this->propertyReflectionFinder = $propertyReflectionFinder; $this->checkUnionTypes = $checkUnionTypes; } public function getNodeType() : string { return Assign::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->var instanceof ArrayDimFetch) { return []; } if (!$node->var->var instanceof Node\Expr\PropertyFetch && !$node->var->var instanceof Node\Expr\StaticPropertyFetch) { return []; } $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($node->var->var, $scope); if ($propertyReflection === null) { return []; } $arrayType = $propertyReflection->getReadableType(); if (!$arrayType->isArray()->yes()) { return []; } if ($node->var->dim !== null) { $dimensionType = $scope->getType($node->var->dim); $isValidKey = \PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType()->isSuperTypeOf($dimensionType); if (!$isValidKey->yes()) { // already handled by InvalidKeyInArrayDimFetchRule return []; } $keyType = $dimensionType->toArrayKey(); if (!$this->checkUnionTypes && $keyType instanceof UnionType) { return []; } } else { $keyType = new IntegerType(); } if (!$arrayType->getIterableKeyType()->isSuperTypeOf($keyType)->yes()) { $verbosity = VerbosityLevel::getRecommendedLevelByType($arrayType->getIterableKeyType(), $keyType); return [RuleErrorBuilder::message(sprintf('Array (%s) does not accept key %s.', $arrayType->describe($verbosity), $keyType->describe(VerbosityLevel::value())))->identifier('array.keyType')->build()]; } return []; } } */ final class ArrayUnpackingRule implements Rule { /** * @var PhpVersion */ private $phpVersion; /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(PhpVersion $phpVersion, RuleLevelHelper $ruleLevelHelper) { $this->phpVersion = $phpVersion; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return ArrayItem::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->unpack === \false || $this->phpVersion->supportsArrayUnpackingWithStringKeys()) { return []; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, new GetIterableKeyTypeExpr($node->value), '', static function (Type $type) : bool { return $type->isString()->no(); }); $keyType = $typeResult->getType(); if ($keyType instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } $isString = $keyType->isString(); if ($isString->no()) { return []; } return [RuleErrorBuilder::message(sprintf('Array unpacking cannot be used on an array with %sstring keys: %s', $isString->yes() ? '' : 'potential ', $scope->getType($node->value)->describe(VerbosityLevel::value())))->identifier('arrayUnpacking.stringOffset')->build()]; } } */ final class AppendedArrayItemTypeRule implements Rule { /** * @var PropertyReflectionFinder */ private $propertyReflectionFinder; /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(PropertyReflectionFinder $propertyReflectionFinder, RuleLevelHelper $ruleLevelHelper) { $this->propertyReflectionFinder = $propertyReflectionFinder; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Expr::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Assign && !$node instanceof AssignOp && !$node instanceof AssignRef) { return []; } if (!$node->var instanceof ArrayDimFetch) { return []; } if (!$node->var->var instanceof Node\Expr\PropertyFetch && !$node->var->var instanceof Node\Expr\StaticPropertyFetch) { return []; } $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($node->var->var, $scope); if ($propertyReflection === null) { return []; } $assignedToType = $propertyReflection->getWritableType(); if (!$assignedToType->isArray()->yes()) { return []; } if ($node instanceof Assign || $node instanceof AssignRef) { $assignedValueType = $scope->getType($node->expr); } else { $assignedValueType = $scope->getType($node); } $itemType = $assignedToType->getIterableValueType(); $accepts = $this->ruleLevelHelper->acceptsWithReason($itemType, $assignedValueType, $scope->isDeclareStrictTypes()); if (!$accepts->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($itemType, $assignedValueType); return [RuleErrorBuilder::message(sprintf('Array (%s) does not accept %s.', $assignedToType->describe($verbosityLevel), $assignedValueType->describe($verbosityLevel)))->acceptsReasonsTip($accepts->reasons)->identifier('array.valueType')->build()]; } return []; } } */ final class OffsetAccessValueAssignmentRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Expr::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Assign && !$node instanceof AssignOp && !$node instanceof Expr\AssignRef) { return []; } if (!$node->var instanceof Expr\ArrayDimFetch) { return []; } $arrayDimFetch = $node->var; $varType = $scope->getType($arrayDimFetch->var); if ($varType->isObject()->no()) { return []; } if ($node instanceof Assign || $node instanceof Expr\AssignRef) { $assignedValueType = $scope->getType($node->expr); } else { $assignedValueType = $scope->getType($node); } $arrayTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $arrayDimFetch->var, '', static function (Type $varType) use($assignedValueType) : bool { $result = $varType->setOffsetValueType(new MixedType(), $assignedValueType); return !$result instanceof ErrorType; }); $arrayType = $arrayTypeResult->getType(); if ($arrayType instanceof ErrorType) { return []; } $isOffsetAccessible = $arrayType->isOffsetAccessible(); if (!$isOffsetAccessible->yes()) { return []; } $resultType = $arrayType->setOffsetValueType(new MixedType(), $assignedValueType); if (!$resultType instanceof ErrorType) { return []; } $originalArrayType = $scope->getType($arrayDimFetch->var); return [RuleErrorBuilder::message(sprintf('%s does not accept %s.', $originalArrayType->describe(VerbosityLevel::value()), $assignedValueType->describe(VerbosityLevel::typeOnly())))->identifier('offsetAssign.valueType')->build()]; } } */ final class OffsetAccessAssignmentRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Expr\ArrayDimFetch::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInExpressionAssign($node)) { return []; } $potentialDimType = null; if ($node->dim !== null) { $potentialDimType = $scope->getType($node->dim); } $varTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $node->var), '', static function (Type $varType) use($potentialDimType) : bool { $arrayDimType = $varType->setOffsetValueType($potentialDimType, new MixedType()); return !$arrayDimType instanceof ErrorType; }); $varType = $varTypeResult->getType(); if ($varType instanceof ErrorType) { return []; } if (!$varType->isOffsetAccessible()->yes()) { return []; } if ($node->dim !== null) { $dimTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->dim, '', static function (Type $dimType) use($varType) : bool { $arrayDimType = $varType->setOffsetValueType($dimType, new MixedType()); return !$arrayDimType instanceof ErrorType; }); $dimType = $dimTypeResult->getType(); } else { $dimType = $potentialDimType; } $resultType = $varType->setOffsetValueType($dimType, new MixedType()); if (!$resultType instanceof ErrorType) { return []; } if ($dimType === null) { return [RuleErrorBuilder::message(sprintf('Cannot assign new offset to %s.', $varType->describe(VerbosityLevel::typeOnly())))->identifier('offsetAssign.dimType')->build()]; } return [RuleErrorBuilder::message(sprintf('Cannot assign offset %s to %s.', $dimType->describe(VerbosityLevel::value()), $varType->describe(VerbosityLevel::typeOnly())))->identifier('offsetAssign.dimType')->build()]; } } */ final class OffsetAccessWithoutDimForReadingRule implements Rule { public function getNodeType() : string { return Node\Expr\ArrayDimFetch::class; } public function processNode(Node $node, Scope $scope) : array { if ($scope->isInExpressionAssign($node)) { return []; } if ($node->dim !== null) { return []; } return [RuleErrorBuilder::message('Cannot use [] for reading.')->identifier('offsetAccess.noDim')->nonIgnorable()->build()]; } } */ final class InvalidKeyInArrayDimFetchRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var bool */ private $reportMaybes; public function __construct(RuleLevelHelper $ruleLevelHelper, bool $reportMaybes) { $this->ruleLevelHelper = $ruleLevelHelper; $this->reportMaybes = $reportMaybes; } public function getNodeType() : string { return Node\Expr\ArrayDimFetch::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->dim === null) { return []; } $dimensionType = $scope->getType($node->dim); if ($dimensionType instanceof MixedType) { return []; } $varType = $this->ruleLevelHelper->findTypeToCheck($scope, $node->var, '', static function (Type $varType) use($dimensionType) : bool { return $varType->isArray()->no() || \PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType()->isSuperTypeOf($dimensionType)->yes(); })->getType(); if ($varType instanceof ErrorType || $varType->isArray()->no()) { return []; } $isSuperType = \PHPStan\Rules\Arrays\AllowedArrayKeysTypes::getType()->isSuperTypeOf($dimensionType); if ($isSuperType->yes() || $isSuperType->maybe() && !$this->reportMaybes) { return []; } return [RuleErrorBuilder::message(sprintf('%s array key type %s.', $isSuperType->no() ? 'Invalid' : 'Possibly invalid', $dimensionType->describe(VerbosityLevel::typeOnly())))->identifier('offsetAccess.invalidOffset')->build()]; } } */ final class NumberComparisonOperatorsConstantConditionRule implements Rule { /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(bool $treatPhpDocTypesAsCertain, bool $treatPhpDocTypesAsCertainTip) { $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return BinaryOp::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof BinaryOp\Greater && !$node instanceof BinaryOp\GreaterOrEqual && !$node instanceof BinaryOp\Smaller && !$node instanceof BinaryOp\SmallerOrEqual) { return []; } $exprType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node) : $scope->getNativeType($node); if ($exprType instanceof ConstantBooleanType) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $scope->getNativeType($node); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; switch (get_class($node)) { case BinaryOp\Greater::class: $nodeType = 'greater'; break; case BinaryOp\GreaterOrEqual::class: $nodeType = 'greaterOrEqual'; break; case BinaryOp\Smaller::class: $nodeType = 'smaller'; break; case BinaryOp\SmallerOrEqual::class: $nodeType = 'smallerOrEqual'; break; default: throw new ShouldNotHappenException(); } return [$addTip(RuleErrorBuilder::message(sprintf('Comparison operation "%s" between %s and %s is always %s.', $node->getOperatorSigil(), $scope->getType($node->left)->describe(VerbosityLevel::value()), $scope->getType($node->right)->describe(VerbosityLevel::value()), $exprType->getValue() ? 'true' : 'false')))->identifier(sprintf('%s.always%s', $nodeType, $exprType->getValue() ? 'True' : 'False'))->build()]; } return []; } } */ final class WhileLoopAlwaysTrueConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return BreaklessWhileLoopNode::class; } public function processNode(Node $node, Scope $scope) : array { foreach ($node->getExitPoints() as $exitPoint) { $statement = $exitPoint->getStatement(); if ($statement instanceof Break_) { return []; } if (!$statement instanceof Continue_) { return []; } if ($statement->num === null) { continue; } if (!$statement->num instanceof LNumber) { continue; } $value = $statement->num->value; if ($value === 1) { continue; } if ($value > 1) { return []; } } $originalNode = $node->getOriginalNode(); $exprType = $this->helper->getBooleanType($scope, $originalNode->cond); if ($exprType->isTrue()->yes()) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $originalNode) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $originalNode->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; return [$addTip(RuleErrorBuilder::message('While loop condition is always true.'))->line($originalNode->cond->getStartLine())->identifier('while.alwaysTrue')->build()]; } return []; } } */ final class TernaryOperatorConstantConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Expr\Ternary::class; } public function processNode(Node $node, Scope $scope) : array { $exprType = $this->helper->getBooleanType($scope, $node->cond); if ($exprType instanceof ConstantBooleanType) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; return [$addTip(RuleErrorBuilder::message(sprintf('Ternary operator condition is always %s.', $exprType->getValue() ? 'true' : 'false')))->identifier(sprintf('ternary.always%s', $exprType->getValue() ? 'True' : 'False'))->build()]; } return []; } } */ final class ImpossibleCheckTypeMethodCallRule implements Rule { /** * @var ImpossibleCheckTypeHelper */ private $impossibleCheckTypeHelper; /** * @var bool */ private $checkAlwaysTrueCheckTypeFunctionCall; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, bool $checkAlwaysTrueCheckTypeFunctionCall, bool $treatPhpDocTypesAsCertain, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->impossibleCheckTypeHelper = $impossibleCheckTypeHelper; $this->checkAlwaysTrueCheckTypeFunctionCall = $checkAlwaysTrueCheckTypeFunctionCall; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Expr\MethodCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } $isAlways = $this->impossibleCheckTypeHelper->findSpecifiedType($scope, $node); if ($isAlways === null) { return []; } $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $isAlways = $this->impossibleCheckTypeHelper->doNotTreatPhpDocTypesAsCertain()->findSpecifiedType($scope, $node); if ($isAlways !== null) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; if (!$isAlways) { $method = $this->getMethod($node->var, $node->name->name, $scope); return [$addTip(RuleErrorBuilder::message(sprintf('Call to method %s::%s()%s will always evaluate to false.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()))))->identifier('method.impossibleType')->build()]; } elseif ($this->checkAlwaysTrueCheckTypeFunctionCall) { $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if ($isLast === \true && !$this->reportAlwaysTrueInLastCondition) { return []; } $method = $this->getMethod($node->var, $node->name->name, $scope); $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Call to method %s::%s()%s will always evaluate to true.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs())))); if ($isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier('method.alreadyNarrowedType'); return [$errorBuilder->build()]; } return []; } private function getMethod(Expr $var, string $methodName, Scope $scope) : MethodReflection { $calledOnType = $scope->getType($var); $method = $scope->getMethodReflection($calledOnType, $methodName); if ($method === null) { throw new ShouldNotHappenException(); } return $method; } } reflectionProvider = $reflectionProvider; $this->typeSpecifier = $typeSpecifier; $this->universalObjectCratesClasses = $universalObjectCratesClasses; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->nullContextForVoidReturningFunctions = $nullContextForVoidReturningFunctions; } public function findSpecifiedType(Scope $scope, Expr $node) : ?bool { if ($node instanceof FuncCall) { if ($node->isFirstClassCallable()) { return null; } $argsCount = count($node->getArgs()); if ($node->name instanceof Node\Name) { $functionName = strtolower((string) $node->name); if ($functionName === 'assert' && $argsCount >= 1) { $arg = $node->getArgs()[0]->value; $assertValue = ($this->treatPhpDocTypesAsCertain ? $scope->getType($arg) : $scope->getNativeType($arg))->toBoolean(); if (!$assertValue instanceof ConstantBooleanType) { return null; } return $assertValue->getValue(); } if (in_array($functionName, ['class_exists', 'interface_exists', 'trait_exists', 'enum_exists'], \true)) { return null; } if (in_array($functionName, ['count', 'sizeof'], \true)) { return null; } elseif ($functionName === 'defined') { return null; } elseif ($functionName === 'array_search') { return null; } elseif ($functionName === 'in_array' && $argsCount >= 2) { $haystackArg = $node->getArgs()[1]->value; $haystackType = $this->treatPhpDocTypesAsCertain ? $scope->getType($haystackArg) : $scope->getNativeType($haystackArg); if ($haystackType instanceof MixedType) { return null; } if (!$haystackType->isArray()->yes()) { return null; } $needleArg = $node->getArgs()[0]->value; $needleType = $this->treatPhpDocTypesAsCertain ? $scope->getType($needleArg) : $scope->getNativeType($needleArg); $isStrictComparison = \false; if ($argsCount >= 3) { $strictNodeType = $scope->getType($node->getArgs()[2]->value); $isStrictComparison = $strictNodeType->isTrue()->yes(); } $isStrictComparison = $isStrictComparison || $needleType->isEnum()->yes() || $haystackType->getIterableValueType()->isEnum()->yes(); if (!$isStrictComparison) { return null; } $valueType = $haystackType->getIterableValueType(); $constantNeedleTypesCount = count($needleType->getFiniteTypes()); $constantHaystackTypesCount = count($valueType->getFiniteTypes()); $isNeedleSupertype = $needleType->isSuperTypeOf($valueType); if ($haystackType->isConstantArray()->no()) { if ($haystackType->isIterableAtLeastOnce()->yes()) { // In this case the generic implementation via typeSpecifier fails, because the argument types cannot be narrowed down. if ($constantNeedleTypesCount === 1 && $constantHaystackTypesCount === 1) { if ($isNeedleSupertype->yes()) { return \true; } if ($isNeedleSupertype->no()) { return \false; } } return null; } } if (!$haystackType instanceof ConstantArrayType || count($haystackType->getValueTypes()) > 0) { $haystackArrayTypes = $haystackType->getArrays(); if (count($haystackArrayTypes) === 1 && $haystackArrayTypes[0]->getIterableValueType() instanceof NeverType) { return null; } if ($isNeedleSupertype->maybe() || $isNeedleSupertype->yes()) { foreach ($haystackArrayTypes as $haystackArrayType) { if ($haystackArrayType instanceof ConstantArrayType) { foreach ($haystackArrayType->getValueTypes() as $i => $haystackArrayValueType) { if ($haystackArrayType->isOptionalKey($i)) { continue; } foreach ($haystackArrayValueType->getConstantScalarTypes() as $constantScalarType) { if ($constantScalarType->isSuperTypeOf($needleType)->yes()) { continue 3; } } } } else { foreach ($haystackArrayType->getIterableValueType()->getConstantScalarTypes() as $constantScalarType) { if ($constantScalarType->isSuperTypeOf($needleType)->yes()) { continue 2; } } } return null; } } if ($isNeedleSupertype->yes()) { $hasConstantNeedleTypes = $constantNeedleTypesCount > 0; $hasConstantHaystackTypes = $constantHaystackTypesCount > 0; if (!$hasConstantNeedleTypes && !$hasConstantHaystackTypes || $hasConstantNeedleTypes !== $hasConstantHaystackTypes) { return null; } } } } elseif ($functionName === 'method_exists' && $argsCount >= 2) { $objectArg = $node->getArgs()[0]->value; $objectType = $this->treatPhpDocTypesAsCertain ? $scope->getType($objectArg) : $scope->getNativeType($objectArg); if ($objectType instanceof ConstantStringType && !$this->reflectionProvider->hasClass($objectType->getValue())) { return \false; } $methodArg = $node->getArgs()[1]->value; $methodType = $this->treatPhpDocTypesAsCertain ? $scope->getType($methodArg) : $scope->getNativeType($methodArg); if ($methodType instanceof ConstantStringType) { if ($objectType instanceof ConstantStringType) { $objectType = new ObjectType($objectType->getValue()); } if ($objectType->getObjectClassNames() !== []) { if ($objectType->hasMethod($methodType->getValue())->yes()) { return \true; } if ($objectType->hasMethod($methodType->getValue())->no()) { return \false; } } $genericType = TypeTraverser::map($objectType, static function (Type $type, callable $traverse) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type instanceof GenericClassStringType) { return $type->getGenericType(); } return new MixedType(); }); if ($genericType instanceof TypeWithClassName) { if ($genericType->hasMethod($methodType->getValue())->yes()) { return \true; } $classReflection = $genericType->getClassReflection(); if ($classReflection !== null && $classReflection->isFinal() && $genericType->hasMethod($methodType->getValue())->no()) { return \false; } } } } } } $typeSpecifierScope = $this->treatPhpDocTypesAsCertain ? $scope : $scope->doNotTreatPhpDocTypesAsCertain(); $specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($typeSpecifierScope, $node, $this->determineContext($typeSpecifierScope, $node)); // don't validate types on overwrite if ($specifiedTypes->shouldOverwrite()) { return null; } $sureTypes = $specifiedTypes->getSureTypes(); $sureNotTypes = $specifiedTypes->getSureNotTypes(); $rootExpr = $specifiedTypes->getRootExpr(); if ($rootExpr !== null) { if (self::isSpecified($typeSpecifierScope, $node, $rootExpr)) { return null; } $rootExprType = $this->treatPhpDocTypesAsCertain ? $scope->getType($rootExpr) : $scope->getNativeType($rootExpr); if ($rootExprType instanceof ConstantBooleanType) { return $rootExprType->getValue(); } return null; } $results = []; foreach ($sureTypes as $sureType) { if (self::isSpecified($typeSpecifierScope, $node, $sureType[0])) { $results[] = TrinaryLogic::createMaybe(); continue; } if ($this->treatPhpDocTypesAsCertain) { $argumentType = $scope->getType($sureType[0]); } else { $argumentType = $scope->getNativeType($sureType[0]); } /** @var Type $resultType */ $resultType = $sureType[1]; $results[] = $resultType->isSuperTypeOf($argumentType); } foreach ($sureNotTypes as $sureNotType) { if (self::isSpecified($typeSpecifierScope, $node, $sureNotType[0])) { $results[] = TrinaryLogic::createMaybe(); continue; } if ($this->treatPhpDocTypesAsCertain) { $argumentType = $scope->getType($sureNotType[0]); } else { $argumentType = $scope->getNativeType($sureNotType[0]); } /** @var Type $resultType */ $resultType = $sureNotType[1]; $results[] = $resultType->isSuperTypeOf($argumentType)->negate(); } if (count($results) === 0) { return null; } $result = TrinaryLogic::createYes()->and(...$results); return $result->maybe() ? null : $result->yes(); } private static function isSpecified(Scope $scope, Expr $node, Expr $expr) : bool { if ($expr === $node) { return \true; } if ($expr instanceof Expr\Variable) { return is_string($expr->name) && !$scope->hasVariableType($expr->name)->yes(); } if ($expr instanceof Expr\BooleanNot) { return self::isSpecified($scope, $node, $expr->expr); } if ($expr instanceof Expr\BinaryOp) { return self::isSpecified($scope, $node, $expr->left) || self::isSpecified($scope, $node, $expr->right); } return ($node instanceof FuncCall || $node instanceof MethodCall || $node instanceof Expr\StaticCall) && $scope->hasExpressionType($expr)->yes(); } /** * @param Node\Arg[] $args */ public function getArgumentsDescription(Scope $scope, array $args) : string { if (count($args) === 0) { return ''; } $descriptions = array_map(function (Arg $arg) use($scope) : string { return ($this->treatPhpDocTypesAsCertain ? $scope->getType($arg->value) : $scope->getNativeType($arg->value))->describe(VerbosityLevel::value()); }, $args); if (count($descriptions) < 3) { return sprintf(' with %s', implode(' and ', $descriptions)); } $lastDescription = array_pop($descriptions); return sprintf(' with arguments %s and %s', implode(', ', $descriptions), $lastDescription); } public function doNotTreatPhpDocTypesAsCertain() : self { if (!$this->treatPhpDocTypesAsCertain) { return $this; } return new self($this->reflectionProvider, $this->typeSpecifier, $this->universalObjectCratesClasses, \false, $this->nullContextForVoidReturningFunctions); } private function determineContext(Scope $scope, Expr $node) : TypeSpecifierContext { if (!$this->nullContextForVoidReturningFunctions) { return TypeSpecifierContext::createTruthy(); } if ($node instanceof Expr\CallLike && $node->isFirstClassCallable()) { return TypeSpecifierContext::createTruthy(); } if ($node instanceof FuncCall && $node->name instanceof Node\Name) { if ($this->reflectionProvider->hasFunction($node->name, $scope)) { $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $returnType = TypeUtils::resolveLateResolvableTypes($parametersAcceptor->getReturnType()); return $returnType->isVoid()->yes() ? TypeSpecifierContext::createNull() : TypeSpecifierContext::createTruthy(); } } elseif ($node instanceof MethodCall && $node->name instanceof Node\Identifier) { $methodCalledOnType = $scope->getType($node->var); $methodReflection = $scope->getMethodReflection($methodCalledOnType, $node->name->name); if ($methodReflection !== null) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); $returnType = TypeUtils::resolveLateResolvableTypes($parametersAcceptor->getReturnType()); return $returnType->isVoid()->yes() ? TypeSpecifierContext::createNull() : TypeSpecifierContext::createTruthy(); } } elseif ($node instanceof StaticCall && $node->name instanceof Node\Identifier) { if ($node->class instanceof Node\Name) { $calleeType = $scope->resolveTypeByName($node->class); } else { $calleeType = $scope->getType($node->class); } $staticMethodReflection = $scope->getMethodReflection($calleeType, $node->name->name); if ($staticMethodReflection !== null) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $staticMethodReflection->getVariants(), $staticMethodReflection->getNamedArgumentsVariants()); $returnType = TypeUtils::resolveLateResolvableTypes($parametersAcceptor->getReturnType()); return $returnType->isVoid()->yes() ? TypeSpecifierContext::createNull() : TypeSpecifierContext::createTruthy(); } } return TypeSpecifierContext::createTruthy(); } } */ final class WhileLoopAlwaysFalseConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return While_::class; } public function processNode(Node $node, Scope $scope) : array { $exprType = $this->helper->getBooleanType($scope, $node->cond); if ($exprType->isFalse()->yes()) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; return [$addTip(RuleErrorBuilder::message('While loop condition is always false.'))->line($node->cond->getStartLine())->identifier('while.alwaysFalse')->build()]; } return []; } } */ final class LogicalXorConstantConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return LogicalXor::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; $leftType = $this->helper->getBooleanType($scope, $node->left); if ($leftType instanceof ConstantBooleanType) { $addTipLeft = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->left); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if (!$leftType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTipLeft(RuleErrorBuilder::message(sprintf('Left side of xor is always %s.', $leftType->getValue() ? 'true' : 'false')))->identifier(sprintf('logicalXor.leftAlways%s', $leftType->getValue() ? 'True' : 'False'))->line($node->left->getStartLine()); if ($leftType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errors[] = $errorBuilder->build(); } } $rightType = $this->helper->getBooleanType($scope, $node->right); if ($rightType instanceof ConstantBooleanType) { $addTipRight = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->right); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if (!$rightType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTipRight(RuleErrorBuilder::message(sprintf('Right side of xor is always %s.', $rightType->getValue() ? 'true' : 'false')))->identifier(sprintf('logicalXor.rightAlways%s', $rightType->getValue() ? 'True' : 'False'))->line($node->right->getStartLine()); if ($rightType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errors[] = $errorBuilder->build(); } } return $errors; } } */ final class IfConstantConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Stmt\If_::class; } public function processNode(Node $node, Scope $scope) : array { $exprType = $this->helper->getBooleanType($scope, $node->cond); if ($exprType instanceof ConstantBooleanType) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; return [$addTip(RuleErrorBuilder::message(sprintf('If condition is always %s.', $exprType->getValue() ? 'true' : 'false')))->identifier(sprintf('if.always%s', $exprType->getValue() ? 'True' : 'False'))->line($node->cond->getStartLine())->build()]; } return []; } } */ final class ImpossibleCheckTypeStaticMethodCallRule implements Rule { /** * @var ImpossibleCheckTypeHelper */ private $impossibleCheckTypeHelper; /** * @var bool */ private $checkAlwaysTrueCheckTypeFunctionCall; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, bool $checkAlwaysTrueCheckTypeFunctionCall, bool $treatPhpDocTypesAsCertain, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->impossibleCheckTypeHelper = $impossibleCheckTypeHelper; $this->checkAlwaysTrueCheckTypeFunctionCall = $checkAlwaysTrueCheckTypeFunctionCall; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Expr\StaticCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Identifier) { return []; } $isAlways = $this->impossibleCheckTypeHelper->findSpecifiedType($scope, $node); if ($isAlways === null) { return []; } $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $isAlways = $this->impossibleCheckTypeHelper->doNotTreatPhpDocTypesAsCertain()->findSpecifiedType($scope, $node); if ($isAlways !== null) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; if (!$isAlways) { $method = $this->getMethod($node->class, $node->name->name, $scope); return [$addTip(RuleErrorBuilder::message(sprintf('Call to static method %s::%s()%s will always evaluate to false.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()))))->identifier('staticMethod.impossibleType')->build()]; } elseif ($this->checkAlwaysTrueCheckTypeFunctionCall) { $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if ($isLast === \true && !$this->reportAlwaysTrueInLastCondition) { return []; } $method = $this->getMethod($node->class, $node->name->name, $scope); $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Call to static method %s::%s()%s will always evaluate to true.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs())))); if ($isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier('staticMethod.alreadyNarrowedType'); return [$errorBuilder->build()]; } return []; } /** * @param Node\Name|Expr $class * @throws ShouldNotHappenException */ private function getMethod($class, string $methodName, Scope $scope) : MethodReflection { if ($class instanceof Node\Name) { $calledOnType = $scope->resolveTypeByName($class); } else { $calledOnType = $scope->getType($class); } $method = $scope->getMethodReflection($calledOnType, $methodName); if ($method === null) { throw new ShouldNotHappenException(); } return $method; } } */ final class StrictComparisonOfDifferentTypesRule implements Rule { /** * @var RicherScopeGetTypeHelper */ private $richerScopeGetTypeHelper; /** * @var bool */ private $checkAlwaysTrueStrictComparison; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(RicherScopeGetTypeHelper $richerScopeGetTypeHelper, bool $checkAlwaysTrueStrictComparison, bool $treatPhpDocTypesAsCertain, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->richerScopeGetTypeHelper = $richerScopeGetTypeHelper; $this->checkAlwaysTrueStrictComparison = $checkAlwaysTrueStrictComparison; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Expr\BinaryOp::class; } public function processNode(Node $node, Scope $scope) : array { if ($node instanceof Node\Expr\BinaryOp\Identical) { $nodeTypeResult = $this->richerScopeGetTypeHelper->getIdenticalResult($this->treatPhpDocTypesAsCertain ? $scope : $scope->doNotTreatPhpDocTypesAsCertain(), $node); } elseif ($node instanceof Node\Expr\BinaryOp\NotIdentical) { $nodeTypeResult = $this->richerScopeGetTypeHelper->getNotIdenticalResult($this->treatPhpDocTypesAsCertain ? $scope : $scope->doNotTreatPhpDocTypesAsCertain(), $node); } else { return []; } $nodeType = $nodeTypeResult->type; if (!$nodeType instanceof ConstantBooleanType) { return []; } $leftType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node->left) : $scope->getNativeType($node->left); $rightType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node->right) : $scope->getNativeType($node->right); $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node, $nodeTypeResult) : RuleErrorBuilder { $reasons = $nodeTypeResult->reasons; if (count($reasons) > 0) { return $ruleErrorBuilder->acceptsReasonsTip($reasons); } if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $instanceofTypeWithoutPhpDocs = $scope->getNativeType($node); if ($instanceofTypeWithoutPhpDocs instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $verbosity = VerbosityLevel::value(); if ($leftType->isConstantScalarValue()->yes() && !$leftType->isString()->no() && !$rightType->isConstantScalarValue()->yes() && !$rightType->isString()->no() && (TrinaryLogic::extremeIdentity($leftType->isLowercaseString(), $rightType->isLowercaseString())->maybe() || TrinaryLogic::extremeIdentity($leftType->isUppercaseString(), $rightType->isUppercaseString())->maybe()) || $rightType->isConstantScalarValue()->yes() && !$rightType->isString()->no() && !$leftType->isConstantScalarValue()->yes() && !$leftType->isString()->no() && (TrinaryLogic::extremeIdentity($leftType->isLowercaseString(), $rightType->isLowercaseString())->maybe() || TrinaryLogic::extremeIdentity($leftType->isUppercaseString(), $rightType->isUppercaseString())->maybe())) { $verbosity = VerbosityLevel::precise(); } if (!$nodeType->getValue()) { return [$addTip(RuleErrorBuilder::message(sprintf('Strict comparison using %s between %s and %s will always evaluate to false.', $node->getOperatorSigil(), $leftType->describe($verbosity), $rightType->describe($verbosity))))->identifier(sprintf('%s.alwaysFalse', $node instanceof Node\Expr\BinaryOp\Identical ? 'identical' : 'notIdentical'))->build()]; } elseif ($this->checkAlwaysTrueStrictComparison) { $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if ($isLast === \true && !$this->reportAlwaysTrueInLastCondition) { return []; } $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Strict comparison using %s between %s and %s will always evaluate to true.', $node->getOperatorSigil(), $leftType->describe($verbosity), $rightType->describe($verbosity)))); if ($isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->addTip('Remove remaining cases below this one and this error will disappear too.'); } if ($leftType->isEnum()->yes() && $rightType->isEnum()->yes() && $node->getAttribute(LastConditionVisitor::ATTRIBUTE_IS_MATCH_NAME, \false) !== \true) { $errorBuilder->addTip('Use match expression instead. PHPStan will report unhandled enum cases.'); } $errorBuilder->identifier(sprintf('%s.alwaysTrue', $node instanceof Node\Expr\BinaryOp\Identical ? 'identical' : 'notIdentical')); return [$errorBuilder->build()]; } return []; } } */ final class DoWhileLoopConstantConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return DoWhileLoopConditionNode::class; } public function processNode(Node $node, Scope $scope) : array { $exprType = $this->helper->getBooleanType($scope, $node->getCond()); if ($exprType instanceof ConstantBooleanType) { if ($exprType->getValue()) { foreach ($node->getExitPoints() as $exitPoint) { $statement = $exitPoint->getStatement(); if ($statement instanceof Break_) { return []; } if (!$statement instanceof Continue_) { return []; } if ($statement->num === null) { continue; } if (!$statement->num instanceof LNumber) { continue; } $value = $statement->num->value; if ($value === 1) { continue; } if ($value > 1) { return []; } } } $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->getCond()); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; return [$addTip(RuleErrorBuilder::message(sprintf('Do-while loop condition is always %s.', $exprType->getValue() ? 'true' : 'false')))->line($node->getCond()->getStartLine())->identifier(sprintf('doWhile.always%s', $exprType->getValue() ? 'True' : 'False'))->build()]; } return []; } } */ final class BooleanAndConstantConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $bleedingEdge; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $bleedingEdge, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->bleedingEdge = $bleedingEdge; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return BooleanAndNode::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; $originalNode = $node->getOriginalNode(); $nodeText = $this->bleedingEdge ? $originalNode->getOperatorSigil() : '&&'; $leftType = $this->helper->getBooleanType($scope, $originalNode->left); $identifierType = $originalNode instanceof Node\Expr\BinaryOp\BooleanAnd ? 'booleanAnd' : 'logicalAnd'; if ($leftType instanceof ConstantBooleanType) { $addTipLeft = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $originalNode) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $originalNode->left); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if (!$leftType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTipLeft(RuleErrorBuilder::message(sprintf('Left side of %s is always %s.', $nodeText, $leftType->getValue() ? 'true' : 'false')))->identifier(sprintf('%s.leftAlways%s', $identifierType, $leftType->getValue() ? 'True' : 'False'))->line($originalNode->left->getStartLine()); if ($leftType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errors[] = $errorBuilder->build(); } } $rightScope = $node->getRightScope(); $rightType = $this->helper->getBooleanType($rightScope, $originalNode->right); if ($rightType instanceof ConstantBooleanType && !$scope->isInFirstLevelStatement()) { $addTipRight = function (RuleErrorBuilder $ruleErrorBuilder) use($rightScope, $originalNode) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($rightScope, $originalNode->right); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if (!$rightType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTipRight(RuleErrorBuilder::message(sprintf('Right side of %s is always %s.', $nodeText, $rightType->getValue() ? 'true' : 'false')))->identifier(sprintf('%s.rightAlways%s', $identifierType, $rightType->getValue() ? 'True' : 'False'))->line($originalNode->right->getStartLine()); if ($rightType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errors[] = $errorBuilder->build(); } } if (count($errors) === 0 && !$scope->isInFirstLevelStatement()) { $nodeType = $this->treatPhpDocTypesAsCertain ? $scope->getType($originalNode) : $scope->getNativeType($originalNode); if ($nodeType instanceof ConstantBooleanType) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $originalNode) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $scope->getNativeType($originalNode); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if (!$nodeType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Result of %s is always %s.', $nodeText, $nodeType->getValue() ? 'true' : 'false'))); if ($nodeType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier(sprintf('%s.always%s', $identifierType, $nodeType->getValue() ? 'True' : 'False')); $errors[] = $errorBuilder->build(); } } } return $errors; } } */ final class BooleanNotConstantConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Expr\BooleanNot::class; } public function processNode(Node $node, Scope $scope) : array { $exprType = $this->helper->getBooleanType($scope, $node->expr); if ($exprType instanceof ConstantBooleanType) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->expr); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if ($exprType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Negated boolean expression is always %s.', $exprType->getValue() ? 'false' : 'true')))->line($node->expr->getStartLine()); if (!$exprType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier(sprintf('booleanNot.always%s', $exprType->getValue() ? 'False' : 'True')); return [$errorBuilder->build()]; } } return []; } } */ final class UsageOfVoidMatchExpressionRule implements Rule { public function getNodeType() : string { return Node\Expr\Match_::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInFirstLevelStatement()) { $matchResultType = $scope->getKeepVoidType($node); if ($matchResultType->isVoid()->yes()) { return [RuleErrorBuilder::message('Result of match expression (void) is used.')->identifier('match.void')->build()]; } } return []; } } */ final class ImpossibleCheckTypeFunctionCallRule implements Rule { /** * @var ImpossibleCheckTypeHelper */ private $impossibleCheckTypeHelper; /** * @var bool */ private $checkAlwaysTrueCheckTypeFunctionCall; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, bool $checkAlwaysTrueCheckTypeFunctionCall, bool $treatPhpDocTypesAsCertain, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->impossibleCheckTypeHelper = $impossibleCheckTypeHelper; $this->checkAlwaysTrueCheckTypeFunctionCall = $checkAlwaysTrueCheckTypeFunctionCall; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Expr\FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } $functionName = (string) $node->name; $isAlways = $this->impossibleCheckTypeHelper->findSpecifiedType($scope, $node); if ($isAlways === null) { return []; } $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $isAlways = $this->impossibleCheckTypeHelper->doNotTreatPhpDocTypesAsCertain()->findSpecifiedType($scope, $node); if ($isAlways !== null) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; if (!$isAlways) { return [$addTip(RuleErrorBuilder::message(sprintf('Call to function %s()%s will always evaluate to false.', $functionName, $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()))))->identifier('function.impossibleType')->build()]; } elseif ($this->checkAlwaysTrueCheckTypeFunctionCall) { $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if ($isLast === \true && !$this->reportAlwaysTrueInLastCondition) { return []; } $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Call to function %s()%s will always evaluate to true.', $functionName, $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs())))); if ($isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier('function.alreadyNarrowedType'); return [$errorBuilder->build()]; } return []; } } */ final class ConstantLooseComparisonRule implements Rule { /** * @var bool */ private $checkAlwaysTrueLooseComparison; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(bool $checkAlwaysTrueLooseComparison, bool $treatPhpDocTypesAsCertain, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->checkAlwaysTrueLooseComparison = $checkAlwaysTrueLooseComparison; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Expr\BinaryOp::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node instanceof Node\Expr\BinaryOp\Equal && !$node instanceof Node\Expr\BinaryOp\NotEqual) { return []; } $nodeType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node) : $scope->getNativeType($node); if (!$nodeType instanceof ConstantBooleanType) { return []; } $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $instanceofTypeWithoutPhpDocs = $scope->getNativeType($node); if ($instanceofTypeWithoutPhpDocs instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; if (!$nodeType->getValue()) { return [$addTip(RuleErrorBuilder::message(sprintf('Loose comparison using %s between %s and %s will always evaluate to false.', $node->getOperatorSigil(), $scope->getType($node->left)->describe(VerbosityLevel::value()), $scope->getType($node->right)->describe(VerbosityLevel::value()))))->identifier(sprintf('%s.alwaysFalse', $node instanceof Node\Expr\BinaryOp\Equal ? 'equal' : 'notEqual'))->build()]; } elseif ($this->checkAlwaysTrueLooseComparison) { $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if ($isLast === \true && !$this->reportAlwaysTrueInLastCondition) { return []; } $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Loose comparison using %s between %s and %s will always evaluate to true.', $node->getOperatorSigil(), $scope->getType($node->left)->describe(VerbosityLevel::value()), $scope->getType($node->right)->describe(VerbosityLevel::value())))); if ($isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier(sprintf('%s.alwaysTrue', $node instanceof Node\Expr\BinaryOp\Equal ? 'equal' : 'notEqual')); return [$errorBuilder->build()]; } return []; } } */ final class UnreachableIfBranchesRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $disable; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $disable, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->disable = $disable; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Stmt\If_::class; } public function processNode(Node $node, Scope $scope) : array { if ($this->disable) { return []; } $errors = []; $condition = $node->cond; $conditionType = $this->treatPhpDocTypesAsCertain ? $scope->getType($condition) : $scope->getNativeType($condition); $conditionBooleanType = $conditionType->toBoolean(); $nextBranchIsDead = $conditionBooleanType->isTrue()->yes() && $this->helper->shouldSkip($scope, $node->cond) && !$this->helper->shouldReportAlwaysTrueByDefault($node->cond); $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, &$condition) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $scope->getNativeType($condition)->toBoolean(); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; foreach ($node->elseifs as $elseif) { if ($nextBranchIsDead) { $errors[] = $addTip(RuleErrorBuilder::message('Elseif branch is unreachable because previous condition is always true.'))->identifier('elseif.unreachable')->line($elseif->getStartLine())->build(); continue; } $condition = $elseif->cond; $conditionType = $this->treatPhpDocTypesAsCertain ? $scope->getType($condition) : $scope->getNativeType($condition); $conditionBooleanType = $conditionType->toBoolean(); $nextBranchIsDead = $conditionBooleanType->isTrue()->yes() && $this->helper->shouldSkip($scope, $elseif->cond) && !$this->helper->shouldReportAlwaysTrueByDefault($elseif->cond); } if ($node->else !== null && $nextBranchIsDead) { $errors[] = $addTip(RuleErrorBuilder::message('Else branch is unreachable because previous condition is always true.'))->identifier('else.unreachable')->line($node->else->getStartLine())->build(); } return $errors; } } impossibleCheckTypeHelper = $impossibleCheckTypeHelper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->looseComparisonRuleEnabled = $looseComparisonRuleEnabled; } public function shouldReportAlwaysTrueByDefault(Expr $expr) : bool { return $expr instanceof Expr\BooleanNot || $expr instanceof Expr\BinaryOp\BooleanOr || $expr instanceof Expr\BinaryOp\BooleanAnd || $expr instanceof Expr\Ternary || $expr instanceof Expr\Isset_ || $expr instanceof Expr\Empty_; } public function shouldSkip(Scope $scope, Expr $expr) : bool { if ($this->looseComparisonRuleEnabled && ($expr instanceof Expr\BinaryOp\Equal || $expr instanceof Expr\BinaryOp\NotEqual)) { return \true; } if ($expr instanceof Expr\Instanceof_ || $expr instanceof Expr\BinaryOp\Identical || $expr instanceof Expr\BinaryOp\NotIdentical || $expr instanceof Expr\BooleanNot || $expr instanceof Expr\BinaryOp\BooleanOr || $expr instanceof Expr\BinaryOp\BooleanAnd || $expr instanceof Expr\Ternary || $expr instanceof Expr\Isset_ || $expr instanceof Expr\Empty_ || $expr instanceof Expr\BinaryOp\Greater || $expr instanceof Expr\BinaryOp\GreaterOrEqual || $expr instanceof Expr\BinaryOp\Smaller || $expr instanceof Expr\BinaryOp\SmallerOrEqual) { // already checked by different rules return \true; } if ($expr instanceof FuncCall || $expr instanceof MethodCall || $expr instanceof Expr\StaticCall) { $isAlways = $this->impossibleCheckTypeHelper->findSpecifiedType($scope, $expr); if ($isAlways !== null) { return \true; } } return \false; } public function getBooleanType(Scope $scope, Expr $expr) : BooleanType { if ($this->shouldSkip($scope, $expr)) { return new BooleanType(); } if ($this->treatPhpDocTypesAsCertain) { return $scope->getType($expr)->toBoolean(); } return $scope->getNativeType($expr)->toBoolean(); } public function getNativeBooleanType(Scope $scope, Expr $expr) : BooleanType { if ($this->shouldSkip($scope, $expr)) { return new BooleanType(); } return $scope->getNativeType($expr)->toBoolean(); } } */ final class BooleanOrConstantConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $bleedingEdge; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $bleedingEdge, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->bleedingEdge = $bleedingEdge; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return BooleanOrNode::class; } public function processNode(Node $node, Scope $scope) : array { $originalNode = $node->getOriginalNode(); $nodeText = $this->bleedingEdge ? $originalNode->getOperatorSigil() : '||'; $messages = []; $leftType = $this->helper->getBooleanType($scope, $originalNode->left); $identifierType = $originalNode instanceof Node\Expr\BinaryOp\BooleanOr ? 'booleanOr' : 'logicalOr'; if ($leftType instanceof ConstantBooleanType) { $addTipLeft = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $originalNode) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $originalNode->left); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if (!$leftType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTipLeft(RuleErrorBuilder::message(sprintf('Left side of %s is always %s.', $nodeText, $leftType->getValue() ? 'true' : 'false')))->identifier(sprintf('%s.leftAlways%s', $identifierType, $leftType->getValue() ? 'True' : 'False'))->line($originalNode->left->getStartLine()); if ($leftType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $messages[] = $errorBuilder->build(); } } $rightScope = $node->getRightScope(); $rightType = $this->helper->getBooleanType($rightScope, $originalNode->right); if ($rightType instanceof ConstantBooleanType && !$scope->isInFirstLevelStatement()) { $addTipRight = function (RuleErrorBuilder $ruleErrorBuilder) use($rightScope, $originalNode) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($rightScope, $originalNode->right); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if (!$rightType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTipRight(RuleErrorBuilder::message(sprintf('Right side of %s is always %s.', $nodeText, $rightType->getValue() ? 'true' : 'false')))->identifier(sprintf('%s.rightAlways%s', $identifierType, $rightType->getValue() ? 'True' : 'False'))->line($originalNode->right->getStartLine()); if ($rightType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $messages[] = $errorBuilder->build(); } } if (count($messages) === 0 && !$scope->isInFirstLevelStatement()) { $nodeType = $this->treatPhpDocTypesAsCertain ? $scope->getType($originalNode) : $scope->getNativeType($originalNode); if ($nodeType instanceof ConstantBooleanType) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $originalNode) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $scope->getNativeType($originalNode); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if (!$nodeType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Result of %s is always %s.', $nodeText, $nodeType->getValue() ? 'true' : 'false'))); if ($nodeType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier(sprintf('%s.always%s', $identifierType, $nodeType->getValue() ? 'True' : 'False')); $messages[] = $errorBuilder->build(); } } } return $messages; } } */ final class ElseIfConstantConditionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Stmt\ElseIf_::class; } public function processNode(Node $node, Scope $scope) : array { $exprType = $this->helper->getBooleanType($scope, $node->cond); if ($exprType instanceof ConstantBooleanType) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $this->helper->getNativeBooleanType($scope, $node->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; $isLast = $node->cond->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); if (!$exprType->getValue() || $isLast !== \true || $this->reportAlwaysTrueInLastCondition) { $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf('Elseif condition is always %s.', $exprType->getValue() ? 'true' : 'false')))->line($node->cond->getStartLine()); if ($exprType->getValue() && $isLast === \false && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier(sprintf('elseif.always%s', $exprType->getValue() ? 'True' : 'False')); return [$errorBuilder->build()]; } } return []; } } */ final class UnreachableTernaryElseBranchRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $helper; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $disable; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $helper, bool $treatPhpDocTypesAsCertain, bool $disable, bool $treatPhpDocTypesAsCertainTip) { $this->helper = $helper; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->disable = $disable; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return Node\Expr\Ternary::class; } public function processNode(Node $node, Scope $scope) : array { if ($this->disable) { return []; } $conditionType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node->cond) : $scope->getNativeType($node->cond); $conditionBooleanType = $conditionType->toBoolean(); if ($conditionBooleanType->isTrue()->yes() && $this->helper->shouldSkip($scope, $node->cond) && !$this->helper->shouldReportAlwaysTrueByDefault($node->cond)) { $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use($scope, $node) : RuleErrorBuilder { if (!$this->treatPhpDocTypesAsCertain) { return $ruleErrorBuilder; } $booleanNativeType = $scope->getNativeType($node->cond); if ($booleanNativeType instanceof ConstantBooleanType) { return $ruleErrorBuilder; } if (!$this->treatPhpDocTypesAsCertainTip) { return $ruleErrorBuilder; } return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); }; return [$addTip(RuleErrorBuilder::message('Else branch is unreachable because ternary operator condition is always true.'))->identifier('ternary.elseUnreachable')->line($node->else->getStartLine())->build()]; } return []; } } */ final class MatchExpressionRule implements Rule { /** * @var ConstantConditionRuleHelper */ private $constantConditionRuleHelper; /** * @var bool */ private $checkAlwaysTrueStrictComparison; /** * @var bool */ private $disableUnreachable; /** * @var bool */ private $reportAlwaysTrueInLastCondition; /** * @var bool */ private $treatPhpDocTypesAsCertain; public function __construct(\PHPStan\Rules\Comparison\ConstantConditionRuleHelper $constantConditionRuleHelper, bool $checkAlwaysTrueStrictComparison, bool $disableUnreachable, bool $reportAlwaysTrueInLastCondition, bool $treatPhpDocTypesAsCertain) { $this->constantConditionRuleHelper = $constantConditionRuleHelper; $this->checkAlwaysTrueStrictComparison = $checkAlwaysTrueStrictComparison; $this->disableUnreachable = $disableUnreachable; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; } public function getNodeType() : string { return MatchExpressionNode::class; } public function processNode(Node $node, Scope $scope) : array { $matchCondition = $node->getCondition(); $matchConditionType = $scope->getType($matchCondition); $nextArmIsDeadForType = \false; $nextArmIsDeadForNativeType = \false; $errors = []; $armsCount = count($node->getArms()); $hasDefault = \false; foreach ($node->getArms() as $i => $arm) { if ($nextArmIsDeadForNativeType || $nextArmIsDeadForType && $this->treatPhpDocTypesAsCertain) { if (!$this->disableUnreachable) { $errors[] = RuleErrorBuilder::message('Match arm is unreachable because previous comparison is always true.')->identifier('match.unreachable')->line($arm->getLine())->build(); } continue; } $armConditions = $arm->getConditions(); if (count($armConditions) === 0) { $hasDefault = \true; } foreach ($armConditions as $armCondition) { $armConditionScope = $armCondition->getScope(); $armConditionExpr = new Node\Expr\BinaryOp\Identical($matchCondition, $armCondition->getCondition()); $armConditionResult = $armConditionScope->getType($armConditionExpr); if (!$armConditionResult instanceof ConstantBooleanType) { continue; } if ($armConditionResult->getValue()) { $nextArmIsDeadForType = \true; } if (!$this->treatPhpDocTypesAsCertain) { $armConditionNativeResult = $armConditionScope->getNativeType($armConditionExpr); if (!$armConditionNativeResult instanceof ConstantBooleanType) { continue; } if ($armConditionNativeResult->getValue()) { $nextArmIsDeadForNativeType = \true; } } if ($matchConditionType instanceof ConstantBooleanType) { $armConditionStandaloneResult = $this->constantConditionRuleHelper->getBooleanType($armConditionScope, $armCondition->getCondition()); if (!$armConditionStandaloneResult instanceof ConstantBooleanType) { continue; } } $armLine = $armCondition->getLine(); if (!$armConditionResult->getValue()) { $errors[] = RuleErrorBuilder::message(sprintf('Match arm comparison between %s and %s is always false.', $armConditionScope->getType($matchCondition)->describe(VerbosityLevel::value()), $armConditionScope->getType($armCondition->getCondition())->describe(VerbosityLevel::value())))->line($armLine)->identifier('match.alwaysFalse')->build(); } else { if ($this->checkAlwaysTrueStrictComparison) { if ($i === $armsCount - 1 && !$this->reportAlwaysTrueInLastCondition) { continue; } $errorBuilder = RuleErrorBuilder::message(sprintf('Match arm comparison between %s and %s is always true.', $armConditionScope->getType($matchCondition)->describe(VerbosityLevel::value()), $armConditionScope->getType($armCondition->getCondition())->describe(VerbosityLevel::value())))->line($armLine); if ($i !== $armsCount - 1 && !$this->reportAlwaysTrueInLastCondition) { $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } $errorBuilder->identifier('match.alwaysTrue'); $errors[] = $errorBuilder->build(); } } } } if (!$hasDefault && !$nextArmIsDeadForType) { $remainingType = $node->getEndScope()->getType($matchCondition); $cases = $remainingType->getEnumCases(); $casesCount = count($cases); if ($casesCount > 1) { $remainingType = new UnionType($cases); } if ($casesCount === 1) { $remainingType = $cases[0]; } if (!$remainingType instanceof NeverType && !$this->isUnhandledMatchErrorCaught($node) && !$this->hasUnhandledMatchErrorThrowsTag($scope)) { $errors[] = RuleErrorBuilder::message(sprintf('Match expression does not handle remaining %s: %s', $remainingType instanceof UnionType ? 'values' : 'value', $remainingType->describe(VerbosityLevel::value())))->identifier('match.unhandled')->build(); } } return $errors; } private function isUnhandledMatchErrorCaught(Node $node) : bool { $tryCatchTypes = $node->getAttribute(TryCatchTypeVisitor::ATTRIBUTE_NAME); if ($tryCatchTypes === null) { return \false; } $tryCatchType = TypeCombinator::union(...array_map(static function (string $class) { return new ObjectType($class); }, $tryCatchTypes)); return $tryCatchType->isSuperTypeOf(new ObjectType(UnhandledMatchError::class))->yes(); } private function hasUnhandledMatchErrorThrowsTag(Scope $scope) : bool { $function = $scope->getFunction(); if ($function === null) { return \false; } $throwsType = $function->getThrowType(); if ($throwsType === null) { return \false; } return $throwsType->isSuperTypeOf(new ObjectType(UnhandledMatchError::class))->yes(); } } disableCheckMissingIterableValueType = $disableCheckMissingIterableValueType; $this->checkMissingIterableValueType = $checkMissingIterableValueType; $this->checkGenericClassInNonGenericObjectType = $checkGenericClassInNonGenericObjectType; $this->checkMissingCallableSignature = $checkMissingCallableSignature; $this->skipCheckGenericClasses = $skipCheckGenericClasses; } /** * @return Type[] */ public function getIterableTypesWithMissingValueTypehint(Type $type) : array { if (!$this->checkMissingIterableValueType) { if (!$this->disableCheckMissingIterableValueType) { return []; } } $iterablesWithMissingValueTypehint = []; TypeTraverser::map($type, function (Type $type, callable $traverse) use(&$iterablesWithMissingValueTypehint) : Type { if ($type instanceof TemplateType) { return $type; } if ($type instanceof AccessoryType) { return $type; } if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { $iterablesWithMissingValueTypehint = array_merge($iterablesWithMissingValueTypehint, $this->getIterableTypesWithMissingValueTypehint($type->getIf()), $this->getIterableTypesWithMissingValueTypehint($type->getElse())); return $type; } if ($type->isIterable()->yes()) { $iterableValue = $type->getIterableValueType(); if ($iterableValue instanceof MixedType && !$iterableValue->isExplicitMixed()) { $iterablesWithMissingValueTypehint[] = $type; } if ($type instanceof IntersectionType) { if ($type->isList()->yes()) { return $traverse($iterableValue); } return $type; } } return $traverse($type); }); return $iterablesWithMissingValueTypehint; } /** * @return array */ public function getNonGenericObjectTypesWithGenericClass(Type $type) : array { if (!$this->checkGenericClassInNonGenericObjectType) { return []; } $objectTypes = []; TypeTraverser::map($type, function (Type $type, callable $traverse) use(&$objectTypes) : Type { if ($type instanceof GenericObjectType || $type instanceof GenericStaticType) { $traverse($type); return $type; } if ($type instanceof TemplateType) { return $type; } if ($type instanceof ObjectType) { $classReflection = $type->getClassReflection(); if ($classReflection === null) { return $type; } if (in_array($classReflection->getName(), self::ITERABLE_GENERIC_CLASS_NAMES, \true)) { // checked by getIterableTypesWithMissingValueTypehint() already return $type; } if (in_array($classReflection->getName(), $this->skipCheckGenericClasses, \true)) { return $type; } if ($classReflection->isTrait()) { return $type; } if (!$classReflection->isGeneric()) { return $type; } $resolvedType = TemplateTypeHelper::resolveToBounds($type); if (!$resolvedType instanceof ObjectType) { throw new ShouldNotHappenException(); } $templateTypes = $classReflection->getTemplateTypeMap()->getTypes(); $templateTypesCount = count($templateTypes); $requiredTemplateTypesCount = count(array_filter($templateTypes, static function (Type $type) { return $type instanceof TemplateType && $type->getDefault() === null; })); if ($requiredTemplateTypesCount === 0) { return $type; } $templateTypesList = implode(', ', array_keys($templateTypes)); if ($requiredTemplateTypesCount !== $templateTypesCount) { $templateTypesList .= sprintf(' (%d-%d required)', $requiredTemplateTypesCount, $templateTypesCount); } $objectTypes[] = [sprintf('%s %s', strtolower($classReflection->getClassTypeDescription()), $classReflection->getDisplayName(\false)), $templateTypesList]; return $type; } return $traverse($type); }); return $objectTypes; } /** * @return Type[] */ public function getCallablesWithMissingSignature(Type $type) : array { if (!$this->checkMissingCallableSignature) { return []; } $result = []; TypeTraverser::map($type, static function (Type $type, callable $traverse) use(&$result) : Type { if ($type instanceof CallableType && $type->isCommonCallable() || $type instanceof ClosureType && $type->isCommonCallable() || $type instanceof ObjectType && $type->getClassName() === Closure::class) { $result[] = $type; } return $traverse($type); }); return $result; } } */ final class DateTimeInstantiationRule implements \PHPStan\Rules\Rule { public function getNodeType() : string { return New_::class; } /** * @param New_ $node */ public function processNode(Node $node, Scope $scope) : array { if (!$node->class instanceof Node\Name) { return []; } $lowerClassName = strtolower((string) $node->class); if (count($node->getArgs()) === 0 || !in_array($lowerClassName, ['datetime', 'datetimeimmutable'], \true)) { return []; } $arg = $scope->getType($node->getArgs()[0]->value); $errors = []; foreach ($arg->getConstantStrings() as $constantString) { $dateString = $constantString->getValue(); try { new DateTime($dateString); } catch (Throwable $e) { // an exception is thrown for errors only but we want to catch warnings too } $lastErrors = DateTime::getLastErrors(); if ($lastErrors === \false) { continue; } foreach ($lastErrors['errors'] as $error) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Instantiating %s with %s produces an error: %s', $lowerClassName === 'datetime' ? 'DateTime' : 'DateTimeImmutable', $dateString, $error))->identifier(sprintf('new.%s', $lowerClassName === 'datetime' ? 'dateTime' : 'dateTimeImmutable'))->build(); } } return $errors; } } */ final class PrintRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Expr\Print_::class; } public function processNode(Node $node, Scope $scope) : array { $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->expr, '', static function (Type $type) : bool { return !$type->toString() instanceof ErrorType; }); if (!$typeResult->getType() instanceof ErrorType && $typeResult->getType()->toString() instanceof ErrorType) { return [RuleErrorBuilder::message(sprintf('Parameter %s of print cannot be converted to string.', $typeResult->getType()->describe(VerbosityLevel::value())))->identifier('print.nonString')->line($node->expr->getStartLine())->build()]; } return []; } } */ final class UnsetCastRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return Node\Expr\Cast\Unset_::class; } public function processNode(Node $node, Scope $scope) : array { if ($this->phpVersion->supportsUnsetCast()) { return []; } return [RuleErrorBuilder::message('The (unset) cast is no longer supported in PHP 8.0 and later.')->identifier('cast.unset')->nonIgnorable()->build()]; } } */ final class InvalidCastRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper) { $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Expr\Cast::class; } public function processNode(Node $node, Scope $scope) : array { $castTypeCallback = static function (Type $type) use($node) : ?array { if ($node instanceof Node\Expr\Cast\Int_) { return [$type->toInteger(), 'int']; } elseif ($node instanceof Node\Expr\Cast\Bool_) { return [$type->toBoolean(), 'bool']; } elseif ($node instanceof Node\Expr\Cast\Double) { return [$type->toFloat(), 'double']; } elseif ($node instanceof Node\Expr\Cast\String_) { return [$type->toString(), 'string']; } return null; }; $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->expr, '', static function (Type $type) use($castTypeCallback) : bool { $castResult = $castTypeCallback($type); if ($castResult === null) { return \true; } [$castType] = $castResult; return !$castType instanceof ErrorType; }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return []; } $castResult = $castTypeCallback($type); if ($castResult === null) { return []; } [$castType, $castIdentifier] = $castResult; if ($castType instanceof ErrorType) { $classReflection = $this->reflectionProvider->getClass(get_class($node)); $shortName = $classReflection->getNativeReflection()->getShortName(); $shortName = strtolower($shortName); if ($shortName === 'double') { $shortName = 'float'; } else { $shortName = substr($shortName, 0, -1); } return [RuleErrorBuilder::message(sprintf('Cannot cast %s to %s.', $scope->getType($node->expr)->describe(VerbosityLevel::value()), $shortName))->identifier(sprintf('cast.%s', $castIdentifier))->line($node->getStartLine())->build()]; } return []; } } */ final class InvalidPartOfEncapsedStringRule implements Rule { /** * @var ExprPrinter */ private $exprPrinter; /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(ExprPrinter $exprPrinter, RuleLevelHelper $ruleLevelHelper) { $this->exprPrinter = $exprPrinter; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Scalar\Encapsed::class; } public function processNode(Node $node, Scope $scope) : array { $messages = []; foreach ($node->parts as $part) { if ($part instanceof Node\Scalar\EncapsedStringPart) { continue; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $part, '', static function (Type $type) : bool { return !$type->toString() instanceof ErrorType; }); $partType = $typeResult->getType(); if ($partType instanceof ErrorType) { continue; } $stringPartType = $partType->toString(); if (!$stringPartType instanceof ErrorType) { continue; } $messages[] = RuleErrorBuilder::message(sprintf('Part %s (%s) of encapsed string cannot be cast to string.', $this->exprPrinter->printExpr($part), $partType->describe(VerbosityLevel::value())))->identifier('encapsedStringPart.nonString')->line($part->getStartLine())->build(); } return $messages; } } */ final class EchoRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Stmt\Echo_::class; } public function processNode(Node $node, Scope $scope) : array { $messages = []; foreach ($node->exprs as $key => $expr) { $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $expr, '', static function (Type $type) : bool { return !$type->toString() instanceof ErrorType; }); if ($typeResult->getType() instanceof ErrorType || !$typeResult->getType()->toString() instanceof ErrorType) { continue; } $messages[] = RuleErrorBuilder::message(sprintf('Parameter #%d (%s) of echo cannot be converted to string.', $key + 1, $typeResult->getType()->describe(VerbosityLevel::value())))->identifier('echo.nonString')->line($expr->getStartLine())->build(); } return $messages; } } */ final class ImplodeParameterCastableToStringRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ParameterCastableToStringCheck */ private $parameterCastableToStringCheck; public function __construct(ReflectionProvider $reflectionProvider, ParameterCastableToStringCheck $parameterCastableToStringCheck) { $this->reflectionProvider = $reflectionProvider; $this->parameterCastableToStringCheck = $parameterCastableToStringCheck; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); $functionName = $functionReflection->getName(); if (!in_array($functionName, ['implode', 'join'], \true)) { return []; } $origArgs = $node->getArgs(); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $origArgs, $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $normalizedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node); if ($normalizedFuncCall === null) { return []; } $normalizedArgs = $normalizedFuncCall->getArgs(); $errorMessage = 'Parameter %s of function %s expects array, %s given.'; if (count($normalizedArgs) === 1) { $argsToCheck = [0 => $normalizedArgs[0]]; } elseif (count($normalizedArgs) === 2) { $argsToCheck = [1 => $normalizedArgs[1]]; } else { return []; } $origNamedArgs = []; foreach ($origArgs as $arg) { if ($arg->unpack || $arg->name === null) { continue; } $origNamedArgs[$arg->name->toString()] = $arg; } $errors = []; foreach ($argsToCheck as $argIdx => $arg) { // implode has weird variants, so $array has to be fixed. It's especially weird with named arguments. if (array_key_exists('array', $origNamedArgs)) { $argName = '$array'; } elseif (array_key_exists('separator', $origNamedArgs) && count($origArgs) === 1) { $argName = '$separator'; } else { $argName = sprintf('#%d $array', $argIdx + 1); } $error = $this->parameterCastableToStringCheck->checkParameter($arg, $scope, $errorMessage, static function (Type $t) { return $t->toString(); }, $functionName, $argName); if ($error === null) { continue; } $errors[] = $error; } return $errors; } } */ final class ArrowFunctionAttributesRule implements Rule { /** * @var AttributesCheck */ private $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType() : string { return Node\Expr\ArrowFunction::class; } public function processNode(Node $node, Scope $scope) : array { return $this->attributesCheck->check($scope, $node->attrGroups, Attribute::TARGET_FUNCTION, 'function'); } } */ final class UnusedClosureUsesRule implements Rule { /** * @var UnusedFunctionParametersCheck */ private $check; public function __construct(UnusedFunctionParametersCheck $check) { $this->check = $check; } public function getNodeType() : string { return Node\Expr\Closure::class; } public function processNode(Node $node, Scope $scope) : array { if (count($node->uses) === 0) { return []; } return $this->check->getUnusedParameters($scope, array_map(static function (Node\Expr\ClosureUse $use) : string { if (!is_string($use->var->name)) { throw new ShouldNotHappenException(); } return $use->var->name; }, $node->uses), $node->stmts, 'Anonymous function has an unused use $%s.', 'closure.unusedUse'); } } */ final class MissingFunctionParameterTypehintRule implements Rule { /** * @var MissingTypehintCheck */ private $missingTypehintCheck; /** * @var bool */ private $paramOut; public function __construct(MissingTypehintCheck $missingTypehintCheck, bool $paramOut) { $this->missingTypehintCheck = $missingTypehintCheck; $this->paramOut = $paramOut; } public function getNodeType() : string { return InFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $functionReflection = $node->getFunctionReflection(); $messages = []; foreach ($functionReflection->getParameters() as $parameterReflection) { foreach ($this->checkFunctionParameter($functionReflection, sprintf('parameter $%s', $parameterReflection->getName()), $parameterReflection->getType()) as $parameterMessage) { $messages[] = $parameterMessage; } if ($parameterReflection->getClosureThisType() !== null) { foreach ($this->checkFunctionParameter($functionReflection, sprintf('@param-closure-this PHPDoc tag for parameter $%s', $parameterReflection->getName()), $parameterReflection->getClosureThisType()) as $parameterMessage) { $messages[] = $parameterMessage; } } if (!$this->paramOut) { continue; } if ($parameterReflection->getOutType() === null) { continue; } foreach ($this->checkFunctionParameter($functionReflection, sprintf('@param-out PHPDoc tag for parameter $%s', $parameterReflection->getName()), $parameterReflection->getOutType()) as $parameterMessage) { $messages[] = $parameterMessage; } } return $messages; } /** * @return list */ private function checkFunctionParameter(FunctionReflection $functionReflection, string $parameterMessage, Type $parameterType) : array { if ($parameterType instanceof MixedType && !$parameterType->isExplicitMixed()) { return [RuleErrorBuilder::message(sprintf('Function %s() has %s with no type specified.', $functionReflection->getName(), $parameterMessage))->identifier('missingType.parameter')->build()]; } $messages = []; foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($parameterType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $messages[] = RuleErrorBuilder::message(sprintf('Function %s() has %s with no value type specified in iterable type %s.', $functionReflection->getName(), $parameterMessage, $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($parameterType) as [$name, $genericTypeNames]) { $messages[] = RuleErrorBuilder::message(sprintf('Function %s() has %s with generic %s but does not specify its types: %s', $functionReflection->getName(), $parameterMessage, $name, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($parameterType) as $callableType) { $messages[] = RuleErrorBuilder::message(sprintf('Function %s() has %s with no signature specified for %s.', $functionReflection->getName(), $parameterMessage, $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $messages; } } */ final class CallToFunctionStatementWithoutSideEffectsRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; private const SIDE_EFFECT_FLIP_PARAMETERS = [ // functionName => [name, pos, testName] 'print_r' => ['return', 1, 'isTruthy'], 'var_export' => ['return', 1, 'isTruthy'], 'highlight_string' => ['return', 1, 'isTruthy'], ]; public const PHPSTAN_TESTING_FUNCTIONS = ['PHPStan\\dumpType', 'PHPStan\\dumpPhpDocType', 'PHPStan\\debugScope', 'PHPStan\\Testing\\assertType', 'PHPStan\\Testing\\assertNativeType', 'PHPStan\\Testing\\assertVariableCertainty']; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return Node\Stmt\Expression::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->expr instanceof Node\Expr\FuncCall) { return []; } $funcCall = $node->expr; if (!$funcCall->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($funcCall->name, $scope)) { return []; } $function = $this->reflectionProvider->getFunction($funcCall->name, $scope); $functionName = $function->getName(); $functionHasSideEffects = !$function->hasSideEffects()->no(); if (in_array($functionName, self::PHPSTAN_TESTING_FUNCTIONS, \true)) { return []; } if (isset(self::SIDE_EFFECT_FLIP_PARAMETERS[$functionName])) { [$flipParameterName, $flipParameterPosition, $testName] = self::SIDE_EFFECT_FLIP_PARAMETERS[$functionName]; $sideEffectFlipped = \false; $hasNamedParameter = \false; $checker = ['isNotNull' => static function (Type $type) { return $type->isNull()->no(); }, 'isTruthy' => static function (Type $type) { return $type->toBoolean()->isTrue()->yes(); }][$testName]; foreach ($funcCall->getRawArgs() as $i => $arg) { if (!$arg instanceof Arg) { return []; } $isFlipParameter = \false; if ($arg->name !== null) { $hasNamedParameter = \true; if ($arg->name->name === $flipParameterName) { $isFlipParameter = \true; } } if (!$hasNamedParameter && $i === $flipParameterPosition) { $isFlipParameter = \true; } if ($isFlipParameter) { $sideEffectFlipped = $checker($scope->getType($arg->value)); break; } } if (!$sideEffectFlipped) { return []; } $functionHasSideEffects = \false; } if (!$functionHasSideEffects || $node->expr->isFirstClassCallable()) { if (!$node->expr->isFirstClassCallable()) { $throwsType = $function->getThrowType(); if ($throwsType !== null && !$throwsType->isVoid()->yes()) { return []; } } $functionResult = $scope->getType($funcCall); if ($functionResult instanceof NeverType && $functionResult->isExplicit()) { return []; } return [RuleErrorBuilder::message(sprintf('Call to function %s() on a separate line has no effect.', $function->getName()))->identifier('function.resultUnused')->build()]; } return []; } } */ final class CallToNonExistentFunctionRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var bool */ private $checkFunctionNameCase; public function __construct(ReflectionProvider $reflectionProvider, bool $checkFunctionNameCase) { $this->reflectionProvider = $reflectionProvider; $this->checkFunctionNameCase = $checkFunctionNameCase; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { if ($scope->isInFunctionExists($node->name->toString())) { return []; } return [RuleErrorBuilder::message(sprintf('Function %s not found.', (string) $node->name))->identifier('function.notFound')->discoveringSymbolsTip()->build()]; } $function = $this->reflectionProvider->getFunction($node->name, $scope); $name = (string) $node->name; if ($this->checkFunctionNameCase) { /** @var string $calledFunctionName */ $calledFunctionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if (strtolower($function->getName()) === strtolower($calledFunctionName) && $function->getName() !== $calledFunctionName) { return [RuleErrorBuilder::message(sprintf('Call to function %s() with incorrect case: %s', $function->getName(), $name))->identifier('function.nameCase')->build()]; } } return []; } } */ final class IncompatibleArrowFunctionDefaultParameterTypeRule implements Rule { public function getNodeType() : string { return InArrowFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $parameters = $node->getClosureType()->getParameters(); $errors = []; foreach ($node->getOriginalNode()->getParams() as $paramI => $param) { if ($param->default === null) { continue; } if ($param->var instanceof Node\Expr\Error || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $defaultValueType = $scope->getType($param->default); $parameterType = $parameters[$paramI]->getType(); $parameterType = TemplateTypeHelper::resolveToBounds($parameterType); $accepts = $parameterType->acceptsWithReason($defaultValueType, \true); if ($accepts->yes()) { continue; } $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $defaultValueType); $errors[] = RuleErrorBuilder::message(sprintf('Default value of the parameter #%d $%s (%s) of anonymous function is incompatible with type %s.', $paramI + 1, $param->var->name, $defaultValueType->describe($verbosityLevel), $parameterType->describe($verbosityLevel)))->line($param->getStartLine())->identifier('parameter.defaultValue')->acceptsReasonsTip($accepts->reasons)->build(); } return $errors; } } */ final class DefineParametersRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if ($this->phpVersion->supportsCaseInsensitiveConstantNames()) { return []; } $name = strtolower((string) $node->name); if ($name !== 'define') { return []; } $args = $node->getArgs(); $argsCount = count($args); // Expects 2 or 3, 1 arg is caught by CallToFunctionParametersRule if ($argsCount < 3) { return []; } return [RuleErrorBuilder::message('Argument #3 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported.')->line($node->getStartLine())->identifier('argument.unused')->build()]; } } */ final class UselessFunctionReturnValueRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; private const USELESS_FUNCTIONS = ['var_export' => 'null', 'print_r' => 'true', 'highlight_string' => 'true']; public function __construct(ReflectionProvider $reflectionProvider) { $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $funcCall, Scope $scope) : array { if (!$funcCall->name instanceof Node\Name || $scope->isInFirstLevelStatement()) { return []; } if (!$this->reflectionProvider->hasFunction($funcCall->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($funcCall->name, $scope); if (!array_key_exists($functionReflection->getName(), self::USELESS_FUNCTIONS)) { return []; } $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $funcCall->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $reorderedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $funcCall); if ($reorderedFuncCall === null) { return []; } $reorderedArgs = $reorderedFuncCall->getArgs(); if (count($reorderedArgs) === 1 || count($reorderedArgs) >= 2 && $scope->getType($reorderedArgs[1]->value)->isFalse()->yes()) { return [RuleErrorBuilder::message(sprintf('Return value of function %s() is always %s and the result is printed instead of being returned. Pass in true as parameter #%d $%s to return the output instead.', $functionReflection->getName(), self::USELESS_FUNCTIONS[$functionReflection->getName()], 2, $parametersAcceptor->getParameters()[1]->getName()))->identifier('function.uselessReturnValue')->line($funcCall->getStartLine())->build()]; } return []; } } */ final class MissingFunctionReturnTypehintRule implements Rule { /** * @var MissingTypehintCheck */ private $missingTypehintCheck; public function __construct(MissingTypehintCheck $missingTypehintCheck) { $this->missingTypehintCheck = $missingTypehintCheck; } public function getNodeType() : string { return InFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $functionReflection = $node->getFunctionReflection(); $returnType = $functionReflection->getReturnType(); if ($returnType instanceof MixedType && !$returnType->isExplicitMixed()) { return [RuleErrorBuilder::message(sprintf('Function %s() has no return type specified.', $functionReflection->getName()))->identifier('missingType.return')->build()]; } $messages = []; foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($returnType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $messages[] = RuleErrorBuilder::message(sprintf('Function %s() return type has no value type specified in iterable type %s.', $functionReflection->getName(), $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($returnType) as [$name, $genericTypeNames]) { $messages[] = RuleErrorBuilder::message(sprintf('Function %s() return type with generic %s does not specify its types: %s', $functionReflection->getName(), $name, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($returnType) as $callableType) { $messages[] = RuleErrorBuilder::message(sprintf('Function %s() return type has no signature specified for %s.', $functionReflection->getName(), $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $messages; } } */ final class ParamAttributesRule implements Rule { /** * @var AttributesCheck */ private $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType() : string { return Node\Param::class; } public function processNode(Node $node, Scope $scope) : array { $targetName = 'parameter'; $targetType = Attribute::TARGET_PARAMETER; if ($node->flags !== 0) { $targetName = 'parameter or property'; $targetType |= Attribute::TARGET_PROPERTY; } return $this->attributesCheck->check($scope, $node->attrGroups, $targetType, $targetName); } } */ final class ExistingClassesInArrowFunctionTypehintsRule implements Rule { /** * @var FunctionDefinitionCheck */ private $check; /** * @var PhpVersion */ private $phpVersion; public function __construct(FunctionDefinitionCheck $check, PhpVersion $phpVersion) { $this->check = $check; $this->phpVersion = $phpVersion; } public function getNodeType() : string { return Node\Expr\ArrowFunction::class; } public function processNode(Node $node, Scope $scope) : array { $messages = []; if ($node->returnType !== null && !$this->phpVersion->supportsNeverReturnTypeInArrowFunction()) { $returnType = ParserNodeTypeToPHPStanType::resolve($node->returnType, $scope->isInClass() ? $scope->getClassReflection() : null); if ($returnType instanceof NonAcceptingNeverType) { $messages[] = RuleErrorBuilder::message('Never return type in arrow function is supported only on PHP 8.2 and later.')->identifier('return.neverTypeNotSupported')->nonIgnorable()->build(); } } return array_merge($messages, $this->check->checkAnonymousFunction($scope, $node->getParams(), $node->getReturnType(), 'Parameter $%s of anonymous function has invalid type %s.', 'Anonymous function has invalid return type %s.', 'Anonymous function uses native union types but they\'re supported only on PHP 8.0 and later.', 'Parameter $%s of anonymous function has unresolvable native type.', 'Anonymous function has unresolvable native return type.')); } } phpVersion = $phpVersion; } public function getPrintfPlaceholdersCount(string $format) : int { return $this->getPlaceholdersCount('(?:[bs%s]|l?[cdeEgfFGouxX])', $format); } public function getScanfPlaceholdersCount(string $format) : int { return $this->getPlaceholdersCount('(?:[cdDeEfinosuxX%s]|\\[[^\\]]+\\])', $format); } private function getPlaceholdersCount(string $specifiersPattern, string $format) : int { $addSpecifier = ''; if ($this->phpVersion->supportsHhPrintfSpecifier()) { $addSpecifier .= 'hH'; } $specifiers = sprintf($specifiersPattern, $addSpecifier); $pattern = '~(?%*)%(?:(?\\d+)\\$)?[-+]?(?:[ 0]|(?:\'[^%]))?(?\\*)?-?\\d*(?:\\.(?:\\d+|(?\\*))?)?' . $specifiers . '~'; $matches = Strings::matchAll($format, $pattern, PREG_SET_ORDER); if (count($matches) === 0) { return 0; } $placeholders = array_filter($matches, static function (array $match) : bool { return strlen($match['before']) % 2 === 0; }); if (count($placeholders) === 0) { return 0; } $maxPositionedNumber = 0; $maxOrdinaryNumber = 0; foreach ($placeholders as $placeholder) { if (isset($placeholder['width']) && $placeholder['width'] !== '') { $maxOrdinaryNumber++; } if (isset($placeholder['precision']) && $placeholder['precision'] !== '') { $maxOrdinaryNumber++; } if (isset($placeholder['position']) && $placeholder['position'] !== '') { $maxPositionedNumber = max((int) $placeholder['position'], $maxPositionedNumber); } else { $maxOrdinaryNumber++; } } return max($maxPositionedNumber, $maxOrdinaryNumber); } } */ final class ParameterCastableToStringRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ParameterCastableToStringCheck */ private $parameterCastableToStringCheck; public function __construct(ReflectionProvider $reflectionProvider, ParameterCastableToStringCheck $parameterCastableToStringCheck) { $this->reflectionProvider = $reflectionProvider; $this->parameterCastableToStringCheck = $parameterCastableToStringCheck; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); $functionName = $functionReflection->getName(); $checkAllArgsFunctions = ['array_intersect', 'array_intersect_assoc', 'array_diff', 'array_diff_assoc']; $checkFirstArgFunctions = ['array_combine', 'natcasesort', 'natsort', 'array_count_values', 'array_fill_keys']; if (!in_array($functionName, $checkAllArgsFunctions, \true) && !in_array($functionName, $checkFirstArgFunctions, \true)) { return []; } $origArgs = $node->getArgs(); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $origArgs, $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $errorMessage = 'Parameter %s of function %s expects an array of values castable to string, %s given.'; $functionParameters = $parametersAcceptor->getParameters(); if (in_array($functionName, $checkAllArgsFunctions, \true)) { $argsToCheck = $origArgs; } elseif (in_array($functionName, $checkFirstArgFunctions, \true)) { $normalizedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node); if ($normalizedFuncCall === null) { return []; } $normalizedArgs = $normalizedFuncCall->getArgs(); if (!array_key_exists(0, $normalizedArgs)) { return []; } $argsToCheck = [0 => $normalizedArgs[0]]; } else { return []; } $errors = []; foreach ($argsToCheck as $argIdx => $arg) { $error = $this->parameterCastableToStringCheck->checkParameter($arg, $scope, $errorMessage, static function (Type $t) { return $t->toString(); }, $functionName, $this->parameterCastableToStringCheck->getParameterName($arg, $argIdx, $functionParameters[$argIdx] ?? null)); if ($error === null) { continue; } $errors[] = $error; } return $errors; } } */ final class InnerFunctionRule implements Rule { public function getNodeType() : string { return Function_::class; } public function processNode(Node $node, Scope $scope) : array { if ($scope->getFunction() === null) { return []; } return [RuleErrorBuilder::message('Inner named functions are not supported by PHPStan. Consider refactoring to an anonymous function, class method, or a top-level-defined function. See issue #165 (https://github.com/phpstan/phpstan/issues/165) for more details.')->identifier('function.inner')->build()]; } } */ final class SortParameterCastableToStringRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var ParameterCastableToStringCheck */ private $parameterCastableToStringCheck; public function __construct(ReflectionProvider $reflectionProvider, ParameterCastableToStringCheck $parameterCastableToStringCheck) { $this->reflectionProvider = $reflectionProvider; $this->parameterCastableToStringCheck = $parameterCastableToStringCheck; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); $functionName = $functionReflection->getName(); if (!in_array($functionName, ['array_unique', 'sort', 'rsort', 'asort', 'arsort'], \true)) { return []; } $origArgs = $node->getArgs(); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $origArgs, $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $functionParameters = $parametersAcceptor->getParameters(); $normalizedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node); if ($normalizedFuncCall === null) { return []; } $normalizedArgs = $normalizedFuncCall->getArgs(); if (!array_key_exists(0, $normalizedArgs)) { return []; } $argsToCheck = [0 => $normalizedArgs[0]]; $flags = null; if (array_key_exists(1, $normalizedArgs)) { $flags = $scope->getType($normalizedArgs[1]->value); } elseif (array_key_exists(1, $functionParameters)) { $flags = $functionParameters[1]->getDefaultValue(); } if ($flags === null || $flags->equals(new ConstantIntegerType(SORT_REGULAR))) { return []; } $constantIntFlags = TypeUtils::getConstantIntegers($flags); $mustBeCastableToString = $mustBeCastableToFloat = $constantIntFlags === []; foreach ($constantIntFlags as $flag) { if ($flag->getValue() === SORT_NUMERIC) { $mustBeCastableToFloat = \true; } elseif (in_array($flag->getValue() & ~SORT_FLAG_CASE, [SORT_STRING, SORT_LOCALE_STRING, SORT_NATURAL], \true)) { $mustBeCastableToString = \true; } } if ($mustBeCastableToString && !$mustBeCastableToFloat) { $errorMessage = 'Parameter %s of function %s expects an array of values castable to string, %s given.'; $castFn = static function (Type $t) { return $t->toString(); }; } elseif ($mustBeCastableToString) { $errorMessage = 'Parameter %s of function %s expects an array of values castable to string and float, %s given.'; $castFn = static function (Type $t) : Type { $float = $t->toFloat(); return $float instanceof ErrorType ? $float : $t->toString(); }; } elseif ($mustBeCastableToFloat) { $errorMessage = 'Parameter %s of function %s expects an array of values castable to float, %s given.'; $castFn = static function (Type $t) { return $t->toFloat(); }; } else { return []; } $errors = []; foreach ($argsToCheck as $argIdx => $arg) { $error = $this->parameterCastableToStringCheck->checkParameter($arg, $scope, $errorMessage, $castFn, $functionName, $this->parameterCastableToStringCheck->getParameterName($arg, $argIdx, $functionParameters[$argIdx] ?? null)); if ($error === null) { continue; } $errors[] = $error; } return $errors; } } */ final class ReturnTypeRule implements Rule { /** * @var FunctionReturnTypeCheck */ private $returnTypeCheck; public function __construct(FunctionReturnTypeCheck $returnTypeCheck) { $this->returnTypeCheck = $returnTypeCheck; } public function getNodeType() : string { return Return_::class; } public function processNode(Node $node, Scope $scope) : array { if ($scope->getFunction() === null) { return []; } if ($scope->isInAnonymousFunction()) { return []; } $function = $scope->getFunction(); if ($function instanceof MethodReflection) { return []; } return $this->returnTypeCheck->checkReturnType($scope, $function->getReturnType(), $node->expr, $node, sprintf('Function %s() should return %%s but empty return statement found.', $function->getName()), sprintf('Function %s() with return type void returns %%s but should not return anything.', $function->getName()), sprintf('Function %s() should return %%s but returns %%s.', $function->getName()), sprintf('Function %s() should never return but return statement found.', $function->getName()), $function->isGenerator()); } } */ final class InvalidLexicalVariablesInClosureUseRule implements Rule { public function getNodeType() : string { return Node\Expr\Closure::class; } /** * @param Node\Expr\Closure $node */ public function processNode(Node $node, Scope $scope) : array { $errors = []; $params = array_filter(array_map(static function (Node\Param $param) { if (!$param->var instanceof Node\Expr\Variable) { return \false; } if (!is_string($param->var->name)) { return \false; } return $param->var->name; }, $node->getParams()), static function ($name) { return $name !== \false; }); foreach ($node->uses as $use) { if (!is_string($use->var->name)) { continue; } $var = $use->var->name; if ($var === 'this') { $errors[] = RuleErrorBuilder::message('Cannot use $this as lexical variable.')->line($use->getStartLine())->identifier('closure.useThis')->nonIgnorable()->build(); continue; } if (in_array($var, Scope::SUPERGLOBAL_VARIABLES, \true)) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot use superglobal variable $%s as lexical variable.', $var))->line($use->getStartLine())->identifier('closure.useSuperGlobal')->nonIgnorable()->build(); continue; } if (!in_array($var, $params, \true)) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('Cannot use lexical variable $%s since a parameter with the same name already exists.', $var))->line($use->getStartLine())->identifier('closure.useDuplicate')->nonIgnorable()->build(); } return $errors; } } */ final class ArrowFunctionReturnNullsafeByRefRule implements Rule { /** * @var NullsafeCheck */ private $nullsafeCheck; public function __construct(NullsafeCheck $nullsafeCheck) { $this->nullsafeCheck = $nullsafeCheck; } public function getNodeType() : string { return Node\Expr\ArrowFunction::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->byRef) { return []; } if (!$this->nullsafeCheck->containsNullSafe($node->expr)) { return []; } return [RuleErrorBuilder::message('Nullsafe cannot be returned by reference.')->nonIgnorable()->identifier('nullsafe.byRef')->build()]; } } */ final class CallToFunctionParametersRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var FunctionCallParametersCheck */ private $check; public function __construct(ReflectionProvider $reflectionProvider, FunctionCallParametersCheck $check) { $this->reflectionProvider = $reflectionProvider; $this->check = $check; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $function = $this->reflectionProvider->getFunction($node->name, $scope); $functionName = SprintfHelper::escapeFormatString($function->getName()); return $this->check->check(ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $function->getVariants(), $function->getNamedArgumentsVariants()), $scope, $function->isBuiltin(), $node, ['Function ' . $functionName . ' invoked with %d parameter, %d required.', 'Function ' . $functionName . ' invoked with %d parameters, %d required.', 'Function ' . $functionName . ' invoked with %d parameter, at least %d required.', 'Function ' . $functionName . ' invoked with %d parameters, at least %d required.', 'Function ' . $functionName . ' invoked with %d parameter, %d-%d required.', 'Function ' . $functionName . ' invoked with %d parameters, %d-%d required.', 'Parameter %s of function ' . $functionName . ' expects %s, %s given.', 'Result of function ' . $functionName . ' (void) is used.', 'Parameter %s of function ' . $functionName . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to function ' . $functionName, 'Missing parameter $%s in call to function ' . $functionName . '.', 'Unknown parameter $%s in call to function ' . $functionName . '.', 'Return type of call to function ' . $functionName . ' contains unresolvable type.', 'Parameter %s of function ' . $functionName . ' contains unresolvable type.', 'Function ' . $functionName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.'], 'function', $function->acceptsNamedArguments()); } } */ final class ClosureReturnTypeRule implements Rule { /** * @var FunctionReturnTypeCheck */ private $returnTypeCheck; public function __construct(FunctionReturnTypeCheck $returnTypeCheck) { $this->returnTypeCheck = $returnTypeCheck; } public function getNodeType() : string { return ClosureReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInAnonymousFunction()) { return []; } /** @var Type $returnType */ $returnType = $scope->getAnonymousFunctionReturnType(); $containsNull = TypeCombinator::containsNull($returnType); $hasNativeTypehint = $node->getClosureExpr()->returnType !== null; $messages = []; foreach ($node->getReturnStatements() as $returnStatement) { $returnNode = $returnStatement->getReturnNode(); $returnExpr = $returnNode->expr; if ($returnExpr === null && $containsNull && !$hasNativeTypehint) { $returnExpr = new Node\Expr\ConstFetch(new Node\Name\FullyQualified('null')); } $returnMessages = $this->returnTypeCheck->checkReturnType($returnStatement->getScope(), $returnType, $returnExpr, $returnNode, 'Anonymous function should return %s but empty return statement found.', 'Anonymous function with return type void returns %s but should not return anything.', 'Anonymous function should return %s but returns %s.', 'Anonymous function should never return but return statement found.', $node->isGenerator()); foreach ($returnMessages as $returnMessage) { $messages[] = $returnMessage; } } return $messages; } } */ final class CallCallablesRule implements Rule { /** * @var FunctionCallParametersCheck */ private $check; /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var bool */ private $reportMaybes; public function __construct(FunctionCallParametersCheck $check, RuleLevelHelper $ruleLevelHelper, bool $reportMaybes) { $this->check = $check; $this->ruleLevelHelper = $ruleLevelHelper; $this->reportMaybes = $reportMaybes; } public function getNodeType() : string { return Node\Expr\FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Expr) { return []; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $node->name), 'Invoking callable on an unknown class %s.', static function (Type $type) : bool { return $type->isCallable()->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } $isCallable = $type->isCallable(); if ($isCallable->no()) { return [RuleErrorBuilder::message(sprintf('Trying to invoke %s but it\'s not a callable.', $type->describe(VerbosityLevel::value())))->identifier('callable.nonCallable')->build()]; } if ($this->reportMaybes && $isCallable->maybe()) { return [RuleErrorBuilder::message(sprintf('Trying to invoke %s but it might not be a callable.', $type->describe(VerbosityLevel::value())))->identifier('callable.nonCallable')->build()]; } $parametersAcceptors = $type->getCallableParametersAcceptors($scope); $messages = []; $acceptsNamedArguments = \true; foreach ($parametersAcceptors as $parametersAcceptor) { $acceptsNamedArguments = $acceptsNamedArguments && $parametersAcceptor->acceptsNamedArguments(); } if (count($parametersAcceptors) === 1 && $parametersAcceptors[0] instanceof InaccessibleMethod) { $method = $parametersAcceptors[0]->getMethod(); $messages[] = RuleErrorBuilder::message(sprintf('Call to %s method %s() of class %s.', $method->isPrivate() ? 'private' : 'protected', $method->getName(), $method->getDeclaringClass()->getDisplayName()))->identifier('callable.inaccessibleMethod')->build(); } $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $parametersAcceptors, null); if ($type instanceof ClosureType) { $callableDescription = 'closure'; } else { $callableDescription = sprintf('callable %s', SprintfHelper::escapeFormatString($type->describe(VerbosityLevel::value()))); } return array_merge($messages, $this->check->check($parametersAcceptor, $scope, \false, $node, [ucfirst($callableDescription) . ' invoked with %d parameter, %d required.', ucfirst($callableDescription) . ' invoked with %d parameters, %d required.', ucfirst($callableDescription) . ' invoked with %d parameter, at least %d required.', ucfirst($callableDescription) . ' invoked with %d parameters, at least %d required.', ucfirst($callableDescription) . ' invoked with %d parameter, %d-%d required.', ucfirst($callableDescription) . ' invoked with %d parameters, %d-%d required.', 'Parameter %s of ' . $callableDescription . ' expects %s, %s given.', 'Result of ' . $callableDescription . ' (void) is used.', 'Parameter %s of ' . $callableDescription . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to ' . $callableDescription, 'Missing parameter $%s in call to ' . $callableDescription . '.', 'Unknown parameter $%s in call to ' . $callableDescription . '.', 'Return type of call to ' . $callableDescription . ' contains unresolvable type.', 'Parameter %s of ' . $callableDescription . ' contains unresolvable type.', ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.'], 'callable', $acceptsNamedArguments)); } } */ final class ReturnNullsafeByRefRule implements Rule { /** * @var NullsafeCheck */ private $nullsafeCheck; public function __construct(NullsafeCheck $nullsafeCheck) { $this->nullsafeCheck = $nullsafeCheck; } public function getNodeType() : string { return ReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->returnsByRef()) { return []; } $errors = []; foreach ($node->getReturnStatements() as $returnStatement) { $returnNode = $returnStatement->getReturnNode(); if ($returnNode->expr === null) { continue; } if (!$this->nullsafeCheck->containsNullSafe($returnNode->expr)) { continue; } $errors[] = RuleErrorBuilder::message('Nullsafe cannot be returned by reference.')->line($returnNode->getStartLine())->identifier('nullsafe.byRef')->nonIgnorable()->build(); } return $errors; } } */ final class ExistingClassesInTypehintsRule implements Rule { /** * @var FunctionDefinitionCheck */ private $check; public function __construct(FunctionDefinitionCheck $check) { $this->check = $check; } public function getNodeType() : string { return InFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $functionName = SprintfHelper::escapeFormatString($node->getFunctionReflection()->getName()); return $this->check->checkFunction($node->getOriginalNode(), $node->getFunctionReflection(), sprintf('Parameter $%%s of function %s() has invalid type %%s.', $functionName), sprintf('Function %s() has invalid return type %%s.', $functionName), sprintf('Function %s() uses native union types but they\'re supported only on PHP 8.0 and later.', $functionName), sprintf('Template type %%s of function %s() is not referenced in a parameter.', $functionName), sprintf('Parameter $%%s of function %s() has unresolvable native type.', $functionName), sprintf('Function %s() has unresolvable native return type.', $functionName)); } } */ final class ClosureAttributesRule implements Rule { /** * @var AttributesCheck */ private $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType() : string { return Node\Expr\Closure::class; } public function processNode(Node $node, Scope $scope) : array { return $this->attributesCheck->check($scope, $node->attrGroups, Attribute::TARGET_FUNCTION, 'function'); } } */ final class ArrowFunctionReturnTypeRule implements Rule { /** * @var FunctionReturnTypeCheck */ private $returnTypeCheck; public function __construct(FunctionReturnTypeCheck $returnTypeCheck) { $this->returnTypeCheck = $returnTypeCheck; } public function getNodeType() : string { return InArrowFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInAnonymousFunction()) { throw new ShouldNotHappenException(); } /** @var Type $returnType */ $returnType = $scope->getAnonymousFunctionReturnType(); $generatorType = new ObjectType(Generator::class); $originalNode = $node->getOriginalNode(); $isVoidSuperType = $returnType->isVoid(); if ($originalNode->returnType === null && $isVoidSuperType->yes()) { return []; } $exprType = $scope->getType($originalNode->expr); if ($returnType instanceof NeverType && $returnType->isExplicit() && $exprType instanceof NeverType && $exprType->isExplicit()) { return []; } return $this->returnTypeCheck->checkReturnType($scope, $returnType, $originalNode->expr, $originalNode->expr, 'Anonymous function should return %s but empty return statement found.', 'Anonymous function with return type void returns %s but should not return anything.', 'Anonymous function should return %s but returns %s.', 'Anonymous function should never return but return statement found.', $generatorType->isSuperTypeOf($returnType)->yes()); } } */ final class IncompatibleClosureDefaultParameterTypeRule implements Rule { public function getNodeType() : string { return InClosureNode::class; } public function processNode(Node $node, Scope $scope) : array { $parameters = $node->getClosureType()->getParameters(); $errors = []; foreach ($node->getOriginalNode()->getParams() as $paramI => $param) { if ($param->default === null) { continue; } if ($param->var instanceof Node\Expr\Error || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $defaultValueType = $scope->getType($param->default); $parameterType = $parameters[$paramI]->getType(); $parameterType = TemplateTypeHelper::resolveToBounds($parameterType); $accepts = $parameterType->acceptsWithReason($defaultValueType, \true); if ($accepts->yes()) { continue; } $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $defaultValueType); $errors[] = RuleErrorBuilder::message(sprintf('Default value of the parameter #%d $%s (%s) of anonymous function is incompatible with type %s.', $paramI + 1, $param->var->name, $defaultValueType->describe($verbosityLevel), $parameterType->describe($verbosityLevel)))->line($param->getStartLine())->identifier('parameter.defaultValue')->acceptsReasonsTip($accepts->reasons)->build(); } return $errors; } } */ final class DuplicateFunctionDeclarationRule implements Rule { /** * @var Reflector */ private $reflector; /** * @var RelativePathHelper */ private $relativePathHelper; public function __construct(Reflector $reflector, RelativePathHelper $relativePathHelper) { $this->reflector = $reflector; $this->relativePathHelper = $relativePathHelper; } public function getNodeType() : string { return InFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $thisFunction = $node->getFunctionReflection(); $allFunctions = $this->reflector->reflectAllFunctions(); $filteredFunctions = []; foreach ($allFunctions as $reflectionFunction) { if ($reflectionFunction->getName() !== $thisFunction->getName()) { continue; } $filteredFunctions[] = $reflectionFunction; } if (count($filteredFunctions) < 2) { return []; } return [RuleErrorBuilder::message(sprintf("Function %s declared multiple times:\n%s", $thisFunction->getName(), implode("\n", array_map(function (ReflectionFunction $function) { return sprintf('- %s:%d', $this->relativePathHelper->getRelativePath($function->getFileName() ?? 'unknown'), $function->getStartLine()); }, $filteredFunctions))))->identifier('function.duplicate')->build()]; } } */ final class ArrayValuesRule implements Rule { /** * @readonly * @var ReflectionProvider */ private $reflectionProvider; /** * @readonly * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(ReflectionProvider $reflectionProvider, bool $treatPhpDocTypesAsCertain, bool $treatPhpDocTypesAsCertainTip) { $this->reflectionProvider = $reflectionProvider; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (AccessoryArrayListType::isListTypeEnabled() === \false) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); if ($functionReflection->getName() !== 'array_values') { return []; } $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $normalizedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node); if ($normalizedFuncCall === null) { return []; } $args = $normalizedFuncCall->getArgs(); if (count($args) === 0) { return []; } if ($this->treatPhpDocTypesAsCertain) { $arrayType = $scope->getType($args[0]->value); } else { $arrayType = $scope->getNativeType($args[0]->value); } if ($arrayType->isIterableAtLeastOnce()->no()) { $message = 'Parameter #1 $array (%s) to function array_values is empty, call has no effect.'; $errorBuilder = RuleErrorBuilder::message(sprintf($message, $arrayType->describe(VerbosityLevel::value())))->identifier('arrayValues.empty'); if ($this->treatPhpDocTypesAsCertain) { $nativeArrayType = $scope->getNativeType($args[0]->value); if ($this->treatPhpDocTypesAsCertainTip && !$nativeArrayType->isIterableAtLeastOnce()->no()) { $errorBuilder->treatPhpDocTypesAsCertainTip(); } } return [$errorBuilder->build()]; } if ($arrayType->isList()->yes()) { $message = 'Parameter #1 $array (%s) of array_values is already a list, call has no effect.'; $errorBuilder = RuleErrorBuilder::message(sprintf($message, $arrayType->describe(VerbosityLevel::value())))->identifier('arrayValues.list'); if ($this->treatPhpDocTypesAsCertain) { $nativeArrayType = $scope->getNativeType($args[0]->value); if ($this->treatPhpDocTypesAsCertainTip && !$nativeArrayType->isList()->yes()) { $errorBuilder->treatPhpDocTypesAsCertainTip(); } } return [$errorBuilder->build()]; } return []; } } */ final class ImplodeFunctionRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var bool */ private $disabled; public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper, bool $disabled) { $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->disabled = $disabled; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if ($this->disabled) { return []; } if (!$node->name instanceof Node\Name) { return []; } $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if (!in_array($functionName, ['implode', 'join'], \true)) { return []; } $args = $node->getArgs(); if (count($args) === 1) { $arrayArg = $args[0]->value; $paramNo = 1; } elseif (count($args) === 2) { $arrayArg = $args[1]->value; $paramNo = 2; } else { return []; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $arrayArg, '', static function (Type $type) : bool { return !$type->getIterableValueType()->toString() instanceof ErrorType; }); if ($typeResult->getType() instanceof ErrorType || !$typeResult->getType()->getIterableValueType()->toString() instanceof ErrorType) { return []; } return [RuleErrorBuilder::message(sprintf('Parameter #%d $array of function %s expects array, %s given.', $paramNo, $functionName, $typeResult->getType()->describe(VerbosityLevel::typeOnly())))->identifier('argument.type')->build()]; } } */ final class RedefinedParametersRule implements Rule { public function getNodeType() : string { return Node\FunctionLike::class; } public function processNode(Node $node, Scope $scope) : array { $params = $node->getParams(); if (count($params) <= 1) { return []; } $vars = []; $errors = []; foreach ($params as $param) { if (!$param->var instanceof Node\Expr\Variable) { continue; } if (!is_string($param->var->name)) { continue; } $var = $param->var->name; if (!isset($vars[$var])) { $vars[$var] = \true; continue; } $errors[] = RuleErrorBuilder::message(sprintf('Redefinition of parameter $%s.', $var))->identifier('parameter.duplicate')->nonIgnorable()->build(); } return $errors; } } */ final class CallUserFuncRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var FunctionCallParametersCheck */ private $check; public function __construct(ReflectionProvider $reflectionProvider, FunctionCallParametersCheck $check) { $this->reflectionProvider = $reflectionProvider; $this->check = $check; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (count($node->getArgs()) === 0) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); if ($functionReflection->getName() !== 'call_user_func') { return []; } $result = ArgumentsNormalizer::reorderCallUserFuncArguments($node, $scope); if ($result === null) { return []; } [$parametersAcceptor, $funcCall, $acceptsNamedArguments] = $result; $callableDescription = 'callable passed to call_user_func()'; return $this->check->check($parametersAcceptor, $scope, \false, $funcCall, [ucfirst($callableDescription) . ' invoked with %d parameter, %d required.', ucfirst($callableDescription) . ' invoked with %d parameters, %d required.', ucfirst($callableDescription) . ' invoked with %d parameter, at least %d required.', ucfirst($callableDescription) . ' invoked with %d parameters, at least %d required.', ucfirst($callableDescription) . ' invoked with %d parameter, %d-%d required.', ucfirst($callableDescription) . ' invoked with %d parameters, %d-%d required.', 'Parameter %s of ' . $callableDescription . ' expects %s, %s given.', 'Result of ' . $callableDescription . ' (void) is used.', 'Parameter %s of ' . $callableDescription . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to ' . $callableDescription, 'Missing parameter $%s in call to ' . $callableDescription . '.', 'Unknown parameter $%s in call to ' . $callableDescription . '.', 'Return type of call to ' . $callableDescription . ' contains unresolvable type.', 'Parameter %s of ' . $callableDescription . ' contains unresolvable type.', ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.'], 'function', $acceptsNamedArguments); } } */ final class VariadicParametersDeclarationRule implements Rule { public function getNodeType() : string { return Node\FunctionLike::class; } public function processNode(Node $node, Scope $scope) : array { $parameters = $node->getParams(); $paramCount = count($parameters); if ($paramCount === 0) { return []; } $errors = []; foreach ($parameters as $index => $parameter) { if (!$parameter->variadic) { continue; } if ($paramCount - 1 === $index) { continue; } $errors[] = RuleErrorBuilder::message('Only the last parameter can be variadic.')->nonIgnorable()->identifier('parameter.variadicNotLast')->build(); } return $errors; } } */ final class FunctionAttributesRule implements Rule { /** * @var AttributesCheck */ private $attributesCheck; public function __construct(AttributesCheck $attributesCheck) { $this->attributesCheck = $attributesCheck; } public function getNodeType() : string { return Node\Stmt\Function_::class; } public function processNode(Node $node, Scope $scope) : array { return $this->attributesCheck->check($scope, $node->attrGroups, Attribute::TARGET_FUNCTION, 'function'); } } */ final class ArrayFilterRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var bool */ private $treatPhpDocTypesAsCertain; /** * @var bool */ private $treatPhpDocTypesAsCertainTip; public function __construct(ReflectionProvider $reflectionProvider, bool $treatPhpDocTypesAsCertain, bool $treatPhpDocTypesAsCertainTip) { $this->reflectionProvider = $reflectionProvider; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); if ($functionReflection->getName() !== 'array_filter') { return []; } $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $normalizedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node); if ($normalizedFuncCall === null) { return []; } $args = $normalizedFuncCall->getArgs(); if (count($args) !== 1) { return []; } if ($this->treatPhpDocTypesAsCertain) { $arrayType = $scope->getType($args[0]->value); } else { $arrayType = $scope->getNativeType($args[0]->value); } if ($arrayType->isIterableAtLeastOnce()->no()) { $message = 'Parameter #1 $array (%s) to function array_filter is empty, call has no effect.'; $errorBuilder = RuleErrorBuilder::message(sprintf($message, $arrayType->describe(VerbosityLevel::value())))->identifier('arrayFilter.empty'); if ($this->treatPhpDocTypesAsCertain) { $nativeArrayType = $scope->getNativeType($args[0]->value); if ($this->treatPhpDocTypesAsCertainTip && !$nativeArrayType->isIterableAtLeastOnce()->no()) { $errorBuilder->treatPhpDocTypesAsCertainTip(); } } return [$errorBuilder->build()]; } $falsyType = StaticTypeFactory::falsey(); $isSuperType = $falsyType->isSuperTypeOf($arrayType->getIterableValueType()); if ($isSuperType->no()) { $message = 'Parameter #1 $array (%s) to function array_filter does not contain falsy values, the array will always stay the same.'; $errorBuilder = RuleErrorBuilder::message(sprintf($message, $arrayType->describe(VerbosityLevel::value())))->identifier('arrayFilter.same'); if ($this->treatPhpDocTypesAsCertain) { $nativeArrayType = $scope->getNativeType($args[0]->value); $isNativeSuperType = $falsyType->isSuperTypeOf($nativeArrayType->getIterableValueType()); if ($this->treatPhpDocTypesAsCertainTip && !$isNativeSuperType->no()) { $errorBuilder->treatPhpDocTypesAsCertainTip(); } } return [$errorBuilder->build()]; } if ($isSuperType->yes()) { $message = 'Parameter #1 $array (%s) to function array_filter contains falsy values only, the result will always be an empty array.'; $errorBuilder = RuleErrorBuilder::message(sprintf($message, $arrayType->describe(VerbosityLevel::value())))->identifier('arrayFilter.alwaysEmpty'); if ($this->treatPhpDocTypesAsCertain) { $nativeArrayType = $scope->getNativeType($args[0]->value); $isNativeSuperType = $falsyType->isSuperTypeOf($nativeArrayType->getIterableValueType()); if ($this->treatPhpDocTypesAsCertainTip && !$isNativeSuperType->yes()) { $errorBuilder->treatPhpDocTypesAsCertainTip(); } } return [$errorBuilder->build()]; } return []; } } */ final class FunctionCallableRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var RuleLevelHelper */ private $ruleLevelHelper; /** * @var PhpVersion */ private $phpVersion; /** * @var bool */ private $checkFunctionNameCase; /** * @var bool */ private $reportMaybes; public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper, PhpVersion $phpVersion, bool $checkFunctionNameCase, bool $reportMaybes) { $this->reflectionProvider = $reflectionProvider; $this->ruleLevelHelper = $ruleLevelHelper; $this->phpVersion = $phpVersion; $this->checkFunctionNameCase = $checkFunctionNameCase; $this->reportMaybes = $reportMaybes; } public function getNodeType() : string { return FunctionCallableNode::class; } public function processNode(Node $node, Scope $scope) : array { if (!$this->phpVersion->supportsFirstClassCallables()) { return [RuleErrorBuilder::message('First-class callables are supported only on PHP 8.1 and later.')->nonIgnorable()->identifier('callable.notSupported')->build()]; } $functionName = $node->getName(); if ($functionName instanceof Node\Name) { $functionNameName = $functionName->toString(); if ($this->reflectionProvider->hasFunction($functionName, $scope)) { if ($this->checkFunctionNameCase) { $function = $this->reflectionProvider->getFunction($functionName, $scope); /** @var string $calledFunctionName */ $calledFunctionName = $this->reflectionProvider->resolveFunctionName($functionName, $scope); if (strtolower($function->getName()) === strtolower($calledFunctionName) && $function->getName() !== $calledFunctionName) { return [RuleErrorBuilder::message(sprintf('Call to function %s() with incorrect case: %s', $function->getName(), $functionNameName))->identifier('function.nameCase')->build()]; } } return []; } if ($scope->isInFunctionExists($functionNameName)) { return []; } return [RuleErrorBuilder::message(sprintf('Function %s not found.', $functionNameName))->identifier('function.notFound')->build()]; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope($scope, $functionName), 'Creating callable from an unknown class %s.', static function (Type $type) : bool { return $type->isCallable()->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } $isCallable = $type->isCallable(); if ($isCallable->no()) { return [RuleErrorBuilder::message(sprintf('Creating callable from %s but it\'s not a callable.', $type->describe(VerbosityLevel::value())))->identifier('callable.nonCallable')->build()]; } if ($this->reportMaybes && $isCallable->maybe()) { return [RuleErrorBuilder::message(sprintf('Creating callable from %s but it might not be a callable.', $type->describe(VerbosityLevel::value())))->identifier('callable.nonCallable')->build()]; } return []; } } */ final class PrintfParametersRule implements Rule { /** * @var PrintfHelper */ private $printfHelper; /** * @var ReflectionProvider */ private $reflectionProvider; private const FORMAT_ARGUMENT_POSITIONS = ['printf' => 0, 'sprintf' => 0, 'sscanf' => 1, 'fscanf' => 1]; private const MINIMUM_NUMBER_OF_ARGUMENTS = ['printf' => 1, 'sprintf' => 1, 'sscanf' => 3, 'fscanf' => 3]; public function __construct(\PHPStan\Rules\Functions\PrintfHelper $printfHelper, ReflectionProvider $reflectionProvider) { $this->printfHelper = $printfHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); $name = $functionReflection->getName(); if (!array_key_exists($name, self::FORMAT_ARGUMENT_POSITIONS)) { return []; } $formatArgumentPosition = self::FORMAT_ARGUMENT_POSITIONS[$name]; $args = $node->getArgs(); foreach ($args as $arg) { if ($arg->unpack) { return []; } } $argsCount = count($args); if ($argsCount < self::MINIMUM_NUMBER_OF_ARGUMENTS[$name]) { return []; // caught by CallToFunctionParametersRule } $formatArgType = $scope->getType($args[$formatArgumentPosition]->value); $maxPlaceHoldersCount = null; foreach ($formatArgType->getConstantStrings() as $formatString) { $format = $formatString->getValue(); if (in_array($name, ['sprintf', 'printf'], \true)) { $tempPlaceHoldersCount = $this->printfHelper->getPrintfPlaceholdersCount($format); } else { $tempPlaceHoldersCount = $this->printfHelper->getScanfPlaceholdersCount($format); } if ($maxPlaceHoldersCount === null) { $maxPlaceHoldersCount = $tempPlaceHoldersCount; } elseif ($tempPlaceHoldersCount > $maxPlaceHoldersCount) { $maxPlaceHoldersCount = $tempPlaceHoldersCount; } } if ($maxPlaceHoldersCount === null) { return []; } $argsCount -= $formatArgumentPosition; if ($argsCount !== $maxPlaceHoldersCount + 1) { return [RuleErrorBuilder::message(sprintf(sprintf('%s, %s.', $maxPlaceHoldersCount === 1 ? 'Call to %s contains %d placeholder' : 'Call to %s contains %d placeholders', $argsCount - 1 === 1 ? '%d value given' : '%d values given'), $name, $maxPlaceHoldersCount, $argsCount - 1))->identifier(sprintf('argument.%s', $name))->build()]; } return []; } } */ final class ExistingClassesInClosureTypehintsRule implements Rule { /** * @var FunctionDefinitionCheck */ private $check; public function __construct(FunctionDefinitionCheck $check) { $this->check = $check; } public function getNodeType() : string { return Closure::class; } public function processNode(Node $node, Scope $scope) : array { return $this->check->checkAnonymousFunction($scope, $node->getParams(), $node->getReturnType(), 'Parameter $%s of anonymous function has invalid type %s.', 'Anonymous function has invalid return type %s.', 'Anonymous function uses native union types but they\'re supported only on PHP 8.0 and later.', 'Parameter $%s of anonymous function has unresolvable native type.', 'Anonymous function has unresolvable native return type.'); } } */ final class PrintfArrayParametersRule implements Rule { /** * @var PrintfHelper */ private $printfHelper; /** * @var ReflectionProvider */ private $reflectionProvider; public function __construct(\PHPStan\Rules\Functions\PrintfHelper $printfHelper, ReflectionProvider $reflectionProvider) { $this->printfHelper = $printfHelper; $this->reflectionProvider = $reflectionProvider; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); $name = $functionReflection->getName(); if (!in_array($name, ['vprintf', 'vsprintf'], \true)) { return []; } $args = $node->getArgs(); $argsCount = count($args); if ($argsCount < 1) { return []; // caught by CallToFunctionParametersRule } $formatArgType = $scope->getType($args[0]->value); $placeHoldersCounts = []; foreach ($formatArgType->getConstantStrings() as $formatString) { $format = $formatString->getValue(); $placeHoldersCounts[] = $this->printfHelper->getPrintfPlaceholdersCount($format); } if ($placeHoldersCounts === []) { return []; } $minCount = min($placeHoldersCounts); $maxCount = max($placeHoldersCounts); if ($minCount === $maxCount) { $placeHoldersCount = new ConstantIntegerType($minCount); } else { $placeHoldersCount = IntegerRangeType::fromInterval($minCount, $maxCount); if (!$placeHoldersCount instanceof IntegerRangeType && !$placeHoldersCount instanceof ConstantIntegerType) { return []; } } $formatArgsCounts = []; if (isset($args[1])) { $formatArgsType = $scope->getType($args[1]->value); $constantArrays = $formatArgsType->getConstantArrays(); if ($constantArrays === []) { $formatArgsCounts[] = new IntegerType(); } foreach ($constantArrays as $constantArray) { $formatArgsCounts[] = $constantArray->getArraySize(); } } if ($formatArgsCounts === []) { $formatArgsCount = new ConstantIntegerType(0); } else { $formatArgsCount = TypeCombinator::union(...$formatArgsCounts); if (!$formatArgsCount instanceof IntegerRangeType && !$formatArgsCount instanceof ConstantIntegerType) { return []; } } if (!$this->placeholdersMatchesArgsCount($placeHoldersCount, $formatArgsCount)) { if ($placeHoldersCount instanceof IntegerRangeType) { $placeholders = $this->getIntegerRangeAsString($placeHoldersCount); $singlePlaceholder = \false; } else { $placeholders = $placeHoldersCount->getValue(); $singlePlaceholder = $placeholders === 1; } if ($formatArgsCount instanceof IntegerRangeType) { $values = $this->getIntegerRangeAsString($formatArgsCount); $singleValue = \false; } else { $values = $formatArgsCount->getValue(); $singleValue = $values === 1; } return [RuleErrorBuilder::message(sprintf(sprintf('%s, %s.', $singlePlaceholder ? 'Call to %s contains %d placeholder' : 'Call to %s contains %s placeholders', $singleValue ? '%d value given' : '%s values given'), $name, $placeholders, $values))->identifier(sprintf('argument.%s', $name))->build()]; } return []; } /** * @param ConstantIntegerType|IntegerRangeType $placeHoldersCount * @param ConstantIntegerType|IntegerRangeType $formatArgsCount */ private function placeholdersMatchesArgsCount($placeHoldersCount, $formatArgsCount) : bool { if ($placeHoldersCount instanceof ConstantIntegerType) { if ($formatArgsCount instanceof ConstantIntegerType) { return $placeHoldersCount->getValue() === $formatArgsCount->getValue(); } // Zero placeholders + array if ($placeHoldersCount->getValue() === 0) { return \true; } return \false; } if ($formatArgsCount instanceof IntegerRangeType && IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($placeHoldersCount)->yes()) { if ($formatArgsCount->getMin() !== null && $formatArgsCount->getMax() !== null) { // constant array return $placeHoldersCount->isSuperTypeOf($formatArgsCount)->yes(); } // general array return IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($formatArgsCount)->yes(); } return \false; } private function getIntegerRangeAsString(IntegerRangeType $range) : string { if ($range->getMin() !== null && $range->getMax() !== null) { return $range->getMin() . '-' . $range->getMax(); } elseif ($range->getMin() !== null) { return $range->getMin() . ' or more'; } elseif ($range->getMax() !== null) { return $range->getMax() . ' or less'; } throw new ShouldNotHappenException(); } } */ final class IncompatibleDefaultParameterTypeRule implements Rule { public function getNodeType() : string { return InFunctionNode::class; } public function processNode(Node $node, Scope $scope) : array { $function = $node->getFunctionReflection(); $errors = []; foreach ($node->getOriginalNode()->getParams() as $paramI => $param) { if ($param->default === null) { continue; } if ($param->var instanceof Node\Expr\Error || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $defaultValueType = $scope->getType($param->default); $parameterType = $function->getParameters()[$paramI]->getType(); $parameterType = TemplateTypeHelper::resolveToBounds($parameterType); $accepts = $parameterType->acceptsWithReason($defaultValueType, \true); if ($accepts->yes()) { continue; } $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $defaultValueType); $errors[] = RuleErrorBuilder::message(sprintf('Default value of the parameter #%d $%s (%s) of function %s() is incompatible with type %s.', $paramI + 1, $param->var->name, $defaultValueType->describe($verbosityLevel), $function->getName(), $parameterType->describe($verbosityLevel)))->line($param->getStartLine())->identifier('parameter.defaultValue')->acceptsReasonsTip($accepts->reasons)->build(); } return $errors; } } */ final class RandomIntParametersRule implements Rule { /** * @var ReflectionProvider */ private $reflectionProvider; /** * @var bool */ private $reportMaybes; public function __construct(ReflectionProvider $reflectionProvider, bool $reportMaybes) { $this->reflectionProvider = $reflectionProvider; $this->reportMaybes = $reportMaybes; } public function getNodeType() : string { return FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Name) { return []; } if ($this->reflectionProvider->resolveFunctionName($node->name, $scope) !== 'random_int') { return []; } $args = array_values($node->getArgs()); if (count($args) < 2) { return []; } $minType = $scope->getType($args[0]->value)->toInteger(); $maxType = $scope->getType($args[1]->value)->toInteger(); if (!$minType instanceof ConstantIntegerType && !$minType instanceof IntegerRangeType || !$maxType instanceof ConstantIntegerType && !$maxType instanceof IntegerRangeType) { return []; } $isSmaller = $maxType->isSmallerThan($minType); if ($isSmaller->yes() || $isSmaller->maybe() && $this->reportMaybes) { $message = 'Parameter #1 $min (%s) of function random_int expects lower number than parameter #2 $max (%s).'; return [RuleErrorBuilder::message(sprintf($message, $minType->describe(VerbosityLevel::value()), $maxType->describe(VerbosityLevel::value())))->identifier('argument.type')->build()]; } return []; } } className = $className; $this->node = $node; } public function getClassName() : string { return $this->className; } public function getNode() : Node { return $this->node; } } */ private $unknownClassErrors; /** * @var ?string */ private $tip; /** * @param string[] $referencedClasses * @param list $unknownClassErrors */ public function __construct(Type $type, array $referencedClasses, array $unknownClassErrors, ?string $tip) { $this->type = $type; $this->referencedClasses = $referencedClasses; $this->unknownClassErrors = $unknownClassErrors; $this->tip = $tip; } public function getType() : Type { return $this->type; } /** * @return string[] */ public function getReferencedClasses() : array { return $this->referencedClasses; } /** * @return list */ public function getUnknownClassErrors() : array { return $this->unknownClassErrors; } public function getTip() : ?string { return $this->tip; } } */ private $tips = []; private function __construct(string $message) { $this->properties['message'] = $message; $this->type = self::TYPE_MESSAGE; } /** * @return array}> */ public static function getRuleErrorTypes() : array { return [self::TYPE_MESSAGE => [\PHPStan\Rules\RuleError::class, [['message', 'string', 'string']]], self::TYPE_LINE => [\PHPStan\Rules\LineRuleError::class, [['line', 'int', 'int']]], self::TYPE_FILE => [\PHPStan\Rules\FileRuleError::class, [['file', 'string', 'string'], ['fileDescription', 'string', 'string']]], self::TYPE_TIP => [\PHPStan\Rules\TipRuleError::class, [['tip', 'string', 'string']]], self::TYPE_IDENTIFIER => [\PHPStan\Rules\IdentifierRuleError::class, [['identifier', 'string', 'string']]], self::TYPE_METADATA => [\PHPStan\Rules\MetadataRuleError::class, [['metadata', 'array', 'mixed[]']]], self::TYPE_NON_IGNORABLE => [\PHPStan\Rules\NonIgnorableRuleError::class, []]]; } /** * @return self */ public static function message(string $message) : self { return new self($message); } /** * @phpstan-this-out self * @return self */ public function line(int $line) : self { $this->properties['line'] = $line; $this->type |= self::TYPE_LINE; return $this; } /** * @phpstan-this-out self * @return self */ public function file(string $file, ?string $fileDescription = null) : self { if (!is_file($file)) { throw new ShouldNotHappenException(sprintf('File %s does not exist.', $file)); } $this->properties['file'] = $file; $this->properties['fileDescription'] = $fileDescription ?? $file; $this->type |= self::TYPE_FILE; return $this; } /** * @phpstan-this-out self * @return self */ public function tip(string $tip) : self { $this->tips = [$tip]; $this->type |= self::TYPE_TIP; return $this; } /** * @phpstan-this-out self * @return self */ public function addTip(string $tip) : self { $this->tips[] = $tip; $this->type |= self::TYPE_TIP; return $this; } /** * @phpstan-this-out self * @return self */ public function discoveringSymbolsTip() : self { return $this->tip('Learn more at https://phpstan.org/user-guide/discovering-symbols'); } /** * @param list $reasons * @phpstan-this-out self * @return self */ public function acceptsReasonsTip(array $reasons) : self { foreach ($reasons as $reason) { $this->addTip($reason); } return $this; } /** * @phpstan-this-out self * @return self */ public function treatPhpDocTypesAsCertainTip() : self { return $this->tip('Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'); } /** * Sets an error identifier. * * List of all current error identifiers in PHPStan: https://phpstan.org/error-identifiers * * @phpstan-this-out self * @return self */ public function identifier(string $identifier) : self { if (!Error::validateIdentifier($identifier)) { throw new ShouldNotHappenException(sprintf('Invalid identifier: %s, error identifiers must match /%s/', $identifier, Error::PATTERN_IDENTIFIER)); } $this->properties['identifier'] = $identifier; $this->type |= self::TYPE_IDENTIFIER; return $this; } /** * @param mixed[] $metadata * @phpstan-this-out self * @return self */ public function metadata(array $metadata) : self { $this->properties['metadata'] = $metadata; $this->type |= self::TYPE_METADATA; return $this; } /** * @phpstan-this-out self * @return self */ public function nonIgnorable() : self { $this->type |= self::TYPE_NON_IGNORABLE; return $this; } /** * @return T */ public function build() : \PHPStan\Rules\RuleError { /** @var class-string $className */ $className = sprintf('PHPStan\\Rules\\RuleErrors\\RuleError%d', $this->type); if (!class_exists($className)) { throw new ShouldNotHappenException(sprintf('Class %s does not exist.', $className)); } $ruleError = new $className(); foreach ($this->properties as $propertyName => $value) { $ruleError->{$propertyName} = $value; } if (count($this->tips) > 0) { if (count($this->tips) === 1) { $ruleError->tip = $this->tips[0]; } else { $ruleError->tip = implode("\n", array_map(static function (string $tip) { return sprintf('• %s', $tip); }, $this->tips)); } } return $ruleError; } } ruleLevelHelper = $ruleLevelHelper; $this->nullsafeCheck = $nullsafeCheck; $this->phpVersion = $phpVersion; $this->unresolvableTypeHelper = $unresolvableTypeHelper; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->checkArgumentTypes = $checkArgumentTypes; $this->checkArgumentsPassedByReference = $checkArgumentsPassedByReference; $this->checkExtraArguments = $checkExtraArguments; $this->checkMissingTypehints = $checkMissingTypehints; $this->checkUnresolvableParameterTypes = $checkUnresolvableParameterTypes; } /** * @param Node\Expr\FuncCall|Node\Expr\MethodCall|Node\Expr\StaticCall|Node\Expr\New_ $funcCall * @param array{0: string, 1: string, 2: string, 3: string, 4: string, 5: string, 6: string, 7: string, 8: string, 9: string, 10: string, 11: string, 12: string, 13?: string, 14?: string} $messages * @param 'attribute'|'callable'|'method'|'staticMethod'|'function'|'new' $nodeType * @return list */ public function check(ParametersAcceptor $parametersAcceptor, Scope $scope, bool $isBuiltin, $funcCall, array $messages, string $nodeType = 'function', bool $acceptsNamedArguments = \true) : array { $functionParametersMinCount = 0; $functionParametersMaxCount = 0; foreach ($parametersAcceptor->getParameters() as $parameter) { if (!$parameter->isOptional()) { $functionParametersMinCount++; } $functionParametersMaxCount++; } if ($parametersAcceptor->isVariadic()) { $functionParametersMaxCount = -1; } /** @var array $arguments */ $arguments = []; /** @var array $args */ $args = $funcCall->getArgs(); $hasNamedArguments = \false; $hasUnpackedArgument = \false; $errors = []; foreach ($args as $arg) { if ($hasNamedArguments && $arg->unpack) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message('Named argument cannot be followed by an unpacked (...) argument.')->identifier('argument.unpackAfterNamed')->line($arg->getStartLine())->nonIgnorable()->build(); } if ($hasUnpackedArgument && !$arg->unpack) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message('Unpacked argument (...) cannot be followed by a non-unpacked argument.')->identifier('argument.nonUnpackAfterUnpacked')->line($arg->getStartLine())->nonIgnorable()->build(); } if ($arg->unpack) { $hasUnpackedArgument = \true; } $argumentName = null; if ($arg->name !== null) { $hasNamedArguments = \true; $argumentName = $arg->name->toString(); } if ($arg->unpack) { $type = $scope->getType($arg->value); $arrays = $type->getConstantArrays(); if (count($arrays) > 0) { $minKeys = null; foreach ($arrays as $array) { $countType = $array->getArraySize(); if ($countType instanceof ConstantIntegerType) { $keysCount = $countType->getValue(); } elseif ($countType instanceof IntegerRangeType) { $keysCount = $countType->getMin(); if ($keysCount === null) { throw new ShouldNotHappenException(); } } else { throw new ShouldNotHappenException(); } if ($minKeys !== null && $keysCount >= $minKeys) { continue; } $minKeys = $keysCount; } for ($j = 0; $j < $minKeys; $j++) { $types = []; $commonKey = null; foreach ($arrays as $constantArray) { $types[] = $constantArray->getValueTypes()[$j]; $keyType = $constantArray->getKeyTypes()[$j]; if ($commonKey === null) { $commonKey = $keyType->getValue(); } elseif ($commonKey !== $keyType->getValue()) { $commonKey = \false; } } $keyArgumentName = null; if (is_string($commonKey)) { $keyArgumentName = $commonKey; $hasNamedArguments = \true; } $arguments[] = [$arg->value, TypeCombinator::union(...$types), \false, $keyArgumentName, $arg->getStartLine()]; } } else { $arguments[] = [$arg->value, $type->getIterableValueType(), \true, null, $arg->getStartLine()]; } continue; } $arguments[] = [$arg->value, null, \false, $argumentName, $arg->getStartLine()]; } if ($hasNamedArguments && !$this->phpVersion->supportsNamedArguments() && !(bool) $funcCall->getAttribute('isAttribute', \false)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message('Named arguments are supported only on PHP 8.0 and later.')->identifier('argument.namedNotSupported')->line($funcCall->getStartLine())->nonIgnorable()->build(); } if (!$hasNamedArguments) { $invokedParametersCount = count($arguments); foreach ($arguments as [$argumentValue, $argumentValueType, $unpack, $argumentName]) { if ($unpack) { $invokedParametersCount = max($functionParametersMinCount, $functionParametersMaxCount); break; } } if ($invokedParametersCount < $functionParametersMinCount || $this->checkExtraArguments && $invokedParametersCount > $functionParametersMaxCount) { if ($functionParametersMinCount === $functionParametersMaxCount) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($invokedParametersCount === 1 ? $messages[0] : $messages[1], $invokedParametersCount, $functionParametersMinCount))->identifier('arguments.count')->line($funcCall->getStartLine())->build(); } elseif ($functionParametersMaxCount === -1 && $invokedParametersCount < $functionParametersMinCount) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($invokedParametersCount === 1 ? $messages[2] : $messages[3], $invokedParametersCount, $functionParametersMinCount))->identifier('arguments.count')->line($funcCall->getStartLine())->build(); } elseif ($functionParametersMaxCount !== -1) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($invokedParametersCount === 1 ? $messages[4] : $messages[5], $invokedParametersCount, $functionParametersMinCount, $functionParametersMaxCount))->identifier('arguments.count')->line($funcCall->getStartLine())->build(); } } } if (!$funcCall instanceof Node\Expr\New_ && !$scope->isInFirstLevelStatement() && $scope->getKeepVoidType($funcCall)->isVoid()->yes()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($messages[7])->identifier(sprintf('%s.void', $nodeType))->line($funcCall->getStartLine())->build(); } [$addedErrors, $argumentsWithParameters] = $this->processArguments($parametersAcceptor, $funcCall->getStartLine(), $isBuiltin, $arguments, $hasNamedArguments, $messages[10], $messages[11]); foreach ($addedErrors as $error) { $errors[] = $error; } if (!$this->checkArgumentTypes && !$this->checkArgumentsPassedByReference) { return $errors; } foreach ($argumentsWithParameters as $i => [$argumentValue, $argumentValueType, $unpack, $argumentName, $argumentLine, $parameter, $originalParameter]) { if ($this->checkArgumentTypes && $unpack) { $iterableTypeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $argumentValue, '', static function (Type $type) : bool { return $type->isIterable()->yes(); }); $iterableTypeResultType = $iterableTypeResult->getType(); if (!$iterableTypeResultType instanceof ErrorType && !$iterableTypeResultType->isIterable()->yes()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Only iterables can be unpacked, %s given in argument #%d.', $iterableTypeResultType->describe(VerbosityLevel::typeOnly()), $i + 1))->identifier('argument.unpackNonIterable')->line($argumentLine)->build(); } } if ($parameter === null) { continue; } if ($argumentValueType === null) { if ($scope instanceof MutatingScope) { $scope = $scope->pushInFunctionCall(null, $parameter); } $argumentValueType = $scope->getType($argumentValue); if ($scope instanceof MutatingScope) { $scope = $scope->popInFunctionCall(); } } if (!$acceptsNamedArguments && $this->checkUnresolvableParameterTypes && isset($messages[14])) { if ($argumentName !== null) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($messages[14], sprintf('named argument $%s', $argumentName)))->identifier('argument.named')->line($argumentLine)->build(); } elseif ($unpack) { $unpackedArrayType = $scope->getType($argumentValue); $hasStringKey = $unpackedArrayType->getIterableKeyType()->isString(); if (!$hasStringKey->no()) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($messages[14], sprintf('unpacked array with %s', $hasStringKey->yes() ? 'string key' : 'possibly string key')))->identifier('argument.named')->line($argumentLine)->build(); } } } if ($this->checkArgumentTypes) { $parameterType = TypeUtils::resolveLateResolvableTypes($parameter->getType()); if (!$parameter->passedByReference()->createsNewVariable() || !$isBuiltin && $this->checkUnresolvableParameterTypes && !$argumentValueType instanceof ErrorType) { $accepts = $this->ruleLevelHelper->acceptsWithReason($parameterType, $argumentValueType, $scope->isDeclareStrictTypes()); if (!$accepts->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $argumentValueType); $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($messages[6], $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), $parameterType->describe($verbosityLevel), $argumentValueType->describe($verbosityLevel)))->identifier('argument.type')->line($argumentLine)->acceptsReasonsTip($accepts->reasons)->build(); } } if ($this->checkUnresolvableParameterTypes && $originalParameter !== null && isset($messages[13]) && !$this->unresolvableTypeHelper->containsUnresolvableType($originalParameter->getType()) && $this->unresolvableTypeHelper->containsUnresolvableType($parameterType)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($messages[13], $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null)))->identifier('argument.unresolvableType')->line($argumentLine)->build(); } if ($parameter instanceof ParameterReflectionWithPhpDocs && $parameter->getClosureThisType() !== null && ($argumentValue instanceof Expr\Closure || $argumentValue instanceof Expr\ArrowFunction) && $argumentValue->static) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($messages[6], $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), 'bindable closure', 'static closure'))->identifier('argument.staticClosure')->line($argumentLine)->build(); } } if (!$this->checkArgumentsPassedByReference || !$parameter->passedByReference()->yes()) { continue; } if ($this->nullsafeCheck->containsNullSafe($argumentValue)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($messages[8], $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null)))->identifier('argument.byRef')->line($argumentLine)->build(); continue; } if ($argumentValue instanceof Node\Expr\PropertyFetch || $argumentValue instanceof Node\Expr\StaticPropertyFetch) { $propertyReflections = $this->propertyReflectionFinder->findPropertyReflectionsFromNode($argumentValue, $scope); foreach ($propertyReflections as $propertyReflection) { $nativePropertyReflection = $propertyReflection->getNativeReflection(); if ($nativePropertyReflection === null) { continue; } if (!$nativePropertyReflection->isReadOnly()) { continue; } if ($nativePropertyReflection->isStatic()) { $propertyDescription = sprintf('static readonly property %s::$%s', $propertyReflection->getDeclaringClass()->getDisplayName(), $propertyReflection->getName()); } else { $propertyDescription = sprintf('readonly property %s::$%s', $propertyReflection->getDeclaringClass()->getDisplayName(), $propertyReflection->getName()); } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Parameter %s is passed by reference so it does not accept %s.', $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), $propertyDescription))->identifier('argument.byRef')->line($argumentLine)->build(); } } if ($argumentValue instanceof Node\Expr\Variable || $argumentValue instanceof Node\Expr\ArrayDimFetch || $argumentValue instanceof Node\Expr\PropertyFetch || $argumentValue instanceof Node\Expr\StaticPropertyFetch) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($messages[8], $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null)))->identifier('argument.byRef')->line($argumentLine)->build(); } if ($this->checkMissingTypehints && $parametersAcceptor instanceof ResolvedFunctionVariant) { $originalParametersAcceptor = $parametersAcceptor->getOriginalParametersAcceptor(); $resolvedTypes = $parametersAcceptor->getResolvedTemplateTypeMap()->getTypes(); if (count($resolvedTypes) > 0) { $returnTemplateTypes = []; TypeTraverser::map($parametersAcceptor->getReturnTypeWithUnresolvableTemplateTypes(), static function (Type $type, callable $traverse) use(&$returnTemplateTypes) : Type { while ($type instanceof ConditionalType && $type->isResolvable()) { $type = $type->resolve(); } if ($type instanceof TemplateType && $type->getDefault() === null) { $returnTemplateTypes[$type->getName()] = \true; return $type; } return $traverse($type); }); $parameterTemplateTypes = []; foreach ($originalParametersAcceptor->getParameters() as $parameter) { TypeTraverser::map($parameter->getType(), static function (Type $type, callable $traverse) use(&$parameterTemplateTypes) : Type { if ($type instanceof TemplateType && $type->getDefault() === null) { $parameterTemplateTypes[$type->getName()] = \true; return $type; } return $traverse($type); }); } foreach ($resolvedTypes as $name => $type) { if (!$type instanceof ErrorType && (!$type instanceof NeverType || $type->isExplicit())) { continue; } if (!array_key_exists($name, $returnTemplateTypes)) { continue; } if (!array_key_exists($name, $parameterTemplateTypes)) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($messages[9], $name))->identifier('argument.templateType')->line($funcCall->getStartLine())->tip('See: https://phpstan.org/blog/solving-phpstan-error-unable-to-resolve-template-type')->build(); } } if (!$this->unresolvableTypeHelper->containsUnresolvableType($originalParametersAcceptor->getReturnType()) && $this->unresolvableTypeHelper->containsUnresolvableType($parametersAcceptor->getReturnType())) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message($messages[12])->identifier(sprintf('%s.unresolvableReturnType', $nodeType))->line($funcCall->getStartLine())->build(); } } return $errors; } /** * @param array $arguments * @return array{list, array} */ private function processArguments(ParametersAcceptor $parametersAcceptor, int $line, bool $isBuiltin, array $arguments, bool $hasNamedArguments, string $missingParameterMessage, string $unknownParameterMessage) : array { $parameters = $parametersAcceptor->getParameters(); $originalParameters = $parametersAcceptor instanceof ResolvedFunctionVariant ? $parametersAcceptor->getOriginalParametersAcceptor()->getParameters() : array_fill(0, count($parameters), null); $parametersByName = []; $originalParametersByName = []; $unusedParametersByName = []; $errors = []; foreach ($parameters as $i => $parameter) { $parametersByName[$parameter->getName()] = $parameter; $originalParametersByName[$parameter->getName()] = $originalParameters[$i]; if ($parameter->isVariadic()) { continue; } $unusedParametersByName[$parameter->getName()] = $parameter; } $newArguments = []; $namedArgumentAlreadyOccurred = \false; foreach ($arguments as $i => [$argumentValue, $argumentValueType, $unpack, $argumentName, $argumentLine]) { if ($argumentName === null) { if (!isset($parameters[$i])) { if (!$parametersAcceptor->isVariadic() || count($parameters) === 0) { $newArguments[$i] = [$argumentValue, $argumentValueType, $unpack, $argumentName, $argumentLine, null, null]; break; } $parameter = $parameters[count($parameters) - 1]; $originalParameter = $originalParameters[count($originalParameters) - 1]; if (!$parameter->isVariadic()) { $newArguments[$i] = [$argumentValue, $argumentValueType, $unpack, $argumentName, $argumentLine, null, null]; break; // func_get_args } } else { $parameter = $parameters[$i]; $originalParameter = $originalParameters[$i]; } } elseif (array_key_exists($argumentName, $parametersByName)) { $namedArgumentAlreadyOccurred = \true; $parameter = $parametersByName[$argumentName]; $originalParameter = $originalParametersByName[$argumentName]; } else { $namedArgumentAlreadyOccurred = \true; $parametersCount = count($parameters); if (!$parametersAcceptor->isVariadic() || $parametersCount <= 0 || $isBuiltin) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($unknownParameterMessage, $argumentName))->identifier('argument.unknown')->line($argumentLine)->build(); $newArguments[$i] = [$argumentValue, $argumentValueType, $unpack, $argumentName, $argumentLine, null, null]; continue; } $parameter = $parameters[$parametersCount - 1]; $originalParameter = $originalParameters[$parametersCount - 1]; } if ($namedArgumentAlreadyOccurred && $argumentName === null && !$unpack) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message('Named argument cannot be followed by a positional argument.')->identifier('argument.positionalAfterNamed')->line($argumentLine)->nonIgnorable()->build(); $newArguments[$i] = [$argumentValue, $argumentValueType, $unpack, $argumentName, $argumentLine, null, null]; continue; } $newArguments[$i] = [$argumentValue, $argumentValueType, $unpack, $argumentName, $argumentLine, $parameter, $originalParameter]; if ($hasNamedArguments && !$parameter->isVariadic() && !array_key_exists($parameter->getName(), $unusedParametersByName)) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf('Argument for parameter $%s has already been passed.', $parameter->getName()))->identifier('argument.duplicate')->line($argumentLine)->build(); continue; } unset($unusedParametersByName[$parameter->getName()]); } if ($hasNamedArguments) { foreach ($unusedParametersByName as $parameter) { if ($parameter->isOptional()) { continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($missingParameterMessage, sprintf('%s (%s)', $parameter->getName(), $parameter->getType()->describe(VerbosityLevel::typeOnly()))))->identifier('argument.missing')->line($line)->build(); } } return [$errors, $newArguments]; } private function describeParameter(ParameterReflection $parameter, ?int $position) : string { $parts = []; if ($position !== null) { $parts[] = '#' . $position; } $name = $parameter->getName(); if ($name !== '') { $parts[] = ($parameter->isVariadic() ? '...$' : '$') . $name; } return implode(' ', $parts); } } */ final class PureFunctionRule implements Rule { /** * @var FunctionPurityCheck */ private $check; public function __construct(\PHPStan\Rules\Pure\FunctionPurityCheck $check) { $this->check = $check; } public function getNodeType() : string { return FunctionReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $function = $node->getFunctionReflection(); return $this->check->check(sprintf('Function %s()', $function->getName()), 'Function', $function, $function->getParameters(), $function->getReturnType(), $node->getImpurePoints(), $node->getStatementResult()->getThrowPoints(), $node->getStatements(), \false); } } */ final class PureMethodRule implements Rule { /** * @var FunctionPurityCheck */ private $check; public function __construct(\PHPStan\Rules\Pure\FunctionPurityCheck $check) { $this->check = $check; } public function getNodeType() : string { return MethodReturnStatementsNode::class; } public function processNode(Node $node, Scope $scope) : array { $method = $node->getMethodReflection(); return $this->check->check(sprintf('Method %s::%s()', $method->getDeclaringClass()->getDisplayName(), $method->getName()), 'Method', $method, $method->getParameters(), $method->getReturnType(), $node->getImpurePoints(), $node->getStatementResult()->getThrowPoints(), $node->getStatements(), $method->isConstructor()); } } * @param FunctionReflection|ExtendedMethodReflection $functionReflection */ public function check(string $functionDescription, string $identifier, $functionReflection, array $parameters, Type $returnType, array $impurePoints, array $throwPoints, array $statements, bool $isConstructor) : array { $errors = []; $isPure = $functionReflection->isPure(); if ($isPure->yes()) { foreach ($parameters as $parameter) { if (!$parameter->passedByReference()->createsNewVariable()) { continue; } $errors[] = RuleErrorBuilder::message(sprintf('%s is marked as pure but parameter $%s is passed by reference.', $functionDescription, $parameter->getName()))->identifier(sprintf('pure%s.parameterByRef', $identifier))->build(); } if ($returnType->isVoid()->yes() && !$isConstructor) { $errors[] = RuleErrorBuilder::message(sprintf('%s is marked as pure but returns void.', $functionDescription))->identifier(sprintf('pure%s.void', $identifier))->build(); } foreach ($impurePoints as $impurePoint) { $errors[] = RuleErrorBuilder::message(sprintf('%s %s in pure %s.', $impurePoint->isCertain() ? 'Impure' : 'Possibly impure', $impurePoint->getDescription(), lcfirst($functionDescription)))->line($impurePoint->getNode()->getStartLine())->identifier(sprintf('%s.%s', $impurePoint->isCertain() ? 'impure' : 'possiblyImpure', $impurePoint->getIdentifier()))->build(); } } elseif ($isPure->no()) { if (count($throwPoints) === 0 && count($impurePoints) === 0 && count($functionReflection->getAsserts()->getAll()) === 0) { $errors[] = RuleErrorBuilder::message(sprintf('%s is marked as impure but does not have any side effects.', $functionDescription))->identifier(sprintf('impure%s.pure', $identifier))->build(); } } elseif ($returnType->isVoid()->yes()) { if (count($throwPoints) === 0 && count($impurePoints) === 0 && !$isConstructor && (!$functionReflection instanceof ExtendedMethodReflection || $functionReflection->isPrivate()) && count($functionReflection->getAsserts()->getAll()) === 0) { $hasByRef = \false; foreach ($parameters as $parameter) { if (!$parameter->passedByReference()->createsNewVariable()) { continue; } $hasByRef = \true; break; } $statements = array_filter($statements, static function (Stmt $stmt) : bool { if ($stmt instanceof Stmt\Nop) { return \false; } if (!$stmt instanceof Stmt\Expression) { return \true; } if (!$stmt->expr instanceof FuncCall) { return \true; } if (!$stmt->expr->name instanceof Name) { return \true; } return !in_array($stmt->expr->name->toString(), CallToFunctionStatementWithoutSideEffectsRule::PHPSTAN_TESTING_FUNCTIONS, \true); }); if (!$hasByRef && count($statements) > 0) { $errors[] = RuleErrorBuilder::message(sprintf('%s returns void but does not have any side effects.', $functionDescription))->identifier('void.pure')->build(); } } } return $errors; } } */ final class ParameterOutAssignedTypeRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return VariableAssignNode::class; } public function processNode(Node $node, Scope $scope) : array { $inFunction = $scope->getFunction(); if ($inFunction === null) { return []; } if ($scope->isInAnonymousFunction()) { return []; } $variable = $node->getVariable(); if (!is_string($variable->name)) { return []; } $parameters = $inFunction->getParameters(); $foundParameter = null; foreach ($parameters as $parameter) { if (!$parameter->passedByReference()->createsNewVariable()) { continue; } if ($parameter->getName() !== $variable->name) { continue; } $foundParameter = $parameter; break; } if ($foundParameter === null) { return []; } $isParamOutType = \true; $outType = $foundParameter->getOutType(); if ($outType === null) { $isParamOutType = \false; $outType = $foundParameter->getType(); } $outType = TypeUtils::resolveLateResolvableTypes($outType); $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->getAssignedExpr(), '', static function (Type $type) use($outType) : bool { return $outType->isSuperTypeOf($type)->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } $assignedExprType = $scope->getType($node->getAssignedExpr()); if ($outType->isSuperTypeOf($assignedExprType)->yes()) { return []; } if ($inFunction instanceof ExtendedMethodReflection) { $functionDescription = sprintf('method %s::%s()', $inFunction->getDeclaringClass()->getDisplayName(), $inFunction->getName()); } else { $functionDescription = sprintf('function %s()', $inFunction->getName()); } $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($outType, $assignedExprType); $errorBuilder = RuleErrorBuilder::message(sprintf('Parameter &$%s %s of %s expects %s, %s given.', $foundParameter->getName(), $isParamOutType ? '@param-out type' : 'by-ref type', $functionDescription, $outType->describe($verbosityLevel), $assignedExprType->describe($verbosityLevel)))->identifier(sprintf('%s.type', $isParamOutType ? 'paramOut' : 'parameterByRef')); if (!$isParamOutType) { $errorBuilder->tip('You can change the parameter out type with @param-out PHPDoc tag.'); } return [$errorBuilder->build()]; } } */ final class ThrowTypeRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Node\Stmt\Throw_::class; } public function processNode(Node $node, Scope $scope) : array { $throwableType = new ObjectType(Throwable::class); $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->expr, 'Throwing object of an unknown class %s.', static function (Type $type) use($throwableType) : bool { return $throwableType->isSuperTypeOf($type)->yes(); }); $foundType = $typeResult->getType(); if ($foundType instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } $isSuperType = $throwableType->isSuperTypeOf($foundType); if ($isSuperType->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Invalid type %s to throw.', $foundType->describe(VerbosityLevel::typeOnly())))->identifier('throw.notThrowable')->build()]; } } */ final class CompactVariablesRule implements Rule { /** * @var bool */ private $checkMaybeUndefinedVariables; public function __construct(bool $checkMaybeUndefinedVariables) { $this->checkMaybeUndefinedVariables = $checkMaybeUndefinedVariables; } public function getNodeType() : string { return Node\Expr\FuncCall::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->name instanceof Node\Expr) { return []; } $functionName = strtolower($node->name->toString()); if ($functionName !== 'compact') { return []; } $functionArguments = $node->getArgs(); $messages = []; foreach ($functionArguments as $argument) { $argumentType = $scope->getType($argument->value); $constantStrings = $this->findConstantStrings($argumentType); foreach ($constantStrings as $constantString) { $variableName = $constantString->getValue(); $scopeHasVariable = $scope->hasVariableType($variableName); if ($scopeHasVariable->no()) { $messages[] = RuleErrorBuilder::message(sprintf('Call to function compact() contains undefined variable $%s.', $variableName))->identifier('variable.undefined')->line($argument->getStartLine())->build(); } elseif ($this->checkMaybeUndefinedVariables && $scopeHasVariable->maybe()) { $messages[] = RuleErrorBuilder::message(sprintf('Call to function compact() contains possibly undefined variable $%s.', $variableName))->identifier('variable.undefined')->line($argument->getStartLine())->build(); } } } return $messages; } /** * @return array */ private function findConstantStrings(Type $type) : array { if ($type instanceof ConstantStringType) { return [$type]; } if ($type instanceof ConstantArrayType) { $result = []; foreach ($type->getValueTypes() as $valueType) { $constantStrings = $this->findConstantStrings($valueType); $result = array_merge($result, $constantStrings); } return $result; } return []; } } */ final class UnsetRule implements Rule { public function getNodeType() : string { return Node\Stmt\Unset_::class; } public function processNode(Node $node, Scope $scope) : array { $functionArguments = $node->vars; $errors = []; foreach ($functionArguments as $argument) { $error = $this->canBeUnset($argument, $scope); if ($error === null) { continue; } $errors[] = $error; } return $errors; } private function canBeUnset(Node $node, Scope $scope) : ?IdentifierRuleError { if ($node instanceof Node\Expr\Variable && is_string($node->name)) { $hasVariable = $scope->hasVariableType($node->name); if ($hasVariable->no()) { return RuleErrorBuilder::message(sprintf('Call to function unset() contains undefined variable $%s.', $node->name))->line($node->getStartLine())->identifier('unset.variable')->build(); } } elseif ($node instanceof Node\Expr\ArrayDimFetch && $node->dim !== null) { $type = $scope->getType($node->var); $dimType = $scope->getType($node->dim); if ($type->isOffsetAccessible()->no() || $type->hasOffsetValueType($dimType)->no()) { return RuleErrorBuilder::message(sprintf('Cannot unset offset %s on %s.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value())))->line($node->getStartLine())->identifier('unset.offset')->build(); } return $this->canBeUnset($node->var, $scope); } return null; } } */ final class DefinedVariableRule implements Rule { /** * @var bool */ private $cliArgumentsVariablesRegistered; /** * @var bool */ private $checkMaybeUndefinedVariables; public function __construct(bool $cliArgumentsVariablesRegistered, bool $checkMaybeUndefinedVariables) { $this->cliArgumentsVariablesRegistered = $cliArgumentsVariablesRegistered; $this->checkMaybeUndefinedVariables = $checkMaybeUndefinedVariables; } public function getNodeType() : string { return Variable::class; } public function processNode(Node $node, Scope $scope) : array { if (!is_string($node->name)) { return []; } if ($this->cliArgumentsVariablesRegistered && in_array($node->name, ['argc', 'argv'], \true)) { $isInMain = !$scope->isInClass() && !$scope->isInAnonymousFunction() && $scope->getFunction() === null; if ($isInMain) { return []; } } if ($scope->isInExpressionAssign($node) || $scope->isUndefinedExpressionAllowed($node)) { return []; } if ($scope->hasVariableType($node->name)->no()) { return [RuleErrorBuilder::message(sprintf('Undefined variable: $%s', $node->name))->identifier('variable.undefined')->build()]; } elseif ($this->checkMaybeUndefinedVariables && !$scope->hasVariableType($node->name)->yes()) { return [RuleErrorBuilder::message(sprintf('Variable $%s might not be defined.', $node->name))->identifier('variable.undefined')->build()]; } return []; } } */ final class VariableCloningRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return Clone_::class; } public function processNode(Node $node, Scope $scope) : array { $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->expr, 'Cloning object of an unknown class %s.', static function (Type $type) : bool { return $type->isCloneable()->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } if ($type->isCloneable()->yes()) { return []; } if ($node->expr instanceof Variable && is_string($node->expr->name)) { return [RuleErrorBuilder::message(sprintf('Cannot clone non-object variable $%s of type %s.', $node->expr->name, $type->describe(VerbosityLevel::typeOnly())))->identifier('clone.nonObject')->build()]; } return [RuleErrorBuilder::message(sprintf('Cannot clone %s.', $type->describe(VerbosityLevel::typeOnly())))->identifier('clone.nonObject')->build()]; } } */ final class ParameterOutExecutionEndTypeRule implements Rule { /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(RuleLevelHelper $ruleLevelHelper) { $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return ExecutionEndNode::class; } public function processNode(Node $node, Scope $scope) : array { $inFunction = $scope->getFunction(); if ($inFunction === null) { return []; } if ($scope->isInAnonymousFunction()) { return []; } $endNode = $node->getNode(); if ($endNode instanceof Node\Stmt\Expression) { $endNodeExpr = $endNode->expr; $endNodeExprType = $scope->getType($endNodeExpr); if ($endNodeExprType instanceof NeverType && $endNodeExprType->isExplicit()) { return []; } } if ($endNode instanceof Node\Stmt\Throw_) { return []; } $parameters = $inFunction->getParameters(); $errors = []; foreach ($parameters as $parameter) { if (!$parameter->passedByReference()->createsNewVariable()) { continue; } foreach ($this->processSingleParameter($scope, $inFunction, $parameter) as $error) { $errors[] = $error; } } return $errors; } /** * @return list * @param FunctionReflection|ExtendedMethodReflection $inFunction */ private function processSingleParameter(Scope $scope, $inFunction, ParameterReflectionWithPhpDocs $parameter) : array { $outType = $parameter->getOutType(); if ($outType === null) { return []; } if ($scope->hasExpressionType(new ParameterVariableOriginalValueExpr($parameter->getName()))->no()) { return []; } $outType = TypeUtils::resolveLateResolvableTypes($outType); $variableExpr = new Node\Expr\Variable($parameter->getName()); $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $variableExpr, '', static function (Type $type) use($outType) : bool { return $outType->isSuperTypeOf($type)->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return $typeResult->getUnknownClassErrors(); } $assignedExprType = $scope->getType($variableExpr); if ($outType->isSuperTypeOf($assignedExprType)->yes()) { return []; } if ($inFunction instanceof ExtendedMethodReflection) { $functionDescription = sprintf('method %s::%s()', $inFunction->getDeclaringClass()->getDisplayName(), $inFunction->getName()); } else { $functionDescription = sprintf('function %s()', $inFunction->getName()); } $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($outType, $assignedExprType); $errorBuilder = RuleErrorBuilder::message(sprintf('Parameter &$%s @param-out type of %s expects %s, %s given.', $parameter->getName(), $functionDescription, $outType->describe($verbosityLevel), $assignedExprType->describe($verbosityLevel)))->identifier(sprintf('paramOut.type')); return [$errorBuilder->build()]; } } */ final class NullCoalesceRule implements Rule { /** * @var IssetCheck */ private $issetCheck; public function __construct(IssetCheck $issetCheck) { $this->issetCheck = $issetCheck; } public function getNodeType() : string { return Node\Expr::class; } public function processNode(Node $node, Scope $scope) : array { $typeMessageCallback = static function (Type $type) : ?string { $isNull = $type->isNull(); if ($isNull->maybe()) { return null; } if ($isNull->yes()) { return 'is always null'; } return 'is not nullable'; }; if ($node instanceof Node\Expr\BinaryOp\Coalesce) { $error = $this->issetCheck->check($node->left, $scope, 'on left side of ??', 'nullCoalesce', $typeMessageCallback); } elseif ($node instanceof Node\Expr\AssignOp\Coalesce) { $error = $this->issetCheck->check($node->var, $scope, 'on left side of ??=', 'nullCoalesce', $typeMessageCallback); } else { return []; } if ($error === null) { return []; } return [$error]; } } */ final class EmptyRule implements Rule { /** * @var IssetCheck */ private $issetCheck; public function __construct(IssetCheck $issetCheck) { $this->issetCheck = $issetCheck; } public function getNodeType() : string { return Node\Expr\Empty_::class; } public function processNode(Node $node, Scope $scope) : array { $error = $this->issetCheck->check($node->expr, $scope, 'in empty()', 'empty', static function (Type $type) : ?string { $isNull = $type->isNull(); if ($isNull->maybe()) { return null; } $isFalsey = $type->toBoolean()->isFalse(); if ($isFalsey->maybe()) { return null; } if ($isNull->yes()) { if ($isFalsey->yes()) { return 'is always falsy'; } if ($isFalsey->no()) { return 'is not falsy'; } return 'is always null'; } if ($isFalsey->yes()) { return 'is always falsy'; } if ($isFalsey->no()) { return 'is not falsy'; } return 'is not nullable'; }); if ($error === null) { return []; } return [$error]; } } */ final class IssetRule implements Rule { /** * @var IssetCheck */ private $issetCheck; public function __construct(IssetCheck $issetCheck) { $this->issetCheck = $issetCheck; } public function getNodeType() : string { return Node\Expr\Isset_::class; } public function processNode(Node $node, Scope $scope) : array { $messages = []; foreach ($node->vars as $var) { $error = $this->issetCheck->check($var, $scope, 'in isset()', 'isset', static function (Type $type) : ?string { $isNull = $type->isNull(); if ($isNull->maybe()) { return null; } if ($isNull->yes()) { return 'is always null'; } return 'is not nullable'; }); if ($error === null) { continue; } $messages[] = $error; } return $messages; } } */ final class UsedNamesRule implements Rule { public function getNodeType() : string { return FileNode::class; } /** * @param FileNode $node */ public function processNode(Node $node, Scope $scope) : array { $usedNames = []; $errors = []; foreach ($node->getNodes() as $oneNode) { if ($oneNode instanceof Namespace_) { $namespaceName = $oneNode->name !== null ? $oneNode->name->toString() : ''; foreach ($oneNode->stmts as $stmt) { foreach ($this->findErrorsForNode($stmt, $namespaceName, $usedNames) as $error) { $errors[] = $error; } } continue; } foreach ($this->findErrorsForNode($oneNode, '', $usedNames) as $error) { $errors[] = $error; } } return $errors; } /** * @param array $usedNames * @return list */ private function findErrorsForNode(Node $node, string $namespace, array &$usedNames) : array { $lowerNamespace = strtolower($namespace); if ($node instanceof Use_) { if ($this->shouldBeIgnored($node)) { return []; } return $this->findErrorsInUses($node->uses, '', $lowerNamespace, $usedNames); } if ($node instanceof GroupUse) { if ($this->shouldBeIgnored($node)) { return []; } $useGroupPrefix = $node->prefix->toString(); return $this->findErrorsInUses($node->uses, $useGroupPrefix, $lowerNamespace, $usedNames); } if ($node instanceof ClassLike) { if ($node->name === null) { return []; } $type = 'class'; if ($node instanceof Interface_) { $type = 'interface'; } elseif ($node instanceof Trait_) { $type = 'trait'; } elseif ($node instanceof Enum_) { $type = 'enum'; } $name = $node->name->toLowerString(); if (in_array($name, $usedNames[$lowerNamespace] ?? [], \true)) { return [RuleErrorBuilder::message(sprintf('Cannot declare %s %s because the name is already in use.', $type, $namespace !== '' ? $namespace . '\\' . $node->name->toString() : $node->name->toString()))->identifier(sprintf('%s.nameInUse', $type))->line($node->getLine())->nonIgnorable()->build()]; } $usedNames[$lowerNamespace][] = $name; return []; } return []; } /** * @param UseUse[] $uses * @param array $usedNames * @return list */ private function findErrorsInUses(array $uses, string $useGroupPrefix, string $lowerNamespace, array &$usedNames) : array { $errors = []; foreach ($uses as $use) { if ($this->shouldBeIgnored($use)) { continue; } $useAlias = $use->getAlias()->toLowerString(); if (in_array($useAlias, $usedNames[$lowerNamespace] ?? [], \true)) { $errors[] = RuleErrorBuilder::message(sprintf('Cannot use %s as %s because the name is already in use.', $useGroupPrefix !== '' ? $useGroupPrefix . '\\' . $use->name->toString() : $use->name->toString(), $use->getAlias()->toString()))->identifier('use.nameInUse')->line($use->getLine())->nonIgnorable()->build(); continue; } $usedNames[$lowerNamespace][] = $useAlias; } return $errors; } /** * @param Use_|GroupUse|UseUse $use */ private function shouldBeIgnored($use) : bool { return in_array($use->type, [Use_::TYPE_FUNCTION, Use_::TYPE_CONSTANT], \true); } } */ final class ClassAsClassConstantRule implements Rule { public function getNodeType() : string { return Node\Stmt\ClassConst::class; } public function processNode(Node $node, Scope $scope) : array { $errors = []; foreach ($node->consts as $const) { if ($const->name->toLowerString() !== 'class') { continue; } $errors[] = RuleErrorBuilder::message('A class constant must not be called \'class\'; it is reserved for class name fetching.')->line($const->getStartLine())->identifier('classConstant.class')->nonIgnorable()->build(); } return $errors; } } container = $container; } public function getExtensions() : array { if ($this->extensions === null) { $this->extensions = $this->container->getServicesByTag(\PHPStan\Rules\Constants\AlwaysUsedClassConstantsExtensionProvider::EXTENSION_TAG); } return $this->extensions; } } */ final class MagicConstantContextRule implements Rule { public function getNodeType() : string { return MagicConst::class; } public function processNode(Node $node, Scope $scope) : array { // test cases https://3v4l.org/ZUvvr if ($node instanceof MagicConst\Class_) { if ($scope->isInClass()) { return []; } return [RuleErrorBuilder::message(sprintf('Magic constant %s is always empty outside a class.', $node->getName()))->identifier('magicConstant.outOfClass')->build()]; } elseif ($node instanceof MagicConst\Trait_) { if ($scope->isInTrait()) { return []; } return [RuleErrorBuilder::message(sprintf('Magic constant %s is always empty outside a trait.', $node->getName()))->identifier('magicConstant.outOfTrait')->build()]; } elseif ($node instanceof MagicConst\Method || $node instanceof MagicConst\Function_) { if ($scope->getFunctionName() !== null) { return []; } if ($scope->isInAnonymousFunction()) { return []; } if ((bool) $node->getAttribute(MagicConstantParamDefaultVisitor::ATTRIBUTE_NAME)) { return []; } return [RuleErrorBuilder::message(sprintf('Magic constant %s is always empty outside a function.', $node->getName()))->identifier('magicConstant.outOfFunction')->build()]; } elseif ($node instanceof MagicConst\Namespace_) { if ($scope->getNamespace() === null) { return [RuleErrorBuilder::message(sprintf('Magic constant %s is always empty in global namespace.', $node->getName()))->identifier('magicConstant.outOfNamespace')->build()]; } } return []; } } */ final class DynamicClassConstantFetchRule implements Rule { /** * @var PhpVersion */ private $phpVersion; /** * @var RuleLevelHelper */ private $ruleLevelHelper; public function __construct(PhpVersion $phpVersion, RuleLevelHelper $ruleLevelHelper) { $this->phpVersion = $phpVersion; $this->ruleLevelHelper = $ruleLevelHelper; } public function getNodeType() : string { return ClassConstFetch::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->name instanceof Node\Expr) { return []; } if (!$this->phpVersion->supportsDynamicClassConstantFetch()) { return [RuleErrorBuilder::message('Fetching class constants with a dynamic name is supported only on PHP 8.3 and later.')->identifier('classConstant.dynamicFetch')->nonIgnorable()->build()]; } $typeResult = $this->ruleLevelHelper->findTypeToCheck($scope, $node->name, '', static function (Type $type) : bool { return $type->isString()->yes(); }); $type = $typeResult->getType(); if ($type instanceof ErrorType) { return []; } if ($type->isString()->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Class constant name in dynamic fetch can only be a string, %s given.', $type->describe(VerbosityLevel::typeOnly())))->identifier('classConstant.nameType')->build()]; } } */ final class ConstantRule implements Rule { public function getNodeType() : string { return Node\Expr\ConstFetch::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->hasConstant($node->name)) { return [RuleErrorBuilder::message(sprintf('Constant %s not found.', (string) $node->name))->identifier('constant.notFound')->discoveringSymbolsTip()->build()]; } return []; } } */ final class ValueAssignedToClassConstantRule implements Rule { public function getNodeType() : string { return Node\Stmt\ClassConst::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $nativeType = null; if ($node->type !== null) { $nativeType = ParserNodeTypeToPHPStanType::resolve($node->type, $scope->getClassReflection()); } $errors = []; foreach ($node->consts as $const) { $constantName = $const->name->toString(); $errors = array_merge($errors, $this->processSingleConstant($scope->getClassReflection(), $constantName, $scope->getType($const->value), $nativeType)); } return $errors; } /** * @return list */ private function processSingleConstant(ClassReflection $classReflection, string $constantName, Type $valueExprType, ?Type $nativeType) : array { $constantReflection = $classReflection->getConstant($constantName); $phpDocType = $constantReflection->getPhpDocType(); if ($phpDocType === null) { if ($nativeType === null) { return []; } $accepts = $nativeType->acceptsWithReason($valueExprType, \true); if ($accepts->yes()) { return []; } return [RuleErrorBuilder::message(sprintf('Constant %s::%s (%s) does not accept value %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $nativeType->describe(VerbosityLevel::typeOnly()), $valueExprType->describe(VerbosityLevel::value())))->acceptsReasonsTip($accepts->reasons)->nonIgnorable()->identifier('classConstant.value')->build()]; } elseif ($nativeType === null) { $isSuperType = $phpDocType->isSuperTypeOf($valueExprType); $verbosity = VerbosityLevel::getRecommendedLevelByType($phpDocType, $valueExprType); if ($isSuperType->no()) { return [RuleErrorBuilder::message(sprintf('PHPDoc tag @var for constant %s::%s with type %s is incompatible with value %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $phpDocType->describe($verbosity), $valueExprType->describe(VerbosityLevel::value())))->identifier('classConstant.phpDocType')->build()]; } elseif ($isSuperType->maybe()) { return [RuleErrorBuilder::message(sprintf('PHPDoc tag @var for constant %s::%s with type %s is not subtype of value %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $phpDocType->describe($verbosity), $valueExprType->describe(VerbosityLevel::value())))->identifier('classConstant.phpDocType')->build()]; } return []; } $type = $constantReflection->getValueType(); $accepts = $type->acceptsWithReason($valueExprType, \true); if ($accepts->yes()) { return []; } $verbosity = VerbosityLevel::getRecommendedLevelByType($type, $valueExprType); return [RuleErrorBuilder::message(sprintf('Constant %s::%s (%s) does not accept value %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $type->describe(VerbosityLevel::typeOnly()), $valueExprType->describe($verbosity)))->acceptsReasonsTip($accepts->reasons)->identifier('classConstant.value')->build()]; } } */ final class NativeTypedClassConstantRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return Node\Stmt\ClassConst::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->type === null) { return []; } if ($this->phpVersion->supportsNativeTypesInClassConstants()) { return []; } return [RuleErrorBuilder::message('Class constants with native types are supported only on PHP 8.3 and later.')->identifier('classConstant.nativeTypeNotSupported')->nonIgnorable()->build()]; } } */ final class OverridingConstantRule implements Rule { /** * @var bool */ private $checkPhpDocMethodSignatures; public function __construct(bool $checkPhpDocMethodSignatures) { $this->checkPhpDocMethodSignatures = $checkPhpDocMethodSignatures; } public function getNodeType() : string { return Node\Stmt\ClassConst::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $errors = []; foreach ($node->consts as $const) { $constantName = $const->name->toString(); $errors = array_merge($errors, $this->processSingleConstant($scope->getClassReflection(), $constantName)); } return $errors; } /** * @return list */ private function processSingleConstant(ClassReflection $classReflection, string $constantName) : array { $prototype = $this->findPrototype($classReflection, $constantName); if (!$prototype instanceof ClassConstantReflection) { return []; } $constantReflection = $classReflection->getConstant($constantName); $errors = []; if ($prototype->isFinal()) { $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s overrides final constant %s::%s.', $classReflection->getDisplayName(), $constantReflection->getName(), $prototype->getDeclaringClass()->getDisplayName(), $prototype->getName()))->identifier('classConstant.final')->nonIgnorable()->build(); } if ($prototype->isPublic()) { if (!$constantReflection->isPublic()) { $errors[] = RuleErrorBuilder::message(sprintf('%s constant %s::%s overriding public constant %s::%s should also be public.', $constantReflection->isPrivate() ? 'Private' : 'Protected', $constantReflection->getDeclaringClass()->getDisplayName(), $constantReflection->getName(), $prototype->getDeclaringClass()->getDisplayName(), $prototype->getName()))->identifier('classConstant.visibility')->nonIgnorable()->build(); } } elseif ($constantReflection->isPrivate()) { $errors[] = RuleErrorBuilder::message(sprintf('Private constant %s::%s overriding protected constant %s::%s should be protected or public.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantReflection->getName(), $prototype->getDeclaringClass()->getDisplayName(), $prototype->getName()))->identifier('classConstant.visibility')->nonIgnorable()->build(); } if (!$this->checkPhpDocMethodSignatures) { return $errors; } $prototypeNativeType = $prototype->getNativeType(); $constantNativeType = $constantReflection->getNativeType(); if ($prototypeNativeType !== null) { if ($constantNativeType !== null) { if (!$prototypeNativeType->isSuperTypeOf($constantNativeType)->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('Native type %s of constant %s::%s is not covariant with native type %s of constant %s::%s.', $constantNativeType->describe(VerbosityLevel::typeOnly()), $constantReflection->getDeclaringClass()->getDisplayName(), $constantReflection->getName(), $prototypeNativeType->describe(VerbosityLevel::typeOnly()), $prototype->getDeclaringClass()->getDisplayName(), $prototype->getName()))->identifier('classConstant.nativeType')->nonIgnorable()->build(); } } else { $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s overriding constant %s::%s (%s) should also have native type %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantReflection->getName(), $prototype->getDeclaringClass()->getDisplayName(), $prototype->getName(), $prototypeNativeType->describe(VerbosityLevel::typeOnly()), $prototypeNativeType->describe(VerbosityLevel::typeOnly())))->identifier('classConstant.missingNativeType')->nonIgnorable()->build(); } } if (!$prototype->hasPhpDocType()) { return $errors; } if (!$constantReflection->hasPhpDocType()) { return $errors; } if (!$prototype->getValueType()->isSuperTypeOf($constantReflection->getValueType())->yes()) { $errors[] = RuleErrorBuilder::message(sprintf('Type %s of constant %s::%s is not covariant with type %s of constant %s::%s.', $constantReflection->getValueType()->describe(VerbosityLevel::value()), $constantReflection->getDeclaringClass()->getDisplayName(), $constantReflection->getName(), $prototype->getValueType()->describe(VerbosityLevel::value()), $prototype->getDeclaringClass()->getDisplayName(), $prototype->getName()))->identifier('classConstant.type')->build(); } return $errors; } private function findPrototype(ClassReflection $classReflection, string $constantName) : ?ConstantReflection { foreach ($classReflection->getImmediateInterfaces() as $immediateInterface) { if ($immediateInterface->hasConstant($constantName)) { return $immediateInterface->getConstant($constantName); } } $parentClass = $classReflection->getParentClass(); if ($parentClass === null) { return null; } if (!$parentClass->hasConstant($constantName)) { return null; } $constant = $parentClass->getConstant($constantName); if ($constant->isPrivate()) { return null; } return $constant; } } */ final class FinalConstantRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return ClassConst::class; } public function processNode(Node $node, Scope $scope) : array { if (!$node->isFinal()) { return []; } if ($this->phpVersion->supportsFinalConstants()) { return []; } return [RuleErrorBuilder::message('Final class constants are supported only on PHP 8.1 and later.')->identifier('classConstant.finalNotSupported')->nonIgnorable()->build()]; } } */ final class MissingClassConstantTypehintRule implements Rule { /** * @var MissingTypehintCheck */ private $missingTypehintCheck; public function __construct(MissingTypehintCheck $missingTypehintCheck) { $this->missingTypehintCheck = $missingTypehintCheck; } public function getNodeType() : string { return Node\Stmt\ClassConst::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $errors = []; foreach ($node->consts as $const) { $constantName = $const->name->toString(); $errors = array_merge($errors, $this->processSingleConstant($scope->getClassReflection(), $constantName)); } return $errors; } /** * @return list */ private function processSingleConstant(ClassReflection $classReflection, string $constantName) : array { $constantReflection = $classReflection->getConstant($constantName); $constantType = $constantReflection->getPhpDocType(); if ($constantType === null) { return []; } $errors = []; foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($constantType) as $iterableType) { $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s type has no value type specified in iterable type %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $iterableTypeDescription))->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP)->identifier('missingType.iterableValue')->build(); } foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($constantType) as [$name, $genericTypeNames]) { $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s with generic %s does not specify its types: %s', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $name, $genericTypeNames))->identifier('missingType.generics')->build(); } foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($constantType) as $callableType) { $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s type has no signature specified for %s.', $constantReflection->getDeclaringClass()->getDisplayName(), $constantName, $callableType->describe(VerbosityLevel::typeOnly())))->identifier('missingType.callable')->build(); } return $errors; } } */ final class ConstantsInTraitsRule implements Rule { /** * @var PhpVersion */ private $phpVersion; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function getNodeType() : string { return Node\Stmt\ClassConst::class; } /** * @param Node\Stmt\ClassConst $node */ public function processNode(Node $node, Scope $scope) : array { if ($this->phpVersion->supportsConstantsInTraits()) { return []; } if (!$scope->isInTrait()) { return []; } return [RuleErrorBuilder::message('Constant is declared inside a trait but is only supported on PHP 8.2 and later.')->identifier('classConstant.inTrait')->nonIgnorable()->build()]; } } */ final class NotAnalysedTraitRule implements Rule { public function getNodeType() : string { return CollectedDataNode::class; } public function processNode(Node $node, Scope $scope) : array { if ($node->isOnlyFilesAnalysis()) { return []; } $traitDeclarationData = $node->get(\PHPStan\Rules\Traits\TraitDeclarationCollector::class); $traitUseData = $node->get(\PHPStan\Rules\Traits\TraitUseCollector::class); $declaredTraits = []; foreach ($traitDeclarationData as $file => $declaration) { foreach ($declaration as [$name, $line]) { $declaredTraits[strtolower($name)] = [$file, $name, $line]; } } foreach ($traitUseData as $usedNamesData) { foreach ($usedNamesData as $usedNames) { foreach ($usedNames as $usedName) { unset($declaredTraits[strtolower($usedName)]); } } } $errors = []; foreach ($declaredTraits as [$file, $name, $line]) { $errors[] = RuleErrorBuilder::message(sprintf('Trait %s is used zero times and is not analysed.', $name))->file($file)->line($line)->identifier('trait.unused')->tip('See: https://phpstan.org/blog/how-phpstan-analyses-traits')->build(); } return $errors; } } */ final class TraitDeclarationCollector implements Collector { public function getNodeType() : string { return Node\Stmt\Trait_::class; } public function processNode(Node $node, Scope $scope) { if ($node->namespacedName === null) { return null; } return [$node->namespacedName->toString(), $node->getStartLine()]; } } */ final class ConflictingTraitConstantsRule implements Rule { /** * @var InitializerExprTypeResolver */ private $initializerExprTypeResolver; public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; } public function getNodeType() : string { return Node\Stmt\ClassConst::class; } public function processNode(Node $node, Scope $scope) : array { if (!$scope->isInClass()) { return []; } $classReflection = $scope->getClassReflection(); $traitConstants = []; foreach ($classReflection->getTraits(\true) as $trait) { foreach ($trait->getNativeReflection()->getReflectionConstants() as $constant) { $traitConstants[] = $constant; } } $errors = []; foreach ($node->consts as $const) { foreach ($traitConstants as $traitConstant) { if ($traitConstant->getName() !== $const->name->toString()) { continue; } foreach ($this->processSingleConstant($classReflection, $traitConstant, $node, $const->value) as $error) { $errors[] = $error; } } } return $errors; } /** * @return list */ private function processSingleConstant(ClassReflection $classReflection, ReflectionClassConstant $traitConstant, Node\Stmt\ClassConst $classConst, Node\Expr $valueExpr) : array { $errors = []; if ($traitConstant->isPublic()) { if ($classConst->isProtected()) { $errors[] = RuleErrorBuilder::message(sprintf('Protected constant %s::%s overriding public constant %s::%s should also be public.', $classReflection->getDisplayName(), $traitConstant->getName(), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName()))->nonIgnorable()->identifier('classConstant.visibility')->build(); } elseif ($classConst->isPrivate()) { $errors[] = RuleErrorBuilder::message(sprintf('Private constant %s::%s overriding public constant %s::%s should also be public.', $classReflection->getDisplayName(), $traitConstant->getName(), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName()))->nonIgnorable()->identifier('classConstant.visibility')->build(); } } elseif ($traitConstant->isProtected()) { if ($classConst->isPublic()) { $errors[] = RuleErrorBuilder::message(sprintf('Public constant %s::%s overriding protected constant %s::%s should also be protected.', $classReflection->getDisplayName(), $traitConstant->getName(), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName()))->nonIgnorable()->identifier('classConstant.visibility')->build(); } elseif ($classConst->isPrivate()) { $errors[] = RuleErrorBuilder::message(sprintf('Private constant %s::%s overriding protected constant %s::%s should also be protected.', $classReflection->getDisplayName(), $traitConstant->getName(), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName()))->nonIgnorable()->identifier('classConstant.visibility')->build(); } } elseif ($traitConstant->isPrivate()) { if ($classConst->isPublic()) { $errors[] = RuleErrorBuilder::message(sprintf('Public constant %s::%s overriding private constant %s::%s should also be private.', $classReflection->getDisplayName(), $traitConstant->getName(), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName()))->nonIgnorable()->identifier('classConstant.visibility')->build(); } elseif ($classConst->isProtected()) { $errors[] = RuleErrorBuilder::message(sprintf('Protected constant %s::%s overriding private constant %s::%s should also be private.', $classReflection->getDisplayName(), $traitConstant->getName(), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName()))->nonIgnorable()->identifier('classConstant.visibility')->build(); } } if ($traitConstant->isFinal()) { if (!$classConst->isFinal()) { $errors[] = RuleErrorBuilder::message(sprintf('Non-final constant %s::%s overriding final constant %s::%s should also be final.', $classReflection->getDisplayName(), $traitConstant->getName(), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName()))->nonIgnorable()->identifier('classConstant.nonFinal')->build(); } } elseif ($classConst->isFinal()) { $errors[] = RuleErrorBuilder::message(sprintf('Final constant %s::%s overriding non-final constant %s::%s should also be non-final.', $classReflection->getDisplayName(), $traitConstant->getName(), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName()))->nonIgnorable()->identifier('classConstant.final')->build(); } $traitNativeType = $traitConstant->getType(); $constantNativeType = $classConst->type; $traitDeclaringClass = $traitConstant->getDeclaringClass(); if ($traitNativeType === null) { if ($constantNativeType !== null) { $constantNativeTypeType = ParserNodeTypeToPHPStanType::resolve($constantNativeType, $classReflection); $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s (%s) overriding constant %s::%s should not have a native type.', $classReflection->getDisplayName(), $traitConstant->getName(), $constantNativeTypeType->describe(VerbosityLevel::typeOnly()), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName()))->nonIgnorable()->identifier('classConstant.nativeType')->build(); } } elseif ($constantNativeType === null) { $traitNativeTypeType = TypehintHelper::decideTypeFromReflection($traitNativeType, null, $traitDeclaringClass->getName()); $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s overriding constant %s::%s (%s) should also have native type %s.', $classReflection->getDisplayName(), $traitConstant->getName(), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName(), $traitNativeTypeType->describe(VerbosityLevel::typeOnly()), $traitNativeTypeType->describe(VerbosityLevel::typeOnly())))->nonIgnorable()->identifier('classConstant.missingNativeType')->build(); } else { $traitNativeTypeType = TypehintHelper::decideTypeFromReflection($traitNativeType, null, $traitDeclaringClass->getName()); $constantNativeTypeType = ParserNodeTypeToPHPStanType::resolve($constantNativeType, $classReflection); if (!$traitNativeTypeType->equals($constantNativeTypeType)) { $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s (%s) overriding constant %s::%s (%s) should have the same native type %s.', $classReflection->getDisplayName(), $traitConstant->getName(), $constantNativeTypeType->describe(VerbosityLevel::typeOnly()), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName(), $traitNativeTypeType->describe(VerbosityLevel::typeOnly()), $traitNativeTypeType->describe(VerbosityLevel::typeOnly())))->nonIgnorable()->identifier('classConstant.nativeType')->build(); } } $classConstantValueType = $this->initializerExprTypeResolver->getType($valueExpr, InitializerExprContext::fromClassReflection($classReflection)); $traitConstantValueType = $this->initializerExprTypeResolver->getType($traitConstant->getValueExpression(), InitializerExprContext::fromClass($traitDeclaringClass->getName(), $traitDeclaringClass->getFileName() !== \false ? $traitDeclaringClass->getFileName() : null)); if (!$classConstantValueType->equals($traitConstantValueType)) { $errors[] = RuleErrorBuilder::message(sprintf('Constant %s::%s with value %s overriding constant %s::%s with different value %s should have the same value.', $classReflection->getDisplayName(), $traitConstant->getName(), $classConstantValueType->describe(VerbosityLevel::value()), $traitConstant->getDeclaringClass()->getName(), $traitConstant->getName(), $traitConstantValueType->describe(VerbosityLevel::value())))->nonIgnorable()->identifier('classConstant.value')->build(); } return $errors; } } > */ final class TraitUseCollector implements Collector { public function getNodeType() : string { return Node\Stmt\TraitUse::class; } /** * @return list */ public function processNode(Node $node, Scope $scope) : array { return array_values(array_map(static function (Node\Name $traitName) { return $traitName->toString(); }, $node->traits)); } } reflectionProvider = $reflectionProvider; } /** * @param string[] $parameterNames * @param Node[] $statements * @param 'constructor.unusedParameter'|'closure.unusedUse' $identifier * @return list */ public function getUnusedParameters(Scope $scope, array $parameterNames, array $statements, string $unusedParameterMessage, string $identifier) : array { $unusedParameters = array_fill_keys($parameterNames, \true); foreach ($this->getUsedVariables($scope, $statements) as $variableName) { if (!isset($unusedParameters[$variableName])) { continue; } unset($unusedParameters[$variableName]); } $errors = []; foreach (array_keys($unusedParameters) as $name) { $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($unusedParameterMessage, $name))->identifier($identifier)->build(); } return $errors; } /** * @param Node[]|Node|scalar|null $node * @return string[] */ private function getUsedVariables(Scope $scope, $node) : array { $variableNames = []; if ($node instanceof Node) { if ($node instanceof Node\Expr\FuncCall && $node->name instanceof Node\Name) { $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); if ($functionName === 'func_get_args' || $functionName === 'get_defined_vars') { return $scope->getDefinedVariables(); } } if ($node instanceof Node\Expr\Variable && is_string($node->name) && $node->name !== 'this') { return [$node->name]; } if ($node instanceof Node\Expr\ClosureUse && is_string($node->var->name)) { return [$node->var->name]; } if ($node instanceof Node\Expr\FuncCall && $node->name instanceof Node\Name && (string) $node->name === 'compact') { foreach ($node->getArgs() as $arg) { $argType = $scope->getType($arg->value); if (!$argType instanceof ConstantStringType) { continue; } $variableNames[] = $argType->getValue(); } } foreach ($node->getSubNodeNames() as $subNodeName) { if ($node instanceof Node\Expr\Closure && $subNodeName !== 'uses') { continue; } $subNode = $node->{$subNodeName}; $variableNames = array_merge($variableNames, $this->getUsedVariables($scope, $subNode)); } } elseif (is_array($node)) { foreach ($node as $subNode) { $variableNames = array_merge($variableNames, $this->getUsedVariables($scope, $subNode)); } } return $variableNames; } } reflectionProvider = $reflectionProvider; $this->checkNullables = $checkNullables; $this->checkThisOnly = $checkThisOnly; $this->checkUnionTypes = $checkUnionTypes; $this->checkExplicitMixed = $checkExplicitMixed; $this->checkImplicitMixed = $checkImplicitMixed; $this->newRuleLevelHelper = $newRuleLevelHelper; $this->checkBenevolentUnionTypes = $checkBenevolentUnionTypes; } /** @api */ public function isThis(Expr $expression) : bool { return $expression instanceof Expr\Variable && $expression->name === 'this'; } /** @api */ public function accepts(Type $acceptingType, Type $acceptedType, bool $strictTypes) : bool { return $this->acceptsWithReason($acceptingType, $acceptedType, $strictTypes)->result; } private function transformCommonType(Type $type) : Type { if (!$this->checkExplicitMixed && !$this->checkImplicitMixed) { return $type; } return TypeTraverser::map($type, function (Type $type, callable $traverse) { if ($type instanceof TemplateMixedType) { if (!$this->newRuleLevelHelper) { return $type->toStrictMixedType(); } if ($this->checkExplicitMixed) { return $type->toStrictMixedType(); } } if ($type instanceof MixedType && ($type->isExplicitMixed() && $this->checkExplicitMixed || !$type->isExplicitMixed() && $this->checkImplicitMixed)) { return new StrictMixedType(); } return $traverse($type); }); } /** * @return array{Type, bool} */ private function transformAcceptedType(Type $acceptingType, Type $acceptedType) : array { $checkForUnion = $this->checkUnionTypes; $acceptedType = TypeTraverser::map($acceptedType, function (Type $acceptedType, callable $traverse) use($acceptingType, &$checkForUnion) : Type { if ($acceptedType instanceof CallableType) { if ($acceptedType->isCommonCallable()) { return $acceptedType; } return new CallableType($acceptedType->getParameters(), $traverse($this->transformCommonType($acceptedType->getReturnType())), $acceptedType->isVariadic(), $acceptedType->getTemplateTypeMap(), $acceptedType->getResolvedTemplateTypeMap(), $acceptedType->getTemplateTags(), $acceptedType->isPure()); } if ($acceptedType instanceof ClosureType) { if ($acceptedType->isCommonCallable()) { return $acceptedType; } return new ClosureType($acceptedType->getParameters(), $traverse($this->transformCommonType($acceptedType->getReturnType())), $acceptedType->isVariadic(), $acceptedType->getTemplateTypeMap(), $acceptedType->getResolvedTemplateTypeMap(), $acceptedType->getCallSiteVarianceMap(), $acceptedType->getTemplateTags(), $acceptedType->getThrowPoints(), $acceptedType->getImpurePoints(), $acceptedType->getInvalidateExpressions(), $acceptedType->getUsedVariables(), $acceptedType->acceptsNamedArguments()); } if (!$this->checkNullables && !$acceptingType instanceof NullType && !$acceptedType instanceof NullType && !$acceptedType instanceof BenevolentUnionType) { return $traverse(TypeCombinator::removeNull($acceptedType)); } if ($this->checkBenevolentUnionTypes) { if ($acceptedType instanceof BenevolentUnionType) { $checkForUnion = \true; return $traverse(TypeUtils::toStrictUnion($acceptedType)); } } return $traverse($this->transformCommonType($acceptedType)); }); return [$acceptedType, $checkForUnion]; } public function acceptsWithReason(Type $acceptingType, Type $acceptedType, bool $strictTypes) : \PHPStan\Rules\RuleLevelHelperAcceptsResult { if ($this->newRuleLevelHelper) { [$acceptedType, $checkForUnion] = $this->transformAcceptedType($acceptingType, $acceptedType); $acceptingType = $this->transformCommonType($acceptingType); $accepts = $acceptingType->acceptsWithReason($acceptedType, $strictTypes); return new \PHPStan\Rules\RuleLevelHelperAcceptsResult($checkForUnion ? $accepts->yes() : !$accepts->no(), $accepts->reasons); } $checkForUnion = $this->checkUnionTypes; if ($this->checkBenevolentUnionTypes) { $traverse = static function (Type $type, callable $traverse) use(&$checkForUnion) : Type { if ($type instanceof BenevolentUnionType) { $checkForUnion = \true; return TypeUtils::toStrictUnion($type); } return $traverse($type); }; $acceptedType = TypeTraverser::map($acceptedType, $traverse); } if ($this->checkExplicitMixed) { $traverse = static function (Type $type, callable $traverse) : Type { if ($type instanceof TemplateMixedType) { return $type->toStrictMixedType(); } if ($type instanceof MixedType && $type->isExplicitMixed()) { return new StrictMixedType(); } return $traverse($type); }; $acceptingType = TypeTraverser::map($acceptingType, $traverse); $acceptedType = TypeTraverser::map($acceptedType, $traverse); } if ($this->checkImplicitMixed) { $traverse = static function (Type $type, callable $traverse) : Type { if ($type instanceof TemplateMixedType) { return $type->toStrictMixedType(); } if ($type instanceof MixedType && !$type->isExplicitMixed()) { return new StrictMixedType(); } return $traverse($type); }; $acceptingType = TypeTraverser::map($acceptingType, $traverse); $acceptedType = TypeTraverser::map($acceptedType, $traverse); } if (!$this->checkNullables && !$acceptingType instanceof NullType && !$acceptedType instanceof NullType && !$acceptedType instanceof BenevolentUnionType) { $acceptedType = TypeCombinator::removeNull($acceptedType); } $accepts = $acceptingType->acceptsWithReason($acceptedType, $strictTypes); if ($accepts->yes()) { return new \PHPStan\Rules\RuleLevelHelperAcceptsResult(\true, $accepts->reasons); } if ($acceptingType instanceof UnionType) { $reasons = []; foreach ($acceptingType->getTypes() as $innerType) { $accepts = self::acceptsWithReason($innerType, $acceptedType, $strictTypes); if ($accepts->result) { return $accepts; } $reasons = array_merge($reasons, $accepts->reasons); } return new \PHPStan\Rules\RuleLevelHelperAcceptsResult(\false, $reasons); } if ($acceptedType->isArray()->yes() && $acceptingType->isArray()->yes() && ($acceptedType->isConstantArray()->no() || !$acceptedType->isIterableAtLeastOnce()->no()) && $acceptingType->isConstantArray()->no()) { if ($acceptingType->isIterableAtLeastOnce()->yes() && !$acceptedType->isIterableAtLeastOnce()->yes()) { $verbosity = VerbosityLevel::getRecommendedLevelByType($acceptingType, $acceptedType); return new \PHPStan\Rules\RuleLevelHelperAcceptsResult(\false, [sprintf('%s %s empty.', $acceptedType->describe($verbosity), $acceptedType->isIterableAtLeastOnce()->no() ? 'is' : 'might be')]); } if ($acceptingType->isList()->yes() && !$acceptedType->isList()->yes()) { $report = $checkForUnion || $acceptedType->isList()->no(); if ($report) { $verbosity = VerbosityLevel::getRecommendedLevelByType($acceptingType, $acceptedType); return new \PHPStan\Rules\RuleLevelHelperAcceptsResult(\false, [sprintf('%s %s a list.', $acceptedType->describe($verbosity), $acceptedType->isList()->no() ? 'is not' : 'might not be')]); } } return self::acceptsWithReason($acceptingType->getIterableKeyType(), $acceptedType->getIterableKeyType(), $strictTypes)->and(self::acceptsWithReason($acceptingType->getIterableValueType(), $acceptedType->getIterableValueType(), $strictTypes)); } return new \PHPStan\Rules\RuleLevelHelperAcceptsResult($checkForUnion ? $accepts->yes() : !$accepts->no(), $accepts->reasons); } /** * @api * @param callable(Type $type): bool $unionTypeCriteriaCallback */ public function findTypeToCheck(Scope $scope, Expr $var, string $unknownClassErrorPattern, callable $unionTypeCriteriaCallback) : \PHPStan\Rules\FoundTypeResult { if ($this->checkThisOnly && !$this->isThis($var)) { return new \PHPStan\Rules\FoundTypeResult(new ErrorType(), [], [], null); } $type = $scope->getType($var); return $this->findTypeToCheckImplementation($scope, $var, $type, $unknownClassErrorPattern, $unionTypeCriteriaCallback, \true); } /** @param callable(Type $type): bool $unionTypeCriteriaCallback */ private function findTypeToCheckImplementation(Scope $scope, Expr $var, Type $type, string $unknownClassErrorPattern, callable $unionTypeCriteriaCallback, bool $isTopLevel = \false) : \PHPStan\Rules\FoundTypeResult { if (!$this->checkNullables && !$type->isNull()->yes()) { $type = TypeCombinator::removeNull($type); } if ($this->newRuleLevelHelper) { if (($this->checkExplicitMixed || $this->checkImplicitMixed) && $type instanceof MixedType && ($type->isExplicitMixed() ? $this->checkExplicitMixed : $this->checkImplicitMixed)) { return new \PHPStan\Rules\FoundTypeResult($type instanceof TemplateMixedType ? $type->toStrictMixedType() : new StrictMixedType(), [], [], null); } } else { if ($this->checkExplicitMixed && $type instanceof MixedType && !$type instanceof TemplateMixedType && $type->isExplicitMixed()) { return new \PHPStan\Rules\FoundTypeResult(new StrictMixedType(), [], [], null); } if ($this->checkImplicitMixed && $type instanceof MixedType && !$type instanceof TemplateMixedType && !$type->isExplicitMixed()) { return new \PHPStan\Rules\FoundTypeResult(new StrictMixedType(), [], [], null); } } if ($type instanceof MixedType || $type instanceof NeverType) { return new \PHPStan\Rules\FoundTypeResult(new ErrorType(), [], [], null); } if (!$this->newRuleLevelHelper) { if ($isTopLevel && $type instanceof StaticType) { $type = $type->getStaticObjectType(); } } $errors = []; $hasClassExistsClass = \false; $directClassNames = []; if ($isTopLevel) { $directClassNames = $type->getObjectClassNames(); foreach ($directClassNames as $referencedClass) { if ($this->reflectionProvider->hasClass($referencedClass)) { $classReflection = $this->reflectionProvider->getClass($referencedClass); if (!$classReflection->isTrait()) { continue; } } if ($scope->isInClassExists($referencedClass)) { $hasClassExistsClass = \true; continue; } $errors[] = \PHPStan\Rules\RuleErrorBuilder::message(sprintf($unknownClassErrorPattern, $referencedClass))->line($var->getStartLine())->identifier('class.notFound')->discoveringSymbolsTip()->build(); } } if (count($errors) > 0 || $hasClassExistsClass) { return new \PHPStan\Rules\FoundTypeResult(new ErrorType(), [], $errors, null); } if (!$this->checkUnionTypes && $type instanceof ObjectWithoutClassType) { return new \PHPStan\Rules\FoundTypeResult(new ErrorType(), [], [], null); } if ($this->newRuleLevelHelper) { if ($type instanceof UnionType) { $shouldFilterUnion = !$this->checkUnionTypes && !$type instanceof BenevolentUnionType || !$this->checkBenevolentUnionTypes && $type instanceof BenevolentUnionType; $newTypes = []; foreach ($type->getTypes() as $innerType) { if ($shouldFilterUnion && !$unionTypeCriteriaCallback($innerType)) { continue; } $newTypes[] = $this->findTypeToCheckImplementation($scope, $var, $innerType, $unknownClassErrorPattern, $unionTypeCriteriaCallback)->getType(); } if (count($newTypes) > 0) { $newUnion = TypeCombinator::union(...$newTypes); if (!$this->checkBenevolentUnionTypes && $type instanceof BenevolentUnionType) { $newUnion = TypeUtils::toBenevolentUnion($newUnion); } return new \PHPStan\Rules\FoundTypeResult($newUnion, $directClassNames, [], null); } } if ($type instanceof IntersectionType) { $newTypes = []; foreach ($type->getTypes() as $innerType) { $newTypes[] = $this->findTypeToCheckImplementation($scope, $var, $innerType, $unknownClassErrorPattern, $unionTypeCriteriaCallback)->getType(); } return new \PHPStan\Rules\FoundTypeResult(TypeCombinator::intersect(...$newTypes), $directClassNames, [], null); } } else { if (!$this->checkUnionTypes && $type instanceof UnionType && !$type instanceof BenevolentUnionType || !$this->checkBenevolentUnionTypes && $type instanceof BenevolentUnionType) { $newTypes = []; foreach ($type->getTypes() as $innerType) { if (!$unionTypeCriteriaCallback($innerType)) { continue; } $newTypes[] = $innerType; } if (count($newTypes) > 0) { return new \PHPStan\Rules\FoundTypeResult(TypeCombinator::union(...$newTypes), $directClassNames, [], null); } } } $tip = null; if ($type instanceof UnionType && count($type->getTypes()) === 2 && $type->getTypes()[0] instanceof ObjectType && $type->getTypes()[1] instanceof ObjectType && $type->getTypes()[0]->getClassName() === 'PhpParser\\Node\\Arg' && $type->getTypes()[1]->getClassName() === 'PhpParser\\Node\\VariadicPlaceholder' && !$unionTypeCriteriaCallback($type)) { $tip = 'Use ->getArgs() instead of ->args.'; } return new \PHPStan\Rules\FoundTypeResult($type, $directClassNames, [], $tip); } } container = $container; } public function create() : \PHPStan\Collectors\Registry { return new \PHPStan\Collectors\Registry($this->container->getServicesByTag(self::COLLECTOR_TAG)); } } collectors[$collector->getNodeType()][] = $collector; } } /** * @template TNodeType of Node * @param class-string $nodeType * @return array> */ public function getCollectors(string $nodeType) : array { if (!isset($this->cache[$nodeType])) { $parentNodeTypes = [$nodeType] + class_parents($nodeType) + class_implements($nodeType); $collectors = []; foreach ($parentNodeTypes as $parentNodeType) { foreach ($this->collectors[$parentNodeType] ?? [] as $collector) { $collectors[] = $collector; } } $this->cache[$nodeType] = $collectors; } /** * @var array> $selectedCollectors */ $selectedCollectors = $this->cache[$nodeType]; return $selectedCollectors; } } */ public function getNodeType() : string; /** * @param TNodeType $node * @return TValue|null Collected data */ public function processNode(Node $node, Scope $scope); } > */ private $collectorType; /** * @param mixed $data * @param class-string> $collectorType */ public function __construct($data, string $filePath, string $collectorType) { $this->data = $data; $this->filePath = $filePath; $this->collectorType = $collectorType; } /** * @return mixed */ public function getData() { return $this->data; } public function getFilePath() : string { return $this->filePath; } public function changeFilePath(string $newFilePath) : self { return new self($this->data, $newFilePath, $this->collectorType); } /** * @return class-string> */ public function getCollectorType() : string { return $this->collectorType; } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['data' => $this->data, 'filePath' => $this->filePath, 'collectorType' => $this->collectorType]; } /** * @param mixed[] $json */ public static function decode(array $json) : self { return new self($json['data'], $json['filePath'], $json['collectorType']); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self($properties['data'], $properties['filePath'], $properties['collectorType']); } } noImplicitWildcard = $noImplicitWildcard; foreach ($analyseExcludes as $exclude) { $len = strlen($exclude); $trailingDirSeparator = $len > 0 && in_array($exclude[$len - 1], ['\\', '/'], \true); $normalized = $fileHelper->normalizePath($exclude); if ($trailingDirSeparator) { $normalized .= DIRECTORY_SEPARATOR; } if (self::isFnmatchPattern($normalized)) { $this->fnmatchAnalyseExcludes[] = $normalized; } else { if ($this->noImplicitWildcard) { if (is_file($normalized)) { $this->literalAnalyseFilesExcludes[] = $normalized; } elseif (is_dir($normalized)) { if (!$trailingDirSeparator) { $normalized .= DIRECTORY_SEPARATOR; } $this->literalAnalyseDirectoryExcludes[] = $normalized; } } else { $this->literalAnalyseExcludes[] = $fileHelper->absolutizePath($normalized); } } } $isWindows = DIRECTORY_SEPARATOR === '\\'; if ($isWindows) { $this->fnmatchFlags = FNM_NOESCAPE | FNM_CASEFOLD; } else { $this->fnmatchFlags = 0; } } public function isExcludedFromAnalysing(string $file) : bool { foreach ($this->literalAnalyseExcludes as $exclude) { if (str_starts_with($file, $exclude)) { return \true; } } if ($this->noImplicitWildcard) { foreach ($this->literalAnalyseDirectoryExcludes as $exclude) { if (str_starts_with($file, $exclude)) { return \true; } } foreach ($this->literalAnalyseFilesExcludes as $exclude) { if ($file === $exclude) { return \true; } } } foreach ($this->fnmatchAnalyseExcludes as $exclude) { if (fnmatch($exclude, $file, $this->fnmatchFlags)) { return \true; } } return \false; } public static function isAbsolutePath(string $path) : bool { if (DIRECTORY_SEPARATOR === '/') { if (str_starts_with($path, '/')) { return \true; } } elseif (substr($path, 1, 1) === ':') { return \true; } return \false; } public static function isFnmatchPattern(string $path) : bool { return preg_match('~[*?[\\]]~', $path) > 0; } } files = $files; $this->onlyFiles = $onlyFiles; } /** * @return string[] */ public function getFiles() : array { return $this->files; } public function isOnlyFiles() : bool { return $this->onlyFiles; } } |null */ private $fileHashes = null; /** @var array|null */ private $filePaths = null; /** * @param string[] $analysedPaths * @param string[] $analysedPathsFromConfig * @param string[] $scanFiles * @param string[] $scanDirectories */ public function __construct(\PHPStan\File\FileFinder $analyseFileFinder, \PHPStan\File\FileFinder $scanFileFinder, array $analysedPaths, array $analysedPathsFromConfig, array $scanFiles, array $scanDirectories) { $this->analyseFileFinder = $analyseFileFinder; $this->scanFileFinder = $scanFileFinder; $this->analysedPaths = $analysedPaths; $this->analysedPathsFromConfig = $analysedPathsFromConfig; $this->scanFiles = $scanFiles; $this->scanDirectories = $scanDirectories; } /** * @param array $filePaths */ public function initialize(array $filePaths) : void { $finderResult = $this->analyseFileFinder->findFiles($this->analysedPaths); $fileHashes = []; foreach (array_unique(array_merge($finderResult->getFiles(), $filePaths, $this->getScannedFiles($finderResult->getFiles()))) as $filePath) { $fileHashes[$filePath] = $this->getFileHash($filePath); } $this->fileHashes = $fileHashes; $this->filePaths = $filePaths; } public function getChanges() : \PHPStan\File\FileMonitorResult { if ($this->fileHashes === null || $this->filePaths === null) { throw new ShouldNotHappenException(); } $finderResult = $this->analyseFileFinder->findFiles($this->analysedPaths); $oldFileHashes = $this->fileHashes; $fileHashes = []; $newFiles = []; $changedFiles = []; $deletedFiles = []; $filePaths = array_unique(array_merge($finderResult->getFiles(), $this->filePaths, $this->getScannedFiles($finderResult->getFiles()))); foreach ($filePaths as $filePath) { if (!array_key_exists($filePath, $oldFileHashes)) { $newFiles[] = $filePath; $fileHashes[$filePath] = $this->getFileHash($filePath); continue; } $oldHash = $oldFileHashes[$filePath]; unset($oldFileHashes[$filePath]); $newHash = $this->getFileHash($filePath); $fileHashes[$filePath] = $newHash; if ($oldHash === $newHash) { continue; } $changedFiles[] = $filePath; } $this->fileHashes = $fileHashes; foreach (array_keys($oldFileHashes) as $file) { $deletedFiles[] = $file; } return new \PHPStan\File\FileMonitorResult($newFiles, $changedFiles, $deletedFiles, count($fileHashes)); } private function getFileHash(string $filePath) : string { $hash = sha1_file($filePath); if ($hash === \false) { throw new \PHPStan\File\CouldNotReadFileException($filePath); } return $hash; } /** * @param string[] $allAnalysedFiles * @return array */ private function getScannedFiles(array $allAnalysedFiles) : array { $scannedFiles = $this->scanFiles; $analysedDirectories = []; foreach (array_merge($this->analysedPaths, $this->analysedPathsFromConfig) as $analysedPath) { if (is_file($analysedPath)) { continue; } if (!is_dir($analysedPath)) { continue; } $analysedDirectories[] = $analysedPath; } $directories = array_unique(array_merge($analysedDirectories, $this->scanDirectories)); foreach ($this->scanFileFinder->findFiles($directories)->getFiles() as $file) { $scannedFiles[] = $file; } return array_diff($scannedFiles, $allAnalysedFiles); } } fallbackRelativePathHelper = $fallbackRelativePathHelper; if ($directorySeparator === null) { $directorySeparator = DIRECTORY_SEPARATOR; } $this->directorySeparator = $directorySeparator; $pathBeginning = null; $pathToTrimArray = null; $trimBeginning = static function (string $path) : array { if (str_starts_with($path, '/')) { return ['/', substr($path, 1)]; } elseif (substr($path, 1, 1) === ':') { return [substr($path, 0, 3), substr($path, 3)]; } return ['', $path]; }; if (!in_array($currentWorkingDirectory, ['', '/'], \true) && !(strlen($currentWorkingDirectory) === 3 && substr($currentWorkingDirectory, 1, 1) === ':')) { [$pathBeginning, $currentWorkingDirectory] = $trimBeginning($currentWorkingDirectory); $pathToTrimArray = explode($directorySeparator, $currentWorkingDirectory); } foreach ($analysedPaths as $pathNumber => $path) { [$tempPathBeginning, $path] = $trimBeginning($path); $pathArray = explode($directorySeparator, $path); $pathTempParts = []; $pathArraySize = count($pathArray); foreach ($pathArray as $i => $pathPart) { if ($i === $pathArraySize - 1 && str_ends_with($pathPart, '.php')) { continue; } if (!isset($pathToTrimArray[$i])) { if ($pathNumber !== 0) { $pathToTrimArray = $pathTempParts; continue 2; } } elseif ($pathToTrimArray[$i] !== $pathPart) { $pathToTrimArray = $pathTempParts; continue 2; } $pathTempParts[] = $pathPart; } $pathBeginning = $tempPathBeginning; $pathToTrimArray = $pathTempParts; } if ($pathToTrimArray === null || count($pathToTrimArray) === 0) { return; } $pathToTrim = $pathBeginning . implode($directorySeparator, $pathToTrimArray); $realPathToTrim = realpath($pathToTrim); if ($realPathToTrim !== \false) { $pathToTrim = $realPathToTrim; } $this->pathToTrim = $pathToTrim; } public function getRelativePath(string $filename) : string { if ($this->pathToTrim !== null && str_starts_with($filename, $this->pathToTrim)) { return ltrim(substr($filename, strlen($this->pathToTrim)), $this->directorySeparator); } return $this->fallbackRelativePathHelper->getRelativePath($filename); } } parentDirectory = $parentDirectory; } public function getRelativePath(string $filename) : string { return implode('/', $this->getFilenameParts($filename)); } /** * @return string[] */ public function getFilenameParts(string $filename) : array { $schemePosition = strpos($filename, '://'); if ($schemePosition !== \false) { $filename = substr($filename, $schemePosition + 3); } $parentParts = explode('/', trim(str_replace('\\', '/', $this->parentDirectory), '/')); $parentPartsCount = count($parentParts); $filenameParts = explode('/', trim(str_replace('\\', '/', $filename), '/')); $filenamePartsCount = count($filenameParts); $i = 0; for (; $i < $filenamePartsCount; $i++) { if ($parentPartsCount < $i + 1) { break; } $parentPath = implode('/', array_slice($parentParts, 0, $i + 1)); $filenamePath = implode('/', array_slice($filenameParts, 0, $i + 1)); if ($parentPath !== $filenamePath) { break; } } if ($i === 0) { return [$filename]; } $dotsCount = $parentPartsCount - $i; if ($dotsCount < 0) { throw new ShouldNotHappenException(); } return array_merge(array_fill(0, $dotsCount, '..'), array_slice($filenameParts, $i)); } } fileHelper = $fileHelper; } public function getRelativePath(string $filename) : string { $cwd = $this->fileHelper->getWorkingDirectory(); if ($cwd !== '' && str_starts_with($filename, $cwd)) { return substr($filename, strlen($cwd) + 1); } return $filename; } } currentWorkingDirectory = $currentWorkingDirectory; } public function getRelativePath(string $filename) : string { if ($this->currentWorkingDirectory !== '' && str_starts_with($filename, $this->currentWorkingDirectory)) { return str_replace('\\', '/', substr($filename, strlen($this->currentWorkingDirectory) + 1)); } return str_replace('\\', '/', $filename); } } , analyseAndScan?: array}|null */ private $excludePaths; /** * @param string[] $obsoleteExcludesAnalyse * @param array{analyse?: array, analyseAndScan?: array}|null $excludePaths */ public function __construct(\PHPStan\File\FileExcluderRawFactory $fileExcluderRawFactory, array $obsoleteExcludesAnalyse, ?array $excludePaths) { $this->fileExcluderRawFactory = $fileExcluderRawFactory; $this->obsoleteExcludesAnalyse = $obsoleteExcludesAnalyse; $this->excludePaths = $excludePaths; } public function createAnalyseFileExcluder() : \PHPStan\File\FileExcluder { if ($this->excludePaths === null) { return $this->fileExcluderRawFactory->create($this->obsoleteExcludesAnalyse); } $paths = []; if (array_key_exists('analyse', $this->excludePaths)) { $paths = $this->excludePaths['analyse']; } if (array_key_exists('analyseAndScan', $this->excludePaths)) { $paths = array_merge($paths, $this->excludePaths['analyseAndScan']); } return $this->fileExcluderRawFactory->create(array_values(array_unique($paths))); } public function createScanFileExcluder() : \PHPStan\File\FileExcluder { if ($this->excludePaths === null) { return $this->fileExcluderRawFactory->create($this->obsoleteExcludesAnalyse); } $paths = []; if (array_key_exists('analyseAndScan', $this->excludePaths)) { $paths = $this->excludePaths['analyseAndScan']; } return $this->fileExcluderRawFactory->create(array_values(array_unique($paths))); } } newFiles = $newFiles; $this->changedFiles = $changedFiles; $this->deletedFiles = $deletedFiles; $this->totalFilesCount = $totalFilesCount; } /** * @return string[] */ public function getChangedFiles() : array { return $this->changedFiles; } public function hasAnyChanges() : bool { return count($this->newFiles) > 0 || count($this->changedFiles) > 0 || count($this->deletedFiles) > 0; } public function getTotalFilesCount() : int { return $this->totalFilesCount; } } fileExcluder = $fileExcluder; $this->fileHelper = $fileHelper; $this->fileExtensions = $fileExtensions; } /** * @param string[] $paths */ public function findFiles(array $paths) : \PHPStan\File\FileFinderResult { $onlyFiles = \true; $files = []; foreach ($paths as $path) { if (is_file($path)) { $files[] = $this->fileHelper->normalizePath($path); } elseif (!file_exists($path)) { throw new \PHPStan\File\PathNotFoundException($path); } else { $finder = new Finder(); $finder->followLinks(); foreach ($finder->files()->name('*.{' . implode(',', $this->fileExtensions) . '}')->in($path) as $fileInfo) { $files[] = $this->fileHelper->normalizePath($fileInfo->getPathname()); $onlyFiles = \false; } } } $files = array_values(array_unique(array_filter($files, function (string $file) : bool { return !$this->fileExcluder->isExcludedFromAnalysing($file); }))); return new \PHPStan\File\FileFinderResult($files, $onlyFiles); } } workingDirectory = $this->normalizePath($workingDirectory); } public function getWorkingDirectory() : string { return $this->workingDirectory; } /** @api */ public function absolutizePath(string $path) : string { if (DIRECTORY_SEPARATOR === '/') { if (str_starts_with($path, '/')) { return $path; } } elseif (substr($path, 1, 1) === ':') { return $path; } if (preg_match('~^[a-z0-9+\\-.]+://~i', $path) === 1) { return $path; } return rtrim($this->getWorkingDirectory(), '/\\') . DIRECTORY_SEPARATOR . ltrim($path, '/\\'); } /** @api */ public function normalizePath(string $originalPath, string $directorySeparator = DIRECTORY_SEPARATOR) : string { $isLocalPath = \false; if ($originalPath !== '') { if ($originalPath[0] === '/') { $isLocalPath = \true; } elseif (strlen($originalPath) >= 3 && $originalPath[1] === ':' && $originalPath[2] === '\\') { // e.g. C:\ $isLocalPath = \true; } } $matches = null; if (!$isLocalPath) { $matches = Strings::match($originalPath, '~^([a-z0-9+\\-.]+)://(.+)$~is'); } if ($matches !== null) { [, $scheme, $path] = $matches; $scheme = strtolower($scheme); } else { $scheme = null; $path = $originalPath; } $path = str_replace(['\\', '//', '///', '////'], '/', $path); $pathRoot = str_starts_with($path, '/') ? $directorySeparator : ''; $pathParts = explode('/', trim($path, '/')); $normalizedPathParts = []; foreach ($pathParts as $pathPart) { if ($pathPart === '.') { continue; } if ($pathPart === '..') { $removedPart = array_pop($normalizedPathParts); if ($scheme === 'phar' && $removedPart !== null && str_ends_with($removedPart, '.phar')) { $scheme = null; } } else { $normalizedPathParts[] = $pathPart; } } return ($scheme !== null ? $scheme . '://' : '') . $pathRoot . implode($directorySeparator, $normalizedPathParts); } } path = $path; parent::__construct(sprintf('Path %s does not exist', $path)); } public function getPath() : string { return $this->path; } } value = $value; } public static function createYes() : self { return self::$registry[self::YES] = self::$registry[self::YES] ?? new self(self::YES); } public static function createNo() : self { return self::$registry[self::NO] = self::$registry[self::NO] ?? new self(self::NO); } public static function createMaybe() : self { return self::$registry[self::MAYBE] = self::$registry[self::MAYBE] ?? new self(self::MAYBE); } public static function createFromBoolean(bool $value) : self { $yesNo = $value ? self::YES : self::NO; return self::$registry[$yesNo] = self::$registry[$yesNo] ?? new self($yesNo); } private static function create(int $value) : self { self::$registry[$value] = self::$registry[$value] ?? new self($value); return self::$registry[$value]; } public function yes() : bool { return $this->value === self::YES; } public function maybe() : bool { return $this->value === self::MAYBE; } public function no() : bool { return $this->value === self::NO; } public function toBooleanType() : BooleanType { if ($this->value === self::MAYBE) { return new BooleanType(); } return new ConstantBooleanType($this->value === self::YES); } public function and(self ...$operands) : self { $operandValues = array_column($operands, 'value'); $operandValues[] = $this->value; return self::create(min($operandValues)); } /** * @template T * @param T[] $objects * @param callable(T): self $callback */ public function lazyAnd(array $objects, callable $callback) : self { if ($this->no()) { return $this; } $results = []; foreach ($objects as $object) { $result = $callback($object); if ($result->no()) { return $result; } $results[] = $result; } return $this->and(...$results); } public function or(self ...$operands) : self { $operandValues = array_column($operands, 'value'); $operandValues[] = $this->value; return self::create(max($operandValues)); } /** * @template T * @param T[] $objects * @param callable(T): self $callback */ public function lazyOr(array $objects, callable $callback) : self { if ($this->yes()) { return $this; } $results = []; foreach ($objects as $object) { $result = $callback($object); if ($result->yes()) { return $result; } $results[] = $result; } return $this->or(...$results); } public static function extremeIdentity(self ...$operands) : self { if ($operands === []) { throw new \PHPStan\ShouldNotHappenException(); } $operandValues = array_column($operands, 'value'); $min = min($operandValues); $max = max($operandValues); return self::create($min === $max ? $min : self::MAYBE); } /** * @template T * @param T[] $objects * @param callable(T): self $callback */ public static function lazyExtremeIdentity(array $objects, callable $callback) : self { if ($objects === []) { throw new \PHPStan\ShouldNotHappenException(); } $lastResult = null; foreach ($objects as $object) { $result = $callback($object); if ($lastResult === null) { $lastResult = $result; continue; } if ($lastResult->equals($result)) { continue; } return self::createMaybe(); } return $lastResult; } public static function maxMin(self ...$operands) : self { if ($operands === []) { throw new \PHPStan\ShouldNotHappenException(); } $operandValues = array_column($operands, 'value'); return self::create(max($operandValues) > 0 ? 1 : min($operandValues)); } /** * @template T * @param T[] $objects * @param callable(T): self $callback */ public static function lazyMaxMin(array $objects, callable $callback) : self { $results = []; foreach ($objects as $object) { $result = $callback($object); if ($result->yes()) { return $result; } $results[] = $result; } return self::maxMin(...$results); } public function negate() : self { return self::create(-$this->value); } public function equals(self $other) : bool { return $this === $other; } public function compareTo(self $other) : ?self { if ($this->value > $other->value) { return $this; } elseif ($other->value > $this->value) { return $other; } return null; } public function describe() : string { static $labels = [self::NO => 'No', self::MAYBE => 'Maybe', self::YES => 'Yes']; return $labels[$this->value]; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return self::create($properties['value']); } } wrappedParser = $wrappedParser; $this->traverser = new NodeTraverser(); $this->traverser->addVisitor(new \PHPStan\Parser\CleaningVisitor()); $this->traverser->addVisitor(new \PHPStan\Parser\RemoveUnusedCodeByPhpVersionIdVisitor($phpVersion->getVersionString())); } public function parseFile(string $file) : array { return $this->clean($this->wrappedParser->parseFile($file)); } public function parseString(string $sourceCode) : array { return $this->clean($this->wrappedParser->parseString($sourceCode)); } /** * @param Stmt[] $ast * @return Stmt[] */ private function clean(array $ast) : array { /** @var Stmt[] */ return $this->traverser->traverse($ast); } } parser = $parser; $this->nameResolver = $nameResolver; } /** * @param string $file path to a file to parse * @return Node\Stmt[] */ public function parseFile(string $file) : array { try { return $this->parseString(FileReader::read($file)); } catch (\PHPStan\Parser\ParserErrorsException $e) { throw new \PHPStan\Parser\ParserErrorsException($e->getErrors(), $file); } } /** * @return Node\Stmt[] */ public function parseString(string $sourceCode) : array { $errorHandler = new Collecting(); $nodes = $this->parser->parse($sourceCode, $errorHandler); if ($errorHandler->hasErrors()) { throw new \PHPStan\Parser\ParserErrorsException($errorHandler->getErrors(), null); } if ($nodes === null) { throw new ShouldNotHappenException(); } $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor($this->nameResolver); /** @var array */ return $nodeTraverser->traverse($nodes); } } nodeFinder = new NodeFinder(); } public function enterNode(Node $node) : ?Node { if ($node instanceof Node\Stmt\Function_) { $node->stmts = $this->keepVariadicsAndYields($node->stmts); return $node; } if ($node instanceof Node\Stmt\ClassMethod && $node->stmts !== null) { $node->stmts = $this->keepVariadicsAndYields($node->stmts); return $node; } if ($node instanceof Node\Expr\Closure) { $node->stmts = $this->keepVariadicsAndYields($node->stmts); return $node; } return null; } /** * @param Node\Stmt[] $stmts * @return Node\Stmt[] */ private function keepVariadicsAndYields(array $stmts) : array { $results = $this->nodeFinder->find($stmts, static function (Node $node) : bool { if ($node instanceof Node\Expr\YieldFrom || $node instanceof Node\Expr\Yield_) { return \true; } if ($node instanceof Node\Expr\FuncCall && $node->name instanceof Node\Name) { return in_array($node->name->toLowerString(), ParametersAcceptor::VARIADIC_FUNCTIONS, \true); } if ($node instanceof Node\Expr\Closure || $node instanceof Node\Expr\ArrowFunction) { return \true; } return \false; }); $newStmts = []; foreach ($results as $result) { if ($result instanceof Node\Expr\Yield_ || $result instanceof Node\Expr\YieldFrom || $result instanceof Node\Expr\Closure || $result instanceof Node\Expr\ArrowFunction) { $newStmts[] = new Node\Stmt\Expression($result); continue; } if (!$result instanceof Node\Expr\FuncCall) { continue; } $newStmts[] = new Node\Stmt\Expression(new Node\Expr\FuncCall(new Node\Name\FullyQualified('func_get_args'))); } return $newStmts; } } depth = 0; return null; } public function enterNode(Node $node) : ?Node { if ($node instanceof Node\Expr\Instanceof_ && $this->depth > 0) { $node->setAttribute(self::ATTRIBUTE_NAME, \true); return null; } if ($node instanceof Node\Expr\StaticCall && $node->class instanceof Node\Name && $node->class->toLowerString() === 'phpstan\\type\\typetraverser' && $node->name instanceof Node\Identifier && $node->name->toLowerString() === 'map') { $this->depth++; } return null; } public function leaveNode(Node $node) : ?Node { if ($node instanceof Node\Expr\StaticCall && $node->class instanceof Node\Name && $node->class->toLowerString() === 'phpstan\\type\\typetraverser' && $node->name instanceof Node\Identifier && $node->name->toLowerString() === 'map') { $this->depth--; } return null; } } name instanceof Node\Expr\Closure) { $node->name->setAttribute(self::ATTRIBUTE_NAME, \true); } return null; } } isFirstClassCallable()) { return null; } if ($node->name instanceof Node\Expr\Assign && $node->name->expr instanceof Node\Expr\Closure) { $closure = $node->name->expr; } elseif ($node->name instanceof Node\Expr\Closure) { $closure = $node->name; } else { return null; } $args = $node->getArgs(); if (count($args) > 0) { $closure->setAttribute(self::ATTRIBUTE_NAME, $args); } return null; } } */ public $traits = []; public function enterNode(Node $node) : ?Node { if (!$node instanceof Node\Stmt\Trait_) { return null; } $this->traits[] = $node; return null; } } errors = $errors; $this->parsedFile = $parsedFile; parent::__construct(implode(', ', array_map(static function (Error $error) : string { return $error->getRawMessage(); }, $errors))); if (count($errors) > 0) { $this->attributes = $errors[0]->getAttributes(); } else { $this->attributes = []; } } /** * @return Error[] */ public function getErrors() : array { return $this->errors; } public function getParsedFile() : ?string { return $this->parsedFile; } /** * @return mixed[] */ public function getAttributes() : array { return $this->attributes; } } |null> */ private $typeStack = []; public function beforeTraverse(array $nodes) : ?array { $this->typeStack = []; return null; } public function enterNode(Node $node) : ?Node { if ($node instanceof Node\Stmt || $node instanceof Node\Expr\Match_) { if (count($this->typeStack) > 0) { $node->setAttribute(self::ATTRIBUTE_NAME, $this->typeStack[count($this->typeStack) - 1]); } } if ($node instanceof Node\FunctionLike) { $this->typeStack[] = null; } if ($node instanceof Node\Stmt\TryCatch) { $types = []; foreach (array_reverse($this->typeStack) as $stackTypes) { if ($stackTypes === null) { break; } foreach ($stackTypes as $type) { $types[] = $type; } } foreach ($node->catches as $catch) { foreach ($catch->types as $type) { $types[] = $type->toString(); } } $this->typeStack[] = $types; } return null; } public function leaveNode(Node $node) : ?Node { if (!$node instanceof Node\Stmt\TryCatch && !$node instanceof Node\FunctionLike) { return null; } array_pop($this->typeStack); return null; } } > */ private $typeStack = []; public function beforeTraverse(array $nodes) : ?array { $this->typeStack = []; return null; } public function enterNode(Node $node) : ?Node { if (!$node instanceof Node\Stmt && !$node instanceof Node\Expr\Closure) { return null; } if (count($this->typeStack) > 0) { $node->setAttribute(self::ATTRIBUTE_NAME, $this->typeStack); } $this->typeStack[] = get_class($node); return null; } public function leaveNode(Node $node) : ?Node { if (!$node instanceof Node\Stmt && !$node instanceof Node\Expr\Closure) { return null; } array_pop($this->typeStack); return null; } } > */ private $nodesPerLine = []; public function beforeTraverse(array $nodes) : ?array { $this->nodesPerLine = []; return null; } public function enterNode(Node $node) : ?Node { if (!$node instanceof Node\Stmt\Class_ || !$node->isAnonymous()) { return null; } $node = AnonymousClassNode::createFromClassNode($node); $node->setAttribute('anonymousClass', \true); // We keep this for backward compatibility $this->nodesPerLine[$node->getStartLine()][] = $node; return $node; } public function afterTraverse(array $nodes) : ?array { foreach ($this->nodesPerLine as $nodesOnLine) { if (count($nodesOnLine) === 1) { continue; } for ($i = 0; $i < count($nodesOnLine); $i++) { $nodesOnLine[$i]->setAttribute(self::ATTRIBUTE_LINE_INDEX, $i + 1); } } $this->nodesPerLine = []; return null; } } var instanceof Node\Expr\PropertyFetch || $node->var instanceof Node\Expr\StaticPropertyFetch) && $node->expr instanceof Node\Expr\New_) { $node->expr->setAttribute(self::ATTRIBUTE_NAME, $node->var); } } return null; } } name instanceof Node\Name) { $functionName = $node->name->toLowerString(); if ($functionName === 'curl_setopt') { $args = $node->getRawArgs(); if (isset($args[0])) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, \true); } } } return null; } } class instanceof Node\Name && $node->class->toLowerString() === 'closure' && $node->name instanceof Identifier && $node->name->toLowerString() === 'bind' && !$node->isFirstClassCallable()) { $args = $node->getArgs(); if (count($args) > 1) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, \true); } } return null; } } */ private $cachedNodesByString = []; /** * @var int */ private $cachedNodesByStringCount = 0; /** @var array */ private $parsedByString = []; public function __construct(\PHPStan\Parser\Parser $originalParser, int $cachedNodesByStringCountMax) { $this->originalParser = $originalParser; $this->cachedNodesByStringCountMax = $cachedNodesByStringCountMax; } /** * @param string $file path to a file to parse * @return Node\Stmt[] */ public function parseFile(string $file) : array { if ($this->cachedNodesByStringCountMax !== 0 && $this->cachedNodesByStringCount >= $this->cachedNodesByStringCountMax) { $this->cachedNodesByString = array_slice($this->cachedNodesByString, 1, null, \true); --$this->cachedNodesByStringCount; } $sourceCode = FileReader::read($file); if (!isset($this->cachedNodesByString[$sourceCode]) || isset($this->parsedByString[$sourceCode])) { $this->cachedNodesByString[$sourceCode] = $this->originalParser->parseFile($file); $this->cachedNodesByStringCount++; unset($this->parsedByString[$sourceCode]); } return $this->cachedNodesByString[$sourceCode]; } /** * @return Node\Stmt[] */ public function parseString(string $sourceCode) : array { if ($this->cachedNodesByStringCountMax !== 0 && $this->cachedNodesByStringCount >= $this->cachedNodesByStringCountMax) { $this->cachedNodesByString = array_slice($this->cachedNodesByString, 1, null, \true); --$this->cachedNodesByStringCount; } if (!isset($this->cachedNodesByString[$sourceCode])) { $this->cachedNodesByString[$sourceCode] = $this->originalParser->parseString($sourceCode); $this->cachedNodesByStringCount++; $this->parsedByString[$sourceCode] = \true; } return $this->cachedNodesByString[$sourceCode]; } public function getCachedNodesByStringCount() : int { return $this->cachedNodesByStringCount; } public function getCachedNodesByStringCountMax() : int { return $this->cachedNodesByStringCountMax; } /** * @return array */ public function getCachedNodesByString() : array { return $this->cachedNodesByString; } } findFunctionCallInStatements($functionNames, $statement); if ($result !== null) { return $result; } } if (!$statement instanceof Node) { continue; } if ($statement instanceof FuncCall && $statement->name instanceof Name) { if (in_array((string) $statement->name, $functionNames, \true)) { return $statement; } } $result = $this->findFunctionCallInStatements($functionNames, $statement); if ($result !== null) { return $result; } } return null; } } isFirstStatement = \true; return null; } public function enterNode(Node $node) : ?Node { // ignore shebang if ($this->isFirstStatement && $node instanceof Node\Stmt\InlineHTML && str_starts_with($node->value, '#!')) { return null; } if ($node instanceof Node\Stmt) { if ($node instanceof Node\Stmt\Declare_) { $node->setAttribute(self::ATTRIBUTE_NAME, $this->isFirstStatement); } $this->isFirstStatement = \false; } return null; } } name instanceof Node\Name) { $functionName = $node->name->toLowerString(); if ($functionName === 'array_walk') { $args = $node->getRawArgs(); if (isset($args[0])) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, \true); } } } return null; } } name instanceof Node\Name) { $functionName = $node->name->toLowerString(); if (in_array($functionName, ['array_all', 'array_any', 'array_find', 'array_find_key'], \true)) { $args = $node->getRawArgs(); if (isset($args[0])) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, \true); } } } return null; } } wrappedParser = $wrappedParser; } /** * @return Node\Stmt[] */ public function parse(string $code, ?ErrorHandler $errorHandler = null) : array { try { return $this->wrappedParser->parseString($code); } catch (\PHPStan\Parser\ParserErrorsException $e) { $message = $e->getMessage(); if ($e->getParsedFile() !== null) { $message .= sprintf(' in file %s', $e->getParsedFile()); } throw new Error($message, $e->getAttributes()); } } } default instanceof Node\Scalar\MagicConst) { $node->default->setAttribute(self::ATTRIBUTE_NAME, \true); } return null; } } name instanceof Node\Name) { $functionName = $node->name->toLowerString(); if ($functionName === 'array_filter') { $args = $node->getRawArgs(); if (isset($args[0])) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, \true); } } } return null; } } isFirstClassCallable()) { return null; } if ($node->name instanceof Node\Expr\Assign && $node->name->expr instanceof Node\Expr\ArrowFunction) { $arrow = $node->name->expr; } elseif ($node->name instanceof Node\Expr\ArrowFunction) { $arrow = $node->name; } else { return null; } $args = $node->getArgs(); if (count($args) > 0) { $arrow->setAttribute(self::ATTRIBUTE_NAME, $args); } return null; } } elseifs !== []) { $lastElseIf = count($node->elseifs) - 1; $elseIsMissingOrThrowing = $node->else === null || count($node->else->stmts) === 1 && $node->else->stmts[0] instanceof Node\Stmt\Throw_; foreach ($node->elseifs as $i => $elseif) { $isLast = $i === $lastElseIf && $elseIsMissingOrThrowing; $elseif->cond->setAttribute(self::ATTRIBUTE_NAME, $isLast); } } if ($node instanceof Node\Expr\Match_ && $node->arms !== []) { $lastArm = count($node->arms) - 1; foreach ($node->arms as $i => $arm) { if ($arm->conds === null || $arm->conds === []) { continue; } $isLast = $i === $lastArm; $index = count($arm->conds) - 1; $arm->conds[$index]->setAttribute(self::ATTRIBUTE_NAME, $isLast); $arm->conds[$index]->setAttribute(self::ATTRIBUTE_IS_MATCH_NAME, \true); } } if ($node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\If_ || $node instanceof Node\Stmt\ElseIf_ || $node instanceof Node\Stmt\Else_ || $node instanceof Node\Stmt\Case_ || $node instanceof Node\Stmt\Catch_ || $node instanceof Node\Stmt\Do_ || $node instanceof Node\Stmt\Finally_ || $node instanceof Node\Stmt\For_ || $node instanceof Node\Stmt\Foreach_ || $node instanceof Node\Stmt\Namespace_ || $node instanceof Node\Stmt\TryCatch || $node instanceof Node\Stmt\While_) { $statements = $node->stmts ?? []; $statementCount = count($statements); if ($statementCount < 2) { return null; } if (!$statements[$statementCount - 1] instanceof Node\Stmt\Throw_) { return null; } if (!$statements[$statementCount - 2] instanceof Node\Stmt\If_ || $statements[$statementCount - 2]->else !== null) { return null; } $if = $statements[$statementCount - 2]; $cond = count($if->elseifs) > 0 ? $if->elseifs[count($if->elseifs) - 1]->cond : $if->cond; $cond->setAttribute(self::ATTRIBUTE_NAME, \true); } return null; } } parser = $parser; $this->lexer = $lexer; $this->nameResolver = $nameResolver; $this->container = $container; $this->ignoreLexer = $ignoreLexer; $this->enableIgnoreErrorsWithinPhpDocs = $enableIgnoreErrorsWithinPhpDocs; } /** * @param string $file path to a file to parse * @return Node\Stmt[] */ public function parseFile(string $file) : array { try { return $this->parseString(FileReader::read($file)); } catch (\PHPStan\Parser\ParserErrorsException $e) { throw new \PHPStan\Parser\ParserErrorsException($e->getErrors(), $file); } } /** * @return Node\Stmt[] */ public function parseString(string $sourceCode) : array { $errorHandler = new Collecting(); $nodes = $this->parser->parse($sourceCode, $errorHandler); /** @var list $tokens */ $tokens = $this->lexer->getTokens(); if ($errorHandler->hasErrors()) { throw new \PHPStan\Parser\ParserErrorsException($errorHandler->getErrors(), null); } if ($nodes === null) { throw new ShouldNotHappenException(); } $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor($this->nameResolver); $traitCollectingVisitor = new \PHPStan\Parser\TraitCollectingVisitor(); $nodeTraverser->addVisitor($traitCollectingVisitor); foreach ($this->container->getServicesByTag(self::VISITOR_SERVICE_TAG) as $visitor) { $nodeTraverser->addVisitor($visitor); } /** @var array */ $nodes = $nodeTraverser->traverse($nodes); ['lines' => $linesToIgnore, 'errors' => $ignoreParseErrors] = $this->getLinesToIgnore($tokens); if (isset($nodes[0])) { $nodes[0]->setAttribute('linesToIgnore', $linesToIgnore); if (count($ignoreParseErrors) > 0) { $nodes[0]->setAttribute('linesToIgnoreParseErrors', $ignoreParseErrors); } } foreach ($traitCollectingVisitor->traits as $trait) { $preexisting = $trait->getAttribute('linesToIgnore', []); $filteredLinesToIgnore = array_filter($linesToIgnore, static function (int $line) use($trait) : bool { return $line >= $trait->getStartLine() && $line <= $trait->getEndLine(); }, ARRAY_FILTER_USE_KEY); foreach ($preexisting as $line => $ignores) { $filteredLinesToIgnore[$line] = $ignores; } $trait->setAttribute('linesToIgnore', $filteredLinesToIgnore); } return $nodes; } /** * @param list $tokens * @return array{lines: array|null>, errors: array>} */ private function getLinesToIgnore(array $tokens) : array { $lines = []; $previousToken = null; $pendingToken = null; $errors = []; foreach ($tokens as $token) { if (is_string($token)) { continue; } $type = $token[0]; $line = $token[2]; if ($type !== T_COMMENT && $type !== T_DOC_COMMENT) { if ($type !== T_WHITESPACE) { if ($pendingToken !== null) { [$pendingText, $pendingIgnorePos, $tokenLine, $pendingLine] = $pendingToken; try { $identifiers = $this->parseIdentifiers($pendingText, $pendingIgnorePos); } catch (IgnoreParseException $e) { $errors[] = [$tokenLine + $e->getPhpDocLine(), $e->getMessage()]; $pendingToken = null; continue; } if ($line !== $pendingLine + 1) { $lineToAdd = $pendingLine; } else { $lineToAdd = $line; } foreach ($identifiers as $identifier) { $lines[$lineToAdd][] = $identifier; } $pendingToken = null; } $previousToken = $token; } continue; } $text = $token[1]; $isNextLine = str_contains($text, '@phpstan-ignore-next-line'); $isCurrentLine = str_contains($text, '@phpstan-ignore-line'); if ($this->enableIgnoreErrorsWithinPhpDocs && $type === T_DOC_COMMENT) { $lines += $this->getLinesToIgnoreForTokenByIgnoreComment($text, $line, '@phpstan-ignore-line'); if ($isNextLine) { $pattern = sprintf('~%s~si', implode('|', [self::PHPDOC_TAG_REGEX, self::PHPDOC_DOCTRINE_TAG_REGEX])); $r = preg_match_all($pattern, $text, $pregMatches, PREG_OFFSET_CAPTURE); if ($r !== \false) { $c = count($pregMatches[0]); if ($c > 0) { [$lastMatchTag, $lastMatchOffset] = $pregMatches[0][$c - 1]; if ($lastMatchTag === '@phpstan-ignore-next-line') { // this will let us ignore errors outside of PHPDoc // and also cut off the PHPDoc text before the last tag $lineToIgnore = $line + 1 + substr_count($text, "\n"); $lines[$lineToIgnore] = null; $text = substr($text, 0, $lastMatchOffset); } } } $lines += $this->getLinesToIgnoreForTokenByIgnoreComment($text, $line, '@phpstan-ignore-next-line', \true); } if ($isNextLine || $isCurrentLine) { continue; } } else { if ($isNextLine) { $line++; } if ($isNextLine || $isCurrentLine) { $line += substr_count($token[1], "\n"); $lines[$line] = null; continue; } } $ignorePos = strpos($text, '@phpstan-ignore'); if ($ignorePos === \false) { continue; } $ignoreLine = substr_count(substr($text, 0, $ignorePos), "\n") - 1; if ($previousToken !== null && $previousToken[2] === $line) { try { foreach ($this->parseIdentifiers($text, $ignorePos) as $identifier) { $lines[$line][] = $identifier; } } catch (IgnoreParseException $e) { $errors[] = [$token[2] + $e->getPhpDocLine() + $ignoreLine, $e->getMessage()]; } continue; } $line += substr_count($token[1], "\n"); $pendingToken = [$text, $ignorePos, $token[2] + $ignoreLine, $line]; } if ($pendingToken !== null) { [$pendingText, $pendingIgnorePos, $tokenLine, $pendingLine] = $pendingToken; try { foreach ($this->parseIdentifiers($pendingText, $pendingIgnorePos) as $identifier) { $lines[$pendingLine][] = $identifier; } } catch (IgnoreParseException $e) { $errors[] = [$tokenLine + $e->getPhpDocLine(), $e->getMessage()]; } } $processedErrors = []; foreach ($errors as [$line, $message]) { $processedErrors[$line][] = $message; } return ['lines' => $lines, 'errors' => $processedErrors]; } /** * @return array */ private function getLinesToIgnoreForTokenByIgnoreComment(string $tokenText, int $tokenLine, string $ignoreComment, bool $ignoreNextLine = \false) : array { $lines = []; $positionsOfIgnoreComment = []; $offset = 0; while (($pos = strpos($tokenText, $ignoreComment, $offset)) !== \false) { $positionsOfIgnoreComment[] = $pos; $offset = $pos + 1; } foreach ($positionsOfIgnoreComment as $pos) { $line = $tokenLine + substr_count(substr($tokenText, 0, $pos), "\n") + ($ignoreNextLine ? 1 : 0); $lines[$line] = null; } return $lines; } /** * @return non-empty-list * @throws IgnoreParseException */ private function parseIdentifiers(string $text, int $ignorePos) : array { $text = substr($text, $ignorePos + strlen('@phpstan-ignore')); $originalTokens = $this->ignoreLexer->tokenize($text); $tokens = []; foreach ($originalTokens as $originalToken) { if ($originalToken[IgnoreLexer::TYPE_OFFSET] === IgnoreLexer::TOKEN_WHITESPACE) { continue; } $tokens[] = $originalToken; } $c = count($tokens); $identifiers = []; $openParenthesisCount = 0; $expected = [IgnoreLexer::TOKEN_IDENTIFIER]; for ($i = 0; $i < $c; $i++) { $lastTokenTypeLabel = isset($tokenType) ? $this->ignoreLexer->getLabel($tokenType) : '@phpstan-ignore'; [IgnoreLexer::VALUE_OFFSET => $content, IgnoreLexer::TYPE_OFFSET => $tokenType, IgnoreLexer::LINE_OFFSET => $tokenLine] = $tokens[$i]; if ($expected !== null && !in_array($tokenType, $expected, \true)) { $tokenTypeLabel = $this->ignoreLexer->getLabel($tokenType); $otherTokenContent = $tokenType === IgnoreLexer::TOKEN_OTHER ? sprintf(" '%s'", $content) : ''; $expectedLabels = implode(' or ', array_map(function ($token) { return $this->ignoreLexer->getLabel($token); }, $expected)); throw new IgnoreParseException(sprintf('Unexpected %s%s after %s, expected %s', $tokenTypeLabel, $otherTokenContent, $lastTokenTypeLabel, $expectedLabels), $tokenLine); } if ($tokenType === IgnoreLexer::TOKEN_OPEN_PARENTHESIS) { $openParenthesisCount++; $expected = null; continue; } if ($tokenType === IgnoreLexer::TOKEN_CLOSE_PARENTHESIS) { $openParenthesisCount--; if ($openParenthesisCount === 0) { $expected = [IgnoreLexer::TOKEN_COMMA, IgnoreLexer::TOKEN_END]; } continue; } if ($openParenthesisCount > 0) { continue; // waiting for comment end } if ($tokenType === IgnoreLexer::TOKEN_IDENTIFIER) { $identifiers[] = $content; $expected = [IgnoreLexer::TOKEN_COMMA, IgnoreLexer::TOKEN_END, IgnoreLexer::TOKEN_OPEN_PARENTHESIS]; continue; } if ($tokenType === IgnoreLexer::TOKEN_COMMA) { $expected = [IgnoreLexer::TOKEN_IDENTIFIER]; continue; } } if ($openParenthesisCount > 0) { throw new IgnoreParseException('Unexpected end, unclosed opening parenthesis', $tokenLine ?? 1); } if (count($identifiers) === 0) { throw new IgnoreParseException('Missing identifier', 1); } return $identifiers; } } ['comments', 'startLine', 'endLine', 'startTokenPos', 'endTokenPos', 'startFilePos', 'endFilePos']]; public function __construct(PhpVersion $phpVersion) { $this->phpVersion = $phpVersion; } public function create() : Lexer { $options = self::OPTIONS; if ($this->phpVersion->getVersionId() === PHP_VERSION_ID) { return new Lexer($options); } $options['phpVersion'] = $this->phpVersion->getVersionString(); return new Lexer\Emulative($options); } public function createEmulative() : Lexer\Emulative { return new Lexer\Emulative(self::OPTIONS); } } name instanceof Node\Name && !$node->isFirstClassCallable()) { $functionName = $node->name->toLowerString(); if ($functionName === 'array_map') { $args = $node->getArgs(); if (isset($args[0])) { $slicedArgs = array_slice($args, 1); if (count($slicedArgs) > 0) { $args[0]->value->setAttribute(self::ATTRIBUTE_NAME, $slicedArgs); } } } } return null; } } name instanceof Identifier && $node->name->toLowerString() === 'bindto' && !$node->isFirstClassCallable()) { $args = $node->getArgs(); if (isset($args[0])) { $args[0]->setAttribute(self::ATTRIBUTE_NAME, $node->var); } } return null; } } phpVersionString = $phpVersionString; } public function enterNode(Node $node) : ?Node { if (!$node instanceof Node\Stmt\If_) { return null; } if (count($node->elseifs) > 0) { return null; } if ($node->else === null) { return null; } $cond = $node->cond; if (!$cond instanceof Node\Expr\BinaryOp\Smaller && !$cond instanceof Node\Expr\BinaryOp\SmallerOrEqual && !$cond instanceof Node\Expr\BinaryOp\Greater && !$cond instanceof Node\Expr\BinaryOp\GreaterOrEqual && !$cond instanceof Node\Expr\BinaryOp\Equal && !$cond instanceof Node\Expr\BinaryOp\NotEqual && !$cond instanceof Node\Expr\BinaryOp\Identical && !$cond instanceof Node\Expr\BinaryOp\NotIdentical) { return null; } $operator = $cond->getOperatorSigil(); if ($operator === '===') { $operator = '=='; } elseif ($operator === '!==') { $operator = '!='; } $operands = $this->getOperands($cond->left, $cond->right); if ($operands === null) { return null; } $result = version_compare($operands[0], $operands[1], $operator); if ($result) { // remove else $node->cond = new Node\Expr\ConstFetch(new Node\Name('true')); $node->else = null; return $node; } // remove if $node->cond = new Node\Expr\ConstFetch(new Node\Name('false')); $node->stmts = []; return $node; } /** * @return array{string, string}|null */ private function getOperands(Node\Expr $left, Node\Expr $right) : ?array { if ($left instanceof Node\Scalar\LNumber && $right instanceof Node\Expr\ConstFetch && $right->name->toString() === 'PHP_VERSION_ID') { return [(new PhpVersion($left->value))->getVersionString(), $this->phpVersionString]; } if ($right instanceof Node\Scalar\LNumber && $left instanceof Node\Expr\ConstFetch && $left->name->toString() === 'PHP_VERSION_ID') { return [$this->phpVersionString, (new PhpVersion($right->value))->getVersionString()]; } return null; } } bool(true) */ private $analysedFiles = []; public function __construct(FileHelper $fileHelper, \PHPStan\Parser\Parser $currentPhpVersionRichParser, \PHPStan\Parser\Parser $currentPhpVersionSimpleParser, \PHPStan\Parser\Parser $php8Parser, ?string $singleReflectionFile) { $this->fileHelper = $fileHelper; $this->currentPhpVersionRichParser = $currentPhpVersionRichParser; $this->currentPhpVersionSimpleParser = $currentPhpVersionSimpleParser; $this->php8Parser = $php8Parser; $this->singleReflectionFile = $singleReflectionFile !== null ? $fileHelper->normalizePath($singleReflectionFile) : null; } /** * @param string[] $files */ public function setAnalysedFiles(array $files) : void { $this->analysedFiles = array_fill_keys($files, \true); } public function parseFile(string $file) : array { $normalizedPath = $this->fileHelper->normalizePath($file, '/'); if (str_contains($normalizedPath, 'vendor/jetbrains/phpstorm-stubs')) { return $this->php8Parser->parseFile($file); } if (str_contains($normalizedPath, 'vendor/phpstan/php-8-stubs/stubs')) { return $this->php8Parser->parseFile($file); } $file = $this->fileHelper->normalizePath($file); if (!isset($this->analysedFiles[$file]) && $file !== $this->singleReflectionFile) { // check symlinked file that still might be in analysedFiles $pathParts = explode(DIRECTORY_SEPARATOR, $file); for ($i = count($pathParts); $i > 1; $i--) { $joinedPartOfPath = implode(DIRECTORY_SEPARATOR, array_slice($pathParts, 0, $i)); if (!@is_link($joinedPartOfPath)) { continue; } $realFilePath = realpath($file); if ($realFilePath !== \false) { $normalizedRealFilePath = $this->fileHelper->normalizePath($realFilePath); if (isset($this->analysedFiles[$normalizedRealFilePath])) { return $this->currentPhpVersionRichParser->parseFile($file); } } break; } return $this->currentPhpVersionSimpleParser->parseFile($file); } return $this->currentPhpVersionRichParser->parseFile($file); } public function parseString(string $sourceCode) : array { return $this->currentPhpVersionSimpleParser->parseString($sourceCode); } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; $this->analysisStartTime = $analysisStartTime; parent::__construct(); } protected function configure() : void { $this->setName(self::NAME)->setDescription('Analyses source code')->setDefinition([new InputArgument('paths', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Paths with source code to run analysis on'), new InputOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Path to project configuration file'), new InputOption(self::OPTION_LEVEL, 'l', InputOption::VALUE_REQUIRED, 'Level of rule options - the higher the stricter'), new InputOption(\PHPStan\Command\ErrorsConsoleStyle::OPTION_NO_PROGRESS, null, InputOption::VALUE_NONE, 'Do not show progress bar, only results'), new InputOption('debug', null, InputOption::VALUE_NONE, 'Show debug information - which file is analysed, do not catch internal errors'), new InputOption('autoload-file', 'a', InputOption::VALUE_REQUIRED, 'Project\'s additional autoload file path'), new InputOption('error-format', null, InputOption::VALUE_REQUIRED, 'Format in which to print the result of the analysis', null), new InputOption('generate-baseline', 'b', InputOption::VALUE_OPTIONAL, 'Path to a file where the baseline should be saved', \false), new InputOption('allow-empty-baseline', null, InputOption::VALUE_NONE, 'Do not error out when the generated baseline is empty'), new InputOption('memory-limit', null, InputOption::VALUE_REQUIRED, 'Memory limit for analysis'), new InputOption('xdebug', null, InputOption::VALUE_NONE, 'Allow running with Xdebug for debugging purposes'), new InputOption('tmp-file', null, InputOption::VALUE_REQUIRED, '(Editor mode) Edited file used in place of --instead-of file'), new InputOption('instead-of', null, InputOption::VALUE_REQUIRED, '(Editor mode) File being replaced by --tmp-file'), new InputOption('fix', null, InputOption::VALUE_NONE, 'Launch PHPStan Pro'), new InputOption('watch', null, InputOption::VALUE_NONE, 'Launch PHPStan Pro'), new InputOption('pro', null, InputOption::VALUE_NONE, 'Launch PHPStan Pro'), new InputOption('fail-without-result-cache', null, InputOption::VALUE_NONE, 'Return non-zero exit code when result cache is not used')]); } /** * @return string[] */ public function getAliases() : array { return ['analyze']; } protected function initialize(InputInterface $input, OutputInterface $output) : void { if ((bool) $input->getOption('debug')) { $application = $this->getApplication(); if ($application === null) { return; } $application->setCatchExceptions(\false); return; } } protected function execute(InputInterface $input, OutputInterface $output) : int { if ($output instanceof ConsoleOutputInterface) { $errorOutput = $output->getErrorOutput(); $errorOutput->writeln(''); $errorOutput->writeln("⚠️ You're running an old version of PHPStan.️"); $errorOutput->writeln(''); $errorOutput->writeln('The last release in the 1.12.x series with new features'); $lastRelease = new DateTimeImmutable('2025-07-17 00:00:00'); $daysSince = (time() - $lastRelease->getTimestamp()) / 60 / 60 / 24; $errorOutput->writeln('and bugfixes was released on July 17th 2025,'); $errorOutput->writeln(sprintf('that\'s %d days ago.', (int) $daysSince)); $errorOutput->writeln(''); $errorOutput->writeln('Since then more than 65 new PHPStan versions were released'); $errorOutput->writeln('with hundreds of new features, bugfixes, and other'); $errorOutput->writeln('quality of life improvements.'); $errorOutput->writeln(''); $errorOutput->writeln("To learn about what you're missing out on, check out"); $errorOutput->writeln('this blog with articles about the latest major releases:'); $errorOutput->writeln('https://phpstan.org/blog'); $errorOutput->writeln(''); $errorOutput->writeln('Upgrade today to PHPStan 2.2 or newer by using'); $errorOutput->writeln('"phpstan/phpstan": "^2.2" in your composer.json.'); $errorOutput->writeln(''); } $paths = $input->getArgument('paths'); $memoryLimit = $input->getOption('memory-limit'); $autoloadFile = $input->getOption('autoload-file'); $configuration = $input->getOption('configuration'); $level = $input->getOption(self::OPTION_LEVEL); $allowXdebug = $input->getOption('xdebug'); $debugEnabled = (bool) $input->getOption('debug'); $fix = (bool) $input->getOption('fix') || (bool) $input->getOption('watch') || (bool) $input->getOption('pro'); $failWithoutResultCache = (bool) $input->getOption('fail-without-result-cache'); /** @var string|false|null $generateBaselineFile */ $generateBaselineFile = $input->getOption('generate-baseline'); if ($generateBaselineFile === \false) { $generateBaselineFile = null; } elseif ($generateBaselineFile === null) { $generateBaselineFile = 'phpstan-baseline.neon'; } $allowEmptyBaseline = (bool) $input->getOption('allow-empty-baseline'); $tmpFile = $input->getOption('tmp-file'); $insteadOfFile = $input->getOption('instead-of'); if (!is_array($paths) || !is_string($memoryLimit) && $memoryLimit !== null || !is_string($autoloadFile) && $autoloadFile !== null || !is_string($configuration) && $configuration !== null || !is_string($level) && $level !== null || !is_string($tmpFile) && $tmpFile !== null || !is_string($insteadOfFile) && $insteadOfFile !== null || !is_bool($allowXdebug)) { throw new ShouldNotHappenException(); } try { $inceptionResult = \PHPStan\Command\CommandHelper::begin($input, $output, $paths, $memoryLimit, $autoloadFile, $this->composerAutoloaderProjectPaths, $configuration, $generateBaselineFile, $level, $allowXdebug, $debugEnabled, $tmpFile, $insteadOfFile); } catch (\PHPStan\Command\InceptionNotSuccessfulException $e) { return 1; } if ($generateBaselineFile === null && $allowEmptyBaseline) { $inceptionResult->getStdOutput()->getStyle()->error('You must pass the --generate-baseline option alongside --allow-empty-baseline.'); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } if ($inceptionResult->getEditorModeTmpFile() !== null) { if ($generateBaselineFile !== null) { $inceptionResult->getStdOutput()->getStyle()->error('Editor mode options --tmp-file and --instead-of cannot be used when generating the baseline.'); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } if ($fix) { $inceptionResult->getStdOutput()->getStyle()->error('Editor mode options --tmp-file and --instead-of cannot be used with PHPStan Pro.'); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } } $errorOutput = $inceptionResult->getErrorOutput(); $obsoleteDockerImage = $_SERVER['PHPSTAN_OBSOLETE_DOCKER_IMAGE'] ?? 'false'; if ($obsoleteDockerImage === 'true') { $errorOutput->writeLineFormatted('⚠️ You\'re using an obsolete PHPStan Docker image. ⚠️️'); $errorOutput->writeLineFormatted(' You can obtain the current one from ghcr.io/phpstan/phpstan.'); $errorOutput->writeLineFormatted(' Read more about it here:'); $errorOutput->writeLineFormatted(' https://phpstan.org/user-guide/docker'); $errorOutput->writeLineFormatted(''); } $errorFormat = $input->getOption('error-format'); if (!is_string($errorFormat) && $errorFormat !== null) { throw new ShouldNotHappenException(); } if ($errorFormat === null) { $errorFormat = $inceptionResult->getContainer()->getParameter('errorFormat'); } if ($errorFormat === null) { $errorFormat = 'table'; } $container = $inceptionResult->getContainer(); $errorFormatterServiceName = sprintf('errorFormatter.%s', $errorFormat); if (!$container->hasService($errorFormatterServiceName)) { $errorOutput->writeLineFormatted(sprintf('Error formatter "%s" not found. Available error formatters are: %s', $errorFormat, implode(', ', array_map(static function (string $name) : string { return substr($name, strlen('errorFormatter.')); }, $container->findServiceNamesByType(ErrorFormatter::class))))); return 1; } $generateBaselineFile = $inceptionResult->getGenerateBaselineFile(); if ($generateBaselineFile !== null) { $baselineExtension = pathinfo($generateBaselineFile, PATHINFO_EXTENSION); if ($baselineExtension === '') { $inceptionResult->getStdOutput()->getStyle()->error(sprintf('Baseline filename must have an extension, %s provided instead.', pathinfo($generateBaselineFile, PATHINFO_BASENAME))); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } if (!in_array($baselineExtension, ['neon', 'php'], \true)) { $inceptionResult->getStdOutput()->getStyle()->error(sprintf('Baseline filename extension must be .neon or .php, .%s was used instead.', $baselineExtension)); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } } try { [$files, $onlyFiles] = $inceptionResult->getFiles(); } catch (PathNotFoundException $e) { $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); $inceptionResult->getErrorOutput()->writeLineFormatted(sprintf('%s', $e->getMessage())); return 1; } catch (\PHPStan\Command\InceptionNotSuccessfulException $e) { $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); return 1; } if (count($files) === 0) { $bleedingEdge = (bool) $container->getParameter('featureToggles')['zeroFiles']; $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); if (!$bleedingEdge) { $inceptionResult->getErrorOutput()->getStyle()->note('No files found to analyse.'); $inceptionResult->getErrorOutput()->getStyle()->warning('This will cause a non-zero exit code in PHPStan 2.0.'); return $inceptionResult->handleReturn(0, null, $this->analysisStartTime); } $inceptionResult->getErrorOutput()->getStyle()->error('No files found to analyse.'); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } if ($inceptionResult->getEditorModeInsteadOfFile() !== null) { if (!in_array($inceptionResult->getEditorModeInsteadOfFile(), $files, \true)) { $inceptionResult->getStdOutput()->getStyle()->error(sprintf('File %s passed to --instead-of is not in analysed project files.', $inceptionResult->getEditorModeInsteadOfFile())); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } } if ($inceptionResult->getEditorModeTmpFile() !== null) { if (in_array($inceptionResult->getEditorModeTmpFile(), $files, \true)) { $inceptionResult->getStdOutput()->getStyle()->error(sprintf('File %s passed to --tmp-file is already in analysed project files.', $inceptionResult->getEditorModeInsteadOfFile())); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } } $analysedConfigFiles = array_intersect($files, $container->getParameter('allConfigFiles')); /** @var RelativePathHelper $relativePathHelper */ $relativePathHelper = $container->getService('relativePathHelper'); foreach ($analysedConfigFiles as $analysedConfigFile) { $fileSize = @filesize($analysedConfigFile); if ($fileSize === \false) { continue; } if ($fileSize <= 512 * 1024) { continue; } $inceptionResult->getErrorOutput()->getStyle()->warning(sprintf('Configuration file %s (%s) is too big and might slow down PHPStan. Consider adding it to excludePaths.', $relativePathHelper->getRelativePath($analysedConfigFile), BytesHelper::bytes($fileSize))); } if ($fix) { if ($generateBaselineFile !== null) { $inceptionResult->getStdOutput()->getStyle()->error('You cannot pass the --generate-baseline option when running PHPStan Pro.'); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } return $this->runFixer($inceptionResult, $container, $onlyFiles, $input, $output, $files); } /** @var AnalyseApplication $application */ $application = $container->getByType(\PHPStan\Command\AnalyseApplication::class); $debug = $input->getOption('debug'); if (!is_bool($debug)) { throw new ShouldNotHappenException(); } try { $analysisResult = $application->analyse($files, $onlyFiles, $inceptionResult->getStdOutput(), $inceptionResult->getErrorOutput(), $inceptionResult->isDefaultLevelUsed(), $debug, $inceptionResult->getProjectConfigFile(), $inceptionResult->getProjectConfigArray(), $inceptionResult->getEditorModeTmpFile(), $inceptionResult->getEditorModeInsteadOfFile(), $input); } catch (Throwable $t) { if ($debug) { $stdOutput = $inceptionResult->getStdOutput(); $stdOutput->writeRaw(sprintf('Uncaught %s: %s in %s:%d', get_class($t), $t->getMessage(), $t->getFile(), $t->getLine())); $stdOutput->writeLineFormatted(''); $stdOutput->writeRaw($t->getTraceAsString()); $stdOutput->writeLineFormatted(''); $previous = $t->getPrevious(); while ($previous !== null) { $stdOutput->writeLineFormatted(''); $stdOutput->writeLineFormatted('Caused by:'); $stdOutput->writeRaw(sprintf('Uncaught %s: %s in %s:%d', get_class($previous), $previous->getMessage(), $previous->getFile(), $previous->getLine())); $stdOutput->writeRaw($previous->getTraceAsString()); $stdOutput->writeLineFormatted(''); $previous = $previous->getPrevious(); } return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } throw $t; } /** * Variable $internalErrorsTuples contains both "internal errors" * and "errors with non-ignorable exception" as InternalError objects. */ $internalErrorsTuples = []; $internalFileSpecificErrors = []; foreach ($analysisResult->getInternalErrorObjects() as $internalError) { $internalErrorsTuples[$internalError->getMessage()] = [new InternalError($internalError->getTraceAsString() !== null ? sprintf('Internal error: %s', $internalError->getMessage()) : $internalError->getMessage(), $internalError->getContextDescription(), $internalError->getTrace(), $internalError->getTraceAsString(), $internalError->shouldReportBug()), \false]; } foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { if (!$fileSpecificError->hasNonIgnorableException()) { continue; } $message = $fileSpecificError->getMessage(); $metadata = $fileSpecificError->getMetadata(); $hasStackTrace = \false; if ($fileSpecificError->getIdentifier() === 'phpstan.internal' && array_key_exists(InternalError::STACK_TRACE_AS_STRING_METADATA_KEY, $metadata)) { $message = sprintf('Internal error: %s', $message); $hasStackTrace = \true; } if (!$hasStackTrace) { if (!array_key_exists($fileSpecificError->getMessage(), $internalFileSpecificErrors)) { $internalFileSpecificErrors[$fileSpecificError->getMessage()] = $fileSpecificError; } } $internalErrorsTuples[$fileSpecificError->getMessage()] = [new InternalError($message, sprintf('analysing file %s', $fileSpecificError->getTraitFilePath() ?? $fileSpecificError->getFilePath()), $metadata[InternalError::STACK_TRACE_METADATA_KEY] ?? [], $metadata[InternalError::STACK_TRACE_AS_STRING_METADATA_KEY] ?? null, \true), !$hasStackTrace]; } $internalErrorsTuples = array_values($internalErrorsTuples); $fileHelper = $container->getByType(FileHelper::class); /** * Variable $internalErrors only contains non-file-specific "internal errors". */ $internalErrors = []; foreach ($internalErrorsTuples as [$internalError, $isInFileSpecificErrors]) { if ($isInFileSpecificErrors) { continue; } $internalErrors[] = new InternalError($this->getMessageFromInternalError($fileHelper, $internalError, $output->getVerbosity()), $internalError->getContextDescription(), $internalError->getTrace(), $internalError->getTraceAsString(), $internalError->shouldReportBug()); } if ($generateBaselineFile !== null) { $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); if (count($internalErrorsTuples) > 0) { foreach ($internalErrorsTuples as [$internalError]) { $inceptionResult->getStdOutput()->writeLineFormatted($internalError->getMessage()); $inceptionResult->getStdOutput()->writeLineFormatted(''); } $inceptionResult->getStdOutput()->getStyle()->error(sprintf('%s occurred. Baseline could not be generated.', count($internalErrors) === 1 ? 'An internal error' : 'Internal errors')); return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } return $this->generateBaseline($generateBaselineFile, $inceptionResult, $analysisResult, $output, $allowEmptyBaseline, $baselineExtension, $failWithoutResultCache); } /** @var ErrorFormatter $errorFormatter */ $errorFormatter = $container->getService($errorFormatterServiceName); if (count($internalErrorsTuples) > 0) { $analysisResult = new \PHPStan\Command\AnalysisResult(array_values($internalFileSpecificErrors), array_map(static function (InternalError $internalError) { return $internalError->getMessage(); }, $internalErrors), [], [], [], $analysisResult->isDefaultLevelUsed(), $analysisResult->getProjectConfigFile(), $analysisResult->isResultCacheSaved(), $analysisResult->getPeakMemoryUsageBytes(), $analysisResult->isResultCacheUsed(), $analysisResult->getChangedProjectExtensionFilesOutsideOfAnalysedPaths()); $exitCode = $errorFormatter->formatErrors($analysisResult, $inceptionResult->getStdOutput()); $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); $errorOutput->writeLineFormatted('⚠️ Result is incomplete because of severe errors. ⚠️'); $errorOutput->writeLineFormatted(' Fix these errors first and then re-run PHPStan'); $errorOutput->writeLineFormatted(' to get all reported errors.'); $errorOutput->writeLineFormatted(''); return $inceptionResult->handleReturn($exitCode, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } $exitCode = $errorFormatter->formatErrors($analysisResult, $inceptionResult->getStdOutput()); if ($failWithoutResultCache && !$analysisResult->isResultCacheUsed()) { $exitCode = 2; } if ($analysisResult->isResultCacheUsed() && $analysisResult->isResultCacheSaved() && !$onlyFiles && $inceptionResult->getProjectConfigArray() !== null) { $projectServicesNotInAnalysedPaths = array_values(array_unique($analysisResult->getChangedProjectExtensionFilesOutsideOfAnalysedPaths())); $projectServiceFileNamesNotInAnalysedPaths = array_keys($analysisResult->getChangedProjectExtensionFilesOutsideOfAnalysedPaths()); if (count($projectServicesNotInAnalysedPaths) > 0) { $one = count($projectServicesNotInAnalysedPaths) === 1; $errorOutput->writeLineFormatted('Result cache might not behave correctly.'); $errorOutput->writeLineFormatted(sprintf('You\'re using custom %s in your project config', $one ? 'extension' : 'extensions')); $errorOutput->writeLineFormatted(sprintf('but %s not part of analysed paths:', $one ? 'this extension is' : 'these extensions are')); $errorOutput->writeLineFormatted(''); foreach ($projectServicesNotInAnalysedPaths as $service) { $errorOutput->writeLineFormatted(sprintf('- %s', $service)); } $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('When you edit them and re-run PHPStan, the result cache will get stale.'); $directoriesToAdd = []; foreach ($projectServiceFileNamesNotInAnalysedPaths as $path) { $directoriesToAdd[] = dirname($relativePathHelper->getRelativePath($path)); } $directoriesToAdd = array_unique($directoriesToAdd); $oneDirectory = count($directoriesToAdd) === 1; $errorOutput->writeLineFormatted(sprintf('Add %s to your analysed paths to get rid of this problem:', $oneDirectory ? 'this directory' : 'these directories')); $errorOutput->writeLineFormatted(''); foreach ($directoriesToAdd as $directory) { $errorOutput->writeLineFormatted(sprintf('- %s', $directory)); } $errorOutput->writeLineFormatted(''); $bleedingEdge = (bool) $container->getParameter('featureToggles')['projectServicesNotInAnalysedPaths']; if ($bleedingEdge) { return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } $errorOutput->getStyle()->warning('This will cause a non-zero exit code in PHPStan 2.0.'); } } $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); return $inceptionResult->handleReturn($exitCode, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } private function createStreamOutput() : StreamOutput { $resource = fopen('php://memory', 'w', \false); if ($resource === \false) { throw new ShouldNotHappenException(); } return new StreamOutput($resource); } private function getMessageFromInternalError(FileHelper $fileHelper, InternalError $internalError, int $verbosity) : string { $message = sprintf('%s while %s', $internalError->getMessage(), $internalError->getContextDescription()); $hasLarastan = \false; $isLaravelLast = \false; foreach (array_reverse($internalError->getTrace()) as $traceItem) { if ($traceItem['file'] === null) { continue; } $file = $fileHelper->normalizePath($traceItem['file'], '/'); if (str_contains($file, '/larastan/')) { $hasLarastan = \true; $isLaravelLast = \false; continue; } if (!str_contains($file, '/laravel/framework/')) { continue; } $isLaravelLast = \true; } if ($hasLarastan) { if ($isLaravelLast) { $message .= "\n"; $message .= "\n" . 'This message is coming from Laravel Framework itself.'; $message .= "\n" . 'Larastan boots up your application in order to provide'; $message .= "\n" . 'smarter static analysis of your codebase.'; $message .= "\n"; $message .= "\n" . 'In order to do that, the environment you run PHPStan in'; $message .= "\n" . 'must match the environment you run your application in.'; $message .= "\n"; $message .= "\n" . 'Make sure you\'ve set your environment variables'; $message .= "\n" . 'or the .env file correctly.'; return $message; } $bugReportUrl = 'https://github.com/larastan/larastan/issues/new?template=bug-report.md'; } else { $bugReportUrl = 'https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml'; } if ($internalError->getTraceAsString() !== null) { if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) { $firstTraceItem = $internalError->getTrace()[0] ?? null; $trace = ''; if ($firstTraceItem !== null && $firstTraceItem['file'] !== null && $firstTraceItem['line'] !== null) { $trace = sprintf('## %s(%d)%s', $firstTraceItem['file'], $firstTraceItem['line'], "\n"); } $trace .= $internalError->getTraceAsString(); if ($internalError->shouldReportBug()) { $message .= sprintf('%sPost the following stack trace to %s: %s%s', "\n", $bugReportUrl, "\n", $trace); } else { $message .= sprintf('%s%s', "\n\n", $trace); } } else { if ($internalError->shouldReportBug()) { $message .= sprintf('%sRun PHPStan with -v option and post the stack trace to:%s%s%s', "\n\n", "\n", $bugReportUrl, "\n"); } else { $message .= sprintf('%sRun PHPStan with -v option to see the stack trace', "\n"); } } } return $message; } private function generateBaseline(string $generateBaselineFile, \PHPStan\Command\InceptionResult $inceptionResult, \PHPStan\Command\AnalysisResult $analysisResult, OutputInterface $output, bool $allowEmptyBaseline, string $baselineExtension, bool $failWithoutResultCache) : int { if (!$allowEmptyBaseline && !$analysisResult->hasErrors()) { $inceptionResult->getStdOutput()->getStyle()->error('No errors were found during the analysis. Baseline could not be generated.'); $inceptionResult->getStdOutput()->writeLineFormatted('To allow generating empty baselines, pass --allow-empty-baseline option.'); return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } $streamOutput = $this->createStreamOutput(); $errorConsoleStyle = new \PHPStan\Command\ErrorsConsoleStyle(new StringInput(''), $streamOutput); $baselineOutput = new SymfonyOutput($streamOutput, new SymfonyStyle($errorConsoleStyle)); $baselineFileDirectory = dirname($generateBaselineFile); $baselinePathHelper = new ParentDirectoryRelativePathHelper($baselineFileDirectory); if ($baselineExtension === 'php') { $baselineErrorFormatter = new BaselinePhpErrorFormatter($baselinePathHelper); $baselineErrorFormatter->formatErrors($analysisResult, $baselineOutput); } else { $baselineErrorFormatter = new BaselineNeonErrorFormatter($baselinePathHelper); $existingBaselineContent = is_file($generateBaselineFile) ? FileReader::read($generateBaselineFile) : ''; $baselineErrorFormatter->formatErrors($analysisResult, $baselineOutput, $existingBaselineContent); } $stream = $streamOutput->getStream(); rewind($stream); $baselineContents = stream_get_contents($stream); if ($baselineContents === \false) { throw new ShouldNotHappenException(); } try { DirectoryCreator::ensureDirectoryExists($baselineFileDirectory, 0644); } catch (DirectoryCreatorException $e) { $inceptionResult->getStdOutput()->writeLineFormatted($e->getMessage()); return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } try { FileWriter::write($generateBaselineFile, $baselineContents); } catch (CouldNotWriteFileException $e) { $inceptionResult->getStdOutput()->writeLineFormatted($e->getMessage()); return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } $errorsCount = 0; $unignorableCount = 0; foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { if (!$fileSpecificError->canBeIgnored()) { $unignorableCount++; if ($output->isVeryVerbose()) { $inceptionResult->getStdOutput()->writeLineFormatted('Unignorable errors could not be added to the baseline:'); $inceptionResult->getStdOutput()->writeLineFormatted($fileSpecificError->getMessage()); $inceptionResult->getStdOutput()->writeLineFormatted($fileSpecificError->getFile()); $inceptionResult->getStdOutput()->writeLineFormatted(''); } continue; } $errorsCount++; } $message = sprintf('Baseline generated with %d %s.', $errorsCount, $errorsCount === 1 ? 'error' : 'errors'); if ($unignorableCount === 0 && count($analysisResult->getNotFileSpecificErrors()) === 0) { $inceptionResult->getStdOutput()->getStyle()->success($message); } else { if ($output->isVeryVerbose()) { $inceptionResult->getStdOutput()->getStyle()->warning($message . "\nSome errors could not be put into baseline."); } else { $inceptionResult->getStdOutput()->getStyle()->warning($message . "\nSome errors could not be put into baseline. Re-run PHPStan with \"-vv\" and fix them."); } } $exitCode = 0; if ($failWithoutResultCache && !$analysisResult->isResultCacheUsed()) { $exitCode = 2; } return $inceptionResult->handleReturn($exitCode, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } /** * @param string[] $files */ private function runFixer(\PHPStan\Command\InceptionResult $inceptionResult, Container $container, bool $onlyFiles, InputInterface $input, OutputInterface $output, array $files) : int { $ciDetector = new CiDetector(); if ($ciDetector->isCiDetected()) { $inceptionResult->getStdOutput()->writeLineFormatted('PHPStan Pro can\'t run in CI environment yet. Stay tuned!'); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); } /** @var FixerApplication $fixerApplication */ $fixerApplication = $container->getByType(\PHPStan\Command\FixerApplication::class); return $fixerApplication->run($inceptionResult->getProjectConfigFile(), $input, $output, count($files), $_SERVER['argv'][0]); } private function runDiagnoseExtensions(Container $container, \PHPStan\Command\Output $errorOutput) : void { if (!$errorOutput->isDebug()) { return; } /** @var PHPStanDiagnoseExtension $phpstanDiagnoseExtension */ $phpstanDiagnoseExtension = $container->getService('phpstanDiagnoseExtension'); // not using tag for this extension to make sure it's always first $phpstanDiagnoseExtension->print($errorOutput); /** @var DiagnoseExtension $extension */ foreach ($container->getServicesByTag(DiagnoseExtension::EXTENSION_TAG) as $extension) { $extension->print($errorOutput); } } } symfonyOutput = $symfonyOutput; $this->style = $style; } public function writeFormatted(string $message) : void { $this->symfonyOutput->write($message, \false, OutputInterface::OUTPUT_NORMAL); } public function writeLineFormatted(string $message) : void { $this->symfonyOutput->writeln($message, OutputInterface::OUTPUT_NORMAL); } public function writeRaw(string $message) : void { $this->symfonyOutput->write($message, \false, OutputInterface::OUTPUT_RAW); } public function getStyle() : OutputStyle { return $this->style; } public function isVerbose() : bool { return $this->symfonyOutput->isVerbose(); } public function isVeryVerbose() : bool { return $this->symfonyOutput->isVeryVerbose(); } public function isDebug() : bool { return $this->symfonyOutput->isDebug(); } public function isDecorated() : bool { return $this->symfonyOutput->isDecorated(); } } symfonyStyle = $symfonyStyle; } public function getSymfonyStyle() : StyleInterface { return $this->symfonyStyle; } public function title(string $message) : void { $this->symfonyStyle->title($message); } public function section(string $message) : void { $this->symfonyStyle->section($message); } public function listing(array $elements) : void { $this->symfonyStyle->listing($elements); } public function success(string $message) : void { $this->symfonyStyle->success($message); } public function error(string $message) : void { $this->symfonyStyle->error($message); } public function warning(string $message) : void { $this->symfonyStyle->warning($message); } public function note(string $message) : void { $this->symfonyStyle->note($message); } public function caution(string $message) : void { $this->symfonyStyle->caution($message); } public function table(array $headers, array $rows) : void { $this->symfonyStyle->table($headers, $rows); } public function newLine(int $count = 1) : void { $this->symfonyStyle->newLine($count); } public function progressStart(int $max = 0) : void { $this->symfonyStyle->progressStart($max); } public function progressAdvance(int $step = 1) : void { $this->symfonyStyle->progressAdvance($step); } public function progressFinish() : void { $this->symfonyStyle->progressFinish(); } } parser = $parser; $this->typeStringResolver = $typeStringResolver; } public function validate(string $regex) : \PHPStan\Command\IgnoredRegexValidatorResult { $regex = $this->removeDelimiters($regex); try { /** @var TreeNode $ast */ $ast = $this->parser->parse($regex); } catch (Exception $e) { return new \PHPStan\Command\IgnoredRegexValidatorResult([], \false, \false); } if (Strings::match($regex, '~(?getIgnoredTypes($ast), $this->hasAnchorsInTheMiddle($ast), \false); } /** * @return array */ private function getIgnoredTypes(TreeNode $ast) : array { /** @var TreeNode|null $alternation */ $alternation = $ast->getChild(0); if ($alternation === null) { return []; } if ($alternation->getId() !== '#alternation') { return []; } $types = []; foreach ($alternation->getChildren() as $child) { $text = $this->getText($child); if ($text === null) { continue; } $matches = Strings::match($text, '#^([a-zA-Z0-9]+)[,]?\\s*#'); if ($matches === null) { continue; } try { $type = $this->typeStringResolver->resolve($matches[1], null); } catch (ParserException $e) { continue; } if ($type instanceof ObjectType) { continue; } $typeDescription = $type->describe(VerbosityLevel::typeOnly()); if ($typeDescription !== $matches[1]) { continue; } $types[$typeDescription] = $text; } return $types; } private function removeDelimiters(string $regex) : string { $delimiter = substr($regex, 0, 1); $endDelimiterPosition = strrpos($regex, $delimiter); if ($endDelimiterPosition === \false) { throw new ShouldNotHappenException(); } return substr($regex, 1, $endDelimiterPosition - 1); } private function getText(TreeNode $treeNode) : ?string { if ($treeNode->getId() === 'token') { return $treeNode->getValueValue(); } if ($treeNode->getId() === '#concatenation') { $fullText = ''; foreach ($treeNode->getChildren() as $child) { $text = $this->getText($child); if ($text === null) { continue; } $fullText .= $text; } if ($fullText === '') { return null; } return $fullText; } return null; } private function hasAnchorsInTheMiddle(TreeNode $ast) : bool { if ($ast->getId() === 'token') { $valueArray = $ast->getValue(); return $valueArray['token'] === 'anchor' && $valueArray['value'] === '$'; } $childrenCount = count($ast->getChildren()); foreach ($ast->getChildren() as $i => $child) { $has = $this->hasAnchorsInTheMiddle($child); if ($has && ($ast->getId() !== '#concatenation' || $i !== $childrenCount - 1)) { return \true; } } return \false; } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } protected function configure() : void { $this->setName(self::NAME)->setDescription('(Internal) Support for PHPStan Pro.')->setDefinition([new InputArgument('paths', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Paths with source code to run analysis on'), new InputOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Path to project configuration file'), new InputOption(\PHPStan\Command\AnalyseCommand::OPTION_LEVEL, 'l', InputOption::VALUE_REQUIRED, 'Level of rule options - the higher the stricter'), new InputOption('autoload-file', 'a', InputOption::VALUE_REQUIRED, 'Project\'s additional autoload file path'), new InputOption('memory-limit', null, InputOption::VALUE_REQUIRED, 'Memory limit for analysis'), new InputOption('xdebug', null, InputOption::VALUE_NONE, 'Allow running with Xdebug for debugging purposes'), new InputOption('server-port', null, InputOption::VALUE_REQUIRED, 'Server port for FixerApplication')])->setHidden(\true); } protected function execute(InputInterface $input, OutputInterface $output) : int { $paths = $input->getArgument('paths'); $memoryLimit = $input->getOption('memory-limit'); $autoloadFile = $input->getOption('autoload-file'); $configuration = $input->getOption('configuration'); $level = $input->getOption(\PHPStan\Command\AnalyseCommand::OPTION_LEVEL); $allowXdebug = $input->getOption('xdebug'); $serverPort = $input->getOption('server-port'); if (!is_array($paths) || !is_string($memoryLimit) && $memoryLimit !== null || !is_string($autoloadFile) && $autoloadFile !== null || !is_string($configuration) && $configuration !== null || !is_string($level) && $level !== null || !is_bool($allowXdebug) || !is_string($serverPort)) { throw new ShouldNotHappenException(); } try { $inceptionResult = \PHPStan\Command\CommandHelper::begin($input, $output, $paths, $memoryLimit, $autoloadFile, $this->composerAutoloaderProjectPaths, $configuration, null, $level, $allowXdebug, \false, null, null, \false); } catch (\PHPStan\Command\InceptionNotSuccessfulException $e) { return 1; } $container = $inceptionResult->getContainer(); /** @var IgnoredErrorHelper $ignoredErrorHelper */ $ignoredErrorHelper = $container->getByType(IgnoredErrorHelper::class); $ignoredErrorHelperResult = $ignoredErrorHelper->initialize(); if (count($ignoredErrorHelperResult->getErrors()) > 0) { throw new ShouldNotHappenException(); } $loop = new StreamSelectLoop(); $tcpConnector = new TcpConnector($loop); $tcpConnector->connect(sprintf('127.0.0.1:%d', $serverPort))->then(function (ConnectionInterface $connection) use($container, $inceptionResult, $configuration, $input, $ignoredErrorHelperResult, $loop) : void { // phpcs:disable SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly $jsonInvalidUtf8Ignore = \defined('JSON_INVALID_UTF8_IGNORE') ? JSON_INVALID_UTF8_IGNORE : 0; // phpcs:enable $out = new Encoder($connection, $jsonInvalidUtf8Ignore); //$in = new Decoder($connection, true, 512, $jsonInvalidUtf8Ignore, 128 * 1024 * 1024); /** @var ResultCacheManager $resultCacheManager */ $resultCacheManager = $container->getByType(ResultCacheManagerFactory::class)->create([]); $projectConfigArray = $inceptionResult->getProjectConfigArray(); /** @var AnalyserResultFinalizer $analyserResultFinalizer */ $analyserResultFinalizer = $container->getByType(AnalyserResultFinalizer::class); try { [$inceptionFiles, $isOnlyFiles] = $inceptionResult->getFiles(); } catch (PathNotFoundException|\PHPStan\Command\InceptionNotSuccessfulException $e) { throw new ShouldNotHappenException(); } $out->write(['action' => 'analysisStart', 'result' => ['analysedFiles' => $inceptionFiles]]); $resultCache = $resultCacheManager->restore($inceptionFiles, \false, \false, $projectConfigArray, $inceptionResult->getErrorOutput()); $errorsFromResultCacheTmp = $resultCache->getErrors(); $locallyIgnoredErrorsFromResultCacheTmp = $resultCache->getLocallyIgnoredErrors(); foreach ($resultCache->getFilesToAnalyse() as $fileToAnalyse) { unset($errorsFromResultCacheTmp[$fileToAnalyse]); unset($locallyIgnoredErrorsFromResultCacheTmp[$fileToAnalyse]); } $errorsFromResultCache = []; foreach ($errorsFromResultCacheTmp as $errorsByFile) { foreach ($errorsByFile as $error) { $errorsFromResultCache[] = $error; } } [$errorsFromResultCache, $ignoredErrorsFromResultCache] = $this->filterErrors($errorsFromResultCache, $ignoredErrorHelperResult, $isOnlyFiles, $inceptionFiles, \false); foreach ($locallyIgnoredErrorsFromResultCacheTmp as $locallyIgnoredErrors) { foreach ($locallyIgnoredErrors as $locallyIgnoredError) { $ignoredErrorsFromResultCache[] = [$locallyIgnoredError, null]; } } $out->write(['action' => 'analysisStream', 'result' => ['errors' => $errorsFromResultCache, 'ignoredErrors' => $ignoredErrorsFromResultCache, 'analysedFiles' => array_diff($inceptionFiles, $resultCache->getFilesToAnalyse())]]); $filesToAnalyse = $resultCache->getFilesToAnalyse(); usort($filesToAnalyse, static function (string $a, string $b) : int { $aTime = @filemtime($a); if ($aTime === \false) { return 1; } $bTime = @filemtime($b); if ($bTime === \false) { return -1; } // files are sorted from the oldest // because ParallelAnalyser reverses the scheduler jobs to do the smallest // jobs first return $aTime <=> $bTime; }); $this->runAnalyser($loop, $container, $filesToAnalyse, $configuration, $input, function (array $errors, array $locallyIgnoredErrors, array $analysedFiles) use($out, $ignoredErrorHelperResult, $isOnlyFiles, $inceptionFiles) : void { $internalErrors = []; foreach ($errors as $fileSpecificError) { if (!$fileSpecificError->hasNonIgnorableException()) { continue; } $internalErrors[] = $this->transformErrorIntoInternalError($fileSpecificError); } if (count($internalErrors) > 0) { $out->write(['action' => 'analysisCrash', 'data' => ['internalErrors' => $internalErrors]]); return; } [$errors, $ignoredErrors] = $this->filterErrors($errors, $ignoredErrorHelperResult, $isOnlyFiles, $inceptionFiles, \false); foreach ($locallyIgnoredErrors as $locallyIgnoredError) { $ignoredErrors[] = [$locallyIgnoredError, null]; } $out->write(['action' => 'analysisStream', 'result' => ['errors' => $errors, 'ignoredErrors' => $ignoredErrors, 'analysedFiles' => $analysedFiles]]); })->then(function (AnalyserResult $intermediateAnalyserResult) use($analyserResultFinalizer, $resultCacheManager, $resultCache, $inceptionResult, $isOnlyFiles, $ignoredErrorHelperResult, $inceptionFiles, $out) : void { $analyserResult = $resultCacheManager->process($intermediateAnalyserResult, $resultCache, $inceptionResult->getErrorOutput(), \false, \true)->getAnalyserResult(); $finalizerResult = $analyserResultFinalizer->finalize($analyserResult, $isOnlyFiles, \false); $internalErrors = []; foreach ($finalizerResult->getAnalyserResult()->getInternalErrors() as $internalError) { $internalErrors[] = new InternalError($internalError->getTraceAsString() !== null ? sprintf('Internal error: %s', $internalError->getMessage()) : $internalError->getMessage(), $internalError->getContextDescription(), $internalError->getTrace(), $internalError->getTraceAsString(), $internalError->shouldReportBug()); } foreach ($finalizerResult->getAnalyserResult()->getUnorderedErrors() as $fileSpecificError) { if (!$fileSpecificError->hasNonIgnorableException()) { continue; } $internalErrors[] = $this->transformErrorIntoInternalError($fileSpecificError); } $hasInternalErrors = count($internalErrors) > 0 || $finalizerResult->getAnalyserResult()->hasReachedInternalErrorsCountLimit(); if ($hasInternalErrors) { $out->write(['action' => 'analysisCrash', 'data' => ['internalErrors' => count($internalErrors) > 0 ? $internalErrors : [new InternalError('Internal error occurred', 'running analyser in PHPStan Pro worker', [], null, \false)]]]); } [$collectorErrors, $ignoredCollectorErrors] = $this->filterErrors($finalizerResult->getCollectorErrors(), $ignoredErrorHelperResult, $isOnlyFiles, $inceptionFiles, $hasInternalErrors); foreach ($finalizerResult->getLocallyIgnoredCollectorErrors() as $locallyIgnoredCollectorError) { $ignoredCollectorErrors[] = [$locallyIgnoredCollectorError, null]; } $out->write(['action' => 'analysisStream', 'result' => ['errors' => $collectorErrors, 'ignoredErrors' => $ignoredCollectorErrors, 'analysedFiles' => []]]); $ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process($finalizerResult->getErrors(), $isOnlyFiles, $inceptionFiles, $hasInternalErrors); $ignoreFileErrors = []; foreach ($ignoredErrorHelperProcessedResult->getNotIgnoredErrors() as $error) { if ($error->getIdentifier() === null) { continue; } if (!in_array($error->getIdentifier(), ['ignore.count', 'ignore.unmatched', 'ignore.unmatchedLine', 'ignore.unmatchedIdentifier'], \true)) { continue; } $ignoreFileErrors[] = $error; } $out->end(['action' => 'analysisEnd', 'result' => ['ignoreFileErrors' => $ignoreFileErrors, 'ignoreNotFileErrors' => $ignoredErrorHelperProcessedResult->getOtherIgnoreMessages()]]); }); }); $loop->run(); return 0; } private function transformErrorIntoInternalError(Error $error) : InternalError { $message = $error->getMessage(); $metadata = $error->getMetadata(); if ($error->getIdentifier() === 'phpstan.internal' && array_key_exists(InternalError::STACK_TRACE_AS_STRING_METADATA_KEY, $metadata)) { $message = sprintf('Internal error: %s', $message); } return new InternalError($message, sprintf('analysing file %s', $error->getTraitFilePath() ?? $error->getFilePath()), $metadata[InternalError::STACK_TRACE_METADATA_KEY] ?? [], $metadata[InternalError::STACK_TRACE_AS_STRING_METADATA_KEY] ?? null, \true); } /** * @param string[] $inceptionFiles * @param array $errors * @return array{list, list} */ private function filterErrors(array $errors, IgnoredErrorHelperResult $ignoredErrorHelperResult, bool $onlyFiles, array $inceptionFiles, bool $hasInternalErrors) : array { $ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process($errors, $onlyFiles, $inceptionFiles, $hasInternalErrors); $finalErrors = []; foreach ($ignoredErrorHelperProcessedResult->getNotIgnoredErrors() as $error) { if ($error->getIdentifier() === null) { $finalErrors[] = $error; continue; } if (in_array($error->getIdentifier(), ['ignore.count', 'ignore.unmatched'], \true)) { continue; } $finalErrors[] = $error; } return [$finalErrors, $ignoredErrorHelperProcessedResult->getIgnoredErrors()]; } /** * @param string[] $files * @param callable(list, list, string[]): void $onFileAnalysisHandler * @return PromiseInterface */ private function runAnalyser(LoopInterface $loop, Container $container, array $files, ?string $configuration, InputInterface $input, callable $onFileAnalysisHandler) : PromiseInterface { /** @var ParallelAnalyser $parallelAnalyser */ $parallelAnalyser = $container->getByType(ParallelAnalyser::class); $filesCount = count($files); if ($filesCount === 0) { return resolve(new AnalyserResult([], [], [], [], [], [], [], [], [], [], [], \false, memory_get_peak_usage(\true))); } /** @var Scheduler $scheduler */ $scheduler = $container->getByType(Scheduler::class); /** @var CpuCoreCounter $cpuCoreCounter */ $cpuCoreCounter = $container->getByType(CpuCoreCounter::class); $schedule = $scheduler->scheduleWork($cpuCoreCounter->getNumberOfCpuCores(), $files); $mainScript = null; if (isset($_SERVER['argv'][0]) && is_file($_SERVER['argv'][0])) { $mainScript = $_SERVER['argv'][0]; } return $parallelAnalyser->analyse($loop, $schedule, $mainScript, null, $configuration, null, null, $input, $onFileAnalysisHandler); } } scheduler = $scheduler; $this->analyser = $analyser; $this->parallelAnalyser = $parallelAnalyser; $this->cpuCoreCounter = $cpuCoreCounter; } /** * @param string[] $files * @param string[] $allAnalysedFiles * @param Closure(string $file): void|null $preFileCallback * @param Closure(int ): void|null $postFileCallback */ public function runAnalyser(array $files, array $allAnalysedFiles, ?Closure $preFileCallback, ?Closure $postFileCallback, bool $debug, bool $allowParallel, ?string $projectConfigFile, ?string $tmpFile, ?string $insteadOfFile, InputInterface $input) : AnalyserResult { $filesCount = count($files); if ($filesCount === 0) { return new AnalyserResult([], [], [], [], [], [], [], [], [], [], [], \false, memory_get_peak_usage(\true)); } $schedule = $this->scheduler->scheduleWork($this->cpuCoreCounter->getNumberOfCpuCores(), $files); $mainScript = null; if (isset($_SERVER['argv'][0]) && is_file($_SERVER['argv'][0])) { $mainScript = $_SERVER['argv'][0]; } if (!$debug && $allowParallel && function_exists('proc_open') && $mainScript !== null && $schedule->getNumberOfProcesses() > 0) { $loop = new StreamSelectLoop(); $result = null; $promise = $this->parallelAnalyser->analyse($loop, $schedule, $mainScript, $postFileCallback, $projectConfigFile, $tmpFile, $insteadOfFile, $input, null); $promise->then(static function (AnalyserResult $tmp) use(&$result) : void { $result = $tmp; }); $loop->run(); if ($result === null) { throw new ShouldNotHappenException(); } return $result; } return $this->analyser->analyse($this->switchTmpFile($files, $insteadOfFile, $tmpFile), $preFileCallback, $postFileCallback, $debug, $this->switchTmpFile($allAnalysedFiles, $insteadOfFile, $tmpFile)); } /** * @param string[] $analysedFiles * @return string[] */ private function switchTmpFile(array $analysedFiles, ?string $insteadOfFile, ?string $tmpFile) : array { if ($insteadOfFile === null) { return $analysedFiles; } $analysedFiles = array_values(array_filter($analysedFiles, static function (string $file) use($insteadOfFile) : bool { return $file !== $insteadOfFile; })); if ($tmpFile !== null) { array_unshift($analysedFiles, $tmpFile); } return $analysedFiles; } } */ private $ignoredTypes; /** * @var bool */ private $anchorsInTheMiddle; /** * @var bool */ private $allErrorsIgnored; /** * @var ?string */ private $wrongSequence; /** * @var ?string */ private $escapedWrongSequence; /** * @param array $ignoredTypes */ public function __construct(array $ignoredTypes, bool $anchorsInTheMiddle, bool $allErrorsIgnored, ?string $wrongSequence = null, ?string $escapedWrongSequence = null) { $this->ignoredTypes = $ignoredTypes; $this->anchorsInTheMiddle = $anchorsInTheMiddle; $this->allErrorsIgnored = $allErrorsIgnored; $this->wrongSequence = $wrongSequence; $this->escapedWrongSequence = $escapedWrongSequence; } /** * @return array */ public function getIgnoredTypes() : array { return $this->ignoredTypes; } public function hasAnchorsInTheMiddle() : bool { return $this->anchorsInTheMiddle; } public function areAllErrorsIgnored() : bool { return $this->allErrorsIgnored; } public function getWrongSequence() : ?string { return $this->wrongSequence; } public function getEscapedWrongSequence() : ?string { return $this->escapedWrongSequence; } } showProgress = $input->hasOption(self::OPTION_NO_PROGRESS) && !(bool) $input->getOption(self::OPTION_NO_PROGRESS); } private function isCiDetected() : bool { if ($this->isCiDetected === null) { $ciDetector = new CiDetector(); $this->isCiDetected = $ciDetector->isCiDetected(); } return $this->isCiDetected; } /** * @param string[] $headers * @param string[][] $rows */ public function table(array $headers, array $rows) : void { /** @var int $terminalWidth */ $terminalWidth = (new Terminal())->getWidth() - 2; $maxHeaderWidth = strlen($headers[0]); foreach ($rows as $row) { $length = strlen($row[0]); if ($maxHeaderWidth !== 0 && $length <= $maxHeaderWidth) { continue; } $maxHeaderWidth = $length; } // manual wrapping could be replaced with $table->setColumnMaxWidth() // but it's buggy for lines // https://github.com/symfony/symfony/issues/45520 // https://github.com/symfony/symfony/issues/45521 $headers = $this->wrap($headers, $terminalWidth, $maxHeaderWidth); foreach ($headers as $i => $header) { $newHeader = []; foreach (explode("\n", $header) as $h) { $newHeader[] = sprintf('%s', $h); } $headers[$i] = implode("\n", $newHeader); } foreach ($rows as $i => $row) { $rows[$i] = $this->wrap($row, $terminalWidth, $maxHeaderWidth); } $table = $this->createTable(); array_unshift($rows, $headers, new TableSeparator()); $table->setRows($rows); $table->render(); $this->newLine(); } /** * @param string[] $rows * @return string[] */ private function wrap(array $rows, int $terminalWidth, int $maxHeaderWidth) : array { foreach ($rows as $i => $column) { $columnRows = explode("\n", $column); foreach ($columnRows as $k => $columnRow) { if (str_starts_with($columnRow, '✏️')) { continue; } $wrapped = wordwrap($columnRow, $terminalWidth - $maxHeaderWidth - 5); if (str_starts_with($columnRow, '💡 ')) { $wrappedLines = explode("\n", $wrapped); $newWrappedLines = []; foreach ($wrappedLines as $l => $line) { if ($l === 0) { $newWrappedLines[] = $line; continue; } $newWrappedLines[] = ' ' . $line; } $columnRows[$k] = implode("\n", $newWrappedLines); } else { $columnRows[$k] = $wrapped; } } $rows[$i] = implode("\n", $columnRows); } return $rows; } public function createProgressBar(int $max = 0) : ProgressBar { $this->progressBar = parent::createProgressBar($max); $format = $this->getProgressBarFormat(); if ($format !== null) { $this->progressBar->setFormat($format); } $ci = $this->isCiDetected(); $this->progressBar->setOverwrite(!$ci); if ($ci) { $this->progressBar->minSecondsBetweenRedraws(15); $this->progressBar->maxSecondsBetweenRedraws(30); } elseif (DIRECTORY_SEPARATOR === '\\') { $this->progressBar->minSecondsBetweenRedraws(0.5); $this->progressBar->maxSecondsBetweenRedraws(2); } else { $this->progressBar->minSecondsBetweenRedraws(0.1); $this->progressBar->maxSecondsBetweenRedraws(0.5); } return $this->progressBar; } private function getProgressBarFormat() : ?string { switch ($this->getVerbosity()) { case OutputInterface::VERBOSITY_NORMAL: $formatName = ProgressBar::FORMAT_NORMAL; break; case OutputInterface::VERBOSITY_VERBOSE: $formatName = ProgressBar::FORMAT_VERBOSE; break; case OutputInterface::VERBOSITY_VERY_VERBOSE: case OutputInterface::VERBOSITY_DEBUG: $formatName = ProgressBar::FORMAT_VERY_VERBOSE; break; default: $formatName = null; break; } if ($formatName === null) { return null; } return ProgressBar::getFormatDefinition($formatName); } public function progressStart(int $max = 0) : void { if (!$this->showProgress) { return; } parent::progressStart($max); } public function progressAdvance(int $step = 1) : void { if (!$this->showProgress) { return; } parent::progressAdvance($step); } public function progressFinish() : void { if (!$this->showProgress) { return; } parent::progressFinish(); } } */ private $dnsServers; /** * @var string[] */ private $composerAutoloaderProjectPaths; /** * @var string[] */ private $allConfigFiles; /** * @var ?string */ private $cliAutoloadFile; /** * @var string[] */ private $bootstrapFiles; /** * @var ?string */ private $editorUrl; /** * @var string */ private $usedLevel; /** @var PromiseInterface|null */ private $processInProgress = null; /** * @var bool */ private $fileMonitorActive = \true; /** * @param string[] $analysedPaths * @param list $dnsServers * @param string[] $composerAutoloaderProjectPaths * @param string[] $allConfigFiles * @param string[] $bootstrapFiles */ public function __construct(FileMonitor $fileMonitor, IgnoredErrorHelper $ignoredErrorHelper, StubFilesProvider $stubFilesProvider, array $analysedPaths, string $currentWorkingDirectory, string $proTmpDir, array $dnsServers, array $composerAutoloaderProjectPaths, array $allConfigFiles, ?string $cliAutoloadFile, array $bootstrapFiles, ?string $editorUrl, string $usedLevel) { $this->fileMonitor = $fileMonitor; $this->ignoredErrorHelper = $ignoredErrorHelper; $this->stubFilesProvider = $stubFilesProvider; $this->analysedPaths = $analysedPaths; $this->currentWorkingDirectory = $currentWorkingDirectory; $this->proTmpDir = $proTmpDir; $this->dnsServers = $dnsServers; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; $this->allConfigFiles = $allConfigFiles; $this->cliAutoloadFile = $cliAutoloadFile; $this->bootstrapFiles = $bootstrapFiles; $this->editorUrl = $editorUrl; $this->usedLevel = $usedLevel; } public function run(?string $projectConfigFile, InputInterface $input, OutputInterface $output, int $filesCount, string $mainScript) : int { $loop = new StreamSelectLoop(); $server = new TcpServer('127.0.0.1:0', $loop); /** @var string $serverAddress */ $serverAddress = $server->getAddress(); /** @var int<0, 65535> $serverPort */ $serverPort = parse_url($serverAddress, PHP_URL_PORT); $server->on('connection', function (ConnectionInterface $connection) use($loop, $projectConfigFile, $input, $output, $mainScript, $filesCount) : void { // phpcs:disable SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly $jsonInvalidUtf8Ignore = defined('JSON_INVALID_UTF8_IGNORE') ? JSON_INVALID_UTF8_IGNORE : 0; // phpcs:enable $decoder = new Decoder($connection, \true, 512, $jsonInvalidUtf8Ignore, 128 * 1024 * 1024); $encoder = new Encoder($connection, $jsonInvalidUtf8Ignore); $encoder->write(['action' => 'initialData', 'data' => ['currentWorkingDirectory' => $this->currentWorkingDirectory, 'analysedPaths' => $this->analysedPaths, 'projectConfigFile' => $projectConfigFile, 'filesCount' => $filesCount, 'phpstanVersion' => ComposerHelper::getPhpStanVersion(), 'editorUrl' => $this->editorUrl, 'ruleLevel' => $this->usedLevel]]); $decoder->on('data', function (array $data) use($output) : void { if ($data['action'] === 'webPort') { $output->writeln(sprintf('Open your web browser at: http://127.0.0.1:%d', $data['data']['port'])); $output->writeln('Press [Ctrl-C] to quit.'); return; } if ($data['action'] === 'resumeFileMonitor') { $this->fileMonitorActive = \true; return; } if ($data['action'] === 'pauseFileMonitor') { $this->fileMonitorActive = \false; return; } }); $this->fileMonitor->initialize(array_merge($this->getComposerLocks(), $this->getComposerInstalled(), $this->getExecutedFiles(), $this->getStubFiles(), $this->allConfigFiles)); $this->analyse($loop, $mainScript, $projectConfigFile, $input, $output, $encoder); $this->monitorFileChanges($loop, function (FileMonitorResult $changes) use($loop, $mainScript, $projectConfigFile, $input, $encoder, $output) : void { if ($this->processInProgress !== null) { $this->processInProgress->cancel(); $this->processInProgress = null; } if (count($changes->getChangedFiles()) > 0) { $encoder->write(['action' => 'changedFiles', 'data' => ['paths' => $changes->getChangedFiles()]]); } $this->analyse($loop, $mainScript, $projectConfigFile, $input, $output, $encoder); }); }); try { $fixerProcess = $this->getFixerProcess($output, $serverPort); } catch (\PHPStan\Command\FixerProcessException $e) { return 1; } $fixerProcess->start($loop); $fixerProcess->on('exit', function ($exitCode) use($output, $loop) : void { $loop->stop(); if ($exitCode === null) { return; } if ($exitCode === 0) { return; } $output->writeln(sprintf('PHPStan Pro process exited with code %d.', $exitCode)); @unlink($this->proTmpDir . '/phar-info.json'); }); $loop->run(); return 0; } /** * @throws FixerProcessException */ private function getFixerProcess(OutputInterface $output, int $serverPort) : Process { try { DirectoryCreator::ensureDirectoryExists($this->proTmpDir, 0777); } catch (DirectoryCreatorException $e) { $output->writeln($e->getMessage()); throw new \PHPStan\Command\FixerProcessException(); } $pharPath = $this->proTmpDir . '/phpstan-fixer.phar'; $infoPath = $this->proTmpDir . '/phar-info.json'; try { $this->downloadPhar($output, $pharPath, $infoPath); } catch (RuntimeException $e) { if (!is_file($pharPath)) { $this->printDownloadError($output, $e); throw new \PHPStan\Command\FixerProcessException(); } } $pubKeyPath = $pharPath . '.pubkey'; FileWriter::write($pubKeyPath, FileReader::read(__DIR__ . '/fixer-phar.pubkey')); try { $phar = new Phar($pharPath); } catch (Throwable $e) { @unlink($pharPath); @unlink($infoPath); $output->writeln('PHPStan Pro PHAR signature is corrupted.'); $output->writeln(sprintf('%s: %s', get_class($e), $e->getMessage())); throw new \PHPStan\Command\FixerProcessException(); } if ($phar->getSignature()['hash_type'] !== 'OpenSSL') { @unlink($pharPath); @unlink($infoPath); $output->writeln('PHPStan Pro PHAR signature is corrupted.'); $output->writeln(sprintf('Wrong hash type: %s', $phar->getSignature()['hash_type'])); throw new \PHPStan\Command\FixerProcessException(); } $env = getenv(); $env['PHPSTAN_PRO_TMP_DIR'] = $this->proTmpDir; $forcedPort = $_SERVER['PHPSTAN_PRO_WEB_PORT'] ?? null; if ($forcedPort !== null) { $env['PHPSTAN_PRO_WEB_PORT'] = $_SERVER['PHPSTAN_PRO_WEB_PORT']; $isDocker = $this->isDockerRunning(); if ($isDocker) { $output->writeln('Running in Docker? Don\'t forget to do these steps:'); $output->writeln('1) Publish this port when running Docker:'); $output->writeln(sprintf(' -p 127.0.0.1:%d:%d', $_SERVER['PHPSTAN_PRO_WEB_PORT'], $_SERVER['PHPSTAN_PRO_WEB_PORT'])); $output->writeln('2) Map the temp directory to a persistent volume'); $output->writeln(' so that you don\'t have to log in every time:'); $output->writeln(sprintf(' -v ~/.phpstan-pro:%s', $this->proTmpDir)); $output->writeln(''); } } else { $isDocker = $this->isDockerRunning(); if ($isDocker) { $output->writeln('Running in Docker? You need to do these steps in order to launch PHPStan Pro:'); $output->writeln(''); $output->writeln('1) Set the PHPSTAN_PRO_WEB_PORT environment variable in the Dockerfile:'); $output->writeln(' ENV PHPSTAN_PRO_WEB_PORT=11111'); $output->writeln('2) Expose this port in the Dockerfile:'); $output->writeln(' EXPOSE 11111'); $output->writeln('3) Publish this port when running Docker:'); $output->writeln(' -p 127.0.0.1:11111:11111'); $output->writeln('4) Map the temp directory to a persistent volume'); $output->writeln(' so that you don\'t have to log in every time:'); $output->writeln(sprintf(' -v ~/phpstan-pro:%s', $this->proTmpDir)); $output->writeln(''); } } return new Process(sprintf('%s -d memory_limit=%s %s --port %d', escapeshellarg(PHP_BINARY), escapeshellarg(ini_get('memory_limit')), escapeshellarg($pharPath), $serverPort), null, $env, []); } private function downloadPhar(OutputInterface $output, string $pharPath, string $infoPath) : void { $currentVersion = null; $branch = '1.1.x'; if (is_file($pharPath) && is_file($infoPath)) { /** @var array{version: string, date: string, branch?: string} $currentInfo */ $currentInfo = Json::decode(FileReader::read($infoPath), Json::FORCE_ARRAY); $currentVersion = $currentInfo['version']; $currentBranch = $currentInfo['branch'] ?? 'master'; $currentDate = DateTime::createFromFormat(DateTime::ATOM, $currentInfo['date']); if ($currentDate === \false) { throw new ShouldNotHappenException(); } if ($currentBranch === $branch && new DateTimeImmutable('', new DateTimeZone('UTC')) <= $currentDate->modify('+24 hours')) { return; } $output->writeln('Checking if there\'s a new PHPStan Pro release...'); } $dnsConfig = new Config(); $dnsConfig->nameservers = $this->dnsServers; $client = new Browser(new Connector(['timeout' => 5, 'tls' => ['cafile' => CaBundle::getBundledCaBundlePath()], 'dns' => $dnsConfig])); /** * @var array{url: string, version: string} $latestInfo */ $latestInfo = Json::decode((string) await($client->get(sprintf('https://fixer-download-api.phpstan.com/latest?%s', http_build_query(['phpVersion' => PHP_VERSION_ID, 'branch' => $branch]))))->getBody(), Json::FORCE_ARRAY); if ($currentVersion !== null && $latestInfo['version'] === $currentVersion) { $this->writeInfoFile($infoPath, $latestInfo['version'], $branch); $output->writeln('You\'re running the latest PHPStan Pro!'); return; } $output->writeln('Downloading the latest PHPStan Pro...'); $pharPathResource = fopen($pharPath, 'w'); if ($pharPathResource === \false) { throw new ShouldNotHappenException(sprintf('Could not open file %s for writing.', $pharPath)); } $progressBar = new ProgressBar($output); $client->requestStreaming('GET', $latestInfo['url'])->then(static function (ResponseInterface $response) use($progressBar, $pharPathResource) : void { $body = $response->getBody(); if (!$body instanceof ReadableStreamInterface) { throw new ShouldNotHappenException(); } $totalSize = (int) $response->getHeaderLine('Content-Length'); $progressBar->setFormat('file_download'); $progressBar->setMessage(sprintf('%.2f MB', $totalSize / 1000000), 'fileSize'); $progressBar->start($totalSize); $bytes = 0; $body->on('data', static function ($chunk) use($pharPathResource, $progressBar, &$bytes) : void { $bytes += strlen($chunk); fwrite($pharPathResource, $chunk); $progressBar->setProgress($bytes); }); }, function (Throwable $e) use($output) : void { $this->printDownloadError($output, $e); }); Loop::run(); fclose($pharPathResource); $progressBar->finish(); $output->writeln(''); $output->writeln(''); $this->writeInfoFile($infoPath, $latestInfo['version'], $branch); } private function printDownloadError(OutputInterface $output, Throwable $e) : void { $output->writeln(sprintf('Could not download the PHPStan Pro executable: %s', $e->getMessage())); $output->writeln(''); $output->writeln('Try different DNS servers in your configuration file:'); $output->writeln(''); $output->writeln('parameters:'); $output->writeln("\tpro:"); $output->writeln("\t\tdnsServers!:"); $output->writeln("\t\t\t- '8.8.8.8'"); $output->writeln(''); } private function writeInfoFile(string $infoPath, string $version, string $branch) : void { FileWriter::write($infoPath, Json::encode(['version' => $version, 'branch' => $branch, 'date' => (new DateTimeImmutable('', new DateTimeZone('UTC')))->format(DateTime::ATOM)])); } /** * @param callable(FileMonitorResult): void $hasChangesCallback */ private function monitorFileChanges(LoopInterface $loop, callable $hasChangesCallback) : void { $callback = function () use(&$callback, $loop, $hasChangesCallback) : void { if (!$this->fileMonitorActive) { $loop->addTimer(1.0, $callback); return; } if ($this->processInProgress !== null) { $loop->addTimer(1.0, $callback); return; } $changes = $this->fileMonitor->getChanges(); if ($changes->hasAnyChanges()) { $hasChangesCallback($changes); } $loop->addTimer(1.0, $callback); }; $loop->addTimer(1.0, $callback); } private function analyse(LoopInterface $loop, string $mainScript, ?string $projectConfigFile, InputInterface $input, OutputInterface $output, Encoder $phpstanFixerEncoder) : void { $ignoredErrorHelperResult = $this->ignoredErrorHelper->initialize(); if (count($ignoredErrorHelperResult->getErrors()) > 0) { throw new ShouldNotHappenException(); } // TCP server for fixer:worker (TCP client) $server = new TcpServer('127.0.0.1:0', $loop); /** @var string $serverAddress */ $serverAddress = $server->getAddress(); /** @var int<0, 65535> $serverPort */ $serverPort = parse_url($serverAddress, PHP_URL_PORT); $server->on('connection', static function (ConnectionInterface $connection) use($phpstanFixerEncoder) : void { // phpcs:disable SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly $jsonInvalidUtf8Ignore = defined('JSON_INVALID_UTF8_IGNORE') ? JSON_INVALID_UTF8_IGNORE : 0; // phpcs:enable $decoder = new Decoder($connection, \true, 512, $jsonInvalidUtf8Ignore, 128 * 1024 * 1024); $decoder->on('data', static function (array $data) use($phpstanFixerEncoder) : void { $phpstanFixerEncoder->write($data); }); }); $process = new ProcessPromise($loop, 'changedFileAnalysis', ProcessHelper::getWorkerCommand($mainScript, 'fixer:worker', $projectConfigFile, ['--server-port', (string) $serverPort], $input)); $this->processInProgress = $process->run(); $this->processInProgress->then(function () use($server) : void { $this->processInProgress = null; $server->close(); }, function (Throwable $e) use($server, $phpstanFixerEncoder) : void { $this->processInProgress = null; $server->close(); if ($e instanceof ProcessCanceledException) { return; } if ($e instanceof ProcessCrashedException) { $message = 'Analysis crashed'; $traceAsString = $e->getMessage(); $trace = []; } else { $message = $e->getMessage(); $traceAsString = $e->getTraceAsString(); $trace = InternalError::prepareTrace($e); } $phpstanFixerEncoder->write(['action' => 'analysisCrash', 'data' => ['internalErrors' => [new InternalError($message, 'running PHPStan Pro worker', $trace, $traceAsString, \false)]]]); }); } private function isDockerRunning() : bool { return is_file('/.dockerenv'); } /** * @return list */ private function getComposerLocks() : array { $locks = []; foreach ($this->composerAutoloaderProjectPaths as $autoloadPath) { $lockPath = $autoloadPath . '/composer.lock'; if (!is_file($lockPath)) { continue; } $locks[] = $lockPath; } return $locks; } /** * @return list */ private function getComposerInstalled() : array { $files = []; foreach ($this->composerAutoloaderProjectPaths as $autoloadPath) { $composer = ComposerHelper::getComposerConfig($autoloadPath); if ($composer === null) { continue; } $filePath = ComposerHelper::getVendorDirFromComposerConfig($autoloadPath, $composer) . '/composer/installed.php'; if (!is_file($filePath)) { continue; } $files[] = $filePath; } return $files; } /** * @return list */ private function getExecutedFiles() : array { $files = []; if ($this->cliAutoloadFile !== null) { $files[] = $this->cliAutoloadFile; } foreach ($this->bootstrapFiles as $bootstrapFile) { $files[] = $bootstrapFile; } return $files; } /** * @return list */ private function getStubFiles() : array { $stubFiles = []; foreach ($this->stubFilesProvider->getProjectStubFiles() as $stubFile) { $stubFiles[] = $stubFile; } return $stubFiles; } } */ private $notFileSpecificErrors; /** * @var list */ private $internalErrors; /** * @var list */ private $warnings; /** * @var list */ private $collectedData; /** * @var bool */ private $defaultLevelUsed; /** * @var ?string */ private $projectConfigFile; /** * @var bool */ private $savedResultCache; /** * @var int */ private $peakMemoryUsageBytes; /** * @var bool */ private $isResultCacheUsed; /** * @var array */ private $changedProjectExtensionFilesOutsideOfAnalysedPaths; /** @var list sorted by their file name, line number and message */ private $fileSpecificErrors; /** * @param list $fileSpecificErrors * @param list $notFileSpecificErrors * @param list $internalErrors * @param list $warnings * @param list $collectedData * @param array $changedProjectExtensionFilesOutsideOfAnalysedPaths */ public function __construct(array $fileSpecificErrors, array $notFileSpecificErrors, array $internalErrors, array $warnings, array $collectedData, bool $defaultLevelUsed, ?string $projectConfigFile, bool $savedResultCache, int $peakMemoryUsageBytes, bool $isResultCacheUsed, array $changedProjectExtensionFilesOutsideOfAnalysedPaths) { $this->notFileSpecificErrors = $notFileSpecificErrors; $this->internalErrors = $internalErrors; $this->warnings = $warnings; $this->collectedData = $collectedData; $this->defaultLevelUsed = $defaultLevelUsed; $this->projectConfigFile = $projectConfigFile; $this->savedResultCache = $savedResultCache; $this->peakMemoryUsageBytes = $peakMemoryUsageBytes; $this->isResultCacheUsed = $isResultCacheUsed; $this->changedProjectExtensionFilesOutsideOfAnalysedPaths = $changedProjectExtensionFilesOutsideOfAnalysedPaths; usort($fileSpecificErrors, static function (Error $a, Error $b) : int { return [$a->getFile(), $a->getLine(), $a->getMessage()] <=> [$b->getFile(), $b->getLine(), $b->getMessage()]; }); $this->fileSpecificErrors = $fileSpecificErrors; } public function hasErrors() : bool { return $this->getTotalErrorsCount() > 0; } public function getTotalErrorsCount() : int { return count($this->fileSpecificErrors) + count($this->notFileSpecificErrors); } /** * @return list sorted by their file name, line number and message */ public function getFileSpecificErrors() : array { return $this->fileSpecificErrors; } /** * @return list */ public function getNotFileSpecificErrors() : array { return $this->notFileSpecificErrors; } /** * @deprecated Use getInternalErrorObjects * @return list */ public function getInternalErrors() : array { return array_map(static function (InternalError $internalError) { return $internalError->getMessage(); }, $this->internalErrors); } /** * @return list */ public function getInternalErrorObjects() : array { return $this->internalErrors; } /** * @return list */ public function getWarnings() : array { return $this->warnings; } public function hasWarnings() : bool { return count($this->warnings) > 0; } /** * @return list */ public function getCollectedData() : array { return $this->collectedData; } public function isDefaultLevelUsed() : bool { return $this->defaultLevelUsed; } public function getProjectConfigFile() : ?string { return $this->projectConfigFile; } public function hasInternalErrors() : bool { return count($this->internalErrors) > 0; } public function isResultCacheSaved() : bool { return $this->savedResultCache; } public function getPeakMemoryUsageBytes() : int { return $this->peakMemoryUsageBytes; } public function isResultCacheUsed() : bool { return $this->isResultCacheUsed; } /** * @return array */ public function getChangedProjectExtensionFilesOutsideOfAnalysedPaths() : array { return $this->changedProjectExtensionFilesOutsideOfAnalysedPaths; } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } protected function configure() : void { $this->setName(self::NAME)->setDescription('(Internal) Support for parallel analysis.')->setDefinition([new InputArgument('paths', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Paths with source code to run analysis on'), new InputOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Path to project configuration file'), new InputOption(\PHPStan\Command\AnalyseCommand::OPTION_LEVEL, 'l', InputOption::VALUE_REQUIRED, 'Level of rule options - the higher the stricter'), new InputOption('autoload-file', 'a', InputOption::VALUE_REQUIRED, 'Project\'s additional autoload file path'), new InputOption('memory-limit', null, InputOption::VALUE_REQUIRED, 'Memory limit for analysis'), new InputOption('xdebug', null, InputOption::VALUE_NONE, 'Allow running with Xdebug for debugging purposes'), new InputOption('port', null, InputOption::VALUE_REQUIRED), new InputOption('identifier', null, InputOption::VALUE_REQUIRED), new InputOption('tmp-file', null, InputOption::VALUE_REQUIRED), new InputOption('instead-of', null, InputOption::VALUE_REQUIRED)])->setHidden(\true); } protected function execute(InputInterface $input, OutputInterface $output) : int { $paths = $input->getArgument('paths'); $memoryLimit = $input->getOption('memory-limit'); $autoloadFile = $input->getOption('autoload-file'); $configuration = $input->getOption('configuration'); $level = $input->getOption(\PHPStan\Command\AnalyseCommand::OPTION_LEVEL); $allowXdebug = $input->getOption('xdebug'); $port = $input->getOption('port'); $identifier = $input->getOption('identifier'); $tmpFile = $input->getOption('tmp-file'); $insteadOfFile = $input->getOption('instead-of'); if (!is_array($paths) || !is_string($memoryLimit) && $memoryLimit !== null || !is_string($autoloadFile) && $autoloadFile !== null || !is_string($configuration) && $configuration !== null || !is_string($level) && $level !== null || !is_bool($allowXdebug) || !is_string($port) || !is_string($identifier) || !is_string($tmpFile) && $tmpFile !== null || !is_string($insteadOfFile) && $insteadOfFile !== null) { throw new ShouldNotHappenException(); } try { $inceptionResult = \PHPStan\Command\CommandHelper::begin($input, $output, $paths, $memoryLimit, $autoloadFile, $this->composerAutoloaderProjectPaths, $configuration, null, $level, $allowXdebug, \false, $tmpFile, $insteadOfFile, \false); } catch (\PHPStan\Command\InceptionNotSuccessfulException $e) { return 1; } $loop = new StreamSelectLoop(); $container = $inceptionResult->getContainer(); try { [$analysedFiles] = $inceptionResult->getFiles(); $analysedFiles = $this->switchTmpFile($analysedFiles, $insteadOfFile, $tmpFile); } catch (PathNotFoundException $e) { $inceptionResult->getErrorOutput()->writeLineFormatted(sprintf('%s', $e->getMessage())); return 1; } catch (\PHPStan\Command\InceptionNotSuccessfulException $e) { return 1; } $nodeScopeResolver = $container->getByType(NodeScopeResolver::class); $nodeScopeResolver->setAnalysedFiles($analysedFiles); $analysedFiles = array_fill_keys($analysedFiles, \true); $tcpConnector = new TcpConnector($loop); $tcpConnector->connect(sprintf('127.0.0.1:%d', $port))->then(function (ConnectionInterface $connection) use($container, $identifier, $output, $analysedFiles, $tmpFile, $insteadOfFile) : void { // phpcs:disable SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly $jsonInvalidUtf8Ignore = defined('JSON_INVALID_UTF8_IGNORE') ? \JSON_INVALID_UTF8_IGNORE : 0; // phpcs:enable $out = new Encoder($connection, $jsonInvalidUtf8Ignore); $in = new Decoder($connection, \true, 512, $jsonInvalidUtf8Ignore, $container->getParameter('parallel')['buffer']); $out->write(['action' => 'hello', 'identifier' => $identifier]); $this->runWorker($container, $out, $in, $output, $analysedFiles, $tmpFile, $insteadOfFile); }); $loop->run(); if ($this->errorCount > 0) { return 1; } return 0; } /** * @param array $analysedFiles */ private function runWorker(Container $container, WritableStreamInterface $out, ReadableStreamInterface $in, OutputInterface $output, array $analysedFiles, ?string $tmpFile, ?string $insteadOfFile) : void { $handleError = function (Throwable $error) use($out, $output) : void { $this->errorCount++; $output->writeln(sprintf('Error: %s', $error->getMessage())); $out->write(['action' => 'result', 'result' => ['errors' => [], 'internalErrors' => [new InternalError($error->getMessage(), 'communicating with main process in parallel worker', InternalError::prepareTrace($error), $error->getTraceAsString(), \true)], 'filteredPhpErrors' => [], 'allPhpErrors' => [], 'locallyIgnoredErrors' => [], 'linesToIgnore' => [], 'unmatchedLineIgnores' => [], 'collectedData' => [], 'memoryUsage' => memory_get_peak_usage(\true), 'dependencies' => [], 'exportedNodes' => [], 'files' => [], 'internalErrorsCount' => 1]]); $out->end(); }; $out->on('error', $handleError); $fileAnalyser = $container->getByType(FileAnalyser::class); $ruleRegistry = $container->getByType(RuleRegistry::class); $collectorRegistry = $container->getByType(CollectorRegistry::class); $in->on('data', static function (array $json) use($fileAnalyser, $ruleRegistry, $collectorRegistry, $out, $analysedFiles, $tmpFile, $insteadOfFile) : void { $action = $json['action']; if ($action !== 'analyse') { return; } $internalErrorsCount = 0; $files = $json['files']; $errors = []; $internalErrors = []; $filteredPhpErrors = []; $allPhpErrors = []; $locallyIgnoredErrors = []; $linesToIgnore = []; $unmatchedLineIgnores = []; $collectedData = []; $dependencies = []; $usedTraitDependencies = []; $exportedNodes = []; foreach ($files as $file) { try { if ($file === $insteadOfFile) { $file = $tmpFile; } $fileAnalyserResult = $fileAnalyser->analyseFile($file, $analysedFiles, $ruleRegistry, $collectorRegistry, null); $fileErrors = $fileAnalyserResult->getErrors(); $filteredPhpErrors = array_merge($filteredPhpErrors, $fileAnalyserResult->getFilteredPhpErrors()); $allPhpErrors = array_merge($allPhpErrors, $fileAnalyserResult->getAllPhpErrors()); $linesToIgnore[$file] = $fileAnalyserResult->getLinesToIgnore(); $unmatchedLineIgnores[$file] = $fileAnalyserResult->getUnmatchedLineIgnores(); $dependencies[$file] = $fileAnalyserResult->getDependencies(); $usedTraitDependencies[$file] = $fileAnalyserResult->getUsedTraitDependencies(); $exportedNodes[$file] = $fileAnalyserResult->getExportedNodes(); foreach ($fileErrors as $fileError) { $errors[] = $fileError; } foreach ($fileAnalyserResult->getLocallyIgnoredErrors() as $locallyIgnoredError) { $locallyIgnoredErrors[] = $locallyIgnoredError; } foreach ($fileAnalyserResult->getCollectedData() as $data) { $collectedData[] = $data; } } catch (Throwable $t) { $internalErrorsCount++; $internalErrors[] = new InternalError($t->getMessage(), sprintf('analysing file %s', $file), InternalError::prepareTrace($t), $t->getTraceAsString(), \true); } } $out->write(['action' => 'result', 'result' => ['errors' => $errors, 'internalErrors' => $internalErrors, 'filteredPhpErrors' => $filteredPhpErrors, 'allPhpErrors' => $allPhpErrors, 'locallyIgnoredErrors' => $locallyIgnoredErrors, 'linesToIgnore' => $linesToIgnore, 'unmatchedLineIgnores' => $unmatchedLineIgnores, 'collectedData' => $collectedData, 'memoryUsage' => memory_get_peak_usage(\true), 'dependencies' => $dependencies, 'usedTraitDependencies' => $usedTraitDependencies, 'exportedNodes' => $exportedNodes, 'files' => $files, 'internalErrorsCount' => $internalErrorsCount]]); }); $in->on('error', $handleError); } /** * @param string[] $analysedFiles * @return string[] */ private function switchTmpFile(array $analysedFiles, ?string $insteadOfFile, ?string $tmpFile) : array { if ($insteadOfFile === null) { return $analysedFiles; } $analysedFiles = array_values(array_filter($analysedFiles, static function (string $file) use($insteadOfFile) : bool { return $file !== $insteadOfFile; })); if ($tmpFile !== null) { array_unshift($analysedFiles, $tmpFile); } return $analysedFiles; } } analyserRunner = $analyserRunner; $this->analyserResultFinalizer = $analyserResultFinalizer; $this->stubValidator = $stubValidator; $this->resultCacheManagerFactory = $resultCacheManagerFactory; $this->ignoredErrorHelper = $ignoredErrorHelper; $this->stubFilesProvider = $stubFilesProvider; } /** * @param string[] $files * @param mixed[]|null $projectConfigArray */ public function analyse(array $files, bool $onlyFiles, \PHPStan\Command\Output $stdOutput, \PHPStan\Command\Output $errorOutput, bool $defaultLevelUsed, bool $debug, ?string $projectConfigFile, ?array $projectConfigArray, ?string $tmpFile, ?string $insteadOfFile, InputInterface $input) : \PHPStan\Command\AnalysisResult { $isResultCacheUsed = \false; $fileReplacements = []; if ($tmpFile !== null && $insteadOfFile !== null) { $fileReplacements = [$insteadOfFile => $tmpFile]; } $resultCacheManager = $this->resultCacheManagerFactory->create($fileReplacements); $ignoredErrorHelperResult = $this->ignoredErrorHelper->initialize(); $fileSpecificErrors = []; if (count($ignoredErrorHelperResult->getErrors()) > 0) { $notFileSpecificErrors = $ignoredErrorHelperResult->getErrors(); $internalErrors = []; $collectedData = []; $savedResultCache = \false; $memoryUsageBytes = memory_get_peak_usage(\true); if ($errorOutput->isVeryVerbose()) { $errorOutput->writeLineFormatted('Result cache was not saved because of ignoredErrorHelperResult errors.'); } $changedProjectExtensionFilesOutsideOfAnalysedPaths = []; } else { $resultCache = $resultCacheManager->restore($files, $debug, $onlyFiles, $projectConfigArray, $errorOutput); $intermediateAnalyserResult = $this->runAnalyser($resultCache->getFilesToAnalyse(), $files, $debug, $projectConfigFile, $tmpFile, $insteadOfFile, $stdOutput, $errorOutput, $input); $projectStubFiles = $this->stubFilesProvider->getProjectStubFiles(); $forceValidateStubFiles = (bool) ($_SERVER['__PHPSTAN_FORCE_VALIDATE_STUB_FILES'] ?? \false); if ($resultCache->isFullAnalysis() && count($projectStubFiles) !== 0 && (!$onlyFiles || $forceValidateStubFiles)) { $stubErrors = $this->stubValidator->validate($projectStubFiles, $debug); $intermediateAnalyserResult = new AnalyserResult(array_merge($intermediateAnalyserResult->getUnorderedErrors(), $stubErrors), $intermediateAnalyserResult->getFilteredPhpErrors(), $intermediateAnalyserResult->getAllPhpErrors(), $intermediateAnalyserResult->getLocallyIgnoredErrors(), $intermediateAnalyserResult->getLinesToIgnore(), $intermediateAnalyserResult->getUnmatchedLineIgnores(), $intermediateAnalyserResult->getInternalErrors(), $intermediateAnalyserResult->getCollectedData(), $intermediateAnalyserResult->getDependencies(), $intermediateAnalyserResult->getUsedTraitDependencies(), $intermediateAnalyserResult->getExportedNodes(), $intermediateAnalyserResult->hasReachedInternalErrorsCountLimit(), $intermediateAnalyserResult->getPeakMemoryUsageBytes()); } $resultCacheResult = $resultCacheManager->process($intermediateAnalyserResult, $resultCache, $errorOutput, $onlyFiles, \true); $analyserResult = $this->analyserResultFinalizer->finalize($this->switchTmpFileInAnalyserResult($resultCacheResult->getAnalyserResult(), $insteadOfFile, $tmpFile), $onlyFiles, $debug)->getAnalyserResult(); $internalErrors = $analyserResult->getInternalErrors(); $errors = array_merge($analyserResult->getErrors(), $analyserResult->getFilteredPhpErrors()); $hasInternalErrors = count($internalErrors) > 0 || $analyserResult->hasReachedInternalErrorsCountLimit(); $memoryUsageBytes = $analyserResult->getPeakMemoryUsageBytes(); $isResultCacheUsed = !$resultCache->isFullAnalysis(); $changedProjectExtensionFilesOutsideOfAnalysedPaths = []; if ($isResultCacheUsed && $resultCacheResult->isSaved() && !$onlyFiles && $projectConfigArray !== null) { foreach ($resultCache->getProjectExtensionFiles() as $file => [$hash, $isAnalysed, $className]) { if ($isAnalysed) { continue; } if (!is_file($file)) { $changedProjectExtensionFilesOutsideOfAnalysedPaths[$file] = $className; continue; } $newHash = sha1_file($file); if ($newHash === $hash) { continue; } $changedProjectExtensionFilesOutsideOfAnalysedPaths[$file] = $className; } } $ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process($errors, $onlyFiles, $files, $hasInternalErrors); $fileSpecificErrors = $ignoredErrorHelperProcessedResult->getNotIgnoredErrors(); $notFileSpecificErrors = $ignoredErrorHelperProcessedResult->getOtherIgnoreMessages(); $collectedData = $analyserResult->getCollectedData(); $savedResultCache = $resultCacheResult->isSaved(); } return new \PHPStan\Command\AnalysisResult($fileSpecificErrors, $notFileSpecificErrors, $internalErrors, [], $collectedData, $defaultLevelUsed, $projectConfigFile, $savedResultCache, $memoryUsageBytes, $isResultCacheUsed, $changedProjectExtensionFilesOutsideOfAnalysedPaths); } /** * @param string[] $files * @param string[] $allAnalysedFiles */ private function runAnalyser(array $files, array $allAnalysedFiles, bool $debug, ?string $projectConfigFile, ?string $tmpFile, ?string $insteadOfFile, \PHPStan\Command\Output $stdOutput, \PHPStan\Command\Output $errorOutput, InputInterface $input) : AnalyserResult { $filesCount = count($files); $allAnalysedFilesCount = count($allAnalysedFiles); if ($filesCount === 0) { $errorOutput->getStyle()->progressStart($allAnalysedFilesCount); $errorOutput->getStyle()->progressAdvance($allAnalysedFilesCount); $errorOutput->getStyle()->progressFinish(); return new AnalyserResult([], [], [], [], [], [], [], [], [], [], [], \false, memory_get_peak_usage(\true)); } if (!$debug) { $preFileCallback = null; $postFileCallback = static function (int $step) use($errorOutput) : void { $errorOutput->getStyle()->progressAdvance($step); }; $errorOutput->getStyle()->progressStart($allAnalysedFilesCount); $errorOutput->getStyle()->progressAdvance($allAnalysedFilesCount - $filesCount); } else { $startTime = null; $preFileCallback = static function (string $file) use($stdOutput, &$startTime) : void { $stdOutput->writeLineFormatted($file); $startTime = microtime(\true); }; $postFileCallback = null; if ($stdOutput->isDebug()) { $previousMemory = memory_get_peak_usage(\true); $postFileCallback = static function () use($stdOutput, &$previousMemory, &$startTime) : void { if ($startTime === null) { throw new ShouldNotHappenException(); } $currentTotalMemory = memory_get_peak_usage(\true); $elapsedTime = microtime(\true) - $startTime; $stdOutput->writeLineFormatted(sprintf('--- consumed %s, total %s, took %.2f s', BytesHelper::bytes($currentTotalMemory - $previousMemory), BytesHelper::bytes($currentTotalMemory), $elapsedTime)); $previousMemory = $currentTotalMemory; }; } } $analyserResult = $this->analyserRunner->runAnalyser($files, $allAnalysedFiles, $preFileCallback, $postFileCallback, $debug, \true, $projectConfigFile, $tmpFile, $insteadOfFile, $input); if (!$debug) { $errorOutput->getStyle()->progressFinish(); } return $analyserResult; } private function switchTmpFileInAnalyserResult(AnalyserResult $analyserResult, ?string $insteadOfFile, ?string $tmpFile) : AnalyserResult { if ($insteadOfFile === null || $tmpFile === null) { return $analyserResult; } $collectedData = []; foreach ($analyserResult->getCollectedData() as $data) { if ($data->getFilePath() === $tmpFile) { $data = $data->changeFilePath($insteadOfFile); } $collectedData[] = $data; } $dependencies = null; if ($analyserResult->getDependencies() !== null) { $dependencies = $this->switchTmpFileInDependencies($analyserResult->getDependencies(), $insteadOfFile, $tmpFile); } $usedTraitDependencies = null; if ($analyserResult->getUsedTraitDependencies() !== null) { $usedTraitDependencies = $this->switchTmpFileInDependencies($analyserResult->getUsedTraitDependencies(), $insteadOfFile, $tmpFile); } $exportedNodes = []; foreach ($analyserResult->getExportedNodes() as $file => $fileExportedNodes) { if ($file === $tmpFile) { $file = $insteadOfFile; } $exportedNodes[$file] = $fileExportedNodes; } return new AnalyserResult($this->switchTmpFileInErrors($analyserResult->getUnorderedErrors(), $insteadOfFile, $tmpFile), $this->switchTmpFileInErrors($analyserResult->getFilteredPhpErrors(), $insteadOfFile, $tmpFile), $this->switchTmpFileInErrors($analyserResult->getAllPhpErrors(), $insteadOfFile, $tmpFile), $this->switchTmpFileInErrors($analyserResult->getLocallyIgnoredErrors(), $insteadOfFile, $tmpFile), $this->swittchTmpFileInLinesToIgnore($analyserResult->getLinesToIgnore(), $insteadOfFile, $tmpFile), $this->swittchTmpFileInLinesToIgnore($analyserResult->getUnmatchedLineIgnores(), $insteadOfFile, $tmpFile), $analyserResult->getInternalErrors(), $collectedData, $dependencies, $usedTraitDependencies, $exportedNodes, $analyserResult->hasReachedInternalErrorsCountLimit(), $analyserResult->getPeakMemoryUsageBytes()); } /** * @param array> $dependencies * @return array> */ private function switchTmpFileInDependencies(array $dependencies, string $insteadOfFile, string $tmpFile) : array { $newDependencies = []; foreach ($dependencies as $dependencyFile => $dependentFiles) { $new = []; foreach ($dependentFiles as $file) { if ($file === $tmpFile) { $new[] = $insteadOfFile; continue; } $new[] = $file; } $key = $dependencyFile; if ($key === $tmpFile) { $key = $insteadOfFile; } $newDependencies[$key] = $new; } return $newDependencies; } /** * @param list $errors * @return list */ private function switchTmpFileInErrors(array $errors, string $insteadOfFile, string $tmpFile) : array { $newErrors = []; foreach ($errors as $error) { if ($error->getFilePath() === $tmpFile) { $error = $error->changeFilePath($insteadOfFile); } if ($error->getTraitFilePath() === $tmpFile) { $error = $error->changeTraitFilePath($insteadOfFile); } $newErrors[] = $error; } return $newErrors; } /** * @param array $linesToIgnore * @return array */ private function swittchTmpFileInLinesToIgnore(array $linesToIgnore, string $insteadOfFile, string $tmpFile) : array { $newLinesToIgnore = []; foreach ($linesToIgnore as $file => $lines) { if ($file === $tmpFile) { $file = $insteadOfFile; } $newLines = []; foreach ($lines as $f => $line) { if ($f === $tmpFile) { $f = $insteadOfFile; } $newLines[$f] = $line; } $newLinesToIgnore[$file] = $newLines; } return $newLinesToIgnore; } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } protected function configure() : void { $this->setName(self::NAME)->setDescription('Dumps all parameters')->setDefinition([new InputOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Path to project configuration file'), new InputOption(\PHPStan\Command\AnalyseCommand::OPTION_LEVEL, 'l', InputOption::VALUE_REQUIRED, 'Level of rule options - the higher the stricter'), new InputOption('autoload-file', 'a', InputOption::VALUE_REQUIRED, 'Project\'s additional autoload file path'), new InputOption('debug', null, InputOption::VALUE_NONE, 'Show debug information - which file is analysed, do not catch internal errors'), new InputOption('memory-limit', null, InputOption::VALUE_REQUIRED, 'Memory limit for clearing result cache'), new InputOption('json', null, InputOption::VALUE_NONE, 'Dump parameters as JSON instead of NEON')]); } protected function initialize(InputInterface $input, OutputInterface $output) : void { if ((bool) $input->getOption('debug')) { $application = $this->getApplication(); if ($application === null) { throw new ShouldNotHappenException(); } $application->setCatchExceptions(\false); return; } } protected function execute(InputInterface $input, OutputInterface $output) : int { $memoryLimit = $input->getOption('memory-limit'); $autoloadFile = $input->getOption('autoload-file'); $configuration = $input->getOption('configuration'); $level = $input->getOption(\PHPStan\Command\AnalyseCommand::OPTION_LEVEL); $json = (bool) $input->getOption('json'); if (!is_string($memoryLimit) && $memoryLimit !== null || !is_string($autoloadFile) && $autoloadFile !== null || !is_string($configuration) && $configuration !== null || !is_string($level) && $level !== null) { throw new ShouldNotHappenException(); } try { $inceptionResult = \PHPStan\Command\CommandHelper::begin($input, $output, [], $memoryLimit, $autoloadFile, $this->composerAutoloaderProjectPaths, $configuration, null, $level, \false); } catch (\PHPStan\Command\InceptionNotSuccessfulException $e) { return 1; } $parameters = $inceptionResult->getContainer()->getParameters(); // always set to '.' unset($parameters['analysedPaths']); // irrelevant Nette parameters unset($parameters['debugMode']); unset($parameters['productionMode']); unset($parameters['tempDir']); unset($parameters['__validate']); // internal - editor mode unset($parameters['singleReflectionFile']); unset($parameters['singleReflectionInsteadOfFile']); if ($json) { $encoded = Json::encode($parameters, Json::PRETTY); } else { $encoded = Neon::encode($parameters, \true); } $output->writeln($encoded); return 0; } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } protected function configure() : void { $this->setName(self::NAME)->setDescription('Shows diagnose information about PHPStan and extensions')->setDefinition([new InputOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Path to project configuration file'), new InputOption(\PHPStan\Command\AnalyseCommand::OPTION_LEVEL, 'l', InputOption::VALUE_REQUIRED, 'Level of rule options - the higher the stricter'), new InputOption('autoload-file', 'a', InputOption::VALUE_REQUIRED, 'Project\'s additional autoload file path'), new InputOption('debug', null, InputOption::VALUE_NONE, 'Show debug information - do not catch internal errors'), new InputOption('memory-limit', null, InputOption::VALUE_REQUIRED, 'Memory limit for clearing result cache')]); } protected function initialize(InputInterface $input, OutputInterface $output) : void { if ((bool) $input->getOption('debug')) { $application = $this->getApplication(); if ($application === null) { throw new ShouldNotHappenException(); } $application->setCatchExceptions(\false); return; } } protected function execute(InputInterface $input, OutputInterface $output) : int { $memoryLimit = $input->getOption('memory-limit'); $autoloadFile = $input->getOption('autoload-file'); $configuration = $input->getOption('configuration'); $level = $input->getOption(\PHPStan\Command\AnalyseCommand::OPTION_LEVEL); if (!is_string($memoryLimit) && $memoryLimit !== null || !is_string($autoloadFile) && $autoloadFile !== null || !is_string($configuration) && $configuration !== null || !is_string($level) && $level !== null) { throw new ShouldNotHappenException(); } try { $inceptionResult = \PHPStan\Command\CommandHelper::begin($input, $output, [], $memoryLimit, $autoloadFile, $this->composerAutoloaderProjectPaths, $configuration, null, $level, \false); } catch (\PHPStan\Command\InceptionNotSuccessfulException $e) { return 1; } $container = $inceptionResult->getContainer(); $output = $inceptionResult->getStdOutput(); /** @var PHPStanDiagnoseExtension $phpstanDiagnoseExtension */ $phpstanDiagnoseExtension = $container->getService('phpstanDiagnoseExtension'); // not using tag for this extension to make sure it's always first $phpstanDiagnoseExtension->print($output); /** @var DiagnoseExtension $extension */ foreach ($container->getServicesByTag(DiagnoseExtension::EXTENSION_TAG) as $extension) { $extension->print($output); } return 0; } } relativePathHelper = $relativePathHelper; } public function formatErrors(AnalysisResult $analysisResult, Output $output) : int { $output->writeRaw(''); $output->writeLineFormatted(''); $output->writeRaw(''); $output->writeLineFormatted(''); foreach ($this->groupByFile($analysisResult) as $relativeFilePath => $errors) { $output->writeRaw(sprintf('', $this->escape($relativeFilePath))); $output->writeLineFormatted(''); foreach ($errors as $error) { $output->writeRaw(sprintf(' ', $this->escape((string) $error->getLine()), $this->escape($error->getMessage()), $error->getIdentifier() !== null ? sprintf(' source="%s"', $this->escape($error->getIdentifier())) : '')); $output->writeLineFormatted(''); } $output->writeRaw(''); $output->writeLineFormatted(''); } $notFileSpecificErrors = $analysisResult->getNotFileSpecificErrors(); if (count($notFileSpecificErrors) > 0) { $output->writeRaw(''); $output->writeLineFormatted(''); foreach ($notFileSpecificErrors as $error) { $output->writeRaw(sprintf(' ', $this->escape($error))); $output->writeLineFormatted(''); } $output->writeRaw(''); $output->writeLineFormatted(''); } if ($analysisResult->hasWarnings()) { $output->writeRaw(''); $output->writeLineFormatted(''); foreach ($analysisResult->getWarnings() as $warning) { $output->writeRaw(sprintf(' ', $this->escape($warning))); $output->writeLineFormatted(''); } $output->writeRaw(''); $output->writeLineFormatted(''); } $output->writeRaw(''); $output->writeLineFormatted(''); return $analysisResult->hasErrors() ? 1 : 0; } /** * Escapes values for using in XML * */ private function escape(string $string) : string { return htmlspecialchars($string, ENT_XML1 | ENT_COMPAT, 'UTF-8'); } /** * Group errors by file * * @return array> Array that have as key the relative path of file * and as value an array with occurred errors. */ private function groupByFile(AnalysisResult $analysisResult) : array { $files = []; /** @var Error $fileSpecificError */ foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { $absolutePath = $fileSpecificError->getFilePath(); if ($fileSpecificError->getTraitFilePath() !== null) { $absolutePath = $fileSpecificError->getTraitFilePath(); } $relativeFilePath = $this->relativePathHelper->getRelativePath($absolutePath); $files[$relativeFilePath][] = $fileSpecificError; } return $files; } } relativePathHelper = $relativePathHelper; } public function formatErrors(AnalysisResult $analysisResult, Output $output, string $existingBaselineContent) : int { if (!$analysisResult->hasErrors()) { $output->writeRaw($this->getNeon([], $existingBaselineContent)); return 0; } $fileErrors = []; foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { if (!$fileSpecificError->canBeIgnored()) { continue; } $fileErrors[$this->relativePathHelper->getRelativePath($fileSpecificError->getFilePath())][] = $fileSpecificError->getMessage(); } ksort($fileErrors, SORT_STRING); $errorsToOutput = []; foreach ($fileErrors as $file => $errorMessages) { $fileErrorsCounts = []; foreach ($errorMessages as $errorMessage) { if (!isset($fileErrorsCounts[$errorMessage])) { $fileErrorsCounts[$errorMessage] = 1; continue; } $fileErrorsCounts[$errorMessage]++; } ksort($fileErrorsCounts, SORT_STRING); foreach ($fileErrorsCounts as $message => $count) { $errorsToOutput[] = ['message' => Helpers::escape('#^' . preg_quote($message, '#') . '$#'), 'count' => $count, 'path' => Helpers::escape($file)]; } } $output->writeRaw($this->getNeon($errorsToOutput, $existingBaselineContent)); return 1; } /** * @param array $ignoreErrors */ private function getNeon(array $ignoreErrors, string $existingBaselineContent) : string { $neon = Neon::encode(['parameters' => ['ignoreErrors' => $ignoreErrors]], Neon::BLOCK); if (substr($neon, -2) !== "\n\n") { throw new ShouldNotHappenException(); } if ($existingBaselineContent === '') { return substr($neon, 0, -1); } $existingBaselineContentEndOfFileNewlinesMatches = Strings::match($existingBaselineContent, "~(\n)+\$~"); $existingBaselineContentEndOfFileNewlines = $existingBaselineContentEndOfFileNewlinesMatches !== null ? $existingBaselineContentEndOfFileNewlinesMatches[0] : ''; return substr($neon, 0, -2) . $existingBaselineContentEndOfFileNewlines; } } relativePathHelper = $relativePathHelper; } public function formatErrors(AnalysisResult $analysisResult, Output $output) : int { foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { $metas = ['file' => $this->relativePathHelper->getRelativePath($fileSpecificError->getFile()), 'line' => $fileSpecificError->getLine(), 'col' => 0]; array_walk($metas, static function (&$value, string $key) : void { $value = sprintf('%s=%s', $key, (string) $value); }); $message = $fileSpecificError->getMessage(); // newlines need to be encoded // see https://github.com/actions/starter-workflows/issues/68#issuecomment-581479448 $message = str_replace("\n", '%0A', $message); $line = sprintf('::error %s::%s', implode(',', $metas), $message); $output->writeRaw($line); $output->writeLineFormatted(''); } foreach ($analysisResult->getNotFileSpecificErrors() as $notFileSpecificError) { // newlines need to be encoded // see https://github.com/actions/starter-workflows/issues/68#issuecomment-581479448 $notFileSpecificError = str_replace("\n", '%0A', $notFileSpecificError); $line = sprintf('::error ::%s', $notFileSpecificError); $output->writeRaw($line); $output->writeLineFormatted(''); } foreach ($analysisResult->getWarnings() as $warning) { // newlines need to be encoded // see https://github.com/actions/starter-workflows/issues/68#issuecomment-581479448 $warning = str_replace("\n", '%0A', $warning); $line = sprintf('::warning ::%s', $warning); $output->writeRaw($line); $output->writeLineFormatted(''); } return $analysisResult->hasErrors() ? 1 : 0; } } relativePathHelper = $relativePathHelper; } public function formatErrors(AnalysisResult $analysisResult, Output $output) : int { $result = ''; $fileSpecificErrors = $analysisResult->getFileSpecificErrors(); $notFileSpecificErrors = $analysisResult->getNotFileSpecificErrors(); $warnings = $analysisResult->getWarnings(); if (count($fileSpecificErrors) === 0 && count($notFileSpecificErrors) === 0 && count($warnings) === 0) { return 0; } $result .= $this->createTeamcityLine('inspectionType', ['id' => 'phpstan', 'name' => 'phpstan', 'category' => 'phpstan', 'description' => 'phpstan Inspection']); foreach ($fileSpecificErrors as $fileSpecificError) { $result .= $this->createTeamcityLine('inspection', [ 'typeId' => 'phpstan', 'message' => $fileSpecificError->getMessage(), 'file' => $this->relativePathHelper->getRelativePath($fileSpecificError->getFile()), 'line' => $fileSpecificError->getLine(), // additional attributes 'SEVERITY' => 'ERROR', 'ignorable' => $fileSpecificError->canBeIgnored(), 'tip' => $fileSpecificError->getTip(), ]); } foreach ($notFileSpecificErrors as $notFileSpecificError) { $result .= $this->createTeamcityLine('inspection', [ 'typeId' => 'phpstan', 'message' => $notFileSpecificError, // the file is required 'file' => $analysisResult->getProjectConfigFile() !== null ? $this->relativePathHelper->getRelativePath($analysisResult->getProjectConfigFile()) : '.', 'SEVERITY' => 'ERROR', ]); } foreach ($warnings as $warning) { $result .= $this->createTeamcityLine('inspection', [ 'typeId' => 'phpstan', 'message' => $warning, // the file is required 'file' => $analysisResult->getProjectConfigFile() !== null ? $this->relativePathHelper->getRelativePath($analysisResult->getProjectConfigFile()) : '.', 'SEVERITY' => 'WARNING', ]); } $output->writeRaw($result); return $analysisResult->hasErrors() ? 1 : 0; } /** * Creates a Teamcity report line * * @param string $messageName The message name * @param mixed[] $keyValuePairs The key=>value pairs * @return string The Teamcity report line */ private function createTeamcityLine(string $messageName, array $keyValuePairs) : string { $string = '##teamcity[' . $messageName; foreach ($keyValuePairs as $key => $value) { if (is_string($value)) { $value = $this->escape($value); } $string .= ' ' . $key . '=\'' . $value . '\''; } return $string . ']' . PHP_EOL; } /** * Escapes the given string for Teamcity output * * @param string $string The string to escape * @return string The escaped string */ private function escape(string $string) : string { $replacements = ['~\\n~' => '|n', '~\\r~' => '|r', '~([\'\\|\\[\\]])~' => '|$1']; return (string) preg_replace(array_keys($replacements), array_values($replacements), $string); } } relativePathHelper = $relativePathHelper; } public function formatErrors(AnalysisResult $analysisResult, Output $output) : int { if (!$analysisResult->hasErrors()) { $php = 'writeRaw($php); return 0; } $fileErrors = []; foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { if (!$fileSpecificError->canBeIgnored()) { continue; } $fileErrors['/' . $this->relativePathHelper->getRelativePath($fileSpecificError->getFilePath())][] = $fileSpecificError; } ksort($fileErrors, SORT_STRING); $php = ' $errors) { $fileErrorsByMessage = []; foreach ($errors as $error) { $errorMessage = $error->getMessage(); if (!isset($fileErrorsByMessage[$errorMessage])) { $fileErrorsByMessage[$errorMessage] = [1, $error->getIdentifier() !== null ? [$error->getIdentifier() => \true] : []]; continue; } $fileErrorsByMessage[$errorMessage][0]++; if ($error->getIdentifier() === null) { continue; } $fileErrorsByMessage[$errorMessage][1][$error->getIdentifier()] = \true; } ksort($fileErrorsByMessage, SORT_STRING); foreach ($fileErrorsByMessage as $message => [$count, $identifiersInKeys]) { $identifiers = array_keys($identifiersInKeys); sort($identifiers); $identifiersComment = ''; if (count($identifiers) > 0) { if (count($identifiers) === 1) { $identifiersComment = "\n\t// identifier: " . $identifiers[0]; } else { $identifiersComment = "\n\t// identifiers: " . implode(', ', $identifiers); } } $php .= sprintf("\$ignoreErrors[] = [%s\n\t'message' => %s,\n\t'count' => %d,\n\t'path' => __DIR__ . %s,\n];\n", $identifiersComment, var_export(Helpers::escape('#^' . preg_quote($message, '#') . '$#'), \true), var_export($count, \true), var_export(Helpers::escape($file), \true)); } } $php .= "\n"; $php .= 'return [\'parameters\' => [\'ignoreErrors\' => $ignoreErrors]];'; $php .= "\n"; $output->writeRaw($php); return 1; } } githubErrorFormatter = $githubErrorFormatter; $this->teamcityErrorFormatter = $teamcityErrorFormatter; } public function formatErrors(AnalysisResult $analysisResult, Output $output) : int { $ciDetector = new CiDetector(); try { $ci = $ciDetector->detect(); if ($ci->getCiName() === CiDetector::CI_GITHUB_ACTIONS) { return $this->githubErrorFormatter->formatErrors($analysisResult, $output); } elseif ($ci->getCiName() === CiDetector::CI_TEAMCITY) { return $this->teamcityErrorFormatter->formatErrors($analysisResult, $output); } } catch (CiNotDetectedException $e) { // pass } if (!$analysisResult->hasErrors() && !$analysisResult->hasWarnings()) { return 0; } return $analysisResult->getTotalErrorsCount() > 0 ? 1 : 0; } } getNotFileSpecificErrors() as $notFileSpecificError) { $output->writeRaw(sprintf('?:?:%s', $notFileSpecificError)); $output->writeLineFormatted(''); } $outputIdentifiers = $output->isVerbose(); foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { $identifier = ''; if ($outputIdentifiers && $fileSpecificError->getIdentifier() !== null) { $identifier = sprintf(' [identifier=%s]', $fileSpecificError->getIdentifier()); } $output->writeRaw(sprintf('%s:%d:%s%s', $fileSpecificError->getFile(), $fileSpecificError->getLine() ?? '?', $fileSpecificError->getMessage(), $identifier)); $output->writeLineFormatted(''); } foreach ($analysisResult->getWarnings() as $warning) { $output->writeRaw(sprintf('?:?:%s', $warning)); $output->writeLineFormatted(''); } return $analysisResult->hasErrors() ? 1 : 0; } } relativePathHelper = $relativePathHelper; } public function formatErrors(AnalysisResult $analysisResult, Output $output) : int { $totalFailuresCount = $analysisResult->getTotalErrorsCount(); $totalTestsCount = $analysisResult->hasErrors() ? $totalFailuresCount : 1; $result = ''; $result .= sprintf('', $totalFailuresCount, $totalTestsCount); foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { $fileName = $this->relativePathHelper->getRelativePath($fileSpecificError->getFile()); $result .= $this->createTestCase(sprintf('%s:%s', $fileName, (string) $fileSpecificError->getLine()), 'ERROR', $fileSpecificError->getMessage()); } foreach ($analysisResult->getNotFileSpecificErrors() as $notFileSpecificError) { $result .= $this->createTestCase('General error', 'ERROR', $notFileSpecificError); } foreach ($analysisResult->getWarnings() as $warning) { $result .= $this->createTestCase('Warning', 'WARNING', $warning); } if (!$analysisResult->hasErrors()) { $result .= $this->createTestCase('phpstan', ''); } $result .= ''; $output->writeRaw($result); return $analysisResult->hasErrors() ? 1 : 0; } /** * Format a single test case * * */ private function createTestCase(string $reference, string $type, ?string $message = null) : string { $result = sprintf('', $this->escape($reference)); if ($message !== null) { $result .= sprintf('', $this->escape($type), $this->escape($message)); } $result .= ''; return $result; } /** * Escapes values for using in XML * */ private function escape(string $string) : string { return htmlspecialchars($string, ENT_XML1 | ENT_COMPAT, 'UTF-8'); } } relativePathHelper = $relativePathHelper; } public function formatErrors(AnalysisResult $analysisResult, Output $output) : int { $errorsArray = []; foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { $error = ['description' => $fileSpecificError->getMessage(), 'fingerprint' => hash('sha256', implode([$fileSpecificError->getFile(), $fileSpecificError->getLine(), $fileSpecificError->getMessage()])), 'severity' => $fileSpecificError->canBeIgnored() ? 'major' : 'blocker', 'location' => ['path' => $this->relativePathHelper->getRelativePath($fileSpecificError->getFile()), 'lines' => ['begin' => $fileSpecificError->getLine() ?? 0]]]; $errorsArray[] = $error; } foreach ($analysisResult->getNotFileSpecificErrors() as $notFileSpecificError) { $errorsArray[] = ['description' => $notFileSpecificError, 'fingerprint' => hash('sha256', $notFileSpecificError), 'severity' => 'major', 'location' => ['path' => '', 'lines' => ['begin' => 0]]]; } $json = Json::encode($errorsArray, Json::PRETTY); $output->writeRaw($json); return $analysisResult->hasErrors() ? 1 : 0; } } pretty = $pretty; } public function formatErrors(AnalysisResult $analysisResult, Output $output) : int { $errorsArray = ['totals' => ['errors' => count($analysisResult->getNotFileSpecificErrors()), 'file_errors' => count($analysisResult->getFileSpecificErrors())], 'files' => [], 'errors' => []]; $tipFormatter = new OutputFormatter(\false); foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { $file = $fileSpecificError->getFile(); if (!array_key_exists($file, $errorsArray['files'])) { $errorsArray['files'][$file] = ['errors' => 0, 'messages' => []]; } $errorsArray['files'][$file]['errors']++; $message = ['message' => $fileSpecificError->getMessage(), 'line' => $fileSpecificError->getLine(), 'ignorable' => $fileSpecificError->canBeIgnored()]; if ($fileSpecificError->getTip() !== null) { $message['tip'] = $tipFormatter->format($fileSpecificError->getTip()); } if ($fileSpecificError->getIdentifier() !== null) { $message['identifier'] = $fileSpecificError->getIdentifier(); } $errorsArray['files'][$file]['messages'][] = $message; } foreach ($analysisResult->getNotFileSpecificErrors() as $notFileSpecificError) { $errorsArray['errors'][] = $notFileSpecificError; } $json = Json::encode($errorsArray, $this->pretty ? Json::PRETTY : 0); $output->writeRaw($json); return $analysisResult->hasErrors() ? 1 : 0; } } relativePathHelper = $relativePathHelper; $this->simpleRelativePathHelper = $simpleRelativePathHelper; $this->ciDetectedErrorFormatter = $ciDetectedErrorFormatter; $this->showTipsOfTheDay = $showTipsOfTheDay; $this->editorUrl = $editorUrl; $this->editorUrlTitle = $editorUrlTitle; } /** @api */ public function formatErrors(AnalysisResult $analysisResult, Output $output) : int { $this->ciDetectedErrorFormatter->formatErrors($analysisResult, $output); $projectConfigFile = 'phpstan.neon'; if ($analysisResult->getProjectConfigFile() !== null) { $projectConfigFile = $this->relativePathHelper->getRelativePath($analysisResult->getProjectConfigFile()); } $style = $output->getStyle(); if (!$analysisResult->hasErrors() && !$analysisResult->hasWarnings()) { $style->success('No errors'); if ($this->showTipsOfTheDay) { if ($analysisResult->isDefaultLevelUsed()) { $output->writeLineFormatted('💡 Tip of the Day:'); $output->writeLineFormatted(sprintf("PHPStan is performing only the most basic checks.\nYou can pass a higher rule level through the --%s option\n(the default and current level is %d) to analyse code more thoroughly.", AnalyseCommand::OPTION_LEVEL, AnalyseCommand::DEFAULT_LEVEL)); $output->writeLineFormatted(''); } } return 0; } /** @var array $fileErrors */ $fileErrors = []; $outputIdentifiers = $output->isVerbose(); $outputIdentifiersInFile = []; foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { if (!isset($fileErrors[$fileSpecificError->getFile()])) { $fileErrors[$fileSpecificError->getFile()] = []; } $fileErrors[$fileSpecificError->getFile()][] = $fileSpecificError; if ($outputIdentifiers) { continue; } $filePath = $fileSpecificError->getTraitFilePath() ?? $fileSpecificError->getFilePath(); if (array_key_exists($filePath, $outputIdentifiersInFile)) { continue; } if ($fileSpecificError->getIdentifier() === null) { continue; } if (!in_array($fileSpecificError->getIdentifier(), ['ignore.unmatchedIdentifier', 'ignore.parseError', 'ignore.unmatched'], \true)) { continue; } $outputIdentifiersInFile[$filePath] = \true; } foreach ($fileErrors as $file => $errors) { $rows = []; foreach ($errors as $error) { $message = $error->getMessage(); $filePath = $error->getTraitFilePath() ?? $error->getFilePath(); if (($outputIdentifiers || array_key_exists($filePath, $outputIdentifiersInFile)) && $error->getIdentifier() !== null && $error->canBeIgnored()) { $message .= "\n"; $message .= '🪪 ' . $error->getIdentifier(); } if ($error->getTip() !== null) { $tip = $error->getTip(); $tip = str_replace('%configurationFile%', $projectConfigFile, $tip); $message .= "\n"; if (str_contains($tip, "\n")) { $lines = explode("\n", $tip); foreach ($lines as $line) { $message .= '💡 ' . ltrim($line, ' •') . "\n"; } } else { $message .= '💡 ' . $tip; } } if (is_string($this->editorUrl)) { $url = str_replace(['%file%', '%relFile%', '%line%'], [$filePath, $this->simpleRelativePathHelper->getRelativePath($filePath), (string) $error->getLine()], $this->editorUrl); if (is_string($this->editorUrlTitle)) { $title = str_replace(['%file%', '%relFile%', '%line%'], [$filePath, $this->simpleRelativePathHelper->getRelativePath($filePath), (string) $error->getLine()], $this->editorUrlTitle); } else { $title = $this->relativePathHelper->getRelativePath($filePath); } $message .= "\n✏️ ' . $title . ''; } $rows[] = [$this->formatLineNumber($error->getLine()), $message]; } $style->table(['Line', $this->relativePathHelper->getRelativePath($file)], $rows); } if (count($analysisResult->getNotFileSpecificErrors()) > 0) { $style->table(['', 'Error'], array_map(static function (string $error) : array { return ['', OutputFormatter::escape($error)]; }, $analysisResult->getNotFileSpecificErrors())); } $warningsCount = count($analysisResult->getWarnings()); if ($warningsCount > 0) { $style->table(['', 'Warning'], array_map(static function (string $warning) : array { return ['', OutputFormatter::escape($warning)]; }, $analysisResult->getWarnings())); } $finalMessage = sprintf($analysisResult->getTotalErrorsCount() === 1 ? 'Found %d error' : 'Found %d errors', $analysisResult->getTotalErrorsCount()); if ($warningsCount > 0) { $finalMessage .= sprintf($warningsCount === 1 ? ' and %d warning' : ' and %d warnings', $warningsCount); } if ($analysisResult->getTotalErrorsCount() > 0) { $style->error($finalMessage); } else { $style->warning($finalMessage); } return $analysisResult->getTotalErrorsCount() > 0 ? 1 : 0; } private function formatLineNumber(?int $lineNumber) : string { if ($lineNumber === null) { return ''; } $isRunningInVSCodeTerminal = getenv('TERM_PROGRAM') === 'vscode'; if ($isRunningInVSCodeTerminal) { return ':' . $lineNumber; } return (string) $lineNumber; } } composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; parent::__construct(); } protected function configure() : void { $this->setName(self::NAME)->setDescription('Clears the result cache.')->setDefinition([new InputOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Path to project configuration file'), new InputOption('autoload-file', 'a', InputOption::VALUE_REQUIRED, 'Project\'s additional autoload file path'), new InputOption('debug', null, InputOption::VALUE_NONE, 'Show debug information - which file is analysed, do not catch internal errors'), new InputOption('memory-limit', null, InputOption::VALUE_REQUIRED, 'Memory limit for clearing result cache'), new InputOption('xdebug', null, InputOption::VALUE_NONE, 'Allow running with Xdebug for debugging purposes')]); } protected function initialize(InputInterface $input, OutputInterface $output) : void { if ((bool) $input->getOption('debug')) { $application = $this->getApplication(); if ($application === null) { throw new ShouldNotHappenException(); } $application->setCatchExceptions(\false); return; } } protected function execute(InputInterface $input, OutputInterface $output) : int { $autoloadFile = $input->getOption('autoload-file'); $configuration = $input->getOption('configuration'); $memoryLimit = $input->getOption('memory-limit'); $debugEnabled = (bool) $input->getOption('debug'); $allowXdebug = $input->getOption('xdebug'); if (!is_string($autoloadFile) && $autoloadFile !== null || !is_string($configuration) && $configuration !== null || !is_string($memoryLimit) && $memoryLimit !== null || !is_bool($allowXdebug)) { throw new ShouldNotHappenException(); } try { $inceptionResult = \PHPStan\Command\CommandHelper::begin($input, $output, [], $memoryLimit, $autoloadFile, $this->composerAutoloaderProjectPaths, $configuration, null, '0', $allowXdebug, $debugEnabled); } catch (\PHPStan\Command\InceptionNotSuccessfulException $e) { return 1; } $container = $inceptionResult->getContainer(); $resultCacheClearer = $container->getByType(ResultCacheClearer::class); $path = $resultCacheClearer->clear(); $output->writeln('Result cache cleared from directory:'); $output->writeln($path); return 0; } } getErrorOutput() : $output; return new SymfonyOutput($symfonyErrorOutput, new SymfonyStyle(new \PHPStan\Command\ErrorsConsoleStyle($input, $symfonyErrorOutput))); })(); if (!$allowXdebug) { $xdebug = new XdebugHandler('phpstan'); $xdebug->setPersistent(); $xdebug->check(); unset($xdebug); } if ($allowXdebug) { if (!XdebugHandler::isXdebugActive()) { $errorOutput->getStyle()->note('You are running with "--xdebug" enabled, but the Xdebug PHP extension is not active. The process will not halt at breakpoints.'); } else { $errorOutput->getStyle()->note("You are running with \"--xdebug\" enabled, and the Xdebug PHP extension is active.\nThe process will halt at breakpoints, but PHPStan will run much slower.\nUse this only if you are debugging PHPStan itself or your custom extensions."); } } elseif (XdebugHandler::isXdebugActive()) { $errorOutput->getStyle()->note('The Xdebug PHP extension is active, but "--xdebug" is not used. This may slow down performance and the process will not halt at breakpoints.'); } elseif ($debugEnabled) { $v = XdebugHandler::getSkippedVersion(); if ($v !== '') { $errorOutput->getStyle()->note("The Xdebug PHP extension is active, but \"--xdebug\" is not used.\n" . "The process was restarted and it will not halt at breakpoints.\n" . 'Use "--xdebug" if you want to halt at breakpoints.'); } } if ($memoryLimit !== null) { if (Strings::match($memoryLimit, '#^-?\\d+[kMG]?$#i') === null) { $errorOutput->writeLineFormatted(sprintf('Invalid memory limit format "%s".', $memoryLimit)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } if (ini_set('memory_limit', $memoryLimit) === \false) { $errorOutput->writeLineFormatted(sprintf('Memory limit "%s" cannot be set.', $memoryLimit)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } } self::$reservedMemory = str_repeat('PHPStan', 1463); // reserve 10 kB of space register_shutdown_function(static function () use($errorOutput) : void { self::$reservedMemory = null; $error = error_get_last(); if ($error === null) { return; } if ($error['type'] !== E_ERROR) { return; } if (!str_contains($error['message'], 'Allowed memory size')) { return; } $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted(sprintf('PHPStan process crashed because it reached configured PHP memory limit: %s', ini_get('memory_limit'))); $errorOutput->writeLineFormatted('Increase your memory limit in php.ini or run PHPStan with --memory-limit CLI option.'); }); $currentWorkingDirectory = getcwd(); if ($currentWorkingDirectory === \false) { throw new ShouldNotHappenException(); } $currentWorkingDirectoryFileHelper = new FileHelper($currentWorkingDirectory); $currentWorkingDirectory = $currentWorkingDirectoryFileHelper->getWorkingDirectory(); /** @var list|false $autoloadFunctionsBefore */ $autoloadFunctionsBefore = spl_autoload_functions(); if ($autoloadFile !== null) { $autoloadFile = $currentWorkingDirectoryFileHelper->absolutizePath($autoloadFile); if (!is_file($autoloadFile)) { $errorOutput->writeLineFormatted(sprintf('Autoload file "%s" not found.', $autoloadFile)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } (static function (string $file) : void { require_once $file; })($autoloadFile); } if ($projectConfigFile === null) { $discoverableConfigNames = ['.phpstan.neon', 'phpstan.neon', '.phpstan.neon.dist', 'phpstan.neon.dist', '.phpstan.dist.neon', 'phpstan.dist.neon']; foreach ($discoverableConfigNames as $discoverableConfigName) { $discoverableConfigFile = $currentWorkingDirectory . DIRECTORY_SEPARATOR . $discoverableConfigName; if (is_file($discoverableConfigFile)) { $projectConfigFile = $discoverableConfigFile; $errorOutput->writeLineFormatted(sprintf('Note: Using configuration file %s.', $projectConfigFile)); break; } } } else { $projectConfigFile = $currentWorkingDirectoryFileHelper->absolutizePath($projectConfigFile); } if ($generateBaselineFile !== null) { $generateBaselineFile = $currentWorkingDirectoryFileHelper->normalizePath($currentWorkingDirectoryFileHelper->absolutizePath($generateBaselineFile)); } if ($singleReflectionFile !== null) { $singleReflectionFile = $currentWorkingDirectoryFileHelper->normalizePath($currentWorkingDirectoryFileHelper->absolutizePath($singleReflectionFile)); if (!is_file($singleReflectionFile)) { $errorOutput->writeLineFormatted(sprintf('File passed to --tmp-file option does not exist: %s', $singleReflectionFile)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } if ($singleReflectionInsteadOfFile === null) { $errorOutput->writeLineFormatted('Both --tmp-file and --instead-of options must be passed at the same time for editor mode to work.'); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } } if ($singleReflectionInsteadOfFile !== null) { $singleReflectionInsteadOfFile = $currentWorkingDirectoryFileHelper->normalizePath($currentWorkingDirectoryFileHelper->absolutizePath($singleReflectionInsteadOfFile)); if (!is_file($singleReflectionInsteadOfFile)) { $errorOutput->writeLineFormatted(sprintf('File passed to --instead-of option does not exist: %s', $singleReflectionInsteadOfFile)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } if ($singleReflectionFile === null) { $errorOutput->writeLineFormatted('Both --tmp-file and --instead-of options must be passed at the same time for editor mode to work.'); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } } $defaultLevelUsed = \false; if ($projectConfigFile === null && $level === null) { $level = self::DEFAULT_LEVEL; $defaultLevelUsed = \true; } $paths = array_map(static function (string $path) use($currentWorkingDirectoryFileHelper) : string { return $currentWorkingDirectoryFileHelper->normalizePath($currentWorkingDirectoryFileHelper->absolutizePath($path)); }, $paths); $analysedPathsFromConfig = []; $containerFactory = new ContainerFactory($currentWorkingDirectory, \true); $projectConfig = null; if ($projectConfigFile !== null) { if (!is_file($projectConfigFile)) { $errorOutput->writeLineFormatted(sprintf('Project config file at path %s does not exist.', $projectConfigFile)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } $loader = (new LoaderFactory($currentWorkingDirectoryFileHelper, $containerFactory->getRootDirectory(), $containerFactory->getCurrentWorkingDirectory(), $generateBaselineFile))->createLoader(); try { $projectConfig = $loader->load($projectConfigFile, null); } catch (InvalidStateException|FileNotFoundException $e) { $errorOutput->writeLineFormatted($e->getMessage()); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } $defaultParameters = ['rootDir' => $containerFactory->getRootDirectory(), 'currentWorkingDirectory' => $containerFactory->getCurrentWorkingDirectory(), 'env' => getenv()]; if (isset($projectConfig['parameters']['tmpDir'])) { $tmpDir = Helpers::expand($projectConfig['parameters']['tmpDir'], $defaultParameters); } if ($level === null && isset($projectConfig['parameters']['level'])) { $level = (string) $projectConfig['parameters']['level']; } if (isset($projectConfig['parameters']['paths'])) { $analysedPathsFromConfig = Helpers::expand($projectConfig['parameters']['paths'], $defaultParameters); } if (count($paths) === 0) { $paths = $analysedPathsFromConfig; } } $additionalConfigFiles = []; if ($level !== null) { $levelConfigFile = sprintf('%s/config.level%s.neon', $containerFactory->getConfigDirectory(), $level); if (!is_file($levelConfigFile)) { $errorOutput->writeLineFormatted(sprintf('Level config file %s was not found.', $levelConfigFile)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } $additionalConfigFiles[] = $levelConfigFile; } if (class_exists('PHPStan\\ExtensionInstaller\\GeneratedConfig')) { $generatedConfigReflection = new ReflectionClass('PHPStan\\ExtensionInstaller\\GeneratedConfig'); $generatedConfigDirectory = dirname($generatedConfigReflection->getFileName()); foreach (GeneratedConfig::EXTENSIONS as $name => $extensionConfig) { foreach ($extensionConfig['extra']['includes'] ?? [] as $includedFile) { if (!is_string($includedFile)) { $errorOutput->writeLineFormatted(sprintf('Cannot include config from package %s, expecting string file path but got %s', $name, gettype($includedFile))); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } $includedFilePath = null; if (isset($extensionConfig['relative_install_path'])) { $includedFilePath = sprintf('%s/%s/%s', $generatedConfigDirectory, $extensionConfig['relative_install_path'], $includedFile); if (!is_file($includedFilePath) || !is_readable($includedFilePath)) { $includedFilePath = null; } } if ($includedFilePath === null) { $includedFilePath = sprintf('%s/%s', $extensionConfig['install_path'], $includedFile); } if (!is_file($includedFilePath) || !is_readable($includedFilePath)) { $errorOutput->writeLineFormatted(sprintf('Config file %s does not exist or isn\'t readable', $includedFilePath)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } $additionalConfigFiles[] = $includedFilePath; } } if (count($additionalConfigFiles) > 0 && $generatedConfigReflection->hasConstant('PHPSTAN_VERSION_CONSTRAINT')) { $generatedConfigPhpStanVersionConstraint = $generatedConfigReflection->getConstant('PHPSTAN_VERSION_CONSTRAINT'); if ($generatedConfigPhpStanVersionConstraint !== null) { $phpstanSemverVersion = ComposerHelper::getPhpStanVersion(); if ($phpstanSemverVersion !== ComposerHelper::UNKNOWN_VERSION && !str_contains($phpstanSemverVersion, '@') && !Semver::satisfies($phpstanSemverVersion, $generatedConfigPhpStanVersionConstraint)) { $errorOutput->writeLineFormatted('Running PHPStan with incompatible extensions'); $errorOutput->writeLineFormatted('You\'re running PHPStan from a different Composer project'); $errorOutput->writeLineFormatted('than the one where you installed extensions.'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted(sprintf('Your PHPStan version is: %s', $phpstanSemverVersion)); $errorOutput->writeLineFormatted(sprintf('Installed PHPStan extensions support: %s', $generatedConfigPhpStanVersionConstraint)); $errorOutput->writeLineFormatted(''); if (isset($_SERVER['argv'][0]) && is_file($_SERVER['argv'][0])) { $mainScript = $_SERVER['argv'][0]; $errorOutput->writeLineFormatted(sprintf('PHPStan is running from: %s', $currentWorkingDirectoryFileHelper->absolutizePath(dirname($mainScript)))); } $errorOutput->writeLineFormatted(sprintf('Extensions were installed in: %s', dirname($generatedConfigDirectory, 3))); $errorOutput->writeLineFormatted(''); $simpleRelativePathHelper = new SimpleRelativePathHelper($currentWorkingDirectory); $errorOutput->writeLineFormatted(sprintf('Run PHPStan with %s to fix this problem.', $simpleRelativePathHelper->getRelativePath(dirname($generatedConfigDirectory, 3) . '/bin/phpstan'))); $errorOutput->writeLineFormatted(''); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } } } } if ($projectConfigFile !== null && $currentWorkingDirectoryFileHelper->normalizePath($projectConfigFile, '/') !== $currentWorkingDirectoryFileHelper->normalizePath(__DIR__ . '/../../conf/config.stubFiles.neon', '/')) { $additionalConfigFiles[] = $projectConfigFile; } $createDir = static function (string $path) use($errorOutput) : void { try { DirectoryCreator::ensureDirectoryExists($path, 0777); } catch (DirectoryCreatorException $e) { $errorOutput->writeLineFormatted($e->getMessage()); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } }; if (!isset($tmpDir)) { $tmpDir = sys_get_temp_dir() . '/phpstan'; $createDir($tmpDir); } try { $container = $containerFactory->create($tmpDir, $additionalConfigFiles, $paths, $composerAutoloaderProjectPaths, $analysedPathsFromConfig, $level ?? self::DEFAULT_LEVEL, $generateBaselineFile, $autoloadFile, $singleReflectionFile, $singleReflectionInsteadOfFile); } catch (InvalidConfigurationException|AssertionException $e) { $errorOutput->writeLineFormatted('Invalid configuration:'); $errorOutput->writeLineFormatted($e->getMessage()); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } catch (InvalidIgnoredErrorPatternsException $e) { $errorOutput->writeLineFormatted(sprintf('Invalid %s in ignoreErrors:', count($e->getErrors()) === 1 ? 'entry' : 'entries')); foreach ($e->getErrors() as $error) { $errorOutput->writeLineFormatted($error); $errorOutput->writeLineFormatted(''); } $errorOutput->writeLineFormatted('To ignore non-existent paths in ignoreErrors,'); $errorOutput->writeLineFormatted('set reportUnmatchedIgnoredErrors: false in your configuration file.'); $errorOutput->writeLineFormatted(''); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } catch (InvalidExcludePathsException $e) { $errorOutput->writeLineFormatted(sprintf('Invalid %s in excludePaths:', count($e->getErrors()) === 1 ? 'entry' : 'entries')); foreach ($e->getErrors() as $error) { $errorOutput->writeLineFormatted($error); $errorOutput->writeLineFormatted(''); } $errorOutput->writeLineFormatted('If the excluded path can sometimes exist, append (?)'); $errorOutput->writeLineFormatted('to its config entry to mark it as optional.'); $errorOutput->writeLineFormatted(''); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } catch (ValidationException $e) { foreach ($e->getMessages() as $message) { $errorOutput->writeLineFormatted('Invalid configuration:'); $errorOutput->writeLineFormatted($message); } throw new \PHPStan\Command\InceptionNotSuccessfulException(); } catch (ServiceCreationException $e) { $matches = Strings::match($e->getMessage(), '#Service of type (?[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\\\]*[a-zA-Z0-9_\\x7f-\\xff]): Service of type (?[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\\\]*[a-zA-Z0-9_\\x7f-\\xff]) needed by \\$(?[a-zA-Z_\\x7f-\\xff][a-zA-Z_0-9\\x7f-\\xff]*) in (?[a-zA-Z_\\x7f-\\xff][a-zA-Z_0-9\\x7f-\\xff]*)\\(\\)#'); if ($matches === null) { throw $e; } if ($matches['parserServiceType'] !== 'PHPStan\\Parser\\Parser') { throw $e; } if ($matches['methodName'] !== '__construct') { throw $e; } $errorOutput->writeLineFormatted('Invalid configuration:'); $errorOutput->writeLineFormatted(sprintf("Service of type %s is no longer autowired.\n", $matches['parserServiceType'])); $errorOutput->writeLineFormatted('You need to choose one of the following services'); $errorOutput->writeLineFormatted(sprintf('and use it in the %s argument of your service %s:', $matches['parameterName'], $matches['serviceType'])); $errorOutput->writeLineFormatted('* defaultAnalysisParser (if you\'re parsing files from analysed paths)'); $errorOutput->writeLineFormatted('* currentPhpVersionSimpleDirectParser (in most other situations)'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('After fixing this problem, your configuration will look something like this:'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('-'); $errorOutput->writeLineFormatted(sprintf("\tclass: %s", $matches['serviceType'])); $errorOutput->writeLineFormatted(sprintf("\targuments:")); $errorOutput->writeLineFormatted(sprintf("\t\t%s: @defaultAnalysisParser", $matches['parameterName'])); $errorOutput->writeLineFormatted(''); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } catch (DuplicateIncludedFilesException $e) { $format = "These files are included multiple times:\n- %s"; if (count($e->getFiles()) === 1) { $format = "This file is included multiple times:\n- %s"; } $errorOutput->writeLineFormatted(sprintf($format, implode("\n- ", $e->getFiles()))); if (class_exists('PHPStan\\ExtensionInstaller\\GeneratedConfig')) { $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('It can lead to unexpected results. If you\'re using phpstan/extension-installer, make sure you have removed corresponding neon files from your project config file.'); } throw new \PHPStan\Command\InceptionNotSuccessfulException(); } if ($cleanupContainerCache) { $containerFactory->clearOldContainers($tmpDir); } /** @var bool|null $customRulesetUsed */ $customRulesetUsed = $container->getParameter('customRulesetUsed'); if ($customRulesetUsed === null) { $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('No rules detected'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('You have the following choices:'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('* while running the analyse option, use the --level option to adjust your rule level - the higher the stricter'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted(sprintf('* create your own custom ruleset by selecting which rules you want to check by copying the service definitions from the built-in config level files in %s.', $currentWorkingDirectoryFileHelper->normalizePath(__DIR__ . '/../../conf'))); $errorOutput->writeLineFormatted(' * in this case, don\'t forget to define parameter customRulesetUsed in your config file.'); $errorOutput->writeLineFormatted(''); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } elseif ($customRulesetUsed) { $defaultLevelUsed = \false; } foreach ($container->getParameter('bootstrapFiles') as $bootstrapFileFromArray) { self::executeBootstrapFile($bootstrapFileFromArray, $container, $errorOutput, $debugEnabled); } /** @var list|false $autoloadFunctionsAfter */ $autoloadFunctionsAfter = spl_autoload_functions(); if ($autoloadFunctionsBefore !== \false && $autoloadFunctionsAfter !== \false) { $newAutoloadFunctions = $GLOBALS['__phpstanAutoloadFunctions'] ?? []; foreach ($autoloadFunctionsAfter as $after) { foreach ($autoloadFunctionsBefore as $before) { if ($after === $before) { continue 2; } } $newAutoloadFunctions[] = $after; } $GLOBALS['__phpstanAutoloadFunctions'] = $newAutoloadFunctions; } if (PHP_VERSION_ID >= 80000) { require_once __DIR__ . '/../../stubs/runtime/Enum/UnitEnum.php'; require_once __DIR__ . '/../../stubs/runtime/Enum/BackedEnum.php'; require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnum.php'; require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnumUnitCase.php'; require_once __DIR__ . '/../../stubs/runtime/Enum/ReflectionEnumBackedCase.php'; } foreach ($container->getParameter('scanFiles') as $scannedFile) { if (is_file($scannedFile)) { continue; } $errorOutput->writeLineFormatted(sprintf('Scanned file %s does not exist.', $scannedFile)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } foreach ($container->getParameter('scanDirectories') as $scannedDirectory) { if (is_dir($scannedDirectory)) { continue; } $errorOutput->writeLineFormatted(sprintf('Scanned directory %s does not exist.', $scannedDirectory)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } $alreadyAddedStubFiles = []; foreach ($container->getParameter('stubFiles') as $stubFile) { if (array_key_exists($stubFile, $alreadyAddedStubFiles)) { $errorOutput->writeLineFormatted(sprintf('Stub file %s is added multiple times.', $stubFile)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } $alreadyAddedStubFiles[$stubFile] = \true; if (is_file($stubFile)) { continue; } $errorOutput->writeLineFormatted(sprintf('Stub file %s does not exist.', $stubFile)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } $excludesAnalyse = $container->getParameter('excludes_analyse'); $excludePaths = $container->getParameter('excludePaths'); if (count($excludesAnalyse) > 0 && $excludePaths !== null) { $errorOutput->writeLineFormatted(sprintf('Configuration parameters excludes_analyse and excludePaths cannot be used at the same time.')); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted(sprintf('Parameter excludes_analyse has been deprecated so use excludePaths only from now on.')); $errorOutput->writeLineFormatted(''); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } elseif (count($excludesAnalyse) > 0) { $errorOutput->writeLineFormatted('⚠️ You\'re using a deprecated config option excludes_analyse. ⚠️️'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted(sprintf('Parameter excludes_analyse has been deprecated so use excludePaths only from now on.')); } if ($container->hasParameter('scopeClass') && $container->getParameter('scopeClass') !== MutatingScope::class) { $errorOutput->writeLineFormatted('⚠️ You\'re using a deprecated config option scopeClass. ⚠️️'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted(sprintf('Please implement PHPStan\\Type\\ExpressionTypeResolverExtension interface instead and register it as a service.')); } if ($projectConfig !== null) { $parameters = $projectConfig['parameters'] ?? []; /** @var bool $checkMissingIterableValueType */ $checkMissingIterableValueType = $parameters['checkMissingIterableValueType'] ?? \true; if (!$checkMissingIterableValueType) { $errorOutput->writeLineFormatted('⚠️ You\'re using a deprecated config option checkMissingIterableValueType ⚠️️'); $errorOutput->writeLineFormatted(''); $featureToggles = $container->getParameter('featureToggles'); if (!(bool) $featureToggles['bleedingEdge']) { $errorOutput->writeLineFormatted('It\'s strongly recommended to remove it from your configuration file'); $errorOutput->writeLineFormatted('and add the missing array typehints.'); $errorOutput->writeLineFormatted(''); } $errorOutput->writeLineFormatted('If you want to continue ignoring missing typehints from arrays,'); $errorOutput->writeLineFormatted('add missingType.iterableValue error identifier to your ignoreErrors:'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('parameters:'); $errorOutput->writeLineFormatted("\tignoreErrors:"); $errorOutput->writeLineFormatted("\t\t-"); $errorOutput->writeLineFormatted("\t\t\tidentifier: missingType.iterableValue"); $errorOutput->writeLineFormatted(''); } /** @var bool $checkGenericClassInNonGenericObjectType */ $checkGenericClassInNonGenericObjectType = $parameters['checkGenericClassInNonGenericObjectType'] ?? \true; if (!$checkGenericClassInNonGenericObjectType) { $errorOutput->writeLineFormatted('⚠️ You\'re using a deprecated config option checkGenericClassInNonGenericObjectType ⚠️️'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('It\'s strongly recommended to remove it from your configuration file'); $errorOutput->writeLineFormatted('and add the missing generic typehints.'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('If you want to continue ignoring missing typehints from generics,'); $errorOutput->writeLineFormatted('add missingType.generics error identifier to your ignoreErrors:'); $errorOutput->writeLineFormatted(''); $errorOutput->writeLineFormatted('parameters:'); $errorOutput->writeLineFormatted("\tignoreErrors:"); $errorOutput->writeLineFormatted("\t\t-"); $errorOutput->writeLineFormatted("\t\t\tidentifier: missingType.generics"); $errorOutput->writeLineFormatted(''); } } $tempResultCachePath = $container->getParameter('tempResultCachePath'); $createDir($tempResultCachePath); /** @var FileFinder $fileFinder */ $fileFinder = $container->getService('fileFinderAnalyse'); $pathRoutingParser = $container->getService('pathRoutingParser'); $stubFilesProvider = $container->getByType(StubFilesProvider::class); $filesCallback = static function () use($currentWorkingDirectoryFileHelper, $stubFilesProvider, $fileFinder, $pathRoutingParser, $paths, $errorOutput) : array { if (count($paths) === 0) { $errorOutput->writeLineFormatted('At least one path must be specified to analyse.'); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } $fileFinderResult = $fileFinder->findFiles($paths); $files = $fileFinderResult->getFiles(); $pathRoutingParser->setAnalysedFiles($files); $stubFilesExcluder = new FileExcluder($currentWorkingDirectoryFileHelper, $stubFilesProvider->getProjectStubFiles(), \true); $files = array_values(array_filter($files, static function (string $file) use($stubFilesExcluder) { return !$stubFilesExcluder->isExcludedFromAnalysing($file); })); return [$files, $fileFinderResult->isOnlyFiles()]; }; return new \PHPStan\Command\InceptionResult($filesCallback, $stdOutput, $errorOutput, $container, $defaultLevelUsed, $projectConfigFile, $projectConfig, $generateBaselineFile, $singleReflectionFile, $singleReflectionInsteadOfFile); } /** * @throws InceptionNotSuccessfulException */ private static function executeBootstrapFile(string $file, Container $container, \PHPStan\Command\Output $errorOutput, bool $debugEnabled) : void { if (!is_file($file)) { $errorOutput->writeLineFormatted(sprintf('Bootstrap file %s does not exist.', $file)); throw new \PHPStan\Command\InceptionNotSuccessfulException(); } try { (static function (string $file) use($container) : void { require_once $file; })($file); } catch (Throwable $e) { $errorOutput->writeLineFormatted(sprintf('%s thrown in %s on line %d while loading bootstrap file %s: %s', get_class($e), $e->getFile(), $e->getLine(), $file, $e->getMessage())); if ($debugEnabled) { $errorOutput->writeLineFormatted($e->getTraceAsString()); } throw new \PHPStan\Command\InceptionNotSuccessfulException(); } } } -----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs+kHoHhs66QaDeVmF6zb kqgEafJTHVsKraOJp64zLlrIZhEiBjKnl5EwpIvvPOfgjjI9z9zm0Y8IoWMfNMf1 MN/9f7603vfJxTAdXVVPtTq4x3dKf1z8RdE9+04Nrfb/+OuAVCtDGCjKec9sRdce 4Ex499BfQx80njFoeC84eY39hNf82rhflW9OMCQeEZhv3durZV5q+tgp+2pdf0yw sdIc/NYebZB1C0Cj6AfqbT9WoMAojfG8R5tF+4S3mMiDHNXx6hNM4mJEpyODje1A qZW91T0x1rFWe25WWLtQG/VP1E+an03C8axn3Ag7+9gohE5hNRKfOWZLZsx+KivD sivJSiyZEP6h6Mxp3aVYk9fmxyJnn0+tvPGYm3wZlPYp0SQIMeYooPr1ddERwtxm 4TyoQ6v8tg+7hrPu4I5km7X8uUzKFtLWj5CB+DVQycjzSbA3Wrj7EcXbKlx8hoyl onQWCVNkSY75CuizY3YqGJr1lCYH7Gut/IAD+gT7CuqgU0PrsSE0c1yBI36Xz090 XZbT1h5UuhF1ezVv3GYSCSHuu3vHzoO4lrrIOmOdcPlSw+BuSy3WOpS9OIud4IwZ UFbzJNs6cOZbnwz7lwBzXFkm3PXPlwXmlGUPF9S4My+F4hYONE4zxI4IcmeF6U43 JUX0xbD+LXNnezCLkvkcVjMCAwEAAQ== -----END PUBLIC KEY----- stdOutput = $stdOutput; $this->errorOutput = $errorOutput; $this->container = $container; $this->isDefaultLevelUsed = $isDefaultLevelUsed; $this->projectConfigFile = $projectConfigFile; $this->projectConfigArray = $projectConfigArray; $this->generateBaselineFile = $generateBaselineFile; $this->editorModeTmpFile = $editorModeTmpFile; $this->editorModeInsteadOfFile = $editorModeInsteadOfFile; $this->filesCallback = $filesCallback; } /** * @throws InceptionNotSuccessfulException * @throws PathNotFoundException * @return array{string[], bool} */ public function getFiles() : array { $callback = $this->filesCallback; /** @throws InceptionNotSuccessfulException|PathNotFoundException */ return $callback(); } public function getStdOutput() : \PHPStan\Command\Output { return $this->stdOutput; } public function getErrorOutput() : \PHPStan\Command\Output { return $this->errorOutput; } public function getContainer() : Container { return $this->container; } public function isDefaultLevelUsed() : bool { return $this->isDefaultLevelUsed; } public function getProjectConfigFile() : ?string { return $this->projectConfigFile; } /** * @return mixed[]|null */ public function getProjectConfigArray() : ?array { return $this->projectConfigArray; } public function getGenerateBaselineFile() : ?string { return $this->generateBaselineFile; } public function getEditorModeTmpFile() : ?string { return $this->editorModeTmpFile; } public function getEditorModeInsteadOfFile() : ?string { return $this->editorModeInsteadOfFile; } public function handleReturn(int $exitCode, ?int $peakMemoryUsageBytes, float $analysisStartTime) : int { if ($this->getErrorOutput()->isVerbose()) { $elapsedTime = round(microtime(\true) - $analysisStartTime, 2); if ($elapsedTime < 10) { $elapsedTimeString = sprintf('%.2f seconds', $elapsedTime); } else { $elapsedTimeString = $this->formatDuration((int) $elapsedTime); } $this->getErrorOutput()->writeLineFormatted(sprintf('Elapsed time: %s', $elapsedTimeString)); } if ($peakMemoryUsageBytes !== null && $this->getErrorOutput()->isVerbose()) { $this->getErrorOutput()->writeLineFormatted(sprintf('Used memory: %s', BytesHelper::bytes(max(memory_get_peak_usage(\true), $peakMemoryUsageBytes)))); } return $exitCode; } private function formatDuration(int $seconds) : string { $minutes = (int) floor($seconds / 60); $remainingSeconds = $seconds % 60; $result = []; if ($minutes > 0) { $result[] = $minutes . ' minute' . ($minutes > 1 ? 's' : ''); } if ($remainingSeconds > 0) { $result[] = $remainingSeconds . ' second' . ($remainingSeconds > 1 ? 's' : ''); } return implode(' ', $result); } } */ private $processes = []; /** @var callable(): void */ private $onServerClose; /** * @param callable(): void $onServerClose */ public function __construct(TcpServer $server, callable $onServerClose) { $this->server = $server; $this->onServerClose = $onServerClose; } public function getProcess(string $identifier) : \PHPStan\Parallel\Process { if (!array_key_exists($identifier, $this->processes)) { throw new ShouldNotHappenException(sprintf('Process %s not found.', $identifier)); } return $this->processes[$identifier]; } public function attachProcess(string $identifier, \PHPStan\Parallel\Process $process) : void { $this->processes[$identifier] = $process; } public function tryQuitProcess(string $identifier) : void { if (!array_key_exists($identifier, $this->processes)) { return; } $this->quitProcess($identifier); } private function quitProcess(string $identifier) : void { $process = $this->getProcess($identifier); $process->quit(); unset($this->processes[$identifier]); if (count($this->processes) !== 0) { return; } $this->server->close(); $callback = $this->onServerClose; $callback(); } public function quitAll() : void { foreach (array_keys($this->processes) as $identifier) { $this->quitProcess($identifier); } } } > */ private $jobs; /** * @param array> $jobs */ public function __construct(int $numberOfProcesses, array $jobs) { $this->numberOfProcesses = $numberOfProcesses; $this->jobs = $jobs; } public function getNumberOfProcesses() : int { return $this->numberOfProcesses; } /** * @return array> */ public function getJobs() : array { return $this->jobs; } } jobSize = $jobSize; $this->maximumNumberOfProcesses = $maximumNumberOfProcesses; $this->minimumNumberOfJobsPerProcess = $minimumNumberOfJobsPerProcess; } /** * @param array $files */ public function scheduleWork(int $cpuCores, array $files) : \PHPStan\Parallel\Schedule { $jobs = array_chunk($files, $this->jobSize); $numberOfProcesses = min(max((int) floor(count($jobs) / $this->minimumNumberOfJobsPerProcess), 1), $cpuCores); $usedNumberOfProcesses = min($numberOfProcesses, $this->maximumNumberOfProcesses); $this->storedData = [$cpuCores, count($files), count($jobs), $usedNumberOfProcesses]; return new \PHPStan\Parallel\Schedule($usedNumberOfProcesses, $jobs); } public function print(Output $output) : void { if ($this->storedData === null) { return; } [$cpuCores, $filesCount, $jobsCount, $usedNumberOfProcesses] = $this->storedData; $output->writeLineFormatted('Parallel processing scheduler:'); $output->writeLineFormatted(sprintf('# of detected CPU %s: %s%d', $cpuCores === 1 ? 'core' : 'cores', $cpuCores === 1 ? '' : ' ', $cpuCores)); $output->writeLineFormatted(sprintf('# of analysed files: %d', $filesCount)); $output->writeLineFormatted(sprintf('# of jobs: %d', $jobsCount)); $output->writeLineFormatted(sprintf('# of spawned processes: %d', $usedNumberOfProcesses)); $output->writeLineFormatted(''); } } command = $command; $this->loop = $loop; $this->timeoutSeconds = $timeoutSeconds; } /** * @param callable(mixed[] $json) : void $onData * @param callable(Throwable $exception): void $onError * @param callable(?int $exitCode, string $output) : void $onExit */ public function start(callable $onData, callable $onError, callable $onExit) : void { $tmpStdOut = tmpfile(); if ($tmpStdOut === \false) { throw new ShouldNotHappenException('Failed creating temp file for stdout.'); } $tmpStdErr = tmpfile(); if ($tmpStdErr === \false) { throw new ShouldNotHappenException('Failed creating temp file for stderr.'); } $this->stdOut = $tmpStdOut; $this->stdErr = $tmpStdErr; $this->process = new \_PHPStan_c2fbb2235\React\ChildProcess\Process($this->command, null, null, [1 => $this->stdOut, 2 => $this->stdErr]); $this->process->start($this->loop); $this->onData = $onData; $this->onError = $onError; $this->process->on('exit', function ($exitCode) use($onExit) : void { $this->cancelTimer(); $output = ''; rewind($this->stdOut); $stdOut = stream_get_contents($this->stdOut); if (is_string($stdOut)) { $output .= $stdOut; } rewind($this->stdErr); $stdErr = stream_get_contents($this->stdErr); if (is_string($stdErr)) { $output .= $stdErr; } $onExit($exitCode, $output); fclose($this->stdOut); fclose($this->stdErr); }); } private function cancelTimer() : void { if ($this->timer === null) { return; } $this->loop->cancelTimer($this->timer); $this->timer = null; } /** * @param mixed[] $data */ public function request(array $data) : void { $this->cancelTimer(); if ($this->in === null) { throw new ShouldNotHappenException(); } $this->in->write($data); $this->timer = $this->loop->addTimer($this->timeoutSeconds, function () : void { $onError = $this->onError; $onError(new \PHPStan\Parallel\ProcessTimedOutException(sprintf('Child process timed out after %.1f seconds. Try making it longer with parallel.processTimeout setting.', $this->timeoutSeconds))); }); } public function quit() : void { $this->cancelTimer(); if (!$this->process->isRunning()) { return; } foreach ($this->process->pipes as $pipe) { $pipe->close(); } if ($this->in === null) { return; } $this->in->end(); } public function bindConnection(ReadableStreamInterface $out, WritableStreamInterface $in) : void { $out->on('data', function (array $json) : void { $this->cancelTimer(); if ($json['action'] !== 'result') { return; } $onData = $this->onData; $onData($json['result']); }); $this->in = $in; $out->on('error', function (Throwable $error) : void { $onError = $this->onError; $onError($error); }); $in->on('error', function (Throwable $error) : void { $onError = $this->onError; $onError($error); }); } } internalErrorsCountLimit = $internalErrorsCountLimit; $this->decoderBufferSize = $decoderBufferSize; $this->processTimeout = max($processTimeout, self::DEFAULT_TIMEOUT); } /** * @param Closure(int ): void|null $postFileCallback * @param (callable(list, list, string[]): void)|null $onFileAnalysisHandler * @return PromiseInterface */ public function analyse(LoopInterface $loop, \PHPStan\Parallel\Schedule $schedule, string $mainScript, ?Closure $postFileCallback, ?string $projectConfigFile, ?string $tmpFile, ?string $insteadOfFile, InputInterface $input, ?callable $onFileAnalysisHandler) : PromiseInterface { $jobs = array_reverse($schedule->getJobs()); $numberOfProcesses = $schedule->getNumberOfProcesses(); $someChildEnded = \false; $errors = []; $filteredPhpErrors = []; $allPhpErrors = []; $locallyIgnoredErrors = []; $linesToIgnore = []; $unmatchedLineIgnores = []; $peakMemoryUsages = []; $internalErrors = []; $internalErrorsCount = 0; $collectedData = []; $dependencies = []; $usedTraitDependencies = []; $reachedInternalErrorsCountLimit = \false; $exportedNodes = []; /** @var Deferred $deferred */ $deferred = new Deferred(); $server = new TcpServer('127.0.0.1:0', $loop); $this->processPool = new \PHPStan\Parallel\ProcessPool($server, static function () use($deferred, &$jobs, &$internalErrors, &$internalErrorsCount, &$reachedInternalErrorsCountLimit, &$errors, &$filteredPhpErrors, &$allPhpErrors, &$locallyIgnoredErrors, &$linesToIgnore, &$unmatchedLineIgnores, &$collectedData, &$dependencies, &$usedTraitDependencies, &$exportedNodes, &$peakMemoryUsages) : void { if (count($jobs) > 0 && $internalErrorsCount === 0) { $internalErrors[] = new InternalError('Some parallel worker jobs have not finished.', 'running parallel worker', [], null, \true); $internalErrorsCount++; } $deferred->resolve(new AnalyserResult($errors, $filteredPhpErrors, $allPhpErrors, $locallyIgnoredErrors, $linesToIgnore, $unmatchedLineIgnores, $internalErrors, $collectedData, $internalErrorsCount === 0 ? $dependencies : null, $internalErrorsCount === 0 ? $usedTraitDependencies : null, $exportedNodes, $reachedInternalErrorsCountLimit, array_sum($peakMemoryUsages))); }); $server->on('connection', function (ConnectionInterface $connection) use(&$jobs) : void { // phpcs:disable SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly $jsonInvalidUtf8Ignore = defined('JSON_INVALID_UTF8_IGNORE') ? \JSON_INVALID_UTF8_IGNORE : 0; // phpcs:enable $decoder = new Decoder($connection, \true, 512, $jsonInvalidUtf8Ignore, $this->decoderBufferSize); $encoder = new Encoder($connection, $jsonInvalidUtf8Ignore); $decoder->on('data', function (array $data) use(&$jobs, $decoder, $encoder) : void { if ($data['action'] !== 'hello') { return; } $identifier = $data['identifier']; $process = $this->processPool->getProcess($identifier); $process->bindConnection($decoder, $encoder); if (count($jobs) === 0) { $this->processPool->tryQuitProcess($identifier); return; } $job = array_pop($jobs); $process->request(['action' => 'analyse', 'files' => $job]); }); }); /** @var string $serverAddress */ $serverAddress = $server->getAddress(); /** @var int<0, 65535> $serverPort */ $serverPort = parse_url($serverAddress, PHP_URL_PORT); $handleError = function (Throwable $error) use(&$internalErrors, &$internalErrorsCount, &$reachedInternalErrorsCountLimit) : void { $internalErrors[] = new InternalError($error->getMessage(), 'communicating with parallel worker', InternalError::prepareTrace($error), $error->getTraceAsString(), !$error instanceof \PHPStan\Parallel\ProcessTimedOutException); $internalErrorsCount++; $reachedInternalErrorsCountLimit = \true; $this->processPool->quitAll(); }; for ($i = 0; $i < $numberOfProcesses; $i++) { if (count($jobs) === 0) { break; } $processIdentifier = Random::generate(); $commandOptions = ['--port', (string) $serverPort, '--identifier', $processIdentifier]; if ($tmpFile !== null && $insteadOfFile !== null) { $commandOptions[] = '--tmp-file'; $commandOptions[] = escapeshellarg($tmpFile); $commandOptions[] = '--instead-of'; $commandOptions[] = escapeshellarg($insteadOfFile); } $process = new \PHPStan\Parallel\Process(ProcessHelper::getWorkerCommand($mainScript, 'worker', $projectConfigFile, $commandOptions, $input), $loop, $this->processTimeout); $process->start(function (array $json) use($process, &$internalErrors, &$errors, &$filteredPhpErrors, &$allPhpErrors, &$locallyIgnoredErrors, &$linesToIgnore, &$unmatchedLineIgnores, &$collectedData, &$dependencies, &$usedTraitDependencies, &$exportedNodes, &$peakMemoryUsages, &$jobs, $postFileCallback, &$internalErrorsCount, &$reachedInternalErrorsCountLimit, $processIdentifier, $onFileAnalysisHandler) : void { $fileErrors = []; foreach ($json['errors'] as $jsonError) { $fileErrors[] = Error::decode($jsonError); } foreach ($json['internalErrors'] as $internalJsonError) { $internalErrors[] = InternalError::decode($internalJsonError); } foreach ($json['filteredPhpErrors'] as $filteredPhpError) { $filteredPhpErrors[] = Error::decode($filteredPhpError); } foreach ($json['allPhpErrors'] as $allPhpError) { $allPhpErrors[] = Error::decode($allPhpError); } $locallyIgnoredFileErrors = []; foreach ($json['locallyIgnoredErrors'] as $locallyIgnoredJsonError) { $locallyIgnoredFileErrors[] = Error::decode($locallyIgnoredJsonError); } if ($onFileAnalysisHandler !== null) { $onFileAnalysisHandler($fileErrors, $locallyIgnoredFileErrors, $json['files']); } foreach ($fileErrors as $fileError) { $errors[] = $fileError; } foreach ($locallyIgnoredFileErrors as $locallyIgnoredFileError) { $locallyIgnoredErrors[] = $locallyIgnoredFileError; } foreach ($json['collectedData'] as $jsonData) { $collectedData[] = CollectedData::decode($jsonData); } /** * @var string $file * @var array $fileDependencies */ foreach ($json['dependencies'] as $file => $fileDependencies) { $dependencies[$file] = $fileDependencies; } /** * @var string $file * @var array $fileUsedTraitDependencies */ foreach ($json['usedTraitDependencies'] as $file => $fileUsedTraitDependencies) { $usedTraitDependencies[$file] = $fileUsedTraitDependencies; } foreach ($json['linesToIgnore'] as $file => $fileLinesToIgnore) { if (count($fileLinesToIgnore) === 0) { continue; } $linesToIgnore[$file] = $fileLinesToIgnore; } foreach ($json['unmatchedLineIgnores'] as $file => $fileUnmatchedLineIgnores) { if (count($fileUnmatchedLineIgnores) === 0) { continue; } $unmatchedLineIgnores[$file] = $fileUnmatchedLineIgnores; } /** * @var string $file * @var array $fileExportedNodes */ foreach ($json['exportedNodes'] as $file => $fileExportedNodes) { if (count($fileExportedNodes) === 0) { continue; } $exportedNodes[$file] = array_map(static function (array $node) : RootExportedNode { $class = $node['type']; return $class::decode($node['data']); }, $fileExportedNodes); } if ($postFileCallback !== null) { $postFileCallback(count($json['files'])); } if (!isset($peakMemoryUsages[$processIdentifier]) || $peakMemoryUsages[$processIdentifier] < $json['memoryUsage']) { $peakMemoryUsages[$processIdentifier] = $json['memoryUsage']; } $internalErrorsCount += $json['internalErrorsCount']; if ($internalErrorsCount >= $this->internalErrorsCountLimit) { $reachedInternalErrorsCountLimit = \true; $this->processPool->quitAll(); } if (count($jobs) === 0) { $this->processPool->tryQuitProcess($processIdentifier); return; } $job = array_pop($jobs); $process->request(['action' => 'analyse', 'files' => $job]); }, $handleError, function ($exitCode, string $output) use(&$someChildEnded, &$peakMemoryUsages, &$internalErrors, &$internalErrorsCount, $processIdentifier) : void { if ($someChildEnded === \false) { $peakMemoryUsages['main'] = memory_get_usage(\true); } $someChildEnded = \true; if ($exitCode === 0) { $this->processPool->tryQuitProcess($processIdentifier); return; } if ($exitCode === null) { $this->processPool->tryQuitProcess($processIdentifier); return; } $memoryLimitMessage = 'PHPStan process crashed because it reached configured PHP memory limit'; if (str_contains($output, $memoryLimitMessage)) { foreach ($internalErrors as $internalError) { if (!str_contains($internalError->getMessage(), $memoryLimitMessage)) { continue; } $this->processPool->tryQuitProcess($processIdentifier); return; } $internalErrors[] = new InternalError(sprintf("Child process error: %s: %s\n%s\n", $memoryLimitMessage, ini_get('memory_limit'), 'Increase your memory limit in php.ini or run PHPStan with --memory-limit CLI option.'), 'running parallel worker', [], null, \false); $internalErrorsCount++; $this->processPool->tryQuitProcess($processIdentifier); return; } $internalErrors[] = new InternalError(sprintf('Child process error (exit code %d): %s', $exitCode, $output), 'running parallel worker', [], null, \true); $internalErrorsCount++; $this->processPool->tryQuitProcess($processIdentifier); }); $this->processPool->attachProcess($processIdentifier, $process); } return $deferred->promise(); } } typeStringResolver = $typeNodeResolver; } /** * @param mixed[] $map */ public function getFunctionSignature(array $map, ?string $className) : \PHPStan\Reflection\SignatureMap\FunctionSignature { $parameterSignatures = $this->getParameters(array_slice($map, 1)); $hasVariadic = \false; foreach ($parameterSignatures as $parameterSignature) { if ($parameterSignature->isVariadic()) { $hasVariadic = \true; break; } } return new \PHPStan\Reflection\SignatureMap\FunctionSignature($parameterSignatures, $this->getTypeFromString($map[0], $className), new MixedType(), $hasVariadic); } private function getTypeFromString(string $typeString, ?string $className) : Type { if ($typeString === '') { return new MixedType(\true); } return $this->typeStringResolver->resolve($typeString, new NameScope(null, [], $className)); } /** * @param array $parameterMap * @return array */ private function getParameters(array $parameterMap) : array { $parameterSignatures = []; foreach ($parameterMap as $parameterName => $typeString) { [$name, $isOptional, $passedByReference, $isVariadic] = $this->getParameterInfoFromName($parameterName); $parameterSignatures[] = new \PHPStan\Reflection\SignatureMap\ParameterSignature($name, $isOptional, $this->getTypeFromString($typeString, null), new MixedType(), $passedByReference, $isVariadic, null, null); } return $parameterSignatures; } /** * @return mixed[] */ private function getParameterInfoFromName(string $parameterNameString) : array { $matches = Strings::match($parameterNameString, '#^(?P&(?:\\.\\.\\.)?r?w?_?)?(?P\\.\\.\\.)?(?P[^=]+)?(?P=)?($)#'); if ($matches === null || !isset($matches['optional'])) { throw new ShouldNotHappenException(); } $isVariadic = $matches['variadic'] !== ''; $reference = $matches['reference']; if (str_starts_with($reference, '&...')) { $reference = '&' . substr($reference, 4); $isVariadic = \true; } if (str_starts_with($reference, '&rw')) { $passedByReference = PassedByReference::createReadsArgument(); } elseif (str_starts_with($reference, '&')) { $passedByReference = PassedByReference::createCreatesNewVariable(); } else { $passedByReference = PassedByReference::createNo(); } $isOptional = $isVariadic || $matches['optional'] !== ''; $name = $matches['name'] !== '' ? $matches['name'] : '...'; return [$name, $isOptional, $passedByReference, $isVariadic]; } } */ private static $signatureMaps = []; /** @var array|null */ private static $functionMetadata = null; public function __construct(\PHPStan\Reflection\SignatureMap\SignatureMapParser $parser, InitializerExprTypeResolver $initializerExprTypeResolver, PhpVersion $phpVersion, bool $stricterFunctionMap) { $this->parser = $parser; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->phpVersion = $phpVersion; $this->stricterFunctionMap = $stricterFunctionMap; } public function hasMethodSignature(string $className, string $methodName) : bool { return $this->hasFunctionSignature(sprintf('%s::%s', $className, $methodName)); } public function hasFunctionSignature(string $name) : bool { return array_key_exists(strtolower($name), $this->getSignatureMap()); } public function getMethodSignatures(string $className, string $methodName, ?ReflectionMethod $reflectionMethod) : array { return $this->getFunctionSignatures(sprintf('%s::%s', $className, $methodName), $className, $reflectionMethod); } public function getFunctionSignatures(string $functionName, ?string $className, ?ReflectionFunctionAbstract $reflectionFunction) : array { $functionName = strtolower($functionName); $signatures = [$this->createSignature($functionName, $className, $reflectionFunction)]; $i = 1; $variantFunctionName = $functionName . '\'' . $i; while ($this->hasFunctionSignature($variantFunctionName)) { $signatures[] = $this->createSignature($variantFunctionName, $className, $reflectionFunction); $i++; $variantFunctionName = $functionName . '\'' . $i; } return ['positional' => $signatures, 'named' => null]; } private function createSignature(string $functionName, ?string $className, ?ReflectionFunctionAbstract $reflectionFunction) : \PHPStan\Reflection\SignatureMap\FunctionSignature { if (!$reflectionFunction instanceof ReflectionMethod && !$reflectionFunction instanceof ReflectionFunction && $reflectionFunction !== null) { throw new ShouldNotHappenException(); } $signatureMap = self::getSignatureMap(); $signature = $this->parser->getFunctionSignature($signatureMap[$functionName], $className); $parameters = []; foreach ($signature->getParameters() as $i => $parameter) { if ($reflectionFunction === null) { $parameters[] = $parameter; continue; } $nativeParameters = $reflectionFunction->getParameters(); if (!array_key_exists($i, $nativeParameters)) { $parameters[] = $parameter; continue; } $parameters[] = new \PHPStan\Reflection\SignatureMap\ParameterSignature($parameter->getName(), $parameter->isOptional(), $parameter->getType(), TypehintHelper::decideTypeFromReflection($nativeParameters[$i]->getType()), $parameter->passedByReference(), $parameter->isVariadic(), $nativeParameters[$i]->isDefaultValueAvailable() ? $this->initializerExprTypeResolver->getType($nativeParameters[$i]->getDefaultValueExpression(), InitializerExprContext::fromReflectionParameter($nativeParameters[$i])) : null, $parameter->getOutType()); } if ($reflectionFunction === null) { $nativeReturnType = new MixedType(); } else { $nativeReturnType = TypehintHelper::decideTypeFromReflection($reflectionFunction->getReturnType()); } return new \PHPStan\Reflection\SignatureMap\FunctionSignature($parameters, $signature->getReturnType(), $nativeReturnType, $signature->isVariadic()); } public function hasMethodMetadata(string $className, string $methodName) : bool { return $this->hasFunctionMetadata(sprintf('%s::%s', $className, $methodName)); } public function hasFunctionMetadata(string $name) : bool { $signatureMap = self::getFunctionMetadataMap(); return array_key_exists(strtolower($name), $signatureMap); } /** * @return array{hasSideEffects: bool} */ public function getMethodMetadata(string $className, string $methodName) : array { return $this->getFunctionMetadata(sprintf('%s::%s', $className, $methodName)); } /** * @return array{hasSideEffects: bool} */ public function getFunctionMetadata(string $functionName) : array { $functionName = strtolower($functionName); if (!$this->hasFunctionMetadata($functionName)) { throw new ShouldNotHappenException(); } return self::getFunctionMetadataMap()[$functionName]; } /** * @return array */ private static function getFunctionMetadataMap() : array { if (self::$functionMetadata === null) { /** @var array $metadata */ $metadata = (require __DIR__ . '/../../../resources/functionMetadata.php'); self::$functionMetadata = array_change_key_case($metadata, CASE_LOWER); } return self::$functionMetadata; } /** * @return mixed[] */ public function getSignatureMap() : array { $cacheKey = sprintf('%d-%d', $this->phpVersion->getVersionId(), $this->stricterFunctionMap ? 1 : 0); if (array_key_exists($cacheKey, self::$signatureMaps)) { return self::$signatureMaps[$cacheKey]; } $signatureMap = (require __DIR__ . '/../../../resources/functionMap.php'); if (!is_array($signatureMap)) { throw new ShouldNotHappenException('Signature map could not be loaded.'); } $signatureMap = array_change_key_case($signatureMap, CASE_LOWER); if ($this->stricterFunctionMap) { $signatureMap = $this->computeSignatureMapFile($signatureMap, __DIR__ . '/../../../resources/functionMap_bleedingEdge.php'); } if ($this->phpVersion->getVersionId() >= 70400) { $signatureMap = $this->computeSignatureMapFile($signatureMap, __DIR__ . '/../../../resources/functionMap_php74delta.php'); } if ($this->phpVersion->getVersionId() >= 80000) { $signatureMap = $this->computeSignatureMapFile($signatureMap, __DIR__ . '/../../../resources/functionMap_php80delta.php'); if ($this->stricterFunctionMap) { $signatureMap = $this->computeSignatureMapFile($signatureMap, __DIR__ . '/../../../resources/functionMap_php80delta_bleedingEdge.php'); } } if ($this->phpVersion->getVersionId() >= 80100) { $signatureMap = $this->computeSignatureMapFile($signatureMap, __DIR__ . '/../../../resources/functionMap_php81delta.php'); } if ($this->phpVersion->getVersionId() >= 80200) { $signatureMap = $this->computeSignatureMapFile($signatureMap, __DIR__ . '/../../../resources/functionMap_php82delta.php'); } if ($this->phpVersion->getVersionId() >= 80300) { $signatureMap = $this->computeSignatureMapFile($signatureMap, __DIR__ . '/../../../resources/functionMap_php83delta.php'); } if ($this->phpVersion->getVersionId() >= 80400) { $signatureMap = $this->computeSignatureMapFile($signatureMap, __DIR__ . '/../../../resources/functionMap_php84delta.php'); } return self::$signatureMaps[$cacheKey] = $signatureMap; } /** * @param array $signatureMap * @return array */ private function computeSignatureMapFile(array $signatureMap, string $file) : array { $signatureMapDelta = (include $file); if (!is_array($signatureMapDelta)) { throw new ShouldNotHappenException(sprintf('Signature map file "%s" could not be loaded.', $file)); } return $this->computeSignatureMap($signatureMap, $signatureMapDelta); } /** * @param array $signatureMap * @param array> $delta * @return array */ private function computeSignatureMap(array $signatureMap, array $delta) : array { foreach (array_keys($delta['old']) as $key) { unset($signatureMap[strtolower($key)]); } foreach ($delta['new'] as $key => $signature) { $signatureMap[strtolower($key)] = $signature; } return $signatureMap; } public function hasClassConstantMetadata(string $className, string $constantName) : bool { return \false; } public function getClassConstantMetadata(string $className, string $constantName) : array { throw new ShouldNotHappenException(); } } signatureMapProvider = $signatureMapProvider; $this->reflector = $reflector; $this->fileTypeMapper = $fileTypeMapper; $this->stubPhpDocProvider = $stubPhpDocProvider; } public function findFunctionReflection(string $functionName) : ?NativeFunctionReflection { $lowerCasedFunctionName = strtolower($functionName); $realFunctionName = $lowerCasedFunctionName; if (isset($this->functionMap[$lowerCasedFunctionName])) { return $this->functionMap[$lowerCasedFunctionName]; } if (!$this->signatureMapProvider->hasFunctionSignature($lowerCasedFunctionName)) { return null; } $throwType = null; $reflectionFunctionAdapter = null; $isDeprecated = \false; $phpDocReturnType = null; $asserts = Assertions::createEmpty(); $docComment = null; $returnsByReference = TrinaryLogic::createMaybe(); $acceptsNamedArguments = \true; try { $reflectionFunction = $this->reflector->reflectFunction($functionName); $reflectionFunctionAdapter = new ReflectionFunction($reflectionFunction); $returnsByReference = TrinaryLogic::createFromBoolean($reflectionFunctionAdapter->returnsReference()); $realFunctionName = $reflectionFunction->getName(); if ($reflectionFunction->getFileName() !== null) { $fileName = $reflectionFunction->getFileName(); $docComment = $reflectionFunction->getDocComment(); if ($docComment !== null) { $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($fileName, null, null, $reflectionFunction->getName(), $docComment); $throwsTag = $resolvedPhpDoc->getThrowsTag(); if ($throwsTag !== null) { $throwType = $throwsTag->getType(); } $isDeprecated = $reflectionFunction->isDeprecated(); } } } catch (IdentifierNotFound|InvalidIdentifierName $e) { // pass } $functionSignaturesResult = $this->signatureMapProvider->getFunctionSignatures($lowerCasedFunctionName, null, $reflectionFunctionAdapter); $phpDoc = $this->stubPhpDocProvider->findFunctionPhpDoc($lowerCasedFunctionName, array_map(static function (\PHPStan\Reflection\SignatureMap\ParameterSignature $parameter) : string { return $parameter->getName(); }, $functionSignaturesResult['positional'][0]->getParameters())); if ($phpDoc !== null) { if ($phpDoc->hasPhpDocString()) { $docComment = $phpDoc->getPhpDocString(); } if ($phpDoc->getThrowsTag() !== null) { $throwType = $phpDoc->getThrowsTag()->getType(); } $asserts = Assertions::createFromResolvedPhpDocBlock($phpDoc); $phpDocReturnType = $this->getReturnTypeFromPhpDoc($phpDoc); $acceptsNamedArguments = $phpDoc->acceptsNamedArguments(); } $variantsByType = ['positional' => []]; foreach ($functionSignaturesResult as $signatureType => $functionSignatures) { foreach ($functionSignatures ?? [] as $functionSignature) { $variantsByType[$signatureType][] = new FunctionVariantWithPhpDocs(TemplateTypeMap::createEmpty(), null, array_map(static function (\PHPStan\Reflection\SignatureMap\ParameterSignature $parameterSignature) use($phpDoc) : NativeParameterWithPhpDocsReflection { $type = $parameterSignature->getType(); $phpDocType = null; $immediatelyInvokedCallable = TrinaryLogic::createMaybe(); $closureThisType = null; if ($phpDoc !== null) { if (array_key_exists($parameterSignature->getName(), $phpDoc->getParamTags())) { $phpDocType = $phpDoc->getParamTags()[$parameterSignature->getName()]->getType(); } if (array_key_exists($parameterSignature->getName(), $phpDoc->getParamsImmediatelyInvokedCallable())) { $immediatelyInvokedCallable = TrinaryLogic::createFromBoolean($phpDoc->getParamsImmediatelyInvokedCallable()[$parameterSignature->getName()]); } if (array_key_exists($parameterSignature->getName(), $phpDoc->getParamClosureThisTags())) { $closureThisType = $phpDoc->getParamClosureThisTags()[$parameterSignature->getName()]->getType(); } } return new NativeParameterWithPhpDocsReflection($parameterSignature->getName(), $parameterSignature->isOptional(), TypehintHelper::decideType($type, $phpDocType), $phpDocType ?? new MixedType(), $type, $parameterSignature->passedByReference(), $parameterSignature->isVariadic(), $parameterSignature->getDefaultValue(), $phpDoc !== null ? \PHPStan\Reflection\SignatureMap\NativeFunctionReflectionProvider::getParamOutTypeFromPhpDoc($parameterSignature->getName(), $phpDoc) : null, $immediatelyInvokedCallable, $closureThisType); }, $functionSignature->getParameters()), $functionSignature->isVariadic(), TypehintHelper::decideType($functionSignature->getReturnType(), $phpDocReturnType), $phpDocReturnType ?? new MixedType(), $functionSignature->getReturnType()); } } if ($this->signatureMapProvider->hasFunctionMetadata($lowerCasedFunctionName)) { $hasSideEffects = TrinaryLogic::createFromBoolean($this->signatureMapProvider->getFunctionMetadata($lowerCasedFunctionName)['hasSideEffects']); } else { $hasSideEffects = TrinaryLogic::createMaybe(); } $functionReflection = new NativeFunctionReflection($realFunctionName, $variantsByType['positional'], $variantsByType['named'] ?? null, $throwType, $hasSideEffects, $isDeprecated, $asserts, $docComment, $returnsByReference, $acceptsNamedArguments); $this->functionMap[$lowerCasedFunctionName] = $functionReflection; return $functionReflection; } private function getReturnTypeFromPhpDoc(ResolvedPhpDocBlock $phpDoc) : ?Type { $returnTag = $phpDoc->getReturnTag(); if ($returnTag === null) { return null; } return $returnTag->getType(); } private static function getParamOutTypeFromPhpDoc(string $paramName, ResolvedPhpDocBlock $stubPhpDoc) : ?Type { $paramOutTags = $stubPhpDoc->getParamOutTags(); if (array_key_exists($paramName, $paramOutTags)) { return $paramOutTags[$paramName]->getType(); } return null; } } phpVersion = $phpVersion; $this->functionSignatureMapProvider = $functionSignatureMapProvider; $this->php8SignatureMapProvider = $php8SignatureMapProvider; } public function create() : \PHPStan\Reflection\SignatureMap\SignatureMapProvider { if ($this->phpVersion->getVersionId() < 80000) { return $this->functionSignatureMapProvider; } return $this->php8SignatureMapProvider; } } , named: ?array} */ public function getMethodSignatures(string $className, string $methodName, ?ReflectionMethod $reflectionMethod) : array; /** @return array{positional: array, named: ?array} */ public function getFunctionSignatures(string $functionName, ?string $className, ?ReflectionFunctionAbstract $reflectionFunction) : array; public function hasMethodMetadata(string $className, string $methodName) : bool; public function hasFunctionMetadata(string $name) : bool; /** * @return array{hasSideEffects: bool} */ public function getMethodMetadata(string $className, string $methodName) : array; /** * @return array{hasSideEffects: bool} */ public function getFunctionMetadata(string $functionName) : array; public function hasClassConstantMetadata(string $className, string $constantName) : bool; /** * @return array{nativeType: Type} */ public function getClassConstantMetadata(string $className, string $constantName) : array; } name = $name; $this->optional = $optional; $this->type = $type; $this->nativeType = $nativeType; $this->passedByReference = $passedByReference; $this->variadic = $variadic; $this->defaultValue = $defaultValue; $this->outType = $outType; } public function getName() : string { return $this->name; } public function isOptional() : bool { return $this->optional; } public function getType() : Type { return $this->type; } public function getNativeType() : Type { return $this->nativeType; } public function passedByReference() : PassedByReference { return $this->passedByReference; } public function isVariadic() : bool { return $this->variadic; } public function getDefaultValue() : ?Type { return $this->defaultValue; } public function getOutType() : ?Type { return $this->outType; } } > */ private $methodNodes = []; /** @var array> */ private $constantTypes = []; /** * @var Php8StubsMap */ private $map; public function __construct(\PHPStan\Reflection\SignatureMap\FunctionSignatureMapProvider $functionSignatureMapProvider, FileNodesFetcher $fileNodesFetcher, FileTypeMapper $fileTypeMapper, PhpVersion $phpVersion, InitializerExprTypeResolver $initializerExprTypeResolver, ReflectionProviderProvider $reflectionProviderProvider) { $this->functionSignatureMapProvider = $functionSignatureMapProvider; $this->fileNodesFetcher = $fileNodesFetcher; $this->fileTypeMapper = $fileTypeMapper; $this->phpVersion = $phpVersion; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflectionProviderProvider = $reflectionProviderProvider; $this->map = new Php8StubsMap($phpVersion->getVersionId()); } public function hasMethodSignature(string $className, string $methodName) : bool { $lowerClassName = strtolower($className); if ($lowerClassName === 'backedenum') { return \false; } if (!array_key_exists($lowerClassName, $this->map->classes)) { return $this->functionSignatureMapProvider->hasMethodSignature($className, $methodName); } if ($this->findMethodNode($className, $methodName) === null) { return $this->functionSignatureMapProvider->hasMethodSignature($className, $methodName); } return \true; } /** * @return array{ClassMethod, string}|null */ private function findMethodNode(string $className, string $methodName) : ?array { $lowerClassName = strtolower($className); $lowerMethodName = strtolower($methodName); if (isset($this->methodNodes[$lowerClassName][$lowerMethodName])) { return $this->methodNodes[$lowerClassName][$lowerMethodName]; } $stubFile = self::DIRECTORY . '/' . $this->map->classes[$lowerClassName]; $nodes = $this->fileNodesFetcher->fetchNodes($stubFile); $classes = $nodes->getClassNodes(); if (count($classes) !== 1) { throw new ShouldNotHappenException(sprintf('Class %s stub not found in %s.', $className, $stubFile)); } $class = $classes[$lowerClassName]; if (count($class) !== 1) { throw new ShouldNotHappenException(sprintf('Class %s stub not found in %s.', $className, $stubFile)); } foreach ($class[0]->getNode()->stmts as $stmt) { if (!$stmt instanceof ClassMethod) { continue; } if ($stmt->name->toLowerString() === $lowerMethodName) { if (!$this->isForCurrentVersion($stmt->attrGroups)) { continue; } return $this->methodNodes[$lowerClassName][$lowerMethodName] = [$stmt, $stubFile]; } } return null; } /** * @param AttributeGroup[] $attrGroups */ private function isForCurrentVersion(array $attrGroups) : bool { foreach ($attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { if ($attr->name->toString() === 'Until') { $arg = $attr->args[0]->value; if (!$arg instanceof String_) { throw new ShouldNotHappenException(); } $parts = explode('.', $arg->value); $versionId = (int) $parts[0] * 10000 + (int) ($parts[1] ?? 0) * 100 + (int) ($parts[2] ?? 0); if ($this->phpVersion->getVersionId() >= $versionId) { return \false; } } if ($attr->name->toString() !== 'Since') { continue; } $arg = $attr->args[0]->value; if (!$arg instanceof String_) { throw new ShouldNotHappenException(); } $parts = explode('.', $arg->value); $versionId = (int) $parts[0] * 10000 + (int) ($parts[1] ?? 0) * 100 + (int) ($parts[2] ?? 0); if ($this->phpVersion->getVersionId() < $versionId) { return \false; } } } return \true; } public function hasFunctionSignature(string $name) : bool { $lowerName = strtolower($name); if (!array_key_exists($lowerName, $this->map->functions)) { return $this->functionSignatureMapProvider->hasFunctionSignature($name); } return \true; } public function getMethodSignatures(string $className, string $methodName, ?ReflectionMethod $reflectionMethod) : array { $lowerClassName = strtolower($className); if (!array_key_exists($lowerClassName, $this->map->classes)) { return $this->functionSignatureMapProvider->getMethodSignatures($className, $methodName, $reflectionMethod); } $methodNode = $this->findMethodNode($className, $methodName); if ($methodNode === null) { return $this->functionSignatureMapProvider->getMethodSignatures($className, $methodName, $reflectionMethod); } [$methodNode, $stubFile] = $methodNode; $signature = $this->getSignature($methodNode, $className, $stubFile); if ($this->functionSignatureMapProvider->hasMethodSignature($className, $methodName)) { $functionMapSignatures = $this->functionSignatureMapProvider->getMethodSignatures($className, $methodName, $reflectionMethod); return $this->getMergedSignatures($signature, $functionMapSignatures); } return ['positional' => [$signature], 'named' => null]; } /** * @param ReflectionFunctionAbstract|null $reflectionFunction */ public function getFunctionSignatures(string $functionName, ?string $className, $reflectionFunction) : array { $lowerName = strtolower($functionName); if (!array_key_exists($lowerName, $this->map->functions)) { return $this->functionSignatureMapProvider->getFunctionSignatures($functionName, $className, $reflectionFunction); } $stubFile = self::DIRECTORY . '/' . $this->map->functions[$lowerName]; $nodes = $this->fileNodesFetcher->fetchNodes($stubFile); $functions = $nodes->getFunctionNodes(); if (!array_key_exists($lowerName, $functions)) { throw new ShouldNotHappenException(sprintf('Function %s stub not found in %s.', $functionName, $stubFile)); } foreach ($functions[$lowerName] as $functionNode) { if (!$this->isForCurrentVersion($functionNode->getNode()->getAttrGroups())) { continue; } $signature = $this->getSignature($functionNode->getNode(), null, $stubFile); if ($this->functionSignatureMapProvider->hasFunctionSignature($functionName)) { $functionMapSignatures = $this->functionSignatureMapProvider->getFunctionSignatures($functionName, $className, $reflectionFunction); return $this->getMergedSignatures($signature, $functionMapSignatures); } return ['positional' => [$signature], 'named' => null]; } throw new ShouldNotHappenException(sprintf('Function %s stub not found in %s.', $functionName, $stubFile)); } /** * @param array{positional: array, named: ?array} $functionMapSignatures * @return array{positional: array, named: ?array} */ private function getMergedSignatures(\PHPStan\Reflection\SignatureMap\FunctionSignature $nativeSignature, array $functionMapSignatures) : array { if (count($functionMapSignatures['positional']) === 1) { return ['positional' => [$this->mergeSignatures($nativeSignature, $functionMapSignatures['positional'][0])], 'named' => null]; } if (count($functionMapSignatures['positional']) === 0) { return ['positional' => [], 'named' => null]; } $nativeParams = $nativeSignature->getParameters(); $namedArgumentsVariants = []; $allParamNamesMatchNative = \true; foreach ($functionMapSignatures['positional'] as $functionMapSignature) { $isPrevParamVariadic = \false; $hasMiddleVariadicParam = \false; // avoid weird functions like array_diff_uassoc foreach ($functionMapSignature->getParameters() as $i => $functionParam) { $nativeParam = $nativeParams[$i] ?? null; $allParamNamesMatchNative = $allParamNamesMatchNative && $nativeParam !== null && $functionParam->getName() === $nativeParam->getName(); $hasMiddleVariadicParam = $hasMiddleVariadicParam || $isPrevParamVariadic; $isPrevParamVariadic = $functionParam->isVariadic() || ($nativeParam !== null ? $nativeParam->isVariadic() : \false); } if ($hasMiddleVariadicParam) { continue; } $parameters = []; foreach ($functionMapSignature->getParameters() as $i => $functionParam) { if (!array_key_exists($i, $nativeParams)) { continue 2; } // it seems that variadic parameters cannot be named in native functions/methods. $nativeParam = $nativeParams[$i]; if ($nativeParam->isVariadic()) { break; } $parameters[] = new \PHPStan\Reflection\SignatureMap\ParameterSignature($nativeParam->getName(), $functionParam->isOptional(), $functionParam->getType(), $functionParam->getNativeType(), $functionParam->passedByReference(), $functionParam->isVariadic(), $functionParam->getDefaultValue(), $functionParam->getOutType()); } $namedArgumentsVariants[] = new \PHPStan\Reflection\SignatureMap\FunctionSignature($parameters, $functionMapSignature->getReturnType(), $functionMapSignature->getNativeReturnType(), $functionMapSignature->isVariadic()); } if ($allParamNamesMatchNative || count($namedArgumentsVariants) === 0) { $namedArgumentsVariants = null; } return ['positional' => $functionMapSignatures['positional'], 'named' => $namedArgumentsVariants]; } private function mergeSignatures(\PHPStan\Reflection\SignatureMap\FunctionSignature $nativeSignature, \PHPStan\Reflection\SignatureMap\FunctionSignature $functionMapSignature) : \PHPStan\Reflection\SignatureMap\FunctionSignature { $parameters = []; foreach ($nativeSignature->getParameters() as $i => $nativeParameter) { if (!array_key_exists($i, $functionMapSignature->getParameters())) { $parameters[] = $nativeParameter; continue; } $functionMapParameter = $functionMapSignature->getParameters()[$i]; $nativeParameterType = $nativeParameter->getNativeType(); $parameters[] = new \PHPStan\Reflection\SignatureMap\ParameterSignature($nativeParameter->getName(), $nativeParameter->isOptional(), TypehintHelper::decideType($nativeParameterType, TypehintHelper::decideType($nativeParameter->getType(), $functionMapParameter->getType())), $nativeParameterType, $nativeParameter->passedByReference()->yes() ? $functionMapParameter->passedByReference() : $nativeParameter->passedByReference(), $nativeParameter->isVariadic(), $nativeParameter->getDefaultValue(), $nativeParameter->getOutType()); } $nativeReturnType = $nativeSignature->getNativeReturnType(); if ($nativeReturnType instanceof MixedType && !$nativeReturnType->isExplicitMixed()) { $returnType = $functionMapSignature->getReturnType(); } else { $returnType = TypehintHelper::decideType($nativeReturnType, TypehintHelper::decideType($nativeSignature->getReturnType(), $functionMapSignature->getReturnType())); } return new \PHPStan\Reflection\SignatureMap\FunctionSignature($parameters, $returnType, $nativeReturnType, $nativeSignature->isVariadic()); } public function hasMethodMetadata(string $className, string $methodName) : bool { return $this->functionSignatureMapProvider->hasMethodMetadata($className, $methodName); } public function hasFunctionMetadata(string $name) : bool { return $this->functionSignatureMapProvider->hasFunctionMetadata($name); } /** * @return array{hasSideEffects: bool} */ public function getMethodMetadata(string $className, string $methodName) : array { return $this->functionSignatureMapProvider->getMethodMetadata($className, $methodName); } /** * @return array{hasSideEffects: bool} */ public function getFunctionMetadata(string $functionName) : array { return $this->functionSignatureMapProvider->getFunctionMetadata($functionName); } /** * @param ClassMethod|Function_ $function */ private function getSignature($function, ?string $className, string $stubFile) : \PHPStan\Reflection\SignatureMap\FunctionSignature { $phpDocParameterTypes = null; $phpDocReturnType = null; if ($function->getDocComment() !== null) { if ($function instanceof ClassMethod) { $functionName = $function->name->toString(); } elseif ($function->namespacedName !== null) { $functionName = $function->namespacedName->toString(); } else { throw new ShouldNotHappenException(); } $phpDoc = $this->fileTypeMapper->getResolvedPhpDoc($stubFile, $className, null, $functionName, $function->getDocComment()->getText()); $phpDocParameterTypes = array_map(static function (ParamTag $param) : Type { return $param->getType(); }, $phpDoc->getParamTags()); if ($phpDoc->getReturnTag() !== null) { $phpDocReturnType = $phpDoc->getReturnTag()->getType(); } } $classReflection = null; if ($className !== null) { $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); $classReflection = $reflectionProvider->getClass($className); } $parameters = []; $variadic = \false; foreach ($function->getParams() as $param) { $name = $param->var; if (!$name instanceof Variable || !is_string($name->name)) { throw new ShouldNotHappenException(); } $parameterType = ParserNodeTypeToPHPStanType::resolve($param->type, $classReflection); $parameters[] = new \PHPStan\Reflection\SignatureMap\ParameterSignature($name->name, $param->default !== null || $param->variadic, TypehintHelper::decideType($parameterType, $phpDocParameterTypes[$name->name] ?? null), $parameterType, $param->byRef ? PassedByReference::createCreatesNewVariable() : PassedByReference::createNo(), $param->variadic, $param->default !== null ? $this->initializerExprTypeResolver->getType($param->default, InitializerExprContext::fromStubParameter($className, $stubFile, $function)) : null, null); $variadic = $variadic || $param->variadic; } $returnType = ParserNodeTypeToPHPStanType::resolve($function->getReturnType(), $classReflection); return new \PHPStan\Reflection\SignatureMap\FunctionSignature($parameters, TypehintHelper::decideType($returnType, $phpDocReturnType ?? null), $returnType, $variadic); } public function hasClassConstantMetadata(string $className, string $constantName) : bool { $lowerClassName = strtolower($className); if (!array_key_exists($lowerClassName, $this->map->classes)) { return \false; } return $this->findConstantType($className, $constantName) !== null; } public function getClassConstantMetadata(string $className, string $constantName) : array { $lowerClassName = strtolower($className); if (!array_key_exists($lowerClassName, $this->map->classes)) { throw new ShouldNotHappenException(); } $type = $this->findConstantType($className, $constantName); if ($type === null) { throw new ShouldNotHappenException(); } return ['nativeType' => $type]; } private function findConstantType(string $className, string $constantName) : ?Type { $lowerClassName = strtolower($className); $lowerConstantName = strtolower($constantName); if (isset($this->constantTypes[$lowerClassName][$lowerConstantName])) { return $this->constantTypes[$lowerClassName][$lowerConstantName]; } $stubFile = self::DIRECTORY . '/' . $this->map->classes[$lowerClassName]; $nodes = $this->fileNodesFetcher->fetchNodes($stubFile); $classes = $nodes->getClassNodes(); if (count($classes) !== 1) { throw new ShouldNotHappenException(sprintf('Class %s stub not found in %s.', $className, $stubFile)); } $class = $classes[$lowerClassName]; if (count($class) !== 1) { throw new ShouldNotHappenException(sprintf('Class %s stub not found in %s.', $className, $stubFile)); } foreach ($class[0]->getNode()->stmts as $stmt) { if (!$stmt instanceof ClassConst) { continue; } foreach ($stmt->consts as $const) { if ($const->name->toString() !== $constantName) { continue; } if (!$this->isForCurrentVersion($stmt->attrGroups)) { continue; } if ($stmt->type === null) { return null; } return $this->constantTypes[$lowerClassName][$lowerConstantName] = ParserNodeTypeToPHPStanType::resolve($stmt->type, null); } } return null; } } */ private $parameters; /** * @var Type */ private $returnType; /** * @var Type */ private $nativeReturnType; /** * @var bool */ private $variadic; /** * @param array $parameters */ public function __construct(array $parameters, Type $returnType, Type $nativeReturnType, bool $variadic) { $this->parameters = $parameters; $this->returnType = $returnType; $this->nativeReturnType = $nativeReturnType; $this->variadic = $variadic; } /** * @return array */ public function getParameters() : array { return $this->parameters; } public function getReturnType() : Type { return $this->returnType; } public function getNativeReturnType() : Type { return $this->nativeReturnType; } public function isVariadic() : bool { return $this->variadic; } } declaringEnum = $declaringEnum; $this->name = $name; $this->backingValueType = $backingValueType; } public function getDeclaringEnum() : \PHPStan\Reflection\ClassReflection { return $this->declaringEnum; } public function getName() : string { return $this->name; } public function getBackingValueType() : ?Type { return $this->backingValueType; } } methodName = $methodName; $this->methods = $methods; } public function getDeclaringClass() : ClassReflection { return $this->methods[0]->getDeclaringClass(); } public function isStatic() : bool { foreach ($this->methods as $method) { if ($method->isStatic()) { return \true; } } return \false; } public function isPrivate() : bool { foreach ($this->methods as $method) { if (!$method->isPrivate()) { return \false; } } return \true; } public function isPublic() : bool { foreach ($this->methods as $method) { if ($method->isPublic()) { return \true; } } return \false; } public function getName() : string { return $this->methodName; } public function getPrototype() : ClassMemberReflection { return $this; } public function getVariants() : array { $returnType = TypeCombinator::intersect(...array_map(static function (MethodReflection $method) : Type { return TypeCombinator::intersect(...array_map(static function (ParametersAcceptor $acceptor) : Type { return $acceptor->getReturnType(); }, $method->getVariants())); }, $this->methods)); $phpDocReturnType = TypeCombinator::intersect(...array_map(static function (MethodReflection $method) : Type { return TypeCombinator::intersect(...array_map(static function (ParametersAcceptor $acceptor) : Type { return $acceptor->getPhpDocReturnType(); }, $method->getVariants())); }, $this->methods)); $nativeReturnType = TypeCombinator::intersect(...array_map(static function (MethodReflection $method) : Type { return TypeCombinator::intersect(...array_map(static function (ParametersAcceptor $acceptor) : Type { return $acceptor->getNativeReturnType(); }, $method->getVariants())); }, $this->methods)); return array_map(static function (ParametersAcceptorWithPhpDocs $acceptor) use($returnType, $phpDocReturnType, $nativeReturnType) : ParametersAcceptorWithPhpDocs { return new FunctionVariantWithPhpDocs($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $acceptor->getParameters(), $acceptor->isVariadic(), $returnType, $phpDocReturnType, $nativeReturnType, $acceptor->getCallSiteVarianceMap()); }, $this->methods[0]->getVariants()); } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { $variants = $this->getVariants(); if (count($variants) !== 1) { throw new ShouldNotHappenException(); } return $variants[0]; } public function getNamedArgumentsVariants() : ?array { return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static function (MethodReflection $method) : TrinaryLogic { return $method->isDeprecated(); }); } public function getDeprecatedDescription() : ?string { $descriptions = []; foreach ($this->methods as $method) { if (!$method->isDeprecated()->yes()) { continue; } $description = $method->getDeprecatedDescription(); if ($description === null) { continue; } $descriptions[] = $description; } if (count($descriptions) === 0) { return null; } return implode(' ', $descriptions); } public function isFinal() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static function (MethodReflection $method) : TrinaryLogic { return $method->isFinal(); }); } public function isFinalByKeyword() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static function (ExtendedMethodReflection $method) : TrinaryLogic { return $method->isFinalByKeyword(); }); } public function isInternal() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static function (MethodReflection $method) : TrinaryLogic { return $method->isInternal(); }); } public function getThrowType() : ?Type { $types = []; foreach ($this->methods as $method) { $type = $method->getThrowType(); if ($type === null) { continue; } $types[] = $type; } if (count($types) === 0) { return null; } return TypeCombinator::intersect(...$types); } public function hasSideEffects() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static function (MethodReflection $method) : TrinaryLogic { return $method->hasSideEffects(); }); } public function isPure() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static function (ExtendedMethodReflection $method) : TrinaryLogic { return $method->isPure(); }); } public function getDocComment() : ?string { return null; } public function getAsserts() : Assertions { $assertions = Assertions::createEmpty(); foreach ($this->methods as $method) { $assertions = $assertions->intersectWith($method->getAsserts()); } return $assertions; } public function acceptsNamedArguments() : bool { $accepts = \true; foreach ($this->methods as $method) { $accepts = $accepts && $method->acceptsNamedArguments(); } return $accepts; } public function getSelfOutType() : ?Type { return null; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static function (ExtendedMethodReflection $method) : TrinaryLogic { return $method->returnsByReference(); }); } public function isAbstract() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->methods, static function (ExtendedMethodReflection $method) : TrinaryLogic { return is_bool($method->isAbstract()) ? TrinaryLogic::createFromBoolean($method->isAbstract()) : $method->isAbstract(); }); } } methodName = $methodName; $this->methodPrototypes = $methodPrototypes; } public function doNotResolveTemplateTypeMapToBounds() : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->methodName, array_map(static function (\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype) : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { return $prototype->doNotResolveTemplateTypeMapToBounds(); }, $this->methodPrototypes)); } public function getNakedMethod() : ExtendedMethodReflection { return $this->getTransformedMethod(); } public function getTransformedMethod() : ExtendedMethodReflection { if ($this->transformedMethod !== null) { return $this->transformedMethod; } $methods = array_map(static function (\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype) : MethodReflection { return $prototype->getTransformedMethod(); }, $this->methodPrototypes); return $this->transformedMethod = new \PHPStan\Reflection\Type\UnionTypeMethodReflection($this->methodName, $methods); } public function withCalledOnType(Type $type) : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { return new self($this->methodName, array_map(static function (\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype) use($type) : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { return $prototype->withCalledOnType($type); }, $this->methodPrototypes)); } } properties = $properties; } public function getDeclaringClass() : ClassReflection { return $this->properties[0]->getDeclaringClass(); } public function isStatic() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isStatic(); }); } public function isPrivate() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isPrivate(); }); } public function isPublic() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isPublic(); }); } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->properties, static function (PropertyReflection $propertyReflection) : TrinaryLogic { return $propertyReflection->isDeprecated(); }); } public function getDeprecatedDescription() : ?string { $descriptions = []; foreach ($this->properties as $property) { if (!$property->isDeprecated()->yes()) { continue; } $description = $property->getDeprecatedDescription(); if ($description === null) { continue; } $descriptions[] = $description; } if (count($descriptions) === 0) { return null; } return implode(' ', $descriptions); } public function isInternal() : TrinaryLogic { return TrinaryLogic::lazyMaxMin($this->properties, static function (PropertyReflection $propertyReflection) : TrinaryLogic { return $propertyReflection->isInternal(); }); } public function getDocComment() : ?string { return null; } public function getReadableType() : Type { return TypeCombinator::intersect(...array_map(static function (PropertyReflection $property) : Type { return $property->getReadableType(); }, $this->properties)); } public function getWritableType() : Type { return TypeCombinator::intersect(...array_map(static function (PropertyReflection $property) : Type { return $property->getWritableType(); }, $this->properties)); } public function canChangeTypeAfterAssignment() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->canChangeTypeAfterAssignment(); }); } public function isReadable() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isReadable(); }); } public function isWritable() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isWritable(); }); } /** * @param callable(PropertyReflection): bool $cb */ private function computeResult(callable $cb) : bool { $result = \false; foreach ($this->properties as $property) { $result = $result || $cb($property); } return $result; } } properties = $properties; } public function getDeclaringClass() : ClassReflection { return $this->properties[0]->getDeclaringClass(); } public function isStatic() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isStatic(); }); } public function isPrivate() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isPrivate(); }); } public function isPublic() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isPublic(); }); } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->properties, static function (PropertyReflection $propertyReflection) : TrinaryLogic { return $propertyReflection->isDeprecated(); }); } public function getDeprecatedDescription() : ?string { $descriptions = []; foreach ($this->properties as $property) { if (!$property->isDeprecated()->yes()) { continue; } $description = $property->getDeprecatedDescription(); if ($description === null) { continue; } $descriptions[] = $description; } if (count($descriptions) === 0) { return null; } return implode(' ', $descriptions); } public function isInternal() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->properties, static function (PropertyReflection $propertyReflection) : TrinaryLogic { return $propertyReflection->isInternal(); }); } public function getDocComment() : ?string { return null; } public function getReadableType() : Type { return TypeCombinator::union(...array_map(static function (PropertyReflection $property) : Type { return $property->getReadableType(); }, $this->properties)); } public function getWritableType() : Type { return TypeCombinator::union(...array_map(static function (PropertyReflection $property) : Type { return $property->getWritableType(); }, $this->properties)); } public function canChangeTypeAfterAssignment() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->canChangeTypeAfterAssignment(); }); } public function isReadable() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isReadable(); }); } public function isWritable() : bool { return $this->computeResult(static function (PropertyReflection $property) { return $property->isWritable(); }); } /** * @param callable(PropertyReflection): bool $cb */ private function computeResult(callable $cb) : bool { $result = \true; foreach ($this->properties as $property) { $result = $result && $cb($property); } return $result; } } methodName = $methodName; $this->methods = $methods; } public function getDeclaringClass() : ClassReflection { return $this->methods[0]->getDeclaringClass(); } public function isStatic() : bool { foreach ($this->methods as $method) { if (!$method->isStatic()) { return \false; } } return \true; } public function isPrivate() : bool { foreach ($this->methods as $method) { if ($method->isPrivate()) { return \true; } } return \false; } public function isPublic() : bool { foreach ($this->methods as $method) { if (!$method->isPublic()) { return \false; } } return \true; } public function getName() : string { return $this->methodName; } public function getPrototype() : ClassMemberReflection { return $this; } public function getVariants() : array { $variants = array_merge(...array_map(static function (MethodReflection $method) { return $method->getVariants(); }, $this->methods)); return [ParametersAcceptorSelector::combineAcceptors($variants)]; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static function (MethodReflection $method) : TrinaryLogic { return $method->isDeprecated(); }); } public function getDeprecatedDescription() : ?string { $descriptions = []; foreach ($this->methods as $method) { if (!$method->isDeprecated()->yes()) { continue; } $description = $method->getDeprecatedDescription(); if ($description === null) { continue; } $descriptions[] = $description; } if (count($descriptions) === 0) { return null; } return implode(' ', $descriptions); } public function isFinal() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static function (MethodReflection $method) : TrinaryLogic { return $method->isFinal(); }); } public function isFinalByKeyword() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static function (ExtendedMethodReflection $method) : TrinaryLogic { return $method->isFinalByKeyword(); }); } public function isInternal() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static function (MethodReflection $method) : TrinaryLogic { return $method->isInternal(); }); } public function getThrowType() : ?Type { $types = []; foreach ($this->methods as $method) { $type = $method->getThrowType(); if ($type === null) { continue; } $types[] = $type; } if (count($types) === 0) { return null; } return TypeCombinator::union(...$types); } public function hasSideEffects() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static function (MethodReflection $method) : TrinaryLogic { return $method->hasSideEffects(); }); } public function isPure() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static function (ExtendedMethodReflection $method) : TrinaryLogic { return $method->isPure(); }); } public function getDocComment() : ?string { return null; } public function getAsserts() : Assertions { return Assertions::createEmpty(); } public function acceptsNamedArguments() : bool { $accepts = \true; foreach ($this->methods as $method) { $accepts = $accepts && $method->acceptsNamedArguments(); } return $accepts; } public function getSelfOutType() : ?Type { return null; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static function (ExtendedMethodReflection $method) : TrinaryLogic { return $method->returnsByReference(); }); } public function isAbstract() : TrinaryLogic { return TrinaryLogic::lazyExtremeIdentity($this->methods, static function (ExtendedMethodReflection $method) : TrinaryLogic { return is_bool($method->isAbstract()) ? TrinaryLogic::createFromBoolean($method->isAbstract()) : $method->isAbstract(); }); } } methodReflection = $methodReflection; $this->resolvedDeclaringClass = $resolvedDeclaringClass; $this->resolveTemplateTypeMapToBounds = $resolveTemplateTypeMapToBounds; $this->calledOnType = $calledOnType; } public function doNotResolveTemplateTypeMapToBounds() : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->methodReflection, $this->resolvedDeclaringClass, \false, $this->calledOnType); } public function getNakedMethod() : ExtendedMethodReflection { return $this->methodReflection; } public function getTransformedMethod() : ExtendedMethodReflection { if ($this->transformedMethod !== null) { return $this->transformedMethod; } $templateTypeMap = $this->resolvedDeclaringClass->getActiveTemplateTypeMap(); $callSiteVarianceMap = $this->resolvedDeclaringClass->getCallSiteVarianceMap(); return $this->transformedMethod = new ResolvedMethodReflection($this->transformMethodWithStaticType($this->resolvedDeclaringClass, $this->methodReflection), $this->resolveTemplateTypeMapToBounds ? $templateTypeMap->resolveToBounds() : $templateTypeMap, $callSiteVarianceMap); } public function withCalledOnType(Type $type) : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { return new self($this->methodReflection, $this->resolvedDeclaringClass, $this->resolveTemplateTypeMapToBounds, $type); } private function transformMethodWithStaticType(ClassReflection $declaringClass, ExtendedMethodReflection $method) : ExtendedMethodReflection { $variantFn = function (ParametersAcceptorWithPhpDocs $acceptor) : ParametersAcceptorWithPhpDocs { return new FunctionVariantWithPhpDocs($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map(function (ParameterReflectionWithPhpDocs $parameter) : ParameterReflectionWithPhpDocs { return new DummyParameterWithPhpDocs($parameter->getName(), $this->transformStaticType($parameter->getType()), $parameter->isOptional(), $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), $parameter->getNativeType(), $this->transformStaticType($parameter->getPhpDocType()), $parameter->getOutType() !== null ? $this->transformStaticType($parameter->getOutType()) : null, $parameter->isImmediatelyInvokedCallable(), $parameter->getClosureThisType() !== null ? $this->transformStaticType($parameter->getClosureThisType()) : null); }, $acceptor->getParameters()), $acceptor->isVariadic(), $this->transformStaticType($acceptor->getReturnType()), $this->transformStaticType($acceptor->getPhpDocReturnType()), $this->transformStaticType($acceptor->getNativeReturnType()), $acceptor->getCallSiteVarianceMap()); }; $variants = array_map($variantFn, $method->getVariants()); $namedArgumentsVariants = $method->getNamedArgumentsVariants(); $namedArgumentsVariants = $namedArgumentsVariants !== null ? array_map($variantFn, $namedArgumentsVariants) : null; return new ChangedTypeMethodReflection($declaringClass, $method, $variants, $namedArgumentsVariants); } private function transformStaticType(Type $type) : Type { return TypeTraverser::map($type, function (Type $type, callable $traverse) : Type { if ($type instanceof GenericStaticType) { $calledOnTypeReflections = $this->calledOnType->getObjectClassReflections(); if (count($calledOnTypeReflections) === 1) { $calledOnTypeReflection = $calledOnTypeReflections[0]; return $traverse($type->changeBaseClass($calledOnTypeReflection)->getStaticObjectType()); } return $this->calledOnType; } if ($type instanceof StaticType) { return $this->calledOnType; } return $traverse($type); }); } } propertyReflection = $propertyReflection; $this->resolvedDeclaringClass = $resolvedDeclaringClass; $this->resolveTemplateTypeMapToBounds = $resolveTemplateTypeMapToBounds; $this->fetchedOnType = $fetchedOnType; } public function doNotResolveTemplateTypeMapToBounds() : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->propertyReflection, $this->resolvedDeclaringClass, \false, $this->fetchedOnType); } public function getNakedProperty() : ExtendedPropertyReflection { return $this->propertyReflection; } public function getTransformedProperty() : ExtendedPropertyReflection { if ($this->transformedProperty !== null) { return $this->transformedProperty; } $templateTypeMap = $this->resolvedDeclaringClass->getActiveTemplateTypeMap(); $callSiteVarianceMap = $this->resolvedDeclaringClass->getCallSiteVarianceMap(); return $this->transformedProperty = new ResolvedPropertyReflection($this->transformPropertyWithStaticType($this->resolvedDeclaringClass, $this->propertyReflection), $this->resolveTemplateTypeMapToBounds ? $templateTypeMap->resolveToBounds() : $templateTypeMap, $callSiteVarianceMap); } public function withFechedOnType(Type $type) : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { return new self($this->propertyReflection, $this->resolvedDeclaringClass, $this->resolveTemplateTypeMapToBounds, $type); } private function transformPropertyWithStaticType(ClassReflection $declaringClass, ExtendedPropertyReflection $property) : ExtendedPropertyReflection { $readableType = $this->transformStaticType($property->getReadableType()); $writableType = $this->transformStaticType($property->getWritableType()); return new ChangedTypePropertyReflection($declaringClass, $property, $readableType, $writableType); } private function transformStaticType(Type $type) : Type { return TypeTraverser::map($type, function (Type $type, callable $traverse) : Type { if ($type instanceof StaticType) { return $this->fetchedOnType; } return $traverse($type); }); } } propertyReflection = $propertyReflection; $this->resolvedDeclaringClass = $resolvedDeclaringClass; $this->resolveTemplateTypeMapToBounds = $resolveTemplateTypeMapToBounds; $this->transformStaticTypeCallback = $transformStaticTypeCallback; } public function doNotResolveTemplateTypeMapToBounds() : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->propertyReflection, $this->resolvedDeclaringClass, \false, $this->transformStaticTypeCallback); } public function getNakedProperty() : ExtendedPropertyReflection { return $this->propertyReflection; } public function getTransformedProperty() : ExtendedPropertyReflection { if ($this->transformedProperty !== null) { return $this->transformedProperty; } $templateTypeMap = $this->resolvedDeclaringClass->getActiveTemplateTypeMap(); $callSiteVarianceMap = $this->resolvedDeclaringClass->getCallSiteVarianceMap(); return $this->transformedProperty = new ResolvedPropertyReflection($this->transformPropertyWithStaticType($this->resolvedDeclaringClass, $this->propertyReflection), $this->resolveTemplateTypeMapToBounds ? $templateTypeMap->resolveToBounds() : $templateTypeMap, $callSiteVarianceMap); } public function withFechedOnType(Type $type) : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { return new \PHPStan\Reflection\Type\CalledOnTypeUnresolvedPropertyPrototypeReflection($this->propertyReflection, $this->resolvedDeclaringClass, $this->resolveTemplateTypeMapToBounds, $type); } private function transformPropertyWithStaticType(ClassReflection $declaringClass, ExtendedPropertyReflection $property) : ExtendedPropertyReflection { $readableType = $this->transformStaticType($property->getReadableType()); $writableType = $this->transformStaticType($property->getWritableType()); return new ChangedTypePropertyReflection($declaringClass, $property, $readableType, $writableType); } private function transformStaticType(Type $type) : Type { $callback = $this->transformStaticTypeCallback; return $callback($type); } } methodName = $methodName; $this->methodPrototypes = $methodPrototypes; } public function doNotResolveTemplateTypeMapToBounds() : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->methodName, array_map(static function (\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype) : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { return $prototype->doNotResolveTemplateTypeMapToBounds(); }, $this->methodPrototypes)); } public function getNakedMethod() : ExtendedMethodReflection { return $this->getTransformedMethod(); } public function getTransformedMethod() : ExtendedMethodReflection { if ($this->transformedMethod !== null) { return $this->transformedMethod; } $methods = array_map(static function (\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype) : MethodReflection { return $prototype->getTransformedMethod(); }, $this->methodPrototypes); return $this->transformedMethod = new \PHPStan\Reflection\Type\IntersectionTypeMethodReflection($this->methodName, $methods); } public function withCalledOnType(Type $type) : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { return new self($this->methodName, array_map(static function (\PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection $prototype) use($type) : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { return $prototype->withCalledOnType($type); }, $this->methodPrototypes)); } } propertyName = $propertyName; $this->propertyPrototypes = $propertyPrototypes; } public function doNotResolveTemplateTypeMapToBounds() : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->propertyName, array_map(static function (\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype) : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { return $prototype->doNotResolveTemplateTypeMapToBounds(); }, $this->propertyPrototypes)); } public function getNakedProperty() : ExtendedPropertyReflection { return $this->getTransformedProperty(); } public function getTransformedProperty() : ExtendedPropertyReflection { if ($this->transformedProperty !== null) { return $this->transformedProperty; } $properties = array_map(static function (\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype) : PropertyReflection { return $prototype->getTransformedProperty(); }, $this->propertyPrototypes); return $this->transformedProperty = new \PHPStan\Reflection\Type\IntersectionTypePropertyReflection($properties); } public function withFechedOnType(Type $type) : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { return new self($this->propertyName, array_map(static function (\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype) use($type) : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { return $prototype->withFechedOnType($type); }, $this->propertyPrototypes)); } } propertyName = $propertyName; $this->propertyPrototypes = $propertyPrototypes; } public function doNotResolveTemplateTypeMapToBounds() : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->propertyName, array_map(static function (\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype) : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { return $prototype->doNotResolveTemplateTypeMapToBounds(); }, $this->propertyPrototypes)); } public function getNakedProperty() : ExtendedPropertyReflection { return $this->getTransformedProperty(); } public function getTransformedProperty() : ExtendedPropertyReflection { if ($this->transformedProperty !== null) { return $this->transformedProperty; } $methods = array_map(static function (\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype) : PropertyReflection { return $prototype->getTransformedProperty(); }, $this->propertyPrototypes); return $this->transformedProperty = new \PHPStan\Reflection\Type\UnionTypePropertyReflection($methods); } public function withFechedOnType(Type $type) : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { return new self($this->propertyName, array_map(static function (\PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection $prototype) use($type) : \PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection { return $prototype->withFechedOnType($type); }, $this->propertyPrototypes)); } } methodReflection = $methodReflection; $this->resolvedDeclaringClass = $resolvedDeclaringClass; $this->resolveTemplateTypeMapToBounds = $resolveTemplateTypeMapToBounds; $this->transformStaticTypeCallback = $transformStaticTypeCallback; } public function doNotResolveTemplateTypeMapToBounds() : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) { return $this->cachedDoNotResolveTemplateTypeMapToBounds; } return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->methodReflection, $this->resolvedDeclaringClass, \false, $this->transformStaticTypeCallback); } public function getNakedMethod() : ExtendedMethodReflection { return $this->methodReflection; } public function getTransformedMethod() : ExtendedMethodReflection { if ($this->transformedMethod !== null) { return $this->transformedMethod; } $templateTypeMap = $this->resolvedDeclaringClass->getActiveTemplateTypeMap(); $callSiteVarianceMap = $this->resolvedDeclaringClass->getCallSiteVarianceMap(); return $this->transformedMethod = new ResolvedMethodReflection($this->transformMethodWithStaticType($this->resolvedDeclaringClass, $this->methodReflection), $this->resolveTemplateTypeMapToBounds ? $templateTypeMap->resolveToBounds() : $templateTypeMap, $callSiteVarianceMap); } public function withCalledOnType(Type $type) : \PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection { return new \PHPStan\Reflection\Type\CalledOnTypeUnresolvedMethodPrototypeReflection($this->methodReflection, $this->resolvedDeclaringClass, $this->resolveTemplateTypeMapToBounds, $type); } private function transformMethodWithStaticType(ClassReflection $declaringClass, ExtendedMethodReflection $method) : ExtendedMethodReflection { $variantFn = function (ParametersAcceptorWithPhpDocs $acceptor) : ParametersAcceptorWithPhpDocs { return new FunctionVariantWithPhpDocs($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map(function (ParameterReflectionWithPhpDocs $parameter) : ParameterReflectionWithPhpDocs { return new DummyParameterWithPhpDocs($parameter->getName(), $this->transformStaticType($parameter->getType()), $parameter->isOptional(), $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), $parameter->getNativeType(), $this->transformStaticType($parameter->getPhpDocType()), $parameter->getOutType() !== null ? $this->transformStaticType($parameter->getOutType()) : null, $parameter->isImmediatelyInvokedCallable(), $parameter->getClosureThisType() !== null ? $this->transformStaticType($parameter->getClosureThisType()) : null); }, $acceptor->getParameters()), $acceptor->isVariadic(), $this->transformStaticType($acceptor->getReturnType()), $this->transformStaticType($acceptor->getPhpDocReturnType()), $this->transformStaticType($acceptor->getNativeReturnType()), $acceptor->getCallSiteVarianceMap()); }; $variants = array_map($variantFn, $method->getVariants()); $namedArgumentVariants = $method->getNamedArgumentsVariants(); $namedArgumentVariants = $namedArgumentVariants !== null ? array_map($variantFn, $namedArgumentVariants) : null; return new ChangedTypeMethodReflection($declaringClass, $method, $variants, $namedArgumentVariants); } private function transformStaticType(Type $type) : Type { $callback = $this->transformStaticTypeCallback; return $callback($type); } } */ public function getParameters() : array; public function getPhpDocReturnType() : Type; public function getNativeReturnType() : Type; public function getCallSiteVarianceMap() : TemplateTypeVarianceMap; } $parameters * @param SimpleThrowPoint[] $throwPoints * @param SimpleImpurePoint[] $impurePoints * @param InvalidateExprNode[] $invalidateExpressions * @param string[] $usedVariables */ public function __construct(TemplateTypeMap $templateTypeMap, ?TemplateTypeMap $resolvedTemplateTypeMap, array $parameters, bool $isVariadic, Type $returnType, Type $phpDocReturnType, Type $nativeReturnType, ?TemplateTypeVarianceMap $callSiteVarianceMap, array $throwPoints, TrinaryLogic $isPure, array $impurePoints, array $invalidateExpressions, array $usedVariables, bool $acceptsNamedArguments) { $this->throwPoints = $throwPoints; $this->isPure = $isPure; $this->impurePoints = $impurePoints; $this->invalidateExpressions = $invalidateExpressions; $this->usedVariables = $usedVariables; $this->acceptsNamedArguments = $acceptsNamedArguments; parent::__construct($templateTypeMap, $resolvedTemplateTypeMap, $parameters, $isVariadic, $returnType, $phpDocReturnType, $nativeReturnType, $callSiteVarianceMap); } public function getThrowPoints() : array { return $this->throwPoints; } public function isPure() : TrinaryLogic { return $this->isPure; } public function getImpurePoints() : array { return $this->impurePoints; } public function getInvalidateExpressions() : array { return $this->invalidateExpressions; } public function getUsedVariables() : array { return $this->usedVariables; } public function acceptsNamedArguments() : bool { return $this->acceptsNamedArguments; } } getClass(stdClass::class); } public function isStatic() : bool { return \false; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getReadableType() : Type { return new MixedType(); } public function getWritableType() : Type { return new MixedType(); } public function canChangeTypeAfterAssignment() : bool { return \true; } public function isReadable() : bool { return \true; } public function isWritable() : bool { return \true; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getDeprecatedDescription() : ?string { return null; } public function isInternal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getDocComment() : ?string { return null; } } declaringClass = $declaringClass; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return \false; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getName() : string { return '__construct'; } public function getPrototype() : ClassMemberReflection { return $this; } public function getVariants() : array { return [new FunctionVariantWithPhpDocs(TemplateTypeMap::createEmpty(), null, [], \false, new VoidType(), new MixedType(), new MixedType(), null)]; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getDeprecatedDescription() : ?string { return null; } public function isFinal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getThrowType() : ?Type { return null; } public function hasSideEffects() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDocComment() : ?string { return null; } public function getAsserts() : Assertions { return Assertions::createEmpty(); } public function acceptsNamedArguments() : bool { return $this->declaringClass->acceptsNamedArguments(); } public function getSelfOutType() : ?Type { return null; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinalByKeyword() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isAbstract() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isPure() : TrinaryLogic { return TrinaryLogic::createYes(); } } name = $name; } public function getDeclaringClass() : ClassReflection { $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); return $reflectionProvider->getClass(stdClass::class); } public function isStatic() : bool { return \false; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getName() : string { return $this->name; } public function getPrototype() : ClassMemberReflection { return $this; } public function getVariants() : array { return [new TrivialParametersAcceptor()]; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getDeprecatedDescription() : ?string { return null; } public function isFinal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isFinalByKeyword() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getThrowType() : ?Type { return null; } public function hasSideEffects() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getDocComment() : ?string { return null; } public function getAsserts() : Assertions { return Assertions::createEmpty(); } public function acceptsNamedArguments() : bool { return \true; } public function getSelfOutType() : ?Type { return null; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isAbstract() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isPure() : TrinaryLogic { return TrinaryLogic::createMaybe(); } } name = $name; } public function getDeclaringClass() : ClassReflection { $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); return $reflectionProvider->getClass(stdClass::class); } public function getFileName() : ?string { return null; } public function isStatic() : bool { return \true; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getName() : string { return $this->name; } /** * @deprecated * @return mixed */ public function getValue() { // so that Scope::getTypeFromValue() returns mixed return new stdClass(); } public function getValueType() : Type { return new MixedType(); } public function getValueExpr() : Expr { return new TypeExpr(new MixedType()); } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getDeprecatedDescription() : ?string { return null; } public function isInternal() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getDocComment() : ?string { return null; } } declaringClass = $declaringClass; $this->reflection = $reflection; $this->readableType = $readableType; $this->writableType = $writableType; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return $this->reflection->isStatic(); } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } public function getDocComment() : ?string { return $this->reflection->getDocComment(); } public function getReadableType() : Type { return $this->readableType; } public function getWritableType() : Type { return $this->writableType; } public function canChangeTypeAfterAssignment() : bool { return $this->reflection->canChangeTypeAfterAssignment(); } public function isReadable() : bool { return $this->reflection->isReadable(); } public function isWritable() : bool { return $this->reflection->isWritable(); } public function isDeprecated() : TrinaryLogic { return $this->reflection->isDeprecated(); } public function getDeprecatedDescription() : ?string { return $this->reflection->getDeprecatedDescription(); } public function isInternal() : TrinaryLogic { return $this->reflection->isInternal(); } public function getOriginalReflection() : ExtendedPropertyReflection { return $this->reflection; } } declaringClass = $declaringClass; $this->reflection = $reflection; $this->variants = $variants; $this->namedArgumentsVariants = $namedArgumentsVariants; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return $this->reflection->isStatic(); } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } public function getDocComment() : ?string { return $this->reflection->getDocComment(); } public function getName() : string { return $this->reflection->getName(); } public function getPrototype() : ClassMemberReflection { return $this->reflection->getPrototype(); } public function getVariants() : array { return $this->variants; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { $variants = $this->getVariants(); if (count($variants) !== 1) { throw new ShouldNotHappenException(); } return $variants[0]; } public function getNamedArgumentsVariants() : ?array { return $this->namedArgumentsVariants; } public function isDeprecated() : TrinaryLogic { return $this->reflection->isDeprecated(); } public function getDeprecatedDescription() : ?string { return $this->reflection->getDeprecatedDescription(); } public function isFinal() : TrinaryLogic { return $this->reflection->isFinal(); } public function isFinalByKeyword() : TrinaryLogic { return $this->reflection->isFinalByKeyword(); } public function isInternal() : TrinaryLogic { return $this->reflection->isInternal(); } public function getThrowType() : ?Type { return $this->reflection->getThrowType(); } public function hasSideEffects() : TrinaryLogic { return $this->reflection->hasSideEffects(); } public function getAsserts() : Assertions { return $this->reflection->getAsserts(); } public function acceptsNamedArguments() : bool { return $this->reflection->acceptsNamedArguments(); } public function getSelfOutType() : ?Type { return $this->reflection->getSelfOutType(); } public function returnsByReference() : TrinaryLogic { return $this->reflection->returnsByReference(); } public function isAbstract() : TrinaryLogic { $abstract = $this->reflection->isAbstract(); if (is_bool($abstract)) { return TrinaryLogic::createFromBoolean($abstract); } return $abstract; } public function isPure() : TrinaryLogic { return $this->reflection->isPure(); } } reflection = $reflection; $this->templateTypeMap = $templateTypeMap; $this->callSiteVarianceMap = $callSiteVarianceMap; } public function getOriginalReflection() : \PHPStan\Reflection\ExtendedPropertyReflection { return $this->reflection; } public function getDeclaringClass() : \PHPStan\Reflection\ClassReflection { return $this->reflection->getDeclaringClass(); } public function getDeclaringTrait() : ?\PHPStan\Reflection\ClassReflection { if ($this->reflection instanceof PhpPropertyReflection) { return $this->reflection->getDeclaringTrait(); } return null; } public function isStatic() : bool { return $this->reflection->isStatic(); } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } public function getReadableType() : Type { $type = $this->readableType; if ($type !== null) { return $type; } $type = TemplateTypeHelper::resolveTemplateTypes($this->reflection->getReadableType(), $this->templateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createCovariant()); $type = TemplateTypeHelper::resolveTemplateTypes($type, $this->templateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createCovariant()); $this->readableType = $type; return $type; } public function getWritableType() : Type { $type = $this->writableType; if ($type !== null) { return $type; } $type = TemplateTypeHelper::resolveTemplateTypes($this->reflection->getWritableType(), $this->templateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createContravariant()); $type = TemplateTypeHelper::resolveTemplateTypes($type, $this->templateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createContravariant()); $this->writableType = $type; return $type; } public function canChangeTypeAfterAssignment() : bool { return $this->reflection->canChangeTypeAfterAssignment(); } public function isReadable() : bool { return $this->reflection->isReadable(); } public function isWritable() : bool { return $this->reflection->isWritable(); } public function getDocComment() : ?string { return $this->reflection->getDocComment(); } public function isDeprecated() : TrinaryLogic { return $this->reflection->isDeprecated(); } public function getDeprecatedDescription() : ?string { return $this->reflection->getDeprecatedDescription(); } public function isInternal() : TrinaryLogic { return $this->reflection->isInternal(); } } name = $name; $this->valueType = $valueType; $this->fileName = $fileName; $this->isDeprecated = $isDeprecated; $this->deprecatedDescription = $deprecatedDescription; } public function getName() : string { return $this->name; } public function getValueType() : Type { return $this->valueType; } public function getFileName() : ?string { return $this->fileName; } public function isDeprecated() : TrinaryLogic { return $this->isDeprecated; } public function getDeprecatedDescription() : ?string { return $this->deprecatedDescription; } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } } callableName = $callableName; } public function getTemplateTypeMap() : TemplateTypeMap { return TemplateTypeMap::createEmpty(); } public function getResolvedTemplateTypeMap() : TemplateTypeMap { return TemplateTypeMap::createEmpty(); } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return TemplateTypeVarianceMap::createEmpty(); } public function getParameters() : array { return []; } public function isVariadic() : bool { return \true; } public function getReturnType() : Type { return new MixedType(); } public function getPhpDocReturnType() : Type { return new MixedType(); } public function getNativeReturnType() : Type { return new MixedType(); } public function getThrowPoints() : array { return []; } public function isPure() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getImpurePoints() : array { return [new SimpleImpurePoint('functionCall', sprintf('call to a %s', $this->callableName), \false)]; } public function getInvalidateExpressions() : array { return []; } public function getUsedVariables() : array { return []; } public function acceptsNamedArguments() : bool { return \true; } } */ private $parameters; /** * @var bool */ private $isVariadic; /** * @var Type */ private $returnType; /** * @var TemplateTypeVarianceMap */ private $callSiteVarianceMap; /** * @api * @param array $parameters */ public function __construct(TemplateTypeMap $templateTypeMap, ?TemplateTypeMap $resolvedTemplateTypeMap, array $parameters, bool $isVariadic, Type $returnType, ?TemplateTypeVarianceMap $callSiteVarianceMap = null) { $this->templateTypeMap = $templateTypeMap; $this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap; $this->parameters = $parameters; $this->isVariadic = $isVariadic; $this->returnType = $returnType; $this->callSiteVarianceMap = $callSiteVarianceMap ?? TemplateTypeVarianceMap::createEmpty(); } public function getTemplateTypeMap() : TemplateTypeMap { return $this->templateTypeMap; } public function getResolvedTemplateTypeMap() : TemplateTypeMap { return $this->resolvedTemplateTypeMap ?? TemplateTypeMap::createEmpty(); } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return $this->callSiteVarianceMap; } /** * @return array */ public function getParameters() : array { return $this->parameters; } public function isVariadic() : bool { return $this->isVariadic; } public function getReturnType() : Type { return $this->returnType; } } method = $method; } public function getDeclaringClass() : \PHPStan\Reflection\ClassReflection { return $this->method->getDeclaringClass(); } public function isStatic() : bool { return $this->method->isStatic(); } public function isPrivate() : bool { return $this->method->isPrivate(); } public function isPublic() : bool { return $this->method->isPublic(); } public function getDocComment() : ?string { return $this->method->getDocComment(); } public function getName() : string { return $this->method->getName(); } public function getPrototype() : \PHPStan\Reflection\ClassMemberReflection { return $this->method->getPrototype(); } public function getVariants() : array { $variants = []; foreach ($this->method->getVariants() as $variant) { if ($variant instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs) { $variants[] = $variant; continue; } $variants[] = new \PHPStan\Reflection\FunctionVariantWithPhpDocs($variant->getTemplateTypeMap(), $variant->getResolvedTemplateTypeMap(), array_map(static function (\PHPStan\Reflection\ParameterReflection $parameter) : \PHPStan\Reflection\ParameterReflectionWithPhpDocs { return $parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs ? $parameter : new DummyParameterWithPhpDocs($parameter->getName(), $parameter->getType(), $parameter->isOptional(), $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), new MixedType(), $parameter->getType(), null, TrinaryLogic::createMaybe(), null); }, $variant->getParameters()), $variant->isVariadic(), $variant->getReturnType(), $variant->getReturnType(), new MixedType(), TemplateTypeVarianceMap::createEmpty()); } return $variants; } public function getOnlyVariant() : \PHPStan\Reflection\ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { return null; } public function isDeprecated() : TrinaryLogic { return $this->method->isDeprecated(); } public function getDeprecatedDescription() : ?string { return $this->method->getDeprecatedDescription(); } public function isFinal() : TrinaryLogic { return $this->method->isFinal(); } public function isFinalByKeyword() : TrinaryLogic { return $this->isFinal(); } public function isInternal() : TrinaryLogic { return $this->method->isInternal(); } public function getThrowType() : ?Type { return $this->method->getThrowType(); } public function hasSideEffects() : TrinaryLogic { return $this->method->hasSideEffects(); } public function isPure() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getAsserts() : \PHPStan\Reflection\Assertions { return \PHPStan\Reflection\Assertions::createEmpty(); } public function acceptsNamedArguments() : bool { return $this->getDeclaringClass()->acceptsNamedArguments(); } public function getSelfOutType() : ?Type { return null; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isAbstract() : TrinaryLogic { return TrinaryLogic::createNo(); } } methods[$classReflection->getCacheKey()][$methodName])) { $method = $this->findClassReflectionWithMethod($classReflection, $classReflection, $methodName); if ($method === null) { return \false; } $this->methods[$classReflection->getCacheKey()][$methodName] = $method; } return isset($this->methods[$classReflection->getCacheKey()][$methodName]); } /** * @return ExtendedMethodReflection */ public function getMethod(ClassReflection $classReflection, string $methodName) : MethodReflection { return $this->methods[$classReflection->getCacheKey()][$methodName]; } private function findClassReflectionWithMethod(ClassReflection $classReflection, ClassReflection $declaringClass, string $methodName) : ?ExtendedMethodReflection { $methodTags = $classReflection->getMethodTags(); if (isset($methodTags[$methodName])) { $parameters = []; foreach ($methodTags[$methodName]->getParameters() as $parameterName => $parameterTag) { $parameters[] = new \PHPStan\Reflection\Annotations\AnnotationsMethodParameterReflection($parameterName, $parameterTag->getType(), $parameterTag->passedByReference(), $parameterTag->isOptional(), $parameterTag->isVariadic(), $parameterTag->getDefaultValue()); } $templateTypeScope = TemplateTypeScope::createWithClass($classReflection->getName()); $templateTypeMap = new TemplateTypeMap(array_map(static function (TemplateTag $tag) use($templateTypeScope) : Type { return TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag); }, $methodTags[$methodName]->getTemplateTags())); $isStatic = $methodTags[$methodName]->isStatic(); $nativeCallMethodName = $isStatic ? '__callStatic' : '__call'; return new \PHPStan\Reflection\Annotations\AnnotationMethodReflection($methodName, $declaringClass, TemplateTypeHelper::resolveTemplateTypes($methodTags[$methodName]->getReturnType(), $classReflection->getActiveTemplateTypeMap(), $classReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createCovariant()), $parameters, $isStatic, $this->detectMethodVariadic($parameters), $classReflection->hasNativeMethod($nativeCallMethodName) ? $classReflection->getNativeMethod($nativeCallMethodName)->getThrowType() : null, $templateTypeMap); } foreach ($classReflection->getTraits() as $traitClass) { $methodWithDeclaringClass = $this->findClassReflectionWithMethod($traitClass, $classReflection, $methodName); if ($methodWithDeclaringClass === null) { continue; } return $methodWithDeclaringClass; } $parentClass = $classReflection->getParentClass(); while ($parentClass !== null) { $methodWithDeclaringClass = $this->findClassReflectionWithMethod($parentClass, $parentClass, $methodName); if ($methodWithDeclaringClass !== null) { return $methodWithDeclaringClass; } $parentClass = $parentClass->getParentClass(); } foreach ($classReflection->getInterfaces() as $interfaceClass) { $methodWithDeclaringClass = $this->findClassReflectionWithMethod($interfaceClass, $interfaceClass, $methodName); if ($methodWithDeclaringClass === null) { continue; } return $methodWithDeclaringClass; } return null; } /** * @param AnnotationsMethodParameterReflection[] $parameters */ private function detectMethodVariadic(array $parameters) : bool { if ($parameters === []) { return \false; } $possibleVariadicParameterIndex = count($parameters) - 1; $possibleVariadicParameter = $parameters[$possibleVariadicParameterIndex]; return $possibleVariadicParameter->isVariadic(); } } name = $name; $this->declaringClass = $declaringClass; $this->returnType = $returnType; $this->parameters = $parameters; $this->isStatic = $isStatic; $this->isVariadic = $isVariadic; $this->throwType = $throwType; $this->templateTypeMap = $templateTypeMap; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function getPrototype() : ClassMemberReflection { return $this; } public function isStatic() : bool { return $this->isStatic; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getName() : string { return $this->name; } public function getVariants() : array { if ($this->variants === null) { $this->variants = [new FunctionVariantWithPhpDocs($this->templateTypeMap, null, $this->parameters, $this->isVariadic, $this->returnType, $this->returnType, new MixedType())]; } return $this->variants; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription() : ?string { return null; } public function isFinal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinalByKeyword() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getThrowType() : ?Type { return $this->throwType; } public function hasSideEffects() : TrinaryLogic { if ($this->returnType->isVoid()->yes()) { return TrinaryLogic::createYes(); } if ((new ThisType($this->declaringClass))->isSuperTypeOf($this->returnType)->yes()) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function getDocComment() : ?string { return null; } public function getAsserts() : Assertions { return Assertions::createEmpty(); } public function acceptsNamedArguments() : bool { return $this->declaringClass->acceptsNamedArguments(); } public function getSelfOutType() : ?Type { return null; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function isAbstract() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isPure() : TrinaryLogic { if ($this->hasSideEffects()->yes()) { return TrinaryLogic::createNo(); } return TrinaryLogic::createMaybe(); } } declaringClass = $declaringClass; $this->readableType = $readableType; $this->writableType = $writableType; $this->readable = $readable; $this->writable = $writable; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return \false; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getReadableType() : Type { return $this->readableType; } public function getWritableType() : Type { return $this->writableType; } public function canChangeTypeAfterAssignment() : bool { return $this->readableType->equals($this->writableType); } public function isReadable() : bool { return $this->readable; } public function isWritable() : bool { return $this->writable; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription() : ?string { return null; } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDocComment() : ?string { return null; } } properties[$classReflection->getCacheKey()][$propertyName])) { $property = $this->findClassReflectionWithProperty($classReflection, $classReflection, $propertyName); if ($property === null) { return \false; } $this->properties[$classReflection->getCacheKey()][$propertyName] = $property; } return isset($this->properties[$classReflection->getCacheKey()][$propertyName]); } /** * @return ExtendedPropertyReflection */ public function getProperty(ClassReflection $classReflection, string $propertyName) : PropertyReflection { return $this->properties[$classReflection->getCacheKey()][$propertyName]; } private function findClassReflectionWithProperty(ClassReflection $classReflection, ClassReflection $declaringClass, string $propertyName) : ?ExtendedPropertyReflection { $propertyTags = $classReflection->getPropertyTags(); if (isset($propertyTags[$propertyName])) { $propertyTag = $propertyTags[$propertyName]; $isReadable = $propertyTags[$propertyName]->isReadable(); $isWritable = $propertyTags[$propertyName]->isWritable(); if ($classReflection->hasNativeProperty($propertyName)) { $nativeProperty = $classReflection->getNativeProperty($propertyName); $isReadable = $isReadable || $nativeProperty->isReadable(); $isWritable = $isWritable || $nativeProperty->isWritable(); } return new \PHPStan\Reflection\Annotations\AnnotationPropertyReflection($declaringClass, TemplateTypeHelper::resolveTemplateTypes($propertyTag->getReadableType() ?? new NeverType(), $classReflection->getActiveTemplateTypeMap(), $classReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createCovariant()), TemplateTypeHelper::resolveTemplateTypes($propertyTag->getWritableType() ?? new NeverType(), $classReflection->getActiveTemplateTypeMap(), $classReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createContravariant()), $isReadable, $isWritable); } foreach ($classReflection->getTraits() as $traitClass) { $methodWithDeclaringClass = $this->findClassReflectionWithProperty($traitClass, $classReflection, $propertyName); if ($methodWithDeclaringClass === null) { continue; } return $methodWithDeclaringClass; } $parentClass = $classReflection->getParentClass(); while ($parentClass !== null) { $methodWithDeclaringClass = $this->findClassReflectionWithProperty($parentClass, $parentClass, $propertyName); if ($methodWithDeclaringClass !== null) { return $methodWithDeclaringClass; } $parentClass = $parentClass->getParentClass(); } foreach ($classReflection->getInterfaces() as $interfaceClass) { $methodWithDeclaringClass = $this->findClassReflectionWithProperty($interfaceClass, $interfaceClass, $propertyName); if ($methodWithDeclaringClass === null) { continue; } return $methodWithDeclaringClass; } return null; } } name = $name; $this->type = $type; $this->passedByReference = $passedByReference; $this->isOptional = $isOptional; $this->isVariadic = $isVariadic; $this->defaultValue = $defaultValue; } public function getName() : string { return $this->name; } public function isOptional() : bool { return $this->isOptional; } public function getType() : Type { return $this->type; } public function getPhpDocType() : Type { return $this->type; } public function getNativeType() : Type { return new MixedType(); } public function getOutType() : ?Type { return null; } public function isImmediatelyInvokedCallable() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getClosureThisType() : ?Type { return null; } public function passedByReference() : PassedByReference { return $this->passedByReference; } public function isVariadic() : bool { return $this->isVariadic; } public function getDefaultValue() : ?Type { return $this->defaultValue; } } propertiesClassReflectionExtensions = $propertiesClassReflectionExtensions; $this->methodsClassReflectionExtensions = $methodsClassReflectionExtensions; $this->allowedSubTypesClassReflectionExtensions = $allowedSubTypesClassReflectionExtensions; $this->requireExtendsPropertiesClassReflectionExtension = $requireExtendsPropertiesClassReflectionExtension; $this->requireExtendsMethodsClassReflectionExtension = $requireExtendsMethodsClassReflectionExtension; foreach (array_merge($propertiesClassReflectionExtensions, $methodsClassReflectionExtensions, $allowedSubTypesClassReflectionExtensions) as $extension) { if (!$extension instanceof \PHPStan\Reflection\BrokerAwareExtension) { continue; } $extension->setBroker($broker); } } /** * @return PropertiesClassReflectionExtension[] */ public function getPropertiesClassReflectionExtensions() : array { return $this->propertiesClassReflectionExtensions; } /** * @return MethodsClassReflectionExtension[] */ public function getMethodsClassReflectionExtensions() : array { return $this->methodsClassReflectionExtensions; } /** * @return AllowedSubTypesClassReflectionExtension[] */ public function getAllowedSubTypesClassReflectionExtensions() : array { return $this->allowedSubTypesClassReflectionExtensions; } public function getRequireExtendsPropertyClassReflectionExtension() : RequireExtendsPropertiesClassReflectionExtension { return $this->requireExtendsPropertiesClassReflectionExtension; } public function getRequireExtendsMethodsClassReflectionExtension() : RequireExtendsMethodsClassReflectionExtension { return $this->requireExtendsMethodsClassReflectionExtension; } } property = $property; } public function getDeclaringClass() : \PHPStan\Reflection\ClassReflection { return $this->property->getDeclaringClass(); } public function isStatic() : bool { return $this->property->isStatic(); } public function isPrivate() : bool { return $this->property->isPrivate(); } public function isPublic() : bool { return $this->property->isPublic(); } public function getDocComment() : ?string { return $this->property->getDocComment(); } public function getReadableType() : Type { return $this->property->getReadableType(); } public function getWritableType() : Type { return $this->property->getWritableType(); } public function canChangeTypeAfterAssignment() : bool { return $this->property->canChangeTypeAfterAssignment(); } public function isReadable() : bool { return $this->property->isReadable(); } public function isWritable() : bool { return $this->property->isWritable(); } public function isDeprecated() : TrinaryLogic { return $this->property->isDeprecated(); } public function getDeprecatedDescription() : ?string { return $this->property->getDeprecatedDescription(); } public function isInternal() : TrinaryLogic { return $this->property->isInternal(); } } phpVersion = $phpVersion; $this->className = $className; $this->methodName = $methodName; } public function getClass() : string { return $this->className; } public function isMethodSupported(MethodReflection $methodReflection) : bool { return $methodReflection->getName() === $this->methodName; } public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope) : ?Type { if ($this->phpVersion->getVersionId() >= 80000) { return null; } return new ObjectType(ReflectionClass::class); } } parametersAcceptor = $parametersAcceptor; $this->throwPoints = $throwPoints; $this->isPure = $isPure; $this->impurePoints = $impurePoints; $this->invalidateExpressions = $invalidateExpressions; $this->usedVariables = $usedVariables; $this->acceptsNamedArguments = $acceptsNamedArguments; } public function getOriginalParametersAcceptor() : \PHPStan\Reflection\ParametersAcceptor { return $this->parametersAcceptor->getOriginalParametersAcceptor(); } public function getTemplateTypeMap() : TemplateTypeMap { return $this->parametersAcceptor->getTemplateTypeMap(); } public function getResolvedTemplateTypeMap() : TemplateTypeMap { return $this->parametersAcceptor->getResolvedTemplateTypeMap(); } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return $this->parametersAcceptor->getCallSiteVarianceMap(); } public function getParameters() : array { return $this->parametersAcceptor->getParameters(); } public function isVariadic() : bool { return $this->parametersAcceptor->isVariadic(); } public function getReturnTypeWithUnresolvableTemplateTypes() : Type { return $this->parametersAcceptor->getReturnTypeWithUnresolvableTemplateTypes(); } public function getPhpDocReturnTypeWithUnresolvableTemplateTypes() : Type { return $this->parametersAcceptor->getPhpDocReturnTypeWithUnresolvableTemplateTypes(); } public function getReturnType() : Type { return $this->parametersAcceptor->getReturnType(); } public function getPhpDocReturnType() : Type { return $this->parametersAcceptor->getPhpDocReturnType(); } public function getNativeReturnType() : Type { return $this->parametersAcceptor->getNativeReturnType(); } public function getThrowPoints() : array { return $this->throwPoints; } public function isPure() : TrinaryLogic { return $this->isPure; } public function getImpurePoints() : array { return $this->impurePoints; } public function getInvalidateExpressions() : array { return $this->invalidateExpressions; } public function getUsedVariables() : array { return $this->usedVariables; } public function acceptsNamedArguments() : bool { return $this->acceptsNamedArguments; } } methodReflection = $methodReflection; } public function getMethod() : \PHPStan\Reflection\ExtendedMethodReflection { return $this->methodReflection; } public function getTemplateTypeMap() : TemplateTypeMap { return TemplateTypeMap::createEmpty(); } public function getResolvedTemplateTypeMap() : TemplateTypeMap { return TemplateTypeMap::createEmpty(); } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return TemplateTypeVarianceMap::createEmpty(); } /** * @return array */ public function getParameters() : array { return []; } public function isVariadic() : bool { return \true; } public function getReturnType() : Type { return new MixedType(); } public function getThrowPoints() : array { return []; } public function isPure() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getImpurePoints() : array { return [new SimpleImpurePoint('methodCall', 'call to unknown method', \false)]; } public function getInvalidateExpressions() : array { return []; } public function getUsedVariables() : array { return []; } public function acceptsNamedArguments() : bool { return $this->methodReflection->acceptsNamedArguments(); } } >> */ private $classNodes; /** * @var array>> */ private $functionNodes; /** * @var array>> */ private $constantNodes; /** * @param array>> $classNodes * @param array>> $functionNodes * @param array>> $constantNodes */ public function __construct(array $classNodes, array $functionNodes, array $constantNodes) { $this->classNodes = $classNodes; $this->functionNodes = $functionNodes; $this->constantNodes = $constantNodes; } /** * @return array>> */ public function getClassNodes() : array { return $this->classNodes; } /** * @return array>> */ public function getFunctionNodes() : array { return $this->functionNodes; } /** * @return array>> */ public function getConstantNodes() : array { return $this->constantNodes; } } */ private $locators = []; public function __construct(PsrAutoloaderMapping $mapping, \PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocatorRepository $optimizedSingleFileSourceLocatorRepository) { $this->mapping = $mapping; $this->optimizedSingleFileSourceLocatorRepository = $optimizedSingleFileSourceLocatorRepository; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { foreach ($this->locators as $locator) { $reflection = $locator->locateIdentifier($reflector, $identifier); if ($reflection === null) { continue; } return $reflection; } foreach ($this->mapping->resolvePossibleFilePaths($identifier) as $file) { if (!is_file($file)) { continue; } $locator = $this->optimizedSingleFileSourceLocatorRepository->getOrCreate($file); $reflection = $locator->locateIdentifier($reflector, $identifier); if ($reflection === null) { continue; } $this->locators[$file] = $locator; return $reflection; } return null; } /** * @return list */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return []; } } |null */ private $classToFile = null; /** @var array|null */ private $constantToFile = null; /** @var array>|null */ private $functionToFiles = null; /** * @param string[] $files */ public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher $fileNodesFetcher, PhpVersion $phpVersion, array $files) { $this->fileNodesFetcher = $fileNodesFetcher; $this->phpVersion = $phpVersion; $this->files = $files; $this->extraTypes = $this->phpVersion->supportsEnums() ? '|enum' : ''; $this->cleaner = new \PHPStan\Reflection\BetterReflection\SourceLocator\PhpFileCleaner(); } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { if ($identifier->isClass()) { $className = strtolower($identifier->getName()); $file = $this->findFileByClass($className); if ($file === null) { return null; } $fetchedClassNodes = $this->fileNodesFetcher->fetchNodes($file)->getClassNodes(); if (!array_key_exists($className, $fetchedClassNodes)) { return null; } /** @var FetchedNode $fetchedClassNode */ $fetchedClassNode = current($fetchedClassNodes[$className]); return $this->nodeToReflection($reflector, $fetchedClassNode); } if ($identifier->isFunction()) { $functionName = strtolower($identifier->getName()); $files = $this->findFilesByFunction($functionName); $fetchedFunctionNode = null; foreach ($files as $file) { $fetchedFunctionNodes = $this->fileNodesFetcher->fetchNodes($file)->getFunctionNodes(); if (!array_key_exists($functionName, $fetchedFunctionNodes)) { continue; } /** @var FetchedNode $fetchedFunctionNode */ $fetchedFunctionNode = current($fetchedFunctionNodes[$functionName]); } if ($fetchedFunctionNode === null) { return null; } return $this->nodeToReflection($reflector, $fetchedFunctionNode); } if ($identifier->isConstant()) { $constantName = ConstantNameHelper::normalize($identifier->getName()); $file = $this->findFileByConstant($constantName); if ($file === null) { return null; } $fetchedConstantNodes = $this->fileNodesFetcher->fetchNodes($file)->getConstantNodes(); if (!array_key_exists($constantName, $fetchedConstantNodes)) { return null; } /** @var FetchedNode $fetchedConstantNode */ $fetchedConstantNode = current($fetchedConstantNodes[$constantName]); return $this->nodeToReflection($reflector, $fetchedConstantNode, $this->findConstantPositionInConstNode($fetchedConstantNode->getNode(), $constantName)); } return null; } /** * @param FetchedNode|FetchedNode|FetchedNode $fetchedNode */ private function nodeToReflection(Reflector $reflector, \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNode $fetchedNode, ?int $positionInNode = null) : Reflection { $nodeToReflection = new NodeToReflection(); return $nodeToReflection->__invoke($reflector, $fetchedNode->getNode(), $fetchedNode->getLocatedSource(), $fetchedNode->getNamespace(), $positionInNode); } private function findFileByClass(string $className) : ?string { if ($this->classToFile === null) { $this->init(); if ($this->classToFile === null) { throw new ShouldNotHappenException(); } } if (!array_key_exists($className, $this->classToFile)) { return null; } return $this->classToFile[$className]; } private function findFileByConstant(string $constantName) : ?string { if ($this->constantToFile === null) { $this->init(); if ($this->constantToFile === null) { throw new ShouldNotHappenException(); } } if (!array_key_exists($constantName, $this->constantToFile)) { return null; } return $this->constantToFile[$constantName]; } /** * @return string[] */ private function findFilesByFunction(string $functionName) : array { if ($this->functionToFiles === null) { $this->init(); if ($this->functionToFiles === null) { throw new ShouldNotHappenException(); } } if (!array_key_exists($functionName, $this->functionToFiles)) { return []; } return $this->functionToFiles[$functionName]; } private function init() : void { $classToFile = []; $constantToFile = []; $functionToFiles = []; foreach ($this->files as $file) { $symbols = $this->findSymbols($file); foreach ($symbols['classes'] as $classInFile) { $classToFile[$classInFile] = $file; } foreach ($symbols['constants'] as $constantInFile) { $constantToFile[$constantInFile] = $file; } foreach ($symbols['functions'] as $functionInFile) { if (!array_key_exists($functionInFile, $functionToFiles)) { $functionToFiles[$functionInFile] = []; } $functionToFiles[$functionInFile][] = $file; } } $this->classToFile = $classToFile; $this->functionToFiles = $functionToFiles; $this->constantToFile = $constantToFile; } /** * Inspired by Composer\Autoload\ClassMapGenerator::findClasses() * @link https://github.com/composer/composer/blob/45d3e133a4691eccb12e9cd6f9dfd76eddc1906d/src/Composer/Autoload/ClassMapGenerator.php#L216 * * @return array{classes: string[], functions: string[], constants: string[]} */ private function findSymbols(string $file) : array { $contents = @php_strip_whitespace($file); if ($contents === '') { return ['classes' => [], 'functions' => [], 'constants' => []]; } $matchResults = (bool) preg_match_all(sprintf('{\\b(?:(?:class|interface|trait|const|function%s)\\s)|(?:define\\s*\\()}i', $this->extraTypes), $contents, $matches); if (!$matchResults) { return ['classes' => [], 'functions' => [], 'constants' => []]; } $contents = $this->cleaner->clean($contents, count($matches[0])); preg_match_all(sprintf('{ (?: \\b(?])(?: (?: (?Pclass|interface|trait%s) \\s++ (?P[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\-]*+) ) | (?: (?Pfunction) \\s++ (?:&\\s*)? (?P[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\-]*+) \\s*+ [&\\(] ) | (?: (?Pconst) \\s++ (?P[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\-]*+) \\s*+ [^;] ) | (?: (?:\\\\)? (?Pdefine) \\s*+ \\( \\s*+ [\'"] (?P[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+(?:[\\\\]{1,2}[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+)*+) ) | (?: (?Pnamespace) (?P\\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', $this->extraTypes), $contents, $matches); $classes = []; $functions = []; $constants = []; $namespace = ''; for ($i = 0, $len = count($matches['type']); $i < $len; $i++) { if (isset($matches['ns'][$i]) && $matches['ns'][$i] !== '') { $namespace = preg_replace('~\\s+~', '', strtolower($matches['nsname'][$i])) . '\\'; continue; } if ($matches['function'][$i] !== '') { $functions[] = strtolower(ltrim($namespace . $matches['fname'][$i], '\\')); continue; } if ($matches['constant'][$i] !== '') { $constants[] = ConstantNameHelper::normalize(ltrim($namespace . $matches['cname'][$i], '\\')); } if ($matches['define'][$i] !== '') { $constants[] = ConstantNameHelper::normalize($matches['dname'][$i]); continue; } $name = $matches['name'][$i]; // skip anon classes extending/implementing if (in_array($name, ['extends', 'implements'], \true)) { continue; } $classes[] = strtolower(ltrim($namespace . $name, '\\')); } return ['classes' => $classes, 'functions' => $functions, 'constants' => $constants]; } /** * @return list */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { if ($this->classToFile === null || $this->functionToFiles === null || $this->constantToFile === null) { $this->init(); if ($this->classToFile === null || $this->functionToFiles === null || $this->constantToFile === null) { throw new ShouldNotHappenException(); } } $reflections = []; if ($identifierType->isClass()) { foreach ($this->classToFile as $file) { $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file); foreach ($fetchedNodesResult->getClassNodes() as $identifierName => $fetchedClassNodes) { foreach ($fetchedClassNodes as $fetchedClassNode) { $reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedClassNode); } } } } elseif ($identifierType->isFunction()) { foreach ($this->functionToFiles as $files) { foreach ($files as $file) { $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file); foreach ($fetchedNodesResult->getFunctionNodes() as $identifierName => $fetchedFunctionNodes) { foreach ($fetchedFunctionNodes as $fetchedFunctionNode) { $reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedFunctionNode); continue 2; } } } } } elseif ($identifierType->isConstant()) { foreach ($this->constantToFile as $file) { $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file); foreach ($fetchedNodesResult->getConstantNodes() as $identifierName => $fetchedConstantNodes) { foreach ($fetchedConstantNodes as $fetchedConstantNode) { $reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedConstantNode, $this->findConstantPositionInConstNode($fetchedConstantNode->getNode(), $identifierName)); } } } } return array_values($reflections); } /** * @param Node\Stmt\Const_|Node\Expr\FuncCall $constantNode */ private function findConstantPositionInConstNode($constantNode, string $constantName) : ?int { if ($constantNode instanceof Node\Expr\FuncCall) { return null; } /** @var int $position */ foreach ($constantNode->consts as $position => $const) { if ($const->namespacedName === null) { throw new ShouldNotHappenException(); } if (ConstantNameHelper::normalize($const->namespacedName->toString()) === $constantName) { return $position; } } throw new ShouldNotHappenException(); } } cachingVisitor = $cachingVisitor; $this->parser = $parser; } public function fetchNodes(string $fileName) : \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNodesResult { $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor($this->cachingVisitor); $contents = FileReader::read($fileName); try { $ast = $this->parser->parseFile($fileName); } catch (ParserErrorsException $e) { return new \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNodesResult([], [], []); } $this->cachingVisitor->reset($fileName, $contents); $nodeTraverser->traverse($ast); $result = new \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNodesResult($this->cachingVisitor->getClassNodes(), $this->cachingVisitor->getFunctionNodes(), $this->cachingVisitor->getConstantNodes()); $this->cachingVisitor->reset($fileName, $contents); return $result; } } fileNodesFetcher = $fileNodesFetcher; $this->fileFinder = $fileFinder; $this->phpVersion = $phpVersion; $this->cache = $cache; $this->extraTypes = $this->phpVersion->supportsEnums() ? '|enum' : ''; $this->cleaner = new \PHPStan\Reflection\BetterReflection\SourceLocator\PhpFileCleaner(); } public function createByDirectory(string $directory) : \PHPStan\Reflection\BetterReflection\SourceLocator\NewOptimizedDirectorySourceLocator { $files = $this->fileFinder->findFiles([$directory])->getFiles(); $fileHashes = []; foreach ($files as $file) { $hash = sha1_file($file); if ($hash === \false) { continue; } $fileHashes[$file] = $hash; } $cacheKey = sprintf('odsl-%s', $directory); $variableCacheKey = 'v1'; /** @var array|null $cached */ $cached = $this->cache->load($cacheKey, $variableCacheKey); if ($cached !== null) { foreach ($cached as $file => [$hash, $classes, $functions, $constants]) { if (!array_key_exists($file, $fileHashes)) { unset($cached[$file]); continue; } $newHash = $fileHashes[$file]; unset($fileHashes[$file]); if ($hash === $newHash) { continue; } [$newClasses, $newFunctions, $newConstants] = $this->findSymbols($file); $cached[$file] = [$newHash, $newClasses, $newFunctions, $newConstants]; } } else { $cached = []; } foreach ($fileHashes as $file => $newHash) { [$newClasses, $newFunctions, $newConstants] = $this->findSymbols($file); $cached[$file] = [$newHash, $newClasses, $newFunctions, $newConstants]; } $this->cache->save($cacheKey, $variableCacheKey, $cached); [$classToFile, $functionToFiles, $constantToFile] = $this->changeStructure($cached); return new \PHPStan\Reflection\BetterReflection\SourceLocator\NewOptimizedDirectorySourceLocator($this->fileNodesFetcher, $classToFile, $functionToFiles, $constantToFile); } /** * @param string[] $files */ public function createByFiles(array $files) : \PHPStan\Reflection\BetterReflection\SourceLocator\NewOptimizedDirectorySourceLocator { $symbols = []; foreach ($files as $file) { [$newClasses, $newFunctions, $newConstants] = $this->findSymbols($file); $symbols[$file] = ['', $newClasses, $newFunctions, $newConstants]; } [$classToFile, $functionToFiles, $constantToFile] = $this->changeStructure($symbols); return new \PHPStan\Reflection\BetterReflection\SourceLocator\NewOptimizedDirectorySourceLocator($this->fileNodesFetcher, $classToFile, $functionToFiles, $constantToFile); } /** * @param array $symbols * @return array{array, array>, array} */ private function changeStructure(array $symbols) : array { $classToFile = []; $constantToFile = []; $functionToFiles = []; foreach ($symbols as $file => [, $classes, $functions, $constants]) { foreach ($classes as $classInFile) { $classToFile[$classInFile] = $file; } foreach ($functions as $functionInFile) { if (!array_key_exists($functionInFile, $functionToFiles)) { $functionToFiles[$functionInFile] = []; } $functionToFiles[$functionInFile][] = $file; } foreach ($constants as $constantInFile) { $constantToFile[$constantInFile] = $file; } } return [$classToFile, $functionToFiles, $constantToFile]; } /** * Inspired by Composer\Autoload\ClassMapGenerator::findClasses() * @link https://github.com/composer/composer/blob/45d3e133a4691eccb12e9cd6f9dfd76eddc1906d/src/Composer/Autoload/ClassMapGenerator.php#L216 * * @return array{string[], string[], string[]} */ private function findSymbols(string $file) : array { $contents = @php_strip_whitespace($file); if ($contents === '') { return [[], [], []]; } $matchResults = (bool) preg_match_all(sprintf('{\\b(?:(?:class|interface|trait|const|function%s)\\s)|(?:define\\s*\\()}i', $this->extraTypes), $contents, $matches); if (!$matchResults) { return [[], [], []]; } $contents = $this->cleaner->clean($contents, count($matches[0])); preg_match_all(sprintf('{ (?: \\b(?])(?: (?: (?Pclass|interface|trait%s) \\s++ (?P[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\-]*+) ) | (?: (?Pfunction) \\s++ (?:&\\s*)? (?P[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\-]*+) \\s*+ [&\\(] ) | (?: (?Pconst) \\s++ (?P[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\-]*+) \\s*+ [^;] ) | (?: (?:\\\\)? (?Pdefine) \\s*+ \\( \\s*+ [\'"] (?P[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+(?:[\\\\]{1,2}[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+)*+) ) | (?: (?Pnamespace) (?P\\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', $this->extraTypes), $contents, $matches); $classes = []; $functions = []; $constants = []; $namespace = ''; for ($i = 0, $len = count($matches['type']); $i < $len; $i++) { if (isset($matches['ns'][$i]) && $matches['ns'][$i] !== '') { $namespace = preg_replace('~\\s+~', '', strtolower($matches['nsname'][$i])) . '\\'; continue; } if ($matches['function'][$i] !== '') { $functions[] = strtolower(ltrim($namespace . $matches['fname'][$i], '\\')); continue; } if ($matches['constant'][$i] !== '') { $constants[] = ConstantNameHelper::normalize(ltrim($namespace . $matches['cname'][$i], '\\')); } if ($matches['define'][$i] !== '') { $constants[] = ConstantNameHelper::normalize($matches['dname'][$i]); continue; } $name = $matches['name'][$i]; // skip anon classes extending/implementing if (in_array($name, ['extends', 'implements'], \true)) { continue; } $classes[] = strtolower(ltrim($namespace . $name, '\\')); } return [$classes, $functions, $constants]; } } , functions: array, constants: array} */ private $presentSymbols = ['classes' => [], 'functions' => [], 'constants' => []]; /** @var array */ private $scannedFiles = []; /** @var array */ private $startLineByClass = []; public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher $fileNodesFetcher, bool $executeAutoloadersInFileReadTrap) { $this->fileNodesFetcher = $fileNodesFetcher; $this->executeAutoloadersInFileReadTrap = $executeAutoloadersInFileReadTrap; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { if ($identifier->isFunction()) { $functionName = $identifier->getName(); $loweredFunctionName = strtolower($functionName); if (array_key_exists($loweredFunctionName, $this->presentSymbols['functions'])) { return $this->findReflection($reflector, $this->presentSymbols['functions'][$loweredFunctionName], $identifier, null); } if (!function_exists($functionName)) { return null; } $reflection = new ReflectionFunction($functionName); $reflectionFileName = $reflection->getFileName(); if (!is_string($reflectionFileName)) { return null; } if (!is_file($reflectionFileName)) { return null; } return $this->findReflection($reflector, $reflectionFileName, $identifier, null); } if ($identifier->isConstant()) { $constantName = ConstantNameHelper::normalize($identifier->getName()); if (array_key_exists($constantName, $this->presentSymbols['constants'])) { return $this->findReflection($reflector, $this->presentSymbols['constants'][$constantName], $identifier, null); } if (!defined($constantName)) { return null; } $constantValue = @constant($constantName); return ReflectionConstant::createFromNode($reflector, new FuncCall(new Name('define'), [new Arg(new String_($constantName)), new Arg(new TypeExpr(ConstantTypeHelper::getTypeFromValue($constantValue)))], ['startLine' => 1, 'endLine' => 1, 'startFilePos' => 1, 'endFilePos' => 4]), new LocatedSource('isClass()) { return null; } $loweredClassName = strtolower($identifier->getName()); if (array_key_exists($loweredClassName, $this->presentSymbols['classes'])) { $startLine = null; if (array_key_exists($loweredClassName, $this->startLineByClass)) { $startLine = $this->startLineByClass[$loweredClassName]; } else { $reflection = $this->getReflectionClass($identifier->getName()); if ($reflection !== null && $reflection->getStartLine() !== \false && is_string($reflection->getFileName()) && is_file($reflection->getFileName()) && $reflection->getFileName() === $this->presentSymbols['classes'][$loweredClassName]) { $startLine = $reflection->getStartLine(); } } return $this->findReflection($reflector, $this->presentSymbols['classes'][$loweredClassName], $identifier, $startLine); } $locateResult = $this->locateClassByName($identifier->getName()); if ($locateResult === null) { return null; } [$potentiallyLocatedFiles, $className, $startLine] = $locateResult; if ($startLine !== null) { $this->startLineByClass[strtolower($className)] = $startLine; } $newIdentifier = new Identifier($className, $identifier->getType()); foreach ($potentiallyLocatedFiles as $potentiallyLocatedFile) { $reflection = $this->findReflection($reflector, $potentiallyLocatedFile, $newIdentifier, $startLine); if ($reflection === null) { continue; } return $reflection; } return null; } private function findReflection(Reflector $reflector, string $file, Identifier $identifier, ?int $startLine) : ?Reflection { $result = $this->fileNodesFetcher->fetchNodes($file); if (!array_key_exists($file, $this->scannedFiles)) { foreach (array_keys($result->getClassNodes()) as $className) { if (array_key_exists($className, $this->presentSymbols['classes'])) { continue; } $this->presentSymbols['classes'][$className] = $file; } foreach (array_keys($result->getFunctionNodes()) as $functionName) { if (array_key_exists($functionName, $this->presentSymbols['functions'])) { continue; } $this->presentSymbols['functions'][$functionName] = $file; } foreach (array_keys($result->getConstantNodes()) as $constantName) { if (array_key_exists($constantName, $this->presentSymbols['constants'])) { continue; } $this->presentSymbols['constants'][$constantName] = $file; } $this->scannedFiles[$file] = \true; } $nodeToReflection = new NodeToReflection(); if ($identifier->isClass()) { $identifierName = strtolower($identifier->getName()); if (!array_key_exists($identifierName, $result->getClassNodes())) { return null; } $classNodesCount = count($result->getClassNodes()[$identifierName]); foreach ($result->getClassNodes()[$identifierName] as $classNode) { if ($classNodesCount > 1 && $startLine !== null) { if (count($classNode->getNode()->attrGroups) > 0 && PHP_VERSION_ID < 80000) { $startLine--; } if ($startLine !== $classNode->getNode()->getStartLine()) { continue; } } return $nodeToReflection->__invoke($reflector, $classNode->getNode(), $classNode->getLocatedSource(), $classNode->getNamespace()); } return null; } if ($identifier->isFunction()) { $identifierName = strtolower($identifier->getName()); if (!array_key_exists($identifierName, $result->getFunctionNodes())) { return null; } foreach ($result->getFunctionNodes()[$identifierName] as $functionNode) { return $nodeToReflection->__invoke($reflector, $functionNode->getNode(), $functionNode->getLocatedSource(), $functionNode->getNamespace()); } } if ($identifier->isConstant()) { $identifierName = ConstantNameHelper::normalize($identifier->getName()); $constantNodes = $result->getConstantNodes(); if (!array_key_exists($identifierName, $constantNodes)) { return null; } foreach ($constantNodes[$identifierName] as $fetchedConstantNode) { $constantNode = $fetchedConstantNode->getNode(); $positionInNode = null; if ($constantNode instanceof Const_) { foreach ($constantNode->consts as $constPosition => $const) { if ($const->namespacedName === null) { throw new ShouldNotHappenException(); } if (ConstantNameHelper::normalize($const->namespacedName->toString()) === $identifierName) { /** @var int $positionInNode */ $positionInNode = $constPosition; break; } } if ($positionInNode === null) { throw new ShouldNotHappenException(); } } return $nodeToReflection->__invoke($reflector, $constantNode, $fetchedConstantNode->getLocatedSource(), $fetchedConstantNode->getNamespace(), $positionInNode); } } return null; } public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return []; } /** * @return ReflectionClass|null */ private function getReflectionClass(string $className) : ?ReflectionClass { if (class_exists($className, \false) || interface_exists($className, \false) || trait_exists($className, \false)) { return new ReflectionClass($className); } return null; } /** * Attempt to locate a class by name. * * If class already exists, simply use internal reflection API to get the * filename and store it. * * If class does not exist, we make an assumption that whatever autoloaders * that are registered will be loading a file. We then override the file:// * protocol stream wrapper to "capture" the filename we expect the class to * be in, and then restore it. Note that class_exists will cause an error * that it cannot find the file, so we squelch the errors by overriding the * error handler temporarily. * * @return array{string[], string, int|null}|null */ private function locateClassByName(string $className) : ?array { $reflection = $this->getReflectionClass($className); if ($reflection !== null) { $filename = $reflection->getFileName(); if (!is_string($filename)) { return null; } if (!is_file($filename)) { return null; } return [[$filename], $reflection->getName(), $reflection->getStartLine() !== \false ? $reflection->getStartLine() : null]; } if (!$this->executeAutoloadersInFileReadTrap) { return null; } $this->silenceErrors(); try { $result = \PHPStan\Reflection\BetterReflection\SourceLocator\FileReadTrapStreamWrapper::withStreamWrapperOverride(static function () use($className) : ?array { $functions = spl_autoload_functions(); if ($functions === \false) { return null; } foreach ($functions as $preExistingAutoloader) { $preExistingAutoloader($className); /** * This static variable is populated by the side-effect of the stream wrapper * trying to read the file path when `include()` is used by an autoloader. * * This will not be `null` when the autoloader tried to read a file. */ if (\PHPStan\Reflection\BetterReflection\SourceLocator\FileReadTrapStreamWrapper::$autoloadLocatedFiles !== []) { return [\PHPStan\Reflection\BetterReflection\SourceLocator\FileReadTrapStreamWrapper::$autoloadLocatedFiles, $className, null]; } } return null; }); if ($result === null) { return null; } if (!function_exists('opcache_invalidate')) { return $result; } foreach ($result[0] as $file) { opcache_invalidate($file, \true); } return $result; } finally { restore_error_handler(); } } private function silenceErrors() : void { set_error_handler(static function () : bool { return \true; }); } } */ private $classToFile; /** * @var array> */ private $functionToFiles; /** * @var array */ private $constantToFile; /** * @param array $classToFile * @param array> $functionToFiles * @param array $constantToFile */ public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher $fileNodesFetcher, array $classToFile, array $functionToFiles, array $constantToFile) { $this->fileNodesFetcher = $fileNodesFetcher; $this->classToFile = $classToFile; $this->functionToFiles = $functionToFiles; $this->constantToFile = $constantToFile; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { if ($identifier->isClass()) { $className = strtolower($identifier->getName()); $file = $this->findFileByClass($className); if ($file === null) { return null; } $fetchedClassNodes = $this->fileNodesFetcher->fetchNodes($file)->getClassNodes(); if (!array_key_exists($className, $fetchedClassNodes)) { return null; } /** @var FetchedNode $fetchedClassNode */ $fetchedClassNode = current($fetchedClassNodes[$className]); return $this->nodeToReflection($reflector, $fetchedClassNode); } if ($identifier->isFunction()) { $functionName = strtolower($identifier->getName()); $files = $this->findFilesByFunction($functionName); $fetchedFunctionNode = null; foreach ($files as $file) { $fetchedFunctionNodes = $this->fileNodesFetcher->fetchNodes($file)->getFunctionNodes(); if (!array_key_exists($functionName, $fetchedFunctionNodes)) { continue; } /** @var FetchedNode $fetchedFunctionNode */ $fetchedFunctionNode = current($fetchedFunctionNodes[$functionName]); } if ($fetchedFunctionNode === null) { return null; } return $this->nodeToReflection($reflector, $fetchedFunctionNode); } if ($identifier->isConstant()) { $constantName = ConstantNameHelper::normalize($identifier->getName()); $file = $this->findFileByConstant($constantName); if ($file === null) { return null; } $fetchedConstantNodes = $this->fileNodesFetcher->fetchNodes($file)->getConstantNodes(); if (!array_key_exists($constantName, $fetchedConstantNodes)) { return null; } /** @var FetchedNode $fetchedConstantNode */ $fetchedConstantNode = current($fetchedConstantNodes[$constantName]); return $this->nodeToReflection($reflector, $fetchedConstantNode, $this->findConstantPositionInConstNode($fetchedConstantNode->getNode(), $constantName)); } return null; } /** * @param FetchedNode|FetchedNode|FetchedNode $fetchedNode */ private function nodeToReflection(Reflector $reflector, \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNode $fetchedNode, ?int $positionInNode = null) : Reflection { $nodeToReflection = new NodeToReflection(); return $nodeToReflection->__invoke($reflector, $fetchedNode->getNode(), $fetchedNode->getLocatedSource(), $fetchedNode->getNamespace(), $positionInNode); } private function findFileByClass(string $className) : ?string { if (!array_key_exists($className, $this->classToFile)) { return null; } return $this->classToFile[$className]; } private function findFileByConstant(string $constantName) : ?string { if (!array_key_exists($constantName, $this->constantToFile)) { return null; } return $this->constantToFile[$constantName]; } /** * @return string[] */ private function findFilesByFunction(string $functionName) : array { if (!array_key_exists($functionName, $this->functionToFiles)) { return []; } return $this->functionToFiles[$functionName]; } /** * @return list */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { $reflections = []; if ($identifierType->isClass()) { foreach ($this->classToFile as $file) { $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file); foreach ($fetchedNodesResult->getClassNodes() as $identifierName => $fetchedClassNodes) { foreach ($fetchedClassNodes as $fetchedClassNode) { $reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedClassNode); } } } } elseif ($identifierType->isFunction()) { foreach ($this->functionToFiles as $files) { foreach ($files as $file) { $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file); foreach ($fetchedNodesResult->getFunctionNodes() as $identifierName => $fetchedFunctionNodes) { foreach ($fetchedFunctionNodes as $fetchedFunctionNode) { $reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedFunctionNode); continue 2; } } } } } elseif ($identifierType->isConstant()) { foreach ($this->constantToFile as $file) { $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file); foreach ($fetchedNodesResult->getConstantNodes() as $identifierName => $fetchedConstantNodes) { foreach ($fetchedConstantNodes as $fetchedConstantNode) { $reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedConstantNode, $this->findConstantPositionInConstNode($fetchedConstantNode->getNode(), $identifierName)); } } } } return array_values($reflections); } /** * @param Node\Stmt\Const_|Node\Expr\FuncCall $constantNode */ private function findConstantPositionInConstNode($constantNode, string $constantName) : ?int { if ($constantNode instanceof Node\Expr\FuncCall) { return null; } /** @var int $position */ foreach ($constantNode->consts as $position => $const) { if ($const->namespacedName === null) { throw new ShouldNotHappenException(); } if (ConstantNameHelper::normalize($const->namespacedName->toString()) === $constantName) { return $position; } } throw new ShouldNotHappenException(); } } node = $node; $this->namespace = $namespace; $this->locatedSource = $locatedSource; } /** * @return T */ public function getNode() : Node { return $this->node; } public function getNamespace() : ?Node\Stmt\Namespace_ { return $this->namespace; } public function getLocatedSource() : LocatedSource { return $this->locatedSource; } } autoloadSourceLocator = $autoloadSourceLocator; $this->reflectionClassSourceLocator = $reflectionClassSourceLocator; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { if (!$identifier->isClass()) { return null; } $className = $identifier->getName(); if (class_exists($className, \false) || interface_exists($className, \false) || trait_exists($className, \false)) { return null; } $autoloadFunctions = autoloadFunctions(); foreach ($autoloadFunctions as $autoloadFunction) { $autoloadFunction($className); $reflection = $this->autoloadSourceLocator->locateIdentifier($reflector, $identifier); if ($reflection !== null) { return $reflection; } $reflection = $this->reflectionClassSourceLocator->locateIdentifier($reflector, $identifier); if ($reflection !== null) { return $reflection; } } return null; } public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return []; } } sourceLocator = $sourceLocator; $this->phpStormStubsSourceStubber = $phpStormStubsSourceStubber; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { if ($identifier->isClass()) { if ($this->phpStormStubsSourceStubber->isPresentClass($identifier->getName()) === \false) { return null; } } if ($identifier->isFunction()) { if ($this->phpStormStubsSourceStubber->isPresentFunction($identifier->getName()) === \false) { return null; } } return $this->sourceLocator->locateIdentifier($reflector, $identifier); } public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return $this->sourceLocator->locateIdentifiersByType($reflector, $identifierType); } } >> */ private $classNodes; /** @var array>> */ private $functionNodes; /** @var array>> */ private $constantNodes; /** * @var ?Node\Stmt\Namespace_ */ private $currentNamespaceNode = null; public function enterNode(Node $node) : ?int { if ($node instanceof Namespace_) { $this->currentNamespaceNode = $node; return null; } if ($node instanceof Node\Stmt\ClassLike) { if ($node->name !== null) { $fullClassName = $node->name->toString(); if ($this->currentNamespaceNode !== null && $this->currentNamespaceNode->name !== null) { $fullClassName = $this->currentNamespaceNode->name . '\\' . $fullClassName; } $this->classNodes[strtolower($fullClassName)][] = new \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNode($node, $this->currentNamespaceNode, new LocatedSource($this->contents, $fullClassName, $this->fileName)); } return NodeTraverser::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Stmt\Function_) { if ($node->namespacedName !== null) { $functionName = $node->namespacedName->toString(); $this->functionNodes[strtolower($functionName)][] = new \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNode($node, $this->currentNamespaceNode, new LocatedSource($this->contents, $functionName, $this->fileName)); } return NodeTraverser::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Stmt\Const_) { foreach ($node->consts as $const) { if ($const->namespacedName === null) { continue; } $this->constantNodes[ConstantNameHelper::normalize($const->namespacedName->toString())][] = new \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNode($node, $this->currentNamespaceNode, new LocatedSource($this->contents, null, $this->fileName)); } return NodeTraverser::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Expr\FuncCall) { try { ConstantNodeChecker::assertValidDefineFunctionCall($node); } catch (InvalidConstantNode $e) { return null; } /** @var Node\Scalar\String_ $nameNode */ $nameNode = $node->getArgs()[0]->value; $constantName = $nameNode->value; $constantNode = new \PHPStan\Reflection\BetterReflection\SourceLocator\FetchedNode($node, $this->currentNamespaceNode, new LocatedSource($this->contents, $constantName, $this->fileName)); $this->constantNodes[ConstantNameHelper::normalize($constantName)][] = $constantNode; return NodeTraverser::DONT_TRAVERSE_CHILDREN; } return null; } /** * @return null */ public function leaveNode(Node $node) { if (!$node instanceof Namespace_) { return null; } $this->currentNamespaceNode = null; return null; } /** * @return array>> */ public function getClassNodes() : array { return $this->classNodes; } /** * @return array>> */ public function getFunctionNodes() : array { return $this->functionNodes; } /** * @return array>> */ public function getConstantNodes() : array { return $this->constantNodes; } public function reset(string $fileName, string $contents) : void { $this->classNodes = []; $this->functionNodes = []; $this->constantNodes = []; $this->fileName = $fileName; $this->contents = $contents; } } sourceLocator = $sourceLocator; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { if ($identifier->isClass()) { $className = $identifier->getName(); if (!class_exists($className, \false)) { return $this->sourceLocator->locateIdentifier($reflector, $identifier); } $reflection = new ReflectionClass($className); if ($reflection->getName() === 'ReturnTypeWillChange') { return $this->sourceLocator->locateIdentifier($reflector, $identifier); } if ($reflection->getFileName() === \false) { return $this->sourceLocator->locateIdentifier($reflector, $identifier); } return null; } return $this->sourceLocator->locateIdentifier($reflector, $identifier); } public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return $this->sourceLocator->locateIdentifiersByType($reflector, $identifierType); } } optimizedDirectorySourceLocatorRepository = $optimizedDirectorySourceLocatorRepository; $this->optimizedPsrAutoloaderLocatorFactory = $optimizedPsrAutoloaderLocatorFactory; $this->optimizedDirectorySourceLocatorFactory = $optimizedDirectorySourceLocatorFactory; $this->phpVersion = $phpVersion; } public function create(string $projectInstallationPath) : ?SourceLocator { $composer = ComposerHelper::getComposerConfig($projectInstallationPath); if ($composer === null) { return null; } $vendorDirectory = ComposerHelper::getVendorDirFromComposerConfig($projectInstallationPath, $composer); $installedJsonPath = $vendorDirectory . '/composer/installed.json'; if (!is_file($installedJsonPath)) { return null; } $installedJsonDirectoryPath = dirname($installedJsonPath); try { $installedJsonContents = FileReader::read($installedJsonPath); $installedJson = Json::decode($installedJsonContents, Json::FORCE_ARRAY); } catch (CouldNotReadFileException|JsonException $e) { return null; } $installed = $installedJson['packages'] ?? $installedJson; $dev = (bool) ($installedJson['dev'] ?? \true); $classMapPaths = array_merge($this->prefixPaths($this->packageToClassMapPaths($composer), $projectInstallationPath . '/'), $dev ? $this->prefixPaths($this->packageToClassMapPaths($composer, 'autoload-dev'), $projectInstallationPath . '/') : [], ...array_map(function (array $package) use($installedJsonDirectoryPath, $vendorDirectory) : array { return $this->prefixPaths($this->packageToClassMapPaths($package), $this->packagePrefixPath($installedJsonDirectoryPath, $package, $vendorDirectory)); }, $installed)); $filePaths = array_merge($this->prefixPaths($this->packageToFilePaths($composer), $projectInstallationPath . '/'), $dev ? $this->prefixPaths($this->packageToFilePaths($composer, 'autoload-dev'), $projectInstallationPath . '/') : [], ...array_map(function (array $package) use($installedJsonDirectoryPath, $vendorDirectory) : array { return $this->prefixPaths($this->packageToFilePaths($package), $this->packagePrefixPath($installedJsonDirectoryPath, $package, $vendorDirectory)); }, $installed)); $locators = []; $locators[] = $this->optimizedPsrAutoloaderLocatorFactory->create(Psr4Mapping::fromArrayMappings(array_merge_recursive($this->prefixWithInstallationPath($this->packageToPsr4AutoloadNamespaces($composer), $projectInstallationPath), $dev ? $this->prefixWithInstallationPath($this->packageToPsr4AutoloadNamespaces($composer, 'autoload-dev'), $projectInstallationPath) : [], ...array_map(function (array $package) use($installedJsonDirectoryPath, $vendorDirectory) : array { return $this->prefixWithPackagePath($this->packageToPsr4AutoloadNamespaces($package), $installedJsonDirectoryPath, $package, $vendorDirectory); }, $installed)))); $locators[] = $this->optimizedPsrAutoloaderLocatorFactory->create(Psr0Mapping::fromArrayMappings(array_merge_recursive($this->prefixWithInstallationPath($this->packageToPsr0AutoloadNamespaces($composer), $projectInstallationPath), $dev ? $this->prefixWithInstallationPath($this->packageToPsr0AutoloadNamespaces($composer, 'autoload-dev'), $projectInstallationPath) : [], ...array_map(function (array $package) use($installedJsonDirectoryPath, $vendorDirectory) : array { return $this->prefixWithPackagePath($this->packageToPsr0AutoloadNamespaces($package), $installedJsonDirectoryPath, $package, $vendorDirectory); }, $installed)))); $files = []; foreach ($classMapPaths as $classMapPath) { if (is_dir($classMapPath)) { $locators[] = $this->optimizedDirectorySourceLocatorRepository->getOrCreate($classMapPath); continue; } if (!is_file($classMapPath)) { continue; } $files[] = $classMapPath; } foreach ($filePaths as $file) { if (!is_file($file)) { continue; } $files[] = $file; } if (count($files) > 0) { $locators[] = $this->optimizedDirectorySourceLocatorFactory->createByFiles($files); } $binDir = ComposerHelper::getBinDirFromComposerConfig($projectInstallationPath, $composer); $phpunitBridgeDir = $binDir . '/.phpunit'; if (!is_dir($vendorDirectory . '/phpunit/phpunit') && is_dir($phpunitBridgeDir)) { // from https://github.com/composer/composer/blob/8ff237afb61b8766efa576b8ae1cc8560c8aed96/phpstan/locate-phpunit-autoloader.php $bestDirFound = null; $phpunitBridgeDirectories = glob($phpunitBridgeDir . '/phpunit-*', GLOB_ONLYDIR); if ($phpunitBridgeDirectories !== \false) { foreach (array_reverse($phpunitBridgeDirectories) as $dir) { $bestDirFound = $dir; if ($this->phpVersion->getVersionId() >= 80100 && str_contains($dir, 'phpunit-10')) { break; } if ($this->phpVersion->getVersionId() >= 80000) { if (str_contains($dir, 'phpunit-9')) { break; } continue; } if (str_contains($dir, 'phpunit-8') || str_contains($dir, 'phpunit-7')) { break; } } if ($bestDirFound !== null) { $phpunitBridgeLocator = $this->create($bestDirFound); if ($phpunitBridgeLocator !== null) { $locators[] = $phpunitBridgeLocator; } } } } return new AggregateSourceLocator($locators); } /** * @param mixed[] $package * * @return array> */ private function packageToPsr4AutoloadNamespaces(array $package, string $autoloadSection = 'autoload') : array { return array_map(static function ($namespacePaths) : array { return (array) $namespacePaths; }, $package[$autoloadSection]['psr-4'] ?? []); } /** * @param mixed[] $package * * @return array> */ private function packageToPsr0AutoloadNamespaces(array $package, string $autoloadSection = 'autoload') : array { return array_map(static function ($namespacePaths) : array { return (array) $namespacePaths; }, $package[$autoloadSection]['psr-0'] ?? []); } /** * @param mixed[] $package * * @return array */ private function packageToClassMapPaths(array $package, string $autoloadSection = 'autoload') : array { return $package[$autoloadSection]['classmap'] ?? []; } /** * @param mixed[] $package * * @return array */ private function packageToFilePaths(array $package, string $autoloadSection = 'autoload') : array { return $package[$autoloadSection]['files'] ?? []; } /** * @param mixed[] $package */ private function packagePrefixPath(string $installedJsonDirectoryPath, array $package, string $vendorDirectory) : string { if (array_key_exists('install-path', $package)) { return $installedJsonDirectoryPath . '/' . $package['install-path'] . '/'; } return $vendorDirectory . '/' . $package['name'] . '/'; } /** * @param array> $paths * @param array> $package * * @return array> */ private function prefixWithPackagePath(array $paths, string $installedJsonDirectoryPath, array $package, string $vendorDirectory) : array { $prefix = $this->packagePrefixPath($installedJsonDirectoryPath, $package, $vendorDirectory); return array_map(function (array $paths) use($prefix) : array { return $this->prefixPaths($paths, $prefix); }, $paths); } /** * @param array> $paths * * @return array> */ private function prefixWithInstallationPath(array $paths, string $trimmedInstallationPath) : array { return array_map(function (array $paths) use($trimmedInstallationPath) : array { return $this->prefixPaths($paths, $trimmedInstallationPath . '/'); }, $paths); } /** * @param array $paths * * @return array */ private function prefixPaths(array $paths, string $prefix) : array { return array_map(static function (string $path) use($prefix) : string { return $prefix . $path; }, $paths); } } */ private $locators = []; public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocatorFactory $factory) { $this->factory = $factory; } public function getOrCreate(string $directory) : \PHPStan\Reflection\BetterReflection\SourceLocator\NewOptimizedDirectorySourceLocator { if (array_key_exists($directory, $this->locators)) { return $this->locators[$directory]; } $this->locators[$directory] = $this->factory->createByDirectory($directory); return $this->locators[$directory]; } } * @see https://github.com/composer/composer/pull/10107 */ final class PhpFileCleaner { /** @var array */ private $typeConfig = []; /** * @var string */ private $restPattern; /** * @var string */ private $contents = ''; /** * @var int */ private $len = 0; /** * @var int */ private $index = 0; public function __construct() { foreach (['class', 'interface', 'trait', 'enum'] as $type) { $this->typeConfig[$type[0]] = ['name' => $type, 'length' => strlen($type), 'pattern' => '{.\\b(?])' . $type . '\\s++[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\-]*+}Ais']; } $this->restPattern = '{[^{}?"\'typeConfig)) . ']+}A'; } public function clean(string $contents, int $maxMatches) : string { $this->contents = $contents; $this->len = strlen($contents); $this->index = 0; $inType = \false; $typeLevel = 0; $inDefine = \false; $clean = ''; while ($this->index < $this->len) { $this->skipToPhp(); $clean .= 'index < $this->len) { $char = $this->contents[$this->index]; if ($char === '?' && $this->peek('>')) { $clean .= '?>'; $this->index += 2; continue 2; } if (in_array($char, ['"', "'"], \true)) { if ($inDefine) { $clean .= $char . $this->consumeString($char); $inDefine = \false; } else { $this->skipString($char); $clean .= 'null'; } continue; } if ($char === '{') { if ($inType) { $typeLevel++; } $clean .= $char; $this->index++; continue; } if ($char === '}') { if ($inType) { $typeLevel--; if ($typeLevel === 0) { $inType = \false; } } $clean .= $char; $this->index++; 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 ($inType && $char === 'c' && $this->match('~.\\b(?])const(\\s++[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\-]*+)~Ais', $match, $this->index - 1)) { // It's invalid PHP but it does not matter $clean .= 'class_const' . $match[1]; $this->index += strlen($match[0]) - 1; continue; } if ($char === 'd' && $this->match('~.\\b(?])define\\s*+\\(~Ais', $match, $this->index - 1)) { $inDefine = \true; $clean .= $match[0]; $this->index += strlen($match[0]) - 1; continue; } if (isset($this->typeConfig[$char])) { $type = $this->typeConfig[$char]; if (substr($this->contents, $this->index, $type['length']) === $type['name']) { if ($maxMatches === 1 && $this->match($type['pattern'], $match, $this->index - 1)) { return $clean . $match[0]; } $inType = \true; } } $this->index += 1; if ($this->match($this->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 consumeString(string $delimiter) : string { $string = ''; $this->index += 1; while ($this->index < $this->len) { if ($this->contents[$this->index] === '\\' && ($this->peek('\\') || $this->peek($delimiter))) { $string .= $this->contents[$this->index]; $string .= $this->contents[$this->index + 1]; $this->index += 2; continue; } if ($this->contents[$this->index] === $delimiter) { $string .= $delimiter; $this->index += 1; break; } $string .= $this->contents[$this->index]; $this->index += 1; } return $string; } 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 (in_array($this->contents[$this->index], ["\r", "\n"], \true)) { 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 string[]|null $match * @param-out string[] $match */ private function match(string $regex, ?array &$match = null, ?int $offset = null) : bool { return preg_match($regex, $this->contents, $match, 0, $offset ?? $this->index) === 1; } } astLocator = $astLocator; $this->reflectionSourceStubber = $reflectionSourceStubber; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { if (!$identifier->isClass()) { return null; } /** @var class-string $className */ $className = $identifier->getName(); $stub = $this->reflectionSourceStubber->generateClassStub($className); if ($stub === null) { return null; } $reflection = new ReflectionClass($className); return $this->astLocator->findReflection($reflector, new LocatedSource($stub->getStub(), $reflection->getName(), null), new Identifier($reflection->getName(), new IdentifierType(IdentifierType::IDENTIFIER_CLASS))); } public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return []; } } */ private $locators = []; public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocatorFactory $factory) { $this->factory = $factory; } public function getOrCreate(string $fileName) : \PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocator { if (array_key_exists($fileName, $this->locators)) { return $this->locators[$fileName]; } $this->locators[$fileName] = $this->factory->create($fileName); return $this->locators[$fileName]; } } originalSourceLocator = $originalSourceLocator; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { if (!$identifier->isClass()) { return $this->originalSourceLocator->locateIdentifier($reflector, $identifier); } if (class_exists($identifier->getName(), \false) || interface_exists($identifier->getName(), \false) || trait_exists($identifier->getName(), \false)) { $classReflection = new CoreReflectionClass($identifier->getName()); return $this->originalSourceLocator->locateIdentifier($reflector, new Identifier($classReflection->getName(), $identifier->getType())); } return $this->originalSourceLocator->locateIdentifier($reflector, $identifier); } public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return $this->originalSourceLocator->locateIdentifiersByType($reflector, $identifierType); } } readFromFile = \false; $this->seekPosition = 0; return $exists; } /** * Since we allow our wrapper's stream_open() to succeed, we need to * simulate a successful read so autoloaders with require() don't explode. * * @param int $count * */ public function stream_read($count) : string { $this->readFromFile = \true; // Dummy return value that is also valid PHP for require(). We'll read // and process the file elsewhere, so it's OK to provide dummy data for // this read. return ''; } /** * Since we allowed the open to succeed, we should allow the close to occur * as well. * */ public function stream_close() : void { // no op } /** * Required for `require_once` and `include_once` to work per PHP.net * comment referenced below. We delegate to url_stat(). * * @see https://www.php.net/manual/en/function.stream-wrapper-register.php#51855 * * @return mixed[]|bool */ public function stream_stat() { if (self::$autoloadLocatedFiles === []) { return \false; } return $this->url_stat(self::$autoloadLocatedFiles[0], STREAM_URL_STAT_QUIET); } /** * url_stat is triggered by calls like "file_exists". The call to "file_exists" must not be overloaded. * This function restores the original "file" stream, issues a call to "stat" to get the real results, * and then re-registers the AutoloadSourceLocator stream wrapper. * * @internal do not call this method directly! This is stream wrapper * voodoo logic that you **DO NOT** want to touch! * * @see https://php.net/manual/en/class.streamwrapper.php * @see https://php.net/manual/en/streamwrapper.url-stat.php * * @param string $path * @param int $flags * * @return mixed[]|bool */ public function url_stat($path, $flags) { return $this->invokeWithRealFileStreamWrapper(static function ($path, $flags) { if (($flags & STREAM_URL_STAT_QUIET) !== 0) { return @stat($path); } return stat($path); }, [$path, $flags]); } /** * @param mixed[] $args * @return mixed */ private function invokeWithRealFileStreamWrapper(callable $cb, array $args) { if (self::$registeredStreamWrapperProtocols === null) { throw new ShouldNotHappenException(self::class . ' not registered: cannot operate. Do not call this method directly.'); } foreach (self::$registeredStreamWrapperProtocols as $protocol) { stream_wrapper_restore($protocol); } $result = $cb(...$args); foreach (self::$registeredStreamWrapperProtocols as $protocol) { stream_wrapper_unregister($protocol); stream_wrapper_register($protocol, self::class); } return $result; } /** * Simulates behavior of reading from an empty file. * */ public function stream_eof() : bool { return $this->readFromFile; } public function stream_flush() : bool { return \true; } public function stream_tell() : int { return $this->seekPosition; } /** * @param int $offset * @param int $whence */ public function stream_seek($offset, $whence) : bool { switch ($whence) { // Behavior is the same for a zero-length file case SEEK_SET: case SEEK_END: if ($offset < 0) { return \false; } $this->seekPosition = $offset; return \true; case SEEK_CUR: if ($offset < 0) { return \false; } $this->seekPosition += $offset; return \true; default: return \false; } } /** * @param int $option * @param int $arg1 * @param int $arg2 */ public function stream_set_option($option, $arg1, $arg2) : bool { return \false; } public function dir_opendir(string $path, int $options) : bool { return is_dir($path); } public function dir_readdir() : string { return ''; } } , functions: array, constants: array}|null */ private $presentSymbols = null; public function __construct(\PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher $fileNodesFetcher, string $fileName) { $this->fileNodesFetcher = $fileNodesFetcher; $this->fileName = $fileName; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?Reflection { if ($this->presentSymbols !== null) { if ($identifier->isClass()) { $className = strtolower($identifier->getName()); if (!array_key_exists($className, $this->presentSymbols['classes'])) { return null; } } if ($identifier->isFunction()) { $className = strtolower($identifier->getName()); if (!array_key_exists($className, $this->presentSymbols['functions'])) { return null; } } if ($identifier->isConstant()) { $constantName = ConstantNameHelper::normalize($identifier->getName()); if (!array_key_exists($constantName, $this->presentSymbols['constants'])) { return null; } } } $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($this->fileName); if ($this->presentSymbols === null) { $presentSymbols = ['classes' => [], 'functions' => [], 'constants' => []]; foreach (array_keys($fetchedNodesResult->getClassNodes()) as $className) { $presentSymbols['classes'][$className] = \true; } foreach (array_keys($fetchedNodesResult->getFunctionNodes()) as $functionName) { $presentSymbols['functions'][$functionName] = \true; } foreach (array_keys($fetchedNodesResult->getConstantNodes()) as $constantName) { $presentSymbols['constants'][$constantName] = \true; } $this->presentSymbols = $presentSymbols; } $nodeToReflection = new NodeToReflection(); if ($identifier->isClass()) { $classNodes = $fetchedNodesResult->getClassNodes(); $className = strtolower($identifier->getName()); if (!array_key_exists($className, $classNodes)) { return null; } foreach ($classNodes[$className] as $classNode) { $classReflection = $nodeToReflection->__invoke($reflector, $classNode->getNode(), $classNode->getLocatedSource(), $classNode->getNamespace()); if (!$classReflection instanceof ReflectionClass) { throw new ShouldNotHappenException(); } return $classReflection; } } if ($identifier->isFunction()) { $functionNodes = $fetchedNodesResult->getFunctionNodes(); $functionName = strtolower($identifier->getName()); if (!array_key_exists($functionName, $functionNodes)) { return null; } foreach ($functionNodes[$functionName] as $functionNode) { $functionReflection = $nodeToReflection->__invoke($reflector, $functionNode->getNode(), $functionNode->getLocatedSource(), $functionNode->getNamespace()); if (!$functionReflection instanceof ReflectionFunction) { throw new ShouldNotHappenException(); } return $functionReflection; } } if ($identifier->isConstant()) { $constantNodes = $fetchedNodesResult->getConstantNodes(); $constantName = ConstantNameHelper::normalize($identifier->getName()); if (!array_key_exists($constantName, $constantNodes)) { return null; } foreach ($constantNodes[$constantName] as $fetchedConstantNode) { $constantNode = $fetchedConstantNode->getNode(); $positionInNode = null; if ($constantNode instanceof Const_) { foreach ($constantNode->consts as $constPosition => $const) { if ($const->namespacedName === null) { throw new ShouldNotHappenException(); } if (ConstantNameHelper::normalize($const->namespacedName->toString()) === $constantName) { /** @var int $positionInNode */ $positionInNode = $constPosition; break; } } if ($positionInNode === null) { throw new ShouldNotHappenException(); } } $constantReflection = $nodeToReflection->__invoke($reflector, $fetchedConstantNode->getNode(), $fetchedConstantNode->getLocatedSource(), $fetchedConstantNode->getNamespace(), $positionInNode); if (!$constantReflection instanceof ReflectionConstant) { throw new ShouldNotHappenException(); } return $constantReflection; } return null; } throw new ShouldNotHappenException(); } public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($this->fileName); $nodeToReflection = new NodeToReflection(); $reflections = []; if ($identifierType->isClass()) { $classNodes = $fetchedNodesResult->getClassNodes(); foreach ($classNodes as $classNodesArray) { foreach ($classNodesArray as $classNode) { $classReflection = $nodeToReflection->__invoke($reflector, $classNode->getNode(), $classNode->getLocatedSource(), $classNode->getNamespace()); if (!$classReflection instanceof ReflectionClass) { throw new ShouldNotHappenException(); } $reflections[] = $classReflection; } } } if ($identifierType->isFunction()) { $functionNodes = $fetchedNodesResult->getFunctionNodes(); foreach ($functionNodes as $functionNodesArray) { foreach ($functionNodesArray as $functionNode) { $functionReflection = $nodeToReflection->__invoke($reflector, $functionNode->getNode(), $functionNode->getLocatedSource(), $functionNode->getNamespace()); $reflections[] = $functionReflection; } } } if ($identifierType->isConstant()) { $constantNodes = $fetchedNodesResult->getConstantNodes(); foreach ($constantNodes as $constantNodesArray) { foreach ($constantNodesArray as $fetchedConstantNode) { $constantNode = $fetchedConstantNode->getNode(); if ($constantNode instanceof Const_) { foreach ($constantNode->consts as $constPosition => $const) { if ($const->namespacedName === null) { throw new ShouldNotHappenException(); } $constantReflection = $nodeToReflection->__invoke($reflector, $constantNode, $fetchedConstantNode->getLocatedSource(), $fetchedConstantNode->getNamespace(), $constPosition); if (!$constantReflection instanceof ReflectionConstant) { throw new ShouldNotHappenException(); } $reflections[] = $constantReflection; } continue; } $constantReflection = $nodeToReflection->__invoke($reflector, $constantNode, $fetchedConstantNode->getLocatedSource(), $fetchedConstantNode->getNamespace()); if (!$constantReflection instanceof ReflectionConstant) { throw new ShouldNotHappenException(); } $reflections[] = $constantReflection; } } } return $reflections; } } parser = $parser; $this->php8Parser = $php8Parser; $this->phpstormStubsSourceStubber = $phpstormStubsSourceStubber; $this->reflectionSourceStubber = $reflectionSourceStubber; $this->optimizedSingleFileSourceLocatorRepository = $optimizedSingleFileSourceLocatorRepository; $this->optimizedDirectorySourceLocatorRepository = $optimizedDirectorySourceLocatorRepository; $this->composerJsonAndInstalledJsonSourceLocatorMaker = $composerJsonAndInstalledJsonSourceLocatorMaker; $this->optimizedPsrAutoloaderLocatorFactory = $optimizedPsrAutoloaderLocatorFactory; $this->fileNodesFetcher = $fileNodesFetcher; $this->scanFiles = $scanFiles; $this->scanDirectories = $scanDirectories; $this->analysedPaths = $analysedPaths; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; $this->analysedPathsFromConfig = $analysedPathsFromConfig; $this->playgroundMode = $playgroundMode; $this->singleReflectionFile = $singleReflectionFile; } public function create() : SourceLocator { $locators = []; if ($this->singleReflectionFile !== null) { $locators[] = $this->optimizedSingleFileSourceLocatorRepository->getOrCreate($this->singleReflectionFile); } $astLocator = new Locator($this->parser); $locators[] = new AutoloadFunctionsSourceLocator(new AutoloadSourceLocator($this->fileNodesFetcher, \false), new ReflectionClassSourceLocator($astLocator, $this->reflectionSourceStubber)); $analysedDirectories = []; $analysedFiles = []; foreach (array_merge($this->analysedPaths, $this->analysedPathsFromConfig) as $analysedPath) { if (is_file($analysedPath)) { $analysedFiles[] = $analysedPath; continue; } if (!is_dir($analysedPath)) { continue; } $analysedDirectories[] = $analysedPath; } $fileLocators = []; $analysedFiles = array_unique(array_merge($analysedFiles, $this->scanFiles)); foreach ($analysedFiles as $analysedFile) { $fileLocators[] = $this->optimizedSingleFileSourceLocatorRepository->getOrCreate($analysedFile); } $directories = array_unique(array_merge($analysedDirectories, $this->scanDirectories)); foreach ($directories as $directory) { $fileLocators[] = $this->optimizedDirectorySourceLocatorRepository->getOrCreate($directory); } $astPhp8Locator = new Locator($this->php8Parser); foreach ($this->composerAutoloaderProjectPaths as $composerAutoloaderProjectPath) { $locator = $this->composerJsonAndInstalledJsonSourceLocatorMaker->create($composerAutoloaderProjectPath); if ($locator === null) { continue; } $fileLocators[] = $locator; } if (extension_loaded('phar')) { $pharProtocolPath = Phar::running(); if ($pharProtocolPath !== '') { $mappings = ['PHPStan\\BetterReflection\\' => [$pharProtocolPath . '/vendor/ondrejmirtes/better-reflection/src/']]; if ($this->playgroundMode) { $mappings['PHPStan\\'] = [$pharProtocolPath . '/src/']; } else { $mappings['PHPStan\\Testing\\'] = [$pharProtocolPath . '/src/Testing/']; } $fileLocators[] = $this->optimizedPsrAutoloaderLocatorFactory->create(Psr4Mapping::fromArrayMappings($mappings)); } } $locators[] = new RewriteClassAliasSourceLocator(new AggregateSourceLocator($fileLocators)); $locators[] = new SkipClassAliasSourceLocator(new PhpInternalSourceLocator($astPhp8Locator, $this->phpstormStubsSourceStubber)); $locators[] = new AutoloadSourceLocator($this->fileNodesFetcher, \true); $locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber); $locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber); return new MemoizingSourceLocator(new AggregateSourceLocator($locators)); } } */ private $cachedConstants = []; /** * @param string[] $universalObjectCratesClasses */ public function __construct(ReflectionProvider\ReflectionProviderProvider $reflectionProviderProvider, InitializerExprTypeResolver $initializerExprTypeResolver, ClassReflectionExtensionRegistryProvider $classReflectionExtensionRegistryProvider, Reflector $reflector, FileTypeMapper $fileTypeMapper, PhpDocInheritanceResolver $phpDocInheritanceResolver, PhpVersion $phpVersion, NativeFunctionReflectionProvider $nativeFunctionReflectionProvider, StubPhpDocProvider $stubPhpDocProvider, FunctionReflectionFactory $functionReflectionFactory, RelativePathHelper $relativePathHelper, AnonymousClassNameHelper $anonymousClassNameHelper, FileHelper $fileHelper, PhpStormStubsSourceStubber $phpstormStubsSourceStubber, SignatureMapProvider $signatureMapProvider, array $universalObjectCratesClasses) { $this->reflectionProviderProvider = $reflectionProviderProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->classReflectionExtensionRegistryProvider = $classReflectionExtensionRegistryProvider; $this->reflector = $reflector; $this->fileTypeMapper = $fileTypeMapper; $this->phpDocInheritanceResolver = $phpDocInheritanceResolver; $this->phpVersion = $phpVersion; $this->nativeFunctionReflectionProvider = $nativeFunctionReflectionProvider; $this->stubPhpDocProvider = $stubPhpDocProvider; $this->functionReflectionFactory = $functionReflectionFactory; $this->relativePathHelper = $relativePathHelper; $this->anonymousClassNameHelper = $anonymousClassNameHelper; $this->fileHelper = $fileHelper; $this->phpstormStubsSourceStubber = $phpstormStubsSourceStubber; $this->signatureMapProvider = $signatureMapProvider; $this->universalObjectCratesClasses = $universalObjectCratesClasses; } public function hasClass(string $className) : bool { if (isset(self::$anonymousClasses[$className])) { return \true; } if (!ClassNameHelper::isValidClassName($className)) { return \false; } try { $this->reflector->reflectClass($className); return \true; } catch (IdentifierNotFound $e) { return \false; } catch (InvalidIdentifierName $e) { return \false; } } public function getClass(string $className) : ClassReflection { if (isset(self::$anonymousClasses[$className])) { return self::$anonymousClasses[$className]; } try { $reflectionClass = $this->reflector->reflectClass($className); } catch (IdentifierNotFound|InvalidIdentifierName $e) { throw new ClassNotFoundException($className); } $reflectionClassName = strtolower($reflectionClass->getName()); if (array_key_exists($reflectionClassName, $this->classReflections)) { return $this->classReflections[$reflectionClassName]; } $enumAdapter = base64_decode('UEhQU3RhblxCZXR0ZXJSZWZsZWN0aW9uXFJlZmxlY3Rpb25cQWRhcHRlclxSZWZsZWN0aW9uRW51bQ==', \true); $classReflection = new ClassReflection($this->reflectionProviderProvider->getReflectionProvider(), $this->initializerExprTypeResolver, $this->fileTypeMapper, $this->stubPhpDocProvider, $this->phpDocInheritanceResolver, $this->phpVersion, $this->signatureMapProvider, $this->classReflectionExtensionRegistryProvider->getRegistry()->getPropertiesClassReflectionExtensions(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getMethodsClassReflectionExtensions(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getAllowedSubTypesClassReflectionExtensions(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsPropertyClassReflectionExtension(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsMethodsClassReflectionExtension(), $reflectionClass->getName(), $reflectionClass instanceof ReflectionEnum && PHP_VERSION_ID >= 80000 ? new $enumAdapter($reflectionClass) : new ReflectionClass($reflectionClass), null, null, $this->stubPhpDocProvider->findClassPhpDoc($reflectionClass->getName()), $this->universalObjectCratesClasses); $this->classReflections[$reflectionClassName] = $classReflection; return $classReflection; } public function getClassName(string $className) : string { if (!$this->hasClass($className)) { throw new ClassNotFoundException($className); } if (isset(self::$anonymousClasses[$className])) { return self::$anonymousClasses[$className]->getDisplayName(); } $reflectionClass = $this->reflector->reflectClass($className); return $reflectionClass->getName(); } public function supportsAnonymousClasses() : bool { return \true; } public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $scope) : ClassReflection { if (isset($classNode->namespacedName)) { throw new ShouldNotHappenException(); } if (!$scope->isInTrait()) { $scopeFile = $scope->getFile(); } else { $scopeFile = $scope->getTraitReflection()->getFileName(); if ($scopeFile === null) { $scopeFile = $scope->getFile(); } } $filename = $this->fileHelper->normalizePath($this->relativePathHelper->getRelativePath($scopeFile), '/'); $className = $this->anonymousClassNameHelper->getAnonymousClassName($classNode, $scopeFile); $classNode->name = new Node\Identifier($className); if (isset(self::$anonymousClasses[$className])) { return self::$anonymousClasses[$className]; } $reflectionClass = \PHPStan\BetterReflection\Reflection\ReflectionClass::createFromNode($this->reflector, $classNode, new LocatedSource(FileReader::read($scopeFile), $className, $scopeFile), null); /** @var int|null $classLineIndex */ $classLineIndex = $classNode->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX); if ($classLineIndex === null) { $displayName = sprintf('class@anonymous/%s:%s', $filename, $classNode->getStartLine()); } else { $displayName = sprintf('class@anonymous/%s:%s:%d', $filename, $classNode->getStartLine(), $classLineIndex); } self::$anonymousClasses[$className] = new ClassReflection($this->reflectionProviderProvider->getReflectionProvider(), $this->initializerExprTypeResolver, $this->fileTypeMapper, $this->stubPhpDocProvider, $this->phpDocInheritanceResolver, $this->phpVersion, $this->signatureMapProvider, $this->classReflectionExtensionRegistryProvider->getRegistry()->getPropertiesClassReflectionExtensions(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getMethodsClassReflectionExtensions(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getAllowedSubTypesClassReflectionExtensions(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsPropertyClassReflectionExtension(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsMethodsClassReflectionExtension(), $displayName, new ReflectionClass($reflectionClass), $scopeFile, null, $this->stubPhpDocProvider->findClassPhpDoc($className), $this->universalObjectCratesClasses); $this->classReflections[$className] = self::$anonymousClasses[$className]; return self::$anonymousClasses[$className]; } public function hasFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : bool { return $this->resolveFunctionName($nameNode, $namespaceAnswerer) !== null; } public function getFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : FunctionReflection { $functionName = $this->resolveFunctionName($nameNode, $namespaceAnswerer); if ($functionName === null) { throw new FunctionNotFoundException((string) $nameNode); } $lowerCasedFunctionName = strtolower($functionName); if (isset($this->functionReflections[$lowerCasedFunctionName])) { return $this->functionReflections[$lowerCasedFunctionName]; } if (in_array($lowerCasedFunctionName, ['exit', 'die'], \true)) { return $this->functionReflections[$lowerCasedFunctionName] = new ExitFunctionReflection($lowerCasedFunctionName); } $nativeFunctionReflection = $this->nativeFunctionReflectionProvider->findFunctionReflection($lowerCasedFunctionName); if ($nativeFunctionReflection !== null) { $this->functionReflections[$lowerCasedFunctionName] = $nativeFunctionReflection; return $nativeFunctionReflection; } $this->functionReflections[$lowerCasedFunctionName] = $this->getCustomFunction($functionName); return $this->functionReflections[$lowerCasedFunctionName]; } private function getCustomFunction(string $functionName) : PhpFunctionReflection { $reflectionFunction = new ReflectionFunction($this->reflector->reflectFunction($functionName)); $templateTypeMap = TemplateTypeMap::createEmpty(); $phpDocParameterTypes = []; $phpDocReturnTag = null; $phpDocThrowsTag = null; $deprecatedTag = null; $isDeprecated = \false; $isInternal = \false; $isFinal = \false; $isPure = null; $asserts = Assertions::createEmpty(); $acceptsNamedArguments = \true; $phpDocComment = null; $phpDocParameterOutTags = []; $phpDocParameterImmediatelyInvokedCallable = []; $phpDocParameterClosureThisTypeTags = []; $resolvedPhpDoc = $this->stubPhpDocProvider->findFunctionPhpDoc($reflectionFunction->getName(), array_map(static function (ReflectionParameter $parameter) : string { return $parameter->getName(); }, $reflectionFunction->getParameters())); if ($resolvedPhpDoc === null && $reflectionFunction->getFileName() !== \false && $reflectionFunction->getDocComment() !== \false) { $docComment = $reflectionFunction->getDocComment(); $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($reflectionFunction->getFileName(), null, null, $reflectionFunction->getName(), $docComment); } if ($resolvedPhpDoc !== null) { $templateTypeMap = $resolvedPhpDoc->getTemplateTypeMap(); $phpDocParameterTypes = array_map(static function ($tag) { return $tag->getType(); }, $resolvedPhpDoc->getParamTags()); $phpDocReturnTag = $resolvedPhpDoc->getReturnTag(); $phpDocThrowsTag = $resolvedPhpDoc->getThrowsTag(); $deprecatedTag = $resolvedPhpDoc->getDeprecatedTag(); $isDeprecated = $resolvedPhpDoc->isDeprecated(); $isInternal = $resolvedPhpDoc->isInternal(); $isFinal = $resolvedPhpDoc->isFinal(); $isPure = $resolvedPhpDoc->isPure(); $asserts = Assertions::createFromResolvedPhpDocBlock($resolvedPhpDoc); if ($resolvedPhpDoc->hasPhpDocString()) { $phpDocComment = $resolvedPhpDoc->getPhpDocString(); } $acceptsNamedArguments = $resolvedPhpDoc->acceptsNamedArguments(); $phpDocParameterOutTags = $resolvedPhpDoc->getParamOutTags(); $phpDocParameterImmediatelyInvokedCallable = $resolvedPhpDoc->getParamsImmediatelyInvokedCallable(); $phpDocParameterClosureThisTypeTags = $resolvedPhpDoc->getParamClosureThisTags(); } return $this->functionReflectionFactory->create($reflectionFunction, $templateTypeMap, $phpDocParameterTypes, $phpDocReturnTag !== null ? $phpDocReturnTag->getType() : null, $phpDocThrowsTag !== null ? $phpDocThrowsTag->getType() : null, $deprecatedTag !== null ? $deprecatedTag->getMessage() : null, $isDeprecated, $isInternal, $isFinal, $reflectionFunction->getFileName() !== \false ? $reflectionFunction->getFileName() : null, $isPure, $asserts, $acceptsNamedArguments, $phpDocComment, array_map(static function (ParamOutTag $paramOutTag) : Type { return $paramOutTag->getType(); }, $phpDocParameterOutTags), $phpDocParameterImmediatelyInvokedCallable, array_map(static function (ParamClosureThisTag $tag) : Type { return $tag->getType(); }, $phpDocParameterClosureThisTypeTags)); } public function resolveFunctionName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : ?string { $name = $nameNode->toLowerString(); if (in_array($name, ['exit', 'die'], \true)) { return $name; } return $this->resolveName($nameNode, function (string $name) : bool { try { $this->reflector->reflectFunction($name); return \true; } catch (IdentifierNotFound $e) { // pass } catch (InvalidIdentifierName $e) { // pass } if ($this->nativeFunctionReflectionProvider->findFunctionReflection($name) !== null) { return $this->phpstormStubsSourceStubber->isPresentFunction($name) !== \false; } return \false; }, $namespaceAnswerer); } public function hasConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : bool { return $this->resolveConstantName($nameNode, $namespaceAnswerer) !== null; } public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : GlobalConstantReflection { $constantName = $this->resolveConstantName($nameNode, $namespaceAnswerer); if ($constantName === null) { throw new ConstantNotFoundException((string) $nameNode); } if (array_key_exists($constantName, $this->cachedConstants)) { return $this->cachedConstants[$constantName]; } $constantReflection = $this->reflector->reflectConstant($constantName); $fileName = $constantReflection->getFileName(); $constantValueType = $this->initializerExprTypeResolver->getType($constantReflection->getValueExpression(), InitializerExprContext::fromGlobalConstant($constantReflection)); $docComment = $constantReflection->getDocComment(); $isDeprecated = TrinaryLogic::createNo(); $deprecatedDescription = null; if ($docComment !== null) { $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($fileName, null, null, null, $docComment); $isDeprecated = TrinaryLogic::createFromBoolean($resolvedPhpDoc->isDeprecated()); if ($resolvedPhpDoc->isDeprecated() && $resolvedPhpDoc->getDeprecatedTag() !== null) { $deprecatedMessage = $resolvedPhpDoc->getDeprecatedTag()->getMessage(); $matches = Strings::match($deprecatedMessage ?? '', '#^(\\d+)\\.(\\d+)(?:\\.(\\d+))?$#'); if ($matches !== null) { $major = $matches[1]; $minor = $matches[2]; $patch = $matches[3] ?? 0; $versionId = sprintf('%d%02d%02d', $major, $minor, $patch); $isDeprecated = TrinaryLogic::createFromBoolean($this->phpVersion->getVersionId() >= $versionId); } else { // filter raw version number messages like in // https://github.com/JetBrains/phpstorm-stubs/blob/9608c953230b08f07b703ecfe459cc58d5421437/filter/filter.php#L478 $deprecatedDescription = $deprecatedMessage; } } } return $this->cachedConstants[$constantName] = new RuntimeConstantReflection($constantName, $constantValueType, $fileName, $isDeprecated, $deprecatedDescription); } public function resolveConstantName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : ?string { return $this->resolveName($nameNode, function (string $name) : bool { try { $this->reflector->reflectConstant($name); return \true; } catch (IdentifierNotFound $e) { // pass } catch (InvalidIdentifierName $e) { // pass } catch (UnableToCompileNode $e) { // pass } return \false; }, $namespaceAnswerer); } /** * @param Closure(string $name): bool $existsCallback */ private function resolveName(Node\Name $nameNode, Closure $existsCallback, ?NamespaceAnswerer $namespaceAnswerer) : ?string { $name = (string) $nameNode; if ($namespaceAnswerer !== null && $namespaceAnswerer->getNamespace() !== null && !$nameNode->isFullyQualified()) { $namespacedName = sprintf('%s\\%s', $namespaceAnswerer->getNamespace(), $name); if ($existsCallback($namespacedName)) { return $namespacedName; } } if ($existsCallback($name)) { return $name; } return null; } } */ private $classReflections = []; /** @var array */ private $constantReflections = []; /** @var array */ private $functionReflections = []; public function __construct(Reflector $reflector) { $this->reflector = $reflector; } public function reflectClass(string $className) : ReflectionClass { $lowerClassName = strtolower($className); if (array_key_exists($lowerClassName, $this->classReflections) && $this->classReflections[$lowerClassName] !== null) { return $this->classReflections[$lowerClassName]; } if (array_key_exists($className, $this->classReflections)) { $classReflection = $this->classReflections[$className]; if ($classReflection === null) { throw IdentifierNotFound::fromIdentifier(new Identifier($className, new IdentifierType(IdentifierType::IDENTIFIER_CLASS))); } return $classReflection; } try { return $this->classReflections[$lowerClassName] = $this->reflector->reflectClass($className); } catch (IdentifierNotFound $e) { $this->classReflections[$className] = null; throw $e; } } public function reflectConstant(string $constantName) : ReflectionConstant { if (array_key_exists($constantName, $this->constantReflections)) { $constantReflection = $this->constantReflections[$constantName]; if ($constantReflection === null) { throw IdentifierNotFound::fromIdentifier(new Identifier($constantName, new IdentifierType(IdentifierType::IDENTIFIER_CONSTANT))); } return $constantReflection; } try { return $this->constantReflections[$constantName] = $this->reflector->reflectConstant($constantName); } catch (IdentifierNotFound $e) { $this->constantReflections[$constantName] = null; throw $e; } } public function reflectFunction(string $functionName) : ReflectionFunction { $lowerFunctionName = strtolower($functionName); if (array_key_exists($lowerFunctionName, $this->functionReflections)) { $functionReflection = $this->functionReflections[$lowerFunctionName]; if ($functionReflection === null) { throw IdentifierNotFound::fromIdentifier(new Identifier($functionName, new IdentifierType(IdentifierType::IDENTIFIER_FUNCTION))); } return $functionReflection; } try { return $this->functionReflections[$lowerFunctionName] = $this->reflector->reflectFunction($functionName); } catch (IdentifierNotFound $e) { $this->functionReflections[$lowerFunctionName] = null; throw $e; } } public function reflectAllClasses() : iterable { return $this->reflector->reflectAllClasses(); } public function reflectAllFunctions() : iterable { return $this->reflector->reflectAllFunctions(); } public function reflectAllConstants() : iterable { return $this->reflector->reflectAllConstants(); } } phpParser = $phpParser; $this->printer = $printer; $this->phpVersion = $phpVersion; } public function create() : PhpStormStubsSourceStubber { return new PhpStormStubsSourceStubber($this->phpParser, $this->printer, $this->phpVersion->getVersionId()); } } printer = $printer; $this->phpVersion = $phpVersion; } public function create() : ReflectionSourceStubber { return new ReflectionSourceStubber($this->printer, $this->phpVersion->getVersionId()); } } */ private $passedArgs; /** @var ParameterReflectionWithPhpDocs[]|null */ private $parameters = null; /** * @var ?Type */ private $returnTypeWithUnresolvableTemplateTypes = null; /** * @var ?Type */ private $phpDocReturnTypeWithUnresolvableTemplateTypes = null; /** * @var ?Type */ private $returnType = null; /** * @var ?Type */ private $phpDocReturnType = null; /** * @param array $passedArgs */ public function __construct(\PHPStan\Reflection\ParametersAcceptorWithPhpDocs $parametersAcceptor, TemplateTypeMap $resolvedTemplateTypeMap, TemplateTypeVarianceMap $callSiteVarianceMap, array $passedArgs) { $this->parametersAcceptor = $parametersAcceptor; $this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap; $this->callSiteVarianceMap = $callSiteVarianceMap; $this->passedArgs = $passedArgs; } public function getOriginalParametersAcceptor() : \PHPStan\Reflection\ParametersAcceptor { return $this->parametersAcceptor; } public function getTemplateTypeMap() : TemplateTypeMap { return $this->parametersAcceptor->getTemplateTypeMap(); } public function getResolvedTemplateTypeMap() : TemplateTypeMap { return $this->resolvedTemplateTypeMap; } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return $this->callSiteVarianceMap; } public function getParameters() : array { $parameters = $this->parameters; if ($parameters === null) { $parameters = array_map(function (\PHPStan\Reflection\ParameterReflectionWithPhpDocs $param) : \PHPStan\Reflection\ParameterReflectionWithPhpDocs { $paramType = TypeUtils::resolveLateResolvableTypes(TemplateTypeHelper::resolveTemplateTypes($this->resolveConditionalTypesForParameter($param->getType()), $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createContravariant()), \false); $paramOutType = $param->getOutType(); if ($paramOutType !== null) { $paramOutType = TypeUtils::resolveLateResolvableTypes(TemplateTypeHelper::resolveTemplateTypes($this->resolveConditionalTypesForParameter($paramOutType), $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createCovariant()), \false); } $closureThisType = $param->getClosureThisType(); if ($closureThisType !== null) { $closureThisType = TypeUtils::resolveLateResolvableTypes(TemplateTypeHelper::resolveTemplateTypes($this->resolveConditionalTypesForParameter($closureThisType), $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createCovariant()), \false); } return new DummyParameterWithPhpDocs($param->getName(), $paramType, $param->isOptional(), $param->passedByReference(), $param->isVariadic(), $param->getDefaultValue(), $param->getNativeType(), $param->getPhpDocType(), $paramOutType, $param->isImmediatelyInvokedCallable(), $closureThisType); }, $this->parametersAcceptor->getParameters()); $this->parameters = $parameters; } return $parameters; } public function isVariadic() : bool { return $this->parametersAcceptor->isVariadic(); } public function getReturnTypeWithUnresolvableTemplateTypes() : Type { return $this->returnTypeWithUnresolvableTemplateTypes = $this->returnTypeWithUnresolvableTemplateTypes ?? $this->resolveConditionalTypesForParameter($this->resolveResolvableTemplateTypes($this->parametersAcceptor->getReturnType(), TemplateTypeVariance::createCovariant())); } public function getPhpDocReturnTypeWithUnresolvableTemplateTypes() : Type { return $this->phpDocReturnTypeWithUnresolvableTemplateTypes = $this->phpDocReturnTypeWithUnresolvableTemplateTypes ?? $this->resolveConditionalTypesForParameter($this->resolveResolvableTemplateTypes($this->parametersAcceptor->getPhpDocReturnType(), TemplateTypeVariance::createCovariant())); } public function getReturnType() : Type { $type = $this->returnType; if ($type === null) { $type = TypeUtils::resolveLateResolvableTypes(TemplateTypeHelper::resolveTemplateTypes($this->getReturnTypeWithUnresolvableTemplateTypes(), $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createCovariant()), \false); $this->returnType = $type; } return $type; } public function getPhpDocReturnType() : Type { $type = $this->phpDocReturnType; if ($type === null) { $type = TypeUtils::resolveLateResolvableTypes(TemplateTypeHelper::resolveTemplateTypes($this->getPhpDocReturnTypeWithUnresolvableTemplateTypes(), $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createCovariant()), \false); $this->phpDocReturnType = $type; } return $type; } public function getNativeReturnType() : Type { return $this->parametersAcceptor->getNativeReturnType(); } private function resolveResolvableTemplateTypes(Type $type, TemplateTypeVariance $positionVariance) : Type { $references = $type->getReferencedTemplateTypes($positionVariance); $objectCb = function (Type $type, callable $traverse) use($references) : Type { if ($type instanceof TemplateType && !$type->isArgument() && $type->getScope()->getFunctionName() !== null) { $newType = $this->resolvedTemplateTypeMap->getType($type->getName()); if ($newType === null || $newType instanceof ErrorType) { return $traverse($type); } $newType = TemplateTypeHelper::generalizeInferredTemplateType($type, $newType); $variance = TemplateTypeVariance::createInvariant(); foreach ($references as $reference) { // this uses identity to distinguish between different occurrences of the same template type // see https://github.com/phpstan/phpstan-src/pull/2485#discussion_r1328555397 for details if ($reference->getType() === $type) { $variance = $reference->getPositionVariance(); break; } } $callSiteVariance = $this->callSiteVarianceMap->getVariance($type->getName()); if ($callSiteVariance === null || $callSiteVariance->invariant()) { return $newType; } if (!$callSiteVariance->covariant() && $variance->covariant()) { return $traverse($type->getBound()); } if (!$callSiteVariance->contravariant() && $variance->contravariant()) { return new NonAcceptingNeverType(); } return $newType; } return $traverse($type); }; return TypeTraverser::map($type, function (Type $type, callable $traverse) use($references, $objectCb) : Type { if (BleedingEdgeToggle::isBleedingEdge() && ($type instanceof GenericObjectType || $type instanceof GenericStaticType)) { return TypeTraverser::map($type, $objectCb); } if ($type instanceof TemplateType && !$type->isArgument()) { $newType = $this->resolvedTemplateTypeMap->getType($type->getName()); if ($newType === null || $newType instanceof ErrorType) { return $traverse($type); } $variance = TemplateTypeVariance::createInvariant(); foreach ($references as $reference) { // this uses identity to distinguish between different occurrences of the same template type // see https://github.com/phpstan/phpstan-src/pull/2485#discussion_r1328555397 for details if ($reference->getType() === $type) { $variance = $reference->getPositionVariance(); break; } } $callSiteVariance = $this->callSiteVarianceMap->getVariance($type->getName()); if ($callSiteVariance === null || $callSiteVariance->invariant()) { return $newType; } if (!$callSiteVariance->covariant() && $variance->covariant()) { return $traverse($type->getBound()); } if (!$callSiteVariance->contravariant() && $variance->contravariant()) { return new NonAcceptingNeverType(); } return $newType; } return $traverse($type); }); } private function resolveConditionalTypesForParameter(Type $type) : Type { return TypeTraverser::map($type, function (Type $type, callable $traverse) : Type { if ($type instanceof ConditionalTypeForParameter && array_key_exists($type->getParameterName(), $this->passedArgs)) { $type = $type->toConditional($this->passedArgs[$type->getParameterName()]); } return $traverse($type); }); } } */ public function getAllowedSubTypes(\PHPStan\Reflection\ClassReflection $classReflection) : array; } > */ private $inProcess = []; /** * @param string[] $mixinExcludeClasses */ public function __construct(array $mixinExcludeClasses) { $this->mixinExcludeClasses = $mixinExcludeClasses; } public function hasMethod(ClassReflection $classReflection, string $methodName) : bool { return $this->findMethod($classReflection, $methodName) !== null; } public function getMethod(ClassReflection $classReflection, string $methodName) : MethodReflection { $method = $this->findMethod($classReflection, $methodName); if ($method === null) { throw new ShouldNotHappenException(); } return $method; } private function findMethod(ClassReflection $classReflection, string $methodName) : ?MethodReflection { $mixinTypes = $classReflection->getResolvedMixinTypes(); foreach ($mixinTypes as $type) { if (count(array_intersect($type->getObjectClassNames(), $this->mixinExcludeClasses)) > 0) { continue; } $typeDescription = $type->describe(VerbosityLevel::typeOnly()); if (isset($this->inProcess[$typeDescription][$methodName])) { continue; } $this->inProcess[$typeDescription][$methodName] = \true; if (!$type->hasMethod($methodName)->yes()) { unset($this->inProcess[$typeDescription][$methodName]); continue; } $method = $type->getMethod($methodName, new OutOfClassScope()); unset($this->inProcess[$typeDescription][$methodName]); $static = $method->isStatic(); if (!$static && $classReflection->hasNativeMethod('__callStatic')) { $static = \true; } return new \PHPStan\Reflection\Mixin\MixinMethodReflection($method, $static); } foreach ($classReflection->getTraits() as $traitClass) { $methodWithDeclaringClass = $this->findMethod($traitClass, $methodName); if ($methodWithDeclaringClass === null) { continue; } return $methodWithDeclaringClass; } $parentClass = $classReflection->getParentClass(); while ($parentClass !== null) { $method = $this->findMethod($parentClass, $methodName); if ($method !== null) { return $method; } $parentClass = $parentClass->getParentClass(); } return null; } } > */ private $inProcess = []; /** * @param string[] $mixinExcludeClasses */ public function __construct(array $mixinExcludeClasses) { $this->mixinExcludeClasses = $mixinExcludeClasses; } public function hasProperty(ClassReflection $classReflection, string $propertyName) : bool { return $this->findProperty($classReflection, $propertyName) !== null; } public function getProperty(ClassReflection $classReflection, string $propertyName) : PropertyReflection { $property = $this->findProperty($classReflection, $propertyName); if ($property === null) { throw new ShouldNotHappenException(); } return $property; } private function findProperty(ClassReflection $classReflection, string $propertyName) : ?PropertyReflection { $mixinTypes = $classReflection->getResolvedMixinTypes(); foreach ($mixinTypes as $type) { if (count(array_intersect($type->getObjectClassNames(), $this->mixinExcludeClasses)) > 0) { continue; } $typeDescription = $type->describe(VerbosityLevel::typeOnly()); if (isset($this->inProcess[$typeDescription][$propertyName])) { continue; } $this->inProcess[$typeDescription][$propertyName] = \true; if (!$type->hasProperty($propertyName)->yes()) { unset($this->inProcess[$typeDescription][$propertyName]); continue; } $property = $type->getProperty($propertyName, new OutOfClassScope()); unset($this->inProcess[$typeDescription][$propertyName]); return $property; } foreach ($classReflection->getTraits() as $traitClass) { $methodWithDeclaringClass = $this->findProperty($traitClass, $propertyName); if ($methodWithDeclaringClass === null) { continue; } return $methodWithDeclaringClass; } $parentClass = $classReflection->getParentClass(); while ($parentClass !== null) { $property = $this->findProperty($parentClass, $propertyName); if ($property !== null) { return $property; } $parentClass = $parentClass->getParentClass(); } return null; } } reflection = $reflection; $this->static = $static; } public function getDeclaringClass() : ClassReflection { return $this->reflection->getDeclaringClass(); } public function isStatic() : bool { return $this->static; } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } public function getDocComment() : ?string { return $this->reflection->getDocComment(); } public function getName() : string { return $this->reflection->getName(); } public function getPrototype() : ClassMemberReflection { return $this->reflection->getPrototype(); } public function getVariants() : array { return $this->reflection->getVariants(); } public function isDeprecated() : TrinaryLogic { return $this->reflection->isDeprecated(); } public function getDeprecatedDescription() : ?string { return $this->reflection->getDeprecatedDescription(); } public function isFinal() : TrinaryLogic { return $this->reflection->isFinal(); } public function isInternal() : TrinaryLogic { return $this->reflection->isInternal(); } public function getThrowType() : ?Type { return $this->reflection->getThrowType(); } public function hasSideEffects() : TrinaryLogic { return $this->reflection->hasSideEffects(); } } value = $value; } private static function create(int $value) : self { if (!array_key_exists($value, self::$registry)) { self::$registry[$value] = new self($value); } return self::$registry[$value]; } public static function createNo() : self { return self::create(self::NO); } public static function createCreatesNewVariable() : self { return self::create(self::CREATES_NEW_VARIABLE); } public static function createReadsArgument() : self { return self::create(self::READS_ARGUMENT); } public function no() : bool { return $this->value === self::NO; } public function yes() : bool { return !$this->no(); } public function equals(self $other) : bool { return $this->value === $other->value; } public function createsNewVariable() : bool { return $this->value === self::CREATES_NEW_VARIABLE; } public function combine(self $other) : self { if ($this->value > $other->value) { return $this; } elseif ($this->value < $other->value) { return $other; } return $this; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self($properties['value']); } } initializerExprTypeResolver = $initializerExprTypeResolver; $this->declaringClass = $declaringClass; $this->reflection = $reflection; $this->nativeType = $nativeType; $this->phpDocType = $phpDocType; $this->deprecatedDescription = $deprecatedDescription; $this->isDeprecated = $isDeprecated; $this->isInternal = $isInternal; $this->isFinal = $isFinal; } public function getName() : string { return $this->reflection->getName(); } public function getFileName() : ?string { return $this->declaringClass->getFileName(); } /** * @deprecated Use getValueExpr() * @return mixed */ public function getValue() { try { return $this->reflection->getValue(); } catch (UnableToCompileNode $e) { return NAN; } } public function getValueExpr() : Expr { return $this->reflection->getValueExpression(); } public function hasPhpDocType() : bool { return $this->phpDocType !== null; } public function getPhpDocType() : ?Type { return $this->phpDocType; } public function hasNativeType() : bool { return $this->nativeType !== null; } public function getNativeType() : ?Type { return $this->nativeType; } public function getValueType() : Type { if ($this->valueType === null) { if ($this->phpDocType !== null) { if ($this->nativeType !== null) { return $this->valueType = TypehintHelper::decideType($this->nativeType, $this->phpDocType); } return $this->phpDocType; } elseif ($this->nativeType !== null) { return $this->nativeType; } $this->valueType = $this->initializerExprTypeResolver->getType($this->getValueExpr(), \PHPStan\Reflection\InitializerExprContext::fromClassReflection($this->declaringClass)); } return $this->valueType; } public function getDeclaringClass() : \PHPStan\Reflection\ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return \true; } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } public function isFinal() : bool { return $this->isFinal || $this->reflection->isFinal(); } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isDeprecated); } public function getDeprecatedDescription() : ?string { if ($this->isDeprecated) { return $this->deprecatedDescription; } return null; } public function isInternal() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isInternal); } public function getDocComment() : ?string { $docComment = $this->reflection->getDocComment(); if ($docComment === \false) { return null; } return $docComment; } } reflection = $reflection; $this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap; $this->callSiteVarianceMap = $callSiteVarianceMap; } public function getName() : string { return $this->reflection->getName(); } public function getPrototype() : \PHPStan\Reflection\ClassMemberReflection { return $this->reflection->getPrototype(); } public function getVariants() : array { $variants = $this->variants; if ($variants !== null) { return $variants; } return $this->variants = $this->resolveVariants($this->reflection->getVariants()); } public function getOnlyVariant() : \PHPStan\Reflection\ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { $variants = $this->namedArgumentVariants; if ($variants !== null) { return $variants; } $innerVariants = $this->reflection->getNamedArgumentsVariants(); if ($innerVariants === null) { return null; } return $this->namedArgumentVariants = $this->resolveVariants($innerVariants); } /** * @param ParametersAcceptorWithPhpDocs[] $variants * @return ResolvedFunctionVariant[] */ private function resolveVariants(array $variants) : array { $result = []; foreach ($variants as $variant) { $result[] = new \PHPStan\Reflection\ResolvedFunctionVariantWithOriginal($variant, $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, []); } return $result; } public function getDeclaringClass() : \PHPStan\Reflection\ClassReflection { return $this->reflection->getDeclaringClass(); } public function getDeclaringTrait() : ?\PHPStan\Reflection\ClassReflection { if ($this->reflection instanceof PhpMethodReflection) { return $this->reflection->getDeclaringTrait(); } return null; } public function isStatic() : bool { return $this->reflection->isStatic(); } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } public function getDocComment() : ?string { return $this->reflection->getDocComment(); } public function isDeprecated() : TrinaryLogic { return $this->reflection->isDeprecated(); } public function getDeprecatedDescription() : ?string { return $this->reflection->getDeprecatedDescription(); } public function isFinal() : TrinaryLogic { return $this->reflection->isFinal(); } public function isFinalByKeyword() : TrinaryLogic { return $this->reflection->isFinalByKeyword(); } public function isInternal() : TrinaryLogic { return $this->reflection->isInternal(); } public function getThrowType() : ?Type { return $this->reflection->getThrowType(); } public function hasSideEffects() : TrinaryLogic { return $this->reflection->hasSideEffects(); } public function isPure() : TrinaryLogic { return $this->reflection->isPure(); } public function getAsserts() : \PHPStan\Reflection\Assertions { return $this->asserts = $this->asserts ?? $this->reflection->getAsserts()->mapTypes(function (Type $type) { return TemplateTypeHelper::resolveTemplateTypes($type, $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createInvariant()); }); } public function acceptsNamedArguments() : bool { return $this->reflection->acceptsNamedArguments(); } public function getSelfOutType() : ?Type { if ($this->selfOutType === \false) { $selfOutType = $this->reflection->getSelfOutType(); if ($selfOutType !== null) { $selfOutType = TemplateTypeHelper::resolveTemplateTypes($selfOutType, $this->resolvedTemplateTypeMap, $this->callSiteVarianceMap, TemplateTypeVariance::createInvariant()); } $this->selfOutType = $selfOutType; } return $this->selfOutType; } public function returnsByReference() : TrinaryLogic { return $this->reflection->returnsByReference(); } public function isAbstract() : TrinaryLogic { $abstract = $this->reflection->isAbstract(); if (is_bool($abstract)) { return TrinaryLogic::createFromBoolean($abstract); } return $abstract; } } 0 && count($parametersAcceptors) > 0) { $arrayMapArgs = $args[0]->value->getAttribute(ArrayMapArgVisitor::ATTRIBUTE_NAME); if ($arrayMapArgs !== null) { $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); $callbackParameters = []; foreach ($arrayMapArgs as $arg) { $argType = $scope->getType($arg->value); if ($arg->unpack) { $constantArrays = $argType->getConstantArrays(); if (count($constantArrays) > 0) { foreach ($constantArrays as $constantArray) { $valueTypes = $constantArray->getValueTypes(); foreach ($valueTypes as $valueType) { $callbackParameters[] = new DummyParameter('item', $scope->getIterableValueType($valueType), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null); } } } } else { $callbackParameters[] = new DummyParameter('item', $scope->getIterableValueType($argType), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null); } } $parameters[0] = new NativeParameterReflection($parameters[0]->getName(), $parameters[0]->isOptional(), new UnionType([new CallableType($callbackParameters, new MixedType(), \false), new NullType()]), $parameters[0]->passedByReference(), $parameters[0]->isVariadic(), $parameters[0]->getDefaultValue()); $parametersAcceptors = [new \PHPStan\Reflection\FunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } if (count($args) >= 3 && (bool) $args[0]->getAttribute(CurlSetOptArgVisitor::ATTRIBUTE_NAME)) { $optType = $scope->getType($args[1]->value); if ($optType instanceof ConstantIntegerType) { $optValueType = self::getCurlOptValueType($optType->getValue()); if ($optValueType !== null) { $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); $parameters[2] = new NativeParameterReflection($parameters[2]->getName(), $parameters[2]->isOptional(), $optValueType, $parameters[2]->passedByReference(), $parameters[2]->isVariadic(), $parameters[2]->getDefaultValue()); $parametersAcceptors = [new \PHPStan\Reflection\FunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } } } if (isset($args[0]) && (bool) $args[0]->getAttribute(ArrayFilterArgVisitor::ATTRIBUTE_NAME)) { if (isset($args[2])) { $mode = $scope->getType($args[2]->value); if ($mode instanceof ConstantIntegerType) { if ($mode->getValue() === ARRAY_FILTER_USE_KEY) { $arrayFilterParameters = [new DummyParameter('key', $scope->getIterableKeyType($scope->getType($args[0]->value)), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null)]; } elseif ($mode->getValue() === ARRAY_FILTER_USE_BOTH) { $arrayFilterParameters = [new DummyParameter('item', $scope->getIterableValueType($scope->getType($args[0]->value)), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null), new DummyParameter('key', $scope->getIterableKeyType($scope->getType($args[0]->value)), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null)]; } } } $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); $parameters[1] = new NativeParameterReflection($parameters[1]->getName(), $parameters[1]->isOptional(), new UnionType([new CallableType($arrayFilterParameters ?? [new DummyParameter('item', $scope->getIterableValueType($scope->getType($args[0]->value)), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null)], new BooleanType(), \false), new NullType()]), $parameters[1]->passedByReference(), $parameters[1]->isVariadic(), $parameters[1]->getDefaultValue()); $parametersAcceptors = [new \PHPStan\Reflection\FunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } if (isset($args[0]) && (bool) $args[0]->getAttribute(ArrayWalkArgVisitor::ATTRIBUTE_NAME)) { $arrayWalkParameters = [new DummyParameter('item', $scope->getIterableValueType($scope->getType($args[0]->value)), \false, \PHPStan\Reflection\PassedByReference::createReadsArgument(), \false, null), new DummyParameter('key', $scope->getIterableKeyType($scope->getType($args[0]->value)), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null)]; if (isset($args[2])) { $arrayWalkParameters[] = new DummyParameter('arg', $scope->getType($args[2]->value), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null); } $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); $parameters[1] = new NativeParameterReflection($parameters[1]->getName(), $parameters[1]->isOptional(), new CallableType($arrayWalkParameters, new MixedType(), \false), $parameters[1]->passedByReference(), $parameters[1]->isVariadic(), $parameters[1]->getDefaultValue()); $parametersAcceptors = [new \PHPStan\Reflection\FunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } if (isset($args[0]) && (bool) $args[0]->getAttribute(ArrayFindArgVisitor::ATTRIBUTE_NAME)) { $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); $argType = $scope->getType($args[0]->value); $parameters[1] = new NativeParameterReflection($parameters[1]->getName(), $parameters[1]->isOptional(), new CallableType([new DummyParameter('value', $scope->getIterableValueType($argType), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null), new DummyParameter('key', $scope->getIterableKeyType($argType), \false, \PHPStan\Reflection\PassedByReference::createNo(), \false, null)], new BooleanType(), \false), $parameters[1]->passedByReference(), $parameters[1]->isVariadic(), $parameters[1]->getDefaultValue()); $parametersAcceptors = [new \PHPStan\Reflection\FunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } if (isset($args[0])) { $closureBindToVar = $args[0]->getAttribute(ClosureBindToVarVisitor::ATTRIBUTE_NAME); if ($closureBindToVar !== null && $closureBindToVar instanceof Node\Expr\Variable && is_string($closureBindToVar->name)) { $varType = $scope->getType($closureBindToVar); if ((new ObjectType(Closure::class))->isSuperTypeOf($varType)->yes()) { $inFunction = $scope->getFunction(); if ($inFunction !== null) { $closureThisParameters = []; foreach ($inFunction->getParameters() as $parameter) { if ($parameter->getClosureThisType() === null) { continue; } $closureThisParameters[$parameter->getName()] = $parameter->getClosureThisType(); } if (array_key_exists($closureBindToVar->name, $closureThisParameters)) { if ($scope->hasExpressionType(new ParameterVariableOriginalValueExpr($closureBindToVar->name))->yes()) { $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); $parameters[0] = new NativeParameterReflection($parameters[0]->getName(), $parameters[0]->isOptional(), $closureThisParameters[$closureBindToVar->name], $parameters[0]->passedByReference(), $parameters[0]->isVariadic(), $parameters[0]->getDefaultValue()); $parametersAcceptors = [new \PHPStan\Reflection\FunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } } } } } if ($args[0]->getAttribute(ClosureBindArgVisitor::ATTRIBUTE_NAME) !== null && $args[0]->value instanceof Node\Expr\Variable && is_string($args[0]->value->name)) { $closureVarName = $args[0]->value->name; $inFunction = $scope->getFunction(); if ($inFunction !== null) { $closureThisParameters = []; foreach ($inFunction->getParameters() as $parameter) { if ($parameter->getClosureThisType() === null) { continue; } $closureThisParameters[$parameter->getName()] = $parameter->getClosureThisType(); } if (array_key_exists($closureVarName, $closureThisParameters)) { if ($scope->hasExpressionType(new ParameterVariableOriginalValueExpr($closureVarName))->yes()) { $acceptor = $parametersAcceptors[0]; $parameters = $acceptor->getParameters(); $parameters[1] = new NativeParameterReflection($parameters[1]->getName(), $parameters[1]->isOptional(), $closureThisParameters[$closureVarName], $parameters[1]->passedByReference(), $parameters[1]->isVariadic(), $parameters[1]->getDefaultValue()); $parametersAcceptors = [new \PHPStan\Reflection\FunctionVariant($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty())]; } } } } } } if (count($parametersAcceptors) === 1) { $acceptor = $parametersAcceptors[0]; if (!self::hasAcceptorTemplateOrLateResolvableType($acceptor)) { return $acceptor; } } $reorderedArgs = $args; $parameters = null; $singleParametersAcceptor = null; if (count($parametersAcceptors) === 1) { $reorderedArgs = ArgumentsNormalizer::reorderArgs($parametersAcceptors[0], $args); $singleParametersAcceptor = $parametersAcceptors[0]; } $hasName = \false; foreach ($reorderedArgs ?? $args as $i => $arg) { $originalArg = $arg->getAttribute(ArgumentsNormalizer::ORIGINAL_ARG_ATTRIBUTE) ?? $arg; $parameter = null; if ($singleParametersAcceptor !== null) { $parameters = $singleParametersAcceptor->getParameters(); if (isset($parameters[$i])) { $parameter = $parameters[$i]; } elseif (count($parameters) > 0 && $singleParametersAcceptor->isVariadic()) { $parameter = $parameters[count($parameters) - 1]; } } if ($parameter !== null && $scope instanceof MutatingScope) { $scope = $scope->pushInFunctionCall(null, $parameter); } $type = $scope->getType($originalArg->value); if ($parameter !== null && $scope instanceof MutatingScope) { $scope = $scope->popInFunctionCall(); } if ($originalArg->name !== null) { $index = $originalArg->name->toString(); $hasName = \true; } else { $index = $i; } if ($originalArg->unpack) { $unpack = \true; $types[$index] = $type->getIterableValueType(); } else { $types[$index] = $type; } } if ($hasName && $namedArgumentsVariants !== null) { return self::selectFromTypes($types, $namedArgumentsVariants, $unpack); } return self::selectFromTypes($types, $parametersAcceptors, $unpack); } private static function hasAcceptorTemplateOrLateResolvableType(\PHPStan\Reflection\ParametersAcceptor $acceptor) : bool { if (self::hasTemplateOrLateResolvableType($acceptor->getReturnType())) { return \true; } foreach ($acceptor->getParameters() as $parameter) { if ($parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs && $parameter->getOutType() !== null && self::hasTemplateOrLateResolvableType($parameter->getOutType())) { return \true; } if ($parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs && $parameter->getClosureThisType() !== null && self::hasTemplateOrLateResolvableType($parameter->getClosureThisType())) { return \true; } if (!self::hasTemplateOrLateResolvableType($parameter->getType())) { continue; } return \true; } return \false; } private static function hasTemplateOrLateResolvableType(Type $type) : bool { $has = \false; TypeTraverser::map($type, static function (Type $type, callable $traverse) use(&$has) : Type { if ($type instanceof TemplateType || $type instanceof LateResolvableType) { $has = \true; return $type; } return $traverse($type); }); return $has; } /** * @param array $types * @param ParametersAcceptor[] $parametersAcceptors */ public static function selectFromTypes(array $types, array $parametersAcceptors, bool $unpack) : \PHPStan\Reflection\ParametersAcceptor { if (count($parametersAcceptors) === 1) { return \PHPStan\Reflection\GenericParametersAcceptorResolver::resolve($types, $parametersAcceptors[0]); } if (count($parametersAcceptors) === 0) { throw new ShouldNotHappenException('getVariants() must return at least one variant.'); } $typesCount = count($types); $acceptableAcceptors = []; foreach ($parametersAcceptors as $parametersAcceptor) { if ($unpack) { $acceptableAcceptors[] = $parametersAcceptor; continue; } $functionParametersMinCount = 0; $functionParametersMaxCount = 0; foreach ($parametersAcceptor->getParameters() as $parameter) { if (!$parameter->isOptional()) { $functionParametersMinCount++; } $functionParametersMaxCount++; } if ($typesCount < $functionParametersMinCount) { continue; } if (!$parametersAcceptor->isVariadic() && $typesCount > $functionParametersMaxCount) { continue; } $acceptableAcceptors[] = $parametersAcceptor; } if (count($acceptableAcceptors) === 0) { return \PHPStan\Reflection\GenericParametersAcceptorResolver::resolve($types, self::combineAcceptors($parametersAcceptors)); } if (count($acceptableAcceptors) === 1) { return \PHPStan\Reflection\GenericParametersAcceptorResolver::resolve($types, $acceptableAcceptors[0]); } $winningAcceptors = []; $winningCertainty = null; foreach ($acceptableAcceptors as $acceptableAcceptor) { $isSuperType = TrinaryLogic::createYes(); $acceptableAcceptor = \PHPStan\Reflection\GenericParametersAcceptorResolver::resolve($types, $acceptableAcceptor); foreach ($acceptableAcceptor->getParameters() as $i => $parameter) { if (!isset($types[$i])) { if (!$unpack || count($types) <= 0) { break; } $type = $types[array_key_last($types)]; } else { $type = $types[$i]; } if ($parameter->getType() instanceof MixedType) { $isSuperType = $isSuperType->and(TrinaryLogic::createMaybe()); } else { $isSuperType = $isSuperType->and($parameter->getType()->isSuperTypeOf($type)); } } if ($isSuperType->no()) { continue; } if ($winningCertainty === null) { $winningAcceptors[] = $acceptableAcceptor; $winningCertainty = $isSuperType; } else { $comparison = $winningCertainty->compareTo($isSuperType); if ($comparison === $isSuperType) { $winningAcceptors = [$acceptableAcceptor]; $winningCertainty = $isSuperType; } elseif ($comparison === null) { $winningAcceptors[] = $acceptableAcceptor; } } } if (count($winningAcceptors) === 0) { return \PHPStan\Reflection\GenericParametersAcceptorResolver::resolve($types, self::combineAcceptors($acceptableAcceptors)); } return \PHPStan\Reflection\GenericParametersAcceptorResolver::resolve($types, self::combineAcceptors($winningAcceptors)); } /** * @param ParametersAcceptor[] $acceptors */ public static function combineAcceptors(array $acceptors) : \PHPStan\Reflection\ParametersAcceptorWithPhpDocs { if (count($acceptors) === 0) { throw new ShouldNotHappenException('getVariants() must return at least one variant.'); } if (count($acceptors) === 1) { return self::wrapAcceptor($acceptors[0]); } $minimumNumberOfParameters = null; foreach ($acceptors as $acceptor) { $acceptorParametersMinCount = 0; foreach ($acceptor->getParameters() as $parameter) { if ($parameter->isOptional()) { continue; } $acceptorParametersMinCount++; } if ($minimumNumberOfParameters !== null && $minimumNumberOfParameters <= $acceptorParametersMinCount) { continue; } $minimumNumberOfParameters = $acceptorParametersMinCount; } $parameters = []; $isVariadic = \false; $returnTypes = []; $phpDocReturnTypes = []; $nativeReturnTypes = []; $callableOccurred = \false; $throwPoints = []; $isPure = TrinaryLogic::createNo(); $impurePoints = []; $invalidateExpressions = []; $usedVariables = []; $acceptsNamedArguments = \false; foreach ($acceptors as $acceptor) { $returnTypes[] = $acceptor->getReturnType(); if ($acceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs) { $phpDocReturnTypes[] = $acceptor->getPhpDocReturnType(); $nativeReturnTypes[] = $acceptor->getNativeReturnType(); } if ($acceptor instanceof CallableParametersAcceptor) { $callableOccurred = \true; $throwPoints = array_merge($throwPoints, $acceptor->getThrowPoints()); $isPure = $isPure->or($acceptor->isPure()); $impurePoints = array_merge($impurePoints, $acceptor->getImpurePoints()); $invalidateExpressions = array_merge($invalidateExpressions, $acceptor->getInvalidateExpressions()); $usedVariables = array_merge($usedVariables, $acceptor->getUsedVariables()); $acceptsNamedArguments = $acceptsNamedArguments || $acceptor->acceptsNamedArguments(); } $isVariadic = $isVariadic || $acceptor->isVariadic(); foreach ($acceptor->getParameters() as $i => $parameter) { if (!isset($parameters[$i])) { $parameters[$i] = new DummyParameterWithPhpDocs($parameter->getName(), $parameter->getType(), $i + 1 > $minimumNumberOfParameters, $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), $parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs ? $parameter->getNativeType() : new MixedType(), $parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs ? $parameter->getPhpDocType() : new MixedType(), $parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs ? $parameter->getOutType() : null, $parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs ? $parameter->isImmediatelyInvokedCallable() : TrinaryLogic::createMaybe(), $parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs ? $parameter->getClosureThisType() : null); continue; } $isVariadic = $parameters[$i]->isVariadic() || $parameter->isVariadic(); $defaultValueLeft = $parameters[$i]->getDefaultValue(); $defaultValueRight = $parameter->getDefaultValue(); if ($defaultValueLeft !== null && $defaultValueRight !== null) { $defaultValue = TypeCombinator::union($defaultValueLeft, $defaultValueRight); } else { $defaultValue = null; } $type = TypeCombinator::union($parameters[$i]->getType(), $parameter->getType()); $nativeType = $parameters[$i]->getNativeType(); $phpDocType = $parameters[$i]->getPhpDocType(); $outType = $parameters[$i]->getOutType(); $immediatelyInvokedCallable = $parameters[$i]->isImmediatelyInvokedCallable(); $closureThisType = $parameters[$i]->getClosureThisType(); if ($parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs) { $nativeType = TypeCombinator::union($nativeType, $parameter->getNativeType()); $phpDocType = TypeCombinator::union($phpDocType, $parameter->getPhpDocType()); if ($parameter->getOutType() !== null) { $outType = $outType === null ? null : TypeCombinator::union($outType, $parameter->getOutType()); } else { $outType = null; } if ($parameter->getClosureThisType() !== null && $closureThisType !== null) { $closureThisType = TypeCombinator::union($closureThisType, $parameter->getClosureThisType()); } else { $closureThisType = null; } $immediatelyInvokedCallable = $parameter->isImmediatelyInvokedCallable()->or($immediatelyInvokedCallable); } else { $nativeType = new MixedType(); $phpDocType = $type; $outType = null; $immediatelyInvokedCallable = TrinaryLogic::createMaybe(); $closureThisType = null; } $parameters[$i] = new DummyParameterWithPhpDocs($parameters[$i]->getName() !== $parameter->getName() ? sprintf('%s|%s', $parameters[$i]->getName(), $parameter->getName()) : $parameter->getName(), $type, $i + 1 > $minimumNumberOfParameters, $parameters[$i]->passedByReference()->combine($parameter->passedByReference()), $isVariadic, $defaultValue, $nativeType, $phpDocType, $outType, $immediatelyInvokedCallable, $closureThisType); if ($isVariadic) { $parameters = array_slice($parameters, 0, $i + 1); break; } } } $returnType = TypeCombinator::union(...$returnTypes); $phpDocReturnType = $phpDocReturnTypes === [] ? null : TypeCombinator::union(...$phpDocReturnTypes); $nativeReturnType = $nativeReturnTypes === [] ? null : TypeCombinator::union(...$nativeReturnTypes); if ($callableOccurred) { return new \PHPStan\Reflection\CallableFunctionVariantWithPhpDocs(TemplateTypeMap::createEmpty(), null, $parameters, $isVariadic, $returnType, $phpDocReturnType ?? $returnType, $nativeReturnType ?? new MixedType(), null, $throwPoints, $isPure, $impurePoints, $invalidateExpressions, $usedVariables, $acceptsNamedArguments); } return new \PHPStan\Reflection\FunctionVariantWithPhpDocs(TemplateTypeMap::createEmpty(), null, $parameters, $isVariadic, $returnType, $phpDocReturnType ?? $returnType, $nativeReturnType ?? new MixedType()); } private static function wrapAcceptor(\PHPStan\Reflection\ParametersAcceptor $acceptor) : \PHPStan\Reflection\ParametersAcceptorWithPhpDocs { if ($acceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs) { return $acceptor; } if ($acceptor instanceof CallableParametersAcceptor) { return new \PHPStan\Reflection\CallableFunctionVariantWithPhpDocs($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map(static function (\PHPStan\Reflection\ParameterReflection $parameter) : \PHPStan\Reflection\ParameterReflectionWithPhpDocs { return self::wrapParameter($parameter); }, $acceptor->getParameters()), $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor->getReturnType(), new MixedType(), TemplateTypeVarianceMap::createEmpty(), $acceptor->getThrowPoints(), $acceptor->isPure(), $acceptor->getImpurePoints(), $acceptor->getInvalidateExpressions(), $acceptor->getUsedVariables(), $acceptor->acceptsNamedArguments()); } return new \PHPStan\Reflection\FunctionVariantWithPhpDocs($acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map(static function (\PHPStan\Reflection\ParameterReflection $parameter) : \PHPStan\Reflection\ParameterReflectionWithPhpDocs { return self::wrapParameter($parameter); }, $acceptor->getParameters()), $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor->getReturnType(), new MixedType(), TemplateTypeVarianceMap::createEmpty()); } private static function wrapParameter(\PHPStan\Reflection\ParameterReflection $parameter) : \PHPStan\Reflection\ParameterReflectionWithPhpDocs { return $parameter instanceof \PHPStan\Reflection\ParameterReflectionWithPhpDocs ? $parameter : new DummyParameterWithPhpDocs($parameter->getName(), $parameter->getType(), $parameter->isOptional(), $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), new MixedType(), $parameter->getType(), null, TrinaryLogic::createMaybe(), null); } private static function getCurlOptValueType(int $curlOpt) : ?Type { if (defined('CURLOPT_SSL_VERIFYHOST') && $curlOpt === CURLOPT_SSL_VERIFYHOST) { return new UnionType([new ConstantIntegerType(0), new ConstantIntegerType(2)]); } $boolConstants = ['CURLOPT_AUTOREFERER', 'CURLOPT_COOKIESESSION', 'CURLOPT_CERTINFO', 'CURLOPT_CONNECT_ONLY', 'CURLOPT_CRLF', 'CURLOPT_DISALLOW_USERNAME_IN_URL', 'CURLOPT_DNS_SHUFFLE_ADDRESSES', 'CURLOPT_HAPROXYPROTOCOL', 'CURLOPT_SSH_COMPRESSION', 'CURLOPT_DNS_USE_GLOBAL_CACHE', 'CURLOPT_FAILONERROR', 'CURLOPT_SSL_FALSESTART', 'CURLOPT_FILETIME', 'CURLOPT_FOLLOWLOCATION', 'CURLOPT_FORBID_REUSE', 'CURLOPT_FRESH_CONNECT', 'CURLOPT_FTP_USE_EPRT', 'CURLOPT_FTP_USE_EPSV', 'CURLOPT_FTP_CREATE_MISSING_DIRS', 'CURLOPT_FTPAPPEND', 'CURLOPT_TCP_NODELAY', 'CURLOPT_FTPASCII', 'CURLOPT_FTPLISTONLY', 'CURLOPT_HEADER', 'CURLOPT_HTTP09_ALLOWED', 'CURLOPT_HTTPGET', 'CURLOPT_HTTPPROXYTUNNEL', 'CURLOPT_HTTP_CONTENT_DECODING', 'CURLOPT_KEEP_SENDING_ON_ERROR', 'CURLOPT_MUTE', 'CURLOPT_NETRC', 'CURLOPT_NOBODY', 'CURLOPT_NOPROGRESS', 'CURLOPT_NOSIGNAL', 'CURLOPT_PATH_AS_IS', 'CURLOPT_PIPEWAIT', 'CURLOPT_POST', 'CURLOPT_PUT', 'CURLOPT_RETURNTRANSFER', 'CURLOPT_SASL_IR', 'CURLOPT_SSL_ENABLE_ALPN', 'CURLOPT_SSL_ENABLE_NPN', 'CURLOPT_SSL_VERIFYPEER', 'CURLOPT_SSL_VERIFYSTATUS', 'CURLOPT_PROXY_SSL_VERIFYPEER', 'CURLOPT_SUPPRESS_CONNECT_HEADERS', 'CURLOPT_TCP_FASTOPEN', 'CURLOPT_TFTP_NO_OPTIONS', 'CURLOPT_TRANSFERTEXT', 'CURLOPT_UNRESTRICTED_AUTH', 'CURLOPT_UPLOAD', 'CURLOPT_VERBOSE']; foreach ($boolConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return new BooleanType(); } } $intConstants = ['CURLOPT_BUFFERSIZE', 'CURLOPT_CONNECTTIMEOUT', 'CURLOPT_CONNECTTIMEOUT_MS', 'CURLOPT_DNS_CACHE_TIMEOUT', 'CURLOPT_EXPECT_100_TIMEOUT_MS', 'CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS', 'CURLOPT_FTPSSLAUTH', 'CURLOPT_HEADEROPT', 'CURLOPT_HTTP_VERSION', 'CURLOPT_HTTPAUTH', 'CURLOPT_INFILESIZE', 'CURLOPT_LOW_SPEED_LIMIT', 'CURLOPT_LOW_SPEED_TIME', 'CURLOPT_MAXCONNECTS', 'CURLOPT_MAXREDIRS', 'CURLOPT_PORT', 'CURLOPT_POSTREDIR', 'CURLOPT_PROTOCOLS', 'CURLOPT_PROXYAUTH', 'CURLOPT_PROXYPORT', 'CURLOPT_PROXYTYPE', 'CURLOPT_REDIR_PROTOCOLS', 'CURLOPT_RESUME_FROM', 'CURLOPT_SOCKS5_AUTH', 'CURLOPT_SSL_OPTIONS', 'CURLOPT_SSL_VERIFYHOST', 'CURLOPT_SSLVERSION', 'CURLOPT_PROXY_SSL_OPTIONS', 'CURLOPT_PROXY_SSL_VERIFYHOST', 'CURLOPT_PROXY_SSLVERSION', 'CURLOPT_STREAM_WEIGHT', 'CURLOPT_TCP_KEEPALIVE', 'CURLOPT_TCP_KEEPIDLE', 'CURLOPT_TCP_KEEPINTVL', 'CURLOPT_TIMECONDITION', 'CURLOPT_TIMEOUT', 'CURLOPT_TIMEOUT_MS', 'CURLOPT_TIMEVALUE', 'CURLOPT_TIMEVALUE_LARGE', 'CURLOPT_MAX_RECV_SPEED_LARGE', 'CURLOPT_SSH_AUTH_TYPES', 'CURLOPT_IPRESOLVE', 'CURLOPT_FTP_FILEMETHOD']; foreach ($intConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return new IntegerType(); } } $nonEmptyStringConstants = ['CURLOPT_ABSTRACT_UNIX_SOCKET', 'CURLOPT_CAINFO', 'CURLOPT_CAPATH', 'CURLOPT_COOKIE', 'CURLOPT_COOKIEJAR', 'CURLOPT_COOKIELIST', 'CURLOPT_CUSTOMREQUEST', 'CURLOPT_DEFAULT_PROTOCOL', 'CURLOPT_DNS_INTERFACE', 'CURLOPT_DNS_LOCAL_IP4', 'CURLOPT_DNS_LOCAL_IP6', 'CURLOPT_EGDSOCKET', 'CURLOPT_FTPPORT', 'CURLOPT_INTERFACE', 'CURLOPT_KEYPASSWD', 'CURLOPT_KRB4LEVEL', 'CURLOPT_LOGIN_OPTIONS', 'CURLOPT_PINNEDPUBLICKEY', 'CURLOPT_PROXY_SERVICE_NAME', 'CURLOPT_PROXY_CAINFO', 'CURLOPT_PROXY_CAPATH', 'CURLOPT_PROXY_CRLFILE', 'CURLOPT_PROXY_KEYPASSWD', 'CURLOPT_PROXY_PINNEDPUBLICKEY', 'CURLOPT_PROXY_SSLCERT', 'CURLOPT_PROXY_SSLCERTTYPE', 'CURLOPT_PROXY_SSL_CIPHER_LIST', 'CURLOPT_PROXY_TLS13_CIPHERS', 'CURLOPT_PROXY_SSLKEY', 'CURLOPT_PROXY_SSLKEYTYPE', 'CURLOPT_PROXY_TLSAUTH_PASSWORD', 'CURLOPT_PROXY_TLSAUTH_TYPE', 'CURLOPT_PROXY_TLSAUTH_USERNAME', 'CURLOPT_PROXYUSERPWD', 'CURLOPT_RANDOM_FILE', 'CURLOPT_RANGE', 'CURLOPT_REFERER', 'CURLOPT_SERVICE_NAME', 'CURLOPT_SSH_HOST_PUBLIC_KEY_MD5', 'CURLOPT_SSH_PUBLIC_KEYFILE', 'CURLOPT_SSH_PRIVATE_KEYFILE', 'CURLOPT_SSL_CIPHER_LIST', 'CURLOPT_SSLCERT', 'CURLOPT_SSLCERTPASSWD', 'CURLOPT_SSLCERTTYPE', 'CURLOPT_SSLENGINE', 'CURLOPT_SSLENGINE_DEFAULT', 'CURLOPT_SSLKEY', 'CURLOPT_SSLKEYPASSWD', 'CURLOPT_SSLKEYTYPE', 'CURLOPT_TLS13_CIPHERS', 'CURLOPT_UNIX_SOCKET_PATH', 'CURLOPT_URL', 'CURLOPT_USERAGENT', 'CURLOPT_USERNAME', 'CURLOPT_PASSWORD', 'CURLOPT_USERPWD', 'CURLOPT_XOAUTH2_BEARER']; foreach ($nonEmptyStringConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return TypeCombinator::intersect(new StringType(), new AccessoryNonEmptyStringType()); } } $stringConstants = ['CURLOPT_COOKIEFILE', 'CURLOPT_ENCODING', 'CURLOPT_PRE_PROXY', 'CURLOPT_PRIVATE', 'CURLOPT_PROXY']; foreach ($stringConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return new StringType(); } } $intArrayStringKeysConstants = ['CURLOPT_HTTPHEADER']; foreach ($intArrayStringKeysConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return new ArrayType(new IntegerType(), new StringType()); } } $arrayConstants = ['CURLOPT_CONNECT_TO', 'CURLOPT_HTTP200ALIASES', 'CURLOPT_POSTQUOTE', 'CURLOPT_PROXYHEADER', 'CURLOPT_QUOTE', 'CURLOPT_RESOLVE']; foreach ($arrayConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return new ArrayType(new MixedType(), new MixedType()); } } $arrayOrStringConstants = ['CURLOPT_POSTFIELDS']; foreach ($arrayOrStringConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return new UnionType([new StringType(), new ArrayType(new MixedType(), new MixedType())]); } } $resourceConstants = ['CURLOPT_FILE', 'CURLOPT_INFILE', 'CURLOPT_STDERR', 'CURLOPT_WRITEHEADER']; foreach ($resourceConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { return new ResourceType(); } } // unknown constant return null; } } */ private $currentlyResolvingClassConstant = []; public function __construct(ConstantResolver $constantResolver, ReflectionProviderProvider $reflectionProviderProvider, PhpVersion $phpVersion, OperatorTypeSpecifyingExtensionRegistryProvider $operatorTypeSpecifyingExtensionRegistryProvider, OversizedArrayBuilder $oversizedArrayBuilder, bool $usePathConstantsAsConstantString = \false) { $this->constantResolver = $constantResolver; $this->reflectionProviderProvider = $reflectionProviderProvider; $this->phpVersion = $phpVersion; $this->operatorTypeSpecifyingExtensionRegistryProvider = $operatorTypeSpecifyingExtensionRegistryProvider; $this->oversizedArrayBuilder = $oversizedArrayBuilder; $this->usePathConstantsAsConstantString = $usePathConstantsAsConstantString; } /** @api */ public function getType(Expr $expr, \PHPStan\Reflection\InitializerExprContext $context) : Type { if ($expr instanceof TypeExpr) { return $expr->getExprType(); } if ($expr instanceof LNumber) { return new ConstantIntegerType($expr->value); } if ($expr instanceof DNumber) { return new ConstantFloatType($expr->value); } if ($expr instanceof String_) { return new ConstantStringType($expr->value); } if ($expr instanceof ConstFetch) { $constName = (string) $expr->name; $loweredConstName = strtolower($constName); if ($loweredConstName === 'true') { return new ConstantBooleanType(\true); } elseif ($loweredConstName === 'false') { return new ConstantBooleanType(\false); } elseif ($loweredConstName === 'null') { return new NullType(); } $constant = $this->constantResolver->resolveConstant($expr->name, $context); if ($constant !== null) { return $constant; } return new ErrorType(); } if ($expr instanceof File) { $file = $context->getFile(); if ($file === null) { return new StringType(); } $stringType = new ConstantStringType($file); return $this->usePathConstantsAsConstantString ? $stringType : $stringType->generalize(GeneralizePrecision::moreSpecific()); } if ($expr instanceof Dir) { $file = $context->getFile(); if ($file === null) { return new StringType(); } $stringType = new ConstantStringType(dirname($file)); return $this->usePathConstantsAsConstantString ? $stringType : $stringType->generalize(GeneralizePrecision::moreSpecific()); } if ($expr instanceof Line) { return new ConstantIntegerType($expr->getStartLine()); } if ($expr instanceof Expr\New_) { if ($expr->class instanceof Name) { return new ObjectType((string) $expr->class); } return new ObjectWithoutClassType(); } if ($expr instanceof Expr\Array_) { return $this->getArrayType($expr, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\ArrayDimFetch && $expr->dim !== null) { $var = $this->getType($expr->var, $context); $dim = $this->getType($expr->dim, $context); return $var->getOffsetValueType($dim); } if ($expr instanceof ClassConstFetch && $expr->name instanceof Identifier) { return $this->getClassConstFetchType($expr->class, $expr->name->toString(), $context->getClassName(), function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\UnaryPlus) { return $this->getType($expr->expr, $context)->toNumber(); } if ($expr instanceof Expr\UnaryMinus) { return $this->getUnaryMinusType($expr->expr, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\Coalesce) { $leftType = $this->getType($expr->left, $context); $rightType = $this->getType($expr->right, $context); return TypeCombinator::union(TypeCombinator::removeNull($leftType), $rightType); } if ($expr instanceof Expr\Ternary) { $condType = $this->getType($expr->cond, $context); $elseType = $this->getType($expr->else, $context); if ($expr->if === null) { return TypeCombinator::union(TypeCombinator::removeFalsey($condType), $elseType); } $ifType = $this->getType($expr->if, $context); return TypeCombinator::union(TypeCombinator::removeFalsey($ifType), $elseType); } if ($expr instanceof Expr\FuncCall && $expr->name instanceof Name && $expr->name->toLowerString() === 'constant') { $firstArg = $expr->args[0] ?? null; if ($firstArg instanceof Arg && $firstArg->value instanceof String_) { $constant = $this->constantResolver->resolvePredefinedConstant($firstArg->value->value); if ($constant !== null) { return $constant; } } } if ($expr instanceof Expr\BooleanNot) { $exprBooleanType = $this->getType($expr->expr, $context)->toBoolean(); if ($exprBooleanType instanceof ConstantBooleanType) { return new ConstantBooleanType(!$exprBooleanType->getValue()); } return new BooleanType(); } if ($expr instanceof Expr\BitwiseNot) { return $this->getBitwiseNotType($expr->expr, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\Concat) { return $this->getConcatType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\BitwiseAnd) { return $this->getBitwiseAndType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\BitwiseOr) { return $this->getBitwiseOrType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\BitwiseXor) { return $this->getBitwiseXorType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\Spaceship) { return $this->getSpaceshipType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\BooleanAnd || $expr instanceof Expr\BinaryOp\LogicalAnd || $expr instanceof Expr\BinaryOp\BooleanOr || $expr instanceof Expr\BinaryOp\LogicalOr) { return new BooleanType(); } if ($expr instanceof Expr\BinaryOp\Div) { return $this->getDivType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\Mod) { return $this->getModType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\Plus) { return $this->getPlusType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\Minus) { return $this->getMinusType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\Mul) { return $this->getMulType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\Pow) { return $this->getPowType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\ShiftLeft) { return $this->getShiftLeftType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof Expr\BinaryOp\ShiftRight) { return $this->getShiftRightType($expr->left, $expr->right, function (Expr $expr) use($context) : Type { return $this->getType($expr, $context); }); } if ($expr instanceof BinaryOp\Identical) { return $this->resolveIdenticalType($this->getType($expr->left, $context), $this->getType($expr->right, $context))->type; } if ($expr instanceof BinaryOp\NotIdentical) { return $this->getType(new Expr\BooleanNot(new BinaryOp\Identical($expr->left, $expr->right)), $context); } if ($expr instanceof BinaryOp\Equal) { return $this->resolveEqualType($this->getType($expr->left, $context), $this->getType($expr->right, $context))->type; } if ($expr instanceof BinaryOp\NotEqual) { return $this->getType(new Expr\BooleanNot(new BinaryOp\Equal($expr->left, $expr->right)), $context); } if ($expr instanceof Expr\BinaryOp\Smaller) { return $this->getType($expr->left, $context)->isSmallerThan($this->getType($expr->right, $context))->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\SmallerOrEqual) { return $this->getType($expr->left, $context)->isSmallerThanOrEqual($this->getType($expr->right, $context))->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\Greater) { return $this->getType($expr->right, $context)->isSmallerThan($this->getType($expr->left, $context))->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\GreaterOrEqual) { return $this->getType($expr->right, $context)->isSmallerThanOrEqual($this->getType($expr->left, $context))->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\LogicalXor) { $leftBooleanType = $this->getType($expr->left, $context)->toBoolean(); $rightBooleanType = $this->getType($expr->right, $context)->toBoolean(); if ($leftBooleanType instanceof ConstantBooleanType && $rightBooleanType instanceof ConstantBooleanType) { return new ConstantBooleanType($leftBooleanType->getValue() xor $rightBooleanType->getValue()); } return new BooleanType(); } if ($expr instanceof MagicConst\Class_) { if ($context->getTraitName() !== null) { return TypeCombinator::intersect(new ClassStringType(), new AccessoryLiteralStringType()); } if ($context->getClassName() === null) { return new ConstantStringType(''); } return new ConstantStringType($context->getClassName(), \true); } if ($expr instanceof MagicConst\Namespace_) { if ($context->getTraitName() !== null) { return TypeCombinator::intersect(new StringType(), new AccessoryLiteralStringType()); } return new ConstantStringType($context->getNamespace() ?? ''); } if ($expr instanceof MagicConst\Method) { return new ConstantStringType($context->getMethod() ?? ''); } if ($expr instanceof MagicConst\Function_) { return new ConstantStringType($context->getFunction() ?? ''); } if ($expr instanceof MagicConst\Trait_) { if ($context->getTraitName() === null) { return new ConstantStringType(''); } return new ConstantStringType($context->getTraitName(), \true); } if ($expr instanceof PropertyFetch && $expr->name instanceof Identifier) { $fetchedOnType = $this->getType($expr->var, $context); if (!$fetchedOnType->hasProperty($expr->name->name)->yes()) { return new ErrorType(); } return $fetchedOnType->getProperty($expr->name->name, new OutOfClassScope())->getReadableType(); } return new MixedType(); } /** * @param callable(Expr): Type $getTypeCallback */ public function getConcatType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); return $this->resolveConcatType($leftType, $rightType); } public function resolveConcatType(Type $left, Type $right) : Type { $leftStringType = $left->toString(); $rightStringType = $right->toString(); if (TypeCombinator::union($leftStringType, $rightStringType) instanceof ErrorType) { return new ErrorType(); } if ($leftStringType instanceof ConstantStringType && $leftStringType->getValue() === '') { return $rightStringType; } if ($rightStringType instanceof ConstantStringType && $rightStringType->getValue() === '') { return $leftStringType; } if ($leftStringType instanceof ConstantStringType && $rightStringType instanceof ConstantStringType) { return $leftStringType->append($rightStringType); } $leftConstantStrings = $leftStringType->getConstantStrings(); $rightConstantStrings = $rightStringType->getConstantStrings(); $combinedConstantStringsCount = count($leftConstantStrings) * count($rightConstantStrings); // we limit the number of union-types for performance reasons if ($combinedConstantStringsCount > 0 && $combinedConstantStringsCount <= 16) { $strings = []; foreach ($leftConstantStrings as $leftConstantString) { if ($leftConstantString->getValue() === '') { $strings = array_merge($strings, $rightConstantStrings); continue; } foreach ($rightConstantStrings as $rightConstantString) { if ($rightConstantString->getValue() === '') { $strings[] = $leftConstantString; continue; } $strings[] = $leftConstantString->append($rightConstantString); } } if (count($strings) > 0) { return TypeCombinator::union(...$strings); } } $accessoryTypes = []; if ($leftStringType->isNonEmptyString()->and($rightStringType->isNonEmptyString())->yes()) { $accessoryTypes[] = new AccessoryNonFalsyStringType(); } elseif ($leftStringType->isNonFalsyString()->or($rightStringType->isNonFalsyString())->yes()) { $accessoryTypes[] = new AccessoryNonFalsyStringType(); } elseif ($leftStringType->isNonEmptyString()->or($rightStringType->isNonEmptyString())->yes()) { $accessoryTypes[] = new AccessoryNonEmptyStringType(); } if ($leftStringType->isLiteralString()->and($rightStringType->isLiteralString())->yes()) { $accessoryTypes[] = new AccessoryLiteralStringType(); } if ($leftStringType->isLowercaseString()->and($rightStringType->isLowercaseString())->yes()) { $accessoryTypes[] = new AccessoryLowercaseStringType(); } if ($leftStringType->isUppercaseString()->and($rightStringType->isUppercaseString())->yes()) { $accessoryTypes[] = new AccessoryUppercaseStringType(); } $leftNumericStringNonEmpty = TypeCombinator::remove($leftStringType, new ConstantStringType('')); if ($leftNumericStringNonEmpty->isNumericString()->yes()) { $allRightConstantsZeroOrMore = \false; foreach ($rightConstantStrings as $rightConstantString) { if ($rightConstantString->getValue() === '') { continue; } if (!is_numeric($rightConstantString->getValue()) || Strings::match($rightConstantString->getValue(), '#^[0-9]+$#') === null) { $allRightConstantsZeroOrMore = \false; break; } $allRightConstantsZeroOrMore = \true; } $zeroOrMoreInteger = IntegerRangeType::fromInterval(0, null); $nonNegativeRight = $allRightConstantsZeroOrMore || $zeroOrMoreInteger->isSuperTypeOf($right)->yes(); if ($nonNegativeRight) { $accessoryTypes[] = new AccessoryNumericStringType(); } } if (count($accessoryTypes) > 0) { $accessoryTypes[] = new StringType(); return new IntersectionType($accessoryTypes); } return new StringType(); } /** * @param callable(Expr): Type $getTypeCallback */ public function getArrayType(Expr\Array_ $expr, callable $getTypeCallback) : Type { if (count($expr->items) > ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { return $this->oversizedArrayBuilder->build($expr, $getTypeCallback); } $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); $isList = null; foreach ($expr->items as $arrayItem) { if ($arrayItem === null) { continue; } $valueType = $getTypeCallback($arrayItem->value); if ($arrayItem->unpack) { $constantArrays = $valueType->getConstantArrays(); if (count($constantArrays) === 1) { $constantArrayType = $constantArrays[0]; $hasStringKey = \false; foreach ($constantArrayType->getKeyTypes() as $keyType) { if ($keyType->isString()->yes()) { $hasStringKey = \true; break; } } foreach ($constantArrayType->getValueTypes() as $i => $innerValueType) { if ($hasStringKey && $this->phpVersion->supportsArrayUnpackingWithStringKeys()) { $arrayBuilder->setOffsetValueType($constantArrayType->getKeyTypes()[$i], $innerValueType, $constantArrayType->isOptionalKey($i)); } else { $arrayBuilder->setOffsetValueType(null, $innerValueType, $constantArrayType->isOptionalKey($i)); } } } else { $arrayBuilder->degradeToGeneralArray(); if ($this->phpVersion->supportsArrayUnpackingWithStringKeys() && !$valueType->getIterableKeyType()->isString()->no()) { $isList = \false; $offsetType = $valueType->getIterableKeyType(); } else { $isList = $isList ?? $arrayBuilder->isList(); $offsetType = new IntegerType(); } $arrayBuilder->setOffsetValueType($offsetType, $valueType->getIterableValueType(), !$valueType->isIterableAtLeastOnce()->yes()); } } else { $arrayBuilder->setOffsetValueType($arrayItem->key !== null ? $getTypeCallback($arrayItem->key) : null, $valueType); } } $arrayType = $arrayBuilder->getArray(); if ($isList === \true) { return AccessoryArrayListType::intersectWith($arrayType); } return $arrayType; } /** * @param callable(Expr): Type $getTypeCallback */ public function getBitwiseAndType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { if ($leftTypeInner instanceof ConstantStringType && $rightTypeInner instanceof ConstantStringType) { $resultType = $this->getTypeFromValue($leftTypeInner->getValue() & $rightTypeInner->getValue()); } else { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } $resultType = $this->getTypeFromValue($leftNumberType->getValue() & $rightNumberType->getValue()); } $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } if ($leftType->isString()->yes() && $rightType->isString()->yes()) { return new StringType(); } $leftNumberType = $leftType->toNumber(); $rightNumberType = $rightType->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if ($rightNumberType instanceof ConstantIntegerType && $rightNumberType->getValue() >= 0) { return IntegerRangeType::fromInterval(0, $rightNumberType->getValue()); } if ($leftNumberType instanceof ConstantIntegerType && $leftNumberType->getValue() >= 0) { return IntegerRangeType::fromInterval(0, $leftNumberType->getValue()); } return new IntegerType(); } /** * @param callable(Expr): Type $getTypeCallback */ public function getBitwiseOrType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { if ($leftTypeInner instanceof ConstantStringType && $rightTypeInner instanceof ConstantStringType) { $resultType = $this->getTypeFromValue($leftTypeInner->getValue() | $rightTypeInner->getValue()); } else { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } $resultType = $this->getTypeFromValue($leftNumberType->getValue() | $rightNumberType->getValue()); } $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } if ($leftType->isString()->yes() && $rightType->isString()->yes()) { return new StringType(); } if (TypeCombinator::union($leftType->toNumber(), $rightType->toNumber()) instanceof ErrorType) { return new ErrorType(); } return new IntegerType(); } /** * @param callable(Expr): Type $getTypeCallback */ public function getBitwiseXorType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { if ($leftTypeInner instanceof ConstantStringType && $rightTypeInner instanceof ConstantStringType) { $resultType = $this->getTypeFromValue($leftTypeInner->getValue() ^ $rightTypeInner->getValue()); } else { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } $resultType = $this->getTypeFromValue($leftNumberType->getValue() ^ $rightNumberType->getValue()); } $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } if ($leftType->isString()->yes() && $rightType->isString()->yes()) { return new StringType(); } if (TypeCombinator::union($leftType->toNumber(), $rightType->toNumber()) instanceof ErrorType) { return new ErrorType(); } return new IntegerType(); } /** * @param callable(Expr): Type $getTypeCallback */ public function getSpaceshipType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $callbackLeftType = $getTypeCallback($left); $callbackRightType = $getTypeCallback($right); if ($callbackLeftType instanceof NeverType || $callbackRightType instanceof NeverType) { return $this->getNeverType($callbackLeftType, $callbackRightType); } $leftTypes = $callbackLeftType->getConstantScalarTypes(); $rightTypes = $callbackRightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0 && $leftTypesCount * $rightTypesCount <= self::CALCULATE_SCALARS_LIMIT) { $resultTypes = []; foreach ($leftTypes as $leftType) { foreach ($rightTypes as $rightType) { $leftValue = $leftType->getValue(); $rightValue = $rightType->getValue(); $resultType = $this->getTypeFromValue($leftValue <=> $rightValue); $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } return IntegerRangeType::fromInterval(-1, 1); } /** * @param callable(Expr): Type $getTypeCallback */ public function getDivType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } if (in_array($rightNumberType->getValue(), [0, 0.0], \true)) { return new ErrorType(); } $resultType = $this->getTypeFromValue($leftNumberType->getValue() / $rightNumberType->getValue()); // @phpstan-ignore binaryOp.invalid $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } $rightScalarValues = $rightType->toNumber()->getConstantScalarValues(); foreach ($rightScalarValues as $scalarValue) { if ($scalarValue === 0 || $scalarValue === 0.0) { return new ErrorType(); } } return $this->resolveCommonMath(new BinaryOp\Div($left, $right), $leftType, $rightType); } /** * @param callable(Expr): Type $getTypeCallback */ public function getModType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } if ($leftType->toNumber() instanceof ErrorType || $rightType->toNumber() instanceof ErrorType) { return new ErrorType(); } $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } $rightIntegerValue = (int) $rightNumberType->getValue(); if ($rightIntegerValue === 0) { return new ErrorType(); } $resultType = $this->getTypeFromValue((int) $leftNumberType->getValue() % $rightIntegerValue); $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } $integerType = $rightType->toInteger(); if ($integerType instanceof ConstantIntegerType && $integerType->getValue() === 1) { return new ConstantIntegerType(0); } $rightScalarValues = $rightType->toNumber()->getConstantScalarValues(); foreach ($rightScalarValues as $scalarValue) { if ($scalarValue === 0 || $scalarValue === 0.0) { return new ErrorType(); } } $positiveInt = IntegerRangeType::fromInterval(0, null); if ($rightType->isInteger()->yes()) { $rangeMin = null; $rangeMax = null; if ($rightType instanceof IntegerRangeType) { $rangeMax = $rightType->getMax() !== null ? $rightType->getMax() - 1 : null; } elseif ($rightType instanceof ConstantIntegerType) { $rangeMax = $rightType->getValue() - 1; } elseif ($rightType instanceof UnionType) { foreach ($rightType->getTypes() as $type) { if ($type instanceof IntegerRangeType) { if ($type->getMax() === null) { $rangeMax = null; } else { $rangeMax = max($rangeMax, $type->getMax()); } } elseif ($type instanceof ConstantIntegerType) { $rangeMax = max($rangeMax, $type->getValue() - 1); } } } if ($positiveInt->isSuperTypeOf($leftType)->yes()) { $rangeMin = 0; } elseif ($rangeMax !== null) { $rangeMin = $rangeMax * -1; } return IntegerRangeType::fromInterval($rangeMin, $rangeMax); } elseif ($positiveInt->isSuperTypeOf($leftType)->yes()) { return IntegerRangeType::fromInterval(0, null); } return new IntegerType(); } /** * @param callable(Expr): Type $getTypeCallback */ public function getPlusType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } $resultType = $this->getTypeFromValue($leftNumberType->getValue() + $rightNumberType->getValue()); $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } $leftConstantArrays = $leftType->getConstantArrays(); $rightConstantArrays = $rightType->getConstantArrays(); $leftCount = count($leftConstantArrays); $rightCount = count($rightConstantArrays); if ($leftCount > 0 && $rightCount > 0 && $leftCount + $rightCount < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { $resultTypes = []; foreach ($rightConstantArrays as $rightConstantArray) { foreach ($leftConstantArrays as $leftConstantArray) { $newArrayBuilder = ConstantArrayTypeBuilder::createFromConstantArray($rightConstantArray); foreach ($leftConstantArray->getKeyTypes() as $i => $leftKeyType) { $optional = $leftConstantArray->isOptionalKey($i); $valueType = $leftConstantArray->getOffsetValueType($leftKeyType); if (!$optional) { if ($rightConstantArray->hasOffsetValueType($leftKeyType)->maybe()) { $valueType = TypeCombinator::union($valueType, $rightConstantArray->getOffsetValueType($leftKeyType)); } } $newArrayBuilder->setOffsetValueType($leftKeyType, $valueType, $optional); } $resultTypes[] = $newArrayBuilder->getArray(); } } return TypeCombinator::union(...$resultTypes); } $leftIsArray = $leftType->isArray(); $rightIsArray = $rightType->isArray(); if ($leftIsArray->yes() && $rightIsArray->yes()) { if ($leftType->getIterableKeyType()->equals($rightType->getIterableKeyType())) { // to preserve BenevolentUnionType $keyType = $leftType->getIterableKeyType(); } else { $keyTypes = []; foreach ([$leftType->getIterableKeyType(), $rightType->getIterableKeyType()] as $keyType) { $keyTypes[] = $keyType; } $keyType = TypeCombinator::union(...$keyTypes); } $arrayType = new ArrayType($keyType, TypeCombinator::union($leftType->getIterableValueType(), $rightType->getIterableValueType())); if ($leftType->isIterableAtLeastOnce()->yes() || $rightType->isIterableAtLeastOnce()->yes()) { $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } if ($leftType->isList()->yes() && $rightType->isList()->yes()) { $arrayType = AccessoryArrayListType::intersectWith($arrayType); } return $arrayType; } if ($leftType instanceof MixedType && $rightType instanceof MixedType) { if ($leftIsArray->no() && $rightIsArray->no()) { return new BenevolentUnionType([new FloatType(), new IntegerType()]); } return new BenevolentUnionType([new FloatType(), new IntegerType(), new ArrayType(new MixedType(), new MixedType())]); } if ($leftIsArray->yes() && $rightIsArray->no() || $leftIsArray->no() && $rightIsArray->yes()) { return new ErrorType(); } if ($leftIsArray->yes() && $rightIsArray->maybe() || $leftIsArray->maybe() && $rightIsArray->yes()) { $resultType = new ArrayType(new MixedType(), new MixedType()); if ($leftType->isIterableAtLeastOnce()->yes() || $rightType->isIterableAtLeastOnce()->yes()) { return TypeCombinator::intersect($resultType, new NonEmptyArrayType()); } return $resultType; } if ($leftIsArray->maybe() && $rightIsArray->maybe()) { $plusable = new UnionType([new StringType(), new FloatType(), new IntegerType(), new ArrayType(new MixedType(), new MixedType()), new BooleanType()]); $plusableSuperTypeOfLeft = $plusable->isSuperTypeOf($leftType)->yes(); $plusableSuperTypeOfRight = $plusable->isSuperTypeOf($rightType)->yes(); if ($plusableSuperTypeOfLeft && $plusableSuperTypeOfRight) { return TypeCombinator::union($leftType, $rightType); } if ($plusableSuperTypeOfLeft && $rightType instanceof MixedType) { return $leftType; } if ($plusableSuperTypeOfRight && $leftType instanceof MixedType) { return $rightType; } } return $this->resolveCommonMath(new BinaryOp\Plus($left, $right), $leftType, $rightType); } /** * @param callable(Expr): Type $getTypeCallback */ public function getMinusType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } $resultType = $this->getTypeFromValue($leftNumberType->getValue() - $rightNumberType->getValue()); $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } return $this->resolveCommonMath(new BinaryOp\Minus($left, $right), $leftType, $rightType); } /** * @param callable(Expr): Type $getTypeCallback */ public function getMulType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } $resultType = $this->getTypeFromValue($leftNumberType->getValue() * $rightNumberType->getValue()); $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } $leftNumberType = $leftType->toNumber(); if ($leftNumberType instanceof ConstantIntegerType && $leftNumberType->getValue() === 0) { if ($rightType->isFloat()->yes()) { return new ConstantFloatType(0.0); } return new ConstantIntegerType(0); } $rightNumberType = $rightType->toNumber(); if ($rightNumberType instanceof ConstantIntegerType && $rightNumberType->getValue() === 0) { if ($leftType->isFloat()->yes()) { return new ConstantFloatType(0.0); } return new ConstantIntegerType(0); } return $this->resolveCommonMath(new BinaryOp\Mul($left, $right), $leftType, $rightType); } /** * @param callable(Expr): Type $getTypeCallback */ public function getPowType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); $exponentiatedTyped = $leftType->exponentiate($rightType); if (!$exponentiatedTyped instanceof ErrorType) { return $exponentiatedTyped; } $extensionSpecified = $this->callOperatorTypeSpecifyingExtensions(new BinaryOp\Pow($left, $right), $leftType, $rightType); if ($extensionSpecified !== null) { return $extensionSpecified; } return new ErrorType(); } /** * @param callable(Expr): Type $getTypeCallback */ public function getShiftLeftType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } if ($rightNumberType->getValue() < 0) { return new ErrorType(); } $resultType = $this->getTypeFromValue(intval($leftNumberType->getValue()) << intval($rightNumberType->getValue())); $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } $leftNumberType = $leftType->toNumber(); $rightNumberType = $rightType->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } return $this->resolveCommonMath(new Expr\BinaryOp\ShiftLeft($left, $right), $leftType, $rightType); } /** * @param callable(Expr): Type $getTypeCallback */ public function getShiftRightType(Expr $left, Expr $right, callable $getTypeCallback) : Type { $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return $this->getNeverType($leftType, $rightType); } $leftTypes = $leftType->getConstantScalarTypes(); $rightTypes = $rightType->getConstantScalarTypes(); $leftTypesCount = count($leftTypes); $rightTypesCount = count($rightTypes); if ($leftTypesCount > 0 && $rightTypesCount > 0) { $resultTypes = []; $generalize = $leftTypesCount * $rightTypesCount > self::CALCULATE_SCALARS_LIMIT; if (!$generalize) { foreach ($leftTypes as $leftTypeInner) { foreach ($rightTypes as $rightTypeInner) { $leftNumberType = $leftTypeInner->toNumber(); $rightNumberType = $rightTypeInner->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if (!$leftNumberType instanceof ConstantScalarType || !$rightNumberType instanceof ConstantScalarType) { throw new ShouldNotHappenException(); } if ($rightNumberType->getValue() < 0) { return new ErrorType(); } $resultType = $this->getTypeFromValue(intval($leftNumberType->getValue()) >> intval($rightNumberType->getValue())); $resultTypes[] = $resultType; } } return TypeCombinator::union(...$resultTypes); } $leftType = $this->optimizeScalarType($leftType); $rightType = $this->optimizeScalarType($rightType); } $leftNumberType = $leftType->toNumber(); $rightNumberType = $rightType->toNumber(); if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } return $this->resolveCommonMath(new Expr\BinaryOp\ShiftRight($left, $right), $leftType, $rightType); } private function optimizeScalarType(Type $type) : Type { $types = []; if ($type->isInteger()->yes()) { $types[] = new IntegerType(); } if ($type->isString()->yes()) { $types[] = new StringType(); } if ($type->isFloat()->yes()) { $types[] = new FloatType(); } if ($type->isNull()->yes()) { $types[] = new NullType(); } if (count($types) === 0) { return new ErrorType(); } if (count($types) === 1) { return $types[0]; } return new UnionType($types); } /** * @return TypeResult */ public function resolveIdenticalType(Type $leftType, Type $rightType) : TypeResult { if ($leftType instanceof NeverType || $rightType instanceof NeverType) { return new TypeResult(new ConstantBooleanType(\false), []); } if ($leftType instanceof ConstantScalarType && $rightType instanceof ConstantScalarType) { return new TypeResult(new ConstantBooleanType($leftType->getValue() === $rightType->getValue()), []); } $leftTypeFiniteTypes = $leftType->getFiniteTypes(); $rightTypeFiniteType = $rightType->getFiniteTypes(); if (count($leftTypeFiniteTypes) === 1 && count($rightTypeFiniteType) === 1) { return new TypeResult(new ConstantBooleanType($leftTypeFiniteTypes[0]->equals($rightTypeFiniteType[0])), []); } $leftIsSuperTypeOfRight = $leftType->isSuperTypeOfWithReason($rightType); $rightIsSuperTypeOfLeft = $rightType->isSuperTypeOfWithReason($leftType); if ($leftIsSuperTypeOfRight->no() && $rightIsSuperTypeOfLeft->no()) { return new TypeResult(new ConstantBooleanType(\false), array_merge($leftIsSuperTypeOfRight->reasons, $rightIsSuperTypeOfLeft->reasons)); } if ($leftType instanceof ConstantArrayType && $rightType instanceof ConstantArrayType) { return $this->resolveConstantArrayTypeComparison($leftType, $rightType, function ($leftValueType, $rightValueType) : TypeResult { return $this->resolveIdenticalType($leftValueType, $rightValueType); }); } return new TypeResult(new BooleanType(), []); } /** * @return TypeResult */ public function resolveEqualType(Type $leftType, Type $rightType) : TypeResult { if ($leftType->isEnum()->yes() && $rightType->isTrue()->no() || $rightType->isEnum()->yes() && $leftType->isTrue()->no()) { return $this->resolveIdenticalType($leftType, $rightType); } if ($leftType instanceof ConstantArrayType && $rightType instanceof ConstantArrayType) { return $this->resolveConstantArrayTypeComparison($leftType, $rightType, function ($leftValueType, $rightValueType) : TypeResult { return $this->resolveEqualType($leftValueType, $rightValueType); }); } return new TypeResult($leftType->looseCompare($rightType, $this->phpVersion), []); } /** * @param callable(Type, Type): TypeResult $valueComparisonCallback * @return TypeResult */ private function resolveConstantArrayTypeComparison(ConstantArrayType $leftType, ConstantArrayType $rightType, callable $valueComparisonCallback) : TypeResult { $leftKeyTypes = $leftType->getKeyTypes(); $rightKeyTypes = $rightType->getKeyTypes(); $leftValueTypes = $leftType->getValueTypes(); $rightValueTypes = $rightType->getValueTypes(); $resultType = new ConstantBooleanType(\true); foreach ($leftKeyTypes as $i => $leftKeyType) { $leftOptional = $leftType->isOptionalKey($i); if ($leftOptional) { $resultType = new BooleanType(); } if (count($rightKeyTypes) === 0) { if (!$leftOptional) { return new TypeResult(new ConstantBooleanType(\false), []); } continue; } $found = \false; foreach ($rightKeyTypes as $j => $rightKeyType) { unset($rightKeyTypes[$j]); if ($leftKeyType->equals($rightKeyType)) { $found = \true; break; } elseif (!$rightType->isOptionalKey($j)) { return new TypeResult(new ConstantBooleanType(\false), []); } } if (!$found) { if (!$leftOptional) { return new TypeResult(new ConstantBooleanType(\false), []); } continue; } if (!isset($j)) { throw new ShouldNotHappenException(); } $rightOptional = $rightType->isOptionalKey($j); if ($rightOptional) { $resultType = new BooleanType(); if ($leftOptional) { continue; } } $leftIdenticalToRightResult = $valueComparisonCallback($leftValueTypes[$i], $rightValueTypes[$j]); $leftIdenticalToRight = $leftIdenticalToRightResult->type; if ($leftIdenticalToRight->isFalse()->yes()) { return $leftIdenticalToRightResult; } $resultType = TypeCombinator::union($resultType, $leftIdenticalToRight); } foreach (array_keys($rightKeyTypes) as $j) { if (!$rightType->isOptionalKey($j)) { return new TypeResult(new ConstantBooleanType(\false), []); } $resultType = new BooleanType(); } return new TypeResult($resultType->toBoolean(), []); } private function callOperatorTypeSpecifyingExtensions(Expr\BinaryOp $expr, Type $leftType, Type $rightType) : ?Type { $operatorSigil = $expr->getOperatorSigil(); $operatorTypeSpecifyingExtensions = $this->operatorTypeSpecifyingExtensionRegistryProvider->getRegistry()->getOperatorTypeSpecifyingExtensions($operatorSigil, $leftType, $rightType); /** @var Type[] $extensionTypes */ $extensionTypes = []; foreach ($operatorTypeSpecifyingExtensions as $extension) { $extensionTypes[] = $extension->specifyType($operatorSigil, $leftType, $rightType); } if (count($extensionTypes) > 0) { return TypeCombinator::union(...$extensionTypes); } return null; } /** * @param BinaryOp\Plus|BinaryOp\Minus|BinaryOp\Mul|BinaryOp\Div|BinaryOp\ShiftLeft|BinaryOp\ShiftRight $expr */ private function resolveCommonMath(Expr\BinaryOp $expr, Type $leftType, Type $rightType) : Type { $types = TypeCombinator::union($leftType, $rightType); $leftNumberType = $leftType->toNumber(); $rightNumberType = $rightType->toNumber(); if (!$types instanceof MixedType && ($rightNumberType instanceof IntegerRangeType || $rightNumberType instanceof ConstantIntegerType || $rightNumberType instanceof UnionType)) { if ($leftNumberType instanceof IntegerRangeType || $leftNumberType instanceof ConstantIntegerType) { return $this->integerRangeMath($leftNumberType, $expr, $rightNumberType); } elseif ($leftNumberType instanceof UnionType) { $unionParts = []; foreach ($leftNumberType->getTypes() as $type) { $numberType = $type->toNumber(); if ($numberType instanceof IntegerRangeType || $numberType instanceof ConstantIntegerType) { $unionParts[] = $this->integerRangeMath($numberType, $expr, $rightNumberType); } else { $unionParts[] = $numberType; } } $union = TypeCombinator::union(...$unionParts); if ($leftNumberType instanceof BenevolentUnionType) { return TypeUtils::toBenevolentUnion($union)->toNumber(); } return $union->toNumber(); } } $specifiedTypes = $this->callOperatorTypeSpecifyingExtensions($expr, $leftType, $rightType); if ($specifiedTypes !== null) { return $specifiedTypes; } if ($leftType->isArray()->yes() || $rightType->isArray()->yes() || $types->isArray()->yes()) { return new ErrorType(); } if ($leftNumberType instanceof ErrorType || $rightNumberType instanceof ErrorType) { return new ErrorType(); } if ($leftNumberType instanceof NeverType || $rightNumberType instanceof NeverType) { return $this->getNeverType($leftNumberType, $rightNumberType); } if ($leftNumberType->isFloat()->yes() || $rightNumberType->isFloat()->yes()) { if ($expr instanceof Expr\BinaryOp\ShiftLeft || $expr instanceof Expr\BinaryOp\ShiftRight) { return new IntegerType(); } return new FloatType(); } $resultType = TypeCombinator::union($leftNumberType, $rightNumberType); if ($expr instanceof Expr\BinaryOp\Div) { if ($types instanceof MixedType || $resultType->isInteger()->yes()) { return new BenevolentUnionType([new IntegerType(), new FloatType()]); } return new UnionType([new IntegerType(), new FloatType()]); } if ($types instanceof MixedType || $leftType instanceof BenevolentUnionType || $rightType instanceof BenevolentUnionType) { return TypeUtils::toBenevolentUnion($resultType); } return $resultType; } /** * @param ConstantIntegerType|IntegerRangeType $range * @param BinaryOp\Div|BinaryOp\Minus|BinaryOp\Mul|BinaryOp\Plus|BinaryOp\ShiftLeft|BinaryOp\ShiftRight $node */ private function integerRangeMath(Type $range, BinaryOp $node, Type $operand) : Type { if ($range instanceof IntegerRangeType) { $rangeMin = $range->getMin(); $rangeMax = $range->getMax(); } else { $rangeMin = $range->getValue(); $rangeMax = $rangeMin; } if ($operand instanceof UnionType) { $unionParts = []; foreach ($operand->getTypes() as $type) { $numberType = $type->toNumber(); if ($numberType instanceof IntegerRangeType || $numberType instanceof ConstantIntegerType) { $unionParts[] = $this->integerRangeMath($range, $node, $numberType); } else { $unionParts[] = $type->toNumber(); } } $union = TypeCombinator::union(...$unionParts); if ($operand instanceof BenevolentUnionType) { return TypeUtils::toBenevolentUnion($union)->toNumber(); } return $union->toNumber(); } $operand = $operand->toNumber(); if ($operand instanceof IntegerRangeType) { $operandMin = $operand->getMin(); $operandMax = $operand->getMax(); } elseif ($operand instanceof ConstantIntegerType) { $operandMin = $operand->getValue(); $operandMax = $operand->getValue(); } else { return $operand; } if ($node instanceof BinaryOp\Plus) { if ($operand instanceof ConstantIntegerType) { /** @var int|float|null $min */ $min = $rangeMin !== null ? $rangeMin + $operand->getValue() : null; /** @var int|float|null $max */ $max = $rangeMax !== null ? $rangeMax + $operand->getValue() : null; } else { /** @var int|float|null $min */ $min = $rangeMin !== null && $operand->getMin() !== null ? $rangeMin + $operand->getMin() : null; /** @var int|float|null $max */ $max = $rangeMax !== null && $operand->getMax() !== null ? $rangeMax + $operand->getMax() : null; } } elseif ($node instanceof BinaryOp\Minus) { if ($operand instanceof ConstantIntegerType) { /** @var int|float|null $min */ $min = $rangeMin !== null ? $rangeMin - $operand->getValue() : null; /** @var int|float|null $max */ $max = $rangeMax !== null ? $rangeMax - $operand->getValue() : null; } else { if ($rangeMin === $rangeMax && $rangeMin !== null && ($operand->getMin() === null || $operand->getMax() === null)) { $min = null; $max = $rangeMin; } else { if ($operand->getMin() === null) { $min = null; } elseif ($rangeMin !== null) { if ($operand->getMax() !== null) { /** @var int|float $min */ $min = $rangeMin - $operand->getMax(); } else { /** @var int|float $min */ $min = $rangeMin - $operand->getMin(); } } else { $min = null; } if ($operand->getMax() === null) { $min = null; $max = null; } elseif ($rangeMax !== null) { if ($rangeMin !== null && $operand->getMin() === null) { /** @var int|float $min */ $min = $rangeMin - $operand->getMax(); $max = null; } elseif ($operand->getMin() !== null) { /** @var int|float $max */ $max = $rangeMax - $operand->getMin(); } else { $max = null; } } else { $max = null; } if ($min !== null && $max !== null && $min > $max) { [$min, $max] = [$max, $min]; } } } } elseif ($node instanceof Expr\BinaryOp\Mul) { $min1 = $rangeMin === 0 || $operandMin === 0 ? 0 : ($rangeMin ?? -INF) * ($operandMin ?? -INF); $min2 = $rangeMin === 0 || $operandMax === 0 ? 0 : ($rangeMin ?? -INF) * ($operandMax ?? INF); $max1 = $rangeMax === 0 || $operandMin === 0 ? 0 : ($rangeMax ?? INF) * ($operandMin ?? -INF); $max2 = $rangeMax === 0 || $operandMax === 0 ? 0 : ($rangeMax ?? INF) * ($operandMax ?? INF); $min = min($min1, $min2, $max1, $max2); $max = max($min1, $min2, $max1, $max2); if (!is_finite($min)) { $min = null; } if (!is_finite($max)) { $max = null; } } elseif ($node instanceof Expr\BinaryOp\Div) { if ($operand instanceof ConstantIntegerType) { $min = $rangeMin !== null && $operand->getValue() !== 0 ? $rangeMin / $operand->getValue() : null; $max = $rangeMax !== null && $operand->getValue() !== 0 ? $rangeMax / $operand->getValue() : null; } else { // Avoid division by zero when looking for the min and the max by using the closest int $operandMin = $operandMin !== 0 ? $operandMin : 1; $operandMax = $operandMax !== 0 ? $operandMax : -1; if (($operandMin < 0 || $operandMin === null) && ($operandMax > 0 || $operandMax === null)) { $negativeOperand = IntegerRangeType::fromInterval($operandMin, 0); assert($negativeOperand instanceof IntegerRangeType); $positiveOperand = IntegerRangeType::fromInterval(0, $operandMax); assert($positiveOperand instanceof IntegerRangeType); $result = TypeCombinator::union($this->integerRangeMath($range, $node, $negativeOperand), $this->integerRangeMath($range, $node, $positiveOperand))->toNumber(); if ($result->equals(new UnionType([new IntegerType(), new FloatType()]))) { return new BenevolentUnionType([new IntegerType(), new FloatType()]); } return $result; } if (($rangeMin < 0 || $rangeMin === null) && ($rangeMax > 0 || $rangeMax === null)) { $negativeRange = IntegerRangeType::fromInterval($rangeMin, 0); assert($negativeRange instanceof IntegerRangeType); $positiveRange = IntegerRangeType::fromInterval(0, $rangeMax); assert($positiveRange instanceof IntegerRangeType); $result = TypeCombinator::union($this->integerRangeMath($negativeRange, $node, $operand), $this->integerRangeMath($positiveRange, $node, $operand))->toNumber(); if ($result->equals(new UnionType([new IntegerType(), new FloatType()]))) { return new BenevolentUnionType([new IntegerType(), new FloatType()]); } return $result; } $rangeMinSign = ($rangeMin ?? -INF) <=> 0; $rangeMaxSign = ($rangeMax ?? INF) <=> 0; $min1 = $operandMin !== null ? ($rangeMin ?? -INF) / $operandMin : $rangeMinSign * -0.1; $min2 = $operandMax !== null ? ($rangeMin ?? -INF) / $operandMax : $rangeMinSign * 0.1; $max1 = $operandMin !== null ? ($rangeMax ?? INF) / $operandMin : $rangeMaxSign * -0.1; $max2 = $operandMax !== null ? ($rangeMax ?? INF) / $operandMax : $rangeMaxSign * 0.1; $min = min($min1, $min2, $max1, $max2); $max = max($min1, $min2, $max1, $max2); if ($min === -INF) { $min = null; } if ($max === INF) { $max = null; } } if ($min !== null && $max !== null && $min > $max) { [$min, $max] = [$max, $min]; } if (is_float($min)) { $min = (int) ceil($min); } if (is_float($max)) { $max = (int) floor($max); } // invert maximas on division with negative constants if (($range instanceof ConstantIntegerType && $range->getValue() < 0 || $operand instanceof ConstantIntegerType && $operand->getValue() < 0) && ($min === null || $max === null)) { [$min, $max] = [$max, $min]; } if ($min === null && $max === null) { return new BenevolentUnionType([new IntegerType(), new FloatType()]); } return TypeCombinator::union(IntegerRangeType::fromInterval($min, $max), new FloatType()); } elseif ($node instanceof Expr\BinaryOp\ShiftLeft) { if (!$operand instanceof ConstantIntegerType) { return new IntegerType(); } if ($operand->getValue() < 0) { return new ErrorType(); } $min = $rangeMin !== null ? intval($rangeMin) << $operand->getValue() : null; $max = $rangeMax !== null ? intval($rangeMax) << $operand->getValue() : null; } elseif ($node instanceof Expr\BinaryOp\ShiftRight) { if (!$operand instanceof ConstantIntegerType) { return new IntegerType(); } if ($operand->getValue() < 0) { return new ErrorType(); } $min = $rangeMin !== null ? intval($rangeMin) >> $operand->getValue() : null; $max = $rangeMax !== null ? intval($rangeMax) >> $operand->getValue() : null; } else { throw new ShouldNotHappenException(); } if (is_float($min)) { $min = null; } if (is_float($max)) { $max = null; } return IntegerRangeType::fromInterval($min, $max); } /** * @param callable(Expr): Type $getTypeCallback * @param Name|Expr $class */ public function getClassConstFetchTypeByReflection($class, string $constantName, ?\PHPStan\Reflection\ClassReflection $classReflection, callable $getTypeCallback) : Type { $isObject = \false; if ($class instanceof Name) { $constantClass = (string) $class; $constantClassType = new ObjectType($constantClass); $namesToResolve = ['self', 'parent']; if ($classReflection !== null) { if ($classReflection->isFinal()) { $namesToResolve[] = 'static'; } elseif (strtolower($constantClass) === 'static') { if (strtolower($constantName) === 'class') { return new GenericClassStringType(new StaticType($classReflection)); } $namesToResolve[] = 'static'; $isObject = \true; } } if (in_array(strtolower($constantClass), $namesToResolve, \true)) { $resolvedName = $this->resolveName($class, $classReflection); if (strtolower($resolvedName) === 'parent' && strtolower($constantName) === 'class') { return new ClassStringType(); } $constantClassType = $this->resolveTypeByName($class, $classReflection); } if (strtolower($constantName) === 'class') { return new ConstantStringType($constantClassType->getClassName(), \true); } } elseif ($class instanceof String_ && strtolower($constantName) === 'class') { return new ConstantStringType($class->value, \true); } else { $constantClassType = $getTypeCallback($class); $isObject = \true; } if (strtolower($constantName) === 'class') { return TypeTraverser::map($constantClassType, function (Type $type, callable $traverse) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type instanceof NullType) { return $type; } if ($type instanceof EnumCaseObjectType) { return TypeCombinator::intersect(new GenericClassStringType(new ObjectType($type->getClassName())), new AccessoryLiteralStringType()); } $objectClassNames = $type->getObjectClassNames(); if (count($objectClassNames) > 1) { throw new ShouldNotHappenException(); } if ($type instanceof TemplateType && $objectClassNames === []) { return TypeCombinator::intersect(new GenericClassStringType($type), new AccessoryLiteralStringType()); } elseif ($objectClassNames !== [] && $this->getReflectionProvider()->hasClass($objectClassNames[0])) { $reflection = $this->getReflectionProvider()->getClass($objectClassNames[0]); if ($reflection->isFinalByKeyword()) { return new ConstantStringType($reflection->getName(), \true); } return TypeCombinator::intersect(new GenericClassStringType($type), new AccessoryLiteralStringType()); } elseif ($type->isObject()->yes()) { return TypeCombinator::intersect(new ClassStringType(), new AccessoryLiteralStringType()); } return new ErrorType(); }); } if ($constantClassType->isClassStringType()->yes()) { if ($constantClassType->isConstantScalarValue()->yes()) { $isObject = \false; } $constantClassType = $constantClassType->getClassStringObjectType(); } $types = []; foreach ($constantClassType->getObjectClassNames() as $referencedClass) { if (!$this->getReflectionProvider()->hasClass($referencedClass)) { continue; } $constantClassReflection = $this->getReflectionProvider()->getClass($referencedClass); if (!$constantClassReflection->hasConstant($constantName)) { continue; } if ($constantClassReflection->isEnum() && $constantClassReflection->hasEnumCase($constantName)) { $types[] = new EnumCaseObjectType($constantClassReflection->getName(), $constantName); continue; } $resolvingName = sprintf('%s::%s', $constantClassReflection->getName(), $constantName); if (array_key_exists($resolvingName, $this->currentlyResolvingClassConstant)) { $types[] = new MixedType(); continue; } $this->currentlyResolvingClassConstant[$resolvingName] = \true; if (!$isObject) { $reflectionConstant = $constantClassReflection->getNativeReflection()->getReflectionConstant($constantName); if ($reflectionConstant === \false) { unset($this->currentlyResolvingClassConstant[$resolvingName]); continue; } $reflectionConstantDeclaringClass = $reflectionConstant->getDeclaringClass(); $constantType = $this->getType($reflectionConstant->getValueExpression(), \PHPStan\Reflection\InitializerExprContext::fromClass($reflectionConstantDeclaringClass->getName(), $reflectionConstantDeclaringClass->getFileName() ?: null)); $nativeType = null; if ($reflectionConstant->getType() !== null) { $nativeType = TypehintHelper::decideTypeFromReflection($reflectionConstant->getType(), null, $constantClassReflection); } $types[] = $this->constantResolver->resolveClassConstantType($constantClassReflection->getName(), $constantName, $constantType, $nativeType); unset($this->currentlyResolvingClassConstant[$resolvingName]); continue; } $constantReflection = $constantClassReflection->getConstant($constantName); if (!$constantClassReflection->isFinal() && !$constantReflection->isFinal() && !$constantReflection->hasPhpDocType() && !$constantReflection->hasNativeType()) { unset($this->currentlyResolvingClassConstant[$resolvingName]); return new MixedType(); } if (!$constantClassReflection->isFinal()) { $constantType = $constantReflection->getValueType(); } else { $constantType = $this->getType($constantReflection->getValueExpr(), \PHPStan\Reflection\InitializerExprContext::fromClassReflection($constantReflection->getDeclaringClass())); } $nativeType = $constantReflection->getNativeType(); $constantType = $this->constantResolver->resolveClassConstantType($constantClassReflection->getName(), $constantName, $constantType, $nativeType); unset($this->currentlyResolvingClassConstant[$resolvingName]); $types[] = $constantType; } if (count($types) > 0) { return TypeCombinator::union(...$types); } if (!$constantClassType->hasConstant($constantName)->yes()) { return new ErrorType(); } return $constantClassType->getConstant($constantName)->getValueType(); } /** * @param callable(Expr): Type $getTypeCallback * @param Name|Expr $class */ public function getClassConstFetchType($class, string $constantName, ?string $className, callable $getTypeCallback) : Type { $classReflection = null; if ($className !== null && $this->getReflectionProvider()->hasClass($className)) { $classReflection = $this->getReflectionProvider()->getClass($className); } return $this->getClassConstFetchTypeByReflection($class, $constantName, $classReflection, $getTypeCallback); } /** * @param callable(Expr): Type $getTypeCallback */ public function getUnaryMinusType(Expr $expr, callable $getTypeCallback) : Type { $type = $getTypeCallback($expr)->toNumber(); $scalarValues = $type->getConstantScalarValues(); if (count($scalarValues) > 0) { $newTypes = []; foreach ($scalarValues as $scalarValue) { if (is_int($scalarValue)) { /** @var int|float $newValue */ $newValue = -$scalarValue; if (!is_int($newValue)) { return $type; } $newTypes[] = new ConstantIntegerType($newValue); } elseif (is_float($scalarValue)) { $newTypes[] = new ConstantFloatType(-$scalarValue); } } return TypeCombinator::union(...$newTypes); } if ($type instanceof IntegerRangeType) { return $getTypeCallback(new Expr\BinaryOp\Mul($expr, new LNumber(-1))); } return $type; } /** * @param callable(Expr): Type $getTypeCallback */ public function getBitwiseNotType(Expr $expr, callable $getTypeCallback) : Type { $exprType = $getTypeCallback($expr); return TypeTraverser::map($exprType, static function (Type $type, callable $traverse) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type instanceof ConstantStringType) { return new ConstantStringType(~$type->getValue()); } if ($type->isString()->yes()) { $accessories = [new StringType()]; if ($type->isNonEmptyString()->yes()) { $accessories[] = new AccessoryNonEmptyStringType(); } // it is not useful to apply numeric and literal strings here. // numeric string isn't certainly kept numeric: 3v4l.org/JERDB return TypeCombinator::intersect(...$accessories); } if ($type->isInteger()->yes() || $type->isFloat()->yes()) { return new IntegerType(); //no const types here, result depends on PHP_INT_SIZE } return new ErrorType(); }); } private function resolveName(Name $name, ?\PHPStan\Reflection\ClassReflection $classReflection) : string { $originalClass = (string) $name; if ($classReflection !== null) { $lowerClass = strtolower($originalClass); if (in_array($lowerClass, ['self', 'static'], \true)) { return $classReflection->getName(); } elseif ($lowerClass === 'parent') { if ($classReflection->getParentClass() !== null) { return $classReflection->getParentClass()->getName(); } } } return $originalClass; } private function resolveTypeByName(Name $name, ?\PHPStan\Reflection\ClassReflection $classReflection) : TypeWithClassName { if ($name->toLowerString() === 'static' && $classReflection !== null) { return new StaticType($classReflection); } $originalClass = $this->resolveName($name, $classReflection); if ($classReflection !== null) { $thisType = new ThisType($classReflection); $ancestor = $thisType->getAncestorWithClassName($originalClass); if ($ancestor !== null) { return $ancestor; } } return new ObjectType($originalClass); } /** * @param mixed $value */ private function getTypeFromValue($value) : Type { return ConstantTypeHelper::getTypeFromValue($value); } private function getReflectionProvider() : \PHPStan\Reflection\ReflectionProvider { return $this->reflectionProviderProvider->getReflectionProvider(); } private function getNeverType(Type $leftType, Type $rightType) : Type { // make sure we don't lose the explicit flag in the process if ($leftType instanceof NeverType && $leftType->isExplicit()) { return $leftType; } if ($rightType instanceof NeverType && $rightType->isExplicit()) { return $rightType; } return new NeverType(); } } getClassReflection() */ public function isInClass() : bool; public function getClassReflection() : ?\PHPStan\Reflection\ClassReflection; public function canAccessProperty(\PHPStan\Reflection\PropertyReflection $propertyReflection) : bool; public function canCallMethod(\PHPStan\Reflection\MethodReflection $methodReflection) : bool; public function canAccessConstant(\PHPStan\Reflection\ConstantReflection $constantReflection) : bool; } $argTypes */ public static function resolve(array $argTypes, \PHPStan\Reflection\ParametersAcceptor $parametersAcceptor) : \PHPStan\Reflection\ParametersAcceptorWithPhpDocs { $typeMap = TemplateTypeMap::createEmpty(); $passedArgs = []; $parameters = $parametersAcceptor->getParameters(); $namedArgTypes = []; foreach ($argTypes as $i => $argType) { if (is_int($i)) { if (isset($parameters[$i])) { $namedArgTypes[$parameters[$i]->getName()] = $argType; continue; } if (count($parameters) > 0) { $lastParameter = $parameters[count($parameters) - 1]; if ($lastParameter->isVariadic()) { $parameterName = $lastParameter->getName(); if (array_key_exists($parameterName, $namedArgTypes)) { $namedArgTypes[$parameterName] = TypeCombinator::union($namedArgTypes[$parameterName], $argType); continue; } $namedArgTypes[$parameterName] = $argType; } } continue; } $namedArgTypes[$i] = $argType; } foreach ($parametersAcceptor->getParameters() as $param) { if (isset($namedArgTypes[$param->getName()])) { $argType = $namedArgTypes[$param->getName()]; } elseif ($param->getDefaultValue() !== null) { $argType = $param->getDefaultValue(); } else { continue; } $paramType = $param->getType(); $typeMap = $typeMap->union($paramType->inferTemplateTypes($argType)); $passedArgs['$' . $param->getName()] = $argType; } $returnType = $parametersAcceptor->getReturnType(); if ($returnType instanceof ConditionalTypeForParameter && !$returnType->isNegated() && array_key_exists($returnType->getParameterName(), $passedArgs)) { $paramType = $returnType->getTarget(); $argType = $passedArgs[$returnType->getParameterName()]; $typeMap = $typeMap->union($paramType->inferTemplateTypes($argType)); } $resolvedTemplateTypeMap = new TemplateTypeMap(array_merge($parametersAcceptor->getTemplateTypeMap()->map(static function (string $name, Type $type) : Type { return new ErrorType(); })->getTypes(), $typeMap->getTypes())); $originalParametersAcceptor = $parametersAcceptor; if (!$parametersAcceptor instanceof \PHPStan\Reflection\ParametersAcceptorWithPhpDocs) { $parametersAcceptor = new \PHPStan\Reflection\FunctionVariantWithPhpDocs($parametersAcceptor->getTemplateTypeMap(), $parametersAcceptor->getResolvedTemplateTypeMap(), array_map(static function (\PHPStan\Reflection\ParameterReflection $parameter) : \PHPStan\Reflection\ParameterReflectionWithPhpDocs { return new DummyParameterWithPhpDocs($parameter->getName(), $parameter->getType(), $parameter->isOptional(), $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), new MixedType(), $parameter->getType(), null, TrinaryLogic::createMaybe(), null); }, $parametersAcceptor->getParameters()), $parametersAcceptor->isVariadic(), $parametersAcceptor->getReturnType(), $parametersAcceptor->getReturnType(), new MixedType(), TemplateTypeVarianceMap::createEmpty()); } $result = new \PHPStan\Reflection\ResolvedFunctionVariantWithOriginal($parametersAcceptor, $resolvedTemplateTypeMap, $parametersAcceptor->getCallSiteVarianceMap(), $passedArgs); if ($originalParametersAcceptor instanceof CallableParametersAcceptor) { return new \PHPStan\Reflection\ResolvedFunctionVariantWithCallable($result, $originalParametersAcceptor->getThrowPoints(), $originalParametersAcceptor->isPure(), $originalParametersAcceptor->getImpurePoints(), $originalParametersAcceptor->getInvalidateExpressions(), $originalParametersAcceptor->getUsedVariables(), $originalParametersAcceptor->acceptsNamedArguments()); } return $result; } } */ private $additionalConstructors; /** @var array> */ private $additionalConstructorsCache = []; /** * @param list $additionalConstructors */ public function __construct(Container $container, array $additionalConstructors) { $this->container = $container; $this->additionalConstructors = $additionalConstructors; } /** * @return list */ public function getConstructors(\PHPStan\Reflection\ClassReflection $classReflection) : array { if (array_key_exists($classReflection->getName(), $this->additionalConstructorsCache)) { return $this->additionalConstructorsCache[$classReflection->getName()]; } $constructors = []; if ($classReflection->hasConstructor()) { $constructors[] = $classReflection->getConstructor()->getName(); } /** @var AdditionalConstructorsExtension[] $extensions */ $extensions = $this->container->getServicesByTag(\PHPStan\Reflection\AdditionalConstructorsExtension::EXTENSION_TAG); foreach ($extensions as $extension) { $extensionConstructors = $extension->getAdditionalConstructors($classReflection); foreach ($extensionConstructors as $extensionConstructor) { $constructors[] = $extensionConstructor; } } $nativeReflection = $classReflection->getNativeReflection(); foreach ($this->additionalConstructors as $additionalConstructor) { [$className, $methodName] = explode('::', $additionalConstructor); if (!$nativeReflection->hasMethod($methodName)) { continue; } $nativeMethod = $nativeReflection->getMethod($methodName); if ($nativeMethod->getDeclaringClass()->getName() !== $nativeReflection->getName()) { continue; } try { $prototype = $nativeMethod->getPrototype(); } catch (ReflectionException $e) { $prototype = $nativeMethod; } if ($prototype->getDeclaringClass()->getName() !== $className) { continue; } $constructors[] = $methodName; } $this->additionalConstructorsCache[$classReflection->getName()] = $constructors; return $constructors; } } |null */ private $ancestors = null; /** * @var ?string */ private $cacheKey = null; /** @var array */ private $subclasses = []; /** * @var string|false|null */ private $filename = \false; /** * @var string|false|null */ private $reflectionDocComment = \false; /** * @var false|ResolvedPhpDocBlock */ private $resolvedPhpDocBlock = \false; /** * @var false|ResolvedPhpDocBlock */ private $traitContextResolvedPhpDocBlock = \false; /** @var ClassReflection[]|null */ private $cachedInterfaces = null; /** * @var ClassReflection|false|null */ private $cachedParentClass = \false; /** @var array|null */ private $typeAliases = null; /** @var array */ private static $resolvingTypeAliasImports = []; /** @var array */ private $hasMethodCache = []; /** * @param PropertiesClassReflectionExtension[] $propertiesClassReflectionExtensions * @param MethodsClassReflectionExtension[] $methodsClassReflectionExtensions * @param AllowedSubTypesClassReflectionExtension[] $allowedSubTypesClassReflectionExtensions * @param string[] $universalObjectCratesClasses * @param ReflectionClass|ReflectionEnum $reflection */ public function __construct(\PHPStan\Reflection\ReflectionProvider $reflectionProvider, \PHPStan\Reflection\InitializerExprTypeResolver $initializerExprTypeResolver, FileTypeMapper $fileTypeMapper, StubPhpDocProvider $stubPhpDocProvider, PhpDocInheritanceResolver $phpDocInheritanceResolver, PhpVersion $phpVersion, SignatureMapProvider $signatureMapProvider, array $propertiesClassReflectionExtensions, array $methodsClassReflectionExtensions, array $allowedSubTypesClassReflectionExtensions, RequireExtendsPropertiesClassReflectionExtension $requireExtendsPropertiesClassReflectionExtension, RequireExtendsMethodsClassReflectionExtension $requireExtendsMethodsClassReflectionExtension, string $displayName, $reflection, ?string $anonymousFilename, ?TemplateTypeMap $resolvedTemplateTypeMap, ?ResolvedPhpDocBlock $stubPhpDocBlock, array $universalObjectCratesClasses, ?string $extraCacheKey = null, ?TemplateTypeVarianceMap $resolvedCallSiteVarianceMap = null) { $this->reflectionProvider = $reflectionProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->fileTypeMapper = $fileTypeMapper; $this->stubPhpDocProvider = $stubPhpDocProvider; $this->phpDocInheritanceResolver = $phpDocInheritanceResolver; $this->phpVersion = $phpVersion; $this->signatureMapProvider = $signatureMapProvider; $this->propertiesClassReflectionExtensions = $propertiesClassReflectionExtensions; $this->methodsClassReflectionExtensions = $methodsClassReflectionExtensions; $this->allowedSubTypesClassReflectionExtensions = $allowedSubTypesClassReflectionExtensions; $this->requireExtendsPropertiesClassReflectionExtension = $requireExtendsPropertiesClassReflectionExtension; $this->requireExtendsMethodsClassReflectionExtension = $requireExtendsMethodsClassReflectionExtension; $this->displayName = $displayName; $this->reflection = $reflection; $this->anonymousFilename = $anonymousFilename; $this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap; $this->stubPhpDocBlock = $stubPhpDocBlock; $this->universalObjectCratesClasses = $universalObjectCratesClasses; $this->extraCacheKey = $extraCacheKey; $this->resolvedCallSiteVarianceMap = $resolvedCallSiteVarianceMap; } /** * @return ReflectionClass|ReflectionEnum */ public function getNativeReflection() { return $this->reflection; } public function getFileName() : ?string { if (!is_bool($this->filename)) { return $this->filename; } if ($this->anonymousFilename !== null) { return $this->filename = $this->anonymousFilename; } $fileName = $this->reflection->getFileName(); if ($fileName === \false) { return $this->filename = null; } if (!is_file($fileName)) { return $this->filename = null; } return $this->filename = $fileName; } /** * @deprecated Use getFileName() */ public function getFileNameWithPhpDocs() : ?string { return $this->getFileName(); } public function getParentClass() : ?\PHPStan\Reflection\ClassReflection { if (!is_bool($this->cachedParentClass)) { return $this->cachedParentClass; } $parentClass = $this->reflection->getParentClass(); if ($parentClass === \false) { return $this->cachedParentClass = null; } $extendsTag = $this->getFirstExtendsTag(); if ($extendsTag !== null && $this->isValidAncestorType($extendsTag->getType(), [$parentClass->getName()])) { $extendedType = $extendsTag->getType(); if ($this->isGeneric()) { $extendedType = TemplateTypeHelper::resolveTemplateTypes($extendedType, $this->getPossiblyIncompleteActiveTemplateTypeMap(), $this->getCallSiteVarianceMap(), TemplateTypeVariance::createStatic()); } if (!$extendedType instanceof GenericObjectType) { return $this->reflectionProvider->getClass($parentClass->getName()); } return $extendedType->getClassReflection() ?? $this->reflectionProvider->getClass($parentClass->getName()); } $parentReflection = $this->reflectionProvider->getClass($parentClass->getName()); if ($parentReflection->isGeneric()) { return $parentReflection->withTypes(array_values($parentReflection->getTemplateTypeMap()->map(static function () : Type { return new ErrorType(); })->getTypes())); } $this->cachedParentClass = $parentReflection; return $parentReflection; } /** * @return class-string */ public function getName() : string { return $this->reflection->getName(); } public function getDisplayName(bool $withTemplateTypes = \true) : string { if ($withTemplateTypes === \false || $this->resolvedTemplateTypeMap === null || count($this->resolvedTemplateTypeMap->getTypes()) === 0) { return $this->displayName; } $templateTypes = []; $variances = $this->getCallSiteVarianceMap()->getVariances(); foreach ($this->getActiveTemplateTypeMap()->getTypes() as $name => $templateType) { $variance = $variances[$name] ?? null; if ($variance === null) { continue; } $templateTypes[] = TypeProjectionHelper::describe($templateType, $variance, VerbosityLevel::typeOnly()); } return $this->displayName . '<' . implode(',', $templateTypes) . '>'; } public function getCacheKey() : string { $cacheKey = $this->cacheKey; if ($cacheKey !== null) { return $this->cacheKey; } $cacheKey = $this->displayName; if ($this->resolvedTemplateTypeMap !== null) { $templateTypes = []; $variances = $this->getCallSiteVarianceMap()->getVariances(); foreach ($this->getActiveTemplateTypeMap()->getTypes() as $name => $templateType) { $variance = $variances[$name] ?? null; if ($variance === null) { continue; } $templateTypes[] = TypeProjectionHelper::describe($templateType, $variance, VerbosityLevel::cache()); } $cacheKey .= '<' . implode(',', $templateTypes) . '>'; } if ($this->extraCacheKey !== null) { $cacheKey .= '-' . $this->extraCacheKey; } $this->cacheKey = $cacheKey; return $cacheKey; } /** * @return int[] */ public function getClassHierarchyDistances() : array { if ($this->classHierarchyDistances === null) { $distance = 0; $distances = [$this->getName() => $distance]; $currentClassReflection = $this->getNativeReflection(); foreach ($this->collectTraits($this->getNativeReflection()) as $trait) { $distance++; if (array_key_exists($trait->getName(), $distances)) { continue; } $distances[$trait->getName()] = $distance; } while ($currentClassReflection->getParentClass() !== \false) { $distance++; $parentClassName = $currentClassReflection->getParentClass()->getName(); if (!array_key_exists($parentClassName, $distances)) { $distances[$parentClassName] = $distance; } $currentClassReflection = $currentClassReflection->getParentClass(); foreach ($this->collectTraits($currentClassReflection) as $trait) { $distance++; if (array_key_exists($trait->getName(), $distances)) { continue; } $distances[$trait->getName()] = $distance; } } foreach ($this->getNativeReflection()->getInterfaces() as $interface) { $distance++; if (array_key_exists($interface->getName(), $distances)) { continue; } $distances[$interface->getName()] = $distance; } $this->classHierarchyDistances = $distances; } return $this->classHierarchyDistances; } /** * @return ReflectionClass[] * @param ReflectionClass|ReflectionEnum $class */ private function collectTraits($class) : array { $traits = []; $traitsLeftToAnalyze = $class->getTraits(); while (count($traitsLeftToAnalyze) !== 0) { $trait = reset($traitsLeftToAnalyze); $traits[] = $trait; foreach ($trait->getTraits() as $subTrait) { if (in_array($subTrait, $traits, \true)) { continue; } $traitsLeftToAnalyze[] = $subTrait; } array_shift($traitsLeftToAnalyze); } return $traits; } public function allowsDynamicProperties() : bool { if ($this->isEnum()) { return \false; } if (!$this->phpVersion->deprecatesDynamicProperties()) { return \true; } if ($this->isReadOnly()) { return \false; } if (UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate($this->reflectionProvider, $this->universalObjectCratesClasses, $this)) { return \true; } $class = $this; $attributes = $class->reflection->getAttributes('AllowDynamicProperties'); while (count($attributes) === 0 && $class->getParentClass() !== null) { $attributes = $class->getParentClass()->reflection->getAttributes('AllowDynamicProperties'); $class = $class->getParentClass(); } return count($attributes) > 0; } private function allowsDynamicPropertiesExtensions() : bool { if ($this->allowsDynamicProperties()) { return \true; } $hasMagicMethod = $this->hasNativeMethod('__get') || $this->hasNativeMethod('__set') || $this->hasNativeMethod('__isset'); if ($hasMagicMethod) { return \true; } foreach ($this->getRequireExtendsTags() as $extendsTag) { $type = $extendsTag->getType(); if (!$type instanceof ObjectType) { continue; } $reflection = $type->getClassReflection(); if ($reflection === null) { continue; } if (!$reflection->allowsDynamicPropertiesExtensions()) { continue; } return \true; } return \false; } public function hasProperty(string $propertyName) : bool { if ($this->isEnum()) { return $this->hasNativeProperty($propertyName); } foreach ($this->propertiesClassReflectionExtensions as $i => $extension) { if ($i > 0 && !$this->allowsDynamicPropertiesExtensions()) { break; } if ($extension->hasProperty($this, $propertyName)) { return \true; } } if ($this->requireExtendsPropertiesClassReflectionExtension->hasProperty($this, $propertyName)) { return \true; } return \false; } public function hasMethod(string $methodName) : bool { if (array_key_exists($methodName, $this->hasMethodCache)) { return $this->hasMethodCache[$methodName]; } foreach ($this->methodsClassReflectionExtensions as $extension) { if ($extension->hasMethod($this, $methodName)) { $this->hasMethodCache[$methodName] = \true; return \true; } } if ($this->requireExtendsMethodsClassReflectionExtension->hasMethod($this, $methodName)) { $this->hasMethodCache[$methodName] = \true; return \true; } $this->hasMethodCache[$methodName] = \false; return \false; } public function getMethod(string $methodName, \PHPStan\Reflection\ClassMemberAccessAnswerer $scope) : \PHPStan\Reflection\ExtendedMethodReflection { $key = $methodName; if ($scope->isInClass()) { $key = sprintf('%s-%s', $key, $scope->getClassReflection()->getCacheKey()); } if (!isset($this->methods[$key])) { foreach ($this->methodsClassReflectionExtensions as $extension) { if (!$extension->hasMethod($this, $methodName)) { continue; } $method = $this->wrapExtendedMethod($extension->getMethod($this, $methodName)); if ($scope->canCallMethod($method)) { return $this->methods[$key] = $method; } $this->methods[$key] = $method; } } if (!isset($this->methods[$key])) { if ($this->requireExtendsMethodsClassReflectionExtension->hasMethod($this, $methodName)) { $method = $this->requireExtendsMethodsClassReflectionExtension->getMethod($this, $methodName); $this->methods[$key] = $method; } } if (!isset($this->methods[$key])) { throw new \PHPStan\Reflection\MissingMethodFromReflectionException($this->getName(), $methodName); } return $this->methods[$key]; } private function wrapExtendedMethod(\PHPStan\Reflection\MethodReflection $method) : \PHPStan\Reflection\ExtendedMethodReflection { if ($method instanceof \PHPStan\Reflection\ExtendedMethodReflection) { return $method; } return new \PHPStan\Reflection\WrappedExtendedMethodReflection($method); } private function wrapExtendedProperty(\PHPStan\Reflection\PropertyReflection $method) : \PHPStan\Reflection\ExtendedPropertyReflection { if ($method instanceof \PHPStan\Reflection\ExtendedPropertyReflection) { return $method; } return new \PHPStan\Reflection\WrappedExtendedPropertyReflection($method); } public function hasNativeMethod(string $methodName) : bool { return $this->getPhpExtension()->hasNativeMethod($this, $methodName); } public function getNativeMethod(string $methodName) : \PHPStan\Reflection\ExtendedMethodReflection { if (!$this->hasNativeMethod($methodName)) { throw new \PHPStan\Reflection\MissingMethodFromReflectionException($this->getName(), $methodName); } return $this->getPhpExtension()->getNativeMethod($this, $methodName); } public function hasConstructor() : bool { return $this->findConstructor() !== null; } public function getConstructor() : \PHPStan\Reflection\ExtendedMethodReflection { $constructor = $this->findConstructor(); if ($constructor === null) { throw new ShouldNotHappenException(); } return $this->getNativeMethod($constructor->getName()); } private function findConstructor() : ?ReflectionMethod { $constructor = $this->reflection->getConstructor(); if ($constructor === null) { return null; } if ($this->phpVersion->supportsLegacyConstructor()) { return $constructor; } if (strtolower($constructor->getName()) !== '__construct') { return null; } return $constructor; } private function getPhpExtension() : PhpClassReflectionExtension { $extension = $this->methodsClassReflectionExtensions[0]; if (!$extension instanceof PhpClassReflectionExtension) { throw new ShouldNotHappenException(); } return $extension; } /** @internal */ public function evictPrivateSymbols() : void { foreach ($this->constants as $name => $constant) { if (!$constant->isPrivate()) { continue; } unset($this->constants[$name]); } foreach ($this->properties as $name => $property) { if (!$property->isPrivate()) { continue; } unset($this->properties[$name]); } foreach ($this->methods as $name => $method) { if (!$method->isPrivate()) { continue; } unset($this->methods[$name]); } $this->getPhpExtension()->evictPrivateSymbols($this->getCacheKey()); } public function getProperty(string $propertyName, \PHPStan\Reflection\ClassMemberAccessAnswerer $scope) : \PHPStan\Reflection\ExtendedPropertyReflection { if ($this->isEnum()) { return $this->getNativeProperty($propertyName); } $key = $propertyName; if ($scope->isInClass()) { $key = sprintf('%s-%s', $key, $scope->getClassReflection()->getCacheKey()); } if (!isset($this->properties[$key])) { foreach ($this->propertiesClassReflectionExtensions as $i => $extension) { if ($i > 0 && !$this->allowsDynamicPropertiesExtensions()) { break; } if (!$extension->hasProperty($this, $propertyName)) { continue; } $property = $this->wrapExtendedProperty($extension->getProperty($this, $propertyName)); if ($scope->canAccessProperty($property)) { return $this->properties[$key] = $property; } $this->properties[$key] = $property; } } if (!isset($this->properties[$key])) { if ($this->requireExtendsPropertiesClassReflectionExtension->hasProperty($this, $propertyName)) { $property = $this->requireExtendsPropertiesClassReflectionExtension->getProperty($this, $propertyName); $this->properties[$key] = $property; } } if (!isset($this->properties[$key])) { throw new \PHPStan\Reflection\MissingPropertyFromReflectionException($this->getName(), $propertyName); } return $this->properties[$key]; } public function hasNativeProperty(string $propertyName) : bool { return $this->getPhpExtension()->hasProperty($this, $propertyName); } public function getNativeProperty(string $propertyName) : PhpPropertyReflection { if (!$this->hasNativeProperty($propertyName)) { throw new \PHPStan\Reflection\MissingPropertyFromReflectionException($this->getName(), $propertyName); } return $this->getPhpExtension()->getNativeProperty($this, $propertyName); } public function isAbstract() : bool { return $this->reflection->isAbstract(); } public function isInterface() : bool { return $this->reflection->isInterface(); } public function isTrait() : bool { return $this->reflection->isTrait(); } /** * @phpstan-assert-if-true ReflectionEnum $this->reflection */ public function isEnum() : bool { return $this->reflection instanceof ReflectionEnum && $this->reflection->isEnum(); } /** * @return 'Interface'|'Trait'|'Enum'|'Class' */ public function getClassTypeDescription() : string { if ($this->isInterface()) { return 'Interface'; } elseif ($this->isTrait()) { return 'Trait'; } elseif ($this->isEnum()) { return 'Enum'; } return 'Class'; } public function isReadOnly() : bool { return $this->reflection->isReadOnly(); } public function isBackedEnum() : bool { if (!$this->reflection instanceof ReflectionEnum) { return \false; } return $this->reflection->isBacked(); } public function getBackedEnumType() : ?Type { if (!$this->reflection instanceof ReflectionEnum) { return null; } if (!$this->reflection->isBacked()) { return null; } return TypehintHelper::decideTypeFromReflection($this->reflection->getBackingType()); } public function hasEnumCase(string $name) : bool { if (!$this->isEnum()) { return \false; } return $this->reflection->hasCase($name); } /** * @return array */ public function getEnumCases() : array { if (!$this->isEnum()) { throw new ShouldNotHappenException(); } if ($this->enumCases !== null) { return $this->enumCases; } $cases = []; $initializerExprContext = \PHPStan\Reflection\InitializerExprContext::fromClassReflection($this); foreach ($this->reflection->getCases() as $case) { $valueType = null; if ($case instanceof ReflectionEnumBackedCase) { $valueType = $this->initializerExprTypeResolver->getType($case->getValueExpression(), $initializerExprContext); } /** @var string $caseName */ $caseName = $case->getName(); $cases[$caseName] = new \PHPStan\Reflection\EnumCaseReflection($this, $caseName, $valueType); } return $this->enumCases = $cases; } public function getEnumCase(string $name) : \PHPStan\Reflection\EnumCaseReflection { if (!$this->hasEnumCase($name)) { throw new ShouldNotHappenException(sprintf('Enum case %s::%s does not exist.', $this->getDisplayName(), $name)); } if (!$this->reflection instanceof ReflectionEnum) { throw new ShouldNotHappenException(); } if ($this->enumCases !== null && array_key_exists($name, $this->enumCases)) { return $this->enumCases[$name]; } $case = $this->reflection->getCase($name); $valueType = null; if ($case instanceof ReflectionEnumBackedCase) { $valueType = $this->initializerExprTypeResolver->getType($case->getValueExpression(), \PHPStan\Reflection\InitializerExprContext::fromClassReflection($this)); } return new \PHPStan\Reflection\EnumCaseReflection($this, $name, $valueType); } public function isClass() : bool { return !$this->isInterface() && !$this->isTrait() && !$this->isEnum(); } public function isAnonymous() : bool { return $this->anonymousFilename !== null; } public function is(string $className) : bool { return $this->getName() === $className || $this->isSubclassOf($className); } public function isSubclassOf(string $className) : bool { if (isset($this->subclasses[$className])) { return $this->subclasses[$className]; } if (!$this->reflectionProvider->hasClass($className)) { return $this->subclasses[$className] = \false; } try { return $this->subclasses[$className] = $this->reflection->isSubclassOf($className); } catch (ReflectionException $e) { return $this->subclasses[$className] = \false; } } public function implementsInterface(string $className) : bool { try { return $this->reflection->implementsInterface($className); } catch (ReflectionException $e) { return \false; } } /** * @return ClassReflection[] */ public function getParents() : array { $parents = []; $parent = $this->getParentClass(); while ($parent !== null) { $parents[] = $parent; $parent = $parent->getParentClass(); } return $parents; } /** * @return ClassReflection[] */ public function getInterfaces() : array { if ($this->cachedInterfaces !== null) { return $this->cachedInterfaces; } $interfaces = $this->getImmediateInterfaces(); $immediateInterfaces = $interfaces; $parent = $this->getParentClass(); while ($parent !== null) { foreach ($parent->getImmediateInterfaces() as $parentInterface) { $interfaces[$parentInterface->getName()] = $parentInterface; foreach ($this->collectInterfaces($parentInterface) as $parentInterfaceInterface) { $interfaces[$parentInterfaceInterface->getName()] = $parentInterfaceInterface; } } $parent = $parent->getParentClass(); } foreach ($immediateInterfaces as $immediateInterface) { foreach ($this->collectInterfaces($immediateInterface) as $interfaceInterface) { $interfaces[$interfaceInterface->getName()] = $interfaceInterface; } } $this->cachedInterfaces = $interfaces; return $interfaces; } /** * @return ClassReflection[] */ private function collectInterfaces(\PHPStan\Reflection\ClassReflection $interface) : array { $interfaces = []; foreach ($interface->getImmediateInterfaces() as $immediateInterface) { $interfaces[$immediateInterface->getName()] = $immediateInterface; foreach ($this->collectInterfaces($immediateInterface) as $immediateInterfaceInterface) { $interfaces[$immediateInterfaceInterface->getName()] = $immediateInterfaceInterface; } } return $interfaces; } /** * @return ClassReflection[] */ public function getImmediateInterfaces() : array { $indirectInterfaceNames = []; $parent = $this->getParentClass(); while ($parent !== null) { foreach ($parent->getNativeReflection()->getInterfaceNames() as $parentInterfaceName) { $indirectInterfaceNames[] = $parentInterfaceName; } $parent = $parent->getParentClass(); } foreach ($this->getNativeReflection()->getInterfaces() as $interfaceInterface) { foreach ($interfaceInterface->getInterfaceNames() as $interfaceInterfaceName) { $indirectInterfaceNames[] = $interfaceInterfaceName; } } if ($this->reflection->isInterface()) { $implementsTags = $this->getExtendsTags(); } else { $implementsTags = $this->getImplementsTags(); } $immediateInterfaceNames = array_diff($this->getNativeReflection()->getInterfaceNames(), $indirectInterfaceNames); $immediateInterfaces = []; foreach ($immediateInterfaceNames as $immediateInterfaceName) { if (!$this->reflectionProvider->hasClass($immediateInterfaceName)) { continue; } $immediateInterface = $this->reflectionProvider->getClass($immediateInterfaceName); if (array_key_exists($immediateInterface->getName(), $implementsTags)) { $implementsTag = $implementsTags[$immediateInterface->getName()]; $implementedType = $implementsTag->getType(); if ($this->isGeneric()) { $implementedType = TemplateTypeHelper::resolveTemplateTypes($implementedType, $this->getPossiblyIncompleteActiveTemplateTypeMap(), $this->getCallSiteVarianceMap(), TemplateTypeVariance::createStatic(), \true); } if ($implementedType instanceof GenericObjectType && $implementedType->getClassReflection() !== null) { $immediateInterfaces[$immediateInterface->getName()] = $implementedType->getClassReflection(); continue; } } if ($immediateInterface->isGeneric()) { $immediateInterfaces[$immediateInterface->getName()] = $immediateInterface->withTypes(array_values($immediateInterface->getTemplateTypeMap()->map(static function () : Type { return new ErrorType(); })->getTypes())); continue; } $immediateInterfaces[$immediateInterface->getName()] = $immediateInterface; } return $immediateInterfaces; } /** * @return array */ public function getTraits(bool $recursive = \false) : array { $traits = []; if ($recursive) { foreach ($this->collectTraits($this->getNativeReflection()) as $trait) { $traits[$trait->getName()] = $trait; } } else { $traits = $this->getNativeReflection()->getTraits(); } $traits = array_map(function (ReflectionClass $trait) : \PHPStan\Reflection\ClassReflection { return $this->reflectionProvider->getClass($trait->getName()); }, $traits); if ($recursive) { $parentClass = $this->getNativeReflection()->getParentClass(); if ($parentClass !== \false) { return array_merge($traits, $this->reflectionProvider->getClass($parentClass->getName())->getTraits(\true)); } } return $traits; } /** * @return list */ public function getParentClassesNames() : array { $parentNames = []; $parentClass = $this->getParentClass(); while ($parentClass !== null) { $parentNames[] = $parentClass->getName(); $parentClass = $parentClass->getParentClass(); } return $parentNames; } public function hasConstant(string $name) : bool { if (!$this->getNativeReflection()->hasConstant($name)) { return \false; } $reflectionConstant = $this->getNativeReflection()->getReflectionConstant($name); if ($reflectionConstant === \false) { return \false; } return $this->reflectionProvider->hasClass($reflectionConstant->getDeclaringClass()->getName()); } public function getConstant(string $name) : \PHPStan\Reflection\ClassConstantReflection { if (!isset($this->constants[$name])) { $reflectionConstant = $this->getNativeReflection()->getReflectionConstant($name); if ($reflectionConstant === \false) { throw new \PHPStan\Reflection\MissingConstantFromReflectionException($this->getName(), $name); } $declaringClass = $this->reflectionProvider->getClass($reflectionConstant->getDeclaringClass()->getName()); $fileName = $declaringClass->getFileName(); $phpDocType = null; $resolvedPhpDoc = $this->stubPhpDocProvider->findClassConstantPhpDoc($declaringClass->getName(), $name); if ($resolvedPhpDoc === null) { $docComment = null; if ($reflectionConstant->getDocComment() !== \false) { $docComment = $reflectionConstant->getDocComment(); } $resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForConstant($docComment, $declaringClass, $fileName, $name); } $deprecatedDescription = $resolvedPhpDoc->getDeprecatedTag() !== null ? $resolvedPhpDoc->getDeprecatedTag()->getMessage() : null; $isDeprecated = $resolvedPhpDoc->isDeprecated(); $isInternal = $resolvedPhpDoc->isInternal(); $isFinal = $resolvedPhpDoc->isFinal(); $nativeType = null; if ($reflectionConstant->getType() !== null) { $nativeType = TypehintHelper::decideTypeFromReflection($reflectionConstant->getType(), null, $declaringClass); } elseif ($this->signatureMapProvider->hasClassConstantMetadata($declaringClass->getName(), $name)) { $nativeType = $this->signatureMapProvider->getClassConstantMetadata($declaringClass->getName(), $name)['nativeType']; } $varTags = $resolvedPhpDoc->getVarTags(); if (isset($varTags[0]) && count($varTags) === 1) { $varTag = $varTags[0]; if ($varTag->isExplicit() || $nativeType === null || $nativeType->isSuperTypeOf($varTag->getType())->yes()) { $phpDocType = $varTag->getType(); } } $this->constants[$name] = new \PHPStan\Reflection\ClassConstantReflection($this->initializerExprTypeResolver, $declaringClass, $reflectionConstant, $nativeType, $phpDocType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal); } return $this->constants[$name]; } public function hasTraitUse(string $traitName) : bool { return in_array($traitName, $this->getTraitNames(), \true); } /** * @return string[] */ private function getTraitNames() : array { $class = $this->reflection; $traitNames = array_map(static function (ReflectionClass $class) { return $class->getName(); }, $this->collectTraits($class)); while ($class->getParentClass() !== \false) { $traitNames = array_values(array_unique(array_merge($traitNames, $class->getParentClass()->getTraitNames()))); $class = $class->getParentClass(); } return $traitNames; } /** * @return array */ public function getTypeAliases() : array { if ($this->typeAliases === null) { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return $this->typeAliases = []; } $typeAliasImportTags = $resolvedPhpDoc->getTypeAliasImportTags(); $typeAliasTags = $resolvedPhpDoc->getTypeAliasTags(); // prevent circular imports if (array_key_exists($this->getName(), self::$resolvingTypeAliasImports)) { throw new CircularTypeAliasDefinitionException(); } self::$resolvingTypeAliasImports[$this->getName()] = \true; $importedAliases = array_map(function (TypeAliasImportTag $typeAliasImportTag) : ?TypeAlias { $importedAlias = $typeAliasImportTag->getImportedAlias(); $importedFromClassName = $typeAliasImportTag->getImportedFrom(); if (!$this->reflectionProvider->hasClass($importedFromClassName)) { return null; } $importedFromReflection = $this->reflectionProvider->getClass($importedFromClassName); try { $typeAliases = $importedFromReflection->getTypeAliases(); } catch (CircularTypeAliasDefinitionException $e) { return TypeAlias::invalid(); } if (!array_key_exists($importedAlias, $typeAliases)) { return null; } return $typeAliases[$importedAlias]; }, $typeAliasImportTags); unset(self::$resolvingTypeAliasImports[$this->getName()]); $localAliases = array_map(static function (TypeAliasTag $typeAliasTag) : TypeAlias { return $typeAliasTag->getTypeAlias(); }, $typeAliasTags); $this->typeAliases = array_filter(array_merge($importedAliases, $localAliases), static function (?TypeAlias $typeAlias) : bool { return $typeAlias !== null; }); } return $this->typeAliases; } public function getDeprecatedDescription() : ?string { if ($this->deprecatedDescription === null && $this->isDeprecated()) { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc !== null && $resolvedPhpDoc->getDeprecatedTag() !== null) { $this->deprecatedDescription = $resolvedPhpDoc->getDeprecatedTag()->getMessage(); } } return $this->deprecatedDescription; } public function isDeprecated() : bool { if ($this->isDeprecated === null) { $resolvedPhpDoc = $this->getResolvedPhpDoc(); $this->isDeprecated = $resolvedPhpDoc !== null && $resolvedPhpDoc->isDeprecated(); } return $this->isDeprecated; } public function isBuiltin() : bool { return $this->reflection->isInternal(); } public function isInternal() : bool { if ($this->isInternal === null) { $resolvedPhpDoc = $this->getResolvedPhpDoc(); $this->isInternal = $resolvedPhpDoc !== null && $resolvedPhpDoc->isInternal(); } return $this->isInternal; } public function isFinal() : bool { if ($this->isFinalByKeyword()) { return \true; } if ($this->isFinal === null) { $resolvedPhpDoc = $this->getResolvedPhpDoc(); $this->isFinal = $resolvedPhpDoc !== null && $resolvedPhpDoc->isFinal(); } return $this->isFinal; } public function isImmutable() : bool { if ($this->isImmutable === null) { $resolvedPhpDoc = $this->getResolvedPhpDoc(); $this->isImmutable = $resolvedPhpDoc !== null && ($resolvedPhpDoc->isImmutable() || $resolvedPhpDoc->isReadOnly()); $parentClass = $this->getParentClass(); if ($parentClass !== null && !$this->isImmutable) { $this->isImmutable = $parentClass->isImmutable(); } } return $this->isImmutable; } public function hasConsistentConstructor() : bool { if ($this->hasConsistentConstructor === null) { $resolvedPhpDoc = $this->getResolvedPhpDoc(); $this->hasConsistentConstructor = $resolvedPhpDoc !== null && $resolvedPhpDoc->hasConsistentConstructor(); } return $this->hasConsistentConstructor; } public function acceptsNamedArguments() : bool { if ($this->acceptsNamedArguments === null) { $resolvedPhpDoc = $this->getResolvedPhpDoc(); $this->acceptsNamedArguments = $resolvedPhpDoc === null || $resolvedPhpDoc->acceptsNamedArguments(); } return $this->acceptsNamedArguments; } public function isFinalByKeyword() : bool { if ($this->isAnonymous()) { return \true; } return $this->reflection->isFinal(); } public function isAttributeClass() : bool { return $this->findAttributeFlags() !== null; } private function findAttributeFlags() : ?int { if ($this->isInterface() || $this->isTrait() || $this->isEnum()) { return null; } $nativeAttributes = $this->reflection->getAttributes(Attribute::class); if (count($nativeAttributes) === 1) { if (!$this->reflectionProvider->hasClass(Attribute::class)) { return null; } $attributeClass = $this->reflectionProvider->getClass(Attribute::class); $arguments = []; foreach ($nativeAttributes[0]->getArgumentsExpressions() as $i => $expression) { $arguments[] = new Arg($expression, \false, \false, [], is_int($i) ? null : new Identifier($i)); } if (!$attributeClass->hasConstructor()) { return null; } $attributeConstructor = $attributeClass->getConstructor(); $attributeConstructorVariant = $attributeConstructor->getOnlyVariant(); if (count($arguments) === 0) { $flagType = $attributeConstructorVariant->getParameters()[0]->getDefaultValue(); } else { $staticCall = ArgumentsNormalizer::reorderStaticCallArguments($attributeConstructorVariant, new StaticCall(new FullyQualified(Attribute::class), $attributeConstructor->getName(), $arguments)); if ($staticCall === null) { return null; } $flagExpr = $staticCall->getArgs()[0]->value; $flagType = $this->initializerExprTypeResolver->getType($flagExpr, \PHPStan\Reflection\InitializerExprContext::fromClassReflection($this)); } if (!$flagType instanceof ConstantIntegerType) { return null; } return $flagType->getValue(); } return null; } public function getAttributeClassFlags() : int { $flags = $this->findAttributeFlags(); if ($flags === null) { throw new ShouldNotHappenException(); } return $flags; } public function getTemplateTypeMap() : TemplateTypeMap { if ($this->templateTypeMap !== null) { return $this->templateTypeMap; } $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { $this->templateTypeMap = TemplateTypeMap::createEmpty(); return $this->templateTypeMap; } $templateTypeScope = TemplateTypeScope::createWithClass($this->getName()); $templateTypeMap = new TemplateTypeMap(array_map(static function (TemplateTag $tag) use($templateTypeScope) : Type { return TemplateTypeFactory::fromTemplateTag($templateTypeScope, $tag); }, $this->getTemplateTags())); $this->templateTypeMap = $templateTypeMap; return $templateTypeMap; } public function getActiveTemplateTypeMap() : TemplateTypeMap { if ($this->activeTemplateTypeMap !== null) { return $this->activeTemplateTypeMap; } $resolved = $this->resolvedTemplateTypeMap; if ($resolved !== null) { $templateTypeMap = $this->getTemplateTypeMap(); return $this->activeTemplateTypeMap = $resolved->map(static function (string $name, Type $type) use($templateTypeMap) : Type { if ($type instanceof ErrorType) { $templateType = $templateTypeMap->getType($name); if ($templateType !== null) { return TemplateTypeHelper::resolveToDefaults($templateType); } } return $type; }); } return $this->activeTemplateTypeMap = $this->getTemplateTypeMap(); } public function getPossiblyIncompleteActiveTemplateTypeMap() : TemplateTypeMap { return $this->resolvedTemplateTypeMap ?? $this->getTemplateTypeMap(); } private function getDefaultCallSiteVarianceMap() : TemplateTypeVarianceMap { if ($this->defaultCallSiteVarianceMap !== null) { return $this->defaultCallSiteVarianceMap; } $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { $this->defaultCallSiteVarianceMap = TemplateTypeVarianceMap::createEmpty(); return $this->defaultCallSiteVarianceMap; } $map = []; foreach ($this->getTemplateTags() as $templateTag) { $map[$templateTag->getName()] = TemplateTypeVariance::createInvariant(); } $this->defaultCallSiteVarianceMap = new TemplateTypeVarianceMap($map); return $this->defaultCallSiteVarianceMap; } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return $this->callSiteVarianceMap = $this->callSiteVarianceMap ?? $this->resolvedCallSiteVarianceMap ?? $this->getDefaultCallSiteVarianceMap(); } public function isGeneric() : bool { if ($this->isGeneric === null) { if ($this->isEnum()) { return $this->isGeneric = \false; } $this->isGeneric = count($this->getTemplateTags()) > 0; } return $this->isGeneric; } /** * @param array $types */ public function typeMapFromList(array $types) : TemplateTypeMap { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return TemplateTypeMap::createEmpty(); } $map = []; $i = 0; foreach ($resolvedPhpDoc->getTemplateTags() as $tag) { $map[$tag->getName()] = $types[$i] ?? $tag->getDefault() ?? $tag->getBound(); $i++; } return new TemplateTypeMap($map); } /** * @param array $variances */ public function varianceMapFromList(array $variances) : TemplateTypeVarianceMap { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return new TemplateTypeVarianceMap([]); } $map = []; $i = 0; foreach ($resolvedPhpDoc->getTemplateTags() as $tag) { $map[$tag->getName()] = $variances[$i] ?? TemplateTypeVariance::createInvariant(); $i++; } return new TemplateTypeVarianceMap($map); } /** @return array */ public function typeMapToList(TemplateTypeMap $typeMap) : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } $list = []; foreach ($resolvedPhpDoc->getTemplateTags() as $tag) { $list[] = $typeMap->getType($tag->getName()) ?? $tag->getDefault() ?? $tag->getBound(); } return $list; } /** @return array */ public function varianceMapToList(TemplateTypeVarianceMap $varianceMap) : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } $list = []; foreach ($resolvedPhpDoc->getTemplateTags() as $tag) { $list[] = $varianceMap->getVariance($tag->getName()) ?? TemplateTypeVariance::createInvariant(); } return $list; } /** * @param array $types */ public function withTypes(array $types) : self { return new self($this->reflectionProvider, $this->initializerExprTypeResolver, $this->fileTypeMapper, $this->stubPhpDocProvider, $this->phpDocInheritanceResolver, $this->phpVersion, $this->signatureMapProvider, $this->propertiesClassReflectionExtensions, $this->methodsClassReflectionExtensions, $this->allowedSubTypesClassReflectionExtensions, $this->requireExtendsPropertiesClassReflectionExtension, $this->requireExtendsMethodsClassReflectionExtension, $this->displayName, $this->reflection, $this->anonymousFilename, $this->typeMapFromList($types), $this->stubPhpDocBlock, $this->universalObjectCratesClasses, null, $this->resolvedCallSiteVarianceMap); } /** * @param array $variances */ public function withVariances(array $variances) : self { return new self($this->reflectionProvider, $this->initializerExprTypeResolver, $this->fileTypeMapper, $this->stubPhpDocProvider, $this->phpDocInheritanceResolver, $this->phpVersion, $this->signatureMapProvider, $this->propertiesClassReflectionExtensions, $this->methodsClassReflectionExtensions, $this->allowedSubTypesClassReflectionExtensions, $this->requireExtendsPropertiesClassReflectionExtension, $this->requireExtendsMethodsClassReflectionExtension, $this->displayName, $this->reflection, $this->anonymousFilename, $this->resolvedTemplateTypeMap, $this->stubPhpDocBlock, $this->universalObjectCratesClasses, null, $this->varianceMapFromList($variances)); } public function getResolvedPhpDoc() : ?ResolvedPhpDocBlock { if ($this->stubPhpDocBlock !== null) { return $this->stubPhpDocBlock; } $fileName = $this->getFileName(); if (is_bool($this->reflectionDocComment)) { $docComment = $this->reflection->getDocComment(); $this->reflectionDocComment = $docComment !== \false ? $docComment : null; } if ($this->reflectionDocComment === null) { return null; } if ($this->resolvedPhpDocBlock !== \false) { return $this->resolvedPhpDocBlock; } return $this->resolvedPhpDocBlock = $this->fileTypeMapper->getResolvedPhpDoc($fileName, $this->getName(), null, null, $this->reflectionDocComment); } public function getTraitContextResolvedPhpDoc(self $implementingClass) : ?ResolvedPhpDocBlock { if (!$this->isTrait()) { throw new ShouldNotHappenException(); } if ($implementingClass->isTrait()) { throw new ShouldNotHappenException(); } $fileName = $this->getFileName(); if (is_bool($this->reflectionDocComment)) { $docComment = $this->reflection->getDocComment(); $this->reflectionDocComment = $docComment !== \false ? $docComment : null; } if ($this->reflectionDocComment === null) { return null; } if ($this->traitContextResolvedPhpDocBlock !== \false) { return $this->traitContextResolvedPhpDocBlock; } return $this->traitContextResolvedPhpDocBlock = $this->fileTypeMapper->getResolvedPhpDoc($fileName, $implementingClass->getName(), $this->getName(), null, $this->reflectionDocComment); } private function getFirstExtendsTag() : ?ExtendsTag { foreach ($this->getExtendsTags() as $tag) { return $tag; } return null; } /** @return array */ public function getExtendsTags() : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } return $resolvedPhpDoc->getExtendsTags(); } /** @return array */ public function getImplementsTags() : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } return $resolvedPhpDoc->getImplementsTags(); } /** @return array */ public function getTemplateTags() : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } return $resolvedPhpDoc->getTemplateTags(); } /** * @return array */ public function getAncestors() : array { $ancestors = $this->ancestors; if ($ancestors === null) { $ancestors = [$this->getName() => $this]; $addToAncestors = static function (string $name, \PHPStan\Reflection\ClassReflection $classReflection) use(&$ancestors) : void { if (array_key_exists($name, $ancestors)) { return; } $ancestors[$name] = $classReflection; }; foreach ($this->getInterfaces() as $interface) { $addToAncestors($interface->getName(), $interface); foreach ($interface->getAncestors() as $name => $ancestor) { $addToAncestors($name, $ancestor); } } foreach ($this->getTraits() as $trait) { $addToAncestors($trait->getName(), $trait); foreach ($trait->getAncestors() as $name => $ancestor) { $addToAncestors($name, $ancestor); } } $parent = $this->getParentClass(); if ($parent !== null) { $addToAncestors($parent->getName(), $parent); foreach ($parent->getAncestors() as $name => $ancestor) { $addToAncestors($name, $ancestor); } } $this->ancestors = $ancestors; } return $ancestors; } public function getAncestorWithClassName(string $className) : ?self { return $this->getAncestors()[$className] ?? null; } /** * @param string[] $ancestorClasses */ private function isValidAncestorType(Type $type, array $ancestorClasses) : bool { if (!$type instanceof GenericObjectType) { return \false; } $reflection = $type->getClassReflection(); if ($reflection === null) { return \false; } return in_array($reflection->getName(), $ancestorClasses, \true); } /** * @return array */ public function getMixinTags() : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } return $resolvedPhpDoc->getMixinTags(); } /** * @return array */ public function getRequireExtendsTags() : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } return $resolvedPhpDoc->getRequireExtendsTags(); } /** * @return array */ public function getRequireImplementsTags() : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } return $resolvedPhpDoc->getRequireImplementsTags(); } /** * @return array */ public function getPropertyTags() : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } return $resolvedPhpDoc->getPropertyTags(); } /** * @return array */ public function getMethodTags() : array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return []; } return $resolvedPhpDoc->getMethodTags(); } /** * @return array */ public function getResolvedMixinTypes() : array { $types = []; foreach ($this->getMixinTags() as $mixinTag) { if (!$this->isGeneric()) { $types[] = $mixinTag->getType(); continue; } $types[] = TemplateTypeHelper::resolveTemplateTypes($mixinTag->getType(), $this->getActiveTemplateTypeMap(), $this->getCallSiteVarianceMap(), TemplateTypeVariance::createStatic()); } return $types; } /** * @return array|null */ public function getAllowedSubTypes() : ?array { foreach ($this->allowedSubTypesClassReflectionExtensions as $allowedSubTypesClassReflectionExtension) { if ($allowedSubTypesClassReflectionExtension->supports($this)) { return $allowedSubTypesClassReflectionExtension->getAllowedSubTypes($this); } } return null; } } */ public function getParameters() : array; public function isVariadic() : bool; public function getReturnType() : Type; } getName() === 'SoapClient' || $classReflection->isSubclassOf('SoapClient'); } public function getMethod(ClassReflection $classReflection, string $methodName) : MethodReflection { return new \PHPStan\Reflection\Php\Soap\SoapClientMethodReflection($classReflection, $methodName); } } declaringClass = $declaringClass; $this->name = $name; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return \false; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getDocComment() : ?string { return null; } public function getName() : string { return $this->name; } public function getPrototype() : ClassMemberReflection { return $this; } public function getVariants() : array { return [new FunctionVariant(TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), [], \true, new MixedType(\true))]; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription() : ?string { return null; } public function isFinal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getThrowType() : Type { return new ObjectType('SoapFault'); } public function hasSideEffects() : TrinaryLogic { return TrinaryLogic::createYes(); } } */ private $immediatelyInvokedCallableParameters; /** * @var array */ private $phpDocClosureThisTypeParameters; /** @var Function_|ClassMethod */ private $functionLike; /** @var FunctionVariantWithPhpDocs[]|null */ private $variants = null; /** * @param Function_|ClassMethod $functionLike * @param Type[] $realParameterTypes * @param Type[] $phpDocParameterTypes * @param Type[] $realParameterDefaultValues * @param Type[] $parameterOutTypes * @param array $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters */ public function __construct(FunctionLike $functionLike, string $fileName, TemplateTypeMap $templateTypeMap, array $realParameterTypes, array $phpDocParameterTypes, array $realParameterDefaultValues, Type $realReturnType, ?Type $phpDocReturnType, ?Type $throwType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?bool $isPure, bool $acceptsNamedArguments, Assertions $assertions, ?string $phpDocComment, array $parameterOutTypes, array $immediatelyInvokedCallableParameters, array $phpDocClosureThisTypeParameters) { $this->fileName = $fileName; $this->templateTypeMap = $templateTypeMap; $this->realParameterTypes = $realParameterTypes; $this->phpDocParameterTypes = $phpDocParameterTypes; $this->realParameterDefaultValues = $realParameterDefaultValues; $this->realReturnType = $realReturnType; $this->phpDocReturnType = $phpDocReturnType; $this->throwType = $throwType; $this->deprecatedDescription = $deprecatedDescription; $this->isDeprecated = $isDeprecated; $this->isInternal = $isInternal; $this->isFinal = $isFinal; $this->isPure = $isPure; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->assertions = $assertions; $this->phpDocComment = $phpDocComment; $this->parameterOutTypes = $parameterOutTypes; $this->immediatelyInvokedCallableParameters = $immediatelyInvokedCallableParameters; $this->phpDocClosureThisTypeParameters = $phpDocClosureThisTypeParameters; $this->functionLike = $functionLike; } protected function getFunctionLike() : FunctionLike { return $this->functionLike; } public function getFileName() : string { return $this->fileName; } public function getName() : string { if ($this->functionLike instanceof ClassMethod) { return $this->functionLike->name->name; } if ($this->functionLike->namespacedName === null) { throw new ShouldNotHappenException(); } return (string) $this->functionLike->namespacedName; } /** * @return ParametersAcceptorWithPhpDocs[] */ public function getVariants() : array { if ($this->variants === null) { $this->variants = [new FunctionVariantWithPhpDocs($this->getTemplateTypeMap(), $this->getResolvedTemplateTypeMap(), $this->getParameters(), $this->isVariadic(), $this->getReturnType(), $this->getPhpDocReturnType(), $this->getNativeReturnType())]; } return $this->variants; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this; } public function getNamedArgumentsVariants() : ?array { return null; } public function getTemplateTypeMap() : TemplateTypeMap { return $this->templateTypeMap; } public function getResolvedTemplateTypeMap() : TemplateTypeMap { return TemplateTypeMap::createEmpty(); } /** * @return array */ public function getParameters() : array { $parameters = []; $isOptional = \true; /** @var Node\Param $parameter */ foreach (array_reverse($this->functionLike->getParams()) as $parameter) { if ($parameter->default === null && !$parameter->variadic) { $isOptional = \false; } if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } if (isset($this->immediatelyInvokedCallableParameters[$parameter->var->name])) { $immediatelyInvokedCallable = TrinaryLogic::createFromBoolean($this->immediatelyInvokedCallableParameters[$parameter->var->name]); } else { $immediatelyInvokedCallable = TrinaryLogic::createMaybe(); } if (isset($this->phpDocClosureThisTypeParameters[$parameter->var->name])) { $closureThisType = $this->phpDocClosureThisTypeParameters[$parameter->var->name]; } else { $closureThisType = null; } $parameters[] = new \PHPStan\Reflection\Php\PhpParameterFromParserNodeReflection($parameter->var->name, $isOptional, $this->realParameterTypes[$parameter->var->name], $this->phpDocParameterTypes[$parameter->var->name] ?? null, $parameter->byRef ? PassedByReference::createCreatesNewVariable() : PassedByReference::createNo(), $this->realParameterDefaultValues[$parameter->var->name] ?? null, $parameter->variadic, $this->parameterOutTypes[$parameter->var->name] ?? null, $immediatelyInvokedCallable, $closureThisType); } return array_reverse($parameters); } public function isVariadic() : bool { foreach ($this->functionLike->getParams() as $parameter) { if ($parameter->variadic) { return \true; } } return \false; } public function getReturnType() : Type { return TypehintHelper::decideType($this->realReturnType, $this->phpDocReturnType); } public function getPhpDocReturnType() : Type { return $this->phpDocReturnType ?? new MixedType(); } public function getNativeReturnType() : Type { return $this->realReturnType; } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return TemplateTypeVarianceMap::createEmpty(); } public function getDeprecatedDescription() : ?string { if ($this->isDeprecated) { return $this->deprecatedDescription; } return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isDeprecated); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isInternal); } public function isFinal() : TrinaryLogic { $finalMethod = \false; if ($this->functionLike instanceof ClassMethod) { $finalMethod = $this->functionLike->isFinal(); } return TrinaryLogic::createFromBoolean($finalMethod || $this->isFinal); } public function isFinalByKeyword() : TrinaryLogic { $finalMethod = \false; if ($this->functionLike instanceof ClassMethod) { $finalMethod = $this->functionLike->isFinal(); } return TrinaryLogic::createFromBoolean($finalMethod); } public function getThrowType() : ?Type { return $this->throwType; } public function hasSideEffects() : TrinaryLogic { if ($this->getReturnType()->isVoid()->yes()) { return TrinaryLogic::createYes(); } if ($this->isPure !== null) { return TrinaryLogic::createFromBoolean(!$this->isPure); } return TrinaryLogic::createMaybe(); } public function isBuiltin() : bool { return \false; } public function isGenerator() : bool { return $this->nodeIsOrContainsYield($this->functionLike); } public function acceptsNamedArguments() : bool { return $this->acceptsNamedArguments; } private function nodeIsOrContainsYield(Node $node) : bool { if ($node instanceof Node\Expr\Yield_) { return \true; } if ($node instanceof Node\Expr\YieldFrom) { return \true; } foreach ($node->getSubNodeNames() as $nodeName) { $nodeProperty = $node->{$nodeName}; if ($nodeProperty instanceof Node && $this->nodeIsOrContainsYield($nodeProperty)) { return \true; } if (!is_array($nodeProperty)) { continue; } foreach ($nodeProperty as $nodePropertyArrayItem) { if ($nodePropertyArrayItem instanceof Node && $this->nodeIsOrContainsYield($nodePropertyArrayItem)) { return \true; } } } return \false; } public function getAsserts() : Assertions { return $this->assertions; } public function getDocComment() : ?string { return $this->phpDocComment; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->functionLike->returnsByRef()); } public function isPure() : TrinaryLogic { if ($this->isPure === null) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createFromBoolean($this->isPure); } } > */ private $propertyTypesCache = []; /** @var array */ private $inferClassConstructorPropertyTypesInProcess = []; public function __construct(ScopeFactory $scopeFactory, NodeScopeResolver $nodeScopeResolver, \PHPStan\Reflection\Php\PhpMethodReflectionFactory $methodReflectionFactory, PhpDocInheritanceResolver $phpDocInheritanceResolver, AnnotationsMethodsClassReflectionExtension $annotationsMethodsClassReflectionExtension, AnnotationsPropertiesClassReflectionExtension $annotationsPropertiesClassReflectionExtension, SignatureMapProvider $signatureMapProvider, Parser $parser, StubPhpDocProvider $stubPhpDocProvider, ReflectionProvider\ReflectionProviderProvider $reflectionProviderProvider, FileTypeMapper $fileTypeMapper, bool $inferPrivatePropertyTypeFromConstructor) { $this->scopeFactory = $scopeFactory; $this->nodeScopeResolver = $nodeScopeResolver; $this->methodReflectionFactory = $methodReflectionFactory; $this->phpDocInheritanceResolver = $phpDocInheritanceResolver; $this->annotationsMethodsClassReflectionExtension = $annotationsMethodsClassReflectionExtension; $this->annotationsPropertiesClassReflectionExtension = $annotationsPropertiesClassReflectionExtension; $this->signatureMapProvider = $signatureMapProvider; $this->parser = $parser; $this->stubPhpDocProvider = $stubPhpDocProvider; $this->reflectionProviderProvider = $reflectionProviderProvider; $this->fileTypeMapper = $fileTypeMapper; $this->inferPrivatePropertyTypeFromConstructor = $inferPrivatePropertyTypeFromConstructor; } public function evictPrivateSymbols(string $classCacheKey) : void { foreach ($this->propertiesIncludingAnnotations as $key => $properties) { if ($key !== $classCacheKey) { continue; } foreach ($properties as $name => $property) { if (!$property->isPrivate()) { continue; } unset($this->propertiesIncludingAnnotations[$key][$name]); } } foreach ($this->nativeProperties as $key => $properties) { if ($key !== $classCacheKey) { continue; } foreach ($properties as $name => $property) { if (!$property->isPrivate()) { continue; } unset($this->nativeProperties[$key][$name]); } } foreach ($this->methodsIncludingAnnotations as $key => $methods) { if ($key !== $classCacheKey) { continue; } foreach ($methods as $name => $method) { if (!$method->isPrivate()) { continue; } unset($this->methodsIncludingAnnotations[$key][$name]); } } foreach ($this->nativeMethods as $key => $methods) { if ($key !== $classCacheKey) { continue; } foreach ($methods as $name => $method) { if (!$method->isPrivate()) { continue; } unset($this->nativeMethods[$key][$name]); } } } public function hasProperty(ClassReflection $classReflection, string $propertyName) : bool { return $classReflection->getNativeReflection()->hasProperty($propertyName); } /** * @return ExtendedPropertyReflection */ public function getProperty(ClassReflection $classReflection, string $propertyName) : PropertyReflection { if (!isset($this->propertiesIncludingAnnotations[$classReflection->getCacheKey()][$propertyName])) { $this->propertiesIncludingAnnotations[$classReflection->getCacheKey()][$propertyName] = $this->createProperty($classReflection, $propertyName, \true); } return $this->propertiesIncludingAnnotations[$classReflection->getCacheKey()][$propertyName]; } public function getNativeProperty(ClassReflection $classReflection, string $propertyName) : \PHPStan\Reflection\Php\PhpPropertyReflection { if (!isset($this->nativeProperties[$classReflection->getCacheKey()][$propertyName])) { /** @var PhpPropertyReflection $property */ $property = $this->createProperty($classReflection, $propertyName, \false); $this->nativeProperties[$classReflection->getCacheKey()][$propertyName] = $property; } return $this->nativeProperties[$classReflection->getCacheKey()][$propertyName]; } private function createProperty(ClassReflection $classReflection, string $propertyName, bool $includingAnnotations) : ExtendedPropertyReflection { $propertyReflection = $classReflection->getNativeReflection()->getProperty($propertyName); $propertyName = $propertyReflection->getName(); $declaringClassName = $propertyReflection->getDeclaringClass()->getName(); $declaringClassReflection = $classReflection->getAncestorWithClassName($declaringClassName); if ($declaringClassReflection === null) { throw new ShouldNotHappenException(sprintf('Internal error: Expected to find an ancestor with class name %s on %s, but none was found.', $declaringClassName, $classReflection->getName())); } if ($declaringClassReflection->isEnum()) { if ($propertyName === 'name' || $declaringClassReflection->isBackedEnum() && $propertyName === 'value') { $types = []; foreach (array_keys($classReflection->getEnumCases()) as $name) { if ($propertyName === 'name') { $types[] = new ConstantStringType($name); continue; } $case = $classReflection->getEnumCase($name); $value = $case->getBackingValueType(); if ($value === null) { throw new ShouldNotHappenException(); } $types[] = $value; } return new \PHPStan\Reflection\Php\PhpPropertyReflection($declaringClassReflection, null, null, TypeCombinator::union(...$types), $classReflection->getNativeReflection()->getProperty($propertyName), null, \false, \false, \false, \false); } } $deprecatedDescription = null; $isDeprecated = \false; $isInternal = \false; $isReadOnlyByPhpDoc = $classReflection->isImmutable(); $isAllowedPrivateMutation = \false; if ($includingAnnotations && !$declaringClassReflection->isEnum() && $this->annotationsPropertiesClassReflectionExtension->hasProperty($classReflection, $propertyName)) { $hierarchyDistances = $classReflection->getClassHierarchyDistances(); $annotationProperty = $this->annotationsPropertiesClassReflectionExtension->getProperty($classReflection, $propertyName); if (!isset($hierarchyDistances[$annotationProperty->getDeclaringClass()->getName()])) { throw new ShouldNotHappenException(); } $distanceDeclaringClass = $propertyReflection->getDeclaringClass()->getName(); $propertyTrait = $this->findPropertyTrait($propertyReflection); if ($propertyTrait !== null) { $distanceDeclaringClass = $propertyTrait; } if (!isset($hierarchyDistances[$distanceDeclaringClass])) { throw new ShouldNotHappenException(); } if ($hierarchyDistances[$annotationProperty->getDeclaringClass()->getName()] <= $hierarchyDistances[$distanceDeclaringClass]) { return $annotationProperty; } } $docComment = $propertyReflection->getDocComment() !== \false ? $propertyReflection->getDocComment() : null; $phpDocType = null; $resolvedPhpDoc = null; $declaringTraitName = $this->findPropertyTrait($propertyReflection); $constructorName = null; if ($propertyReflection->isPromoted()) { if ($declaringClassReflection->hasConstructor()) { $constructorName = $declaringClassReflection->getConstructor()->getName(); } } if ($constructorName === null) { $resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForProperty($docComment, $declaringClassReflection, $declaringClassReflection->getFileName(), $declaringTraitName, $propertyName); } elseif ($docComment !== null) { $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($declaringClassReflection->getFileName(), $declaringClassName, $declaringTraitName, $constructorName, $docComment); } $phpDocBlockClassReflection = $declaringClassReflection; if ($resolvedPhpDoc !== null) { $varTags = $resolvedPhpDoc->getVarTags(); if (isset($varTags[0]) && count($varTags) === 1) { $phpDocType = $varTags[0]->getType(); } elseif (isset($varTags[$propertyName])) { $phpDocType = $varTags[$propertyName]->getType(); } $phpDocType = $phpDocType !== null ? TemplateTypeHelper::resolveTemplateTypes($phpDocType, $phpDocBlockClassReflection->getActiveTemplateTypeMap(), $phpDocBlockClassReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createInvariant()) : null; $deprecatedDescription = $resolvedPhpDoc->getDeprecatedTag() !== null ? $resolvedPhpDoc->getDeprecatedTag()->getMessage() : null; $isDeprecated = $resolvedPhpDoc->isDeprecated(); $isInternal = $resolvedPhpDoc->isInternal(); $isReadOnlyByPhpDoc = $isReadOnlyByPhpDoc || $resolvedPhpDoc->isReadOnly(); $isAllowedPrivateMutation = $resolvedPhpDoc->isAllowedPrivateMutation(); } if ($phpDocType === null) { if (isset($constructorName)) { $constructorDocComment = $declaringClassReflection->getConstructor()->getDocComment(); $nativeClassReflection = $declaringClassReflection->getNativeReflection(); $positionalParameterNames = []; if ($nativeClassReflection->getConstructor() !== null) { $positionalParameterNames = array_map(static function (ReflectionParameter $parameter) : string { return $parameter->getName(); }, $nativeClassReflection->getConstructor()->getParameters()); } $resolvedConstructorPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForMethod($constructorDocComment, $declaringClassReflection->getFileName(), $declaringClassReflection, $declaringTraitName, $constructorName, $positionalParameterNames); $paramTags = $resolvedConstructorPhpDoc->getParamTags(); if (isset($paramTags[$propertyReflection->getName()])) { $phpDocType = $paramTags[$propertyReflection->getName()]->getType(); } } } if ($phpDocType === null && $this->inferPrivatePropertyTypeFromConstructor && $declaringClassReflection->getFileName() !== null && $propertyReflection->isPrivate() && !$propertyReflection->isPromoted() && !$propertyReflection->hasType() && $declaringClassReflection->hasConstructor() && $declaringClassReflection->getConstructor()->getDeclaringClass()->getName() === $declaringClassReflection->getName()) { $phpDocType = $this->inferPrivatePropertyType($propertyReflection->getName(), $declaringClassReflection->getConstructor()); } $nativeType = null; if ($propertyReflection->getType() !== null) { $nativeType = $propertyReflection->getType(); } $declaringTrait = null; $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); if ($declaringTraitName !== null && $reflectionProvider->hasClass($declaringTraitName)) { $declaringTrait = $reflectionProvider->getClass($declaringTraitName); } return new \PHPStan\Reflection\Php\PhpPropertyReflection($declaringClassReflection, $declaringTrait, $nativeType, $phpDocType, $propertyReflection, $deprecatedDescription, $isDeprecated, $isInternal, $isReadOnlyByPhpDoc, $isAllowedPrivateMutation); } public function hasMethod(ClassReflection $classReflection, string $methodName) : bool { return $classReflection->getNativeReflection()->hasMethod($methodName); } /** * @return ExtendedMethodReflection */ public function getMethod(ClassReflection $classReflection, string $methodName) : MethodReflection { if (isset($this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$methodName])) { return $this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$methodName]; } $nativeMethodReflection = new \PHPStan\Reflection\Php\NativeBuiltinMethodReflection($classReflection->getNativeReflection()->getMethod($methodName)); if (!isset($this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$nativeMethodReflection->getName()])) { $method = $this->createMethod($classReflection, $nativeMethodReflection, \true); $this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$nativeMethodReflection->getName()] = $method; if ($nativeMethodReflection->getName() !== $methodName) { $this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$methodName] = $method; } } return $this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$nativeMethodReflection->getName()]; } public function hasNativeMethod(ClassReflection $classReflection, string $methodName) : bool { return $this->hasMethod($classReflection, $methodName); } public function getNativeMethod(ClassReflection $classReflection, string $methodName) : ExtendedMethodReflection { if (isset($this->nativeMethods[$classReflection->getCacheKey()][$methodName])) { return $this->nativeMethods[$classReflection->getCacheKey()][$methodName]; } if (!$classReflection->getNativeReflection()->hasMethod($methodName)) { throw new ShouldNotHappenException(); } $reflectionMethod = $classReflection->getNativeReflection()->getMethod($methodName); $nativeMethodReflection = new \PHPStan\Reflection\Php\NativeBuiltinMethodReflection($reflectionMethod); if (!isset($this->nativeMethods[$classReflection->getCacheKey()][$nativeMethodReflection->getName()])) { $method = $this->createMethod($classReflection, $nativeMethodReflection, \false); $this->nativeMethods[$classReflection->getCacheKey()][$nativeMethodReflection->getName()] = $method; } return $this->nativeMethods[$classReflection->getCacheKey()][$nativeMethodReflection->getName()]; } private function createMethod(ClassReflection $classReflection, \PHPStan\Reflection\Php\BuiltinMethodReflection $methodReflection, bool $includingAnnotations) : ExtendedMethodReflection { if ($includingAnnotations && $this->annotationsMethodsClassReflectionExtension->hasMethod($classReflection, $methodReflection->getName())) { $hierarchyDistances = $classReflection->getClassHierarchyDistances(); $annotationMethod = $this->annotationsMethodsClassReflectionExtension->getMethod($classReflection, $methodReflection->getName()); if (!isset($hierarchyDistances[$annotationMethod->getDeclaringClass()->getName()])) { throw new ShouldNotHappenException(); } $distanceDeclaringClass = $methodReflection->getDeclaringClass()->getName(); $methodTrait = $this->findMethodTrait($methodReflection); if ($methodTrait !== null) { $distanceDeclaringClass = $methodTrait; } if (!isset($hierarchyDistances[$distanceDeclaringClass])) { throw new ShouldNotHappenException(); } if ($hierarchyDistances[$annotationMethod->getDeclaringClass()->getName()] <= $hierarchyDistances[$distanceDeclaringClass]) { return $annotationMethod; } } $declaringClassName = $methodReflection->getDeclaringClass()->getName(); $declaringClass = $classReflection->getAncestorWithClassName($declaringClassName); if ($declaringClass === null) { throw new ShouldNotHappenException(sprintf('Internal error: Expected to find an ancestor with class name %s on %s, but none was found.', $declaringClassName, $classReflection->getName())); } if ($declaringClass->isEnum() && $declaringClass->getName() !== 'UnitEnum' && strtolower($methodReflection->getName()) === 'cases') { $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach (array_keys($classReflection->getEnumCases()) as $name) { $arrayBuilder->setOffsetValueType(null, new EnumCaseObjectType($classReflection->getName(), $name)); } return new \PHPStan\Reflection\Php\EnumCasesMethodReflection($declaringClass, $arrayBuilder->getArray()); } if ($this->signatureMapProvider->hasMethodSignature($declaringClassName, $methodReflection->getName())) { $variantsByType = ['positional' => []]; $reflectionMethod = null; $throwType = null; $asserts = Assertions::createEmpty(); $acceptsNamedArguments = \true; $selfOutType = null; $phpDocComment = null; if ($classReflection->getNativeReflection()->hasMethod($methodReflection->getName())) { $reflectionMethod = $classReflection->getNativeReflection()->getMethod($methodReflection->getName()); } $methodSignaturesResult = $this->signatureMapProvider->getMethodSignatures($declaringClassName, $methodReflection->getName(), $reflectionMethod); foreach ($methodSignaturesResult as $signatureType => $methodSignatures) { if ($methodSignatures === null) { continue; } foreach ($methodSignatures as $methodSignature) { $phpDocParameterNameMapping = []; foreach ($methodSignature->getParameters() as $parameter) { $phpDocParameterNameMapping[$parameter->getName()] = $parameter->getName(); } $stubPhpDocReturnType = null; $stubPhpDocParameterTypes = []; $stubPhpDocParameterVariadicity = []; $phpDocParameterTypes = []; $phpDocReturnType = null; $stubPhpDocPair = null; $stubPhpParameterOutTypes = []; $phpDocParameterOutTypes = []; $immediatelyInvokedCallableParameters = []; $closureThisParameters = []; $stubImmediatelyInvokedCallableParameters = []; $stubClosureThisParameters = []; if (count($methodSignatures) === 1) { $stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors($declaringClass, $declaringClass, $methodReflection->getName(), array_map(static function (ParameterSignature $parameterSignature) : string { return $parameterSignature->getName(); }, $methodSignature->getParameters())); if ($stubPhpDocPair !== null) { [$stubPhpDoc, $stubDeclaringClass] = $stubPhpDocPair; $templateTypeMap = $stubDeclaringClass->getActiveTemplateTypeMap(); $callSiteVarianceMap = $stubDeclaringClass->getCallSiteVarianceMap(); $returnTag = $stubPhpDoc->getReturnTag(); $stubImmediatelyInvokedCallableParameters = array_map(static function (bool $immediate) { return TrinaryLogic::createFromBoolean($immediate); }, $stubPhpDoc->getParamsImmediatelyInvokedCallable()); if ($returnTag !== null) { $stubPhpDocReturnType = TemplateTypeHelper::resolveTemplateTypes($returnTag->getType(), $templateTypeMap, $callSiteVarianceMap, TemplateTypeVariance::createCovariant()); } $stubClosureThisParameters = array_map(static function ($tag) { return $tag->getType(); }, $stubPhpDoc->getParamClosureThisTags()); foreach ($stubPhpDoc->getParamTags() as $name => $paramTag) { $stubPhpDocParameterTypes[$name] = TemplateTypeHelper::resolveTemplateTypes($paramTag->getType(), $templateTypeMap, $callSiteVarianceMap, TemplateTypeVariance::createContravariant()); $stubPhpDocParameterVariadicity[$name] = $paramTag->isVariadic(); } $throwsTag = $stubPhpDoc->getThrowsTag(); if ($throwsTag !== null) { $throwType = $throwsTag->getType(); } $asserts = Assertions::createFromResolvedPhpDocBlock($stubPhpDoc); $acceptsNamedArguments = $stubPhpDoc->acceptsNamedArguments(); $selfOutTypeTag = $stubPhpDoc->getSelfOutTag(); if ($selfOutTypeTag !== null) { $selfOutType = $selfOutTypeTag->getType(); } foreach ($stubPhpDoc->getParamOutTags() as $name => $paramOutTag) { $stubPhpParameterOutTypes[$name] = TemplateTypeHelper::resolveTemplateTypes($paramOutTag->getType(), $templateTypeMap, $callSiteVarianceMap, TemplateTypeVariance::createCovariant()); } if ($declaringClassName === $stubDeclaringClass->getName() && $stubPhpDoc->hasPhpDocString()) { $phpDocComment = $stubPhpDoc->getPhpDocString(); } } } if ($stubPhpDocPair === null && $reflectionMethod !== null && $reflectionMethod->getDocComment() !== \false) { $filename = $reflectionMethod->getFileName(); if ($filename !== \false) { $phpDocBlock = $this->fileTypeMapper->getResolvedPhpDoc($filename, $declaringClassName, null, $reflectionMethod->getName(), $reflectionMethod->getDocComment()); $throwsTag = $phpDocBlock->getThrowsTag(); if ($throwsTag !== null) { $throwType = $throwsTag->getType(); } $returnTag = $phpDocBlock->getReturnTag(); if ($returnTag !== null && count($methodSignatures) === 1) { $phpDocReturnType = $returnTag->getType(); } $immediatelyInvokedCallableParameters = array_map(static function ($immediate) { return TrinaryLogic::createFromBoolean($immediate); }, $phpDocBlock->getParamsImmediatelyInvokedCallable()); $closureThisParameters = array_map(static function ($tag) { return $tag->getType(); }, $phpDocBlock->getParamClosureThisTags()); foreach ($phpDocBlock->getParamTags() as $name => $paramTag) { $phpDocParameterTypes[$name] = $paramTag->getType(); } $asserts = Assertions::createFromResolvedPhpDocBlock($phpDocBlock); $acceptsNamedArguments = $phpDocBlock->acceptsNamedArguments(); $selfOutTypeTag = $phpDocBlock->getSelfOutTag(); if ($selfOutTypeTag !== null) { $selfOutType = $selfOutTypeTag->getType(); } if ($phpDocBlock->hasPhpDocString()) { $phpDocComment = $phpDocBlock->getPhpDocString(); } foreach ($phpDocBlock->getParamOutTags() as $name => $paramOutTag) { $phpDocParameterOutTypes[$name] = $paramOutTag->getType(); } $signatureParameters = $methodSignature->getParameters(); foreach ($reflectionMethod->getParameters() as $paramI => $reflectionParameter) { if (!array_key_exists($paramI, $signatureParameters)) { continue; } $phpDocParameterNameMapping[$signatureParameters[$paramI]->getName()] = $reflectionParameter->getName(); } } } $variantsByType[$signatureType][] = $this->createNativeMethodVariant($methodSignature, $stubPhpDocParameterTypes, $stubPhpDocParameterVariadicity, $stubPhpDocReturnType, $phpDocParameterTypes, $phpDocReturnType, $phpDocParameterNameMapping, $stubPhpParameterOutTypes, $phpDocParameterOutTypes, $stubImmediatelyInvokedCallableParameters, $immediatelyInvokedCallableParameters, $stubClosureThisParameters, $closureThisParameters, $signatureType !== 'named'); } } if ($this->signatureMapProvider->hasMethodMetadata($declaringClassName, $methodReflection->getName())) { $hasSideEffects = TrinaryLogic::createFromBoolean($this->signatureMapProvider->getMethodMetadata($declaringClassName, $methodReflection->getName())['hasSideEffects']); } else { $hasSideEffects = TrinaryLogic::createMaybe(); } return new NativeMethodReflection($this->reflectionProviderProvider->getReflectionProvider(), $declaringClass, $methodReflection, $variantsByType['positional'], $variantsByType['named'] ?? null, $hasSideEffects, $throwType, $asserts, $acceptsNamedArguments, $selfOutType, $phpDocComment); } return $this->createUserlandMethodReflection($declaringClass, $declaringClass, $methodReflection, $this->findMethodTrait($methodReflection)); } public function createUserlandMethodReflection(ClassReflection $fileDeclaringClass, ClassReflection $actualDeclaringClass, \PHPStan\Reflection\Php\BuiltinMethodReflection $methodReflection, ?string $declaringTraitName) : \PHPStan\Reflection\Php\PhpMethodReflection { $resolvedPhpDoc = null; $stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors($fileDeclaringClass, $fileDeclaringClass, $methodReflection->getName(), array_map(static function (ReflectionParameter $parameter) : string { return $parameter->getName(); }, $methodReflection->getParameters())); $phpDocBlockClassReflection = $fileDeclaringClass; if ($methodReflection->getReflection() !== null) { $methodDeclaringClass = $methodReflection->getReflection()->getBetterReflection()->getDeclaringClass(); if ($stubPhpDocPair === null && $methodDeclaringClass->isTrait()) { if (!$methodReflection->getDeclaringClass()->isTrait() || $methodDeclaringClass->getName() !== $methodReflection->getDeclaringClass()->getName()) { $stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors($this->reflectionProviderProvider->getReflectionProvider()->getClass($methodDeclaringClass->getName()), $this->reflectionProviderProvider->getReflectionProvider()->getClass($methodReflection->getDeclaringClass()->getName()), $methodReflection->getName(), array_map(static function (ReflectionParameter $parameter) : string { return $parameter->getName(); }, $methodReflection->getParameters())); } } } if ($stubPhpDocPair !== null) { [$resolvedPhpDoc, $phpDocBlockClassReflection] = $stubPhpDocPair; } if ($resolvedPhpDoc === null) { $docComment = $methodReflection->getDocComment(); $positionalParameterNames = array_map(static function (ReflectionParameter $parameter) : string { return $parameter->getName(); }, $methodReflection->getParameters()); $resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForMethod($docComment, $actualDeclaringClass->getFileName(), $actualDeclaringClass, $declaringTraitName, $methodReflection->getName(), $positionalParameterNames); $phpDocBlockClassReflection = $fileDeclaringClass; } $declaringTrait = null; $reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider(); if ($declaringTraitName !== null && $reflectionProvider->hasClass($declaringTraitName)) { $declaringTrait = $reflectionProvider->getClass($declaringTraitName); } $phpDocParameterTypes = []; if ($methodReflection instanceof \PHPStan\Reflection\Php\NativeBuiltinMethodReflection && $methodReflection->isConstructor()) { foreach ($methodReflection->getParameters() as $parameter) { if (!$parameter->isPromoted()) { continue; } if (!$methodReflection->getDeclaringClass()->hasProperty($parameter->getName())) { continue; } $parameterProperty = $methodReflection->getDeclaringClass()->getProperty($parameter->getName()); if (!$parameterProperty->isPromoted()) { continue; } if ($parameterProperty->getDocComment() === \false) { continue; } $propertyDocblock = $this->fileTypeMapper->getResolvedPhpDoc($fileDeclaringClass->getFileName(), $fileDeclaringClass->getName(), $declaringTraitName, $methodReflection->getName(), $parameterProperty->getDocComment()); $varTags = $propertyDocblock->getVarTags(); if (isset($varTags[0]) && count($varTags) === 1) { $phpDocType = $varTags[0]->getType(); } elseif (isset($varTags[$parameter->getName()])) { $phpDocType = $varTags[$parameter->getName()]->getType(); } else { continue; } $phpDocParameterTypes[$parameter->getName()] = $phpDocType; } } $templateTypeMap = $resolvedPhpDoc->getTemplateTypeMap(); $immediatelyInvokedCallableParameters = array_map(static function (bool $immediate) { return TrinaryLogic::createFromBoolean($immediate); }, $resolvedPhpDoc->getParamsImmediatelyInvokedCallable()); $closureThisParameters = array_map(static function ($tag) { return $tag->getType(); }, $resolvedPhpDoc->getParamClosureThisTags()); foreach ($resolvedPhpDoc->getParamTags() as $paramName => $paramTag) { if (array_key_exists($paramName, $phpDocParameterTypes)) { continue; } $phpDocParameterTypes[$paramName] = $paramTag->getType(); } foreach ($phpDocParameterTypes as $paramName => $paramType) { $phpDocParameterTypes[$paramName] = TemplateTypeHelper::resolveTemplateTypes($paramType, $phpDocBlockClassReflection->getActiveTemplateTypeMap(), $phpDocBlockClassReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createContravariant()); } $phpDocParameterOutTypes = []; foreach ($resolvedPhpDoc->getParamOutTags() as $paramName => $paramOutTag) { $phpDocParameterOutTypes[$paramName] = TemplateTypeHelper::resolveTemplateTypes($paramOutTag->getType(), $phpDocBlockClassReflection->getActiveTemplateTypeMap(), $phpDocBlockClassReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createCovariant()); } $nativeReturnType = TypehintHelper::decideTypeFromReflection($methodReflection->getReturnType(), null, $actualDeclaringClass); $phpDocReturnType = $this->getPhpDocReturnType($phpDocBlockClassReflection, $resolvedPhpDoc, $nativeReturnType); $phpDocThrowType = $resolvedPhpDoc->getThrowsTag() !== null ? $resolvedPhpDoc->getThrowsTag()->getType() : null; $deprecatedDescription = $resolvedPhpDoc->getDeprecatedTag() !== null ? $resolvedPhpDoc->getDeprecatedTag()->getMessage() : null; $isDeprecated = $resolvedPhpDoc->isDeprecated(); $isInternal = $resolvedPhpDoc->isInternal(); $isFinal = $resolvedPhpDoc->isFinal(); $isPure = $resolvedPhpDoc->isPure(); $asserts = Assertions::createFromResolvedPhpDocBlock($resolvedPhpDoc); $acceptsNamedArguments = $resolvedPhpDoc->acceptsNamedArguments(); $selfOutType = $resolvedPhpDoc->getSelfOutTag() !== null ? $resolvedPhpDoc->getSelfOutTag()->getType() : null; $phpDocComment = null; if ($resolvedPhpDoc->hasPhpDocString()) { $phpDocComment = $resolvedPhpDoc->getPhpDocString(); } return $this->methodReflectionFactory->create($actualDeclaringClass, $declaringTrait, $methodReflection, $templateTypeMap, $phpDocParameterTypes, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $asserts, $selfOutType, $phpDocComment, $phpDocParameterOutTypes, $immediatelyInvokedCallableParameters, $closureThisParameters, $acceptsNamedArguments); } /** * @param array $stubPhpDocParameterTypes * @param array $stubPhpDocParameterVariadicity * @param array $phpDocParameterTypes * @param array $phpDocParameterNameMapping * @param array $stubPhpDocParameterOutTypes * @param array $phpDocParameterOutTypes * @param array $stubImmediatelyInvokedCallableParameters * @param array $immediatelyInvokedCallableParameters * @param array $stubClosureThisParameters * @param array $closureThisParameters */ private function createNativeMethodVariant(FunctionSignature $methodSignature, array $stubPhpDocParameterTypes, array $stubPhpDocParameterVariadicity, ?Type $stubPhpDocReturnType, array $phpDocParameterTypes, ?Type $phpDocReturnType, array $phpDocParameterNameMapping, array $stubPhpDocParameterOutTypes, array $phpDocParameterOutTypes, array $stubImmediatelyInvokedCallableParameters, array $immediatelyInvokedCallableParameters, array $stubClosureThisParameters, array $closureThisParameters, bool $usePhpDocParameterNames) : FunctionVariantWithPhpDocs { $parameters = []; foreach ($methodSignature->getParameters() as $parameterSignature) { $type = null; $phpDocType = null; $parameterOutType = null; $phpDocParameterName = $phpDocParameterNameMapping[$parameterSignature->getName()] ?? $parameterSignature->getName(); if (isset($stubPhpDocParameterTypes[$parameterSignature->getName()])) { $type = $stubPhpDocParameterTypes[$parameterSignature->getName()]; $phpDocType = $stubPhpDocParameterTypes[$parameterSignature->getName()]; } elseif (isset($phpDocParameterTypes[$phpDocParameterName])) { $phpDocType = $phpDocParameterTypes[$phpDocParameterName]; } if (isset($stubPhpDocParameterOutTypes[$parameterSignature->getName()])) { $parameterOutType = $stubPhpDocParameterOutTypes[$parameterSignature->getName()]; } elseif (isset($phpDocParameterOutTypes[$phpDocParameterName])) { $parameterOutType = $phpDocParameterOutTypes[$phpDocParameterName]; } if (isset($stubImmediatelyInvokedCallableParameters[$parameterSignature->getName()])) { $immediatelyInvoked = $stubImmediatelyInvokedCallableParameters[$parameterSignature->getName()]; } elseif (isset($immediatelyInvokedCallableParameters[$phpDocParameterName])) { $immediatelyInvoked = $immediatelyInvokedCallableParameters[$phpDocParameterName]; } else { $immediatelyInvoked = TrinaryLogic::createMaybe(); } $closureThisType = null; if (isset($stubClosureThisParameters[$parameterSignature->getName()])) { $closureThisType = $stubClosureThisParameters[$parameterSignature->getName()]; } elseif (isset($closureThisParameters[$phpDocParameterName])) { $closureThisType = $closureThisParameters[$phpDocParameterName]; } $parameters[] = new NativeParameterWithPhpDocsReflection($usePhpDocParameterNames ? $phpDocParameterName : $parameterSignature->getName(), $parameterSignature->isOptional(), $type ?? $parameterSignature->getType(), $phpDocType ?? new MixedType(), $parameterSignature->getNativeType(), $parameterSignature->passedByReference(), $stubPhpDocParameterVariadicity[$parameterSignature->getName()] ?? $parameterSignature->isVariadic(), $parameterSignature->getDefaultValue(), $parameterOutType ?? $parameterSignature->getOutType(), $immediatelyInvoked, $closureThisType); } if ($stubPhpDocReturnType !== null) { $returnType = $stubPhpDocReturnType; $phpDocReturnType = $stubPhpDocReturnType; } else { $returnType = TypehintHelper::decideType($methodSignature->getReturnType(), $phpDocReturnType); } return new FunctionVariantWithPhpDocs(TemplateTypeMap::createEmpty(), null, $parameters, $methodSignature->isVariadic(), $returnType, $phpDocReturnType ?? new MixedType(), $methodSignature->getNativeReturnType()); } private function findPropertyTrait(ReflectionProperty $propertyReflection) : ?string { $declaringClass = $propertyReflection->getBetterReflection()->getDeclaringClass(); if ($declaringClass->isTrait()) { if ($propertyReflection->getDeclaringClass()->isTrait() && $propertyReflection->getDeclaringClass()->getName() === $declaringClass->getName()) { return null; } return $declaringClass->getName(); } return null; } private function findMethodTrait(\PHPStan\Reflection\Php\BuiltinMethodReflection $methodReflection) : ?string { if ($methodReflection->getReflection() === null) { return null; } $declaringClass = $methodReflection->getReflection()->getBetterReflection()->getDeclaringClass(); if ($declaringClass->isTrait()) { if ($methodReflection->getDeclaringClass()->isTrait() && $declaringClass->getName() === $methodReflection->getDeclaringClass()->getName()) { return null; } return $declaringClass->getName(); } return null; } private function inferPrivatePropertyType(string $propertyName, MethodReflection $constructor) : ?Type { $declaringClassName = $constructor->getDeclaringClass()->getName(); if (isset($this->inferClassConstructorPropertyTypesInProcess[$declaringClassName])) { return null; } $this->inferClassConstructorPropertyTypesInProcess[$declaringClassName] = \true; $propertyTypes = $this->inferAndCachePropertyTypes($constructor); unset($this->inferClassConstructorPropertyTypesInProcess[$declaringClassName]); if (array_key_exists($propertyName, $propertyTypes)) { return $propertyTypes[$propertyName]; } return null; } /** * @return array */ private function inferAndCachePropertyTypes(MethodReflection $constructor) : array { $declaringClass = $constructor->getDeclaringClass(); if (isset($this->propertyTypesCache[$declaringClass->getName()])) { return $this->propertyTypesCache[$declaringClass->getName()]; } if ($declaringClass->getFileName() === null) { return $this->propertyTypesCache[$declaringClass->getName()] = []; } $fileName = $declaringClass->getFileName(); $nodes = $this->parser->parseFile($fileName); $classNode = $this->findClassNode($declaringClass->getName(), $nodes); if ($classNode === null) { return $this->propertyTypesCache[$declaringClass->getName()] = []; } $methodNode = $this->findConstructorNode($constructor->getName(), $classNode->stmts); if ($methodNode === null || $methodNode->stmts === null || count($methodNode->stmts) === 0) { return $this->propertyTypesCache[$declaringClass->getName()] = []; } $classNameParts = explode('\\', $declaringClass->getName()); $namespace = null; if (count($classNameParts) > 1) { $namespace = implode('\\', array_slice($classNameParts, 0, -1)); } $classScope = $this->scopeFactory->create(ScopeContext::create($fileName)); if ($namespace !== null) { $classScope = $classScope->enterNamespace($namespace); } $classScope = $classScope->enterClass($declaringClass); [$templateTypeMap, $phpDocParameterTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, , $phpDocComment, $asserts, $selfOutType, $phpDocParameterOutTypes] = $this->nodeScopeResolver->getPhpDocs($classScope, $methodNode); $methodScope = $classScope->enterClassMethod($methodNode, $templateTypeMap, $phpDocParameterTypes, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, $asserts, $selfOutType, $phpDocComment, $phpDocParameterOutTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters); $propertyTypes = []; foreach ($methodNode->stmts as $statement) { if (!$statement instanceof Node\Stmt\Expression) { continue; } $expr = $statement->expr; if (!$expr instanceof Node\Expr\Assign) { continue; } if (!$expr->var instanceof Node\Expr\PropertyFetch) { continue; } $propertyFetch = $expr->var; if (!$propertyFetch->var instanceof Node\Expr\Variable || $propertyFetch->var->name !== 'this' || !$propertyFetch->name instanceof Node\Identifier) { continue; } $propertyType = $methodScope->getType($expr->expr); if ($propertyType instanceof ErrorType || $propertyType instanceof NeverType) { continue; } $propertyType = $propertyType->generalize(GeneralizePrecision::lessSpecific()); if ($propertyType->isConstantArray()->yes()) { $propertyType = new ArrayType(new MixedType(\true), new MixedType(\true)); } $propertyTypes[$propertyFetch->name->toString()] = $propertyType; } return $this->propertyTypesCache[$declaringClass->getName()] = $propertyTypes; } /** * @param Node[] $nodes */ private function findClassNode(string $className, array $nodes) : ?Class_ { foreach ($nodes as $node) { if ($node instanceof Class_ && $node->namespacedName !== null && $node->namespacedName->toString() === $className) { return $node; } if (!$node instanceof Namespace_ && !$node instanceof Declare_) { continue; } $subNodeNames = $node->getSubNodeNames(); foreach ($subNodeNames as $subNodeName) { $subNode = $node->{$subNodeName}; if (!is_array($subNode)) { $subNode = [$subNode]; } $result = $this->findClassNode($className, $subNode); if ($result === null) { continue; } return $result; } } return null; } /** * @param Node\Stmt[] $classStatements */ private function findConstructorNode(string $methodName, array $classStatements) : ?ClassMethod { foreach ($classStatements as $statement) { if ($statement instanceof ClassMethod && $statement->name->toString() === $methodName) { return $statement; } } return null; } private function getPhpDocReturnType(ClassReflection $phpDocBlockClassReflection, ResolvedPhpDocBlock $resolvedPhpDoc, Type $nativeReturnType) : ?Type { $returnTag = $resolvedPhpDoc->getReturnTag(); if ($returnTag === null) { return null; } $phpDocReturnType = $returnTag->getType(); $phpDocReturnType = TemplateTypeHelper::resolveTemplateTypes($phpDocReturnType, $phpDocBlockClassReflection->getActiveTemplateTypeMap(), $phpDocBlockClassReflection->getCallSiteVarianceMap(), TemplateTypeVariance::createCovariant()); if ($returnTag->isExplicit() || $nativeReturnType->isSuperTypeOf($phpDocReturnType)->yes()) { return $phpDocReturnType; } return null; } /** * @param array $positionalParameterNames * @return array{ResolvedPhpDocBlock, ClassReflection}|null */ private function findMethodPhpDocIncludingAncestors(ClassReflection $declaringClass, ClassReflection $implementingClass, string $methodName, array $positionalParameterNames) : ?array { $declaringClassName = $declaringClass->getName(); $resolved = $this->stubPhpDocProvider->findMethodPhpDoc($declaringClassName, $implementingClass->getName(), $methodName, $positionalParameterNames); if ($resolved !== null) { return [$resolved, $declaringClass]; } if (!$this->stubPhpDocProvider->isKnownClass($declaringClassName)) { return null; } $ancestors = $declaringClass->getAncestors(); foreach ($ancestors as $ancestor) { if ($ancestor->getName() === $declaringClassName) { continue; } if (!$ancestor->hasNativeMethod($methodName)) { continue; } $resolved = $this->stubPhpDocProvider->findMethodPhpDoc($ancestor->getName(), $ancestor->getName(), $methodName, $positionalParameterNames); if ($resolved === null) { continue; } return [$resolved, $ancestor]; } return null; } } $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters */ public function create(ClassReflection $declaringClass, ?ClassReflection $declaringTrait, \PHPStan\Reflection\Php\BuiltinMethodReflection $reflection, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $phpDocThrowType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?bool $isPure, Assertions $asserts, ?Type $selfOutType, ?string $phpDocComment, array $phpDocParameterOutTypes, array $immediatelyInvokedCallableParameters = [], array $phpDocClosureThisTypeParameters = [], bool $acceptsNamedArguments = \true) : \PHPStan\Reflection\Php\PhpMethodReflection; } $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters */ public function __construct(ClassReflection $declaringClass, ClassMethod $classMethod, string $fileName, TemplateTypeMap $templateTypeMap, array $realParameterTypes, array $phpDocParameterTypes, array $realParameterDefaultValues, Type $realReturnType, ?Type $phpDocReturnType, ?Type $throwType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?bool $isPure, bool $acceptsNamedArguments, Assertions $assertions, ?Type $selfOutType, ?string $phpDocComment, array $parameterOutTypes, array $immediatelyInvokedCallableParameters, array $phpDocClosureThisTypeParameters, bool $isConstructor) { $this->declaringClass = $declaringClass; $this->selfOutType = $selfOutType; $this->isConstructor = $isConstructor; $name = strtolower($classMethod->name->name); if ($this->isConstructor) { $realReturnType = new VoidType(); } if (in_array($name, ['__destruct', '__unset', '__wakeup', '__clone'], \true)) { $realReturnType = new VoidType(); } if ($name === '__tostring') { $realReturnType = new StringType(); } if ($name === '__isset') { $realReturnType = new BooleanType(); } if ($name === '__sleep') { $realReturnType = new ArrayType(new IntegerType(), new StringType()); } if ($name === '__set_state') { $realReturnType = TypeCombinator::intersect(new ObjectWithoutClassType(), $realReturnType); } if ($name === '__set') { $realReturnType = new VoidType(); } if ($name === '__debuginfo') { $realReturnType = TypeCombinator::intersect(TypeCombinator::addNull(new ArrayType(new MixedType(\true), new MixedType(\true))), $realReturnType); } if ($name === '__unserialize') { $realReturnType = new VoidType(); } if ($name === '__serialize') { $realReturnType = new ArrayType(new MixedType(\true), new MixedType(\true)); } parent::__construct($classMethod, $fileName, $templateTypeMap, $realParameterTypes, $phpDocParameterTypes, $realParameterDefaultValues, $realReturnType, $phpDocReturnType, $throwType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal || $classMethod->isFinal(), $isPure, $acceptsNamedArguments, $assertions, $phpDocComment, $parameterOutTypes, $immediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters); } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function getPrototype() : ClassMemberReflection { try { return $this->declaringClass->getNativeMethod($this->getClassMethod()->name->name)->getPrototype(); } catch (MissingMethodFromReflectionException $e) { return $this; } } private function getClassMethod() : ClassMethod { /** @var Node\Stmt\ClassMethod $functionLike */ $functionLike = $this->getFunctionLike(); return $functionLike; } public function isStatic() : bool { return $this->getClassMethod()->isStatic(); } public function isPrivate() : bool { return $this->getClassMethod()->isPrivate(); } public function isPublic() : bool { return $this->getClassMethod()->isPublic(); } public function isBuiltin() : bool { return \false; } public function getSelfOutType() : ?Type { return $this->selfOutType; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->getClassMethod()->returnsByRef()); } public function isAbstract() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->getClassMethod()->isAbstract()); } public function isConstructor() : bool { return $this->isConstructor; } public function hasSideEffects() : TrinaryLogic { if (strtolower($this->getName()) !== '__construct' && $this->getReturnType()->isVoid()->yes()) { return TrinaryLogic::createYes(); } if ($this->isPure !== null) { return TrinaryLogic::createFromBoolean(!$this->isPure); } return TrinaryLogic::createMaybe(); } } nativeMethodReflection = $nativeMethodReflection; $this->closureType = $closureType; } public function getDeclaringClass() : ClassReflection { return $this->nativeMethodReflection->getDeclaringClass(); } public function isStatic() : bool { return $this->nativeMethodReflection->isStatic(); } public function isPrivate() : bool { return $this->nativeMethodReflection->isPrivate(); } public function isPublic() : bool { return $this->nativeMethodReflection->isPublic(); } public function getDocComment() : ?string { return $this->nativeMethodReflection->getDocComment(); } public function getName() : string { return $this->nativeMethodReflection->getName(); } public function getPrototype() : ClassMemberReflection { return $this->nativeMethodReflection->getPrototype(); } public function getVariants() : array { $parameters = $this->closureType->getParameters(); $newThis = new NativeParameterReflection('newThis', \false, new ObjectWithoutClassType(), PassedByReference::createNo(), \false, null); array_unshift($parameters, $newThis); return [new FunctionVariantWithPhpDocs($this->closureType->getTemplateTypeMap(), $this->closureType->getResolvedTemplateTypeMap(), array_map(static function (ParameterReflection $parameter) : ParameterReflectionWithPhpDocs { return new \PHPStan\Reflection\Php\DummyParameterWithPhpDocs($parameter->getName(), $parameter->getType(), $parameter->isOptional(), $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), new MixedType(), $parameter->getType(), null, TrinaryLogic::createMaybe(), null); }, $parameters), $this->closureType->isVariadic(), $this->closureType->getReturnType(), $this->closureType->getReturnType(), new MixedType(), $this->closureType->getCallSiteVarianceMap())]; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { return null; } public function isDeprecated() : TrinaryLogic { return $this->nativeMethodReflection->isDeprecated(); } public function getDeprecatedDescription() : ?string { return $this->nativeMethodReflection->getDeprecatedDescription(); } public function isFinal() : TrinaryLogic { return $this->nativeMethodReflection->isFinal(); } public function isFinalByKeyword() : TrinaryLogic { return $this->nativeMethodReflection->isFinalByKeyword(); } public function isInternal() : TrinaryLogic { return $this->nativeMethodReflection->isInternal(); } public function getThrowType() : ?Type { return $this->nativeMethodReflection->getThrowType(); } public function hasSideEffects() : TrinaryLogic { return $this->nativeMethodReflection->hasSideEffects(); } public function getAsserts() : Assertions { return $this->nativeMethodReflection->getAsserts(); } public function acceptsNamedArguments() : bool { return $this->nativeMethodReflection->acceptsNamedArguments(); } public function getSelfOutType() : ?Type { return $this->nativeMethodReflection->getSelfOutType(); } public function returnsByReference() : TrinaryLogic { return $this->nativeMethodReflection->returnsByReference(); } public function isAbstract() : TrinaryLogic { $abstract = $this->nativeMethodReflection->isAbstract(); if (is_bool($abstract)) { return TrinaryLogic::createFromBoolean($abstract); } return $abstract; } public function isPure() : TrinaryLogic { return $this->nativeMethodReflection->isPure(); } } initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflection = $reflection; $this->phpDocType = $phpDocType; $this->declaringClassName = $declaringClassName; $this->outType = $outType; $this->immediatelyInvokedCallable = $immediatelyInvokedCallable; $this->closureThisType = $closureThisType; } public function isOptional() : bool { return $this->reflection->isOptional(); } public function getName() : string { return $this->reflection->getName(); } public function getType() : Type { if ($this->type === null) { $phpDocType = $this->phpDocType; if ($phpDocType !== null && $this->reflection->isDefaultValueAvailable()) { $defaultValueType = $this->initializerExprTypeResolver->getType($this->reflection->getDefaultValueExpression(), InitializerExprContext::fromReflectionParameter($this->reflection)); if ($defaultValueType->isNull()->yes()) { $phpDocType = TypeCombinator::addNull($phpDocType); } } $this->type = TypehintHelper::decideTypeFromReflection($this->reflection->getType(), $phpDocType, $this->declaringClassName, $this->isVariadic()); } return $this->type; } public function passedByReference() : PassedByReference { return $this->reflection->isPassedByReference() ? PassedByReference::createCreatesNewVariable() : PassedByReference::createNo(); } public function isVariadic() : bool { return $this->reflection->isVariadic(); } public function getPhpDocType() : Type { if ($this->phpDocType !== null) { return $this->phpDocType; } return new MixedType(); } public function getNativeType() : Type { if ($this->nativeType === null) { $this->nativeType = TypehintHelper::decideTypeFromReflection($this->reflection->getType(), null, $this->declaringClassName, $this->isVariadic()); } return $this->nativeType; } public function getDefaultValue() : ?Type { if ($this->reflection->isDefaultValueAvailable()) { return $this->initializerExprTypeResolver->getType($this->reflection->getDefaultValueExpression(), InitializerExprContext::fromReflectionParameter($this->reflection)); } return null; } public function getOutType() : ?Type { return $this->outType; } public function isImmediatelyInvokedCallable() : TrinaryLogic { return $this->immediatelyInvokedCallable; } public function getClosureThisType() : ?Type { return $this->closureThisType; } } */ private $immediatelyInvokedCallableParameters; /** * @var array */ private $phpDocClosureThisTypeParameters; /** @var PhpParameterReflection[]|null */ private $parameters = null; /** * @var ?Type */ private $returnType = null; /** * @var ?Type */ private $nativeReturnType = null; /** @var FunctionVariantWithPhpDocs[]|null */ private $variants = null; /** * @param Type[] $phpDocParameterTypes * @param Type[] $phpDocParameterOutTypes * @param array $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters */ public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver, ClassReflection $declaringClass, ?ClassReflection $declaringTrait, \PHPStan\Reflection\Php\BuiltinMethodReflection $reflection, ReflectionProvider $reflectionProvider, Parser $parser, FunctionCallStatementFinder $functionCallStatementFinder, Cache $cache, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $phpDocThrowType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?bool $isPure, Assertions $asserts, bool $acceptsNamedArguments, ?Type $selfOutType, ?string $phpDocComment, array $phpDocParameterOutTypes, array $immediatelyInvokedCallableParameters, array $phpDocClosureThisTypeParameters) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->declaringClass = $declaringClass; $this->declaringTrait = $declaringTrait; $this->reflection = $reflection; $this->reflectionProvider = $reflectionProvider; $this->parser = $parser; $this->functionCallStatementFinder = $functionCallStatementFinder; $this->cache = $cache; $this->templateTypeMap = $templateTypeMap; $this->phpDocParameterTypes = $phpDocParameterTypes; $this->phpDocReturnType = $phpDocReturnType; $this->phpDocThrowType = $phpDocThrowType; $this->deprecatedDescription = $deprecatedDescription; $this->isDeprecated = $isDeprecated; $this->isInternal = $isInternal; $this->isFinal = $isFinal; $this->isPure = $isPure; $this->asserts = $asserts; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->selfOutType = $selfOutType; $this->phpDocComment = $phpDocComment; $this->phpDocParameterOutTypes = $phpDocParameterOutTypes; $this->immediatelyInvokedCallableParameters = $immediatelyInvokedCallableParameters; $this->phpDocClosureThisTypeParameters = $phpDocClosureThisTypeParameters; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function getDeclaringTrait() : ?ClassReflection { return $this->declaringTrait; } /** * @return self|MethodPrototypeReflection */ public function getPrototype() : ClassMemberReflection { try { $prototypeMethod = $this->reflection->getPrototype(); $prototypeDeclaringClass = $this->declaringClass->getAncestorWithClassName($prototypeMethod->getDeclaringClass()->getName()); if ($prototypeDeclaringClass === null) { $prototypeDeclaringClass = $this->reflectionProvider->getClass($prototypeMethod->getDeclaringClass()->getName()); } if (!$prototypeDeclaringClass->hasNativeMethod($prototypeMethod->getName())) { return $this; } $tentativeReturnType = null; if ($prototypeMethod->getTentativeReturnType() !== null) { $tentativeReturnType = TypehintHelper::decideTypeFromReflection($prototypeMethod->getTentativeReturnType()); } return new MethodPrototypeReflection($prototypeMethod->getName(), $prototypeDeclaringClass, $prototypeMethod->isStatic(), $prototypeMethod->isPrivate(), $prototypeMethod->isPublic(), $prototypeMethod->isAbstract(), $prototypeMethod->isFinal(), $prototypeMethod->isInternal(), $prototypeDeclaringClass->getNativeMethod($prototypeMethod->getName())->getVariants(), $tentativeReturnType); } catch (ReflectionException $e) { return $this; } } public function isStatic() : bool { return $this->reflection->isStatic(); } public function getName() : string { $name = $this->reflection->getName(); $lowercaseName = strtolower($name); if ($lowercaseName === $name) { if (PHP_VERSION_ID >= 80000) { return $name; } // fix for https://bugs.php.net/bug.php?id=74939 foreach ($this->getDeclaringClass()->getNativeReflection()->getTraitAliases() as $traitTarget) { $correctName = $this->getMethodNameWithCorrectCase($name, $traitTarget); if ($correctName !== null) { $name = $correctName; break; } } } return $name; } private function getMethodNameWithCorrectCase(string $lowercaseMethodName, string $traitTarget) : ?string { $trait = explode('::', $traitTarget)[0]; $traitReflection = $this->reflectionProvider->getClass($trait)->getNativeReflection(); foreach ($traitReflection->getTraitAliases() as $methodAlias => $aliasTraitTarget) { if ($lowercaseMethodName === strtolower($methodAlias)) { return $methodAlias; } $correctName = $this->getMethodNameWithCorrectCase($lowercaseMethodName, $aliasTraitTarget); if ($correctName !== null) { return $correctName; } } return null; } /** * @return ParametersAcceptorWithPhpDocs[] */ public function getVariants() : array { if ($this->variants === null) { $this->variants = [new FunctionVariantWithPhpDocs($this->templateTypeMap, null, $this->getParameters(), $this->isVariadic(), $this->getReturnType(), $this->getPhpDocReturnType(), $this->getNativeReturnType())]; } return $this->variants; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { return null; } /** * @return ParameterReflectionWithPhpDocs[] */ private function getParameters() : array { if ($this->parameters === null) { $this->parameters = array_map(function (ReflectionParameter $reflection) : \PHPStan\Reflection\Php\PhpParameterReflection { return new \PHPStan\Reflection\Php\PhpParameterReflection($this->initializerExprTypeResolver, $reflection, $this->phpDocParameterTypes[$reflection->getName()] ?? null, $this->getDeclaringClass()->getName(), $this->phpDocParameterOutTypes[$reflection->getName()] ?? null, $this->immediatelyInvokedCallableParameters[$reflection->getName()] ?? TrinaryLogic::createMaybe(), $this->phpDocClosureThisTypeParameters[$reflection->getName()] ?? null); }, $this->reflection->getParameters()); } return $this->parameters; } private function isVariadic() : bool { $isNativelyVariadic = $this->reflection->isVariadic(); $declaringClass = $this->declaringClass; $filename = $this->declaringClass->getFileName(); if ($this->declaringTrait !== null) { $declaringClass = $this->declaringTrait; $filename = $this->declaringTrait->getFileName(); } if (!$isNativelyVariadic && $filename !== null) { $modifiedTime = @filemtime($filename); if ($modifiedTime === \false) { $modifiedTime = time(); } $key = sprintf('variadic-method-%s-%s-%s', $declaringClass->getName(), $this->reflection->getName(), $filename); $variableCacheKey = sprintf('%d-v4', $modifiedTime); $cachedResult = $this->cache->load($key, $variableCacheKey); if ($cachedResult === null || !is_bool($cachedResult)) { $nodes = $this->parser->parseFile($filename); $result = $this->callsFuncGetArgs($declaringClass, $nodes); $this->cache->save($key, $variableCacheKey, $result); return $result; } return $cachedResult; } return $isNativelyVariadic; } /** * @param Node[] $nodes */ private function callsFuncGetArgs(ClassReflection $declaringClass, array $nodes) : bool { foreach ($nodes as $node) { if ($node instanceof Node\Stmt\ClassLike) { if (!isset($node->namespacedName)) { continue; } if ($declaringClass->getName() !== (string) $node->namespacedName) { continue; } if ($this->callsFuncGetArgs($declaringClass, $node->stmts)) { return \true; } continue; } if ($node instanceof ClassMethod) { if ($node->getStmts() === null) { continue; // interface } $methodName = $node->name->name; if ($methodName === $this->reflection->getName()) { return $this->functionCallStatementFinder->findFunctionCallInStatements(ParametersAcceptor::VARIADIC_FUNCTIONS, $node->getStmts()) !== null; } continue; } if ($node instanceof Function_) { continue; } if ($node instanceof Namespace_) { if ($this->callsFuncGetArgs($declaringClass, $node->stmts)) { return \true; } continue; } if (!$node instanceof Declare_ || $node->stmts === null) { continue; } if ($this->callsFuncGetArgs($declaringClass, $node->stmts)) { return \true; } } return \false; } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } private function getReturnType() : Type { if ($this->returnType === null) { $name = strtolower($this->getName()); $returnType = $this->reflection->getReturnType(); if ($returnType === null) { if (in_array($name, ['__construct', '__destruct', '__unset', '__wakeup', '__clone'], \true)) { return $this->returnType = TypehintHelper::decideType(new VoidType(), $this->phpDocReturnType); } if ($name === '__tostring') { return $this->returnType = TypehintHelper::decideType(new StringType(), $this->phpDocReturnType); } if ($name === '__isset') { return $this->returnType = TypehintHelper::decideType(new BooleanType(), $this->phpDocReturnType); } if ($name === '__sleep') { return $this->returnType = TypehintHelper::decideType(new ArrayType(new IntegerType(), new StringType()), $this->phpDocReturnType); } if ($name === '__set_state') { return $this->returnType = TypehintHelper::decideType(new ObjectWithoutClassType(), $this->phpDocReturnType); } } $this->returnType = TypehintHelper::decideTypeFromReflection($returnType, $this->phpDocReturnType, $this->declaringClass); } return $this->returnType; } private function getPhpDocReturnType() : Type { if ($this->phpDocReturnType !== null) { return $this->phpDocReturnType; } return new MixedType(); } private function getNativeReturnType() : Type { if ($this->nativeReturnType === null) { $this->nativeReturnType = TypehintHelper::decideTypeFromReflection($this->reflection->getReturnType(), null, $this->declaringClass); } return $this->nativeReturnType; } public function getDeprecatedDescription() : ?string { if ($this->isDeprecated) { return $this->deprecatedDescription; } return null; } public function isDeprecated() : TrinaryLogic { if ($this->isDeprecated) { return TrinaryLogic::createYes(); } return $this->reflection->isDeprecated(); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isInternal || $this->reflection->isInternal()); } public function isFinal() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isFinal || $this->reflection->isFinal()); } public function isFinalByKeyword() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->isFinal()); } public function isAbstract() : bool { return $this->reflection->isAbstract(); } public function getThrowType() : ?Type { return $this->phpDocThrowType; } public function hasSideEffects() : TrinaryLogic { if (strtolower($this->getName()) !== '__construct' && $this->getReturnType()->isVoid()->yes()) { return TrinaryLogic::createYes(); } if ($this->isPure !== null) { return TrinaryLogic::createFromBoolean(!$this->isPure); } if ((new ThisType($this->declaringClass))->isSuperTypeOf($this->getReturnType())->yes()) { return TrinaryLogic::createYes(); } return TrinaryLogic::createMaybe(); } public function getAsserts() : Assertions { return $this->asserts; } public function acceptsNamedArguments() : bool { return $this->declaringClass->acceptsNamedArguments() && $this->acceptsNamedArguments; } public function getSelfOutType() : ?Type { return $this->selfOutType; } public function getDocComment() : ?string { return $this->phpDocComment; } public function returnsByReference() : TrinaryLogic { return $this->reflection->returnsByReference(); } public function isPure() : TrinaryLogic { if ($this->isPure === null) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createFromBoolean($this->isPure); } } declaringClass = $declaringClass; $this->readableType = $readableType; $this->writableType = $writableType; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return \false; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getReadableType() : Type { return $this->readableType; } public function getWritableType() : Type { return $this->writableType; } public function canChangeTypeAfterAssignment() : bool { return \true; } public function isReadable() : bool { return \true; } public function isWritable() : bool { return \true; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription() : ?string { return null; } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDocComment() : ?string { return null; } } declaringClass = $declaringClass; $this->type = $type; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return \false; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getReadableType() : Type { return $this->type; } public function getWritableType() : Type { return TypeCombinator::union($this->type, new IntegerType(), new FloatType(), new StringType(), new BooleanType()); } public function isReadable() : bool { return \true; } public function isWritable() : bool { return \true; } public function canChangeTypeAfterAssignment() : bool { return \false; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription() : ?string { return null; } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDocComment() : ?string { return null; } } declaringClass = $declaringClass; $this->returnType = $returnType; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return \true; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getDocComment() : ?string { return null; } public function getName() : string { return 'cases'; } public function getPrototype() : ClassMemberReflection { $unitEnum = $this->declaringClass->getAncestorWithClassName('UnitEnum'); if ($unitEnum === null) { throw new ShouldNotHappenException(); } return $unitEnum->getNativeMethod('cases'); } public function getVariants() : array { return [new FunctionVariantWithPhpDocs(TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), [], \false, $this->returnType, new MixedType(), $this->returnType)]; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription() : ?string { return null; } public function isFinal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isFinalByKeyword() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getThrowType() : ?Type { return null; } public function hasSideEffects() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getAsserts() : Assertions { return Assertions::createEmpty(); } public function acceptsNamedArguments() : bool { return $this->declaringClass->acceptsNamedArguments(); } public function getSelfOutType() : ?Type { return null; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isAbstract() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isPure() : TrinaryLogic { return TrinaryLogic::createYes(); } } name = $name; } public function getName() : string { return $this->name; } public function getFileName() : ?string { return null; } public function getVariants() : array { $parameterType = new UnionType([new StringType(), new IntegerType()]); return [new FunctionVariantWithPhpDocs(TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), [new \PHPStan\Reflection\Php\DummyParameterWithPhpDocs('status', $parameterType, \true, PassedByReference::createNo(), \false, new ConstantIntegerType(0), $parameterType, new MixedType(), null, TrinaryLogic::createNo(), null)], \false, new NeverType(\true), new MixedType(), new NeverType(\true), TemplateTypeVarianceMap::createEmpty())]; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } /** * @return ParametersAcceptorWithPhpDocs[] */ public function getNamedArgumentsVariants() : array { return $this->getVariants(); } public function acceptsNamedArguments() : bool { return \true; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription() : ?string { return null; } public function isFinal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createYes(); } public function getThrowType() : ?Type { return null; } public function hasSideEffects() : TrinaryLogic { return TrinaryLogic::createYes(); } public function isBuiltin() : bool { return \true; } public function getAsserts() : Assertions { return Assertions::createEmpty(); } public function getDocComment() : ?string { return null; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isPure() : TrinaryLogic { return TrinaryLogic::createNo(); } } name = $name; $this->optional = $optional; $this->realType = $realType; $this->phpDocType = $phpDocType; $this->passedByReference = $passedByReference; $this->defaultValue = $defaultValue; $this->variadic = $variadic; $this->outType = $outType; $this->immediatelyInvokedCallable = $immediatelyInvokedCallable; $this->closureThisType = $closureThisType; } public function getName() : string { return $this->name; } public function isOptional() : bool { return $this->optional; } public function getType() : Type { if ($this->type === null) { $phpDocType = $this->phpDocType; if ($phpDocType !== null && $this->defaultValue !== null) { if ($this->defaultValue->isNull()->yes()) { $inferred = $phpDocType->inferTemplateTypes($this->defaultValue); if ($inferred->isEmpty()) { $phpDocType = TypeCombinator::addNull($phpDocType); } } } $this->type = TypehintHelper::decideType($this->realType, $phpDocType); } return $this->type; } public function getPhpDocType() : Type { return $this->phpDocType ?? new MixedType(); } public function getNativeType() : Type { return $this->realType; } public function passedByReference() : PassedByReference { return $this->passedByReference; } public function isVariadic() : bool { return $this->variadic; } public function getDefaultValue() : ?Type { return $this->defaultValue; } public function getOutType() : ?Type { return $this->outType; } public function isImmediatelyInvokedCallable() : TrinaryLogic { return $this->immediatelyInvokedCallable; } public function getClosureThisType() : ?Type { return $this->closureThisType; } } name = $name; $this->type = $type; $this->optional = $optional; $this->variadic = $variadic; $this->defaultValue = $defaultValue; $this->passedByReference = $passedByReference ?? PassedByReference::createNo(); } public function getName() : string { return $this->name; } public function isOptional() : bool { return $this->optional; } public function getType() : Type { return $this->type; } public function passedByReference() : PassedByReference { return $this->passedByReference; } public function isVariadic() : bool { return $this->variadic; } public function getDefaultValue() : ?Type { return $this->defaultValue; } } property = $property; } public function doNotResolveTemplateTypeMapToBounds() : UnresolvedPropertyPrototypeReflection { return $this; } public function getNakedProperty() : ExtendedPropertyReflection { return $this->property; } public function getTransformedProperty() : ExtendedPropertyReflection { return $this->property; } public function withFechedOnType(Type $type) : UnresolvedPropertyPrototypeReflection { return $this; } } nativeType = $nativeType; $this->phpDocType = $phpDocType; $this->outType = $outType; $this->immediatelyInvokedCallable = $immediatelyInvokedCallable; $this->closureThisType = $closureThisType; parent::__construct($name, $type, $optional, $passedByReference, $variadic, $defaultValue); } public function getPhpDocType() : Type { return $this->phpDocType; } public function getNativeType() : Type { return $this->nativeType; } public function getOutType() : ?Type { return $this->outType; } public function isImmediatelyInvokedCallable() : TrinaryLogic { return $this->immediatelyInvokedCallable; } public function getClosureThisType() : ?Type { return $this->closureThisType; } } reflectionProvider = $reflectionProvider; $this->classes = $classes; $this->annotationClassReflection = $annotationClassReflection; } public function hasProperty(ClassReflection $classReflection, string $propertyName) : bool { return self::isUniversalObjectCrate($this->reflectionProvider, $this->classes, $classReflection); } /** * @param string[] $classes */ public static function isUniversalObjectCrate(ReflectionProvider $reflectionProvider, array $classes, ClassReflection $classReflection) : bool { foreach ($classes as $className) { if (!$reflectionProvider->hasClass($className)) { continue; } if ($classReflection->getName() === $className || $classReflection->isSubclassOf($className)) { return \true; } } return \false; } public function getProperty(ClassReflection $classReflection, string $propertyName) : PropertyReflection { if ($this->annotationClassReflection->hasProperty($classReflection, $propertyName)) { return $this->annotationClassReflection->getProperty($classReflection, $propertyName); } if ($classReflection->hasNativeMethod('__get')) { $readableType = $classReflection->getNativeMethod('__get')->getOnlyVariant()->getReturnType(); } else { $readableType = new MixedType(); } if ($classReflection->hasNativeMethod('__set')) { $writableType = $classReflection->getNativeMethod('__set')->getOnlyVariant()->getParameters()[1]->getType(); } else { $writableType = new MixedType(); } return new \PHPStan\Reflection\Php\UniversalObjectCrateProperty($classReflection, $readableType, $writableType); } } */ private $phpDocParameterTypes; /** * @var ?Type */ private $phpDocReturnType; /** * @var ?Type */ private $phpDocThrowType; /** * @var ?string */ private $deprecatedDescription; /** * @var bool */ private $isDeprecated; /** * @var bool */ private $isInternal; /** * @var bool */ private $isFinal; /** * @var ?string */ private $filename; /** * @var ?bool */ private $isPure; /** * @var Assertions */ private $asserts; /** * @var bool */ private $acceptsNamedArguments; /** * @var ?string */ private $phpDocComment; /** * @var array */ private $phpDocParameterOutTypes; /** * @var array */ private $phpDocParameterImmediatelyInvokedCallable; /** * @var array */ private $phpDocParameterClosureThisTypes; /** @var FunctionVariantWithPhpDocs[]|null */ private $variants = null; /** * @param array $phpDocParameterTypes * @param array $phpDocParameterOutTypes * @param array $phpDocParameterImmediatelyInvokedCallable * @param array $phpDocParameterClosureThisTypes */ public function __construct(InitializerExprTypeResolver $initializerExprTypeResolver, ReflectionFunction $reflection, Parser $parser, FunctionCallStatementFinder $functionCallStatementFinder, Cache $cache, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $phpDocThrowType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?string $filename, ?bool $isPure, Assertions $asserts, bool $acceptsNamedArguments, ?string $phpDocComment, array $phpDocParameterOutTypes, array $phpDocParameterImmediatelyInvokedCallable, array $phpDocParameterClosureThisTypes) { $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflection = $reflection; $this->parser = $parser; $this->functionCallStatementFinder = $functionCallStatementFinder; $this->cache = $cache; $this->templateTypeMap = $templateTypeMap; $this->phpDocParameterTypes = $phpDocParameterTypes; $this->phpDocReturnType = $phpDocReturnType; $this->phpDocThrowType = $phpDocThrowType; $this->deprecatedDescription = $deprecatedDescription; $this->isDeprecated = $isDeprecated; $this->isInternal = $isInternal; $this->isFinal = $isFinal; $this->filename = $filename; $this->isPure = $isPure; $this->asserts = $asserts; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->phpDocComment = $phpDocComment; $this->phpDocParameterOutTypes = $phpDocParameterOutTypes; $this->phpDocParameterImmediatelyInvokedCallable = $phpDocParameterImmediatelyInvokedCallable; $this->phpDocParameterClosureThisTypes = $phpDocParameterClosureThisTypes; } public function getName() : string { return $this->reflection->getName(); } public function getFileName() : ?string { if ($this->filename === null) { return null; } if (!is_file($this->filename)) { return null; } return $this->filename; } /** * @return ParametersAcceptorWithPhpDocs[] */ public function getVariants() : array { if ($this->variants === null) { $this->variants = [new FunctionVariantWithPhpDocs($this->templateTypeMap, null, $this->getParameters(), $this->isVariadic(), $this->getReturnType(), $this->getPhpDocReturnType(), $this->getNativeReturnType())]; } return $this->variants; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { return $this->getVariants()[0]; } public function getNamedArgumentsVariants() : ?array { return null; } /** * @return ParameterReflectionWithPhpDocs[] */ private function getParameters() : array { return array_map(function (ReflectionParameter $reflection) : \PHPStan\Reflection\Php\PhpParameterReflection { if (array_key_exists($reflection->getName(), $this->phpDocParameterImmediatelyInvokedCallable)) { $immediatelyInvokedCallable = TrinaryLogic::createFromBoolean($this->phpDocParameterImmediatelyInvokedCallable[$reflection->getName()]); } else { $immediatelyInvokedCallable = TrinaryLogic::createMaybe(); } return new \PHPStan\Reflection\Php\PhpParameterReflection($this->initializerExprTypeResolver, $reflection, $this->phpDocParameterTypes[$reflection->getName()] ?? null, null, $this->phpDocParameterOutTypes[$reflection->getName()] ?? null, $immediatelyInvokedCallable, $this->phpDocParameterClosureThisTypes[$reflection->getName()] ?? null); }, $this->reflection->getParameters()); } private function isVariadic() : bool { $isNativelyVariadic = $this->reflection->isVariadic(); if (!$isNativelyVariadic && $this->reflection->getFileName() !== \false) { $fileName = $this->reflection->getFileName(); if (is_file($fileName)) { $functionName = $this->reflection->getName(); $modifiedTime = filemtime($fileName); if ($modifiedTime === \false) { $modifiedTime = time(); } $variableCacheKey = sprintf('%d-v4', $modifiedTime); $key = sprintf('variadic-function-%s-%s', $functionName, $fileName); $cachedResult = $this->cache->load($key, $variableCacheKey); if ($cachedResult === null) { $nodes = $this->parser->parseFile($fileName); $result = !$this->containsVariadicFunction($nodes)->no(); $this->cache->save($key, $variableCacheKey, $result); return $result; } return $cachedResult; } } return $isNativelyVariadic; } /** * @param Node[]|scalar[]|Node $node */ private function containsVariadicFunction($node) : TrinaryLogic { $result = TrinaryLogic::createMaybe(); if ($node instanceof Node) { if ($node instanceof Function_) { $functionName = (string) $node->namespacedName; if ($functionName === $this->reflection->getName()) { return TrinaryLogic::createFromBoolean($this->isFunctionNodeVariadic($node)); } } foreach ($node->getSubNodeNames() as $subNodeName) { $innerNode = $node->{$subNodeName}; if (!$innerNode instanceof Node && !is_array($innerNode)) { continue; } $result = $result->and($this->containsVariadicFunction($innerNode)); } } elseif (is_array($node)) { foreach ($node as $subNode) { if (!$subNode instanceof Node) { continue; } $result = $result->and($this->containsVariadicFunction($subNode)); } } return $result; } private function getReturnType() : Type { return TypehintHelper::decideTypeFromReflection($this->reflection->getReturnType(), $this->phpDocReturnType); } private function getPhpDocReturnType() : Type { if ($this->phpDocReturnType !== null) { return $this->phpDocReturnType; } return new MixedType(); } private function getNativeReturnType() : Type { return TypehintHelper::decideTypeFromReflection($this->reflection->getReturnType()); } public function getDeprecatedDescription() : ?string { if ($this->isDeprecated) { return $this->deprecatedDescription; } return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isDeprecated || $this->reflection->isDeprecated()); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isInternal); } public function isFinal() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isFinal); } public function getThrowType() : ?Type { return $this->phpDocThrowType; } public function hasSideEffects() : TrinaryLogic { if ($this->getReturnType()->isVoid()->yes()) { return TrinaryLogic::createYes(); } if ($this->isPure !== null) { return TrinaryLogic::createFromBoolean(!$this->isPure); } return TrinaryLogic::createMaybe(); } public function isPure() : TrinaryLogic { if ($this->isPure === null) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createFromBoolean($this->isPure); } public function isBuiltin() : bool { return $this->reflection->isInternal(); } public function getAsserts() : Assertions { return $this->asserts; } public function getDocComment() : ?string { return $this->phpDocComment; } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->returnsReference()); } public function acceptsNamedArguments() : bool { return $this->acceptsNamedArguments; } private function isFunctionNodeVariadic(Function_ $node) : bool { foreach ($node->params as $parameter) { if ($parameter->variadic) { return \true; } } if ($this->functionCallStatementFinder->findFunctionCallInStatements(ParametersAcceptor::VARIADIC_FUNCTIONS, $node->getStmts()) !== null) { return \true; } return \false; } } declaringClass = $declaringClass; $this->declaringTrait = $declaringTrait; $this->nativeType = $nativeType; $this->phpDocType = $phpDocType; $this->reflection = $reflection; $this->deprecatedDescription = $deprecatedDescription; $this->isDeprecated = $isDeprecated; $this->isInternal = $isInternal; $this->isReadOnlyByPhpDoc = $isReadOnlyByPhpDoc; $this->isAllowedPrivateMutation = $isAllowedPrivateMutation; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function getDeclaringTrait() : ?ClassReflection { return $this->declaringTrait; } public function getDocComment() : ?string { $docComment = $this->reflection->getDocComment(); if ($docComment === \false) { return null; } return $docComment; } public function isStatic() : bool { return $this->reflection->isStatic(); } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } public function isReadOnly() : bool { return $this->reflection->isReadOnly(); } public function isReadOnlyByPhpDoc() : bool { return $this->isReadOnlyByPhpDoc; } public function getReadableType() : Type { if ($this->type === null) { $this->type = TypehintHelper::decideTypeFromReflection($this->nativeType, $this->phpDocType, $this->declaringClass); } return $this->type; } public function getWritableType() : Type { return $this->getReadableType(); } public function canChangeTypeAfterAssignment() : bool { return \true; } public function isPromoted() : bool { return $this->reflection->isPromoted(); } public function hasPhpDocType() : bool { return $this->phpDocType !== null; } public function getPhpDocType() : Type { if ($this->phpDocType !== null) { return $this->phpDocType; } return new MixedType(); } public function hasNativeType() : bool { return $this->nativeType !== null; } public function getNativeType() : Type { if ($this->finalNativeType === null) { $this->finalNativeType = TypehintHelper::decideTypeFromReflection($this->nativeType, null, $this->declaringClass); } return $this->finalNativeType; } public function isReadable() : bool { return \true; } public function isWritable() : bool { return \true; } public function getDeprecatedDescription() : ?string { if ($this->isDeprecated) { return $this->deprecatedDescription; } return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isDeprecated); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isInternal); } public function isAllowedPrivateMutation() : bool { return $this->isAllowedPrivateMutation; } public function getNativeReflection() : ReflectionProperty { return $this->reflection; } } reflection = $reflection; } public function getName() : string { return $this->reflection->getName(); } public function getReflection() : ReflectionMethod { return $this->reflection; } public function getFileName() : ?string { $fileName = $this->reflection->getFileName(); if ($fileName === \false) { return null; } return $fileName; } public function getDeclaringClass() : ReflectionClass { return $this->reflection->getDeclaringClass(); } public function getStartLine() : ?int { $line = $this->reflection->getStartLine(); if ($line === \false) { return null; } return $line; } public function getEndLine() : ?int { $line = $this->reflection->getEndLine(); if ($line === \false) { return null; } return $line; } public function getDocComment() : ?string { $docComment = $this->reflection->getDocComment(); if ($docComment === \false) { return null; } return $docComment; } public function isStatic() : bool { return $this->reflection->isStatic(); } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } public function isConstructor() : bool { return $this->reflection->isConstructor(); } public function getPrototype() : \PHPStan\Reflection\Php\BuiltinMethodReflection { return new self($this->reflection->getPrototype()); } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->isDeprecated()); } public function isFinal() : bool { return $this->reflection->isFinal(); } public function isInternal() : bool { return $this->reflection->isInternal(); } public function isAbstract() : bool { return $this->reflection->isAbstract(); } public function isVariadic() : bool { return $this->reflection->isVariadic(); } /** * @return ReflectionIntersectionType|ReflectionNamedType|ReflectionUnionType|null */ public function getReturnType() { return $this->reflection->getReturnType(); } /** * @return ReflectionIntersectionType|ReflectionNamedType|ReflectionUnionType|null */ public function getTentativeReturnType() { return $this->reflection->getTentativeReturnType(); } /** * @return ReflectionParameter[] */ public function getParameters() : array { return $this->reflection->getParameters(); } public function returnsByReference() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->returnsReference()); } } isEnum(); } public function getAllowedSubTypes(ClassReflection $classReflection) : array { $cases = []; foreach (array_keys($classReflection->getEnumCases()) as $name) { $cases[] = new EnumCaseObjectType($classReflection->getName(), $name); } return $cases; } } prototype = $prototype; $this->closure = $closure; } public function doNotResolveTemplateTypeMapToBounds() : UnresolvedMethodPrototypeReflection { return new self($this->prototype->doNotResolveTemplateTypeMapToBounds(), $this->closure); } public function getNakedMethod() : ExtendedMethodReflection { return $this->getTransformedMethod(); } public function getTransformedMethod() : ExtendedMethodReflection { return new \PHPStan\Reflection\Php\ClosureCallMethodReflection($this->prototype->getTransformedMethod(), $this->closure); } public function withCalledOnType(Type $type) : UnresolvedMethodPrototypeReflection { return new self($this->prototype->withCalledOnType($type), $this->closure); } } declaringClass = $declaringClass; $this->type = $type; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return \false; } public function isPrivate() : bool { return \false; } public function isPublic() : bool { return \true; } public function getDocComment() : ?string { return null; } public function getReadableType() : Type { return $this->type; } public function getWritableType() : Type { return $this->type; } public function canChangeTypeAfterAssignment() : bool { return \true; } public function isReadable() : bool { return \true; } public function isWritable() : bool { return \false; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createNo(); } public function getDeprecatedDescription() : ?string { return null; } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } } file = $file; $this->namespace = $namespace; $this->className = $className; $this->traitName = $traitName; $this->function = $function; $this->method = $method; } public static function fromScope(Scope $scope) : self { return new self($scope->getFile(), $scope->getNamespace(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $scope->isInAnonymousFunction() ? '{closure}' : ($scope->getFunction() !== null ? $scope->getFunction()->getName() : null), $scope->isInAnonymousFunction() ? '{closure}' : ($scope->getFunction() instanceof \PHPStan\Reflection\MethodReflection ? sprintf('%s::%s', $scope->getFunction()->getDeclaringClass()->getName(), $scope->getFunction()->getName()) : ($scope->getFunction() instanceof \PHPStan\Reflection\FunctionReflection ? $scope->getFunction()->getName() : null))); } /** * @return non-empty-string|null */ private static function parseNamespace(string $name) : ?string { $parts = explode('\\', $name); if (count($parts) > 1) { $ns = implode('\\', array_slice($parts, 0, -1)); if ($ns === '') { throw new ShouldNotHappenException('Namespace cannot be empty.'); } return $ns; } return null; } public static function fromClassReflection(\PHPStan\Reflection\ClassReflection $classReflection) : self { return self::fromClass($classReflection->getName(), $classReflection->getFileName()); } public static function fromClass(string $className, ?string $fileName) : self { return new self($fileName, self::parseNamespace($className), $className, null, null, null); } public static function fromReflectionParameter(ReflectionParameter $parameter) : self { $declaringFunction = $parameter->getDeclaringFunction(); if ($declaringFunction instanceof ReflectionFunction) { $file = $declaringFunction->getFileName(); return new self($file === \false ? null : $file, self::parseNamespace($declaringFunction->getName()), null, null, $declaringFunction->getName(), $declaringFunction->getName()); } $file = $declaringFunction->getFileName(); $betterReflection = $declaringFunction->getBetterReflection(); return new self($file === \false ? null : $file, self::parseNamespace($betterReflection->getDeclaringClass()->getName()), $declaringFunction->getDeclaringClass()->getName(), $betterReflection->getDeclaringClass()->isTrait() ? $betterReflection->getDeclaringClass()->getName() : null, $declaringFunction->getName(), sprintf('%s::%s', $declaringFunction->getDeclaringClass()->getName(), $declaringFunction->getName())); } /** * @param ClassMethod|Function_ $function */ public static function fromStubParameter(?string $className, string $stubFile, $function) : self { $namespace = null; if ($className !== null) { $namespace = self::parseNamespace($className); } else { if ($function instanceof Function_ && $function->namespacedName !== null) { $namespace = self::parseNamespace($function->namespacedName->toString()); } } return new self($stubFile, $namespace, $className, null, $function instanceof Function_ && $function->namespacedName !== null ? $function->namespacedName->toString() : ($function instanceof ClassMethod ? $function->name->toString() : null), $function instanceof ClassMethod && $className !== null ? sprintf('%s::%s', $className, $function->name->toString()) : ($function instanceof Function_ && $function->namespacedName !== null ? $function->namespacedName->toString() : null)); } public static function fromGlobalConstant(ReflectionConstant $constant) : self { return new self($constant->getFileName(), $constant->getNamespaceName(), null, null, null, null); } public static function createEmpty() : self { return new self(null, null, null, null, null, null); } public function getFile() : ?string { return $this->file; } public function getClassName() : ?string { return $this->className; } public function getNamespace() : ?string { return $this->namespace; } public function getTraitName() : ?string { return $this->traitName; } public function getFunction() : ?string { return $this->function; } public function getMethod() : ?string { return $this->method; } } $phpDocParameterTypes * @param array $phpDocParameterOutTypes * @param array $phpDocParameterImmediatelyInvokedCallable * @param array $phpDocParameterClosureThisTypes */ public function create(ReflectionFunction $reflection, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $phpDocThrowType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?string $filename, ?bool $isPure, \PHPStan\Reflection\Assertions $asserts, bool $acceptsNamedArguments, ?string $phpDocComment, array $phpDocParameterOutTypes, array $phpDocParameterImmediatelyInvokedCallable, array $phpDocParameterClosureThisTypes) : PhpFunctionReflection; } name = $name; $this->declaringClass = $declaringClass; $this->isStatic = $isStatic; $this->isPrivate = $isPrivate; $this->isPublic = $isPublic; $this->isAbstract = $isAbstract; $this->isFinal = $isFinal; $this->isInternal = $isInternal; $this->variants = $variants; $this->tentativeReturnType = $tentativeReturnType; } public function getName() : string { return $this->name; } public function getDeclaringClass() : \PHPStan\Reflection\ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return $this->isStatic; } public function isPrivate() : bool { return $this->isPrivate; } public function isPublic() : bool { return $this->isPublic; } public function isAbstract() : bool { return $this->isAbstract; } public function isFinal() : bool { return $this->isFinal; } public function isInternal() : bool { return $this->isInternal; } public function getDocComment() : ?string { return null; } /** * @return ParametersAcceptor[] */ public function getVariants() : array { return $this->variants; } public function getTentativeReturnType() : ?Type { return $this->tentativeReturnType; } } staticReflectionProvider = $staticReflectionProvider; } public function create() : ReflectionProvider { return new \PHPStan\Reflection\ReflectionProvider\MemoizingReflectionProvider($this->staticReflectionProvider); } } reflectionProvider = $reflectionProvider; } public function getReflectionProvider() : ReflectionProvider { return $this->reflectionProvider; } } */ private $hasClasses = []; /** @var array */ private $classes = []; /** @var array */ private $classNames = []; public function __construct(ReflectionProvider $provider) { $this->provider = $provider; } public function hasClass(string $className) : bool { if (isset($this->hasClasses[$className])) { return $this->hasClasses[$className]; } return $this->hasClasses[$className] = $this->provider->hasClass($className); } public function getClass(string $className) : ClassReflection { $lowerClassName = strtolower($className); if (isset($this->classes[$lowerClassName])) { return $this->classes[$lowerClassName]; } return $this->classes[$lowerClassName] = $this->provider->getClass($className); } public function getClassName(string $className) : string { $lowerClassName = strtolower($className); if (isset($this->classNames[$lowerClassName])) { return $this->classNames[$lowerClassName]; } return $this->classNames[$lowerClassName] = $this->provider->getClassName($className); } public function supportsAnonymousClasses() : bool { return $this->provider->supportsAnonymousClasses(); } public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $scope) : ClassReflection { return $this->provider->getAnonymousClassReflection($classNode, $scope); } public function hasFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : bool { return $this->provider->hasFunction($nameNode, $namespaceAnswerer); } public function getFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : FunctionReflection { return $this->provider->getFunction($nameNode, $namespaceAnswerer); } public function resolveFunctionName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : ?string { return $this->provider->resolveFunctionName($nameNode, $namespaceAnswerer); } public function hasConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : bool { return $this->provider->hasConstant($nameNode, $namespaceAnswerer); } public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : GlobalConstantReflection { return $this->provider->getConstant($nameNode, $namespaceAnswerer); } public function resolveConstantName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer) : ?string { return $this->provider->resolveConstantName($nameNode, $namespaceAnswerer); } } container = $container; } public function getReflectionProvider() : ReflectionProvider { return $this->container->getByType(ReflectionProvider::class); } } reflectionProvider = $reflectionProvider; } public function getReflectionProvider() : ReflectionProvider { return $this->reflectionProvider; } } name = $name; $this->optional = $optional; $this->type = $type; $this->phpDocType = $phpDocType; $this->nativeType = $nativeType; $this->passedByReference = $passedByReference; $this->variadic = $variadic; $this->defaultValue = $defaultValue; $this->outType = $outType; $this->immediatelyInvokedCallable = $immediatelyInvokedCallable; $this->closureThisType = $closureThisType; } public function getName() : string { return $this->name; } public function isOptional() : bool { return $this->optional; } public function getType() : Type { return $this->type; } public function getPhpDocType() : Type { return $this->phpDocType; } public function getNativeType() : Type { return $this->nativeType; } public function passedByReference() : PassedByReference { return $this->passedByReference; } public function isVariadic() : bool { return $this->variadic; } public function getDefaultValue() : ?Type { return $this->defaultValue; } public function getOutType() : ?Type { return $this->outType; } public function isImmediatelyInvokedCallable() : TrinaryLogic { return $this->immediatelyInvokedCallable; } public function getClosureThisType() : ?Type { return $this->closureThisType; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self($properties['name'], $properties['optional'], $properties['type'], $properties['phpDocType'], $properties['nativeType'], $properties['passedByReference'], $properties['variadic'], $properties['defaultValue'], $properties['outType'], $properties['immediatelyInvokedCallable'], $properties['closureThisType']); } } name = $name; $this->variants = $variants; $this->namedArgumentsVariants = $namedArgumentsVariants; $this->throwType = $throwType; $this->hasSideEffects = $hasSideEffects; $this->isDeprecated = $isDeprecated; $this->phpDocComment = $phpDocComment; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->assertions = $assertions ?? Assertions::createEmpty(); $this->returnsByReference = $returnsByReference ?? TrinaryLogic::createMaybe(); } public function getName() : string { return $this->name; } public function getFileName() : ?string { return null; } public function getVariants() : array { return $this->variants; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { $variants = $this->getVariants(); if (count($variants) !== 1) { throw new ShouldNotHappenException(); } return $variants[0]; } public function getNamedArgumentsVariants() : ?array { return $this->namedArgumentsVariants; } public function getThrowType() : ?Type { return $this->throwType; } public function getDeprecatedDescription() : ?string { return null; } public function isDeprecated() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->isDeprecated); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function isFinal() : TrinaryLogic { return TrinaryLogic::createNo(); } public function hasSideEffects() : TrinaryLogic { if ($this->isVoid()) { return TrinaryLogic::createYes(); } return $this->hasSideEffects; } public function isPure() : TrinaryLogic { if ($this->hasSideEffects()->yes()) { return TrinaryLogic::createNo(); } return $this->hasSideEffects->negate(); } private function isVoid() : bool { foreach ($this->variants as $variant) { if (!$variant->getReturnType()->isVoid()->yes()) { return \false; } } return \true; } public function isBuiltin() : bool { return \true; } public function getAsserts() : Assertions { return $this->assertions; } public function getDocComment() : ?string { return $this->phpDocComment; } public function returnsByReference() : TrinaryLogic { return $this->returnsByReference; } public function acceptsNamedArguments() : bool { return $this->acceptsNamedArguments; } } name = $name; $this->optional = $optional; $this->type = $type; $this->passedByReference = $passedByReference; $this->variadic = $variadic; $this->defaultValue = $defaultValue; } public function getName() : string { return $this->name; } public function isOptional() : bool { return $this->optional; } public function getType() : Type { return $this->type; } public function passedByReference() : PassedByReference { return $this->passedByReference; } public function isVariadic() : bool { return $this->variadic; } public function getDefaultValue() : ?Type { return $this->defaultValue; } public function union(self $other) : self { return new self($this->name, $this->optional && $other->optional, TypeCombinator::union($this->type, $other->type), $this->passedByReference->combine($other->passedByReference), $this->variadic && $other->variadic, $this->optional && $other->optional ? $this->defaultValue : null); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self($properties['name'], $properties['optional'], $properties['type'], $properties['passedByReference'], $properties['variadic'], $properties['defaultValue']); } } reflectionProvider = $reflectionProvider; $this->declaringClass = $declaringClass; $this->reflection = $reflection; $this->variants = $variants; $this->namedArgumentsVariants = $namedArgumentsVariants; $this->hasSideEffects = $hasSideEffects; $this->throwType = $throwType; $this->assertions = $assertions; $this->acceptsNamedArguments = $acceptsNamedArguments; $this->selfOutType = $selfOutType; $this->phpDocComment = $phpDocComment; } public function getDeclaringClass() : ClassReflection { return $this->declaringClass; } public function isStatic() : bool { return $this->reflection->isStatic(); } public function isPrivate() : bool { return $this->reflection->isPrivate(); } public function isPublic() : bool { return $this->reflection->isPublic(); } public function isAbstract() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->isAbstract()); } public function getPrototype() : ClassMemberReflection { try { $prototypeMethod = $this->reflection->getPrototype(); $prototypeDeclaringClass = $this->declaringClass->getAncestorWithClassName($prototypeMethod->getDeclaringClass()->getName()); if ($prototypeDeclaringClass === null) { $prototypeDeclaringClass = $this->reflectionProvider->getClass($prototypeMethod->getDeclaringClass()->getName()); } if (!$prototypeDeclaringClass->hasNativeMethod($prototypeMethod->getName())) { return $this; } $tentativeReturnType = null; if ($prototypeMethod->getTentativeReturnType() !== null) { $tentativeReturnType = TypehintHelper::decideTypeFromReflection($prototypeMethod->getTentativeReturnType()); } return new MethodPrototypeReflection($prototypeMethod->getName(), $prototypeDeclaringClass, $prototypeMethod->isStatic(), $prototypeMethod->isPrivate(), $prototypeMethod->isPublic(), $prototypeMethod->isAbstract(), $prototypeMethod->isFinal(), $prototypeMethod->isInternal(), $prototypeDeclaringClass->getNativeMethod($prototypeMethod->getName())->getVariants(), $tentativeReturnType); } catch (ReflectionException $e) { return $this; } } public function getName() : string { return $this->reflection->getName(); } public function getVariants() : array { return $this->variants; } public function getOnlyVariant() : ParametersAcceptorWithPhpDocs { $variants = $this->getVariants(); if (count($variants) !== 1) { throw new ShouldNotHappenException(); } return $variants[0]; } public function getNamedArgumentsVariants() : ?array { return $this->namedArgumentsVariants; } public function getDeprecatedDescription() : ?string { return null; } public function isDeprecated() : TrinaryLogic { return $this->reflection->isDeprecated(); } public function isInternal() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->isInternal()); } public function isFinal() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->reflection->isFinal()); } public function isFinalByKeyword() : TrinaryLogic { return $this->isFinal(); } public function getThrowType() : ?Type { return $this->throwType; } public function hasSideEffects() : TrinaryLogic { $name = strtolower($this->getName()); $isVoid = $this->isVoid(); if ($name !== '__construct' && $isVoid) { return TrinaryLogic::createYes(); } return $this->hasSideEffects; } public function isPure() : TrinaryLogic { if ($this->hasSideEffects()->yes()) { return TrinaryLogic::createNo(); } return $this->hasSideEffects->negate(); } private function isVoid() : bool { foreach ($this->variants as $variant) { if (!$variant->getReturnType()->isVoid()->yes()) { return \false; } } return \true; } public function getDocComment() : ?string { return $this->phpDocComment; } public function getAsserts() : Assertions { return $this->assertions; } public function acceptsNamedArguments() : bool { return $this->declaringClass->acceptsNamedArguments() && $this->acceptsNamedArguments; } public function getSelfOutType() : ?Type { return $this->selfOutType; } public function returnsByReference() : TrinaryLogic { return $this->reflection->returnsByReference(); } } identifier = $identifier; $this->description = $description; $this->certain = $certain; } /** * @param FunctionReflection|ExtendedMethodReflection $function */ public static function createFromVariant($function, ?ParametersAcceptor $variant) : ?self { if (!$function->hasSideEffects()->no()) { $certain = $function->isPure()->no(); if ($variant !== null) { $certain = $certain || $variant->getReturnType()->isVoid()->yes(); } if ($function instanceof FunctionReflection) { return new \PHPStan\Reflection\Callables\SimpleImpurePoint('functionCall', sprintf('call to function %s()', $function->getName()), $certain); } return new \PHPStan\Reflection\Callables\SimpleImpurePoint('methodCall', sprintf('call to method %s::%s()', $function->getDeclaringClass()->getDisplayName(), $function->getName()), $certain); } return null; } /** * @return ImpurePointIdentifier */ public function getIdentifier() : string { return $this->identifier; } public function getDescription() : string { return $this->description; } public function isCertain() : bool { return $this->certain; } } type = $type; $this->explicit = $explicit; $this->canContainAnyThrowable = $canContainAnyThrowable; } public static function createExplicit(Type $type, bool $canContainAnyThrowable) : self { return new self($type, \true, $canContainAnyThrowable); } public static function createImplicit() : self { return new self(new ObjectType(Throwable::class), \false, \true); } public function getType() : Type { return $this->type; } public function isExplicit() : bool { return $this->explicit; } public function canContainAnyThrowable() : bool { return $this->canContainAnyThrowable; } } function = $function; $this->variant = $variant; } /** * @param ParametersAcceptorWithPhpDocs[] $variants * @return self[] * @param FunctionReflection|ExtendedMethodReflection $function */ public static function createFromVariants($function, array $variants) : array { return array_map(static function (ParametersAcceptorWithPhpDocs $variant) use($function) { return new self($function, $variant); }, $variants); } public function getTemplateTypeMap() : TemplateTypeMap { return $this->variant->getTemplateTypeMap(); } public function getResolvedTemplateTypeMap() : TemplateTypeMap { return $this->variant->getResolvedTemplateTypeMap(); } /** * @return array */ public function getParameters() : array { return $this->variant->getParameters(); } public function isVariadic() : bool { return $this->variant->isVariadic(); } public function getReturnType() : Type { return $this->variant->getReturnType(); } public function getPhpDocReturnType() : Type { return $this->variant->getPhpDocReturnType(); } public function getNativeReturnType() : Type { return $this->variant->getNativeReturnType(); } public function getCallSiteVarianceMap() : TemplateTypeVarianceMap { return $this->variant->getCallSiteVarianceMap(); } public function getThrowPoints() : array { if ($this->throwPoints !== null) { return $this->throwPoints; } if ($this->variant instanceof \PHPStan\Reflection\Callables\CallableParametersAcceptor) { return $this->throwPoints = $this->variant->getThrowPoints(); } $returnType = $this->variant->getReturnType(); $throwType = $this->function->getThrowType(); if ($throwType === null) { if ($returnType instanceof NeverType && $returnType->isExplicit()) { $throwType = new ObjectType(Throwable::class); } } $throwPoints = []; if ($throwType !== null) { if (!$throwType->isVoid()->yes()) { $throwPoints[] = \PHPStan\Reflection\Callables\SimpleThrowPoint::createExplicit($throwType, \true); } } else { if (!(new ObjectType(Throwable::class))->isSuperTypeOf($returnType)->yes()) { $throwPoints[] = \PHPStan\Reflection\Callables\SimpleThrowPoint::createImplicit(); } } return $this->throwPoints = $throwPoints; } public function isPure() : TrinaryLogic { $impurePoints = $this->getImpurePoints(); if (count($impurePoints) === 0) { return TrinaryLogic::createYes(); } $certainCount = 0; foreach ($impurePoints as $impurePoint) { if (!$impurePoint->isCertain()) { continue; } $certainCount++; } return $certainCount > 0 ? TrinaryLogic::createNo() : TrinaryLogic::createMaybe(); } public function getImpurePoints() : array { if ($this->impurePoints !== null) { return $this->impurePoints; } if ($this->variant instanceof \PHPStan\Reflection\Callables\CallableParametersAcceptor) { return $this->impurePoints = $this->variant->getImpurePoints(); } $impurePoint = \PHPStan\Reflection\Callables\SimpleImpurePoint::createFromVariant($this->function, $this->variant); if ($impurePoint === null) { return $this->impurePoints = []; } return $this->impurePoints = [$impurePoint]; } public function getInvalidateExpressions() : array { return []; } public function getUsedVariables() : array { return []; } public function acceptsNamedArguments() : bool { return $this->function->acceptsNamedArguments(); } } asserts = $asserts; } /** * @return AssertTag[] */ public function getAll() : array { return $this->asserts; } /** * @return AssertTag[] */ public function getAsserts() : array { return array_filter($this->asserts, static function (AssertTag $assert) { return $assert->getIf() === AssertTag::NULL; }); } /** * @return AssertTag[] */ public function getAssertsIfTrue() : array { return array_merge(array_filter($this->asserts, static function (AssertTag $assert) { return $assert->getIf() === AssertTag::IF_TRUE; }), array_map(static function (AssertTag $assert) { return $assert->negate(); }, array_filter($this->asserts, static function (AssertTag $assert) { return $assert->getIf() === AssertTag::IF_FALSE && !$assert->isEquality(); }))); } /** * @return AssertTag[] */ public function getAssertsIfFalse() : array { return array_merge(array_filter($this->asserts, static function (AssertTag $assert) { return $assert->getIf() === AssertTag::IF_FALSE; }), array_map(static function (AssertTag $assert) { return $assert->negate(); }, array_filter($this->asserts, static function (AssertTag $assert) { return $assert->getIf() === AssertTag::IF_TRUE && !$assert->isEquality(); }))); } /** * @param callable(Type): Type $callable */ public function mapTypes(callable $callable) : self { $assertTagsCallback = static function (AssertTag $tag) use($callable) : AssertTag { return $tag->withType($callable($tag->getType())); }; return new self(array_map($assertTagsCallback, $this->asserts)); } public function intersectWith(\PHPStan\Reflection\Assertions $other) : self { return new self(array_merge($this->getAll(), $other->getAll())); } public static function createEmpty() : self { $empty = self::$empty; if ($empty !== null) { return $empty; } $empty = new self([]); self::$empty = $empty; return $empty; } public static function createFromResolvedPhpDocBlock(ResolvedPhpDocBlock $phpDocBlock) : self { $tags = $phpDocBlock->getAssertTags(); if (count($tags) === 0) { return self::createEmpty(); } return new self($tags); } } findMethod($classReflection, $methodName) !== null; } /** * @return ExtendedMethodReflection */ public function getMethod(ClassReflection $classReflection, string $methodName) : MethodReflection { $method = $this->findMethod($classReflection, $methodName); if ($method === null) { throw new ShouldNotHappenException(); } return $method; } /** * @return ExtendedMethodReflection|null */ private function findMethod(ClassReflection $classReflection, string $methodName) : ?MethodReflection { if (!$classReflection->isInterface()) { return null; } $extendsTags = $classReflection->getRequireExtendsTags(); foreach ($extendsTags as $extendsTag) { $type = $extendsTag->getType(); if (!$type->hasMethod($methodName)->yes()) { continue; } return $type->getMethod($methodName, new OutOfClassScope()); } $interfaces = $classReflection->getInterfaces(); foreach ($interfaces as $interface) { $method = $this->findMethod($interface, $methodName); if ($method !== null) { return $method; } } return null; } } findProperty($classReflection, $propertyName) !== null; } /** * @return ExtendedPropertyReflection */ public function getProperty(ClassReflection $classReflection, string $propertyName) : PropertyReflection { $property = $this->findProperty($classReflection, $propertyName); if ($property === null) { throw new ShouldNotHappenException(); } return $property; } private function findProperty(ClassReflection $classReflection, string $propertyName) : ?ExtendedPropertyReflection { if (!$classReflection->isInterface()) { return null; } $requireExtendsTags = $classReflection->getRequireExtendsTags(); foreach ($requireExtendsTags as $requireExtendsTag) { $type = $requireExtendsTag->getType(); if (!$type->hasProperty($propertyName)->yes()) { continue; } return $type->getProperty($propertyName, new OutOfClassScope()); } $interfaces = $classReflection->getInterfaces(); foreach ($interfaces as $interface) { $property = $this->findProperty($interface, $propertyName); if ($property !== null) { return $property; } } return null; } } $parameters */ public function __construct(TemplateTypeMap $templateTypeMap, ?TemplateTypeMap $resolvedTemplateTypeMap, array $parameters, bool $isVariadic, Type $returnType, Type $phpDocReturnType, Type $nativeReturnType, ?TemplateTypeVarianceMap $callSiteVarianceMap = null) { $this->phpDocReturnType = $phpDocReturnType; $this->nativeReturnType = $nativeReturnType; parent::__construct($templateTypeMap, $resolvedTemplateTypeMap, $parameters, $isVariadic, $returnType, $callSiteVarianceMap); } /** * @return array */ public function getParameters() : array { /** @var array $parameters */ $parameters = parent::getParameters(); return $parameters; } public function getPhpDocReturnType() : Type { return $this->phpDocReturnType; } public function getNativeReturnType() : Type { return $this->nativeReturnType; } } */ function autoloadFunctions() : array { return $GLOBALS['__phpstanAutoloadFunctions'] ?? []; } phpVersion = $phpVersion; $this->fileHelper = $fileHelper; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; $this->allConfigFiles = $allConfigFiles; } public function print(Output $output) : void { $phpRuntimeVersion = new PhpVersion(PHP_VERSION_ID); $output->writeLineFormatted(sprintf('PHP runtime version: %s', $phpRuntimeVersion->getVersionString())); $output->writeLineFormatted(sprintf('PHP version for analysis: %s (from %s)', $this->phpVersion->getVersionString(), $this->phpVersion->getSourceLabel())); $output->writeLineFormatted(''); $output->writeLineFormatted(sprintf('PHPStan version: %s', ComposerHelper::getPhpStanVersion())); $output->writeLineFormatted('PHPStan running from:'); $pharRunning = Phar::running(\false); if ($pharRunning !== '') { $output->writeLineFormatted(dirname($pharRunning)); } else { if (isset($_SERVER['argv'][0]) && is_file($_SERVER['argv'][0])) { $output->writeLineFormatted($_SERVER['argv'][0]); } else { $output->writeLineFormatted('Unknown'); } } $output->writeLineFormatted(''); $configFilesFromExtensionInstaller = []; if (class_exists('PHPStan\\ExtensionInstaller\\GeneratedConfig')) { $output->writeLineFormatted('Extension installer:'); if (count(GeneratedConfig::EXTENSIONS) === 0) { $output->writeLineFormatted('No extensions installed'); } $generatedConfigReflection = new ReflectionClass('PHPStan\\ExtensionInstaller\\GeneratedConfig'); $generatedConfigDirectory = dirname($generatedConfigReflection->getFileName()); foreach (GeneratedConfig::EXTENSIONS as $name => $extensionConfig) { $output->writeLineFormatted(sprintf('%s: %s', $name, $extensionConfig['version'] ?? 'Unknown version')); foreach ($extensionConfig['extra']['includes'] ?? [] as $includedFile) { $includedFilePath = null; if (isset($extensionConfig['relative_install_path'])) { $includedFilePath = sprintf('%s/%s/%s', $generatedConfigDirectory, $extensionConfig['relative_install_path'], $includedFile); if (!is_file($includedFilePath) || !is_readable($includedFilePath)) { $includedFilePath = null; } } if ($includedFilePath === null) { $includedFilePath = sprintf('%s/%s', $extensionConfig['install_path'], $includedFile); } $configFilesFromExtensionInstaller[] = $this->fileHelper->normalizePath($includedFilePath, '/'); } } } else { $output->writeLineFormatted('Extension installer: Not installed'); } $output->writeLineFormatted(''); $thirdPartyIncludedConfigs = []; foreach ($this->allConfigFiles as $configFile) { $configFile = $this->fileHelper->normalizePath($configFile, '/'); if (in_array($configFile, $configFilesFromExtensionInstaller, \true)) { continue; } foreach ($this->composerAutoloaderProjectPaths as $composerAutoloaderProjectPath) { $composerConfig = ComposerHelper::getComposerConfig($composerAutoloaderProjectPath); if ($composerConfig === null) { continue; } $vendorDir = $this->fileHelper->normalizePath(ComposerHelper::getVendorDirFromComposerConfig($composerAutoloaderProjectPath, $composerConfig), '/'); if (!str_starts_with($configFile, $vendorDir)) { continue; } $installedPath = $vendorDir . '/composer/installed.php'; if (!is_file($installedPath)) { continue; } $installed = (require $installedPath); $trimmed = substr($configFile, strlen($vendorDir) + 1); $parts = explode('/', $trimmed); $package = implode('/', array_slice($parts, 0, 2)); $configPath = implode('/', array_slice($parts, 2)); if (!array_key_exists($package, $installed['versions'])) { continue; } $packageVersion = $installed['versions'][$package]['pretty_version'] ?? null; if ($packageVersion === null) { continue; } $thirdPartyIncludedConfigs[] = [$package, $packageVersion, $configPath]; } } if (count($thirdPartyIncludedConfigs) > 0) { $output->writeLineFormatted('Included configs from Composer packages:'); foreach ($thirdPartyIncludedConfigs as [$package, $packageVersion, $configPath]) { $output->writeLineFormatted(sprintf('%s (%s): %s', $package, $configPath, $packageVersion)); } $output->writeLineFormatted(''); } $composerAutoloaderProjectPathsCount = count($this->composerAutoloaderProjectPaths); $output->writeLineFormatted(sprintf('Discovered Composer project %s:', $composerAutoloaderProjectPathsCount === 1 ? 'root' : 'roots')); if ($composerAutoloaderProjectPathsCount === 0) { $output->writeLineFormatted('None'); } foreach ($this->composerAutoloaderProjectPaths as $composerAutoloaderProjectPath) { $output->writeLineFormatted($composerAutoloaderProjectPath); } $output->writeLineFormatted(''); } } expression = $expression; $this->originalType = $originalType; $this->originalNativeType = $originalNativeType; $this->certainty = $certainty; } public function getExpression() : Expr { return $this->expression; } public function getOriginalType() : Type { return $this->originalType; } public function getOriginalNativeType() : Type { return $this->originalNativeType; } public function getCertainty() : TrinaryLogic { return $this->certainty; } } scope = $scope; $this->throwPoints = $throwPoints; $this->impurePoints = $impurePoints; $this->invalidateExpressions = $invalidateExpressions; } public function getScope() : \PHPStan\Analyser\MutatingScope { return $this->scope; } /** * @return ThrowPoint[] */ public function getThrowPoints() : array { return $this->throwPoints; } /** * @return ImpurePoint[] */ public function getImpurePoints() : array { return $this->impurePoints; } /** * @return InvalidateExprNode[] */ public function getInvalidateExpressions() : array { return $this->invalidateExpressions; } } ruleRegistry = $ruleRegistry; $this->ruleErrorTransformer = $ruleErrorTransformer; $this->scopeFactory = $scopeFactory; $this->localIgnoresProcessor = $localIgnoresProcessor; $this->reportUnmatchedIgnoredErrors = $reportUnmatchedIgnoredErrors; } public function finalize(\PHPStan\Analyser\AnalyserResult $analyserResult, bool $onlyFiles, bool $debug) : \PHPStan\Analyser\FinalizerResult { if (count($analyserResult->getCollectedData()) === 0) { return $this->addUnmatchedIgnoredErrors($this->mergeFilteredPhpErrors($analyserResult), [], []); } $hasInternalErrors = count($analyserResult->getInternalErrors()) > 0 || $analyserResult->hasReachedInternalErrorsCountLimit(); if ($hasInternalErrors) { return $this->addUnmatchedIgnoredErrors($this->mergeFilteredPhpErrors($analyserResult), [], []); } $nodeType = CollectedDataNode::class; $node = new CollectedDataNode($analyserResult->getCollectedData(), $onlyFiles); $file = 'N/A'; $scope = $this->scopeFactory->create(\PHPStan\Analyser\ScopeContext::create($file)); $tempCollectorErrors = []; $internalErrors = $analyserResult->getInternalErrors(); foreach ($this->ruleRegistry->getRules($nodeType) as $rule) { try { $ruleErrors = $rule->processNode($node, $scope); } catch (AnalysedCodeException $e) { $tempCollectorErrors[] = (new \PHPStan\Analyser\Error($e->getMessage(), $file, $node->getStartLine(), $e, null, null, $e->getTip()))->withIdentifier('phpstan.internal')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); continue; } catch (IdentifierNotFound $e) { $tempCollectorErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s not found.', $e->getIdentifier()->getName()), $file, $node->getStartLine(), $e, null, null, 'Learn more at https://phpstan.org/user-guide/discovering-symbols'))->withIdentifier('phpstan.reflection')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); continue; } catch (UnableToCompileNode|CircularReference $e) { $tempCollectorErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s', $e->getMessage()), $file, $node->getStartLine(), $e))->withIdentifier('phpstan.reflection')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); continue; } catch (Throwable $t) { if ($debug) { throw $t; } $internalErrors[] = new \PHPStan\Analyser\InternalError($t->getMessage(), sprintf('running CollectedDataNode rule %s', get_class($rule)), \PHPStan\Analyser\InternalError::prepareTrace($t), $t->getTraceAsString(), \true); continue; } foreach ($ruleErrors as $ruleError) { $tempCollectorErrors[] = $this->ruleErrorTransformer->transform($ruleError, $scope, $nodeType, $node->getStartLine()); } } $errors = $analyserResult->getUnorderedErrors(); $locallyIgnoredErrors = $analyserResult->getLocallyIgnoredErrors(); $allLinesToIgnore = $analyserResult->getLinesToIgnore(); $allUnmatchedLineIgnores = $analyserResult->getUnmatchedLineIgnores(); $collectorErrors = []; $locallyIgnoredCollectorErrors = []; foreach ($tempCollectorErrors as $tempCollectorError) { $file = $tempCollectorError->getFilePath(); $linesToIgnore = $allLinesToIgnore[$file] ?? []; $unmatchedLineIgnores = $allUnmatchedLineIgnores[$file] ?? []; $localIgnoresProcessorResult = $this->localIgnoresProcessor->process([$tempCollectorError], $linesToIgnore, $unmatchedLineIgnores); foreach ($localIgnoresProcessorResult->getFileErrors() as $error) { $errors[] = $error; $collectorErrors[] = $error; } foreach ($localIgnoresProcessorResult->getLocallyIgnoredErrors() as $locallyIgnoredError) { $locallyIgnoredErrors[] = $locallyIgnoredError; $locallyIgnoredCollectorErrors[] = $locallyIgnoredError; } $allLinesToIgnore[$file] = $localIgnoresProcessorResult->getLinesToIgnore(); $allUnmatchedLineIgnores[$file] = $localIgnoresProcessorResult->getUnmatchedLineIgnores(); } return $this->addUnmatchedIgnoredErrors(new \PHPStan\Analyser\AnalyserResult(array_merge($errors, $analyserResult->getFilteredPhpErrors()), [], $analyserResult->getAllPhpErrors(), $locallyIgnoredErrors, $allLinesToIgnore, $allUnmatchedLineIgnores, $internalErrors, $analyserResult->getCollectedData(), $analyserResult->getDependencies(), $analyserResult->getUsedTraitDependencies(), $analyserResult->getExportedNodes(), $analyserResult->hasReachedInternalErrorsCountLimit(), $analyserResult->getPeakMemoryUsageBytes()), $collectorErrors, $locallyIgnoredCollectorErrors); } private function mergeFilteredPhpErrors(\PHPStan\Analyser\AnalyserResult $analyserResult) : \PHPStan\Analyser\AnalyserResult { return new \PHPStan\Analyser\AnalyserResult(array_merge($analyserResult->getUnorderedErrors(), $analyserResult->getFilteredPhpErrors()), [], $analyserResult->getAllPhpErrors(), $analyserResult->getLocallyIgnoredErrors(), $analyserResult->getLinesToIgnore(), $analyserResult->getUnmatchedLineIgnores(), $analyserResult->getInternalErrors(), $analyserResult->getCollectedData(), $analyserResult->getDependencies(), $analyserResult->getUsedTraitDependencies(), $analyserResult->getExportedNodes(), $analyserResult->hasReachedInternalErrorsCountLimit(), $analyserResult->getPeakMemoryUsageBytes()); } /** * @param list $collectorErrors * @param list $locallyIgnoredCollectorErrors */ private function addUnmatchedIgnoredErrors(\PHPStan\Analyser\AnalyserResult $analyserResult, array $collectorErrors, array $locallyIgnoredCollectorErrors) : \PHPStan\Analyser\FinalizerResult { if (!$this->reportUnmatchedIgnoredErrors) { return new \PHPStan\Analyser\FinalizerResult($analyserResult, $collectorErrors, $locallyIgnoredCollectorErrors); } $errors = $analyserResult->getUnorderedErrors(); foreach ($analyserResult->getUnmatchedLineIgnores() as $file => $data) { foreach ($data as $ignoredFile => $lines) { if ($ignoredFile !== $file) { continue; } foreach ($lines as $line => $identifiers) { if ($identifiers === null) { $errors[] = (new \PHPStan\Analyser\Error(sprintf('No error to ignore is reported on line %d.', $line), $file, $line, \false, $file))->withIdentifier('ignore.unmatchedLine'); continue; } foreach ($identifiers as $identifier) { $errors[] = (new \PHPStan\Analyser\Error(sprintf('No error with identifier %s is reported on line %d.', $identifier, $line), $file, $line, \false, $file))->withIdentifier('ignore.unmatchedIdentifier'); } } } } return new \PHPStan\Analyser\FinalizerResult(new \PHPStan\Analyser\AnalyserResult($errors, $analyserResult->getFilteredPhpErrors(), $analyserResult->getAllPhpErrors(), $analyserResult->getLocallyIgnoredErrors(), $analyserResult->getLinesToIgnore(), $analyserResult->getUnmatchedLineIgnores(), $analyserResult->getInternalErrors(), $analyserResult->getCollectedData(), $analyserResult->getDependencies(), $analyserResult->getUsedTraitDependencies(), $analyserResult->getExportedNodes(), $analyserResult->hasReachedInternalErrorsCountLimit(), $analyserResult->getPeakMemoryUsageBytes()), $collectorErrors, $locallyIgnoredCollectorErrors); } } */ private $errors; /** * @var array> */ private $otherIgnoreErrors; /** * @var array>> */ private $ignoreErrorsByFile; /** * @var (string|mixed[])[] */ private $ignoreErrors; /** * @var bool */ private $reportUnmatchedIgnoredErrors; /** * @param list $errors * @param array> $otherIgnoreErrors * @param array>> $ignoreErrorsByFile * @param (string|mixed[])[] $ignoreErrors */ public function __construct(FileHelper $fileHelper, array $errors, array $otherIgnoreErrors, array $ignoreErrorsByFile, array $ignoreErrors, bool $reportUnmatchedIgnoredErrors) { $this->fileHelper = $fileHelper; $this->errors = $errors; $this->otherIgnoreErrors = $otherIgnoreErrors; $this->ignoreErrorsByFile = $ignoreErrorsByFile; $this->ignoreErrors = $ignoreErrors; $this->reportUnmatchedIgnoredErrors = $reportUnmatchedIgnoredErrors; } /** * @return list */ public function getErrors() : array { return $this->errors; } /** * @param Error[] $errors * @param string[] $analysedFiles */ public function process(array $errors, bool $onlyFiles, array $analysedFiles, bool $hasInternalErrors) : \PHPStan\Analyser\Ignore\IgnoredErrorHelperProcessedResult { $unmatchedIgnoredErrors = $this->ignoreErrors; $stringErrors = []; $processIgnoreError = function (Error $error, int $i, $ignore) use(&$unmatchedIgnoredErrors, &$stringErrors) : bool { $shouldBeIgnored = \false; if (is_string($ignore)) { $shouldBeIgnored = \PHPStan\Analyser\Ignore\IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore, null, null); if ($shouldBeIgnored) { unset($unmatchedIgnoredErrors[$i]); } } else { if (isset($ignore['path'])) { $shouldBeIgnored = \PHPStan\Analyser\Ignore\IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['identifier'] ?? null, $ignore['path']); if ($shouldBeIgnored) { if (isset($ignore['count'])) { $realCount = $unmatchedIgnoredErrors[$i]['realCount'] ?? 0; $realCount++; $unmatchedIgnoredErrors[$i]['realCount'] = $realCount; if (!isset($unmatchedIgnoredErrors[$i]['file'])) { $unmatchedIgnoredErrors[$i]['file'] = $error->getFile(); $unmatchedIgnoredErrors[$i]['line'] = $error->getLine(); } if ($realCount > $ignore['count']) { $shouldBeIgnored = \false; } } else { unset($unmatchedIgnoredErrors[$i]); } } } elseif (isset($ignore['paths'])) { foreach ($ignore['paths'] as $j => $ignorePath) { $shouldBeIgnored = \PHPStan\Analyser\Ignore\IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['identifier'] ?? null, $ignorePath); if (!$shouldBeIgnored) { continue; } if (isset($unmatchedIgnoredErrors[$i])) { if (!is_array($unmatchedIgnoredErrors[$i])) { throw new ShouldNotHappenException(); } unset($unmatchedIgnoredErrors[$i]['paths'][$j]); if (isset($unmatchedIgnoredErrors[$i]['paths']) && count($unmatchedIgnoredErrors[$i]['paths']) === 0) { unset($unmatchedIgnoredErrors[$i]); } } break; } } else { $shouldBeIgnored = \PHPStan\Analyser\Ignore\IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['identifier'] ?? null, null); if ($shouldBeIgnored) { unset($unmatchedIgnoredErrors[$i]); } } } if ($shouldBeIgnored) { if (!$error->canBeIgnored()) { $stringErrors[] = sprintf('Error message "%s" cannot be ignored, use excludePaths instead.', $error->getMessage()); return \true; } return \false; } return \true; }; $ignoredErrors = []; foreach ($errors as $errorIndex => $error) { $filePath = $this->fileHelper->normalizePath($error->getFilePath()); if (isset($this->ignoreErrorsByFile[$filePath])) { foreach ($this->ignoreErrorsByFile[$filePath] as $ignoreError) { $i = $ignoreError['index']; $ignore = $ignoreError['ignoreError']; $result = $processIgnoreError($error, $i, $ignore); if (!$result) { unset($errors[$errorIndex]); $ignoredErrors[] = [$error, $ignore]; continue 2; } } } $traitFilePath = $error->getTraitFilePath(); if ($traitFilePath !== null) { $normalizedTraitFilePath = $this->fileHelper->normalizePath($traitFilePath); if (isset($this->ignoreErrorsByFile[$normalizedTraitFilePath])) { foreach ($this->ignoreErrorsByFile[$normalizedTraitFilePath] as $ignoreError) { $i = $ignoreError['index']; $ignore = $ignoreError['ignoreError']; $result = $processIgnoreError($error, $i, $ignore); if (!$result) { unset($errors[$errorIndex]); $ignoredErrors[] = [$error, $ignore]; continue 2; } } } } foreach ($this->otherIgnoreErrors as $ignoreError) { $i = $ignoreError['index']; $ignore = $ignoreError['ignoreError']; $result = $processIgnoreError($error, $i, $ignore); if (!$result) { unset($errors[$errorIndex]); $ignoredErrors[] = [$error, $ignore]; continue 2; } } } $errors = array_values($errors); foreach ($unmatchedIgnoredErrors as $unmatchedIgnoredError) { if (!isset($unmatchedIgnoredError['count']) || !isset($unmatchedIgnoredError['realCount'])) { continue; } if ($unmatchedIgnoredError['realCount'] <= $unmatchedIgnoredError['count']) { continue; } $errors[] = (new Error(sprintf('Ignored error pattern %s is expected to occur %d %s, but occurred %d %s.', \PHPStan\Analyser\Ignore\IgnoredError::stringifyPattern($unmatchedIgnoredError), $unmatchedIgnoredError['count'], $unmatchedIgnoredError['count'] === 1 ? 'time' : 'times', $unmatchedIgnoredError['realCount'], $unmatchedIgnoredError['realCount'] === 1 ? 'time' : 'times'), $unmatchedIgnoredError['file'], $unmatchedIgnoredError['line'], \false))->withIdentifier('ignore.count'); } $analysedFilesKeys = array_fill_keys($analysedFiles, \true); if (!$hasInternalErrors) { foreach ($unmatchedIgnoredErrors as $unmatchedIgnoredError) { $reportUnmatched = $unmatchedIgnoredError['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors; if ($reportUnmatched === \false) { continue; } if (isset($unmatchedIgnoredError['count']) && isset($unmatchedIgnoredError['realCount']) && (isset($unmatchedIgnoredError['realPath']) || !$onlyFiles)) { if ($unmatchedIgnoredError['realCount'] < $unmatchedIgnoredError['count']) { $errors[] = (new Error(sprintf('Ignored error pattern %s is expected to occur %d %s, but occurred only %d %s.', \PHPStan\Analyser\Ignore\IgnoredError::stringifyPattern($unmatchedIgnoredError), $unmatchedIgnoredError['count'], $unmatchedIgnoredError['count'] === 1 ? 'time' : 'times', $unmatchedIgnoredError['realCount'], $unmatchedIgnoredError['realCount'] === 1 ? 'time' : 'times'), $unmatchedIgnoredError['file'], $unmatchedIgnoredError['line'], \false))->withIdentifier('ignore.count'); } } elseif (isset($unmatchedIgnoredError['realPath'])) { if (!array_key_exists($unmatchedIgnoredError['realPath'], $analysedFilesKeys)) { continue; } $errors[] = (new Error(sprintf('Ignored error pattern %s was not matched in reported errors.', \PHPStan\Analyser\Ignore\IgnoredError::stringifyPattern($unmatchedIgnoredError)), $unmatchedIgnoredError['realPath'], null, \false))->withIdentifier('ignore.unmatched'); } elseif (!$onlyFiles) { $stringErrors[] = sprintf('Ignored error pattern %s was not matched in reported errors.', \PHPStan\Analyser\Ignore\IgnoredError::stringifyPattern($unmatchedIgnoredError)); } } } return new \PHPStan\Analyser\Ignore\IgnoredErrorHelperProcessedResult($errors, $ignoredErrors, $stringErrors); } } 'T_WHITESPACE', self::TOKEN_END => 'end', self::TOKEN_IDENTIFIER => 'identifier', self::TOKEN_COMMA => 'comma (,)', self::TOKEN_OPEN_PARENTHESIS => 'T_OPEN_PARENTHESIS', self::TOKEN_CLOSE_PARENTHESIS => 'T_CLOSE_PARENTHESIS', self::TOKEN_OTHER => 'T_OTHER']; public const VALUE_OFFSET = 0; public const TYPE_OFFSET = 1; public const LINE_OFFSET = 2; /** * @var ?string */ private $regexp = null; /** * @return list */ public function tokenize(string $input) : array { if ($this->regexp === null) { $this->regexp = $this->generateRegexp(); } $matches = Strings::matchAll($input, $this->regexp, PREG_SET_ORDER); $tokens = []; $line = 1; foreach ($matches as $match) { /** @var self::TOKEN_* $type */ $type = (int) $match['MARK']; $tokens[] = [$match[0], $type, $line]; if ($type !== self::TOKEN_END) { continue; } $line++; } if (($type ?? null) !== self::TOKEN_END) { $tokens[] = ['', self::TOKEN_END, $line]; // ensure ending token is present } return $tokens; } /** * @param self::TOKEN_* $type */ public function getLabel(int $type) : string { return self::LABELS[$type]; } private function generateRegexp() : string { $patterns = [ self::TOKEN_WHITESPACE => '[\\x09\\x20]++', self::TOKEN_END => '(\\r?+\\n[\\x09\\x20]*+(?:\\*(?!/)\\x20?+)?|\\*/)', self::TOKEN_IDENTIFIER => Error::PATTERN_IDENTIFIER, self::TOKEN_COMMA => ',', self::TOKEN_OPEN_PARENTHESIS => '\\(', self::TOKEN_CLOSE_PARENTHESIS => '\\)', // everything except whitespaces and parentheses self::TOKEN_OTHER => '([^\\s\\)\\(])++', ]; foreach ($patterns as $type => &$pattern) { $pattern = '(?:' . $pattern . ')(*MARK:' . $type . ')'; } return '~' . implode('|', $patterns) . '~Asi'; } } phpDocLine = $phpDocLine; parent::__construct($message); } public function getPhpDocLine() : int { return $this->phpDocLine; } } */ private $notIgnoredErrors; /** * @var list */ private $ignoredErrors; /** * @var list */ private $otherIgnoreMessages; /** * @param list $notIgnoredErrors * @param list $ignoredErrors * @param list $otherIgnoreMessages */ public function __construct(array $notIgnoredErrors, array $ignoredErrors, array $otherIgnoreMessages) { $this->notIgnoredErrors = $notIgnoredErrors; $this->ignoredErrors = $ignoredErrors; $this->otherIgnoreMessages = $otherIgnoreMessages; } /** * @return list */ public function getNotIgnoredErrors() : array { return $this->notIgnoredErrors; } /** * @return list */ public function getIgnoredErrors() : array { return $this->ignoredErrors; } /** * @return list */ public function getOtherIgnoreMessages() : array { return $this->otherIgnoreMessages; } } getIdentifier() !== $identifier) { return \false; } } if ($ignoredErrorPattern !== null) { // normalize newlines to allow working with ignore-patterns independent of used OS newline-format $errorMessage = $error->getMessage(); $errorMessage = str_replace(['\\r\\n', '\\r'], '\\n', $errorMessage); $ignoredErrorPattern = str_replace([preg_quote('\\r\\n'), preg_quote('\\r')], preg_quote('\\n'), $ignoredErrorPattern); if (Strings::match($errorMessage, $ignoredErrorPattern) === null) { return \false; } } if ($path !== null) { $fileExcluder = new FileExcluder($fileHelper, [$path], BleedingEdgeToggle::isBleedingEdge()); $isExcluded = $fileExcluder->isExcludedFromAnalysing($error->getFilePath()); if (!$isExcluded && $error->getTraitFilePath() !== null) { return $fileExcluder->isExcludedFromAnalysing($error->getTraitFilePath()); } return $isExcluded; } return \true; } } fileHelper = $fileHelper; $this->ignoreErrors = $ignoreErrors; $this->reportUnmatchedIgnoredErrors = $reportUnmatchedIgnoredErrors; } public function initialize() : \PHPStan\Analyser\Ignore\IgnoredErrorHelperResult { $otherIgnoreErrors = []; $ignoreErrorsByFile = []; $errors = []; $expandedIgnoreErrors = []; foreach ($this->ignoreErrors as $ignoreError) { if (is_array($ignoreError)) { if (!isset($ignoreError['message']) && !isset($ignoreError['messages']) && !isset($ignoreError['identifier'])) { $errors[] = sprintf('Ignored error %s is missing a message or an identifier.', Json::encode($ignoreError)); continue; } if (isset($ignoreError['messages'])) { foreach ($ignoreError['messages'] as $message) { $expandedIgnoreError = $ignoreError; unset($expandedIgnoreError['messages']); $expandedIgnoreError['message'] = $message; $expandedIgnoreErrors[] = $expandedIgnoreError; } } else { $expandedIgnoreErrors[] = $ignoreError; } } else { $expandedIgnoreErrors[] = $ignoreError; } } $uniquedExpandedIgnoreErrors = []; foreach ($expandedIgnoreErrors as $ignoreError) { if (!isset($ignoreError['message']) && !isset($ignoreError['identifier'])) { $uniquedExpandedIgnoreErrors[] = $ignoreError; continue; } if (!isset($ignoreError['path'])) { $uniquedExpandedIgnoreErrors[] = $ignoreError; continue; } $key = $ignoreError['path']; if (isset($ignoreError['message'])) { $key = sprintf("%s\n%s", $key, $ignoreError['message']); } if (isset($ignoreError['identifier'])) { $key = sprintf("%s\n%s", $key, $ignoreError['identifier']); } if ($key === '') { throw new ShouldNotHappenException(); } if (!array_key_exists($key, $uniquedExpandedIgnoreErrors)) { $uniquedExpandedIgnoreErrors[$key] = $ignoreError; continue; } $uniquedExpandedIgnoreErrors[$key] = ['message' => $ignoreError['message'] ?? null, 'path' => $ignoreError['path'], 'identifier' => $ignoreError['identifier'] ?? null, 'count' => ($uniquedExpandedIgnoreErrors[$key]['count'] ?? 1) + ($ignoreError['count'] ?? 1), 'reportUnmatched' => ($uniquedExpandedIgnoreErrors[$key]['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors) || ($ignoreError['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors)]; } $expandedIgnoreErrors = array_values($uniquedExpandedIgnoreErrors); foreach ($expandedIgnoreErrors as $i => $ignoreError) { $ignoreErrorEntry = ['index' => $i, 'ignoreError' => $ignoreError]; try { if (is_array($ignoreError)) { if (!isset($ignoreError['message']) && !isset($ignoreError['identifier'])) { $errors[] = sprintf('Ignored error %s is missing a message or an identifier.', Json::encode($ignoreError)); continue; } if (!isset($ignoreError['path'])) { $otherIgnoreErrors[] = $ignoreErrorEntry; } elseif (@is_file($ignoreError['path'])) { $normalizedPath = $this->fileHelper->normalizePath($ignoreError['path']); $ignoreError['path'] = $normalizedPath; $ignoreErrorsByFile[$normalizedPath][] = $ignoreErrorEntry; $ignoreError['realPath'] = $normalizedPath; $expandedIgnoreErrors[$i] = $ignoreError; } else { $otherIgnoreErrors[] = $ignoreErrorEntry; } } else { $otherIgnoreErrors[] = $ignoreErrorEntry; } } catch (JsonException $e) { $errors[] = $e->getMessage(); } } return new \PHPStan\Analyser\Ignore\IgnoredErrorHelperResult($this->fileHelper, $errors, $otherIgnoreErrors, $ignoreErrorsByFile, $expandedIgnoreErrors, $this->reportUnmatchedIgnoredErrors); } } $fileReplacements */ public function create(array $fileReplacements) : \PHPStan\Analyser\ResultCache\ResultCacheManager; } */ private $fileReplacements; /** * @var bool */ private $checkDependenciesOfProjectExtensionFiles; private const CACHE_VERSION = 'v12-linesToIgnore'; /** @var array */ private $fileHashes = []; /** @var array */ private $alreadyProcessed = []; /** * @param string[] $analysedPaths * @param string[] $analysedPathsFromConfig * @param string[] $composerAutoloaderProjectPaths * @param string[] $bootstrapFiles * @param string[] $scanFiles * @param string[] $scanDirectories * @param array $fileReplacements */ public function __construct(ExportedNodeFetcher $exportedNodeFetcher, FileFinder $scanFileFinder, ReflectionProvider $reflectionProvider, StubFilesProvider $stubFilesProvider, FileHelper $fileHelper, string $cacheFilePath, array $analysedPaths, array $analysedPathsFromConfig, array $composerAutoloaderProjectPaths, string $usedLevel, ?string $cliAutoloadFile, array $bootstrapFiles, array $scanFiles, array $scanDirectories, array $fileReplacements, bool $checkDependenciesOfProjectExtensionFiles) { $this->exportedNodeFetcher = $exportedNodeFetcher; $this->scanFileFinder = $scanFileFinder; $this->reflectionProvider = $reflectionProvider; $this->stubFilesProvider = $stubFilesProvider; $this->fileHelper = $fileHelper; $this->cacheFilePath = $cacheFilePath; $this->analysedPaths = $analysedPaths; $this->analysedPathsFromConfig = $analysedPathsFromConfig; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; $this->usedLevel = $usedLevel; $this->cliAutoloadFile = $cliAutoloadFile; $this->bootstrapFiles = $bootstrapFiles; $this->scanFiles = $scanFiles; $this->scanDirectories = $scanDirectories; $this->fileReplacements = $fileReplacements; $this->checkDependenciesOfProjectExtensionFiles = $checkDependenciesOfProjectExtensionFiles; } /** * @param string[] $allAnalysedFiles * @param mixed[]|null $projectConfigArray */ public function restore(array $allAnalysedFiles, bool $debug, bool $onlyFiles, ?array $projectConfigArray, Output $output) : \PHPStan\Analyser\ResultCache\ResultCache { $startTime = microtime(\true); $currentFileHashes = []; foreach ($allAnalysedFiles as $analysedFile) { if (!is_file($analysedFile)) { continue; } $currentFileHashes[$analysedFile] = $this->getFileHash($analysedFile); } if ($debug) { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache not used because of debug mode.'); } return new \PHPStan\Analyser\ResultCache\ResultCache($allAnalysedFiles, \true, time(), $this->getMeta($allAnalysedFiles, $projectConfigArray), [], [], [], [], [], [], [], [], [], $currentFileHashes); } if ($onlyFiles) { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache not used because only files were passed as analysed paths.'); } return new \PHPStan\Analyser\ResultCache\ResultCache($allAnalysedFiles, \true, time(), $this->getMeta($allAnalysedFiles, $projectConfigArray), [], [], [], [], [], [], [], [], [], $currentFileHashes); } $cacheFilePath = $this->cacheFilePath; if (!is_file($cacheFilePath)) { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache not used because the cache file does not exist.'); } return new \PHPStan\Analyser\ResultCache\ResultCache($allAnalysedFiles, \true, time(), $this->getMeta($allAnalysedFiles, $projectConfigArray), [], [], [], [], [], [], [], [], [], $currentFileHashes); } try { $data = (require $cacheFilePath); } catch (Throwable $e) { if ($output->isVeryVerbose()) { $output->writeLineFormatted(sprintf('Result cache not used because an error occurred while loading the cache file: %s', $e->getMessage())); } @unlink($cacheFilePath); return new \PHPStan\Analyser\ResultCache\ResultCache($allAnalysedFiles, \true, time(), $this->getMeta($allAnalysedFiles, $projectConfigArray), [], [], [], [], [], [], [], [], [], $currentFileHashes); } if (!is_array($data)) { @unlink($cacheFilePath); if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache not used because the cache file is corrupted.'); } return new \PHPStan\Analyser\ResultCache\ResultCache($allAnalysedFiles, \true, time(), $this->getMeta($allAnalysedFiles, $projectConfigArray), [], [], [], [], [], [], [], [], [], $currentFileHashes); } $meta = $this->getMeta($allAnalysedFiles, $projectConfigArray); if ($this->isMetaDifferent($data['meta'], $meta)) { if ($output->isVeryVerbose()) { $diffs = $this->getMetaKeyDifferences($data['meta'], $meta); $output->writeLineFormatted('Result cache not used because the metadata do not match: ' . implode(', ', $diffs)); } return new \PHPStan\Analyser\ResultCache\ResultCache($allAnalysedFiles, \true, time(), $meta, [], [], [], [], [], [], [], [], [], $currentFileHashes); } if (time() - $data['lastFullAnalysisTime'] >= 60 * 60 * 24 * 7) { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache not used because it\'s more than 7 days since last full analysis.'); } // run full analysis if the result cache is older than 7 days return new \PHPStan\Analyser\ResultCache\ResultCache($allAnalysedFiles, \true, time(), $meta, [], [], [], [], [], [], [], [], [], $currentFileHashes); } /** * @var string $fileHash * @var bool $isAnalysed */ foreach ($data['projectExtensionFiles'] as $extensionFile => [$fileHash, $isAnalysed]) { if (!$isAnalysed) { continue; } if (!is_file($extensionFile)) { if ($output->isVeryVerbose()) { $output->writeLineFormatted(sprintf('Result cache not used because extension file %s was not found.', $extensionFile)); } return new \PHPStan\Analyser\ResultCache\ResultCache($allAnalysedFiles, \true, time(), $meta, [], [], [], [], [], [], [], [], [], $currentFileHashes); } if ($this->getFileHash($extensionFile) === $fileHash) { continue; } if ($output->isVeryVerbose()) { $output->writeLineFormatted(sprintf('Result cache not used because extension file %s hash does not match.', $extensionFile)); } return new \PHPStan\Analyser\ResultCache\ResultCache($allAnalysedFiles, \true, time(), $meta, [], [], [], [], [], [], [], [], [], $currentFileHashes); } $invertedDependencies = $data['dependencies']; $deletedFiles = array_fill_keys(array_keys($invertedDependencies), \true); $filesToAnalyse = []; $invertedDependenciesToReturn = []; $invertedUsedTraitDependenciesToReturn = []; $errors = $data['errorsCallback'](); $locallyIgnoredErrors = $data['locallyIgnoredErrorsCallback'](); $linesToIgnore = $data['linesToIgnore']; $unmatchedLineIgnores = $data['unmatchedLineIgnores']; $collectedData = $data['collectedDataCallback'](); $exportedNodes = $data['exportedNodesCallback'](); $filteredErrors = []; $filteredLocallyIgnoredErrors = []; $filteredLinesToIgnore = []; $filteredUnmatchedLineIgnores = []; $filteredCollectedData = []; $filteredExportedNodes = []; $newFileAppeared = \false; foreach ($this->getStubFiles() as $stubFile) { if (!array_key_exists($stubFile, $errors)) { continue; } $filteredErrors[$stubFile] = $errors[$stubFile]; } foreach ($allAnalysedFiles as $analysedFile) { if (array_key_exists($analysedFile, $errors)) { $filteredErrors[$analysedFile] = $errors[$analysedFile]; } if (array_key_exists($analysedFile, $locallyIgnoredErrors)) { $filteredLocallyIgnoredErrors[$analysedFile] = $locallyIgnoredErrors[$analysedFile]; } if (array_key_exists($analysedFile, $linesToIgnore)) { $filteredLinesToIgnore[$analysedFile] = $linesToIgnore[$analysedFile]; } if (array_key_exists($analysedFile, $unmatchedLineIgnores)) { $filteredUnmatchedLineIgnores[$analysedFile] = $unmatchedLineIgnores[$analysedFile]; } if (array_key_exists($analysedFile, $collectedData)) { $filteredCollectedData[$analysedFile] = $collectedData[$analysedFile]; } if (array_key_exists($analysedFile, $exportedNodes)) { $filteredExportedNodes[$analysedFile] = $exportedNodes[$analysedFile]; } if (!array_key_exists($analysedFile, $invertedDependencies)) { // new file $filesToAnalyse[] = $analysedFile; $newFileAppeared = \true; continue; } unset($deletedFiles[$analysedFile]); $analysedFileData = $invertedDependencies[$analysedFile]; $cachedFileHash = $analysedFileData['fileHash']; $dependentFiles = $analysedFileData['dependentFiles']; $invertedDependenciesToReturn[$analysedFile] = $dependentFiles; $usedTraitDependentFiles = $analysedFileData['usedTraitDependentFiles'] ?? []; if (count($usedTraitDependentFiles) > 0) { $invertedUsedTraitDependenciesToReturn[$analysedFile] = $usedTraitDependentFiles; } $currentFileHash = $currentFileHashes[$analysedFile]; if ($cachedFileHash === $currentFileHash) { continue; } $filesToAnalyse[] = $analysedFile; if (!array_key_exists($analysedFile, $filteredExportedNodes)) { continue; } $cachedFileExportedNodes = $filteredExportedNodes[$analysedFile]; $exportedNodesChanged = $this->exportedNodesChanged($analysedFile, $cachedFileExportedNodes); if ($exportedNodesChanged === null) { if (count($cachedFileExportedNodes) === 0) { continue; } foreach ($cachedFileExportedNodes as $exportedNode) { if (!$exportedNode instanceof ExportedTraitNode) { continue 2; } } // if the file changed but no exported nodes changed and the only exported nodes are traits // reanalyse files with classes using those traits // but not other dependent files foreach ($usedTraitDependentFiles as $usedTraitDependentFile) { if (!is_file($usedTraitDependentFile)) { continue; } $filesToAnalyse[] = $usedTraitDependentFile; } continue; } if ($exportedNodesChanged) { $newFileAppeared = \true; } foreach ($dependentFiles as $dependentFile) { if (!is_file($dependentFile)) { continue; } $filesToAnalyse[] = $dependentFile; } } foreach (array_keys($deletedFiles) as $deletedFile) { if (!array_key_exists($deletedFile, $invertedDependencies)) { continue; } $deletedFileData = $invertedDependencies[$deletedFile]; $dependentFiles = $deletedFileData['dependentFiles']; foreach ($dependentFiles as $dependentFile) { if (!is_file($dependentFile)) { continue; } $filesToAnalyse[] = $dependentFile; } } if ($newFileAppeared) { foreach (array_keys($filteredErrors) as $fileWithError) { $filesToAnalyse[] = $fileWithError; } } $filesToAnalyse = array_unique($filesToAnalyse); $filesToAnalyseCount = count($filesToAnalyse); if ($output->isVeryVerbose()) { $elapsed = microtime(\true) - $startTime; $elapsedString = $elapsed > 5 ? sprintf(' in %f seconds', round($elapsed, 1)) : ''; $output->writeLineFormatted(sprintf('Result cache restored%s. %d %s will be reanalysed.', $elapsedString, $filesToAnalyseCount, $filesToAnalyseCount === 1 ? 'file' : 'files')); } return new \PHPStan\Analyser\ResultCache\ResultCache($filesToAnalyse, \false, $data['lastFullAnalysisTime'], $meta, $filteredErrors, $filteredLocallyIgnoredErrors, $filteredLinesToIgnore, $filteredUnmatchedLineIgnores, $filteredCollectedData, $invertedDependenciesToReturn, $invertedUsedTraitDependenciesToReturn, $filteredExportedNodes, $data['projectExtensionFiles'], $currentFileHashes); } /** * @param mixed[] $cachedMeta * @param mixed[] $currentMeta */ private function isMetaDifferent(array $cachedMeta, array $currentMeta) : bool { $projectConfig = $currentMeta['projectConfig']; if ($projectConfig !== null) { ksort($currentMeta['projectConfig']); $currentMeta['projectConfig'] = Neon::encode($currentMeta['projectConfig']); } return $cachedMeta !== $currentMeta; } /** * @param mixed[] $cachedMeta * @param mixed[] $currentMeta * * @return string[] */ private function getMetaKeyDifferences(array $cachedMeta, array $currentMeta) : array { $diffs = []; foreach ($cachedMeta as $key => $value) { if (!array_key_exists($key, $currentMeta)) { $diffs[] = $key; continue; } if ($value === $currentMeta[$key]) { continue; } $diffs[] = $key; } if ($diffs === []) { // when none of the keys is different, // the order of the keys is the problem $diffs[] = 'keyOrder'; } return $diffs; } /** * @param array $cachedFileExportedNodes * @return bool|null null means nothing changed, true means new root symbol appeared, false means nested node changed */ private function exportedNodesChanged(string $analysedFile, array $cachedFileExportedNodes) : ?bool { if (array_key_exists($analysedFile, $this->fileReplacements)) { $analysedFile = $this->fileReplacements[$analysedFile]; } $fileExportedNodes = $this->exportedNodeFetcher->fetchNodes($analysedFile); $cachedSymbols = []; foreach ($cachedFileExportedNodes as $cachedFileExportedNode) { $cachedSymbols[$cachedFileExportedNode->getType()][] = $cachedFileExportedNode->getName(); } $fileSymbols = []; foreach ($fileExportedNodes as $fileExportedNode) { $fileSymbols[$fileExportedNode->getType()][] = $fileExportedNode->getName(); } if ($cachedSymbols !== $fileSymbols) { return \true; } if (count($fileExportedNodes) !== count($cachedFileExportedNodes)) { return \true; } foreach ($fileExportedNodes as $i => $fileExportedNode) { $cachedExportedNode = $cachedFileExportedNodes[$i]; if (!$cachedExportedNode->equals($fileExportedNode)) { return \false; } } return null; } public function process(AnalyserResult $analyserResult, \PHPStan\Analyser\ResultCache\ResultCache $resultCache, Output $output, bool $onlyFiles, bool $save) : \PHPStan\Analyser\ResultCache\ResultCacheProcessResult { $internalErrors = $analyserResult->getInternalErrors(); $freshErrorsByFile = []; foreach ($analyserResult->getErrors() as $error) { $freshErrorsByFile[$error->getFilePath()][] = $error; } $freshLocallyIgnoredErrorsByFile = []; foreach ($analyserResult->getLocallyIgnoredErrors() as $error) { $freshLocallyIgnoredErrorsByFile[$error->getFilePath()][] = $error; } $freshCollectedDataByFile = []; foreach ($analyserResult->getCollectedData() as $collectedData) { $freshCollectedDataByFile[$collectedData->getFilePath()][] = $collectedData; } $meta = $resultCache->getMeta(); $projectConfigArray = $meta['projectConfig']; if ($projectConfigArray !== null) { $meta['projectConfig'] = Neon::encode($projectConfigArray); } $doSave = function (array $errorsByFile, $locallyIgnoredErrorsByFile, $linesToIgnore, $unmatchedLineIgnores, $collectedDataByFile, ?array $dependencies, ?array $usedTraitDependencies, array $exportedNodes, array $projectExtensionFiles) use($internalErrors, $resultCache, $output, $onlyFiles, $meta) : bool { if ($onlyFiles) { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache was not saved because only files were passed as analysed paths.'); } return \false; } if ($dependencies === null) { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache was not saved because of error in dependencies.'); } return \false; } if ($usedTraitDependencies === null) { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache was not saved because of error in used trait dependencies.'); } return \false; } if (count($internalErrors) > 0) { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache was not saved because of internal errors.'); } return \false; } if (count($this->fileReplacements) > 0) { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache was not saved because of --tmp-file and --instead-of CLI options passed (editor mode).'); } return \false; } foreach ($errorsByFile as $errors) { foreach ($errors as $error) { if (!$error->hasNonIgnorableException()) { continue; } if ($output->isVeryVerbose()) { $output->writeLineFormatted(sprintf('Result cache was not saved because of non-ignorable exception: %s', $error->getMessage())); } return \false; } } $this->save($resultCache->getLastFullAnalysisTime(), $errorsByFile, $locallyIgnoredErrorsByFile, $linesToIgnore, $unmatchedLineIgnores, $collectedDataByFile, $dependencies, $usedTraitDependencies, $exportedNodes, $projectExtensionFiles, $resultCache->getCurrentFileHashes(), $meta); if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache is saved.'); } return \true; }; if ($resultCache->isFullAnalysis()) { $saved = \false; if ($save !== \false) { $projectExtensionFiles = []; if ($analyserResult->getDependencies() !== null) { $projectExtensionFiles = $this->getProjectExtensionFiles($projectConfigArray, $analyserResult->getDependencies()); } $saved = $doSave($freshErrorsByFile, $freshLocallyIgnoredErrorsByFile, $analyserResult->getLinesToIgnore(), $analyserResult->getUnmatchedLineIgnores(), $freshCollectedDataByFile, $analyserResult->getDependencies(), $analyserResult->getUsedTraitDependencies(), $analyserResult->getExportedNodes(), $projectExtensionFiles); } else { if ($output->isVeryVerbose()) { $output->writeLineFormatted('Result cache was not saved because it was not requested.'); } } return new \PHPStan\Analyser\ResultCache\ResultCacheProcessResult($analyserResult, $saved); } $errorsByFile = $this->mergeErrors($resultCache, $freshErrorsByFile); $locallyIgnoredErrorsByFile = $this->mergeLocallyIgnoredErrors($resultCache, $freshLocallyIgnoredErrorsByFile); $collectedDataByFile = $this->mergeCollectedData($resultCache, $freshCollectedDataByFile); $dependencies = $this->mergeDependencies($resultCache->getDependencies(), $resultCache->getFilesToAnalyse(), $analyserResult->getDependencies()); $usedTraitDependencies = $this->mergeDependencies($resultCache->getUsedTraitDependencies(), $resultCache->getFilesToAnalyse(), $analyserResult->getUsedTraitDependencies()); $exportedNodes = $this->mergeExportedNodes($resultCache, $analyserResult->getExportedNodes()); $linesToIgnore = $this->mergeLinesToIgnore($resultCache, $analyserResult->getLinesToIgnore()); $unmatchedLineIgnores = $this->mergeUnmatchedLineIgnores($resultCache, $analyserResult->getUnmatchedLineIgnores()); $saved = \false; if ($save !== \false) { $projectExtensionFiles = []; foreach ($resultCache->getProjectExtensionFiles() as $file => [$hash, $isAnalysed, $className]) { if ($isAnalysed) { continue; } // keep the same file hashes from the old run // so that the message "When you edit them and re-run PHPStan, the result cache will get stale." // keeps being shown on subsequent runs $projectExtensionFiles[$file] = [$hash, \false, $className]; } if ($dependencies !== null) { foreach ($this->getProjectExtensionFiles($projectConfigArray, $dependencies) as $file => [$hash, $isAnalysed, $className]) { if (!$isAnalysed) { continue; } $projectExtensionFiles[$file] = [$hash, \true, $className]; } } $saved = $doSave($errorsByFile, $locallyIgnoredErrorsByFile, $linesToIgnore, $unmatchedLineIgnores, $collectedDataByFile, $dependencies, $usedTraitDependencies, $exportedNodes, $projectExtensionFiles); } $flatErrors = []; foreach ($errorsByFile as $fileErrors) { foreach ($fileErrors as $fileError) { $flatErrors[] = $fileError; } } $flatLocallyIgnoredErrors = []; foreach ($locallyIgnoredErrorsByFile as $fileErrors) { foreach ($fileErrors as $fileError) { $flatLocallyIgnoredErrors[] = $fileError; } } $flatCollectedData = []; foreach ($collectedDataByFile as $fileCollectedData) { foreach ($fileCollectedData as $collectedData) { $flatCollectedData[] = $collectedData; } } return new \PHPStan\Analyser\ResultCache\ResultCacheProcessResult(new AnalyserResult($flatErrors, $analyserResult->getFilteredPhpErrors(), $analyserResult->getAllPhpErrors(), $flatLocallyIgnoredErrors, $linesToIgnore, $unmatchedLineIgnores, $internalErrors, $flatCollectedData, $dependencies, $usedTraitDependencies, $exportedNodes, $analyserResult->hasReachedInternalErrorsCountLimit(), $analyserResult->getPeakMemoryUsageBytes()), $saved); } /** * @param array> $freshErrorsByFile * @return array> */ private function mergeErrors(\PHPStan\Analyser\ResultCache\ResultCache $resultCache, array $freshErrorsByFile) : array { $errorsByFile = $resultCache->getErrors(); foreach ($resultCache->getFilesToAnalyse() as $file) { if (array_key_exists($file, $this->fileReplacements)) { unset($errorsByFile[$file]); $file = $this->fileReplacements[$file]; } if (!array_key_exists($file, $freshErrorsByFile)) { unset($errorsByFile[$file]); continue; } $errorsByFile[$file] = $freshErrorsByFile[$file]; } return $errorsByFile; } /** * @param array> $freshLocallyIgnoredErrorsByFile * @return array> */ private function mergeLocallyIgnoredErrors(\PHPStan\Analyser\ResultCache\ResultCache $resultCache, array $freshLocallyIgnoredErrorsByFile) : array { $errorsByFile = $resultCache->getLocallyIgnoredErrors(); foreach ($resultCache->getFilesToAnalyse() as $file) { if (array_key_exists($file, $this->fileReplacements)) { unset($errorsByFile[$file]); $file = $this->fileReplacements[$file]; } if (!array_key_exists($file, $freshLocallyIgnoredErrorsByFile)) { unset($errorsByFile[$file]); continue; } $errorsByFile[$file] = $freshLocallyIgnoredErrorsByFile[$file]; } return $errorsByFile; } /** * @param array> $freshCollectedDataByFile * @return array> */ private function mergeCollectedData(\PHPStan\Analyser\ResultCache\ResultCache $resultCache, array $freshCollectedDataByFile) : array { $collectedDataByFile = $resultCache->getCollectedData(); foreach ($resultCache->getFilesToAnalyse() as $file) { if (array_key_exists($file, $this->fileReplacements)) { unset($collectedDataByFile[$file]); $file = $this->fileReplacements[$file]; } if (!array_key_exists($file, $freshCollectedDataByFile)) { unset($collectedDataByFile[$file]); continue; } $collectedDataByFile[$file] = $freshCollectedDataByFile[$file]; } return $collectedDataByFile; } /** * @param array> $resultCacheDependencies * @param string[] $filesToAnalyse * @param array>|null $freshDependencies * @return array>|null */ private function mergeDependencies(array $resultCacheDependencies, array $filesToAnalyse, ?array $freshDependencies) : ?array { if ($freshDependencies === null) { return null; } $cachedDependencies = []; $filesNoOneIsDependingOn = array_fill_keys(array_keys($resultCacheDependencies), \true); foreach ($resultCacheDependencies as $file => $filesDependingOnFile) { foreach ($filesDependingOnFile as $fileDependingOnFile) { $cachedDependencies[$fileDependingOnFile][] = $file; unset($filesNoOneIsDependingOn[$fileDependingOnFile]); } } foreach (array_keys($filesNoOneIsDependingOn) as $file) { if (array_key_exists($file, $cachedDependencies)) { throw new ShouldNotHappenException(); } $cachedDependencies[$file] = []; } $newDependencies = $cachedDependencies; foreach ($filesToAnalyse as $file) { if (array_key_exists($file, $this->fileReplacements)) { unset($newDependencies[$file]); $file = $this->fileReplacements[$file]; } if (!array_key_exists($file, $freshDependencies)) { unset($newDependencies[$file]); continue; } $newDependencies[$file] = $freshDependencies[$file]; } return $newDependencies; } /** * @param array> $freshExportedNodes * @return array> */ private function mergeExportedNodes(\PHPStan\Analyser\ResultCache\ResultCache $resultCache, array $freshExportedNodes) : array { $newExportedNodes = $resultCache->getExportedNodes(); foreach ($resultCache->getFilesToAnalyse() as $file) { if (array_key_exists($file, $this->fileReplacements)) { unset($newExportedNodes[$file]); $file = $this->fileReplacements[$file]; } if (!array_key_exists($file, $freshExportedNodes)) { unset($newExportedNodes[$file]); continue; } $newExportedNodes[$file] = $freshExportedNodes[$file]; } return $newExportedNodes; } /** * @param array $freshLinesToIgnore * @return array */ private function mergeLinesToIgnore(\PHPStan\Analyser\ResultCache\ResultCache $resultCache, array $freshLinesToIgnore) : array { $newLinesToIgnore = $resultCache->getLinesToIgnore(); foreach ($resultCache->getFilesToAnalyse() as $file) { if (array_key_exists($file, $this->fileReplacements)) { unset($newLinesToIgnore[$file]); $file = $this->fileReplacements[$file]; } if (!array_key_exists($file, $freshLinesToIgnore)) { unset($newLinesToIgnore[$file]); continue; } $newLinesToIgnore[$file] = $freshLinesToIgnore[$file]; } return $newLinesToIgnore; } /** * @param array $freshUnmatchedLineIgnores * @return array */ private function mergeUnmatchedLineIgnores(\PHPStan\Analyser\ResultCache\ResultCache $resultCache, array $freshUnmatchedLineIgnores) : array { $newUnmatchedLineIgnores = $resultCache->getUnmatchedLineIgnores(); foreach ($resultCache->getFilesToAnalyse() as $file) { if (array_key_exists($file, $this->fileReplacements)) { unset($newUnmatchedLineIgnores[$file]); $file = $this->fileReplacements[$file]; } if (!array_key_exists($file, $freshUnmatchedLineIgnores)) { unset($newUnmatchedLineIgnores[$file]); continue; } $newUnmatchedLineIgnores[$file] = $freshUnmatchedLineIgnores[$file]; } return $newUnmatchedLineIgnores; } /** * @param array> $errors * @param array> $locallyIgnoredErrors * @param array $linesToIgnore * @param array $unmatchedLineIgnores * @param array> $collectedData * @param array> $dependencies * @param array> $usedTraitDependencies * @param array> $exportedNodes * @param array $projectExtensionFiles * @param array $currentFileHashes * @param mixed[] $meta */ private function save(int $lastFullAnalysisTime, array $errors, array $locallyIgnoredErrors, array $linesToIgnore, array $unmatchedLineIgnores, array $collectedData, array $dependencies, array $usedTraitDependencies, array $exportedNodes, array $projectExtensionFiles, array $currentFileHashes, array $meta) : void { $invertedDependencies = []; $filesNoOneIsDependingOn = array_fill_keys(array_keys($dependencies), \true); foreach ($dependencies as $file => $fileDependencies) { foreach ($fileDependencies as $fileDep) { if (!array_key_exists($fileDep, $invertedDependencies)) { $invertedDependencies[$fileDep] = ['fileHash' => $currentFileHashes[$fileDep] ?? $this->getFileHash($fileDep), 'dependentFiles' => []]; unset($filesNoOneIsDependingOn[$fileDep]); } $invertedDependencies[$fileDep]['dependentFiles'][] = $file; } } foreach ($usedTraitDependencies as $file => $fileUsedTraitDependencies) { foreach ($fileUsedTraitDependencies as $usedTraitFileDep) { if (!array_key_exists($usedTraitFileDep, $invertedDependencies)) { $invertedDependencies[$usedTraitFileDep] = ['fileHash' => $currentFileHashes[$usedTraitFileDep] ?? $this->getFileHash($usedTraitFileDep), 'dependentFiles' => [], 'usedTraitDependentFiles' => []]; unset($filesNoOneIsDependingOn[$usedTraitFileDep]); } $invertedDependencies[$usedTraitFileDep]['usedTraitDependentFiles'][] = $file; } } foreach (array_keys($filesNoOneIsDependingOn) as $file) { if (array_key_exists($file, $invertedDependencies)) { throw new ShouldNotHappenException(); } if (!is_file($file)) { continue; } $invertedDependencies[$file] = ['fileHash' => $currentFileHashes[$file] ?? $this->getFileHash($file), 'dependentFiles' => []]; } ksort($errors); ksort($locallyIgnoredErrors); ksort($linesToIgnore); ksort($unmatchedLineIgnores); ksort($collectedData); ksort($invertedDependencies); foreach ($invertedDependencies as $file => $fileData) { $dependentFiles = $fileData['dependentFiles']; sort($dependentFiles); $invertedDependencies[$file]['dependentFiles'] = $dependentFiles; $usedTraitDependentFiles = $fileData['usedTraitDependentFiles'] ?? []; if (count($usedTraitDependentFiles) === 0) { continue; } sort($usedTraitDependentFiles); $invertedDependencies[$file]['usedTraitDependentFiles'] = $usedTraitDependentFiles; } ksort($exportedNodes); $file = $this->cacheFilePath; FileWriter::write($file, " " . var_export($lastFullAnalysisTime, \true) . ",\n\t'meta' => " . var_export($meta, \true) . ",\n\t'projectExtensionFiles' => " . var_export($projectExtensionFiles, \true) . ",\n\t'errorsCallback' => static function (): array { return " . var_export($errors, \true) . "; },\n\t'locallyIgnoredErrorsCallback' => static function (): array { return " . var_export($locallyIgnoredErrors, \true) . "; },\n\t'linesToIgnore' => " . var_export($linesToIgnore, \true) . ",\n\t'unmatchedLineIgnores' => " . var_export($unmatchedLineIgnores, \true) . ",\n\t'collectedDataCallback' => static function (): array { return " . var_export($collectedData, \true) . "; },\n\t'dependencies' => " . var_export($invertedDependencies, \true) . ",\n\t'exportedNodesCallback' => static function (): array { return " . var_export($exportedNodes, \true) . '; }, ]; '); } /** * @param mixed[]|null $projectConfig * @param array $dependencies * @return array */ private function getProjectExtensionFiles(?array $projectConfig, array $dependencies) : array { $this->alreadyProcessed = []; $projectExtensionFiles = []; if ($projectConfig !== null) { $vendorDirs = []; foreach ($this->composerAutoloaderProjectPaths as $autoloaderProjectPath) { $composer = ComposerHelper::getComposerConfig($autoloaderProjectPath); if ($composer === null) { continue; } $vendorDirectory = ComposerHelper::getVendorDirFromComposerConfig($autoloaderProjectPath, $composer); $vendorDirs[] = $this->fileHelper->normalizePath($vendorDirectory); } $classes = ProjectConfigHelper::getServiceClassNames($projectConfig); foreach ($classes as $class) { if (!$this->reflectionProvider->hasClass($class)) { continue; } $classReflection = $this->reflectionProvider->getClass($class); $fileName = $classReflection->getFileName(); if ($fileName === null) { continue; } if (str_starts_with($fileName, 'phar://')) { continue; } $allServiceFiles = $this->getAllDependencies($fileName, $dependencies); if (count($allServiceFiles) === 0) { $normalizedFileName = $this->fileHelper->normalizePath($fileName); foreach ($vendorDirs as $vendorDir) { if (str_starts_with($normalizedFileName, $vendorDir)) { continue 2; } } $projectExtensionFiles[$fileName] = [$this->getFileHash($fileName), \false, $class]; continue; } foreach ($allServiceFiles as $serviceFile) { if (array_key_exists($serviceFile, $projectExtensionFiles)) { continue; } $projectExtensionFiles[$serviceFile] = [$this->getFileHash($serviceFile), \true, $class]; } } } return $projectExtensionFiles; } /** * @param array> $dependencies * @return array */ private function getAllDependencies(string $fileName, array $dependencies) : array { if (!array_key_exists($fileName, $dependencies)) { return []; } if (array_key_exists($fileName, $this->alreadyProcessed)) { return []; } $this->alreadyProcessed[$fileName] = \true; $files = [$fileName]; if ($this->checkDependenciesOfProjectExtensionFiles) { foreach ($dependencies[$fileName] as $fileDep) { foreach ($this->getAllDependencies($fileDep, $dependencies) as $fileDep2) { $files[] = $fileDep2; } } } return $files; } /** * @param string[] $allAnalysedFiles * @param mixed[]|null $projectConfigArray * @return mixed[] */ private function getMeta(array $allAnalysedFiles, ?array $projectConfigArray) : array { $extensions = array_values(array_filter(get_loaded_extensions(), static function (string $extension) : bool { return $extension !== 'xdebug'; })); sort($extensions); if ($projectConfigArray !== null) { unset($projectConfigArray['parameters']['editorUrl']); unset($projectConfigArray['parameters']['editorUrlTitle']); unset($projectConfigArray['parameters']['errorFormat']); unset($projectConfigArray['parameters']['ignoreErrors']); unset($projectConfigArray['parameters']['reportUnmatchedIgnoredErrors']); unset($projectConfigArray['parameters']['tipsOfTheDay']); unset($projectConfigArray['parameters']['parallel']); unset($projectConfigArray['parameters']['internalErrorsCountLimit']); unset($projectConfigArray['parameters']['cache']); unset($projectConfigArray['parameters']['memoryLimitFile']); unset($projectConfigArray['parameters']['pro']); unset($projectConfigArray['parametersSchema']); ksort($projectConfigArray); } return ['cacheVersion' => self::CACHE_VERSION, 'phpstanVersion' => ComposerHelper::getPhpStanVersion(), 'phpVersion' => PHP_VERSION_ID, 'projectConfig' => $projectConfigArray, 'analysedPaths' => $this->analysedPaths, 'scannedFiles' => $this->getScannedFiles($allAnalysedFiles), 'composerLocks' => $this->getComposerLocks(), 'composerInstalled' => $this->getComposerInstalled(), 'executedFilesHashes' => $this->getExecutedFileHashes(), 'phpExtensions' => $extensions, 'stubFiles' => $this->getStubFiles(), 'level' => $this->usedLevel]; } private function getFileHash(string $path) : string { if (array_key_exists($path, $this->fileReplacements)) { $path = $this->fileReplacements[$path]; } if (array_key_exists($path, $this->fileHashes)) { return $this->fileHashes[$path]; } $hash = sha1_file($path); if ($hash === \false) { throw new CouldNotReadFileException($path); } $this->fileHashes[$path] = $hash; return $hash; } /** * @param string[] $allAnalysedFiles * @return array */ private function getScannedFiles(array $allAnalysedFiles) : array { $scannedFiles = $this->scanFiles; $analysedDirectories = []; foreach (array_merge($this->analysedPaths, $this->analysedPathsFromConfig) as $analysedPath) { if (is_file($analysedPath)) { continue; } if (!is_dir($analysedPath)) { continue; } $analysedDirectories[] = $analysedPath; } $directories = array_unique(array_merge($analysedDirectories, $this->scanDirectories)); foreach ($this->scanFileFinder->findFiles($directories)->getFiles() as $file) { $scannedFiles[] = $file; } $hashes = []; foreach (array_diff($scannedFiles, $allAnalysedFiles) as $file) { $hashes[$file] = $this->getFileHash($file); } ksort($hashes); return $hashes; } /** * @return array */ private function getExecutedFileHashes() : array { $hashes = []; if ($this->cliAutoloadFile !== null) { $hashes[$this->cliAutoloadFile] = $this->getFileHash($this->cliAutoloadFile); } foreach ($this->bootstrapFiles as $bootstrapFile) { $hashes[$bootstrapFile] = $this->getFileHash($bootstrapFile); } ksort($hashes); return $hashes; } /** * @return array */ private function getComposerLocks() : array { $locks = []; foreach ($this->composerAutoloaderProjectPaths as $autoloadPath) { $lockPath = $autoloadPath . '/composer.lock'; if (!is_file($lockPath)) { continue; } $locks[$lockPath] = $this->getFileHash($lockPath); } return $locks; } /** * @return array */ private function getComposerInstalled() : array { $data = []; foreach ($this->composerAutoloaderProjectPaths as $autoloadPath) { $composer = ComposerHelper::getComposerConfig($autoloadPath); if ($composer === null) { continue; } $filePath = ComposerHelper::getVendorDirFromComposerConfig($autoloadPath, $composer) . '/composer/installed.php'; if (!is_file($filePath)) { continue; } $installed = (require $filePath); $rootName = $installed['root']['name']; unset($installed['root']); unset($installed['versions'][$rootName]); $data[$filePath] = $installed; } return $data; } /** * @return array */ private function getStubFiles() : array { $stubFiles = []; foreach ($this->stubFilesProvider->getProjectStubFiles() as $stubFile) { $stubFiles[$stubFile] = $this->getFileHash($stubFile); } ksort($stubFiles); return $stubFiles; } } cacheFilePath = $cacheFilePath; } public function clear() : string { $dir = dirname($this->cacheFilePath); if (!is_file($this->cacheFilePath)) { return $dir; } @unlink($this->cacheFilePath); return $dir; } } analyserResult = $analyserResult; $this->saved = $saved; } public function getAnalyserResult() : AnalyserResult { return $this->analyserResult; } public function isSaved() : bool { return $this->saved; } } > */ private $errors; /** * @var array> */ private $locallyIgnoredErrors; /** * @var array */ private $linesToIgnore; /** * @var array */ private $unmatchedLineIgnores; /** * @var array> */ private $collectedData; /** * @var array> */ private $dependencies; /** * @var array> */ private $usedTraitDependencies; /** * @var array> */ private $exportedNodes; /** * @var array */ private $projectExtensionFiles; /** * @var array */ private $currentFileHashes; /** * @param string[] $filesToAnalyse * @param mixed[] $meta * @param array> $errors * @param array> $locallyIgnoredErrors * @param array $linesToIgnore * @param array $unmatchedLineIgnores * @param array> $collectedData * @param array> $dependencies * @param array> $usedTraitDependencies * @param array> $exportedNodes * @param array $projectExtensionFiles * @param array $currentFileHashes */ public function __construct(array $filesToAnalyse, bool $fullAnalysis, int $lastFullAnalysisTime, array $meta, array $errors, array $locallyIgnoredErrors, array $linesToIgnore, array $unmatchedLineIgnores, array $collectedData, array $dependencies, array $usedTraitDependencies, array $exportedNodes, array $projectExtensionFiles, array $currentFileHashes) { $this->filesToAnalyse = $filesToAnalyse; $this->fullAnalysis = $fullAnalysis; $this->lastFullAnalysisTime = $lastFullAnalysisTime; $this->meta = $meta; $this->errors = $errors; $this->locallyIgnoredErrors = $locallyIgnoredErrors; $this->linesToIgnore = $linesToIgnore; $this->unmatchedLineIgnores = $unmatchedLineIgnores; $this->collectedData = $collectedData; $this->dependencies = $dependencies; $this->usedTraitDependencies = $usedTraitDependencies; $this->exportedNodes = $exportedNodes; $this->projectExtensionFiles = $projectExtensionFiles; $this->currentFileHashes = $currentFileHashes; } /** * @return string[] */ public function getFilesToAnalyse() : array { return $this->filesToAnalyse; } public function isFullAnalysis() : bool { return $this->fullAnalysis; } public function getLastFullAnalysisTime() : int { return $this->lastFullAnalysisTime; } /** * @return mixed[] */ public function getMeta() : array { return $this->meta; } /** * @return array> */ public function getErrors() : array { return $this->errors; } /** * @return array> */ public function getLocallyIgnoredErrors() : array { return $this->locallyIgnoredErrors; } /** * @return array */ public function getLinesToIgnore() : array { return $this->linesToIgnore; } /** * @return array */ public function getUnmatchedLineIgnores() : array { return $this->unmatchedLineIgnores; } /** * @return array> */ public function getCollectedData() : array { return $this->collectedData; } /** * @return array> */ public function getDependencies() : array { return $this->dependencies; } /** * @return array> */ public function getUsedTraitDependencies() : array { return $this->usedTraitDependencies; } /** * @return array> */ public function getExportedNodes() : array { return $this->exportedNodes; } /** * @return array */ public function getProjectExtensionFiles() : array { return $this->projectExtensionFiles; } /** * @return array */ public function getCurrentFileHashes() : array { return $this->currentFileHashes; } } exprPrinter = $exprPrinter; $this->reflectionProvider = $reflectionProvider; $this->functionTypeSpecifyingExtensions = $functionTypeSpecifyingExtensions; $this->methodTypeSpecifyingExtensions = $methodTypeSpecifyingExtensions; $this->staticMethodTypeSpecifyingExtensions = $staticMethodTypeSpecifyingExtensions; $this->rememberPossiblyImpureFunctionValues = $rememberPossiblyImpureFunctionValues; foreach (array_merge($functionTypeSpecifyingExtensions, $methodTypeSpecifyingExtensions, $staticMethodTypeSpecifyingExtensions) as $extension) { if (!$extension instanceof \PHPStan\Analyser\TypeSpecifierAwareExtension) { continue; } $extension->setTypeSpecifier($this); } } /** @api */ public function specifyTypesInCondition(\PHPStan\Analyser\Scope $scope, Expr $expr, \PHPStan\Analyser\TypeSpecifierContext $context, ?Expr $rootExpr = null) : \PHPStan\Analyser\SpecifiedTypes { $rootExpr = $rootExpr ?? $expr; if ($expr instanceof Expr\CallLike && $expr->isFirstClassCallable()) { return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } if ($expr instanceof Instanceof_) { $exprNode = $expr->expr; if ($expr->class instanceof Name) { $className = (string) $expr->class; $lowercasedClassName = strtolower($className); if ($lowercasedClassName === 'self' && $scope->isInClass()) { $type = new ObjectType($scope->getClassReflection()->getName()); } elseif ($lowercasedClassName === 'static' && $scope->isInClass()) { $type = new StaticType($scope->getClassReflection()); } elseif ($lowercasedClassName === 'parent') { if ($scope->isInClass() && $scope->getClassReflection()->getParentClass() !== null) { $type = new ObjectType($scope->getClassReflection()->getParentClass()->getName()); } else { $type = new NonexistentParentClassType(); } } else { $type = new ObjectType($className); } return $this->create($exprNode, $type, $context, \false, $scope, $rootExpr); } $classType = $scope->getType($expr->class); $uncertainty = \false; $type = TypeTraverser::map($classType, static function (Type $type, callable $traverse) use(&$uncertainty) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type->getObjectClassNames() !== []) { $uncertainty = \true; return $type; } if ($type instanceof GenericClassStringType) { $uncertainty = \true; return $type->getGenericType(); } if ($type instanceof ConstantStringType) { return new ObjectType($type->getValue()); } return new MixedType(); }); if (!$type->isSuperTypeOf(new MixedType())->yes()) { if ($context->true()) { $type = TypeCombinator::intersect($type, new ObjectWithoutClassType()); return $this->create($exprNode, $type, $context, \false, $scope, $rootExpr); } elseif ($context->false() && !$uncertainty) { $exprType = $scope->getType($expr->expr); if (!$type->isSuperTypeOf($exprType)->yes()) { return $this->create($exprNode, $type, $context, \false, $scope, $rootExpr); } } } if ($context->true()) { return $this->create($exprNode, new ObjectWithoutClassType(), $context, \false, $scope, $rootExpr); } } elseif ($expr instanceof Node\Expr\BinaryOp\Identical) { return $this->resolveIdentical($expr, $scope, $context, $rootExpr); } elseif ($expr instanceof Node\Expr\BinaryOp\NotIdentical) { return $this->specifyTypesInCondition($scope, new Node\Expr\BooleanNot(new Node\Expr\BinaryOp\Identical($expr->left, $expr->right)), $context, $rootExpr); } elseif ($expr instanceof Expr\Cast\Bool_) { return $this->specifyTypesInCondition($scope, new Node\Expr\BinaryOp\Equal($expr->expr, new ConstFetch(new Name\FullyQualified('true'))), $context, $rootExpr); } elseif ($expr instanceof Expr\Cast\String_) { return $this->specifyTypesInCondition($scope, new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\String_('')), $context, $rootExpr); } elseif ($expr instanceof Expr\Cast\Int_) { return $this->specifyTypesInCondition($scope, new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\LNumber(0)), $context, $rootExpr); } elseif ($expr instanceof Expr\Cast\Double) { return $this->specifyTypesInCondition($scope, new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\DNumber(0.0)), $context, $rootExpr); } elseif ($expr instanceof Node\Expr\BinaryOp\Equal) { return $this->resolveEqual($expr, $scope, $context, $rootExpr); } elseif ($expr instanceof Node\Expr\BinaryOp\NotEqual) { return $this->specifyTypesInCondition($scope, new Node\Expr\BooleanNot(new Node\Expr\BinaryOp\Equal($expr->left, $expr->right)), $context, $rootExpr); } elseif ($expr instanceof Node\Expr\BinaryOp\Smaller || $expr instanceof Node\Expr\BinaryOp\SmallerOrEqual) { if ($expr->left instanceof FuncCall && count($expr->left->getArgs()) >= 1 && $expr->left->name instanceof Name && in_array(strtolower((string) $expr->left->name), ['count', 'sizeof', 'strlen', 'mb_strlen', 'preg_match'], \true) && (!$expr->right instanceof FuncCall || !$expr->right->name instanceof Name || !in_array(strtolower((string) $expr->right->name), ['count', 'sizeof', 'strlen', 'mb_strlen', 'preg_match'], \true))) { $inverseOperator = $expr instanceof Node\Expr\BinaryOp\Smaller ? new Node\Expr\BinaryOp\SmallerOrEqual($expr->right, $expr->left) : new Node\Expr\BinaryOp\Smaller($expr->right, $expr->left); return $this->specifyTypesInCondition($scope, new Node\Expr\BooleanNot($inverseOperator), $context, $rootExpr); } $orEqual = $expr instanceof Node\Expr\BinaryOp\SmallerOrEqual; $offset = $orEqual ? 0 : 1; $leftType = $scope->getType($expr->left); $result = new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); if (!$context->null() && $expr->right instanceof FuncCall && count($expr->right->getArgs()) >= 1 && $expr->right->name instanceof Name && in_array(strtolower((string) $expr->right->name), ['count', 'sizeof'], \true) && $leftType->isInteger()->yes()) { $argType = $scope->getType($expr->right->getArgs()[0]->value); if ($argType instanceof UnionType) { $sizeType = null; if ($leftType instanceof ConstantIntegerType) { if ($orEqual) { $sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo($leftType->getValue()); } else { $sizeType = IntegerRangeType::createAllGreaterThan($leftType->getValue()); } } elseif ($leftType instanceof IntegerRangeType) { $sizeType = $leftType; } $narrowed = $this->narrowUnionByArraySize($expr->right, $argType, $sizeType, $context, $scope, $rootExpr); if ($narrowed !== null) { return $narrowed; } } if ($context->true() && IntegerRangeType::createAllGreaterThanOrEqualTo(1 - $offset)->isSuperTypeOf($leftType)->yes() || $context->false() && (new ConstantIntegerType(1 - $offset))->isSuperTypeOf($leftType)->yes()) { if ($context->truthy() && $argType->isArray()->maybe()) { $countables = []; if ($argType instanceof UnionType) { $countableInterface = new ObjectType(Countable::class); foreach ($argType->getTypes() as $innerType) { if ($innerType->isArray()->yes()) { $innerType = TypeCombinator::intersect(new NonEmptyArrayType(), $innerType); $countables[] = $innerType; } if (!$countableInterface->isSuperTypeOf($innerType)->yes()) { continue; } $countables[] = $innerType; } } if (count($countables) > 0) { $countableType = TypeCombinator::union(...$countables); return $this->create($expr->right->getArgs()[0]->value, $countableType, $context, \false, $scope, $rootExpr); } } if ($argType->isArray()->yes()) { $newType = new NonEmptyArrayType(); if ($context->true() && $argType->isList()->yes()) { $newType = AccessoryArrayListType::intersectWith($newType); } $result = $result->unionWith($this->create($expr->right->getArgs()[0]->value, $newType, $context, \false, $scope, $rootExpr)); } } } if (!$context->null() && $expr->right instanceof FuncCall && count($expr->right->getArgs()) >= 3 && $expr->right->name instanceof Name && in_array(strtolower((string) $expr->right->name), ['preg_match'], \true) && IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($leftType)->yes()) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\NotIdentical($expr->right, new ConstFetch(new Name('false'))), $context, $rootExpr); } if (!$context->null() && $expr->right instanceof FuncCall && count($expr->right->getArgs()) === 1 && $expr->right->name instanceof Name && in_array(strtolower((string) $expr->right->name), ['strlen', 'mb_strlen'], \true) && $leftType->isInteger()->yes()) { if ($context->true() && IntegerRangeType::createAllGreaterThanOrEqualTo(1 - $offset)->isSuperTypeOf($leftType)->yes() || $context->false() && (new ConstantIntegerType(1 - $offset))->isSuperTypeOf($leftType)->yes()) { $argType = $scope->getType($expr->right->getArgs()[0]->value); if ($argType->isString()->yes()) { $accessory = new AccessoryNonEmptyStringType(); if (IntegerRangeType::createAllGreaterThanOrEqualTo(2 - $offset)->isSuperTypeOf($leftType)->yes()) { $accessory = new AccessoryNonFalsyStringType(); } $result = $result->unionWith($this->create($expr->right->getArgs()[0]->value, $accessory, $context, \false, $scope, $rootExpr)); } } } if ($leftType instanceof ConstantIntegerType) { if ($expr->right instanceof Expr\PostInc) { $result = $result->unionWith($this->createRangeTypes($rootExpr, $expr->right->var, IntegerRangeType::fromInterval($leftType->getValue(), null, $offset + 1), $context)); } elseif ($expr->right instanceof Expr\PostDec) { $result = $result->unionWith($this->createRangeTypes($rootExpr, $expr->right->var, IntegerRangeType::fromInterval($leftType->getValue(), null, $offset - 1), $context)); } elseif ($expr->right instanceof Expr\PreInc || $expr->right instanceof Expr\PreDec) { $result = $result->unionWith($this->createRangeTypes($rootExpr, $expr->right->var, IntegerRangeType::fromInterval($leftType->getValue(), null, $offset), $context)); } } $rightType = $scope->getType($expr->right); if ($rightType instanceof ConstantIntegerType) { if ($expr->left instanceof Expr\PostInc) { $result = $result->unionWith($this->createRangeTypes($rootExpr, $expr->left->var, IntegerRangeType::fromInterval(null, $rightType->getValue(), -$offset + 1), $context)); } elseif ($expr->left instanceof Expr\PostDec) { $result = $result->unionWith($this->createRangeTypes($rootExpr, $expr->left->var, IntegerRangeType::fromInterval(null, $rightType->getValue(), -$offset - 1), $context)); } elseif ($expr->left instanceof Expr\PreInc || $expr->left instanceof Expr\PreDec) { $result = $result->unionWith($this->createRangeTypes($rootExpr, $expr->left->var, IntegerRangeType::fromInterval(null, $rightType->getValue(), -$offset), $context)); } } if ($context->true()) { if (!$expr->left instanceof Node\Scalar) { $result = $result->unionWith($this->create($expr->left, $orEqual ? $rightType->getSmallerOrEqualType() : $rightType->getSmallerType(), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), \false, $scope, $rootExpr)); } if (!$expr->right instanceof Node\Scalar) { $result = $result->unionWith($this->create($expr->right, $orEqual ? $leftType->getGreaterOrEqualType() : $leftType->getGreaterType(), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), \false, $scope, $rootExpr)); } } elseif ($context->false()) { if (!$expr->left instanceof Node\Scalar) { $result = $result->unionWith($this->create($expr->left, $orEqual ? $rightType->getGreaterType() : $rightType->getGreaterOrEqualType(), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), \false, $scope, $rootExpr)); } if (!$expr->right instanceof Node\Scalar) { $result = $result->unionWith($this->create($expr->right, $orEqual ? $leftType->getSmallerType() : $leftType->getSmallerOrEqualType(), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), \false, $scope, $rootExpr)); } } return $result; } elseif ($expr instanceof Node\Expr\BinaryOp\Greater) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Smaller($expr->right, $expr->left), $context, $rootExpr); } elseif ($expr instanceof Node\Expr\BinaryOp\GreaterOrEqual) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\SmallerOrEqual($expr->right, $expr->left), $context, $rootExpr); } elseif ($expr instanceof FuncCall && $expr->name instanceof Name) { if ($this->reflectionProvider->hasFunction($expr->name, $scope)) { $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); foreach ($this->getFunctionTypeSpecifyingExtensions() as $extension) { if (!$extension->isFunctionSupported($functionReflection, $expr, $context)) { continue; } return $extension->specifyTypes($functionReflection, $expr, $scope, $context); } // lazy create parametersAcceptor, as creation can be expensive $parametersAcceptor = null; if (count($expr->getArgs()) > 0) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $specifiedTypes = $this->specifyTypesFromConditionalReturnType($context, $expr, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } $assertions = $functionReflection->getAsserts(); if ($assertions->getAll() !== []) { $parametersAcceptor = $parametersAcceptor ?? ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $asserts = $assertions->mapTypes(static function (Type $type) use($parametersAcceptor) { return TemplateTypeHelper::resolveTemplateTypes($type, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant()); }); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } } return $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); } elseif ($expr instanceof MethodCall && $expr->name instanceof Node\Identifier) { $methodCalledOnType = $scope->getType($expr->var); $methodReflection = $scope->getMethodReflection($methodCalledOnType, $expr->name->name); if ($methodReflection !== null) { $referencedClasses = $methodCalledOnType->getObjectClassNames(); if (count($referencedClasses) === 1 && $this->reflectionProvider->hasClass($referencedClasses[0])) { $methodClassReflection = $this->reflectionProvider->getClass($referencedClasses[0]); foreach ($this->getMethodTypeSpecifyingExtensionsForClass($methodClassReflection->getName()) as $extension) { if (!$extension->isMethodSupported($methodReflection, $expr, $context)) { continue; } return $extension->specifyTypes($methodReflection, $expr, $scope, $context); } } // lazy create parametersAcceptor, as creation can be expensive $parametersAcceptor = null; if (count($expr->getArgs()) > 0) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); $specifiedTypes = $this->specifyTypesFromConditionalReturnType($context, $expr, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } $assertions = $methodReflection->getAsserts(); if ($assertions->getAll() !== []) { $parametersAcceptor = $parametersAcceptor ?? ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); $asserts = $assertions->mapTypes(static function (Type $type) use($parametersAcceptor) { return TemplateTypeHelper::resolveTemplateTypes($type, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant()); }); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } } return $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); } elseif ($expr instanceof StaticCall && $expr->name instanceof Node\Identifier) { if ($expr->class instanceof Name) { $calleeType = $scope->resolveTypeByName($expr->class); } else { $calleeType = $scope->getType($expr->class); } $staticMethodReflection = $scope->getMethodReflection($calleeType, $expr->name->name); if ($staticMethodReflection !== null) { $referencedClasses = $calleeType->getObjectClassNames(); if (count($referencedClasses) === 1 && $this->reflectionProvider->hasClass($referencedClasses[0])) { $staticMethodClassReflection = $this->reflectionProvider->getClass($referencedClasses[0]); foreach ($this->getStaticMethodTypeSpecifyingExtensionsForClass($staticMethodClassReflection->getName()) as $extension) { if (!$extension->isStaticMethodSupported($staticMethodReflection, $expr, $context)) { continue; } return $extension->specifyTypes($staticMethodReflection, $expr, $scope, $context); } } // lazy create parametersAcceptor, as creation can be expensive $parametersAcceptor = null; if (count($expr->getArgs()) > 0) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $staticMethodReflection->getVariants(), $staticMethodReflection->getNamedArgumentsVariants()); $specifiedTypes = $this->specifyTypesFromConditionalReturnType($context, $expr, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } $assertions = $staticMethodReflection->getAsserts(); if ($assertions->getAll() !== []) { $parametersAcceptor = $parametersAcceptor ?? ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $staticMethodReflection->getVariants(), $staticMethodReflection->getNamedArgumentsVariants()); $asserts = $assertions->mapTypes(static function (Type $type) use($parametersAcceptor) { return TemplateTypeHelper::resolveTemplateTypes($type, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant()); }); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } } return $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); } elseif ($expr instanceof BooleanAnd || $expr instanceof LogicalAnd) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } $leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr); $rightScope = $scope->filterByTruthyValue($expr->left); $rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr); $types = $context->true() ? $leftTypes->unionWith($rightTypes) : $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope)); if ($context->false()) { return new \PHPStan\Analyser\SpecifiedTypes($types->getSureTypes(), $types->getSureNotTypes(), \false, array_merge($this->processBooleanNotSureConditionalTypes($scope, $leftTypes, $rightTypes), $this->processBooleanNotSureConditionalTypes($scope, $rightTypes, $leftTypes), $this->processBooleanSureConditionalTypes($scope, $leftTypes, $rightTypes), $this->processBooleanSureConditionalTypes($scope, $rightTypes, $leftTypes)), $rootExpr); } return $types; } elseif ($expr instanceof BooleanOr || $expr instanceof LogicalOr) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } $leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr); $rightScope = $scope->filterByFalseyValue($expr->left); $rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr); $types = $context->true() ? $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope)) : $leftTypes->unionWith($rightTypes); if ($context->true()) { return new \PHPStan\Analyser\SpecifiedTypes($types->getSureTypes(), $types->getSureNotTypes(), \false, array_merge($this->processBooleanNotSureConditionalTypes($scope, $leftTypes, $rightTypes), $this->processBooleanNotSureConditionalTypes($scope, $rightTypes, $leftTypes), $this->processBooleanSureConditionalTypes($scope, $leftTypes, $rightTypes), $this->processBooleanSureConditionalTypes($scope, $rightTypes, $leftTypes)), $rootExpr); } return $types; } elseif ($expr instanceof Node\Expr\BooleanNot && !$context->null()) { return $this->specifyTypesInCondition($scope, $expr->expr, $context->negate(), $rootExpr); } elseif ($expr instanceof Node\Expr\Assign) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } if ($context->null()) { return $this->specifyTypesInCondition($scope->exitFirstLevelStatements(), $expr->expr, $context, $rootExpr); } return $this->specifyTypesInCondition($scope->exitFirstLevelStatements(), $expr->var, $context, $rootExpr); } elseif ($expr instanceof Expr\Isset_ && count($expr->vars) > 0 && !$context->null()) { // rewrite multi param isset() to and-chained single param isset() if (count($expr->vars) > 1) { $issets = []; foreach ($expr->vars as $var) { $issets[] = new Expr\Isset_([$var], $expr->getAttributes()); } $first = array_shift($issets); $andChain = null; foreach ($issets as $isset) { if ($andChain === null) { $andChain = new BooleanAnd($first, $isset); continue; } $andChain = new BooleanAnd($andChain, $isset); } if ($andChain === null) { throw new ShouldNotHappenException(); } return $this->specifyTypesInCondition($scope, $andChain, $context, $rootExpr); } $issetExpr = $expr->vars[0]; if (!$context->true()) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } $isset = $scope->issetCheck($issetExpr, static function () { return \true; }); if ($isset === \false) { return new \PHPStan\Analyser\SpecifiedTypes(); } $type = $scope->getType($issetExpr); $isNullable = !$type->isNull()->no(); $exprType = $this->create($issetExpr, new NullType(), $context->negate(), \false, $scope, $rootExpr); if ($issetExpr instanceof Expr\Variable && is_string($issetExpr->name)) { if ($isset === \true) { if ($isNullable) { return $exprType; } // variable cannot exist in !isset() return $exprType->unionWith($this->create(new IssetExpr($issetExpr), new NullType(), $context, \false, $scope, $rootExpr)); } if ($isNullable) { // reduces variable certainty to maybe return $exprType->unionWith($this->create(new IssetExpr($issetExpr), new NullType(), $context->negate(), \false, $scope, $rootExpr)); } // variable cannot exist in !isset() return $this->create(new IssetExpr($issetExpr), new NullType(), $context, \false, $scope, $rootExpr); } if ($isNullable && $isset === \true) { return $exprType; } return new \PHPStan\Analyser\SpecifiedTypes(); } $tmpVars = [$issetExpr]; while ($issetExpr instanceof ArrayDimFetch || $issetExpr instanceof PropertyFetch || $issetExpr instanceof StaticPropertyFetch && $issetExpr->class instanceof Expr) { if ($issetExpr instanceof StaticPropertyFetch) { /** @var Expr $issetExpr */ $issetExpr = $issetExpr->class; } else { $issetExpr = $issetExpr->var; } $tmpVars[] = $issetExpr; } $vars = array_reverse($tmpVars); $types = new \PHPStan\Analyser\SpecifiedTypes(); foreach ($vars as $var) { if ($var instanceof Expr\Variable && is_string($var->name)) { if ($scope->hasVariableType($var->name)->no()) { return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } } if ($var instanceof ArrayDimFetch && $var->dim !== null && !$scope->getType($var->var) instanceof MixedType) { $dimType = $scope->getType($var->dim); if ($dimType instanceof ConstantIntegerType || $dimType instanceof ConstantStringType) { $types = $types->unionWith($this->create($var->var, new HasOffsetType($dimType), $context, \false, $scope, $rootExpr)); } else { $varType = $scope->getType($var->var); $narrowedKey = AllowedArrayKeysTypes::narrowOffsetKeyType($varType, $dimType); if ($narrowedKey !== null) { $types = $types->unionWith($this->create($var->dim, $narrowedKey, $context, \false, $scope, $rootExpr)); } } } if ($var instanceof PropertyFetch && $var->name instanceof Node\Identifier) { $types = $types->unionWith($this->create($var->var, new IntersectionType([new ObjectWithoutClassType(), new HasPropertyType($var->name->toString())]), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), \false, $scope, $rootExpr)); } elseif ($var instanceof StaticPropertyFetch && $var->class instanceof Expr && $var->name instanceof Node\VarLikeIdentifier) { $types = $types->unionWith($this->create($var->class, new IntersectionType([new ObjectWithoutClassType(), new HasPropertyType($var->name->toString())]), \PHPStan\Analyser\TypeSpecifierContext::createTruthy(), \false, $scope, $rootExpr)); } $types = $types->unionWith($this->create($var, new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), \false, $scope, $rootExpr)); } return $types; } elseif ($expr instanceof Expr\BinaryOp\Coalesce && !$context->null()) { if (!$context->true()) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } $isset = $scope->issetCheck($expr->left, static function () { return \true; }); if ($isset !== \true) { return new \PHPStan\Analyser\SpecifiedTypes(); } return $this->create($expr->left, new NullType(), $context->negate(), \false, $scope, $rootExpr); } if ((new ConstantBooleanType(\false))->isSuperTypeOf($scope->getType($expr->right)->toBoolean())->yes()) { return $this->create($expr->left, new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), \false, $scope, $rootExpr); } } elseif ($expr instanceof Expr\Empty_) { if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { throw new ShouldNotHappenException(); } $isset = $scope->issetCheck($expr->expr, static function () { return \true; }); if ($isset === \false) { return new \PHPStan\Analyser\SpecifiedTypes(); } return $this->specifyTypesInCondition($scope, new BooleanOr(new Expr\BooleanNot(new Expr\Isset_([$expr->expr])), new Expr\BooleanNot($expr->expr)), $context, $rootExpr); } elseif ($expr instanceof Expr\ErrorSuppress) { return $this->specifyTypesInCondition($scope, $expr->expr, $context, $rootExpr); } elseif ($expr instanceof Expr\Ternary && !$context->null() && $scope->getType($expr->else)->isFalse()->yes()) { $conditionExpr = $expr->cond; if ($expr->if !== null) { $conditionExpr = new BooleanAnd($conditionExpr, $expr->if); } return $this->specifyTypesInCondition($scope, $conditionExpr, $context, $rootExpr); } elseif ($expr instanceof Expr\NullsafePropertyFetch && !$context->null()) { $types = $this->specifyTypesInCondition($scope, new BooleanAnd(new Expr\BinaryOp\NotIdentical($expr->var, new ConstFetch(new Name('null'))), new PropertyFetch($expr->var, $expr->name)), $context, $rootExpr); $nullSafeTypes = $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); return $context->true() ? $types->unionWith($nullSafeTypes) : $types->normalize($scope)->intersectWith($nullSafeTypes->normalize($scope)); } elseif ($expr instanceof Expr\NullsafeMethodCall && !$context->null()) { $types = $this->specifyTypesInCondition($scope, new BooleanAnd(new Expr\BinaryOp\NotIdentical($expr->var, new ConstFetch(new Name('null'))), new MethodCall($expr->var, $expr->name, $expr->args)), $context, $rootExpr); $nullSafeTypes = $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); return $context->true() ? $types->unionWith($nullSafeTypes) : $types->normalize($scope)->intersectWith($nullSafeTypes->normalize($scope)); } elseif ($expr instanceof Expr\New_ && $expr->class instanceof Name && $this->reflectionProvider->hasClass($expr->class->toString())) { $classReflection = $this->reflectionProvider->getClass($expr->class->toString()); if ($classReflection->hasConstructor()) { $methodReflection = $classReflection->getConstructor(); $asserts = $methodReflection->getAsserts(); if ($asserts->getAll() !== []) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); $asserts = $asserts->mapTypes(static function (Type $type) use($parametersAcceptor) { return TemplateTypeHelper::resolveTemplateTypes($type, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant()); }); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); if ($specifiedTypes !== null) { return $specifiedTypes; } } } } elseif (!$context->null()) { return $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); } return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } private function narrowUnionByArraySize(FuncCall $countFuncCall, UnionType $argType, ?Type $sizeType, \PHPStan\Analyser\TypeSpecifierContext $context, \PHPStan\Analyser\Scope $scope, ?Expr $rootExpr) : ?\PHPStan\Analyser\SpecifiedTypes { if ($sizeType === null) { return null; } if (count($countFuncCall->getArgs()) === 1) { $isNormalCount = TrinaryLogic::createYes(); } else { $mode = $scope->getType($countFuncCall->getArgs()[1]->value); $isNormalCount = (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->or($argType->getIterableValueType()->isArray()->negate()); } if ($isNormalCount->yes() && $argType->isConstantArray()->yes()) { $result = []; foreach ($argType->getTypes() as $innerType) { $arraySize = $innerType->getArraySize(); $isSize = $sizeType->isSuperTypeOf($arraySize); if ($context->truthy()) { if ($isSize->no()) { continue; } $constArray = $this->turnListIntoConstantArray($countFuncCall, $innerType, $sizeType, $scope); if ($constArray !== null) { $innerType = $constArray; } } if ($context->falsey()) { if (!$isSize->yes()) { continue; } } $result[] = $innerType; } return $this->create($countFuncCall->getArgs()[0]->value, TypeCombinator::union(...$result), $context, \false, $scope, $rootExpr); } return null; } private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type, Type $sizeType, \PHPStan\Analyser\Scope $scope) : ?Type { $argType = $scope->getType($countFuncCall->getArgs()[0]->value); if (count($countFuncCall->getArgs()) === 1) { $isNormalCount = TrinaryLogic::createYes(); } else { $mode = $scope->getType($countFuncCall->getArgs()[1]->value); $isNormalCount = (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->or($argType->getIterableValueType()->isArray()->negate()); } if ($isNormalCount->yes() && $type->isList()->yes() && $sizeType instanceof ConstantIntegerType && $sizeType->getValue() < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT) { // turn optional offsets non-optional $valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty(); for ($i = 0; $i < $sizeType->getValue(); $i++) { $offsetType = new ConstantIntegerType($i); $valueTypesBuilder->setOffsetValueType($offsetType, $type->getOffsetValueType($offsetType)); } return $valueTypesBuilder->getArray(); } if ($isNormalCount->yes() && $type->isList()->yes() && $sizeType instanceof IntegerRangeType && $sizeType->getMin() !== null) { // turn optional offsets non-optional $valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty(); for ($i = 0; $i < $sizeType->getMin(); $i++) { $offsetType = new ConstantIntegerType($i); $valueTypesBuilder->setOffsetValueType($offsetType, $type->getOffsetValueType($offsetType)); } if ($sizeType->getMax() !== null) { for ($i = $sizeType->getMin(); $i < $sizeType->getMax(); $i++) { $offsetType = new ConstantIntegerType($i); $valueTypesBuilder->setOffsetValueType($offsetType, $type->getOffsetValueType($offsetType), \true); } } elseif ($type->isConstantArray()->yes()) { for ($i = $sizeType->getMin();; $i++) { $offsetType = new ConstantIntegerType($i); $hasOffset = $type->hasOffsetValueType($offsetType); if ($hasOffset->no()) { break; } $valueTypesBuilder->setOffsetValueType($offsetType, $type->getOffsetValueType($offsetType), !$hasOffset->yes()); } } else { return null; } $arrayType = $valueTypesBuilder->getArray(); if ($arrayType->isIterableAtLeastOnce()->yes()) { return $arrayType; } } return null; } private function specifyTypesForConstantBinaryExpression(Expr $exprNode, Type $constantType, \PHPStan\Analyser\TypeSpecifierContext $context, \PHPStan\Analyser\Scope $scope, ?Expr $rootExpr) : ?\PHPStan\Analyser\SpecifiedTypes { if (!$context->null() && $constantType->isFalse()->yes()) { $types = $this->create($exprNode, $constantType, $context, \false, $scope, $rootExpr); if (!$context->true() && ($exprNode instanceof Expr\NullsafeMethodCall || $exprNode instanceof Expr\NullsafePropertyFetch)) { return $types; } return $types->unionWith($this->specifyTypesInCondition($scope, $exprNode, $context->true() ? \PHPStan\Analyser\TypeSpecifierContext::createFalse() : \PHPStan\Analyser\TypeSpecifierContext::createFalse()->negate(), $rootExpr)); } if (!$context->null() && $constantType->isTrue()->yes()) { $types = $this->create($exprNode, $constantType, $context, \false, $scope, $rootExpr); if (!$context->true() && ($exprNode instanceof Expr\NullsafeMethodCall || $exprNode instanceof Expr\NullsafePropertyFetch)) { return $types; } return $types->unionWith($this->specifyTypesInCondition($scope, $exprNode, $context->true() ? \PHPStan\Analyser\TypeSpecifierContext::createTrue() : \PHPStan\Analyser\TypeSpecifierContext::createTrue()->negate(), $rootExpr)); } return null; } private function specifyTypesForConstantStringBinaryExpression(Expr $exprNode, Type $constantType, \PHPStan\Analyser\TypeSpecifierContext $context, \PHPStan\Analyser\Scope $scope, ?Expr $rootExpr) : ?\PHPStan\Analyser\SpecifiedTypes { $scalarValues = $constantType->getConstantScalarValues(); if (count($scalarValues) !== 1 || !is_string($scalarValues[0])) { return null; } $constantStringValue = $scalarValues[0]; if ($exprNode instanceof FuncCall && $exprNode->name instanceof Name && strtolower($exprNode->name->toString()) === 'gettype' && isset($exprNode->getArgs()[0])) { $type = null; if ($constantStringValue === 'string') { $type = new StringType(); } if ($constantStringValue === 'array') { $type = new ArrayType(new MixedType(), new MixedType()); } if ($constantStringValue === 'boolean') { $type = new BooleanType(); } if (in_array($constantStringValue, ['resource', 'resource (closed)'], \true)) { $type = new ResourceType(); } if ($constantStringValue === 'integer') { $type = new IntegerType(); } if ($constantStringValue === 'double') { $type = new FloatType(); } if ($constantStringValue === 'NULL') { $type = new NullType(); } if ($constantStringValue === 'object') { $type = new ObjectWithoutClassType(); } if ($type !== null) { $callType = $this->create($exprNode, $constantType, $context, \false, $scope, $rootExpr); $argType = $this->create($exprNode->getArgs()[0]->value, $type, $context, \false, $scope, $rootExpr); return $callType->unionWith($argType); } } if ($context->true() && $exprNode instanceof FuncCall && $exprNode->name instanceof Name && strtolower((string) $exprNode->name) === 'get_parent_class' && isset($exprNode->getArgs()[0])) { $argType = $scope->getType($exprNode->getArgs()[0]->value); $objectType = new ObjectType($constantStringValue); $classStringType = new GenericClassStringType($objectType); if ($argType->isString()->yes()) { return $this->create($exprNode->getArgs()[0]->value, $classStringType, $context, \false, $scope); } if ($argType->isObject()->yes()) { return $this->create($exprNode->getArgs()[0]->value, $objectType, $context, \false, $scope); } return $this->create($exprNode->getArgs()[0]->value, TypeCombinator::union($objectType, $classStringType), $context, \false, $scope); } return null; } private function handleDefaultTruthyOrFalseyContext(\PHPStan\Analyser\TypeSpecifierContext $context, ?Expr $rootExpr, Expr $expr, \PHPStan\Analyser\Scope $scope) : \PHPStan\Analyser\SpecifiedTypes { if ($context->null()) { return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } if (!$context->truthy()) { $type = StaticTypeFactory::truthy(); return $this->create($expr, $type, \PHPStan\Analyser\TypeSpecifierContext::createFalse(), \false, $scope, $rootExpr); } elseif (!$context->falsey()) { $type = StaticTypeFactory::falsey(); return $this->create($expr, $type, \PHPStan\Analyser\TypeSpecifierContext::createFalse(), \false, $scope, $rootExpr); } return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } private function specifyTypesFromConditionalReturnType(\PHPStan\Analyser\TypeSpecifierContext $context, Expr\CallLike $call, ParametersAcceptor $parametersAcceptor, \PHPStan\Analyser\Scope $scope) : ?\PHPStan\Analyser\SpecifiedTypes { if (!$parametersAcceptor instanceof ResolvedFunctionVariant) { return null; } $returnType = $parametersAcceptor->getOriginalParametersAcceptor()->getReturnType(); if (!$returnType instanceof ConditionalTypeForParameter) { return null; } if ($context->true()) { $leftType = new ConstantBooleanType(\true); $rightType = new ConstantBooleanType(\false); } elseif ($context->false()) { $leftType = new ConstantBooleanType(\false); $rightType = new ConstantBooleanType(\true); } elseif ($context->null()) { $leftType = new MixedType(); $rightType = new NeverType(); } else { return null; } $argsMap = []; $parameters = $parametersAcceptor->getParameters(); foreach ($call->getArgs() as $i => $arg) { if ($arg->unpack) { continue; } if ($arg->name !== null) { $paramName = $arg->name->toString(); } elseif (isset($parameters[$i])) { $paramName = $parameters[$i]->getName(); } else { continue; } $argsMap['$' . $paramName] = $arg->value; } return $this->getConditionalSpecifiedTypes($returnType, $leftType, $rightType, $scope, $argsMap); } /** * @param array $argsMap */ public function getConditionalSpecifiedTypes(ConditionalTypeForParameter $conditionalType, Type $leftType, Type $rightType, \PHPStan\Analyser\Scope $scope, array $argsMap) : ?\PHPStan\Analyser\SpecifiedTypes { $parameterName = $conditionalType->getParameterName(); if (!array_key_exists($parameterName, $argsMap)) { return null; } $targetType = $conditionalType->getTarget(); $ifType = $conditionalType->getIf(); $elseType = $conditionalType->getElse(); if ($leftType->isSuperTypeOf($ifType)->yes() && $rightType->isSuperTypeOf($elseType)->yes()) { $context = $conditionalType->isNegated() ? \PHPStan\Analyser\TypeSpecifierContext::createFalse() : \PHPStan\Analyser\TypeSpecifierContext::createTrue(); } elseif ($leftType->isSuperTypeOf($elseType)->yes() && $rightType->isSuperTypeOf($ifType)->yes()) { $context = $conditionalType->isNegated() ? \PHPStan\Analyser\TypeSpecifierContext::createTrue() : \PHPStan\Analyser\TypeSpecifierContext::createFalse(); } else { return null; } $specifiedTypes = $this->create($argsMap[$parameterName], $targetType, $context, \false, $scope); if ($targetType instanceof ConstantBooleanType) { if (!$targetType->getValue()) { $context = $context->negate(); } $specifiedTypes = $specifiedTypes->unionWith($this->specifyTypesInCondition($scope, $argsMap[$parameterName], $context)); } return $specifiedTypes; } private function specifyTypesFromAsserts(\PHPStan\Analyser\TypeSpecifierContext $context, Expr\CallLike $call, Assertions $assertions, ParametersAcceptor $parametersAcceptor, \PHPStan\Analyser\Scope $scope) : ?\PHPStan\Analyser\SpecifiedTypes { if ($context->null()) { $asserts = $assertions->getAsserts(); } elseif ($context->true()) { $asserts = $assertions->getAssertsIfTrue(); } elseif ($context->false()) { $asserts = $assertions->getAssertsIfFalse(); } else { throw new ShouldNotHappenException(); } if (count($asserts) === 0) { return null; } $argsMap = []; $parameters = $parametersAcceptor->getParameters(); foreach ($call->getArgs() as $i => $arg) { if ($arg->unpack) { continue; } if ($arg->name !== null) { $paramName = $arg->name->toString(); } elseif (isset($parameters[$i])) { $paramName = $parameters[$i]->getName(); } elseif (count($parameters) > 0 && $parametersAcceptor->isVariadic()) { $lastParameter = $parameters[count($parameters) - 1]; $paramName = $lastParameter->getName(); } else { continue; } $argsMap[$paramName][] = $arg->value; } if ($call instanceof MethodCall) { $argsMap['this'] = [$call->var]; } /** @var SpecifiedTypes|null $types */ $types = null; foreach ($asserts as $assert) { foreach ($argsMap[substr($assert->getParameter()->getParameterName(), 1)] ?? [] as $parameterExpr) { $assertedType = TypeTraverser::map($assert->getType(), static function (Type $type, callable $traverse) use($argsMap, $scope) : Type { if ($type instanceof ConditionalTypeForParameter) { $parameterName = substr($type->getParameterName(), 1); if (array_key_exists($parameterName, $argsMap)) { $argType = TypeCombinator::union(...array_map(static function (Expr $expr) use($scope) { return $scope->getType($expr); }, $argsMap[$parameterName])); $type = $type->toConditional($argType); } } return $traverse($type); }); $assertExpr = $assert->getParameter()->getExpr($parameterExpr); $templateTypeMap = $parametersAcceptor->getResolvedTemplateTypeMap(); $containsUnresolvedTemplate = \false; TypeTraverser::map($assert->getOriginalType(), static function (Type $type, callable $traverse) use($templateTypeMap, &$containsUnresolvedTemplate) { if ($type instanceof TemplateType && $type->getScope()->getClassName() !== null) { $resolvedType = $templateTypeMap->getType($type->getName()); if ($resolvedType === null || $type->getBound()->equals($resolvedType)) { $containsUnresolvedTemplate = \true; return $type; } } return $traverse($type); }); $newTypes = $this->create($assertExpr, $assertedType, $assert->isNegated() ? \PHPStan\Analyser\TypeSpecifierContext::createFalse() : \PHPStan\Analyser\TypeSpecifierContext::createTrue(), \false, $scope, $containsUnresolvedTemplate || $assert->isEquality() ? $call : null); $types = $types !== null ? $types->unionWith($newTypes) : $newTypes; if (!$context->null() || !$assertedType instanceof ConstantBooleanType) { continue; } $subContext = $assertedType->getValue() ? \PHPStan\Analyser\TypeSpecifierContext::createTrue() : \PHPStan\Analyser\TypeSpecifierContext::createFalse(); if ($assert->isNegated()) { $subContext = $subContext->negate(); } $types = $types->unionWith($this->specifyTypesInCondition($scope, $assertExpr, $subContext)); } } return $types; } /** * @return array */ private function processBooleanSureConditionalTypes(\PHPStan\Analyser\Scope $scope, \PHPStan\Analyser\SpecifiedTypes $leftTypes, \PHPStan\Analyser\SpecifiedTypes $rightTypes) : array { $conditionExpressionTypes = []; foreach ($leftTypes->getSureTypes() as $exprString => [$expr, $type]) { if (!$expr instanceof Expr\Variable) { continue; } if (!is_string($expr->name)) { continue; } $conditionExpressionTypes[$exprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($expr, TypeCombinator::remove($scope->getType($expr), $type)); } if (count($conditionExpressionTypes) > 0) { $holders = []; foreach ($rightTypes->getSureTypes() as $exprString => [$expr, $type]) { if (!$expr instanceof Expr\Variable) { continue; } if (!is_string($expr->name)) { continue; } if (!isset($holders[$exprString])) { $holders[$exprString] = []; } $conditions = $conditionExpressionTypes; foreach ($conditions as $conditionExprString => $conditionExprTypeHolder) { $conditionExpr = $conditionExprTypeHolder->getExpr(); if (!$conditionExpr instanceof Expr\Variable) { continue; } if (!is_string($conditionExpr->name)) { continue; } if ($conditionExpr->name !== $expr->name) { continue; } unset($conditions[$conditionExprString]); } if (count($conditions) === 0) { continue; } $holder = new \PHPStan\Analyser\ConditionalExpressionHolder($conditions, new \PHPStan\Analyser\ExpressionTypeHolder($expr, TypeCombinator::intersect($scope->getType($expr), $type), TrinaryLogic::createYes())); $holders[$exprString][$holder->getKey()] = $holder; } return $holders; } return []; } /** * @return array */ private function processBooleanNotSureConditionalTypes(\PHPStan\Analyser\Scope $scope, \PHPStan\Analyser\SpecifiedTypes $leftTypes, \PHPStan\Analyser\SpecifiedTypes $rightTypes) : array { $conditionExpressionTypes = []; foreach ($leftTypes->getSureNotTypes() as $exprString => [$expr, $type]) { if (!$expr instanceof Expr\Variable) { continue; } if (!is_string($expr->name)) { continue; } $conditionExpressionTypes[$exprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($expr, TypeCombinator::intersect($scope->getType($expr), $type)); } if (count($conditionExpressionTypes) > 0) { $holders = []; foreach ($rightTypes->getSureNotTypes() as $exprString => [$expr, $type]) { if (!$expr instanceof Expr\Variable) { continue; } if (!is_string($expr->name)) { continue; } if (!isset($holders[$exprString])) { $holders[$exprString] = []; } $conditions = $conditionExpressionTypes; foreach ($conditions as $conditionExprString => $conditionExprTypeHolder) { $conditionExpr = $conditionExprTypeHolder->getExpr(); if (!$conditionExpr instanceof Expr\Variable) { continue; } if (!is_string($conditionExpr->name)) { continue; } if ($conditionExpr->name !== $expr->name) { continue; } unset($conditions[$conditionExprString]); } if (count($conditions) === 0) { continue; } $holder = new \PHPStan\Analyser\ConditionalExpressionHolder($conditions, new \PHPStan\Analyser\ExpressionTypeHolder($expr, TypeCombinator::remove($scope->getType($expr), $type), TrinaryLogic::createYes())); $holders[$exprString][$holder->getKey()] = $holder; } return $holders; } return []; } /** * @return array{Expr, ConstantScalarType, Type}|null */ private function findTypeExpressionsFromBinaryOperation(\PHPStan\Analyser\Scope $scope, Node\Expr\BinaryOp $binaryOperation) : ?array { $leftType = $scope->getType($binaryOperation->left); $rightType = $scope->getType($binaryOperation->right); $rightExpr = $binaryOperation->right; if ($rightExpr instanceof AlwaysRememberedExpr) { $rightExpr = $rightExpr->getExpr(); } $leftExpr = $binaryOperation->left; if ($leftExpr instanceof AlwaysRememberedExpr) { $leftExpr = $leftExpr->getExpr(); } if ($leftType instanceof ConstantScalarType && !$rightExpr instanceof ConstFetch && !$rightExpr instanceof ClassConstFetch) { return [$binaryOperation->right, $leftType, $rightType]; } elseif ($rightType instanceof ConstantScalarType && !$leftExpr instanceof ConstFetch && !$leftExpr instanceof ClassConstFetch) { return [$binaryOperation->left, $rightType, $leftType]; } return null; } /** @api */ public function create(Expr $expr, Type $type, \PHPStan\Analyser\TypeSpecifierContext $context, bool $overwrite = \false, ?\PHPStan\Analyser\Scope $scope = null, ?Expr $rootExpr = null) : \PHPStan\Analyser\SpecifiedTypes { if ($expr instanceof Instanceof_ || $expr instanceof Expr\List_) { return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } $specifiedExprs = []; if ($expr instanceof AlwaysRememberedExpr) { $specifiedExprs[] = $expr; $expr = $expr->expr; } if ($expr instanceof Expr\Assign) { $specifiedExprs[] = $expr->var; $specifiedExprs[] = $expr->expr; while ($expr->expr instanceof Expr\Assign) { $specifiedExprs[] = $expr->expr->var; $expr = $expr->expr; } } elseif ($expr instanceof Expr\AssignOp\Coalesce) { $specifiedExprs[] = $expr->var; } else { $specifiedExprs[] = $expr; } $types = null; foreach ($specifiedExprs as $specifiedExpr) { $newTypes = $this->createForExpr($specifiedExpr, $type, $context, $overwrite, $scope, $rootExpr); if ($types === null) { $types = $newTypes; } else { $types = $types->unionWith($newTypes); } } return $types; } private function createForExpr(Expr $expr, Type $type, \PHPStan\Analyser\TypeSpecifierContext $context, bool $overwrite = \false, ?\PHPStan\Analyser\Scope $scope = null, ?Expr $rootExpr = null) : \PHPStan\Analyser\SpecifiedTypes { if ($scope !== null) { if ($context->true()) { $containsNull = !$type->isNull()->no() && !$scope->getType($expr)->isNull()->no(); } elseif ($context->false()) { $containsNull = !TypeCombinator::containsNull($type) && !$scope->getType($expr)->isNull()->no(); } } $originalExpr = $expr; if (isset($containsNull) && !$containsNull) { $expr = \PHPStan\Analyser\NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($expr); } if ($scope !== null && !$context->null() && $expr instanceof Expr\BinaryOp\Coalesce) { $rightIsSuperType = $type->isSuperTypeOf($scope->getType($expr->right)); if ($context->true() && $rightIsSuperType->no() || $context->false() && $rightIsSuperType->yes()) { $expr = $expr->left; } } if ($expr instanceof FuncCall && $expr->name instanceof Name) { $has = $this->reflectionProvider->hasFunction($expr->name, $scope); if (!$has) { // backwards compatibility with previous behaviour return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); $hasSideEffects = $functionReflection->hasSideEffects(); if ($hasSideEffects->yes()) { return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } if (!$this->rememberPossiblyImpureFunctionValues && !$hasSideEffects->no()) { return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } } if ($expr instanceof MethodCall && $expr->name instanceof Node\Identifier && $scope !== null) { $methodName = $expr->name->toString(); $calledOnType = $scope->getType($expr->var); $methodReflection = $scope->getMethodReflection($calledOnType, $methodName); if ($methodReflection === null || $methodReflection->hasSideEffects()->yes() || !$this->rememberPossiblyImpureFunctionValues && !$methodReflection->hasSideEffects()->no()) { if (isset($containsNull) && !$containsNull) { return $this->createNullsafeTypes($rootExpr, $originalExpr, $scope, $context, $overwrite, $type); } return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } } if ($expr instanceof StaticCall && $expr->name instanceof Node\Identifier && $scope !== null) { $methodName = $expr->name->toString(); if ($expr->class instanceof Name) { $calledOnType = $scope->resolveTypeByName($expr->class); } else { $calledOnType = $scope->getType($expr->class); } $methodReflection = $scope->getMethodReflection($calledOnType, $methodName); if ($methodReflection === null || $methodReflection->hasSideEffects()->yes() || !$this->rememberPossiblyImpureFunctionValues && !$methodReflection->hasSideEffects()->no()) { if (isset($containsNull) && !$containsNull) { return $this->createNullsafeTypes($rootExpr, $originalExpr, $scope, $context, $overwrite, $type); } return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } } $sureTypes = []; $sureNotTypes = []; $exprString = $this->exprPrinter->printExpr($expr); $originalExprString = $this->exprPrinter->printExpr($originalExpr); if ($context->false()) { $sureNotTypes[$exprString] = [$expr, $type]; if ($exprString !== $originalExprString) { $sureNotTypes[$originalExprString] = [$originalExpr, $type]; } } elseif ($context->true()) { $sureTypes[$exprString] = [$expr, $type]; if ($exprString !== $originalExprString) { $sureTypes[$originalExprString] = [$originalExpr, $type]; } } $types = new \PHPStan\Analyser\SpecifiedTypes($sureTypes, $sureNotTypes, $overwrite, [], $rootExpr); if ($scope !== null && isset($containsNull) && !$containsNull) { return $this->createNullsafeTypes($rootExpr, $originalExpr, $scope, $context, $overwrite, $type)->unionWith($types); } return $types; } private function createNullsafeTypes(?Expr $rootExpr, Expr $expr, \PHPStan\Analyser\Scope $scope, \PHPStan\Analyser\TypeSpecifierContext $context, bool $overwrite, ?Type $type) : \PHPStan\Analyser\SpecifiedTypes { if ($expr instanceof Expr\NullsafePropertyFetch) { if ($type !== null) { $propertyFetchTypes = $this->create(new PropertyFetch($expr->var, $expr->name), $type, $context, \false, $scope, $rootExpr); } else { $propertyFetchTypes = $this->create(new PropertyFetch($expr->var, $expr->name), new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), \false, $scope, $rootExpr); } return $propertyFetchTypes->unionWith($this->create($expr->var, new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $overwrite, $scope, $rootExpr)); } if ($expr instanceof Expr\NullsafeMethodCall) { if ($type !== null) { $methodCallTypes = $this->create(new MethodCall($expr->var, $expr->name, $expr->args), $type, $context, $overwrite, $scope, $rootExpr); } else { $methodCallTypes = $this->create(new MethodCall($expr->var, $expr->name, $expr->args), new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $overwrite, $scope, $rootExpr); } return $methodCallTypes->unionWith($this->create($expr->var, new NullType(), \PHPStan\Analyser\TypeSpecifierContext::createFalse(), $overwrite, $scope, $rootExpr)); } if ($expr instanceof Expr\PropertyFetch) { return $this->createNullsafeTypes($rootExpr, $expr->var, $scope, $context, $overwrite, null); } if ($expr instanceof Expr\MethodCall) { return $this->createNullsafeTypes($rootExpr, $expr->var, $scope, $context, $overwrite, null); } if ($expr instanceof Expr\ArrayDimFetch) { return $this->createNullsafeTypes($rootExpr, $expr->var, $scope, $context, $overwrite, null); } if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) { return $this->createNullsafeTypes($rootExpr, $expr->class, $scope, $context, $overwrite, null); } if ($expr instanceof Expr\StaticCall && $expr->class instanceof Expr) { return $this->createNullsafeTypes($rootExpr, $expr->class, $scope, $context, $overwrite, null); } return new \PHPStan\Analyser\SpecifiedTypes([], [], $overwrite, [], $rootExpr); } private function createRangeTypes(?Expr $rootExpr, Expr $expr, Type $type, \PHPStan\Analyser\TypeSpecifierContext $context) : \PHPStan\Analyser\SpecifiedTypes { $sureNotTypes = []; if ($type instanceof IntegerRangeType || $type instanceof ConstantIntegerType) { $exprString = $this->exprPrinter->printExpr($expr); if ($context->false()) { $sureNotTypes[$exprString] = [$expr, $type]; } elseif ($context->true()) { $inverted = TypeCombinator::remove(new IntegerType(), $type); $sureNotTypes[$exprString] = [$expr, $inverted]; } } return new \PHPStan\Analyser\SpecifiedTypes([], $sureNotTypes, \false, [], $rootExpr); } /** * @return FunctionTypeSpecifyingExtension[] */ private function getFunctionTypeSpecifyingExtensions() : array { return $this->functionTypeSpecifyingExtensions; } /** * @return MethodTypeSpecifyingExtension[] */ private function getMethodTypeSpecifyingExtensionsForClass(string $className) : array { if ($this->methodTypeSpecifyingExtensionsByClass === null) { $byClass = []; foreach ($this->methodTypeSpecifyingExtensions as $extension) { $byClass[$extension->getClass()][] = $extension; } $this->methodTypeSpecifyingExtensionsByClass = $byClass; } return $this->getTypeSpecifyingExtensionsForType($this->methodTypeSpecifyingExtensionsByClass, $className); } /** * @return StaticMethodTypeSpecifyingExtension[] */ private function getStaticMethodTypeSpecifyingExtensionsForClass(string $className) : array { if ($this->staticMethodTypeSpecifyingExtensionsByClass === null) { $byClass = []; foreach ($this->staticMethodTypeSpecifyingExtensions as $extension) { $byClass[$extension->getClass()][] = $extension; } $this->staticMethodTypeSpecifyingExtensionsByClass = $byClass; } return $this->getTypeSpecifyingExtensionsForType($this->staticMethodTypeSpecifyingExtensionsByClass, $className); } /** * @param MethodTypeSpecifyingExtension[][]|StaticMethodTypeSpecifyingExtension[][] $extensions * @return mixed[] */ private function getTypeSpecifyingExtensionsForType(array $extensions, string $className) : array { $extensionsForClass = [[]]; $class = $this->reflectionProvider->getClass($className); foreach (array_merge([$className], $class->getParentClassesNames(), $class->getNativeReflection()->getInterfaceNames()) as $extensionClassName) { if (!isset($extensions[$extensionClassName])) { continue; } $extensionsForClass[] = $extensions[$extensionClassName]; } return array_merge(...$extensionsForClass); } public function resolveEqual(Expr\BinaryOp\Equal $expr, \PHPStan\Analyser\Scope $scope, \PHPStan\Analyser\TypeSpecifierContext $context, ?Expr $rootExpr) : \PHPStan\Analyser\SpecifiedTypes { $expressions = $this->findTypeExpressionsFromBinaryOperation($scope, $expr); if ($expressions !== null) { $exprNode = $expressions[0]; $constantType = $expressions[1]; $otherType = $expressions[2]; if (!$context->null() && $constantType->getValue() === null) { $trueTypes = [new NullType(), new ConstantBooleanType(\false), new ConstantIntegerType(0), new ConstantFloatType(0.0), new ConstantStringType(''), new ConstantArrayType([], [])]; return $this->create($exprNode, new UnionType($trueTypes), $context, \false, $scope, $rootExpr); } if (!$context->null() && $constantType->getValue() === \false) { return $this->specifyTypesInCondition($scope, $exprNode, $context->true() ? \PHPStan\Analyser\TypeSpecifierContext::createFalsey() : \PHPStan\Analyser\TypeSpecifierContext::createFalsey()->negate(), $rootExpr); } if (!$context->null() && $constantType->getValue() === \true) { return $this->specifyTypesInCondition($scope, $exprNode, $context->true() ? \PHPStan\Analyser\TypeSpecifierContext::createTruthy() : \PHPStan\Analyser\TypeSpecifierContext::createTruthy()->negate(), $rootExpr); } if (!$context->null() && $constantType->getValue() === 0 && !$otherType->isInteger()->yes() && !$otherType->isBoolean()->yes()) { /* There is a difference between php 7.x and 8.x on the equality * behavior between zero and the empty string, so to be conservative * we leave it untouched regardless of the language version */ if ($context->true()) { $trueTypes = [new NullType(), new ConstantBooleanType(\false), new ConstantIntegerType(0), new ConstantFloatType(0.0), new StringType()]; } else { $trueTypes = [new NullType(), new ConstantBooleanType(\false), new ConstantIntegerType(0), new ConstantFloatType(0.0), new ConstantStringType('0')]; } return $this->create($exprNode, new UnionType($trueTypes), $context, \false, $scope, $rootExpr); } if (!$context->null() && $constantType->getValue() === '') { /* There is a difference between php 7.x and 8.x on the equality * behavior between zero and the empty string, so to be conservative * we leave it untouched regardless of the language version */ if ($context->true()) { $trueTypes = [new NullType(), new ConstantBooleanType(\false), new ConstantIntegerType(0), new ConstantFloatType(0.0), new ConstantStringType('')]; } else { $trueTypes = [new NullType(), new ConstantBooleanType(\false), new ConstantStringType('')]; } return $this->create($exprNode, new UnionType($trueTypes), $context, \false, $scope, $rootExpr); } if ($exprNode instanceof FuncCall && $exprNode->name instanceof Name && in_array(strtolower($exprNode->name->toString()), ['gettype', 'get_class', 'get_debug_type'], \true) && isset($exprNode->getArgs()[0]) && $constantType->isString()->yes()) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context, $rootExpr); } if ($context->true() && $exprNode instanceof FuncCall && $exprNode->name instanceof Name && $exprNode->name->toLowerString() === 'preg_match' && (new ConstantIntegerType(1))->isSuperTypeOf($constantType)->yes()) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context, $rootExpr); } } $leftType = $scope->getType($expr->left); $rightType = $scope->getType($expr->right); $leftBooleanType = $leftType->toBoolean(); if ($leftBooleanType instanceof ConstantBooleanType && $rightType->isBoolean()->yes()) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical(new ConstFetch(new Name($leftBooleanType->getValue() ? 'true' : 'false')), $expr->right), $context, $rootExpr); } $rightBooleanType = $rightType->toBoolean(); if ($rightBooleanType instanceof ConstantBooleanType && $leftType->isBoolean()->yes()) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, new ConstFetch(new Name($rightBooleanType->getValue() ? 'true' : 'false'))), $context, $rootExpr); } if (!$context->null() && $rightType->isArray()->yes() && $leftType->isConstantArray()->yes() && $leftType->isIterableAtLeastOnce()->no()) { return $this->create($expr->right, new NonEmptyArrayType(), $context->negate(), \false, $scope, $rootExpr); } if (!$context->null() && $leftType->isArray()->yes() && $rightType->isConstantArray()->yes() && $rightType->isIterableAtLeastOnce()->no()) { return $this->create($expr->left, new NonEmptyArrayType(), $context->negate(), \false, $scope, $rootExpr); } if ($leftType->isString()->yes() && $rightType->isString()->yes() || $leftType->isInteger()->yes() && $rightType->isInteger()->yes() || $leftType->isFloat()->yes() && $rightType->isFloat()->yes() || $leftType->isEnum()->yes() && $rightType->isEnum()->yes()) { return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context, $rootExpr); } $leftExprString = $this->exprPrinter->printExpr($expr->left); $rightExprString = $this->exprPrinter->printExpr($expr->right); if ($leftExprString === $rightExprString) { if (!$expr->left instanceof Expr\Variable || !$expr->right instanceof Expr\Variable) { return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } } $leftTypes = $this->create($expr->left, $leftType, $context, \false, $scope, $rootExpr); $rightTypes = $this->create($expr->right, $rightType, $context, \false, $scope, $rootExpr); return $context->true() ? $leftTypes->unionWith($rightTypes) : $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($scope)); } public function resolveIdentical(Expr\BinaryOp\Identical $expr, \PHPStan\Analyser\Scope $scope, \PHPStan\Analyser\TypeSpecifierContext $context, ?Expr $rootExpr) : \PHPStan\Analyser\SpecifiedTypes { // Normalize to: fn() === expr $leftExpr = $expr->left; $rightExpr = $expr->right; if ($rightExpr instanceof FuncCall && !$leftExpr instanceof FuncCall) { [$leftExpr, $rightExpr] = [$rightExpr, $leftExpr]; } $unwrappedLeftExpr = $leftExpr; if ($leftExpr instanceof AlwaysRememberedExpr) { $unwrappedLeftExpr = $leftExpr->getExpr(); } $unwrappedRightExpr = $rightExpr; if ($rightExpr instanceof AlwaysRememberedExpr) { $unwrappedRightExpr = $rightExpr->getExpr(); } $rightType = $scope->getType($rightExpr); // (count($a) === $b) if (!$context->null() && $unwrappedLeftExpr instanceof FuncCall && count($unwrappedLeftExpr->getArgs()) >= 1 && $unwrappedLeftExpr->name instanceof Name && in_array(strtolower((string) $unwrappedLeftExpr->name), ['count', 'sizeof'], \true) && $rightType->isInteger()->yes()) { if (IntegerRangeType::fromInterval(null, -1)->isSuperTypeOf($rightType)->yes()) { return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, \false, $scope, $rootExpr); } $argType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value); $isZero = (new ConstantIntegerType(0))->isSuperTypeOf($rightType); if ($isZero->yes()) { $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, \false, $scope, $rootExpr); if ($context->truthy() && !$argType->isArray()->yes()) { $newArgType = new UnionType([new ObjectType(Countable::class), new ConstantArrayType([], [])]); } else { $newArgType = new ConstantArrayType([], []); } return $funcTypes->unionWith($this->create($unwrappedLeftExpr->getArgs()[0]->value, $newArgType, $context, \false, $scope, $rootExpr)); } if ($argType instanceof UnionType) { $narrowed = $this->narrowUnionByArraySize($unwrappedLeftExpr, $argType, $rightType, $context, $scope, $rootExpr); if ($narrowed !== null) { return $narrowed; } } if ($context->truthy()) { if ($argType->isArray()->yes()) { if ($argType->isConstantArray()->yes() && $rightType->isSuperTypeOf($argType->getArraySize())->no()) { return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, \false, $scope, $rootExpr); } $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, \false, $scope, $rootExpr); $constArray = $this->turnListIntoConstantArray($unwrappedLeftExpr, $argType, $rightType, $scope); if ($constArray !== null) { return $funcTypes->unionWith($this->create($unwrappedLeftExpr->getArgs()[0]->value, $constArray, $context, \false, $scope, $rootExpr)); } elseif (IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($rightType)->yes()) { return $funcTypes->unionWith($this->create($unwrappedLeftExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context, \false, $scope, $rootExpr)); } return $funcTypes; } } } // strlen($a) === $b if (!$context->null() && $unwrappedLeftExpr instanceof FuncCall && count($unwrappedLeftExpr->getArgs()) === 1 && $unwrappedLeftExpr->name instanceof Name && in_array(strtolower((string) $unwrappedLeftExpr->name), ['strlen', 'mb_strlen'], \true) && $rightType->isInteger()->yes()) { if (IntegerRangeType::fromInterval(null, -1)->isSuperTypeOf($rightType)->yes()) { return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, \false, $scope, $rootExpr); } $isZero = (new ConstantIntegerType(0))->isSuperTypeOf($rightType); if ($isZero->yes()) { $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, \false, $scope, $rootExpr); return $funcTypes->unionWith($this->create($unwrappedLeftExpr->getArgs()[0]->value, new ConstantStringType(''), $context, \false, $scope, $rootExpr)); } if ($context->truthy() && IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($rightType)->yes()) { $argType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value); if ($argType->isString()->yes()) { $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, \false, $scope, $rootExpr); $accessory = new AccessoryNonEmptyStringType(); if (IntegerRangeType::fromInterval(2, null)->isSuperTypeOf($rightType)->yes()) { $accessory = new AccessoryNonFalsyStringType(); } $valueTypes = $this->create($unwrappedLeftExpr->getArgs()[0]->value, $accessory, $context, \false, $scope, $rootExpr); return $funcTypes->unionWith($valueTypes); } } } // preg_match($a) === $b if ($context->true() && $unwrappedLeftExpr instanceof FuncCall && $unwrappedLeftExpr->name instanceof Name && $unwrappedLeftExpr->name->toLowerString() === 'preg_match' && (new ConstantIntegerType(1))->isSuperTypeOf($rightType)->yes()) { return $this->specifyTypesInCondition($scope, $leftExpr, $context, $rootExpr); } // get_class($a) === 'Foo' if ($context->true() && $unwrappedLeftExpr instanceof FuncCall && $unwrappedLeftExpr->name instanceof Name && in_array(strtolower($unwrappedLeftExpr->name->toString()), ['get_class', 'get_debug_type'], \true) && isset($unwrappedLeftExpr->getArgs()[0])) { if ($rightType->getClassStringObjectType()->isObject()->yes()) { return $this->create($unwrappedLeftExpr->getArgs()[0]->value, $rightType->getClassStringObjectType(), $context, \false, $scope, $rootExpr)->unionWith($this->create($leftExpr, $rightType, $context, \false, $scope, $rootExpr)); } } // get_class($a) === 'Foo' if ($context->truthy() && $unwrappedLeftExpr instanceof FuncCall && $unwrappedLeftExpr->name instanceof Name && in_array(strtolower($unwrappedLeftExpr->name->toString()), ['substr', 'strstr', 'stristr', 'strchr', 'strrchr', 'strtolower', 'strtoupper', 'ucfirst', 'lcfirst', 'mb_substr', 'mb_strstr', 'mb_stristr', 'mb_strchr', 'mb_strrchr', 'mb_strtolower', 'mb_strtoupper', 'mb_ucfirst', 'mb_lcfirst', 'ucwords', 'mb_convert_case', 'mb_convert_kana'], \true) && isset($unwrappedLeftExpr->getArgs()[0]) && $rightType->isNonEmptyString()->yes()) { $argType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value); if ($argType->isString()->yes()) { if ($rightType->isNonFalsyString()->yes()) { return $this->create($unwrappedLeftExpr->getArgs()[0]->value, TypeCombinator::intersect($argType, new AccessoryNonFalsyStringType()), $context, \false, $scope); } return $this->create($unwrappedLeftExpr->getArgs()[0]->value, TypeCombinator::intersect($argType, new AccessoryNonEmptyStringType()), $context, \false, $scope); } } if ($rightType->isString()->yes()) { $types = null; foreach ($rightType->getConstantStrings() as $constantString) { $specifiedType = $this->specifyTypesForConstantStringBinaryExpression($unwrappedLeftExpr, $constantString, $context, $scope, $rootExpr); if ($specifiedType === null) { continue; } if ($types === null) { $types = $specifiedType; continue; } $types = $types->intersectWith($specifiedType); } if ($types !== null) { if ($leftExpr !== $unwrappedLeftExpr) { $types = $types->unionWith($this->create($leftExpr, $rightType, $context, \false, $scope, $rootExpr)); } return $types; } } $expressions = $this->findTypeExpressionsFromBinaryOperation($scope, $expr); if ($expressions !== null) { $exprNode = $expressions[0]; $constantType = $expressions[1]; $unwrappedExprNode = $exprNode; if ($exprNode instanceof AlwaysRememberedExpr) { $unwrappedExprNode = $exprNode->getExpr(); } $specifiedType = $this->specifyTypesForConstantBinaryExpression($unwrappedExprNode, $constantType, $context, $scope, $rootExpr); if ($specifiedType !== null) { if ($exprNode !== $unwrappedExprNode) { $specifiedType = $specifiedType->unionWith($this->create($exprNode, $constantType, $context, \false, $scope, $rootExpr)); } return $specifiedType; } } // $a::class === 'Foo' if ($context->true() && $unwrappedLeftExpr instanceof ClassConstFetch && $unwrappedLeftExpr->class instanceof Expr && $unwrappedLeftExpr->name instanceof Node\Identifier && $unwrappedRightExpr instanceof ClassConstFetch && $rightType instanceof ConstantStringType && $rightType->getValue() !== '' && strtolower($unwrappedLeftExpr->name->toString()) === 'class') { return $this->specifyTypesInCondition($scope, new Instanceof_($unwrappedLeftExpr->class, new Name($rightType->getValue())), $context, $rootExpr)->unionWith($this->create($leftExpr, $rightType, $context, \false, $scope, $rootExpr)); } $leftType = $scope->getType($leftExpr); // 'Foo' === $a::class if ($context->true() && $unwrappedRightExpr instanceof ClassConstFetch && $unwrappedRightExpr->class instanceof Expr && $unwrappedRightExpr->name instanceof Node\Identifier && $unwrappedLeftExpr instanceof ClassConstFetch && $leftType instanceof ConstantStringType && $leftType->getValue() !== '' && strtolower($unwrappedRightExpr->name->toString()) === 'class') { return $this->specifyTypesInCondition($scope, new Instanceof_($unwrappedRightExpr->class, new Name($leftType->getValue())), $context, $rootExpr)->unionWith($this->create($rightExpr, $leftType, $context, \false, $scope, $rootExpr)); } if ($context->false()) { $identicalType = $scope->getType($expr); if ($identicalType instanceof ConstantBooleanType) { $never = new NeverType(); $contextForTypes = $identicalType->getValue() ? $context->negate() : $context; $leftTypes = $this->create($leftExpr, $never, $contextForTypes, \false, $scope, $rootExpr); $rightTypes = $this->create($rightExpr, $never, $contextForTypes, \false, $scope, $rootExpr); if ($leftExpr instanceof AlwaysRememberedExpr) { $leftTypes = $leftTypes->unionWith($this->create($unwrappedLeftExpr, $never, $contextForTypes, \false, $scope, $rootExpr)); } if ($rightExpr instanceof AlwaysRememberedExpr) { $rightTypes = $rightTypes->unionWith($this->create($unwrappedRightExpr, $never, $contextForTypes, \false, $scope, $rootExpr)); } return $leftTypes->unionWith($rightTypes); } } $types = null; if (count($leftType->getFiniteTypes()) === 1 || $context->true() && $leftType->isConstantValue()->yes() && !$rightType->equals($leftType) && $rightType->isSuperTypeOf($leftType)->yes()) { $types = $this->create($rightExpr, $leftType, $context, \false, $scope, $rootExpr); if ($rightExpr instanceof AlwaysRememberedExpr) { $types = $types->unionWith($this->create($unwrappedRightExpr, $leftType, $context, \false, $scope, $rootExpr)); } } if (count($rightType->getFiniteTypes()) === 1 || $context->true() && $rightType->isConstantValue()->yes() && !$leftType->equals($rightType) && $leftType->isSuperTypeOf($rightType)->yes()) { $leftTypes = $this->create($leftExpr, $rightType, $context, \false, $scope, $rootExpr); if ($leftExpr instanceof AlwaysRememberedExpr) { $leftTypes = $leftTypes->unionWith($this->create($unwrappedLeftExpr, $rightType, $context, \false, $scope, $rootExpr)); } if ($types !== null) { $types = $types->unionWith($leftTypes); } else { $types = $leftTypes; } } if ($types !== null) { return $types; } $leftExprString = $this->exprPrinter->printExpr($unwrappedLeftExpr); $rightExprString = $this->exprPrinter->printExpr($unwrappedRightExpr); if ($leftExprString === $rightExprString) { if (!$unwrappedLeftExpr instanceof Expr\Variable || !$unwrappedRightExpr instanceof Expr\Variable) { return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } } if ($context->true()) { $leftTypes = $this->create($leftExpr, $rightType, $context, \false, $scope, $rootExpr); $rightTypes = $this->create($rightExpr, $leftType, $context, \false, $scope, $rootExpr); if ($leftExpr instanceof AlwaysRememberedExpr) { $leftTypes = $leftTypes->unionWith($this->create($unwrappedLeftExpr, $rightType, $context, \false, $scope, $rootExpr)); } if ($rightExpr instanceof AlwaysRememberedExpr) { $rightTypes = $rightTypes->unionWith($this->create($unwrappedRightExpr, $leftType, $context, \false, $scope, $rootExpr)); } return $leftTypes->unionWith($rightTypes); } elseif ($context->false()) { return $this->create($leftExpr, $leftType, $context, \false, $scope, $rootExpr)->normalize($scope)->intersectWith($this->create($rightExpr, $rightType, $context, \false, $scope, $rootExpr)->normalize($scope)); } return new \PHPStan\Analyser\SpecifiedTypes([], [], \false, [], $rootExpr); } } |null>> */ final class FileAnalyserResult { /** * @var list */ private $errors; /** * @var list */ private $filteredPhpErrors; /** * @var list */ private $allPhpErrors; /** * @var list */ private $locallyIgnoredErrors; /** * @var list */ private $collectedData; /** * @var list */ private $dependencies; /** * @var list */ private $usedTraitDependencies; /** * @var list */ private $exportedNodes; /** * @var LinesToIgnore */ private $linesToIgnore; /** * @var LinesToIgnore */ private $unmatchedLineIgnores; /** * @param list $errors * @param list $filteredPhpErrors * @param list $allPhpErrors * @param list $locallyIgnoredErrors * @param list $collectedData * @param list $dependencies * @param list $usedTraitDependencies * @param list $exportedNodes * @param LinesToIgnore $linesToIgnore * @param LinesToIgnore $unmatchedLineIgnores */ public function __construct(array $errors, array $filteredPhpErrors, array $allPhpErrors, array $locallyIgnoredErrors, array $collectedData, array $dependencies, array $usedTraitDependencies, array $exportedNodes, array $linesToIgnore, array $unmatchedLineIgnores) { $this->errors = $errors; $this->filteredPhpErrors = $filteredPhpErrors; $this->allPhpErrors = $allPhpErrors; $this->locallyIgnoredErrors = $locallyIgnoredErrors; $this->collectedData = $collectedData; $this->dependencies = $dependencies; $this->usedTraitDependencies = $usedTraitDependencies; $this->exportedNodes = $exportedNodes; $this->linesToIgnore = $linesToIgnore; $this->unmatchedLineIgnores = $unmatchedLineIgnores; } /** * @return list */ public function getErrors() : array { return $this->errors; } /** * @return list */ public function getFilteredPhpErrors() : array { return $this->filteredPhpErrors; } /** * @return list */ public function getAllPhpErrors() : array { return $this->allPhpErrors; } /** * @return list */ public function getLocallyIgnoredErrors() : array { return $this->locallyIgnoredErrors; } /** * @return list */ public function getCollectedData() : array { return $this->collectedData; } /** * @return list */ public function getDependencies() : array { return $this->dependencies; } /** * @return list */ public function getUsedTraitDependencies() : array { return $this->usedTraitDependencies; } /** * @return list */ public function getExportedNodes() : array { return $this->exportedNodes; } /** * @return LinesToIgnore */ public function getLinesToIgnore() : array { return $this->linesToIgnore; } /** * @return LinesToIgnore */ public function getUnmatchedLineIgnores() : array { return $this->unmatchedLineIgnores; } } value = $value; } private static function create(?int $value) : self { self::$registry[$value] = self::$registry[$value] ?? new self($value); return self::$registry[$value]; } public static function createTrue() : self { return self::create(self::CONTEXT_TRUE); } public static function createTruthy() : self { return self::create(self::CONTEXT_TRUTHY); } public static function createFalse() : self { return self::create(self::CONTEXT_FALSE); } public static function createFalsey() : self { return self::create(self::CONTEXT_FALSEY); } public static function createNull() : self { return self::create(null); } public function negate() : self { if ($this->value === null) { throw new ShouldNotHappenException(); } return self::create(~$this->value & self::CONTEXT_BITMASK); } public function true() : bool { return $this->value !== null && (bool) ($this->value & self::CONTEXT_TRUE); } public function truthy() : bool { return $this->value !== null && (bool) ($this->value & self::CONTEXT_TRUTHY); } public function false() : bool { return $this->value !== null && (bool) ($this->value & self::CONTEXT_FALSE); } public function falsey() : bool { return $this->value !== null && (bool) ($this->value & self::CONTEXT_FALSEY); } public function null() : bool { return $this->value === null; } } scope = $scope; $this->type = $type; $this->node = $node; $this->explicit = $explicit; $this->canContainAnyThrowable = $canContainAnyThrowable; } /** * @param Node\Expr|Node\Stmt $node */ public static function createExplicit(\PHPStan\Analyser\MutatingScope $scope, Type $type, Node $node, bool $canContainAnyThrowable) : self { return new self($scope, $type, $node, \true, $canContainAnyThrowable); } /** * @param Node\Expr|Node\Stmt $node */ public static function createImplicit(\PHPStan\Analyser\MutatingScope $scope, Node $node) : self { return new self($scope, new ObjectType(Throwable::class), $node, \false, \true); } public function getScope() : \PHPStan\Analyser\MutatingScope { return $this->scope; } public function getType() : Type { return $this->type; } /** * @return Node\Expr|Node\Stmt */ public function getNode() { return $this->node; } public function isExplicit() : bool { return $this->explicit; } public function canContainAnyThrowable() : bool { return $this->canContainAnyThrowable; } public function subtractCatchType(Type $catchType) : self { return new self($this->scope, TypeCombinator::remove($this->type, $catchType), $this->node, $this->explicit, $this->canContainAnyThrowable); } } scopeClass = $scopeClass; $this->reflectionProvider = $reflectionProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->dynamicReturnTypeExtensionRegistryProvider = $dynamicReturnTypeExtensionRegistryProvider; $this->expressionTypeResolverExtensionRegistryProvider = $expressionTypeResolverExtensionRegistryProvider; $this->exprPrinter = $exprPrinter; $this->typeSpecifier = $typeSpecifier; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->parser = $parser; $this->nodeScopeResolver = $nodeScopeResolver; $this->richerScopeGetTypeHelper = $richerScopeGetTypeHelper; $this->phpVersion = $phpVersion; $this->explicitMixedInUnknownGenericNew = $explicitMixedInUnknownGenericNew; $this->explicitMixedForGlobalVariables = $explicitMixedForGlobalVariables; $this->constantResolver = $constantResolver; } /** * @param array $expressionTypes * @param array $nativeExpressionTypes * @param array $conditionalExpressions * @param list $inFunctionCallsStack * @param array $currentlyAssignedExpressions * @param array $currentlyAllowedUndefinedExpressions * @param FunctionReflection|MethodReflection|null $function */ public function create(\PHPStan\Analyser\ScopeContext $context, bool $declareStrictTypes = \false, $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], array $conditionalExpressions = [], array $inClosureBindScopeClasses = [], ?ParametersAcceptor $anonymousFunctionReflection = null, bool $inFirstLevelStatement = \true, array $currentlyAssignedExpressions = [], array $currentlyAllowedUndefinedExpressions = [], array $inFunctionCallsStack = [], bool $afterExtractCall = \false, ?\PHPStan\Analyser\Scope $parentScope = null, bool $nativeTypesPromoted = \false) : \PHPStan\Analyser\MutatingScope { $scopeClass = $this->scopeClass; if (!is_a($scopeClass, \PHPStan\Analyser\MutatingScope::class, \true)) { throw new ShouldNotHappenException(); } return new $scopeClass($this, $this->reflectionProvider, $this->initializerExprTypeResolver, $this->dynamicReturnTypeExtensionRegistryProvider->getRegistry(), $this->expressionTypeResolverExtensionRegistryProvider->getRegistry(), $this->exprPrinter, $this->typeSpecifier, $this->propertyReflectionFinder, $this->parser, $this->nodeScopeResolver, $this->richerScopeGetTypeHelper, $this->constantResolver, $context, $this->phpVersion, $declareStrictTypes, $function, $namespace, $expressionTypes, $nativeExpressionTypes, $conditionalExpressions, $inClosureBindScopeClasses, $anonymousFunctionReflection, $inFirstLevelStatement, $currentlyAssignedExpressions, $currentlyAllowedUndefinedExpressions, $inFunctionCallsStack, $afterExtractCall, $parentScope, $nativeTypesPromoted, $this->explicitMixedInUnknownGenericNew, $this->explicitMixedForGlobalVariables); } } */ private $allPhpErrors = []; /** @var list */ private $filteredPhpErrors = []; public function __construct(\PHPStan\Analyser\ScopeFactory $scopeFactory, \PHPStan\Analyser\NodeScopeResolver $nodeScopeResolver, Parser $parser, DependencyResolver $dependencyResolver, \PHPStan\Analyser\RuleErrorTransformer $ruleErrorTransformer, \PHPStan\Analyser\LocalIgnoresProcessor $localIgnoresProcessor) { $this->scopeFactory = $scopeFactory; $this->nodeScopeResolver = $nodeScopeResolver; $this->parser = $parser; $this->dependencyResolver = $dependencyResolver; $this->ruleErrorTransformer = $ruleErrorTransformer; $this->localIgnoresProcessor = $localIgnoresProcessor; } /** * @param array $analysedFiles * @param callable(Node $node, Scope $scope): void|null $outerNodeCallback */ public function analyseFile(string $file, array $analysedFiles, RuleRegistry $ruleRegistry, CollectorRegistry $collectorRegistry, ?callable $outerNodeCallback) : \PHPStan\Analyser\FileAnalyserResult { /** @var list $fileErrors */ $fileErrors = []; /** @var list $locallyIgnoredErrors */ $locallyIgnoredErrors = []; /** @var list $fileCollectedData */ $fileCollectedData = []; $fileDependencies = []; $usedTraitFileDependencies = []; $exportedNodes = []; $linesToIgnore = []; $unmatchedLineIgnores = []; if (is_file($file)) { try { $this->collectErrors($analysedFiles); $parserNodes = $this->parser->parseFile($file); $linesToIgnore = $unmatchedLineIgnores = [$file => $this->getLinesToIgnoreFromTokens($parserNodes)]; $temporaryFileErrors = []; $nodeCallback = function (Node $node, \PHPStan\Analyser\Scope $scope) use(&$fileErrors, &$fileCollectedData, &$fileDependencies, &$usedTraitFileDependencies, &$exportedNodes, $file, $ruleRegistry, $collectorRegistry, $outerNodeCallback, $analysedFiles, &$linesToIgnore, &$unmatchedLineIgnores, &$temporaryFileErrors) : void { if ($node instanceof Node\Stmt\Trait_) { foreach (array_keys($linesToIgnore[$file] ?? []) as $lineToIgnore) { if ($lineToIgnore < $node->getStartLine() || $lineToIgnore > $node->getEndLine()) { continue; } unset($unmatchedLineIgnores[$file][$lineToIgnore]); } } if ($node instanceof InTraitNode) { $traitNode = $node->getOriginalNode(); $linesToIgnore[$scope->getFileDescription()] = $this->getLinesToIgnoreFromTokens([$traitNode]); } if ($outerNodeCallback !== null) { $outerNodeCallback($node, $scope); } $uniquedAnalysedCodeExceptionMessages = []; $nodeType = get_class($node); foreach ($ruleRegistry->getRules($nodeType) as $rule) { try { $ruleErrors = $rule->processNode($node, $scope); } catch (AnalysedCodeException $e) { if (isset($uniquedAnalysedCodeExceptionMessages[$e->getMessage()])) { continue; } $uniquedAnalysedCodeExceptionMessages[$e->getMessage()] = \true; $fileErrors[] = (new \PHPStan\Analyser\Error($e->getMessage(), $file, $node->getStartLine(), $e, null, null, $e->getTip()))->withIdentifier('phpstan.internal')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); continue; } catch (IdentifierNotFound $e) { $fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s not found.', $e->getIdentifier()->getName()), $file, $node->getStartLine(), $e, null, null, 'Learn more at https://phpstan.org/user-guide/discovering-symbols'))->withIdentifier('phpstan.reflection')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); continue; } catch (UnableToCompileNode|CircularReference $e) { $fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s', $e->getMessage()), $file, $node->getStartLine(), $e))->withIdentifier('phpstan.reflection')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); continue; } foreach ($ruleErrors as $ruleError) { $temporaryFileErrors[] = $this->ruleErrorTransformer->transform($ruleError, $scope, $nodeType, $node->getStartLine()); } } foreach ($collectorRegistry->getCollectors($nodeType) as $collector) { try { $collectedData = $collector->processNode($node, $scope); } catch (AnalysedCodeException $e) { if (isset($uniquedAnalysedCodeExceptionMessages[$e->getMessage()])) { continue; } $uniquedAnalysedCodeExceptionMessages[$e->getMessage()] = \true; $fileErrors[] = (new \PHPStan\Analyser\Error($e->getMessage(), $file, $node->getStartLine(), $e, null, null, $e->getTip()))->withIdentifier('phpstan.internal')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); continue; } catch (IdentifierNotFound $e) { $fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s not found.', $e->getIdentifier()->getName()), $file, $node->getStartLine(), $e, null, null, 'Learn more at https://phpstan.org/user-guide/discovering-symbols'))->withIdentifier('phpstan.reflection')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); continue; } catch (UnableToCompileNode|CircularReference $e) { $fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s', $e->getMessage()), $file, $node->getStartLine(), $e))->withIdentifier('phpstan.reflection')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); continue; } if ($collectedData === null) { continue; } $fileCollectedData[] = new CollectedData($collectedData, $scope->getFile(), get_class($collector)); } try { $dependencies = $this->dependencyResolver->resolveDependencies($node, $scope); foreach ($dependencies->getFileDependencies($scope->getFile(), $analysedFiles) as $dependentFile) { $fileDependencies[] = $dependentFile; } if ($dependencies->getExportedNode() !== null) { $exportedNodes[] = $dependencies->getExportedNode(); } } catch (AnalysedCodeException $e) { // pass } catch (IdentifierNotFound $e) { // pass } catch (UnableToCompileNode $e) { // pass } if (!$node instanceof InClassNode) { return; } $usedTraitDependencies = $this->dependencyResolver->resolveUsedTraitDependencies($node); foreach ($usedTraitDependencies->getFileDependencies($scope->getFile(), $analysedFiles) as $dependentFile) { $usedTraitFileDependencies[] = $dependentFile; } }; $scope = $this->scopeFactory->create(\PHPStan\Analyser\ScopeContext::create($file)); $nodeCallback(new FileNode($parserNodes), $scope); $this->nodeScopeResolver->processNodes($parserNodes, $scope, $nodeCallback); $localIgnoresProcessorResult = $this->localIgnoresProcessor->process($temporaryFileErrors, $linesToIgnore, $unmatchedLineIgnores); foreach ($localIgnoresProcessorResult->getFileErrors() as $fileError) { $fileErrors[] = $fileError; } foreach ($localIgnoresProcessorResult->getLocallyIgnoredErrors() as $locallyIgnoredError) { $locallyIgnoredErrors[] = $locallyIgnoredError; } $linesToIgnore = $localIgnoresProcessorResult->getLinesToIgnore(); $unmatchedLineIgnores = $localIgnoresProcessorResult->getUnmatchedLineIgnores(); } catch (\PhpParser\Error $e) { $fileErrors[] = (new \PHPStan\Analyser\Error($e->getRawMessage(), $file, $e->getStartLine() !== -1 ? $e->getStartLine() : null, $e))->withIdentifier('phpstan.parse'); } catch (ParserErrorsException $e) { foreach ($e->getErrors() as $error) { $fileErrors[] = (new \PHPStan\Analyser\Error($error->getMessage(), $e->getParsedFile() ?? $file, $error->getLine() !== -1 ? $error->getStartLine() : null, $e))->withIdentifier('phpstan.parse'); } } catch (AnalysedCodeException $e) { $fileErrors[] = (new \PHPStan\Analyser\Error($e->getMessage(), $file, null, $e, null, null, $e->getTip()))->withIdentifier('phpstan.internal')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); } catch (IdentifierNotFound $e) { $fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s not found.', $e->getIdentifier()->getName()), $file, null, $e, null, null, 'Learn more at https://phpstan.org/user-guide/discovering-symbols'))->withIdentifier('phpstan.reflection')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); } catch (UnableToCompileNode|CircularReference $e) { $fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('Reflection error: %s', $e->getMessage()), $file, null, $e))->withIdentifier('phpstan.reflection')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($e), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $e->getTraceAsString()]); } finally { $this->restoreCollectErrorsHandler(); } } elseif (is_dir($file)) { $fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('File %s is a directory.', $file), $file, null, \false))->withIdentifier('phpstan.path'); } else { $fileErrors[] = (new \PHPStan\Analyser\Error(sprintf('File %s does not exist.', $file), $file, null, \false))->withIdentifier('phpstan.path'); } foreach ($linesToIgnore as $fileKey => $lines) { if (count($lines) > 0) { continue; } unset($linesToIgnore[$fileKey]); } foreach ($unmatchedLineIgnores as $fileKey => $lines) { if (count($lines) > 0) { continue; } unset($unmatchedLineIgnores[$fileKey]); } return new \PHPStan\Analyser\FileAnalyserResult($fileErrors, $this->filteredPhpErrors, $this->allPhpErrors, $locallyIgnoredErrors, $fileCollectedData, array_values(array_unique($fileDependencies)), array_values(array_unique($usedTraitFileDependencies)), $exportedNodes, $linesToIgnore, $unmatchedLineIgnores); } /** * @param Node[] $nodes * @return array|null> */ private function getLinesToIgnoreFromTokens(array $nodes) : array { if (!isset($nodes[0])) { return []; } /** @var array|null> */ return $nodes[0]->getAttribute('linesToIgnore', []); } /** * @param array $analysedFiles */ private function collectErrors(array $analysedFiles) : void { $this->filteredPhpErrors = []; $this->allPhpErrors = []; set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) use($analysedFiles) : bool { if ((error_reporting() & $errno) === 0) { // silence @ operator return \true; } $errorMessage = sprintf('%s: %s', $this->getErrorLabel($errno), $errstr); $this->allPhpErrors[] = (new \PHPStan\Analyser\Error($errorMessage, $errfile, $errline, \true))->withIdentifier('phpstan.php'); if ($errno === E_DEPRECATED) { return \true; } if (!isset($analysedFiles[$errfile])) { return \true; } $this->filteredPhpErrors[] = (new \PHPStan\Analyser\Error($errorMessage, $errfile, $errline, \true))->withIdentifier('phpstan.php'); return \true; }); } private function restoreCollectErrorsHandler() : void { restore_error_handler(); } private function getErrorLabel(int $errno) : string { switch ($errno) { case E_ERROR: return 'Fatal error'; case E_WARNING: return 'Warning'; case E_PARSE: return 'Parse error'; case E_NOTICE: return 'Notice'; case E_USER_ERROR: return 'User error (E_USER_ERROR)'; case E_USER_WARNING: return 'User warning (E_USER_WARNING)'; case E_USER_NOTICE: return 'User notice (E_USER_NOTICE)'; case E_STRICT: return 'Strict error (E_STRICT)'; } return 'Unknown PHP error'; } } */ private $earlyTerminatingFunctionCalls; /** * @readonly * @var string[] */ private $universalObjectCratesClasses; /** * @readonly * @var bool */ private $implicitThrows; /** * @readonly * @var bool */ private $treatPhpDocTypesAsCertain; /** * @readonly * @var bool */ private $detectDeadTypeInMultiCatch; /** * @readonly * @var bool */ private $paramOutType; /** * @readonly * @var bool */ private $preciseMissingReturn; /** * @readonly * @var bool */ private $explicitThrow; private const LOOP_SCOPE_ITERATIONS = 3; private const GENERALIZE_AFTER_ITERATION = 1; /** @var bool[] filePath(string) => bool(true) */ private $analysedFiles = []; /** @var array */ private $earlyTerminatingMethodNames; /** @var array */ private $calledMethodStack = []; /** @var array */ private $calledMethodResults = []; /** * @param string[][] $earlyTerminatingMethodCalls className(string) => methods(string[]) * @param array $earlyTerminatingFunctionCalls * @param string[] $universalObjectCratesClasses */ public function __construct(ReflectionProvider $reflectionProvider, InitializerExprTypeResolver $initializerExprTypeResolver, Reflector $reflector, ClassReflectionExtensionRegistryProvider $classReflectionExtensionRegistryProvider, ParameterOutTypeExtensionProvider $parameterOutTypeExtensionProvider, Parser $parser, FileTypeMapper $fileTypeMapper, StubPhpDocProvider $stubPhpDocProvider, PhpVersion $phpVersion, SignatureMapProvider $signatureMapProvider, PhpDocInheritanceResolver $phpDocInheritanceResolver, FileHelper $fileHelper, \PHPStan\Analyser\TypeSpecifier $typeSpecifier, DynamicThrowTypeExtensionProvider $dynamicThrowTypeExtensionProvider, ReadWritePropertiesExtensionProvider $readWritePropertiesExtensionProvider, ParameterClosureTypeExtensionProvider $parameterClosureTypeExtensionProvider, \PHPStan\Analyser\ScopeFactory $scopeFactory, bool $polluteScopeWithLoopInitialAssignments, bool $polluteScopeWithAlwaysIterableForeach, array $earlyTerminatingMethodCalls, array $earlyTerminatingFunctionCalls, array $universalObjectCratesClasses, bool $implicitThrows, bool $treatPhpDocTypesAsCertain, bool $detectDeadTypeInMultiCatch, bool $paramOutType, bool $preciseMissingReturn, bool $explicitThrow) { $this->reflectionProvider = $reflectionProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->reflector = $reflector; $this->classReflectionExtensionRegistryProvider = $classReflectionExtensionRegistryProvider; $this->parameterOutTypeExtensionProvider = $parameterOutTypeExtensionProvider; $this->parser = $parser; $this->fileTypeMapper = $fileTypeMapper; $this->stubPhpDocProvider = $stubPhpDocProvider; $this->phpVersion = $phpVersion; $this->signatureMapProvider = $signatureMapProvider; $this->phpDocInheritanceResolver = $phpDocInheritanceResolver; $this->fileHelper = $fileHelper; $this->typeSpecifier = $typeSpecifier; $this->dynamicThrowTypeExtensionProvider = $dynamicThrowTypeExtensionProvider; $this->readWritePropertiesExtensionProvider = $readWritePropertiesExtensionProvider; $this->parameterClosureTypeExtensionProvider = $parameterClosureTypeExtensionProvider; $this->scopeFactory = $scopeFactory; $this->polluteScopeWithLoopInitialAssignments = $polluteScopeWithLoopInitialAssignments; $this->polluteScopeWithAlwaysIterableForeach = $polluteScopeWithAlwaysIterableForeach; $this->earlyTerminatingMethodCalls = $earlyTerminatingMethodCalls; $this->earlyTerminatingFunctionCalls = $earlyTerminatingFunctionCalls; $this->universalObjectCratesClasses = $universalObjectCratesClasses; $this->implicitThrows = $implicitThrows; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->detectDeadTypeInMultiCatch = $detectDeadTypeInMultiCatch; $this->paramOutType = $paramOutType; $this->preciseMissingReturn = $preciseMissingReturn; $this->explicitThrow = $explicitThrow; $earlyTerminatingMethodNames = []; foreach ($this->earlyTerminatingMethodCalls as $methodNames) { foreach ($methodNames as $methodName) { $earlyTerminatingMethodNames[strtolower($methodName)] = \true; } } $this->earlyTerminatingMethodNames = $earlyTerminatingMethodNames; } /** * @api * @param string[] $files */ public function setAnalysedFiles(array $files) : void { $this->analysedFiles = array_fill_keys($files, \true); } /** * @api * @param Node[] $nodes * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function processNodes(array $nodes, \PHPStan\Analyser\MutatingScope $scope, callable $nodeCallback) : void { $alreadyTerminated = \false; foreach ($nodes as $i => $node) { if (!$node instanceof Node\Stmt || $alreadyTerminated && !($node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\ClassLike)) { continue; } $statementResult = $this->processStmtNode($node, $scope, $nodeCallback, \PHPStan\Analyser\StatementContext::createTopLevel()); $scope = $statementResult->getScope(); if ($alreadyTerminated || !$statementResult->isAlwaysTerminating()) { continue; } $alreadyTerminated = \true; $nextStmt = $this->getFirstUnreachableNode(array_slice($nodes, $i + 1), \true); if (!$nextStmt instanceof Node\Stmt) { continue; } $nodeCallback(new UnreachableStatementNode($nextStmt), $scope); } } /** * @api * @param Node\Stmt[] $stmts * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function processStmtNodes(Node $parentNode, array $stmts, \PHPStan\Analyser\MutatingScope $scope, callable $nodeCallback, ?\PHPStan\Analyser\StatementContext $context = null) : \PHPStan\Analyser\StatementResult { if ($context === null) { $context = \PHPStan\Analyser\StatementContext::createTopLevel(); } $exitPoints = []; $throwPoints = []; $impurePoints = []; $alreadyTerminated = \false; $hasYield = \false; $stmtCount = count($stmts); $shouldCheckLastStatement = $parentNode instanceof Node\Stmt\Function_ || $parentNode instanceof Node\Stmt\ClassMethod || $parentNode instanceof Expr\Closure; foreach ($stmts as $i => $stmt) { if ($alreadyTerminated && !($stmt instanceof Node\Stmt\Function_ || $stmt instanceof Node\Stmt\ClassLike)) { continue; } $isLast = $i === $stmtCount - 1; $statementResult = $this->processStmtNode($stmt, $scope, $nodeCallback, $context); $scope = $statementResult->getScope(); $hasYield = $hasYield || $statementResult->hasYield(); if ($shouldCheckLastStatement && $isLast) { /** @var Node\Stmt\Function_|Node\Stmt\ClassMethod|Expr\Closure $parentNode */ $parentNode = $parentNode; $endStatements = $statementResult->getEndStatements(); if ($this->preciseMissingReturn && count($endStatements) > 0) { foreach ($endStatements as $endStatement) { $endStatementResult = $endStatement->getResult(); $nodeCallback(new ExecutionEndNode($endStatement->getStatement(), new \PHPStan\Analyser\StatementResult($endStatementResult->getScope(), $hasYield, $endStatementResult->isAlwaysTerminating(), $endStatementResult->getExitPoints(), $endStatementResult->getThrowPoints(), $endStatementResult->getImpurePoints()), $parentNode->returnType !== null), $endStatementResult->getScope()); } } else { $nodeCallback(new ExecutionEndNode($stmt, new \PHPStan\Analyser\StatementResult($scope, $hasYield, $statementResult->isAlwaysTerminating(), $statementResult->getExitPoints(), $statementResult->getThrowPoints(), $statementResult->getImpurePoints()), $parentNode->returnType !== null), $scope); } } $exitPoints = array_merge($exitPoints, $statementResult->getExitPoints()); $throwPoints = array_merge($throwPoints, $statementResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $statementResult->getImpurePoints()); if ($alreadyTerminated || !$statementResult->isAlwaysTerminating()) { continue; } $alreadyTerminated = \true; $nextStmt = $this->getFirstUnreachableNode(array_slice($stmts, $i + 1), $parentNode instanceof Node\Stmt\Namespace_); if ($nextStmt === null) { continue; } $nodeCallback(new UnreachableStatementNode($nextStmt), $scope); } $statementResult = new \PHPStan\Analyser\StatementResult($scope, $hasYield, $alreadyTerminated, $exitPoints, $throwPoints, $impurePoints); if ($stmtCount === 0 && $shouldCheckLastStatement) { /** @var Node\Stmt\Function_|Node\Stmt\ClassMethod|Expr\Closure $parentNode */ $parentNode = $parentNode; $returnTypeNode = $parentNode->returnType; if ($parentNode instanceof Expr\Closure) { $parentNode = new Node\Stmt\Expression($parentNode, $parentNode->getAttributes()); } $nodeCallback(new ExecutionEndNode($parentNode, $statementResult, $returnTypeNode !== null), $scope); } return $statementResult; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processStmtNode(Node\Stmt $stmt, \PHPStan\Analyser\MutatingScope $scope, callable $nodeCallback, \PHPStan\Analyser\StatementContext $context) : \PHPStan\Analyser\StatementResult { if (!$stmt instanceof Static_ && !$stmt instanceof Foreach_ && !$stmt instanceof Node\Stmt\Global_ && !$stmt instanceof Node\Stmt\Property && !$stmt instanceof Node\Stmt\PropertyProperty && !$stmt instanceof Node\Stmt\ClassConst && !$stmt instanceof Node\Stmt\Const_) { $scope = $this->processStmtVarAnnotation($scope, $stmt, null, $nodeCallback); } if ($stmt instanceof Node\Stmt\ClassMethod) { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } if ($scope->isInTrait() && $scope->getClassReflection()->hasNativeMethod($stmt->name->toString())) { $methodReflection = $scope->getClassReflection()->getNativeMethod($stmt->name->toString()); if ($methodReflection instanceof NativeMethodReflection) { return new \PHPStan\Analyser\StatementResult($scope, \false, \false, [], [], []); } if ($methodReflection instanceof PhpMethodReflection) { $declaringTrait = $methodReflection->getDeclaringTrait(); if ($declaringTrait === null || $declaringTrait->getName() !== $scope->getTraitReflection()->getName()) { return new \PHPStan\Analyser\StatementResult($scope, \false, \false, [], [], []); } } } } $stmtScope = $scope; if ($stmt instanceof Throw_ || $stmt instanceof Return_) { $stmtScope = $this->processStmtVarAnnotation($scope, $stmt, $stmt->expr, $nodeCallback); } $nodeCallback($stmt, $stmtScope); $overridingThrowPoints = $this->getOverridingThrowPoints($stmt, $scope); if ($stmt instanceof Node\Stmt\Declare_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $alwaysTerminating = \false; $exitPoints = []; foreach ($stmt->declares as $declare) { $nodeCallback($declare, $scope); $nodeCallback($declare->value, $scope); if ($declare->key->name !== 'strict_types' || !$declare->value instanceof Node\Scalar\LNumber || $declare->value->value !== 1) { continue; } $scope = $scope->enterDeclareStrictTypes(); } if ($stmt->stmts !== null) { $result = $this->processStmtNodes($stmt, $stmt->stmts, $scope, $nodeCallback, $context); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $alwaysTerminating = $result->isAlwaysTerminating(); $exitPoints = $result->getExitPoints(); } return new \PHPStan\Analyser\StatementResult($scope, $hasYield, $alwaysTerminating, $exitPoints, $throwPoints, $impurePoints); } elseif ($stmt instanceof Node\Stmt\Function_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $this->processAttributeGroups($stmt, $stmt->attrGroups, $scope, $nodeCallback); [$templateTypeMap, $phpDocParameterTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, , $phpDocComment, $asserts, , $phpDocParameterOutTypes] = $this->getPhpDocs($scope, $stmt); foreach ($stmt->params as $param) { $this->processParamNode($stmt, $param, $scope, $nodeCallback); } if ($stmt->returnType !== null) { $nodeCallback($stmt->returnType, $scope); } $functionScope = $scope->enterFunction($stmt, $templateTypeMap, $phpDocParameterTypes, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, $asserts, $phpDocComment, $phpDocParameterOutTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters); $functionReflection = $functionScope->getFunction(); if (!$functionReflection instanceof PhpFunctionFromParserNodeReflection) { throw new ShouldNotHappenException(); } $nodeCallback(new InFunctionNode($functionReflection, $stmt), $functionScope); $gatheredReturnStatements = []; $gatheredYieldStatements = []; $executionEnds = []; $functionImpurePoints = []; $statementResult = $this->processStmtNodes($stmt, $stmt->stmts, $functionScope, static function (Node $node, \PHPStan\Analyser\Scope $scope) use($nodeCallback, $functionScope, &$gatheredReturnStatements, &$gatheredYieldStatements, &$executionEnds, &$functionImpurePoints) : void { $nodeCallback($node, $scope); if ($scope->getFunction() !== $functionScope->getFunction()) { return; } if ($scope->isInAnonymousFunction()) { return; } if ($node instanceof PropertyAssignNode) { $functionImpurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $node, 'propertyAssign', 'property assignment', \true); return; } if ($node instanceof ExecutionEndNode) { $executionEnds[] = $node; return; } if ($node instanceof Expr\Yield_ || $node instanceof Expr\YieldFrom) { $gatheredYieldStatements[] = $node; } if (!$node instanceof Return_) { return; } $gatheredReturnStatements[] = new ReturnStatement($scope, $node); }, \PHPStan\Analyser\StatementContext::createTopLevel()); $nodeCallback(new FunctionReturnStatementsNode($stmt, $gatheredReturnStatements, $gatheredYieldStatements, $statementResult, $executionEnds, array_merge($statementResult->getImpurePoints(), $functionImpurePoints), $functionReflection), $functionScope); } elseif ($stmt instanceof Node\Stmt\ClassMethod) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $this->processAttributeGroups($stmt, $stmt->attrGroups, $scope, $nodeCallback); [$templateTypeMap, $phpDocParameterTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, , $phpDocComment, $asserts, $selfOutType, $phpDocParameterOutTypes] = $this->getPhpDocs($scope, $stmt); foreach ($stmt->params as $param) { $this->processParamNode($stmt, $param, $scope, $nodeCallback); } if ($stmt->returnType !== null) { $nodeCallback($stmt->returnType, $scope); } $isFromTrait = $stmt->getAttribute('originalTraitMethodName') === '__construct'; $isConstructor = $isFromTrait || $stmt->name->toLowerString() === '__construct'; $methodScope = $scope->enterClassMethod($stmt, $templateTypeMap, $phpDocParameterTypes, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, $asserts, $selfOutType, $phpDocComment, $phpDocParameterOutTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $isConstructor); if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } if ($isConstructor) { foreach ($stmt->params as $param) { if ($param->flags === 0) { continue; } if (!$param->var instanceof Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $phpDoc = null; if ($param->getDocComment() !== null) { $phpDoc = $param->getDocComment()->getText(); } $nodeCallback(new ClassPropertyNode($param->var->name, $param->flags, $param->type, null, $phpDoc, $phpDocParameterTypes[$param->var->name] ?? null, \true, $isFromTrait, $param, \false, $scope->isInTrait(), $scope->getClassReflection()->isReadOnly(), \false, $scope->getClassReflection()), $methodScope); $methodScope = $methodScope->assignExpression(new PropertyInitializationExpr($param->var->name), new MixedType(), new MixedType()); } } if ($stmt->getAttribute('virtual', \false) === \false) { $methodReflection = $methodScope->getFunction(); if (!$methodReflection instanceof PhpMethodFromParserNodeReflection) { throw new ShouldNotHappenException(); } $nodeCallback(new InClassMethodNode($scope->getClassReflection(), $methodReflection, $stmt), $methodScope); } if ($stmt->stmts !== null) { $gatheredReturnStatements = []; $gatheredYieldStatements = []; $executionEnds = []; $methodImpurePoints = []; $statementResult = $this->processStmtNodes($stmt, $stmt->stmts, $methodScope, static function (Node $node, \PHPStan\Analyser\Scope $scope) use($nodeCallback, $methodScope, &$gatheredReturnStatements, &$gatheredYieldStatements, &$executionEnds, &$methodImpurePoints) : void { $nodeCallback($node, $scope); if ($scope->getFunction() !== $methodScope->getFunction()) { return; } if ($scope->isInAnonymousFunction()) { return; } if ($node instanceof PropertyAssignNode) { if ($node->getPropertyFetch() instanceof Expr\PropertyFetch && $scope->getFunction() instanceof PhpMethodFromParserNodeReflection && $scope->getFunction()->getDeclaringClass()->hasConstructor() && $scope->getFunction()->getDeclaringClass()->getConstructor()->getName() === $scope->getFunction()->getName() && TypeUtils::findThisType($scope->getType($node->getPropertyFetch()->var)) !== null) { return; } $methodImpurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $node, 'propertyAssign', 'property assignment', \true); return; } if ($node instanceof ExecutionEndNode) { $executionEnds[] = $node; return; } if ($node instanceof Expr\Yield_ || $node instanceof Expr\YieldFrom) { $gatheredYieldStatements[] = $node; } if (!$node instanceof Return_) { return; } $gatheredReturnStatements[] = new ReturnStatement($scope, $node); }, \PHPStan\Analyser\StatementContext::createTopLevel()); $classReflection = $scope->getClassReflection(); $methodReflection = $methodScope->getFunction(); if (!$methodReflection instanceof PhpMethodFromParserNodeReflection) { throw new ShouldNotHappenException(); } $nodeCallback(new MethodReturnStatementsNode($stmt, $gatheredReturnStatements, $gatheredYieldStatements, $statementResult, $executionEnds, array_merge($statementResult->getImpurePoints(), $methodImpurePoints), $classReflection, $methodReflection), $methodScope); } } elseif ($stmt instanceof Echo_) { $hasYield = \false; $throwPoints = []; foreach ($stmt->exprs as $echoExpr) { $result = $this->processExprNode($stmt, $echoExpr, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $scope = $result->getScope(); $hasYield = $hasYield || $result->hasYield(); } $throwPoints = $overridingThrowPoints ?? $throwPoints; $impurePoints = [new \PHPStan\Analyser\ImpurePoint($scope, $stmt, 'echo', 'echo', \true)]; } elseif ($stmt instanceof Return_) { if ($stmt->expr !== null) { $result = $this->processExprNode($stmt, $stmt->expr, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $scope = $result->getScope(); $hasYield = $result->hasYield(); } else { $hasYield = \false; $throwPoints = []; $impurePoints = []; } return new \PHPStan\Analyser\StatementResult($scope, $hasYield, \true, [new \PHPStan\Analyser\StatementExitPoint($stmt, $scope)], $overridingThrowPoints ?? $throwPoints, $impurePoints); } elseif ($stmt instanceof Continue_ || $stmt instanceof Break_) { if ($stmt->num !== null) { $result = $this->processExprNode($stmt, $stmt->num, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); } else { $hasYield = \false; $throwPoints = []; $impurePoints = []; } return new \PHPStan\Analyser\StatementResult($scope, $hasYield, \true, [new \PHPStan\Analyser\StatementExitPoint($stmt, $scope)], $overridingThrowPoints ?? $throwPoints, $impurePoints); } elseif ($stmt instanceof Node\Stmt\Expression) { $earlyTerminationExpr = $this->findEarlyTerminatingExpr($stmt->expr, $scope); $hasAssign = \false; $currentScope = $scope; $result = $this->processExprNode($stmt, $stmt->expr, $scope, static function (Node $node, \PHPStan\Analyser\Scope $scope) use($nodeCallback, $currentScope, &$hasAssign) : void { $nodeCallback($node, $scope); if ($scope->getAnonymousFunctionReflection() !== $currentScope->getAnonymousFunctionReflection()) { return; } if ($scope->getFunction() !== $currentScope->getFunction()) { return; } if (!$node instanceof VariableAssignNode && !$node instanceof PropertyAssignNode) { return; } $hasAssign = \true; }, \PHPStan\Analyser\ExpressionContext::createTopLevel()); $throwPoints = array_filter($result->getThrowPoints(), static function ($throwPoint) { return $throwPoint->isExplicit(); }); if (count($result->getImpurePoints()) === 0 && count($throwPoints) === 0 && !$stmt->expr instanceof Expr\PostInc && !$stmt->expr instanceof Expr\PreInc && !$stmt->expr instanceof Expr\PostDec && !$stmt->expr instanceof Expr\PreDec) { $nodeCallback(new NoopExpressionNode($stmt->expr, $hasAssign), $scope); } $scope = $result->getScope(); $scope = $scope->filterBySpecifiedTypes($this->typeSpecifier->specifyTypesInCondition($scope, $stmt->expr, \PHPStan\Analyser\TypeSpecifierContext::createNull())); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); if ($earlyTerminationExpr !== null) { return new \PHPStan\Analyser\StatementResult($scope, $hasYield, \true, [new \PHPStan\Analyser\StatementExitPoint($stmt, $scope)], $overridingThrowPoints ?? $throwPoints, $impurePoints); } return new \PHPStan\Analyser\StatementResult($scope, $hasYield, \false, [], $overridingThrowPoints ?? $throwPoints, $impurePoints); } elseif ($stmt instanceof Node\Stmt\Namespace_) { if ($stmt->name !== null) { $scope = $scope->enterNamespace($stmt->name->toString()); } $scope = $this->processStmtNodes($stmt, $stmt->stmts, $scope, $nodeCallback, $context)->getScope(); $hasYield = \false; $throwPoints = []; $impurePoints = []; } elseif ($stmt instanceof Node\Stmt\Trait_) { return new \PHPStan\Analyser\StatementResult($scope, \false, \false, [], [], []); } elseif ($stmt instanceof Node\Stmt\ClassLike) { if (!$context->isTopLevel()) { return new \PHPStan\Analyser\StatementResult($scope, \false, \false, [], [], []); } $hasYield = \false; $throwPoints = []; $impurePoints = []; if (isset($stmt->namespacedName)) { $classReflection = $this->getCurrentClassReflection($stmt, $stmt->namespacedName->toString(), $scope); $classScope = $scope->enterClass($classReflection); $nodeCallback(new InClassNode($stmt, $classReflection), $classScope); } elseif ($stmt instanceof Class_) { if ($stmt->name === null) { throw new ShouldNotHappenException(); } if (!$stmt->isAnonymous()) { $classReflection = $this->reflectionProvider->getClass($stmt->name->toString()); } else { $classReflection = $this->reflectionProvider->getAnonymousClassReflection($stmt, $scope); } $classScope = $scope->enterClass($classReflection); $nodeCallback(new InClassNode($stmt, $classReflection), $classScope); } else { throw new ShouldNotHappenException(); } $classStatementsGatherer = new ClassStatementsGatherer($classReflection, $nodeCallback); $this->processAttributeGroups($stmt, $stmt->attrGroups, $classScope, $classStatementsGatherer); $this->processStmtNodes($stmt, $stmt->stmts, $classScope, $classStatementsGatherer, $context); $nodeCallback(new ClassPropertiesNode($stmt, $this->readWritePropertiesExtensionProvider, $classStatementsGatherer->getProperties(), $classStatementsGatherer->getPropertyUsages(), $classStatementsGatherer->getMethodCalls(), $classStatementsGatherer->getReturnStatementsNodes(), $classStatementsGatherer->getPropertyAssigns(), $classReflection), $classScope); $nodeCallback(new ClassMethodsNode($stmt, $classStatementsGatherer->getMethods(), $classStatementsGatherer->getMethodCalls(), $classReflection), $classScope); $nodeCallback(new ClassConstantsNode($stmt, $classStatementsGatherer->getConstants(), $classStatementsGatherer->getConstantFetches(), $classReflection), $classScope); $classReflection->evictPrivateSymbols(); $this->calledMethodResults = []; } elseif ($stmt instanceof Node\Stmt\Property) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $this->processAttributeGroups($stmt, $stmt->attrGroups, $scope, $nodeCallback); foreach ($stmt->props as $prop) { $nodeCallback($prop, $scope); if ($prop->default !== null) { $this->processExprNode($stmt, $prop->default, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); } [, , , , , , , , , , , , $isReadOnly, $docComment, , , , $varTags, $isAllowedPrivateMutation] = $this->getPhpDocs($scope, $stmt); if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $propertyName = $prop->name->toString(); $phpDocType = null; if (isset($varTags[0]) && count($varTags) === 1) { $phpDocType = $varTags[0]->getType(); } elseif (isset($varTags[$propertyName])) { $phpDocType = $varTags[$propertyName]->getType(); } $nodeCallback(new ClassPropertyNode($propertyName, $stmt->flags, $stmt->type, $prop->default, $docComment, $phpDocType, \false, \false, $prop, $isReadOnly, $scope->isInTrait(), $scope->getClassReflection()->isReadOnly(), $isAllowedPrivateMutation, $scope->getClassReflection()), $scope); } if ($stmt->type !== null) { $nodeCallback($stmt->type, $scope); } } elseif ($stmt instanceof Throw_) { $result = $this->processExprNode($stmt, $stmt->expr, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = $result->getThrowPoints(); $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createExplicit($result->getScope(), $scope->getType($stmt->expr), $stmt, \false); $impurePoints = $result->getImpurePoints(); return new \PHPStan\Analyser\StatementResult($result->getScope(), $result->hasYield(), \true, [new \PHPStan\Analyser\StatementExitPoint($stmt, $scope)], $throwPoints, $impurePoints); } elseif ($stmt instanceof If_) { $conditionType = ($this->treatPhpDocTypesAsCertain ? $scope->getType($stmt->cond) : $scope->getNativeType($stmt->cond))->toBoolean(); $ifAlwaysTrue = $conditionType->isTrue()->yes(); $condResult = $this->processExprNode($stmt, $stmt->cond, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $exitPoints = []; $throwPoints = $overridingThrowPoints ?? $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); $endStatements = []; $finalScope = null; $alwaysTerminating = \true; $hasYield = $condResult->hasYield(); $branchScopeStatementResult = $this->processStmtNodes($stmt, $stmt->stmts, $condResult->getTruthyScope(), $nodeCallback, $context); if (!$conditionType instanceof ConstantBooleanType || $conditionType->getValue()) { $exitPoints = $branchScopeStatementResult->getExitPoints(); $throwPoints = array_merge($throwPoints, $branchScopeStatementResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $branchScopeStatementResult->getImpurePoints()); $branchScope = $branchScopeStatementResult->getScope(); $finalScope = $branchScopeStatementResult->isAlwaysTerminating() ? null : $branchScope; $alwaysTerminating = $branchScopeStatementResult->isAlwaysTerminating(); if (count($branchScopeStatementResult->getEndStatements()) > 0) { $endStatements = array_merge($endStatements, $branchScopeStatementResult->getEndStatements()); } elseif (count($stmt->stmts) > 0) { $endStatements[] = new \PHPStan\Analyser\EndStatementResult($stmt->stmts[count($stmt->stmts) - 1], $branchScopeStatementResult); } else { $endStatements[] = new \PHPStan\Analyser\EndStatementResult($stmt, $branchScopeStatementResult); } $hasYield = $branchScopeStatementResult->hasYield() || $hasYield; } $scope = $condResult->getFalseyScope(); $lastElseIfConditionIsTrue = \false; $condScope = $scope; foreach ($stmt->elseifs as $elseif) { $nodeCallback($elseif, $scope); $elseIfConditionType = ($this->treatPhpDocTypesAsCertain ? $condScope->getType($elseif->cond) : $scope->getNativeType($elseif->cond))->toBoolean(); $condResult = $this->processExprNode($stmt, $elseif->cond, $condScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = array_merge($throwPoints, $condResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $condResult->getImpurePoints()); $condScope = $condResult->getScope(); $branchScopeStatementResult = $this->processStmtNodes($elseif, $elseif->stmts, $condResult->getTruthyScope(), $nodeCallback, $context); if (!$ifAlwaysTrue && (!$lastElseIfConditionIsTrue && (!$elseIfConditionType instanceof ConstantBooleanType || $elseIfConditionType->getValue()))) { $exitPoints = array_merge($exitPoints, $branchScopeStatementResult->getExitPoints()); $throwPoints = array_merge($throwPoints, $branchScopeStatementResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $branchScopeStatementResult->getImpurePoints()); $branchScope = $branchScopeStatementResult->getScope(); $finalScope = $branchScopeStatementResult->isAlwaysTerminating() ? $finalScope : $branchScope->mergeWith($finalScope); $alwaysTerminating = $alwaysTerminating && $branchScopeStatementResult->isAlwaysTerminating(); if (count($branchScopeStatementResult->getEndStatements()) > 0) { $endStatements = array_merge($endStatements, $branchScopeStatementResult->getEndStatements()); } elseif (count($elseif->stmts) > 0) { $endStatements[] = new \PHPStan\Analyser\EndStatementResult($elseif->stmts[count($elseif->stmts) - 1], $branchScopeStatementResult); } else { $endStatements[] = new \PHPStan\Analyser\EndStatementResult($elseif, $branchScopeStatementResult); } $hasYield = $hasYield || $branchScopeStatementResult->hasYield(); } if ($elseIfConditionType->isTrue()->yes()) { $lastElseIfConditionIsTrue = \true; } $condScope = $condScope->filterByFalseyValue($elseif->cond); $scope = $condScope; } if ($stmt->else === null) { if (!$ifAlwaysTrue && !$lastElseIfConditionIsTrue) { $finalScope = $scope->mergeWith($finalScope); $alwaysTerminating = \false; } } else { $nodeCallback($stmt->else, $scope); $branchScopeStatementResult = $this->processStmtNodes($stmt->else, $stmt->else->stmts, $scope, $nodeCallback, $context); if (!$ifAlwaysTrue && !$lastElseIfConditionIsTrue) { $exitPoints = array_merge($exitPoints, $branchScopeStatementResult->getExitPoints()); $throwPoints = array_merge($throwPoints, $branchScopeStatementResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $branchScopeStatementResult->getImpurePoints()); $branchScope = $branchScopeStatementResult->getScope(); $finalScope = $branchScopeStatementResult->isAlwaysTerminating() ? $finalScope : $branchScope->mergeWith($finalScope); $alwaysTerminating = $alwaysTerminating && $branchScopeStatementResult->isAlwaysTerminating(); if (count($branchScopeStatementResult->getEndStatements()) > 0) { $endStatements = array_merge($endStatements, $branchScopeStatementResult->getEndStatements()); } elseif (count($stmt->else->stmts) > 0) { $endStatements[] = new \PHPStan\Analyser\EndStatementResult($stmt->else->stmts[count($stmt->else->stmts) - 1], $branchScopeStatementResult); } else { $endStatements[] = new \PHPStan\Analyser\EndStatementResult($stmt->else, $branchScopeStatementResult); } $hasYield = $hasYield || $branchScopeStatementResult->hasYield(); } } if ($finalScope === null) { $finalScope = $scope; } if ($stmt->else === null && !$ifAlwaysTrue && !$lastElseIfConditionIsTrue) { $endStatements[] = new \PHPStan\Analyser\EndStatementResult($stmt, new \PHPStan\Analyser\StatementResult($finalScope, $hasYield, $alwaysTerminating, $exitPoints, $throwPoints, $impurePoints)); } return new \PHPStan\Analyser\StatementResult($finalScope, $hasYield, $alwaysTerminating, $exitPoints, $throwPoints, $impurePoints, $endStatements); } elseif ($stmt instanceof Node\Stmt\TraitUse) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $this->processTraitUse($stmt, $scope, $nodeCallback); } elseif ($stmt instanceof Foreach_) { $condResult = $this->processExprNode($stmt, $stmt->expr, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = $overridingThrowPoints ?? $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); $scope = $condResult->getScope(); $arrayComparisonExpr = new BinaryOp\NotIdentical($stmt->expr, new Array_([])); if ($stmt->expr instanceof Variable && is_string($stmt->expr->name)) { $scope = $this->processVarAnnotation($scope, [$stmt->expr->name], $stmt); } $nodeCallback(new InForeachNode($stmt), $scope); $originalScope = $scope; $bodyScope = $scope; if ($context->isTopLevel()) { $originalScope = $this->polluteScopeWithAlwaysIterableForeach ? $scope->filterByTruthyValue($arrayComparisonExpr) : $scope; $bodyScope = $this->enterForeach($originalScope, $originalScope, $stmt); $count = 0; do { $prevScope = $bodyScope; $bodyScope = $bodyScope->mergeWith($this->polluteScopeWithAlwaysIterableForeach ? $scope->filterByTruthyValue($arrayComparisonExpr) : $scope); $bodyScope = $this->enterForeach($bodyScope, $originalScope, $stmt); $bodyScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, static function () : void { }, $context->enterDeep())->filterOutLoopExitPoints(); $bodyScope = $bodyScopeResult->getScope(); foreach ($bodyScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $bodyScope = $bodyScope->mergeWith($continueExitPoint->getScope()); } if ($bodyScope->equals($prevScope)) { break; } if ($count >= self::GENERALIZE_AFTER_ITERATION) { $bodyScope = $prevScope->generalizeWith($bodyScope); } $count++; } while ($count < self::LOOP_SCOPE_ITERATIONS); } $bodyScope = $bodyScope->mergeWith($this->polluteScopeWithAlwaysIterableForeach ? $scope->filterByTruthyValue($arrayComparisonExpr) : $scope); $bodyScope = $this->enterForeach($bodyScope, $originalScope, $stmt); $finalScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, $nodeCallback, $context)->filterOutLoopExitPoints(); $finalScope = $finalScopeResult->getScope(); foreach ($finalScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $finalScope = $continueExitPoint->getScope()->mergeWith($finalScope); } foreach ($finalScopeResult->getExitPointsByType(Break_::class) as $breakExitPoint) { $finalScope = $breakExitPoint->getScope()->mergeWith($finalScope); } $exprType = $scope->getType($stmt->expr); $isIterableAtLeastOnce = $exprType->isIterableAtLeastOnce(); if ($exprType->isIterable()->no() || $isIterableAtLeastOnce->maybe()) { $finalScope = $finalScope->mergeWith($scope->filterByTruthyValue(new BooleanOr(new BinaryOp\Identical($stmt->expr, new Array_([])), new FuncCall(new Name\FullyQualified('is_object'), [new Arg($stmt->expr)])))); } elseif ($isIterableAtLeastOnce->no() || $finalScopeResult->isAlwaysTerminating()) { $finalScope = $scope; } elseif (!$this->polluteScopeWithAlwaysIterableForeach) { $finalScope = $scope->processAlwaysIterableForeachScopeWithoutPollute($finalScope); // get types from finalScope, but don't create new variables } if (!$isIterableAtLeastOnce->no()) { $throwPoints = array_merge($throwPoints, $finalScopeResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $finalScopeResult->getImpurePoints()); } if (!(new ObjectType(Traversable::class))->isSuperTypeOf($scope->getType($stmt->expr))->no()) { $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $stmt->expr); } return new \PHPStan\Analyser\StatementResult($finalScope, $finalScopeResult->hasYield() || $condResult->hasYield(), $isIterableAtLeastOnce->yes() && $finalScopeResult->isAlwaysTerminating(), $finalScopeResult->getExitPointsForOuterLoop(), $throwPoints, $impurePoints); } elseif ($stmt instanceof While_) { $condResult = $this->processExprNode($stmt, $stmt->cond, $scope, static function () : void { }, \PHPStan\Analyser\ExpressionContext::createDeep()); $bodyScope = $condResult->getTruthyScope(); if ($context->isTopLevel()) { $count = 0; do { $prevScope = $bodyScope; $bodyScope = $bodyScope->mergeWith($scope); $bodyScope = $this->processExprNode($stmt, $stmt->cond, $bodyScope, static function () : void { }, \PHPStan\Analyser\ExpressionContext::createDeep())->getTruthyScope(); $bodyScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, static function () : void { }, $context->enterDeep())->filterOutLoopExitPoints(); $bodyScope = $bodyScopeResult->getScope(); foreach ($bodyScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $bodyScope = $bodyScope->mergeWith($continueExitPoint->getScope()); } if ($bodyScope->equals($prevScope)) { break; } if ($count >= self::GENERALIZE_AFTER_ITERATION) { $bodyScope = $prevScope->generalizeWith($bodyScope); } $count++; } while ($count < self::LOOP_SCOPE_ITERATIONS); } $bodyScope = $bodyScope->mergeWith($scope); $bodyScopeMaybeRan = $bodyScope; $bodyScope = $this->processExprNode($stmt, $stmt->cond, $bodyScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep())->getTruthyScope(); $finalScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, $nodeCallback, $context)->filterOutLoopExitPoints(); $finalScope = $finalScopeResult->getScope()->filterByFalseyValue($stmt->cond); $condBooleanType = ($this->treatPhpDocTypesAsCertain ? $bodyScopeMaybeRan->getType($stmt->cond) : $bodyScopeMaybeRan->getNativeType($stmt->cond))->toBoolean(); $alwaysIterates = $condBooleanType->isTrue()->yes() && $context->isTopLevel(); $neverIterates = $condBooleanType->isFalse()->yes() && $context->isTopLevel(); if (!$alwaysIterates) { foreach ($finalScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $finalScope = $finalScope->mergeWith($continueExitPoint->getScope()); } } $breakExitPoints = $finalScopeResult->getExitPointsByType(Break_::class); foreach ($breakExitPoints as $breakExitPoint) { $finalScope = $finalScope->mergeWith($breakExitPoint->getScope()); } $beforeCondBooleanType = ($this->treatPhpDocTypesAsCertain ? $scope->getType($stmt->cond) : $scope->getNativeType($stmt->cond))->toBoolean(); $isIterableAtLeastOnce = $beforeCondBooleanType->isTrue()->yes(); $nodeCallback(new BreaklessWhileLoopNode($stmt, $finalScopeResult->getExitPoints()), $bodyScopeMaybeRan); if ($alwaysIterates) { $isAlwaysTerminating = count($finalScopeResult->getExitPointsByType(Break_::class)) === 0; } elseif ($isIterableAtLeastOnce) { $isAlwaysTerminating = $finalScopeResult->isAlwaysTerminating(); } else { $isAlwaysTerminating = \false; } $condScope = $condResult->getFalseyScope(); if (!$isIterableAtLeastOnce) { if (!$this->polluteScopeWithLoopInitialAssignments) { $condScope = $condScope->mergeWith($scope); } $finalScope = $finalScope->mergeWith($condScope); } $throwPoints = $overridingThrowPoints ?? $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); if (!$neverIterates) { $throwPoints = array_merge($throwPoints, $finalScopeResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $finalScopeResult->getImpurePoints()); } return new \PHPStan\Analyser\StatementResult($finalScope, $finalScopeResult->hasYield() || $condResult->hasYield(), $isAlwaysTerminating, $finalScopeResult->getExitPointsForOuterLoop(), $throwPoints, $impurePoints); } elseif ($stmt instanceof Do_) { $finalScope = null; $bodyScope = $scope; $count = 0; $hasYield = \false; $throwPoints = []; $impurePoints = []; if ($context->isTopLevel()) { do { $prevScope = $bodyScope; $bodyScope = $bodyScope->mergeWith($scope); $bodyScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, static function () : void { }, $context->enterDeep())->filterOutLoopExitPoints(); $alwaysTerminating = $bodyScopeResult->isAlwaysTerminating(); $bodyScope = $bodyScopeResult->getScope(); foreach ($bodyScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $bodyScope = $bodyScope->mergeWith($continueExitPoint->getScope()); } $finalScope = $alwaysTerminating ? $finalScope : $bodyScope->mergeWith($finalScope); foreach ($bodyScopeResult->getExitPointsByType(Break_::class) as $breakExitPoint) { $finalScope = $breakExitPoint->getScope()->mergeWith($finalScope); } $bodyScope = $this->processExprNode($stmt, $stmt->cond, $bodyScope, static function () : void { }, \PHPStan\Analyser\ExpressionContext::createDeep())->getTruthyScope(); if ($bodyScope->equals($prevScope)) { break; } if ($count >= self::GENERALIZE_AFTER_ITERATION) { $bodyScope = $prevScope->generalizeWith($bodyScope); } $count++; } while ($count < self::LOOP_SCOPE_ITERATIONS); $bodyScope = $bodyScope->mergeWith($scope); } $bodyScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, $nodeCallback, $context)->filterOutLoopExitPoints(); $bodyScope = $bodyScopeResult->getScope(); foreach ($bodyScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $bodyScope = $bodyScope->mergeWith($continueExitPoint->getScope()); } $condBooleanType = ($this->treatPhpDocTypesAsCertain ? $bodyScope->getType($stmt->cond) : $bodyScope->getNativeType($stmt->cond))->toBoolean(); $alwaysIterates = $condBooleanType->isTrue()->yes() && $context->isTopLevel(); $nodeCallback(new DoWhileLoopConditionNode($stmt->cond, $bodyScopeResult->getExitPoints()), $bodyScope); if ($alwaysIterates) { $alwaysTerminating = count($bodyScopeResult->getExitPointsByType(Break_::class)) === 0; } else { $alwaysTerminating = $bodyScopeResult->isAlwaysTerminating(); } $finalScope = $alwaysTerminating ? $finalScope : $bodyScope->mergeWith($finalScope); if ($finalScope === null) { $finalScope = $scope; } if (!$alwaysTerminating) { $condResult = $this->processExprNode($stmt, $stmt->cond, $bodyScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $hasYield = $condResult->hasYield(); $throwPoints = $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); $finalScope = $condResult->getFalseyScope(); } else { $this->processExprNode($stmt, $stmt->cond, $bodyScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); } foreach ($bodyScopeResult->getExitPointsByType(Break_::class) as $breakExitPoint) { $finalScope = $breakExitPoint->getScope()->mergeWith($finalScope); } return new \PHPStan\Analyser\StatementResult($finalScope, $bodyScopeResult->hasYield() || $hasYield, $alwaysTerminating, $bodyScopeResult->getExitPointsForOuterLoop(), array_merge($throwPoints, $bodyScopeResult->getThrowPoints()), array_merge($impurePoints, $bodyScopeResult->getImpurePoints())); } elseif ($stmt instanceof For_) { $initScope = $scope; $hasYield = \false; $throwPoints = []; $impurePoints = []; foreach ($stmt->init as $initExpr) { $initResult = $this->processExprNode($stmt, $initExpr, $initScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createTopLevel()); $initScope = $initResult->getScope(); $hasYield = $hasYield || $initResult->hasYield(); $throwPoints = array_merge($throwPoints, $initResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $initResult->getImpurePoints()); } $bodyScope = $initScope; $isIterableAtLeastOnce = TrinaryLogic::createYes(); $lastCondExpr = $stmt->cond[count($stmt->cond) - 1] ?? null; foreach ($stmt->cond as $condExpr) { $condResult = $this->processExprNode($stmt, $condExpr, $bodyScope, static function () : void { }, \PHPStan\Analyser\ExpressionContext::createDeep()); $initScope = $condResult->getScope(); $condResultScope = $condResult->getScope(); if ($condExpr === $lastCondExpr) { $condTruthiness = ($this->treatPhpDocTypesAsCertain ? $condResultScope->getType($condExpr) : $condResultScope->getNativeType($condExpr))->toBoolean(); $isIterableAtLeastOnce = $isIterableAtLeastOnce->and($condTruthiness->isTrue()); } $hasYield = $hasYield || $condResult->hasYield(); $throwPoints = array_merge($throwPoints, $condResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $condResult->getImpurePoints()); $bodyScope = $condResult->getTruthyScope(); } if ($context->isTopLevel()) { $count = 0; do { $prevScope = $bodyScope; $bodyScope = $bodyScope->mergeWith($initScope); if ($lastCondExpr !== null) { $bodyScope = $this->processExprNode($stmt, $lastCondExpr, $bodyScope, static function () : void { }, \PHPStan\Analyser\ExpressionContext::createDeep())->getTruthyScope(); } $bodyScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, static function () : void { }, $context->enterDeep())->filterOutLoopExitPoints(); $bodyScope = $bodyScopeResult->getScope(); foreach ($bodyScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $bodyScope = $bodyScope->mergeWith($continueExitPoint->getScope()); } foreach ($stmt->loop as $loopExpr) { $exprResult = $this->processExprNode($stmt, $loopExpr, $bodyScope, static function () : void { }, \PHPStan\Analyser\ExpressionContext::createTopLevel()); $bodyScope = $exprResult->getScope(); $hasYield = $hasYield || $exprResult->hasYield(); $throwPoints = array_merge($throwPoints, $exprResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $exprResult->getImpurePoints()); } if ($bodyScope->equals($prevScope)) { break; } if ($count >= self::GENERALIZE_AFTER_ITERATION) { $bodyScope = $prevScope->generalizeWith($bodyScope); } $count++; } while ($count < self::LOOP_SCOPE_ITERATIONS); } $bodyScope = $bodyScope->mergeWith($initScope); $alwaysIterates = TrinaryLogic::createFromBoolean($context->isTopLevel()); if ($lastCondExpr !== null) { $alwaysIterates = $alwaysIterates->and($bodyScope->getType($lastCondExpr)->toBoolean()->isTrue()); $bodyScope = $this->processExprNode($stmt, $lastCondExpr, $bodyScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep())->getTruthyScope(); } $finalScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, $nodeCallback, $context)->filterOutLoopExitPoints(); $finalScope = $finalScopeResult->getScope(); foreach ($finalScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $finalScope = $continueExitPoint->getScope()->mergeWith($finalScope); } $loopScope = $finalScope; foreach ($stmt->loop as $loopExpr) { $loopScope = $this->processExprNode($stmt, $loopExpr, $loopScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createTopLevel())->getScope(); } $finalScope = $finalScope->generalizeWith($loopScope); if ($lastCondExpr !== null) { $finalScope = $finalScope->filterByFalseyValue($lastCondExpr); } foreach ($finalScopeResult->getExitPointsByType(Break_::class) as $breakExitPoint) { $finalScope = $breakExitPoint->getScope()->mergeWith($finalScope); } if ($isIterableAtLeastOnce->no() || $finalScopeResult->isAlwaysTerminating()) { if ($this->polluteScopeWithLoopInitialAssignments) { $finalScope = $initScope; } else { $finalScope = $scope; } } elseif ($isIterableAtLeastOnce->maybe()) { if ($this->polluteScopeWithLoopInitialAssignments) { $finalScope = $finalScope->mergeWith($initScope); } else { $finalScope = $finalScope->mergeWith($scope); } } else { if (!$this->polluteScopeWithLoopInitialAssignments) { $finalScope = $finalScope->mergeWith($scope); } } if ($alwaysIterates->yes()) { $isAlwaysTerminating = count($finalScopeResult->getExitPointsByType(Break_::class)) === 0; } elseif ($isIterableAtLeastOnce->yes()) { $isAlwaysTerminating = $finalScopeResult->isAlwaysTerminating(); } else { $isAlwaysTerminating = \false; } return new \PHPStan\Analyser\StatementResult($finalScope, $finalScopeResult->hasYield() || $hasYield, $isAlwaysTerminating, $finalScopeResult->getExitPointsForOuterLoop(), array_merge($throwPoints, $finalScopeResult->getThrowPoints()), array_merge($impurePoints, $finalScopeResult->getImpurePoints())); } elseif ($stmt instanceof Switch_) { $condResult = $this->processExprNode($stmt, $stmt->cond, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scope = $condResult->getScope(); $scopeForBranches = $scope; $finalScope = null; $prevScope = null; $hasDefaultCase = \false; $alwaysTerminating = \true; $hasYield = $condResult->hasYield(); $exitPointsForOuterLoop = []; $throwPoints = $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); $fullCondExpr = null; foreach ($stmt->cases as $caseNode) { if ($caseNode->cond !== null) { $condExpr = new BinaryOp\Equal($stmt->cond, $caseNode->cond); $fullCondExpr = $fullCondExpr === null ? $condExpr : new BooleanOr($fullCondExpr, $condExpr); $caseResult = $this->processExprNode($stmt, $caseNode->cond, $scopeForBranches, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scopeForBranches = $caseResult->getScope(); $hasYield = $hasYield || $caseResult->hasYield(); $throwPoints = array_merge($throwPoints, $caseResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $caseResult->getImpurePoints()); $branchScope = $caseResult->getTruthyScope()->filterByTruthyValue($condExpr); } else { $hasDefaultCase = \true; $fullCondExpr = null; $branchScope = $scopeForBranches; } $branchScope = $branchScope->mergeWith($prevScope); $branchScopeResult = $this->processStmtNodes($caseNode, $caseNode->stmts, $branchScope, $nodeCallback, $context); $branchScope = $branchScopeResult->getScope(); $branchFinalScopeResult = $branchScopeResult->filterOutLoopExitPoints(); $hasYield = $hasYield || $branchFinalScopeResult->hasYield(); foreach ($branchScopeResult->getExitPointsByType(Break_::class) as $breakExitPoint) { $alwaysTerminating = \false; $finalScope = $breakExitPoint->getScope()->mergeWith($finalScope); } foreach ($branchScopeResult->getExitPointsByType(Continue_::class) as $continueExitPoint) { $finalScope = $continueExitPoint->getScope()->mergeWith($finalScope); } $exitPointsForOuterLoop = array_merge($exitPointsForOuterLoop, $branchFinalScopeResult->getExitPointsForOuterLoop()); $throwPoints = array_merge($throwPoints, $branchFinalScopeResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $branchFinalScopeResult->getImpurePoints()); if ($branchScopeResult->isAlwaysTerminating()) { $alwaysTerminating = $alwaysTerminating && $branchFinalScopeResult->isAlwaysTerminating(); $prevScope = null; if (isset($fullCondExpr)) { $scopeForBranches = $scopeForBranches->filterByFalseyValue($fullCondExpr); $fullCondExpr = null; } if (!$branchFinalScopeResult->isAlwaysTerminating()) { $finalScope = $branchScope->mergeWith($finalScope); } } else { $prevScope = $branchScope; } } $exhaustive = $scopeForBranches->getType($stmt->cond) instanceof NeverType; if (!$hasDefaultCase && !$exhaustive) { $alwaysTerminating = \false; } if ($prevScope !== null && isset($branchFinalScopeResult)) { $finalScope = $prevScope->mergeWith($finalScope); $alwaysTerminating = $alwaysTerminating && $branchFinalScopeResult->isAlwaysTerminating(); } if (!$hasDefaultCase && !$exhaustive || $finalScope === null) { $finalScope = $scope->mergeWith($finalScope); } return new \PHPStan\Analyser\StatementResult($finalScope, $hasYield, $alwaysTerminating, $exitPointsForOuterLoop, $throwPoints, $impurePoints); } elseif ($stmt instanceof TryCatch) { $branchScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $scope, $nodeCallback, $context); $branchScope = $branchScopeResult->getScope(); $finalScope = $branchScopeResult->isAlwaysTerminating() ? null : $branchScope; $exitPoints = []; $finallyExitPoints = []; $alwaysTerminating = $branchScopeResult->isAlwaysTerminating(); $hasYield = $branchScopeResult->hasYield(); if ($stmt->finally !== null) { $finallyScope = $branchScope; } else { $finallyScope = null; } foreach ($branchScopeResult->getExitPoints() as $exitPoint) { $finallyExitPoints[] = $exitPoint; if ($exitPoint->getStatement() instanceof Throw_) { continue; } if ($finallyScope !== null) { $finallyScope = $finallyScope->mergeWith($exitPoint->getScope()); } $exitPoints[] = $exitPoint; } $throwPoints = $branchScopeResult->getThrowPoints(); $impurePoints = $branchScopeResult->getImpurePoints(); $throwPointsForLater = []; $pastCatchTypes = new NeverType(); foreach ($stmt->catches as $catchNode) { $nodeCallback($catchNode, $scope); $originalCatchTypes = array_map(static function (Name $name) : Type { return new ObjectType($name->toString()); }, $catchNode->types); $catchTypes = array_map(static function (Type $type) use($pastCatchTypes) : Type { return TypeCombinator::remove($type, $pastCatchTypes); }, $originalCatchTypes); $originalCatchType = TypeCombinator::union(...$originalCatchTypes); $catchType = TypeCombinator::union(...$catchTypes); $pastCatchTypes = TypeCombinator::union($pastCatchTypes, $originalCatchType); $matchingThrowPoints = []; $matchingCatchTypes = array_fill_keys(array_keys($originalCatchTypes), \false); // throwable matches all foreach ($originalCatchTypes as $catchTypeIndex => $catchTypeItem) { if (!$catchTypeItem->isSuperTypeOf(new ObjectType(Throwable::class))->yes()) { continue; } foreach ($throwPoints as $throwPointIndex => $throwPoint) { $matchingThrowPoints[$throwPointIndex] = $throwPoint; $matchingCatchTypes[$catchTypeIndex] = \true; } } // explicit only $onlyExplicitIsThrow = \true; if (count($matchingThrowPoints) === 0) { foreach ($throwPoints as $throwPointIndex => $throwPoint) { foreach ($catchTypes as $catchTypeIndex => $catchTypeItem) { if ($catchTypeItem->isSuperTypeOf($throwPoint->getType())->no()) { continue; } $matchingCatchTypes[$catchTypeIndex] = \true; if (!$throwPoint->isExplicit()) { continue; } $throwNode = $throwPoint->getNode(); if (!$throwNode instanceof Throw_ && !$throwNode instanceof Expr\Throw_ && !($throwNode instanceof Node\Stmt\Expression && $throwNode->expr instanceof Expr\Throw_)) { $onlyExplicitIsThrow = \false; } $matchingThrowPoints[$throwPointIndex] = $throwPoint; } } } // implicit only if (count($matchingThrowPoints) === 0 || $this->explicitThrow && $onlyExplicitIsThrow) { foreach ($throwPoints as $throwPointIndex => $throwPoint) { if ($throwPoint->isExplicit()) { continue; } foreach ($catchTypes as $catchTypeIndex => $catchTypeItem) { if ($catchTypeItem->isSuperTypeOf($throwPoint->getType())->no()) { continue; } $matchingThrowPoints[$throwPointIndex] = $throwPoint; } } } // include previously removed throw points if (count($matchingThrowPoints) === 0) { if ($originalCatchType->isSuperTypeOf(new ObjectType(Throwable::class))->yes()) { foreach ($branchScopeResult->getThrowPoints() as $originalThrowPoint) { if (!$originalThrowPoint->canContainAnyThrowable()) { continue; } $matchingThrowPoints[] = $originalThrowPoint; $matchingCatchTypes = array_fill_keys(array_keys($originalCatchTypes), \true); } } } // emit error if ($this->detectDeadTypeInMultiCatch) { foreach ($matchingCatchTypes as $catchTypeIndex => $matched) { if ($matched) { continue; } $nodeCallback(new CatchWithUnthrownExceptionNode($catchNode, $catchTypes[$catchTypeIndex], $originalCatchTypes[$catchTypeIndex]), $scope); } } if (count($matchingThrowPoints) === 0) { if (!$this->detectDeadTypeInMultiCatch) { $nodeCallback(new CatchWithUnthrownExceptionNode($catchNode, $catchType, $originalCatchType), $scope); } continue; } // recompute throw points $newThrowPoints = []; foreach ($throwPoints as $throwPoint) { $newThrowPoint = $throwPoint->subtractCatchType($originalCatchType); if ($newThrowPoint->getType() instanceof NeverType) { continue; } $newThrowPoints[] = $newThrowPoint; } $throwPoints = $newThrowPoints; $catchScope = null; foreach ($matchingThrowPoints as $matchingThrowPoint) { if ($catchScope === null) { $catchScope = $matchingThrowPoint->getScope(); } else { $catchScope = $catchScope->mergeWith($matchingThrowPoint->getScope()); } } $variableName = null; if ($catchNode->var !== null) { if (!is_string($catchNode->var->name)) { throw new ShouldNotHappenException(); } $variableName = $catchNode->var->name; } $catchScopeResult = $this->processStmtNodes($catchNode, $catchNode->stmts, $catchScope->enterCatchType($catchType, $variableName), $nodeCallback, $context); $catchScopeForFinally = $catchScopeResult->getScope(); $finalScope = $catchScopeResult->isAlwaysTerminating() ? $finalScope : $catchScopeResult->getScope()->mergeWith($finalScope); $alwaysTerminating = $alwaysTerminating && $catchScopeResult->isAlwaysTerminating(); $hasYield = $hasYield || $catchScopeResult->hasYield(); $catchThrowPoints = $catchScopeResult->getThrowPoints(); $impurePoints = array_merge($impurePoints, $catchScopeResult->getImpurePoints()); $throwPointsForLater = array_merge($throwPointsForLater, $catchThrowPoints); if ($finallyScope !== null) { $finallyScope = $finallyScope->mergeWith($catchScopeForFinally); } foreach ($catchScopeResult->getExitPoints() as $exitPoint) { $finallyExitPoints[] = $exitPoint; if ($exitPoint->getStatement() instanceof Throw_) { continue; } if ($finallyScope !== null) { $finallyScope = $finallyScope->mergeWith($exitPoint->getScope()); } $exitPoints[] = $exitPoint; } foreach ($catchThrowPoints as $catchThrowPoint) { if ($finallyScope === null) { continue; } $finallyScope = $finallyScope->mergeWith($catchThrowPoint->getScope()); } } if ($finalScope === null) { $finalScope = $scope; } foreach ($throwPoints as $throwPoint) { if ($finallyScope === null) { continue; } $finallyScope = $finallyScope->mergeWith($throwPoint->getScope()); } if ($finallyScope !== null && $stmt->finally !== null) { $originalFinallyScope = $finallyScope; $finallyResult = $this->processStmtNodes($stmt->finally, $stmt->finally->stmts, $finallyScope, $nodeCallback, $context); $alwaysTerminating = $alwaysTerminating || $finallyResult->isAlwaysTerminating(); $hasYield = $hasYield || $finallyResult->hasYield(); $throwPointsForLater = array_merge($throwPointsForLater, $finallyResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $finallyResult->getImpurePoints()); $finallyScope = $finallyResult->getScope(); $finalScope = $finallyResult->isAlwaysTerminating() ? $finalScope : $finalScope->processFinallyScope($finallyScope, $originalFinallyScope); if (count($finallyResult->getExitPoints()) > 0) { $nodeCallback(new FinallyExitPointsNode($finallyResult->getExitPoints(), $finallyExitPoints), $scope); } $exitPoints = array_merge($exitPoints, $finallyResult->getExitPoints()); } return new \PHPStan\Analyser\StatementResult($finalScope, $hasYield, $alwaysTerminating, $exitPoints, array_merge($throwPoints, $throwPointsForLater), $impurePoints); } elseif ($stmt instanceof Unset_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; foreach ($stmt->vars as $var) { $scope = $this->lookForSetAllowedUndefinedExpressions($scope, $var); $exprResult = $this->processExprNode($stmt, $var, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scope = $exprResult->getScope(); $scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $var); $hasYield = $hasYield || $exprResult->hasYield(); $throwPoints = array_merge($throwPoints, $exprResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $exprResult->getImpurePoints()); if ($var instanceof ArrayDimFetch && $var->dim !== null) { $cloningTraverser = new NodeTraverser(); $cloningTraverser->addVisitor(new CloningVisitor()); /** @var Expr $clonedVar */ [$clonedVar] = $cloningTraverser->traverse([$var->var]); $traverser = new NodeTraverser(); $traverser->addVisitor(new class extends NodeVisitorAbstract { public function leaveNode(Node $node) : ?ExistingArrayDimFetch { if (!$node instanceof ArrayDimFetch || $node->dim === null) { return null; } return new ExistingArrayDimFetch($node->var, $node->dim); } }); /** @var Expr $clonedVar */ [$clonedVar] = $traverser->traverse([$clonedVar]); $scope = $this->processAssignVar($scope, $stmt, $clonedVar, new UnsetOffsetExpr($var->var, $var->dim), static function (Node $node, \PHPStan\Analyser\Scope $scope) use($nodeCallback) : void { if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) { return; } $nodeCallback($node, $scope); }, \PHPStan\Analyser\ExpressionContext::createDeep(), static function (\PHPStan\Analyser\MutatingScope $scope) : \PHPStan\Analyser\ExpressionResult { return new \PHPStan\Analyser\ExpressionResult($scope, \false, [], []); }, \false)->getScope(); } elseif ($var instanceof PropertyFetch) { $scope = $scope->invalidateExpression($var); $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $var, 'propertyUnset', 'property unset', \true); } else { $scope = $scope->invalidateExpression($var); } } } elseif ($stmt instanceof Node\Stmt\Use_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; foreach ($stmt->uses as $use) { $nodeCallback($use, $scope); } } elseif ($stmt instanceof Node\Stmt\Global_) { $hasYield = \false; $throwPoints = []; $impurePoints = [new \PHPStan\Analyser\ImpurePoint($scope, $stmt, 'global', 'global variable', \true)]; $vars = []; foreach ($stmt->vars as $var) { if (!$var instanceof Variable) { throw new ShouldNotHappenException(); } $scope = $this->lookForSetAllowedUndefinedExpressions($scope, $var); $varResult = $this->processExprNode($stmt, $var, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $impurePoints = array_merge($impurePoints, $varResult->getImpurePoints()); $scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $var); if (!is_string($var->name)) { continue; } $scope = $scope->assignVariable($var->name, new MixedType(), new MixedType()); $vars[] = $var->name; } $scope = $this->processVarAnnotation($scope, $vars, $stmt); } elseif ($stmt instanceof Static_) { $hasYield = \false; $throwPoints = []; $impurePoints = [new \PHPStan\Analyser\ImpurePoint($scope, $stmt, 'static', 'static variable', \true)]; $vars = []; foreach ($stmt->vars as $var) { if (!is_string($var->var->name)) { throw new ShouldNotHappenException(); } if ($var->default !== null) { $defaultExprResult = $this->processExprNode($stmt, $var->default, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $impurePoints = array_merge($impurePoints, $defaultExprResult->getImpurePoints()); } $scope = $scope->enterExpressionAssign($var->var); $varResult = $this->processExprNode($stmt, $var->var, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $impurePoints = array_merge($impurePoints, $varResult->getImpurePoints()); $scope = $scope->exitExpressionAssign($var->var); $scope = $scope->assignVariable($var->var->name, new MixedType(), new MixedType()); $vars[] = $var->var->name; } $scope = $this->processVarAnnotation($scope, $vars, $stmt); } elseif ($stmt instanceof Node\Stmt\Const_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; foreach ($stmt->consts as $const) { $nodeCallback($const, $scope); $constResult = $this->processExprNode($stmt, $const->value, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $impurePoints = array_merge($impurePoints, $constResult->getImpurePoints()); if ($const->namespacedName !== null) { $constantName = new Name\FullyQualified($const->namespacedName->toString()); } else { if ($const->name->toString() === '') { throw new ShouldNotHappenException('Constant cannot have a empty name'); } $constantName = new Name\FullyQualified($const->name->toString()); } $scope = $scope->assignExpression(new ConstFetch($constantName), $scope->getType($const->value), $scope->getNativeType($const->value)); } } elseif ($stmt instanceof Node\Stmt\ClassConst) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $this->processAttributeGroups($stmt, $stmt->attrGroups, $scope, $nodeCallback); foreach ($stmt->consts as $const) { $nodeCallback($const, $scope); $constResult = $this->processExprNode($stmt, $const->value, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $impurePoints = array_merge($impurePoints, $constResult->getImpurePoints()); if ($scope->getClassReflection() === null) { throw new ShouldNotHappenException(); } $scope = $scope->assignExpression(new Expr\ClassConstFetch(new Name\FullyQualified($scope->getClassReflection()->getName()), $const->name), $scope->getType($const->value), $scope->getNativeType($const->value)); } } elseif ($stmt instanceof Node\Stmt\EnumCase) { $hasYield = \false; $throwPoints = []; $this->processAttributeGroups($stmt, $stmt->attrGroups, $scope, $nodeCallback); $impurePoints = []; if ($stmt->expr !== null) { $exprResult = $this->processExprNode($stmt, $stmt->expr, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $impurePoints = $exprResult->getImpurePoints(); } } elseif ($stmt instanceof InlineHTML) { $hasYield = \false; $throwPoints = []; $impurePoints = [new \PHPStan\Analyser\ImpurePoint($scope, $stmt, 'betweenPhpTags', 'output between PHP opening and closing tags', \true)]; } elseif ($stmt instanceof Node\Stmt\Nop) { $hasYield = \false; $throwPoints = $overridingThrowPoints ?? []; $impurePoints = []; } elseif ($stmt instanceof Node\Stmt\GroupUse) { $hasYield = \false; $throwPoints = []; foreach ($stmt->uses as $use) { $nodeCallback($use, $scope); } $impurePoints = []; } else { $hasYield = \false; $throwPoints = $overridingThrowPoints ?? []; $impurePoints = []; } return new \PHPStan\Analyser\StatementResult($scope, $hasYield, \false, [], $throwPoints, $impurePoints); } /** * @return ThrowPoint[]|null */ private function getOverridingThrowPoints(Node\Stmt $statement, \PHPStan\Analyser\MutatingScope $scope) : ?array { foreach ($statement->getComments() as $comment) { if (!$comment instanceof Doc) { continue; } $function = $scope->getFunction(); $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $function !== null ? $function->getName() : null, $comment->getText()); $throwsTag = $resolvedPhpDoc->getThrowsTag(); if ($throwsTag !== null) { $throwsType = $throwsTag->getType(); if ($throwsType->isVoid()->yes()) { return []; } return [\PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwsType, $statement, \false)]; } } return null; } private function getCurrentClassReflection(Node\Stmt\ClassLike $stmt, string $className, \PHPStan\Analyser\Scope $scope) : ClassReflection { if (!$this->reflectionProvider->hasClass($className)) { return $this->createAstClassReflection($stmt, $className, $scope); } $defaultClassReflection = $this->reflectionProvider->getClass($className); if ($defaultClassReflection->getFileName() !== $scope->getFile()) { return $this->createAstClassReflection($stmt, $className, $scope); } $startLine = $defaultClassReflection->getNativeReflection()->getStartLine(); if ($startLine !== $stmt->getStartLine()) { return $this->createAstClassReflection($stmt, $className, $scope); } return $defaultClassReflection; } private function createAstClassReflection(Node\Stmt\ClassLike $stmt, string $className, \PHPStan\Analyser\Scope $scope) : ClassReflection { $nodeToReflection = new NodeToReflection(); $betterReflectionClass = $nodeToReflection->__invoke($this->reflector, $stmt, new LocatedSource(FileReader::read($scope->getFile()), $className, $scope->getFile()), $scope->getNamespace() !== null ? new Node\Stmt\Namespace_(new Name($scope->getNamespace())) : null); if (!$betterReflectionClass instanceof \PHPStan\BetterReflection\Reflection\ReflectionClass) { throw new ShouldNotHappenException(); } $enumAdapter = base64_decode('UEhQU3RhblxCZXR0ZXJSZWZsZWN0aW9uXFJlZmxlY3Rpb25cQWRhcHRlclxSZWZsZWN0aW9uRW51bQ==', \true); return new ClassReflection($this->reflectionProvider, $this->initializerExprTypeResolver, $this->fileTypeMapper, $this->stubPhpDocProvider, $this->phpDocInheritanceResolver, $this->phpVersion, $this->signatureMapProvider, $this->classReflectionExtensionRegistryProvider->getRegistry()->getPropertiesClassReflectionExtensions(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getMethodsClassReflectionExtensions(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getAllowedSubTypesClassReflectionExtensions(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsPropertyClassReflectionExtension(), $this->classReflectionExtensionRegistryProvider->getRegistry()->getRequireExtendsMethodsClassReflectionExtension(), $betterReflectionClass->getName(), $betterReflectionClass instanceof ReflectionEnum && PHP_VERSION_ID >= 80000 ? new $enumAdapter($betterReflectionClass) : new ReflectionClass($betterReflectionClass), null, null, null, $this->universalObjectCratesClasses, sprintf('%s:%d', $scope->getFile(), $stmt->getStartLine())); } private function lookForSetAllowedUndefinedExpressions(\PHPStan\Analyser\MutatingScope $scope, Expr $expr) : \PHPStan\Analyser\MutatingScope { return $this->lookForExpressionCallback($scope, $expr, static function (\PHPStan\Analyser\MutatingScope $scope, Expr $expr) : \PHPStan\Analyser\MutatingScope { return $scope->setAllowedUndefinedExpression($expr); }); } private function lookForUnsetAllowedUndefinedExpressions(\PHPStan\Analyser\MutatingScope $scope, Expr $expr) : \PHPStan\Analyser\MutatingScope { return $this->lookForExpressionCallback($scope, $expr, static function (\PHPStan\Analyser\MutatingScope $scope, Expr $expr) : \PHPStan\Analyser\MutatingScope { return $scope->unsetAllowedUndefinedExpression($expr); }); } /** * @param Closure(MutatingScope $scope, Expr $expr): MutatingScope $callback */ private function lookForExpressionCallback(\PHPStan\Analyser\MutatingScope $scope, Expr $expr, Closure $callback) : \PHPStan\Analyser\MutatingScope { if (!$expr instanceof ArrayDimFetch || $expr->dim !== null) { $scope = $callback($scope, $expr); } if ($expr instanceof ArrayDimFetch) { $scope = $this->lookForExpressionCallback($scope, $expr->var, $callback); } elseif ($expr instanceof PropertyFetch || $expr instanceof Expr\NullsafePropertyFetch) { $scope = $this->lookForExpressionCallback($scope, $expr->var, $callback); } elseif ($expr instanceof StaticPropertyFetch && $expr->class instanceof Expr) { $scope = $this->lookForExpressionCallback($scope, $expr->class, $callback); } elseif ($expr instanceof Array_ || $expr instanceof List_) { foreach ($expr->items as $item) { if ($item === null) { continue; } $scope = $this->lookForExpressionCallback($scope, $item->value, $callback); } } return $scope; } private function ensureShallowNonNullability(\PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\Scope $originalScope, Expr $exprToSpecify) : \PHPStan\Analyser\EnsuredNonNullabilityResult { $exprType = $scope->getType($exprToSpecify); $isNull = $exprType->isNull(); if ($isNull->yes()) { return new \PHPStan\Analyser\EnsuredNonNullabilityResult($scope, []); } // keep certainty $certainty = TrinaryLogic::createYes(); $hasExpressionType = $originalScope->hasExpressionType($exprToSpecify); if (!$hasExpressionType->no()) { $certainty = $hasExpressionType; } $exprTypeWithoutNull = TypeCombinator::removeNull($exprType); if ($exprType->equals($exprTypeWithoutNull)) { $originalExprType = $originalScope->getType($exprToSpecify); if (!$originalExprType->equals($exprTypeWithoutNull)) { $originalNativeType = $originalScope->getNativeType($exprToSpecify); return new \PHPStan\Analyser\EnsuredNonNullabilityResult($scope, [new \PHPStan\Analyser\EnsuredNonNullabilityResultExpression($exprToSpecify, $originalExprType, $originalNativeType, $certainty)]); } return new \PHPStan\Analyser\EnsuredNonNullabilityResult($scope, []); } $nativeType = $scope->getNativeType($exprToSpecify); $scope = $scope->specifyExpressionType($exprToSpecify, $exprTypeWithoutNull, TypeCombinator::removeNull($nativeType)); return new \PHPStan\Analyser\EnsuredNonNullabilityResult($scope, [new \PHPStan\Analyser\EnsuredNonNullabilityResultExpression($exprToSpecify, $exprType, $nativeType, $certainty)]); } private function ensureNonNullability(\PHPStan\Analyser\MutatingScope $scope, Expr $expr) : \PHPStan\Analyser\EnsuredNonNullabilityResult { $specifiedExpressions = []; $originalScope = $scope; $scope = $this->lookForExpressionCallback($scope, $expr, function ($scope, $expr) use(&$specifiedExpressions, $originalScope) { $result = $this->ensureShallowNonNullability($scope, $originalScope, $expr); foreach ($result->getSpecifiedExpressions() as $specifiedExpression) { $specifiedExpressions[] = $specifiedExpression; } return $result->getScope(); }); return new \PHPStan\Analyser\EnsuredNonNullabilityResult($scope, $specifiedExpressions); } /** * @param EnsuredNonNullabilityResultExpression[] $specifiedExpressions */ private function revertNonNullability(\PHPStan\Analyser\MutatingScope $scope, array $specifiedExpressions) : \PHPStan\Analyser\MutatingScope { foreach ($specifiedExpressions as $specifiedExpressionResult) { $scope = $scope->specifyExpressionType($specifiedExpressionResult->getExpression(), $specifiedExpressionResult->getOriginalType(), $specifiedExpressionResult->getOriginalNativeType(), $specifiedExpressionResult->getCertainty()); } return $scope; } private function findEarlyTerminatingExpr(Expr $expr, \PHPStan\Analyser\Scope $scope) : ?Expr { if (($expr instanceof MethodCall || $expr instanceof Expr\StaticCall) && $expr->name instanceof Node\Identifier) { if (array_key_exists($expr->name->toLowerString(), $this->earlyTerminatingMethodNames)) { if ($expr instanceof MethodCall) { $methodCalledOnType = $scope->getType($expr->var); } else { if ($expr->class instanceof Name) { $methodCalledOnType = $scope->resolveTypeByName($expr->class); } else { $methodCalledOnType = $scope->getType($expr->class); } } foreach ($methodCalledOnType->getObjectClassNames() as $referencedClass) { if (!$this->reflectionProvider->hasClass($referencedClass)) { continue; } $classReflection = $this->reflectionProvider->getClass($referencedClass); foreach (array_merge([$referencedClass], $classReflection->getParentClassesNames(), $classReflection->getNativeReflection()->getInterfaceNames()) as $className) { if (!isset($this->earlyTerminatingMethodCalls[$className])) { continue; } if (in_array((string) $expr->name, $this->earlyTerminatingMethodCalls[$className], \true)) { return $expr; } } } } } if ($expr instanceof FuncCall && $expr->name instanceof Name) { if (in_array((string) $expr->name, $this->earlyTerminatingFunctionCalls, \true)) { return $expr; } } if ($expr instanceof Expr\Exit_ || $expr instanceof Expr\Throw_) { return $expr; } $exprType = $scope->getType($expr); if ($exprType instanceof NeverType && $exprType->isExplicit()) { return $expr; } return null; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ public function processExprNode(Node\Stmt $stmt, Expr $expr, \PHPStan\Analyser\MutatingScope $scope, callable $nodeCallback, \PHPStan\Analyser\ExpressionContext $context) : \PHPStan\Analyser\ExpressionResult { if ($expr instanceof Expr\CallLike && $expr->isFirstClassCallable()) { if ($expr instanceof FuncCall) { $newExpr = new FunctionCallableNode($expr->name, $expr); } elseif ($expr instanceof MethodCall) { $newExpr = new MethodCallableNode($expr->var, $expr->name, $expr); } elseif ($expr instanceof StaticCall) { $newExpr = new StaticMethodCallableNode($expr->class, $expr->name, $expr); } elseif ($expr instanceof New_ && !$expr->class instanceof Class_) { $newExpr = new InstantiationCallableNode($expr->class, $expr); } else { throw new ShouldNotHappenException(); } return $this->processExprNode($stmt, $newExpr, $scope, $nodeCallback, $context); } $this->callNodeCallbackWithExpression($nodeCallback, $expr, $scope, $context); if ($expr instanceof Variable) { $hasYield = \false; $throwPoints = []; $impurePoints = []; if ($expr->name instanceof Expr) { return $this->processExprNode($stmt, $expr->name, $scope, $nodeCallback, $context->enterDeep()); } elseif (in_array($expr->name, \PHPStan\Analyser\Scope::SUPERGLOBAL_VARIABLES, \true)) { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'superglobal', 'access to superglobal variable', \true); } } elseif ($expr instanceof Assign || $expr instanceof AssignRef) { $result = $this->processAssignVar($scope, $stmt, $expr->var, $expr->expr, $nodeCallback, $context, function (\PHPStan\Analyser\MutatingScope $scope) use($stmt, $expr, $nodeCallback, $context) : \PHPStan\Analyser\ExpressionResult { $impurePoints = []; if ($expr instanceof AssignRef) { $referencedExpr = $expr->expr; while ($referencedExpr instanceof ArrayDimFetch) { $referencedExpr = $referencedExpr->var; } if ($referencedExpr instanceof PropertyFetch || $referencedExpr instanceof StaticPropertyFetch) { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'propertyAssignByRef', 'property assignment by reference', \false); } $scope = $scope->enterExpressionAssign($expr->expr); } if ($expr->var instanceof Variable && is_string($expr->var->name)) { $context = $context->enterRightSideAssign($expr->var->name, $scope->getType($expr->expr), $scope->getNativeType($expr->expr)); } $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); if ($expr instanceof AssignRef) { $scope = $scope->exitExpressionAssign($expr->expr); } return new \PHPStan\Analyser\ExpressionResult($scope, $hasYield, $throwPoints, $impurePoints); }, \true); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $vars = $this->getAssignedVariables($expr->var); if (count($vars) > 0) { $varChangedScope = \false; $scope = $this->processVarAnnotation($scope, $vars, $stmt, $varChangedScope); if (!$varChangedScope) { $scope = $this->processStmtVarAnnotation($scope, $stmt, null, $nodeCallback); } } } elseif ($expr instanceof Expr\AssignOp) { $result = $this->processAssignVar($scope, $stmt, $expr->var, $expr, $nodeCallback, $context, function (\PHPStan\Analyser\MutatingScope $scope) use($stmt, $expr, $nodeCallback, $context) : \PHPStan\Analyser\ExpressionResult { $originalScope = $scope; if ($expr instanceof Expr\AssignOp\Coalesce) { $scope = $scope->filterByFalseyValue(new BinaryOp\NotIdentical($expr->var, new ConstFetch(new Name('null')))); } $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); if ($expr instanceof Expr\AssignOp\Coalesce) { return new \PHPStan\Analyser\ExpressionResult($result->getScope()->mergeWith($originalScope), $result->hasYield(), $result->getThrowPoints(), $result->getImpurePoints()); } return $result; }, $expr instanceof Expr\AssignOp\Coalesce); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); if (($expr instanceof Expr\AssignOp\Div || $expr instanceof Expr\AssignOp\Mod) && !$scope->getType($expr->expr)->toNumber()->isSuperTypeOf(new ConstantIntegerType(0))->no()) { $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createExplicit($scope, new ObjectType(DivisionByZeroError::class), $expr, \false); } } elseif ($expr instanceof FuncCall) { $parametersAcceptor = null; $functionReflection = null; $throwPoints = []; $impurePoints = []; if ($expr->name instanceof Expr) { $nameType = $scope->getType($expr->name); if (!$nameType->isCallable()->no()) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $nameType->getCallableParametersAcceptors($scope), null); } $nameResult = $this->processExprNode($stmt, $expr->name, $scope, $nodeCallback, $context->enterDeep()); $scope = $nameResult->getScope(); $throwPoints = $nameResult->getThrowPoints(); $impurePoints = $nameResult->getImpurePoints(); if ($nameType->isObject()->yes() && $nameType->isCallable()->yes() && (new ObjectType(Closure::class))->isSuperTypeOf($nameType)->no()) { $invokeResult = $this->processExprNode($stmt, new MethodCall($expr->name, '__invoke', $expr->getArgs(), $expr->getAttributes()), $scope, static function () : void { }, $context->enterDeep()); $throwPoints = array_merge($throwPoints, $invokeResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $invokeResult->getImpurePoints()); } elseif ($parametersAcceptor instanceof CallableParametersAcceptor) { $callableThrowPoints = array_map(static function (SimpleThrowPoint $throwPoint) use($scope, $expr) { return $throwPoint->isExplicit() ? \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwPoint->getType(), $expr, $throwPoint->canContainAnyThrowable()) : \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr); }, $parametersAcceptor->getThrowPoints()); if (!$this->implicitThrows) { $callableThrowPoints = array_values(array_filter($callableThrowPoints, static function (\PHPStan\Analyser\ThrowPoint $throwPoint) { return $throwPoint->isExplicit(); })); } $throwPoints = array_merge($throwPoints, $callableThrowPoints); $impurePoints = array_merge($impurePoints, array_map(static function (SimpleImpurePoint $impurePoint) use($scope, $expr) { return new \PHPStan\Analyser\ImpurePoint($scope, $expr, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()); }, $parametersAcceptor->getImpurePoints())); $scope = $this->processImmediatelyCalledCallable($scope, $parametersAcceptor->getInvalidateExpressions(), $parametersAcceptor->getUsedVariables()); } } elseif ($this->reflectionProvider->hasFunction($expr->name, $scope)) { $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $impurePoint = SimpleImpurePoint::createFromVariant($functionReflection, $parametersAcceptor); if ($impurePoint !== null) { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()); } } else { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'functionCall', 'call to unknown function', \false); } if ($parametersAcceptor !== null) { $expr = \PHPStan\Analyser\ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $expr) ?? $expr; } $result = $this->processArgs($stmt, $functionReflection, null, $parametersAcceptor, $expr, $scope, $nodeCallback, $context); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); if ($functionReflection !== null) { $functionThrowPoint = $this->getFunctionThrowPoint($functionReflection, $parametersAcceptor, $expr, $scope); if ($functionThrowPoint !== null) { $throwPoints[] = $functionThrowPoint; } } else { $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['json_encode', 'json_decode'], \true)) { $scope = $scope->invalidateExpression(new FuncCall(new Name('json_last_error'), []))->invalidateExpression(new FuncCall(new Name\FullyQualified('json_last_error'), []))->invalidateExpression(new FuncCall(new Name('json_last_error_msg'), []))->invalidateExpression(new FuncCall(new Name\FullyQualified('json_last_error_msg'), [])); } if ($functionReflection !== null && $functionReflection->getName() === 'file_put_contents' && count($expr->getArgs()) > 0) { $scope = $scope->invalidateExpression(new FuncCall(new Name('file_get_contents'), [$expr->getArgs()[0]]))->invalidateExpression(new FuncCall(new Name\FullyQualified('file_get_contents'), [$expr->getArgs()[0]])); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['array_pop', 'array_shift'], \true) && count($expr->getArgs()) >= 1) { $arrayArg = $expr->getArgs()[0]->value; $arrayArgType = $scope->getType($arrayArg); $arrayArgNativeType = $scope->getNativeType($arrayArg); $isArrayPop = $functionReflection->getName() === 'array_pop'; $scope = $scope->invalidateExpression($arrayArg)->assignExpression($arrayArg, $isArrayPop ? $arrayArgType->popArray() : $arrayArgType->shiftArray(), $isArrayPop ? $arrayArgNativeType->popArray() : $arrayArgNativeType->shiftArray()); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['array_push', 'array_unshift'], \true) && count($expr->getArgs()) >= 2) { $arrayType = $this->getArrayFunctionAppendingType($functionReflection, $scope, $expr); $arrayNativeType = $this->getArrayFunctionAppendingType($functionReflection, $scope->doNotTreatPhpDocTypesAsCertain(), $expr); $arrayArg = $expr->getArgs()[0]->value; $scope = $scope->invalidateExpression($arrayArg)->assignExpression($arrayArg, $arrayType, $arrayNativeType); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['fopen', 'file_get_contents'], \true)) { $scope = $scope->assignVariable('http_response_header', AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())), new ArrayType(new IntegerType(), new StringType())); } if ($functionReflection !== null && $functionReflection->getName() === 'shuffle') { $arrayArg = $expr->getArgs()[0]->value; $scope = $scope->assignExpression($arrayArg, $scope->getType($arrayArg)->shuffleArray(), $scope->getNativeType($arrayArg)->shuffleArray()); } if ($functionReflection !== null && $functionReflection->getName() === 'array_splice' && count($expr->getArgs()) >= 1) { $arrayArg = $expr->getArgs()[0]->value; $arrayArgType = $scope->getType($arrayArg); $valueType = $arrayArgType->getIterableValueType(); if (count($expr->getArgs()) >= 4) { $replacementType = $scope->getType($expr->getArgs()[3]->value)->toArray(); $valueType = TypeCombinator::union($valueType, $replacementType->getIterableValueType()); } $scope = $scope->invalidateExpression($arrayArg)->assignExpression($arrayArg, new ArrayType($arrayArgType->getIterableKeyType(), $valueType), new ArrayType($arrayArgType->getIterableKeyType(), $valueType)); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['sort', 'rsort', 'usort'], \true) && count($expr->getArgs()) >= 1) { $arrayArg = $expr->getArgs()[0]->value; $scope = $scope->assignExpression($arrayArg, $this->getArraySortPreserveListFunctionType($scope->getType($arrayArg)), $this->getArraySortPreserveListFunctionType($scope->getNativeType($arrayArg))); } if ($functionReflection !== null && in_array($functionReflection->getName(), ['natcasesort', 'natsort', 'arsort', 'asort', 'ksort', 'krsort', 'uasort', 'uksort'], \true) && count($expr->getArgs()) >= 1) { $arrayArg = $expr->getArgs()[0]->value; $scope = $scope->assignExpression($arrayArg, $this->getArraySortDoNotPreserveListFunctionType($scope->getType($arrayArg)), $this->getArraySortDoNotPreserveListFunctionType($scope->getNativeType($arrayArg))); } if ($functionReflection !== null && $functionReflection->getName() === 'extract') { $extractedArg = $expr->getArgs()[0]->value; $extractedType = $scope->getType($extractedArg); $constantArrays = $extractedType->getConstantArrays(); if (count($constantArrays) > 0) { $properties = []; $optionalProperties = []; $refCount = []; foreach ($constantArrays as $constantArray) { foreach ($constantArray->getKeyTypes() as $i => $keyType) { if ($keyType->isString()->no()) { // integers as variable names not allowed continue; } $key = (string) $keyType->getValue(); $valueType = $constantArray->getValueTypes()[$i]; $optional = $constantArray->isOptionalKey($i); if ($optional) { $optionalProperties[] = $key; } if (isset($properties[$key])) { $properties[$key] = TypeCombinator::union($properties[$key], $valueType); $refCount[$key]++; } else { $properties[$key] = $valueType; $refCount[$key] = 1; } } } foreach ($properties as $name => $type) { $optional = in_array($name, $optionalProperties, \true) || $refCount[$name] < count($constantArrays); $scope = $scope->assignVariable($name, $type, $type, $optional ? TrinaryLogic::createMaybe() : TrinaryLogic::createYes()); } } else { $scope = $scope->afterExtractCall(); } } if ($functionReflection !== null && in_array($functionReflection->getName(), ['clearstatcache', 'unlink'], \true)) { $scope = $scope->afterClearstatcacheCall(); } if ($functionReflection !== null && str_starts_with($functionReflection->getName(), 'openssl')) { $scope = $scope->afterOpenSslCall($functionReflection->getName()); } } elseif ($expr instanceof MethodCall) { $originalScope = $scope; if (($expr->var instanceof Expr\Closure || $expr->var instanceof Expr\ArrowFunction) && $expr->name instanceof Node\Identifier && strtolower($expr->name->name) === 'call' && isset($expr->getArgs()[0])) { $closureCallScope = $scope->enterClosureCall($scope->getType($expr->getArgs()[0]->value), $scope->getNativeType($expr->getArgs()[0]->value)); } $result = $this->processExprNode($stmt, $expr->var, $closureCallScope ?? $scope, $nodeCallback, $context->enterDeep()); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $scope = $result->getScope(); if (isset($closureCallScope)) { $scope = $scope->restoreOriginalScopeAfterClosureBind($originalScope); } $parametersAcceptor = null; $methodReflection = null; $calledOnType = $scope->getType($expr->var); if ($expr->name instanceof Expr) { $methodNameResult = $this->processExprNode($stmt, $expr->name, $scope, $nodeCallback, $context->enterDeep()); $throwPoints = array_merge($throwPoints, $methodNameResult->getThrowPoints()); $scope = $methodNameResult->getScope(); } else { $methodName = $expr->name->name; $methodReflection = $scope->getMethodReflection($calledOnType, $methodName); if ($methodReflection !== null) { $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); $methodThrowPoint = $this->getMethodThrowPoint($methodReflection, $parametersAcceptor, $expr, $scope); if ($methodThrowPoint !== null) { $throwPoints[] = $methodThrowPoint; } } } if ($methodReflection !== null) { $impurePoint = SimpleImpurePoint::createFromVariant($methodReflection, $parametersAcceptor); if ($impurePoint !== null) { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()); } } else { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'methodCall', 'call to unknown method', \false); } if ($parametersAcceptor !== null) { $expr = \PHPStan\Analyser\ArgumentsNormalizer::reorderMethodArguments($parametersAcceptor, $expr) ?? $expr; } $result = $this->processArgs($stmt, $methodReflection, $methodReflection !== null ? $scope->getNakedMethod($calledOnType, $methodReflection->getName()) : null, $parametersAcceptor, $expr, $scope, $nodeCallback, $context); $scope = $result->getScope(); if ($methodReflection !== null) { $hasSideEffects = $methodReflection->hasSideEffects(); if ($hasSideEffects->yes() || $methodReflection->getName() === '__construct') { $nodeCallback(new InvalidateExprNode($expr->var), $scope); $scope = $scope->invalidateExpression($expr->var, \true); } if ($parametersAcceptor !== null && !$methodReflection->isStatic()) { $selfOutType = $methodReflection->getSelfOutType(); if ($selfOutType !== null) { $scope = $scope->assignExpression($expr->var, TemplateTypeHelper::resolveTemplateTypes($selfOutType, $parametersAcceptor->getResolvedTemplateTypeMap(), $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createCovariant()), $scope->getNativeType($expr->var)); } } if ($scope->isInClass() && $scope->getClassReflection()->getName() === $methodReflection->getDeclaringClass()->getName() && TypeUtils::findThisType($calledOnType) !== null) { $calledMethodScope = $this->processCalledMethod($methodReflection); if ($calledMethodScope !== null) { $scope = $scope->mergeInitializedProperties($calledMethodScope); } } } else { $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr); } $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); } elseif ($expr instanceof Expr\NullsafeMethodCall) { $nonNullabilityResult = $this->ensureShallowNonNullability($scope, $scope, $expr->var); $exprResult = $this->processExprNode($stmt, new MethodCall($expr->var, $expr->name, $expr->args, array_merge($expr->getAttributes(), ['virtualNullsafeMethodCall' => \true])), $nonNullabilityResult->getScope(), $nodeCallback, $context); $scope = $this->revertNonNullability($exprResult->getScope(), $nonNullabilityResult->getSpecifiedExpressions()); return new \PHPStan\Analyser\ExpressionResult($scope, $exprResult->hasYield(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints(), static function () use($scope, $expr) : \PHPStan\Analyser\MutatingScope { return $scope->filterByTruthyValue($expr); }, static function () use($scope, $expr) : \PHPStan\Analyser\MutatingScope { return $scope->filterByFalseyValue($expr); }); } elseif ($expr instanceof StaticCall) { $hasYield = \false; $throwPoints = []; $impurePoints = []; if ($expr->class instanceof Expr) { $objectClasses = $scope->getType($expr->class)->getObjectClassNames(); if (count($objectClasses) !== 1) { $objectClasses = $scope->getType(new New_($expr->class))->getObjectClassNames(); } if (count($objectClasses) === 1) { $objectExprResult = $this->processExprNode($stmt, new StaticCall(new Name($objectClasses[0]), $expr->name, []), $scope, static function () : void { }, $context->enterDeep()); $additionalThrowPoints = $objectExprResult->getThrowPoints(); } else { $additionalThrowPoints = [\PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr)]; } $classResult = $this->processExprNode($stmt, $expr->class, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $classResult->hasYield(); $throwPoints = array_merge($throwPoints, $classResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $classResult->getImpurePoints()); foreach ($additionalThrowPoints as $throwPoint) { $throwPoints[] = $throwPoint; } $scope = $classResult->getScope(); } $parametersAcceptor = null; $methodReflection = null; if ($expr->name instanceof Expr) { $result = $this->processExprNode($stmt, $expr->name, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); } elseif ($expr->class instanceof Name) { $classType = $scope->resolveTypeByName($expr->class); $methodName = $expr->name->name; if ($classType->hasMethod($methodName)->yes()) { $methodReflection = $classType->getMethod($methodName, $scope); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); $methodThrowPoint = $this->getStaticMethodThrowPoint($methodReflection, $parametersAcceptor, $expr, $scope); if ($methodThrowPoint !== null) { $throwPoints[] = $methodThrowPoint; } $declaringClass = $methodReflection->getDeclaringClass(); if ($declaringClass->getName() === 'Closure' && strtolower($methodName) === 'bind') { $thisType = null; $nativeThisType = null; if (isset($expr->getArgs()[1])) { $argType = $scope->getType($expr->getArgs()[1]->value); if ($argType->isNull()->yes()) { $thisType = null; } else { $thisType = $argType; } $nativeArgType = $scope->getNativeType($expr->getArgs()[1]->value); if ($nativeArgType->isNull()->yes()) { $nativeThisType = null; } else { $nativeThisType = $nativeArgType; } } $scopeClasses = ['static']; if (isset($expr->getArgs()[2])) { $argValue = $expr->getArgs()[2]->value; $argValueType = $scope->getType($argValue); $directClassNames = $argValueType->getObjectClassNames(); if (count($directClassNames) > 0) { $scopeClasses = $directClassNames; $thisTypes = []; foreach ($directClassNames as $directClassName) { $thisTypes[] = new ObjectType($directClassName); } $thisType = TypeCombinator::union(...$thisTypes); } else { $thisType = $argValueType->getClassStringObjectType(); $scopeClasses = $thisType->getObjectClassNames(); } } $closureBindScope = $scope->enterClosureBind($thisType, $nativeThisType, $scopeClasses); } } else { $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr); } } if ($methodReflection !== null) { $impurePoint = SimpleImpurePoint::createFromVariant($methodReflection, $parametersAcceptor); if ($impurePoint !== null) { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()); } } else { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'methodCall', 'call to unknown method', \false); } if ($parametersAcceptor !== null) { $expr = \PHPStan\Analyser\ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $expr) ?? $expr; } $result = $this->processArgs($stmt, $methodReflection, null, $parametersAcceptor, $expr, $scope, $nodeCallback, $context, $closureBindScope ?? null); $scope = $result->getScope(); $scopeFunction = $scope->getFunction(); if ($methodReflection !== null && !$methodReflection->isStatic() && ($methodReflection->hasSideEffects()->yes() || $methodReflection->getName() === '__construct') && $scopeFunction instanceof MethodReflection && !$scopeFunction->isStatic() && $scope->isInClass() && ($scope->getClassReflection()->getName() === $methodReflection->getDeclaringClass()->getName() || $scope->getClassReflection()->isSubclassOf($methodReflection->getDeclaringClass()->getName()))) { $scope = $scope->invalidateExpression(new Variable('this'), \true); } if ($methodReflection !== null && !$methodReflection->isStatic() && $methodReflection->getName() === '__construct' && $scopeFunction instanceof MethodReflection && !$scopeFunction->isStatic() && $scope->isInClass() && $scope->getClassReflection()->isSubclassOf($methodReflection->getDeclaringClass()->getName())) { $thisType = $scope->getType(new Variable('this')); $methodClassReflection = $methodReflection->getDeclaringClass(); foreach ($methodClassReflection->getNativeReflection()->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED) as $property) { if (!$property->isPromoted() || $property->getDeclaringClass()->getName() !== $methodClassReflection->getName()) { continue; } $scope = $scope->assignInitializedProperty($thisType, $property->getName()); } } $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); } elseif ($expr instanceof PropertyFetch) { $result = $this->processExprNode($stmt, $expr->var, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $scope = $result->getScope(); if ($expr->name instanceof Expr) { $result = $this->processExprNode($stmt, $expr->name, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); } } elseif ($expr instanceof Expr\NullsafePropertyFetch) { $nonNullabilityResult = $this->ensureShallowNonNullability($scope, $scope, $expr->var); $exprResult = $this->processExprNode($stmt, new PropertyFetch($expr->var, $expr->name, array_merge($expr->getAttributes(), ['virtualNullsafePropertyFetch' => \true])), $nonNullabilityResult->getScope(), $nodeCallback, $context); $scope = $this->revertNonNullability($exprResult->getScope(), $nonNullabilityResult->getSpecifiedExpressions()); return new \PHPStan\Analyser\ExpressionResult($scope, $exprResult->hasYield(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints(), static function () use($scope, $expr) : \PHPStan\Analyser\MutatingScope { return $scope->filterByTruthyValue($expr); }, static function () use($scope, $expr) : \PHPStan\Analyser\MutatingScope { return $scope->filterByFalseyValue($expr); }); } elseif ($expr instanceof StaticPropertyFetch) { $hasYield = \false; $throwPoints = []; $impurePoints = [new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'staticPropertyAccess', 'static property access', \true)]; if ($expr->class instanceof Expr) { $result = $this->processExprNode($stmt, $expr->class, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $scope = $result->getScope(); } if ($expr->name instanceof Expr) { $result = $this->processExprNode($stmt, $expr->name, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); } } elseif ($expr instanceof Expr\Closure) { $processClosureResult = $this->processClosureNode($stmt, $expr, $scope, $nodeCallback, $context, null); return new \PHPStan\Analyser\ExpressionResult($processClosureResult->getScope(), \false, [], []); } elseif ($expr instanceof Expr\ArrowFunction) { $result = $this->processArrowFunctionNode($stmt, $expr, $scope, $nodeCallback, null); return new \PHPStan\Analyser\ExpressionResult($result->getScope(), $result->hasYield(), [], []); } elseif ($expr instanceof ErrorSuppress) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $scope = $result->getScope(); } elseif ($expr instanceof Exit_) { $hasYield = \false; $throwPoints = []; $kind = $expr->getAttribute('kind', Exit_::KIND_EXIT); $identifier = $kind === Exit_::KIND_DIE ? 'die' : 'exit'; $impurePoints = [new \PHPStan\Analyser\ImpurePoint($scope, $expr, $identifier, $identifier, \true)]; if ($expr->expr !== null) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); } } elseif ($expr instanceof Node\Scalar\Encapsed) { $hasYield = \false; $throwPoints = []; $impurePoints = []; foreach ($expr->parts as $part) { $result = $this->processExprNode($stmt, $part, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); } } elseif ($expr instanceof ArrayDimFetch) { $hasYield = \false; $throwPoints = []; $impurePoints = []; if ($expr->dim !== null) { $result = $this->processExprNode($stmt, $expr->dim, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $scope = $result->getScope(); } $result = $this->processExprNode($stmt, $expr->var, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); } elseif ($expr instanceof Array_) { $itemNodes = []; $hasYield = \false; $throwPoints = []; $impurePoints = []; foreach ($expr->items as $arrayItem) { $itemNodes[] = new LiteralArrayItem($scope, $arrayItem); if ($arrayItem === null) { continue; } $nodeCallback($arrayItem, $scope); if ($arrayItem->key !== null) { $keyResult = $this->processExprNode($stmt, $arrayItem->key, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $keyResult->hasYield(); $throwPoints = array_merge($throwPoints, $keyResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $keyResult->getImpurePoints()); $scope = $keyResult->getScope(); } $valueResult = $this->processExprNode($stmt, $arrayItem->value, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $valueResult->hasYield(); $throwPoints = array_merge($throwPoints, $valueResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $valueResult->getImpurePoints()); $scope = $valueResult->getScope(); } $nodeCallback(new LiteralArrayNode($expr, $itemNodes), $scope); } elseif ($expr instanceof BooleanAnd || $expr instanceof BinaryOp\LogicalAnd) { $leftResult = $this->processExprNode($stmt, $expr->left, $scope, $nodeCallback, $context->enterDeep()); $rightResult = $this->processExprNode($stmt, $expr->right, $leftResult->getTruthyScope(), $nodeCallback, $context); $rightExprType = $rightResult->getScope()->getType($expr->right); if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { $leftMergedWithRightScope = $leftResult->getFalseyScope(); } else { $leftMergedWithRightScope = $leftResult->getScope()->mergeWith($rightResult->getScope()); } $this->callNodeCallbackWithExpression($nodeCallback, new BooleanAndNode($expr, $leftResult->getTruthyScope()), $scope, $context); return new \PHPStan\Analyser\ExpressionResult($leftMergedWithRightScope, $leftResult->hasYield() || $rightResult->hasYield(), array_merge($leftResult->getThrowPoints(), $rightResult->getThrowPoints()), array_merge($leftResult->getImpurePoints(), $rightResult->getImpurePoints()), static function () use($rightResult, $expr) : \PHPStan\Analyser\MutatingScope { return $rightResult->getScope()->filterByTruthyValue($expr); }, static function () use($leftMergedWithRightScope, $expr) : \PHPStan\Analyser\MutatingScope { return $leftMergedWithRightScope->filterByFalseyValue($expr); }); } elseif ($expr instanceof BooleanOr || $expr instanceof BinaryOp\LogicalOr) { $leftResult = $this->processExprNode($stmt, $expr->left, $scope, $nodeCallback, $context->enterDeep()); $rightResult = $this->processExprNode($stmt, $expr->right, $leftResult->getFalseyScope(), $nodeCallback, $context); $rightExprType = $rightResult->getScope()->getType($expr->right); if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { $leftMergedWithRightScope = $leftResult->getTruthyScope(); } else { $leftMergedWithRightScope = $leftResult->getScope()->mergeWith($rightResult->getScope()); } $this->callNodeCallbackWithExpression($nodeCallback, new BooleanOrNode($expr, $leftResult->getFalseyScope()), $scope, $context); return new \PHPStan\Analyser\ExpressionResult($leftMergedWithRightScope, $leftResult->hasYield() || $rightResult->hasYield(), array_merge($leftResult->getThrowPoints(), $rightResult->getThrowPoints()), array_merge($leftResult->getImpurePoints(), $rightResult->getImpurePoints()), static function () use($leftMergedWithRightScope, $expr) : \PHPStan\Analyser\MutatingScope { return $leftMergedWithRightScope->filterByTruthyValue($expr); }, static function () use($rightResult, $expr) : \PHPStan\Analyser\MutatingScope { return $rightResult->getScope()->filterByFalseyValue($expr); }); } elseif ($expr instanceof Coalesce) { $nonNullabilityResult = $this->ensureNonNullability($scope, $expr->left); $condScope = $this->lookForSetAllowedUndefinedExpressions($nonNullabilityResult->getScope(), $expr->left); $condResult = $this->processExprNode($stmt, $expr->left, $condScope, $nodeCallback, $context->enterDeep()); $scope = $this->revertNonNullability($condResult->getScope(), $nonNullabilityResult->getSpecifiedExpressions()); $scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $expr->left); $rightScope = $scope->filterByFalseyValue($expr); $rightResult = $this->processExprNode($stmt, $expr->right, $rightScope, $nodeCallback, $context->enterDeep()); $rightExprType = $scope->getType($expr->right); if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { $scope = $scope->filterByTruthyValue(new Expr\Isset_([$expr->left])); } else { $scope = $scope->filterByTruthyValue(new Expr\Isset_([$expr->left]))->mergeWith($rightResult->getScope()); } $hasYield = $condResult->hasYield() || $rightResult->hasYield(); $throwPoints = array_merge($condResult->getThrowPoints(), $rightResult->getThrowPoints()); $impurePoints = array_merge($condResult->getImpurePoints(), $rightResult->getImpurePoints()); } elseif ($expr instanceof BinaryOp) { $result = $this->processExprNode($stmt, $expr->left, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $result = $this->processExprNode($stmt, $expr->right, $scope, $nodeCallback, $context->enterDeep()); if (($expr instanceof BinaryOp\Div || $expr instanceof BinaryOp\Mod) && !$scope->getType($expr->right)->toNumber()->isSuperTypeOf(new ConstantIntegerType(0))->no()) { $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createExplicit($scope, new ObjectType(DivisionByZeroError::class), $expr, \false); } $scope = $result->getScope(); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); } elseif ($expr instanceof Expr\Include_) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $throwPoints = $result->getThrowPoints(); $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr); $impurePoints = $result->getImpurePoints(); $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, in_array($expr->type, [Expr\Include_::TYPE_INCLUDE, Expr\Include_::TYPE_INCLUDE_ONCE], \true) ? 'include' : 'require', in_array($expr->type, [Expr\Include_::TYPE_INCLUDE, Expr\Include_::TYPE_INCLUDE_ONCE], \true) ? 'include' : 'require', \true); $hasYield = $result->hasYield(); $scope = $result->getScope()->afterExtractCall(); } elseif ($expr instanceof Expr\Print_) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'print', 'print', \true); $hasYield = $result->hasYield(); $scope = $result->getScope(); } elseif ($expr instanceof Cast\String_) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $hasYield = $result->hasYield(); $exprType = $scope->getType($expr->expr); $toStringMethod = $scope->getMethodReflection($exprType, '__toString'); if ($toStringMethod !== null) { if (!$toStringMethod->hasSideEffects()->no()) { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'methodCall', sprintf('call to method %s::%s()', $toStringMethod->getDeclaringClass()->getDisplayName(), $toStringMethod->getName()), $toStringMethod->isPure()->no()); } } $scope = $result->getScope(); } elseif ($expr instanceof Expr\BitwiseNot || $expr instanceof Cast || $expr instanceof Expr\Clone_ || $expr instanceof Expr\UnaryMinus || $expr instanceof Expr\UnaryPlus) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $hasYield = $result->hasYield(); $scope = $result->getScope(); } elseif ($expr instanceof Expr\Eval_) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $throwPoints = $result->getThrowPoints(); $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr); $impurePoints = $result->getImpurePoints(); $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'eval', 'eval', \true); $hasYield = $result->hasYield(); $scope = $result->getScope(); } elseif ($expr instanceof Expr\YieldFrom) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $throwPoints = $result->getThrowPoints(); $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr); $impurePoints = $result->getImpurePoints(); $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'yieldFrom', 'yield from', \true); $hasYield = \true; $scope = $result->getScope(); } elseif ($expr instanceof BooleanNot) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); } elseif ($expr instanceof Expr\ClassConstFetch) { if ($expr->class instanceof Expr) { $result = $this->processExprNode($stmt, $expr->class, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); } else { $hasYield = \false; $throwPoints = []; $impurePoints = []; $nodeCallback($expr->class, $scope); } if ($expr->name instanceof Expr) { $result = $this->processExprNode($stmt, $expr->name, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); } else { $nodeCallback($expr->name, $scope); } } elseif ($expr instanceof Expr\Empty_) { $nonNullabilityResult = $this->ensureNonNullability($scope, $expr->expr); $scope = $this->lookForSetAllowedUndefinedExpressions($nonNullabilityResult->getScope(), $expr->expr); $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $scope = $this->revertNonNullability($scope, $nonNullabilityResult->getSpecifiedExpressions()); $scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $expr->expr); } elseif ($expr instanceof Expr\Isset_) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $nonNullabilityResults = []; foreach ($expr->vars as $var) { $nonNullabilityResult = $this->ensureNonNullability($scope, $var); $scope = $this->lookForSetAllowedUndefinedExpressions($nonNullabilityResult->getScope(), $var); $result = $this->processExprNode($stmt, $var, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $nonNullabilityResults[] = $nonNullabilityResult; } foreach (array_reverse($expr->vars) as $var) { $scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $var); } foreach (array_reverse($nonNullabilityResults) as $nonNullabilityResult) { $scope = $this->revertNonNullability($scope, $nonNullabilityResult->getSpecifiedExpressions()); } } elseif ($expr instanceof Instanceof_) { $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); if ($expr->class instanceof Expr) { $result = $this->processExprNode($stmt, $expr->class, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); } } elseif ($expr instanceof List_) { // only in assign and foreach, processed elsewhere return new \PHPStan\Analyser\ExpressionResult($scope, \false, [], []); } elseif ($expr instanceof New_) { $parametersAcceptor = null; $constructorReflection = null; $hasYield = \false; $throwPoints = []; $impurePoints = []; $className = null; if ($expr->class instanceof Expr || $expr->class instanceof Name) { if ($expr->class instanceof Expr) { $objectClasses = $scope->getType($expr)->getObjectClassNames(); if (count($objectClasses) === 1) { $objectExprResult = $this->processExprNode($stmt, new New_(new Name($objectClasses[0])), $scope, static function () : void { }, $context->enterDeep()); $className = $objectClasses[0]; $additionalThrowPoints = $objectExprResult->getThrowPoints(); } else { $additionalThrowPoints = [\PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr)]; } $result = $this->processExprNode($stmt, $expr->class, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); foreach ($additionalThrowPoints as $throwPoint) { $throwPoints[] = $throwPoint; } } else { $className = $scope->resolveName($expr->class); } $classReflection = null; if ($className !== null && $this->reflectionProvider->hasClass($className)) { $classReflection = $this->reflectionProvider->getClass($className); if ($classReflection->hasConstructor()) { $constructorReflection = $classReflection->getConstructor(); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $constructorReflection->getVariants(), $constructorReflection->getNamedArgumentsVariants()); $constructorThrowPoint = $this->getConstructorThrowPoint($constructorReflection, $parametersAcceptor, $classReflection, $expr, new Name\FullyQualified($className), $expr->getArgs(), $scope); if ($constructorThrowPoint !== null) { $throwPoints[] = $constructorThrowPoint; } } } else { $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr); } if ($constructorReflection !== null) { if (!$constructorReflection->hasSideEffects()->no()) { $certain = $constructorReflection->isPure()->no(); $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'new', sprintf('instantiation of class %s', $constructorReflection->getDeclaringClass()->getDisplayName()), $certain); } } elseif ($classReflection === null) { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'new', 'instantiation of unknown class', \false); } if ($parametersAcceptor !== null) { $expr = \PHPStan\Analyser\ArgumentsNormalizer::reorderNewArguments($parametersAcceptor, $expr) ?? $expr; } } else { $classReflection = $this->reflectionProvider->getAnonymousClassReflection($expr->class, $scope); // populates $expr->class->name $constructorResult = null; $this->processStmtNode($expr->class, $scope, static function (Node $node, \PHPStan\Analyser\Scope $scope) use($nodeCallback, $classReflection, &$constructorResult) : void { $nodeCallback($node, $scope); if (!$node instanceof MethodReturnStatementsNode) { return; } if ($constructorResult !== null) { return; } $currentClassReflection = $node->getClassReflection(); if ($currentClassReflection->getName() !== $classReflection->getName()) { return; } if (!$currentClassReflection->hasConstructor()) { return; } if ($currentClassReflection->getConstructor()->getName() !== $node->getMethodReflection()->getName()) { return; } $constructorResult = $node; }, \PHPStan\Analyser\StatementContext::createTopLevel()); if ($constructorResult !== null) { $throwPoints = array_merge($throwPoints, $constructorResult->getStatementResult()->getThrowPoints()); $impurePoints = array_merge($impurePoints, $constructorResult->getImpurePoints()); } if ($classReflection->hasConstructor()) { $constructorReflection = $classReflection->getConstructor(); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $expr->getArgs(), $constructorReflection->getVariants(), $constructorReflection->getNamedArgumentsVariants()); } } $result = $this->processArgs($stmt, $constructorReflection, null, $parametersAcceptor, $expr, $scope, $nodeCallback, $context); $scope = $result->getScope(); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); } elseif ($expr instanceof Expr\PreInc || $expr instanceof Expr\PostInc || $expr instanceof Expr\PreDec || $expr instanceof Expr\PostDec) { $result = $this->processExprNode($stmt, $expr->var, $scope, $nodeCallback, $context->enterDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $newExpr = $expr; if ($expr instanceof Expr\PostInc) { $newExpr = new Expr\PreInc($expr->var); } elseif ($expr instanceof Expr\PostDec) { $newExpr = new Expr\PreDec($expr->var); } $scope = $this->processAssignVar($scope, $stmt, $expr->var, $newExpr, static function (Node $node, \PHPStan\Analyser\Scope $scope) use($nodeCallback) : void { if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) { return; } $nodeCallback($node, $scope); }, $context, static function (\PHPStan\Analyser\MutatingScope $scope) : \PHPStan\Analyser\ExpressionResult { return new \PHPStan\Analyser\ExpressionResult($scope, \false, [], []); }, \false)->getScope(); } elseif ($expr instanceof Ternary) { $ternaryCondResult = $this->processExprNode($stmt, $expr->cond, $scope, $nodeCallback, $context->enterDeep()); $throwPoints = $ternaryCondResult->getThrowPoints(); $impurePoints = $ternaryCondResult->getImpurePoints(); $ifTrueScope = $ternaryCondResult->getTruthyScope(); $ifFalseScope = $ternaryCondResult->getFalseyScope(); $ifTrueType = null; if ($expr->if !== null) { $ifResult = $this->processExprNode($stmt, $expr->if, $ifTrueScope, $nodeCallback, $context); $throwPoints = array_merge($throwPoints, $ifResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $ifResult->getImpurePoints()); $ifTrueScope = $ifResult->getScope(); $ifTrueType = $ifTrueScope->getType($expr->if); } $elseResult = $this->processExprNode($stmt, $expr->else, $ifFalseScope, $nodeCallback, $context); $throwPoints = array_merge($throwPoints, $elseResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $elseResult->getImpurePoints()); $ifFalseScope = $elseResult->getScope(); $condType = $scope->getType($expr->cond); if ($condType->isTrue()->yes()) { $finalScope = $ifTrueScope; } elseif ($condType->isFalse()->yes()) { $finalScope = $ifFalseScope; } else { if ($ifTrueType instanceof NeverType && $ifTrueType->isExplicit()) { $finalScope = $ifFalseScope; } else { $ifFalseType = $ifFalseScope->getType($expr->else); if ($ifFalseType instanceof NeverType && $ifFalseType->isExplicit()) { $finalScope = $ifTrueScope; } else { $finalScope = $ifTrueScope->mergeWith($ifFalseScope); } } } return new \PHPStan\Analyser\ExpressionResult($finalScope, $ternaryCondResult->hasYield(), $throwPoints, $impurePoints, static function () use($finalScope, $expr) : \PHPStan\Analyser\MutatingScope { return $finalScope->filterByTruthyValue($expr); }, static function () use($finalScope, $expr) : \PHPStan\Analyser\MutatingScope { return $finalScope->filterByFalseyValue($expr); }); } elseif ($expr instanceof Expr\Yield_) { $throwPoints = [\PHPStan\Analyser\ThrowPoint::createImplicit($scope, $expr)]; $impurePoints = [new \PHPStan\Analyser\ImpurePoint($scope, $expr, 'yield', 'yield', \true)]; if ($expr->key !== null) { $keyResult = $this->processExprNode($stmt, $expr->key, $scope, $nodeCallback, $context->enterDeep()); $scope = $keyResult->getScope(); $throwPoints = $keyResult->getThrowPoints(); $impurePoints = array_merge($impurePoints, $keyResult->getImpurePoints()); } if ($expr->value !== null) { $valueResult = $this->processExprNode($stmt, $expr->value, $scope, $nodeCallback, $context->enterDeep()); $scope = $valueResult->getScope(); $throwPoints = array_merge($throwPoints, $valueResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $valueResult->getImpurePoints()); } $hasYield = \true; } elseif ($expr instanceof Expr\Match_) { $deepContext = $context->enterDeep(); $condType = $scope->getType($expr->cond); $condResult = $this->processExprNode($stmt, $expr->cond, $scope, $nodeCallback, $deepContext); $scope = $condResult->getScope(); $hasYield = $condResult->hasYield(); $throwPoints = $condResult->getThrowPoints(); $impurePoints = $condResult->getImpurePoints(); $matchScope = $scope->enterMatch($expr); $armNodes = []; $hasDefaultCond = \false; $hasAlwaysTrueCond = \false; $arms = $expr->arms; if ($condType->isEnum()->yes()) { // enum match analysis would work even without this if branch // but would be much slower // this avoids using ObjectType::$subtractedType which is slow for huge enums // because of repeated union type normalization $enumCases = $condType->getEnumCases(); if (count($enumCases) > 0) { $indexedEnumCases = []; foreach ($enumCases as $enumCase) { $indexedEnumCases[strtolower($enumCase->getClassName())][$enumCase->getEnumCaseName()] = $enumCase; } $unusedIndexedEnumCases = $indexedEnumCases; foreach ($arms as $i => $arm) { if ($arm->conds === null) { continue; } $condNodes = []; $conditionCases = []; foreach ($arm->conds as $cond) { if (!$cond instanceof Expr\ClassConstFetch) { continue 2; } if (!$cond->class instanceof Name) { continue 2; } if (!$cond->name instanceof Node\Identifier) { continue 2; } $fetchedClassName = $scope->resolveName($cond->class); $loweredFetchedClassName = strtolower($fetchedClassName); if (!array_key_exists($loweredFetchedClassName, $indexedEnumCases)) { continue 2; } if (!array_key_exists($loweredFetchedClassName, $unusedIndexedEnumCases)) { throw new ShouldNotHappenException(); } $caseName = $cond->name->toString(); if (!array_key_exists($caseName, $indexedEnumCases[$loweredFetchedClassName])) { continue 2; } $enumCase = $indexedEnumCases[$loweredFetchedClassName][$caseName]; $conditionCases[] = $enumCase; $armConditionScope = $matchScope; if (!array_key_exists($caseName, $unusedIndexedEnumCases[$loweredFetchedClassName])) { // force "always false" $armConditionScope = $armConditionScope->removeTypeFromExpression($expr->cond, $enumCase); } else { $unusedCasesCount = 0; foreach ($unusedIndexedEnumCases as $cases) { $unusedCasesCount += count($cases); } if ($unusedCasesCount === 1) { $hasAlwaysTrueCond = \true; // force "always true" $armConditionScope = $armConditionScope->addTypeToExpression($expr->cond, $enumCase); } } $this->processExprNode($stmt, $cond, $armConditionScope, $nodeCallback, $deepContext); $condNodes[] = new MatchExpressionArmCondition($cond, $armConditionScope, $cond->getStartLine()); unset($unusedIndexedEnumCases[$loweredFetchedClassName][$caseName]); } $conditionCasesCount = count($conditionCases); if ($conditionCasesCount === 0) { throw new ShouldNotHappenException(); } elseif ($conditionCasesCount === 1) { $conditionCaseType = $conditionCases[0]; } else { $conditionCaseType = new UnionType($conditionCases); } $matchArmBodyScope = $matchScope->addTypeToExpression($expr->cond, $conditionCaseType); $matchArmBody = new MatchExpressionArmBody($matchArmBodyScope, $arm->body); $armNodes[$i] = new MatchExpressionArm($matchArmBody, $condNodes, $arm->getStartLine()); $armResult = $this->processExprNode($stmt, $arm->body, $matchArmBodyScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createTopLevel()); $armScope = $armResult->getScope(); $scope = $scope->mergeWith($armScope); $hasYield = $hasYield || $armResult->hasYield(); $throwPoints = array_merge($throwPoints, $armResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $armResult->getImpurePoints()); unset($arms[$i]); } $remainingCases = []; foreach ($unusedIndexedEnumCases as $cases) { foreach ($cases as $case) { $remainingCases[] = $case; } } $remainingCasesCount = count($remainingCases); if ($remainingCasesCount === 0) { $remainingType = new NeverType(); } elseif ($remainingCasesCount === 1) { $remainingType = $remainingCases[0]; } else { $remainingType = new UnionType($remainingCases); } $matchScope = $matchScope->addTypeToExpression($expr->cond, $remainingType); } } foreach ($arms as $i => $arm) { if ($arm->conds === null) { $hasDefaultCond = \true; $matchArmBody = new MatchExpressionArmBody($matchScope, $arm->body); $armNodes[$i] = new MatchExpressionArm($matchArmBody, [], $arm->getStartLine()); $armResult = $this->processExprNode($stmt, $arm->body, $matchScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createTopLevel()); $matchScope = $armResult->getScope(); $hasYield = $hasYield || $armResult->hasYield(); $throwPoints = array_merge($throwPoints, $armResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $armResult->getImpurePoints()); $scope = $scope->mergeWith($matchScope); continue; } if (count($arm->conds) === 0) { throw new ShouldNotHappenException(); } $filteringExprs = []; $armCondScope = $matchScope; $condNodes = []; foreach ($arm->conds as $armCond) { $condNodes[] = new MatchExpressionArmCondition($armCond, $armCondScope, $armCond->getStartLine()); $armCondResult = $this->processExprNode($stmt, $armCond, $armCondScope, $nodeCallback, $deepContext); $hasYield = $hasYield || $armCondResult->hasYield(); $throwPoints = array_merge($throwPoints, $armCondResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $armCondResult->getImpurePoints()); $armCondExpr = new BinaryOp\Identical($expr->cond, $armCond); $armCondResultScope = $armCondResult->getScope(); $armCondType = $this->treatPhpDocTypesAsCertain ? $armCondResultScope->getType($armCondExpr) : $armCondResultScope->getNativeType($armCondExpr); if ($armCondType->isTrue()->yes()) { $hasAlwaysTrueCond = \true; } $armCondScope = $armCondResult->getScope()->filterByFalseyValue($armCondExpr); $filteringExprs[] = $armCond; } if (count($filteringExprs) === 1) { $filteringExpr = new BinaryOp\Identical($expr->cond, $filteringExprs[0]); } else { $items = []; foreach ($filteringExprs as $filteringExpr) { $items[] = new ArrayItem($filteringExpr); } $filteringExpr = new FuncCall(new Name\FullyQualified('in_array'), [new Arg($expr->cond), new Arg(new Array_($items)), new Arg(new ConstFetch(new Name\FullyQualified('true')))]); } $bodyScope = $this->processExprNode($stmt, $filteringExpr, $matchScope, static function () : void { }, $deepContext)->getTruthyScope(); $matchArmBody = new MatchExpressionArmBody($bodyScope, $arm->body); $armNodes[$i] = new MatchExpressionArm($matchArmBody, $condNodes, $arm->getStartLine()); $armResult = $this->processExprNode($stmt, $arm->body, $bodyScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createTopLevel()); $armScope = $armResult->getScope(); $scope = $scope->mergeWith($armScope); $hasYield = $hasYield || $armResult->hasYield(); $throwPoints = array_merge($throwPoints, $armResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $armResult->getImpurePoints()); $matchScope = $matchScope->filterByFalseyValue($filteringExpr); } $remainingType = $matchScope->getType($expr->cond); if (!$hasDefaultCond && !$hasAlwaysTrueCond && !$remainingType instanceof NeverType) { $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createExplicit($scope, new ObjectType(UnhandledMatchError::class), $expr, \false); } ksort($armNodes, SORT_NUMERIC); $nodeCallback(new MatchExpressionNode($expr->cond, array_values($armNodes), $expr, $matchScope), $scope); } elseif ($expr instanceof AlwaysRememberedExpr) { $result = $this->processExprNode($stmt, $expr->getExpr(), $scope, $nodeCallback, $context); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $scope = $result->getScope(); } elseif ($expr instanceof Expr\Throw_) { $hasYield = \false; $result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $scope->getType($expr->expr), $expr, \false); } elseif ($expr instanceof FunctionCallableNode) { $throwPoints = []; $impurePoints = []; $hasYield = \false; if ($expr->getName() instanceof Expr) { $result = $this->processExprNode($stmt, $expr->getName(), $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); } } elseif ($expr instanceof MethodCallableNode) { $result = $this->processExprNode($stmt, $expr->getVar(), $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scope = $result->getScope(); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); if ($expr->getName() instanceof Expr) { $nameResult = $this->processExprNode($stmt, $expr->getVar(), $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scope = $nameResult->getScope(); $hasYield = $hasYield || $nameResult->hasYield(); $throwPoints = array_merge($throwPoints, $nameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $nameResult->getImpurePoints()); } } elseif ($expr instanceof StaticMethodCallableNode) { $throwPoints = []; $impurePoints = []; $hasYield = \false; if ($expr->getClass() instanceof Expr) { $classResult = $this->processExprNode($stmt, $expr->getClass(), $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scope = $classResult->getScope(); $hasYield = $classResult->hasYield(); $throwPoints = $classResult->getThrowPoints(); $impurePoints = $classResult->getImpurePoints(); } if ($expr->getName() instanceof Expr) { $nameResult = $this->processExprNode($stmt, $expr->getName(), $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scope = $nameResult->getScope(); $hasYield = $hasYield || $nameResult->hasYield(); $throwPoints = array_merge($throwPoints, $nameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $nameResult->getImpurePoints()); } } elseif ($expr instanceof InstantiationCallableNode) { $throwPoints = []; $impurePoints = []; $hasYield = \false; if ($expr->getClass() instanceof Expr) { $classResult = $this->processExprNode($stmt, $expr->getClass(), $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $scope = $classResult->getScope(); $hasYield = $classResult->hasYield(); $throwPoints = $classResult->getThrowPoints(); $impurePoints = $classResult->getImpurePoints(); } } elseif ($expr instanceof Node\Scalar) { $hasYield = \false; $throwPoints = []; $impurePoints = []; } elseif ($expr instanceof ConstFetch) { $hasYield = \false; $throwPoints = []; $impurePoints = []; $nodeCallback($expr->name, $scope); } else { $hasYield = \false; $throwPoints = []; $impurePoints = []; } return new \PHPStan\Analyser\ExpressionResult($scope, $hasYield, $throwPoints, $impurePoints, static function () use($scope, $expr) : \PHPStan\Analyser\MutatingScope { return $scope->filterByTruthyValue($expr); }, static function () use($scope, $expr) : \PHPStan\Analyser\MutatingScope { return $scope->filterByFalseyValue($expr); }); } private function getArrayFunctionAppendingType(FunctionReflection $functionReflection, \PHPStan\Analyser\Scope $scope, FuncCall $expr) : Type { $arrayArg = $expr->getArgs()[0]->value; $arrayType = $scope->getType($arrayArg); $callArgs = array_slice($expr->getArgs(), 1); /** * @param Arg[] $callArgs * @param callable(?Type, Type, bool): void $setOffsetValueType */ $setOffsetValueTypes = static function (\PHPStan\Analyser\Scope $scope, array $callArgs, callable $setOffsetValueType, ?bool &$nonConstantArrayWasUnpacked = null) : void { foreach ($callArgs as $callArg) { $callArgType = $scope->getType($callArg->value); if ($callArg->unpack) { $constantArrays = $callArgType->getConstantArrays(); if (count($constantArrays) === 1) { $iterableValueTypes = $constantArrays[0]->getValueTypes(); } else { $iterableValueTypes = [$callArgType->getIterableValueType()]; $nonConstantArrayWasUnpacked = \true; } $isOptional = !$callArgType->isIterableAtLeastOnce()->yes(); foreach ($iterableValueTypes as $iterableValueType) { if ($iterableValueType instanceof UnionType) { foreach ($iterableValueType->getTypes() as $innerType) { $setOffsetValueType(null, $innerType, $isOptional); } } else { $setOffsetValueType(null, $iterableValueType, $isOptional); } } continue; } $setOffsetValueType(null, $callArgType, \false); } }; $constantArrays = $arrayType->getConstantArrays(); if (count($constantArrays) > 0) { $newArrayTypes = []; $prepend = $functionReflection->getName() === 'array_unshift'; foreach ($constantArrays as $constantArray) { $arrayTypeBuilder = $prepend ? ConstantArrayTypeBuilder::createEmpty() : ConstantArrayTypeBuilder::createFromConstantArray($constantArray); $setOffsetValueTypes($scope, $callArgs, static function (?Type $offsetType, Type $valueType, bool $optional) use(&$arrayTypeBuilder) : void { $arrayTypeBuilder->setOffsetValueType($offsetType, $valueType, $optional); }, $nonConstantArrayWasUnpacked); if ($prepend) { $keyTypes = $constantArray->getKeyTypes(); $valueTypes = $constantArray->getValueTypes(); foreach ($keyTypes as $k => $keyType) { $arrayTypeBuilder->setOffsetValueType(count($keyType->getConstantStrings()) === 1 ? $keyType->getConstantStrings()[0] : null, $valueTypes[$k], $constantArray->isOptionalKey($k)); } } $constantArray = $arrayTypeBuilder->getArray(); if ($constantArray->isConstantArray()->yes() && $nonConstantArrayWasUnpacked) { $array = new ArrayType($constantArray->generalize(GeneralizePrecision::lessSpecific())->getIterableKeyType(), $constantArray->getIterableValueType()); $isList = $constantArray->isList()->yes(); $constantArray = $constantArray->isIterableAtLeastOnce()->yes() ? TypeCombinator::intersect($array, new NonEmptyArrayType()) : $array; $constantArray = $isList ? AccessoryArrayListType::intersectWith($constantArray) : $constantArray; } $newArrayTypes[] = $constantArray; } return TypeCombinator::union(...$newArrayTypes); } $setOffsetValueTypes($scope, $callArgs, static function (?Type $offsetType, Type $valueType, bool $optional) use(&$arrayType) : void { $isIterableAtLeastOnce = $arrayType->isIterableAtLeastOnce()->yes() || !$optional; $arrayType = $arrayType->setOffsetValueType($offsetType, $valueType); if ($isIterableAtLeastOnce) { return; } $arrayType = TypeCombinator::union($arrayType, new ConstantArrayType([], [])); }); return $arrayType; } private function getArraySortPreserveListFunctionType(Type $type) : Type { $isIterableAtLeastOnce = $type->isIterableAtLeastOnce(); if ($isIterableAtLeastOnce->no()) { return $type; } return TypeTraverser::map($type, static function (Type $type, callable $traverse) use($isIterableAtLeastOnce) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if (!$type instanceof ArrayType) { return $type; } $newArrayType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $type->getIterableValueType())); if ($isIterableAtLeastOnce->yes()) { $newArrayType = TypeCombinator::intersect($newArrayType, new NonEmptyArrayType()); } return $newArrayType; }); } private function getArraySortDoNotPreserveListFunctionType(Type $type) : Type { $isIterableAtLeastOnce = $type->isIterableAtLeastOnce(); if ($isIterableAtLeastOnce->no()) { return $type; } return TypeTraverser::map($type, static function (Type $type, callable $traverse) use($isIterableAtLeastOnce) : Type { if ($type instanceof UnionType) { return $traverse($type); } $constantArrays = $type->getConstantArrays(); if (count($constantArrays) > 0) { $types = []; foreach ($constantArrays as $constantArray) { $types[] = new ConstantArrayType($constantArray->getKeyTypes(), $constantArray->getValueTypes(), $constantArray->getNextAutoIndexes(), $constantArray->getOptionalKeys(), $constantArray->isList()->and(TrinaryLogic::createMaybe())); } return TypeCombinator::union(...$types); } $newArrayType = new ArrayType($type->getIterableKeyType(), $type->getIterableValueType()); if ($isIterableAtLeastOnce->yes()) { $newArrayType = TypeCombinator::intersect($newArrayType, new NonEmptyArrayType()); } return $newArrayType; }); } private function getFunctionThrowPoint(FunctionReflection $functionReflection, ?ParametersAcceptor $parametersAcceptor, FuncCall $funcCall, \PHPStan\Analyser\MutatingScope $scope) : ?\PHPStan\Analyser\ThrowPoint { $normalizedFuncCall = $funcCall; if ($parametersAcceptor !== null) { $normalizedFuncCall = \PHPStan\Analyser\ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $funcCall); } if ($normalizedFuncCall !== null) { foreach ($this->dynamicThrowTypeExtensionProvider->getDynamicFunctionThrowTypeExtensions() as $extension) { if (!$extension->isFunctionSupported($functionReflection)) { continue; } $throwType = $extension->getThrowTypeFromFunctionCall($functionReflection, $normalizedFuncCall, $scope); if ($throwType === null) { return null; } return \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwType, $funcCall, \false); } } $throwType = $functionReflection->getThrowType(); if ($throwType === null && $parametersAcceptor !== null) { $returnType = $parametersAcceptor->getReturnType(); if ($returnType instanceof NeverType && $returnType->isExplicit()) { $throwType = new ObjectType(Throwable::class); } } if ($throwType !== null) { if (!$throwType->isVoid()->yes()) { return \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwType, $funcCall, \true); } } elseif ($this->implicitThrows) { $requiredParameters = null; if ($parametersAcceptor !== null) { $requiredParameters = 0; foreach ($parametersAcceptor->getParameters() as $parameter) { if ($parameter->isOptional()) { continue; } $requiredParameters++; } } if (!$functionReflection->isBuiltin() || $requiredParameters === null || $requiredParameters > 0 || count($funcCall->getArgs()) > 0) { $functionReturnedType = $scope->getType($funcCall); if (!(new ObjectType(Throwable::class))->isSuperTypeOf($functionReturnedType)->yes()) { return \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $funcCall); } } } return null; } private function getMethodThrowPoint(MethodReflection $methodReflection, ParametersAcceptor $parametersAcceptor, MethodCall $methodCall, \PHPStan\Analyser\MutatingScope $scope) : ?\PHPStan\Analyser\ThrowPoint { $normalizedMethodCall = \PHPStan\Analyser\ArgumentsNormalizer::reorderMethodArguments($parametersAcceptor, $methodCall); if ($normalizedMethodCall !== null) { foreach ($this->dynamicThrowTypeExtensionProvider->getDynamicMethodThrowTypeExtensions() as $extension) { if (!$extension->isMethodSupported($methodReflection)) { continue; } $throwType = $extension->getThrowTypeFromMethodCall($methodReflection, $normalizedMethodCall, $scope); if ($throwType === null) { return null; } return \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwType, $methodCall, \false); } } $throwType = $methodReflection->getThrowType(); if ($throwType === null) { $returnType = $parametersAcceptor->getReturnType(); if ($returnType instanceof NeverType && $returnType->isExplicit()) { $throwType = new ObjectType(Throwable::class); } } if ($throwType !== null) { if (!$throwType->isVoid()->yes()) { return \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwType, $methodCall, \true); } } elseif ($this->implicitThrows) { $methodReturnedType = $scope->getType($methodCall); if (!(new ObjectType(Throwable::class))->isSuperTypeOf($methodReturnedType)->yes()) { return \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $methodCall); } } return null; } /** * @param Node\Arg[] $args */ private function getConstructorThrowPoint(MethodReflection $constructorReflection, ParametersAcceptor $parametersAcceptor, ClassReflection $classReflection, New_ $new, Name $className, array $args, \PHPStan\Analyser\MutatingScope $scope) : ?\PHPStan\Analyser\ThrowPoint { $methodCall = new StaticCall($className, $constructorReflection->getName(), $args); $normalizedMethodCall = \PHPStan\Analyser\ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $methodCall); if ($normalizedMethodCall !== null) { foreach ($this->dynamicThrowTypeExtensionProvider->getDynamicStaticMethodThrowTypeExtensions() as $extension) { if (!$extension->isStaticMethodSupported($constructorReflection)) { continue; } $throwType = $extension->getThrowTypeFromStaticMethodCall($constructorReflection, $normalizedMethodCall, $scope); if ($throwType === null) { return null; } return \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwType, $new, \false); } } if ($constructorReflection->getThrowType() !== null) { $throwType = $constructorReflection->getThrowType(); if (!$throwType->isVoid()->yes()) { return \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwType, $new, \true); } } elseif ($this->implicitThrows) { if ($classReflection->getName() !== Throwable::class && !$classReflection->isSubclassOf(Throwable::class)) { return \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $methodCall); } } return null; } private function getStaticMethodThrowPoint(MethodReflection $methodReflection, ParametersAcceptor $parametersAcceptor, StaticCall $methodCall, \PHPStan\Analyser\MutatingScope $scope) : ?\PHPStan\Analyser\ThrowPoint { $normalizedMethodCall = \PHPStan\Analyser\ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $methodCall); if ($normalizedMethodCall !== null) { foreach ($this->dynamicThrowTypeExtensionProvider->getDynamicStaticMethodThrowTypeExtensions() as $extension) { if (!$extension->isStaticMethodSupported($methodReflection)) { continue; } $throwType = $extension->getThrowTypeFromStaticMethodCall($methodReflection, $normalizedMethodCall, $scope); if ($throwType === null) { return null; } return \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwType, $methodCall, \false); } } if ($methodReflection->getThrowType() !== null) { $throwType = $methodReflection->getThrowType(); if (!$throwType->isVoid()->yes()) { return \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwType, $methodCall, \true); } } elseif ($this->implicitThrows) { $methodReturnedType = $scope->getType($methodCall); if (!(new ObjectType(Throwable::class))->isSuperTypeOf($methodReturnedType)->yes()) { return \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $methodCall); } } return null; } /** * @return string[] */ private function getAssignedVariables(Expr $expr) : array { if ($expr instanceof Expr\Variable) { if (is_string($expr->name)) { return [$expr->name]; } return []; } if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) { $names = []; foreach ($expr->items as $item) { if ($item === null) { continue; } $names = array_merge($names, $this->getAssignedVariables($item->value)); } return $names; } if ($expr instanceof ArrayDimFetch) { return $this->getAssignedVariables($expr->var); } return []; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function callNodeCallbackWithExpression(callable $nodeCallback, Expr $expr, \PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\ExpressionContext $context) : void { if ($context->isDeep()) { $scope = $scope->exitFirstLevelStatements(); } $nodeCallback($expr, $scope); } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processClosureNode(Node\Stmt $stmt, Expr\Closure $expr, \PHPStan\Analyser\MutatingScope $scope, callable $nodeCallback, \PHPStan\Analyser\ExpressionContext $context, ?Type $passedToType) : \PHPStan\Analyser\ProcessClosureResult { foreach ($expr->params as $param) { $this->processParamNode($stmt, $param, $scope, $nodeCallback); } $byRefUses = []; $closureCallArgs = $expr->getAttribute(ClosureArgVisitor::ATTRIBUTE_NAME); $callableParameters = $this->createCallableParameters($scope, $expr, $closureCallArgs, $passedToType); $useScope = $scope; foreach ($expr->uses as $use) { if ($use->byRef) { $byRefUses[] = $use; $useScope = $useScope->enterExpressionAssign($use->var); $inAssignRightSideVariableName = $context->getInAssignRightSideVariableName(); $inAssignRightSideType = $context->getInAssignRightSideType(); $inAssignRightSideNativeType = $context->getInAssignRightSideNativeType(); if ($inAssignRightSideVariableName === $use->var->name && $inAssignRightSideType !== null && $inAssignRightSideNativeType !== null) { if ($inAssignRightSideType instanceof ClosureType) { $variableType = $inAssignRightSideType; } else { $alreadyHasVariableType = $scope->hasVariableType($inAssignRightSideVariableName); if ($alreadyHasVariableType->no()) { $variableType = TypeCombinator::union(new NullType(), $inAssignRightSideType); } else { $variableType = TypeCombinator::union($scope->getVariableType($inAssignRightSideVariableName), $inAssignRightSideType); } } if ($inAssignRightSideNativeType instanceof ClosureType) { $variableNativeType = $inAssignRightSideNativeType; } else { $alreadyHasVariableType = $scope->hasVariableType($inAssignRightSideVariableName); if ($alreadyHasVariableType->no()) { $variableNativeType = TypeCombinator::union(new NullType(), $inAssignRightSideNativeType); } else { $variableNativeType = TypeCombinator::union($scope->getVariableType($inAssignRightSideVariableName), $inAssignRightSideNativeType); } } $scope = $scope->assignVariable($inAssignRightSideVariableName, $variableType, $variableNativeType); } } $this->processExprNode($stmt, $use->var, $useScope, $nodeCallback, $context); if (!$use->byRef) { continue; } $useScope = $useScope->exitExpressionAssign($use->var); } if ($expr->returnType !== null) { $nodeCallback($expr->returnType, $scope); } $closureScope = $scope->enterAnonymousFunction($expr, $callableParameters); $closureScope = $closureScope->processClosureScope($scope, null, $byRefUses); $closureType = $closureScope->getAnonymousFunctionReflection(); if (!$closureType instanceof ClosureType) { throw new ShouldNotHappenException(); } $nodeCallback(new InClosureNode($closureType, $expr), $closureScope); $executionEnds = []; $gatheredReturnStatements = []; $gatheredYieldStatements = []; $closureImpurePoints = []; $invalidateExpressions = []; $closureStmtsCallback = static function (Node $node, \PHPStan\Analyser\Scope $scope) use($nodeCallback, &$executionEnds, &$gatheredReturnStatements, &$gatheredYieldStatements, &$closureScope, &$closureImpurePoints, &$invalidateExpressions) : void { $nodeCallback($node, $scope); if ($scope->getAnonymousFunctionReflection() !== $closureScope->getAnonymousFunctionReflection()) { return; } if ($node instanceof PropertyAssignNode) { $closureImpurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $node, 'propertyAssign', 'property assignment', \true); return; } if ($node instanceof ExecutionEndNode) { $executionEnds[] = $node; return; } if ($node instanceof InvalidateExprNode) { $invalidateExpressions[] = $node; return; } if ($node instanceof Expr\Yield_ || $node instanceof Expr\YieldFrom) { $gatheredYieldStatements[] = $node; } if (!$node instanceof Return_) { return; } $gatheredReturnStatements[] = new ReturnStatement($scope, $node); }; if (count($byRefUses) === 0) { $statementResult = $this->processStmtNodes($expr, $expr->stmts, $closureScope, $closureStmtsCallback, \PHPStan\Analyser\StatementContext::createTopLevel()); $nodeCallback(new ClosureReturnStatementsNode($expr, $gatheredReturnStatements, $gatheredYieldStatements, $statementResult, $executionEnds, array_merge($statementResult->getImpurePoints(), $closureImpurePoints)), $closureScope); return new \PHPStan\Analyser\ProcessClosureResult($scope, $statementResult->getThrowPoints(), $statementResult->getImpurePoints(), $invalidateExpressions); } $count = 0; $closureResultScope = null; do { $prevScope = $closureScope; $intermediaryClosureScopeResult = $this->processStmtNodes($expr, $expr->stmts, $closureScope, static function () : void { }, \PHPStan\Analyser\StatementContext::createTopLevel()); $intermediaryClosureScope = $intermediaryClosureScopeResult->getScope(); foreach ($intermediaryClosureScopeResult->getExitPoints() as $exitPoint) { $intermediaryClosureScope = $intermediaryClosureScope->mergeWith($exitPoint->getScope()); } if ($expr->getAttribute(ImmediatelyInvokedClosureVisitor::ATTRIBUTE_NAME) === \true) { $closureResultScope = $intermediaryClosureScope; break; } $closureScope = $scope->enterAnonymousFunction($expr, $callableParameters); $closureScope = $closureScope->processClosureScope($intermediaryClosureScope, $prevScope, $byRefUses); if ($closureScope->equals($prevScope)) { break; } if ($count >= self::GENERALIZE_AFTER_ITERATION) { $closureScope = $prevScope->generalizeWith($closureScope); } $count++; } while ($count < self::LOOP_SCOPE_ITERATIONS); if ($closureResultScope === null) { $closureResultScope = $closureScope; } $statementResult = $this->processStmtNodes($expr, $expr->stmts, $closureScope, $closureStmtsCallback, \PHPStan\Analyser\StatementContext::createTopLevel()); $nodeCallback(new ClosureReturnStatementsNode($expr, $gatheredReturnStatements, $gatheredYieldStatements, $statementResult, $executionEnds, array_merge($statementResult->getImpurePoints(), $closureImpurePoints)), $closureScope); return new \PHPStan\Analyser\ProcessClosureResult($scope->processClosureScope($closureResultScope, null, $byRefUses), $statementResult->getThrowPoints(), $statementResult->getImpurePoints(), $invalidateExpressions); } /** * @param InvalidateExprNode[] $invalidatedExpressions * @param string[] $uses */ private function processImmediatelyCalledCallable(\PHPStan\Analyser\MutatingScope $scope, array $invalidatedExpressions, array $uses) : \PHPStan\Analyser\MutatingScope { if ($scope->isInClass()) { $uses[] = 'this'; } $finder = new NodeFinder(); foreach ($invalidatedExpressions as $invalidateExpression) { $found = \false; foreach ($uses as $use) { $result = $finder->findFirst([$invalidateExpression->getExpr()], static function ($node) use($use) { return $node instanceof Variable && $node->name === $use; }); if ($result === null) { continue; } $found = \true; break; } if (!$found) { continue; } $scope = $scope->invalidateExpression($invalidateExpression->getExpr(), \true); } return $scope; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processArrowFunctionNode(Node\Stmt $stmt, Expr\ArrowFunction $expr, \PHPStan\Analyser\MutatingScope $scope, callable $nodeCallback, ?Type $passedToType) : \PHPStan\Analyser\ExpressionResult { foreach ($expr->params as $param) { $this->processParamNode($stmt, $param, $scope, $nodeCallback); } if ($expr->returnType !== null) { $nodeCallback($expr->returnType, $scope); } $arrowFunctionCallArgs = $expr->getAttribute(ArrowFunctionArgVisitor::ATTRIBUTE_NAME); $arrowFunctionScope = $scope->enterArrowFunction($expr, $this->createCallableParameters($scope, $expr, $arrowFunctionCallArgs, $passedToType)); $arrowFunctionType = $arrowFunctionScope->getAnonymousFunctionReflection(); if (!$arrowFunctionType instanceof ClosureType) { throw new ShouldNotHappenException(); } $nodeCallback(new InArrowFunctionNode($arrowFunctionType, $expr), $arrowFunctionScope); $exprResult = $this->processExprNode($stmt, $expr->expr, $arrowFunctionScope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createTopLevel()); return new \PHPStan\Analyser\ExpressionResult($scope, \false, $exprResult->getThrowPoints(), $exprResult->getImpurePoints()); } /** * @param Node\Arg[] $args * @return ParameterReflection[]|null */ public function createCallableParameters(\PHPStan\Analyser\Scope $scope, Expr $closureExpr, ?array $args, ?Type $passedToType) : ?array { $callableParameters = null; if ($args !== null) { $closureType = $scope->getType($closureExpr); if ($closureType->isCallable()->no()) { return null; } $acceptors = $closureType->getCallableParametersAcceptors($scope); if (count($acceptors) === 1) { $callableParameters = $acceptors[0]->getParameters(); foreach ($callableParameters as $index => $callableParameter) { if (!isset($args[$index])) { continue; } $type = $scope->getType($args[$index]->value); $callableParameters[$index] = new NativeParameterReflection($callableParameter->getName(), $callableParameter->isOptional(), $type, $callableParameter->passedByReference(), $callableParameter->isVariadic(), $callableParameter->getDefaultValue()); } } } elseif ($passedToType !== null && !$passedToType->isCallable()->no()) { if ($passedToType instanceof UnionType) { $passedToType = TypeCombinator::union(...array_filter($passedToType->getTypes(), static function (Type $type) { return $type->isCallable()->yes(); })); if ($passedToType->isCallable()->no()) { return null; } } $acceptors = $passedToType->getCallableParametersAcceptors($scope); if (count($acceptors) > 0) { foreach ($acceptors as $acceptor) { if ($callableParameters === null) { $callableParameters = array_map(static function (ParameterReflection $callableParameter) { return new NativeParameterReflection($callableParameter->getName(), $callableParameter->isOptional(), $callableParameter->getType(), $callableParameter->passedByReference(), $callableParameter->isVariadic(), $callableParameter->getDefaultValue()); }, $acceptor->getParameters()); continue; } $newParameters = []; foreach ($acceptor->getParameters() as $i => $callableParameter) { if (!array_key_exists($i, $callableParameters)) { $newParameters[] = $callableParameter; continue; } $newParameters[] = $callableParameters[$i]->union(new NativeParameterReflection($callableParameter->getName(), $callableParameter->isOptional(), $callableParameter->getType(), $callableParameter->passedByReference(), $callableParameter->isVariadic(), $callableParameter->getDefaultValue())); } $callableParameters = $newParameters; } } } return $callableParameters; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processParamNode(Node\Stmt $stmt, Node\Param $param, \PHPStan\Analyser\MutatingScope $scope, callable $nodeCallback) : void { $this->processAttributeGroups($stmt, $param->attrGroups, $scope, $nodeCallback); $nodeCallback($param, $scope); if ($param->type !== null) { $nodeCallback($param->type, $scope); } if ($param->default === null) { return; } $this->processExprNode($stmt, $param->default, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); } /** * @param AttributeGroup[] $attrGroups * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processAttributeGroups(Node\Stmt $stmt, array $attrGroups, \PHPStan\Analyser\MutatingScope $scope, callable $nodeCallback) : void { foreach ($attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { foreach ($attr->args as $arg) { $this->processExprNode($stmt, $arg->value, $scope, $nodeCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $nodeCallback($arg, $scope); } $nodeCallback($attr, $scope); } $nodeCallback($attrGroup, $scope); } } /** * @param MethodReflection|FunctionReflection|null $calleeReflection * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processArgs(Node\Stmt $stmt, $calleeReflection, ?ExtendedMethodReflection $nakedMethodReflection, ?ParametersAcceptor $parametersAcceptor, CallLike $callLike, \PHPStan\Analyser\MutatingScope $scope, callable $nodeCallback, \PHPStan\Analyser\ExpressionContext $context, ?\PHPStan\Analyser\MutatingScope $closureBindScope = null) : \PHPStan\Analyser\ExpressionResult { $args = $callLike->getArgs(); if ($parametersAcceptor !== null) { $parameters = $parametersAcceptor->getParameters(); } $hasYield = \false; $throwPoints = []; $impurePoints = []; foreach ($args as $i => $arg) { $assignByReference = \false; $parameter = null; $parameterType = null; $parameterNativeType = null; if (isset($parameters) && $parametersAcceptor !== null) { if (isset($parameters[$i])) { $assignByReference = $parameters[$i]->passedByReference()->createsNewVariable(); $parameterType = $parameters[$i]->getType(); if ($parameters[$i] instanceof ParameterReflectionWithPhpDocs) { $parameterNativeType = $parameters[$i]->getNativeType(); } $parameter = $parameters[$i]; } elseif (count($parameters) > 0 && $parametersAcceptor->isVariadic()) { $lastParameter = $parameters[count($parameters) - 1]; $assignByReference = $lastParameter->passedByReference()->createsNewVariable(); $parameterType = $lastParameter->getType(); if ($lastParameter instanceof ParameterReflectionWithPhpDocs) { $parameterNativeType = $lastParameter->getNativeType(); } $parameter = $lastParameter; } } $lookForUnset = \false; if ($assignByReference) { $isBuiltin = \false; if ($calleeReflection instanceof FunctionReflection && $calleeReflection->isBuiltin()) { $isBuiltin = \true; } elseif ($calleeReflection instanceof ExtendedMethodReflection && $calleeReflection->getDeclaringClass()->isBuiltin()) { $isBuiltin = \true; } if ($isBuiltin || ($parameterNativeType === null || !$parameterNativeType->isNull()->no())) { $scope = $this->lookForSetAllowedUndefinedExpressions($scope, $arg->value); $lookForUnset = \true; } } if ($calleeReflection !== null) { $scope = $scope->pushInFunctionCall($calleeReflection, $parameter); } $originalArg = $arg->getAttribute(\PHPStan\Analyser\ArgumentsNormalizer::ORIGINAL_ARG_ATTRIBUTE) ?? $arg; $nodeCallback($originalArg, $scope); $originalScope = $scope; $scopeToPass = $scope; if ($i === 0 && $closureBindScope !== null) { $scopeToPass = $closureBindScope; } if ($parameter instanceof ParameterReflectionWithPhpDocs) { $parameterCallImmediately = $parameter->isImmediatelyInvokedCallable(); if ($parameterCallImmediately->maybe()) { $callCallbackImmediately = $calleeReflection instanceof FunctionReflection; } else { $callCallbackImmediately = $parameterCallImmediately->yes(); } } else { $callCallbackImmediately = $calleeReflection instanceof FunctionReflection; } if ($arg->value instanceof Expr\Closure) { $restoreThisScope = null; if ($closureBindScope === null && $parameter instanceof ParameterReflectionWithPhpDocs && $parameter->getClosureThisType() !== null && !$arg->value->static) { $restoreThisScope = $scopeToPass; $scopeToPass = $scopeToPass->assignVariable('this', $parameter->getClosureThisType(), new ObjectWithoutClassType()); } if ($parameter !== null) { $overwritingParameterType = $this->getParameterTypeFromParameterClosureTypeExtension($callLike, $calleeReflection, $parameter, $scopeToPass); if ($overwritingParameterType !== null) { $parameterType = $overwritingParameterType; } } $this->callNodeCallbackWithExpression($nodeCallback, $arg->value, $scopeToPass, $context); $closureResult = $this->processClosureNode($stmt, $arg->value, $scopeToPass, $nodeCallback, $context, $parameterType ?? null); if ($callCallbackImmediately) { $throwPoints = array_merge($throwPoints, array_map(static function (\PHPStan\Analyser\ThrowPoint $throwPoint) use($scope, $arg) { return $throwPoint->isExplicit() ? \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwPoint->getType(), $arg->value, $throwPoint->canContainAnyThrowable()) : \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $arg->value); }, $closureResult->getThrowPoints())); $impurePoints = array_merge($impurePoints, $closureResult->getImpurePoints()); } $uses = []; foreach ($arg->value->uses as $use) { if (!is_string($use->var->name)) { continue; } $uses[] = $use->var->name; } $scope = $closureResult->getScope(); $invalidateExpressions = $closureResult->getInvalidateExpressions(); if ($restoreThisScope !== null) { $nodeFinder = new NodeFinder(); $cb = static function ($expr) { return $expr instanceof Variable && $expr->name === 'this'; }; foreach ($invalidateExpressions as $j => $invalidateExprNode) { $foundThis = $nodeFinder->findFirst([$invalidateExprNode->getExpr()], $cb); if ($foundThis === null) { continue; } unset($invalidateExpressions[$j]); } $invalidateExpressions = array_values($invalidateExpressions); $scope = $scope->restoreThis($restoreThisScope); } $scope = $this->processImmediatelyCalledCallable($scope, $invalidateExpressions, $uses); } elseif ($arg->value instanceof Expr\ArrowFunction) { if ($closureBindScope === null && $parameter instanceof ParameterReflectionWithPhpDocs && $parameter->getClosureThisType() !== null && !$arg->value->static) { $scopeToPass = $scopeToPass->assignVariable('this', $parameter->getClosureThisType(), new ObjectWithoutClassType()); } if ($parameter !== null) { $overwritingParameterType = $this->getParameterTypeFromParameterClosureTypeExtension($callLike, $calleeReflection, $parameter, $scopeToPass); if ($overwritingParameterType !== null) { $parameterType = $overwritingParameterType; } } $this->callNodeCallbackWithExpression($nodeCallback, $arg->value, $scopeToPass, $context); $arrowFunctionResult = $this->processArrowFunctionNode($stmt, $arg->value, $scopeToPass, $nodeCallback, $parameterType ?? null); if ($callCallbackImmediately) { $throwPoints = array_merge($throwPoints, array_map(static function (\PHPStan\Analyser\ThrowPoint $throwPoint) use($scope, $arg) { return $throwPoint->isExplicit() ? \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwPoint->getType(), $arg->value, $throwPoint->canContainAnyThrowable()) : \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $arg->value); }, $arrowFunctionResult->getThrowPoints())); $impurePoints = array_merge($impurePoints, $arrowFunctionResult->getImpurePoints()); } } else { $exprType = $scope->getType($arg->value); $exprResult = $this->processExprNode($stmt, $arg->value, $scopeToPass, $nodeCallback, $context->enterDeep()); $throwPoints = array_merge($throwPoints, $exprResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $exprResult->getImpurePoints()); $scope = $exprResult->getScope(); $hasYield = $hasYield || $exprResult->hasYield(); if ($exprType->isCallable()->yes()) { $acceptors = $exprType->getCallableParametersAcceptors($scope); if (count($acceptors) === 1) { $scope = $this->processImmediatelyCalledCallable($scope, $acceptors[0]->getInvalidateExpressions(), $acceptors[0]->getUsedVariables()); if ($callCallbackImmediately) { $callableThrowPoints = array_map(static function (SimpleThrowPoint $throwPoint) use($scope, $arg) { return $throwPoint->isExplicit() ? \PHPStan\Analyser\ThrowPoint::createExplicit($scope, $throwPoint->getType(), $arg->value, $throwPoint->canContainAnyThrowable()) : \PHPStan\Analyser\ThrowPoint::createImplicit($scope, $arg->value); }, $acceptors[0]->getThrowPoints()); if (!$this->implicitThrows) { $callableThrowPoints = array_values(array_filter($callableThrowPoints, static function (\PHPStan\Analyser\ThrowPoint $throwPoint) { return $throwPoint->isExplicit(); })); } $throwPoints = array_merge($throwPoints, $callableThrowPoints); $impurePoints = array_merge($impurePoints, array_map(static function (SimpleImpurePoint $impurePoint) use($scope, $arg) { return new \PHPStan\Analyser\ImpurePoint($scope, $arg->value, $impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()); }, $acceptors[0]->getImpurePoints())); } } } } if ($assignByReference && $lookForUnset) { $scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $arg->value); } if ($calleeReflection !== null) { $scope = $scope->popInFunctionCall(); } if ($i !== 0 || $closureBindScope === null) { continue; } $scope = $scope->restoreOriginalScopeAfterClosureBind($originalScope); } foreach ($args as $i => $arg) { if (!isset($parameters) || $parametersAcceptor === null) { continue; } $byRefType = new MixedType(); $assignByReference = \false; $currentParameter = null; if (isset($parameters[$i])) { $currentParameter = $parameters[$i]; } elseif (count($parameters) > 0 && $parametersAcceptor->isVariadic()) { $currentParameter = $parameters[count($parameters) - 1]; } if ($currentParameter !== null) { $assignByReference = $currentParameter->passedByReference()->createsNewVariable(); if ($assignByReference) { if ($currentParameter instanceof ParameterReflectionWithPhpDocs && $currentParameter->getOutType() !== null) { $byRefType = $currentParameter->getOutType(); } elseif ($calleeReflection instanceof MethodReflection && !$calleeReflection->getDeclaringClass()->isBuiltin() && $this->paramOutType) { $byRefType = $currentParameter->getType(); } elseif ($calleeReflection instanceof FunctionReflection && !$calleeReflection->isBuiltin() && $this->paramOutType) { $byRefType = $currentParameter->getType(); } } } if ($assignByReference) { if ($currentParameter === null) { throw new ShouldNotHappenException(); } $argValue = $arg->value; if (!$argValue instanceof Variable || $argValue->name !== 'this') { $paramOutType = $this->getParameterOutExtensionsType($callLike, $calleeReflection, $currentParameter, $scope); if ($paramOutType !== null) { $byRefType = $paramOutType; } $result = $this->processAssignVar($scope, $stmt, $argValue, new TypeExpr($byRefType), static function (Node $node, \PHPStan\Analyser\Scope $scope) use($nodeCallback) : void { if (!$node instanceof PropertyAssignNode && !$node instanceof VariableAssignNode) { return; } $nodeCallback($node, $scope); }, $context, static function (\PHPStan\Analyser\MutatingScope $scope) : \PHPStan\Analyser\ExpressionResult { return new \PHPStan\Analyser\ExpressionResult($scope, \false, [], []); }, \true); $scope = $result->getScope(); } } elseif ($calleeReflection !== null && $calleeReflection->hasSideEffects()->yes()) { $argType = $scope->getType($arg->value); if (!$argType->isObject()->no()) { $nakedReturnType = null; if ($nakedMethodReflection !== null) { $nakedParametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $args, $nakedMethodReflection->getVariants(), $nakedMethodReflection->getNamedArgumentsVariants()); $nakedReturnType = $nakedParametersAcceptor->getReturnType(); } if ($nakedReturnType === null || !(new ThisType($nakedMethodReflection->getDeclaringClass()))->isSuperTypeOf($nakedReturnType)->yes() || $nakedMethodReflection->isPure()->no()) { $nodeCallback(new InvalidateExprNode($arg->value), $scope); $scope = $scope->invalidateExpression($arg->value, \true); } } elseif (!(new ResourceType())->isSuperTypeOf($argType)->no()) { $nodeCallback(new InvalidateExprNode($arg->value), $scope); $scope = $scope->invalidateExpression($arg->value, \true); } } } return new \PHPStan\Analyser\ExpressionResult($scope, $hasYield, $throwPoints, $impurePoints); } /** * @param MethodReflection|FunctionReflection|null $calleeReflection */ private function getParameterTypeFromParameterClosureTypeExtension(CallLike $callLike, $calleeReflection, ParameterReflection $parameter, \PHPStan\Analyser\MutatingScope $scope) : ?Type { if ($callLike instanceof FuncCall && $calleeReflection instanceof FunctionReflection) { foreach ($this->parameterClosureTypeExtensionProvider->getFunctionParameterClosureTypeExtensions() as $functionParameterClosureTypeExtension) { if ($functionParameterClosureTypeExtension->isFunctionSupported($calleeReflection, $parameter)) { return $functionParameterClosureTypeExtension->getTypeFromFunctionCall($calleeReflection, $callLike, $parameter, $scope); } } } elseif ($calleeReflection instanceof MethodReflection) { if ($callLike instanceof StaticCall) { foreach ($this->parameterClosureTypeExtensionProvider->getStaticMethodParameterClosureTypeExtensions() as $staticMethodParameterClosureTypeExtension) { if ($staticMethodParameterClosureTypeExtension->isStaticMethodSupported($calleeReflection, $parameter)) { return $staticMethodParameterClosureTypeExtension->getTypeFromStaticMethodCall($calleeReflection, $callLike, $parameter, $scope); } } } elseif ($callLike instanceof MethodCall) { foreach ($this->parameterClosureTypeExtensionProvider->getMethodParameterClosureTypeExtensions() as $methodParameterClosureTypeExtension) { if ($methodParameterClosureTypeExtension->isMethodSupported($calleeReflection, $parameter)) { return $methodParameterClosureTypeExtension->getTypeFromMethodCall($calleeReflection, $callLike, $parameter, $scope); } } } } return null; } /** * @param MethodReflection|FunctionReflection|null $calleeReflection */ private function getParameterOutExtensionsType(CallLike $callLike, $calleeReflection, ParameterReflection $currentParameter, \PHPStan\Analyser\MutatingScope $scope) : ?Type { $paramOutTypes = []; if ($callLike instanceof FuncCall && $calleeReflection instanceof FunctionReflection) { foreach ($this->parameterOutTypeExtensionProvider->getFunctionParameterOutTypeExtensions() as $functionParameterOutTypeExtension) { if (!$functionParameterOutTypeExtension->isFunctionSupported($calleeReflection, $currentParameter)) { continue; } $resolvedType = $functionParameterOutTypeExtension->getParameterOutTypeFromFunctionCall($calleeReflection, $callLike, $currentParameter, $scope); if ($resolvedType === null) { continue; } $paramOutTypes[] = $resolvedType; } } elseif ($callLike instanceof MethodCall && $calleeReflection instanceof MethodReflection) { foreach ($this->parameterOutTypeExtensionProvider->getMethodParameterOutTypeExtensions() as $methodParameterOutTypeExtension) { if (!$methodParameterOutTypeExtension->isMethodSupported($calleeReflection, $currentParameter)) { continue; } $resolvedType = $methodParameterOutTypeExtension->getParameterOutTypeFromMethodCall($calleeReflection, $callLike, $currentParameter, $scope); if ($resolvedType === null) { continue; } $paramOutTypes[] = $resolvedType; } } elseif ($callLike instanceof StaticCall && $calleeReflection instanceof MethodReflection) { foreach ($this->parameterOutTypeExtensionProvider->getStaticMethodParameterOutTypeExtensions() as $staticMethodParameterOutTypeExtension) { if (!$staticMethodParameterOutTypeExtension->isStaticMethodSupported($calleeReflection, $currentParameter)) { continue; } $resolvedType = $staticMethodParameterOutTypeExtension->getParameterOutTypeFromStaticMethodCall($calleeReflection, $callLike, $currentParameter, $scope); if ($resolvedType === null) { continue; } $paramOutTypes[] = $resolvedType; } } if (count($paramOutTypes) === 1) { return $paramOutTypes[0]; } if (count($paramOutTypes) > 1) { return TypeCombinator::union(...$paramOutTypes); } return null; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback * @param Closure(MutatingScope $scope): ExpressionResult $processExprCallback */ private function processAssignVar(\PHPStan\Analyser\MutatingScope $scope, Node\Stmt $stmt, Expr $var, Expr $assignedExpr, callable $nodeCallback, \PHPStan\Analyser\ExpressionContext $context, Closure $processExprCallback, bool $enterExpressionAssign) : \PHPStan\Analyser\ExpressionResult { $nodeCallback($var, $enterExpressionAssign ? $scope->enterExpressionAssign($var) : $scope); $hasYield = \false; $throwPoints = []; $impurePoints = []; $isAssignOp = $assignedExpr instanceof Expr\AssignOp && !$enterExpressionAssign; if ($var instanceof Variable && is_string($var->name)) { $result = $processExprCallback($scope); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); if (in_array($var->name, \PHPStan\Analyser\Scope::SUPERGLOBAL_VARIABLES, \true)) { $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $var, 'superglobal', 'assign to superglobal variable', \true); } $assignedExpr = $this->unwrapAssign($assignedExpr); $type = $scope->getType($assignedExpr); $conditionalExpressions = []; if ($assignedExpr instanceof Ternary) { $if = $assignedExpr->if; if ($if === null) { $if = $assignedExpr->cond; } $condScope = $this->processExprNode($stmt, $assignedExpr->cond, $scope, static function () : void { }, \PHPStan\Analyser\ExpressionContext::createDeep())->getScope(); $truthySpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($condScope, $assignedExpr->cond, \PHPStan\Analyser\TypeSpecifierContext::createTruthy()); $falseySpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($condScope, $assignedExpr->cond, \PHPStan\Analyser\TypeSpecifierContext::createFalsey()); $truthyScope = $condScope->filterBySpecifiedTypes($truthySpecifiedTypes); $falsyScope = $condScope->filterBySpecifiedTypes($falseySpecifiedTypes); $truthyType = $truthyScope->getType($if); $falseyType = $falsyScope->getType($assignedExpr->else); if ($truthyType->isSuperTypeOf($falseyType)->no() && $falseyType->isSuperTypeOf($truthyType)->no()) { $conditionalExpressions = $this->processSureTypesForConditionalExpressionsAfterAssign($condScope, $var->name, $conditionalExpressions, $truthySpecifiedTypes, $truthyType); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($condScope, $var->name, $conditionalExpressions, $truthySpecifiedTypes, $truthyType); $conditionalExpressions = $this->processSureTypesForConditionalExpressionsAfterAssign($condScope, $var->name, $conditionalExpressions, $falseySpecifiedTypes, $falseyType); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($condScope, $var->name, $conditionalExpressions, $falseySpecifiedTypes, $falseyType); } } $scope = $result->getScope(); $truthySpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($scope, $assignedExpr, \PHPStan\Analyser\TypeSpecifierContext::createTruthy()); $falseySpecifiedTypes = $this->typeSpecifier->specifyTypesInCondition($scope, $assignedExpr, \PHPStan\Analyser\TypeSpecifierContext::createFalsey()); $truthyType = TypeCombinator::removeFalsey($type); $falseyType = TypeCombinator::intersect($type, StaticTypeFactory::falsey()); $conditionalExpressions = $this->processSureTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $truthySpecifiedTypes, $truthyType); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $truthySpecifiedTypes, $truthyType); $conditionalExpressions = $this->processSureTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $falseySpecifiedTypes, $falseyType); $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $falseySpecifiedTypes, $falseyType); $nodeCallback(new VariableAssignNode($var, $assignedExpr, $isAssignOp), $result->getScope()); $scope = $scope->assignVariable($var->name, $type, $scope->getNativeType($assignedExpr)); foreach ($conditionalExpressions as $exprString => $holders) { $scope = $scope->addConditionalExpressions($exprString, $holders); } } elseif ($var instanceof ArrayDimFetch) { $dimFetchStack = []; $originalVar = $var; $assignedPropertyExpr = $assignedExpr; while ($var instanceof ArrayDimFetch) { $varForSetOffsetValue = $var->var; if ($varForSetOffsetValue instanceof PropertyFetch || $varForSetOffsetValue instanceof StaticPropertyFetch) { $varForSetOffsetValue = new OriginalPropertyTypeExpr($varForSetOffsetValue); } $assignedPropertyExpr = new SetOffsetValueTypeExpr($varForSetOffsetValue, $var->dim, $assignedPropertyExpr); $dimFetchStack[] = $var; $var = $var->var; } // 1. eval root expr if ($enterExpressionAssign) { $scope = $scope->enterExpressionAssign($var); } $result = $this->processExprNode($stmt, $var, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $result->hasYield(); $throwPoints = $result->getThrowPoints(); $impurePoints = $result->getImpurePoints(); $scope = $result->getScope(); if ($enterExpressionAssign) { $scope = $scope->exitExpressionAssign($var); } // 2. eval dimensions $offsetTypes = []; $offsetNativeTypes = []; $dimFetchStack = array_reverse($dimFetchStack); $lastDimKey = array_key_last($dimFetchStack); foreach ($dimFetchStack as $key => $dimFetch) { $dimExpr = $dimFetch->dim; // Callback was already called for last dim at the beginning of the method. if ($key !== $lastDimKey) { $nodeCallback($dimFetch, $enterExpressionAssign ? $scope->enterExpressionAssign($dimFetch) : $scope); } if ($dimExpr === null) { $offsetTypes[] = null; $offsetNativeTypes[] = null; } else { $offsetTypes[] = $scope->getType($dimExpr); $offsetNativeTypes[] = $scope->getNativeType($dimExpr); if ($enterExpressionAssign) { $scope->enterExpressionAssign($dimExpr); } $result = $this->processExprNode($stmt, $dimExpr, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $scope = $result->getScope(); if ($enterExpressionAssign) { $scope = $scope->exitExpressionAssign($dimExpr); } } } $valueToWrite = $scope->getType($assignedExpr); $nativeValueToWrite = $scope->getNativeType($assignedExpr); $originalValueToWrite = $valueToWrite; $originalNativeValueToWrite = $nativeValueToWrite; // 3. eval assigned expr $result = $processExprCallback($scope); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); $varType = $scope->getType($var); $varNativeType = $scope->getNativeType($var); // 4. compose types if ($varType instanceof ErrorType) { $varType = new ConstantArrayType([], []); } if ($varNativeType instanceof ErrorType) { $varNativeType = new ConstantArrayType([], []); } $offsetValueType = $varType; $offsetNativeValueType = $varNativeType; $valueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetTypes, $offsetValueType, $valueToWrite); if (!$offsetValueType->equals($offsetNativeValueType) || !$valueToWrite->equals($nativeValueToWrite)) { $nativeValueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetNativeTypes, $offsetNativeValueType, $nativeValueToWrite); } else { $rewritten = \false; foreach ($offsetTypes as $i => $offsetType) { $offsetNativeType = $offsetNativeTypes[$i]; if ($offsetType === null) { if ($offsetNativeType !== null) { throw new ShouldNotHappenException(); } continue; } elseif ($offsetNativeType === null) { throw new ShouldNotHappenException(); } if ($offsetType->equals($offsetNativeType)) { continue; } $nativeValueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetNativeTypes, $offsetNativeValueType, $nativeValueToWrite); $rewritten = \true; break; } if (!$rewritten) { $nativeValueToWrite = $valueToWrite; } } if ($varType->isArray()->yes() || !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->yes()) { if ($var instanceof Variable && is_string($var->name)) { $nodeCallback(new VariableAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); $scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite); } else { if ($var instanceof PropertyFetch || $var instanceof StaticPropertyFetch) { $nodeCallback(new PropertyAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); if ($var instanceof PropertyFetch && $var->name instanceof Node\Identifier && !$isAssignOp) { $scope = $scope->assignInitializedProperty($scope->getType($var->var), $var->name->toString()); } } $scope = $scope->assignExpression($var, $valueToWrite, $nativeValueToWrite); } if ($originalVar->dim instanceof Variable || $originalVar->dim instanceof Node\Scalar) { $currentVarType = $scope->getType($originalVar); if (!$originalValueToWrite->isSuperTypeOf($currentVarType)->yes()) { $scope = $scope->assignExpression($originalVar, $originalValueToWrite, $originalNativeValueToWrite); } } } else { if ($var instanceof Variable) { $nodeCallback(new VariableAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); } elseif ($var instanceof PropertyFetch || $var instanceof StaticPropertyFetch) { $nodeCallback(new PropertyAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); if ($var instanceof PropertyFetch && $var->name instanceof Node\Identifier && !$isAssignOp) { $scope = $scope->assignInitializedProperty($scope->getType($var->var), $var->name->toString()); } } } if (!$varType->isArray()->yes() && !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->no()) { $throwPoints = array_merge($throwPoints, $this->processExprNode($stmt, new MethodCall($var, 'offsetSet'), $scope, static function () : void { }, $context)->getThrowPoints()); } } elseif ($var instanceof PropertyFetch) { $objectResult = $this->processExprNode($stmt, $var->var, $scope, $nodeCallback, $context); $hasYield = $objectResult->hasYield(); $throwPoints = $objectResult->getThrowPoints(); $impurePoints = $objectResult->getImpurePoints(); $scope = $objectResult->getScope(); $propertyName = null; if ($var->name instanceof Node\Identifier) { $propertyName = $var->name->name; } else { $propertyNameResult = $this->processExprNode($stmt, $var->name, $scope, $nodeCallback, $context); $hasYield = $hasYield || $propertyNameResult->hasYield(); $throwPoints = array_merge($throwPoints, $propertyNameResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $propertyNameResult->getImpurePoints()); $scope = $propertyNameResult->getScope(); } $result = $processExprCallback($scope); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); $propertyHolderType = $scope->getType($var->var); if ($propertyName !== null && $propertyHolderType->hasProperty($propertyName)->yes()) { $propertyReflection = $propertyHolderType->getProperty($propertyName, $scope); $assignedExprType = $scope->getType($assignedExpr); $nodeCallback(new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scope); if ($propertyReflection->canChangeTypeAfterAssignment()) { $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } $declaringClass = $propertyReflection->getDeclaringClass(); if ($declaringClass->hasNativeProperty($propertyName)) { $nativeProperty = $declaringClass->getNativeProperty($propertyName); if (!$nativeProperty->getNativeType()->accepts($assignedExprType, \true)->yes()) { $throwPoints[] = \PHPStan\Analyser\ThrowPoint::createExplicit($scope, new ObjectType(TypeError::class), $assignedExpr, \false); } if ($enterExpressionAssign) { $scope = $scope->assignInitializedProperty($propertyHolderType, $propertyName); } } } else { // fallback $assignedExprType = $scope->getType($assignedExpr); $nodeCallback(new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scope); $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); // simulate dynamic property assign by __set to get throw points if (!$propertyHolderType->hasMethod('__set')->no()) { $throwPoints = array_merge($throwPoints, $this->processExprNode($stmt, new MethodCall($var->var, '__set'), $scope, static function () : void { }, $context)->getThrowPoints()); } } } elseif ($var instanceof Expr\StaticPropertyFetch) { if ($var->class instanceof Node\Name) { $propertyHolderType = $scope->resolveTypeByName($var->class); } else { $this->processExprNode($stmt, $var->class, $scope, $nodeCallback, $context); $propertyHolderType = $scope->getType($var->class); } $propertyName = null; if ($var->name instanceof Node\Identifier) { $propertyName = $var->name->name; } else { $propertyNameResult = $this->processExprNode($stmt, $var->name, $scope, $nodeCallback, $context); $hasYield = $propertyNameResult->hasYield(); $throwPoints = $propertyNameResult->getThrowPoints(); $impurePoints = $propertyNameResult->getImpurePoints(); $scope = $propertyNameResult->getScope(); } $result = $processExprCallback($scope); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); if ($propertyName !== null) { $propertyReflection = $scope->getPropertyReflection($propertyHolderType, $propertyName); $assignedExprType = $scope->getType($assignedExpr); $nodeCallback(new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scope); if ($propertyReflection !== null && $propertyReflection->canChangeTypeAfterAssignment()) { $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } } else { // fallback $assignedExprType = $scope->getType($assignedExpr); $nodeCallback(new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scope); $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } } elseif ($var instanceof List_ || $var instanceof Array_) { $result = $processExprCallback($scope); $hasYield = $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); foreach ($var->items as $i => $arrayItem) { if ($arrayItem === null) { continue; } $itemScope = $scope; if ($enterExpressionAssign) { $itemScope = $itemScope->enterExpressionAssign($arrayItem->value); } $itemScope = $this->lookForSetAllowedUndefinedExpressions($itemScope, $arrayItem->value); $nodeCallback($arrayItem, $itemScope); if ($arrayItem->key !== null) { $keyResult = $this->processExprNode($stmt, $arrayItem->key, $itemScope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $keyResult->hasYield(); $throwPoints = array_merge($throwPoints, $keyResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $keyResult->getImpurePoints()); $itemScope = $keyResult->getScope(); } $valueResult = $this->processExprNode($stmt, $arrayItem->value, $itemScope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $valueResult->hasYield(); $throwPoints = array_merge($throwPoints, $valueResult->getThrowPoints()); $impurePoints = array_merge($impurePoints, $valueResult->getImpurePoints()); if ($arrayItem->key === null) { $dimExpr = new Node\Scalar\LNumber($i); } else { $dimExpr = $arrayItem->key; } $result = $this->processAssignVar($scope, $stmt, $arrayItem->value, new GetOffsetValueTypeExpr($assignedExpr, $dimExpr), $nodeCallback, $context, static function (\PHPStan\Analyser\MutatingScope $scope) : \PHPStan\Analyser\ExpressionResult { return new \PHPStan\Analyser\ExpressionResult($scope, \false, [], []); }, $enterExpressionAssign); $scope = $result->getScope(); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); } } elseif ($var instanceof ExistingArrayDimFetch) { $dimFetchStack = []; $assignedPropertyExpr = $assignedExpr; while ($var instanceof ExistingArrayDimFetch) { $varForSetOffsetValue = $var->getVar(); if ($varForSetOffsetValue instanceof PropertyFetch || $varForSetOffsetValue instanceof StaticPropertyFetch) { $varForSetOffsetValue = new OriginalPropertyTypeExpr($varForSetOffsetValue); } $assignedPropertyExpr = new SetExistingOffsetValueTypeExpr($varForSetOffsetValue, $var->getDim(), $assignedPropertyExpr); $dimFetchStack[] = $var; $var = $var->getVar(); } $offsetTypes = []; $offsetNativeTypes = []; foreach (array_reverse($dimFetchStack) as $dimFetch) { $dimExpr = $dimFetch->getDim(); $offsetTypes[] = $scope->getType($dimExpr); $offsetNativeTypes[] = $scope->getNativeType($dimExpr); } $valueToWrite = $scope->getType($assignedExpr); $nativeValueToWrite = $scope->getNativeType($assignedExpr); $varType = $scope->getType($var); $varNativeType = $scope->getNativeType($var); $offsetValueType = $varType; $offsetNativeValueType = $varNativeType; $offsetValueTypeStack = [$offsetValueType]; $offsetValueNativeTypeStack = [$offsetNativeValueType]; foreach (array_slice($offsetTypes, 0, -1) as $offsetType) { $offsetValueType = $offsetValueType->getOffsetValueType($offsetType); $offsetValueTypeStack[] = $offsetValueType; } foreach (array_slice($offsetNativeTypes, 0, -1) as $offsetNativeType) { $offsetNativeValueType = $offsetNativeValueType->getOffsetValueType($offsetNativeType); $offsetValueNativeTypeStack[] = $offsetNativeValueType; } foreach (array_reverse($offsetTypes) as $offsetType) { /** @var Type $offsetValueType */ $offsetValueType = array_pop($offsetValueTypeStack); $valueToWrite = $offsetValueType->setExistingOffsetValueType($offsetType, $valueToWrite); } foreach (array_reverse($offsetNativeTypes) as $offsetNativeType) { /** @var Type $offsetNativeValueType */ $offsetNativeValueType = array_pop($offsetValueNativeTypeStack); $nativeValueToWrite = $offsetNativeValueType->setExistingOffsetValueType($offsetNativeType, $nativeValueToWrite); } if ($var instanceof Variable && is_string($var->name)) { $nodeCallback(new VariableAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); $scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite); } else { if ($var instanceof PropertyFetch || $var instanceof StaticPropertyFetch) { $nodeCallback(new PropertyAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); } $scope = $scope->assignExpression($var, $valueToWrite, $nativeValueToWrite); } } return new \PHPStan\Analyser\ExpressionResult($scope, $hasYield, $throwPoints, $impurePoints); } /** * @param list $offsetTypes */ private function produceArrayDimFetchAssignValueToWrite(array $offsetTypes, Type $offsetValueType, Type $valueToWrite) : Type { $offsetValueTypeStack = [$offsetValueType]; foreach (array_slice($offsetTypes, 0, -1) as $offsetType) { if ($offsetType === null) { $offsetValueType = new ConstantArrayType([], []); } else { $offsetValueType = $offsetValueType->getOffsetValueType($offsetType); if ($offsetValueType instanceof ErrorType) { $offsetValueType = new ConstantArrayType([], []); } } $offsetValueTypeStack[] = $offsetValueType; } foreach (array_reverse($offsetTypes) as $i => $offsetType) { /** @var Type $offsetValueType */ $offsetValueType = array_pop($offsetValueTypeStack); if (!$offsetValueType instanceof MixedType) { $types = [new ArrayType(new MixedType(), new MixedType()), new ObjectType(ArrayAccess::class), new NullType()]; if ($offsetType !== null && $offsetType->isInteger()->yes()) { $types[] = new StringType(); } $offsetValueType = TypeCombinator::intersect($offsetValueType, TypeCombinator::union(...$types)); } $valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0); } return $valueToWrite; } private function unwrapAssign(Expr $expr) : Expr { if ($expr instanceof Assign) { return $this->unwrapAssign($expr->expr); } return $expr; } /** * @param array $conditionalExpressions * @return array */ private function processSureTypesForConditionalExpressionsAfterAssign(\PHPStan\Analyser\Scope $scope, string $variableName, array $conditionalExpressions, \PHPStan\Analyser\SpecifiedTypes $specifiedTypes, Type $variableType) : array { foreach ($specifiedTypes->getSureTypes() as $exprString => [$expr, $exprType]) { if (!$expr instanceof Variable) { continue; } if (!is_string($expr->name)) { continue; } if ($expr->name === $variableName) { continue; } if (!isset($conditionalExpressions[$exprString])) { $conditionalExpressions[$exprString] = []; } $holder = new \PHPStan\Analyser\ConditionalExpressionHolder(['$' . $variableName => \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($variableName), $variableType)], \PHPStan\Analyser\ExpressionTypeHolder::createYes($expr, TypeCombinator::intersect($scope->getType($expr), $exprType))); $conditionalExpressions[$exprString][$holder->getKey()] = $holder; } return $conditionalExpressions; } /** * @param array $conditionalExpressions * @return array */ private function processSureNotTypesForConditionalExpressionsAfterAssign(\PHPStan\Analyser\Scope $scope, string $variableName, array $conditionalExpressions, \PHPStan\Analyser\SpecifiedTypes $specifiedTypes, Type $variableType) : array { foreach ($specifiedTypes->getSureNotTypes() as $exprString => [$expr, $exprType]) { if (!$expr instanceof Variable) { continue; } if (!is_string($expr->name)) { continue; } if ($expr->name === $variableName) { continue; } if (!isset($conditionalExpressions[$exprString])) { $conditionalExpressions[$exprString] = []; } $holder = new \PHPStan\Analyser\ConditionalExpressionHolder(['$' . $variableName => \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($variableName), $variableType)], \PHPStan\Analyser\ExpressionTypeHolder::createYes($expr, TypeCombinator::remove($scope->getType($expr), $exprType))); $conditionalExpressions[$exprString][$holder->getKey()] = $holder; } return $conditionalExpressions; } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processStmtVarAnnotation(\PHPStan\Analyser\MutatingScope $scope, Node\Stmt $stmt, ?Expr $defaultExpr, callable $nodeCallback) : \PHPStan\Analyser\MutatingScope { $function = $scope->getFunction(); $variableLessTags = []; foreach ($stmt->getComments() as $comment) { if (!$comment instanceof Doc) { continue; } $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $function !== null ? $function->getName() : null, $comment->getText()); $assignedVariable = null; if ($stmt instanceof Node\Stmt\Expression && ($stmt->expr instanceof Assign || $stmt->expr instanceof AssignRef) && $stmt->expr->var instanceof Variable && is_string($stmt->expr->var->name)) { $assignedVariable = $stmt->expr->var->name; } foreach ($resolvedPhpDoc->getVarTags() as $name => $varTag) { if (is_int($name)) { $variableLessTags[] = $varTag; continue; } if ($name === $assignedVariable) { continue; } $certainty = $scope->hasVariableType($name); if ($certainty->no()) { continue; } if ($scope->isInClass() && $scope->getFunction() === null) { continue; } if ($scope->canAnyVariableExist()) { $certainty = TrinaryLogic::createYes(); } $variableNode = new Variable($name, $stmt->getAttributes()); $originalType = $scope->getVariableType($name); if (!$originalType->equals($varTag->getType())) { $nodeCallback(new VarTagChangedExpressionTypeNode($varTag, $variableNode), $scope); } $scope = $scope->assignVariable($name, $varTag->getType(), $scope->getNativeType($variableNode), $certainty); } } if (count($variableLessTags) === 1 && $defaultExpr !== null) { $originalType = $scope->getType($defaultExpr); $varTag = $variableLessTags[0]; if (!$originalType->equals($varTag->getType())) { $nodeCallback(new VarTagChangedExpressionTypeNode($varTag, $defaultExpr), $scope); } $scope = $scope->assignExpression($defaultExpr, $varTag->getType(), new MixedType()); } return $scope; } /** * @param array $variableNames */ private function processVarAnnotation(\PHPStan\Analyser\MutatingScope $scope, array $variableNames, Node\Stmt $node, bool &$changed = \false) : \PHPStan\Analyser\MutatingScope { $function = $scope->getFunction(); $varTags = []; foreach ($node->getComments() as $comment) { if (!$comment instanceof Doc) { continue; } $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()->getName() : null, $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, $function !== null ? $function->getName() : null, $comment->getText()); foreach ($resolvedPhpDoc->getVarTags() as $key => $varTag) { $varTags[$key] = $varTag; } } if (count($varTags) === 0) { return $scope; } foreach ($variableNames as $variableName) { if (!isset($varTags[$variableName])) { continue; } $variableType = $varTags[$variableName]->getType(); $changed = \true; $scope = $scope->assignVariable($variableName, $variableType, new MixedType()); } if (count($variableNames) === 1 && count($varTags) === 1 && isset($varTags[0])) { $variableType = $varTags[0]->getType(); $changed = \true; $scope = $scope->assignVariable($variableNames[0], $variableType, new MixedType()); } return $scope; } private function enterForeach(\PHPStan\Analyser\MutatingScope $scope, \PHPStan\Analyser\MutatingScope $originalScope, Foreach_ $stmt) : \PHPStan\Analyser\MutatingScope { if ($stmt->expr instanceof Variable && is_string($stmt->expr->name)) { $scope = $this->processVarAnnotation($scope, [$stmt->expr->name], $stmt); } $iterateeType = $originalScope->getType($stmt->expr); if ($stmt->valueVar instanceof Variable && is_string($stmt->valueVar->name) && ($stmt->keyVar === null || $stmt->keyVar instanceof Variable && is_string($stmt->keyVar->name))) { $keyVarName = null; if ($stmt->keyVar instanceof Variable && is_string($stmt->keyVar->name)) { $keyVarName = $stmt->keyVar->name; } $scope = $scope->enterForeach($originalScope, $stmt->expr, $stmt->valueVar->name, $keyVarName); $vars = [$stmt->valueVar->name]; if ($keyVarName !== null) { $vars[] = $keyVarName; } } else { $scope = $this->processAssignVar($scope, $stmt, $stmt->valueVar, new GetIterableValueTypeExpr($stmt->expr), static function () : void { }, \PHPStan\Analyser\ExpressionContext::createDeep(), static function (\PHPStan\Analyser\MutatingScope $scope) : \PHPStan\Analyser\ExpressionResult { return new \PHPStan\Analyser\ExpressionResult($scope, \false, [], []); }, \true)->getScope(); $vars = $this->getAssignedVariables($stmt->valueVar); if ($stmt->keyVar instanceof Variable && is_string($stmt->keyVar->name)) { $scope = $scope->enterForeachKey($originalScope, $stmt->expr, $stmt->keyVar->name); $vars[] = $stmt->keyVar->name; } elseif ($stmt->keyVar !== null) { $scope = $this->processAssignVar($scope, $stmt, $stmt->keyVar, new GetIterableKeyTypeExpr($stmt->expr), static function () : void { }, \PHPStan\Analyser\ExpressionContext::createDeep(), static function (\PHPStan\Analyser\MutatingScope $scope) : \PHPStan\Analyser\ExpressionResult { return new \PHPStan\Analyser\ExpressionResult($scope, \false, [], []); }, \true)->getScope(); $vars = array_merge($vars, $this->getAssignedVariables($stmt->keyVar)); } } $constantArrays = $iterateeType->getConstantArrays(); if ($stmt->getDocComment() === null && $iterateeType->isConstantArray()->yes() && count($constantArrays) === 1 && $stmt->valueVar instanceof Variable && is_string($stmt->valueVar->name) && $stmt->keyVar instanceof Variable && is_string($stmt->keyVar->name)) { $valueConditionalHolders = []; $arrayDimFetchConditionalHolders = []; foreach ($constantArrays[0]->getKeyTypes() as $i => $keyType) { $valueType = $constantArrays[0]->getValueTypes()[$i]; $holder = new \PHPStan\Analyser\ConditionalExpressionHolder(['$' . $stmt->keyVar->name => \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($stmt->keyVar->name), $keyType)], new \PHPStan\Analyser\ExpressionTypeHolder($stmt->valueVar, $valueType, TrinaryLogic::createYes())); $valueConditionalHolders[$holder->getKey()] = $holder; $arrayDimFetchHolder = new \PHPStan\Analyser\ConditionalExpressionHolder(['$' . $stmt->keyVar->name => \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($stmt->keyVar->name), $keyType)], new \PHPStan\Analyser\ExpressionTypeHolder(new ArrayDimFetch($stmt->expr, $stmt->keyVar), $valueType, TrinaryLogic::createYes())); $arrayDimFetchConditionalHolders[$arrayDimFetchHolder->getKey()] = $arrayDimFetchHolder; } $scope = $scope->addConditionalExpressions('$' . $stmt->valueVar->name, $valueConditionalHolders); if ($stmt->expr instanceof Variable && is_string($stmt->expr->name)) { $scope = $scope->addConditionalExpressions(sprintf('$%s[$%s]', $stmt->expr->name, $stmt->keyVar->name), $arrayDimFetchConditionalHolders); } } return $this->processVarAnnotation($scope, $vars, $stmt); } /** * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processTraitUse(Node\Stmt\TraitUse $node, \PHPStan\Analyser\MutatingScope $classScope, callable $nodeCallback) : void { $parentTraitNames = []; $parent = $classScope->getParentScope(); while ($parent !== null) { if ($parent->isInTrait()) { $parentTraitNames[] = $parent->getTraitReflection()->getName(); } $parent = $parent->getParentScope(); } foreach ($node->traits as $trait) { $traitName = (string) $trait; if (in_array($traitName, $parentTraitNames, \true)) { continue; } if (!$this->reflectionProvider->hasClass($traitName)) { continue; } $traitReflection = $this->reflectionProvider->getClass($traitName); $traitFileName = $traitReflection->getFileName(); if ($traitFileName === null) { continue; // trait from eval or from PHP itself } $fileName = $this->fileHelper->normalizePath($traitFileName); if (!isset($this->analysedFiles[$fileName])) { continue; } $adaptations = []; foreach ($node->adaptations as $adaptation) { if ($adaptation->trait === null) { $adaptations[] = $adaptation; continue; } if ($adaptation->trait->toLowerString() !== $trait->toLowerString()) { continue; } $adaptations[] = $adaptation; } $parserNodes = $this->parser->parseFile($fileName); $this->processNodesForTraitUse($parserNodes, $traitReflection, $classScope, $adaptations, $nodeCallback); } } /** * @param Node[]|Node|scalar|null $node * @param Node\Stmt\TraitUseAdaptation[] $adaptations * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processNodesForTraitUse($node, ClassReflection $traitReflection, \PHPStan\Analyser\MutatingScope $scope, array $adaptations, callable $nodeCallback) : void { if ($node instanceof Node) { if ($node instanceof Node\Stmt\Trait_ && $traitReflection->getName() === (string) $node->namespacedName && $traitReflection->getNativeReflection()->getStartLine() === $node->getStartLine()) { $methodModifiers = []; $methodNames = []; foreach ($adaptations as $adaptation) { if (!$adaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) { continue; } $methodName = $adaptation->method->toLowerString(); if ($adaptation->newModifier !== null) { $methodModifiers[$methodName] = $adaptation->newModifier; } if ($adaptation->newName === null) { continue; } $methodNames[$methodName] = $adaptation->newName; } $stmts = $node->stmts; foreach ($stmts as $i => $stmt) { if (!$stmt instanceof Node\Stmt\ClassMethod) { continue; } $methodName = $stmt->name->toLowerString(); $methodAst = clone $stmt; $stmts[$i] = $methodAst; if (array_key_exists($methodName, $methodModifiers)) { $methodAst->flags = $methodAst->flags & ~Node\Stmt\Class_::VISIBILITY_MODIFIER_MASK | $methodModifiers[$methodName]; } if (!array_key_exists($methodName, $methodNames)) { continue; } $methodAst->setAttribute('originalTraitMethodName', $methodAst->name->toLowerString()); $methodAst->name = $methodNames[$methodName]; } if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $traitScope = $scope->enterTrait($traitReflection); $nodeCallback(new InTraitNode($node, $traitReflection, $scope->getClassReflection()), $traitScope); $this->processStmtNodes($node, $stmts, $traitScope, $nodeCallback, \PHPStan\Analyser\StatementContext::createTopLevel()); return; } if ($node instanceof Node\Stmt\ClassLike) { return; } if ($node instanceof Node\FunctionLike) { return; } foreach ($node->getSubNodeNames() as $subNodeName) { $subNode = $node->{$subNodeName}; $this->processNodesForTraitUse($subNode, $traitReflection, $scope, $adaptations, $nodeCallback); } } elseif (is_array($node)) { foreach ($node as $subNode) { $this->processNodesForTraitUse($subNode, $traitReflection, $scope, $adaptations, $nodeCallback); } } } private function processCalledMethod(MethodReflection $methodReflection) : ?\PHPStan\Analyser\MutatingScope { $declaringClass = $methodReflection->getDeclaringClass(); if ($declaringClass->isAnonymous()) { return null; } if ($declaringClass->getFileName() === null) { return null; } $stackName = sprintf('%s::%s', $declaringClass->getName(), $methodReflection->getName()); if (array_key_exists($stackName, $this->calledMethodResults)) { return $this->calledMethodResults[$stackName]; } if (array_key_exists($stackName, $this->calledMethodStack)) { return null; } if (count($this->calledMethodStack) > 0) { return null; } $this->calledMethodStack[$stackName] = \true; $fileName = $this->fileHelper->normalizePath($declaringClass->getFileName()); if (!isset($this->analysedFiles[$fileName])) { return null; } $parserNodes = $this->parser->parseFile($fileName); $returnStatement = null; $this->processNodesForCalledMethod($parserNodes, $fileName, $methodReflection, static function (Node $node, \PHPStan\Analyser\Scope $scope) use($methodReflection, &$returnStatement) : void { if (!$node instanceof MethodReturnStatementsNode) { return; } if ($node->getClassReflection()->getName() !== $methodReflection->getDeclaringClass()->getName()) { return; } if ($returnStatement !== null) { return; } $returnStatement = $node; }); $calledMethodEndScope = null; if ($returnStatement !== null) { foreach ($returnStatement->getExecutionEnds() as $executionEnd) { $statementResult = $executionEnd->getStatementResult(); $endNode = $executionEnd->getNode(); if ($endNode instanceof Node\Stmt\Throw_) { continue; } if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); if ($exprType instanceof NeverType && $exprType->isExplicit()) { continue; } } if ($calledMethodEndScope === null) { $calledMethodEndScope = $statementResult->getScope(); continue; } $calledMethodEndScope = $calledMethodEndScope->mergeWith($statementResult->getScope()); } foreach ($returnStatement->getReturnStatements() as $statement) { if ($calledMethodEndScope === null) { $calledMethodEndScope = $statement->getScope(); continue; } $calledMethodEndScope = $calledMethodEndScope->mergeWith($statement->getScope()); } } unset($this->calledMethodStack[$stackName]); $this->calledMethodResults[$stackName] = $calledMethodEndScope; return $calledMethodEndScope; } /** * @param Node[]|Node|scalar|null $node * @param callable(Node $node, Scope $scope): void $nodeCallback */ private function processNodesForCalledMethod($node, string $fileName, MethodReflection $methodReflection, callable $nodeCallback) : void { if ($node instanceof Node) { $declaringClass = $methodReflection->getDeclaringClass(); if ($node instanceof Node\Stmt\Class_ && $node->namespacedName !== null && $declaringClass->getName() === (string) $node->namespacedName && $declaringClass->getNativeReflection()->getStartLine() === $node->getStartLine()) { $stmts = $node->stmts; foreach ($stmts as $stmt) { if (!$stmt instanceof Node\Stmt\ClassMethod) { continue; } if ($stmt->name->toString() !== $methodReflection->getName()) { continue; } if ($stmt->getEndLine() - $stmt->getStartLine() > 50) { continue; } $scope = $this->scopeFactory->create(\PHPStan\Analyser\ScopeContext::create($fileName))->enterClass($declaringClass); $this->processStmtNode($stmt, $scope, $nodeCallback, \PHPStan\Analyser\StatementContext::createTopLevel()); } return; } if ($node instanceof Node\Stmt\ClassLike) { return; } if ($node instanceof Node\FunctionLike) { return; } foreach ($node->getSubNodeNames() as $subNodeName) { $subNode = $node->{$subNodeName}; $this->processNodesForCalledMethod($subNode, $fileName, $methodReflection, $nodeCallback); } } elseif (is_array($node)) { foreach ($node as $subNode) { $this->processNodesForCalledMethod($subNode, $fileName, $methodReflection, $nodeCallback); } } } /** * @return array{TemplateTypeMap, array, array, array, ?Type, ?Type, ?string, bool, bool, bool, bool|null, bool, bool, string|null, Assertions, ?Type, array, array<(string|int), VarTag>, bool} * @param Node\FunctionLike|Node\Stmt\Property $node */ public function getPhpDocs(\PHPStan\Analyser\Scope $scope, $node) : array { $templateTypeMap = TemplateTypeMap::createEmpty(); $phpDocParameterTypes = []; $phpDocImmediatelyInvokedCallableParameters = []; $phpDocClosureThisTypeParameters = []; $phpDocReturnType = null; $phpDocThrowType = null; $deprecatedDescription = null; $isDeprecated = \false; $isInternal = \false; $isFinal = \false; $isPure = null; $isAllowedPrivateMutation = \false; $acceptsNamedArguments = \true; $isReadOnly = $scope->isInClass() && $scope->getClassReflection()->isImmutable(); $asserts = Assertions::createEmpty(); $selfOutType = null; $docComment = $node->getDocComment() !== null ? $node->getDocComment()->getText() : null; $file = $scope->getFile(); $class = $scope->isInClass() ? $scope->getClassReflection()->getName() : null; $trait = $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null; $resolvedPhpDoc = null; $functionName = null; $phpDocParameterOutTypes = []; if ($node instanceof Node\Stmt\ClassMethod) { if (!$scope->isInClass()) { throw new ShouldNotHappenException(); } $functionName = $node->name->name; $positionalParameterNames = array_map(static function (Node\Param $param) : string { if (!$param->var instanceof Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } return $param->var->name; }, $node->getParams()); $resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForMethod($docComment, $file, $scope->getClassReflection(), $trait, $node->name->name, $positionalParameterNames); if ($node->name->toLowerString() === '__construct') { foreach ($node->params as $param) { if ($param->flags === 0) { continue; } if ($param->getDocComment() === null) { continue; } if (!$param->var instanceof Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $paramPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($file, $class, $trait, '__construct', $param->getDocComment()->getText()); $varTags = $paramPhpDoc->getVarTags(); if (isset($varTags[0]) && count($varTags) === 1) { $phpDocType = $varTags[0]->getType(); } elseif (isset($varTags[$param->var->name])) { $phpDocType = $varTags[$param->var->name]->getType(); } else { continue; } $phpDocParameterTypes[$param->var->name] = $phpDocType; } } } elseif ($node instanceof Node\Stmt\Function_) { $functionName = trim($scope->getNamespace() . '\\' . $node->name->name, '\\'); } if ($docComment !== null && $resolvedPhpDoc === null) { $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($file, $class, $trait, $functionName, $docComment); } $varTags = []; if ($resolvedPhpDoc !== null) { $templateTypeMap = $resolvedPhpDoc->getTemplateTypeMap(); $phpDocImmediatelyInvokedCallableParameters = $resolvedPhpDoc->getParamsImmediatelyInvokedCallable(); foreach ($resolvedPhpDoc->getParamTags() as $paramName => $paramTag) { if (array_key_exists($paramName, $phpDocParameterTypes)) { continue; } $paramType = $paramTag->getType(); if ($scope->isInClass()) { $paramType = $this->transformStaticType($scope->getClassReflection(), $paramType); } $phpDocParameterTypes[$paramName] = $paramType; } foreach ($resolvedPhpDoc->getParamClosureThisTags() as $paramName => $paramClosureThisTag) { if (array_key_exists($paramName, $phpDocClosureThisTypeParameters)) { continue; } $paramClosureThisType = $paramClosureThisTag->getType(); if ($scope->isInClass()) { $paramClosureThisType = $this->transformStaticType($scope->getClassReflection(), $paramClosureThisType); } $phpDocClosureThisTypeParameters[$paramName] = $paramClosureThisType; } foreach ($resolvedPhpDoc->getParamOutTags() as $paramName => $paramOutTag) { $phpDocParameterOutTypes[$paramName] = $paramOutTag->getType(); } if ($node instanceof Node\FunctionLike) { $nativeReturnType = $scope->getFunctionType($node->getReturnType(), \false, \false); $phpDocReturnType = $this->getPhpDocReturnType($resolvedPhpDoc, $nativeReturnType); if ($phpDocReturnType !== null && $scope->isInClass()) { $phpDocReturnType = $this->transformStaticType($scope->getClassReflection(), $phpDocReturnType); } } $phpDocThrowType = $resolvedPhpDoc->getThrowsTag() !== null ? $resolvedPhpDoc->getThrowsTag()->getType() : null; $deprecatedDescription = $resolvedPhpDoc->getDeprecatedTag() !== null ? $resolvedPhpDoc->getDeprecatedTag()->getMessage() : null; $isDeprecated = $resolvedPhpDoc->isDeprecated(); $isInternal = $resolvedPhpDoc->isInternal(); $isFinal = $resolvedPhpDoc->isFinal(); $isPure = $resolvedPhpDoc->isPure(); $isAllowedPrivateMutation = $resolvedPhpDoc->isAllowedPrivateMutation(); $acceptsNamedArguments = $resolvedPhpDoc->acceptsNamedArguments(); if ($acceptsNamedArguments && $scope->isInClass()) { $acceptsNamedArguments = $scope->getClassReflection()->acceptsNamedArguments(); } $isReadOnly = $isReadOnly || $resolvedPhpDoc->isReadOnly(); $asserts = Assertions::createFromResolvedPhpDocBlock($resolvedPhpDoc); $selfOutType = $resolvedPhpDoc->getSelfOutTag() !== null ? $resolvedPhpDoc->getSelfOutTag()->getType() : null; $varTags = $resolvedPhpDoc->getVarTags(); } return [$templateTypeMap, $phpDocParameterTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, $isReadOnly, $docComment, $asserts, $selfOutType, $phpDocParameterOutTypes, $varTags, $isAllowedPrivateMutation]; } private function transformStaticType(ClassReflection $declaringClass, Type $type) : Type { return TypeTraverser::map($type, static function (Type $type, callable $traverse) use($declaringClass) : Type { if ($type instanceof StaticType) { $changedType = $type->changeBaseClass($declaringClass); if ($declaringClass->isFinal() && !$type instanceof ThisType) { $changedType = $changedType->getStaticObjectType(); } return $traverse($changedType); } return $traverse($type); }); } private function getPhpDocReturnType(ResolvedPhpDocBlock $resolvedPhpDoc, Type $nativeReturnType) : ?Type { $returnTag = $resolvedPhpDoc->getReturnTag(); if ($returnTag === null) { return null; } $phpDocReturnType = $returnTag->getType(); if ($returnTag->isExplicit()) { return $phpDocReturnType; } if ($nativeReturnType->isSuperTypeOf(TemplateTypeHelper::resolveToBounds($phpDocReturnType))->yes()) { return $phpDocReturnType; } return null; } /** * @template T of Node * @param array $nodes * @return T|null */ private function getFirstUnreachableNode(array $nodes, bool $earlyBinding) : ?Node { foreach ($nodes as $node) { if ($node instanceof Node\Stmt\Nop) { continue; } if ($earlyBinding && ($node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\HaltCompiler)) { continue; } return $node; } return null; } } statement = $statement; $this->scope = $scope; } public function getStatement() : Stmt { return $this->statement; } public function getScope() : \PHPStan\Analyser\MutatingScope { return $this->scope; } } container = $container; } public function create() : \PHPStan\Analyser\TypeSpecifier { $typeSpecifier = new \PHPStan\Analyser\TypeSpecifier($this->container->getByType(ExprPrinter::class), $this->container->getByType(ReflectionProvider::class), $this->container->getServicesByTag(self::FUNCTION_TYPE_SPECIFYING_EXTENSION_TAG), $this->container->getServicesByTag(self::METHOD_TYPE_SPECIFYING_EXTENSION_TAG), $this->container->getServicesByTag(self::STATIC_METHOD_TYPE_SPECIFYING_EXTENSION_TAG), $this->container->getParameter('rememberPossiblyImpureFunctionValues')); foreach (array_merge($this->container->getServicesByTag(BrokerFactory::PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG), $this->container->getServicesByTag(BrokerFactory::METHODS_CLASS_REFLECTION_EXTENSION_TAG), $this->container->getServicesByTag(BrokerFactory::DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG), $this->container->getServicesByTag(BrokerFactory::DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG), $this->container->getServicesByTag(BrokerFactory::DYNAMIC_FUNCTION_RETURN_TYPE_EXTENSION_TAG)) as $extension) { if (!$extension instanceof \PHPStan\Analyser\TypeSpecifierAwareExtension) { continue; } $extension->setTypeSpecifier($typeSpecifier); } return $typeSpecifier; } } $nodeType * @param string|RuleError $ruleError */ public function transform($ruleError, \PHPStan\Analyser\Scope $scope, string $nodeType, int $nodeLine) : \PHPStan\Analyser\Error { $line = $nodeLine; $canBeIgnored = \true; $fileName = $scope->getFileDescription(); $filePath = $scope->getFile(); $traitFilePath = null; $tip = null; $identifier = null; $metadata = []; if ($scope->isInTrait()) { $traitReflection = $scope->getTraitReflection(); if ($traitReflection->getFileName() !== null) { $traitFilePath = $traitReflection->getFileName(); } } if (is_string($ruleError)) { $message = $ruleError; } else { $message = $ruleError->getMessage(); if ($ruleError instanceof LineRuleError && $ruleError->getLine() !== -1) { $line = $ruleError->getLine(); } if ($ruleError instanceof FileRuleError && $ruleError->getFile() !== '') { $fileName = $ruleError->getFileDescription(); $filePath = $ruleError->getFile(); $traitFilePath = null; } if ($ruleError instanceof TipRuleError) { $tip = $ruleError->getTip(); } if ($ruleError instanceof IdentifierRuleError) { $identifier = $ruleError->getIdentifier(); } if ($ruleError instanceof MetadataRuleError) { $metadata = $ruleError->getMetadata(); } if ($ruleError instanceof NonIgnorableRuleError) { $canBeIgnored = \false; } } return new \PHPStan\Analyser\Error($message, $fileName, $line, $canBeIgnored, $filePath, $traitFilePath, $tip, $nodeLine, $nodeType, $identifier, $metadata); } } $temporaryFileErrors * @param LinesToIgnore $linesToIgnore * @param LinesToIgnore $unmatchedLineIgnores */ public function process(array $temporaryFileErrors, array $linesToIgnore, array $unmatchedLineIgnores) : \PHPStan\Analyser\LocalIgnoresProcessorResult { $fileErrors = []; $locallyIgnoredErrors = []; foreach ($temporaryFileErrors as $tmpFileError) { $line = $tmpFileError->getLine(); if ($line !== null && $tmpFileError->canBeIgnored() && array_key_exists($tmpFileError->getFile(), $linesToIgnore) && array_key_exists($line, $linesToIgnore[$tmpFileError->getFile()])) { $identifiers = $linesToIgnore[$tmpFileError->getFile()][$line]; if ($identifiers === null) { $locallyIgnoredErrors[] = $tmpFileError; unset($unmatchedLineIgnores[$tmpFileError->getFile()][$line]); continue; } if ($tmpFileError->getIdentifier() === null) { $fileErrors[] = $tmpFileError; continue; } foreach ($identifiers as $i => $ignoredIdentifier) { if ($ignoredIdentifier !== $tmpFileError->getIdentifier()) { continue; } unset($identifiers[$i]); if (count($identifiers) > 0) { $linesToIgnore[$tmpFileError->getFile()][$line] = array_values($identifiers); } else { unset($linesToIgnore[$tmpFileError->getFile()][$line]); } if (array_key_exists($tmpFileError->getFile(), $unmatchedLineIgnores) && array_key_exists($line, $unmatchedLineIgnores[$tmpFileError->getFile()])) { $unmatchedIgnoredIdentifiers = $unmatchedLineIgnores[$tmpFileError->getFile()][$line]; if (is_array($unmatchedIgnoredIdentifiers)) { foreach ($unmatchedIgnoredIdentifiers as $j => $unmatchedIgnoredIdentifier) { if ($ignoredIdentifier !== $unmatchedIgnoredIdentifier) { continue; } unset($unmatchedIgnoredIdentifiers[$j]); if (count($unmatchedIgnoredIdentifiers) > 0) { $unmatchedLineIgnores[$tmpFileError->getFile()][$line] = array_values($unmatchedIgnoredIdentifiers); } else { unset($unmatchedLineIgnores[$tmpFileError->getFile()][$line]); } break; } } } $locallyIgnoredErrors[] = $tmpFileError; continue 2; } } $fileErrors[] = $tmpFileError; } return new \PHPStan\Analyser\LocalIgnoresProcessorResult($fileErrors, $locallyIgnoredErrors, $linesToIgnore, $unmatchedLineIgnores); } } */ private $fileErrors; /** * @var list */ private $locallyIgnoredErrors; /** * @var LinesToIgnore */ private $linesToIgnore; /** * @var LinesToIgnore */ private $unmatchedLineIgnores; /** * @param list $fileErrors * @param list $locallyIgnoredErrors * @param LinesToIgnore $linesToIgnore * @param LinesToIgnore $unmatchedLineIgnores */ public function __construct(array $fileErrors, array $locallyIgnoredErrors, array $linesToIgnore, array $unmatchedLineIgnores) { $this->fileErrors = $fileErrors; $this->locallyIgnoredErrors = $locallyIgnoredErrors; $this->linesToIgnore = $linesToIgnore; $this->unmatchedLineIgnores = $unmatchedLineIgnores; } /** * @return list */ public function getFileErrors() : array { return $this->fileErrors; } /** * @return list */ public function getLocallyIgnoredErrors() : array { return $this->locallyIgnoredErrors; } /** * @return LinesToIgnore */ public function getLinesToIgnore() : array { return $this->linesToIgnore; } /** * @return LinesToIgnore */ public function getUnmatchedLineIgnores() : array { return $this->unmatchedLineIgnores; } } */ private $conditionExpressionTypeHolders; /** * @var ExpressionTypeHolder */ private $typeHolder; /** * @param array $conditionExpressionTypeHolders */ public function __construct(array $conditionExpressionTypeHolders, \PHPStan\Analyser\ExpressionTypeHolder $typeHolder) { $this->conditionExpressionTypeHolders = $conditionExpressionTypeHolders; $this->typeHolder = $typeHolder; if (count($conditionExpressionTypeHolders) === 0) { throw new ShouldNotHappenException(); } } /** * @return array */ public function getConditionExpressionTypeHolders() : array { return $this->conditionExpressionTypeHolders; } public function getTypeHolder() : \PHPStan\Analyser\ExpressionTypeHolder { return $this->typeHolder; } public function getKey() : string { $parts = []; foreach ($this->conditionExpressionTypeHolders as $exprString => $typeHolder) { $parts[] = $exprString . '=' . $typeHolder->getType()->describe(VerbosityLevel::precise()); } return sprintf('%s => %s (%s)', implode(' && ', $parts), $this->typeHolder->getType()->describe(VerbosityLevel::precise()), $this->typeHolder->getCertainty()->describe()); } } fileAnalyser = $fileAnalyser; $this->ruleRegistry = $ruleRegistry; $this->collectorRegistry = $collectorRegistry; $this->nodeScopeResolver = $nodeScopeResolver; $this->internalErrorsCountLimit = $internalErrorsCountLimit; } /** * @param string[] $files * @param Closure(string $file): void|null $preFileCallback * @param Closure(int ): void|null $postFileCallback * @param string[]|null $allAnalysedFiles */ public function analyse(array $files, ?Closure $preFileCallback = null, ?Closure $postFileCallback = null, bool $debug = \false, ?array $allAnalysedFiles = null) : \PHPStan\Analyser\AnalyserResult { if ($allAnalysedFiles === null) { $allAnalysedFiles = $files; } $this->nodeScopeResolver->setAnalysedFiles($allAnalysedFiles); $allAnalysedFiles = array_fill_keys($allAnalysedFiles, \true); /** @var list $errors */ $errors = []; /** @var list $filteredPhpErrors */ $filteredPhpErrors = []; /** @var list $allPhpErrors */ $allPhpErrors = []; /** @var list $locallyIgnoredErrors */ $locallyIgnoredErrors = []; $linesToIgnore = []; $unmatchedLineIgnores = []; /** @var list $collectedData */ $collectedData = []; $internalErrorsCount = 0; $reachedInternalErrorsCountLimit = \false; $dependencies = []; $usedTraitDependencies = []; $exportedNodes = []; foreach ($files as $file) { if ($preFileCallback !== null) { $preFileCallback($file); } try { $fileAnalyserResult = $this->fileAnalyser->analyseFile($file, $allAnalysedFiles, $this->ruleRegistry, $this->collectorRegistry, null); $errors = array_merge($errors, $fileAnalyserResult->getErrors()); $filteredPhpErrors = array_merge($filteredPhpErrors, $fileAnalyserResult->getFilteredPhpErrors()); $allPhpErrors = array_merge($allPhpErrors, $fileAnalyserResult->getAllPhpErrors()); $locallyIgnoredErrors = array_merge($locallyIgnoredErrors, $fileAnalyserResult->getLocallyIgnoredErrors()); $linesToIgnore[$file] = $fileAnalyserResult->getLinesToIgnore(); $unmatchedLineIgnores[$file] = $fileAnalyserResult->getUnmatchedLineIgnores(); $collectedData = array_merge($collectedData, $fileAnalyserResult->getCollectedData()); $dependencies[$file] = $fileAnalyserResult->getDependencies(); $usedTraitDependencies[$file] = $fileAnalyserResult->getUsedTraitDependencies(); $fileExportedNodes = $fileAnalyserResult->getExportedNodes(); if (count($fileExportedNodes) > 0) { $exportedNodes[$file] = $fileExportedNodes; } } catch (Throwable $t) { if ($debug) { throw $t; } $internalErrorsCount++; $errors[] = (new \PHPStan\Analyser\Error($t->getMessage(), $file, null, $t))->withIdentifier('phpstan.internal')->withMetadata([\PHPStan\Analyser\InternalError::STACK_TRACE_METADATA_KEY => \PHPStan\Analyser\InternalError::prepareTrace($t), \PHPStan\Analyser\InternalError::STACK_TRACE_AS_STRING_METADATA_KEY => $t->getTraceAsString()]); if ($internalErrorsCount >= $this->internalErrorsCountLimit) { $reachedInternalErrorsCountLimit = \true; break; } } if ($postFileCallback === null) { continue; } $postFileCallback(1); } return new \PHPStan\Analyser\AnalyserResult($errors, $filteredPhpErrors, $allPhpErrors, $locallyIgnoredErrors, $linesToIgnore, $unmatchedLineIgnores, [], $collectedData, $internalErrorsCount === 0 ? $dependencies : null, $internalErrorsCount === 0 ? $usedTraitDependencies : null, $exportedNodes, $reachedInternalErrorsCountLimit, memory_get_peak_usage(\true)); } } initializerExprTypeResolver = $initializerExprTypeResolver; } /** * @return TypeResult */ public function getIdenticalResult(\PHPStan\Analyser\Scope $scope, Identical $expr) : TypeResult { if ($expr->left instanceof Variable && is_string($expr->left->name) && $expr->right instanceof Variable && is_string($expr->right->name) && $expr->left->name === $expr->right->name) { return new TypeResult(new ConstantBooleanType(\true), []); } $leftType = $scope->getType($expr->left); $rightType = $scope->getType($expr->right); if (!$scope instanceof \PHPStan\Analyser\MutatingScope) { return $this->initializerExprTypeResolver->resolveIdenticalType($leftType, $rightType); } if (($expr->left instanceof Node\Expr\PropertyFetch || $expr->left instanceof Node\Expr\StaticPropertyFetch) && $rightType->isNull()->yes() && !$scope->hasPropertyNativeType($expr->left)) { return new TypeResult(new BooleanType(), []); } if (($expr->right instanceof Node\Expr\PropertyFetch || $expr->right instanceof Node\Expr\StaticPropertyFetch) && $leftType->isNull()->yes() && !$scope->hasPropertyNativeType($expr->right)) { return new TypeResult(new BooleanType(), []); } return $this->initializerExprTypeResolver->resolveIdenticalType($leftType, $rightType); } /** * @return TypeResult */ public function getNotIdenticalResult(\PHPStan\Analyser\Scope $scope, Node\Expr\BinaryOp\NotIdentical $expr) : TypeResult { $identicalResult = $this->getIdenticalResult($scope, new Identical($expr->left, $expr->right)); $identicalType = $identicalResult->type; if ($identicalType instanceof ConstantBooleanType) { return new TypeResult(new ConstantBooleanType(!$identicalType->getValue()), $identicalResult->reasons); } return new TypeResult(new BooleanType(), []); } } file = $file; $this->classReflection = $classReflection; $this->traitReflection = $traitReflection; } /** @api */ public static function create(string $file) : self { return new self($file, null, null); } public function beginFile() : self { return new self($this->file, null, null); } public function enterClass(ClassReflection $classReflection) : self { if ($this->classReflection !== null && !$classReflection->isAnonymous()) { throw new ShouldNotHappenException(); } if ($classReflection->isTrait()) { throw new ShouldNotHappenException(); } return new self($this->file, $classReflection, null); } public function enterTrait(ClassReflection $traitReflection) : self { if ($this->classReflection === null) { throw new ShouldNotHappenException(); } if (!$traitReflection->isTrait()) { throw new ShouldNotHappenException(); } return new self($this->file, $this->classReflection, $traitReflection); } public function equals(self $otherContext) : bool { if ($this->file !== $otherContext->file) { return \false; } if ($this->getClassReflection() === null) { return $otherContext->getClassReflection() === null; } elseif ($otherContext->getClassReflection() === null) { return \false; } $isSameClass = $this->getClassReflection()->getName() === $otherContext->getClassReflection()->getName(); if ($this->getTraitReflection() === null) { return $otherContext->getTraitReflection() === null && $isSameClass; } elseif ($otherContext->getTraitReflection() === null) { return \false; } $isSameTrait = $this->getTraitReflection()->getName() === $otherContext->getTraitReflection()->getName(); return $isSameClass && $isSameTrait; } public function getFile() : string { return $this->file; } public function getClassReflection() : ?ClassReflection { return $this->classReflection; } public function getTraitReflection() : ?ClassReflection { return $this->traitReflection; } } |null */ private $nodeType; /** * @var ?string */ private $identifier; /** * @var mixed[] */ private $metadata; public const PATTERN_IDENTIFIER = '[a-zA-Z0-9](?:[a-zA-Z0-9\\.]*[a-zA-Z0-9])?'; /** * Error constructor. * * @param class-string|null $nodeType * @param mixed[] $metadata * @param bool|Throwable $canBeIgnored */ public function __construct(string $message, string $file, ?int $line = null, $canBeIgnored = \true, ?string $filePath = null, ?string $traitFilePath = null, ?string $tip = null, ?int $nodeLine = null, ?string $nodeType = null, ?string $identifier = null, array $metadata = []) { $this->message = $message; $this->file = $file; $this->line = $line; $this->canBeIgnored = $canBeIgnored; $this->filePath = $filePath; $this->traitFilePath = $traitFilePath; $this->tip = $tip; $this->nodeLine = $nodeLine; $this->nodeType = $nodeType; $this->identifier = $identifier; $this->metadata = $metadata; if ($this->identifier !== null && !self::validateIdentifier($this->identifier)) { throw new ShouldNotHappenException(sprintf('Invalid identifier: %s', $this->identifier)); } } public function getMessage() : string { return $this->message; } public function getFile() : string { return $this->file; } public function getFilePath() : string { if ($this->filePath === null) { return $this->file; } return $this->filePath; } public function changeFilePath(string $newFilePath) : self { if ($this->traitFilePath !== null) { throw new ShouldNotHappenException('Errors in traits not yet supported'); } return new self($this->message, $newFilePath, $this->line, $this->canBeIgnored, $newFilePath, null, $this->tip, $this->nodeLine, $this->nodeType, $this->identifier, $this->metadata); } public function changeTraitFilePath(string $newFilePath) : self { return new self($this->message, $this->file, $this->line, $this->canBeIgnored, $this->filePath, $newFilePath, $this->tip, $this->nodeLine, $this->nodeType, $this->identifier, $this->metadata); } public function getTraitFilePath() : ?string { return $this->traitFilePath; } public function getLine() : ?int { return $this->line; } public function canBeIgnored() : bool { return $this->canBeIgnored === \true; } public function hasNonIgnorableException() : bool { return $this->canBeIgnored instanceof Throwable; } public function getTip() : ?string { return $this->tip; } public function withoutTip() : self { if ($this->tip === null) { return $this; } return new self($this->message, $this->file, $this->line, $this->canBeIgnored, $this->filePath, $this->traitFilePath, null, $this->nodeLine, $this->nodeType); } public function doNotIgnore() : self { if (!$this->canBeIgnored()) { return $this; } return new self($this->message, $this->file, $this->line, \false, $this->filePath, $this->traitFilePath, $this->tip, $this->nodeLine, $this->nodeType); } public function withIdentifier(string $identifier) : self { if ($this->identifier !== null) { throw new ShouldNotHappenException(sprintf('Error already has an identifier: %s', $this->identifier)); } return new self($this->message, $this->file, $this->line, $this->canBeIgnored, $this->filePath, $this->traitFilePath, $this->tip, $this->nodeLine, $this->nodeType, $identifier, $this->metadata); } /** * @param mixed[] $metadata */ public function withMetadata(array $metadata) : self { if ($this->metadata !== []) { throw new ShouldNotHappenException('Error already has metadata'); } return new self($this->message, $this->file, $this->line, $this->canBeIgnored, $this->filePath, $this->traitFilePath, $this->tip, $this->nodeLine, $this->nodeType, $this->identifier, $metadata); } public function getNodeLine() : ?int { return $this->nodeLine; } /** * @return class-string|null */ public function getNodeType() : ?string { return $this->nodeType; } /** * Error identifier set via `RuleErrorBuilder::identifier()`. * * List of all current error identifiers in PHPStan: https://phpstan.org/error-identifiers */ public function getIdentifier() : ?string { return $this->identifier; } /** * @return mixed[] */ public function getMetadata() : array { return $this->metadata; } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['message' => $this->message, 'file' => $this->file, 'line' => $this->line, 'canBeIgnored' => is_bool($this->canBeIgnored) ? $this->canBeIgnored : 'exception', 'filePath' => $this->filePath, 'traitFilePath' => $this->traitFilePath, 'tip' => $this->tip, 'nodeLine' => $this->nodeLine, 'nodeType' => $this->nodeType, 'identifier' => $this->identifier, 'metadata' => $this->metadata]; } /** * @param mixed[] $json */ public static function decode(array $json) : self { return new self($json['message'], $json['file'], $json['line'], $json['canBeIgnored'] === 'exception' ? new Exception() : $json['canBeIgnored'], $json['filePath'], $json['traitFilePath'], $json['tip'], $json['nodeLine'] ?? null, $json['nodeType'] ?? null, $json['identifier'] ?? null, $json['metadata'] ?? []); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self($properties['message'], $properties['file'], $properties['line'], $properties['canBeIgnored'], $properties['filePath'], $properties['traitFilePath'], $properties['tip'], $properties['nodeLine'] ?? null, $properties['nodeType'] ?? null, $properties['identifier'] ?? null, $properties['metadata'] ?? []); } public static function validateIdentifier(string $identifier) : bool { return Strings::match($identifier, '~^' . self::PATTERN_IDENTIFIER . '$~') !== null; } } expr = $expr; $this->type = $type; $this->certainty = $certainty; } public static function createYes(Expr $expr, Type $type) : self { return new self($expr, $type, TrinaryLogic::createYes()); } public static function createMaybe(Expr $expr, Type $type) : self { return new self($expr, $type, TrinaryLogic::createMaybe()); } public function equals(self $other) : bool { if (!$this->certainty->equals($other->certainty)) { return \false; } return $this->type->equals($other->type); } public function and(self $other) : self { if ($this->getType()->equals($other->getType())) { $type = $this->getType(); } else { $type = TypeCombinator::union($this->getType(), $other->getType()); } return new self($this->expr, $type, $this->getCertainty()->and($other->getCertainty())); } public function getExpr() : Expr { return $this->expr; } public function getType() : Type { return $this->type; } public function getCertainty() : TrinaryLogic { return $this->certainty; } } internalScopeFactory = $internalScopeFactory; } public function create(\PHPStan\Analyser\ScopeContext $context) : \PHPStan\Analyser\MutatingScope { return $this->internalScopeFactory->create($context); } } getArgs(); if (count($args) < 1) { return null; } $passThruArgs = []; $callbackArg = null; foreach ($args as $i => $arg) { if ($callbackArg === null) { if ($arg->name === null && $i === 0) { $callbackArg = $arg; continue; } if ($arg->name !== null && $arg->name->toString() === 'callback') { $callbackArg = $arg; continue; } } $passThruArgs[] = $arg; } if ($callbackArg === null) { return null; } $calledOnType = $scope->getType($callbackArg->value); if (!$calledOnType->isCallable()->yes()) { return null; } $callableParametersAcceptors = $calledOnType->getCallableParametersAcceptors($scope); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $passThruArgs, $callableParametersAcceptors, null); $acceptsNamedArguments = \true; foreach ($callableParametersAcceptors as $callableParametersAcceptor) { $acceptsNamedArguments = $acceptsNamedArguments && $callableParametersAcceptor->acceptsNamedArguments(); } return [$parametersAcceptor, new FuncCall($callbackArg->value, $passThruArgs, $callUserFuncCall->getAttributes()), $acceptsNamedArguments]; } public static function reorderFuncArguments(ParametersAcceptor $parametersAcceptor, FuncCall $functionCall) : ?FuncCall { $reorderedArgs = self::reorderArgs($parametersAcceptor, $functionCall->getArgs()); if ($reorderedArgs === null) { return null; } return new FuncCall($functionCall->name, $reorderedArgs, $functionCall->getAttributes()); } public static function reorderMethodArguments(ParametersAcceptor $parametersAcceptor, MethodCall $methodCall) : ?MethodCall { $reorderedArgs = self::reorderArgs($parametersAcceptor, $methodCall->getArgs()); if ($reorderedArgs === null) { return null; } return new MethodCall($methodCall->var, $methodCall->name, $reorderedArgs, $methodCall->getAttributes()); } public static function reorderStaticCallArguments(ParametersAcceptor $parametersAcceptor, StaticCall $staticCall) : ?StaticCall { $reorderedArgs = self::reorderArgs($parametersAcceptor, $staticCall->getArgs()); if ($reorderedArgs === null) { return null; } return new StaticCall($staticCall->class, $staticCall->name, $reorderedArgs, $staticCall->getAttributes()); } public static function reorderNewArguments(ParametersAcceptor $parametersAcceptor, New_ $new) : ?New_ { $reorderedArgs = self::reorderArgs($parametersAcceptor, $new->getArgs()); if ($reorderedArgs === null) { return null; } return new New_($new->class, $reorderedArgs, $new->getAttributes()); } /** * @param Arg[] $callArgs * @return ?array */ public static function reorderArgs(ParametersAcceptor $parametersAcceptor, array $callArgs) : ?array { if (count($callArgs) === 0) { return []; } $signatureParameters = $parametersAcceptor->getParameters(); $hasNamedArgs = \false; foreach ($callArgs as $arg) { if ($arg->name !== null) { $hasNamedArgs = \true; break; } } if (!$hasNamedArgs) { return $callArgs; } $hasVariadic = \false; $argumentPositions = []; foreach ($signatureParameters as $i => $parameter) { if ($hasVariadic) { // variadic parameter must be last return null; } $hasVariadic = $parameter->isVariadic(); $argumentPositions[$parameter->getName()] = $i; } $reorderedArgs = []; $additionalNamedArgs = []; $appendArgs = []; foreach ($callArgs as $i => $arg) { if ($arg->name === null) { // add regular args as is $reorderedArgs[$i] = $arg; } elseif (array_key_exists($arg->name->toString(), $argumentPositions)) { $argName = $arg->name->toString(); // order named args into the position the signature expects them $attributes = $arg->getAttributes(); $attributes[self::ORIGINAL_ARG_ATTRIBUTE] = $arg; $reorderedArgs[$argumentPositions[$argName]] = new Arg($arg->value, $arg->byRef, $arg->unpack, $attributes, null); } else { if (!$hasVariadic) { $attributes = $arg->getAttributes(); $attributes[self::ORIGINAL_ARG_ATTRIBUTE] = $arg; $appendArgs[] = new Arg($arg->value, $arg->byRef, $arg->unpack, $attributes, null); continue; } $attributes = $arg->getAttributes(); $attributes[self::ORIGINAL_ARG_ATTRIBUTE] = $arg; $additionalNamedArgs[] = new Arg($arg->value, $arg->byRef, $arg->unpack, $attributes, null); } } // replace variadic parameter with additional named args, except if it is already set $additionalNamedArgsOffset = count($argumentPositions) - 1; if (array_key_exists($additionalNamedArgsOffset, $reorderedArgs)) { $additionalNamedArgsOffset++; } foreach ($additionalNamedArgs as $i => $additionalNamedArg) { $reorderedArgs[$additionalNamedArgsOffset + $i] = $additionalNamedArg; } if (count($reorderedArgs) === 0) { foreach ($appendArgs as $arg) { $reorderedArgs[] = $arg; } return $reorderedArgs; } // fill up all holes with default values until the last given argument for ($j = 0; $j < max(array_keys($reorderedArgs)); $j++) { if (array_key_exists($j, $reorderedArgs)) { continue; } if (!array_key_exists($j, $signatureParameters)) { throw new ShouldNotHappenException('Parameter signatures cannot have holes'); } $parameter = $signatureParameters[$j]; // we can only fill up optional parameters with default values if (!$parameter->isOptional()) { return null; } $defaultValue = $parameter->getDefaultValue(); if ($defaultValue === null) { if (!$parameter->isVariadic()) { throw new ShouldNotHappenException('An optional parameter must have a default value'); } $defaultValue = new ConstantArrayType([], []); } $reorderedArgs[$j] = new Arg(new TypeExpr($defaultValue)); } ksort($reorderedArgs); foreach ($appendArgs as $arg) { $reorderedArgs[] = $arg; } return $reorderedArgs; } } scope = $scope; $this->hasYield = $hasYield; $this->isAlwaysTerminating = $isAlwaysTerminating; $this->exitPoints = $exitPoints; $this->throwPoints = $throwPoints; $this->impurePoints = $impurePoints; $this->endStatements = $endStatements; } public function getScope() : \PHPStan\Analyser\MutatingScope { return $this->scope; } public function hasYield() : bool { return $this->hasYield; } public function isAlwaysTerminating() : bool { return $this->isAlwaysTerminating; } public function filterOutLoopExitPoints() : self { if (!$this->isAlwaysTerminating) { return $this; } foreach ($this->exitPoints as $exitPoint) { $statement = $exitPoint->getStatement(); if (!$statement instanceof Stmt\Break_ && !$statement instanceof Stmt\Continue_) { continue; } $num = $statement->num; if (!$num instanceof LNumber) { return new self($this->scope, $this->hasYield, \false, $this->exitPoints, $this->throwPoints, $this->impurePoints); } if ($num->value !== 1) { continue; } return new self($this->scope, $this->hasYield, \false, $this->exitPoints, $this->throwPoints, $this->impurePoints); } return $this; } /** * @return StatementExitPoint[] */ public function getExitPoints() : array { return $this->exitPoints; } /** * @param class-string|class-string $stmtClass * @return StatementExitPoint[] */ public function getExitPointsByType(string $stmtClass) : array { $exitPoints = []; foreach ($this->exitPoints as $exitPoint) { $statement = $exitPoint->getStatement(); if (!$statement instanceof $stmtClass) { continue; } $value = $statement->num; if ($value === null) { $exitPoints[] = $exitPoint; continue; } if (!$value instanceof LNumber) { $exitPoints[] = $exitPoint; continue; } $value = $value->value; if ($value !== 1) { continue; } $exitPoints[] = $exitPoint; } return $exitPoints; } /** * @return StatementExitPoint[] */ public function getExitPointsForOuterLoop() : array { $exitPoints = []; foreach ($this->exitPoints as $exitPoint) { $statement = $exitPoint->getStatement(); if (!$statement instanceof Stmt\Continue_ && !$statement instanceof Stmt\Break_) { $exitPoints[] = $exitPoint; continue; } if ($statement->num === null) { continue; } if (!$statement->num instanceof LNumber) { continue; } $value = $statement->num->value; if ($value === 1) { continue; } $newNode = null; if ($value > 2) { $newNode = new LNumber($value - 1); } if ($statement instanceof Stmt\Continue_) { $newStatement = new Stmt\Continue_($newNode); } else { $newStatement = new Stmt\Break_($newNode); } $exitPoints[] = new \PHPStan\Analyser\StatementExitPoint($newStatement, $exitPoint->getScope()); } return $exitPoints; } /** * @return ThrowPoint[] */ public function getThrowPoints() : array { return $this->throwPoints; } /** * @return ImpurePoint[] */ public function getImpurePoints() : array { return $this->impurePoints; } /** * Top-level StatementResult represents the state of the code * at the end of control flow statements like If_ or TryCatch. * * It shows how Scope etc. looks like after If_ no matter * which code branch was executed. * * For If_, "end statements" contain the state of the code * at the end of each branch - if, elseifs, else, including the last * statement node in each branch. * * For nested ifs, end statements try to contain the last non-control flow * statement like Return_ or Throw_, instead of If_, TryCatch, or Foreach_. * * @return EndStatementResult[] */ public function getEndStatements() : array { return $this->endStatements; } } */ private $collectorErrors; /** * @var list */ private $locallyIgnoredCollectorErrors; /** * @param list $collectorErrors * @param list $locallyIgnoredCollectorErrors */ public function __construct(\PHPStan\Analyser\AnalyserResult $analyserResult, array $collectorErrors, array $locallyIgnoredCollectorErrors) { $this->analyserResult = $analyserResult; $this->collectorErrors = $collectorErrors; $this->locallyIgnoredCollectorErrors = $locallyIgnoredCollectorErrors; } /** * @return list */ public function getErrors() : array { return $this->analyserResult->getErrors(); } public function getAnalyserResult() : \PHPStan\Analyser\AnalyserResult { return $this->analyserResult; } /** * @return list */ public function getCollectorErrors() : array { return $this->collectorErrors; } /** * @return list */ public function getLocallyIgnoredCollectorErrors() : array { return $this->locallyIgnoredCollectorErrors; } } scope = $scope; $this->node = $node; $this->identifier = $identifier; $this->description = $description; $this->certain = $certain; } public function getScope() : \PHPStan\Analyser\Scope { return $this->scope; } /** * @return Node\Expr|Node\Stmt|VirtualNode */ public function getNode() { return $this->node; } /** * @return ImpurePointIdentifier */ public function getIdentifier() : string { return $this->identifier; } public function getDescription() : string { return $this->description; } public function isCertain() : bool { return $this->certain; } } isPublic(); } public function canCallMethod(MethodReflection $methodReflection) : bool { return $methodReflection->isPublic(); } public function canAccessConstant(ConstantReflection $constantReflection) : bool { return $constantReflection->isPublic(); } } getTraitReflection() */ public function isInTrait() : bool; public function getTraitReflection() : ?ClassReflection; public function getFunction() : ?PhpFunctionFromParserNodeReflection; public function getFunctionName() : ?string; public function getParentScope() : ?self; public function hasVariableType(string $variableName) : TrinaryLogic; public function getVariableType(string $variableName) : Type; public function canAnyVariableExist() : bool; /** * @return array */ public function getDefinedVariables() : array; /** * @return array */ public function getMaybeDefinedVariables() : array; public function hasConstant(Name $name) : bool; public function getPropertyReflection(Type $typeWithProperty, string $propertyName) : ?ExtendedPropertyReflection; public function getMethodReflection(Type $typeWithMethod, string $methodName) : ?ExtendedMethodReflection; public function getConstantReflection(Type $typeWithConstant, string $constantName) : ?ConstantReflection; public function getIterableKeyType(Type $iteratee) : Type; public function getIterableValueType(Type $iteratee) : Type; public function isInAnonymousFunction() : bool; public function getAnonymousFunctionReflection() : ?ParametersAcceptor; public function getAnonymousFunctionReturnType() : ?Type; public function getType(Expr $node) : Type; public function getNativeType(Expr $expr) : Type; public function getKeepVoidType(Expr $node) : Type; /** * @deprecated Use getNativeType() */ public function doNotTreatPhpDocTypesAsCertain() : self; public function resolveName(Name $name) : string; public function resolveTypeByName(Name $name) : TypeWithClassName; /** * @param mixed $value */ public function getTypeFromValue($value) : Type; /** @deprecated use hasExpressionType instead */ public function isSpecified(Expr $node) : bool; public function hasExpressionType(Expr $node) : TrinaryLogic; public function isInClassExists(string $className) : bool; public function isInFunctionExists(string $functionName) : bool; public function isInClosureBind() : bool; /** @return list */ public function getFunctionCallStack() : array; /** @return list */ public function getFunctionCallStackWithParameters() : array; public function isParameterValueNullable(Param $parameter) : bool; /** * @param Node\Name|Node\Identifier|Node\ComplexType|null $type */ public function getFunctionType($type, bool $isNullable, bool $isVariadic) : Type; public function isInExpressionAssign(Expr $expr) : bool; public function isUndefinedExpressionAllowed(Expr $expr) : bool; public function filterByTruthyValue(Expr $expr) : self; public function filterByFalseyValue(Expr $expr) : self; public function isInFirstLevelStatement() : bool; } */ private $sureTypes; /** * @var array */ private $sureNotTypes; /** * @var bool */ private $overwrite; /** * @var array */ private $newConditionalExpressionHolders; /** * @var ?Expr */ private $rootExpr; /** * @api * @param array $sureTypes * @param array $sureNotTypes * @param array $newConditionalExpressionHolders */ public function __construct(array $sureTypes = [], array $sureNotTypes = [], bool $overwrite = \false, array $newConditionalExpressionHolders = [], ?Expr $rootExpr = null) { $this->sureTypes = $sureTypes; $this->sureNotTypes = $sureNotTypes; $this->overwrite = $overwrite; $this->newConditionalExpressionHolders = $newConditionalExpressionHolders; $this->rootExpr = $rootExpr; } /** * @api * @return array */ public function getSureTypes() : array { return $this->sureTypes; } /** * @api * @return array */ public function getSureNotTypes() : array { return $this->sureNotTypes; } public function shouldOverwrite() : bool { return $this->overwrite; } /** * @return array */ public function getNewConditionalExpressionHolders() : array { return $this->newConditionalExpressionHolders; } public function getRootExpr() : ?Expr { return $this->rootExpr; } /** @api */ public function intersectWith(\PHPStan\Analyser\SpecifiedTypes $other) : self { $sureTypeUnion = []; $sureNotTypeUnion = []; $rootExpr = $this->mergeRootExpr($this->rootExpr, $other->rootExpr); foreach ($this->sureTypes as $exprString => [$exprNode, $type]) { if (!isset($other->sureTypes[$exprString])) { continue; } $sureTypeUnion[$exprString] = [$exprNode, TypeCombinator::union($type, $other->sureTypes[$exprString][1])]; } foreach ($this->sureNotTypes as $exprString => [$exprNode, $type]) { if (!isset($other->sureNotTypes[$exprString])) { continue; } $sureNotTypeUnion[$exprString] = [$exprNode, TypeCombinator::intersect($type, $other->sureNotTypes[$exprString][1])]; } return new self($sureTypeUnion, $sureNotTypeUnion, $this->overwrite && $other->overwrite, [], $rootExpr); } /** @api */ public function unionWith(\PHPStan\Analyser\SpecifiedTypes $other) : self { $sureTypeUnion = $this->sureTypes + $other->sureTypes; $sureNotTypeUnion = $this->sureNotTypes + $other->sureNotTypes; $rootExpr = $this->mergeRootExpr($this->rootExpr, $other->rootExpr); foreach ($this->sureTypes as $exprString => [$exprNode, $type]) { if (!isset($other->sureTypes[$exprString])) { continue; } $sureTypeUnion[$exprString] = [$exprNode, TypeCombinator::intersect($type, $other->sureTypes[$exprString][1])]; } foreach ($this->sureNotTypes as $exprString => [$exprNode, $type]) { if (!isset($other->sureNotTypes[$exprString])) { continue; } $sureNotTypeUnion[$exprString] = [$exprNode, TypeCombinator::union($type, $other->sureNotTypes[$exprString][1])]; } return new self($sureTypeUnion, $sureNotTypeUnion, $this->overwrite || $other->overwrite, [], $rootExpr); } public function normalize(\PHPStan\Analyser\Scope $scope) : self { $sureTypes = $this->sureTypes; foreach ($this->sureNotTypes as $exprString => [$exprNode, $sureNotType]) { if (!isset($sureTypes[$exprString])) { $sureTypes[$exprString] = [$exprNode, TypeCombinator::remove($scope->getType($exprNode), $sureNotType)]; continue; } $sureTypes[$exprString][1] = TypeCombinator::remove($sureTypes[$exprString][1], $sureNotType); } return new self($sureTypes, [], $this->overwrite, $this->newConditionalExpressionHolders, $this->rootExpr); } private function mergeRootExpr(?Expr $rootExprA, ?Expr $rootExprB) : ?Expr { if ($rootExprA === $rootExprB) { return $rootExprA; } if ($rootExprA === null || $rootExprB === null) { return $rootExprA ?? $rootExprB; } return null; } } */ private $expressionTypes; /** * @var array */ private $nativeExpressionTypes; /** * @var array */ private $conditionalExpressions; /** * @var list */ private $inClosureBindScopeClasses; /** * @var ?ParametersAcceptor */ private $anonymousFunctionReflection; /** * @var bool */ private $inFirstLevelStatement; /** * @var array */ private $currentlyAssignedExpressions; /** * @var array */ private $currentlyAllowedUndefinedExpressions; /** * @var list */ private $inFunctionCallsStack; /** * @var bool */ private $afterExtractCall; /** * @var ?Scope */ private $parentScope; /** * @var bool */ private $nativeTypesPromoted; /** * @var bool */ private $explicitMixedInUnknownGenericNew; /** * @var bool */ private $explicitMixedForGlobalVariables; private const BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH = 4; private const KEEP_VOID_ATTRIBUTE_NAME = 'keepVoid'; /** @var Type[] */ private $resolvedTypes = []; /** @var array */ private $truthyScopes = []; /** @var array */ private $falseyScopes = []; /** @var non-empty-string|null */ private $namespace; /** * @var ?self */ private $scopeOutOfFirstLevelStatement = null; /** * @var ?self */ private $scopeWithPromotedNativeTypes = null; /** * @var int */ private static $resolveClosureTypeDepth = 0; /** * @param array $expressionTypes * @param array $conditionalExpressions * @param list $inClosureBindScopeClasses * @param array $currentlyAssignedExpressions * @param array $currentlyAllowedUndefinedExpressions * @param array $nativeExpressionTypes * @param list $inFunctionCallsStack * @param PhpFunctionFromParserNodeReflection|null $function */ public function __construct(\PHPStan\Analyser\InternalScopeFactory $scopeFactory, ReflectionProvider $reflectionProvider, InitializerExprTypeResolver $initializerExprTypeResolver, DynamicReturnTypeExtensionRegistry $dynamicReturnTypeExtensionRegistry, ExpressionTypeResolverExtensionRegistry $expressionTypeResolverExtensionRegistry, ExprPrinter $exprPrinter, \PHPStan\Analyser\TypeSpecifier $typeSpecifier, PropertyReflectionFinder $propertyReflectionFinder, Parser $parser, \PHPStan\Analyser\NodeScopeResolver $nodeScopeResolver, \PHPStan\Analyser\RicherScopeGetTypeHelper $richerScopeGetTypeHelper, \PHPStan\Analyser\ConstantResolver $constantResolver, \PHPStan\Analyser\ScopeContext $context, PhpVersion $phpVersion, bool $declareStrictTypes = \false, $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], array $conditionalExpressions = [], array $inClosureBindScopeClasses = [], ?ParametersAcceptor $anonymousFunctionReflection = null, bool $inFirstLevelStatement = \true, array $currentlyAssignedExpressions = [], array $currentlyAllowedUndefinedExpressions = [], array $inFunctionCallsStack = [], bool $afterExtractCall = \false, ?\PHPStan\Analyser\Scope $parentScope = null, bool $nativeTypesPromoted = \false, bool $explicitMixedInUnknownGenericNew = \false, bool $explicitMixedForGlobalVariables = \false) { $this->scopeFactory = $scopeFactory; $this->reflectionProvider = $reflectionProvider; $this->initializerExprTypeResolver = $initializerExprTypeResolver; $this->dynamicReturnTypeExtensionRegistry = $dynamicReturnTypeExtensionRegistry; $this->expressionTypeResolverExtensionRegistry = $expressionTypeResolverExtensionRegistry; $this->exprPrinter = $exprPrinter; $this->typeSpecifier = $typeSpecifier; $this->propertyReflectionFinder = $propertyReflectionFinder; $this->parser = $parser; $this->nodeScopeResolver = $nodeScopeResolver; $this->richerScopeGetTypeHelper = $richerScopeGetTypeHelper; $this->constantResolver = $constantResolver; $this->context = $context; $this->phpVersion = $phpVersion; $this->declareStrictTypes = $declareStrictTypes; $this->function = $function; $this->expressionTypes = $expressionTypes; $this->nativeExpressionTypes = $nativeExpressionTypes; $this->conditionalExpressions = $conditionalExpressions; $this->inClosureBindScopeClasses = $inClosureBindScopeClasses; $this->anonymousFunctionReflection = $anonymousFunctionReflection; $this->inFirstLevelStatement = $inFirstLevelStatement; $this->currentlyAssignedExpressions = $currentlyAssignedExpressions; $this->currentlyAllowedUndefinedExpressions = $currentlyAllowedUndefinedExpressions; $this->inFunctionCallsStack = $inFunctionCallsStack; $this->afterExtractCall = $afterExtractCall; $this->parentScope = $parentScope; $this->nativeTypesPromoted = $nativeTypesPromoted; $this->explicitMixedInUnknownGenericNew = $explicitMixedInUnknownGenericNew; $this->explicitMixedForGlobalVariables = $explicitMixedForGlobalVariables; if ($namespace === '') { $namespace = null; } $this->namespace = $namespace; } /** @api */ public function getFile() : string { return $this->context->getFile(); } /** @api */ public function getFileDescription() : string { if ($this->context->getTraitReflection() === null) { return $this->getFile(); } /** @var ClassReflection $classReflection */ $classReflection = $this->context->getClassReflection(); $className = $classReflection->getDisplayName(); if (!$classReflection->isAnonymous()) { $className = sprintf('class %s', $className); } $traitReflection = $this->context->getTraitReflection(); if ($traitReflection->getFileName() === null) { throw new ShouldNotHappenException(); } return sprintf('%s (in context of %s)', $traitReflection->getFileName(), $className); } /** @api */ public function isDeclareStrictTypes() : bool { return $this->declareStrictTypes; } public function enterDeclareStrictTypes() : self { return $this->scopeFactory->create($this->context, \true, null, null, $this->expressionTypes, $this->nativeExpressionTypes); } /** @api */ public function isInClass() : bool { return $this->context->getClassReflection() !== null; } /** @api */ public function isInTrait() : bool { return $this->context->getTraitReflection() !== null; } /** @api */ public function getClassReflection() : ?ClassReflection { return $this->context->getClassReflection(); } /** @api */ public function getTraitReflection() : ?ClassReflection { return $this->context->getTraitReflection(); } /** * @api */ public function getFunction() : ?PhpFunctionFromParserNodeReflection { return $this->function; } /** @api */ public function getFunctionName() : ?string { return $this->function !== null ? $this->function->getName() : null; } /** @api */ public function getNamespace() : ?string { return $this->namespace; } /** @api */ public function getParentScope() : ?\PHPStan\Analyser\Scope { return $this->parentScope; } /** @api */ public function canAnyVariableExist() : bool { return $this->function === null && !$this->isInAnonymousFunction() || $this->afterExtractCall; } public function afterExtractCall() : self { return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, [], $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->isInFirstLevelStatement(), $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $this->inFunctionCallsStack, \true, $this->parentScope, $this->nativeTypesPromoted); } public function afterClearstatcacheCall() : self { $expressionTypes = $this->expressionTypes; foreach (array_keys($expressionTypes) as $exprString) { // list from https://www.php.net/manual/en/function.clearstatcache.php // stat(), lstat(), file_exists(), is_writable(), is_readable(), is_executable(), is_file(), is_dir(), is_link(), filectime(), fileatime(), filemtime(), fileinode(), filegroup(), fileowner(), filesize(), filetype(), and fileperms(). foreach (['stat', 'lstat', 'file_exists', 'is_writable', 'is_writeable', 'is_readable', 'is_executable', 'is_file', 'is_dir', 'is_link', 'filectime', 'fileatime', 'filemtime', 'fileinode', 'filegroup', 'fileowner', 'filesize', 'filetype', 'fileperms'] as $functionName) { if (!str_starts_with($exprString, $functionName . '(') && !str_starts_with($exprString, '\\' . $functionName . '(')) { continue; } unset($expressionTypes[$exprString]); continue 2; } } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->isInFirstLevelStatement(), $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } public function afterOpenSslCall(string $openSslFunctionName) : self { $expressionTypes = $this->expressionTypes; if (in_array($openSslFunctionName, ['openssl_cipher_iv_length', 'openssl_cms_decrypt', 'openssl_cms_encrypt', 'openssl_cms_read', 'openssl_cms_sign', 'openssl_cms_verify', 'openssl_csr_export_to_file', 'openssl_csr_export', 'openssl_csr_get_public_key', 'openssl_csr_get_subject', 'openssl_csr_new', 'openssl_csr_sign', 'openssl_decrypt', 'openssl_dh_compute_key', 'openssl_digest', 'openssl_encrypt', 'openssl_get_curve_names', 'openssl_get_privatekey', 'openssl_get_publickey', 'openssl_open', 'openssl_pbkdf2', 'openssl_pkcs12_export_to_file', 'openssl_pkcs12_export', 'openssl_pkcs12_read', 'openssl_pkcs7_decrypt', 'openssl_pkcs7_encrypt', 'openssl_pkcs7_read', 'openssl_pkcs7_sign', 'openssl_pkcs7_verify', 'openssl_pkey_derive', 'openssl_pkey_export_to_file', 'openssl_pkey_export', 'openssl_pkey_get_private', 'openssl_pkey_get_public', 'openssl_pkey_new', 'openssl_private_decrypt', 'openssl_private_encrypt', 'openssl_public_decrypt', 'openssl_public_encrypt', 'openssl_random_pseudo_bytes', 'openssl_seal', 'openssl_sign', 'openssl_spki_export_challenge', 'openssl_spki_export', 'openssl_spki_new', 'openssl_spki_verify', 'openssl_verify', 'openssl_x509_checkpurpose', 'openssl_x509_export_to_file', 'openssl_x509_export', 'openssl_x509_fingerprint', 'openssl_x509_read', 'openssl_x509_verify'], \true)) { unset($expressionTypes['\\openssl_error_string()']); } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->isInFirstLevelStatement(), $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } /** @api */ public function hasVariableType(string $variableName) : TrinaryLogic { if ($this->isGlobalVariable($variableName)) { return TrinaryLogic::createYes(); } $varExprString = '$' . $variableName; if (!isset($this->expressionTypes[$varExprString])) { if ($this->canAnyVariableExist()) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); } return $this->expressionTypes[$varExprString]->getCertainty(); } /** @api */ public function getVariableType(string $variableName) : Type { if ($this->hasVariableType($variableName)->maybe()) { if ($variableName === 'argc') { return IntegerRangeType::fromInterval(1, null); } if ($variableName === 'argv') { return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(new ArrayType(new IntegerType(), new StringType()), new NonEmptyArrayType())); } if ($this->canAnyVariableExist()) { return new MixedType(); } } if ($this->isGlobalVariable($variableName)) { return new ArrayType(new BenevolentUnionType([new IntegerType(), new StringType()]), new MixedType($this->explicitMixedForGlobalVariables)); } if ($this->hasVariableType($variableName)->no()) { throw new \PHPStan\Analyser\UndefinedVariableException($this, $variableName); } $varExprString = '$' . $variableName; if (!array_key_exists($varExprString, $this->expressionTypes)) { return new MixedType(); } return TypeUtils::resolveLateResolvableTypes($this->expressionTypes[$varExprString]->getType()); } /** * @api * @return array */ public function getDefinedVariables() : array { $variables = []; foreach ($this->expressionTypes as $exprString => $holder) { if (!$holder->getExpr() instanceof Variable) { continue; } if (!$holder->getCertainty()->yes()) { continue; } $variables[] = substr($exprString, 1); } return $variables; } /** * @api * @return array */ public function getMaybeDefinedVariables() : array { $variables = []; foreach ($this->expressionTypes as $exprString => $holder) { if (!$holder->getExpr() instanceof Variable) { continue; } if (!$holder->getCertainty()->maybe()) { continue; } $variables[] = substr($exprString, 1); } return $variables; } private function isGlobalVariable(string $variableName) : bool { return in_array($variableName, self::SUPERGLOBAL_VARIABLES, \true); } /** @api */ public function hasConstant(Name $name) : bool { $isCompilerHaltOffset = $name->toString() === '__COMPILER_HALT_OFFSET__'; if ($isCompilerHaltOffset) { return $this->fileHasCompilerHaltStatementCalls(); } if (!$name->isFullyQualified() && $this->getNamespace() !== null) { if ($this->hasExpressionType(new ConstFetch(new FullyQualified([$this->getNamespace(), $name->toString()])))->yes()) { return \true; } } if ($this->hasExpressionType(new ConstFetch(new FullyQualified($name->toString())))->yes()) { return \true; } return $this->reflectionProvider->hasConstant($name, $this); } private function fileHasCompilerHaltStatementCalls() : bool { $nodes = $this->parser->parseFile($this->getFile()); foreach ($nodes as $node) { if ($node instanceof Node\Stmt\HaltCompiler) { return \true; } } return \false; } /** @api */ public function isInAnonymousFunction() : bool { return $this->anonymousFunctionReflection !== null; } /** @api */ public function getAnonymousFunctionReflection() : ?ParametersAcceptor { return $this->anonymousFunctionReflection; } /** @api */ public function getAnonymousFunctionReturnType() : ?Type { if ($this->anonymousFunctionReflection === null) { return null; } return $this->anonymousFunctionReflection->getReturnType(); } /** @api */ public function getType(Expr $node) : Type { if ($node instanceof GetIterableKeyTypeExpr) { return $this->getIterableKeyType($this->getType($node->getExpr())); } if ($node instanceof GetIterableValueTypeExpr) { return $this->getIterableValueType($this->getType($node->getExpr())); } if ($node instanceof GetOffsetValueTypeExpr) { return $this->getType($node->getVar())->getOffsetValueType($this->getType($node->getDim())); } if ($node instanceof ExistingArrayDimFetch) { return $this->getType(new Expr\ArrayDimFetch($node->getVar(), $node->getDim())); } if ($node instanceof UnsetOffsetExpr) { return $this->getType($node->getVar())->unsetOffset($this->getType($node->getDim())); } if ($node instanceof SetOffsetValueTypeExpr) { return $this->getType($node->getVar())->setOffsetValueType($node->getDim() !== null ? $this->getType($node->getDim()) : null, $this->getType($node->getValue())); } if ($node instanceof SetExistingOffsetValueTypeExpr) { return $this->getType($node->getVar())->setExistingOffsetValueType($this->getType($node->getDim()), $this->getType($node->getValue())); } if ($node instanceof TypeExpr) { return $node->getExprType(); } if ($node instanceof OriginalPropertyTypeExpr) { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($node->getPropertyFetch(), $this); if ($propertyReflection === null) { return new ErrorType(); } return $propertyReflection->getReadableType(); } $key = $this->getNodeKey($node); if (!array_key_exists($key, $this->resolvedTypes)) { $this->resolvedTypes[$key] = TypeUtils::resolveLateResolvableTypes($this->resolveType($key, $node)); } return $this->resolvedTypes[$key]; } private function getNodeKey(Expr $node) : string { $key = $this->exprPrinter->printExpr($node); $attributes = $node->getAttributes(); if ($node instanceof Node\FunctionLike && ($attributes[ArrayMapArgVisitor::ATTRIBUTE_NAME] ?? null) !== null && ($attributes['startFilePos'] ?? null) !== null) { $key .= '/*' . $attributes['startFilePos'] . '*/'; } if (($attributes[self::KEEP_VOID_ATTRIBUTE_NAME] ?? null) === \true) { $key .= '/*' . self::KEEP_VOID_ATTRIBUTE_NAME . '*/'; } return $key; } private function getClosureScopeCacheKey() : string { $parts = []; foreach ($this->expressionTypes as $exprString => $expressionTypeHolder) { $parts[] = sprintf('%s::%s', $exprString, $expressionTypeHolder->getType()->describe(VerbosityLevel::cache())); } $parts[] = '---'; foreach ($this->nativeExpressionTypes as $exprString => $expressionTypeHolder) { $parts[] = sprintf('%s::%s', $exprString, $expressionTypeHolder->getType()->describe(VerbosityLevel::cache())); } $parts[] = sprintf(':%d', count($this->inFunctionCallsStack)); foreach ($this->inFunctionCallsStack as [$method, $parameter]) { if ($parameter === null) { $parts[] = ',null'; continue; } $parts[] = sprintf(',%s', $parameter->getType()->describe(VerbosityLevel::cache())); } return md5(implode("\n", $parts)); } private function resolveType(string $exprString, Expr $node) : Type { foreach ($this->expressionTypeResolverExtensionRegistry->getExtensions() as $extension) { $type = $extension->getType($node, $this); if ($type !== null) { return $type; } } if ($node instanceof Expr\Exit_ || $node instanceof Expr\Throw_) { return new NonAcceptingNeverType(); } if (!$node instanceof Variable && $this->hasExpressionType($node)->yes()) { return $this->expressionTypes[$exprString]->getType(); } if ($node instanceof AlwaysRememberedExpr) { return $node->getExprType(); } if ($node instanceof Expr\BinaryOp\Smaller) { return $this->getType($node->left)->isSmallerThan($this->getType($node->right))->toBooleanType(); } if ($node instanceof Expr\BinaryOp\SmallerOrEqual) { return $this->getType($node->left)->isSmallerThanOrEqual($this->getType($node->right))->toBooleanType(); } if ($node instanceof Expr\BinaryOp\Greater) { return $this->getType($node->right)->isSmallerThan($this->getType($node->left))->toBooleanType(); } if ($node instanceof Expr\BinaryOp\GreaterOrEqual) { return $this->getType($node->right)->isSmallerThanOrEqual($this->getType($node->left))->toBooleanType(); } if ($node instanceof Expr\BinaryOp\Equal) { if ($node->left instanceof Variable && is_string($node->left->name) && $node->right instanceof Variable && is_string($node->right->name) && $node->left->name === $node->right->name) { return new ConstantBooleanType(\true); } $leftType = $this->getType($node->left); $rightType = $this->getType($node->right); return $this->initializerExprTypeResolver->resolveEqualType($leftType, $rightType)->type; } if ($node instanceof Expr\BinaryOp\NotEqual) { return $this->getType(new Expr\BooleanNot(new BinaryOp\Equal($node->left, $node->right))); } if ($node instanceof Expr\Empty_) { $result = $this->issetCheck($node->expr, static function (Type $type) : ?bool { $isNull = $type->isNull(); $isFalsey = $type->toBoolean()->isFalse(); if ($isNull->maybe()) { return null; } if ($isFalsey->maybe()) { return null; } if ($isNull->yes()) { return $isFalsey->no(); } return !$isFalsey->yes(); }); if ($result === null) { return new BooleanType(); } return new ConstantBooleanType(!$result); } if ($node instanceof Node\Expr\BooleanNot) { $exprBooleanType = $this->getType($node->expr)->toBoolean(); if ($exprBooleanType instanceof ConstantBooleanType) { return new ConstantBooleanType(!$exprBooleanType->getValue()); } return new BooleanType(); } if ($node instanceof Node\Expr\BitwiseNot) { return $this->initializerExprTypeResolver->getBitwiseNotType($node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Node\Expr\BinaryOp\BooleanAnd || $node instanceof Node\Expr\BinaryOp\LogicalAnd) { $leftBooleanType = $this->getType($node->left)->toBoolean(); if ($leftBooleanType->isFalse()->yes()) { return new ConstantBooleanType(\false); } if ($this->getBooleanExpressionDepth($node->left) <= self::BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH) { $noopCallback = static function () : void { }; $leftResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->left), $node->left, $this, $noopCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $rightBooleanType = $leftResult->getTruthyScope()->getType($node->right)->toBoolean(); } else { $rightBooleanType = $this->filterByTruthyValue($node->left)->getType($node->right)->toBoolean(); } if ($rightBooleanType->isFalse()->yes()) { return new ConstantBooleanType(\false); } if ($leftBooleanType->isTrue()->yes() && $rightBooleanType->isTrue()->yes()) { return new ConstantBooleanType(\true); } return new BooleanType(); } if ($node instanceof Node\Expr\BinaryOp\BooleanOr || $node instanceof Node\Expr\BinaryOp\LogicalOr) { $leftBooleanType = $this->getType($node->left)->toBoolean(); if ($leftBooleanType->isTrue()->yes()) { return new ConstantBooleanType(\true); } if ($this->getBooleanExpressionDepth($node->left) <= self::BOOLEAN_EXPRESSION_MAX_PROCESS_DEPTH) { $noopCallback = static function () : void { }; $leftResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->left), $node->left, $this, $noopCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); $rightBooleanType = $leftResult->getFalseyScope()->getType($node->right)->toBoolean(); } else { $rightBooleanType = $this->filterByFalseyValue($node->left)->getType($node->right)->toBoolean(); } if ($rightBooleanType->isTrue()->yes()) { return new ConstantBooleanType(\true); } if ($leftBooleanType->isFalse()->yes() && $rightBooleanType->isFalse()->yes()) { return new ConstantBooleanType(\false); } return new BooleanType(); } if ($node instanceof Node\Expr\BinaryOp\LogicalXor) { $leftBooleanType = $this->getType($node->left)->toBoolean(); $rightBooleanType = $this->getType($node->right)->toBoolean(); if ($leftBooleanType instanceof ConstantBooleanType && $rightBooleanType instanceof ConstantBooleanType) { return new ConstantBooleanType($leftBooleanType->getValue() xor $rightBooleanType->getValue()); } return new BooleanType(); } if ($node instanceof Expr\BinaryOp\Identical) { return $this->richerScopeGetTypeHelper->getIdenticalResult($this, $node)->type; } if ($node instanceof Expr\BinaryOp\NotIdentical) { return $this->richerScopeGetTypeHelper->getNotIdenticalResult($this, $node)->type; } if ($node instanceof Expr\Instanceof_) { $expressionType = $this->getType($node->expr); if ($this->isInTrait() && TypeUtils::findThisType($expressionType) !== null) { return new BooleanType(); } if ($expressionType instanceof NeverType) { return new ConstantBooleanType(\false); } $uncertainty = \false; if ($node->class instanceof Node\Name) { $unresolvedClassName = $node->class->toString(); if (strtolower($unresolvedClassName) === 'static' && $this->isInClass()) { $classType = new StaticType($this->getClassReflection()); } else { $className = $this->resolveName($node->class); $classType = new ObjectType($className); } } else { $classType = $this->getType($node->class); $classType = TypeTraverser::map($classType, static function (Type $type, callable $traverse) use(&$uncertainty) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type->getObjectClassNames() !== []) { $uncertainty = \true; return $type; } if ($type instanceof GenericClassStringType) { $uncertainty = \true; return $type->getGenericType(); } if ($type instanceof ConstantStringType) { return new ObjectType($type->getValue()); } return new MixedType(); }); } if ($classType->isSuperTypeOf(new MixedType())->yes()) { return new BooleanType(); } $isSuperType = $classType->isSuperTypeOf($expressionType); if ($isSuperType->no()) { return new ConstantBooleanType(\false); } elseif ($isSuperType->yes() && !$uncertainty) { return new ConstantBooleanType(\true); } return new BooleanType(); } if ($node instanceof Node\Expr\UnaryPlus) { return $this->getType($node->expr)->toNumber(); } if ($node instanceof Expr\ErrorSuppress || $node instanceof Expr\Assign) { return $this->getType($node->expr); } if ($node instanceof Node\Expr\UnaryMinus) { return $this->initializerExprTypeResolver->getUnaryMinusType($node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\BinaryOp\Concat) { return $this->initializerExprTypeResolver->getConcatType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\Concat) { return $this->initializerExprTypeResolver->getConcatType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\BitwiseAnd) { return $this->initializerExprTypeResolver->getBitwiseAndType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\BitwiseAnd) { return $this->initializerExprTypeResolver->getBitwiseAndType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\BitwiseOr) { return $this->initializerExprTypeResolver->getBitwiseOrType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\BitwiseOr) { return $this->initializerExprTypeResolver->getBitwiseOrType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\BitwiseXor) { return $this->initializerExprTypeResolver->getBitwiseXorType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\BitwiseXor) { return $this->initializerExprTypeResolver->getBitwiseXorType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\BinaryOp\Spaceship) { return $this->initializerExprTypeResolver->getSpaceshipType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\Div) { return $this->initializerExprTypeResolver->getDivType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\Div) { return $this->initializerExprTypeResolver->getDivType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\Mod) { return $this->initializerExprTypeResolver->getModType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\Mod) { return $this->initializerExprTypeResolver->getModType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\Plus) { return $this->initializerExprTypeResolver->getPlusType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\Plus) { return $this->initializerExprTypeResolver->getPlusType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\Minus) { return $this->initializerExprTypeResolver->getMinusType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\Minus) { return $this->initializerExprTypeResolver->getMinusType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\Mul) { return $this->initializerExprTypeResolver->getMulType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\Mul) { return $this->initializerExprTypeResolver->getMulType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\Pow) { return $this->initializerExprTypeResolver->getPowType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\Pow) { return $this->initializerExprTypeResolver->getPowType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\ShiftLeft) { return $this->initializerExprTypeResolver->getShiftLeftType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\ShiftLeft) { return $this->initializerExprTypeResolver->getShiftLeftType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof BinaryOp\ShiftRight) { return $this->initializerExprTypeResolver->getShiftRightType($node->left, $node->right, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\AssignOp\ShiftRight) { return $this->initializerExprTypeResolver->getShiftRightType($node->var, $node->expr, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\Clone_) { return $this->getType($node->expr); } if ($node instanceof LNumber) { return $this->initializerExprTypeResolver->getType($node, InitializerExprContext::fromScope($this)); } elseif ($node instanceof String_) { return $this->initializerExprTypeResolver->getType($node, InitializerExprContext::fromScope($this)); } elseif ($node instanceof Node\Scalar\Encapsed) { $resultType = null; foreach ($node->parts as $part) { $partType = $part instanceof EncapsedStringPart ? new ConstantStringType($part->value) : $this->getType($part)->toString(); if ($resultType === null) { $resultType = $partType; continue; } $resultType = $this->initializerExprTypeResolver->resolveConcatType($resultType, $partType); } return $resultType ?? new ConstantStringType(''); } elseif ($node instanceof DNumber) { return $this->initializerExprTypeResolver->getType($node, InitializerExprContext::fromScope($this)); } elseif ($node instanceof Expr\CallLike && $node->isFirstClassCallable()) { if ($node instanceof FuncCall) { if ($node->name instanceof Name) { if ($this->reflectionProvider->hasFunction($node->name, $this)) { $function = $this->reflectionProvider->getFunction($node->name, $this); return $this->createFirstClassCallable($function, $function->getVariants()); } return new ObjectType(Closure::class); } $callableType = $this->getType($node->name); if (!$callableType->isCallable()->yes()) { return new ObjectType(Closure::class); } return $this->createFirstClassCallable(null, $callableType->getCallableParametersAcceptors($this)); } if ($node instanceof MethodCall) { if (!$node->name instanceof Node\Identifier) { return new ObjectType(Closure::class); } $varType = $this->getType($node->var); $method = $this->getMethodReflection($varType, $node->name->toString()); if ($method === null) { return new ObjectType(Closure::class); } return $this->createFirstClassCallable($method, $method->getVariants()); } if ($node instanceof Expr\StaticCall) { if (!$node->class instanceof Name) { return new ObjectType(Closure::class); } if (!$node->name instanceof Node\Identifier) { return new ObjectType(Closure::class); } $classType = $this->resolveTypeByNameWithLateStaticBinding($node->class, $node->name); $methodName = $node->name->toString(); if (!$classType->hasMethod($methodName)->yes()) { return new ObjectType(Closure::class); } $method = $classType->getMethod($methodName, $this); return $this->createFirstClassCallable($method, $method->getVariants()); } if ($node instanceof New_) { return new ErrorType(); } throw new ShouldNotHappenException(); } elseif ($node instanceof Expr\Closure || $node instanceof Expr\ArrowFunction) { $parameters = []; $isVariadic = \false; $firstOptionalParameterIndex = null; foreach ($node->params as $i => $param) { $isOptionalCandidate = $param->default !== null || $param->variadic; if ($isOptionalCandidate) { if ($firstOptionalParameterIndex === null) { $firstOptionalParameterIndex = $i; } } else { $firstOptionalParameterIndex = null; } } foreach ($node->params as $i => $param) { if ($param->variadic) { $isVariadic = \true; } if (!$param->var instanceof Variable || !is_string($param->var->name)) { throw new ShouldNotHappenException(); } $parameters[] = new NativeParameterReflection($param->var->name, $firstOptionalParameterIndex !== null && $i >= $firstOptionalParameterIndex, $this->getFunctionType($param->type, $this->isParameterValueNullable($param), \false), $param->byRef ? PassedByReference::createCreatesNewVariable() : PassedByReference::createNo(), $param->variadic, $param->default !== null ? $this->getType($param->default) : null); } $callableParameters = null; $arrayMapArgs = $node->getAttribute(ArrayMapArgVisitor::ATTRIBUTE_NAME); if ($arrayMapArgs !== null) { $callableParameters = []; foreach ($arrayMapArgs as $funcCallArg) { $callableParameters[] = new DummyParameter('item', $this->getType($funcCallArg->value)->getIterableValueType(), \false, PassedByReference::createNo(), \false, null); } } else { $inFunctionCallsStackCount = count($this->inFunctionCallsStack); if ($inFunctionCallsStackCount > 0) { [, $inParameter] = $this->inFunctionCallsStack[$inFunctionCallsStackCount - 1]; if ($inParameter !== null) { $callableParameters = $this->nodeScopeResolver->createCallableParameters($this, $node, null, $inParameter->getType()); } } } if ($node instanceof Expr\ArrowFunction) { $arrowScope = $this->enterArrowFunctionWithoutReflection($node, $callableParameters); if ($node->expr instanceof Expr\Yield_ || $node->expr instanceof Expr\YieldFrom) { $yieldNode = $node->expr; if ($yieldNode instanceof Expr\Yield_) { if ($yieldNode->key === null) { $keyType = new IntegerType(); } else { $keyType = $arrowScope->getType($yieldNode->key); } if ($yieldNode->value === null) { $valueType = new NullType(); } else { $valueType = $arrowScope->getType($yieldNode->value); } } else { $yieldFromType = $arrowScope->getType($yieldNode->expr); $keyType = $arrowScope->getIterableKeyType($yieldFromType); $valueType = $arrowScope->getIterableValueType($yieldFromType); } $returnType = new GenericObjectType(Generator::class, [$keyType, $valueType, new MixedType(), new VoidType()]); } else { $returnType = $arrowScope->getKeepVoidType($node->expr); if ($node->returnType !== null) { $nativeReturnType = $this->getFunctionType($node->returnType, \false, \false); $returnType = self::intersectButNotNever($nativeReturnType, $returnType); } } $arrowFunctionImpurePoints = []; $invalidateExpressions = []; $arrowFunctionExprResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->expr), $node->expr, $arrowScope, static function (Node $node, \PHPStan\Analyser\Scope $scope) use($arrowScope, &$arrowFunctionImpurePoints, &$invalidateExpressions) : void { if ($scope->getAnonymousFunctionReflection() !== $arrowScope->getAnonymousFunctionReflection()) { return; } if ($node instanceof InvalidateExprNode) { $invalidateExpressions[] = $node; return; } if (!$node instanceof PropertyAssignNode) { return; } $arrowFunctionImpurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $node, 'propertyAssign', 'property assignment', \true); }, \PHPStan\Analyser\ExpressionContext::createDeep()); $throwPoints = $arrowFunctionExprResult->getThrowPoints(); $impurePoints = array_merge($arrowFunctionImpurePoints, $arrowFunctionExprResult->getImpurePoints()); $usedVariables = []; } else { $cachedTypes = $node->getAttribute('phpstanCachedTypes', []); $cacheKey = $this->getClosureScopeCacheKey(); if (array_key_exists($cacheKey, $cachedTypes)) { $cachedClosureData = $cachedTypes[$cacheKey]; return new ClosureType($parameters, $cachedClosureData['returnType'], $isVariadic, TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), TemplateTypeVarianceMap::createEmpty(), [], $cachedClosureData['throwPoints'], $cachedClosureData['impurePoints'], $cachedClosureData['invalidateExpressions'], $cachedClosureData['usedVariables'], \true); } if (self::$resolveClosureTypeDepth >= 2) { return new ClosureType($parameters, $this->getFunctionType($node->returnType, \false, \false), $isVariadic); } self::$resolveClosureTypeDepth++; $closureScope = $this->enterAnonymousFunctionWithoutReflection($node, $callableParameters); $closureReturnStatements = []; $closureYieldStatements = []; $onlyNeverExecutionEnds = null; $closureImpurePoints = []; $invalidateExpressions = []; try { $closureStatementResult = $this->nodeScopeResolver->processStmtNodes($node, $node->stmts, $closureScope, static function (Node $node, \PHPStan\Analyser\Scope $scope) use($closureScope, &$closureReturnStatements, &$closureYieldStatements, &$onlyNeverExecutionEnds, &$closureImpurePoints, &$invalidateExpressions) : void { if ($scope->getAnonymousFunctionReflection() !== $closureScope->getAnonymousFunctionReflection()) { return; } if ($node instanceof InvalidateExprNode) { $invalidateExpressions[] = $node; return; } if ($node instanceof PropertyAssignNode) { $closureImpurePoints[] = new \PHPStan\Analyser\ImpurePoint($scope, $node, 'propertyAssign', 'property assignment', \true); return; } if ($node instanceof ExecutionEndNode) { if ($node->getStatementResult()->isAlwaysTerminating()) { foreach ($node->getStatementResult()->getExitPoints() as $exitPoint) { if ($exitPoint->getStatement() instanceof Node\Stmt\Return_) { $onlyNeverExecutionEnds = \false; continue; } if ($onlyNeverExecutionEnds === null) { $onlyNeverExecutionEnds = \true; } break; } if (count($node->getStatementResult()->getExitPoints()) === 0) { if ($onlyNeverExecutionEnds === null) { $onlyNeverExecutionEnds = \true; } } } else { $onlyNeverExecutionEnds = \false; } return; } if ($node instanceof Node\Stmt\Return_) { $closureReturnStatements[] = [$node, $scope]; } if (!$node instanceof Expr\Yield_ && !$node instanceof Expr\YieldFrom) { return; } $closureYieldStatements[] = [$node, $scope]; }, \PHPStan\Analyser\StatementContext::createTopLevel()); } finally { self::$resolveClosureTypeDepth--; } $throwPoints = $closureStatementResult->getThrowPoints(); $impurePoints = array_merge($closureImpurePoints, $closureStatementResult->getImpurePoints()); $returnTypes = []; $hasNull = \false; foreach ($closureReturnStatements as [$returnNode, $returnScope]) { if ($returnNode->expr === null) { $hasNull = \true; continue; } $returnTypes[] = $returnScope->getType($returnNode->expr); } if (count($returnTypes) === 0) { if ($onlyNeverExecutionEnds === \true && !$hasNull) { $returnType = new NonAcceptingNeverType(); } else { $returnType = new VoidType(); } } else { if ($onlyNeverExecutionEnds === \true) { $returnTypes[] = new NonAcceptingNeverType(); } if ($hasNull) { $returnTypes[] = new NullType(); } $returnType = TypeCombinator::union(...$returnTypes); } if (count($closureYieldStatements) > 0) { $keyTypes = []; $valueTypes = []; foreach ($closureYieldStatements as [$yieldNode, $yieldScope]) { if ($yieldNode instanceof Expr\Yield_) { if ($yieldNode->key === null) { $keyTypes[] = new IntegerType(); } else { $keyTypes[] = $yieldScope->getType($yieldNode->key); } if ($yieldNode->value === null) { $valueTypes[] = new NullType(); } else { $valueTypes[] = $yieldScope->getType($yieldNode->value); } continue; } $yieldFromType = $yieldScope->getType($yieldNode->expr); $keyTypes[] = $yieldScope->getIterableKeyType($yieldFromType); $valueTypes[] = $yieldScope->getIterableValueType($yieldFromType); } $returnType = new GenericObjectType(Generator::class, [TypeCombinator::union(...$keyTypes), TypeCombinator::union(...$valueTypes), new MixedType(), $returnType]); } else { if ($node->returnType !== null) { $nativeReturnType = $this->getFunctionType($node->returnType, \false, \false); $returnType = self::intersectButNotNever($nativeReturnType, $returnType); } } $usedVariables = []; foreach ($node->uses as $use) { if (!is_string($use->var->name)) { continue; } $usedVariables[] = $use->var->name; } foreach ($node->uses as $use) { if (!$use->byRef) { continue; } $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($this, $node, 'functionCall', 'call to a Closure with by-ref use', \true); break; } } foreach ($parameters as $parameter) { if ($parameter->passedByReference()->no()) { continue; } $impurePoints[] = new \PHPStan\Analyser\ImpurePoint($this, $node, 'functionCall', 'call to a Closure with by-ref parameter', \true); } $throwPointsForClosureType = array_map(static function (\PHPStan\Analyser\ThrowPoint $throwPoint) { return $throwPoint->isExplicit() ? SimpleThrowPoint::createExplicit($throwPoint->getType(), $throwPoint->canContainAnyThrowable()) : SimpleThrowPoint::createImplicit(); }, $throwPoints); $impurePointsForClosureType = array_map(static function (\PHPStan\Analyser\ImpurePoint $impurePoint) { return new SimpleImpurePoint($impurePoint->getIdentifier(), $impurePoint->getDescription(), $impurePoint->isCertain()); }, $impurePoints); $cachedTypes = $node->getAttribute('phpstanCachedTypes', []); $cachedTypes[$this->getClosureScopeCacheKey()] = ['returnType' => $returnType, 'throwPoints' => $throwPointsForClosureType, 'impurePoints' => $impurePointsForClosureType, 'invalidateExpressions' => $invalidateExpressions, 'usedVariables' => $usedVariables]; $node->setAttribute('phpstanCachedTypes', $cachedTypes); return new ClosureType($parameters, $returnType, $isVariadic, TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), TemplateTypeVarianceMap::createEmpty(), [], $throwPointsForClosureType, $impurePointsForClosureType, $invalidateExpressions, $usedVariables, \true); } elseif ($node instanceof New_) { if ($node->class instanceof Name) { $type = $this->exactInstantiation($node, $node->class->toString()); if ($type !== null) { return $type; } $lowercasedClassName = strtolower($node->class->toString()); if ($lowercasedClassName === 'static') { if (!$this->isInClass()) { return new ErrorType(); } return new StaticType($this->getClassReflection()); } if ($lowercasedClassName === 'parent') { return new NonexistentParentClassType(); } return new ObjectType($node->class->toString()); } if ($node->class instanceof Node\Stmt\Class_) { $anonymousClassReflection = $this->reflectionProvider->getAnonymousClassReflection($node->class, $this); return new ObjectType($anonymousClassReflection->getName()); } $exprType = $this->getType($node->class); return $exprType->getObjectTypeOrClassStringObjectType(); } elseif ($node instanceof Array_) { return $this->initializerExprTypeResolver->getArrayType($node, function (Expr $expr) : Type { return $this->getType($expr); }); } elseif ($node instanceof Int_) { return $this->getType($node->expr)->toInteger(); } elseif ($node instanceof Bool_) { return $this->getType($node->expr)->toBoolean(); } elseif ($node instanceof Double) { return $this->getType($node->expr)->toFloat(); } elseif ($node instanceof Node\Expr\Cast\String_) { return $this->getType($node->expr)->toString(); } elseif ($node instanceof Node\Expr\Cast\Array_) { return $this->getType($node->expr)->toArray(); } elseif ($node instanceof Node\Scalar\MagicConst) { return $this->initializerExprTypeResolver->getType($node, InitializerExprContext::fromScope($this)); } elseif ($node instanceof Object_) { $castToObject = static function (Type $type) : Type { $constantArrays = $type->getConstantArrays(); if (count($constantArrays) > 0) { $objects = []; foreach ($constantArrays as $constantArray) { $properties = []; $optionalProperties = []; foreach ($constantArray->getKeyTypes() as $i => $keyType) { if (!$keyType instanceof ConstantStringType) { // an object with integer properties is >weird< continue; } $valueType = $constantArray->getValueTypes()[$i]; $optional = $constantArray->isOptionalKey($i); if ($optional) { $optionalProperties[] = $keyType->getValue(); } $properties[$keyType->getValue()] = $valueType; } $objects[] = TypeCombinator::intersect(new ObjectShapeType($properties, $optionalProperties), new ObjectType(stdClass::class)); } return TypeCombinator::union(...$objects); } if ($type->isObject()->yes()) { return $type; } return new ObjectType('stdClass'); }; $exprType = $this->getType($node->expr); if ($exprType instanceof UnionType) { return TypeCombinator::union(...array_map($castToObject, $exprType->getTypes())); } return $castToObject($exprType); } elseif ($node instanceof Unset_) { return new NullType(); } elseif ($node instanceof Expr\PostInc || $node instanceof Expr\PostDec) { return $this->getType($node->var); } elseif ($node instanceof Expr\PreInc || $node instanceof Expr\PreDec) { $varType = $this->getType($node->var); $varScalars = $varType->getConstantScalarValues(); if (count($varScalars) > 0) { $newTypes = []; foreach ($varScalars as $varValue) { if ($node instanceof Expr\PreInc) { if (!is_bool($varValue)) { ++$varValue; } } elseif (is_numeric($varValue)) { --$varValue; } $newTypes[] = $this->getTypeFromValue($varValue); } return TypeCombinator::union(...$newTypes); } elseif ($varType->isString()->yes()) { if ($varType->isLiteralString()->yes()) { return new IntersectionType([new StringType(), new AccessoryLiteralStringType()]); } if ($varType->isNumericString()->yes()) { return new BenevolentUnionType([new IntegerType(), new FloatType()]); } return new BenevolentUnionType([new StringType(), new IntegerType(), new FloatType()]); } if ($node instanceof Expr\PreInc) { return $this->getType(new BinaryOp\Plus($node->var, new LNumber(1))); } return $this->getType(new BinaryOp\Minus($node->var, new LNumber(1))); } elseif ($node instanceof Expr\Yield_) { $functionReflection = $this->getFunction(); if ($functionReflection === null) { return new MixedType(); } $returnType = $functionReflection->getReturnType(); $generatorSendType = $returnType->getTemplateType(Generator::class, 'TSend'); if ($generatorSendType instanceof ErrorType) { return new MixedType(); } return $generatorSendType; } elseif ($node instanceof Expr\YieldFrom) { $yieldFromType = $this->getType($node->expr); $generatorReturnType = $yieldFromType->getTemplateType(Generator::class, 'TReturn'); if ($generatorReturnType instanceof ErrorType) { return new MixedType(); } return $generatorReturnType; } elseif ($node instanceof Expr\Match_) { $cond = $node->cond; $condType = $this->getType($cond); $types = []; $matchScope = $this; $arms = $node->arms; if ($condType->isEnum()->yes()) { // enum match analysis would work even without this if branch // but would be much slower // this avoids using ObjectType::$subtractedType which is slow for huge enums // because of repeated union type normalization $enumCases = $condType->getEnumCases(); if (count($enumCases) > 0) { $indexedEnumCases = []; foreach ($enumCases as $enumCase) { $indexedEnumCases[strtolower($enumCase->getClassName())][$enumCase->getEnumCaseName()] = $enumCase; } $unusedIndexedEnumCases = $indexedEnumCases; foreach ($arms as $i => $arm) { if ($arm->conds === null) { continue; } $conditionCases = []; foreach ($arm->conds as $armCond) { if (!$armCond instanceof Expr\ClassConstFetch) { continue 2; } if (!$armCond->class instanceof Name) { continue 2; } if (!$armCond->name instanceof Node\Identifier) { continue 2; } $fetchedClassName = $this->resolveName($armCond->class); $loweredFetchedClassName = strtolower($fetchedClassName); if (!array_key_exists($loweredFetchedClassName, $indexedEnumCases)) { continue 2; } $caseName = $armCond->name->toString(); if (!array_key_exists($caseName, $indexedEnumCases[$loweredFetchedClassName])) { continue 2; } $conditionCases[] = $indexedEnumCases[$loweredFetchedClassName][$caseName]; unset($unusedIndexedEnumCases[$loweredFetchedClassName][$caseName]); } $conditionCasesCount = count($conditionCases); if ($conditionCasesCount === 0) { throw new ShouldNotHappenException(); } elseif ($conditionCasesCount === 1) { $conditionCaseType = $conditionCases[0]; } else { $conditionCaseType = new UnionType($conditionCases); } $types[] = $matchScope->addTypeToExpression($cond, $conditionCaseType)->getType($arm->body); unset($arms[$i]); } $remainingCases = []; foreach ($unusedIndexedEnumCases as $cases) { foreach ($cases as $case) { $remainingCases[] = $case; } } $remainingCasesCount = count($remainingCases); if ($remainingCasesCount === 0) { $remainingType = new NeverType(); } elseif ($remainingCasesCount === 1) { $remainingType = $remainingCases[0]; } else { $remainingType = new UnionType($remainingCases); } $matchScope = $matchScope->addTypeToExpression($cond, $remainingType); } } foreach ($arms as $arm) { if ($arm->conds === null) { if ($node->hasAttribute(self::KEEP_VOID_ATTRIBUTE_NAME)) { $arm->body->setAttribute(self::KEEP_VOID_ATTRIBUTE_NAME, $node->getAttribute(self::KEEP_VOID_ATTRIBUTE_NAME)); } $types[] = $matchScope->getType($arm->body); continue; } if (count($arm->conds) === 0) { throw new ShouldNotHappenException(); } if (count($arm->conds) === 1) { $filteringExpr = new BinaryOp\Identical($cond, $arm->conds[0]); } else { $items = []; foreach ($arm->conds as $filteringExpr) { $items[] = new Expr\ArrayItem($filteringExpr); } $filteringExpr = new FuncCall(new Name\FullyQualified('in_array'), [new Arg($cond), new Arg(new Array_($items)), new Arg(new ConstFetch(new Name\FullyQualified('true')))]); } $filteringExprType = $matchScope->getType($filteringExpr); if (!$filteringExprType->isFalse()->yes()) { $truthyScope = $matchScope->filterByTruthyValue($filteringExpr); if ($node->hasAttribute(self::KEEP_VOID_ATTRIBUTE_NAME)) { $arm->body->setAttribute(self::KEEP_VOID_ATTRIBUTE_NAME, $node->getAttribute(self::KEEP_VOID_ATTRIBUTE_NAME)); } $types[] = $truthyScope->getType($arm->body); } $matchScope = $matchScope->filterByFalseyValue($filteringExpr); } return TypeCombinator::union(...$types); } if ($node instanceof Expr\Isset_) { $issetResult = \true; foreach ($node->vars as $var) { $result = $this->issetCheck($var, static function (Type $type) : ?bool { $isNull = $type->isNull(); if ($isNull->maybe()) { return null; } return !$isNull->yes(); }); if ($result !== null) { if (!$result) { return new ConstantBooleanType($result); } continue; } $issetResult = $result; } if ($issetResult === null) { return new BooleanType(); } return new ConstantBooleanType($issetResult); } if ($node instanceof Expr\AssignOp\Coalesce) { return $this->getType(new BinaryOp\Coalesce($node->var, $node->expr, $node->getAttributes())); } if ($node instanceof Expr\BinaryOp\Coalesce) { $issetLeftExpr = new Expr\Isset_([$node->left]); $leftType = $this->filterByTruthyValue($issetLeftExpr)->getType($node->left); $result = $this->issetCheck($node->left, static function (Type $type) : ?bool { $isNull = $type->isNull(); if ($isNull->maybe()) { return null; } return !$isNull->yes(); }); if ($result !== null && $result !== \false) { return TypeCombinator::removeNull($leftType); } $rightType = $this->filterByFalseyValue($issetLeftExpr)->getType($node->right); if ($result === null) { return TypeCombinator::union(TypeCombinator::removeNull($leftType), $rightType); } return $rightType; } if ($node instanceof ConstFetch) { $constName = (string) $node->name; $loweredConstName = strtolower($constName); if ($loweredConstName === 'true') { return new ConstantBooleanType(\true); } elseif ($loweredConstName === 'false') { return new ConstantBooleanType(\false); } elseif ($loweredConstName === 'null') { return new NullType(); } $namespacedName = null; if (!$node->name->isFullyQualified() && $this->getNamespace() !== null) { $namespacedName = new FullyQualified([$this->getNamespace(), $node->name->toString()]); } $globalName = new FullyQualified($node->name->toString()); foreach ([$namespacedName, $globalName] as $name) { if ($name === null) { continue; } $constFetch = new ConstFetch($name); if ($this->hasExpressionType($constFetch)->yes()) { return $this->constantResolver->resolveConstantType($name->toString(), $this->expressionTypes[$this->getNodeKey($constFetch)]->getType()); } } $constantType = $this->constantResolver->resolveConstant($node->name, $this); if ($constantType !== null) { return $constantType; } return new ErrorType(); } elseif ($node instanceof Node\Expr\ClassConstFetch && $node->name instanceof Node\Identifier) { if ($this->hasExpressionType($node)->yes()) { return $this->expressionTypes[$exprString]->getType(); } return $this->initializerExprTypeResolver->getClassConstFetchTypeByReflection($node->class, $node->name->name, $this->isInClass() ? $this->getClassReflection() : null, function (Expr $expr) : Type { return $this->getType($expr); }); } if ($node instanceof Expr\Ternary) { $noopCallback = static function () : void { }; $condResult = $this->nodeScopeResolver->processExprNode(new Node\Stmt\Expression($node->cond), $node->cond, $this, $noopCallback, \PHPStan\Analyser\ExpressionContext::createDeep()); if ($node->if === null) { $conditionType = $this->getType($node->cond); $booleanConditionType = $conditionType->toBoolean(); if ($booleanConditionType->isTrue()->yes()) { return $condResult->getTruthyScope()->getType($node->cond); } if ($booleanConditionType->isFalse()->yes()) { return $condResult->getFalseyScope()->getType($node->else); } return TypeCombinator::union(TypeCombinator::removeFalsey($condResult->getTruthyScope()->getType($node->cond)), $condResult->getFalseyScope()->getType($node->else)); } $booleanConditionType = $this->getType($node->cond)->toBoolean(); if ($booleanConditionType->isTrue()->yes()) { return $condResult->getTruthyScope()->getType($node->if); } if ($booleanConditionType->isFalse()->yes()) { return $condResult->getFalseyScope()->getType($node->else); } return TypeCombinator::union($condResult->getTruthyScope()->getType($node->if), $condResult->getFalseyScope()->getType($node->else)); } if ($node instanceof Variable && is_string($node->name)) { if ($this->hasVariableType($node->name)->no()) { return new ErrorType(); } return $this->getVariableType($node->name); } if ($node instanceof Expr\ArrayDimFetch && $node->dim !== null) { return $this->getNullsafeShortCircuitingType($node->var, $this->getTypeFromArrayDimFetch($node, $this->getType($node->dim), $this->getType($node->var))); } if ($node instanceof MethodCall && $node->name instanceof Node\Identifier) { if ($this->nativeTypesPromoted) { $typeCallback = function () use($node) : Type { $methodReflection = $this->getMethodReflection($this->getNativeType($node->var), $node->name->name); if ($methodReflection === null) { return new ErrorType(); } return ParametersAcceptorSelector::combineAcceptors($methodReflection->getVariants())->getNativeReturnType(); }; return $this->getNullsafeShortCircuitingType($node->var, $typeCallback()); } $typeCallback = function () use($node) : Type { $returnType = $this->methodCallReturnType($this->getType($node->var), $node->name->name, $node); if ($returnType === null) { return new ErrorType(); } return $returnType; }; return $this->getNullsafeShortCircuitingType($node->var, $typeCallback()); } if ($node instanceof Expr\NullsafeMethodCall) { $varType = $this->getType($node->var); if ($varType->isNull()->yes()) { return new NullType(); } if (!TypeCombinator::containsNull($varType)) { return $this->getType(new MethodCall($node->var, $node->name, $node->args)); } return TypeCombinator::union($this->filterByTruthyValue(new BinaryOp\NotIdentical($node->var, new ConstFetch(new Name('null'))))->getType(new MethodCall($node->var, $node->name, $node->args)), new NullType()); } if ($node instanceof Expr\StaticCall && $node->name instanceof Node\Identifier) { if ($this->nativeTypesPromoted) { $typeCallback = function () use($node) : Type { if ($node->class instanceof Name) { $staticMethodCalledOnType = $this->resolveTypeByNameWithLateStaticBinding($node->class, $node->name); } else { $staticMethodCalledOnType = $this->getNativeType($node->class); } $methodReflection = $this->getMethodReflection($staticMethodCalledOnType, $node->name->name); if ($methodReflection === null) { return new ErrorType(); } return ParametersAcceptorSelector::combineAcceptors($methodReflection->getVariants())->getNativeReturnType(); }; $callType = $typeCallback(); if ($node->class instanceof Expr) { return $this->getNullsafeShortCircuitingType($node->class, $callType); } return $callType; } $typeCallback = function () use($node) : Type { if ($node->class instanceof Name) { $staticMethodCalledOnType = $this->resolveTypeByNameWithLateStaticBinding($node->class, $node->name); } else { $staticMethodCalledOnType = TypeCombinator::removeNull($this->getType($node->class))->getObjectTypeOrClassStringObjectType(); } $returnType = $this->methodCallReturnType($staticMethodCalledOnType, $node->name->toString(), $node); if ($returnType === null) { return new ErrorType(); } return $returnType; }; $callType = $typeCallback(); if ($node->class instanceof Expr) { return $this->getNullsafeShortCircuitingType($node->class, $callType); } return $callType; } if ($node instanceof PropertyFetch && $node->name instanceof Node\Identifier) { if ($this->nativeTypesPromoted) { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($node, $this); if ($propertyReflection === null) { return new ErrorType(); } $nativeType = $propertyReflection->getNativeType(); if ($nativeType === null) { return new ErrorType(); } return $this->getNullsafeShortCircuitingType($node->var, $nativeType); } $typeCallback = function () use($node) : Type { $returnType = $this->propertyFetchType($this->getType($node->var), $node->name->name, $node); if ($returnType === null) { return new ErrorType(); } return $returnType; }; return $this->getNullsafeShortCircuitingType($node->var, $typeCallback()); } if ($node instanceof Expr\NullsafePropertyFetch) { $varType = $this->getType($node->var); if ($varType->isNull()->yes()) { return new NullType(); } if (!TypeCombinator::containsNull($varType)) { return $this->getType(new PropertyFetch($node->var, $node->name)); } return TypeCombinator::union($this->filterByTruthyValue(new BinaryOp\NotIdentical($node->var, new ConstFetch(new Name('null'))))->getType(new PropertyFetch($node->var, $node->name)), new NullType()); } if ($node instanceof Expr\StaticPropertyFetch && $node->name instanceof Node\VarLikeIdentifier) { if ($this->nativeTypesPromoted) { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($node, $this); if ($propertyReflection === null) { return new ErrorType(); } $nativeType = $propertyReflection->getNativeType(); if ($nativeType === null) { return new ErrorType(); } if ($node->class instanceof Expr) { return $this->getNullsafeShortCircuitingType($node->class, $nativeType); } return $nativeType; } $typeCallback = function () use($node) : Type { if ($node->class instanceof Name) { $staticPropertyFetchedOnType = $this->resolveTypeByName($node->class); } else { $staticPropertyFetchedOnType = TypeCombinator::removeNull($this->getType($node->class))->getObjectTypeOrClassStringObjectType(); } $returnType = $this->propertyFetchType($staticPropertyFetchedOnType, $node->name->toString(), $node); if ($returnType === null) { return new ErrorType(); } return $returnType; }; $fetchType = $typeCallback(); if ($node->class instanceof Expr) { return $this->getNullsafeShortCircuitingType($node->class, $fetchType); } return $fetchType; } if ($node instanceof FuncCall) { if ($node->name instanceof Expr) { $calledOnType = $this->getType($node->name); if ($calledOnType->isCallable()->no()) { return new ErrorType(); } return ParametersAcceptorSelector::selectFromArgs($this, $node->getArgs(), $calledOnType->getCallableParametersAcceptors($this), null)->getReturnType(); } if (!$this->reflectionProvider->hasFunction($node->name, $this)) { return new ErrorType(); } $functionReflection = $this->reflectionProvider->getFunction($node->name, $this); if ($this->nativeTypesPromoted) { return ParametersAcceptorSelector::combineAcceptors($functionReflection->getVariants())->getNativeReturnType(); } if ($functionReflection->getName() === 'call_user_func') { $result = \PHPStan\Analyser\ArgumentsNormalizer::reorderCallUserFuncArguments($node, $this); if ($result !== null) { [, $innerFuncCall] = $result; return $this->getType($innerFuncCall); } } $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($this, $node->getArgs(), $functionReflection->getVariants(), $functionReflection->getNamedArgumentsVariants()); $normalizedNode = \PHPStan\Analyser\ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node); if ($normalizedNode !== null) { foreach ($this->dynamicReturnTypeExtensionRegistry->getDynamicFunctionReturnTypeExtensions() as $dynamicFunctionReturnTypeExtension) { if (!$dynamicFunctionReturnTypeExtension->isFunctionSupported($functionReflection)) { continue; } $resolvedType = $dynamicFunctionReturnTypeExtension->getTypeFromFunctionCall($functionReflection, $normalizedNode, $this); if ($resolvedType !== null) { return $resolvedType; } } } return $this->transformVoidToNull($parametersAcceptor->getReturnType(), $node); } return new MixedType(); } private function getNullsafeShortCircuitingType(Expr $expr, Type $type) : Type { if ($expr instanceof Expr\NullsafePropertyFetch || $expr instanceof Expr\NullsafeMethodCall) { $varType = $this->getType($expr->var); if (TypeCombinator::containsNull($varType)) { return TypeCombinator::addNull($type); } return $type; } if ($expr instanceof Expr\ArrayDimFetch) { return $this->getNullsafeShortCircuitingType($expr->var, $type); } if ($expr instanceof PropertyFetch) { return $this->getNullsafeShortCircuitingType($expr->var, $type); } if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) { return $this->getNullsafeShortCircuitingType($expr->class, $type); } if ($expr instanceof MethodCall) { return $this->getNullsafeShortCircuitingType($expr->var, $type); } if ($expr instanceof Expr\StaticCall && $expr->class instanceof Expr) { return $this->getNullsafeShortCircuitingType($expr->class, $type); } return $type; } private function transformVoidToNull(Type $type, Node $node) : Type { if ($node->getAttribute(self::KEEP_VOID_ATTRIBUTE_NAME) === \true) { return $type; } return TypeTraverser::map($type, static function (Type $type, callable $traverse) : Type { if ($type instanceof UnionType || $type instanceof IntersectionType) { return $traverse($type); } if ($type->isVoid()->yes()) { return new NullType(); } return $type; }); } /** * @param callable(Type): ?bool $typeCallback */ public function issetCheck(Expr $expr, callable $typeCallback, ?bool $result = null) : ?bool { // mirrored in PHPStan\Rules\IssetCheck if ($expr instanceof Node\Expr\Variable && is_string($expr->name)) { $hasVariable = $this->hasVariableType($expr->name); if ($hasVariable->maybe()) { return null; } if ($result === null) { if ($hasVariable->yes()) { if ($expr->name === '_SESSION') { return null; } return $typeCallback($this->getVariableType($expr->name)); } return \false; } return $result; } elseif ($expr instanceof Node\Expr\ArrayDimFetch && $expr->dim !== null) { $type = $this->getType($expr->var); if (!$type->isOffsetAccessible()->yes()) { return $result ?? $this->issetCheckUndefined($expr->var); } $dimType = $this->getType($expr->dim); $hasOffsetValue = $type->hasOffsetValueType($dimType); if ($hasOffsetValue->no()) { return \false; } // If offset cannot be null, store this error message and see if one of the earlier offsets is. // E.g. $array['a']['b']['c'] ?? null; is a valid coalesce if a OR b or C might be null. if ($hasOffsetValue->yes()) { $result = $typeCallback($type->getOffsetValueType($dimType)); if ($result !== null) { return $this->issetCheck($expr->var, $typeCallback, $result); } } // Has offset, it is nullable return null; } elseif ($expr instanceof Node\Expr\PropertyFetch || $expr instanceof Node\Expr\StaticPropertyFetch) { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $this); if ($propertyReflection === null) { if ($expr instanceof Node\Expr\PropertyFetch) { return $this->issetCheckUndefined($expr->var); } if ($expr->class instanceof Expr) { return $this->issetCheckUndefined($expr->class); } return null; } if (!$propertyReflection->isNative()) { if ($expr instanceof Node\Expr\PropertyFetch) { return $this->issetCheckUndefined($expr->var); } if ($expr->class instanceof Expr) { return $this->issetCheckUndefined($expr->class); } return null; } $nativeType = $propertyReflection->getNativeType(); if (!$nativeType instanceof MixedType) { if (!$this->hasExpressionType($expr)->yes()) { if ($expr instanceof Node\Expr\PropertyFetch) { return $this->issetCheckUndefined($expr->var); } if ($expr->class instanceof Expr) { return $this->issetCheckUndefined($expr->class); } return null; } } if ($result !== null) { return $result; } $result = $typeCallback($propertyReflection->getWritableType()); if ($result !== null) { if ($expr instanceof Node\Expr\PropertyFetch) { return $this->issetCheck($expr->var, $typeCallback, $result); } if ($expr->class instanceof Expr) { return $this->issetCheck($expr->class, $typeCallback, $result); } } return $result; } if ($result !== null) { return $result; } return $typeCallback($this->getType($expr)); } private function issetCheckUndefined(Expr $expr) : ?bool { if ($expr instanceof Node\Expr\Variable && is_string($expr->name)) { $hasVariable = $this->hasVariableType($expr->name); if (!$hasVariable->no()) { return null; } return \false; } if ($expr instanceof Node\Expr\ArrayDimFetch && $expr->dim !== null) { $type = $this->getType($expr->var); if (!$type->isOffsetAccessible()->yes()) { return $this->issetCheckUndefined($expr->var); } $dimType = $this->getType($expr->dim); $hasOffsetValue = $type->hasOffsetValueType($dimType); if (!$hasOffsetValue->no()) { return $this->issetCheckUndefined($expr->var); } return \false; } if ($expr instanceof Expr\PropertyFetch) { return $this->issetCheckUndefined($expr->var); } if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) { return $this->issetCheckUndefined($expr->class); } return null; } /** * @param ParametersAcceptor[] $variants * @param FunctionReflection|ExtendedMethodReflection|null $function */ private function createFirstClassCallable($function, array $variants) : Type { $closureTypes = []; foreach ($variants as $variant) { $returnType = $variant->getReturnType(); if ($variant instanceof ParametersAcceptorWithPhpDocs) { $returnType = $this->nativeTypesPromoted ? $variant->getNativeReturnType() : $returnType; } $templateTags = []; foreach ($variant->getTemplateTypeMap()->getTypes() as $templateType) { if (!$templateType instanceof TemplateType) { continue; } $templateTags[$templateType->getName()] = new TemplateTag($templateType->getName(), $templateType->getBound(), $templateType->getDefault(), $templateType->getVariance()); } $throwPoints = []; $impurePoints = []; $acceptsNamedArguments = \true; if ($variant instanceof CallableParametersAcceptor) { $throwPoints = $variant->getThrowPoints(); $impurePoints = $variant->getImpurePoints(); $acceptsNamedArguments = $variant->acceptsNamedArguments(); } elseif ($function !== null) { $returnTypeForThrow = $variant->getReturnType(); $throwType = $function->getThrowType(); if ($throwType === null) { if ($returnTypeForThrow instanceof NeverType && $returnTypeForThrow->isExplicit()) { $throwType = new ObjectType(Throwable::class); } } if ($throwType !== null) { if (!$throwType->isVoid()->yes()) { $throwPoints[] = SimpleThrowPoint::createExplicit($throwType, \true); } } else { if (!(new ObjectType(Throwable::class))->isSuperTypeOf($returnTypeForThrow)->yes()) { $throwPoints[] = SimpleThrowPoint::createImplicit(); } } $impurePoint = SimpleImpurePoint::createFromVariant($function, $variant); if ($impurePoint !== null) { $impurePoints[] = $impurePoint; } $acceptsNamedArguments = $function->acceptsNamedArguments(); } $parameters = $variant->getParameters(); $closureTypes[] = new ClosureType($parameters, $returnType, $variant->isVariadic(), $variant->getTemplateTypeMap(), $variant->getResolvedTemplateTypeMap(), $variant instanceof ParametersAcceptorWithPhpDocs ? $variant->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), $templateTags, $throwPoints, $impurePoints, [], [], $acceptsNamedArguments); } return TypeCombinator::union(...$closureTypes); } /** @api */ public function getNativeType(Expr $expr) : Type { return $this->promoteNativeTypes()->getType($expr); } public function getKeepVoidType(Expr $node) : Type { $clonedNode = clone $node; $clonedNode->setAttribute(self::KEEP_VOID_ATTRIBUTE_NAME, \true); return $this->getType($clonedNode); } /** * @api * @deprecated Use getNativeType() */ public function doNotTreatPhpDocTypesAsCertain() : \PHPStan\Analyser\Scope { return $this->promoteNativeTypes(); } private function promoteNativeTypes() : self { if ($this->nativeTypesPromoted) { return $this; } if ($this->scopeWithPromotedNativeTypes !== null) { return $this->scopeWithPromotedNativeTypes; } return $this->scopeWithPromotedNativeTypes = $this->scopeFactory->create($this->context, $this->declareStrictTypes, $this->function, $this->namespace, $this->nativeExpressionTypes, [], [], $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, \true); } /** * @param Node\Expr\PropertyFetch|Node\Expr\StaticPropertyFetch $propertyFetch */ public function hasPropertyNativeType($propertyFetch) : bool { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($propertyFetch, $this); if ($propertyReflection === null) { return \false; } if (!$propertyReflection->isNative()) { return \false; } return !$propertyReflection->getNativeType() instanceof MixedType; } /** @api */ protected function getTypeFromArrayDimFetch(Expr\ArrayDimFetch $arrayDimFetch, Type $offsetType, Type $offsetAccessibleType) : Type { if ($arrayDimFetch->dim === null) { throw new ShouldNotHappenException(); } if (!$offsetAccessibleType->isArray()->yes() && (new ObjectType(ArrayAccess::class))->isSuperTypeOf($offsetAccessibleType)->yes()) { return $this->getType(new MethodCall($arrayDimFetch->var, new Node\Identifier('offsetGet'), [new Node\Arg($arrayDimFetch->dim)])); } return $offsetAccessibleType->getOffsetValueType($offsetType); } private function resolveExactName(Name $name) : ?string { $originalClass = (string) $name; switch (strtolower($originalClass)) { case 'self': if (!$this->isInClass()) { return null; } return $this->getClassReflection()->getName(); case 'parent': if (!$this->isInClass()) { return null; } $currentClassReflection = $this->getClassReflection(); if ($currentClassReflection->getParentClass() !== null) { return $currentClassReflection->getParentClass()->getName(); } return null; case 'static': return null; } return $originalClass; } /** @api */ public function resolveName(Name $name) : string { $originalClass = (string) $name; if ($this->isInClass()) { $lowerClass = strtolower($originalClass); if (in_array($lowerClass, ['self', 'static'], \true)) { if ($this->inClosureBindScopeClasses !== [] && $this->inClosureBindScopeClasses !== ['static']) { return $this->inClosureBindScopeClasses[0]; } return $this->getClassReflection()->getName(); } elseif ($lowerClass === 'parent') { $currentClassReflection = $this->getClassReflection(); if ($currentClassReflection->getParentClass() !== null) { return $currentClassReflection->getParentClass()->getName(); } } } return $originalClass; } /** @api */ public function resolveTypeByName(Name $name) : TypeWithClassName { if ($name->toLowerString() === 'static' && $this->isInClass()) { if ($this->inClosureBindScopeClasses !== [] && $this->inClosureBindScopeClasses !== ['static']) { if ($this->reflectionProvider->hasClass($this->inClosureBindScopeClasses[0])) { return new StaticType($this->reflectionProvider->getClass($this->inClosureBindScopeClasses[0])); } } return new StaticType($this->getClassReflection()); } $originalClass = $this->resolveName($name); if ($this->isInClass()) { if ($this->inClosureBindScopeClasses === [$originalClass]) { if ($this->reflectionProvider->hasClass($originalClass)) { return new ThisType($this->reflectionProvider->getClass($originalClass)); } return new ObjectType($originalClass); } $thisType = new ThisType($this->getClassReflection()); $ancestor = $thisType->getAncestorWithClassName($originalClass); if ($ancestor !== null) { return $ancestor; } } return new ObjectType($originalClass); } private function resolveTypeByNameWithLateStaticBinding(Name $class, Node\Identifier $name) : TypeWithClassName { $classType = $this->resolveTypeByName($class); if ($classType instanceof StaticType && !in_array($class->toLowerString(), ['self', 'static', 'parent'], \true)) { $methodReflectionCandidate = $this->getMethodReflection($classType, $name->name); if ($methodReflectionCandidate !== null && $methodReflectionCandidate->isStatic()) { $classType = $classType->getStaticObjectType(); } } return $classType; } /** * @api * @param mixed $value */ public function getTypeFromValue($value) : Type { return ConstantTypeHelper::getTypeFromValue($value); } /** * @api * @deprecated use hasExpressionType instead */ public function isSpecified(Expr $node) : bool { return !$node instanceof Variable && $this->hasExpressionType($node)->yes(); } /** @api */ public function hasExpressionType(Expr $node) : TrinaryLogic { if ($node instanceof Variable && is_string($node->name)) { return $this->hasVariableType($node->name); } $exprString = $this->getNodeKey($node); if (!isset($this->expressionTypes[$exprString])) { return TrinaryLogic::createNo(); } return $this->expressionTypes[$exprString]->getCertainty(); } /** * @param MethodReflection|FunctionReflection|null $reflection */ public function pushInFunctionCall($reflection, ?ParameterReflection $parameter) : self { $stack = $this->inFunctionCallsStack; $stack[] = [$reflection, $parameter]; return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->isInFirstLevelStatement(), $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $stack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } public function popInFunctionCall() : self { $stack = $this->inFunctionCallsStack; array_pop($stack); return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->isInFirstLevelStatement(), $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $stack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } /** @api */ public function isInClassExists(string $className) : bool { foreach ($this->inFunctionCallsStack as [$inFunctionCall]) { if (!$inFunctionCall instanceof FunctionReflection) { continue; } if (in_array($inFunctionCall->getName(), ['class_exists', 'interface_exists', 'trait_exists'], \true)) { return \true; } } $expr = new FuncCall(new FullyQualified('class_exists'), [new Arg(new String_(ltrim($className, '\\')))]); return $this->getType($expr)->isTrue()->yes(); } public function getFunctionCallStack() : array { return array_values(array_filter(array_map(static function ($values) { return $values[0]; }, $this->inFunctionCallsStack), static function ($reflection) { return $reflection !== null; })); } public function getFunctionCallStackWithParameters() : array { return array_values(array_filter($this->inFunctionCallsStack, static function ($item) { return $item[0] !== null; })); } /** @api */ public function isInFunctionExists(string $functionName) : bool { $expr = new FuncCall(new FullyQualified('function_exists'), [new Arg(new String_(ltrim($functionName, '\\')))]); return $this->getType($expr)->isTrue()->yes(); } /** @api */ public function enterClass(ClassReflection $classReflection) : self { $thisHolder = \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable('this'), new ThisType($classReflection)); $constantTypes = $this->getConstantTypes(); $constantTypes['$this'] = $thisHolder; $nativeConstantTypes = $this->getNativeConstantTypes(); $nativeConstantTypes['$this'] = $thisHolder; return $this->scopeFactory->create($this->context->enterClass($classReflection), $this->isDeclareStrictTypes(), null, $this->getNamespace(), $constantTypes, $nativeConstantTypes, [], [], null, \true, [], [], [], \false, $classReflection->isAnonymous() ? $this : null); } public function enterTrait(ClassReflection $traitReflection) : self { $namespace = null; $traitName = $traitReflection->getName(); $traitNameParts = explode('\\', $traitName); if (count($traitNameParts) > 1) { $namespace = implode('\\', array_slice($traitNameParts, 0, -1)); } return $this->scopeFactory->create($this->context->enterTrait($traitReflection), $this->isDeclareStrictTypes(), $this->getFunction(), $namespace, $this->expressionTypes, $this->nativeExpressionTypes, [], $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection); } /** * @api * @param Type[] $phpDocParameterTypes * @param Type[] $parameterOutTypes * @param array $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters */ public function enterClassMethod(Node\Stmt\ClassMethod $classMethod, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $throwType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?bool $isPure = null, bool $acceptsNamedArguments = \true, ?Assertions $asserts = null, ?Type $selfOutType = null, ?string $phpDocComment = null, array $parameterOutTypes = [], array $immediatelyInvokedCallableParameters = [], array $phpDocClosureThisTypeParameters = [], bool $isConstructor = \false) : self { if (!$this->isInClass()) { throw new ShouldNotHappenException(); } return $this->enterFunctionLike(new PhpMethodFromParserNodeReflection($this->getClassReflection(), $classMethod, $this->getFile(), $templateTypeMap, $this->getRealParameterTypes($classMethod), array_map(function (Type $type) : Type { return $this->transformStaticType(TemplateTypeHelper::toArgument($type)); }, $phpDocParameterTypes), $this->getRealParameterDefaultValues($classMethod), $this->transformStaticType($this->getFunctionType($classMethod->returnType, \false, \false)), $phpDocReturnType !== null ? $this->transformStaticType(TemplateTypeHelper::toArgument($phpDocReturnType)) : null, $throwType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, $asserts ?? Assertions::createEmpty(), $selfOutType, $phpDocComment, array_map(function (Type $type) : Type { return $this->transformStaticType(TemplateTypeHelper::toArgument($type)); }, $parameterOutTypes), $immediatelyInvokedCallableParameters, array_map(function (Type $type) : Type { return $this->transformStaticType(TemplateTypeHelper::toArgument($type)); }, $phpDocClosureThisTypeParameters), $isConstructor), !$classMethod->isStatic()); } private function transformStaticType(Type $type) : Type { return TypeTraverser::map($type, function (Type $type, callable $traverse) : Type { if (!$this->isInClass()) { return $type; } if ($type instanceof StaticType) { $classReflection = $this->getClassReflection(); $changedType = $type->changeBaseClass($classReflection); if ($classReflection->isFinal() && !$type instanceof ThisType) { $changedType = $changedType->getStaticObjectType(); } return $traverse($changedType); } return $traverse($type); }); } /** * @return Type[] */ private function getRealParameterTypes(Node\FunctionLike $functionLike) : array { $realParameterTypes = []; foreach ($functionLike->getParams() as $parameter) { if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } $realParameterTypes[$parameter->var->name] = $this->getFunctionType($parameter->type, $this->isParameterValueNullable($parameter) && $parameter->flags === 0, \false); } return $realParameterTypes; } /** * @return Type[] */ private function getRealParameterDefaultValues(Node\FunctionLike $functionLike) : array { $realParameterDefaultValues = []; foreach ($functionLike->getParams() as $parameter) { if ($parameter->default === null) { continue; } if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } $realParameterDefaultValues[$parameter->var->name] = $this->getType($parameter->default); } return $realParameterDefaultValues; } /** * @api * @param Type[] $phpDocParameterTypes * @param Type[] $parameterOutTypes * @param array $immediatelyInvokedCallableParameters * @param array $phpDocClosureThisTypeParameters */ public function enterFunction(Node\Stmt\Function_ $function, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, ?Type $throwType, ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, bool $isFinal, ?bool $isPure = null, bool $acceptsNamedArguments = \true, ?Assertions $asserts = null, ?string $phpDocComment = null, array $parameterOutTypes = [], array $immediatelyInvokedCallableParameters = [], array $phpDocClosureThisTypeParameters = []) : self { return $this->enterFunctionLike(new PhpFunctionFromParserNodeReflection($function, $this->getFile(), $templateTypeMap, $this->getRealParameterTypes($function), array_map(static function (Type $type) : Type { return TemplateTypeHelper::toArgument($type); }, $phpDocParameterTypes), $this->getRealParameterDefaultValues($function), $this->getFunctionType($function->returnType, $function->returnType === null, \false), $phpDocReturnType !== null ? TemplateTypeHelper::toArgument($phpDocReturnType) : null, $throwType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, $asserts ?? Assertions::createEmpty(), $phpDocComment, array_map(static function (Type $type) : Type { return TemplateTypeHelper::toArgument($type); }, $parameterOutTypes), $immediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters), \false); } private function enterFunctionLike(PhpFunctionFromParserNodeReflection $functionReflection, bool $preserveThis) : self { $parametersByName = []; foreach ($functionReflection->getParameters() as $parameter) { $parametersByName[$parameter->getName()] = $parameter; } $expressionTypes = []; $nativeExpressionTypes = []; $conditionalTypes = []; foreach ($functionReflection->getParameters() as $parameter) { $parameterType = $parameter->getType(); if ($parameterType instanceof ConditionalTypeForParameter) { $targetParameterName = substr($parameterType->getParameterName(), 1); if (array_key_exists($targetParameterName, $parametersByName)) { $targetParameter = $parametersByName[$targetParameterName]; $ifType = $parameterType->isNegated() ? $parameterType->getElse() : $parameterType->getIf(); $elseType = $parameterType->isNegated() ? $parameterType->getIf() : $parameterType->getElse(); $holder = new \PHPStan\Analyser\ConditionalExpressionHolder([$parameterType->getParameterName() => \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($targetParameterName), TypeCombinator::intersect($targetParameter->getType(), $parameterType->getTarget()))], new \PHPStan\Analyser\ExpressionTypeHolder(new Variable($parameter->getName()), $ifType, TrinaryLogic::createYes())); $conditionalTypes['$' . $parameter->getName()][$holder->getKey()] = $holder; $holder = new \PHPStan\Analyser\ConditionalExpressionHolder([$parameterType->getParameterName() => \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable($targetParameterName), TypeCombinator::remove($targetParameter->getType(), $parameterType->getTarget()))], new \PHPStan\Analyser\ExpressionTypeHolder(new Variable($parameter->getName()), $elseType, TrinaryLogic::createYes())); $conditionalTypes['$' . $parameter->getName()][$holder->getKey()] = $holder; } } $paramExprString = '$' . $parameter->getName(); if ($parameter->isVariadic()) { if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()) { $parameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $parameterType); } else { $parameterType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $parameterType)); } } $parameterNode = new Variable($parameter->getName()); $expressionTypes[$paramExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($parameterNode, $parameterType); $parameterOriginalValueExpr = new ParameterVariableOriginalValueExpr($parameter->getName()); $parameterOriginalValueExprString = $this->getNodeKey($parameterOriginalValueExpr); $expressionTypes[$parameterOriginalValueExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($parameterOriginalValueExpr, $parameterType); $nativeParameterType = $parameter->getNativeType(); if ($parameter->isVariadic()) { if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()) { $nativeParameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $nativeParameterType); } else { $nativeParameterType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $nativeParameterType)); } } $nativeExpressionTypes[$paramExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($parameterNode, $nativeParameterType); $nativeExpressionTypes[$parameterOriginalValueExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($parameterOriginalValueExpr, $nativeParameterType); } if ($preserveThis && array_key_exists('$this', $this->expressionTypes)) { $expressionTypes['$this'] = $this->expressionTypes['$this']; } if ($preserveThis && array_key_exists('$this', $this->nativeExpressionTypes)) { $nativeExpressionTypes['$this'] = $this->nativeExpressionTypes['$this']; } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $functionReflection, $this->getNamespace(), array_merge($this->getConstantTypes(), $expressionTypes), array_merge($this->getNativeConstantTypes(), $nativeExpressionTypes), $conditionalTypes); } /** @api */ public function enterNamespace(string $namespaceName) : self { return $this->scopeFactory->create($this->context->beginFile(), $this->isDeclareStrictTypes(), null, $namespaceName); } /** * @param list $scopeClasses */ public function enterClosureBind(?Type $thisType, ?Type $nativeThisType, array $scopeClasses) : self { $expressionTypes = $this->expressionTypes; if ($thisType !== null) { $expressionTypes['$this'] = \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable('this'), $thisType); } else { unset($expressionTypes['$this']); } $nativeExpressionTypes = $this->nativeExpressionTypes; if ($nativeThisType !== null) { $nativeExpressionTypes['$this'] = \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable('this'), $nativeThisType); } else { unset($nativeExpressionTypes['$this']); } if ($scopeClasses === ['static'] && $this->isInClass()) { $scopeClasses = [$this->getClassReflection()->getName()]; } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $nativeExpressionTypes, $this->conditionalExpressions, $scopeClasses, $this->anonymousFunctionReflection); } public function restoreOriginalScopeAfterClosureBind(self $originalScope) : self { $expressionTypes = $this->expressionTypes; if (isset($originalScope->expressionTypes['$this'])) { $expressionTypes['$this'] = $originalScope->expressionTypes['$this']; } else { unset($expressionTypes['$this']); } $nativeExpressionTypes = $this->nativeExpressionTypes; if (isset($originalScope->nativeExpressionTypes['$this'])) { $nativeExpressionTypes['$this'] = $originalScope->nativeExpressionTypes['$this']; } else { unset($nativeExpressionTypes['$this']); } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $nativeExpressionTypes, $this->conditionalExpressions, $originalScope->inClosureBindScopeClasses, $this->anonymousFunctionReflection); } public function restoreThis(self $restoreThisScope) : self { $expressionTypes = $this->expressionTypes; $nativeExpressionTypes = $this->nativeExpressionTypes; if ($restoreThisScope->isInClass()) { $nodeFinder = new NodeFinder(); $cb = static function ($expr) { return $expr instanceof Variable && $expr->name === 'this'; }; foreach ($restoreThisScope->expressionTypes as $exprString => $expressionTypeHolder) { $expr = $expressionTypeHolder->getExpr(); $thisExpr = $nodeFinder->findFirst([$expr], $cb); if ($thisExpr === null) { continue; } $expressionTypes[$exprString] = $expressionTypeHolder; } foreach ($restoreThisScope->nativeExpressionTypes as $exprString => $expressionTypeHolder) { $expr = $expressionTypeHolder->getExpr(); $thisExpr = $nodeFinder->findFirst([$expr], $cb); if ($thisExpr === null) { continue; } $nativeExpressionTypes[$exprString] = $expressionTypeHolder; } } else { unset($expressionTypes['$this']); unset($nativeExpressionTypes['$this']); } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, [], [], $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } public function enterClosureCall(Type $thisType, Type $nativeThisType) : self { $expressionTypes = $this->expressionTypes; $expressionTypes['$this'] = \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable('this'), $thisType); $nativeExpressionTypes = $this->nativeExpressionTypes; $nativeExpressionTypes['$this'] = \PHPStan\Analyser\ExpressionTypeHolder::createYes(new Variable('this'), $nativeThisType); return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $nativeExpressionTypes, $this->conditionalExpressions, $thisType->getObjectClassNames(), $this->anonymousFunctionReflection); } /** @api */ public function isInClosureBind() : bool { return $this->inClosureBindScopeClasses !== []; } /** * @api * @param ParameterReflection[]|null $callableParameters */ public function enterAnonymousFunction(Expr\Closure $closure, ?array $callableParameters = null) : self { $anonymousFunctionReflection = $this->getType($closure); if (!$anonymousFunctionReflection instanceof ClosureType) { throw new ShouldNotHappenException(); } $scope = $this->enterAnonymousFunctionWithoutReflection($closure, $callableParameters); return $this->scopeFactory->create($scope->context, $scope->isDeclareStrictTypes(), $scope->getFunction(), $scope->getNamespace(), $scope->expressionTypes, $scope->nativeExpressionTypes, [], $scope->inClosureBindScopeClasses, $anonymousFunctionReflection, \true, [], [], $this->inFunctionCallsStack, \false, $this, $this->nativeTypesPromoted); } /** * @param ParameterReflection[]|null $callableParameters */ private function enterAnonymousFunctionWithoutReflection(Expr\Closure $closure, ?array $callableParameters = null) : self { $expressionTypes = []; $nativeTypes = []; foreach ($closure->params as $i => $parameter) { if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } $paramExprString = sprintf('$%s', $parameter->var->name); $isNullable = $this->isParameterValueNullable($parameter); $parameterType = $this->getFunctionType($parameter->type, $isNullable, $parameter->variadic); if ($callableParameters !== null) { if (isset($callableParameters[$i])) { $parameterType = self::intersectButNotNever($parameterType, $callableParameters[$i]->getType()); } elseif (count($callableParameters) > 0) { $lastParameter = $callableParameters[count($callableParameters) - 1]; if ($lastParameter->isVariadic()) { $parameterType = self::intersectButNotNever($parameterType, $lastParameter->getType()); } else { $parameterType = self::intersectButNotNever($parameterType, new MixedType()); } } else { $parameterType = self::intersectButNotNever($parameterType, new MixedType()); } } $holder = \PHPStan\Analyser\ExpressionTypeHolder::createYes($parameter->var, $parameterType); $expressionTypes[$paramExprString] = $holder; $nativeTypes[$paramExprString] = $holder; } $nonRefVariableNames = []; foreach ($closure->uses as $use) { if (!is_string($use->var->name)) { throw new ShouldNotHappenException(); } $variableName = $use->var->name; $paramExprString = '$' . $use->var->name; if ($use->byRef) { $holder = \PHPStan\Analyser\ExpressionTypeHolder::createYes($use->var, new MixedType()); $expressionTypes[$paramExprString] = $holder; $nativeTypes[$paramExprString] = $holder; continue; } $nonRefVariableNames[$variableName] = \true; if ($this->hasVariableType($variableName)->no()) { $variableType = new ErrorType(); $variableNativeType = new ErrorType(); } else { $variableType = $this->getVariableType($variableName); $variableNativeType = $this->getNativeType($use->var); } $expressionTypes[$paramExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($use->var, $variableType); $nativeTypes[$paramExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($use->var, $variableNativeType); } foreach ($this->invalidateStaticExpressions($this->expressionTypes) as $exprString => $typeHolder) { $expr = $typeHolder->getExpr(); if ($expr instanceof Variable) { continue; } $variables = (new NodeFinder())->findInstanceOf([$expr], Variable::class); if ($variables === [] && !$this->expressionTypeIsUnchangeable($typeHolder)) { continue; } foreach ($variables as $variable) { if (!$variable instanceof Variable) { continue 2; } if (!is_string($variable->name)) { continue 2; } if (!array_key_exists($variable->name, $nonRefVariableNames)) { continue 2; } } $expressionTypes[$exprString] = $typeHolder; } if ($this->hasVariableType('this')->yes() && !$closure->static) { $node = new Variable('this'); $expressionTypes['$this'] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($node, $this->getType($node)); $nativeTypes['$this'] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($node, $this->getNativeType($node)); } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), array_merge($this->getConstantTypes(), $expressionTypes), array_merge($this->getNativeConstantTypes(), $nativeTypes), [], $this->inClosureBindScopeClasses, new TrivialParametersAcceptor(), \true, [], [], [], \false, $this, $this->nativeTypesPromoted); } private function expressionTypeIsUnchangeable(\PHPStan\Analyser\ExpressionTypeHolder $typeHolder) : bool { $expr = $typeHolder->getExpr(); $type = $typeHolder->getType(); return $expr instanceof FuncCall && !$expr->isFirstClassCallable() && $expr->name instanceof FullyQualified && $expr->name->toLowerString() === 'function_exists' && isset($expr->getArgs()[0]) && count($this->getType($expr->getArgs()[0]->value)->getConstantStrings()) === 1 && $type->isTrue()->yes(); } /** * @param array $expressionTypes * @return array */ private function invalidateStaticExpressions(array $expressionTypes) : array { $filteredExpressionTypes = []; $nodeFinder = new NodeFinder(); foreach ($expressionTypes as $exprString => $expressionType) { $staticExpression = $nodeFinder->findFirst([$expressionType->getExpr()], static function ($node) { return $node instanceof Expr\StaticCall || $node instanceof Expr\StaticPropertyFetch; }); if ($staticExpression !== null) { continue; } $filteredExpressionTypes[$exprString] = $expressionType; } return $filteredExpressionTypes; } /** * @api * @param ParameterReflection[]|null $callableParameters */ public function enterArrowFunction(Expr\ArrowFunction $arrowFunction, ?array $callableParameters = null) : self { $anonymousFunctionReflection = $this->getType($arrowFunction); if (!$anonymousFunctionReflection instanceof ClosureType) { throw new ShouldNotHappenException(); } $scope = $this->enterArrowFunctionWithoutReflection($arrowFunction, $callableParameters); return $this->scopeFactory->create($scope->context, $scope->isDeclareStrictTypes(), $scope->getFunction(), $scope->getNamespace(), $scope->expressionTypes, $scope->nativeExpressionTypes, $scope->conditionalExpressions, $scope->inClosureBindScopeClasses, $anonymousFunctionReflection, \true, [], [], $this->inFunctionCallsStack, $scope->afterExtractCall, $scope->parentScope, $this->nativeTypesPromoted); } /** * @param ParameterReflection[]|null $callableParameters */ private function enterArrowFunctionWithoutReflection(Expr\ArrowFunction $arrowFunction, ?array $callableParameters) : self { $arrowFunctionScope = $this; foreach ($arrowFunction->params as $i => $parameter) { if ($parameter->type === null) { $parameterType = new MixedType(); } else { $isNullable = $this->isParameterValueNullable($parameter); $parameterType = $this->getFunctionType($parameter->type, $isNullable, $parameter->variadic); } if ($callableParameters !== null) { if (isset($callableParameters[$i])) { $parameterType = self::intersectButNotNever($parameterType, $callableParameters[$i]->getType()); } elseif (count($callableParameters) > 0) { $lastParameter = $callableParameters[count($callableParameters) - 1]; if ($lastParameter->isVariadic()) { $parameterType = self::intersectButNotNever($parameterType, $lastParameter->getType()); } else { $parameterType = self::intersectButNotNever($parameterType, new MixedType()); } } else { $parameterType = self::intersectButNotNever($parameterType, new MixedType()); } } if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } $arrowFunctionScope = $arrowFunctionScope->assignVariable($parameter->var->name, $parameterType, $parameterType); } if ($arrowFunction->static) { $arrowFunctionScope = $arrowFunctionScope->invalidateExpression(new Variable('this')); } return $this->scopeFactory->create($arrowFunctionScope->context, $this->isDeclareStrictTypes(), $arrowFunctionScope->getFunction(), $arrowFunctionScope->getNamespace(), $this->invalidateStaticExpressions($arrowFunctionScope->expressionTypes), $arrowFunctionScope->nativeExpressionTypes, $arrowFunctionScope->conditionalExpressions, $arrowFunctionScope->inClosureBindScopeClasses, new TrivialParametersAcceptor(), \true, [], [], [], $arrowFunctionScope->afterExtractCall, $arrowFunctionScope->parentScope, $this->nativeTypesPromoted); } public function isParameterValueNullable(Node\Param $parameter) : bool { if ($parameter->default instanceof ConstFetch) { return strtolower((string) $parameter->default->name) === 'null'; } return \false; } /** * @api * @param Node\Name|Node\Identifier|Node\ComplexType|null $type */ public function getFunctionType($type, bool $isNullable, bool $isVariadic) : Type { if ($isNullable) { return TypeCombinator::addNull($this->getFunctionType($type, \false, $isVariadic)); } if ($isVariadic) { if ($this->phpVersion->supportsNamedArguments()) { return new ArrayType(new UnionType([new IntegerType(), new StringType()]), $this->getFunctionType($type, \false, \false)); } return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $this->getFunctionType($type, \false, \false))); } if ($type instanceof Name) { $className = (string) $type; $lowercasedClassName = strtolower($className); if ($lowercasedClassName === 'parent') { if ($this->isInClass() && $this->getClassReflection()->getParentClass() !== null) { return new ObjectType($this->getClassReflection()->getParentClass()->getName()); } return new NonexistentParentClassType(); } } return ParserNodeTypeToPHPStanType::resolve($type, $this->isInClass() ? $this->getClassReflection() : null); } private static function intersectButNotNever(Type $nativeType, Type $inferredType) : Type { if ($nativeType->isSuperTypeOf($inferredType)->no()) { return $nativeType; } $result = TypeCombinator::intersect($nativeType, $inferredType); if (TypeCombinator::containsNull($nativeType)) { return TypeCombinator::addNull($result); } return $result; } public function enterMatch(Expr\Match_ $expr) : self { if ($expr->cond instanceof Variable) { return $this; } if ($expr->cond instanceof AlwaysRememberedExpr) { $cond = $expr->cond->expr; } else { $cond = $expr->cond; } $type = $this->getType($cond); $nativeType = $this->getNativeType($cond); $condExpr = new AlwaysRememberedExpr($cond, $type, $nativeType); $expr->cond = $condExpr; return $this->assignExpression($condExpr, $type, $nativeType); } public function enterForeach(self $originalScope, Expr $iteratee, string $valueName, ?string $keyName) : self { $iterateeType = $originalScope->getType($iteratee); $nativeIterateeType = $originalScope->getNativeType($iteratee); $scope = $this->assignVariable($valueName, $originalScope->getIterableValueType($iterateeType), $originalScope->getIterableValueType($nativeIterateeType)); if ($keyName !== null) { $scope = $scope->enterForeachKey($originalScope, $iteratee, $keyName); } return $scope; } public function enterForeachKey(self $originalScope, Expr $iteratee, string $keyName) : self { $iterateeType = $originalScope->getType($iteratee); $nativeIterateeType = $originalScope->getNativeType($iteratee); $scope = $this->assignVariable($keyName, $originalScope->getIterableKeyType($iterateeType), $originalScope->getIterableKeyType($nativeIterateeType)); if ($iterateeType->isArray()->yes()) { $scope = $scope->assignExpression(new Expr\ArrayDimFetch($iteratee, new Variable($keyName)), $originalScope->getIterableValueType($iterateeType), $originalScope->getIterableValueType($nativeIterateeType)); } return $scope; } /** * @deprecated Use enterCatchType * @param Node\Name[] $classes */ public function enterCatch(array $classes, ?string $variableName) : self { $type = TypeCombinator::union(...array_map(static function (Node\Name $class) : ObjectType { return new ObjectType((string) $class); }, $classes)); return $this->enterCatchType($type, $variableName); } public function enterCatchType(Type $catchType, ?string $variableName) : self { if ($variableName === null) { return $this; } return $this->assignVariable($variableName, TypeCombinator::intersect($catchType, new ObjectType(Throwable::class)), TypeCombinator::intersect($catchType, new ObjectType(Throwable::class))); } public function enterExpressionAssign(Expr $expr) : self { $exprString = $this->getNodeKey($expr); $currentlyAssignedExpressions = $this->currentlyAssignedExpressions; $currentlyAssignedExpressions[$exprString] = \true; $scope = $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->isInFirstLevelStatement(), $currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, [], $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); $scope->resolvedTypes = $this->resolvedTypes; $scope->truthyScopes = $this->truthyScopes; $scope->falseyScopes = $this->falseyScopes; return $scope; } public function exitExpressionAssign(Expr $expr) : self { $exprString = $this->getNodeKey($expr); $currentlyAssignedExpressions = $this->currentlyAssignedExpressions; unset($currentlyAssignedExpressions[$exprString]); $scope = $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->isInFirstLevelStatement(), $currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, [], $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); $scope->resolvedTypes = $this->resolvedTypes; $scope->truthyScopes = $this->truthyScopes; $scope->falseyScopes = $this->falseyScopes; return $scope; } /** @api */ public function isInExpressionAssign(Expr $expr) : bool { $exprString = $this->getNodeKey($expr); return array_key_exists($exprString, $this->currentlyAssignedExpressions); } public function setAllowedUndefinedExpression(Expr $expr) : self { if ($this->phpVersion->deprecatesDynamicProperties() && $expr instanceof Expr\StaticPropertyFetch) { return $this; } $exprString = $this->getNodeKey($expr); $currentlyAllowedUndefinedExpressions = $this->currentlyAllowedUndefinedExpressions; $currentlyAllowedUndefinedExpressions[$exprString] = \true; $scope = $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->isInFirstLevelStatement(), $this->currentlyAssignedExpressions, $currentlyAllowedUndefinedExpressions, [], $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); $scope->resolvedTypes = $this->resolvedTypes; $scope->truthyScopes = $this->truthyScopes; $scope->falseyScopes = $this->falseyScopes; return $scope; } public function unsetAllowedUndefinedExpression(Expr $expr) : self { $exprString = $this->getNodeKey($expr); $currentlyAllowedUndefinedExpressions = $this->currentlyAllowedUndefinedExpressions; unset($currentlyAllowedUndefinedExpressions[$exprString]); $scope = $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->isInFirstLevelStatement(), $this->currentlyAssignedExpressions, $currentlyAllowedUndefinedExpressions, [], $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); $scope->resolvedTypes = $this->resolvedTypes; $scope->truthyScopes = $this->truthyScopes; $scope->falseyScopes = $this->falseyScopes; return $scope; } /** @api */ public function isUndefinedExpressionAllowed(Expr $expr) : bool { $exprString = $this->getNodeKey($expr); return array_key_exists($exprString, $this->currentlyAllowedUndefinedExpressions); } public function assignVariable(string $variableName, Type $type, Type $nativeType, ?TrinaryLogic $certainty = null) : self { $node = new Variable($variableName); $scope = $this->assignExpression($node, $type, $nativeType); if ($certainty !== null) { if ($certainty->no()) { throw new ShouldNotHappenException(); } elseif (!$certainty->yes()) { $exprString = '$' . $variableName; $scope->expressionTypes[$exprString] = new \PHPStan\Analyser\ExpressionTypeHolder($node, $type, $certainty); $scope->nativeExpressionTypes[$exprString] = new \PHPStan\Analyser\ExpressionTypeHolder($node, $nativeType, $certainty); } } $parameterOriginalValueExprString = $this->getNodeKey(new ParameterVariableOriginalValueExpr($variableName)); unset($scope->expressionTypes[$parameterOriginalValueExprString]); unset($scope->nativeExpressionTypes[$parameterOriginalValueExprString]); return $scope; } public function unsetExpression(Expr $expr) : self { $scope = $this; if ($expr instanceof Expr\ArrayDimFetch && $expr->dim !== null) { $exprVarType = $scope->getType($expr->var); $dimType = $scope->getType($expr->dim); $unsetType = $exprVarType->unsetOffset($dimType); $exprVarNativeType = $scope->getNativeType($expr->var); $dimNativeType = $scope->getNativeType($expr->dim); $unsetNativeType = $exprVarNativeType->unsetOffset($dimNativeType); $scope = $scope->assignExpression($expr->var, $unsetType, $unsetNativeType)->invalidateExpression(new FuncCall(new FullyQualified('count'), [new Arg($expr->var)]))->invalidateExpression(new FuncCall(new FullyQualified('sizeof'), [new Arg($expr->var)]))->invalidateExpression(new FuncCall(new Name('count'), [new Arg($expr->var)]))->invalidateExpression(new FuncCall(new Name('sizeof'), [new Arg($expr->var)])); if ($expr->var instanceof Expr\ArrayDimFetch && $expr->var->dim !== null) { $scope = $scope->assignExpression($expr->var->var, $this->getType($expr->var->var)->setOffsetValueType($scope->getType($expr->var->dim), $scope->getType($expr->var)), $this->getNativeType($expr->var->var)->setOffsetValueType($scope->getNativeType($expr->var->dim), $scope->getNativeType($expr->var))); } } return $scope->invalidateExpression($expr); } public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType, ?TrinaryLogic $certainty = null) : self { if ($expr instanceof ConstFetch) { $loweredConstName = strtolower($expr->name->toString()); if (in_array($loweredConstName, ['true', 'false', 'null'], \true)) { return $this; } } if ($expr instanceof FuncCall && $expr->name instanceof Name && $type->isFalse()->yes()) { $functionName = $this->reflectionProvider->resolveFunctionName($expr->name, $this); if ($functionName !== null && in_array(strtolower($functionName), ['is_dir', 'is_file', 'file_exists'], \true)) { return $this; } } $scope = $this; if ($expr instanceof Expr\ArrayDimFetch && $expr->dim !== null) { $dimType = $scope->getType($expr->dim)->toArrayKey(); if ($dimType instanceof ConstantIntegerType || $dimType instanceof ConstantStringType) { $exprVarType = $scope->getType($expr->var); if (!$exprVarType instanceof MixedType && !$exprVarType->isArray()->no()) { $types = [new ArrayType(new MixedType(), new MixedType()), new ObjectType(ArrayAccess::class), new NullType()]; if ($dimType instanceof ConstantIntegerType) { $types[] = new StringType(); } $scope = $scope->specifyExpressionType($expr->var, TypeCombinator::intersect(TypeCombinator::intersect($exprVarType, TypeCombinator::union(...$types)), new HasOffsetValueType($dimType, $type)), $scope->getNativeType($expr->var), $certainty); } } } if ($certainty === null) { $certainty = TrinaryLogic::createYes(); } elseif ($certainty->no()) { throw new ShouldNotHappenException(); } $exprString = $this->getNodeKey($expr); $expressionTypes = $scope->expressionTypes; $expressionTypes[$exprString] = new \PHPStan\Analyser\ExpressionTypeHolder($expr, $type, $certainty); $nativeTypes = $scope->nativeExpressionTypes; $nativeTypes[$exprString] = new \PHPStan\Analyser\ExpressionTypeHolder($expr, $nativeType, $certainty); $scope = $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $nativeTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); if ($expr instanceof AlwaysRememberedExpr) { return $scope->specifyExpressionType($expr->expr, $type, $nativeType, $certainty); } return $scope; } public function assignExpression(Expr $expr, Type $type, ?Type $nativeType = null) : self { if ($nativeType === null) { $nativeType = new MixedType(); } $scope = $this; if ($expr instanceof PropertyFetch) { $scope = $this->invalidateExpression($expr)->invalidateMethodsOnExpression($expr->var); } elseif ($expr instanceof Expr\StaticPropertyFetch) { $scope = $this->invalidateExpression($expr); } elseif ($expr instanceof Variable) { $scope = $this->invalidateExpression($expr); } return $scope->specifyExpressionType($expr, $type, $nativeType); } public function assignInitializedProperty(Type $fetchedOnType, string $propertyName) : self { if (!$this->isInClass()) { return $this; } if (TypeUtils::findThisType($fetchedOnType) === null) { return $this; } $propertyReflection = $this->getPropertyReflection($fetchedOnType, $propertyName); if ($propertyReflection === null) { return $this; } $declaringClass = $propertyReflection->getDeclaringClass(); if ($this->getClassReflection()->getName() !== $declaringClass->getName()) { return $this; } if (!$declaringClass->hasNativeProperty($propertyName)) { return $this; } return $this->assignExpression(new PropertyInitializationExpr($propertyName), new MixedType(), new MixedType()); } public function invalidateExpression(Expr $expressionToInvalidate, bool $requireMoreCharacters = \false) : self { $expressionTypes = $this->expressionTypes; $nativeExpressionTypes = $this->nativeExpressionTypes; $invalidated = \false; $exprStringToInvalidate = $this->getNodeKey($expressionToInvalidate); foreach ($expressionTypes as $exprString => $exprTypeHolder) { $exprExpr = $exprTypeHolder->getExpr(); if (!$this->shouldInvalidateExpression($exprStringToInvalidate, $expressionToInvalidate, $exprExpr, $requireMoreCharacters)) { continue; } unset($expressionTypes[$exprString]); unset($nativeExpressionTypes[$exprString]); $invalidated = \true; } $newConditionalExpressions = []; foreach ($this->conditionalExpressions as $conditionalExprString => $holders) { if (count($holders) === 0) { continue; } if ($this->shouldInvalidateExpression($exprStringToInvalidate, $expressionToInvalidate, $holders[array_key_first($holders)]->getTypeHolder()->getExpr())) { $invalidated = \true; continue; } foreach ($holders as $holder) { $conditionalTypeHolders = $holder->getConditionExpressionTypeHolders(); foreach ($conditionalTypeHolders as $conditionalTypeHolder) { if ($this->shouldInvalidateExpression($exprStringToInvalidate, $expressionToInvalidate, $conditionalTypeHolder->getExpr())) { $invalidated = \true; continue 3; } } } $newConditionalExpressions[$conditionalExprString] = $holders; } if (!$invalidated) { return $this; } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $nativeExpressionTypes, $newConditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, [], $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } private function shouldInvalidateExpression(string $exprStringToInvalidate, Expr $exprToInvalidate, Expr $expr, bool $requireMoreCharacters = \false) : bool { if ($requireMoreCharacters && $exprStringToInvalidate === $this->getNodeKey($expr)) { return \false; } // Variables will not contain traversable expressions. skip the NodeFinder overhead if ($expr instanceof Variable && is_string($expr->name) && !$requireMoreCharacters) { return $exprStringToInvalidate === $this->getNodeKey($expr); } $nodeFinder = new NodeFinder(); $expressionToInvalidateClass = get_class($exprToInvalidate); $found = $nodeFinder->findFirst([$expr], function (Node $node) use($expressionToInvalidateClass, $exprStringToInvalidate) : bool { if (!$node instanceof $expressionToInvalidateClass) { return \false; } $nodeString = $this->getNodeKey($node); return $nodeString === $exprStringToInvalidate; }); if ($found === null) { return \false; } if ($this->phpVersion->supportsReadOnlyProperties() && $expr instanceof PropertyFetch && $expr->name instanceof Node\Identifier && $requireMoreCharacters) { $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $this); if ($propertyReflection !== null) { $nativePropertyReflection = $propertyReflection->getNativeReflection(); if ($nativePropertyReflection !== null && $nativePropertyReflection->isReadOnly()) { return \false; } } } return \true; } private function invalidateMethodsOnExpression(Expr $expressionToInvalidate) : self { $exprStringToInvalidate = $this->getNodeKey($expressionToInvalidate); $expressionTypes = $this->expressionTypes; $nativeExpressionTypes = $this->nativeExpressionTypes; $invalidated = \false; $nodeFinder = new NodeFinder(); foreach ($expressionTypes as $exprString => $exprTypeHolder) { $expr = $exprTypeHolder->getExpr(); $found = $nodeFinder->findFirst([$expr], function (Node $node) use($exprStringToInvalidate) : bool { if (!$node instanceof MethodCall) { return \false; } return $this->getNodeKey($node->var) === $exprStringToInvalidate; }); if ($found === null) { continue; } unset($expressionTypes[$exprString]); unset($nativeExpressionTypes[$exprString]); $invalidated = \true; } if (!$invalidated) { return $this; } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, [], $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } private function setExpressionCertainty(Expr $expr, TrinaryLogic $certainty) : self { if ($this->hasExpressionType($expr)->no()) { throw new ShouldNotHappenException(); } $originalExprType = $this->getType($expr); $nativeType = $this->getNativeType($expr); return $this->specifyExpressionType($expr, $originalExprType, $nativeType, $certainty); } public function addTypeToExpression(Expr $expr, Type $type) : self { $originalExprType = $this->getType($expr); $nativeType = $this->getNativeType($expr); if ($originalExprType->equals($nativeType)) { $newType = TypeCombinator::intersect($type, $originalExprType); return $this->specifyExpressionType($expr, $newType, $newType); } return $this->specifyExpressionType($expr, TypeCombinator::intersect($type, $originalExprType), TypeCombinator::intersect($type, $nativeType)); } public function removeTypeFromExpression(Expr $expr, Type $typeToRemove) : self { $exprType = $this->getType($expr); if ($exprType instanceof NeverType || $typeToRemove instanceof NeverType) { return $this; } return $this->specifyExpressionType($expr, TypeCombinator::remove($exprType, $typeToRemove), TypeCombinator::remove($this->getNativeType($expr), $typeToRemove)); } /** * @api * @return MutatingScope */ public function filterByTruthyValue(Expr $expr) : \PHPStan\Analyser\Scope { $exprString = $this->getNodeKey($expr); if (array_key_exists($exprString, $this->truthyScopes)) { return $this->truthyScopes[$exprString]; } $specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, \PHPStan\Analyser\TypeSpecifierContext::createTruthy()); $scope = $this->filterBySpecifiedTypes($specifiedTypes); $this->truthyScopes[$exprString] = $scope; return $scope; } /** * @api * @return MutatingScope */ public function filterByFalseyValue(Expr $expr) : \PHPStan\Analyser\Scope { $exprString = $this->getNodeKey($expr); if (array_key_exists($exprString, $this->falseyScopes)) { return $this->falseyScopes[$exprString]; } $specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, \PHPStan\Analyser\TypeSpecifierContext::createFalsey()); $scope = $this->filterBySpecifiedTypes($specifiedTypes); $this->falseyScopes[$exprString] = $scope; return $scope; } public function filterBySpecifiedTypes(\PHPStan\Analyser\SpecifiedTypes $specifiedTypes) : self { $typeSpecifications = []; foreach ($specifiedTypes->getSureTypes() as $exprString => [$expr, $type]) { if ($expr instanceof Node\Scalar || $expr instanceof Array_ || $expr instanceof Expr\UnaryMinus && $expr->expr instanceof Node\Scalar) { continue; } $typeSpecifications[] = ['sure' => \true, 'exprString' => (string) $exprString, 'expr' => $expr, 'type' => $type]; } foreach ($specifiedTypes->getSureNotTypes() as $exprString => [$expr, $type]) { if ($expr instanceof Node\Scalar || $expr instanceof Array_ || $expr instanceof Expr\UnaryMinus && $expr->expr instanceof Node\Scalar) { continue; } $typeSpecifications[] = ['sure' => \false, 'exprString' => (string) $exprString, 'expr' => $expr, 'type' => $type]; } usort($typeSpecifications, static function (array $a, array $b) : int { $length = strlen($a['exprString']) - strlen($b['exprString']); if ($length !== 0) { return $length; } return $b['sure'] - $a['sure']; // @phpstan-ignore minus.leftNonNumeric, minus.rightNonNumeric }); $scope = $this; $specifiedExpressions = []; foreach ($typeSpecifications as $typeSpecification) { $expr = $typeSpecification['expr']; $type = $typeSpecification['type']; if ($expr instanceof IssetExpr) { $issetExpr = $expr; $expr = $issetExpr->getExpr(); if ($typeSpecification['sure']) { $scope = $scope->setExpressionCertainty($expr, TrinaryLogic::createMaybe()); } else { $scope = $scope->unsetExpression($expr); } continue; } if ($typeSpecification['sure']) { if ($specifiedTypes->shouldOverwrite()) { $scope = $scope->assignExpression($expr, $type, $type); } else { $scope = $scope->addTypeToExpression($expr, $type); } } else { $scope = $scope->removeTypeFromExpression($expr, $type); } $specifiedExpressions[$this->getNodeKey($expr)] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($expr, $scope->getType($expr)); } $conditions = []; foreach ($scope->conditionalExpressions as $conditionalExprString => $conditionalExpressions) { foreach ($conditionalExpressions as $conditionalExpression) { foreach ($conditionalExpression->getConditionExpressionTypeHolders() as $holderExprString => $conditionalTypeHolder) { if (!array_key_exists($holderExprString, $specifiedExpressions) || !$specifiedExpressions[$holderExprString]->equals($conditionalTypeHolder)) { continue 2; } } $conditions[$conditionalExprString][] = $conditionalExpression; $specifiedExpressions[$conditionalExprString] = $conditionalExpression->getTypeHolder(); } } foreach ($conditions as $conditionalExprString => $expressions) { $certainty = TrinaryLogic::lazyExtremeIdentity($expressions, static function (\PHPStan\Analyser\ConditionalExpressionHolder $holder) { return $holder->getTypeHolder()->getCertainty(); }); if ($certainty->no()) { unset($scope->expressionTypes[$conditionalExprString]); } else { $type = TypeCombinator::intersect(...array_map(static function (\PHPStan\Analyser\ConditionalExpressionHolder $holder) { return $holder->getTypeHolder()->getType(); }, $expressions)); $scope->expressionTypes[$conditionalExprString] = array_key_exists($conditionalExprString, $scope->expressionTypes) ? new \PHPStan\Analyser\ExpressionTypeHolder($scope->expressionTypes[$conditionalExprString]->getExpr(), TypeCombinator::intersect($scope->expressionTypes[$conditionalExprString]->getType(), $type), TrinaryLogic::maxMin($scope->expressionTypes[$conditionalExprString]->getCertainty(), $certainty)) : $expressions[0]->getTypeHolder(); } } return $scope->scopeFactory->create($scope->context, $scope->isDeclareStrictTypes(), $scope->getFunction(), $scope->getNamespace(), $scope->expressionTypes, $scope->nativeExpressionTypes, array_merge($specifiedTypes->getNewConditionalExpressionHolders(), $scope->conditionalExpressions), $scope->inClosureBindScopeClasses, $scope->anonymousFunctionReflection, $scope->inFirstLevelStatement, $scope->currentlyAssignedExpressions, $scope->currentlyAllowedUndefinedExpressions, $scope->inFunctionCallsStack, $scope->afterExtractCall, $scope->parentScope, $scope->nativeTypesPromoted); } /** * @param ConditionalExpressionHolder[] $conditionalExpressionHolders */ public function addConditionalExpressions(string $exprString, array $conditionalExpressionHolders) : self { $conditionalExpressions = $this->conditionalExpressions; $conditionalExpressions[$exprString] = $conditionalExpressionHolders; return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, $conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } public function exitFirstLevelStatements() : self { if (!$this->inFirstLevelStatement) { return $this; } if ($this->scopeOutOfFirstLevelStatement !== null) { return $this->scopeOutOfFirstLevelStatement; } $scope = $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->expressionTypes, $this->nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, \false, $this->currentlyAssignedExpressions, $this->currentlyAllowedUndefinedExpressions, $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); $scope->resolvedTypes = $this->resolvedTypes; $scope->truthyScopes = $this->truthyScopes; $scope->falseyScopes = $this->falseyScopes; $this->scopeOutOfFirstLevelStatement = $scope; return $scope; } /** @api */ public function isInFirstLevelStatement() : bool { return $this->inFirstLevelStatement; } public function mergeWith(?self $otherScope) : self { if ($otherScope === null) { return $this; } $ourExpressionTypes = $this->expressionTypes; $theirExpressionTypes = $otherScope->expressionTypes; $mergedExpressionTypes = $this->mergeVariableHolders($ourExpressionTypes, $theirExpressionTypes); $conditionalExpressions = $this->intersectConditionalExpressions($otherScope->conditionalExpressions); $conditionalExpressions = $this->createConditionalExpressions($conditionalExpressions, $ourExpressionTypes, $theirExpressionTypes, $mergedExpressionTypes); $conditionalExpressions = $this->createConditionalExpressions($conditionalExpressions, $theirExpressionTypes, $ourExpressionTypes, $mergedExpressionTypes); return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $mergedExpressionTypes, $this->mergeVariableHolders($this->nativeExpressionTypes, $otherScope->nativeExpressionTypes), $conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, [], [], [], $this->afterExtractCall && $otherScope->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } /** * @param array $otherConditionalExpressions * @return array */ private function intersectConditionalExpressions(array $otherConditionalExpressions) : array { $newConditionalExpressions = []; foreach ($this->conditionalExpressions as $exprString => $holders) { if (!array_key_exists($exprString, $otherConditionalExpressions)) { continue; } $otherHolders = $otherConditionalExpressions[$exprString]; foreach (array_keys($holders) as $key) { if (!array_key_exists($key, $otherHolders)) { continue 2; } } $newConditionalExpressions[$exprString] = $holders; } return $newConditionalExpressions; } /** * @param array $conditionalExpressions * @param array $ourExpressionTypes * @param array $theirExpressionTypes * @param array $mergedExpressionTypes * @return array */ private function createConditionalExpressions(array $conditionalExpressions, array $ourExpressionTypes, array $theirExpressionTypes, array $mergedExpressionTypes) : array { $newVariableTypes = $ourExpressionTypes; foreach ($theirExpressionTypes as $exprString => $holder) { if (!array_key_exists($exprString, $mergedExpressionTypes)) { continue; } if (!$mergedExpressionTypes[$exprString]->getType()->equals($holder->getType())) { continue; } unset($newVariableTypes[$exprString]); } $typeGuards = []; foreach ($newVariableTypes as $exprString => $holder) { if (!$holder->getCertainty()->yes()) { continue; } if (!array_key_exists($exprString, $mergedExpressionTypes)) { continue; } if ($mergedExpressionTypes[$exprString]->getType()->equals($holder->getType())) { continue; } $typeGuards[$exprString] = $holder; } if (count($typeGuards) === 0) { return $conditionalExpressions; } foreach ($newVariableTypes as $exprString => $holder) { if (array_key_exists($exprString, $mergedExpressionTypes) && $mergedExpressionTypes[$exprString]->equals($holder)) { continue; } $variableTypeGuards = $typeGuards; unset($variableTypeGuards[$exprString]); if (count($variableTypeGuards) === 0) { continue; } $conditionalExpression = new \PHPStan\Analyser\ConditionalExpressionHolder($variableTypeGuards, $holder); $conditionalExpressions[$exprString][$conditionalExpression->getKey()] = $conditionalExpression; } foreach ($mergedExpressionTypes as $exprString => $mergedExprTypeHolder) { if (array_key_exists($exprString, $ourExpressionTypes)) { continue; } $conditionalExpression = new \PHPStan\Analyser\ConditionalExpressionHolder($typeGuards, new \PHPStan\Analyser\ExpressionTypeHolder($mergedExprTypeHolder->getExpr(), new ErrorType(), TrinaryLogic::createNo())); $conditionalExpressions[$exprString][$conditionalExpression->getKey()] = $conditionalExpression; } return $conditionalExpressions; } /** * @param array $ourVariableTypeHolders * @param array $theirVariableTypeHolders * @return array */ private function mergeVariableHolders(array $ourVariableTypeHolders, array $theirVariableTypeHolders) : array { $intersectedVariableTypeHolders = []; foreach ($ourVariableTypeHolders as $exprString => $variableTypeHolder) { if (isset($theirVariableTypeHolders[$exprString])) { $intersectedVariableTypeHolders[$exprString] = $variableTypeHolder->and($theirVariableTypeHolders[$exprString]); } else { $intersectedVariableTypeHolders[$exprString] = \PHPStan\Analyser\ExpressionTypeHolder::createMaybe($variableTypeHolder->getExpr(), $variableTypeHolder->getType()); } } foreach ($theirVariableTypeHolders as $exprString => $variableTypeHolder) { if (isset($intersectedVariableTypeHolders[$exprString])) { continue; } $intersectedVariableTypeHolders[$exprString] = \PHPStan\Analyser\ExpressionTypeHolder::createMaybe($variableTypeHolder->getExpr(), $variableTypeHolder->getType()); } return $intersectedVariableTypeHolders; } public function mergeInitializedProperties(self $calledMethodScope) : self { $scope = $this; foreach ($calledMethodScope->expressionTypes as $exprString => $typeHolder) { $exprString = (string) $exprString; if (!str_starts_with($exprString, '__phpstanPropertyInitialization(')) { continue; } $propertyName = substr($exprString, strlen('__phpstanPropertyInitialization('), -1); $propertyExpr = new PropertyInitializationExpr($propertyName); if (!array_key_exists($exprString, $scope->expressionTypes)) { $scope = $scope->assignExpression($propertyExpr, new MixedType(), new MixedType()); $scope->expressionTypes[$exprString] = $typeHolder; continue; } $certainty = $scope->expressionTypes[$exprString]->getCertainty(); $scope = $scope->assignExpression($propertyExpr, new MixedType(), new MixedType()); $scope->expressionTypes[$exprString] = new \PHPStan\Analyser\ExpressionTypeHolder($typeHolder->getExpr(), $typeHolder->getType(), $typeHolder->getCertainty()->or($certainty)); } return $scope; } public function processFinallyScope(self $finallyScope, self $originalFinallyScope) : self { return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $this->processFinallyScopeVariableTypeHolders($this->expressionTypes, $finallyScope->expressionTypes, $originalFinallyScope->expressionTypes), $this->processFinallyScopeVariableTypeHolders($this->nativeExpressionTypes, $finallyScope->nativeExpressionTypes, $originalFinallyScope->nativeExpressionTypes), $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, [], [], [], $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } /** * @param array $ourVariableTypeHolders * @param array $finallyVariableTypeHolders * @param array $originalVariableTypeHolders * @return array */ private function processFinallyScopeVariableTypeHolders(array $ourVariableTypeHolders, array $finallyVariableTypeHolders, array $originalVariableTypeHolders) : array { foreach ($finallyVariableTypeHolders as $exprString => $variableTypeHolder) { if (isset($originalVariableTypeHolders[$exprString]) && !$originalVariableTypeHolders[$exprString]->getType()->equals($variableTypeHolder->getType())) { $ourVariableTypeHolders[$exprString] = $variableTypeHolder; continue; } if (isset($originalVariableTypeHolders[$exprString])) { continue; } $ourVariableTypeHolders[$exprString] = $variableTypeHolder; } return $ourVariableTypeHolders; } /** * @param Expr\ClosureUse[] $byRefUses */ public function processClosureScope(self $closureScope, ?self $prevScope, array $byRefUses) : self { $nativeExpressionTypes = $this->nativeExpressionTypes; $expressionTypes = $this->expressionTypes; if (count($byRefUses) === 0) { return $this; } foreach ($byRefUses as $use) { if (!is_string($use->var->name)) { throw new ShouldNotHappenException(); } $variableName = $use->var->name; $variableExprString = '$' . $variableName; if (!$closureScope->hasVariableType($variableName)->yes()) { $holder = \PHPStan\Analyser\ExpressionTypeHolder::createYes($use->var, new NullType()); $expressionTypes[$variableExprString] = $holder; $nativeExpressionTypes[$variableExprString] = $holder; continue; } $variableType = $closureScope->getVariableType($variableName); if ($prevScope !== null) { $prevVariableType = $prevScope->getVariableType($variableName); if (!$variableType->equals($prevVariableType)) { $variableType = TypeCombinator::union($variableType, $prevVariableType); $variableType = self::generalizeType($variableType, $prevVariableType, 0); } } $expressionTypes[$variableExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($use->var, $variableType); $nativeExpressionTypes[$variableExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createYes($use->var, $variableType); } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $nativeExpressionTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, [], [], $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } public function processAlwaysIterableForeachScopeWithoutPollute(self $finalScope) : self { $expressionTypes = $this->expressionTypes; foreach ($finalScope->expressionTypes as $variableExprString => $variableTypeHolder) { if (!isset($expressionTypes[$variableExprString])) { $expressionTypes[$variableExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createMaybe($variableTypeHolder->getExpr(), $variableTypeHolder->getType()); continue; } $expressionTypes[$variableExprString] = new \PHPStan\Analyser\ExpressionTypeHolder($variableTypeHolder->getExpr(), $variableTypeHolder->getType(), $variableTypeHolder->getCertainty()->and($expressionTypes[$variableExprString]->getCertainty())); } $nativeTypes = $this->nativeExpressionTypes; foreach ($finalScope->nativeExpressionTypes as $variableExprString => $variableTypeHolder) { if (!isset($nativeTypes[$variableExprString])) { $nativeTypes[$variableExprString] = \PHPStan\Analyser\ExpressionTypeHolder::createMaybe($variableTypeHolder->getExpr(), $variableTypeHolder->getType()); continue; } $nativeTypes[$variableExprString] = new \PHPStan\Analyser\ExpressionTypeHolder($variableTypeHolder->getExpr(), $variableTypeHolder->getType(), $variableTypeHolder->getCertainty()->and($nativeTypes[$variableExprString]->getCertainty())); } return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $expressionTypes, $nativeTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, [], [], [], $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } public function generalizeWith(self $otherScope) : self { $variableTypeHolders = $this->generalizeVariableTypeHolders($this->expressionTypes, $otherScope->expressionTypes); $nativeTypes = $this->generalizeVariableTypeHolders($this->nativeExpressionTypes, $otherScope->nativeExpressionTypes); return $this->scopeFactory->create($this->context, $this->isDeclareStrictTypes(), $this->getFunction(), $this->getNamespace(), $variableTypeHolders, $nativeTypes, $this->conditionalExpressions, $this->inClosureBindScopeClasses, $this->anonymousFunctionReflection, $this->inFirstLevelStatement, [], [], [], $this->afterExtractCall, $this->parentScope, $this->nativeTypesPromoted); } /** * @param array $variableTypeHolders * @param array $otherVariableTypeHolders * @return array */ private function generalizeVariableTypeHolders(array $variableTypeHolders, array $otherVariableTypeHolders) : array { foreach ($variableTypeHolders as $variableExprString => $variableTypeHolder) { if (!isset($otherVariableTypeHolders[$variableExprString])) { continue; } $variableTypeHolders[$variableExprString] = new \PHPStan\Analyser\ExpressionTypeHolder($variableTypeHolder->getExpr(), self::generalizeType($variableTypeHolder->getType(), $otherVariableTypeHolders[$variableExprString]->getType(), 0), $variableTypeHolder->getCertainty()); } return $variableTypeHolders; } private static function generalizeType(Type $a, Type $b, int $depth) : Type { if ($a->equals($b)) { return $a; } $constantIntegers = ['a' => [], 'b' => []]; $constantFloats = ['a' => [], 'b' => []]; $constantBooleans = ['a' => [], 'b' => []]; $constantStrings = ['a' => [], 'b' => []]; $constantArrays = ['a' => [], 'b' => []]; $generalArrays = ['a' => [], 'b' => []]; $integerRanges = ['a' => [], 'b' => []]; $otherTypes = []; foreach (['a' => TypeUtils::flattenTypes($a), 'b' => TypeUtils::flattenTypes($b)] as $key => $types) { foreach ($types as $type) { if ($type instanceof ConstantIntegerType) { $constantIntegers[$key][] = $type; continue; } if ($type instanceof ConstantFloatType) { $constantFloats[$key][] = $type; continue; } if ($type instanceof ConstantBooleanType) { $constantBooleans[$key][] = $type; continue; } if ($type instanceof ConstantStringType) { $constantStrings[$key][] = $type; continue; } if ($type->isConstantArray()->yes()) { $constantArrays[$key][] = $type; continue; } if ($type->isArray()->yes()) { $generalArrays[$key][] = $type; continue; } if ($type instanceof IntegerRangeType) { $integerRanges[$key][] = $type; continue; } $otherTypes[] = $type; } } $resultTypes = []; foreach ([$constantFloats, $constantBooleans, $constantStrings] as $constantTypes) { if (count($constantTypes['a']) === 0) { if (count($constantTypes['b']) > 0) { $resultTypes[] = TypeCombinator::union(...$constantTypes['b']); } continue; } elseif (count($constantTypes['b']) === 0) { $resultTypes[] = TypeCombinator::union(...$constantTypes['a']); continue; } $aTypes = TypeCombinator::union(...$constantTypes['a']); $bTypes = TypeCombinator::union(...$constantTypes['b']); if ($aTypes->equals($bTypes)) { $resultTypes[] = $aTypes; continue; } $resultTypes[] = TypeCombinator::union(...$constantTypes['a'], ...$constantTypes['b'])->generalize(GeneralizePrecision::moreSpecific()); } if (count($constantArrays['a']) > 0) { if (count($constantArrays['b']) === 0) { $resultTypes[] = TypeCombinator::union(...$constantArrays['a']); } else { $constantArraysA = TypeCombinator::union(...$constantArrays['a']); $constantArraysB = TypeCombinator::union(...$constantArrays['b']); if ($constantArraysA->getIterableKeyType()->equals($constantArraysB->getIterableKeyType()) && $constantArraysA->getArraySize()->getGreaterOrEqualType()->isSuperTypeOf($constantArraysB->getArraySize())->yes()) { $resultArrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach (TypeUtils::flattenTypes($constantArraysA->getIterableKeyType()) as $keyType) { $resultArrayBuilder->setOffsetValueType($keyType, self::generalizeType($constantArraysA->getOffsetValueType($keyType), $constantArraysB->getOffsetValueType($keyType), $depth + 1), !$constantArraysA->hasOffsetValueType($keyType)->and($constantArraysB->hasOffsetValueType($keyType))->negate()->no()); } $resultTypes[] = $resultArrayBuilder->getArray(); } else { $resultType = new ArrayType(TypeCombinator::union(self::generalizeType($constantArraysA->getIterableKeyType(), $constantArraysB->getIterableKeyType(), $depth + 1)), TypeCombinator::union(self::generalizeType($constantArraysA->getIterableValueType(), $constantArraysB->getIterableValueType(), $depth + 1))); if ($constantArraysA->isIterableAtLeastOnce()->yes() && $constantArraysB->isIterableAtLeastOnce()->yes() && $constantArraysA->getArraySize()->getGreaterOrEqualType()->isSuperTypeOf($constantArraysB->getArraySize())->yes()) { $resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType()); } if ($constantArraysA->isList()->yes() && $constantArraysB->isList()->yes()) { $resultType = AccessoryArrayListType::intersectWith($resultType); } $resultTypes[] = $resultType; } } } elseif (count($constantArrays['b']) > 0) { $resultTypes[] = TypeCombinator::union(...$constantArrays['b']); } if (count($generalArrays['a']) > 0) { if (count($generalArrays['b']) === 0) { $resultTypes[] = TypeCombinator::union(...$generalArrays['a']); } else { $generalArraysA = TypeCombinator::union(...$generalArrays['a']); $generalArraysB = TypeCombinator::union(...$generalArrays['b']); $aValueType = $generalArraysA->getIterableValueType(); $bValueType = $generalArraysB->getIterableValueType(); if ($aValueType->isArray()->yes() && $aValueType->isConstantArray()->no() && $bValueType->isArray()->yes() && $bValueType->isConstantArray()->no()) { $aDepth = self::getArrayDepth($aValueType) + $depth; $bDepth = self::getArrayDepth($bValueType) + $depth; if (($aDepth > 2 || $bDepth > 2) && abs($aDepth - $bDepth) > 0) { $aValueType = new MixedType(); $bValueType = new MixedType(); } } $resultType = new ArrayType(TypeCombinator::union(self::generalizeType($generalArraysA->getIterableKeyType(), $generalArraysB->getIterableKeyType(), $depth + 1)), TypeCombinator::union(self::generalizeType($aValueType, $bValueType, $depth + 1))); if ($generalArraysA->isIterableAtLeastOnce()->yes() && $generalArraysB->isIterableAtLeastOnce()->yes()) { $resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType()); } if ($generalArraysA->isList()->yes() && $generalArraysB->isList()->yes()) { $resultType = AccessoryArrayListType::intersectWith($resultType); } if ($generalArraysA->isOversizedArray()->yes() && $generalArraysB->isOversizedArray()->yes()) { $resultType = TypeCombinator::intersect($resultType, new OversizedArrayType()); } $resultTypes[] = $resultType; } } elseif (count($generalArrays['b']) > 0) { $resultTypes[] = TypeCombinator::union(...$generalArrays['b']); } if (count($constantIntegers['a']) > 0) { if (count($constantIntegers['b']) === 0) { $resultTypes[] = TypeCombinator::union(...$constantIntegers['a']); } else { $constantIntegersA = TypeCombinator::union(...$constantIntegers['a']); $constantIntegersB = TypeCombinator::union(...$constantIntegers['b']); if ($constantIntegersA->equals($constantIntegersB)) { $resultTypes[] = $constantIntegersA; } else { $min = null; $max = null; foreach ($constantIntegers['a'] as $int) { if ($min === null || $int->getValue() < $min) { $min = $int->getValue(); } if ($max !== null && $int->getValue() <= $max) { continue; } $max = $int->getValue(); } $gotGreater = \false; $gotSmaller = \false; foreach ($constantIntegers['b'] as $int) { if ($int->getValue() > $max) { $gotGreater = \true; } if ($int->getValue() >= $min) { continue; } $gotSmaller = \true; } if ($gotGreater && $gotSmaller) { $resultTypes[] = new IntegerType(); } elseif ($gotGreater) { $resultTypes[] = IntegerRangeType::fromInterval($min, null); } elseif ($gotSmaller) { $resultTypes[] = IntegerRangeType::fromInterval(null, $max); } else { $resultTypes[] = TypeCombinator::union($constantIntegersA, $constantIntegersB); } } } } elseif (count($constantIntegers['b']) > 0) { $resultTypes[] = TypeCombinator::union(...$constantIntegers['b']); } if (count($integerRanges['a']) > 0) { if (count($integerRanges['b']) === 0) { $resultTypes[] = TypeCombinator::union(...$integerRanges['a']); } else { $integerRangesA = TypeCombinator::union(...$integerRanges['a']); $integerRangesB = TypeCombinator::union(...$integerRanges['b']); if ($integerRangesA->equals($integerRangesB)) { $resultTypes[] = $integerRangesA; } else { $min = null; $max = null; foreach ($integerRanges['a'] as $range) { if ($range->getMin() === null) { $rangeMin = PHP_INT_MIN; } else { $rangeMin = $range->getMin(); } if ($range->getMax() === null) { $rangeMax = PHP_INT_MAX; } else { $rangeMax = $range->getMax(); } if ($min === null || $rangeMin < $min) { $min = $rangeMin; } if ($max !== null && $rangeMax <= $max) { continue; } $max = $rangeMax; } $gotGreater = \false; $gotSmaller = \false; foreach ($integerRanges['b'] as $range) { if ($range->getMin() === null) { $rangeMin = PHP_INT_MIN; } else { $rangeMin = $range->getMin(); } if ($range->getMax() === null) { $rangeMax = PHP_INT_MAX; } else { $rangeMax = $range->getMax(); } if ($rangeMax > $max) { $gotGreater = \true; } if ($rangeMin >= $min) { continue; } $gotSmaller = \true; } if ($min === PHP_INT_MIN) { $min = null; } if ($max === PHP_INT_MAX) { $max = null; } if ($gotGreater && $gotSmaller) { $resultTypes[] = new IntegerType(); } elseif ($gotGreater) { $resultTypes[] = IntegerRangeType::fromInterval($min, null); } elseif ($gotSmaller) { $resultTypes[] = IntegerRangeType::fromInterval(null, $max); } else { $resultTypes[] = TypeCombinator::union($integerRangesA, $integerRangesB); } } } } elseif (count($integerRanges['b']) > 0) { $resultTypes[] = TypeCombinator::union(...$integerRanges['b']); } $accessoryTypes = array_map(static function (Type $type) : Type { return $type->generalize(GeneralizePrecision::moreSpecific()); }, TypeUtils::getAccessoryTypes($a)); return TypeCombinator::union(TypeCombinator::intersect(TypeCombinator::union(...$resultTypes, ...$otherTypes), ...$accessoryTypes), ...$otherTypes); } private static function getArrayDepth(Type $type) : int { $depth = 0; $arrays = TypeUtils::getAnyArrays($type); while (count($arrays) > 0) { $temp = $type->getIterableValueType(); $type = $temp; $arrays = TypeUtils::getAnyArrays($type); $depth++; } return $depth; } public function equals(self $otherScope) : bool { if (!$this->context->equals($otherScope->context)) { return \false; } if (!$this->compareVariableTypeHolders($this->expressionTypes, $otherScope->expressionTypes)) { return \false; } return $this->compareVariableTypeHolders($this->nativeExpressionTypes, $otherScope->nativeExpressionTypes); } /** * @param array $variableTypeHolders * @param array $otherVariableTypeHolders */ private function compareVariableTypeHolders(array $variableTypeHolders, array $otherVariableTypeHolders) : bool { if (count($variableTypeHolders) !== count($otherVariableTypeHolders)) { return \false; } foreach ($variableTypeHolders as $variableExprString => $variableTypeHolder) { if (!isset($otherVariableTypeHolders[$variableExprString])) { return \false; } if (!$variableTypeHolder->getCertainty()->equals($otherVariableTypeHolders[$variableExprString]->getCertainty())) { return \false; } if (!$variableTypeHolder->getType()->equals($otherVariableTypeHolders[$variableExprString]->getType())) { return \false; } unset($otherVariableTypeHolders[$variableExprString]); } return \true; } private function getBooleanExpressionDepth(Expr $expr, int $depth = 0) : int { while ($expr instanceof BinaryOp\BooleanOr || $expr instanceof BinaryOp\LogicalOr || $expr instanceof BinaryOp\BooleanAnd || $expr instanceof BinaryOp\LogicalAnd) { return $this->getBooleanExpressionDepth($expr->left, $depth + 1); } return $depth; } /** @api */ public function canAccessProperty(PropertyReflection $propertyReflection) : bool { return $this->canAccessClassMember($propertyReflection); } /** @api */ public function canCallMethod(MethodReflection $methodReflection) : bool { if ($this->canAccessClassMember($methodReflection)) { return \true; } return $this->canAccessClassMember($methodReflection->getPrototype()); } /** @api */ public function canAccessConstant(ConstantReflection $constantReflection) : bool { return $this->canAccessClassMember($constantReflection); } private function canAccessClassMember(ClassMemberReflection $classMemberReflection) : bool { if ($classMemberReflection->isPublic()) { return \true; } $classReflectionName = $classMemberReflection->getDeclaringClass()->getName(); $canAccessClassMember = static function (ClassReflection $classReflection) use($classMemberReflection, $classReflectionName) { if ($classMemberReflection->isPrivate()) { return $classReflection->getName() === $classReflectionName; } // protected if ($classReflection->getName() === $classReflectionName || $classReflection->isSubclassOf($classReflectionName)) { return \true; } return $classMemberReflection->getDeclaringClass()->isSubclassOf($classReflection->getName()); }; foreach ($this->inClosureBindScopeClasses as $inClosureBindScopeClass) { if (!$this->reflectionProvider->hasClass($inClosureBindScopeClass)) { continue; } if ($canAccessClassMember($this->reflectionProvider->getClass($inClosureBindScopeClass))) { return \true; } } if ($this->isInClass()) { return $canAccessClassMember($this->getClassReflection()); } return \false; } /** * @return string[] */ public function debug() : array { $descriptions = []; foreach ($this->expressionTypes as $name => $variableTypeHolder) { $key = sprintf('%s (%s)', $name, $variableTypeHolder->getCertainty()->describe()); $descriptions[$key] = $variableTypeHolder->getType()->describe(VerbosityLevel::precise()); } foreach ($this->nativeExpressionTypes as $exprString => $nativeTypeHolder) { $key = sprintf('native %s (%s)', $exprString, $nativeTypeHolder->getCertainty()->describe()); $descriptions[$key] = $nativeTypeHolder->getType()->describe(VerbosityLevel::precise()); } foreach ($this->conditionalExpressions as $exprString => $holders) { foreach (array_values($holders) as $i => $holder) { $key = sprintf('condition about %s #%d', $exprString, $i + 1); $parts = []; foreach ($holder->getConditionExpressionTypeHolders() as $conditionalExprString => $expressionTypeHolder) { $parts[] = $conditionalExprString . '=' . $expressionTypeHolder->getType()->describe(VerbosityLevel::precise()); } $condition = implode(' && ', $parts); $descriptions[$key] = sprintf('if %s then %s is %s (%s)', $condition, $exprString, $holder->getTypeHolder()->getType()->describe(VerbosityLevel::precise()), $holder->getTypeHolder()->getCertainty()->describe()); } } return $descriptions; } /** * @param non-empty-string $className */ private function exactInstantiation(New_ $node, string $className) : ?Type { $resolvedClassName = $this->resolveExactName(new Name($className)); $isStatic = \false; if ($resolvedClassName === null) { if (strtolower($className) !== 'static') { return null; } if (!$this->isInClass()) { return null; } $resolvedClassName = $this->getClassReflection()->getName(); $isStatic = \true; } if (!$this->reflectionProvider->hasClass($resolvedClassName)) { return null; } $classReflection = $this->reflectionProvider->getClass($resolvedClassName); if ($classReflection->hasConstructor()) { $constructorMethod = $classReflection->getConstructor(); } else { $constructorMethod = new DummyConstructorReflection($classReflection); } $resolvedTypes = []; $methodCall = new Expr\StaticCall(new Name($resolvedClassName), new Node\Identifier($constructorMethod->getName()), $node->getArgs()); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($this, $methodCall->getArgs(), $constructorMethod->getVariants(), $constructorMethod->getNamedArgumentsVariants()); $normalizedMethodCall = \PHPStan\Analyser\ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $methodCall); if ($normalizedMethodCall !== null) { foreach ($this->dynamicReturnTypeExtensionRegistry->getDynamicStaticMethodReturnTypeExtensionsForClass($classReflection->getName()) as $dynamicStaticMethodReturnTypeExtension) { if (!$dynamicStaticMethodReturnTypeExtension->isStaticMethodSupported($constructorMethod)) { continue; } $resolvedType = $dynamicStaticMethodReturnTypeExtension->getTypeFromStaticMethodCall($constructorMethod, $normalizedMethodCall, $this); if ($resolvedType === null) { continue; } $resolvedTypes[] = $resolvedType; } } if (count($resolvedTypes) > 0) { return TypeCombinator::union(...$resolvedTypes); } $methodResult = $this->getType($methodCall); if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { return $methodResult; } $objectType = $isStatic ? new StaticType($classReflection) : new ObjectType($resolvedClassName); if (!$classReflection->isGeneric()) { return $objectType; } $assignedToProperty = $node->getAttribute(NewAssignedToPropertyVisitor::ATTRIBUTE_NAME); if ($assignedToProperty !== null) { $constructorVariant = $constructorMethod->getOnlyVariant(); $classTemplateTypes = $classReflection->getTemplateTypeMap()->getTypes(); $originalClassTemplateTypes = $classTemplateTypes; foreach ($constructorVariant->getParameters() as $parameter) { TypeTraverser::map($parameter->getType(), static function (Type $type, callable $traverse) use(&$classTemplateTypes) : Type { if ($type instanceof TemplateType && array_key_exists($type->getName(), $classTemplateTypes)) { $classTemplateType = $classTemplateTypes[$type->getName()]; if ($classTemplateType instanceof TemplateType && $classTemplateType->getScope()->equals($type->getScope())) { unset($classTemplateTypes[$type->getName()]); } return $type; } return $traverse($type); }); } if (count($classTemplateTypes) === count($originalClassTemplateTypes)) { $propertyType = TypeCombinator::removeNull($this->getType($assignedToProperty)); if ($objectType->isSuperTypeOf($propertyType)->yes()) { return $propertyType; } } } if ($constructorMethod instanceof DummyConstructorReflection) { if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), null, []); } return new GenericObjectType($resolvedClassName, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds())); } if ($constructorMethod->getDeclaringClass()->getName() !== $classReflection->getName()) { if (!$constructorMethod->getDeclaringClass()->isGeneric()) { if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), null, []); } return new GenericObjectType($resolvedClassName, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds())); } $newType = new GenericObjectType($resolvedClassName, $classReflection->typeMapToList($classReflection->getTemplateTypeMap())); $ancestorType = $newType->getAncestorWithClassName($constructorMethod->getDeclaringClass()->getName()); if ($ancestorType === null) { if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), null, []); } return new GenericObjectType($resolvedClassName, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds())); } $ancestorClassReflections = $ancestorType->getObjectClassReflections(); if (count($ancestorClassReflections) !== 1) { if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), null, []); } return new GenericObjectType($resolvedClassName, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds())); } $newParentNode = new New_(new Name($constructorMethod->getDeclaringClass()->getName()), $node->args); $newParentType = $this->getType($newParentNode); $newParentTypeClassReflections = $newParentType->getObjectClassReflections(); if (count($newParentTypeClassReflections) !== 1) { if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds()), null, []); } return new GenericObjectType($resolvedClassName, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()->resolveToBounds())); } $newParentTypeClassReflection = $newParentTypeClassReflections[0]; $ancestorClassReflection = $ancestorClassReflections[0]; $ancestorMapping = []; foreach ($ancestorClassReflection->getActiveTemplateTypeMap()->getTypes() as $typeName => $templateType) { if (!$templateType instanceof TemplateType) { continue; } $ancestorMapping[$typeName] = $templateType; } $resolvedTypeMap = []; foreach ($newParentTypeClassReflection->getActiveTemplateTypeMap()->getTypes() as $typeName => $type) { if (!array_key_exists($typeName, $ancestorMapping)) { continue; } $ancestorType = $ancestorMapping[$typeName]; if (!$ancestorType->getBound()->isSuperTypeOf($type)->yes()) { continue; } if (!array_key_exists($ancestorType->getName(), $resolvedTypeMap)) { $resolvedTypeMap[$ancestorType->getName()] = $type; continue; } $resolvedTypeMap[$ancestorType->getName()] = TypeCombinator::union($resolvedTypeMap[$ancestorType->getName()], $type); } if ($isStatic) { return new GenericStaticType($classReflection, $classReflection->typeMapToList(new TemplateTypeMap($resolvedTypeMap)), null, []); } return new GenericObjectType($resolvedClassName, $classReflection->typeMapToList(new TemplateTypeMap($resolvedTypeMap))); } $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($this, $methodCall->getArgs(), $constructorMethod->getVariants(), $constructorMethod->getNamedArgumentsVariants()); if ($this->explicitMixedInUnknownGenericNew) { $resolvedTemplateTypeMap = $parametersAcceptor->getResolvedTemplateTypeMap(); $newGenericType = new GenericObjectType($resolvedClassName, $classReflection->typeMapToList($classReflection->getTemplateTypeMap())); if ($isStatic) { $newGenericType = new GenericStaticType($classReflection, $classReflection->typeMapToList($classReflection->getTemplateTypeMap()), null, []); } return TypeTraverser::map($newGenericType, static function (Type $type, callable $traverse) use($resolvedTemplateTypeMap) : Type { if ($type instanceof TemplateType && !$type->isArgument()) { $newType = $resolvedTemplateTypeMap->getType($type->getName()); if ($newType === null || $newType instanceof ErrorType) { return $type->getBound(); } return TemplateTypeHelper::generalizeInferredTemplateType($type, $newType); } return $traverse($type); }); } $resolvedPhpDoc = $classReflection->getResolvedPhpDoc(); if ($resolvedPhpDoc === null) { return $objectType; } $list = []; $typeMap = $parametersAcceptor->getResolvedTemplateTypeMap(); foreach ($resolvedPhpDoc->getTemplateTags() as $tag) { $templateType = $typeMap->getType($tag->getName()); if ($templateType !== null) { $list[] = $templateType; continue; } $default = $tag->getDefault(); if ($default !== null) { $list[] = $default; continue; } $bound = $tag->getBound(); if ($bound instanceof MixedType && $bound->isExplicitMixed()) { $bound = new MixedType(\false); } $list[] = $bound; } if ($isStatic) { return new GenericStaticType($classReflection, $list, null, []); } return new GenericObjectType($resolvedClassName, $list); } private function filterTypeWithMethod(Type $typeWithMethod, string $methodName) : ?Type { if ($typeWithMethod instanceof UnionType) { $typeWithMethod = $typeWithMethod->filterTypes(static function (Type $innerType) use($methodName) { return $innerType->hasMethod($methodName)->yes(); }); } if (!$typeWithMethod->hasMethod($methodName)->yes()) { return null; } return $typeWithMethod; } /** @api */ public function getMethodReflection(Type $typeWithMethod, string $methodName) : ?ExtendedMethodReflection { $type = $this->filterTypeWithMethod($typeWithMethod, $methodName); if ($type === null) { return null; } return $type->getMethod($methodName, $this); } /** @api */ public function getNakedMethod(Type $typeWithMethod, string $methodName) : ?ExtendedMethodReflection { $type = $this->filterTypeWithMethod($typeWithMethod, $methodName); if ($type === null) { return null; } return $type->getUnresolvedMethodPrototype($methodName, $this)->getNakedMethod(); } /** * @param MethodCall|Node\Expr\StaticCall $methodCall */ private function methodCallReturnType(Type $typeWithMethod, string $methodName, Expr $methodCall) : ?Type { $typeWithMethod = $this->filterTypeWithMethod($typeWithMethod, $methodName); if ($typeWithMethod === null) { return null; } $methodReflection = $typeWithMethod->getMethod($methodName, $this); $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($this, $methodCall->getArgs(), $methodReflection->getVariants(), $methodReflection->getNamedArgumentsVariants()); if ($methodCall instanceof MethodCall) { $normalizedMethodCall = \PHPStan\Analyser\ArgumentsNormalizer::reorderMethodArguments($parametersAcceptor, $methodCall); } else { $normalizedMethodCall = \PHPStan\Analyser\ArgumentsNormalizer::reorderStaticCallArguments($parametersAcceptor, $methodCall); } if ($normalizedMethodCall === null) { return $this->transformVoidToNull($parametersAcceptor->getReturnType(), $methodCall); } $resolvedTypes = []; foreach ($typeWithMethod->getObjectClassNames() as $className) { if ($normalizedMethodCall instanceof MethodCall) { foreach ($this->dynamicReturnTypeExtensionRegistry->getDynamicMethodReturnTypeExtensionsForClass($className) as $dynamicMethodReturnTypeExtension) { if (!$dynamicMethodReturnTypeExtension->isMethodSupported($methodReflection)) { continue; } $resolvedType = $dynamicMethodReturnTypeExtension->getTypeFromMethodCall($methodReflection, $normalizedMethodCall, $this); if ($resolvedType === null) { continue; } $resolvedTypes[] = $resolvedType; } } else { foreach ($this->dynamicReturnTypeExtensionRegistry->getDynamicStaticMethodReturnTypeExtensionsForClass($className) as $dynamicStaticMethodReturnTypeExtension) { if (!$dynamicStaticMethodReturnTypeExtension->isStaticMethodSupported($methodReflection)) { continue; } $resolvedType = $dynamicStaticMethodReturnTypeExtension->getTypeFromStaticMethodCall($methodReflection, $normalizedMethodCall, $this); if ($resolvedType === null) { continue; } $resolvedTypes[] = $resolvedType; } } } if (count($resolvedTypes) > 0) { return $this->transformVoidToNull(TypeCombinator::union(...$resolvedTypes), $methodCall); } return $this->transformVoidToNull($parametersAcceptor->getReturnType(), $methodCall); } /** @api */ public function getPropertyReflection(Type $typeWithProperty, string $propertyName) : ?ExtendedPropertyReflection { if ($typeWithProperty instanceof UnionType) { $typeWithProperty = $typeWithProperty->filterTypes(static function (Type $innerType) use($propertyName) { return $innerType->hasProperty($propertyName)->yes(); }); } if (!$typeWithProperty->hasProperty($propertyName)->yes()) { return null; } return $typeWithProperty->getProperty($propertyName, $this); } /** * @param PropertyFetch|Node\Expr\StaticPropertyFetch $propertyFetch */ private function propertyFetchType(Type $fetchedOnType, string $propertyName, Expr $propertyFetch) : ?Type { $propertyReflection = $this->getPropertyReflection($fetchedOnType, $propertyName); if ($propertyReflection === null) { return null; } if ($this->isInExpressionAssign($propertyFetch)) { return $propertyReflection->getWritableType(); } return $propertyReflection->getReadableType(); } public function getConstantReflection(Type $typeWithConstant, string $constantName) : ?ConstantReflection { if ($typeWithConstant instanceof UnionType) { $typeWithConstant = $typeWithConstant->filterTypes(static function (Type $innerType) use($constantName) { return $innerType->hasConstant($constantName)->yes(); }); } if (!$typeWithConstant->hasConstant($constantName)->yes()) { return null; } return $typeWithConstant->getConstant($constantName); } /** * @return array */ private function getConstantTypes() : array { $constantTypes = []; foreach ($this->expressionTypes as $exprString => $typeHolder) { $expr = $typeHolder->getExpr(); if (!$expr instanceof ConstFetch) { continue; } $constantTypes[$exprString] = $typeHolder; } return $constantTypes; } /** * @return array */ private function getNativeConstantTypes() : array { $constantTypes = []; foreach ($this->nativeExpressionTypes as $exprString => $typeHolder) { $expr = $typeHolder->getExpr(); if (!$expr instanceof ConstFetch) { continue; } $constantTypes[$exprString] = $typeHolder; } return $constantTypes; } public function getIterableKeyType(Type $iteratee) : Type { if ($iteratee instanceof UnionType) { $filtered = $iteratee->filterTypes(static function (Type $innerType) { return $innerType->isIterable()->yes(); }); if (!$filtered instanceof NeverType) { $iteratee = $filtered; } } return $iteratee->getIterableKeyType(); } public function getIterableValueType(Type $iteratee) : Type { if ($iteratee instanceof UnionType) { $filtered = $iteratee->filterTypes(static function (Type $innerType) { return $innerType->isIterable()->yes(); }); if (!$filtered instanceof NeverType) { $iteratee = $filtered; } } return $iteratee->getIterableValueType(); } } getType($expr))) { // We're in most likely in context of a null-safe operator ($scope->moreSpecificType is defined for $expr) // Modifying the expression would not bring any value or worse ruin the context information return $expr; } return self::getNullsafeShortcircuitedExpr($expr); } /** * @internal Use NullsafeOperatorHelper::getNullsafeShortcircuitedExprRespectingScope */ public static function getNullsafeShortcircuitedExpr(Expr $expr) : Expr { if ($expr instanceof Expr\NullsafeMethodCall) { return new Expr\MethodCall(self::getNullsafeShortcircuitedExpr($expr->var), $expr->name, $expr->args); } if ($expr instanceof Expr\MethodCall) { $var = self::getNullsafeShortcircuitedExpr($expr->var); if ($expr->var === $var) { return $expr; } return new Expr\MethodCall($var, $expr->name, $expr->getArgs()); } if ($expr instanceof Expr\StaticCall && $expr->class instanceof Expr) { $class = self::getNullsafeShortcircuitedExpr($expr->class); if ($expr->class === $class) { return $expr; } return new Expr\StaticCall($class, $expr->name, $expr->getArgs()); } if ($expr instanceof Expr\ArrayDimFetch) { $var = self::getNullsafeShortcircuitedExpr($expr->var); if ($expr->var === $var) { return $expr; } return new Expr\ArrayDimFetch($var, $expr->dim); } if ($expr instanceof Expr\NullsafePropertyFetch) { return new Expr\PropertyFetch(self::getNullsafeShortcircuitedExpr($expr->var), $expr->name); } if ($expr instanceof Expr\PropertyFetch) { $var = self::getNullsafeShortcircuitedExpr($expr->var); if ($expr->var === $var) { return $expr; } return new Expr\PropertyFetch($var, $expr->name); } if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) { $class = self::getNullsafeShortcircuitedExpr($expr->class); if ($expr->class === $class) { return $expr; } return new Expr\StaticPropertyFetch($class, $expr->name); } return $expr; } } */ private $unorderedErrors; /** * @var list */ private $filteredPhpErrors; /** * @var list */ private $allPhpErrors; /** * @var list */ private $locallyIgnoredErrors; /** * @var array */ private $linesToIgnore; /** * @var array */ private $unmatchedLineIgnores; /** * @var list */ private $internalErrors; /** * @var list */ private $collectedData; /** * @var array>|null */ private $dependencies; /** * @var array>|null */ private $usedTraitDependencies; /** * @var array> */ private $exportedNodes; /** * @var bool */ private $reachedInternalErrorsCountLimit; /** * @var int */ private $peakMemoryUsageBytes; /** @var list|null */ private $errors = null; /** * @param list $unorderedErrors * @param list $filteredPhpErrors * @param list $allPhpErrors * @param list $locallyIgnoredErrors * @param array $linesToIgnore * @param array $unmatchedLineIgnores * @param list $collectedData * @param list $internalErrors * @param array>|null $dependencies * @param array>|null $usedTraitDependencies * @param array> $exportedNodes */ public function __construct(array $unorderedErrors, array $filteredPhpErrors, array $allPhpErrors, array $locallyIgnoredErrors, array $linesToIgnore, array $unmatchedLineIgnores, array $internalErrors, array $collectedData, ?array $dependencies, ?array $usedTraitDependencies, array $exportedNodes, bool $reachedInternalErrorsCountLimit, int $peakMemoryUsageBytes) { $this->unorderedErrors = $unorderedErrors; $this->filteredPhpErrors = $filteredPhpErrors; $this->allPhpErrors = $allPhpErrors; $this->locallyIgnoredErrors = $locallyIgnoredErrors; $this->linesToIgnore = $linesToIgnore; $this->unmatchedLineIgnores = $unmatchedLineIgnores; $this->internalErrors = $internalErrors; $this->collectedData = $collectedData; $this->dependencies = $dependencies; $this->usedTraitDependencies = $usedTraitDependencies; $this->exportedNodes = $exportedNodes; $this->reachedInternalErrorsCountLimit = $reachedInternalErrorsCountLimit; $this->peakMemoryUsageBytes = $peakMemoryUsageBytes; } /** * @return list */ public function getUnorderedErrors() : array { return $this->unorderedErrors; } /** * @return list */ public function getErrors() : array { if (!isset($this->errors)) { $this->errors = $this->unorderedErrors; usort($this->errors, static function (\PHPStan\Analyser\Error $a, \PHPStan\Analyser\Error $b) : int { return [$a->getFile(), $a->getLine(), $a->getMessage()] <=> [$b->getFile(), $b->getLine(), $b->getMessage()]; }); } return $this->errors; } /** * @return list */ public function getFilteredPhpErrors() : array { return $this->filteredPhpErrors; } /** * @return list */ public function getAllPhpErrors() : array { return $this->allPhpErrors; } /** * @return list */ public function getLocallyIgnoredErrors() : array { return $this->locallyIgnoredErrors; } /** * @return array */ public function getLinesToIgnore() : array { return $this->linesToIgnore; } /** * @return array */ public function getUnmatchedLineIgnores() : array { return $this->unmatchedLineIgnores; } /** * @return list */ public function getInternalErrors() : array { return $this->internalErrors; } /** * @return list */ public function getCollectedData() : array { return $this->collectedData; } /** * @return array>|null */ public function getDependencies() : ?array { return $this->dependencies; } /** * @return array>|null */ public function getUsedTraitDependencies() : ?array { return $this->usedTraitDependencies; } /** * @return array> */ public function getExportedNodes() : array { return $this->exportedNodes; } public function hasReachedInternalErrorsCountLimit() : bool { return $this->reachedInternalErrorsCountLimit; } public function getPeakMemoryUsageBytes() : int { return $this->peakMemoryUsageBytes; } } scope = $scope; $this->specifiedExpressions = $specifiedExpressions; } public function getScope() : \PHPStan\Analyser\MutatingScope { return $this->scope; } /** * @return EnsuredNonNullabilityResultExpression[] */ public function getSpecifiedExpressions() : array { return $this->specifiedExpressions; } } */ private $uses; /** * @var ?string */ private $className; /** * @var ?string */ private $functionName; /** * @var array */ private $typeAliasesMap; /** * @var bool */ private $bypassTypeAliases; /** * @var array */ private $constUses; /** * @var ?string */ private $typeAliasClassName; /** * @var TemplateTypeMap */ private $templateTypeMap; /** * @api * @param non-empty-string|null $namespace * @param array $uses alias(string) => fullName(string) * @param array $constUses alias(string) => fullName(string) * @param array $typeAliasesMap */ public function __construct(?string $namespace, array $uses, ?string $className = null, ?string $functionName = null, ?TemplateTypeMap $templateTypeMap = null, array $typeAliasesMap = [], bool $bypassTypeAliases = \false, array $constUses = [], ?string $typeAliasClassName = null) { $this->namespace = $namespace; $this->uses = $uses; $this->className = $className; $this->functionName = $functionName; $this->typeAliasesMap = $typeAliasesMap; $this->bypassTypeAliases = $bypassTypeAliases; $this->constUses = $constUses; $this->typeAliasClassName = $typeAliasClassName; $this->templateTypeMap = $templateTypeMap ?? TemplateTypeMap::createEmpty(); } public function getNamespace() : ?string { return $this->namespace; } /** * @return array */ public function getUses() : array { return $this->uses; } public function hasUseAlias(string $name) : bool { return isset($this->uses[strtolower($name)]); } /** * @return array */ public function getConstUses() : array { return $this->constUses; } public function getClassName() : ?string { return $this->className; } public function getClassNameForTypeAlias() : ?string { return $this->typeAliasClassName ?? $this->className; } public function resolveStringName(string $name) : string { if (str_starts_with($name, '\\')) { return ltrim($name, '\\'); } $nameParts = explode('\\', $name); $firstNamePart = strtolower($nameParts[0]); if (isset($this->uses[$firstNamePart])) { if (count($nameParts) === 1) { return $this->uses[$firstNamePart]; } array_shift($nameParts); return sprintf('%s\\%s', $this->uses[$firstNamePart], implode('\\', $nameParts)); } if ($this->namespace !== null) { return sprintf('%s\\%s', $this->namespace, $name); } return $name; } /** * @return non-empty-list */ public function resolveConstantNames(string $name) : array { if (str_starts_with($name, '\\')) { return [ltrim($name, '\\')]; } $nameParts = explode('\\', $name); $firstNamePart = strtolower($nameParts[0]); if (count($nameParts) > 1) { if (isset($this->uses[$firstNamePart])) { array_shift($nameParts); return [sprintf('%s\\%s', $this->uses[$firstNamePart], implode('\\', $nameParts))]; } } elseif (isset($this->constUses[$firstNamePart])) { return [$this->constUses[$firstNamePart]]; } if ($this->namespace !== null) { return [sprintf('%s\\%s', $this->namespace, $name), $name]; } return [$name]; } public function getTemplateTypeScope() : ?TemplateTypeScope { if ($this->className !== null) { if ($this->functionName !== null) { return TemplateTypeScope::createWithMethod($this->className, $this->functionName); } return TemplateTypeScope::createWithClass($this->className); } if ($this->functionName !== null) { return TemplateTypeScope::createWithFunction($this->functionName); } return null; } public function getTemplateTypeMap() : TemplateTypeMap { return $this->templateTypeMap; } public function resolveTemplateTypeName(string $name) : ?Type { return $this->templateTypeMap->getType($name); } public function withTemplateTypeMap(TemplateTypeMap $map) : self { if ($map->isEmpty() && $this->templateTypeMap->isEmpty()) { return $this; } return new self($this->namespace, $this->uses, $this->className, $this->functionName, new TemplateTypeMap(array_merge($this->templateTypeMap->getTypes(), $map->getTypes())), $this->typeAliasesMap, $this->bypassTypeAliases, $this->constUses); } public function withoutNamespaceAndUses() : self { return new self(null, [], $this->className, $this->functionName, $this->templateTypeMap, $this->typeAliasesMap, $this->bypassTypeAliases, $this->constUses); } public function withClassName(string $className) : self { return new self($this->namespace, $this->uses, $className, $this->functionName, $this->templateTypeMap, $this->typeAliasesMap, $this->bypassTypeAliases, $this->constUses); } public function unsetTemplateType(string $name) : self { $map = $this->templateTypeMap; if (!$map->hasType($name)) { return $this; } return new self($this->namespace, $this->uses, $this->className, $this->functionName, $this->templateTypeMap->unsetType($name), $this->typeAliasesMap, $this->bypassTypeAliases, $this->constUses); } public function bypassTypeAliases() : self { return new self($this->namespace, $this->uses, $this->className, $this->functionName, $this->templateTypeMap, $this->typeAliasesMap, \true, $this->constUses); } public function shouldBypassTypeAliases() : bool { return $this->bypassTypeAliases; } public function hasTypeAlias(string $alias) : bool { return array_key_exists($alias, $this->typeAliasesMap); } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self($properties['namespace'], $properties['uses'], $properties['className'], $properties['functionName'], $properties['templateTypeMap'], $properties['typeAliasesMap'], $properties['bypassTypeAliases'], $properties['constUses']); } } */ class InternalError implements JsonSerializable { /** * @var string */ private $message; /** * @var string */ private $contextDescription; /** * @var Trace */ private $trace; /** * @var ?string */ private $traceAsString; /** * @var bool */ private $shouldReportBug; public const STACK_TRACE_METADATA_KEY = 'stackTrace'; public const STACK_TRACE_AS_STRING_METADATA_KEY = 'stackTraceAsString'; /** * @param Trace $trace */ public function __construct(string $message, string $contextDescription, array $trace, ?string $traceAsString, bool $shouldReportBug) { $this->message = $message; $this->contextDescription = $contextDescription; $this->trace = $trace; $this->traceAsString = $traceAsString; $this->shouldReportBug = $shouldReportBug; } /** * @return Trace */ public static function prepareTrace(Throwable $exception) : array { $trace = array_map(static function (array $trace) { return ['file' => $trace['file'] ?? null, 'line' => $trace['line'] ?? null]; }, $exception->getTrace()); array_unshift($trace, ['file' => $exception->getFile(), 'line' => $exception->getLine()]); return $trace; } public function getMessage() : string { return $this->message; } public function getContextDescription() : string { return $this->contextDescription; } /** * @return Trace */ public function getTrace() : array { return $this->trace; } public function getTraceAsString() : ?string { return $this->traceAsString; } public function shouldReportBug() : bool { return $this->shouldReportBug; } /** * @param mixed[] $json */ public static function decode(array $json) : self { return new self($json['message'], $json['contextDescription'], $json['trace'], $json['traceAsString'], $json['shouldReportBug']); } /** * @return mixed */ #[\ReturnTypeWillChange] public function jsonSerialize() { return ['message' => $this->message, 'contextDescription' => $this->contextDescription, 'trace' => $this->trace, 'traceAsString' => $this->traceAsString, 'shouldReportBug' => $this->shouldReportBug]; } } isDeep = $isDeep; $this->inAssignRightSideVariableName = $inAssignRightSideVariableName; $this->inAssignRightSideType = $inAssignRightSideType; $this->inAssignRightSideNativeType = $inAssignRightSideNativeType; } public static function createTopLevel() : self { return new self(\false, null, null, null); } public static function createDeep() : self { return new self(\true, null, null, null); } public function enterDeep() : self { if ($this->isDeep) { return $this; } return new self(\true, $this->inAssignRightSideVariableName, $this->inAssignRightSideType, $this->inAssignRightSideNativeType); } public function isDeep() : bool { return $this->isDeep; } public function enterRightSideAssign(string $variableName, Type $type, Type $nativeType) : self { return new self($this->isDeep, $variableName, $type, $nativeType); } public function getInAssignRightSideVariableName() : ?string { return $this->inAssignRightSideVariableName; } public function getInAssignRightSideType() : ?Type { return $this->inAssignRightSideType; } public function getInAssignRightSideNativeType() : ?Type { return $this->inAssignRightSideNativeType; } } isTopLevel = $isTopLevel; } public static function createTopLevel() : self { return new self(\true); } public static function createDeep() : self { return new self(\false); } public function isTopLevel() : bool { return $this->isTopLevel; } public function enterDeep() : self { if ($this->isTopLevel) { return self::createDeep(); } return $this; } } reflectionProviderProvider = $reflectionProviderProvider; $this->container = $container; } public function create() : \PHPStan\Analyser\ConstantResolver { return new \PHPStan\Analyser\ConstantResolver($this->reflectionProviderProvider, $this->container->getParameter('dynamicConstantNames')); } } $expressionTypes * @param array $nativeExpressionTypes * @param array $conditionalExpressions * @param list $inClosureBindScopeClasses * @param array $currentlyAssignedExpressions * @param array $currentlyAllowedUndefinedExpressions * @param list $inFunctionCallsStack * @param FunctionReflection|MethodReflection|null $function */ public function create(\PHPStan\Analyser\ScopeContext $context, bool $declareStrictTypes = \false, $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], array $conditionalExpressions = [], array $inClosureBindScopeClasses = [], ?ParametersAcceptor $anonymousFunctionReflection = null, bool $inFirstLevelStatement = \true, array $currentlyAssignedExpressions = [], array $currentlyAllowedUndefinedExpressions = [], array $inFunctionCallsStack = [], bool $afterExtractCall = \false, ?\PHPStan\Analyser\Scope $parentScope = null, bool $nativeTypesPromoted = \false) : \PHPStan\Analyser\MutatingScope; } scopeClass = $scopeClass; $this->container = $container; $this->explicitMixedInUnknownGenericNew = $this->container->getParameter('featureToggles')['explicitMixedInUnknownGenericNew']; $this->explicitMixedForGlobalVariables = $this->container->getParameter('featureToggles')['explicitMixedForGlobalVariables']; } /** * @param array $expressionTypes * @param array $nativeExpressionTypes * @param array $conditionalExpressions * @param array $currentlyAssignedExpressions * @param array $currentlyAllowedUndefinedExpressions * @param list $inFunctionCallsStack * @param FunctionReflection|MethodReflection|null $function */ public function create(\PHPStan\Analyser\ScopeContext $context, bool $declareStrictTypes = \false, $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], array $conditionalExpressions = [], array $inClosureBindScopeClasses = [], ?ParametersAcceptor $anonymousFunctionReflection = null, bool $inFirstLevelStatement = \true, array $currentlyAssignedExpressions = [], array $currentlyAllowedUndefinedExpressions = [], array $inFunctionCallsStack = [], bool $afterExtractCall = \false, ?\PHPStan\Analyser\Scope $parentScope = null, bool $nativeTypesPromoted = \false) : \PHPStan\Analyser\MutatingScope { $scopeClass = $this->scopeClass; if (!is_a($scopeClass, \PHPStan\Analyser\MutatingScope::class, \true)) { throw new ShouldNotHappenException(); } return new $scopeClass($this, $this->container->getByType(ReflectionProvider::class), $this->container->getByType(InitializerExprTypeResolver::class), $this->container->getByType(DynamicReturnTypeExtensionRegistryProvider::class)->getRegistry(), $this->container->getByType(ExpressionTypeResolverExtensionRegistryProvider::class)->getRegistry(), $this->container->getByType(ExprPrinter::class), $this->container->getByType(\PHPStan\Analyser\TypeSpecifier::class), $this->container->getByType(PropertyReflectionFinder::class), $this->container->getService('currentPhpVersionSimpleParser'), $this->container->getByType(\PHPStan\Analyser\NodeScopeResolver::class), $this->container->getByType(\PHPStan\Analyser\RicherScopeGetTypeHelper::class), $this->container->getByType(\PHPStan\Analyser\ConstantResolver::class), $context, $this->container->getByType(PhpVersion::class), $declareStrictTypes, $function, $namespace, $expressionTypes, $nativeExpressionTypes, $conditionalExpressions, $inClosureBindScopeClasses, $anonymousFunctionReflection, $inFirstLevelStatement, $currentlyAssignedExpressions, $currentlyAllowedUndefinedExpressions, $inFunctionCallsStack, $afterExtractCall, $parentScope, $nativeTypesPromoted, $this->explicitMixedInUnknownGenericNew, $this->explicitMixedForGlobalVariables); } } scope = $scope; $this->hasYield = $hasYield; $this->throwPoints = $throwPoints; $this->impurePoints = $impurePoints; $this->truthyScopeCallback = $truthyScopeCallback; $this->falseyScopeCallback = $falseyScopeCallback; } public function getScope() : \PHPStan\Analyser\MutatingScope { return $this->scope; } public function hasYield() : bool { return $this->hasYield; } /** * @return ThrowPoint[] */ public function getThrowPoints() : array { return $this->throwPoints; } /** * @return ImpurePoint[] */ public function getImpurePoints() : array { return $this->impurePoints; } public function getTruthyScope() : \PHPStan\Analyser\MutatingScope { if ($this->truthyScopeCallback === null) { return $this->scope; } if ($this->truthyScope !== null) { return $this->truthyScope; } $callback = $this->truthyScopeCallback; $this->truthyScope = $callback(); return $this->truthyScope; } public function getFalseyScope() : \PHPStan\Analyser\MutatingScope { if ($this->falseyScopeCallback === null) { return $this->scope; } if ($this->falseyScope !== null) { return $this->falseyScope; } $callback = $this->falseyScopeCallback; $this->falseyScope = $callback(); return $this->falseyScope; } } statement = $statement; $this->result = $result; } public function getStatement() : Stmt { return $this->statement; } public function getResult() : \PHPStan\Analyser\StatementResult { return $this->result; } } scope = $scope; $this->variableName = $variableName; parent::__construct(sprintf('Undefined variable: $%s', $variableName)); } public function getScope() : \PHPStan\Analyser\Scope { return $this->scope; } public function getVariableName() : string { return $this->variableName; } public function getTip() : ?string { return null; } } */ private $currentlyResolving = []; /** * @param string[] $dynamicConstantNames */ public function __construct(ReflectionProviderProvider $reflectionProviderProvider, array $dynamicConstantNames) { $this->reflectionProviderProvider = $reflectionProviderProvider; $this->dynamicConstantNames = $dynamicConstantNames; } public function resolveConstant(Name $name, ?NamespaceAnswerer $scope) : ?Type { if (!$this->getReflectionProvider()->hasConstant($name, $scope)) { return null; } /** @var string $resolvedConstantName */ $resolvedConstantName = $this->getReflectionProvider()->resolveConstantName($name, $scope); $constantType = $this->resolvePredefinedConstant($resolvedConstantName); if ($constantType !== null) { return $constantType; } if (array_key_exists($resolvedConstantName, $this->currentlyResolving)) { return new MixedType(); } $this->currentlyResolving[$resolvedConstantName] = \true; $constantReflection = $this->getReflectionProvider()->getConstant($name, $scope); $constantType = $constantReflection->getValueType(); $type = $this->resolveConstantType($resolvedConstantName, $constantType); unset($this->currentlyResolving[$resolvedConstantName]); return $type; } public function resolvePredefinedConstant(string $resolvedConstantName) : ?Type { // core, https://www.php.net/manual/en/reserved.constants.php if ($resolvedConstantName === 'PHP_VERSION') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_MAJOR_VERSION') { return IntegerRangeType::fromInterval(5, null); } if ($resolvedConstantName === 'PHP_MINOR_VERSION') { return IntegerRangeType::fromInterval(0, null); } if ($resolvedConstantName === 'PHP_RELEASE_VERSION') { return IntegerRangeType::fromInterval(0, null); } if ($resolvedConstantName === 'PHP_VERSION_ID') { return IntegerRangeType::fromInterval(50207, null); } if ($resolvedConstantName === 'PHP_ZTS') { return new UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]); } if ($resolvedConstantName === 'PHP_DEBUG') { return new UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]); } if ($resolvedConstantName === 'PHP_MAXPATHLEN') { return IntegerRangeType::fromInterval(1, null); } if ($resolvedConstantName === 'PHP_OS') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_OS_FAMILY') { return new UnionType([new ConstantStringType('Windows'), new ConstantStringType('BSD'), new ConstantStringType('Darwin'), new ConstantStringType('Solaris'), new ConstantStringType('Linux'), new ConstantStringType('Unknown')]); } if ($resolvedConstantName === 'PHP_SAPI') { return new UnionType([new ConstantStringType('apache'), new ConstantStringType('apache2handler'), new ConstantStringType('cgi'), new ConstantStringType('cli'), new ConstantStringType('cli-server'), new ConstantStringType('embed'), new ConstantStringType('fpm-fcgi'), new ConstantStringType('litespeed'), new ConstantStringType('phpdbg'), new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()])]); } if ($resolvedConstantName === 'PHP_EOL') { return new UnionType([new ConstantStringType("\n"), new ConstantStringType("\r\n")]); } if ($resolvedConstantName === 'PHP_INT_MAX') { return PHP_INT_SIZE === 8 ? new UnionType([new ConstantIntegerType(2147483647), new ConstantIntegerType(9223372036854775807)]) : new ConstantIntegerType(2147483647); } if ($resolvedConstantName === 'PHP_INT_MIN') { // Why the -1 you might wonder, the answer is to fit it into an int :/ see https://3v4l.org/4SHIQ return PHP_INT_SIZE === 8 ? new UnionType([new ConstantIntegerType(-9223372036854775807 - 1), new ConstantIntegerType(-2147483647 - 1)]) : new ConstantIntegerType(-2147483647 - 1); } if ($resolvedConstantName === 'PHP_INT_SIZE') { return new UnionType([new ConstantIntegerType(4), new ConstantIntegerType(8)]); } if ($resolvedConstantName === 'PHP_FLOAT_DIG') { return IntegerRangeType::fromInterval(1, null); } if ($resolvedConstantName === 'PHP_EXTENSION_DIR') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_PREFIX') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_BINDIR') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_BINARY') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_MANDIR') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_LIBDIR') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_DATADIR') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_SYSCONFDIR') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_LOCALSTATEDIR') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_CONFIG_FILE_PATH') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if ($resolvedConstantName === 'PHP_SHLIB_SUFFIX') { return new UnionType([new ConstantStringType('so'), new ConstantStringType('dll')]); } if ($resolvedConstantName === 'PHP_FD_SETSIZE') { return IntegerRangeType::fromInterval(1, null); } if ($resolvedConstantName === '__COMPILER_HALT_OFFSET__') { return IntegerRangeType::fromInterval(1, null); } // core other, https://www.php.net/manual/en/info.constants.php if ($resolvedConstantName === 'PHP_WINDOWS_VERSION_MAJOR') { return IntegerRangeType::fromInterval(4, null); } if ($resolvedConstantName === 'PHP_WINDOWS_VERSION_MINOR') { return IntegerRangeType::fromInterval(0, null); } if ($resolvedConstantName === 'PHP_WINDOWS_VERSION_BUILD') { return IntegerRangeType::fromInterval(1, null); } // dir, https://www.php.net/manual/en/dir.constants.php if ($resolvedConstantName === 'DIRECTORY_SEPARATOR') { return new UnionType([new ConstantStringType('/'), new ConstantStringType('\\')]); } if ($resolvedConstantName === 'PATH_SEPARATOR') { return new UnionType([new ConstantStringType(':'), new ConstantStringType(';')]); } // iconv, https://www.php.net/manual/en/iconv.constants.php if ($resolvedConstantName === 'ICONV_IMPL') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } // libxml, https://www.php.net/manual/en/libxml.constants.php if ($resolvedConstantName === 'LIBXML_VERSION') { return IntegerRangeType::fromInterval(1, null); } if ($resolvedConstantName === 'LIBXML_DOTTED_VERSION') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } // openssl, https://www.php.net/manual/en/openssl.constants.php if ($resolvedConstantName === 'OPENSSL_VERSION_NUMBER') { return IntegerRangeType::fromInterval(1, null); } // pcre, https://www.php.net/manual/en/pcre.constants.php if ($resolvedConstantName === 'PCRE_VERSION') { return new IntersectionType([new StringType(), new AccessoryNonFalsyStringType()]); } if (in_array($resolvedConstantName, ['STDIN', 'STDOUT', 'STDERR'], \true)) { return new ResourceType(); } if ($resolvedConstantName === 'NAN') { return new ConstantFloatType(NAN); } if ($resolvedConstantName === 'INF') { return new ConstantFloatType(INF); } return null; } public function resolveConstantType(string $constantName, Type $constantType) : Type { if ($constantType->isConstantValue()->yes() && in_array($constantName, $this->dynamicConstantNames, \true)) { return $constantType->generalize(GeneralizePrecision::lessSpecific()); } return $constantType; } public function resolveClassConstantType(string $className, string $constantName, Type $constantType, ?Type $nativeType) : Type { $lookupConstantName = sprintf('%s::%s', $className, $constantName); if (in_array($lookupConstantName, $this->dynamicConstantNames, \true)) { if ($nativeType !== null) { return $nativeType; } if ($constantType->isConstantValue()->yes()) { return $constantType->generalize(GeneralizePrecision::lessSpecific()); } } return $constantType; } private function getReflectionProvider() : ReflectionProvider { return $this->reflectionProviderProvider->getReflectionProvider(); } } */ private $storage = []; /** * @return mixed|null */ public function load(string $key, string $variableKey) { if (!isset($this->storage[$key])) { return null; } $item = $this->storage[$key]; if (!$item->isVariableKeyValid($variableKey)) { return null; } return $item->getData(); } /** * @param mixed $data */ public function save(string $key, string $variableKey, $data) : void { $item = new \PHPStan\Cache\CacheItem($variableKey, $data); @var_export($item, \true); $this->storage[$key] = $item; } } variableKey = $variableKey; $this->data = $data; } public function isVariableKeyValid(string $variableKey) : bool { return $this->variableKey === $variableKey; } /** * @return mixed */ public function getData() { return $this->data; } /** * @param mixed[] $properties */ public static function __set_state(array $properties) : self { return new self($properties['variableKey'], $properties['data']); } } directory = $directory; } /** * @return mixed|null */ public function load(string $key, string $variableKey) { [, , $filePath] = $this->getFilePaths($key); return (static function () use($variableKey, $filePath) { $cacheItem = @(include $filePath); if (!$cacheItem instanceof \PHPStan\Cache\CacheItem) { return null; } if (!$cacheItem->isVariableKeyValid($variableKey)) { return null; } return $cacheItem->getData(); })(); } /** * @param mixed $data * @throws DirectoryCreatorException */ public function save(string $key, string $variableKey, $data) : void { [$firstDirectory, $secondDirectory, $path] = $this->getFilePaths($key); DirectoryCreator::ensureDirectoryExists($this->directory, 0777); DirectoryCreator::ensureDirectoryExists($firstDirectory, 0777); DirectoryCreator::ensureDirectoryExists($secondDirectory, 0777); $tmpPath = sprintf('%s/%s.tmp', $this->directory, Random::generate()); $errorBefore = error_get_last(); $exported = @var_export(new \PHPStan\Cache\CacheItem($variableKey, $data), \true); $errorAfter = error_get_last(); if ($errorAfter !== null && $errorBefore !== $errorAfter) { throw new ShouldNotHappenException(sprintf('Error occurred while saving item %s (%s) to cache: %s', $key, $variableKey, $errorAfter['message'])); } FileWriter::write($tmpPath, sprintf("directory, substr($keyHash, 0, 2)); $secondDirectory = sprintf('%s/%s', $firstDirectory, substr($keyHash, 2, 2)); $filePath = sprintf('%s/%s.php', $secondDirectory, $keyHash); return [$firstDirectory, $secondDirectory, $filePath]; } } storage = $storage; } /** * @return mixed|null */ public function load(string $key, string $variableKey) { return $this->storage->load($key, $variableKey); } /** * @param mixed $data */ public function save(string $key, string $variableKey, $data) : void { $this->storage->save($key, $variableKey, $data); } } versionId = $versionId; $this->composerAutoloaderProjectPaths = $composerAutoloaderProjectPaths; } public function create() : \PHPStan\Php\PhpVersionFactory { $composerPhpVersion = null; if (count($this->composerAutoloaderProjectPaths) > 0) { $composerJsonPath = end($this->composerAutoloaderProjectPaths) . '/composer.json'; if (is_file($composerJsonPath)) { try { $composerJsonContents = FileReader::read($composerJsonPath); $composer = Json::decode($composerJsonContents, Json::FORCE_ARRAY); $platformVersion = $composer['config']['platform']['php'] ?? null; if (is_string($platformVersion)) { $composerPhpVersion = $platformVersion; } } catch (CouldNotReadFileException|JsonException $e) { // pass } } } return new \PHPStan\Php\PhpVersionFactory($this->versionId, $composerPhpVersion); } } versionId = $versionId; $this->source = $source; } public function getSourceLabel() : string { switch ($this->source) { case self::SOURCE_RUNTIME: return 'runtime'; case self::SOURCE_CONFIG: return 'config'; case self::SOURCE_COMPOSER_PLATFORM_PHP: return 'config.platform.php in composer.json'; } return 'unknown'; } public function getVersionId() : int { return $this->versionId; } public function getVersionString() : string { $first = (int) floor($this->versionId / 10000); $second = (int) floor($this->versionId % 10000 / 100); $third = (int) floor($this->versionId % 100); return $first . '.' . $second . ($third !== 0 ? '.' . $third : ''); } public function supportsNullCoalesceAssign() : bool { return $this->versionId >= 70400; } public function supportsParameterContravariance() : bool { return $this->versionId >= 70400; } public function supportsReturnCovariance() : bool { return $this->versionId >= 70400; } public function supportsNoncapturingCatches() : bool { return $this->versionId >= 80000; } public function supportsNativeUnionTypes() : bool { return $this->versionId >= 80000; } public function deprecatesRequiredParameterAfterOptional() : bool { return $this->versionId >= 80000; } public function deprecatesRequiredParameterAfterOptionalNullableAndDefaultNull() : bool { return $this->versionId >= 80100; } public function deprecatesRequiredParameterAfterOptionalUnionOrMixed() : bool { return $this->versionId >= 80300; } public function supportsLessOverridenParametersWithVariadic() : bool { return $this->versionId >= 80000; } public function supportsThrowExpression() : bool { return $this->versionId >= 80000; } public function supportsClassConstantOnExpression() : bool { return $this->versionId >= 80000; } public function supportsLegacyConstructor() : bool { return $this->versionId < 80000; } public function supportsPromotedProperties() : bool { return $this->versionId >= 80000; } public function supportsParameterTypeWidening() : bool { return $this->versionId >= 70200; } public function supportsUnsetCast() : bool { return $this->versionId < 80000; } public function supportsNamedArguments() : bool { return $this->versionId >= 80000; } public function throwsTypeErrorForInternalFunctions() : bool { return $this->versionId >= 80000; } public function throwsValueErrorForInternalFunctions() : bool { return $this->versionId >= 80000; } public function supportsHhPrintfSpecifier() : bool { return $this->versionId >= 80000; } public function isEmptyStringValidAliasForNoneInMbSubstituteCharacter() : bool { return $this->versionId < 80000; } public function supportsAllUnicodeScalarCodePointsInMbSubstituteCharacter() : bool { return $this->versionId >= 70200; } public function isNumericStringValidArgInMbSubstituteCharacter() : bool { return $this->versionId < 80000; } public function isNullValidArgInMbSubstituteCharacter() : bool { return $this->versionId >= 80000; } public function isInterfaceConstantImplicitlyFinal() : bool { return $this->versionId < 80100; } public function supportsFinalConstants() : bool { return $this->versionId >= 80100; } public function supportsReadOnlyProperties() : bool { return $this->versionId >= 80100; } public function supportsEnums() : bool { return $this->versionId >= 80100; } public function supportsPureIntersectionTypes() : bool { return $this->versionId >= 80100; } public function supportsCaseInsensitiveConstantNames() : bool { return $this->versionId < 80000; } public function hasStricterRoundFunctions() : bool { return $this->versionId >= 80000; } public function hasTentativeReturnTypes() : bool { return $this->versionId >= 80100; } public function supportsFirstClassCallables() : bool { return $this->versionId >= 80100; } public function supportsArrayUnpackingWithStringKeys() : bool { return $this->versionId >= 80100; } public function throwsOnInvalidMbStringEncoding() : bool { return $this->versionId >= 80000; } public function supportsPassNoneEncodings() : bool { return $this->versionId < 70300; } public function producesWarningForFinalPrivateMethods() : bool { return $this->versionId >= 80000; } public function deprecatesDynamicProperties() : bool { return $this->versionId >= 80200; } public function strSplitReturnsEmptyArray() : bool { return $this->versionId >= 80200; } public function supportsDisjunctiveNormalForm() : bool { return $this->versionId >= 80200; } public function serializableRequiresMagicMethods() : bool { return $this->versionId >= 80100; } public function arrayFunctionsReturnNullWithNonArray() : bool { return $this->versionId < 80000; } public function castsNumbersToStringsOnLooseComparison() : bool { return $this->versionId >= 80000; } public function supportsCallableInstanceMethods() : bool { return $this->versionId < 80000; } public function supportsJsonValidate() : bool { return $this->versionId >= 80300; } public function supportsConstantsInTraits() : bool { return $this->versionId >= 80200; } public function supportsNativeTypesInClassConstants() : bool { return $this->versionId >= 80300; } public function supportsAbstractTraitMethods() : bool { return $this->versionId >= 80000; } public function supportsOverrideAttribute() : bool { return $this->versionId >= 80300; } public function supportsDynamicClassConstantFetch() : bool { return $this->versionId >= 80300; } public function supportsReadOnlyClasses() : bool { return $this->versionId >= 80200; } public function supportsReadOnlyAnonymousClasses() : bool { return $this->versionId >= 80300; } public function supportsNeverReturnTypeInArrowFunction() : bool { return $this->versionId >= 80200; } public function supportsPregUnmatchedAsNull() : bool { // while PREG_UNMATCHED_AS_NULL is defined in php-src since 7.2.x it starts working as expected with 7.4.x // https://3v4l.org/v3HE4 return $this->versionId >= 70400; } public function supportsPregCaptureOnlyNamedGroups() : bool { // https://php.watch/versions/8.2/preg-n-no-capture-modifier return $this->versionId >= 80200; } public function hasDateTimeExceptions() : bool { return $this->versionId >= 80300; } public function isCurloptUrlCheckingFileSchemeWithOpenBasedir() : bool { // Before PHP 8.0, when setting CURLOPT_URL, an unparsable URL or a file:// scheme would fail if open_basedir is used // https://github.com/php/php-src/blob/php-7.4.33/ext/curl/interface.c#L139-L158 // https://github.com/php/php-src/blob/php-8.0.0/ext/curl/interface.c#L128-L130 return $this->versionId < 80000; } public function highlightStringDoesNotReturnFalse() : bool { return $this->versionId >= 80400; } public function deprecatesImplicitlyNullableParameterTypes() : bool { return $this->versionId >= 80400; } public function substrReturnFalseInsteadOfEmptyString() : bool { return $this->versionId < 80000; } } versionId = $versionId; $this->composerPhpVersion = $composerPhpVersion; } public function create() : \PHPStan\Php\PhpVersion { $versionId = $this->versionId; if ($versionId !== null) { $source = \PHPStan\Php\PhpVersion::SOURCE_CONFIG; } elseif ($this->composerPhpVersion !== null) { $parts = explode('.', $this->composerPhpVersion); $tmp = (int) $parts[0] * 10000 + (int) ($parts[1] ?? 0) * 100 + (int) ($parts[2] ?? 0); $tmp = max($tmp, 70100); $versionId = min($tmp, 80499); $source = \PHPStan\Php\PhpVersion::SOURCE_COMPOSER_PLATFORM_PHP; } else { $versionId = PHP_VERSION_ID; $source = \PHPStan\Php\PhpVersion::SOURCE_RUNTIME; } return new \PHPStan\Php\PhpVersion($versionId, $source); } } get($name); } } get('CODEBUILD_CI') !== \false; } public function getCiName() : string { return CiDetector::CI_AWS_CODEBUILD; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean(\mb_strpos($this->env->getString('CODEBUILD_WEBHOOK_EVENT'), 'PULL_REQUEST') === 0); } public function getBuildNumber() : string { return $this->env->getString('CODEBUILD_BUILD_NUMBER'); } public function getBuildUrl() : string { return $this->env->getString('CODEBUILD_BUILD_URL'); } public function getGitCommit() : string { return $this->env->getString('CODEBUILD_RESOLVED_SOURCE_VERSION'); } public function getGitBranch() : string { $gitReference = $this->env->getString('CODEBUILD_WEBHOOK_HEAD_REF'); return \preg_replace('~^refs/heads/~', '', $gitReference) ?? ''; } public function getRepositoryName() : string { return ''; // unsupported } public function getRepositoryUrl() : string { return $this->env->getString('CODEBUILD_SOURCE_REPO_URL'); } } env = $env; } } get('CIRCLECI') !== \false; } public function getCiName() : string { return CiDetector::CI_CIRCLE; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->getString('CI_PULL_REQUEST') !== ''); } public function getBuildNumber() : string { return $this->env->getString('CIRCLE_BUILD_NUM'); } public function getBuildUrl() : string { return $this->env->getString('CIRCLE_BUILD_URL'); } public function getGitCommit() : string { return $this->env->getString('CIRCLE_SHA1'); } public function getGitBranch() : string { return $this->env->getString('CIRCLE_BRANCH'); } public function getRepositoryName() : string { return \sprintf('%s/%s', $this->env->getString('CIRCLE_PROJECT_USERNAME'), $this->env->getString('CIRCLE_PROJECT_REPONAME')); } public function getRepositoryUrl() : string { return $this->env->getString('CIRCLE_REPOSITORY_URL'); } } get('GITLAB_CI') !== \false; } public function getCiName() : string { return CiDetector::CI_GITLAB; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->get('CI_MERGE_REQUEST_ID') !== \false || $this->env->get('CI_EXTERNAL_PULL_REQUEST_IID') !== \false); } public function getBuildNumber() : string { return !empty($this->env->getString('CI_JOB_ID')) ? $this->env->getString('CI_JOB_ID') : $this->env->getString('CI_BUILD_ID'); } public function getBuildUrl() : string { return $this->env->getString('CI_PROJECT_URL') . '/builds/' . $this->getBuildNumber(); } public function getGitCommit() : string { return !empty($this->env->getString('CI_COMMIT_SHA')) ? $this->env->getString('CI_COMMIT_SHA') : $this->env->getString('CI_BUILD_REF'); } public function getGitBranch() : string { return !empty($this->env->getString('CI_COMMIT_REF_NAME')) ? $this->env->getString('CI_COMMIT_REF_NAME') : $this->env->getString('CI_BUILD_REF_NAME'); } public function getRepositoryName() : string { return $this->env->getString('CI_PROJECT_PATH'); } public function getRepositoryUrl() : string { return !empty($this->env->getString('CI_REPOSITORY_URL')) ? $this->env->getString('CI_REPOSITORY_URL') : $this->env->getString('CI_BUILD_REPO'); } } get('TRAVIS') !== \false; } public function getCiName() : string { return CiDetector::CI_TRAVIS; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->getString('TRAVIS_PULL_REQUEST') !== 'false'); } public function getBuildNumber() : string { return $this->env->getString('TRAVIS_JOB_NUMBER'); } public function getBuildUrl() : string { return \sprintf('%s/%s/jobs/%s', self::TRAVIS_BASE_URL, $this->env->get('TRAVIS_REPO_SLUG'), $this->env->get('TRAVIS_JOB_ID')); } public function getGitCommit() : string { return $this->env->getString('TRAVIS_COMMIT'); } public function getGitBranch() : string { if ($this->isPullRequest()->no()) { return $this->env->getString('TRAVIS_BRANCH'); } // If the build is for PR, return name of the branch with the PR, not the target PR branch // https://github.com/travis-ci/travis-ci/issues/6652 return $this->env->getString('TRAVIS_PULL_REQUEST_BRANCH'); } public function getRepositoryName() : string { return $this->env->getString('TRAVIS_REPO_SLUG'); } public function getRepositoryUrl() : string { return ''; // unsupported } } get('WERCKER') === 'true'; } public function getCiName() : string { return CiDetector::CI_WERCKER; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getBuildNumber() : string { return $this->env->getString('WERCKER_RUN_ID'); } public function getBuildUrl() : string { return $this->env->getString('WERCKER_RUN_URL'); } public function getGitCommit() : string { return $this->env->getString('WERCKER_GIT_COMMIT'); } public function getGitBranch() : string { return $this->env->getString('WERCKER_GIT_BRANCH'); } public function getRepositoryName() : string { return $this->env->getString('WERCKER_GIT_OWNER') . '/' . $this->env->getString('WERCKER_GIT_REPOSITORY'); } public function getRepositoryUrl() : string { return ''; // unsupported } } get('TEAMCITY_VERSION') !== \false; } public function getCiName() : string { return CiDetector::CI_TEAMCITY; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getBuildNumber() : string { return $this->env->getString('BUILD_NUMBER'); } public function getBuildUrl() : string { return ''; // unsupported } public function getGitCommit() : string { return $this->env->getString('BUILD_VCS_NUMBER'); } public function getGitBranch() : string { return ''; // unsupported } public function getRepositoryName() : string { return ''; // unsupported } public function getRepositoryUrl() : string { return ''; // unsupported } } get('APPVEYOR') === 'True'; } public function getCiName() : string { return CiDetector::CI_APPVEYOR; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->getString('APPVEYOR_PULL_REQUEST_NUMBER') !== ''); } public function getBuildNumber() : string { return $this->env->getString('APPVEYOR_BUILD_NUMBER'); } public function getBuildUrl() : string { return \sprintf('%s/project/%s/%s/builds/%s', $this->env->get('APPVEYOR_URL'), $this->env->get('APPVEYOR_ACCOUNT_NAME'), $this->env->get('APPVEYOR_PROJECT_SLUG'), $this->env->get('APPVEYOR_BUILD_ID')); } public function getGitCommit() : string { return $this->env->getString('APPVEYOR_REPO_COMMIT'); } public function getGitBranch() : string { $prBranch = $this->env->getString('APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH'); if ($this->isPullRequest()->no() || empty($prBranch)) { return $this->env->getString('APPVEYOR_REPO_BRANCH'); } return $prBranch; } public function getRepositoryName() : string { return $this->env->getString('APPVEYOR_REPO_NAME'); } public function getRepositoryUrl() : string { return ''; // unsupported } } get('BUDDY') !== \false; } public function getCiName() : string { return CiDetector::CI_BUDDY; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->getString('BUDDY_EXECUTION_PULL_REQUEST_ID') !== ''); } public function getBuildNumber() : string { return $this->env->getString('BUDDY_EXECUTION_ID'); } public function getBuildUrl() : string { return $this->env->getString('BUDDY_EXECUTION_URL'); } public function getGitCommit() : string { return $this->env->getString('BUDDY_EXECUTION_REVISION'); } public function getGitBranch() : string { $prBranch = $this->env->getString('BUDDY_EXECUTION_PULL_REQUEST_HEAD_BRANCH'); if ($this->isPullRequest()->no() || empty($prBranch)) { return $this->env->getString('BUDDY_EXECUTION_BRANCH'); } return $prBranch; } public function getRepositoryName() : string { return $this->env->getString('BUDDY_REPO_SLUG'); } public function getRepositoryUrl() : string { return $this->env->getString('BUDDY_SCM_URL'); } } get('CI_NAME') === 'codeship'; } public function getCiName() : string { return CiDetector::CI_CODESHIP; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->getString('CI_PULL_REQUEST') !== 'false'); } public function getBuildNumber() : string { return $this->env->getString('CI_BUILD_NUMBER'); } public function getBuildUrl() : string { return $this->env->getString('CI_BUILD_URL'); } public function getGitCommit() : string { return $this->env->getString('COMMIT_ID'); } public function getGitBranch() : string { return $this->env->getString('CI_BRANCH'); } public function getRepositoryName() : string { return $this->env->getString('CI_REPO_NAME'); } public function getRepositoryUrl() : string { return ''; // unsupported } } get('GITHUB_ACTIONS') !== \false; } public function getCiName() : string { return CiDetector::CI_GITHUB_ACTIONS; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->getString('GITHUB_EVENT_NAME') === 'pull_request'); } public function getBuildNumber() : string { return $this->env->getString('GITHUB_RUN_NUMBER'); } public function getBuildUrl() : string { return \sprintf('%s/%s/commit/%s/checks', self::GITHUB_BASE_URL, $this->env->get('GITHUB_REPOSITORY'), $this->env->get('GITHUB_SHA')); } public function getGitCommit() : string { return $this->env->getString('GITHUB_SHA'); } public function getGitBranch() : string { $prBranch = $this->env->getString('GITHUB_HEAD_REF'); if ($this->isPullRequest()->no() || empty($prBranch)) { $gitReference = $this->env->getString('GITHUB_REF'); return \preg_replace('~^refs/heads/~', '', $gitReference) ?? ''; } return $prBranch; } public function getRepositoryName() : string { return $this->env->getString('GITHUB_REPOSITORY'); } public function getRepositoryUrl() : string { return \sprintf('%s/%s', self::GITHUB_BASE_URL, $this->env->get('GITHUB_REPOSITORY')); } } get('BITBUCKET_COMMIT') !== \false; } public function getCiName() : string { return CiDetector::CI_BITBUCKET_PIPELINES; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->getString('BITBUCKET_PR_ID') !== ''); } public function getBuildNumber() : string { return $this->env->getString('BITBUCKET_BUILD_NUMBER'); } public function getBuildUrl() : string { return \sprintf('%s/addon/pipelines/home#!/results/%s', $this->env->get('BITBUCKET_GIT_HTTP_ORIGIN'), $this->env->get('BITBUCKET_BUILD_NUMBER')); } public function getGitCommit() : string { return $this->env->getString('BITBUCKET_COMMIT'); } public function getGitBranch() : string { return $this->env->getString('BITBUCKET_BRANCH'); } public function getRepositoryName() : string { return $this->env->getString('BITBUCKET_REPO_FULL_NAME'); } public function getRepositoryUrl() : string { return \sprintf('ssh://%s', $this->env->get('BITBUCKET_GIT_SSH_ORIGIN')); } } get('bamboo_buildKey') !== \false; } public function getCiName() : string { return CiDetector::CI_BAMBOO; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->get('bamboo_repository_pr_key') !== \false); } public function getBuildNumber() : string { return $this->env->getString('bamboo_buildNumber'); } public function getBuildUrl() : string { return $this->env->getString('bamboo_resultsUrl'); } public function getGitCommit() : string { return $this->env->getString('bamboo_planRepository_revision'); } public function getGitBranch() : string { $prBranch = $this->env->getString('bamboo_repository_pr_sourceBranch'); if ($this->isPullRequest()->no() || empty($prBranch)) { return $this->env->getString('bamboo_planRepository_branch'); } return $prBranch; } public function getRepositoryName() : string { return $this->env->getString('bamboo_planRepository_name'); } public function getRepositoryUrl() : string { return $this->env->getString('bamboo_planRepository_repositoryUrl'); } } get('JENKINS_URL') !== \false; } public function getCiName() : string { return CiDetector::CI_JENKINS; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createMaybe(); } public function getBuildNumber() : string { return $this->env->getString('BUILD_NUMBER'); } public function getBuildUrl() : string { return $this->env->getString('BUILD_URL'); } public function getGitCommit() : string { return $this->env->getString('GIT_COMMIT'); } public function getGitBranch() : string { return $this->env->getString('GIT_BRANCH'); } public function getRepositoryName() : string { return ''; // unsupported } public function getRepositoryUrl() : string { return $this->env->getString('GIT_URL'); } } get('CI') === 'drone'; } public function getCiName() : string { return CiDetector::CI_DRONE; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->getString('DRONE_PULL_REQUEST') !== ''); } public function getBuildNumber() : string { return $this->env->getString('DRONE_BUILD_NUMBER'); } public function getBuildUrl() : string { return $this->env->getString('DRONE_BUILD_LINK'); } public function getGitCommit() : string { return $this->env->getString('DRONE_COMMIT_SHA'); } public function getGitBranch() : string { return $this->env->getString('DRONE_COMMIT_BRANCH'); } public function getRepositoryName() : string { return $this->env->getString('DRONE_REPO'); } public function getRepositoryUrl() : string { return $this->env->getString('DRONE_REPO_LINK'); } } get('CONTINUOUSPHP') === 'continuousphp'; } public function getCiName() : string { return CiDetector::CI_CONTINUOUSPHP; } public function isPullRequest() : TrinaryLogic { return TrinaryLogic::createFromBoolean($this->env->getString('CPHP_PR_ID') !== ''); } public function getBuildNumber() : string { return $this->env->getString('CPHP_BUILD_ID'); } public function getBuildUrl() : string { return $this->env->getString(''); } public function getGitCommit() : string { return $this->env->getString('CPHP_GIT_COMMIT'); } public function getGitBranch() : string { $gitReference = $this->env->getString('CPHP_GIT_REF'); return \preg_replace('~^refs/heads/~', '', $gitReference) ?? ''; } public function getRepositoryName() : string { return ''; // unsupported } public function getRepositoryUrl() : string { return $this->env->getString(''); } } value = $value; } public static function createMaybe() : self { return self::create(self::MAYBE); } public static function createFromBoolean(bool $value) : self { return self::create($value ? self::YES : self::NO); } private static function create(int $value) : self { return self::$registry[$value] = self::$registry[$value] ?? new self($value); } /** * Return true if its known for sure that the value is true */ public function yes() : bool { return $this->value === self::YES; } /** * Return true if its not known for sure whether the value is true or false */ public function maybe() : bool { return $this->value === self::MAYBE; } /** * Return true if its known for sure that the value is false */ public function no() : bool { return $this->value === self::NO; } /** * Return string representation of the value. * "Yes" when the value is true, "No" when its false, "Maybe" when its not known for sure whether its true or false. */ public function describe() : string { static $labels = [self::NO => 'No', self::MAYBE => 'Maybe', self::YES => 'Yes']; return $labels[$this->value]; } } environment = new Env(); } public static function fromEnvironment(Env $environment) : self { $detector = new static(); $detector->environment = $environment; return $detector; } /** * Is current environment an recognized CI server? */ public function isCiDetected() : bool { $ciServer = $this->detectCurrentCiServer(); return $ciServer !== null; } /** * Detect current CI server and return instance of its settings * * @throws CiNotDetectedException */ public function detect() : CiInterface { $ciServer = $this->detectCurrentCiServer(); if ($ciServer === null) { throw new CiNotDetectedException('No CI server detected in current environment'); } return $ciServer; } /** * @return string[] */ protected function getCiServers() : array { return [Ci\AppVeyor::class, Ci\AwsCodeBuild::class, Ci\Bamboo::class, Ci\BitbucketPipelines::class, Ci\Buddy::class, Ci\Circle::class, Ci\Codeship::class, Ci\Continuousphp::class, Ci\Drone::class, Ci\GitHubActions::class, Ci\GitLab::class, Ci\Jenkins::class, Ci\TeamCity::class, Ci\Travis::class, Ci\Wercker::class]; } protected function detectCurrentCiServer() : ?CiInterface { $ciServers = $this->getCiServers(); foreach ($ciServers as $ciClass) { $callback = [$ciClass, 'isDetected']; if (\is_callable($callback)) { if ($callback($this->environment)) { return new $ciClass($this->environment); } } } return null; } } { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "local>Ocramius/.github:renovate-config" ] } findFile directory, rather than * ClassLoader->loadClass because this library has a strict requirement that we * do NOT actually load the classes */ class ComposerSourceLocator extends \PHPStan\BetterReflection\SourceLocator\Type\AbstractSourceLocator { /** * @var \Composer\Autoload\ClassLoader */ private $classLoader; public function __construct(ClassLoader $classLoader, Locator $astLocator) { $this->classLoader = $classLoader; parent::__construct($astLocator); } /** * {@inheritDoc} * * @throws InvalidArgumentException * @throws InvalidFileLocation */ protected function createLocatedSource(Identifier $identifier) : ?\PHPStan\BetterReflection\SourceLocator\Located\LocatedSource { if ($identifier->getType()->getName() !== IdentifierType::IDENTIFIER_CLASS) { return null; } $filename = $this->classLoader->findFile($identifier->getName()); if ($filename === \false) { return null; } return new LocatedSource(file_get_contents($filename), $identifier->getName(), $filename); } } astLocator = $astLocator; } /** * {@inheritDoc} * * @throws ParseToAstFailure */ public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?\PHPStan\BetterReflection\Reflection\Reflection { $locatedSource = $this->createLocatedSource($identifier); if (!$locatedSource) { return null; } try { return $this->astLocator->findReflection($reflector, $locatedSource, $identifier); } catch (IdentifierNotFound $exception) { return null; } } /** * {@inheritDoc} * * @throws ParseToAstFailure */ public final function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { $locatedSource = $this->createLocatedSource(new Identifier(Identifier::WILDCARD, $identifierType)); if (!$locatedSource) { return []; } return $this->astLocator->findReflectionsOfType($reflector, $locatedSource, $identifierType); } } }|list|null $installedJson */ $installedJson = json_decode($jsonContent, \true); if (!is_array($composer)) { throw FailedToParseJson::inFile($composerJsonPath); } if (!is_array($installedJson)) { throw FailedToParseJson::inFile($installedJsonPath); } /** @psalm-var list $installed */ $installed = $installedJson['packages'] ?? $installedJson; $classMapPaths = array_merge($this->prefixPaths($this->packageToClassMapPaths($composer), $realInstallationPath . '/'), ...array_map(function (array $package) use($realInstallationPath, $vendorDir) : array { return $this->prefixPaths($this->packageToClassMapPaths($package), $this->packagePrefixPath($realInstallationPath, $package, $vendorDir)); }, $installed)); $classMapFiles = array_filter($classMapPaths, 'is_file'); $classMapDirectories = array_values(array_filter($classMapPaths, 'is_dir')); $filePaths = array_merge($this->prefixPaths($this->packageToFilePaths($composer), $realInstallationPath . '/'), ...array_map(function (array $package) use($realInstallationPath, $vendorDir) : array { return $this->prefixPaths($this->packageToFilePaths($package), $this->packagePrefixPath($realInstallationPath, $package, $vendorDir)); }, $installed)); return new AggregateSourceLocator(array_merge([new PsrAutoloaderLocator(Psr4Mapping::fromArrayMappings(array_merge_recursive($this->prefixWithInstallationPath($this->packageToPsr4AutoloadNamespaces($composer), $realInstallationPath), ...array_map(function (array $package) use($realInstallationPath, $vendorDir) : array { return $this->prefixWithPackagePath($this->packageToPsr4AutoloadNamespaces($package), $realInstallationPath, $package, $vendorDir); }, $installed))), $astLocator), new PsrAutoloaderLocator(Psr0Mapping::fromArrayMappings(array_merge_recursive($this->prefixWithInstallationPath($this->packageToPsr0AutoloadNamespaces($composer), $realInstallationPath), ...array_map(function (array $package) use($realInstallationPath, $vendorDir) : array { return $this->prefixWithPackagePath($this->packageToPsr0AutoloadNamespaces($package), $realInstallationPath, $package, $vendorDir); }, $installed))), $astLocator), new DirectoriesSourceLocator($classMapDirectories, $astLocator)], ...array_map(static function (string $file) use($astLocator) : array { assert($file !== ''); return [new SingleFileSourceLocator($file, $astLocator)]; }, array_merge($classMapFiles, $filePaths)))); } /** * @param ComposerPackage|Composer $package * * @return array> */ private function packageToPsr4AutoloadNamespaces(array $package) : array { return array_map(static function ($namespacePaths) : array { return (array) $namespacePaths; }, $package['autoload']['psr-4'] ?? []); } /** * @param ComposerPackage|Composer $package * * @return array> */ private function packageToPsr0AutoloadNamespaces(array $package) : array { return array_map(static function ($namespacePaths) : array { return (array) $namespacePaths; }, $package['autoload']['psr-0'] ?? []); } /** * @param ComposerPackage|Composer $package * * @return list */ private function packageToClassMapPaths(array $package) : array { return $package['autoload']['classmap'] ?? []; } /** * @param ComposerPackage|Composer $package * * @return list */ private function packageToFilePaths(array $package) : array { return $package['autoload']['files'] ?? []; } /** @param ComposerPackage $package */ private function packagePrefixPath(string $trimmedInstallationPath, array $package, string $vendorDir) : string { return $trimmedInstallationPath . '/' . $vendorDir . '/' . $package['name'] . '/'; } /** * @param array> $paths * @param ComposerPackage $package $package * * @return array> */ private function prefixWithPackagePath(array $paths, string $trimmedInstallationPath, array $package, string $vendorDir) : array { $prefix = $this->packagePrefixPath($trimmedInstallationPath, $package, $vendorDir); return array_map(function (array $paths) use($prefix) : array { return $this->prefixPaths($paths, $prefix); }, $paths); } /** * @param array> $paths * * @return array> */ private function prefixWithInstallationPath(array $paths, string $trimmedInstallationPath) : array { return array_map(function (array $paths) use($trimmedInstallationPath) : array { return $this->prefixPaths($paths, $trimmedInstallationPath . '/'); }, $paths); } /** * @param list $paths * * @return list */ private function prefixPaths(array $paths, string $prefix) : array { return array_map(static function (string $path) use($prefix) : string { return $prefix . $path; }, $paths); } } >, * psr-4?: array>, * classmap?: list, * files?: list, * exclude-from-classmap?: list * } * @psalm-type ComposerPackage array{ * name: string, * autoload: ComposerAutoload * } * @psalm-type Composer array{ * autoload: ComposerAutoload, * config?: array{vendor-dir?: string} * } */ final class MakeLocatorForComposerJson { public function __invoke(string $installationPath, Locator $astLocator) : SourceLocator { $realInstallationPath = (string) realpath($installationPath); if (!is_dir($realInstallationPath)) { throw InvalidProjectDirectory::atPath($installationPath); } $composerJsonPath = $realInstallationPath . '/composer.json'; if (!is_file($composerJsonPath)) { throw MissingComposerJson::inProjectPath($installationPath); } $composerJsonContent = file_get_contents($composerJsonPath); assert(is_string($composerJsonContent)); /** @psalm-var array{autoload: ComposerAutoload}|null $composer */ $composer = json_decode($composerJsonContent, \true); if (!is_array($composer)) { throw FailedToParseJson::inFile($composerJsonPath); } $pathPrefix = $realInstallationPath . '/'; $classMapPaths = $this->prefixPaths($this->packageToClassMapPaths($composer), $pathPrefix); $classMapFiles = array_filter($classMapPaths, 'is_file'); $classMapDirectories = array_values(array_filter($classMapPaths, 'is_dir')); $filePaths = $this->prefixPaths($this->packageToFilePaths($composer), $pathPrefix); return new AggregateSourceLocator(array_merge([new PsrAutoloaderLocator(Psr4Mapping::fromArrayMappings($this->prefixWithInstallationPath($this->packageToPsr4AutoloadNamespaces($composer), $pathPrefix)), $astLocator), new PsrAutoloaderLocator(Psr0Mapping::fromArrayMappings($this->prefixWithInstallationPath($this->packageToPsr0AutoloadNamespaces($composer), $pathPrefix)), $astLocator), new DirectoriesSourceLocator($classMapDirectories, $astLocator)], ...array_map(static function (string $file) use($astLocator) : array { assert($file !== ''); return [new SingleFileSourceLocator($file, $astLocator)]; }, array_merge($classMapFiles, $filePaths)))); } /** * @param array{autoload: ComposerAutoload} $package * * @return array> */ private function packageToPsr4AutoloadNamespaces(array $package) : array { return array_map(static function ($namespacePaths) : array { return (array) $namespacePaths; }, $package['autoload']['psr-4'] ?? []); } /** * @param array{autoload: ComposerAutoload} $package * * @return array> */ private function packageToPsr0AutoloadNamespaces(array $package) : array { return array_map(static function ($namespacePaths) : array { return (array) $namespacePaths; }, $package['autoload']['psr-0'] ?? []); } /** * @param array{autoload: ComposerAutoload} $package * * @return list */ private function packageToClassMapPaths(array $package) : array { return $package['autoload']['classmap'] ?? []; } /** * @param array{autoload: ComposerAutoload} $package * * @return list */ private function packageToFilePaths(array $package) : array { return $package['autoload']['files'] ?? []; } /** * @param array> $paths * * @return array> */ private function prefixWithInstallationPath(array $paths, string $trimmedInstallationPath) : array { return array_map(function (array $paths) use($trimmedInstallationPath) : array { return $this->prefixPaths($paths, $trimmedInstallationPath); }, $paths); } /** * @param list $paths * * @return list */ private function prefixPaths(array $paths, string $prefix) : array { return array_map(static function (string $path) use($prefix) : string { return $prefix . $path; }, $paths); } } }|list|null $installedJson */ $installedJson = json_decode($jsonContent, \true); if (!is_array($installedJson)) { throw FailedToParseJson::inFile($installedJsonPath); } /** @psalm-var list $installed */ $installed = $installedJson['packages'] ?? $installedJson; $classMapPaths = array_merge([], ...array_map(function (array $package) use($realInstallationPath, $vendorDir) : array { return $this->prefixPaths($this->packageToClassMapPaths($package), $this->packagePrefixPath($realInstallationPath, $package, $vendorDir)); }, $installed)); $classMapFiles = array_filter($classMapPaths, 'is_file'); $classMapDirectories = array_values(array_filter($classMapPaths, 'is_dir')); $filePaths = array_merge([], ...array_map(function (array $package) use($realInstallationPath, $vendorDir) : array { return $this->prefixPaths($this->packageToFilePaths($package), $this->packagePrefixPath($realInstallationPath, $package, $vendorDir)); }, $installed)); return new AggregateSourceLocator(array_merge([new PsrAutoloaderLocator(Psr4Mapping::fromArrayMappings(array_merge_recursive([], ...array_map(function (array $package) use($realInstallationPath, $vendorDir) : array { return $this->prefixWithPackagePath($this->packageToPsr4AutoloadNamespaces($package), $realInstallationPath, $package, $vendorDir); }, $installed))), $astLocator), new PsrAutoloaderLocator(Psr0Mapping::fromArrayMappings(array_merge_recursive([], ...array_map(function (array $package) use($realInstallationPath, $vendorDir) : array { return $this->prefixWithPackagePath($this->packageToPsr0AutoloadNamespaces($package), $realInstallationPath, $package, $vendorDir); }, $installed))), $astLocator), new DirectoriesSourceLocator($classMapDirectories, $astLocator)], ...array_map(static function (string $file) use($astLocator) : array { assert($file !== ''); return [new SingleFileSourceLocator($file, $astLocator)]; }, array_merge($classMapFiles, $filePaths)))); } /** * @param ComposerPackage $package * * @return array> */ private function packageToPsr4AutoloadNamespaces(array $package) : array { return array_map(static function ($namespacePaths) : array { return (array) $namespacePaths; }, $package['autoload']['psr-4'] ?? []); } /** * @param ComposerPackage $package * * @return array> */ private function packageToPsr0AutoloadNamespaces(array $package) : array { return array_map(static function ($namespacePaths) : array { return (array) $namespacePaths; }, $package['autoload']['psr-0'] ?? []); } /** * @param ComposerPackage $package * * @return list */ private function packageToClassMapPaths(array $package) : array { return $package['autoload']['classmap'] ?? []; } /** * @param ComposerPackage $package * * @return list */ private function packageToFilePaths(array $package) : array { return $package['autoload']['files'] ?? []; } /** @param ComposerPackage $package */ private function packagePrefixPath(string $trimmedInstallationPath, array $package, string $vendorDir) : string { return $trimmedInstallationPath . '/' . $vendorDir . '/' . $package['name'] . '/'; } /** * @param array> $paths * @param ComposerPackage $package * * @return array> */ private function prefixWithPackagePath(array $paths, string $trimmedInstallationPath, array $package, string $vendorDir) : array { $prefix = $this->packagePrefixPath($trimmedInstallationPath, $package, $vendorDir); return array_map(function (array $paths) use($prefix) : array { return $this->prefixPaths($paths, $prefix); }, $paths); } /** * @param array $paths * * @return array */ private function prefixPaths(array $paths, string $prefix) : array { return array_map(static function (string $path) use($prefix) : string { return $prefix . $path; }, $paths); } } mapping = $mapping; $this->astLocator = $astLocator; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?\PHPStan\BetterReflection\Reflection\Reflection { /** @phpstan-var non-empty-string $file */ foreach ($this->mapping->resolvePossibleFilePaths($identifier) as $file) { try { FileChecker::assertReadableFile($file); return $this->astLocator->findReflection($reflector, new LocatedSource(file_get_contents($file), $identifier->getName(), $file), $identifier); } catch (InvalidFileLocation $exception) { // Ignore } catch (IdentifierNotFound $exception) { // on purpose - autoloading is allowed to fail, and silently-failing autoloaders are normal/endorsed } } return null; } /** * Find all identifiers of a type * * @return list */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return (new DirectoriesSourceLocator($this->mapping->directories(), $this->astLocator))->locateIdentifiersByType($reflector, $identifierType); } } */ public function resolvePossibleFilePaths(Identifier $identifier) : array; /** @return list */ public function directories() : array; } > */ private $mappings = []; private function __construct() { } /** @param array> $mappings */ public static function fromArrayMappings(array $mappings) : self { $instance = new self(); $instance->mappings = array_map(static function (array $directories) : array { return array_map(static function (string $directory) : string { return rtrim($directory, '/'); }, $directories); }, $mappings); return $instance; } /** {@inheritDoc} */ public function resolvePossibleFilePaths(Identifier $identifier) : array { if (!$identifier->isClass()) { return []; } $className = $identifier->getName(); foreach ($this->mappings as $prefix => $paths) { if ($prefix === '') { continue; } if (strpos($className, $prefix) === 0) { return array_map(static function (string $path) use($className) : string { return $path . '/' . str_replace(['\\', '_'], '/', $className) . '.php'; }, $paths); } } return []; } /** {@inheritDoc} */ public function directories() : array { return array_values(array_unique(array_merge([], ...array_values($this->mappings)))); } } > */ private $mappings = []; private function __construct() { } /** @param array> $mappings */ public static function fromArrayMappings(array $mappings) : self { $instance = new self(); $instance->mappings = array_map(static function (array $directories) : array { return array_map(static function (string $directory) : string { return rtrim($directory, '/'); }, $directories); }, $mappings); return $instance; } /** {@inheritDoc} */ public function resolvePossibleFilePaths(Identifier $identifier) : array { if (!$identifier->isClass()) { return []; } $className = $identifier->getName(); $matchingPrefixes = $this->matchingPrefixes($className); return array_values(array_filter(array_merge([], ...array_map(static function (array $paths, string $prefix) use($className) : array { $subPath = ltrim(str_replace('\\', '/', substr($className, strlen($prefix))), '/'); if ($subPath === '') { return []; } return array_map(static function (string $path) use($subPath) : string { return $path . '/' . $subPath . '.php'; }, $paths); }, $matchingPrefixes, array_keys($matchingPrefixes))))); } /** @return array> */ private function matchingPrefixes(string $className) : array { return array_filter($this->mappings, static function (string $prefix) use($className) : bool { if ($prefix === '') { return \false; } return strpos($className, $prefix) === 0; }, ARRAY_FILTER_USE_KEY); } /** {@inheritDoc} */ public function directories() : array { return array_values(array_unique(array_merge([], ...array_values($this->mappings)))); } } */ private $fileSystemIterator; /** * @var \PHPStan\BetterReflection\SourceLocator\Ast\Locator */ private $astLocator; /** * @param Iterator $fileInfoIterator note: only SplFileInfo allowed in this iterator * * @throws InvalidFileInfo In case of iterator not contains only SplFileInfo. */ public function __construct(Iterator $fileInfoIterator, Locator $astLocator) { $this->astLocator = $astLocator; foreach ($fileInfoIterator as $fileInfo) { if (!$fileInfo instanceof SplFileInfo) { throw InvalidFileInfo::fromNonSplFileInfo($fileInfo); } } $this->fileSystemIterator = $fileInfoIterator; } /** @throws InvalidFileLocation */ private function getAggregatedSourceLocator() : \PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator { // @infection-ignore-all Coalesce: There's no difference, it's just optimization return $this->aggregateSourceLocator ?? ($this->aggregateSourceLocator = new \PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator(array_values(array_filter(array_map(function (SplFileInfo $item) : ?\PHPStan\BetterReflection\SourceLocator\Type\SingleFileSourceLocator { $realPath = $item->getRealPath(); if (!($item->isFile() && pathinfo($realPath, PATHINFO_EXTENSION) === 'php')) { return null; } return new \PHPStan\BetterReflection\SourceLocator\Type\SingleFileSourceLocator($realPath, $this->astLocator); }, iterator_to_array($this->fileSystemIterator)))))); } /** * {@inheritDoc} * * @throws InvalidFileLocation */ public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?\PHPStan\BetterReflection\Reflection\Reflection { return $this->getAggregatedSourceLocator()->locateIdentifier($reflector, $identifier); } /** * {@inheritDoc} * * @throws InvalidFileLocation */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return $this->getAggregatedSourceLocator()->locateIdentifiersByType($reflector, $identifierType); } } $directories directories to scan * * @throws InvalidDirectory * @throws InvalidFileInfo */ public function __construct(array $directories, Locator $astLocator) { $this->aggregateSourceLocator = new \PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator(array_map(static function (string $directory) use($astLocator) : \PHPStan\BetterReflection\SourceLocator\Type\FileIteratorSourceLocator { if (!is_dir($directory)) { throw InvalidDirectory::fromNonDirectory($directory); } return new \PHPStan\BetterReflection\SourceLocator\Type\FileIteratorSourceLocator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS)), $astLocator); }, $directories)); } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?\PHPStan\BetterReflection\Reflection\Reflection { return $this->aggregateSourceLocator->locateIdentifier($reflector, $identifier); } /** * {@inheritDoc} */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return $this->aggregateSourceLocator->locateIdentifiersByType($reflector, $identifierType); } } source = $source; parent::__construct($astLocator); } /** * {@inheritDoc} * * @throws InvalidArgumentException * @throws InvalidFileLocation */ protected function createLocatedSource(Identifier $identifier) : ?\PHPStan\BetterReflection\SourceLocator\Located\LocatedSource { return new LocatedSource($this->source, $identifier->getName(), null); } } astLocator()); $this->phpParser = $phpParser ?? $betterReflection->phpParser(); $this->constantVisitor = $this->createConstantVisitor(); $this->nodeTraverser = new NodeTraverser(); $this->nodeTraverser->addVisitor(new NameResolver()); $this->nodeTraverser->addVisitor($this->constantVisitor); } /** * {@inheritDoc} * * @throws InvalidArgumentException * @throws InvalidFileLocation */ protected function createLocatedSource(Identifier $identifier) : ?\PHPStan\BetterReflection\SourceLocator\Located\LocatedSource { $locatedData = $this->attemptAutoloadForIdentifier($identifier); if ($locatedData === null) { return null; } if (!is_file($locatedData['fileName'])) { return null; } if (strtolower($identifier->getName()) !== strtolower($locatedData['name'])) { return new AliasLocatedSource(file_get_contents($locatedData['fileName']), $locatedData['name'], $locatedData['fileName'], $identifier->getName()); } return new LocatedSource(file_get_contents($locatedData['fileName']), $identifier->getName(), $locatedData['fileName']); } /** * Attempts to locate the specified identifier. * * @return array{fileName: string, name: string}|null * * @throws ReflectionException */ private function attemptAutoloadForIdentifier(Identifier $identifier) : ?array { if ($identifier->isClass()) { return $this->locateClassByName($identifier->getName()); } if ($identifier->isFunction()) { return $this->locateFunctionByName($identifier->getName()); } if ($identifier->isConstant()) { return $this->locateConstantByName($identifier->getName()); } return null; } /** * Attempt to locate a class by name. * * If class already exists, simply use internal reflection API to get the * filename and store it. * * If class does not exist, we make an assumption that whatever autoloaders * that are registered will be loading a file. We then override the file:// * protocol stream wrapper to "capture" the filename we expect the class to * be in, and then restore it. Note that class_exists will cause an error * that it cannot find the file, so we squelch the errors by overriding the * error handler temporarily. * * Note: the following code is designed so that the first hit on an actual * **file** leads to a path being resolved. No actual autoloading nor * file reading should happen, and most certainly no other classes * should exist after execution. The only filesystem access is to * check whether the file exists. * * @return array{fileName: string, name: string}|null * * @throws ReflectionException */ private function locateClassByName(string $className) : ?array { if (ClassExistenceChecker::exists($className, \false)) { $classReflection = new ReflectionClass($className); $filename = $classReflection->getFileName(); if (!is_string($filename)) { return null; } return ['fileName' => $filename, 'name' => $classReflection->getName()]; } $this->silenceErrors(); try { $locatedFile = FileReadTrapStreamWrapper::withStreamWrapperOverride(static function () use($className) : ?string { foreach (spl_autoload_functions() as $preExistingAutoloader) { $preExistingAutoloader($className); /** * This static variable is populated by the side-effect of the stream wrapper * trying to read the file path when `include()` is used by an autoloader. * * This will not be `null` when the autoloader tried to read a file. */ if (FileReadTrapStreamWrapper::$autoloadLocatedFile !== null) { return FileReadTrapStreamWrapper::$autoloadLocatedFile; } } return null; }); if ($locatedFile === null) { return null; } return ['fileName' => $locatedFile, 'name' => $className]; } finally { restore_error_handler(); } } private function silenceErrors() : void { set_error_handler(static function () : bool { return \true; }); } /** * We can only load functions if they already exist, because PHP does not * have function autoloading. Therefore if it exists, we simply use the * internal reflection API to find the filename. If it doesn't we can do * nothing so throw an exception. * * @return array{fileName: string, name: string}|null * * @throws ReflectionException */ private function locateFunctionByName(string $functionName) : ?array { if (!function_exists($functionName)) { return null; } $reflectionFileName = (new ReflectionFunction($functionName))->getFileName(); if (!is_string($reflectionFileName)) { return null; } return ['fileName' => $reflectionFileName, 'name' => $functionName]; } /** * We can only load constants if they already exist, because PHP does not * have constant autoloading. Therefore if it exists, we simply use brute force * to search throughout all included files to find the right filename. * * @return array{fileName: string, name: string}|null */ private function locateConstantByName(string $constantName) : ?array { if (!defined($constantName)) { return null; } /** @var array|resource|null>> $constants */ $constants = get_defined_constants(\true); if (!array_key_exists($constantName, $constants['user'])) { return null; } /** @psalm-suppress UndefinedMethod */ $this->constantVisitor->setConstantName($constantName); $constantFileName = null; // Note: looking at files in reverse order, since newer files are more likely to have // defined a constant that is being looked up. Earlier files are possibly related // to libraries/frameworks that we rely upon. // @infection-ignore-all UnwrapArrayReverse: Ignore because the result is some with or without array_reverse() /** @phpstan-var non-empty-string $includedFileName */ foreach (array_reverse(get_included_files()) as $includedFileName) { try { FileChecker::assertReadableFile($includedFileName); } catch (InvalidFileLocation $exception) { continue; } /** @var list $ast */ $ast = $this->phpParser->parse(file_get_contents($includedFileName)); $this->nodeTraverser->traverse($ast); /** @psalm-suppress UndefinedMethod */ if ($this->constantVisitor->getNode() !== null) { $constantFileName = $includedFileName; break; } } if ($constantFileName === null) { return null; } return ['fileName' => $constantFileName, 'name' => $constantName]; } private function createConstantVisitor() : NodeVisitorAbstract { return new class extends NodeVisitorAbstract { /** * @var string|null */ private $constantName = null; /** * @var \PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall|null */ private $node = null; public function enterNode(Node $node) : ?int { if ($node instanceof Node\Stmt\Const_) { foreach ($node->consts as $constNode) { if ((($constNodeNamespacedName = $constNode->namespacedName) ? $constNodeNamespacedName->toString() : null) === $this->constantName) { $this->node = $node; return NodeTraverser::STOP_TRAVERSAL; } } return NodeTraverser::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Expr\FuncCall) { try { ConstantNodeChecker::assertValidDefineFunctionCall($node); } catch (InvalidConstantNode $exception) { return null; } $argumentNameNode = $node->args[0]; assert($argumentNameNode instanceof Node\Arg); $nameNode = $argumentNameNode->value; assert($nameNode instanceof Node\Scalar\String_); if ($nameNode->value === $this->constantName) { $this->node = $node; return NodeTraverser::STOP_TRAVERSAL; } } return null; } public function setConstantName(string $constantName) : void { $this->constantName = $constantName; } /** @return Node\Stmt\Const_|Node\Expr\FuncCall|null */ public function getNode() { return $this->node; } }; } } getClassesFromFile * (which loads all classes from specified file) */ class SingleFileSourceLocator extends \PHPStan\BetterReflection\SourceLocator\Type\AbstractSourceLocator { /** * @var non-empty-string */ private $fileName; /** * @param non-empty-string $fileName * * @throws InvalidFileLocation */ public function __construct(string $fileName, Locator $astLocator) { $this->fileName = $fileName; FileChecker::assertReadableFile($fileName); parent::__construct($astLocator); } /** * {@inheritDoc} * * @throws InvalidArgumentException * @throws InvalidFileLocation */ protected function createLocatedSource(Identifier $identifier) : ?\PHPStan\BetterReflection\SourceLocator\Located\LocatedSource { return new LocatedSource(file_get_contents($this->fileName), $identifier->getName(), $this->fileName); } } indexed by reflector key and identifier cache key */ private $cacheByIdentifierKeyAndOid = []; /** @var array> indexed by reflector key and identifier type cache key */ private $cacheByIdentifierTypeKeyAndOid = []; /** * @var \PHPStan\BetterReflection\SourceLocator\Type\SourceLocator */ private $wrappedSourceLocator; public function __construct(\PHPStan\BetterReflection\SourceLocator\Type\SourceLocator $wrappedSourceLocator) { $this->wrappedSourceLocator = $wrappedSourceLocator; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?\PHPStan\BetterReflection\Reflection\Reflection { $cacheKey = sprintf('%s_%s', $this->reflectorCacheKey($reflector), $this->identifierToCacheKey($identifier)); if (array_key_exists($cacheKey, $this->cacheByIdentifierKeyAndOid)) { return $this->cacheByIdentifierKeyAndOid[$cacheKey]; } return $this->cacheByIdentifierKeyAndOid[$cacheKey] = $this->wrappedSourceLocator->locateIdentifier($reflector, $identifier); } /** @return list */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { $cacheKey = sprintf('%s_%s', $this->reflectorCacheKey($reflector), $this->identifierTypeToCacheKey($identifierType)); if (array_key_exists($cacheKey, $this->cacheByIdentifierTypeKeyAndOid)) { return $this->cacheByIdentifierTypeKeyAndOid[$cacheKey]; } return $this->cacheByIdentifierTypeKeyAndOid[$cacheKey] = $this->wrappedSourceLocator->locateIdentifiersByType($reflector, $identifierType); } private function reflectorCacheKey(Reflector $reflector) : string { return sprintf('type:%s#oid:%d', \get_class($reflector), spl_object_id($reflector)); } private function identifierToCacheKey(Identifier $identifier) : string { return sprintf('%s#name:%s', $this->identifierTypeToCacheKey($identifier->getType()), $identifier->getName()); } private function identifierTypeToCacheKey(IdentifierType $identifierType) : string { return sprintf('type:%s', $identifierType->getName()); } } */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array; } */ private $sourceLocators = []; /** @param list $sourceLocators */ public function __construct(array $sourceLocators = []) { $this->sourceLocators = $sourceLocators; } public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?\PHPStan\BetterReflection\Reflection\Reflection { foreach ($this->sourceLocators as $sourceLocator) { $located = $sourceLocator->locateIdentifier($reflector, $identifier); if ($located) { return $located; } } return null; } /** * {@inheritDoc} */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return array_merge([], ...array_map(static function (\PHPStan\BetterReflection\SourceLocator\Type\SourceLocator $sourceLocator) use($reflector, $identifierType) : array { return $sourceLocator->locateIdentifiersByType($reflector, $identifierType); }, $this->sourceLocators)); } } |null */ private static $registeredStreamWrapperProtocols = null; /** * Read this property to determine the last file on which reads were attempted * * @psalm-readonly * @psalm-allow-private-mutation * @var string|null */ public static $autoloadLocatedFile = null; /** @var resource */ public $context; /** * @param callable() : ExecutedMethodReturnType $executeMeWithinStreamWrapperOverride * @param list $streamWrapperProtocols * * @psalm-return ExecutedMethodReturnType * * @psalm-template ExecutedMethodReturnType of mixed * @return mixed */ public static function withStreamWrapperOverride(callable $executeMeWithinStreamWrapperOverride, array $streamWrapperProtocols = self::DEFAULT_STREAM_WRAPPER_PROTOCOLS) { self::$registeredStreamWrapperProtocols = $streamWrapperProtocols; self::$autoloadLocatedFile = null; try { foreach ($streamWrapperProtocols as $protocol) { stream_wrapper_unregister($protocol); stream_wrapper_register($protocol, self::class); } $result = $executeMeWithinStreamWrapperOverride(); } finally { foreach ($streamWrapperProtocols as $protocol) { @stream_wrapper_restore($protocol); } self::$registeredStreamWrapperProtocols = null; self::$autoloadLocatedFile = null; } return $result; } /** * Our wrapper simply records which file we tried to load and returns * boolean false indicating failure. * * @internal do not call this method directly! This is stream wrapper * voodoo logic that you **DO NOT** want to touch! * * @see https://php.net/manual/en/class.streamwrapper.php * @see https://php.net/manual/en/streamwrapper.stream-open.php * * @param string $path * @param string $mode * @param int $options * @param string $opened_path */ public function stream_open($path, $mode, $options, &$opened_path) : bool { self::$autoloadLocatedFile = $path; // @infection-ignore-all FalseValue return \false; } /** * url_stat is triggered by calls like "file_exists". The call to "file_exists" must not be overloaded. * This function restores the original "file" stream, issues a call to "stat" to get the real results, * and then re-registers the AutoloadSourceLocator stream wrapper. * * @internal do not call this method directly! This is stream wrapper * voodoo logic that you **DO NOT** want to touch! * * @see https://php.net/manual/en/class.streamwrapper.php * @see https://php.net/manual/en/streamwrapper.url-stat.php * * @param string $path * @param int $flags * * @return mixed[]|bool */ public function url_stat($path, $flags) { if (self::$registeredStreamWrapperProtocols === null) { throw new LogicException(sprintf('%s not registered: cannot operate. Do not call this method directly.', self::class)); } foreach (self::$registeredStreamWrapperProtocols as $protocol) { stream_wrapper_restore($protocol); } if (($flags & STREAM_URL_STAT_QUIET) === STREAM_URL_STAT_QUIET) { $result = @stat($path); } else { $result = stat($path); } foreach (self::$registeredStreamWrapperProtocols as $protocol) { stream_wrapper_unregister($protocol); stream_wrapper_register($protocol, self::class); } return $result; } } parser = $parser; $this->coreFunctionReflection = new CoreFunctionReflection($closure); } /** * {@inheritDoc} * * @throws ParseToAstFailure */ public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?\PHPStan\BetterReflection\Reflection\Reflection { return $this->getReflectionFunction($reflector, $identifier->getType()); } /** * {@inheritDoc} * * @throws ParseToAstFailure */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return array_filter([$this->getReflectionFunction($reflector, $identifierType)]); } private function getReflectionFunction(Reflector $reflector, IdentifierType $identifierType) : ?\PHPStan\BetterReflection\Reflection\ReflectionFunction { if (!$identifierType->isFunction()) { return null; } /** @phpstan-var non-empty-string $fileName */ $fileName = $this->coreFunctionReflection->getFileName(); if (strpos($fileName, 'eval()\'d code') !== \false) { throw EvaledClosureCannotBeLocated::create(); } FileChecker::assertReadableFile($fileName); $fileName = FileHelper::normalizeWindowsPath($fileName); $nodeVisitor = new class($fileName, $this->coreFunctionReflection->getStartLine()) extends NodeVisitorAbstract { /** @var list */ private $closureNodes = []; /** * @var \PhpParser\Node\Stmt\Namespace_|null */ private $currentNamespace = null; /** * @var string */ private $fileName; /** * @var int */ private $startLine; public function __construct(string $fileName, int $startLine) { $this->fileName = $fileName; $this->startLine = $startLine; } /** * {@inheritDoc} */ public function enterNode(Node $node) { if ($node instanceof Namespace_) { $this->currentNamespace = $node; return null; } if ($node->getStartLine() === $this->startLine && ($node instanceof Node\Expr\Closure || $node instanceof Node\Expr\ArrowFunction)) { $this->closureNodes[] = ['node' => $node, 'namespace' => $this->currentNamespace]; } return null; } /** * {@inheritDoc} */ public function leaveNode(Node $node) { if (!$node instanceof Namespace_) { return null; } $this->currentNamespace = null; return null; } /** * @return array{node: Node\Expr\Closure|Node\Expr\ArrowFunction, namespace: Namespace_|null} * * @throws NoClosureOnLine * @throws TwoClosuresOnSameLine */ public function getClosureNodes() : array { if ($this->closureNodes === []) { throw NoClosureOnLine::create($this->fileName, $this->startLine); } if (isset($this->closureNodes[1])) { throw TwoClosuresOnSameLine::create($this->fileName, $this->startLine); } return $this->closureNodes[0]; } }; $fileContents = file_get_contents($fileName); /** @var list $ast */ $ast = $this->parser->parse($fileContents); $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor(new NameResolver()); $nodeTraverser->addVisitor($nodeVisitor); $nodeTraverser->traverse($ast); $closureNodes = $nodeVisitor->getClosureNodes(); $reflectionFunction = (new NodeToReflection())->__invoke($reflector, $closureNodes['node'], new AnonymousLocatedSource($fileContents, $fileName), $closureNodes['namespace']); assert($reflectionFunction instanceof ReflectionFunction); return $reflectionFunction; } } parser = $parser; $this->coreClassReflection = new CoreReflectionClass($anonymousClassObject); } /** * {@inheritDoc} * * @throws ParseToAstFailure */ public function locateIdentifier(Reflector $reflector, Identifier $identifier) : ?\PHPStan\BetterReflection\Reflection\Reflection { return $this->getReflectionClass($reflector, $identifier->getType()); } /** * {@inheritDoc} * * @throws ParseToAstFailure */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType) : array { return array_filter([$this->getReflectionClass($reflector, $identifierType)]); } private function getReflectionClass(Reflector $reflector, IdentifierType $identifierType) : ?\PHPStan\BetterReflection\Reflection\ReflectionClass { if (!$identifierType->isClass()) { return null; } if (!$this->coreClassReflection->isAnonymous()) { return null; } /** @phpstan-var non-empty-string $fileName */ $fileName = $this->coreClassReflection->getFileName(); if (strpos($fileName, 'eval()\'d code') !== \false) { throw EvaledAnonymousClassCannotBeLocated::create(); } FileChecker::assertReadableFile($fileName); $fileName = FileHelper::normalizeWindowsPath($fileName); $nodeVisitor = new class($fileName, $this->coreClassReflection->getStartLine()) extends NodeVisitorAbstract { /** @var list */ private $anonymousClassNodes = []; /** * @var string */ private $fileName; /** * @var int */ private $startLine; public function __construct(string $fileName, int $startLine) { $this->fileName = $fileName; $this->startLine = $startLine; } /** * {@inheritDoc} */ public function enterNode(Node $node) { if (!$node instanceof Node\Stmt\Class_ || $node->name !== null || $node->getLine() !== $this->startLine) { return null; } $this->anonymousClassNodes[] = $node; return null; } public function getAnonymousClassNode() : Class_ { if ($this->anonymousClassNodes === []) { throw NoAnonymousClassOnLine::create($this->fileName, $this->startLine); } if (isset($this->anonymousClassNodes[1])) { throw TwoAnonymousClassesOnSameLine::create($this->fileName, $this->startLine); } return $this->anonymousClassNodes[0]; } }; $fileContents = file_get_contents($fileName); /** @var list $ast */ $ast = $this->parser->parse($fileContents); $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor(new NameResolver()); $nodeTraverser->addVisitor($nodeVisitor); $nodeTraverser->traverse($ast); $reflectionClass = (new NodeToReflection())->__invoke($reflector, $nodeVisitor->getAnonymousClassNode(), new AnonymousLocatedSource($fileContents, $fileName), null); assert($reflectionClass instanceof ReflectionClass); return $reflectionClass; } } stubber = $stubber; parent::__construct($astLocator); } /** * {@inheritDoc} * * @throws InvalidArgumentException * @throws InvalidFileLocation */ protected function createLocatedSource(Identifier $identifier) : ?\PHPStan\BetterReflection\SourceLocator\Located\LocatedSource { $classReflection = $this->getInternalReflectionClass($identifier); if ($classReflection === null) { return null; } $stubData = $this->stubber->generateClassStub($classReflection->getName()); if ($stubData === null) { return null; } return new EvaledLocatedSource($stubData->getStub(), $classReflection->getName()); } private function getInternalReflectionClass(Identifier $identifier) : ?\ReflectionClass { if (!$identifier->isClass()) { return null; } /** @psalm-var class-string|trait-string $name */ $name = $identifier->getName(); if (!ClassExistenceChecker::exists($name, \false)) { return null; // not an available internal class } $reflection = new ReflectionClass($name); $sourceFile = $reflection->getFileName(); return $sourceFile !== \false && is_file($sourceFile) ? null : $reflection; } } stubber = $stubber; parent::__construct($astLocator); } /** * {@inheritDoc} * * @throws InvalidArgumentException * @throws InvalidFileLocation */ protected function createLocatedSource(Identifier $identifier) : ?\PHPStan\BetterReflection\SourceLocator\Located\LocatedSource { return $this->getClassSource($identifier) ?? $this->getFunctionSource($identifier) ?? $this->getConstantSource($identifier); } private function getClassSource(Identifier $identifier) : ?\PHPStan\BetterReflection\SourceLocator\Located\InternalLocatedSource { if (!$identifier->isClass()) { return null; } /** @psalm-var class-string|trait-string $className */ $className = $identifier->getName(); return $this->createLocatedSourceFromStubData($identifier, $this->stubber->generateClassStub($className)); } private function getFunctionSource(Identifier $identifier) : ?\PHPStan\BetterReflection\SourceLocator\Located\InternalLocatedSource { if (!$identifier->isFunction()) { return null; } return $this->createLocatedSourceFromStubData($identifier, $this->stubber->generateFunctionStub($identifier->getName())); } private function getConstantSource(Identifier $identifier) : ?\PHPStan\BetterReflection\SourceLocator\Located\InternalLocatedSource { if (!$identifier->isConstant()) { return null; } return $this->createLocatedSourceFromStubData($identifier, $this->stubber->generateConstantStub($identifier->getName())); } private function createLocatedSourceFromStubData(Identifier $identifier, ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData $stubData) : ?\PHPStan\BetterReflection\SourceLocator\Located\InternalLocatedSource { if ($stubData === null) { return null; } $extensionName = $stubData->getExtensionName(); if ($extensionName === null) { // Not internal return null; } return new InternalLocatedSource($stubData->getStub(), $identifier->getName(), $extensionName, $stubData->getFileName()); } } aliasName = $aliasName; parent::__construct($source, $name, $filename); } public function getAliasName() : ?string { return $this->aliasName; } } source = $source; $this->name = $name; if ($filename !== null) { assert($filename !== ''); $filename = FileHelper::normalizeWindowsPath($filename); } $this->filename = $filename; } public function getSource() : string { return $this->source; } public function getName() : ?string { return $this->name; } /** @return non-empty-string|null */ public function getFileName() : ?string { return $this->filename; } /** * Is the located source in PHP internals? */ public function isInternal() : bool { return \false; } /** @return non-empty-string|null */ public function getExtensionName() : ?string { return null; } /** * Is the located source produced by eval() or \function_create()? */ public function isEvaled() : bool { return \false; } public function getAliasName() : ?string { return null; } } extensionName = $extensionName; parent::__construct($source, $name, $fileName); } public function isInternal() : bool { return \true; } /** @return non-empty-string|null */ public function getExtensionName() : ?string { return $this->extensionName; } } phpVersion = $phpVersion; $this->builderFactory = new BuilderFactory(); $this->prettyPrinter = $prettyPrinter; } /** @param class-string|trait-string $className */ public function generateClassStub(string $className) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { if (!ClassExistenceChecker::exists($className, \false)) { return null; } $enumExists = function (string $enum, bool $autoload = \true) : bool { if (function_exists('enum_exists')) { return \enum_exists($enum, $autoload); } return $autoload && \class_exists($enum) && \false; }; /** phpcs:disable SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName */ $isEnum = function_exists('enum_exists') && $enumExists($className, \false); /** phpcs:enable */ $classReflection = $isEnum ? new CoreReflectionEnum($className) : new CoreReflectionClass($className); $classNode = $this->createClass($classReflection); if ($classNode instanceof Class_) { $this->addClassModifiers($classNode, $classReflection); } if ($classNode instanceof Class_ || $classNode instanceof Interface_ || $classNode instanceof Enum_) { $this->addExtendsAndImplements($classNode, $classReflection); } if ($classNode instanceof Class_ || $classNode instanceof Trait_) { $this->addProperties($classNode, $classReflection); } if ($classNode instanceof Class_ || $classNode instanceof Trait_ || $classNode instanceof Enum_) { $this->addTraitUse($classNode, $classReflection); } $this->addAttributes($classNode, $classReflection); $this->addDocComment($classNode, $classReflection); if ($classNode instanceof Enum_ && $classReflection instanceof CoreReflectionEnum) { $this->addEnumBackingType($classNode, $classReflection); $this->addEnumCases($classNode, $classReflection); } $this->addClassConstants($classNode, $classReflection); $this->addMethods($classNode, $classReflection); $node = $classNode->getNode(); $stub = $classReflection->inNamespace() ? $this->generateStubInNamespace($node, $classReflection->getNamespaceName()) : $this->generateStub($node); $extensionName = ($getExtension = $classReflection->getExtension()) ? $getExtension->getName() : null; assert(is_string($extensionName) && $extensionName !== '' || $extensionName === null); return $this->createStubData($stub, $extensionName, $classReflection->getFileName() !== \false ? $classReflection->getFileName() : null); } public function generateFunctionStub(string $functionName) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { if (!function_exists($functionName)) { return null; } return $this->generateFunctionStubFromReflection(new CoreReflectionFunction($functionName)); } public function generateFunctionStubFromReflection(CoreReflectionFunction $functionReflection) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { $shortName = $functionReflection->getShortName(); if ($functionReflection->isClosure()) { $shortName = '{closure}'; } $functionNode = $this->builderFactory->function($shortName); $this->addAttributes($functionNode, $functionReflection); $this->addDocComment($functionNode, $functionReflection); $this->addParameters($functionNode, $functionReflection); $returnType = $functionReflection->getReturnType(); if ($returnType === null && method_exists($functionReflection, 'getTentativeReturnType')) { $returnType = $functionReflection->getTentativeReturnType(); } if ($returnType !== null) { assert($returnType instanceof CoreReflectionNamedType || $returnType instanceof CoreReflectionUnionType || $returnType instanceof CoreReflectionIntersectionType); $functionNode->setReturnType($this->formatType($returnType)); } $extensionName = ($getExtension = $functionReflection->getExtension()) ? $getExtension->getName() : null; assert(is_string($extensionName) && $extensionName !== '' || $extensionName === null); if (!$functionReflection->inNamespace() || $functionReflection->isClosure()) { return $this->createStubData($this->generateStub($functionNode->getNode()), $extensionName, $functionReflection->getFileName() !== \false ? $functionReflection->getFileName() : null); } return $this->createStubData($this->generateStubInNamespace($functionNode->getNode(), $functionReflection->getNamespaceName()), $extensionName, $functionReflection->getFileName() !== \false ? $functionReflection->getFileName() : null); } public function generateConstantStub(string $constantName) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { $constantData = $this->findConstantData($constantName); if ($constantData === null) { return null; } [$constantValue, $extensionName] = $constantData; if ($extensionName === null) { return null; } if (is_resource($constantValue)) { $constantValue = $this->builderFactory->funcCall('constant', [$constantName]); } $constantNode = $this->builderFactory->funcCall('define', [$constantName, $constantValue]); return $this->createStubData($this->generateStub($constantNode), $extensionName, null); } /** @return array{0: scalar|list|resource|null, 1: non-empty-string|null}|null */ private function findConstantData(string $constantName) { /** @var array|resource|null>> $constants */ $constants = get_defined_constants(\true); foreach ($constants as $constantExtensionName => $extensionConstants) { if (array_key_exists($constantName, $extensionConstants)) { return [$extensionConstants[$constantName], $constantExtensionName !== 'user' ? $constantExtensionName : null]; } } return null; } /** * @return \PhpParser\Builder\Class_|\PhpParser\Builder\Interface_|\PhpParser\Builder\Trait_|\PhpParser\Builder\Enum_ */ private function createClass(CoreReflectionClass $classReflection) { if ($classReflection instanceof CoreReflectionEnum) { return $this->builderFactory->enum($classReflection->getShortName()); } if ($classReflection->isTrait()) { return $this->builderFactory->trait($classReflection->getShortName()); } if ($classReflection->isInterface()) { return $this->builderFactory->interface($classReflection->getShortName()); } return $this->builderFactory->class($classReflection->getShortName()); } /** * @param \PhpParser\Builder\Class_|\PhpParser\Builder\Interface_|\PhpParser\Builder\Trait_|\PhpParser\Builder\Enum_|\PhpParser\Builder\ClassConst|\PhpParser\Builder\EnumCase|\PhpParser\Builder\Method|\PhpParser\Builder\Property|\PhpParser\Builder\Function_|\PhpParser\Builder\Param $node * @param CoreReflectionClass|CoreReflectionClassConstant|CoreReflectionEnumUnitCase|CoreReflectionMethod|CoreReflectionProperty|CoreReflectionFunction|CoreReflectionParameter $reflection */ private function addAttributes($node, $reflection) : void { if (!method_exists($reflection, 'getAttributes')) { return; } $attributeReflections = $reflection->getAttributes(); if ($attributeReflections === []) { return; } foreach ($attributeReflections as $attributeReflection) { $node->addAttribute($this->builderFactory->attribute(new FullyQualified($attributeReflection->getName()), $attributeReflection->getArguments())); } } /** * @param \PhpParser\Builder\Class_|\PhpParser\Builder\Interface_|\PhpParser\Builder\Trait_|\PhpParser\Builder\Enum_|\PhpParser\Builder\Method|\PhpParser\Builder\Property|\PhpParser\Builder\Function_ $node * @param CoreReflectionClass|CoreReflectionMethod|CoreReflectionProperty|CoreReflectionFunction $reflection */ private function addDocComment($node, $reflection) : void { $docComment = $reflection->getDocComment() !== \false ? $reflection->getDocComment() : ''; $annotations = []; if (($reflection instanceof CoreReflectionMethod || $reflection instanceof CoreReflectionFunction) && $reflection->isInternal()) { if ($reflection->isDeprecated()) { $annotations[] = '@deprecated'; } if (method_exists($reflection, 'hasTentativeReturnType') && $reflection->hasTentativeReturnType()) { $annotations[] = sprintf('@%s', AnnotationHelper::TENTATIVE_RETURN_TYPE_ANNOTATION); } } if ($docComment === '' && $annotations === []) { return; } if ($docComment === '') { $docComment = sprintf("/**\n* %s\n*/", implode("\n *", $annotations)); } elseif ($annotations !== []) { $docComment = preg_replace('~\\s+\\*/$~', sprintf("\n* %s\n*/", implode("\n *", $annotations)), $docComment); } $node->setDocComment(new Doc($docComment)); } private function addEnumBackingType(Enum_ $enumNode, CoreReflectionEnum $enumReflection) : void { if (!$enumReflection->isBacked()) { return; } $backingType = $enumReflection->getBackingType(); assert($backingType instanceof CoreReflectionNamedType); $enumNode->setScalarType($backingType->getName()); } private function addClassModifiers(Class_ $classNode, CoreReflectionClass $classReflection) : void { if (!$classReflection->isInterface() && $classReflection->isAbstract()) { // Interface \Iterator is interface and abstract $classNode->makeAbstract(); } if (!$classReflection->isFinal()) { return; } $classNode->makeFinal(); } /** * @param \PhpParser\Builder\Class_|\PhpParser\Builder\Interface_|\PhpParser\Builder\Enum_ $classNode */ private function addExtendsAndImplements($classNode, CoreReflectionClass $classReflection) : void { $interfaces = $classReflection->getInterfaceNames(); if ($classNode instanceof Class_ || $classNode instanceof Interface_) { $parentClass = $classReflection->getParentClass(); if ($parentClass !== \false) { $classNode->extend(new FullyQualified($parentClass->getName())); $interfaces = array_diff($interfaces, $parentClass->getInterfaceNames()); } } foreach ($classReflection->getInterfaces() as $interface) { $interfaces = array_diff($interfaces, $interface->getInterfaceNames()); } foreach ($interfaces as $interfaceName) { if (method_exists($classReflection, 'isEnum') && $classReflection->isEnum() && in_array($interfaceName, [BackedEnum::class, UnitEnum::class], \true)) { continue; } $interfaceNode = new FullyQualified($interfaceName); if ($classNode instanceof Interface_) { $classNode->extend($interfaceNode); } else { $classNode->implement($interfaceNode); } } } /** * @param \PhpParser\Builder\Class_|\PhpParser\Builder\Trait_|\PhpParser\Builder\Enum_ $classNode */ private function addTraitUse($classNode, CoreReflectionClass $classReflection) : void { /** @var array $traitAliases */ $traitAliases = $classReflection->getTraitAliases(); $traitUseAdaptations = []; foreach ($traitAliases as $methodNameAlias => $methodInfo) { [$traitName, $methodName] = explode('::', $methodInfo); $traitUseAdaptation = $this->builderFactory->traitUseAdaptation(new FullyQualified($traitName), $methodName); $traitUseAdaptation->as($methodNameAlias); $traitUseAdaptations[$traitName] = $traitUseAdaptation; } foreach ($classReflection->getTraitNames() as $traitName) { $traitUse = $this->builderFactory->useTrait(new FullyQualified($traitName)); if (array_key_exists($traitName, $traitUseAdaptations)) { $traitUse->with($traitUseAdaptations[$traitName]); } $classNode->addStmt($traitUse); } } /** * @param \PhpParser\Builder\Class_|\PhpParser\Builder\Trait_ $classNode */ private function addProperties($classNode, CoreReflectionClass $classReflection) : void { foreach ($classReflection->getProperties() as $propertyReflection) { if (!$this->isPropertyDeclaredInClass($propertyReflection, $classReflection)) { continue; } $propertyNode = $this->builderFactory->property($propertyReflection->getName()); $this->addPropertyModifiers($propertyNode, $propertyReflection); $this->addAttributes($propertyNode, $propertyReflection); $this->addDocComment($propertyNode, $propertyReflection); if (method_exists($propertyReflection, 'hasDefaultValue') && $propertyReflection->hasDefaultValue()) { try { $propertyNode->setDefault($propertyReflection->getDeclaringClass()->getDefaultProperties()[$propertyReflection->getName()] ?? null); } catch (LogicException $exception) { // Nothing } } if ($this->phpVersion >= 70400) { $propertyType = method_exists($propertyReflection, 'getType') ? method_exists($propertyReflection, 'getType') ? $propertyReflection->getType() : null : null; if ($propertyType !== null) { assert($propertyType instanceof CoreReflectionNamedType || $propertyType instanceof CoreReflectionUnionType || $propertyType instanceof CoreReflectionIntersectionType); $propertyNode->setType($this->formatType($propertyType)); } } $classNode->addStmt($propertyNode); } } private function isPropertyDeclaredInClass(CoreReflectionProperty $propertyReflection, CoreReflectionClass $classReflection) : bool { if ($propertyReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { return \false; } foreach ($classReflection->getTraits() as $trait) { if ($trait->hasProperty($propertyReflection->getName())) { return \false; } } return \true; } private function addPropertyModifiers(Property $propertyNode, CoreReflectionProperty $propertyReflection) : void { if ($this->phpVersion >= 80100) { if (method_exists($propertyReflection, 'isReadOnly') && $propertyReflection->isReadOnly()) { $propertyNode->makeReadonly(); } } if ($propertyReflection->isStatic()) { $propertyNode->makeStatic(); } if ($propertyReflection->isPublic()) { $propertyNode->makePublic(); } elseif ($propertyReflection->isProtected()) { $propertyNode->makeProtected(); } else { $propertyNode->makePrivate(); } } private function addEnumCases(Enum_ $enumNode, CoreReflectionEnum $enumReflection) : void { foreach ($enumReflection->getCases() as $enumCaseReflection) { $enumCaseNode = $this->builderFactory->enumCase($enumCaseReflection->getName()); $this->addAttributes($enumCaseNode, $enumCaseReflection); if ($enumCaseReflection instanceof CoreReflectionEnumBackedCase) { $enumCaseNode->setValue($enumCaseReflection->getBackingValue()); } $enumNode->addStmt($enumCaseNode); } } /** * @param \PhpParser\Builder\Class_|\PhpParser\Builder\Interface_|\PhpParser\Builder\Trait_|\PhpParser\Builder\Enum_ $classNode */ private function addClassConstants($classNode, CoreReflectionClass $classReflection) : void { foreach ($classReflection->getReflectionConstants() as $constantReflection) { if (method_exists($constantReflection, 'isEnumCase') && $constantReflection->isEnumCase()) { continue; } if ($constantReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { continue; } $classConstantNode = $this->builderFactory->classConst($constantReflection->getName(), $constantReflection->getValue()); if (method_exists($constantReflection, 'getType')) { $constantType = $constantReflection->getType(); if ($constantType !== null) { assert($constantType instanceof CoreReflectionNamedType || $constantType instanceof CoreReflectionUnionType || $constantType instanceof CoreReflectionIntersectionType); $classConstantNode->setType($this->formatType($constantType)); } } $this->addAttributes($classConstantNode, $constantReflection); if ($constantReflection->getDocComment() !== \false) { $classConstantNode->setDocComment(new Doc($constantReflection->getDocComment())); } $this->addClassConstantModifiers($classConstantNode, $constantReflection); $classNode->addStmt($classConstantNode); } } private function addClassConstantModifiers(ClassConst $classConstantNode, CoreReflectionClassConstant $classConstantReflection) : void { if (method_exists($classConstantReflection, 'isFinal') && $classConstantReflection->isFinal()) { $classConstantNode->makeFinal(); } if ($classConstantReflection->isPrivate()) { $classConstantNode->makePrivate(); } elseif ($classConstantReflection->isProtected()) { $classConstantNode->makeProtected(); } else { $classConstantNode->makePublic(); } } /** * @param \PhpParser\Builder\Class_|\PhpParser\Builder\Interface_|\PhpParser\Builder\Trait_|\PhpParser\Builder\Enum_ $classNode */ private function addMethods($classNode, CoreReflectionClass $classReflection) : void { foreach ($classReflection->getMethods() as $methodReflection) { if (!$this->isMethodDeclaredInClass($methodReflection, $classReflection)) { continue; } $methodNode = $this->builderFactory->method($methodReflection->getName()); $this->addMethodFlags($methodNode, $methodReflection); $this->addAttributes($methodNode, $methodReflection); $this->addDocComment($methodNode, $methodReflection); $this->addParameters($methodNode, $methodReflection); $returnType = $methodReflection->getReturnType(); if ($returnType === null && method_exists($methodReflection, 'getTentativeReturnType')) { $returnType = $methodReflection->getTentativeReturnType(); } if ($returnType !== null) { assert($returnType instanceof CoreReflectionNamedType || $returnType instanceof CoreReflectionUnionType || $returnType instanceof CoreReflectionIntersectionType); $methodNode->setReturnType($this->formatType($returnType)); } $classNode->addStmt($methodNode); } } private function isMethodDeclaredInClass(CoreReflectionMethod $methodReflection, CoreReflectionClass $classReflection) : bool { if ($methodReflection->getDeclaringClass()->getName() !== $classReflection->getName()) { return \false; } $methodName = $methodReflection->getName(); /** @var array $traitAliases */ $traitAliases = $classReflection->getTraitAliases(); if (array_key_exists($methodName, $traitAliases)) { return \false; } foreach ($classReflection->getTraits() as $trait) { if ($trait->hasMethod($methodName)) { return \false; } } if ($classReflection instanceof CoreReflectionEnum) { if ($methodName === 'cases') { return \false; } if ($classReflection->isBacked() && in_array($methodName, ['from', 'tryFrom'], \true)) { return \false; } } return \true; } private function addMethodFlags(Method $methodNode, CoreReflectionMethod $methodReflection) : void { if ($methodReflection->isFinal()) { $methodNode->makeFinal(); } if ($methodReflection->isAbstract() && !$methodReflection->getDeclaringClass()->isInterface()) { $methodNode->makeAbstract(); } if ($methodReflection->isStatic()) { $methodNode->makeStatic(); } if ($methodReflection->isPublic()) { $methodNode->makePublic(); } if ($methodReflection->isProtected()) { $methodNode->makeProtected(); } if ($methodReflection->isPrivate()) { $methodNode->makePrivate(); } if (!$methodReflection->returnsReference()) { return; } $methodNode->makeReturnByRef(); } private function addParameters(FunctionLike $functionNode, CoreReflectionFunctionAbstract $functionReflectionAbstract) : void { foreach ($functionReflectionAbstract->getParameters() as $parameterReflection) { $parameterNode = $this->builderFactory->param($parameterReflection->getName()); $this->addParameterModifiers($parameterReflection, $parameterNode); $this->setParameterDefaultValue($parameterReflection, $parameterNode); $this->addAttributes($parameterNode, $parameterReflection); $functionNode->addParam($parameterNode); } } private function addParameterModifiers(CoreReflectionParameter $parameterReflection, Param $parameterNode) : void { if ($parameterReflection->isVariadic()) { $parameterNode->makeVariadic(); } if ($parameterReflection->isPassedByReference()) { $parameterNode->makeByRef(); } $parameterType = $parameterReflection->getType(); if ($parameterType === null) { return; } assert($parameterType instanceof CoreReflectionNamedType || $parameterType instanceof CoreReflectionUnionType || $parameterType instanceof CoreReflectionIntersectionType); $parameterNode->setType($this->formatType($parameterType)); } private function setParameterDefaultValue(CoreReflectionParameter $parameterReflection, Param $parameterNode) : void { if (!$parameterReflection->isOptional()) { return; } if ($parameterReflection->isVariadic()) { return; } if (!$parameterReflection->isDefaultValueAvailable()) { if ($parameterReflection->allowsNull()) { $parameterNode->setDefault(null); } else { $parameterNode->setDefault(new Node\Expr\ConstFetch(new FullyQualified('UNKNOWN'))); } return; } $defaultValue = $parameterReflection->getDefaultValue(); if (is_object($defaultValue)) { $className = get_class($defaultValue); $enumExists = function (string $enum, bool $autoload = \true) : bool { if (function_exists('enum_exists')) { return \enum_exists($enum, $autoload); } return $autoload && \class_exists($enum) && \false; }; $isEnum = function_exists('enum_exists') && $enumExists($className, \false); if ($isEnum) { $parameterNode->setDefault(new Node\Expr\ClassConstFetch(new FullyQualified($className), new Node\Identifier($defaultValue->name))); return; } if ($this->phpVersion >= 80100) { $parameterNode->setDefault(new Node\Expr\New_(new FullyQualified($className))); } else { $parameterNode->setDefault(new Node\Expr\ConstFetch(new Name('null'))); } return; } $parameterNode->setDefault($defaultValue); } /** * @return \PhpParser\Node\Name|\PhpParser\Node\NullableType|\PhpParser\Node\UnionType|\PhpParser\Node\IntersectionType */ private function formatType(CoreReflectionType $type) { if ($type instanceof CoreReflectionIntersectionType) { /** @var list $types */ $types = $this->formatTypes($type->getTypes()); if ($this->phpVersion >= 80100) { return new IntersectionType($types); } return $types[0]; } if ($type instanceof CoreReflectionUnionType) { /** @var list $types */ $types = $this->formatTypes($type->getTypes()); if ($this->phpVersion >= 80200) { return new UnionType($types); } if ($this->phpVersion < 80000) { return $types[0]; } $intersectionTypes = []; $otherNames = []; foreach ($types as $type) { if ($type instanceof IntersectionType) { $intersectionTypes[] = $type; continue; } $otherNames[] = $type; } if ($this->phpVersion >= 80100) { if (\count($intersectionTypes) > 0) { return $intersectionTypes[0]; } } if (\count($otherNames) > 1) { return new UnionType($otherNames); } if (\count($otherNames) > 0) { return $otherNames[0]; } return new Name('null'); } assert($type instanceof CoreReflectionNamedType); $name = $type->getName(); $nameNode = $this->formatNamedType($type); if (!$type->allowsNull() || $name === 'mixed' || $name === 'null') { return $nameNode; } return new NullableType($nameNode); } /** * @param list $types * * @return list */ private function formatTypes(array $types) : array { return array_map(function (CoreReflectionType $type) { $formattedType = $this->formatType($type); assert($formattedType instanceof Name || $formattedType instanceof UnionType || $formattedType instanceof IntersectionType); return $formattedType; }, $types); } private function formatNamedType(CoreReflectionNamedType $type) : Name { $name = $type->getName(); return $type->isBuiltin() || in_array($name, ['self', 'parent', 'static'], \true) ? new Name($name) : new FullyQualified($name); } private function generateStubInNamespace(Node $node, string $namespaceName) : string { $namespaceBuilder = $this->builderFactory->namespace($namespaceName); $namespaceBuilder->addStmt($node); return $this->generateStub($namespaceBuilder->getNode()); } private function generateStub(Node $node) : string { return sprintf("prettyPrinter->prettyPrint([$node]), $node instanceof Node\Expr\FuncCall ? ';' : ''); } /** @param non-empty-string|null $extensionName */ private function createStubData(string $stub, ?string $extensionName, ?string $fileName) : \PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { return new \PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData($stub, $extensionName, $fileName); } } */ private $classNodes = []; /** @var array> */ private $functionNodes = []; /** @var array */ private $constantNodes = []; /** * @var \PhpParser\BuilderFactory */ private $builderFactory; public function __construct(BuilderFactory $builderFactory) { $this->builderFactory = $builderFactory; } public function enterNode(Node $node) : ?int { if ($node instanceof Node\Stmt\Namespace_) { $this->currentNamespace = $node; return null; } if ($node instanceof Node\Stmt\ClassLike) { $classNamespacedName = $node->namespacedName; assert($classNamespacedName instanceof Node\Name); $className = $classNamespacedName->toString(); $this->classNodes[$className] = [$node, $this->currentNamespace]; foreach ($node->getConstants() as $constantsNode) { foreach ($constantsNode->consts as $constNode) { $constClassName = sprintf('%s::%s', $className, $constNode->name->toString()); $this->updateConstantValue($constNode, $constClassName); } } // We need to traverse children to resolve attributes names for methods, properties etc. return null; } if ($node instanceof Node\Stmt\ClassMethod) { return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; } if ($node instanceof Node\Stmt\Function_) { $functionNamespacedName = $node->namespacedName; assert($functionNamespacedName instanceof Node\Name); $functionName = $functionNamespacedName->toString(); $this->functionNodes[$functionName][] = [$node, $this->currentNamespace]; return NodeTraverser::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Stmt\Const_) { foreach ($node->consts as $constNode) { $constNamespacedName = $constNode->namespacedName; assert($constNamespacedName instanceof Node\Name); $constNodeName = $constNamespacedName->toString(); $this->updateConstantValue($constNode, $constNodeName); $this->constantNodes[$constNodeName] = [$node, $this->currentNamespace]; } return NodeTraverser::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Expr\FuncCall) { $argumentNameNode = $node->args[0]; assert($argumentNameNode instanceof Node\Arg); $nameNode = $argumentNameNode->value; assert($nameNode instanceof Node\Scalar\String_); $constantName = $nameNode->value; // The definition is stubs looks like `define('STDIN', fopen('php://stdin', 'r'))` // We will modify it to `define('STDIN', constant('STDIN')); // The later definition can pass validation in `ConstantNodeChecker` and has support in `CompileNodeToValue` if (in_array($constantName, ['STDIN', 'STDOUT', 'STDERR'], \true) && array_key_exists(1, $node->args) && $node->args[1] instanceof Node\Arg) { $node->args[1]->value = $this->builderFactory->funcCall('constant', [$constantName]); } // @codeCoverageIgnoreStart // @infection-ignore-all // No invalid definition in PhpStorm stubs try { ConstantNodeChecker::assertValidDefineFunctionCall($node); } catch (InvalidConstantNode $exception) { return null; } // @codeCoverageIgnoreEnd if (in_array($constantName, self::TRUE_FALSE_NULL, \true)) { $constantName = strtoupper($constantName); $nameNode->value = $constantName; } $this->updateConstantValue($node, $constantName); $this->constantNodes[$constantName] = [$node, $this->currentNamespace]; if (array_key_exists(2, $node->args) && $node->args[2] instanceof Node\Arg && $node->args[2]->value instanceof Node\Expr\ConstFetch && $node->args[2]->value->name->toLowerString() === 'true') { $this->constantNodes[strtolower($constantName)] = [$node, $this->currentNamespace]; } return NodeTraverser::DONT_TRAVERSE_CHILDREN; } return null; } /** * {@inheritDoc} */ public function leaveNode(Node $node) { if ($node instanceof Node\Stmt\Namespace_) { $this->currentNamespace = null; } return null; } /** @return array */ public function getClassNodes() : array { return $this->classNodes; } /** @return array> */ public function getFunctionNodes() : array { return $this->functionNodes; } /** @return array */ public function getConstantNodes() : array { return $this->constantNodes; } public function clearNodes() : void { $this->classNodes = []; $this->functionNodes = []; $this->constantNodes = []; } /** * Some constants have different values on different systems, some are not actual in stubs. * @param \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Const_ $node */ private function updateConstantValue($node, string $constantName) : void { // prevent autoloading while discovering class constants $parts = explode('::', $constantName, 2); if (count($parts) === 2) { [$className, $classConstName] = $parts; if (!class_exists($className, \false)) { return; } } if (!defined($constantName)) { return; } // @ because access to deprecated constant throws deprecated warning /** @var scalar|resource|list|null $constantValue */ $constantValue = @constant($constantName); $normalizedConstantValue = is_resource($constantValue) ? $this->builderFactory->funcCall('constant', [$constantName]) : $this->builderFactory->val($constantValue); if ($node instanceof Node\Expr\FuncCall) { $argumentValueNode = $node->args[1]; assert($argumentValueNode instanceof Node\Arg); $argumentValueNode->value = $normalizedConstantValue; } else { $node->value = $normalizedConstantValue; } } } */ private $sourceStubbers; public function __construct(\PHPStan\BetterReflection\SourceLocator\SourceStubber\SourceStubber $sourceStubber, \PHPStan\BetterReflection\SourceLocator\SourceStubber\SourceStubber ...$otherSourceStubbers) { $this->sourceStubbers = array_values(array_merge([$sourceStubber], $otherSourceStubbers)); } /** @param class-string|trait-string $className */ public function generateClassStub(string $className) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { foreach ($this->sourceStubbers as $sourceStubber) { $stubData = $sourceStubber->generateClassStub($className); if ($stubData !== null) { return $stubData; } } return null; } public function generateFunctionStub(string $functionName) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { foreach ($this->sourceStubbers as $sourceStubber) { $stubData = $sourceStubber->generateFunctionStub($functionName); if ($stubData !== null) { return $stubData; } } return null; } public function generateConstantStub(string $constantName) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { return array_reduce($this->sourceStubbers, static function (?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData $stubData, \PHPStan\BetterReflection\SourceLocator\SourceStubber\SourceStubber $sourceStubber) use($constantName) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { return $stubData ?? $sourceStubber->generateConstantStub($constantName); }, null); } } stub = $stub; $this->extensionName = $extensionName; $this->fileName = $fileName; } public function getStub() : string { return $this->stub; } /** @return non-empty-string|null */ public function getExtensionName() : ?string { return $this->extensionName; } public function getFileName() : ?string { return $this->fileName; } } */ private $classNodes = []; /** * `null` means "function is not supported in the required PHP version" * * @var array */ private $functionNodes = []; /** * `null` means "failed lookup" for constant that is not case insensitive or "constant is not supported in the required PHP version" * * @var array */ private $constantNodes = []; /** * @var bool */ private static $mapsInitialized = \false; /** @var array */ private static $classMap; /** @var array */ private static $functionMap; /** @var array */ private static $constantMap; /** * @var \PhpParser\Parser */ private $phpParser; /** * @var int */ private $phpVersion = PHP_VERSION_ID; public function __construct(Parser $phpParser, Standard $prettyPrinter, int $phpVersion = PHP_VERSION_ID) { $this->phpParser = $phpParser; $this->phpVersion = $phpVersion; $this->builderFactory = new BuilderFactory(); $this->prettyPrinter = $prettyPrinter; $this->cachingVisitor = new CachingVisitor($this->builderFactory); $this->nodeTraverser = new NodeTraverser(); $this->nodeTraverser->addVisitor(new NameResolver()); $this->nodeTraverser->addVisitor($this->cachingVisitor); if (self::$mapsInitialized) { return; } /** @psalm-suppress PropertyTypeCoercion */ self::$classMap = array_change_key_case(PhpStormStubsMap::CLASSES); /** @psalm-suppress PropertyTypeCoercion */ self::$functionMap = array_change_key_case(PhpStormStubsMap::FUNCTIONS); /** @psalm-suppress PropertyTypeCoercion */ self::$constantMap = array_change_key_case(PhpStormStubsMap::CONSTANTS); self::$mapsInitialized = \true; } public function hasClass(string $className) : bool { $lowercaseClassName = strtolower($className); return array_key_exists($lowercaseClassName, self::$classMap); } public function isPresentClass(string $className) : ?bool { $lowercaseClassName = strtolower($className); if (!array_key_exists($lowercaseClassName, self::$classMap)) { return null; } $classNode = $this->getClassNodeData($lowercaseClassName); return $classNode !== null; } public function isPresentFunction(string $functionName) : ?bool { $lowercaseFunctionName = strtolower($functionName); if (!array_key_exists($lowercaseFunctionName, self::$functionMap)) { return null; } $functionNode = $this->getFunctionNodeData($lowercaseFunctionName); return $functionNode !== null; } /** @param class-string|trait-string $className */ public function generateClassStub(string $className) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { if (strtolower($className) === 'iterable') { return null; } $classNodeData = $this->getClassNodeData($className); if ($classNodeData === null) { return null; } $classNode = $classNodeData[0]; if ($classNode instanceof Node\Stmt\Class_) { if ($classNode->extends !== null) { $modifiedExtends = $this->replaceExtendsOrImplementsByPhpVersion($className, [$classNode->extends]); $classNode->extends = $modifiedExtends !== [] ? $modifiedExtends[0] : null; } $classNode->implements = $this->replaceExtendsOrImplementsByPhpVersion($className, $classNode->implements); } elseif ($classNode instanceof Node\Stmt\Interface_) { $classNode->extends = $this->replaceExtendsOrImplementsByPhpVersion($className, $classNode->extends); } $filePath = self::$classMap[strtolower($className)]; $extension = $this->getExtensionFromFilePath($filePath); $stub = $this->createStub($classNode, $classNodeData[1]); if ($className === Traversable::class) { // See https://github.com/JetBrains/phpstorm-stubs/commit/0778a26992c47d7dbee4d0b0bfb7fad4344371b1#diff-575bacb45377d474336c71cbf53c1729 $stub = str_replace(' extends \\iterable', '', $stub); } elseif ($className === Generator::class) { $stub = str_replace('PS_UNRESERVE_PREFIX_throw', 'throw', $stub); } return new \PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData($stub, $extension, $this->getAbsoluteFilePath($filePath)); } /** @return array{0: Node\Stmt\ClassLike, 1: Node\Stmt\Namespace_|null}|null */ private function getClassNodeData(string $className) { $lowercaseClassName = strtolower($className); if (!array_key_exists($lowercaseClassName, self::$classMap)) { return null; } $filePath = self::$classMap[$lowercaseClassName]; if (!array_key_exists($lowercaseClassName, $this->classNodes)) { $this->parseFile($filePath); /** @psalm-suppress RedundantCondition */ if (!array_key_exists($lowercaseClassName, $this->classNodes)) { // Save `null` so we don't parse the file again for the same $lowercaseClassName $this->classNodes[$lowercaseClassName] = null; } } return $this->classNodes[$lowercaseClassName]; } /** * @return array{0: Node\Stmt\Function_, 1: Node\Stmt\Namespace_|null}|null */ private function getFunctionNodeData(string $functionName) : ?array { $lowercaseFunctionName = strtolower($functionName); if (!array_key_exists($lowercaseFunctionName, self::$functionMap)) { return null; } $filePath = self::$functionMap[$lowercaseFunctionName]; if (!array_key_exists($lowercaseFunctionName, $this->functionNodes)) { $this->parseFile($filePath); /** @psalm-suppress RedundantCondition */ if (!array_key_exists($lowercaseFunctionName, $this->functionNodes)) { // Save `null` so we don't parse the file again for the same $lowercaseFunctionName $this->functionNodes[$lowercaseFunctionName] = null; } } return $this->functionNodes[$lowercaseFunctionName]; } public function generateFunctionStub(string $functionName) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { $functionNodeData = $this->getFunctionNodeData($functionName); if ($functionNodeData === null) { return null; } $filePath = self::$functionMap[strtolower($functionName)]; $extension = $this->getExtensionFromFilePath($filePath); return new \PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData($this->createStub($functionNodeData[0], $functionNodeData[1]), $extension, $this->getAbsoluteFilePath($filePath)); } public function generateConstantStub(string $constantName) : ?\PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData { $lowercaseConstantName = strtolower($constantName); if (!array_key_exists($lowercaseConstantName, self::$constantMap)) { return null; } if (array_key_exists($lowercaseConstantName, $this->constantNodes) && $this->constantNodes[$lowercaseConstantName] === null) { return null; } $filePath = self::$constantMap[$lowercaseConstantName]; $constantNodeData = $this->constantNodes[$constantName] ?? $this->constantNodes[$lowercaseConstantName] ?? null; if ($constantNodeData === null) { $this->parseFile($filePath); $constantNodeData = $this->constantNodes[$constantName] ?? $this->constantNodes[$lowercaseConstantName] ?? null; if ($constantNodeData === null) { // Still `null` - the constant is not case-insensitive. Save `null` so we don't parse the file again for the same $constantName $this->constantNodes[$lowercaseConstantName] = null; return null; } } $extension = $this->getExtensionFromFilePath($filePath); return new \PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData($this->createStub($constantNodeData[0], $constantNodeData[1]), $extension, $this->getAbsoluteFilePath($filePath)); } private function parseFile(string $filePath) : void { $absoluteFilePath = $this->getAbsoluteFilePath($filePath); FileChecker::assertReadableFile($absoluteFilePath); /** @var list $ast */ $ast = $this->phpParser->parse(file_get_contents($absoluteFilePath)); // "@since" and "@removed" annotations in some cases do not contain a PHP version, but an extension version - e.g. "@since 1.3.0" // So we check PHP version only for stubs of core extensions $isCoreExtension = $this->isCoreExtension($this->getExtensionFromFilePath($filePath)); $this->cachingVisitor->clearNodes(); $this->nodeTraverser->traverse($ast); foreach ($this->cachingVisitor->getClassNodes() as $className => $classNodeData) { [$classNode] = $classNodeData; if ($isCoreExtension) { if ($className !== 'Attribute' && $className !== 'ReturnTypeWillChange' && $className !== 'AllowDynamicProperties' && $className !== 'SensitiveParameter' && $className !== 'Override' && !$this->isSupportedInPhpVersion($classNode)) { continue; } $classNode->stmts = $this->modifyStmtsByPhpVersion($classNode->stmts); } $this->classNodes[strtolower($className)] = $classNodeData; } foreach ($this->cachingVisitor->getFunctionNodes() as $functionName => $functionNodesData) { foreach ($functionNodesData as $functionNodeData) { [$functionNode] = $functionNodeData; if ($isCoreExtension) { if (!$this->isSupportedInPhpVersion($functionNode)) { continue; } $this->modifyFunctionReturnTypeByPhpVersion($functionNode); $this->modifyFunctionParametersByPhpVersion($functionNode); } $lowercaseFunctionName = strtolower($functionName); if (array_key_exists($lowercaseFunctionName, $this->functionNodes)) { continue; } $this->functionNodes[$lowercaseFunctionName] = $functionNodeData; } } foreach ($this->cachingVisitor->getConstantNodes() as $constantName => $constantNodeData) { [$constantNode] = $constantNodeData; if ($isCoreExtension && !$this->isSupportedInPhpVersion($constantNode)) { continue; } $this->constantNodes[$constantName] = $constantNodeData; } } /** * @param \PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall $node */ private function createStub($node, ?\PhpParser\Node\Stmt\Namespace_ $namespaceNode) : string { if ($node instanceof Node\Expr\FuncCall) { try { ConstantNodeChecker::assertValidDefineFunctionCall($node); $this->addDeprecatedDocComment($node); } catch (InvalidConstantNode $exception) { // just keep going } } if (!$node instanceof Node\Expr\FuncCall) { $this->addDeprecatedDocComment($node); $nodeWithNamespaceName = $node instanceof Node\Stmt\Const_ ? $node->consts[0] : $node; $namespacedName = $nodeWithNamespaceName->namespacedName; assert($namespacedName instanceof Node\Name); $namespaceBuilder = $this->builderFactory->namespace($namespacedName->slice(0, -1)); if ($namespaceNode !== null) { foreach ($namespaceNode->stmts as $stmt) { if (!$stmt instanceof Node\Stmt\Use_ && !$stmt instanceof Node\Stmt\GroupUse) { continue; } $namespaceBuilder->addStmt($stmt); } } $namespaceBuilder->addStmt($node); $node = $namespaceBuilder->getNode(); } return sprintf("prettyPrinter->prettyPrint([$node]), $node instanceof Node\Expr\FuncCall ? ';' : ''); } /** @return non-empty-string */ private function getExtensionFromFilePath(string $filePath) : string { $extensionName = explode('/', $filePath)[0]; assert($extensionName !== ''); return $extensionName; } /** @return non-empty-string */ private function getAbsoluteFilePath(string $filePath) : string { return sprintf('%s/%s', $this->getStubsDirectory(), $filePath); } /** * Some stubs extend/implement classes from newer PHP versions. We need to filter those names in regard to set PHP version so that those stubs remain valid. * * @param array $nameNodes * * @return list */ private function replaceExtendsOrImplementsByPhpVersion(string $className, array $nameNodes) : array { $modifiedNames = []; foreach ($nameNodes as $nameNode) { $name = $nameNode->toString(); if ($className === ParseError::class) { if ($name === CompileError::class && $this->phpVersion < 70300) { $modifiedNames[] = new Node\Name\FullyQualified(Error::class); continue; } } elseif ($className === SplFixedArray::class) { if ($name === JsonSerializable::class && $this->phpVersion < 80100) { continue; } if ($name === IteratorAggregate::class && $this->phpVersion < 80000) { continue; } if ($name === Iterator::class && $this->phpVersion >= 80000) { continue; } } elseif ($className === SimpleXMLElement::class) { if ($name === RecursiveIterator::class && $this->phpVersion < 80000) { continue; } } elseif ($className === DatePeriod::class || $className === PDOStatement::class) { if ($name === IteratorAggregate::class && $this->phpVersion < 80000) { $modifiedNames[] = new Node\Name\FullyQualified(Traversable::class); continue; } } elseif ($className === SplObjectStorage::class) { if ($name === SeekableIterator::class && $this->phpVersion < 80400) { $modifiedNames[] = new Node\Name\FullyQualified(Iterator::class); continue; } } if ($this->getClassNodeData($name) === null) { continue; } $modifiedNames[] = $nameNode; } return $modifiedNames; } /** * @param array $stmts * * @return list */ private function modifyStmtsByPhpVersion(array $stmts) : array { $newStmts = []; foreach ($stmts as $stmt) { assert($stmt instanceof Node\Stmt\ClassConst || $stmt instanceof Node\Stmt\Property || $stmt instanceof Node\Stmt\ClassMethod || $stmt instanceof Node\Stmt\EnumCase); if (!$this->isSupportedInPhpVersion($stmt)) { continue; } if ($stmt instanceof Node\Stmt\Property) { $this->modifyStmtTypeByPhpVersion($stmt); } if ($stmt instanceof Node\Stmt\ClassMethod) { $this->modifyFunctionReturnTypeByPhpVersion($stmt); $this->modifyFunctionParametersByPhpVersion($stmt); } $this->addDeprecatedDocComment($stmt); $newStmts[] = $stmt; } return $newStmts; } /** * @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $stmt */ private function modifyStmtTypeByPhpVersion($stmt) : void { $type = $this->getStmtType($stmt); if ($type === null) { return; } $stmt->type = $type; } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_ $function */ private function modifyFunctionReturnTypeByPhpVersion($function) : void { $isTentativeReturnType = $this->getNodeAttribute($function, 'JetBrains\\PhpStorm\\Internal\\TentativeType') !== null; if ($isTentativeReturnType) { // Tentative types are the most correct in stubs // If the type is tentative in stubs, we should remove the type for PHP < 8.1 if ($this->phpVersion >= 80100) { $this->addAnnotationToDocComment($function, AnnotationHelper::TENTATIVE_RETURN_TYPE_ANNOTATION); } else { $function->returnType = null; } return; } $type = $this->getStmtType($function); if ($type === null) { return; } $function->returnType = $type; } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_ $function */ private function modifyFunctionParametersByPhpVersion($function) : void { $parameters = []; foreach ($function->getParams() as $parameterNode) { if (!$this->isSupportedInPhpVersion($parameterNode)) { continue; } $this->modifyStmtTypeByPhpVersion($parameterNode); $parameters[] = $parameterNode; } $function->params = $parameters; } /** * @param \PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $node * @return \PhpParser\Node\Name|\PhpParser\Node\Identifier|\PhpParser\Node\ComplexType|null */ private function getStmtType($node) { $languageLevelTypeAwareAttribute = $this->getNodeAttribute($node, 'JetBrains\\PhpStorm\\Internal\\LanguageLevelTypeAware'); if ($languageLevelTypeAwareAttribute === null) { return null; } assert($languageLevelTypeAwareAttribute->args[0]->value instanceof Node\Expr\Array_); /** @var list $types */ $types = $languageLevelTypeAwareAttribute->args[0]->value->items; usort($types, static function (Node\Expr\ArrayItem $a, Node\Expr\ArrayItem $b) : int { return $b->key <=> $a->key; }); foreach ($types as $type) { assert($type->key instanceof Node\Scalar\String_); assert($type->value instanceof Node\Scalar\String_); if ($this->parsePhpVersion($type->key->value) > $this->phpVersion) { continue; } return $this->normalizeType($type->value->value); } assert($languageLevelTypeAwareAttribute->args[1]->value instanceof Node\Scalar\String_); return $languageLevelTypeAwareAttribute->args[1]->value->value !== '' ? $this->normalizeType($languageLevelTypeAwareAttribute->args[1]->value->value) : null; } /** * @param \PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Stmt\EnumCase $node */ private function addDeprecatedDocComment($node) : void { if ($node instanceof Node\Expr\FuncCall) { if (!$this->isDeprecatedByPhpDocInPhpVersion($node)) { $this->removeAnnotationFromDocComment($node, 'deprecated'); } return; } if ($node instanceof Node\Stmt\Const_) { return; } if (!$this->isDeprecatedInPhpVersion($node)) { $this->removeAnnotationFromDocComment($node, 'deprecated'); return; } $this->addAnnotationToDocComment($node, 'deprecated'); } /** * @param \PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Stmt\EnumCase $node */ private function addAnnotationToDocComment($node, string $annotationName) : void { $docComment = $node->getDocComment(); if ($docComment === null) { $docCommentText = sprintf('/** @%s */', $annotationName); } else { $docCommentText = preg_replace('~(\\r?\\n\\s*)\\*/~', sprintf('\\1* @%s\\1*/', $annotationName), $docComment->getText()); } $node->setDocComment(new Doc($docCommentText)); } /** * @param \PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Stmt\EnumCase $node */ private function removeAnnotationFromDocComment($node, string $annotationName) : void { $docComment = $node->getDocComment(); if ($docComment === null) { return; } $docCommentText = preg_replace('~@' . $annotationName . '.*$~m', '', $docComment->getText()); $node->setDocComment(new Doc($docCommentText)); } private function isCoreExtension(string $extension) : bool { return in_array($extension, self::CORE_EXTENSIONS, \true); } private function isDeprecatedByPhpDocInPhpVersion(Node\Expr\FuncCall $node) : bool { $docComment = $node->getDocComment(); if ($docComment === null) { return \false; } if (preg_match('#@deprecated\\s+(\\d+)\\.(\\d+)(?:\\.(\\d+))?$#m', $docComment->getText(), $matches) === 1) { $major = $matches[1]; $minor = $matches[2]; $patch = $matches[3] ?? 0; $versionId = sprintf('%d%02d%02d', $major, $minor, $patch); return $this->phpVersion >= $versionId; } return \true; } /** * @param \PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\EnumCase $node */ private function isDeprecatedInPhpVersion($node) : bool { $deprecatedAttribute = $this->getNodeAttribute($node, 'JetBrains\\PhpStorm\\Deprecated'); if ($deprecatedAttribute === null) { return \false; } foreach ($deprecatedAttribute->args as $attributeArg) { if ($attributeArg->name !== null && $attributeArg->name->toString() === 'since') { assert($attributeArg->value instanceof Node\Scalar\String_); return $this->parsePhpVersion($attributeArg->value->value) <= $this->phpVersion; } } return \true; } /** * @param \PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Param|\PhpParser\Node\Stmt\EnumCase $node */ private function isSupportedInPhpVersion($node) : bool { [$fromVersion, $toVersion] = $this->getSupportedPhpVersions($node); if ($fromVersion !== null && $fromVersion > $this->phpVersion) { return \false; } return $toVersion === null || $toVersion >= $this->phpVersion; } /** @return array{0: int|null, 1: int|null} * @param \PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Param|\PhpParser\Node\Stmt\EnumCase $node */ private function getSupportedPhpVersions($node) : array { $fromVersion = null; $toVersion = null; $docComment = $node->getDocComment(); if ($docComment !== null) { if (preg_match('~@since\\s+(?P\\d+\\.\\d+(?:\\.\\d+)?)\\s+~', $docComment->getText(), $sinceMatches) === 1) { $fromVersion = $this->parsePhpVersion($sinceMatches['version']); } if (preg_match('~@removed\\s+(?P\\d+\\.\\d+(?:\\.\\d+)?)\\s+~', $docComment->getText(), $removedMatches) === 1) { $toVersion = $this->parsePhpVersion($removedMatches['version']) - 1; } } $elementsAvailable = $this->getNodeAttribute($node, 'JetBrains\\PhpStorm\\Internal\\PhpStormStubsElementAvailable'); if ($elementsAvailable !== null) { foreach ($elementsAvailable->args as $i => $attributeArg) { $isFrom = \false; if ($attributeArg->name !== null && $attributeArg->name->toString() === 'from') { $isFrom = \true; } if ($attributeArg->name === null && $i === 0) { $isFrom = \true; } if ($isFrom) { assert($attributeArg->value instanceof Node\Scalar\String_); $fromVersion = $this->parsePhpVersion($attributeArg->value->value); } $isTo = \false; if ($attributeArg->name !== null && $attributeArg->name->toString() === 'to') { $isTo = \true; } if ($attributeArg->name === null && $i === 1) { $isTo = \true; } if (!$isTo) { continue; } assert($attributeArg->value instanceof Node\Scalar\String_); $toVersion = $this->parsePhpVersion($attributeArg->value->value, 99); } } return [$fromVersion, $toVersion]; } /** * @param \PhpParser\Node\Stmt\ClassLike|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Param|\PhpParser\Node\Stmt\EnumCase $node */ private function getNodeAttribute($node, string $attributeName) : ?\PhpParser\Node\Attribute { if ($node instanceof Node\Expr\FuncCall || $node instanceof Node\Stmt\Const_) { return null; } foreach ($node->attrGroups as $attributesGroupNode) { foreach ($attributesGroupNode->attrs as $attributeNode) { if ($attributeNode->name->toString() === $attributeName) { return $attributeNode; } } } return null; } private function parsePhpVersion(string $version, int $defaultPatch = 0) : int { $parts = array_map('intval', explode('.', $version)); return $parts[0] * 10000 + $parts[1] * 100 + ($parts[2] ?? $defaultPatch); } /** * @return \PhpParser\Node\Name|\PhpParser\Node\Identifier|\PhpParser\Node\ComplexType|null */ private function normalizeType(string $type) { // There are some invalid types in stubs, eg. `string[]|string|null` if (\strpos($type, '[') !== \false) { return null; } /** @psalm-suppress InternalClass, InternalMethod */ return BuilderHelpers::normalizeType($type); } private function getStubsDirectory() : string { if ($this->stubsDirectory !== null) { return $this->stubsDirectory; } foreach (self::SEARCH_DIRECTORIES as $directory) { if (is_dir($directory)) { return $this->stubsDirectory = $directory; } } // @codeCoverageIgnoreStart // @infection-ignore-all // Untestable code throw CouldNotFindPhpStormStubs::create(); // @codeCoverageIgnoreEnd } } astConversionStrategy = $astConversionStrategy; } /** * Find all reflections of a given type in an Abstract Syntax Tree * * @param Node[] $ast * * @return list */ public function __invoke(Reflector $reflector, array $ast, IdentifierType $identifierType, LocatedSource $locatedSource) : array { $nodeVisitor = new class($reflector, $identifierType, $locatedSource, $this->astConversionStrategy) extends NodeVisitorAbstract { /** @var list */ private $reflections = []; /** * @var \PhpParser\Node\Stmt\Namespace_|null */ private $currentNamespace = null; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @var \PHPStan\BetterReflection\Identifier\IdentifierType */ private $identifierType; /** * @var \PHPStan\BetterReflection\SourceLocator\Located\LocatedSource */ private $locatedSource; /** * @var \PHPStan\BetterReflection\SourceLocator\Ast\Strategy\AstConversionStrategy */ private $astConversionStrategy; public function __construct(Reflector $reflector, IdentifierType $identifierType, LocatedSource $locatedSource, AstConversionStrategy $astConversionStrategy) { $this->reflector = $reflector; $this->identifierType = $identifierType; $this->locatedSource = $locatedSource; $this->astConversionStrategy = $astConversionStrategy; } /** * {@inheritDoc} */ public function enterNode(Node $node) { if ($node instanceof Namespace_) { $this->currentNamespace = $node; } return null; } /** * {@inheritDoc} */ public function leaveNode(Node $node) { if ($this->identifierType->isClass() && ($node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Interface_ || $node instanceof Node\Stmt\Trait_ || $node instanceof Node\Stmt\Enum_)) { $classNamespace = $node->name === null ? null : $this->currentNamespace; $this->reflections[] = $this->astConversionStrategy->__invoke($this->reflector, $node, $this->locatedSource, $classNamespace); return null; } if ($this->identifierType->isConstant()) { if ($node instanceof Node\Stmt\Const_) { for ($i = 0; $i < count($node->consts); $i++) { $this->reflections[] = $this->astConversionStrategy->__invoke($this->reflector, $node, $this->locatedSource, $this->currentNamespace, $i); } return null; } if ($node instanceof Node\Expr\FuncCall) { try { ConstantNodeChecker::assertValidDefineFunctionCall($node); } catch (InvalidConstantNode $exception) { return null; } if ($node->name->hasAttribute('namespacedName')) { $namespacedName = $node->name->getAttribute('namespacedName'); assert($namespacedName instanceof Name); try { $this->reflector->reflectFunction($namespacedName->toString()); return null; } catch (IdentifierNotFound $exception) { // Global define() } } $this->reflections[] = $this->astConversionStrategy->__invoke($this->reflector, $node, $this->locatedSource, $this->currentNamespace); return null; } } if ($this->identifierType->isFunction() && $node instanceof Node\Stmt\Function_) { $this->reflections[] = $this->astConversionStrategy->__invoke($this->reflector, $node, $this->locatedSource, $this->currentNamespace); } if ($node instanceof Namespace_) { $this->currentNamespace = null; } return null; } /** @return list */ public function getReflections() : array { return $this->reflections; } }; $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor(new NameResolver()); $nodeTraverser->addVisitor($nodeVisitor); $nodeTraverser->traverse($ast); return $nodeVisitor->getReflections(); } } indexed by source hash */ private $sourceHashToAst = []; /** * @var \PhpParser\Parser */ private $wrappedParser; public function __construct(Parser $wrappedParser) { $this->wrappedParser = $wrappedParser; } public function parse(string $code, ?\PhpParser\ErrorHandler $errorHandler = null) : ?array { // note: this code is mathematically buggy by default, as we are using a hash to identify // cache entries. The string length is added to further reduce likeliness (although // already imperceptible) of key collisions. // In the "real world", this code will work just fine. $hash = sprintf('%s:%d', hash('sha256', $code), strlen($code)); if (array_key_exists($hash, $this->sourceHashToAst)) { /** @var Node\Stmt[]|null $ast */ $ast = unserialize($this->sourceHashToAst[$hash]); return $ast; } $ast = $this->wrappedParser->parse($code, $errorHandler); $this->sourceHashToAst[$hash] = serialize($ast); return $ast; } } name : null) !== null ? implode('\\', $namespace->name->getParts()) : null; if ($namespaceName === '') { throw new LogicException('Namespace name should never be empty'); } if ($node instanceof Node\Stmt\Enum_) { return ReflectionEnum::createFromNode($reflector, $node, $locatedSource, $namespaceName); } if ($node instanceof Node\Stmt\ClassLike) { return ReflectionClass::createFromNode($reflector, $node, $locatedSource, $namespaceName); } if ($node instanceof Node\Stmt\Const_) { return ReflectionConstant::createFromNode($reflector, $node, $locatedSource, $namespaceName, $positionInNode); } if ($node instanceof Node\Expr\FuncCall) { return ReflectionConstant::createFromNode($reflector, $node, $locatedSource); } return ReflectionFunction::createFromNode($reflector, $node, $locatedSource, $namespaceName); } } parser = $parser; $this->findReflectionsInTree = new \PHPStan\BetterReflection\SourceLocator\Ast\FindReflectionsInTree(new NodeToReflection()); } /** * @throws IdentifierNotFound * @throws Exception\ParseToAstFailure */ public function findReflection(Reflector $reflector, LocatedSource $locatedSource, Identifier $identifier) : Reflection { return $this->findInArray($this->findReflectionsOfType($reflector, $locatedSource, $identifier->getType()), $identifier, $locatedSource->getName()); } /** * Get an array of reflections found in some code. * * @return list * * @throws Exception\ParseToAstFailure */ public function findReflectionsOfType(Reflector $reflector, LocatedSource $locatedSource, IdentifierType $identifierType) : array { try { /** @var list $ast */ $ast = $this->parser->parse($locatedSource->getSource()); return $this->findReflectionsInTree->__invoke($reflector, $ast, $identifierType, $locatedSource); } catch (Throwable $exception) { throw \PHPStan\BetterReflection\SourceLocator\Ast\Exception\ParseToAstFailure::fromLocatedSource($locatedSource, $exception); } } /** * Given an array of Reflections, try to find the identifier. * * @param list $reflections * * @throws IdentifierNotFound */ private function findInArray(array $reflections, Identifier $identifier, ?string $name) : Reflection { if ($name === null) { throw IdentifierNotFound::fromIdentifier($identifier); } $identifierName = strtolower($name); foreach ($reflections as $reflection) { if (strtolower($reflection->getName()) === $identifierName) { return $reflection; } } throw IdentifierNotFound::fromIdentifier($identifier); } } getFileName(); if ($fileName !== null) { $additionalInformation = sprintf(' in file %s', $fileName); } if ($previous instanceof Error) { $errorStartLine = $previous->getStartLine(); $source = null; if ($errorStartLine !== -1) { $additionalInformation .= sprintf(' (line %d)', $errorStartLine); $lines = explode("\n", $locatedSource->getSource()); $minLine = max(1, $errorStartLine - 5); $maxLine = min(count($lines), $errorStartLine + 5); $source = implode("\n", array_slice($lines, $minLine - 1, $maxLine - $minLine + 1)); } $additionalInformation .= sprintf(': %s', $previous->getRawMessage()); if ($source !== null) { $additionalInformation .= sprintf("\n\n%s", $source); } } else { $additionalInformation .= sprintf(': %s', $previous->getMessage()); } return new self(sprintf('AST failed to parse in located source%s', $additionalInformation), 0, $previous); } } value = $value; $this->constantName = $constantName; } } reflector = $reflector; $this->contextReflection = $contextReflection; } public function getReflector() : Reflector { return $this->reflector; } /** @return non-empty-string|null */ public function getFileName() : ?string { if ($this->contextReflection instanceof ReflectionConstant) { $fileName = $this->contextReflection->getFileName(); if ($fileName === null) { return null; } return $this->realPath($fileName); } $fileName = (($getClass = $this->getClass()) ? $getClass->getFileName() : null) ?? (($getFunction = $this->getFunction()) ? $getFunction->getFileName() : null); if ($fileName === null) { return null; } return $this->realPath($fileName); } private function realPath(string $fileName) : string { return FileHelper::normalizePath($fileName, '/'); } public function getNamespace() : ?string { if ($this->contextReflection instanceof ReflectionConstant) { return $this->contextReflection->getNamespaceName(); } // @infection-ignore-all Coalesce: There's no difference return (($getClass = $this->getClass()) ? $getClass->getNamespaceName() : null) ?? (($getFunction = $this->getFunction()) ? $getFunction->getNamespaceName() : null); } public function getClass() : ?\PHPStan\BetterReflection\Reflection\ReflectionClass { if ($this->contextReflection instanceof ReflectionClass) { return $this->contextReflection; } if ($this->contextReflection instanceof ReflectionFunction) { return null; } if ($this->contextReflection instanceof ReflectionConstant) { return null; } if ($this->contextReflection instanceof ReflectionClassConstant) { return $this->contextReflection->getDeclaringClass(); } if ($this->contextReflection instanceof ReflectionEnumCase) { return $this->contextReflection->getDeclaringClass(); } return $this->contextReflection->getImplementingClass(); } /** * @return \PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|null */ public function getFunction() { if ($this->contextReflection instanceof ReflectionMethod) { return $this->contextReflection; } if ($this->contextReflection instanceof ReflectionFunction) { return $this->contextReflection; } if ($this->contextReflection instanceof ReflectionParameter) { return $this->contextReflection->getDeclaringFunction(); } return null; } } expr, $context); } $constantName = null; if ($node instanceof Node\Expr\ConstFetch && !in_array($node->name->toLowerString(), self::TRUE_FALSE_NULL, \true)) { $constantName = $this->resolveConstantName($node, $context); } elseif ($node instanceof Node\Expr\ClassConstFetch) { $constantName = $this->resolveClassConstantName($node, $context); } $constExprEvaluator = new ConstExprEvaluator(function (Node\Expr $node) use($context, $constantName) { if ($node instanceof Node\Expr\ConstFetch) { return $this->getConstantValue($node, $constantName, $context); } if ($node instanceof Node\Expr\ClassConstFetch) { return $this->getClassConstantValue($node, $constantName, $context); } if ($node instanceof Node\Expr\New_) { return $this->compileNew($node, $context); } if ($node instanceof Node\Scalar\MagicConst\Dir) { return $this->compileDirConstant($context, $node); } if ($node instanceof Node\Scalar\MagicConst\File) { return $this->compileFileConstant($context, $node); } if ($node instanceof Node\Scalar\MagicConst\Class_) { return $this->compileClassConstant($context); } if ($node instanceof Node\Scalar\MagicConst\Line) { return $node->getLine(); } if ($node instanceof Node\Scalar\MagicConst\Namespace_) { return $context->getNamespace() ?? ''; } if ($node instanceof Node\Scalar\MagicConst\Method) { $class = $context->getClass(); $function = $context->getFunction(); if ($class !== null && $function !== null) { return sprintf('%s::%s', $class->getName(), $function->getName()); } if ($function !== null) { return $function->getName(); } return ''; } if ($node instanceof Node\Scalar\MagicConst\Function_) { return (($getFunction = $context->getFunction()) ? $getFunction->getName() : null) ?? ''; } if ($node instanceof Node\Scalar\MagicConst\Trait_) { $class = $context->getClass(); if ($class !== null && $class->isTrait()) { return $class->getName(); } return ''; } if ($node instanceof Node\Expr\FuncCall && $node->name instanceof Node\Name && $node->name->toLowerString() === 'constant' && $node->args[0] instanceof Node\Arg && $node->args[0]->value instanceof Node\Scalar\String_ && defined($node->args[0]->value->value)) { return constant($node->args[0]->value->value); } if ($node instanceof Node\Expr\PropertyFetch && $node->var instanceof Node\Expr\ClassConstFetch) { return $this->getEnumPropertyValue($node, $context); } throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::forUnRecognizedExpressionInContext($node, $context); }); /** @psalm-var mixed $value */ $value = $constExprEvaluator->evaluateDirectly($node); return new \PHPStan\BetterReflection\NodeCompiler\CompiledValue($value, $constantName); } /** * @return mixed */ private function getEnumPropertyValue(Node\Expr\PropertyFetch $node, \PHPStan\BetterReflection\NodeCompiler\CompilerContext $context) { assert($node->var instanceof Node\Expr\ClassConstFetch); assert($node->var->class instanceof Node\Name); $className = $this->resolveClassName($node->var->class->toString(), $context); $class = $context->getReflector()->reflectClass($className); if (!$class instanceof ReflectionEnum) { throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfInvalidEnumCasePropertyFetch($context, $class, $node); } assert($node->var->name instanceof Node\Identifier); $caseName = $node->var->name->name; assert($caseName !== ''); $case = $class->getCase($caseName); if ($case === null) { throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfInvalidEnumCasePropertyFetch($context, $class, $node); } assert($node->name instanceof Node\Identifier); switch ($node->name->toString()) { case 'value': return $case->getValue(); case 'name': return $case->getName(); default: throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfInvalidEnumCasePropertyFetch($context, $class, $node); } } private function resolveConstantName(Node\Expr\ConstFetch $constNode, \PHPStan\BetterReflection\NodeCompiler\CompilerContext $context) : string { $constantName = $constNode->name->toString(); $namespace = $context->getNamespace() ?? ''; if ($constNode->name->isUnqualified()) { $namespacedConstantName = sprintf('%s\\%s', $namespace, $constantName); if ($this->constantExists($namespacedConstantName, $context)) { return $namespacedConstantName; } } if ($this->constantExists($constantName, $context)) { return $constantName; } throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfNotFoundConstantReference($context, $constNode, $constantName); } private function constantExists(string $constantName, \PHPStan\BetterReflection\NodeCompiler\CompilerContext $context) : bool { if (defined($constantName)) { return \true; } try { $context->getReflector()->reflectConstant($constantName); return \true; } catch (IdentifierNotFound $exception) { return \false; } } /** * @return mixed */ private function getConstantValue(Node\Expr\ConstFetch $node, ?string $constantName, \PHPStan\BetterReflection\NodeCompiler\CompilerContext $context) { // It's not resolved when constant value is expression // @infection-ignore-all Assignment, AssignCoalesce: There's no difference, ??= is just optimization $constantName = $constantName ?? $this->resolveConstantName($node, $context); if (defined($constantName)) { return constant($constantName); } return $context->getReflector()->reflectConstant($constantName)->getValue(); } private function resolveClassConstantName(Node\Expr\ClassConstFetch $node, \PHPStan\BetterReflection\NodeCompiler\CompilerContext $context) : string { assert($node->name instanceof Node\Identifier); $constantName = $node->name->name; assert($node->class instanceof Node\Name); $className = $node->class->toString(); return sprintf('%s::%s', $this->resolveClassName($className, $context), $constantName); } /** * @return mixed */ private function getClassConstantValue(Node\Expr\ClassConstFetch $node, ?string $classConstantName, \PHPStan\BetterReflection\NodeCompiler\CompilerContext $context) { // It's not resolved when constant value is expression // @infection-ignore-all Assignment, AssignCoalesce: There's no difference, ??= is just optimization $classConstantName = $classConstantName ?? $this->resolveClassConstantName($node, $context); [$className, $constantName] = explode('::', $classConstantName); assert($constantName !== ''); if ($constantName === 'class') { return $className; } $classContext = $context->getClass(); $classReflection = $classContext !== null && $classContext->getName() === $className ? $classContext : $context->getReflector()->reflectClass($className); if ($classReflection instanceof ReflectionEnum) { if ($classReflection->hasCase($constantName)) { return constant(sprintf('%s::%s', $className, $constantName)); } } if ($classReflection instanceof ReflectionEnum) { if ($classReflection->hasCase($constantName)) { throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfValueIsEnum($context, $classReflection, $node); } } $reflectionConstant = $classReflection->getConstant($constantName); if (!$reflectionConstant instanceof ReflectionClassConstant) { throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfNotFoundClassConstantReference($context, $classReflection, $node); } return $reflectionConstant->getValue(); } private function compileNew(Node\Expr\New_ $node, \PHPStan\BetterReflection\NodeCompiler\CompilerContext $context) : object { assert($node->class instanceof Node\Name); /** @psalm-var class-string $className */ $className = $node->class->toString(); if (!class_exists($className)) { throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfClassCannotBeLoaded($context, $node, $className); } $arguments = []; foreach ($node->args as $argNo => $arg) { $arguments[(($argName = $arg->name) ? $argName->toString() : null) ?? $argNo] = $this($arg->value, $context)->value; } return new $className(...$arguments); } /** * Compile a __DIR__ node */ private function compileDirConstant(\PHPStan\BetterReflection\NodeCompiler\CompilerContext $context, Node\Scalar\MagicConst\Dir $node) : string { $fileName = $context->getFileName(); if ($fileName === null) { throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfMissingFileName($context, $node); } if (!is_file($fileName)) { throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfNonexistentFile($context, $fileName); } return dirname($fileName); } /** * Compile a __FILE__ node */ private function compileFileConstant(\PHPStan\BetterReflection\NodeCompiler\CompilerContext $context, Node\Scalar\MagicConst\File $node) : string { $fileName = $context->getFileName(); if ($fileName === null) { throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfMissingFileName($context, $node); } if (!is_file($fileName)) { throw \PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode::becauseOfNonexistentFile($context, $fileName); } return $fileName; } /** * Compiles magic constant __CLASS__ */ private function compileClassConstant(\PHPStan\BetterReflection\NodeCompiler\CompilerContext $context) : string { return (($getClass = $context->getClass()) ? $getClass->getName() : null) ?? ''; } private function resolveClassName(string $className, \PHPStan\BetterReflection\NodeCompiler\CompilerContext $context) : string { if ($className !== 'self' && $className !== 'static' && $className !== 'parent') { return $className; } $classContext = $context->getClass(); assert($classContext !== null); if ($className !== 'parent') { return $classContext->getName(); } $parentClass = $classContext->getParentClass(); assert($parentClass instanceof ReflectionClass); return $parentClass->getName(); } } constantName; } public static function forUnRecognizedExpressionInContext(Node\Expr $expression, CompilerContext $context) : self { return new self(sprintf('Unable to compile expression in %s: unrecognized node type %s in file %s (line %d)', self::compilerContextToContextDescription($context), \get_class($expression), self::getFileName($context), $expression->getLine())); } public static function becauseOfNotFoundClassConstantReference(CompilerContext $fetchContext, ReflectionClass $targetClass, Node\Expr\ClassConstFetch $constantFetch) : self { assert($constantFetch->name instanceof Node\Identifier); return new self(sprintf('Could not locate constant %s::%s while trying to evaluate constant expression in %s in file %s (line %d)', $targetClass->getName(), $constantFetch->name->name, self::compilerContextToContextDescription($fetchContext), self::getFileName($fetchContext), $constantFetch->getLine())); } public static function becauseOfNotFoundConstantReference(CompilerContext $fetchContext, Node\Expr\ConstFetch $constantFetch, string $constantName) : self { $exception = new self(sprintf('Could not locate constant "%s" while evaluating expression in %s in file %s (line %d)', $constantName, self::compilerContextToContextDescription($fetchContext), self::getFileName($fetchContext), $constantFetch->getLine())); $exception->constantName = $constantName; return $exception; } public static function becauseOfInvalidEnumCasePropertyFetch(CompilerContext $fetchContext, ReflectionClass $targetClass, Node\Expr\PropertyFetch $propertyFetch) : self { assert($propertyFetch->var instanceof Node\Expr\ClassConstFetch); assert($propertyFetch->var->name instanceof Node\Identifier); assert($propertyFetch->name instanceof Node\Identifier); return new self(sprintf('Could not get %s::%s->%s while trying to evaluate constant expression in %s in file %s (line %d)', $targetClass->getName(), $propertyFetch->var->name->name, $propertyFetch->name->toString(), self::compilerContextToContextDescription($fetchContext), self::getFileName($fetchContext), $propertyFetch->getLine())); } /** * @param \PhpParser\Node\Scalar\MagicConst\Dir|\PhpParser\Node\Scalar\MagicConst\File $node */ public static function becauseOfMissingFileName(CompilerContext $context, $node) : self { return new self(sprintf('No file name for %s (line %d)', self::compilerContextToContextDescription($context), $node->getLine())); } public static function becauseOfNonexistentFile(CompilerContext $context, string $fileName) : self { return new self(sprintf('File not found for %s: %s', self::compilerContextToContextDescription($context), $fileName)); } public static function becauseOfClassCannotBeLoaded(CompilerContext $context, Node\Expr\New_ $newNode, string $className) : self { return new self(sprintf('Cound not load class "%s" while evaluating expression in %s in file %s (line %d)', $className, self::compilerContextToContextDescription($context), self::getFileName($context), $newNode->getLine())); } public static function becauseOfValueIsEnum(CompilerContext $fetchContext, ReflectionClass $targetClass, Node\Expr\ClassConstFetch $constantFetch) : self { assert($constantFetch->name instanceof Node\Identifier); return new self(sprintf('An enum expression %s::%s is not supported in %s in file %s (line %d)', $targetClass->getName(), $constantFetch->name->name, self::compilerContextToContextDescription($fetchContext), self::getFileName($fetchContext), $constantFetch->getLine())); } private static function getFileName(CompilerContext $fetchContext) : string { $fileName = $fetchContext->getFileName(); return $fileName !== null ? FileHelper::normalizeWindowsPath($fileName) : '""'; } private static function compilerContextToContextDescription(CompilerContext $fetchContext) : string { $class = $fetchContext->getClass(); $function = $fetchContext->getFunction(); if ($class !== null && $function !== null) { return sprintf('method %s::%s()', $class->getName(), $function->getName()); } if ($class !== null) { return sprintf('class %s', $class->getName()); } if ($function !== null) { return sprintf('function %s()', $function->getName()); } $namespace = $fetchContext->getNamespace(); if ($namespace !== null) { return sprintf('namespace %s', $namespace); } return 'global namespace'; } } */ private $attributes; /** @var non-empty-string|null */ private $docComment; /** @var positive-int */ private $startLine; /** @var positive-int */ private $endLine; /** @var positive-int */ private $startColumn; /** @var positive-int */ private $endColumn; /** @psalm-allow-private-mutation * @var \PHPStan\BetterReflection\NodeCompiler\CompiledValue|null */ private $compiledValue = null; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionEnum */ private $enum; private function __construct(Reflector $reflector, EnumCase $node, \PHPStan\BetterReflection\Reflection\ReflectionEnum $enum) { $this->reflector = $reflector; $this->enum = $enum; $name = $node->name->toString(); assert($name !== ''); $this->name = $name; $this->value = $node->expr; $this->attributes = ReflectionAttributeHelper::createAttributes($reflector, $this, $node->attrGroups); $this->docComment = GetLastDocComment::forNode($node); $startLine = $node->getStartLine(); assert($startLine > 0); $endLine = $node->getEndLine(); assert($endLine > 0); $this->startLine = $startLine; $this->endLine = $endLine; $this->startColumn = CalculateReflectionColumn::getStartColumn($this->enum->getLocatedSource()->getSource(), $node); $this->endColumn = CalculateReflectionColumn::getEndColumn($this->enum->getLocatedSource()->getSource(), $node); } /** @internal */ public static function createFromNode(Reflector $reflector, EnumCase $node, \PHPStan\BetterReflection\Reflection\ReflectionEnum $enum) : self { return new self($reflector, $node, $enum); } /** @return non-empty-string */ public function getName() : string { return $this->name; } /** * @deprecated Use getValueExpression() */ public function getValueExpr() : Node\Expr { return $this->getValueExpression(); } /** * Check ReflectionEnum::isBacked() being true first to avoid throwing exception. * * @throws LogicException */ public function getValueExpression() : Node\Expr { if ($this->value === null) { throw new LogicException('This enum case does not have a value'); } return $this->value; } /** * @return string|int */ public function getValue() { $value = $this->getCompiledValue()->value; assert(is_string($value) || is_int($value)); return $value; } /** * Check ReflectionEnum::isBacked() being true first to avoid throwing exception. * * @throws LogicException */ private function getCompiledValue() : CompiledValue { if ($this->value === null) { throw new LogicException('This enum case does not have a value'); } if ($this->compiledValue === null) { $this->compiledValue = (new CompileNodeToValue())->__invoke($this->value, new CompilerContext($this->reflector, $this)); } return $this->compiledValue; } /** @return positive-int */ public function getStartLine() : int { return $this->startLine; } /** @return positive-int */ public function getEndLine() : int { return $this->endLine; } /** @return positive-int */ public function getStartColumn() : int { return $this->startColumn; } /** @return positive-int */ public function getEndColumn() : int { return $this->endColumn; } public function getDeclaringEnum() : \PHPStan\BetterReflection\Reflection\ReflectionEnum { return $this->enum; } public function getDeclaringClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->enum; } /** @return non-empty-string|null */ public function getDocComment() : ?string { return $this->docComment; } public function isDeprecated() : bool { return AnnotationHelper::isDeprecated($this->docComment); } /** @return list */ public function getAttributes() : array { return $this->attributes; } /** @return list */ public function getAttributesByName(string $name) : array { return ReflectionAttributeHelper::filterAttributesByName($this->getAttributes(), $name); } /** * @param class-string $className * * @return list */ public function getAttributesByInstance(string $className) : array { return ReflectionAttributeHelper::filterAttributesByInstance($this->getAttributes(), $className); } /** @return non-empty-string */ public function __toString() : string { return ReflectionEnumCaseStringCast::toString($this); } } */ private $modifiers; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ private $type; /** * @var \PhpParser\Node\Expr|null */ private $default; /** @var non-empty-string|null */ private $docComment; /** @var list */ private $attributes; /** @var positive-int|null */ private $startLine; /** @var positive-int|null */ private $endLine; /** @var positive-int|null */ private $startColumn; /** @var positive-int|null */ private $endColumn; /** @psalm-allow-private-mutation * @var \PHPStan\BetterReflection\NodeCompiler\CompiledValue|null */ private $compiledDefaultValue = null; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionClass */ private $declaringClass; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionClass */ private $implementingClass; /** * @var bool */ private $isPromoted; /** * @var bool */ private $declaredAtCompileTime; private function __construct(Reflector $reflector, PropertyNode $node, Node\Stmt\PropertyProperty $propertyNode, \PHPStan\BetterReflection\Reflection\ReflectionClass $declaringClass, \PHPStan\BetterReflection\Reflection\ReflectionClass $implementingClass, bool $isPromoted, bool $declaredAtCompileTime) { $this->reflector = $reflector; $this->declaringClass = $declaringClass; $this->implementingClass = $implementingClass; $this->isPromoted = $isPromoted; $this->declaredAtCompileTime = $declaredAtCompileTime; $name = $propertyNode->name->name; assert($name !== ''); $this->name = $name; $this->modifiers = $this->computeModifiers($node); $this->type = $this->createType($node); $this->default = $propertyNode->default; $this->docComment = GetLastDocComment::forNode($node); $this->attributes = ReflectionAttributeHelper::createAttributes($reflector, $this, $node->attrGroups); $startLine = null; if ($node->hasAttribute('startLine')) { $startLine = $node->getStartLine(); assert($startLine > 0); } $endLine = null; if ($node->hasAttribute('endLine')) { $endLine = $node->getEndLine(); assert($endLine > 0); } $this->startLine = $startLine; $this->endLine = $endLine; try { $this->startColumn = CalculateReflectionColumn::getStartColumn($declaringClass->getLocatedSource()->getSource(), $node); } catch (NoNodePosition $exception) { $this->startColumn = null; } try { $this->endColumn = CalculateReflectionColumn::getEndColumn($declaringClass->getLocatedSource()->getSource(), $node); } catch (NoNodePosition $exception) { $this->endColumn = null; } } /** * Create a reflection of a class's property by its name * * @param non-empty-string $propertyName * * @throws OutOfBoundsException */ public static function createFromName(string $className, string $propertyName) : self { $property = \PHPStan\BetterReflection\Reflection\ReflectionClass::createFromName($className)->getProperty($propertyName); if ($property === null) { throw new OutOfBoundsException(sprintf('Could not find property: %s', $propertyName)); } return $property; } /** * Create a reflection of an instance's property by its name * * @param non-empty-string $propertyName * * @throws ReflectionException * @throws IdentifierNotFound * @throws OutOfBoundsException */ public static function createFromInstance(object $instance, string $propertyName) : self { $property = \PHPStan\BetterReflection\Reflection\ReflectionClass::createFromInstance($instance)->getProperty($propertyName); if ($property === null) { throw new OutOfBoundsException(sprintf('Could not find property: %s', $propertyName)); } return $property; } /** @internal */ public function withImplementingClass(\PHPStan\BetterReflection\Reflection\ReflectionClass $implementingClass) : self { $clone = clone $this; $clone->implementingClass = $implementingClass; if ($clone->type !== null) { $clone->type = $clone->type->withOwner($clone); } $clone->attributes = array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionAttribute $attribute) use($clone) : \PHPStan\BetterReflection\Reflection\ReflectionAttribute { return $attribute->withOwner($clone); }, $this->attributes); $this->compiledDefaultValue = null; return $clone; } /** @return non-empty-string */ public function __toString() : string { return ReflectionPropertyStringCast::toString($this); } /** * @internal * * @param PropertyNode $node Node has to be processed by the PhpParser\NodeVisitor\NameResolver */ public static function createFromNode(Reflector $reflector, PropertyNode $node, Node\Stmt\PropertyProperty $propertyProperty, \PHPStan\BetterReflection\Reflection\ReflectionClass $declaringClass, \PHPStan\BetterReflection\Reflection\ReflectionClass $implementingClass, bool $isPromoted = \false, bool $declaredAtCompileTime = \true) : self { return new self($reflector, $node, $propertyProperty, $declaringClass, $implementingClass, $isPromoted, $declaredAtCompileTime); } /** * Has the property been declared at compile-time? * * Note that unless the property is static, this is hard coded to return * true, because we are unable to reflect instances of classes, therefore * we can be sure that all properties are always declared at compile-time. */ public function isDefault() : bool { return $this->declaredAtCompileTime; } /** * Get the core-reflection-compatible modifier values. * * @return int-mask-of */ public function getModifiers() : int { return $this->modifiers; } /** * Get the name of the property. * * @return non-empty-string */ public function getName() : string { return $this->name; } /** * Is the property private? */ public function isPrivate() : bool { return ($this->modifiers & CoreReflectionProperty::IS_PRIVATE) === CoreReflectionProperty::IS_PRIVATE; } /** * Is the property protected? */ public function isProtected() : bool { return ($this->modifiers & CoreReflectionProperty::IS_PROTECTED) === CoreReflectionProperty::IS_PROTECTED; } /** * Is the property public? */ public function isPublic() : bool { return ($this->modifiers & CoreReflectionProperty::IS_PUBLIC) === CoreReflectionProperty::IS_PUBLIC; } /** * Is the property static? */ public function isStatic() : bool { return ($this->modifiers & CoreReflectionProperty::IS_STATIC) === CoreReflectionProperty::IS_STATIC; } public function isPromoted() : bool { return $this->isPromoted; } public function isInitialized($object = null) : bool { if ($object === null && $this->isStatic()) { return !$this->hasType() || $this->hasDefaultValue(); } try { $this->getValue($object); return \true; // @phpstan-ignore-next-line } catch (Error $e) { if (\strpos($e->getMessage(), 'must not be accessed before initialization') !== \false) { return \false; } throw $e; } } public function isReadOnly() : bool { return ($this->modifiers & ReflectionPropertyAdapter::IS_READONLY_COMPATIBILITY) === ReflectionPropertyAdapter::IS_READONLY_COMPATIBILITY || $this->getDeclaringClass()->isReadOnly(); } public function getDeclaringClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->declaringClass; } public function getImplementingClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->implementingClass; } /** @return non-empty-string|null */ public function getDocComment() : ?string { return $this->docComment; } public function hasDefaultValue() : bool { return !$this->hasType() || $this->default !== null; } /** * @deprecated Use getDefaultValueExpression() */ public function getDefaultValueExpr() : ?\PhpParser\Node\Expr { return $this->getDefaultValueExpression(); } public function getDefaultValueExpression() : ?\PhpParser\Node\Expr { return $this->default; } /** * Get the default value of the property (as defined before constructor is * called, when the property is defined) * * @deprecated Use getDefaultValueExpr() * @return mixed */ public function getDefaultValue() { if ($this->default === null) { return null; } if ($this->compiledDefaultValue === null) { $this->compiledDefaultValue = (new CompileNodeToValue())->__invoke($this->default, new CompilerContext($this->reflector, $this)); } /** @psalm-var scalar|array|null $value */ $value = $this->compiledDefaultValue->value; return $value; } public function isDeprecated() : bool { return AnnotationHelper::isDeprecated($this->getDocComment()); } /** * Get the line number that this property starts on. * * @return positive-int * * @throws CodeLocationMissing */ public function getStartLine() : int { if ($this->startLine === null) { throw CodeLocationMissing::create(); } return $this->startLine; } /** * Get the line number that this property ends on. * * @return positive-int * * @throws CodeLocationMissing */ public function getEndLine() : int { if ($this->endLine === null) { throw CodeLocationMissing::create(); } return $this->endLine; } /** * @return positive-int * * @throws CodeLocationMissing */ public function getStartColumn() : int { if ($this->startColumn === null) { throw CodeLocationMissing::create(); } return $this->startColumn; } /** * @return positive-int * * @throws CodeLocationMissing */ public function getEndColumn() : int { if ($this->endColumn === null) { throw CodeLocationMissing::create(); } return $this->endColumn; } /** @return list */ public function getAttributes() : array { return $this->attributes; } /** @return list */ public function getAttributesByName(string $name) : array { return ReflectionAttributeHelper::filterAttributesByName($this->getAttributes(), $name); } /** * @param class-string $className * * @return list */ public function getAttributesByInstance(string $className) : array { return ReflectionAttributeHelper::filterAttributesByInstance($this->getAttributes(), $className); } /** * @throws ClassDoesNotExist * @throws NoObjectProvided * @throws ObjectNotInstanceOfClass * @return mixed */ public function getValue($object = null) { $implementingClassName = $this->getImplementingClass()->getName(); if ($this->isStatic()) { $this->assertClassExist($implementingClassName); $closure = Closure::bind(function (string $implementingClassName, string $propertyName) { return $implementingClassName::${$propertyName}; }, null, $implementingClassName); assert($closure instanceof Closure); return $closure->__invoke($implementingClassName, $this->getName()); } $instance = $this->assertObject($object); $closure = Closure::bind(function (object $instance, string $propertyName) { return $instance->{$propertyName}; }, $instance, $implementingClassName); assert($closure instanceof Closure); return $closure->__invoke($instance, $this->getName()); } /** * @throws ClassDoesNotExist * @throws NoObjectProvided * @throws NotAnObject * @throws ObjectNotInstanceOfClass * @param mixed $object * @param mixed $value */ public function setValue($object, $value = null) : void { $implementingClassName = $this->getImplementingClass()->getName(); if ($this->isStatic()) { $this->assertClassExist($implementingClassName); $closure = Closure::bind(function (string $_implementingClassName, string $_propertyName, $value) : void { /** @psalm-suppress MixedAssignment */ $_implementingClassName::${$_propertyName} = $value; }, null, $implementingClassName); assert($closure instanceof Closure); $closure->__invoke($implementingClassName, $this->getName(), func_num_args() === 2 ? $value : $object); return; } $instance = $this->assertObject($object); $closure = Closure::bind(function (object $instance, string $propertyName, $value) : void { $instance->{$propertyName} = $value; }, $instance, $implementingClassName); assert($closure instanceof Closure); $closure->__invoke($instance, $this->getName(), $value); } /** * Does this property allow null? */ public function allowsNull() : bool { return $this->type === null || $this->type->allowsNull(); } /** * @return \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ private function createType(PropertyNode $node) { $type = $node->type; if ($type === null) { return null; } assert($type instanceof Node\Identifier || $type instanceof Node\Name || $type instanceof Node\NullableType || $type instanceof Node\UnionType || $type instanceof Node\IntersectionType); return \PHPStan\BetterReflection\Reflection\ReflectionType::createFromNode($this->reflector, $this, $type); } /** * Get the ReflectionType instance representing the type declaration for * this property * * (note: this has nothing to do with DocBlocks). * @return \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ public function getType() { return $this->type; } /** * Does this property have a type declaration? * * (note: this has nothing to do with DocBlocks). */ public function hasType() : bool { return $this->type !== null; } /** * @param class-string $className * * @throws ClassDoesNotExist */ private function assertClassExist(string $className) : void { if (!ClassExistenceChecker::classExists($className, \true) && !ClassExistenceChecker::traitExists($className, \true)) { throw new ClassDoesNotExist('Property cannot be retrieved as the class does not exist'); } } /** * @throws NoObjectProvided * @throws NotAnObject * @throws ObjectNotInstanceOfClass * * @psalm-assert object $object * @param mixed $object */ private function assertObject($object) : object { if ($object === null) { throw NoObjectProvided::create(); } if (!is_object($object)) { throw NotAnObject::fromNonObject($object); } $implementingClassName = $this->getImplementingClass()->getName(); if (\get_class($object) !== $implementingClassName) { throw ObjectNotInstanceOfClass::fromClassName($implementingClassName); } return $object; } /** @return int-mask-of */ private function computeModifiers(PropertyNode $node) : int { $modifiers = $node->isReadonly() ? ReflectionPropertyAdapter::IS_READONLY_COMPATIBILITY : 0; $modifiers += $node->isStatic() ? CoreReflectionProperty::IS_STATIC : 0; $modifiers += $node->isPrivate() ? CoreReflectionProperty::IS_PRIVATE : 0; $modifiers += $node->isProtected() ? CoreReflectionProperty::IS_PROTECTED : 0; $modifiers += $node->isPublic() ? CoreReflectionProperty::IS_PUBLIC : 0; return $modifiers; } } */ private $types; /** @internal * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $owner */ public function __construct(Reflector $reflector, $owner, IntersectionType $type) { /** @var non-empty-list $types */ $types = array_map(static function ($type) use($reflector, $owner) : \PHPStan\BetterReflection\Reflection\ReflectionNamedType { $type = \PHPStan\BetterReflection\Reflection\ReflectionType::createFromNode($reflector, $owner, $type); assert($type instanceof \PHPStan\BetterReflection\Reflection\ReflectionNamedType); return $type; }, $type->types); $this->types = $types; } /** @internal * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $owner * @return $this */ public function withOwner($owner) { $clone = clone $this; foreach ($clone->types as $typeNo => $innerType) { $clone->types[$typeNo] = $innerType->withOwner($owner); } return $clone; } /** @return non-empty-list */ public function getTypes() : array { return $this->types; } /** @return false */ public function allowsNull() : bool { return \false; } /** @return non-empty-string */ public function __toString() : string { // @infection-ignore-all UnwrapArrayMap: It works without array_map() as well but this is less magical return implode('&', array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionNamedType $type) : string { return $type->__toString(); }, $this->types)); } } */ private $classNames; /** @param array $classNames */ private function __construct(array $classNames) { $this->classNames = $classNames; } public static function createEmpty() : self { return new self([]); } /** @param class-string $className */ public function push(string $className) : void { if (array_key_exists($className, $this->classNames)) { throw CircularReference::fromClassName($className); } $this->classNames[$className] = null; } } */ private $modifiers; /** @var non-empty-string|null */ private $docComment; /** @var list */ private $attributes; /** @var positive-int */ private $startLine; /** @var positive-int */ private $endLine; /** @var positive-int */ private $startColumn; /** @var positive-int */ private $endColumn; /** @var class-string|null */ private $parentClassName; /** @var list */ private $implementsClassNames; /** @var list */ private $traitClassNames; /** @var array */ private $immediateConstants; /** @var array */ private $immediateProperties; /** @var array */ private $immediateMethods; /** @var array{aliases: array, modifiers: array>, precedences: array} */ private $traitsData; /** * @var array|null * @psalm-allow-private-mutation */ private $cachedConstants = null; /** * @var array|null * @psalm-allow-private-mutation */ private $cachedProperties = null; /** @var array|null */ private $cachedInterfaces = null; /** @var list|null */ private $cachedInterfaceNames = null; /** @var list|null */ private $cachedTraits = null; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionMethod|null */ private $cachedConstructor = null; /** * @var string|null */ private $cachedName = null; /** * @psalm-allow-private-mutation * @var array|null */ private $cachedMethods = null; /** * @var list|null * @psalm-allow-private-mutation */ private $cachedParentClasses = null; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @var \PHPStan\BetterReflection\SourceLocator\Located\LocatedSource */ private $locatedSource; /** * @var non-empty-string|null */ private $namespace = null; /** * @internal * * @param non-empty-string|null $namespace * @param ClassNode|InterfaceNode|TraitNode|EnumNode $node */ protected function __construct(Reflector $reflector, $node, LocatedSource $locatedSource, ?string $namespace = null) { $this->reflector = $reflector; $this->locatedSource = $locatedSource; $this->namespace = $namespace; $this->name = null; $this->shortName = null; if ($node->name instanceof Node\Identifier) { $namespacedName = $node->namespacedName; if ($namespacedName === null) { /** @psalm-var class-string|trait-string */ $name = $node->name->name; } else { /** @psalm-var class-string|trait-string */ $name = $namespacedName->toString(); } $this->name = $name; $this->shortName = $node->name->name; } $this->isInterface = $node instanceof InterfaceNode; $this->isTrait = $node instanceof TraitNode; $this->isEnum = $node instanceof EnumNode; $this->isBackedEnum = $node instanceof EnumNode && $node->scalarType !== null; $this->modifiers = $this->computeModifiers($node); $this->docComment = GetLastDocComment::forNode($node); $this->attributes = ReflectionAttributeHelper::createAttributes($reflector, $this, $node->attrGroups); $startLine = $node->getStartLine(); assert($startLine > 0); $endLine = $node->getEndLine(); assert($endLine > 0); $this->startLine = $startLine; $this->endLine = $endLine; $this->startColumn = CalculateReflectionColumn::getStartColumn($locatedSource->getSource(), $node); $this->endColumn = CalculateReflectionColumn::getEndColumn($locatedSource->getSource(), $node); /** @var class-string|null $parentClassName */ $parentClassName = $node instanceof ClassNode ? ($nodeExtends = $node->extends) ? $nodeExtends->toString() : null : null; $this->parentClassName = $parentClassName; // @infection-ignore-all UnwrapArrayMap: It works without array_map() as well but this is less magical /** @var list $implementsClassNames */ $implementsClassNames = array_map(static function (Node\Name $name) : string { return $name->toString(); }, $node instanceof TraitNode ? [] : ($node instanceof InterfaceNode ? $node->extends : $node->implements)); $this->implementsClassNames = $implementsClassNames; /** @var list $traitClassNames */ $traitClassNames = array_merge([], ...array_map( // @infection-ignore-all UnwrapArrayMap: It works without array_map() as well but this is less magical static function (TraitUse $traitUse) : array { return array_map(static function (Node\Name $traitName) : string { return $traitName->toString(); }, $traitUse->traits); }, $node->getTraitUses() )); $this->traitClassNames = $traitClassNames; $this->immediateConstants = $this->createImmediateConstants($node, $reflector); $this->immediateProperties = $this->createImmediateProperties($node, $reflector); $this->immediateMethods = $this->createImmediateMethods($node, $reflector); $this->traitsData = $this->computeTraitsData($node); } /** @return non-empty-string */ public function __toString() : string { return ReflectionClassStringCast::toString($this); } /** * Create a ReflectionClass by name, using default reflectors etc. * * @deprecated Use Reflector instead. * * @throws IdentifierNotFound */ public static function createFromName(string $className) : self { return (new BetterReflection())->reflector()->reflectClass($className); } /** * Create a ReflectionClass from an instance, using default reflectors etc. * * This is simply a helper method that calls ReflectionObject::createFromInstance(). * * @see ReflectionObject::createFromInstance * * @throws IdentifierNotFound * @throws ReflectionException */ public static function createFromInstance(object $instance) : self { return \PHPStan\BetterReflection\Reflection\ReflectionObject::createFromInstance($instance); } /** * Create from a Class Node. * * @internal * * @param ClassNode|InterfaceNode|TraitNode|EnumNode $node Node has to be processed by the PhpParser\NodeVisitor\NameResolver * @param non-empty-string|null $namespace optional - if omitted, we assume it is global namespaced class */ public static function createFromNode(Reflector $reflector, $node, LocatedSource $locatedSource, ?string $namespace = null) : self { return new self($reflector, $node, $locatedSource, $namespace); } /** * Get the "short" name of the class (e.g. for A\B\Foo, this will return * "Foo"). * * @return non-empty-string */ public function getShortName() : string { if ($this->shortName !== null) { return $this->shortName; } $fileName = $this->getFileName(); if ($fileName === null) { $fileName = sha1($this->locatedSource->getSource()); } return sprintf('%s%s%c%s(%d)', $this->getAnonymousClassNamePrefix(), self::ANONYMOUS_CLASS_NAME_SUFFIX, "\x00", $fileName, $this->getStartLine()); } /** * PHP creates the name of the anonymous class based on first parent * or implemented interface. */ private function getAnonymousClassNamePrefix() : string { if ($this->parentClassName !== null) { return $this->parentClassName; } if ($this->implementsClassNames !== []) { return $this->implementsClassNames[0]; } return 'class'; } /** * Get the "full" name of the class (e.g. for A\B\Foo, this will return * "A\B\Foo"). * * @return class-string|trait-string */ public function getName() : string { if ($this->cachedName !== null) { return $this->cachedName; } if (!$this->inNamespace()) { /** @psalm-var class-string|trait-string */ return $this->cachedName = $this->getShortName(); } assert($this->name !== null); return $this->cachedName = $this->name; } /** @return class-string|null */ public function getParentClassName() : ?string { return $this->parentClassName; } /** * Get the "namespace" name of the class (e.g. for A\B\Foo, this will * return "A\B"). * * @return non-empty-string|null */ public function getNamespaceName() : ?string { return $this->namespace; } /** * Decide if this class is part of a namespace. Returns false if the class * is in the global namespace or does not have a specified namespace. */ public function inNamespace() : bool { return $this->namespace !== null; } /** @return non-empty-string|null */ public function getExtensionName() : ?string { return $this->locatedSource->getExtensionName(); } /** @return list */ private function createMethodsFromTrait(\PHPStan\BetterReflection\Reflection\ReflectionMethod $method) : array { $methodModifiers = $method->getModifiers(); $methodHash = $this->methodHash($method->getImplementingClass()->getName(), $method->getName()); if (array_key_exists($methodHash, $this->traitsData['modifiers'])) { $newModifierAst = $this->traitsData['modifiers'][$methodHash]; if ($this->traitsData['modifiers'][$methodHash] & ClassNode::VISIBILITY_MODIFIER_MASK) { $methodModifiersWithoutVisibility = $methodModifiers; if (($methodModifiers & CoreReflectionMethod::IS_PUBLIC) === CoreReflectionMethod::IS_PUBLIC) { $methodModifiersWithoutVisibility -= CoreReflectionMethod::IS_PUBLIC; } if (($methodModifiers & CoreReflectionMethod::IS_PROTECTED) === CoreReflectionMethod::IS_PROTECTED) { $methodModifiersWithoutVisibility -= CoreReflectionMethod::IS_PROTECTED; } if (($methodModifiers & CoreReflectionMethod::IS_PRIVATE) === CoreReflectionMethod::IS_PRIVATE) { $methodModifiersWithoutVisibility -= CoreReflectionMethod::IS_PRIVATE; } $newModifier = 0; if (($newModifierAst & ClassNode::MODIFIER_PUBLIC) === ClassNode::MODIFIER_PUBLIC) { $newModifier = CoreReflectionMethod::IS_PUBLIC; } if (($newModifierAst & ClassNode::MODIFIER_PROTECTED) === ClassNode::MODIFIER_PROTECTED) { $newModifier = CoreReflectionMethod::IS_PROTECTED; } if (($newModifierAst & ClassNode::MODIFIER_PRIVATE) === ClassNode::MODIFIER_PRIVATE) { $newModifier = CoreReflectionMethod::IS_PRIVATE; } $methodModifiers = $methodModifiersWithoutVisibility | $newModifier; } if (($newModifierAst & ClassNode::MODIFIER_FINAL) === ClassNode::MODIFIER_FINAL) { $methodModifiers |= CoreReflectionMethod::IS_FINAL; } } $createMethod = function (?string $aliasMethodName) use($method, $methodModifiers) : \PHPStan\BetterReflection\Reflection\ReflectionMethod { assert($aliasMethodName === null || $aliasMethodName !== ''); /** @phpstan-ignore-next-line */ return $method->withImplementingClass($this, $aliasMethodName, $methodModifiers); }; $methods = []; if (!array_key_exists($methodHash, $this->traitsData['precedences'])) { $methods[] = $createMethod($method->getAliasName()); } foreach ($this->traitsData['aliases'] as $aliasMethodName => $traitAliasDefinition) { if ($methodHash !== $traitAliasDefinition) { continue; } $methods[] = $createMethod($aliasMethodName); } return $methods; } /** * Construct a flat list of all methods in this precise order from: * - current class * - parent class * - traits used in parent class * - interfaces implemented in parent class * - traits used in current class * - interfaces implemented in current class * * Methods are not merged via their name as array index, since internal PHP method * sorting does not follow `\array_merge()` semantics. * * @return array indexed by method name */ private function getMethodsIndexedByLowercasedName(AlreadyVisitedClasses $alreadyVisitedClasses) : array { if ($this->cachedMethods !== null) { return $this->cachedMethods; } $alreadyVisitedClasses->push($this->getName()); $immediateMethods = $this->getImmediateMethods(); $className = $this->getName(); $methods = \array_combine(array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionMethod $method) : string { return strtolower($method->getName()); }, $immediateMethods), $immediateMethods); $parentClass = $this->getParentClass(); if ($parentClass !== null) { foreach ($parentClass->getMethodsIndexedByLowercasedName($alreadyVisitedClasses) as $lowercasedMethodName => $method) { if (array_key_exists($lowercasedMethodName, $methods)) { continue; } $methods[$lowercasedMethodName] = $method->withCurrentClass($this); } } foreach ($this->getTraits() as $trait) { $alreadyVisitedClassesCopy = clone $alreadyVisitedClasses; foreach ($trait->getMethodsIndexedByLowercasedName($alreadyVisitedClassesCopy) as $method) { foreach ($this->createMethodsFromTrait($method) as $traitMethod) { $lowercasedMethodName = strtolower($traitMethod->getName()); if (!array_key_exists($lowercasedMethodName, $methods)) { $methods[$lowercasedMethodName] = $traitMethod; continue; } if ($traitMethod->isAbstract()) { continue; } // Non-abstract trait method can overwrite existing method: // - when existing method comes from parent class // - when existing method comes from trait and is abstract $existingMethod = $methods[$lowercasedMethodName]; if ($existingMethod->getDeclaringClass()->getName() === $className && !($existingMethod->isAbstract() && $existingMethod->getDeclaringClass()->isTrait())) { continue; } $methods[$lowercasedMethodName] = $traitMethod; } } } foreach ($this->getImmediateInterfaces() as $interface) { $alreadyVisitedClassesCopy = clone $alreadyVisitedClasses; foreach ($interface->getMethodsIndexedByLowercasedName($alreadyVisitedClassesCopy) as $lowercasedMethodName => $method) { if (array_key_exists($lowercasedMethodName, $methods)) { continue; } $methods[$lowercasedMethodName] = $method; } } $this->cachedMethods = $methods; return $this->cachedMethods; } /** * Fetch an array of all methods for this class. * * Filter the results to include only methods with certain attributes. Defaults * to no filtering. * Any combination of \ReflectionMethod::IS_STATIC, * \ReflectionMethod::IS_PUBLIC, * \ReflectionMethod::IS_PROTECTED, * \ReflectionMethod::IS_PRIVATE, * \ReflectionMethod::IS_ABSTRACT, * \ReflectionMethod::IS_FINAL. * For example if $filter = \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_FINAL * the only the final public methods will be returned * * @param int-mask-of $filter * * @return array */ public function getMethods(int $filter = 0) : array { $methods = $this->getMethodsIndexedByLowercasedName(AlreadyVisitedClasses::createEmpty()); if ($filter !== 0) { $methods = array_filter($methods, static function (\PHPStan\BetterReflection\Reflection\ReflectionMethod $method) use($filter) : bool { return (bool) ($filter & $method->getModifiers()); }); } return \array_combine(array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionMethod $method) : string { return $method->getName(); }, $methods), $methods); } /** * Get only the methods that this class implements (i.e. do not search * up parent classes etc.) * * @see ReflectionClass::getMethods for the usage of $filter * * @param int-mask-of $filter * * @return array */ public function getImmediateMethods(int $filter = 0) : array { if ($filter === 0) { return $this->immediateMethods; } return array_filter($this->immediateMethods, static function (\PHPStan\BetterReflection\Reflection\ReflectionMethod $method) use($filter) : bool { return (bool) ($filter & $method->getModifiers()); }); } /** @return array * @param ClassNode|InterfaceNode|TraitNode|EnumNode $node */ private function createImmediateMethods($node, Reflector $reflector) : array { $methods = []; foreach ($node->getMethods() as $methodNode) { $method = \PHPStan\BetterReflection\Reflection\ReflectionMethod::createFromNode($reflector, $methodNode, $this->locatedSource, $this->getNamespaceName(), $this, $this, $this); if (array_key_exists($method->getName(), $methods)) { continue; } $methods[$method->getName()] = $method; } if ($node instanceof EnumNode) { $methods = $this->addEnumMethods($node, $methods); } return $methods; } /** * @param array $methods * * @return array */ private function addEnumMethods(EnumNode $node, array $methods) : array { $internalLocatedSource = new InternalLocatedSource('', $this->getName(), 'Core', $this->getFileName()); $createMethod = function (string $name, array $params, $returnType) use($internalLocatedSource) : \PHPStan\BetterReflection\Reflection\ReflectionMethod { return \PHPStan\BetterReflection\Reflection\ReflectionMethod::createFromNode($this->reflector, new ClassMethod(new Node\Identifier($name), ['flags' => ClassNode::MODIFIER_PUBLIC | ClassNode::MODIFIER_STATIC, 'params' => $params, 'returnType' => $returnType]), $internalLocatedSource, $this->getNamespaceName(), $this, $this, $this); }; $methods['cases'] = $createMethod('cases', [], new Node\Identifier('array')); if ($node->scalarType === null) { return $methods; } $valueParameter = new Node\Param(new Node\Expr\Variable('value'), null, new Node\UnionType([new Node\Identifier('string'), new Node\Identifier('int')])); $methods['from'] = $createMethod('from', [$valueParameter], new Node\Identifier('static')); $methods['tryFrom'] = $createMethod('tryFrom', [$valueParameter], new Node\NullableType(new Node\Identifier('static'))); return $methods; } /** * Get a single method with the name $methodName. * * @param non-empty-string $methodName */ public function getMethod(string $methodName) : ?\PHPStan\BetterReflection\Reflection\ReflectionMethod { $lowercaseMethodName = strtolower($methodName); $methods = $this->getMethodsIndexedByLowercasedName(AlreadyVisitedClasses::createEmpty()); return $methods[$lowercaseMethodName] ?? null; } /** * Does the class have the specified method? * * @param non-empty-string $methodName */ public function hasMethod(string $methodName) : bool { return $this->getMethod($methodName) !== null; } /** * Get an associative array of only the constants for this specific class (i.e. do not search * up parent classes etc.), with keys as constant names and values as {@see ReflectionClassConstant} objects. * * @param int-mask-of $filter * * @return array indexed by name */ public function getImmediateConstants(int $filter = 0) : array { if ($filter === 0) { return $this->immediateConstants; } return array_filter($this->immediateConstants, static function (\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $constant) use($filter) : bool { return (bool) ($filter & $constant->getModifiers()); }); } /** * Does this class have the specified constant? * * @param non-empty-string $name */ public function hasConstant(string $name) : bool { return $this->getConstant($name) !== null; } /** * Get the reflection object of the specified class constant. * * Returns null if not specified. * * @param non-empty-string $name */ public function getConstant(string $name) : ?\PHPStan\BetterReflection\Reflection\ReflectionClassConstant { return $this->getConstants()[$name] ?? null; } /** @return array * @param ClassNode|InterfaceNode|TraitNode|EnumNode $node */ private function createImmediateConstants($node, Reflector $reflector) : array { $constants = []; foreach ($node->getConstants() as $constantsNode) { foreach (array_keys($constantsNode->consts) as $constantPositionInNode) { assert(is_int($constantPositionInNode)); $constant = \PHPStan\BetterReflection\Reflection\ReflectionClassConstant::createFromNode($reflector, $constantsNode, $constantPositionInNode, $this, $this); $constants[$constant->getName()] = $constant; } } return $constants; } /** * Get an associative array of the defined constants in this class, * with keys as constant names and values as {@see ReflectionClassConstant} objects. * * @param int-mask-of $filter * * @return array indexed by name */ public function getConstants(int $filter = 0) : array { $constants = $this->getConstantsConsideringAlreadyVisitedClasses(AlreadyVisitedClasses::createEmpty()); if ($filter === 0) { return $constants; } return array_filter($constants, static function (\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $constant) use($filter) : bool { return (bool) ($filter & $constant->getModifiers()); }); } /** @return array indexed by name */ private function getConstantsConsideringAlreadyVisitedClasses(AlreadyVisitedClasses $alreadyVisitedClasses) : array { if ($this->cachedConstants !== null) { return $this->cachedConstants; } $alreadyVisitedClasses->push($this->getName()); // Note: constants are not merged via their name as array index, since internal PHP constant // sorting does not follow `\array_merge()` semantics $constants = $this->getImmediateConstants(); $parentClass = $this->getParentClass(); if ($parentClass !== null) { foreach ($parentClass->getConstantsConsideringAlreadyVisitedClasses($alreadyVisitedClasses) as $constantName => $constant) { if ($constant->isPrivate()) { continue; } if (array_key_exists($constantName, $constants)) { continue; } $constants[$constantName] = $constant; } } foreach ($this->getTraits() as $trait) { foreach ($trait->getConstantsConsideringAlreadyVisitedClasses($alreadyVisitedClasses) as $constantName => $constant) { if (array_key_exists($constantName, $constants)) { continue; } $constants[$constantName] = $constant->withImplementingClass($this); } } foreach ($this->getImmediateInterfaces() as $interface) { $alreadyVisitedClassesCopy = clone $alreadyVisitedClasses; foreach ($interface->getConstantsConsideringAlreadyVisitedClasses($alreadyVisitedClassesCopy) as $constantName => $constant) { if (array_key_exists($constantName, $constants)) { continue; } $constants[$constantName] = $constant; } } $this->cachedConstants = $constants; return $this->cachedConstants; } /** * Get the constructor method for this class. */ public function getConstructor() : ?\PHPStan\BetterReflection\Reflection\ReflectionMethod { if ($this->cachedConstructor !== null) { return $this->cachedConstructor; } $constructors = array_values(array_filter($this->getMethods(), static function (\PHPStan\BetterReflection\Reflection\ReflectionMethod $method) : bool { return $method->isConstructor(); })); return $this->cachedConstructor = $constructors[0] ?? null; } /** * Get only the properties for this specific class (i.e. do not search * up parent classes etc.) * * @see ReflectionClass::getProperties() for the usage of filter * * @param int-mask-of $filter * * @return array */ public function getImmediateProperties(int $filter = 0) : array { if ($filter === 0) { return $this->immediateProperties; } return array_filter($this->immediateProperties, static function (\PHPStan\BetterReflection\Reflection\ReflectionProperty $property) use($filter) : bool { return (bool) ($filter & $property->getModifiers()); }); } /** @return array * @param ClassNode|InterfaceNode|TraitNode|EnumNode $node */ private function createImmediateProperties($node, Reflector $reflector) : array { $properties = []; foreach ($node->getProperties() as $propertiesNode) { foreach ($propertiesNode->props as $propertyPropertyNode) { $property = \PHPStan\BetterReflection\Reflection\ReflectionProperty::createFromNode($reflector, $propertiesNode, $propertyPropertyNode, $this, $this); $properties[$property->getName()] = $property; } } foreach ($node->getMethods() as $methodNode) { if ($methodNode->name->toLowerString() !== '__construct') { continue; } foreach ($methodNode->params as $parameterNode) { if ($parameterNode->flags === 0) { // No flags, no promotion continue; } $parameterNameNode = $parameterNode->var; assert($parameterNameNode instanceof Node\Expr\Variable); assert(is_string($parameterNameNode->name)); $propertyNode = new Node\Stmt\Property($parameterNode->flags, [new Node\Stmt\PropertyProperty($parameterNameNode->name)], $parameterNode->getAttributes(), $parameterNode->type, $parameterNode->attrGroups); $property = \PHPStan\BetterReflection\Reflection\ReflectionProperty::createFromNode($reflector, $propertyNode, $propertyNode->props[0], $this, $this, \true); $properties[$property->getName()] = $property; } } if ($node instanceof EnumNode || $node instanceof InterfaceNode) { $properties = $this->addEnumProperties($properties, $node, $reflector); } return $properties; } /** * @param array $properties * * @return array * @param EnumNode|InterfaceNode $node */ private function addEnumProperties(array $properties, $node, Reflector $reflector) : array { $createProperty = function (string $name, $type) use($reflector) : \PHPStan\BetterReflection\Reflection\ReflectionProperty { $propertyNode = new Node\Stmt\Property(ClassNode::MODIFIER_PUBLIC | ClassNode::MODIFIER_READONLY, [new Node\Stmt\PropertyProperty($name)], [], $type); return \PHPStan\BetterReflection\Reflection\ReflectionProperty::createFromNode($reflector, $propertyNode, $propertyNode->props[0], $this, $this); }; if ($node instanceof InterfaceNode) { $interfaceName = $this->getName(); if ($interfaceName === 'UnitEnum') { $properties['name'] = $createProperty('name', 'string'); } if ($interfaceName === 'BackedEnum') { $properties['value'] = $createProperty('value', new Node\UnionType([new Node\Identifier('int'), new Node\Identifier('string')])); } } else { $properties['name'] = $createProperty('name', 'string'); if ($node->scalarType !== null) { $properties['value'] = $createProperty('value', $node->scalarType); } } return $properties; } /** * Get the properties for this class. * * Filter the results to include only properties with certain attributes. Defaults * to no filtering. * Any combination of \ReflectionProperty::IS_STATIC, * \ReflectionProperty::IS_PUBLIC, * \ReflectionProperty::IS_PROTECTED, * \ReflectionProperty::IS_PRIVATE. * For example if $filter = \ReflectionProperty::IS_STATIC | \ReflectionProperty::IS_PUBLIC * only the static public properties will be returned * * @param int-mask-of $filter * * @return array */ public function getProperties(int $filter = 0) : array { $properties = $this->getPropertiesConsideringAlreadyVisitedClasses(AlreadyVisitedClasses::createEmpty()); if ($filter === 0) { return $properties; } return array_filter($properties, static function (\PHPStan\BetterReflection\Reflection\ReflectionProperty $property) use($filter) : bool { return (bool) ($filter & $property->getModifiers()); }); } /** @return array */ private function getPropertiesConsideringAlreadyVisitedClasses(AlreadyVisitedClasses $alreadyVisitedClasses) : array { if ($this->cachedProperties !== null) { return $this->cachedProperties; } $alreadyVisitedClasses->push($this->getName()); $immediateProperties = $this->getImmediateProperties(); // Merging together properties from parent class, interfaces, traits, current class (in this precise order) $properties = array_merge(array_filter((($getParentClass = $this->getParentClass()) ? $getParentClass->getPropertiesConsideringAlreadyVisitedClasses($alreadyVisitedClasses) : null) ?? [], static function (\PHPStan\BetterReflection\Reflection\ReflectionProperty $property) { return !$property->isPrivate(); }), ...array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionClass $ancestor) use($alreadyVisitedClasses) : array { return $ancestor->getPropertiesConsideringAlreadyVisitedClasses(clone $alreadyVisitedClasses); }, array_values($this->getImmediateInterfaces()))); foreach ($this->getTraits() as $trait) { foreach ($trait->getPropertiesConsideringAlreadyVisitedClasses($alreadyVisitedClasses) as $traitProperty) { $traitPropertyName = $traitProperty->getName(); if (array_key_exists($traitPropertyName, $properties) || array_key_exists($traitPropertyName, $immediateProperties)) { continue; } $properties[$traitPropertyName] = $traitProperty->withImplementingClass($this); } } // Merge immediate properties last to get the required order $properties = array_merge($properties, $immediateProperties); $this->cachedProperties = $properties; return $this->cachedProperties; } /** * Get the property called $name. * * Returns null if property does not exist. * * @param non-empty-string $name */ public function getProperty(string $name) : ?\PHPStan\BetterReflection\Reflection\ReflectionProperty { $properties = $this->getProperties(); if (!isset($properties[$name])) { return null; } return $properties[$name]; } /** * Does this class have the specified property? * * @param non-empty-string $name */ public function hasProperty(string $name) : bool { return $this->getProperty($name) !== null; } /** @return array */ public function getDefaultProperties() : array { return array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionProperty $property) { return $property->getDefaultValue(); }, $this->getProperties()); } /** @return non-empty-string|null */ public function getFileName() : ?string { return $this->locatedSource->getFileName(); } public function getLocatedSource() : LocatedSource { return $this->locatedSource; } /** * Get the line number that this class starts on. * * @return positive-int */ public function getStartLine() : int { return $this->startLine; } /** * Get the line number that this class ends on. * * @return positive-int */ public function getEndLine() : int { return $this->endLine; } /** @return positive-int */ public function getStartColumn() : int { return $this->startColumn; } /** @return positive-int */ public function getEndColumn() : int { return $this->endColumn; } /** * Get the parent class, if it is defined. */ public function getParentClass() : ?\PHPStan\BetterReflection\Reflection\ReflectionClass { $parentClassName = $this->getParentClassName(); if ($parentClassName === null) { return null; } if ($this->name === $parentClassName) { throw CircularReference::fromClassName($parentClassName); } try { return $this->reflector->reflectClass($parentClassName); } catch (IdentifierNotFound $exception) { return null; } } /** * Gets the parent class names. * * @return list A numerical array with parent class names as the values. */ public function getParentClassNames() : array { return array_map(static function (self $parentClass) : string { return $parentClass->getName(); }, $this->getParentClasses()); } /** @return list */ private function getParentClasses() : array { if ($this->cachedParentClasses === null) { $parentClasses = []; $parentClassName = $this->parentClassName; while ($parentClassName !== null) { try { $parentClass = $this->reflector->reflectClass($parentClassName); } catch (IdentifierNotFound $exception) { break; } if ($this->name === $parentClassName || array_key_exists($parentClassName, $parentClasses)) { throw CircularReference::fromClassName($parentClassName); } $parentClasses[$parentClassName] = $parentClass; $parentClassName = $parentClass->parentClassName; } $this->cachedParentClasses = array_values($parentClasses); } return $this->cachedParentClasses; } /** @return non-empty-string|null */ public function getDocComment() : ?string { return $this->docComment; } public function isAnonymous() : bool { return $this->name === null; } /** * Is this an internal class? */ public function isInternal() : bool { return $this->locatedSource->isInternal(); } /** * Is this a user-defined function (will always return the opposite of * whatever isInternal returns). */ public function isUserDefined() : bool { return !$this->isInternal(); } public function isDeprecated() : bool { return AnnotationHelper::isDeprecated($this->docComment); } /** * Is this class an abstract class. */ public function isAbstract() : bool { return ($this->modifiers & CoreReflectionClass::IS_EXPLICIT_ABSTRACT) === CoreReflectionClass::IS_EXPLICIT_ABSTRACT; } /** * Is this class a final class. */ public function isFinal() : bool { if ($this->isEnum) { return \true; } return ($this->modifiers & CoreReflectionClass::IS_FINAL) === CoreReflectionClass::IS_FINAL; } public function isReadOnly() : bool { return ($this->modifiers & ReflectionClassAdapter::IS_READONLY_COMPATIBILITY) === ReflectionClassAdapter::IS_READONLY_COMPATIBILITY; } /** * Get the core-reflection-compatible modifier values. * * @return int-mask-of */ public function getModifiers() : int { return $this->modifiers; } /** @return int-mask-of * @param ClassNode|InterfaceNode|TraitNode|EnumNode $node */ private function computeModifiers($node) : int { if (!$node instanceof ClassNode) { return 0; } $modifiers = $node->isAbstract() ? CoreReflectionClass::IS_EXPLICIT_ABSTRACT : 0; $modifiers += $node->isFinal() ? CoreReflectionClass::IS_FINAL : 0; $modifiers += $node->isReadonly() ? ReflectionClassAdapter::IS_READONLY_COMPATIBILITY : 0; return $modifiers; } /** * Is this reflection a trait? */ public function isTrait() : bool { return $this->isTrait; } /** * Is this reflection an interface? */ public function isInterface() : bool { return $this->isInterface; } /** * Get the traits used, if any are defined. If this class does not have any * defined traits, this will return an empty array. * * @return list */ public function getTraits() : array { if ($this->cachedTraits !== null) { return $this->cachedTraits; } $traits = []; foreach ($this->traitClassNames as $traitClassName) { try { $traits[] = $this->reflector->reflectClass($traitClassName); } catch (IdentifierNotFound $exception) { // pass } } return $this->cachedTraits = $traits; } /** * @param array $interfaces * * @return array */ private function addStringableInterface(array $interfaces) : array { if (BetterReflection::$phpVersion < 80000) { return $interfaces; } /** @psalm-var class-string $stringableClassName */ $stringableClassName = Stringable::class; if (array_key_exists($stringableClassName, $interfaces) || $this->isInterface && $this->getName() === $stringableClassName) { return $interfaces; } foreach (array_keys($this->immediateMethods) as $immediateMethodName) { if (strtolower($immediateMethodName) === '__tostring') { try { $stringableInterfaceReflection = $this->reflector->reflectClass($stringableClassName); $interfaces[$stringableClassName] = $stringableInterfaceReflection; } catch (IdentifierNotFound $exception) { // Stringable interface does not exist on target PHP version } // @infection-ignore-all Break_: There's no difference between break and continue - break is just optimization break; } } return $interfaces; } /** * @param array $interfaces * * @return array * * @psalm-suppress MoreSpecificReturnType */ private function addEnumInterfaces(array $interfaces) : array { assert($this->isEnum === \true); $interfaces[UnitEnum::class] = $this->reflector->reflectClass(UnitEnum::class); if ($this->isBackedEnum) { $interfaces[BackedEnum::class] = $this->reflector->reflectClass(BackedEnum::class); } /** @psalm-suppress LessSpecificReturnStatement */ return $interfaces; } /** @return list */ public function getTraitClassNames() : array { return $this->traitClassNames; } /** * Get the names of the traits used as an array of strings, if any are * defined. If this class does not have any defined traits, this will * return an empty array. * * @return list */ public function getTraitNames() : array { return array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionClass $trait) : string { /** @psalm-var trait-string $traitName */ $traitName = $trait->getName(); return $traitName; }, $this->getTraits()); } /** * Return a list of the aliases used when importing traits for this class. * The returned array is in key/value pair in this format:. * * 'aliasedMethodName' => 'ActualClass::actualMethod' * * @return array * * @example * // When reflecting a class such as: * class Foo * { * use MyTrait { * myTraitMethod as myAliasedMethod; * } * } * // This method would return * // ['myAliasedMethod' => 'MyTrait::myTraitMethod'] */ public function getTraitAliases() : array { return $this->traitsData['aliases']; } /** * Returns data when importing traits for this class: * * 'aliases': List of the aliases used when importing traits. In format: * * 'aliasedMethodName' => 'ActualClass::actualMethod' * * Example: * // When reflecting a code such as: * * use MyTrait { * myTraitMethod as myAliasedMethod; * } * * // This method would return * // ['myAliasedMethod' => 'MyTrait::myTraitMethod'] * * 'modifiers': Used modifiers when importing traits. In format: * * 'methodName' => 'modifier' * * Example: * // When reflecting a code such as: * * use MyTrait { * myTraitMethod as public; * } * * // This method would return * // ['myTraitMethod' => 1] * * 'precedences': Precedences used when importing traits. In format: * * 'Class::method' => 'Class::method' * * Example: * // When reflecting a code such as: * * use MyTrait, MyTrait2 { * MyTrait2::foo insteadof MyTrait1; * } * * // This method would return * // ['MyTrait1::foo' => 'MyTrait2::foo'] * * @return array{aliases: array, modifiers: array>, precedences: array} * @param ClassNode|InterfaceNode|TraitNode|EnumNode $node */ private function computeTraitsData($node) : array { $traitsData = ['aliases' => [], 'modifiers' => [], 'precedences' => []]; foreach ($node->getTraitUses() as $traitUsage) { $traitNames = $traitUsage->traits; $adaptations = $traitUsage->adaptations; foreach ($adaptations as $adaptation) { $usedTrait = $adaptation->trait; if ($usedTrait === null) { $usedTrait = end($traitNames); } $methodHash = $this->methodHash($usedTrait->toString(), $adaptation->method->toString()); if ($adaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) { if ($adaptation->newModifier !== null) { /** @var int-mask-of $modifier */ $modifier = $adaptation->newModifier; $traitsData['modifiers'][$methodHash] = $modifier; } if ($adaptation->newName) { $adaptationName = $adaptation->newName->name; assert($adaptationName !== ''); $traitsData['aliases'][$adaptationName] = $methodHash; continue; } } if (!$adaptation instanceof Node\Stmt\TraitUseAdaptation\Precedence || !$adaptation->insteadof) { continue; } foreach ($adaptation->insteadof as $insteadof) { $adaptationNameHash = $this->methodHash($insteadof->toString(), $adaptation->method->toString()); $traitsData['precedences'][$adaptationNameHash] = $methodHash; } } } return $traitsData; } /** * @return non-empty-string * * @psalm-pure */ private function methodHash(string $className, string $methodName) : string { return sprintf('%s::%s', $className, strtolower($methodName)); } /** @return list */ public function getInterfaceClassNames() : array { return $this->implementsClassNames; } /** * Gets the interfaces. * * @link https://php.net/manual/en/reflectionclass.getinterfaces.php * * @return array An associative array of interfaces, with keys as interface names and the array * values as {@see ReflectionClass} objects. */ public function getInterfaces() : array { if ($this->cachedInterfaces !== null) { return $this->cachedInterfaces; } $interfaces = array_merge([$this->getCurrentClassImplementedInterfacesIndexedByName()], array_map(static function (self $parentClass) : array { return $parentClass->getCurrentClassImplementedInterfacesIndexedByName(); }, $this->getParentClasses())); return $this->cachedInterfaces = array_merge(...array_reverse($interfaces)); } /** * Get only the interfaces that this class implements (i.e. do not search * up parent classes etc.) * * @return array */ public function getImmediateInterfaces() : array { if ($this->isTrait) { return []; } $interfaces = []; foreach ($this->implementsClassNames as $interfaceClassName) { try { $interfaces[$interfaceClassName] = $this->reflector->reflectClass($interfaceClassName); } catch (IdentifierNotFound $exception) { continue; } } if ($this->isEnum) { $interfaces = $this->addEnumInterfaces($interfaces); } return $this->addStringableInterface($interfaces); } /** * Gets the interface names. * * @link https://php.net/manual/en/reflectionclass.getinterfacenames.php * * @return list A numerical array with interface names as the values. */ public function getInterfaceNames() : array { if ($this->cachedInterfaceNames !== null) { return $this->cachedInterfaceNames; } return $this->cachedInterfaceNames = array_values(array_map(static function (self $interface) : string { return $interface->getName(); }, $this->getInterfaces())); } /** * Checks whether the given object is an instance. * * @link https://php.net/manual/en/reflectionclass.isinstance.php */ public function isInstance(object $object) : bool { $className = $this->getName(); // note: since $object was loaded, we can safely assume that $className is available in the current // php script execution context return $object instanceof $className; } /** * Checks whether the given class string is a subclass of this class. * * @link https://php.net/manual/en/reflectionclass.isinstance.php */ public function isSubclassOf(string $className) : bool { return in_array(ltrim($className, '\\'), $this->getParentClassNames(), \true); } /** * Checks whether this class implements the given interface. * * @link https://php.net/manual/en/reflectionclass.implementsinterface.php */ public function implementsInterface(string $interfaceName) : bool { return in_array(ltrim($interfaceName, '\\'), $this->getInterfaceNames(), \true); } /** * Checks whether this reflection is an instantiable class * * @link https://php.net/manual/en/reflectionclass.isinstantiable.php */ public function isInstantiable() : bool { // @TODO doesn't consider internal non-instantiable classes yet. if ($this->isAbstract()) { return \false; } if ($this->isInterface()) { return \false; } if ($this->isTrait()) { return \false; } $constructor = $this->getConstructor(); if ($constructor === null) { return \true; } return $constructor->isPublic(); } /** * Checks whether this is a reflection of a class that supports the clone operator * * @link https://php.net/manual/en/reflectionclass.iscloneable.php */ public function isCloneable() : bool { if (!$this->isInstantiable()) { return \false; } $cloneMethod = $this->getMethod('__clone'); if ($cloneMethod === null) { return \true; } return $cloneMethod->isPublic(); } /** * Checks if iterateable * * @link https://php.net/manual/en/reflectionclass.isiterateable.php */ public function isIterateable() : bool { return $this->isInstantiable() && $this->implementsInterface(Traversable::class); } public function isEnum() : bool { return $this->isEnum; } /** @return array */ private function getCurrentClassImplementedInterfacesIndexedByName() : array { if ($this->isTrait) { return []; } if ($this->isInterface) { // assumption: first key is the current interface return array_slice($this->getInterfacesHierarchy(AlreadyVisitedClasses::createEmpty()), 1); } $interfaces = []; foreach ($this->implementsClassNames as $name) { try { $interface = $this->reflector->reflectClass($name); foreach ($interface->getInterfacesHierarchy(AlreadyVisitedClasses::createEmpty()) as $n => $i) { $interfaces[$n] = $i; } } catch (IdentifierNotFound $exception) { continue; } } if ($this->isEnum) { $interfaces = $this->addEnumInterfaces($interfaces); } return $this->addStringableInterface($interfaces); } /** * This method allows us to retrieve all interfaces parent of this interface. Do not use on class nodes! * * @return array parent interfaces of this interface */ private function getInterfacesHierarchy(AlreadyVisitedClasses $alreadyVisitedClasses) : array { if (!$this->isInterface) { return []; } $interfaceClassName = $this->getName(); $alreadyVisitedClasses->push($interfaceClassName); /** @var array $interfaces */ $interfaces = [$interfaceClassName => $this]; foreach ($this->getImmediateInterfaces() as $interface) { $alreadyVisitedClassesCopyForInterface = clone $alreadyVisitedClasses; foreach ($interface->getInterfacesHierarchy($alreadyVisitedClassesCopyForInterface) as $extendedInterfaceName => $extendedInterface) { $interfaces[$extendedInterfaceName] = $extendedInterface; } } return $this->addStringableInterface($interfaces); } /** * Get the value of a static property, if it exists. Throws a * PropertyDoesNotExist exception if it does not exist or is not static. * (note, differs very slightly from internal reflection behaviour) * * @param non-empty-string $propertyName * * @throws ClassDoesNotExist * @throws NoObjectProvided * @throws NotAnObject * @throws ObjectNotInstanceOfClass * @return mixed */ public function getStaticPropertyValue(string $propertyName) { $property = $this->getProperty($propertyName); if (!$property || !$property->isStatic()) { throw PropertyDoesNotExist::fromName($propertyName); } return $property->getValue(); } /** * Set the value of a static property * * @param non-empty-string $propertyName * * @throws ClassDoesNotExist * @throws NoObjectProvided * @throws NotAnObject * @throws ObjectNotInstanceOfClass * @param mixed $value */ public function setStaticPropertyValue(string $propertyName, $value) : void { $property = $this->getProperty($propertyName); if (!$property || !$property->isStatic()) { throw PropertyDoesNotExist::fromName($propertyName); } $property->setValue($value); } /** @return array */ public function getStaticProperties() : array { $staticProperties = []; foreach ($this->getProperties() as $property) { if (!$property->isStatic()) { continue; } /** @psalm-suppress MixedAssignment */ $staticProperties[$property->getName()] = $property->getValue(); } return $staticProperties; } /** @return list */ public function getAttributes() : array { return $this->attributes; } /** @return list */ public function getAttributesByName(string $name) : array { return ReflectionAttributeHelper::filterAttributesByName($this->getAttributes(), $name); } /** * @param class-string $className * * @return list */ public function getAttributesByInstance(string $className) : array { return ReflectionAttributeHelper::filterAttributesByInstance($this->getAttributes(), $className); } } reflector = $reflector; $this->reflectionClass = $reflectionClass; $this->object = $object; } /** * Pass an instance of an object to this method to reflect it * * @throws ReflectionException * @throws IdentifierNotFound */ public static function createFromInstance(object $instance) : \PHPStan\BetterReflection\Reflection\ReflectionClass { $className = \get_class($instance); $betterReflection = new BetterReflection(); if (preg_match(\PHPStan\BetterReflection\Reflection\ReflectionClass::ANONYMOUS_CLASS_NAME_PREFIX_REGEXP, $className) === 1) { $reflector = new DefaultReflector(new AggregateSourceLocator([$betterReflection->sourceLocator(), new AnonymousClassObjectSourceLocator($instance, $betterReflection->phpParser())])); } else { $reflector = $betterReflection->reflector(); } return new self($reflector, $reflector->reflectClass($className), $instance); } /** * Reflect on runtime properties for the current instance * * @see ReflectionClass::getProperties() for the usage of $filter * * @param int-mask-of $filter * * @return array */ private function getRuntimeProperties(int $filter = 0) : array { if (!$this->reflectionClass->isInstance($this->object)) { throw new InvalidArgumentException('Cannot reflect runtime properties of a separate class'); } if ($filter !== 0 && !($filter & CoreReflectionProperty::IS_PUBLIC)) { return []; } // Ensure we have already cached existing properties so we can add to them $this->reflectionClass->getProperties(); // Only known current way is to use internal ReflectionObject to get // the runtime-declared properties :/ $reflectionProperties = (new CoreReflectionObject($this->object))->getProperties(); $runtimeProperties = []; foreach ($reflectionProperties as $property) { $propertyName = $property->getName(); if ($this->reflectionClass->hasProperty($propertyName)) { continue; } $propertyNode = $this->createPropertyNodeFromRuntimePropertyReflection($property, $this->object); $runtimeProperties[$propertyName] = \PHPStan\BetterReflection\Reflection\ReflectionProperty::createFromNode($this->reflector, $propertyNode, $propertyNode->props[0], $this, $this, \false, \false); } return $runtimeProperties; } /** * Create an AST PropertyNode given a reflection * * Note that we don't copy across DocBlock, protected, private or static * because runtime properties can't have these attributes. */ private function createPropertyNodeFromRuntimePropertyReflection(CoreReflectionProperty $property, object $instance) : PropertyNode { $builder = new PropertyNodeBuilder($property->getName()); $builder->setDefault($property->getValue($instance)); $builder->makePublic(); return $builder->getNode(); } public function getShortName() : string { return $this->reflectionClass->getShortName(); } public function getName() : string { return $this->reflectionClass->getName(); } public function getNamespaceName() : ?string { return $this->reflectionClass->getNamespaceName(); } public function inNamespace() : bool { return $this->reflectionClass->inNamespace(); } /** @return non-empty-string|null */ public function getExtensionName() : ?string { return $this->reflectionClass->getExtensionName(); } /** * {@inheritDoc} */ public function getMethods(int $filter = 0) : array { return $this->reflectionClass->getMethods($filter); } /** * {@inheritDoc} */ public function getImmediateMethods(int $filter = 0) : array { return $this->reflectionClass->getImmediateMethods($filter); } /** @param non-empty-string $methodName */ public function getMethod(string $methodName) : ?\PHPStan\BetterReflection\Reflection\ReflectionMethod { return $this->reflectionClass->getMethod($methodName); } /** @param non-empty-string $methodName */ public function hasMethod(string $methodName) : bool { return $this->reflectionClass->hasMethod($methodName); } /** * {@inheritDoc} */ public function getImmediateConstants(int $filter = 0) : array { return $this->reflectionClass->getImmediateConstants($filter); } /** * {@inheritDoc} */ public function getConstants(int $filter = 0) : array { return $this->reflectionClass->getConstants($filter); } public function hasConstant(string $name) : bool { return $this->reflectionClass->hasConstant($name); } public function getConstant(string $name) : ?\PHPStan\BetterReflection\Reflection\ReflectionClassConstant { return $this->reflectionClass->getConstant($name); } public function getConstructor() : ?\PHPStan\BetterReflection\Reflection\ReflectionMethod { return $this->reflectionClass->getConstructor(); } /** * {@inheritDoc} */ public function getProperties(int $filter = 0) : array { return array_merge($this->reflectionClass->getProperties($filter), $this->getRuntimeProperties($filter)); } /** * {@inheritDoc} */ public function getImmediateProperties(int $filter = 0) : array { return array_merge($this->reflectionClass->getImmediateProperties($filter), $this->getRuntimeProperties($filter)); } public function getProperty(string $name) : ?\PHPStan\BetterReflection\Reflection\ReflectionProperty { $runtimeProperties = $this->getRuntimeProperties(); if (isset($runtimeProperties[$name])) { return $runtimeProperties[$name]; } return $this->reflectionClass->getProperty($name); } public function hasProperty(string $name) : bool { $runtimeProperties = $this->getRuntimeProperties(); return isset($runtimeProperties[$name]) || $this->reflectionClass->hasProperty($name); } /** * {@inheritDoc} */ public function getDefaultProperties() : array { return array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionProperty $property) { return $property->getDefaultValue(); }, array_filter($this->getProperties(), static function (\PHPStan\BetterReflection\Reflection\ReflectionProperty $property) : bool { return $property->isDefault(); })); } /** @return non-empty-string|null */ public function getFileName() : ?string { return $this->reflectionClass->getFileName(); } public function getLocatedSource() : LocatedSource { return $this->reflectionClass->getLocatedSource(); } public function getStartLine() : int { return $this->reflectionClass->getStartLine(); } public function getEndLine() : int { return $this->reflectionClass->getEndLine(); } public function getStartColumn() : int { return $this->reflectionClass->getStartColumn(); } public function getEndColumn() : int { return $this->reflectionClass->getEndColumn(); } public function getParentClass() : ?\PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->reflectionClass->getParentClass(); } /** @return class-string|null */ public function getParentClassName() : ?string { return $this->reflectionClass->getParentClassName(); } /** * {@inheritDoc} */ public function getParentClassNames() : array { return $this->reflectionClass->getParentClassNames(); } /** @return non-empty-string|null */ public function getDocComment() : ?string { return $this->reflectionClass->getDocComment(); } public function isAnonymous() : bool { return $this->reflectionClass->isAnonymous(); } public function isInternal() : bool { return $this->reflectionClass->isInternal(); } public function isUserDefined() : bool { return $this->reflectionClass->isUserDefined(); } public function isDeprecated() : bool { return $this->reflectionClass->isDeprecated(); } public function isAbstract() : bool { return $this->reflectionClass->isAbstract(); } public function isFinal() : bool { return $this->reflectionClass->isFinal(); } public function isReadOnly() : bool { return $this->reflectionClass->isReadOnly(); } public function getModifiers() : int { return $this->reflectionClass->getModifiers(); } public function isTrait() : bool { return $this->reflectionClass->isTrait(); } public function isInterface() : bool { return $this->reflectionClass->isInterface(); } /** * {@inheritDoc} */ public function getTraitClassNames() : array { return $this->reflectionClass->getTraitClassNames(); } /** * {@inheritDoc} */ public function getTraits() : array { return $this->reflectionClass->getTraits(); } /** * {@inheritDoc} */ public function getTraitNames() : array { return $this->reflectionClass->getTraitNames(); } /** * {@inheritDoc} */ public function getTraitAliases() : array { return $this->reflectionClass->getTraitAliases(); } /** * {@inheritDoc} */ public function getInterfaceClassNames() : array { return $this->reflectionClass->getInterfaceClassNames(); } /** * {@inheritDoc} */ public function getInterfaces() : array { return $this->reflectionClass->getInterfaces(); } /** * {@inheritDoc} */ public function getImmediateInterfaces() : array { return $this->reflectionClass->getImmediateInterfaces(); } /** * {@inheritDoc} */ public function getInterfaceNames() : array { return $this->reflectionClass->getInterfaceNames(); } public function isInstance(object $object) : bool { return $this->reflectionClass->isInstance($object); } public function isSubclassOf(string $className) : bool { return $this->reflectionClass->isSubclassOf($className); } public function implementsInterface(string $interfaceName) : bool { return $this->reflectionClass->implementsInterface($interfaceName); } public function isInstantiable() : bool { return $this->reflectionClass->isInstantiable(); } public function isCloneable() : bool { return $this->reflectionClass->isCloneable(); } public function isIterateable() : bool { return $this->reflectionClass->isIterateable(); } public function isEnum() : bool { return $this->reflectionClass->isEnum(); } /** * {@inheritDoc} */ public function getStaticProperties() : array { return $this->reflectionClass->getStaticProperties(); } /** * @param mixed $value */ public function setStaticPropertyValue(string $propertyName, $value) : void { $this->reflectionClass->setStaticPropertyValue($propertyName, $value); } /** * @return mixed */ public function getStaticPropertyValue(string $propertyName) { return $this->reflectionClass->getStaticPropertyValue($propertyName); } /** @return list */ public function getAttributes() : array { return $this->reflectionClass->getAttributes(); } /** @return list */ public function getAttributesByName(string $name) : array { return $this->reflectionClass->getAttributesByName($name); } /** * @param class-string $className * * @return list */ public function getAttributesByInstance(string $className) : array { return $this->reflectionClass->getAttributesByInstance($className); } } $value */ $value = $constantReflection->getValue(); return sprintf("Constant [ %s%s %s %s ] { %s }\n", $constantReflection->isFinal() ? 'final ' : '', self::visibilityToString($constantReflection), gettype($value), $constantReflection->getName(), is_array($value) ? 'Array' : (string) $value); } /** @psalm-pure */ private static function visibilityToString(ReflectionClassConstant $constantReflection) : string { if ($constantReflection->isProtected()) { return 'protected'; } if ($constantReflection->isPrivate()) { return 'private'; } return 'public'; } } isStatic()) { $stateModifier = $propertyReflection->isDefault() ? ' ' : ' '; } $type = $propertyReflection->getType(); return sprintf('Property [%s %s%s%s%s $%s ]', $stateModifier, self::visibilityToString($propertyReflection), $propertyReflection->isStatic() ? ' static' : '', $propertyReflection->isReadOnly() ? ' readonly' : '', $type !== null ? sprintf(' %s', \PHPStan\BetterReflection\Reflection\StringCast\ReflectionTypeStringCast::toString($type)) : '', $propertyReflection->getName()); } /** @psalm-pure */ private static function visibilityToString(ReflectionProperty $propertyReflection) : string { if ($propertyReflection->isProtected()) { return 'protected'; } if ($propertyReflection->isPrivate()) { return 'private'; } return 'public'; } } getArguments(); $argumentsFormat = $arguments !== [] ? " {\n - Arguments [%d] {%s\n }\n}" : ''; return sprintf('Attribute [ %s ]' . $argumentsFormat . "\n", $attributeReflection->getName(), count($arguments), self::argumentsToString($arguments)); } /** * @param array $arguments * * @psalm-pure */ private static function argumentsToString(array $arguments) : string { if ($arguments === []) { return ''; } $string = ''; $argumentNo = 0; /** @psalm-suppress MixedAssignment */ foreach ($arguments as $argumentName => $argumentValue) { $string .= sprintf("\n Argument #%d [ %s%s ]", $argumentNo, is_string($argumentName) ? sprintf('%s = ', $argumentName) : '', self::argumentValueToString($argumentValue)); $argumentNo++; } return $string; } /** @psalm-pure * @param mixed $value */ private static function argumentValueToString($value) : string { if (is_array($value)) { return 'Array'; } if (is_string($value) && strlen($value) > 15) { return var_export(substr($value, 0, 15) . '...', \true); } return var_export($value, \true); } } %s%s%s %s%s%s ] {\n"; $format .= "%s\n"; $format .= " - Constants [%d] {%s\n }\n\n"; $format .= " - Static properties [%d] {%s\n }\n\n"; $format .= " - Static methods [%d] {%s\n }\n\n"; $format .= " - Properties [%d] {%s\n }\n\n"; $format .= $isObject ? " - Dynamic properties [%d] {%s\n }\n\n" : '%s%s'; $format .= " - Methods [%d] {%s\n }\n"; $format .= "}\n"; $type = self::typeToString($classReflection); $constants = $classReflection->getConstants(); $enumCases = $classReflection instanceof ReflectionEnum ? $classReflection->getCases() : []; $staticProperties = self::getStaticProperties($classReflection); $staticMethods = self::getStaticMethods($classReflection); $defaultProperties = self::getDefaultProperties($classReflection); $dynamicProperties = self::getDynamicProperties($classReflection); $methods = self::getMethods($classReflection); return sprintf($format, $isObject ? 'Object of class' : $type, self::sourceToString($classReflection), $classReflection->isFinal() ? 'final ' : '', $classReflection->isAbstract() ? 'abstract ' : '', strtolower($type), $classReflection->getName(), self::extendsToString($classReflection), self::implementsToString($classReflection), self::fileAndLinesToString($classReflection), count($constants) + count($enumCases), self::constantsToString($constants, $enumCases), count($staticProperties), self::propertiesToString($staticProperties), count($staticMethods), self::methodsToString($staticMethods), count($defaultProperties), self::propertiesToString($defaultProperties), $isObject ? count($dynamicProperties) : '', $isObject ? self::propertiesToString($dynamicProperties) : '', count($methods), self::methodsToString($methods, 2)); } /** @psalm-pure */ private static function typeToString(ReflectionClass $classReflection) : string { if ($classReflection->isInterface()) { return 'Interface'; } if ($classReflection->isTrait()) { return 'Trait'; } return 'Class'; } /** @psalm-pure */ private static function sourceToString(ReflectionClass $classReflection) : string { if ($classReflection->isUserDefined()) { return 'user'; } $extensionName = $classReflection->getExtensionName(); assert(is_string($extensionName)); return sprintf('internal:%s', $extensionName); } /** @psalm-pure */ private static function extendsToString(ReflectionClass $classReflection) : string { $parentClass = $classReflection->getParentClass(); if ($parentClass === null) { return ''; } return ' extends ' . $parentClass->getName(); } /** @psalm-pure */ private static function implementsToString(ReflectionClass $classReflection) : string { $interfaceNames = $classReflection->getInterfaceNames(); if ($interfaceNames === []) { return ''; } return ' implements ' . implode(', ', $interfaceNames); } /** @psalm-pure */ private static function fileAndLinesToString(ReflectionClass $classReflection) : string { if ($classReflection->isInternal()) { return ''; } $fileName = $classReflection->getFileName(); if ($fileName === null) { return ''; } return sprintf(" @@ %s %d-%d\n", $fileName, $classReflection->getStartLine(), $classReflection->getEndLine()); } /** * @param array $constants * @param array $enumCases * * @psalm-pure */ private static function constantsToString(array $constants, array $enumCases) : string { if ($constants === [] && $enumCases === []) { return ''; } $items = array_map(static function (ReflectionEnumCase $enumCaseReflection) : string { return trim(\PHPStan\BetterReflection\Reflection\StringCast\ReflectionEnumCaseStringCast::toString($enumCaseReflection)); }, $enumCases) + array_map(static function (ReflectionClassConstant $constantReflection) : string { return trim(\PHPStan\BetterReflection\Reflection\StringCast\ReflectionClassConstantStringCast::toString($constantReflection)); }, $constants); return self::itemsToString($items); } /** * @param array $properties * * @psalm-pure */ private static function propertiesToString(array $properties) : string { if ($properties === []) { return ''; } return self::itemsToString(array_map(static function (ReflectionProperty $propertyReflection) : string { return \PHPStan\BetterReflection\Reflection\StringCast\ReflectionPropertyStringCast::toString($propertyReflection); }, $properties)); } /** * @param array $methods * * @psalm-pure */ private static function methodsToString(array $methods, int $emptyLinesAmongItems = 1) : string { if ($methods === []) { return ''; } return self::itemsToString(array_map(static function (ReflectionMethod $method) : string { return \PHPStan\BetterReflection\Reflection\StringCast\ReflectionMethodStringCast::toString($method); }, $methods), $emptyLinesAmongItems); } /** * @param array $items * * @psalm-pure */ private static function itemsToString(array $items, int $emptyLinesAmongItems = 1) : string { $string = implode(str_repeat("\n", $emptyLinesAmongItems), $items); return "\n" . preg_replace('/(^|\\n)(?!\\n)/', '\\1' . self::indent(), $string); } /** @psalm-pure */ private static function indent() : string { return str_repeat(' ', 4); } /** * @return array * * @psalm-pure */ private static function getStaticProperties(ReflectionClass $classReflection) : array { return array_filter($classReflection->getProperties(), static function (ReflectionProperty $propertyReflection) : bool { return $propertyReflection->isStatic(); }); } /** * @return array * * @psalm-pure */ private static function getStaticMethods(ReflectionClass $classReflection) : array { return array_filter($classReflection->getMethods(), static function (ReflectionMethod $methodReflection) : bool { return $methodReflection->isStatic(); }); } /** * @return array * * @psalm-pure */ private static function getDefaultProperties(ReflectionClass $classReflection) : array { return array_filter($classReflection->getProperties(), static function (ReflectionProperty $propertyReflection) : bool { return !$propertyReflection->isStatic() && $propertyReflection->isDefault(); }); } /** * @return array * * @psalm-pure */ private static function getDynamicProperties(ReflectionClass $classReflection) : array { return array_filter($classReflection->getProperties(), static function (ReflectionProperty $propertyReflection) : bool { return !$propertyReflection->isStatic() && !$propertyReflection->isDefault(); }); } /** * @return array * * @psalm-pure */ private static function getMethods(ReflectionClass $classReflection) : array { return array_filter($classReflection->getMethods(), static function (ReflectionMethod $methodReflection) : bool { return !$methodReflection->isStatic(); }); } } getNumberOfParameters() > 0 || $methodReflection->hasReturnType() ? "\n\n - Parameters [%d] {%s\n }" : ''; $returnTypeFormat = $methodReflection->hasReturnType() ? "\n - Return [ %s ]" : ''; return sprintf('Method [ <%s%s%s%s%s%s>%s%s%s %s method %s ] {%s' . $parametersFormat . $returnTypeFormat . "\n}", self::sourceToString($methodReflection), $methodReflection->isConstructor() ? ', ctor' : '', $methodReflection->isDestructor() ? ', dtor' : '', self::overwritesToString($methodReflection), self::inheritsToString($methodReflection), self::prototypeToString($methodReflection), $methodReflection->isFinal() ? ' final' : '', $methodReflection->isStatic() ? ' static' : '', $methodReflection->isAbstract() ? ' abstract' : '', self::visibilityToString($methodReflection), $methodReflection->getName(), self::fileAndLinesToString($methodReflection), count($methodReflection->getParameters()), self::parametersToString($methodReflection), self::returnTypeToString($methodReflection)); } /** @psalm-pure */ private static function sourceToString(ReflectionMethod $methodReflection) : string { if ($methodReflection->isUserDefined()) { return 'user'; } $extensionName = $methodReflection->getExtensionName(); assert(is_string($extensionName)); return sprintf('internal:%s', $extensionName); } /** @psalm-pure */ private static function overwritesToString(ReflectionMethod $methodReflection) : string { $parentClass = $methodReflection->getDeclaringClass()->getParentClass(); if ($parentClass === null) { return ''; } if (!$parentClass->hasMethod($methodReflection->getName())) { return ''; } return sprintf(', overwrites %s', $parentClass->getName()); } /** @psalm-pure */ private static function inheritsToString(ReflectionMethod $methodReflection) : string { if ($methodReflection->getDeclaringClass() === $methodReflection->getCurrentClass()) { return ''; } return sprintf(', inherits %s', $methodReflection->getDeclaringClass()->getName()); } /** @psalm-pure */ private static function prototypeToString(ReflectionMethod $methodReflection) : string { try { return sprintf(', prototype %s', $methodReflection->getPrototype()->getDeclaringClass()->getName()); } catch (MethodPrototypeNotFound $exception) { return ''; } } /** @psalm-pure */ private static function visibilityToString(ReflectionMethod $methodReflection) : string { if ($methodReflection->isProtected()) { return 'protected'; } if ($methodReflection->isPrivate()) { return 'private'; } return 'public'; } /** @psalm-pure */ private static function fileAndLinesToString(ReflectionMethod $methodReflection) : string { if ($methodReflection->isInternal()) { return ''; } $fileName = $methodReflection->getFileName(); assert(is_string($fileName)); return sprintf("\n @@ %s %d - %d", $fileName, $methodReflection->getStartLine(), $methodReflection->getEndLine()); } /** @psalm-pure */ private static function parametersToString(ReflectionMethod $methodReflection) : string { return array_reduce($methodReflection->getParameters(), static function (string $string, ReflectionParameter $parameterReflection) : string { return $string . "\n " . \PHPStan\BetterReflection\Reflection\StringCast\ReflectionParameterStringCast::toString($parameterReflection); }, ''); } /** @psalm-pure */ private static function returnTypeToString(ReflectionMethod $methodReflection) : string { $type = $methodReflection->getReturnType(); if ($type === null) { return ''; } return \PHPStan\BetterReflection\Reflection\StringCast\ReflectionTypeStringCast::toString($type); } } $value */ $value = $constantReflection->getValue(); if (is_object($value)) { $valueAsString = 'Object'; } elseif (is_array($value)) { $valueAsString = 'Array'; } else { $valueAsString = (string) $value; } return sprintf('Constant [ <%s> %s %s ] {%s %s }', self::sourceToString($constantReflection), gettype($value), $constantReflection->getName(), self::fileAndLinesToString($constantReflection), $valueAsString); } /** @psalm-pure */ private static function sourceToString(ReflectionConstant $constantReflection) : string { if ($constantReflection->isUserDefined()) { return 'user'; } $extensionName = $constantReflection->getExtensionName(); assert(is_string($extensionName)); return sprintf('internal:%s', $extensionName); } /** @psalm-pure */ private static function fileAndLinesToString(ReflectionConstant $constantReflection) : string { if ($constantReflection->isInternal()) { return ''; } $fileName = $constantReflection->getFileName(); if ($fileName === null) { return ''; } return sprintf("\n @@ %s %d - %d\n", $fileName, $constantReflection->getStartLine(), $constantReflection->getEndLine()); } } getNumberOfParameters() > 0 || $functionReflection->hasReturnType() ? "\n\n - Parameters [%d] {%s\n }" : ''; $returnTypeFormat = $functionReflection->hasReturnType() ? "\n - Return [ %s ]" : ''; return sprintf('Function [ <%s> function %s ] {%s' . $parametersFormat . $returnTypeFormat . "\n}", self::sourceToString($functionReflection), $functionReflection->getName(), self::fileAndLinesToString($functionReflection), count($functionReflection->getParameters()), self::parametersToString($functionReflection), self::returnTypeToString($functionReflection)); } /** @psalm-pure */ private static function sourceToString(ReflectionFunction $functionReflection) : string { if ($functionReflection->isUserDefined()) { return 'user'; } $extensionName = $functionReflection->getExtensionName(); assert(is_string($extensionName)); return sprintf('internal:%s', $extensionName); } /** @psalm-pure */ private static function fileAndLinesToString(ReflectionFunction $functionReflection) : string { if ($functionReflection->isInternal()) { return ''; } $fileName = $functionReflection->getFileName(); if ($fileName === null) { return ''; } return sprintf("\n @@ %s %d - %d", $fileName, $functionReflection->getStartLine(), $functionReflection->getEndLine()); } /** @psalm-pure */ private static function parametersToString(ReflectionFunction $functionReflection) : string { return array_reduce($functionReflection->getParameters(), static function (string $string, ReflectionParameter $parameterReflection) : string { return $string . "\n " . \PHPStan\BetterReflection\Reflection\StringCast\ReflectionParameterStringCast::toString($parameterReflection); }, ''); } /** @psalm-pure */ private static function returnTypeToString(ReflectionFunction $methodReflection) : string { $type = $methodReflection->getReturnType(); if ($type === null) { return ''; } return \PHPStan\BetterReflection\Reflection\StringCast\ReflectionTypeStringCast::toString($type); } } getPosition(), $parameterReflection->isOptional() ? '' : '', self::typeToString($parameterReflection), $parameterReflection->isVariadic() ? '...' : '', $parameterReflection->isPassedByReference() ? '&' : '', $parameterReflection->getName(), self::valueToString($parameterReflection)); } /** @psalm-pure */ private static function typeToString(ReflectionParameter $parameterReflection) : string { $type = $parameterReflection->getType(); if ($type === null) { return ''; } return \PHPStan\BetterReflection\Reflection\StringCast\ReflectionTypeStringCast::toString($type) . ' '; } /** @psalm-pure */ private static function valueToString(ReflectionParameter $parameterReflection) : string { if (!($parameterReflection->isOptional() && $parameterReflection->isDefaultValueAvailable())) { return ''; } $defaultValue = $parameterReflection->getDefaultValue(); if (is_array($defaultValue)) { return ' = Array'; } if (is_string($defaultValue) && strlen($defaultValue) > 15) { return ' = ' . var_export(substr($defaultValue, 0, 15) . '...', \true); } return ' = ' . var_export($defaultValue, \true); } } getDeclaringEnum(); $value = $enumReflection->isBacked() ? $enumCaseReflection->getValue() : 'Object'; $type = $enumReflection->isBacked() ? gettype($value) : $enumReflection->getName(); return sprintf("Constant [ public %s %s ] { %s }\n", $type, $enumCaseReflection->getName(), $value); } } getTypes(), static function (ReflectionType $type) : bool { return !($type instanceof ReflectionNamedType && $type->getName() === 'null'); })); if ($type->allowsNull() && count($nonNullTypes) === 1 && $nonNullTypes[0] instanceof ReflectionNamedType) { return '?' . $nonNullTypes[0]->__toString(); } } return $type->__toString(); } } */ private $arguments = []; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionClass|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant|\PHPStan\BetterReflection\Reflection\ReflectionEnumCase|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionParameter */ private $owner; /** * @var bool */ private $isRepeated; /** @internal * @param \PHPStan\BetterReflection\Reflection\ReflectionClass|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant|\PHPStan\BetterReflection\Reflection\ReflectionEnumCase|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionParameter $owner */ public function __construct(Reflector $reflector, Node\Attribute $node, $owner, bool $isRepeated) { $this->reflector = $reflector; $this->owner = $owner; $this->isRepeated = $isRepeated; $name = $node->name->toString(); assert($name !== ''); $this->name = $name; foreach ($node->args as $argNo => $arg) { $this->arguments[(($argName = $arg->name) ? $argName->toString() : null) ?? $argNo] = $arg->value; } } /** @internal * @param \PHPStan\BetterReflection\Reflection\ReflectionClass|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant|\PHPStan\BetterReflection\Reflection\ReflectionEnumCase|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionParameter $owner */ public function withOwner($owner) : self { $clone = clone $this; $clone->owner = $owner; return $clone; } /** @return non-empty-string */ public function getName() : string { return $this->name; } public function getClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->reflector->reflectClass($this->getName()); } /** @return array */ public function getArgumentsExpressions() : array { return $this->arguments; } /** * @deprecated Use getArgumentsExpressions() * @return array */ public function getArguments() : array { $compiler = new CompileNodeToValue(); $context = new CompilerContext($this->reflector, $this->owner); return array_map(static function (Node\Expr $value) use($compiler, $context) { return $compiler->__invoke($value, $context)->value; }, $this->arguments); } /** @return int-mask-of */ public function getTarget() : int { switch (\true) { case $this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionClass: return Attribute::TARGET_CLASS; case $this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionFunction: return Attribute::TARGET_FUNCTION; case $this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionMethod: return Attribute::TARGET_METHOD; case $this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionProperty: return Attribute::TARGET_PROPERTY; case $this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionClassConstant: return Attribute::TARGET_CLASS_CONSTANT; case $this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionEnumCase: return Attribute::TARGET_CLASS_CONSTANT; case $this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionParameter: return Attribute::TARGET_PARAMETER; default: throw new LogicException('unknown owner'); } } public function isRepeated() : bool { return $this->isRepeated; } /** @return non-empty-string */ public function __toString() : string { return ReflectionAttributeStringCast::toString($this); } } null, 'float' => null, 'string' => null, 'bool' => null, 'callable' => null, 'self' => null, 'parent' => null, 'array' => null, 'iterable' => null, 'object' => null, 'void' => null, 'mixed' => null, 'static' => null, 'null' => null, 'never' => null, 'false' => null, 'true' => null]; /** @var non-empty-string */ private $name; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant */ private $owner; /** * @var \PhpParser\Node\Identifier|\PhpParser\Node\Name */ private $type; /** @internal * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $owner * @param \PhpParser\Node\Identifier|\PhpParser\Node\Name $type */ public function __construct(Reflector $reflector, $owner, $type) { $this->reflector = $reflector; $this->owner = $owner; $this->type = $type; $name = $type->toString(); assert($name !== ''); $this->name = $name; } /** @internal * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $owner * @return $this */ public function withOwner($owner) { $clone = clone $this; $clone->owner = $owner; return $clone; } /** @return non-empty-string */ public function getName() : string { return $this->name; } /** * Checks if it is a built-in type (i.e., it's not an object...) * * @see https://php.net/manual/en/reflectiontype.isbuiltin.php */ public function isBuiltin() : bool { return array_key_exists(strtolower($this->name), self::BUILT_IN_TYPES); } public function getClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { if (!$this->isBuiltin()) { return $this->reflector->reflectClass($this->name); } if ($this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionEnum || $this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionFunction || $this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionParameter && $this->owner->getDeclaringFunction() instanceof \PHPStan\BetterReflection\Reflection\ReflectionFunction) { throw new LogicException(sprintf('The type %s cannot be resolved to class', $this->name)); } $lowercaseName = strtolower($this->name); if ($lowercaseName === 'self') { $class = $this->owner->getImplementingClass(); assert($class instanceof \PHPStan\BetterReflection\Reflection\ReflectionClass); return $class; } if ($lowercaseName === 'parent') { $class = $this->owner->getDeclaringClass(); assert($class instanceof \PHPStan\BetterReflection\Reflection\ReflectionClass); $parentClass = $class->getParentClass(); assert($parentClass instanceof \PHPStan\BetterReflection\Reflection\ReflectionClass); return $parentClass; } if ($this->owner instanceof \PHPStan\BetterReflection\Reflection\ReflectionMethod && $lowercaseName === 'static') { return $this->owner->getCurrentClass(); } throw new LogicException(sprintf('The type %s cannot be resolved to class', $this->name)); } public function allowsNull() : bool { switch (strtolower($this->name)) { case 'mixed': return \true; case 'null': return \true; default: return \false; } } public function isIdentifier() : bool { return $this->type instanceof Identifier; } /** @return non-empty-string */ public function __toString() : string { return $this->getName(); } } */ private $attributes; /** @var positive-int|null */ private $startLine; /** @var positive-int|null */ private $endLine; /** @var positive-int|null */ private $startColumn; /** @var positive-int|null */ private $endColumn; /** @psalm-allow-private-mutation * @var \PHPStan\BetterReflection\NodeCompiler\CompiledValue|null */ private $compiledDefaultValue = null; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction */ private $function; /** * @var int */ private $parameterIndex; /** * @var bool */ private $isOptional; /** * @param \PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction $function */ private function __construct(Reflector $reflector, ParamNode $node, $function, int $parameterIndex, bool $isOptional) { $this->reflector = $reflector; $this->function = $function; $this->parameterIndex = $parameterIndex; $this->isOptional = $isOptional; assert($node->var instanceof Node\Expr\Variable); assert(is_string($node->var->name)); $name = $node->var->name; assert($name !== ''); $this->name = $name; $this->default = $node->default; $this->isPromoted = $node->flags !== 0; $this->type = $this->createType($node); $this->isVariadic = $node->variadic; $this->byRef = $node->byRef; $this->attributes = ReflectionAttributeHelper::createAttributes($reflector, $this, $node->attrGroups); if ($node->hasAttribute('startLine')) { $startLine = $node->getStartLine(); assert($startLine > 0); } else { $startLine = null; } if ($node->hasAttribute('endLine')) { $endLine = $node->getEndLine(); assert($endLine > 0); } else { $endLine = null; } $this->startLine = $startLine; $this->endLine = $endLine; try { $this->startColumn = CalculateReflectionColumn::getStartColumn($function->getLocatedSource()->getSource(), $node); } catch (NoNodePosition $exception) { $this->startColumn = null; } try { $this->endColumn = CalculateReflectionColumn::getEndColumn($function->getLocatedSource()->getSource(), $node); } catch (NoNodePosition $exception) { $this->endColumn = null; } } /** * Create a reflection of a parameter using a class name * * @param non-empty-string $methodName * @param non-empty-string $parameterName * * @throws OutOfBoundsException */ public static function createFromClassNameAndMethod(string $className, string $methodName, string $parameterName) : self { $parameter = ($getMethod = \PHPStan\BetterReflection\Reflection\ReflectionClass::createFromName($className)->getMethod($methodName)) ? $getMethod->getParameter($parameterName) : null; if ($parameter === null) { throw new OutOfBoundsException(sprintf('Could not find parameter: %s', $parameterName)); } return $parameter; } /** * Create a reflection of a parameter using an instance * * @param non-empty-string $methodName * @param non-empty-string $parameterName * * @throws OutOfBoundsException */ public static function createFromClassInstanceAndMethod(object $instance, string $methodName, string $parameterName) : self { $parameter = ($getMethod = \PHPStan\BetterReflection\Reflection\ReflectionClass::createFromInstance($instance)->getMethod($methodName)) ? $getMethod->getParameter($parameterName) : null; if ($parameter === null) { throw new OutOfBoundsException(sprintf('Could not find parameter: %s', $parameterName)); } return $parameter; } /** * Create a reflection of a parameter using a closure * * @param non-empty-string $parameterName * * @throws OutOfBoundsException */ public static function createFromClosure(Closure $closure, string $parameterName) : \PHPStan\BetterReflection\Reflection\ReflectionParameter { $parameter = \PHPStan\BetterReflection\Reflection\ReflectionFunction::createFromClosure($closure)->getParameter($parameterName); if ($parameter === null) { throw new OutOfBoundsException(sprintf('Could not find parameter: %s', $parameterName)); } return $parameter; } /** * Create the parameter from the given spec. Possible $spec parameters are: * * - [$instance, 'method'] * - ['Foo', 'bar'] * - ['foo'] * - [function () {}] * * @param object[]|string[]|string|Closure $spec * @param non-empty-string $parameterName * * @throws Exception * @throws InvalidArgumentException */ public static function createFromSpec($spec, string $parameterName) : self { try { if (is_array($spec) && count($spec) === 2 && is_string($spec[1])) { assert($spec[1] !== ''); if (is_object($spec[0])) { return self::createFromClassInstanceAndMethod($spec[0], $spec[1], $parameterName); } return self::createFromClassNameAndMethod($spec[0], $spec[1], $parameterName); } if (is_string($spec)) { $parameter = \PHPStan\BetterReflection\Reflection\ReflectionFunction::createFromName($spec)->getParameter($parameterName); if ($parameter === null) { throw new OutOfBoundsException(sprintf('Could not find parameter: %s', $parameterName)); } return $parameter; } if ($spec instanceof Closure) { return self::createFromClosure($spec, $parameterName); } } catch (OutOfBoundsException $e) { throw new InvalidArgumentException('Could not create reflection from the spec given', 0, $e); } throw new InvalidArgumentException('Could not create reflection from the spec given'); } /** @return non-empty-string */ public function __toString() : string { return ReflectionParameterStringCast::toString($this); } /** * @internal * * @param ParamNode $node Node has to be processed by the PhpParser\NodeVisitor\NameResolver * @param \PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction $function */ public static function createFromNode(Reflector $reflector, ParamNode $node, $function, int $parameterIndex, bool $isOptional) : self { return new self($reflector, $node, $function, $parameterIndex, $isOptional); } /** @internal * @param \PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction $function */ public function withFunction($function) : self { $clone = clone $this; $clone->function = $function; if ($clone->type !== null) { $clone->type = $clone->type->withOwner($clone); } $clone->attributes = array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionAttribute $attribute) use($clone) : \PHPStan\BetterReflection\Reflection\ReflectionAttribute { return $attribute->withOwner($clone); }, $this->attributes); $this->compiledDefaultValue = null; return $clone; } /** @throws LogicException */ private function getCompiledDefaultValue() : CompiledValue { if (!$this->isDefaultValueAvailable()) { throw new LogicException('This parameter does not have a default value available'); } if ($this->compiledDefaultValue === null) { $this->compiledDefaultValue = (new CompileNodeToValue())->__invoke($this->default, new CompilerContext($this->reflector, $this)); } return $this->compiledDefaultValue; } /** * Get the name of the parameter. * * @return non-empty-string */ public function getName() : string { return $this->name; } /** * Get the function (or method) that declared this parameter. * @return \PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction */ public function getDeclaringFunction() { return $this->function; } /** * Get the class from the method that this parameter belongs to, if it * exists. * * This will return null if the declaring function is not a method. */ public function getDeclaringClass() : ?\PHPStan\BetterReflection\Reflection\ReflectionClass { if ($this->function instanceof \PHPStan\BetterReflection\Reflection\ReflectionMethod) { return $this->function->getDeclaringClass(); } return null; } public function getImplementingClass() : ?\PHPStan\BetterReflection\Reflection\ReflectionClass { if ($this->function instanceof \PHPStan\BetterReflection\Reflection\ReflectionMethod) { return $this->function->getImplementingClass(); } return null; } /** * Is the parameter optional? * * Note this is distinct from "isDefaultValueAvailable" because you can have * a default value, but the parameter not be optional. In the example, the * $foo parameter isOptional() == false, but isDefaultValueAvailable == true * * @example someMethod($foo = 'foo', $bar) */ public function isOptional() : bool { return $this->isOptional; } /** * Does the parameter have a default, regardless of whether it is optional. * * Note this is distinct from "isOptional" because you can have * a default value, but the parameter not be optional. In the example, the * $foo parameter isOptional() == false, but isDefaultValueAvailable == true * * @example someMethod($foo = 'foo', $bar) * @psalm-assert-if-true Node\Expr $this->default */ public function isDefaultValueAvailable() : bool { return $this->default !== null; } /** * @deprecated Use getDefaultValueExpression() */ public function getDefaultValueExpr() : ?\PhpParser\Node\Expr { return $this->getDefaultValueExpression(); } public function getDefaultValueExpression() : ?\PhpParser\Node\Expr { return $this->default; } /** * Get the default value of the parameter. * * @deprecated Use getDefaultValueExpression() * * @throws LogicException * @throws UnableToCompileNode * @return mixed */ public function getDefaultValue() { /** @psalm-var scalar|array|null $value */ $value = $this->getCompiledDefaultValue()->value; return $value; } /** * Does this method allow null for a parameter? */ public function allowsNull() : bool { $type = $this->getType(); if ($type === null) { return \true; } return $type->allowsNull(); } /** * Find the position of the parameter, left to right, starting at zero. */ public function getPosition() : int { return $this->parameterIndex; } /** * Get the ReflectionType instance representing the type declaration for * this parameter * * (note: this has nothing to do with DocBlocks). * @return \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ public function getType() { return $this->type; } /** * @return \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ private function createType(ParamNode $node) { $type = $node->type; if ($type === null) { return null; } assert($type instanceof Node\Identifier || $type instanceof Node\Name || $type instanceof Node\NullableType || $type instanceof Node\UnionType || $type instanceof Node\IntersectionType); $allowsNull = $this->default instanceof Node\Expr\ConstFetch && $this->default->name->toLowerString() === 'null' && !$this->isPromoted; return \PHPStan\BetterReflection\Reflection\ReflectionType::createFromNode($this->reflector, $this, $type, $allowsNull); } /** * Does this parameter have a type declaration? * * (note: this has nothing to do with DocBlocks). */ public function hasType() : bool { return $this->type !== null; } /** * Is this parameter a variadic (denoted by ...$param). */ public function isVariadic() : bool { return $this->isVariadic; } /** * Is this parameter passed by reference (denoted by &$param). */ public function isPassedByReference() : bool { return $this->byRef; } public function canBePassedByValue() : bool { return !$this->isPassedByReference(); } public function isPromoted() : bool { return $this->isPromoted; } /** @throws LogicException */ public function isDefaultValueConstant() : bool { return $this->getCompiledDefaultValue()->constantName !== null; } /** @throws LogicException */ public function getDefaultValueConstantName() : string { $compiledDefaultValue = $this->getCompiledDefaultValue(); if ($compiledDefaultValue->constantName === null) { throw new LogicException('This parameter is not a constant default value, so cannot have a constant name'); } return $compiledDefaultValue->constantName; } /** * @return positive-int * * @throws CodeLocationMissing */ public function getStartLine() : int { if ($this->startLine === null) { throw CodeLocationMissing::create(); } return $this->startLine; } /** * @return positive-int * * @throws CodeLocationMissing */ public function getEndLine() : int { if ($this->endLine === null) { throw CodeLocationMissing::create(); } return $this->endLine; } /** * @return positive-int * * @throws CodeLocationMissing */ public function getStartColumn() : int { if ($this->startColumn === null) { throw CodeLocationMissing::create(); } return $this->startColumn; } /** * @return positive-int * * @throws CodeLocationMissing */ public function getEndColumn() : int { if ($this->endColumn === null) { throw CodeLocationMissing::create(); } return $this->endColumn; } /** @return list */ public function getAttributes() : array { return $this->attributes; } /** @return list */ public function getAttributesByName(string $name) : array { return ReflectionAttributeHelper::filterAttributesByName($this->getAttributes(), $name); } /** * @param class-string $className * * @return list */ public function getAttributesByInstance(string $className) : array { return ReflectionAttributeHelper::filterAttributesByInstance($this->getAttributes(), $className); } } * @psalm-allow-private-mutation */ private $parameters; /** @psalm-allow-private-mutation * @var bool */ private $returnsReference; /** @psalm-allow-private-mutation * @var \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ private $returnType; /** * @var list * @psalm-allow-private-mutation */ private $attributes; /** * @var non-empty-string|null * @psalm-allow-private-mutation */ private $docComment; /** * @var positive-int|null * @psalm-allow-private-mutation */ private $startLine; /** * @var positive-int|null * @psalm-allow-private-mutation */ private $endLine; /** * @var positive-int|null * @psalm-allow-private-mutation */ private $startColumn; /** * @var positive-int|null * @psalm-allow-private-mutation */ private $endColumn; /** @psalm-allow-private-mutation * @var bool */ private $couldThrow = \false; /** @psalm-allow-private-mutation * @var bool */ private $isClosure = \false; /** @psalm-allow-private-mutation * @var bool */ private $isGenerator = \false; /** @return non-empty-string */ public abstract function __toString() : string; /** @return non-empty-string */ public abstract function getShortName() : string; /** @psalm-external-mutation-free * @param MethodNode|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $node */ private function fillFromNode($node) : void { $this->parameters = $this->createParameters($node); $this->returnsReference = $node->returnsByRef(); $this->returnType = $this->createReturnType($node); $this->attributes = ReflectionAttributeHelper::createAttributes($this->reflector, $this, $node->attrGroups); $this->docComment = GetLastDocComment::forNode($node); $this->couldThrow = $this->computeCouldThrow($node); $startLine = null; if ($node->hasAttribute('startLine')) { $startLine = $node->getStartLine(); assert($startLine > 0); } $endLine = null; if ($node->hasAttribute('endLine')) { $endLine = $node->getEndLine(); assert($endLine > 0); } $this->startLine = $startLine; $this->endLine = $endLine; try { $this->startColumn = CalculateReflectionColumn::getStartColumn($this->getLocatedSource()->getSource(), $node); } catch (NoNodePosition $exception) { $this->startColumn = null; } try { $this->endColumn = CalculateReflectionColumn::getEndColumn($this->getLocatedSource()->getSource(), $node); } catch (NoNodePosition $exception) { $this->endColumn = null; } } /** @return array * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $node */ private function createParameters($node) : array { $parameters = []; /** @var list $nodeParams */ $nodeParams = $node->params; foreach ($nodeParams as $paramIndex => $paramNode) { $parameter = \PHPStan\BetterReflection\Reflection\ReflectionParameter::createFromNode($this->reflector, $paramNode, $this, $paramIndex, $this->isParameterOptional($nodeParams, $paramIndex)); $parameters[$parameter->getName()] = $parameter; } return $parameters; } /** * Get the "full" name of the function (e.g. for A\B\foo, this will return * "A\B\foo"). * * @return non-empty-string */ public function getName() : string { $namespace = $this->getNamespaceName(); if ($namespace === null) { return $this->getShortName(); } return $namespace . '\\' . $this->getShortName(); } /** * Get the "namespace" name of the function (e.g. for A\B\foo, this will * return "A\B"). * * @return non-empty-string|null */ public function getNamespaceName() : ?string { return $this->namespace; } /** * Decide if this function is part of a namespace. Returns false if the class * is in the global namespace or does not have a specified namespace. */ public function inNamespace() : bool { return $this->namespace !== null; } /** * Get the number of parameters for this class. * * @return positive-int|0 */ public function getNumberOfParameters() : int { return count($this->parameters); } /** * Get the number of required parameters for this method. * * @return positive-int|0 */ public function getNumberOfRequiredParameters() : int { return count(array_filter($this->parameters, static function (\PHPStan\BetterReflection\Reflection\ReflectionParameter $p) : bool { return !$p->isOptional(); })); } /** * Get an array list of the parameters for this method signature, as an * array of ReflectionParameter instances. * * @return list */ public function getParameters() : array { return array_values($this->parameters); } /** @param list $parameterNodes */ private function isParameterOptional(array $parameterNodes, int $parameterIndex) : bool { foreach ($parameterNodes as $otherParameterIndex => $otherParameterNode) { if ($otherParameterIndex < $parameterIndex) { continue; } // When we find next parameter that does not have a default or is not variadic, // it means current parameter cannot be optional EVEN if it has a default value if ($otherParameterNode->default === null && !$otherParameterNode->variadic) { return \false; } } return \true; } /** * Get a single parameter by name. Returns null if parameter not found for * the function. * * @param non-empty-string $parameterName */ public function getParameter(string $parameterName) : ?\PHPStan\BetterReflection\Reflection\ReflectionParameter { return $this->parameters[$parameterName] ?? null; } /** @return non-empty-string|null */ public function getDocComment() : ?string { return $this->docComment; } /** @return non-empty-string|null */ public function getFileName() : ?string { return $this->locatedSource->getFileName(); } public function getLocatedSource() : LocatedSource { return $this->locatedSource; } /** * Is this function a closure? */ public function isClosure() : bool { return $this->isClosure; } public function isDeprecated() : bool { return AnnotationHelper::isDeprecated($this->docComment); } public function isInternal() : bool { return $this->locatedSource->isInternal(); } /** * Is this a user-defined function (will always return the opposite of * whatever isInternal returns). */ public function isUserDefined() : bool { return !$this->isInternal(); } /** @return non-empty-string|null */ public function getExtensionName() : ?string { return $this->locatedSource->getExtensionName(); } /** * Check if the function has a variadic parameter. */ public function isVariadic() : bool { foreach ($this->parameters as $parameter) { if ($parameter->isVariadic()) { return \true; } } return \false; } /** Checks if the function/method contains `throw` expressions. */ public function couldThrow() : bool { return $this->couldThrow; } /** * @param MethodNode|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $node */ private function computeCouldThrow($node) : bool { $statements = $node->getStmts(); if ($statements === null) { return \false; } $visitor = new FindingVisitor(static function (Node $node) : bool { return $node instanceof NodeThrow; }); $traverser = new NodeTraverser(); $traverser->addVisitor($visitor); $traverser->traverse($statements); return $visitor->getFoundNodes() !== []; } /** * Recursively search an array of statements (PhpParser nodes) to find if a * yield expression exists anywhere (thus indicating this is a generator). */ private function nodeIsOrContainsYield(Node $node) : bool { if ($node instanceof YieldNode) { return \true; } if ($node instanceof YieldFromNode) { return \true; } /** @psalm-var string $nodeName */ foreach ($node->getSubNodeNames() as $nodeName) { $nodeProperty = $node->{$nodeName}; if ($nodeProperty instanceof Node && $this->nodeIsOrContainsYield($nodeProperty)) { return \true; } if (!is_array($nodeProperty)) { continue; } /** @psalm-var mixed $nodePropertyArrayItem */ foreach ($nodeProperty as $nodePropertyArrayItem) { if ($nodePropertyArrayItem instanceof Node && $this->nodeIsOrContainsYield($nodePropertyArrayItem)) { return \true; } } } return \false; } /** * Check if this function can be used as a generator (i.e. contains the * "yield" keyword). */ public function isGenerator() : bool { return $this->isGenerator; } /** * Get the line number that this function starts on. * * @return positive-int * * @throws CodeLocationMissing */ public function getStartLine() : int { if ($this->startLine === null) { throw CodeLocationMissing::create(); } return $this->startLine; } /** * Get the line number that this function ends on. * * @return positive-int * * @throws CodeLocationMissing */ public function getEndLine() : int { if ($this->endLine === null) { throw CodeLocationMissing::create(); } return $this->endLine; } /** * @return positive-int * * @throws CodeLocationMissing */ public function getStartColumn() : int { if ($this->startColumn === null) { throw CodeLocationMissing::create(); } return $this->startColumn; } /** * @return positive-int * * @throws CodeLocationMissing */ public function getEndColumn() : int { if ($this->endColumn === null) { throw CodeLocationMissing::create(); } return $this->endColumn; } /** * Is this function declared as a reference. */ public function returnsReference() : bool { return $this->returnsReference; } /** * Get the return type declaration * @return \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ public function getReturnType() { if ($this->hasTentativeReturnType()) { return null; } return $this->returnType; } /** * Do we have a return type declaration */ public function hasReturnType() : bool { if ($this->hasTentativeReturnType()) { return \false; } return $this->returnType !== null; } public function hasTentativeReturnType() : bool { if ($this->isUserDefined()) { return \false; } return AnnotationHelper::hasTentativeReturnType($this->docComment); } /** * @return \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ public function getTentativeReturnType() { if (!$this->hasTentativeReturnType()) { return null; } return $this->returnType; } /** * @param MethodNode|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $node * @return \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ private function createReturnType($node) { $returnType = $node->getReturnType(); if ($returnType === null) { return null; } assert($returnType instanceof Node\Identifier || $returnType instanceof Node\Name || $returnType instanceof Node\NullableType || $returnType instanceof Node\UnionType || $returnType instanceof Node\IntersectionType); return \PHPStan\BetterReflection\Reflection\ReflectionType::createFromNode($this->reflector, $this, $returnType); } /** @return list */ public function getAttributes() : array { return $this->attributes; } /** @return list */ public function getAttributesByName(string $name) : array { return ReflectionAttributeHelper::filterAttributesByName($this->getAttributes(), $name); } /** * @param class-string $className * * @return list */ public function getAttributesByInstance(string $className) : array { return ReflectionAttributeHelper::filterAttributesByInstance($this->getAttributes(), $className); } } type; $allowsNull = \true; } if ($type instanceof Identifier || $type instanceof Name) { if ($type->toLowerString() === 'null' || $type->toLowerString() === 'mixed' || !$allowsNull) { return new \PHPStan\BetterReflection\Reflection\ReflectionNamedType($reflector, $owner, $type); } return new \PHPStan\BetterReflection\Reflection\ReflectionUnionType($reflector, $owner, new UnionType([$type, new Identifier('null')])); } if ($type instanceof IntersectionType) { return new \PHPStan\BetterReflection\Reflection\ReflectionIntersectionType($reflector, $owner, $type); } if (!$allowsNull) { return new \PHPStan\BetterReflection\Reflection\ReflectionUnionType($reflector, $owner, $type); } foreach ($type->types as $innerUnionType) { if (($innerUnionType instanceof Identifier || $innerUnionType instanceof Name) && $innerUnionType->toLowerString() === 'null') { return new \PHPStan\BetterReflection\Reflection\ReflectionUnionType($reflector, $owner, $type); } } $types = $type->types; $types[] = new Identifier('null'); return new \PHPStan\BetterReflection\Reflection\ReflectionUnionType($reflector, $owner, new UnionType($types)); } /** * Does the type allow null? */ public abstract function allowsNull() : bool; /** * Convert this string type to a string * * @return non-empty-string */ public abstract function __toString() : string; } */ private $types; /** @internal * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $owner */ public function __construct(Reflector $reflector, $owner, UnionType $type) { /** @var non-empty-list $types */ $types = array_map(static function ($type) use($reflector, $owner) { $type = \PHPStan\BetterReflection\Reflection\ReflectionType::createFromNode($reflector, $owner, $type); assert($type instanceof \PHPStan\BetterReflection\Reflection\ReflectionNamedType || $type instanceof \PHPStan\BetterReflection\Reflection\ReflectionIntersectionType); return $type; }, $type->types); $this->types = $types; } /** @internal * @param \PHPStan\BetterReflection\Reflection\ReflectionParameter|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionEnum|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant $owner * @return $this */ public function withOwner($owner) { $clone = clone $this; foreach ($clone->types as $typeNo => $innerType) { $clone->types[$typeNo] = $innerType->withOwner($owner); } return $clone; } /** @return non-empty-list */ public function getTypes() : array { return $this->types; } public function allowsNull() : bool { foreach ($this->types as $type) { if ($type->allowsNull()) { return \true; } } return \false; } /** @return non-empty-string */ public function __toString() : string { return implode('|', array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionType $type) : string { if ($type instanceof \PHPStan\BetterReflection\Reflection\ReflectionIntersectionType) { return sprintf('(%s)', $type->__toString()); } return $type->__toString(); }, $this->types)); } } */ private $modifiers; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @var \PHPStan\BetterReflection\SourceLocator\Located\LocatedSource */ private $locatedSource; /** * @var non-empty-string|null */ private $namespace; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionClass */ private $declaringClass; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionClass */ private $implementingClass; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionClass */ private $currentClass; /** * @var non-empty-string|null */ private $aliasName; /** * @param non-empty-string|null $aliasName * @param non-empty-string|null $namespace * @param MethodNode|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $node */ private function __construct(Reflector $reflector, $node, LocatedSource $locatedSource, ?string $namespace, \PHPStan\BetterReflection\Reflection\ReflectionClass $declaringClass, \PHPStan\BetterReflection\Reflection\ReflectionClass $implementingClass, \PHPStan\BetterReflection\Reflection\ReflectionClass $currentClass, ?string $aliasName) { $this->reflector = $reflector; $this->locatedSource = $locatedSource; $this->namespace = $namespace; $this->declaringClass = $declaringClass; $this->implementingClass = $implementingClass; $this->currentClass = $currentClass; $this->aliasName = $aliasName; assert($node instanceof MethodNode); $name = $node->name->name; assert($name !== ''); $this->name = $name; $this->modifiers = $this->computeModifiers($node); $this->fillFromNode($node); } /** * @internal * * @param non-empty-string|null $aliasName * @param non-empty-string|null $namespace */ public static function createFromNode(Reflector $reflector, MethodNode $node, LocatedSource $locatedSource, ?string $namespace, \PHPStan\BetterReflection\Reflection\ReflectionClass $declaringClass, \PHPStan\BetterReflection\Reflection\ReflectionClass $implementingClass, \PHPStan\BetterReflection\Reflection\ReflectionClass $currentClass, ?string $aliasName = null) : self { return new self($reflector, $node, $locatedSource, $namespace, $declaringClass, $implementingClass, $currentClass, $aliasName); } /** * Create a reflection of a method by it's name using a named class * * @param non-empty-string $methodName * * @throws IdentifierNotFound * @throws OutOfBoundsException */ public static function createFromName(string $className, string $methodName) : self { $method = \PHPStan\BetterReflection\Reflection\ReflectionClass::createFromName($className)->getMethod($methodName); if ($method === null) { throw new OutOfBoundsException(sprintf('Could not find method: %s', $methodName)); } return $method; } /** * Create a reflection of a method by it's name using an instance * * @param non-empty-string $methodName * * @throws ReflectionException * @throws IdentifierNotFound * @throws OutOfBoundsException */ public static function createFromInstance(object $instance, string $methodName) : self { $method = \PHPStan\BetterReflection\Reflection\ReflectionClass::createFromInstance($instance)->getMethod($methodName); if ($method === null) { throw new OutOfBoundsException(sprintf('Could not find method: %s', $methodName)); } return $method; } /** * @internal * * @param non-empty-string|null $aliasName * @param int-mask-of $modifiers */ public function withImplementingClass(\PHPStan\BetterReflection\Reflection\ReflectionClass $implementingClass, ?string $aliasName, int $modifiers) : self { $clone = clone $this; $clone->aliasName = $aliasName; $clone->modifiers = $modifiers; $clone->implementingClass = $implementingClass; $clone->currentClass = $implementingClass; if ($clone->returnType !== null) { $clone->returnType = $clone->returnType->withOwner($clone); } $clone->parameters = array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionParameter $parameter) use($clone) : \PHPStan\BetterReflection\Reflection\ReflectionParameter { return $parameter->withFunction($clone); }, $this->parameters); $clone->attributes = array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionAttribute $attribute) use($clone) : \PHPStan\BetterReflection\Reflection\ReflectionAttribute { return $attribute->withOwner($clone); }, $this->attributes); return $clone; } /** @internal */ public function withCurrentClass(\PHPStan\BetterReflection\Reflection\ReflectionClass $currentClass) : self { $clone = clone $this; $clone->currentClass = $currentClass; if ($clone->returnType !== null) { $clone->returnType = $clone->returnType->withOwner($clone); } // We don't need to clone parameters and attributes return $clone; } /** @return non-empty-string */ public function getShortName() : string { if ($this->aliasName !== null) { return $this->aliasName; } return $this->name; } /** @return non-empty-string|null */ public function getAliasName() : ?string { return $this->aliasName; } /** * Find the prototype for this method, if it exists. If it does not exist * it will throw a MethodPrototypeNotFound exception. * * @throws Exception\MethodPrototypeNotFound */ public function getPrototype() : self { $currentClass = $this->getImplementingClass(); foreach ($currentClass->getImmediateInterfaces() as $interface) { $interfaceMethod = $interface->getMethod($this->getName()); if ($interfaceMethod !== null) { return $interfaceMethod; } } $currentClass = $currentClass->getParentClass(); if ($currentClass !== null) { $prototype = ($getMethod = $currentClass->getMethod($this->getName())) ? $getMethod->findPrototype() : null; if ($prototype !== null && (!$this->isConstructor() || $prototype->isAbstract())) { return $prototype; } } throw new \PHPStan\BetterReflection\Reflection\Exception\MethodPrototypeNotFound(sprintf('Method %s::%s does not have a prototype', $this->getDeclaringClass()->getName(), $this->getName())); } private function findPrototype() : ?self { if ($this->isAbstract()) { return $this; } if ($this->isPrivate()) { return null; } try { return $this->getPrototype(); } catch (\PHPStan\BetterReflection\Reflection\Exception\MethodPrototypeNotFound $exception) { return $this; } } /** * Get the core-reflection-compatible modifier values. * * @return int-mask-of */ public function getModifiers() : int { return $this->modifiers; } /** @return int-mask-of */ private function computeModifiers(MethodNode $node) : int { $modifiers = $node->isStatic() ? CoreReflectionMethod::IS_STATIC : 0; $modifiers += $node->isPublic() ? CoreReflectionMethod::IS_PUBLIC : 0; $modifiers += $node->isProtected() ? CoreReflectionMethod::IS_PROTECTED : 0; $modifiers += $node->isPrivate() ? CoreReflectionMethod::IS_PRIVATE : 0; $modifiers += $node->isAbstract() ? CoreReflectionMethod::IS_ABSTRACT : 0; $modifiers += $node->isFinal() ? CoreReflectionMethod::IS_FINAL : 0; return $modifiers; } /** @return non-empty-string */ public function __toString() : string { return ReflectionMethodStringCast::toString($this); } public function inNamespace() : bool { return \false; } public function getNamespaceName() : ?string { return null; } public function isClosure() : bool { return \false; } /** * Is the method abstract. */ public function isAbstract() : bool { return ($this->modifiers & CoreReflectionMethod::IS_ABSTRACT) === CoreReflectionMethod::IS_ABSTRACT || $this->declaringClass->isInterface(); } /** * Is the method final. */ public function isFinal() : bool { return ($this->modifiers & CoreReflectionMethod::IS_FINAL) === CoreReflectionMethod::IS_FINAL; } /** * Is the method private visibility. */ public function isPrivate() : bool { return ($this->modifiers & CoreReflectionMethod::IS_PRIVATE) === CoreReflectionMethod::IS_PRIVATE; } /** * Is the method protected visibility. */ public function isProtected() : bool { return ($this->modifiers & CoreReflectionMethod::IS_PROTECTED) === CoreReflectionMethod::IS_PROTECTED; } /** * Is the method public visibility. */ public function isPublic() : bool { return ($this->modifiers & CoreReflectionMethod::IS_PUBLIC) === CoreReflectionMethod::IS_PUBLIC; } /** * Is the method static. */ public function isStatic() : bool { return ($this->modifiers & CoreReflectionMethod::IS_STATIC) === CoreReflectionMethod::IS_STATIC; } /** * Is the method a constructor. */ public function isConstructor() : bool { if (strtolower($this->getName()) === '__construct') { return \true; } $declaringClass = $this->getDeclaringClass(); if ($declaringClass->inNamespace()) { return \false; } return strtolower($this->getName()) === strtolower($declaringClass->getShortName()); } /** * Is the method a destructor. */ public function isDestructor() : bool { return strtolower($this->getName()) === '__destruct'; } /** * Get the class that declares this method. */ public function getDeclaringClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->declaringClass; } /** * Get the class that implemented the method based on trait use. */ public function getImplementingClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->implementingClass; } /** * Get the current reflected class. * * @internal */ public function getCurrentClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->currentClass; } /** * @throws ClassDoesNotExist * @throws NoObjectProvided * @throws ObjectNotInstanceOfClass */ public function getClosure($object = null) : Closure { $declaringClassName = $this->getDeclaringClass()->getName(); if ($this->isStatic()) { $this->assertClassExist($declaringClassName); return function (...$args) { return $this->callStaticMethod($args); }; } $instance = $this->assertObject($object); return function (...$args) use($instance) { return $this->callObjectMethod($instance, $args); }; } /** * @throws ClassDoesNotExist * @throws NoObjectProvided * @throws ObjectNotInstanceOfClass * @param mixed ...$args * @return mixed */ public function invoke($object = null, ...$args) { return $this->invokeArgs($object, $args); } /** * @param array $args * * @throws ClassDoesNotExist * @throws NoObjectProvided * @throws ObjectNotInstanceOfClass * @return mixed */ public function invokeArgs($object = null, array $args = []) { $implementingClassName = $this->getImplementingClass()->getName(); if ($this->isStatic()) { $this->assertClassExist($implementingClassName); return $this->callStaticMethod($args); } return $this->callObjectMethod($this->assertObject($object), $args); } /** @param array $args * @return mixed */ private function callStaticMethod(array $args) { $implementingClassName = $this->getImplementingClass()->getName(); /** @psalm-suppress InvalidStringClass */ $closure = Closure::bind(function (string $implementingClassName, string $_methodName, array $methodArgs) { return $implementingClassName::$_methodName(...$methodArgs); }, null, $implementingClassName); assert($closure instanceof Closure); return $closure->__invoke($implementingClassName, $this->getName(), $args); } /** @param array $args * @return mixed */ private function callObjectMethod(object $object, array $args) { /** @psalm-suppress MixedMethodCall */ $closure = Closure::bind(function (object $object, string $methodName, array $methodArgs) { return $object->{$methodName}(...$methodArgs); }, $object, $this->getImplementingClass()->getName()); assert($closure instanceof Closure); return $closure->__invoke($object, $this->getName(), $args); } /** @throws ClassDoesNotExist */ private function assertClassExist(string $className) : void { if (!ClassExistenceChecker::classExists($className, \true) && !ClassExistenceChecker::traitExists($className, \true)) { throw new ClassDoesNotExist(sprintf('Method of class %s cannot be used as the class does not exist', $className)); } } /** * @throws NoObjectProvided * @throws ObjectNotInstanceOfClass */ private function assertObject($object) : object { if ($object === null) { throw NoObjectProvided::create(); } $implementingClassName = $this->getImplementingClass()->getName(); if (\get_class($object) !== $implementingClassName) { throw ObjectNotInstanceOfClass::fromClassName($implementingClassName); } return $object; } } */ private $modifiers; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ private $type; /** * @var \PhpParser\Node\Expr */ private $value; /** @var non-empty-string|null */ private $docComment; /** @var list */ private $attributes; /** @var positive-int */ private $startLine; /** @var positive-int */ private $endLine; /** @var positive-int */ private $startColumn; /** @var positive-int */ private $endColumn; /** @psalm-allow-private-mutation * @var \PHPStan\BetterReflection\NodeCompiler\CompiledValue|null */ private $compiledValue = null; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionClass */ private $declaringClass; /** * @var \PHPStan\BetterReflection\Reflection\ReflectionClass */ private $implementingClass; private function __construct(Reflector $reflector, ClassConst $node, int $positionInNode, \PHPStan\BetterReflection\Reflection\ReflectionClass $declaringClass, \PHPStan\BetterReflection\Reflection\ReflectionClass $implementingClass) { $this->reflector = $reflector; $this->declaringClass = $declaringClass; $this->implementingClass = $implementingClass; $name = $node->consts[$positionInNode]->name->name; assert($name !== ''); $this->name = $name; $this->modifiers = $this->computeModifiers($node); $this->type = $this->createType($node); $this->value = $node->consts[$positionInNode]->value; $this->docComment = GetLastDocComment::forNode($node); $this->attributes = ReflectionAttributeHelper::createAttributes($reflector, $this, $node->attrGroups); $startLine = $node->getStartLine(); assert($startLine > 0); $endLine = $node->getEndLine(); assert($endLine > 0); $this->startLine = $startLine; $this->endLine = $endLine; $this->startColumn = CalculateReflectionColumn::getStartColumn($declaringClass->getLocatedSource()->getSource(), $node); $this->endColumn = CalculateReflectionColumn::getEndColumn($declaringClass->getLocatedSource()->getSource(), $node); } /** * Create a reflection of a class's constant by Const Node * * @internal */ public static function createFromNode(Reflector $reflector, ClassConst $node, int $positionInNode, \PHPStan\BetterReflection\Reflection\ReflectionClass $declaringClass, \PHPStan\BetterReflection\Reflection\ReflectionClass $implementingClass) : self { return new self($reflector, $node, $positionInNode, $declaringClass, $implementingClass); } /** @internal */ public function withImplementingClass(\PHPStan\BetterReflection\Reflection\ReflectionClass $implementingClass) : self { $clone = clone $this; $clone->implementingClass = $implementingClass; $clone->attributes = array_map(static function (\PHPStan\BetterReflection\Reflection\ReflectionAttribute $attribute) use($clone) : \PHPStan\BetterReflection\Reflection\ReflectionAttribute { return $attribute->withOwner($clone); }, $this->attributes); $this->compiledValue = null; return $clone; } /** * Get the name of the reflection (e.g. if this is a ReflectionClass this * will be the class name). * * @return non-empty-string */ public function getName() : string { return $this->name; } /** * @return \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ private function createType(ClassConst $node) { $type = $node->type; if ($type === null) { return null; } assert($type instanceof Node\Identifier || $type instanceof Node\Name || $type instanceof Node\NullableType || $type instanceof Node\UnionType || $type instanceof Node\IntersectionType); return \PHPStan\BetterReflection\Reflection\ReflectionType::createFromNode($this->reflector, $this, $type); } /** * @return \PHPStan\BetterReflection\Reflection\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\ReflectionIntersectionType|null */ public function getType() { return $this->type; } public function hasType() : bool { return $this->type !== null; } /** * @deprecated Use getValueExpression */ public function getValueExpr() : Node\Expr { return $this->getValueExpression(); } public function getValueExpression() : Node\Expr { return $this->value; } /** * Returns constant value * * @deprecated Use getValueExpression() * @return mixed */ public function getValue() { if ($this->compiledValue === null) { $this->compiledValue = (new CompileNodeToValue())->__invoke($this->value, new CompilerContext($this->reflector, $this)); } return $this->compiledValue->value; } /** * Constant is public */ public function isPublic() : bool { return ($this->modifiers & ReflectionClassConstantAdapter::IS_PUBLIC_COMPATIBILITY) === ReflectionClassConstantAdapter::IS_PUBLIC_COMPATIBILITY; } /** * Constant is private */ public function isPrivate() : bool { // Private constant cannot be final return $this->modifiers === ReflectionClassConstantAdapter::IS_PRIVATE_COMPATIBILITY; } /** * Constant is protected */ public function isProtected() : bool { return ($this->modifiers & ReflectionClassConstantAdapter::IS_PROTECTED_COMPATIBILITY) === ReflectionClassConstantAdapter::IS_PROTECTED_COMPATIBILITY; } public function isFinal() : bool { $final = ($this->modifiers & ReflectionClassConstantAdapter::IS_FINAL_COMPATIBILITY) === ReflectionClassConstantAdapter::IS_FINAL_COMPATIBILITY; if ($final) { return \true; } if (BetterReflection::$phpVersion >= 80100) { return \false; } return $this->getDeclaringClass()->isInterface(); } /** * Returns a bitfield of the access modifiers for this constant * * @return int-mask-of */ public function getModifiers() : int { return $this->modifiers; } /** * Get the line number that this constant starts on. * * @return positive-int */ public function getStartLine() : int { return $this->startLine; } /** * Get the line number that this constant ends on. * * @return positive-int */ public function getEndLine() : int { return $this->endLine; } /** @return positive-int */ public function getStartColumn() : int { return $this->startColumn; } /** @return positive-int */ public function getEndColumn() : int { return $this->endColumn; } /** * Get the declaring class */ public function getDeclaringClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->declaringClass; } /** * Get the class that implemented the method based on trait use. */ public function getImplementingClass() : \PHPStan\BetterReflection\Reflection\ReflectionClass { return $this->implementingClass; } /** @return non-empty-string|null */ public function getDocComment() : ?string { return $this->docComment; } public function isDeprecated() : bool { return AnnotationHelper::isDeprecated($this->getDocComment()); } /** @return non-empty-string */ public function __toString() : string { return ReflectionClassConstantStringCast::toString($this); } /** @return list */ public function getAttributes() : array { return $this->attributes; } /** @return list */ public function getAttributesByName(string $name) : array { return ReflectionAttributeHelper::filterAttributesByName($this->getAttributes(), $name); } /** * @param class-string $className * * @return list */ public function getAttributesByInstance(string $className) : array { return ReflectionAttributeHelper::filterAttributesByInstance($this->getAttributes(), $className); } /** @return int-mask-of */ private function computeModifiers(ClassConst $node) : int { $modifiers = $node->isFinal() ? ReflectionClassConstantAdapter::IS_FINAL_COMPATIBILITY : 0; $modifiers += $node->isPrivate() ? ReflectionClassConstantAdapter::IS_PRIVATE_COMPATIBILITY : 0; $modifiers += $node->isProtected() ? ReflectionClassConstantAdapter::IS_PROTECTED_COMPATIBILITY : 0; $modifiers += $node->isPublic() ? ReflectionClassConstantAdapter::IS_PUBLIC_COMPATIBILITY : 0; return $modifiers; } } reflector = $reflector; $this->locatedSource = $locatedSource; $this->namespace = $namespace; assert($node instanceof Node\Stmt\Function_ || $node instanceof Node\Expr\Closure || $node instanceof Node\Expr\ArrowFunction); $name = $node instanceof Node\Expr\Closure || $node instanceof Node\Expr\ArrowFunction ? self::CLOSURE_NAME : $node->name->name; assert($name !== ''); $this->name = $name; $this->fillFromNode($node); $isClosure = $node instanceof Node\Expr\Closure || $node instanceof Node\Expr\ArrowFunction; $this->isStatic = $isClosure && $node->static; $this->isClosure = $isClosure; $this->isGenerator = $this->nodeIsOrContainsYield($node); } /** * @deprecated Use Reflector instead. * * @throws IdentifierNotFound */ public static function createFromName(string $functionName) : self { return (new BetterReflection())->reflector()->reflectFunction($functionName); } /** @throws IdentifierNotFound */ public static function createFromClosure(Closure $closure) : self { $configuration = new BetterReflection(); return (new DefaultReflector(new AggregateSourceLocator([$configuration->sourceLocator(), new ClosureSourceLocator($closure, $configuration->phpParser())])))->reflectFunction(self::CLOSURE_NAME); } /** @return non-empty-string */ public function __toString() : string { return ReflectionFunctionStringCast::toString($this); } /** * @internal * * @param non-empty-string|null $namespace * @param \PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $node */ public static function createFromNode(Reflector $reflector, $node, LocatedSource $locatedSource, ?string $namespace = null) : self { return new self($reflector, $node, $locatedSource, $namespace); } /** * Get the "short" name of the function (e.g. for A\B\foo, this will return * "foo"). * * @return non-empty-string */ public function getShortName() : string { return $this->name; } /** * Check to see if this function has been disabled (by the PHP INI file * directive `disable_functions`). * * Note - we cannot reflect on internal functions (as there is no PHP source * code we can access. This means, at present, we can only EVER return false * from this function, because you cannot disable user-defined functions. * * @see https://php.net/manual/en/ini.core.php#ini.disable-functions * * @todo https://github.com/Roave/BetterReflection/issues/14 */ public function isDisabled() : bool { return \false; } public function isStatic() : bool { return $this->isStatic; } /** * @throws NotImplemented * @throws FunctionDoesNotExist */ public function getClosure() : Closure { $this->assertIsNoClosure(); $functionName = $this->getName(); $this->assertFunctionExist($functionName); return static function (...$args) use($functionName) { return $functionName(...$args); }; } /** * @throws NotImplemented * @throws FunctionDoesNotExist * @param mixed ...$args * @return mixed */ public function invoke(...$args) { return $this->invokeArgs($args); } /** * @param array $args * * @throws NotImplemented * @throws FunctionDoesNotExist * @return mixed */ public function invokeArgs(array $args = []) { $this->assertIsNoClosure(); $functionName = $this->getName(); $this->assertFunctionExist($functionName); return $functionName(...$args); } /** @throws NotImplemented */ private function assertIsNoClosure() : void { if ($this->isClosure()) { throw new NotImplemented('Not implemented for closures'); } } /** @throws FunctionDoesNotExist */ private function assertFunctionExist(string $functionName) : void { if (!function_exists($functionName)) { throw FunctionDoesNotExist::fromName($functionName); } } } betterReflectionProperty = $betterReflectionProperty; unset($this->name); unset($this->class); } public function __toString() : string { return $this->betterReflectionProperty->__toString(); } public function getName() : string { return $this->betterReflectionProperty->getName(); } /** * {@inheritDoc} * @return mixed */ #[\ReturnTypeWillChange] public function getValue($object = null) { try { return $this->betterReflectionProperty->getValue($object); } catch (NoObjectProvided $exception) { return null; } catch (Throwable $e) { throw new CoreReflectionException($e->getMessage(), 0, $e); } } /** @psalm-suppress MethodSignatureMismatch * @param mixed $objectOrValue * @param mixed $value */ public function setValue($objectOrValue, $value = null) : void { try { $this->betterReflectionProperty->setValue($objectOrValue, $value); } catch (NoObjectProvided $exception) { throw new ArgumentCountError('ReflectionProperty::setValue() expects exactly 2 arguments, 1 given'); } catch (NotAnObject $exception) { throw new TypeError(sprintf('ReflectionProperty::setValue(): Argument #1 ($objectOrValue) must be of type object, %s given', gettype($objectOrValue))); } catch (Throwable $e) { throw new CoreReflectionException($e->getMessage(), 0, $e); } } public function hasType() : bool { return $this->betterReflectionProperty->hasType(); } /** * @return ReflectionUnionType|ReflectionNamedType|ReflectionIntersectionType|null */ public function getType() : ?\ReflectionType { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionType::fromTypeOrNull($this->betterReflectionProperty->getType()); } public function isPublic() : bool { return $this->betterReflectionProperty->isPublic(); } public function isPrivate() : bool { return $this->betterReflectionProperty->isPrivate(); } public function isProtected() : bool { return $this->betterReflectionProperty->isProtected(); } public function isStatic() : bool { return $this->betterReflectionProperty->isStatic(); } public function isDefault() : bool { return $this->betterReflectionProperty->isDefault(); } public function getModifiers() : int { return $this->betterReflectionProperty->getModifiers(); } public function getDeclaringClass() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($this->betterReflectionProperty->getImplementingClass()); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getDocComment() { return $this->betterReflectionProperty->getDocComment() ?? \false; } /** * {@inheritDoc} * @codeCoverageIgnore * @infection-ignore-all */ public function setAccessible($accessible) : void { } public function hasDefaultValue() : bool { return $this->betterReflectionProperty->hasDefaultValue(); } /** * @deprecated Use getDefaultValueExpression() * @return mixed */ #[\ReturnTypeWillChange] public function getDefaultValue() { return $this->betterReflectionProperty->getDefaultValue(); } /** * @deprecated Use getDefaultValueExpression() */ public function getDefaultValueExpr() : Expr { return $this->betterReflectionProperty->getDefaultValueExpression(); } public function getDefaultValueExpression() : Expr { return $this->betterReflectionProperty->getDefaultValueExpression(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function isInitialized($object = null) { try { return $this->betterReflectionProperty->isInitialized($object); } catch (Throwable $e) { throw new CoreReflectionException($e->getMessage(), 0, $e); } } public function isPromoted() : bool { return $this->betterReflectionProperty->isPromoted(); } /** * @param class-string|null $name * * @return list */ public function getAttributes(?string $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterReflectionProperty->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterReflectionProperty->getAttributesByName($name); } else { $attributes = $this->betterReflectionProperty->getAttributes(); } return array_map(static function (BetterReflectionAttribute $betterReflectionAttribute) { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute); }, $attributes); } public function isReadOnly() : bool { return $this->betterReflectionProperty->isReadOnly(); } /** * @return mixed */ public function __get(string $name) { if ($name === 'name') { return $this->betterReflectionProperty->getName(); } if ($name === 'class') { return $this->betterReflectionProperty->getImplementingClass()->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } public function getBetterReflection() : BetterReflectionProperty { return $this->betterReflectionProperty; } } name); unset($this->class); } /** * Get the name of the reflection (e.g. if this is a ReflectionClass this * will be the class name). */ public function getName() : string { return $this->betterReflectionEnumCase->getName(); } public function hasType() : bool { return \false; } public function getType() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\Adapter\ReflectionIntersectionType|null { return null; } public function getValue() : UnitEnum { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } public function isPublic() : bool { return \true; } public function isPrivate() : bool { return \false; } public function isProtected() : bool { return \false; } public function getModifiers() : int { return self::IS_PUBLIC; } public function getDeclaringClass() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($this->betterReflectionEnumCase->getDeclaringClass()); } public function getDocComment() : string|false { return $this->betterReflectionEnumCase->getDocComment() ?? \false; } /** @return non-empty-string */ public function __toString() : string { return $this->betterReflectionEnumCase->__toString(); } /** * @param class-string|null $name * * @return list */ public function getAttributes(string|null $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterReflectionEnumCase->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterReflectionEnumCase->getAttributesByName($name); } else { $attributes = $this->betterReflectionEnumCase->getAttributes(); } /** @psalm-suppress ImpureFunctionCall */ return array_map(static fn(BetterReflectionAttribute $betterReflectionAttribute): \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute|\PHPStan\BetterReflection\Reflection\Adapter\FakeReflectionAttribute => \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute), $attributes); } public function isFinal() : bool { return \true; } public function isEnumCase() : bool { return \true; } public function getEnum() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum($this->betterReflectionEnumCase->getDeclaringEnum()); } /** * @deprecated Use getValueExpression() */ public function getBackingValue() : int|string { return $this->betterReflectionEnumCase->getValue(); } /** * @deprecated Use getValueExpression() */ public function getValueExpr() : Expr { return $this->getValueExpression(); } public function getValueExpression() : Expr { return $this->betterReflectionEnumCase->getValueExpression(); } public function __get(string $name) : mixed { if ($name === 'name') { return $this->betterReflectionEnumCase->getName(); } if ($name === 'class') { return $this->betterReflectionEnumCase->getDeclaringClass()->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } } betterReflectionType = $betterReflectionType; } /** @return non-empty-list */ public function getTypes() : array { return array_map(static function (BetterReflectionNamedType $type) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType { $adapterType = \PHPStan\BetterReflection\Reflection\Adapter\ReflectionType::fromType($type); assert($adapterType instanceof \PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType); return $adapterType; }, $this->betterReflectionType->getTypes()); } /** @return non-empty-string */ public function __toString() : string { return $this->betterReflectionType->__toString(); } /** @return false */ public function allowsNull() : bool { return $this->betterReflectionType->allowsNull(); } } * @psalm-suppress PropertyNotSetInConstructor */ final class ReflectionClass extends CoreReflectionClass { /** @internal */ public const IS_READONLY_COMPATIBILITY = 65536; /** * @var BetterReflectionClass|BetterReflectionEnum */ private $betterReflectionClass; /** * @param BetterReflectionClass|BetterReflectionEnum $betterReflectionClass */ public function __construct($betterReflectionClass) { $this->betterReflectionClass = $betterReflectionClass; unset($this->name); } /** @return non-empty-string */ public function __toString() : string { return $this->betterReflectionClass->__toString(); } /** * @return mixed */ public function __get(string $name) { if ($name === 'name') { return $this->betterReflectionClass->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } /** * @psalm-mutation-free * @return class-string */ public function getName() : string { return $this->betterReflectionClass->getName(); } /** @psalm-mutation-free */ public function isAnonymous() : bool { return $this->betterReflectionClass->isAnonymous(); } /** @psalm-mutation-free */ public function isInternal() : bool { return $this->betterReflectionClass->isInternal(); } /** @psalm-mutation-free */ public function isUserDefined() : bool { return $this->betterReflectionClass->isUserDefined(); } /** @psalm-mutation-free */ public function isInstantiable() : bool { return $this->betterReflectionClass->isInstantiable(); } /** @psalm-mutation-free */ public function isCloneable() : bool { return $this->betterReflectionClass->isCloneable(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getFileName() { $fileName = $this->betterReflectionClass->getFileName(); return $fileName !== null ? FileHelper::normalizeSystemPath($fileName) : \false; } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getStartLine() { return $this->betterReflectionClass->getStartLine(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getEndLine() { return $this->betterReflectionClass->getEndLine(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getDocComment() { return $this->betterReflectionClass->getDocComment() ?? \false; } /** * @psalm-mutation-free * @return ReflectionMethod|null */ public function getConstructor() : ?CoreReflectionMethod { $constructor = $this->betterReflectionClass->getConstructor(); if ($constructor === null) { return null; } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($constructor); } /** * {@inheritDoc} */ public function hasMethod($name) : bool { if ($name === '') { return \false; } return $this->betterReflectionClass->hasMethod($name); } /** * @param string $name * @return ReflectionMethod */ public function getMethod($name) : CoreReflectionMethod { $method = $name !== '' ? $this->betterReflectionClass->getMethod($name) : null; if ($method === null) { throw new CoreReflectionException(sprintf('Method %s::%s() does not exist', $this->betterReflectionClass->getName(), $name)); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($method); } /** * @param int-mask-of|null $filter * @return ReflectionMethod[] */ public function getMethods($filter = null) : array { /** @psalm-suppress ImpureFunctionCall */ return array_values(array_map(static function (BetterReflectionMethod $method) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($method); }, $this->betterReflectionClass->getMethods($filter ?? 0))); } /** * {@inheritDoc} */ public function hasProperty($name) : bool { if ($name === '') { return \false; } return $this->betterReflectionClass->hasProperty($name); } /** * @param string $name * @return ReflectionProperty */ public function getProperty($name) : \ReflectionProperty { $betterReflectionProperty = $name !== '' ? $this->betterReflectionClass->getProperty($name) : null; if ($betterReflectionProperty === null) { throw new CoreReflectionException(sprintf('Property %s::$%s does not exist', $this->betterReflectionClass->getName(), $name)); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($betterReflectionProperty); } /** * @param int-mask-of|null $filter * @return ReflectionProperty[] */ public function getProperties($filter = null) : array { /** @psalm-suppress ImpureFunctionCall */ return array_values(array_map(static function (BetterReflectionProperty $property) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($property); }, $this->betterReflectionClass->getProperties($filter ?? 0))); } /** * {@inheritDoc} */ public function hasConstant($name) : bool { if ($name === '') { return \false; } if ($this->betterReflectionClass instanceof BetterReflectionEnum && $this->betterReflectionClass->hasCase($name)) { return \true; } return $this->betterReflectionClass->hasConstant($name); } /** * @deprecated Use getReflectionConstants() * * @param int-mask-of|null $filter * * @return array * * @psalm-mutation-free */ public function getConstants(?int $filter = null) : array { /** @psalm-suppress ImpureFunctionCall */ return array_map(function ($betterConstantOrEnumCase) { return $this->getConstantValue($betterConstantOrEnumCase); }, $this->filterBetterReflectionClassConstants($filter)); } /** * @deprecated Use getReflectionConstant() * @return mixed */ #[\ReturnTypeWillChange] public function getConstant($name) { if ($name === '') { return \false; } if ($this->betterReflectionClass instanceof BetterReflectionEnum) { $enumCase = $this->betterReflectionClass->getCase($name); if ($enumCase !== null) { return $this->getConstantValue($enumCase); } } $betterReflectionConstant = $this->betterReflectionClass->getConstant($name); if ($betterReflectionConstant === null) { return \false; } return $betterReflectionConstant->getValue(); } /** @psalm-pure * @param BetterReflectionClassConstant|BetterReflectionEnumCase $betterConstantOrEnumCase * @return mixed */ private function getConstantValue($betterConstantOrEnumCase) { if ($betterConstantOrEnumCase instanceof BetterReflectionEnumCase) { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } return $betterConstantOrEnumCase->getValue(); } /** * @param string $name * @return ReflectionClassConstant|false */ #[\ReturnTypeWillChange] public function getReflectionConstant($name) { if ($name === '') { return \false; } if ($this->betterReflectionClass instanceof BetterReflectionEnum) { $enumCase = $this->betterReflectionClass->getCase($name); if ($enumCase !== null) { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant($enumCase); } } $betterReflectionConstant = $this->betterReflectionClass->getConstant($name); if ($betterReflectionConstant === null) { return \false; } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant($betterReflectionConstant); } /** * @param int-mask-of|null $filter * * @return list * * @psalm-mutation-free */ public function getReflectionConstants(?int $filter = null) : array { return array_values(array_map(static function ($betterConstantOrEnum) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant($betterConstantOrEnum); }, $this->filterBetterReflectionClassConstants($filter))); } /** * @param int-mask-of|null $filter * * @return array * * @psalm-mutation-free */ private function filterBetterReflectionClassConstants(?int $filter) : array { $reflectionConstants = $this->betterReflectionClass->getConstants($filter ?? 0); if ($this->betterReflectionClass instanceof BetterReflectionEnum && ($filter === null || $filter & \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant::IS_PUBLIC_COMPATIBILITY)) { $reflectionConstants += $this->betterReflectionClass->getCases(); } return $reflectionConstants; } /** @return list */ public function getInterfaceClassNames() : array { return $this->betterReflectionClass->getInterfaceClassNames(); } /** * @psalm-mutation-free * @return array */ public function getInterfaces() : array { /** @psalm-suppress ImpureFunctionCall */ return array_map(static function (BetterReflectionClass $interface) : self { return new self($interface); }, $this->betterReflectionClass->getInterfaces()); } /** * @return list * * @psalm-mutation-free */ public function getInterfaceNames() : array { return $this->betterReflectionClass->getInterfaceNames(); } /** @psalm-mutation-free */ public function isInterface() : bool { return $this->betterReflectionClass->isInterface(); } /** @return list */ public function getTraitClassNames() : array { return $this->betterReflectionClass->getTraitClassNames(); } /** * @psalm-mutation-free * @return array */ public function getTraits() : array { $traits = $this->betterReflectionClass->getTraits(); /** @var list $traitNames */ $traitNames = array_map(static function (BetterReflectionClass $trait) : string { return $trait->getName(); }, $traits); /** @psalm-suppress ImpureFunctionCall */ return array_combine($traitNames, array_map(static function (BetterReflectionClass $trait) : self { return new self($trait); }, $traits)); } /** * @return list * * @psalm-mutation-free */ public function getTraitNames() : array { return $this->betterReflectionClass->getTraitNames(); } /** * @return array * * @psalm-mutation-free */ public function getTraitAliases() : array { return $this->betterReflectionClass->getTraitAliases(); } /** @psalm-mutation-free */ public function isTrait() : bool { return $this->betterReflectionClass->isTrait(); } /** @psalm-mutation-free */ public function isAbstract() : bool { return $this->betterReflectionClass->isAbstract(); } /** @psalm-mutation-free */ public function isFinal() : bool { return $this->betterReflectionClass->isFinal(); } /** @psalm-mutation-free */ public function isReadOnly() : bool { return $this->betterReflectionClass->isReadOnly(); } /** @psalm-mutation-free */ public function getModifiers() : int { return $this->betterReflectionClass->getModifiers(); } /** * {@inheritDoc} */ public function isInstance($object) : bool { return $this->betterReflectionClass->isInstance($object); } /** * @return object * @param mixed $arg * @param mixed $args */ #[\ReturnTypeWillChange] public function newInstance($arg = null, ...$args) { ClassExistenceChecker::classExists($this->getName(), \true); $reflection = new CoreReflectionClass($this->getName()); return $reflection->newInstance(...func_get_args()); } public function newInstanceWithoutConstructor() : object { ClassExistenceChecker::classExists($this->getName(), \true); $reflection = new CoreReflectionClass($this->getName()); return $reflection->newInstanceWithoutConstructor(); } public function newInstanceArgs(?array $args = null) : object { ClassExistenceChecker::classExists($this->getName(), \true); $reflection = new CoreReflectionClass($this->getName()); return $reflection->newInstanceArgs($args); } /** @return class-string|null */ public function getParentClassName() : ?string { return $this->betterReflectionClass->getParentClassName(); } /** * @return self|false */ #[\ReturnTypeWillChange] public function getParentClass() { $parentClass = $this->betterReflectionClass->getParentClass(); if ($parentClass === null) { return \false; } return new self($parentClass); } /** * {@inheritDoc} */ public function isSubclassOf($class) : bool { $realParentClassNames = $this->betterReflectionClass->getParentClassNames(); $parentClassNames = array_combine(array_map(static function (string $parentClassName) : string { return strtolower($parentClassName); }, $realParentClassNames), $realParentClassNames); $className = $class instanceof CoreReflectionClass ? $class->getName() : $class; $lowercasedClassName = strtolower($className); $realParentClassName = $parentClassNames[$lowercasedClassName] ?? $className; if ($this->betterReflectionClass->isSubclassOf($realParentClassName)) { return \true; } return $this->implementsInterface($className); } /** * @return array * * @psalm-suppress LessSpecificImplementedReturnType */ public function getStaticProperties() : array { return $this->betterReflectionClass->getStaticProperties(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getStaticPropertyValue($name, $default = null) { $betterReflectionProperty = $name !== '' ? $this->betterReflectionClass->getProperty($name) : null; if ($betterReflectionProperty === null) { if (func_num_args() === 2) { return $default; } throw new CoreReflectionException(sprintf('Property %s::$%s does not exist', $this->betterReflectionClass->getName(), $name)); } $property = new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($betterReflectionProperty); if (!$property->isStatic()) { throw new CoreReflectionException(sprintf('Property %s::$%s does not exist', $this->betterReflectionClass->getName(), $name)); } return $property->getValue(); } /** * {@inheritDoc} */ public function setStaticPropertyValue($name, $value) : void { $betterReflectionProperty = $name !== '' ? $this->betterReflectionClass->getProperty($name) : null; if ($betterReflectionProperty === null) { throw new CoreReflectionException(sprintf('Class %s does not have a property named %s', $this->betterReflectionClass->getName(), $name)); } $property = new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($betterReflectionProperty); if (!$property->isStatic()) { throw new CoreReflectionException(sprintf('Class %s does not have a property named %s', $this->betterReflectionClass->getName(), $name)); } $property->setValue($value); } /** * @return array * * @psalm-mutation-free */ public function getDefaultProperties() : array { return $this->betterReflectionClass->getDefaultProperties(); } /** @psalm-mutation-free */ public function isIterateable() : bool { return $this->betterReflectionClass->isIterateable(); } /** @psalm-mutation-free */ public function isIterable() : bool { return $this->isIterateable(); } /** * @param \ReflectionClass|string $interface */ public function implementsInterface($interface) : bool { $realInterfaceNames = $this->betterReflectionClass->getInterfaceNames(); $interfaceNames = array_combine(array_map(static function (string $interfaceName) : string { return strtolower($interfaceName); }, $realInterfaceNames), $realInterfaceNames); $interfaceName = $interface instanceof CoreReflectionClass ? $interface->getName() : $interface; $lowercasedInterfaceName = strtolower($interfaceName); $realInterfaceName = $interfaceNames[$lowercasedInterfaceName] ?? $interfaceName; return $this->betterReflectionClass->implementsInterface($realInterfaceName); } /** @psalm-mutation-free */ public function getExtension() : ?CoreReflectionExtension { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getExtensionName() { return $this->betterReflectionClass->getExtensionName() ?? \false; } /** @psalm-mutation-free */ public function inNamespace() : bool { return $this->betterReflectionClass->inNamespace(); } /** @psalm-mutation-free */ public function getNamespaceName() : string { return $this->betterReflectionClass->getNamespaceName() ?? ''; } /** @psalm-mutation-free */ public function getShortName() : string { return $this->betterReflectionClass->getShortName(); } /** * @param class-string|null $name * * @return list */ public function getAttributes(?string $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterReflectionClass->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterReflectionClass->getAttributesByName($name); } else { $attributes = $this->betterReflectionClass->getAttributes(); } /** @psalm-suppress ImpureFunctionCall */ return array_map(static function (BetterReflectionAttribute $betterReflectionAttribute) { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute); }, $attributes); } /** @psalm-mutation-free */ public function isEnum() : bool { return $this->betterReflectionClass->isEnum(); } } betterReflectionObject = $betterReflectionObject; unset($this->name); } public function __toString() : string { return $this->betterReflectionObject->__toString(); } public function getName() : string { return $this->betterReflectionObject->getName(); } public function isInternal() : bool { return $this->betterReflectionObject->isInternal(); } public function isUserDefined() : bool { return $this->betterReflectionObject->isUserDefined(); } public function isInstantiable() : bool { return $this->betterReflectionObject->isInstantiable(); } public function isCloneable() : bool { return $this->betterReflectionObject->isCloneable(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getFileName() { $fileName = $this->betterReflectionObject->getFileName(); return $fileName !== null ? FileHelper::normalizeSystemPath($fileName) : \false; } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getStartLine() { return $this->betterReflectionObject->getStartLine(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getEndLine() { return $this->betterReflectionObject->getEndLine(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getDocComment() { return $this->betterReflectionObject->getDocComment() ?? \false; } public function getConstructor() : ?\PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod { $constructor = $this->betterReflectionObject->getConstructor(); if ($constructor === null) { return null; } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($constructor); } /** * {@inheritDoc} */ public function hasMethod($name) : bool { if ($name === '') { return \false; } return $this->betterReflectionObject->hasMethod($this->getMethodRealName($name)); } /** * {@inheritDoc} */ public function getMethod($name) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod { $method = $name !== '' ? $this->betterReflectionObject->getMethod($this->getMethodRealName($name)) : null; if ($method === null) { throw new CoreReflectionException(sprintf('Method %s::%s() does not exist', $this->betterReflectionObject->getName(), $name)); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($method); } /** * @param non-empty-string $name * * @return non-empty-string */ private function getMethodRealName(string $name) : string { $realMethodNames = array_map(static function (BetterReflectionMethod $method) : string { return $method->getName(); }, $this->betterReflectionObject->getMethods()); $methodNames = array_combine(array_map(static function (string $methodName) : string { return strtolower($methodName); }, $realMethodNames), $realMethodNames); $lowercasedName = strtolower($name); return $methodNames[$lowercasedName] ?? $name; } /** * @param int-mask-of|null $filter * @return ReflectionMethod[] */ public function getMethods($filter = null) : array { return array_values(array_map(static function (BetterReflectionMethod $method) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($method); }, $this->betterReflectionObject->getMethods($filter ?? 0))); } /** * {@inheritDoc} */ public function hasProperty($name) : bool { if ($name === '') { return \false; } return $this->betterReflectionObject->hasProperty($name); } /** * @param string $name * @return ReflectionProperty */ public function getProperty($name) : \ReflectionProperty { $property = $name !== '' ? $this->betterReflectionObject->getProperty($name) : null; if ($property === null) { throw new CoreReflectionException(sprintf('Property %s::$%s does not exist', $this->betterReflectionObject->getName(), $name)); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($property); } /** * @param int-mask-of|null $filter * @return ReflectionProperty[] */ public function getProperties($filter = null) : array { return array_values(array_map(static function (BetterReflectionProperty $property) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($property); }, $this->betterReflectionObject->getProperties($filter ?? 0))); } /** * {@inheritDoc} */ public function hasConstant($name) : bool { if ($name === '') { return \false; } return $this->betterReflectionObject->hasConstant($name); } /** * @param int-mask-of|null $filter * * @return array */ public function getConstants(?int $filter = null) : array { return array_map(static function (BetterReflectionClassConstant $betterConstant) { return $betterConstant->getValue(); }, $this->betterReflectionObject->getConstants($filter ?? 0)); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getConstant($name) { if ($name === '') { return \false; } $betterReflectionConstant = $this->betterReflectionObject->getConstant($name); if ($betterReflectionConstant === null) { return \false; } return $betterReflectionConstant->getValue(); } /** * @param string $name * @return ReflectionClassConstant|false */ #[\ReturnTypeWillChange] public function getReflectionConstant($name) { if ($name === '') { return \false; } $betterReflectionConstant = $this->betterReflectionObject->getConstant($name); if ($betterReflectionConstant === null) { return \false; } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant($betterReflectionConstant); } /** * @param int-mask-of|null $filter * * @return list */ public function getReflectionConstants(?int $filter = null) : array { return array_values(array_map(static function (BetterReflectionClassConstant $betterConstant) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant($betterConstant); }, $this->betterReflectionObject->getConstants($filter ?? 0))); } /** @return array */ public function getInterfaces() : array { return array_map(static function (BetterReflectionClass $interface) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($interface); }, $this->betterReflectionObject->getInterfaces()); } /** @return list */ public function getInterfaceNames() : array { return $this->betterReflectionObject->getInterfaceNames(); } public function isInterface() : bool { return $this->betterReflectionObject->isInterface(); } /** @return array */ public function getTraits() : array { $traits = $this->betterReflectionObject->getTraits(); /** @var list $traitNames */ $traitNames = array_map(static function (BetterReflectionClass $trait) : string { return $trait->getName(); }, $traits); return array_combine($traitNames, array_map(static function (BetterReflectionClass $trait) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($trait); }, $traits)); } /** @return list */ public function getTraitNames() : array { return $this->betterReflectionObject->getTraitNames(); } /** @return array */ public function getTraitAliases() : array { return $this->betterReflectionObject->getTraitAliases(); } public function isTrait() : bool { return $this->betterReflectionObject->isTrait(); } public function isAbstract() : bool { return $this->betterReflectionObject->isAbstract(); } public function isFinal() : bool { return $this->betterReflectionObject->isFinal(); } public function isReadOnly() : bool { return $this->betterReflectionObject->isReadOnly(); } public function getModifiers() : int { return $this->betterReflectionObject->getModifiers(); } /** * {@inheritDoc} */ public function isInstance($object) : bool { return $this->betterReflectionObject->isInstance($object); } /** * @param mixed $arg * @param mixed ...$args * * @return object */ #[\ReturnTypeWillChange] public function newInstance($arg = null, ...$args) { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function newInstanceWithoutConstructor() { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function newInstanceArgs(?array $args = null) { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } /** * @return ReflectionClass|false */ #[\ReturnTypeWillChange] public function getParentClass() { $parentClass = $this->betterReflectionObject->getParentClass(); if ($parentClass === null) { return \false; } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($parentClass); } /** * {@inheritDoc} */ public function isSubclassOf($class) : bool { $realParentClassNames = $this->betterReflectionObject->getParentClassNames(); $parentClassNames = array_combine(array_map(static function (string $parentClassName) : string { return strtolower($parentClassName); }, $realParentClassNames), $realParentClassNames); $className = $class instanceof CoreReflectionClass ? $class->getName() : $class; $lowercasedClassName = strtolower($className); $realParentClassName = $parentClassNames[$lowercasedClassName] ?? $className; return $this->betterReflectionObject->isSubclassOf($realParentClassName); } /** * @return array * * @psalm-suppress LessSpecificImplementedReturnType */ public function getStaticProperties() : array { return $this->betterReflectionObject->getStaticProperties(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getStaticPropertyValue($name, $default = null) { $betterReflectionProperty = $name !== '' ? $this->betterReflectionObject->getProperty($name) : null; if ($betterReflectionProperty === null) { if (func_num_args() === 2) { return $default; } throw new CoreReflectionException(sprintf('Property %s::$%s does not exist', $this->betterReflectionObject->getName(), $name)); } $property = new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($betterReflectionProperty); if (!$property->isStatic()) { throw new CoreReflectionException(sprintf('Property %s::$%s does not exist', $this->betterReflectionObject->getName(), $name)); } return $property->getValue(); } /** * {@inheritDoc} */ public function setStaticPropertyValue($name, $value) : void { $betterReflectionProperty = $name !== '' ? $this->betterReflectionObject->getProperty($name) : null; if ($betterReflectionProperty === null) { throw new CoreReflectionException(sprintf('Class %s does not have a property named %s', $this->betterReflectionObject->getName(), $name)); } $property = new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($betterReflectionProperty); if (!$property->isStatic()) { throw new CoreReflectionException(sprintf('Class %s does not have a property named %s', $this->betterReflectionObject->getName(), $name)); } $property->setValue($value); } /** @return array|null> */ public function getDefaultProperties() : array { return $this->betterReflectionObject->getDefaultProperties(); } public function isIterateable() : bool { return $this->betterReflectionObject->isIterateable(); } public function isIterable() : bool { return $this->isIterateable(); } /** * @param \ReflectionClass|string $interface */ public function implementsInterface($interface) : bool { $realInterfaceNames = $this->betterReflectionObject->getInterfaceNames(); $interfaceNames = array_combine(array_map(static function (string $interfaceName) : string { return strtolower($interfaceName); }, $realInterfaceNames), $realInterfaceNames); $interfaceName = $interface instanceof CoreReflectionClass ? $interface->getName() : $interface; $lowercasedInterfaceName = strtolower($interfaceName); $realInterfaceName = $interfaceNames[$lowercasedInterfaceName] ?? $interfaceName; return $this->betterReflectionObject->implementsInterface($realInterfaceName); } public function getExtension() : ?CoreReflectionExtension { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getExtensionName() { return $this->betterReflectionObject->getExtensionName() ?? \false; } public function inNamespace() : bool { return $this->betterReflectionObject->inNamespace(); } public function getNamespaceName() : string { return $this->betterReflectionObject->getNamespaceName() ?? ''; } public function getShortName() : string { return $this->betterReflectionObject->getShortName(); } public function isAnonymous() : bool { return $this->betterReflectionObject->isAnonymous(); } /** * @param class-string|null $name * * @return list */ public function getAttributes(?string $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterReflectionObject->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterReflectionObject->getAttributesByName($name); } else { $attributes = $this->betterReflectionObject->getAttributes(); } return array_map(static function (BetterReflectionAttribute $betterReflectionAttribute) { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute); }, $attributes); } public function isEnum() : bool { return $this->betterReflectionObject->isEnum(); } /** * @return mixed */ public function __get(string $name) { if ($name === 'name') { return $this->betterReflectionObject->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } } */ final class ReflectionAttribute extends CoreReflectionAttribute { /** * @var BetterReflectionAttribute */ private $betterReflectionAttribute; public function __construct(BetterReflectionAttribute $betterReflectionAttribute) { $this->betterReflectionAttribute = $betterReflectionAttribute; } /** @psalm-mutation-free */ public function getName() : string { return $this->betterReflectionAttribute->getName(); } /** * @return int-mask-of * * @psalm-mutation-free * @psalm-suppress ImplementedReturnTypeMismatch */ public function getTarget() : int { return $this->betterReflectionAttribute->getTarget(); } /** @psalm-mutation-free */ public function isRepeated() : bool { return $this->betterReflectionAttribute->isRepeated(); } /** * @deprecated Use getArgumentsExpressions() * @return array */ public function getArguments() : array { return $this->betterReflectionAttribute->getArguments(); } /** @return array */ public function getArgumentsExpressions() : array { return $this->betterReflectionAttribute->getArgumentsExpressions(); } public function newInstance() : object { $class = $this->getName(); return new $class(...$this->getArguments()); } /** @return non-empty-string */ public function __toString() : string { return $this->betterReflectionAttribute->__toString(); } } betterReflectionType = $betterReflectionType; $this->allowsNull = $allowsNull; } public function getName() : string { return $this->betterReflectionType->getName(); } /** @return non-empty-string */ public function __toString() : string { $type = strtolower($this->betterReflectionType->getName()); if (!$this->allowsNull || $type === 'mixed' || $type === 'null') { return $this->betterReflectionType->__toString(); } return '?' . $this->betterReflectionType->__toString(); } public function allowsNull() : bool { return $this->allowsNull; } public function isBuiltin() : bool { $type = strtolower($this->betterReflectionType->getName()); if ($type === 'self' || $type === 'parent' || $type === 'static') { return \false; } return $this->betterReflectionType->isBuiltin(); } public function isIdentifier() : bool { return $this->betterReflectionType->isIdentifier(); } } betterReflectionParameter = $betterReflectionParameter; unset($this->name); } /** @return non-empty-string */ public function __toString() : string { return $this->betterReflectionParameter->__toString(); } public function getName() : string { return $this->betterReflectionParameter->getName(); } public function isPassedByReference() : bool { return $this->betterReflectionParameter->isPassedByReference(); } public function canBePassedByValue() : bool { return $this->betterReflectionParameter->canBePassedByValue(); } /** * @return ReflectionFunction|ReflectionMethod */ public function getDeclaringFunction() : CoreReflectionFunctionAbstract { $function = $this->betterReflectionParameter->getDeclaringFunction(); if ($function instanceof BetterReflectionMethod) { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($function); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionFunction($function); } /** @return ReflectionClass|null */ public function getDeclaringClass() : ?CoreReflectionClass { $declaringClass = $this->betterReflectionParameter->getDeclaringClass(); if ($declaringClass === null) { return null; } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($declaringClass); } /** @return ReflectionClass|null */ public function getClass() : ?CoreReflectionClass { $type = $this->betterReflectionParameter->getType(); if ($type === null) { return null; } if ($type instanceof BetterReflectionIntersectionType) { return null; } if ($type instanceof BetterReflectionNamedType) { $classType = $type; } else { $unionTypes = $type->getTypes(); if (count($unionTypes) !== 2) { return null; } if (!$type->allowsNull()) { return null; } foreach ($unionTypes as $unionInnerType) { if (!$unionInnerType instanceof BetterReflectionNamedType) { return null; } if ($unionInnerType->allowsNull()) { continue; } $classType = $unionInnerType; break; } } try { /** @phpstan-ignore-next-line */ return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($classType->getClass()); } catch (LogicException $exception) { return null; } } public function isArray() : bool { return $this->isType($this->betterReflectionParameter->getType(), 'array'); } public function isCallable() : bool { return $this->isType($this->betterReflectionParameter->getType(), 'callable'); } /** * For isArray() and isCallable(). * @param BetterReflectionNamedType|BetterReflectionUnionType|BetterReflectionIntersectionType|null $typeReflection */ private function isType($typeReflection, string $type) : bool { if ($typeReflection === null) { return \false; } if ($typeReflection instanceof BetterReflectionIntersectionType) { return \false; } $isOneOfAllowedTypes = static function (BetterReflectionType $namedType, string ...$types) : bool { foreach ($types as $type) { if ($namedType instanceof BetterReflectionNamedType && strtolower($namedType->getName()) === $type) { return \true; } } return \false; }; if ($typeReflection instanceof BetterReflectionUnionType) { $unionTypes = $typeReflection->getTypes(); foreach ($unionTypes as $unionType) { if (!$isOneOfAllowedTypes($unionType, $type, 'null')) { return \false; } } return \true; } return $isOneOfAllowedTypes($typeReflection, $type); } public function allowsNull() : bool { return $this->betterReflectionParameter->allowsNull(); } public function getPosition() : int { return $this->betterReflectionParameter->getPosition(); } public function isOptional() : bool { return $this->betterReflectionParameter->isOptional(); } public function isVariadic() : bool { return $this->betterReflectionParameter->isVariadic(); } public function isDefaultValueAvailable() : bool { return $this->betterReflectionParameter->isDefaultValueAvailable(); } /** * @deprecated Use getDefaultValueExpression() */ #[\ReturnTypeWillChange] public function getDefaultValue() { return $this->betterReflectionParameter->getDefaultValue(); } /** * @deprecated Use getDefaultValueExpression() */ public function getDefaultValueExpr() : Expr { return $this->betterReflectionParameter->getDefaultValueExpression(); } public function getDefaultValueExpression() : Expr { return $this->betterReflectionParameter->getDefaultValueExpression(); } public function isDefaultValueConstant() : bool { return $this->betterReflectionParameter->isDefaultValueConstant(); } public function getDefaultValueConstantName() : string { return $this->betterReflectionParameter->getDefaultValueConstantName(); } public function hasType() : bool { return $this->betterReflectionParameter->hasType(); } /** * @return ReflectionUnionType|ReflectionNamedType|ReflectionIntersectionType|null */ public function getType() : ?\ReflectionType { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionType::fromTypeOrNull($this->betterReflectionParameter->getType()); } public function isPromoted() : bool { return $this->betterReflectionParameter->isPromoted(); } /** * @param class-string|null $name * * @return list */ public function getAttributes(?string $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterReflectionParameter->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterReflectionParameter->getAttributesByName($name); } else { $attributes = $this->betterReflectionParameter->getAttributes(); } /** @psalm-suppress ImpureFunctionCall */ return array_map(static function (BetterReflectionAttribute $betterReflectionAttribute) { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute); }, $attributes); } /** * @return mixed */ public function __get(string $name) { if ($name === 'name') { return $this->betterReflectionParameter->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } } getTypes(), static function (BetterReflectionType $type) : bool { return !($type instanceof BetterReflectionNamedType && $type->getName() === 'null'); })); if ($betterReflectionType->allowsNull() && count($nonNullTypes) === 1 && $nonNullTypes[0] instanceof BetterReflectionNamedType) { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType($nonNullTypes[0], \true); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionUnionType($betterReflectionType); } if ($betterReflectionType instanceof BetterReflectionIntersectionType) { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionIntersectionType($betterReflectionType); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType($betterReflectionType, $betterReflectionType->allowsNull()); } } betterReflectionType = $betterReflectionType; } /** @return non-empty-list */ public function getTypes() : array { return array_map(static function (BetterReflectionType $type) { $adapterType = \PHPStan\BetterReflection\Reflection\Adapter\ReflectionType::fromType($type); assert($adapterType instanceof \PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType || $adapterType instanceof \PHPStan\BetterReflection\Reflection\Adapter\ReflectionIntersectionType); return $adapterType; }, $this->betterReflectionType->getTypes()); } /** @return non-empty-string */ public function __toString() : string { return $this->betterReflectionType->__toString(); } public function allowsNull() : bool { return $this->betterReflectionType->allowsNull(); } } betterReflectionMethod = $betterReflectionMethod; unset($this->name); unset($this->class); } /** @return non-empty-string */ public function __toString() : string { return $this->betterReflectionMethod->__toString(); } public function inNamespace() : bool { return $this->betterReflectionMethod->inNamespace(); } public function isClosure() : bool { return $this->betterReflectionMethod->isClosure(); } public function isDeprecated() : bool { return $this->betterReflectionMethod->isDeprecated(); } public function isInternal() : bool { return $this->betterReflectionMethod->isInternal(); } public function isUserDefined() : bool { return $this->betterReflectionMethod->isUserDefined(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getClosureThis() { throw new NotImplemented('Not implemented'); } public function getClosureScopeClass() : ?CoreReflectionClass { throw new NotImplemented('Not implemented'); } public function getClosureCalledClass() : ?CoreReflectionClass { throw new NotImplemented('Not implemented'); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getDocComment() { return $this->betterReflectionMethod->getDocComment() ?? \false; } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getStartLine() { try { return $this->betterReflectionMethod->getStartLine(); } catch (CodeLocationMissing $exception) { return \false; } } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getEndLine() { try { return $this->betterReflectionMethod->getEndLine(); } catch (CodeLocationMissing $exception) { return \false; } } /** @psalm-suppress ImplementedReturnTypeMismatch */ public function getExtension() : ?CoreReflectionExtension { throw new NotImplemented('Not implemented'); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getExtensionName() { return $this->betterReflectionMethod->getExtensionName() ?? \false; } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getFileName() { $fileName = $this->betterReflectionMethod->getFileName(); return $fileName !== null ? FileHelper::normalizeSystemPath($fileName) : \false; } public function getName() : string { return $this->betterReflectionMethod->getName(); } public function getNamespaceName() : string { return $this->betterReflectionMethod->getNamespaceName() ?? ''; } public function getNumberOfParameters() : int { return $this->betterReflectionMethod->getNumberOfParameters(); } public function getNumberOfRequiredParameters() : int { return $this->betterReflectionMethod->getNumberOfRequiredParameters(); } /** @return list */ public function getParameters() : array { return array_map(static function (BetterReflectionParameter $parameter) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter($parameter); }, $this->betterReflectionMethod->getParameters()); } public function hasReturnType() : bool { return $this->betterReflectionMethod->hasReturnType(); } /** @return ReflectionUnionType|ReflectionNamedType|ReflectionIntersectionType|null */ public function getReturnType() : ?CoreReflectionType { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionType::fromTypeOrNull($this->betterReflectionMethod->getReturnType()); } public function getShortName() : string { return $this->betterReflectionMethod->getShortName(); } /** @return array */ public function getStaticVariables() : array { throw new NotImplemented('Not implemented'); } public function returnsReference() : bool { return $this->betterReflectionMethod->returnsReference(); } public function isGenerator() : bool { return $this->betterReflectionMethod->isGenerator(); } public function isVariadic() : bool { return $this->betterReflectionMethod->isVariadic(); } public function isPublic() : bool { return $this->betterReflectionMethod->isPublic(); } public function isPrivate() : bool { return $this->betterReflectionMethod->isPrivate(); } public function isProtected() : bool { return $this->betterReflectionMethod->isProtected(); } public function isAbstract() : bool { return $this->betterReflectionMethod->isAbstract(); } public function isFinal() : bool { return $this->betterReflectionMethod->isFinal(); } public function isStatic() : bool { return $this->betterReflectionMethod->isStatic(); } public function isConstructor() : bool { return $this->betterReflectionMethod->isConstructor(); } public function isDestructor() : bool { return $this->betterReflectionMethod->isDestructor(); } /** * {@inheritDoc} */ public function getClosure($object = null) : Closure { try { return $this->betterReflectionMethod->getClosure($object); } catch (NoObjectProvided $e) { throw new ValueError($e->getMessage(), 0, $e); } catch (Throwable $e) { throw new CoreReflectionException($e->getMessage(), 0, $e); } } public function getModifiers() : int { return $this->betterReflectionMethod->getModifiers(); } /** * @param object $object * @param mixed $arg * @param mixed ...$args * * @return mixed * * @throws CoreReflectionException */ #[\ReturnTypeWillChange] public function invoke($object = null, $arg = null, ...$args) { try { return $this->betterReflectionMethod->invoke($object, $arg, ...$args); } catch (NoObjectProvided $exception) { return null; } catch (Throwable $e) { throw new CoreReflectionException($e->getMessage(), 0, $e); } } /** * @param object $object * @param mixed[] $args * * @return mixed * * @throws CoreReflectionException */ #[\ReturnTypeWillChange] public function invokeArgs($object = null, array $args = []) { try { return $this->betterReflectionMethod->invokeArgs($object, $args); } catch (NoObjectProvided $exception) { return null; } catch (Throwable $e) { throw new CoreReflectionException($e->getMessage(), 0, $e); } } public function getDeclaringClass() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($this->betterReflectionMethod->getImplementingClass()); } public function getPrototype() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod { return new self($this->betterReflectionMethod->getPrototype()); } public function hasPrototype() : bool { try { $this->betterReflectionMethod->getPrototype(); return \true; } catch (MethodPrototypeNotFound $exception) { return \false; } } /** * {@inheritDoc} * @codeCoverageIgnore * @infection-ignore-all */ public function setAccessible($accessible) : void { } /** * @param class-string|null $name * * @return list */ public function getAttributes(?string $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterReflectionMethod->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterReflectionMethod->getAttributesByName($name); } else { $attributes = $this->betterReflectionMethod->getAttributes(); } return array_map(static function (BetterReflectionAttribute $betterReflectionAttribute) { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute); }, $attributes); } public function hasTentativeReturnType() : bool { return $this->betterReflectionMethod->hasTentativeReturnType(); } /** @return ReflectionUnionType|ReflectionNamedType|ReflectionIntersectionType|null */ public function getTentativeReturnType() : ?CoreReflectionType { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionType::fromTypeOrNull($this->betterReflectionMethod->getTentativeReturnType()); } /** @return mixed[] */ public function getClosureUsedVariables() : array { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } /** * @return mixed */ public function __get(string $name) { if ($name === 'name') { return $this->betterReflectionMethod->getName(); } if ($name === 'class') { return $this->betterReflectionMethod->getImplementingClass()->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } public function getBetterReflection() : BetterReflectionMethod { return $this->betterReflectionMethod; } } betterClassConstantOrEnumCase = $betterClassConstantOrEnumCase; unset($this->name); unset($this->class); } public function getName() : string { return $this->betterClassConstantOrEnumCase->getName(); } /** @psalm-mutation-free */ public function hasType() : bool { if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) { return \false; } return $this->betterClassConstantOrEnumCase->hasType(); } /** * @psalm-mutation-free * @return ReflectionUnionType|ReflectionNamedType|ReflectionIntersectionType|null */ public function getType() : ?CoreReflectionType { if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) { return null; } return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionType::fromTypeOrNull($this->betterClassConstantOrEnumCase->getType()); } /** * @deprecated Use getValueExpression() */ #[\ReturnTypeWillChange] public function getValue() { if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } return $this->betterClassConstantOrEnumCase->getValue(); } /** * @deprecated Use getValueExpression() */ public function getValueExpr() : Expr { return $this->getValueExpression(); } public function getValueExpression() : Expr { return $this->betterClassConstantOrEnumCase->getValueExpression(); } public function isPublic() : bool { if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) { return \true; } return $this->betterClassConstantOrEnumCase->isPublic(); } public function isPrivate() : bool { if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) { return \false; } return $this->betterClassConstantOrEnumCase->isPrivate(); } public function isProtected() : bool { if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) { return \false; } return $this->betterClassConstantOrEnumCase->isProtected(); } public function getModifiers() : int { if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant::IS_PUBLIC_COMPATIBILITY; } return $this->betterClassConstantOrEnumCase->getModifiers(); } public function getDeclaringClass() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass { if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($this->betterClassConstantOrEnumCase->getDeclaringClass()); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($this->betterClassConstantOrEnumCase->getImplementingClass()); } /** * Returns the doc comment for this constant * * @return string|false */ #[\ReturnTypeWillChange] public function getDocComment() { return $this->betterClassConstantOrEnumCase->getDocComment() ?? \false; } /** * To string * * @link https://php.net/manual/en/reflector.tostring.php * * @return non-empty-string */ public function __toString() : string { return $this->betterClassConstantOrEnumCase->__toString(); } /** * @param class-string|null $name * * @return list */ public function getAttributes(?string $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterClassConstantOrEnumCase->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterClassConstantOrEnumCase->getAttributesByName($name); } else { $attributes = $this->betterClassConstantOrEnumCase->getAttributes(); } /** @psalm-suppress ImpureFunctionCall */ return array_map(static function (BetterReflectionAttribute $betterReflectionAttribute) { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute); }, $attributes); } public function isFinal() : bool { if ($this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase) { return \true; } return $this->betterClassConstantOrEnumCase->isFinal(); } public function isEnumCase() : bool { return $this->betterClassConstantOrEnumCase instanceof BetterReflectionEnumCase; } /** * @return mixed */ public function __get(string $name) { if ($name === 'name') { return $this->betterClassConstantOrEnumCase->getName(); } if ($name === 'class') { return $this->getDeclaringClass()->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } } = 80000 && PHP_VERSION_ID < 80012) { return new \PHPStan\BetterReflection\Reflection\Adapter\FakeReflectionAttribute($betterReflectionAttribute); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute($betterReflectionAttribute); } } betterReflectionFunction = $betterReflectionFunction; unset($this->name); } public function __toString() : string { return $this->betterReflectionFunction->__toString(); } public function inNamespace() : bool { return $this->betterReflectionFunction->inNamespace(); } public function isClosure() : bool { return $this->betterReflectionFunction->isClosure(); } public function isDeprecated() : bool { return $this->betterReflectionFunction->isDeprecated(); } public function isInternal() : bool { return $this->betterReflectionFunction->isInternal(); } public function isUserDefined() : bool { return $this->betterReflectionFunction->isUserDefined(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getClosureThis() { throw new NotImplemented('Not implemented'); } public function getClosureScopeClass() : ?CoreReflectionClass { throw new NotImplemented('Not implemented'); } public function getClosureCalledClass() : ?CoreReflectionClass { throw new NotImplemented('Not implemented'); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getDocComment() { return $this->betterReflectionFunction->getDocComment() ?? \false; } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getStartLine() { return $this->betterReflectionFunction->getStartLine(); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getEndLine() { return $this->betterReflectionFunction->getEndLine(); } /** @psalm-suppress ImplementedReturnTypeMismatch */ public function getExtension() : ?CoreReflectionExtension { throw new NotImplemented('Not implemented'); } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getExtensionName() { return $this->betterReflectionFunction->getExtensionName() ?? \false; } /** * {@inheritDoc} */ #[\ReturnTypeWillChange] public function getFileName() { $fileName = $this->betterReflectionFunction->getFileName(); return $fileName !== null ? FileHelper::normalizeSystemPath($fileName) : \false; } public function getName() : string { return $this->betterReflectionFunction->getName(); } public function getNamespaceName() : string { return $this->betterReflectionFunction->getNamespaceName() ?? ''; } public function getNumberOfParameters() : int { return $this->betterReflectionFunction->getNumberOfParameters(); } public function getNumberOfRequiredParameters() : int { return $this->betterReflectionFunction->getNumberOfRequiredParameters(); } /** @return list */ public function getParameters() : array { return array_map(static function (BetterReflectionParameter $parameter) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter($parameter); }, $this->betterReflectionFunction->getParameters()); } public function hasReturnType() : bool { return $this->betterReflectionFunction->hasReturnType(); } /** @return ReflectionUnionType|ReflectionNamedType|ReflectionIntersectionType|null */ public function getReturnType() : ?CoreReflectionType { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionType::fromTypeOrNull($this->betterReflectionFunction->getReturnType()); } public function getShortName() : string { return $this->betterReflectionFunction->getShortName(); } /** @return array */ public function getStaticVariables() : array { throw new NotImplemented('Not implemented'); } public function returnsReference() : bool { return $this->betterReflectionFunction->returnsReference(); } public function isGenerator() : bool { return $this->betterReflectionFunction->isGenerator(); } public function isVariadic() : bool { return $this->betterReflectionFunction->isVariadic(); } public function isDisabled() : bool { return $this->betterReflectionFunction->isDisabled(); } /** * @param mixed $arg * @param mixed ...$args * * @return mixed * * @throws CoreReflectionException */ #[\ReturnTypeWillChange] public function invoke($arg = null, ...$args) { try { return $this->betterReflectionFunction->invoke(...func_get_args()); } catch (Throwable $e) { throw new CoreReflectionException($e->getMessage(), 0, $e); } } /** * @param mixed[] $args */ #[\ReturnTypeWillChange] public function invokeArgs(array $args) { try { return $this->betterReflectionFunction->invokeArgs($args); } catch (Throwable $e) { throw new CoreReflectionException($e->getMessage(), 0, $e); } } public function getClosure() : Closure { return $this->betterReflectionFunction->getClosure(); } /** @return mixed[] */ public function getClosureUsedVariables() : array { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } public function hasTentativeReturnType() : bool { return $this->betterReflectionFunction->hasTentativeReturnType(); } /** @return ReflectionUnionType|ReflectionNamedType|ReflectionIntersectionType|null */ public function getTentativeReturnType() : ?CoreReflectionType { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionType::fromTypeOrNull($this->betterReflectionFunction->getTentativeReturnType()); } public function isStatic() : bool { return $this->betterReflectionFunction->isStatic(); } /** * @param class-string|null $name * * @return list */ public function getAttributes(?string $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterReflectionFunction->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterReflectionFunction->getAttributesByName($name); } else { $attributes = $this->betterReflectionFunction->getAttributes(); } return array_map(static function (BetterReflectionAttribute $betterReflectionAttribute) { return \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute); }, $attributes); } /** * @return mixed */ public function __get(string $name) { if ($name === 'name') { return $this->betterReflectionFunction->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } public function isAnonymous() : bool { return $this->betterReflectionFunction->isClosure(); } } name); unset($this->class); } /** * Get the name of the reflection (e.g. if this is a ReflectionClass this * will be the class name). */ public function getName() : string { return $this->betterReflectionEnumCase->getName(); } public function hasType() : bool { return \false; } public function getType() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionUnionType|\PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType|\PHPStan\BetterReflection\Reflection\Adapter\ReflectionIntersectionType|null { return null; } public function getValue() : UnitEnum { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } public function isPublic() : bool { return \true; } public function isPrivate() : bool { return \false; } public function isProtected() : bool { return \false; } public function getModifiers() : int { return self::IS_PUBLIC; } public function getDeclaringClass() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($this->betterReflectionEnumCase->getDeclaringClass()); } public function getDocComment() : string|false { return $this->betterReflectionEnumCase->getDocComment() ?? \false; } /** @return non-empty-string */ public function __toString() : string { return $this->betterReflectionEnumCase->__toString(); } /** * @param class-string|null $name * * @return list */ public function getAttributes(string|null $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterReflectionEnumCase->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterReflectionEnumCase->getAttributesByName($name); } else { $attributes = $this->betterReflectionEnumCase->getAttributes(); } /** @psalm-suppress ImpureFunctionCall */ return array_map(static fn(BetterReflectionAttribute $betterReflectionAttribute): \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute|\PHPStan\BetterReflection\Reflection\Adapter\FakeReflectionAttribute => \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute), $attributes); } public function isFinal() : bool { return \true; } public function isEnumCase() : bool { return \true; } public function getEnum() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum($this->betterReflectionEnumCase->getDeclaringEnum()); } public function __get(string $name) : mixed { if ($name === 'name') { return $this->betterReflectionEnumCase->getName(); } if ($name === 'class') { return $this->betterReflectionEnumCase->getDeclaringClass()->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } } betterReflectionAttribute = $betterReflectionAttribute; } public function getName() : string { return $this->betterReflectionAttribute->getName(); } public function getTarget() : int { return $this->betterReflectionAttribute->getTarget(); } public function isRepeated() : bool { return $this->betterReflectionAttribute->isRepeated(); } /** * @deprecated Use getArgumentsExpressions() * @return array */ public function getArguments() : array { return $this->betterReflectionAttribute->getArguments(); } /** @return array */ public function getArgumentsExpressions() : array { return $this->betterReflectionAttribute->getArgumentsExpressions(); } public function newInstance() : object { $class = $this->getName(); return new $class(...$this->getArguments()); } public function __toString() : string { return $this->betterReflectionAttribute->__toString(); } } name); } /** @return non-empty-string */ public function __toString() : string { return $this->betterReflectionEnum->__toString(); } public function __get(string $name) : mixed { if ($name === 'name') { return $this->betterReflectionEnum->getName(); } throw new OutOfBoundsException(sprintf('Property %s::$%s does not exist.', self::class, $name)); } /** @return class-string */ public function getName() : string { return $this->betterReflectionEnum->getName(); } public function isAnonymous() : bool { return $this->betterReflectionEnum->isAnonymous(); } public function isInternal() : bool { return $this->betterReflectionEnum->isInternal(); } public function isUserDefined() : bool { return $this->betterReflectionEnum->isUserDefined(); } public function isInstantiable() : bool { return $this->betterReflectionEnum->isInstantiable(); } public function isCloneable() : bool { return $this->betterReflectionEnum->isCloneable(); } /** @return non-empty-string|false */ public function getFileName() : string|false { $fileName = $this->betterReflectionEnum->getFileName(); return $fileName !== null ? FileHelper::normalizeSystemPath($fileName) : \false; } public function getStartLine() : int|false { return $this->betterReflectionEnum->getStartLine(); } public function getEndLine() : int|false { return $this->betterReflectionEnum->getEndLine(); } public function getDocComment() : string|false { return $this->betterReflectionEnum->getDocComment() ?? \false; } /** @return ReflectionMethod|null */ public function getConstructor() : ?CoreReflectionMethod { $constructor = $this->betterReflectionEnum->getConstructor(); if ($constructor === null) { return null; } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($constructor); } public function hasMethod(string $name) : bool { if ($name === '') { return \false; } return $this->betterReflectionEnum->hasMethod($name); } public function getMethod(string $name) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod { $method = $name !== '' ? $this->betterReflectionEnum->getMethod($name) : null; if ($method === null) { throw new CoreReflectionException(sprintf('Method %s::%s() does not exist', $this->betterReflectionEnum->getName(), $name)); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($method); } /** * @param int-mask-of|null $filter * * @return list */ public function getMethods(int|null $filter = null) : array { /** @psalm-suppress ImpureFunctionCall */ return array_values(array_map(static fn(BetterReflectionMethod $method): \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod => new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod($method), $this->betterReflectionEnum->getMethods($filter ?? 0))); } public function hasProperty(string $name) : bool { if ($name === '') { return \false; } return $this->betterReflectionEnum->hasProperty($name); } public function getProperty(string $name) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty { $betterReflectionProperty = $name !== '' ? $this->betterReflectionEnum->getProperty($name) : null; if ($betterReflectionProperty === null) { throw new CoreReflectionException(sprintf('Property %s::$%s does not exist', $this->betterReflectionEnum->getName(), $name)); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($betterReflectionProperty); } /** * @param int-mask-of|null $filter * * @return list */ public function getProperties(int|null $filter = null) : array { /** @psalm-suppress ImpureFunctionCall */ return array_values(array_map(static fn(BetterReflectionProperty $property): \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty => new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty($property), $this->betterReflectionEnum->getProperties($filter ?? 0))); } public function hasConstant(string $name) : bool { if ($name === '') { return \false; } return $this->betterReflectionEnum->hasCase($name) || $this->betterReflectionEnum->hasConstant($name); } /** * @deprecated Use getReflectionConstants() * * @param int-mask-of|null $filter * * @return array */ public function getConstants(int|null $filter = null) : array { /** @psalm-suppress ImpureFunctionCall */ return array_map(fn(BetterReflectionClassConstant|BetterReflectionEnumCase $betterConstantOrEnumCase): mixed => $this->getConstantValue($betterConstantOrEnumCase), $this->filterBetterReflectionClassConstants($filter)); } /** * @deprecated Use getReflectionConstant() */ public function getConstant(string $name) : mixed { if ($name === '') { return \false; } $enumCase = $this->betterReflectionEnum->getCase($name); if ($enumCase !== null) { return $this->getConstantValue($enumCase); } $betterReflectionConstant = $this->betterReflectionEnum->getConstant($name); if ($betterReflectionConstant === null) { return \false; } return $betterReflectionConstant->getValue(); } private function getConstantValue(BetterReflectionClassConstant|BetterReflectionEnumCase $betterConstantOrEnumCase) : mixed { if ($betterConstantOrEnumCase instanceof BetterReflectionEnumCase) { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } return $betterConstantOrEnumCase->getValue(); } public function getReflectionConstant(string $name) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant|false { if ($name === '') { return \false; } // @infection-ignore-all Coalesce: There's no difference $betterReflectionConstantOrEnumCase = $this->betterReflectionEnum->getCase($name) ?? $this->betterReflectionEnum->getConstant($name); if ($betterReflectionConstantOrEnumCase === null) { return \false; } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant($betterReflectionConstantOrEnumCase); } /** * @param int-mask-of|null $filter * * @return list */ public function getReflectionConstants(int|null $filter = null) : array { return array_values(array_map(static fn(BetterReflectionClassConstant|BetterReflectionEnumCase $betterConstantOrEnum): \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant => new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant($betterConstantOrEnum), $this->filterBetterReflectionClassConstants($filter))); } /** * @param int-mask-of|null $filter * * @return array */ private function filterBetterReflectionClassConstants(int|null $filter) : array { $reflectionConstants = $this->betterReflectionEnum->getConstants($filter ?? 0); if ($filter === null || $filter & \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant::IS_PUBLIC_COMPATIBILITY) { $reflectionConstants += $this->betterReflectionEnum->getCases(); } return $reflectionConstants; } /** @return array */ public function getInterfaces() : array { /** @psalm-suppress ImpureFunctionCall */ return array_map(static fn(BetterReflectionClass $interface): \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass => new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($interface), $this->betterReflectionEnum->getInterfaces()); } /** @return list */ public function getInterfaceNames() : array { return $this->betterReflectionEnum->getInterfaceNames(); } public function isInterface() : bool { return $this->betterReflectionEnum->isInterface(); } /** @return array */ public function getTraits() : array { $traits = $this->betterReflectionEnum->getTraits(); /** @var list $traitNames */ $traitNames = array_map(static fn(BetterReflectionClass $trait): string => $trait->getName(), $traits); /** @psalm-suppress ImpureFunctionCall */ return array_combine($traitNames, array_map(static fn(BetterReflectionClass $trait): \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass => new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass($trait), $traits)); } /** @return list */ public function getTraitNames() : array { return $this->betterReflectionEnum->getTraitNames(); } /** @return array */ public function getTraitAliases() : array { return $this->betterReflectionEnum->getTraitAliases(); } public function isTrait() : bool { return $this->betterReflectionEnum->isTrait(); } public function isAbstract() : bool { return $this->betterReflectionEnum->isAbstract(); } public function isFinal() : bool { return $this->betterReflectionEnum->isFinal(); } public function isReadOnly() : bool { return $this->betterReflectionEnum->isReadOnly(); } public function getModifiers() : int { return $this->betterReflectionEnum->getModifiers(); } public function isInstance(object $object) : bool { return $this->betterReflectionEnum->isInstance($object); } public function newInstance(mixed ...$args) : object { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } public function newInstanceWithoutConstructor() : object { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } public function newInstanceArgs(array|null $args = null) : object { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } public function getParentClass() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass|false { return \false; } public function isSubclassOf(CoreReflectionClass|string $class) : bool { $realParentClassNames = $this->betterReflectionEnum->getParentClassNames(); $parentClassNames = array_combine(array_map(static fn(string $parentClassName): string => strtolower($parentClassName), $realParentClassNames), $realParentClassNames); $className = $class instanceof CoreReflectionClass ? $class->getName() : $class; $lowercasedClassName = strtolower($className); $realParentClassName = $parentClassNames[$lowercasedClassName] ?? $className; if ($this->betterReflectionEnum->isSubclassOf($realParentClassName)) { return \true; } return $this->implementsInterface($className); } /** * @return array * * @psalm-suppress LessSpecificImplementedReturnType */ public function getStaticProperties() : array { return $this->betterReflectionEnum->getStaticProperties(); } public function getStaticPropertyValue(string $name, mixed $default = null) : mixed { throw new CoreReflectionException(sprintf('Property %s::$%s does not exist', $this->betterReflectionEnum->getName(), $name)); } public function setStaticPropertyValue(string $name, mixed $value) : void { throw new CoreReflectionException(sprintf('Class %s does not have a property named %s', $this->betterReflectionEnum->getName(), $name)); } /** @return array */ public function getDefaultProperties() : array { return $this->betterReflectionEnum->getDefaultProperties(); } public function isIterateable() : bool { return $this->betterReflectionEnum->isIterateable(); } public function isIterable() : bool { return $this->isIterateable(); } public function implementsInterface(CoreReflectionClass|string $interface) : bool { $realInterfaceNames = $this->betterReflectionEnum->getInterfaceNames(); $interfaceNames = array_combine(array_map(static fn(string $interfaceName): string => strtolower($interfaceName), $realInterfaceNames), $realInterfaceNames); $interfaceName = $interface instanceof CoreReflectionClass ? $interface->getName() : $interface; $lowercasedInterfaceName = strtolower($interfaceName); $realInterfaceName = $interfaceNames[$lowercasedInterfaceName] ?? $interfaceName; return $this->betterReflectionEnum->implementsInterface($realInterfaceName); } public function getExtension() : ?CoreReflectionExtension { throw new \PHPStan\BetterReflection\Reflection\Adapter\Exception\NotImplemented('Not implemented'); } /** @return non-empty-string|false */ public function getExtensionName() : string|false { return $this->betterReflectionEnum->getExtensionName() ?? \false; } public function inNamespace() : bool { return $this->betterReflectionEnum->inNamespace(); } public function getNamespaceName() : string { return $this->betterReflectionEnum->getNamespaceName() ?? ''; } public function getShortName() : string { return $this->betterReflectionEnum->getShortName(); } /** * @param class-string|null $name * * @return list */ public function getAttributes(string|null $name = null, int $flags = 0) : array { if ($flags !== 0 && $flags !== \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute::IS_INSTANCEOF) { throw new ValueError('Argument #2 ($flags) must be a valid attribute filter flag'); } if ($name !== null && $flags !== 0) { $attributes = $this->betterReflectionEnum->getAttributesByInstance($name); } elseif ($name !== null) { $attributes = $this->betterReflectionEnum->getAttributesByName($name); } else { $attributes = $this->betterReflectionEnum->getAttributes(); } /** @psalm-suppress ImpureFunctionCall */ return array_map(static fn(BetterReflectionAttribute $betterReflectionAttribute): \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute|\PHPStan\BetterReflection\Reflection\Adapter\FakeReflectionAttribute => \PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttributeFactory::create($betterReflectionAttribute), $attributes); } public function isEnum() : bool { return $this->betterReflectionEnum->isEnum(); } public function hasCase(string $name) : bool { if ($name === '') { return \false; } return $this->betterReflectionEnum->hasCase($name); } public function getCase(string $name) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumUnitCase|\PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumBackedCase { $case = $name !== '' ? $this->betterReflectionEnum->getCase($name) : null; if ($case === null) { throw new CoreReflectionException(sprintf('Case %s::%s does not exist', $this->betterReflectionEnum->getName(), $name)); } if ($this->betterReflectionEnum->isBacked()) { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumBackedCase($case); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumUnitCase($case); } /** @return list */ public function getCases() : array { /** @psalm-suppress ImpureFunctionCall */ return array_map(function (BetterReflectionEnumCase $case) : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumUnitCase|\PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumBackedCase { if ($this->betterReflectionEnum->isBacked()) { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumBackedCase($case); } return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumUnitCase($case); }, array_values($this->betterReflectionEnum->getCases())); } public function isBacked() : bool { return $this->betterReflectionEnum->isBacked(); } public function getBackingType() : \PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType|null { if ($this->betterReflectionEnum->isBacked()) { return new \PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType($this->betterReflectionEnum->getBackingType(), \false); } return null; } } reflector = $reflector; $this->locatedSource = $locatedSource; /** @psalm-allow-private-mutation */ $this->namespace = $namespace; $this->setNamesFromNode($node, $positionInNode); if ($node instanceof Node\Expr\FuncCall) { $argumentValueNode = $node->args[1]; assert($argumentValueNode instanceof Node\Arg); $this->value = $argumentValueNode->value; } else { /** @psalm-suppress PossiblyNullArrayOffset */ $this->value = $node->consts[$positionInNode]->value; } $this->docComment = GetLastDocComment::forNode($node); $startLine = $node->getStartLine(); assert($startLine > 0); $endLine = $node->getEndLine(); assert($endLine > 0); $this->startLine = $startLine; $this->endLine = $endLine; $this->startColumn = CalculateReflectionColumn::getStartColumn($this->locatedSource->getSource(), $node); $this->endColumn = CalculateReflectionColumn::getEndColumn($this->locatedSource->getSource(), $node); } /** * Create a ReflectionConstant by name, using default reflectors etc. * * @deprecated Use Reflector instead. * * @throws IdentifierNotFound */ public static function createFromName(string $constantName) : self { return (new BetterReflection())->reflector()->reflectConstant($constantName); } /** * Create a reflection of a constant * * @internal * * @param Node\Stmt\Const_|Node\Expr\FuncCall $node Node has to be processed by the PhpParser\NodeVisitor\NameResolver * @param non-empty-string|null $namespace */ public static function createFromNode(Reflector $reflector, Node $node, LocatedSource $locatedSource, ?string $namespace = null, ?int $positionInNode = null) : self { if ($node instanceof Node\Stmt\Const_) { assert(is_int($positionInNode)); return self::createFromConstKeyword($reflector, $node, $locatedSource, $namespace, $positionInNode); } return self::createFromDefineFunctionCall($reflector, $node, $locatedSource); } /** @param non-empty-string|null $namespace */ private static function createFromConstKeyword(Reflector $reflector, Node\Stmt\Const_ $node, LocatedSource $locatedSource, ?string $namespace, int $positionInNode) : self { return new self($reflector, $node, $locatedSource, $namespace, $positionInNode); } /** @throws InvalidConstantNode */ private static function createFromDefineFunctionCall(Reflector $reflector, Node\Expr\FuncCall $node, LocatedSource $locatedSource) : self { ConstantNodeChecker::assertValidDefineFunctionCall($node); return new self($reflector, $node, $locatedSource); } /** * Get the "short" name of the constant (e.g. for A\B\FOO, this will return * "FOO"). * * @return non-empty-string */ public function getShortName() : string { return $this->shortName; } /** * Get the "full" name of the constant (e.g. for A\B\FOO, this will return * "A\B\FOO"). * * @return non-empty-string */ public function getName() : string { return $this->name; } /** * Get the "namespace" name of the constant (e.g. for A\B\FOO, this will * return "A\B"). * * @return non-empty-string|null */ public function getNamespaceName() : ?string { return $this->namespace; } /** * Decide if this constant is part of a namespace. Returns false if the constant * is in the global namespace or does not have a specified namespace. */ public function inNamespace() : bool { return $this->namespace !== null; } /** @return non-empty-string|null */ public function getExtensionName() : ?string { return $this->locatedSource->getExtensionName(); } /** * Is this an internal constant? */ public function isInternal() : bool { return $this->locatedSource->isInternal(); } /** * Is this a user-defined function (will always return the opposite of * whatever isInternal returns). */ public function isUserDefined() : bool { return !$this->isInternal(); } public function isDeprecated() : bool { return AnnotationHelper::isDeprecated($this->getDocComment()); } /** * @deprecated Use getValueExpression() * @return Node\Expr */ public function getValueExpr() : Node\Expr { return $this->getValueExpression(); } public function getValueExpression() : Node\Expr { return $this->value; } /** * @deprecated Use getValueExpression() * @return mixed */ public function getValue() { if ($this->compiledValue === null) { $this->compiledValue = (new CompileNodeToValue())->__invoke($this->value, new CompilerContext($this->reflector, $this)); } return $this->compiledValue->value; } /** @return non-empty-string|null */ public function getFileName() : ?string { return $this->locatedSource->getFileName(); } public function getLocatedSource() : LocatedSource { return $this->locatedSource; } /** * Get the line number that this constant starts on. * * @return positive-int */ public function getStartLine() : int { return $this->startLine; } /** * Get the line number that this constant ends on. * * @return positive-int */ public function getEndLine() : int { return $this->endLine; } /** @return positive-int */ public function getStartColumn() : int { return $this->startColumn; } /** @return positive-int */ public function getEndColumn() : int { return $this->endColumn; } /** @return non-empty-string|null */ public function getDocComment() : ?string { return $this->docComment; } /** @return non-empty-string */ public function __toString() : string { return ReflectionConstantStringCast::toString($this); } /** * @param \PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall $node */ private function setNamesFromNode($node, ?int $positionInNode) : void { if ($node instanceof Node\Expr\FuncCall) { $name = $this->getNameFromDefineFunctionCall($node); $nameParts = explode('\\', $name); $this->namespace = implode('\\', array_slice($nameParts, 0, -1)) ?: null; $shortName = $nameParts[count($nameParts) - 1]; assert($shortName !== ''); } else { /** @psalm-suppress PossiblyNullArrayOffset */ $constNode = $node->consts[$positionInNode]; $namespacedName = $constNode->namespacedName; assert($namespacedName instanceof Node\Name); $name = $namespacedName->toString(); assert($name !== ''); $shortName = $constNode->name->name; assert($shortName !== ''); } $this->name = $name; $this->shortName = $shortName; } /** @return non-empty-string */ private function getNameFromDefineFunctionCall(Node\Expr\FuncCall $node) : string { $argumentNameNode = $node->args[0]; assert($argumentNameNode instanceof Node\Arg); $nameNode = $argumentNameNode->value; assert($nameNode instanceof Node\Scalar\String_); /** @psalm-var non-empty-string */ return $nameNode->value; } } printer(); return new self(sprintf('Invalid arrow function body node (first 50 characters: %s)', substr($printer->prettyPrint([$node]), 0, 50))); } } printer(); return new self(sprintf('Invalid constant node (first 50 characters: %s)', substr($printer->prettyPrint([$node]), 0, 50))); } } getName())); } } * * @psalm-pure * @param \PHPStan\BetterReflection\Reflection\ReflectionClass|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionClassConstant|\PHPStan\BetterReflection\Reflection\ReflectionEnumCase|\PHPStan\BetterReflection\Reflection\ReflectionProperty|\PHPStan\BetterReflection\Reflection\ReflectionParameter $reflection */ public static function createAttributes(Reflector $reflector, $reflection, array $attrGroups) : array { $repeated = []; foreach ($attrGroups as $attributesGroupNode) { foreach ($attributesGroupNode->attrs as $attributeNode) { $repeated[$attributeNode->name->toLowerString()][] = $attributeNode; } } $attributes = []; foreach ($attrGroups as $attributesGroupNode) { foreach ($attributesGroupNode->attrs as $attributeNode) { $attributes[] = new ReflectionAttribute($reflector, $attributeNode, $reflection, count($repeated[$attributeNode->name->toLowerString()]) > 1); } } return $attributes; } /** * @param list $attributes * * @return list * * @psalm-pure */ public static function filterAttributesByName(array $attributes, string $name) : array { return array_values(array_filter($attributes, static function (ReflectionAttribute $attribute) use($name) : bool { return $attribute->getName() === $name; })); } /** * @param list $attributes * @param class-string $className * * @return list * * @psalm-pure */ public static function filterAttributesByInstance(array $attributes, string $className) : array { return array_values(array_filter($attributes, static function (ReflectionAttribute $attribute) use($className) : bool { $class = $attribute->getClass(); return $class->getName() === $className || $class->isSubclassOf($className) || $class->implementsInterface($className); })); } } */ private $cases; /** * @var \PHPStan\BetterReflection\Reflector\Reflector */ private $reflector; /** * @param non-empty-string|null $namespace * * @phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod.Found */ private function __construct(Reflector $reflector, EnumNode $node, LocatedSource $locatedSource, ?string $namespace = null) { $this->reflector = $reflector; parent::__construct($reflector, $node, $locatedSource, $namespace); $this->backingType = $this->createBackingType($node); $this->cases = $this->createCases($node); } /** * @internal * * @param EnumNode $node * @param non-empty-string|null $namespace * * @psalm-suppress MoreSpecificImplementedParamType * @return $this */ public static function createFromNode(Reflector $reflector, $node, LocatedSource $locatedSource, ?string $namespace = null) : \PHPStan\BetterReflection\Reflection\ReflectionClass { $node = $node; assert($node instanceof EnumNode); return new self($reflector, $node, $locatedSource, $namespace); } /** @param non-empty-string $name */ public function hasCase(string $name) : bool { return array_key_exists($name, $this->cases); } /** @param non-empty-string $name */ public function getCase(string $name) : ?\PHPStan\BetterReflection\Reflection\ReflectionEnumCase { return $this->cases[$name] ?? null; } /** @return array */ public function getCases() : array { return $this->cases; } /** @return array */ private function createCases(EnumNode $node) : array { $enumCasesNodes = array_filter($node->stmts, static function (Node\Stmt $stmt) : bool { return $stmt instanceof Node\Stmt\EnumCase; }); return array_combine(array_map(static function (Node\Stmt\EnumCase $enumCaseNode) : string { $enumCaseName = $enumCaseNode->name->toString(); assert($enumCaseName !== ''); return $enumCaseName; }, $enumCasesNodes), array_map(function (Node\Stmt\EnumCase $enumCaseNode) : \PHPStan\BetterReflection\Reflection\ReflectionEnumCase { return \PHPStan\BetterReflection\Reflection\ReflectionEnumCase::createFromNode($this->reflector, $enumCaseNode, $this); }, $enumCasesNodes)); } public function isBacked() : bool { return $this->backingType !== null; } public function getBackingType() : \PHPStan\BetterReflection\Reflection\ReflectionNamedType { if ($this->backingType === null) { throw new LogicException('This enum does not have a backing type available'); } return $this->backingType; } private function createBackingType(EnumNode $node) : ?\PHPStan\BetterReflection\Reflection\ReflectionNamedType { if ($node->scalarType === null) { return null; } $backingType = \PHPStan\BetterReflection\Reflection\ReflectionNamedType::createFromNode($this->reflector, $this, $node->scalarType); assert($backingType instanceof \PHPStan\BetterReflection\Reflection\ReflectionNamedType); return $backingType; } } reflector = new \PHPStan\BetterReflection\Reflector\DefaultReflector($sourceLocator); } /** * Create a ReflectionFunction for the specified $functionName. * * @throws IdentifierNotFound */ public function reflect(string $constantName) : ReflectionConstant { return $this->reflector->reflectConstant($constantName); } /** * Get all the classes available in the scope specified by the SourceLocator. * * @return ReflectionConstant[] */ public function getAllConstants() : array { return $this->reflector->reflectAllConstants(); } public function reflectClass(string $identifierName) : ReflectionClass { return $this->reflector->reflectClass($identifierName); } /** * @return list */ public function reflectAllClasses() : iterable { return $this->reflector->reflectAllClasses(); } public function reflectFunction(string $identifierName) : ReflectionFunction { return $this->reflector->reflectFunction($identifierName); } /** * @return list */ public function reflectAllFunctions() : iterable { return $this->reflector->reflectAllFunctions(); } public function reflectConstant(string $identifierName) : ReflectionConstant { return $this->reflector->reflectConstant($identifierName); } /** * @return list */ public function reflectAllConstants() : iterable { return $this->reflector->reflectAllConstants(); } } reflector = new \PHPStan\BetterReflection\Reflector\DefaultReflector($sourceLocator); } /** * Create a ReflectionFunction for the specified $functionName. * * @throws IdentifierNotFound */ public function reflect(string $functionName) : ReflectionFunction { return $this->reflector->reflectFunction($functionName); } /** * Get all the classes available in the scope specified by the SourceLocator. * * @return ReflectionFunction[] */ public function getAllFunctions() : array { return $this->reflector->reflectAllFunctions(); } public function reflectClass(string $identifierName) : ReflectionClass { return $this->reflector->reflectClass($identifierName); } /** * @return list */ public function reflectAllClasses() : iterable { return $this->reflector->reflectAllClasses(); } public function reflectFunction(string $identifierName) : ReflectionFunction { return $this->reflector->reflectFunction($identifierName); } /** * @return list */ public function reflectAllFunctions() : iterable { return $this->reflector->reflectAllFunctions(); } public function reflectConstant(string $identifierName) : ReflectionConstant { return $this->reflector->reflectConstant($identifierName); } /** * @return list */ public function reflectAllConstants() : iterable { return $this->reflector->reflectAllConstants(); } } */ public function reflectAllClasses() : iterable; /** * Create a ReflectionFunction for the specified $functionName. * * @throws IdentifierNotFound */ public function reflectFunction(string $identifierName) : ReflectionFunction; /** * Get all the functions available in the scope specified by the SourceLocator. * * @return list */ public function reflectAllFunctions() : iterable; /** * Create a ReflectionConstant for the specified $constantName. * * @throws IdentifierNotFound */ public function reflectConstant(string $identifierName) : ReflectionConstant; /** * Get all the constants available in the scope specified by the SourceLocator. * * @return list */ public function reflectAllConstants() : iterable; } reflector = new \PHPStan\BetterReflection\Reflector\DefaultReflector($sourceLocator); } /** * Create a ReflectionClass for the specified $className. * * @throws IdentifierNotFound */ public function reflect(string $className) : ReflectionClass { return $this->reflector->reflectClass($className); } /** * Get all the classes available in the scope specified by the SourceLocator. * * @return ReflectionClass[] */ public function getAllClasses() : array { return $this->reflector->reflectAllClasses(); } public function reflectClass(string $identifierName) : ReflectionClass { return $this->reflector->reflectClass($identifierName); } /** * @return list */ public function reflectAllClasses() : iterable { return $this->reflector->reflectAllClasses(); } public function reflectFunction(string $identifierName) : ReflectionFunction { return $this->reflector->reflectFunction($identifierName); } /** * @return list */ public function reflectAllFunctions() : iterable { return $this->reflector->reflectAllFunctions(); } public function reflectConstant(string $identifierName) : ReflectionConstant { return $this->reflector->reflectConstant($identifierName); } /** * @return list */ public function reflectAllConstants() : iterable { return $this->reflector->reflectAllConstants(); } } sourceLocator = $sourceLocator; } /** * Create a ReflectionClass for the specified $className. * * @throws IdentifierNotFound */ public function reflectClass(string $identifierName) : ReflectionClass { $identifier = new Identifier($identifierName, new IdentifierType(IdentifierType::IDENTIFIER_CLASS)); $classInfo = $this->sourceLocator->locateIdentifier($this, $identifier); if ($classInfo === null) { throw \PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound::fromIdentifier($identifier); } assert($classInfo instanceof ReflectionClass); return $classInfo; } /** * Get all the classes available in the scope specified by the SourceLocator. * * @return list */ public function reflectAllClasses() : iterable { /** @var list $allClasses */ $allClasses = $this->sourceLocator->locateIdentifiersByType($this, new IdentifierType(IdentifierType::IDENTIFIER_CLASS)); return $allClasses; } /** * Create a ReflectionFunction for the specified $functionName. * * @throws IdentifierNotFound */ public function reflectFunction(string $identifierName) : ReflectionFunction { $identifier = new Identifier($identifierName, new IdentifierType(IdentifierType::IDENTIFIER_FUNCTION)); $functionInfo = $this->sourceLocator->locateIdentifier($this, $identifier); if ($functionInfo === null) { throw \PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound::fromIdentifier($identifier); } assert($functionInfo instanceof ReflectionFunction); return $functionInfo; } /** * Get all the functions available in the scope specified by the SourceLocator. * * @return list */ public function reflectAllFunctions() : iterable { /** @var list $allFunctions */ $allFunctions = $this->sourceLocator->locateIdentifiersByType($this, new IdentifierType(IdentifierType::IDENTIFIER_FUNCTION)); return $allFunctions; } /** * Create a ReflectionConstant for the specified $constantName. * * @throws IdentifierNotFound */ public function reflectConstant(string $identifierName) : ReflectionConstant { $identifier = new Identifier($identifierName, new IdentifierType(IdentifierType::IDENTIFIER_CONSTANT)); $constantInfo = $this->sourceLocator->locateIdentifier($this, $identifier); if ($constantInfo === null) { throw \PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound::fromIdentifier($identifier); } assert($constantInfo instanceof ReflectionConstant); return $constantInfo; } /** * Get all the constants available in the scope specified by the SourceLocator. * * @return list */ public function reflectAllConstants() : iterable { /** @var list $allConstants */ $allConstants = $this->sourceLocator->locateIdentifiersByType($this, new IdentifierType(IdentifierType::IDENTIFIER_CONSTANT)); return $allConstants; } } identifier = $identifier; parent::__construct($message); } public function getIdentifier() : Identifier { return $this->identifier; } public static function fromIdentifier(Identifier $identifier) : self { return new self(sprintf('%s "%s" could not be found in the located source', $identifier->getType()->getName(), $identifier->getName()), $identifier); } } sourceLocator = $sourceLocator; $this->astLocator = $astLocator; } /** * Find a reflection on the specified line number. * * Returns null if no reflections found on the line. * * @param non-empty-string $filename * * @throws InvalidFileLocation * @throws ParseToAstFailure * @throws InvalidArgumentException * @return \PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionClass|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionConstant|\PHPStan\BetterReflection\Reflection\Reflection|null */ public function __invoke(string $filename, int $lineNumber) { $reflections = $this->computeReflections($filename); foreach ($reflections as $reflection) { if ($reflection instanceof ReflectionClass && $this->containsLine($reflection, $lineNumber)) { foreach ($reflection->getMethods() as $method) { if ($this->containsLine($method, $lineNumber)) { return $method; } } return $reflection; } if ($reflection instanceof ReflectionFunction && $this->containsLine($reflection, $lineNumber)) { return $reflection; } if ($reflection instanceof ReflectionConstant && $this->containsLine($reflection, $lineNumber)) { return $reflection; } } return null; } /** * Find all class and function reflections in the specified file * * @param non-empty-string $filename * * @return list * * @throws ParseToAstFailure * @throws InvalidFileLocation */ private function computeReflections(string $filename) : array { $singleFileSourceLocator = new SingleFileSourceLocator($filename, $this->astLocator); $reflector = new DefaultReflector(new AggregateSourceLocator([$singleFileSourceLocator, $this->sourceLocator])); return array_merge($singleFileSourceLocator->locateIdentifiersByType($reflector, new IdentifierType(IdentifierType::IDENTIFIER_CLASS)), $singleFileSourceLocator->locateIdentifiersByType($reflector, new IdentifierType(IdentifierType::IDENTIFIER_FUNCTION)), $singleFileSourceLocator->locateIdentifiersByType($reflector, new IdentifierType(IdentifierType::IDENTIFIER_CONSTANT))); } /** * Check to see if the line is within the boundaries of the reflection specified. * @param \PHPStan\BetterReflection\Reflection\ReflectionClass|\PHPStan\BetterReflection\Reflection\ReflectionMethod|\PHPStan\BetterReflection\Reflection\ReflectionFunction|\PHPStan\BetterReflection\Reflection\ReflectionConstant $reflection */ private function containsLine($reflection, int $lineNumber) : bool { return $lineNumber >= $reflection->getStartLine() && $lineNumber <= $reflection->getEndLine(); } } name instanceof Node\Name) { throw InvalidConstantNode::create($node); } if ($node->name->toLowerString() !== 'define') { throw InvalidConstantNode::create($node); } if (!in_array(count($node->args), self::DEFINE_ARGUMENTS_COUNTS, \true)) { throw InvalidConstantNode::create($node); } if (!$node->args[0] instanceof Node\Arg || !$node->args[0]->value instanceof Node\Scalar\String_) { throw InvalidConstantNode::create($node); } if (!$node->args[1] instanceof Node\Arg) { throw InvalidConstantNode::create($node); } $valueNode = $node->args[1]->value; if ($valueNode instanceof Node\Expr\FuncCall && !($valueNode->name instanceof Node\Name && $valueNode->name->toLowerString() === 'constant')) { throw InvalidConstantNode::create($node); } if ($valueNode instanceof Node\Expr\Variable) { throw InvalidConstantNode::create($node); } } } getDocComment(); if ($docComment === null) { return null; } /** @psalm-suppress ImpureMethodCall */ $comment = $docComment->getReformattedText(); assert(is_string($comment) && $comment !== ''); return $comment; } } hasAttribute('startFilePos')) { return -1; } return self::calculateColumn($source, $node->getStartFilePos()); } /** * @throws InvalidNodePosition * @throws NoNodePosition * * @psalm-pure */ public static function getEndColumn(string $source, Node $node) : int { if (!$node->hasAttribute('endFilePos')) { return -1; } return self::calculateColumn($source, $node->getEndFilePos()); } /** * @throws InvalidNodePosition * * @psalm-pure */ private static function calculateColumn(string $source, int $position) : int { $sourceLength = strlen($source); if ($position >= $sourceLength) { return -1; } $lineStartPosition = strrpos($source, "\n", $position - $sourceLength); /** @psalm-var positive-int */ return $lineStartPosition === \false ? $position + 1 : $position - $lineStartPosition; } } sourceLocator = self::$sharedSourceLocator; $this->reflector = self::$sharedReflector; $this->phpParser = self::$sharedPhpParser; $this->sourceStubber = self::$sharedSourceStubber; $this->printer = self::$sharedPrinter; } public function sourceLocator() : SourceLocator { $astLocator = $this->astLocator(); $sourceStubber = $this->sourceStubber(); return $this->sourceLocator ?? ($this->sourceLocator = new MemoizingSourceLocator(new AggregateSourceLocator([new PhpInternalSourceLocator($astLocator, $sourceStubber), new EvaledCodeSourceLocator($astLocator, $sourceStubber), new AutoloadSourceLocator($astLocator, $this->phpParser())]))); } public function reflector() : Reflector { return $this->reflector ?? ($this->reflector = new DefaultReflector($this->sourceLocator())); } public function phpParser() : Parser { return $this->phpParser ?? ($this->phpParser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7, new Emulative(['usedAttributes' => ['comments', 'startLine', 'endLine', 'startFilePos', 'endFilePos']]))); } public function astLocator() : AstLocator { return $this->astLocator ?? ($this->astLocator = new AstLocator($this->phpParser())); } public function findReflectionsOnLine() : FindReflectionOnLine { return $this->findReflectionOnLine ?? ($this->findReflectionOnLine = new FindReflectionOnLine($this->sourceLocator(), $this->astLocator())); } public function sourceStubber() : SourceStubber { return $this->sourceStubber ?? ($this->sourceStubber = new AggregateSourceStubber(new PhpStormStubsSourceStubber($this->phpParser(), $this->printer(), self::$phpVersion), new ReflectionSourceStubber($this->printer()))); } public function printer() : Standard { return $this->printer ?? ($this->printer = new Standard(['shortArraySyntax' => \true])); } } null, self::IDENTIFIER_FUNCTION => null, self::IDENTIFIER_CONSTANT => null]; /** * @var string */ private $name; public function __construct(string $type = self::IDENTIFIER_CLASS) { if (!array_key_exists($type, self::VALID_TYPES)) { throw new InvalidArgumentException(sprintf('%s is not a valid identifier type', $type)); } $this->name = $type; } public function getName() : string { return $this->name; } public function isClass() : bool { return $this->name === self::IDENTIFIER_CLASS; } public function isFunction() : bool { return $this->name === self::IDENTIFIER_FUNCTION; } public function isConstant() : bool { return $this->name === self::IDENTIFIER_CONSTANT; } } type = $type; if ($name === self::WILDCARD || $name === ReflectionFunction::CLOSURE_NAME || strpos($name, ReflectionClass::ANONYMOUS_CLASS_NAME_PREFIX) === 0) { $this->name = $name; return; } $name = ltrim($name, '\\'); if (!preg_match(self::VALID_NAME_REGEXP, $name)) { throw InvalidIdentifierName::fromInvalidName($name); } $this->name = $name; } public function getName() : string { return $this->name; } public function getType() : \PHPStan\BetterReflection\Identifier\IdentifierType { return $this->type; } public function isClass() : bool { return $this->type->isClass(); } public function isFunction() : bool { return $this->type->isFunction(); } public function isConstant() : bool { return $this->type->isConstant(); } } 8, 'endcap' => GEOSBUF_CAP_ROUND, 'join' => GEOSBUF_JOIN_ROUND, 'mitre_limit' => 5.0, 'single_sided' => false ]): GEOSGeometry {} /** * @param float $distance * @param array $styleArray * Keys supported: * 'quad_segs' * Type: int * Number of segments used to approximate * a quarter circle (defaults to 8). * 'join' * Type: long * Join style (defaults to GEOSBUF_JOIN_ROUND) * 'mitre_limit' * Type: double * mitre ratio limit (only affects joins with GEOSBUF_JOIN_MITRE style) * 'miter_limit' is also accepted as a synonym for 'mitre_limit'. * @return GEOSGeometry * @throws Exception */ public function offsetCurve(float $distance, array $styleArray = [ 'quad_segs' => 8, 'join' => GEOSBUF_JOIN_ROUND, 'mitre_limit' => 5.0 ]): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function envelope(): GEOSGeometry {} /** * @param GEOSGeometry $geom * @return GEOSGeometry * @throws Exception */ public function intersection(GEOSGeometry $geom): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function convexHull(): GEOSGeometry {} /** * @param GEOSGeometry $geom * @return GEOSGeometry * @throws Exception */ public function difference(GEOSGeometry $geom): GEOSGeometry {} /** * @param GEOSGeometry $geom * @return GEOSGeometry * @throws Exception */ public function symDifference(GEOSGeometry $geom): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function boundary(): GEOSGeometry {} /** * @param GEOSGeometry|null $geom * @return GEOSGeometry * @throws Exception */ public function union(GEOSGeometry $geom = null): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function pointOnSurface(): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function centroid(): GEOSGeometry {} /** * @param GEOSGeometry $geom * @param string|null $pattern * @return bool|string * @throws Exception */ public function relate(GEOSGeometry $geom, string $pattern = null) {} /** * @param GEOSGeometry $geom * @param int $rule * @return string * @throws Exception */ public function relateBoundaryNodeRule(GEOSGeometry $geom, int $rule = GEOSRELATE_BNR_OGC): string {} /** * @param float $tolerance * @param bool $preserveTopology * @return GEOSGeometry * @throws Exception */ public function simplify(float $tolerance, bool $preserveTopology = false): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function normalize(): GEOSGeometry {} /** * @param float $gridSize * @param int $flags * @return GEOSGeometry * @throws Exception */ public function setPrecision(float $gridSize, int $flags = 0): GEOSGeometry {} /** * @return float */ public function getPrecision(): float {} /** * @return GEOSGeometry * @throws Exception */ public function extractUniquePoints(): GEOSGeometry {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function disjoint(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function touches(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function intersects(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function crosses(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function within(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function contains(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function overlaps(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function covers(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function coveredBy(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @return bool * @throws Exception */ public function equals(GEOSGeometry $geom): bool {} /** * @param GEOSGeometry $geom * @param float $tolerance * @return bool * @throws Exception */ public function equalsExact(GEOSGeometry $geom, float $tolerance = 0): bool {} /** * @return bool * @throws Exception */ public function isEmpty(): bool {} /** * @return array * @throws Exception */ public function checkValidity(): array {} /** * @return bool * @throws Exception */ public function isSimple(): bool {} /** * @return bool * @throws Exception */ public function isRing(): bool {} /** * @return bool * @throws Exception */ public function hasZ(): bool {} /** * @return bool * @throws Exception */ public function isClosed(): bool {} /** * @return string * @throws Exception */ public function typeName(): string {} /** * @return int * @throws Exception */ public function typeId(): int {} /** * @return int */ public function getSRID(): int {} /** * @param int $srid * @throws Exception */ public function setSRID(int $srid): void {} /** * @return int * @throws Exception */ public function numGeometries(): int {} /** * @param int $n * @return GEOSGeometry * @throws Exception */ public function geometryN(int $n): GEOSGeometry {} /** * @return int * @throws Exception */ public function numInteriorRings(): int {} /** * @return int * @throws Exception */ public function numPoints(): int {} /** * @return float * @throws Exception */ public function getX(): float {} /** * @return float * @throws Exception */ public function getY(): float {} /** * @param int $n * @return GEOSGeometry * @throws Exception */ public function interiorRingN(int $n): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function exteriorRing(): GEOSGeometry {} /** * @return int * @throws Exception */ public function numCoordinates(): int {} /** * @return int * @throws Exception */ public function dimension(): int {} /** * @return int * @throws Exception */ public function coordinateDimension(): int {} /** * @param int $n * @return GEOSGeometry * @throws Exception */ public function pointN(int $n): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function startPoint(): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function endPoint(): GEOSGeometry {} /** * @return float * @throws Exception */ public function area(): float {} /** * @return float * @throws Exception */ public function length(): float {} /** * @param GEOSGeometry $geom * @return float * @throws Exception */ public function distance(GEOSGeometry $geom): float {} /** * @param GEOSGeometry $geom * @return float * @throws Exception */ public function hausdorffDistance(GEOSGeometry $geom): float {} /** * @param GEOSGeometry $geom * @param float $tolerance * @return GEOSGeometry */ public function snapTo(GEOSGeometry $geom, float $tolerance): GEOSGeometry {} /** * @return GEOSGeometry * @throws Exception */ public function node(): GEOSGeometry {} /** * @param float $tolerance Snapping tolerance to use for improved robustness * @param bool $onlyEdges if true, will return a MULTILINESTRING, * otherwise (the default) it will return a GEOMETRYCOLLECTION containing triangular POLYGONs. * @return GEOSGeometry * @throws Exception */ public function delaunayTriangulation(float $tolerance = 0.0, bool $onlyEdges = false): GEOSGeometry {} /** * @param float $tolerance Snapping tolerance to use for improved robustness * @param bool $onlyEdges If true will return a MULTILINESTRING, * otherwise (the default) it will return a GEOMETRYCOLLECTION containing POLYGONs. * @param GEOSGeometry|null $extent Clip returned diagram by the extent of the given geometry * @return GEOSGeometry * @throws Exception */ public function voronoiDiagram(float $tolerance = 0.0, bool $onlyEdges = false, GEOSGeometry $extent = null): GEOSGeometry {} /** * @param float $xmin * @param float $ymin * @param float $xmax * @param float $ymax * @return GEOSGeometry * @throws Exception */ public function clipByRect(float $xmin, float $ymin, float $xmax, float $ymax): GEOSGeometry {} } /** * Class GEOSWKBWriter * @see https://github.com/libgeos/php-geos/blob/master/tests/004_WKBWriter.phpt */ class GEOSWKBWriter { /** * GEOSWKBWriter constructor. */ public function __construct() {} /** * @return int */ public function getOutputDimension(): int {} /** * @param int $dimension * @throws Exception */ public function setOutputDimension(int $dimension): void {} /** * @return int */ public function getByteOrder(): int {} /** * @param int $byteOrder * @throws Exception */ public function setByteOrder(int $byteOrder): void {} /** * @return int */ public function getIncludeSRID(): int {} /** * @param int $srid * @throws Exception */ public function setIncludeSRID(int $srid): void {} /** * @param GEOSGeometry $geom * @return string * @throws Exception */ public function write(GEOSGeometry $geom): string {} /** * @param GEOSGeometry $geom * @return string * @throws Exception */ public function writeHEX(GEOSGeometry $geom): string {} } /** * Class GEOSWKBReader * @see https://github.com/libgeos/php-geos/blob/master/tests/005_WKBReader.phpt */ class GEOSWKBReader { /** * GEOSWKBReader constructor. */ public function __construct() {} /** * @param string $wkb * @return GEOSGeometry * @throws Exception */ public function read(string $wkb): GEOSGeometry {} /** * @param string $wkb * @return GEOSGeometry * @throws Exception */ public function readHEX(string $wkb): GEOSGeometry {} } * Construct a new Judy object. A Judy object can be accessed like a PHP Array. * @link https://php.net/manual/en/judy.construct.php * @param int $judy_type

The Judy type to be used.

*/ public function __construct($judy_type) {} /** * (PECL judy >= 0.1.1)
* Destruct a Judy object. * @link https://php.net/manual/en/judy.destruct.php */ public function __destruct() {} /** * (PECL judy >= 0.1.1)
* Locate the Nth index present in the Judy array. * @link https://php.net/manual/en/judy.bycount.php * @param int $nth_index

Nth index to return. If nth_index equal 1, then it will return the first index in the array.

* @return int

Return the index at the given Nth position.

*/ public function byCount($nth_index) {} /** * (PECL judy >= 0.1.1)
* Count the number of elements in the Judy array. * @link https://php.net/manual/en/judy.count.php * @param int $index_start [optional]

Start counting from the given index. Default is first index.

* @param int $index_end [optional]

Stop counting when reaching this index. Default is last index.

* @return int

Return the number of elements.

*/ public function count($index_start = 0, $index_end = -1) {} /** * (PECL judy >= 0.1.1)
* Search (inclusive) for the first index present that is equal to or greater than the passed Index. * @link https://php.net/manual/en/judy.first.php * @param mixed $index [optional]

The index can be an integer or a string corresponding to the index where to start the search.

* @return mixed

Return the corresponding index in the array.

*/ public function first($index = 0) {} /** * (PECL judy >= 0.1.1)
* Search (inclusive) for the first absent index that is equal to or greater than the passed Index. * @link https://php.net/manual/en/judy.firstempty.php * @param mixed $index [optional]

The index can be an integer or a string corresponding to the index where to start the search.

* @return mixed

Return the corresponding index in the array.

*/ public function firstEmpty($index = 0) {} /** * (PECL judy >= 0.1.1)
* Free the entire Judy array. * @link https://php.net/manual/en/judy.free.php */ public function free() {} /** * (PECL judy >= 0.1.1)
* Return an integer corresponding to the Judy type of the current object. * @link https://php.net/manual/en/judy.gettype.php * @return int

Return an integer corresponding to a Judy type.

*/ public function getType() {} /** * (PECL judy >= 0.1.1)
* Search (inclusive) for the last index present that is equal to or less than the passed Index. * @link https://php.net/manual/en/judy.last.php * @param int|string $index [optional]

The index can be an integer or a string corresponding to the index where to start the search.

* @return mixed

Return the corresponding index in the array.

*/ public function last($index = -1) {} /** * (PECL judy >= 0.1.1)
* Search (inclusive) for the last absent index that is equal to or less than the passed Index. * @link https://php.net/manual/en/judy.lastempty.php * @param int|string $index [optional]

The index can be an integer or a string corresponding to the index where to start the search.

* @return mixed

Return the corresponding index in the array.

*/ public function lastEmpty($index = -1) {} /** * (PECL judy >= 0.1.1)
* Return the memory used by the Judy array. * @link https://php.net/manual/en/judy.memoryusage.php * @return int

Return the memory used in bytes.

*/ public function memoryUsage() {} /** * (PECL judy >= 0.1.1)
* Search (exclusive) for the next index present that is greater than the passed Index. * @link https://php.net/manual/en/judy.next.php * @param mixed $index

The index can be an integer or a string corresponding to the index where to start the search.

* @return mixed

Return the corresponding index in the array.

*/ public function next($index) {} /** * (PECL judy >= 0.1.1)
* Search (exclusive) for the next absent index that is greater than the passed Index. * @link https://php.net/manual/en/judy.nextempty.php * @param int|string $index

The index can be an integer or a string corresponding to the index where to start the search.

* @return mixed

Return the corresponding index in the array.

*/ public function nextEmpty($index) {} /** * (PECL judy >= 0.1.1)
* Whether or not an offset exists. * @link https://php.net/manual/en/judy.offsetexists.php * @param mixed $offset

An offset to check for.

* @return bool

Returns TRUE on success or FALSE on failure.

*/ public function offsetExists($offset) {} /** * (PECL judy >= 0.1.1)
* Returns the value at specified offset. * @link https://php.net/manual/en/judy.offsetget.php * @param mixed $offset

An offset to check for.

* @return mixed

Can return all value types.

*/ public function offsetGet($offset) {} /** * (PECL judy >= 0.1.1)
* Assigns a value to the specified offset. * @link https://php.net/manual/en/judy.offsetset.php * @param mixed $offset

The offset to assign the value to.

* @param mixed $value

The value to set.

*/ public function offsetSet($offset, $value) {} /** * (PECL judy >= 0.1.1)
* Unsets an offset. * @link https://php.net/manual/en/judy.offsetunset.php * @param mixed $offset

The offset to assign the value to.

*/ public function offsetUnset($offset) {} /** * (PECL judy >= 0.1.1)
* Search (exclusive) for the previous index present that is less than the passed Index. * @link https://php.net/manual/en/judy.prev.php * @param mixed $index

The index can be an integer or a string corresponding to the index where to start the search.

* @return mixed

Return the corresponding index in the array.

*/ public function prev($index) {} /** * (PECL judy >= 0.1.1)
* Search (exclusive) for the previous index absent that is less than the passed Index. * @link https://php.net/manual/en/judy.prevempty.php * @param mixed $index

The index can be an integer or a string corresponding to the index where to start the search.

* @return mixed

Return the corresponding index in the array.

*/ public function prevEmpty($index) {} /** * (PECL judy >= 0.1.1)
* Count the number of elements in the Judy array.
* This method is an alias of const count. * @link https://php.net/manual/en/judy.size.php * @param int $index_start [optional]

Start counting from the given index. Default is first index.

* @param int $index_end [optional]

Stop counting when reaching this index. Default is last index.

* @return int

Return the number of elements.

*/ public function size($index_start = 0, $index_end = -1) {} } // End of judy. * An optional seed value *

* @param int $mode [optional]

* Use one of the following constants to specify the implementation of the algorithm to use. *

* @return void */ function mt_srand( #[LanguageLevelTypeAware(['8.3' => 'int|null'], default: 'int')] $seed = null, #[PhpStormStubsElementAvailable(from: '7.1')] int $mode = MT_RAND_MT19937 ): void {} /** * Seed the random number generator *

Note: As of PHP 7.1.0, {@see srand()} has been made * an alias of {@see mt_srand()}. *

* @link https://php.net/manual/en/function.srand.php * @param int|null $seed

* Optional seed value *

* @param int $mode [optional]

* Use one of the following constants to specify the implementation of the algorithm to use. *

* @return void */ function srand( #[LanguageLevelTypeAware(['8.3' => 'int|null'], default: 'int')] $seed = null, #[PhpStormStubsElementAvailable(from: '7.1')] int $mode = MT_RAND_MT19937 ): void {} /** * Generate a random integer * @link https://php.net/manual/en/function.rand.php * @param int $min [optional] * @param int $max [optional] * @return int A pseudo random value between min * (or 0) and max (or getrandmax, inclusive). */ function rand(int $min, int $max): int {} /** * Generate a random value via the Mersenne Twister Random Number Generator * @link https://php.net/manual/en/function.mt-rand.php * @param int $min [optional]

* Optional lowest value to be returned (default: 0) *

* @param int $max [optional]

* Optional highest value to be returned (default: mt_getrandmax()) *

* @return int A random integer value between min (or 0) * and max (or mt_getrandmax, inclusive) */ function mt_rand(int $min, int $max): int {} /** * Show largest possible random value * @link https://php.net/manual/en/function.mt-getrandmax.php * @return int the maximum random value returned by mt_rand */ #[Pure] function mt_getrandmax(): int {} /** * Show largest possible random value * @link https://php.net/manual/en/function.getrandmax.php * @return int The largest possible random value returned by rand */ #[Pure] function getrandmax(): int {} /** * Generates cryptographically secure pseudo-random bytes * @link https://php.net/manual/en/function.random-bytes.php * @param int $length The length of the random string that should be returned in bytes. * @return string Returns a string containing the requested number of cryptographically secure random bytes. * @since 7.0 * @throws Random\RandomException if an appropriate source of randomness cannot be found. */ function random_bytes(int $length): string {} /** * Generates cryptographically secure pseudo-random integers * @link https://php.net/manual/en/function.random-int.php * @param int $min The lowest value to be returned, which must be PHP_INT_MIN or higher. * @param int $max The highest value to be returned, which must be less than or equal to PHP_INT_MAX. * @return int Returns a cryptographically secure random integer in the range min to max, inclusive. * @since 7.0 * @throws Random\RandomException if an appropriate source of randomness cannot be found. */ function random_int(int $min, int $max): int {} } namespace Random\Engine { /** * @since 8.2 */ final class Mt19937 implements \Random\Engine { public function __construct(int|null $seed = null, int $mode = MT_RAND_MT19937) {} public function generate(): string {} public function __serialize(): array {} public function __unserialize(array $data): void {} public function __debugInfo(): array {} } /** * @since 8.2 */ final class PcgOneseq128XslRr64 implements \Random\Engine { public function __construct(string|int|null $seed = null) {} public function generate(): string {} public function jump(int $advance): void {} public function __serialize(): array {} public function __unserialize(array $data): void {} public function __debugInfo(): array {} } /** * @since 8.2 */ final class Xoshiro256StarStar implements \Random\Engine { public function __construct(string|int|null $seed = null) {} public function generate(): string {} public function jump(): void {} public function jumpLong(): void {} public function __serialize(): array {} public function __unserialize(array $data): void {} public function __debugInfo(): array {} } /** * @since 8.2 */ final class Secure implements \Random\CryptoSafeEngine { public function generate(): string {} } } namespace Random { use Error; use Exception; /** * @since 8.2 */ interface Engine { public function generate(): string; } /** * @since 8.2 */ interface CryptoSafeEngine extends Engine {} /** * @since 8.2 */ final class Randomizer { public readonly Engine $engine; public function __construct(?Engine $engine = null) {} public function nextInt(): int {} public function getInt(int $min, int $max): int {} public function getBytes(int $length): string {} public function shuffleArray(array $array): array {} public function shuffleBytes(string $bytes): string {} public function pickArrayKeys(array $array, int $num): array {} public function __serialize(): array {} public function __unserialize(array $data): void {} /** * @since 8.3 */ public function nextFloat(): float {} /** * @since 8.3 */ public function getFloat(float $min, float $max, IntervalBoundary $boundary = IntervalBoundary::ClosedOpen): float {} /** * @since 8.3 */ public function getBytesFromString(string $string, int $length): string {} } /** * @since 8.2 */ class RandomError extends Error {} /** * @since 8.2 */ class BrokenRandomEngineError extends RandomError {} /** * @since 8.2 */ class RandomException extends Exception {} /** * @since 8.3 */ enum IntervalBoundary implements \UnitEnum { public string $name; case ClosedOpen; case ClosedClosed; case OpenClosed; case OpenOpen; public static function cases(): array {} } } 'localhost', * 'port' => 6379, * 'readTimeout' => 2.5, * 'connectTimeout' => 2.5, * 'persistent' => true, * // Valid formats: NULL, ['user', 'pass'], 'pass', or ['pass'] * 'auth' => ['phpredis', 'phpredis'], * // See PHP stream options for valid SSL configuration settings. * 'ssl' => ['verify_peer' => false], * // How quickly to retry a connection after we time out or it closes. * // Note that this setting is overridden by 'backoff' strategies. * 'retryInterval' => 100, * // Which backoff algorithm to use. 'decorrelated jitter' is * // likely the best one for most solution, but there are many * // to choose from: * // REDIS_BACKOFF_ALGORITHM_DEFAULT * // REDIS_BACKOFF_ALGORITHM_CONSTANT * // REDIS_BACKOFF_ALGORITHM_UNIFORM * // REDIS_BACKOFF_ALGORITHM_EXPONENTIAL * // REDIS_BACKOFF_ALGORITHM_FULL_JITTER * // REDIS_BACKOFF_ALGORITHM_EQUAL_JITTER * // REDIS_BACKOFF_ALGORITHM_DECORRELATED_JITTER * // 'base', and 'cap' are in milliseconds and represent the first * // delay redis will use when reconnecting, and the maximum delay * // we will reach while retrying. * 'backoff' => [ * 'algorithm' => Redis::BACKOFF_ALGORITHM_DECORRELATED_JITTER, * 'base' => 500, * 'cap' => 750, * ] * ]; * Note: If you do wish to connect via the constructor, only 'host' is * strictly required, which will cause PhpRedis to connect to that * host on Redis' default port (6379). * @param array|null $options * @see https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ * @see Redis::connect() */ public function __construct(?array $options = null) {} public function __destruct() {} /** * Compress a value with the currently configured compressor as set with * Redis::setOption(). * @param string $value The value to be compressed * @return string The compressed result * @see Redis::setOption() */ public function _compress(string $value): string {} /** * Uncompress the provided argument that has been compressed with the * currently configured compressor as set with Redis::setOption(). * @param string $value The compressed value to uncompress. * @return string The uncompressed result. * @see Redis::setOption() */ public function _uncompress(string $value): string {} /** * Prefix the passed argument with the currently set key prefix as set * with Redis::setOption(). * @param string $key The key/string to prefix * @return string The prefixed string */ public function _prefix(string $key): string {} /** * Serialize the provided value with the currently set serializer as set * with Redis::setOption(). * @param mixed $value The value to serialize * @return string The serialized result * @see Redis::setOption() */ public function _serialize(mixed $value): string {} /** * Unserialize the passed argument with the currently set serializer as set * with Redis::setOption(). * @param string $value The value to unserialize * @return mixed The unserialized result * @see Redis::setOption() */ public function _unserialize(string $value): mixed {} /** * Pack the provided value with the configured serializer and compressor * as set with Redis::setOption(). * @param mixed $value The value to pack * @return string The packed result having been serialized and * compressed. */ public function _pack(mixed $value): string {} /** * Unpack the provided value with the configured compressor and serializer * as set with Redis::setOption(). * @param string $value The value which has been serialized and compressed. * @return mixed The uncompressed and eserialized value. */ public function _unpack(string $value): mixed {} public function acl(string $subcmd, string ...$args): mixed {} /** * Append data to a Redis STRING key. * @param string $key The key in question * @param mixed $value The data to append to the key. * @return Redis|int|false The new string length of the key or false on failure. * @see https://redis.io/commands/append * @example * $redis->set('foo', 'hello); * $redis->append('foo', 'world'); */ public function append(string $key, mixed $value): Redis|int|false {} /** * Authenticate a Redis connection after its been established. * $redis->auth('password'); * $redis->auth(['password']); * $redis->auth(['username', 'password']); * @see https://redis.io/commands/auth * @param mixed $credentials A string password, or an array with one or two string elements. * @return Redis|bool Whether the AUTH was successful. */ public function auth(#[\SensitiveParameter] mixed $credentials): Redis|bool {} /** * Execute a save of the Redis database in the background. * @see https://redis.io/commands/bgsave * @return Redis|bool Whether the command was successful. */ public function bgSave(): Redis|bool {} /** * Asynchronously rewrite Redis' append-only file * @see https://redis.io/commands/bgrewriteaof * @return Redis|bool Whether the command was successful. */ public function bgrewriteaof(): Redis|bool {} /** * Count the number of set bits in a Redis string. * @see https://redis.io/commands/bitcount/ * @param string $key The key in question (must be a string key) * @param int $start The index where Redis should start counting. If omitted it * defaults to zero, which means the start of the string. * @param int $end The index where Redis should stop counting. If omitted it * defaults to -1, meaning the very end of the string. * @param bool $bybit Whether or not Redis should treat $start and $end as bit * positions, rather than bytes. * @return Redis|int|false The number of bits set in the requested range. */ public function bitcount(string $key, int $start = 0, int $end = -1, bool $bybit = false): Redis|int|false {} public function bitop(string $operation, string $deskey, string $srckey, string ...$other_keys): Redis|int|false {} /** * Return the position of the first bit set to 0 or 1 in a string. * @see https://redis.io/commands/bitpos/ * @param string $key The key to check (must be a string) * @param bool $bit Whether to look for an unset (0) or set (1) bit. * @param int $start Where in the string to start looking. * @param int $end Where in the string to stop looking. * @param bool $bybit If true, Redis will treat $start and $end as BIT values and not bytes, so if start * was 0 and end was 2, Redis would only search the first two bits. * @return Redis|int|false The position of the first set or unset bit. **/ public function bitpos(string $key, bool $bit, int $start = 0, int $end = -1, bool $bybit = false): Redis|int|false {} /** * Pop an element off the beginning of a Redis list or lists, potentially blocking up to a specified * timeout. This method may be called in two distinct ways, of which examples are provided below. * @see https://redis.io/commands/blpop/ * @param string|array $key_or_keys This can either be a string key or an array of one or more * keys. * @param string|float|int $timeout_or_key If the previous argument was a string key, this can either * be an additional key, or the timeout you wish to send to * the command. * @return Redis|array|null|false Can return various things depending on command and data in Redis. * @example * $redis->blPop('list1', 'list2', 'list3', 1.5); * $relay->blPop(['list1', 'list2', 'list3'], 1.5); */ public function blPop(string|array $key_or_keys, string|float|int $timeout_or_key, mixed ...$extra_args): Redis|array|null|false {} /** * Pop an element off of the end of a Redis list or lists, potentially blocking up to a specified timeout. * The calling convention is identical to Redis::blPop() so see that documentation for more details. * @see https://redis.io/commands/brpop/ * @see Redis::blPop() */ public function brPop(string|array $key_or_keys, string|float|int $timeout_or_key, mixed ...$extra_args): Redis|array|null|false {} /** * Pop an element from the end of a Redis list, pushing it to the beginning of another Redis list, * optionally blocking up to a specified timeout. * @see https://redis.io/commands/brpoplpush/ * @param string $src The source list * @param string $dst The destination list * @param int|float $timeout The number of seconds to wait. Note that you must be connected * to Redis >= 6.0.0 to send a floating point timeout. */ public function brpoplpush(string $src, string $dst, int|float $timeout): Redis|string|false {} /** * POP the maximum scoring element off of one or more sorted sets, blocking up to a specified * timeout if no elements are available. * Following are examples of the two main ways to call this method. * **NOTE**: We reccomend calling this function with an array and a timeout as the other strategy * may be deprecated in future versions of PhpRedis * @see https://redis.io/commands/bzpopmax * @param string|array $key Either a string key or an array of one or more keys. * @param string|int $timeout_or_key If the previous argument was an array, this argument * must be a timeout value. Otherwise it could also be * another key. * @param mixed $extra_args Can consist of additional keys, until the last argument * which needs to be a timeout. * @return Redis|array|false The popped elements. * @example * $redis->bzPopMax('key1', 'key2', 'key3', 1.5); * $redis->bzPopMax(['key1', 'key2', 'key3'], 1.5); */ public function bzPopMax(string|array $key, string|int $timeout_or_key, mixed ...$extra_args): Redis|array|false {} /** * POP the minimum scoring element off of one or more sorted sets, blocking up to a specified timeout * if no elements are available * This command is identical in semantics to bzPopMax so please see that method for more information. * @see https://redis.io/commands/bzpopmin * @see Redis::bzPopMax() */ public function bzPopMin(string|array $key, string|int $timeout_or_key, mixed ...$extra_args): Redis|array|false {} /** * POP one or more elements from one or more sorted sets, blocking up to a specified amount of time * when no elements are available. * @param float $timeout How long to block if there are no element available * @param array $keys The sorted sets to pop from * @param string $from The string 'MIN' or 'MAX' (case insensitive) telling Redis whether you wish to * pop the lowest or highest scoring members from the set(s). * @param int $count Pop up to how many elements. * @return Redis|array|null|false This function will return an array of popped elements, or false * depending on whether any elements could be popped within the * specified timeout. * NOTE: If Redis::OPT_NULL_MULTIBULK_AS_NULL is set to true via Redis::setOption(), this method will * instead return NULL when Redis doesn't pop any elements. */ public function bzmpop(float $timeout, array $keys, string $from, int $count = 1): Redis|array|null|false {} /** * POP one or more of the highest or lowest scoring elements from one or more sorted sets. * @see https://redis.io/commands/zmpop * @param array $keys One or more sorted sets * @param string $from The string 'MIN' or 'MAX' (case insensitive) telling Redis whether you want to * pop the lowest or highest scoring elements. * @param int $count Pop up to how many elements at once. * @return Redis|array|null|false An array of popped elements or false if none could be popped. */ public function zmpop(array $keys, string $from, int $count = 1): Redis|array|null|false {} /** * Pop one or more elements from one or more Redis LISTs, blocking up to a specified timeout when * no elements are available. * @see https://redis.io/commands/blmpop * @param float $timeout The number of seconds Redis will block when no elements are available. * @param array $keys One or more Redis LISTs to pop from. * @param string $from The string 'LEFT' or 'RIGHT' (case insensitive), telling Redis whether * to pop elements from the beginning or end of the LISTs. * @param int $count Pop up to how many elements at once. * @return Redis|array|null|false One or more elements popped from the list(s) or false if all LISTs * were empty. */ public function blmpop(float $timeout, array $keys, string $from, int $count = 1): Redis|array|null|false {} /** * Pop one or more elements off of one or more Redis LISTs. * @see https://redis.io/commands/lmpop * @param array $keys An array with one or more Redis LIST key names. * @param string $from The string 'LEFT' or 'RIGHT' (case insensitive), telling Redis whether to pop\ * elements from the beginning or end of the LISTs. * @param int $count The maximum number of elements to pop at once. * @return Redis|array|null|false One or more elements popped from the LIST(s) or false if all the LISTs * were empty. */ public function lmpop(array $keys, string $from, int $count = 1): Redis|array|null|false {} /** * Reset any last error on the connection to NULL * @return bool This should always return true or throw an exception if we're not connected. * @see Redis::getLastError() * @example * $redis = new Redis(['host' => 'localhost']); * $redis->set('string', 'this_is_a_string'); * $redis->smembers('string'); * var_dump($redis->getLastError()); * $redis->clearLastError(); * var_dump($redis->getLastError()); */ public function clearLastError(): bool {} public function client(string $opt, mixed ...$args): mixed {} public function close(): bool {} public function command(?string $opt = null, mixed ...$args): mixed {} /** * Execute the Redis CONFIG command in a variety of ways. * What the command does in particular depends on the `$operation` qualifier. * Operations that PhpRedis supports are: RESETSTAT, REWRITE, GET, and SET. * @param string $operation The CONFIG operation to execute (e.g. GET, SET, REWRITE). * @param array|string|null $key_or_settings One or more keys or values. * @param string|null $value The value if this is a `CONFIG SET` operation. * @return mixed * @see https://redis.io/commands/config * @example * $redis->config('GET', 'timeout'); * $redis->config('GET', ['timeout', 'databases']); * $redis->config('SET', 'timeout', 30); * $redis->config('SET', ['timeout' => 30, 'loglevel' => 'warning']); */ public function config(string $operation, array|string|null $key_or_settings = null, ?string $value = null): mixed {} public function connect( string $host, int $port = 6379, float $timeout = 0, ?string $persistent_id = null, int $retry_interval = 0, float $read_timeout = 0, ?array $context = null ): bool {} /** * Make a copy of a key. * $redis = new Redis(['host' => 'localhost']); * @param string $src The key to copy * @param string $dst The name of the new key created from the source key. * @param array|null $options An array with modifiers on how COPY should operate. * * $options = [ * 'REPLACE' => true|false # Whether to replace an existing key. * 'DB' => int # Copy key to specific db. * ]; * * @return Redis|bool True if the copy was completed and false if not. * @see https://redis.io/commands/copy * @example * $redis->pipeline() * ->select(1) * ->del('newkey') * ->select(0) * ->del('newkey') * ->mset(['source1' => 'value1', 'exists' => 'old_value']) * ->exec(); * var_dump($redis->copy('source1', 'newkey')); * var_dump($redis->copy('source1', 'newkey', ['db' => 1])); * var_dump($redis->copy('source1', 'exists')); * var_dump($redis->copy('source1', 'exists', ['REPLACE' => true])); */ public function copy(string $src, string $dst, ?array $options = null): Redis|bool {} /** * Return the number of keys in the currently selected Redis database. * @see https://redis.io/commands/dbsize * @return Redis|int|false The number of keys or false on failure. * @example * $redis = new Redis(['host' => 'localhost']); * $redis->flushdb(); * $redis->set('foo', 'bar'); * var_dump($redis->dbsize()); * $redis->mset(['a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd']); * var_dump($redis->dbsize()); */ public function dbSize(): Redis|int|false {} public function debug(string $key): Redis|string {} /** * Decrement a Redis integer by 1 or a provided value. * @param string $key The key to decrement * @param int $by How much to decrement the key. Note that if this value is * not sent or is set to `1`, PhpRedis will actually invoke * the 'DECR' command. If it is any value other than `1` * PhpRedis will actually send the `DECRBY` command. * @return Redis|int|false The new value of the key or false on failure. * @see https://redis.io/commands/decr * @see https://redis.io/commands/decrby * @example $redis->decr('counter'); * @example $redis->decr('counter', 2); */ public function decr(string $key, int $by = 1): Redis|int|false {} /** * Decrement a redis integer by a value * @param string $key The integer key to decrement. * @param int $value How much to decrement the key. * @return Redis|int|false The new value of the key or false on failure. * @see https://redis.io/commands/decrby * @example $redis->decrby('counter', 1); * @example $redis->decrby('counter', 2); */ public function decrBy(string $key, int $value): Redis|int|false {} /** * Delete one or more keys from Redis. * This method can be called in two distinct ways. The first is to pass a single array * of keys to delete, and the second is to pass N arguments, all names of keys. See * below for an example of both strategies. * @param array|string $key Either an array with one or more key names or a string with * the name of a key. * @param string ...$other_keys One or more additional keys passed in a variadic fashion. * @return Redis|int|false The number of keys that were deleted * @see https://redis.io/commands/del * @example $redis->del('key:0', 'key:1'); * @example $redis->del(['key:2', 'key:3', 'key:4']); */ public function del(array|string $key, string ...$other_keys): Redis|int|false {} /** * @deprecated */ public function delete(array|string $key, string ...$other_keys): Redis|int|false {} /** * Discard a transaction currently in progress. * @return Redis|bool True if we could discard the transaction. * @example * $redis->getMode(); * $redis->set('foo', 'bar'); * $redis->discard(); * $redis->getMode(); */ public function discard(): Redis|bool {} /** * Dump Redis' internal binary representation of a key. * $redis->zRange('new-zset', 0, -1, true); * * @param string $key The key to dump. * @return Redis|string A binary string representing the key's value. * @see https://redis.io/commands/dump * @example * $redis->zadd('zset', 0, 'zero', 1, 'one', 2, 'two'); * $binary = $redis->dump('zset'); * $redis->restore('new-zset', 0, $binary); */ public function dump(string $key): Redis|string {} /** * Have Redis repeat back an arbitrary string to the client. * @param string $str The string to echo * @return Redis|string|false The string sent to Redis or false on failure. * @see https://redis.io/commands/echo * @example $redis->echo('Hello, World'); */ public function echo(string $str): Redis|string|false {} /** * Execute a LUA script on the redis server. * @see https://redis.io/commands/eval/ * @param string $script A string containing the LUA script * @param array $args An array of arguments to pass to this script * @param int $num_keys How many of the arguments are keys. This is needed * as redis distinguishes between key name arguments * and other data. * @return mixed LUA scripts may return arbitrary data so this method can return * strings, arrays, nested arrays, etc. */ public function eval(string $script, array $args = [], int $num_keys = 0): mixed {} /** * This is simply the read-only variant of eval, meaning the underlying script * may not modify data in redis. * @see Redis::eval_ro() */ public function eval_ro(string $script_sha, array $args = [], int $num_keys = 0): mixed {} /** * Execute a LUA script on the server but instead of sending the script, send * the SHA1 hash of the script. * @param string $sha1 The SHA1 hash of the lua code. Note that the script * must already exist on the server, either having been * loaded with `SCRIPT LOAD` or having been executed directly * with `EVAL` first. * @param array $args Arguments to send to the script. * @param int $num_keys The number of arguments that are keys * @return mixed Returns whatever the specific script does. * @see https://redis.io/commands/evalsha/ * @see Redis::eval(); */ public function evalsha(string $sha1, array $args = [], int $num_keys = 0): mixed {} /** * This is simply the read-only variant of evalsha, meaning the underlying script * may not modify data in redis. * @see Redis::evalsha() */ public function evalsha_ro(string $sha1, array $args = [], int $num_keys = 0): mixed {} /** * Execute either a MULTI or PIPELINE block and return the array of replies. * @return Redis|array|false The array of pipeline'd or multi replies or false on failure. * @see https://redis.io/commands/exec * @see https://redis.io/commands/multi * @see Redis::pipeline() * @see Redis::multi() * @example * $res = $redis->multi() * ->set('foo', 'bar') * ->get('foo') * ->del('list') * ->rpush('list', 'one', 'two', 'three') * ->exec(); */ public function exec(): Redis|array|false {} /** * Test if one or more keys exist. * @param mixed $key Either an array of keys or a string key * @param mixed $other_keys If the previous argument was a string, you may send any number of * additional keys to test. * @return Redis|int|bool The number of keys that do exist and false on failure * @see https://redis.io/commands/exists * @example $redis->exists(['k1', 'k2', 'k3']); * @example $redis->exists('k4', 'k5', 'notakey'); */ public function exists(mixed $key, mixed ...$other_keys): Redis|int|bool {} /** * Sets an expiration in seconds on the key in question. If connected to * redis-server >= 7.0.0 you may send an additional "mode" argument which * modifies how the command will execute. * @param string $key The key to set an expiration on. * @param int $timeout The number of seconds after which key will be automatically deleted. * @param string|null $mode A two character modifier that changes how the * command works. * * NX - Set expiry only if key has no expiry * XX - Set expiry only if key has an expiry * LT - Set expiry only when new expiry is < current expiry * GT - Set expiry only when new expiry is > current expiry * * @return Redis|bool True if an expiration was set and false otherwise. * @see https://redis.io/commands/expire */ public function expire(string $key, int $timeout, ?string $mode = null): Redis|bool {} /* * Set a key's expiration to a specific Unix timestamp in seconds. * * If connected to Redis >= 7.0.0 you can pass an optional 'mode' argument. * @see Redis::expire() For a description of the mode argument. * * @param string $key The key to set an expiration on. * * @return Redis|bool True if an expiration was set, false if not. * */ /** * Set a key to expire at an exact unix timestamp. * @param string $key The key to set an expiration on. * @param int $timestamp The unix timestamp to expire at. * @param string|null $mode An option 'mode' that modifies how the command acts (see {@link Redis::expire}). * @return Redis|bool True if an expiration was set, false if not. * @see https://redis.io/commands/expireat * @see https://redis.io/commands/expire * @see Redis::expire() */ public function expireAt(string $key, int $timestamp, ?string $mode = null): Redis|bool {} public function failover(?array $to = null, bool $abort = false, int $timeout = 0): Redis|bool {} /** * Get the expiration of a given key as a unix timestamp * @param string $key The key to check. * @return Redis|int|false The timestamp when the key expires, or -1 if the key has no expiry * and -2 if the key doesn't exist. * @see https://redis.io/commands/expiretime * @example * $redis->setEx('mykey', 60, 'myval'); * $redis->expiretime('mykey'); */ public function expiretime(string $key): Redis|int|false {} /** * Get the expriation timestamp of a given Redis key but in milliseconds. * @see https://redis.io/commands/pexpiretime * @see Redis::expiretime() * @param string $key The key to check * @return Redis|int|false The expiration timestamp of this key (in milliseconds) or -1 if the * key has no expiration, and -2 if it does not exist. */ public function pexpiretime(string $key): Redis|int|false {} /** * Invoke a function. * @param string $fn The name of the function * @param array $keys Optional list of keys * @param array $args Optional list of args * @return mixed Function may return arbitrary data so this method can return * strings, arrays, nested arrays, etc. * @see https://redis.io/commands/fcall */ public function fcall(string $fn, array $keys = [], array $args = []): mixed {} /** * This is a read-only variant of the FCALL command that cannot execute commands that modify data. * @param string $fn The name of the function * @param array $keys Optional list of keys * @param array $args Optional list of args * @return mixed Function may return arbitrary data so this method can return * strings, arrays, nested arrays, etc. * @see https://redis.io/commands/fcall_ro */ public function fcall_ro(string $fn, array $keys = [], array $args = []): mixed {} /** * Deletes every key in all Redis databases * @param bool $sync Whether to perform the task in a blocking or non-blocking way. * @return Redis|bool * @see https://redis.io/commands/flushall */ public function flushAll(?bool $sync = null): Redis|bool {} /** * Deletes all the keys of the currently selected database. * @param bool $sync Whether to perform the task in a blocking or non-blocking way. * @return Redis|bool * @see https://redis.io/commands/flushdb */ public function flushDB(?bool $sync = null): Redis|bool {} /** * Functions is an API for managing code to be executed on the server. * @param string $operation The subcommand you intend to execute. Valid options are as follows * 'LOAD' - Create a new library with the given library name and code. * 'DELETE' - Delete the given library. * 'LIST' - Return general information on all the libraries * 'STATS' - Return information about the current function running * 'KILL' - Kill the current running function * 'FLUSH' - Delete all the libraries * 'DUMP' - Return a serialized payload representing the current libraries * 'RESTORE' - Restore the libraries represented by the given payload * @param mixed ...$args Additional arguments * @return Redis|bool|string|array Depends on subcommand. * @see https://redis.io/commands/function */ public function function(string $operation, mixed ...$args): Redis|bool|string|array {} /** * Add one or more members to a geospacial sorted set * @param string $key The sorted set to add data to. * @param float $lng The longitude of the first member * @param float $lat The lattitude of the first member. * @param mixed ...$other_triples_and_options You can continue to pass longitude, lattitude, and member * arguments to add as many members as you wish. Optionally, the final argument may be * a string with options for the command @return Redis|int|false The number of added elements is returned. If the 'CH' option is specified, * the return value is the number of members *changed*. * @see Redis documentation for the options. * @example $redis->geoAdd('cities', -121.8374, 39.7284, 'Chico', -122.03218, 37.322, 'Cupertino'); * @example $redis->geoadd('cities', -121.837478, 39.728494, 'Chico', ['XX', 'CH']); * @see https://redis.io/commands/geoadd */ public function geoadd(string $key, float $lng, float $lat, string $member, mixed ...$other_triples_and_options): Redis|int|false {} /** * Get the distance between two members of a geospacially encoded sorted set. * @param string $key The Sorted set to query. * @param string $src The first member. * @param string $dst The second member. * @param string|null $unit Which unit to use when computing distance, defaulting to meters. * * M - meters * KM - kilometers * FT - feet * MI - miles * * @return Redis|float|false The calculated distance in whichever units were specified or false * if one or both members did not exist. * @example $redis->geodist('cities', 'Chico', 'Cupertino', 'mi'); * @see https://redis.io/commands/geodist */ public function geodist(string $key, string $src, string $dst, ?string $unit = null): Redis|float|false {} /** * Retrieve one or more GeoHash encoded strings for members of the set. * @param string $key The key to query * @param string $member The first member to request * @param string ...$other_members One or more additional members to request. * @return Redis|array|false An array of GeoHash encoded values. * @see https://redis.io/commands/geohash * @see https://en.wikipedia.org/wiki/Geohash * @example $redis->geohash('cities', 'Chico', 'Cupertino'); */ public function geohash(string $key, string $member, string ...$other_members): Redis|array|false {} /** * Return the longitude and lattitude for one or more members of a geospacially encoded sorted set. * @param string $key The set to query. * @param string $member The first member to query. * @param string ...$other_members One or more members to query. * @return Redis|array|false array of longitude and lattitude pairs. * @see https://redis.io/commands/geopos * @example $redis->geopos('cities', 'Seattle', 'New York'); */ public function geopos(string $key, string $member, string ...$other_members): Redis|array|false {} /** * Retrieve members of a geospacially sorted set that are within a certain radius of a location. * @param string $key The set to query * @param float $lng The longitude of the location to query. * @param float $lat The latitude of the location to query. * @param float $radius The radius of the area to include. * @param string $unit The unit of the provided radius (defaults to 'meters). * See {@link Redis::geodist} for possible units. * @param array $options An array of options that modifies how the command behaves. * * $options = [ * 'WITHCOORD', # Return members and their coordinates. * 'WITHDIST', # Return members and their distances from the center. * 'WITHHASH', # Return members GeoHash string. * 'ASC' | 'DESC', # The sort order of returned members * # Limit to N returned members. Optionally a two element array may be * # passed as the `LIMIT` argument, and the `ANY` argument. * 'COUNT' => [], or [, ] * # Instead of returning members, store them in the specified key. * 'STORE' => * # Store the distances in the specified key * 'STOREDIST' => * ]; * * @return mixed This command can return various things, depending on the options passed. * @see https://redis.io/commands/georadius * @example $redis->georadius('cities', 47.608013, -122.335167, 1000, 'km'); */ public function georadius(string $key, float $lng, float $lat, float $radius, string $unit, array $options = []): mixed {} /** * A readonly variant of `GEORADIUS` that may be executed on replicas. * @see Redis::georadius */ public function georadius_ro(string $key, float $lng, float $lat, float $radius, string $unit, array $options = []): mixed {} /** * Similar to `GEORADIUS` except it uses a member as the center of the query. * @param string $key The key to query. * @param string $member The member to treat as the center of the query. * @param float $radius The radius from the member to include. * @param string $unit The unit of the provided radius * See {@link Redis::geodist} for possible units. * @param array $options An array with various options to modify the command's behavior. * See {@link Redis::georadius} for options. * @return mixed This command can return various things depending on options. * @example $redis->georadiusbymember('cities', 'Seattle', 200, 'mi'); */ public function georadiusbymember(string $key, string $member, float $radius, string $unit, array $options = []): mixed {} /** * This is the read-only variant of `GEORADIUSBYMEMBER` that can be run on replicas. */ public function georadiusbymember_ro(string $key, string $member, float $radius, string $unit, array $options = []): mixed {} /** * Search a geospacial sorted set for members in various ways. * @param string $key The set to query. * @param array|string $position Either a two element array with longitude and lattitude, or * a string representing a member of the set. * @param array|int|float $shape Either a number representine the radius of a circle to search, or * a two element array representing the width and height of a box * to search. * @param string $unit The unit of our shape. See {@link Redis::geodist} for possible units. * @param array $options @see {@link Redis::georadius} for options. Note that the `STORE` * options are not allowed for this command. */ public function geosearch(string $key, array|string $position, array|int|float $shape, string $unit, array $options = []): array {} /** * Search a geospacial sorted set for members within a given area or range, storing the results into * a new set. * @param string $dst The destination where results will be stored. * @param string $src The key to query. * @param array|string $position Either a two element array with longitude and lattitude, or * a string representing a member of the set. * @param array|int|float $shape Either a number representine the radius of a circle to search, or * a two element array representing the width and height of a box * to search. * @param string $unit The unit of our shape. See {@link Redis::geodist} for possible units. * @param array $options * * $options = [ * 'ASC' | 'DESC', # The sort order of returned members * 'WITHDIST' # Also store distances. * # Limit to N returned members. Optionally a two element array may be * # passed as the `LIMIT` argument, and the `ANY` argument. * 'COUNT' => [], or [, ] * ]; * */ public function geosearchstore(string $dst, string $src, array|string $position, array|int|float $shape, string $unit, array $options = []): Redis|array|int|false {} /** * Retrieve a string keys value. * @param string $key The key to query * @return mixed The keys value or false if it did not exist. * @see https://redis.io/commands/get * @example $redis->get('foo'); */ public function get(string $key): mixed {} /** * Get the authentication information on the connection, if any. * @return mixed The authentication information used to authenticate the connection. * @see Redis::auth() */ public function getAuth(): mixed {} /** * Get the bit at a given index in a string key. * @param string $key The key to query. * @param int $idx The Nth bit that we want to query. * @example $redis->getbit('bitmap', 1337); * @see https://redis.io/commands/getbit */ public function getBit(string $key, int $idx): Redis|int|false {} /** * Get the value of a key and optionally set it's expiration. * @param string $key The key to query * @param array $options Options to modify how the command works. * * $options = [ * 'EX' => # Expire in N seconds * 'PX' => # Expire in N milliseconds * 'EXAT' => # Expire at a unix timestamp (in seconds) * 'PXAT' => # Expire at a unix timestamp (in milliseconds); * 'PERSIST' # Remove any configured expiration on the key. * ]; * * @return Redis|string|bool The key's value or false if it didn't exist. * @see https://redis.io/comands/getex * @example $redis->getEx('mykey', ['EX' => 60]); */ public function getEx(string $key, array $options = []): Redis|string|bool {} /** * Get the database number PhpRedis thinks we're connected to. * This value is updated internally in PhpRedis each time {@link Redis::select} is called. * @return int The database we're connected to. * @see Redis::select() * @see https://redis.io/commands/select */ public function getDBNum(): int {} /** * Get a key from Redis and delete it in an atomic operation. * @param string $key The key to get/delete. * @return Redis|string|bool The value of the key or false if it didn't exist. * @see https://redis.io/commands/getdel * @example $redis->getdel('token:123'); */ public function getDel(string $key): Redis|string|bool {} /** * Return the host or Unix socket we are connected to. * @return string The host or Unix socket. */ public function getHost(): string {} /** * Get the last error returned to us from Redis, if any. * @return string|null The error string or NULL if there is none. */ public function getLastError(): ?string {} /** * Returns whether the connection is in ATOMIC, MULTI, or PIPELINE mode * @return int The mode we're in. */ public function getMode(): int {} /** * Retrieve the value of a configuration setting as set by Redis::setOption() * @return mixed The setting itself or false on failure * @see Redis::setOption() for a detailed list of options and their values. */ public function getOption(int $option): mixed {} /** * Get the persistent connection ID, if there is one. * @return string|null The ID or NULL if we don't have one. */ public function getPersistentID(): ?string {} /** * Get the port we are connected to. This number will be zero if we are connected to a unix socket. * @return int The port. */ public function getPort(): int {} /** * Retrieve a substring of a string by index. * @param string $key The string to query. * @param int $start The zero-based starting index. * @param int $end The zero-based ending index. * @return Redis|string|false The substring or false on failure. * @see https://redis.io/commands/getrange * @example * $redis->set('silly-word', 'Supercalifragilisticexpialidocious'); * echo $redis->getRange('silly-word', 0, 4) . "\n"; */ public function getRange(string $key, int $start, int $end): Redis|string|false {} /** * Get the longest common subsequence between two string keys. * @param string $key1 The first key to check * @param string $key2 The second key to check * @param array|null $options An optional array of modifiers for the comand. * * $options = [ * 'MINMATCHLEN' => int # Exclude matching substrings that are less than this value * 'WITHMATCHLEN' => bool # Whether each match should also include its length. * 'LEN' # Return the length of the longest subsequence * 'IDX' # Each returned match will include the indexes where the * # match occurs in each string. * ]; * * NOTE: 'LEN' cannot be used with 'IDX'. * @return Redis|string|array|int|false Various reply types depending on options. * @see https://redis.io/commands/lcs * @example * $redis->set('seq1', 'gtaggcccgcacggtctttaatgtatccctgtttaccatgccatacctgagcgcatacgc'); * $redis->set('seq2', 'aactcggcgcgagtaccaggccaaggtcgttccagagcaaagactcgtgccccgctgagc'); * echo $redis->lcs('seq1', 'seq2') . "\n"; */ public function lcs(string $key1, string $key2, ?array $options = null): Redis|string|array|int|false {} /** * Get the currently set read timeout on the connection. * @return float The timeout. */ public function getReadTimeout(): float {} /** * Sets a key and returns any previously set value, if the key already existed. * @param string $key The key to set. * @param mixed $value The value to set the key to. * @return Redis|string|false The old value of the key or false if it didn't exist. * @see https://redis.io/commands/getset * @example * $redis->getset('captain', 'Pike'); * $redis->getset('captain', 'Kirk'); */ public function getset(string $key, mixed $value): Redis|string|false {} /** * Retrieve any set connection timeout * @return float|false The currently set timeout or false on failure (e.g. we aren't connected). */ public function getTimeout(): float|false {} /** * Get the number of bytes sent and received on the socket. * @return array An array in the form [$sent_bytes, $received_bytes] */ public function getTransferredBytes(): array {} /** * Reset the number of bytes sent and received on the socket. * @return void */ public function clearTransferredBytes(): void {} /** * Remove one or more fields from a hash. * @param string $key The hash key in question. * @param string $field The first field to remove * @param string ...$other_fields One or more additional fields to remove. * @return Redis|int|false The number of fields actually removed. * @see https://redis.io/commands/hdel * @example $redis->hDel('communication', 'Alice', 'Bob'); */ public function hDel(string $key, string $field, string ...$other_fields): Redis|int|false {} /** * Checks whether a field exists in a hash. * @param string $key The hash to query. * @param string $field The field to check * @return Redis|bool True if it exists, false if not. * @see https://redis.io/commands/hexists * @example $redis->hExists('communication', 'Alice'); */ public function hExists(string $key, string $field): Redis|bool {} public function hGet(string $key, string $member): mixed {} /** * Read every field and value from a hash. * @param string $key The hash to query. * @return Redis|array|false All fields and values or false if the key didn't exist. * @see https://redis.io/commands/hgetall * @example $redis->hgetall('myhash'); */ public function hGetAll(string $key): Redis|array|false {} /** * Increment a hash field's value by an integer * @param string $key The hash to modify * @param string $field The field to increment * @param int $value How much to increment the value. * @return Redis|int|false The new value of the field. * @see https://redis.io/commands/hincrby * @example * $redis->hMSet('player:1', ['name' => 'Alice', 'score' => 0]); * $redis->hincrby('player:1', 'score', 10); */ public function hIncrBy(string $key, string $field, int $value): Redis|int|false {} /** * Increment a hash field by a floating point value * @param string $key The hash with the field to increment. * @param string $field The field to increment. * @return Redis|float|false The field value after incremented. * @see https://redis.io/commands/hincrbyfloat * @example * $redis->hincrbyfloat('numbers', 'tau', 2 * 3.1415926); */ public function hIncrByFloat(string $key, string $field, float $value): Redis|float|false {} /** * Retrieve all of the fields of a hash. * @param string $key The hash to query. * @return Redis|array|false The fields in the hash or false if the hash doesn't exist. * @see https://redis.io/commands/hkeys * @example $redis->hkeys('myhash'); */ public function hKeys(string $key): Redis|array|false {} /** * Get the number of fields in a hash. * @see https://redis.io/commands/hlen * @param string $key The hash to check. * @return Redis|int|false The number of fields or false if the key didn't exist. * @example $redis->hlen('myhash'); */ public function hLen(string $key): Redis|int|false {} /** * Get one or more fields from a hash. * @param string $key The hash to query. * @param array $fields One or more fields to query in the hash. * @return Redis|array|false The fields and values or false if the key didn't exist. * @see https://redis.io/commands/hmget * @example $redis->hMGet('player:1', ['name', 'score']); */ public function hMget(string $key, array $fields): Redis|array|false {} /** * Add or update one or more hash fields and values * @param string $key The hash to create/update * @param array $fieldvals An associative array with fields and their values. * @return Redis|bool True if the operation was successful * @see https://redis.io/commands/hmset * @example $redis->hmset('updates', ['status' => 'starting', 'elapsed' => 0]); */ public function hMset(string $key, array $fieldvals): Redis|bool {} /** * Get one or more random field from a hash. * @param string $key The hash to query. * @param array|null $options An array of options to modify how the command behaves. * * $options = [ * 'COUNT' => int # An optional number of fields to return. * 'WITHVALUES' => bool # Also return the field values. * ]; * * @return Redis|array|string One or more random fields (and possibly values). * @see https://redis.io/commands/hrandfield * @example $redis->hrandfield('settings'); * @example $redis->hrandfield('settings', ['count' => 2, 'withvalues' => true]); */ public function hRandField(string $key, ?array $options = null): Redis|string|array {} public function hSet(string $key, string $member, mixed $value): Redis|int|false {} /** * Set a hash field and value, but only if that field does not exist * @param string $key The hash to update. * @param string $field The value to set. * @return Redis|bool True if the field was set and false if not. * @see https://redis.io/commands/hsetnx * @example * $redis->hsetnx('player:1', 'lock', 'enabled'); * $redis->hsetnx('player:1', 'lock', 'enabled'); */ public function hSetNx(string $key, string $field, string $value): Redis|bool {} /** * Get the string length of a hash field * @param string $key The hash to query. * @param string $field The field to query. * @return Redis|int|false The string length of the field or false. * @example * $redis = new Redis(['host' => 'localhost']); * $redis->del('hash'); * $redis->hmset('hash', ['50bytes' => str_repeat('a', 50)]); * $redis->hstrlen('hash', '50bytes'); * @see https://redis.io/commands/hstrlen */ public function hStrLen(string $key, string $field): Redis|int|false {} /** * Get all of the values from a hash. * @param string $key The hash to query. * @return Redis|array|false The values from the hash. * @see https://redis.io/commands/hvals * @example $redis->hvals('player:1'); */ public function hVals(string $key): Redis|array|false {} /** * Iterate over the fields and values of a hash in an incremental fashion. * @see https://redis.io/commands/hscan * @see https://redis.io/commands/scan * @param string $key The hash to query. * @param int|null $iterator The scan iterator, which should be initialized to NULL before the first call. * This value will be updated after every call to hscan, until it reaches zero * meaning the scan is complete. * @param string|null $pattern An optional glob-style pattern to filter fields with. * @param int $count An optional hint to Redis about how many fields and values to return per HSCAN. * @return Redis|array|bool An array with a subset of fields and values. * @example * $redis = new Redis(['host' => 'localhost']); * $redis->del('big-hash'); * for ($i = 0; $i < 1000; $i++) { * $fields["field:$i"] = "value:$i"; * } * $redis->hmset('big-hash', $fields); * $it = null; * do { * // Scan the hash but limit it to fields that match '*:1?3' * $fields = $redis->hscan('big-hash', $it, '*:1?3'); * foreach ($fields as $field => $value) { * echo "[$field] => $value\n"; * } * } while ($it != 0); */ public function hscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): Redis|array|bool {} /** * Increment a key's value, optionally by a specifc amount. * @see https://redis.io/commands/incr * @see https://redis.io/commands/incrby * @param string $key The key to increment * @param int $by An optional amount to increment by. * @return Redis|int|false The new value of the key after incremented. * @example $redis->incr('mycounter'); * @example $redis->incr('mycounter', 10); */ public function incr(string $key, int $by = 1): Redis|int|false {} /** * Increment a key by a specific integer value * @see https://redis.io/commands/incrby * @param string $key The key to increment. * @param int $value The amount to increment. * @example * $redis->set('primes', 2); * $redis->incrby('primes', 1); * $redis->incrby('primes', 2); * $redis->incrby('primes', 2); * $redis->incrby('primes', 4); */ public function incrBy(string $key, int $value): Redis|int|false {} /** * Increment a numeric key by a floating point value. * @param string $key The key to increment * @param float $value How much to increment (or decrement) the value. * @return Redis|float|false The new value of the key or false if the key didn't contain a string. * @example * $redis->incrbyfloat('tau', 3.1415926); * $redis->incrbyfloat('tau', 3.1415926); */ public function incrByFloat(string $key, float $value): Redis|float|false {} /** * Retrieve information about the connected redis-server. If no arguments are passed to * this function, redis will return every info field. Alternatively you may pass a specific * section you want returned (e.g. 'server', or 'memory') to receive only information pertaining * to that section. * If connected to Redis server >= 7.0.0 you may pass multiple optional sections. * @see https://redis.io/commands/info/ * @param string ...$sections Optional section(s) you wish Redis server to return. * @return Redis|array|false */ public function info(string ...$sections): Redis|array|false {} /** * Check if we are currently connected to a Redis instance. * @return bool True if we are, false if not */ public function isConnected(): bool {} /** @return Redis|array|false */ public function keys(string $pattern) {} public function lInsert(string $key, string $pos, mixed $pivot, mixed $value) {} /** * Retrieve the lenght of a list. * @param string $key The list * @return Redis|int|false The number of elements in the list or false on failure. */ public function lLen(string $key): Redis|int|false {} /** * Move an element from one list into another. * @param string $src The source list. * @param string $dst The destination list * @param string $wherefrom Where in the source list to retrieve the element. This can be either * - `Redis::LEFT`, or `Redis::RIGHT`. * @param string $whereto Where in the destination list to put the element. This can be either * - `Redis::LEFT`, or `Redis::RIGHT`. * @return Redis|string|false The element removed from the source list. * @example * $redis->rPush('numbers', 'one', 'two', 'three'); * $redis->lMove('numbers', 'odds', Redis::LEFT, Redis::LEFT); */ public function lMove(string $src, string $dst, string $wherefrom, string $whereto): Redis|string|false {} /** * Move an element from one list to another, blocking up to a timeout until an element is available. * @param string $src The source list * @param string $dst The destination list * @param string $wherefrom Where in the source list to extract the element. * - `Redis::LEFT`, or `Redis::RIGHT`. * @param string $whereto Where in the destination list to put the element. * - `Redis::LEFT`, or `Redis::RIGHT`. * @param float $timeout How long to block for an element. * @return Redis|string|false * @example * $redis->lPush('numbers', 'one'); * $redis->blmove('numbers', 'odds', Redis::LEFT, Redis::LEFT 1.0); * // This call will block, if no additional elements are in 'numbers' * $redis->blmove('numbers', 'odds', Redis::LEFT, Redis::LEFT, 1.0); */ public function blmove(string $src, string $dst, string $wherefrom, string $whereto, float $timeout): Redis|string|false {} /** * Pop one or more elements off a list. * @param string $key The list to pop from. * @param int $count Optional number of elements to remove. By default one element is popped. * @return Redis|bool|string|array Will return the element(s) popped from the list or false/NULL * if none was removed. * @see https://redis.io/commands/lpop * @example $redis->lpop('mylist'); * @example $redis->lpop('mylist', 4); */ public function lPop(string $key, int $count = 0): Redis|bool|string|array {} /** * Retrieve the index of an element in a list. * @param string $key The list to query. * @param mixed $value The value to search for. * @param array|null $options Options to configure how the command operates * * $options = [ * # How many matches to return. By default a single match is returned. * # If count is set to zero, it means unlimited. * 'COUNT' => * # Specify which match you want returned. `RANK` 1 means "the first match" * # 2 means the second, and so on. If passed as a negative number the * # RANK is computed right to left, so a `RANK` of -1 means "the last match". * 'RANK' => * # This argument allows you to limit how many elements Redis will search before * # returning. This is useful to prevent Redis searching very long lists while * # blocking the client. * 'MAXLEN => * ]; * * @return Redis|null|bool|int|array Returns one or more of the matching indexes, or null/false if none were found. */ public function lPos(string $key, mixed $value, ?array $options = null): Redis|null|bool|int|array {} /** * Prepend one or more elements to a list. * @param string $key The list to prepend. * @param mixed $elements One or more elements to prepend. * @return Redis|int|false The new length of the list after prepending. * @see https://redis.io/commands/lpush * @example $redis->lPush('mylist', 'cat', 'bear', 'aligator'); */ public function lPush(string $key, mixed ...$elements): Redis|int|false {} /** * Append one or more elements to a list. * @param string $key The list to append to. * @param mixed $elements one or more elements to append. * @return Redis|int|false The new length of the list * @see https://redis.io/commands/rpush * @example $redis->rPush('mylist', 'xray', 'yankee', 'zebra'); */ public function rPush(string $key, mixed ...$elements): Redis|int|false {} /** * Prepend an element to a list but only if the list exists * @param string $key The key to prepend to. * @param mixed $value The value to prepend. * @return Redis|int|false The new length of the list. */ public function lPushx(string $key, mixed $value): Redis|int|false {} /** * Append an element to a list but only if the list exists * @param string $key The key to prepend to. * @param mixed $value The value to prepend. * @return Redis|int|false The new length of the list. */ public function rPushx(string $key, mixed $value): Redis|int|false {} /** * Set a list element at an index to a specific value. * @param string $key The list to modify. * @param int $index The position of the element to change. * @param mixed $value The new value. * @return Redis|bool True if the list was modified. * @see https://redis.io/commands/lset */ public function lSet(string $key, int $index, mixed $value): Redis|bool {} /** * Retrieve the last time Redis' database was persisted to disk. * @return int The unix timestamp of the last save time * @see https://redis.io/commands/lastsave */ public function lastSave(): int {} /** * Get the element of a list by its index. * @param string $key The key to query * @param int $index The index to check. * @return mixed The index or NULL/false if the element was not found. */ public function lindex(string $key, int $index): mixed {} /** * Retrieve elements from a list. * @param string $key The list to query. * @param int $start The beginning index to retrieve. This number can be negative * meaning start from the end of the list. * @param int $end The end index to retrieve. This can also be negative to start * from the end of the list. * @return Redis|array|false The range of elements between the indexes. * @example $redis->lrange('mylist', 0, -1); // the whole list * @example $redis->lrange('mylist', -2, -1); // the last two elements in the list. */ public function lrange(string $key, int $start, int $end): Redis|array|false {} /** * Remove one or more matching elements from a list. * @param string $key The list to truncate. * @param mixed $value The value to remove. * @param int $count How many elements matching the value to remove. * @return Redis|int|false The number of elements removed. * @see https://redis.io/commands/lrem */ public function lrem(string $key, mixed $value, int $count = 0): Redis|int|false {} /** * Trim a list to a subrange of elements. * @param string $key The list to trim * @param int $start The starting index to keep * @param int $end The ending index to keep. * @return Redis|bool true if the list was trimmed. * @example $redis->ltrim('mylist', 0, 3); // Keep the first four elements */ public function ltrim(string $key, int $start, int $end): Redis|bool {} /** * Get one ore more string keys. * @param array $keys The keys to retrieve * @return Redis|array an array of keys with their values. * @example $redis->mget(['key1', 'key2']); */ public function mget(array $keys): Redis|array {} public function migrate( string $host, int $port, string|array $key, int $dstdb, int $timeout, bool $copy = false, bool $replace = false, #[\SensitiveParameter] mixed $credentials = null ): Redis|bool {} /** * Move a key to a different database on the same redis instance. * @param string $key The key to move * @return Redis|bool True if the key was moved */ public function move(string $key, int $index): Redis|bool {} /** * Set one ore more string keys. * @param array $key_values An array with keys and their values. * @return Redis|bool True if the keys could be set. * @see https://redis.io/commands/mset * @example $redis->mSet(['foo' => 'bar', 'baz' => 'bop']); */ public function mset(array $key_values): Redis|bool {} /** * Set one ore more string keys but only if none of the key exist. * @param array $key_values An array of keys with their values. * @return Redis|bool True if the keys were set and false if not. * @see https://redis.io/commands/msetnx * @example $redis->msetnx(['foo' => 'bar', 'baz' => 'bop']); */ public function msetnx(array $key_values): Redis|bool {} /** * Begin a transaction. * @param int $value The type of transaction to start. This can either be `Redis::MULTI` or * `Redis::PIPELINE'. * @return Redis|bool True if the transaction could be started. * @see https://redis.io/commands/multi * @example * $redis->multi(); * $redis->set('foo', 'bar'); * $redis->get('foo'); * $redis->exec(); */ public function multi(int $value = Redis::MULTI): bool|Redis {} public function object(string $subcommand, string $key): Redis|int|string|false {} /** * @deprecated */ public function open(string $host, int $port = 6379, float $timeout = 0, ?string $persistent_id = null, int $retry_interval = 0, float $read_timeout = 0, ?array $context = null): bool {} public function pconnect(string $host, int $port = 6379, float $timeout = 0, ?string $persistent_id = null, int $retry_interval = 0, float $read_timeout = 0, ?array $context = null): bool {} /** * Remove the expiration from a key. * @param string $key The key to operate against. * @return Redis|bool True if a timeout was removed and false if it was not or the key didn't exist. */ public function persist(string $key): Redis|bool {} /** * Sets an expiration in milliseconds on a given key. If connected to Redis >= 7.0.0 * you can pass an optional mode argument that modifies how the command will execute. * @param string $key The key to set an expiration on. * @param int $timeout The number of milliseconds after which key will be automatically deleted. * @param string|null $mode A two character modifier that changes how the * command works. * @return bool True if an expiry was set on the key, and false otherwise. * @see Redis::expire() for a description of the mode argument. */ public function pexpire(string $key, int $timeout, ?string $mode = null): bool {} /** * Set a key's expiration to a specific Unix Timestamp in milliseconds. If connected to * Redis >= 7.0.0 you can pass an optional 'mode' argument. * @param string $key The key to set an expiration on. * @param int $timestamp The unix timestamp to expire at. * @param string|null $mode A two character modifier that changes how the * command works. * @return Redis|bool True if an expiration was set on the key, false otherwise. * @see Redis::expire() For a description of the mode argument. */ public function pexpireAt(string $key, int $timestamp, ?string $mode = null): Redis|bool {} /** * Add one or more elements to a Redis HyperLogLog key * @see https://redis.io/commands/pfadd * @param string $key The key in question. * @param array $elements One or more elements to add. * @return Redis|int Returns 1 if the set was altered, and zero if not. */ public function pfadd(string $key, array $elements): Redis|int {} /** * Retrieve the cardinality of a Redis HyperLogLog key. * @see https://redis.io/commands/pfcount * @param array|string $key_or_keys Either one key or an array of keys * @return Redis|int|false The estimated cardinality of the set. */ public function pfcount(array|string $key_or_keys): Redis|int|false {} /** * Merge one or more source HyperLogLog sets into a destination set. * @see https://redis.io/commands/pfmerge * @param string $dst The destination key. * @param array $srckeys One or more source keys. * @return Redis|bool Always returns true. */ public function pfmerge(string $dst, array $srckeys): Redis|bool {} /** * PING the redis server with an optional string argument. * @see https://redis.io/commands/ping * @param string|null $message An optional string message that Redis will reply with, if passed. * @return Redis|string|false If passed no message, this command will simply return `true`. * If a message is passed, it will return the message. * @example $redis->ping(); * @example $redis->ping('beep boop'); */ public function ping(?string $message = null): Redis|string|bool {} /** * Enter into pipeline mode. * Pipeline mode is the highest performance way to send many commands to Redis * as they are aggregated into one stream of commands and then all sent at once * when the user calls Redis::exec(). * NOTE: That this is shorthand for Redis::multi(Redis::PIPELINE) * @return Redis|bool The redis object is returned, to facilitate method chaining. * @example * $redis->pipeline() * ->set('foo', 'bar') * ->del('mylist') * ->rpush('mylist', 'a', 'b', 'c') * ->exec(); */ public function pipeline(): bool|Redis {} /** * @deprecated */ public function popen(string $host, int $port = 6379, float $timeout = 0, ?string $persistent_id = null, int $retry_interval = 0, float $read_timeout = 0, ?array $context = null): bool {} /** * Set a key with an expiration time in milliseconds * @param string $key The key to set * @param int $expire The TTL to set, in milliseconds. * @param mixed $value The value to set the key to. * @return Redis|bool True if the key could be set. * @example $redis->psetex('mykey', 1000, 'myval'); */ public function psetex(string $key, int $expire, mixed $value): Redis|bool {} /** * Subscribe to one or more glob-style patterns * @param array $patterns One or more patterns to subscribe to. * @param callable $cb A callback with the following prototype: * * function ($redis, $channel, $message) { } * * @return bool True if we were subscribed. * @see https://redis.io/commands/psubscribe */ public function psubscribe(array $patterns, callable $cb): bool {} /** * Get a keys time to live in milliseconds. * @param string $key The key to check. * @return Redis|int|false The key's TTL or one of two special values if it has none. * * -1 - The key has no TTL. * -2 - The key did not exist. * * @see https://redis.io/commands/pttl * @example $redis->pttl('ttl-key'); */ public function pttl(string $key): Redis|int|false {} /** * Publish a message to a pubsub channel * @see https://redis.io/commands/publish * @param string $channel The channel to publish to. * @param string $message The message itself. * @return Redis|int|false The number of subscribed clients to the given channel. */ public function publish(string $channel, string $message): Redis|int|false {} public function pubsub(string $command, mixed $arg = null): mixed {} /** * Unsubscribe from one or more channels by pattern * @see https://redis.io/commands/punsubscribe * @see https://redis.io/commands/subscribe * @see Redis::subscribe() * @param array $patterns One or more glob-style patterns of channel names. * @return Redis|array|bool The array of subscribed patterns or false on failure. */ public function punsubscribe(array $patterns): Redis|array|bool {} /** * Pop one or more elements from the end of a list. * @param string $key A redis LIST key name. * @param int $count The maximum number of elements to pop at once. * NOTE: The `count` argument requires Redis >= 6.2.0 * @return Redis|array|string|bool One ore more popped elements or false if all were empty. * @see https://redis.io/commands/rpop * @example $redis->rPop('mylist'); * @example $redis->rPop('mylist', 4); */ public function rPop(string $key, int $count = 0): Redis|array|string|bool {} /** * Return a random key from the current database * @see https://redis.io/commands/randomkey * @return Redis|string|false A random key name or false if no keys exist */ public function randomKey(): Redis|string|false {} /** * Execute any arbitrary Redis command by name. * @param string $command The command to execute * @param mixed $args One or more arguments to pass to the command. * @return mixed Can return any number of things depending on command executed. * @example $redis->rawCommand('del', 'mystring', 'mylist'); * @example $redis->rawCommand('set', 'mystring', 'myvalue'); * @example $redis->rawCommand('rpush', 'mylist', 'one', 'two', 'three'); */ public function rawcommand(string $command, mixed ...$args): mixed {} /** * Unconditionally rename a key from $old_name to $new_name * @see https://redis.io/commands/rename * @param string $old_name The original name of the key * @param string $new_name The new name for the key * @return Redis|bool True if the key was renamed or false if not. */ public function rename(string $old_name, string $new_name): Redis|bool {} /** * Renames $key_src to $key_dst but only if newkey does not exist. * @see https://redis.io/commands/renamenx * @param string $key_src The source key name * @param string $key_dst The destination key name. * @return Redis|bool True if the key was renamed, false if not. * @example * $redis->set('src', 'src_key'); * $redis->set('existing-dst', 'i_exist'); * $redis->renamenx('src', 'dst'); * $redis->renamenx('dst', 'existing-dst'); */ public function renameNx(string $key_src, string $key_dst): Redis|bool {} /** * Reset the state of the connection. * @return Redis|bool Should always return true unless there is an error. */ public function reset(): Redis|bool {} /** * Restore a key by the binary payload generated by the DUMP command. * @param string $key The name of the key you wish to create. * @param int $ttl What Redis should set the key's TTL (in milliseconds) to once it is created. * Zero means no TTL at all. * @param string $value The serialized binary value of the string (generated by DUMP). * @param array|null $options An array of additional options that modifies how the command operates. * * $options = [ * 'ABSTTL' # If this is present, the `$ttl` provided by the user should * # be an absolute timestamp, in milliseconds() * 'REPLACE' # This flag instructs Redis to store the key even if a key with * # that name already exists. * 'IDLETIME' => int # Tells Redis to set the keys internal 'idletime' value to a * # specific number (see the Redis command OBJECT for more info). * 'FREQ' => int # Tells Redis to set the keys internal 'FREQ' value to a specific * # number (this relates to Redis' LFU eviction algorithm). * ]; * * @return Redis|bool True if the key was stored, false if not. * @see https://redis.io/commands/restore * @see https://redis.io/commands/dump * @see Redis::dump() * @example * $redis->sAdd('captains', 'Janeway', 'Picard', 'Sisko', 'Kirk', 'Archer'); * $serialized = $redis->dump('captains'); * $redis->restore('captains-backup', 0, $serialized); */ public function restore(string $key, int $ttl, string $value, ?array $options = null): Redis|bool {} /** * Query whether the connected instance is a primary or replica * @return mixed Will return an array with the role of the connected instance unless there is * an error. */ public function role(): mixed {} /** * Atomically pop an element off the end of a Redis LIST and push it to the beginning of * another. * @param string $srckey The source key to pop from. * @param string $dstkey The destination key to push to. * @return Redis|string|false The popped element or false if the source key was empty. * @see https://redis.io/commands/rpoplpush * @example * $redis->pipeline() * ->del('list1', 'list2') * ->rpush('list1', 'list1-1', 'list1-2') * ->rpush('list2', 'list2-1', 'list2-2') * ->exec(); * $redis->rpoplpush('list2', 'list1'); */ public function rpoplpush(string $srckey, string $dstkey): Redis|string|false {} /** * Add one or more values to a Redis SET key. * @param string $key The key name * @param mixed $value A value to add to the set. * @param mixed ...$other_values One or more additional values to add * @return Redis|int|false The number of values added to the set. * @see https://redis.io/commands/sadd * @example * $redis->del('myset'); * $redis->sadd('myset', 'foo', 'bar', 'baz'); * $redis->sadd('myset', 'foo', 'new'); */ public function sAdd(string $key, mixed $value, mixed ...$other_values): Redis|int|false {} /** * Add one ore more values to a Redis SET key. This is an alternative to Redis::sadd() but * instead of being variadic, takes a single array of values. * @see https://redis.io/commands/sadd * @see Redis::sadd() * @param string $key The set to add values to. * @param array $values One or more members to add to the set. * @return int The number of members added to the set. * @example * $redis->del('myset'); * $redis->sAddArray('myset', ['foo', 'bar', 'baz']); * $redis->sAddArray('myset', ['foo', 'new']); */ public function sAddArray(string $key, array $values): int {} /** * Given one or more Redis SETS, this command returns all of the members from the first * set that are not in any subsequent set. * @param string $key The first set * @param string ...$other_keys One or more additional sets * @return Redis|array|false Returns the elements from keys 2..N that don't exist in the * first sorted set, or false on failure. * @see https://redis.io/commands/sdiff * @example * $redis->pipeline() * ->del('set1', 'set2', 'set3') * ->sadd('set1', 'apple', 'banana', 'carrot', 'date') * ->sadd('set2', 'carrot') * ->sadd('set3', 'apple', 'carrot', 'eggplant') * ->exec(); * $redis->sdiff('set1', 'set2', 'set3'); */ public function sDiff(string $key, string ...$other_keys): Redis|array|false {} /** * This method performs the same operation as SDIFF except it stores the resulting diff * values in a specified destination key. * @see https://redis.io/commands/sdiffstore * @see Redis::sdiff() * @param string $dst The key where to store the result * @param string $key The first key to perform the DIFF on * @param string ...$other_keys One or more additional keys. * @return Redis|int|false The number of values stored in the destination set or false on failure. */ public function sDiffStore(string $dst, string $key, string ...$other_keys): Redis|int|false {} /** * Given one or more Redis SET keys, this command will return all of the elements that are * in every one. * @see https://redis.io/commands/sinter * @param array|string $key The first SET key to intersect. * @param string ...$other_keys One or more Redis SET keys. * @example * $redis->pipeline() * ->del('alice_likes', 'bob_likes', 'bill_likes') * ->sadd('alice_likes', 'asparagus', 'broccoli', 'carrot', 'potato') * ->sadd('bob_likes', 'asparagus', 'carrot', 'potato') * ->sadd('bill_likes', 'broccoli', 'potato') * ->exec(); * var_dump($redis->sinter('alice_likes', 'bob_likes', 'bill_likes')); * */ public function sInter(array|string $key, string ...$other_keys): Redis|array|false {} /** * Compute the intersection of one or more sets and return the cardinality of the result. * @param array $keys One or more set key names. * @param int $limit A maximum cardinality to return. This is useful to put an upper bound * on the amount of work Redis will do. * @return Redis|int|false The * @see https://redis.io/commands/sintercard * @example * $redis->sAdd('set1', 'apple', 'pear', 'banana', 'carrot'); * $redis->sAdd('set2', 'apple', 'banana'); * $redis->sAdd('set3', 'pear', 'banana'); * $redis->sInterCard(['set1', 'set2', 'set3']); * ?> * */ public function sintercard(array $keys, int $limit = -1): Redis|int|false {} /** * Perform the intersection of one or more Redis SETs, storing the result in a destination * key, rather than returning them. * @param array|string $key Either a string key, or an array of keys (with at least two * elements, consisting of the destination key name and one * or more source keys names. * @param string ...$other_keys If the first argument was a string, subsequent arguments should * be source key names. * @return Redis|int|false The number of values stored in the destination key or false on failure. * @see https://redis.io/commands/sinterstore * @see Redis::sinter() * @example $redis->sInterStore(['dst', 'src1', 'src2', 'src3']); * @example $redis->sInterStore('dst', 'src1', 'src'2', 'src3'); * ?> * */ public function sInterStore(array|string $key, string ...$other_keys): Redis|int|false {} /** * Retrieve every member from a set key. * @param string $key The set name. * @return Redis|array|false Every element in the set or false on failure. * @see https://redis.io/commands/smembers * @example * $redis->sAdd('tng-crew', ...['Picard', 'Riker', 'Data', 'Worf', 'La Forge', 'Troi', 'Crusher', 'Broccoli']); * $redis->sMembers('tng-crew'); */ public function sMembers(string $key): Redis|array|false {} /** * Check if one or more values are members of a set. * @see https://redis.io/commands/smismember * @see https://redis.io/commands/smember * @see Redis::smember() * @param string $key The set to query. * @param string $member The first value to test if exists in the set. * @param string ...$other_members Any number of additional values to check. * @return Redis|array|false An array of integers representing whether each passed value * was a member of the set. * @example * $redis->sAdd('ds9-crew', ...["Sisko", "Kira", "Dax", "Worf", "Bashir", "O'Brien"]); * $members = $redis->sMIsMember('ds9-crew', ...['Sisko', 'Picard', 'Data', 'Worf']); */ public function sMisMember(string $key, string $member, string ...$other_members): Redis|array|false {} /** * Pop a member from one set and push it onto another. This command will create the * destination set if it does not currently exist. * @see https://redis.io/commands/smove * @param string $src The source set. * @param string $dst The destination set. * @param mixed $value The member you wish to move. * @return Redis|bool True if the member was moved, and false if it wasn't in the set. * @example * $redis->sAdd('numbers', 'zero', 'one', 'two', 'three', 'four'); * $redis->sMove('numbers', 'evens', 'zero'); * $redis->sMove('numbers', 'evens', 'two'); * $redis->sMove('numbers', 'evens', 'four'); */ public function sMove(string $src, string $dst, mixed $value): Redis|bool {} /** * Remove one or more elements from a set. * @see https://redis.io/commands/spop * @param string $key The set in question. * @param int $count An optional number of members to pop. This defaults to * removing one element. * @example * $redis->del('numbers', 'evens'); * $redis->sAdd('numbers', 'zero', 'one', 'two', 'three', 'four'); * $redis->sPop('numbers'); */ public function sPop(string $key, int $count = 0): Redis|string|array|false {} /** * Retrieve one or more random members of a set. * @param string $key The set to query. * @param int $count An optional count of members to return. * If this value is positive, Redis will return *up to* the requested * number but with unique elements that will never repeat. This means * you may recieve fewer then `$count` replies. * If the number is negative, Redis will return the exact number requested * but the result may contain duplicate elements. * @return Redis|array|string|false One or more random members or false on failure. * @see https://redis.io/commands/srandmember * @example $redis->sRandMember('myset'); * @example $redis->sRandMember('myset', 10); * @example $redis->sRandMember('myset', -10); */ public function sRandMember(string $key, int $count = 0): Redis|string|array|false {} /** * Returns the union of one or more Redis SET keys. * @see https://redis.io/commands/sunion * @param string $key The first SET to do a union with * @param string ...$other_keys One or more subsequent keys * @return Redis|array|false The union of the one or more input sets or false on failure. * @example $redis->sunion('set1', 'set2'); */ public function sUnion(string $key, string ...$other_keys): Redis|array|false {} /** * Perform a union of one or more Redis SET keys and store the result in a new set * @see https://redis.io/commands/sunionstore * @see Redis::sunion() * @param string $dst The destination key * @param string $key The first source key * @param string ...$other_keys One or more additional source keys * @return Redis|int|false The number of elements stored in the destination SET or * false on failure. */ public function sUnionStore(string $dst, string $key, string ...$other_keys): Redis|int|false {} /** * Persist the Redis database to disk. This command will block the server until the save is * completed. For a nonblocking alternative, see Redis::bgsave(). * @see https://redis.io/commands/save * @see Redis::bgsave() * @return Redis|bool Returns true unless an error occurs. */ public function save(): Redis|bool {} /** * Incrementally scan the Redis keyspace, with optional pattern and type matching. * A note about Redis::SCAN_NORETRY and Redis::SCAN_RETRY. * For convenience, PhpRedis can retry SCAN commands itself when Redis returns an empty array of * keys with a nonzero iterator. This can happen when matching against a pattern that very few * keys match inside a key space with a great many keys. The following example demonstrates how * to use Redis::scan() with the option disabled and enabled. * @param int|null $iterator The cursor returned by Redis for every subsequent call to SCAN. On * the initial invocation of the call, it should be initialized by the * caller to NULL. Each time SCAN is invoked, the iterator will be * updated to a new number, until finally Redis will set the value to * zero, indicating that the scan is complete. * @param string|null $pattern An optional glob-style pattern for matching key names. If passed as * NULL, it is the equivalent of sending '*' (match every key). * @param int $count A hint to redis that tells it how many keys to return in a single * call to SCAN. The larger the number, the longer Redis may block * clients while iterating the key space. * @param string|null $type An optional argument to specify which key types to scan (e.g. * 'STRING', 'LIST', 'SET') * @return array|false An array of keys, or false if no keys were returned for this * invocation of scan. Note that it is possible for Redis to return * zero keys before having scanned the entire key space, so the caller * should instead continue to SCAN until the iterator reference is * returned to zero. * @see https://redis.io/commands/scan * @see Redis::setOption() * @example * $redis = new Redis(['host' => 'localhost']); * $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_NORETRY); * $it = null; * do { * $keys = $redis->scan($it, '*zorg*'); * foreach ($keys as $key) { * echo "KEY: $key\n"; * } * } while ($it != 0); * $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); * $it = null; * // When Redis::SCAN_RETRY is enabled, we can use simpler logic, as we will never receive an * // empty array of keys when the iterator is nonzero. * while ($keys = $redis->scan($it, '*zorg*')) { * foreach ($keys as $key) { * echo "KEY: $key\n"; * } * } */ public function scan(?int &$iterator, ?string $pattern = null, int $count = 0, ?string $type = null): array|false {} /** * Retrieve the number of members in a Redis set. * @param string $key The set to get the cardinality of. * @return Redis|int|false The cardinality of the set or false on failure. * @see https://redis.io/commands/scard * @example $redis->scard('set'); * */ public function scard(string $key): Redis|int|false {} /** * An administrative command used to interact with LUA scripts stored on the server. * @see https://redis.io/commands/script * @param string $command The script suboperation to execute. * @param mixed $args One ore more additional argument * @return mixed This command returns various things depending on the specific operation executed. * @example $redis->script('load', 'return 1'); * @example $redis->script('exists', sha1('return 1')); */ public function script(string $command, mixed ...$args): mixed {} /** * Select a specific Redis database. * @param int $db The database to select. Note that by default Redis has 16 databases (0-15). * @return Redis|bool true on success and false on failure * @see https://redis.io/commands/select * @example $redis->select(1); */ public function select(int $db): Redis|bool {} /** * Create or set a Redis STRING key to a value. * @param string $key The key name to set. * @param mixed $value The value to set the key to. * @param array|int $options Either an array with options for how to perform the set or an * integer with an expiration. If an expiration is set PhpRedis * will actually send the `SETEX` command. * OPTION DESCRIPTION * ------------ -------------------------------------------------------------- * ['EX' => 60] expire 60 seconds. * ['PX' => 6000] expire in 6000 milliseconds. * ['EXAT' => time() + 10] expire in 10 seconds. * ['PXAT' => time()*1000 + 1000] expire in 1 second. * ['KEEPTTL' => true] Redis will not update the key's current TTL. * ['XX'] Only set the key if it already exists. * ['NX'] Only set the key if it doesn't exist. * ['GET'] Instead of returning `+OK` return the previous value of the * key or NULL if the key didn't exist. * @return Redis|string|bool True if the key was set or false on failure. * @see https://redis.io/commands/set * @see https://redis.io/commands/setex * @example $redis->set('key', 'value'); * @example $redis->set('key', 'expires_in_60_seconds', 60); */ public function set(string $key, mixed $value, mixed $options = null): Redis|string|bool {} /** * Set a specific bit in a Redis string to zero or one * @see https://redis.io/commands/setbit * @param string $key The Redis STRING key to modify * @param bool $value Whether to set the bit to zero or one. * @return Redis|int|false The original value of the bit or false on failure. * @example * $redis->set('foo', 'bar'); * $redis->setbit('foo', 7, 1); */ public function setBit(string $key, int $idx, bool $value): Redis|int|false {} /** * Update or append to a Redis string at a specific starting index * @see https://redis.io/commands/setrange * @param string $key The key to update * @param int $index Where to insert the provided value * @param string $value The value to copy into the string. * @return Redis|int|false The new length of the string or false on failure * @example * $redis->set('message', 'Hello World'); * $redis->setRange('message', 6, 'Redis'); */ public function setRange(string $key, int $index, string $value): Redis|int|false {} /** * Set a configurable option on the Redis object. * Following are a list of options you can set: * | OPTION | TYPE | DESCRIPTION | * | --------------- | ---- | ----------- | * | OPT_MAX_RETRIES | int | The maximum number of times Redis will attempt to reconnect if it gets disconnected, before throwing an exception. | * | OPT_SCAN | enum | Redis::OPT_SCAN_RETRY, or Redis::OPT_SCAN_NORETRY. Whether PhpRedis should automatically SCAN again when zero keys but a nonzero iterator are returned. | * | OPT_SERIALIZER | enum | Set the automatic data serializer.
`Redis::SERIALIZER_NONE`
`Redis::SERIALIZER_PHP`
`Redis::SERIALIZER_IGBINARY`
`Redis::SERIALIZER_MSGPACK`, `Redis::SERIALIZER_JSON`| * | OPT_PREFIX | string | A string PhpRedis will use to prefix every key we read or write. | * | OPT_READ_TIMEOUT | float | How long PhpRedis will block for a response from Redis before throwing a 'read error on connection' exception. | * | OPT_TCP_KEEPALIVE | bool | Set or disable TCP_KEEPALIVE on the connection. | * | OPT_COMPRESSION | enum | Set the compression algorithm
`Redis::COMPRESSION_NONE`
`Redis::COMPRESSION_LZF`
`Redis::COMPRESSION_LZ4`
`Redis::COMPRESSION_ZSTD` | * | OPT_REPLY_LITERAL | bool | If set to true, PhpRedis will return the literal string Redis returns for LINE replies (e.g. '+OK'), rather than `true`. | * | OPT_COMPRESSION_LEVEL | int | Set a specific compression level if Redis is compressing data. | * | OPT_NULL_MULTIBULK_AS_NULL | bool | Causes PhpRedis to return `NULL` rather than `false` for NULL MULTIBULK replies | * | OPT_BACKOFF_ALGORITHM | enum | The exponential backoff strategy to use. | * | OPT_BACKOFF_BASE | int | The minimum delay between retries when backing off. | * | OPT_BACKOFF_CAP | int | The maximum delay between replies when backing off. | * @param int $option The option constant. * @param mixed $value The option value. * @return bool true if the setting was updated, false if not. * @see Redis::__construct() for details about backoff strategies. * @see Redis::getOption() */ public function setOption(int $option, mixed $value): bool {} /** * Set a Redis STRING key with a specific expiration in seconds. * @param string $key The name of the key to set. * @param int $expire The key's expiration in seconds. * @param mixed $value The value to set the key. * @return Redis|bool True on success or false on failure. * @example $redis->setex('60s-ttl', 60, 'some-value'); */ public function setex(string $key, int $expire, mixed $value) {} /** * Set a key to a value, but only if that key does not already exist. * @see https://redis.io/commands/setnx * @param string $key The key name to set. * @param mixed $value What to set the key to. * @return Redis|bool Returns true if the key was set and false otherwise. * @example $redis->setnx('existing-key', 'existing-value'); * @example $redis->setnx('new-key', 'new-value'); */ public function setnx(string $key, mixed $value): Redis|bool {} /** * Check whether a given value is the member of a Redis SET. * @param string $key The redis set to check. * @param mixed $value The value to test. * @return Redis|bool True if the member exists and false if not. * @example $redis->sismember('myset', 'mem1', 'mem2'); */ public function sismember(string $key, mixed $value): Redis|bool {} /** * Turn a redis instance into a replica of another or promote a replica * to a primary. * This method and the corresponding command in Redis has been marked deprecated * and users should instead use Redis::replicaof() if connecting to redis-server * >= 5.0.0. * @deprecated * @see https://redis.io/commands/slaveof * @see https://redis.io/commands/replicaof * @see Redis::replicaof() */ public function slaveof(?string $host = null, int $port = 6379): Redis|bool {} /** * Used to turn a Redis instance into a replica of another, or to remove * replica status promoting the instance to a primary. * @see https://redis.io/commands/replicaof * @see https://redis.io/commands/slaveof * @see Redis::slaveof() * @param string|null $host The host of the primary to start replicating. * @param int $port The port of the primary to start replicating. * @return Redis|bool Success if we were successfully able to start replicating a primary or * were able to promote teh replicat to a primary. * @example * $redis = new Redis(['host' => 'localhost']); * // Attempt to become a replica of a Redis instance at 127.0.0.1:9999 * $redis->replicaof('127.0.0.1', 9999); * // When passed no arguments, PhpRedis will deliver the command `REPLICAOF NO ONE` * // attempting to promote the instance to a primary. * $redis->replicaof(); */ public function replicaof(?string $host = null, int $port = 6379): Redis|bool {} /** * Update one or more keys last modified metadata. * @see https://redis.io/commands/touch/ * @param array|string $key_or_array * @param string ...$more_keys One or more keys to send to the command. * @return Redis|int|false This command returns the number of keys that exist and * had their last modified time reset */ public function touch(array|string $key_or_array, string ...$more_keys): Redis|int|false {} /** * Interact with Redis' slowlog functionality in various ways, depending * on the value of 'operation'. * @param string $operation The operation you wish to perform. This can * be one of the following values: * 'GET' - Retrieve the Redis slowlog as an array. * 'LEN' - Retrieve the length of the slowlog. * 'RESET' - Remove all slowlog entries. * @param int $length This optional argument can be passed when operation * is 'get' and will specify how many elements to retrieve. * If omitted Redis will send up to a default number of * entries, which is configurable. * Note: With Redis >= 7.0.0 you can send -1 to mean "all". * @return mixed * @see https://redis.io/commands/slowlog/ * @example $redis->slowlog('get', -1); // Retrieve all slowlog entries. * @example $redis->slowlog('len'); // Retrieve slowlog length. * @example $redis->slowlog('reset'); // Reset the slowlog. */ public function slowlog(string $operation, int $length = 0): mixed {} /** * Sort the contents of a Redis key in various ways. * @see https://redis.io/commands/sort/ * @param string $key The key you wish to sort * @param array|null $options Various options controlling how you would like the * data sorted. See blow for a detailed description * of this options array. * @return mixed This command can either return an array with the sorted data * or the number of elements placed in a destination set when * using the STORE option. * @example * $options = [ * 'SORT' => 'ASC'|| 'DESC' // Sort in descending or descending order. * 'ALPHA' => true || false // Whether to sort alphanumerically. * 'LIMIT' => [0, 10] // Return a subset of the data at offset, count * 'BY' => 'weight_*' // For each element in the key, read data from the * external key weight_* and sort based on that value. * 'GET' => 'weight_*' // For each element in the source key, retrieve the * data from key weight_* and return that in the result * rather than the source keys' element. This can * be used in combination with 'BY' * ]; */ public function sort(string $key, ?array $options = null): mixed {} /** * This is simply a read-only variant of the sort command * @see Redis::sort() */ public function sort_ro(string $key, ?array $options = null): mixed {} /** * @deprecated */ public function sortAsc(string $key, ?string $pattern = null, mixed $get = null, int $offset = -1, int $count = -1, ?string $store = null): array {} /** * @deprecated */ public function sortAscAlpha(string $key, ?string $pattern = null, mixed $get = null, int $offset = -1, int $count = -1, ?string $store = null): array {} /** * @deprecated */ public function sortDesc(string $key, ?string $pattern = null, mixed $get = null, int $offset = -1, int $count = -1, ?string $store = null): array {} /** * @deprecated */ public function sortDescAlpha(string $key, ?string $pattern = null, mixed $get = null, int $offset = -1, int $count = -1, ?string $store = null): array {} /** * Remove one or more values from a Redis SET key. * @see https://redis.io/commands/srem * @param string $key The Redis SET key in question. * @param mixed $value The first value to remove. * @param mixed ...$other_values One or more additional values to remove. * @return Redis|int|false The number of values removed from the set or false on failure. * @example $redis->sRem('set1', 'mem1', 'mem2', 'not-in-set'); */ public function srem(string $key, mixed $value, mixed ...$other_values): Redis|int|false {} /** * Scan the members of a redis SET key. * @see https://redis.io/commands/sscan * @see https://redis.io/commands/scan * @see Redis::setOption() * @param string $key The Redis SET key in question. * @param int|null $iterator A reference to an iterator which should be initialized to NULL that * PhpRedis will update with the value returned from Redis after each * subsequent call to SSCAN. Once this cursor is zero you know all * members have been traversed. * @param string|null $pattern An optional glob style pattern to match against, so Redis only * returns the subset of members matching this pattern. * @param int $count A hint to Redis as to how many members it should scan in one command * before returning members for that iteration. * @return array|false * @example * $redis->del('myset'); * for ($i = 0; $i < 10000; $i++) { * $redis->sAdd('myset', "member:$i"); * } * $redis->sadd('myset', 'foofoo'); * $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_NORETRY); * $scanned = 0; * $it = null; * // Without Redis::SCAN_RETRY we may receive empty results and * // a nonzero iterator. * do { * // Scan members containing '5' * $members = $redis->sscan('myset', $it, '*5*'); * foreach ($members as $member) { * echo "NORETRY: $member\n"; * $scanned++; * } * } while ($it != 0); * echo "TOTAL: $scanned\n"; * $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); * $scanned = 0; * $it = null; * // With Redis::SCAN_RETRY PhpRedis will never return an empty array * // when the cursor is non-zero * while (($members = $redis->sscan('myset', $it, '*5*'))) { * foreach ($members as $member) { * echo "RETRY: $member\n"; * $scanned++; * } * } */ public function sscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): array|false {} /** * Subscribes the client to the specified shard channels. * @param array $channels One or more channel names. * @param callable $cb The callback PhpRedis will invoke when we receive a message * from one of the subscribed channels. * @return bool True on success, false on faiilure. Note that this command will block the * client in a subscribe loop, waiting for messages to arrive. * @see https://redis.io/commands/ssubscribe * @example * $redis = new Redis(['host' => 'localhost']); * $redis->ssubscribe(['channel-1', 'channel-2'], function ($redis, $channel, $message) { * echo "[$channel]: $message\n"; * // Unsubscribe from the message channel when we read 'quit' * if ($message == 'quit') { * echo "Unsubscribing from '$channel'\n"; * $redis->sunsubscribe([$channel]); * } * }); * // Once we read 'quit' from both channel-1 and channel-2 the subscribe loop will be * // broken and this command will execute. * echo "Subscribe loop ended\n"; */ public function ssubscribe(array $channels, callable $cb): bool {} /** * Retrieve the length of a Redis STRING key. * @param string $key The key we want the length of. * @return Redis|int|false The length of the string key if it exists, zero if it does not, and * false on failure. * @see https://redis.io/commands/strlen * @example $redis->strlen('mykey'); */ public function strlen(string $key): Redis|int|false {} /** * Subscribe to one or more Redis pubsub channels. * @param array $channels One or more channel names. * @param callable $cb The callback PhpRedis will invoke when we receive a message * from one of the subscribed channels. * @return bool True on success, false on faiilure. Note that this command will block the * client in a subscribe loop, waiting for messages to arrive. * @see https://redis.io/commands/subscribe * @example * $redis = new Redis(['host' => 'localhost']); * $redis->subscribe(['channel-1', 'channel-2'], function ($redis, $channel, $message) { * echo "[$channel]: $message\n"; * // Unsubscribe from the message channel when we read 'quit' * if ($message == 'quit') { * echo "Unsubscribing from '$channel'\n"; * $redis->unsubscribe([$channel]); * } * }); * // Once we read 'quit' from both channel-1 and channel-2 the subscribe loop will be * // broken and this command will execute. * echo "Subscribe loop ended\n"; */ public function subscribe(array $channels, callable $cb): bool {} /** * Unsubscribes the client from the given shard channels, * or from all of them if none is given. * @param array $channels One or more channels to unsubscribe from. * @return Redis|array|bool The array of unsubscribed channels. * @see https://redis.io/commands/sunsubscribe * @see Redis::ssubscribe() * @example * $redis->ssubscribe(['channel-1', 'channel-2'], function ($redis, $channel, $message) { * if ($message == 'quit') { * echo "$channel => 'quit' detected, unsubscribing!\n"; * $redis->sunsubscribe([$channel]); * } else { * echo "$channel => $message\n"; * } * }); * echo "We've unsubscribed from both channels, exiting\n"; */ public function sunsubscribe(array $channels): Redis|array|bool {} /** * Atomically swap two Redis databases so that all of the keys in the source database will * now be in the destination database and vice-versa. * Note: This command simply swaps Redis' internal pointer to the database and is therefore * very fast, regardless of the size of the underlying databases. * @param int $src The source database number * @param int $dst The destination database number * @return Redis|bool Success if the databases could be swapped and false on failure. * @see https://redis.io/commands/swapdb * @see Redis::del() * @example * $redis->select(0); * $redis->set('db0-key', 'db0-value'); * $redis->swapdb(0, 1); * $redis->get('db0-key'); */ public function swapdb(int $src, int $dst): Redis|bool {} /** * Retrieve the server time from the connected Redis instance. * @see https://redis.io/commands/time * @return Redis|array A two element array consisting of a Unix Timestamp and the number of microseconds * elapsed since the second. * @example $redis->time(); */ public function time(): Redis|array {} /** * Get the amount of time a Redis key has before it will expire, in seconds. * @param string $key The Key we want the TTL for. * @return Redis|int|false (a) The number of seconds until the key expires, or -1 if the key has * no expiration, and -2 if the key does not exist. In the event of an * error, this command will return false. * @see https://redis.io/commands/ttl * @example $redis->ttl('mykey'); */ public function ttl(string $key): Redis|int|false {} /** * Get the type of a given Redis key. * @see https://redis.io/commands/type * @param string $key The key to check * @return Redis|int|false The Redis type constant or false on failure. * The Redis class defines several type constants that correspond with Redis key types. * Redis::REDIS_NOT_FOUND * Redis::REDIS_STRING * Redis::REDIS_SET * Redis::REDIS_LIST * Redis::REDIS_ZSET * Redis::REDIS_HASH * Redis::REDIS_STREAM * @example * foreach ($redis->keys('*') as $key) { * echo "$key => " . $redis->type($key) . "\n"; * } */ public function type(string $key): Redis|int|false {} /** * Delete one or more keys from the Redis database. Unlike this operation, the actual * deletion is asynchronous, meaning it is safe to delete large keys without fear of * Redis blocking for a long period of time. * @param array|string $key Either an array with one or more keys or a string with * the first key to delete. * @param string ...$other_keys If the first argument passed to this method was a string * you may pass any number of additional key names. * @return Redis|int|false The number of keys deleted or false on failure. * @see https://redis.io/commands/unlink * @see https://redis.io/commands/del * @see Redis::del() * @example $redis->unlink('key1', 'key2', 'key3'); * @example $redis->unlink(['key1', 'key2', 'key3']); */ public function unlink(array|string $key, string ...$other_keys): Redis|int|false {} /** * Unsubscribe from one or more subscribed channels. * @param array $channels One or more channels to unsubscribe from. * @return Redis|array|bool The array of unsubscribed channels. * @see https://redis.io/commands/unsubscribe * @see Redis::subscribe() * @example * $redis->subscribe(['channel-1', 'channel-2'], function ($redis, $channel, $message) { * if ($message == 'quit') { * echo "$channel => 'quit' detected, unsubscribing!\n"; * $redis->unsubscribe([$channel]); * } else { * echo "$channel => $message\n"; * } * }); * echo "We've unsubscribed from both channels, exiting\n"; */ public function unsubscribe(array $channels): Redis|array|bool {} /** * Remove any previously WATCH'ed keys in a transaction. * @see https://redis.io/commands/unwatch * @see https://redis.io/commands/unwatch * @see Redis::watch() * @return Redis|bool on success and false on failure. */ public function unwatch(): Redis|bool {} /** * Watch one or more keys for conditional execution of a transaction. * @param array|string $key Either an array with one or more key names, or a string key name * @param string ...$other_keys If the first argument was passed as a string, any number of additional * string key names may be passed variadically. * @return Redis|bool * @see https://redis.io/commands/watch * @see https://redis.io/commands/unwatch * @example * $redis1 = new Redis(['host' => 'localhost']); * $redis2 = new Redis(['host' => 'localhost']); * // Start watching 'incr-key' * $redis1->watch('incr-key'); * // Retrieve its value. * $val = $redis1->get('incr-key'); * // A second client modifies 'incr-key' after we read it. * $redis2->set('incr-key', 0); * // Because another client changed the value of 'incr-key' after we read it, this * // is no longer a proper increment operation, but because we are `WATCH`ing the * // key, this transaction will fail and we can try again. * // * // If were to comment out the above `$redis2->set('incr-key', 0)` line the * // transaction would succeed. * $redis1->multi(); * $redis1->set('incr-key', $val + 1); * $res = $redis1->exec(); * // bool(false) * var_dump($res); */ public function watch(array|string $key, string ...$other_keys): Redis|bool {} /** * Block the client up to the provided timeout until a certain number of replicas have confirmed * recieving them. * @see https://redis.io/commands/wait * @param int $numreplicas The number of replicas we want to confirm write operaions * @param int $timeout How long to wait (zero meaning forever). * @return int|false The number of replicas that have confirmed or false on failure. */ public function wait(int $numreplicas, int $timeout): int|false {} /** * Acknowledge one ore more messages that are pending (have been consumed using XREADGROUP but * not yet acknowledged by XACK.) * @param string $key The stream to query. * @param string $group The consumer group to use. * @param array $ids An array of stream entry IDs. * @return int|false The number of acknowledged messages * @see https://redis.io/commands/xack * @see https://redis.io/commands/xreadgroup * @see Redis::xack() * @example * $redis->xAdd('ships', '*', ['name' => 'Enterprise']); * $redis->xAdd('ships', '*', ['name' => 'Defiant']); * $redis->xGroup('CREATE', 'ships', 'Federation', '0-0'); * // Consume a single message with the consumer group 'Federation' * $ship = $redis->xReadGroup('Federation', 'Picard', ['ships' => '>'], 1); * /* Retrieve the ID of the message we read. * assert(isset($ship['ships'])); * $id = key($ship['ships']); * // The message we just read is now pending. * $res = $redis->xPending('ships', 'Federation')); * var_dump($res); * // We can tell Redis we were able to process the message by using XACK * $res = $redis->xAck('ships', 'Federation', [$id]); * assert($res === 1); * // The message should no longer be pending. * $res = $redis->xPending('ships', 'Federation'); * var_dump($res); */ public function xack(string $key, string $group, array $ids): int|false {} /** * Append a message to a stream. * @param string $key The stream name. * @param string $id The ID for the message we want to add. This can be the special value '*' * which means Redis will generate the ID that appends the message to the * end of the stream. It can also be a value in the form -* which will * generate an ID that appends to the end ot entries with the same value * (if any exist). * @param int $maxlen If specified Redis will append the new message but trim any number of the * oldest messages in the stream until the length is <= $maxlen. * @param bool $approx Used in conjunction with `$maxlen`, this flag tells Redis to trim the stream * but in a more efficient way, meaning the trimming may not be exactly to * `$maxlen` values. * @param bool $nomkstream If passed as `TRUE`, the stream must exist for Redis to append the message. * @see https://redis.io/commands/xadd * @example $redis->xAdd('ds9-season-1', '1-1', ['title' => 'Emissary Part 1']); * @example $redis->xAdd('ds9-season-1', '1-2', ['title' => 'A Man Alone']); */ public function xadd(string $key, string $id, array $values, int $maxlen = 0, bool $approx = false, bool $nomkstream = false): Redis|string|false {} /** * This command allows a consumer to claim pending messages that have been idle for a specified period of time. * Its purpose is to provide a mechanism for picking up messages that may have had a failed consumer. * @see https://redis.io/commands/xautoclaim * @see https://redis.io/commands/xclaim * @see https://redis.io/docs/data-types/streams-tutorial/ * @param string $key The stream to check. * @param string $group The consumer group to query. * @param string $consumer Which consumer to check. * @param int $min_idle The minimum time in milliseconds for the message to have been pending. * @param string $start The minimum message id to check. * @param int $count An optional limit on how many messages are returned. * @param bool $justid If the client only wants message IDs and not all of their data. * @return Redis|array|bool An array of pending IDs or false if there are none, or on failure. * @example * $redis->xGroup('CREATE', 'ships', 'combatants', '0-0', true); * $redis->xAdd('ships', '1424-74205', ['name' => 'Defiant']); * // Consume the ['name' => 'Defiant'] message * $msgs = $redis->xReadGroup('combatants', "Jem'Hadar", ['ships' => '>'], 1); * // The "Jem'Hadar" consumer has the message presently * $pending = $redis->xPending('ships', 'combatants'); * var_dump($pending); * // Asssume control of the pending message with a different consumer. * $res = $redis->xAutoClaim('ships', 'combatants', 'Sisko', 0, '0-0'); * // Now the 'Sisko' consumer owns the message * $pending = $redis->xPending('ships', 'combatants'); * var_dump($pending); */ public function xautoclaim(string $key, string $group, string $consumer, int $min_idle, string $start, int $count = -1, bool $justid = false): Redis|bool|array {} /** * This method allows a consumer to take ownership of pending stream entries, by ID. Another * command that does much the same thing but does not require passing specific IDs is `Redis::xAutoClaim`. * @see https://redis.io/commands/xclaim * @see https://redis.io/commands/xautoclaim. * @param string $key The stream we wish to claim messages for. * @param string $group Our consumer group. * @param string $consumer Our consumer. * @param int $min_idle The minimum idle-time in milliseconds a message must have for ownership to be transferred. * @param array $options An options array that modifies how the command operates. * * # Following is an options array describing every option you can pass. Note that * # 'IDLE', and 'TIME' are mutually exclusive. * $options = [ * 'IDLE' => 3 # Set the idle time of the message to a 3. By default * # the idle time is set to zero. * 'TIME' => 1000*time() # Same as IDLE except it takes a unix timestamp in * # milliseconds. * 'RETRYCOUNT' => 0 # Set the retry counter to zero. By default XCLAIM * # doesn't modify the counter. * 'FORCE' # Creates the pending message entry even if IDs are * # not already * # in the PEL with another client. * 'JUSTID' # Return only an array of IDs rather than the messages * # themselves. * ]; * * @return Redis|array|bool An array of claimed messags or false on failure. * @example * $redis->xGroup('CREATE', 'ships', 'combatants', '0-0', true); * $redis->xAdd('ships', '1424-74205', ['name' => 'Defiant']); * // Consume the ['name' => 'Defiant'] message * $msgs = $redis->xReadGroup('combatants', "Jem'Hadar", ['ships' => '>'], 1); * // The "Jem'Hadar" consumer has the message presently * $pending = $redis->xPending('ships', 'combatants'); * var_dump($pending); * assert($pending && isset($pending[1])); * // Claim the message by ID. * $claimed = $redis->xClaim('ships', 'combatants', 'Sisko', 0, [$pending[1]], ['JUSTID']); * var_dump($claimed); * // Now the 'Sisko' consumer owns the message * $pending = $redis->xPending('ships', 'combatants'); * var_dump($pending); */ public function xclaim(string $key, string $group, string $consumer, int $min_idle, array $ids, array $options): Redis|array|bool {} /** * Remove one or more specific IDs from a stream. * @param string $key The stream to modify. * @param array $ids One or more message IDs to remove. * @return Redis|int|false The number of messages removed or false on failure. * @example $redis->xDel('stream', ['1-1', '2-1', '3-1']); */ public function xdel(string $key, array $ids): Redis|int|false {} /** * XGROUP * Perform various operation on consumer groups for a particular Redis STREAM. What the command does * is primarily based on which operation is passed. * @see https://redis.io/commands/xgroup/ * @param string $operation The subcommand you intend to execute. Valid options are as follows * 'HELP' - Redis will return information about the command * Requires: none * 'CREATE' - Create a consumer group. * Requires: Key, group, consumer. * 'SETID' - Set the ID of an existing consumer group for the stream. * Requires: Key, group, id. * 'CREATECONSUMER' - Create a new consumer group for the stream. You must * also pass key, group, and the consumer name you wish to * create. * Requires: Key, group, consumer. * 'DELCONSUMER' - Delete a consumer from group attached to the stream. * Requires: Key, group, consumer. * 'DESTROY' - Delete a consumer group from a stream. * Requires: Key, group. * @param string|null $key The STREAM we're operating on. * @param string|null $group The consumer group we want to create/modify/delete. * @param string|null $id_or_consumer The STREAM id (e.g. '$') or consumer group. See the operation section * for information about which to send. * @param bool $mkstream This flag may be sent in combination with the 'CREATE' operation, and * cause Redis to also create the STREAM if it doesn't currently exist. * @param int $entries_read * @return mixed This command return various results depending on the operation performed. */ public function xgroup( string $operation, ?string $key = null, ?string $group = null, ?string $id_or_consumer = null, bool $mkstream = false, int $entries_read = -2 ): mixed {} /** * Retrieve information about a stream key. * @param string $operation The specific info operation to perform. * @param string|null $arg1 The first argument (depends on operation) * @param string|null $arg2 The second argument * @param int $count The COUNT argument to `XINFO STREAM` * @return mixed This command can return different things depending on the operation being called. * @see https://redis.io/commands/xinfo * @example $redis->xInfo('CONSUMERS', 'stream'); * @example $redis->xInfo('GROUPS', 'stream'); * @example $redis->xInfo('STREAM', 'stream'); */ public function xinfo(string $operation, ?string $arg1 = null, ?string $arg2 = null, int $count = -1): mixed {} /** * Get the number of messages in a Redis STREAM key. * @param string $key The Stream to check. * @return Redis|int|false The number of messages or false on failure. * @see https://redis.io/commands/xlen * @example $redis->xLen('stream'); */ public function xlen(string $key): Redis|int|false {} /** * Interact with stream messages that have been consumed by a consumer group but not yet * acknowledged with XACK. * @see https://redis.io/commands/xpending * @see https://redis.io/commands/xreadgroup * @param string $key The stream to inspect. * @param string $group The user group we want to see pending messages from. * @param string|null $start The minimum ID to consider. * @param string|null $end The maximum ID to consider. * @param int $count Optional maximum number of messages to return. * @param string|null $consumer If provided, limit the returned messages to a specific consumer. * @return Redis|array|false The pending messages belonging to the stream or false on failure. */ public function xpending(string $key, string $group, ?string $start = null, ?string $end = null, int $count = -1, ?string $consumer = null): Redis|array|false {} /** * Get a range of entries from a STREAM key. * @param string $key The stream key name to list. * @param string $start The minimum ID to return. * @param string $end The maximum ID to return. * @param int $count An optional maximum number of entries to return. * @return Redis|array|bool The entries in the stream within the requested range or false on failure. * @see https://redis.io/commands/xrange * @example $redis->xRange('stream', '0-1', '0-2'); * @example $redis->xRange('stream', '-', '+'); */ public function xrange(string $key, string $start, string $end, int $count = -1): Redis|array|bool {} /** * Consume one or more unconsumed elements in one or more streams. * @param array $streams An associative array with stream name keys and minimum id values. * @param int $count An optional limit to how many entries are returnd *per stream* * @param int $block An optional maximum number of milliseconds to block the caller if no * data is available on any of the provided streams. * @return Redis|array|bool An array of read elements or false if there aren't any. * @see https://redis.io/commands/xread * @example * $redis->xAdd('s03', '3-1', ['title' => 'The Search, Part I']); * $redis->xAdd('s03', '3-2', ['title' => 'The Search, Part II']); * $redis->xAdd('s03', '3-3', ['title' => 'The House Of Quark']); * $redis->xAdd('s04', '4-1', ['title' => 'The Way of the Warrior']); * $redis->xAdd('s04', '4-3', ['title' => 'The Visitor']); * $redis->xAdd('s04', '4-4', ['title' => 'Hippocratic Oath']); * $redis->xRead(['s03' => '3-2', 's04' => '4-1']); */ public function xread(array $streams, int $count = -1, int $block = -1): Redis|array|bool {} /** * Read one or more messages using a consumer group. * @param string $group The consumer group to use. * @param string $consumer The consumer to use. * @param array $streams An array of stream names and message IDs * @param int $count Optional maximum number of messages to return * @param int $block How long to block if there are no messages available. * @return Redis|array|bool Zero or more unread messages or false on failure. * @see https://redis.io/commands/xreadgroup * @example * $redis->xGroup('CREATE', 'episodes', 'ds9', '0-0', true); * $redis->xAdd('episodes', '1-1', ['title' => 'Emissary: Part 1']); * $redis->xAdd('episodes', '1-2', ['title' => 'A Man Alone']); * $messages = $redis->xReadGroup('ds9', 'sisko', ['episodes' => '>']); * // After having read the two messages, add another * $redis->xAdd('episodes', '1-3', ['title' => 'Emissary: Part 2']); * // Acknowledge the first two read messages * foreach ($messages as $stream => $stream_messages) { * $ids = array_keys($stream_messages); * $redis->xAck('stream', 'ds9', $ids); * } * // We can now pick up where we left off, and will only get the final message * $msgs = $redis->xReadGroup('ds9', 'sisko', ['episodes' => '>']); */ public function xreadgroup(string $group, string $consumer, array $streams, int $count = 1, int $block = 1): Redis|array|bool {} /** * Get a range of entries from a STREAM ke in reverse cronological order. * @param string $key The stream key to query. * @param string $end The maximum message ID to include. * @param string $start The minimum message ID to include. * @param int $count An optional maximum number of messages to include. * @return Redis|array|bool The entries within the requested range, from newest to oldest. * @see https://redis.io/commands/xrevrange * @see https://redis.io/commands/xrange * @example $redis->xRevRange('stream', '0-2', '0-1'); * @example $redis->xRevRange('stream', '+', '-'); */ public function xrevrange(string $key, string $end, string $start, int $count = -1): Redis|array|bool {} /** * Truncate a STREAM key in various ways. * @param string $key The STREAM key to trim. * @param string $threshold This can either be a maximum length, or a minimum id. * MAXLEN - An integer describing the maximum desired length of the stream after the command. * MINID - An ID that will become the new minimum ID in the stream, as Redis will trim all * messages older than this ID. * @param bool $approx Whether redis is allowed to do an approximate trimming of the stream. This is * more efficient for Redis given how streams are stored internally. * @param bool $minid When set to `true`, users should pass a minimum ID to the `$threshold` argument. * @param int $limit An optional upper bound on how many entries to trim during the command. * @return Redis|int|false The number of entries deleted from the stream. * @see https://redis.io/commands/xtrim * @example $redis->xTrim('stream', 3); * @example $redis->xTrim('stream', '2-1', false, true); */ public function xtrim(string $key, string $threshold, bool $approx = false, bool $minid = false, int $limit = -1): Redis|int|false {} /** * Add one or more elements and scores to a Redis sorted set. * @param string $key The sorted set in question. * @param array|float $score_or_options Either the score for the first element, or an array of options. * * $options = [ * 'NX', # Only update elements that already exist * 'NX', # Only add new elements but don't update existing ones. * 'LT' # Only update existing elements if the new score is * # less than the existing one. * 'GT' # Only update existing elements if the new score is * # greater than the existing one. * 'CH' # Instead of returning the number of elements added, * # Redis will return the number Of elements that were * # changed in the operation. * 'INCR' # Instead of setting each element to the provide score, * # increment the element by the * # provided score, much like ZINCRBY. When this option * # is passed, you may only send a single score and member. * ]; * Note: 'GX', 'LT', and 'NX' cannot be passed together, and PhpRedis * will send whichever one is last in the options array. * @param mixed $more_scores_and_mems A variadic number of additional scores and members. * @return Redis|int|float|false The return value varies depending on the options passed. * Following is information about the options that may be passed as the second argument: * @see https://redis.io/commands/zadd * @example $redis->zadd('zs', 1, 'first', 2, 'second', 3, 'third'); * @example $redis->zAdd('zs', ['XX'], 8, 'second', 99, 'new-element'); */ public function zAdd(string $key, array|float $score_or_options, mixed ...$more_scores_and_mems): Redis|int|float|false {} /** * Return the number of elements in a sorted set. * @param string $key The sorted set to retreive cardinality from. * @return Redis|int|false The number of elements in the set or false on failure * @see https://redis.io/commands/zcard * @example $redis->zCard('zs'); */ public function zCard(string $key): Redis|int|false {} /** * Count the number of members in a sorted set with scores inside a provided range. * @param string $key The sorted set to check. * @param string $start The minimum score to include in the count * @param string $end The maximum score to include in the count * NOTE: In addition to a floating point score you may pass the special values of '-inf' and * '+inf' meaning negative and positive infinity, respectively. * @see https://redis.io/commands/zcount * @example $redis->zCount('fruit-rankings', '0', '+inf'); * @example $redis->zCount('fruit-rankings', 50, 60); * @example $redis->zCount('fruit-rankings', '-inf', 0); */ public function zCount(string $key, string $start, string $end): Redis|int|false {} /** * Create or increment the score of a member in a Redis sorted set * @param string $key The sorted set in question. * @param float $value How much to increment the score. * @return Redis|float|false The new score of the member or false on failure. * @see https://redis.io/commands/zincrby * @example $redis->zIncrBy('zs', 5.0, 'bananas'); * @example $redis->zIncrBy('zs', 2.0, 'eggplants'); */ public function zIncrBy(string $key, float $value, mixed $member): Redis|float|false {} /** * Count the number of elements in a sorted set whos members fall within the provided * lexographical range. * @param string $key The sorted set to check. * @param string $min The minimum matching lexographical string * @param string $max The maximum matching lexographical string * @return Redis|int|false The number of members that fall within the range or false on failure. * @see https://redis.io/commands/zlexcount * @example * $redis->zAdd('captains', 0, 'Janeway', 0, 'Kirk', 0, 'Picard', 0, 'Sisko', 0, 'Archer'); * $redis->zLexCount('captains', '[A', '[S'); */ public function zLexCount(string $key, string $min, string $max): Redis|int|false {} /** * Retrieve the score of one or more members in a sorted set. * @see https://redis.io/commands/zmscore * @param string $key The sorted set * @param mixed $member The first member to return the score from * @param mixed $other_members One or more additional members to return the scores of. * @return Redis|array|false An array of the scores of the requested elements. * @example * $redis->zAdd('zs', 0, 'zero', 1, 'one', 2, 'two', 3, 'three'); * $redis->zMScore('zs', 'zero', 'two'); * $redis->zMScore('zs', 'one', 'not-a-member'); */ public function zMscore(string $key, mixed $member, mixed ...$other_members): Redis|array|false {} /** * Pop one or more of the highest scoring elements from a sorted set. * @param string $key The sorted set to pop elements from. * @param int|null $count An optional count of elements to pop. * @return Redis|array|false All of the popped elements with scores or false on fialure. * @see https://redis.io/commands/zpopmax * @example * $redis->zAdd('zs', 0, 'zero', 1, 'one', 2, 'two', 3, 'three'); * $redis->zPopMax('zs'); * $redis->zPopMax('zs', 2);. */ public function zPopMax(string $key, ?int $count = null): Redis|array|false {} /** * Pop one or more of the lowest scoring elements from a sorted set. * @param string $key The sorted set to pop elements from. * @param int|null $count An optional count of elements to pop. * @return Redis|array|false The popped elements with their scores or false on failure. * @see https://redis.io/commands/zpopmin * @example * $redis->zAdd('zs', 0, 'zero', 1, 'one', 2, 'two', 3, 'three'); * $redis->zPopMin('zs'); * $redis->zPopMin('zs', 2); */ public function zPopMin(string $key, ?int $count = null): Redis|array|false {} /** * Retrieve a range of elements of a sorted set between a start and end point. * How the command works in particular is greatly affected by the options that * are passed in. * @param string $key The sorted set in question. * @param mixed $start The starting index we want to return. * @param mixed $end The final index we want to return. * @param array|bool|null $options This value may either be an array of options to pass to * the command, or for historical purposes a boolean which * controls just the 'WITHSCORES' option. * * $options = [ * 'WITHSCORES' => true, # Return both scores and members. * 'LIMIT' => [10, 10], # Start at offset 10 and return 10 elements. * 'REV' # Return the elements in reverse order * 'BYSCORE', # Treat `start` and `end` as scores instead * 'BYLEX' # Treat `start` and `end` as lexicographical values. * ]; * * Note: 'BYLEX' and 'BYSCORE' are mutually exclusive. * @return Redis|array|false An array with matching elements or false on failure. * @see https://redis.io/commands/zrange/ * @example $redis->zRange('zset', 0, -1); * @example $redis->zRange('zset', '-inf', 'inf', ['byscore']); */ public function zRange(string $key, string|int $start, string|int $end, array|bool|null $options = null): Redis|array|false {} /** * Retrieve a range of elements from a sorted set by legographical range. * @param string $key The sorted set to retreive elements from * @param string $min The minimum legographical value to return * @param string $max The maximum legographical value to return * @param int $offset An optional offset within the matching values to return * @param int $count An optional count to limit the replies to (used in conjunction with offset) * @return Redis|array|false An array of matching elements or false on failure. * @see https://redis.io/commands/zrangebylex * @example * $redis = new Redis(['host' => 'localhost']); * $redis->zAdd('captains', 0, 'Janeway', 0, 'Kirk', 0, 'Picard', 0, 'Sisko', 0, 'Archer'); * $redis->zRangeByLex('captains', '[A', '[S'); * $redis->zRangeByLex('captains', '[A', '[S', 2, 2); */ public function zRangeByLex(string $key, string $min, string $max, int $offset = -1, int $count = -1): Redis|array|false {} /** * Retrieve a range of members from a sorted set by their score. * @param string $key The sorted set to query. * @param string $start The minimum score of elements that Redis should return. * @param string $end The maximum score of elements that Redis should return. * @param array $options Options that change how Redis will execute the command. * OPTION TYPE MEANING * 'WITHSCORES' bool Whether to also return scores. * 'LIMIT' [offset, count] Limit the reply to a subset of elements. * @return Redis|array|false The number of matching elements or false on failure. * @see https://redis.io/commands/zrangebyscore * @example $redis->zRangeByScore('zs', 20, 30, ['WITHSCORES' => true]); * @example $redis->zRangeByScore('zs', 20, 30, ['WITHSCORES' => true, 'LIMIT' => [5, 5]]); */ public function zRangeByScore(string $key, string $start, string $end, array $options = []): Redis|array|false {} /** * This command is similar to ZRANGE except that instead of returning the values directly * it will store them in a destination key provided by the user * @param string $dstkey The key to store the resulting element(s) * @param string $srckey The source key with element(s) to retrieve * @param string $start The starting index to store * @param string $end The ending index to store * @param array|bool|null $options Our options array that controls how the command will function. * @return Redis|int|false The number of elements stored in $dstkey or false on failure. * @see https://redis.io/commands/zrange/ * @see Redis::zRange * See {@link Redis::zRange} for a full description of the possible options. */ public function zrangestore( string $dstkey, string $srckey, string $start, string $end, array|bool|null $options = null ): Redis|int|false {} /** * Retrieve one or more random members from a Redis sorted set. * @param string $key The sorted set to pull random members from. * @param array|null $options One or more options that determine exactly how the command operates. * OPTION TYPE MEANING * 'COUNT' int The number of random members to return. * 'WITHSCORES' bool Whether to return scores and members instead of * @return Redis|string|array One ore more random elements. * @see https://redis.io/commands/zrandmember * @example $redis->zRandMember('zs', ['COUNT' => 2, 'WITHSCORES' => true]); */ public function zRandMember(string $key, ?array $options = null): Redis|string|array {} /** * Get the rank of a member of a sorted set, by score. * @param string $key The sorted set to check. * @param mixed $member The member to test. * @return Redis|int|false The rank of the requested member. * @see https://redis.io/commands/zrank * @example $redis->zRank('zs', 'zero'); * @example $redis->zRank('zs', 'three'); */ public function zRank(string $key, mixed $member): Redis|int|false {} /** * Remove one or more members from a Redis sorted set. * @param mixed $key The sorted set in question. * @param mixed $member The first member to remove. * @param mixed $other_members One or more members to remove passed in a variadic fashion. * @return Redis|int|false The number of members that were actually removed or false on failure. * @see https://redis.io/commands/zrem * @example $redis->zRem('zs', 'mem:0', 'mem:1', 'mem:2', 'mem:6', 'mem:7', 'mem:8', 'mem:9'); */ public function zRem(mixed $key, mixed $member, mixed ...$other_members): Redis|int|false {} /** * Remove zero or more elements from a Redis sorted set by legographical range. * @param string $key The sorted set to remove elements from. * @param string $min The start of the lexographical range to remove. * @param string $max The end of the lexographical range to remove * @return Redis|int|false The number of elements removed from the set or false on failure. * @see https://redis.io/commands/zremrangebylex * @see Redis::zrangebylex() * @example $redis->zRemRangeByLex('zs', '[a', '(b'); * @example $redis->zRemRangeByLex('zs', '(banana', '(eggplant'); */ public function zRemRangeByLex(string $key, string $min, string $max): Redis|int|false {} /** * Remove one or more members of a sorted set by their rank. * @param string $key The sorted set where we wnat to remove members. * @param int $start The rank when we want to start removing members * @param int $end The rank we want to stop removing membersk. * @return Redis|int|false The number of members removed from the set or false on failure. * @see https://redis.io/commands/zremrangebyrank * @example $redis->zRemRangeByRank('zs', 0, 3); */ public function zRemRangeByRank(string $key, int $start, int $end): Redis|int|false {} /** * Remove one or more members of a sorted set by their score. * @param string $key The sorted set where we wnat to remove members. * @param string $start The lowest score to remove. * @param string $end The highest score to remove. * @return Redis|int|false The number of members removed from the set or false on failure. * @see https://redis.io/commands/zremrangebyrank * @example * $redis->zAdd('zs', 2, 'two', 4, 'four', 6, 'six'); * $redis->zRemRangeByScore('zs', 2, 4); */ public function zRemRangeByScore(string $key, string $start, string $end): Redis|int|false {} /** * List the members of a Redis sorted set in reverse order * @param string $key The sorted set in question. * @param int $start The index to start listing elements * @param int $end The index to stop listing elements. * @param mixed $scores Whether or not Redis should also return each members score. See * the example below demonstrating how it may be used. * @return Redis|array|false The members (and possibly scores) of the matching elements or false * on failure. * @see https://redis.io/commands/zrevrange * @example $redis->zRevRange('zs', 0, -1); * @example $redis->zRevRange('zs', 2, 3); * @example $redis->zRevRange('zs', 0, -1, true); * @example $redis->zRevRange('zs', 0, -1, ['withscores' => true]); */ public function zRevRange(string $key, int $start, int $end, mixed $scores = null): Redis|array|false {} /** * List members of a Redis sorted set within a legographical range, in reverse order. * @param string $key The sorted set to list * @param string $max The maximum legographical element to include in the result. * @param string $min The minimum lexographical element to include in the result. * @param int $offset An option offset within the matching elements to start at. * @param int $count An optional count to limit the replies to. * @return Redis|array|false The matching members or false on failure. * @see https://redis.io/commands/zrevrangebylex * @see Redis::zrangebylex() * @example $redis->zRevRangeByLex('captains', '[Q', '[J'); * @example $redis->zRevRangeByLex('captains', '[Q', '[J', 1, 2); */ public function zRevRangeByLex(string $key, string $max, string $min, int $offset = -1, int $count = -1): Redis|array|false {} /** * List elements from a Redis sorted set by score, highest to lowest * @param string $key The sorted set to query. * @param string $max The highest score to include in the results. * @param string $min The lowest score to include in the results. * @param array|bool $options An options array that modifies how the command executes. * * $options = [ * 'WITHSCORES' => true|false # Whether or not to return scores * 'LIMIT' => [offset, count] # Return a subset of the matching members * ]; * * NOTE: For legacy reason, you may also simply pass `true` for the * options argument, to mean `WITHSCORES`. * @return Redis|array|false The matching members in reverse order of score or false on failure. * @see https://redis.io/commands/zrevrangebyscore * @example * $redis->zadd('oldest-people', 122.4493, 'Jeanne Calment', 119.2932, 'Kane Tanaka', * 119.2658, 'Sarah Knauss', 118.7205, 'Lucile Randon', * 117.7123, 'Nabi Tajima', 117.6301, 'Marie-Louise Meilleur', * 117.5178, 'Violet Brown', 117.3753, 'Emma Morano', * 117.2219, 'Chiyo Miyako', 117.0740, 'Misao Okawa'); * $redis->zRevRangeByScore('oldest-people', 122, 119); * $redis->zRevRangeByScore('oldest-people', 'inf', 118); * $redis->zRevRangeByScore('oldest-people', '117.5', '-inf', ['LIMIT' => [0, 1]]); */ public function zRevRangeByScore(string $key, string $max, string $min, array|bool $options = []): Redis|array|false {} /** * Retrieve a member of a sorted set by reverse rank. * @param string $key The sorted set to query. * @param mixed $member The member to look up. * @return Redis|int|false The reverse rank (the rank if counted high to low) of the member or * false on failure. * @see https://redis.io/commands/zrevrank * @example * $redis->zAdd('ds9-characters', 10, 'Sisko', 9, 'Garak', 8, 'Dax', 7, 'Odo'); * $redis->zrevrank('ds9-characters', 'Sisko'); * $redis->zrevrank('ds9-characters', 'Garak'); */ public function zRevRank(string $key, mixed $member): Redis|int|false {} /** * Get the score of a member of a sorted set. * @param string $key The sorted set to query. * @param mixed $member The member we wish to query. * @return Redis|float|false The score of the requested element or false if it is not found. * @see https://redis.io/commands/zscore * @example * $redis->zAdd('telescopes', 11.9, 'LBT', 10.4, 'GTC', 10, 'HET'); * $redis->zScore('telescopes', 'LBT'); */ public function zScore(string $key, mixed $member): Redis|float|false {} /** * Given one or more sorted set key names, return every element that is in the first * set but not any of the others. * @param array $keys One ore more sorted sets. * @param array|null $options An array which can contain ['WITHSCORES' => true] if you want Redis to * return members and scores. * @return Redis|array|false An array of members or false on failure. * @see https://redis.io/commands/zdiff * @example * $redis->zAdd('primes', 1, 'one', 3, 'three', 5, 'five'); * $redis->zAdd('evens', 2, 'two', 4, 'four'); * $redis->zAdd('mod3', 3, 'three', 6, 'six'); * $redis->zDiff(['primes', 'evens', 'mod3']); */ public function zdiff(array $keys, ?array $options = null): Redis|array|false {} /** * Store the difference of one or more sorted sets in a destination sorted set. * See {@link Redis::zdiff} for a more detailed description of how the diff operation works. * @param string $dst The destination set name. * @param array $keys One or more source key names * @return Redis|int|false The number of elements stored in the destination set or false on * failure. * @see https://redis.io/commands/zdiff * @see Redis::zdiff() */ public function zdiffstore(string $dst, array $keys): Redis|int|false {} /** * Compute the intersection of one or more sorted sets and return the members * @param array $keys One ore more sorted sets. * @param array|null $weights An optional array of weights to be applied to each set when performing * the intersection. * @param array|null $options Options for how Redis should combine duplicate elements when performing the * intersection. See Redis::zunion() for details. * @return Redis|array|false All of the members that exist in every set. * @see https://redis.io/commands/zinter * @example * $redis->zAdd('TNG', 2, 'Worf', 2.5, 'Data', 4.0, 'Picard'); * $redis->zAdd('DS9', 2.5, 'Worf', 3.0, 'Kira', 4.0, 'Sisko'); * $redis->zInter(['TNG', 'DS9']); * $redis->zInter(['TNG', 'DS9'], NULL, ['withscores' => true]); * $redis->zInter(['TNG', 'DS9'], NULL, ['withscores' => true, 'aggregate' => 'max']); */ public function zinter(array $keys, ?array $weights = null, ?array $options = null): Redis|array|false {} /** * Similar to ZINTER but instead of returning the intersected values, this command returns the * cardinality of the intersected set. * @see https://redis.io/commands/zintercard * @see https://redis.io/commands/zinter * @see Redis::zinter() * @param array $keys One ore more sorted set key names. * @param int $limit An optional upper bound on the returned cardinality. If set to a value * greater than zero, Redis will stop processing the intersection once the * resulting cardinality reaches this limit. * @return Redis|int|false The cardinality of the intersection or false on failure. * @example * $redis->zAdd('zs1', 1, 'one', 2, 'two', 3, 'three', 4, 'four'); * $redis->zAdd('zs2', 2, 'two', 4, 'four'); * $redis->zInterCard(['zs1', 'zs2']); */ public function zintercard(array $keys, int $limit = -1): Redis|int|false {} /** * Compute the intersection of one ore more sorted sets storing the result in a new sorted set. * @param string $dst The destination sorted set to store the intersected values. * @param array $keys One ore more sorted set key names. * @param array|null $weights An optional array of floats to weight each passed input set. * @param string|null $aggregate An optional aggregation method to use. * 'SUM' - Store sum of all intersected members (this is the default). * 'MIN' - Store minimum value for each intersected member. * 'MAX' - Store maximum value for each intersected member. * @return Redis|int|false The total number of members writtern to the destination set or false on failure. * @see https://redis.io/commands/zinterstore * @see https://redis.io/commands/zinter * @example * $redis->zAdd('zs1', 3, 'apples', 2, 'pears'); * $redis->zAdd('zs2', 4, 'pears', 3, 'bananas'); * $redis->zAdd('zs3', 2, 'figs', 3, 'pears'); * $redis->zInterStore('fruit-sum', ['zs1', 'zs2', 'zs3']); * $redis->zInterStore('fruit-max', ['zs1', 'zs2', 'zs3'], NULL, 'MAX'); */ public function zinterstore(string $dst, array $keys, ?array $weights = null, ?string $aggregate = null): Redis|int|false {} /** * Scan the members of a sorted set incrementally, using a cursor * @param string $key The sorted set to scan. * @param int|null $iterator A reference to an iterator that should be initialized to NULL initially, that * will be updated after each subsequent call to ZSCAN. Once the iterator * has returned to zero the scan is complete * @param string|null $pattern An optional glob-style pattern that limits which members are returned during * the scanning process. * @param int $count A hint for Redis that tells it how many elements it should test before returning * from the call. The higher the more work Redis may do in any one given call to * ZSCAN potentially blocking for longer periods of time. * @return Redis|array|false An array of elements or false on failure. * @see https://redis.io/commands/zscan * @see https://redis.io/commands/scan * @see Redis::scan() * NOTE: See Redis::scan() for detailed example code on how to call SCAN like commands. */ public function zscan(string $key, ?int &$iterator, ?string $pattern = null, int $count = 0): Redis|array|false {} /** * Retrieve the union of one or more sorted sets * @param array $keys One ore more sorted set key names * @param array|null $weights An optional array with floating point weights used when performing the union. * Note that if this argument is passed, it must contain the same number of * elements as the $keys array. * @param array|null $options An array that modifies how this command functions. * * $options = [ * # By default when members exist in more than one set Redis will SUM * # total score for each match. Instead, it can return the AVG, MIN, * # or MAX value based on this option. * 'AGGREGATE' => 'sum' | 'min' | 'max' * # Whether Redis should also return each members aggregated score. * 'WITHSCORES' => true | false * ] * * @return Redis|array|false The union of each sorted set or false on failure * @example * $redis->del('store1', 'store2', 'store3'); * $redis->zAdd('store1', 1, 'apples', 3, 'pears', 6, 'bananas'); * $redis->zAdd('store2', 3, 'apples', 5, 'coconuts', 2, 'bananas'); * $redis->zAdd('store3', 2, 'bananas', 6, 'apples', 4, 'figs'); * $redis->zUnion(['store1', 'store2', 'store3'], NULL, ['withscores' => true]); * $redis->zUnion(['store1', 'store3'], [2, .5], ['withscores' => true]); * $redis->zUnion(['store1', 'store3'], [2, .5], ['withscores' => true, 'aggregate' => 'MIN']); */ public function zunion(array $keys, ?array $weights = null, ?array $options = null): Redis|array|false {} /** * Perform a union on one or more Redis sets and store the result in a destination sorted set. * @param string $dst The destination set to store the union. * @param array $keys One or more input keys on which to perform our union. * @param array|null $weights An optional weights array used to weight each input set. * @param string|null $aggregate An optional modifier in how Redis will combine duplicate members. * Valid: 'MIN', 'MAX', 'SUM'. * @return Redis|int|false The number of members stored in the destination set or false on failure. * @see https://redis.io/commands/zunionstore * @see Redis::zunion() * @example * $redis->zAdd('zs1', 1, 'one', 3, 'three'); * $redis->zAdd('zs1', 2, 'two', 4, 'four'); * $redis->zadd('zs3', 1, 'one', 7, 'five'); * $redis->zUnionStore('dst', ['zs1', 'zs2', 'zs3']); */ public function zunionstore(string $dst, array $keys, ?array $weights = null, ?string $aggregate = null): Redis|int|false {} } class RedisException extends RuntimeException {} * $redis->info(); * */ public function info(): bool|array {} } * @link https://github.com/zgb7mtr/phpredis_cluster_phpdoc * * @method mixed eval($script, $args = array(), $numKeys = 0) */ class RedisCluster { public const AFTER = 'after'; public const BEFORE = 'before'; /** * Options */ public const OPT_SERIALIZER = 1; public const OPT_PREFIX = 2; public const OPT_READ_TIMEOUT = 3; public const OPT_SCAN = 4; public const OPT_SLAVE_FAILOVER = 5; /** * Cluster options */ public const FAILOVER_NONE = 0; public const FAILOVER_ERROR = 1; public const FAILOVER_DISTRIBUTE = 2; public const FAILOVER_DISTRIBUTE_SLAVES = 3; /** * SCAN options */ public const SCAN_NORETRY = 0; public const SCAN_RETRY = 1; /** * @since 5.3.0 */ public const SCAN_PREFIX = 2; /** * @since 5.3.0 */ public const SCAN_NOPREFIX = 3; /** * Serializers */ public const SERIALIZER_NONE = 0; public const SERIALIZER_PHP = 1; public const SERIALIZER_IGBINARY = 2; public const SERIALIZER_MSGPACK = 3; public const SERIALIZER_JSON = 4; /** * Multi */ public const ATOMIC = 0; public const MULTI = 1; public const PIPELINE = 2; /** * Type */ public const REDIS_NOT_FOUND = 0; public const REDIS_STRING = 1; public const REDIS_SET = 2; public const REDIS_LIST = 3; public const REDIS_ZSET = 4; public const REDIS_HASH = 5; /** * Creates a Redis Cluster client * * @param string|null $name * @param array|null $seeds * @param int|float $timeout * @param int|float $readTimeout * @param bool $persistent * @param mixed $auth * @param array|null $context * @throws RedisClusterException * * @example *
     * // Declaring a cluster with an array of seeds
     * $redisCluster = new RedisCluster(null,['127.0.0.1:6379']);
     *
     * // Loading a cluster configuration by name
     * // In order to load a named array, one must first define the seed nodes in redis.ini.
     * // The following lines would define the cluster 'mycluster', and be loaded automatically by phpredis.
     *
     * // # In redis.ini
     * // redis.clusters.seeds = "mycluster[]=localhost:7000&test[]=localhost:7001"
     * // redis.clusters.timeout = "mycluster=5"
     * // redis.clusters.read_timeout = "mycluster=10"
     * // redis.clusters.auth = "mycluster=password" OR ['user' => 'foo', 'pass' => 'bar] as example
     *
     * //Then, this cluster can be loaded by doing the following
     *
     * $redisClusterPro = new RedisCluster('mycluster');
     * $redisClusterDev = new RedisCluster('test');
     * 
*/ public function __construct($name, $seeds = null, $timeout = null, $readTimeout = null, $persistent = false, $auth = null, $context = null) {} /** * Disconnects from the RedisCluster instance, except when pconnect is used. */ public function close() {} /** * Get the value related to the specified key * * @param string $key * * @return string|false If key didn't exist, FALSE is returned. Otherwise, the value related to this key is * returned. * * @link https://redis.io/commands/get * @example *
     * $redisCluster->get('key');
     * 
*/ public function get($key) {} /** * Set the string value in argument as value of the key. * * @since If you're using Redis >= 2.6.12, you can pass extended options as explained in example * * @param string $key * @param string $value * @param int|array $timeout If you pass an integer, phpredis will redirect to SETEX, and will try to use Redis * >= 2.6.12 extended options if you pass an array with valid values. * * @return bool TRUE if the command is successful. * * @link https://redis.io/commands/set * @example *
     * // Simple key -> value set
     * $redisCluster->set('key', 'value');
     *
     * // Will redirect, and actually make an SETEX call
     * $redisCluster->set('key','value', 10);
     *
     * // Will set the key, if it doesn't exist, with a ttl of 10 seconds
     * $redisCluster->set('key', 'value', Array('nx', 'ex'=>10));
     *
     * // Will set a key, if it does exist, with a ttl of 1000 milliseconds
     * $redisCluster->set('key', 'value', Array('xx', 'px'=>1000));
     * 
*/ public function set($key, $value, $timeout = null) {} /** * Returns the values of all specified keys. * * For every key that does not hold a string value or does not exist, * the special value false is returned. Because of this, the operation never fails. * * @param array $array * * @return array * * @link https://redis.io/commands/mget * @example *
     * $redisCluster->del('x', 'y', 'z', 'h');    // remove x y z
     * $redisCluster->mset(array('x' => 'a', 'y' => 'b', 'z' => 'c'));
     * $redisCluster->hset('h', 'field', 'value');
     * var_dump($redisCluster->mget(array('x', 'y', 'z', 'h')));
     * // Output:
     * // array(3) {
     * // [0]=>
     * // string(1) "a"
     * // [1]=>
     * // string(1) "b"
     * // [2]=>
     * // string(1) "c"
     * // [3]=>
     * // bool(false)
     * // }
     * 
*/ public function mget(array $array) {} /** * Sets multiple key-value pairs in one atomic command. * MSETNX only returns TRUE if all the keys were set (see SETNX). * * @param array $array Pairs: array(key => value, ...) * * @return bool TRUE in case of success, FALSE in case of failure. * @link https://redis.io/commands/mset * @example *
     * $redisCluster->mset(array('key0' => 'value0', 'key1' => 'value1'));
     * var_dump($redisCluster->get('key0'));
     * var_dump($redisCluster->get('key1'));
     * // Output:
     * // string(6) "value0"
     * // string(6) "value1"
     * 
*/ public function mset(array $array) {} /** * @see mset() * * @param array $array * * @return int 1 (if the keys were set) or 0 (no key was set) * @link https://redis.io/commands/msetnx */ public function msetnx(array $array) {} /** * Remove specified keys. * * @param int|string|array $key1 An array of keys, or an undefined number of parameters, each a key: key1 key2 key3 * ... keyN * @param int|string ...$otherKeys * * @return int Number of keys deleted. * @link https://redis.io/commands/del * @example *
     * $redisCluster->set('key1', 'val1');
     * $redisCluster->set('key2', 'val2');
     * $redisCluster->set('key3', 'val3');
     * $redisCluster->set('key4', 'val4');
     * $redisCluster->del('key1', 'key2');          // return 2
     * $redisCluster->del(array('key3', 'key4'));   // return 2
     * 
*/ public function del($key1, ...$otherKeys) {} /** * Set the string value in argument as value of the key, with a time to live. * * @param string $key * @param int $ttl * @param mixed $value * * @return bool TRUE if the command is successful. * @link https://redis.io/commands/setex * @example *
     * $redisCluster->setex('key', 3600, 'value'); // sets key → value, with 1h TTL.
     * 
*/ public function setex($key, $ttl, $value) {} /** * PSETEX works exactly like SETEX with the sole difference that the expire time is specified in milliseconds * instead of seconds. * * @param string $key * @param int $ttl * @param string $value * * @return bool TRUE if the command is successful. * @link https://redis.io/commands/psetex * @example *
     * $redisCluster->psetex('key', 1000, 'value'); // sets key → value, with 1s TTL.
     * 
*/ public function psetex($key, $ttl, $value) {} /** * Set the string value in argument as value of the key if the key doesn't already exist in the database. * * @param string $key * @param string $value * * @return bool TRUE in case of success, FALSE in case of failure. * @link https://redis.io/commands/setnx * @example *
     * $redisCluster->setnx('key', 'value');   // return TRUE
     * $redisCluster->setnx('key', 'value');   // return FALSE
     * 
*/ public function setnx($key, $value) {} /** * Sets a value and returns the previous entry at that key. * * @param string $key * @param string $value * * @return string A string, the previous value located at this key. * @link https://redis.io/commands/getset * @example *
     * $redisCluster->set('x', '42');
     * $exValue = $redisCluster->getSet('x', 'lol');   // return '42', replaces x by 'lol'
     * $newValue = $redisCluster->get('x');            // return 'lol'
     * 
*/ public function getSet($key, $value) {} /** * Verify if the specified key exists. * * @param string $key * * @return bool If the key exists, return TRUE, otherwise return FALSE. * @link https://redis.io/commands/exists * @example *
     * $redisCluster->set('key', 'value');
     * $redisCluster->exists('key');               //  TRUE
     * $redisCluster->exists('NonExistingKey');    // FALSE
     * 
*/ public function exists($key) {} /** * Returns the keys that match a certain pattern. * * @param string $pattern pattern, using '*' as a wildcard. * * @return array of STRING: The keys that match a certain pattern. * @link https://redis.io/commands/keys * @example *
     * $allKeys = $redisCluster->keys('*');   // all keys will match this.
     * $keyWithUserPrefix = $redisCluster->keys('user*');
     * 
*/ public function keys($pattern) {} /** * Returns the type of data pointed by a given key. * * @param string $key * * @return int * * Depending on the type of the data pointed by the key, * this method will return the following value: * - string: RedisCluster::REDIS_STRING * - set: RedisCluster::REDIS_SET * - list: RedisCluster::REDIS_LIST * - zset: RedisCluster::REDIS_ZSET * - hash: RedisCluster::REDIS_HASH * - other: RedisCluster::REDIS_NOT_FOUND * @link https://redis.io/commands/type * @example $redisCluster->type('key'); */ public function type($key) {} /** * Returns and removes the first element of the list. * * @param string $key * * @return string|false if command executed successfully BOOL FALSE in case of failure (empty list) * @link https://redis.io/commands/lpop * @example *
     * $redisCluster->rPush('key1', 'A');
     * $redisCluster->rPush('key1', 'B');
     * $redisCluster->rPush('key1', 'C');
     * var_dump( $redisCluster->lRange('key1', 0, -1) );
     * // Output:
     * // array(3) {
     * //   [0]=> string(1) "A"
     * //   [1]=> string(1) "B"
     * //   [2]=> string(1) "C"
     * // }
     * $redisCluster->lPop('key1');
     * var_dump( $redisCluster->lRange('key1', 0, -1) );
     * // Output:
     * // array(2) {
     * //   [0]=> string(1) "B"
     * //   [1]=> string(1) "C"
     * // }
     * 
*/ public function lPop($key) {} /** * Returns and removes the last element of the list. * * @param string $key * * @return string|false if command executed successfully BOOL FALSE in case of failure (empty list) * @link https://redis.io/commands/rpop * @example *
     * $redisCluster->rPush('key1', 'A');
     * $redisCluster->rPush('key1', 'B');
     * $redisCluster->rPush('key1', 'C');
     * var_dump( $redisCluster->lRange('key1', 0, -1) );
     * // Output:
     * // array(3) {
     * //   [0]=> string(1) "A"
     * //   [1]=> string(1) "B"
     * //   [2]=> string(1) "C"
     * // }
     * $redisCluster->rPop('key1');
     * var_dump( $redisCluster->lRange('key1', 0, -1) );
     * // Output:
     * // array(2) {
     * //   [0]=> string(1) "A"
     * //   [1]=> string(1) "B"
     * // }
     * 
*/ public function rPop($key) {} /** * Set the list at index with the new value. * * @param string $key * @param int $index * @param string $value * * @return bool TRUE if the new value is setted. FALSE if the index is out of range, or data type identified by key * is not a list. * @link https://redis.io/commands/lset * @example *
     * $redisCluster->rPush('key1', 'A');
     * $redisCluster->rPush('key1', 'B');
     * $redisCluster->rPush('key1', 'C');  // key1 => [ 'A', 'B', 'C' ]
     * $redisCluster->lGet('key1', 0);     // 'A'
     * $redisCluster->lSet('key1', 0, 'X');
     * $redisCluster->lGet('key1', 0);     // 'X'
     * 
*/ public function lSet($key, $index, $value) {} /** * Removes and returns a random element from the set value at Key. * * @param string $key * * @return string "popped" value * bool FALSE if set identified by key is empty or doesn't exist. * @link https://redis.io/commands/spop * @example *
     * $redisCluster->sAdd('key1' , 'set1');
     * $redisCluster->sAdd('key1' , 'set2');
     * $redisCluster->sAdd('key1' , 'set3');
     * var_dump($redisCluster->sMembers('key1'));// 'key1' => {'set3', 'set1', 'set2'}
     * $redisCluster->sPop('key1');// 'set1'
     * var_dump($redisCluster->sMembers('key1'));// 'key1' => {'set3', 'set2'}
     * $redisCluster->sPop('key1');// 'set3',
     * var_dump($redisCluster->sMembers('key1'));// 'key1' => {'set2'}
     * 
*/ public function sPop($key) {} /** * Adds the string values to the head (left) of the list. Creates the list if the key didn't exist. * If the key exists and is not a list, FALSE is returned. * * @param string $key * @param string $value1 String, value to push in key * @param string $value2 Optional * @param string $valueN Optional * * @return int|false The new length of the list in case of success, FALSE in case of Failure. * @link https://redis.io/commands/lpush * @example *
     * $redisCluster->lPush('l', 'v1', 'v2', 'v3', 'v4')   // int(4)
     * var_dump( $redisCluster->lRange('l', 0, -1) );
     * //// Output:
     * // array(4) {
     * //   [0]=> string(2) "v4"
     * //   [1]=> string(2) "v3"
     * //   [2]=> string(2) "v2"
     * //   [3]=> string(2) "v1"
     * // }
     * 
*/ public function lPush($key, $value1, $value2 = null, $valueN = null) {} /** * Adds the string values to the tail (right) of the list. Creates the list if the key didn't exist. * If the key exists and is not a list, FALSE is returned. * * @param string $key * @param string $value1 String, value to push in key * @param string $value2 Optional * @param string $valueN Optional * * @return int|false The new length of the list in case of success, FALSE in case of Failure. * @link https://redis.io/commands/rpush * @example *
     * $redisCluster->rPush('r', 'v1', 'v2', 'v3', 'v4');    // int(4)
     * var_dump( $redisCluster->lRange('r', 0, -1) );
     * //// Output:
     * // array(4) {
     * //   [0]=> string(2) "v1"
     * //   [1]=> string(2) "v2"
     * //   [2]=> string(2) "v3"
     * //   [3]=> string(2) "v4"
     * // }
     * 
*/ public function rPush($key, $value1, $value2 = null, $valueN = null) {} /** * BLPOP is a blocking list pop primitive. * It is the blocking version of LPOP because it blocks the connection when * there are no elements to pop from any of the given lists. * An element is popped from the head of the first list that is non-empty, * with the given keys being checked in the order that they are given. * * @param array $keys Array containing the keys of the lists * Or STRING Key1 STRING Key2 STRING Key3 ... STRING Keyn * @param int $timeout Timeout * * @return array array('listName', 'element') * @link https://redis.io/commands/blpop * @example *
     * // Non blocking feature
     * $redisCluster->lPush('key1', 'A');
     * $redisCluster->del('key2');
     *
     * $redisCluster->blPop('key1', 'key2', 10); // array('key1', 'A')
     * // OR
     * $redisCluster->blPop(array('key1', 'key2'), 10); // array('key1', 'A')
     *
     * $redisCluster->brPop('key1', 'key2', 10); // array('key1', 'A')
     * // OR
     * $redisCluster->brPop(array('key1', 'key2'), 10); // array('key1', 'A')
     *
     * // Blocking feature
     *
     * // process 1
     * $redisCluster->del('key1');
     * $redisCluster->blPop('key1', 10);
     * // blocking for 10 seconds
     *
     * // process 2
     * $redisCluster->lPush('key1', 'A');
     *
     * // process 1
     * // array('key1', 'A') is returned
     * 
*/ public function blPop(array $keys, $timeout) {} /** * BRPOP is a blocking list pop primitive. * It is the blocking version of RPOP because it blocks the connection when * there are no elements to pop from any of the given lists. * An element is popped from the tail of the first list that is non-empty, * with the given keys being checked in the order that they are given. * See the BLPOP documentation(https://redis.io/commands/blpop) for the exact semantics, * since BRPOP is identical to BLPOP with the only difference being that * it pops elements from the tail of a list instead of popping from the head. * * @param array $keys Array containing the keys of the lists * Or STRING Key1 STRING Key2 STRING Key3 ... STRING Keyn * @param int $timeout Timeout * * @return array array('listName', 'element') * @link https://redis.io/commands/brpop * @example *
     * // Non blocking feature
     * $redisCluster->lPush('key1', 'A');
     * $redisCluster->del('key2');
     *
     * $redisCluster->blPop('key1', 'key2', 10); // array('key1', 'A')
     * // OR
     * $redisCluster->blPop(array('key1', 'key2'), 10); // array('key1', 'A')
     *
     * $redisCluster->brPop('key1', 'key2', 10); // array('key1', 'A')
     * // OR
     * $redisCluster->brPop(array('key1', 'key2'), 10); // array('key1', 'A')
     *
     * // Blocking feature
     *
     * // process 1
     * $redisCluster->del('key1');
     * $redisCluster->blPop('key1', 10);
     * // blocking for 10 seconds
     *
     * // process 2
     * $redisCluster->lPush('key1', 'A');
     *
     * // process 1
     * // array('key1', 'A') is returned
     * 
*/ public function brPop(array $keys, $timeout) {} /** * Adds the string value to the tail (right) of the list if the ist exists. FALSE in case of Failure. * * @param string $key * @param string $value String, value to push in key * * @return int|false The new length of the list in case of success, FALSE in case of Failure. * @link https://redis.io/commands/rpushx * @example *
     * $redisCluster->del('key1');
     * $redisCluster->rPushx('key1', 'A'); // returns 0
     * $redisCluster->rPush('key1', 'A'); // returns 1
     * $redisCluster->rPushx('key1', 'B'); // returns 2
     * $redisCluster->rPushx('key1', 'C'); // returns 3
     * // key1 now points to the following list: [ 'A', 'B', 'C' ]
     * 
*/ public function rPushx($key, $value) {} /** * Adds the string value to the head (left) of the list if the list exists. * * @param string $key * @param string $value String, value to push in key * * @return int|false The new length of the list in case of success, FALSE in case of Failure. * @link https://redis.io/commands/lpushx * @example *
     * $redisCluster->del('key1');
     * $redisCluster->lPushx('key1', 'A');     // returns 0
     * $redisCluster->lPush('key1', 'A');      // returns 1
     * $redisCluster->lPushx('key1', 'B');     // returns 2
     * $redisCluster->lPushx('key1', 'C');     // returns 3
     * // key1 now points to the following list: [ 'C', 'B', 'A' ]
     * 
*/ public function lPushx($key, $value) {} /** * Insert value in the list before or after the pivot value. the parameter options * specify the position of the insert (before or after). If the list didn't exists, * or the pivot didn't exists, the value is not inserted. * * @param string $key * @param string $position RedisCluster::BEFORE | RedisCluster::AFTER * @param string $pivot * @param string $value * * @return int The number of the elements in the list, -1 if the pivot didn't exists. * @link https://redis.io/commands/linsert * @example *
     * $redisCluster->del('key1');
     * $redisCluster->lInsert('key1', RedisCluster::AFTER, 'A', 'X');    // 0
     *
     * $redisCluster->lPush('key1', 'A');
     * $redisCluster->lPush('key1', 'B');
     * $redisCluster->lPush('key1', 'C');
     *
     * $redisCluster->lInsert('key1', RedisCluster::BEFORE, 'C', 'X');   // 4
     * $redisCluster->lRange('key1', 0, -1);                      // array('X', 'C', 'B', 'A')
     *
     * $redisCluster->lInsert('key1', RedisCluster::AFTER, 'C', 'Y');    // 5
     * $redisCluster->lRange('key1', 0, -1);                      // array('X', 'C', 'Y', 'B', 'A')
     *
     * $redisCluster->lInsert('key1', RedisCluster::AFTER, 'W', 'value'); // -1
     * 
*/ public function lInsert($key, $position, $pivot, $value) {} /** * Return the specified element of the list stored at the specified key. * 0 the first element, 1 the second ... -1 the last element, -2 the penultimate ... * Return FALSE in case of a bad index or a key that doesn't point to a list. * * @param string $key * @param int $index * * @return string|false the element at this index * Bool FALSE if the key identifies a non-string data type, or no value corresponds to this index in the list Key. * @link https://redis.io/commands/lindex * @example *
     * $redisCluster->rPush('key1', 'A');
     * $redisCluster->rPush('key1', 'B');
     * $redisCluster->rPush('key1', 'C');  // key1 => [ 'A', 'B', 'C' ]
     * $redisCluster->lGet('key1', 0);     // 'A'
     * $redisCluster->lGet('key1', -1);    // 'C'
     * $redisCluster->lGet('key1', 10);    // `FALSE`
     * 
*/ public function lIndex($key, $index) {} /** * Removes the first count occurrences of the value element from the list. * If count is zero, all the matching elements are removed. If count is negative, * elements are removed from tail to head. * * @param string $key * @param string $value * @param int $count * * @return int the number of elements to remove * bool FALSE if the value identified by key is not a list. * @link https://redis.io/commands/lrem * @example *
     * $redisCluster->lPush('key1', 'A');
     * $redisCluster->lPush('key1', 'B');
     * $redisCluster->lPush('key1', 'C');
     * $redisCluster->lPush('key1', 'A');
     * $redisCluster->lPush('key1', 'A');
     *
     * $redisCluster->lRange('key1', 0, -1);   // array('A', 'A', 'C', 'B', 'A')
     * $redisCluster->lRem('key1', 'A', 2);    // 2
     * $redisCluster->lRange('key1', 0, -1);   // array('C', 'B', 'A')
     * 
*/ public function lRem($key, $value, $count) {} /** * A blocking version of rpoplpush, with an integral timeout in the third parameter. * * @param string $srcKey * @param string $dstKey * @param int $timeout * * @return string|false The element that was moved in case of success, FALSE in case of timeout. * @link https://redis.io/commands/brpoplpush */ public function brpoplpush($srcKey, $dstKey, $timeout) {} /** * Pops a value from the tail of a list, and pushes it to the front of another list. * Also return this value. * * @since redis >= 1.2 * * @param string $srcKey * @param string $dstKey * * @return string|false The element that was moved in case of success, FALSE in case of failure. * @link https://redis.io/commands/rpoplpush * @example *
     * $redisCluster->del('x', 'y');
     *
     * $redisCluster->lPush('x', 'abc');
     * $redisCluster->lPush('x', 'def');
     * $redisCluster->lPush('y', '123');
     * $redisCluster->lPush('y', '456');
     *
     * // move the last of x to the front of y.
     * var_dump($redisCluster->rpoplpush('x', 'y'));
     * var_dump($redisCluster->lRange('x', 0, -1));
     * var_dump($redisCluster->lRange('y', 0, -1));
     *
     * ////Output:
     * //
     * //string(3) "abc"
     * //array(1) {
     * //  [0]=>
     * //  string(3) "def"
     * //}
     * //array(3) {
     * //  [0]=>
     * //  string(3) "abc"
     * //  [1]=>
     * //  string(3) "456"
     * //  [2]=>
     * //  string(3) "123"
     * //}
     * 
*/ public function rpoplpush($srcKey, $dstKey) {} /** * Returns the size of a list identified by Key. If the list didn't exist or is empty, * the command returns 0. If the data type identified by Key is not a list, the command return FALSE. * * @param string $key * * @return int The size of the list identified by Key exists. * bool FALSE if the data type identified by Key is not list * @link https://redis.io/commands/llen * @example *
     * $redisCluster->rPush('key1', 'A');
     * $redisCluster->rPush('key1', 'B');
     * $redisCluster->rPush('key1', 'C');  // key1 => [ 'A', 'B', 'C' ]
     * $redisCluster->lLen('key1');       // 3
     * $redisCluster->rPop('key1');
     * $redisCluster->lLen('key1');       // 2
     * 
*/ public function lLen($key) {} /** * Returns the set cardinality (number of elements) of the set stored at key. * * @param string $key * * @return int the cardinality (number of elements) of the set, or 0 if key does not exist. * @link https://redis.io/commands/scard * @example *
     * $redisCluster->sAdd('key1' , 'set1');
     * $redisCluster->sAdd('key1' , 'set2');
     * $redisCluster->sAdd('key1' , 'set3');   // 'key1' => {'set1', 'set2', 'set3'}
     * $redisCluster->sCard('key1');           // 3
     * $redisCluster->sCard('keyX');           // 0
     * 
*/ public function sCard($key) {} /** * Returns all the members of the set value stored at key. * This has the same effect as running SINTER with one argument key. * * @param string $key * * @return array All elements of the set. * @link https://redis.io/commands/smembers * @example *
     * $redisCluster->del('s');
     * $redisCluster->sAdd('s', 'a');
     * $redisCluster->sAdd('s', 'b');
     * $redisCluster->sAdd('s', 'a');
     * $redisCluster->sAdd('s', 'c');
     * var_dump($redisCluster->sMembers('s'));
     *
     * ////Output:
     * //
     * //array(3) {
     * //  [0]=>
     * //  string(1) "b"
     * //  [1]=>
     * //  string(1) "c"
     * //  [2]=>
     * //  string(1) "a"
     * //}
     * // The order is random and corresponds to redis' own internal representation of the set structure.
     * 
*/ public function sMembers($key) {} /** * Returns if member is a member of the set stored at key. * * @param string $key * @param string $value * * @return bool TRUE if value is a member of the set at key key, FALSE otherwise. * @link https://redis.io/commands/sismember * @example *
     * $redisCluster->sAdd('key1' , 'set1');
     * $redisCluster->sAdd('key1' , 'set2');
     * $redisCluster->sAdd('key1' , 'set3'); // 'key1' => {'set1', 'set2', 'set3'}
     *
     * $redisCluster->sIsMember('key1', 'set1'); // TRUE
     * $redisCluster->sIsMember('key1', 'setX'); // FALSE
     * 
*/ public function sIsMember($key, $value) {} /** * Adds a values to the set value stored at key. * If this value is already in the set, FALSE is returned. * * @param string $key Required key * @param mixed $value1 Required value * @param mixed $value2 Optional value * @param mixed $valueN Optional value * * @return int|false The number of elements added to the set * @link https://redis.io/commands/sadd * @example *
     * $redisCluster->sAdd('k', 'v1');                // int(1)
     * $redisCluster->sAdd('k', 'v1', 'v2', 'v3');    // int(2)
     * 
*/ public function sAdd($key, $value1, $value2 = null, $valueN = null) {} /** * Adds a values to the set value stored at key. * If this value is already in the set, FALSE is returned. * * @param string $key Required key * @param array $valueArray * * @return int|false The number of elements added to the set * @example *
     * $redisCluster->sAddArray('k', ['v1', 'v2', 'v3']);
     * //This is a feature in php only. Same as $redisCluster->sAdd('k', 'v1', 'v2', 'v3');
     * 
*/ public function sAddArray($key, array $valueArray) {} /** * Removes the specified members from the set value stored at key. * * @param string $key * @param string $member1 * @param string $member2 * @param string $memberN * * @return int The number of elements removed from the set. * @link https://redis.io/commands/srem * @example *
     * var_dump( $redisCluster->sAdd('k', 'v1', 'v2', 'v3') );    // int(3)
     * var_dump( $redisCluster->sRem('k', 'v2', 'v3') );          // int(2)
     * var_dump( $redisCluster->sMembers('k') );
     * //// Output:
     * // array(1) {
     * //   [0]=> string(2) "v1"
     * // }
     * 
*/ public function sRem($key, $member1, $member2 = null, $memberN = null) {} /** * Performs the union between N sets and returns it. * * @param string $key1 Any number of keys corresponding to sets in redis. * @param string $key2 ... * @param string $keyN ... * * @return array of strings: The union of all these sets. * @link https://redis.io/commands/sunionstore * @example *
     * $redisCluster->del('s0', 's1', 's2');
     *
     * $redisCluster->sAdd('s0', '1');
     * $redisCluster->sAdd('s0', '2');
     * $redisCluster->sAdd('s1', '3');
     * $redisCluster->sAdd('s1', '1');
     * $redisCluster->sAdd('s2', '3');
     * $redisCluster->sAdd('s2', '4');
     *
     * var_dump($redisCluster->sUnion('s0', 's1', 's2'));
     *
     * //// Output:
     * //
     * //array(4) {
     * //  [0]=>
     * //  string(1) "3"
     * //  [1]=>
     * //  string(1) "4"
     * //  [2]=>
     * //  string(1) "1"
     * //  [3]=>
     * //  string(1) "2"
     * //}
     * 
*/ public function sUnion($key1, $key2, $keyN = null) {} /** * Performs the same action as sUnion, but stores the result in the first key * * @param string $dstKey the key to store the diff into. * @param string $key1 Any number of keys corresponding to sets in redis. * @param string $key2 ... * @param string $keyN ... * * @return int Any number of keys corresponding to sets in redis. * @link https://redis.io/commands/sunionstore * @example *
     * $redisCluster->del('s0', 's1', 's2');
     *
     * $redisCluster->sAdd('s0', '1');
     * $redisCluster->sAdd('s0', '2');
     * $redisCluster->sAdd('s1', '3');
     * $redisCluster->sAdd('s1', '1');
     * $redisCluster->sAdd('s2', '3');
     * $redisCluster->sAdd('s2', '4');
     *
     * var_dump($redisCluster->sUnionStore('dst', 's0', 's1', 's2'));
     * var_dump($redisCluster->sMembers('dst'));
     *
     * //// Output:
     * //
     * //int(4)
     * //array(4) {
     * //  [0]=>
     * //  string(1) "3"
     * //  [1]=>
     * //  string(1) "4"
     * //  [2]=>
     * //  string(1) "1"
     * //  [3]=>
     * //  string(1) "2"
     * //}
     * 
*/ public function sUnionStore($dstKey, $key1, $key2, $keyN = null) {} /** * Returns the members of a set resulting from the intersection of all the sets * held at the specified keys. If just a single key is specified, then this command * produces the members of this set. If one of the keys is missing, FALSE is returned. * * @param string $key1 keys identifying the different sets on which we will apply the intersection. * @param string $key2 ... * @param string $keyN ... * * @return array contain the result of the intersection between those keys. * If the intersection between the different sets is empty, the return value will be empty array. * @link https://redis.io/commands/sinterstore * @example *
     * $redisCluster->sAdd('key1', 'val1');
     * $redisCluster->sAdd('key1', 'val2');
     * $redisCluster->sAdd('key1', 'val3');
     * $redisCluster->sAdd('key1', 'val4');
     *
     * $redisCluster->sAdd('key2', 'val3');
     * $redisCluster->sAdd('key2', 'val4');
     *
     * $redisCluster->sAdd('key3', 'val3');
     * $redisCluster->sAdd('key3', 'val4');
     *
     * var_dump($redisCluster->sInter('key1', 'key2', 'key3'));
     *
     * // Output:
     * //
     * //array(2) {
     * //  [0]=>
     * //  string(4) "val4"
     * //  [1]=>
     * //  string(4) "val3"
     * //}
     * 
*/ public function sInter($key1, $key2, $keyN = null) {} /** * Performs a sInter command and stores the result in a new set. * * @param string $dstKey the key to store the diff into. * @param string $key1 are intersected as in sInter. * @param string $key2 ... * @param string $keyN ... * * @return int|false The cardinality of the resulting set, or FALSE in case of a missing key. * @link https://redis.io/commands/sinterstore * @example *
     * $redisCluster->sAdd('key1', 'val1');
     * $redisCluster->sAdd('key1', 'val2');
     * $redisCluster->sAdd('key1', 'val3');
     * $redisCluster->sAdd('key1', 'val4');
     *
     * $redisCluster->sAdd('key2', 'val3');
     * $redisCluster->sAdd('key2', 'val4');
     *
     * $redisCluster->sAdd('key3', 'val3');
     * $redisCluster->sAdd('key3', 'val4');
     *
     * var_dump($redisCluster->sInterStore('output', 'key1', 'key2', 'key3'));
     * var_dump($redisCluster->sMembers('output'));
     *
     * //// Output:
     * //
     * //int(2)
     * //array(2) {
     * //  [0]=>
     * //  string(4) "val4"
     * //  [1]=>
     * //  string(4) "val3"
     * //}
     * 
*/ public function sInterStore($dstKey, $key1, $key2, $keyN = null) {} /** * Performs the difference between N sets and returns it. * * @param string $key1 Any number of keys corresponding to sets in redis. * @param string $key2 ... * @param string $keyN ... * * @return array of strings: The difference of the first set will all the others. * @link https://redis.io/commands/sdiff * @example *
     * $redisCluster->del('s0', 's1', 's2');
     *
     * $redisCluster->sAdd('s0', '1');
     * $redisCluster->sAdd('s0', '2');
     * $redisCluster->sAdd('s0', '3');
     * $redisCluster->sAdd('s0', '4');
     *
     * $redisCluster->sAdd('s1', '1');
     * $redisCluster->sAdd('s2', '3');
     *
     * var_dump($redisCluster->sDiff('s0', 's1', 's2'));
     *
     * //// Output:
     * //
     * //array(2) {
     * //  [0]=>
     * //  string(1) "4"
     * //  [1]=>
     * //  string(1) "2"
     * //}
     * 
*/ public function sDiff($key1, $key2, $keyN = null) {} /** * Performs the same action as sDiff, but stores the result in the first key * * @param string $dstKey the key to store the diff into. * @param string $key1 Any number of keys corresponding to sets in redis * @param string $key2 ... * @param string $keyN ... * * @return int|false The cardinality of the resulting set, or FALSE in case of a missing key. * @link https://redis.io/commands/sdiffstore * @example *
     * $redisCluster->del('s0', 's1', 's2');
     *
     * $redisCluster->sAdd('s0', '1');
     * $redisCluster->sAdd('s0', '2');
     * $redisCluster->sAdd('s0', '3');
     * $redisCluster->sAdd('s0', '4');
     *
     * $redisCluster->sAdd('s1', '1');
     * $redisCluster->sAdd('s2', '3');
     *
     * var_dump($redisCluster->sDiffStore('dst', 's0', 's1', 's2'));
     * var_dump($redisCluster->sMembers('dst'));
     *
     * //// Output:
     * //
     * //int(2)
     * //array(2) {
     * //  [0]=>
     * //  string(1) "4"
     * //  [1]=>
     * //  string(1) "2"
     * //}
     * 
*/ public function sDiffStore($dstKey, $key1, $key2, $keyN = null) {} /** * Returns a random element(s) from the set value at Key, without removing it. * * @param string $key * @param int $count [optional] * * @return string|array value(s) from the set * bool FALSE if set identified by key is empty or doesn't exist and count argument isn't passed. * @link https://redis.io/commands/srandmember * @example *
     * $redisCluster->sAdd('key1' , 'one');
     * $redisCluster->sAdd('key1' , 'two');
     * $redisCluster->sAdd('key1' , 'three');              // 'key1' => {'one', 'two', 'three'}
     *
     * var_dump( $redisCluster->sRandMember('key1') );     // 'key1' => {'one', 'two', 'three'}
     *
     * // string(5) "three"
     *
     * var_dump( $redisCluster->sRandMember('key1', 2) );  // 'key1' => {'one', 'two', 'three'}
     *
     * // array(2) {
     * //   [0]=> string(2) "one"
     * //   [1]=> string(2) "three"
     * // }
     * 
*/ public function sRandMember($key, $count = null) {} /** * Get the length of a string value. * * @param string $key * * @return int * @link https://redis.io/commands/strlen * @example *
     * $redisCluster->set('key', 'value');
     * $redisCluster->strlen('key'); // 5
     * 
*/ public function strlen($key) {} /** * Remove the expiration timer from a key. * * @param string $key * * @return bool TRUE if a timeout was removed, FALSE if the key didn’t exist or didn’t have an expiration timer. * @link https://redis.io/commands/persist * @example $redisCluster->persist('key'); */ public function persist($key) {} /** * Returns the remaining time to live of a key that has a timeout. * This introspection capability allows a Redis client to check how many seconds a given key will continue to be * part of the dataset. In Redis 2.6 or older the command returns -1 if the key does not exist or if the key exist * but has no associated expire. Starting with Redis 2.8 the return value in case of error changed: Returns -2 if * the key does not exist. Returns -1 if the key exists but has no associated expire. * * @param string $key * * @return int the time left to live in seconds. * @link https://redis.io/commands/ttl * @example $redisCluster->ttl('key'); */ public function ttl($key) {} /** * Returns the remaining time to live of a key that has an expire set, * with the sole difference that TTL returns the amount of remaining time in seconds while PTTL returns it in * milliseconds. In Redis 2.6 or older the command returns -1 if the key does not exist or if the key exist but has * no associated expire. Starting with Redis 2.8 the return value in case of error changed: Returns -2 if the key * does not exist. Returns -1 if the key exists but has no associated expire. * * @param string $key * * @return int the time left to live in milliseconds. * @link https://redis.io/commands/pttl * @example $redisCluster->pttl('key'); */ public function pttl($key) {} /** * Returns the cardinality of an ordered set. * * @param string $key * * @return int the set's cardinality * @link https://redis.io/commands/zsize * @example *
     * $redisCluster->zAdd('key', 0, 'val0');
     * $redisCluster->zAdd('key', 2, 'val2');
     * $redisCluster->zAdd('key', 10, 'val10');
     * $redisCluster->zCard('key');            // 3
     * 
*/ public function zCard($key) {} /** * Returns the number of elements of the sorted set stored at the specified key which have * scores in the range [start,end]. Adding a parenthesis before start or end excludes it * from the range. +inf and -inf are also valid limits. * * @param string $key * @param string $start * @param string $end * * @return int the size of a corresponding zRangeByScore. * @link https://redis.io/commands/zcount * @example *
     * $redisCluster->zAdd('key', 0, 'val0');
     * $redisCluster->zAdd('key', 2, 'val2');
     * $redisCluster->zAdd('key', 10, 'val10');
     * $redisCluster->zCount('key', 0, 3); // 2, corresponding to array('val0', 'val2')
     * 
*/ public function zCount($key, $start, $end) {} /** * Deletes the elements of the sorted set stored at the specified key which have scores in the range [start,end]. * * @param string $key * @param string $start double or "+inf" or "-inf" as a string * @param string $end double or "+inf" or "-inf" as a string * * @return int The number of values deleted from the sorted set * @link https://redis.io/commands/zremrangebyscore * @example *
     * $redisCluster->zAdd('key', 0, 'val0');
     * $redisCluster->zAdd('key', 2, 'val2');
     * $redisCluster->zAdd('key', 10, 'val10');
     * $redisCluster->zRemRangeByScore('key', '0', '3'); // 2
     * 
*/ public function zRemRangeByScore($key, $start, $end) {} /** * Returns the score of a given member in the specified sorted set. * * @param string $key * @param string $member * * @return float * @link https://redis.io/commands/zscore * @example *
     * $redisCluster->zAdd('key', 2.5, 'val2');
     * $redisCluster->zScore('key', 'val2'); // 2.5
     * 
*/ public function zScore($key, $member) {} /** * Adds the specified member with a given score to the sorted set stored at key. * * @param string $key Required key * @param float $score1 Required score * @param string $value1 Required value * @param float $score2 Optional score * @param string $value2 Optional value * @param float $scoreN Optional score * @param string $valueN Optional value * * @return int Number of values added * @link https://redis.io/commands/zadd * @example *
     * $redisCluster->zAdd('z', 1, 'v2', 2, 'v2', 3, 'v3', 4, 'v4' );  // int(3)
     * $redisCluster->zRem('z', 'v2', 'v3');                           // int(2)
     * var_dump( $redisCluster->zRange('z', 0, -1) );
     *
     * //// Output:
     * // array(1) {
     * //   [0]=> string(2) "v4"
     * // }
     * 
*/ public function zAdd($key, $score1, $value1, $score2 = null, $value2 = null, $scoreN = null, $valueN = null) {} /** * Increments the score of a member from a sorted set by a given amount. * * @param string $key * @param float $value (double) value that will be added to the member's score * @param string $member * * @return float the new value * @link https://redis.io/commands/zincrby * @example *
     * $redisCluster->del('key');
     * $redisCluster->zIncrBy('key', 2.5, 'member1');// key or member1 didn't exist, so member1's score is to 0 ;
     *                                              //before the increment and now has the value 2.5
     * $redisCluster->zIncrBy('key', 1, 'member1');    // 3.5
     * 
*/ public function zIncrBy($key, $value, $member) {} /** * Returns the length of a hash, in number of items * * @param string $key * * @return int|false the number of items in a hash, FALSE if the key doesn't exist or isn't a hash. * @link https://redis.io/commands/hlen * @example *
     * $redisCluster->del('h');
     * $redisCluster->hSet('h', 'key1', 'hello');
     * $redisCluster->hSet('h', 'key2', 'plop');
     * $redisCluster->hLen('h'); // returns 2
     * 
*/ public function hLen($key) {} /** * Returns the keys in a hash, as an array of strings. * * @param string $key * * @return array An array of elements, the keys of the hash. This works like PHP's array_keys(). * @link https://redis.io/commands/hkeys * @example *
     * $redisCluster->del('h');
     * $redisCluster->hSet('h', 'a', 'x');
     * $redisCluster->hSet('h', 'b', 'y');
     * $redisCluster->hSet('h', 'c', 'z');
     * $redisCluster->hSet('h', 'd', 't');
     * var_dump($redisCluster->hKeys('h'));
     *
     * //// Output:
     * //
     * // array(4) {
     * // [0]=>
     * // string(1) "a"
     * // [1]=>
     * // string(1) "b"
     * // [2]=>
     * // string(1) "c"
     * // [3]=>
     * // string(1) "d"
     * // }
     * // The order is random and corresponds to redis' own internal representation of the set structure.
     * 
*/ public function hKeys($key) {} /** * Returns the values in a hash, as an array of strings. * * @param string $key * * @return array An array of elements, the values of the hash. This works like PHP's array_values(). * @link https://redis.io/commands/hvals * @example *
     * $redisCluster->del('h');
     * $redisCluster->hSet('h', 'a', 'x');
     * $redisCluster->hSet('h', 'b', 'y');
     * $redisCluster->hSet('h', 'c', 'z');
     * $redisCluster->hSet('h', 'd', 't');
     * var_dump($redisCluster->hVals('h'));
     *
     * //// Output:
     * //
     * // array(4) {
     * //   [0]=>
     * //   string(1) "x"
     * //   [1]=>
     * //   string(1) "y"
     * //   [2]=>
     * //   string(1) "z"
     * //   [3]=>
     * //   string(1) "t"
     * // }
     * // The order is random and corresponds to redis' own internal representation of the set structure.
     * 
*/ public function hVals($key) {} /** * Gets a value from the hash stored at key. * If the hash table doesn't exist, or the key doesn't exist, FALSE is returned. * * @param string $key * @param string $hashKey * * @return string|false The value, if the command executed successfully BOOL FALSE in case of failure * @link https://redis.io/commands/hget * @example *
     * $redisCluster->del('h');
     * $redisCluster->hSet('h', 'a', 'x');
     * $redisCluster->hGet('h', 'a'); // 'X'
     * 
*/ public function hGet($key, $hashKey) {} /** * Returns the whole hash, as an array of strings indexed by strings. * * @param string $key * * @return array An array of elements, the contents of the hash. * @link https://redis.io/commands/hgetall * @example *
     * $redisCluster->del('h');
     * $redisCluster->hSet('h', 'a', 'x');
     * $redisCluster->hSet('h', 'b', 'y');
     * $redisCluster->hSet('h', 'c', 'z');
     * $redisCluster->hSet('h', 'd', 't');
     * var_dump($redisCluster->hGetAll('h'));
     *
     * //// Output:
     * //
     * // array(4) {
     * //   ["a"]=>
     * //   string(1) "x"
     * //   ["b"]=>
     * //   string(1) "y"
     * //   ["c"]=>
     * //   string(1) "z"
     * //   ["d"]=>
     * //   string(1) "t"
     * // }
     * // The order is random and corresponds to redis' own internal representation of the set structure.
     * 
*/ public function hGetAll($key) {} /** * Verify if the specified member exists in a key. * * @param string $key * @param string $hashKey * * @return bool If the member exists in the hash table, return TRUE, otherwise return FALSE. * @link https://redis.io/commands/hexists * @example *
     * $redisCluster->hSet('h', 'a', 'x');
     * $redisCluster->hExists('h', 'a');               //  TRUE
     * $redisCluster->hExists('h', 'NonExistingKey');  // FALSE
     * 
*/ public function hExists($key, $hashKey) {} /** * Increments the value of a member from a hash by a given amount. * * @param string $key * @param string $hashKey * @param int $value (integer) value that will be added to the member's value * * @return int the new value * @link https://redis.io/commands/hincrby * @example *
     * $redisCluster->del('h');
     * $redisCluster->hIncrBy('h', 'x', 2); // returns 2: h[x] = 2 now.
     * $redisCluster->hIncrBy('h', 'x', 1); // h[x] ← 2 + 1. Returns 3
     * 
*/ public function hIncrBy($key, $hashKey, $value) {} /** * Adds a value to the hash stored at key. If this value is already in the hash, FALSE is returned. * * @param string $key * @param string $hashKey * @param mixed $value * * @return int * 1 if value didn't exist and was added successfully, * 0 if the value was already present and was replaced, FALSE if there was an error. * @link https://redis.io/commands/hset * @example *
     * $redisCluster->del('h')
     * $redisCluster->hSet('h', 'key1', 'hello');  // 1, 'key1' => 'hello' in the hash at "h"
     * $redisCluster->hGet('h', 'key1');           // returns "hello"
     *
     * $redisCluster->hSet('h', 'key1', 'plop');   // 0, value was replaced.
     * $redisCluster->hGet('h', 'key1');           // returns "plop"
     * 
*/ public function hSet($key, $hashKey, $value) {} /** * Adds a value to the hash stored at key only if this field isn't already in the hash. * * @param string $key * @param string $hashKey * @param string $value * * @return bool TRUE if the field was set, FALSE if it was already present. * @link https://redis.io/commands/hsetnx * @example *
     * $redisCluster->del('h')
     * $redisCluster->hSetNx('h', 'key1', 'hello'); // TRUE, 'key1' => 'hello' in the hash at "h"
     * $redisCluster->hSetNx('h', 'key1', 'world'); // FALSE, 'key1' => 'hello' in the hash at "h". No change since the
     * field wasn't replaced.
     * 
*/ public function hSetNx($key, $hashKey, $value) {} /** * Retrieve the values associated to the specified fields in the hash. * * @param string $key * @param array $hashKeys * * @return array Array An array of elements, the values of the specified fields in the hash, * with the hash keys as array keys. * @link https://redis.io/commands/hmget * @example *
     * $redisCluster->del('h');
     * $redisCluster->hSet('h', 'field1', 'value1');
     * $redisCluster->hSet('h', 'field2', 'value2');
     * $redisCluster->hMGet('h', array('field1', 'field2')); // returns array('field1' => 'value1', 'field2' =>
     * 'value2')
     * 
*/ public function hMGet($key, $hashKeys) {} /** * Fills in a whole hash. Non-string values are converted to string, using the standard (string) cast. * NULL values are stored as empty strings * * @param string $key * @param array $hashKeys key → value array * * @return bool * @link https://redis.io/commands/hmset * @example *
     * $redisCluster->del('user:1');
     * $redisCluster->hMSet('user:1', array('name' => 'Joe', 'salary' => 2000));
     * $redisCluster->hIncrBy('user:1', 'salary', 100); // Joe earns 100 more now.
     * 
*/ public function hMSet($key, $hashKeys) {} /** * Removes a values from the hash stored at key. * If the hash table doesn't exist, or the key doesn't exist, FALSE is returned. * * @param string $key * @param string $hashKey1 * @param string $hashKey2 * @param string $hashKeyN * * @return int Number of deleted fields * @link https://redis.io/commands/hdel * @example *
     * $redisCluster->hMSet('h',
     *               array(
     *                    'f1' => 'v1',
     *                    'f2' => 'v2',
     *                    'f3' => 'v3',
     *                    'f4' => 'v4',
     *               ));
     *
     * var_dump( $redisCluster->hDel('h', 'f1') );        // int(1)
     * var_dump( $redisCluster->hDel('h', 'f2', 'f3') );  // int(2)
     *
     * var_dump( $redisCluster->hGetAll('h') );
     *
     * //// Output:
     * //
     * //  array(1) {
     * //    ["f4"]=> string(2) "v4"
     * //  }
     * 
*/ public function hDel($key, $hashKey1, $hashKey2 = null, $hashKeyN = null) {} /** * Increment the float value of a hash field by the given amount * * @param string $key * @param string $field * @param float $increment * * @return float * @link https://redis.io/commands/hincrbyfloat * @example *
     * $redisCluster->hset('h', 'float', 3);
     * $redisCluster->hset('h', 'int',   3);
     * var_dump( $redisCluster->hIncrByFloat('h', 'float', 1.5) ); // float(4.5)
     *
     * var_dump( $redisCluster->hGetAll('h') );
     *
     * //// Output:
     * //
     * // array(2) {
     * //   ["float"]=>
     * //   string(3) "4.5"
     * //   ["int"]=>
     * //   string(1) "3"
     * // }
     * 
*/ public function hIncrByFloat($key, $field, $increment) {} /** * Dump a key out of a redis database, the value of which can later be passed into redis using the RESTORE command. * The data that comes out of DUMP is a binary representation of the key as Redis stores it. * * @param string $key * * @return string|false The Redis encoded value of the key, or FALSE if the key doesn't exist * @link https://redis.io/commands/dump * @example *
     * $redisCluster->set('foo', 'bar');
     * $val = $redisCluster->dump('foo'); // $val will be the Redis encoded key value
     * 
*/ public function dump($key) {} /** * Returns the rank of a given member in the specified sorted set, starting at 0 for the item * with the smallest score. zRevRank starts at 0 for the item with the largest score. * * @param string $key * @param string $member * * @return int the item's score. * @link https://redis.io/commands/zrank * @example *
     * $redisCluster->del('z');
     * $redisCluster->zAdd('key', 1, 'one');
     * $redisCluster->zAdd('key', 2, 'two');
     * $redisCluster->zRank('key', 'one');     // 0
     * $redisCluster->zRank('key', 'two');     // 1
     * $redisCluster->zRevRank('key', 'one');  // 1
     * $redisCluster->zRevRank('key', 'two');  // 0
     * 
*/ public function zRank($key, $member) {} /** * @see zRank() * * @param string $key * @param string $member * * @return int the item's score * @link https://redis.io/commands/zrevrank */ public function zRevRank($key, $member) {} /** * Increment the number stored at key by one. * * @param string $key * * @return int the new value * @link https://redis.io/commands/incr * @example *
     * $redisCluster->incr('key1'); // key1 didn't exists, set to 0 before the increment and now has the value 1
     * $redisCluster->incr('key1'); // 2
     * $redisCluster->incr('key1'); // 3
     * $redisCluster->incr('key1'); // 4
     * 
*/ public function incr($key) {} /** * Decrement the number stored at key by one. * * @param string $key * * @return int the new value * @link https://redis.io/commands/decr * @example *
     * $redisCluster->decr('key1'); // key1 didn't exists, set to 0 before the increment and now has the value -1
     * $redisCluster->decr('key1'); // -2
     * $redisCluster->decr('key1'); // -3
     * 
*/ public function decr($key) {} /** * Increment the number stored at key by one. If the second argument is filled, it will be used as the integer * value of the increment. * * @param string $key key * @param int $value value that will be added to key (only for incrBy) * * @return int the new value * @link https://redis.io/commands/incrby * @example *
     * $redisCluster->incr('key1');        // key1 didn't exists, set to 0 before the increment and now has the value 1
     * $redisCluster->incr('key1');        // 2
     * $redisCluster->incr('key1');        // 3
     * $redisCluster->incr('key1');        // 4
     * $redisCluster->incrBy('key1', 10);  // 14
     * 
*/ public function incrBy($key, $value) {} /** * Decrement the number stored at key by one. If the second argument is filled, it will be used as the integer * value of the decrement. * * @param string $key * @param int $value that will be subtracted to key (only for decrBy) * * @return int the new value * @link https://redis.io/commands/decrby * @example *
     * $redisCluster->decr('key1');        // key1 didn't exists, set to 0 before the increment and now has the value -1
     * $redisCluster->decr('key1');        // -2
     * $redisCluster->decr('key1');        // -3
     * $redisCluster->decrBy('key1', 10);  // -13
     * 
*/ public function decrBy($key, $value) {} /** * Increment the float value of a key by the given amount * * @param string $key * @param float $increment * * @return float * @link https://redis.io/commands/incrbyfloat * @example *
     * $redisCluster->set('x', 3);
     * var_dump( $redisCluster->incrByFloat('x', 1.5) );   // float(4.5)
     *
     * var_dump( $redisCluster->get('x') );                // string(3) "4.5"
     * 
*/ public function incrByFloat($key, $increment) {} /** * Sets an expiration date (a timeout) on an item. * * @param string $key The key that will disappear. * @param int $ttl The key's remaining Time To Live, in seconds. * * @return bool TRUE in case of success, FALSE in case of failure. * @link https://redis.io/commands/expire * @example *
     * $redisCluster->set('x', '42');
     * $redisCluster->expire('x', 3);  // x will disappear in 3 seconds.
     * sleep(5);                    // wait 5 seconds
     * $redisCluster->get('x');            // will return `FALSE`, as 'x' has expired.
     * 
*/ public function expire($key, $ttl) {} /** * Sets an expiration date (a timeout in milliseconds) on an item. * * @param string $key The key that will disappear. * @param int $ttl The key's remaining Time To Live, in milliseconds. * * @return bool TRUE in case of success, FALSE in case of failure. * @link https://redis.io/commands/pexpire * @example *
     * $redisCluster->set('x', '42');
     * $redisCluster->pExpire('x', 11500); // x will disappear in 11500 milliseconds.
     * $redisCluster->ttl('x');            // 12
     * $redisCluster->pttl('x');           // 11500
     * 
*/ public function pExpire($key, $ttl) {} /** * Sets an expiration date (a timestamp) on an item. * * @param string $key The key that will disappear. * @param int $timestamp Unix timestamp. The key's date of death, in seconds from Epoch time. * * @return bool TRUE in case of success, FALSE in case of failure. * @link https://redis.io/commands/expireat * @example *
     * $redisCluster->set('x', '42');
     * $now = time();               // current timestamp
     * $redisCluster->expireAt('x', $now + 3); // x will disappear in 3 seconds.
     * sleep(5);                        // wait 5 seconds
     * $redisCluster->get('x');                // will return `FALSE`, as 'x' has expired.
     * 
*/ public function expireAt($key, $timestamp) {} /** * Sets an expiration date (a timestamp) on an item. Requires a timestamp in milliseconds * * @param string $key The key that will disappear. * @param int $timestamp Unix timestamp. The key's date of death, in seconds from Epoch time. * * @return bool TRUE in case of success, FALSE in case of failure. * @link https://redis.io/commands/pexpireat * @example *
     * $redisCluster->set('x', '42');
     * $redisCluster->pExpireAt('x', 1555555555005);
     * $redisCluster->ttl('x');                       // 218270121
     * $redisCluster->pttl('x');                      // 218270120575
     * 
*/ public function pExpireAt($key, $timestamp) {} /** * Append specified string to the string stored in specified key. * * @param string $key * @param string $value * * @return int Size of the value after the append * @link https://redis.io/commands/append * @example *
     * $redisCluster->set('key', 'value1');
     * $redisCluster->append('key', 'value2'); // 12
     * $redisCluster->get('key');              // 'value1value2'
     * 
*/ public function append($key, $value) {} /** * Return a single bit out of a larger string * * @param string $key * @param int $offset * * @return int the bit value (0 or 1) * @link https://redis.io/commands/getbit * @example *
     * $redisCluster->set('key', "\x7f");  // this is 0111 1111
     * $redisCluster->getBit('key', 0);    // 0
     * $redisCluster->getBit('key', 1);    // 1
     * 
*/ public function getBit($key, $offset) {} /** * Changes a single bit of a string. * * @param string $key * @param int $offset * @param bool|int $value bool or int (1 or 0) * * @return int 0 or 1, the value of the bit before it was set. * @link https://redis.io/commands/setbit * @example *
     * $redisCluster->set('key', "*");     // ord("*") = 42 = 0x2f = "0010 1010"
     * $redisCluster->setBit('key', 5, 1); // returns 0
     * $redisCluster->setBit('key', 7, 1); // returns 0
     * $redisCluster->get('key');          // chr(0x2f) = "/" = b("0010 1111")
     * 
*/ public function setBit($key, $offset, $value) {} /** * Bitwise operation on multiple keys. * * @param string $operation either "AND", "OR", "NOT", "XOR" * @param string $retKey return key * @param string $key1 * @param string $key2 * @param string $key3 * * @return int The size of the string stored in the destination key. * @link https://redis.io/commands/bitop * @example *
     * $redisCluster->set('bit1', '1'); // 11 0001
     * $redisCluster->set('bit2', '2'); // 11 0010
     *
     * $redisCluster->bitOp('AND', 'bit', 'bit1', 'bit2'); // bit = 110000
     * $redisCluster->bitOp('OR',  'bit', 'bit1', 'bit2'); // bit = 110011
     * $redisCluster->bitOp('NOT', 'bit', 'bit1', 'bit2'); // bit = 110011
     * $redisCluster->bitOp('XOR', 'bit', 'bit1', 'bit2'); // bit = 11
     * 
*/ public function bitOp($operation, $retKey, $key1, $key2, $key3 = null) {} /** * Return the position of the first bit set to 1 or 0 in a string. The position is returned, thinking of the * string as an array of bits from left to right, where the first byte's most significant bit is at position 0, * the second byte's most significant bit is at position 8, and so forth. * * @param string $key * @param int $bit * @param int $start * @param int $end * * @return int The command returns the position of the first bit set to 1 or 0 according to the request. * If we look for set bits (the bit argument is 1) and the string is empty or composed of just * zero bytes, -1 is returned. If we look for clear bits (the bit argument is 0) and the string * only contains bit set to 1, the function returns the first bit not part of the string on the * right. So if the string is three bytes set to the value 0xff the command BITPOS key 0 will * return 24, since up to bit 23 all the bits are 1. Basically, the function considers the right * of the string as padded with zeros if you look for clear bits and specify no range or the * start argument only. However, this behavior changes if you are looking for clear bits and * specify a range with both start and end. If no clear bit is found in the specified range, the * function returns -1 as the user specified a clear range and there are no 0 bits in that range. * @link https://redis.io/commands/bitpos * @example *
     * $redisCluster->set('key', '\xff\xff');
     * $redisCluster->bitpos('key', 1); // int(0)
     * $redisCluster->bitpos('key', 1, 1); // int(8)
     * $redisCluster->bitpos('key', 1, 3); // int(-1)
     * $redisCluster->bitpos('key', 0); // int(16)
     * $redisCluster->bitpos('key', 0, 1); // int(16)
     * $redisCluster->bitpos('key', 0, 1, 5); // int(-1)
     * 
*/ public function bitpos($key, $bit, $start = 0, $end = null) {} /** * Count bits in a string. * * @param string $key * * @return int The number of bits set to 1 in the value behind the input key. * @link https://redis.io/commands/bitcount * @example *
     * $redisCluster->set('bit', '345'); // // 11 0011  0011 0100  0011 0101
     * var_dump( $redisCluster->bitCount('bit', 0, 0) ); // int(4)
     * var_dump( $redisCluster->bitCount('bit', 1, 1) ); // int(3)
     * var_dump( $redisCluster->bitCount('bit', 2, 2) ); // int(4)
     * var_dump( $redisCluster->bitCount('bit', 0, 2) ); // int(11)
     * 
*/ public function bitCount($key) {} /** * @see lIndex() * * @param string $key * @param int $index * * @link https://redis.io/commands/lindex */ public function lGet($key, $index) {} /** * Return a substring of a larger string * * @param string $key * @param int $start * @param int $end * * @return string the substring * @link https://redis.io/commands/getrange * @example *
     * $redisCluster->set('key', 'string value');
     * $redisCluster->getRange('key', 0, 5);   // 'string'
     * $redisCluster->getRange('key', -5, -1); // 'value'
     * 
*/ public function getRange($key, $start, $end) {} /** * Trims an existing list so that it will contain only a specified range of elements. * * @param string $key * @param int $start * @param int $stop * * @return array|false Bool return FALSE if the key identify a non-list value. * @link https://redis.io/commands/ltrim * @example *
     * $redisCluster->rPush('key1', 'A');
     * $redisCluster->rPush('key1', 'B');
     * $redisCluster->rPush('key1', 'C');
     * $redisCluster->lRange('key1', 0, -1); // array('A', 'B', 'C')
     * $redisCluster->lTrim('key1', 0, 1);
     * $redisCluster->lRange('key1', 0, -1); // array('A', 'B')
     * 
*/ public function lTrim($key, $start, $stop) {} /** * Returns the specified elements of the list stored at the specified key in * the range [start, end]. start and stop are interpretated as indices: 0 the first element, * 1 the second ... -1 the last element, -2 the penultimate ... * * @param string $key * @param int $start * @param int $end * * @return array containing the values in specified range. * @link https://redis.io/commands/lrange * @example *
     * $redisCluster->rPush('key1', 'A');
     * $redisCluster->rPush('key1', 'B');
     * $redisCluster->rPush('key1', 'C');
     * $redisCluster->lRange('key1', 0, -1); // array('A', 'B', 'C')
     * 
*/ public function lRange($key, $start, $end) {} /** * Deletes the elements of the sorted set stored at the specified key which have rank in the range [start,end]. * * @param string $key * @param int $start * @param int $end * * @return int The number of values deleted from the sorted set * @link https://redis.io/commands/zremrangebyrank * @example *
     * $redisCluster->zAdd('key', 1, 'one');
     * $redisCluster->zAdd('key', 2, 'two');
     * $redisCluster->zAdd('key', 3, 'three');
     * $redisCluster->zRemRangeByRank('key', 0, 1); // 2
     * $redisCluster->zRange('key', 0, -1, true); // array('three' => 3)
     * 
*/ public function zRemRangeByRank($key, $start, $end) {} /** * Publish messages to channels. Warning: this function will probably change in the future. * * @param string $channel a channel to publish to * @param string $message string * * @link https://redis.io/commands/publish * @return int Number of clients that received the message * @example $redisCluster->publish('chan-1', 'hello, world!'); // send message. */ public function publish($channel, $message) {} /** * Renames a key. * * @param string $srcKey * @param string $dstKey * * @return bool TRUE in case of success, FALSE in case of failure. * @link https://redis.io/commands/rename * @example *
     * $redisCluster->set('x', '42');
     * $redisCluster->rename('x', 'y');
     * $redisCluster->get('y');   // → 42
     * $redisCluster->get('x');   // → `FALSE`
     * 
*/ public function rename($srcKey, $dstKey) {} /** * Renames a key. * * Same as rename, but will not replace a key if the destination already exists. * This is the same behaviour as setNx. * * @param string $srcKey * @param string $dstKey * * @return bool TRUE in case of success, FALSE in case of failure. * @link https://redis.io/commands/renamenx * @example *
     * $redisCluster->set('x', '42');
     * $redisCluster->renameNx('x', 'y');
     * $redisCluster->get('y');   // → 42
     * $redisCluster->get('x');   // → `FALSE`
     * 
*/ public function renameNx($srcKey, $dstKey) {} /** * When called with a single key, returns the approximated cardinality computed by the HyperLogLog data * structure stored at the specified variable, which is 0 if the variable does not exist. * * @param string|array $key * * @return int * @link https://redis.io/commands/pfcount * @example *
     * $redisCluster->pfAdd('key1', array('elem1', 'elem2'));
     * $redisCluster->pfAdd('key2', array('elem3', 'elem2'));
     * $redisCluster->pfCount('key1'); // int(2)
     * $redisCluster->pfCount(array('key1', 'key2')); // int(3)
     * 
*/ public function pfCount($key) {} /** * Adds all the element arguments to the HyperLogLog data structure stored at the key. * * @param string $key * @param array $elements * * @return bool * @link https://redis.io/commands/pfadd * @example $redisCluster->pfAdd('key', array('elem1', 'elem2')) */ public function pfAdd($key, array $elements) {} /** * Merge multiple HyperLogLog values into an unique value that will approximate the cardinality * of the union of the observed Sets of the source HyperLogLog structures. * * @param string $destKey * @param array $sourceKeys * * @return bool * @link https://redis.io/commands/pfmerge * @example *
     * $redisCluster->pfAdd('key1', array('elem1', 'elem2'));
     * $redisCluster->pfAdd('key2', array('elem3', 'elem2'));
     * $redisCluster->pfMerge('key3', array('key1', 'key2'));
     * $redisCluster->pfCount('key3'); // int(3)
     * 
*/ public function pfMerge($destKey, array $sourceKeys) {} /** * Changes a substring of a larger string. * * @param string $key * @param int $offset * @param string $value * * @return string the length of the string after it was modified. * @link https://redis.io/commands/setrange * @example *
     * $redisCluster->set('key', 'Hello world');
     * $redisCluster->setRange('key', 6, "redis"); // returns 11
     * $redisCluster->get('key');                  // "Hello redis"
     * 
*/ public function setRange($key, $offset, $value) {} /** * Restore a key from the result of a DUMP operation. * * @param string $key The key name * @param int $ttl How long the key should live (if zero, no expire will be set on the key) * @param string $value (binary). The Redis encoded key value (from DUMP) * * @return bool * @link https://redis.io/commands/restore * @example *
     * $redisCluster->set('foo', 'bar');
     * $val = $redisCluster->dump('foo');
     * $redisCluster->restore('bar', 0, $val); // The key 'bar', will now be equal to the key 'foo'
     * 
*/ public function restore($key, $ttl, $value) {} /** * Moves the specified member from the set at srcKey to the set at dstKey. * * @param string $srcKey * @param string $dstKey * @param string $member * * @return bool If the operation is successful, return TRUE. * If the srcKey and/or dstKey didn't exist, and/or the member didn't exist in srcKey, FALSE is returned. * @link https://redis.io/commands/smove * @example *
     * $redisCluster->sAdd('key1' , 'set11');
     * $redisCluster->sAdd('key1' , 'set12');
     * $redisCluster->sAdd('key1' , 'set13');          // 'key1' => {'set11', 'set12', 'set13'}
     * $redisCluster->sAdd('key2' , 'set21');
     * $redisCluster->sAdd('key2' , 'set22');          // 'key2' => {'set21', 'set22'}
     * $redisCluster->sMove('key1', 'key2', 'set13');  // 'key1' =>  {'set11', 'set12'}
     *                                          // 'key2' =>  {'set21', 'set22', 'set13'}
     * 
*/ public function sMove($srcKey, $dstKey, $member) {} /** * Returns a range of elements from the ordered set stored at the specified key, * with values in the range [start, end]. start and stop are interpreted as zero-based indices: * 0 the first element, * 1 the second ... * -1 the last element, * -2 the penultimate ... * * @param string $key * @param int $start * @param int $end * @param bool $withscores * * @return array Array containing the values in specified range. * @link https://redis.io/commands/zrange * @example *
     * $redisCluster->zAdd('key1', 0, 'val0');
     * $redisCluster->zAdd('key1', 2, 'val2');
     * $redisCluster->zAdd('key1', 10, 'val10');
     * $redisCluster->zRange('key1', 0, -1); // array('val0', 'val2', 'val10')
     * // with scores
     * $redisCluster->zRange('key1', 0, -1, true); // array('val0' => 0, 'val2' => 2, 'val10' => 10)
     * 
*/ public function zRange($key, $start, $end, $withscores = null) {} /** * Returns the elements of the sorted set stored at the specified key in the range [start, end] * in reverse order. start and stop are interpretated as zero-based indices: * 0 the first element, * 1 the second ... * -1 the last element, * -2 the penultimate ... * * @param string $key * @param int $start * @param int $end * @param bool $withscore * * @return array Array containing the values in specified range. * @link https://redis.io/commands/zrevrange * @example *
     * $redisCluster->zAdd('key', 0, 'val0');
     * $redisCluster->zAdd('key', 2, 'val2');
     * $redisCluster->zAdd('key', 10, 'val10');
     * $redisCluster->zRevRange('key', 0, -1); // array('val10', 'val2', 'val0')
     *
     * // with scores
     * $redisCluster->zRevRange('key', 0, -1, true); // array('val10' => 10, 'val2' => 2, 'val0' => 0)
     * 
*/ public function zRevRange($key, $start, $end, $withscore = null) {} /** * Returns the elements of the sorted set stored at the specified key which have scores in the * range [start,end]. Adding a parenthesis before start or end excludes it from the range. * +inf and -inf are also valid limits. * * zRevRangeByScore returns the same items in reverse order, when the start and end parameters are swapped. * * @param string $key * @param int $start * @param int $end * @param array $options Two options are available: * - withscores => TRUE, * - and limit => array($offset, $count) * * @return array Array containing the values in specified range. * @link https://redis.io/commands/zrangebyscore * @example *
     * $redisCluster->zAdd('key', 0, 'val0');
     * $redisCluster->zAdd('key', 2, 'val2');
     * $redisCluster->zAdd('key', 10, 'val10');
     * $redisCluster->zRangeByScore('key', 0, 3);
     * // array('val0', 'val2')
     * $redisCluster->zRangeByScore('key', 0, 3, array('withscores' => TRUE);
     * // array('val0' => 0, 'val2' => 2)
     * $redisCluster->zRangeByScore('key', 0, 3, array('limit' => array(1, 1));
     * // array('val2' => 2)
     * $redisCluster->zRangeByScore('key', 0, 3, array('limit' => array(1, 1));
     * // array('val2')
     * $redisCluster->zRangeByScore('key', 0, 3, array('withscores' => TRUE, 'limit' => array(1, 1));
     * // array('val2'=> 2)
     * 
*/ public function zRangeByScore($key, $start, $end, array $options = []) {} /** * @see zRangeByScore() * * @param string $key * @param int $start * @param int $end * @param array $options * * @return array */ public function zRevRangeByScore($key, $start, $end, array $options = []) {} /** * Returns a range of members in a sorted set, by lexicographical range * * @param string $key The ZSET you wish to run against. * @param int $min The minimum alphanumeric value you wish to get. * @param int $max The maximum alphanumeric value you wish to get. * @param int $offset Optional argument if you wish to start somewhere other than the first element. * @param int $limit Optional argument if you wish to limit the number of elements returned. * * @return array Array containing the values in the specified range. * @link https://redis.io/commands/zrangebylex * @example *
     * foreach (array('a', 'b', 'c', 'd', 'e', 'f', 'g') as $k => $char) {
     *     $redisCluster->zAdd('key', $k, $char);
     * }
     *
     * $redisCluster->zRangeByLex('key', '-', '[c'); // array('a', 'b', 'c')
     * $redisCluster->zRangeByLex('key', '-', '(c'); // array('a', 'b')
     * $redisCluster->zRevRangeByLex('key', '(c','-'); // array('b', 'a')
     * 
*/ public function zRangeByLex($key, $min, $max, $offset = null, $limit = null) {} /** * @see zRangeByLex() * * @param string $key * @param int $min * @param int $max * @param int $offset * @param int $limit * * @return array * @link https://redis.io/commands/zrevrangebylex */ public function zRevRangeByLex($key, $min, $max, $offset = null, $limit = null) {} /** * Count the number of members in a sorted set between a given lexicographical range. * * @param string $key * @param int $min * @param int $max * * @return int The number of elements in the specified score range. * @link https://redis.io/commands/zlexcount * @example *
     * foreach (array('a', 'b', 'c', 'd', 'e', 'f', 'g') as $k => $char) {
     *     $redisCluster->zAdd('key', $k, $char);
     * }
     * $redisCluster->zLexCount('key', '[b', '[f'); // 5
     * 
*/ public function zLexCount($key, $min, $max) {} /** * Remove all members in a sorted set between the given lexicographical range. * * @param string $key The ZSET you wish to run against. * @param string $min The minimum alphanumeric value you wish to get. * @param string $max The maximum alphanumeric value you wish to get. * * @return int|false the number of elements removed. * @link https://redis.io/commands/zremrangebylex * @example *
     * foreach (array('a', 'b', 'c', 'd', 'e', 'f', 'g') as $k => $char) {
     *     $redisCluster->zAdd('key', $k, $char);
     * }
     * $redisCluster->zRemRangeByLex('key', '(b','[d'); // 2 , remove element 'c' and 'd'
     * $redisCluster->zRange('key',0,-1);// array('a','b','e','f','g')
     * 
*/ public function zRemRangeByLex(string $key, string $min, string $max) {} /** * Add multiple sorted sets and store the resulting sorted set in a new key * * @param string $Output * @param array $ZSetKeys * @param null|array $Weights * @param string $aggregateFunction Either "SUM", "MIN", or "MAX": defines the behaviour to use on * duplicate entries during the zUnion. * * @return int The number of values in the new sorted set. * @link https://redis.io/commands/zunionstore * @example *
     * $redisCluster->del('k1');
     * $redisCluster->del('k2');
     * $redisCluster->del('k3');
     * $redisCluster->del('ko1');
     * $redisCluster->del('ko2');
     * $redisCluster->del('ko3');
     *
     * $redisCluster->zAdd('k1', 0, 'val0');
     * $redisCluster->zAdd('k1', 1, 'val1');
     *
     * $redisCluster->zAdd('k2', 2, 'val2');
     * $redisCluster->zAdd('k2', 3, 'val3');
     *
     * $redisCluster->zUnionStore('ko1', array('k1', 'k2')); // 4, 'ko1' => array('val0', 'val1', 'val2', 'val3')
     *
     * // Weighted zUnionStore
     * $redisCluster->zUnionStore('ko2', array('k1', 'k2'), array(1, 1)); // 4, 'ko2' => array('val0', 'val1', 'val2','val3')
     * $redisCluster->zUnionStore('ko3', array('k1', 'k2'), array(5, 1)); // 4, 'ko3' => array('val0', 'val2', 'val3','val1')
     * 
*/ public function zUnionStore($Output, $ZSetKeys, ?array $Weights = null, $aggregateFunction = 'SUM') {} /** * Intersect multiple sorted sets and store the resulting sorted set in a new key * * @param string $Output * @param array $ZSetKeys * @param null|array $Weights * @param string $aggregateFunction Either "SUM", "MIN", or "MAX": * defines the behaviour to use on duplicate entries during the zInterStore. * * @return int The number of values in the new sorted set. * @link https://redis.io/commands/zinterstore * @example *
     * $redisCluster->del('k1');
     * $redisCluster->del('k2');
     * $redisCluster->del('k3');
     *
     * $redisCluster->del('ko1');
     * $redisCluster->del('ko2');
     * $redisCluster->del('ko3');
     * $redisCluster->del('ko4');
     *
     * $redisCluster->zAdd('k1', 0, 'val0');
     * $redisCluster->zAdd('k1', 1, 'val1');
     * $redisCluster->zAdd('k1', 3, 'val3');
     *
     * $redisCluster->zAdd('k2', 2, 'val1');
     * $redisCluster->zAdd('k2', 3, 'val3');
     *
     * $redisCluster->zInterStore('ko1', array('k1', 'k2'));               // 2, 'ko1' => array('val1', 'val3')
     * $redisCluster->zInterStore('ko2', array('k1', 'k2'), array(1, 1));  // 2, 'ko2' => array('val1', 'val3')
     *
     * // Weighted zInterStore
     * $redisCluster->zInterStore('ko3', array('k1', 'k2'), array(1, 5), 'min'); // 2, 'ko3' => array('val1', 'val3')
     * $redisCluster->zInterStore('ko4', array('k1', 'k2'), array(1, 5), 'max'); // 2, 'ko4' => array('val3', 'val1')
     * 
*/ public function zInterStore($Output, $ZSetKeys, array $Weights = null, $aggregateFunction = 'SUM') {} /** * Deletes a specified member from the ordered set. * * @param string $key * @param string $member1 * @param string $member2 * @param string $memberN * * @return int Number of deleted values * @link https://redis.io/commands/zrem * @example *
     * $redisCluster->zAdd('z', 1, 'v1', 2, 'v2', 3, 'v3', 4, 'v4' );  // int(2)
     * $redisCluster->zRem('z', 'v2', 'v3');                           // int(2)
     * var_dump( $redisCluster->zRange('z', 0, -1) );
     * //// Output:
     * //
     * // array(2) {
     * //   [0]=> string(2) "v1"
     * //   [1]=> string(2) "v4"
     * // }
     * 
*/ public function zRem($key, $member1, $member2 = null, $memberN = null) {} /** * Sort * * @param string $key * @param array $option array(key => value, ...) - optional, with the following keys and values: * - 'by' => 'some_pattern_*', * - 'limit' => array(0, 1), * - 'get' => 'some_other_pattern_*' or an array of patterns, * - 'sort' => 'asc' or 'desc', * - 'alpha' => TRUE, * - 'store' => 'external-key' * * @return array * An array of values, or a number corresponding to the number of elements stored if that was used. * @link https://redis.io/commands/sort * @example *
     * $redisCluster->del('s');
     * $redisCluster->sadd('s', 5);
     * $redisCluster->sadd('s', 4);
     * $redisCluster->sadd('s', 2);
     * $redisCluster->sadd('s', 1);
     * $redisCluster->sadd('s', 3);
     *
     * var_dump($redisCluster->sort('s')); // 1,2,3,4,5
     * var_dump($redisCluster->sort('s', array('sort' => 'desc'))); // 5,4,3,2,1
     * var_dump($redisCluster->sort('s', array('sort' => 'desc', 'store' => 'out'))); // (int)5
     * 
*/ public function sort($key, $option = null) {} /** * Describes the object pointed to by a key. * The information to retrieve (string) and the key (string). * Info can be one of the following: * - "encoding" * - "refcount" * - "idletime" * * @param string $string * @param string $key * * @return string|false for "encoding", int for "refcount" and "idletime", FALSE if the key doesn't exist. * @link https://redis.io/commands/object * @example *
     * $redisCluster->object("encoding", "l"); // → ziplist
     * $redisCluster->object("refcount", "l"); // → 1
     * $redisCluster->object("idletime", "l"); // → 400 (in seconds, with a precision of 10 seconds).
     * 
*/ public function object($string = '', $key = '') {} /** * Subscribe to channels. Warning: this function will probably change in the future. * * @param array $channels an array of channels to subscribe to * @param string|array $callback either a string or an array($instance, 'method_name'). * The callback function receives 3 parameters: the redis instance, the channel * name, and the message. * * @return mixed Any non-null return value in the callback will be returned to the caller. * @link https://redis.io/commands/subscribe * @example *
     * function f($redisCluster, $chan, $msg) {
     *  switch($chan) {
     *      case 'chan-1':
     *          ...
     *          break;
     *
     *      case 'chan-2':
     *                     ...
     *          break;
     *
     *      case 'chan-2':
     *          ...
     *          break;
     *      }
     * }
     *
     * $redisCluster->subscribe(array('chan-1', 'chan-2', 'chan-3'), 'f'); // subscribe to 3 chans
     * 
*/ public function subscribe($channels, $callback) {} /** * Subscribe to channels by pattern * * @param array $patterns The number of elements removed from the set. * @param string|array $callback Either a string or an array with an object and method. * The callback will get four arguments ($redis, $pattern, $channel, $message) * * @return mixed Any non-null return value in the callback will be returned to the caller. * * @link https://redis.io/commands/psubscribe * @example *
     * function psubscribe($redisCluster, $pattern, $chan, $msg) {
     *  echo "Pattern: $pattern\n";
     *  echo "Channel: $chan\n";
     *  echo "Payload: $msg\n";
     * }
     * 
*/ public function psubscribe($patterns, $callback) {} /** * Unsubscribes the client from the given channels, or from all of them if none is given. * * @param $channels * @param $callback */ public function unSubscribe($channels, $callback) {} /** * Unsubscribes the client from the given patterns, or from all of them if none is given. * * @param $channels * @param $callback */ public function punSubscribe($channels, $callback) {} /** * Evaluate a LUA script serverside, from the SHA1 hash of the script instead of the script itself. * In order to run this command Redis will have to have already loaded the script, either by running it or via * the SCRIPT LOAD command. * * @param string $scriptSha * @param array $args * @param int $numKeys * * @return mixed @see eval() * @see eval() * @link https://redis.io/commands/evalsha * @example *
     * $script = 'return 1';
     * $sha = $redisCluster->script('load', $script);
     * $redisCluster->evalSha($sha); // Returns 1
     * 
*/ public function evalSha($scriptSha, $args = [], $numKeys = 0) {} /** * Scan the keyspace for keys. * * @param int &$iterator Iterator, initialized to NULL. * @param string|array $node Node identified by key or host/port array * @param string $pattern Pattern to match. * @param int $count Count of keys per iteration (only a suggestion to Redis). * * @return array|false This function will return an array of keys or FALSE if there are no more keys. * @link https://redis.io/commands/scan * @example *
     * $iterator = null;
     * while($keys = $redisCluster->scan($iterator)) {
     *     foreach($keys as $key) {
     *         echo $key . PHP_EOL;
     *     }
     * }
     * 
*/ public function scan(&$iterator, $node, $pattern = null, $count = 0) {} /** * Scan a set for members. * * @param string $key The set to search. * @param int &$iterator LONG (reference) to the iterator as we go. * @param null $pattern String, optional pattern to match against. * @param int $count How many members to return at a time (Redis might return a different amount). * * @return array|false PHPRedis will return an array of keys or FALSE when we're done iterating. * @link https://redis.io/commands/sscan * @example *
     * $iterator = null;
     * while ($members = $redisCluster->sScan('set', $iterator)) {
     *     foreach ($members as $member) {
     *         echo $member . PHP_EOL;
     *     }
     * }
     * 
*/ public function sScan($key, &$iterator, $pattern = null, $count = 0) {} /** * Scan a sorted set for members, with optional pattern and count. * * @param string $key String, the set to scan. * @param int &$iterator Long (reference), initialized to NULL. * @param string $pattern String (optional), the pattern to match. * @param int $count How many keys to return per iteration (Redis might return a different number). * * @return array|false PHPRedis will return matching keys from Redis, or FALSE when iteration is complete. * @link https://redis.io/commands/zscan * @example *
     * $iterator = null;
     * while ($members = $redis-zscan('zset', $iterator)) {
     *     foreach ($members as $member => $score) {
     *         echo $member . ' => ' . $score . PHP_EOL;
     *     }
     * }
     * 
*/ public function zScan($key, &$iterator, $pattern = null, $count = 0) {} /** * Scan a HASH value for members, with an optional pattern and count. * * @param string $key * @param int &$iterator * @param string $pattern Optional pattern to match against. * @param int $count How many keys to return in a go (only a sugestion to Redis). * * @return array An array of members that match our pattern. * @link https://redis.io/commands/hscan * @example *
     * $iterator = null;
     * while($elements = $redisCluster->hscan('hash', $iterator)) {
     *    foreach($elements as $key => $value) {
     *         echo $key . ' => ' . $value . PHP_EOL;
     *     }
     * }
     * 
*/ public function hScan($key, &$iterator, $pattern = null, $count = 0) {} /** * Detect whether we're in ATOMIC/MULTI/PIPELINE mode. * * @return int Either RedisCluster::ATOMIC, RedisCluster::MULTI or RedisCluster::PIPELINE * @example $redisCluster->getMode(); */ public function getMode() {} /** * The last error message (if any) * * @return string|null A string with the last returned script based error message, or NULL if there is no error * @example *
     * $redisCluster->eval('this-is-not-lua');
     * $err = $redisCluster->getLastError();
     * // "ERR Error compiling script (new function): user_script:1: '=' expected near '-'"
     * 
*/ public function getLastError() {} /** * Clear the last error message * * @return bool true * @example *
     * $redisCluster->set('x', 'a');
     * $redisCluster->incr('x');
     * $err = $redisCluster->getLastError();
     * // "ERR value is not an integer or out of range"
     * $redisCluster->clearLastError();
     * $err = $redisCluster->getLastError();
     * // NULL
     * 
*/ public function clearLastError() {} /** * Get client option * * @param int $option parameter * * @return int|string Parameter value. * @example * // return RedisCluster::SERIALIZER_NONE, RedisCluster::SERIALIZER_PHP, or RedisCluster::SERIALIZER_IGBINARY. * $redisCluster->getOption(RedisCluster::OPT_SERIALIZER); */ public function getOption($option) {} /** * Set client option. * * @param int $option parameter * @param int|string $value parameter value * * @return bool TRUE on success, FALSE on error. * @example *
     * $redisCluster->setOption(RedisCluster::OPT_SERIALIZER, RedisCluster::SERIALIZER_NONE);        // don't serialize data
     * $redisCluster->setOption(RedisCluster::OPT_SERIALIZER, RedisCluster::SERIALIZER_PHP);         // use built-in serialize/unserialize
     * $redisCluster->setOption(RedisCluster::OPT_SERIALIZER, RedisCluster::SERIALIZER_IGBINARY);    // use igBinary serialize/unserialize
     * $redisCluster->setOption(RedisCluster::OPT_PREFIX, 'myAppName:');                             // use custom prefix on all keys
     * 
*/ public function setOption($option, $value) {} /** * A utility method to prefix the value with the prefix setting for phpredis. * * @param mixed $value The value you wish to prefix * * @return string If a prefix is set up, the value now prefixed. If there is no prefix, the value will be returned unchanged. * @example *
     * $redisCluster->setOption(RedisCluster::OPT_PREFIX, 'my-prefix:');
     * $redisCluster->_prefix('my-value'); // Will return 'my-prefix:my-value'
     * 
*/ public function _prefix($value) {} /** * A utility method to serialize values manually. This method allows you to serialize a value with whatever * serializer is configured, manually. This can be useful for serialization/unserialization of data going in * and out of EVAL commands as phpredis can't automatically do this itself. Note that if no serializer is * set, phpredis will change Array values to 'Array', and Objects to 'Object'. * * @param mixed $value The value to be serialized. * * @return mixed * @example *
     * $redisCluster->setOption(RedisCluster::OPT_SERIALIZER, RedisCluster::SERIALIZER_NONE);
     * $redisCluster->_serialize("foo"); // returns "foo"
     * $redisCluster->_serialize(Array()); // Returns "Array"
     * $redisCluster->_serialize(new stdClass()); // Returns "Object"
     *
     * $redisCluster->setOption(RedisCluster::OPT_SERIALIZER, RedisCluster::SERIALIZER_PHP);
     * $redisCluster->_serialize("foo"); // Returns 's:3:"foo";'
     * 
*/ public function _serialize($value) {} /** * A utility method to unserialize data with whatever serializer is set up. If there is no serializer set, the * value will be returned unchanged. If there is a serializer set up, and the data passed in is malformed, an * exception will be thrown. This can be useful if phpredis is serializing values, and you return something from * redis in a LUA script that is serialized. * * @param string $value The value to be unserialized * * @return mixed * @example *
     * $redisCluster->setOption(RedisCluster::OPT_SERIALIZER, RedisCluster::SERIALIZER_PHP);
     * $redisCluster->_unserialize('a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}'); // Will return Array(1,2,3)
     * 
*/ public function _unserialize($value) {} /** * Return all redis master nodes * * @return array * @example *
     * $redisCluster->_masters(); // Will return [[0=>'127.0.0.1','6379'],[0=>'127.0.0.1','6380']]
     * 
*/ public function _masters() {} /** * Enter and exit transactional mode. * * @param int $mode RedisCluster::MULTI|RedisCluster::PIPELINE * Defaults to RedisCluster::MULTI. * A RedisCluster::MULTI block of commands runs as a single transaction; * a RedisCluster::PIPELINE block is simply transmitted faster to the server, but without any guarantee * of atomicity. discard cancels a transaction. * * @return RedisCluster returns the RedisCluster instance and enters multi-mode. * Once in multi-mode, all subsequent method calls return the same object until exec() is called. * @link https://redis.io/commands/multi * @example *
     * $ret = $redisCluster->multi()
     *      ->set('key1', 'val1')
     *      ->get('key1')
     *      ->set('key2', 'val2')
     *      ->get('key2')
     *      ->exec();
     *
     * //$ret == array (
     * //    0 => TRUE,
     * //    1 => 'val1',
     * //    2 => TRUE,
     * //    3 => 'val2');
     * 
*/ public function multi($mode = RedisCluster::MULTI) {} /** * @see multi() * @return void|array * @link https://redis.io/commands/exec */ public function exec() {} /** * @see multi() * @link https://redis.io/commands/discard */ public function discard() {} /** * Watches a key for modifications by another client. If the key is modified between WATCH and EXEC, * the MULTI/EXEC transaction will fail (return FALSE). unwatch cancels all the watching of all keys by this client. * * @param string|array $key : a list of keys * * @return void * @link https://redis.io/commands/watch * @example *
     * $redisCluster->watch('x');
     * // long code here during the execution of which other clients could well modify `x`
     * $ret = $redisCluster->multi()
     *          ->incr('x')
     *          ->exec();
     * // $ret = FALSE if x has been modified between the call to WATCH and the call to EXEC.
     * 
*/ public function watch($key) {} /** * @see watch() * @link https://redis.io/commands/unwatch */ public function unwatch() {} /** * Performs a synchronous save at a specific node. * * @param string|array $nodeParams key or [host,port] * * @return bool TRUE in case of success, FALSE in case of failure. * If a save is already running, this command will fail and return FALSE. * @link https://redis.io/commands/save * @example * $redisCluster->save('x'); //key * $redisCluster->save(['127.0.0.1',6379]); //[host,port] */ public function save($nodeParams) {} /** * Performs a background save at a specific node. * * @param string|array $nodeParams key or [host,port] * * @return bool TRUE in case of success, FALSE in case of failure. * If a save is already running, this command will fail and return FALSE. * @link https://redis.io/commands/bgsave */ public function bgsave($nodeParams) {} /** * Removes all entries from the current database at a specific node. * * @param string|array $nodeParams key or [host,port] * * @return bool Always TRUE. * @link https://redis.io/commands/flushdb */ public function flushDB($nodeParams) {} /** * Removes all entries from all databases at a specific node. * * @param string|array $nodeParams key or [host,port] * * @return bool Always TRUE. * @link https://redis.io/commands/flushall */ public function flushAll($nodeParams) {} /** * Returns the current database's size at a specific node. * * @param string|array $nodeParams key or [host,port] * * @return int DB size, in number of keys. * @link https://redis.io/commands/dbsize * @example *
     * $count = $redisCluster->dbSize('x');
     * echo "Redis has $count keys\n";
     * 
*/ public function dbSize($nodeParams) {} /** * Starts the background rewrite of AOF (Append-Only File) at a specific node. * * @param string|array $nodeParams key or [host,port] * * @return bool TRUE in case of success, FALSE in case of failure. * @link https://redis.io/commands/bgrewriteaof * @example $redisCluster->bgrewriteaof('x'); */ public function bgrewriteaof($nodeParams) {} /** * Returns the timestamp of the last disk save at a specific node. * * @param string|array $nodeParams key or [host,port] * * @return int timestamp. * @link https://redis.io/commands/lastsave * @example $redisCluster->lastSave('x'); */ public function lastSave($nodeParams) {} /** * Returns an associative array of strings and integers * * @param string $option Optional. The option to provide redis. * SERVER | CLIENTS | MEMORY | PERSISTENCE | STATS | REPLICATION | CPU | CLASTER | KEYSPACE * | COMANDSTATS * * Returns an associative array of strings and integers, with the following keys: * - redis_version * - redis_git_sha1 * - redis_git_dirty * - redis_build_id * - redis_mode * - os * - arch_bits * - multiplexing_api * - atomicvar_api * - gcc_version * - process_id * - run_id * - tcp_port * - uptime_in_seconds * - uptime_in_days * - hz * - lru_clock * - executable * - config_file * - connected_clients * - client_longest_output_list * - client_biggest_input_buf * - blocked_clients * - used_memory * - used_memory_human * - used_memory_rss * - used_memory_rss_human * - used_memory_peak * - used_memory_peak_human * - used_memory_peak_perc * - used_memory_peak * - used_memory_overhead * - used_memory_startup * - used_memory_dataset * - used_memory_dataset_perc * - total_system_memory * - total_system_memory_human * - used_memory_lua * - used_memory_lua_human * - maxmemory * - maxmemory_human * - maxmemory_policy * - mem_fragmentation_ratio * - mem_allocator * - active_defrag_running * - lazyfree_pending_objects * - mem_fragmentation_ratio * - loading * - rdb_changes_since_last_save * - rdb_bgsave_in_progress * - rdb_last_save_time * - rdb_last_bgsave_status * - rdb_last_bgsave_time_sec * - rdb_current_bgsave_time_sec * - rdb_last_cow_size * - aof_enabled * - aof_rewrite_in_progress * - aof_rewrite_scheduled * - aof_last_rewrite_time_sec * - aof_current_rewrite_time_sec * - aof_last_bgrewrite_status * - aof_last_write_status * - aof_last_cow_size * - changes_since_last_save * - aof_current_size * - aof_base_size * - aof_pending_rewrite * - aof_buffer_length * - aof_rewrite_buffer_length * - aof_pending_bio_fsync * - aof_delayed_fsync * - loading_start_time * - loading_total_bytes * - loading_loaded_bytes * - loading_loaded_perc * - loading_eta_seconds * - total_connections_received * - total_commands_processed * - instantaneous_ops_per_sec * - total_net_input_bytes * - total_net_output_bytes * - instantaneous_input_kbps * - instantaneous_output_kbps * - rejected_connections * - maxclients * - sync_full * - sync_partial_ok * - sync_partial_err * - expired_keys * - evicted_keys * - keyspace_hits * - keyspace_misses * - pubsub_channels * - pubsub_patterns * - latest_fork_usec * - migrate_cached_sockets * - slave_expires_tracked_keys * - active_defrag_hits * - active_defrag_misses * - active_defrag_key_hits * - active_defrag_key_misses * - role * - master_replid * - master_replid2 * - master_repl_offset * - second_repl_offset * - repl_backlog_active * - repl_backlog_size * - repl_backlog_first_byte_offset * - repl_backlog_histlen * - master_host * - master_port * - master_link_status * - master_last_io_seconds_ago * - master_sync_in_progress * - slave_repl_offset * - slave_priority * - slave_read_only * - master_sync_left_bytes * - master_sync_last_io_seconds_ago * - master_link_down_since_seconds * - connected_slaves * - min-slaves-to-write * - min-replicas-to-write * - min_slaves_good_slaves * - used_cpu_sys * - used_cpu_user * - used_cpu_sys_children * - used_cpu_user_children * - cluster_enabled * * @link https://redis.io/commands/info * @return array * @example *
     * $redisCluster->info();
     *
     * or
     *
     * $redisCluster->info("COMMANDSTATS"); //Information on the commands that have been run (>=2.6 only)
     * $redisCluster->info("CPU"); // just CPU information from Redis INFO
     * 
*/ public function info($option = null) {} /** * @since redis >= 2.8.12. * Returns the role of the instance in the context of replication * * @param string|array $nodeParams key or [host,port] * * @return array * @link https://redis.io/commands/role * @example *
     * $redisCluster->role(['127.0.0.1',6379]);
     * // [ 0=>'master',1 => 3129659, 2 => [ ['127.0.0.1','9001','3129242'], ['127.0.0.1','9002','3129543'] ] ]
     * 
*/ public function role($nodeParams) {} /** * Returns a random key at the specified node * * @param string|array $nodeParams key or [host,port] * * @return string an existing key in redis. * @link https://redis.io/commands/randomkey * @example *
     * $key = $redisCluster->randomKey('x');
     * $surprise = $redisCluster->get($key);  // who knows what's in there.
     * 
*/ public function randomKey($nodeParams) {} /** * Return the specified node server time. * * @param string|array $nodeParams key or [host,port] * * @return array If successfully, the time will come back as an associative array with element zero being the * unix timestamp, and element one being microseconds. * @link https://redis.io/commands/time * @example *
     * var_dump( $redisCluster->time('x') );
     * //// Output:
     * //
     * // array(2) {
     * //   [0] => string(10) "1342364352"
     * //   [1] => string(6) "253002"
     * // }
     * 
*/ public function time($nodeParams) {} /** * Check the specified node status * * @param string|array $nodeParams key or [host,port] * * @return string STRING: +PONG on success. Throws a RedisClusterException object on connectivity error, as described * above. * @link https://redis.io/commands/ping */ public function ping($nodeParams) {} /** * Returns message. * * @param string|array $nodeParams key or [host,port] * @param string $msg * * @return mixed */ public function echo($nodeParams, $msg) {} /** * Returns Array reply of details about all Redis Cluster commands. * * @return mixed array | bool */ public function command() {} /** * Send arbitrary things to the redis server at the specified node * * @param string|array $nodeParams key or [host,port] * @param string $command Required command to send to the server. * @param mixed $arguments Optional variable amount of arguments to send to the server. * * @return mixed */ public function rawCommand($nodeParams, $command, $arguments) {} /** * @since redis >= 3.0 * Executes cluster command * * @param string|array $nodeParams key or [host,port] * @param string $command Required command to send to the server. * @param mixed $arguments Optional variable amount of arguments to send to the server. * * @return mixed * @link https://redis.io/commands#cluster * @example *
     * $redisCluster->cluster(['127.0.0.1',6379],'INFO');
     * 
*/ public function cluster($nodeParams, $command, $arguments) {} /** * Allows you to get information of the cluster client * * @param string|array $nodeParams key or [host,port] * @param string $subCmd can be: 'LIST', 'KILL', 'GETNAME', or 'SETNAME' * @param string $args optional arguments */ public function client($nodeParams, $subCmd, $args) {} /** * Get or Set the redis config keys. * * @param string|array $nodeParams key or [host,port] * @param string $operation either `GET` or `SET` * @param string $key for `SET`, glob-pattern for `GET`. See https://redis.io/commands/config-get for examples. * @param string $value optional string (only for `SET`) * * @return array Associative array for `GET`, key -> value * @link https://redis.io/commands/config-get * @link https://redis.io/commands/config-set * @example *
     * $redisCluster->config(['127.0.0.1',6379], "GET", "*max-*-entries*");
     * $redisCluster->config(['127.0.0.1',6379], "SET", "dir", "/var/run/redis/dumps/");
     * 
*/ public function config($nodeParams, $operation, $key, $value) {} /** * A command allowing you to get information on the Redis pub/sub system. * * @param string|array $nodeParams key or [host,port] * * @param string $keyword String, which can be: "channels", "numsub", or "numpat" * @param string|array $argument Optional, variant. * For the "channels" subcommand, you can pass a string pattern. * For "numsub" an array of channel names * * @return array|int Either an integer or an array. * - channels Returns an array where the members are the matching channels. * - numsub Returns a key/value array where the keys are channel names and * values are their counts. * - numpat Integer return containing the number active pattern subscriptions. * @link https://redis.io/commands/pubsub * @example *
     * $redisCluster->pubsub(['127.0.0.1',6379], 'channels'); // All channels
     * $redisCluster->pubsub(['127.0.0.1',6379], 'channels', '*pattern*'); // Just channels matching your pattern
     * $redisCluster->pubsub(['127.0.0.1',6379], 'numsub', array('chan1', 'chan2')); // Get subscriber counts for
     * 'chan1' and 'chan2'
     * $redisCluster->pubsub(['127.0.0.1',6379], 'numpat'); // Get the number of pattern subscribers
     * 
*/ public function pubsub($nodeParams, $keyword, $argument) {} /** * Execute the Redis SCRIPT command to perform various operations on the scripting subsystem. * * @param string|array $nodeParams key or [host,port] * @param string $command load | flush | kill | exists * @param string $script * * @return mixed * @link https://redis.io/commands/script-load * @link https://redis.io/commands/script-kill * @link https://redis.io/commands/script-flush * @link https://redis.io/commands/script-exists * @example *
     * $redisCluster->script(['127.0.0.1',6379], 'load', $script);
     * $redisCluster->script(['127.0.0.1',6379], 'flush');
     * $redisCluster->script(['127.0.0.1',6379], 'kill');
     * $redisCluster->script(['127.0.0.1',6379], 'exists', $script1, [$script2, $script3, ...]);
     * 
* * SCRIPT LOAD will return the SHA1 hash of the passed script on success, and FALSE on failure. * SCRIPT FLUSH should always return TRUE * SCRIPT KILL will return true if a script was able to be killed and false if not * SCRIPT EXISTS will return an array with TRUE or FALSE for each passed script */ public function script($nodeParams, $command, $script) {} /** * This function is used in order to read and reset the Redis slow queries log. * * @param string|array $nodeParams key or [host,port] * @param string $command * @param mixed $argument * * @link https://redis.io/commands/slowlog * @example *
     * $redisCluster->slowLog(['127.0.0.1',6379],'get','2');
     * 
*/ public function slowLog($nodeParams, $command, $argument) {} /** * Add one or more geospatial items in the geospatial index represented using a sorted set * * @param string $key * @param float $longitude * @param float $latitude * @param string $member * * @link https://redis.io/commands/geoadd * @example *
     * $redisCluster->geoAdd('Sicily', 13.361389, 38.115556, 'Palermo'); // int(1)
     * $redisCluster->geoAdd('Sicily', 15.087269, 37.502669, "Catania"); // int(1)
     * 
*/ public function geoAdd($key, $longitude, $latitude, $member) {} /** * Returns members of a geospatial index as standard geohash strings * * @param string $key * @param string $member1 * @param string $member2 * @param string $memberN * * @example *
     * $redisCluster->geoAdd('Sicily', 13.361389, 38.115556, 'Palermo'); // int(1)
     * $redisCluster->geoAdd('Sicily', 15.087269, 37.502669, "Catania"); // int(1)
     * $redisCluster->geohash('Sicily','Palermo','Catania');//['sqc8b49rny0','sqdtr74hyu0']
     * 
*/ public function geohash($key, $member1, $member2 = null, $memberN = null) {} /** * Returns longitude and latitude of members of a geospatial index * * @param string $key * @param string $member1 * @param string $member2 * @param string $memberN * @example *
     * $redisCluster->geoAdd('Sicily', 15.087269, 37.502669, "Catania"); // int(1)
     * $redisCluster->geopos('Sicily','Palermo');//[['13.36138933897018433','38.11555639549629859']]
     * 
*/ public function geopos($key, $member1, $member2 = null, $memberN = null) {} /** * Returns the distance between two members of a geospatial index * * @param string $key * @param string $member1 * @param string $member2 * @param string $unit The unit must be one of the following, and defaults to meters: * m for meters. * km for kilometers. * mi for miles. * ft for feet. * * @link https://redis.io/commands/geoadd * @example *
     * $redisCluster->geoAdd('Sicily', 13.361389, 38.115556, 'Palermo'); // int(1)
     * $redisCluster->geoAdd('Sicily', 15.087269, 37.502669, "Catania"); // int(1)
     * $redisCluster->geoDist('Sicily', 'Palermo' ,'Catania'); // float(166274.1516)
     * $redisCluster->geoDist('Sicily', 'Palermo','Catania', 'km'); // float(166.2742)
     * 
*/ public function geoDist($key, $member1, $member2, $unit = 'm') {} /** * Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point * * @param string $key * @param float $longitude * @param float $latitude * @param float $radius * @param string $radiusUnit String can be: "m" for meters; "km" for kilometers , "mi" for miles, or "ft" for feet. * @param array $options * * @link https://redis.io/commands/georadius * @example *
     * $redisCluster->del('Sicily');
     * $redisCluster->geoAdd('Sicily', 12.361389, 35.115556, 'Palermo'); // int(1)
     * $redisCluster->geoAdd('Sicily', 15.087269, 37.502669, "Catania"); // int(1)
     * $redisCluster->geoAdd('Sicily', 13.3585, 35.330022, "Agrigento"); // int(1)
     *
     * var_dump( $redisCluster->geoRadius('Sicily',13.3585, 35.330022, 300, 'km', ['WITHDIST' ,'DESC']) );
     *
     * array(3) {
     *    [0]=>
     *   array(2) {
     *        [0]=>
     *     string(7) "Catania"
     *        [1]=>
     *     string(8) "286.9362"
     *   }
     *   [1]=>
     *   array(2) {
     *        [0]=>
     *     string(7) "Palermo"
     *        [1]=>
     *     string(7) "93.6874"
     *   }
     *   [2]=>
     *   array(2) {
     *        [0]=>
     *     string(9) "Agrigento"
     *        [1]=>
     *     string(6) "0.0002"
     *   }
     * }
     * var_dump( $redisCluster->geoRadiusByMember('Sicily','Agrigento', 100, 'km', ['WITHDIST' ,'DESC']) );
     *
     * * array(2) {
     *    [0]=>
     *   array(2) {
     *        [0]=>
     *     string(7) "Palermo"
     *        [1]=>
     *     string(7) "93.6872"
     *   }
     *   [1]=>
     *   array(2) {
     *        [0]=>
     *     string(9) "Agrigento"
     *        [1]=>
     *     string(6) "0.0000"
     *   }
     * }
     *
     * 
     */
    public function geoRadius($key, $longitude, $latitude, $radius, $radiusUnit, array $options) {}

    /**
     * Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member
     *
     * @see geoRadius
     *
     * @param string $key
     * @param string $member
     * @param float  $radius
     * @param string $radiusUnit
     * @param array  $options
     */
    public function geoRadiusByMember($key, $member, $radius, $radiusUnit, array $options) {}
}

class RedisClusterException extends Exception {}
.
 */

/**
 * Helper autocomplete for phpredis extension
 *
 * @author  Tawana Musewe 
 * @link    https://github.com/tbtmuse/phpredis-sentinel-phpdoc
 */
class RedisSentinel
{
    /**
     * Creates a Redis Sentinel
     *
     * @param string      $host          Sentinel IP address or hostname
     * @param int         $port          Sentinel Port
     * @param float       $timeout       Value in seconds (optional, default is 0 meaning unlimited)
     * @param string|null $persistent    Persistent connection id (optional, default is null meaning not persistent)
     * @param int         $retryInterval Value in milliseconds (optional, default is 0)
     * @param float       $readTimeout   Value in seconds (optional, default is 0 meaning unlimited)
     *
     * @example
     * // 1s timeout, 100ms delay between reconnection attempts.
     * $sentinel = new RedisSentinel('127.0.0.1', 26379, 1, null, 100);
     */
    public function __construct(
        string $host,
        int $port,
        float $timeout = 0,
        ?string $persistent = null,
        int $retryInterval = 0,
        float $readTimeout = 0
    ) {}

    /**
     * Creates a Redis Sentinel
     *
     * Accepts and array of options.
     *
     * Available options:
     *   - 'host' => string, Sentinel IP address or hostname
     *   - 'port' => int, Sentinel Port (optional, default is 26379)
     *   - 'connectTimeout' => float, Value in seconds (optional, default is 0 meaning unlimited)
     *   - 'persistent' => string, Persistent connection id (optional, default is NULL meaning not persistent)
     *   - 'retryInterval' => int, Value in milliseconds (optional, default is 0)
     *   - 'readTimeout' => float, Value in seconds (optional, default is 0 meaning unlimited)
     *   - 'auth' => string|array, Authentication credentials (optional, default is NULL meaning NOAUTH)
     *
     * @param array $options Associative array of options
     *
     * @example $sentinel = new RedisSentinel(['host' => '127.0.0.1']); // default parameters
     *
     * @since >= 6.0.0
     */
    public function __construct(array $options) {}

    /**
     * Check if the current Sentinel configuration is able to reach the quorum needed to failover a master, and the
     * majority needed to authorize the failover. This command should be used in monitoring systems to check if a
     * Sentinel deployment is ok.
     *
     * @param string $master Name of master
     *
     * @return bool True in case of success, False in case of failure.
     *
     * @example $sentinel->ckquorum('mymaster');
     *
     * @since   >= 5.2.0
     */
    public function ckquorum(string $master): bool {}

    /**
     * Force a failover as if the master was not reachable, and without asking for agreement to other Sentinels
     * (however a new version of the configuration will be published so that the other Sentinels will update
     * their configurations).
     *
     * @param string $master Name of master
     *
     * @return bool True in case of success, False in case of failure.
     *
     * @example $sentinel->failover('mymaster');
     *
     * @since   >= 5.2.0
     */
    public function failover(string $master): bool {}

    /**
     * Force Sentinel to rewrite its configuration on disk, including the current Sentinel state.
     *
     * Normally Sentinel rewrites the configuration every time something changes in its state (in the context of the
     * subset of the state which is persisted on disk across restart). However sometimes it is possible that the
     * configuration file is lost because of operation errors, disk failures, package upgrade scripts or configuration
     * managers. In those cases a way to to force Sentinel to rewrite the configuration file is handy.
     *
     * This command works even if the previous configuration file is completely missing.
     *
     * @return bool True in case of success, False in case of failure.
     *
     * @example $sentinel->flushconfig();
     *
     * @since   >= 5.2.0
     */
    public function flushconfig(): bool {}

    /**
     * Return the ip and port number of the master with that name. If a failover is in progress or terminated
     * successfully for this master it returns the address and port of the promoted replica.
     *
     * @param string $master Name of master
     *
     * @return array|false ['address', 'port'] in case of success, False in case of failure.
     *
     * @example $sentinel->getMasterAddrByName('mymaster');
     *
     * @since   >= 5.2.0
     */
    public function getMasterAddrByName(string $master) {}

    /**
     * Return the state and info of the specified master
     *
     * @param string $master Name of master
     *
     * @return array|false Associative array with info in case of success, False in case of failure.
     *
     * @example $sentinel->master('mymaster');
     *
     * @since   >= 5.2.0
     */
    public function master(string $master) {}

    /**
     * Return a list of monitored masters and their state
     *
     * @return array|false Array of arrays with info for each master in case of success, FALSE in case of failure.
     *
     * @example $sentinel->masters();
     *
     * @since   >= 5.2.0
     */
    public function masters() {}

    /**
     * Ping the sentinel
     *
     * @return bool True in case of success, False in case of failure
     *
     * @example $sentinel->ping();
     *
     * @since   >= 5.2.0
     */
    public function ping(): bool {}

    /**
     * Reset all the masters with matching name. The pattern argument is a glob-style pattern.
     * The reset process clears any previous state in a master (including a failover in progress), and removes every
     * replica and sentinel already discovered and associated with the master.
     *
     * @param string $pattern Glob-style pattern
     *
     * @return bool True in case of success, False in case of failure
     *
     * @example $sentinel->reset('*');
     *
     * @since   >= 5.2.0
     */
    public function reset(string $pattern): bool {}

    /**
     * Return a list of sentinel instances for this master, and their state
     *
     * @param string $master Name of master
     *
     * @return array|false Array of arrays with info for each sentinel in case of success, False in case of failure
     *
     * @example $sentinel->sentinels('mymaster');
     *
     * @since   >= 5.2.0
     */
    public function sentinels(string $master) {}

    /**
     * Return a list of sentinel instances for this master, and their state
     *
     * @param string $master Name of master
     *
     * @return array|false Array of arrays with info for each replica in case of success, False in case of failure
     *
     * @example $sentinel->slaves('mymaster');
     *
     * @since   >= 5.2.0
     */
    public function slaves(string $master) {}
}

     * 
SNMP_VALUE_LIBRARY
The return values will be as returned by the Net-SNMP library.
*
SNMP_VALUE_PLAIN
The return values will be the plain value without the SNMP type hint.
*
SNMP_VALUE_OBJECT
The return values will be objects with the properties "value" and "type", where the latter is one of the SNMP_OCTET_STR, SNMP_COUNTER etc. constants. The way "value" is returned is based on which one of SNMP_VALUE_LIBRARY, SNMP_VALUE_PLAIN is set
*
* @link https://secure.php.net/manual/en/class.snmp.php#snmp.props.max-oids */ public $valueretrieval; /** * @var bool Value of quick_print within the NET-SNMP library *

Sets the value of quick_print within the NET-SNMP library. When this is set (1), the SNMP library will return 'quick printed' values. This means that just the value will be printed. When quick_print is not enabled (default) the UCD SNMP library prints extra information including the type of the value (i.e. IpAddress or OID). Additionally, if quick_print is not enabled, the library prints additional hex values for all strings of three characters or less. * @link https://secure.php.net/manual/en/class.snmp.php#snmp.props.quick-print */ public $quick_print; /** * @var bool Controls the way enum values are printed *

Parameter toggles if walk/get etc. should automatically lookup enum values in the MIB and return them together with their human readable string. * @link https://secure.php.net/manual/en/class.snmp.php#snmp.props.enum-print */ public $enum_print; /** * @var int Controls OID output format *

OID .1.3.6.1.2.1.1.3.0 representation for various oid_output_format values *

*
SNMP_OID_OUTPUT_FULL
.iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.sysUpTimeInstance
*
SNMP_OID_OUTPUT_NUMERIC
.1.3.6.1.2.1.1.3.0
*
SNMP_OID_OUTPUT_MODULE
DISMAN-EVENT-MIB::sysUpTimeInstance
*
SNMP_OID_OUTPUT_SUFFIX
sysUpTimeInstance
*
SNMP_OID_OUTPUT_UCD
system.sysUpTime.sysUpTimeInstance
*
SNMP_OID_OUTPUT_NONE
Undefined
*
* @link https://secure.php.net/manual/en/class.snmp.php#snmp.props.oid-output-format */ public $oid_output_format; /** * @var bool Controls disabling check for increasing OID while walking OID tree *

Some SNMP agents are known for returning OIDs out of order but can complete the walk anyway. Other agents return OIDs that are out of order and can cause SNMP::walk() to loop indefinitely until memory limit will be reached. PHP SNMP library by default performs OID increasing check and stops walking on OID tree when it detects possible loop with issuing warning about non-increasing OID faced. Set oid_increasing_check to FALSE to disable this check. * @link https://secure.php.net/manual/en/class.snmp.php#snmp.props.oid-increasing-check */ public $oid_increasing_check; /** * @var int Controls which failures will raise SNMPException instead of warning. Use bitwise OR'ed SNMP::ERRNO_* constants. By default all SNMP exceptions are disabled. * @link https://secure.php.net/manual/en/class.snmp.php#snmp.props.exceptions-enabled */ public $exceptions_enabled; /** * @var array Read-only property with remote agent configuration: hostname, port, default timeout, default retries count * @link https://secure.php.net/manual/en/class.snmp.php#snmp.props.info */ public $info; public const VERSION_1 = 0; public const VERSION_2c = 1; public const VERSION_2C = 1; public const VERSION_3 = 3; public const ERRNO_NOERROR = 0; public const ERRNO_ANY = 126; public const ERRNO_GENERIC = 2; public const ERRNO_TIMEOUT = 4; public const ERRNO_ERROR_IN_REPLY = 8; public const ERRNO_OID_NOT_INCREASING = 16; public const ERRNO_OID_PARSING_ERROR = 32; public const ERRNO_MULTIPLE_SET_QUERIES = 64; /** * Creates SNMP instance representing session to remote SNMP agent * @link https://php.net/manual/en/snmp.construct.php * @param int $version

SNMP protocol version: * SNMP::VERSION_1, * SNMP::VERSION_2C, * SNMP::VERSION_3.

* @param string $hostname The SNMP agent. hostname may be suffixed with * optional SNMP agent port after colon. IPv6 addresses must be enclosed in square * brackets if used with port. If FQDN is used for hostname * it will be resolved by php-snmp library, not by Net-SNMP engine. Usage * of IPv6 addresses when specifying FQDN may be forced by enclosing FQDN * into square brackets. Here it is some examples: * * * * * * * * * * * *
IPv4 with default port127.0.0.1
IPv6 with default port::1 or [::1]
IPv4 with specific port127.0.0.1:1161
IPv6 with specific port[::1]:1161
FQDN with default porthost.domain
FQDN with specific porthost.domain:1161
FQDN with default port, force usage of IPv6 address[host.domain]
FQDN with specific port, force usage of IPv6 address[host.domain]:1161
* @param string $community

The purpuse of community is * SNMP version specific:

* * * * * * *
SNMP::VERSION_1SNMP community
SNMP::VERSION_2CSNMP community
SNMP::VERSION_3SNMPv3 securityName
* @param int $timeout [optional] The number of microseconds until the first timeout. * @param int $retries [optional] The number of retries in case timeout occurs. * @since 5.4 */ public function __construct($version, $hostname, $community, $timeout = 1000000, $retries = 5) {} /** * Close SNMP session * @link https://php.net/manual/en/snmp.close.php * @return bool TRUE on success or FALSE on failure. * @since 5.4 */ public function close() {} /** * Configures security-related SNMPv3 session parameters * @link https://php.net/manual/en/snmp.setsecurity.php * @param string $sec_level the security level (noAuthNoPriv|authNoPriv|authPriv) * @param string $auth_protocol [optional] the authentication protocol (MD5 or SHA) * @param string $auth_passphrase [optional] the authentication pass phrase * @param string $priv_protocol [optional] the privacy protocol (DES or AES) * @param string $priv_passphrase [optional] the privacy pass phrase * @param string $contextName [optional] the context name * @param string $contextEngineID [optional] the context EngineID * @return bool TRUE on success or FALSE on failure. * @since 5.4 */ public function setSecurity($sec_level, $auth_protocol, $auth_passphrase, $priv_protocol, $priv_passphrase, $contextName, $contextEngineID) {} /** * Fetch an SNMP object * @link https://php.net/manual/en/snmp.get.php * @param mixed $object_id The SNMP object (OID) or objects * @param bool $preserve_keys [optional] When object_id is a array and preserve_keys set to TRUE keys in results will be taken exactly as in object_id, otherwise SNMP::oid_output_format property is used to determinate the form of keys. * @return mixed SNMP objects requested as string or array * depending on object_id type or FALSE on error. * @since 5.4 */ public function get($object_id, $preserve_keys = false) {} /** * Fetch an SNMP object which * follows the given object id * @link https://php.net/manual/en/snmp.getnext.php * @param mixed $object_id

* The SNMP object (OID) or objects *

* @return mixed SNMP objects requested as string or array * depending on object_id type or FALSE on error. * @since 5.4 */ public function getnext($object_id) {} /** * Fetch SNMP object subtree * @link https://php.net/manual/en/snmp.walk.php * @param string $object_id

Root of subtree to be fetched

* @param bool $suffix_as_keys [optional]

By default full OID notation is used for keys in output array. If set to TRUE subtree prefix will be removed from keys leaving only suffix of object_id.

* @param int $max_repetitions [optional]

This specifies the maximum number of iterations over the repeating variables. The default is to use this value from SNMP object.

* @param int $non_repeaters [optional]

This specifies the number of supplied variables that should not be iterated over. The default is to use this value from SNMP object.

* @return array|false associative array of the SNMP object ids and their values on success or FALSE on error. * When a SNMP error occures SNMP::getErrno and * SNMP::getError can be used for retrieving error * number (specific to SNMP extension, see class constants) and error message * respectively. * @since 5.4 */ public function walk($object_id, $suffix_as_keys = false, $max_repetitions, $non_repeaters) {} /** * Set the value of an SNMP object * @link https://php.net/manual/en/snmp.set.php * @param string $object_id

The SNMP object id

* @since 5.4 * *

When count of OIDs in object_id array is greater than * max_oids object property set method will have to use multiple queries * to perform requested value updates. In this case type and value checks * are made per-chunk so second or subsequent requests may fail due to * wrong type or value for OID requested. To mark this a warning is * raised when count of OIDs in object_id array is greater than max_oids. * When count of OIDs in object_id array is greater than max_oids object property set method will have to use multiple queries to perform requested value updates. In this case type and value checks are made per-chunk so second or subsequent requests may fail due to wrong type or value for OID requested. To mark this a warning is raised when count of OIDs in object_id array is greater than max_oids.

* @param mixed $type

The MIB defines the type of each object id. It has to be specified as a single character from the below list.

* types: * * * * * * * * * * * * * * *
=The type is taken from the MIB
iINTEGER
uINTEGER
sSTRING
xHEX STRING
dDECIMAL STRING
nNULLOBJ
oOBJID
tTIMETICKS
aIPADDRESS
bBITS
*

* If OPAQUE_SPECIAL_TYPES was defined while compiling the SNMP library, the following are also valid: *

* types: * * * * * * * *
Uunsigned int64
Isigned int64
Ffloat
Ddouble
*

* Most of these will use the obvious corresponding ASN.1 type. 's', 'x', 'd' and 'b' are all different ways of specifying an OCTET STRING value, and * the 'u' unsigned type is also used for handling Gauge32 values. *

* *

* If the MIB-Files are loaded by into the MIB Tree with "snmp_read_mib" or by specifying it in the libsnmp config, '=' may be used as * the type parameter for all object ids as the type can then be automatically read from the MIB. *

* *

* Note that there are two ways to set a variable of the type BITS like e.g. * "SYNTAX BITS {telnet(0), ftp(1), http(2), icmp(3), snmp(4), ssh(5), https(6)}": *

*
    *
  • * Using type "b" and a list of bit numbers. This method is not recommended since GET query for the same OID would return e.g. 0xF8. *
  • *
  • * Using type "x" and a hex number but without(!) the usual "0x" prefix. *
  • *
*

* See examples section for more details. *

* @param mixed $value

* The new value.

* @return bool TRUE on success or FALSE on failure. */ public function set($object_id, $type, $value) {} /** * Get last error code * @link https://php.net/manual/en/snmp.geterrno.php * @return int one of SNMP error code values described in constants chapter. * @since 5.4 */ public function getErrno() {} /** * Get last error message * @link https://php.net/manual/en/snmp.geterror.php * @return string String describing error from last SNMP request. * @since 5.4 */ public function getError() {} } /** * Represents an error raised by SNMP. You should not throw a * SNMPException from your own code. * See Exceptions for more * information about Exceptions in PHP. * @link https://php.net/manual/en/class.snmpexception.php */ class SNMPException extends RuntimeException { /** * @var string Textual error message. Exception::getMessage() to access it. */ protected $message; /** * @var string SNMP library error code. Use Exception::getCode() to access it. */ protected $code; } /** * Fetch an SNMP object * @link https://php.net/manual/en/function.snmpget.php * @param string $hostname

* The SNMP agent. *

* @param string $community

* The read community. *

* @param string $object_id

* The SNMP object. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return string|false SNMP object value on success or FALSE on error. */ function snmpget($hostname, $community, $object_id, $timeout = 1000000, $retries = 5) {} /** * Fetch the SNMP object which follows the given object id * @link https://php.net/manual/en/function.snmpgetnext.php * @param string $host

The hostname of the SNMP agent (server).

* @param string $community

The read community.

* @param string $object_id

The SNMP object id which precedes the wanted one.

* @param int $timeout [optional]

The number of microseconds until the first timeout.

* @param int $retries [optional]

The number of times to retry if timeouts occur.

* @return string|false SNMP object value on success or FALSE on error. * In case of an error, an E_WARNING message is shown. */ function snmpgetnext($host, $community, $object_id, $timeout = 1000000, $retries = 5) {} /** * Fetch all the SNMP objects from an agent * @link https://php.net/manual/en/function.snmpwalk.php * @param string $hostname

* The SNMP agent (server). *

* @param string $community

* The read community. *

* @param string $object_id

* If NULL, object_id is taken as the root of * the SNMP objects tree and all objects under that tree are returned as * an array. *

*

* If object_id is specified, all the SNMP objects * below that object_id are returned. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

The number of times to retry if timeouts occur.

* @return array an array of SNMP object values starting from the * object_id as root or FALSE on error. */ function snmpwalk($hostname, $community, $object_id, $timeout = 1000000, $retries = 5) {} /** * Return all objects including their respective object ID within the specified one * @link https://php.net/manual/en/function.snmprealwalk.php * @param string $host

The hostname of the SNMP agent (server).

* @param string $community

The read community.

* @param string $object_id

The SNMP object id which precedes the wanted one.

* @param int $timeout [optional]

The number of microseconds until the first timeout.

* @param int $retries [optional]

The number of times to retry if timeouts occur.

* @return array|false an associative array of the SNMP object ids and their values on success or FALSE on error. * In case of an error, an E_WARNING message is shown. */ function snmprealwalk($host, $community, $object_id, $timeout = 1000000, $retries = 5) {} /** * Query for a tree of information about a network entity * @link https://php.net/manual/en/function.snmpwalkoid.php * @param string $hostname

* The SNMP agent. *

* @param string $community

* The read community. *

* @param string $object_id

* If NULL, object_id is taken as the root of * the SNMP objects tree and all objects under that tree are returned as * an array. *

*

* If object_id is specified, all the SNMP objects * below that object_id are returned. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return array an associative array with object ids and their respective * object value starting from the object_id * as root or FALSE on error. */ function snmpwalkoid($hostname, $community, $object_id, $timeout = 1000000, $retries = 5) {} /** * Set the value of an SNMP object * @link https://php.net/manual/en/function.snmpset.php * @param string $host

* The hostname of the SNMP agent (server). *

* @param string $community

* The write community. *

* @param string $object_id

* The SNMP object id. *

* @param string $type The MIB defines the type of each object id. It has to be specified as a single character from the below list. *

* types * =The type is taken from the MIB * iINTEGER * uINTEGER * sSTRING * xHEX STRING * dDECIMAL STRING * nNULLOBJ * oOBJID * tTIMETICKS * aIPADDRESS * bBITS * * If OPAQUE_SPECIAL_TYPES was defined while compiling the SNMP library, the following are also valid: *

* types * Uunsigned int64 * Isigned int64 * Ffloat * Ddouble * * Most of these will use the obvious corresponding ASN.1 type. 's', 'x', 'd' and 'b' are all different ways of specifying an OCTET STRING value, and * the 'u' unsigned type is also used for handling Gauge32 values. *

* If the MIB-Files are loaded by into the MIB Tree with "snmp_read_mib" or by specifying it in the libsnmp config, '=' may be used as * the type parameter for all object ids as the type can then be automatically read from the MIB. *

* Note that there are two ways to set a variable of the type BITS like e.g. * "SYNTAX BITS {telnet(0), ftp(1), http(2), icmp(3), snmp(4), ssh(5), https(6)}": *

* Using type "b" and a list of bit numbers. This method is not recommended since GET query for the same OID would return e.g. 0xF8. * Using type "x" and a hex number but without(!) the usual "0x" prefix. * See examples section for more details. *

* @param mixed $value

* The new value. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return bool TRUE on success or FALSE on failure. *

* If the SNMP host rejects the data type, an E_WARNING message like "Warning: Error in packet. Reason: (badValue) The value given has the wrong type or length." is shown. * If an unknown or invalid OID is specified the warning probably reads "Could not add variable". *

*/ function snmpset($host, $community, $object_id, $type, $value, $timeout = 1000000, $retries = 5) {} /** * Fetches the current value of the UCD library's quick_print setting * @link https://php.net/manual/en/function.snmp-get-quick-print.php * @return bool TRUE if quick_print is on, FALSE otherwise. */ function snmp_get_quick_print() {} /** * Set the value of quick_print within the UCD SNMP library * @link https://php.net/manual/en/function.snmp-set-quick-print.php * @param bool $quick_print * @return bool No value is returned. */ function snmp_set_quick_print($quick_print) {} /** * Return all values that are enums with their enum value instead of the raw integer * @link https://php.net/manual/en/function.snmp-set-enum-print.php * @param int $enum_print

* As the value is interpreted as boolean by the Net-SNMP library, it can only be "0" or "1". *

* @return bool */ function snmp_set_enum_print($enum_print) {} /** * Set the OID output format * @link https://php.net/manual/en/function.snmp-set-oid-output-format.php * @param int $oid_format [optional] * OID .1.3.6.1.2.1.1.3.0 representation for various oid_format values * * *
SNMP_OID_OUTPUT_FULL.iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.sysUpTimeInstance
SNMP_OID_OUTPUT_NUMERIC.1.3.6.1.2.1.1.3.0
*

Begining from PHP 5.4.0 four additional constants available: *

* * * * *
SNMP_OID_OUTPUT_MODULEDISMAN-EVENT-MIB::sysUpTimeInstance
SNMP_OID_OUTPUT_SUFFIXsysUpTimeInstance
SNMP_OID_OUTPUT_UCDsystem.sysUpTime.sysUpTimeInstance
SNMP_OID_OUTPUT_NONEUndefined
*

* @return bool No value is returned. */ function snmp_set_oid_output_format($oid_format = SNMP_OID_OUTPUT_MODULE) {} /** * Set the oid output format * @link https://php.net/manual/en/function.snmp-set-oid-numeric-print.php * @param int $oid_format * @return void */ function snmp_set_oid_numeric_print($oid_format) {} /** * Fetch an SNMP object * @link https://php.net/manual/en/function.snmp2-get.php * @param string $host

* The SNMP agent. *

* @param string $community

* The read community. *

* @param string $object_id

* The SNMP object. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return string|false SNMP object value on success or FALSE on error. */ function snmp2_get($host, $community, $object_id, $timeout = 1000000, $retries = 5) {} /** * Fetch the SNMP object which follows the given object id * @link https://php.net/manual/en/function.snmp2-getnext.php * @param string $host

* The hostname of the SNMP agent (server). *

* @param string $community

* The read community. *

* @param string $object_id

* The SNMP object id which precedes the wanted one. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return string|false SNMP object value on success or FALSE on error. * In case of an error, an E_WARNING message is shown. */ function snmp2_getnext($host, $community, $object_id, $timeout = 1000000, $retries = 5) {} /** * Fetch all the SNMP objects from an agent * @link https://php.net/manual/en/function.snmp2-walk.php * @param string $host

* The SNMP agent (server). *

* @param string $community

* The read community. *

* @param string $object_id

* If NULL, object_id is taken as the root of * the SNMP objects tree and all objects under that tree are returned as * an array. *

*

* If object_id is specified, all the SNMP objects * below that object_id are returned. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return array an array of SNMP object values starting from the * object_id as root or FALSE on error. */ function snmp2_walk($host, $community, $object_id, $timeout = 1000000, $retries = 5) {} /** * Return all objects including their respective object ID within the specified one * @link https://php.net/manual/en/function.snmp2-real-walk.php * @param string $host

* The hostname of the SNMP agent (server). *

* @param string $community

* The read community. *

* @param string $object_id

* The SNMP object id which precedes the wanted one. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return array|false an associative array of the SNMP object ids and their values on success or FALSE on error. * In case of an error, an E_WARNING message is shown. */ function snmp2_real_walk($host, $community, $object_id, $timeout = 1000000, $retries = 5) {} /** * Set the value of an SNMP object * @link https://php.net/manual/en/function.snmp2-set.php * @param string $host

* The hostname of the SNMP agent (server). *

* @param string $community

* The write community. *

* @param string $object_id

* The SNMP object id. *

* @param string $type

The MIB defines the type of each object id. It has to be specified as a single character from the below list. *

*

types:

* * * * * * * * * * * * *
=The type is taken from the MIB
iINTEGER
uINTEGER
sSTRING
xHEX STRING
dDECIMAL STRING
nNULLOBJ
oOBJID
tTIMETICKS
aIPADDRESS
bBITS
*

If OPAQUE_SPECIAL_TYPES was defined while compiling the SNMP library, the following are also valid: *

*

types:

* * * * * *
Uunsigned int64
Isigned int64
Ffloat
Ddouble
*

Most of these will use the obvious corresponding ASN.1 type. 's', 'x', 'd' and 'b' are all different ways of specifying an OCTET STRING value, and * the 'u' unsigned type is also used for handling Gauge32 values. *

* If the MIB-Files are loaded by into the MIB Tree with "snmp_read_mib" or by specifying it in the libsnmp config, '=' may be used as * the type parameter for all object ids as the type can then be automatically read from the MIB. *

* Note that there are two ways to set a variable of the type BITS like e.g. * "SYNTAX BITS {telnet(0), ftp(1), http(2), icmp(3), snmp(4), ssh(5), https(6)}": *

* Using type "b" and a list of bit numbers. This method is not recommended since GET query for the same OID would return e.g. 0xF8. * Using type "x" and a hex number but without(!) the usual "0x" prefix. * See examples section for more details. *

* @param string $value

* The new value. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return bool TRUE on success or FALSE on failure. *

* If the SNMP host rejects the data type, an E_WARNING message like "Warning: Error in packet. Reason: (badValue) The value given has the wrong type or length." is shown. * If an unknown or invalid OID is specified the warning probably reads "Could not add variable". *

*/ function snmp2_set($host, $community, $object_id, $type, $value, $timeout = 1000000, $retries = 5) {} /** * Fetch an SNMP object * @link https://php.net/manual/en/function.snmp3-get.php * @param string $host

* The hostname of the SNMP agent (server). *

* @param string $sec_name

* the security name, usually some kind of username *

* @param string $sec_level

* the security level (noAuthNoPriv|authNoPriv|authPriv) *

* @param string $auth_protocol

* the authentication protocol (MD5 or SHA) *

* @param string $auth_passphrase

* the authentication pass phrase *

* @param string $priv_protocol

* the privacy protocol (DES or AES) *

* @param string $priv_passphrase

* the privacy pass phrase *

* @param string $object_id

* The SNMP object id. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return string|false SNMP object value on success or FALSE on error. */ function snmp3_get($host, $sec_name, $sec_level, $auth_protocol, $auth_passphrase, $priv_protocol, $priv_passphrase, $object_id, $timeout = 1000000, $retries = 5) {} /** * Fetch the SNMP object which follows the given object id * @link https://php.net/manual/en/function.snmp3-getnext.php * @param string $host

* The hostname of the * SNMP agent (server). *

* @param string $sec_name

* the security name, usually some kind of username *

* @param string $sec_level

* the security level (noAuthNoPriv|authNoPriv|authPriv) *

* @param string $auth_protocol

* the authentication protocol (MD5 or SHA) *

* @param string $auth_passphrase

* the authentication pass phrase *

* @param string $priv_protocol

* the privacy protocol (DES or AES) *

* @param string $priv_passphrase

* the privacy pass phrase *

* @param string $object_id

* The SNMP object id. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return string|false SNMP object value on success or FALSE on error. * In case of an error, an E_WARNING message is shown. */ function snmp3_getnext($host, $sec_name, $sec_level, $auth_protocol, $auth_passphrase, $priv_protocol, $priv_passphrase, $object_id, $timeout = 1000000, $retries = 5) {} /** * Fetch all the SNMP objects from an agent * @link https://php.net/manual/en/function.snmp3-walk.php * @param string $host

* The hostname of the SNMP agent (server). *

* @param string $sec_name

* the security name, usually some kind of username *

* @param string $sec_level

* the security level (noAuthNoPriv|authNoPriv|authPriv) *

* @param string $auth_protocol

* the authentication protocol (MD5 or SHA) *

* @param string $auth_passphrase

* the authentication pass phrase *

* @param string $priv_protocol

* the privacy protocol (DES or AES) *

* @param string $priv_passphrase

* the privacy pass phrase *

* @param string $object_id

* If NULL, object_id is taken as the root of * the SNMP objects tree and all objects under that tree are returned as * an array. *

*

* If object_id is specified, all the SNMP objects * below that object_id are returned. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return array an array of SNMP object values starting from the * object_id as root or FALSE on error. */ function snmp3_walk($host, $sec_name, $sec_level, $auth_protocol, $auth_passphrase, $priv_protocol, $priv_passphrase, $object_id, $timeout = 1000000, $retries = 5) {} /** * Return all objects including their respective object ID within the specified one * @link https://php.net/manual/en/function.snmp3-real-walk.php * @param string $host

* The hostname of the * SNMP agent (server). *

* @param string $sec_name

* the security name, usually some kind of username *

* @param string $sec_level

* the security level (noAuthNoPriv|authNoPriv|authPriv) *

* @param string $auth_protocol

* the authentication protocol (MD5 or SHA) *

* @param string $auth_passphrase

* the authentication pass phrase *

* @param string $priv_protocol

* the privacy protocol (DES or AES) *

* @param string $priv_passphrase

* the privacy pass phrase *

* @param string $object_id

* The SNMP object id. *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return array an associative array of the * SNMP object ids and their values on success or FALSE on error. * In case of an error, an E_WARNING message is shown. */ function snmp3_real_walk($host, $sec_name, $sec_level, $auth_protocol, $auth_passphrase, $priv_protocol, $priv_passphrase, $object_id, $timeout = null, $retries = null) {} /** * Set the value of an SNMP object * @link https://php.net/manual/en/function.snmp3-set.php * @param string $host

* The hostname of the SNMP agent (server). *

* @param string $sec_name

* the security name, usually some kind of username *

* @param string $sec_level

* the security level (noAuthNoPriv|authNoPriv|authPriv) *

* @param string $auth_protocol

* the authentication protocol (MD5 or SHA) *

* @param string $auth_passphrase

* the authentication pass phrase *

* @param string $priv_protocol

* the privacy protocol (DES or AES) *

* @param string $priv_passphrase

* the privacy pass phrase *

* @param string $object_id

* The SNMP object id. *

* @param string $type

The MIB defines the type of each object id. It has to be specified as a single character from the below list.

*

types:

* * * * * * * * * * * * *
=The type is taken from the MIB
iINTEGER
uINTEGER
sSTRING
xHEX STRING
dDECIMAL STRING
nNULLOBJ
oOBJID
tTIMETICKS
aIPADDRESS
bBITS
*

If OPAQUE_SPECIAL_TYPES was defined while compiling the SNMP library, the following are also valid: *

*

types:

* * * * * *
Uunsigned int64
Isigned int64
Ffloat
Ddouble
*

Most of these will use the obvious corresponding ASN.1 type. 's', 'x', 'd' and 'b' are all different ways of specifying an OCTET STRING value, and * the 'u' unsigned type is also used for handling Gauge32 values. *

*

* If the MIB-Files are loaded by into the MIB Tree with "snmp_read_mib" or by specifying it in the libsnmp config, '=' may be used as * the type parameter for all object ids as the type can then be automatically read from the MIB. *

*

* Note that there are two ways to set a variable of the type BITS like e.g. * "SYNTAX BITS {telnet(0), ftp(1), http(2), icmp(3), snmp(4), ssh(5), https(6)}": *

*

* Using type "b" and a list of bit numbers. This method is not recommended since GET query for the same OID would return e.g. 0xF8. * Using type "x" and a hex number but without(!) the usual "0x" prefix. * See examples section for more details. *

* @param string $value

* The new value *

* @param int $timeout [optional]

* The number of microseconds until the first timeout. *

* @param int $retries [optional]

* The number of times to retry if timeouts occur. *

* @return bool TRUE on success or FALSE on failure. *

* If the SNMP host rejects the data type, an E_WARNING message like "Warning: Error in packet. Reason: (badValue) The value given has the wrong type or length." is shown. * If an unknown or invalid OID is specified the warning probably reads "Could not add variable". *

*/ function snmp3_set($host, $sec_name, $sec_level, $auth_protocol, $auth_passphrase, $priv_protocol, $priv_passphrase, $object_id, $type, $value, $timeout = 1000000, $retries = 5) {} /** * Specify the method how the SNMP values will be returned * @link https://php.net/manual/en/function.snmp-set-valueretrieval.php * @param int $method * types * * * * * * * * * * * * *
SNMP_VALUE_LIBRARYThe return values will be as returned by the Net-SNMP library.
SNMP_VALUE_PLAINThe return values will be the plain value without the SNMP type hint.
SNMP_VALUE_OBJECT * The return values will be objects with the properties "value" and "type", where the latter * is one of the SNMP_OCTET_STR, SNMP_COUNTER etc. constants. The * way "value" is returned is based on which one of constants * SNMP_VALUE_LIBRARY, SNMP_VALUE_PLAIN is set. *
* @return bool */ function snmp_set_valueretrieval($method) {} /** * Return the method how the SNMP values will be returned * @link https://php.net/manual/en/function.snmp-get-valueretrieval.php * @return int OR-ed combitantion of constants ( SNMP_VALUE_LIBRARY or * SNMP_VALUE_PLAIN ) with * possible SNMP_VALUE_OBJECT set. */ function snmp_get_valueretrieval() {} /** * Reads and parses a MIB file into the active MIB tree * @link https://php.net/manual/en/function.snmp-read-mib.php * @param string $filename

The filename of the MIB.

* @return bool */ function snmp_read_mib($filename) {} /** * As of 5.4 * @link https://php.net/manual/en/snmp.constants.php */ define('SNMP_OID_OUTPUT_SUFFIX', 1); /** * As of 5.4 * @link https://php.net/manual/en/snmp.constants.php */ define('SNMP_OID_OUTPUT_MODULE', 2); /** * As of 5.2 * @link https://php.net/manual/en/snmp.constants.php */ define('SNMP_OID_OUTPUT_FULL', 3); /** * As of 5.2 * @link https://php.net/manual/en/snmp.constants.php */ define('SNMP_OID_OUTPUT_NUMERIC', 4); /** * As of 5.4 * @link https://php.net/manual/en/snmp.constants.php */ define('SNMP_OID_OUTPUT_UCD', 5); /** * As of 5.4 * @link https://php.net/manual/en/snmp.constants.php */ define('SNMP_OID_OUTPUT_NONE', 6); define('SNMP_VALUE_LIBRARY', 0); define('SNMP_VALUE_PLAIN', 1); define('SNMP_VALUE_OBJECT', 2); define('SNMP_BIT_STR', 3); define('SNMP_OCTET_STR', 4); define('SNMP_OPAQUE', 68); define('SNMP_NULL', 5); define('SNMP_OBJECT_ID', 6); define('SNMP_IPADDRESS', 64); define('SNMP_COUNTER', 66); define('SNMP_UNSIGNED', 66); define('SNMP_TIMETICKS', 67); define('SNMP_UINTEGER', 71); define('SNMP_INTEGER', 2); define('SNMP_COUNTER64', 70); // End of snmp v.0.1 * @link https://github.com/iMega/grpc-phpdoc */ /** * Grpc * @see https://grpc.io * @see https://github.com/grpc/grpc/tree/master/src/php/ext/grpc */ namespace Grpc; /** * Register call error constants */ /** * everything went ok */ const CALL_OK = 0; /** * something failed, we don't know what */ const CALL_ERROR = 1; /** * this method is not available on the server */ const CALL_ERROR_NOT_ON_SERVER = 2; /** * this method is not available on the client */ const CALL_ERROR_NOT_ON_CLIENT = 3; /** * this method must be called before server_accept */ const CALL_ERROR_ALREADY_ACCEPTED = 4; /** * this method must be called before invoke */ const CALL_ERROR_ALREADY_INVOKED = 5; /** * this method must be called after invoke */ const CALL_ERROR_NOT_INVOKED = 6; /** * this call is already finished * (writes_done or write_status has already been called) */ const CALL_ERROR_ALREADY_FINISHED = 7; /** * there is already an outstanding read/write operation on the call */ const CALL_ERROR_TOO_MANY_OPERATIONS = 8; /** * the flags value was illegal for this call */ const CALL_ERROR_INVALID_FLAGS = 9; /** * invalid metadata was passed to this call */ const CALL_ERROR_INVALID_METADATA = 10; /** * invalid message was passed to this call */ const CALL_ERROR_INVALID_MESSAGE = 11; /** * completion queue for notification has not been registered with the * server */ const CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE = 12; /** * this batch of operations leads to more operations than allowed */ const CALL_ERROR_BATCH_TOO_BIG = 13; /** * payload type requested is not the type registered */ const CALL_ERROR_PAYLOAD_TYPE_MISMATCH = 14; /* * Register write flags */ /** * Hint that the write may be buffered and need not go out on the wire * immediately. GRPC is free to buffer the message until the next non-buffered * write, or until writes_done, but it need not buffer completely or at all. */ const WRITE_BUFFER_HINT = 1; /** * Force compression to be disabled for a particular write * (start_write/add_metadata). Illegal on invoke/accept. */ const WRITE_NO_COMPRESS = 2; /* * Register status constants */ /** * Not an error; returned on success */ const STATUS_OK = 0; /** * The operation was cancelled (typically by the caller). */ const STATUS_CANCELLED = 1; /** * Unknown error. An example of where this error may be returned is * if a Status value received from another address space belongs to * an error-space that is not known in this address space. Also * errors raised by APIs that do not return enough error information * may be converted to this error. */ const STATUS_UNKNOWN = 2; /** * Client specified an invalid argument. Note that this differs * from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments * that are problematic regardless of the state of the system * (e.g., a malformed file name). */ const STATUS_INVALID_ARGUMENT = 3; /** * Deadline expired before operation could complete. For operations * that change the state of the system, this error may be returned * even if the operation has completed successfully. For example, a * successful response from a server could have been delayed long * enough for the deadline to expire. */ const STATUS_DEADLINE_EXCEEDED = 4; /** * Some requested entity (e.g., file or directory) was not found. */ const STATUS_NOT_FOUND = 5; /* Some entity that we attempted to create (e.g., file or directory) * already exists. */ const STATUS_ALREADY_EXISTS = 6; /** * The caller does not have permission to execute the specified * operation. PERMISSION_DENIED must not be used for rejections * caused by exhausting some resource (use RESOURCE_EXHAUSTED * instead for those errors). PERMISSION_DENIED must not be * used if the caller can not be identified (use UNAUTHENTICATED * instead for those errors). */ const STATUS_PERMISSION_DENIED = 7; /** * The request does not have valid authentication credentials for the * operation. */ const STATUS_UNAUTHENTICATED = 16; /** * Some resource has been exhausted, perhaps a per-user quota, or * perhaps the entire file system is out of space. */ const STATUS_RESOURCE_EXHAUSTED = 8; /** * Operation was rejected because the system is not in a state * required for the operation's execution. For example, directory * to be deleted may be non-empty, an rmdir operation is applied to * a non-directory, etc. * * A litmus test that may help a service implementor in deciding * between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: * (a) Use UNAVAILABLE if the client can retry just the failing call. * (b) Use ABORTED if the client should retry at a higher-level * (e.g., restarting a read-modify-write sequence). * (c) Use FAILED_PRECONDITION if the client should not retry until * the system state has been explicitly fixed. E.g., if an "rmdir" * fails because the directory is non-empty, FAILED_PRECONDITION * should be returned since the client should not retry unless * they have first fixed up the directory by deleting files from it. * (d) Use FAILED_PRECONDITION if the client performs conditional * REST Get/Update/Delete on a resource and the resource on the * server does not match the condition. E.g., conflicting * read-modify-write on the same resource. */ const STATUS_FAILED_PRECONDITION = 9; /** * The operation was aborted, typically due to a concurrency issue * like sequencer check failures, transaction aborts, etc. * * See litmus test above for deciding between FAILED_PRECONDITION, * ABORTED, and UNAVAILABLE. */ const STATUS_ABORTED = 10; /** * Operation was attempted past the valid range. E.g., seeking or * reading past end of file. * * Unlike INVALID_ARGUMENT, this error indicates a problem that may * be fixed if the system state changes. For example, a 32-bit file * system will generate INVALID_ARGUMENT if asked to read at an * offset that is not in the range [0,2^32-1], but it will generate * OUT_OF_RANGE if asked to read from an offset past the current * file size. * * There is a fair bit of overlap between FAILED_PRECONDITION and * OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific * error) when it applies so that callers who are iterating through * a space can easily look for an OUT_OF_RANGE error to detect when * they are done. */ const STATUS_OUT_OF_RANGE = 11; /** * Operation is not implemented or not supported/enabled in this service. */ const STATUS_UNIMPLEMENTED = 12; /** * Internal errors. Means some invariants expected by underlying * system has been broken. If you see one of these errors, * something is very broken. */ const STATUS_INTERNAL = 13; /** * The service is currently unavailable. This is a most likely a * transient condition and may be corrected by retrying with * a backoff. * * See litmus test above for deciding between FAILED_PRECONDITION, * ABORTED, and UNAVAILABLE. */ const STATUS_UNAVAILABLE = 14; /** * Unrecoverable data loss or corruption. */ const STATUS_DATA_LOSS = 15; /* * Register op type constants */ /** * Send initial metadata: one and only one instance MUST be sent for each * call, unless the call was cancelled - in which case this can be skipped. * This op completes after all bytes of metadata have been accepted by * outgoing flow control. */ const OP_SEND_INITIAL_METADATA = 0; /** * Send a message: 0 or more of these operations can occur for each call. * This op completes after all bytes for the message have been accepted by * outgoing flow control. */ const OP_SEND_MESSAGE = 1; /** Send a close from the client: one and only one instance MUST be sent from * the client, unless the call was cancelled - in which case this can be * skipped. * This op completes after all bytes for the call (including the close) * have passed outgoing flow control. */ const OP_SEND_CLOSE_FROM_CLIENT = 2; /** * Send status from the server: one and only one instance MUST be sent from * the server unless the call was cancelled - in which case this can be * skipped. * This op completes after all bytes for the call (including the status) * have passed outgoing flow control. */ const OP_SEND_STATUS_FROM_SERVER = 3; /** * Receive initial metadata: one and only one MUST be made on the client, * must not be made on the server. * This op completes after all initial metadata has been read from the * peer. */ const OP_RECV_INITIAL_METADATA = 4; /** * Receive a message: 0 or more of these operations can occur for each call. * This op completes after all bytes of the received message have been * read, or after a half-close has been received on this call. */ const OP_RECV_MESSAGE = 5; /** * Receive status on the client: one and only one must be made on the client. * This operation always succeeds, meaning ops paired with this operation * will also appear to succeed, even though they may not have. In that case * the status will indicate some failure. * This op completes after all activity on the call has completed. */ const OP_RECV_STATUS_ON_CLIENT = 6; /** * Receive close on the server: one and only one must be made on the * server. * This op completes after the close has been received by the server. * This operation always succeeds, meaning ops paired with this operation * will also appear to succeed, even though they may not have. */ const OP_RECV_CLOSE_ON_SERVER = 7; /* * Register connectivity state constants */ /** * channel is idle */ const CHANNEL_IDLE = 0; /** * channel is connecting */ const CHANNEL_CONNECTING = 1; /** * channel is ready for work */ const CHANNEL_READY = 2; /** * channel has seen a failure but expects to recover */ const CHANNEL_TRANSIENT_FAILURE = 3; /** * channel has seen a failure that it cannot recover from */ const CHANNEL_SHUTDOWN = 4; const CHANNEL_FATAL_FAILURE = 4; /** * Class Server * @see https://github.com/grpc/grpc/tree/master/src/php/ext/grpc */ class Server { /** * Constructs a new instance of the Server class * * @param array $args The arguments to pass to the server (optional) */ public function __construct(array $args) {} /** * Request a call on a server. Creates a single GRPC_SERVER_RPC_NEW event. * * @param int $tag_new The tag to associate with the new request * @param int $tag_cancel The tag to use if the call is cancelled */ public function requestCall($tag_new, $tag_cancel) {} /** * Add a http2 over tcp listener. * * @param string $addr The address to add * * @return bool true on success, false on failure */ public function addHttp2Port($addr) {} /** * Add a secure http2 over tcp listener. * * @param string $addr The address to add * @param ServerCredentials $creds_obj * * @return bool true on success, false on failure */ public function addSecureHttp2Port($addr, $creds_obj) {} /** * Start a server - tells all listeners to start listening */ public function start() {} } /** * Class ServerCredentials * @see https://github.com/grpc/grpc/tree/master/src/php/ext/grpc */ class ServerCredentials { /** * Create SSL credentials. * * @param string $pem_root_certs PEM encoding of the server root certificates * @param string $pem_private_key PEM encoding of the client's private key * @param string $pem_cert_chain PEM encoding of the client's certificate chain * * @return object Credentials The new SSL credentials object * @throws \InvalidArgumentException */ public static function createSsl( $pem_root_certs, $pem_private_key, $pem_cert_chain ) {} } /** * Class Channel * @see https://github.com/grpc/grpc/tree/master/src/php/ext/grpc */ class Channel { /** * Construct an instance of the Channel class. If the $args array contains a * "credentials" key mapping to a ChannelCredentials object, a secure channel * will be created with those credentials. * * @param string $target The hostname to associate with this channel * @param array $args The arguments to pass to the Channel (optional) * * @throws \InvalidArgumentException */ public function __construct($target, $args = []) {} /** * Get the endpoint this call/stream is connected to * * @return string The URI of the endpoint */ public function getTarget() {} /** * Get the connectivity state of the channel * * @param bool $try_to_connect try to connect on the channel * * @return int The grpc connectivity state * @throws \InvalidArgumentException */ public function getConnectivityState($try_to_connect = false) {} /** * Watch the connectivity state of the channel until it changed * * @param int $last_state The previous connectivity state of the channel * @param Timeval $deadline_obj The deadline this function should wait until * * @return bool If the connectivity state changes from last_state * before deadline * @throws \InvalidArgumentException */ public function watchConnectivityState($last_state, Timeval $deadline_obj) {} /** * Close the channel */ public function close() {} } /** * Class ChannelCredentials * @see https://github.com/grpc/grpc/tree/master/src/php/ext/grpc */ class ChannelCredentials { /** * Set default roots pem. * * @param string $pem_roots PEM encoding of the server root certificates * * @throws \InvalidArgumentException */ public static function setDefaultRootsPem($pem_roots) {} /** * Create a default channel credentials object. * * @return ChannelCredentials The new default channel credentials object */ public static function createDefault() {} /** * Create SSL credentials. * * @param string|null $pem_root_certs PEM encoding of the server root certificates * @param string|null $pem_private_key PEM encoding of the client's private key * @param string|null $pem_cert_chain PEM encoding of the client's certificate chain * * @return ChannelCredentials The new SSL credentials object * @throws \InvalidArgumentException */ public static function createSsl( string $pem_root_certs = null, string $pem_private_key = null, string $pem_cert_chain = null ) {} /** * Create composite credentials from two existing credentials. * * @param ChannelCredentials $cred1 The first credential * @param CallCredentials $cred2 The second credential * * @return ChannelCredentials The new composite credentials object * @throws \InvalidArgumentException */ public static function createComposite( ChannelCredentials $cred1, CallCredentials $cred2 ) {} /** * Create insecure channel credentials * * @return null */ public static function createInsecure() {} } /** * Class Call * @see https://github.com/grpc/grpc/tree/master/src/php/ext/grpc */ class Call { /** * Constructs a new instance of the Call class. * * @param Channel $channel The channel to associate the call with. * Must not be closed. * @param string $method The method to call * @param Timeval $absolute_deadline The deadline for completing the call * @param null|string $host_override The host is set by user (optional) * * @throws \InvalidArgumentException */ public function __construct( Channel $channel, $method, Timeval $absolute_deadline, $host_override = null ) {} /** * Start a batch of RPC actions. * * @param array $batch Array of actions to take * * @return object Object with results of all actions * @throws \InvalidArgumentException * @throws \LogicException */ public function startBatch(array $batch) {} /** * Set the CallCredentials for this call. * * @param CallCredentials $creds_obj The CallCredentials object * * @return int The error code * @throws \InvalidArgumentException */ public function setCredentials(CallCredentials $creds_obj) {} /** * Get the endpoint this call/stream is connected to * * @return string The URI of the endpoint */ public function getPeer() {} /** * Cancel the call. This will cause the call to end with STATUS_CANCELLED if it * has not already ended with another status. */ public function cancel() {} } /** * Class CallCredentials * @see https://github.com/grpc/grpc/tree/master/src/php/ext/grpc */ class CallCredentials { /** * Create composite credentials from two existing credentials. * * @param CallCredentials $cred1 The first credential * @param CallCredentials $cred2 The second credential * * @return CallCredentials The new composite credentials object * @throws \InvalidArgumentException */ public static function createComposite( CallCredentials $cred1, CallCredentials $cred2 ) {} /** * Create a call credentials object from the plugin API * * @param \Closure $callback The callback function * * @return CallCredentials The new call credentials object * @throws \InvalidArgumentException */ public static function createFromPlugin(\Closure $callback) {} } /** * Class Timeval * * @see https://github.com/grpc/grpc/tree/master/src/php/ext/grpc */ class Timeval { /** * Constructs a new instance of the Timeval class * * @param int $usec The number of microseconds in the interval */ public function __construct($usec) {} /** * Adds another Timeval to this one and returns the sum. Calculations saturate * at infinities. * * @param Timeval $other The other Timeval object to add * * @return Timeval A new Timeval object containing the sum * @throws \InvalidArgumentException */ public function add(Timeval $other) {} /** * Return negative, 0, or positive according to whether a < b, a == b, or a > b * respectively. * * @param Timeval $a The first time to compare * @param Timeval $b The second time to compare * * @return int * @throws \InvalidArgumentException */ public static function compare(Timeval $a, Timeval $b) {} /** * Returns the infinite future time value as a timeval object * * @return Timeval Infinite future time value */ public static function infFuture() {} /** * Returns the infinite past time value as a timeval object * * @return Timeval Infinite past time value */ public static function infPast() {} /** * Returns the current time as a timeval object * * @return Timeval The current time */ public static function now() {} /** * Checks whether the two times are within $threshold of each other * * @param Timeval $a The first time to compare * @param Timeval $b The second time to compare * @param Timeval $threshold The threshold to check against * * @return bool True if $a and $b are within $threshold, False otherwise * @throws \InvalidArgumentException */ public static function similar(Timeval $a, Timeval $b, Timeval $threshold) {} /** * Sleep until this time, interpreted as an absolute timeout */ public function sleepUntil() {} /** * Subtracts another Timeval from this one and returns the difference. * Calculations saturate at infinities. * * @param Timeval $other The other Timeval object to subtract * * @return Timeval A new Timeval object containing the sum * @throws \InvalidArgumentException */ public function subtract(Timeval $other) {} /** * Returns the zero time interval as a timeval object * * @return Timeval Zero length time interval */ public static function zero() {} } DOMElement object from a SimpleXMLElement object * @link https://php.net/manual/en/function.dom-import-simplexml.php * @param SimpleXMLElement $node

* The SimpleXMLElement node. *

* @return DOMElement|null The DOMElement node added or NULL if any errors occur. */ #[LanguageLevelTypeAware(['8.0' => 'DOMElement'], default: 'DOMElement|null')] function dom_import_simplexml(object $node) {} /** * Node is a DOMElement * @link https://php.net/manual/en/dom.constants.php */ define('XML_ELEMENT_NODE', 1); /** * Node is a DOMAttr * @link https://php.net/manual/en/dom.constants.php */ define('XML_ATTRIBUTE_NODE', 2); /** * Node is a DOMText * @link https://php.net/manual/en/dom.constants.php */ define('XML_TEXT_NODE', 3); /** * Node is a DOMCharacterData * @link https://php.net/manual/en/dom.constants.php */ define('XML_CDATA_SECTION_NODE', 4); /** * Node is a DOMEntityReference * @link https://php.net/manual/en/dom.constants.php */ define('XML_ENTITY_REF_NODE', 5); /** * Node is a DOMEntity * @link https://php.net/manual/en/dom.constants.php */ define('XML_ENTITY_NODE', 6); /** * Node is a DOMProcessingInstruction * @link https://php.net/manual/en/dom.constants.php */ define('XML_PI_NODE', 7); /** * Node is a DOMComment * @link https://php.net/manual/en/dom.constants.php */ define('XML_COMMENT_NODE', 8); /** * Node is a DOMDocument * @link https://php.net/manual/en/dom.constants.php */ define('XML_DOCUMENT_NODE', 9); /** * Node is a DOMDocumentType * @link https://php.net/manual/en/dom.constants.php */ define('XML_DOCUMENT_TYPE_NODE', 10); /** * Node is a DOMDocumentFragment * @link https://php.net/manual/en/dom.constants.php */ define('XML_DOCUMENT_FRAG_NODE', 11); /** * Node is a DOMNotation * @link https://php.net/manual/en/dom.constants.php */ define('XML_NOTATION_NODE', 12); define('XML_HTML_DOCUMENT_NODE', 13); define('XML_DTD_NODE', 14); define('XML_ELEMENT_DECL_NODE', 15); define('XML_ATTRIBUTE_DECL_NODE', 16); define('XML_ENTITY_DECL_NODE', 17); define('XML_NAMESPACE_DECL_NODE', 18); define('XML_LOCAL_NAMESPACE', 18); define('XML_ATTRIBUTE_CDATA', 1); define('XML_ATTRIBUTE_ID', 2); define('XML_ATTRIBUTE_IDREF', 3); define('XML_ATTRIBUTE_IDREFS', 4); define('XML_ATTRIBUTE_ENTITY', 6); define('XML_ATTRIBUTE_NMTOKEN', 7); define('XML_ATTRIBUTE_NMTOKENS', 8); define('XML_ATTRIBUTE_ENUMERATION', 9); define('XML_ATTRIBUTE_NOTATION', 10); /** * Error code not part of the DOM specification. Meant for PHP errors. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_PHP_ERR', 0); /** * If index or size is negative, or greater than the allowed value. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_INDEX_SIZE_ERR', 1); /** * If the specified range of text does not fit into a * DOMString. * @link https://php.net/manual/en/dom.constants.php */ define('DOMSTRING_SIZE_ERR', 2); /** * If any node is inserted somewhere it doesn't belong * @link https://php.net/manual/en/dom.constants.php */ define('DOM_HIERARCHY_REQUEST_ERR', 3); /** * If a node is used in a different document than the one that created it. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_WRONG_DOCUMENT_ERR', 4); /** * If an invalid or illegal character is specified, such as in a name. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_INVALID_CHARACTER_ERR', 5); /** * If data is specified for a node which does not support data. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_NO_DATA_ALLOWED_ERR', 6); /** * If an attempt is made to modify an object where modifications are not allowed. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_NO_MODIFICATION_ALLOWED_ERR', 7); /** * If an attempt is made to reference a node in a context where it does not exist. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_NOT_FOUND_ERR', 8); /** * If the implementation does not support the requested type of object or operation. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_NOT_SUPPORTED_ERR', 9); /** * If an attempt is made to add an attribute that is already in use elsewhere. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_INUSE_ATTRIBUTE_ERR', 10); /** * If an attempt is made to use an object that is not, or is no longer, usable. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_INVALID_STATE_ERR', 11); /** * If an invalid or illegal string is specified. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_SYNTAX_ERR', 12); /** * If an attempt is made to modify the type of the underlying object. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_INVALID_MODIFICATION_ERR', 13); /** * If an attempt is made to create or change an object in a way which is * incorrect with regard to namespaces. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_NAMESPACE_ERR', 14); /** * If a parameter or an operation is not supported by the underlying object. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_INVALID_ACCESS_ERR', 15); /** * If a call to a method such as insertBefore or removeChild would make the Node * invalid with respect to "partial validity", this exception would be raised and * the operation would not be done. * @link https://php.net/manual/en/dom.constants.php */ define('DOM_VALIDATION_ERR', 16); // End of dom v.20031129 'string'], default: '')] public $nodeName; /** * @var string|null * The value of this node, depending on its type * @link https://php.net/manual/en/class.domnode.php#domnode.props.nodevalue */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $nodeValue; /** * @var int * Gets the type of the node. One of the predefined * XML_xxx_NODE constants * @link https://php.net/manual/en/class.domnode.php#domnode.props.nodetype */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $nodeType; /** * @var DOMNode|null * The parent of this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.parentnode */ #[LanguageLevelTypeAware(['8.1' => 'DOMNode|null'], default: '')] public $parentNode; /** * @var DOMNodeList * A DOMNodeList that contains all children of this node. If there are no children, this is an empty DOMNodeList. * @link https://php.net/manual/en/class.domnode.php#domnode.props.childnodes */ #[LanguageLevelTypeAware(['8.1' => 'DOMNodeList'], default: '')] public $childNodes; /** * @var DOMNode|null * The first child of this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.firstchild */ #[LanguageLevelTypeAware(['8.1' => 'DOMNode|null'], default: '')] public $firstChild; /** * @var DOMNode|null * The last child of this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.lastchild */ #[LanguageLevelTypeAware(['8.1' => 'DOMNode|null'], default: '')] public $lastChild; /** * @var DOMNode|null * The node immediately preceding this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.previoussibling */ #[LanguageLevelTypeAware(['8.1' => 'DOMNode|null'], default: '')] public $previousSibling; /** * @var DOMNode|null * The node immediately following this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.nextsibling */ #[LanguageLevelTypeAware(['8.1' => 'DOMNode|null'], default: '')] public $nextSibling; /** * @var DOMNamedNodeMap|null * A DOMNamedNodeMap containing the attributes of this node (if it is a DOMElement) or NULL otherwise. * @link https://php.net/manual/en/class.domnode.php#domnode.props.attributes */ #[LanguageLevelTypeAware(['8.1' => 'DOMNamedNodeMap|null'], default: '')] public $attributes; /** * @var DOMDocument|null * The DOMDocument object associated with this node, or NULL if this node is a DOMDocument. * @link https://php.net/manual/en/class.domnode.php#domnode.props.ownerdocument */ #[LanguageLevelTypeAware(['8.1' => 'DOMDocument|null'], default: '')] public $ownerDocument; /** * @var string|null * The namespace URI of this node, or NULL if it is unspecified. * @link https://php.net/manual/en/class.domnode.php#domnode.props.namespaceuri */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $namespaceURI; /** * @var string|null * The namespace prefix of this node, or NULL if it is unspecified. * @link https://php.net/manual/en/class.domnode.php#domnode.props.prefix */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $prefix; /** * @var string|null * Returns the local part of the qualified name of this node. * @link https://php.net/manual/en/class.domnode.php#domnode.props.localname */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $localName; /** * @var string|null * The absolute base URI of this node or NULL if the implementation wasn't able to obtain an absolute URI. * @link https://php.net/manual/en/class.domnode.php#domnode.props.baseuri */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $baseURI; /** * @var string * This attribute returns the text content of this node and its descendants. * @link https://php.net/manual/en/class.domnode.php#domnode.props.textcontent */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $textContent; #[PhpStormStubsElementAvailable(from: '8.3')] public bool $isConnected; #[PhpStormStubsElementAvailable(from: '8.3')] public ?DOMElement $parentElement; /** * Adds a new child before a reference node * @link https://php.net/manual/en/domnode.insertbefore.php * @param DOMNode $node

* The new node. *

* @param null|DOMNode $child [optional]

* The reference node. If not supplied, newnode is * appended to the children. *

* @return DOMNode The inserted node. */ public function insertBefore( DOMNode $node, #[LanguageLevelTypeAware(['8.0' => 'DOMNode|null'], default: 'DOMNode')] $child = null ) {} /** * Replaces a child * @link https://php.net/manual/en/domnode.replacechild.php * @param DOMNode $node

* The new node. It must be a member of the target document, i.e. * created by one of the DOMDocument->createXXX() methods or imported in * the document by . *

* @param DOMNode $child

* The old node. *

* @return DOMNode|false The old node or false if an error occur. */ public function replaceChild(DOMNode $node, DOMNode $child) {} /** * Removes child from list of children * @link https://php.net/manual/en/domnode.removechild.php * @param DOMNode $child

* The removed child. *

* @return DOMNode If the child could be removed the functions returns the old child. */ public function removeChild(DOMNode $child) {} /** * Adds new child at the end of the children * @link https://php.net/manual/en/domnode.appendchild.php * @param DOMNode $node

* The appended child. *

* @return DOMNode The node added. */ public function appendChild(DOMNode $node) {} /** * Checks if node has children * @link https://php.net/manual/en/domnode.haschildnodes.php * @return bool true on success or false on failure. */ #[TentativeType] public function hasChildNodes(): bool {} /** * Clones a node * @link https://php.net/manual/en/domnode.clonenode.php * @param bool $deep

* Indicates whether to copy all descendant nodes. This parameter is * defaulted to false. *

* @return static The cloned node. */ public function cloneNode( #[PhpStormStubsElementAvailable(from: '5.3', to: '5.6')] $deep, #[PhpStormStubsElementAvailable(from: '7.0')] #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $deep = false ) {} /** * Normalizes the node * @link https://php.net/manual/en/domnode.normalize.php * @return void */ #[TentativeType] public function normalize(): void {} /** * Checks if feature is supported for specified version * @link https://php.net/manual/en/domnode.issupported.php * @param string $feature

* The feature to test. See the example of * DOMImplementation::hasFeature for a * list of features. *

* @param string $version

* The version number of the feature to test. *

* @return bool true on success or false on failure. */ #[TentativeType] public function isSupported( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $feature, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $version ): bool {} /** * Checks if node has attributes * @link https://php.net/manual/en/domnode.hasattributes.php * @return bool true on success or false on failure. */ #[TentativeType] public function hasAttributes(): bool {} /** * @return int */ #[LanguageLevelTypeAware(['8.4' => 'int'], default: '')] public function compareDocumentPosition(DOMNode $other) {} /** * Indicates if two nodes are the same node * @link https://php.net/manual/en/domnode.issamenode.php * @param DOMNode $otherNode

* The compared node. *

* @return bool true on success or false on failure. */ #[TentativeType] public function isSameNode(DOMNode $otherNode): bool {} /** * Gets the namespace prefix of the node based on the namespace URI * @link https://php.net/manual/en/domnode.lookupprefix.php * @param string $namespace

* The namespace URI. *

* @return string The prefix of the namespace. */ #[TentativeType] public function lookupPrefix(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace): ?string {} /** * Checks if the specified namespaceURI is the default namespace or not * @link https://php.net/manual/en/domnode.isdefaultnamespace.php * @param string $namespace

* The namespace URI to look for. *

* @return bool Return true if namespaceURI is the default * namespace, false otherwise. */ #[TentativeType] public function isDefaultNamespace(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace): bool {} /** * Gets the namespace URI of the node based on the prefix * @link https://php.net/manual/en/domnode.lookupnamespaceuri.php * @param string|null $prefix

* The prefix of the namespace. *

* @return string|null The namespace URI of the node. */ #[PhpStormStubsElementAvailable(from: '8.0')] #[TentativeType] public function lookupNamespaceURI(?string $prefix): ?string {} /** * Gets the namespace URI of the node based on the prefix * @link https://php.net/manual/en/domnode.lookupnamespaceuri.php * @param string|null $prefix

* The prefix of the namespace. *

* @return string|null The namespace URI of the node. */ #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] public function lookupNamespaceUri($prefix) {} /** * @param DOMNode|null $arg * @return bool */ #[LanguageLevelTypeAware(['8.3' => 'bool'], default: '')] public function isEqualNode(#[LanguageLevelTypeAware(['8.3' => 'DOMNode|null'], default: 'DOMNode')] $otherNode) {} public function getFeature($feature, $version) {} public function setUserData($key, $data, $handler) {} public function getUserData($key) {} /** * Gets an XPath location path for the node * @return string|null the XPath, or NULL in case of an error. * @link https://secure.php.net/manual/en/domnode.getnodepath.php */ #[TentativeType] public function getNodePath(): ?string {} /** * Get line number for a node * @link https://php.net/manual/en/domnode.getlineno.php * @return int Always returns the line number where the node was defined in. */ #[TentativeType] public function getLineNo(): int {} /** * Canonicalize nodes to a string * @param bool $exclusive [optional] Enable exclusive parsing of only the nodes matched by the provided xpath or namespace prefixes. * @param bool $withComments [optional] Retain comments in output. * @param null|array $xpath [optional] An array of xpaths to filter the nodes by. * @param null|array $nsPrefixes [optional] An array of namespace prefixes to filter the nodes by. * @return string|false Canonicalized nodes as a string or FALSE on failure */ #[TentativeType] public function C14N( #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $exclusive = false, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $withComments = false, #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: 'array')] $xpath = null, #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: 'array')] $nsPrefixes = null ): string|false {} /** * Canonicalize nodes to a file. * @link https://www.php.net/manual/en/domnode.c14nfile * @param string $uri Number of bytes written or FALSE on failure * @param bool $exclusive [optional] Enable exclusive parsing of only the nodes matched by the provided xpath or namespace prefixes. * @param bool $withComments [optional] Retain comments in output. * @param null|array $xpath [optional] An array of xpaths to filter the nodes by. * @param null|array $nsPrefixes [optional] An array of namespace prefixes to filter the nodes by. * @return int|false Number of bytes written or FALSE on failure */ #[TentativeType] public function C14NFile( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $uri, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $exclusive = false, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $withComments = false, #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: 'array')] $xpath = null, #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: 'array')] $nsPrefixes = null ): int|false {} /** * @since 8.3 */ public function contains(DOMNode|DOMNameSpaceNode|null $other): bool {} /** * @since 8.3 */ public function getRootNode(?array $options = null): DOMNode {} /** * @since 8.1 */ public function __sleep(): array {} /** * @since 8.1 */ public function __wakeup(): void {} } /** * DOM operations raise exceptions under particular circumstances, i.e., * when an operation is impossible to perform for logical reasons. * @link https://php.net/manual/en/class.domexception.php */ final class DOMException extends Exception { /** * @link https://php.net/manual/en/class.domexception.php#domexception.props.code * @var int An integer indicating the type of error generated */ public $code; } class DOMStringList { /** * @param $index * @return mixed */ public function item($index) {} } /** * @link https://php.net/manual/en/ref.dom.php * @removed 8.0 */ class DOMNameList { /** * @param $index * @return mixed */ public function getName($index) {} /** * @param $index * @return mixed */ public function getNamespaceURI($index) {} } /** * @removed 8.0 */ class DOMImplementationList { /** * @param $index * @return mixed */ public function item($index) {} } /** * @removed 8.0 */ class DOMImplementationSource { /** * @param $features * @return mixed */ public function getDomimplementation($features) {} /** * @param $features * @return mixed */ public function getDomimplementations($features) {} } /** * The DOMImplementation interface provides a number * of methods for performing operations that are independent of any * particular instance of the document object model. * @link https://php.net/manual/en/class.domimplementation.php */ class DOMImplementation { /** * @param string $feature * @param string $version * @return mixed */ #[TentativeType] public function getFeature( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $feature, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $version ): never {} /** * Test if the DOM implementation implements a specific feature * @link https://php.net/manual/en/domimplementation.hasfeature.php * @param string $feature

* The feature to test. *

* @param string $version

* The version number of the feature to test. In * level 2, this can be either 2.0 or 1.0. *

* @return bool true on success or false on failure. */ public function hasFeature($feature, $version) {} /** * Creates an empty DOMDocumentType object * @link https://php.net/manual/en/domimplementation.createdocumenttype.php * @param string $qualifiedName

* The qualified name of the document type to create. *

* @param string $publicId

* The external subset public identifier. *

* @param string $systemId

* The external subset system identifier. *

* @return DOMDocumentType|false A new DOMDocumentType node with its * ownerDocument set to null. * @throws DOMException If there is an error with the namespace */ public function createDocumentType( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $publicId, #[PhpStormStubsElementAvailable(from: '8.0')] string $publicId = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $systemId, #[PhpStormStubsElementAvailable(from: '8.0')] string $systemId = '' ) {} /** * Creates a DOMDocument object of the specified type with its document element * @link https://php.net/manual/en/domimplementation.createdocument.php * @param string|null $namespace

* The namespace URI of the document element to create. *

* @param string $qualifiedName

* The qualified name of the document element to create. *

* @param DOMDocumentType|null $doctype

* The type of document to create or null. *

* @return DOMDocument|false A new DOMDocument object. If * namespaceURI, qualifiedName, and doctype are null, the * returned DOMDocument is empty with no document element. * @throws DOMException If $doctype has already been used * with adifferent document or was created from a different * implementation. If there is an error with the namespace, * as determined by $namespace and $qualifiedName. */ #[LanguageLevelTypeAware(['8.4' => 'DOMDocument'], default: 'DOMDocument|false')] #[TentativeType] public function createDocument( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $namespace, #[PhpStormStubsElementAvailable(from: '8.0')] ?string $namespace = null, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $qualifiedName, #[PhpStormStubsElementAvailable(from: '8.0')] string $qualifiedName = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.3')] DOMDocumentType $doctype, #[PhpStormStubsElementAvailable(from: '7.4')] #[LanguageLevelTypeAware(['8.0' => 'DOMDocumentType|null'], default: 'DOMDocumentType')] $doctype = null ) {} } class DOMNameSpaceNode { #[LanguageLevelTypeAware(['8.1' => 'DOMNode|null'], default: '')] public $parentNode; #[LanguageLevelTypeAware(['8.1' => 'DOMDocument|null'], default: '')] public $ownerDocument; #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $namespaceURI; #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $localName; #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $prefix; #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $nodeType; #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $nodeValue; #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $nodeName; public ?DOMElement $parentElement; public bool $isConnected; /** * @since 8.1 */ public function __sleep(): array {} /** * @since 8.1 */ public function __wakeup(): void {} } /** * The DOMDocumentFragment class * @link https://php.net/manual/en/class.domdocumentfragment.php */ class DOMDocumentFragment extends DOMNode implements DOMParentNode { #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $childElementCount; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $lastElementChild; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $firstElementChild; public function __construct() {} /** * Append raw XML data * @link https://php.net/manual/en/domdocumentfragment.appendxml.php * @param string $data

* XML to append. *

* @return bool true on success or false on failure. */ #[TentativeType] public function appendXML(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data): bool {} /** * {@inheritDoc} */ public function append(...$nodes): void {} /** * {@inheritDoc} */ public function prepend(...$nodes): void {} /** * @since 8.3 * {@inheritDoc} */ public function replaceChildren(...$nodes): void {} } /** * The DOMDocument class represents an entire HTML or XML * document; serves as the root of the document tree. * @link https://php.net/manual/en/class.domdocument.php */ class DOMDocument extends DOMNode implements DOMParentNode { /** * @var string|null * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.actualencoding */ #[Deprecated("Actual encoding of the document, is a readonly equivalent to encoding.")] #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $actualEncoding; /** * @var DOMConfiguration * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.config * @see DOMDocument::normalizeDocument() */ #[Deprecated("Configuration used when DOMDocument::normalizeDocument() is invoked.")] #[LanguageLevelTypeAware(['8.1' => 'mixed'], default: '')] public $config; /** * @var DOMDocumentType * The Document Type Declaration associated with this document. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.doctype */ #[LanguageLevelTypeAware(['8.1' => 'DOMDocumentType|null'], default: '')] public $doctype; /** * @var DOMElement * This is a convenience attribute that allows direct access to the child node * that is the document element of the document. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.documentelement */ #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $documentElement; /** * @var string|null * The location of the document or NULL if undefined. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.documenturi */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $documentURI; /** * @var string|null * Encoding of the document, as specified by the XML declaration. This attribute is not present * in the final DOM Level 3 specification, but is the only way of manipulating XML document * encoding in this implementation. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.encoding */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $encoding; /** * @var bool * Nicely formats output with indentation and extra space. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.formatoutput */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $formatOutput; /** * @var DOMImplementation * The DOMImplementation object that handles this document. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.implementation */ #[LanguageLevelTypeAware(['8.1' => 'DOMImplementation'], default: '')] public $implementation; /** * @var bool * Do not remove redundant white space. Default to TRUE. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.preservewhitespace */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $preserveWhiteSpace = true; /** * @var bool * Proprietary. Enables recovery mode, i.e. trying to parse non-well formed documents. * This attribute is not part of the DOM specification and is specific to libxml. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.recover */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $recover; /** * @var bool * Set it to TRUE to load external entities from a doctype declaration. This is useful for * including character entities in your XML document. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.resolveexternals */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $resolveExternals; /** * @var bool * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.standalone */ #[Deprecated("Whether or not the document is standalone, as specified by the XML declaration, corresponds to xmlStandalone.")] #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $standalone; /** * @var bool * Throws DOMException on errors. Default to TRUE. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.stricterrorchecking */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $strictErrorChecking = true; /** * @var bool * Proprietary. Whether or not to substitute entities. This attribute is not part of the DOM * specification and is specific to libxml. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.substituteentities */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $substituteEntities; /** * @var bool * Loads and validates against the DTD. Default to FALSE. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.validateonparse */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $validateOnParse = false; /** * @var string * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.version */ #[Deprecated('Version of XML, corresponds to xmlVersion')] #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $version; /** * @var string|null * An attribute specifying, as part of the XML declaration, the encoding of this document. This is NULL when * unspecified or when it is not known, such as when the Document was created in memory. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.xmlencoding */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $xmlEncoding; /** * @var bool * An attribute specifying, as part of the XML declaration, whether this document is standalone. * This is FALSE when unspecified. * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.xmlstandalone */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $xmlStandalone; /** * @var string|null * An attribute specifying, as part of the XML declaration, the version number of this document. If there is no * declaration and if this document supports the "XML" feature, the value is "1.0". * @link https://php.net/manual/en/class.domdocument.php#domdocument.props.xmlversion */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $xmlVersion; #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $childElementCount; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $lastElementChild; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $firstElementChild; /** * Create new element node * @link https://php.net/manual/en/domdocument.createelement.php * @param string $localName

* The tag name of the element. *

* @param string $value [optional]

* The value of the element. By default, an empty element will be created. * You can also set the value later with DOMElement->nodeValue. *

* @return DOMElement|false A new instance of class DOMElement or false * if an error occurred. * @throws DOMException If invalid $localName */ public function createElement( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $value = '' ) {} /** * Create new document fragment * @link https://php.net/manual/en/domdocument.createdocumentfragment.php * @return DOMDocumentFragment|false The new DOMDocumentFragment or false if an error occurred. */ #[TentativeType] public function createDocumentFragment(): DOMDocumentFragment {} /** * Create new text node * @link https://php.net/manual/en/domdocument.createtextnode.php * @param string $data

* The content of the text. *

* @return DOMText|false The new DOMText or false if an error occurred. */ #[TentativeType] public function createTextNode(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data): DOMText {} /** * Create new comment node * @link https://php.net/manual/en/domdocument.createcomment.php * @param string $data

* The content of the comment. *

* @return DOMComment|false The new DOMComment or false if an error occurred. */ #[TentativeType] public function createComment(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data): DOMComment {} /** * Create new cdata node * @link https://php.net/manual/en/domdocument.createcdatasection.php * @param string $data

* The content of the cdata. *

* @return DOMCDATASection|false The new DOMCDATASection or false if an error occurred. */ public function createCDATASection(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data) {} /** * Creates new PI node * @link https://php.net/manual/en/domdocument.createprocessinginstruction.php * @param string $target

* The target of the processing instruction. *

* @param string $data

* The content of the processing instruction. *

* @return DOMProcessingInstruction|false The new DOMProcessingInstruction or false if an error occurred. */ public function createProcessingInstruction( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $target, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.3')] $data, #[PhpStormStubsElementAvailable(from: '7.4')] #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data = '' ) {} /** * Create new attribute * @link https://php.net/manual/en/domdocument.createattribute.php * @param string $localName

* The name of the attribute. *

* @return DOMAttr|false The new DOMAttr or false if an error occurred. * @throws DOMException If invalid $localName */ public function createAttribute(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName) {} /** * Create new entity reference node * @link https://php.net/manual/en/domdocument.createentityreference.php * @param string $name

* The content of the entity reference, e.g. the entity reference minus * the leading & and the trailing * ; characters. *

* @return DOMEntityReference|false The new DOMEntityReference or false if an error * occurred. */ public function createEntityReference(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name) {} /** * Searches for all elements with given tag name * @link https://php.net/manual/en/domdocument.getelementsbytagname.php * @param string $qualifiedName

* The name of the tag to match on. The special value * * matches all tags. *

* @return DOMNodeList A new DOMNodeList object containing all the matched * elements. */ #[TentativeType] public function getElementsByTagName(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName): DOMNodeList {} /** * Import node into current document * @link https://php.net/manual/en/domdocument.importnode.php * @param DOMNode $node

* The node to import. *

* @param bool $deep

* If set to true, this method will recursively import the subtree under * the importedNode. *

*

* To copy the nodes attributes deep needs to be set to true *

* @return DOMNode|false The copied node or false, if it cannot be copied. */ public function importNode( DOMNode $node, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.3')] $deep, #[PhpStormStubsElementAvailable(from: '7.4')] #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $deep = false ) {} /** * Create new element node with an associated namespace * @link https://php.net/manual/en/domdocument.createelementns.php * @param string|null $namespace

* The URI of the namespace. *

* @param string $qualifiedName

* The qualified name of the element, as prefix:tagname. *

* @param string $value [optional]

* The value of the element. By default, an empty element will be created. * You can also set the value later with DOMElement->nodeValue. *

* @return DOMElement|false The new DOMElement or false if an error occurred. * @throws DOMException If invalid $namespace or $qualifiedName */ public function createElementNS( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $value = '' ) {} /** * Create new attribute node with an associated namespace * @link https://php.net/manual/en/domdocument.createattributens.php * @param string|null $namespace

* The URI of the namespace. *

* @param string $qualifiedName

* The tag name and prefix of the attribute, as prefix:tagname. *

* @return DOMAttr|false The new DOMAttr or false if an error occurred. * @throws DOMException If invalid $namespace or $qualifiedName */ public function createAttributeNS( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName ) {} /** * Searches for all elements with given tag name in specified namespace * @link https://php.net/manual/en/domdocument.getelementsbytagnamens.php * @param string $namespace

* The namespace URI of the elements to match on. * The special value * matches all namespaces. *

* @param string $localName

* The local name of the elements to match on. * The special value * matches all local names. *

* @return DOMNodeList A new DOMNodeList object containing all the matched * elements. */ #[TentativeType] public function getElementsByTagNameNS( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName ): DOMNodeList {} /** * Searches for an element with a certain id * @link https://php.net/manual/en/domdocument.getelementbyid.php * @param string $elementId

* The unique id value for an element. *

* @return DOMElement|null The DOMElement or null if the element is * not found. */ #[TentativeType] public function getElementById(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $elementId): ?DOMElement {} #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'DOMNode|false'], default: '')] public function adoptNode(DOMNode $node) {} /** * {@inheritDoc} */ public function append(...$nodes): void {} /** * {@inheritDoc} */ public function prepend(...$nodes): void {} /** * @since 8.3 * {@inheritDoc} */ public function replaceChildren(...$nodes): void {} /** * Normalizes the document * @link https://php.net/manual/en/domdocument.normalizedocument.php * @return void */ #[TentativeType] public function normalizeDocument(): void {} /** * @param DOMNode $node * @param $namespace * @param $qualifiedName */ public function renameNode(DOMNode $node, $namespace, $qualifiedName) {} /** * Load XML from a file * @link https://php.net/manual/en/domdocument.load.php * @param string $filename

* The path to the XML document. *

* @param int $options [optional]

* Bitwise OR * of the libxml option constants. *

* @return DOMDocument|bool true on success or false on failure. Prior to PHP 8.3 if called statically, returns a * DOMDocument and issues E_STRICT * warning. */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'bool'], default: 'DOMDocument|bool')] public function load( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = 0 ) {} /** * Dumps the internal XML tree back into a file * @link https://php.net/manual/en/domdocument.save.php * @param string $filename

* The path to the saved XML document. *

* @param int $options [optional]

* Additional Options. Currently only LIBXML_NOEMPTYTAG is supported. *

* @return int|false the number of bytes written or false if an error occurred. */ public function save($filename, $options = null) {} /** * Load XML from a string * @link https://php.net/manual/en/domdocument.loadxml.php * @param string $source

* The string containing the XML. *

* @param int $options [optional]

* Bitwise OR * of the libxml option constants. *

* @return DOMDocument|bool true on success or false on failure. Prior to PHP 8.3 if called statically, returns a * DOMDocument and issues E_STRICT * warning. */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'bool'], default: 'DOMDocument|bool')] public function loadXML( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $source, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = 0 ) {} /** * Dumps the internal XML tree back into a string * @link https://php.net/manual/en/domdocument.savexml.php * @param null|DOMNode $node [optional]

* Use this parameter to output only a specific node without XML declaration * rather than the entire document. *

* @param int $options [optional]

* Additional Options. Currently only LIBXML_NOEMPTYTAG is supported. *

* @return string|false the XML, or false if an error occurred. */ #[TentativeType] public function saveXML( #[LanguageLevelTypeAware(['7.1' => '?DOMNode'], default: '')] $node = null, #[PhpStormStubsElementAvailable(from: '7.0')] #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = 0 ): string|false {} /** * Creates a new DOMDocument object * @link https://php.net/manual/en/domdocument.construct.php * @param string $version [optional] The version number of the document as part of the XML declaration. * @param string $encoding [optional] The encoding of the document as part of the XML declaration. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $version = '1.0', #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $encoding = '' ) {} /** * Validates the document based on its DTD * @link https://php.net/manual/en/domdocument.validate.php * @return bool true on success or false on failure. * If the document have no DTD attached, this method will return false. */ #[TentativeType] public function validate(): bool {} /** * Substitutes XIncludes in a DOMDocument Object * @link https://php.net/manual/en/domdocument.xinclude.php * @param int $options [optional]

* libxml parameters. Available * since PHP 5.1.0 and Libxml 2.6.7. *

* @return int|false the number of XIncludes in the document. */ #[TentativeType] public function xinclude(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = 0): int|false {} /** * Load HTML from a string * @link https://php.net/manual/en/domdocument.loadhtml.php * @param string $source

* The HTML string. *

* @param int $options [optional]

* Since PHP 5.4.0 and Libxml 2.6.0, you may also * use the options parameter to specify additional Libxml parameters. *

* @return DOMDocument|bool true on success or false on failure. Prior to PHP 8.3 if called statically, returns a * DOMDocument and issues E_STRICT * warning. */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'bool'], default: 'DOMDocument|bool')] public function loadHTML( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $source, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = 0 ) {} /** * Load HTML from a file * @link https://php.net/manual/en/domdocument.loadhtmlfile.php * @param string $filename

* The path to the HTML file. *

* @param int $options [optional]

* Since PHP 5.4.0 and Libxml 2.6.0, you may also * use the options parameter to specify additional Libxml parameters. *

* @return DOMDocument|bool true on success or false on failure. Prior to PHP 8.3 if called statically, returns a * DOMDocument and issues E_STRICT * warning. */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'bool'], default: 'DOMDocument|bool')] public function loadHTMLFile( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = 0 ) {} /** * Dumps the internal document into a string using HTML formatting * @link https://php.net/manual/en/domdocument.savehtml.php * @param null|DOMNode $node [optional] parameter to output a subset of the document. * @return string|false The HTML, or false if an error occurred. */ public function saveHTML(DOMNode $node = null) {} /** * Dumps the internal document into a file using HTML formatting * @link https://php.net/manual/en/domdocument.savehtmlfile.php * @param string $filename

* The path to the saved HTML document. *

* @return int|false the number of bytes written or false if an error occurred. */ #[TentativeType] public function saveHTMLFile(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename): int|false {} /** * Validates a document based on a schema * @link https://php.net/manual/en/domdocument.schemavalidate.php * @param string $filename

* The path to the schema. *

* @param int $options [optional]

* Bitwise OR * of the libxml option constants. *

* @return bool true on success or false on failure. */ public function schemaValidate($filename, $options = null) {} /** * Validates a document based on a schema * @link https://php.net/manual/en/domdocument.schemavalidatesource.php * @param string $source

* A string containing the schema. *

* @param int $flags [optional]

A bitmask of Libxml schema validation flags. Currently the only supported value is LIBXML_SCHEMA_CREATE. * Available since PHP 5.5.2 and Libxml 2.6.14.

* @return bool true on success or false on failure. */ public function schemaValidateSource($source, $flags) {} /** * Performs relaxNG validation on the document * @link https://php.net/manual/en/domdocument.relaxngvalidate.php * @param string $filename

* The RNG file. *

* @return bool true on success or false on failure. */ #[TentativeType] public function relaxNGValidate(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename): bool {} /** * Performs relaxNG validation on the document * @link https://php.net/manual/en/domdocument.relaxngvalidatesource.php * @param string $source

* A string containing the RNG schema. *

* @return bool true on success or false on failure. */ #[TentativeType] public function relaxNGValidateSource(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $source): bool {} /** * Register extended class used to create base node type * @link https://php.net/manual/en/domdocument.registernodeclass.php * @param string $baseClass

* The DOM class that you want to extend. You can find a list of these * classes in the chapter introduction. *

* @param string $extendedClass

* Your extended class name. If null is provided, any previously * registered class extending baseclass will * be removed. *

* @return bool true on success or false on failure. */ #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] public function registerNodeClass( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $baseClass, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $extendedClass ) {} } /** * The DOMNodeList class * @link https://php.net/manual/en/class.domnodelist.php */ class DOMNodeList implements IteratorAggregate, Countable { /** * @var int * The number of nodes in the list. The range of valid child node indices is 0 to length - 1 inclusive. * @link https://php.net/manual/en/class.domnodelist.php#domnodelist.props.length */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] #[Immutable] public $length; /** * Retrieves a node specified by index * @link https://php.net/manual/en/domnodelist.item.php * @param int $index

* Index of the node into the collection. * The range of valid child node indices is 0 to length - 1 inclusive. *

* @return DOMElement|DOMNode|DOMNameSpaceNode|null The node at the indexth position in the * DOMNodeList, or null if that is not a valid * index. */ public function item(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index) {} /** * @return int<0, max> * @since 7.2 */ #[TentativeType] public function count(): int {} /** * @return Iterator * @since 8.0 */ public function getIterator(): Iterator {} } /** * The DOMNamedNodeMap class * @link https://php.net/manual/en/class.domnamednodemap.php * @property-read int $length The number of nodes in the map. The range of valid child node indices is 0 to length - 1 inclusive. */ class DOMNamedNodeMap implements IteratorAggregate, Countable { /** * The number of nodes in the map. The range of valid child node indices is 0 to length - 1 inclusive. * @var int * @readonly */ #[PhpStormStubsElementAvailable(from: '8.1')] public $length; /** * Retrieves a node specified by name * @link https://php.net/manual/en/domnamednodemap.getnameditem.php * @param string $qualifiedName

* The nodeName of the node to retrieve. *

* @return DOMNode|null A node (of any type) with the specified nodeName, or * null if no node is found. */ #[TentativeType] public function getNamedItem(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName): ?DOMNode {} /** * @param DOMNode $arg */ public function setNamedItem(DOMNode $arg) {} /** * @param $name [optional] */ public function removeNamedItem($name) {} /** * Retrieves a node specified by index * @link https://php.net/manual/en/domnamednodemap.item.php * @param int $index

* Index into this map. *

* @return DOMNode|null The node at the indexth position in the map, or null * if that is not a valid index (greater than or equal to the number of nodes * in this map). */ #[TentativeType] public function item( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] $index = 0, #[PhpStormStubsElementAvailable(from: '7.1')] #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index ): ?DOMNode {} /** * Retrieves a node specified by local name and namespace URI * @link https://php.net/manual/en/domnamednodemap.getnameditemns.php * @param string $namespace

* The namespace URI of the node to retrieve. *

* @param string $localName

* The local name of the node to retrieve. *

* @return DOMNode|null A node (of any type) with the specified local name and namespace URI, or * null if no node is found. */ #[TentativeType] public function getNamedItemNS( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $namespaceURI = '', #[PhpStormStubsElementAvailable(from: '8.0')] ?string $namespace, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $localName = '', #[PhpStormStubsElementAvailable(from: '8.0')] string $localName ): ?DOMNode {} /** * @param DOMNode $arg [optional] */ public function setNamedItemNS(DOMNode $arg) {} /** * @param $namespace [optional] * @param $localName [optional] */ public function removeNamedItemNS($namespace, $localName) {} /** * @return int<0,max> * @since 7.2 */ #[TentativeType] public function count(): int {} /** * @return Iterator * @since 8.0 */ public function getIterator(): Iterator {} } /** * The DOMCharacterData class represents nodes with character data. * No nodes directly correspond to this class, but other nodes do inherit from it. * @link https://php.net/manual/en/class.domcharacterdata.php */ class DOMCharacterData extends DOMNode implements DOMChildNode { /** * @var string * The contents of the node. * @link https://php.net/manual/en/class.domcharacterdata.php#domcharacterdata.props.data */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $data; /** * @var int * The length of the contents. * @link https://php.net/manual/en/class.domcharacterdata.php#domcharacterdata.props.length */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $length; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $nextElementSibling; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $previousElementSibling; /** * Extracts a range of data from the node * @link https://php.net/manual/en/domcharacterdata.substringdata.php * @param int $offset

* Start offset of substring to extract. *

* @param int $count

* The number of characters to extract. *

* @return string The specified substring. If the sum of offset * and count exceeds the length, then all 16-bit units * to the end of the data are returned. */ public function substringData( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $count ) {} /** * Append the string to the end of the character data of the node * @link https://php.net/manual/en/domcharacterdata.appenddata.php * @param string $data

* The string to append. *

*/ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function appendData(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data) {} /** * Insert a string at the specified 16-bit unit offset * @link https://php.net/manual/en/domcharacterdata.insertdata.php * @param int $offset

* The character offset at which to insert. *

* @param string $data

* The string to insert. *

* @return bool */ #[TentativeType] public function insertData( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data ): bool {} /** * Remove a range of characters from the node * @link https://php.net/manual/en/domcharacterdata.deletedata.php * @param int $offset

* The offset from which to start removing. *

* @param int $count

* The number of characters to delete. If the sum of * offset and count exceeds * the length, then all characters to the end of the data are deleted. *

* @return void */ #[TentativeType] public function deleteData( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $count ): bool {} /** * Replace a substring within the DOMCharacterData node * @link https://php.net/manual/en/domcharacterdata.replacedata.php * @param int $offset

* The offset from which to start replacing. *

* @param int $count

* The number of characters to replace. If the sum of * offset and count exceeds * the length, then all characters to the end of the data are replaced. *

* @param string $data

* The string with which the range must be replaced. *

* @return bool */ #[TentativeType] public function replaceData( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $count, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data ): bool {} /** * {@inheritDoc} */ public function remove(): void {} /** * {@inheritDoc} */ public function before(...$nodes): void {} /** * {@inheritDoc} */ public function after(...$nodes): void {} /** * {@inheritDoc} */ public function replaceWith(...$nodes): void {} } /** * The DOMAttr interface represents an attribute in an DOMElement object. * @link https://php.net/manual/en/class.domattr.php */ class DOMAttr extends DOMNode { /** * @var string * (PHP5)
* The name of the attribute * @link https://php.net/manual/en/class.domattr.php#domattr.props.name */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $name; /** * @var DOMElement * (PHP5)
* The element which contains the attribute * @link https://php.net/manual/en/class.domattr.php#domattr.props.ownerelement */ #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $ownerElement; /** * @var bool * (PHP5)
* Not implemented yet, always is NULL * @link https://php.net/manual/en/class.domattr.php#domattr.props.schematypeinfo */ #[LanguageLevelTypeAware(['8.1' => 'mixed'], default: '')] public $schemaTypeInfo; /** * @var bool * (PHP5)
* Not implemented yet, always is NULL * @link https://php.net/manual/en/class.domattr.php#domattr.props.specified */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $specified; /** * @var string * (PHP5)
* The value of the attribute * @link https://php.net/manual/en/class.domattr.php#domattr.props.value */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $value; /** * Checks if attribute is a defined ID * @link https://php.net/manual/en/domattr.isid.php * @return bool true on success or false on failure. */ #[TentativeType] public function isId(): bool {} /** * Creates a new {@see DOMAttr} object * @link https://php.net/manual/en/domattr.construct.php * @param string $name

The tag name of the attribute.

* @param string $value [optional]

The value of the attribute.

* @throws DOMException If invalid $name */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $value = '' ) {} } /** * The DOMElement class * @link https://php.net/manual/en/class.domelement.php */ class DOMElement extends DOMNode implements DOMParentNode, DOMChildNode { /** * @var DOMNode|null * The parent of this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.parentnode */ public $parentNode; /** * @var DOMNode|null * The first child of this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.firstchild */ public $firstChild; /** * @var DOMNode|null * The last child of this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.lastchild */ public $lastChild; /** * @var DOMNode|null * The node immediately preceding this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.previoussibling */ public $previousSibling; /** * @var DOMNode|null * The node immediately following this node. If there is no such node, this returns NULL. * @link https://php.net/manual/en/class.domnode.php#domnode.props.nextsibling */ public $nextSibling; /** * @var DOMNamedNodeMap * A DOMNamedNodeMap containing the attributes of this node (if it is a DOMElement) or NULL otherwise. * @link https://php.net/manual/en/class.domnode.php#domnode.props.attributes */ #[LanguageLevelTypeAware(['8.1' => 'DOMNamedNodeMap'], default: '')] public $attributes; /** * @var bool * Not implemented yet, always return NULL * @link https://php.net/manual/en/class.domelement.php#domelement.props.schematypeinfo */ #[LanguageLevelTypeAware(['8.1' => 'mixed'], default: '')] public $schemaTypeInfo; /** * @var string * The element name * @link https://php.net/manual/en/class.domelement.php#domelement.props.tagname */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $tagName; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $firstElementChild; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $lastElementChild; #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $childElementCount; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $previousElementSibling; #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $nextElementSibling; public string $id; public string $className; /** * Returns value of attribute * @link https://php.net/manual/en/domelement.getattribute.php * @param string $qualifiedName

* The name of the attribute. *

* @return string The value of the attribute, or an empty string if no attribute with the * given name is found. */ #[TentativeType] public function getAttribute(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName): string {} /** * Adds new attribute * @link https://php.net/manual/en/domelement.setattribute.php * @param string $qualifiedName

* The name of the attribute. *

* @param string $value

* The value of the attribute. *

* @return DOMAttr|false The new DOMAttr or false if an error occurred. */ public function setAttribute( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $value ) {} /** * Removes attribute * @link https://php.net/manual/en/domelement.removeattribute.php * @param string $qualifiedName

* The name of the attribute. *

* @return bool true on success or false on failure. */ #[TentativeType] public function removeAttribute(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName): bool {} /** * Returns attribute node * @link https://php.net/manual/en/domelement.getattributenode.php * @param string $qualifiedName

* The name of the attribute. *

* @return DOMAttr The attribute node. */ public function getAttributeNode(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName) {} /** * Adds new attribute node to element * @link https://php.net/manual/en/domelement.setattributenode.php * @param DOMAttr $attr

* The attribute node. *

* @return DOMAttr|null Old node if the attribute has been replaced or null. */ public function setAttributeNode(DOMAttr $attr) {} /** * Removes attribute * @link https://php.net/manual/en/domelement.removeattributenode.php * @param DOMAttr $attr

* The attribute node. *

* @return bool true on success or false on failure. */ public function removeAttributeNode(DOMAttr $attr) {} /** * Gets elements by tagname * @link https://php.net/manual/en/domelement.getelementsbytagname.php * @param string $qualifiedName

* The tag name. Use * to return all elements within * the element tree. *

* @return DOMNodeList This function returns a new instance of the class * DOMNodeList of all matched elements. */ #[TentativeType] public function getElementsByTagName(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName): DOMNodeList {} /** * Returns value of attribute * @link https://php.net/manual/en/domelement.getattributens.php * @param string $namespace

* The namespace URI. *

* @param string $localName

* The local name. *

* @return string The value of the attribute, or an empty string if no attribute with the * given localName and namespaceURI * is found. */ #[TentativeType] public function getAttributeNS( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName ): string {} /** * Adds new attribute * @link https://php.net/manual/en/domelement.setattributens.php * @param string $namespace

* The namespace URI. *

* @param string $qualifiedName

* The qualified name of the attribute, as prefix:tagname. *

* @param string $value

* The value of the attribute. *

* @return void */ #[TentativeType] public function setAttributeNS( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $value ): void {} /** * Removes attribute * @link https://php.net/manual/en/domelement.removeattributens.php * @param string $namespace

* The namespace URI. *

* @param string $localName

* The local name. *

* @return bool true on success or false on failure. */ #[TentativeType] public function removeAttributeNS( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName ): void {} /** * Returns attribute node * @link https://php.net/manual/en/domelement.getattributenodens.php * @param string $namespace

* The namespace URI. *

* @param string $localName

* The local name. *

* @return DOMAttr The attribute node. */ public function getAttributeNodeNS( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName ) {} /** * Adds new attribute node to element * @link https://php.net/manual/en/domelement.setattributenodens.php * @param DOMAttr $attr * @return DOMAttr the old node if the attribute has been replaced. */ public function setAttributeNodeNS(DOMAttr $attr) {} /** * Get elements by namespaceURI and localName * @link https://php.net/manual/en/domelement.getelementsbytagnamens.php * @param string $namespace

* The namespace URI. *

* @param string $localName

* The local name. Use * to return all elements within * the element tree. *

* @return DOMNodeList This function returns a new instance of the class * DOMNodeList of all matched elements in the order in * which they are encountered in a preorder traversal of this element tree. */ #[TentativeType] public function getElementsByTagNameNS( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName ): DOMNodeList {} /** * Checks to see if attribute exists * @link https://php.net/manual/en/domelement.hasattribute.php * @param string $qualifiedName

* The attribute name. *

* @return bool true on success or false on failure. */ #[TentativeType] public function hasAttribute(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName): bool {} /** * Checks to see if attribute exists * @link https://php.net/manual/en/domelement.hasattributens.php * @param string $namespace

* The namespace URI. *

* @param string $localName

* The local name. *

* @return bool true on success or false on failure. */ #[TentativeType] public function hasAttributeNS( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName ): bool {} /** * Declares the attribute specified by name to be of type ID * @link https://php.net/manual/en/domelement.setidattribute.php * @param string $qualifiedName

* The name of the attribute. *

* @param bool $isId

* Set it to true if you want name to be of type * ID, false otherwise. *

* @return void */ #[TentativeType] public function setIdAttribute( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $isId ): void {} /** * Declares the attribute specified by local name and namespace URI to be of type ID * @link https://php.net/manual/en/domelement.setidattributens.php * @param string $namespace

* The namespace URI of the attribute. *

* @param string $qualifiedName

* The local name of the attribute, as prefix:tagname. *

* @param bool $isId

* Set it to true if you want name to be of type * ID, false otherwise. *

* @return void */ #[TentativeType] public function setIdAttributeNS( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $isId ): void {} /** * Declares the attribute specified by node to be of type ID * @link https://php.net/manual/en/domelement.setidattributenode.php * @param DOMAttr $attr

* The attribute node. *

* @param bool $isId

* Set it to true if you want name to be of type * ID, false otherwise. *

* @return void */ #[TentativeType] public function setIdAttributeNode(DOMAttr $attr, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $isId): void {} /** * {@inheritDoc} */ public function remove(): void {} /** * {@inheritDoc} */ public function before(...$nodes): void {} /** * {@inheritDoc} */ public function after(...$nodes): void {} /** * {@inheritDoc} */ public function replaceWith(...$nodes): void {} /** * {@inheritDoc} */ public function append(...$nodes): void {} /** * {@inheritDoc} */ public function prepend(...$nodes): void {} /** * @since 8.3 * {@inheritDoc} */ public function replaceChildren(...$nodes): void {} /** * Creates a new DOMElement object * @link https://php.net/manual/en/domelement.construct.php * @param string $qualifiedName The tag name of the element. When also passing in namespaceURI, the element name may take a prefix to be associated with the URI. * @param string|null $value [optional] The value of the element. * @param string $namespace [optional] A namespace URI to create the element within a specific namespace. * @throws DOMException If invalid $qualifiedName */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $value = null, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace = '' ) {} /** * @since 8.3 */ public function getAttributeNames(): array {} /** * @since 8.3 */ public function toggleAttribute(string $qualifiedName, ?bool $force = null): bool {} /** * @since 8.3 */ public function insertAdjacentElement(string $where, DOMElement $element): ?DOMElement {} /** * @since 8.3 */ public function insertAdjacentText(string $where, string $data): void {} } /** * The DOMText class inherits from DOMCharacterData and represents the textual content of * a DOMElement or DOMAttr. * @link https://php.net/manual/en/class.domtext.php */ class DOMText extends DOMCharacterData { /** * Holds all the text of logically-adjacent (not separated by Element, Comment or Processing Instruction) Text nodes. * @link https://php.net/manual/en/class.domtext.php#domtext.props.wholeText */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $wholeText; /** * Breaks this node into two nodes at the specified offset * @link https://php.net/manual/en/domtext.splittext.php * @param int $offset

* The offset at which to split, starting from 0. *

* @return DOMText The new node of the same type, which contains all the content at and after the * offset. */ public function splitText(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset) {} /** * Indicates whether this text node contains whitespace * @link https://php.net/manual/en/domtext.iswhitespaceinelementcontent.php * @return bool true on success or false on failure. */ #[TentativeType] public function isWhitespaceInElementContent(): bool {} #[TentativeType] public function isElementContentWhitespace(): bool {} /** * @param $content */ public function replaceWholeText($content) {} /** * Creates a new DOMText object * @link https://php.net/manual/en/domtext.construct.php * @param string $data [optional] The value of the text node. If not supplied an empty text node is created. */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data = '') {} } /** * The DOMComment class represents comment nodes, * characters delimited by lt;!-- and -->. * @link https://php.net/manual/en/class.domcomment.php */ class DOMComment extends DOMCharacterData { /** * Creates a new DOMComment object * @link https://php.net/manual/en/domcomment.construct.php * @param string $data [optional] The value of the comment */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data = '') {} } /** * @removed 8.0 */ class DOMTypeinfo {} /** * @removed 8.0 */ class DOMUserDataHandler { public function handle() {} } /** * @removed 8.0 */ class DOMDomError {} /** * @removed 8.0 */ class DOMErrorHandler { /** * @param DOMDomError $error */ public function handleError(DOMDomError $error) {} } /** * @removed 8.0 */ class DOMLocator {} /** * @removed 8.0 */ class DOMConfiguration { /** * @param $name * @param $value */ public function setParameter($name, $value) {} /** * @param $name [optional] */ public function getParameter($name) {} /** * @param $name [optional] * @param $value [optional] */ public function canSetParameter($name, $value) {} } /** * The DOMCdataSection inherits from DOMText for textural representation of CData constructs. * @link https://secure.php.net/manual/en/class.domcdatasection.php */ class DOMCdataSection extends DOMText { /** * The value of the CDATA node. If not supplied, an empty CDATA node is created. * @param string $data The value of the CDATA node. If not supplied, an empty CDATA node is created. * @link https://secure.php.net/manual/en/domcdatasection.construct.php */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data) {} } /** * The DOMDocumentType class * @link https://php.net/manual/en/class.domdocumenttype.php */ class DOMDocumentType extends DOMNode { /** * @var string * The public identifier of the external subset. * @link https://php.net/manual/en/class.domdocumenttype.php#domdocumenttype.props.publicid */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $publicId; /** * @var string * The system identifier of the external subset. This may be an absolute URI or not. * @link https://php.net/manual/en/class.domdocumenttype.php#domdocumenttype.props.systemid */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $systemId; /** * @var string * The name of DTD; i.e., the name immediately following the DOCTYPE keyword. * @link https://php.net/manual/en/class.domdocumenttype.php#domdocumenttype.props.name */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $name; /** * @var DOMNamedNodeMap * A DOMNamedNodeMap containing the general entities, both external and internal, declared in the DTD. * @link https://php.net/manual/en/class.domdocumenttype.php#domdocumenttype.props.entities */ #[LanguageLevelTypeAware(['8.1' => 'DOMNamedNodeMap'], default: '')] public $entities; /** * @var DOMNamedNodeMap * A DOMNamedNodeMap containing the notations declared in the DTD. * @link https://php.net/manual/en/class.domdocumenttype.php#domdocumenttype.props.notations */ #[LanguageLevelTypeAware(['8.1' => 'DOMNamedNodeMap'], default: '')] public $notations; /** * @var string|null * The internal subset as a string, or null if there is none. This is does not contain the delimiting square brackets. * @link https://php.net/manual/en/class.domdocumenttype.php#domdocumenttype.props.internalsubset */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $internalSubset; } /** * The DOMNotation class * @link https://php.net/manual/en/class.domnotation.php */ class DOMNotation extends DOMNode { /** * @var string * * @link https://php.net/manual/en/class.domnotation.php#domnotation.props.publicid */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $publicId; /** * @var string * * @link https://php.net/manual/en/class.domnotation.php#domnotation.props.systemid */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $systemId; } /** * The DOMEntity class represents a known entity, either parsed or unparsed, in an XML document. * @link https://php.net/manual/en/class.domentity.php */ class DOMEntity extends DOMNode { /** * @var string|null * The public identifier associated with the entity if specified, and NULL otherwise. * @link https://php.net/manual/en/class.domentity.php#domentity.props.publicid */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $publicId; /** * @var string|null * The system identifier associated with the entity if specified, and NULL otherwise. This may be an * absolute URI or not. * @link https://php.net/manual/en/class.domentity.php#domentity.props.systemid */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $systemId; /** * @var string|null * For unparsed entities, the name of the notation for the entity. For parsed entities, this is NULL. * @link https://php.net/manual/en/class.domentity.php#domentity.props.notationname */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $notationName; /** * @var string|null * An attribute specifying the encoding used for this entity at the time of parsing, when it is an external * parsed entity. This is NULL if it an entity from the internal subset or if it is not known. * @link https://php.net/manual/en/class.domentity.php#domentity.props.actualencoding */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $actualEncoding; /** * @var string|null * An attribute specifying, as part of the text declaration, the encoding of this entity, when it is an external * parsed entity. This is NULL otherwise. * @link https://php.net/manual/en/class.domentity.php#domentity.props.encoding */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $encoding; /** * @var string|null * An attribute specifying, as part of the text declaration, the version number of this entity, when it is an * external parsed entity. This is NULL otherwise. * @link https://php.net/manual/en/class.domentity.php#domentity.props.version */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $version; } /** * Extends DOMNode. * @link https://php.net/manual/en/class.domentityreference.php */ class DOMEntityReference extends DOMNode { /** * Creates a new DOMEntityReference object * @link https://php.net/manual/en/domentityreference.construct.php * @param string $name The name of the entity reference. */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name) {} } /** * The DOMProcessingInstruction class * @link https://php.net/manual/en/class.domprocessinginstruction.php */ class DOMProcessingInstruction extends DOMNode { /** * @link https://php.net/manual/en/class.domprocessinginstruction.php#domprocessinginstruction.props.target */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $target; /** * @link https://php.net/manual/en/class.domprocessinginstruction.php#domprocessinginstruction.props.data */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $data; /** * Creates a new DOMProcessingInstruction object * @link https://php.net/manual/en/domprocessinginstruction.construct.php * @param string $name The tag name of the processing instruction. * @param string $value [optional] The value of the processing instruction. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $value = '' ) {} } class DOMStringExtend { /** * @param $offset32 */ public function findOffset16($offset32) {} /** * @param $offset16 */ public function findOffset32($offset16) {} } /** * The DOMXPath class (supports XPath 1.0) * @link https://php.net/manual/en/class.domxpath.php */ class DOMXPath { /** * @var DOMDocument * * @link https://php.net/manual/en/class.domxpath.php#domxpath.props.document */ #[LanguageLevelTypeAware(['8.1' => 'DOMDocument'], default: '')] public $document; #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $registerNodeNamespaces; /** * Creates a new DOMXPath object * @link https://php.net/manual/en/domxpath.construct.php * @param DOMDocument $document The DOMDocument associated with the DOMXPath. * @param bool $registerNodeNS [optional] allow global flag to configure query() or evaluate() calls. Since 8.0. */ public function __construct(DOMDocument $document, #[PhpStormStubsElementAvailable(from: '8.0')] bool $registerNodeNS = true) {} /** * Registers the namespace with the DOMXPath object * @link https://php.net/manual/en/domxpath.registernamespace.php * @param string $prefix

* The prefix. *

* @param string $namespace

* The URI of the namespace. *

* @return bool true on success or false on failure. */ #[TentativeType] public function registerNamespace( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $prefix, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace ): bool {} /** * Evaluates the given XPath expression * @link https://php.net/manual/en/domxpath.query.php * @param string $expression

* The XPath expression to execute. *

* @param DOMNode $contextNode [optional]

* The optional contextnode can be specified for * doing relative XPath queries. By default, the queries are relative to * the root element. *

* @param bool $registerNodeNS [optional]

The optional registerNodeNS can be specified to * disable automatic registration of the context node.

* @return DOMNodeList|false a DOMNodeList containing all nodes matching * the given XPath expression. Any expression which does not return nodes * will return an empty DOMNodeList. The return is false if the expression * is malformed or the contextnode is invalid. */ #[TentativeType] public function query( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] #[Language('XPath')] $expression, #[LanguageLevelTypeAware(['8.0' => 'DOMNode|null'], default: '')] $contextNode = null, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $registerNodeNS = true ): mixed {} /** * Evaluates the given XPath expression and returns a typed result if possible. * @link https://php.net/manual/en/domxpath.evaluate.php * @param string $expression

* The XPath expression to execute. *

* @param DOMNode $contextNode [optional]

* The optional contextnode can be specified for * doing relative XPath queries. By default, the queries are relative to * the root element. *

* @param bool $registerNodeNS [optional] *

* The optional registerNodeNS can be specified to disable automatic registration of the context node. *

* @return mixed a typed result if possible or a DOMNodeList * containing all nodes matching the given XPath expression. */ #[TentativeType] public function evaluate( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] #[Language('XPath')] $expression, #[LanguageLevelTypeAware(['8.0' => 'DOMNode|null'], default: '')] $contextNode = null, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $registerNodeNS = true ): mixed {} /** * Register PHP functions as XPath functions * @link https://php.net/manual/en/domxpath.registerphpfunctions.php * @param string|string[] $restrict [optional]

* Use this parameter to only allow certain functions to be called from XPath. *

*

* This parameter can be either a string (a function name) or * an array of function names. *

* @return void */ public function registerPhpFunctions($restrict = null) {} /** * @since 8.4 */ public function registerPhpFunctionNS(string $namespaceURI, string $name, callable $callable): void {} /** * @since 8.4 */ public static function quote(string $str): string {} } /** * @property-read DOMElement|null $firstElementChild * @property-read DOMElement|null $lastElementChild * @property-read int $childElementCount * * @since 8.0 */ interface DOMParentNode { /** * Appends one or many nodes to the list of children behind the last * child node. * * @param DOMNode|string|null ...$nodes * @return void * @since 8.0 */ public function append(...$nodes): void; /** * Prepends one or many nodes to the list of children before the first * child node. * * @param DOMNode|string|null ...$nodes * @return void * @since 8.0 */ public function prepend(...$nodes): void; /** * @since 8.3 */ public function replaceChildren(...$nodes): void; } /** * @property-read DOMElement|null $previousElementSibling * @property-read DOMElement|null $nextElementSibling * * @since 8.0 */ interface DOMChildNode { /** * Acts as a simpler version of {@see DOMNode::removeChild()}. * * @return void * @since 8.0 */ public function remove(): void; /** * Add passed node(s) before the current node * * @param DOMNode|string|null ...$nodes * @return void * @since 8.0 */ public function before(...$nodes): void; /** * Add passed node(s) after the current node * * @param DOMNode|string|null ...$nodes * @return void * @since 8.0 */ public function after(...$nodes): void; /** * Replace current node with new node(s), a combination * of {@see DOMChildNode::remove()} + {@see DOMChildNode::append()}. * * @param DOMNode|string|null ...$nodes * @return void * @since 8.0 */ public function replaceWith(...$nodes): void; } * A mailbox name consists of a server and a mailbox path on this server. * The special name INBOX stands for the current users * personal mailbox. Mailbox names that contain international characters * besides those in the printable ASCII space have to be encoded width * imap_utf7_encode. *

*

* The server part, which is enclosed in '{' and '}', consists of the servers * name or ip address, an optional port (prefixed by ':'), and an optional * protocol specification (prefixed by '/'). *

*

* The server part is mandatory in all mailbox * parameters. *

*

* All names which start with { are remote names, and are * in the form "{" remote_system_name [":" port] [flags] "}" * [mailbox_name] where: * remote_system_name - Internet domain name or * bracketed IP address of server.

* @param string $user

* The user name *

* @param string $password

* The password associated with the username *

* @param int $flags [optional]

* The options are a bit mask with one or more of * the following: * OP_READONLY - Open mailbox read-only

* @param int $retries [optional]

* Number of maximum connect attempts *

* @param null|array $options

* Connection parameters, the following (string) keys maybe used * to set one or more connection parameters: * DISABLE_AUTHENTICATOR - Disable authentication properties

* @return resource|false an IMAP stream on success or FALSE on error. */ #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection|false'], default: 'resource|false')] function imap_open(string $mailbox, string $user, string $password, int $flags = 0, int $retries = 0, array $options = []) {} /** * Reopen IMAP stream to new mailbox * @link https://php.net/manual/en/function.imap-reopen.php * @param resource $imap * @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @param int $flags [optional]

* The options are a bit mask with one or more of * the following: * OP_READONLY - Open mailbox read-only

* @param int $retries [optional]

* Number of maximum connect attempts *

* @return bool TRUE if the stream is reopened, FALSE otherwise. */ function imap_reopen( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox, int $flags = 0, int $retries = 0 ): bool {} /** * Close an IMAP stream * @link https://php.net/manual/en/function.imap-close.php * @param resource $imap * @param int $flags [optional]

* If set to CL_EXPUNGE, the function will silently * expunge the mailbox before closing, removing all messages marked for * deletion. You can achieve the same thing by using * imap_expunge *

*/ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function imap_close(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $flags = 0) {} /** * Gets the number of messages in the current mailbox * @link https://php.net/manual/en/function.imap-num-msg.php * @param resource $imap * @return int|false Return the number of messages in the current mailbox, as an integer. */ function imap_num_msg(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap): int|false {} /** * Gets the number of recent messages in current mailbox * @link https://php.net/manual/en/function.imap-num-recent.php * @param resource $imap * @return int the number of recent messages in the current mailbox, as an * integer. */ function imap_num_recent(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap): int {} /** * Returns headers for all messages in a mailbox * @link https://php.net/manual/en/function.imap-headers.php * @param resource $imap * @return array|false an array of string formatted with header info. One * element per mail message. */ function imap_headers(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap): array|false {} /** * Read the header of the message * @link https://php.net/manual/en/function.imap-headerinfo.php * @param resource|IMAP\Connection $imap An IMAP stream returned by imap_open(). * @param int $message_num The message number * @param int $from_length [optional] Number of characters for the fetchfrom property. Must be greater than or equal to zero. * @param int $subject_length [optional] Number of characters for the fetchsubject property Must be greater than or equal to zero. * @param $default_host [optional] * @return stdClass|false Returns the information in an object with following properties: *
*
toaddress
full to: line, up to 1024 characters
*
to
an array of objects from the To: line, with the following properties: personal, adl, mailbox, and host
*
fromaddress
full from: line, up to 1024 characters
*
from
an array of objects from the From: line, with the following properties: personal, adl, mailbox, and host
*
ccaddress
full cc: line, up to 1024 characters
*
cc
an array of objects from the Cc: line, with the following properties: personal, adl, mailbox, and host
*
bccaddress
full bcc: line, up to 1024 characters
*
bcc
an array of objects from the Bcc: line, with the following properties: personal, adl, mailbox, and host
*
reply_toaddress
full Reply-To: line, up to 1024 characters
*
reply_to
an array of objects from the Reply-To: line, with the following properties: personal, adl, mailbox, and host
*
senderaddress
full sender: line, up to 1024 characters
*
sender
an array of objects from the Sender: line, with the following properties: personal, adl, mailbox, and host
*
return_pathaddress
full Return-Path: line, up to 1024 characters
*
return_path
an array of objects from the Return-Path: line, with the following properties: personal, adl, mailbox, and host
*
remail -
*
date
The message date as found in its headers
*
Date
Same as date
*
subject
The message subject
*
Subject
Same a subject
*
in_reply_to -
*
message_id -
*
newsgroups -
*
followup_to -
*
references -
*
Recent
R if recent and seen, N if recent and not seen, ' ' if not recent.
*
Unseen
U if not seen AND not recent, ' ' if seen OR not seen and recent
*
Flagged
F if flagged, ' ' if not flagged
*
Answered
A if answered, ' ' if unanswered
*
Deleted
D if deleted, ' ' if not deleted
*
Draft
X if draft, ' ' if not draft
*
Msgno
The message number
*
MailDate -
*
Size
The message size
*
udate
mail message date in Unix time
*
fetchfrom
from line formatted to fit fromlength characters
*
fetchsubject
subject line formatted to fit subjectlength characters
*
*/ function imap_headerinfo( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_num, int $from_length = 0, int $subject_length = 0, #[PhpStormStubsElementAvailable(to: '7.4')] $default_host = null ): stdClass|false {} /** * Parse mail headers from a string * @link https://php.net/manual/en/function.imap-rfc822-parse-headers.php * @param string $headers

* The parsed headers data *

* @param string $default_hostname [optional]

* The default host name *

* @return object|stdClass an object similar to the one returned by * imap_header, except for the flags and other * properties that come from the IMAP server. */ function imap_rfc822_parse_headers(string $headers, string $default_hostname = "UNKNOWN"): stdClass {} /** * Returns a properly formatted email address given the mailbox, host, and personal info * @link https://php.net/manual/en/function.imap-rfc822-write-address.php * @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @param string $hostname

* The email host part *

* @param string $personal

* The name of the account owner *

* @return string|false a string properly formatted email address as defined in RFC2822. */ function imap_rfc822_write_address(string $mailbox, string $hostname, string $personal): string|false {} /** * Parses an address string * @link https://php.net/manual/en/function.imap-rfc822-parse-adrlist.php * @param string $string

* A string containing addresses *

* @param string $default_hostname

* The default host name *

* @return array an array of objects. The objects properties are: *

* mailbox - the mailbox name (username) * host - the host name * personal - the personal name * adl - at domain source route *

*/ function imap_rfc822_parse_adrlist(string $string, string $default_hostname): array {} /** * Read the message body * @link https://php.net/manual/en/function.imap-body.php * @param resource $imap * @param int $message_num

* The message number *

* @param int $flags [optional]

* The optional options are a bit mask * with one or more of the following: * FT_UID - The msg_number is a UID

* @return string|false the body of the specified message, as a string. */ function imap_body( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_num, int $flags = 0 ): string|false {} /** * Read the structure of a specified body section of a specific message * @link https://php.net/manual/en/function.imap-bodystruct.php * @param resource $imap * @param int $message_num

* The message number *

* @param string $section

* The body section to read *

* @return object the information in an object, for a detailed description * of the object structure and properties see * imap_fetchstructure. */ #[LanguageLevelTypeAware(['8.1' => 'stdClass|false'], default: 'object')] function imap_bodystruct(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_num, string $section) {} /** * Fetch a particular section of the body of the message * @link https://php.net/manual/en/function.imap-fetchbody.php * @param resource $imap * @param int $message_num

* The message number *

* @param string $section

* The part number. It is a string of integers delimited by period which * index into a body part list as per the IMAP4 specification *

* @param int $flags [optional]

* A bitmask with one or more of the following: * FT_UID - The msg_number is a UID

* @return string|false a particular section of the body of the specified messages as a * text string. */ function imap_fetchbody( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_num, string $section, int $flags = 0 ): string|false {} /** * Fetch MIME headers for a particular section of the message * @link https://php.net/manual/en/function.imap-fetchmime.php * @param resource $imap * @param int $message_num

* The message number *

* @param string $section

* The part number. It is a string of integers delimited by period which * index into a body part list as per the IMAP4 specification *

* @param int $flags [optional]

* A bitmask with one or more of the following: * FT_UID - The msg_number is a UID

* @return string|false the MIME headers of a particular section of the body of the specified messages as a * text string. * @since 5.3.6 */ function imap_fetchmime( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_num, string $section, int $flags = 0 ): string|false {} /** * Save a specific body section to a file * @link https://php.net/manual/en/function.imap-savebody.php * @param resource $imap * @param mixed $file

* The path to the saved file as a string, or a valid file descriptor * returned by fopen. *

* @param int $message_num

* The message number *

* @param string $section [optional]

* The part number. It is a string of integers delimited by period which * index into a body part list as per the IMAP4 specification *

* @param int $flags [optional]

* A bitmask with one or more of the following: * FT_UID - The msg_number is a UID

* @return bool TRUE on success or FALSE on failure. * @since 5.1.3 */ function imap_savebody( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, $file, int $message_num, string $section = "", int $flags = 0 ): bool {} /** * Returns header for a message * @link https://php.net/manual/en/function.imap-fetchheader.php * @param resource $imap * @param int $message_num

* The message number *

* @param int $flags [optional]

* The possible options are: * FT_UID - The msgno * argument is a UID

* @return string|false the header of the specified message as a text string. */ function imap_fetchheader( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_num, int $flags = 0 ): string|false {} /** * Read the structure of a particular message * @link https://php.net/manual/en/function.imap-fetchstructure.php * @param resource $imap * @param int $message_num

* The message number *

* @param int $flags [optional]

* This optional parameter only has a single option, * FT_UID, which tells the function to treat the * msg_number argument as a * UID. *

* @return object|stdClass|false an object includes the envelope, internal date, size, flags and * body structure along with a similar object for each mime attachment. The * structure of the returned objects is as follows: *

*

*

* Returned Objects for imap_fetchstructure * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
typePrimary body type
encodingBody transfer encoding
ifsubtypeTRUE if there is a subtype string
subtypeMIME subtype
ifdescriptionTRUE if there is a description string
descriptionContent description string
ifidTRUE if there is an identification string
idIdentification string
linesNumber of lines
bytesNumber of bytes
ifdispositionTRUE if there is a disposition string
dispositionDisposition string
ifdparametersTRUE if the dparameters array exists
dparametersAn array of objects where each object has an * "attribute" and a "value" * property corresponding to the parameters on the * Content-disposition MIME * header.
ifparametersTRUE if the parameters array exists
parametersAn array of objects where each object has an * "attribute" and a "value" * property.
partsAn array of objects identical in structure to the top-level * object, each of which corresponds to a MIME body * part.
*

*

*

* Primary body type (may vary with used library) * * * * * * * * *
0text
1multipart
2message
3application
4audio
5image
6video
7other
*

*

*

* Transfer encodings (may vary with used library) * * * * * * *
07BIT
18BIT
2BINARY
3BASE64
4QUOTED-PRINTABLE
5OTHER
*/ function imap_fetchstructure(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_num, int $flags = 0): stdClass|false {} /** * Clears IMAP cache * @link https://php.net/manual/en/function.imap-gc.php * @param resource $imap * @param int $flags

* Specifies the cache to purge. It may one or a combination * of the following constants: * IMAP_GC_ELT (message cache elements), * IMAP_GC_ENV (enveloppe and bodies), * IMAP_GC_TEXTS (texts). *

*/ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function imap_gc( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] int $flags = 0, #[PhpStormStubsElementAvailable(from: '8.0')] int $flags ) {} /** * Delete all messages marked for deletion * @link https://php.net/manual/en/function.imap-expunge.php * @param resource $imap */ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function imap_expunge(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap) {} /** * Mark a message for deletion from current mailbox * @link https://php.net/manual/en/function.imap-delete.php * @param resource $imap * @param string $message_nums

* The message number *

* @param int $flags [optional]

* You can set the FT_UID which tells the function * to treat the msg_number argument as an * UID. *

*/ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function imap_delete(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $message_nums, int $flags = 0) {} /** * Unmark the message which is marked deleted * @link https://php.net/manual/en/function.imap-undelete.php * @param resource $imap * @param string $message_nums

* The message number *

* @param int $flags [optional] */ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function imap_undelete(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $message_nums, int $flags = 0) {} /** * Check current mailbox * @link https://php.net/manual/en/function.imap-check.php * @param resource $imap * @return object|stdClass|false the information in an object with following properties: * Date - current system time formatted according to RFC2822 * Driver - protocol used to access this mailbox: * POP3, IMAP, NNTP * Mailbox - the mailbox name * Nmsgs - number of messages in the mailbox * Recent - number of recent messages in the mailbox *

*

* Returns FALSE on failure. */ function imap_check(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap): stdClass|false {} /** * Returns the list of mailboxes that matches the given text * @link https://php.net/manual/en/function.imap-listscan.php * @param resource $imap * @param string $reference

* ref should normally be just the server * specification as described in imap_open *

* @param string $pattern Specifies where in the mailbox hierarchy * to start searching.

There are two special characters you can * pass as part of the pattern: * '*' and '%'. * '*' means to return all mailboxes. If you pass * pattern as '*', you will * get a list of the entire mailbox hierarchy. * '%' * means to return the current level only. * '%' as the pattern * parameter will return only the top level * mailboxes; '~/mail/%' on UW_IMAPD will return every mailbox in the ~/mail directory, but none in subfolders of that directory.

* @param string $content

* The searched string *

* @return array|false an array containing the names of the mailboxes that have * content in the text of the mailbox. */ function imap_listscan(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $reference, string $pattern, string $content): array|false {} /** * Copy specified messages to a mailbox * @link https://php.net/manual/en/function.imap-mail-copy.php * @param resource $imap * @param string $message_nums

* msglist is a range not just message * numbers (as described in RFC2060). *

* @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @param int $flags [optional]

* options is a bitmask of one or more of * CP_UID - the sequence numbers contain UIDS

* @return bool TRUE on success or FALSE on failure. */ function imap_mail_copy(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $message_nums, string $mailbox, int $flags = 0): bool {} /** * Move specified messages to a mailbox * @link https://php.net/manual/en/function.imap-mail-move.php * @param resource $imap * @param string $message_nums

* msglist is a range not just message numbers * (as described in RFC2060). *

* @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @param int $flags [optional]

* options is a bitmask and may contain the single option: * CP_UID - the sequence numbers contain UIDS

* @return bool TRUE on success or FALSE on failure. */ function imap_mail_move(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $message_nums, string $mailbox, int $flags = 0): bool {} /** * Create a MIME message based on given envelope and body sections * @link https://php.net/manual/en/function.imap-mail-compose.php * @param array $envelope

* An associative array of headers fields. Valid keys are: "remail", * "return_path", "date", "from", "reply_to", "in_reply_to", "subject", * "to", "cc", "bcc", "message_id" and "custom_headers" (which contains * associative array of other headers). *

* @param array $bodies

* An indexed array of bodies *

*

* A body is an associative array which can consist of the following keys: * "type", "encoding", "charset", "type.parameters", "subtype", "id", * "description", "disposition.type", "disposition", "contents.data", * "lines", "bytes" and "md5". *

* @return string|false the MIME message. */ function imap_mail_compose(array $envelope, array $bodies): string|false {} /** * Create a new mailbox * @link https://php.net/manual/en/function.imap-createmailbox.php * @param resource $imap * @param string $mailbox

* The mailbox name, see imap_open for more * information. Names containing international characters should be * encoded by imap_utf7_encode *

* @return bool TRUE on success or FALSE on failure. */ function imap_createmailbox(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox): bool {} /** * Rename an old mailbox to new mailbox * @link https://php.net/manual/en/function.imap-renamemailbox.php * @param resource $imap * @param string $from

* The old mailbox name, see imap_open for more * information *

* @param string $to

* The new mailbox name, see imap_open for more * information *

* @return bool TRUE on success or FALSE on failure. */ function imap_renamemailbox(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $from, string $to): bool {} /** * Delete a mailbox * @link https://php.net/manual/en/function.imap-deletemailbox.php * @param resource $imap * @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @return bool TRUE on success or FALSE on failure. */ function imap_deletemailbox(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox): bool {} /** * Subscribe to a mailbox * @link https://php.net/manual/en/function.imap-subscribe.php * @param resource $imap * @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @return bool TRUE on success or FALSE on failure. */ function imap_subscribe(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox): bool {} /** * Unsubscribe from a mailbox * @link https://php.net/manual/en/function.imap-unsubscribe.php * @param resource $imap * @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @return bool TRUE on success or FALSE on failure. */ function imap_unsubscribe(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox): bool {} /** * Append a string message to a specified mailbox * @link https://php.net/manual/en/function.imap-append.php * @param resource $imap * @param string $folder

* The mailbox name, see imap_open for more * information *

* @param string $message

* The message to be append, as a string *

*

* When talking to the Cyrus IMAP server, you must use "\r\n" as * your end-of-line terminator instead of "\n" or the operation will * fail *

* @param string $options [optional]

* If provided, the options will also be written * to the mailbox *

* @param string $internal_date [optional]

* If this parameter is set, it will set the INTERNALDATE on the appended message. The parameter should be a date string that conforms to the rfc2060 specifications for a date_time value. *

* @return bool TRUE on success or FALSE on failure. */ function imap_append(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $folder, string $message, ?string $options = null, ?string $internal_date = null): bool {} /** * Check if the IMAP stream is still active * @link https://php.net/manual/en/function.imap-ping.php * @param resource $imap * @return bool TRUE if the stream is still alive, FALSE otherwise. */ function imap_ping(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap): bool {} /** * Decode BASE64 encoded text * @link https://php.net/manual/en/function.imap-base64.php * @param string $string

* The encoded text *

* @return string|false the decoded message as a string. */ function imap_base64(string $string): string|false {} /** * Convert a quoted-printable string to an 8 bit string * @link https://php.net/manual/en/function.imap-qprint.php * @param string $string

* A quoted-printable string *

* @return string|false an 8 bits string. */ function imap_qprint(string $string): string|false {} /** * Convert an 8bit string to a quoted-printable string * @link https://php.net/manual/en/function.imap-8bit.php * @param string $string

* The 8bit string to convert *

* @return string|false a quoted-printable string. */ function imap_8bit(string $string): string|false {} /** * Convert an 8bit string to a base64 string * @link https://php.net/manual/en/function.imap-binary.php * @param string $string

* The 8bit string *

* @return string|false a base64 encoded string. */ function imap_binary(string $string): string|false {} /** * Converts MIME-encoded text to UTF-8 * @link https://php.net/manual/en/function.imap-utf8.php * @param string $mime_encoded_text

* A MIME encoded string. MIME encoding method and the UTF-8 * specification are described in RFC2047 and RFC2044 respectively. *

* @return string an UTF-8 encoded string. */ function imap_utf8(string $mime_encoded_text): string {} /** * Returns status information on a mailbox * @link https://php.net/manual/en/function.imap-status.php * @param resource $imap * @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @param int $flags

* Valid flags are: * SA_MESSAGES - set $status->messages to the * number of messages in the mailbox * @return object This function returns an object containing status information. * The object has the following properties: messages, * recent, unseen, * uidnext, and uidvalidity. *

*

* flags is also set, which contains a bitmask which can * be checked against any of the above constants.

*/ #[LanguageLevelTypeAware(['8.1' => 'stdClass|false'], default: 'object')] function imap_status(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox, int $flags) {} /** * @param $stream_id * @param $options */ function imap_status_current($stream_id, $options) {} /** * Get information about the current mailbox * @link https://php.net/manual/en/function.imap-mailboxmsginfo.php * @param resource $imap * @return object|stdClass|false the information in an object with following properties: * * Mailbox properties * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Datedate of last change (current datetime)
Driverdriver
Mailboxname of the mailbox
Nmsgsnumber of messages
Recentnumber of recent messages
Unreadnumber of unread messages
Deletednumber of deleted messages
Sizemailbox size
*

*

* Returns FALSE on failure. */ function imap_mailboxmsginfo(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap): stdClass {} /** * Sets flags on messages * @link https://php.net/manual/en/function.imap-setflag-full.php * @param resource $imap * @param string $sequence

* A sequence of message numbers. You can enumerate desired messages * with the X,Y syntax, or retrieve all messages * within an interval with the X:Y syntax *

* @param string $flag

* The flags which you can set are \Seen, * \Answered, \Flagged, * \Deleted, and \Draft as * defined by RFC2060. *

* @param int $options [optional]

* A bit mask that may contain the single option: * ST_UID - The sequence argument contains UIDs * instead of sequence numbers

*/ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function imap_setflag_full(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $sequence, string $flag, int $options = NIL) {} /** * Clears flags on messages * @link https://php.net/manual/en/function.imap-clearflag-full.php * @param resource $imap * @param string $sequence

* A sequence of message numbers. You can enumerate desired messages * with the X,Y syntax, or retrieve all messages * within an interval with the X:Y syntax *

* @param string $flag

* The flags which you can unset are "\\Seen", "\\Answered", "\\Flagged", * "\\Deleted", and "\\Draft" (as defined by RFC2060) *

* @param int $options [optional]

* options are a bit mask and may contain * the single option: * ST_UID - The sequence argument contains UIDs * instead of sequence numbers

*/ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function imap_clearflag_full(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $sequence, string $flag, int $options = 0) {} /** * Gets and sort messages * @link https://php.net/manual/en/function.imap-sort.php * @param resource $imap * @param int $criteria

* Criteria can be one (and only one) of the following: * SORTDATE - message Date

* @param bool $reverse

* Set this to 1 for reverse sorting *

* @param int $flags [optional]

* The options are a bitmask of one or more of the * following: * SE_UID - Return UIDs instead of sequence numbers

* @param string|null $search_criteria [optional] * @param string|null $charset [optional] * @return array|false an array of message numbers sorted by the given * parameters. */ function imap_sort( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $criteria, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: 'int')] $reverse, int $flags = 0, ?string $search_criteria = null, ?string $charset = null ): array|false {} /** * This function returns the UID for the given message sequence number * @link https://php.net/manual/en/function.imap-uid.php * @param resource $imap * @param int $message_num

* The message number. *

* @return int|false The UID of the given message. */ function imap_uid(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_num): int|false {} /** * Gets the message sequence number for the given UID * @link https://php.net/manual/en/function.imap-msgno.php * @param resource $imap * @param int $message_uid

* The message UID *

* @return int the message sequence number for the given * uid. */ function imap_msgno(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_uid): int {} /** * Read the list of mailboxes * @link https://php.net/manual/en/function.imap-list.php * @param resource $imap * @param string $reference

* ref should normally be just the server * specification as described in imap_open. *

* @param string $pattern Specifies where in the mailbox hierarchy * to start searching.

There are two special characters you can * pass as part of the pattern: * '*' and '%'. * '*' means to return all mailboxes. If you pass * pattern as '*', you will * get a list of the entire mailbox hierarchy. * '%' * means to return the current level only. * '%' as the pattern * parameter will return only the top level * mailboxes; '~/mail/%' on UW_IMAPD will return every mailbox in the ~/mail directory, but none in subfolders of that directory.

* @return array|false an array containing the names of the mailboxes. */ function imap_list(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $reference, string $pattern): array|false {} /** * List all the subscribed mailboxes * @link https://php.net/manual/en/function.imap-lsub.php * @param resource $imap * @param string $reference

* ref should normally be just the server * specification as described in imap_open *

* @param string $pattern Specifies where in the mailbox hierarchy * to start searching.

There are two special characters you can * pass as part of the pattern: * '*' and '%'. * '*' means to return all mailboxes. If you pass * pattern as '*', you will * get a list of the entire mailbox hierarchy. * '%' * means to return the current level only. * '%' as the pattern * parameter will return only the top level * mailboxes; '~/mail/%' on UW_IMAPD will return every mailbox in the ~/mail directory, but none in subfolders of that directory.

* @return array|false an array of all the subscribed mailboxes. */ function imap_lsub(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $reference, string $pattern): array|false {} /** * Read an overview of the information in the headers of the given message * @link https://php.net/manual/en/function.imap-fetch-overview.php * @param resource $imap * @param string $sequence

* A message sequence description. You can enumerate desired messages * with the X,Y syntax, or retrieve all messages * within an interval with the X:Y syntax *

* @param int $flags [optional]

* sequence will contain a sequence of message * indices or UIDs, if this parameter is set to * FT_UID. *

* @return array|false an array of objects describing one message header each. * The object will only define a property if it exists. The possible * properties are: * subject - the messages subject * from - who sent it * to - recipient * date - when was it sent * message_id - Message-ID * references - is a reference to this message id * in_reply_to - is a reply to this message id * size - size in bytes * uid - UID the message has in the mailbox * msgno - message sequence number in the mailbox * recent - this message is flagged as recent * flagged - this message is flagged * answered - this message is flagged as answered * deleted - this message is flagged for deletion * seen - this message is flagged as already read * draft - this message is flagged as being a draft */ function imap_fetch_overview(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $sequence, int $flags = 0): array|false {} /** * Returns all IMAP alert messages that have occurred * @link https://php.net/manual/en/function.imap-alerts.php * @return array|false an array of all of the IMAP alert messages generated or FALSE if * no alert messages are available. */ function imap_alerts(): array|false {} /** * Returns all of the IMAP errors that have occurred * @link https://php.net/manual/en/function.imap-errors.php * @return array|false This function returns an array of all of the IMAP error messages * generated since the last imap_errors call, * or the beginning of the page. Returns FALSE if no error messages are * available. */ function imap_errors(): array|false {} /** * Gets the last IMAP error that occurred during this page request * @link https://php.net/manual/en/function.imap-last-error.php * @return string|false the full text of the last IMAP error message that occurred on the * current page. Returns FALSE if no error messages are available. */ function imap_last_error(): string|false {} /** * This function returns an array of messages matching the given search criteria * @link https://php.net/manual/en/function.imap-search.php * @param resource $imap * @param string $criteria

* A string, delimited by spaces, in which the following keywords are * allowed. Any multi-word arguments (e.g. * FROM "joey smith") must be quoted. Results will match * all criteria entries. * ALL - return all messages matching the rest of the criteria

* @param int $flags [optional]

* Valid values for options are * SE_UID, which causes the returned array to * contain UIDs instead of messages sequence numbers. *

* @param string $charset * @return array|false an array of message numbers or UIDs. *

* Return FALSE if it does not understand the search * criteria or no messages have been found. *

*/ function imap_search( #[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $criteria, int $flags = SE_FREE, string $charset = "" ): array|false {} /** * Decodes a modified UTF-7 encoded string * @link https://php.net/manual/en/function.imap-utf7-decode.php * @param string $string

* A modified UTF-7 encoding string, as defined in RFC 2060, section 5.1.3 (original UTF-7 * was defined in RFC1642). *

* @return string|false a string that is encoded in ISO-8859-1 and consists of the same * sequence of characters in text, or FALSE * if text contains invalid modified UTF-7 sequence * or text contains a character that is not part of * ISO-8859-1 character set. */ function imap_utf7_decode(string $string): string|false {} /** * Converts ISO-8859-1 string to modified UTF-7 text * @link https://php.net/manual/en/function.imap-utf7-encode.php * @param string $string

* An ISO-8859-1 string. *

* @return string data encoded with the modified UTF-7 * encoding as defined in RFC 2060, * section 5.1.3 (original UTF-7 was defined in RFC1642). */ function imap_utf7_encode(string $string): string {} /** * Decode MIME header elements * @link https://php.net/manual/en/function.imap-mime-header-decode.php * @param string $string

* The MIME text *

* @return array|false The decoded elements are returned in an array of objects, where each * object has two properties, charset and * text. *

*

* If the element hasn't been encoded, and in other words is in * plain US-ASCII, the charset property of that element is * set to default. */ function imap_mime_header_decode(string $string): array|false {} /** * Returns a tree of threaded message * @link https://php.net/manual/en/function.imap-thread.php * @param resource $imap * @param int $flags [optional] * @return array|false imap_thread returns an associative array containing * a tree of messages threaded by REFERENCES, or FALSE * on error. *

*

* Every message in the current mailbox will be represented by three entries * in the resulting array: *

* $thread["XX.num"] - current message number *

*

* $thread["XX.next"] *

*

* $thread["XX.branch"] *

*/ function imap_thread(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $flags = SE_FREE): array|false {} /** * Set or fetch imap timeout * @link https://php.net/manual/en/function.imap-timeout.php * @param int $timeout_type

* One of the following: * IMAP_OPENTIMEOUT, * IMAP_READTIMEOUT, * IMAP_WRITETIMEOUT, or * IMAP_CLOSETIMEOUT. *

* @param int $timeout [optional]

* The timeout, in seconds. *

* @return int|bool If the timeout parameter is set, this function * returns TRUE on success and FALSE on failure. *

*

* If timeout is not provided or evaluates to -1, * the current timeout value of timeout_type is * returned as an integer. */ function imap_timeout(int $timeout_type, int $timeout = -1): int|bool {} /** * Retrieve the quota level settings, and usage statics per mailbox * @link https://php.net/manual/en/function.imap-get-quota.php * @param resource $imap * @param string $quota_root

* quota_root should normally be in the form of * user.name where name is the mailbox you wish to * retrieve information about. *

* @return array|false an array with integer values limit and usage for the given * mailbox. The value of limit represents the total amount of space * allowed for this mailbox. The usage value represents the mailboxes * current level of capacity. Will return FALSE in the case of failure. *

*

* As of PHP 4.3, the function more properly reflects the * functionality as dictated by the RFC2087. * The array return value has changed to support an unlimited number of returned * resources (i.e. messages, or sub-folders) with each named resource receiving * an individual array key. Each key value then contains an another array with * the usage and limit values within it. *

*

* For backwards compatibility reasons, the original access methods are * still available for use, although it is suggested to update. */ #[ArrayShape(["usage" => "int", "limit" => "int"])] function imap_get_quota(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $quota_root): array|false {} /** * Retrieve the quota settings per user * @link https://php.net/manual/en/function.imap-get-quotaroot.php * @param resource $imap * @param string $mailbox

* quota_root should normally be in the form of * which mailbox (i.e. INBOX). *

* @return array|false an array of integer values pertaining to the specified user * mailbox. All values contain a key based upon the resource name, and a * corresponding array with the usage and limit values within. *

*

* This function will return FALSE in the case of call failure, and an * array of information about the connection upon an un-parsable response * from the server. */ function imap_get_quotaroot(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox): array|false {} /** * Sets a quota for a given mailbox * @link https://php.net/manual/en/function.imap-set-quota.php * @param resource $imap * @param string $quota_root

* The mailbox to have a quota set. This should follow the IMAP standard * format for a mailbox: user.name. *

* @param int $mailbox_size

* The maximum size (in KB) for the quota_root *

* @return bool TRUE on success or FALSE on failure. */ function imap_set_quota(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $quota_root, int $mailbox_size): bool {} /** * Sets the ACL for a given mailbox * @link https://php.net/manual/en/function.imap-setacl.php * @param resource $imap * @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @param string $user_id

* The user to give the rights to. *

* @param string $rights

* The rights to give to the user. Passing an empty string will delete * acl. *

* @return bool TRUE on success or FALSE on failure. */ function imap_setacl(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox, string $user_id, string $rights): bool {} /** * Gets the ACL for a given mailbox * @link https://php.net/manual/en/function.imap-getacl.php * @param resource $imap * @param string $mailbox

* The mailbox name, see imap_open for more * information *

* @return array|false an associative array of "folder" => "acl" pairs. */ function imap_getacl(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox): array|false {} /** * @param $stream_id * @param $mailbox */ function imap_myrights($stream_id, $mailbox) {} /** * @param $stream_id * @param $mailbox * @param $entry * @param $attr * @param $value */ function imap_setannotation($stream_id, $mailbox, $entry, $attr, $value) {} /** * @param $stream_id * @param $mailbox * @param $entry * @param $attr */ function imap_getannotation($stream_id, $mailbox, $entry, $attr) {} /** * Send an email message * @link https://php.net/manual/en/function.imap-mail.php * @param string $to

* The receiver *

* @param string $subject

* The mail subject *

* @param string $message

* The mail body, see imap_mail_compose *

* @param string $additional_headers [optional]

* As string with additional headers to be set on the mail *

* @param string $cc [optional] * @param string $bcc [optional]

* The receivers specified in bcc will get the * mail, but are excluded from the headers. *

* @param string $return_path [optional]

* Use this parameter to specify return path upon mail delivery failure. * This is useful when using PHP as a mail client for multiple users. *

* @return bool TRUE on success or FALSE on failure. */ function imap_mail(string $to, string $subject, string $message, ?string $additional_headers = null, ?string $cc = null, ?string $bcc = null, ?string $return_path = null): bool {} /** * Alias of imap_headerinfo * @link https://php.net/manual/en/function.imap-header.php * @param resource $stream_id An IMAP stream returned by imap_open(). * @param int $msg_no The message number * @param int $from_length [optional] Number of characters for the fetchfrom property. Must be greater than or equal to zero. * @param int $subject_length [optional] Number of characters for the fetchsubject property Must be greater than or equal to zero. * @param $default_host [optional] * @return object Returns the information in an object with following properties: *
*
toaddress
full to: line, up to 1024 characters
*
to
an array of objects from the To: line, with the following properties: personal, adl, mailbox, and host
*
fromaddress
full from: line, up to 1024 characters
*
from
an array of objects from the From: line, with the following properties: personal, adl, mailbox, and host
*
ccaddress
full cc: line, up to 1024 characters
*
cc
an array of objects from the Cc: line, with the following properties: personal, adl, mailbox, and host
*
bccaddress
full bcc: line, up to 1024 characters
*
bcc
an array of objects from the Bcc: line, with the following properties: personal, adl, mailbox, and host
*
reply_toaddress
full Reply-To: line, up to 1024 characters
*
reply_to
an array of objects from the Reply-To: line, with the following properties: personal, adl, mailbox, and host
*
senderaddress
full sender: line, up to 1024 characters
*
sender
an array of objects from the Sender: line, with the following properties: personal, adl, mailbox, and host
*
return_pathaddress
full Return-Path: line, up to 1024 characters
*
return_path
an array of objects from the Return-Path: line, with the following properties: personal, adl, mailbox, and host
*
remail -
*
date
The message date as found in its headers
*
Date
Same as date
*
subject
The message subject
*
Subject
Same a subject
*
in_reply_to -
*
message_id -
*
newsgroups -
*
followup_to -
*
references -
*
Recent
R if recent and seen, N if recent and not seen, ' ' if not recent.
*
Unseen
U if not seen AND not recent, ' ' if seen OR not seen and recent
*
Flagged
F if flagged, ' ' if not flagged
*
Answered
A if answered, ' ' if unanswered
*
Deleted
D if deleted, ' ' if not deleted
*
Draft
X if draft, ' ' if not draft
*
Msgno
The message number
*
MailDate -
*
Size
The message size
*
udate
mail message date in Unix time
*
fetchfrom
from line formatted to fit fromlength characters
*
fetchsubject
subject line formatted to fit subjectlength characters
*
*/ #[PhpStormStubsElementAvailable(to: '7.4')] function imap_header($stream_id, $msg_no, $from_length = 0, $subject_length = 0, $default_host = null) {} /** * Alias of imap_list * @link https://php.net/manual/en/function.imap-listmailbox.php * @param resource $imap * @param string $reference * @param string $pattern * @return array|false */ function imap_listmailbox(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $reference, string $pattern): array|false {} /** * Read the list of mailboxes, returning detailed information on each one * @link https://php.net/manual/en/function.imap-getmailboxes.php * @param resource $imap * @param string $reference

* ref should normally be just the server * specification as described in imap_open *

* @param string $pattern Specifies where in the mailbox hierarchy * to start searching.

There are two special characters you can * pass as part of the pattern: * '*' and '%'. * '*' means to return all mailboxes. If you pass * pattern as '*', you will * get a list of the entire mailbox hierarchy. * '%' * means to return the current level only. * '%' as the pattern * parameter will return only the top level * mailboxes; '~/mail/%' on UW_IMAPD will return every mailbox in the ~/mail directory, but none in subfolders of that directory.

* @return array|false an array of objects containing mailbox information. Each * object has the attributes name, specifying * the full name of the mailbox; delimiter, * which is the hierarchy delimiter for the part of the hierarchy * this mailbox is in; and * attributes. Attributes * is a bitmask that can be tested against: *

* LATT_NOINFERIORS - This mailbox contains, and may not contain any * "children" (there are no mailboxes below this one). Calling * imap_createmailbox will not work on this mailbox. *

*

* LATT_NOSELECT - This is only a container, * not a mailbox - you cannot open it. *

*

* LATT_MARKED - This mailbox is marked. This means that it may * contain new messages since the last time it was checked. Not provided by all IMAP * servers. *

*

* LATT_UNMARKED - This mailbox is not marked, does not contain new * messages. If either MARKED or UNMARKED is * provided, you can assume the IMAP server supports this feature for this mailbox. *

*/ function imap_getmailboxes(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $reference, string $pattern): array|false {} /** * Alias of imap_listscan * @link https://php.net/manual/en/function.imap-scanmailbox.php * @param $imap * @param $reference * @param $pattern * @param $content */ function imap_scanmailbox(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $reference, string $pattern, string $content): array|false {} /** * Alias of imap_lsub * @link https://php.net/manual/en/function.imap-listsubscribed.php * @param resource $imap * @param string $reference * @param string $pattern * @return array|false */ function imap_listsubscribed(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $reference, string $pattern): array|false {} /** * List all the subscribed mailboxes * @link https://php.net/manual/en/function.imap-getsubscribed.php * @param resource $imap * @param string $reference

* ref should normally be just the server * specification as described in imap_open *

* @param string $pattern Specifies where in the mailbox hierarchy * to start searching.

There are two special characters you can * pass as part of the pattern: * '*' and '%'. * '*' means to return all mailboxes. If you pass * pattern as '*', you will * get a list of the entire mailbox hierarchy. * '%' * means to return the current level only. * '%' as the pattern * parameter will return only the top level * mailboxes; '~/mail/%' on UW_IMAPD will return every mailbox in the ~/mail directory, but none in subfolders of that directory.

* @return array|false an array of objects containing mailbox information. Each * object has the attributes name, specifying * the full name of the mailbox; delimiter, * which is the hierarchy delimiter for the part of the hierarchy * this mailbox is in; and * attributes. Attributes * is a bitmask that can be tested against: * LATT_NOINFERIORS - This mailbox has no * "children" (there are no mailboxes below this one). * LATT_NOSELECT - This is only a container, * not a mailbox - you cannot open it. * LATT_MARKED - This mailbox is marked. * Only used by UW-IMAPD. * LATT_UNMARKED - This mailbox is not marked. * Only used by UW-IMAPD. */ function imap_getsubscribed(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $reference, string $pattern): array|false {} /** * (PHP 4, PHP 5)
* Alias of imap_body() * @param resource $imap An IMAP stream returned by imap_open() * @param int $message_num message number * @param int $flags [optional] A bitmask with one or more of the following:
    *
  • FT_UID - The msg_number is a UID *
  • FT_PEEK - Do not set the \Seen flag if not already set *
  • FT_INTERNAL - The return string is in internal format, will not canonicalize to CRLF.

* @return string|false body of the specified message */ function imap_fetchtext(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, int $message_num, int $flags = 0): string|false {} /** * Alias of imap_listscan * @link https://php.net/manual/en/function.imap-scan.php * @param $imap * @param $reference * @param $pattern * @param $content */ function imap_scan(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $reference, string $pattern, string $content): array|false {} /** * Alias of imap_createmailbox * @link https://php.net/manual/en/function.imap-create.php * @param $imap * @param $mailbox */ function imap_create(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $mailbox): bool {} /** * Alias of imap_renamemailbox * @link https://php.net/manual/en/function.imap-rename.php * @param $imap * @param $from * @param $to */ function imap_rename(#[LanguageLevelTypeAware(['8.1' => 'IMAP\Connection'], default: 'resource')] $imap, string $from, string $to): bool {} /** * Decode a modified UTF-7 string to UTF-8 * * @link https://www.php.net/manual/en/function.imap-mutf7-to-utf8.php * * @param string $string * @return string|false */ function imap_mutf7_to_utf8(string $string): string|false {} /** * Encode a UTF-8 string to modified UTF-7 * * @link https://www.php.net/manual/en/function.imap-utf8-to-mutf7.php * * @param string $string * @return string|false */ function imap_utf8_to_mutf7(string $string): string|false {} /** * @since 8.2 */ function imap_is_open(IMAP\Connection $imap): bool {} /** * @deprecated 8.1 */ define('NIL', 0); define('IMAP_OPENTIMEOUT', 1); define('IMAP_READTIMEOUT', 2); define('IMAP_WRITETIMEOUT', 3); define('IMAP_CLOSETIMEOUT', 4); define('OP_DEBUG', 1); /** * Open mailbox read-only * @link https://php.net/manual/en/imap.constants.php */ define('OP_READONLY', 2); /** * Don't use or update a .newsrc for news * (NNTP only) * @link https://php.net/manual/en/imap.constants.php */ define('OP_ANONYMOUS', 4); define('OP_SHORTCACHE', 8); define('OP_SILENT', 16); define('OP_PROTOTYPE', 32); /** * For IMAP and NNTP * names, open a connection but don't open a mailbox. * @link https://php.net/manual/en/imap.constants.php */ define('OP_HALFOPEN', 64); define('OP_EXPUNGE', 128); define('OP_SECURE', 256); /** * silently expunge the mailbox before closing when * calling imap_close * @link https://php.net/manual/en/imap.constants.php */ define('CL_EXPUNGE', 32768); /** * The parameter is a UID * @link https://php.net/manual/en/imap.constants.php */ define('FT_UID', 1); /** * Do not set the \Seen flag if not already set * @link https://php.net/manual/en/imap.constants.php */ define('FT_PEEK', 2); define('FT_NOT', 4); /** * The return string is in internal format, will not canonicalize to CRLF. * @link https://php.net/manual/en/imap.constants.php */ define('FT_INTERNAL', 8); define('FT_PREFETCHTEXT', 32); /** * The sequence argument contains UIDs instead of sequence numbers * @link https://php.net/manual/en/imap.constants.php */ define('ST_UID', 1); define('ST_SILENT', 2); define('ST_SET', 4); /** * the sequence numbers contain UIDS * @link https://php.net/manual/en/imap.constants.php */ define('CP_UID', 1); /** * Delete the messages from the current mailbox after copying * with imap_mail_copy * @link https://php.net/manual/en/imap.constants.php */ define('CP_MOVE', 2); /** * Return UIDs instead of sequence numbers * @link https://php.net/manual/en/imap.constants.php */ define('SE_UID', 1); define('SE_FREE', 2); /** * Don't prefetch searched messages * @link https://php.net/manual/en/imap.constants.php */ define('SE_NOPREFETCH', 4); define('SO_FREE', 8); define('SO_NOSERVER', 8); define('SA_MESSAGES', 1); define('SA_RECENT', 2); define('SA_UNSEEN', 4); define('SA_UIDNEXT', 8); define('SA_UIDVALIDITY', 16); define('SA_ALL', 31); /** * This mailbox has no "children" (there are no * mailboxes below this one). * @link https://php.net/manual/en/imap.constants.php */ define('LATT_NOINFERIORS', 1); /** * This is only a container, not a mailbox - you * cannot open it. * @link https://php.net/manual/en/imap.constants.php */ define('LATT_NOSELECT', 2); /** * This mailbox is marked. Only used by UW-IMAPD. * @link https://php.net/manual/en/imap.constants.php */ define('LATT_MARKED', 4); /** * This mailbox is not marked. Only used by * UW-IMAPD. * @link https://php.net/manual/en/imap.constants.php */ define('LATT_UNMARKED', 8); define('LATT_REFERRAL', 16); define('LATT_HASCHILDREN', 32); define('LATT_HASNOCHILDREN', 64); /** * Sort criteria for imap_sort: * message Date * @link https://php.net/manual/en/imap.constants.php */ define('SORTDATE', 0); /** * Sort criteria for imap_sort: * arrival date * @link https://php.net/manual/en/imap.constants.php */ define('SORTARRIVAL', 1); /** * Sort criteria for imap_sort: * mailbox in first From address * @link https://php.net/manual/en/imap.constants.php */ define('SORTFROM', 2); /** * Sort criteria for imap_sort: * message subject * @link https://php.net/manual/en/imap.constants.php */ define('SORTSUBJECT', 3); /** * Sort criteria for imap_sort: * mailbox in first To address * @link https://php.net/manual/en/imap.constants.php */ define('SORTTO', 4); /** * Sort criteria for imap_sort: * mailbox in first cc address * @link https://php.net/manual/en/imap.constants.php */ define('SORTCC', 5); /** * Sort criteria for imap_sort: * size of message in octets * @link https://php.net/manual/en/imap.constants.php */ define('SORTSIZE', 6); define('TYPETEXT', 0); define('TYPEMULTIPART', 1); define('TYPEMESSAGE', 2); define('TYPEAPPLICATION', 3); define('TYPEAUDIO', 4); define('TYPEIMAGE', 5); define('TYPEVIDEO', 6); define('TYPEMODEL', 7); define('TYPEOTHER', 8); define('ENC7BIT', 0); define('ENC8BIT', 1); define('ENCBINARY', 2); define('ENCBASE64', 3); define('ENCQUOTEDPRINTABLE', 4); define('ENCOTHER', 5); /** * Garbage collector, clear message cache elements. * @link https://php.net/manual/en/imap.constants.php */ define('IMAP_GC_ELT', 1); /** * Garbage collector, clear envelopes and bodies. * @link https://php.net/manual/en/imap.constants.php */ define('IMAP_GC_ENV', 2); /** * Garbage collector, clear texts. * @link https://php.net/manual/en/imap.constants.php */ define('IMAP_GC_TEXTS', 4); * The location of the image file. This cannot be an URL. * Since 7.2.0 this can either be a path to the file (stream wrappers are also supported as usual) * or a stream resource. *

* @param string|null $required_sections [optional]

* Is a comma separated list of sections that need to be present in file * to produce a result array. If none of the requested * sections could be found the return value is FALSE. * * FILE * FileName, FileSize, FileDateTime, SectionsFound * * * COMPUTED * * html, Width, Height, IsColor, and more if available. Height and * Width are computed the same way getimagesize * does so their values must not be part of any header returned. * Also, html is a height/width text string to be used inside normal * HTML. * * * * ANY_TAG * Any information that has a Tag e.g. IFD0, EXIF, ... * * * IFD0 * * All tagged data of IFD0. In normal imagefiles this contains * image size and so forth. * * * * THUMBNAIL * * A file is supposed to contain a thumbnail if it has a second IFD. * All tagged information about the embedded thumbnail is stored in * this section. * * * * COMMENT * Comment headers of JPEG images. * * * EXIF * * The EXIF section is a sub section of IFD0. It contains * more detailed information about an image. Most of these entries * are digital camera related. * * *

* @param bool $as_arrays [optional]

* Specifies whether or not each section becomes an array. The * sections COMPUTED, * THUMBNAIL, and COMMENT * always become arrays as they may contain values whose names conflict * with other sections. *

* @param bool $read_thumbnail [optional]

* When set to TRUE the thumbnail itself is read. Otherwise, only the * tagged data is read. *

* @return array|false It returns an associative array where the array indexes are * the header names and the array values are the values associated with * those headers. If no data can be returned, * exif_read_data will return FALSE. */ function exif_read_data($file, ?string $required_sections, bool $as_arrays = false, bool $read_thumbnail = false): array|false {} /** * Alias of exif_read_data * @link https://php.net/manual/en/function.read-exif-data.php * @param $filename * @param $sections [optional] * @param $arrays [optional] * @param $thumbnail [optional] * @removed 8.0 */ #[Deprecated(replacement: "exif_read_data(%parametersList%)", since: "7.2")] function read_exif_data($filename, $sections = null, $arrays = false, $thumbnail = false) {} /** * Get the header name for an index * @link https://php.net/manual/en/function.exif-tagname.php * @param int $index

* The Tag ID for which a Tag Name will be looked up. *

* @return string|false the header name, or FALSE if index is * not a defined EXIF tag id. */ function exif_tagname(int $index): string|false {} /** * Retrieve the embedded thumbnail of a TIFF or JPEG image * @link https://php.net/manual/en/function.exif-thumbnail.php * @param string|resource $file

* The location of the image file. This cannot be an URL. * Since 7.2.0 this can either be a path to the file (stream wrappers are also supported as usual) * or a stream resource. *

* @param int &$width [optional]

* The return width of the returned thumbnail. *

* @param int &$height [optional]

* The returned height of the returned thumbnail. *

* @param int &$image_type [optional]

* The returned image type of the returned thumbnail. This is either * TIFF or JPEG. *

* @return string|false the embedded thumbnail, or FALSE if the image contains no * thumbnail. */ function exif_thumbnail($file, &$width, &$height, &$image_type): string|false {} /** * Determine the type of an image * @link https://php.net/manual/en/function.exif-imagetype.php * @param string $filename The image being checked. * @return int|false When a correct signature is found, the appropriate constant value will be * returned otherwise the return value is FALSE. The return value is the * same value that getimagesize returns in index 2 but * exif_imagetype is much faster. *

*

* exif_imagetype will emit an E_NOTICE * and return FALSE if it is unable to read enough bytes from the file to * determine the image type. */ function exif_imagetype(string $filename): int|false {} define('EXIF_USE_MBSTRING', 1); // End of exif v.1.4 $Id$ amqp.host The host to connect too. Note: Max 1024 characters. * 'port' => amqp.port Port on the host. * 'vhost' => amqp.vhost The virtual host on the host. Note: Max 128 characters. * 'login' => amqp.login The login name to use. Note: Max 128 characters. * 'password' => amqp.password Password. Note: Max 128 characters. * 'read_timeout' => Timeout in for income activity. Note: 0 or greater seconds. May be fractional. * 'write_timeout' => Timeout in for outcome activity. Note: 0 or greater seconds. May be fractional. * 'connect_timeout' => Connection timeout. Note: 0 or greater seconds. May be fractional. * 'rpc_timeout' => RPC timeout. Note: 0 or greater seconds. May be fractional. * * Connection tuning options (see http://www.rabbitmq.com/amqp-0-9-1-reference.html#connection.tune for details): * 'channel_max' => Specifies highest channel number that the server permits. 0 means standard extension limit * (see PHP_AMQP_MAX_CHANNELS constant) * 'frame_max' => The largest frame size that the server proposes for the connection, including frame header * and end-byte. 0 means standard extension limit (depends on librabbimq default frame size limit) * 'heartbeat' => The delay, in seconds, of the connection heartbeat that the server wants. * 0 means the server does not want a heartbeat. Note, librabbitmq has limited heartbeat support, * which means heartbeats checked only during blocking calls. * * TLS support (see https://www.rabbitmq.com/ssl.html for details): * 'cacert' => Path to the CA cert file in PEM format.. * 'cert' => Path to the client certificate in PEM foramt. * 'key' => Path to the client key in PEM format. * 'verify' => Enable or disable peer verification. If peer verification is enabled then the common name in the * server certificate must match the server name. Peer verification is enabled by default. * * 'connection_name' => A user determined name for the connection * ) * * @param array $credentials Optional array of credential information for * connecting to the AMQP broker. */ public function __construct(array $credentials = []) {} /** * Check whether the connection to the AMQP broker is still valid. * * Cannot reliably detect dropped connections or unusual socket errors, as it does not actively * engage the socket. * * @return bool TRUE if connected, FALSE otherwise. */ public function isConnected() {} /** * Whether connection persistent. * * When no connection is established, it will always return FALSE. The same disclaimer as for * {@see AMQPConnection::isConnected()} applies. * * @return bool TRUE if persistently connected, FALSE otherwise. */ public function isPersistent() {} /** * Establish a transient connection with the AMQP broker. * * This method will initiate a connection with the AMQP broker. * * @throws AMQPConnectionException * @return void */ public function connect() {} /** * Closes the transient connection with the AMQP broker. * * This method will close an open connection with the AMQP broker. * * @throws AMQPConnectionException When attempting to disconnect a persistent connection * * @return void */ public function disconnect() {} /** * Close any open transient connections and initiate a new one with the AMQP broker. * * @return void */ public function reconnect() {} /** * Establish a persistent connection with the AMQP broker. * * This method will initiate a connection with the AMQP broker * or reuse an existing one if present. * * @throws AMQPConnectionException * @return void */ public function pconnect() {} /** * Closes a persistent connection with the AMQP broker. * * This method will close an open persistent connection with the AMQP * broker. * * @throws AMQPConnectionException When attempting to disconnect a transient connection * * @return void */ public function pdisconnect() {} /** * Close any open persistent connections and initiate a new one with the AMQP broker. * * @throws AMQPConnectionException * * @return void */ public function preconnect() {} /** * Get the configured host. * * @return string The configured hostname of the broker */ public function getHost() {} /** * Get the configured login. * * @return string The configured login as a string. */ public function getLogin() {} /** * Get the configured password. * * @return string The configured password as a string. */ public function getPassword() {} /** * Get the configured port. * * @return int The configured port as an integer. */ public function getPort() {} /** * Get the configured vhost. * * @return string The configured virtual host as a string. */ public function getVhost() {} /** * Set the hostname used to connect to the AMQP broker. * * @param string $host The hostname of the AMQP broker. * * @throws AMQPConnectionException If host is longer then 1024 characters. * * @return void */ public function setHost($host) {} /** * Set the login string used to connect to the AMQP broker. * * @param string $login The login string used to authenticate * with the AMQP broker. * * @throws AMQPConnectionException If login is longer then 32 characters. * * @return void */ public function setLogin($login) {} /** * Set the password string used to connect to the AMQP broker. * * @param string $password The password string used to authenticate * with the AMQP broker. * * @throws AMQPConnectionException If password is longer then 32characters. * * @return void */ public function setPassword($password) {} /** * Set the port used to connect to the AMQP broker. * * @param int $port The port used to connect to the AMQP broker. * * @throws AMQPConnectionException If port is longer not between * 1 and 65535. * * @return void */ public function setPort($port) {} /** * Sets the virtual host to which to connect on the AMQP broker. * * @param string $vhost The virtual host to use on the AMQP * broker. * * @throws AMQPConnectionException If host is longer then 32 characters. * * @return void */ public function setVhost($vhost) {} /** * Sets the interval of time to wait for income activity from AMQP broker * * @deprecated use AMQPConnection::setReadTimeout($timeout) instead * * @param float $timeout * * @throws AMQPConnectionException If timeout is less than 0. * * @return void */ #[Deprecated(replacement: "%class%->setReadTimout(%parameter0%)")] public function setTimeout($timeout) {} /** * Get the configured interval of time to wait for income activity * from AMQP broker * * @deprecated use AMQPConnection::getReadTimeout() instead * * @return float */ #[Deprecated(replacement: '%class%->getReadTimout(%parameter0%)')] public function getTimeout() {} /** * Sets the interval of time to wait for income activity from AMQP broker * * @param float $timeout * * @throws AMQPConnectionException If timeout is less than 0. * * @return void */ public function setReadTimeout($timeout) {} /** * Get the configured interval of time to wait for income activity * from AMQP broker * * @return float */ public function getReadTimeout() {} /** * Sets the interval of time to wait for outcome activity to AMQP broker * * @param float $timeout * * @throws AMQPConnectionException If timeout is less than 0. * * @return void */ public function setWriteTimeout($timeout) {} /** * Get the configured interval of time to wait for outcome activity * to AMQP broker * * @return float */ public function getWriteTimeout() {} /** * Get the configured timeout (in seconds) for connecting to the AMQP broker */ public function getConnectTimeout(): float {} /** * Sets the interval of time to wait for RPC activity to AMQP broker * * @param float $timeout * * @throws AMQPConnectionException If timeout is less than 0. * * @return void */ public function setRpcTimeout($timeout) {} /** * Get the configured interval of time to wait for RPC activity * to AMQP broker * * @return float */ public function getRpcTimeout() {} /** * Return last used channel id during current connection session. * * @return int */ public function getUsedChannels() {} /** * Get the maximum number of channels the connection can handle. * * When connection is connected, effective connection value returned, which is normally the same as original * correspondent value passed to constructor, otherwise original value passed to constructor returned. * * @return int */ public function getMaxChannels() {} /** * Get max supported frame size per connection in bytes. * * When connection is connected, effective connection value returned, which is normally the same as original * correspondent value passed to constructor, otherwise original value passed to constructor returned. * * @return int */ public function getMaxFrameSize() {} /** * Get number of seconds between heartbeats of the connection in seconds. * * When connection is connected, effective connection value returned, which is normally the same as original * correspondent value passed to constructor, otherwise original value passed to constructor returned. * * @return int */ public function getHeartbeatInterval() {} /** * Get path to the CA cert file in PEM format * * @return string|null */ public function getCACert() {} /** * Set path to the CA cert file in PEM format * * @param string $cacert * * @return void */ public function setCACert($cacert) {} /** * Get path to the client certificate in PEM format * * @return string|null */ public function getCert() {} /** * Set path to the client certificate in PEM format * * @param string $cert * * @return void */ public function setCert($cert) {} /** * Get path to the client key in PEM format * * @return string|null */ public function getKey() {} /** * Set path to the client key in PEM format * * @param string|null $key * * @return void */ public function setKey($key) {} /** * Get whether peer verification enabled or disabled * * @return bool */ public function getVerify() {} /** * Enable or disable peer verification * * @param bool $verify * * @return void */ public function setVerify($verify) {} /** * set authentication method * * @param int $saslMethod AMQP_SASL_METHOD_PLAIN | AMQP_SASL_METHOD_EXTERNAL * * @return void */ public function setSaslMethod($method) {} /** * Get authentication mechanism configuration * * @return int AMQP_SASL_METHOD_PLAIN | AMQP_SASL_METHOD_EXTERNAL */ public function getSaslMethod() {} public function setConnectionName(?string $connectionName): void {} public function getConnectionName(): ?string {} } /** * stub class representing AMQPConnectionException from pecl-amqp */ class AMQPConnectionException extends AMQPException {} /** * Interface representing AMQP values */ interface AMQPValue { public function toAmqpValue(): float|array|AMQPDecimal|bool|int|AMQPValue|string|AMQPTimestamp|null; } /** * stub class representing AMQPDecimal from pecl-amqp */ final /* readonly */ class AMQPDecimal implements AMQPValue { public const EXPONENT_MIN = 0; public const EXPONENT_MAX = 255; public const SIGNIFICAND_MIN = 0; public const SIGNIFICAND_MAX = 4294967295; /** * @param $exponent * @param $significand * * @throws AMQPExchangeValue */ public function __construct($exponent, $significand) {} /** @return int */ public function getExponent() {} /** @return int */ public function getSignificand() {} public function toAmqpValue(): float|array|AMQPDecimal|bool|int|AMQPValue|string|AMQPTimestamp|null {} } /** * stub class representing AMQPEnvelope from pecl-amqp */ class AMQPEnvelope extends AMQPBasicProperties { /** * Get the body of the message. * * @return string The contents of the message body. */ public function getBody() {} /** * Get the routing key of the message. * * @return string The message routing key. */ public function getRoutingKey() {} /** * Get the consumer tag of the message. * * @return string|null The consumer tag of the message. */ public function getConsumerTag() {} /** * Get the delivery tag of the message. * * @return int|null The delivery tag of the message. */ public function getDeliveryTag() {} /** * Get the exchange name on which the message was published. * * @return string|null The exchange name on which the message was published. */ public function getExchangeName() {} /** * Whether this is a redelivery of the message. * * Whether this is a redelivery of a message. If this message has been * delivered and AMQPEnvelope::nack() was called, the message will be put * back on the queue to be redelivered, at which point the message will * always return TRUE when this method is called. * * @return bool TRUE if this is a redelivery, FALSE otherwise. */ public function isRedelivery() {} /** * Get a specific message header. * * @param string $headerName Name of the header to get the value from. * * @return mixed The contents of the specified header or null if not set. */ public function getHeader($headerName) {} /** * Check whether specific message header exists. * * @param string $headerName Name of the header to check. * * @return bool */ public function hasHeader($headerName) {} } /** * stub class representing AMQPEnvelopeException from pecl-amqp */ class AMQPEnvelopeException extends AMQPException { public function getEnvelope(): AMQPEnvelope {} } /** * stub class representing AMQPException from pecl-amqp */ class AMQPException extends Exception {} /** * stub class representing AMQPExchange from pecl-amqp */ class AMQPExchange { /** * Create an instance of AMQPExchange. * * Returns a new instance of an AMQPExchange object, associated with the * given AMQPChannel object. * * @param AMQPChannel $channel A valid AMQPChannel object, connected * to a broker. * * @throws AMQPExchangeException When amqp_channel is not connected to * a broker. * @throws AMQPConnectionException If the connection to the broker was * lost. */ public function __construct(AMQPChannel $channel) {} /** * Bind to another exchange. * * Bind an exchange to another exchange using the specified routing key. * * @param string $exchangeName Name of the exchange to bind. * @param string $routingKey The routing key to use for binding. * @param array $arguments Additional binding arguments. * * @throws AMQPExchangeException On failure. * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return void */ public function bind($exchangeName, $routingKey = '', array $arguments = []) {} /** * Remove binding to another exchange. * * Remove a routing key binding on an another exchange from the given exchange. * * @param string $exchangeName Name of the exchange to bind. * @param string $routingKey The routing key to use for binding. * @param array $arguments Additional binding arguments. * * @throws AMQPExchangeException On failure. * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return void */ public function unbind($exchangeName, $routingKey = '', array $arguments = []) {} /** * Declare a new exchange on the broker. * * @throws AMQPExchangeException On failure. * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return void */ public function declareExchange() {} /** * Declare a new exchange on the broker. * * @throws AMQPExchangeException On failure. * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return void */ public function declare(): void {} /** * Delete the exchange from the broker. * * @param string $exchangeName Optional name of exchange to delete. * @param int $flags Optionally AMQP_IFUNUSED can be specified * to indicate the exchange should not be * deleted until no clients are connected to * it. * * @throws AMQPExchangeException On failure. * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return void */ public function delete($exchangeName = null, $flags = AMQP_NOPARAM) {} /** * Get the argument associated with the given key. * Get the argument associated with the given key. * * @param string $argumentName The key to look up. * * @throws AMQPExchangeException If key does not exist * * @return bool|int|float|string|null */ public function getArgument($argumentName) {} /** * Check whether argument associated with the given key exists. * * @param string $argumentName The key to look up. * * @return bool */ public function hasArgument($argumentName) {} /** * Get all arguments set on the given exchange. * * @return array An array containing all of the set key/value pairs. */ public function getArguments() {} /** * Get all the flags currently set on the given exchange. * * @return int An integer bitmask of all the flags currently set on this * exchange object. */ public function getFlags() {} /** * Get the configured name. * * @return string|null The configured name as a string. */ public function getName() {} /** * Get the configured type. * * @return string|null The configured type as a string. */ public function getType() {} /** * Publish a message to an exchange. * * Publish a message to the exchange represented by the AMQPExchange object. * * @param string $message The message to publish. * @param string|null $routingKey The optional routing key to which to * publish to. * @param int|null $flags One or more of AMQP_MANDATORY and * AMQP_IMMEDIATE. * @param array $headers One of content_type, content_encoding, * message_id, user_id, app_id, delivery_mode, * priority, timestamp, expiration, type * or reply_to, headers. * * @throws AMQPExchangeException On failure. * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return void */ public function publish( $message, $routingKey = null, $flags = null, array $headers = [] ) {} /** * Set the value for the given key. * * @param string $argumentName Name of the argument to set. * @param string|int $argumentValue Value of the argument to set. * * @return void */ public function setArgument($argumentName, $argumentValue) {} /** * Set the value for the given key. * * @param string $argumentName Name of the argument to remove. */ public function removeArgument(string $argumentName): void {} /** * Set all arguments on the exchange. * * @param array $arguments An array of key/value pairs of arguments. * * @return bool TRUE on success or FALSE on failure. */ public function setArguments(array $arguments) {} /** * Set the flags on an exchange. * * @param int|null $flags A bitmask of flags. This call currently only * considers the following flags: * AMQP_DURABLE, AMQP_PASSIVE * (and AMQP_DURABLE, if librabbitmq version >= 0.5.3) * * @return void */ public function setFlags($flags) {} /** * Set the name of the exchange. * * @param string $exchangeName The name of the exchange to set as string. * * @return void */ public function setName($exchangeName) {} /** * Set the type of the exchange. * * Set the type of the exchange. This can be any of AMQP_EX_TYPE_DIRECT, * AMQP_EX_TYPE_FANOUT, AMQP_EX_TYPE_HEADERS or AMQP_EX_TYPE_TOPIC. * * @param string $exchangeType The type of exchange as a string. * * @return void */ public function setType($exchangeType) {} /** * Get the AMQPChannel object in use * * @return AMQPChannel */ public function getChannel() {} /** * Get the AMQPConnection object in use * * @return AMQPConnection */ public function getConnection() {} } /** * stub class representing AMQPExchangeException from pecl-amqp */ class AMQPExchangeException extends AMQPException {} /** * stub class representing AMQPQueue from pecl-amqp */ class AMQPQueue { /** * Create an instance of an AMQPQueue object. * * @param AMQPChannel $channel The amqp channel to use. * * @throws AMQPQueueException When amqp_channel is not connected to a * broker. * @throws AMQPConnectionException If the connection to the broker was lost. */ public function __construct(AMQPChannel $channel) {} /** * Acknowledge the receipt of a message. * * This method allows the acknowledgement of a message that is retrieved * without the AMQP_AUTOACK flag through AMQPQueue::get() or * AMQPQueue::consume() * * @param int $deliveryTag The message delivery tag of which to * acknowledge receipt. * @param int|null $flags The only valid flag that can be passed is * AMQP_MULTIPLE. * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return void */ public function ack($deliveryTag, $flags = null) {} /** * Bind the given queue to a routing key on an exchange. * * @param string $exchangeName Name of the exchange to bind to. * @param string|null $routingKey Pattern or routing key to bind with. * @param array $arguments Additional binding arguments. * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return bool */ public function bind($exchangeName, $routingKey = null, array $arguments = []) {} /** * Cancel a queue that is already bound to an exchange and routing key. * * @param string $consumer_tag The consumer tag cancel. If no tag provided, * or it is empty string, the latest consumer * tag on this queue will be used and after * successful request it will set to null. * If it also empty, no `basic.cancel` * request will be sent. When consumer_tag give * and it equals to latest consumer_tag on queue, * it will be interpreted as latest consumer_tag usage. * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return bool */ public function cancel($consumer_tag = '') {} /** * Consume messages from a queue. * * Blocking function that will retrieve the next message from the queue as * it becomes available and will pass it off to the callback. * * @param callable|null $callback A callback function to which the * consumed message will be passed. The * function must accept at a minimum * one parameter, an AMQPEnvelope object, * and an optional second parameter * the AMQPQueue object from which callback * was invoked. The AMQPQueue::consume() will * not return the processing thread back to * the PHP script until the callback * function returns FALSE. * If the callback is omitted or null is passed, * then the messages delivered to this client will * be made available to the first real callback * registered. That allows one to have a single * callback consuming from multiple queues. * @param int|null $flags A bitmask of any of the flags: AMQP_AUTOACK, * AMQP_JUST_CONSUME. Note: when AMQP_JUST_CONSUME * flag used all other flags are ignored and * $consumerTag parameter has no sense. * AMQP_JUST_CONSUME flag prevent from sending * `basic.consume` request and just run $callback * if it provided. Calling method with empty $callback * and AMQP_JUST_CONSUME makes no sense. * @param string|null $consumerTag A string describing this consumer. Used * for canceling subscriptions with cancel(). * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * @throws AMQPEnvelopeException When no queue found for envelope. * @throws AMQPQueueException If timeout occurs or queue is not exists. * * @return void */ public function consume( callable $callback = null, $flags = null, $consumerTag = null ) {} /** * Declare a new queue on the broker. * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * @throws AMQPQueueException On failure. * * @return int the message count. */ public function declareQueue() {} /** * Declare a new queue on the broker. * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * @throws AMQPQueueException On failure. * * @return int the message count. */ public function declare(): int {} /** * Delete a queue from the broker. * * This includes its entire contents of unread or unacknowledged messages. * * @param int $flags Optionally AMQP_IFUNUSED can be specified * to indicate the queue should not be * deleted until no clients are connected to * it. * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return int The number of deleted messages. */ public function delete($flags = AMQP_NOPARAM) {} /** * Retrieve the next message from the queue. * * Retrieve the next available message from the queue. If no messages are * present in the queue, this function will return NULL immediately. This * is a non blocking alternative to the AMQPQueue::consume() method. * Currently, the only supported flag for the flags parameter is * AMQP_AUTOACK. If this flag is passed in, then the message returned will * automatically be marked as acknowledged by the broker as soon as the * frames are sent to the client. * * @param int $flags A bitmask of supported flags for the * method call. Currently, the only the * supported flag is AMQP_AUTOACK. If this * value is not provided, it will use the * value of ini-setting amqp.auto_ack. * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * @throws AMQPQueueException If queue is not exist. * * @return AMQPEnvelope|null */ public function get($flags = null) {} /** * Get all the flags currently set on the given queue. * * @return int An integer bitmask of all the flags currently set on this * exchange object. */ public function getFlags(): int {} /** * Get the configured name. * * @return string|null The configured name as a string. */ public function getName(): ?string {} /** * Mark a message as explicitly not acknowledged. * * Mark the message identified by delivery_tag as explicitly not * acknowledged. This method can only be called on messages that have not * yet been acknowledged, meaning that messages retrieved with by * AMQPQueue::consume() and AMQPQueue::get() and using the AMQP_AUTOACK * flag are not eligible. When called, the broker will immediately put the * message back onto the queue, instead of waiting until the connection is * closed. This method is only supported by the RabbitMQ broker. The * behavior of calling this method while connected to any other broker is * undefined. * * @param int $deliveryTag Delivery tag of last message to reject. * @param int $flags AMQP_REQUEUE to requeue the message(s), * AMQP_MULTIPLE to nack all previous * unacked messages as well. * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return bool */ public function nack($deliveryTag, $flags = AMQP_NOPARAM) {} /** * Mark one message as explicitly not acknowledged. * * Mark the message identified by delivery_tag as explicitly not * acknowledged. This method can only be called on messages that have not * yet been acknowledged, meaning that messages retrieved with by * AMQPQueue::consume() and AMQPQueue::get() and using the AMQP_AUTOACK * flag are not eligible. * * @param int $deliveryTag Delivery tag of the message to reject. * @param int|null $flags AMQP_REQUEUE to requeue the message(s). * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return bool */ public function reject($deliveryTag, $flags = null) {} /** * Recover unacknowledged messages delivered to the current consumer. * * Recover all the unacknowledged messages delivered to the current consumer. * If $requeue is true, the broker can redeliver the messages to different * consumers. If $requeue is FALSE, it can only redeliver it to the current * consumer. RabbitMQ does not implement $request = false. * This method exposes `basic.recover` from the AMQP spec. * * @param bool $requeue If TRUE, deliver to any consumer, if FALSE, deliver to the current consumer only * @throws AMQPConnectionException If the connection to the broker was lost. * @throws AMQPChannelException If the channel is not open. */ public function recover(bool $requeue = true): void {} /** * Purge the contents of a queue. * * Returns the number of purged messages * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return int */ public function purge() {} /** * Get the argument associated with the given key. * * @param string $argumentName The key to look up. * @throws AMQPQueueException If key does not exist * @return bool|int|float|string|null|array|AMQPValue|AMQPDecimal|AMQPTimestamp */ public function getArgument($argumentName) {} /** * Set a queue argument. * * @param string $argumentName The key to set. * @param bool|int|float|string|null|array|AMQPValue|AMQPDecimal|AMQPTimestamp $argumentValue The argument value to set. * * @return void */ public function setArgument(string $argumentName, $argumentValue) {} /** * Set a queue argument. * * @param string $argumentName The argument name to set. */ public function removeArgument(string $argumentName): void {} /** * Set all arguments on the given queue. * * All other argument settings will be wiped. * * @param array $arguments An array of name/value pairs of arguments. */ public function setArguments(array $arguments): void {} /** * Get all set arguments as an array of key/value pairs. * * @return array An array containing all the set key/value pairs. */ public function getArguments(): array {} /** * Check whether a queue has specific argument. * * @param string $argumentName The argument name to check. * * @return bool */ public function hasArgument(string $argumentName): bool {} /** * Set the flags on the queue. * * @param int|null $flags A bitmask of flags: * AMQP_DURABLE, AMQP_PASSIVE, * AMQP_EXCLUSIVE, AMQP_AUTODELETE. * * @return bool */ public function setFlags($flags = null) {} /** * Set the queue name. * * @param string $name The name of the queue. * * @return bool */ public function setName($name) {} /** * Remove a routing key binding on an exchange from the given queue. * * @param string $exchangeName The name of the exchange on which the * queue is bound. * @param string|null $routingKey The binding routing key used by the * queue. * @param array $arguments Additional binding arguments. * * @throws AMQPChannelException If the channel is not open. * @throws AMQPConnectionException If the connection to the broker was lost. * * @return bool */ public function unbind($exchangeName, $routingKey = null, array $arguments = []) {} /** * Get the AMQPChannel object in use * * @return AMQPChannel */ public function getChannel() {} /** * Get the AMQPConnection object in use * * @return AMQPConnection */ public function getConnection() {} /** * Get latest consumer tag. If no consumer available or the latest on was canceled null will be returned. * * @return string|null */ public function getConsumerTag() {} } /** * stub class representing AMQPQueueException from pecl-amqp */ class AMQPQueueException extends AMQPException {} class AMQPValueException extends AMQPException {} /** * stub class representing AMQPTimestamp from pecl-amqp */ final /* readonly */ class AMQPTimestamp implements AMQPValue { public const MIN = 0.0; public const MAX = 18446744073709551616; /** * @throws AMQPValueException */ public function __construct(float $timestamp) {} public function __toString(): string {} public function getTimestamp(): float {} public function toAmqpValue(): float|array|AMQPDecimal|bool|int|AMQPValue|string|AMQPTimestamp|null {} } /** * stub class representing AMQPExchangeValue from pecl-amqp */ class AMQPExchangeValue extends AMQPException {} * Shall start recording coverage information * @return void */ function start() {} /** * (PHP >= 7.0, PECL pcov >= 1.0.0)
* Shall stop recording coverage information * @return void */ function stop() {} /** * (PHP >= 7.0, PECL pcov >= 1.0.0)
* Shall collect coverage information * @param int $type [optional]

* pcov\all shall collect coverage information for all files * pcov\inclusive shall collect coverage information for the specified files * pcov\exclusive shall collect coverage information for all but the specified files *

* @param array $filter

* path of files (realpath) that should be filtered *

* @return array */ function collect(int $type = all, array $filter = []) {} /** * (PHP >= 7.0, PECL pcov >= 1.0.0)
* Shall clear stored information * @param bool $files [optional]

* set true to clear file tables * Note: clearing the file tables may have surprising consequences *

* @return void */ function clear(bool $files = false) {} /** * (PHP >= 7.0, PECL pcov >= 1.0.0)
* Shall return list of files waiting to be collected * @return array */ function waiting() {} /** * (PHP >= 7.0, PECL pcov >= 1.0.0)
* Shall return the current size of the trace and cfg arena * @return int */ function memory() {} } * Checks out a working copy from the repository * @link https://php.net/manual/en/function.svn-checkout.php * @param string $repos

* String URL path to directory in repository to check out. *

* @param string $targetpath

* String local path to directory to check out in to *

* Relative paths will be resolved as if the current working directory was the one that contains the PHP binary. To use the calling script's working directory, use realpath or dirname(__FILE__). * @param int $revision [optional]

* Integer revision number of repository to check out. Default is * HEAD, the most recent revision. *

* @param int $flags [optional]

* Any combination of SVN_NON_RECURSIVE and * SVN_IGNORE_EXTERNALS. *

* @return bool TRUE on success or FALSE on failure. */ function svn_checkout($repos, $targetpath, $revision = SVN_REVISION_HEAD, $flags = 0) {} /** * (PECL svn >= 0.1.0)
* Returns the contents of a file in a repository * @link https://php.net/manual/en/function.svn-cat.php * @param string $repos_url

* String URL path to item in a repository. *

* @param int $revision_no [optional]

* Integer revision number of item to retrieve, default is the HEAD * revision. *

* @return string the string contents of the item from the repository on * success, and FALSE on failure. */ function svn_cat($repos_url, $revision_no = SVN_REVISION_HEAD) {} /** * (PECL svn >= 0.1.0)
* Returns list of directory contents in repository URL, optionally at revision number * @link https://php.net/manual/en/function.svn-ls.php * @param string $repos_url * @param int $revision_no [optional] * @param bool $recurse [optional]

* Enables recursion. *

* @param bool $peg [optional] * @return array On success, this function returns an array file listing in the format * of: *
 * [0] => Array
 * (
 * [created_rev] => integer revision number of last edit
 * [last_author] => string author name of last edit
 * [size] => integer byte file size of file
 * [time] => string date of last edit in form 'M d H:i'
 * or 'M d Y', depending on how old the file is
 * [time_t] => integer unix timestamp of last edit
 * [name] => name of file/directory
 * [type] => type, can be 'file' or 'dir'
 * )
 * [1] => ...
 * 
*/ function svn_ls($repos_url, $revision_no = SVN_REVISION_HEAD, $recurse = false, $peg = false) {} /** * (PECL svn >= 0.1.0)
* Returns the commit log messages of a repository URL * @link https://php.net/manual/en/function.svn-log.php * @param string $repos_url

* Repository URL of the item to retrieve log history from. *

* @param int $start_revision [optional]

* Revision number of the first log to retrieve. Use * SVN_REVISION_HEAD to retrieve the log from * the most recent revision. *

* @param int $end_revision [optional]

* Revision number of the last log to retrieve. Defaults to * start_revision if specified or to * SVN_REVISION_INITIAL otherwise. *

* @param int $limit [optional]

* Number of logs to retrieve. *

* @param int $flags [optional]

* Any combination of SVN_OMIT_MESSAGES, * SVN_DISCOVER_CHANGED_PATHS and * SVN_STOP_ON_COPY. *

* @return array On success, this function returns an array file listing in the format * of: *
 * [0] => Array, ordered most recent (highest) revision first
 * (
 * [rev] => integer revision number
 * [author] => string author name
 * [msg] => string log message
 * [date] => string date formatted per ISO 8601, i.e. date('c')
 * [paths] => Array, describing changed files
 * (
 * [0] => Array
 * (
 * [action] => string letter signifying change
 * [path] => absolute repository path of changed file
 * )
 * [1] => ...
 * )
 * )
 * [1] => ...
 * 
*

*

* The output will always be a numerically indexed array of arrays, * even when there are none or only one log message(s). *

*

* The value of action is a subset of the * status output * in the first column, where possible values are: *

* * Actions * * * * * * * * * * * * * * * * * * * * *
LetterDescription
MItem/props was modified
AItem was added
DItem was deleted
RItem was replaced
*

* If no changes were made to the item, an empty array is returned. */ function svn_log($repos_url, $start_revision = null, $end_revision = null, $limit = 0, $flags = SVN_DISCOVER_CHANGED_PATHS|SVN_STOP_ON_COPY) {} /** * (PECL svn >= 0.1.0)
* Sets an authentication parameter * @link https://php.net/manual/en/function.svn-auth-set-parameter.php * @param string $key

* String key name. Use the authentication constants * defined by this extension to specify a key. *

* @param string $value

* String value to set to parameter at key. Format of value varies * with the parameter. *

* @return void No value is returned. */ function svn_auth_set_parameter($key, $value) {} /** * (PECL svn >= 0.1.0)
* Retrieves authentication parameter * @link https://php.net/manual/en/function.svn-auth-get-parameter.php * @param string $key

* String key name. Use the authentication constants * defined by this extension to specify a key. *

* @return string|null the string value of the parameter at key; * returns NULL if parameter does not exist. */ function svn_auth_get_parameter($key) {} /** * (PECL svn >= 0.1.0)
* Returns the version of the SVN client libraries * @link https://php.net/manual/en/function.svn-client-version.php * @return string String version number, usually in form of x.y.z. */ function svn_client_version() {} function svn_config_ensure() {} /** * (PECL svn >= 0.1.0)
* Recursively diffs two paths * @link https://php.net/manual/en/function.svn-diff.php * @param string $path1

* First path to diff. This can be a URL to a file/directory in an SVN * repository or a local file/directory path. *

* Relative paths will be resolved as if the current working directory was the one that contains the PHP binary. To use the calling script's working directory, use realpath or dirname(__FILE__). * If a local file path has only backslashes and no forward slashes, * this extension will fail to find the path. Always * replace all backslashes with forward slashes when using this * function. * @param int $rev1

* First path's revision number. Use SVN_REVISION_HEAD * to specify the most recent revision. *

* @param string $path2

* Second path to diff. See path1 for description. *

* @param int $rev2

* Second path's revision number. See rev1 * for description. *

* @return array an array-list consisting of two streams: the first is the diff output * and the second contains error stream output. The streams can be * read using fread. Returns FALSE or NULL on * error. *

*

* The diff output will, by default, be in the form of Subversion's * custom unified diff format, but an * external * diff engine may be * used depending on Subversion's configuration. */ function svn_diff($path1, $rev1, $path2, $rev2) {} /** * (PECL svn >= 0.1.0)
* Recursively cleanup a working copy directory, finishing incomplete operations and removing locks * @link https://php.net/manual/en/function.svn-cleanup.php * @param string $workingdir

* String path to local working directory to cleanup *

* Relative paths will be resolved as if the current working directory was the one that contains the PHP binary. To use the calling script's working directory, use realpath or dirname(__FILE__). * @return bool TRUE on success or FALSE on failure. */ function svn_cleanup($workingdir) {} /** * (PECL svn >= 0.3.0)
* Revert changes to the working copy * @link https://php.net/manual/en/function.svn-revert.php * @param string $path

* The path to the working repository. *

* @param bool $recursive [optional]

* Optionally make recursive changes. *

* @return bool TRUE on success or FALSE on failure. */ function svn_revert($path, $recursive = false) {} function svn_resolved() {} /** * (PECL svn >= 0.1.0)
* Sends changes from the local working copy to the repository * @link https://php.net/manual/en/function.svn-commit.php * @param string $log

* String log text to commit *

* @param array $targets

* Array of local paths of files to be committed *

* This parameter must be an array, a string for a single * target is not acceptable. * Relative paths will be resolved as if the current working directory was the one that contains the PHP binary. To use the calling script's working directory, use realpath or dirname(__FILE__). * @param bool $recursive [optional]

* Boolean flag to disable recursive committing of * directories in the targets array. * Default is TRUE. *

* @return array array in form of: *
 * array(
 * 0 => integer revision number of commit
 * 1 => string ISO 8601 date and time of commit
 * 2 => name of committer
 * )
 * 
*

* Returns FALSE on failure. *

*/ function svn_commit($log, array $targets, $recursive = true) {} function svn_lock() {} function svn_unlock() {} /** * (PECL svn >= 0.1.0)
* Schedules the addition of an item in a working directory * @link https://php.net/manual/en/function.svn-add.php * @param string $path

* Path of item to add. *

* Relative paths will be resolved as if the current working directory was the one that contains the PHP binary. To use the calling script's working directory, use realpath or dirname(__FILE__). * @param bool $recursive [optional]

* If item is directory, whether or not to recursively add * all of its contents. Default is TRUE *

* @param bool $force [optional]

* If true, Subversion will recurse into already versioned directories * in order to add unversioned files that may be hiding in those * directories. Default is FALSE *

* @return bool TRUE on success or FALSE on failure. */ function svn_add($path, $recursive = true, $force = false) {} /** * (PECL svn >= 0.1.0)
* Returns the status of working copy files and directories * @link https://php.net/manual/en/function.svn-status.php * @param string $path

* Local path to file or directory to retrieve status of. *

* Relative paths will be resolved as if the current working directory was the one that contains the PHP binary. To use the calling script's working directory, use realpath or dirname(__FILE__). * @param int $flags [optional]

* Any combination of SVN_NON_RECURSIVE, * SVN_ALL (regardless of modification status), * SVN_SHOW_UPDATES (entries will be added for items * that are out-of-date), SVN_NO_IGNORE (disregard * svn:ignore properties when scanning for new files) * and SVN_IGNORE_EXTERNALS. *

* @return array a numerically indexed array of associative arrays detailing * the status of items in the repository: *

*
 * Array (
 * [0] => Array (
 * // information on item
 * )
 * [1] => ...
 * )
 * 
*

* The information on the item is an associative array that can contain * the following keys: *

* path * String path to file/directory of this entry on local filesystem. * text_status * Status of item's text. Refer to status constants for possible values. * repos_text_status * Status of item's text in repository. Only accurate if * update was set to TRUE. * Refer to status constants for possible values. * prop_status * Status of item's properties. Refer to status constants for possible values. * repos_prop_status * Status of item's property in repository. Only accurate if * update was set to TRUE. Refer to status constants for possible values. * locked * Whether or not the item is locked. (Only set if TRUE.) * copied * Whether or not the item was copied (scheduled for addition with * history). (Only set if TRUE.) * switched * Whether or not the item was switched using the switch command. * (Only set if TRUE) *

* These keys are only set if the item is versioned: *

* name * Base name of item in repository. * url * URL of item in repository. * repos * Base URL of repository. * revision * Integer revision of item in working copy. * kind * Type of item, i.e. file or directory. Refer to type constants for possible values. * schedule * Scheduled action for item, i.e. addition or deletion. Constants * for these magic numbers are not available, they can * be emulated by using: * * if (!defined('svn_wc_schedule_normal')) { * define('svn_wc_schedule_normal', 0); // nothing special * define('svn_wc_schedule_add', 1); // item will be added * define('svn_wc_schedule_delete', 2); // item will be deleted * define('svn_wc_schedule_replace', 3); // item will be added and deleted * } * * deleted * Whether or not the item was deleted, but parent revision lags * behind. (Only set if TRUE.) * absent * Whether or not the item is absent, that is, Subversion knows that * there should be something there but there isn't. (Only set if * TRUE.) * incomplete * Whether or not the entries file for a directory is incomplete. * (Only set if TRUE.) * cmt_date * Integer Unix timestamp of last commit date. (Unaffected by update.) * cmt_rev * Integer revision of last commit. (Unaffected by update.) * cmt_author * String author of last commit. (Unaffected by update */ function svn_status($path, $flags = 0) {} /** * (PECL svn >= 0.1.0)
* Update working copy * @link https://php.net/manual/en/function.svn-update.php * @param string $path

* Path to local working copy. *

* Relative paths will be resolved as if the current working directory was the one that contains the PHP binary. To use the calling script's working directory, use realpath or dirname(__FILE__). * @param int $revno [optional]

* Revision number to update to, default is SVN_REVISION_HEAD. *

* @param bool $recurse [optional]

* Whether or not to recursively update directories. *

* @return int|false new revision number on success, returns FALSE on failure. */ function svn_update($path, $revno = SVN_REVISION_HEAD, $recurse = true) {} /** * (PECL svn >= 0.2.0)
* Imports an unversioned path into a repository * @link https://php.net/manual/en/function.svn-import.php * @param string $path

* Path of file or directory to import. *

* Relative paths will be resolved as if the current working directory was the one that contains the PHP binary. To use the calling script's working directory, use realpath or dirname(__FILE__). * @param string $url

* Repository URL to import into. *

* @param bool $nonrecursive

* Whether or not to refrain from recursively processing directories. *

* @return bool TRUE on success or FALSE on failure. */ function svn_import($path, $url, $nonrecursive) {} function svn_info() {} /** * (PECL svn >= 0.3.0)
* Export the contents of a SVN directory * @link https://php.net/manual/en/function.svn-export.php * @param string $frompath

* The path to the current repository. *

* @param string $topath

* The path to the new repository. *

* @param bool $working_copy [optional]

* If TRUE, it will export uncommitted files from the working copy. *

* @param int $revision_no [optional] * @return bool TRUE on success or FALSE on failure. */ function svn_export($frompath, $topath, $working_copy = true, $revision_no = -1) {} function svn_copy() {} function svn_switch() {} /** * (PECL svn >= 0.3.0)
* Get the SVN blame for a file * @link https://php.net/manual/en/function.svn-blame.php * @param string $repository_url

* The repository URL. *

* @param int $revision_no [optional]

* The revision number. *

* @return array An array of SVN blame information separated by line * which includes the revision number, line number, line of code, * author, and date. */ function svn_blame($repository_url, $revision_no = SVN_REVISION_HEAD) {} /** * (PECL svn >= 0.4.0)
* Delete items from a working copy or repository. * @link https://php.net/manual/en/function.svn-delete.php * @param string $path

* Path of item to delete. *

* Relative paths will be resolved as if the current working directory was the one that contains the PHP binary. To use the calling script's working directory, use realpath or dirname(__FILE__). * @param bool $force [optional]

* If TRUE, the file will be deleted even if it has local modifications. * Otherwise, local modifications will result in a failure. Default is * FALSE *

* @return bool TRUE on success or FALSE on failure. */ function svn_delete($path, $force = false) {} /** * (PECL svn >= 0.4.0)
* Creates a directory in a working copy or repository * @link https://php.net/manual/en/function.svn-mkdir.php * @param string $path

* The path to the working copy or repository. *

* @param string $log_message [optional] * @return bool TRUE on success or FALSE on failure. */ function svn_mkdir($path, $log_message = null) {} /** * @link https://php.net/manual/en/ref.svn.php * @param string $src_path * @param string $dst_path * @param bool $force [optional] * @return mixed */ function svn_move($src_path, $dst_path, $force = false) {} /** * @link https://php.net/manual/en/ref.svn.php * @param string $path * @param bool $recurse [optional] * @param int $revision [optional] * @return mixed */ function svn_proplist($path, $recurse = false, $revision) {} /** * @param string $path * @param string $property_name * @param bool $recurse [optional] * @param int $revision [optional] * @return mixed */ function svn_propget($path, $property_name, $recurse = false, $revision) {} /** * (PECL svn >= 0.1.0)
* Create a new subversion repository at path * @link https://php.net/manual/en/function.svn-repos-create.php * @param string $path

* Its description *

* @param null|array $config [optional]

* Its description *

* @param null|array $fsconfig [optional]

* Its description *

* @return resource What the function returns, first on success, then on failure. */ function svn_repos_create($path, ?array $config = null, ?array $fsconfig = null) {} /** * (PECL svn >= 0.1.0)
* Run recovery procedures on the repository located at path. * @link https://php.net/manual/en/function.svn-repos-recover.php * @param string $path

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_repos_recover($path) {} /** * (PECL svn >= 0.1.0)
* Make a hot-copy of the repos at repospath; copy it to destpath * @link https://php.net/manual/en/function.svn-repos-hotcopy.php * @param string $repospath

* Its description *

* @param string $destpath

* Its description *

* @param bool $cleanlogs

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_repos_hotcopy($repospath, $destpath, $cleanlogs) {} /** * (PECL svn >= 0.1.0)
* Open a shared lock on a repository. * @link https://php.net/manual/en/function.svn-repos-open.php * @param string $path

* Its description *

* @return resource What the function returns, first on success, then on failure. */ function svn_repos_open($path) {} /** * (PECL svn >= 0.1.0)
* Gets a handle on the filesystem for a repository * @link https://php.net/manual/en/function.svn-repos-fs.php * @param resource $repos

* Its description *

* @return resource What the function returns, first on success, then on failure. */ function svn_repos_fs($repos) {} /** * (PECL svn >= 0.2.0)
* Create a new transaction * @link https://php.net/manual/en/function.svn-repos-fs-begin-txn-for-commit.php * @param resource $repos

* Its description *

* @param int $rev

* Its description *

* @param string $author

* Its description *

* @param string $log_msg

* Its description *

* @return resource What the function returns, first on success, then on failure. */ function svn_repos_fs_begin_txn_for_commit($repos, $rev, $author, $log_msg) {} /** * (PECL svn >= 0.2.0)
* Commits a transaction and returns the new revision * @link https://php.net/manual/en/function.svn-repos-fs-commit-txn.php * @param resource $txn

* Its description *

* @return int What the function returns, first on success, then on failure. */ function svn_repos_fs_commit_txn($txn) {} /** * (PECL svn >= 0.1.0)
* Get a handle on a specific version of the repository root * @link https://php.net/manual/en/function.svn-fs-revision-root.php * @param resource $fs

* Its description *

* @param int $revnum

* Its description *

* @return resource What the function returns, first on success, then on failure. */ function svn_fs_revision_root($fs, $revnum) {} /** * (PECL svn >= 0.1.0)
* Determines what kind of item lives at path in a given repository fsroot * @link https://php.net/manual/en/function.svn-fs-check-path.php * @param resource $fsroot

* Its description *

* @param string $path

* Its description *

* @return int What the function returns, first on success, then on failure. */ function svn_fs_check_path($fsroot, $path) {} /** * (PECL svn >= 0.1.0)
* Fetches the value of a named property * @link https://php.net/manual/en/function.svn-fs-revision-prop.php * @param resource $fs

* Its description *

* @param int $revnum

* Its description *

* @param string $propname

* Its description *

* @return string What the function returns, first on success, then on failure. */ function svn_fs_revision_prop($fs, $revnum, $propname) {} /** * (PECL svn >= 0.1.0)
* Enumerates the directory entries under path; returns a hash of dir names to file type * @link https://php.net/manual/en/function.svn-fs-dir-entries.php * @param resource $fsroot

* Its description *

* @param string $path

* Its description *

* @return array What the function returns, first on success, then on failure. */ function svn_fs_dir_entries($fsroot, $path) {} /** * (PECL svn >= 0.1.0)
* Returns the revision in which path under fsroot was created * @link https://php.net/manual/en/function.svn-fs-node-created-rev.php * @param resource $fsroot

* Its description *

* @param string $path

* Its description *

* @return int What the function returns, first on success, then on failure. */ function svn_fs_node_created_rev($fsroot, $path) {} /** * (PECL svn >= 0.1.0)
* Returns the number of the youngest revision in the filesystem * @link https://php.net/manual/en/function.svn-fs-youngest-rev.php * @param resource $fs

* Its description *

* @return int What the function returns, first on success, then on failure. */ function svn_fs_youngest_rev($fs) {} /** * (PECL svn >= 0.1.0)
* Returns a stream to access the contents of a file from a given version of the fs * @link https://php.net/manual/en/function.svn-fs-file-contents.php * @param resource $fsroot

* Its description *

* @param string $path

* Its description *

* @return resource What the function returns, first on success, then on failure. */ function svn_fs_file_contents($fsroot, $path) {} /** * (PECL svn >= 0.1.0)
* Returns the length of a file from a given version of the fs * @link https://php.net/manual/en/function.svn-fs-file-length.php * @param resource $fsroot

* Its description *

* @param string $path

* Its description *

* @return int What the function returns, first on success, then on failure. */ function svn_fs_file_length($fsroot, $path) {} /** * (PECL svn >= 0.2.0)
* Creates and returns a transaction root * @link https://php.net/manual/en/function.svn-fs-txn-root.php * @param resource $txn

* Its description *

* @return resource What the function returns, first on success, then on failure. */ function svn_fs_txn_root($txn) {} /** * (PECL svn >= 0.2.0)
* Creates a new empty file, returns true if all is ok, false otherwise * @link https://php.net/manual/en/function.svn-fs-make-file.php * @param resource $root

* Its description *

* @param string $path

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_make_file($root, $path) {} /** * (PECL svn >= 0.2.0)
* Creates a new empty directory, returns true if all is ok, false otherwise * @link https://php.net/manual/en/function.svn-fs-make-dir.php * @param resource $root

* Its description *

* @param string $path

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_make_dir($root, $path) {} /** * (PECL svn >= 0.2.0)
* Creates and returns a stream that will be used to replace * @link https://php.net/manual/en/function.svn-fs-apply-text.php * @param resource $root

* Its description *

* @param string $path

* Its description *

* @return resource What the function returns, first on success, then on failure. */ function svn_fs_apply_text($root, $path) {} /** * (PECL svn >= 0.2.0)
* Copies a file or a directory, returns true if all is ok, false otherwise * @link https://php.net/manual/en/function.svn-fs-copy.php * @param resource $from_root

* Its description *

* @param string $from_path

* Its description *

* @param resource $to_root

* Its description *

* @param string $to_path

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_copy($from_root, $from_path, $to_root, $to_path) {} /** * (PECL svn >= 0.2.0)
* Deletes a file or a directory, return true if all is ok, false otherwise * @link https://php.net/manual/en/function.svn-fs-delete.php * @param resource $root

* Its description *

* @param string $path

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_delete($root, $path) {} /** * (PECL svn >= 0.2.0)
* Create a new transaction * @link https://php.net/manual/en/function.svn-fs-begin-txn2.php * @param resource $repos

* Its description *

* @param int $rev

* Its description *

* @return resource What the function returns, first on success, then on failure. */ function svn_fs_begin_txn2($repos, $rev) {} /** * (PECL svn >= 0.2.0)
* Return true if the path points to a directory, false otherwise * @link https://php.net/manual/en/function.svn-fs-is-dir.php * @param resource $root

* Its description *

* @param string $path

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_is_dir($root, $path) {} /** * (PECL svn >= 0.2.0)
* Return true if the path points to a file, false otherwise * @link https://php.net/manual/en/function.svn-fs-is-file.php * @param resource $root

* Its description *

* @param string $path

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_is_file($root, $path) {} /** * (PECL svn >= 0.1.0)
* Returns the value of a property for a node * @link https://php.net/manual/en/function.svn-fs-node-prop.php * @param resource $fsroot

* Its description *

* @param string $path

* Its description *

* @param string $propname

* Its description *

* @return string What the function returns, first on success, then on failure. */ function svn_fs_node_prop($fsroot, $path, $propname) {} /** * (PECL svn >= 0.2.0)
* Return true if everything is ok, false otherwise * @link https://php.net/manual/en/function.svn-fs-change-node-prop.php * @param resource $root

* Its description *

* @param string $path

* Its description *

* @param string $name

* Its description *

* @param string $value

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_change_node_prop($root, $path, $name, $value) {} /** * (PECL svn >= 0.2.0)
* Return true if content is different, false otherwise * @link https://php.net/manual/en/function.svn-fs-contents-changed.php * @param resource $root1

* Its description *

* @param string $path1

* Its description *

* @param resource $root2

* Its description *

* @param string $path2

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_contents_changed($root1, $path1, $root2, $path2) {} /** * (PECL svn >= 0.2.0)
* Return true if props are different, false otherwise * @link https://php.net/manual/en/function.svn-fs-props-changed.php * @param resource $root1

* Its description *

* @param string $path1

* Its description *

* @param resource $root2

* Its description *

* @param string $path2

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_props_changed($root1, $path1, $root2, $path2) {} /** * (PECL svn >= 0.2.0)
* Abort a transaction, returns true if everything is okay, false otherwise * @link https://php.net/manual/en/function.svn-fs-abort-txn.php * @param resource $txn

* Its description *

* @return bool What the function returns, first on success, then on failure. */ function svn_fs_abort_txn($txn) {} /** * Property for default username to use when performing basic authentication * @link https://php.net/manual/en/svn.constants.php */ define('SVN_AUTH_PARAM_DEFAULT_USERNAME', "svn:auth:username"); /** * Property for default password to use when performing basic authentication * @link https://php.net/manual/en/svn.constants.php */ define('SVN_AUTH_PARAM_DEFAULT_PASSWORD', "svn:auth:password"); define('SVN_AUTH_PARAM_NON_INTERACTIVE', "svn:auth:non-interactive"); define('SVN_AUTH_PARAM_DONT_STORE_PASSWORDS', "svn:auth:dont-store-passwords"); define('SVN_AUTH_PARAM_NO_AUTH_CACHE', "svn:auth:no-auth-cache"); define('SVN_AUTH_PARAM_SSL_SERVER_FAILURES', "svn:auth:ssl:failures"); define('SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO', "svn:auth:ssl:cert-info"); define('SVN_AUTH_PARAM_CONFIG', "svn:auth:config-category-servers"); define('SVN_AUTH_PARAM_SERVER_GROUP', "svn:auth:server-group"); define('SVN_AUTH_PARAM_CONFIG_DIR', "svn:auth:config-dir"); /** * Custom property for ignoring SSL cert verification errors * @link https://php.net/manual/en/svn.constants.php */ define('PHP_SVN_AUTH_PARAM_IGNORE_SSL_VERIFY_ERRORS', "php:svn:auth:ignore-ssl-verify-errors"); /** * Configuration key that determines filesystem type * @link https://php.net/manual/en/svn.constants.php */ define('SVN_FS_CONFIG_FS_TYPE', "fs-type"); /** * Filesystem is Berkeley-DB implementation * @link https://php.net/manual/en/svn.constants.php */ define('SVN_FS_TYPE_BDB', "bdb"); /** * Filesystem is native-filesystem implementation * @link https://php.net/manual/en/svn.constants.php */ define('SVN_FS_TYPE_FSFS', "fsfs"); /** * svn:date * @link https://php.net/manual/en/svn.constants.php */ define('SVN_PROP_REVISION_DATE', "svn:date"); /** * svn:original-date * @link https://php.net/manual/en/svn.constants.php */ define('SVN_PROP_REVISION_ORIG_DATE', "svn:original-date"); /** * svn:author * @link https://php.net/manual/en/svn.constants.php */ define('SVN_PROP_REVISION_AUTHOR', "svn:author"); /** * svn:log * @link https://php.net/manual/en/svn.constants.php */ define('SVN_PROP_REVISION_LOG', "svn:log"); define('SVN_REVISION_INITIAL', 1); /** * Magic number (-1) specifying the HEAD revision * @link https://php.net/manual/en/svn.constants.php */ define('SVN_REVISION_HEAD', -1); define('SVN_REVISION_BASE', -2); define('SVN_REVISION_COMMITTED', -3); define('SVN_REVISION_PREV', -4); define('SVN_REVISION_UNSPECIFIED', -5); define('SVN_NON_RECURSIVE', 1); define('SVN_DISCOVER_CHANGED_PATHS', 2); define('SVN_OMIT_MESSAGES', 4); define('SVN_STOP_ON_COPY', 8); define('SVN_ALL', 16); define('SVN_SHOW_UPDATES', 32); define('SVN_NO_IGNORE', 64); /** * Status does not exist * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_NONE', 1); /** * Item is not versioned in working copy * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_UNVERSIONED', 2); /** * Item exists, nothing else is happening * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_NORMAL', 3); /** * Item is scheduled for addition * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_ADDED', 4); /** * Item is versioned but missing from the working copy * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_MISSING', 5); /** * Item is scheduled for deletion * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_DELETED', 6); /** * Item was deleted and then re-added * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_REPLACED', 7); /** * Item (text or properties) was modified * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_MODIFIED', 8); /** * Item's local modifications were merged with repository modifications * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_MERGED', 9); /** * Item's local modifications conflicted with repository modifications * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_CONFLICTED', 10); /** * Item is unversioned but configured to be ignored * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_IGNORED', 11); /** * Unversioned item is in the way of a versioned resource * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_OBSTRUCTED', 12); /** * Unversioned path that is populated using svn:externals * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_EXTERNAL', 13); /** * Directory does not contain complete entries list * @link https://php.net/manual/en/svn.constants.php */ define('SVN_WC_STATUS_INCOMPLETE', 14); /** * Absent * @link https://php.net/manual/en/svn.constants.php */ define('SVN_NODE_NONE', 0); /** * File * @link https://php.net/manual/en/svn.constants.php */ define('SVN_NODE_FILE', 1); /** * Directory * @link https://php.net/manual/en/svn.constants.php */ define('SVN_NODE_DIR', 2); /** * Something Subversion cannot identify * @link https://php.net/manual/en/svn.constants.php */ define('SVN_NODE_UNKNOWN', 3); define('SVN_WC_SCHEDULE_NORMAL', 0); define('SVN_WC_SCHEDULE_ADD', 1); define('SVN_WC_SCHEDULE_DELETE', 2); define('SVN_WC_SCHEDULE_REPLACE', 3); true, // if the specified database does not exist will create a new one 'error_if_exists' => false, // if the opened database exists will throw exception 'paranoid_checks' => false, 'block_cache_size' => 8 * (2 << 20), 'write_buffer_size' => 4 << 20, 'block_size' => 4096, 'max_open_files' => 1000, 'block_restart_interval' => 16, 'compression' => LEVELDB_SNAPPY_COMPRESSION, 'comparator' => null, // any callable parameter return 0, -1, 1 ], array $read_options = [ 'verify_check_sum' => false, //may be set to true to force checksum verification of all data that is read from the file system on behalf of a particular read. By default, no such verification is done. 'fill_cache' => true, //When performing a bulk read, the application may set this to false to disable the caching so that the data processed by the bulk read does not end up displacing most of the cached contents. ], array $write_options = [ //Only one element named sync in the write option array. By default, each write to leveldb is asynchronous. 'sync' => false ]) {} /** * @param string $key * @param array $read_options * * @return string|false */ public function get($key, array $read_options = []) {} /** * Alias of LevelDB::put() * * @param string $key * @param string $value * @param array $write_options */ public function set($key, $value, array $write_options = []) {} /** * @param string $key * @param string $value * @param array $write_options */ public function put($key, $value, array $write_options = []) {} /** * @param string $key * @param array $write_options * * @return bool */ public function delete($key, array $write_options = []) {} /** * Executes all of the operations added in the write batch. * * @param LevelDBWriteBatch $batch * @param array $write_options */ public function write(LevelDBWriteBatch $batch, array $write_options = []) {} /** * Valid properties: * - leveldb.stats: returns the status of the entire db * - leveldb.num-files-at-level: returns the number of files for each level. For example, you can use leveldb.num-files-at-level0 the number of files for zero level. * - leveldb.sstables: returns current status of sstables * * @param string $name * * @return mixed */ public function getProperty($name) {} public function getApproximateSizes($start, $limit) {} public function compactRange($start, $limit) {} public function close() {} /** * @param array $options * * @return LevelDBIterator */ public function getIterator(array $options = []) {} /** * @return LevelDBSnapshot */ public function getSnapshot() {} public static function destroy($name, array $options = []) {} public static function repair($name, array $options = []) {} } class LevelDBIterator implements Iterator { public function __construct(LevelDB $db, array $read_options = []) {} public function valid() {} public function rewind() {} public function last() {} public function seek($key) {} public function next() {} public function prev() {} public function key() {} public function current() {} public function getError() {} public function destroy() {} } class LevelDBWriteBatch { public function __construct() {} public function set($key, $value, array $write_options = []) {} public function put($key, $value, array $write_options = []) {} public function delete($key, array $write_options = []) {} public function clear() {} } class LevelDBSnapshot { public function __construct(LevelDB $db) {} public function release() {} } class LevelDBException extends Exception {} * @copyright Copyright 2013-2016 Aerospike, Inc. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2 * @link https://github.com/aerospike/aerospike-client-php/blob/master/doc/README.md#handling-unsupported-types * @filesource */ namespace Aerospike; /** * \Aerospike\Bytes is a utility for wrapping PHP strings containing * potentially harmful bytes such as \0. By wrapping the binary-string, the * Aerospike client will serialize the data into an as_bytes rather than an * as_string. * This ensures that the string will not get truncated or otherwise lose data. * The main difference is that strings in the Aerospike cluster can have a * secondary index built over them, and queries executed against the index, * while bytes data cannot. * * @package Aerospike * @author Ronen Botzer */ class Bytes implements \Serializable { /** * The container for the binary-string * @var string */ public $s; /** * Constructor for \Aerospike\Bytes class. * * @param string $bin_str a PHP binary-string such as gzdeflate() produces. */ public function __construct($bin_str) { $this->s = $bin_str; } /** * Returns a serialized representation of the binary-string. * Called by serialize() * * @return string */ public function serialize() { return $this->s; } /** * Re-wraps the binary-string when called by unserialize(). * * @param string $bin_str a PHP binary-string. Called by unserialize(). * @return string */ public function unserialize($bin_str) { return $this->s = $bin_str; } /** * Returns the binary-string held in the \Aerospike\Bytes object. * * @return string */ public function __toString() { return $this->s; } /** * Unwraps an \Aerospike\Bytes object, returning the binary-string inside. * * @param \Aerospike\Bytes $bytes_wrap * @return string */ public static function unwrap(Bytes $bytes_wrap) { return $bytes_wrap->s; } } * @copyright Copyright 2013-2018 Aerospike, Inc. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2 * @link https://www.aerospike.com/docs/client/php/ * @filesource */ use JetBrains\PhpStorm\Deprecated; /** * The Aerospike client class * * The Aerospike config options for `php.ini`: * ```php * // The connection timeout in milliseconds. * aerospike.connect_timeout = 1000; * // The read operation timeout in milliseconds. * aerospike.read_timeout = 1000; * // The write operation timeout in milliseconds. * aerospike.write_timeout = 1000; * // Whether to send and store the record's (ns,set,key) data along with * // its (unique identifier) digest. 0: digest, 1: send * aerospike.key_policy = 0; // only digest * // The unsupported type handler. 0: none, 1: PHP, 2: user-defined * aerospike.serializer = 1; // php serializer * // Path to the user-defined Lua function modules. * aerospike.udf.lua_user_path = /usr/local/aerospike/usr-lua; * // Indicates if shared memory should be used for cluster tending. * // Recommended for multi-process cases such as FPM. { true, false } * aerospike.shm.use = false; * // Explicitly sets the shm key for this client to store shared-memory * // cluster tending results in. * aerospike.shm.key = 0xA8000000; // integer value * // Shared memory maximum number of server nodes allowed. Leave a cushion so * // new nodes can be added without needing a client restart. * aerospike.shm.max_nodes = 16; * // Shared memory maximum number of namespaces allowed. Leave a cushion for * // new namespaces. * aerospike.shm.max_namespaces = 8; * // Take over shared memory cluster tending if the cluster hasn't been tended * // by this threshold in seconds. * aerospike.shm.takeover_threshold_sec = 30; * // Control the batch protocol. 0: batch-index, 1: batch-direct * aerospike.use_batch_direct = 0; * // The client will compress records larger than this value in bytes for transport. * aerospike.compression_threshold = 0; * // Max size of the synchronous connection pool for each server node * aerospike.max_threads = 300; * // Number of threads stored in underlying thread pool that is used in * // batch/scan/query commands. In ZTS builds, this is always 0. * aerospike.thread_pool_size = 16; * // When turning on the optional logging in the client, this is the path to the log file. * aerospike.log_path = NULL; * aerospike.log_level = NULL; * aerospike.nesting_depth = 3; * * // session handler * session.save_handler = aerospike; // to use the Aerospike session handler * session.gc_maxlifetime = 1440; // the TTL of the record used to store the session in seconds * session.save_path = NULL; // should follow the format ns|set|addr:port[,addr:port[,...]]. Ex: "test|sess|127.0.0.1:3000". The host info of just one cluster node is necessary * ``` * @author Robert Marks */ class Aerospike { // Lifecycle and Connection Methods /** * Construct an Aerospike client object, and connect to the cluster defined * in $config. * * Aerospike::isConnected() can be used to test whether the connection has * succeeded. If a config or connection error has occured, Aerospike::error() * and Aerospike::errorno() can be used to inspect it. * * ```php * $config = [ * "hosts" => [ * ["addr" => "localhost", "port" => 3000] * ], * "shm" => [] * ]; * // Set a default policy for write and read operations * $writeOpts = [Aerospike::OPT_POLICY_KEY => Aerospike::POLICY_KEY_SEND]; * $readOpts = [Aerospike::OPT_TOTAL_TIMEOUT => 150]; * $opts = [Aerospike::OPT_WRITE_DEFAULT_POL => $writeOpts, Aerospike::OPT_READ_DEFAULT_POL => $readOpts]; * $client = new Aerospike($config, true, $opts); * if (!$client->isConnected()) { * echo "Aerospike failed to connect[{$client->errorno()}]: {$client->error()}\n"; * exit(1); * } * ``` * @see Aerospike php.ini config parameters * @link https://github.com/aerospike/aerospike-client-php/blob/master/doc/README.md#configuration-in-a-web-server-context Configuration in a Web Server Context * @param array $config holds cluster connection and client config information * * _hosts_ a **required** array of host pairs. One node or more (for failover) * may be defined. Once a connection is established to the * "seed" node, the client will retrieve the full list of nodes in * the cluster, and manage its connections to them. * * _addr_ hostname or IP of the node * * _port_ the port of the node * * _user_ **required** for the Enterprise Edition * * _pass_ **required** for the Enterprise Edition * * _shm_ optional. Shared-memory cluster tending is enabled if an array * (even an empty one) is provided. Disabled by default. * * _shm\_key_ explicitly sets the shm key for the cluster. It is * otherwise implicitly evaluated per unique hostname, and can be * inspected with shmKey(). (default: 0xA8000000) * * _shm\_max\_nodes_ maximum number of nodes allowed. Pad so new nodes * can be added without configuration changes (default: 16) * * _shm\_max\_namespaces_ maximum number of namespaces allowed (default: 8) * * _shm\_takeover\_threshold\_sec_ take over tending if the cluster * hasn't been checked for this many seconds (default: 30) * * _max\_threads_ (default: 300) * * _thread\_pool\_size_ should be at least the number of nodes in the cluster (default: 16) In ZTS builds this is set to 0 * * _compression\_threshold_ client will compress records larger than this value for transport (default: 0) * * _tender\_interval_ polling interval in milliseconds for cluster tender (default: 1000) * * _cluster\_name_ if specified, only server nodes matching this name will be used when determining the cluster * * _rack\_aware_ Boolean: Track server rack data. This field is useful when directing read commands to * the server node that contains the key and exists on the same rack as the client. * This serves to lower cloud provider costs when nodes are distributed across different * racks/data centers. * POLICY_REPLICA_PREFER_RACK must be set as the replica policy for reads and _rack\_id_ must be set toenable this functionality. * (Default: false) * * _rack\_id_ Integer. Rack where this client instance resides. * * _rack\_aware_, POLICY_REPLICA_PREFER_RACK and server rack configuration must also be * set to enable this functionality. * * Default: 0 * * Aerospike::OPT_TLS_CONFIG an array of TLS setup parameters whose keys include * * * Aerospike::OPT_TLS_ENABLE boolean Whether or not to enable TLS. * * * Aerospike::OPT_OPT_TLS_CAFILE * * * Aerospike::OPT_TLS_CAPATH * * * Aerospike::OPT_TLS_PROTOCOLS * * * Aerospike::OPT_TLS_CIPHER_SUITE * * * Aerospike::OPT_TLS_CRL_CHECK * * * Aerospike::OPT_TLS_CRL_CHECK_ALL * * * Aerospike::OPT_TLS_CERT_BLACKLIST * * * Aerospike::OPT_TLS_LOG_SESSION_INFO * * * Aerospike::OPT_TLS_KEYFILE * * * Aerospike::OPT_TLS_CERTFILE * @param bool $persistent_connection In a multiprocess context, such as a * web server, the client should be configured to use * persistent connections. This allows for reduced overhead, * saving on discovery of the cluster topology, fetching its partition * map, and on opening connections to the nodes. * @param array $options An optional client config array whose keys include * * Aerospike::OPT_CONNECT_TIMEOUT * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_EXISTS * * Aerospike::OPT_SERIALIZER * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_REPLICA * * Aerospike::OPT_POLICY_READ_MODE_AP * * Aerospike::OPT_POLICY_READ_MODE_SC * * Aerospike::OPT_READ_DEFAULT_POL An array of default policies for read operations. * * Aerospike::OPT_WRITE_DEFAULT_POL An array of default policies for write operations. * * AEROSPIKE::OPT_REMOVE_DEFAULT_POL An array of default policies for remove operations. * * Aerospike::OPT_BATCH_DEFAULT_POL An array of default policies for batch operations. * * Aerospike::OPT_OPERATE_DEFAULT_POL An array of default policies for operate operations. * * Aerospike::OPT_QUERY_DEFAULT_POL An array of default policies for query operations. * * Aerospike::OPT_SCAN_DEFAULT_POL An array of default policies for scan operations. * * Aerospike::OPT_APPLY_DEFAULT_POL An array of default policies for apply operations. * @see Aerospike::OPT_CONNECT_TIMEOUT Aerospike::OPT_CONNECT_TIMEOUT options * @see Aerospike::OPT_READ_TIMEOUT Aerospike::OPT_READ_TIMEOUT options * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_EXISTS Aerospike::OPT_POLICY_EXISTS options * @see Aerospike::OPT_SERIALIZER Aerospike::OPT_SERIALIZER options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_POLICY_REPLICA Aerospike::OPT_POLICY_REPLICA options * @see Aerospike::OPT_POLICY_READ_MODE_AP Aerospike::OPT_POLICY_READ_MODE_AP options * @see Aerospike::OPT_POLICY_READ_MODE_SC Aerospike::OPT_POLICY_READ_MODE_SC options * @see Aerospike::isConnected() isConnected() * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() */ public function __construct($config, $persistent_connection = true, array $options = []) {} /** * Disconnect from the Aerospike cluster and clean up resources. * * No need to ever call this method explicilty. * @return void */ public function __destruct() {} /** * Test whether the client is connected to the cluster. * * If a connection error has occured, Aerospike::error() and Aerospike::errorno() * can be used to inspect it. * ```php * if (!$client->isConnected()) { * echo "Aerospike failed to connect[{$client->errorno()}]: {$client->error()}\n"; * exit(1); * } * ``` * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return bool */ public function isConnected() {} /** * Disconnect the client from all the cluster nodes. * * This method should be explicitly called when using non-persistent connections. * @see Aerospike::isConnected() * @see Aerospike::reconnect() * @return void */ public function close() {} /** * Reconnect the client to the cluster nodes. * * Aerospike::isConnected() can be used to test whether the re-connection * succeded. If a connection error occured Aerospike::error() and * Aerospike::errorno() can be used to inspect it. * ```php * $client = new Aerospike($config, false); * $client->close(); * $client->reconnect(); * if (!$client->isConnected()) { * echo "Aerospike failed to connect[{$client->errorno()}]: {$client->error()}\n"; * exit(1); * } * ``` * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return void */ public function reconnect() {} /** * Expose the shared memory key used by shared-memory cluster tending * * If shm cluster tending is enabled, Aerospike::shmKey will return the * value of the shm key being used by the client. If it was set explicitly * under the client's shm config parameter, or through the global * `aerospike.shm.key` we expect to see that value. Otherwise the implicit * value generated by the client will be returned * @return int|null null if not enabled */ public function shmKey() {} /** * Return the error message associated with the last operation. * * If the operation was successful the return value should be an empty string. * ```php * $client = new Aerospike($config, false); * if (!$client->isConnected()) { * echo "{$client->error()} [{$client->errorno()}]"; * exit(1); * } * ``` * On connection error would show: * ``` * Unable to connect to server [-1] * ``` * @see Aerospike::OK Error Codes * @return string */ public function error() {} /** * Return the error code associated with the last operation. * If the operation was successful the return value should be 0 (Aerospike::OK) * @see Aerospike::OK Error Codes * @return int */ public function errorno() {} // Key-Value Methods. /** * Return an array that represents the record's key. * * This value can be passed as the $key arguement required by other * key-value methods. * * In Aerospike, a record is identified by the tuple (namespace, set, * primary key), or by the digest which results from hashing this tuple * through RIPEMD-160. * * ** Initializing a key ** * * ```php * $key = $client->initKey("test", "users", 1234); * var_dump($key); * ``` * * ```bash *array(3) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["key"]=> * int(1234) *} * ``` * * ** Setting a digest ** * * ```php * $base64_encoded_digest = '7EV9CpdMSNVoWn76A9E33Iu95+M='; * $digest = base64_decode($base64_encoded_digest); * $key = $client->initKey("test", "users", $digest, true); * var_dump($key); * ``` * * ```bash *array(3) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["digest"]=> * string(20) "?E} *?LH?hZ~??7Ü‹???" *} * ``` * * @link https://github.com/aerospike/aerospike-client-php/blob/master/doc/README.md#configuration-in-a-web-server-context Configuration in a Web Server Context * @param string $ns the namespace * @param string $set the set within the given namespace * @param int|string $pk The primary key in the application, or the RIPEMD-160 digest of the (namespce, set, primary-key) tuple * @param bool $is_digest True if the *$pk* argument is a digest * @return array * @see Aerospike::getKeyDigest() getKeyDigest() */ public function initKey($ns, $set, $pk, $is_digest = false) {} /** * Return the digest of hashing the (namespace, set, primary-key) tuple * with RIPEMD-160. * * The digest uniquely identifies the record in the cluster, and is used to * calculate a partition ID. Using the partition ID, the client can identify * the node holding the record's master partition or replica partition(s) by * looking it up against the cluster's partition map. * * ```php * $digest = $client->getKeyDigest("test", "users", 1); * $key = $client->initKey("test", "users", $digest, true); * var_dump($digest, $key); * ``` * * ```bash * string(20) "9!?@%??;???Wp?'??Ag" * array(3) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["digest"]=> * string(20) "9!?@%??;???Wp?'??Ag" * } * ``` * * @link https://github.com/aerospike/aerospike-client-php/blob/master/doc/README.md#configuration-in-a-web-server-context Configuration in a Web Server Context * @param string $ns the namespace * @param string $set the set within the given namespace * @param int|string $pk The primary key in the application * @return string * @see Aerospike::initKey() initKey() */ public function getKeyDigest($ns, $set, $pk) {} /** * Write a record identified by the $key with $bins, an array of bin-name => bin-value pairs. * * By default Aerospike::put() behaves in a set-and-replace mode, similar to * how new keys are added to an array, or the value of existing ones is overwritten. * This behavior can be modified using the *$options* parameter. * * **Note:** a binary-string which includes a null-byte will get truncated * at the position of the **\0** character if it is not wrapped. For more * information and the workaround see 'Handling Unsupported Types'. * * **Example #1 Aerospike::put() default behavior example** * ```php * $key = $client->initKey("test", "users", 1234); * $bins = ["email" => "hey@example.com", "name" => "Hey There"]; * // will ensure a record exists at the given key with the specified bins * $status = $client->put($key, $bins); * if ($status == Aerospike::OK) { * echo "Record written.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * * // Updating the record * $bins = ["name" => "You There", "age" => 33]; * // will update the name bin, and create a new 'age' bin * $status = $client->put($key, $bins); * if ($status == Aerospike::OK) { * echo "Record updated.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * Record written. * Record updated. * ``` * * **Example #2 Fail unless the put explicitly creates a new record** * ```php * * // This time we expect an error, due to the record already existing (assuming we * // ran Example #1) * $status = $client->put($key, $bins, 0, [Aerospike::OPT_POLICY_EXISTS => Aerospike::POLICY_EXISTS_CREATE]); * * if ($status == Aerospike::OK) { * echo "Record written.\n"; * } elseif ($status == Aerospike::ERR_RECORD_EXISTS) { * echo "The Aerospike server already has a record with the given key.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * The Aerospike cluster already has a record with the given key. * ``` * * **Example #3 Fail if the record has been written since it was last read * (CAS)** * ```php * // Get the record metadata and note its generation * $client->exists($key, $metadata); * $gen = $metadata['generation']; * $gen_policy = [Aerospike::POLICY_GEN_EQ, $gen]; * $res = $client->put($key, $bins, 0, [Aerospike::OPT_POLICY_GEN => $gen_policy]); * * if ($res == Aerospike::OK) { * echo "Record written.\n"; * } elseif ($res == Aerospike::ERR_RECORD_GENERATION) { * echo "The record has been written since we last read it.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ?> * ``` * ``` * The record has been written since we last read it. * ``` * * **Example #4 Handling binary strings** * ```php * $str = 'Glagnar\'s Human Rinds, "It\'s a bunch\'a munch\'a crunch\'a human!'; * $deflated = new \Aerospike\Bytes(gzdeflate($str)); * $wrapped = new \Aerospike\Bytes("trunc\0ated"); * * $key = $client->initKey('test', 'demo', 'wrapped-bytes'); * $status = $client->put($key, ['unwrapped'=>"trunc\0ated", 'wrapped'=> $wrapped, 'deflated' => $deflated]); * if ($status !== Aerospike::OK) { * die($client->error()); * } * $client->get($key, $record); * $wrapped = \Aerospike\Bytes::unwrap($record['bins']['wrapped']); * $deflated = $record['bins']['deflated']; * $inflated = gzinflate($deflated->s); * echo "$inflated\n"; * echo "wrapped binary-string: "; * var_dump($wrapped); * $unwrapped = $record['bins']['unwrapped']; * echo "The binary-string that was given to put() without a wrapper: $unwrapped\n"; * ``` * ``` * Glagnar's Human Rinds, "It's a bunch'a munch'a crunch'a human! * wrapped binary-string: string(10) "truncated" * The binary-string that was given to put() without a wrapper: trunc * ``` * @link https://www.aerospike.com/docs/architecture/data-model.html Aerospike Data Model * @link https://www.aerospike.com/docs/guide/kvs.html Key-Value Store * @link https://github.com/aerospike/aerospike-client-php/blob/master/doc/README.md#handling-unsupported-types Handling Unsupported Types * @link https://www.aerospike.com/docs/client/c/usage/kvs/write.html#change-record-time-to-live-ttl Time-to-live * @link https://www.aerospike.com/docs/guide/glossary.html Glossary * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param array $bins The array of bin names and values to write. **Bin names cannot be longer than 14 characters.** Binary data containing the null byte (**\0**) may get truncated. See 'Handling Unsupported Types' for more details and a workaround * @param int $ttl The record's time-to-live in seconds * @param array $options an optional array of write policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_SERIALIZER * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_EXISTS * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::COMPRESSION_THRESHOLD * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_SERIALIZER Aerospike::OPT_SERIALIZER options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_EXISTS Aerospike::OPT_POLICY_EXISTS options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::COMPRESSION_THRESHOLD * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function put(array $key, array $bins, $ttl = 0, array $options = []) {} /** * Read a record with a given key, and store it in $record * * The bins returned in *$record* can be filtered by passing a *$select* * array of bin names. Non-existent bins will appear in the *$record* with a `NULL` value. * * **Example #1 Aerospike::get() default behavior example** * ```php * $key = $client->initKey("test", "users", 1234); * $status = $client->get($key, $record); * if ($status == Aerospike::OK) { * var_dump($record); * } elseif ($status == Aerospike::ERR_RECORD_NOT_FOUND) { * echo "A user with key ". $key['key']. " does not exist in the database\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * array(3) { * ["key"]=> * array(4) { * ["digest"]=> * string(40) "436a3b9fcafb96d12844ab1377c0ff0d7a0b70cc" * ["namespace"]=> * NULL * ["set"]=> * NULL * ["key"]=> * NULL * } * ["metadata"]=> * array(2) { * ["generation"]=> * int(3) * ["ttl"]=> * int(12345) * } * ["bins"]=> * array(3) { * ["email"]=> * string(9) "hey@example.com" * ["name"]=> * string(9) "You There" * ["age"]=> * int(33) * } * } * ``` * **Example #2 get the record with filtered bins** * ```php * // assuming this follows Example #1, getting a filtered record * $filter = ["email", "manager"]; * unset($record); * $status = $client->get($key, $record, $filter); * if ($status == Aerospike::OK) { * var_dump($record); * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * array(3) { * ["key"]=> * array(4) { * ["digest"]=> * string(40) "436a3b9fcafb96d12844ab1377c0ff0d7a0b70cc" * ["namespace"]=> * NULL * ["set"]=> * NULL * ["key"]=> * NULL * } * ["metadata"]=> * array(2) { * ["generation"]=> * int(3) * ["ttl"]=> * int(12344) * } * ["bins"]=> * array(2) { * ["email"]=> * string(15) "hey@example.com" * ["manager"]=> * NULL * } * } * ``` * @link https://www.aerospike.com/docs/architecture/data-model.html Aerospike Data Model * @link https://www.aerospike.com/docs/guide/kvs.html Key-Value Store * @link https://www.aerospike.com/docs/guide/glossary.html Glossary * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param array &$record a reference to a variable which will contain the retrieved record of `['key', metadata', 'bins]` with the structure: * ``` * Array: * key => Array * ns => namespace * set => set name * key => primary-key, present if written with POLICY_KEY_SEND * digest => the record's RIPEMD-160 digest, always present * metadata => Array * ttl => time in seconds until the record expires * generation => the number of times the record has been written * bins => Array of bin-name => bin-value pairs * ``` * @param null|array $select only these bins out of the record (optional) * @param array $options an optional array of read policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_DESERIALIZE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * * Aerospike::OPT_POLICY_REPLICA * * Aerospike::OPT_POLICY_READ_MODE_AP * * Aerospike::OPT_POLICY_READ_MODE_SC * @see Aerospike::OPT_READ_TIMEOUT Aerospike::OPT_READ_TIMEOUT options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_DESERIALIZE Aerospike::OPT_DESERIALIZE option * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OPT_POLICY_REPLICA Aerospike::OPT_POLICY_REPLICA options * @see Aerospike::OPT_POLICY_READ_MODE_AP Aerospike::OPT_POLICY_READ_MODE_AP options * @see Aerospike::OPT_POLICY_READ_MODE_SC Aerospike::OPT_POLICY_READ_MODE_SC options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function get(array $key, &$record, $select = null, array $options = []) {} /** * Get the metadata of a record with a given key, and store it in $metadata * * ```php * $key = $client->initKey("test", "users", 1234); * $status = $client->exists($key, $metadata); * if ($status == Aerospike::OK) { * var_dump($metadata); * } elseif ($status == Aerospike::ERR_RECORD_NOT_FOUND) { * echo "A user with key ". $key['key']. " does not exist in the database\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * array(2) { * ["generation"]=> * int(4) * ["ttl"]=> * int(1337) * } * ``` * **or** * ``` * A user with key 1234 does not exist in the database. * ``` * @link https://www.aerospike.com/docs/guide/glossary.html Glossary * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param array &$metadata a reference to a variable which will be filled with an array of `['ttl', 'generation']` values * @param array $options an optional array of read policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_DESERIALIZE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_REPLICA * * Aerospike::OPT_POLICY_READ_MODE_AP * * Aerospike::OPT_POLICY_READ_MODE_SC * @see Aerospike::OPT_READ_TIMEOUT Aerospike::OPT_READ_TIMEOUT options * @see Aerospike::OPT_DESERIALIZE Aerospike::OPT_DESERIALIZE option * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_REPLICA Aerospike::OPT_POLICY_REPLICA options * @see Aerospike::OPT_POLICY_READ_MODE_AP Aerospike::OPT_POLICY_READ_MODE_AP options * @see Aerospike::OPT_POLICY_READ_MODE_SC Aerospike::OPT_POLICY_READ_MODE_SC options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function exists(array $key, &$metadata, array $options = []) {} /** * Touch the record identified by the $key, resetting its time-to-live. * * ```php * $key = $client->initKey("test", "users", 1234); * $status = $client->touch($key, 120); * if ($status == Aerospike::OK) { * echo "Added 120 seconds to the record's expiration.\n" * } elseif ($status == Aerospike::ERR_RECORD_NOT_FOUND) { * echo "A user with key ". $key['key']. " does not exist in the database\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * Added 120 seconds to the record's expiration. * ``` * **or** * ``` * A user with key 1234 does not exist in the database. * ``` * @link https://www.aerospike.com/docs/client/c/usage/kvs/write.html#change-record-time-to-live-ttl Time-to-live * @link https://www.aerospike.com/docs/guide/FAQ.html FAQ * @link https://discuss.aerospike.com/t/records-ttl-and-evictions/737 Record TTL and Evictions * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param int $ttl The record's time-to-live in seconds * @param array $options an optional array of write policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_DESERIALIZE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_DESERIALIZE Aerospike::OPT_DESERIALIZE option * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function touch(array $key, $ttl = 0, array $options = []) {} /** * Remove the record identified by the $key. * * ```php * $key = $client->initKey("test", "users", 1234); * $status = $client->remove($key); * if ($status == Aerospike::OK) { * echo "Record removed.\n"; * } elseif ($status == Aerospike::ERR_RECORD_NOT_FOUND) { * echo "A user with key ". $key['key']. " does not exist in the database\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * Record removed. * ``` * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param array $options an optional array of write policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function remove(array $key, array $options = []) {} /** * Remove $bins from the record identified by the $key. * * ```php * $key = ["ns" => "test", "set" => "users", "key" => 1234]; * $options = array(Aerospike::OPT_TTL => 3600); * $status = $client->removeBin($key, ["age"], $options); * if ($status == Aerospike::OK) { * echo "Removed bin 'age' from the record.\n"; * } elseif ($status == Aerospike::ERR_RECORD_NOT_FOUND) { * echo "The database has no record with the given key.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param array $bins A list of bin names to remove * @param array $options an optional array of write policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::COMPRESSION_THRESHOLD * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::COMPRESSION_THRESHOLD * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function removeBin(array $key, array $bins, array $options = []) {} /** * Remove all the records from a namespace or set * * Remove records in a specified namespace/set efficiently. This method is * many orders of magnitude faster than deleting records one at a time. * **Note:** works with Aerospike Server versions >= 3.12 * See {@link https://www.aerospike.com/docs/reference/info#truncate Truncate command information} * * This asynchronous server call may return before the truncation is complete. * The user can still write new records after the server returns because new * records will have last update times greater than the truncate cutoff * (set at the time of truncate call). * * The truncate command does not durably delete records in the Community Edition. * The Enterprise Edition provides durability through the truncate command. * * ```php * $secondsInDay = 24 * 60 * 60; * * // Multiply by 10 ^ 9 to get nanoseconds * $yesterday = 1000000000 * (time() - $secondsInDay); * * // Remove all records in test/truncateSet updated before 24 hours ago * $status = $client->truncate("test", "demoSet", $yesterday); * * // Truncate all records in test, regardless of update time * $status = $client->truncate("test", null, 0); * ``` * @version 3.12 Requires server >= 3.12 * @param string $ns the namespace * @param string $set the set within the given namespace * @param int $nanos cutoff threshold indicating that records * last updated before the threshold will be removed. Units are in * nanoseconds since unix epoch (1970-01-01 00:00:00). A value of 0 * indicates that all records in the set should be truncated * regardless of update time. The value must not be in the future. * @param array $options an optional array of write policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function truncate($ns, $set, $nanos, array $options = []) {} /** * Increment the value of $bin in the record identified by the $key by an * $offset. * * ```php * $key = $client->initKey("test", "users", 1234); * $options = [Aerospike::OPT_TTL => 7200]; * $status = $client->increment($key, 'pto', -4, $options); * if ($status == Aerospike::OK) { * echo "Decremented four vacation days from the user's PTO balance.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin The name of the bin to increment * @param int|float $offset The value by which to increment the bin * @param array $options an optional array of write policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function increment(array $key, $bin, $offset, array $options = []) {} /** * Append a string $value to the one already in $bin, in the record identified by the $key. * * ```php * $key = $client->initKey("test", "users", 1234); * $options = [Aerospike::OPT_TTL => 3600]; * $status = $client->append($key, 'name', ' Ph.D.', $options); * if ($status == Aerospike::OK) { * echo "Added the Ph.D. suffix to the user.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin The name of the bin * @param string $value The string value to append to the bin * @param array $options an optional array of write policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_DESERIALIZE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_DESERIALIZE Aerospike::OPT_DESERIALIZE option * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function append(array $key, $bin, $value, array $options = []) {} /** * Prepend a string $value to the one already in $bin, in the record identified by the $key. * * ```php * $key = $client->initKey("test", "users", 1234); * $options = [Aerospike::OPT_TTL => 3600]; * $status = $client->prepend($key, 'name', '*', $options); * if ($status == Aerospike::OK) { * echo "Starred the user.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin The name of the bin * @param string $value The string value to prepend to the bin * @param array $options an optional array of write policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_DESERIALIZE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_DESERIALIZE Aerospike::OPT_DESERIALIZE option * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function prepend(array $key, $bin, $value, array $options = []) {} /** * Perform multiple bin operations on a record with a given key, with write operations happening before read ones. * * Non-existent bins being read will have a `NULL` value. * * Currently a call to operate() can include only one write operation per-bin. * For example, you cannot both append and prepend to the same bin, in the same call. * * Like other bin operations, operate() only works on existing records (i.e. ones that were previously created with a put()). * * **Example #1 Combining several write operations into one multi-op call** * * ``` * [ * ["op" => Aerospike::OPERATOR_APPEND, "bin" => "name", "val" => " Ph.D."], * ["op" => Aerospike::OPERATOR_INCR, "bin" => "age", "val" => 1], * ["op" => Aerospike::OPERATOR_READ, "bin" => "age"] * ] * ``` * * ```php * $config = ["hosts" => [["addr"=>"localhost", "port"=>3000]], "shm"=>[]]; * $client = new Aerospike($config, true); * if (!$client->isConnected()) { * echo "Aerospike failed to connect[{$client->errorno()}]: {$client->error()}\n"; * exit(1); * } * * $key = $client->initKey("test", "users", 1234); * $operations = [ * ["op" => Aerospike::OPERATOR_APPEND, "bin" => "name", "val" => " Ph.D."], * ["op" => Aerospike::OPERATOR_INCR, "bin" => "age", "val" => 1], * ["op" => Aerospike::OPERATOR_READ, "bin" => "age"], * ]; * $options = [Aerospike::OPT_TTL => 600]; * $status = $client->operate($key, $operations, $returned, $options); * if ($status == Aerospike::OK) { * var_dump($returned); * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * array(1) { * ["age"]=> * int(34) * } * ``` * * **Example #2 Implementing an LRU by reading a bin and touching a record in the same operation** * * ``` * [ * ["op" => Aerospike::OPERATOR_READ, "bin" => "age"], * ["op" => Aerospike::OPERATOR_TOUCH, "ttl" => 20] * ] * ``` * @link https://www.aerospike.com/docs/guide/kvs.html Key-Value Store * @link https://github.com/aerospike/aerospike-client-php/blob/master/doc/README.md#handling-unsupported-types Handling Unsupported Types * @link https://www.aerospike.com/docs/client/c/usage/kvs/write.html#change-record-time-to-live-ttl Time-to-live * @link https://www.aerospike.com/docs/guide/glossary.html Glossary * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param array $operations The array of of one or more per-bin operations conforming to the following structure: * ``` * Write Operation: * op => Aerospike::OPERATOR_WRITE * bin => bin name (cannot be longer than 14 characters) * val => the value to store in the bin * * Increment Operation: * op => Aerospike::OPERATOR_INCR * bin => bin name * val => the integer by which to increment the value in the bin * * Prepend Operation: * op => Aerospike::OPERATOR_PREPEND * bin => bin name * val => the string to prepend the string value in the bin * * Append Operation: * op => Aerospike::OPERATOR_APPEND * bin => bin name * val => the string to append the string value in the bin * * Read Operation: * op => Aerospike::OPERATOR_READ * bin => name of the bin we want to read after any write operations * * Touch Operation: reset the time-to-live of the record and increment its generation * (only combines with read operations) * op => Aerospike::OPERATOR_TOUCH * ttl => a positive integer value to set as time-to-live for the record * * Delete Operation: * op => Aerospike::OPERATOR_DELETE * * List Append Operation: * op => Aerospike::OP_LIST_APPEND, * bin => "events", * val => 1234 * * List Merge Operation: * op => Aerospike::OP_LIST_MERGE, * bin => "events", * val => [ 123, 456 ] * * List Insert Operation: * op => Aerospike::OP_LIST_INSERT, * bin => "events", * index => 2, * val => 1234 * * List Insert Items Operation: * op => Aerospike::OP_LIST_INSERT_ITEMS, * bin => "events", * index => 2, * val => [ 123, 456 ] * * List Pop Operation: * op => Aerospike::OP_LIST_POP, # returns a value * bin => "events", * index => 2 * * List Pop Range Operation: * op => Aerospike::OP_LIST_POP_RANGE, # returns a value * bin => "events", * index => 2, * val => 3 # remove 3 elements starting at index 2 * * List Remove Operation: * op => Aerospike::OP_LIST_REMOVE, * bin => "events", * index => 2 * * List Remove Range Operation: * op => Aerospike::OP_LIST_REMOVE_RANGE, * bin => "events", * index => 2, * val => 3 # remove 3 elements starting at index 2 * * List Clear Operation: * op => Aerospike::OP_LIST_CLEAR, * bin => "events" * * List Set Operation: * op => Aerospike::OP_LIST_SET, * bin => "events", * index => 2, * val => "latest event at index 2" # set this value at index 2 * * List Get Operation: * op => Aerospike::OP_LIST_GET, # returns a value * bin => "events", * index => 2 # similar to Aerospike::OPERATOR_READ but only returns the value * at index 2 of the list, not the whole bin * * List Get Range Operation: * op => Aerospike::OP_LIST_GET_RANGE, # returns a value * bin => "events", * index => 2, * val => 3 # get 3 elements starting at index 2 * * List Trim Operation: * op => Aerospike::OP_LIST_TRIM, * bin => "events", * index => 2, * val => 3 # remove all elements not in the range between index 2 and index 2 + 3 * * List Size Operation: * op => Aerospike::OP_LIST_SIZE, # returns a value * bin => "events" # gets the size of a list contained in the bin * * * Map operations * * Map Policies: * Many of the following operations require a map policy, the policy is an array * containing any of the keys AEROSPIKE::OPT_MAP_ORDER, AEROSPIKE::OPT_MAP_WRITE_MODE * * the value for AEROSPIKE::OPT_MAP_ORDER should be one of AEROSPIKE::AS_MAP_UNORDERED , AEROSPIKE::AS_MAP_KEY_ORDERED , AEROSPIKE::AS_MAP_KEY_VALUE_ORDERED * the default value is currently AEROSPIKE::AS_MAP_UNORDERED * * the value for AEROSPIKE::OPT_MAP_WRITE_MODE should be one of: AEROSPIKE::AS_MAP_UPDATE, AEROSPIKE::AS_MAP_UPDATE_ONLY , AEROSPIKE::AS_MAP_CREATE_ONLY * the default value is currently AEROSPIKE::AS_MAP_UPDATE * * the value for AEROSPIKE::OPT_MAP_WRITE_FLAGS should be one of: AEROSPIKE::AS_MAP_WRITE_DEFAULT, AEROSPIKE::AS_MAP_WRITE_CREATE_ONLY, AEROSPIKE::AS_MAP_WRITE_UPDATE_ONLY, AEROSPIKE::AS_MAP_WRITE_NO_FAIL, AEROSPIKE::AS_MAP_WRITE_PARTIAL * the default value is currently AEROSPIKE::AS_MAP_WRITE_DEFAULT * * Map return types: * many of the map operations require a return_type entry. * this specifies the format in which the response should be returned. The options are: * AEROSPIKE::AS_MAP_RETURN_NONE # Do not return a result. * AEROSPIKE::AS_MAP_RETURN_INDEX # Return key index order. * AEROSPIKE::AS_MAP_RETURN_REVERSE_INDEX # Return reverse key order. * AEROSPIKE::AS_MAP_RETURN_RANK # Return value order. * AEROSPIKE::AS_MAP_RETURN_REVERSE_RANK # Return reserve value order. * AEROSPIKE::AS_MAP_RETURN_COUNT # Return count of items selected. * AEROSPIKE::AS_MAP_RETURN_KEY # Return key for single key read and key list for range read. * AEROSPIKE::AS_MAP_RETURN_VALUE # Return value for single key read and value list for range read. * AEROSPIKE::AS_MAP_RETURN_KEY_VALUE # Return key/value items. Will be of the form ['key1', 'val1', 'key2', 'val2', 'key3', 'val3] * * Map policy Operation: * op => Aerospike::OP_MAP_SET_POLICY, * bin => "map", * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map clear operation: (Remove all items from a map) * op => AEROSPIKE::OP_MAP_CLEAR, * bin => "bin_name" * * * Map Size Operation: Return the number of items in a map * op => AEROSPIKE::OP_MAP_SIZE, * bin => "bin_name" * * Map Get by Key operation * op => AEROSPIKE::OP_MAP_GET_BY_KEY , * bin => "bin_name", * key => "my_key", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get By Key Range operation: * op => AEROSPIKE::OP_MAP_GET_BY_KEY_RANGE , * bin => "bin_name", * key => "aaa", * range_end => "bbb" * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get By Value operation: * op => AEROSPIKE::OP_MAP_GET_BY_VALUE , * bin => "bin_name", * value => "my_val" * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get by Value Range operation: * op => AEROSPIKE::OP_MAP_GET_BY_VALUE_RANGE , * bin => "bin_name", * value => "value_a", * range_end => "value_z", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get By Index operation * op => AEROSPIKE::OP_MAP_GET_BY_INDEX , * bin => "bin_name", * index => 2, * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get by Index Range operation * op => AEROSPIKE::OP_MAP_GET_BY_INDEX_RANGE, * bin => "bin_name", * index => 2, * count => 2, * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get By Rank operation * op => AEROSPIKE::OP_MAP_GET_BY_RANK , * bin => "bin_name", * rank => -1, # get the item with the largest value * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get by Rank Range operation * op => AEROSPIKE::OP_MAP_GET_BY_RANK_RANGE , * rank => -2 , * count => 2 , * bin => "bin_name", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Put operation * op => AEROSPIKE::OP_MAP_PUT , * bin => "bin_name", * key => "aero", * val => "spike", * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map Put Items operations * op => AEROSPIKE::OP_MAP_PUT_ITEMS , * bin => "bin_name", * val => [1, "a", 1.5], * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map Increment operation * op => AEROSPIKE::OP_MAP_INCREMENT , * bin => "bin_name", * val => 5, #increment the value by 5 * key => "key_to_increment", * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map Decrement operation * op => AEROSPIKE::OP_MAP_DECREMENT , * bin => "bin_name", * key => "key_to_decrement", * val => 5, #decrement by 5 * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map Remove by Key operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_KEY , * bin => "bin_name", * key => "key_to_remove", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Remove by Key list operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_KEY_LIST , * bin => "bin_name", * key => ["key1", 2, "key3"], * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by Key Range operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_KEY_RANGE , * bin => "bin", * key => "a", * range_end => "d", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by Value operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_VALUE , * bin => "bin_name", * val => 5, * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by value range operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_VALUE_RANGE , * bin => "bin_name", * val => "a", * range_end => "d" * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by value list operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_VALUE_LIST , * bin => "bin_name", * val => [1, 2, 3, 4], * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Remove by Index operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_INDEX , * index => 2, * bin => "bin_name", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Remove By Index Range operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_INDEX_RANGE , * bin => "bin_name", * index => 3 , * count => 3 , * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Remove by Rank operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_RANK , * rank => -1 , * bin => "bin_name", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by rank range * op => AEROSPIKE::OP_MAP_REMOVE_BY_RANK_RANGE, * bin => "bin_name", * rank => -1, * count => return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * * * ``` * * @param array &$returned a pass-by-reference array of bins retrieved by read operations. If multiple operations exist for a specific bin name, the last operation will be the one placed as the value * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_REPLICA * * Aerospike::OPT_POLICY_READ_MODE_AP * * Aerospike::OPT_POLICY_READ_MODE_SC * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_DESERIALIZE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_POLICY_REPLICA Aerospike::OPT_POLICY_REPLICA options * @see Aerospike::OPT_POLICY_READ_MODE_AP Aerospike::OPT_POLICY_READ_MODE_AP options * @see Aerospike::OPT_POLICY_READ_MODE_SC Aerospike::OPT_POLICY_READ_MODE_SC options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_DESERIALIZE Aerospike::OPT_DESERIALIZE option * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @see Aerospike::OPERATOR_WRITE Aerospike::OPERATOR_WRITE and other operators * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function operate(array $key, array $operations, &$returned, array $options = []) {} /** * Perform multiple bin operations on a record with a given key, with write operations happening before read ones. * The order of the resulting elements will correspond to the order of the operations in the parameters. * * Non-existent bins being read will have a `NULL` value. * * Currently a call to operateOrdered() can include only one write operation per-bin. * For example, you cannot both append and prepend to the same bin, in the same call. * * Like other bin operations, operateOrdered() only works on existing records (i.e. ones that were previously created with a put()). * * **Example #1 Combining several write operations into one multi-op call** * * ```php * $config = ["hosts" => [["addr"=>"localhost", "port"=>3000]], "shm"=>[]]; * $client = new Aerospike($config, true); * if (!$client->isConnected()) { * echo "Aerospike failed to connect[{$client->errorno()}]: {$client->error()}\n"; * exit(1); * } * * $key = $client->initKey("test", "demo", "pk458"); * $operations = [ * array("op" => Aerospike::OP_LIST_APPEND, "bin" => "age", "val"=>49), * array("op" => Aerospike::OP_LIST_GET, "bin" => "age", "index"=>0), * array("op" => Aerospike::OP_LIST_POP, "bin" => "age", "index"=>0) * ]; * $returned = "output value"; * $status = $client->operateOrdered($key, $operations, $returned); * * if ($status == Aerospike::OK) { * var_dump($returned); * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * * @link https://www.aerospike.com/docs/guide/kvs.html Key-Value Store * @link https://github.com/aerospike/aerospike-client-php/blob/master/doc/README.md#handling-unsupported-types Handling Unsupported Types * @link https://www.aerospike.com/docs/client/c/usage/kvs/write.html#change-record-time-to-live-ttl Time-to-live * @link https://www.aerospike.com/docs/guide/glossary.html Glossary * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param array $operations The array of of one or more per-bin operations conforming to the following structure: * ``` * Write Operation: * op => Aerospike::OPERATOR_WRITE * bin => bin name (cannot be longer than 14 characters) * val => the value to store in the bin * * Increment Operation: * op => Aerospike::OPERATOR_INCR * bin => bin name * val => the integer by which to increment the value in the bin * * Prepend Operation: * op => Aerospike::OPERATOR_PREPEND * bin => bin name * val => the string to prepend the string value in the bin * * Append Operation: * op => Aerospike::OPERATOR_APPEND * bin => bin name * val => the string to append the string value in the bin * * Read Operation: * op => Aerospike::OPERATOR_READ * bin => name of the bin we want to read after any write operations * * Touch Operation: reset the time-to-live of the record and increment its generation * (only combines with read operations) * op => Aerospike::OPERATOR_TOUCH * ttl => a positive integer value to set as time-to-live for the record * * Delete Operation: * op => Aerospike::OPERATOR_DELETE * * List Append Operation: * op => Aerospike::OP_LIST_APPEND, * bin => "events", * val => 1234 * * List Merge Operation: * op => Aerospike::OP_LIST_MERGE, * bin => "events", * val => [ 123, 456 ] * * List Insert Operation: * op => Aerospike::OP_LIST_INSERT, * bin => "events", * index => 2, * val => 1234 * * List Insert Items Operation: * op => Aerospike::OP_LIST_INSERT_ITEMS, * bin => "events", * index => 2, * val => [ 123, 456 ] * * List Pop Operation: * op => Aerospike::OP_LIST_POP, # returns a value * bin => "events", * index => 2 * * List Pop Range Operation: * op => Aerospike::OP_LIST_POP_RANGE, # returns a value * bin => "events", * index => 2, * val => 3 # remove 3 elements starting at index 2 * * List Remove Operation: * op => Aerospike::OP_LIST_REMOVE, * bin => "events", * index => 2 * * List Remove Range Operation: * op => Aerospike::OP_LIST_REMOVE_RANGE, * bin => "events", * index => 2, * val => 3 # remove 3 elements starting at index 2 * * List Clear Operation: * op => Aerospike::OP_LIST_CLEAR, * bin => "events" * * List Set Operation: * op => Aerospike::OP_LIST_SET, * bin => "events", * index => 2, * val => "latest event at index 2" # set this value at index 2 * * List Get Operation: * op => Aerospike::OP_LIST_GET, # returns a value * bin => "events", * index => 2 # similar to Aerospike::OPERATOR_READ but only returns the value * at index 2 of the list, not the whole bin * * List Get Range Operation: * op => Aerospike::OP_LIST_GET_RANGE, # returns a value * bin => "events", * index => 2, * val => 3 # get 3 elements starting at index 2 * * List Trim Operation: * op => Aerospike::OP_LIST_TRIM, * bin => "events", * index => 2, * val => 3 # remove all elements not in the range between index 2 and index 2 + 3 * * List Size Operation: * op => Aerospike::OP_LIST_SIZE, # returns a value * bin => "events" # gets the size of a list contained in the bin * * * Map operations * * Map Policies: * Many of the following operations require a map policy, the policy is an array * containing any of the keys AEROSPIKE::OPT_MAP_ORDER, AEROSPIKE::OPT_MAP_WRITE_MODE * * the value for AEROSPIKE::OPT_MAP_ORDER should be one of AEROSPIKE::AS_MAP_UNORDERED , AEROSPIKE::AS_MAP_KEY_ORDERED , AEROSPIKE::AS_MAP_KEY_VALUE_ORDERED * the default value is currently AEROSPIKE::AS_MAP_UNORDERED * * the value for AEROSPIKE::OPT_MAP_WRITE_MODE should be one of: AEROSPIKE::AS_MAP_UPDATE, AEROSPIKE::AS_MAP_UPDATE_ONLY , AEROSPIKE::AS_MAP_CREATE_ONLY * the default value is currently AEROSPIKE::AS_MAP_UPDATE * * the value for AEROSPIKE::OPT_MAP_WRITE_FLAGS should be one of: AEROSPIKE::AS_MAP_WRITE_DEFAULT, AEROSPIKE::AS_MAP_WRITE_CREATE_ONLY, AEROSPIKE::AS_MAP_WRITE_UPDATE_ONLY, AEROSPIKE::AS_MAP_WRITE_NO_FAIL, AEROSPIKE::AS_MAP_WRITE_PARTIAL * the default value is currently AEROSPIKE::AS_MAP_WRITE_DEFAULT * * Map return types: * many of the map operations require a return_type entry. * this specifies the format in which the response should be returned. The options are: * AEROSPIKE::AS_MAP_RETURN_NONE # Do not return a result. * AEROSPIKE::AS_MAP_RETURN_INDEX # Return key index order. * AEROSPIKE::AS_MAP_RETURN_REVERSE_INDEX # Return reverse key order. * AEROSPIKE::AS_MAP_RETURN_RANK # Return value order. * AEROSPIKE::AS_MAP_RETURN_REVERSE_RANK # Return reserve value order. * AEROSPIKE::AS_MAP_RETURN_COUNT # Return count of items selected. * AEROSPIKE::AS_MAP_RETURN_KEY # Return key for single key read and key list for range read. * AEROSPIKE::AS_MAP_RETURN_VALUE # Return value for single key read and value list for range read. * AEROSPIKE::AS_MAP_RETURN_KEY_VALUE # Return key/value items. Will be of the form ['key1', 'val1', 'key2', 'val2', 'key3', 'val3] * * Map policy Operation: * op => Aerospike::OP_MAP_SET_POLICY, * bin => "map", * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map clear operation: (Remove all items from a map) * op => AEROSPIKE::OP_MAP_CLEAR, * bin => "bin_name" * * * Map Size Operation: Return the number of items in a map * op => AEROSPIKE::OP_MAP_SIZE, * bin => "bin_name" * * Map Get by Key operation * op => AEROSPIKE::OP_MAP_GET_BY_KEY , * bin => "bin_name", * key => "my_key", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get By Key Range operation: * op => AEROSPIKE::OP_MAP_GET_BY_KEY_RANGE , * bin => "bin_name", * key => "aaa", * range_end => "bbb" * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get By Value operation: * op => AEROSPIKE::OP_MAP_GET_BY_VALUE , * bin => "bin_name", * value => "my_val" * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get by Value Range operation: * op => AEROSPIKE::OP_MAP_GET_BY_VALUE_RANGE , * bin => "bin_name", * value => "value_a", * range_end => "value_z", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get By Index operation * op => AEROSPIKE::OP_MAP_GET_BY_INDEX , * bin => "bin_name", * index => 2, * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get by Index Range operation * op => AEROSPIKE::OP_MAP_GET_BY_INDEX_RANGE, * bin => "bin_name", * index => 2, * count => 2, * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get By Rank operation * op => AEROSPIKE::OP_MAP_GET_BY_RANK , * bin => "bin_name", * rank => -1, # get the item with the largest value * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Get by Rank Range operation * op => AEROSPIKE::OP_MAP_GET_BY_RANK_RANGE , * rank => -2 , * count => 2 , * bin => "bin_name", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Put operation * op => AEROSPIKE::OP_MAP_PUT , * bin => "bin_name", * key => "aero", * val => "spike", * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map Put Items operations * op => AEROSPIKE::OP_MAP_PUT_ITEMS , * bin => "bin_name", * val => [1, "a", 1.5], * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map Increment operation * op => AEROSPIKE::OP_MAP_INCREMENT , * bin => "bin_name", * val => 5, #increment the value by 5 * key => "key_to_increment", * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map Decrement operation * op => AEROSPIKE::OP_MAP_DECREMENT , * bin => "bin_name", * key => "key_to_decrement", * val => 5, #decrement by 5 * map_policy => [ AEROSPIKE::OPT_MAP_ORDER => AEROSPIKE::AS_MAP_KEY_ORDERED] * * Map Remove by Key operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_KEY , * bin => "bin_name", * key => "key_to_remove", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Remove by Key list operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_KEY_LIST , * bin => "bin_name", * key => ["key1", 2, "key3"], * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by Key Range operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_KEY_RANGE , * bin => "bin", * key => "a", * range_end => "d", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by Value operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_VALUE , * bin => "bin_name", * val => 5, * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by value range operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_VALUE_RANGE , * bin => "bin_name", * val => "a", * range_end => "d" * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by value list operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_VALUE_LIST , * bin => "bin_name", * val => [1, 2, 3, 4], * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Remove by Index operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_INDEX , * index => 2, * bin => "bin_name", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Remove By Index Range operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_INDEX_RANGE , * bin => "bin_name", * index => 3 , * count => 3 , * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map Remove by Rank operation * op => AEROSPIKE::OP_MAP_REMOVE_BY_RANK , * rank => -1 , * bin => "bin_name", * return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * Map remove by rank range * op => AEROSPIKE::OP_MAP_REMOVE_BY_RANK_RANGE, * bin => "bin_name", * rank => -1, * count => return_type => AEROSPIKE::MAP_RETURN_KEY_VALUE * * * * ``` * * @param array &$returned a pass-by-reference array of bins retrieved by read operations. If multiple operations exist for a specific bin name, the last operation will be the one placed as the value * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_REPLICA * * Aerospike::OPT_POLICY_READ_MODE_AP * * Aerospike::OPT_POLICY_READ_MODE_SC * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_DESERIALIZE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_POLICY_REPLICA Aerospike::OPT_POLICY_REPLICA options * @see Aerospike::OPT_POLICY_READ_MODE_AP Aerospike::OPT_POLICY_READ_MODE_AP options * @see Aerospike::OPT_POLICY_READ_MODE_SC Aerospike::OPT_POLICY_READ_MODE_SC options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_DESERIALIZE Aerospike::OPT_DESERIALIZE option * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @see Aerospike::OPERATOR_WRITE Aerospike::OPERATOR_WRITE and other operators * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function operateOrdered(array $key, array $operations, &$returned, array $options = []) {} /** * Count the number of elements in a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int &$count pass-by-reference param * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_REPLICA * * Aerospike::OPT_POLICY_READ_MODE_AP * * Aerospike::OPT_POLICY_READ_MODE_SC * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_READ_TIMEOUT Aerospike::OPT_READ_TIMEOUT options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_REPLICA Aerospike::OPT_POLICY_REPLICA options * @see Aerospike::OPT_POLICY_READ_MODE_AP Aerospike::OPT_POLICY_READ_MODE_AP options * @see Aerospike::OPT_POLICY_READ_MODE_SC Aerospike::OPT_POLICY_READ_MODE_SC options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listSize(array $key, $bin, &$count, array $options = []) {} /** * Add a single value (of any type) to the end of a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param mixed $value * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listAppend(array $key, $bin, $value, array $options = []) {} /** * Add several items to the end of a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param array $items * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listMerge(array $key, $bin, array $items, array $options = []) {} /** * Insert a single element (of any type) at a specified index of a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param mixed $value * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listInsert(array $key, $bin, $index, $value, array $options = []) {} /** * Insert several elements at a specified index of a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param array $elements * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listInsertItems(array $key, $bin, $index, array $elements, array $options = []) {} /** * Remove and get back the element at a specified index of a list type bin * Index -1 is the last item in the list, -3 is the third from last, 0 is the first in the list. * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param mixed &$element pass-by-reference param * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listPop(array $key, $bin, $index, &$element, array $options = []) {} /** * Remove and get back several elements at a specified index range of a list type bin * Index -1 is the last item in the list, -3 is the third from last, 0 is the first in the list. * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param int $count * @param array &$elements pass-by-reference param. After the method call it will be an array holding the popped elements. * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listPopRange(array $key, $bin, $index, $count, &$elements, array $options = []) {} /** * Remove a list element at a specified index of a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listRemove(array $key, $bin, $index, array $options = []) {} /** * Remove several list elements at a specified index range of a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param int $count * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listRemoveRange(array $key, $bin, $index, $count, array $options = []) {} /** * Trim the list, removing all elements not in the specified index range of a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param int $count * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listTrim(array $key, $bin, $index, $count, array $options = []) {} /** * Remove all the elements from a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listClear(array $key, $bin, array $options = []) {} /** * Set an element at a specified index of a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param mixed $value * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_TTL * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_GEN * * Aerospike::OPT_POLICY_COMMIT_LEVEL * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_TTL Aerospike::OPT_TTL options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_GEN Aerospike::OPT_POLICY_GEN options * @see Aerospike::OPT_POLICY_COMMIT_LEVEL Aerospike::OPT_POLICY_COMMIT_LEVEL options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listSet(array $key, $bin, $index, $value, array $options = []) {} /** * Get an element from a specified index of a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param array &$element pass-by-reference param which will hold the returned element. * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_REPLICA * * Aerospike::OPT_POLICY_READ_MODE_AP * * Aerospike::OPT_POLICY_READ_MODE_SC * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_READ_TIMEOUT Aerospike::OPT_READ_TIMEOUT options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_REPLICA Aerospike::OPT_POLICY_REPLICA options * @see Aerospike::OPT_POLICY_READ_MODE_AP Aerospike::OPT_POLICY_READ_MODE_AP options * @see Aerospike::OPT_POLICY_READ_MODE_SC Aerospike::OPT_POLICY_READ_MODE_SC options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listGet(array $key, $bin, $index, array &$element, array $options = []) {} /** * Get several elements starting at a specified index from a list type bin * * @version 3.7 Requires server >= 3.7 * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $bin * @param int $index * @param int $count * @param array &$elements pass-by-reference param which will hold an array of returned elements from the specified list bin. * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_POLICY_REPLICA * * Aerospike::OPT_POLICY_READ_MODE_AP * * Aerospike::OPT_POLICY_READ_MODE_SC * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_READ_TIMEOUT Aerospike::OPT_READ_TIMEOUT options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_POLICY_REPLICA Aerospike::OPT_POLICY_REPLICA options * @see Aerospike::OPT_POLICY_READ_MODE_AP Aerospike::OPT_POLICY_READ_MODE_AP options * @see Aerospike::OPT_POLICY_READ_MODE_SC Aerospike::OPT_POLICY_READ_MODE_SC options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listGetRange(array $key, $bin, $index, $count, &$elements, array $options = []) {} // Batch Operation Methods /** * Read a batch of records from a list of given keys, and fill $records with the resulting indexed array * * Each record is an array consisting of *key*, *metadata* and *bins* (see: {@see Aerospike::get() get()}). * Non-existent records will have `NULL` for their *metadata* and *bins* fields. * The bins returned can be filtered by passing an array of bin names. * * **Note** that the protocol getMany() will use (batch-direct or batch-index) * is configurable through the config parameter `Aerospike::USE_BATCH_DIRECT` * or `php.ini` config parameter `aerospike.use_batch_direct`. * By default batch-index is used with servers that support it (version >= 3.6.0). * * **Example #1 Aerospike::getMany() default behavior example** * ```php * $config = ["hosts" => [["addr"=>"localhost", "port"=>3000]], "shm"=>[]]; * $client = new Aerospike($config, true); * if (!$client->isConnected()) { * echo "Aerospike failed to connect[{$client->errorno()}]: {$client->error()}\n"; * exit(1); * } * * $key1 = $client->initKey("test", "users", 1234); * $key2 = $client->initKey("test", "users", 1235); // this key does not exist * $key3 = $client->initKey("test", "users", 1236); * $keys = array($key1, $key2, $key3); * $status = $client->getMany($keys, $records); * if ($status == Aerospike::OK) { * var_dump($records); * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * array(3) { * [0]=> * array(3) { * ["key"]=> * array(4) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["key"]=> * int(1234) * ["digest"]=> * string(20) "M?v2Kp??? * * ?[??4?v * } * ["metadata"]=> * array(2) { * ["ttl"]=> * int(4294967295) * ["generation"]=> * int(1) * } * ["bins"]=> * array(3) { * ["email"]=> * string(15) "hey@example.com" * ["name"]=> * string(9) "You There" * ["age"]=> * int(33) * } * } * [1]=> * array(3) { * ["key"]=> * array(4) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["key"]=> * int(1235) * ["digest"]=> * string(20) "?C??[?vwS??ƨ?????" * } * ["metadata"]=> * NULL * ["bins"]=> * NULL * } * [2]=> * array(3) { * ["key"]=> * array(4) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["key"]=> * int(1236) * ["digest"]=> * string(20) "'?9? * ?????? * ? ?" * } * ["metadata"]=> * array(2) { * ["ttl"]=> * int(4294967295) * ["generation"]=> * int(1) * } * ["bins"]=> * array(3) { * ["email"]=> * string(19) "thisguy@example.com" * ["name"]=> * string(8) "This Guy" * ["age"]=> * int(42) * } * } * } * ``` * **Example #2 getMany records with filtered bins** * ```php * // assuming this follows Example #1 * * $filter = ["email"]; * $keys = [$key1, $key3]; * $status = $client->getMany($keys, $records, $filter); * if ($status == Aerospike::OK) { * var_dump($records); * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * array(2) { * [0]=> * array(3) { * ["key"]=> * array(4) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["key"]=> * int(1234) * ["digest"]=> * string(20) "M?v2Kp??? * * ?[??4?v * } * ["metadata"]=> * array(2) { * ["ttl"]=> * int(4294967295) * ["generation"]=> * int(4) * } * ["bins"]=> * array(1) { * ["email"]=> * string(15) "hey@example.com" * } * } * [1]=> * array(3) { * ["key"]=> * array(4) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["key"]=> * int(1236) * ["digest"]=> * string(20) "'?9? * ?????? * ? ?" * } * ["metadata"]=> * array(2) { * ["ttl"]=> * int(4294967295) * ["generation"]=> * int(4) * } * ["bins"]=> * array(1) { * ["email"]=> * string(19) "thisguy@example.com" * } * } * } * ``` * @param array $keys an array of initialized keys, each key an array with keys `['ns','set','key']` or `['ns','set','digest']` * @param array &$records a pass-by-reference variable which will hold an array of record values, each record an array of `['key', 'metadata', 'bins']` * @param array $select only these bins out of the record (optional) * @param array $options an optional array of read policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::USE_BATCH_DIRECT * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * * Aerospike::OPT_BATCH_CONCURRENT * * Aerospike::OPT_SEND_SET_NAME * * Aerospike::OPT_ALLOW_INLINE * @see Aerospike::USE_BATCH_DIRECT Aerospike::USE_BATCH_DIRECT options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @see Aerospike::get() get() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function getMany(array $keys, &$records, array $select = [], array $options = []) {} /** * Check if a batch of records exists in the database and fill $metdata with the results * * Checks for the existence a batch of given *keys* (see: {@see Aerospike::exists() exists()}), * and return an indexed array matching the order of the *keys*. * Non-existent records will have `NULL` for their *metadata*. * * **Note** that the protocol existsMany() will use (batch-direct or batch-index) * is configurable through the config parameter `Aerospike::USE_BATCH_DIRECT` * or `php.ini` config parameter `aerospike.use_batch_direct`. * By default batch-index is used with servers that support it (version >= 3.6.0). * * **Example #1 Aerospike::existsMany() default behavior example** * ```php * $config = ["hosts" => [["addr"=>"localhost", "port"=>3000]], "shm"=>[]]; * $client = new Aerospike($config, true); * if (!$client->isConnected()) { * echo "Aerospike failed to connect[{$client->errorno()}]: {$client->error()}\n"; * exit(1); * } * * $key1 = $client->initKey("test", "users", 1234); * $key2 = $client->initKey("test", "users", 1235); // this key does not exist * $key3 = $client->initKey("test", "users", 1236); * $keys = array($key1, $key2, $key3); * $status = $client->existsMany($keys, $metadata); * if ($status == Aerospike::OK) { * var_dump($records); * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * array(3) { * [0]=> * array(3) { * ["key"]=> * array(4) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["key"]=> * int(1234) * ["digest"]=> * string(20) "M?v2Kp??? * * ?[??4?v * } * ["metadata"]=> * array(2) { * ["ttl"]=> * int(4294967295) * ["generation"]=> * int(1) * } * } * [1]=> * array(3) { * ["key"]=> * array(4) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["key"]=> * int(1235) * ["digest"]=> * string(20) "?C??[?vwS??ƨ?????" * } * ["metadata"]=> * NULL * } * [2]=> * array(3) { * ["key"]=> * array(4) { * ["ns"]=> * string(4) "test" * ["set"]=> * string(5) "users" * ["key"]=> * int(1236) * ["digest"]=> * string(20) "'?9? * ?????? * ? ?" * } * ["metadata"]=> * array(2) { * ["ttl"]=> * int(4294967295) * ["generation"]=> * int(1) * } * } * } * ``` * @param array $keys an array of initialized keys, each key an array with keys `['ns','set','key']` or `['ns','set','digest']` * @param array &$metadata a pass-by-reference array of metadata values, each an array of `['key', 'metadata']` * @param array $options an optional array of read policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::USE_BATCH_DIRECT * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * * Aerospike::OPT_BATCH_CONCURRENT * * Aerospike::OPT_SEND_SET_NAME * * Aerospike::OPT_ALLOW_INLINE * @see Aerospike::USE_BATCH_DIRECT Aerospike::USE_BATCH_DIRECT options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::OK Aerospike::OK and error status codes * @see Aerospike::error() error() * @see Aerospike::errorno() errorno() * @see Aerospike::exists() exists() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function existsMany(array $keys, array &$metadata, array $options = []) {} // Scan and Query /** * Scan a namespace or set * * Scan a _ns.set_, and invoke a callback function *record_cb* on each * record streaming back from the cluster. * * Optionally select the bins to be returned. Non-existent bins in this list will appear in the * record with a NULL value. * * ```php * $options = [Aerospike::OPT_SCAN_PRIORITY => Aerospike::SCAN_PRIORITY_MEDIUM]; * $processed = 0; * $status = $client->scan('test', 'users', function ($record) use (&$processed) { * if (!is_null($record['bins']['email'])) echo $record['bins']['email']."\n"; * if ($processed++ > 19) return false; // halt the stream by returning a false * }, ['email'], $options); * * var_dump($status, $processed); * ``` * ``` * foo@example.com * : * bar@example.com * I think a sample of 20 records is enough * ``` * @link https://www.aerospike.com/docs/architecture/data-model.html Aerospike Data Model * @link https://www.aerospike.com/docs/guide/scan.html Scans * @link https://www.aerospike.com/docs/operations/manage/scans/ Managing Scans * @param string $ns the namespace * @param string $set the set within the given namespace * @param callable $record_cb A callback function invoked for each record streaming back from the cluster * @param array $select An array of bin names which are the subset to be returned * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_SOCKET_TIMEOUT maximum socket idle time in milliseconds (0 means do not apply a socket idle timeout) * * Aerospike::OPT_SCAN_PRIORITY * * Aerospike::OPT_SCAN_PERCENTAGE of the records in the set to return * * Aerospike::OPT_SCAN_CONCURRENTLY whether to run the scan in parallel * * Aerospike::OPT_SCAN_NOBINS whether to not retrieve bins for the records * * Aerospike::OPT_SCAN_RPS_LIMIT limit the scan to process OPT_SCAN_RPS_LIMIT per second. * * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function scan($ns, $set, callable $record_cb, array $select = [], array $options = []) {} /** * Query a secondary index on a namespace or set * * Query a _ns.set_ with a specified predicate, and invoke a callback function *record_cb* on each * record matched by the query and streaming back from the cluster. * * Optionally select the bins to be returned. Non-existent bins in this list will appear in the * record with a NULL value. * * ```php * $result = []; * $where = Aerospike::predicateBetween("age", 30, 39); * $status = $client->query("test", "users", $where, function ($record) use (&$result) { * $result[] = $record['bins']; * }); * if ($status !== Aerospike::OK) { * echo "An error occured while querying[{$client->errorno()}] {$client->error()}\n"; * } else { * echo "The query returned ".count($result)." records\n"; * } * ``` * ``` * foo@example.com * : * bar@example.com * I think a sample of 20 records is enough * ``` * @link https://www.aerospike.com/docs/architecture/data-model.html Aerospike Data Model * @link https://www.aerospike.com/docs/guide/query.html Query * @link https://www.aerospike.com/docs/operations/manage/queries/index.html Managing Queries * @param string $ns the namespace * @param string $set the set within the given namespace * @param array $where the predicate for the query, usually created by the * predicate helper methods. The arrays conform to one of the following: * ``` * Array: * bin => bin name * op => one of Aerospike::OP_EQ, Aerospike::OP_BETWEEN, Aerospike::OP_CONTAINS, Aerospike::OP_RANGE, etc * val => scalar integer/string for OP_EQ and OP_CONTAINS or [$min, $max] for OP_BETWEEN and OP_RANGE * * or an empty array() for no predicate * ``` * examples * ``` * ["bin"=>"name", "op"=>Aerospike::OP_EQ, "val"=>"foo"] * ["bin"=>"age", "op"=>Aerospike::OP_BETWEEN, "val"=>[35,50]] * ["bin"=>"movies", "op"=>Aerospike::OP_CONTAINS, "val"=>"12 Monkeys"] * ["bin"=>"movies", "op"=>Aerospike::OP_RANGE, "val"=>[10,1000]] * [] // no predicate * ``` * @param callable $record_cb A callback function invoked for each record streaming back from the cluster * @param array $select An array of bin names which are the subset to be returned * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * * Aerospike::OPT_QUERY_NOBINS * @see Aerospike::predicateEquals() * @see Aerospike::predicateBetween() * @see Aerospike::predicateContains() * @see Aerospike::predicateRange() * @see Aerospike::predicateGeoContainsGeoJSONPoint() * @see Aerospike::predicateGeoWithinGeoJSONRegion() * @see Aerospike::predicateGeoContainsPoint() * @see Aerospike::predicateGeoWithinRadius() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function query($ns, $set, array $where, callable $record_cb, array $select = [], array $options = []) {} /** * Helper method for creating an EQUALS predicate * @param string $bin name * @param int|string $val * @see Aerospike::query() * @see Aerospike::queryApply() * @see Aerospike::aggregate() * @return array expressing the predicate, to be used by query(), queryApply() or aggregate() * ``` * Associative Array: * bin => bin name * op => Aerospike::OP_EQ * val => scalar integer/string value * ``` */ public static function predicateEquals($bin, $val) {} /** * Helper method for creating a BETWEEN predicate * @param string $bin name * @param int $min * @param int $max * @see Aerospike::query() * @see Aerospike::queryApply() * @see Aerospike::aggregate() * @return array expressing the predicate, to be used by query(), queryApply() or aggregate() * ``` * Associative Array: * bin => bin name * op => Aerospike::OP_BETWEEN * val => [min, max] * ``` */ public static function predicateBetween($bin, $min, $max) {} /** * Helper method for creating an CONTAINS predicate * * Similar to predicateEquals(), predicateContains() looks for an exact * match of a value inside a complex type - a list containing the value * (if the index type is *INDEX_TYPE_LIST*), the value contained in the keys * of a map (if the index type is *INDEX_TYPE_MAPKEYS*), or a record with the * given value contained in the values of a map (if the index type was * *INDEX_TYPE_MAPVALUES*). * @param string $bin name * @param int $index_type one of Aerospike::INDEX_TYPE_* * @param int|string $val * @see Aerospike::query() * @see Aerospike::queryApply() * @see Aerospike::aggregate() * @return array expressing the predicate, to be used by query(), queryApply() or aggregate() * ``` * Associative Array: * bin => bin name * index_type => Aerospike::INDEX_TYPE_* * op => Aerospike::OP_CONTAINS * val => scalar integer/string value * ``` */ public static function predicateContains($bin, $index_type, $val) {} /** * Helper method for creating a RANGE predicate * * Similar to predicateBetween(), predicateRange() looks for records with a * range of values inside a complex type - a list containing the values * (if the index type is *INDEX_TYPE_LIST*), the values contained in the keys * of a map (if the index type is *INDEX_TYPE_MAPKEYS*), or a record with the * given values contained in the values of a map (if the index type was * *INDEX_TYPE_MAPVALUES*) * @param string $bin name * @param int $index_type one of Aerospike::INDEX_TYPE_* * @param int $min * @param int $max * @see Aerospike::query() * @see Aerospike::queryApply() * @see Aerospike::aggregate() * @return array expressing the predicate, to be used by query(), queryApply() or aggregate() * ``` * Associative Array: * bin => bin name * index_type => Aerospike::INDEX_TYPE_* * op => Aerospike::OP_BETWEEN * val => [min, max] * ``` */ public static function predicateRange($bin, $index_type, $min, $max) {} /** * Helper method for creating a GEOCONTAINS point predicate * @param string $bin name * @param string $point GeoJSON string describing a point * @see Aerospike::query() * @see Aerospike::queryApply() * @see Aerospike::aggregate() * @return array expressing the predicate, to be used by query(), queryApply() or aggregate() * ``` * Associative Array: * bin => bin name * op => Aerospike::OP_GEOCONTAINSPOINT * val => GeoJSON string * ``` */ public static function predicateGeoContainsGeoJSONPoint($bin, $point) {} /** * Helper method for creating a GEOCONTAINS point predicate * @param string $bin name * @param float $long longitude of the point * @param float $lat latitude of the point * @see Aerospike::query() * @see Aerospike::queryApply() * @see Aerospike::aggregate() * @return array expressing the predicate, to be used by query(), queryApply() or aggregate() * ``` * Associative Array: * bin => bin name * op => Aerospike::OP_GEOCONTAINSPOINT * val => GeoJSON string produced from $long and $lat * ``` */ public static function predicateGeoContainsPoint($bin, $long, $lat) {} /** * Helper method for creating a GEOWITHIN region predicate * @param string $bin name * @param string $region GeoJSON string describing the region (polygon) * @see Aerospike::query() * @see Aerospike::queryApply() * @see Aerospike::aggregate() * @return array expressing the predicate, to be used by query(), queryApply() or aggregate() * ``` * Associative Array: * bin => bin name * op => Aerospike::OP_GEOWITHINREGION * val => GeoJSON string * ``` */ public static function predicateGeoWithinGeoJSONRegion($bin, $region) {} /** * Helper method for creating a GEOWITHIN circle region predicate * @param string $bin name * @param float $long longitude of the point * @param float $lat latitude of the point * @param float $radiusMeter radius of the circle in meters * @see Aerospike::query() * @see Aerospike::queryApply() * @see Aerospike::aggregate() * @return array expressing the predicate, to be used by query(), queryApply() or aggregate() * ``` * Associative Array: * bin => bin name * op => Aerospike::OP_GEOWITHINREGION * val => GeoJSON string produced from $long, $lat and $radius * ``` */ public static function predicateGeoWithinRadius($bin, $long, $lat, $radiusMeter) {} /** * Get the status of a background job triggered by Aerospike::scanApply or Aerospike::queryApply * * ```php * // after a queryApply() where $job_id was set: * do { * time_nanosleep(0, 30000000); // pause 30ms * $status = $client->jobInfo($job_id, Aerospike::JOB_QUERY, $job_info); * var_dump($job_info); * } while($job_info['status'] != Aerospike::JOB_STATUS_COMPLETED); * ``` * * @param int $job_id The Job ID * @param int $job_type The type of the job, either Aerospike::JOB_QUERY, or Aerospike::JOB_SCAN * @param array &$info The status of the background job filled (by reference) as an array of * ``` * [ * 'progress_pct' => progress percentage for the job * 'records_read' => number of records read by the job * 'status' => one of Aerospike::STATUS_* * ] * ``` * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * @see Aerospike::scanApply() * @see Aerospike::queryApply() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function jobInfo($job_id, $job_type, array &$info, array $options = []) {} // UDF Methods /** * Register a UDF module with the cluster * * Note that modules containing stream UDFs need to also be copied to the * path described in `aerospike.udf.lua_user_path`, as the last reduce * iteration is run locally on the client (after reducing on all the nodes * of the cluster). * * Currently the only UDF language supported is Lua. * ```php * $status = $client->register('/path/to/my_udf.lua', 'my_udf.lua'); * if ($status == Aerospike::OK) { * echo "UDF module at $path is registered as my_udf on the Aerospike DB.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * @link https://www.aerospike.com/docs/udf/udf_guide.html UDF Development Guide * @param string $path the path to the Lua file on the client-side machine * @param string $module the name of the UDF module to register with the cluster * @param int $language * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OK Aerospike::OK and error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function register($path, $module, $language = Aerospike::UDF_TYPE_LUA, $options = []) {} /** * Remove a UDF module from the cluster * * ```php * $status = $client->deregister('my_udf'); * if ($status == Aerospike::OK) { * echo "UDF module my_udf was removed from the Aerospike DB.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * @param string $module the name of the UDF module registered with the cluster * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT * @see Aerospike::ERR_UDF_NOT_FOUND UDF error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function deregister($module, $options = []) {} /** * List the UDF modules registered with the cluster * * The modules array has the following structure: * ``` * Array of: * name => module name * type => Aerospike::UDF_TYPE_* * ``` * **Example** * ```php * $status = $client->listRegistered($modules); * if ($status == Aerospike::OK) { * var_dump($modules); * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * array(2) { * [0]=> * array(2) { * ["name"]=> * string(13) "my_record_udf" * ["type"]=> * int(0) * } * [1]=> * array(2) { * ["name"]=> * string(13) "my_stream_udf" * ["type"]=> * int(0) * } * } * ``` * @param array &$modules pass-by-reference param * @param int $language * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * @see Aerospike::OPT_READ_TIMEOUT Aerospike::OPT_READ_TIMEOUT * @see Aerospike::OK Aerospike::OK and error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function listRegistered(&$modules, $language = Aerospike::UDF_TYPE_LUA, $options = []) {} /** * Get the code for a UDF module registered with the cluster * * Populates _code_ with the content of the matching UDF _module_ that was * previously registered with the server. * * **Example** * ```php * $status = $client->getRegistered('my_udf', $code); * if ($status == Aerospike::OK) { * var_dump($code); * } elseif ($status == Aerospike::ERR_LUA_FILE_NOT_FOUND) { * echo "The UDF module my_udf was not found to be registered with the server.\n"; * } * ``` * ``` * string(351) "function startswith(rec, bin_name, prefix) * if not aerospike:exists(rec) then * return false * end * if not prefix then * return true * end * if not rec[bin_name] then * return false * end * local bin_val = rec[bin_name] * l = prefix:len() * if l > bin_val:len() then * return false * end * ret = bin_val:sub(1, l) == prefix * return ret * end * " * ``` * @param string $module the name of the UDF module registered with the cluster * @param string &$code pass-by-reference param * @param string $language * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * @see Aerospike::OPT_READ_TIMEOUT Aerospike::OPT_READ_TIMEOUT * @see Aerospike::ERR_LUA_FILE_NOT_FOUND UDF error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function getRegistered($module, &$code, $language = Aerospike::UDF_TYPE_LUA, $options = []) {} /** * Apply a UDF to a record * * Applies the UDF _module.function_ to a record with a given _key_. * Arguments can be passed to the UDF and any returned value optionally captured. * * Currently the only UDF language supported is Lua. * ```php * $key = ["ns" => "test", "set" => "users", "key" => "1234"]; * $status = $client->apply($key, 'my_udf', 'startswith', ['email', 'hey@'], $returned); * if ($status == Aerospike::OK) { * if ($returned) { * echo "The email of the user with key {$key['key']} starts with 'hey@'.\n"; * } else { * echo "The email of the user with key {$key['key']} does not start with 'hey@'.\n"; * } * } elseif ($status == Aerospike::ERR_UDF_NOT_FOUND) { * echo "The UDF module my_udf.lua was not registered with the Aerospike DB.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * ``` * The email of the user with key 1234 starts with 'hey@'. * ``` * @link https://www.aerospike.com/docs/udf/udf_guide.html UDF Development Guide * @link https://www.aerospike.com/docs/udf/developing_record_udfs.html Developing Record UDFs * @link https://www.aerospike.com/docs/udf/api_reference.html Lua UDF - API Reference * @param array $key The key identifying the record. An array with keys `['ns','set','key']` or `['ns','set','digest']` * @param string $module the name of the UDF module registered with the cluster * @param string $function the name of the UDF * @param array $args optional arguments for the UDF * @param mixed &$returned pass-by-reference param * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_POLICY_KEY * * Aerospike::OPT_SERIALIZER * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_POLICY_KEY Aerospike::OPT_POLICY_KEY options * @see Aerospike::OPT_SERIALIZER Aerospike::OPT_SERIALIZER options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::ERR_LUA UDF error status codes * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function apply(array $key, $module, $function, array $args = [], &$returned = null, $options = []) {} /** * Apply a UDF to each record in a scan * * Scan the *ns.set* and apply a UDF _module.function_ to each of its records. * Arguments can be passed to the UDF and any returned value optionally captured. * * Currently the only UDF language supported is Lua. * ```php * $status = $client->scanApply("test", "users", "my_udf", "mytransform", array(20), $job_id); * if ($status === Aerospike::OK) { * var_dump("Job ID is $job_id"); * } else if ($status === Aerospike::ERR_CLIENT) { * echo "An error occured while initiating the BACKGROUND SCAN [{$client->errorno()}] ".$client->error(); * } else { * echo "An error occured while running the BACKGROUND SCAN [{$client->errorno()}] ".$client->error(); * } * ``` * ``` * string(12) "Job ID is 1" * ``` * @link https://www.aerospike.com/docs/udf/udf_guide.html UDF Development Guide * @link https://www.aerospike.com/docs/udf/developing_record_udfs.html Developing Record UDFs * @link https://www.aerospike.com/docs/udf/api_reference.html Lua UDF - API Reference * @param string $ns the namespace * @param string $set the set within the given namespace * @param string $module the name of the UDF module registered with the cluster * @param string $function the name of the UDF * @param array $args optional arguments for the UDF * @param int &$job_id pass-by-reference filled by the job ID of the scan * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * * Aerospike::OPT_FAIL_ON_CLUSTER_CHANGE * * Aerospike::OPT_SCAN_RPS_LIMIT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::ERR_LUA UDF error status codes * @see Aerospike::jobInfo() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function scanApply($ns, $set, $module, $function, array $args, &$job_id, array $options = []) {} /** * Apply a UDF to each record in a query * * Query the *ns.set* with a predicate, and apply a UDF _module.function_ * to each of matched records. * Arguments can be passed to the UDF and any returned value optionally captured. * * Currently the only UDF language supported is Lua. * ```php * $where = Aerospike::predicateBetween("age", 30, 39); * $status = $client->queryApply("test", "users", "my_udf", "mytransform", [20], $job_id); * if ($status === Aerospike::OK) { * var_dump("Job ID is $job_id"); * } else if ($status === Aerospike::ERR_CLIENT) { * echo "An error occured while initiating the BACKGROUND SCAN [{$client->errorno()}] ".$client->error(); * } else { * echo "An error occured while running the BACKGROUND SCAN [{$client->errorno()}] ".$client->error(); * } * ``` * ``` * string(12) "Job ID is 1" * ``` * @link https://www.aerospike.com/docs/udf/udf_guide.html UDF Development Guide * @link https://www.aerospike.com/docs/udf/developing_record_udfs.html Developing Record UDFs * @link https://www.aerospike.com/docs/udf/api_reference.html Lua UDF - API Reference * @param string $ns the namespace * @param string $set the set within the given namespace * @param array $where the predicate for the query, usually created by the * predicate methods. The arrays conform to one of the following: * ``` * Array: * bin => bin name * op => one of Aerospike::OP_EQ, Aerospike::OP_BETWEEN, Aerospike::OP_CONTAINS, Aerospike::OP_RANGE, etc * val => scalar integer/string for OP_EQ and OP_CONTAINS or [$min, $max] for OP_BETWEEN and OP_RANGE * * or an empty array() for no predicate * ``` * examples * ``` * ["bin"=>"name", "op"=>Aerospike::OP_EQ, "val"=>"foo"] * ["bin"=>"age", "op"=>Aerospike::OP_BETWEEN, "val"=>[35,50]] * ["bin"=>"movies", "op"=>Aerospike::OP_CONTAINS, "val"=>"12 Monkeys"] * ["bin"=>"movies", "op"=>Aerospike::OP_RANGE, "val"=>[10,1000]] * [] // no predicate * ``` * @param string $module the name of the UDF module registered with the cluster * @param string $function the name of the UDF * @param array $args optional arguments for the UDF * @param int &$job_id pass-by-reference filled by the job ID of the scan * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * * Aerospike::OPT_POLICY_DURABLE_DELETE * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_WRITE_TIMEOUT Aerospike::OPT_WRITE_TIMEOUT options * @see Aerospike::OPT_POLICY_DURABLE_DELETE Aerospike::OPT_POLICY_DURABLE_DELETE options * @see Aerospike::OPT_SLEEP_BETWEEN_RETRIES Aerospike::OPT_SLEEP_BETWEEN_RETRIES options * @see Aerospike::OPT_TOTAL_TIMEOUT Aerospike::OPT_TOTAL_TIMEOUT options * @see Aerospike::OPT_SOCKET_TIMEOUT Aerospike::OPT_SOCKET_TIMEOUT options * @see Aerospike::MAX_RETRIES Aerospike::MAX_RETRIES options * @see Aerospike::ERR_LUA UDF error status codes * @see Aerospike::jobInfo() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function queryApply($ns, $set, array $where, $module, $function, array $args, &$job_id, array $options = []) {} /** * Apply a stream UDF to a scan or secondary index query * * Apply the UDF _module.function_ to the result of running a secondary * index query on _ns.set_. The aggregated _returned_ variable is then * filled, with its type depending on the UDF. It may be a string, integer * or array, and potentially an array of arrays, such as in the case the * UDF does not specify a reducer and there are multiple nodes in the * cluster, each sending back the result of its own aggregation. * * As with query(), if an empty array is given as the _where_ predicate a * 'scan aggregation' is initiated instead of a query, which means the * stream UDF is applied to all the records returned by the scan. * * **Note** that modules containing stream UDFs need to also be copied to the * path described in `aerospike.udf.lua_user_path`, as the last reduce * iteration is run locally on the client, after reducing on all the nodes * of the cluster. * * **Note** aggregate is currently unsupported in PHP built with ZTS enabled. * Attempting to use it in that environment will fail. * * Currently the only UDF language supported is Lua. * * **Example Stream UDF** * * Module registered as stream_udf.lua * ``` * local function having_ge_threshold(bin_having, ge_threshold) * debug("group_count::thresh_filter: %s > %s ?", tostring(rec[bin_having]), tostring(ge_threshold)) * return function(rec) * if rec[bin_having] < ge_threshold then * return false * end * return true * end * end * * local function count(group_by_bin) * return function(group, rec) * if rec[group_by_bin] then * local bin_name = rec[group_by_bin] * group[bin_name] = (group[bin_name] or 0) + 1 * end * return group * end * end * * local function add_values(val1, val2) * return val1 + val2 * end * * local function reduce_groups(a, b) * return map.merge(a, b, add_values) * end * * function group_count(stream, group_by_bin, bin_having, ge_threshold) * if bin_having and ge_threshold then * local myfilter = having_ge_threshold(bin_having, ge_threshold) * return stream : filter(myfilter) : aggregate(map{}, count(group_by_bin)) : reduce(reduce_groups) * else * return stream : aggregate(map{}, count(group_by_bin)) : reduce(reduce_groups) * end * end * ``` * **Example of aggregating a stream UDF to the result of a secondary index query** * ```php * // assuming test.users has a bin first_name, show the first name distribution * // for users in their twenties * $where = Aerospike::predicateBetween("age", 20, 29); * $status = $client->aggregate("test", "users", $where, "stream_udf", "group_count", ["first_name"], $names); * if ($status == Aerospike::OK) { * var_dump($names); * } else { * echo "An error occured while running the AGGREGATE [{$client->errorno()}] ".$client->error(); * } * ``` * ``` * array(5) { * ["Claudio"]=> * int(1) * ["Michael"]=> * int(3) * ["Jennifer"]=> * int(2) * ["Jessica"]=> * int(3) * ["Jonathan"]=> * int(3) * } * ``` * @link https://www.aerospike.com/docs/udf/udf_guide.html UDF Development Guide * @link https://www.aerospike.com/docs/udf/developing_stream_udfs.html Developing Stream UDFs * @link https://www.aerospike.com/docs/guide/aggregation.html Aggregation * @param string $ns the namespace * @param string $set the set within the given namespace * @param array $where the predicate for the query, usually created by the * predicate methods. The arrays conform to one of the following: * ``` * Array: * bin => bin name * op => one of Aerospike::OP_EQ, Aerospike::OP_BETWEEN, Aerospike::OP_CONTAINS, Aerospike::OP_RANGE * val => scalar integer/string for OP_EQ and OP_CONTAINS or [$min, $max] for OP_BETWEEN and OP_RANGE * * or an empty array() for no predicate * ``` * examples * ``` * ["bin"=>"name", "op"=>Aerospike::OP_EQ, "val"=>"foo"] * ["bin"=>"age", "op"=>Aerospike::OP_BETWEEN, "val"=>[35,50]] * ["bin"=>"movies", "op"=>Aerospike::OP_CONTAINS, "val"=>"12 Monkeys"] * ["bin"=>"movies", "op"=>Aerospike::OP_RANGE, "val"=>[10,1000]] * [] // no predicate * ``` * @param string $module the name of the UDF module registered with the cluster * @param string $function the name of the UDF * @param array $args optional arguments for the UDF * @param mixed &$returned pass-by-reference param * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_READ_TIMEOUT * * Aerospike::OPT_SLEEP_BETWEEN_RETRIES * * Aerospike::OPT_TOTAL_TIMEOUT * * Aerospike::OPT_MAX_RETRIES * * Aerospike::OPT_SOCKET_TIMEOUT * @see Aerospike::OPT_READ_TIMEOUT Aerospike::OPT_READ_TIMEOUT options * @see Aerospike::ERR_LUA UDF error status codes * @see Aerospike::predicateEquals() * @see Aerospike::predicateBetween() * @see Aerospike::predicateContains() * @see Aerospike::predicateRange() * @see Aerospike::predicateGeoContainsGeoJSONPoint() * @see Aerospike::predicateGeoWithinGeoJSONRegion() * @see Aerospike::predicateGeoContainsPoint() * @see Aerospike::predicateGeoWithinRadius() * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function aggregate($ns, $set, array $where, $module, $function, array $args, &$returned, array $options = []) {} // Admin methods /** * Create a secondary index on a bin of a specified set * * Create a secondary index of a given *index_type* on a namespace *ns*, *set* and *bin* with a specified *name* * ```php * $status = $client->addIndex("test", "user", "email", "user_email_idx", Aerospike::INDEX_TYPE_DEFAULT, Aerospike::INDEX_STRING); * if ($status == Aerospike::OK) { * echo "Index user_email_idx created on test.user.email\n"; * } else if ($status == Aerospike::ERR_INDEX_FOUND) { * echo "This index has already been created.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * * $client->addIndex("test", "user", "movies", "user_movie_titles_idx", Aerospike::INDEX_TYPE_MAPKEYS, Aerospike::INDEX_STRING); * $client->addIndex("test", "user", "movies", "user_movie_views_idx", Aerospike::INDEX_TYPE_MAPVALUES, Aerospike::INDEX_NUMERIC); * $client->addIndex("test", "user", "aliases", "user_aliases_idx", Aerospike::INDEX_TYPE_LIST, Aerospike::INDEX_STRING); * * $client->info("sindex", $res); * echo($res); * ``` * @param string $ns the namespace * @param string $set the set within the given namespace * @param string $bin the bin on which the secondary index is to be created * @param string $name the name of the index * @param int $indexType one of *Aerospike::INDEX\_TYPE\_\** * @param int $dataType one of *Aerospike::INDEX_NUMERIC* and *Aerospike::INDEX_STRING* * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * @see Aerospike::INDEX_TYPE_DEFAULT * @see Aerospike::INDEX_STRING * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function addIndex($ns, $set, $bin, $name, $indexType, $dataType, array $options = []) {} /** * Drop a secondary index * * ```php * $status = $client->dropIndex("test", "user_email_idx"); * if ($status == Aerospike::OK) { * echo "Index user_email_idx was dropped from namespace 'test'\n"; * } else if ($status == Aerospike::ERR_INDEX_NOT_FOUND) { * echo "No such index exists.\n"; * } else { * echo "[{$client->errorno()}] ".$client->error(); * } * ``` * @param string $ns the namespace * @param string $name the name of the index * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_WRITE_TIMEOUT * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function dropIndex($ns, $name, array $options = []) {} // Info Methods /** * Send an info request to a single cluster node * * Interface with the cluster's command and control functions. * A formatted request string is sent to a cluster node, and a formatted * response returned. * * A specific host can be optionally set, otherwise the request command is * sent to the host definded for client constructor. * * ```php * $client->info('bins/test', $response); * var_dump($response); * ``` * ``` * string(53) "bins/test num-bin-names=2,bin-names-quota=32768,demo,characters" * ``` * @link https://www.aerospike.com/docs/reference/info Info Command Reference * @param string $request a formatted info command * @param string &$response a formatted response from the server, filled by reference * @param null|array $host an array holding the cluster node connection information cluster * and manage its connections to them. ```[ 'addr' => $addr , 'port' => $port ]``` * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * @return int The status code of the operation. Compare to the Aerospike class status constants. */ public function info($request, &$response, $host = null, array $options = []) {} /** * Send an info request to a single cluster node * * Interface with the cluster's command and control functions. * A formatted request string is sent to a cluster node, and a formatted * response returned. * * A specific host can be optionally set, otherwise the request command is * sent to the host definded for client constructor. * * ```php * $response = $client->infoMany('build'); * var_dump($response); * ``` * ``` * array(3) { * ["BB936F106CA0568"]=> * string(6) "build 3.3.19" * ["AE712F245BB9876"]=> * string(6) "build 3.3.19" * ["DCBA9AA34EE12FA"]=> * string(6) "build 3.3.19" * } * ``` * @link https://www.aerospike.com/docs/reference/info Info Command Reference * @param string $request a formatted info command * @param null|array $host an array of _host_ arrays, each with ```[ 'addr' => $addr , 'port' => $port ]``` * @param array $options an optional array of policy options, whose keys include * * Aerospike::OPT_READ_TIMEOUT * @return array results in the format * ``` * Array: * NODE-ID => response string * ``` */ public function infoMany($request, $host = null, array $options = []) {} /** * Get the addresses of the cluster nodes * * ```php * $nodes = $client->getNodes(); * var_dump($nodes); * ``` * ``` * array(2) { * [0]=> * array(2) { * ["addr"]=> * string(15) "192.168.120.145" * ["port"]=> * string(4) "3000" * } * [1]=> * array(2) { * ["addr"]=> * string(15) "192.168.120.144" * ["port"]=> * string(4) "3000" * } * } * ``` * @return array results in the format * ``` * Array: * Array: * 'addr' => the IP address of the node * 'port' => the port of the node * ``` */ public function getNodes() {} // Logging Methods /** * Set the logging threshold of the Aerospike object * * @param int $log_level one of `Aerospike::LOG_LEVEL_*` values * * Aerospike::LOG_LEVEL_OFF * * Aerospike::LOG_LEVEL_ERROR * * Aerospike::LOG_LEVEL_WARN * * Aerospike::LOG_LEVEL_INFO * * Aerospike::LOG_LEVEL_DEBUG * * Aerospike::LOG_LEVEL_TRACE * @see Aerospike::LOG_LEVEL_OFF Aerospike::LOG_LEVEL_* constants */ public function setLogLevel($log_level) {} /** * Set a handler for log events * * Registers a callback method that will be triggered whenever a logging event above the declared log threshold occurs. * * ```php * $config = ["hosts" => [["addr"=>"localhost", "port"=>3000]], "shm"=>[]]; * $client = new Aerospike($config, true); * if (!$client->isConnected()) { * echo "Aerospike failed to connect[{$client->errorno()}]: {$client->error()}\n"; * exit(1); * } * $client->setLogLevel(Aerospike::LOG_LEVEL_DEBUG); * $client->setLogHandler(function ($level, $file, $function, $line) { * switch ($level) { * case Aerospike::LOG_LEVEL_ERROR: * $lvl_str = 'ERROR'; * break; * case Aerospike::LOG_LEVEL_WARN: * $lvl_str = 'WARN'; * break; * case Aerospike::LOG_LEVEL_INFO: * $lvl_str = 'INFO'; * break; * case Aerospike::LOG_LEVEL_DEBUG: * $lvl_str = 'DEBUG'; * break; * case Aerospike::LOG_LEVEL_TRACE: * $lvl_str = 'TRACE'; * break; * default: * $lvl_str = '???'; * } * error_log("[$lvl_str] in $function at $file:$line"); * }); * ``` * * @see Aerospike::LOG_LEVEL_OFF Aerospike::LOG_LEVEL_* constants * @param callable $log_handler a callback function with the signature * ```php * function log_handler ( int $level, string $file, string $function, int $line ) : void * ``` */ public function setLogHandler(callable $log_handler) {} // Unsupported Type Handler Methods /** * Set a serialization handler for unsupported types * * Registers a callback method that will be triggered whenever a write method handles a value whose type is unsupported. * This is a static method and the *serialize_cb* handler is global across all instances of the Aerospike class. * * ```php * Aerospike::setSerializer(function ($val) { * return gzcompress(json_encode($val)); * }); * ``` * * @link https://github.com/aerospike/aerospike-client-php/tree/master/doc#handling-unsupported-types Handling Unsupported Types * @param callable $serialize_cb a callback invoked for each value of an unsupported type, when writing to the cluster. The function must follow the signature * ```php * function aerospike_serialize ( mixed $value ) : string * ``` * @see Aerospike::OPT_SERIALIZER Aerospike::OPT_SERIALIZER options */ public function setSerializer(callable $serialize_cb) {} /** * Set a deserialization handler for unsupported types * * Registers a callback method that will be triggered whenever a read method handles a value whose type is unsupported. * This is a static method and the *unserialize_cb* handler is global across all instances of the Aerospike class. * * ```php * Aerospike::setDeserializer(function ($val) { * return json_decode(gzuncompress($val)); * }); * ``` * * @link https://github.com/aerospike/aerospike-client-php/tree/master/doc#handling-unsupported-types Handling Unsupported Types * @param callable $unserialize_cb a callback invoked for each value of an unsupported type, when reading from the cluster. The function must follow the signature * ```php * // $value is binary data of type AS_BYTES_BLOB * function aerospike_deserialize ( string $value ) * ``` * @see Aerospike::OPT_SERIALIZER Aerospike::OPT_SERIALIZER options */ public function setDeserializer(callable $unserialize_cb) {} /* * Options can be assigned values that modify default behavior * Used by the constructor, read, write, scan, query, apply, and info * operations. */ /* Key used to specify an array of read policy defaults used in the constructor. See https://github.com/aerospike/aerospike-client-php/blob/master/doc/policies.md */ public const OPT_READ_DEFAULT_POL = "OPT_READ_DEFAULT_POL"; /* Key used to specify an array of write policy defaults used in the constructor. See https://github.com/aerospike/aerospike-client-php/blob/master/doc/policies.md */ public const OPT_WRITE_DEFAULT_POL = "OPT_WRITE_DEFAULT_POL"; /* Key used to specify an array of remove policy defaults used in the constructor. See https://github.com/aerospike/aerospike-client-php/blob/master/doc/policies.md */ public const OPT_REMOVE_DEFAULT_POL = "OPT_REMOVE_DEFAULT_POL"; /* Key used to specify an array of batch policy defaults used in the constructor. See https://github.com/aerospike/aerospike-client-php/blob/master/doc/policies.md */ public const OPT_BATCH_DEFAULT_POL = "OPT_BATCH_DEFAULT_POL"; /* Key used to specify an array of operate policy defaults used in the constructor. See https://github.com/aerospike/aerospike-client-php/blob/master/doc/policies.md */ public const OPT_OPERATE_DEFAULT_POL = "OPT_OPERATE_DEFAULT_POL"; /* Key used to specify an array of query policy defaults used in the constructor. See https://github.com/aerospike/aerospike-client-php/blob/master/doc/policies.md */ public const OPT_QUERY_DEFAULT_POL = "OPT_QUERY_DEFAULT_POL"; /* Key used to specify an array of scan policy defaults used in the constructor. See https://github.com/aerospike/aerospike-client-php/blob/master/doc/policies.md */ public const OPT_SCAN_DEFAULT_POL = "OPT_SCAN_DEFAULT_POL"; /* Key used to specify an array of apply policy defaults used in the constructor. See https://github.com/aerospike/aerospike-client-php/blob/master/doc/policies.md */ public const OPT_APPLY_DEFAULT_POL = "OPT_APPLY_DEFAULT_POL"; /* Key used in the options argument of the constructor used to point to an array of TLS configuration parameters. Use of TLS requires an enterprise version of the Aerospike Server. */ public const OPT_TLS_CONFIG = "OPT_TLS_CONFIG"; /* Key used in the OPT_TLS boolean Whether or not to enable TLS. */ public const OPT_TLS_ENABLE = "OPT_TLS_ENABLE"; /* Key used to specify a string path to a trusted CA certificate file. By default TLS will use system standard trusted CA certificates */ public const OPT_OPT_TLS_CAFILE = "OPT_OPT_TLS_CAFILE"; /* Key used to specify a Path to a directory of trusted certificates. See the OpenSSL SSL_CTX_load_verify_locations manual page for more information about the format of the directory. */ public const OPT_TLS_CAPATH = "OPT_TLS_CAPATH"; /*Key used to specify a string representation of allowed protocols. Specifies enabled protocols. This format is the same as Apache's SSLProtocol documented at https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslprotocol . If not specified the client will use "-all +TLSv1.2". */ public const OPT_TLS_PROTOCOLS = "OPT_TLS_PROTOCOLS"; /* Key used to specify a string. Specifies enabled cipher suites. The format is the same as OpenSSL's Cipher List Format documented at https://www.openssl.org/docs/manmaster/apps/ciphers.html .If not specified the OpenSSL default cipher suite described in the ciphers documentation will be used. If you are not sure what cipher suite to select this option is best left unspecified */ public const OPT_TLS_CIPHER_SUITE = "OPT_TLS_CIPHER_SUITE"; /* Key used to specify a boolean. Enable CRL checking for the certificate chain leaf certificate. An error occurs if a suitable CRL cannot be found. By default CRL checking is disabled. */ public const OPT_TLS_CRL_CHECK = "OPT_TLS_CRL_CHECK"; /* Key used to specify a bolean. Enable CRL checking for the entire certificate chain. An error occurs if a suitable CRL cannot be found. By default CRL checking is disabled. */ public const OPT_TLS_CRL_CHECK_ALL = "OPT_TLS_CRL_CHECK_ALL"; /* Key used to specify a path to a certificate blacklist file. The file should contain one line for each blacklisted certificate. Each line starts with the certificate serial number expressed in hex. Each entry may optionally specify the issuer name of the certificate (serial numbers are only required to be unique per issuer). Example records: 867EC87482B2 /C=US/ST=CA/O=Acme/OU=Engineering/CN=Test Chain CA E2D4B0E570F9EF8E885C065899886461 */ public const OPT_TLS_CERT_BLACKLIST = "OPT_TLS_CERT_BLACKLIST"; /* Boolean: Log session information for each connection. */ public const OPT_TLS_LOG_SESSION_INFO = "OPT_TLS_LOG_SESSION_INFO"; /* Path to the client's key for mutual authentication. By default mutual authentication is disabled. */ public const OPT_TLS_KEYFILE = "OPT_TLS_KEYFILE"; /* Path to the client's certificate chain file for mutual authentication. By default mutual authentication is disabled. */ public const OPT_TLS_CERTFILE = "OPT_TLS_CERTFILE"; /** * Defines the length of time (in milliseconds) the client waits on establishing a connection. * value in milliseconds (default: 1000) */ public const OPT_CONNECT_TIMEOUT = "OPT_CONNECT_TIMEOUT"; /** * Defines the length of time (in milliseconds) the client waits on a read * operation. * value in milliseconds (default: 1000) */ public const OPT_READ_TIMEOUT = "OPT_READ_TIMEOUT"; /** * Defines the length of time (in milliseconds) the client waits on a write * operation. * value in milliseconds (default: 1000) */ public const OPT_WRITE_TIMEOUT = "OPT_WRITE_TIMEOUT"; /** * Sets the TTL of the record along with a write operation. * * * TTL > 0 sets the number of seconds into the future in which to expire the record. * * TTL = 0 uses the default TTL defined for the namespace. * * TTL = -1 means the record should never expire. * * TTL = -2 means the record's TTL should not be modified. * value in seconds, or the special values 0, -1 or -2 (default: 0) */ public const OPT_TTL = "OPT_TTL"; /** * Accepts one of the POLICY_KEY_* values. * * {@link https://www.aerospike.com/docs/client/php/usage/kvs/record-structure.html Records} * are uniquely identified by their digest, and can optionally store the value of their primary key * (their unique ID in the application). * Key storage policy option (digest-only or send key) */ public const OPT_POLICY_KEY = "OPT_POLICY_KEY"; /** * Do not store the primary key with the record (default) * digest only */ public const POLICY_KEY_DIGEST = 0; /** * Store the primary key with the record * store the primary key with the record */ public const POLICY_KEY_SEND = 1; /** * Accepts one of the POLICY_EXISTS_* values. * * By default writes will try to create a record or update its bins, which * is a behavior similar to how arrays work in PHP. Setting a write with a * different POLICY\_EXISTS\_* value can simulate a more DML-like behavior, * similar to an RDBMS. * existence policy option */ public const OPT_POLICY_EXISTS = "OPT_POLICY_EXISTS"; /** * "CREATE_OR_UPDATE" behavior. Create the record if it does not exist, * or update its bins if it does. (default) * create or update behavior */ public const POLICY_EXISTS_IGNORE = 0; /** * Create a record ONLY if it DOES NOT exist. * create only behavior (fail otherwise) */ public const POLICY_EXISTS_CREATE = 1; /** * Update a record ONLY if it exists. * update only behavior (fail otherwise) */ public const POLICY_EXISTS_UPDATE = 2; /** * Replace a record ONLY if it exists. * replace only behavior (fail otherwise) */ public const POLICY_EXISTS_REPLACE = 3; /** * Create the record if it does not exist, or replace its bins if it does. * create or replace behavior */ public const POLICY_EXISTS_CREATE_OR_REPLACE = 4; /** * Set to an array( Aerospike::POLICY_GEN_* [, (int) $gen_value ] ) * * Specifies the behavior of write opertions with regards to the record's * generation. Used to implement a check-and-set (CAS) pattern. * generation policy option */ public const OPT_POLICY_GEN = "OPT_POLICY_GEN"; /** * Do not consider generation for the write operation. * write a record, regardless of generation (default) */ public const POLICY_GEN_IGNORE = 0; /** * Only write if the record was not modified since a given generation value. * write a record, ONLY if generations are equal */ public const POLICY_GEN_EQ = 1; /** * write a record, ONLY if local generation is greater-than remote generation */ public const POLICY_GEN_GT = 2; /** * Set to one of the SERIALIZER_* values. * * Supported types, such as string, integer, and array get directly cast to * the matching Aerospike types, such as as_string, as_integer, and as_map. * Unsupported types, such as boolean, need a serializer to handle them. * determines a handler for unsupported data types */ public const OPT_SERIALIZER = "OPT_SERIALIZER"; /** * Throw an exception instead of serializing unsupported types. * throw an error when serialization is required */ public const SERIALIZER_NONE = 0; /** * Use the built-in PHP serializer for any unsupported types. * use the PHP serialize/unserialize functions (default) */ public const SERIALIZER_PHP = 1; /** * Use a user-defined serializer for any unsupported types. * use a pair of functions written in PHP for serialization */ public const SERIALIZER_USER = 2; /** * Accepts one of the POLICY_COMMIT_LEVEL_* values. * * One of the {@link https://www.aerospike.com/docs/architecture/consistency.html per-transaction consistency levels}. * Specifies the number of replicas required to be successfully committed * before returning success in a write operation to provide the desired * consistency level. * commit level policy option */ public const OPT_POLICY_COMMIT_LEVEL = "OPT_POLICY_COMMIT_LEVEL"; /** * Return succcess only after successfully committing all replicas. * write to the master and all replicas (default) */ public const POLICY_COMMIT_LEVEL_ALL = 0; /** * Return succcess after successfully committing the master replica. * master will asynchronously write to replicas */ public const POLICY_COMMIT_LEVEL_MASTER = 1; /** * Accepts one of the POLICY_REPLICA_* values. * * One of the {@link https://www.aerospike.com/docs/architecture/consistency.html per-transaction consistency levels}. * Specifies which partition replica to read from. * replica policy option */ public const OPT_POLICY_REPLICA = "OPT_POLICY_REPLICA"; /** * Read from the partition master replica node. * read from master */ public const POLICY_REPLICA_MASTER = 0; /** * Read from an unspecified replica node. * read from any replica node */ public const POLICY_REPLICA_ANY = 1; /** * Always try node containing master partition first. If connection fails and * `retry_on_timeout` is true, try node containing replica partition. * Currently restricted to master and one replica. (default) * attempt to read from master first, then try the node containing replica partition if connection failed. (default) */ public const POLICY_REPLICA_SEQUENCE = 2; /** * Try node on the same rack as the client first. If there are no nodes on the * same rack, use POLICY_REPLICA_SEQUENCE instead. * * "rack_aware" must be set to true in the client constructor, and "rack_id" must match the server rack configuration * to enable this functionality. * attemp to read from master first, then try the node containing replica partition if connection failed. (default) */ public const POLICY_REPLICA_PREFER_RACK = 3; /** * Accepts one of the POLICY_READ_MODE_AP_* values. * * One of the {@link https://www.aerospike.com/docs/architecture/consistency.html per-transaction consistency levels}. * Specifies the number of replicas to be consulted in a read operation to * provide the desired consistency level in availability mode. * policy read option for availability namespaces */ public const OPT_POLICY_READ_MODE_AP = "OPT_POLICY_READ_MODE_AP"; /** * Involve a single replica in the operation. * (default) */ public const POLICY_READ_MODE_AP_ONE = 0; /** * Involve all replicas in the operation. * */ public const AS_POLICY_READ_MODE_AP_ALL = 1; /** * Accepts one of the POLICY_READ_MODE_SC_* values. * * One of the {@link https://www.aerospike.com/docs/architecture/consistency.html per-transaction consistency levels}. * Specifies the number of replicas to be consulted in a read operation to * provide the desired consistency level. * policy read option for consistency namespaces */ public const OPT_POLICY_READ_MODE_SC = "OPT_POLICY_READ_MODE_SC"; /** * Always read from master. Record versions are local to session. * (default) */ public const POLICY_READ_MODE_SC_SESSION = 0; /** * Always read from master. Record versions are global and thus serialized. * */ public const POLICY_READ_MODE_SC_LINEARIZE = 1; /** * Read from master or fully migrated replica. Record versions may not always increase. * */ public const POLICY_READ_MODE_SC_ALLOW_REPLICA = 2; /** * Read from master or fully migrated replica. Unavailable partitions are allowed. Record versions may not always increase. * */ public const POLICY_READ_MODE_SC_ALLOW_UNAVAILABLE = 3; /* * Should raw bytes representing a list or map be deserialized to an array. * Set to false for backup programs that just need access to raw bytes. * Default: true */ public const OPT_DESERIALIZE = "deserialize"; /** * Milliseconds to sleep between retries. Enter zero to skip sleep. * const OPT_SLEEP_BETWEEN_RETRIES */ public const OPT_SLEEP_BETWEEN_RETRIES = "sleep_between_retries"; /** * Maximum number of retries before aborting the current transaction. * The initial attempt is not counted as a retry. * If OPT_MAX_RETRIES is exceeded, the transaction will return error ERR_TIMEOUT. * WARNING: Database writes that are not idempotent (such as "add") * should not be retried because the write operation may be performed * multiple times if the client timed out previous transaction attempts. * It's important to use a distinct write policy for non-idempotent * writes which sets OPT_MAX_RETRIES = 0; **/ public const OPT_MAX_RETRIES = "OPT_MAX_RETRIES"; /** * Total transaction timeout in milliseconds. * The OPT_TOTAL_TIMEOUT is tracked on the client and sent to the server along with * the transaction in the wire protocol. The client will most likely timeout * first, but the server also has the capability to timeout the transaction. * If OPT_TOTAL_TIMEOUT is not zero and OPT_TOTAL_TIMEOUT is reached before the transaction * completes, the transaction will return error ERR_TIMEOUT. * If OPT_TOTAL_TIMEOUT is zero, there will be no total time limit. */ public const OPT_TOTAL_TIMEOUT = "OPT_TOTAL_TIMEOUT"; /** * Socket idle timeout in milliseconds when processing a database command. * If OPT_SOCKET_TIMEOUT is not zero and the socket has been idle for at least OPT_SOCKET_TIMEOUT, * both OPT_MAX_RETRIES and OPT_TOTAL_TIMEOUT are checked. If OPT_MAX_RETRIES and OPT_TOTAL_TIMEOUT are not * exceeded, the transaction is retried. * If both OPT_SOCKET_TIMEOUT and OPT_TOTAL_TIMEOUT are non-zero and OPT_SOCKET_TIMEOUT > OPT_TOTAL_TIMEOUT, * then OPT_SOCKET_TIMEOUT will be set to OPT_TOTAL_TIMEOUT. If OPT_SOCKET_TIMEOUT is zero, there will be * no socket idle limit. */ public const OPT_SOCKET_TIMEOUT = "OPT_SOCKET_TIMEOUT"; /** * Determine if batch commands to each server are run in parallel threads. */ public const OPT_BATCH_CONCURRENT = "OPT_BATCH_CONCURRENT"; /** * Allow batch to be processed immediately in the server's receiving thread when the server * deems it to be appropriate. If false, the batch will always be processed in separate * transaction threads. This field is only relevant for the new batch index protocol. * * For batch exists or batch reads of smaller sized records (<= 1K per record), inline * processing will be significantly faster on "in memory" namespaces. The server disables * inline processing on disk based namespaces regardless of this policy field. * * Inline processing can introduce the possibility of unfairness because the server * can process the entire batch before moving onto the next command. * Default: true */ public const OPT_ALLOW_INLINE = "OPT_ALLOW_INLINE"; /** * Send set name field to server for every key in the batch for batch index protocol. * This is only necessary when authentication is enabled and security roles are defined * on a per set basis. * Default: false */ public const OPT_SEND_SET_NAME = "OPT_SEND_SET_NAME"; /** * Abort the scan if the cluster is not in a stable state. Default false */ public const OPT_FAIL_ON_CLUSTER_CHANGE = "OPT_FAIL_ON_CLUSTER_CHANGE"; /** * Accepts one of the SCAN_PRIORITY_* values. * * The priority of the scan */ public const OPT_SCAN_PRIORITY = "OPT_SCAN_PRIORITY"; /** * The cluster will auto-adjust the priority of the scan. * auto-adjust the scan priority (default) */ public const SCAN_PRIORITY_AUTO = "SCAN_PRIORITY_AUTO"; /** * Set the scan as having low priority. * low priority scan */ public const SCAN_PRIORITY_LOW = "SCAN_PRIORITY_LOW"; /** * Set the scan as having medium priority. * medium priority scan */ public const SCAN_PRIORITY_MEDIUM = "SCAN_PRIORITY_MEDIUM"; /** * Set the scan as having high priority. * high priority scan */ public const SCAN_PRIORITY_HIGH = "SCAN_PRIORITY_HIGH"; /** * Do not return the bins of the records matched by the scan. * * boolean value (default: false) */ public const OPT_SCAN_NOBINS = "OPT_SCAN_NOBINS"; /** * Set the scan to run over a given percentage of the possible records. * * integer value from 1-100 (default: 100) */ public const OPT_SCAN_PERCENTAGE = "OPT_SCAN_PERCENTAGE"; /** * Scan all the nodes in the cluster concurrently. * * boolean value (default: false) */ public const OPT_SCAN_CONCURRENTLY = "OPT_SCAN_CONCURRENTLY"; /** * Do not return the bins of the records matched by the query. * * boolean value (default: false) */ public const OPT_QUERY_NOBINS = "OPT_QUERY_NOBINS"; /** * Revert to the older batch-direct protocol, instead of batch-index. * * boolean value (default: false) */ public const USE_BATCH_DIRECT = "USE_BATCH_DIRECT"; /** * Set to true to enable durable delete for the operation. * Durable deletes are an Enterprise Edition feature * * boolean value (default: false) */ public const OPT_POLICY_DURABLE_DELETE = "OPT_POLICY_DURABLE_DELETE"; /** * Map policy declaring the ordering of an Aerospike map type * * @see Aerospike::AS_MAP_UNORDERED * @see Aerospike::AS_MAP_KEY_ORDERED * @see Aerospike::AS_MAP_KEY_VALUE_ORDERED * */ public const OPT_MAP_ORDER = "OPT_MAP_ORDER"; /** * The Aerospike map is unordered * (default) */ public const AS_MAP_UNORDERED = "AS_MAP_UNORDERED"; /** * The Aerospike map is ordered by key * */ public const AS_MAP_KEY_ORDERED = "AS_MAP_KEY_ORDERED"; /** * The Aerospike map is ordered by key and value * */ public const AS_MAP_KEY_VALUE_ORDERED = "AS_MAP_KEY_VALUE_ORDERED"; /** * Map policy declaring the behavior of map write operations * @see Aerospike::AS_MAP_UPDATE * @see Aerospike::AS_MAP_UPDATE_ONLY * @see Aerospike::AS_MAP_CREATE_ONLY * */ public const OPT_MAP_WRITE_MODE = "OPT_MAP_WRITE_MODE"; /** * (default) */ public const AS_MAP_UPDATE = "AS_MAP_UPDATE"; public const AS_MAP_UPDATE_ONLY = "AS_MAP_UPDATE_ONLY"; public const AS_MAP_CREATE_ONLY = "AS_MAP_CREATE_ONLY"; /** * Map policy flags declaring the behavior of map write operations * @see Aerospike::AS_MAP_WRITE_DEFAULT * @see Aerospike::AS_MAP_WRITE_CREATE_ONLY * @see Aerospike::AS_MAP_WRITE_UPDATE_ONLY * @see Aerospike::AS_MAP_WRITE_NO_FAIL * @see Aerospike::AS_MAP_WRITE_PARTIAL * */ public const OPT_MAP_WRITE_FLAGS = "OPT_MAP_WRITE_FLAGS"; /** * Default. Allow create or update. * (default) */ public const AS_MAP_WRITE_DEFAULT = "AS_MAP_WRITE_DEFAULT"; /** * If the key already exists, the item will be denied. If the key does not exist, a new item will be created. * */ public const AS_MAP_WRITE_CREATE_ONLY = "AS_MAP_WRITE_CREATE_ONLY"; /** * If the key already exists, the item will be overwritten. If the key does not exist, the item will be denied. * */ public const AS_MAP_WRITE_UPDATE_ONLY = "AS_MAP_WRITE_UPDATE_ONLY"; /** * Do not raise error if a map item is denied due to write flag constraints (always succeed). * */ public const AS_MAP_WRITE_NO_FAIL = "AS_MAP_WRITE_NO_FAIL"; /** * Allow other valid map items to be committed if a map item is denied due to write flag constraints. * */ public const AS_MAP_WRITE_PARTIAL = "AS_MAP_WRITE_PARTIAL"; /** * Do not return a result for the map operation (get and remove operations) * @link https://www.aerospike.com/docs/guide/cdt-map.html#map-apis Map Result Types * */ public const MAP_RETURN_NONE = "AS_MAP_RETURN_NONE"; /** * Return in key index order * @link https://www.aerospike.com/docs/guide/cdt-map.html#map-apis Map Result Types * */ public const MAP_RETURN_INDEX = "AS_MAP_RETURN_INDEX"; /** * Return in reverse key order * @link https://www.aerospike.com/docs/guide/cdt-map.html#map-apis Map Result Types * */ public const MAP_RETURN_REVERSE_INDEX = "AS_MAP_RETURN_REVERSE_INDEX"; /** * Return in value order * @link https://www.aerospike.com/docs/guide/cdt-map.html#map-apis Map Result Types * */ public const MAP_RETURN_RANK = "AS_MAP_RETURN_RANK"; /** * Return in reverse value order * @link https://www.aerospike.com/docs/guide/cdt-map.html#map-apis Map Result Types * */ public const MAP_RETURN_REVERSE_RANK = "AS_MAP_RETURN_REVERSE_RANK"; /** * Return count of items selected * @link https://www.aerospike.com/docs/guide/cdt-map.html#map-apis Map Result Types * */ public const MAP_RETURN_COUNT = "AS_MAP_RETURN_COUNT"; /** * Return key for single key read and key list for range read * @link https://www.aerospike.com/docs/guide/cdt-map.html#map-apis Map Result Types * */ public const MAP_RETURN_KEY = "AS_MAP_RETURN_KEY"; /** * Return value for single key read and value list for range read * @link https://www.aerospike.com/docs/guide/cdt-map.html#map-apis Map Result Types * */ public const MAP_RETURN_VALUE = "AS_MAP_RETURN_VALUE"; /** * Return key/value items * Will be of the form ['key1', 'val1', 'key2', 'val2', 'key3', 'val3] * @link https://www.aerospike.com/docs/guide/cdt-map.html#map-apis Map Result Types * */ public const MAP_RETURN_KEY_VALUE = "AS_MAP_RETURN_KEY_VALUE"; public const LOG_LEVEL_OFF = "LOG_LEVEL_OFF"; public const LOG_LEVEL_ERROR = "LOG_LEVEL_ERROR"; public const LOG_LEVEL_WARN = "LOG_LEVEL_WARN"; public const LOG_LEVEL_INFO = "LOG_LEVEL_INFO"; public const LOG_LEVEL_DEBUG = "LOG_LEVEL_DEBUG"; public const LOG_LEVEL_TRACE = "LOG_LEVEL_TRACE"; /** * Aerospike Status Codes * * Each Aerospike API method invocation returns a status code from the * server. * * The status codes map to the * {@link https://github.com/aerospike/aerospike-client-c/blob/master/src/include/aerospike/as_status.h status codes} * of the C client. * * Success */ public const OK = "AEROSPIKE_OK"; // -10 - -1 - Client Errors /** * Synchronous connection error * */ public const ERR_CONNECTION = "AEROSPIKE_ERR_CONNECTION"; /** * Node invalid or could not be found * */ public const ERR_TLS_ERROR = "AEROSPIKE_ERR_TLS"; /** * Node invalid or could not be found * */ public const ERR_INVALID_NODE = "AEROSPIKE_ERR_INVALID_NODE"; /** * Client hit the max asynchronous connections * */ public const ERR_NO_MORE_CONNECTIONS = "AEROSPIKE_ERR_NO_MORE_CONNECTIONS"; /** * Asynchronous connection error * */ public const ERR_ASYNC_CONNECTION = "AEROSPIKE_ERR_ASYNC_CONNECTION"; /** * Query or scan was aborted in user's callback * */ public const ERR_CLIENT_ABORT = "AEROSPIKE_ERR_CLIENT_ABORT"; /** * Host name could not be found in DNS lookup * */ public const ERR_INVALID_HOST = "AEROSPIKE_ERR_INVALID_HOST"; /** * Invalid client API parameter * */ public const ERR_PARAM = "AEROSPIKE_ERR_PARAM"; /** * Generic client API usage error * */ public const ERR_CLIENT = "AEROSPIKE_ERR_CLIENT"; // 1-49 - Basic Server Errors /** * Generic error returned by server * */ public const ERR_SERVER = "AEROSPIKE_ERR_SERVER"; /** * No record is found with the specified namespace/set/key combination. * May be returned by a read, or a write with OPT_POLICY_EXISTS * set to POLICY_EXISTS_UPDATE * */ public const ERR_RECORD_NOT_FOUND = "AEROSPIKE_ERR_RECORD_NOT_FOUND"; /** * Generation of record does not satisfy the OPT_POLICY_GEN write policy * */ public const ERR_RECORD_GENERATION = "AEROSPIKE_ERR_RECORD_GENERATION"; /** * Illegal parameter sent from client. Check client parameters and verify * each is supported by current server version * */ public const ERR_REQUEST_INVALID = "AEROSPIKE_ERR_REQUEST_INVALID"; /** * The operation cannot be applied to the current bin on the server * */ public const ERR_OP_NOT_APPLICABLE = "AEROSPIKE_ERR_OP_NOT_APPLICABLE"; /** * Record already exists. May be returned by a write with the * OPT_POLICY_EXISTS write policy set to POLICY_EXISTS_CREATE * */ public const ERR_RECORD_EXISTS = "AEROSPIKE_ERR_RECORD_EXISTS"; /** * (future) For future write requests which specify 'BIN_CREATE_ONLY', * request failed because one of the bins in the write already exists * */ public const ERR_BIN_EXISTS = "AEROSPIKE_ERR_BIN_EXISTS"; /** * On scan requests, the scan terminates because cluster is in migration. * Only occur when client requested 'fail_on_cluster_change' policy on scan * */ public const ERR_CLUSTER_CHANGE = "AEROSPIKE_ERR_CLUSTER_CHANGE"; /** * Occurs when stop_writes is true (either memory - stop-writes-pct - * or disk - min-avail-pct). Can also occur if memory cannot be allocated * anymore (but stop_writes should in general hit first). Namespace will no * longer be able to accept write requests * */ public const ERR_SERVER_FULL = "AEROSPIKE_ERR_SERVER_FULL"; /** * Request was not completed during the allocated time, thus aborted * */ public const ERR_TIMEOUT = "AEROSPIKE_ERR_TIMEOUT"; /** * Write request is rejected because XDR is not running. * Only occur when XDR configuration xdr-stop-writes-noxdr is on * */ #[Deprecated("Will be reused as ERR_ALWAYS_FORBIDDEN")] public const ERR_ALWAYS_FORBIDDEN = "AEROSPIKE_ERR_ALWAYS_FORBIDDEN"; /** * Server is not accepting requests. * Occur during single node on a quick restart to join existing cluster * */ public const ERR_CLUSTER = "AEROSPIKE_ERR_CLUSTER"; /** * Operation is not allowed due to data type or namespace configuration incompatibility. * For example, append to a float data type, or insert a non-integer when * namespace is configured as data-in-index * */ public const ERR_BIN_INCOMPATIBLE_TYPE = "AEROSPIKE_ERR_BIN_INCOMPATIBLE_TYPE"; /** * Attempt to write a record whose size is bigger than the configured write-block-size * */ public const ERR_RECORD_TOO_BIG = "AEROSPIKE_ERR_RECORD_TOO_BIG"; /** * Too many concurrent operations (> transaction-pending-limit) on the same record. * A "hot-key" situation * */ public const ERR_RECORD_BUSY = "AEROSPIKE_ERR_RECORD_BUSY"; /** * Scan aborted by user on server * */ public const ERR_SCAN_ABORTED = "AEROSPIKE_ERR_SCAN_ABORTED"; /** * The client is trying to use a feature that does not yet exist in the * version of the server node it is talking to * */ public const ERR_UNSUPPORTED_FEATURE = "AEROSPIKE_ERR_UNSUPPORTED_FEATURE"; /** * (future) For future write requests which specify 'REPLACE_ONLY', * request fail because specified bin name does not exist in record * */ public const ERR_BIN_NOT_FOUND = "AEROSPIKE_ERR_BIN_NOT_FOUND"; /** * Write request is rejected because one or more storage devices of the node are not keeping up * */ public const ERR_DEVICE_OVERLOAD = "AEROSPIKE_ERR_DEVICE_OVERLOAD"; /** * For update request on records which has key stored, the incoming key does not match * the existing stored key. This indicates a RIPEMD160 key collision has happend (report as a bug) * */ public const ERR_RECORD_KEY_MISMATCH = "AEROSPIKE_ERR_RECORD_KEY_MISMATCH"; /** * Namespace in request not found on server * */ public const ERR_NAMESPACE_NOT_FOUND = "AEROSPIKE_ERR_NAMESPACE_NOT_FOUND"; /** * Bin name length greater than 14 characters, or maximum number of unique bin names are exceeded * */ public const ERR_BIN_NAME = "AEROSPIKE_ERR_BIN_NAME"; /** * Operation not allowed at this time. * For writes, the set is in the middle of being deleted, or the set's stop-write is reached; * For scan, too many concurrent scan jobs (> scan-max-active); * For XDR-ed cluster, fail writes which are not replicated from another datacenter * */ public const ERR_FAIL_FORBIDDEN = "AEROSPIKE_ERR_FORBIDDEN"; /** * Target was not found for operations that requires a target to be found * */ public const ERR_FAIL_ELEMENT_NOT_FOUND = "AEROSPIKE_ERR_FAIL_NOT_FOUND"; /** * Target already exist for operations that requires the target to not exist * */ public const ERR_FAIL_ELEMENT_EXISTS = "AEROSPIKE_ERR_FAIL_ELEMENT_EXISTS"; // 50-89 - Security Specific Errors /** * Security functionality not supported by connected server * */ public const ERR_SECURITY_NOT_SUPPORTED = "AEROSPIKE_ERR_SECURITY_NOT_SUPPORTED"; /** * Security functionality not enabled by connected server * */ public const ERR_SECURITY_NOT_ENABLED = "AEROSPIKE_ERR_SECURITY_NOT_ENABLED"; /** * Security scheme not supported * */ public const ERR_SECURITY_SCHEME_NOT_SUPPORTED = "AEROSPIKE_ERR_SECURITY_SCHEME_NOT_SUPPORTED"; /** * Unrecognized security command * */ public const ERR_INVALID_COMMAND = "AEROSPIKE_ERR_INVALID_COMMAND"; /** * Field is not valid * */ public const ERR_INVALID_FIELD = "AEROSPIKE_ERR_INVALID_FIELD"; /** * Security protocol not followed * */ public const ERR_ILLEGAL_STATE = "AEROSPIKE_ERR_ILLEGAL_STATE"; /** * No user supplied or unknown user * */ public const ERR_INVALID_USER = "AEROSPIKE_ERR_INVALID_USER"; /** * User already exists * */ public const ERR_USER_ALREADY_EXISTS = "AEROSPIKE_ERR_USER_ALREADY_EXISTS"; /** * Password does not exists or not recognized * */ public const ERR_INVALID_PASSWORD = "AEROSPIKE_ERR_INVALID_PASSWORD"; /** * Expired password * */ public const ERR_EXPIRED_PASSWORD = "AEROSPIKE_ERR_EXPIRED_PASSWORD"; /** * Forbidden password (e.g. recently used) * */ public const ERR_FORBIDDEN_PASSWORD = "AEROSPIKE_ERR_FORBIDDEN_PASSWORD"; /** * Invalid credential or credential does not exist * */ public const ERR_INVALID_CREDENTIAL = "AEROSPIKE_ERR_INVALID_CREDENTIAL"; /** * No role(s) or unknown role(s) * */ public const ERR_INVALID_ROLE = "AEROSPIKE_ERR_INVALID_ROLE"; /** * Privilege is invalid * */ public const ERR_INVALID_PRIVILEGE = "AEROSPIKE_ERR_INVALID_PRIVILEGE"; /** * User must be authenticated before performing database operations * */ public const ERR_NOT_AUTHENTICATED = "AEROSPIKE_ERR_NOT_AUTHENTICATED"; /** * User does not possess the required role to perform the database operation * */ public const ERR_ROLE_VIOLATION = "AEROSPIKE_ERR_ROLE_VIOLATION"; /** * Role already exists * */ public const ERR_ROLE_ALREADY_EXISTS = "AEROSPIKE_ERR_ROLE_ALREADY_EXISTS"; // 100-109 - UDF Specific Errors // /** * A user defined function failed to execute * */ public const ERR_UDF = "AEROSPIKE_ERR_UDF"; /** * The UDF does not exist * */ public const ERR_UDF_NOT_FOUND = "AEROSPIKE_ERR_UDF_NOT_FOUND"; /** * The LUA file does not exist * */ public const ERR_LUA_FILE_NOT_FOUND = "AEROSPIKE_ERR_LUA_FILE_NOT_FOUND"; // 150-159 - Batch Specific Errors /** * Batch functionality has been disabled by configuring the batch-index-thread=0 * */ public const ERR_BATCH_DISABLED = "AEROSPIKE_ERR_BATCH_DISABLED"; /** * Batch max requests has been exceeded * */ public const ERR_BATCH_MAX_REQUESTS_EXCEEDED = "AEROSPIKE_ERR_BATCH_MAX_REQUESTS_EXCEEDED"; /** * All batch queues are full * */ public const ERR_BATCH_QUEUES_FULL = "AEROSPIKE_ERR_BATCH_QUEUES_FULL"; // 160-169 - Geo Specific Errors /** * GeoJSON is malformed or not supported * */ public const ERR_GEO_INVALID_GEOJSON = "AEROSPIKE_ERR_GEO_INVALID_GEOJSON"; // 200-219 - Secondary Index Specific Errors /** * Secondary index already exists * * Accepts one of the POLICY_KEY_* values. * * {@link https://www.aerospike.com/docs/client/php/usage/kvs/record-structure.html Records} * are uniquely identified by their digest, and can optionally store the value of their primary key * (their unique ID in the application). * Key storage policy option (digest-only or send key) */ public const ERR_INDEX_FOUND = "AEROSPIKE_ERR_INDEX_FOUND"; /** * Secondary index does not exist * */ public const ERR_INDEX_NOT_FOUND = "AEROSPIKE_ERR_INDEX_NOT_FOUND"; /** * Secondary index memory space exceeded * */ public const ERR_INDEX_OOM = "AEROSPIKE_ERR_INDEX_OOM"; /** * Secondary index not available for query. Occurs when indexing creation has not finished * */ public const ERR_INDEX_NOT_READABLE = "AEROSPIKE_ERR_INDEX_NOT_READABLE"; /** * Generic secondary index error * */ public const ERR_INDEX = "AEROSPIKE_ERR_INDEX"; /** * Index name maximun length exceeded * */ public const ERR_INDEX_NAME_MAXLEN = "AEROSPIKE_ERR_INDEX_NAME_MAXLEN"; /** * Maximum number of indicies exceeded * */ public const ERR_INDEX_MAXCOUNT = "AEROSPIKE_ERR_INDEX_MAXCOUNT"; /** * Secondary index query aborted * */ public const ERR_QUERY_ABORTED = "AEROSPIKE_ERR_QUERY_ABORTED"; /** * Secondary index queue full * */ public const ERR_QUERY_QUEUE_FULL = "AEROSPIKE_ERR_QUERY_QUEUE_FULL"; /** * Secondary index query timed out on server * */ public const ERR_QUERY_TIMEOUT = "AEROSPIKE_ERR_QUERY_TIMEOUT"; /** * Generic query error * */ public const ERR_QUERY = "AEROSPIKE_ERR_QUERY"; /** * write operator for the operate() method * */ public const OPERATOR_WRITE = "OPERATOR_WRITE"; /** * read operator for the operate() method * */ public const OPERATOR_READ = "OPERATOR_READ"; /** * increment operator for the operate() method * */ public const OPERATOR_INCR = "OPERATOR_INCR"; /** * prepend operator for the operate() method * */ public const OPERATOR_PREPEND = "OPERATOR_PREPEND"; /** * append operator for the operate() method * */ public const OPERATOR_APPEND = "OPERATOR_APPEND"; /** * touch operator for the operate() method * */ public const OPERATOR_TOUCH = "OPERATOR_TOUCH"; /** * delete operator for the operate() method * */ public const OPERATOR_DELETE = "OPERATOR_DELETE"; // List operation constants /** * list-append operator for the operate() method * */ public const OP_LIST_APPEND = "OP_LIST_APPEND"; /** * list-merge operator for the operate() method * */ public const OP_LIST_MERGE = "OP_LIST_MERGE"; /** * list-insert operator for the operate() method * */ public const OP_LIST_INSERT = "OP_LIST_INSERT"; /** * list-insert-items operator for the operate() method * */ public const OP_LIST_INSERT_ITEMS = "OP_LIST_INSERT_ITEMS"; /** * list-pop operator for the operate() method * */ public const OP_LIST_POP = "OP_LIST_POP"; /** * list-pop-range operator for the operate() method * */ public const OP_LIST_POP_RANGE = "OP_LIST_POP_RANGE"; /** * list-remove operator for the operate() method * */ public const OP_LIST_REMOVE = "OP_LIST_REMOVE"; /** * list-remove-range operator for the operate() method * */ public const OP_LIST_REMOVE_RANGE = "OP_LIST_REMOVE_RANGE"; /** * list-clear operator for the operate() method * */ public const OP_LIST_CLEAR = "OP_LIST_CLEAR"; /** * list-set operator for the operate() method * */ public const OP_LIST_SET = "OP_LIST_SET"; /** * list-get operator for the operate() method * */ public const OP_LIST_GET = "OP_LIST_GET"; /** * list-get-range operator for the operate() method * */ public const OP_LIST_GET_RANGE = "OP_LIST_GET_RANGE"; /** * list-trim operator for the operate() method * */ public const OP_LIST_TRIM = "OP_LIST_TRIM"; /** * list-size operator for the operate() method * */ public const OP_LIST_SIZE = "OP_LIST_SIZE"; // Map operation constants /** * map-size operator for the operate() method * */ public const OP_MAP_SIZE = "OP_MAP_SIZE"; /** * map-size operator for the operate() method * */ public const OP_MAP_CLEAR = "OP_MAP_CLEAR"; /** * map-set-policy operator for the operate() method * */ public const OP_MAP_SET_POLICY = "OP_MAP_SET_POLICY"; /** * map-get-by-key operator for the operate() method * */ public const OP_MAP_GET_BY_KEY = "OP_MAP_GET_BY_KEY"; /** * map-get-by-key-range operator for the operate() method * */ public const OP_MAP_GET_BY_KEY_RANGE = "OP_MAP_GET_BY_KEY_RANGE"; /** * map-get-by-value operator for the operate() method * */ public const OP_MAP_GET_BY_VALUE = "OP_MAP_GET_BY_VALUE"; /** * map-get-by-value-range operator for the operate() method * */ public const OP_MAP_GET_BY_VALUE_RANGE = "OP_MAP_GET_BY_VALUE_RANGE"; /** * map-get-by-index operator for the operate() method * */ public const OP_MAP_GET_BY_INDEX = "OP_MAP_GET_BY_INDEX"; /** * map-get-by-index-range operator for the operate() method * */ public const OP_MAP_GET_BY_INDEX_RANGE = "OP_MAP_GET_BY_INDEX_RANGE"; /** * map-get-by-rank operator for the operate() method * */ public const OP_MAP_GET_BY_RANK = "OP_MAP_GET_BY_RANK"; /** * map-get-by-rank-range operator for the operate() method * */ public const OP_MAP_GET_BY_RANK_RANGE = "OP_MAP_GET_BY_RANK_RANGE"; /** * map-put operator for the operate() method * */ public const OP_MAP_PUT = "OP_MAP_PUT"; /** * map-put-items operator for the operate() method * */ public const OP_MAP_PUT_ITEMS = "OP_MAP_PUT_ITEMS"; /** * map-increment operator for the operate() method * */ public const OP_MAP_INCREMENT = "OP_MAP_INCREMENT"; /** * map-decrement operator for the operate() method * */ public const OP_MAP_DECREMENT = "OP_MAP_DECREMENT"; /** * map-remove-by-key operator for the operate() method * */ public const OP_MAP_REMOVE_BY_KEY = "OP_MAP_REMOVE_BY_KEY"; /** * map-remove-by-key-list operator for the operate() method * */ public const OP_MAP_REMOVE_BY_KEY_LIST = "OP_MAP_REMOVE_BY_KEY_LIST"; /** * map-remove-by-key-range key operator for the operate() method * */ public const OP_MAP_REMOVE_BY_KEY_RANGE = "OP_MAP_REMOVE_BY_KEY_RANGE"; /** * map-remove-by-value operator for the operate() method * */ public const OP_MAP_REMOVE_BY_VALUE = "OP_MAP_REMOVE_BY_VALUE"; /** * map-remove-by-value operator for the operate() method * */ public const OP_MAP_REMOVE_BY_VALUE_RANGE = "OP_MAP_REMOVE_BY_VALUE_RANGE"; /** * map-remove-by-value-list operator for the operate() method * */ public const OP_MAP_REMOVE_BY_VALUE_LIST = "OP_MAP_REMOVE_BY_VALUE_LIST"; /** * map-remove-by-index operator for the operate() method * */ public const OP_MAP_REMOVE_BY_INDEX = "OP_MAP_REMOVE_BY_INDEX"; /** * map-remove-by-index-range operator for the operate() method * */ public const OP_MAP_REMOVE_BY_INDEX_RANGE = "OP_MAP_REMOVE_BY_INDEX_RANGE"; /** * map-remove-by-rank operator for the operate() method * */ public const OP_MAP_REMOVE_BY_RANK = "OP_MAP_REMOVE_BY_RANK"; /** * map-remove-by-rank-range operator for the operate() method * */ public const OP_MAP_REMOVE_BY_RANK_RANGE = "OP_MAP_REMOVE_BY_RANK_RANGE"; // Query Predicate Operators /** * predicate operator for equality check of scalar integer or string value * * @see Aerospike::predicateEquals */ public const OP_EQ = "="; /** * predicate operator matching whether an integer falls between a range of integer values * * @see Aerospike::predicateBetween */ public const OP_BETWEEN = "BETWEEN"; /** * predicate operator for a whether a specific value is in an indexed list, mapkeys, or mapvalues * * @see Aerospike::predicateContains */ public const OP_CONTAINS = "CONTAINS"; /** * predicate operator for whether an indexed list, mapkeys, or mapvalues has an integer value within a specified range * * @see Aerospike::predicateRange */ public const OP_RANGE = "RANGE"; /** * geospatial predicate operator for points within a specified region * */ public const OP_GEOWITHINREGION = "GEOWITHIN"; /** * geospatial predicate operator for regons containing a sepcified point * */ public const OP_GEOCONTAINSPOINT = "GEOCONTAINS"; /** * Scan status is undefined */ #[Deprecated('use JOB_STATUS_UNDEF along with jobInfo()')] public const SCAN_STATUS_UNDEF = "SCAN_STATUS_UNDEF"; /** * Scan is currently running */ #[Deprecated('use JOB_STATUS_INPROGRESS along with jobInfo()')] public const SCAN_STATUS_INPROGRESS = "SCAN_STATUS_INPROGRESS"; /** * Scan completed successfully */ #[Deprecated] public const SCAN_STATUS_ABORTED = "SCAN_STATUS_ABORTED"; /** * Scan was aborted due to failure or the user */ #[Deprecated('use JOB_STATUS_COMPLETED along with jobInfo()')] public const SCAN_STATUS_COMPLETED = "SCAN_STATUS_COMPLETED"; // Status values returned by jobInfo() /** * Job status is undefined */ public const JOB_STATUS_UNDEF = "JOB_STATUS_UNDEF"; /** * Job is currently running */ public const JOB_STATUS_INPROGRESS = "JOB_STATUS_INPROGRESS"; /** * Job completed successfully */ public const JOB_STATUS_COMPLETED = "JOB_STATUS_COMPLETED"; // Index (container) types /** * The bin being indexed should contain scalar values such as string or integer * */ public const INDEX_TYPE_DEFAULT = "INDEX_TYPE_DEFAULT"; /** * The bin being indexed should contain a list * */ public const INDEX_TYPE_LIST = "INDEX_TYPE_LIST"; /** * The bin being indexed should contain a map. The map keys will be indexed * */ public const INDEX_TYPE_MAPKEYS = "INDEX_TYPE_MAPKEYS"; /** * The bin being indexed should contain a map. The map values will be indexed * */ public const INDEX_TYPE_MAPVALUES = "INDEX_TYPE_MAPVALUES"; // Data type /** * If and only if the container type matches, the value should be of type string * */ public const INDEX_STRING = "INDEX_STRING"; /** * If and only if the container type matches, the value should be of type integer * */ public const INDEX_NUMERIC = "INDEX_NUMERIC"; /** * If and only if the container type matches, the value should be GeoJSON * */ public const INDEX_GEO2DSPHERE = "INDEX_GEO2DSPHERE"; /** * Declare the UDF module's language to be Lua * */ public const UDF_TYPE_LUA = "UDF_TYPE_LUA"; // Security role privileges /** * Privilege to read data * * @link https://www.aerospike.com/docs/guide/security/access-control.html Access Control */ public const PRIV_READ = "PRIV_READ"; /** * Privilege to read and write data * * @link https://www.aerospike.com/docs/guide/security/access-control.html Access Control */ public const PRIV_READ_WRITE = "PRIV_READ_WRITE"; /** * Privilege to read, write and execute user-defined functions * * @link https://www.aerospike.com/docs/guide/security/access-control.html Access Control */ public const PRIV_READ_WRITE_UDF = "PRIV_READ_WRITE_UDF"; /** * Privilege to create and assign roles to users * * @link https://www.aerospike.com/docs/guide/security/access-control.html Access Control */ public const PRIV_USER_ADMIN = "PRIV_USER_ADMIN"; /** * Privilege to manage indexes and UDFs, monitor and abort scan/query jobs, get server config * * @link https://www.aerospike.com/docs/guide/security/access-control.html Access Control */ public const PRIV_DATA_ADMIN = "PRIV_DATA_ADMIN"; // can perform data admin functions that do not involve user admin /** Privilege to modify dynamic server configs, get config and stats, and all data admin privileges * * @link https://www.aerospike.com/docs/guide/security/access-control.html Access Control */ public const PRIV_SYS_ADMIN = "PRIV_SYS_ADMIN"; // can perform sysadmin functions that do not involve user admin /* // TODO: // security methods public int createRole ( string $role, array $privileges [, array $options ] ) public int grantPrivileges ( string $role, array $privileges [, array $options ] ) public int revokePrivileges ( string $role, array $privileges [, array $options ] ) public int queryRole ( string $role, array &$privileges [, array $options ] ) public int queryRoles ( array &$roles [, array $options ] ) public int dropRole ( string $role [, array $options ] ) public int createUser ( string $user, string $password, array $roles [, array $options ] ) public int setPassword ( string $user, string $password [, array $options ] ) public int changePassword ( string $user, string $password [, array $options ] ) public int grantRoles ( string $user, array $roles [, array $options ] ) public int revokeRoles ( string $user, array $roles [, array $options ] ) public int queryUser ( string $user, array &$roles [, array $options ] ) public int queryUsers ( array &$roles [, array $options ] ) public int dropUser ( string $user [, array $options ] ) */ } *
  • "start" - offset where lock begins
  • *
  • "length" - size of locked area. zero means to end of file
  • *
  • "whence" - Where l_start is relative to: can be SEEK_SET, SEEK_END and SEEK_CUR
  • *
  • "type" - type of lock: can be F_RDLCK (read lock), F_WRLCK (write lock) or F_UNLCK (unlock)
  • * * @return mixed Returns the result of the C call. */ function dio_fcntl($fd, int $cmd, ...$args) {} /** * Opens a file (creating it if necessary) at a lower level than theC library input/ouput stream functions allow * * dio_open ( string $filename , int $flags [, int $mode = 0 ] ) : resource * * @link https://www.php.net/manual/en/function.dio-open.php * @param string $filename The pathname of the file to open. * @param int $flags The flags parameter is a bitwise-ORed value comprising flags from the following list. *
      *
    • O_RDONLY - opens the file for read access.
    • *
    • O_WRONLY - opens the file for write access.
    • *
    • O_RDWR - opens the file for both reading and writing.
    • *
    • O_CREAT - creates the file, if it doesn't already exist.
    • *
    • O_EXCL - if both O_CREAT and O_EXCL are set and the file already exists, dio_open() will fail.
    • *
    • O_TRUNC - if the file exists and is opened for write access, the file will be truncated to zero length.
    • *
    • O_APPEND - write operations write data at the end of the file.
    • *
    • O_NONBLOCK - sets non blocking mode.
    • *
    • O_NOCTTY - prevent the OS from assigning the opened file as the process's controllingterminal when opening a TTY device file.
    • *
    * @param int $mode If flags contains O_CREAT, mode will set the permissions of the file (creation permissions). * @return resource|false A file descriptor or FALSE on error. */ function dio_open(string $filename, int $flags, int $mode = 0) {} /** * Reads bytes from a file descriptor. * * dio_read ( resource $fd [, int $len = 1024 ] ) : string * * @param resource $fd The file descriptor returned by dio_open(). * @param int $len The number of bytes to read. If not specified, dio_read() reads 1k sized block. * @return string The bytes read from fd. * @link https://www.php.net/manual/en/function.dio-read.php */ function dio_read($fd, int $len = 1024) {} /** * Seeks to pos on fd from whence * * dio_seek ( resource $fd , int $pos [, int $whence = SEEK_SET ] ): int * * @param resource $fd The file descriptor returned by dio_open(). * @param int $pos The new position. * @param int $whence Specifies how the position pos should be interpreted: *
      *
    • SEEK_SET - (Default) Specifies that pos is specified from the beginning of the file.
    • *
    • SEEK_CUR - Specifies that pos is a count of characters from the current file position. This count may be positive or negative.
    • *
    • SEEK_END - Specifies that pos is a count of characters from the end of the file.
    • *
    * @return int * @link https://www.php.net/manual/en/function.dio-seek.php */ function dio_seek($fd, int $pos, int $whence = SEEK_SET) {} /** * Gets stat information about the file descriptor fd * * dio_stat ( resource $fd ) : array * * @param resource $fd The file descriptor returned by dio_open(). * @return array|null Returns an associative array with the following keys: *
      *
    • "device" - device
    • *
    • "inode" - inode
    • *
    • "mode" - mode
    • *
    • "nlink" - number of hard links
    • *
    • "uid" - user id
    • *
    • "gid" - group id
    • *
    • "device_type" - device type (if inode device)
    • *
    • "size" - total size in bytes
    • *
    • "blocksize" - blocksize
    • *
    • "blocks" - number of blocks allocated
    • *
    • "atime" - time of last access
    • *
    • "mtime" - time of last modification
    • *
    • "ctime" - time of last change
    • *
    * On error dio_stat() returns NULL. * @link https://www.php.net/manual/en/function.dio-stat.php */ function dio_stat($fd) {} /** * Sets terminal attributes and baud rate for a serial port * * dio_tcsetattr ( resource $fd , array $options ) : bool * * @param resource $fd The file descriptor returned by dio_open(). * @param array $options The currently available options are: *
      *
    • "baud" - baud rate of the port - can be 38400, 19200, 9600, 4800, 2400, 1800, 1200, 600, 300, 200, 150, 134, 110, 75 or 50, default value is 9600.
    • *
    • "bits" - data bits - can be 8,7,6 or 5. Default value is 8.
    • *
    • "stop" - stop bits - can be 1 or 2. Default value is 1.
    • *
    • "parity" - can be 0,1 or 2. Default value is 0.
    • *
    * @return void * @link https://www.php.net/manual/en/function.dio-tcsetattr.php */ function dio_tcsetattr($fd, array $options) {} /** * Truncates a file to at most offset bytes in size. * * dio_truncate ( resource $fd , int $offset ) : bool * * If the file previously was larger than this size, the extra data is lost. * If the file previously was shorter, it is unspecified whether the file is left unchanged or is extended. * In the latter case the extended part reads as zero bytes. * @param resource $fd The file descriptor returned by dio_open(). * @param int $offset The offset in bytes. * @return bool Returns TRUE on success or FALSE on failure. * @link https://www.php.net/manual/en/function.dio-truncate.php */ function dio_truncate($fd, int $offset) {} /** * Writes data to fd with optional truncation at length * * dio_write ( resource $fd , string $data [, int $len = 0 ] ) : int * * @link https://www.php.net/manual/en/function.dio-write.php * @param resource $fd The file descriptor returned by dio_open(). * @param string $data The written data. * @param int $len The length of data to write in bytes. If not specified, the function writes all the data to the specified file. * @return int Returns the number of bytes written to fd. */ function dio_write($fd, string $data, int $len = 0) {} /** * Opens a raw direct IO stream. * * dio_raw ( string filename , string mode [, array options] ) : ?resource * * @param string $filename The pathname of the file to open. * @param string $mode The mode parameter specifies the type of access you require to the stream (as fopen()). * @param array|null $options The currently available options are: *
      *
    • "data_rate" - baud rate of the port - can be 75, 110, 134, 150, 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 38400, 57600, 115200, 56000, 128000 or 256000 default value is 9600.
    • *
    • "data_bits" - can be 8, 7, 6 or 5. Default value is 8.
    • *
    • "stop_bits" - can be 1 or 2. Default value is 1.
    • *
    • "parity" - can be 0, 1 or 2. Default value is 0.
    • *
    • "flow_control" - can be 0 or 1. Default value is 1.
    • *
    • "is_canonical" - can be 0 or 1. Default value is 1.
    • *
    * @return resource|null A stream resource or null on error. */ function dio_raw(string $filename, string $mode, ?array $options) {} /** * Opens a serial direct IO stream. * * dio_serial ( string $filename , string $mode [, array $options = null] ) : ?resource * * @param string $filename The pathname of the file to open. * @param string $mode The mode parameter specifies the type of access you require to the stream (as fopen()). * @param array|null $options The currently available options are: *
      *
    • "data_rate" - baud rate of the port - can be 75, 110, 134, 150, 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 38400, 57600, 115200, 56000, 128000 or 256000 default value is 9600.
    • *
    • "data_bits" - can be 8, 7, 6 or 5. Default value is 8.
    • *
    • "stop_bits" - can be 1 or 2. Default value is 1.
    • *
    • "parity" - can be 0, 1 or 2. Default value is 0.
    • *
    • "flow_control" - can be 0 or 1. Default value is 1.
    • *
    • "is_canonical" - can be 0 or 1. Default value is 1.
    • *
    * @return resource|null A stream resource or null on error. */ function dio_serial(string $filename, string $mode, ?array $options) {} * Returns the value of the specified configuration option for the tidy document * @link https://php.net/manual/en/tidy.getopt.php * @param string $option

    * You will find a list with each configuration option and their types * at: http://tidy.sourceforge.net/docs/quickref.html. *

    * @return string|int|bool the value of the specified option. * The return type depends on the type of the specified one. */ #[TentativeType] public function getOpt(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $option): string|int|bool {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Execute configured cleanup and repair operations on parsed markup * @link https://php.net/manual/en/tidy.cleanrepair.php * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function cleanRepair(): bool {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Parse markup in file or URI * @link https://php.net/manual/en/tidy.parsefile.php * @param string $filename

    * If the filename parameter is given, this function * will also read that file and initialize the object with the file, * acting like tidy_parse_file. *

    * @param mixed $config [optional]

    * The config config can be passed either as an * array or as a string. If a string is passed, it is interpreted as the * name of the configuration file, otherwise, it is interpreted as the * options themselves. *

    *

    * For an explanation about each option, see * http://tidy.sourceforge.net/docs/quickref.html. *

    * @param string|null $encoding [optional]

    * The encoding parameter sets the encoding for * input/output documents. The possible values for encoding are: * ascii, latin0, latin1, * raw, utf8, iso2022, * mac, win1252, ibm858, * utf16, utf16le, utf16be, * big5, and shiftjis. *

    * @param bool $useIncludePath [optional]

    * Search for the file in the include_path. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function parseFile( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'array|string|null'], default: '')] $config = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $encoding = null, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $useIncludePath = false ): bool {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Parse a document stored in a string * @link https://php.net/manual/en/tidy.parsestring.php * @param string $string

    * The data to be parsed. *

    * @param mixed $config [optional]

    * The config config can be passed either as an * array or as a string. If a string is passed, it is interpreted as the * name of the configuration file, otherwise, it is interpreted as the * options themselves. *

    *

    * For an explanation about each option, visit http://tidy.sourceforge.net/docs/quickref.html. *

    * @param string|null $encoding [optional]

    * The encoding parameter sets the encoding for * input/output documents. The possible values for encoding are: * ascii, latin0, latin1, * raw, utf8, iso2022, * mac, win1252, ibm858, * utf16, utf16le, utf16be, * big5, and shiftjis. *

    * @return bool a new tidy instance. */ #[TentativeType] public function parseString( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $string, #[LanguageLevelTypeAware(['8.0' => 'array|string|null'], default: '')] $config = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $encoding = null ): bool {} /** * (PHP 5, PECL tidy >= 0.7.0)
    * Repair a string using an optionally provided configuration file * @link https://php.net/manual/en/tidy.repairstring.php * @param string $string

    * The data to be repaired. *

    * @param array|string|null $config [optional]

    * The config config can be passed either as an * array or as a string. If a string is passed, it is interpreted as the * name of the configuration file, otherwise, it is interpreted as the * options themselves. *

    *

    * Check http://tidy.sourceforge.net/docs/quickref.html for * an explanation about each option. *

    * @param string|null $encoding [optional]

    * The encoding parameter sets the encoding for * input/output documents. The possible values for encoding are: * ascii, latin0, latin1, * raw, utf8, iso2022, * mac, win1252, ibm858, * utf16, utf16le, utf16be, * big5, and shiftjis. *

    * @return string|false the repaired string. */ #[TentativeType] public static function repairString( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $string, #[LanguageLevelTypeAware(['8.0' => 'array|string|null'], default: '')] $config = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $encoding = null ): string|false {} /** * (PHP 5, PECL tidy >= 0.7.0)
    * Repair a file and return it as a string * @link https://php.net/manual/en/tidy.repairfile.php * @param string $filename

    * The file to be repaired. *

    * @param array|string|null $config [optional]

    * The config config can be passed either as an * array or as a string. If a string is passed, it is interpreted as the * name of the configuration file, otherwise, it is interpreted as the * options themselves. *

    *

    * Check http://tidy.sourceforge.net/docs/quickref.html for an * explanation about each option. *

    * @param string|null $encoding [optional]

    * The encoding parameter sets the encoding for * input/output documents. The possible values for encoding are: * ascii, latin0, latin1, * raw, utf8, iso2022, * mac, win1252, ibm858, * utf16, utf16le, utf16be, * big5, and shiftjis. *

    * @param bool $useIncludePath [optional]

    * Search for the file in the include_path. *

    * @return string|false the repaired contents as a string. */ #[TentativeType] public static function repairFile( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'array|string|null'], default: '')] $config = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $encoding = null, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $useIncludePath = false ): string|false {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Run configured diagnostics on parsed and repaired markup * @link https://php.net/manual/en/tidy.diagnose.php * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function diagnose(): bool {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Get release date (version) for Tidy library * @link https://php.net/manual/en/tidy.getrelease.php * @return string a string with the release date of the Tidy library. */ #[TentativeType] public function getRelease(): string {} /** * (PHP 5, PECL tidy >= 0.7.0)
    * Get current Tidy configuration * @link https://php.net/manual/en/tidy.getconfig.php * @return array an array of configuration options. *

    *

    * For an explanation about each option, visit http://tidy.sourceforge.net/docs/quickref.html. */ #[TentativeType] public function getConfig(): array {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Get status of specified document * @link https://php.net/manual/en/tidy.getstatus.php * @return int 0 if no error/warning was raised, 1 for warnings or accessibility * errors, or 2 for errors. */ #[TentativeType] public function getStatus(): int {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Get the Detected HTML version for the specified document * @link https://php.net/manual/en/tidy.gethtmlver.php * @return int the detected HTML version. *

    *

    * This function is not yet implemented in the Tidylib itself, so it always * return 0. */ #[TentativeType] public function getHtmlVer(): int {} /** * Returns the documentation for the given option name * @link https://php.net/manual/en/tidy.getoptdoc.php * @param string $option

    * The option name *

    * @return string|false a string if the option exists and has documentation available, or * FALSE otherwise. */ #[TentativeType] public function getOptDoc(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $option): string|false {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Indicates if the document is a XHTML document * @link https://php.net/manual/en/tidy.isxhtml.php * @return bool This function returns TRUE if the specified tidy * object is a XHTML document, or FALSE otherwise. *

    *

    * This function is not yet implemented in the Tidylib itself, so it always * return FALSE. */ #[TentativeType] public function isXhtml(): bool {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Indicates if the document is a generic (non HTML/XHTML) XML document * @link https://php.net/manual/en/tidy.isxml.php * @return bool This function returns TRUE if the specified tidy * object is a generic XML document (non HTML/XHTML), * or FALSE otherwise. *

    *

    * This function is not yet implemented in the Tidylib itself, so it always * return FALSE. */ #[TentativeType] public function isXml(): bool {} /** * (PHP 5, PECL tidy 0.5.2-1.0.0)
    * Returns a tidyNode object representing the root of the tidy parse tree * @link https://php.net/manual/en/tidy.root.php * @return tidyNode|null the tidyNode object. */ #[TentativeType] public function root(): ?tidyNode {} /** * (PHP 5, PECL tidy 0.5.2-1.0.0)
    * Returns a tidyNode object starting from the <head> tag of the tidy parse tree * @link https://php.net/manual/en/tidy.head.php * @return tidyNode|null the tidyNode object. */ #[TentativeType] public function head(): ?tidyNode {} /** * (PHP 5, PECL tidy 0.5.2-1.0.0)
    * Returns a tidyNode object starting from the <html> tag of the tidy parse tree * @link https://php.net/manual/en/tidy.html.php * @return tidyNode|null the tidyNode object. */ #[TentativeType] public function html(): ?tidyNode {} /** * (PHP 5, PECL tidy 0.5.2-1.0)
    * Returns a tidyNode object starting from the <body> tag of the tidy parse tree * @link https://php.net/manual/en/tidy.body.php * @return tidyNode|null a tidyNode object starting from the * <body> tag of the tidy parse tree. */ #[TentativeType] public function body(): ?tidyNode {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Constructs a new tidy object * @link https://php.net/manual/en/tidy.construct.php * @param string $filename [optional]

    * If the filename parameter is given, this function * will also read that file and initialize the object with the file, * acting like tidy_parse_file. *

    * @param mixed $config [optional]

    * The config config can be passed either as an * array or as a string. If a string is passed, it is interpreted as the * name of the configuration file, otherwise, it is interpreted as the * options themselves. *

    *

    * For an explanation about each option, visit http://tidy.sourceforge.net/docs/quickref.html. *

    * @param string|null $encoding [optional]

    * The encoding parameter sets the encoding for * input/output documents. The possible values for encoding are: * ascii, latin0, latin1, * raw, utf8, iso2022, * mac, win1252, ibm858, * utf16, utf16le, utf16be, * big5, and shiftjis. *

    * @param bool $useIncludePath [optional]

    * Search for the file in the include_path. *

    */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $filename = null, #[LanguageLevelTypeAware(['8.0' => 'array|string|null'], default: '')] $config = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $encoding = null, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $useIncludePath = null ) {} } /** * An HTML node in an HTML file, as detected by tidy. * @link https://php.net/manual/en/class.tidynode.php */ final class tidyNode { /** *

    The HTML representation of the node, including the surrounding tags.

    * @var string */ public readonly string $value; /** *

    The name of the HTML node

    * @var string */ public readonly string $name; /** *

    The type of the tag (one of the constants above, e.g. TIDY_NODETYPE_PHP)

    * @var int */ public readonly int $type; /** *

    The line number at which the tags is located in the file

    * @var int */ public readonly int $line; /** *

    The column number at which the tags is located in the file

    * @var int */ public readonly int $column; /** *

    Indicates if the node is a proprietary tag

    * @var bool */ public readonly bool $proprietary; /** *

    The ID of the tag (one of the constants above, e.g. TIDY_TAG_FRAME)

    * @var int|null */ public readonly ?int $id; /** *

    * An array of string, representing * the attributes names (as keys) of the current node. *

    * @var array|null */ public readonly ?array $attribute; /** *

    * An array of tidyNode, representing * the children of the current node. *

    * @var array|null */ public readonly ?array $child; /** * Checks if a node has children * @link https://php.net/manual/en/tidynode.haschildren.php * @return bool TRUE if the node has children, FALSE otherwise. * @since 5.0.1 */ public function hasChildren():bool {} /** * Checks if a node has siblings * @link https://php.net/manual/en/tidynode.hassiblings.php * @return bool TRUE if the node has siblings, FALSE otherwise. * @since 5.0.1 */ public function hasSiblings(): bool {} /** * Checks if a node represents a comment * @link https://php.net/manual/en/tidynode.iscomment.php * @return bool TRUE if the node is a comment, FALSE otherwise. * @since 5.0.1 */ public function isComment():bool {} /** * Checks if a node is part of a HTML document * @link https://php.net/manual/en/tidynode.ishtml.php * @return bool TRUE if the node is part of a HTML document, FALSE otherwise. * @since 5.0.1 */ public function isHtml(): bool {} /** * Checks if a node represents text (no markup) * @link https://php.net/manual/en/tidynode.istext.php * @return bool TRUE if the node represent a text, FALSE otherwise. * @since 5.0.1 */ public function isText(): bool {} /** * Checks if this node is JSTE * @link https://php.net/manual/en/tidynode.isjste.php * @return bool TRUE if the node is JSTE, FALSE otherwise. * @since 5.0.1 */ public function isJste(): bool {} /** * Checks if this node is ASP * @link https://php.net/manual/en/tidynode.isasp.php * @return bool TRUE if the node is ASP, FALSE otherwise. * @since 5.0.1 */ public function isAsp(): bool {} /** * Checks if a node is PHP * @link https://php.net/manual/en/tidynode.isphp.php * @return bool TRUE if the current node is PHP code, FALSE otherwise. * @since 5.0.1 */ public function isPhp(): bool {} /** * Returns the parent node of the current node * @link https://php.net/manual/en/tidynode.getparent.php * @return tidyNode|null a tidyNode if the node has a parent, or NULL * otherwise. * @since 5.2.2 */ public function getParent(): ?tidyNode {} private function __construct() {} } /** * (PHP 5, PECL tidy >= 0.5.2)
    * Returns the value of the specified configuration option for the tidy document * @link https://php.net/manual/en/tidy.getopt.php * @param tidy $tidy

    * The Tidy object. *

    * @param string $option

    * You will find a list with each configuration option and their types * at: http://tidy.sourceforge.net/docs/quickref.html. *

    * @return string|int|bool the value of the specified option. * The return type depends on the type of the specified one. */ function tidy_getopt(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy, string $option):string|int|bool {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Parse a document stored in a string * @link https://php.net/manual/en/tidy.parsestring.php * @param string $string

    * The data to be parsed. *

    * @param mixed $config [optional]

    * The config config can be passed either as an * array or as a string. If a string is passed, it is interpreted as the * name of the configuration file, otherwise, it is interpreted as the * options themselves. *

    *

    * For an explanation about each option, visit http://tidy.sourceforge.net/docs/quickref.html. *

    * @param string|null $encoding [optional]

    * The encoding parameter sets the encoding for * input/output documents. The possible values for encoding are: * ascii, latin0, latin1, * raw, utf8, iso2022, * mac, win1252, ibm858, * utf16, utf16le, utf16be, * big5, and shiftjis. *

    * @return tidy|false a new tidy instance. */ function tidy_parse_string(string $string, array|string|null $config = null, null|string $encoding = null):tidy|false {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Parse markup in file or URI * @link https://php.net/manual/en/tidy.parsefile.php * @param string $filename

    * If the filename parameter is given, this function * will also read that file and initialize the object with the file, * acting like tidy_parse_file. *

    * @param mixed $config [optional]

    * The config config can be passed either as an * array or as a string. If a string is passed, it is interpreted as the * name of the configuration file, otherwise, it is interpreted as the * options themselves. *

    *

    * For an explanation about each option, see * http://tidy.sourceforge.net/docs/quickref.html. *

    * @param string|null $encoding [optional]

    * The encoding parameter sets the encoding for * input/output documents. The possible values for encoding are: * ascii, latin0, latin1, * raw, utf8, iso2022, * mac, win1252, ibm858, * utf16, utf16le, utf16be, * big5, and shiftjis. *

    * @param bool $useIncludePath [optional]

    * Search for the file in the include_path. *

    * @return tidy|false a new tidy instance. */ function tidy_parse_file(string $filename, array|string|null $config = null, null|string $encoding = null, bool $useIncludePath = false):tidy|false {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Return a string representing the parsed tidy markup * @link https://php.net/manual/en/function.tidy-get-output.php * @param tidy $tidy

    * The Tidy object. *

    * @return string the parsed tidy markup. */ function tidy_get_output(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):string {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Return warnings and errors which occurred parsing the specified document * @link https://php.net/manual/en/tidy.props.errorbuffer.php * @param tidy $tidy

    * The Tidy object. *

    * @return string|false the error buffer as a string. */ function tidy_get_error_buffer(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):string|false {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Execute configured cleanup and repair operations on parsed markup * @link https://php.net/manual/en/tidy.cleanrepair.php * @param tidy $tidy The Tidy object. * @return bool TRUE on success or FALSE on failure. */ function tidy_clean_repair(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):bool {} /** * (PHP 5, PECL tidy >= 0.7.0)
    * Repair a string using an optionally provided configuration file * @link https://php.net/manual/en/tidy.repairstring.php * @param string $string

    * The data to be repaired. *

    * @param mixed $config [optional]

    * The config config can be passed either as an * array or as a string. If a string is passed, it is interpreted as the * name of the configuration file, otherwise, it is interpreted as the * options themselves. *

    *

    * Check http://tidy.sourceforge.net/docs/quickref.html for * an explanation about each option. *

    * @param string|null $encoding [optional]

    * The encoding parameter sets the encoding for * input/output documents. The possible values for encoding are: * ascii, latin0, latin1, * raw, utf8, iso2022, * mac, win1252, ibm858, * utf16, utf16le, utf16be, * big5, and shiftjis. *

    * @return string|false the repaired string. */ function tidy_repair_string(string $string, array|string|null $config = null, null|string $encoding = null):string|false {} /** * (PHP 5, PECL tidy >= 0.7.0)
    * Repair a file and return it as a string * @link https://php.net/manual/en/tidy.repairfile.php * @param string $filename

    * The file to be repaired. *

    * @param mixed $config [optional]

    * The config config can be passed either as an * array or as a string. If a string is passed, it is interpreted as the * name of the configuration file, otherwise, it is interpreted as the * options themselves. *

    *

    * Check http://tidy.sourceforge.net/docs/quickref.html for an * explanation about each option. *

    * @param string|null $encoding [optional]

    * The encoding parameter sets the encoding for * input/output documents. The possible values for encoding are: * ascii, latin0, latin1, * raw, utf8, iso2022, * mac, win1252, ibm858, * utf16, utf16le, utf16be, * big5, and shiftjis. *

    * @param bool $useIncludePath [optional]

    * Search for the file in the include_path. *

    * @return string|false the repaired contents as a string. */ function tidy_repair_file(string $filename, array|string|null $config = null, null|string $encoding = null, bool $useIncludePath = false):string|false {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Run configured diagnostics on parsed and repaired markup * @link https://php.net/manual/en/tidy.diagnose.php * @param tidy $tidy

    * The Tidy object. *

    * @return bool TRUE on success or FALSE on failure. */ function tidy_diagnose(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):bool {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Get release date (version) for Tidy library * @link https://php.net/manual/en/tidy.getrelease.php * @return string a string with the release date of the Tidy library. */ function tidy_get_release():string {} /** * (PHP 5, PECL tidy >= 0.7.0)
    * Get current Tidy configuration * @link https://php.net/manual/en/tidy.getconfig.php * @param tidy $tidy

    * The Tidy object. *

    * @return array an array of configuration options. *

    * For an explanation about each option, visit http://tidy.sourceforge.net/docs/quickref.html. *

    */ function tidy_get_config(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):array {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Get status of specified document * @link https://php.net/manual/en/tidy.getstatus.php * @param tidy $tidy

    * The Tidy object. *

    * @return int 0 if no error/warning was raised, 1 for warnings or accessibility * errors, or 2 for errors. */ function tidy_get_status(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):int {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Get the Detected HTML version for the specified document * @link https://php.net/manual/en/tidy.gethtmlver.php * @param tidy $tidy

    * The Tidy object. *

    * @return int the detected HTML version. *

    * This function is not yet implemented in the Tidylib itself, so it always * return 0. *

    */ function tidy_get_html_ver(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):int {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Indicates if the document is a XHTML document * @link https://php.net/manual/en/tidy.isxhtml.php * @param tidy $tidy

    * The Tidy object. *

    * @return bool This function returns TRUE if the specified tidy * object is a XHTML document, or FALSE otherwise. *

    *

    * This function is not yet implemented in the Tidylib itself, so it always * return FALSE. */ function tidy_is_xhtml(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):bool {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Indicates if the document is a generic (non HTML/XHTML) XML document * @link https://php.net/manual/en/tidy.isxml.php * @param tidy $tidy

    * The Tidy object. *

    * @return bool This function returns TRUE if the specified tidy * object is a generic XML document (non HTML/XHTML), * or FALSE otherwise. *

    *

    * This function is not yet implemented in the Tidylib itself, so it always * return FALSE. */ function tidy_is_xml(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):bool {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Returns the Number of Tidy errors encountered for specified document * @link https://php.net/manual/en/function.tidy-error-count.php * @param tidy $tidy

    * The Tidy object. *

    * @return int the number of errors. */ function tidy_error_count(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy): int {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Returns the Number of Tidy warnings encountered for specified document * @link https://php.net/manual/en/function.tidy-warning-count.php * @param tidy $tidy

    * The Tidy object. *

    * @return int the number of warnings. */ function tidy_warning_count(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):int {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Returns the Number of Tidy accessibility warnings encountered for specified document * @link https://php.net/manual/en/function.tidy-access-count.php * @param tidy $tidy

    * The Tidy object. *

    * @return int the number of warnings. */ function tidy_access_count(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy): int {} /** * (PHP 5, PECL tidy >= 0.5.2)
    * Returns the Number of Tidy configuration errors encountered for specified document * @link https://php.net/manual/en/function.tidy-config-count.php * @param tidy $tidy

    * The Tidy object. *

    * @return int the number of errors. */ function tidy_config_count(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):int {} /** * Returns the documentation for the given option name * @link https://php.net/manual/en/tidy.getoptdoc.php * @param tidy $tidy

    * The Tidy object. *

    * @param string $option

    * The option name *

    * @return string|false a string if the option exists and has documentation available, or * FALSE otherwise. */ function tidy_get_opt_doc(tidy $tidy, string $option):string|false {} /** * (PHP 5, PECL tidy 0.5.2-1.0.0)
    * Returns a tidyNode object representing the root of the tidy parse tree * @link https://php.net/manual/en/tidy.root.php * @param tidy $tidy

    * The Tidy object. *

    * @return tidyNode|null the tidyNode object. */ function tidy_get_root(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):?tidyNode {} /** * (PHP 5, PECL tidy 0.5.2-1.0.0)
    * Returns a tidyNode object starting from the <head> tag of the tidy parse tree * @link https://php.net/manual/en/tidy.head.php * @param tidy $tidy

    * The Tidy object. *

    * @return tidyNode|null the tidyNode object. */ function tidy_get_head(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):?tidyNode {} /** * (PHP 5, PECL tidy 0.5.2-1.0.0)
    * Returns a tidyNode object starting from the <html> tag of the tidy parse tree * @link https://php.net/manual/en/tidy.html.php * @param tidy $tidy

    * The Tidy object. *

    * @return tidyNode|null the tidyNode object. */ function tidy_get_html(#[PhpStormStubsElementAvailable(from: '8.0')] tidy $tidy):?tidyNode {} /** * (PHP 5, PECL tidy 0.5.2-1.0)
    * Returns a tidyNode object starting from the <body> tag of the tidy parse tree * @link https://php.net/manual/en/tidy.body.php * @param tidy $tidy

    * The Tidy object. *

    * @return tidyNode|null a tidyNode object starting from the * <body> tag of the tidy parse tree. */ function tidy_get_body(tidy $tidy): ?tidyNode {} /** * ob_start callback function to repair the buffer * @link https://php.net/manual/en/function.ob-tidyhandler.php * @param string $input

    * The buffer. *

    * @param int $mode [optional]

    * The buffer mode. *

    * @return string the modified buffer. */ function ob_tidyhandler($input, $mode = null) {} /** * description * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_TAG_UNKNOWN', 0); define('TIDY_TAG_A', 1); define('TIDY_TAG_ABBR', 2); define('TIDY_TAG_ACRONYM', 3); define('TIDY_TAG_ADDRESS', 4); define('TIDY_TAG_ALIGN', 5); define('TIDY_TAG_APPLET', 6); define('TIDY_TAG_AREA', 7); define('TIDY_TAG_B', 8); define('TIDY_TAG_BASE', 9); define('TIDY_TAG_BASEFONT', 10); define('TIDY_TAG_BDO', 11); define('TIDY_TAG_BGSOUND', 12); define('TIDY_TAG_BIG', 13); define('TIDY_TAG_BLINK', 14); define('TIDY_TAG_BLOCKQUOTE', 15); define('TIDY_TAG_BODY', 16); define('TIDY_TAG_BR', 17); define('TIDY_TAG_BUTTON', 18); define('TIDY_TAG_CAPTION', 19); define('TIDY_TAG_CENTER', 20); define('TIDY_TAG_CITE', 21); define('TIDY_TAG_CODE', 22); define('TIDY_TAG_COL', 23); define('TIDY_TAG_COLGROUP', 24); define('TIDY_TAG_COMMENT', 25); define('TIDY_TAG_DD', 26); define('TIDY_TAG_DEL', 27); define('TIDY_TAG_DFN', 28); define('TIDY_TAG_DIR', 29); define('TIDY_TAG_DIV', 30); define('TIDY_TAG_DL', 31); define('TIDY_TAG_DT', 32); define('TIDY_TAG_EM', 33); define('TIDY_TAG_EMBED', 34); define('TIDY_TAG_FIELDSET', 35); define('TIDY_TAG_FONT', 36); define('TIDY_TAG_FORM', 37); define('TIDY_TAG_FRAME', 38); define('TIDY_TAG_FRAMESET', 39); define('TIDY_TAG_H1', 40); define('TIDY_TAG_H2', 41); define('TIDY_TAG_H3', 42); define('TIDY_TAG_H4', 43); define('TIDY_TAG_H5', 44); define('TIDY_TAG_H6', 45); define('TIDY_TAG_HEAD', 46); define('TIDY_TAG_HR', 47); define('TIDY_TAG_HTML', 48); define('TIDY_TAG_I', 49); define('TIDY_TAG_IFRAME', 50); define('TIDY_TAG_ILAYER', 51); define('TIDY_TAG_IMG', 52); define('TIDY_TAG_INPUT', 53); define('TIDY_TAG_INS', 54); define('TIDY_TAG_ISINDEX', 55); define('TIDY_TAG_KBD', 56); define('TIDY_TAG_KEYGEN', 57); define('TIDY_TAG_LABEL', 58); define('TIDY_TAG_LAYER', 59); define('TIDY_TAG_LEGEND', 60); define('TIDY_TAG_LI', 61); define('TIDY_TAG_LINK', 62); define('TIDY_TAG_LISTING', 63); define('TIDY_TAG_MAP', 64); define('TIDY_TAG_MARQUEE', 65); define('TIDY_TAG_MENU', 66); define('TIDY_TAG_META', 67); define('TIDY_TAG_MULTICOL', 68); define('TIDY_TAG_NOBR', 69); define('TIDY_TAG_NOEMBED', 70); define('TIDY_TAG_NOFRAMES', 71); define('TIDY_TAG_NOLAYER', 72); define('TIDY_TAG_NOSAVE', 73); define('TIDY_TAG_NOSCRIPT', 74); define('TIDY_TAG_OBJECT', 75); define('TIDY_TAG_OL', 76); define('TIDY_TAG_OPTGROUP', 77); define('TIDY_TAG_OPTION', 78); define('TIDY_TAG_P', 79); define('TIDY_TAG_PARAM', 80); define('TIDY_TAG_PLAINTEXT', 81); define('TIDY_TAG_PRE', 82); define('TIDY_TAG_Q', 83); define('TIDY_TAG_RB', 84); define('TIDY_TAG_RBC', 85); define('TIDY_TAG_RP', 86); define('TIDY_TAG_RT', 87); define('TIDY_TAG_RTC', 88); define('TIDY_TAG_RUBY', 89); define('TIDY_TAG_S', 90); define('TIDY_TAG_SAMP', 91); define('TIDY_TAG_SCRIPT', 92); define('TIDY_TAG_SELECT', 93); define('TIDY_TAG_SERVER', 94); define('TIDY_TAG_SERVLET', 95); define('TIDY_TAG_SMALL', 96); define('TIDY_TAG_SPACER', 97); define('TIDY_TAG_SPAN', 98); define('TIDY_TAG_STRIKE', 99); define('TIDY_TAG_STRONG', 100); define('TIDY_TAG_STYLE', 101); define('TIDY_TAG_SUB', 102); define('TIDY_TAG_SUP', 103); define('TIDY_TAG_TABLE', 104); define('TIDY_TAG_TBODY', 105); define('TIDY_TAG_TD', 106); define('TIDY_TAG_TEXTAREA', 107); define('TIDY_TAG_TFOOT', 108); define('TIDY_TAG_TH', 109); define('TIDY_TAG_THEAD', 110); define('TIDY_TAG_TITLE', 111); define('TIDY_TAG_TR', 112); define('TIDY_TAG_TT', 113); define('TIDY_TAG_U', 114); define('TIDY_TAG_UL', 115); define('TIDY_TAG_VAR', 116); define('TIDY_TAG_WBR', 117); define('TIDY_TAG_XMP', 118); /** * @since 7.4 */ define('TIDY_TAG_ARTICLE', 123); /** * @since 7.4 */ define('TIDY_TAG_ASIDE', 124); /** * @since 7.4 */ define('TIDY_TAG_AUDIO', 125); /** * @since 7.4 */ define('TIDY_TAG_BDI', 126); /** * @since 7.4 */ define('TIDY_TAG_CANVAS', 127); /** * @since 7.4 */ define('TIDY_TAG_COMMAND', 128); /** * @since 7.4 */ define('TIDY_TAG_DATALIST', 129); /** * @since 7.4 */ define('TIDY_TAG_DETAILS', 130); /** * @since 7.4 */ define('TIDY_TAG_DIALOG', 131); /** * @since 7.4 */ define('TIDY_TAG_FIGCAPTION', 132); /** * @since 7.4 */ define('TIDY_TAG_FIGURE', 133); /** * @since 7.4 */ define('TIDY_TAG_FOOTER', 134); /** * @since 7.4 */ define('TIDY_TAG_HEADER', 135); /** * @since 7.4 */ define('TIDY_TAG_HGROUP', 136); /** * @since 7.4 */ define('TIDY_TAG_MAIN', 137); /** * @since 7.4 */ define('TIDY_TAG_MARK', 138); /** * @since 7.4 */ define('TIDY_TAG_MENUITEM', 139); /** * @since 7.4 */ define('TIDY_TAG_METER', 140); /** * @since 7.4 */ define('TIDY_TAG_NAV', 141); /** * @since 7.4 */ define('TIDY_TAG_OUTPUT', 142); /** * @since 7.4 */ define('TIDY_TAG_PROGRESS', 143); /** * @since 7.4 */ define('TIDY_TAG_SECTION', 144); /** * @since 7.4 */ define('TIDY_TAG_SOURCE', 145); /** * @since 7.4 */ define('TIDY_TAG_SUMMARY', 146); /** * @since 7.4 */ define('TIDY_TAG_TEMPLATE', 147); /** * @since 7.4 */ define('TIDY_TAG_TIME', 148); /** * @since 7.4 */ define('TIDY_TAG_TRACK', 149); /** * @since 7.4 */ define('TIDY_TAG_VIDEO', 150); /** * root node * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_ROOT', 0); /** * doctype * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_DOCTYPE', 1); /** * HTML comment * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_COMMENT', 2); /** * Processing Instruction * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_PROCINS', 3); /** * Text * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_TEXT', 4); /** * start tag * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_START', 5); /** * end tag * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_END', 6); /** * empty tag * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_STARTEND', 7); /** * CDATA * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_CDATA', 8); /** * XML section * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_SECTION', 9); /** * ASP code * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_ASP', 10); /** * JSTE code * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_JSTE', 11); /** * PHP code * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_PHP', 12); /** * XML declaration * @link https://php.net/manual/en/tidy.constants.php */ define('TIDY_NODETYPE_XMLDECL', 13); // End of tidy v.2.0 * XML response returned by XMLRPC method. *

    * @param string $encoding [optional]

    * Input encoding supported by iconv. *

    * @return mixed either an array, or an integer, or a string, or a boolean according * to the response returned by the XMLRPC method. */ function xmlrpc_decode($xml, $encoding = "iso-8859-1") {} /** * Decodes XML into native PHP types * @link https://php.net/manual/en/function.xmlrpc-decode-request.php * @param string $xml * @param string &$method * @param string $encoding [optional] * @return mixed */ function xmlrpc_decode_request($xml, &$method, $encoding = null) {} /** * Generates XML for a method request * @link https://php.net/manual/en/function.xmlrpc-encode-request.php * @param string $method

    * Name of the method to call. *

    * @param mixed $params

    * Method parameters compatible with method signature. *

    * @param null|array $output_options [optional]

    * Array specifying output options may contain (default values are * emphasised): * output_type: php, xml

    * @return string a string containing the XML representation of the request. */ function xmlrpc_encode_request($method, $params, ?array $output_options = null) {} /** * Gets xmlrpc type for a PHP value * @link https://php.net/manual/en/function.xmlrpc-get-type.php * @param mixed $value

    * PHP value *

    * @return string the XML-RPC type. */ function xmlrpc_get_type($value) {} /** * Sets xmlrpc type, base64 or datetime, for a PHP string value * @link https://php.net/manual/en/function.xmlrpc-set-type.php * @param string &$value

    * Value to set the type *

    * @param string $type

    * 'base64' or 'datetime' *

    * @return bool TRUE on success or FALSE on failure. * If successful, value is converted to an object. */ function xmlrpc_set_type(&$value, $type) {} /** * Determines if an array value represents an XMLRPC fault * @link https://php.net/manual/en/function.xmlrpc-is-fault.php * @param array $arg

    * Array returned by xmlrpc_decode. *

    * @return bool TRUE if the argument means fault, FALSE otherwise. Fault * description is available in $arg["faultString"], fault * code is in $arg["faultCode"]. */ function xmlrpc_is_fault(array $arg) {} /** * Creates an xmlrpc server * @link https://php.net/manual/en/function.xmlrpc-server-create.php * @return resource */ function xmlrpc_server_create() {} /** * Destroys server resources * @link https://php.net/manual/en/function.xmlrpc-server-destroy.php * @param resource $server * @return int */ function xmlrpc_server_destroy($server) {} /** * Register a PHP function to resource method matching method_name * @link https://php.net/manual/en/function.xmlrpc-server-register-method.php * @param resource $server * @param string $method_name * @param callable $function * @return bool */ function xmlrpc_server_register_method($server, $method_name, $function) {} /** * Parses XML requests and call methods * @link https://php.net/manual/en/function.xmlrpc-server-call-method.php * @param resource $server * @param string $xml * @param mixed $user_data * @param null|array $output_options [optional] * @return string */ function xmlrpc_server_call_method($server, $xml, $user_data, ?array $output_options = null) {} /** * Decodes XML into a list of method descriptions * @link https://php.net/manual/en/function.xmlrpc-parse-method-descriptions.php * @param string $xml * @return array */ function xmlrpc_parse_method_descriptions($xml) {} /** * Adds introspection documentation * @link https://php.net/manual/en/function.xmlrpc-server-add-introspection-data.php * @param resource $server * @param array $desc * @return int */ function xmlrpc_server_add_introspection_data($server, array $desc) {} /** * Register a PHP function to generate documentation * @link https://php.net/manual/en/function.xmlrpc-server-register-introspection-callback.php * @param resource $server * @param string $function * @return bool */ function xmlrpc_server_register_introspection_callback($server, $function) {} // End of xmlrpc v.0.51 setProperty('report', 'true'). * * @return XdmNode */ public function getValidationReport() {} /** * Set the parameters required for XQuery Processor * * @param string $name * @param XdmValue $value * @return void */ public function setParameter($name, $value) {} /** * Set properties for Schema Validator. * * @param string $name * @param string $value * @return void */ public function setProperty($name, $value) {} /** * Clear parameter values set * * @return void */ public function clearParameters() {} /** * Clear property values set * * @return void */ public function clearProperties() {} /** * Clear any exception thrown * * @return void */ public function exceptionClear() {} /** * Get the $i'th error code if there are any errors * * @param int $i * @return string */ public function getErrorCode($i) {} /** * Get the $i'th error message if there are any errors * * @param int $i * @return string */ public function getErrorMessage($i) {} /** * Get number of error during execution of the validator * * @return int */ public function getExceptionCount() {} } /** * @link https://www.saxonica.com/saxon-c/documentation/index.html#!api/saxon_c_php_api/saxon_c_php_xdmvalue */ class XdmValue { /** * Get the first item in the sequence * * @return XdmItem */ public function getHead() {} /** * Get the n'th item in the value, counting from zero * * @param int $index * @return XdmItem */ public function itemAt($index) {} /** * Get the number of items in the sequence * * @return int */ public function size() {} /** * Add item to the sequence at the end. * * @param XdmItem $item */ public function addXdmItem($item) {} } /** * @link https://www.saxonica.com/saxon-c/documentation/index.html#!api/saxon_c_php_api/saxon_c_php_xdmitem */ class XdmItem extends XdmValue { /** * Get the string value of the item. For a node, this gets the string value of the node. For an atomic value, it has the same effect as casting the value to a string. In all cases the result is the same as applying the XPath string() function. * * @return string */ public function getStringValue() {} /** * Determine whether the item is a node value or not. * * @return bool */ public function isNode() {} /** * Determine whether the item is an atomic value or not. * * @return bool */ public function isAtomic() {} /** * Provided the item is an atomic value we return the {@link XdmAtomicValue} otherwise return null * * @return XdmAtomicValue|null */ public function getAtomicValue() {} /** * Provided the item is a node value we return the {@link XdmNode} otherwise return null * * @return XdmNode|null */ public function getNodeValue() {} } /** * @link https://www.saxonica.com/saxon-c/documentation/index.html#!api/saxon_c_php_api/saxon_c_php_xdmnode */ class XdmNode extends XdmItem { /** * Get the string value of the item. For a node, this gets the string value of the node. * * @return string */ public function getStringValue() {} /** * Get the kind of node * * @return int */ public function getNodeKind() {} /** * Get the name of the node, as a EQName * * @return string */ public function getNodeName() {} /** * Determine whether the item is an atomic value or a node. This method will return FALSE as the item is not atomic * * @return false */ public function isAtomic() {} /** * Get the count of child node at this current node * * @return int */ public function getChildCount() {} /** * Get the count of attribute nodes at this node * * @return int */ public function getAttributeCount() {} /** * Get the n'th child node at this node. If the child node selected does not exist then return null * * @param int $index * @return XdmNode|null */ public function getChildNode($index) {} /** * Get the parent of this node. If parent node does not exist then return null * * @return XdmNode|null */ public function getParent() {} /** * Get the n'th attribute node at this node. If the attribute node selected does not exist then return null * * @param int $index * @return XdmNode|null */ public function getAttributeNode($index) {} /** * Get the n'th attribute node value at this node. If the attribute node selected does not exist then return null * * @param int $index * @return string|null */ public function getAttributeValue($index) {} } /** * @link https://www.saxonica.com/saxon-c/documentation/index.html#!api/saxon_c_php_api/saxon_c_php_xdmatomicvalue */ class XdmAtomicValue extends XdmItem { /** * Get the string value of the item. For an atomic value, it has the same effect as casting the value to a string. In all cases the result is the same as applying the XPath string() function. * * @return string */ public function getStringValue() {} /** * Get the value converted to a boolean using the XPath casting rules * * @return bool */ public function getBooleanValue() {} /** * Get the value converted to a float using the XPath casting rules. If the value is a string, the XSD 1.1 rules are used, which means that the string "+INF" is recognised * * @return float */ public function getDoubleValue() {} /** * Get the value converted to an integer using the XPath casting rules * * @return int */ public function getLongValue() {} /** * Determine whether the item is an atomic value or a node. Return TRUE if the item is an atomic value * * @return true */ public function isAtomic() {} } */ // start of PECL/rrd v1.0 /** * Gets latest error message * @link https://php.net/manual/en/function.rrd-error.php * @return string Latest error message. * @since PECL rrd >= 0.9.0 */ function rrd_error() {} /** * Creates rrd database file * @link https://php.net/manual/en/function.rrd-create.php * @param string $filename

    * Filename for newly created rrd file. *

    * @param array $options

    * Options for rrd create - list of strings. See man page of rrd create for whole list of options. *

    * @return bool TRUE on success or FALSE on failure. * @since PECL rrd >= 0.9.0 */ function rrd_create($filename, $options) {} /** * Gets data for graph output from RRD database file as array. This function has same result as rrd_graph(), but fetched data are returned as array, no image file is created. * @link https://php.net/manual/en/function.rrd-fetch.php * @param string $file

    * RRD database file name. *

    * @param array $options

    * Array of options for resolution specification. *

    * @return array Array with information about retrieved graph data. * @since PECL rrd >= 0.9.0 */ function rrd_fetch($file, $options) {} /** * Gets the timestamp of the first sample from from the specified RRA of the RRD file. * @link https://php.net/manual/en/function.rrd-first.php * @param string $file

    * RRD database file name. *

    * @param int $raaindex

    * The index number of the RRA that is to be examined. Default value is 0. *

    * @return int|false Integer as unix timestamp, FALSE if some error occurs. * @since PECL rrd >= 0.9.0 */ function rrd_first($file, $raaindex = 0) {} /** * Creates image from a data. * @link https://php.net/manual/en/function.rrd-graph.php * @param string $file

    * The filename to output the graph to. This will generally end in either .png, .svg or .eps, depending on the format you want to output. *

    * @param array $options

    * Options for generating image. See man page of rrd graph for all possible options. All options (data definitions, variable definitions, etc.) are allowed. *

    * @return array|false If image is created successfully an array with information about generated image is returned, FALSE when error occurs. * @since PECL rrd >= 0.9.0 */ function rrd_graph($file, $options) {} /** * Returns information about particular RRD database file. * @link https://php.net/manual/en/function.rrd-info.php * @param string $file

    * RRD database file name. *

    * @return array|false Array with information about requsted RRD file, FALSE when error occurs. * @since PECL rrd >= 0.9.0 */ function rrd_info($file) {} /** * Returns the UNIX timestamp of the most recent update of the RRD database. * @link https://php.net/manual/en/function.rrd-last.php * @param string $file

    * RRD database file name. *

    * @return int Integer as unix timestamp of the most recent data from the RRD database. * @since PECL rrd >= 0.9.0 */ function rrd_last($file) {} /** * Gets array of the UNIX timestamp and the values stored for each date in the most recent update of the RRD database file. * @link https://php.net/manual/en/function.rrd-lastupdate.php * @param string $file

    * RRD database file name. *

    * @return array|false Array of information about last update, FALSE when error occurs. * @since PECL rrd >= 0.9.0 */ function rrd_lastupdate($file) {} /** * Restores the RRD file from the XML dump. * @link https://php.net/manual/en/function.rrd-restore.php * @param string $xml_file

    * XML filename with the dump of the original RRD database file. *

    * @param string $rrd_file

    * Restored RRD database file name. *

    * @param array $options

    * Array of options for restoring. See man page for rrd restore. *

    * @return bool Returns TRUE on success, FALSE otherwise. * @since PECL rrd >= 0.9.0 */ function rrd_restore($xml_file, $rrd_file, $options = []) {} /** * Change some options in the RRD dabase header file. E.g. renames the source for the data etc. * @link https://php.net/manual/en/function.rrd-tune.php * @param string $file

    * RRD database file name. *

    * @param array $options

    * Options with RRD database file properties which will be changed. See rrd tune man page for details. *

    * @return bool Returns TRUE on success, FALSE otherwise. * @since PECL rrd >= 0.9.0 */ function rrd_tune($file, $options) {} /** * Updates the RRD database file. The input data is time interpolated according to the properties of the RRD database file. * @link https://php.net/manual/en/function.rrd-update.php * @param string $file

    * RRD database file name. This database will be updated. *

    * @param array $options

    * Options for updating the RRD database. This is list of strings. See man page of rrd update for whole list of options. *

    * @return bool Updates the RRD database file. The input data is time interpolated according to the properties of the RRD database file. * @since PECL rrd >= 0.9.0 */ function rrd_update($file, $options) {} /** * Returns information about underlying rrdtool library. * @link https://php.net/manual/en/function.rrd-version.php * @return string String with rrdtool version number e.g. "1.4.3". * @since PECL rrd >= 1.0.0 */ function rrd_version() {} /** * Exports the information about RRD database file. This data can be converted to XML file via user space PHP script and then restored back as RRD database file. * @link https://php.net/manual/en/function.rrd-xport.php * @param array $options

    * Array of options for the export, see rrd xport man page. *

    * @return array|false Array with information about RRD database file, FALSE when error occurs. * @since PECL rrd >= 0.9.0 */ function rrd_xport($options) {} /** * Close any outstanding connection to rrd caching daemon

    * This function is automatically called when the whole PHP process is terminated. It depends on used SAPI. For example, it's called automatically at the end of command line script.

    * It's up user whether he wants to call this function at the end of every request or otherwise.

    * @link https://php.net/manual/en/function.rrdc-disconnect.php * @return void * @since PECL rrd >= 1.1.2 */ function rrd_disconnect() {} /** * Close any outstanding connection to rrd caching daemon. * This function is automatically called when the whole PHP process is terminated. It depends on used SAPI. * For example, it's called automatically at the end of command line script. * It's up user whether he wants to call this function at the end of every request or otherwise. */ function rrdc_disconnect() {} /** * Class for creation of RRD database file. * @link https://php.net/manual/en/class.rrdcreator.php * @since PECL rrd >= 0.9.0 */ class RRDCreator { /** * Adds RRA - archive of data values for each data source.

    * Archive consists of a number of data values or statistics for each of the defined data-sources (DS). Data sources are defined by method RRDCreator::addDataSource(). You need call this method for each requested archive. *

    * @link https://php.net/manual/en/rrdcreator.addarchive.php * @see RRDCreator::addDataSource() * @param string $description

    * Class for creation of RRD database file. *

    * @return void * @since PECL rrd >= 0.9.0 */ public function addArchive($description) {} /** * Adds data source definition for RRD database.

    * RRD can accept input from several data sources (DS), e.g incoming and outgoing traffic. This method adds data source by description. You need call this method for each data source. *

    * @link https://php.net/manual/en/rrdcreator.adddatasource.php * @param string $description

    * Definition of data source - DS. This has same format as DS definition in rrd create command. See man page of rrd create for more details. *

    * @return void * @since PECL rrd >= 0.9.0 */ public function addDataSource($description) {} /** * Creates new RRDCreator instance. * @link https://php.net/manual/en/rrdcreator.construct.php * @param string $path

    * Path for newly created RRD database file. *

    * @param string $startTime

    * Time for the first value in RRD database. Parameter supports all formats which are supported by rrd create call. *

    * @param int $step

    * Base interval in seconds with which data will be fed into the RRD database. *

    * @since PECL rrd >= 0.9.0 */ public function __construct($path, $startTime = '', $step = 0) {} /** * Saves the RRD database into file, which name is defined by RRDCreator::__construct() * @link https://php.net/manual/en/rrdcreator.save.php * @see RRDCreator::__construct() * @return bool TRUE on success or FALSE on failure. * @since PECL rrd >= 0.9.0 */ public function save() {} } /** * Class for exporting data from RRD database to image file. * @link https://php.net/manual/en/class.rrdgraph.php * @since PECL rrd >= 0.9.0 */ class RRDGraph { /** * Creates new RRDGraph instance. This instance is responsible for rendering the result of RRD database query into image. * @link https://php.net/manual/en/rrdgraph.construct.php * @param string $path

    * Full path for the newly created image. *

    * @since PECL rrd >= 0.9.0 */ public function __construct($path) {} /** * Saves the result of RRD database query into image defined by RRDGraph::__construct(). * @link https://php.net/manual/en/rrdgraph.save.php * @return array|false Array with information about generated image is returned, FALSE if error occurs. * @since PECL rrd >= 0.9.0 */ public function save() {} /** * Saves the RRD database query into image and returns the verbose information about generated graph.

    * If "-" is used as image filename, image data are also returned in result array. *

    * @link https://php.net/manual/en/rrdgraph.saveverbose.php * @return array|false Array with detailed information about generated image is returned, optionally with image data, FALSE if error occurs. * @since PECL rrd >= 0.9.0 */ public function saveVerbose() {} /** * Sets the options for rrd graph export * @link https://php.net/manual/en/rrdgraph.setoptions.php * @param array $options

    * List of options for the image generation from the RRD database file. It can be list of strings or list of strings with keys for better readability. Read the rrd graph man pages for list of available options. *

    * @return void * @since PECL rrd >= 0.9.0 */ public function setOptions($options) {} } /** * Class for updating RDD database file. * @link https://php.net/manual/en/class.rrdupdater.php * @since PECL rrd >= 0.9.0 */ class RRDUpdater { /** * Creates new RRDUpdater instance. This instance is responsible for updating the RRD database file. * RRDUpdater constructor. * @link https://php.net/manual/en/rrdupdater.construct.php * @param string $path

    * Filesystem path for RRD database file, which will be updated. *

    * @since PECL rrd >= 0.9.0 */ public function __construct($path) {} /** * Update the RRD file defined via RRDUpdater::__construct(). The file is updated with a specific values. * @link https://php.net/manual/en/rrdupdater.update.php * @param array $values

    * Data for update. Key is data source name. *

    * @param string $time

    * Time value for updating the RRD with a particulat data. Default value is current time. *

    * @return bool TRUE on success or FALSE on failure. * @throws \Exception on error * @since PECL rrd >= 0.9.0 */ public function update($values, $time = '') {} } // end of PECL/rrd v1.0 getCode(). * This can be compared against the `SIMDJSON_ERR_*` constants. * * Before simdjson 2.1.0, a regular RuntimeException with an error code of 0 was thrown. */ class SimdJsonException extends RuntimeException {} /** * Thrown for error conditions on fields such as $depth that are not expected to be * from user-provided JSON, with similar behavior to php 8.0. * * NOTE: https://www.php.net/valueerror was added in php 8.0. * In older php versions, this extends Error instead. * * When support for php 8.0 is dropped completely, * a major release of simdjson will likely switch to a standard ValueError. */ class SimdJsonValueError extends ValueError {} CURLSSH_AUTH_PUBLICKEY, * CURLSSH_AUTH_PASSWORD, * CURLSSH_AUTH_HOST, * CURLSSH_AUTH_KEYBOARD. Set to * CURLSSH_AUTH_ANY to let libcurl pick one. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSH_AUTH_TYPES', 151); /** * TRUE tells the library to perform all the required proxy authentication * and connection setup, but no data transfer. This option is implemented for * HTTP, SMTP and POP3. * @since 5.5 * @link https://php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_CONNECT_ONLY', 141); /** * With the CURLOPT_FOLLOWLOCATION option disabled: * redirect URL found in the last transaction, that should be requested manually next. * With the CURLOPT_FOLLOWLOCATION option enabled: * this is empty. The redirect URL in this case is available in CURLINFO_EFFECTIVE_URL * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 5.3.7 */ define('CURLINFO_REDIRECT_URL', 1048607); /** * IP address of the most recent connection * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 5.4.7 */ define('CURLINFO_PRIMARY_IP', 1048608); /** * Destination port of the most recent connection * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 5.4.7 */ define('CURLINFO_PRIMARY_PORT', 2097192); /** * Local (source) IP address of the most recent connection * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 5.4.7 */ define('CURLINFO_LOCAL_IP', 1048617); /** * Local (source) port of the most recent connection * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 5.4.7 */ define('CURLINFO_LOCAL_PORT', 2097194); /** * A result of {@see curl_share_init()}. Makes the cURL handle to use the data from the shared handle. * @link https://php.net/manual/en/function.curl-setopt.php * @since 5.5 */ define('CURLOPT_SHARE', 10100); /** * Allows an application to select what kind of IP addresses to use when resolving host names. * This is only interesting when using host names that resolve addresses using more than one version of IP, * possible values are CURL_IPRESOLVE_WHATEVER, CURL_IPRESOLVE_V4, CURL_IPRESOLVE_V6, by default CURL_IPRESOLVE_WHATEVER. * @link https://php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_IPRESOLVE', 113); /** * Value for the CURLOPT_IPRESOLVE option. * Default, resolves addresses to all IP versions that your system allows. * @link https://www.php.net/manual/en/function.curl-setopt.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_IPRESOLVE.html */ define('CURL_IPRESOLVE_WHATEVER', 0); /** * Value for the CURLOPT_IPRESOLVE option. * Resolve to IPv4 addresses. * @link https://www.php.net/manual/en/function.curl-setopt.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_IPRESOLVE.html */ define('CURL_IPRESOLVE_V4', 1); /** * Value for the CURLOPT_IPRESOLVE option. * Resolve to IPv6 addresses. * @link https://www.php.net/manual/en/function.curl-setopt.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_IPRESOLVE.html */ define('CURL_IPRESOLVE_V6', 2); /** * TRUE to use a global DNS cache. This option is not thread-safe. * It is conditionally enabled by default if PHP is built for non-threaded use (CLI, FCGI, Apache2-Prefork, etc.). * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_DNS_USE_GLOBAL_CACHE', 91); /** * The number of seconds to keep DNS entries in memory. * This option is set to 120 (2 minutes) by default. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_DNS_CACHE_TIMEOUT', 92); /** * An alternative port number to connect to. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_PORT', 3); /** * The file that the transfer should be written to. The default is STDOUT (the browser window). * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FILE', 10001); /** * Custom pointer passed to the read callback. * If you use the CURLOPT_READFUNCTION option, this is the pointer you'll get as input in the 4th argument to the callback. * @link https://www.php.net/manual/en/function.curl-setopt.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_READDATA.html */ define('CURLOPT_READDATA', 10009); /** * The file that the transfer should be read from when uploading. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_INFILE', 10009); /** * The expected size, in bytes, of the file when uploading a file to a remote site. * Note that using this option will not stop libcurl from sending more data, as exactly what is sent depends on CURLOPT_READFUNCTION. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_INFILESIZE', 14); /** * The URL to fetch. This can also be set when initializing a session with {@see curl_init()}. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_URL', 10002); /** * The HTTP proxy to tunnel requests through. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_PROXY', 10004); /** * TRUE to output verbose information. * Writes output to STDERR, or the file specified using CURLOPT_STDERR. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_VERBOSE', 41); /** * TRUE to include the header in the output. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_HEADER', 42); /** * An array of HTTP header fields to set, in the format array('Content-type: text/plain', 'Content-length: 100') * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_HTTPHEADER', 10023); /** * TRUE to disable the progress meter for cURL transfers. * (PHP automatically sets this option to TRUE, this should only be changed for debugging purposes.) * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_NOPROGRESS', 43); /** * A callback accepting five parameters. * The first is the cURL resource, * the second is the total number of bytes expected to be downloaded in this transfer, * the third is the number of bytes downloaded so far, * the fourth is the total number of bytes expected to be uploaded in this transfer, * and the fifth is the number of bytes uploaded so far. * (The callback is only called when the CURLOPT_NOPROGRESS option is set to FALSE.) * Return a non-zero value to abort the transfer. In which case, the transfer will set a CURLE_ABORTED_BY_CALLBACK error. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.3 */ define('CURLOPT_PROGRESSFUNCTION', 20056); /** * TRUE to exclude the body from the output. Request method is then set to HEAD. Changing this to FALSE does not change it to GET. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_NOBODY', 44); /** * TRUE to fail verbosely if the HTTP code returned is greater than or equal to 400. * The default behavior is to return the page normally, ignoring the code. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FAILONERROR', 45); /** * TRUE to prepare for an upload. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_UPLOAD', 46); /** * TRUE to do a regular HTTP POST. * This POST is the normal application/x-www-form-urlencoded kind, most commonly used by HTML forms. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_POST', 47); /** * TRUE to only list the names of an FTP directory. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FTPLISTONLY', 48); /** * TRUE to append to the remote file instead of overwriting it. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FTPAPPEND', 50); /** * TRUE to scan the ~/.netrc file to find a username and password for the remote site that a connection is being established with. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_NETRC', 51); /** * A bitmask of 1 (301 Moved Permanently), 2 (302 Found) and 4 (303 See Other) if the HTTP POST method should be maintained * when CURLOPT_FOLLOWLOCATION is set and a specific type of redirect occurs. * @link https://secure.php.net/manual/en/function.curl-setopt.php * @since 5.3.2 */ define('CURLOPT_POSTREDIR', 161); /** * TRUE to output SSL certification information to STDERR on secure transfers. * Requires CURLOPT_VERBOSE to be on to have an effect. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.3.2 */ define('CURLOPT_CERTINFO', 172); /** * An alias of CURLOPT_TRANSFERTEXT. Use that instead. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FTPASCII', -1); /** * TRUE to be completely silent with regards to the cURL functions. * @link https://www.php.net/manual/en/function.curl-setopt.php * @deprecated use CURLOPT_RETURNTRANSFER instead since cURL 7.15.5 */ define('CURLOPT_MUTE', -1); /** * Bitmask of CURLPROTO_* values. If used, this bitmask limits what protocols libcurl may use in the transfer. * This allows you to have a libcurl built to support a wide range of protocols but still limit specific transfers * to only be allowed to use a subset of them. * By default libcurl will accept all protocols it supports. See also CURLOPT_REDIR_PROTOCOLS. * Valid protocol options are: * CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_FTP, CURLPROTO_FTPS, CURLPROTO_SCP, CURLPROTO_SFTP, * CURLPROTO_TELNET, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_TFTP, * CURLPROTO_ALL * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.2.10 */ define('CURLOPT_PROTOCOLS', 181); /** * Bitmask of CURLPROTO_* values. If used, this bitmask limits what protocols libcurl may use in a transfer * that it follows to in a redirect when CURLOPT_FOLLOWLOCATION is enabled. * This allows you to limit specific transfers to only be allowed to use a subset of protocols in redirections. * By default libcurl will allow all protocols except for FILE and SCP. * This is a difference compared to pre-7.19.4 versions which unconditionally would follow to all protocols supported. * See also CURLOPT_PROTOCOLS for protocol constant values. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.2.10 */ define('CURLOPT_REDIR_PROTOCOLS', 182); /** * If a download exceeds this speed (counted in bytes per second) on cumulative average during the transfer, * the transfer will pause to keep the average rate less than or equal to the parameter value. * Defaults to unlimited speed. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.4 */ define('CURLOPT_MAX_RECV_SPEED_LARGE', 30146); /** * If an upload exceeds this speed (counted in bytes per second) on cumulative average during the transfer, * the transfer will pause to keep the average rate less than or equal to the parameter value. * Defaults to unlimited speed. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.4 */ define('CURLOPT_MAX_SEND_SPEED_LARGE', 30145); /** * A callback accepting three parameters. * The first is the cURL resource, the second is a string containing a password prompt, and the third is the maximum password length. * Return the string containing the password. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_PASSWDFUNCTION', -1); /** * TRUE to follow any "Location: " header that the server sends as part of the HTTP header * (note this is recursive, PHP will follow as many "Location: " headers that it is sent, unless CURLOPT_MAXREDIRS is set). * This constant is not available when open_basedir * or safe_mode are enabled. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FOLLOWLOCATION', 52); /** * TRUE to HTTP PUT a file. The file to PUT must be set with CURLOPT_INFILE and CURLOPT_INFILESIZE. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_PUT', 54); /** * A username and password formatted as "[username]:[password]" to use for the connection. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_USERPWD', 10005); /** * A username and password formatted as "[username]:[password]" to use for the connection to the proxy. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_PROXYUSERPWD', 10006); /** * Range(s) of data to retrieve in the format "X-Y" where X or Y are optional. * HTTP transfers also support several intervals, separated with commas in the format "X-Y,N-M". * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_RANGE', 10007); /** * The maximum number of seconds to allow cURL functions to execute. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_TIMEOUT', 13); /** * The maximum number of milliseconds to allow cURL functions to execute. * If libcurl is built to use the standard system name resolver, * that portion of the connect will still use full-second resolution for timeouts with a minimum timeout allowed of one second. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.2 */ define('CURLOPT_TIMEOUT_MS', 155); /** * The full data to post in a HTTP "POST" operation. * To post a file, prepend a filename with @ and use the full path. * The filetype can be explicitly specified by following the filename with the type in the format ';type=mimetype'. * This parameter can either be passed * as a urlencoded string like 'para1=val1¶2=val2&...' * or as an array with the field name as key and field data as value. * If value is an array, the Content-Type header will be set to multipart/form-data. * As of PHP 5.2.0, value must be an array if files are passed to this option with the @ prefix. * As of PHP 5.5.0, the @ prefix is deprecated and files can be sent using CURLFile. * The @ prefix can be disabled for safe passing of values beginning with @ by setting the CURLOPT_SAFE_UPLOAD option to TRUE. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_POSTFIELDS', 10015); /** * The contents of the "Referer: " header to be used in a HTTP request. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_REFERER', 10016); /** * A string containing 32 hexadecimal digits. * The string should be the MD5 checksum of the remote host's public key, and libcurl will reject the connection to the host unless the md5sums match. * This option is only for SCP and SFTP transfers. * @link https://php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSH_HOST_PUBLIC_KEY_MD5', 10162); /** * The file name for your public key. If not used, libcurl defaults to $HOME/.ssh/id_dsa.pub * if the HOME environment variable is set, and just "id_dsa.pub" in the current directory if HOME is not set. * @link https://php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSH_PUBLIC_KEYFILE', 10152); /** * The file name for your private key. If not used, libcurl defaults to $HOME/.ssh/id_dsa * if the HOME environment variable is set, and just "id_dsa" in the current directory if HOME is not set. * If the file is password-protected, set the password with CURLOPT_KEYPASSWD. * @link https://php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSH_PRIVATE_KEYFILE', 10153); /** * The contents of the "User-Agent: " header to be used in a HTTP request. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_USERAGENT', 10018); /** * The value which will be used to get the IP address to use for the FTP "PORT" instruction. * The "PORT" instruction tells the remote server to connect to our specified IP address. * The string may be a plain IP address, a hostname, a network interface name (under Unix), * or just a plain '-' to use the systems default IP address. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FTPPORT', 10017); /** * TRUE to first try an EPSV command for FTP transfers before reverting back to PASV. Set to FALSE to disable EPSV. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FTP_USE_EPSV', 85); /** * The transfer speed, in bytes per second, that the transfer should be below during the count of CURLOPT_LOW_SPEED_TIME seconds * before PHP considers the transfer too slow and aborts. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_LOW_SPEED_LIMIT', 19); /** * The number of seconds the transfer speed should be below CURLOPT_LOW_SPEED_LIMIT * before PHP considers the transfer too slow and aborts. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_LOW_SPEED_TIME', 20); /** * The offset, in bytes, to resume a transfer from. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_RESUME_FROM', 21); /** * The contents of the "Cookie: " header to be used in the HTTP request. * Note that multiple cookies are separated with a semicolon followed by a space (e.g., "fruit=apple; colour=red") * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_COOKIE', 10022); /** * TRUE to mark this as a new cookie "session". * It will force libcurl to ignore all cookies it is about to load that are "session cookies" from the previous session. * By default, libcurl always stores and loads all cookies, independent if they are session cookies or not. * Session cookies are cookies without expiry date and they are meant to be alive and existing for this "session" only. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_COOKIESESSION', 96); /** * TRUE to automatically set the Referer: field in requests where it follows a Location: redirect. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_AUTOREFERER', 58); /** * The name of a file containing a PEM formatted certificate. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSLCERT', 10025); /** * The password required to use the CURLOPT_SSLCERT certificate. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSLCERTPASSWD', 10026); /** * The file that the header part of the transfer is written to. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_WRITEHEADER', 10029); /** * 1 to check the existence of a common name in the SSL peer certificate. (Deprecated) * 2 to check the existence of a common name and also verify that it matches the hostname provided. * 0 to not check the names. In production environments the value of this option should be kept at 2 (default value). * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSL_VERIFYHOST', 81); /** * The name of the file containing the cookie data. * The cookie file can be in Netscape format, or just plain HTTP-style headers dumped into a file. * If the name is an empty string, no cookies are loaded, but cookie handling is still enabled. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_COOKIEFILE', 10031); /** * One of CURL_SSLVERSION_DEFAULT (0), CURL_SSLVERSION_TLSv1 (1), CURL_SSLVERSION_SSLv2 (2), CURL_SSLVERSION_SSLv3 (3), * CURL_SSLVERSION_TLSv1_0 (4), CURL_SSLVERSION_TLSv1_1 (5) or CURL_SSLVERSION_TLSv1_2 (6). * The maximum TLS version can be set by using one of the CURL_SSLVERSION_MAX_* constants. * It is also possible to OR one of the CURL_SSLVERSION_* constants with one of the CURL_SSLVERSION_MAX_* constants. * CURL_SSLVERSION_MAX_DEFAULT (the maximum version supported by the library), CURL_SSLVERSION_MAX_TLSv1_0, CURL_SSLVERSION_MAX_TLSv1_1, * CURL_SSLVERSION_MAX_TLSv1_2, or CURL_SSLVERSION_MAX_TLSv1_3. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSLVERSION', 32); /** * Value for the CURLOPT_SSLVERSION option. * @link https://www.php.net/manual/en/curl.constants.php */ define('CURL_SSLVERSION_DEFAULT', 0); /** * Value for the CURLOPT_SSLVERSION option. * @link https://www.php.net/manual/en/curl.constants.php */ define('CURL_SSLVERSION_TLSv1', 1); /** * Value for the CURLOPT_SSLVERSION option. * @link https://www.php.net/manual/en/curl.constants.php */ define('CURL_SSLVERSION_SSLv2', 2); /** * Value for the CURLOPT_SSLVERSION option. * @link https://www.php.net/manual/en/curl.constants.php */ define('CURL_SSLVERSION_SSLv3', 3); /** * Value for the CURLOPT_SSLVERSION option. * @link https://www.php.net/manual/en/curl.constants.php * @since 5.6.3 * @since 5.5.19 */ define('CURL_SSLVERSION_TLSv1_0', 4); /** * Value for the CURLOPT_SSLVERSION option. * @link https://www.php.net/manual/en/curl.constants.php * @since 5.6.3 * @since 5.5.19 */ define('CURL_SSLVERSION_TLSv1_1', 5); /** * Value for the CURLOPT_SSLVERSION option. * @link https://www.php.net/manual/en/curl.constants.php * @since 5.6.3 * @since 5.5.19 */ define('CURL_SSLVERSION_TLSv1_2', 6); /** * How CURLOPT_TIMEVALUE is treated. * Use CURL_TIMECOND_IFMODSINCE to return the page only if it has been modified since the time specified in CURLOPT_TIMEVALUE. * If it hasn't been modified, a "304 Not Modified" header will be returned assuming CURLOPT_HEADER is TRUE. * Use CURL_TIMECOND_IFUNMODSINCE for the reverse effect. * CURL_TIMECOND_IFMODSINCE is the default. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_TIMECONDITION', 33); /** * The time in seconds since January 1st, 1970. * The time will be used by CURLOPT_TIMECONDITION. By default, CURL_TIMECOND_IFMODSINCE is used. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_TIMEVALUE', 34); /** * A custom request method to use instead of "GET" or "HEAD" when doing a HTTP request. * This is useful for doing "DELETE" or other, more obscure HTTP requests. * Valid values are things like "GET", "POST", "CONNECT" and so on; i.e. Do not enter a whole HTTP request line here. * For instance, entering "GET /index.html HTTP/1.0\r\n\r\n" would be incorrect. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_CUSTOMREQUEST', 10036); /** * An alternative location to output errors to instead of STDERR. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_STDERR', 10037); /** * TRUE to use ASCII mode for FTP transfers. * For LDAP, it retrieves data in plain text instead of HTML. * On Windows systems, it will not set STDOUT to binary mode. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_TRANSFERTEXT', 53); /** * TRUE to return the transfer as a string of the return value of {@see curl_exec()} instead of outputting it directly. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_RETURNTRANSFER', 19913); /** * An array of FTP commands to execute on the server prior to the FTP request. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_QUOTE', 10028); /** * An array of FTP commands to execute on the server after the FTP request has been performed. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_POSTQUOTE', 10039); /** * The name of the outgoing network interface to use. This can be an interface name, an IP address or a host name. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_INTERFACE', 10062); /** * The KRB4 (Kerberos 4) security level. * Any of the following values (in order from least to most powerful) are valid: "clear", "safe", "confidential", "private". * If the string does not match one of these, "private" is used. * Setting this option to NULL will disable KRB4 security. Currently KRB4 security only works with FTP transactions. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_KRB4LEVEL', 10063); /** * TRUE to tunnel through a given HTTP proxy. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_HTTPPROXYTUNNEL', 61); /** * TRUE to attempt to retrieve the modification date of the remote document. * This value can be retrieved using the CURLINFO_FILETIME option with {@see curl_getinfo()}. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FILETIME', 69); /** * A callback accepting two parameters. The first is the cURL resource, and the second is a string with the data to be written. * The data must be saved by this callback. It must return the exact number of bytes written or the transfer will be aborted with an error. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_WRITEFUNCTION', 20011); /** * A callback accepting three parameters. * The first is the cURL resource, * the second is a stream resource provided to cURL through the option CURLOPT_INFILE, * and the third is the maximum amount of data to be read. * The callback must return a string with a length equal or smaller than the amount of data requested, typically by reading it from the passed stream resource. * It should return an empty string to signal EOF. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_READFUNCTION', 20012); /** * A callback accepting two parameters. The first is the cURL resource, the second is a string with the header data to be written. * The header data must be written by this callback. Return the number of bytes written. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_HEADERFUNCTION', 20079); /** * The maximum amount of HTTP redirections to follow. Use this option alongside CURLOPT_FOLLOWLOCATION. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_MAXREDIRS', 68); /** * The maximum amount of persistent connections that are allowed. * When the limit is reached, CURLOPT_CLOSEPOLICY is used to determine which connection to close. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_MAXCONNECTS', 71); /** * This option is deprecated, as it was never implemented in cURL and never had any effect. * @link https://www.php.net/manual/en/function.curl-setopt.php * @removed 5.6 */ define('CURLOPT_CLOSEPOLICY', 72); /** * TRUE to force the use of a new connection instead of a cached one. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FRESH_CONNECT', 74); /** * TRUE to force the connection to explicitly close when it has finished processing, and not be pooled for reuse. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FORBID_REUSE', 75); /** * A filename to be used to seed the random number generator for SSL. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_RANDOM_FILE', 10076); /** * Like CURLOPT_RANDOM_FILE, except a filename to an Entropy Gathering Daemon socket. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_EGDSOCKET', 10077); /** * The number of seconds to wait while trying to connect. Use 0 to wait indefinitely. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_CONNECTTIMEOUT', 78); /** * The number of milliseconds to wait while trying to connect. Use 0 to wait indefinitely. * If libcurl is built to use the standard system name resolver, that portion of the connect * will still use full-second resolution for timeouts with a minimum timeout allowed of one second. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.2.3 */ define('CURLOPT_CONNECTTIMEOUT_MS', 156); /** * FALSE to stop cURL from verifying the peer's certificate. * Alternate certificates to verify against can be specified with the CURLOPT_CAINFO option or * a certificate directory can be specified with the CURLOPT_CAPATH option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSL_VERIFYPEER', 64); /** * The name of a file holding one or more certificates to verify the peer with. * This only makes sense when used in combination with CURLOPT_SSL_VERIFYPEER. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_CAINFO', 10065); /** * A directory that holds multiple CA certificates. Use this option alongside CURLOPT_SSL_VERIFYPEER. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_CAPATH', 10097); /** * The name of a file to save all internal cookies to when the handle is closed, e.g. after a call to curl_close. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_COOKIEJAR', 10082); /** * A list of ciphers to use for SSL. For example, RC4-SHA and TLSv1 are valid cipher lists. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSL_CIPHER_LIST', 10083); /** * TRUE to return the raw output when CURLOPT_RETURNTRANSFER is used. * @link https://www.php.net/manual/en/function.curl-setopt.php * @deprecated 5.1.3 */ define('CURLOPT_BINARYTRANSFER', 19914); /** * TRUE to ignore any cURL function that causes a signal to be sent to the PHP process. * This is turned on by default in multi-threaded SAPIs so timeout options can still be used. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_NOSIGNAL', 99); /** * Either CURLPROXY_HTTP (default), CURLPROXY_SOCKS4, CURLPROXY_SOCKS5, CURLPROXY_SOCKS4A or CURLPROXY_SOCKS5_HOSTNAME. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_PROXYTYPE', 101); /** * The size of the buffer to use for each read. There is no guarantee this request will be fulfilled, however. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_BUFFERSIZE', 98); /** * TRUE to reset the HTTP request method to GET. Since GET is the default, this is only necessary if the request method has been changed. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_HTTPGET', 80); /** * CURL_HTTP_VERSION_NONE (default, lets CURL decide which version to use), * CURL_HTTP_VERSION_1_0 (forces HTTP/1.0), CURL_HTTP_VERSION_1_1 (forces HTTP/1.1), CURL_HTTP_VERSION_2_0 (attempts HTTP 2), * CURL_HTTP_VERSION_2 (alias of CURL_HTTP_VERSION_2_0), CURL_HTTP_VERSION_2TLS (attempts HTTP 2 over TLS (HTTPS) only) or * CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE (issues non-TLS HTTP requests using HTTP/2 without HTTP/1.1 Upgrade). * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_HTTP_VERSION', 84); /** * The name of a file containing a private SSL key. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSLKEY', 10087); /** * The key type of the private SSL key specified in CURLOPT_SSLKEY. * Supported key types are "PEM" (default), "DER", and "ENG". * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSLKEYTYPE', 10088); /** * The secret password needed to use the private SSL key specified in CURLOPT_SSLKEY. * (Since this option contains a sensitive password, remember to keep the PHP script it is contained within safe) * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSLKEYPASSWD', 10026); /** * The identifier for the crypto engine of the private SSL key specified in CURLOPT_SSLKEY. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSLENGINE', 10089); /** * The identifier for the crypto engine used for asymmetric crypto operations. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSLENGINE_DEFAULT', 90); /** * The format of the certificate. * Supported formats are "PEM" (default), "DER", and "ENG". As of OpenSSL 0.9.3, "P12" (for PKCS#12-encoded files) is also supported. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_SSLCERTTYPE', 10086); /** * TRUE to convert Unix newlines to CRLF newlines on transfers. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_CRLF', 27); /** * The contents of the "Accept-Encoding: " header. This enables decoding of the response. * Supported encodings are "identity", "deflate", and "gzip". * If an empty string, "", is set, a header containing all supported encoding types is sent. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_ENCODING', 10102); /** * The port number of the proxy to connect to. This port number can also be set in CURLOPT_PROXY. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_PROXYPORT', 59); /** * TRUE to keep sending the username and password when following locations * (using CURLOPT_FOLLOWLOCATION), even when the hostname has changed. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_UNRESTRICTED_AUTH', 105); /** * TRUE to use EPRT (and LPRT) when doing active FTP downloads. Use FALSE to disable EPRT and LPRT and use PORT only. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FTP_USE_EPRT', 106); /** * TRUE to disable TCP's Nagle algorithm, which tries to minimize the number of small packets on the network. * @link https://php.net/manual/en/curl.constants.php * @since 5.2.1 */ define('CURLOPT_TCP_NODELAY', 121); /** * An array of HTTP 200 responses that will be treated as valid responses and not as errors. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_HTTP200ALIASES', 10104); /** * Value for the CURLOPT_TIMECONDITION option. * Return the page only if it has been modified since the time specified in CURLOPT_TIMEVALUE. * @link https://www.php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_TIMECONDITION.html */ define('CURL_TIMECOND_IFMODSINCE', 1); /** * Value for the CURLOPT_TIMECONDITION option. * Return the page if it hasn't been modified since the time specified in CURLOPT_TIMEVALUE. * @link https://www.php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_TIMECONDITION.html */ define('CURL_TIMECOND_IFUNMODSINCE', 2); /** * Value for the CURLOPT_TIMECONDITION option. * @link https://www.php.net/manual/en/curl.constants.php */ define('CURL_TIMECOND_LASTMOD', 3); /** * The HTTP authentication method(s) to use. * The options are: CURLAUTH_BASIC, CURLAUTH_DIGEST, CURLAUTH_GSSNEGOTIATE, CURLAUTH_NTLM, CURLAUTH_ANY, and CURLAUTH_ANYSAFE. * The bitwise | (or) operator can be used to combine more than one method. * If this is done, cURL will poll the server to see what methods it supports and pick the best one. * CURLAUTH_ANY is an alias for CURLAUTH_BASIC | CURLAUTH_DIGEST | CURLAUTH_GSSNEGOTIATE | CURLAUTH_NTLM. * CURLAUTH_ANYSAFE is an alias for CURLAUTH_DIGEST | CURLAUTH_GSSNEGOTIATE | CURLAUTH_NTLM. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_HTTPAUTH', 107); /** * Value for the CURLOPT_HTTPAUTH option. * Allows username/password authentication. * @link https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html */ define('CURLAUTH_BASIC', 1); /** * Value for the CURLOPT_HTTPAUTH option. * @link https://www.php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html */ define('CURLAUTH_DIGEST', 2); /** * Value for the CURLOPT_HTTPAUTH option. * @link https://www.php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html */ define('CURLAUTH_GSSNEGOTIATE', 4); /** * Value for the CURLOPT_HTTPAUTH option. * @link https://www.php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html */ define('CURLAUTH_NTLM', 8); /** * Value for the CURLOPT_HTTPAUTH option. * Is an alias for CURLAUTH_BASIC | CURLAUTH_DIGEST | CURLAUTH_GSSNEGOTIATE | CURLAUTH_NTLM. * @link https://www.php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html */ define('CURLAUTH_ANY', -17); /** * Value for the CURLOPT_HTTPAUTH option. * Is an alias for CURLAUTH_DIGEST | CURLAUTH_GSSNEGOTIATE | CURLAUTH_NTLM. * @link https://www.php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html */ define('CURLAUTH_ANYSAFE', -18); /** * The HTTP authentication method(s) to use for the proxy connection. * Use the same bitmasks as described in CURLOPT_HTTPAUTH. * For proxy authentication, only CURLAUTH_BASIC and CURLAUTH_NTLM are currently supported. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_PROXYAUTH', 111); /** * TRUE to create missing directories when an FTP operation encounters a path that currently doesn't exist. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_FTP_CREATE_MISSING_DIRS', 110); /** * Any data that should be associated with this cURL handle. * This data can subsequently be retrieved with the CURLINFO_PRIVATE option of {@see curl_getinfo()}. cURL does nothing with this data. * When using a cURL multi handle, this private data is typically a unique key to identify a standard cURL handle. * @link https://php.net/manual/en/curl.constants.php * @since 5.2.4 */ define('CURLOPT_PRIVATE', 10103); /** * The last response code * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_RESPONSE_CODE', 2097154); /** * The CONNECT response code * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_HTTP_CONNECTCODE', 2097174); /** * Bitmask indicating the authentication method(s) available according to the previous response * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_HTTPAUTH_AVAIL', 2097175); /** * Bitmask indicating the proxy authentication method(s) available according to the previous response * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_PROXYAUTH_AVAIL', 2097176); /** * Errno from a connect failure. The number is OS and system specific. * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_OS_ERRNO', 2097177); /** * Number of connections curl had to create to achieve the previous transfer * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_NUM_CONNECTS', 2097178); /** * OpenSSL crypto-engines supported * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_SSL_ENGINES', 4194331); /** * All known cookies * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_COOKIELIST', 4194332); /** * Entry path in FTP server * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_FTP_ENTRY_PATH', 1048606); /** * Time in seconds it took from the start until the SSL/SSH connect/handshake to the remote host was completed * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_APPCONNECT_TIME', 3145761); /** * TLS certificate chain * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_CERTINFO', 4194338); /** * Info on unmet time conditional * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_CONDITION_UNMET', 2097187); /** * Next RTSP client CSeq * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_RTSP_CLIENT_CSEQ', 2097189); /** * Recently received CSeq * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_RTSP_CSEQ_RECV', 2097191); /** * Next RTSP server CSeq * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_RTSP_SERVER_CSEQ', 2097190); /** * RTSP session ID * @link https://php.net/manual/en/function.curl-getinfo.php * @since 5.5 */ define('CURLINFO_RTSP_SESSION_ID', 1048612); /** * Value for the CURLOPT_CLOSEPOLICY option. * @link https://www.php.net/manual/en/curl.constants.php * @removed 5.6 */ define('CURLCLOSEPOLICY_LEAST_RECENTLY_USED', 2); /** * Value for the CURLOPT_CLOSEPOLICY option. * @link https://www.php.net/manual/en/curl.constants.php * @removed 5.6 */ define('CURLCLOSEPOLICY_LEAST_TRAFFIC', 3); /** * Value for the CURLOPT_CLOSEPOLICY option. * @link https://www.php.net/manual/en/curl.constants.php * @removed 5.6 */ define('CURLCLOSEPOLICY_SLOWEST', 4); /** * Value for the CURLOPT_CLOSEPOLICY option. * @link https://www.php.net/manual/en/curl.constants.php * @removed 5.6 */ define('CURLCLOSEPOLICY_CALLBACK', 5); /** * Value for the CURLOPT_CLOSEPOLICY option. * @link https://www.php.net/manual/en/curl.constants.php * @removed 5.6 */ define('CURLCLOSEPOLICY_OLDEST', 1); /** * Last effective URL * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_EFFECTIVE_URL', 1048577); /** * As of PHP 5.5.0 and cURL 7.10.8, this is a legacy alias of CURLINFO_RESPONSE_CODE. * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_HTTP_CODE', 2097154); /** * Total size of all headers received * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_HEADER_SIZE', 2097163); /** * Total size of issued requests, currently only for HTTP requests * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_REQUEST_SIZE', 2097164); /** * Total transaction time in seconds for last transfer * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_TOTAL_TIME', 3145731); /** * Time in seconds until name resolving was complete * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_NAMELOOKUP_TIME', 3145732); /** * Time in seconds it took to establish the connection * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_CONNECT_TIME', 3145733); /** * Time in seconds from start until just before file transfer begins * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_PRETRANSFER_TIME', 3145734); /** * Total number of bytes uploaded * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_SIZE_UPLOAD', 3145735); /** * Total number of bytes downloaded * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_SIZE_DOWNLOAD', 3145736); /** * Average download speed * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_SPEED_DOWNLOAD', 3145737); /** * Average upload speed * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_SPEED_UPLOAD', 3145738); /** * Remote time of the retrieved document, with the CURLOPT_FILETIME enabled; * if -1 is returned the time of the document is unknown * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_FILETIME', 2097166); /** * Result of SSL certification verification requested by setting CURLOPT_SSL_VERIFYPEER * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_SSL_VERIFYRESULT', 2097165); /** * Content length of download, read from Content-Length: field * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_CONTENT_LENGTH_DOWNLOAD', 3145743); /** * Specified size of upload * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_CONTENT_LENGTH_UPLOAD', 3145744); /** * Time in seconds until the first byte is about to be transferred * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_STARTTRANSFER_TIME', 3145745); /** * Content-Type: of the requested document. NULL indicates server did not send valid Content-Type: header * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_CONTENT_TYPE', 1048594); /** * Time in seconds of all redirection steps before final transaction was started, * with the CURLOPT_FOLLOWLOCATION option enabled * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_REDIRECT_TIME', 3145747); /** * Number of redirects, with the CURLOPT_FOLLOWLOCATION option enabled * @link https://www.php.net/manual/en/function.curl-getinfo.php */ define('CURLINFO_REDIRECT_COUNT', 2097172); /** * TRUE to track the handle's request string * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 5.1.3 */ define('CURLINFO_HEADER_OUT', 2); /** * Private data associated with this cURL handle, previously set with the CURLOPT_PRIVATE option of {@see curl_getinfo()} * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 5.2.4 */ define('CURLINFO_PRIVATE', 1048597); /** * @since 8.3 */ define('CURLINFO_CAPATH', 1048638); /** * @since 8.3 */ define('CURLINFO_CAINFO', 1048637); /** * Supports IPv6 * @link https://php.net/manual/en/curl.constants.php */ define('CURL_VERSION_IPV6', 1); /** * Supports Kerberos V4 (when using FTP) * @link https://php.net/manual/en/curl.constants.php */ define('CURL_VERSION_KERBEROS4', 2); /** * Supports SSL (HTTPS/FTPS) * @link https://php.net/manual/en/curl.constants.php */ define('CURL_VERSION_SSL', 4); /** * Supports HTTP deflate using libz * @link https://php.net/manual/en/curl.constants.php */ define('CURL_VERSION_LIBZ', 8); /** * Will be the most recent age value for the libcurl. * @link https://php.net/manual/en/curl.constants.php */ define('CURLVERSION_NOW', 10); /** * All fine. Proceed as usual. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_OK', 0); /** * @since 8.3 */ define('CURLKHMATCH_OK', 0); /** * @since 8.3 */ define('CURLKHMATCH_MISMATCH', 1); /** * @since 8.3 */ define('CURLKHMATCH_MISSING', 2); /** * @since 8.3 */ define('CURLKHMATCH_LAST', 3); /** * @since 8.3 */ define('CURLOPT_MIME_OPTIONS', 315); /** * @since 8.3 */ define('CURLMIMEOPT_FORMESCAPE', 1); /** * The URL you passed to libcurl used a protocol that this libcurl does not support. * The support might be a compile-time option that you didn't use, * it can be a misspelled protocol string or just a protocol libcurl has no code for. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_UNSUPPORTED_PROTOCOL', 1); /** * Very early initialization code failed. * This is likely to be an internal error or problem, * or a resource problem where something fundamental couldn't get done at init time. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FAILED_INIT', 2); /** * The URL was not properly formatted. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_URL_MALFORMAT', 3); /** * A requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_URL_MALFORMAT_USER', 4); /** * Couldn't resolve proxy. The given proxy host could not be resolved. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_COULDNT_RESOLVE_PROXY', 5); /** * Couldn't resolve host. The given remote host was not resolved. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_COULDNT_RESOLVE_HOST', 6); /** * Failed to connect to host or proxy. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_COULDNT_CONNECT', 7); /** * The server sent data libcurl couldn't parse. * This error code was known as as CURLE_FTP_WEIRD_SERVER_REPLY before 7.51.0. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_WEIRD_SERVER_REPLY', 8); /** * We were denied access to the resource given in the URL. * For FTP, this occurs while trying to change to the remote directory. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_ACCESS_DENIED', 9); /** * While waiting for the server to connect back when an active FTP session is used, * an error code was sent over the control connection or similar. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_USER_PASSWORD_INCORRECT', 10); /** * After having sent the FTP password to the server, libcurl expects a proper reply. * This error code indicates that an unexpected code was returned. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_WEIRD_PASS_REPLY', 11); /** * During an active FTP session while waiting for the server to connect, * the CURLOPT_ACCEPTTIMEOUT_MS (or the internal default) timeout expired. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_WEIRD_USER_REPLY', 12); /** * Libcurl failed to get a sensible result back from the server as a response to either a PASV or a EPSV command. * The server is flawed. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_WEIRD_PASV_REPLY', 13); /** * FTP servers return a 227-line as a response to a PASV command. * If libcurl fails to parse that line, this return code is passed back. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_WEIRD_227_FORMAT', 14); /** * An internal failure to lookup the host used for the new connection. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_CANT_GET_HOST', 15); /** * A problem was detected in the HTTP2 framing layer. * This is somewhat generic and can be one out of several problems, see the error buffer for details. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_CANT_RECONNECT', 16); /** * Received an error when trying to set the transfer mode to binary or ASCII. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_COULDNT_SET_BINARY', 17); /** * A file transfer was shorter or larger than expected. * This happens when the server first reports an expected transfer size, and then delivers data * that doesn't match the previously given size. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_PARTIAL_FILE', 18); /** * This was either a weird reply to a 'RETR' command or a zero byte transfer complete. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_COULDNT_RETR_FILE', 19); /** * After a completed file transfer, the FTP server did not respond a proper * @link https://php.net/manual/en/curl.constants.php */ define('CURLE_FTP_WRITE_ERROR', 20); /** * When sending custom "QUOTE" commands to the remote server, * one of the commands returned an error code that was 400 or higher (for FTP) or otherwise indicated unsuccessful completion of the command. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_QUOTE_ERROR', 21); /** * This is returned if CURLOPT_FAILONERROR is set TRUE and the HTTP server returns an error code that is >= 400. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_HTTP_NOT_FOUND', 22); /** * An error occurred when writing received data to a local file, or an error was returned to libcurl from a write callback. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_WRITE_ERROR', 23); /** * @link https://php.net/manual/en/curl.constants.php */ define('CURLE_MALFORMAT_USER', 24); /** * Failed starting the upload. For FTP, the server typically denied the STOR command. * The error buffer usually contains the server's explanation for this. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_COULDNT_STOR_FILE', 25); /** * There was a problem reading a local file or an error returned by the read callback. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_READ_ERROR', 26); /** * A memory allocation request failed. This is serious badness and things are severely screwed up if this ever occurs. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_OUT_OF_MEMORY', 27); /** * Operation timeout. The specified time-out period was reached according to the conditions. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_OPERATION_TIMEOUTED', 28); /** * libcurl failed to set ASCII transfer type (TYPE A). * @link https://php.net/manual/en/curl.constants.php */ define('CURLE_FTP_COULDNT_SET_ASCII', 29); /** * The FTP PORT command returned error. * This mostly happens when you haven't specified a good enough address for libcurl to use. See CURLOPT_FTPPORT. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_PORT_FAILED', 30); /** * The FTP REST command returned error. This should never happen if the server is sane. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_COULDNT_USE_REST', 31); /** * The FTP SIZE command returned error. SIZE is not a kosher FTP command, * it is an extension and not all servers support it. * @link https://php.net/manual/en/curl.constants.php */ define('CURLE_FTP_COULDNT_GET_SIZE', 32); /** * The server does not support or accept range requests. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_HTTP_RANGE_ERROR', 33); /** * This is an odd error that mainly occurs due to internal confusion. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_HTTP_POST_ERROR', 34); /** * A problem occurred somewhere in the SSL/TLS handshake. * You really want the error buffer and read the message there as it pinpoints the problem slightly more. * Could be certificates (file formats, paths, permissions), passwords, and others. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_SSL_CONNECT_ERROR', 35); /** * The download could not be resumed because the specified offset was out of the file boundary. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_BAD_DOWNLOAD_RESUME', 36); /** * A file given with FILE:// couldn't be opened. * Most likely because the file path doesn't identify an existing file. Did you check file permissions? * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FILE_COULDNT_READ_FILE', 37); /** * LDAP cannot bind. LDAP bind operation failed. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_LDAP_CANNOT_BIND', 38); /** * LDAP search failed. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_LDAP_SEARCH_FAILED', 39); /** * Library not found. The LDAP library was not found. * @link https://php.net/manual/en/curl.constants.php */ define('CURLE_LIBRARY_NOT_FOUND', 40); /** * Function not found. A required zlib function was not found. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FUNCTION_NOT_FOUND', 41); /** * Aborted by callback. A callback returned "abort" to libcurl. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_ABORTED_BY_CALLBACK', 42); /** * A function was called with a bad parameter. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_BAD_FUNCTION_ARGUMENT', 43); /** * This is never returned * @link https://php.net/manual/en/curl.constants.php */ define('CURLE_BAD_CALLING_ORDER', 44); /** * Interface error. A specified outgoing interface could not be used. * Set which interface to use for outgoing connections' source IP address with CURLOPT_INTERFACE. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_HTTP_PORT_FAILED', 45); /** * This is never returned * @link https://php.net/manual/en/curl.constants.php */ define('CURLE_BAD_PASSWORD_ENTERED', 46); /** * Too many redirects. When following redirects, libcurl hit the maximum amount. * Set your limit with CURLOPT_MAXREDIRS. * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_TOO_MANY_REDIRECTS', 47); /** * An option passed to libcurl is not recognized/known. Refer to the appropriate documentation. * This is most likely a problem in the program that uses libcurl. * The error buffer might contain more specific information about which exact option it concerns. * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_UNKNOWN_TELNET_OPTION', 48); /** * A telnet option string was Illegally formatted. * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_TELNET_OPTION_SYNTAX', 49); /** * Currently unused. * @link https://php.net/manual/en/curl.constants.php */ define('CURLE_OBSOLETE', 50); /** * The remote server's SSL certificate or SSH md5 fingerprint was deemed not OK. * This error code has been unified with CURLE_SSL_CACERT since 7.62.0. Its previous value was 51. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_SSL_PEER_CERTIFICATE', 60); /** * Nothing was returned from the server, and under the circumstances, getting nothing is considered an error. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_GOT_NOTHING', 52); /** * The specified crypto engine wasn't found. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_SSL_ENGINE_NOTFOUND', 53); /** * Failed setting the selected SSL crypto engine as default! * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_SSL_ENGINE_SETFAILED', 54); /** * Failed sending network data. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_SEND_ERROR', 55); /** * Failure with receiving network data. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_RECV_ERROR', 56); /** * The share object is currently in use. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_SHARE_IN_USE', 57); /** * Problem with the local client certificate. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_SSL_CERTPROBLEM', 58); /** * Couldn't use specified cipher. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_SSL_CIPHER', 59); /** * The remote server's SSL certificate or SSH md5 fingerprint was deemed not OK. * This error code has been unified with CURLE_SSL_PEER_CERTIFICATE since 7.62.0. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_SSL_CACERT', 60); /** * Unrecognized transfer encoding. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_BAD_CONTENT_ENCODING', 61); /** * Invalid LDAP URL. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_LDAP_INVALID_URL', 62); /** * Maximum file size exceeded. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FILESIZE_EXCEEDED', 63); /** * Requested FTP SSL level failed. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_FTP_SSL_FAILED', 64); /** * Value for the CURLOPT_PROXYTYPE option. * @link https://php.net/manual/en/curl.constants.php */ define('CURLPROXY_HTTP', 0); /** * Value for the CURLOPT_PROXYTYPE option. * @link https://php.net/manual/en/curl.constants.php */ define('CURLPROXY_SOCKS4', 4); /** * Value for the CURLOPT_PROXYTYPE option. * @link https://php.net/manual/en/curl.constants.php */ define('CURLPROXY_SOCKS5', 5); /** * Value for the CURLOPT_NETRC option. * The use of the ~/.netrc file is optional, and information in the URL is to be preferred. * The file will be scanned for the host and user name (to find the password only) or for the host only, * to find the first user name and password after that machine, which ever information is not specified. * @link https://curl.haxx.se/libcurl/c/CURLOPT_NETRC.html */ define('CURL_NETRC_OPTIONAL', 1); /** * Value for the CURLOPT_NETRC option. * The library will ignore the ~/.netrc file. This is the default. * @link https://curl.haxx.se/libcurl/c/CURLOPT_NETRC.html */ define('CURL_NETRC_IGNORED', 0); /** * Value for the CURLOPT_NETRC option. * The use of the ~/.netrc file is required, and information in the URL is to be ignored. * The file will be scanned for the host and user name (to find the password only) or for the host only, * to find the first user name and password after that machine, which ever information is not specified. * @link https://curl.haxx.se/libcurl/c/CURLOPT_NETRC.html */ define('CURL_NETRC_REQUIRED', 2); /** * Value for the CURLOPT_HTTP_VERSION option. * Let's CURL decide which version to use. * @link https://php.net/manual/en/curl.constants.php */ define('CURL_HTTP_VERSION_NONE', 0); /** * Value for the CURLOPT_HTTP_VERSION option. * Forces HTTP/1.0. * @link https://php.net/manual/en/curl.constants.php */ define('CURL_HTTP_VERSION_1_0', 1); /** * Value for the CURLOPT_HTTP_VERSION option. * Forces HTTP/1.1. * @link https://php.net/manual/en/curl.constants.php */ define('CURL_HTTP_VERSION_1_1', 2); /** * Value for the CURLOPT_HTTP_VERSION option. * Attempts HTTP 2. * @link https://php.net/manual/en/curl.constants.php */ define('CURL_HTTP_VERSION_2_0', 3); /** * This is not really an error. It means you should call {@see curl_multi_exec()} again without doing select() or similar in between. * Before version 7.20.0 this could be returned by {@see curl_multi_exec()}, but in later versions this return code is never used. * @link https://www.php.net/manual/en/function.curl-multi-exec.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLM_CALL_MULTI_PERFORM', -1); /** * Things are fine. * @link https://www.php.net/manual/en/function.curl-multi-exec.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLM_OK', 0); /** * The passed-in handle is not a valid CURLM handle. * @link https://www.php.net/manual/en/function.curl-multi-exec.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLM_BAD_HANDLE', 1); /** * 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 use by this or another multi handle. * @link https://www.php.net/manual/en/function.curl-multi-exec.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLM_BAD_EASY_HANDLE', 2); /** * Out of memory error. * @link https://www.php.net/manual/en/function.curl-multi-exec.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLM_OUT_OF_MEMORY', 3); /** * libcurl' internal error. * @link https://www.php.net/manual/en/function.curl-multi-exec.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLM_INTERNAL_ERROR', 4); /** * The message identifies a transfer that is done, and then result contains the return code for the easy handle that just completed. * Other return values are currently not available. * @link https://www.php.net/manual/en/function.curl-multi-info-read.php * @link https://curl.haxx.se/libcurl/c/curl_multi_info_read.html */ define('CURLMSG_DONE', 1); /** * The FTP authentication method (when is activated): * CURLFTPAUTH_SSL (try SSL first), CURLFTPAUTH_TLS (try TLS first), or CURLFTPAUTH_DEFAULT (let cURL decide). * @link https://php.net/manual/en/curl.constants.php */ define('CURLOPT_FTPSSLAUTH', 129); /** * Value for the CURLOPT_FTPSSLAUTH option. * Let cURL decide FTP authentication method. * @link https://php.net/manual/en/curl.constants.php */ define('CURLFTPAUTH_DEFAULT', 0); /** * Value for the CURLOPT_FTPSSLAUTH option. * Try SSL first as FTP authentication method. * @link https://php.net/manual/en/curl.constants.php */ define('CURLFTPAUTH_SSL', 1); /** * Value for the CURLOPT_FTPSSLAUTH option. * Try TLS first as FTP authentication method. * @link https://php.net/manual/en/curl.constants.php */ define('CURLFTPAUTH_TLS', 2); /** * @link https://php.net/manual/en/curl.constants.php * @deprecated use CURLOPT_USE_SSL instead. */ define('CURLOPT_FTP_SSL', 119); /** * Value for the CURLOPT_FTP_SSL option. * Don't attempt to use SSL. * @link https://php.net/manual/en/curl.constants.php */ define('CURLFTPSSL_NONE', 0); /** * Value for the CURLOPT_FTP_SSL option. * Try using SSL, proceed as normal otherwise. * @link https://php.net/manual/en/curl.constants.php */ define('CURLFTPSSL_TRY', 1); /** * Value for the CURLOPT_FTP_SSL option. * Require SSL for the control connection or fail. * @link https://php.net/manual/en/curl.constants.php */ define('CURLFTPSSL_CONTROL', 2); /** * Value for the CURLOPT_FTP_SSL option. * Require SSL for all communication or fail. * @link https://php.net/manual/en/curl.constants.php */ define('CURLFTPSSL_ALL', 3); /** * Tell curl which method to use to reach a file on a FTP(S) server. * Possible values are CURLFTPMETHOD_MULTICWD, CURLFTPMETHOD_NOCWD and CURLFTPMETHOD_SINGLECWD. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.3 */ define('CURLOPT_FTP_FILEMETHOD', 138); /** * Ignore the IP address in the PASV response * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_SKIP_PASV_IP.html */ define('CURLOPT_FTP_SKIP_PASV_IP', 137); /** * TRUE to disable support for the @ prefix for uploading files in CURLOPT_POSTFIELDS, * which means that values starting with @ can be safely passed as fields. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.5 * @deprecated 7.0 Use CURLFile for uploads instead. */ define('CURLOPT_SAFE_UPLOAD', -1); /** * Value for the CURLOPT_FTP_FILEMETHOD option. * libcurl does a single CWD operation for each path part in the given URL. * For deep hierarchies this means many commands. This is how RFC 1738 says it should be done. This is the default but the slowest behavior. * @link https://www.php.net/manual/en/curl.constants.php */ define('CURLFTPMETHOD_MULTICWD', 1); /** * Value for the CURLOPT_FTP_FILEMETHOD option. * libcurl does no CWD at all. * libcurl will do SIZE, RETR, STOR etc and give a full path to the server for all these commands. This is the fastest behavior. * @link https://www.php.net/manual/en/curl.constants.php */ define('CURLFTPMETHOD_NOCWD', 2); /** * Value for the CURLOPT_FTP_FILEMETHOD option. * libcurl does one CWD with the full target directory and then operates on the file "normally" (like in the multicwd case). * This is somewhat more standards compliant than 'nocwd' but without the full penalty of 'multicwd'. * @link https://www.php.net/manual/en/curl.constants.php */ define('CURLFTPMETHOD_SINGLECWD', 3); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_HTTP', 1); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_HTTPS', 2); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_FTP', 4); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_FTPS', 8); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_SCP', 16); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_SFTP', 32); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_TELNET', 64); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_LDAP', 128); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_LDAPS', 256); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_DICT', 512); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_FILE', 1024); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_TFTP', 2048); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLPROTO_ALL', -1); /** * As of cURL 7.43.0, the value is a bitmask. * Pass 1 to enable or 0 to disable. * Enabling pipelining on a multi handle will make it attempt to perform HTTP Pipelining as far as possible for transfers * using this handle. This means that if you add a second request that can use an already existing connection, * the second request will be "piped" on the same connection. * Pass 2 to try to multiplex the new transfer over an existing HTTP/2 connection if possible. * Pass 3 instructs cURL to ask for pipelining and multiplexing independently of each other. * As of cURL 7.62.0, setting the pipelining bit has no effect. * Instead of integer literals, you can also use the CURLPIPE_* constants if available. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 5.5 */ define('CURLMOPT_PIPELINING', 3); /** * Pass a number that will be used as the maximum amount of simultaneously open connections that libcurl may cache. * By default the size will be enlarged to fit four times the number of handles added via {@see curl_multi_add_handle()}. * When the cache is full, curl closes the oldest one in the cache to prevent the number of open connections from increasing. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 5.5 */ define('CURLMOPT_MAXCONNECTS', 6); /** * Specifies a type of data that should be shared. * @link https://www.php.net/manual/en/function.curl-share-setopt.php */ define('CURLSHOPT_SHARE', 1); /** * Specifies a type of data that will be no longer shared. * @link https://www.php.net/manual/en/function.curl-share-setopt.php */ define('CURLSHOPT_UNSHARE', 2); /** * Value for the CURLSHOPT_SHARE option. * Shares cookie data. * @link https://www.php.net/manual/en/function.curl-share-setopt.php */ define('CURL_LOCK_DATA_COOKIE', 2); /** * Value for the CURLSHOPT_SHARE option. * Shares DNS cache. Note that when you use cURL multi handles, * all handles added to the same multi handle will share DNS cache by default. * @link https://www.php.net/manual/en/function.curl-share-setopt.php */ define('CURL_LOCK_DATA_DNS', 3); /** * Value for the CURLSHOPT_SHARE option. * Shares SSL session IDs, reducing the time spent on the SSL handshake when reconnecting to the same server. * Note that SSL session IDs are reused within the same handle by default. * @link https://www.php.net/manual/en/function.curl-share-setopt.php */ define('CURL_LOCK_DATA_SSL_SESSION', 4); /** * The password required to use the CURLOPT_SSLKEY or CURLOPT_SSH_PRIVATE_KEYFILE private key. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define('CURLOPT_KEYPASSWD', 10026); /** * Value for the CURLOPT_FTP_CREATE_MISSING_DIRS option. * libcurl will attempt to create any remote directory that it fails to "move" into. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_CREATE_MISSING_DIRS.html * @since 7.0.7 */ define('CURLFTP_CREATE_DIR', 1); /** * Value for the CURLOPT_FTP_CREATE_MISSING_DIRS option. * libcurl will not attempt to create any remote directory that it fails to "move" into. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_CREATE_MISSING_DIRS.html * @since 7.0.7 */ define('CURLFTP_CREATE_DIR_NONE', 0); /** * Value for the CURLOPT_HTTPAUTH option. * NTLM delegating to winbind helper. * Authentication is performed by a separate binary application that is executed when needed. * The name of the application is specified at compile time but is typically /usr/bin/ntlm_auth. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURLAUTH_NTLM_WB', 32); /** * Value for the CURLOPT_HTTP_VERSION option. * Alias of CURL_HTTP_VERSION_2_0 * Attempts HTTP 2 * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_HTTP_VERSION_2', 3); /** * Value for the CURLOPT_HTTP_VERSION option. * Attempts HTTP 2 over TLS (HTTPS) only * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_HTTP_VERSION_2TLS', 4); /** * Value for the CURLOPT_HTTP_VERSION option. * Issues non-TLS HTTP requests using HTTP/2 without HTTP/1.1 Upgrade * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE', 5); /** * TRUE to enable sending the initial response in the first packet. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_SASL_IR', 218); /** * Set the name of the network interface that the DNS resolver should bind to. This must be an interface name (not an address). * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_DNS_INTERFACE', 10221); /** * Set the local IPv4 address that the resolver should bind to. The argument should contain a single numerical IPv4 address as a string. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_DNS_LOCAL_IP4', 10222); /** * Set the local IPv6 address that the resolver should bind to. The argument should contain a single numerical IPv6 address as a string. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_DNS_LOCAL_IP6', 10223); /** * Specifies the OAuth 2.0 access token. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_XOAUTH2_BEARER', 10220); /** * Can be used to set protocol specific login options, such as the preferred authentication mechanism via "AUTH=NTLM" or "AUTH=*", * and should be used in conjunction with the CURLOPT_USERNAME option. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_LOGIN_OPTIONS', 10224); /** * The timeout for Expect: 100-continue responses in milliseconds. Defaults to 1000 milliseconds. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_EXPECT_100_TIMEOUT_MS', 227); /** * FALSE to disable ALPN in the SSL handshake (if the SSL backend libcurl is built to use supports it), * which can be used to negotiate http2. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_SSL_ENABLE_ALPN', 226); /** * FALSE to disable NPN in the SSL handshake (if the SSL backend libcurl is built to use supports it), * which can be used to negotiate http2. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_SSL_ENABLE_NPN', 225); /** * Set the pinned public key. The string can be the file name of your pinned public key. The file format expected is "PEM" or "DER". * The string can also be any number of base64 encoded sha256 hashes preceded by "sha256//" and separated by ";". * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_PINNEDPUBLICKEY', 10230); /** * Enables the use of Unix domain sockets as connection endpoint and sets the path to the given string. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_UNIX_SOCKET_PATH', 10231); /** * TRUE to verify the certificate's status. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_SSL_VERIFYSTATUS', 232); /** * TRUE to not handle dot dot sequences. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_PATH_AS_IS', 234); /** * TRUE to enable TLS false start. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_SSL_FALSESTART', 233); /** * TRUE to wait for pipelining/multiplexing. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_PIPEWAIT', 237); /** * The proxy authentication service name. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_PROXY_SERVICE_NAME', 10235); /** * The authentication service name. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_SERVICE_NAME', 10236); /** * @since 8.3 */ define('CURLOPT_SSH_HOSTKEYFUNCTION', 20316); /** * @since 8.3 */ define('CURLOPT_PROTOCOLS_STR', 10318); /** * @since 8.3 */ define('CURLOPT_REDIR_PROTOCOLS_STR', 10319); /** * @since 8.3 */ define('CURLOPT_WS_OPTIONS', 320); /** * @since 8.3 */ define('CURLWS_RAW_MODE', 1); /** * @since 8.3 */ define('CURLOPT_CA_CACHE_TIMEOUT', 321); /** * @since 8.3 */ define('CURLOPT_QUICK_EXIT', 322); /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * libcurl attempts to connect to ssh-agent or pageant and let the agent attempt the authentication. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURLSSH_AUTH_AGENT', 16); /** * Value for the CURLMOPT_PIPELINING option. * Default, which means doing no attempts at pipelining or multiplexing. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLMOPT_PIPELINING.html * @since 7.0.7 */ define('CURLPIPE_NOTHING', 0); /** * Value for the CURLMOPT_PIPELINING option. * If this bit is set, libcurl will try to pipeline HTTP/1.1 requests on connections that are already established and in use to hosts. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLMOPT_PIPELINING.html * @deprecated 7.4 * @since 7.0.7 */ define('CURLPIPE_HTTP1', 1); /** * Value for the CURLMOPT_PIPELINING option. * If this bit is set, libcurl will try to multiplex the new transfer over an existing connection if possible. This requires HTTP/2. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLMOPT_PIPELINING.html * @since 7.0.7 */ define('CURLPIPE_MULTIPLEX', 2); /** * Value for the CURLOPT_HEADEROPT option. * Makes CURLOPT_HTTPHEADER headers only get sent to a server and not to a proxy. * Proxy headers must be set with CURLOPT_PROXYHEADER to get used. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURLHEADER_SEPARATE', 1); /** * Value for the CURLOPT_HEADEROPT option. * The headers specified in CURLOPT_HTTPHEADER will be used in requests both to servers and proxies. * With this option enabled, CURLOPT_PROXYHEADER will not have any effect. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURLHEADER_UNIFIED', 0); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURLPROTO_SMB', 67108864); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURLPROTO_SMBS', 134217728); /** * How to deal with headers. * One of the following constants: * CURLHEADER_UNIFIED: the headers specified in CURLOPT_HTTPHEADER will be used in requests both to servers and proxies. * With this option enabled, CURLOPT_PROXYHEADER will not have any effect. * CURLHEADER_SEPARATE: makes CURLOPT_HTTPHEADER headers only get sent to a server and not to a proxy. * Proxy headers must be set with CURLOPT_PROXYHEADER to get used. * Note that if a non-CONNECT request is sent to a proxy, libcurl will send both server headers and proxy headers. * When doing CONNECT, libcurl will send CURLOPT_PROXYHEADER headers only to the proxy and then CURLOPT_HTTPHEADER headers only to the server. * Defaults to CURLHEADER_SEPARATE as of cURL 7.42.1, and CURLHEADER_UNIFIED before. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_HEADEROPT', 229); /** * An array of custom HTTP headers to pass to proxies. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define('CURLOPT_PROXYHEADER', 10228); /** * Value for the CURLOPT_POSTREDIR option. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_REDIR_POST_301', 1); /** * Value for the CURLOPT_POSTREDIR option. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_REDIR_POST_302', 2); /** * Value for the CURLOPT_POSTREDIR option. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_REDIR_POST_303', 4); /** * Value for the CURLOPT_PROXYTYPE option. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURLPROXY_HTTP_1_0', 1); /** * Value for the CURLOPT_POSTREDIR option. * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_REDIR_POST_ALL', 7); /** * Pass a number that specifies the chunk length threshold for pipelining in bytes. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 7.0.7 */ define('CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE', 30010); /** * Pass a number that specifies the size threshold for pipelining penalty in bytes. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 7.0.7 */ define('CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE', 30009); /** * Pass a number that specifies the maximum number of connections to a single host. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 7.0.7 */ define('CURLMOPT_MAX_HOST_CONNECTIONS', 7); /** * Pass a number that specifies the maximum number of requests in a pipeline. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 7.0.7 */ define('CURLMOPT_MAX_PIPELINE_LENGTH', 8); /** * Pass a number that specifies the maximum number of simultaneously open connections. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 7.0.7 */ define('CURLMOPT_MAX_TOTAL_CONNECTIONS', 13); /** * Value for the CURLOPT_FTP_CREATE_MISSING_DIRS option. * libcurl will not attempt to create any remote directory that it fails to "move" into. * Tells libcurl to retry the CWD command again if the subsequent MKD command fails. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_CREATE_MISSING_DIRS.html * @since 7.0.7 */ define('CURLFTP_CREATE_DIR_RETRY', 2); /** * Value for the CURLOPT_HTTPAUTH option. * HTTP Negotiate (SPNEGO) authentication * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURLAUTH_NEGOTIATE', 4); /** * Pass a callable that will be registered to handle server pushes and should have the following signature: * parent_ch * The parent cURL handle (the request the client made). * pushed_ch * A new cURL handle for the pushed request. * headers * The push promise headers. * The push function is supposed to return either CURL_PUSH_OK if it can handle the push, * or CURL_PUSH_DENY to reject it. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 7.1 */ define('CURLMOPT_PUSHFUNCTION', 20014); /** * Returned value from the push function - can handle the push. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 7.1 */ define('CURL_PUSH_OK', 0); /** * Returned value from the push function - can't handle the push. * @link https://www.php.net/manual/en/function.curl-multi-setopt.php * @since 7.1 */ define('CURL_PUSH_DENY', 1); /** * The default buffer size for CURLOPT_BUFFERSIZE * @link https://php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_MAX_READ_SIZE', 10485760); /** * Enables the use of an abstract Unix domain socket instead of establishing a TCP connection to a host and sets the path to the given string. * This option shares the same semantics as CURLOPT_UNIX_SOCKET_PATH. * These two options share the same storage and therefore only one of them can be set per handle. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_ABSTRACT_UNIX_SOCKET', 10264); /** * Value for the CURLOPT_SSLVERSION option. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_SSLVERSION_MAX_DEFAULT', 65536); /** * Value for the CURLOPT_SSLVERSION option. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_SSLVERSION_MAX_NONE', 0); /** * Value for the CURLOPT_SSLVERSION option. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_SSLVERSION_MAX_TLSv1_0', 262144); /** * Value for the CURLOPT_SSLVERSION option. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_SSLVERSION_MAX_TLSv1_1', 327680); /** * Value for the CURLOPT_SSLVERSION option. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_SSLVERSION_MAX_TLSv1_2', 393216); /** * Value for the CURLOPT_SSLVERSION option. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_SSLVERSION_MAX_TLSv1_3', 458752); /** * TRUE to suppress proxy CONNECT response headers from the user callback functions * CURLOPT_HEADERFUNCTION and CURLOPT_WRITEFUNCTION, * when CURLOPT_HTTPPROXYTUNNEL is used and a CONNECT request is made. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_SUPPRESS_CONNECT_HEADERS', 265); /** * Value for the CURLOPT_HTTPAUTH option. * Allows GSS-API authentication. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURLAUTH_GSSAPI', 4); /** * The content-length of the download. This is the value read from the Content-Type: field. -1 if the size isn't known * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_CONTENT_LENGTH_DOWNLOAD_T', 6291471); /** * The specified size of the upload. -1 if the size isn't known * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_CONTENT_LENGTH_UPLOAD_T', 6291472); /** * Total number of bytes that were downloaded. * The number is only for the latest transfer and will be reset again for each new transfer * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_SIZE_DOWNLOAD_T', 6291464); /** * Total number of bytes that were uploaded * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_SIZE_UPLOAD_T', 6291463); /** * The average download speed in bytes/second that curl measured for the complete download * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_SPEED_DOWNLOAD_T', 6291465); /** * The average upload speed in bytes/second that curl measured for the complete upload * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_SPEED_UPLOAD_T', 6291466); /** * Specify an alternative target for this request * @link https://www.php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/CURLOPT_REQUEST_TARGET.html * @since 7.3 */ define('CURLOPT_REQUEST_TARGET', 10266); /** * The SOCKS5 authentication method(s) to use. The options are: CURLAUTH_BASIC, CURLAUTH_GSSAPI, CURLAUTH_NONE. * The bitwise | (or) operator can be used to combine more than one method. If this is done, * cURL will poll the server to see what methods it supports and pick the best one. * CURLAUTH_BASIC allows username/password authentication. * CURLAUTH_GSSAPI allows GSS-API authentication. * CURLAUTH_NONE allows no authentication. * Defaults to CURLAUTH_BASIC|CURLAUTH_GSSAPI. * Set the actual username and password with the CURLOPT_PROXYUSERPWD option. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_SOCKS5_AUTH', 267); /** * TRUE to enable built-in SSH compression. This is a request, not an order; the server may or may not do it. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_SSH_COMPRESSION', 268); /** * libcurl was build with multiple ssh backends. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_MULTI_SSL', 4194304); /** * Supports HTTP Brotli content encoding using libbrotlidec * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_BROTLI', 8388608); /** * Value for the CURLSHOPT_SHARE option. * Put the connection cache in the share object and make all easy handles using this share object share the connection cache. * Using this, you can for example do multi-threaded libcurl use with one handle in each thread, and yet * have a shared pool of unused connections and this way get way better connection re-use * than if you use one separate pool in each thread. * Connections that are used for HTTP/1.1 Pipelining or HTTP/2 multiplexing only get additional transfers * added to them if the existing connection is held by the same multi or easy handle. * libcurl does not support doing HTTP/2 streams in different threads using a shared connection. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/curl_share_setopt.html * @since 7.3 */ define('CURL_LOCK_DATA_CONNECT', 5); /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURLSSH_AUTH_GSSAPI', 32); /** * Remote time of the retrieved document (as Unix timestamp), * an alternative to CURLINFO_FILETIME to allow systems with 32 bit long variables to extract dates * outside of the 32bit timestamp range * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_FILETIME_T', 6291470); /** * Head start for ipv6 for the happy eyeballs algorithm. * Happy eyeballs attempts to connect to both IPv4 and IPv6 addresses for dual-stack hosts, * preferring IPv6 first for timeout milliseconds. * Defaults to CURL_HET_DEFAULT, which is currently 200 milliseconds. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS', 271); /** * The time in seconds since January 1st, 1970. * The time will be used by CURLOPT_TIMECONDITION. Defaults to zero. * The difference between this option and CURLOPT_TIMEVALUE is the type of the argument. * On systems where 'long' is only 32 bit wide, this option has to be used to set dates beyond the year 2038. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_TIMEVALUE_LARGE', 30270); /** * TRUE to shuffle the order of all returned addresses so that they will be used in a random order, * when a name is resolved and more than one IP address is returned. * This may cause IPv4 to be used before IPv6 or vice versa. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_DNS_SHUFFLE_ADDRESSES', 275); /** * TRUE to send an HAProxy PROXY protocol v1 header at the start of the connection. * The default action is not to send this header. * @link https://php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURLOPT_HAPROXYPROTOCOL', 274); /** * Value for the CURLSHOPT_SHARE option. * The Public Suffix List stored in the share object is made available to all easy handle bound to the later. * Since the Public Suffix List is periodically refreshed, this avoids updates in too many different contexts. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/curl_share_setopt.html * @since 7.3 */ define('CURL_LOCK_DATA_PSL', 6); /** * Value for the CURLOPT_HTTPAUTH option. * HTTP Bearer token authentication, used primarily in OAuth 2.0 protocol. * @link https://php.net/manual/en/curl.constants.php * https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html * @since 7.3 */ define('CURLAUTH_BEARER', 64); /** * Time, in microseconds, it took from the start until the SSL/SSH connect/handshake to the remote host was completed * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_APPCONNECT_TIME_T', 6291512); /** * Total time taken, in microseconds, from the start until the connection to the remote host (or proxy) was completed * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_CONNECT_TIME_T', 6291508); /** * Time in microseconds from the start until the name resolving was completed * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_NAMELOOKUP_TIME_T', 6291507); /** * Time taken from the start until the file transfer is just about to begin, in microseconds * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_PRETRANSFER_TIME_T', 6291509); /** * Total time, in microseconds, * it took for all redirection steps include name lookup, connect, pretransfer and transfer before final transaction was started * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_REDIRECT_TIME_T', 6291511); /** * Time, in microseconds, it took from the start until the first byte is received * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_STARTTRANSFER_TIME_T', 6291510); /** * Total time in microseconds for the previous transfer, including name resolving, TCP connect etc. * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_TOTAL_TIME_T', 6291506); /** * TRUE to not allow URLs that include a username. Usernames are allowed by default (0). * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_DISALLOW_USERNAME_IN_URL', 278); /** * The list of cipher suites to use for the TLS 1.3 connection to a proxy. * The list must be syntactically correct, it consists of one or more cipher suite strings separated by colons. * This option is currently used only when curl is built to use OpenSSL 1.1.1 or later. * If you are using a different SSL backend you can try setting TLS 1.3 cipher suites by using the CURLOPT_PROXY_SSL_CIPHER_LIST option. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_TLS13_CIPHERS', 10277); /** * The list of cipher suites to use for the TLS 1.3 connection. * The list must be syntactically correct, it consists of one or more cipher suite strings separated by colons. * This option is currently used only when curl is built to use OpenSSL 1.1.1 or later. * If you are using a different SSL backend you can try setting TLS 1.3 cipher suites by using the CURLOPT_SSL_CIPHER_LIST option. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_TLS13_CIPHERS', 10276); /** * Time allowed to wait for FTP response. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_RESPONSE_TIMEOUT.html * @since 5.5 */ define('CURLOPT_FTP_RESPONSE_TIMEOUT', 112); /** * Provide a custom address for a specific host and port pair. * An array of hostname, port, and IP address strings, each element separated by a colon. * In the format: array("example.com:80:127.0.0.1") * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.5 */ define('CURLOPT_RESOLVE', 10203); /** * Enable appending to the remote file * @link https://curl.haxx.se/libcurl/c/CURLOPT_APPEND.html * @since 5.5 */ define('CURLOPT_APPEND', 50); /** * Ask for names only in a directory listing * @link https://curl.haxx.se/libcurl/c/CURLOPT_DIRLISTONLY.html * @since 5.5 */ define('CURLOPT_DIRLISTONLY', 48); /** * Permissions for remotely created directories * Pass a long as a parameter, containing the value of the permissions that will be assigned to newly created directories on the remote server. * The default value is 0755, but any valid value can be used. * The only protocols that can use this are sftp://, scp://, and file://. * @link https://curl.haxx.se/libcurl/c/CURLOPT_NEW_DIRECTORY_PERMS.html * @since 5.5 */ define('CURLOPT_NEW_DIRECTORY_PERMS', 160); /** * Permissions for remotely created files. * Pass a long as a parameter, containing the value of the permissions that will be assigned to newly created files on the remote server. * The default value is 0644, but any valid value can be used. * The only protocols that can use this are sftp://, scp://, and file://. * @link https://curl.haxx.se/libcurl/c/CURLOPT_NEW_FILE_PERMS.html * @since 5.5 */ define('CURLOPT_NEW_FILE_PERMS', 159); /** * TRUE to scan the ~/.netrc file to find a username and password for the remote site that a connection is being established with. * @link https://curl.haxx.se/libcurl/c/CURLOPT_NETRC_FILE.html * @since 5.5 */ define('CURLOPT_NETRC_FILE', 10118); /** * Commands to run before an FTP transfer * @link https://curl.haxx.se/libcurl/c/CURLOPT_PREQUOTE.html * @since 5.5 */ define('CURLOPT_PREQUOTE', 10093); /** * Set FTP kerberos security level * @link https://curl.haxx.se/libcurl/c/CURLOPT_KRBLEVEL.html * @since 5.5 */ define('CURLOPT_KRBLEVEL', 10063); /** * Maximum file size allowed to download (in bytes) * @link https://curl.haxx.se/libcurl/c/CURLOPT_MAXFILESIZE.html * @since 5.5 */ define('CURLOPT_MAXFILESIZE', 114); /** * Set account info for FTP * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_ACCOUNT.html * @since 5.5 */ define('CURLOPT_FTP_ACCOUNT', 10134); /** * A cookie string (i.e. a single line in Netscape/Mozilla format, or a regular HTTP-style Set-Cookie header) adds that single cookie to the internal cookie store. * "ALL" erases all cookies held in memory. * "SESS" erases all session cookies held in memory. * "FLUSH" writes all known cookies to the file specified by CURLOPT_COOKIEJAR. * "RELOAD" loads all cookies from the files specified by CURLOPT_COOKIEFILE. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.5 */ define('CURLOPT_COOKIELIST', 10135); /** * Set local port number to use for socket * @link https://curl.haxx.se/libcurl/c/CURLOPT_LOCALPORT.html * @since 5.5 */ define('CURLOPT_LOCALPORT', 139); /** * Number of additional local ports to try. * Pass a long. The range argument is the number of attempts libcurl will make to find a working local port number. * It starts with the given CURLOPT_LOCALPORT and adds one to the number for each retry. * @link https://curl.haxx.se/libcurl/c/CURLOPT_LOCALPORTRANGE.html * @since 5.5 */ define('CURLOPT_LOCALPORTRANGE', 140); /** * Command to use instead of USER with FTP. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_ALTERNATIVE_TO_USER.html * @since 5.5 */ define('CURLOPT_FTP_ALTERNATIVE_TO_USER', 10147); /** * Enable/disable use of the SSL session-ID cache. * @link https://curl.haxx.se/libcurl/c/CURLOPT_SSL_SESSIONID_CACHE.html * @since 5.5 */ define('CURLOPT_SSL_SESSIONID_CACHE', 150); /** * Switch off SSL again with FTP after auth. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_SSL_CCC.html * @since 5.5 */ define('CURLOPT_FTP_SSL_CCC', 154); /** * FALSE to get the raw HTTP response body. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.5 */ define('CURLOPT_HTTP_CONTENT_DECODING', 158); /** * Enable/disable HTTP transfer decoding. * @link https://curl.haxx.se/libcurl/c/CURLOPT_HTTP_TRANSFER_DECODING.html * @since 5.5 */ define('CURLOPT_HTTP_TRANSFER_DECODING', 157); /** * Append FTP transfer mode to URL for proxy. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROXY_TRANSFER_MODE.html * @since 5.5 */ define('CURLOPT_PROXY_TRANSFER_MODE', 166); /** * Set scope id for IPv6 addresses. * @link https://curl.haxx.se/libcurl/c/CURLOPT_ADDRESS_SCOPE.html * @since 5.5 */ define('CURLOPT_ADDRESS_SCOPE', 171); /** * Specify a Certificate Revocation List file. * @link https://curl.haxx.se/libcurl/c/CURLOPT_CRLFILE.html * @since 5.5 */ define('CURLOPT_CRLFILE', 10169); /** * Issuer SSL certificate filename. * @link https://curl.haxx.se/libcurl/c/CURLOPT_ISSUERCERT.html * @since 5.5 */ define('CURLOPT_ISSUERCERT', 10170); /** * The user name to use in authentication. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.5 */ define('CURLOPT_USERNAME', 10173); /** * Password to use in authentication. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PASSWORD.html * @since 5.5 */ define('CURLOPT_PASSWORD', 10174); /** * User name to use for proxy authentication. * @since 5.5 */ define('CURLOPT_PROXYUSERNAME', 10175); /** * Password to use for proxy authentication. * @since 5.5 */ define('CURLOPT_PROXYPASSWORD', 10176); /** * Disable proxy use for specific hosts. * @link https://curl.haxx.se/libcurl/c/CURLOPT_NOPROXY.html * @since 5.5 */ define('CURLOPT_NOPROXY', 10177); /** * Set socks proxy gssapi negotiation protection. * @link https://curl.haxx.se/libcurl/c/CURLOPT_SOCKS5_GSSAPI_NEC.html * @since 5.5 */ define('CURLOPT_SOCKS5_GSSAPI_NEC', 180); /** * SOCKS5 proxy authentication service name. * @link https://curl.haxx.se/libcurl/c/CURLOPT_SOCKS5_GSSAPI_SERVICE.html * @deprecated Use CURLOPT_PROXY_SERVICE_NAME instead. * @since 5.5 */ define('CURLOPT_SOCKS5_GSSAPI_SERVICE', 10179); /** * Specify blocksize to use for TFTP data transmission. * @link https://curl.haxx.se/libcurl/c/CURLOPT_TFTP_BLKSIZE.html * @since 5.5 */ define('CURLOPT_TFTP_BLKSIZE', 178); /** * File name holding the SSH known hosts. * @link https://curl.haxx.se/libcurl/c/CURLOPT_SSH_KNOWNHOSTS.html * @since 5.5 */ define('CURLOPT_SSH_KNOWNHOSTS', 10183); /** * Enable the PRET command. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_USE_PRET.html * @since 5.5 */ define('CURLOPT_FTP_USE_PRET', 188); /** * SMTP sender address. * @link https://curl.haxx.se/libcurl/c/CURLOPT_MAIL_FROM.html * @since 5.5 */ define('CURLOPT_MAIL_FROM', 10186); /** * List of SMTP mail recipients. * @link https://curl.haxx.se/libcurl/c/CURLOPT_MAIL_RCPT.html * @since 5.5 */ define('CURLOPT_MAIL_RCPT', 10187); /** * Set the RTSP client CSEQ number. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_CLIENT_CSEQ.html * @since 5.5 */ define('CURLOPT_RTSP_CLIENT_CSEQ', 193); /** * Set the RTSP server CSEQ number. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_SERVER_CSEQ.html * @since 5.5 */ define('CURLOPT_RTSP_SERVER_CSEQ', 194); /** * Set RTSP session ID. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_SESSION_ID.html * @since 5.5 */ define('CURLOPT_RTSP_SESSION_ID', 10190); /** * Set RTSP stream URI. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_STREAM_URI.html * @since 5.5 */ define('CURLOPT_RTSP_STREAM_URI', 10191); /** * Set RTSP Transport: header. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_TRANSPORT.html * @since 5.5 */ define('CURLOPT_RTSP_TRANSPORT', 10192); /** * Specify RTSP request. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html * @since 5.5 */ define('CURLOPT_RTSP_REQUEST', 189); /** * Ignore content length. * If TRUE, ignore the Content-Length header in the HTTP response and ignore asking for or relying on it for FTP transfers. * This is useful for HTTP with Apache 1.x (and similar servers) which will report incorrect content length for files over 2 gigabytes. * If this option is used, curl will not be able to accurately report progress, and will simply stop the download when the server ends the connection. * It is also useful with FTP when for example the file is growing while the transfer is in progress * which otherwise will unconditionally cause libcurl to report error. * @link https://curl.haxx.se/libcurl/c/CURLOPT_IGNORE_CONTENT_LENGTH.html * @since 5.5 */ define('CURLOPT_IGNORE_CONTENT_LENGTH', 136); /** * Enables automatic decompression of HTTP downloads * @link https://curl.haxx.se/libcurl/c/CURLOPT_ACCEPT_ENCODING.html * @since 5.5 */ define('CURLOPT_ACCEPT_ENCODING', 10102); /** * Ask for HTTP Transfer Encoding. * Adds a request for compressed Transfer Encoding in the outgoing HTTP request. * If the server supports this and so desires, it can respond with the HTTP response sent using a compressed Transfer-Encoding * that will be automatically uncompressed by libcurl on reception. * @link https://curl.haxx.se/libcurl/c/CURLOPT_TRANSFER_ENCODING.html * @since 5.5 */ define('CURLOPT_TRANSFER_ENCODING', 207); /** * Set preferred DNS servers: host[:port][,host[:port]]... * @link https://curl.haxx.se/libcurl/c/CURLOPT_DNS_SERVERS.html * @since 5.5 */ define('CURLOPT_DNS_SERVERS', 10211); /** * Request using SSL / TLS for the transfer * @link https://curl.haxx.se/libcurl/c/CURLOPT_USE_SSL.html * @since 5.5 */ define('CURLOPT_USE_SSL', 119); /** * Custom telnet options * @link https://curl.haxx.se/libcurl/c/CURLOPT_TELNETOPTIONS.html */ define("CURLOPT_TELNETOPTIONS", 10070); /** * The download could not be resumed because the specified offset was out of the file boundary. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define("CURLE_BAD_DOWNLOAD_RESUME", 36); /** * A file transfer was shorter or larger than expected. * This happens when the server first reports an expected transfer size, and then delivers data * that doesn't match the previously given size. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define("CURLE_FTP_PARTIAL_FILE", 18); /** * This is returned if CURLOPT_FAILONERROR is set TRUE and the HTTP server returns an error code that is >= 400. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define("CURLE_HTTP_RETURNED_ERROR", 22); /** * Operation timeout. The specified time-out period was reached according to the conditions. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define("CURLE_OPERATION_TIMEDOUT", 28); /** * Failed to match the pinned key specified with CURLOPT_PINNEDPUBLICKEY. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define("CURLE_SSL_PINNEDPUBKEYNOTMATCH", 90); /** * @link https://php.net/manual/en/curl.constants.php */ define("CURLINFO_LASTONE", 64); /** * An easy handle already added to a multi handle was attempted to get added a second time. * @link https://www.php.net/manual/en/function.curl-multi-exec.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define("CURLM_ADDED_ALREADY", 7); /** * @link https://curl.haxx.se/libcurl/c/symbols-in-versions.html */ define("CURLSHOPT_NONE", 0); /** * Default value for the CURLOPT_TIMECONDITION option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_TIMECONDITION.html */ define("CURL_TIMECOND_NONE", 0); /** * Value for the CURLOPT_HTTPAUTH option. * Allows no authentication. * @link https://www.php.net/manual/en/function.curl-setopt.php */ define("CURLAUTH_NONE", 0); /** * Problem with reading the SSL CA cert (path? access rights?) * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define("CURLE_SSL_CACERT_BADFILE", 77); /** * An unspecified error occurred during the SSH session. * @link https://php.net/manual/en/curl.constants.php * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define("CURLE_SSH", 79); /** * Value for the CURLOPT_FTP_SSL_CCC option. * Initiate the shutdown and wait for a reply. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_SSL_CCC.html */ define("CURLFTPSSL_CCC_ACTIVE", 2); /** * Value for the CURLOPT_FTP_SSL_CCC option. * Don't attempt to use CCC. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_SSL_CCC.html */ define("CURLFTPSSL_CCC_NONE", 0); /** * Value for the CURLOPT_FTP_SSL_CCC option. * Do not initiate the shutdown, but wait for the server to do it. Do not send a reply. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FTP_SSL_CCC.html */ define("CURLFTPSSL_CCC_PASSIVE", 1); /** * Value for the CURLOPT_USE_SSL option. * Require SSL for all communication or fail. * @link https://curl.haxx.se/libcurl/c/CURLOPT_USE_SSL.html */ define("CURLUSESSL_ALL", 3); /** * Value for the CURLOPT_USE_SSL option. * Require SSL for the control connection or fail. * @link https://curl.haxx.se/libcurl/c/CURLOPT_USE_SSL.html */ define("CURLUSESSL_CONTROL", 2); /** * Value for the CURLOPT_USE_SSL option. * Don't attempt to use SSL. * @link https://curl.haxx.se/libcurl/c/CURLOPT_USE_SSL.html */ define("CURLUSESSL_NONE", 0); /** * Value for the CURLOPT_USE_SSL option. * Try using SSL, proceed as normal otherwise. * @link https://curl.haxx.se/libcurl/c/CURLOPT_USE_SSL.html */ define("CURLUSESSL_TRY", 1); /** * Convenience define that pauses both directions. * @link https://php.net/manual/en/curl.constants.php * @since 5.5 */ define("CURLPAUSE_ALL", 5); /** * Convenience define that unpauses both directions. * @link https://php.net/manual/en/curl.constants.php * @since 5.5 */ define("CURLPAUSE_CONT", 0); /** * Pause receiving data. There will be no data received on this connection until this function is called again without this bit set. * Thus, the write callback (CURLOPT_WRITEFUNCTION) won't be called. * @link https://php.net/manual/en/curl.constants.php * @since 5.5 */ define("CURLPAUSE_RECV", 1); /** * @link https://php.net/manual/en/curl.constants.php * @since 5.5 */ define("CURLPAUSE_RECV_CONT", 0); /** * Pause sending data. There will be no data sent on this connection until this function is called again without this bit set. * Thus, the read callback (CURLOPT_READFUNCTION) won't be called. * @link https://php.net/manual/en/curl.constants.php * @since 5.5 */ define("CURLPAUSE_SEND", 4); /** * @link https://php.net/manual/en/curl.constants.php * @since 5.5 */ define("CURLPAUSE_SEND_CONT", 0); /** * Read callback for data uploads. * @link https://curl.haxx.se/libcurl/c/CURLOPT_READFUNCTION.html */ define("CURL_READFUNC_PAUSE", 268435457); /** * Set callback for writing received data. * @link https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html */ define("CURL_WRITEFUNC_PAUSE", 268435457); /** * Value for the CURLOPT_PROXYTYPE option. * @link https://www.php.net/manual/en/curl.constants.php * @since 5.5.23 */ define("CURLPROXY_SOCKS4A", 6); /** * Value for the CURLOPT_PROXYTYPE option. * Proxy resolves URL hostname. * @link https://www.php.net/manual/en/curl.constants.php * @since 5.5.23 */ define("CURLPROXY_SOCKS5_HOSTNAME", 7); /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * @link https://www.php.net/manual/en/curl.constants.php */ define("CURLSSH_AUTH_ANY", -1); /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * @link https://www.php.net/manual/en/curl.constants.php */ define("CURLSSH_AUTH_DEFAULT", -1); /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * @link https://www.php.net/manual/en/curl.constants.php */ define("CURLSSH_AUTH_HOST", 4); /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * @link https://www.php.net/manual/en/curl.constants.php */ define("CURLSSH_AUTH_KEYBOARD", 8); /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * @link https://www.php.net/manual/en/curl.constants.php */ define("CURLSSH_AUTH_NONE", 0); /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * @link https://www.php.net/manual/en/curl.constants.php */ define("CURLSSH_AUTH_PASSWORD", 2); /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * @link https://www.php.net/manual/en/curl.constants.php */ define("CURLSSH_AUTH_PUBLICKEY", 1); /** * Value for the CURLOPT_HTTPAUTH option. * HTTP Digest authentication with an IE flavor. * Digest authentication is defined in RFC 2617 and is a more secure way to do authentication over public networks than * the regular old-fashioned Basic method. * The IE flavor is simply that libcurl will use a special "quirk" that IE is known to have used before version 7 * and that some servers require the client to use. * @link https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html */ define("CURLAUTH_DIGEST_IE", 16); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_IMAP", 4096); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_IMAPS", 8192); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_POP3", 16384); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_POP3S", 32768); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_RTSP", 262144); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_SMTP", 65536); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_SMTPS", 131072); /** * Value for the CURLOPT_RTSP_REQUEST option. * When sent by a client, this method changes the description of the session. * For example, if a client is using the server to record a meeting, * the client can use Announce to inform the server of all the meta-information about the session. * ANNOUNCE acts like an HTTP PUT or POST * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_ANNOUNCE", 3); /** * Value for the CURLOPT_RTSP_REQUEST option. * Used to get the low level description of a stream. * The application should note what formats it understands in the 'Accept:' header. * Unless set manually, libcurl will automatically fill in 'Accept: application/sdp'. * Time-condition headers will be added to Describe requests if the CURLOPT_TIMECONDITION option is active. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_DESCRIBE", 2); /** * Value for the CURLOPT_RTSP_REQUEST option. * Retrieve a parameter from the server. * By default, libcurl will automatically include a Content-Type: text/parameters header on all non-empty requests * unless a custom one is set. GET_PARAMETER acts just like an HTTP PUT or POST * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_GET_PARAMETER", 8); /** * Value for the CURLOPT_RTSP_REQUEST option. * Used to retrieve the available methods of the server. * The application is responsible for parsing and obeying the response. * The session ID is not needed for this method. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_OPTIONS", 1); /** * Value for the CURLOPT_RTSP_REQUEST option. * Send a Pause command to the server. * Use the CURLOPT_RANGE option with a single value to indicate when the stream should be halted. (e.g. npt='25') * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_PAUSE", 6); /** * Value for the CURLOPT_RTSP_REQUEST option. * Send a Play command to the server. * Use the CURLOPT_RANGE option to modify the playback time (e.g. 'npt=10-15'). * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_PLAY", 5); /** * Value for the CURLOPT_RTSP_REQUEST option. * This is a special request because it does not send any data to the server. * The application may call this function in order to receive interleaved RTP data. * It will return after processing one read buffer of data in order to give the application a chance to run. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_RECEIVE", 11); /** * Value for the CURLOPT_RTSP_REQUEST option. * Used to tell the server to record a session. Use the CURLOPT_RANGE option to modify the record time. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_RECORD", 10); /** * Value for the CURLOPT_RTSP_REQUEST option. * Set a parameter on the server. * By default, libcurl will automatically include a Content-Type: text/parameters header unless a custom one is set. * The interaction with SET_PARAMETER is much like an HTTP PUT or POST. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_SET_PARAMETER", 9); /** * Value for the CURLOPT_RTSP_REQUEST option. * Setup is used to initialize the transport layer for the session. * The application must set the desired Transport options for a session * by using the CURLOPT_RTSP_TRANSPORT option prior to calling setup. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_SETUP", 4); /** * Value for the CURLOPT_RTSP_REQUEST option. * This command terminates an RTSP session. * Simply closing a connection does not terminate the RTSP session since it is valid to control an RTSP session over different connections. * @link https://curl.haxx.se/libcurl/c/CURLOPT_RTSP_REQUEST.html */ define("CURL_RTSPREQ_TEARDOWN", 7); /** * Wildcard matching function callback. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FNMATCH_FUNCTION.html */ define("CURLOPT_FNMATCH_FUNCTION", 20200); /** * Enable directory wildcard transfers. * @link https://curl.haxx.se/libcurl/c/CURLOPT_WILDCARDMATCH.html */ define("CURLOPT_WILDCARDMATCH", 197); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_RTMP", 524288); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_RTMPE", 2097152); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_RTMPS", 8388608); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_RTMPT", 1048576); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_RTMPTE", 4194304); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_RTMPTS", 16777216); /** * Return value for the CURLOPT_FNMATCH_FUNCTION if an error was occurred. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FNMATCH_FUNCTION.html */ define("CURL_FNMATCHFUNC_FAIL", 2); /** * Return value for the CURLOPT_FNMATCH_FUNCTION if pattern matches the string. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FNMATCH_FUNCTION.html */ define("CURL_FNMATCHFUNC_MATCH", 0); /** * Return value for the CURLOPT_FNMATCH_FUNCTION if pattern not matches the string. * @link https://curl.haxx.se/libcurl/c/CURLOPT_FNMATCH_FUNCTION.html */ define("CURL_FNMATCHFUNC_NOMATCH", 1); /** * Value for the CURLOPT_PROTOCOLS option. * @link https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html */ define("CURLPROTO_GOPHER", 33554432); /** * Value for the CURLOPT_HTTPAUTH option. * This is a meta symbol. * OR this value together with a single specific auth value to force libcurl to probe for un-restricted auth and if not, * only that single auth algorithm is acceptable. * @link https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html */ define("CURLAUTH_ONLY", 2147483648); /** * Password to use for TLS authentication. * @link https://curl.haxx.se/libcurl/c/CURLOPT_TLSAUTH_PASSWORD.html */ define("CURLOPT_TLSAUTH_PASSWORD", 10205); /** * Set TLS authentication methods. * @link https://curl.haxx.se/libcurl/c/CURLOPT_TLSAUTH_TYPE.html */ define("CURLOPT_TLSAUTH_TYPE", 10206); /** * User name to use for TLS authentication. * @link https://curl.haxx.se/libcurl/c/CURLOPT_TLSAUTH_USERNAME.html */ define("CURLOPT_TLSAUTH_USERNAME", 10204); /** * Value for the CURLOPT_TLSAUTH_TYPE option. * TLS-SRP authentication. * Secure Remote Password authentication for TLS is defined in RFC 5054 and provides mutual authentication if both sides have a shared secret. * @link https://curl.haxx.se/libcurl/c/CURLOPT_TLSAUTH_TYPE.html */ define("CURL_TLSAUTH_SRP", 1); /** * Value for the CURLOPT_GSSAPI_DELEGATION option. * Allow unconditional GSSAPI credential delegation. * @link https://curl.haxx.se/libcurl/c/CURLOPT_GSSAPI_DELEGATION.html */ define("CURLGSSAPI_DELEGATION_FLAG", 2); /** * Value for the CURLOPT_GSSAPI_DELEGATION option. * Delegate only if the OK-AS-DELEGATE flag is set in the service ticket * in case this feature is supported by the GSS-API implementation. * @link https://curl.haxx.se/libcurl/c/CURLOPT_GSSAPI_DELEGATION.html */ define("CURLGSSAPI_DELEGATION_POLICY_FLAG", 1); /** * Set allowed GSS-API delegation. * @link https://curl.haxx.se/libcurl/c/CURLOPT_GSSAPI_DELEGATION.html */ define("CURLOPT_GSSAPI_DELEGATION", 210); /** * Timeout waiting for FTP server to connect back * @link https://curl.haxx.se/libcurl/c/CURLOPT_ACCEPTTIMEOUT_MS.html */ define("CURLOPT_ACCEPTTIMEOUT_MS", 212); /** * SMTP authentication address * @link https://curl.haxx.se/libcurl/c/CURLOPT_MAIL_AUTH.html */ define("CURLOPT_MAIL_AUTH", 10217); /** * Set SSL behavior options, which is a bitmask of any of the following constants: * CURLSSLOPT_ALLOW_BEAST: do not attempt to use any workarounds for a security flaw in the SSL3 and TLS1.0 protocols. * CURLSSLOPT_NO_REVOKE: disable certificate revocation checks for those SSL backends where such behavior is present. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.6 */ define("CURLOPT_SSL_OPTIONS", 216); /** * If set to 1, TCP keepalive probes will be sent. * The delay and frequency of these probes can be controlled by the CURLOPT_TCP_KEEPIDLE and CURLOPT_TCP_KEEPINTVL options, * provided the operating system supports them. * If set to 0 (default) keepalive probes are disabled. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.5 */ define("CURLOPT_TCP_KEEPALIVE", 213); /** * Sets the delay, in seconds, that the operating system will wait while the connection is idle before sending keepalive probes, * if CURLOPT_TCP_KEEPALIVE is enabled. Not all operating systems support this option. The default is 60. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.5 */ define("CURLOPT_TCP_KEEPIDLE", 214); /** * Sets the interval, in seconds, that the operating system will wait between sending keepalive probes, * if CURLOPT_TCP_KEEPALIVE is enabled. Not all operating systems support this option. The default is 60. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.5 */ define("CURLOPT_TCP_KEEPINTVL", 215); /** * Value for the CURLOPT_SSL_OPTIONS option. * Do not attempt to use any workarounds for a security flaw in the SSL3 and TLS1.0 protocols. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 5.6 */ define("CURLSSLOPT_ALLOW_BEAST", 1); /** * Supports HTTP2. * @link https://www.php.net/manual/en/curl.constants.php * @since 5.5.24 */ define("CURL_VERSION_HTTP2", 65536); /** * Value for the CURLOPT_SSL_OPTIONS option. * Disable certificate revocation checks for those SSL backends where such behavior is present. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define("CURLSSLOPT_NO_REVOKE", 2); /** * The default protocol to use if the URL is missing a scheme name. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define("CURLOPT_DEFAULT_PROTOCOL", 10238); /** * Set the numerical stream weight (a number between 1 and 256). * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define("CURLOPT_STREAM_WEIGHT", 239); /** * TRUE to not send TFTP options requests. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define("CURLOPT_TFTP_NO_OPTIONS", 242); /** * Connect to a specific host and port instead of the URL's host and port. * Accepts an array of strings with the format HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define("CURLOPT_CONNECT_TO", 10243); /** * TRUE to enable TCP Fast Open. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.0.7 */ define("CURLOPT_TCP_FASTOPEN", 244); /** * The server sent data libcurl couldn't parse. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURLE_WEIRD_SERVER_REPLY', 8); /** * TRUE to keep sending the request body if the HTTP code returned is equal to or larger than 300. * The default action would be to stop sending and close the stream or connection. Suitable for manual NTLM authentication. * Most applications do not need this option. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_KEEP_SENDING_ON_ERROR', 245); /** * Value for the CURLOPT_SSLVERSION option. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_SSLVERSION_TLSv1_3', 7); /** * Supports HTTPS proxy. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_HTTPS_PROXY', 2097152); /** * The protocol used in the last HTTP connection. The returned value will be exactly one of the CURLPROTO_* values * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_PROTOCOL', 2097200); /** * Supports asynchronous name lookups. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_ASYNCHDNS', 128); /** * Supports memory tracking debug capabilities. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3.6 */ define('CURL_VERSION_CURLDEBUG', 8192); /** * Supports character conversions. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_CONV', 4096); /** * libcurl was built with debug capabilities * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_DEBUG', 64); /** * Supports HTTP GSS-Negotiate. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_GSSNEGOTIATE', 32); /** * Supports the IDNA. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_IDN', 1024); /** * Supports large files. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_LARGEFILE', 512); /** * Supports HTTP NTLM. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_NTLM', 16); /** * Supports the Mozilla's Public Suffix List. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_VERSION_PSL', 1048576); /** * Supports for SPNEGO authentication (RFC 2478). * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_SPNEGO', 256); /** * Supports SSPI. Windows-specific. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_SSPI', 2048); /** * Supports the TLS-SRP. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_TLSAUTH_SRP', 16384); /** * Supports the NTLM delegation to a winbind helper. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_NTLM_WB', 32768); /** * Supports the GSSAPI. This makes libcurl use provided functions for Kerberos and SPNEGO authentication. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_GSSAPI', 131072); /** * Supports Kerberos V5 authentication for FTP, IMAP, POP3, SMTP and SOCKSv5 proxy. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURL_VERSION_KERBEROS5', 262144); /** * The path to proxy Certificate Authority (CA) bundle. * Set the path as a string naming a file holding one or more certificates to verify the HTTPS proxy with. * This option is for connecting to an HTTPS proxy, not an HTTPS server. * Defaults set to the system path where libcurl's cacert bundle is assumed to be stored. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_CAINFO', 10246); /** * The directory holding multiple CA certificates to verify the HTTPS proxy with. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_CAPATH', 10247); /** * Set the file name with the concatenation of CRL (Certificate Revocation List) in PEM format * to use in the certificate validation that occurs during the SSL exchange. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_CRLFILE', 10260); /** * Set the string be used as the password required to use the CURLOPT_PROXY_SSLKEY private key. * You never needed a passphrase to load a certificate but you need one to load your private key. * This option is for connecting to an HTTPS proxy, not an HTTPS server. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_KEYPASSWD', 10258); /** * The format of your client certificate used when connecting to an HTTPS proxy. Supported formats are "PEM" and "DER", except with Secure Transport. * OpenSSL (versions 0.9.3 and later) and Secure Transport (on iOS 5 or later, or OS X 10.7 or later) also support "P12" for PKCS#12-encoded files. * Defaults to "PEM". * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_SSLCERTTYPE', 10255); /** * The format of your private key. Supported formats are "PEM", "DER" and "ENG". * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_SSLKEYTYPE', 10257); /** * One of CURL_SSLVERSION_DEFAULT, CURL_SSLVERSION_TLSv1, CURL_SSLVERSION_TLSv1_0, CURL_SSLVERSION_TLSv1_1, CURL_SSLVERSION_TLSv1_2, * CURL_SSLVERSION_TLSv1_3, CURL_SSLVERSION_MAX_DEFAULT, CURL_SSLVERSION_MAX_TLSv1_0, CURL_SSLVERSION_MAX_TLSv1_1, * CURL_SSLVERSION_MAX_TLSv1_2, CURL_SSLVERSION_MAX_TLSv1_3 or CURL_SSLVERSION_SSLv3. * See also CURLOPT_SSLVERSION. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_SSLVERSION', 250); /** * Tusername to use for the HTTPS proxy TLS authentication method specified with the CURLOPT_PROXY_TLSAUTH_TYPE option. * Requires that the CURLOPT_PROXY_TLSAUTH_PASSWORD option to also be set. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_TLSAUTH_USERNAME', 10251); /** * The password to use for the TLS authentication method specified with the CURLOPT_PROXY_TLSAUTH_TYPE option. * Requires that the CURLOPT_PROXY_TLSAUTH_USERNAME option to also be set. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_TLSAUTH_PASSWORD', 10252); /** * The method of the TLS authentication used for the HTTPS connection. Supported method is "SRP". * Secure Remote Password (SRP) authentication for TLS provides mutual authentication if both sides have a shared secret. * To use TLS-SRP, you must also set the CURLOPT_PROXY_TLSAUTH_USERNAME and CURLOPT_PROXY_TLSAUTH_PASSWORD options. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_TLSAUTH_TYPE', 10253); /** * Value for the CURLOPT_PROXYTYPE option. * Use HTTPS Proxy. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3 */ define('CURLPROXY_HTTPS', 2); /** * Set the pinned public key for HTTPS proxy. The string can be the file name of your pinned public key. The file format expected is "PEM" or "DER". * The string can also be any number of base64 encoded sha256 hashes preceded by "sha256//" and separated by ";" * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_PINNEDPUBLICKEY', 10263); /** * The file name of your private key used for connecting to the HTTPS proxy. * The default format is "PEM" and can be changed with CURLOPT_PROXY_SSLKEYTYPE. * (iOS and Mac OS X only) This option is ignored if curl was built against Secure Transport. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_SSLKEY', 10256); /** * The list of ciphers to use for the connection to the HTTPS proxy. * The list must be syntactically correct, it consists of one or more cipher strings separated by colons. * Commas or spaces are also acceptable separators but colons are normally used, !, - and + can be used as operators. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_SSL_CIPHER_LIST', 10259); /** * Set proxy SSL behavior options, which is a bitmask of any of the following constants: * CURLSSLOPT_ALLOW_BEAST: do not attempt to use any workarounds for a security flaw in the SSL3 and TLS1.0 protocols. * CURLSSLOPT_NO_REVOKE: disable certificate revocation checks for those SSL backends where such behavior is present. (curl >= 7.44.0) * CURLSSLOPT_NO_PARTIALCHAIN: do not accept "partial" certificate chains, which it otherwise does by default. (curl >= 7.68.0) * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_SSL_OPTIONS', 261); /** * Set to 2 to verify in the HTTPS proxy's certificate name fields against the proxy name. * When set to 0 the connection succeeds regardless of the names used in the certificate. * Use that ability with caution! 1 treated as a debug option in curl 7.28.0 and earlier. * From curl 7.28.1 to 7.65.3 CURLE_BAD_FUNCTION_ARGUMENT is returned. * From curl 7.66.0 onwards 1 and 2 is treated as the same value. * In production environments the value of this option should be kept at 2 (default value). * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_SSL_VERIFYHOST', 249); /** * FALSE to stop cURL from verifying the peer's certificate. * Alternate certificates to verify against can be specified with the CURLOPT_CAINFO option or * a certificate directory can be specified with the CURLOPT_CAPATH option. * When set to false, the peer certificate verification succeeds regardless. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_SSL_VERIFYPEER', 248); /** * The file name of your client certificate used to connect to the HTTPS proxy. * The default format is "P12" on Secure Transport and "PEM" on other engines, and can be changed with CURLOPT_PROXY_SSLCERTTYPE. * With NSS or Secure Transport, this can also be the nickname of the certificate you wish to authenticate with as it is named in the security database. * If you want to use a file from the current directory, please precede it with "./" prefix, in order to avoid confusion with a nickname. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PROXY_SSLCERT', 10254); /** * The URL scheme used for the most recent connection * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_SCHEME', 1048625); /** * Supports UNIX sockets. * @link https://www.php.net/manual/en/curl.constants.php * @since 7.0.7 */ define('CURL_VERSION_UNIX_SOCKETS', 524288); /** * The version used in the last HTTP connection. The return value will be one of the defined * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_HTTP_VERSION', 2097198); /** * Set a string holding the host name or dotted numerical IP address to be used as the preproxy that curl connects to before * it connects to the HTTP(S) proxy specified in the CURLOPT_PROXY option for the upcoming request. * The preproxy can only be a SOCKS proxy and it should be prefixed with [scheme]:// to specify which kind of socks is used. * A numerical IPv6 address must be written within [brackets]. Setting the preproxy to an empty string explicitly disables the use of a preproxy. * To specify port number in this string, append :[port] to the end of the host name. * The proxy's port number may optionally be specified with the separate option CURLOPT_PROXYPORT. * Defaults to using port 1080 for proxies if a port is not specified. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_PRE_PROXY', 10262); /** * The result of the certificate verification that was requested (using the CURLOPT_PROXY_SSL_VERIFYPEER option). * Only used for HTTPS proxies * @link https://www.php.net/manual/en/function.curl-getinfo.php * @since 7.3 */ define('CURLINFO_PROXY_SSL_VERIFYRESULT', 2097199); /** * Whether to allow HTTP/0.9 responses. * Defaults to FALSE as of libcurl 7.66.0; formerly it defaulted to TRUE. * @link https://www.php.net/manual/en/function.curl-setopt.php * @since 7.3 */ define('CURLOPT_HTTP09_ALLOWED', 285); /** * @link https://www.php.net/manual/en/curl.constants.php * @since 7.3.6 */ define('CURL_VERSION_ALTSVC', 16777216); /** * @since 8.1 */ define('CURLOPT_DOH_URL', 10279); /** * @since 8.1 */ define('CURLOPT_ISSUERCERT_BLOB', 40295); /** * @since 8.1 */ define('CURLOPT_PROXY_ISSUERCERT', 10296); /** * @since 8.1 */ define('CURLOPT_PROXY_ISSUERCERT_BLOB', 40297); /** * @since 8.1 */ define('CURLOPT_PROXY_SSLCERT_BLOB', 40293); /** * @since 8.1 */ define('CURLOPT_PROXY_SSLKEY_BLOB', 40294); /** * @since 8.1 */ define('CURLOPT_SSLCERT_BLOB', 40291); /** * @since 8.1 */ define('CURLOPT_SSLKEY_BLOB', 40292); /** * @since 8.2 */ define('CURLOPT_XFERINFOFUNCTION', 20219); /** * @since 8.2 */ define('CURLINFO_EFFECTIVE_METHOD', 1048634); /** * @since 8.2 */ define('CURLOPT_MAXFILESIZE_LARGE', 30117); /** * @since 8.2 */ define('CURLFTPMETHOD_DEFAULT', 0); /** * @since 8.2 */ define('CURLOPT_UPKEEP_INTERVAL_MS', 281); /** * @since 8.2 */ define('CURLOPT_UPLOAD_BUFFERSIZE', 280); /** * @since 8.2 */ define('CURLALTSVC_H1', 8); /** * @since 8.2 */ define('CURLALTSVC_H2', 16); /** * @since 8.2 */ define('CURLALTSVC_H3', 32); /** * @since 8.2 */ define('CURLALTSVC_READONLYFILE', 4); /** * @since 8.2 */ define('CURLOPT_ALTSVC', 10287); /** * @since 8.2 */ define('CURLOPT_ALTSVC_CTRL', 286); /** * @since 8.2 */ define('CURLOPT_MAXAGE_CONN', 288); /** * @since 8.2 */ define('CURLOPT_SASL_AUTHZID', 10289); /** * @since 8.2 */ define('CURL_VERSION_HTTP3', 33554432); /** * @since 8.2 */ define('CURLINFO_RETRY_AFTER', 6291513); /** * @since 8.2 */ define('CURLMOPT_MAX_CONCURRENT_STREAMS', 16); /** * @since 8.2 */ define('CURLSSLOPT_NO_PARTIALCHAIN', 4); /** * @since 8.2 */ define('CURLOPT_MAIL_RCPT_ALLLOWFAILS', 290); /** * @since 8.2 */ define('CURLSSLOPT_REVOKE_BEST_EFFORT', 8); /** * @since 8.2 */ define('CURLPROTO_MQTT', 268435456); /** * @since 8.2 */ define('CURLSSLOPT_NATIVE_CA', 16); /** * @since 8.2 */ define('CURL_VERSION_UNICODE', 134217728); /** * @since 8.2 */ define('CURL_VERSION_ZSTD', 67108864); /** * @since 8.2 */ define('CURLE_PROXY', 97); /** * @since 8.2 */ define('CURLINFO_PROXY_ERROR', 2097211); /** * @since 8.2 */ define('CURLOPT_SSL_EC_CURVES', 10298); /** * @since 8.2 */ define('CURLPX_BAD_ADDRESS_TYPE', 1); /** * @since 8.2 */ define('CURLPX_BAD_VERSION', 2); /** * @since 8.2 */ define('CURLPX_CLOSED', 3); /** * @since 8.2 */ define('CURLPX_GSSAPI', 4); /** * @since 8.2 */ define('CURLPX_GSSAPI_PERMSG', 5); /** * @since 8.2 */ define('CURLPX_GSSAPI_PROTECTION', 6); /** * @since 8.2 */ define('CURLPX_IDENTD', 7); /** * @since 8.2 */ define('CURLPX_IDENTD_DIFFER', 8); /** * @since 8.2 */ define('CURLPX_LONG_HOSTNAME', 9); /** * @since 8.2 */ define('CURLPX_LONG_PASSWD', 10); /** * @since 8.2 */ define('CURLPX_LONG_USER', 11); /** * @since 8.2 */ define('CURLPX_NO_AUTH', 12); /** * @since 8.2 */ define('CURLPX_OK', 0); /** * @since 8.2 */ define('CURLPX_RECV_ADDRESS', 13); /** * @since 8.2 */ define('CURLPX_RECV_AUTH', 14); /** * @since 8.2 */ define('CURLPX_RECV_CONNECT', 15); /** * @since 8.2 */ define('CURLPX_RECV_REQACK', 16); /** * @since 8.2 */ define('CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED', 17); /** * @since 8.2 */ define('CURLPX_REPLY_COMMAND_NOT_SUPPORTED', 18); /** * @since 8.2 */ define('CURLPX_REPLY_CONNECTION_REFUSED', 19); /** * @since 8.2 */ define('CURLPX_REPLY_GENERAL_SERVER_FAILURE', 20); /** * @since 8.2 */ define('CURLPX_REPLY_HOST_UNREACHABLE', 21); /** * @since 8.2 */ define('CURLPX_REPLY_NETWORK_UNREACHABLE', 22); /** * @since 8.2 */ define('CURLPX_REPLY_NOT_ALLOWED', 23); /** * @since 8.2 */ define('CURLPX_REPLY_TTL_EXPIRED', 24); /** * @since 8.2 */ define('CURLPX_REPLY_UNASSIGNED', 25); /** * @since 8.2 */ define('CURLPX_REQUEST_FAILED', 26); /** * @since 8.2 */ define('CURLPX_RESOLVE_HOST', 27); /** * @since 8.2 */ define('CURLPX_SEND_CONNECT', 29); /** * @since 8.2 */ define('CURLPX_SEND_AUTH', 28); /** * @since 8.2 */ define('CURLPX_SEND_REQUEST', 30); /** * @since 8.2 */ define('CURLPX_UNKNOWN_FAIL', 31); /** * @since 8.2 */ define('CURLPX_UNKNOWN_MODE', 32); /** * @since 8.2 */ define('CURLPX_USER_REJECTED', 33); /** * @since 8.2 */ define('CURLHSTS_ENABLE', 1); /** * @since 8.2 */ define('CURLHSTS_READONLYFILE', 2); /** * @since 8.2 */ define('CURLOPT_HSTS', 10300); /** * @since 8.2 */ define('CURLOPT_HSTS_CTRL', 299); /** * @since 8.2 */ define('CURL_VERSION_HSTS', 268435456); /** * @since 8.2 */ define('CURLAUTH_AWS_SIGV4', 128); /** * @since 8.2 */ define('CURLOPT_AWS_SIGV4', 10305); /** * @since 8.2 */ define('CURLINFO_REFERER', 1048636); /** * @since 8.2 */ define('CURLOPT_DOH_SSL_VERIFYHOST', 307); /** * @since 8.2 */ define('CURLOPT_DOH_SSL_VERIFYPEER', 306); /** * @since 8.2 */ define('CURLOPT_DOH_SSL_VERIFYSTATUS', 308); /** * @since 8.2 */ define('CURL_VERSION_GSASL', 536870912); /** * @since 8.2 */ define('CURLOPT_CAINFO_BLOB', 40309); /** * @since 8.2 */ define('CURLOPT_PROXY_CAINFO_BLOB', 40310); /** * @since 8.2 */ define('CURLSSLOPT_AUTO_CLIENT_CERT', 32); /** * @since 8.2 */ define('CURLOPT_MAXLIFETIME_CONN', 314); /** * @since 8.2 */ define('CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256', 10311); /** * @since 8.4 */ define('CURL_HTTP_VERSION_3', 30); /** * @since 8.4 */ define('CURL_HTTP_VERSION_3ONLY', 31); /** * @since 8.4 */ define('CURLOPT_PREREQFUNCTION', 20312); /** * @since 8.4 */ define('CURL_PREREQFUNC_OK', 0); /** * @since 8.4 */ define('CURL_PREREQFUNC_ABORT', 1); /** * @since 8.4 */ define('CURLOPT_TCP_KEEPCNT', 326); 'string'], default: '')] public $name; #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $mime; #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $postname; /** * Create a CURLFile object * @link https://secure.php.net/manual/en/curlfile.construct.php * @param string $filename

    Path to the file which will be uploaded.

    * @param string $mime_type [optional]

    Mimetype of the file.

    * @param string $posted_filename [optional]

    Name of the file.

    * @since 5.5 */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $mime_type = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $posted_filename = null ) {} /** * Get file name * @link https://secure.php.net/manual/en/curlfile.getfilename.php * @return string Returns file name. * @since 5.5 */ #[Pure] #[TentativeType] public function getFilename(): string {} /** * Get MIME type * @link https://secure.php.net/manual/en/curlfile.getmimetype.php * @return string Returns MIME type. * @since 5.5 */ #[Pure] #[TentativeType] public function getMimeType(): string {} /** * Get file name for POST * @link https://secure.php.net/manual/en/curlfile.getpostfilename.php * @return string Returns file name for POST. * @since 5.5 */ #[Pure] #[TentativeType] public function getPostFilename(): string {} /** * Set MIME type * @link https://secure.php.net/manual/en/curlfile.setmimetype.php * @param string $mime_type * @since 5.5 */ #[TentativeType] public function setMimeType(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $mime_type): void {} /** * Set file name for POST * https://secure.php.net/manual/en/curlfile.setpostfilename.php * @param string $posted_filename * @since 5.5 */ #[TentativeType] public function setPostFilename(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $posted_filename): void {} /** * @link https://secure.php.net/manual/en/curlfile.wakeup.php * Unserialization handler * @since 5.5 */ public function __wakeup() {} } /** * Initialize a cURL session * @link https://php.net/manual/en/function.curl-init.php * @param string|null $url [optional]

    * If provided, the CURLOPT_URL option will be set * to its value. You can manually set this using the * curl_setopt function. *

    * @return resource|false|CurlHandle a cURL handle on success, false on errors. */ #[LanguageLevelTypeAware(['8.0' => 'CurlHandle|false'], default: 'resource|false')] function curl_init(?string $url) {} /** * Copy a cURL handle along with all of its preferences * @link https://php.net/manual/en/function.curl-copy-handle.php * @param CurlHandle|resource $handle * @return CurlHandle|resource|false a new cURL handle. */ #[Pure] #[LanguageLevelTypeAware(['8.0' => 'CurlHandle|false'], default: 'resource|false')] function curl_copy_handle(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle) {} /** * Gets cURL version information * @link https://php.net/manual/en/function.curl-version.php * @param int $age [optional] Removed since version PHP 8.0. * @return array|false an associative array with the following elements: * * Indice * Value description * * * version_number * cURL 24 bit version number * * * version * cURL version number, as a string * * * ssl_version_number * OpenSSL 24 bit version number * * * ssl_version * OpenSSL version number, as a string * * * libz_version * zlib version number, as a string * * * host * Information about the host where cURL was built * * * age * * * * features * A bitmask of the CURL_VERSION_XXX constants * * * protocols * An array of protocols names supported by cURL * */ #[ArrayShape(["version_number" => "string", "version" => "string", "ssl_version_number" => "int", "ssl_version" => "string", "libz_version" => "string", "host" => "string", "age" => "int", "features" => "int", "protocols" => "array"])] #[Pure] function curl_version(#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $age = null): array|false {} /** * Set an option for a cURL transfer * @link https://php.net/manual/en/function.curl-setopt.php * @param CurlHandle|resource $handle * @param int $option

    * The CURLOPT_XXX option to set. *

    * @param mixed|callable $value

    * The value to be set on option. *

    *

    * value should be a bool for the * following values of the option parameter:

    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    OptionSet value toNotes
    CURLOPT_AUTOREFERER * TRUE to automatically set the Referer: field in * requests where it follows a Location: redirect. * *
    CURLOPT_BINARYTRANSFER * TRUE to return the raw output when * CURLOPT_RETURNTRANSFER is used. * * From PHP 5.1.3, this option has no effect: the raw output will * always be returned when * CURLOPT_RETURNTRANSFER is used. *
    CURLOPT_COOKIESESSION * TRUE to mark this as a new cookie "session". It will force libcurl * to ignore all cookies it is about to load that are "session cookies" * from the previous session. By default, libcurl always stores and * loads all cookies, independent if they are session cookies or not. * Session cookies are cookies without expiry date and they are meant * to be alive and existing for this "session" only. * *
    CURLOPT_CERTINFO * TRUE to output SSL certification information to STDERR * on secure transfers. * * Added in cURL 7.19.1. * Available since PHP 5.3.2. * Requires CURLOPT_VERBOSE to be on to have an effect. *
    CURLOPT_CONNECT_ONLY * TRUE tells the library to perform all the required proxy authentication * and connection setup, but no data transfer. This option is implemented for * HTTP, SMTP and POP3. * * Added in 7.15.2. * Available since PHP 5.5.0. *
    CURLOPT_CRLF * TRUE to convert Unix newlines to CRLF newlines * on transfers. * *
    CURLOPT_DNS_USE_GLOBAL_CACHE * TRUE to use a global DNS cache. This option is * not thread-safe and is enabled by default. * *
    CURLOPT_FAILONERROR * TRUE to fail verbosely if the HTTP code returned * is greater than or equal to 400. The default behavior is to return * the page normally, ignoring the code. * *
    CURLOPT_FILETIME * TRUE to attempt to retrieve the modification * date of the remote document. This value can be retrieved using * the CURLINFO_FILETIME option with * {@see curl_getinfo()}. * *
    CURLOPT_FOLLOWLOCATION * TRUE to follow any * "Location: " header that the server sends as * part of the HTTP header (note this is recursive, PHP will follow as * many "Location: " headers that it is sent, * unless CURLOPT_MAXREDIRS is set). * *
    CURLOPT_FORBID_REUSE * TRUE to force the connection to explicitly * close when it has finished processing, and not be pooled for reuse. * *
    CURLOPT_FRESH_CONNECT * TRUE to force the use of a new connection * instead of a cached one. * *
    CURLOPT_FTP_USE_EPRT * TRUE to use EPRT (and LPRT) when doing active * FTP downloads. Use FALSE to disable EPRT and LPRT and use PORT * only. * *
    CURLOPT_FTP_USE_EPSV * TRUE to first try an EPSV command for FTP * transfers before reverting back to PASV. Set to FALSE * to disable EPSV. * *
    CURLOPT_FTP_CREATE_MISSING_DIRS * TRUE to create missing directories when an FTP operation * encounters a path that currently doesn't exist. * *
    CURLOPT_FTPAPPEND * TRUE to append to the remote file instead of * overwriting it. * *
    CURLOPT_TCP_NODELAY * TRUE to disable TCP's Nagle algorithm, which tries to minimize * the number of small packets on the network. * * Available since PHP 5.2.1 for versions compiled with libcurl 7.11.2 or * greater. *
    CURLOPT_FTPASCII * An alias of * CURLOPT_TRANSFERTEXT. Use that instead. * *
    CURLOPT_FTPLISTONLY * TRUE to only list the names of an FTP * directory. * *
    CURLOPT_HEADER * TRUE to include the header in the output. * *
    CURLINFO_HEADER_OUT * TRUE to track the handle's request string. * * Available since PHP 5.1.3. The CURLINFO_ * prefix is intentional. *
    CURLOPT_HTTPGET * TRUE to reset the HTTP request method to GET. * Since GET is the default, this is only necessary if the request * method has been changed. * *
    CURLOPT_HTTPPROXYTUNNEL * TRUE to tunnel through a given HTTP proxy. * *
    CURLOPT_MUTE * TRUE to be completely silent with regards to * the cURL functions. * * Removed in cURL 7.15.5 (You can use CURLOPT_RETURNTRANSFER instead) *
    CURLOPT_NETRC * TRUE to scan the ~/.netrc * file to find a username and password for the remote site that * a connection is being established with. * *
    CURLOPT_NOBODY * TRUE to exclude the body from the output. * Request method is then set to HEAD. Changing this to FALSE does * not change it to GET. * *
    CURLOPT_NOPROGRESS

    * TRUE to disable the progress meter for cURL transfers. *

    Note: *

    * PHP automatically sets this option to TRUE, this should only be * changed for debugging purposes. *

    *
    *
    *
    CURLOPT_NOSIGNAL * TRUE to ignore any cURL function that causes a * signal to be sent to the PHP process. This is turned on by default * in multi-threaded SAPIs so timeout options can still be used. * * Added in cURL 7.10. *
    CURLOPT_POST * TRUE to do a regular HTTP POST. This POST is the * normal application/x-www-form-urlencoded kind, * most commonly used by HTML forms. * *
    CURLOPT_PUT * TRUE to HTTP PUT a file. The file to PUT must * be set with CURLOPT_INFILE and * CURLOPT_INFILESIZE. * *
    CURLOPT_RETURNTRANSFER * TRUE to return the transfer as a string of the * return value of {@see curl_exec()} instead of outputting * it out directly. * *
    CURLOPT_SAFE_UPLOAD * TRUE to disable support for the @ prefix for * uploading files in CURLOPT_POSTFIELDS, which * means that values starting with @ can be safely * passed as fields. {@see CURLFile} may be used for * uploads instead. * * Added in PHP 5.5.0 with FALSE as the default value. PHP 5.6.0 * changes the default value to TRUE. *
    CURLOPT_SSL_VERIFYPEER * FALSE to stop cURL from verifying the peer's * certificate. Alternate certificates to verify against can be * specified with the CURLOPT_CAINFO option * or a certificate directory can be specified with the * CURLOPT_CAPATH option. * * TRUE by default as of cURL 7.10. Default bundle installed as of * cURL 7.10. *
    CURLOPT_TRANSFERTEXT * TRUE to use ASCII mode for FTP transfers. * For LDAP, it retrieves data in plain text instead of HTML. On * Windows systems, it will not set STDOUT to binary * mode. * *
    CURLOPT_UNRESTRICTED_AUTH * TRUE to keep sending the username and password * when following locations (using * CURLOPT_FOLLOWLOCATION), even when the * hostname has changed. * *
    CURLOPT_UPLOAD * TRUE to prepare for an upload. * *
    CURLOPT_VERBOSE * TRUE to output verbose information. Writes * output to STDERR, or the file specified using * CURLOPT_STDERR. * *
    * * value should be an integer for the following values of the option parameter: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    OptionSet value toNotes
    CURLOPT_BUFFERSIZE * The size of the buffer to use for each read. There is no guarantee * this request will be fulfilled, however. * * Added in cURL 7.10. *
    CURLOPT_CLOSEPOLICY * One of the CURLCLOSEPOLICY_* values. *

    Note: *

    * This option is deprecated, as it was never implemented in cURL and * never had any effect. *

    *
    *
    * Removed in PHP 5.6.0. *
    CURLOPT_CONNECTTIMEOUT * The number of seconds to wait while trying to connect. Use 0 to * wait indefinitely. * *
    CURLOPT_CONNECTTIMEOUT_MS * The number of milliseconds to wait while trying to connect. Use 0 to * wait indefinitely. * * If libcurl is built to use the standard system name resolver, that * portion of the connect will still use full-second resolution for * timeouts with a minimum timeout allowed of one second. * * Added in cURL 7.16.2. Available since PHP 5.2.3. *
    CURLOPT_DNS_CACHE_TIMEOUT * The number of seconds to keep DNS entries in memory. This * option is set to 120 (2 minutes) by default. * *
    CURLOPT_FTPSSLAUTH * The FTP authentication method (when is activated): * CURLFTPAUTH_SSL (try SSL first), * CURLFTPAUTH_TLS (try TLS first), or * CURLFTPAUTH_DEFAULT (let cURL decide). * * Added in cURL 7.12.2. *
    CURLOPT_HTTP_VERSION * CURL_HTTP_VERSION_NONE (default, lets CURL * decide which version to use), * CURL_HTTP_VERSION_1_0 (forces HTTP/1.0), * or CURL_HTTP_VERSION_1_1 (forces HTTP/1.1). * *
    CURLOPT_HTTPAUTH *

    * The HTTP authentication method(s) to use. The options are: * CURLAUTH_BASIC, * CURLAUTH_DIGEST, * CURLAUTH_GSSNEGOTIATE, * CURLAUTH_NTLM, * CURLAUTH_ANY, and * CURLAUTH_ANYSAFE. *

    *

    * The bitwise | (or) operator can be used to combine * more than one method. If this is done, cURL will poll the server to see * what methods it supports and pick the best one. *

    *

    * CURLAUTH_ANY is an alias for * CURLAUTH_BASIC | CURLAUTH_DIGEST | CURLAUTH_GSSNEGOTIATE | CURLAUTH_NTLM. *

    *

    * CURLAUTH_ANYSAFE is an alias for * CURLAUTH_DIGEST | CURLAUTH_GSSNEGOTIATE | CURLAUTH_NTLM. *

    *
    *
    CURLOPT_INFILESIZE * The expected size, in bytes, of the file when uploading a file to * a remote site. Note that using this option will not stop libcurl * from sending more data, as exactly what is sent depends on * CURLOPT_READFUNCTION. * *
    CURLOPT_LOW_SPEED_LIMIT * The transfer speed, in bytes per second, that the transfer should be * below during the count of CURLOPT_LOW_SPEED_TIME * seconds before PHP considers the transfer too slow and aborts. * *
    CURLOPT_LOW_SPEED_TIME * The number of seconds the transfer speed should be below * CURLOPT_LOW_SPEED_LIMIT before PHP considers * the transfer too slow and aborts. * *
    CURLOPT_MAXCONNECTS * The maximum amount of persistent connections that are allowed. * When the limit is reached, * CURLOPT_CLOSEPOLICY is used to determine * which connection to close. * *
    CURLOPT_MAXREDIRS * The maximum amount of HTTP redirections to follow. Use this option * alongside CURLOPT_FOLLOWLOCATION. * *
    CURLOPT_PORT * An alternative port number to connect to. * *
    CURLOPT_POSTREDIR * A bitmask of 1 (301 Moved Permanently), 2 (302 Found) * vand 4 (303 See Other) if the HTTP POST method should be maintained * when CURLOPT_FOLLOWLOCATION is set and a * specific type of redirect occurs. * * Added in cURL 7.19.1. Available since PHP 5.3.2. *
    CURLOPT_PROTOCOLS *

    * Bitmask of CURLPROTO_* values. If used, this bitmask * limits what protocols libcurl may use in the transfer. This allows you to have * a libcurl built to support a wide range of protocols but still limit specific * transfers to only be allowed to use a subset of them. By default libcurl will * accept all protocols it supports. * See also CURLOPT_REDIR_PROTOCOLS. *

    *

    * Valid protocol options are: * CURLPROTO_HTTP, * CURLPROTO_HTTPS, * CURLPROTO_FTP, * CURLPROTO_FTPS, * CURLPROTO_SCP, * CURLPROTO_SFTP, * CURLPROTO_TELNET, * CURLPROTO_LDAP, * CURLPROTO_LDAPS, * CURLPROTO_DICT, * CURLPROTO_FILE, * CURLPROTO_TFTP, * CURLPROTO_ALL *

    *
    * Added in cURL 7.19.4. *
    CURLOPT_PROXYAUTH * The HTTP authentication method(s) to use for the proxy connection. * Use the same bitmasks as described in * CURLOPT_HTTPAUTH. For proxy authentication, * only CURLAUTH_BASIC and * CURLAUTH_NTLM are currently supported. * * Added in cURL 7.10.7. *
    CURLOPT_PROXYPORT * The port number of the proxy to connect to. This port number can * also be set in CURLOPT_PROXY. * *
    CURLOPT_PROXYTYPE * Either CURLPROXY_HTTP (default), * CURLPROXY_SOCKS4, * CURLPROXY_SOCKS5, * CURLPROXY_SOCKS4A or * CURLPROXY_SOCKS5_HOSTNAME. * * Added in cURL 7.10. *
    CURLOPT_REDIR_PROTOCOLS * Bitmask of CURLPROTO_* values. If used, this bitmask * limits what protocols libcurl may use in a transfer that it follows to in * a redirect when CURLOPT_FOLLOWLOCATION is enabled. * This allows you to limit specific transfers to only be allowed to use a subset * of protocols in redirections. By default libcurl will allow all protocols * except for FILE and SCP. This is a difference compared to pre-7.19.4 versions * which unconditionally would follow to all protocols supported. * See also CURLOPT_PROTOCOLS for protocol constant values. * * Added in cURL 7.19.4. *
    CURLOPT_RESUME_FROM * The offset, in bytes, to resume a transfer from. * *
    CURLOPT_SSL_VERIFYHOST * 1 to check the existence of a common name in the * SSL peer certificate. 2 to check the existence of * a common name and also verify that it matches the hostname * provided. In production environments the value of this option * should be kept at 2 (default value). * * Support for value 1 removed in cURL 7.28.1 *
    CURLOPT_SSLVERSION * One of CURL_SSLVERSION_DEFAULT (0), * CURL_SSLVERSION_TLSv1 (1), * CURL_SSLVERSION_SSLv2 (2), * CURL_SSLVERSION_SSLv3 (3), * CURL_SSLVERSION_TLSv1_0 (4), * CURL_SSLVERSION_TLSv1_1 (5) or * CURL_SSLVERSION_TLSv1_2 (6). *

    Note: *

    * Your best bet is to not set this and let it use the default. * Setting it to 2 or 3 is very dangerous given the known * vulnerabilities in SSLv2 and SSLv3. *

    *
    *
    *
    CURLOPT_TIMECONDITION * How CURLOPT_TIMEVALUE is treated. * Use CURL_TIMECOND_IFMODSINCE to return the * page only if it has been modified since the time specified in * CURLOPT_TIMEVALUE. If it hasn't been modified, * a "304 Not Modified" header will be returned * assuming CURLOPT_HEADER is TRUE. * Use CURL_TIMECOND_IFUNMODSINCE for the reverse * effect. CURL_TIMECOND_IFMODSINCE is the * default. * *
    CURLOPT_TIMEOUT * The maximum number of seconds to allow cURL functions to execute. * *
    CURLOPT_TIMEOUT_MS * The maximum number of milliseconds to allow cURL functions to * execute. * * If libcurl is built to use the standard system name resolver, that * portion of the connect will still use full-second resolution for * timeouts with a minimum timeout allowed of one second. * * Added in cURL 7.16.2. Available since PHP 5.2.3. *
    CURLOPT_TIMEVALUE * The time in seconds since January 1st, 1970. The time will be used * by CURLOPT_TIMECONDITION. By default, * CURL_TIMECOND_IFMODSINCE is used. * *
    CURLOPT_MAX_RECV_SPEED_LARGE * If a download exceeds this speed (counted in bytes per second) on * cumulative average during the transfer, the transfer will pause to * keep the average rate less than or equal to the parameter value. * Defaults to unlimited speed. * * Added in cURL 7.15.5. Available since PHP 5.4.0. *
    CURLOPT_MAX_SEND_SPEED_LARGE * If an upload exceeds this speed (counted in bytes per second) on * cumulative average during the transfer, the transfer will pause to * keep the average rate less than or equal to the parameter value. * Defaults to unlimited speed. * * Added in cURL 7.15.5. Available since PHP 5.4.0. *
    CURLOPT_SSH_AUTH_TYPES * A bitmask consisting of one or more of * CURLSSH_AUTH_PUBLICKEY, * CURLSSH_AUTH_PASSWORD, * CURLSSH_AUTH_HOST, * CURLSSH_AUTH_KEYBOARD. Set to * CURLSSH_AUTH_ANY to let libcurl pick one. * * Added in cURL 7.16.1. *
    CURLOPT_IPRESOLVE * Allows an application to select what kind of IP addresses to use when * resolving host names. This is only interesting when using host names that * resolve addresses using more than one version of IP, possible values are * CURL_IPRESOLVE_WHATEVER, * CURL_IPRESOLVE_V4, * CURL_IPRESOLVE_V6, by default * CURL_IPRESOLVE_WHATEVER. * * Added in cURL 7.10.8. *
    * * value should be a string for the following values of the option parameter: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    OptionSet value toNotes
    CURLOPT_CAINFO * The name of a file holding one or more certificates to verify the * peer with. This only makes sense when used in combination with * CURLOPT_SSL_VERIFYPEER. * * Might require an absolute path. *
    CURLOPT_CAPATH * A directory that holds multiple CA certificates. Use this option * alongside CURLOPT_SSL_VERIFYPEER. * *
    CURLOPT_COOKIE * The contents of the "Cookie: " header to be * used in the HTTP request. * Note that multiple cookies are separated with a semicolon followed * by a space (e.g., "fruit=apple; colour=red") * *
    CURLOPT_COOKIEFILE * The name of the file containing the cookie data. The cookie file can * be in Netscape format, or just plain HTTP-style headers dumped into * a file. * If the name is an empty string, no cookies are loaded, but cookie * handling is still enabled. * *
    CURLOPT_COOKIEJAR * The name of a file to save all internal cookies to when the handle is closed, * e.g. after a call to curl_close. * *
    CURLOPT_CUSTOMREQUEST

    * A custom request method to use instead of * "GET" or "HEAD" when doing * a HTTP request. This is useful for doing * "DELETE" or other, more obscure HTTP requests. * Valid values are things like "GET", * "POST", "CONNECT" and so on; * i.e. Do not enter a whole HTTP request line here. For instance, * entering "GET /index.html HTTP/1.0\r\n\r\n" * would be incorrect. *

    Note: *

    * Don't do this without making sure the server supports the custom * request method first. *

    *
    *
    *
    CURLOPT_EGDSOCKET * Like CURLOPT_RANDOM_FILE, except a filename * to an Entropy Gathering Daemon socket. * *
    CURLOPT_ENCODING * The contents of the "Accept-Encoding: " header. * This enables decoding of the response. Supported encodings are * "identity", "deflate", and * "gzip". If an empty string, "", * is set, a header containing all supported encoding types is sent. * * Added in cURL 7.10. *
    CURLOPT_FTPPORT * The value which will be used to get the IP address to use * for the FTP "PORT" instruction. The "PORT" instruction tells * the remote server to connect to our specified IP address. The * string may be a plain IP address, a hostname, a network * interface name (under Unix), or just a plain '-' to use the * systems default IP address. * *
    CURLOPT_INTERFACE * The name of the outgoing network interface to use. This can be an * interface name, an IP address or a host name. * *
    CURLOPT_KEYPASSWD * The password required to use the CURLOPT_SSLKEY * or CURLOPT_SSH_PRIVATE_KEYFILE private key. * * Added in cURL 7.16.1. *
    CURLOPT_KRB4LEVEL * The KRB4 (Kerberos 4) security level. Any of the following values * (in order from least to most powerful) are valid: * "clear", * "safe", * "confidential", * "private".. * If the string does not match one of these, * "private" is used. Setting this option to NULL * will disable KRB4 security. Currently KRB4 security only works * with FTP transactions. * *
    CURLOPT_POSTFIELDS * * The full data to post in a HTTP "POST" operation. * To post a file, prepend a filename with @ and * use the full path. The filetype can be explicitly specified by * following the filename with the type in the format * ';type=mimetype'. This parameter can either be * passed as a urlencoded string like 'para1=val1&para2=val2&...' * or as an array with the field name as key and field data as value. * If value is an array, the * Content-Type header will be set to * multipart/form-data. * * * As of PHP 5.2.0, value must be an array if * files are passed to this option with the @ prefix. * * * As of PHP 5.5.0, the @ prefix is deprecated and * files can be sent using CURLFile. The * @ prefix can be disabled for safe passing of * values beginning with @ by setting the * CURLOPT_SAFE_UPLOAD option to TRUE. * * *
    CURLOPT_PROXY * The HTTP proxy to tunnel requests through. * *
    CURLOPT_PROXYUSERPWD * A username and password formatted as * "[username]:[password]" to use for the * connection to the proxy. * *
    CURLOPT_RANDOM_FILE * A filename to be used to seed the random number generator for SSL. * *
    CURLOPT_RANGE * Range(s) of data to retrieve in the format * "X-Y" where X or Y are optional. HTTP transfers * also support several intervals, separated with commas in the format * "X-Y,N-M". * *
    CURLOPT_REFERER * The contents of the "Referer: " header to be used * in a HTTP request. * *
    CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 * A string containing 32 hexadecimal digits. The string should be the * MD5 checksum of the remote host's public key, and libcurl will reject * the connection to the host unless the md5sums match. * This option is only for SCP and SFTP transfers. * * Added in cURL 7.17.1. *
    CURLOPT_SSH_PUBLIC_KEYFILE * The file name for your public key. If not used, libcurl defaults to * $HOME/.ssh/id_dsa.pub if the HOME environment variable is set, * and just "id_dsa.pub" in the current directory if HOME is not set. * * Added in cURL 7.16.1. *
    CURLOPT_SSH_PRIVATE_KEYFILE * The file name for your private key. If not used, libcurl defaults to * $HOME/.ssh/id_dsa if the HOME environment variable is set, * and just "id_dsa" in the current directory if HOME is not set. * If the file is password-protected, set the password with * CURLOPT_KEYPASSWD. * * Added in cURL 7.16.1. *
    CURLOPT_SSL_CIPHER_LIST * A list of ciphers to use for SSL. For example, * RC4-SHA and TLSv1 are valid * cipher lists. * *
    CURLOPT_SSLCERT * The name of a file containing a PEM formatted certificate. * *
    CURLOPT_SSLCERTPASSWD * The password required to use the * CURLOPT_SSLCERT certificate. * *
    CURLOPT_SSLCERTTYPE * The format of the certificate. Supported formats are * "PEM" (default), "DER", * and "ENG". * * Added in cURL 7.9.3. *
    CURLOPT_SSLENGINE * The identifier for the crypto engine of the private SSL key * specified in CURLOPT_SSLKEY. * *
    CURLOPT_SSLENGINE_DEFAULT * The identifier for the crypto engine used for asymmetric crypto * operations. * *
    CURLOPT_SSLKEY * The name of a file containing a private SSL key. * *
    CURLOPT_SSLKEYPASSWD

    * The secret password needed to use the private SSL key specified in * CURLOPT_SSLKEY. *

    Note: *

    * Since this option contains a sensitive password, remember to keep * the PHP script it is contained within safe. *

    *
    *
    *
    CURLOPT_SSLKEYTYPE * The key type of the private SSL key specified in * CURLOPT_SSLKEY. Supported key types are * "PEM" (default), "DER", * and "ENG". * *
    CURLOPT_URL * The URL to fetch. This can also be set when initializing a * session with {@see curl_init()}. * *
    CURLOPT_USERAGENT * The contents of the "User-Agent: " header to be * used in a HTTP request. * *
    CURLOPT_USERPWD * A username and password formatted as * "[username]:[password]" to use for the * connection. * *
    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    OptionSet value toNotes
    CURLOPT_CAINFO * The name of a file holding one or more certificates to verify the * peer with. This only makes sense when used in combination with * CURLOPT_SSL_VERIFYPEER. * * Might require an absolute path. *
    CURLOPT_CAPATH * A directory that holds multiple CA certificates. Use this option * alongside CURLOPT_SSL_VERIFYPEER. * *
    CURLOPT_COOKIE * The contents of the "Cookie: " header to be * used in the HTTP request. * Note that multiple cookies are separated with a semicolon followed * by a space (e.g., "fruit=apple; colour=red") * *
    CURLOPT_COOKIEFILE * The name of the file containing the cookie data. The cookie file can * be in Netscape format, or just plain HTTP-style headers dumped into * a file. * If the name is an empty string, no cookies are loaded, but cookie * handling is still enabled. * *
    CURLOPT_COOKIEJAR * The name of a file to save all internal cookies to when the handle is closed, * e.g. after a call to curl_close. * *
    CURLOPT_CUSTOMREQUEST

    * A custom request method to use instead of * "GET" or "HEAD" when doing * a HTTP request. This is useful for doing * "DELETE" or other, more obscure HTTP requests. * Valid values are things like "GET", * "POST", "CONNECT" and so on; * i.e. Do not enter a whole HTTP request line here. For instance, * entering "GET /index.html HTTP/1.0\r\n\r\n" * would be incorrect. *

    Note: *

    * Don't do this without making sure the server supports the custom * request method first. *

    *
    *
    *
    CURLOPT_EGDSOCKET * Like CURLOPT_RANDOM_FILE, except a filename * to an Entropy Gathering Daemon socket. * *
    CURLOPT_ENCODING * The contents of the "Accept-Encoding: " header. * This enables decoding of the response. Supported encodings are * "identity", "deflate", and * "gzip". If an empty string, "", * is set, a header containing all supported encoding types is sent. * * Added in cURL 7.10. *
    CURLOPT_FTPPORT * The value which will be used to get the IP address to use * for the FTP "PORT" instruction. The "PORT" instruction tells * the remote server to connect to our specified IP address. The * string may be a plain IP address, a hostname, a network * interface name (under Unix), or just a plain '-' to use the * systems default IP address. * *
    CURLOPT_INTERFACE * The name of the outgoing network interface to use. This can be an * interface name, an IP address or a host name. * *
    CURLOPT_KEYPASSWD * The password required to use the CURLOPT_SSLKEY * or CURLOPT_SSH_PRIVATE_KEYFILE private key. * * Added in cURL 7.16.1. *
    CURLOPT_KRB4LEVEL * The KRB4 (Kerberos 4) security level. Any of the following values * (in order from least to most powerful) are valid: * "clear", * "safe", * "confidential", * "private".. * If the string does not match one of these, * "private" is used. Setting this option to NULL * will disable KRB4 security. Currently KRB4 security only works * with FTP transactions. * *
    CURLOPT_POSTFIELDS * * The full data to post in a HTTP "POST" operation. * To post a file, prepend a filename with @ and * use the full path. The filetype can be explicitly specified by * following the filename with the type in the format * ';type=mimetype'. This parameter can either be * passed as a urlencoded string like 'para1=val1&para2=val2&...' * or as an array with the field name as key and field data as value. * If value is an array, the * Content-Type header will be set to * multipart/form-data. * * * As of PHP 5.2.0, value must be an array if * files are passed to this option with the @ prefix. * * * As of PHP 5.5.0, the @ prefix is deprecated and * files can be sent using CURLFile. The * @ prefix can be disabled for safe passing of * values beginning with @ by setting the * CURLOPT_SAFE_UPLOAD option to TRUE. * * *
    CURLOPT_PROXY * The HTTP proxy to tunnel requests through. * *
    CURLOPT_PROXYUSERPWD * A username and password formatted as * "[username]:[password]" to use for the * connection to the proxy. * *
    CURLOPT_RANDOM_FILE * A filename to be used to seed the random number generator for SSL. * *
    CURLOPT_RANGE * Range(s) of data to retrieve in the format * "X-Y" where X or Y are optional. HTTP transfers * also support several intervals, separated with commas in the format * "X-Y,N-M". * *
    CURLOPT_REFERER * The contents of the "Referer: " header to be used * in a HTTP request. * *
    CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 * A string containing 32 hexadecimal digits. The string should be the * MD5 checksum of the remote host's public key, and libcurl will reject * the connection to the host unless the md5sums match. * This option is only for SCP and SFTP transfers. * * Added in cURL 7.17.1. *
    CURLOPT_SSH_PUBLIC_KEYFILE * The file name for your public key. If not used, libcurl defaults to * $HOME/.ssh/id_dsa.pub if the HOME environment variable is set, * and just "id_dsa.pub" in the current directory if HOME is not set. * * Added in cURL 7.16.1. *
    CURLOPT_SSH_PRIVATE_KEYFILE * The file name for your private key. If not used, libcurl defaults to * $HOME/.ssh/id_dsa if the HOME environment variable is set, * and just "id_dsa" in the current directory if HOME is not set. * If the file is password-protected, set the password with * CURLOPT_KEYPASSWD. * * Added in cURL 7.16.1. *
    CURLOPT_SSL_CIPHER_LIST * A list of ciphers to use for SSL. For example, * RC4-SHA and TLSv1 are valid * cipher lists. * *
    CURLOPT_SSLCERT * The name of a file containing a PEM formatted certificate. * *
    CURLOPT_SSLCERTPASSWD * The password required to use the * CURLOPT_SSLCERT certificate. * *
    CURLOPT_SSLCERTTYPE * The format of the certificate. Supported formats are * "PEM" (default), "DER", * and "ENG". * * Added in cURL 7.9.3. *
    CURLOPT_SSLENGINE * The identifier for the crypto engine of the private SSL key * specified in CURLOPT_SSLKEY. * *
    CURLOPT_SSLENGINE_DEFAULT * The identifier for the crypto engine used for asymmetric crypto * operations. * *
    CURLOPT_SSLKEY * The name of a file containing a private SSL key. * *
    CURLOPT_SSLKEYPASSWD

    * The secret password needed to use the private SSL key specified in * CURLOPT_SSLKEY. *

    Note: *

    * Since this option contains a sensitive password, remember to keep * the PHP script it is contained within safe. *

    *
    *
    *
    CURLOPT_SSLKEYTYPE * The key type of the private SSL key specified in * CURLOPT_SSLKEY. Supported key types are * "PEM" (default), "DER", * and "ENG". * *
    CURLOPT_URL * The URL to fetch. This can also be set when initializing a * session with curl_init(). * *
    CURLOPT_USERAGENT * The contents of the "User-Agent: " header to be * used in a HTTP request. * *
    CURLOPT_USERPWD * A username and password formatted as * "[username]:[password]" to use for the * connection. * *
    *

    * value should be an array for the following values of the option parameter:

    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    OptionSet value toNotes
    CURLOPT_HTTP200ALIASES * An array of HTTP 200 responses that will be treated as valid * responses and not as errors. * * Added in cURL 7.10.3. *
    CURLOPT_HTTPHEADER * An array of HTTP header fields to set, in the format * * array('Content-type: text/plain', 'Content-length: 100') * * *
    CURLOPT_POSTQUOTE * An array of FTP commands to execute on the server after the FTP * request has been performed. * *
    CURLOPT_QUOTE * An array of FTP commands to execute on the server prior to the FTP * request. * *
    * value should be a stream resource (using {@see fopen()}, for example) for the following values of the option parameter: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    OptionSet value to
    CURLOPT_FILE * The file that the transfer should be written to. The default * is STDOUT (the browser window). *
    CURLOPT_INFILE * The file that the transfer should be read from when uploading. *
    CURLOPT_STDERR * An alternative location to output errors to instead of * STDERR. *
    CURLOPT_WRITEHEADER * The file that the header part of the transfer is written to. *
    * value should be the name of a valid function or a Closure for the following values of the option parameter: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    OptionSet value to
    CURLOPT_HEADERFUNCTION * A callback accepting two parameters. * The first is the cURL resource, the second is a * string with the header data to be written. The header data must * be written by this callback. Return the number of * bytes written. *
    CURLOPT_PASSWDFUNCTION * A callback accepting three parameters. * The first is the cURL resource, the second is a * string containing a password prompt, and the third is the maximum * password length. Return the string containing the password. *
    CURLOPT_PROGRESSFUNCTION *

    * A callback accepting five parameters. * The first is the cURL resource, the second is the total number of * bytes expected to be downloaded in this transfer, the third is * the number of bytes downloaded so far, the fourth is the total * number of bytes expected to be uploaded in this transfer, and the * fifth is the number of bytes uploaded so far. *

    *

    Note: *

    * The callback is only called when the CURLOPT_NOPROGRESS * option is set to FALSE. *

    *
    *

    * Return a non-zero value to abort the transfer. In which case, the * transfer will set a CURLE_ABORTED_BY_CALLBACK * error. *

    *
    CURLOPT_READFUNCTION * A callback accepting three parameters. * The first is the cURL resource, the second is a * stream resource provided to cURL through the option * CURLOPT_INFILE, and the third is the maximum * amount of data to be read. The callback must return a string * with a length equal or smaller than the amount of data requested, * typically by reading it from the passed stream resource. It should * return an empty string to signal EOF. *
    CURLOPT_WRITEFUNCTION * A callback accepting two parameters. * The first is the cURL resource, and the second is a * string with the data to be written. The data must be saved by * this callback. It must return the exact number of bytes written * or the transfer will be aborted with an error. *
    * Other values: * * * * * * * * * * * * * * * * *
    OptionSet value to
    CURLOPT_SHARE * A result of {@see curl_share_init()}. Makes the cURL * handle to use the data from the shared handle. *
    * @return bool true on success or false on failure. */ function curl_setopt(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle, int $option, mixed $value): bool {} /** * Set multiple options for a cURL transfer * @link https://php.net/manual/en/function.curl-setopt-array.php * @param CurlHandle|resource $handle * @param array $options

    * An array specifying which options to set and their values. * The keys should be valid curl_setopt constants or * their integer equivalents. *

    * @return bool true if all options were successfully set. If an option could * not be successfully set, false is immediately returned, ignoring any * future options in the options array. * @since 5.1.3 */ function curl_setopt_array(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle, array $options): bool {} /** * (PHP 5 >=5.5.0)
    * Close a cURL share handle * @link https://secure.php.net/manual/en/function.curl-share-close.php * @param CurlShareHandle|resource $share_handle

    * A cURL share handle returned by {@link https://secure.php.net/manual/en/function.curl-share-init.php curl_share_init()} *

    * @return void * @since 5.5 */ function curl_share_close(#[LanguageLevelTypeAware(['8.0' => 'CurlShareHandle'], default: 'resource')] $share_handle): void {} /** * (PHP 5 >=5.5.0)
    * Initialize a cURL share handle * @link https://secure.php.net/manual/en/function.curl-share-init.php * @return resource|CurlShareHandle Returns resource of type "cURL Share Handle". * @since 5.5 */ #[LanguageLevelTypeAware(['8.0' => 'CurlShareHandle'], default: 'resource')] function curl_share_init() {} /** * (PHP 5 >=5.5.0)
    * Set an option for a cURL share handle. * @link https://secure.php.net/manual/en/function.curl-share-setopt.php * @param CurlShareHandle|resource $share_handle

    * A cURL share handle returned by {@link https://secure.php.net/manual/en/function.curl-share-init.php curl_share_init()}. *

    * @param int $option * * * * * * * * * * * * * * * * * * * * * *
    OptionDescription
    CURLSHOPT_SHARE * Specifies a type of data that should be shared. *
    CURLSHOPT_UNSHARE * Specifies a type of data that will be no longer shared. *
    * @param string $value

    * * * * * * * * * * * * * * * * * * * * * * * * * * *
    ValueDescription
    CURL_LOCK_DATA_COOKIE * Shares cookie data. *
    CURL_LOCK_DATA_DNS * Shares DNS cache. Note that when you use cURL multi handles, * all handles added to the same multi handle will share DNS cache * by default. *
    CURL_LOCK_DATA_SSL_SESSION * Shares SSL session IDs, reducing the time spent on the SSL * handshake when reconnecting to the same server. Note that SSL * session IDs are reused within the same handle by default. *
    *

    * @return bool * Returns TRUE on success or FALSE on failure. * @since 5.5 */ function curl_share_setopt(#[LanguageLevelTypeAware(['8.0' => 'CurlShareHandle'], default: 'resource')] $share_handle, int $option, mixed $value): bool {} /** * (PHP 5 >=5.5.0)
    * Return string describing the given error code * @link https://secure.php.net/manual/en/function.curl-strerror.php * @param int $error_code

    * One of the {@link https://curl.haxx.se/libcurl/c/libcurl-errors.html  cURL error codes} constants. *

    * @return string|null Returns error description or NULL for invalid error code. * @since 5.5 */ #[Pure] function curl_strerror(int $error_code): ?string {} /** * (PHP 5 >=5.5.0)
    * Decodes the given URL encoded string * @link https://secure.php.net/manual/en/function.curl-unescape.php * @param CurlHandle|resource $handle

    A cURL handle returned by * {@link https://secure.php.net/manual/en/function.curl-init.php curl_init()}.

    * @param string $string

    * The URL encoded string to be decoded. *

    * @return string|false Returns decoded string or FALSE on failure. * @since 5.5 */ #[Pure] function curl_unescape(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle, string $string): string|false {} /** * Perform a cURL session * @link https://php.net/manual/en/function.curl-exec.php * @param CurlHandle|resource $handle * @return string|bool true on success or false on failure. However, if the CURLOPT_RETURNTRANSFER * option is set, it will return the result on success, false on failure. */ function curl_exec(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle): string|bool {} /** * Get information regarding a specific transfer * @link https://php.net/manual/en/function.curl-getinfo.php * @param CurlHandle|resource $handle * @param int|null $option [optional]

    * This may be one of the following constants: *

      *
    • * CURLINFO_EFFECTIVE_URL - Last effective URL *
    • *
    • * CURLINFO_HTTP_CODE - The last response code. As of cURL 7.10.8, this is a legacy alias of * CURLINFO_RESPONSE_CODE * *
    • *
    • * CURLINFO_FILETIME - Remote time of the retrieved document, with the * CURLOPT_FILETIME * enabled; if -1 is returned the time of the document is unknown *
    • *
    • * CURLINFO_TOTAL_TIME - Total transaction time in seconds for last transfer *
    • *
    • * CURLINFO_NAMELOOKUP_TIME - Time in seconds until name resolving was complete *
    • *
    • * CURLINFO_CONNECT_TIME - Time in seconds it took to establish the connection *
    • *
    • * CURLINFO_PRETRANSFER_TIME - Time in seconds from start until just before file transfer begins *
    • *
    • * CURLINFO_STARTTRANSFER_TIME - Time in seconds until the first byte is about to be transferred *
    • *
    • * CURLINFO_REDIRECT_COUNT - Number of redirects, with the * CURLOPT_FOLLOWLOCATION * option enabled *
    • *
    • * CURLINFO_REDIRECT_TIME - Time in seconds of all redirection steps before final transaction was started, with the * CURLOPT_FOLLOWLOCATION * option enabled *
    • *
    • * CURLINFO_REDIRECT_URL - With the * CURLOPT_FOLLOWLOCATION * option disabled: redirect URL found in the last transaction, that should be requested manually next. With the * CURLOPT_FOLLOWLOCATION * option enabled: this is empty. The redirect URL in this case is available in * CURLINFO_EFFECTIVE_URL * *
    • *
    • * CURLINFO_PRIMARY_IP - IP address of the most recent connection *
    • *
    • * CURLINFO_PRIMARY_PORT - Destination port of the most recent connection *
    • *
    • * CURLINFO_LOCAL_IP - Local (source) IP address of the most recent connection *
    • *
    • * CURLINFO_LOCAL_PORT - Local (source) port of the most recent connection *
    • *
    • * CURLINFO_SIZE_UPLOAD - Total number of bytes uploaded *
    • *
    • * CURLINFO_SIZE_DOWNLOAD - Total number of bytes downloaded *
    • *
    • * CURLINFO_SPEED_DOWNLOAD - Average download speed *
    • *
    • * CURLINFO_SPEED_UPLOAD - Average upload speed *
    • *
    • * CURLINFO_HEADER_SIZE - Total size of all headers received *
    • *
    • * CURLINFO_HEADER_OUT - The request string sent. For this to work, add the * CURLINFO_HEADER_OUT * option to the handle by calling curl_setopt() *
    • *
    • * CURLINFO_REQUEST_SIZE - Total size of issued requests, currently only for HTTP requests *
    • *
    • * CURLINFO_SSL_VERIFYRESULT - Result of SSL certification verification requested by setting * CURLOPT_SSL_VERIFYPEER * *
    • *
    • * CURLINFO_CONTENT_LENGTH_DOWNLOAD - Content length of download, read from * Content-Length: field *
    • *
    • * CURLINFO_CONTENT_LENGTH_UPLOAD - Specified size of upload *
    • *
    • * CURLINFO_CONTENT_TYPE * - * Content-Type: of the requested document. NULL indicates server did not send valid * Content-Type: header *
    • *
    • * CURLINFO_PRIVATE - Private data associated with this cURL handle, previously set with the * CURLOPT_PRIVATE * option of curl_setopt() *
    • *
    • * CURLINFO_RESPONSE_CODE - The last response code *
    • *
    • * CURLINFO_HTTP_CONNECTCODE - The CONNECT response code *
    • *
    • * CURLINFO_HTTPAUTH_AVAIL - Bitmask indicating the authentication method(s) available according to the previous response *
    • *
    • * CURLINFO_PROXYAUTH_AVAIL - Bitmask indicating the proxy authentication method(s) available according to the previous response *
    • *
    • * CURLINFO_OS_ERRNO - Errno from a connect failure. The number is OS and system specific. *
    • *
    • * CURLINFO_NUM_CONNECTS - Number of connections curl had to create to achieve the previous transfer *
    • *
    • * CURLINFO_SSL_ENGINES - OpenSSL crypto-engines supported *
    • *
    • * CURLINFO_COOKIELIST - All known cookies *
    • *
    • * CURLINFO_FTP_ENTRY_PATH - Entry path in FTP server *
    • *
    • * CURLINFO_APPCONNECT_TIME - Time in seconds it took from the start until the SSL/SSH connect/handshake to the remote host was completed *
    • *
    • * CURLINFO_CERTINFO - TLS certificate chain *
    • *
    • * CURLINFO_CONDITION_UNMET - Info on unmet time conditional *
    • *
    • * CURLINFO_RTSP_CLIENT_CSEQ - Next RTSP client CSeq *
    • *
    • * CURLINFO_RTSP_CSEQ_RECV - Recently received CSeq *
    • *
    • * CURLINFO_RTSP_SERVER_CSEQ - Next RTSP server CSeq *
    • *
    • * CURLINFO_RTSP_SESSION_ID - RTSP session ID *
    • *
    • * CURLINFO_CONTENT_LENGTH_DOWNLOAD_T - The content-length of the download. This is the value read from the * Content-Type: field. -1 if the size isn't known *
    • *
    • * CURLINFO_CONTENT_LENGTH_UPLOAD_T - The specified size of the upload. -1 if the size isn't known *
    • *
    • * CURLINFO_HTTP_VERSION - The version used in the last HTTP connection. The return value will be one of the defined * CURL_HTTP_VERSION_* * constants or 0 if the version can't be determined *
    • *
    • * CURLINFO_PROTOCOL - The protocol used in the last HTTP connection. The returned value will be exactly one of the * CURLPROTO_* * values *
    • *
    • * CURLINFO_PROXY_SSL_VERIFYRESULT - The result of the certificate verification that was requested (using the * CURLOPT_PROXY_SSL_VERIFYPEER * option). Only used for HTTPS proxies *
    • *
    • * CURLINFO_SCHEME - The URL scheme used for the most recent connection *
    • *
    • * CURLINFO_SIZE_DOWNLOAD_T - Total number of bytes that were downloaded. The number is only for the latest transfer and will be reset again for each new transfer *
    • *
    • * CURLINFO_SIZE_UPLOAD_T - Total number of bytes that were uploaded *
    • *
    • * CURLINFO_SPEED_DOWNLOAD_T - The average download speed in bytes/second that curl measured for the complete download *
    • *
    • * CURLINFO_SPEED_UPLOAD_T - The average upload speed in bytes/second that curl measured for the complete upload *
    • *
    • * CURLINFO_APPCONNECT_TIME_T - Time, in microseconds, it took from the start until the SSL/SSH connect/handshake to the remote host was completed *
    • *
    • * CURLINFO_CONNECT_TIME_T - Total time taken, in microseconds, from the start until the connection to the remote host (or proxy) was completed *
    • *
    • * CURLINFO_FILETIME_T - Remote time of the retrieved document (as Unix timestamp), an alternative to * CURLINFO_FILETIME * to allow systems with 32 bit long variables to extract dates outside of the 32bit timestamp range *
    • *
    • * CURLINFO_NAMELOOKUP_TIME_T - Time in microseconds from the start until the name resolving was completed *
    • *
    • * CURLINFO_PRETRANSFER_TIME_T - Time taken from the start until the file transfer is just about to begin, in microseconds *
    • *
    • * CURLINFO_REDIRECT_TIME_T - Total time, in microseconds, it took for all redirection steps include name lookup, connect, pretransfer and transfer before final transaction was started *
    • *
    • * CURLINFO_STARTTRANSFER_TIME_T - Time, in microseconds, it took from the start until the first byte is received *
    • *
    • * CURLINFO_TOTAL_TIME_T - Total time in microseconds for the previous transfer, including name resolving, TCP connect etc. *
    * * @return mixed If $option is given, returns its value as a string. * Otherwise, returns an associative array with the following elements * (which correspond to $option), or false on failure: *
      *
    • url
    • *
    • content_type
    • *
    • http_code
    • *
    • header_size
    • *
    • request_size
    • *
    • filetime
    • *
    • ssl_verify_result
    • *
    • redirect_count
    • *
    • total_time
    • *
    • namelookup_time
    • *
    • connect_time
    • *
    • pretransfer_time
    • *
    • size_upload
    • *
    • size_download
    • *
    • speed_download
    • *
    • speed_upload
    • *
    • download_content_length
    • *
    • upload_content_length
    • *
    • starttransfer_time
    • *
    • redirect_time
    • *
    • certinfo
    • *
    • primary_ip
    • *
    • primary_port
    • *
    • local_ip
    • *
    • local_port
    • *
    • redirect_url
    • *
    • request_header (This is only set if the * CURLINFO_HEADER_OUT * is set by a previous call to curl_setopt() *
    • *
    */ #[Pure(true)] function curl_getinfo(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle, ?int $option): mixed {} /** * Return a string containing the last error for the current session * @link https://php.net/manual/en/function.curl-error.php * @param CurlHandle|resource $handle * @return string the error message or '' (the empty string) if no * error occurred. */ #[Pure(true)] function curl_error(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle): string {} /** * Return the last error number * @link https://php.net/manual/en/function.curl-errno.php * @param CurlHandle|resource $handle * @return int the error number or 0 (zero) if no error * occurred. */ #[Pure(true)] function curl_errno(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle): int {} /** * URL encodes the given string * @link https://secure.php.net/manual/en/function.curl-escape.php * @param CurlHandle|resource $handle

    * A cURL handle returned by * {@link https://secure.php.net/manual/en/function.curl-init.php curl_init()}.

    * @param string $string

    * The string to be encoded.

    * @return string|false Returns escaped string or FALSE on failure. * @since 5.5 */ #[Pure] function curl_escape(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle, string $string): string|false {} /** * (PHP 5 >= 5.5.0)
    * Create a CURLFile object * @link https://secure.php.net/manual/en/curlfile.construct.php * @param string $filename

    Path to the file which will be uploaded.

    * @param string|null $mime_type

    Mimetype of the file.

    * @param string|null $posted_filename

    Name of the file.

    * @return CURLFile * Returns a {@link https://secure.php.net/manual/en/class.curlfile.php CURLFile} object. * @since 5.5 */ #[Pure] function curl_file_create(string $filename, ?string $mime_type = null, ?string $posted_filename = null): CURLFile {} /** * Close a cURL session * @link https://php.net/manual/en/function.curl-close.php * @param CurlHandle|resource $handle * @return void */ function curl_close(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle): void {} /** * Returns a new cURL multi handle * @link https://php.net/manual/en/function.curl-multi-init.php * @return resource|CurlMultiHandle a cURL multi handle resource or object depends on the php version */ #[LanguageLevelTypeAware(['8.0' => 'CurlMultiHandle'], default: 'resource')] function curl_multi_init(): CurlMultiHandle {} /** * Add a normal cURL handle to a cURL multi handle * @link https://php.net/manual/en/function.curl-multi-add-handle.php * @param CurlMultiHandle|resource $multi_handle * @param CurlHandle|resource $handle * @return int 0 on success, or one of the CURLM_XXX errors * code. */ function curl_multi_add_handle(#[LanguageLevelTypeAware(['8.0' => 'CurlMultiHandle'], default: 'resource')] $multi_handle, #[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle): int {} /** * Remove a multi handle from a set of cURL handles * @link https://php.net/manual/en/function.curl-multi-remove-handle.php * @param CurlMultiHandle|resource $multi_handle * @param CurlHandle|resource $handle * @return int|false On success, returns one of the CURLM_XXX error codes, false on failure. */ #[LanguageLevelTypeAware(['8.0' => 'int'], default: 'int|false')] function curl_multi_remove_handle(#[LanguageLevelTypeAware(['8.0' => 'CurlMultiHandle'], default: 'resource')] $multi_handle, #[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle) {} /** * Wait for activity on any curl_multi connection * @link https://php.net/manual/en/function.curl-multi-select.php * @param CurlMultiHandle|resource $multi_handle * @param float $timeout [optional]

    * Time, in seconds, to wait for a response. *

    * @return int On success, returns the number of descriptors contained in, * the descriptor sets. On failure, this function will return -1 on a select failure or timeout (from the underlying select system call). */ function curl_multi_select(#[LanguageLevelTypeAware(['8.0' => 'CurlMultiHandle'], default: 'resource')] $multi_handle, float $timeout = 1.0): int {} /** * (PHP 5 >=5.5.0)
    * Set an option for the cURL multi handle * @link https://secure.php.net/manual/en/function.curl-multi-setopt.php * @param CurlMultiHandle|resource $multi_handle * @param int $option

    * One of the CURLMOPT_* constants. *

    * @param mixed $value

    * The value to be set on option. *

    *

    * value should be an {@link https://php.net/manual/en/language.types.integer.php int} for the * following values of the option parameter: *

    * * * * * * * * * * * * * * * * * * * *
    OptionSet value to
    CURLMOPT_PIPELINING * Pass 1 to enable or 0 to disable. Enabling pipelining on a multi * handle will make it attempt to perform HTTP Pipelining as far as * possible for transfers using this handle. This means that if you add * a second request that can use an already existing connection, the * second request will be "piped" on the same connection rather than * being executed in parallel. *
    CURLMOPT_MAXCONNECTS * Pass a number that will be used as the maximum amount of * simultaneously open connections that libcurl may cache. Default is * 10. When the cache is full, curl closes the oldest one in the cache * to prevent the number of open connections from increasing. *
    * @return bool Returns TRUE on success or FALSE on failure. * @since 5.5 */ function curl_multi_setopt(#[LanguageLevelTypeAware(['8.0' => 'CurlMultiHandle'], default: 'resource')] $multi_handle, int $option, mixed $value): bool {} /** * (PHP 5 >=5.5.0)
    * Return string describing error code * @link https://secure.php.net/manual/en/function.curl-multi-strerror.php * @param int $error_code

    * One of the {@link https://curl.haxx.se/libcurl/c/libcurl-errors.html CURLM error codes} constants. *

    * @return string|null Returns error string for valid error code, NULL otherwise. * @since 5.5 */ function curl_multi_strerror(int $error_code): ?string {} /** * (PHP 5 >=5.5.0)
    * Pause and unpause a connection * @link https://secure.php.net/manual/en/function.curl-pause.php * @param CurlHandle|resource $handle *

    A cURL handle returned by {@link https://secure.php.net/manual/en/function.curl-init.php curl_init()}.

    * @param int $flags

    One of CURLPAUSE_* constants.

    * @return int Returns an error code (CURLE_OK for no error). * @since 5.5 */ function curl_pause(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle, int $flags): int {} /** * (PHP 5 >=5.5.0)
    * Reset all options of a libcurl session handle * @link https://secure.php.net/manual/en/function.curl-reset.php * @param CurlHandle|resource $handle

    A cURL handle returned by * {@link https://secure.php.net/manual/en/function.curl-init.php curl_init()}.

    * @return void * @since 5.5 */ function curl_reset(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle): void {} /** * Run the sub-connections of the current cURL handle * @link https://php.net/manual/en/function.curl-multi-exec.php * @param CurlMultiHandle|resource $multi_handle * @param int &$still_running

    * A reference to a flag to tell whether the operations are still running. *

    * @return int A cURL code defined in the cURL Predefined Constants. *

    * This only returns errors regarding the whole multi stack. There might still have * occurred problems on individual transfers even when this function returns * CURLM_OK. *

    */ function curl_multi_exec( #[LanguageLevelTypeAware(['8.0' => 'CurlMultiHandle'], default: 'resource')] $multi_handle, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] &$still_running = 0, #[PhpStormStubsElementAvailable(from: '8.0')] &$still_running ): int {} /** * Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set * @link https://php.net/manual/en/function.curl-multi-getcontent.php * @param CurlHandle|resource $handle * @return null|string Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set. */ #[Pure] function curl_multi_getcontent(#[LanguageLevelTypeAware(['8.0' => 'CurlHandle'], default: 'resource')] $handle): ?string {} /** * Get information about the current transfers * @link https://php.net/manual/en/function.curl-multi-info-read.php * @param CurlMultiHandle|resource $multi_handle * @param int &$queued_messages [optional]

    * Number of messages that are still in the queue *

    * @return array|false On success, returns an associative array for the message, false on failure. */ #[Pure] #[ArrayShape(["msg" => "int", "result" => "int", "handle" => "resource"])] function curl_multi_info_read(#[LanguageLevelTypeAware(['8.0' => 'CurlMultiHandle'], default: 'resource')] $multi_handle, &$queued_messages): array|false {} /** * Close a set of cURL handles * @link https://php.net/manual/en/function.curl-multi-close.php * @param CurlMultiHandle|resource $multi_handle * @return void */ function curl_multi_close(#[LanguageLevelTypeAware(['8.0' => 'CurlMultiHandle'], default: 'resource')] $multi_handle): void {} /** * Return the last multi curl error number * @param CurlMultiHandle|resource $multi_handle * @return int * @since 7.1 */ #[Pure(true)] function curl_multi_errno(#[LanguageLevelTypeAware(['8.0' => 'CurlMultiHandle'], default: 'resource')] $multi_handle): int {} /** * Return the last share curl error number * @param CurlMultiHandle|resource $share_handle * @return int * @since 7.1 */ #[Pure(true)] function curl_share_errno(#[LanguageLevelTypeAware(['8.0' => 'CurlShareHandle'], default: 'resource')] $share_handle): int {} /** * Return string describing the given error code * @param int $error_code * @return string|null * @since 7.1 */ #[Pure] function curl_share_strerror(int $error_code): ?string {} /** * @since 8.2 */ function curl_upkeep(CurlHandle $handle): bool {} /** * @since 8.0 */ final class CurlHandle { /** * Cannot directly construct CurlHandle, use curl_init() instead * @see curl_init() */ private function __construct() {} } /** * @since 8.0 */ final class CurlMultiHandle { /** * Cannot directly construct CurlMultiHandle, use curl_multi_init() instead * @see curl_multi_init() */ private function __construct() {} } /** * @since 8.0 */ final class CurlShareHandle { /** * Cannot directly construct CurlShareHandle, use curl_share_init() instead * @see curl_share_init() */ private function __construct() {} } * Case sensitive regular expression. *

    * @param string $string

    * The input string. *

    * @param null|array &$regs [optional]

    * If matches are found for parenthesized substrings of * pattern and the function is called with the * third argument regs, the matches will be stored * in the elements of the array regs. *

    *

    * $regs[1] will contain the substring which starts at * the first left parenthesis; $regs[2] will contain * the substring starting at the second, and so on. * $regs[0] will contain a copy of the complete string * matched. *

    * @return int the length of the matched string if a match for * pattern was found in string, * or FALSE if no matches were found or an error occurred. *

    *

    * If the optional parameter regs was not passed or * the length of the matched string is 0, this function returns 1. * @removed 7.0 * @see preg_match() */ #[Deprecated(reason: "Use preg_match() instead", since: "5.3")] function ereg($pattern, $string, ?array &$regs = null) {} /** * Replace regular expression * @link https://php.net/manual/en/function.ereg-replace.php * @param string $pattern

    * A POSIX extended regular expression. *

    * @param string $replacement

    * If pattern contains parenthesized substrings, * replacement may contain substrings of the form * \digit, which will be * replaced by the text matching the digit'th parenthesized substring; * \0 will produce the entire contents of string. * Up to nine substrings may be used. Parentheses may be nested, in which * case they are counted by the opening parenthesis. *

    * @param string $string

    * The input string. *

    * @return string The modified string is returned. If no matches are found in * string, then it will be returned unchanged. * @removed 7.0 * @see preg_replace() */ #[Deprecated(reason: "Use preg_replace() instead", since: "5.3")] function ereg_replace($pattern, $replacement, $string) {} /** * Case insensitive regular expression match * @link https://php.net/manual/en/function.eregi.php * @param string $pattern

    * Case insensitive regular expression. *

    * @param string $string

    * The input string. *

    * @param null|array &$regs [optional]

    * If matches are found for parenthesized substrings of * pattern and the function is called with the * third argument regs, the matches will be stored * in the elements of the array regs. *

    *

    * $regs[1] will contain the substring which starts at the first left * parenthesis; $regs[2] will contain the substring starting at the * second, and so on. $regs[0] will contain a copy of the complete string * matched. *

    * @return int the length of the matched string if a match for * pattern was found in string, * or FALSE if no matches were found or an error occurred. *

    *

    * If the optional parameter regs was not passed or * the length of the matched string is 0, this function returns 1. * @removed 7.0 * @see preg_match() */ #[Deprecated(reason: "Use preg_match() instead", since: "5.3")] function eregi($pattern, $string, array &$regs = null) {} /** * Replace regular expression case insensitive * @link https://php.net/manual/en/function.eregi-replace.php * @param string $pattern

    * A POSIX extended regular expression. *

    * @param string $replacement

    * If pattern contains parenthesized substrings, * replacement may contain substrings of the form * \digit, which will be * replaced by the text matching the digit'th parenthesized substring; * \0 will produce the entire contents of string. * Up to nine substrings may be used. Parentheses may be nested, in which * case they are counted by the opening parenthesis. *

    * @param string $string

    * The input string. *

    * @return string The modified string is returned. If no matches are found in * string, then it will be returned unchanged. * @removed 7.0 * @see preg_replace() */ #[Deprecated(reason: "Use preg_replace() instead", since: "5.3")] function eregi_replace($pattern, $replacement, $string) {} /** * Split string into array by regular expression * @link https://php.net/manual/en/function.split.php * @param string $pattern

    * Case sensitive regular expression. *

    *

    * If you want to split on any of the characters which are considered * special by regular expressions, you'll need to escape them first. If * you think split (or any other regex function, for * that matter) is doing something weird, please read the file * regex.7, included in the * regex/ subdirectory of the PHP distribution. It's * in manpage format, so you'll want to do something along the lines of * man /usr/local/src/regex/regex.7 in order to read it. *

    * @param string $string

    * The input string. *

    * @param int $limit [optional]

    * If limit is set, the returned array will * contain a maximum of limit elements with the * last element containing the whole rest of * string. *

    * @return array an array of strings, each of which is a substring of * string formed by splitting it on boundaries formed * by the case-sensitive regular expression pattern. *

    *

    * If there are n occurrences of * pattern, the returned array will contain * n+1 items. For example, if * there is no occurrence of pattern, an array with * only one element will be returned. Of course, this is also true if * string is empty. If an error occurs, * split returns FALSE. * @removed 7.0 * @see preg_split() */ #[Deprecated(reason: "Use preg_split() instead", since: "5.3")] function split($pattern, $string, $limit = -1) {} /** * Split string into array by regular expression case insensitive * @link https://php.net/manual/en/function.spliti.php * @param string $pattern

    * Case insensitive regular expression. *

    *

    * If you want to split on any of the characters which are considered * special by regular expressions, you'll need to escape them first. If * you think spliti (or any other regex function, for * that matter) is doing something weird, please read the file * regex.7, included in the * regex/ subdirectory of the PHP distribution. It's * in manpage format, so you'll want to do something along the lines of * man /usr/local/src/regex/regex.7 in order to read it. *

    * @param string $string

    * The input string. *

    * @param int $limit [optional]

    * If limit is set, the returned array will * contain a maximum of limit elements with the * last element containing the whole rest of * string. *

    * @return array an array of strings, each of which is a substring of * string formed by splitting it on boundaries formed * by the case insensitive regular expression pattern. *

    *

    * If there are n occurrences of * pattern, the returned array will contain * n+1 items. For example, if * there is no occurrence of pattern, an array with * only one element will be returned. Of course, this is also true if * string is empty. If an error occurs, * spliti returns FALSE. * @removed 7.0 * @see preg_split() */ #[Deprecated(reason: "Use preg_split() instead", since: "5.3")] function spliti($pattern, $string, $limit = -1) {} /** * Make regular expression for case insensitive match * @link https://php.net/manual/en/function.sql-regcase.php * @param string $string

    * The input string. *

    * @return string a valid regular expression which will match * string, ignoring case. This expression is * string with each alphabetic character converted to * a bracket expression; this bracket expression contains that character's * uppercase and lowercase form. Other characters remain unchanged. * @removed 7.0 */ #[Deprecated(since: '5.3')] function sql_regcase($string) {} // End of ereg v. * The value of pid can be one of the following: * * possible values for pid * * * * * * * * * * * * * * * * *
    < -1 * wait for any child process whose process group ID is equal to * the absolute value of pid. *
    -1 * wait for any child process; this is the same behaviour that * the wait function exhibits. *
    0 * wait for any child process whose process group ID is equal to * that of the calling process. *
    > 0 * wait for the child whose process ID is equal to the value of * pid. *
    *

    *

    * Specifying -1 as the pid is * equivalent to the functionality pcntl_wait provides * (minus options). *

    * @param int &$status

    * pcntl_waitpid will store status information * in the status parameter which can be * evaluated using the following functions: * pcntl_wifexited, * pcntl_wifstopped, * pcntl_wifsignaled, * pcntl_wexitstatus, * pcntl_wtermsig and * pcntl_wstopsig. *

    * @param int $flags [optional]

    * The value of options is the value of zero * or more of the following two global constants * OR'ed together: *

    * possible values for options * * * * * * * * *
    WNOHANG * return immediately if no child has exited. *
    WUNTRACED * return for children which are stopped, and whose status has * not been reported. *
    *

    * @param array &$resource_usage * @return int pcntl_waitpid returns the process ID of the * child which exited, -1 on error or zero if WNOHANG was used and no * child was available */ function pcntl_waitpid( int $process_id, &$status, int $flags = 0, #[PhpStormStubsElementAvailable(from: '7.0')] &$resource_usage = [] ): int {} /** * Waits on or returns the status of a forked child * @link https://php.net/manual/en/function.pcntl-wait.php * @param int &$status

    * pcntl_wait will store status information * in the status parameter which can be * evaluated using the following functions: * pcntl_wifexited, * pcntl_wifstopped, * pcntl_wifsignaled, * pcntl_wexitstatus, * pcntl_wtermsig and * pcntl_wstopsig. *

    * @param int $flags [optional]

    * If wait3 is available on your system (mostly BSD-style systems), you can * provide the optional flags parameter. If this * parameter is not provided, wait will be used for the system call. If * wait3 is not available, providing a value for flags * will have no effect. The value of flags * is the value of zero or more of the following two constants * OR'ed together: *

    * Possible values for flags * * * * * * * * *
    WNOHANG * Return immediately if no child has exited. *
    WUNTRACED * Return for children which are stopped, and whose status has * not been reported. *
    *

    * @param array &$resource_usage * @return int pcntl_wait returns the process ID of the * child which exited, -1 on error or zero if WNOHANG was provided as an * option (on wait3-available systems) and no child was available. */ function pcntl_wait( &$status, int $flags = 0, #[PhpStormStubsElementAvailable(from: '7.0')] &$resource_usage = [] ): int {} /** * Installs a signal handler * @link https://php.net/manual/en/function.pcntl-signal.php * @param int $signal

    * The signal number. *

    * @param callable|int $handler

    * The signal handler. This may be either a callable, which * will be invoked to handle the signal, or either of the two global * constants SIG_IGN or SIG_DFL, * which will ignore the signal or restore the default signal handler * respectively. *

    *

    * If a callable is given, it must implement the following * signature: *

    *

    * voidhandler * intsigno * signo * The signal being handled.

    * @param bool $restart_syscalls [optional]

    * Specifies whether system call restarting should be used when this * signal arrives. *

    * @return bool TRUE on success or FALSE on failure. */ function pcntl_signal(int $signal, $handler, bool $restart_syscalls = true): bool {} /** * Calls signal handlers for pending signals * @link https://php.net/manual/en/function.pcntl-signal-dispatch.php * @return bool TRUE on success or FALSE on failure. */ function pcntl_signal_dispatch(): bool {} /** * Checks if status code represents a normal exit * @link https://php.net/manual/en/function.pcntl-wifexited.php * @param int $status

    The status * parameter is the status parameter supplied to a successful * call to pcntl_waitpid.

    * @return bool TRUE if the child status code represents a normal exit, FALSE * otherwise. */ #[Pure] function pcntl_wifexited(int $status): bool {} /** * Checks whether the child process is currently stopped * @link https://php.net/manual/en/function.pcntl-wifstopped.php * @param int $status

    The status * parameter is the status parameter supplied to a successful * call to pcntl_waitpid.

    * @return bool TRUE if the child process which caused the return is * currently stopped, FALSE otherwise. */ #[Pure] function pcntl_wifstopped(int $status): bool {} /** * Checks whether the status code represents a termination due to a signal * @link https://php.net/manual/en/function.pcntl-wifsignaled.php * @param int $status

    The status * parameter is the status parameter supplied to a successful * call to pcntl_waitpid.

    * @return bool TRUE if the child process exited because of a signal which was * not caught, FALSE otherwise. */ #[Pure] function pcntl_wifsignaled(int $status): bool {} /** * Returns the return code of a terminated child * @link https://php.net/manual/en/function.pcntl-wexitstatus.php * @param int $status

    The status * parameter is the status parameter supplied to a successful * call to pcntl_waitpid.

    * @return int|false the return code, as an integer. */ #[Pure] function pcntl_wexitstatus(int $status): int|false {} /** * @param int $status * @return bool */ #[Pure] function pcntl_wifcontinued(int $status): bool {} /** * Returns the signal which caused the child to terminate * @link https://php.net/manual/en/function.pcntl-wtermsig.php * @param int $status

    The status * parameter is the status parameter supplied to a successful * call to pcntl_waitpid.

    * @return int|false the signal number, as an integer. */ #[Pure] function pcntl_wtermsig(int $status): int|false {} /** * Returns the signal which caused the child to stop * @link https://php.net/manual/en/function.pcntl-wstopsig.php * @param int $status

    The status * parameter is the status parameter supplied to a successful * call to pcntl_waitpid.

    * @return int|false the signal number. */ #[Pure] function pcntl_wstopsig(int $status): int|false {} /** * Executes specified program in current process space * @link https://php.net/manual/en/function.pcntl-exec.php * @param string $path

    * path must be the path to a binary executable or a * script with a valid path pointing to an executable in the shebang ( * #!/usr/local/bin/perl for example) as the first line. See your system's * man execve(2) page for additional information. *

    * @param array $args

    * args is an array of argument strings passed to the * program. *

    * @param array $env_vars

    * envs is an array of strings which are passed as * environment to the program. The array is in the format of name => value, * the key being the name of the environmental variable and the value being * the value of that variable. *

    * @return bool FALSE on error and does not return on success. */ function pcntl_exec(string $path, array $args = [], array $env_vars = []): bool {} /** * Set an alarm clock for delivery of a signal * @link https://php.net/manual/en/function.pcntl-alarm.php * @param int $seconds

    * The number of seconds to wait. If seconds is * zero, no new alarm is created. *

    * @return int the time in seconds that any previously scheduled alarm had * remaining before it was to be delivered, or 0 if there * was no previously scheduled alarm. */ function pcntl_alarm(int $seconds): int {} /** * Retrieve the error number set by the last pcntl function which failed * @link https://php.net/manual/en/function.pcntl-get-last-error.php * @return int error code. * @since 5.3.4 */ #[Pure(true)] function pcntl_get_last_error(): int {} /** * Alias of pcntl_get_last_error * @link https://php.net/manual/en/function.pcntl-errno.php * @return int error code. * @since 5.3.4 */ #[Pure(true)] function pcntl_errno(): int {} /** * Retrieve the system error message associated with the given errno * @link https://php.net/manual/en/function.pcntl-strerror.php * @param int $error_code

    *

    * @return string|false error description on success or FALSE on failure. * @since 5.3.4 */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] function pcntl_strerror(int $error_code): false|string {} /** * Get the priority of any process * @link https://php.net/manual/en/function.pcntl-getpriority.php * @param int|null $process_id [optional]

    * If not specified, the pid of the current process (getmypid()) is used. *

    * @param int $mode [optional]

    * One of PRIO_PGRP, PRIO_USER * or PRIO_PROCESS. *

    * @return int|false pcntl_getpriority returns the priority of the process * or FALSE on error. A lower numerical value causes more favorable * scheduling. */ #[Pure] function pcntl_getpriority(?int $process_id, int $mode = PRIO_PROCESS): int|false {} /** * Change the priority of any process * @link https://php.net/manual/en/function.pcntl-setpriority.php * @param int $priority

    * priority is generally a value in the range * -20 to 20. The default priority * is 0 while a lower numerical value causes more * favorable scheduling. Because priority levels can differ between * system types and kernel versions, please see your system's setpriority(2) * man page for specific details. *

    * @param int|null $process_id [optional]

    * If not specified, the pid of the current process (getmypid()) is used. *

    * @param int $mode [optional]

    * One of PRIO_PGRP, PRIO_USER * or PRIO_PROCESS. *

    * @return bool TRUE on success or FALSE on failure. */ function pcntl_setpriority(int $priority, ?int $process_id, int $mode = PRIO_PROCESS): bool {} /** * Sets and retrieves blocked signals * @link https://php.net/manual/en/function.pcntl-sigprocmask.php * @param int $mode

    * Sets the behavior of pcntl_sigprocmask. Possible * values: * SIG_BLOCK: Add the signals to the * currently blocked signals. * SIG_UNBLOCK: Remove the signals from the * currently blocked signals. * SIG_SETMASK: Replace the currently * blocked signals by the given list of signals. *

    * @param array $signals

    * List of signals. *

    * @param array &$old_signals [optional]

    * The old_signals parameter is set to an array * containing the list of the previously blocked signals. *

    * @return bool TRUE on success or FALSE on failure. */ function pcntl_sigprocmask(int $mode, array $signals, &$old_signals): bool {} /** * Waits for signals * @link https://php.net/manual/en/function.pcntl-sigwaitinfo.php * @param array $signals

    * Array of signals to wait for. *

    * @param array &$info

    * The info parameter is set to an array containing * informations about the signal. *

    *

    * The following elements are set for all signals: * signo: Signal number * errno: An error number * code: Signal code *

    *

    * The following elements may be set for the SIGCHLD signal: * status: Exit value or signal * utime: User time consumed * stime: System time consumed * pid: Sending process ID * uid: Real user ID of sending process *

    *

    * The following elements may be set for the SIGILL, * SIGFPE, SIGSEGV and * SIGBUS signals: * addr: Memory location which caused fault *

    *

    * The following element may be set for the SIGPOLL * signal: * band: Band event * fd: File descriptor number *

    * @return int|false On success, pcntl_sigwaitinfo returns a signal number. */ function pcntl_sigwaitinfo(array $signals, &$info = []): int|false {} /** * Waits for signals, with a timeout * @link https://php.net/manual/en/function.pcntl-sigtimedwait.php * @param array $signals

    * Array of signals to wait for. *

    * @param array &$info

    * The siginfo is set to an array containing * informations about the signal. See * pcntl_sigwaitinfo. *

    * @param int $seconds [optional]

    * Timeout in seconds. *

    * @param int $nanoseconds [optional]

    * Timeout in nanoseconds. *

    * @return int|false On success, pcntl_sigtimedwait returns a signal number. */ function pcntl_sigtimedwait(array $signals, &$info = [], int $seconds = 0, int $nanoseconds = 0): int|false {} /** * Enable/disable asynchronous signal handling or return the old setting.
    * If the enable parameter is omitted, it returns whether asynchronous * signal handling is enabled. * @link https://www.php.net/manual/en/function.pcntl-async-signals.php * * @param bool|null $enable

    * Whether asynchronous signal handling should be enabled. *

    * * @return bool * @since 7.1 */ function pcntl_async_signals( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] ?bool $enable, #[PhpStormStubsElementAvailable(from: '8.0')] ?bool $enable = null ): bool {} /** * Get the current handler for specified signal. * @link https://www.php.net/manual/en/function.pcntl-signal-get-handler.php * * @param int $signal

    * The signal number. *

    * * @return bool|resource * @since 7.1 */ function pcntl_signal_get_handler(int $signal) {} /** * @param int $flags * @return bool * @since 7.4 */ function pcntl_unshare(int $flags): bool {} /** * @since 8.4 */ function pcntl_waitid(int $idtype = P_ALL, ?int $id = null, &$info = [], int $flags = WEXITED): bool {} /** * @since 8.4 */ function pcntl_getcpuaffinity(?int $process_id = null): array|false {} /** * @since 8.4 */ function pcntl_setcpuaffinity(?int $process_id = null, array $cpu_ids = []): bool {} /** * @since 8.4 */ function pcntl_getcpu(): int {} define('WNOHANG', 1); define('WUNTRACED', 2); define('WCONTINUED', 8); define('SIG_IGN', 1); define('SIG_DFL', 0); define('SIG_ERR', -1); define('SIGHUP', 1); define('SIGINT', 2); define('SIGQUIT', 3); define('SIGILL', 4); define('SIGTRAP', 5); define('SIGABRT', 6); define('SIGIOT', 6); define('SIGBUS', 7); define('SIGFPE', 8); define('SIGKILL', 9); define('SIGUSR1', 10); define('SIGSEGV', 11); define('SIGUSR2', 12); define('SIGPIPE', 13); define('SIGALRM', 14); define('SIGTERM', 15); define('SIGSTKFLT', 16); define('SIGCLD', 17); define('SIGCHLD', 17); define('SIGCONT', 18); define('SIGSTOP', 19); define('SIGTSTP', 20); define('SIGTTIN', 21); define('SIGTTOU', 22); define('SIGURG', 23); define('SIGXCPU', 24); define('SIGXFSZ', 25); define('SIGVTALRM', 26); define('SIGPROF', 27); define('SIGWINCH', 28); define('SIGPOLL', 29); define('SIGIO', 29); define('SIGPWR', 30); define('SIGSYS', 31); define('SIGBABY', 31); define('PRIO_PGRP', 1); define('PRIO_USER', 2); define('PRIO_PROCESS', 0); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SIG_BLOCK', 0); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SIG_UNBLOCK', 1); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SIG_SETMASK', 2); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SIGRTMIN', 35); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SIGRTMAX', 64); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SI_USER', 0); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SI_KERNEL', 128); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SI_QUEUE', -1); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SI_TIMER', -2); define('SI_MESGQ', -3); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SI_ASYNCIO', -4); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SI_SIGIO', -5); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SI_TKILL', -6); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('CLD_EXITED', 1); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('CLD_KILLED', 2); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('CLD_DUMPED', 3); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('CLD_TRAPPED', 4); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('CLD_STOPPED', 5); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('CLD_CONTINUED', 6); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('TRAP_BRKPT', 1); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('TRAP_TRACE', 2); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('POLL_IN', 1); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('POLL_OUT', 2); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('POLL_MSG', 3); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('POLL_ERR', 4); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('POLL_PRI', 5); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('POLL_HUP', 6); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('ILL_ILLOPC', 1); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('ILL_ILLOPN', 2); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('ILL_ILLADR', 3); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('ILL_ILLTRP', 4); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('ILL_PRVOPC', 5); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('ILL_PRVREG', 6); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('ILL_COPROC', 7); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('ILL_BADSTK', 8); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('FPE_INTDIV', 1); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('FPE_INTOVF', 2); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('FPE_FLTDIV', 3); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('FPE_FLTOVF', 4); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('FPE_FLTUND', 5); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('FPE_FLTRES', 6); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('FPE_FLTINV', 7); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('FPE_FLTSUB', 8); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SEGV_MAPERR', 1); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('SEGV_ACCERR', 2); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('BUS_ADRALN', 1); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('BUS_ADRERR', 2); /** * @link https://php.net/manual/en/pcntl.constants.php */ define('BUS_OBJERR', 3); define('PCNTL_EINTR', 4); define('PCNTL_ECHILD', 10); define('PCNTL_EINVAL', 22); define('PCNTL_EAGAIN', 11); define('PCNTL_ESRCH', 3); define('PCNTL_EACCES', 13); define('PCNTL_EPERM', 1); define('PCNTL_ENOMEM', 12); define('PCNTL_E2BIG', 7); define('PCNTL_EFAULT', 14); define('PCNTL_EIO', 5); define('PCNTL_EISDIR', 21); define('PCNTL_ELIBBAD', 80); define('PCNTL_ELOOP', 40); define('PCNTL_EMFILE', 24); define('PCNTL_ENAMETOOLONG', 36); define('PCNTL_ENFILE', 23); define('PCNTL_ENOENT', 2); define('PCNTL_ENOEXEC', 8); define('PCNTL_ENOTDIR', 20); define('PCNTL_ETXTBSY', 26); /** * @since 7.4 */ define('PCNTL_ENOSPC', 28); /** * @since 7.4 */ define('PCNTL_EUSERS', 87); /** * @since 7.4 */ define('CLONE_NEWNS', 131072); /** * @since 7.4 */ define('CLONE_NEWIPC', 134217728); /** * @since 7.4 */ define('CLONE_NEWUTS', 67108864); /** * @since 7.4 */ define('CLONE_NEWNET', 1073741824); /** * @since 7.4 */ define('CLONE_NEWPID', 536870912); /** * @since 7.4 */ define('CLONE_NEWUSER', 268435456); /** * @since 7.4 */ define('CLONE_NEWCGROUP', 33554432); /** * @since 8.4 */ define('P_ALL', 0); /** * @since 8.4 */ define('WEXITED', 4); /** * @since 8.4 */ define('WSTOPPED', 2); /** * @since 8.4 */ define('WNOWAIT', 16777216); /** * @since 8.4 */ define('P_PID', 1); /** * @since 8.4 */ define('P_PGID', 2); /** * @since 8.4 */ define('P_PIDFD', 3); // End of pcntl v. * Send the YAML representation of a value to a file * @link https://php.net/manual/en/function.yaml-emit-file.php * @param string $filename Path to the file. * @param mixed $data The data being encoded. Can be any type except a resource. * @param int $encoding Output character encoding chosen from YAML_ANY_ENCODING, YAML_UTF8_ENCODING, YAML_UTF16LE_ENCODING, YAML_UTF16BE_ENCODING. * @param int $linebreak Output linebreak style chosen from YAML_ANY_BREAK, YAML_CR_BREAK, YAML_LN_BREAK, YAML_CRLN_BREAK. * @param array $callbacks [optional] Content handlers for YAML nodes. Associative array of YAML tag => callable mappings. See parse callbacks for more details. * @return bool Returns TRUE on success. */ function yaml_emit_file($filename, $data, $encoding = YAML_ANY_ENCODING, $linebreak = YAML_ANY_BREAK, array $callbacks = []) {} /** * (PHP 5 >= 5.2.0, PECL yaml >= 0.5.0)
    * @link https://php.net/manual/en/function.yaml-emit.php * @param mixed $data The data being encoded. Can be any type except a resource. * @param int $encoding [optional] Output character encoding chosen from YAML_ANY_ENCODING, YAML_UTF8_ENCODING, YAML_UTF16LE_ENCODING, YAML_UTF16BE_ENCODING. * @param int $linebreak [optional] Output linebreak style chosen from YAML_ANY_BREAK, YAML_CR_BREAK, YAML_LN_BREAK, YAML_CRLN_BREAK. * @param array $callbacks [optional] Content handlers for YAML nodes. Associative array of YAML tag => callable mappings. See parse callbacks for more details. * @return string Returns a YAML encoded string on success. */ function yaml_emit($data, $encoding = YAML_ANY_ENCODING, $linebreak = YAML_ANY_BREAK, array $callbacks = []) {} /** * (PHP 5 >= 5.2.0, PECL yaml >= 0.4.0)
    * Parse a YAML stream from a file * @link https://php.net/manual/en/function.yaml-parse-file.php * @param string $filename Path to the file. * @param int $pos [optional] Document to extract from stream (-1 for all documents, 0 for first document, ...). * @param int &$ndocs [optional] If ndocs is provided, then it is filled with the number of documents found in stream. * @param array $callbacks [optional] Content handlers for YAML nodes. Associative array of YAML tag => callable mappings. See parse callbacks for more details. * @return mixed|false Returns the value encoded in input in appropriate PHP type or FALSE on failure. If pos is -1 an array will be returned with one entry for each document found in the stream. */ function yaml_parse_file($filename, $pos = 0, &$ndocs = null, array $callbacks = []) {} /** * (PHP 5 >= 5.2.0, PECL yaml >= 0.4.0)
    * Parse a Yaml stream from a URL * @link https://php.net/manual/en/function.yaml-parse-url.php * @param string $url url should be of the form "scheme://...". PHP will search for a protocol handler (also known as a wrapper) for that scheme. If no wrappers for that protocol are registered, PHP will emit a notice to help you track potential problems in your script and then continue as though filename specifies a regular file. * @param int $pos [optional] Document to extract from stream (-1 for all documents, 0 for first document, ...). * @param int &$ndocs [optional] If ndocs is provided, then it is filled with the number of documents found in stream. * @param array $callbacks [optional] Content handlers for YAML nodes. Associative array of YAML tag => callable mappings. See parse callbacks for more details. * @return mixed|false Returns the value encoded in input in appropriate PHP type or FALSE on failure. If pos is -1 an array will be returned with one entry for each document found in the stream. */ function yaml_parse_url($url, $pos = 0, &$ndocs = null, array $callbacks = []) {} /** * (PHP 5 >= 5.2.0, PECL yaml >= 0.4.0)
    * Parse a YAML stream * @link https://php.net/manual/en/function.yaml-parse.php * @param string $input The string to parse as a YAML document stream. * @param int $pos [optional] Document to extract from stream (-1 for all documents, 0 for first document, ...). * @param int &$ndocs [optional] If ndocs is provided, then it is filled with the number of documents found in stream. * @param array $callbacks [optional] Content handlers for YAML nodes. Associative array of YAML tag => callable mappings. See parse callbacks for more details. * @return mixed|false Returns the value encoded in input in appropriate PHP type or FALSE on failure. If pos is -1 an array will be returned with one entry for each document found in the stream. */ function yaml_parse($input, $pos = 0, &$ndocs = null, array $callbacks = []) {} = 4.0.0) * and the mutation operation succeeded. * * If set, it can be used for enhanced durability requirements, as well as optimized consistency * for N1QL queries. */ public $token; } /** * A fragment of a JSON Document returned by the sub-document API. * * @see \Couchbase\Bucket::mutateIn() * @see \Couchbase\Bucket::lookupIn() */ class DocumentFragment { /** * @var Exception exception object in case of error, or NULL */ public $error; /** * @var mixed The value sub-document command returned. */ public $value; /** * @var string The last known CAS value of the document */ public $cas; /** * @var MutationToken * The optional, opaque mutation token related to updated document the environment. * * Note that the mutation token is always NULL, unless they are explicitly enabled on the * connection string (`?fetch_mutation_tokens=true`), the server version is supported (>= 4.0.0) * and the mutation operation succeeded. * * If set, it can be used for enhanced durability requirements, as well as optimized consistency * for N1QL queries. */ public $token; } /** * Represents a Couchbase Server Cluster. * * It is an entry point to the library, and in charge of opening connections to the Buckets. * In addition it can instantiate \Couchbase\ClusterManager to peform cluster-wide operations. * * @see \Couchbase\Bucket * @see \Couchbase\ClusterManager * @see \Couchbase\Authenticator */ class Cluster { /** * Create cluster object * * @param string $connstr connection string */ public function __construct($connstr) {} /** * Open connection to the Couchbase bucket * * @param string $name Name of the bucket. * @param string $password Password of the bucket to override authenticator. * @return Bucket * * @see \Couchbase\Authenticator */ public function openBucket($name = "default", $password = "") {} /** * Open management connection to the Couchbase cluster. * * @param string $username Name of the administrator to override authenticator or NULL. * @param string $password Password of the administrator to override authenticator or NULL. * @return ClusterManager * * @see \Couchbase\Authenticator */ public function manager($username = null, $password = null) {} /** * Associate authenticator with Cluster * * @param Authenticator $authenticator * @return null * * @see \Couchbase\Authenticator * @see \Couchbase\ClassicAuthenticator * @see \Couchbase\PasswordAuthenticator */ public function authenticate($authenticator) {} /** * Create \Couchbase\PasswordAuthenticator from given credentials and associate it with Cluster * * @param string $username * @param string $password * @return null * * @see \Couchbase\Authenticator * @see \Couchbase\PasswordAuthenticator */ public function authenticateAs($username, $password) {} } /** * Provides management capabilities for a Couchbase Server Cluster * * @see \Couchbase\Cluster */ class ClusterManager { /** * The user account managed by Couchbase Cluster. */ public const RBAC_DOMAIN_LOCAL = 1; /** * The user account managed by external system (e.g. LDAP). */ public const RBAC_DOMAIN_EXTERNAL = 2; final private function __construct() {} /** * Lists all buckets on this cluster. * * @return array */ public function listBuckets() {} /** * Creates new bucket * * @param string $name Name of the bucket * @param array $options Bucket options * * "authType" (default: "sasl") type of the bucket authentication * * "bucketType" (default: "couchbase") type of the bucket * * "ramQuotaMB" (default: 100) memory quota of the bucket * * "replicaNumber" (default: 1) number of replicas. * * @see https://developer.couchbase.com/documentation/server/current/rest-api/rest-bucket-create.html * More options and details */ public function createBucket($name, $options = []) {} /** * Removes a bucket identified by its name. * * @param string $name name of the bucket * * @see https://developer.couchbase.com/documentation/server/current/rest-api/rest-bucket-delete.html * More details */ public function removeBucket($name) {} /** * Provides information about the cluster. * * Returns an associative array of status information as seen on the cluster. The exact structure of the returned * data can be seen in the Couchbase Manual by looking at the cluster /info endpoint. * * @return array * * @see https://developer.couchbase.com/documentation/server/current/rest-api/rest-cluster-get.html * Retrieving Cluster Information */ public function info() {} /** * Lists all users on this cluster. * * @param int $domain RBAC domain * * @return array * * @see \Couchbase\ClusterManager::RBAC_DOMAIN_LOCAL * @see \Couchbase\ClusterManager::RBAC_DOMAIN_EXTERNAL */ public function listUsers($domain = RBAC_DOMAIN_LOCAL) {} /** * Fetch single user by its name * * @param string $username The user's identifier * @param int $domain RBAC domain * * @return array * * @see \Couchbase\ClusterManager::RBAC_DOMAIN_LOCAL * @see \Couchbase\ClusterManager::RBAC_DOMAIN_EXTERNAL */ public function getUser($username, $domain = RBAC_DOMAIN_LOCAL) {} /** * Creates new user * * @param string $name Name of the user * @param \Couchbase\UserSettings $settings settings (credentials and roles) * @param int $domain RBAC domain * * @see https://developer.couchbase.com/documentation/server/5.0/rest-api/rbac.html * More options and details * @see \Couchbase\ClusterManager::RBAC_DOMAIN_LOCAL * @see \Couchbase\ClusterManager::RBAC_DOMAIN_EXTERNAL */ public function upsertUser($name, $settings, $domain = RBAC_DOMAIN_LOCAL) {} /** * Removes a user identified by its name. * * @param string $name name of the bucket * @param int $domain RBAC domain * * @see https://developer.couchbase.com/documentation/server/5.0/rest-api/rbac.html * More details * @see \Couchbase\ClusterManager::RBAC_DOMAIN_LOCAL * @see \Couchbase\ClusterManager::RBAC_DOMAIN_EXTERNAL */ public function removeUser($name, $domain = RBAC_DOMAIN_LOCAL) {} } /** * Represents settings for new/updated user. * * @see https://developer.couchbase.com/documentation/server/5.0/rest-api/rbac.html */ class UserSettings { /** * Sets full name of the user (optional). * * @param string $fullName Full name of the user * * @return \Couchbase\UserSettings * * @see https://developer.couchbase.com/documentation/server/5.0/rest-api/rbac.html * More details */ public function fullName($fullName) {} /** * Sets password of the user. * * @param string $password Password of the user * * @return \Couchbase\UserSettings * * @see https://developer.couchbase.com/documentation/server/5.0/rest-api/rbac.html * More details */ public function password($password) {} /** * Adds role to the list of the accessible roles of the user. * * @param string $role identifier of the role * @param string $bucket the bucket where this role applicable (or `*` for all buckets) * * @return \Couchbase\UserSettings * * @see https://developer.couchbase.com/documentation/server/5.0/rest-api/rbac.html * More details */ public function role($role, $bucket = null) {} } /** * Represents connection to the Couchbase Server * * @property int $operationTimeout * The operation timeout (in microseconds) is the maximum amount of time the * library will wait for an operation to receive a response before invoking * its callback with a failure status. * * An operation may timeout if: * * * A server is taking too long to respond * * An updated cluster configuration has not been promptly received * * @property int $viewTimeout * The I/O timeout (in microseconds) for HTTP requests to Couchbase Views API * * @property int $n1qlTimeout * The I/O timeout (in microseconds) for N1QL queries. * * @property int $httpTimeout * The I/O timeout (in microseconds) for HTTP queries (management API). * * @property int $configTimeout * How long (in microseconds) the client will wait to obtain the initial * configuration. * * @property int $configNodeTimeout * Per-node configuration timeout (in microseconds). * * This timeout sets the amount of time to wait for each node within * the bootstrap/configuration process. This interval is a subset of * the $configTimeout option mentioned above and is intended to ensure * that the bootstrap process does not wait too long for a given node. * Nodes that are physically offline may never respond and it may take * a long time until they are detected as being offline. * * @property int $configDelay * Config refresh throttling * * Modify the amount of time (in microseconds) before the configiration * error threshold will forcefully be set to its maximum number forcing * a configuration refresh. * * Note that if you expect a high number of timeouts in your operations, * you should set this to a high number. If you are using the default * timeout setting, then this value is likely optimal. * * @property int $htconfigIdleTimeout * Idling/Persistence for HTTP bootstrap (in microseconds) * * By default the behavior of the library for HTTP bootstrap is to keep * the stream open at all times (opening a new stream on a different host * if the existing one is broken) in order to proactively receive * configuration updates. * * The default value for this setting is -1. Changing this to another * number invokes the following semantics: * * * The configuration stream is not kept alive indefinitely. It is kept * open for the number of seconds specified in this setting. The socket * is closed after a period of inactivity (indicated by this setting). * * * If the stream is broken (and no current refresh was requested by * the client) then a new stream is not opened. * * @property int $durabilityInterval * The time (in microseconds) the client will wait between repeated probes * to a given server. * * @property int $durabilityTimeout * The time (in microseconds) the client will spend sending repeated probes * to a given key's vBucket masters and replicas before they are deemed not * to have satisfied the durability requirements * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/start-using-sdk.html * Start Using SDK */ class Bucket { /** Ping data (Key/Value) service. */ public const PINGSVC_KV = 0x01; /** Ping query (N1QL) service. */ public const PINGSVC_N1QL = 0x02; /** Ping views (Map/Reduce) service. */ public const PINGSVC_VIEWS = 0x04; /** Ping full text search (FTS) service. */ public const PINGSVC_FTS = 0x08; final private function __construct() {} /** * @param string $name * @return int */ final private function __get($name) {} /** * @param string $name * @param int $value * @return int */ final private function __set($name, $value) {} /** * Returns the name of the bucket for current connection * * @return string */ public function getName() {} /** * Returns an instance of a CouchbaseBucketManager for performing management operations against a bucket. * * @return BucketManager */ public function manager() {} /** * Sets custom encoder and decoder functions for handling serialization. * * @param callable $encoder * @param callable $decoder * * @see \Couchbase\defaultEncoder * @see \Couchbase\defaultDecoder * @see \Couchbase\passthruEncoder * @see \Couchbase\passthruDecoder */ public function setTranscoder($encoder, $decoder) {} /** * Retrieves a document * * @param string|array $ids one or more IDs * @param array $options options * * "lockTime" non zero if the documents have to be locked * * "expiry" non zero if the expiration time should be updated * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see \Couchbase\Bucket::getAndLock() * @see \Couchbase\Bucket::getAndTouch() * @see \Couchbase\Bucket::unlock() * @see \Couchbase\Bucket::touch() * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function get($ids, $options = []) {} /** * Retrieves a document and locks it. * * After the document has been locked on the server, its CAS would be masked, * and all mutations of it will be rejected until the server unlocks the document * automatically or it will be done manually with \Couchbase\Bucket::unlock() operation. * * @param string|array $ids one or more IDs * @param int $lockTime time to lock the documents * @param array $options options * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see \Couchbase\Bucket::unlock() * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK * @see https://forums.couchbase.com/t/is-there-a-way-to-do-pessimistic-locking-for-more-than-30-seconds/10666/3 * Forum post about getting server defaults for the $lockTime */ public function getAndLock($ids, $lockTime, $options = []) {} /** * Retrieves a document and updates its expiration time. * * @param string|array $ids one or more IDs * @param int $expiry time after which the document will not be accessible. * If larger than 30 days (60*60*24*30), it will be interpreted by the * server as absolute UNIX time (seconds from epoch 1970-01-01T00:00:00). * @param array $options options * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function getAndTouch($ids, $expiry, $options = []) {} /** * Retrieves a document from a replica. * * @param string|array $ids one or more IDs * @param array $options options * * "index" the replica index. If the index is zero, it will return * first successful replica, otherwise it will read only selected node. * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK * @see https://developer.couchbase.com/documentation/server/current/sdk/php/failure-considerations.html * More about failure considerations. */ public function getFromReplica($ids, $options = []) {} /** * Inserts or updates a document, depending on whether the document already exists on the cluster. * * @param string|array $ids one or more IDs * @param mixed $value value of the document * @param array $options options * * "expiry" document expiration time in seconds. If larger than 30 days (60*60*24*30), * it will be interpreted by the server as absolute UNIX time (seconds from epoch * 1970-01-01T00:00:00). * * "persist_to" how many nodes the key should be persisted to (including master). * If set to 0 then persistence will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which persistence * is possible (which will always contain at least the master node). * * "replicate_to" how many nodes the key should be persisted to (excluding master). * If set to 0 then replication will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which replication * is possible (which may be 0 if the bucket is not configured for replicas). * * "flags" override flags (not recommended to use) * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function upsert($ids, $value, $options = []) {} /** * Inserts a document. This operation will fail if the document already exists on the cluster. * * @param string|array $ids one or more IDs * @param mixed $value value of the document * @param array $options options * * "expiry" document expiration time in seconds. If larger than 30 days (60*60*24*30), * it will be interpreted by the server as absolute UNIX time (seconds from epoch * 1970-01-01T00:00:00). * * "persist_to" how many nodes the key should be persisted to (including master). * If set to 0 then persistence will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which persistence * is possible (which will always contain at least the master node). * * "replicate_to" how many nodes the key should be persisted to (excluding master). * If set to 0 then replication will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which replication * is possible (which may be 0 if the bucket is not configured for replicas). * * "flags" override flags (not recommended to use) * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function insert($ids, $value, $options = []) {} /** * Replaces a document. This operation will fail if the document does not exists on the cluster. * * @param string|array $ids one or more IDs * @param mixed $value value of the document * @param array $options options * * "cas" last known document CAS, which serves for optimistic locking. * * "expiry" document expiration time in seconds. If larger than 30 days (60*60*24*30), * it will be interpreted by the server as absolute UNIX time (seconds from epoch * 1970-01-01T00:00:00). * * "persist_to" how many nodes the key should be persisted to (including master). * If set to 0 then persistence will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which persistence * is possible (which will always contain at least the master node). * * "replicate_to" how many nodes the key should be persisted to (excluding master). * If set to 0 then replication will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which replication * is possible (which may be 0 if the bucket is not configured for replicas). * * "flags" override flags (not recommended to use) * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function replace($ids, $value, $options = []) {} /** * Appends content to a document. * * On the server side it just contatenate passed value to the existing one. * Note that this might make the value un-decodable. Consider sub-document API * for partial updates of the JSON documents. * * @param string|array $ids one or more IDs * @param mixed $value value of the document * @param array $options options * * "cas" last known document CAS, which serves for optimistic locking. * * "expiry" document expiration time in seconds. If larger than 30 days (60*60*24*30), * it will be interpreted by the server as absolute UNIX time (seconds from epoch * 1970-01-01T00:00:00). * * "persist_to" how many nodes the key should be persisted to (including master). * If set to 0 then persistence will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which persistence * is possible (which will always contain at least the master node). * * "replicate_to" how many nodes the key should be persisted to (excluding master). * If set to 0 then replication will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which replication * is possible (which may be 0 if the bucket is not configured for replicas). * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see \Couchbase\Bucket::mutateIn() * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function append($ids, $value, $options = []) {} /** * Prepends content to a document. * * On the server side it just contatenate existing value to the passed one. * Note that this might make the value un-decodable. Consider sub-document API * for partial updates of the JSON documents. * * @param string|array $ids one or more IDs * @param mixed $value value of the document * @param array $options options * * "cas" last known document CAS, which serves for optimistic locking. * * "expiry" document expiration time in seconds. If larger than 30 days (60*60*24*30), * it will be interpreted by the server as absolute UNIX time (seconds from epoch * 1970-01-01T00:00:00). * * "persist_to" how many nodes the key should be persisted to (including master). * If set to 0 then persistence will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which persistence * is possible (which will always contain at least the master node). * * "replicate_to" how many nodes the key should be persisted to (excluding master). * If set to 0 then replication will not be checked. If set to a negative * number, will be set to the maximum number of nodes to which replication * is possible (which may be 0 if the bucket is not configured for replicas). * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see \Couchbase\Bucket::mutateIn() * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function prepend($ids, $value, $options = []) {} /** * Removes the document. * * @param string|array $ids one or more IDs * @param array $options options * * "cas" last known document CAS, which serves for optimistic locking. * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function remove($ids, $options = []) {} /** * Unlocks previously locked document * * @param string|array $ids one or more IDs * @param array $options options * * "cas" last known document CAS, which has been returned by locking command. * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see \Couchbase\Bucket::get() * @see \Couchbase\Bucket::getAndLock() * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function unlock($ids, $options = []) {} /** * Updates document's expiration time. * * @param string|array $ids one or more IDs * @param int $expiry time after which the document will not be accessible. * If larger than 30 days (60*60*24*30), it will be interpreted by the * server as absolute UNIX time (seconds from epoch 1970-01-01T00:00:00). * @param array $options options * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function touch($ids, $expiry, $options = []) {} /** * Increments or decrements a key (based on $delta) * * @param string|array $ids one or more IDs * @param int $delta the number whih determines the sign (positive/negative) and the value of the increment * @param array $options options * * "initial" initial value of the counter if it does not exist * * "expiry" time after which the document will not be accessible. * If larger than 30 days (60*60*24*30), it will be interpreted by the * server as absolute UNIX time (seconds from epoch 1970-01-01T00:00:00). * * "groupid" override value for hashing (not recommended to use) * @return \Couchbase\Document|array document or list of the documents * * @see https://developer.couchbase.com/documentation/server/current/sdk/core-operations.html * Overview of K/V operations * @see https://developer.couchbase.com/documentation/server/current/sdk/php/document-operations.html * More details about K/V operations for PHP SDK */ public function counter($ids, $delta = 1, $options = []) {} /** * Returns a builder for reading subdocument API. * * @param string $id The ID of the JSON document * @return LookupInBuilder * * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function lookupIn($id) {} /** * Retrieves specified paths in JSON document * * This is essentially a shortcut for `lookupIn($id)->get($paths)->execute()`. * * @param string $id The ID of the JSON document * @param string ...$paths List of the paths inside JSON documents (see "Path syntax" section of the * "Sub-Document Operations" documentation). * @return \Couchbase\DocumentFragment * * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function retrieveIn($id, ...$paths) {} /** * Returns a builder for writing subdocument API. * * @param string $id The ID of the JSON document * @param string $cas Last known document CAS value for optimisti locking * @return MutateInBuilder * * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function mutateIn($id, $cas) {} /** * Performs a query to Couchbase Server * * @param N1qlQuery|ViewQuery|SpatialViewQuery|SearchQuery|AnalyticsQuery $query * @param bool $jsonAsArray if true, the values in the result rows (or hits) will be represented as * PHP arrays, otherwise they will be instances of the `stdClass` * @return object Query-specific result object. * * @see \Couchbase\N1qlQuery * @see \Couchbase\SearchQuery * @see \Couchbase\ViewQuery * @see \Couchbase\SpatialViewQuery */ public function query($query, $jsonAsArray = false) {} /** * Returns size of the map * * @param string $id ID of the document * @return int number of the key-value pairs * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function mapSize($id) {} /** * Add key to the map * * @param string $id ID of the document * @param string $key key * @param mixed $value value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function mapAdd($id, $key, $value) {} /** * Removes key from the map * * @param string $id ID of the document * @param string $key key * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function mapRemove($id, $key) {} /** * Get an item from a map * * @param string $id ID of the document * @param string $key key * @return mixed value associated with the key * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function mapGet($id, $key) {} /** * Returns size of the set * * @param string $id ID of the document * @return int number of the elements * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function setSize($id) {} /** * Add value to the set * * Note, that currently only primitive values could be stored in the set (strings, integers and booleans). * * @param string $id ID of the document * @param string|int|float|bool $value new value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function setAdd($id, $value) {} /** * Check if the value exists in the set * * @param string $id ID of the document * @param string|int|float|bool $value value to check * @return bool true if the value exists in the set * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function setExists($id, $value) {} /** * Remove value from the set * * @param string $id ID of the document * @param string|int|float|bool $value value to remove * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function setRemove($id, $value) {} /** * Returns size of the list * * @param string $id ID of the document * @return int number of the elements * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function listSize($id) {} /** * Add an element to the end of the list * * @param string $id ID of the document * @param mixed $value new value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function listPush($id, $value) {} /** * Add an element to the beginning of the list * * @param string $id ID of the document * @param mixed $value new value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function listShift($id, $value) {} /** * Remove an element at the given position * * @param string $id ID of the document * @param int $index index of the element to be removed * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function listRemove($id, $index) {} /** * Get an element at the given position * * @param string $id ID of the document * @param int $index index of the element * @return mixed the value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function listGet($id, $index) {} /** * Set an element at the given position * * @param string $id ID of the document * @param int $index index of the element * @param mixed $value new value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function listSet($id, $index, $value) {} /** * Check if the list contains specified value * * @param string $id ID of the document * @param mixed $value value to look for * @return bool true if the list contains the value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function listExists($id, $value) {} /** * Returns size of the queue * * @param string $id ID of the document * @return int number of the elements in the queue * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function queueSize($id) {} /** * Checks if the queue contains specified value * * @param string $id ID of the document * @param mixed $value value to look for * @return bool true if the queue contains the value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function queueExists($id, $value) {} /** * Add an element to the beginning of the queue * * @param string $id ID of the document * @param mixed $value new value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function queueAdd($id, $value) {} /** * Remove the element at the end of the queue and return it * * @param string $id ID of the document * @return mixed removed value * * @see https://developer.couchbase.com/documentation/server/current/sdk/php/datastructures.html * More details on Data Structures * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Overview of Sub-Document Operations */ public function queueRemove($id) {} /** * Try to reach specified services, and measure network latency. * * @param int $services bitwise mask of required services (and all services when zero) * @param string $reportId custom identifier, which will be appended to "id" property in report * @return array the report object * * @see \Couchbase\Bucket::PINGSVC_KV * @see \Couchbase\Bucket::PINGSVC_N1QL * @see \Couchbase\Bucket::PINGSVC_VIEWS * @see \Couchbase\Bucket::PINGSVC_FTS * * @see https://github.com/couchbaselabs/sdk-rfcs/blob/master/rfc/0034-health-check.md * SDK RFC #34, which describes the feature and report layout. */ public function ping($services = 0, $reportId = null) {} /** * Collect and return information about state of internal network connections. * * @param string $reportId custom identifier, which will be appended to "id" property in report * @return array the report object * * @see https://github.com/couchbaselabs/sdk-rfcs/blob/master/rfc/0034-health-check.md * SDK RFC #34, which describes the feature and report layout. */ public function diag($reportId = null) {} /** * Encrypt fields inside specified document. * * @param array $document document structure * @param array $fieldOptions specification for fields needed to be encrypted. Where 'alg' contains * a string with alias of the registed crypto provider, and 'name' contains the name of the field. * @param string $prefix optional prefix for modified field (when null, the library will use "__crypt") * * @return array where the fields encrypted * * @see https://github.com/couchbase/php-couchbase-encryption */ public function encryptFields($document, $fieldOptions, $prefix = null) {} /** * Decrypt fields inside specified document. * * @param array $document document structure * @param array $fieldOptions specification for fields needed to be decrypted. Where 'alg' contains * a string with alias of the registed crypto provider, and 'name' contains the name of the field. * @param string $prefix optional prefix for modified field (when null, the library will use "__crypt") * * @return array where the fields decrypted * * @see https://github.com/couchbase/php-couchbase-encryption */ public function decryptFields($document, $fieldOptions, $prefix = null) {} } /** * Provides management capabilities for the Couchbase Bucket */ class BucketManager { final private function __construct() {} /** * Returns information about the bucket * * Returns an associative array of status information as seen by the cluster for * this bucket. The exact structure of the returned data can be seen in the Couchbase * Manual by looking at the bucket /info endpoint. * * @return array * * @see https://developer.couchbase.com/documentation/server/current/rest-api/rest-bucket-info.html * Getting Single Bucket Information */ public function info() {} /** * Flushes the bucket (clears all data) */ public function flush() {} /** * Returns all design documents of the bucket. * * @return array */ public function listDesignDocuments() {} /** * Get design document by its name * * @param string $name name of the design document (without _design/ prefix) * @return array */ public function getDesignDocument($name) {} /** * Removes design document by its name * * @param string $name name of the design document (without _design/ prefix) */ public function removeDesignDocument($name) {} /** * Creates or replaces design document. * * @param string $name name of the design document (without _design/ prefix) * @param array $document */ public function upsertDesignDocument($name, $document) {} /** * Inserts design document and fails if it is exist already. * * @param string $name name of the design document (without _design/ prefix) * @param array $document */ public function insertDesignDocument($name, $document) {} /** * List all N1QL indexes that are registered for the current bucket. * * @return array */ public function listN1qlIndexes() {} /** * Create a primary N1QL index. * * @param string $customName the custom name for the primary index. * @param bool $ignoreIfExist if a primary index already exists, an exception * will be thrown unless this is set to true. * @param bool $defer true to defer index building. */ public function createN1qlPrimaryIndex($customName = '', $ignoreIfExist = false, $defer = false) {} /** * Create secondary N1QL index. * * @param string $name name of the index * @param array $fields list of JSON fields to index * @param string $whereClause the WHERE clause of the index. * @param bool $ignoreIfExist if a secondary index already exists, an exception * will be thrown unless this is set to true. * @param bool $defer true to defer index building. */ public function createN1qlIndex($name, $fields, $whereClause = '', $ignoreIfExist = false, $defer = false) {} /** * Drop the given primary index * * @param string $customName the custom name for the primary index * @param bool $ignoreIfNotExist if a primary index does not exist, an exception * will be thrown unless this is set to true. */ public function dropN1qlPrimaryIndex($customName = '', $ignoreIfNotExist = false) {} /** * Drop the given secondary index * * @param string $name the index name * @param bool $ignoreIfNotExist if a secondary index does not exist, an exception * will be thrown unless this is set to true. */ public function dropN1qlIndex($name, $ignoreIfNotExist = false) {} } /** * Interface of authentication containers. * * @see \Couchbase\Cluster::authenticate() * @see \Couchbase\ClassicAuthenticator * @see \Couchbase\PasswordAuthenticator */ interface Authenticator {} /** * Authenticator based on login/password credentials. * * This authenticator uses separate credentials for Cluster management interface * as well as for each bucket. * * * * @see \Couchbase\Cluster::authenticate() * @see \Couchbase\Authenticator */ class ClassicAuthenticator implements Authenticator { /** * Registers cluster management credentials in the container * * @param string $username admin username * @param string $password admin password */ public function cluster($username, $password) {} /** * Registers bucket credentials in the container * * @param string $name bucket name * @param string $password bucket password */ public function bucket($name, $password) {} } /** * Authenticator based on RBAC feature of Couchbase Server 5+. * * This authenticator uses single credentials for all operations (data and management). * * @see \Couchbase\Cluster::authenticate() * @see \Couchbase\Authenticator */ class PasswordAuthenticator implements Authenticator { /** * Sets username * * @param string $username username * @return \Couchbase\PasswordAuthenticator */ public function username($username) {} /** * Sets password * * @param string $password password * @return \Couchbase\PasswordAuthenticator */ public function password($password) {} } /** * An object which contains meta information of the document needed to enforce query consistency. */ class MutationToken { final private function __construct() {} /** * Creates new mutation token * * @param string $bucketName name of the bucket * @param int $vbucketId partition number * @param string $vbucketUuid UUID of the partition * @param string $sequenceNumber sequence number inside partition */ public static function from($bucketName, $vbucketId, $vbucketUuid, $sequenceNumber) {} /** * Returns bucket name * * @return string */ public function bucketName() {} /** * Returns partition number * * @return int */ public function vbucketId() {} /** * Returns UUID of the partition * * @return string */ public function vbucketUuid() {} /** * Returns the sequence number inside partition * * @return string */ public function sequenceNumber() {} } /** * Container for mutation tokens. */ class MutationState { final private function __construct() {} /** * Create container from the given mutation token holders. * * @param array|Document|DocumentFragment $source anything that can have attached MutationToken * @return MutationState * * @see \Couchbase\MutationToken */ public static function from($source) {} /** * Update container with the given mutation token holders. * * @param array|Document|DocumentFragment $source anything that can have attached MutationToken * * @see \Couchbase\MutationToken */ public function add($source) {} } /** * Common interface for all View queries * * @see \Couchbase\ViewQuery * @see \Couchbase\SpatialViewQuery */ interface ViewQueryEncodable { /** * Returns associative array, representing the View query. * * @return array object which is ready to be serialized. */ public function encode(); } /** * Represents regular Couchbase Map/Reduce View query * * @see \Couchbase\Bucket::query() * @see \Couchbase\SpatialViewQuery * @see https://developer.couchbase.com/documentation/server/current/sdk/php/view-queries-with-sdk.html * MapReduce Views * @see https://developer.couchbase.com/documentation/server/current/architecture/querying-data-with-views.html * Querying Data with Views * @see https://developer.couchbase.com/documentation/server/current/rest-api/rest-views-get.html * Getting Views Information */ class ViewQuery implements ViewQueryEncodable { /** Force a view update before returning data */ public const UPDATE_BEFORE = 1; /** Allow stale views */ public const UPDATE_NONE = 2; /** Allow stale view, update view after it has been accessed. */ public const UPDATE_AFTER = 3; public const ORDER_ASCENDING = 1; public const ORDER_DESCENDING = 2; final private function __construct() {} /** * Creates a new Couchbase ViewQuery instance for performing a view query. * * @param string $designDocumentName the name of the design document to query * @param string $viewName the name of the view to query * @return ViewQuery */ public static function from($designDocumentName, $viewName) {} /** * Creates a new Couchbase ViewQuery instance for performing a spatial query. * @param string $designDocumentName the name of the design document to query * @param string $viewName the name of the view to query * @return SpatialViewQuery */ public static function fromSpatial($designDocumentName, $viewName) {} /** * Returns associative array, representing the View query. * * @return array object which is ready to be serialized. */ public function encode() {} /** * Limits the result set to a specified number rows. * * @param int $limit maximum number of records in the response * @return ViewQuery */ public function limit($limit) {} /** * Skips a number o records rom the beginning of the result set * * @param int $skip number of records to skip * @return ViewQuery */ public function skip($skip) {} /** * Specifies the mode of updating to perorm before and after executing the query * * @param int $consistency use constants UPDATE_BEFORE, UPDATE_NONE, UPDATE_AFTER * @return ViewQuery * * @see \Couchbase\ViewQuery::UPDATE_BEFORE * @see \Couchbase\ViewQuery::UPDATE_NONE * @see \Couchbase\ViewQuery::UPDATE_AFTER */ public function consistency($consistency) {} /** * Orders the results by key as specified * * @param int $order use contstants ORDER_ASCENDING, ORDER_DESCENDING * @return ViewQuery */ public function order($order) {} /** * Specifies whether the reduction function should be applied to results of the query. * * @param bool $reduce * @return ViewQuery */ public function reduce($reduce) {} /** * Group the results using the reduce function to a group or single row. * * Important: this setter and groupLevel should not be used together in the * same ViewQuery. It is sufficient to only set the grouping level only and * use this setter in cases where you always want the highest group level * implictly. * * @param bool $group * @return ViewQuery * * @see \Couchbase\ViewQuery::groupLevel */ public function group($group) {} /** * Specify the group level to be used. * * Important: group() and this setter should not be used together in the * same ViewQuery. It is sufficient to only use this setter and use group() * in cases where you always want the highest group level implictly. * * @param int $groupLevel the number of elements in the keys to use * @return ViewQuery * * @see \Couchbase\ViewQuery::group */ public function groupLevel($groupLevel) {} /** * Restict results of the query to the specified key * * @param mixed $key key * @return ViewQuery */ public function key($key) {} /** * Restict results of the query to the specified set of keys * * @param array $keys set of keys * @return ViewQuery */ public function keys($keys) {} /** * Specifies a range of the keys to return from the index. * * @param mixed $startKey * @param mixed $endKey * @param bool $inclusiveEnd * @return ViewQuery */ public function range($startKey, $endKey, $inclusiveEnd = false) {} /** * Specifies start and end document IDs in addition to range limits. * * This might be needed for more precise pagination with a lot of documents * with the same key selected into the same page. * * @param string $startKeyDocumentId document ID * @param string $endKeyDocumentId document ID * @return ViewQuery */ public function idRange($startKeyDocumentId, $endKeyDocumentId) {} /** * Specifies custom options to pass to the server. * * Note that these options are expected to be already encoded. * * @param array $customParameters parameters * @return ViewQuery * * @see https://developer.couchbase.com/documentation/server/current/rest-api/rest-views-get.html * Getting Views Information */ public function custom($customParameters) {} } /** * Represents spatial Couchbase Map/Reduce View query * * @see \Couchbase\Bucket::query() * @see \Couchbase\ViewQuery * @see https://developer.couchbase.com/documentation/server/current/architecture/querying-geo-data-spatial-views.html * Querying Geographic Data with Spatial Views * @see https://developer.couchbase.com/documentation/server/current/rest-api/rest-views-get.html * Getting Views Information * @see https://developer.couchbase.com/documentation/server/current/views/sv-query-parameters.html * Querying spatial views */ class SpatialViewQuery implements ViewQueryEncodable { final private function __construct() {} /** * Returns associative array, representing the View query. * * @return array object which is ready to be serialized. */ public function encode() {} /** * Limits the result set to a specified number rows. * * @param int $limit maximum number of records in the response * @return SpatialViewQuery */ public function limit($limit) {} /** * Skips a number o records rom the beginning of the result set * * @param int $skip number of records to skip * @return SpatialViewQuery */ public function skip($skip) {} /** * Specifies the mode of updating to perorm before and after executing the query * * @param int $consistency use constants UPDATE_BEFORE, UPDATE_NONE, UPDATE_AFTER * @return SpatialViewQuery * * @see \Couchbase\ViewQuery::UPDATE_BEFORE * @see \Couchbase\ViewQuery::UPDATE_NONE * @see \Couchbase\ViewQuery::UPDATE_AFTER */ public function consistency($consistency) {} /** * Orders the results by key as specified * * @param int $order use contstants ORDER_ASCENDING, ORDER_DESCENDING * @return SpatialViewQuery */ public function order($order) {} /** * Specifies the bounding box to search within. * * Note, using bbox() is discouraged, startRange/endRange is more flexible and should be preferred. * * @param array $bbox bounding box coordinates expressed as a list of numeric values * @return SpatialViewQuery * * @see \Couchbase\SpatialViewQuery::startRange() * @see \Couchbase\SpatialViewQuery::endRange() */ public function bbox($bbox) {} /** * Specify start range for query * * @param array $range * @return SpatialViewQuery * * @see https://developer.couchbase.com/documentation/server/current/views/sv-query-parameters.html * Querying spatial views */ public function startRange($range) {} /** * Specify end range for query * * @param array $range * @return SpatialViewQuery * * @see https://developer.couchbase.com/documentation/server/current/views/sv-query-parameters.html * Querying spatial views */ public function endRange($range) {} /** * Specifies custom options to pass to the server. * * Note that these options are expected to be already encoded. * * @param array $customParameters parameters * * @see https://developer.couchbase.com/documentation/server/current/rest-api/rest-views-get.html * Getting Views Information * @see https://developer.couchbase.com/documentation/server/current/views/sv-query-parameters.html * Querying spatial views */ public function custom($customParameters) {} } /** * Represents a N1QL query * * @see https://developer.couchbase.com/documentation/server/current/sdk/n1ql-query.html * Querying with N1QL * @see https://developer.couchbase.com/documentation/server/current/sdk/php/n1ql-queries-with-sdk.html * N1QL from the SDKs * @see https://developer.couchbase.com/documentation/server/current/n1ql/n1ql-rest-api/index.html * N1QL REST API * @see https://developer.couchbase.com/documentation/server/current/performance/index-scans.html * Understanding Index Scans * @see https://developer.couchbase.com/documentation/server/current/performance/indexing-and-query-perf.html * Indexing JSON Documents and Query Performance */ class N1qlQuery { /** * This is the default (for single-statement requests). * No timestamp vector is used in the index scan. * This is also the fastest mode, because we avoid the cost of obtaining the vector, * and we also avoid any wait for the index to catch up to the vector. */ public const NOT_BOUNDED = 1; /** * This implements strong consistency per request. * Before processing the request, a current vector is obtained. * The vector is used as a lower bound for the statements in the request. * If there are DML statements in the request, RYOW is also applied within the request. */ public const REQUEST_PLUS = 2; /** * This implements strong consistency per statement. * Before processing each statement, a current vector is obtained * and used as a lower bound for that statement. */ public const STATEMENT_PLUS = 3; /** * Disables profiling. This is the default */ public const PROFILE_NONE = 'off'; /** * Enables phase profiling. */ public const PROFILE_PHASES = 'phases'; /** * Enables general timing profiling. */ public const PROFILE_TIMINGS = 'timings'; final private function __construct() {} /** * Creates new N1qlQuery instance directly from the N1QL string. * * @param string $statement N1QL string * @return N1qlQuery */ public static function fromString($statement) {} /** * Allows to specify if this query is adhoc or not. * * If it is not adhoc (so performed often), the client will try to perform optimizations * transparently based on the server capabilities, like preparing the statement and * then executing a query plan instead of the raw query. * * @param bool $adhoc if query is adhoc, default is true (plain execution) * @return N1qlQuery */ public function adhoc($adhoc) {} /** * Allows to pull credentials from the Authenticator * * @param bool $crossBucket if query includes joins for multiple buckets (default is false) * @return N1qlQuery * * * @see \Couchbase\Authenticator * @see \Couchbase\ClassicAuthenticator */ public function crossBucket($crossBucket) {} /** * Specify array of positional parameters * * Previously specified positional parameters will be replaced. * Note: carefully choose type of quotes for the query string, because PHP also uses `$` * (dollar sign) for variable interpolation. If you are using double quotes, make sure * that N1QL parameters properly escaped. * * @param array $params * @return N1qlQuery */ public function positionalParams($params) {} /** * Specify associative array of named parameters * * The supplied array of key/value pairs will be merged with already existing named parameters. * Note: carefully choose type of quotes for the query string, because PHP also uses `$` * (dollar sign) for variable interpolation. If you are using double quotes, make sure * that N1QL parameters properly escaped. * * @param array $params * @return N1qlQuery */ public function namedParams($params) {} /** * Specifies the consistency level for this query * * @param int $consistency consistency level * @return N1qlQuery * * @see \Couchbase\N1qlQuery::NOT_BOUNDED * @see \Couchbase\N1qlQuery::REQUEST_PLUS * @see \Couchbase\N1qlQuery::STATEMENT_PLUS * @see \Couchbase\N1qlQuery::consistentWith() */ public function consistency($consistency) {} /** * Controls the profiling mode used during query execution * * @param string $profileType * @return N1qlQuery * @see \Couchbase\N1qlQuery::PROFILE_NONE * @see \Couchbase\N1qlQuery::PROFILE_PHASES * @see \Couchbase\N1qlQuery::PROFILE_TIMINGS */ public function profile($profileType) {} /** * Sets mutation state the query should be consistent with * * @param MutationState $state the container of mutation tokens * @return N1qlQuery * * @see \Couchbase\MutationState */ public function consistentWith($state) {} /** * If set to true, it will signal the query engine on the server that only non-data modifying requests * are allowed. Note that this rule is enforced on the server and not the SDK side. * * Controls whether a query can change a resulting record set. * * If readonly is true, then the following statements are not allowed: * - CREATE INDEX * - DROP INDEX * - INSERT * - MERGE * - UPDATE * - UPSERT * - DELETE * * @param bool $readonly true if readonly should be forced, false is the default and will use the server side default. * @return N1qlQuery */ public function readonly($readonly) {} /** * Advanced: Maximum buffered channel size between the indexer client and the query service for index scans. * * This parameter controls when to use scan backfill. Use 0 or a negative number to disable. * * @param int $scanCap the scan_cap param, use 0 or negative number to disable. * @return N1qlQuery */ public function scanCap($scanCap) {} /** * Advanced: Controls the number of items execution operators can batch for Fetch from the KV. * * @param int $pipelineBatch the pipeline_batch param. * @return N1qlQuery */ public function pipelineBatch($pipelineBatch) {} /** * Advanced: Maximum number of items each execution operator can buffer between various operators. * * @param int $pipelineCap the pipeline_cap param. * @return N1qlQuery */ public function pipelineCap($pipelineCap) {} /** * Allows to override the default maximum parallelism for the query execution on the server side. * * @param int $maxParallelism the maximum parallelism for this query, 0 or negative values disable it. * @return N1qlQuery */ public function maxParallelism($maxParallelism) {} } /** * Represents N1QL index definition * * @see https://developer.couchbase.com/documentation/server/current/performance/indexing-and-query-perf.html * Indexing JSON Documents and Query Performance */ class N1qlIndex { public const UNSPECIFIED = 0; public const GSI = 1; public const VIEW = 2; final private function __construct() {} /** * Name of the index * * @var string */ public $name; /** * Is it primary index * * @var bool */ public $isPrimary; /** * Type of the index * * @var int * * @see \Couchbase\N1qlIndex::UNSPECIFIED * @see \Couchbase\N1qlIndex::GSI * @see \Couchbase\N1qlIndex::VIEW */ public $type; /** * The descriptive state of the index * * @var string */ public $state; /** * The keyspace for the index, typically the bucket name * @var string */ public $keyspace; /** * The namespace for the index. A namespace is a resource pool that contains multiple keyspaces * @var string */ public $namespace; /** * The fields covered by index * @var array */ public $fields; /** * Return the string representation of the index's condition (the WHERE clause * of the index), or an empty String if no condition was set. * * Note that the query service can present the condition in a slightly different * manner from when you declared the index: for instance it will wrap expressions * with parentheses and show the fields in an escaped format (surrounded by backticks). * * @var string */ public $condition; } /** * A builder for subdocument lookups. In order to perform the final set of operations, use the * execute() method. * * Instances of this builder should be obtained through \Couchbase\Bucket->lookupIn() * * @see \Couchbase\Bucket::lookupIn * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Sub-Document Operations */ class LookupInBuilder { final private function __construct() {} /** * Get a value inside the JSON document. * * @param string $path the path inside the document where to get the value from. * @param array $options the array with command modificators. Supported values are * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return LookupInBuilder */ public function get($path, $options = []) {} /** * Get a count of values inside the JSON document. * * This method is only available with Couchbase Server 5.0 and later. * * @param string $path the path inside the document where to get the count from. * @param array $options the array with command modificators. Supported values are * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return LookupInBuilder */ public function getCount($path, $options = []) {} /** * Check if a value exists inside the document. * * This doesn't transmit the value on the wire if it exists, saving the corresponding byte overhead. * * @param string $path the path inside the document to check for existence * @param array $options the array with command modificators. Supported values are * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return LookupInBuilder */ public function exists($path, $options = []) {} /** * Perform several lookup operations inside a single existing JSON document, using a specific timeout * @return DocumentFragment */ public function execute() {} } /** * A builder for subdocument mutations. In order to perform the final set of operations, use the * execute() method. * * Instances of this builder should be obtained through \Couchbase\Bucket->mutateIn() * * @see \Couchbase\Bucket::mutateIn * @see https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html * Sub-Document Operations */ class MutateInBuilder { public const FULLDOC_REPLACE = 0; public const FULLDOC_UPSERT = 1; public const FULLDOC_INSERT = 2; final private function __construct() {} /** * Insert a fragment provided the last element of the path doesn't exists. * * @param string $path the path where to insert a new dictionary value. * @param mixed $value the new dictionary value to insert. * @param array|bool $options the array with command modificators. * The boolean value, controls "createPath" option. Supported values are: * * "createPath" (default: false) true to create missing intermediary nodes. * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function insert($path, $value, $options = []) {} /** * Select mode for new full-document operations. * * It defines behaviour of MutateInBuilder#upsert() method. The $mode * could take one of three modes: * * FULLDOC_REPLACE: complain when document does not exist * * FULLDOC_INSERT: complain when document does exist * * FULLDOC_UPSERT: unconditionally set value for the document * * @param int $mode operation mode */ public function modeDocument($mode) {} /** * Insert a fragment, replacing the old value if the path exists. * * When only one argument supplied, the library will handle it as full-document * upsert, and treat this argument as value. See MutateInBuilder#modeDocument() * * @param string $path the path where to insert (or replace) a dictionary value * @param mixed $value the new dictionary value to be applied. * @param array|bool $options the array with command modificators. * The boolean value, controls "createPath" option. Supported values are: * * "createPath" (default: false) true to create missing intermediary nodes. * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function upsert($path, $value, $options = []) {} /** * Replace an existing value by the given fragment * * @param string $path the path where the value to replace is * @param mixed $value the new value * @param array $options the array with command modificators. Supported values are: * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function replace($path, $value, $options = []) {} /** * Remove an entry in a JSON document. * * Scalar, array element, dictionary entry, whole array or dictionary, depending on the path. * * @param string $path the path to remove * @param array $options the array with command modificators. Supported values are: * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function remove($path, $options = []) {} /** * Prepend to an existing array, pushing the value to the front/first position in the array. * * @param string $path the path of the array * @param mixed $value the value to insert at the front of the array * @param array|bool $options the array with command modificators. * The boolean value, controls "createPath" option. Supported values are: * * "createPath" (default: false) true to create missing intermediary nodes. * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function arrayPrepend($path, $value, $options = []) {} /** * Prepend multiple values at once in an existing array. * * Push all values in the collection's iteration order to the front/start of the array. * For example given an array [A, B, C], prepending the values X and Y yields [X, Y, A, B, C] * and not [[X, Y], A, B, C]. * * @param string $path the path of the array * @param array $values the values to insert at the front of the array as individual elements * @param array|bool $options the array with command modificators. * The boolean value, controls "createPath" option. Supported values are: * * "createPath" (default: false) true to create missing intermediary nodes. * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function arrayPrependAll($path, $values, $options = []) {} /** * Append to an existing array, pushing the value to the back/last position in the array. * * @param string $path the path of the array * @param mixed $value the value to insert at the back of the array * @param array|bool $options the array with command modificators. * The boolean value, controls "createPath" option. Supported values are: * * "createPath" (default: false) true to create missing intermediary nodes. * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function arrayAppend($path, $value, $options = []) {} /** * Append multiple values at once in an existing array. * * Push all values in the collection's iteration order to the back/end of the array. * For example given an array [A, B, C], appending the values X and Y yields [A, B, C, X, Y] * and not [A, B, C, [X, Y]]. * * @param string $path the path of the array * @param array $values the values to individually insert at the back of the array * @param array|bool $options the array with command modificators. * The boolean value, controls "createPath" option. Supported values are: * * "createPath" (default: false) true to create missing intermediary nodes. * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function arrayAppendAll($path, $values, $options = []) {} /** * Insert into an existing array at a specific position * * Position denoted in the path, eg. "sub.array[2]". * * @param string $path the path (including array position) where to insert the value * @param mixed $value the value to insert in the array * @param array $options the array with command modificators. Supported values are: * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function arrayInsert($path, $value, $options = []) {} /** * Insert multiple values at once in an existing array at a specified position. * * Position denoted in the path, eg. "sub.array[2]"), inserting all values in the collection's iteration order * at the given position and shifting existing values beyond the position by the number of elements in the * collection. * * For example given an array [A, B, C], inserting the values X and Y at position 1 yields [A, B, X, Y, C] * and not [A, B, [X, Y], C]. * @param string $path the path of the array * @param array $values the values to insert at the specified position of the array, each value becoming * an entry at or after the insert position. * @param array $options the array with command modificators. Supported values are: * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function arrayInsertAll($path, $values, $options = []) {} /** * Insert a value in an existing array only if the value * isn't already contained in the array (by way of string comparison). * * @param string $path the path to mutate in the JSON * @param mixed $value the value to insert * @param array|bool $options the array with command modificators. * The boolean value, controls "createPath" option. Supported values are: * * "createPath" (default: false) true to create missing intermediary nodes. * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function arrayAddUnique($path, $value, $options = []) {} /** * Increment/decrement a numerical fragment in a JSON document. * * If the value (last element of the path) doesn't exist the counter * is created and takes the value of the delta. * * @param string $path the path to the counter (must be containing a number). * @param int $delta the value to increment or decrement the counter by * @param array|bool $options the array with command modificators. * The boolean value, controls "createPath" option. Supported values are: * * "createPath" (default: false) true to create missing intermediary nodes. * * "xattr" (default: false) if true, the path refers to a location * within the document's extended attributes, not the document body. * @return MutateInBuilder */ public function counter($path, $delta, $options = []) {} /** * Change the expiry of the enclosing document as part of the mutation. * * @param mixed $expiry the new expiry to apply (or 0 to avoid changing the expiry) * @return MutateInBuilder */ public function withExpiry($expiry) {} /** * Perform several mutation operations inside a single existing JSON document. * @return DocumentFragment */ public function execute() {} } /** * Represents full text search query * * @see https://developer.couchbase.com/documentation/server/4.6/sdk/php/full-text-searching-with-sdk.html * Searching from the SDK */ class SearchQuery implements \JsonSerializable { public const HIGHLIGHT_HTML = 'html'; public const HIGHLIGHT_ANSI = 'ansi'; public const HIGHLIGHT_SIMPLE = 'simple'; /** * Prepare boolean search query * * @return BooleanSearchQuery */ public static function boolean() {} /** * Prepare date range search query * * @return DateRangeSearchQuery */ public static function dateRange() {} /** * Prepare numeric range search query * * @return NumericRangeSearchQuery */ public static function numericRange() {} /** * Prepare term range search query * * @return TermRangeSearchQuery */ public static function termRange() {} /** * Prepare boolean field search query * * @param bool $value * @return BooleanFieldSearchQuery */ public static function booleanField($value) {} /** * Prepare compound conjunction search query * * @param SearchQueryPart ...$queries list of inner query parts * @return ConjunctionSearchQuery */ public static function conjuncts(...$queries) {} /** * Prepare compound disjunction search query * * @param SearchQueryPart ...$queries list of inner query parts * @return DisjunctionSearchQuery */ public static function disjuncts(...$queries) {} /** * Prepare document ID search query * * @param string ...$documentIds * @return DocIdSearchQuery */ public static function docId(...$documentIds) {} /** * Prepare match search query * * @param string $match * @return MatchSearchQuery */ public static function match($match) {} /** * Prepare match all search query * * @return MatchAllSearchQuery */ public static function matchAll() {} /** * Prepare match non search query * * @return MatchNoneSearchQuery */ public static function matchNone() {} /** * Prepare phrase search query * * @param string ...$terms * @return MatchPhraseSearchQuery */ public static function matchPhrase(...$terms) {} /** * Prepare prefix search query * * @param string $prefix * @return PrefixSearchQuery */ public static function prefix($prefix) {} /** * Prepare query string search query * * @param string $queryString * @return QueryStringSearchQuery */ public static function queryString($queryString) {} /** * Prepare regexp search query * * @param string $regexp * @return RegexpSearchQuery */ public static function regexp($regexp) {} /** * Prepare term search query * * @param string $term * @return TermSearchQuery */ public static function term($term) {} /** * Prepare wildcard search query * * @param string $wildcard * @return WildcardSearchQuery */ public static function wildcard($wildcard) {} /** * Prepare geo distance search query * * @param float $longitude * @param float $latitude * @param string $distance e.g. "10mi" * @return GeoDistanceSearchQuery */ public static function geoDistance($longitude, $latitude, $distance) {} /** * Prepare geo bounding box search query * * @param float $topLeftLongitude * @param float $topLeftLatitude * @param float $bottomRightLongitude * @param float $bottomRightLatitude * @return GeoBoundingBoxSearchQuery */ public static function geoBoundingBox($topLeftLongitude, $topLeftLatitude, $bottomRightLongitude, $bottomRightLatitude) {} /** * Prepare term search facet * * @param string $field * @param int $limit * @return TermSearchFacet */ public static function termFacet($field, $limit) {} /** * Prepare date range search facet * * @param string $field * @param int $limit * @return DateRangeSearchFacet */ public static function dateRangeFacet($field, $limit) {} /** * Prepare numeric range search facet * * @param string $field * @param int $limit * @return NumericRangeSearchFacet */ public static function numericRangeFacet($field, $limit) {} /** * Prepare an FTS SearchQuery on an index. * * Top level query parameters can be set after that by using the fluent API. * * @param string $indexName the FTS index to search in * @param SearchQueryPart $queryPart the body of the FTS query (e.g. a match phrase query) */ public function __construct($indexName, $queryPart) {} /** * @return array */ public function jsonSerialize() {} /** * Add a limit to the query on the number of hits it can return * * @param int $limit the maximum number of hits to return * @return SearchQuery */ public function limit($limit) {} /** * Set the number of hits to skip (eg. for pagination). * * @param int $skip the number of results to skip * @return SearchQuery */ public function skip($skip) {} /** * Activates the explanation of each result hit in the response * * @param bool $explain * @return SearchQuery */ public function explain($explain) {} /** * Sets the server side timeout in milliseconds * * @param int $serverSideTimeout the server side timeout to apply * @return SearchQuery */ public function serverSideTimeout($serverSideTimeout) {} /** * Sets the consistency to consider for this FTS query to AT_PLUS and * uses the MutationState to parameterize the consistency. * * This replaces any consistency tuning previously set. * * @param MutationState $state the mutation state information to work with * @return SearchQuery */ public function consistentWith($state) {} /** * Configures the list of fields for which the whole value should be included in the response. * * If empty, no field values are included. This drives the inclusion of the fields in each hit. * Note that to be highlighted, the fields must be stored in the FTS index. * * @param string ...$fields * @return SearchQuery */ public function fields(...$fields) {} /** * Configures the highlighting of matches in the response * * @param string $style highlight style to apply. Use constants HIGHLIGHT_HTML, * HIGHLIGHT_ANSI, HIGHLIGHT_SIMPLE. * @param string ...$fields the optional fields on which to highlight. * If none, all fields where there is a match are highlighted. * @return SearchQuery * * @see \Couchbase\SearchQuery::HIGHLIGHT_HTML * @see \Couchbase\SearchQuery::HIGHLIGHT_ANSI * @see \Couchbase\SearchQuery::HIGHLIGHT_SIMPLE */ public function highlight($style, ...$fields) {} /** * Configures the list of fields (including special fields) which are used for sorting purposes. * If empty, the default sorting (descending by score) is used by the server. * * The list of sort fields can include actual fields (like "firstname" but then they must be stored in the * index, configured in the server side mapping). Fields provided first are considered first and in a "tie" case * the next sort field is considered. So sorting by "firstname" and then "lastname" will first sort ascending by * the firstname and if the names are equal then sort ascending by lastname. Special fields like "_id" and * "_score" can also be used. If prefixed with "-" the sort order is set to descending. * * If no sort is provided, it is equal to sort("-_score"), since the server will sort it by score in descending * order. * * @param mixed $sort the fields that should take part in the sorting. * @return SearchQuery */ public function sort(...$sort) {} /** * Adds one SearchFacet to the query * * This is an additive operation (the given facets are added to any facet previously requested), * but if an existing facet has the same name it will be replaced. * * Note that to be faceted, a field's value must be stored in the FTS index. * * @param string $name * @param SearchFacet $facet * @return SearchQuery * * @see \Couchbase\SearchFacet * @see \Couchbase\TermSearchFacet * @see \Couchbase\NumericRangeSearchFacet * @see \Couchbase\DateRangeSearchFacet */ public function addFacet($name, $facet) {} } /** * Common interface for all classes, which could be used as a body of SearchQuery * * @see \Couchbase\SearchQuery::__construct() */ interface SearchQueryPart {} /** * A FTS query that queries fields explicitly indexed as boolean. */ class BooleanFieldSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return BooleanFieldSearchQuery */ public function boost($boost) {} /** * @param string $field * @return BooleanFieldSearchQuery */ public function field($field) {} } /** * A compound FTS query that allows various combinations of sub-queries. */ class BooleanSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return BooleanSearchQuery */ public function boost($boost) {} /** * @param SearchQueryPart ...$queries * @return BooleanSearchQuery */ public function must(...$queries) {} /** * @param SearchQueryPart ...$queries * @return BooleanSearchQuery */ public function mustNot(...$queries) {} /** * @param SearchQueryPart ...$queries * @return BooleanSearchQuery */ public function should(...$queries) {} } /** * A compound FTS query that performs a logical AND between all its sub-queries (conjunction). */ class ConjunctionSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return ConjunctionSearchQuery */ public function boost($boost) {} /** * @param SearchQueryPart ...$queries * @return ConjunctionSearchQuery */ public function every(...$queries) {} } /** * A compound FTS query that performs a logical OR between all its sub-queries (disjunction). It requires that a * minimum of the queries match. The minimum is configurable (default 1). */ class DisjunctionSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return DisjunctionSearchQuery */ public function boost($boost) {} /** * @param SearchQueryPart ...$queries * @return DisjunctionSearchQuery */ public function either(...$queries) {} /** * @param int $min * @return DisjunctionSearchQuery */ public function min($min) {} } /** * A FTS query that matches documents on a range of values. At least one bound is required, and the * inclusiveness of each bound can be configured. */ class DateRangeSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return DateRangeSearchQuery */ public function boost($boost) {} /** * @param string $field * @return DateRangeSearchQuery */ public function field($field) {} /** * @param int|string $start The strings will be taken verbatim and supposed to be formatted with custom date * time formatter (see dateTimeParser). Integers interpreted as unix timestamps and represented as RFC3339 * strings. * @param bool $inclusive * @return DateRangeSearchQuery */ public function start($start, $inclusive = true) {} /** * @param int|string $end The strings will be taken verbatim and supposed to be formatted with custom date * time formatter (see dateTimeParser). Integers interpreted as unix timestamps and represented as RFC3339 * strings. * @param bool $inclusive * @return DateRangeSearchQuery */ public function end($end, $inclusive = false) {} /** * @param string $dateTimeParser * @return DateRangeSearchQuery */ public function dateTimeParser($dateTimeParser) {} } /** * A FTS query that matches documents on a range of values. At least one bound is required, and the * inclusiveness of each bound can be configured. */ class NumericRangeSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return NumericRangeSearchQuery */ public function boost($boost) {} /** * @param string $field * @return NumericRangeSearchQuery */ public function field($field) {} /** * @param float $min * @param bool $inclusive * @return NumericRangeSearchQuery */ public function min($min, $inclusive = true) {} /** * @param float $max * @param bool $inclusive * @return NumericRangeSearchQuery */ public function max($max, $inclusive = false) {} } /** * A FTS query that matches on Couchbase document IDs. Useful to restrict the search space to a list of keys (by using * this in a compound query). */ class DocIdSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return DocIdSearchQuery */ public function boost($boost) {} /** * @param string $field * @return DocIdSearchQuery */ public function field($field) {} /** * @param string ...$documentIds * @return DocIdSearchQuery */ public function docIds(...$documentIds) {} } /** * A FTS query that matches all indexed documents (usually for debugging purposes). */ class MatchAllSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return MatchAllSearchQuery */ public function boost($boost) {} } /** * A FTS query that matches 0 document (usually for debugging purposes). */ class MatchNoneSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return MatchNoneSearchQuery */ public function boost($boost) {} } /** * A FTS query that matches several given terms (a "phrase"), applying further processing * like analyzers to them. */ class MatchPhraseSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return MatchPhraseSearchQuery */ public function boost($boost) {} /** * @param string $field * @return MatchPhraseSearchQuery */ public function field($field) {} /** * @param string $analyzer * @return MatchPhraseSearchQuery */ public function analyzer($analyzer) {} } /** * A FTS query that matches a given term, applying further processing to it * like analyzers, stemming and even #fuzziness(int). */ class MatchSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return MatchSearchQuery */ public function boost($boost) {} /** * @param string $field * @return MatchSearchQuery */ public function field($field) {} /** * @param string $analyzer * @return MatchSearchQuery */ public function analyzer($analyzer) {} /** * @param int $prefixLength * @return MatchSearchQuery */ public function prefixLength($prefixLength) {} /** * @param int $fuzziness * @return MatchSearchQuery */ public function fuzziness($fuzziness) {} } /** * A FTS query that matches several terms (a "phrase") as is. The order of the terms mater and no further processing is * applied to them, so they must appear in the index exactly as provided. Usually for debugging purposes, prefer * MatchPhraseQuery. */ class PhraseSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return PhraseSearchQuery */ public function boost($boost) {} /** * @param string $field * @return PhraseSearchQuery */ public function field($field) {} } /** * A FTS query that allows for simple matching of regular expressions. */ class RegexpSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return RegexpSearchQuery */ public function boost($boost) {} /** * @param string $field * @return RegexpSearchQuery */ public function field($field) {} } /** * A FTS query that allows for simple matching using wildcard characters (* and ?). */ class WildcardSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return WildcardSearchQuery */ public function boost($boost) {} /** * @param string $field * @return WildcardSearchQuery */ public function field($field) {} } /** * A FTS query that allows for simple matching on a given prefix. */ class PrefixSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return PrefixSearchQuery */ public function boost($boost) {} /** * @param string $field * @return PrefixSearchQuery */ public function field($field) {} } /** * A FTS query that performs a search according to the "string query" syntax. */ class QueryStringSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return QueryStringSearchQuery */ public function boost($boost) {} } /** * A facet that gives the number of occurrences of the most recurring terms in all hits. */ class TermSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return TermSearchQuery */ public function boost($boost) {} /** * @param string $field * @return TermSearchQuery */ public function field($field) {} /** * @param int $prefixLength * @return TermSearchQuery */ public function prefixLength($prefixLength) {} /** * @param int $fuzziness * @return TermSearchQuery */ public function fuzziness($fuzziness) {} } /** * A FTS query that matches documents on a range of values. At least one bound is required, and the * inclusiveness of each bound can be configured. */ class TermRangeSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return TermRangeSearchQuery */ public function boost($boost) {} /** * @param string $field * @return TermRangeSearchQuery */ public function field($field) {} /** * @param string $min * @param bool $inclusive * @return TermRangeSearchQuery */ public function min($min, $inclusive = true) {} /** * @param string $max * @param bool $inclusive * @return TermRangeSearchQuery */ public function max($max, $inclusive = false) {} } /** * A FTS query that finds all matches from a given location (point) within the given distance. * * Both the point and the distance are required. */ class GeoDistanceSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return GeoDistanceSearchQuery */ public function boost($boost) {} /** * @param string $field * @return GeoDistanceSearchQuery */ public function field($field) {} } /** * A FTS query which allows to match geo bounding boxes. */ class GeoBoundingBoxSearchQuery implements \JsonSerializable, SearchQueryPart { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param float $boost * @return GeoBoundingBoxSearchQuery */ public function boost($boost) {} /** * @param string $field * @return GeoBoundingBoxSearchQuery */ public function field($field) {} } /** * Common interface for all search facets * * @see \Couchbase\SearchQuery::addFacet() * @see \Couchbase\TermSearchFacet * @see \Couchbase\DateRangeSearchFacet * @see \Couchbase\NumericRangeSearchFacet */ interface SearchFacet {} /** * A facet that gives the number of occurrences of the most recurring terms in all hits. */ class TermSearchFacet implements \JsonSerializable, SearchFacet { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} } /** * A facet that categorizes hits inside date ranges (or buckets) provided by the user. */ class DateRangeSearchFacet implements \JsonSerializable, SearchFacet { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param string $name * @param int|string $start * @param int|string $end * @return DateSearchFacet */ public function addRange($name, $start, $end) {} } /** * A facet that categorizes hits into numerical ranges (or buckets) provided by the user. */ class NumericRangeSearchFacet implements \JsonSerializable, SearchFacet { final private function __construct() {} /** * @return array */ public function jsonSerialize() {} /** * @param string $name * @param float $min * @param float $max * @return NumericSearchFacet */ public function addRange($name, $min, $max) {} } /** * Base class for all FTS sort options in querying. */ class SearchSort { private function __construct() {} /** * Sort by the document identifier. * * @return SearchSortId */ public static function id() {} /** * Sort by the hit score. * * @return SearchSortScore */ public static function score() {} /** * Sort by a field in the hits. * * @param string $field the field name * * @return SearchSortField */ public static function field($field) {} /** * Sort by geo location. * * @param string $field the field name * @param float $longitude the longitude of the location * @param float $latitude the latitude of the location * * @return SearchSortGeoDistance */ public static function geoDistance($field, $longitude, $latitude) {} } /** * Sort by the document identifier. */ class SearchSortId extends SearchSort implements \JsonSerializable { private function __construct() {} /** * Direction of the sort * * @param bool $descending * * @return SearchSortId */ public function descending($descending) {} } /** * Sort by the hit score. */ class SearchSortScore extends SearchSort implements \JsonSerializable { private function __construct() {} /** * Direction of the sort * * @param bool $descending * * @return SearchSortScore */ public function descending($descending) {} } /** * Sort by a field in the hits. */ class SearchSortField extends SearchSort implements \JsonSerializable { public const TYPE_AUTO = "auto"; public const TYPE_STRING = "string"; public const TYPE_NUMBER = "number"; public const TYPE_DATE = "date"; public const MODE_DEFAULT = "default"; public const MODE_MIN = "min"; public const MODE_MAX = "max"; public const MISSING_FIRST = "first"; public const MISSING_LAST = "last"; private function __construct() {} /** * Direction of the sort * * @param bool $descending * * @return SearchSortField */ public function descending($descending) {} /** * Set type of the field * * @param string $type the type * * @see SearchSortField::TYPE_AUTO * @see SearchSortField::TYPE_STRING * @see SearchSortField::TYPE_NUMBER * @see SearchSortField::TYPE_DATE */ public function type($type) {} /** * Set mode of the sort * * @param string $mode the mode * * @see SearchSortField::MODE_MIN * @see SearchSortField::MODE_MAX */ public function mode($mode) {} /** * Set where the hits with missing field will be inserted * * @param string $missing strategy for hits with missing fields * * @see SearchSortField::MISSING_FIRST * @see SearchSortField::MISSING_LAST */ public function missing($missing) {} } /** * Sort by a location and unit in the hits. */ class SearchSortGeoDistance extends SearchSort implements \JsonSerializable { private function __construct() {} /** * Direction of the sort * * @param bool $descending * * @return SearchSortGeoDistance */ public function descending($descending) {} /** * Name of the units * * @param string $unit * * @return SearchSortGeoDistance */ public function unit($unit) {} } /** * Represents a Analytics query (currently experimental support). * * @see https://developer.couchbase.com/documentation/server/4.5/analytics/quick-start.html * Analytics quick start */ class AnalyticsQuery { final private function __construct() {} /** * Creates new AnalyticsQuery instance directly from the string. * * @param string $statement statement string * @return AnalyticsQuery */ public static function fromString($statement) {} } * Cookie name. *

    * @param string $value

    * Cookie value. *

    * @return string|false the encrypted string or false on failure. */ function suhosin_encrypt_cookie($name, $value) {} /** * Returns an array containing the raw cookie values * @link https://php.net/manual/en/function.suhosin-get-raw-cookies.php * @return array an array containing the raw cookie values. */ function suhosin_get_raw_cookies() {} = 1.0.1 are `tlsv1.2`, `tlsv1.1` and `tlsv1`. * @param string|null $ciphers A string describing the ciphers available for use. See the `openssl ciphers` tool for more information. If `null`, the default set will be used. * @return int */ public function setTlsOptions($certReqs, $tlsVersion = null, $ciphers = null) {} /** * Configure the client for pre-shared-key based TLS support. Must be called before `connect`. Cannot be used in * conjunction with setTlsCertificates. * * @param string $psk The pre-shared key in hex format with no leading "0x". * @param string $identity The identity of this client. May be used as the username depending on server settings. * @param string|null $ciphers Optional. A string describing the ciphers available for use. See the `openssl ciphers` tool for more information. If `null`, the default set will be used. * @return int */ public function setTlsPSK($psk, $identity, $ciphers = null) {} /** * Set the client “last will and testament”, which will be sent on an unclean disconnection from the broker. * Must be called before `connect`. * * @param string $topic The topic on which to publish the will. * @param string $payload The data to send. * @param int $qos Optional. Default 0. Integer 0, 1, or 2 indicating the Quality of Service to be used. * @param bool $retain Optional. Default false. If true, the message will be retained. */ public function setWill($topic, $payload, $qos = 0, $retain = false) {} /** * Remove a previously-set will. No parameters. */ public function clearWill() {} /** * Control the behaviour of the client when it has unexpectedly disconnected in Client::loopForever(). * The default behaviour if this method is not used is to repeatedly attempt to reconnect with a delay of 1 second * until the connection succeeds. * * @param int $reconnectDelay Set delay between successive reconnection attempts. * @param int $exponentialDelay Set max delay between successive reconnection attempts when exponential backoff is enabled * @param bool $exponentialBackoff Pass `true` to enable exponential backoff */ public function setReconnectDelay($reconnectDelay, $exponentialDelay = 0, $exponentialBackoff = false) {} /** * Connect to an MQTT broker. * * @param string $host Hostname to connect to * @param int $port Optional. Port number to connect to. Defaults to 1883. * @param int $keepalive Optional. Number of sections after which the broker should PING the client if no messages have been received. * @param string|null $interface Optional. The address or hostname of a local interface to bind to for this connection. * @return int */ public function connect($host, $port = 1883, $keepalive = 60, $interface = null) {} /** * Disconnect from the broker. No parameters. */ public function disconnect() {} /** * Set the connect callback. This is called when the broker sends a CONNACK message in response to a connection. * * (int) $rc, (string) $message * function ($rc, $message) {} * * Response codes: * 0 = Success * 1 = Connection refused (unacceptable protocol version) * 2 = Connection refused (identifier rejected) * 3 = Connection refused (broker unavailable) * 4-255 = Reserved for future use * * @param callable $callback */ public function onConnect($callback) {} /** * Set the disconnect callback. This is called when the broker has received the DISCONNECT command and has * disconnected the client. * * (int) $rc * function ($rc) {} * * Response codes: * 0 = requested by client * <0 = indicates an unexpected disconnection. * * @param callable $callback */ public function onDisconnect($callback) {} /** * Set the logging callback. * * (int) $level, (string) $str * function ($level, $str) {} * * Log levels: * Client::LOG_DEBUG * Client::LOG_INFO * Client::LOG_NOTICE * Client::LOG_WARNING * Client::LOG_ERR * * @param callable $callback */ public function onLog($callback) {} /** * Set the subscribe callback. This is called when the broker responds to a subscription request. * * (int) $mid, (int) $qosCount * function ($mid, $qosCount) {} * * @param callable $callback */ public function onSubscribe($callback) {} /** * Set the unsubscribe callback. This is called when the broker responds to a unsubscribe request. * * (int) $mid * function ($mid) {} * * @param callable $callback */ public function onUnsubscribe($callback) {} /** * Set the message callback. This is called when a message is received from the broker. * * (object) $message * function (Mosquitto\Message $message) {} * * @param callable $callback */ public function onMessage($callback) {} /** * Set the publish callback. This is called when a message is published by the client itself. * * Warning: this may be called before the method publish returns the message id, so, you need to create a queue to * deal with the MID list. * * (int) $mid - the message id returned by `publish` * function ($mid) {} * * @param callable $callback */ public function onPublish($callback) {} /** * Set the number of QoS 1 and 2 messages that can be “in flight” at one time. An in flight message is part way * through its delivery flow. Attempts to send further messages with publish will result in the messages * being queued until the number of in flight messages reduces. * * Set to 0 for no maximum. * * @param int $maxInFlightMessages */ public function setMaxInFlightMessages($maxInFlightMessages) {} /** * Set the number of seconds to wait before retrying messages. This applies to publishing messages with QoS > 0. * May be called at any time. * * @param int $messageRetryPeriod The retry period */ public function setMessageRetry($messageRetryPeriod) {} /** * Publish a message on a given topic. * Return the message ID returned by the broker. Warning: the message ID is not unique. * * @param string $topic The topic to publish on * @param string $payload The message payload * @param int $qos Integer value 0, 1 or 2 indicating the QoS for this message * @param bool $retain If true, retain this message * @return int */ public function publish($topic, $payload, $qos = 0, $retain = false) {} /** * Subscribe to a topic. * Return the message ID of the subscription message, so this can be matched up in the `onSubscribe` callback. * * @param string $topic * @param int $qos * @return int */ public function subscribe($topic, $qos) {} /** * Unsubscribe from a topic. * Return the message ID of the subscription message, so this can be matched up in the `onUnsubscribe` callback. * * @param string $topic * @param int $qos * @return int */ public function unsubscribe($topic, $qos) {} /** * The main network loop for the client. You must call this frequently in order to keep communications between * the client and broker working. If incoming data is present it will then be processed. Outgoing commands, * from e.g. `publish`, are normally sent immediately that their function is called, but this is not always possible. * `loop` will also attempt to send any remaining outgoing messages, which also includes commands that are part * of the flow for messages with QoS > 0. * * @param int $timeout Optional. Number of milliseconds to wait for network activity. Pass 0 for instant timeout. */ public function loop($timeout = 1000) {} /** * Call loop() in an infinite blocking loop. Callbacks will be called as required. This will handle reconnecting * if the connection is lost. Call `disconnect` in a callback to disconnect and return from the loop. Alternatively, * call `exitLoop` to exit the loop without disconnecting. You will need to re-enter the loop again afterwards * to maintain the connection. * * @param int $timeout Optional. Number of milliseconds to wait for network activity. Pass 0 for instant timeout. */ public function loopForever($timeout = 1000) {} /** * Exit the `loopForever` event loop without disconnecting. You will need to re-enter the loop afterwards * in order to maintain the connection. */ public function exitLoop() {} } /** * @link https://mosquitto-php.readthedocs.io/en/latest/message.html */ class Message { /** @var string */ public $topic; /** @var string */ public $payload; /** @var int */ public $mid; /** @var int */ public $qos; /** @var bool */ public $retain; /** * Returns true if the supplied topic matches the supplied description, and otherwise false. * * @param string $topic The topic to match * @param string $subscription The subscription to match * @return bool */ public static function topicMatchesSub($topic, $subscription) {} /** * Tokenise a topic or subscription string into an array of strings representing the topic hierarchy. * * @param string $topic * @return array */ public static function tokeniseTopic($topic) {} } /** * @link https://mosquitto-php.readthedocs.io/en/latest/exception.html */ class Exception extends \Exception {} * Start xhprof profiler. * * @link https://php.net/manual/en/function.xhprof-enable.php * * @param int $flags

    Optional flags to add additional information to the profiling. See the a * href="https://secure.php.net/manual/en/xhprof.constants.php">XHprof constants for further * information about these flags, e.g., XHPROF_FLAGS_MEMORY to enable memory * profiling.

    * @param array $options [optional]

    An array of optional options, namely, the 'ignored_functions' option to pass in functions * to be ignored during profiling.

    * * @return null */ function xhprof_enable($flags = 0, array $options = []) {} /** * (PHP >= 5.2.0, PECL xhprof >= 0.9.0)
    * Stops the profiler, and returns xhprof data from the run. * * @link https://php.net/manual/en/function.xhprof-disable.php * @return array an array of xhprof data, from the run. */ function xhprof_disable() {} /** * (PHP >= 5.2.0, PECL xhprof >= 0.9.0)
    * Starts profiling in sample mode, which is a lighter weight version of {@see xhprof_enable()}. The sampling interval * is 0.1 seconds, and samples record the full function call stack. The main use case is when lower overhead is * required when doing performance monitoring and diagnostics. * * @link https://php.net/manual/en/function.xhprof-sample-enable.php * @return null */ function xhprof_sample_enable() {} /** * (PHP >= 5.2.0, PECL xhprof >= 0.9.0)
    * Stops the sample mode xhprof profiler, and returns xhprof data from the run. * * @link https://php.net/manual/en/function.xhprof-sample-disable.php * @return array an array of xhprof sample data, from the run. */ function xhprof_sample_disable() {} /** * @link https://php.net/manual/en/xhprof.constants.php#constant.xhprof-flags-no-builtins */ const XHPROF_FLAGS_NO_BUILTINS = 1; /** * @link https://php.net/manual/en/xhprof.constants.php#constant.xhprof-flags-cpu */ const XHPROF_FLAGS_CPU = 2; /** * @link https://php.net/manual/en/xhprof.constants.php##constant.xhprof-flags-memory */ const XHPROF_FLAGS_MEMORY = 4; // End of xhprof v.0.9.4 'FTP\Connection'], default: 'resource')] $ftp, string $remote_filename, string $local_filename, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $mode, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '7.3')] int $mode = FTP_BINARY ): bool {} /** * returns a list of files in the given directory * @param resource $ftp * @param string $directory * @return array|false * @since 7.2 */ function ftp_mlsd(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $directory): array|false {} /** * Opens an FTP connection * @link https://php.net/manual/en/function.ftp-connect.php * @param string $hostname

    * The FTP server address. This parameter shouldn't have any trailing * slashes and shouldn't be prefixed with ftp://. *

    * @param int $port [optional]

    * This parameter specifies an alternate port to connect to. If it is * omitted or set to zero, then the default FTP port, 21, will be used. *

    * @param int $timeout [optional]

    * This parameter specifies the timeout for all subsequent network operations. * If omitted, the default value is 90 seconds. The timeout can be changed and * queried at any time with ftp_set_option and * ftp_get_option. *

    * @return resource|false a FTP stream on success or FALSE on error. */ #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection|false'], default: 'resource|false')] function ftp_connect(string $hostname, int $port = 21, int $timeout = 90) {} /** * Opens a Secure SSL-FTP connection * @link https://php.net/manual/en/function.ftp-ssl-connect.php * @param string $hostname

    * The FTP server address. This parameter shouldn't have any trailing * slashes and shouldn't be prefixed with ftp://. *

    * @param int $port [optional]

    * This parameter specifies an alternate port to connect to. If it is * omitted or set to zero, then the default FTP port, 21, will be used. *

    * @param int $timeout [optional]

    * This parameter specifies the timeout for all subsequent network operations. * If omitted, the default value is 90 seconds. The timeout can be changed and * queried at any time with ftp_set_option and * ftp_get_option. *

    * @return resource|false a SSL-FTP stream on success or FALSE on error. */ #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection|false'], default: 'resource|false')] function ftp_ssl_connect(string $hostname, int $port = 21, int $timeout = 90) {} /** * Logs in to an FTP connection * @link https://php.net/manual/en/function.ftp-login.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $username

    * The username (USER). *

    * @param string $password

    * The password (PASS). *

    * @return bool TRUE on success or FALSE on failure. * If login fails, PHP will also throw a warning. */ function ftp_login(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $username, string $password): bool {} /** * Returns the current directory name * @link https://php.net/manual/en/function.ftp-pwd.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @return string|false the current directory name or FALSE on error. */ function ftp_pwd(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp): string|false {} /** * Changes to the parent directory * @link https://php.net/manual/en/function.ftp-cdup.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_cdup(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp): bool {} /** * Changes the current directory on a FTP server * @link https://php.net/manual/en/function.ftp-chdir.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $directory

    * The target directory. *

    * @return bool TRUE on success or FALSE on failure. * If changing directory fails, PHP will also throw a warning. */ function ftp_chdir(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $directory): bool {} /** * Requests execution of a command on the FTP server * @link https://php.net/manual/en/function.ftp-exec.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $command

    * The command to execute. *

    * @return bool TRUE if the command was successful (server sent response code: * 200); otherwise returns FALSE. */ function ftp_exec(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $command): bool {} /** * Sends an arbitrary command to an FTP server * @link https://php.net/manual/en/function.ftp-raw.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $command

    * The command to execute. *

    * @return string[] the server's response as an array of strings. * No parsing is performed on the response string, nor does * ftp_raw determine if the command succeeded. */ #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: 'array')] function ftp_raw(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $command) {} /** * Creates a directory * @link https://php.net/manual/en/function.ftp-mkdir.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $directory

    * The name of the directory that will be created. *

    * @return string|false the newly created directory name on success or FALSE on error. */ function ftp_mkdir(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $directory): string|false {} /** * Removes a directory * @link https://php.net/manual/en/function.ftp-rmdir.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $directory

    * The directory to delete. This must be either an absolute or relative * path to an empty directory. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_rmdir(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $directory): bool {} /** * Set permissions on a file via FTP * @link https://php.net/manual/en/function.ftp-chmod.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param int $permissions

    * The new permissions, given as an octal value. *

    * @param string $filename

    * The remote file. *

    * @return int|false the new file permissions on success or FALSE on error. */ function ftp_chmod(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, int $permissions, string $filename): int|false {} /** * Allocates space for a file to be uploaded * @link https://php.net/manual/en/function.ftp-alloc.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param int $size

    * The number of bytes to allocate. *

    * @param string &$response [optional]

    * A textual representation of the servers response will be returned by * reference in result if a variable is provided. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_alloc(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, int $size, &$response): bool {} /** * Returns a list of files in the given directory * @link https://php.net/manual/en/function.ftp-nlist.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $directory

    * The directory to be listed. This parameter can also include arguments, eg. * ftp_nlist($conn_id, "-la /your/dir"); * Note that this parameter isn't escaped so there may be some issues with * filenames containing spaces and other characters. *

    * @return string[]|false an array of filenames from the specified directory on success or * FALSE on error. */ function ftp_nlist(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $directory): array|false {} /** * Returns a detailed list of files in the given directory * @link https://php.net/manual/en/function.ftp-rawlist.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $directory

    * The directory path. May include arguments for the LIST * command. *

    * @param bool $recursive [optional]

    * If set to TRUE, the issued command will be LIST -R. *

    * @return string[]|false an array where each element corresponds to one line of text. *

    * The output is not parsed in any way. The system type identifier returned by * ftp_systype can be used to determine how the results * should be interpreted. *

    */ function ftp_rawlist(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $directory, bool $recursive = false): array|false {} /** * Returns the system type identifier of the remote FTP server * @link https://php.net/manual/en/function.ftp-systype.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @return string|false the remote system type, or FALSE on error. */ function ftp_systype(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp): string|false {} /** * Turns passive mode on or off * @link https://php.net/manual/en/function.ftp-pasv.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param bool $enable

    * If TRUE, the passive mode is turned on, else it's turned off. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_pasv(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, bool $enable): bool {} /** * Downloads a file from the FTP server * @link https://php.net/manual/en/function.ftp-get.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $local_filename

    * The local file path (will be overwritten if the file already exists). *

    * @param string $remote_filename

    * The remote file path. *

    * @param int $mode

    * The transfer mode. Must be either FTP_ASCII or FTP_BINARY. Optional since PHP 7.3 *

    * @param int $offset [optional]

    * The position in the remote file to start downloading from. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_get( #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $local_filename, string $remote_filename, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $mode, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '7.3')] int $mode = FTP_BINARY, int $offset = 0 ): bool {} /** * Downloads a file from the FTP server and saves to an open file * @link https://php.net/manual/en/function.ftp-fget.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param resource $stream

    * An open file pointer in which we store the data. *

    * @param string $remote_filename

    * The remote file path. *

    * @param int $mode

    * The transfer mode. Must be either FTP_ASCII or FTP_BINARY. Since PHP 7.3 parameter is optional *

    * @param int $offset [optional]

    * The position in the remote file to start downloading from. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_fget( #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, $stream, string $remote_filename, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $mode, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '7.3')] int $mode = FTP_BINARY, int $offset = 0 ): bool {} /** * Uploads a file to the FTP server * @link https://php.net/manual/en/function.ftp-put.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $remote_filename

    * The remote file path. *

    * @param string $local_filename

    * The local file path. *

    * @param int $mode

    * The transfer mode. Must be either FTP_ASCII or FTP_BINARY. Optional since PHP 7.3 *

    * @param int $offset [optional]

    The position in the remote file to start uploading to.

    * @return bool TRUE on success or FALSE on failure. */ function ftp_put( #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $remote_filename, string $local_filename, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $mode, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '7.3')] int $mode = FTP_BINARY, int $offset = 0 ): bool {} /** * Uploads from an open file to the FTP server * @link https://php.net/manual/en/function.ftp-fput.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $remote_filename

    * The remote file path. *

    * @param resource $stream

    * An open file pointer on the local file. Reading stops at end of file. *

    * @param int $mode

    * The transfer mode. Must be either FTP_ASCII or FTP_BINARY. Optional since PHP 7.3 *

    * @param int $offset [optional]

    The position in the remote file to start uploading to.

    * @return bool TRUE on success or FALSE on failure. */ function ftp_fput( #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $remote_filename, $stream, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $mode, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '7.3')] int $mode = FTP_BINARY, int $offset = 0 ): bool {} /** * Returns the size of the given file * @link https://php.net/manual/en/function.ftp-size.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $filename

    * The remote file. *

    * @return int the file size on success, or -1 on error. */ function ftp_size(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $filename): int {} /** * Returns the last modified time of the given file * @link https://php.net/manual/en/function.ftp-mdtm.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $filename

    * The file from which to extract the last modification time. *

    * @return int the last modified time as a Unix timestamp on success, or -1 on * error. */ function ftp_mdtm(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $filename): int {} /** * Renames a file or a directory on the FTP server * @link https://php.net/manual/en/function.ftp-rename.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $from

    * The old file/directory name. *

    * @param string $to

    * The new name. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_rename(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $from, string $to): bool {} /** * Deletes a file on the FTP server * @link https://php.net/manual/en/function.ftp-delete.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $filename

    * The file to delete. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_delete(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $filename): bool {} /** * Sends a SITE command to the server * @link https://php.net/manual/en/function.ftp-site.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $command

    * The SITE command. Note that this parameter isn't escaped so there may * be some issues with filenames containing spaces and other characters. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_site(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $command): bool {} /** * Closes an FTP connection * @link https://php.net/manual/en/function.ftp-close.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @return bool TRUE on success or FALSE on failure. */ function ftp_close(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp): bool {} /** * Set miscellaneous runtime FTP options * @link https://php.net/manual/en/function.ftp-set-option.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param int $option

    * Currently, the following options are supported: *

    * Supported runtime FTP options * * * * * * * * *
    FTP_TIMEOUT_SEC * Changes the timeout in seconds used for all network related * functions. value must be an integer that * is greater than 0. The default timeout is 90 seconds. *
    FTP_AUTOSEEK * When enabled, GET or PUT requests with a * resumepos or startpos * parameter will first seek to the requested position within the file. * This is enabled by default. *
    *

    * @param mixed $value

    * This parameter depends on which option is chosen * to be altered. *

    * @return bool TRUE if the option could be set; FALSE if not. A warning * message will be thrown if the option is not * supported or the passed value doesn't match the * expected value for the given option. */ function ftp_set_option(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, #[EV(flags: [FTP_TIMEOUT_SEC, FTP_AUTOSEEK, FTP_USEPASVADDRESS])] int $option, $value): bool {} /** * Retrieves various runtime behaviours of the current FTP stream * @link https://php.net/manual/en/function.ftp-get-option.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param int $option

    * Currently, the following options are supported: *

    * Supported runtime FTP options * * * * * * * * *
    FTP_TIMEOUT_SEC * Returns the current timeout used for network related operations. *
    FTP_AUTOSEEK * Returns TRUE if this option is on, FALSE otherwise. *
    *

    * @return int|bool the value on success or FALSE if the given * option is not supported. In the latter case, a * warning message is also thrown. */ function ftp_get_option(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, #[EV(flags: [FTP_TIMEOUT_SEC, FTP_AUTOSEEK])] int $option): int|bool {} /** * Retrieves a file from the FTP server and writes it to an open file (non-blocking) * @link https://php.net/manual/en/function.ftp-nb-fget.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param resource $stream

    * An open file pointer in which we store the data. *

    * @param string $remote_filename

    * The remote file path. *

    * @param int $mode

    * The transfer mode. Must be either FTP_ASCII or FTP_BINARY. Optional since PHP 7.3 *

    * @param int $offset [optional]

    The position in the remote file to start downloading from.

    * @return int FTP_FAILED or FTP_FINISHED * or FTP_MOREDATA. */ #[EV([FTP_FAILED, FTP_FINISHED, FTP_MOREDATA])] function ftp_nb_fget( #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, $stream, string $remote_filename, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $mode, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '7.3')] int $mode = FTP_BINARY, int $offset = 0 ): int {} /** * Retrieves a file from the FTP server and writes it to a local file (non-blocking) * @link https://php.net/manual/en/function.ftp-nb-get.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $local_filename

    * The local file path (will be overwritten if the file already exists). *

    * @param string $remote_filename

    * The remote file path. *

    * @param int $mode

    * The transfer mode. Must be either FTP_ASCII or FTP_BINARY. Optional since PHP 7.3 *

    * @param int $offset [optional]

    The position in the remote file to start downloading from.

    * @return int|false FTP_FAILED or FTP_FINISHED * or FTP_MOREDATA. */ #[EV([FTP_FAILED, FTP_FINISHED, FTP_MOREDATA])] #[LanguageLevelTypeAware(["8.1" => "int|false"], default: "int")] function ftp_nb_get( #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $local_filename, string $remote_filename, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $mode, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '7.3')] int $mode = FTP_BINARY, int $offset = 0 ) {} /** * Continues retrieving/sending a file (non-blocking) * @link https://php.net/manual/en/function.ftp-nb-continue.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @return int FTP_FAILED or FTP_FINISHED * or FTP_MOREDATA. */ #[EV([FTP_FAILED, FTP_FINISHED, FTP_MOREDATA])] function ftp_nb_continue(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp): int {} /** * Stores a file on the FTP server (non-blocking) * @link https://php.net/manual/en/function.ftp-nb-put.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $remote_filename

    * The remote file path. *

    * @param string $local_filename

    * The local file path. *

    * @param int $mode

    * The transfer mode. Must be either FTP_ASCII or FTP_BINARY. Optional since PHP 7.3 *

    * @param int $offset [optional]

    The position in the remote file to start uploading to.

    * @return int|false FTP_FAILED or FTP_FINISHED * or FTP_MOREDATA. */ #[EV([FTP_FAILED, FTP_FINISHED, FTP_MOREDATA])] function ftp_nb_put( #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $remote_filename, string $local_filename, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $mode, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '7.3')] int $mode = FTP_BINARY, int $offset = 0 ): int|false {} /** * Stores a file from an open file to the FTP server (non-blocking) * @link https://php.net/manual/en/function.ftp-nb-fput.php * @param resource $ftp

    * The link identifier of the FTP connection. *

    * @param string $remote_filename

    * The remote file path. *

    * @param resource $stream

    * An open file pointer on the local file. Reading stops at end of file. *

    * @param int $mode

    * The transfer mode. Must be either FTP_ASCII or FTP_BINARY. Optional since PHP 7.3 *

    * @param int $offset [optional]

    The position in the remote file to start uploading to.

    * @return int FTP_FAILED or FTP_FINISHED * or FTP_MOREDATA. */ #[EV([FTP_FAILED, FTP_FINISHED, FTP_MOREDATA])] function ftp_nb_fput( #[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp, string $remote_filename, $stream, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] int $mode, #[EV([FTP_ASCII, FTP_BINARY])] #[PhpStormStubsElementAvailable(from: '7.3')] int $mode = FTP_BINARY, int $offset = 0 ): int {} /** * Alias of ftp_close * @link https://php.net/manual/en/function.ftp-quit.php * @param resource $ftp * @return bool TRUE on success or FALSE on failure. */ function ftp_quit(#[LanguageLevelTypeAware(['8.1' => 'FTP\Connection'], default: 'resource')] $ftp): bool {} /** *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_ASCII', 1); /** *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_TEXT', 1); /** *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_BINARY', 2); /** *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_IMAGE', 2); /** *

    * Automatically determine resume position and start position for GET and PUT requests * (only works if FTP_AUTOSEEK is enabled) *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_AUTORESUME', -1); /** *

    * See ftp_set_option for information. *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_TIMEOUT_SEC', 0); /** *

    * See ftp_set_option for information. *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_AUTOSEEK', 1); define('FTP_USEPASVADDRESS', 2); /** *

    * Asynchronous transfer has failed *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_FAILED', 0); /** *

    * Asynchronous transfer has finished *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_FINISHED', 1); /** *

    * Asynchronous transfer is still active *

    * @link https://php.net/manual/en/ftp.constants.php */ define('FTP_MOREDATA', 2); // End of ftp v. * The Threshold. Lower is more accurate, hence larger file size. *

    * @return void */ function ming_setcubicthreshold($threshold) {} /** * Set the global scaling factor. * @link https://php.net/manual/en/function.ming-setscale.php * @param float $scale

    * The scale to be set. *

    * @return void */ function ming_setscale($scale) {} /** * Sets the SWF version * @link https://php.net/manual/en/function.ming-useswfversion.php * @param int $version

    * SWF version to use. *

    * @return void */ function ming_useswfversion($version) {} /** * Returns the action flag for keyPress(char) * @link https://php.net/manual/en/function.ming-keypress.php * @param string $char * @return int What the function returns, first on success, then on failure. See * also the &return.success; entity */ function ming_keypress($char) {} /** * Use constant pool * @link https://php.net/manual/en/function.ming-useconstants.php * @param int $use

    * Its description *

    * @return void */ function ming_useconstants($use) {} /** * Sets the SWF output compression * @link https://php.net/manual/en/function.ming-setswfcompression.php * @param int $level

    * The new compression level. Should be a value between 1 and 9 * inclusive. *

    * @return void */ function ming_setswfcompression($level) {} define('MING_NEW', 1); define('MING_ZLIB', 1); define('SWFBUTTON_HIT', 8); define('SWFBUTTON_DOWN', 4); define('SWFBUTTON_OVER', 2); define('SWFBUTTON_UP', 1); define('SWFBUTTON_MOUSEUPOUTSIDE', 64); define('SWFBUTTON_DRAGOVER', 160); define('SWFBUTTON_DRAGOUT', 272); define('SWFBUTTON_MOUSEUP', 8); define('SWFBUTTON_MOUSEDOWN', 4); define('SWFBUTTON_MOUSEOUT', 2); define('SWFBUTTON_MOUSEOVER', 1); define('SWFFILL_RADIAL_GRADIENT', 18); define('SWFFILL_LINEAR_GRADIENT', 16); define('SWFFILL_TILED_BITMAP', 64); define('SWFFILL_CLIPPED_BITMAP', 65); define('SWFTEXTFIELD_HASLENGTH', 2); define('SWFTEXTFIELD_NOEDIT', 8); define('SWFTEXTFIELD_PASSWORD', 16); define('SWFTEXTFIELD_MULTILINE', 32); define('SWFTEXTFIELD_WORDWRAP', 64); define('SWFTEXTFIELD_DRAWBOX', 2048); define('SWFTEXTFIELD_NOSELECT', 4096); define('SWFTEXTFIELD_HTML', 512); define('SWFTEXTFIELD_USEFONT', 256); define('SWFTEXTFIELD_AUTOSIZE', 16384); define('SWFTEXTFIELD_ALIGN_LEFT', 0); define('SWFTEXTFIELD_ALIGN_RIGHT', 1); define('SWFTEXTFIELD_ALIGN_CENTER', 2); define('SWFTEXTFIELD_ALIGN_JUSTIFY', 3); define('SWFACTION_ONLOAD', 1); define('SWFACTION_ENTERFRAME', 2); define('SWFACTION_UNLOAD', 4); define('SWFACTION_MOUSEMOVE', 8); define('SWFACTION_MOUSEDOWN', 16); define('SWFACTION_MOUSEUP', 32); define('SWFACTION_KEYDOWN', 64); define('SWFACTION_KEYUP', 128); define('SWFACTION_DATA', 256); define('SWF_SOUND_NOT_COMPRESSED', 0); define('SWF_SOUND_ADPCM_COMPRESSED', 16); define('SWF_SOUND_MP3_COMPRESSED', 32); define('SWF_SOUND_NOT_COMPRESSED_LE', 48); define('SWF_SOUND_NELLY_COMPRESSED', 96); define('SWF_SOUND_5KHZ', 0); define('SWF_SOUND_11KHZ', 4); define('SWF_SOUND_22KHZ', 8); define('SWF_SOUND_44KHZ', 12); define('SWF_SOUND_8BITS', 0); define('SWF_SOUND_16BITS', 2); define('SWF_SOUND_MONO', 0); define('SWF_SOUND_STEREO', 1); // End of ming v. * A Pool is a container for, and controller of, an adjustable number of * Workers.
    * Pooling provides a higher level abstraction of the Worker functionality, * including the management of references in the way required by pthreads. * @link https://secure.php.net/manual/en/class.pool.php */ class Pool { /** * Maximum number of Workers this Pool can use * @var int */ protected $size; /** * The class of the Worker * @var string */ protected $class; /** * The arguments for constructor of new Workers * @var array */ protected $ctor; /** * References to Workers * @var array */ protected $workers; /** * Offset in workers of the last Worker used * @var int */ protected $last; /** * (PECL pthreads >= 2.0.0)
    * Construct a new pool of workers. Pools lazily create their threads, which means * new threads will only be spawned when they are required to execute tasks. * @link https://secure.php.net/manual/en/pool.construct.php * @param int $size

    The maximum number of workers for this pool to create

    * @param string $class [optional]

    The class for new Workers. If no class is * given, then it defaults to the {@link Worker} class.

    * @param array $ctor [optional]

    An array of arguments to be passed to new * Workers

    */ public function __construct(int $size, string $class = 'Worker', array $ctor = []) {} /** * (PECL pthreads >= 2.0.0)
    * Allows the pool to collect references determined to be garbage by the * optionally given collector * @link https://secure.php.net/manual/en/pool.collect.php * @param null|callable $collector [optional]

    A Callable collector that returns a * boolean on whether the task can be collected or not. Only in rare cases should * a custom collector need to be used.

    * @return int

    The number of remaining tasks in the pool to be collected

    */ public function collect(?callable $collector = null) {} /** * (PECL pthreads >= 2.0.0)
    * Resize the Pool * @link https://secure.php.net/manual/en/pool.resize.php * @param int $size

    The maximum number of Workers this Pool can create

    * @return void */ public function resize(int $size) {} /** * (PECL pthreads >= 2.0.0)
    * Shuts down all of the workers in the pool. This will block until all submitted * tasks have been executed. * @link https://secure.php.net/manual/en/pool.shutdown.php * @return void */ public function shutdown() {} /** * (PECL pthreads >= 2.0.0)
    * Submit the task to the next Worker in the Pool * @link https://secure.php.net/manual/en/pool.submit.php * @param Threaded $task

    The task for execution

    * @return int

    the identifier of the Worker executing the object

    */ public function submit(Threaded $task) {} /** * (PECL pthreads >= 2.0.0)
    * Submit a task to the specified worker in the pool. The workers are indexed * from 0, and will only exist if the pool has needed to create them (since * threads are lazily spawned). * @link https://secure.php.net/manual/en/pool.submitTo.php * @param int $worker

    The worker to stack the task onto, indexed from 0

    * @param Threaded $task

    The task for execution

    * @return int

    The identifier of the worker that accepted the task

    */ public function submitTo(int $worker, Threaded $task) {} } /** * Threaded objects form the basis of pthreads ability to execute user code * in parallel; they expose synchronization methods and various useful * interfaces.
    * Threaded objects, most importantly, provide implicit safety for the programmer; * all operations on the object scope are safe. * * @link https://secure.php.net/manual/en/class.threaded.php */ class Threaded implements Collectable, Traversable, Countable, ArrayAccess { /** * Worker object in which this Threaded is being executed * @var Worker */ protected $worker; /** * (PECL pthreads >= 3.0.0)
    * Increments the internal number of references to a Threaded object * @return void */ public function addRef() {} /** * (PECL pthreads >= 2.0.0)
    * Fetches a chunk of the objects property table of the given size, * optionally preserving keys * @link https://secure.php.net/manual/en/threaded.chunk.php * @param int $size

    The number of items to fetch

    * @param bool $preserve [optional]

    Preserve the keys of members, by default false

    * @return array

    An array of items from the objects property table

    */ public function chunk($size, $preserve = false) {} /** * (PECL pthreads >= 2.0.0)
    * Returns the number of properties for this object * @link https://secure.php.net/manual/en/threaded.count.php * @return int

    The number of properties for this object

    */ public function count() {} /** * (PECL pthreads >= 3.0.0)
    * Decrements the internal number of references to a Threaded object * @return void */ public function delRef() {} /** * (PECL pthreads >= 2.0.8)
    * Makes thread safe standard class at runtime * @link https://secure.php.net/manual/en/threaded.extend.php * @param string $class

    The class to extend

    * @return bool

    A boolean indication of success

    */ public static function extend($class) {} /** * (PECL pthreads >= 3.0.0)
    * Retrieves the internal number of references to a Threaded object * @return int

    The number of references to the Threaded object

    */ public function getRefCount() {} /** * (PECL pthreads >= 2.0.0)
    * Tell if the referenced object is executing * @link https://secure.php.net/manual/en/thread.isrunning.php * @return bool

    A boolean indication of state

    */ public function isRunning() {} /** * (PECL pthreads >= 3.1.0)
    * @inheritdoc * @see Collectable::isGarbage() */ public function isGarbage(): bool {} /** * (PECL pthreads >= 2.0.0)
    * Tell if the referenced object was terminated during execution; suffered * fatal errors, or threw uncaught exceptions * @link https://secure.php.net/manual/en/threaded.isterminated.php * @return bool

    A boolean indication of state

    */ public function isTerminated() {} /** * (PECL pthreads >= 2.0.0)
    * Merges data into the current object * @link https://secure.php.net/manual/en/threaded.merge.php * @var mixed

    The data to merge

    * @var bool [optional]

    Overwrite existing keys, by default true

    * @return bool

    A boolean indication of success

    */ public function merge($from, $overwrite = true) {} /** * (PECL pthreads >= 2.0.0)
    * Send notification to the referenced object * @link https://secure.php.net/manual/en/threaded.notify.php * @return bool

    A boolean indication of success

    */ public function notify() {} /** * (PECL pthreads >= 3.0.0)
    * Send notification to the referenced object. This unblocks at least one * of the blocked threads (as opposed to unblocking all of them, as seen with * Threaded::notify()). * @link https://secure.php.net/manual/en/threaded.notifyone.php * @return bool

    A boolean indication of success

    */ public function notifyOne() {} /** * (PECL pthreads >= 2.0.0)
    * Pops an item from the objects property table * @link https://secure.php.net/manual/en/threaded.pop.php * @return mixed

    The last item from the objects property table

    */ public function pop() {} /** * (PECL pthreads >= 2.0.0)
    * The programmer should always implement the run method for objects * that are intended for execution. * @link https://secure.php.net/manual/en/threaded.run.php * @return void */ public function run() {} /** * (PECL pthreads >= 2.0.0)
    * Shifts an item from the objects property table * @link https://secure.php.net/manual/en/threaded.shift.php * @return mixed

    The first item from the objects property table

    */ public function shift() {} /** * (PECL pthreads >= 2.0.0)
    * Executes the block while retaining the referenced objects * synchronization lock for the calling context * @link https://secure.php.net/manual/en/threaded.synchronized.php * @param Closure $block

    The block of code to execute

    * @param mixed ...$_ [optional]

    Variable length list of arguments * to use as function arguments to the block

    * @return mixed

    The return value from the block

    */ public function synchronized(Closure $block, ...$_) {} /** * (PECL pthreads >= 2.0.0)
    * Will cause the calling context to wait for notification from the * referenced object * @link https://secure.php.net/manual/en/threaded.wait.php * @param int $timeout [optional]

    An optional timeout in microseconds

    * @return bool

    A boolean indication of success

    */ public function wait(int $timeout = 0) {} /** * @inheritdoc * @see ArrayAccess::offsetExists() */ public function offsetExists($offset) {} /** * @inheritdoc * @see ArrayAccess::offsetGet() */ public function offsetGet($offset) {} /** * @inheritdoc * @see ArrayAccess::offsetSet() */ public function offsetSet($offset, $value) {} /** * @inheritdoc * @see ArrayAccess::offsetUnset() */ public function offsetUnset($offset) {} } /** * (PECL pthreads >= 2.0.0)
    * When the start method of a Thread is invoked, the run method code will be * executed in separate Thread, in parallel.
    * After the run method is executed the Thread will exit immediately, it will * be joined with the creating Thread at the appropriate time. * * @link https://secure.php.net/manual/en/class.thread.php */ class Thread extends Threaded implements Countable, Traversable, ArrayAccess { /** * (PECL pthreads >= 2.0.0)
    * Will return the identity of the Thread that created the referenced Thread * @link https://secure.php.net/manual/en/thread.getcreatorid.php * @return int

    A numeric identity

    */ public function getCreatorId() {} /** * (PECL pthreads >= 2.0.0)
    * Return a reference to the currently executing Thread * @link https://secure.php.net/manual/en/thread.getcurrentthread.php * @return Thread

    An object representing the currently executing Thread

    */ public static function getCurrentThread() {} /** * (PECL pthreads >= 2.0.0)
    * Will return the identity of the currently executing Thread * @link https://secure.php.net/manual/en/thread.getcurrentthreadid.php * @return int

    A numeric identity

    */ public static function getCurrentThreadId() {} /** * (PECL pthreads >= 2.0.0)
    * Will return the identity of the referenced Thread * @link https://secure.php.net/manual/en/thread.getthreadid.php * @return int

    A numeric identity

    */ public function getThreadId() {} /** * (PECL pthreads >= 2.0.0)
    * Tell if the referenced Thread has been joined * @link https://secure.php.net/manual/en/thread.isjoined.php * @return bool

    A boolean indication of state

    */ public function isJoined() {} /** * (PECL pthreads >= 2.0.0)
    * Tell if the referenced Thread was started * @link https://secure.php.net/manual/en/thread.isstarted.php * @return bool

    A boolean indication of state

    */ public function isStarted() {} /** * (PECL pthreads >= 2.0.0)
    * Causes the calling context to wait for the referenced Thread to finish executing * @link https://secure.php.net/manual/en/thread.join.php * @return bool

    A boolean indication of success

    */ public function join() {} /** * (PECL pthreads >= 2.0.0)
    * Will start a new Thread to execute the implemented run method * @link https://secure.php.net/manual/en/thread.start.php * @param int $options [optional]

    An optional mask of inheritance * constants, by default {@link PTHREADS_INHERIT_ALL}

    * @return bool

    A boolean indication of success

    */ public function start(int $options = PTHREADS_INHERIT_ALL) {} } /** * (PECL pthreads >= 2.0.0)
    * Worker Threads have a persistent context, as such should be used over * Threads in most cases.
    * When a Worker is started, the run method will be executed, but the Thread will * not leave until one of the following conditions are met:
      *
    • the Worker goes out of scope (no more references remain)
    • *
    • the programmer calls shutdown
    • *
    • the script dies
    * This means the programmer can reuse the context throughout execution; placing * objects on the stack of the Worker will cause the Worker to execute the stacked * objects run method. * @link https://secure.php.net/manual/en/class.worker.php */ class Worker extends Thread implements Traversable, Countable, ArrayAccess { /** * (PECL pthreads >= 3.0.0)
    * Allows the worker to collect references determined to be garbage by the * optionally given collector * @link https://secure.php.net/manual/en/worker.collect.php * @param null|callable $collector [optional]

    A Callable collector that returns * a boolean on whether the task can be collected or not. Only in rare cases * should a custom collector need to be used

    * @return int

    The number of remaining tasks on the worker's stack to be * collected

    */ public function collect(?callable $collector = null) {} /** * (PECL pthreads >= 2.0.0)
    * Returns the number of tasks left on the stack * @link https://secure.php.net/manual/en/worker.getstacked.php * @return int

    Returns the number of tasks currently waiting to be * executed by the worker

    */ public function getStacked() {} /** * (PECL pthreads >= 2.0.0)
    * Whether the worker has been shutdown or not * @link https://secure.php.net/manual/en/worker.isshutdown.php * @return bool

    Returns whether the worker has been shutdown or not

    */ public function isShutdown() {} /** * (PECL pthreads >= 2.0.0)
    * Shuts down the Worker after executing all of the stacked tasks * @link https://secure.php.net/manual/en/worker.shutdown.php * @return bool

    Whether the worker was successfully shutdown or not

    */ public function shutdown() {} /** * (PECL pthreads >= 2.0.0)
    * Appends the new work to the stack of the referenced worker * @link https://secure.php.net/manual/en/worker.stack.php * @param Threaded $work

    A Threaded object to be executed by the Worker

    * @return int

    The new size of the stack

    */ public function stack(Threaded $work) {} /** * (PECL pthreads >= 2.0.0)
    * Removes the first task (the oldest one) in the stack * @link https://secure.php.net/manual/en/worker.unstack.php * @return Threaded|null

    The item removed from the stack

    */ public function unstack() {} } /** * (PECL pthreads >= 2.0.8)
    * Represents a garbage-collectable object. * @link https://secure.php.net/manual/en/class.collectable.php */ interface Collectable { /** * (PECL pthreads >= 2.0.8)
    * Can be called in {@link Pool::collect()} to determine if this object is garbage * @link https://secure.php.net/manual/en/collectable.isgarbage.php * @return bool

    Whether this object is garbage or not

    */ public function isGarbage(): bool; } /** * (PECL pthreads >= 3.0.0)
    * The Volatile class is new to pthreads v3. Its introduction is a consequence of * the new immutability semantics of Threaded members of Threaded classes. The * Volatile class enables for mutability of its Threaded members, and is also * used to store PHP arrays in Threaded contexts. * @see Threaded * @link https://secure.php.net/manual/en/class.volatile.php */ class Volatile extends Threaded implements Collectable, Traversable {} * Returns large object's contents * @link https://php.net/manual/en/oci-lob.load.php * @return string|false The contents of the object, or FALSE on errors. */ public function load() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the current position of internal pointer of large object * @link https://php.net/manual/en/oci-lob.tell.php * @return int|false Current position of a LOB's internal pointer or FALSE if an * error occurred. */ public function tell() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Truncates large object * @link https://php.net/manual/en/oci-lob.truncate.php * @param int $length [optional]

    * If provided, this method will truncate the LOB to * length bytes. Otherwise, it will completely * purge the LOB. *

    * @return bool TRUE on success or FALSE on failure. */ public function truncate($length = 0) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Erases a specified portion of the internal LOB data * @link https://php.net/manual/en/oci-lob.erase.php * @param int $offset [optional] * @param int $length [optional] * @return int|false The actual number of characters/bytes erased or FALSE on failure. */ public function erase($offset = null, $length = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Flushes/writes buffer of the LOB to the server * @link https://php.net/manual/en/oci-lob.flush.php * @param int $flag [optional]

    * By default, resources are not freed, but using flag * OCI_LOB_BUFFER_FREE you can do it explicitly. * Be sure you know what you're doing - next read/write operation to the * same part of LOB will involve a round-trip to the server and initialize * new buffer resources. It is recommended to use * OCI_LOB_BUFFER_FREE flag only when you are not * going to work with the LOB anymore. *

    * @return bool TRUE on success or FALSE on failure. *

    *

    * Returns FALSE if buffering was not enabled or an error occurred. */ public function flush($flag = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Changes current state of buffering for the large object * @link https://php.net/manual/en/oci-lob.setbuffering.php * @param bool $on_off

    * TRUE for on and FALSE for off. *

    * @return bool TRUE on success or FALSE on failure. Repeated calls to this method with the same flag will * return TRUE. */ public function setbuffering($on_off) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns current state of buffering for the large object * @link https://php.net/manual/en/oci-lob.getbuffering.php * @return bool FALSE if buffering for the large object is off and TRUE if * buffering is used. */ public function getbuffering() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Moves the internal pointer to the beginning of the large object * @link https://php.net/manual/en/oci-lob.rewind.php * @return bool TRUE on success or FALSE on failure. */ public function rewind() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Reads part of the large object * @link https://php.net/manual/en/oci-lob.read.php * @param int $length

    * The length of data to read, in bytes. Large values will be rounded down to 1 MB. *

    * @return string|false The contents as a string, or FALSE on failure. */ public function read($length) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Tests for end-of-file on a large object's descriptor * @link https://php.net/manual/en/oci-lob.eof.php * @return bool TRUE if internal pointer of large object is at the end of LOB. * Otherwise returns FALSE. */ public function eof() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Sets the internal pointer of the large object * @link https://php.net/manual/en/oci-lob.seek.php * @param int $offset

    * Indicates the amount of bytes, on which internal pointer should be * moved from the position, pointed by whence. *

    * @param int $whence [optional]

    * May be one of: * OCI_SEEK_SET - sets the position equal to * offset * OCI_SEEK_CUR - adds offset * bytes to the current position * OCI_SEEK_END - adds offset * bytes to the end of large object (use negative value to move to a position * before the end of large object) *

    * @return bool TRUE on success or FALSE on failure. */ public function seek($offset, $whence = OCI_SEEK_SET) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Writes data to the large object * @link https://php.net/manual/en/oci-lob.write.php * @param string $data

    * The data to write in the LOB. *

    * @param int $length [optional]

    * If this parameter is given, writing will stop after * length bytes have been written or the end of * data is reached, whichever comes first. *

    * @return int|false The number of bytes written or FALSE on failure. */ public function write($data, $length = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Appends data from the large object to another large object * @link https://php.net/manual/en/oci-lob.append.php * @param OCILob $lob_from

    * The copied LOB. *

    * @return bool TRUE on success or FALSE on failure. */ public function append(OCILob $lob_from) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns size of large object * @link https://php.net/manual/en/oci-lob.size.php * @return int|false Length of large object value or FALSE on failure. * Empty objects have zero length. */ public function size() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Alias of {@see OCILob::export} * @link https://php.net/manual/en/oci-lob.writetofile.php * @param $filename * @param $start [optional] * @param $length [optional] * @return bool TRUE on success or FALSE on failure. */ public function writetofile($filename, $start, $length) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Exports LOB's contents to a file * @link https://php.net/manual/en/oci-lob.export.php * @param string $filename

    * Path to the file. *

    * @param int $start [optional]

    * Indicates from where to start exporting. *

    * @param int $length [optional]

    * Indicates the length of data to be exported. *

    * @return bool TRUE on success or FALSE on failure. */ public function export($filename, $start = null, $length = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Imports file data to the LOB * @link https://php.net/manual/en/oci-lob.import.php * @param string $filename

    * Path to the file. *

    * @return bool TRUE on success or FALSE on failure. */ public function import($filename) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Writes a temporary large object * @link https://php.net/manual/en/oci-lob.writetemporary.php * @param string $data

    * The data to write. *

    * @param int $lob_type [optional]

    * Can be one of the following: * OCI_TEMP_BLOB is used to create temporary BLOBs * OCI_TEMP_CLOB is used to create * temporary CLOBs *

    * @return bool TRUE on success or FALSE on failure. */ public function writeTemporary($data, $lob_type = OCI_TEMP_CLOB) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Closes LOB descriptor * @link https://php.net/manual/en/oci-lob.close.php * @return bool TRUE on success or FALSE on failure. */ public function close() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Saves data to the large object * @link https://php.net/manual/en/oci-lob.save.php * @param string $data

    * The data to be saved. *

    * @param int $offset [optional]

    * Can be used to indicate offset from the beginning of the large object. *

    * @return bool TRUE on success or FALSE on failure. */ public function save($data, $offset = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Alias of {@see OCILob::import} * @link https://php.net/manual/en/oci-lob.savefile.php * @param $filename * @return bool Return true on success and false on failure */ public function savefile($filename) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Frees resources associated with the LOB descriptor * @link https://php.net/manual/en/oci-lob.free.php * @return bool TRUE on success or FALSE on failure. */ public function free() {} } /** * OCI8 Collection functionality. * @link https://php.net/manual/en/class.OCICollection.php * @since 8.0 */ class OCICollection { /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Appends element to the collection * @link https://php.net/manual/en/oci-collection.append.php * @param mixed $value

    * The value to be added to the collection. Can be a string or a number. *

    * @return bool TRUE on success or FALSE on failure. */ public function append($value) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns value of the element * @link https://php.net/manual/en/oci-collection.getelem.php * @param int $index

    * The element index. First index is 0. *

    * @return mixed FALSE if such element doesn't exist; NULL if element is NULL; * string if element is column of a string datatype or number if element is * numeric field. */ public function getelem($index) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Assigns a value to the element of the collection * @link https://php.net/manual/en/oci-collection.assignelem.php * @param int $index

    * The element index. First index is 0. *

    * @param mixed $value

    * Can be a string or a number. *

    * @return bool TRUE on success or FALSE on failure. */ public function assignelem($index, $value) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Assigns a value to the collection from another existing collection * @link https://php.net/manual/en/oci-collection.assign.php * @param OCICollection $from

    * An instance of OCICollection. *

    * @return bool TRUE on success or FALSE on failure. */ public function assign(OCICollection $from) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns size of the collection * @link https://php.net/manual/en/oci-collection.size.php * @return int|false The number of elements in the collection or FALSE on error. */ public function size() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the maximum number of elements in the collection * @link https://php.net/manual/en/oci-collection.max.php * @return int|false The maximum number as an integer, or FALSE on errors. *

    *

    * If the returned value is 0, then the number of elements is not limited. */ public function max() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Trims elements from the end of the collection * @link https://php.net/manual/en/oci-collection.trim.php * @param int $num

    * The number of elements to be trimmed. *

    * @return bool TRUE on success or FALSE on failure. */ public function trim($num) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Frees the resources associated with the collection object * @link https://php.net/manual/en/oci-collection.free.php * @return bool TRUE on success or FALSE on failure. */ public function free() {} } /** * (PHP 7.2 >= 7.2.14, PHP 8, PHP 7 >= 7.3.1, PHP 8, PECL OCI8 >= 2.2.0)
    * Sets a millisecond timeout for database calls * @link https://php.net/manual/en/function.oci-set-call-timout.php * @param resource $connection

    An Oracle connection identifier, * returned by {@see oci_connect}, {@see oci_pconnect}, * or {@see oci_new_connect}.

    * @param int $time_out

    The maximum time in milliseconds that any * single round-trip between PHP and Oracle Database may take. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_set_call_timeout($connection, int $time_out) {} /** * (PHP 7 >== 7.2.14, PHP 8, PHP 7 >= 7.3.1, PHP 8, PECL OCI8 >= 2.2.0) * Sets the database operation * @link https://www.php.net/manual/en/function.oci-set-db-operation.php * @param resource $connection

    An Oracle connection identifier, * returned by {@see oci_connect}, {@see oci_pconnect}, * or {@see oci_new_connect}.

    * @param string $dbop

    User chosen string.

    * @return bool TRUE on success or FALSE on failure. */ function oci_set_db_operation($connection, string $dbop) {} /** * Sets the size of the LOB column that will be prefetched by OCI8 when executing a query. * This can improve performance when working with large LOB data. * * @param resource $statement The OCI8 statement resource. * @param int $prefetch_lob_size The size of the LOB column, in bytes, to be prefetched. * @return bool Returns TRUE on success or FALSE on failure. * @link https://php.net/manual/en/function.oci-set-prefetch-lob.php * @since 8.2 */ function oci_set_prefetch_lob($statement, int $prefetch_lob_size): bool {} * Returns large object's contents * @link https://php.net/manual/en/oci-lob.load.php * @return string|false The contents of the object, or FALSE on errors. */ public function load() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the current position of internal pointer of large object * @link https://php.net/manual/en/oci-lob.tell.php * @return int|false Current position of a LOB's internal pointer or FALSE if an * error occurred. */ public function tell() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Truncates large object * @link https://php.net/manual/en/oci-lob.truncate.php * @param int $length [optional]

    * If provided, this method will truncate the LOB to * length bytes. Otherwise, it will completely * purge the LOB. *

    * @return bool TRUE on success or FALSE on failure. */ public function truncate($length = 0) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Erases a specified portion of the internal LOB data * @link https://php.net/manual/en/oci-lob.erase.php * @param int $offset [optional] * @param int $length [optional] * @return int|false The actual number of characters/bytes erased or FALSE on failure. */ public function erase($offset = null, $length = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Flushes/writes buffer of the LOB to the server * @link https://php.net/manual/en/oci-lob.flush.php * @param int $flag [optional]

    * By default, resources are not freed, but using flag * OCI_LOB_BUFFER_FREE you can do it explicitly. * Be sure you know what you're doing - next read/write operation to the * same part of LOB will involve a round-trip to the server and initialize * new buffer resources. It is recommended to use * OCI_LOB_BUFFER_FREE flag only when you are not * going to work with the LOB anymore. *

    * @return bool TRUE on success or FALSE on failure. *

    *

    * Returns FALSE if buffering was not enabled or an error occurred. */ public function flush($flag = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Changes current state of buffering for the large object * @link https://php.net/manual/en/oci-lob.setbuffering.php * @param bool $on_off

    * TRUE for on and FALSE for off. *

    * @return bool TRUE on success or FALSE on failure. Repeated calls to this method with the same flag will * return TRUE. */ public function setbuffering($on_off) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns current state of buffering for the large object * @link https://php.net/manual/en/oci-lob.getbuffering.php * @return bool FALSE if buffering for the large object is off and TRUE if * buffering is used. */ public function getbuffering() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Moves the internal pointer to the beginning of the large object * @link https://php.net/manual/en/oci-lob.rewind.php * @return bool TRUE on success or FALSE on failure. */ public function rewind() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Reads part of the large object * @link https://php.net/manual/en/oci-lob.read.php * @param int $length

    * The length of data to read, in bytes. Large values will be rounded down to 1 MB. *

    * @return string|false The contents as a string, or FALSE on failure. */ public function read($length) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Tests for end-of-file on a large object's descriptor * @link https://php.net/manual/en/oci-lob.eof.php * @return bool TRUE if internal pointer of large object is at the end of LOB. * Otherwise returns FALSE. */ public function eof() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Sets the internal pointer of the large object * @link https://php.net/manual/en/oci-lob.seek.php * @param int $offset

    * Indicates the amount of bytes, on which internal pointer should be * moved from the position, pointed by whence. *

    * @param int $whence [optional]

    * May be one of: * OCI_SEEK_SET - sets the position equal to * offset * OCI_SEEK_CUR - adds offset * bytes to the current position * OCI_SEEK_END - adds offset * bytes to the end of large object (use negative value to move to a position * before the end of large object) *

    * @return bool TRUE on success or FALSE on failure. */ public function seek($offset, $whence = OCI_SEEK_SET) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Writes data to the large object * @link https://php.net/manual/en/oci-lob.write.php * @param string $data

    * The data to write in the LOB. *

    * @param int $length [optional]

    * If this parameter is given, writing will stop after * length bytes have been written or the end of * data is reached, whichever comes first. *

    * @return int|false The number of bytes written or FALSE on failure. */ public function write($data, $length = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Appends data from the large object to another large object * @link https://php.net/manual/en/oci-lob.append.php * @param OCI_Lob $lob_from

    * The copied LOB. *

    * @return bool TRUE on success or FALSE on failure. */ public function append(#[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob_from) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns size of large object * @link https://php.net/manual/en/oci-lob.size.php * @return int|false Length of large object value or FALSE on failure. * Empty objects have zero length. */ public function size() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Alias of {@see OCI_Lob::export} * @link https://php.net/manual/en/oci-lob.writetofile.php * @param $filename * @param $start [optional] * @param $length [optional] * @return bool TRUE on success or FALSE on failure. */ public function writetofile($filename, $start, $length) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Exports LOB's contents to a file * @link https://php.net/manual/en/oci-lob.export.php * @param string $filename

    * Path to the file. *

    * @param int $start [optional]

    * Indicates from where to start exporting. *

    * @param int $length [optional]

    * Indicates the length of data to be exported. *

    * @return bool TRUE on success or FALSE on failure. */ public function export($filename, $start = null, $length = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Imports file data to the LOB * @link https://php.net/manual/en/oci-lob.import.php * @param string $filename

    * Path to the file. *

    * @return bool TRUE on success or FALSE on failure. */ public function import($filename) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Writes a temporary large object * @link https://php.net/manual/en/oci-lob.writetemporary.php * @param string $data

    * The data to write. *

    * @param int $lob_type [optional]

    * Can be one of the following: * OCI_TEMP_BLOB is used to create temporary BLOBs * OCI_TEMP_CLOB is used to create * temporary CLOBs *

    * @return bool TRUE on success or FALSE on failure. */ public function writeTemporary($data, $lob_type = OCI_TEMP_CLOB) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Closes LOB descriptor * @link https://php.net/manual/en/oci-lob.close.php * @return bool TRUE on success or FALSE on failure. */ public function close() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Saves data to the large object * @link https://php.net/manual/en/oci-lob.save.php * @param string $data

    * The data to be saved. *

    * @param int $offset [optional]

    * Can be used to indicate offset from the beginning of the large object. *

    * @return bool TRUE on success or FALSE on failure. */ public function save($data, $offset = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Alias of {@see OCI_Lob::import} * @link https://php.net/manual/en/oci-lob.savefile.php * @param $filename * @return bool Return true on success and false on failure */ public function savefile($filename) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Frees resources associated with the LOB descriptor * @link https://php.net/manual/en/oci-lob.free.php * @return bool TRUE on success or FALSE on failure. */ public function free() {} } /** * OCI8 Collection functionality. * @link https://php.net/manual/en/class.OCI-Collection.php * @removed 8.0 */ class OCI_Collection { /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Appends element to the collection * @link https://php.net/manual/en/oci-collection.append.php * @param mixed $value

    * The value to be added to the collection. Can be a string or a number. *

    * @return bool TRUE on success or FALSE on failure. */ public function append($value) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns value of the element * @link https://php.net/manual/en/oci-collection.getelem.php * @param int $index

    * The element index. First index is 0. *

    * @return mixed FALSE if such element doesn't exist; NULL if element is NULL; * string if element is column of a string datatype or number if element is * numeric field. */ public function getelem($index) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Assigns a value to the element of the collection * @link https://php.net/manual/en/oci-collection.assignelem.php * @param int $index

    * The element index. First index is 0. *

    * @param mixed $value

    * Can be a string or a number. *

    * @return bool TRUE on success or FALSE on failure. */ public function assignelem($index, $value) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Assigns a value to the collection from another existing collection * @link https://php.net/manual/en/oci-collection.assign.php * @param OCI_Collection $from

    * An instance of OCI-Collection. *

    * @return bool TRUE on success or FALSE on failure. */ public function assign(#[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $from) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns size of the collection * @link https://php.net/manual/en/oci-collection.size.php * @return int|false The number of elements in the collection or FALSE on error. */ public function size() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the maximum number of elements in the collection * @link https://php.net/manual/en/oci-collection.max.php * @return int|false The maximum number as an integer, or FALSE on errors. *

    *

    * If the returned value is 0, then the number of elements is not limited. */ public function max() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Trims elements from the end of the collection * @link https://php.net/manual/en/oci-collection.trim.php * @param int $num

    * The number of elements to be trimmed. *

    * @return bool TRUE on success or FALSE on failure. */ public function trim($num) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Frees the resources associated with the collection object * @link https://php.net/manual/en/oci-collection.free.php * @return bool TRUE on success or FALSE on failure. */ public function free() {} } /** * Register a user-defined callback function for Oracle Database TAF. * @link https://www.php.net/manual/en/function.oci-register-taf-callback.php * @param resource $connection

    * An Oracle connection identifier. *

    * @param mixed $callbackFn [optional]

    * A user-defined callback to register for Oracle TAF. It can be a string of the function name or a Closure (anonymous function).
    * The interface of a TAF user-defined callback function is as follows:
    * userCallbackFn ( resource $connection , int $event , int $type ) : int
    * See the parameter description and an example on OCI8 Transparent Application Failover (TAF) Support page. *

    * @return bool TRUE on success or FALSE on failure. * @since 7.2 */ function oci_register_taf_callback($connection, $callbackFn) {} /** * Unregister a user-defined callback function for Oracle Database TAF. * @link https://www.php.net/manual/en/function.oci-unregister-taf-callback.php * @param resource $connection

    * An Oracle connection identifier. *

    * @return bool TRUE on success or FALSE on failure. * @since 7.2 */ function oci_unregister_taf_callback($connection) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Associates a PHP variable with a column for query fetches * @link https://php.net/manual/en/function.oci-define-by-name.php * @param resource $statement

    A valid OCI8 statement * identifier created by {@see oci_parse} and executed * by {@see oci_execute}, or a REF * CURSOR statement identifier.

    * @param string $column_name

    * The column name used in the query. *

    *

    * Use uppercase for Oracle's default, non-case sensitive column * names. Use the exact column name case for case-sensitive * column names. *

    * @param mixed &$variable

    * The PHP variable that will contain the returned column value. *

    * @param int $type [optional]

    * The data type to be returned. Generally not needed. Note that * Oracle-style data conversions are not performed. For example, * SQLT_INT will be ignored and the returned * data type will still be SQLT_CHR. *

    *

    * You can optionally use {@see oci_new_descriptor} * to allocate LOB/ROWID/BFILE descriptors. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_define_by_name($statement, $column_name, &$variable, $type = SQLT_CHR) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Binds a PHP variable to an Oracle placeholder * @link https://php.net/manual/en/function.oci-bind-by-name.php * @param resource $statement

    * A valid OCI8 statement identifier. *

    * @param string $bv_name

    * The colon-prefixed bind variable placeholder used in the * statement. The colon is optional * in bv_name. Oracle does not use question * marks for placeholders. *

    * @param mixed &$variable

    * The PHP variable to be associated with bv_name *

    * @param int $maxlength [optional]

    * Sets the maximum length for the data. If you set it to -1, this * function will use the current length * of variable to set the maximum * length. In this case the variable must * exist and contain data * when {@see oci_bind_by_name} is called. *

    * @param int $type [optional]

    * The datatype that Oracle will treat the data as. The * default type used * is SQLT_CHR. Oracle will convert the data * between this type and the database column (or PL/SQL variable * type), when possible. *

    *

    * If you need to bind an abstract datatype (LOB/ROWID/BFILE) you * need to allocate it first using the * {@see oci_new_descriptor} function. The * length is not used for abstract datatypes * and should be set to -1. *

    *

    * Possible values for type are: *

    *

    * SQLT_BFILEE or OCI_B_BFILE * - for BFILEs; *

    * @return bool TRUE on success or FALSE on failure. */ function oci_bind_by_name($statement, $bv_name, &$variable, $maxlength = -1, $type = SQLT_CHR) {} /** * (PHP 5 >= 5.1.2, PECL OCI8 >= 1.2.0)
    * Binds a PHP array to an Oracle PL/SQL array parameter * @link https://php.net/manual/en/function.oci-bind-array-by-name.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @param string $name

    * The Oracle placeholder. *

    * @param array &$var_array

    * An array. *

    * @param int $max_table_length

    * Sets the maximum length both for incoming and result arrays. *

    * @param int $max_item_length [optional]

    * Sets maximum length for array items. If not specified or equals to -1, * {@see oci_bind_array_by_name} will find the longest * element in the incoming array and will use it as the maximum length. *

    * @param int $type [optional]

    * Should be used to set the type of PL/SQL array items. See list of * available types below: *

    *

    * SQLT_NUM - for arrays of NUMBER. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_bind_array_by_name($statement, $name, array &$var_array, $max_table_length, $max_item_length = -1, $type = SQLT_AFC) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Checks if a field in the currently fetched row NULL * @link https://php.net/manual/en/function.oci-field-is-null.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @param mixed $field

    * Can be a field's index or a field's name (uppercased). *

    * @return bool TRUE if field is NULL, FALSE otherwise. */ function oci_field_is_null($statement, $field) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the name of a field from the statement * @link https://php.net/manual/en/function.oci-field-name.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @param string|int $field

    * Can be the field's index (1-based) or name. *

    * @return string|false The name as a string, or FALSE on errors. */ function oci_field_name($statement, $field) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns field's size * @link https://php.net/manual/en/function.oci-field-size.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @param mixed $field

    * Can be the field's index (1-based) or name. *

    * @return int|false The size of a field in bytes, or FALSE on * errors. */ function oci_field_size($statement, $field) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Tell the scale of the field * @link https://php.net/manual/en/function.oci-field-scale.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @param string|int $field

    * Can be the field's index (1-based) or name. *

    * @return int|false The scale as an integer, or FALSE on errors. */ function oci_field_scale($statement, $field) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Tell the precision of a field * @link https://php.net/manual/en/function.oci-field-precision.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @param string|int $field

    * Can be the field's index (1-based) or name. *

    * @return int|false The precision as an integer, or FALSE on errors. */ function oci_field_precision($statement, $field) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns field's data type * @link https://php.net/manual/en/function.oci-field-type.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @param string|int $field

    * Can be the field's index (1-based) or name. *

    * @return mixed the field data type as a string, or FALSE on errors. */ function oci_field_type($statement, $field) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Tell the raw Oracle data type of the field * @link https://php.net/manual/en/function.oci-field-type-raw.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @param int $field

    * Can be the field's index (1-based) or name. *

    * @return int|false Oracle's raw data type as a string, or FALSE on errors. */ function oci_field_type_raw($statement, $field) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Executes a statement * @link https://php.net/manual/en/function.oci-execute.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @param int $mode [optional]

    * An optional second parameter can be one of the following constants: *

    * Execution Modes * * * * * * * * * * * * * * * * *
    ConstantDescription
    OCI_COMMIT_ON_SUCCESSAutomatically commit all outstanding changes for * this connection when the statement has succeeded. This * is the default.
    OCI_DESCRIBE_ONLYMake query meta data available to functions * like {@see oci_field_name} but do not * create a result set. Any subsequent fetch call such * as {@see oci_fetch_array} will * fail.
    OCI_NO_AUTO_COMMITDo not automatically commit changes. Prior to PHP * 5.3.2 (PECL OCI8 1.4) * use OCI_DEFAULT which is equivalent * to OCI_NO_AUTO_COMMIT.
    *

    *

    * Using OCI_NO_AUTO_COMMIT mode starts or continues a * transaction. Transactions are automatically rolled back when * the connection is closed, or when the script ends. Explicitly * call {@see oci_commit} to commit a transaction, * or {@see oci_rollback} to abort it. *

    *

    * When inserting or updating data, using transactions is * recommended for relational data consistency and for performance * reasons. *

    *

    * If OCI_NO_AUTO_COMMIT mode is used for any * statement including queries, and * {@see oci_commit} * or {@see oci_rollback} is not subsequently * called, then OCI8 will perform a rollback at the end of the * script even if no data was changed. To avoid an unnecessary * rollback, many scripts do not * use OCI_NO_AUTO_COMMIT mode for queries or * PL/SQL. Be careful to ensure the appropriate transactional * consistency for the application when * using {@see oci_execute} with different modes in * the same script. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_execute($statement, $mode = OCI_COMMIT_ON_SUCCESS) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Cancels reading from cursor * @link https://php.net/manual/en/function.oci-cancel.php * @param resource $statement

    * An OCI statement. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_cancel($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Fetches the next row from a query into internal buffers * @link https://php.net/manual/en/function.oci-fetch.php * @param resource $statement

    A valid OCI8 statement * identifier created by {@see oci_parse} and executed * by {@see oci_execute}, or a REF * CURSOR statement identifier.

    * @return bool TRUE on success or FALSE if there are no more rows in the * statement. */ function oci_fetch($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the next row from a query as an object * @link https://php.net/manual/en/function.oci-fetch-object.php * @param resource $statement

    A valid OCI8 statement * identifier created by {@see oci_parse} and executed * by {@see oci_execute}, or a REF * CURSOR statement identifier.

    * @return object|false

    An object. Each attribute of the object corresponds to a * column of the row. If there are no more rows in * the statement then FALSE is returned. *

    *

    * Any LOB columns are returned as LOB descriptors. *

    *

    * DATE columns are returned as strings formatted * to the current date format. The default format can be changed with * Oracle environment variables such as NLS_LANG or * by a previously executed ALTER SESSION SET * NLS_DATE_FORMAT command. *

    *

    * Oracle's default, non-case sensitive column names will have * uppercase attribute names. Case-sensitive column names will have * attribute names using the exact column case. * Use var_dump on the result object to verify * the appropriate case for attribute access. *

    *

    * Attribute values will be NULL for any NULL * data fields. *

    */ function oci_fetch_object($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the next row from a query as a numeric array * @link https://php.net/manual/en/function.oci-fetch-row.php * @param resource $statement

    A valid OCI8 statement * identifier created by {@see oci_parse} and executed * by {@see oci_execute}, or a REF * CURSOR statement identifier.

    * @return array|false A numerically indexed array. If there are no more rows in * the statement then FALSE is returned. */ function oci_fetch_row($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the next row from a query as an associative array * @link https://php.net/manual/en/function.oci-fetch-assoc.php * @param resource $statement

    A valid OCI8 statement * identifier created by {@see oci_parse} and executed * by {@see oci_execute}, or a REF * CURSOR statement identifier.

    * @return array|false An associative array. If there are no more rows in * the statement then FALSE is returned. */ function oci_fetch_assoc($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the next row from a query as an associative or numeric array * @link https://php.net/manual/en/function.oci-fetch-array.php * @param resource $statement

    A valid OCI8 statement * identifier created by {@see oci_parse} and executed * by {@see oci_execute}, or a REF * CURSOR statement identifier.

    *

    * Can also be a statement identifier returned by {@see oci_get_implicit_resultset}. *

    * @param int $mode [optional]

    * An optional second parameter can be any combination of the following * constants: *

    * {@see oci_fetch_array} Modes * * * * * * * * * * * * * * * * * * * * * * * * *
    ConstantDescription
    OCI_BOTHReturns an array with both associative and numeric * indices. This is the same * as OCI_ASSOC * + OCI_NUM and is the default * behavior.
    OCI_ASSOCReturns an associative array.
    OCI_NUMReturns a numeric array.
    OCI_RETURN_NULLSCreates elements for NULL fields. The element * values will be a PHP NULL. *
    OCI_RETURN_LOBSReturns the contents of LOBs instead of the LOB * descriptors.
    *

    *

    * The default mode is OCI_BOTH. *

    *

    * Use the addition operator "+" to specify more than * one mode at a time. *

    * @return array|false

    An array with associative and/or numeric indices. If there * are no more rows in the statement then * FALSE is returned. *

    *

    * By default, LOB columns are returned as LOB descriptors. *

    *

    * DATE columns are returned as strings formatted * to the current date format. The default format can be changed with * Oracle environment variables such as NLS_LANG or * by a previously executed ALTER SESSION SET * NLS_DATE_FORMAT command. *

    *

    * Oracle's default, non-case sensitive column names will have * uppercase associative indices in the result array. Case-sensitive * column names will have array indices using the exact column case. * Use var_dump on the result array to verify the * appropriate case to use for each query. *

    *

    * The table name is not included in the array index. If your query * contains two different columns with the same name, * use OCI_NUM or add a column alias to the query * to ensure name uniqueness, see example #7. Otherwise only one * column will be returned via PHP. *

    */ function oci_fetch_array($statement, $mode = null) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Obsolete variant of {@see oci_fetch_array}, {@see oci_fetch_object}, * {@see oci_fetch_assoc} and * {@see oci_fetch_row} * @link https://php.net/manual/en/function.ocifetchinto.php * @param resource $statement_resource * @param array &$result * @param int $mode [optional] * @return int|bool */ #[Deprecated(since: "5.4")] function ocifetchinto($statement_resource, &$result, $mode = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Fetches multiple rows from a query into a two-dimensional array * @link https://php.net/manual/en/function.oci-fetch-all.php * @param resource $statement

    A valid OCI8 statement * identifier created by {@see oci_parse} and executed * by {@see oci_execute}, or a REF * CURSOR statement identifier.

    * @param array &$output

    * The variable to contain the returned rows. *

    *

    * LOB columns are returned as strings, where Oracle supports * conversion. *

    *

    * See {@see oci_fetch_array} for more information * on how data and types are fetched. *

    * @param int $skip [optional]

    * The number of initial rows to discard when fetching the * result. The default value is 0, so the first row onwards is * returned. *

    * @param int $maxrows [optional]

    * The number of rows to return. The default is -1 meaning return * all the rows from skip + 1 onwards. *

    * @param int $flags [optional]

    * Parameter flags indicates the array * structure and whether associative arrays should be used. *

    * {@see oci_fetch_all} Array Structure Modes * * * * * * * * * * * * *
    ConstantDescription
    OCI_FETCHSTATEMENT_BY_ROWThe outer array will contain one sub-array per query * row.
    OCI_FETCHSTATEMENT_BY_COLUMNThe outer array will contain one sub-array per query * column. This is the default.
    *

    *

    * Arrays can be indexed by column heading or numerically. *

    * {@see oci_fetch_all} Array Index Modes * * * * * * * * * * * * *
    ConstantDescription
    OCI_NUMNumeric indexes are used for each column's array.
    OCI_ASSOCAssociative indexes are used for each column's * array. This is the default.
    *

    *

    * Use the addition operator "+" to choose a combination * of array structure and index modes. *

    *

    * Oracle's default, non-case sensitive column names will have * uppercase array keys. Case-sensitive column names will have * array keys using the exact column case. * Use var_dump * on output to verify the appropriate case * to use for each query. *

    *

    * Queries that have more than one column with the same name * should use column aliases. Otherwise only one of the columns * will appear in an associative array. *

    * @return int|false The number of rows in output, which * may be 0 or more, or FALSE on failure. */ function oci_fetch_all($statement, array &$output, $skip = 0, $maxrows = -1, $flags = OCI_FETCHSTATEMENT_BY_COLUMN|OCI_ASSOC) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Frees all resources associated with statement or cursor * @link https://php.net/manual/en/function.oci-free-statement.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_free_statement($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Enables or disables internal debug output * @link https://php.net/manual/en/function.oci-internal-debug.php * @param bool $onoff

    * Set this to FALSE to turn debug output off or TRUE to turn it on. *

    * @removed 8.0 * @return void No value is returned. */ function oci_internal_debug($onoff) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the number of result columns in a statement * @link https://php.net/manual/en/function.oci-num-fields.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @return int|false The number of columns as an integer, or FALSE on errors. */ function oci_num_fields($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Prepares an Oracle statement for execution * @link https://php.net/manual/en/function.oci-parse.php * @param resource $connection

    * An Oracle connection identifier, returned by * {@see oci_connect}, {@see oci_pconnect}, or {@see oci_new_connect}. *

    * @param string $sql_text

    * The SQL or PL/SQL statement. *

    *

    * SQL statements should not end with a * semi-colon (";"). PL/SQL * statements should end with a semi-colon * (";"). *

    * @return resource|false A statement handle on success, or FALSE on error. */ function oci_parse($connection, $sql_text) {} /** * (PECL OCI8 >= 2.0.0)
    * Returns the next child statement resource from a parent statement resource that has Oracle Database 12c Implicit Result Sets * @link https://php.net/manual/en/function.oci-get-implicit-resultset.php * @param resource $statement

    A valid OCI8 statement identifier created * by {@see oci_parse} and executed * by {@see oci_execute}. The statement * identifier may or may not be associated with a SQL statement * that returns Implicit Result Sets. *

    * @return resource|false A statement handle for the next child statement available * on statement. Returns FALSE when child * statements do not exist, or all child statements have been returned * by previous calls * to {@see oci_get_implicit_resultset}. */ function oci_get_implicit_resultset($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Allocates and returns a new cursor (statement handle) * @link https://php.net/manual/en/function.oci-new-cursor.php * @param resource $connection

    * An Oracle connection identifier, returned by * {@see oci_connect} or {@see oci_pconnect}. *

    * @return resource|false A new statement handle, or FALSE on error. */ function oci_new_cursor($connection) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns field's value from the fetched row * @link https://php.net/manual/en/function.oci-result.php * @param resource $statement * @param mixed $field

    * Can be either use the column number (1-based) or the column name. * The case of the column name must be the case that Oracle meta data * describes the column as, which is uppercase for columns created * case insensitively. *

    * @return mixed everything as strings except for abstract types (ROWIDs, LOBs and * FILEs). Returns FALSE on error. */ function oci_result($statement, $field) {} /** * (PHP 5.3.7, PECL OCI8 >= 1.4.6)
    * Returns the Oracle client library version * @link https://php.net/manual/en/function.oci-client-version.php * @return string the version number as a string. */ function oci_client_version() {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the Oracle Database version * @link https://php.net/manual/en/function.oci-server-version.php * @param resource $connection * @return string|false The version information as a string or FALSE on error. */ function oci_server_version($connection) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the type of a statement * @link https://php.net/manual/en/function.oci-statement-type.php * @param resource $statement

    * A valid OCI8 statement identifier from {@see oci_parse}. *

    * @return string|false The type of statement as one of the * following strings. * * Statement type * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    Return StringNotes
    ALTER
    BEGIN
    CALLIntroduced in PHP 5.2.1 (PECL OCI8 1.2.3)
    CREATE
    DECLARE
    DELETE
    DROP
    INSERT
    SELECT
    UPDATE
    UNKNOWN
    *

    *

    * Returns FALSE on error. */ function oci_statement_type($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns number of rows affected during statement execution * @link https://php.net/manual/en/function.oci-num-rows.php * @param resource $statement

    * A valid OCI statement identifier. *

    * @return int|false The number of rows affected as an integer, or FALSE on errors. */ function oci_num_rows($statement) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Closes an Oracle connection * @link https://php.net/manual/en/function.oci-close.php * @param resource $connection

    * An Oracle connection identifier returned by * {@see oci_connect}, {@see oci_pconnect}, * or {@see oci_new_connect}. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_close($connection) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Connect to an Oracle database * @link https://php.net/manual/en/function.oci-connect.php * @param string $username

    * The Oracle user name. *

    * @param string $password

    * The password for username. *

    * @param string $connection_string [optional]

    Contains * the Oracle instance to connect to. It can be * an Easy Connect * string, or a Connect Name from * the tnsnames.ora file, or the name of a local * Oracle instance. *

    *

    * If not specified, PHP uses * environment variables such as TWO_TASK (on Linux) * or LOCAL (on Windows) * and ORACLE_SID to determine the * Oracle instance to connect to. *

    *

    * To use the Easy Connect naming method, PHP must be linked with Oracle * 10g or greater Client libraries. The Easy Connect string for Oracle * 10g is of the form: * [//]host_name[:port][/service_name]. From Oracle * 11g, the syntax is: * [//]host_name[:port][/service_name][:server_type][/instance_name]. * Service names can be found by running the Oracle * utility lsnrctl status on the database server * machine. *

    *

    * The tnsnames.ora file can be in the Oracle Net * search path, which * includes $ORACLE_HOME/network/admin * and /etc. Alternatively * set TNS_ADMIN so * that $TNS_ADMIN/tnsnames.ora is read. Make sure * the web daemon has read access to the file. *

    * @param string $character_set [optional]

    Determines * the character set used by the Oracle Client libraries. The character * set does not need to match the character set used by the database. If * it doesn't match, Oracle will do its best to convert data to and from * the database character set. Depending on the character sets this may * not give usable results. Conversion also adds some time overhead. *

    *

    * If not specified, the * Oracle Client libraries determine a character set from * the NLS_LANG environment variable. *

    *

    * Passing this parameter can * reduce the time taken to connect. *

    *

    * @param int $session_mode [optional] This * parameter is available since version PHP 5 (PECL OCI8 1.1) and accepts the * following values: OCI_DEFAULT, * OCI_SYSOPER and OCI_SYSDBA. * If either OCI_SYSOPER or * OCI_SYSDBA were specified, this function will try * to establish privileged connection using external credentials. * Privileged connections are disabled by default. To enable them you * need to set oci8.privileged_connect * to On. *

    *

    * PHP 5.3 (PECL OCI8 1.3.4) introduced the * OCI_CRED_EXT mode value. This tells Oracle to use * External or OS authentication, which must be configured in the * database. The OCI_CRED_EXT flag can only be used * with username of "/" and a empty password. * oci8.privileged_connect * may be On or Off. *

    *

    * OCI_CRED_EXT may be combined with the * OCI_SYSOPER or * OCI_SYSDBA modes. *

    *

    * OCI_CRED_EXT is not supported on Windows for * security reasons. *

    * @return resource|false A connection identifier or FALSE on error. */ function oci_connect($username, $password, $connection_string = null, $character_set = null, $session_mode = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Connect to the Oracle server using a unique connection * @link https://php.net/manual/en/function.oci-new-connect.php * @param string $username

    * The Oracle user name. *

    * @param string $password

    * The password for username. *

    * @param string $connection_string [optional]

    Contains * the Oracle instance to connect to. It can be * an Easy Connect * string, or a Connect Name from * the tnsnames.ora file, or the name of a local * Oracle instance. *

    *

    * If not specified, PHP uses * environment variables such as TWO_TASK (on Linux) * or LOCAL (on Windows) * and ORACLE_SID to determine the * Oracle instance to connect to. *

    *

    * To use the Easy Connect naming method, PHP must be linked with Oracle * 10g or greater Client libraries. The Easy Connect string for Oracle * 10g is of the form: * [//]host_name[:port][/service_name]. From Oracle * 11g, the syntax is: * [//]host_name[:port][/service_name][:server_type][/instance_name]. * Service names can be found by running the Oracle * utility lsnrctl status on the database server * machine. *

    *

    * The tnsnames.ora file can be in the Oracle Net * search path, which * includes $ORACLE_HOME/network/admin * and /etc. Alternatively * set TNS_ADMIN so * that $TNS_ADMIN/tnsnames.ora is read. Make sure * the web daemon has read access to the file. *

    * @param string $character_set [optional]

    Determines * the character set used by the Oracle Client libraries. The character * set does not need to match the character set used by the database. If * it doesn't match, Oracle will do its best to convert data to and from * the database character set. Depending on the character sets this may * not give usable results. Conversion also adds some time overhead. *

    *

    * If not specified, the * Oracle Client libraries determine a character set from * the NLS_LANG environment variable. *

    *

    * Passing this parameter can * reduce the time taken to connect. *

    * @param int $session_mode [optional]

    This * parameter is available since version PHP 5 (PECL OCI8 1.1) and accepts the * following values: OCI_DEFAULT, * OCI_SYSOPER and OCI_SYSDBA. * If either OCI_SYSOPER or * OCI_SYSDBA were specified, this function will try * to establish privileged connection using external credentials. * Privileged connections are disabled by default. To enable them you * need to set oci8.privileged_connect * to On. *

    *

    * PHP 5.3 (PECL OCI8 1.3.4) introduced the * OCI_CRED_EXT mode value. This tells Oracle to use * External or OS authentication, which must be configured in the * database. The OCI_CRED_EXT flag can only be used * with username of "/" and a empty password. * oci8.privileged_connect * may be On or Off. *

    *

    * OCI_CRED_EXT may be combined with the * OCI_SYSOPER or * OCI_SYSDBA modes. *

    *

    * OCI_CRED_EXT is not supported on Windows for * security reasons. *

    * @return resource|false A connection identifier or FALSE on error. */ function oci_new_connect($username, $password, $connection_string = null, $character_set = null, $session_mode = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Connect to an Oracle database using a persistent connection * @link https://php.net/manual/en/function.oci-pconnect.php * @param string $username

    * The Oracle user name. *

    * @param string $password

    * The password for username. *

    * @param string $connection_string [optional]

    Contains * the Oracle instance to connect to. It can be * an Easy Connect * string, or a Connect Name from * the tnsnames.ora file, or the name of a local * Oracle instance. *

    *

    * If not specified, PHP uses * environment variables such as TWO_TASK (on Linux) * or LOCAL (on Windows) * and ORACLE_SID to determine the * Oracle instance to connect to. *

    *

    * To use the Easy Connect naming method, PHP must be linked with Oracle * 10g or greater Client libraries. The Easy Connect string for Oracle * 10g is of the form: * [//]host_name[:port][/service_name]. From Oracle * 11g, the syntax is: * [//]host_name[:port][/service_name][:server_type][/instance_name]. * Service names can be found by running the Oracle * utility lsnrctl status on the database server * machine. *

    *

    * The tnsnames.ora file can be in the Oracle Net * search path, which * includes $ORACLE_HOME/network/admin * and /etc. Alternatively * set TNS_ADMIN so * that $TNS_ADMIN/tnsnames.ora is read. Make sure * the web daemon has read access to the file. *

    * @param string $character_set [optional]

    Determines * the character set used by the Oracle Client libraries. The character * set does not need to match the character set used by the database. If * it doesn't match, Oracle will do its best to convert data to and from * the database character set. Depending on the character sets this may * not give usable results. Conversion also adds some time overhead. *

    *

    * If not specified, the * Oracle Client libraries determine a character set from * the NLS_LANG environment variable. *

    *

    * Passing this parameter can * reduce the time taken to connect. *

    * @param int $session_mode [optional]

    This * parameter is available since version PHP 5 (PECL OCI8 1.1) and accepts the * following values: OCI_DEFAULT, * OCI_SYSOPER and OCI_SYSDBA. * If either OCI_SYSOPER or * OCI_SYSDBA were specified, this function will try * to establish privileged connection using external credentials. * Privileged connections are disabled by default. To enable them you * need to set oci8.privileged_connect * to On. *

    *

    * PHP 5.3 (PECL OCI8 1.3.4) introduced the * OCI_CRED_EXT mode value. This tells Oracle to use * External or OS authentication, which must be configured in the * database. The OCI_CRED_EXT flag can only be used * with username of "/" and a empty password. * oci8.privileged_connect * may be On or Off. *

    *

    * OCI_CRED_EXT may be combined with the * OCI_SYSOPER or * OCI_SYSDBA modes. *

    *

    * OCI_CRED_EXT is not supported on Windows for * security reasons. *

    * @return resource|false A connection identifier or FALSE on error. */ function oci_pconnect($username, $password, $connection_string = null, $character_set = null, $session_mode = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Returns the last error found * @link https://php.net/manual/en/function.oci-error.php * @param resource $resource [optional]

    * For most errors, resource is the * resource handle that was passed to the failing function call. * For connection errors with {@see oci_connect}, * {@see oci_new_connect} or * {@see oci_pconnect} do not pass resource. *

    * @return array|false If no error is found, {@see oci_error} returns * FALSE. Otherwise, {@see oci_error} returns the * error information as an associative array. *

    *

    *

    * {@see oci_error} Array Description * * * * * * * * * * * * * * * * * * * * * * * * * *
    Array keyTypeDescription
    codeinteger * The Oracle error number. *
    messagestring * The Oracle error text. *
    offsetinteger * The byte position of an error in the SQL statement. If there * was no statement, this is 0 *
    sqltextstring * The SQL statement text. If there was no statement, this is * an empty string. *
    */ #[ArrayShape(["code" => "int", "message" => "string", "offset" => "int", "sqltext" => "string"])] function oci_error($resource = null) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Frees a descriptor * @link https://php.net/manual/en/function.oci-free-descriptor.php * @param resource $descriptor * @return bool TRUE on success or FALSE on failure. */ function oci_free_descriptor($descriptor) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Compares two LOB/FILE locators for equality * @link https://php.net/manual/en/function.oci-lob-is-equal.php * @param OCI_Lob $lob1

    * A LOB identifier. *

    * @param OCI_Lob $lob2

    * A LOB identifier. *

    * @return bool TRUE if these objects are equal, FALSE otherwise. */ function oci_lob_is_equal( #[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob1, #[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob2 ) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Copies large object * @link https://php.net/manual/en/function.oci-lob-copy.php * @param OCI_Lob $lob_to

    * The destination LOB. *

    * @param OCI_Lob $lob_from

    * The copied LOB. *

    * @param int $length [optional]

    * Indicates the length of data to be copied. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_lob_copy( #[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob_to, #[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob_from, $length = 0 ) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Commits the outstanding database transaction * @link https://php.net/manual/en/function.oci-commit.php * @param resource $connection

    * An Oracle connection identifier, returned by * {@see oci_connect}, {@see oci_pconnect}, or {@see oci_new_connect}. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_commit($connection) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Rolls back the outstanding database transaction * @link https://php.net/manual/en/function.oci-rollback.php * @param resource $connection

    * An Oracle connection identifier, returned by * {@see oci_connect}, {@see oci_pconnect} * or {@see oci_new_connect}. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_rollback($connection) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Initializes a new empty LOB or FILE descriptor * @link https://php.net/manual/en/function.oci-new-descriptor.php * @param resource $connection

    * An Oracle connection identifier, returned by * {@see oci_connect} or {@see oci_pconnect}. *

    * @param int $type [optional]

    * Valid values for type are: * OCI_DTYPE_FILE, OCI_DTYPE_LOB and * OCI_DTYPE_ROWID. *

    * @return OCI_Lob|OCILob|false A new LOB or FILE descriptor on success, FALSE on error. */ #[LanguageLevelTypeAware(['8.0' => 'OCILob|false'], default: 'OCI_Lob|false')] function oci_new_descriptor($connection, $type = OCI_DTYPE_LOB) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Sets number of rows to be prefetched by queries * @link https://php.net/manual/en/function.oci-set-prefetch.php * @param resource $statement

    A valid OCI8 statement * identifier created by {@see oci_parse} and executed * by {@see oci_execute}, or a REF * CURSOR statement identifier.

    * @param int $rows

    * The number of rows to be prefetched, >= 0 *

    * @return bool TRUE on success or FALSE on failure. */ function oci_set_prefetch($statement, $rows) {} /** * (PHP 5.3.2, PECL OCI8 >= 1.4.0)
    * Sets the client identifier * @link https://php.net/manual/en/function.oci-set-client-identifier.php * @param resource $connection

    An Oracle connection identifier, * returned by {@see oci_connect}, {@see oci_pconnect}, * or {@see oci_new_connect}.

    * @param string $client_identifier

    * User chosen string up to 64 bytes long. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_set_client_identifier($connection, $client_identifier) {} /** * (PHP 5.3.2, PECL OCI8 >= 1.4.0)
    * Sets the database edition * @link https://php.net/manual/en/function.oci-set-edition.php * @param string $edition

    * Oracle Database edition name previously created with the SQL * "CREATE EDITION" command. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_set_edition($edition) {} /** * (PHP 5.3.2, PECL OCI8 >= 1.4.0)
    * Sets the module name * @link https://php.net/manual/en/function.oci-set-module-name.php * @param resource $connection

    An Oracle connection identifier, * returned by {@see oci_connect}, {@see oci_pconnect}, * or {@see oci_new_connect}.

    * @param string $module_name

    * User chosen string up to 48 bytes long. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_set_module_name($connection, $module_name) {} /** * (PHP 5.3.2, PECL OCI8 >= 1.4.0)
    * Sets the action name * @link https://php.net/manual/en/function.oci-set-action.php * @param resource $connection

    An Oracle connection identifier, * returned by {@see oci_connect}, {@see oci_pconnect}, * or {@see oci_new_connect}.

    * @param string $action_name

    * User chosen string up to 32 bytes long. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_set_action($connection, $action_name) {} /** * (PHP 5.3.2, PECL OCI8 >= 1.4.0)
    * Sets the client information * @link https://php.net/manual/en/function.oci-set-client-info.php * @param resource $connection

    An Oracle connection identifier, * returned by {@see oci_connect}, {@see oci_pconnect}, * or {@see oci_new_connect}.

    * @param string $client_info

    * User chosen string up to 64 bytes long. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_set_client_info($connection, $client_info) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Changes password of Oracle's user * @link https://php.net/manual/en/function.oci-password-change.php * @param resource $connection

    * An Oracle connection identifier, returned by * {@see oci_connect} or {@see oci_pconnect}. *

    * @param string $username

    * The Oracle user name. *

    * @param string $old_password

    * The old password. *

    * @param string $new_password

    * The new password to be set. *

    * @return bool TRUE on success or FALSE on failure. */ function oci_password_change($connection, $username, $old_password, $new_password) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Allocates new collection object * @link https://php.net/manual/en/function.oci-new-collection.php * @param resource $connection

    * An Oracle connection identifier, returned by * {@see oci_connect} or {@see oci_pconnect}. *

    * @param string $tdo

    * Should be a valid named type (uppercase). *

    * @param string $schema [optional]

    * Should point to the scheme, where the named type was created. The name * of the current user is the default value. *

    * @return OCI_Collection|false A new OCICollection object or FALSE on * error. */ #[LanguageLevelTypeAware(['8.0' => 'OCICollection|false'], default: 'OCI_Collection|false')] function oci_new_collection($connection, $tdo, $schema = null) {} /** * Alias of {@see oci_free_statement()} * @link https://php.net/manual/en/function.ocifreecursor.php * @param $statement_resource * @return bool Returns TRUE on success or FALSE on failure. */ function oci_free_cursor($statement_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see oci_free_statement} * @link https://php.net/manual/en/function.ocifreecursor.php * @param resource $statement_resource * @return bool TRUE on success or FALSE on failure. */ #[Deprecated(replacement: "oci_free_statement", since: "5.4")] function ocifreecursor($statement_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_bind_by_name} * @link https://php.net/manual/en/function.ocibindbyname.php * @param resource $statement * @param string $column_name * @param mixed &$variable * @param int $maximum_length [optional] * @param int $type [optional] * @return bool Returns TRUE on success or FALSE on failure. */ #[Deprecated(replacement: "oci_bind_by_name", since: "5.4")] function ocibindbyname($statement, $column_name, &$variable, $maximum_length = -1, $type = SQLT_CHR) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_define_by_name} * @link https://php.net/manual/en/function.ocidefinebyname.php * @param resource $statement

    A valid OCI8 statement identifier created by {@see oci_parse()} and executed by {@see oci_execute()}, or a REF CURSOR statement identifier.

    * @param string $column_name

    The column name used in the query. Use uppercase for Oracle's default, non-case sensitive column names. Use the exact column name case for case-sensitive column names.

    * @param mixed &$variable

    The PHP variable that will contain the returned column value.

    * @param int $type [optional]

    The data type to be returned. Generally not needed. Note that Oracle-style data conversions are not performed. For example, SQLT_INT will be ignored and the returned data type will still be SQLT_CHR. * You can optionally use {@see oci_new_descriptor()} to allocate LOB/ROWID/BFILE descriptors.

    * @return bool Returns TRUE on success or FALSE on failure. */ #[Deprecated(replacement: "oci_define_by_name", since: "5.4")] function ocidefinebyname($statement, $column_name, &$variable, $type = SQLT_CHR) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_field_is_null} * @link https://php.net/manual/en/function.ocicolumnisnull.php * @param resource $statement * @param mixed $column_number_or_name * @return bool Returns TRUE if field is NULL, FALSE otherwise. */ #[Deprecated(replacement: "oci_field_is_null", since: "5.4")] function ocicolumnisnull($statement, $column_number_or_name) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_field_name} * @link https://php.net/manual/en/function.ocicolumnname.php * @param resource $statement * @param mixed $column_number * @return string|false Returns the name as a string, or FALSE on errors. */ #[Deprecated(replacement: "oci_field_name", since: "5.4")] function ocicolumnname($statement, $column_number) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_field_size} * @link https://php.net/manual/en/function.ocicolumnsize.php * @param resource $statement * @param mixed $column_number_or_name * @return int|false Returns the size of a field in bytes, or FALSE on errors. */ #[Deprecated(replacement: "oci_field_size", since: "5.4")] function ocicolumnsize($statement, $column_number_or_name) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_field_scale} * @link https://php.net/manual/en/function.ocicolumnscale.php * @param resource $statement_resource * @param $column_number * @return int|false Returns the scale as an integer, or FALSE on errors. */ #[Deprecated(replacement: "oci_field_scale", since: "5.4")] function ocicolumnscale($statement_resource, $column_number) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_field_precision} * @link https://php.net/manual/en/function.ocicolumnprecision.php * @param resource $statement_resource * @param string|int $column_number * @return int|false Returns the precision as an integer, or FALSE on errors. */ #[Deprecated(replacement: "oci_field_precision", since: "5.4")] function ocicolumnprecision($statement_resource, $column_number) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_field_type} * @link https://php.net/manual/en/function.ocicolumntype.php * @param resource $statement_resource * @param string|int $column_number * @return mixed|false Returns the field data type as a string, or FALSE on errors. */ #[Deprecated(replacement: "oci_field_type", since: "5.4")] function ocicolumntype($statement_resource, $column_number) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_field_type_raw} * @link https://php.net/manual/en/function.ocicolumntyperaw.php * @param resource $statement_resource * @param string|int $column_number * @return int|false Returns Oracle's raw data type as a number, or FALSE on errors. */ #[Deprecated(replacement: "oci_field_type_raw", since: "5.4")] function ocicolumntyperaw($statement_resource, $column_number) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_execute} * @link https://php.net/manual/en/function.ociexecute.php * @param $statement_resource * @param $mode [optional] * @return bool Returns TRUE on success or FALSE on failure */ #[Deprecated(replacement: "oci_execute", since: "5.4")] function ociexecute($statement_resource, $mode = OCI_COMMIT_ON_SUCCESS) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_cancel} * @link https://php.net/manual/en/function.ocicancel.php * @param resource $statement_resource * @return bool Returns TRUE on success or FALSE on failure */ #[Deprecated(replacement: 'oci_cancel', since: "5.4")] function ocicancel($statement_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_fetch} * @link https://php.net/manual/en/function.ocifetch.php * @param resource $statement_resource * @return bool Returns TRUE on success or FALSE if there are no more rows in the statement. */ #[Deprecated(replacement: "oci_fetch", since: "5.4")] function ocifetch($statement_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_fetch_all} * @link https://php.net/manual/en/function.ocifetchstatement.php * @param resource $statement_resource * @param array &$output * @param int $skip [optional] * @param int $maximum_rows [optional] * @param int $flags [optional] * @return int|false Returns the number of rows in output, which may be 0 or more, or FALSE on failure. */ #[Deprecated(replacement: "oci_fetch_all", since: "5.4")] function ocifetchstatement($statement_resource, &$output, $skip, $maximum_rows, $flags) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_free_statement} * @link https://php.net/manual/en/function.ocifreestatement.php * @param resource $statement_resource * @return bool Returns TRUE on success or FALSE on failure. */ #[Deprecated(replacement: "oci_free_statement", since: "5.4")] function ocifreestatement($statement_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_internal_debug} * @link https://php.net/manual/en/function.ociinternaldebug.php * @param bool $mode * @removed 8.0 */ #[Deprecated(replacement: "oci_internal_debug", since: "5.4")] function ociinternaldebug($mode) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_num_fields} * @link https://php.net/manual/en/function.ocinumcols.php * @param resource $statement_resource * @return int|false Returns the number of columns as an integer, or FALSE on errors. */ #[Deprecated(replacement: "oci_num_fields", since: "5.4")] function ocinumcols($statement_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_parse} * @link https://php.net/manual/en/function.ociparse.php * @param resource $connection_resource * @param string $sql_text * @return resource|false Returns a statement handle on success, or FALSE on error. */ #[Deprecated(replacement: "oci_parse", since: "5.4")] function ociparse($connection_resource, $sql_text) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_new_cursor} * @link https://php.net/manual/en/function.ocinewcursor.php * @param resource $connection_resource * @return resource|false Returns a new statement handle, or FALSE on error. */ #[Deprecated(replacement: "oci_new_cursor", since: "5.4")] function ocinewcursor($connection_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_result} * @link https://php.net/manual/en/function.ociresult.php * @param resource $statement_resource * @param $column_number_or_name * @return false|mixed Returns everything as strings except for abstract types (ROWIDs, LOBs and FILEs). Returns FALSE on error. */ #[Deprecated(replacement: "oci_result", since: "5.4")] function ociresult($statement_resource, $column_number_or_name) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_server_version} * @link https://php.net/manual/en/function.ociserverversion.php * @param $connection_resource * @return string|false Returns the version information as a string or FALSE on error. */ #[Deprecated(replacement: "oci_server_version", since: "5.4")] function ociserverversion($connection_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_statement_type} * @link https://php.net/manual/en/function.ocistatementtype.php * @param resource $statement_resource * @return string|false Returns everything as strings except for abstract types (ROWIDs, LOBs and FILEs). Returns FALSE on error. */ #[Deprecated(replacement: "oci_statement_type", since: "5.4")] function ocistatementtype($statement_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_num_rows} * @link https://php.net/manual/en/function.ocirowcount.php * @param resource $statement_resource * @return int|false Returns the number of rows affected as an integer, or FALSE on errors. */ #[Deprecated(replacement: "oci_num_rows", since: "5.4")] function ocirowcount($statement_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_close} * @link https://php.net/manual/en/function.ocilogoff.php * @param resource $connection_resource * @return bool Returns TRUE on success or FALSE on failure. */ #[Deprecated(replacement: "oci_close", since: "5.4")] function ocilogoff($connection_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_connect} * @link https://php.net/manual/en/function.ocilogon.php * @param string $username * @param string $password * @param string $connection_string [optional] * @param string $character_set [optional] * @param int $session_mode [optional] * @return resource|false Returns a connection identifier or FALSE on error. */ #[Deprecated(replacement: "oci_connect", since: "5.4")] function ocilogon($username, $password, $connection_string, $character_set, $session_mode) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see oci_new_connect} * @link https://php.net/manual/en/function.ocinlogon.php * @param $username * @param $password * @param $connection_string [optional] * @param $character_set [optional] * @param $session_mode [optional] * @return resource|false

    Returns a connection identifier or FALSE on error.

    */ #[Deprecated(replacement: "oci_new_connect", since: "5.4")] function ocinlogon($username, $password, $connection_string, $character_set, $session_mode) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see oci_pconnect} * @link https://php.net/manual/en/function.ociplogon.php * @param string $username

    The Oracle user name.

    * @param string $password

    The password for username

    * @param $connection_string [optional] * @param $character_set [optional] * @param $session_mode [optional] * @return resource|false

    Returns a connection identifier or FALSE on error.

    */ #[Deprecated(replacement: "oci_pconnect", since: "5.4")] function ociplogon($username, $password, $connection_string, $character_set, $session_mode) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see oci_error} * @link https://php.net/manual/en/function.ocierror.php * @param resource $connection_or_statement_resource [optional] For most errors, resource is the resource handle that was passed to the failing function call. * For connection errors with oci_connect(), oci_new_connect() or oci_pconnect() do not pass resource. * @return array|false If no error is found, oci_error() returns FALSE. Otherwise, oci_error() returns the error information as an associative array. */ #[Deprecated(replacement: "oci_error", since: "5.4")] function ocierror($connection_or_statement_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see OCI-Lob::free} * @link https://php.net/manual/en/function.ocifreedesc.php * @param $lob_descriptor * @return bool

    Returns TRUE on success or FALSE on failure.

    */ #[Deprecated(replacement: "OCI-Lob::free", since: "5.4")] function ocifreedesc($lob_descriptor) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see OCI-Lob::save} * @link https://php.net/manual/en/function.ocisavelob.php * @param OCI_Lob|OCILob $lob_descriptor * @param string $data * @param int $offset [optional] * @return bool */ #[Deprecated(replacement: "OCI-Lob::save", since: "5.4")] function ocisavelob(#[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob_descriptor, $data, $offset) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see OCI_Lob::import} * @link https://php.net/manual/en/function.ocisavelobfile.php * @param OCI_Lob|OCILob $lob_descriptor * @param string $filename * @return bool */ #[Deprecated(replacement: "OCI_Lob::import", since: "5.4")] function ocisavelobfile(#[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob_descriptor, $filename) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see OCI_Lob::export} * @link https://php.net/manual/en/function.ociwritelobtofile.php * @param OCI_Lob|OCILob $lob_descriptor * @param string $filename

    Path to the file.

    * @param int $start [optional]

    Indicates from where to start exporting.

    * @param int $length [optional]

    Indicates the length of data to be exported.

    * @return bool Returns TRUE on success or FALSE on failure. */ #[Deprecated(replacement: "OCI_Lob::export", since: "5.4")] function ociwritelobtofile( #[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob_descriptor, $filename, $start, $length ) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see OCI_Lob::load} * @link https://php.net/manual/en/function.ociloadlob.php * @param OCI_Lob|OCILob $lob_descriptor * @return string|false

    Returns the contents of the object, or FALSE on errors.

    */ #[Deprecated(replacement: "OCI_Lob::load", since: "5.4")] function ociloadlob(#[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob_descriptor) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see oci_commit} * @link https://php.net/manual/en/function.ocicommit.php * @param $connection_resource

    * An Oracle connection identifier, returned by * {@see oci_connect()}, * {@see oci_pconnect()}, or * {@see oci_new_connect()}. *

    * @return bool

    Returns TRUE on success or FALSE on failure.

    */ #[Deprecated(replacement: "oci_commit", since: "5.4")] function ocicommit($connection_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see oci_rollback} * @link https://php.net/manual/en/function.ocirollback.php * @param resource $connection_resource * @return bool

    Returns TRUE on success or FALSE on failure.

    */ #[Deprecated(replacement: "oci_rollback", since: "5.4")] function ocirollback($connection_resource) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see oci_new_descriptor} * @link https://php.net/manual/en/function.ocinewdescriptor.php * @param resource $connection_resource

    * An Oracle connection identifier, returned by * {@see oci_connect()} or {@see oci_pconnect()}. *

    * @param $type [optional]

    Valid values for type are: OCI_DTYPE_FILE, OCI_DTYPE_LOB and OCI_DTYPE_ROWID.

    * @return OCI_LOB|false Returns a new LOB or FILE descriptor on success, FALSE on error. */ #[Deprecated(replacement: "oci_new_descriptor", since: "5.4")] #[LanguageLevelTypeAware(['8.0' => 'OCILob|false'], default: 'OCI_Lob|false')] function ocinewdescriptor($connection_resource, $type = OCI_DTYPE_LOB) {} /** * (PHP 4, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see oci_set_prefetch} * @link https://php.net/manual/en/function.ocisetprefetch.php * @param resource $statement_resource

    A valid OCI8 statement * identifier created by * {@see oci_parse()} and executed * by * {@see oci_execute()}, or a REF CURSOR statement identifier.

    * @param $number_of_rows * @return bool

    Returns TRUE on success or FALSE on failure.

    */ #[Deprecated(replacement: "oci_set_prefetch", since: "5.4")] function ocisetprefetch($statement_resource, $number_of_rows) {} /** * (PHP 5, PECL OCI8 >= 1.1.0)
    * Changes password of Oracle's user * @param resource|string $connection_resource_or_connection_string_or_dbname

    An Oracle connection identifier, returned by * {@see oci_connect()} or * {@see oci_pconnect()}.

    * @param string $username

    The Oracle user name.

    * @param string $old_password

    The new password to be set.

    * @param string $new_password

    The new password to be set.

    * @return resource|bool

    Returns TRUE on success or FALSE on failure or resource, depending on the function parameters.

    */ function ocipasswordchange($connection_resource_or_connection_string_or_dbname, $username, $old_password, $new_password) {} /** * (PHP 4 >= 4.0.7, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see OCI_Collection::free} * @link https://php.net/manual/en/function.ocifreecollection.php * @param OCI_Collection|OCICollection $collection * @return bool Returns TRUE on success or FALSE on failure. */ #[Deprecated(replacement: "OCI_Collection::free", since: "5.4")] function ocifreecollection(#[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $collection) {} /** * (PHP 4 >= 4.0.6, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see oci_new_collection} * @link https://php.net/manual/en/function.ocinewcollection.php * @param $connection_resource

    * An Oracle connection identifier, returned by * {@see oci_connect()} or * {@see oci_pconnect()}. * @param $tdo

    Should be a valid named type (uppercase).

    * @param $schema

    Should point to the scheme, where the named type was created. The name of the current user is the default value.

    *

    * @return OCI_Collection|false

    Returns a new OCI_Collection object or FALSE on error.

    */ #[Deprecated(replacement: "oci_new_collection", since: "5.4")] #[LanguageLevelTypeAware(['8.0' => 'OCICollection|false'], default: 'OCI_Collection|false')] function ocinewcollection($connection_resource, $tdo, $schema = null) {} /** * (PHP 4 >= 4.0.6, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * (@see OCI_Collection::append) * @link https://php.net/manual/en/function.ocicollappend.php * @param OCI_Collection $collection * @param mixed $value

    The value to be added to the collection. Can be a string or a number.

    * @return bool

    Returns TRUE on success or FALSE on failure.

    */ #[Deprecated(replacement: "OCI_Collection::append", since: "5.4")] function ocicollappend(#[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $collection, $value) {} /** * (PHP 4 >= 4.0.6, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see OCI_COLLection::getElem} * @link https://php.net/manual/en/function.ocicollgetelem.php * @param OCI_Collection $collection * @param int $index

    The element index. First index is 0.

    * @return mixed

    Returns FALSE if such element doesn't exist; NULL if element is NULL; string if element is column of a string datatype or number if element is numeric field.

    */ #[Deprecated(replacement: "OCI_COLLection::getElem", since: "5.4")] function ocicollgetelem(#[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $collection, $index) {} /** * (PHP 4 >= 4.0.6, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of {@see OCI_Collection::assignElem} * @link https://php.net/manual/en/function.ocicollassignelem.php * @param OCI_Collection $collection * @param $index

    The element index. First index is 0.

    * @param $value

    Can be a string or a number.

    * @return bool

    Returns TRUE on success or FALSE on failure.

    */ #[Deprecated(replacement: "OCI_Collection::assignElem", since: "5.4")] function ocicollassignelem(#[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $collection, $index, $value) {} /** * (PHP 4 >= 4.0.6, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see OCI_COLLection::size} * @link https://php.net/manual/en/function.ocicollsize.php * @param OCI_Collection $collection * @return int|false

    Returns the number of elements in the collection or FALSE on error.

    */ #[Deprecated(replacement: "OCI_COLLection::size", since: "5.4")] function ocicollsize(#[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $collection) {} /** * (PHP 4 >= 4.0.6, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see OCI_COLLection::max} * @link https://php.net/manual/en/function.ocicollmax.php * @param OCI_Collection $collection * @return int|false

    Returns the maximum number as an integer, or FALSE on errors. * If the returned value is 0, then the number of elements is not limited.

    */ #[Deprecated(replacement: "OCI_COLLection::max", since: "5.4")] function ocicollmax(#[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $collection) {} /** * (PHP 4 >= 4.0.6, PHP 5, PECL OCI8 >= 1.0.0)
    * Alias of * {@see OCI_Collection::trim} * @link https://php.net/manual/en/function.ocicolltrim.php * @param OCI_Collection $collection * @param int|float $number * @return bool Returns TRUE or FALSE on failure. */ #[Deprecated(replacement: "OCI_Collection::trim", since: "5.4")] function ocicolltrim(#[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $collection, $number) {} /** * (PHP 4 >= 4.0.6, PECL OCI8 1.0) * Writes a temporary large object * Alias of {@see OCI-Lob::writeTemporary()} * @link https://php.net/manual/en/function.ociwritetemporarylob.php * @param OCI_Lob|OCILob $lob_descriptor * @param string $data

    The data to write.

    * @param int $lob_type

    * Can be one of the following: *

      *
    • * OCI_TEMP_BLOB is used to create temporary BLOBs *
    • *
    • * OCI_TEMP_CLOB is used to create * temporary CLOBs *
    • *
    * @return bool

    Returns TRUE on success or FALSE on failure.

    */ #[Deprecated(replacement: "OCI-Lob::writeTemporary", since: "5.4")] function ociwritetemporarylob( #[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob_descriptor, $data, $lob_type = OCI_TEMP_CLOB ) {} /** * (PHP 4 >= 4.0.6, PECL OCI8 1.0) * Alias of {@see OCI-Lob::close()} * @link https://php.net/manual/en/function.ocicloselob.php * @param OCI_Lob|OCILob $lob_descriptor * @return bool

    Returns TRUE on success or FALSE on failure.

    */ #[Deprecated(replacement: "OCI-Lob::close()", since: "5.4")] function ocicloselob(#[LanguageLevelTypeAware(['8.0' => 'OCILob'], default: 'OCI_Lob')] $lob_descriptor) {} /** * (PHP 4 >= 4.0.6, PECL OCI8 1.0) * Alias of {@see OCI-Collection::assign()} * Assigns a value to the collection from another existing collection * @link https://php.net/manual/en/function.ocicollassign.php * @param OCI_Collection $to * @param OCI_Collection $from An instance of OCI-Collection. * @return bool

    Returns TRUE on success or FALSE on failure.

    */ #[Deprecated(replacement: "OCI-Collection::assign", since: "5.4")] function ocicollassign( #[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $to, #[LanguageLevelTypeAware(['8.0' => 'OCICollection'], default: 'OCI_Collection')] $from ) {} /** * See OCI_NO_AUTO_COMMIT. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_DEFAULT', 0); /** * Used with {@see oci_connect} to connect with * the SYSOPER privilege. The php.ini setting * oci8.privileged_connect * should be enabled to use this. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_SYSOPER', 4); /** * Used with {@see oci_connect} to connect with * the SYSDBA privilege. The php.ini setting * oci8.privileged_connect * should be enabled to use this. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_SYSDBA', 2); /** * Used with {@see oci_connect} for using * Oracles' External or OS authentication. Introduced in PHP * 5.3 and PECL OCI8 1.3.4. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_CRED_EXT', -2147483648); /** * Statement execution mode * for {@see oci_execute}. Use this mode if you * want meta data such as the column names but don't want to * fetch rows from the query. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_DESCRIBE_ONLY', 16); /** * Statement execution mode for {@see oci_execute} * call. Automatically commit changes when the statement has * succeeded. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_COMMIT_ON_SUCCESS', 32); /** * Statement execution mode * for {@see oci_execute}. The transaction is not * automatically committed when using this mode. For * readability in new code, use this value instead of the * older, equivalent OCI_DEFAULT constant. * Introduced in PHP 5.3.2 (PECL OCI8 1.4). * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_NO_AUTO_COMMIT', 0); /** * Obsolete. Statement fetch mode. Used when the application * knows in advance exactly how many rows it will be fetching. * This mode turns prefetching off for Oracle release 8 or * later mode. The cursor is canceled after the desired rows * are fetched which may result in reduced server-side * resource usage. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_EXACT_FETCH', 2); /** * Used with to set the seek position. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_SEEK_SET', 0); /** * Used with to set the seek position. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_SEEK_CUR', 1); /** * Used with to set the seek position. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_SEEK_END', 2); /** * Used with to free * buffers used. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_LOB_BUFFER_FREE', 1); /** * The same as OCI_B_BFILE. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_BFILEE', 114); /** * The same as OCI_B_CFILEE. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_CFILEE', 115); /** * The same as OCI_B_CLOB. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_CLOB', 112); /** * The same as OCI_B_BLOB. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_BLOB', 113); /** * The same as OCI_B_ROWID. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_RDD', 104); /** * The same as OCI_B_INT. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_INT', 3); /** * The same as OCI_B_NUM. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_NUM', 2); /** * The same as OCI_B_CURSOR. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_RSET', 116); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * CHAR. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_AFC', 96); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * VARCHAR2. * Also used with {@see oci_bind_by_name}. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_CHR', 1); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * VARCHAR. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_VCS', 9); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * VARCHAR2. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_AVC', 97); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * STRING. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_STR', 5); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * LONG VARCHAR. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_LVC', 94); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * FLOAT. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_FLT', 4); /** * Not supported. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_UIN', 68); /** * Used with {@see oci_bind_by_name} to bind LONG values. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_LNG', 8); /** * Used with {@see oci_bind_by_name} to bind LONG RAW values. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_LBI', 24); /** * The same as OCI_B_BIN. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_BIN', 23); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * LONG. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_ODT', 156); /** * Not supported. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_BDOUBLE', 22); /** * Not supported. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_BFLOAT', 21); /** * Used with {@see oci_bind_by_name} when binding * named data types. Note: in PHP < 5.0 it was called * OCI_B_SQLT_NTY. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_NTY', 108); /** * The same as OCI_B_NTY. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_NTY', 108); /** * Obsolete. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_SYSDATE', "SYSDATE"); /** * Used with {@see oci_bind_by_name} when binding * BFILEs. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_BFILE', 114); /** * Used with {@see oci_bind_by_name} when binding * CFILEs. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_CFILEE', 115); /** * Used with {@see oci_bind_by_name} when binding * CLOBs. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_CLOB', 112); /** * Used with {@see oci_bind_by_name} when * binding BLOBs. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_BLOB', 113); /** * Used with {@see oci_bind_by_name} when binding * ROWIDs. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_ROWID', 104); /** * Used with {@see oci_bind_by_name} when binding * cursors, previously allocated * with {@see oci_new_descriptor}. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_CURSOR', 116); /** * Used with {@see oci_bind_by_name} to bind RAW values. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_BIN', 23); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * INTEGER. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_INT', 3); /** * Used with {@see oci_bind_array_by_name} to bind arrays of * NUMBER. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_NUM', 2); /** * Default mode of {@see oci_fetch_all}. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_FETCHSTATEMENT_BY_COLUMN', 16); /** * Alternative mode of {@see oci_fetch_all}. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_FETCHSTATEMENT_BY_ROW', 32); /** * Used with {@see oci_fetch_all} and * {@see oci_fetch_array} to get results as an associative * array. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_ASSOC', 1); /** * Used with {@see oci_fetch_all} and * {@see oci_fetch_array} to get results as an * enumerated array. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_NUM', 2); /** * Used with {@see oci_fetch_all} and * {@see oci_fetch_array} to get results as an * array with both associative and number indices. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_BOTH', 3); /** * Used with {@see oci_fetch_array} to get empty * array elements if the row items value is NULL. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_RETURN_NULLS', 4); /** * Used with {@see oci_fetch_array} to get the * data value of the LOB instead of the descriptor. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_RETURN_LOBS', 8); /** * This flag tells {@see oci_new_descriptor} to * initialize a new FILE descriptor. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_DTYPE_FILE', 56); /** * This flag tells {@see oci_new_descriptor} to * initialize a new LOB descriptor. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_DTYPE_LOB', 50); /** * This flag tells {@see oci_new_descriptor} to * initialize a new ROWID descriptor. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_DTYPE_ROWID', 54); /** * The same as OCI_DTYPE_FILE. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_D_FILE', 56); /** * The same as OCI_DTYPE_LOB. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_D_LOB', 50); /** * The same as OCI_DTYPE_ROWID. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_D_ROWID', 54); /** * Used with * to indicate that a temporary CLOB should be created. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_TEMP_CLOB', 2); /** * Used with * to indicate that a temporary BLOB should be created. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_TEMP_BLOB', 1); /** * (PECL OCI8 >= 2.0.7)
    * The same as OCI_B_BOL. * @link https://php.net/manual/en/oci8.constants.php */ define('SQLT_BOL', 252); /** * (PECL OCI8 >= 2.0.7)
    * Used with {@see oci_bind_by_name} when * binding PL/SQL BOOLEAN. * @link https://php.net/manual/en/oci8.constants.php */ define('OCI_B_BOL', 252); // End of oci8 v.2.0.7 'true'], default: 'bool')] function sodium_crypto_generichash_update(string &$state, string $message): bool {} /** * Get the final hash * BLAKE2b * @link https://www.php.net/manual/en/function.sodium-crypto-generichash-final.php * @param string &$state * @param int $length * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_generichash_final( string &$state, int $length = 32 ): string {} /** * Secure password-based key derivation function * Argon2i * @link https://www.php.net/manual/en/function.sodium-crypto-pwhash.php * @param int $length * @param string $password * @param string $salt * @param int $opslimit * @param int $memlimit * @param int $algo [optional] * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_pwhash(int $length, string $password, string $salt, int $opslimit, int $memlimit, int $algo = SODIUM_CRYPTO_PWHASH_ALG_DEFAULT): string {} /** * Get a formatted password hash (for storage) * Argon2i * @link https://www.php.net/manual/en/function.sodium-crypto-pwhash-str.php * @param string $password * @param int $opslimit * @param int $memlimit * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_pwhash_str(string $password, int $opslimit, int $memlimit): string {} /** * Verify a password against a hash * Argon2i * @link https://www.php.net/manual/en/function.sodium-crypto-pwhash-str-verify.php * @param string $hash * @param string $password * @return bool * @throws SodiumException * @since 7.2 */ function sodium_crypto_pwhash_str_verify(string $hash, string $password): bool {} /** * Secure password-based key derivation function * Scrypt * @link https://www.php.net/manual/en/function.sodium-crypto-pwhash-scryptsalsa208sha256.php * @param int $length * @param string $password * @param string $salt * @param int $opslimit * @param int $memlimit * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_pwhash_scryptsalsa208sha256( int $length, string $password, string $salt, int $opslimit, int $memlimit, #[PhpStormStubsElementAvailable(from: '7.2', to: '7.4')] $alg = null ): string {} /** * Get a formatted password hash (for storage) * Scrypt * @link https://www.php.net/manual/en/function.sodium-crypto-pwhash-scryptsalsa208sha256-str.php * @param string $password * @param int $opslimit * @param int $memlimit * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_pwhash_scryptsalsa208sha256_str(string $password, int $opslimit, int $memlimit): string {} /** * Verify a password against a hash * Scrypt * @link https://www.php.net/manual/en/function.sodium-crypto-pwhash-scryptsalsa208sha256-str-verify * @param string $hash * @param string $password * @return bool * @since 7.2 */ function sodium_crypto_pwhash_scryptsalsa208sha256_str_verify(string $hash, string $password): bool {} /** * Elliptic Curve Diffie Hellman over Curve25519 * X25519 * @link https://www.php.net/manual/en/function.sodium-crypto-scalarmult.php * @param string $n * @param string $p * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_scalarmult(string $n, string $p): string {} /** * Authenticated secret-key encryption (encrypt) * Xsals20 + Poly1305 * @link https://www.php.net/manual/en/function.sodium-crypto-secretbox.php * @param string $message * @param string $nonce * @param string $key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_secretbox(string $message, string $nonce, string $key): string {} /** * Authenticated secret-key encryption (decrypt) * Xsals20 + Poly1305 * @link https://www.php.net/manual/en/function.sodium-crypto-secretbox-open.php * @param string $ciphertext * @param string $nonce * @param string $key * @return string|false * @throws SodiumException * @since 7.2 */ function sodium_crypto_secretbox_open(string $ciphertext, string $nonce, string $key): string|false {} /** * A short keyed hash suitable for data structures * SipHash-2-4 * @link https://www.php.net/manual/en/function.sodium-crypto-shorthash.php * @param string $message * @param string $key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_shorthash(string $message, string $key): string {} /** * Digital Signature * Ed25519 * @link https://www.php.net/manual/en/function.sodium-crypto-sign.php * @param string $message * @param string $secret_key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign(string $message, string $secret_key): string {} /** * Digital Signature (detached) * Ed25519 * @link https://www.php.net/manual/en/function.sodium-crypto-sign-detached.php * @param string $message * @param string $secret_key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_detached(string $message, string $secret_key): string {} /** * Convert an Ed25519 public key to an X25519 public key * @link https://www.php.net/manual/en/function.sodium-crypto-sign-ed25519-pk-to-curve25519.php * @param string $public_key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_ed25519_pk_to_curve25519(string $public_key): string {} /** * Convert an Ed25519 secret key to an X25519 secret key * @link https://www.php.net/manual/en/function.sodium-crypto-sign-ed25519-sk-to-curve25519.php * @param string $secret_key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_ed25519_sk_to_curve25519(string $secret_key): string {} /** * Generate an Ed25519 keypair for use with the crypto_sign API * @link https://www.php.net/manual/en/function.sodium-crypto-sign-keypair.php * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_keypair(): string {} /** * Create an Ed25519 keypair from an Ed25519 secret key + Ed25519 public key * @link https://www.php.net/manual/en/function.sodium-crypto-sign-keypair-from-secretkey-and-publickey.php * @param string $secret_key * @param string $public_key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_keypair_from_secretkey_and_publickey( string $secret_key, string $public_key ): string {} /** * Verify a signed message and return the plaintext * @link https://www.php.net/manual/en/function.sodium-crypto-sign-open.php * @param string $signed_message * @param string $public_key * @return string|false * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_open(string $signed_message, string $public_key): string|false {} /** * Get the public key from an Ed25519 keypair * @link https://www.php.net/manual/en/function.sodium-crypto-sign-publickey.php * @param string $key_pair * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_publickey(string $key_pair): string {} /** * Get the secret key from an Ed25519 keypair * @link https://www.php.net/manual/en/function.sodium-crypto-sign-secretkey.php * @param string $key_pair * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_secretkey(string $key_pair): string {} /** * Derive an Ed25519 public key from an Ed25519 secret key * @link https://www.php.net/manual/en/function.sodium-crypto-sign-publickey-from-secretkey.php * @param string $secret_key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_publickey_from_secretkey(string $secret_key): string {} /** * Derive an Ed25519 keypair for use with the crypto_sign API from a seed * @link https://www.php.net/manual/en/function.sodium-crypto-sign-seed-keypair.php * @param string $seed * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_seed_keypair(string $seed): string {} /** * Verify a detached signature * @link https://www.php.net/manual/en/function.sodium-crypto-sign-verify-detached.php * @param string $signature * @param string $message * @param string $public_key * @return bool * @throws SodiumException * @since 7.2 */ function sodium_crypto_sign_verify_detached(string $signature, string $message, string $public_key): bool {} /** * Create a keystream from a key and nonce * Xsalsa20 * @link https://www.php.net/manual/en/function.sodium-crypto-stream.php * @param int $length * @param string $nonce * @param string $key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_stream( int $length, string $nonce, string $key ): string {} /** * Encrypt a message using a stream cipher * Xsalsa20 * @link https://www.php.net/manual/en/function.sodium-crypto-stream-xor.php * @param string $message * @param string $nonce * @param string $key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_stream_xor( string $message, string $nonce, string $key ): string {} /** * Generate a string of random bytes * /dev/urandom * * @param int $length * @return string|false * @since 7.2 */ function sodium_randombytes_buf(int $length): string {} /** * Generate a 16-bit integer * /dev/urandom * * @return int * @since 7.2 */ function sodium_randombytes_random16(): int {} /** * Generate an unbiased random integer between 0 and a specified value * /dev/urandom * * @param int $upperBoundNonInclusive * @return int * @since 7.2 */ function sodium_randombytes_uniform(int $upperBoundNonInclusive): int {} /** * Convert to hex without side-chanels * @link https://www.php.net/manual/en/function.sodium-bin2hex.php * @param string $string * @return string * @throws SodiumException * @since 7.2 */ function sodium_bin2hex(string $string): string {} /** * Compare two strings in constant time * @link https://www.php.net/manual/en/function.sodium-compare.php * @param string $string1 * @param string $string2 * @return int * @throws SodiumException * @since 7.2 */ function sodium_compare(string $string1, string $string2): int {} /** * Convert from hex without side-chanels * @link https://www.php.net/manual/en/function.sodium-hex2bin.php * @param string $string * @param string $ignore * @return string * @throws SodiumException * @since 7.2 */ function sodium_hex2bin(string $string, string $ignore = ''): string {} /** * Increment a string in little-endian * @link https://www.php.net/manual/en/function.sodium-increment.php * @param string &$string * @return void * @throws SodiumException * @since 7.2 */ function sodium_increment(string &$string): void {} /** * Add the right operand to the left * @link https://www.php.net/manual/en/function.sodium-add.php * @param string &$string1 * @param string $string2 * @throws SodiumException * @since 7.2 */ function sodium_add(string &$string1, string $string2): void {} /** * Get the true major version of libsodium * @return int * @since 7.2 */ function sodium_library_version_major(): int {} /** * Get the true minor version of libsodium * @return int * @since 7.2 */ function sodium_library_version_minor(): int {} /** * Compare two strings in constant time * @link https://www.php.net/manual/en/function.sodium-memcmp.php * @param string $string1 * @param string $string2 * @return int * @throws SodiumException * @since 7.2 */ function sodium_memcmp(string $string1, string $string2): int {} /** * Wipe a buffer * @link https://www.php.net/manual/en/function.sodium-memzero.php * @param string &$string * @throws SodiumException * @since 7.2 */ function sodium_memzero(string &$string): void {} /** * Get the version string * * @return string * @since 7.2 */ function sodium_version_string(): string {} /** * Scalar multiplication of the base point and your key * @link https://www.php.net/manual/en/function.sodium-crypto-scalarmult-base * @param string $secret_key * @return string * @throws SodiumException * @since 7.2 */ function sodium_crypto_scalarmult_base( string $secret_key, #[PhpStormStubsElementAvailable(from: '7.2', to: '7.4')] $string_2 ): string {} /** * Creates a random key * * It is equivalent to calling random_bytes() but improves code clarity and can * prevent misuse by ensuring that the provided key length is always be correct. * * @since 7.2 * @see https://secure.php.net/manual/en/function.sodium-crypto-secretbox-keygen.php */ function sodium_crypto_secretbox_keygen(): string {} /** * Creates a random key * * It is equivalent to calling random_bytes() but improves code clarity and can * prevent misuse by ensuring that the provided key length is always be correct. * * @since 7.2 * @see https://secure.php.net/manual/en/function.sodium-crypto-aead-aes256gcm-keygen.php */ function sodium_crypto_aead_aes256gcm_keygen(): string {} /** * Creates a random key * It is equivalent to calling random_bytes() but improves code clarity and can * prevent misuse by ensuring that the provided key length is always be correct. * * @since 7.2 * @see https://secure.php.net/manual/en/function.sodium-crypto-aead-chacha20poly1305-keygen.php */ function sodium_crypto_aead_chacha20poly1305_keygen(): string {} /** * Creates a random key * * It is equivalent to calling random_bytes() but improves code clarity and can * prevent misuse by ensuring that the provided key length is always be correct. * * @since 7.2 * @see https://secure.php.net/manual/en/function.sodium-crypto-aead-chacha20poly1305-ietf-keygen.php */ function sodium_crypto_aead_chacha20poly1305_ietf_keygen(): string {} /** * @param string $ciphertext * @param string $additional_data * @param string $nonce * @param string $key * @return string|false * @throws SodiumException * @since 7.2 * @see https://www.php.net/manual/en/function.sodium-crypto-aead-xchacha20poly1305-ietf-decrypt.php */ function sodium_crypto_aead_xchacha20poly1305_ietf_decrypt(string $ciphertext, string $additional_data, string $nonce, string $key): string|false {} /** * @param string $message * @param string $additional_data * @param string $nonce * @param string $key * @return string * @throws SodiumException * @since 7.2 * https://www.php.net/manual/en/function.sodium-crypto-aead-xchacha20poly1305-ietf-encrypt.php */ function sodium_crypto_aead_xchacha20poly1305_ietf_encrypt(string $message, string $additional_data, string $nonce, string $key): string {} /** * @since 7.2 * @see https://www.php.net/manual/en/function.sodium-crypto-aead-xchacha20poly1305-ietf-keygen.php */ function sodium_crypto_aead_xchacha20poly1305_ietf_keygen(): string {} /** * @param string $password * @param int $opslimit * @param int $memlimit * @return bool * @since 7.2 * @see https://www.php.net/manual/en/function.sodium-crypto-pwhash-str-needs-rehash.php */ function sodium_crypto_pwhash_str_needs_rehash(string $password, int $opslimit, int $memlimit): bool {} /** * @since 7.2 * @see https://www.php.net/manual/en/function.sodium-crypto-secretstream-xchacha20poly1305-keygen.php */ function sodium_crypto_secretstream_xchacha20poly1305_keygen(): string {} /** * @param string $key * @return array * @throws SodiumException * @since 7.2 * @see https://www.php.net/manual/en/function.sodium-crypto-secretstream-xchacha20poly1305-init-push.php */ function sodium_crypto_secretstream_xchacha20poly1305_init_push(string $key): array {} #[PhpStormStubsElementAvailable('7.2')] function sodium_crypto_secretstream_xchacha20poly1305_push(string &$state, #[\SensitiveParameter] string $message, string $additional_data = "", int $tag = SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE): string {} /** * @param string $header * @param string $key * @return string * @throws SodiumException * @since 7.2 * @see https://www.php.net/manual/en/function.sodium-crypto-secretstream-xchacha20poly1305-init-pull.php */ function sodium_crypto_secretstream_xchacha20poly1305_init_pull(string $header, string $key): string {} #[PhpStormStubsElementAvailable('7.2')] function sodium_crypto_secretstream_xchacha20poly1305_pull(string &$state, string $ciphertext, string $additional_data = ""): array|false {} /** * @param string &$state * @throws SodiumException * @since 7.2 * @see https://www.php.net/manual/en/function.sodium-crypto-secretstream-xchacha20poly1305-rekey.php */ function sodium_crypto_secretstream_xchacha20poly1305_rekey(string &$state): void {} /** * @param string $string * @param int $id * @return string * @throws SodiumException * @since 7.2 * @see https://www.php.net/manual/en/function.sodium-bin2base64.php */ function sodium_bin2base64(string $string, int $id): string {} /** * @param string $string * @param int $id * @param string $ignore * @throws SodiumException * @since 7.2 * @see https://www.php.net/manual/en/function.sodium-base642bin.php * @return string */ function sodium_base642bin(string $string, int $id, string $ignore = ''): string {} class SodiumException extends Exception {} 'int'], default: '')] $revents) {} /** * Returns the loop responsible for the watcher. * * @return EvLoop Event loop object responsible for the watcher. */ public function getLoop() {} /** * Invokes the watcher callback with the given received events bit mask. * * @param int $revents Bit mask of watcher received events. */ public function invoke(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $revents) {} /** * Configures whether to keep the loop from returning. * * Configures whether to keep the loop from returning. With keepalive value set to FALSE the watcher won't keep * Ev::run() / EvLoop::run() from returning even though the watcher is active. * * Watchers have keepalive value TRUE by default. * * Clearing keepalive status is useful when returning from Ev::run() / EvLoop::run() just because of the watcher * is undesirable. It could be a long running UDP socket watcher or so. * * @param bool $value With keepalive value set to FALSE the watcher won't keep Ev::run() / EvLoop::run() from * returning even though the watcher is active. */ public function keepalive(#[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $value = true) {} /** * Sets new callback for the watcher. * * @param callable $callback void callback ([ object $watcher = NULL [, int $revents = NULL ]] ) */ public function setCallback(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback) {} /** * Starts the watcher. * * Marks the watcher as active. Note that only active watchers will receive events. */ public function start() {} /** * Stops the watcher. * * Marks the watcher as inactive. Note that only active watchers will receive events. */ public function stop() {} } /** * Class EvCheck * * EvPrepare and EvCheck watchers are usually used in pairs. EvPrepare watchers get invoked before the process blocks, * EvCheck afterwards. * * It is not allowed to call EvLoop::run() or similar methods or functions that enter the current event loop from either * EvPrepare or EvCheck watchers. Other loops than the current one are fine, however. The rationale behind this is that * one don't need to check for recursion in those watchers, i.e. the sequence will always be: EvPrepare -> blocking -> * EvCheck , so having a watcher of each kind they will always be called in pairs bracketing the blocking call. * * The main purpose is to integrate other event mechanisms into libev and their use is somewhat advanced. They could be * used, for example, to track variable changes, implement custom watchers, integrate net-snmp or a coroutine library * and lots more. They are also occasionally useful to cache some data and want to flush it before blocking. * * It is recommended to give EvCheck watchers highest( Ev::MAXPRI ) priority, to ensure that they are being run before * any other watchers after the poll (this doesn’t matter for EvPrepare watchers). * * Also, EvCheck watchers should not activate/feed events. While libev fully supports this, they might get executed * before other EvCheck watchers did their job. */ final class EvCheck extends EvWatcher { /** * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $priority = 0 ) {} /** * @param callable $callback * @param mixed $data * @param int $priority * @return EvCheck */ final public static function createStopped(mixed $callback, mixed $data = null, int $priority = 0) {} } /** * Class EvChild * * EvChild watchers trigger when the process receives a SIGCHLD in response to some child status changes (most typically * when a child dies or exits). It is permissible to install an EvChild watcher after the child has been forked (which * implies it might have already exited), as long as the event loop isn't entered(or is continued from a watcher), i.e. * forking and then immediately registering a watcher for the child is fine, but forking and registering a watcher a few * event loop iterations later or in the next callback invocation is not. * * It is allowed to register EvChild watchers in the default loop only. */ final class EvChild extends EvWatcher { /** * @var int The process ID this watcher watches out for, or 0, meaning any process ID. */ #[Immutable] public $pid; /** * @var int The process ID that detected a status change. */ #[Immutable] public $rpid; /** * @var int The process exit status caused by rpid. */ #[Immutable] public $rstatus; /** * Constructs the EvChild watcher object. * * Call the callback when a status change for process ID pid (or any PID if pid is 0) has been received (a status * change happens when the process terminates or is killed, or, when trace is TRUE, additionally when it is stopped * or continued). In other words, when the process receives a SIGCHLD, Ev will fetch the outstanding exit/wait * status for all changed/zombie children and call the callback. * * It is valid to install a child watcher after an EvChild has exited but before the event loop has started its next * iteration. For example, first one calls fork , then the new child process might exit, and only then an EvChild * watcher is installed in the parent for the new PID . * * You can access both exit/tracing status and pid by using the rstatus and rpid properties of the watcher object. * * The number of PID watchers per PID is unlimited. All of them will be called. * * The EvChild::createStopped() method doesn't start(activate) the newly created watcher. * * @param int $pid Wait for status changes of process PID(or any process if PID is specified as 0 ). * @param bool $trace If FALSE, only activate the watcher when the process terminates. Otherwise(TRUE) additionally * activate the watcher when the process is stopped or continued. * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $pid, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $trace, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $priority = 0 ) {} /** * Create instance of a stopped EvCheck watcher. * * The same as EvChild::__construct() , but doesn't start the watcher automatically. * * @param int $pid Wait for status changes of process PID(or any process if PID is specified as 0 ). * @param bool $trace If FALSE, only activate the watcher when the process terminates. Otherwise(TRUE) additionally * activate the watcher when the process is stopped or continued. * @param callable $callback * @param mixed $data * @param int $priority * * @return EvChild */ final public static function createStopped(int $pid, bool $trace, mixed $callback, mixed $data = null, int $priority = 0) {} /** * Configures the watcher * * @param int $pid Wait for status changes of process PID(or any process if PID is specified as 0 ). * @param bool $trace If FALSE, only activate the watcher when the process terminates. Otherwise(TRUE) additionally * activate the watcher when the process is stopped or continued. */ public function set( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $pid, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $trace ) {} } /** * Class EvEmbed * * Used to embed one event loop into another. */ final class EvEmbed extends EvWatcher { /** * @var EvLoop The embedded loop */ #[Immutable] public $embed; /** * Constructs the EvEmbed object. * * This is a rather advanced watcher type that lets to embed one event loop into another(currently only IO events * are supported in the embedded loop, other types of watchers might be handled in a delayed or incorrect fashion * and must not be used). * * See the libev documentation for details. * * This watcher is most useful on BSD systems without working kqueue to still be able to handle a large number of * sockets. * * @param EvLoop $other The loop to embed, this loop must be embeddable(see Ev::embeddableBackends()). * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct( EvLoop $other, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $priority = 0 ) {} /** * Configures the watcher. * * @param EvLoop $other The loop to embed, this loop must be embeddable(see Ev::embeddableBackends()). */ public function set(EvLoop $other) {} /** * Make a single, non-blocking sweep over the embedded loop. */ public function sweep() {} /** * Create stopped EvEmbed watcher object * * The same as EvEmbed::__construct() , but doesn't start the watcher automatically. * * @param EvLoop $other The loop to embed, this loop must be embeddable(see Ev::embeddableBackends()). * @param callable $callback * @param mixed $data * @param int $priority * * @return EvEmbed */ final public static function createStopped(EvLoop $other, mixed $callback, mixed $data = null, int $priority = 0) {} } /** * Class EvIo * * EvIo watchers check whether a file descriptor(or socket, or a stream castable to numeric file descriptor) is readable * or writable in each iteration of the event loop, or, more precisely, when reading would not block the process and * writing would at least be able to write some data. This behaviour is called level-triggering because events are kept * receiving as long as the condition persists. To stop receiving events just stop the watcher. * * The number of read and/or write event watchers per fd is unlimited. Setting all file descriptors to non-blocking mode * is also usually a good idea (but not required). * * Another thing to watch out for is that it is quite easy to receive false readiness notifications, i.e. the callback * might be called with Ev::READ but a subsequent read() will actually block because there is no data. It is very easy * to get into this situation. Thus it is best to always use non-blocking I/O: An extra read() returning EAGAIN (or * similar) is far preferable to a program hanging until some data arrives. * * If for some reason it is impossible to run the fd in non-blocking mode, then separately re-test whether a file * descriptor is really ready. Some people additionally use SIGALRM and an interval timer, just to be sure they won't * block infinitely. * * Always consider using non-blocking mode. */ final class EvIo extends EvWatcher { /** * @var resource A stream opened with fopen() or similar functions, numeric file descriptor, or socket. */ #[Immutable] public $fd; /** * @var int Ev::READ and/or Ev::WRITE. See the bit masks. */ #[Immutable] #[ExpectedValues(flags: [Ev::READ, Ev::WRITE])] public $events; /** * Constructs EvIo watcher object. * * Constructs EvIo watcher object and starts the watcher automatically. * * @param resource $fd A stream opened with fopen() or similar functions, numeric file descriptor, or socket. * @param int $events Ev::READ and/or Ev::WRITE. See the bit masks. * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $fd, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $events, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $priority = 0 ) {} /** * Configures the watcher. * * @param resource $fd A stream opened with fopen() or similar functions, numeric file descriptor, or socket. * @param int $events Ev::READ and/or Ev::WRITE. See the bit masks. */ public function set( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $fd, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $events ) {} /** * Create stopped EvIo watcher object. * * The same as EvIo::__construct() , but doesn't start the watcher automatically. * * @param resource $fd A stream opened with fopen() or similar functions, numeric file descriptor, or socket. * @param int $events Ev::READ and/or Ev::WRITE. See the bit masks. * @param callable $callback * @param mixed $data * @param int $priority * * @return EvIo */ final public static function createStopped(mixed $fd, int $events, mixed $callback, mixed $data = null, int $priority = 0) {} } /** * Class EvPeriodic * * Periodic watchers are also timers of a kind, but they are very versatile. * * Unlike EvTimer, EvPeriodic watchers are not based on real time (or relative time, the physical time that passes) but * on wall clock time (absolute time, calendar or clock). The difference is that wall clock time can run faster or * slower than real time, and time jumps are not uncommon (e.g. when adjusting it). * * EvPeriodic watcher can be configured to trigger after some specific point in time. For example, if an EvPeriodic * watcher is configured to trigger "in 10 seconds" (e.g. EvLoop::now() + 10.0 , i.e. an absolute time, not a delay), * and the system clock is reset to January of the previous year , then it will take a year or more to trigger the event * (unlike an EvTimer , which would still trigger roughly 10 seconds after starting it as it uses a relative timeout). * * As with timers, the callback is guaranteed to be invoked only when the point in time where it is supposed to trigger * has passed. If multiple timers become ready during the same loop iteration then the ones with earlier time-out values * are invoked before ones with later time-out values (but this is no longer true when a callback calls EvLoop::run() * recursively). */ final class EvPeriodic extends EvWatcher { /** * @var float When repeating, this contains the offset value, otherwise this is the absolute point in time (the * offset value passed to EvPeriodic::set(), although libev might modify this value for better numerical * stability). */ public $offset; /** * @var float The current interval value. Can be modified any time, but changes only take effect when the periodic * timer fires or EvPeriodic::again() is being called. */ public $interval; /** * Constructs EvPeriodic watcher object. * * Constructs EvPeriodic watcher object and starts it automatically. EvPeriodic::createStopped() method creates * stopped periodic watcher. * * @param float $offset When repeating, this contains the offset value, otherwise this is the absolute point in * time (the offset value passed to EvPeriodic::set(), although libev might modify this value for better * numerical stability). * @param float $interval The current interval value. Can be modified any time, but changes only take effect when * the periodic timer fires or EvPeriodic::again() is being called. * @param null|callable $reschedule_cb If set, tt must return the next time to trigger, based on the passed time value * (that is, the lowest time value larger than or equal to the second argument). It will usually be called just * before the callback will be triggered, but might be called at other times, too. * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $offset, #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $interval, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $reschedule_cb, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $priority = 0 ) {} /** * Simply stops and restarts the periodic watcher again. * * Simply stops and restarts the periodic watcher again. This is only useful when attributes are changed. * * @return void */ public function again() {} /** * Returns the absolute time that this watcher is supposed to trigger next. * * When the watcher is active, returns the absolute time that this watcher is supposed to trigger next. This is not * the same as the offset argument to EvPeriodic::set() or EvPeriodic::__construct(), but indeed works even in * interval mode. * * @return float Rhe absolute time this watcher is supposed to trigger next in seconds. */ public function at() {} /** * Create a stopped EvPeriodic watcher * * Create EvPeriodic object. Unlike EvPeriodic::__construct() this method doesn't start the watcher automatically. * * @param float $offset When repeating, this contains the offset value, otherwise this is the absolute point in * time (the offset value passed to EvPeriodic::set(), although libev might modify this value for better * numerical stability). * @param float $interval The current interval value. Can be modified any time, but changes only take effect when * the periodic timer fires or EvPeriodic::again() is being called. * @param null|callable $reschedule_cb If set, tt must return the next time to trigger, based on the passed time value * (that is, the lowest time value larger than or equal to the second argument). It will usually be called just * before the callback will be triggered, but might be called at other times, too. * @param callable $callback * @param mixed $data * @param int $priority * * @return EvPeriodic */ final public static function createStopped(float $offset, float $interval, mixed $reschedule_cb, mixed $callback, mixed $data = null, int $priority = 0) {} /** * Configures the watcher * @param float $offset The same meaning as for {@see EvPeriodic::__construct} * @param float $interval The same meaning as for {@see EvPeriodic::__construct} * @param null|callable $reschedule_cb The same meaning as for {@see EvPeriodic::__construct} * @return void */ public function set( #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $offset, #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $interval, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $reschedule_cb = null ) {} } /** * Class EvPrepare * * EvPrepare and EvCheck watchers are usually used in pairs. EvPrepare watchers get invoked before the process blocks, * EvCheck afterwards. * * It is not allowed to call EvLoop::run() or similar methods or functions that enter the current event loop from either * EvPrepare or EvCheck watchers. Other loops than the current one are fine, however. The rationale behind this is that * one don't need to check for recursion in those watchers, i.e. the sequence will always be: EvPrepare -> blocking -> * EvCheck, so having a watcher of each kind they will always be called in pairs bracketing the blocking call. * * The main purpose is to integrate other event mechanisms into libev and their use is somewhat advanced. They could be * used, for example, to track variable changes, implement custom watchers, integrate net-snmp or a coroutine library * and lots more. They are also occasionally useful to cache some data and want to flush it before blocking. * * It is recommended to give EvCheck watchers highest (Ev::MAXPRI) priority, to ensure that they are being run before * any other watchers after the poll (this doesn’t matter for EvPrepare watchers). * * Also, EvCheck watchers should not activate/feed events. While libev fully supports this, they might get executed * before other EvCheck watchers did their job. */ final class EvPrepare extends EvWatcher { /** * Constructs EvPrepare watcher object. * * Constructs EvPrepare watcher object and starts the watcher automatically. If you need a stopped watcher, consider * using EvPrepare::createStopped(). * * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $priority = 0 ) {} /** * Creates a stopped instance of EvPrepare watcher. * * Creates a stopped instance of EvPrepare watcher. Unlike EvPrepare::__construct(), this method doesn't start the * watcher automatically. * * @param callable $callback * @param mixed $data * @param int $priority * * @return EvPrepare */ final public static function createStopped(mixed $callback, mixed $data = null, int $priority = 0) {} } /** * Class EvSignal * * EvSignal watchers will trigger an event when the process receives a specific signal one or more times. Even though * signals are very asynchronous, libev will try its best to deliver signals synchronously, i.e. as part of the normal * event processing, like any other event. * * There is no limit for the number of watchers for the same signal, but only within the same loop, i.e. one can watch * for SIGINT in the default loop and for SIGIO in another loop, but it is not allowed to watch for SIGINT in both the * default loop and another loop at the same time. At the moment, SIGCHLD is permanently tied to the default loop. * * If possible and supported, libev will install its handlers with SA_RESTART (or equivalent) behaviour enabled, so * system calls should not be unduly interrupted. In case of a problem with system calls getting interrupted by signals, * all the signals can be blocked in an EvCheck watcher and unblocked in a EvPrepare watcher. */ final class EvSignal extends EvWatcher { /** * @var int Signal number. See the constants exported by pcntl extension. See also signal(7) man page. */ #[Immutable] public $signum; /** * Constructs EvSignal watcher object * * @param int $signum Signal number. See the constants exported by pcntl extension. See also signal(7) man page. * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $signum, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $priority = 0 ) {} /** * Configures the watcher. * * @param int $signum Signal number. See the constants exported by pcntl extension. See also signal(7) man page. */ public function set(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $signum) {} /** * Creates a stopped instance of EvSignal watcher. * * Creates a stopped instance of EvSignal watcher. Unlike EvPrepare::__construct(), this method doesn't start the * watcher automatically. * * @param int $signum Signal number. See the constants exported by pcntl extension. See also signal(7) man page. * @param callable $callback * @param mixed $data * @param int $priority * * @return EvSignal */ final public static function createStopped(int $signum, mixed $callback, mixed $data = null, int $priority = 0) {} } /** * Class EvStat * * EvStat monitors a file system path for attribute changes. It calls stat() on that path in regular intervals (or when * the OS signals it changed) and sees if it changed compared to the last time, invoking the callback if it did. * * The path does not need to exist: changing from "path exists" to "path does not exist" is a status change like any * other. The condition "path does not exist" is signified by the 'nlink' item being 0 (returned by EvStat::attr() * method). * * The path must not end in a slash or contain special components such as '.' or '..'. The path should be absolute: if * it is relative and the working directory changes, then the behaviour is undefined. * * Since there is no portable change notification interface available, the portable implementation simply calls stat() * regularly on the path to see if it changed somehow. For this case a recommended polling interval can be specified. If * one specifies a polling interval of 0.0 (highly recommended) then a suitable, unspecified default value will be used * (which could be expected to be around 5 seconds, although this might change dynamically). libev will also impose a * minimum interval which is currently around 0.1 , but that’s usually overkill. * * This watcher type is not meant for massive numbers of EvStat watchers, as even with OS-supported change * notifications, this can be resource-intensive. */ final class EvStat extends EvWatcher { /** * @var float Hint on how quickly a change is expected to be detected and should normally be * specified as 0.0 to let libev choose a suitable value. */ #[Immutable] public $interval; /** * @var string The path to wait for status changes on. */ #[Immutable] public $path; /** * Constructs EvStat watcher object. * * Constructs EvStat watcher object and starts the watcher automatically. * * @param string $path The path to wait for status changes on. * @param float $interval Hint on how quickly a change is expected to be detected and should normally be specified * as 0.0 to let libev choose a suitable value. * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $path, #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $interval, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $priority = 0 ) {} /** * @return array The values most recently detect by Ev (without actual stat'ing). See stat(2) man page for details. */ public function attr() {} /** * @return array Just like EvStat::attr() , but returns the previous set of values. */ public function prev() {} /** * Configures the watcher. * * @param string $path The path to wait for status changes on. * @param float $interval Hint on how quickly a change is expected to be detected and should normally be specified * as 0.0 to let libev choose a suitable value. */ public function set( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $path, #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $interval ) {} /** * Initiates the stat call. * * Initiates the stat call(updates internal cache). It stats (using lstat) the path specified in the watcher and * sets the internal cache to the values found. * * @return bool TRUE if path exists. Otherwise FALSE. */ public function stat() {} /** * Create a stopped EvStat watcher object. * * Creates EvStat watcher object, but doesn't start it automatically (unlike EvStat::__construct()). * * @param string $path The path to wait for status changes on. * @param float $interval Hint on how quickly a change is expected to be detected and should normally be specified * as 0.0 to let libev choose a suitable value. * @param callable $callback * @param mixed $data * @param int $priority * * @return EvStat */ final public static function createStopped(string $path, float $interval, mixed $callback, mixed $data = null, int $priority = 0) {} } /** * Class EvTimer * * EvTimer watchers are simple relative timers that generate an event after a given time, and optionally repeating in * regular intervals after that. * * The timers are based on real time, that is, if one registers an event that times out after an hour and resets the * system clock to January last year, it will still time out after( roughly) one hour. "Roughly" because detecting time * jumps is hard, and some inaccuracies are unavoidable. * * The callback is guaranteed to be invoked only after its timeout has passed (not at, so on systems with very * low-resolution clocks this might introduce a small delay). If multiple timers become ready during the same loop * iteration then the ones with earlier time-out values are invoked before ones of the same priority with later time-out * values (but this is no longer true when a callback calls EvLoop::run() recursively). * * The timer itself will do a best-effort at avoiding drift, that is, if a timer is configured to trigger every 10 * seconds, then it will normally trigger at exactly 10 second intervals. If, however, the script cannot keep up with * the timer (because it takes longer than those 10 seconds to do) the timer will not fire more than once per event loop * iteration. */ final class EvTimer extends EvWatcher { /** * @var float If repeat is 0.0, then it will automatically be stopped once the timeout is reached. If it is * positive, then the timer will automatically be configured to trigger again every repeat seconds later, until * stopped manually. */ public $repeat; /** * @var float The remaining time until a timer fires. If the timer is active, then this time is relative to the * current event loop time, otherwise it's the timeout value currently configured. * * That is, after instantiating an EvTimer with an after value of 5.0 and repeat value of 7.0, remaining * returns 5.0. When the timer is started and one second passes, remaining will return 4.0 . When the timer * expires and is restarted, it will return roughly 7.0 (likely slightly less as callback invocation takes some * time too), and so on. */ public $remaining; /** * Constructs an EvTimer watcher object. * * @param float $after Configures the timer to trigger after $after seconds. * @param float $repeat If repeat is 0.0, then it will automatically be stopped once the timeout is reached. If it * is positive, then the timer will automatically be configured to trigger again every repeat seconds later, * until stopped manually. * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $after, #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $repeat, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $callback, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $priority = 0 ) {} /** * Restarts the timer watcher. * * This will act as if the timer timed out and restart it again if it is repeating. The exact semantics are: * * - if the timer is pending, its pending status is cleared. * - if the timer is started but non-repeating, stop it (as if it timed out). * - if the timer is repeating, either start it if necessary (with the repeat value), or reset the running timer to * the repeat value. */ public function again() {} /** * Configures the watcher. * * @param float $after Configures the timer to trigger after $after seconds. * @param float $repeat If repeat is 0.0, then it will automatically be stopped once the timeout is reached. If it * is positive, then the timer will automatically be configured to trigger again every repeat seconds later, * until stopped manually. */ public function set( #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $after, #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $repeat ) {} /** * Creates a stopped EvTimer watcher object. * * @param float $after Configures the timer to trigger after $after seconds. * @param float $repeat If repeat is 0.0, then it will automatically be stopped once the timeout is reached. If it * is positive, then the timer will automatically be configured to trigger again every repeat seconds later, * until stopped manually. * @param callable $callback * @param mixed $data * @param int $priority * * @return EvTimer */ final public static function createStopped(float $after, float $repeat, mixed $callback, mixed $data = null, int $priority = 0) {} } /** * Class EvIdle * * EvIdle watchers trigger events when no other events of the same or higher priority are pending (EvPrepare, EvCheck * and other EvIdle watchers do not count as receiving events). * * Thus, as long as the process is busy handling sockets or timeouts (or even signals) of the same or higher priority it * will not be triggered. But when the process is idle (or only lower-priority watchers are pending), the EvIdle * watchers are being called once per event loop iteration - until stopped, that is, or the process receives more events * and becomes busy again with higher priority stuff. * * Apart from keeping the process non-blocking (which is a useful on its own sometimes), EvIdle watchers are a good * place to do "pseudo-background processing", or delay processing stuff to after the event loop has handled all * outstanding events. * * The most noticeable effect is that as long as any idle watchers are active, the process will not block when waiting * for new events. */ final class EvIdle extends EvWatcher { /** * Constructs an EvIdle instance. * * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct(mixed $callback, mixed $data = null, int $priority = 0) {} /** * Creates a stopped EvIdle instance. * * @param callable $callback * @param mixed $data * @param int $priority * * @return EvIdle */ final public static function createStopped(mixed $callback, mixed $data = null, int $priority = 0) {} } /** * Class EvFork * * Fork watchers are called when a fork() was detected (usually because whoever signalled libev about it by calling * EvLoop::fork()). The invocation is done before the event loop blocks next and before EvCheck watchers are being * called, and only in the child after the fork. Note that if someone calls EvLoop::fork() in the wrong process, the * fork handlers will be invoked, too. */ final class EvFork extends EvWatcher { /** * Constructs an EvFork instance. * * @param callable $callback * @param mixed $data * @param int $priority */ public function __construct(EvLoop $loop, mixed $callback, mixed $data = null, int $priority = 0) {} /** * Creates a stopped EvFork instance. * * @param callable $callback * @param mixed $data * @param int $priority * * @return EvFork */ final public static function createStopped(EvLoop $loop, mixed $callback, mixed $data = null, int $priority = 0) {} } /** * Class EvLoop * * Represents an event loop that is always distinct from the default loop. Unlike the default loop, it cannot handle * EvChild watchers. * * Having threads we have to create a loop per thread, and use the the default loop in the parent thread. * * The default event loop is initialized automatically by Ev. It is accessible via methods of the Ev class, or via * EvLoop::defaultLoop() method. */ final class EvLoop { /** * @var int The Ev::BACKEND_* flag indicating the event backend in use. */ #[Immutable] #[ExpectedValues(flags: [Ev::BACKEND_ALL, Ev::BACKEND_DEVPOLL, Ev::BACKEND_EPOLL, Ev::BACKEND_KQUEUE, Ev::BACKEND_MASK, Ev::BACKEND_POLL, Ev::BACKEND_PORT, Ev::BACKEND_SELECT])] public $backend; /** * @var bool TRUE if it is the default event loop. */ #[Immutable] public $is_default_loop; /** * @var mixed Custom data attached to the loop. */ public $data; /** * @var int The current iteration count of the loop. See Ev::iteration(). */ public $iteration; /** * @var int The number of pending watchers. 0 indicates that there are no watchers pending. */ public $pending; /** * @var float Higher io_interval allows libev to spend more time collecting EvIo events, so more events can be * handled per iteration, at the cost of increasing latency. Timeouts (both EvPeriodic and EvTimer) will not be * affected. Setting this to a non-zero value will introduce an additional sleep() call into most loop * iterations. The sleep time ensures that libev will not poll for EvIo events more often than once per this * interval, on average. Many programs can usually benefit by setting the io_interval to a value near 0.1, * which is often enough for interactive servers (not for games). It usually doesn't make much sense to set it * to a lower value than 0.01, as this approaches the timing granularity of most systems. */ public $io_interval; /** * @var float Higher timeout_interval allows libev to spend more time collecting timeouts, at the expense of * increased latency/jitter/inexactness (the watcher callback will be called later). EvIo watchers will not be * affected. Setting this to a non-null value will not introduce any overhead in libev. */ public $timeout_interval; /** * @var int The recursion depth. */ public $depth; /** * @param int $flags * @param mixed $data * @param float $io_interval * @param float $timeout_interval */ public function __construct(int $flags = Ev::FLAG_AUTO, mixed $data = null, float $io_interval = 0.0, float $timeout_interval = 0.0) {} /** * Returns an integer describing the backend used by libev. * * @return int An integer describing the backend used by libev. See Ev::backend(). */ public function backend() {} /** * Creates EvCheck object associated with the current event loop instance. * * @param callable $callback * @param mixed $data * @param int $priority * @return EvCheck */ final public function check(callable $callback, $data = null, $priority = 0) {} /** * Creates EvChild object associated with the current event loop instance; * @link https://www.php.net/manual/en/evloop.child.php * @param int $pid * @param bool $trace * @param callable $callback * @param mixed $data * @param int $priority * @return EvChild */ final public function child(int $pid, bool $trace, mixed $callback, mixed $data = null, int $priority = 0) {} /** * Creates EvEmbed object associated with the current event loop instance. * * @param EvLoop $other * @param callable $callback * @param mixed $data * @param int $priority * @return EvEmbed */ final public function embed(EvLoop $other, callable $callback, $data = null, $priority = 0) {} /** * Creates EvFork object associated with the current event loop instance. * * @param callable $callback * @param mixed $data * @param int $priority * @return EvFork */ final public function fork(callable $callback, $data = null, $priority = 0) {} /** * Creates EvIdle object associated with the current event loop instance. * * @param callable $callback * @param null $data * @param int $priority * @return EvIdle */ final public function idle(mixed $callback, mixed $data = null, int $priority = 0) {} /** * Invoke all pending watchers while resetting their pending state. */ public function invokePending() {} /** * Creates EvIo object associated with the current event loop instance. * * @param resource $fd * @param int $events * @param callable $callback * @param mixed $data * @param int $priority * @return EvIo */ final public function io(mixed $fd, int $events, mixed $callback, mixed $data = null, int $priority = 0) {} /** * Must be called after a fork. * * Must be called after a fork in the child, before entering or continuing the event loop. An alternative is to use * Ev::FLAG_FORKCHECK which calls this function automatically, at some performance loss (refer to the libev * documentation). */ public function loopFork() {} /** * Returns the current "event loop time". * * Returns the current "event loop time", which is the time the event loop received events and started processing * them. This timestamp does not change as long as callbacks are being processed, and this is also the base time * used for relative timers. You can treat it as the timestamp of the event occurring (or more correctly, libev * finding out about it). * * @return float Time of the event loop in (fractional) seconds. */ public function now() {} /** * Establishes the current time by querying the kernel, updating the time returned by Ev::now in the progress. * * Establishes the current time by querying the kernel, updating the time returned by Ev::now() in the progress. * This is a costly operation and is usually done automatically within Ev::run(). * * This method is rarely useful, but when some event callback runs for a very long time without entering the event * loop, updating libev's consideration of the current time is a good idea. */ public function nowUpdate() {} /** * Creates EvPeriodic object associated with the current event loop instance. * * @param float $offset * @param float $interval * @param callable $reschedule_cb * @param callable $callback * @param mixed $data * @param int $priority */ final public function periodic(float $offset, float $interval, mixed $reschedule_cb, mixed $callback, mixed $data = null, int $priority = 0) {} /** * Creates EvPrepare object associated with the current event loop instance. * * @param callable $callback * @param mixed $data * @param int $priority */ final public function prepare(callable $callback, $data = null, $priority = 0) {} /** * Resume previously suspended default event loop. * * EvLoop::suspend() and EvLoop::resume() methods suspend and resume a loop correspondingly. */ public function resume() {} /** * Begin checking for events and calling callbacks for the loop. * * Begin checking for events and calling callbacks for the current event loop. Returns when a callback calls * Ev::stop() method, or the flags are nonzero (in which case the return value is true) or when there are no active * watchers which reference the loop (EvWatcher::keepalive() is TRUE), in which case the return value will be FALSE. * The return value can generally be interpreted as if TRUE, there is more work left to do. * * @param int $flags One of the Ev::RUN_* flags. */ public function run(int $flags = Ev::FLAG_AUTO) {} /** * Creates EvSignal object associated with the current event loop instance. * * @param int $signum * @param callable $callback * @param mixed $data * @param int $priority * @return EvSignal */ final public function signal(int $signum, mixed $callback, mixed $data = null, int $priority = 0) {} /** * Creates EvStats object associated with the current event loop instance. * * @param string $path * @param float $interval * @param callable $callback * @param mixed $data * @param int $priority * @return EvStat */ final public function stat(string $path, float $interval, mixed $callback, mixed $data = null, int $priority = 0) {} /** * Stops the event loop. * * @param int $how One of the Ev::BREAK_* flags. */ public function stop(int $how = Ev::BREAK_ALL) {} /** * Suspend the loop. * * EvLoop::suspend() and EvLoop::resume() methods suspend and resume a loop correspondingly. */ public function suspend() {} /** * Creates EvTimer object associated with the current event loop instance. * * @param float $after * @param float $repeat * @param callable $callback * @param mixed $data * @param int $priority * @return EvTimer */ final public function timer(float $after, float $repeat, mixed $callback, mixed $data = null, int $priority = 0) {} /** * Performs internal consistency checks (for debugging). * * Performs internal consistency checks (for debugging libev) and abort the program if any data structures were * found to be corrupted. */ public function verify() {} /** * Returns or creates the default event loop. * * If the default event loop is not created, EvLoop::defaultLoop() creates it with the specified parameters. * Otherwise, it just returns the object representing previously created instance ignoring all the parameters. * * @param int $flags * @param mixed $data * @param float $io_interval * @param float $timeout_interval * @return EvLoop */ public static function defaultLoop( int $flags = Ev::FLAG_AUTO, mixed $data = null, float $io_interval = 0.0, float $timeout_interval = 0.0 ): EvLoop {} } version: 1.0 failThreshold: 100 profile: path: Inspections.xml exclude: - name: PhpInconsistentReturnPointsInspection - name: PhpTooManyParametersInspection - name: PhpUnnecessaryDoubleQuotesInspection - name: PhpMissingParentCallCommonInspection - name: PhpMissingParentCallMagicInspection - name: PhpMissingParentConstructorInspection - name: PhpMissingReturnTypeInspection - name: PhpMissingParamTypeInspection - name: PhpDefineCanBeReplacedWithConstInspection - name: PhpReturnDocTypeMismatchInspection - name: PhpDocRedundantThrowsInspection - name: PhpMissingStrictTypesDeclarationInspection - name: PhpUnused paths: - aerospike - amqp - apache - apcu - ast - bcmath - blackfire - bz2 - calendar - cassandra - com_dotnet - Core - couchbase - couchbase_v2 - crypto - ctype - cubrid - curl - date - dba - decimal - dio - dom - ds - enchant - Ev - event - exif - expect - fann - FFI - ffmpeg - fileinfo - filter - fpm - ftp - gd - gearman - geoip - geos - gettext - gmagick - gmp - gnupg - grpc - hash - http - ibm_db2 - iconv - igbinary - imagick - imap - inotify - interbase - intl - json - judy - ldap - leveldb - libevent - libsodium - libvirt-php - libxml - lua - LuaSandbox - lzf - mailparse - mapscript - mbstring - mcrypt - memcache - memcached - meminfo - meta - ming - mongo - mongodb - mosquitto-php - mqseries - msgpack - mssql - mysql - mysql_xdevapi - mysqli - ncurses - newrelic - oauth - oci8 - odbc - openssl - parallel - Parle - pcntl - pcov - pcre - pdflib - PDO - pdo_ibm - pdo_mysql - pdo_pgsql - pdo_sqlite - pgsql - Phar - phpdbg - posix - pq - pspell - pthreads - radius - rar - rdkafka - readline - recode - redis - Reflection - regex - rpminfo - rrd - SaxonC - session - shmop - SimpleXML - snmp - soap - sockets - sodium - solr - SPL - SplType - SQLite - sqlite3 - sqlsrv - ssh2 - standard - stats - stomp - suhosin - superglobals - svm - svn - sybase - sync - sysvmsg - sysvsem - sysvshm - tidy - tokenizer - uopz - uuid - uv - v8js - vendor - wddx - win32service - winbinder - wincache - xcache - xdebug - xdiff - xhprof - xlswriter - xml - xmlreader - xmlrpc - xmlwriter - xsl - xxtea - yaf - yaml - yar - zend - Zend OPcache - ZendCache - ZendDebugger - ZendUtils - zip - zlib - zmp - zmq - zookeeper - zstd Enables or disables payload compression. When enabled, * item values longer than a certain threshold (currently 100 bytes) will be * compressed during storage and decompressed during retrieval * transparently.

    *

    Type: boolean, default: TRUE.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_COMPRESSION = -1001; public const OPT_COMPRESSION_TYPE = -1004; /** *

    This can be used to create a "domain" for your item keys. The value * specified here will be prefixed to each of the keys. It cannot be * longer than 128 characters and will reduce the * maximum available key size. The prefix is applied only to the item keys, * not to the server keys.

    *

    Type: string, default: "".

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_PREFIX_KEY = -1002; /** *

    * Specifies the serializer to use for serializing non-scalar values. * The valid serializers are Memcached::SERIALIZER_PHP * or Memcached::SERIALIZER_IGBINARY. The latter is * supported only when memcached is configured with * --enable-memcached-igbinary option and the * igbinary extension is loaded. *

    *

    Type: integer, default: Memcached::SERIALIZER_PHP.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_SERIALIZER = -1003; /** *

    Indicates whether igbinary serializer support is available.

    *

    Type: boolean.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HAVE_IGBINARY = false; /** *

    Indicates whether JSON serializer support is available.

    *

    Type: boolean.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HAVE_JSON = false; /** *

    Indicates whether msgpack serializer support is available.

    *

    Type: boolean.

    * Available as of Memcached 3.0.0. * @since 3.0.0 * @link https://php.net/manual/en/memcached.constants.php */ public const HAVE_MSGPACK = false; /** *

    Indicate whether set_encoding_key is available

    *

    Type: boolean.

    * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/memcached-api.php, https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/php_memcached.c#L4387 */ public const HAVE_ENCODING = false; /** * Feature support */ public const HAVE_SESSION = true; public const HAVE_SASL = false; /** *

    Specifies the hashing algorithm used for the item keys. The valid * values are supplied via Memcached::HASH_* constants. * Each hash algorithm has its advantages and its disadvantages. Go with the * default if you don't know or don't care.

    *

    Type: integer, default: Memcached::HASH_DEFAULT

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_HASH = 2; /** *

    The default (Jenkins one-at-a-time) item key hashing algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HASH_DEFAULT = 0; /** *

    MD5 item key hashing algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HASH_MD5 = 1; /** *

    CRC item key hashing algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HASH_CRC = 2; /** *

    FNV1_64 item key hashing algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HASH_FNV1_64 = 3; /** *

    FNV1_64A item key hashing algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HASH_FNV1A_64 = 4; /** *

    FNV1_32 item key hashing algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HASH_FNV1_32 = 5; /** *

    FNV1_32A item key hashing algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HASH_FNV1A_32 = 6; /** *

    Hsieh item key hashing algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HASH_HSIEH = 7; /** *

    Murmur item key hashing algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const HASH_MURMUR = 8; /** *

    Specifies the method of distributing item keys to the servers. * Currently supported methods are modulo and consistent hashing. Consistent * hashing delivers better distribution and allows servers to be added to * the cluster with minimal cache losses.

    *

    Type: integer, default: Memcached::DISTRIBUTION_MODULA.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_DISTRIBUTION = 9; /** *

    Modulo-based key distribution algorithm.

    * @link https://php.net/manual/en/memcached.constants.php */ public const DISTRIBUTION_MODULA = 0; /** *

    Consistent hashing key distribution algorithm (based on libketama).

    * @link https://php.net/manual/en/memcached.constants.php */ public const DISTRIBUTION_CONSISTENT = 1; public const DISTRIBUTION_VIRTUAL_BUCKET = 6; /** *

    Enables or disables compatibility with libketama-like behavior. When * enabled, the item key hashing algorithm is set to MD5 and distribution is * set to be weighted consistent hashing distribution. This is useful * because other libketama-based clients (Python, Ruby, etc.) with the same * server configuration will be able to access the keys transparently. *

    *

    * It is highly recommended to enable this option if you want to use * consistent hashing, and it may be enabled by default in future * releases. *

    *

    Type: boolean, default: FALSE.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_LIBKETAMA_COMPATIBLE = 16; public const OPT_LIBKETAMA_HASH = 17; public const OPT_TCP_KEEPALIVE = 32; /** *

    Enables or disables buffered I/O. Enabling buffered I/O causes * storage commands to "buffer" instead of being sent. Any action that * retrieves data causes this buffer to be sent to the remote connection. * Quitting the connection or closing down the connection will also cause * the buffered data to be pushed to the remote connection.

    *

    Type: boolean, default: FALSE.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_BUFFER_WRITES = 10; /** *

    Enable the use of the binary protocol. Please note that you cannot * toggle this option on an open connection.

    *

    Type: boolean, default: FALSE.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_BINARY_PROTOCOL = 18; /** *

    Enables or disables asynchronous I/O. This is the fastest transport * available for storage functions.

    *

    Type: boolean, default: FALSE.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_NO_BLOCK = 0; /** *

    Enables or disables the no-delay feature for connecting sockets (may * be faster in some environments).

    *

    Type: boolean, default: FALSE.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_TCP_NODELAY = 1; /** *

    The maximum socket send buffer in bytes.

    *

    Type: integer, default: varies by platform/kernel * configuration.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_SOCKET_SEND_SIZE = 4; /** *

    The maximum socket receive buffer in bytes.

    *

    Type: integer, default: varies by platform/kernel * configuration.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_SOCKET_RECV_SIZE = 5; /** *

    In non-blocking mode this set the value of the timeout during socket * connection, in milliseconds.

    *

    Type: integer, default: 1000.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_CONNECT_TIMEOUT = 14; /** *

    The amount of time, in seconds, to wait until retrying a failed * connection attempt.

    *

    Type: integer, default: 0.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_RETRY_TIMEOUT = 15; /** *

    Socket sending timeout, in microseconds. In cases where you cannot * use non-blocking I/O this will allow you to still have timeouts on the * sending of data.

    *

    Type: integer, default: 0.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_SEND_TIMEOUT = 19; /** *

    Socket reading timeout, in microseconds. In cases where you cannot * use non-blocking I/O this will allow you to still have timeouts on the * reading of data.

    *

    Type: integer, default: 0.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_RECV_TIMEOUT = 20; /** *

    Timeout for connection polling, in milliseconds.

    *

    Type: integer, default: 1000.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_POLL_TIMEOUT = 8; /** *

    Enables or disables caching of DNS lookups.

    *

    Type: boolean, default: FALSE.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_CACHE_LOOKUPS = 6; /** *

    Specifies the failure limit for server connection attempts. The * server will be removed after this many continuous connection * failures.

    *

    Type: integer, default: 0.

    * @link https://php.net/manual/en/memcached.constants.php */ public const OPT_SERVER_FAILURE_LIMIT = 21; public const OPT_AUTO_EJECT_HOSTS = 28; public const OPT_HASH_WITH_PREFIX_KEY = 25; public const OPT_NOREPLY = 26; public const OPT_SORT_HOSTS = 12; public const OPT_VERIFY_KEY = 13; public const OPT_USE_UDP = 27; public const OPT_NUMBER_OF_REPLICAS = 29; public const OPT_RANDOMIZE_REPLICA_READ = 30; public const OPT_CORK = 31; public const OPT_REMOVE_FAILED_SERVERS = 35; public const OPT_DEAD_TIMEOUT = 36; public const OPT_SERVER_TIMEOUT_LIMIT = 37; public const OPT_MAX = 38; public const OPT_IO_BYTES_WATERMARK = 23; public const OPT_IO_KEY_PREFETCH = 24; public const OPT_IO_MSG_WATERMARK = 22; public const OPT_LOAD_FROM_FILE = 34; public const OPT_SUPPORT_CAS = 7; public const OPT_TCP_KEEPIDLE = 33; public const OPT_USER_DATA = 11; /** * libmemcached result codes */ /** *

    The operation was successful.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_SUCCESS = 0; /** *

    The operation failed in some fashion.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_FAILURE = 1; /** *

    DNS lookup failed.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_HOST_LOOKUP_FAILURE = 2; /** *

    Failed to read network data.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_UNKNOWN_READ_FAILURE = 7; /** *

    Bad command in memcached protocol.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_PROTOCOL_ERROR = 8; /** *

    Error on the client side.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_CLIENT_ERROR = 9; /** *

    Error on the server side.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_SERVER_ERROR = 10; /** *

    Failed to write network data.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_WRITE_FAILURE = 5; /** *

    Failed to do compare-and-swap: item you are trying to store has been * modified since you last fetched it.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_DATA_EXISTS = 12; /** *

    Item was not stored: but not because of an error. This normally * means that either the condition for an "add" or a "replace" command * wasn't met, or that the item is in a delete queue.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_NOTSTORED = 14; /** *

    Item with this key was not found (with "get" operation or "cas" * operations).

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_NOTFOUND = 16; /** *

    Partial network data read error.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_PARTIAL_READ = 18; /** *

    Some errors occurred during multi-get.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_SOME_ERRORS = 19; /** *

    Server list is empty.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_NO_SERVERS = 20; /** *

    End of result set.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_END = 21; /** *

    System error.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_ERRNO = 26; /** *

    The operation was buffered.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_BUFFERED = 32; /** *

    The operation timed out.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_TIMEOUT = 31; /** *

    Bad key.

    * @link https://php.net/manual/en/memcached.constants.php, http://docs.libmemcached.org/index.html */ /** *

    MEMCACHED_BAD_KEY_PROVIDED: The key provided is not a valid key.

    */ public const RES_BAD_KEY_PROVIDED = 33; /** *

    MEMCACHED_STORED: The requested object has been successfully stored on the server.

    */ public const RES_STORED = 15; /** *

    MEMCACHED_DELETED: The object requested by the key has been deleted.

    */ public const RES_DELETED = 22; /** *

    MEMCACHED_STAT: A “stat” command has been returned in the protocol.

    */ public const RES_STAT = 24; /** *

    MEMCACHED_ITEM: An item has been fetched (this is an internal error only).

    */ public const RES_ITEM = 25; /** *

    MEMCACHED_NOT_SUPPORTED: The given method is not supported in the server.

    */ public const RES_NOT_SUPPORTED = 28; /** *

    MEMCACHED_FETCH_NOTFINISHED: A request has been made, but the server has not finished the fetch of the last request.

    */ public const RES_FETCH_NOTFINISHED = 30; /** *

    MEMCACHED_SERVER_MARKED_DEAD: The requested server has been marked dead.

    */ public const RES_SERVER_MARKED_DEAD = 35; /** *

    MEMCACHED_UNKNOWN_STAT_KEY: The server you are communicating with has a stat key which has not be defined in the protocol.

    */ public const RES_UNKNOWN_STAT_KEY = 36; /** *

    MEMCACHED_INVALID_HOST_PROTOCOL: The server you are connecting too has an invalid protocol. Most likely you are connecting to an older server that does not speak the binary protocol.

    */ public const RES_INVALID_HOST_PROTOCOL = 34; /** *

    MEMCACHED_MEMORY_ALLOCATION_FAILURE: An error has occurred while trying to allocate memory.

    */ public const RES_MEMORY_ALLOCATION_FAILURE = 17; /** *

    MEMCACHED_E2BIG: Item is too large for the server to store.

    */ public const RES_E2BIG = 37; /** *

    MEMCACHED_KEY_TOO_BIG: The key that has been provided is too large for the given server.

    */ public const RES_KEY_TOO_BIG = 39; /** *

    MEMCACHED_SERVER_TEMPORARILY_DISABLED

    */ public const RES_SERVER_TEMPORARILY_DISABLED = 47; /** *

    MEMORY_ALLOCATION_FAILURE: An error has occurred while trying to allocate memory. * * #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000008

    */ public const RES_SERVER_MEMORY_ALLOCATION_FAILURE = 48; /** *

    MEMCACHED_AUTH_PROBLEM: An unknown issue has occured during authentication.

    */ public const RES_AUTH_PROBLEM = 40; /** *

    MEMCACHED_AUTH_FAILURE: The credentials provided are not valid for this server.

    */ public const RES_AUTH_FAILURE = 41; /** *

    MEMCACHED_AUTH_CONTINUE: Authentication has been paused.

    */ public const RES_AUTH_CONTINUE = 42; /** *

    MEMCACHED_CONNECTION_FAILURE: A unknown error has occured while trying to connect to a server.

    */ public const RES_CONNECTION_FAILURE = 3; /** * MEMCACHED_CONNECTION_BIND_FAILURE: We were not able to bind() to the socket. */ #[Deprecated('Deprecated since version 0.30(libmemcached)')] public const RES_CONNECTION_BIND_FAILURE = 4; /** *

    MEMCACHED_READ_FAILURE: A read failure has occurred.

    */ public const RES_READ_FAILURE = 6; /** *

    MEMCACHED_DATA_DOES_NOT_EXIST: The data requested with the key given was not found.

    */ public const RES_DATA_DOES_NOT_EXIST = 13; /** *

    MEMCACHED_VALUE: A value has been returned from the server (this is an internal condition only).

    */ public const RES_VALUE = 23; /** *

    MEMCACHED_FAIL_UNIX_SOCKET: A connection was not established with the server via a unix domain socket.

    */ public const RES_FAIL_UNIX_SOCKET = 27; /** * No key was provided.

    */ #[Deprecated('Deprecated since version 0.30 (libmemcached). Use MEMCACHED_BAD_KEY_PROVIDED instead.')] public const RES_NO_KEY_PROVIDED = 29; /** *

    MEMCACHED_INVALID_ARGUMENTS: The arguments supplied to the given function were not valid.

    */ public const RES_INVALID_ARGUMENTS = 38; /** *

    MEMCACHED_PARSE_ERROR: An error has occurred while trying to parse the configuration string. You should use memparse to determine what the error was.

    */ public const RES_PARSE_ERROR = 43; /** *

    MEMCACHED_PARSE_USER_ERROR: An error has occurred in parsing the configuration string.

    */ public const RES_PARSE_USER_ERROR = 44; /** *

    MEMCACHED_DEPRECATED: The method that was requested has been deprecated.

    */ public const RES_DEPRECATED = 45; //unknow public const RES_IN_PROGRESS = 46; /** *

    MEMCACHED_MAXIMUM_RETURN: This in an internal only state.

    */ public const RES_MAXIMUM_RETURN = 49; /** * Server callbacks, if compiled with --memcached-protocol * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/memcached-api.php */ public const ON_CONNECT = 0; public const ON_ADD = 1; public const ON_APPEND = 2; public const ON_DECREMENT = 3; public const ON_DELETE = 4; public const ON_FLUSH = 5; public const ON_GET = 6; public const ON_INCREMENT = 7; public const ON_NOOP = 8; public const ON_PREPEND = 9; public const ON_QUIT = 10; public const ON_REPLACE = 11; public const ON_SET = 12; public const ON_STAT = 13; public const ON_VERSION = 14; /** * Constants used when compiled with --memcached-protocol * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/memcached-api.php */ public const RESPONSE_SUCCESS = 0; public const RESPONSE_KEY_ENOENT = 1; public const RESPONSE_KEY_EEXISTS = 2; public const RESPONSE_E2BIG = 3; public const RESPONSE_EINVAL = 4; public const RESPONSE_NOT_STORED = 5; public const RESPONSE_DELTA_BADVAL = 6; public const RESPONSE_NOT_MY_VBUCKET = 7; public const RESPONSE_AUTH_ERROR = 32; public const RESPONSE_AUTH_CONTINUE = 33; public const RESPONSE_UNKNOWN_COMMAND = 129; public const RESPONSE_ENOMEM = 130; public const RESPONSE_NOT_SUPPORTED = 131; public const RESPONSE_EINTERNAL = 132; public const RESPONSE_EBUSY = 133; public const RESPONSE_ETMPFAIL = 134; /** *

    Failed to create network socket.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_CONNECTION_SOCKET_CREATE_FAILURE = 11; /** *

    Payload failure: could not compress/decompress or serialize/unserialize the value.

    * @link https://php.net/manual/en/memcached.constants.php */ public const RES_PAYLOAD_FAILURE = -1001; /** *

    The default PHP serializer.

    * @link https://php.net/manual/en/memcached.constants.php */ public const SERIALIZER_PHP = 1; /** *

    The igbinary serializer. * Instead of textual representation it stores PHP data structures in a * compact binary form, resulting in space and time gains.

    * @link https://php.net/manual/en/memcached.constants.php */ public const SERIALIZER_IGBINARY = 2; /** *

    The JSON serializer. Requires PHP 5.2.10+.

    * @link https://php.net/manual/en/memcached.constants.php */ public const SERIALIZER_JSON = 3; public const SERIALIZER_JSON_ARRAY = 4; /** *

    The msgpack serializer.

    * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/memcached-api.php */ public const SERIALIZER_MSGPACK = 5; public const COMPRESSION_FASTLZ = 2; public const COMPRESSION_ZLIB = 1; /** *

    A flag for Memcached::getMulti and * Memcached::getMultiByKey to ensure that the keys are * returned in the same order as they were requested in. Non-existing keys * get a default value of NULL.

    * @link https://php.net/manual/en/memcached.constants.php */ public const GET_PRESERVE_ORDER = 1; /** * A flag for Memcached::get(), Memcached::getMulti() and * Memcached::getMultiByKey() to ensure that the CAS token values are returned as well. * @link https://php.net/manual/en/memcached.constants.php * @since 3.0.0 */ public const GET_EXTENDED = 2; public const GET_ERROR_RETURN_VALUE = false; /** * (PECL memcached >= 0.1.0)
    * Create a Memcached instance * @link https://php.net/manual/en/memcached.construct.php, https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/php_memcached.c * @param string $persistent_id [optional] * @param callable $on_new_object_cb [optional] * @param string $connection_str [optional] */ public function __construct($persistent_id = '', $on_new_object_cb = null, $connection_str = '') {} /** * (PECL memcached >= 0.1.0)
    * Return the result code of the last operation * @link https://php.net/manual/en/memcached.getresultcode.php * @return int Result code of the last Memcached operation. */ public function getResultCode() {} /** * (PECL memcached >= 1.0.0)
    * Return the message describing the result of the last operation * @link https://php.net/manual/en/memcached.getresultmessage.php * @return string Message describing the result of the last Memcached operation. */ public function getResultMessage() {} /** * (PECL memcached >= 0.1.0)
    * Retrieve an item * @link https://php.net/manual/en/memcached.get.php * @param string $key

    * The key of the item to retrieve. *

    * @param callable $cache_cb [optional]

    * Read-through caching callback or NULL. *

    * @param int $flags [optional]

    * The flags for the get operation. *

    * @return mixed the value stored in the cache or FALSE otherwise. * The Memcached::getResultCode will return * Memcached::RES_NOTFOUND if the key does not exist. */ public function get($key, callable $cache_cb = null, $flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Retrieve an item from a specific server * @link https://php.net/manual/en/memcached.getbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key of the item to fetch. *

    * @param callable $cache_cb [optional]

    * Read-through caching callback or NULL *

    * @param int $flags [optional]

    * The flags for the get operation. *

    * @return mixed the value stored in the cache or FALSE otherwise. * The Memcached::getResultCode will return * Memcached::RES_NOTFOUND if the key does not exist. */ public function getByKey($server_key, $key, callable $cache_cb = null, $flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Retrieve multiple items * @link https://php.net/manual/en/memcached.getmulti.php * @param array $keys

    * Array of keys to retrieve. *

    * @param int $flags [optional]

    * The flags for the get operation. *

    * @return mixed the array of found items or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function getMulti(array $keys, $flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Retrieve multiple items from a specific server * @link https://php.net/manual/en/memcached.getmultibykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param array $keys

    * Array of keys to retrieve. *

    * @param int $flags [optional]

    * The flags for the get operation. *

    * @return array|false the array of found items or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function getMultiByKey($server_key, array $keys, $flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Request multiple items * @link https://php.net/manual/en/memcached.getdelayed.php * @param array $keys

    * Array of keys to request. *

    * @param bool $with_cas [optional]

    * Whether to request CAS token values also. *

    * @param callable $value_cb [optional]

    * The result callback or NULL. *

    * @return bool TRUE on success or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function getDelayed(array $keys, $with_cas = null, callable $value_cb = null) {} /** * (PECL memcached >= 0.1.0)
    * Request multiple items from a specific server * @link https://php.net/manual/en/memcached.getdelayedbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param array $keys

    * Array of keys to request. *

    * @param bool $with_cas [optional]

    * Whether to request CAS token values also. *

    * @param callable $value_cb [optional]

    * The result callback or NULL. *

    * @return bool TRUE on success or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function getDelayedByKey($server_key, array $keys, $with_cas = null, callable $value_cb = null) {} /** * (PECL memcached >= 0.1.0)
    * Fetch the next result * @link https://php.net/manual/en/memcached.fetch.php * @return array|false the next result or FALSE otherwise. * The Memcached::getResultCode will return * Memcached::RES_END if result set is exhausted. */ public function fetch() {} /** * (PECL memcached >= 0.1.0)
    * Fetch all the remaining results * @link https://php.net/manual/en/memcached.fetchall.php * @return array|false the results or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function fetchAll() {} /** * (PECL memcached >= 0.1.0)
    * Store an item * @link https://php.net/manual/en/memcached.set.php * @param string $key

    * The key under which to store the value. *

    * @param mixed $value

    * The value to store. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function set($key, $value, $expiration = 0, $udf_flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Store an item on a specific server * @link https://php.net/manual/en/memcached.setbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key under which to store the value. *

    * @param mixed $value

    * The value to store. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function setByKey($server_key, $key, $value, $expiration = 0, $udf_flags = 0) {} /** * (PECL memcached >= 2.0.0)
    * Set a new expiration on an item * @link https://php.net/manual/en/memcached.touch.php * @param string $key

    * The key under which to store the value. *

    * @param int $expiration

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @return bool TRUE on success or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function touch($key, $expiration = 0) {} /** * (PECL memcached >= 2.0.0)
    * Set a new expiration on an item on a specific server * @link https://php.net/manual/en/memcached.touchbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key under which to store the value. *

    * @param int $expiration

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @return bool TRUE on success or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function touchByKey($server_key, $key, $expiration) {} /** * (PECL memcached >= 0.1.0)
    * Store multiple items * @link https://php.net/manual/en/memcached.setmulti.php * @param array $items

    * An array of key/value pairs to store on the server. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function setMulti(array $items, $expiration = 0, $udf_flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Store multiple items on a specific server * @link https://php.net/manual/en/memcached.setmultibykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param array $items

    * An array of key/value pairs to store on the server. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function setMultiByKey($server_key, array $items, $expiration = 0, $udf_flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Compare and swap an item * @link https://php.net/manual/en/memcached.cas.php * @param float $cas_token

    * Unique value associated with the existing item. Generated by memcache. *

    * @param string $key

    * The key under which to store the value. *

    * @param mixed $value

    * The value to store. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_DATA_EXISTS if the item you are trying * to store has been modified since you last fetched it. */ public function cas($cas_token, $key, $value, $expiration = 0, $udf_flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Compare and swap an item on a specific server * @link https://php.net/manual/en/memcached.casbykey.php * @param float $cas_token

    * Unique value associated with the existing item. Generated by memcache. *

    * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key under which to store the value. *

    * @param mixed $value

    * The value to store. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_DATA_EXISTS if the item you are trying * to store has been modified since you last fetched it. */ public function casByKey($cas_token, $server_key, $key, $value, $expiration = 0, $udf_flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Add an item under a new key * @link https://php.net/manual/en/memcached.add.php * @param string $key

    * The key under which to store the value. *

    * @param mixed $value

    * The value to store. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTSTORED if the key already exists. */ public function add($key, $value, $expiration = 0, $udf_flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Add an item under a new key on a specific server * @link https://php.net/manual/en/memcached.addbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key under which to store the value. *

    * @param mixed $value

    * The value to store. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTSTORED if the key already exists. */ public function addByKey($server_key, $key, $value, $expiration = 0, $udf_flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Append data to an existing item * @link https://php.net/manual/en/memcached.append.php * @param string $key

    * The key under which to store the value. *

    * @param string $value

    * The string to append. *

    * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTSTORED if the key does not exist. */ public function append($key, $value) {} /** * (PECL memcached >= 0.1.0)
    * Append data to an existing item on a specific server * @link https://php.net/manual/en/memcached.appendbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key under which to store the value. *

    * @param string $value

    * The string to append. *

    * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTSTORED if the key does not exist. */ public function appendByKey($server_key, $key, $value) {} /** * (PECL memcached >= 0.1.0)
    * Prepend data to an existing item * @link https://php.net/manual/en/memcached.prepend.php * @param string $key

    * The key of the item to prepend the data to. *

    * @param string $value

    * The string to prepend. *

    * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTSTORED if the key does not exist. */ public function prepend($key, $value) {} /** * (PECL memcached >= 0.1.0)
    * Prepend data to an existing item on a specific server * @link https://php.net/manual/en/memcached.prependbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key of the item to prepend the data to. *

    * @param string $value

    * The string to prepend. *

    * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTSTORED if the key does not exist. */ public function prependByKey($server_key, $key, $value) {} /** * (PECL memcached >= 0.1.0)
    * Replace the item under an existing key * @link https://php.net/manual/en/memcached.replace.php * @param string $key

    * The key under which to store the value. *

    * @param mixed $value

    * The value to store. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTSTORED if the key does not exist. */ public function replace($key, $value, $expiration = null, $udf_flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Replace the item under an existing key on a specific server * @link https://php.net/manual/en/memcached.replacebykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key under which to store the value. *

    * @param mixed $value

    * The value to store. *

    * @param int $expiration [optional]

    * The expiration time, defaults to 0. See Expiration Times for more info. *

    * @param int $udf_flags [optional] * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTSTORED if the key does not exist. */ public function replaceByKey($server_key, $key, $value, $expiration = null, $udf_flags = 0) {} /** * (PECL memcached >= 0.1.0)
    * Delete an item * @link https://php.net/manual/en/memcached.delete.php * @param string $key

    * The key to be deleted. *

    * @param int $time [optional]

    * The amount of time the server will wait to delete the item. *

    * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTFOUND if the key does not exist. */ public function delete($key, $time = 0) {} /** * (PECL memcached >= 2.0.0)
    * Delete multiple items * @link https://php.net/manual/en/memcached.deletemulti.php * @param array $keys

    * The keys to be deleted. *

    * @param int $time [optional]

    * The amount of time the server will wait to delete the items. *

    * @return array Returns array indexed by keys and where values are indicating whether operation succeeded or not. * The Memcached::getResultCode will return * Memcached::RES_NOTFOUND if the key does not exist. */ public function deleteMulti(array $keys, $time = 0) {} /** * (PECL memcached >= 0.1.0)
    * Delete an item from a specific server * @link https://php.net/manual/en/memcached.deletebykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key to be deleted. *

    * @param int $time [optional]

    * The amount of time the server will wait to delete the item. *

    * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTFOUND if the key does not exist. */ public function deleteByKey($server_key, $key, $time = 0) {} /** * (PECL memcached >= 2.0.0)
    * Delete multiple items from a specific server * @link https://php.net/manual/en/memcached.deletemultibykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param array $keys

    * The keys to be deleted. *

    * @param int $time [optional]

    * The amount of time the server will wait to delete the items. *

    * @return bool TRUE on success or FALSE on failure. * The Memcached::getResultCode will return * Memcached::RES_NOTFOUND if the key does not exist. */ public function deleteMultiByKey($server_key, array $keys, $time = 0) {} /** * (PECL memcached >= 0.1.0)
    * Increment numeric item's value * @link https://php.net/manual/en/memcached.increment.php * @param string $key

    * The key of the item to increment. *

    * @param int $offset [optional]

    * The amount by which to increment the item's value. *

    * @param int $initial_value [optional]

    * The value to set the item to if it doesn't currently exist. *

    * @param int $expiry [optional]

    * The expiry time to set on the item. *

    * @return int|false new item's value on success or FALSE on failure. */ public function increment($key, $offset = 1, $initial_value = 0, $expiry = 0) {} /** * (PECL memcached >= 0.1.0)
    * Decrement numeric item's value * @link https://php.net/manual/en/memcached.decrement.php * @param string $key

    * The key of the item to decrement. *

    * @param int $offset [optional]

    * The amount by which to decrement the item's value. *

    * @param int $initial_value [optional]

    * The value to set the item to if it doesn't currently exist. *

    * @param int $expiry [optional]

    * The expiry time to set on the item. *

    * @return int|false item's new value on success or FALSE on failure. */ public function decrement($key, $offset = 1, $initial_value = 0, $expiry = 0) {} /** * (PECL memcached >= 2.0.0)
    * Increment numeric item's value, stored on a specific server * @link https://php.net/manual/en/memcached.incrementbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key of the item to increment. *

    * @param int $offset [optional]

    * The amount by which to increment the item's value. *

    * @param int $initial_value [optional]

    * The value to set the item to if it doesn't currently exist. *

    * @param int $expiry [optional]

    * The expiry time to set on the item. *

    * @return int|false new item's value on success or FALSE on failure. */ public function incrementByKey($server_key, $key, $offset = 1, $initial_value = 0, $expiry = 0) {} /** * (PECL memcached >= 2.0.0)
    * Decrement numeric item's value, stored on a specific server * @link https://php.net/manual/en/memcached.decrementbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @param string $key

    * The key of the item to decrement. *

    * @param int $offset [optional]

    * The amount by which to decrement the item's value. *

    * @param int $initial_value [optional]

    * The value to set the item to if it doesn't currently exist. *

    * @param int $expiry [optional]

    * The expiry time to set on the item. *

    * @return int|false item's new value on success or FALSE on failure. */ public function decrementByKey($server_key, $key, $offset = 1, $initial_value = 0, $expiry = 0) {} /** * (PECL memcached >= 0.1.0)
    * Add a server to the server pool * @link https://php.net/manual/en/memcached.addserver.php * @param string $host

    * The hostname of the memcache server. If the hostname is invalid, data-related * operations will set * Memcached::RES_HOST_LOOKUP_FAILURE result code. *

    * @param int $port

    * The port on which memcache is running. Usually, this is * 11211. *

    * @param int $weight [optional]

    * The weight of the server relative to the total weight of all the * servers in the pool. This controls the probability of the server being * selected for operations. This is used only with consistent distribution * option and usually corresponds to the amount of memory available to * memcache on that server. *

    * @return bool TRUE on success or FALSE on failure. */ public function addServer($host, $port, $weight = 0) {} /** * (PECL memcached >= 0.1.1)
    * Add multiple servers to the server pool * @link https://php.net/manual/en/memcached.addservers.php * @param array $servers * @return bool TRUE on success or FALSE on failure. */ public function addServers(array $servers) {} /** * (PECL memcached >= 0.1.0)
    * Get the list of the servers in the pool * @link https://php.net/manual/en/memcached.getserverlist.php * @return array The list of all servers in the server pool. */ public function getServerList() {} /** * (PECL memcached >= 0.1.0)
    * Map a key to a server * @link https://php.net/manual/en/memcached.getserverbykey.php * @param string $server_key

    * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. *

    * @return array an array containing three keys of host, * port, and weight on success or FALSE * on failure. * Use Memcached::getResultCode if necessary. */ public function getServerByKey($server_key) {} /** * (PECL memcached >= 2.0.0)
    * Clears all servers from the server list * @link https://php.net/manual/en/memcached.resetserverlist.php * @return bool TRUE on success or FALSE on failure. */ public function resetServerList() {} /** * (PECL memcached >= 2.0.0)
    * Close any open connections * @link https://php.net/manual/en/memcached.quit.php * @return bool TRUE on success or FALSE on failure. */ public function quit() {} /** * (PECL memcached >= 0.1.0)
    * Get server pool statistics * @link https://php.net/manual/en/memcached.getstats.php * @param string $type

    items, slabs, sizes ...

    * @return array|false Array of server statistics, one entry per server. */ public function getStats($type = null) {} /** * (PECL memcached >= 0.1.5)
    * Get server pool version info * @link https://php.net/manual/en/memcached.getversion.php * @return array Array of server versions, one entry per server. */ public function getVersion() {} /** * (PECL memcached >= 2.0.0)
    * Gets the keys stored on all the servers * @link https://php.net/manual/en/memcached.getallkeys.php * @return array|false the keys stored on all the servers on success or FALSE on failure. */ public function getAllKeys() {} /** * (PECL memcached >= 0.1.0)
    * Invalidate all items in the cache * @link https://php.net/manual/en/memcached.flush.php * @param int $delay [optional]

    * Numer of seconds to wait before invalidating the items. *

    * @return bool TRUE on success or FALSE on failure. * Use Memcached::getResultCode if necessary. */ public function flush($delay = 0) {} /** * (PECL memcached >= 0.1.0)
    * Retrieve a Memcached option value * @link https://php.net/manual/en/memcached.getoption.php * @param int $option

    * One of the Memcached::OPT_* constants. *

    * @return mixed the value of the requested option, or FALSE on * error. */ public function getOption($option) {} /** * (PECL memcached >= 0.1.0)
    * Set a Memcached option * @link https://php.net/manual/en/memcached.setoption.php * @param int $option * @param mixed $value * @return bool TRUE on success or FALSE on failure. */ public function setOption($option, $value) {} /** * (PECL memcached >= 2.0.0)
    * Set Memcached options * @link https://php.net/manual/en/memcached.setoptions.php * @param array $options

    * An associative array of options where the key is the option to set and * the value is the new value for the option. *

    * @return bool TRUE on success or FALSE on failure. */ public function setOptions(array $options) {} /** * (PECL memcached >= 2.0.0)
    * Set the credentials to use for authentication * @link https://secure.php.net/manual/en/memcached.setsaslauthdata.php * @param string $username

    * The username to use for authentication. *

    * @param string $password

    * The password to use for authentication. *

    * @return void */ public function setSaslAuthData(string $username, string $password) {} /** * (PECL memcached >= 2.0.0)
    * Check if a persitent connection to memcache is being used * @link https://php.net/manual/en/memcached.ispersistent.php * @return bool true if Memcache instance uses a persistent connection, false otherwise. */ public function isPersistent() {} /** * (PECL memcached >= 2.0.0)
    * Check if the instance was recently created * @link https://php.net/manual/en/memcached.ispristine.php * @return bool the true if instance is recently created, false otherwise. */ public function isPristine() {} /** * (PECL memcached >= 3.2.0)
    * Check if the given key is valid. * @param string $key * @return bool */ public function checkKey($key) {} /** * Flush and send buffered commands * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/php_memcached.c * @return bool */ public function flushBuffers() {} /** * Sets AES encryption key (libmemcached 1.0.6 and higher) * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/php_memcached.c * @param string $key * @return bool */ public function setEncodingKey($key) {} /** * Returns the last disconnected server. Was added in 0.34 according to libmemcached's Changelog * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/php_memcached.c * @return array|false */ public function getLastDisconnectedServer() {} /** * Returns the last error errno that occurred * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/php_memcached.c * @return int */ public function getLastErrorErrno() {} /** * Returns the last error code that occurred * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/php_memcached.c * @return int */ public function getLastErrorCode() {} /** * Returns the last error message that occurred * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/php_memcached.c * @return string */ public function getLastErrorMessage() {} /** * Sets the memcached virtual buckets * @link https://github.com/php-memcached-dev/php-memcached/blob/v3.1.5/php_memcached.c * @param array $host_map * @param array $forward_map * @param int $replicas * @return bool */ public function setBucket(array $host_map, array $forward_map, $replicas) {} } /** * @link https://php.net/manual/en/class.memcachedexception.php */ class MemcachedException extends RuntimeException { #[\JetBrains\PhpStorm\Pure] public function __construct($errmsg = "", $errcode = 0) {} } // End of memcached v.3.1.5 value pairs. * The constant_name must follow the normal constant naming rules. Value must evaluate to a scalar value. * @param bool $case_sensitive The default behaviour for constants is to be declared case-sensitive; * i.e. CONSTANT and Constant represent different values. If this parameter evaluates to FALSE * the constants will be declared as case-insensitive symbols. * @return bool Returns TRUE on success or FALSE on failure. */ function apc_define_constants($key, array $constants, $case_sensitive = true) {} /** * Caches a variable in the data store, only if it's not already stored * @link https://php.net/manual/en/function.apc-add.php * @param string $key Store the variable using this name. Keys are cache-unique, * so attempting to use apc_add() to store data with a key that already exists will not * overwrite the existing data, and will instead return FALSE. (This is the only difference * between apc_add() and apc_store().) * @param mixed $var The variable to store * @param int $ttl Time To Live; store var in the cache for ttl seconds. After the ttl has passed, * the stored variable will be expunged from the cache (on the next request). If no ttl is supplied * (or if the ttl is 0), the value will persist until it is removed from the cache manually, * or otherwise fails to exist in the cache (clear, restart, etc.). * @return bool */ function apc_add($key, $var, $ttl = 0) {} /** * Stores a file in the bytecode cache, bypassing all filters * @link https://php.net/manual/en/function.apc-compile-file.php * @param string|string[] $filename Full or relative path to a PHP file that will be * compiled and stored in the bytecode cache. * @param bool $atomic * @return bool Returns TRUE on success or FALSE on failure. */ function apc_compile_file($filename, $atomic = true) {} /** * Loads a set of constants from the cache * @link https://php.net/manual/en/function.apc-load-constants.php * @param string $key The name of the constant set (that was stored * with apc_define_constants()) to be retrieved. * @param bool $case_sensitive The default behaviour for constants is to be declared case-sensitive; * i.e. CONSTANT and Constant represent different values. If this parameter evaluates to FALSE * the constants will be declared as case-insensitive symbols. * @return bool Returns TRUE on success or FALSE on failure. */ function apc_load_constants($key, $case_sensitive = true) {} /** * Checks if APC key exists * @link https://php.net/manual/en/function.apc-exists.php * @param string|string[] $keys A string, or an array of strings, that contain keys. * @return bool|string[] Returns TRUE if the key exists, otherwise FALSE * Or if an array was passed to keys, then an array is returned that * contains all existing keys, or an empty array if none exist. */ function apc_exists($keys) {} /** * Deletes the given files from the opcode cache * * Accepts a string, array of strings, or APCIterator object. * Returns True/False, or for an Array an Array of failed files. * * @link https://php.net/manual/en/function.apc-delete-file.php * @param string|string[]|APCIterator $keys * @return bool|string[] */ function apc_delete_file($keys) {} /** * Increase a stored number * @link https://php.net/manual/en/function.apc-inc.php * @param string $key The key of the value being increased. * @param int $step The step, or value to increase. * @param bool|null &$success Optionally pass the success or fail boolean value to this referenced variable. * @return int|false Returns the current value of key's value on success, or FALSE on failure. */ function apc_inc($key, $step = 1, &$success = null) {} /** * Decrease a stored number * @link https://php.net/manual/en/function.apc-dec.php * @param string $key The key of the value being decreased. * @param int $step The step, or value to decrease. * @param bool|null &$success Optionally pass the success or fail boolean value to this referenced variable. * @return int|false Returns the current value of key's value on success, or FALSE on failure. */ function apc_dec($key, $step = 1, &$success = null) {} /** * Updates an old value with a new value * @link https://php.net/manual/en/function.apc-cas.php * @param string $key * @param int $old * @param int $new * @return bool */ function apc_cas($key, $old, $new) {} /** * Returns a binary dump of the given files and user variables from the APC cache * * A NULL for files or user_vars signals a dump of every entry, while array() will dump nothing. * * @link https://php.net/manual/en/function.apc-bin-dump.php * @param string[]|null $files The files. Passing in NULL signals a dump of every entry, while passing in array() will dump nothing. * @param string[]|null $user_vars The user vars. Passing in NULL signals a dump of every entry, while passing in array() will dump nothing. * @return string|false|null Returns a binary dump of the given files and user variables from the APC cache, FALSE if APC is not enabled, or NULL if an unknown error is encountered. */ function apc_bin_dump($files = null, $user_vars = null) {} /** * Output a binary dump of the given files and user variables from the APC cache to the named file * @link https://php.net/manual/en/function.apc-bin-dumpfile.php * @param string[]|null $files The file names being dumped. * @param string[]|null $user_vars The user variables being dumped. * @param string $filename The filename where the dump is being saved. * @param int $flags Flags passed to the filename stream. See the file_put_contents() documentation for details. * @param resource $context The context passed to the filename stream. See the file_put_contents() documentation for details. * @return int|false The number of bytes written to the file, otherwise FALSE if APC * is not enabled, filename is an invalid file name, filename can't be opened, * the file dump can't be completed (e.g., the hard drive is out of disk space), * or an unknown error was encountered. */ function apc_bin_dumpfile($files, $user_vars, $filename, $flags = 0, $context = null) {} /** * Load the given binary dump into the APC file/user cache * @link https://php.net/manual/en/function.apc-bin-load.php * @param string $data The binary dump being loaded, likely from apc_bin_dump(). * @param int $flags Either APC_BIN_VERIFY_CRC32, APC_BIN_VERIFY_MD5, or both. * @return bool Returns TRUE if the binary dump data was loaded with success, otherwise FALSE is returned. * FALSE is returned if APC is not enabled, or if the data is not a valid APC binary dump (e.g., unexpected size). */ function apc_bin_load($data, $flags = 0) {} /** * Load the given binary dump from the named file into the APC file/user cache * @link https://php.net/manual/en/function.apc-bin-loadfile.php * @param string $filename The file name containing the dump, likely from apc_bin_dumpfile(). * @param resource $context The files context. * @param int $flags Either APC_BIN_VERIFY_CRC32, APC_BIN_VERIFY_MD5, or both. * @return bool Returns TRUE on success, otherwise FALSE Reasons it may return FALSE include APC * is not enabled, filename is an invalid file name or empty, filename can't be opened, * the file dump can't be completed, or if the data is not a valid APC binary dump (e.g., unexpected size). */ function apc_bin_loadfile($filename, $context = null, $flags = 0) {} /** * The APCIterator class * * The APCIterator class makes it easier to iterate over large APC caches. * This is helpful as it allows iterating over large caches in steps, while grabbing a defined number * of entries per lock instance, so it frees the cache locks for other activities rather than hold up * the entire cache to grab 100 (the default) entries. Also, using regular expression matching is more * efficient as it's been moved to the C level. * * @link https://php.net/manual/en/class.apciterator.php */ class APCIterator implements Iterator { /** * Constructs an APCIterator iterator object * @link https://php.net/manual/en/apciterator.construct.php * @param string $cache The cache type, which will be 'user' or 'file'. * @param string|string[]|null $search A PCRE regular expression that matches against APC key names, * either as a string for a single regular expression, or as an array of regular expressions. * Or, optionally pass in NULL to skip the search. * @param int $format The desired format, as configured with one ore more of the APC_ITER_* constants. * @param int $chunk_size The chunk size. Must be a value greater than 0. The default value is 100. * @param int $list The type to list. Either pass in APC_LIST_ACTIVE or APC_LIST_INACTIVE. */ public function __construct($cache, $search = null, $format = APC_ITER_ALL, $chunk_size = 100, $list = APC_LIST_ACTIVE) {} /** * Rewinds back the iterator to the first element * @link https://php.net/manual/en/apciterator.rewind.php */ public function rewind() {} /** * Checks if the current iterator position is valid * @link https://php.net/manual/en/apciterator.valid.php * @return bool Returns TRUE if the current iterator position is valid, otherwise FALSE. */ public function valid() {} /** * Gets the current item from the APCIterator stack * @link https://php.net/manual/en/apciterator.current.php * @return mixed|false Returns the current item on success, or FALSE if no more items or exist, or on failure. */ public function current() {} /** * Gets the current iterator key * @link https://php.net/manual/en/apciterator.key.php * @return string|int|false Returns the key on success, or FALSE upon failure. */ public function key() {} /** * Moves the iterator pointer to the next element * @link https://php.net/manual/en/apciterator.next.php * @return bool Returns TRUE on success or FALSE on failure. */ public function next() {} /** * Gets the total number of cache hits * @link https://php.net/manual/en/apciterator.gettotalhits.php * @return int|false The number of hits on success, or FALSE on failure. */ public function getTotalHits() {} /** * Gets the total cache size * @link https://php.net/manual/en/apciterator.gettotalsize.php * @return int|bool The total cache size. */ public function getTotalSize() {} /** * Get the total count * @link https://php.net/manual/en/apciterator.gettotalcount.php * @return int|bool The total count. */ public function getTotalCount() {} } /** * Stubs for APCu 5.0.0 */ /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_LIST_ACTIVE', 1); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_LIST_DELETED', 2); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_TYPE', 1); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_KEY', 2); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_FILENAME', 4); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_DEVICE', 8); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_INODE', 16); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_VALUE', 32); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_MD5', 64); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_NUM_HITS', 128); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_MTIME', 256); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_CTIME', 512); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_DTIME', 1024); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_ATIME', 2048); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_REFCOUNT', 4096); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_MEM_SIZE', 8192); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_TTL', 16384); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_NONE', 0); /** * @link https://php.net/manual/en/apcu.constants.php */ define('APC_ITER_ALL', -1); /** * Clears the APCu cache * @link https://php.net/manual/en/function.apcu-clear-cache.php * * @return bool Returns TRUE always. */ function apcu_clear_cache() {} /** * Retrieves APCu Shared Memory Allocation information * @link https://php.net/manual/en/function.apcu-sma-info.php * @param bool $limited When set to FALSE (default) apcu_sma_info() will * return a detailed information about each segment. * * @return array|false Array of Shared Memory Allocation data; FALSE on failure. */ function apcu_sma_info($limited = false) {} /** * Cache a variable in the data store * @link https://php.net/manual/en/function.apcu-store.php * @param string|string[] $key String: Store the variable using this name. Keys are cache-unique, * so storing a second value with the same key will overwrite the original value. * Array: Names in key, variables in value. * @param mixed $var [optional] The variable to store * @param int $ttl [optional] Time To Live; store var in the cache for ttl seconds. After the ttl has passed, * the stored variable will be expunged from the cache (on the next request). If no ttl is supplied * (or if the ttl is 0), the value will persist until it is removed from the cache manually, * or otherwise fails to exist in the cache (clear, restart, etc.). * @return bool|array Returns TRUE on success or FALSE on failure | array with error keys. */ function apcu_store($key, $var, $ttl = 0) {} /** * Fetch a stored variable from the cache * @link https://php.net/manual/en/function.apcu-fetch.php * @param string|string[] $key The key used to store the value (with apcu_store()). * If an array is passed then each element is fetched and returned. * @param bool|null &$success Set to TRUE in success and FALSE in failure. * @return mixed|false The stored variable or array of variables on success; FALSE on failure. */ function apcu_fetch($key, &$success = null) {} /** * Removes a stored variable from the cache * @link https://php.net/manual/en/function.apcu-delete.php * @param string|string[]|APCUIterator $key The key used to store the value (with apcu_store()). * @return bool|string[] Returns TRUE on success or FALSE on failure. For array of keys returns list of failed keys. */ function apcu_delete($key) {} /** * Caches a variable in the data store, only if it's not already stored * @link https://php.net/manual/en/function.apcu-add.php * @param string|array $key Store the variable using this name. Keys are cache-unique, * so attempting to use apcu_add() to store data with a key that already exists will not * overwrite the existing data, and will instead return FALSE. (This is the only difference * between apcu_add() and apcu_store().) * Array: Names in key, variables in value. * @param mixed $var The variable to store * @param int $ttl Time To Live; store var in the cache for ttl seconds. After the ttl has passed, * the stored variable will be expunged from the cache (on the next request). If no ttl is supplied * (or if the ttl is 0), the value will persist until it is removed from the cache manually, * or otherwise fails to exist in the cache (clear, restart, etc.). * @return bool|array Returns TRUE if something has effectively been added into the cache, FALSE otherwise. * Second syntax returns array with error keys. */ function apcu_add($key, $var, $ttl = 0) {} /** * Checks if APCu key exists * @link https://php.net/manual/en/function.apcu-exists.php * @param string|string[] $keys A string, or an array of strings, that contain keys. * @return bool|string[] Returns TRUE if the key exists, otherwise FALSE * Or if an array was passed to keys, then an array is returned that * contains all existing keys, or an empty array if none exist. */ function apcu_exists($keys) {} /** * Increase a stored number * @link https://php.net/manual/en/function.apcu-inc.php * @param string $key The key of the value being increased. * @param int $step The step, or value to increase. * @param int $ttl Time To Live; store var in the cache for ttl seconds. After the ttl has passed, * the stored variable will be expunged from the cache (on the next request). If no ttl is supplied * (or if the ttl is 0), the value will persist until it is removed from the cache manually, * or otherwise fails to exist in the cache (clear, restart, etc.). * @param bool|null &$success Optionally pass the success or fail boolean value to this referenced variable. * @return int|false Returns the current value of key's value on success, or FALSE on failure. */ function apcu_inc($key, $step = 1, &$success = null, $ttl = 0) {} /** * Decrease a stored number * @link https://php.net/manual/en/function.apcu-dec.php * @param string $key The key of the value being decreased. * @param int $step The step, or value to decrease. * @param int $ttl Time To Live; store var in the cache for ttl seconds. After the ttl has passed, * the stored variable will be expunged from the cache (on the next request). If no ttl is supplied * (or if the ttl is 0), the value will persist until it is removed from the cache manually, * or otherwise fails to exist in the cache (clear, restart, etc.). * @param bool|null &$success Optionally pass the success or fail boolean value to this referenced variable. * @return int|false Returns the current value of key's value on success, or FALSE on failure. */ function apcu_dec($key, $step = 1, &$success = null, $ttl = 0) {} /** * Updates an old value with a new value * * apcu_cas() updates an already existing integer value if the old parameter matches the currently stored value * with the value of the new parameter. * * @link https://php.net/manual/en/function.apcu-cas.php * @param string $key The key of the value being updated. * @param int $old The old value (the value currently stored). * @param int $new The new value to update to. * @return bool Returns TRUE on success or FALSE on failure. */ function apcu_cas($key, $old, $new) {} /** * Atomically fetch or generate a cache entry * *

    Atomically attempts to find key in the cache, if it cannot be found generator is called, * passing key as the only argument. The return value of the call is then cached with the optionally * specified ttl, and returned. *

    * *

    Note: When control enters apcu_entry() the lock for the cache is acquired exclusively, it is released when * control leaves apcu_entry(): In effect, this turns the body of generator into a critical section, * disallowing two processes from executing the same code paths concurrently. * In addition, it prohibits the concurrent execution of any other APCu functions, * since they will acquire the same lock. *

    * * @link https://php.net/manual/en/function.apcu-entry.php * * @param string $key Identity of cache entry * @param callable $generator A callable that accepts key as the only argument and returns the value to cache. *

    Warning * The only APCu function that can be called safely by generator is apcu_entry().

    * @param int $ttl [optional] Time To Live; store var in the cache for ttl seconds. * After the ttl has passed, the stored variable will be expunged from the cache (on the next request). * If no ttl is supplied (or if the ttl is 0), the value will persist until it is removed from the cache manually, * or otherwise fails to exist in the cache (clear, restart, etc.). * @return mixed Returns the cached value * @since APCu 5.1.0 */ function apcu_entry($key, callable $generator, $ttl = 0) {} /** * Retrieves cached information from APCu's data store * * @link https://php.net/manual/en/function.apcu-cache-info.php * * @param bool $limited If limited is TRUE, the return value will exclude the individual list of cache entries. * This is useful when trying to optimize calls for statistics gathering. * @return array|false Array of cached data (and meta-data) or FALSE on failure */ function apcu_cache_info($limited = false) {} /** * Whether APCu is usable in the current environment * * @link https://www.php.net/manual/en/function.apcu-enabled.php * * @return bool */ function apcu_enabled() {} /** * @param string $key * @return array|null */ function apcu_key_info($key) {} /** * The APCUIterator class * * The APCUIterator class makes it easier to iterate over large APCu caches. * This is helpful as it allows iterating over large caches in steps, while grabbing a defined number * of entries per lock instance, so it frees the cache locks for other activities rather than hold up * the entire cache to grab 100 (the default) entries. Also, using regular expression matching is more * efficient as it's been moved to the C level. * * @link https://php.net/manual/en/class.apcuiterator.php * @since APCu 5.0.0 */ class APCUIterator implements Iterator { /** * Constructs an APCUIterator iterator object * @link https://php.net/manual/en/apcuiterator.construct.php * @param string|string[]|null $search A PCRE regular expression that matches against APCu key names, * either as a string for a single regular expression, or as an array of regular expressions. * Or, optionally pass in NULL to skip the search. * @param int $format The desired format, as configured with one ore more of the APC_ITER_* constants. * @param int $chunk_size The chunk size. Must be a value greater than 0. The default value is 100. * @param int $list The type to list. Either pass in APC_LIST_ACTIVE or APC_LIST_DELETED. */ public function __construct($search = null, $format = APC_ITER_ALL, $chunk_size = 100, $list = APC_LIST_ACTIVE) {} /** * Rewinds back the iterator to the first element * @link https://php.net/manual/en/apcuiterator.rewind.php */ public function rewind() {} /** * Checks if the current iterator position is valid * @link https://php.net/manual/en/apcuiterator.valid.php * @return bool Returns TRUE if the current iterator position is valid, otherwise FALSE. */ public function valid() {} /** * Gets the current item from the APCUIterator stack * @link https://php.net/manual/en/apcuiterator.current.php * @return mixed|false Returns the current item on success, or FALSE if no more items or exist, or on failure. */ public function current() {} /** * Gets the current iterator key * @link https://php.net/manual/en/apcuiterator.key.php * @return string|int|false Returns the key on success, or FALSE upon failure. */ public function key() {} /** * Moves the iterator pointer to the next element * @link https://php.net/manual/en/apcuiterator.next.php * @return bool Returns TRUE on success or FALSE on failure. */ public function next() {} /** * Gets the total number of cache hits * @link https://php.net/manual/en/apcuiterator.gettotalhits.php * @return int|false The number of hits on success, or FALSE on failure. */ public function getTotalHits() {} /** * Gets the total cache size * @link https://php.net/manual/en/apcuiterator.gettotalsize.php * @return int|false The total cache size. */ public function getTotalSize() {} /** * Get the total count * @link https://php.net/manual/en/apcuiterator.gettotalcount.php * @return int|false The total count. */ public function getTotalCount() {} } * Open MS SQL server connection * @link https://php.net/manual/en/function.mssql-connect.php * @param string $servername [optional]

    * The MS SQL server. It can also include a port number, e.g. * hostname:port (Linux), or * hostname,port (Windows). *

    * @param string $username [optional]

    * The username. *

    * @param string $password [optional]

    * The password. *

    * @param bool $new_link [optional]

    * If a second call is made to mssql_connect with the * same arguments, no new link will be established, but instead, the link * identifier of the already opened link will be returned. This parameter * modifies this behavior and makes mssql_connect * always open a new link, even if mssql_connect was * called before with the same parameters. *

    * @return resource|false a MS SQL link identifier on success, or false on error. * @removed 7.0 */ function mssql_connect($servername = null, $username = null, $password = null, $new_link = false) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Open persistent MS SQL connection * @link https://php.net/manual/en/function.mssql-pconnect.php * @param string $servername [optional]

    * The MS SQL server. It can also include a port number. e.g. * hostname:port. *

    * @param string $username [optional]

    * The username. *

    * @param string $password [optional]

    * The password. *

    * @param bool $new_link [optional]

    * If a second call is made to mssql_pconnect with * the same arguments, no new link will be established, but instead, the * link identifier of the already opened link will be returned. This * parameter modifies this behavior and makes * mssql_pconnect always open a new link, even if * mssql_pconnect was called before with the same * parameters. *

    * @return resource|false a positive MS SQL persistent link identifier on success, or * false on error. * @removed 7.0 */ function mssql_pconnect($servername = null, $username = null, $password = null, $new_link = false) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Close MS SQL Server connection * @link https://php.net/manual/en/function.mssql-close.php * @param resource $link_identifier [optional]

    * A MS SQL link identifier, returned by * mssql_connect. *

    *

    * This function will not close persistent links generated by * mssql_pconnect. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function mssql_close($link_identifier = null) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Select MS SQL database * @link https://php.net/manual/en/function.mssql-select-db.php * @param string $database_name

    * The database name. *

    *

    * To escape the name of a database that contains spaces, hyphens ("-"), * or any other exceptional characters, the database name must be * enclosed in brackets, as is shown in the example, below. This * technique must also be applied when selecting a database name that is * also a reserved word (such as primary). *

    * @param resource $link_identifier [optional]

    * A MS SQL link identifier, returned by * mssql_connect or * mssql_pconnect. *

    *

    * If no link identifier is specified, the last opened link is assumed. * If no link is open, the function will try to establish a link as if * mssql_connect was called, and use it. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function mssql_select_db($database_name, $link_identifier = null) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Send MS SQL query * @link https://php.net/manual/en/function.mssql-query.php * @param string $query

    * An SQL query. *

    * @param resource $link_identifier [optional]

    * A MS SQL link identifier, returned by * mssql_connect or * mssql_pconnect. *

    *

    * If the link identifier isn't specified, the last opened link is * assumed. If no link is open, the function tries to establish a link * as if mssql_connect was called, and use it. *

    * @param int $batch_size [optional]

    * The number of records to batch in the buffer. *

    * @return resource|bool a MS SQL result resource on success, true if no rows were * returned, or false on error. * @removed 7.0 */ function mssql_query($query, $link_identifier = null, $batch_size = 0) {} /** * (PHP 4 >= 4.0.4, PHP 5, PECL odbtp >= 1.1.1)
    * Returns the next batch of records * @link https://php.net/manual/en/function.mssql-fetch-batch.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @return int the batch number as an integer. * @removed 7.0 */ function mssql_fetch_batch($result) {} /** * (PHP 4 >= 4.0.4, PHP 5, PECL odbtp >= 1.1.1)
    * Returns the number of records affected by the query * @link https://php.net/manual/en/function.mssql-rows-affected.php * @param resource $link_identifier

    * A MS SQL link identifier, returned by * mssql_connect or * mssql_pconnect. *

    * @return int the number of records affected by last operation. * @removed 7.0 */ function mssql_rows_affected($link_identifier) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Free result memory * @link https://php.net/manual/en/function.mssql-free-result.php * @param resource $result

    * The result resource that is being freed. This result comes from a * call to mssql_query. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function mssql_free_result($result) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Returns the last message from the server * @link https://php.net/manual/en/function.mssql-get-last-message.php * @return string last error message from server, or an empty string if * no error messages are returned from MSSQL. * @removed 7.0 */ function mssql_get_last_message() {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Gets the number of rows in result * @link https://php.net/manual/en/function.mssql-num-rows.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @return int the number of rows, as an integer. * @removed 7.0 */ function mssql_num_rows($result) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Gets the number of fields in result * @link https://php.net/manual/en/function.mssql-num-fields.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @return int the number of fields, as an integer. * @removed 7.0 */ function mssql_num_fields($result) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Get field information * @link https://php.net/manual/en/function.mssql-fetch-field.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @param int $field_offset [optional]

    * The numerical field offset. If the field offset is not specified, the * next field that was not yet retrieved by this function is retrieved. The * field_offset starts at 0. *

    * @return object an object containing field information. * @removed 7.0 */ function mssql_fetch_field($result, $field_offset = -1) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Get row as enumerated array * @link https://php.net/manual/en/function.mssql-fetch-row.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @return array|false an array that corresponds to the fetched row, or false if there * are no more rows. * @removed 7.0 */ function mssql_fetch_row($result) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Fetch a result row as an associative array, a numeric array, or both * @link https://php.net/manual/en/function.mssql-fetch-array.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @param int $result_type [optional]

    * The type of array that is to be fetched. It's a constant and can take * the following values: MSSQL_ASSOC, * MSSQL_NUM, and * MSSQL_BOTH. *

    * @return array|false an array that corresponds to the fetched row, or false if there * are no more rows. * @removed 7.0 */ function mssql_fetch_array($result, $result_type = MSSQL_BOTH) {} /** * (PHP 4 >= 4.2.0, PHP 5, PECL odbtp >= 1.1.1)
    * Returns an associative array of the current row in the result * @link https://php.net/manual/en/function.mssql-fetch-assoc.php * @param resource $result_id

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @return array an associative array that corresponds to the fetched row, or * false if there are no more rows. * @removed 7.0 */ function mssql_fetch_assoc($result_id) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Fetch row as object * @link https://php.net/manual/en/function.mssql-fetch-object.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @return object an object with properties that correspond to the fetched row, or * false if there are no more rows. * @removed 7.0 */ function mssql_fetch_object($result) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Get the length of a field * @link https://php.net/manual/en/function.mssql-field-length.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @param int $offset [optional]

    * The field offset, starts at 0. If omitted, the current field is used. *

    * @return int|false The length of the specified field index on success or false on failure. * @removed 7.0 */ function mssql_field_length($result, $offset = null) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Get the name of a field * @link https://php.net/manual/en/function.mssql-field-name.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @param int $offset [optional]

    * The field offset, starts at 0. If omitted, the current field is used. *

    * @return string|false The name of the specified field index on success or false on failure. * @removed 7.0 */ function mssql_field_name($result, $offset = -1) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Gets the type of a field * @link https://php.net/manual/en/function.mssql-field-type.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @param int $offset [optional]

    * The field offset, starts at 0. If omitted, the current field is used. *

    * @return string|false The type of the specified field index on success or false on failure. * @removed 7.0 */ function mssql_field_type($result, $offset = -1) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Moves internal row pointer * @link https://php.net/manual/en/function.mssql-data-seek.php * @param resource $result_identifier

    * The result resource that is being evaluated. *

    * @param int $row_number

    * The desired row number of the new result pointer. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function mssql_data_seek($result_identifier, $row_number) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Seeks to the specified field offset * @link https://php.net/manual/en/function.mssql-field-seek.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @param int $field_offset

    * The field offset, starts at 0. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function mssql_field_seek($result, $field_offset) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Get result data * @link https://php.net/manual/en/function.mssql-result.php * @param resource $result

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @param int $row

    * The row number. *

    * @param mixed $field

    * Can be the field's offset, the field's name or the field's table dot * field's name (tablename.fieldname). If the column name has been * aliased ('select foo as bar from...'), it uses the alias instead of * the column name. *

    *

    * Specifying a numeric offset for the field * argument is much quicker than specifying a * fieldname or * tablename.fieldname argument. *

    * @return string the contents of the specified cell. * @removed 7.0 */ function mssql_result($result, $row, $field) {} /** * (PHP 4 >= 4.0.5, PHP 5, PECL odbtp >= 1.1.1)
    * Move the internal result pointer to the next result * @link https://php.net/manual/en/function.mssql-next-result.php * @param resource $result_id

    * The result resource that is being evaluated. This result comes from a * call to mssql_query. *

    * @return bool true if an additional result set was available or false * otherwise. * @removed 7.0 */ function mssql_next_result($result_id) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Sets the minimum error severity * @link https://php.net/manual/en/function.mssql-min-error-severity.php * @param int $severity

    * The new error severity. *

    * @return void * @removed 7.0 */ function mssql_min_error_severity($severity) {} /** * (PHP 4, PHP 5, PECL odbtp >= 1.1.1)
    * Sets the minimum message severity * @link https://php.net/manual/en/function.mssql-min-message-severity.php * @param int $severity

    * The new message severity. *

    * @return void * @removed 7.0 */ function mssql_min_message_severity($severity) {} /** * (PHP 4 >= 4.0.7, PHP 5, PECL odbtp >= 1.1.1)
    * Initializes a stored procedure or a remote stored procedure * @link https://php.net/manual/en/function.mssql-init.php * @param string $sp_name

    * Stored procedure name, like ownew.sp_name or * otherdb.owner.sp_name. *

    * @param resource $link_identifier [optional]

    * A MS SQL link identifier, returned by * mssql_connect. *

    * @return resource|false a resource identifier "statement", used in subsequent calls to * mssql_bind and mssql_execute, * or false on errors. * @removed 7.0 */ function mssql_init($sp_name, $link_identifier = null) {} /** * (PHP 4 >= 4.0.7, PHP 5, PECL odbtp >= 1.1.1)
    * Adds a parameter to a stored procedure or a remote stored procedure * @link https://php.net/manual/en/function.mssql-bind.php * @param resource $stmt

    * Statement resource, obtained with mssql_init. *

    * @param string $param_name

    * The parameter name, as a string. *

    *

    * You have to include the @ character, like in the * T-SQL syntax. See the explanation included in * mssql_execute. *

    * @param mixed &$var

    * The PHP variable you'll bind the MSSQL parameter to. It is passed by * reference, to retrieve OUTPUT and RETVAL values after * the procedure execution. *

    * @param int $type

    * One of: SQLTEXT, * SQLVARCHAR, SQLCHAR, * SQLINT1, SQLINT2, * SQLINT4, SQLBIT, * SQLFLT4, SQLFLT8, * SQLFLTN. *

    * @param bool $is_output [optional]

    * Whether the value is an OUTPUT parameter or not. If it's an OUTPUT * parameter and you don't mention it, it will be treated as a normal * input parameter and no error will be thrown. *

    * @param bool $is_null [optional]

    * Whether the parameter is null or not. Passing the null value as * var will not do the job. *

    * @param int $maxlen [optional]

    * Used with char/varchar values. You have to indicate the length of the * data so if the parameter is a varchar(50), the type must be * SQLVARCHAR and this value 50. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function mssql_bind($stmt, $param_name, &$var, $type, $is_output = false, $is_null = false, $maxlen = -1) {} /** * (PHP 4 >= 4.0.7, PHP 5, PECL odbtp >= 1.1.1)
    * Executes a stored procedure on a MS SQL server database * @link https://php.net/manual/en/function.mssql-execute.php * @param resource $stmt

    * Statement handle obtained with mssql_init. *

    * @param bool $skip_results [optional]

    * Whenever to skip the results or not. *

    * @return mixed * @removed 7.0 */ function mssql_execute($stmt, $skip_results = false) {} /** * (PHP 4 >= 4.3.2, PHP 5, PECL odbtp >= 1.1.1)
    * Free statement memory * @link https://php.net/manual/en/function.mssql-free-statement.php * @param resource $stmt

    * Statement resource, obtained with mssql_init. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function mssql_free_statement($stmt) {} /** * (PHP 4 >= 4.0.7, PHP 5, PECL odbtp >= 1.1.1)
    * Converts a 16 byte binary GUID to a string * @link https://php.net/manual/en/function.mssql-guid-string.php * @param string $binary

    * A 16 byte binary GUID. *

    * @param bool $short_format [optional]

    * Whenever to use short format. *

    * @return string the converted string on success. * @removed 7.0 */ function mssql_guid_string($binary, $short_format = null) {} /** * Return an associative array. Used on * mssql_fetch_array's * result_type parameter. * @link https://php.net/manual/en/mssql.constants.php */ define('MSSQL_ASSOC', 1); /** * Return an array with numeric keys. Used on * mssql_fetch_array's * result_type parameter. * @link https://php.net/manual/en/mssql.constants.php */ define('MSSQL_NUM', 2); /** * Return an array with both numeric keys and * keys with their field name. This is the * default value for mssql_fetch_array's * result_type parameter. * @link https://php.net/manual/en/mssql.constants.php */ define('MSSQL_BOTH', 3); /** * Indicates the 'TEXT' type in MSSQL, used by * mssql_bind's type * parameter. * @link https://php.net/manual/en/mssql.constants.php */ define('SQLTEXT', 35); /** * Indicates the 'VARCHAR' type in MSSQL, used by * mssql_bind's type * parameter. * @link https://php.net/manual/en/mssql.constants.php */ define('SQLVARCHAR', 39); /** * Indicates the 'CHAR' type in MSSQL, used by * mssql_bind's type * parameter. * @link https://php.net/manual/en/mssql.constants.php */ define('SQLCHAR', 47); /** * Represents one byte, with a range of -128 to 127. * @link https://php.net/manual/en/mssql.constants.php */ define('SQLINT1', 48); /** * Represents two bytes, with a range of -32768 * to 32767. * @link https://php.net/manual/en/mssql.constants.php */ define('SQLINT2', 52); /** * Represents four bytes, with a range of -2147483648 * to 2147483647. * @link https://php.net/manual/en/mssql.constants.php */ define('SQLINT4', 56); /** * Indicates the 'BIT' type in MSSQL, used by * mssql_bind's type * parameter. * @link https://php.net/manual/en/mssql.constants.php */ define('SQLBIT', 50); /** * Represents an four byte float. * @link https://php.net/manual/en/mssql.constants.php */ define('SQLFLT4', 59); /** * Represents an eight byte float. * @link https://php.net/manual/en/mssql.constants.php */ define('SQLFLT8', 62); define('SQLFLTN', 109); // End of mssql v. TRUE on success or FALSE on failure. * @since 5.1.2 */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function close() {} /** * Get the value of a named attribute * @link https://php.net/manual/en/xmlreader.getattribute.php * @param string $name

    * The name of the attribute. *

    * @return string|null The value of the attribute, or NULL if no attribute with the given * name is found or not positioned on an element node. * @since 5.1.2 */ #[TentativeType] public function getAttribute(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): ?string {} /** * Get the value of an attribute by index * @link https://php.net/manual/en/xmlreader.getattributeno.php * @param int $index

    * The position of the attribute. *

    * @return string|null The value of the attribute, or NULL if no attribute exists * at index or not positioned of element. * @since 5.1.2 */ #[TentativeType] public function getAttributeNo(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index): ?string {} /** * Get the value of an attribute by localname and URI * @link https://php.net/manual/en/xmlreader.getattributens.php * @param string $name

    * The local name. *

    * @param string $namespace

    * The namespace URI. *

    * @return string|null The value of the attribute, or NULL if no attribute with the * given localName and * namespaceURI is found or not positioned of element. * @since 5.1.2 */ #[TentativeType] public function getAttributeNs( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace ): ?string {} /** * Indicates if specified property has been set * @link https://php.net/manual/en/xmlreader.getparserproperty.php * @param int $property

    * One of the parser option * constants. *

    * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function getParserProperty(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $property): bool {} /** * Indicates if the parsed document is valid * @link https://php.net/manual/en/xmlreader.isvalid.php * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function isValid(): bool {} /** * Lookup namespace for a prefix * @link https://php.net/manual/en/xmlreader.lookupnamespace.php * @param string $prefix

    * String containing the prefix. *

    * @return string|null TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function lookupNamespace(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $prefix): ?string {} /** * Move cursor to an attribute by index * @link https://php.net/manual/en/xmlreader.movetoattributeno.php * @param int $index

    * The position of the attribute. *

    * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function moveToAttributeNo(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index): bool {} /** * Move cursor to a named attribute * @link https://php.net/manual/en/xmlreader.movetoattribute.php * @param string $name

    * The name of the attribute. *

    * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function moveToAttribute(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): bool {} /** * Move cursor to a named attribute * @link https://php.net/manual/en/xmlreader.movetoattributens.php * @param string $name

    * The local name. *

    * @param string $namespace

    * The namespace URI. *

    * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function moveToAttributeNs( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace ): bool {} /** * Position cursor on the parent Element of current Attribute * @link https://php.net/manual/en/xmlreader.movetoelement.php * @return bool TRUE if successful and FALSE if it fails or not positioned on * Attribute when this method is called. * @since 5.1.2 */ #[TentativeType] public function moveToElement(): bool {} /** * Position cursor on the first Attribute * @link https://php.net/manual/en/xmlreader.movetofirstattribute.php * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function moveToFirstAttribute(): bool {} /** * Position cursor on the next Attribute * @link https://php.net/manual/en/xmlreader.movetonextattribute.php * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function moveToNextAttribute(): bool {} /** * Set the URI containing the XML to parse * @link https://php.net/manual/en/xmlreader.open.php * @param string $uri

    * URI pointing to the document. *

    * @param string $encoding [optional]

    * The document encoding or NULL. *

    * @param int $flags [optional]

    * A bitmask of the LIBXML_* * constants. *

    * @return XMLReader|bool TRUE on success or FALSE on failure. If called statically, returns an * XMLReader or FALSE on failure. * @since 5.1.2 */ public static function open( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $uri, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $encoding = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0 ) {} /** * Move to next node in document * @link https://php.net/manual/en/xmlreader.read.php * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function read(): bool {} /** * Move cursor to next node skipping all subtrees * @link https://php.net/manual/en/xmlreader.next.php * @param string $name [optional]

    * The name of the next node to move to. *

    * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function next(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $name = null): bool {} /** * Retrieve XML from current node * @link https://php.net/manual/en/xmlreader.readinnerxml.php * @return string the contents of the current node as a string. Empty string on failure. */ #[TentativeType] public function readInnerXml(): string {} /** * Retrieve XML from current node, including it self * @link https://php.net/manual/en/xmlreader.readouterxml.php * @return string the contents of current node, including itself, as a string. Empty string on failure. */ #[TentativeType] public function readOuterXml(): string {} /** * Reads the contents of the current node as a string * @link https://php.net/manual/en/xmlreader.readstring.php * @return string the content of the current node as a string. Empty string on * failure. */ #[TentativeType] public function readString(): string {} /** * Validate document against XSD * @link https://php.net/manual/en/xmlreader.setschema.php * @param string $filename

    * The filename of the XSD schema. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setSchema(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $filename): bool {} /** * Set parser options * @link https://php.net/manual/en/xmlreader.setparserproperty.php * @param int $property

    * One of the parser option * constants. *

    * @param bool $value

    * If set to TRUE the option will be enabled otherwise will * be disabled. *

    * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function setParserProperty( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $property, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $value ): bool {} /** * Set the filename or URI for a RelaxNG Schema * @link https://php.net/manual/en/xmlreader.setrelaxngschema.php * @param string $filename

    * filename or URI pointing to a RelaxNG Schema. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setRelaxNGSchema(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $filename): bool {} /** * Set the data containing a RelaxNG Schema * @link https://php.net/manual/en/xmlreader.setrelaxngschemasource.php * @param string $source

    * String containing the RelaxNG Schema. *

    * @return bool TRUE on success or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function setRelaxNGSchemaSource(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $source): bool {} /** * Set the data containing the XML to parse * @link https://php.net/manual/en/xmlreader.xml.php * @param string $source

    * String containing the XML to be parsed. *

    * @param string $encoding [optional]

    * The document encoding or NULL. *

    * @param int $flags [optional]

    * A bitmask of the LIBXML_* * constants. *

    * @return XMLReader|bool TRUE on success or FALSE on failure. If called statically, returns an * XMLReader or FALSE on failure. * @since 5.1.2 */ public static function XML( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $source, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $encoding = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0 ) {} /** * Returns a copy of the current node as a DOM object * @link https://php.net/manual/en/xmlreader.expand.php * @param null|DOMNode $baseNode [optional] * @return DOMNode|false The resulting DOMNode or FALSE on error. * @since 5.1.2 */ #[TentativeType] public function expand( #[PhpStormStubsElementAvailable(from: '7.0')] #[LanguageLevelTypeAware(['8.0' => 'DOMNode|null'], default: '')] $baseNode = null ): DOMNode|false {} /** * @since 8.4 */ public static function fromUri(string $uri, ?string $encoding = null, int $flags = 0): static {} /** * @since 8.4 */ public static function fromStream($stream, ?string $encoding = null, int $flags = 0, ?string $documentUri = null): static {} /** * @since 8.4 */ public static function fromString(string $source, ?string $encoding = null, int $flags = 0): static {} } // End of xmlreader v.0.2 ' before the name means push. Use the signature without id for either continuation or to * start matching, when a continuation or recursion is required. * If '<' is specified as exit state, it means pop. In that case, the signature containing the id can be used to * identify the match. Note that even in the case an id is specified, the rule will finish first when all the * previous pushes popped. * @return void * @link https://php.net/manual/en/parle-rlexer.push.php */ public function push(string $state, string $regex, int $id, string $newState): void {} /** * Add a lexer rule * * Push a pattern for lexeme recognition. * A 'start state' and 'exit state' can be specified by using a suitable signature. * * @param string $state State name. If '*' is used as start state, then the rule is applied to all lexer states. * @param string $regex Regular expression used for token matching. * @param string $newState * New state name, after the rule was applied. * If '.' is specified as the exit state, then the lexer state is unchanged when that rule matches. * An exit state with '>' before the name means push. Use the signature without id for either continuation or to * start matching, when a continuation or recursion is required. * If '<' is specified as exit state, it means pop. In that case, the signature containing the id can be used to * identify the match. Note that even in the case an id is specified, the rule will finish first when all the * previous pushes popped. * @return void * @link https://php.net/manual/en/parle-rlexer.push.php */ public function push(string $state, string $regex, string $newState): void {} /** * Push a new start state * This lexer type can have more than one state machine. * This allows you to lex different tokens depending on context, thus allowing simple parsing to take place. * Once a state pushed, it can be used with a suitable Parle\RLexer::push() signature variant. * * @see RLexer::push() * @link https://php.net/manual/en/parle-rlexer.pushstate.php * @param string $state Name of the state. * @return int */ public function pushState(string $state): int {} /** * Reset lexer * * Reset lexing optionally supplying the desired offset. * * @param int $pos Reset position. */ public function reset(int $pos): void {} } * The number of processes that can acquire the semaphore simultaneously * is set to max_acquire. *

    * @param int $permissions [optional]

    * The semaphore permissions. Actually this value is * set only if the process finds it is the only process currently * attached to the semaphore. *

    * @param bool $auto_release [optional]

    * Specifies if the semaphore should be automatically released on request * shutdown. *

    * @return resource|false|SysvSemaphore a positive semaphore identifier on success, or FALSE on * error. */ #[LanguageLevelTypeAware(["8.0" => "SysvSemaphore|false"], default: "resource|false")] function sem_get(int $key, int $max_acquire = 1, int $permissions = 0666, bool $auto_release = true) {} /** * Acquire a semaphore * @link https://php.net/manual/en/function.sem-acquire.php * @param SysvSemaphore|resource $semaphore

    * sem_identifier is a semaphore resource, * obtained from sem_get. *

    * @param bool $non_blocking [optional]

    * Specifies if the process shouldn't wait for the semaphore to be acquired. * If set to true, the call will return false immediately if a * semaphore cannot be immediately acquired. *

    * @return bool TRUE on success or FALSE on failure. */ function sem_acquire(#[LanguageLevelTypeAware(["8.0" => "SysvSemaphore"], default: "resource")] $semaphore, bool $non_blocking = false): bool {} /** * Release a semaphore * @link https://php.net/manual/en/function.sem-release.php * @param SysvSemaphore|resource $semaphore

    * A Semaphore resource handle as returned by * sem_get. *

    * @return bool TRUE on success or FALSE on failure. */ function sem_release(#[LanguageLevelTypeAware(["8.0" => "SysvSemaphore"], default: "resource")] $semaphore): bool {} /** * Remove a semaphore * @link https://php.net/manual/en/function.sem-remove.php * @param SysvSemaphore|resource $semaphore

    * A semaphore resource identifier as returned * by sem_get. *

    * @return bool TRUE on success or FALSE on failure. */ function sem_remove(#[LanguageLevelTypeAware(["8.0" => "SysvSemaphore"], default: "resource")] $semaphore): bool {} /** * @since 8.0 */ final class SysvSemaphore { /** * Cannot directly construct SysvSemaphore, use sem_get() instead * @see sem_get() */ private function __construct() {} } // End of sysvsem v. * The string being converted. *

    * @param int $mode

    * The mode of the conversion. It can be one of * MB_CASE_UPPER, * MB_CASE_LOWER, or * MB_CASE_TITLE. *

    * @param string|null $encoding [optional] * @return string A case folded version of string converted in the * way specified by mode. */ #[Pure] function mb_convert_case(string $string, int $mode, ?string $encoding): string {} /** * Make a string uppercase * @link https://php.net/manual/en/function.mb-strtoupper.php * @param string $string

    * The string being uppercased. *

    * @param string|null $encoding [optional] * @return string str with all alphabetic characters converted to uppercase. */ #[Pure] function mb_strtoupper(string $string, ?string $encoding): string {} /** * Make a string lowercase * @link https://php.net/manual/en/function.mb-strtolower.php * @param string $string

    * The string being lowercased. *

    * @param string|null $encoding [optional] * @return string str with all alphabetic characters converted to lowercase. */ #[Pure] function mb_strtolower(string $string, ?string $encoding): string {} /** * Set/Get current language * @link https://php.net/manual/en/function.mb-language.php * @param string|null $language [optional]

    * Used for encoding * e-mail messages. Valid languages are "Japanese", * "ja","English","en" and "uni" * (UTF-8). mb_send_mail uses this setting to * encode e-mail. *

    *

    * Language and its setting is ISO-2022-JP/Base64 for * Japanese, UTF-8/Base64 for uni, ISO-8859-1/quoted printable for * English. *

    * @return bool|string If language is set and * language is valid, it returns * true. Otherwise, it returns false. * When language is omitted, it returns the language * name as a string. If no language is set previously, it then returns * false. */ function mb_language(?string $language): string|bool {} /** * Set/Get internal character encoding * @link https://php.net/manual/en/function.mb-internal-encoding.php * @param string|null $encoding [optional]

    * encoding is the character encoding name * used for the HTTP input character encoding conversion, HTTP output * character encoding conversion, and the default character encoding * for string functions defined by the mbstring module. *

    * @return bool|string If encoding is set, then * true on success or false on failure. * If encoding is omitted, then * the current character encoding name is returned. */ function mb_internal_encoding(?string $encoding): string|bool {} /** * Detect HTTP input character encoding * @link https://php.net/manual/en/function.mb-http-input.php * @param string|null $type [optional]

    * Input string specifies the input type. * "G" for GET, "P" for POST, "C" for COOKIE, "S" for string, "L" for list, and * "I" for the whole list (will return array). * If type is omitted, it returns the last input type processed. *

    * @return array|false|string The character encoding name, as per the type. * If mb_http_input does not process specified * HTTP input, it returns false. */ #[Pure] function mb_http_input(?string $type): array|string|false {} /** * Set/Get HTTP output character encoding * @link https://php.net/manual/en/function.mb-http-output.php * @param string|null $encoding [optional]

    * If encoding is set, * mb_http_output sets the HTTP output character * encoding to encoding. *

    *

    * If encoding is omitted, * mb_http_output returns the current HTTP output * character encoding. *

    * @return bool|string If encoding is omitted, * mb_http_output returns the current HTTP output * character encoding. Otherwise, * true on success or false on failure. */ function mb_http_output(?string $encoding): string|bool {} /** * Set/Get character encoding detection order * @link https://php.net/manual/en/function.mb-detect-order.php * @param array|string|null $encoding [optional]

    * encoding_list is an array or * comma separated list of character encoding. ("auto" is expanded to * "ASCII, JIS, UTF-8, EUC-JP, SJIS") *

    *

    * If encoding_list is omitted, it returns * the current character encoding detection order as array. *

    *

    * This setting affects mb_detect_encoding and * mb_send_mail. *

    *

    * mbstring currently implements the following * encoding detection filters. If there is an invalid byte sequence * for the following encodings, encoding detection will fail. *

    * UTF-8, UTF-7, * ASCII, * EUC-JP,SJIS, * eucJP-win, SJIS-win, * JIS, ISO-2022-JP *

    * For ISO-8859-*, mbstring * always detects as ISO-8859-*. *

    *

    * For UTF-16, UTF-32, * UCS2 and UCS4, encoding * detection will fail always. *

    *

    * Useless detect order example *

    * @return bool|string[] When setting the encoding detection order, * true is returned on success or FALSE on failure. * When getting the encoding detection order, an ordered array * of the encodings is returned. */ #[LanguageLevelTypeAware(['8.2' => 'array|true'], default: 'array|bool')] function mb_detect_order(array|string|null $encoding = null): array|bool {} /** * Set/Get substitution character * @link https://php.net/manual/en/function.mb-substitute-character.php * @param string|int|null $substitute_character [optional]

    * Specify the Unicode value as an integer, * or as one of the following strings:

      *
    • "none" : no output
    • *
    • "long": Output character code value (Example: U+3000, JIS+7E7E)
    • *
    • "entity": Output character entity (Example: Ȁ)
    • *
    * @return bool|int|string If substchar is set, it returns true for success, * otherwise returns false. * If substchar is not set, it returns the Unicode value, * or "none" or "long". */ function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool {} /** * Parse GET/POST/COOKIE data and set global variable * @link https://php.net/manual/en/function.mb-parse-str.php * @param string $string

    * The URL encoded data. *

    * @param array &$result [optional]

    * An array containing decoded and character encoded converted values. *

    * @return bool true on success or false on failure. */ #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] function mb_parse_str(string $string, &$result): bool {} /** * Parse GET/POST/COOKIE data and set global variable * @link https://php.net/manual/en/function.mb-parse-str.php * @param string $string

    * The URL encoded data. *

    * @param array &$result

    * An array containing decoded and character encoded converted values. *

    * @return bool true on success or false on failure. */ #[PhpStormStubsElementAvailable(from: '8.0')] function mb_parse_str(string $string, &$result): bool {} /** * Callback function converts character encoding in output buffer * @link https://php.net/manual/en/function.mb-output-handler.php * @param string $string

    * The contents of the output buffer. *

    * @param int $status

    * The status of the output buffer. *

    * @return string The converted string. */ #[Pure] function mb_output_handler(string $string, int $status): string {} /** * Get MIME charset string * @link https://php.net/manual/en/function.mb-preferred-mime-name.php * @param string $encoding

    * The encoding being checked. *

    * @return string|false The MIME charset string for character encoding * encoding. */ #[Pure] function mb_preferred_mime_name(string $encoding): string|false {} /** * Get string length * @link https://php.net/manual/en/function.mb-strlen.php * @param string $string

    * The string being checked for length. *

    * @param string|null $encoding [optional] * @return int|false the number of characters in * string str having character encoding * encoding. A multi-byte character is * counted as 1. */ #[Pure] #[LanguageLevelTypeAware(['8.0' => 'int'], default: 'int|false')] function mb_strlen(string $string, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: 'string')] $encoding) {} /** * Find position of first occurrence of string in a string * @link https://php.net/manual/en/function.mb-strpos.php * @param string $haystack

    * The string being checked. *

    * @param string $needle

    * The position counted from the beginning of haystack. *

    * @param int<0,max> $offset [optional]

    * The search offset. If it is not specified, 0 is used. *

    * @param string|null $encoding [optional] * @return int<0,max>|false the numeric position of * the first occurrence of needle in the * haystack string. If * needle is not found, it returns false. */ #[Pure] function mb_strpos(string $haystack, string $needle, int $offset = 0, ?string $encoding): int|false {} /** * Find position of last occurrence of a string in a string * @link https://php.net/manual/en/function.mb-strrpos.php * @param string $haystack

    * The string being checked, for the last occurrence * of needle *

    * @param string $needle

    * The string to find in haystack. *

    * @param int $offset [optional] May be specified to begin searching an arbitrary number of characters into * the string. Negative values will stop searching at an arbitrary point * prior to the end of the string. * @param string|null $encoding [optional] * @return int|false the numeric position of * the last occurrence of needle in the * haystack string. If * needle is not found, it returns false. */ #[Pure] function mb_strrpos(string $haystack, string $needle, int $offset = 0, ?string $encoding): int|false {} /** * Finds position of first occurrence of a string within another, case insensitive * @link https://php.net/manual/en/function.mb-stripos.php * @param string $haystack

    * The string from which to get the position of the first occurrence * of needle *

    * @param string $needle

    * The string to find in haystack *

    * @param int $offset [optional]

    * The position in haystack * to start searching *

    * @param string|null $encoding [optional]

    * Character encoding name to use. * If it is omitted, internal character encoding is used. *

    * @return int|false Return the numeric position of the first occurrence of * needle in the haystack * string, or false if needle is not found. */ #[Pure] function mb_stripos(string $haystack, string $needle, int $offset = 0, ?string $encoding): int|false {} /** * Finds position of last occurrence of a string within another, case insensitive * @link https://php.net/manual/en/function.mb-strripos.php * @param string $haystack

    * The string from which to get the position of the last occurrence * of needle *

    * @param string $needle

    * The string to find in haystack *

    * @param int $offset [optional]

    * The position in haystack * to start searching *

    * @param string|null $encoding [optional]

    * Character encoding name to use. * If it is omitted, internal character encoding is used. *

    * @return int|false Return the numeric position of * the last occurrence of needle in the * haystack string, or false * if needle is not found. */ #[Pure] function mb_strripos(string $haystack, string $needle, int $offset = 0, ?string $encoding): int|false {} /** * Finds first occurrence of a string within another * @link https://php.net/manual/en/function.mb-strstr.php * @param string $haystack

    * The string from which to get the first occurrence * of needle *

    * @param string $needle

    * The string to find in haystack *

    * @param bool $before_needle [optional]

    * Determines which portion of haystack * this function returns. * If set to true, it returns all of haystack * from the beginning to the first occurrence of needle. * If set to false, it returns all of haystack * from the first occurrence of needle to the end, *

    * @param string|null $encoding [optional]

    * Character encoding name to use. * If it is omitted, internal character encoding is used. *

    * @return string|false the portion of haystack, * or false if needle is not found. */ #[Pure] function mb_strstr(string $haystack, string $needle, bool $before_needle = false, ?string $encoding): string|false {} /** * Finds the last occurrence of a character in a string within another * @link https://php.net/manual/en/function.mb-strrchr.php * @param string $haystack

    * The string from which to get the last occurrence * of needle *

    * @param string $needle

    * The string to find in haystack *

    * @param bool $before_needle [optional]

    * Determines which portion of haystack * this function returns. * If set to true, it returns all of haystack * from the beginning to the last occurrence of needle. * If set to false, it returns all of haystack * from the last occurrence of needle to the end, *

    * @param string|null $encoding [optional]

    * Character encoding name to use. * If it is omitted, internal character encoding is used. *

    * @return string|false the portion of haystack. * or false if needle is not found. */ #[Pure] function mb_strrchr(string $haystack, string $needle, bool $before_needle = false, ?string $encoding): string|false {} /** * Finds first occurrence of a string within another, case insensitive * @link https://php.net/manual/en/function.mb-stristr.php * @param string $haystack

    * The string from which to get the first occurrence * of needle *

    * @param string $needle

    * The string to find in haystack *

    * @param bool $before_needle [optional]

    * Determines which portion of haystack * this function returns. * If set to true, it returns all of haystack * from the beginning to the first occurrence of needle. * If set to false, it returns all of haystack * from the first occurrence of needle to the end, *

    * @param string|null $encoding [optional]

    * Character encoding name to use. * If it is omitted, internal character encoding is used. *

    * @return string|false the portion of haystack, * or false if needle is not found. */ #[Pure] function mb_stristr(string $haystack, string $needle, bool $before_needle = false, ?string $encoding): string|false {} /** * Finds the last occurrence of a character in a string within another, case insensitive * @link https://php.net/manual/en/function.mb-strrichr.php * @param string $haystack

    * The string from which to get the last occurrence * of needle *

    * @param string $needle

    * The string to find in haystack *

    * @param bool $before_needle [optional]

    * Determines which portion of haystack * this function returns. * If set to true, it returns all of haystack * from the beginning to the last occurrence of needle. * If set to false, it returns all of haystack * from the last occurrence of needle to the end, *

    * @param string|null $encoding [optional]

    * Character encoding name to use. * If it is omitted, internal character encoding is used. *

    * @return string|false the portion of haystack. * or false if needle is not found. */ #[Pure] function mb_strrichr(string $haystack, string $needle, bool $before_needle = false, ?string $encoding): string|false {} /** * Count the number of substring occurrences * @link https://php.net/manual/en/function.mb-substr-count.php * @param string $haystack

    * The string being checked. *

    * @param string $needle

    * The string being found. *

    * @param string|null $encoding [optional] * @return int The number of times the * needle substring occurs in the * haystack string. */ #[Pure] function mb_substr_count(string $haystack, string $needle, ?string $encoding): int {} /** * Get part of string * @link https://php.net/manual/en/function.mb-substr.php * @param string $string

    * The string being checked. *

    * @param int $start

    * The first position used in str. *

    * @param int|null $length [optional]

    * The maximum length of the returned string. *

    * @param string|null $encoding [optional] * @return string mb_substr returns the portion of * str specified by the * start and * length parameters. */ #[Pure] function mb_substr(string $string, int $start, ?int $length, ?string $encoding): string {} /** * Get part of string * @link https://php.net/manual/en/function.mb-strcut.php * @param string $string

    * The string being cut. *

    * @param int $start

    * The position that begins the cut. *

    * @param int|null $length [optional]

    * The string being decoded. *

    * @param string|null $encoding [optional] * @return string mb_strcut returns the portion of * str specified by the * start and * length parameters. */ #[Pure] function mb_strcut(string $string, int $start, ?int $length, ?string $encoding): string {} /** * Return width of string * @link https://php.net/manual/en/function.mb-strwidth.php * @param string $string

    * The string being decoded. *

    * @param string|null $encoding [optional] * @return int The width of string str. */ #[Pure] function mb_strwidth(string $string, ?string $encoding): int {} /** * Get truncated string with specified width * @link https://php.net/manual/en/function.mb-strimwidth.php * @param string $string

    * The string being decoded. *

    * @param int $start

    * The start position offset. Number of * characters from the beginning of string. (First character is 0) *

    * @param int $width

    * The width of the desired trim. *

    * @param string $trim_marker

    * A string that is added to the end of string * when string is truncated. *

    * @param string|null $encoding [optional] * @return string The truncated string. If trimmarker is set, * trimmarker is appended to the return value. */ #[Pure] function mb_strimwidth(string $string, int $start, int $width, string $trim_marker = '', ?string $encoding): string {} /** * Convert character encoding * @link https://php.net/manual/en/function.mb-convert-encoding.php * @param string|array $string

    * The string being encoded. *

    * @param string $to_encoding

    * The type of encoding that str is being converted to. *

    * @param string|string[]|null $from_encoding [optional]

    * Is specified by character code names before conversion. It is either * an array, or a comma separated enumerated list. * If from_encoding is not specified, the internal * encoding will be used. *

    *

    * "auto" may be used, which expands to * "ASCII,JIS,UTF-8,EUC-JP,SJIS". *

    * @return array|string|false The encoded string. */ #[Pure] function mb_convert_encoding(array|string $string, string $to_encoding, array|string|null $from_encoding = null): array|string|false {} /** * Detect character encoding * @link https://php.net/manual/en/function.mb-detect-encoding.php * @param string $string

    * The string being detected. *

    * @param string|string[]|null $encodings [optional]

    * encoding_list is list of character * encoding. Encoding order may be specified by array or comma * separated list string. *

    *

    * If encoding_list is omitted, * detect_order is used. *

    * @param bool $strict [optional]

    * strict specifies whether to use * the strict encoding detection or not. * Default is false. *

    * @return string|false The detected character encoding or false if the encoding cannot be * detected from the given string. */ #[Pure] function mb_detect_encoding(string $string, array|string|null $encodings = null, bool $strict = false): string|false {} /** * Returns an array of all supported encodings * @link https://php.net/manual/en/function.mb-list-encodings.php * @return string[] a numerically indexed array. */ #[Pure] function mb_list_encodings(): array {} /** * Get aliases of a known encoding type * @param string $encoding The encoding type being checked, for aliases. * @return string[]|false a numerically indexed array of encoding aliases on success, or FALSE on failure * @link https://php.net/manual/en/function.mb-encoding-aliases.php */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] function mb_encoding_aliases(string $encoding) {} /** * Convert "kana" one from another ("zen-kaku", "han-kaku" and more) * @link https://php.net/manual/en/function.mb-convert-kana.php * @param string $string

    * The string being converted. *

    * @param string $mode [optional]

    * The conversion option. *

    *

    * Specify with a combination of following options. *

    * Applicable Conversion Options * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    OptionMeaning
    r * Convert "zen-kaku" alphabets to "han-kaku" *
    R * Convert "han-kaku" alphabets to "zen-kaku" *
    n * Convert "zen-kaku" numbers to "han-kaku" *
    N * Convert "han-kaku" numbers to "zen-kaku" *
    a * Convert "zen-kaku" alphabets and numbers to "han-kaku" *
    A * Convert "han-kaku" alphabets and numbers to "zen-kaku" * (Characters included in "a", "A" options are * U+0021 - U+007E excluding U+0022, U+0027, U+005C, U+007E) *
    s * Convert "zen-kaku" space to "han-kaku" (U+3000 -> U+0020) *
    S * Convert "han-kaku" space to "zen-kaku" (U+0020 -> U+3000) *
    k * Convert "zen-kaku kata-kana" to "han-kaku kata-kana" *
    K * Convert "han-kaku kata-kana" to "zen-kaku kata-kana" *
    h * Convert "zen-kaku hira-gana" to "han-kaku kata-kana" *
    H * Convert "han-kaku kata-kana" to "zen-kaku hira-gana" *
    c * Convert "zen-kaku kata-kana" to "zen-kaku hira-gana" *
    C * Convert "zen-kaku hira-gana" to "zen-kaku kata-kana" *
    V * Collapse voiced sound notation and convert them into a character. Use with "K","H" *
    *

    * @param string|null $encoding [optional] * @return string The converted string. */ #[Pure] function mb_convert_kana(string $string, string $mode = 'KV', ?string $encoding): string {} /** * Encode string for MIME header * @link https://php.net/manual/en/function.mb-encode-mimeheader.php * @param string $string

    * The string being encoded. *

    * @param string|null $charset [optional]

    * charset specifies the name of the character set * in which str is represented in. The default value * is determined by the current NLS setting (mbstring.language). * mb_internal_encoding should be set to same encoding. *

    * @param string|null $transfer_encoding [optional]

    * transfer_encoding specifies the scheme of MIME * encoding. It should be either "B" (Base64) or * "Q" (Quoted-Printable). Falls back to * "B" if not given. *

    * @param string $newline [optional]

    * linefeed specifies the EOL (end-of-line) marker * with which mb_encode_mimeheader performs * line-folding (a RFC term, * the act of breaking a line longer than a certain length into multiple * lines. The length is currently hard-coded to 74 characters). * Falls back to "\r\n" (CRLF) if not given. *

    * @param int $indent

    * Indentation of the first line (number of characters in the header * before str). *

    * @return string A converted version of the string represented in ASCII. */ #[Pure] function mb_encode_mimeheader(string $string, ?string $charset, ?string $transfer_encoding, string $newline = "\r\n", int $indent = 0): string {} /** * Decode string in MIME header field * @link https://php.net/manual/en/function.mb-decode-mimeheader.php * @param string $string

    * The string being decoded. *

    * @return string The decoded string in internal character encoding. */ #[Pure] function mb_decode_mimeheader(string $string): string {} /** * Convert character code in variable(s) * @link https://php.net/manual/en/function.mb-convert-variables.php * @param string $to_encoding

    * The encoding that the string is being converted to. *

    * @param string|string[] $from_encoding

    * from_encoding is specified as an array * or comma separated string, it tries to detect encoding from * from-coding. When from_encoding * is omitted, detect_order is used. *

    * @param string|array|object &$var var is the reference to the variable being converted. * @param string|array|object &...$vars

    * vars is the other references to the * variables being converted. String, Array and Object are accepted. * mb_convert_variables assumes all parameters * have the same encoding. *

    * @return string|false The character encoding before conversion for success, * or false for failure. */ function mb_convert_variables( string $to_encoding, array|string $from_encoding, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] &$vars, #[PhpStormStubsElementAvailable(from: '8.0')] mixed &$var, mixed &...$vars ): string|false {} /** * Encode character to HTML numeric string reference * @link https://php.net/manual/en/function.mb-encode-numericentity.php * @param string $string

    * The string being encoded. *

    * @param int[] $map

    * convmap is array specifies code area to * convert. *

    * @param null|string $encoding * @param bool $hex [optional] * @return string The converted string. */ #[Pure] function mb_encode_numericentity(string $string, array $map, ?string $encoding = null, bool $hex = false): string {} /** * Decode HTML numeric string reference to character * @link https://php.net/manual/en/function.mb-decode-numericentity.php * @param string $string

    * The string being decoded. *

    * @param int[] $map

    * convmap is an array that specifies * the code area to convert. *

    * @param null|string $encoding * @param bool $is_hex [optional]

    * this parameter is not used. *

    * @return string|false|null The converted string. */ #[Pure] #[LanguageLevelTypeAware(['8.0' => 'string'], default: 'string|false|null')] function mb_decode_numericentity(string $string, array $map, ?string $encoding = null, #[PhpStormStubsElementAvailable(from: '7.2', to: '7.4')] $is_hex = false) {} /** * Send encoded mail * @link https://php.net/manual/en/function.mb-send-mail.php * @param string $to

    * The mail addresses being sent to. Multiple * recipients may be specified by putting a comma between each * address in to. * This parameter is not automatically encoded. *

    * @param string $subject

    * The subject of the mail. *

    * @param string $message

    * The message of the mail. *

    * @param string|array $additional_headers

    * String or array to be inserted at the end of the email header.
    * Since 7.2.0 accepts an array. Its keys are the header names and its values are the respective header values.
    * This is typically used to add extra * headers. Multiple extra headers are separated with a * newline ("\n"). *

    * @param string|null $additional_params [optional]

    * additional_parameter is a MTA command line * parameter. It is useful when setting the correct Return-Path * header when using sendmail. *

    * @return bool true on success or false on failure. */ function mb_send_mail(string $to, string $subject, string $message, array|string $additional_headers = [], ?string $additional_params): bool {} /** * Get internal settings of mbstring * @link https://php.net/manual/en/function.mb-get-info.php * @param string $type [optional]

    * If type isn't specified or is specified to * "all", an array having the elements "internal_encoding", * "http_output", "http_input", "func_overload", "mail_charset", * "mail_header_encoding", "mail_body_encoding" will be returned. *

    *

    * If type is specified as "http_output", * "http_input", "internal_encoding", "func_overload", * the specified setting parameter will be returned. *

    * @return array|string|int|false An array of type information if type * is not specified, otherwise a specific type. */ #[Pure] #[ArrayShape([ 'internal_encoding' => 'string', 'http_input' => 'string', 'http_output' => 'string', 'http_output_conv_mimetypes' => 'string', 'mail_charset' => 'string', 'mail_header_encoding' => 'string', 'mail_body_encoding' => 'string', 'illegal_chars' => 'string', 'encoding_translation' => 'string', 'language' => 'string', 'detect_order' => 'string', 'substitute_character' => 'string', 'strict_detection' => 'string', ])] #[LanguageLevelTypeAware(['8.2' => 'array|string|int|false|null'], default: 'array|string|int|false')] function mb_get_info(string $type = 'all') {} /** * Check if the string is valid for the specified encoding * @link https://php.net/manual/en/function.mb-check-encoding.php * @param string|string[]|null $value [optional]

    * The byte stream to check. If it is omitted, this function checks * all the input from the beginning of the request. *

    * @param string|null $encoding [optional]

    * The expected encoding. *

    * @return bool true on success or false on failure. * @since 5.1.3 */ #[Pure] function mb_check_encoding(array|string|null $value = null, ?string $encoding): bool {} /** * Returns current encoding for multibyte regex as string * @link https://php.net/manual/en/function.mb-regex-encoding.php * @param string|null $encoding [optional] * @return bool|string If encoding is set, then Returns TRUE on success * or FALSE on failure. In this case, the internal character encoding * is NOT changed. If encoding is omitted, then the current character * encoding name for a multibyte regex is returned. */ function mb_regex_encoding(?string $encoding): string|bool {} /** * Set/Get the default options for mbregex functions * @link https://php.net/manual/en/function.mb-regex-set-options.php * @param string|null $options [optional]

    * The options to set. *

    * @return string The previous options. If options is omitted, * it returns the string that describes the current options. */ function mb_regex_set_options(?string $options): string {} /** * Regular expression match with multibyte support * @link https://php.net/manual/en/function.mb-ereg.php * @param string $pattern

    * The search pattern. *

    * @param string $string

    * The search string. *

    * @param string[] &$matches [optional]

    * Contains a substring of the matched string. *

    * @return bool */ function mb_ereg(string $pattern, string $string, &$matches): bool {} /** * Regular expression match ignoring case with multibyte support * @link https://php.net/manual/en/function.mb-eregi.php * @param string $pattern

    * The regular expression pattern. *

    * @param string $string

    * The string being searched. *

    * @param string[] &$matches [optional]

    * Contains a substring of the matched string. *

    * @return bool|int */ #[LanguageLevelTypeAware(["8.0" => "bool"], default: "false|int")] function mb_eregi(string $pattern, string $string, &$matches): bool {} /** * Replace regular expression with multibyte support * @link https://php.net/manual/en/function.mb-ereg-replace.php * @param string $pattern

    * The regular expression pattern. *

    *

    * Multibyte characters may be used in pattern. *

    * @param string $replacement

    * The replacement text. *

    * @param string $string

    * The string being checked. *

    * @param string|null $options Matching condition can be set by option * parameter. If i is specified for this * parameter, the case will be ignored. If x is * specified, white space will be ignored. If m * is specified, match will be executed in multiline mode and line * break will be included in '.'. If p is * specified, match will be executed in POSIX mode, line break * will be considered as normal character. If e * is specified, replacement string will be * evaluated as PHP expression. *

    PHP 7.1: The e modifier has been deprecated.

    * @return string|false|null The resultant string on success, or false on error. */ #[Pure] function mb_ereg_replace(string $pattern, string $replacement, string $string, ?string $options = null): string|false|null {} /** * Perform a regular expresssion seach and replace with multibyte support using a callback * @link https://secure.php.net/manual/en/function.mb-ereg-replace-callback.php * @param string $pattern

    * The regular expression pattern. *

    *

    * Multibyte characters may be used in pattern. *

    * @param callable $callback

    * A callback that will be called and passed an array of matched elements * in the subject string. The callback should * return the replacement string. *

    *

    * You'll often need the callback function * for a mb_ereg_replace_callback() in just one place. * In this case you can use an anonymous function to * declare the callback within the call to * mb_ereg_replace_callback(). By doing it this way * you have all information for the call in one place and do not * clutter the function namespace with a callback function's name * not used anywhere else. *

    * @param string $string

    * The string being checked. *

    * @param string $options

    * Matching condition can be set by option * parameter. If i is specified for this * parameter, the case will be ignored. If x is * specified, white space will be ignored. If m * is specified, match will be executed in multiline mode and line * break will be included in '.'. If p is * specified, match will be executed in POSIX mode, line break * will be considered as normal character. Note that e * cannot be used for mb_ereg_replace_callback(). *

    * @return string|false|null

    * The resultant string on success, or FALSE on error. *

    * @since 5.4.1 */ function mb_ereg_replace_callback(string $pattern, callable $callback, string $string, ?string $options = null): string|false|null {} /** * Replace regular expression with multibyte support ignoring case * @link https://php.net/manual/en/function.mb-eregi-replace.php * @param string $pattern

    * The regular expression pattern. Multibyte characters may be used. The case will be ignored. *

    * @param string $replacement

    * The replacement text. *

    * @param string $string

    * The searched string. *

    * @param string|null $options option has the same meaning as in * mb_ereg_replace. *

    PHP 7.1: The e modifier has been deprecated.

    * @return string|false|null The resultant string or false on error. */ #[Pure] function mb_eregi_replace( string $pattern, string $replacement, string $string, #[PhpStormStubsElementAvailable(from: '7.0')] ?string $options = null ): string|false|null {} /** * Split multibyte string using regular expression * @link https://php.net/manual/en/function.mb-split.php * @param string $pattern

    * The regular expression pattern. *

    * @param string $string

    * The string being split. *

    * @param int $limit [optional] If optional parameter limit is specified, * it will be split in limit elements as * maximum. * @return string[]|false The result as an array. */ #[Pure] function mb_split(string $pattern, string $string, int $limit = -1): array|false {} /** * Regular expression match for multibyte string * @link https://php.net/manual/en/function.mb-ereg-match.php * @param string $pattern

    * The regular expression pattern. *

    * @param string $string

    * The string being evaluated. *

    * @param string|null $options [optional]

    *

    * @return bool */ #[Pure] function mb_ereg_match(string $pattern, string $string, ?string $options): bool {} /** * Multibyte regular expression match for predefined multibyte string * @link https://php.net/manual/en/function.mb-ereg-search.php * @param string|null $pattern [optional]

    * The search pattern. *

    * @param string|null $options [optional]

    * The search option. *

    * @return bool */ #[Pure] function mb_ereg_search(?string $pattern, ?string $options): bool {} /** * Returns position and length of a matched part of the multibyte regular expression for a predefined multibyte string * @link https://php.net/manual/en/function.mb-ereg-search-pos.php * @param string|null $pattern [optional]

    * The search pattern. *

    * @param string|null $options [optional]

    * The search option. *

    * @return int[]|false An array containing two elements. The first * element is the offset, in bytes, where the match begins relative * to the start of the search string, and the second element is the * length in bytes of the match. If an error occurs, FALSE is returned. */ #[Pure] function mb_ereg_search_pos(?string $pattern, ?string $options): array|false {} /** * Returns the matched part of a multibyte regular expression * @link https://php.net/manual/en/function.mb-ereg-search-regs.php * @param string|null $pattern [optional]

    * The search pattern. *

    * @param string|null $options [optional]

    * The search option. *

    * @return string[]|false mb_ereg_search_regs() executes the multibyte * regular expression match, and if there are some matched part, it * returns an array including substring of matched part as first element, * the first grouped part with brackets as second element, the second grouped * part as third element, and so on. It returns FALSE on error. */ #[Pure] function mb_ereg_search_regs(?string $pattern, ?string $options): array|false {} /** * Setup string and regular expression for a multibyte regular expression match * @link https://php.net/manual/en/function.mb-ereg-search-init.php * @param string $string

    * The search string. *

    * @param string|null $pattern [optional]

    * The search pattern. *

    * @param string|null $options [optional]

    * The search option. *

    * @return bool */ function mb_ereg_search_init(string $string, ?string $pattern, ?string $options): bool {} /** * Retrieve the result from the last multibyte regular expression match * @link https://php.net/manual/en/function.mb-ereg-search-getregs.php * @return string[]|false An array including the sub-string of matched * part by last mb_ereg_search(), mb_ereg_search_pos(), mb_ereg_search_regs(). * If there are some matches, the first element will have the matched * sub-string, the second element will have the first part grouped with * brackets, the third element will have the second part grouped with * brackets, and so on. It returns FALSE on error; */ #[Pure] function mb_ereg_search_getregs(): array|false {} /** * Returns start point for next regular expression match * @link https://php.net/manual/en/function.mb-ereg-search-getpos.php * @return int */ #[Pure] function mb_ereg_search_getpos(): int {} /** * Set start point of next regular expression match * @link https://php.net/manual/en/function.mb-ereg-search-setpos.php * @param int $offset

    * The position to set. *

    * @return bool */ #[Pure] function mb_ereg_search_setpos(int $offset): bool {} /** * @param $encoding [optional] * @see mb_regex_encoding * @removed 8.0 */ #[Deprecated(replacement: "mb_regex_encoding(%parametersList%)", since: "7.3")] function mbregex_encoding($encoding) {} /** * @param string $pattern * @param string $string * @param array &$registers [optional] * @see mb_ereg * @removed 8.0 */ #[Deprecated(replacement: 'mb_ereg(%parametersList%)', since: '7.3')] function mbereg(string $pattern, string $string, array &$registers) {} /** * @param string $pattern * @param string $string * @param array &$registers [optional] * @see mb_eregi * @removed 8.0 */ #[Deprecated(replacement: "mb_eregi(%parametersList%)", since: "7.3")] function mberegi(string $pattern, string $string, array &$registers) {} /** * @param $pattern * @param $replacement * @param $string * @param $option [optional] * @see mb_ereg_replace * @removed 8.0 */ #[Deprecated(replacement: 'mb_ereg_replace(%parametersList%)', since: '7.3')] function mbereg_replace($pattern, $replacement, $string, $option) {} /** * @param $pattern * @param $replacement * @param $string * @param string $option * @return string * @see mb_eregi_replace * @removed 8.0 */ #[Deprecated(replacement: "mb_eregi_replace(%parametersList%)", since: "7.3")] function mberegi_replace( $pattern, $replacement, $string, #[PhpStormStubsElementAvailable(from: '7.0')] string $option = "msri" ): string {} /** * @param $pattern * @param $string * @param $limit [optional] * @see mb_split * @removed 8.0 */ #[Deprecated(replacement: 'mb_split(%parametersList%)', since: '7.3')] function mbsplit($pattern, $string, $limit) {} /** * @param $pattern * @param $string * @param $option [optional] * @see mb_ereg_match * @removed 8.0 */ #[Deprecated(replacement: "mb_ereg_match(%parametersList%)", since: "7.3")] function mbereg_match($pattern, $string, $option) {} /** * @param $pattern [optional] * @param $option [optional] * @see mb_ereg_search * @removed 8.0 */ #[Deprecated("use mb_ereg_search instead", replacement: "mb_ereg_search(%parametersList%)", since: "7.3")] function mbereg_search($pattern, $option) {} /** * @param $pattern [optional] * @param $option [optional] * @see mb_ereg_search_pos * @removed 8.0 */ #[Deprecated(replacement: "mb_ereg_search_pos(%parametersList%)", since: "7.3")] function mbereg_search_pos($pattern, $option) {} /** * @param $pattern [optional] * @param $option [optional] * @see mb_ereg_search_regs * @removed 8.0 */ #[Deprecated(replacement: 'mb_ereg_search_regs(%parametersList%)', since: '7.3')] function mbereg_search_regs($pattern, $option) {} /** * @param $string * @param $pattern [optional] * @param $option [optional] * @see mb_ereg_search_init * @removed 8.0 */ #[Deprecated(replacement: "mb_ereg_search_init(%parametersList%)", since: "7.3")] function mbereg_search_init($string, $pattern, $option) {} /** * @see mb_ereg_search_getregs * @removed 8.0 */ #[Deprecated(replacement: 'mb_ereg_search_getregs(%parametersList%)', since: '7.3')] function mbereg_search_getregs() {} /** * @see mb_ereg_search_getpos * @removed 8.0 */ #[Deprecated(replacement: "mb_ereg_search_getpos()", since: "7.3")] function mbereg_search_getpos() {} /** * Get a specific character. * @link https://www.php.net/manual/en/function.mb-chr.php * @param int $codepoint * @param string|null $encoding [optional] * @return string|false specific character or FALSE on failure. * @since 7.2 */ #[Pure] function mb_chr(int $codepoint, ?string $encoding): string|false {} /** * Get code point of character * @link https://www.php.net/manual/en/function.mb-ord.php * @param string $string * @param string|null $encoding [optional] * @return int|false code point of character or FALSE on failure. * @since 7.2 */ #[Pure] function mb_ord(string $string, ?string $encoding): int|false {} /** * Scrub broken multibyte strings. * @link https://www.php.net/manual/en/function.mb-scrub.php * @param string $string * @param string|null $encoding [optional] * @return string|false * @since 7.2 */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] function mb_scrub(string $string, ?string $encoding): false|string {} /** * @param $position * @see mb_ereg_search_setpos */ #[Deprecated(replacement: "mb_ereg_search_setpos(%parametersList%)", since: "7.3")] #[Pure] function mbereg_search_setpos($position) {} /** * Function performs string splitting to an array of defined size chunks. * @param string $string

    * The string to split into characters or chunks. *

    * @param int $length [optional]

    * If specified, each element of the returned array will be composed of multiple characters instead of a single character. *

    * @param string|null $encoding [optional]

    * Character encoding name to use. * If it is omitted, internal character encoding is used. *

    * @return string[]|false * @since 7.4 */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] function mb_str_split(string $string, int $length = 1, ?string $encoding) {} /** * @since 8.3 */ function mb_str_pad(string $string, int $length, string $pad_string = " ", int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string {} /** * @since 8.4 */ function mb_ucfirst(string $string, ?string $encoding = null): string {} /** * @since 8.4 */ function mb_lcfirst(string $string, ?string $encoding = null): string {} /** * @since 8.4 */ function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string {} /** * @since 8.4 */ function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string {} /** * @since 8.4 */ function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string {} /** * @removed 8.0 */ define('MB_OVERLOAD_MAIL', 1); /** * @removed 8.0 */ define('MB_OVERLOAD_STRING', 2); /** * @removed 8.0 */ define('MB_OVERLOAD_REGEX', 4); define('MB_CASE_UPPER', 0); define('MB_CASE_LOWER', 1); define('MB_CASE_TITLE', 2); /** * @since 7.3 */ define('MB_CASE_FOLD', 3); /** * @since 7.3 */ define('MB_CASE_UPPER_SIMPLE', 4); /** * @since 7.3 */ define('MB_CASE_LOWER_SIMPLE', 5); /** * @since 7.3 */ define('MB_CASE_TITLE_SIMPLE', 6); /** * @since 7.3 */ define('MB_CASE_FOLD_SIMPLE', 7); /** * @since 7.4 */ define('MB_ONIGURUMA_VERSION', '6.9.9'); // End of mbstring v. * the severity of the error (one of the following constants: * LIBXML_ERR_WARNING, * LIBXML_ERR_ERROR or * LIBXML_ERR_FATAL) *

    * @var int */ public int $level; /** *

    * The error's code. *

    * @var int */ public int $code; /** *

    * The column where the error occurred. *

    *

    Note: *

    * This property isn't entirely implemented in libxml and therefore * 0 is often returned. *

    * @var int */ public int $column; /** *

    * The error message, if any. *

    * @var string */ public string $message; /** *

    The filename, or empty if the XML was loaded from a string.

    * @var string */ public string $file; /** *

    * The line where the error occurred. *

    * @var int */ public int $line; } /** * Set the streams context for the next libxml document load or write * @link https://php.net/manual/en/function.libxml-set-streams-context.php * @param resource $context

    * The stream context resource (created with * stream_context_create) *

    * @return void No value is returned. */ function libxml_set_streams_context($context): void {} /** * Disable libxml errors and allow user to fetch error information as needed * @link https://php.net/manual/en/function.libxml-use-internal-errors.php * @param bool|null $use_errors

    * Enable (TRUE) user error handling or disable (FALSE) user error handling. Disabling will also clear any existing libxml errors. *

    * @return bool This function returns the previous value of * use_errors. */ function libxml_use_internal_errors( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] bool $use_errors = false, #[PhpStormStubsElementAvailable(from: '8.0')] ?bool $use_errors = null ): bool {} /** * Retrieve last error from libxml * @link https://php.net/manual/en/function.libxml-get-last-error.php * @return LibXMLError|false a LibXMLError object if there is any error in the * buffer, FALSE otherwise. */ #[Pure(true)] function libxml_get_last_error(): LibXMLError|false {} /** * Clear libxml error buffer * @link https://php.net/manual/en/function.libxml-clear-errors.php * @return void No value is returned. */ function libxml_clear_errors(): void {} /** * Retrieve array of errors * @link https://php.net/manual/en/function.libxml-get-errors.php * @return LibXMLError[] an array with LibXMLError objects if there are any * errors in the buffer, or an empty array otherwise. */ #[Pure(true)] function libxml_get_errors(): array {} /** * Disable the ability to load external entities * @link https://php.net/manual/en/function.libxml-disable-entity-loader.php * @param bool $disable [optional]

    * Disable (TRUE) or enable (FALSE) libxml extensions (such as * , * and ) to load external entities. *

    * @return bool the previous value. * @since 5.2.11 */ #[Deprecated(since: "8.0")] function libxml_disable_entity_loader(bool $disable = true): bool {} /** * Changes the default external entity loader * @link https://php.net/manual/en/function.libxml-set-external-entity-loader.php * @param callable|null $resolver_function

    * A callable that takes three arguments. Two strings, a public id * and system id, and a context (an array with four keys) as the third argument. * This callback should return a resource, a string from which a resource can be * opened, or NULL. *

    * @return bool * @since 5.4 */ function libxml_set_external_entity_loader(?callable $resolver_function): bool {} /** * Returns the currently installed external entity loader, i.e. the value which was passed to * libxml_set_external_entity_loader() or null if no loader was installed and the default entity loader will be used. * This allows libraries to save and restore the loader, controlling entity expansion without interfering with the rest * of the application. * * @return callable|null * @since 8.2 */ function libxml_get_external_entity_loader(): ?callable {} /** * libxml version like 20605 or 20617 * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_VERSION', 20901); /** * libxml version like 2.6.5 or 2.6.17 * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_DOTTED_VERSION', "2.9.1"); define('LIBXML_LOADED_VERSION', 20901); /** * Substitute entities * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_NOENT', 2); /** * Load the external subset * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_DTDLOAD', 4); /** * Default DTD attributes * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_DTDATTR', 8); /** * Validate with the DTD * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_DTDVALID', 16); /** * Suppress error reports * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_NOERROR', 32); /** * Suppress warning reports * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_NOWARNING', 64); /** * Remove blank nodes * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_NOBLANKS', 256); /** * Implement XInclude substitution * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_XINCLUDE', 1024); /** * Remove redundant namespaces declarations * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_NSCLEAN', 8192); /** * Merge CDATA as text nodes * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_NOCDATA', 16384); /** * Disable network access when loading documents * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_NONET', 2048); /** * Sets XML_PARSE_PEDANTIC flag, which enables pedentic error reporting. * @link https://php.net/manual/en/libxml.constants.php * @since 5.4 */ define('LIBXML_PEDANTIC', 128); /** * Activate small nodes allocation optimization. This may speed up your * application without needing to change the code. *

    * Only available in Libxml >= 2.6.21 *

    * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_COMPACT', 65536); /** * Allows line numbers greater than 65535 to be reported correctly. *

    * Only available in Libxml >= 2.9.0 *

    * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_BIGLINES', 65535); /** * Drop the XML declaration when saving a document *

    * Only available in Libxml >= 2.6.21 *

    * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_NOXMLDECL', 2); /** * Sets XML_PARSE_HUGE flag, which relaxes any hardcoded limit from the parser. This affects * limits like maximum depth of a document or the entity recursion, as well as limits of the * size of text nodes. *

    * Only available in Libxml >= 2.7.0 (as of PHP >= 5.3.2 and PHP >= 5.2.12) *

    * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_PARSEHUGE', 524288); /** * Expand empty tags (e.g. <br/> to * <br></br>) *

    * This option is currently just available in the * and * functions. *

    * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_NOEMPTYTAG', 4); /** * Create default/fixed value nodes during XSD schema validation *

    * Only available in Libxml >= 2.6.14 (as of PHP >= 5.5.2) *

    * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_SCHEMA_CREATE', 1); /** * Sets HTML_PARSE_NOIMPLIED flag, which turns off the * automatic adding of implied html/body... elements. *

    * Only available in Libxml >= 2.7.7 (as of PHP >= 5.4.0) *

    * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_HTML_NOIMPLIED', 8192); /** * Sets HTML_PARSE_NODEFDTD flag, which prevents a default doctype * being added when one is not found. *

    * Only available in Libxml >= 2.7.8 (as of PHP >= 5.4.0) *

    * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_HTML_NODEFDTD', 4); /** * No errors * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_ERR_NONE', 0); /** * A simple warning * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_ERR_WARNING', 1); /** * A recoverable error * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_ERR_ERROR', 2); /** * A fatal error * @link https://php.net/manual/en/libxml.constants.php */ define('LIBXML_ERR_FATAL', 3); /** * @since 8.4 */ define('LIBXML_RECOVER', 1); // End of libxml v. * Returns the difference between two DateTime objects * @link https://secure.php.net/manual/en/datetime.diff.php * @param DateTimeInterface $targetObject

    The date to compare to.

    * @param bool $absolute

    Should the interval be forced to be positive?

    * @return DateInterval * The https://secure.php.net/manual/en/class.dateinterval.php DateInterval} object representing the * difference between the two dates. */ #[TentativeType] public function diff( DateTimeInterface $targetObject, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $absolute = false ): DateInterval; /** * (PHP 5 >=5.5.0)
    * Returns date formatted according to given format * @link https://secure.php.net/manual/en/datetime.format.php * @param string $format

    * Format accepted by {@link https://secure.php.net/manual/en/function.date.php date()}. *

    * @return string * Returns the formatted date string on success or FALSE on failure. * Since PHP8, it always returns STRING. */ #[TentativeType] public function format(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $format): string; /** * (PHP 5 >=5.5.0)
    * Returns the timezone offset * @return int|false * Returns the timezone offset in seconds from UTC on success * or FALSE on failure. Since PHP8, it always returns INT. */ #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] #[TentativeType] public function getOffset(): int; /** * (PHP 5 >=5.5.0)
    * Gets the Unix timestamp * @return int * Returns the Unix timestamp representing the date. */ #[TentativeType] #[LanguageLevelTypeAware(['8.1' => 'int'], default: 'int|false')] public function getTimestamp(); /** * (PHP 5 >=5.5.0)
    * Return time zone relative to given DateTime * @link https://secure.php.net/manual/en/datetime.gettimezone.php * @return DateTimeZone|false * Returns a {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone} object on success * or FALSE on failure. */ #[TentativeType] public function getTimezone(): DateTimeZone|false; /** * (PHP 5 >=5.5.0)
    * The __wakeup handler * @link https://secure.php.net/manual/en/datetime.wakeup.php * @return void Initializes a DateTime object. */ #[TentativeType] public function __wakeup(): void; #[PhpStormStubsElementAvailable(from: '8.2')] public function __serialize(): array; #[PhpStormStubsElementAvailable(from: '8.2')] public function __unserialize(array $data): void; /** * @since 8.4 */ public function createFromTimestamp(); /** * @since 8.4 */ public function getMicrosecond(): int; /** * @since 8.4 */ public function setMicrosecond(); } /** * @since 5.5 */ class DateTimeImmutable implements DateTimeInterface { /* Methods */ /** * (PHP 5 >=5.5.0)
    * @link https://secure.php.net/manual/en/datetimeimmutable.construct.php * @param string $datetime [optional] *

    A date/time string. Valid formats are explained in {@link https://secure.php.net/manual/en/datetime.formats.php Date and Time Formats}.

    *

    Enter NULL here to obtain the current time when using the $timezone parameter.

    * @param null|DateTimeZone $timezone [optional]

    * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone} object representing the timezone of $datetime. *

    *

    If $timezone is omitted, the current timezone will be used.

    *

    Note:

    * The $timezone parameter and the current timezone are ignored when the $datetime parameter either * is a UNIX timestamp (e.g. @946684800) or specifies a timezone (e.g. 2010-01-28T15:00:00+02:00). *

    * @throws DateMalformedStringException Emits Exception in case of an error. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $datetime = "now", #[LanguageLevelTypeAware(['8.0' => 'DateTimeZone|null'], default: 'DateTimeZone')] $timezone = null ) {} /** * (PHP 5 >=5.5.0)
    * Adds an amount of days, months, years, hours, minutes and seconds * @param DateInterval $interval * @return static * @link https://secure.php.net/manual/en/datetimeimmutable.add.php */ #[TentativeType] public function add(DateInterval $interval): DateTimeImmutable {} /** * (PHP 5 >=5.5.0)
    * Returns new DateTimeImmutable object formatted according to the specified format * @link https://secure.php.net/manual/en/datetimeimmutable.createfromformat.php * @param string $format * @param string $datetime * @param null|DateTimeZone $timezone [optional] * @return DateTimeImmutable|false */ #[TentativeType] public static function createFromFormat( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $format, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $datetime, #[LanguageLevelTypeAware(['8.0' => 'DateTimeZone|null'], default: 'DateTimeZone')] $timezone = null ): DateTimeImmutable|false {} /** * (PHP 5 >=5.6.0)
    * Returns new DateTimeImmutable object encapsulating the given DateTime object * @link https://secure.php.net/manual/en/datetimeimmutable.createfrommutable.php * @param DateTime $object The mutable DateTime object that you want to convert to an immutable version. This object is not modified, but instead a new DateTimeImmutable object is created containing the same date time and timezone information. * @return DateTimeImmutable returns a new DateTimeImmutable instance. */ #[TentativeType] #[LanguageLevelTypeAware(['8.2' => 'static'], default: 'DateTimeImmutable')] public static function createFromMutable(DateTime $object) {} /** * (PHP 5 >=5.5.0)
    * Returns the warnings and errors * @link https://secure.php.net/manual/en/datetimeimmutable.getlasterrors.php * @return array|false Returns array containing info about warnings and errors. */ #[ArrayShape(["warning_count" => "int", "warnings" => "string[]", "error_count" => "int", "errors" => "string[]"])] #[TentativeType] public static function getLastErrors(): array|false {} /** * (PHP 5 >=5.5.0)
    * Alters the timestamp * @link https://secure.php.net/manual/en/datetimeimmutable.modify.php * @param string $modifier

    A date/time string. Valid formats are explained in * {@link https://secure.php.net/manual/en/datetime.formats.php Date and Time Formats}.

    * @return static|false Returns the newly created object or false on failure. * @throws DateMalformedStringException * Returns the {@link https://secure.php.net/manual/en/class.datetimeimmutable.php DateTimeImmutable} object for method chaining or FALSE on failure. */ #[Pure] #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'DateTimeImmutable'], default: 'DateTimeImmutable|false')] public function modify(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $modifier) {} /** * (PHP 5 >=5.5.0)
    * The __set_state handler * @link https://secure.php.net/manual/en/datetimeimmutable.set-state.php * @param array $array

    Initialization array.

    * @return DateTimeImmutable * Returns a new instance of a {@link https://secure.php.net/manual/en/class.datetimeimmutable.php DateTimeImmutable} object. */ public static function __set_state(array $array) {} /** * (PHP 5 >=5.5.0)
    * Sets the date * @link https://secure.php.net/manual/en/datetimeimmutable.setdate.php * @param int $year

    Year of the date.

    * @param int $month

    Month of the date.

    * @param int $day

    Day of the date.

    * @return static|false * Returns the {@link https://secure.php.net/manual/en/class.datetimeimmutable.php DateTimeImmutable} object for method chaining or FALSE on failure. */ #[TentativeType] public function setDate( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $year, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $month, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $day ): DateTimeImmutable {} /** * (PHP 5 >=5.5.0)
    * Sets the ISO date * @link https://php.net/manual/en/class.datetimeimmutable.php * @param int $year

    Year of the date.

    * @param int $week

    Week of the date.

    * @param int $dayOfWeek [optional]

    Offset from the first day of the week.

    * @return static|false * Returns the {@link https://secure.php.net/manual/en/class.datetimeimmutable.php DateTimeImmutable} object for method chaining or FALSE on failure. */ #[TentativeType] public function setISODate( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $year, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $week, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $dayOfWeek = 1 ): DateTimeImmutable {} /** * (PHP 5 >=5.5.0)
    * Sets the time * @link https://secure.php.net/manual/en/datetimeimmutable.settime.php * @param int $hour

    Hour of the time.

    * @param int $minute

    Minute of the time.

    * @param int $second [optional]

    Second of the time.

    * @param int $microsecond [optional]

    Microseconds of the time. Added since 7.1

    * @return static|false * Returns the {@link https://secure.php.net/manual/en/class.datetimeimmutable.php DateTimeImmutable} object for method chaining or FALSE on failure. */ #[TentativeType] public function setTime( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $hour, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $minute, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $second = 0, #[PhpStormStubsElementAvailable(from: '7.1')] #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $microsecond = 0 ): DateTimeImmutable {} /** * (PHP 5 >=5.5.0)
    * Sets the date and time based on an Unix timestamp * @link https://secure.php.net/manual/en/datetimeimmutable.settimestamp.php * @param int $timestamp

    Unix timestamp representing the date.

    * @return static * Returns the {@link https://secure.php.net/manual/en/class.datetimeimmutable.php DateTimeImmutable} object for method chaining or FALSE on failure. */ #[TentativeType] public function setTimestamp(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $timestamp): DateTimeImmutable {} /** * (PHP 5 >=5.5.0)
    * Sets the time zone * @link https://secure.php.net/manual/en/datetimeimmutable.settimezone.php * @param DateTimeZone $timezone

    * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone} object representing the * desired time zone. *

    * @return static * Returns the {@link https://secure.php.net/manual/en/class.datetimeimmutable.php DateTimeImmutable} object for method chaining or FALSE on failure. */ #[TentativeType] public function setTimezone(DateTimeZone $timezone): DateTimeImmutable {} /** * (PHP 5 >=5.5.0)
    * Subtracts an amount of days, months, years, hours, minutes and seconds * @link https://secure.php.net/manual/en/datetimeimmutable.sub.php * @param DateInterval $interval

    * A {@link https://secure.php.net/manual/en/class.dateinterval.php DateInterval} object *

    * @return static * @throws DateInvalidOperationException * Returns the {@link https://secure.php.net/manual/en/class.datetimeimmutable.php DateTimeImmutable} object for method chaining or FALSE on failure. */ #[TentativeType] public function sub(DateInterval $interval): DateTimeImmutable {} /** * (PHP 5 >=5.5.0)
    * Returns the difference between two DateTime objects * @link https://secure.php.net/manual/en/datetime.diff.php * @param DateTimeInterface $targetObject

    The date to compare to.

    * @param bool $absolute [optional]

    Should the interval be forced to be positive?

    * @return DateInterval|false * The {@link https://secure.php.net/manual/en/class.dateinterval.php DateInterval} object representing the * difference between the two dates or FALSE on failure. */ #[TentativeType] public function diff( #[LanguageLevelTypeAware(['8.0' => 'DateTimeInterface'], default: '')] $targetObject, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $absolute = false ): DateInterval {} /** * (PHP 5 >=5.5.0)
    * Returns date formatted according to given format * @link https://secure.php.net/manual/en/datetime.format.php * @param string $format

    * Format accepted by {@link https://secure.php.net/manual/en/function.date.php date()}. *

    * @return string * Returns the formatted date string on success or FALSE on failure. */ #[TentativeType] public function format(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $format): string {} /** * (PHP 5 >=5.5.0)
    * Returns the timezone offset * @return int * Returns the timezone offset in seconds from UTC on success * or FALSE on failure. */ #[TentativeType] public function getOffset(): int {} /** * (PHP 5 >=5.5.0)
    * Gets the Unix timestamp * @return int * Returns the Unix timestamp representing the date. */ #[TentativeType] public function getTimestamp(): int {} /** * (PHP 5 >=5.5.0)
    * Return time zone relative to given DateTime * @link https://secure.php.net/manual/en/datetime.gettimezone.php * @return DateTimeZone|false * Returns a {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone} object on success * or FALSE on failure. */ #[TentativeType] public function getTimezone(): DateTimeZone|false {} /** * (PHP 5 >=5.5.0)
    * The __wakeup handler * @link https://secure.php.net/manual/en/datetime.wakeup.php * @return void Initializes a DateTime object. */ #[TentativeType] public function __wakeup(): void {} /** * @param DateTimeInterface $object * @return DateTimeImmutable * @since 8.0 */ public static function createFromInterface(DateTimeInterface $object): DateTimeImmutable {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __serialize(): array {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __unserialize(array $data): void {} /** * @since 8.4 */ #[TentativeType] public static function createFromTimestamp(int|float $timestamp): static {} /** * @since 8.4 */ public function getMicrosecond(): int {} /** * @since 8.4 */ public function setMicrosecond(int $microsecond): static {} } /** * Representation of date and time. * @link https://php.net/manual/en/class.datetime.php */ class DateTime implements DateTimeInterface { /** * @removed 7.2 */ public const ATOM = 'Y-m-d\TH:i:sP'; /** * @removed 7.2 */ public const COOKIE = 'l, d-M-Y H:i:s T'; /** * @removed 7.2 */ public const ISO8601 = 'Y-m-d\TH:i:sO'; /** * @removed 7.2 */ public const RFC822 = 'D, d M y H:i:s O'; /** * @removed 7.2 */ public const RFC850 = 'l, d-M-y H:i:s T'; /** * @removed 7.2 */ public const RFC1036 = 'D, d M y H:i:s O'; /** * @removed 7.2 */ public const RFC1123 = 'D, d M Y H:i:s O'; /** * @removed 7.2 */ public const RFC2822 = 'D, d M Y H:i:s O'; /** * @removed 7.2 */ public const RFC3339 = 'Y-m-d\TH:i:sP'; /** * @removed 7.2 */ public const RFC3339_EXTENDED = 'Y-m-d\TH:i:s.vP'; /** * @removed 7.2 */ public const RFC7231 = 'D, d M Y H:i:s \G\M\T'; /** * @removed 7.2 */ public const RSS = 'D, d M Y H:i:s O'; /** * @removed 7.2 */ public const W3C = 'Y-m-d\TH:i:sP'; /** * (PHP 5 >=5.2.0)
    * @link https://php.net/manual/en/datetime.construct.php * @param string $datetime [optional] *

    A date/time string. Valid formats are explained in {@link https://php.net/manual/en/datetime.formats.php Date and Time Formats}.

    *

    * Enter now here to obtain the current time when using * the $timezone parameter. *

    * @param null|DateTimeZone $timezone [optional]

    * A {@link https://php.net/manual/en/class.datetimezone.php DateTimeZone} object representing the * timezone of $datetime. *

    *

    * If $timezone is omitted, * the current timezone will be used. *

    *

    Note: *

    * The $timezone parameter * and the current timezone are ignored when the * $time parameter either * is a UNIX timestamp (e.g. @946684800) * or specifies a timezone * (e.g. 2010-01-28T15:00:00+02:00). *

    * @throws DateMalformedStringException Emits Exception in case of an error. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $datetime = 'now', #[LanguageLevelTypeAware(['8.0' => 'DateTimeZone|null'], default: 'DateTimeZone')] $timezone = null ) {} /** * @return void * @link https://php.net/manual/en/datetime.wakeup.php */ #[TentativeType] public function __wakeup(): void {} /** * Returns date formatted according to given format. * @param string $format * @return string * @link https://php.net/manual/en/datetime.format.php */ #[TentativeType] public function format(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $format): string {} /** * Alter the timestamp of a DateTime object by incrementing or decrementing * in a format accepted by strtotime(). * @param string $modifier A date/time string. Valid formats are explained in Date and Time Formats. * @return static|false Returns the DateTime object for method chaining or FALSE on failure. * @throws DateMalformedStringException * @link https://php.net/manual/en/datetime.modify.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'DateTime'], default: 'DateTime|false')] public function modify(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $modifier) {} /** * Adds an amount of days, months, years, hours, minutes and seconds to a DateTime object * @param DateInterval $interval * @return static * @link https://php.net/manual/en/datetime.add.php */ #[TentativeType] public function add(DateInterval $interval): DateTime {} /** * @param DateTimeImmutable $object * @return DateTime * @since 7.3 */ #[TentativeType] #[LanguageLevelTypeAware(['8.2' => 'static'], default: 'DateTime')] public static function createFromImmutable(DateTimeImmutable $object) {} /** * Subtracts an amount of days, months, years, hours, minutes and seconds from a DateTime object * @param DateInterval $interval * @return static * @link https://php.net/manual/en/datetime.sub.php */ #[TentativeType] public function sub(DateInterval $interval): DateTime {} /** * Get the TimeZone associated with the DateTime * @return DateTimeZone|false * @link https://php.net/manual/en/datetime.gettimezone.php */ #[TentativeType] public function getTimezone(): DateTimeZone|false {} /** * Set the TimeZone associated with the DateTime * @param DateTimeZone $timezone * @return static * @link https://php.net/manual/en/datetime.settimezone.php */ #[TentativeType] public function setTimezone(#[LanguageLevelTypeAware(['8.0' => 'DateTimeZone'], default: '')] $timezone): DateTime {} /** * Returns the timezone offset * @return int * @link https://php.net/manual/en/datetime.getoffset.php */ #[TentativeType] public function getOffset(): int {} /** * Sets the current time of the DateTime object to a different time. * @param int $hour * @param int $minute * @param int $second * @param int $microsecond Added since 7.1 * @return static * @link https://php.net/manual/en/datetime.settime.php */ #[TentativeType] public function setTime( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $hour, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $minute, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $second = 0, #[PhpStormStubsElementAvailable(from: '7.1')] #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $microsecond = 0 ): DateTime {} /** * Sets the current date of the DateTime object to a different date. * @param int $year * @param int $month * @param int $day * @return static * @link https://php.net/manual/en/datetime.setdate.php */ #[TentativeType] public function setDate( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $year, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $month, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $day ): DateTime {} /** * Set a date according to the ISO 8601 standard - using weeks and day offsets rather than specific dates. * @param int $year * @param int $week * @param int $dayOfWeek * @return static * @link https://php.net/manual/en/datetime.setisodate.php */ #[TentativeType] public function setISODate( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $year, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $week, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $dayOfWeek = 1 ): DateTime {} /** * Sets the date and time based on a Unix timestamp. * @param int $timestamp * @return static * @link https://php.net/manual/en/datetime.settimestamp.php */ #[TentativeType] public function setTimestamp(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $timestamp): DateTime {} /** * Gets the Unix timestamp. * @return int * @link https://php.net/manual/en/datetime.gettimestamp.php */ #[TentativeType] public function getTimestamp(): int {} /** * Returns the difference between two DateTime objects represented as a DateInterval. * @param DateTimeInterface $targetObject The date to compare to. * @param bool $absolute [optional] Whether to return absolute difference. * @return DateInterval|false The DateInterval object representing the difference between the two dates. * @link https://php.net/manual/en/datetime.diff.php */ #[TentativeType] public function diff( #[LanguageLevelTypeAware(['8.0' => 'DateTimeInterface'], default: '')] $targetObject, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $absolute = false ): DateInterval {} /** * Parse a string into a new DateTime object according to the specified format * @param string $format Format accepted by date(). * @param string $datetime String representing the time. * @param null|DateTimeZone $timezone A DateTimeZone object representing the desired time zone. * @return DateTime|false * @link https://php.net/manual/en/datetime.createfromformat.php */ #[TentativeType] public static function createFromFormat( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $format, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $datetime, #[LanguageLevelTypeAware(['8.0' => 'DateTimeZone|null'], default: 'DateTimeZone')] $timezone = null ): DateTime|false {} /** * Returns an array of warnings and errors found while parsing a date/time string * @return array|false * @link https://php.net/manual/en/datetime.getlasterrors.php */ #[ArrayShape(["warning_count" => "int", "warnings" => "string[]", "error_count" => "int", "errors" => "string[]"])] #[TentativeType] public static function getLastErrors(): array|false {} /** * The __set_state handler * @link https://php.net/manual/en/datetime.set-state.php * @param array $array

    Initialization array.

    * @return DateTime

    Returns a new instance of a DateTime object.

    */ public static function __set_state($array) {} /** * @param DateTimeInterface $object * @return DateTime * @since 8.0 */ public static function createFromInterface(DateTimeInterface $object): DateTime {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __serialize(): array {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __unserialize(array $data): void {} /** * @since 8.4 */ #[TentativeType] public static function createFromTimestamp(int|float $timestamp): static {} /** * @since 8.4 */ public function getMicrosecond(): int {} /** * @since 8.4 */ public function setMicrosecond(int $microsecond): static {} } /** * Representation of time zone * @link https://php.net/manual/en/class.datetimezone.php */ class DateTimeZone { public const AFRICA = 1; public const AMERICA = 2; public const ANTARCTICA = 4; public const ARCTIC = 8; public const ASIA = 16; public const ATLANTIC = 32; public const AUSTRALIA = 64; public const EUROPE = 128; public const INDIAN = 256; public const PACIFIC = 512; public const UTC = 1024; public const ALL = 2047; public const ALL_WITH_BC = 4095; public const PER_COUNTRY = 4096; /** * @param string $timezone * @link https://php.net/manual/en/datetimezone.construct.php * @throws DateInvalidTimeZoneException Emits Exception in case of an error. */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $timezone) {} /** * Returns the name of the timezone * @return string * @link https://php.net/manual/en/datetimezone.getname.php */ #[TentativeType] public function getName(): string {} /** * Returns location information for a timezone * @return array|false * @link https://php.net/manual/en/datetimezone.getlocation.php */ #[TentativeType] #[ArrayShape([ 'country_code' => 'string', 'latitude' => 'double', 'longitude' => 'double', 'comments' => 'string', ])] public function getLocation(): array|false {} /** * Returns the timezone offset from GMT * @param DateTimeInterface $datetime * @return int * @link https://php.net/manual/en/datetimezone.getoffset.php */ #[TentativeType] public function getOffset(DateTimeInterface $datetime): int {} /** * Returns all transitions for the timezone * @param int $timestampBegin * @param int $timestampEnd * @return array|false * @link https://php.net/manual/en/datetimezone.gettransitions.php */ #[TentativeType] public function getTransitions( #[PhpStormStubsElementAvailable(from: '5.3', to: '5.6')] $timestampBegin, #[PhpStormStubsElementAvailable(from: '5.3', to: '5.6')] $timestampEnd, #[PhpStormStubsElementAvailable(from: '7.0')] #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $timestampBegin = PHP_INT_MIN, #[PhpStormStubsElementAvailable(from: '7.0')] #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $timestampEnd = PHP_INT_MAX ): array|false {} /** * Returns associative array containing dst, offset and the timezone name * @return array> * @link https://php.net/manual/en/datetimezone.listabbreviations.php */ #[TentativeType] public static function listAbbreviations(): array {} /** * Returns a numerically indexed array with all timezone identifiers * @param int $timezoneGroup * @param string $countryCode * @return array|false Returns the array of timezone identifiers, or FALSE on failure. Since PHP8, always returns array. * @link https://php.net/manual/en/datetimezone.listidentifiers.php */ #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] #[TentativeType] public static function listIdentifiers( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $timezoneGroup = DateTimeZone::ALL, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $countryCode = null ): array {} /** * @link https://php.net/manual/en/datetime.wakeup.php */ #[TentativeType] public function __wakeup(): void {} public static function __set_state($an_array) {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __serialize(): array {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __unserialize(array $data): void {} } /** * Representation of date interval. A date interval stores either a fixed amount of * time (in years, months, days, hours etc) or a relative time string in the format * that DateTime's constructor supports. * @link https://php.net/manual/en/class.dateinterval.php */ class DateInterval { /** * Number of years * @var int */ public $y; /** * Number of months * @var int */ public $m; /** * Number of days * @var int */ public $d; /** * Number of hours * @var int */ public $h; /** * Number of minutes * @var int */ public $i; /** * Number of seconds * @var int */ public $s; /** * Number of microseconds * @since 7.1.0 * @var float */ public $f; /** * Is 1 if the interval is inverted and 0 otherwise * @var int */ public $invert; /** * Total number of days the interval spans. If this is unknown, days will be FALSE. * @var int|false */ public $days; /** * @param string $duration * @throws DateMalformedIntervalStringException when the $duration cannot be parsed as an interval. * @link https://php.net/manual/en/dateinterval.construct.php */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $duration) {} /** * Formats the interval * @param string $format * @return string * @link https://php.net/manual/en/dateinterval.format.php */ #[TentativeType] public function format(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $format): string {} /** * Sets up a DateInterval from the relative parts of the string * @param string $datetime * @return DateInterval|false Returns a new {@link https://www.php.net/manual/en/class.dateinterval.php DateInterval} * instance on success, or FALSE on failure. * @link https://php.net/manual/en/dateinterval.createfromdatestring.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'DateInterval'], default: 'DateInterval|false')] public static function createFromDateString(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $datetime) {} #[TentativeType] public function __wakeup(): void {} public static function __set_state($an_array) {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __serialize(): array {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __unserialize(array $data): void {} } /** * Representation of date period. * @link https://php.net/manual/en/class.dateperiod.php * @template TDate of DateTimeInterface * @template TEnd of ?DateTimeInterface * @implements \IteratorAggregate */ class DatePeriod implements IteratorAggregate { public const EXCLUDE_START_DATE = 1; /** * @since 8.2 */ public const INCLUDE_END_DATE = 2; /** * Start date * @var DateTimeInterface */ #[LanguageLevelTypeAware(['8.2' => 'DateTimeInterface|null'], default: '')] #[Immutable] public $start; /** * Current iterator value. * @var DateTimeInterface|null */ #[LanguageLevelTypeAware(['8.2' => 'DateTimeInterface|null'], default: '')] public $current; /** * End date. * @var DateTimeInterface|null */ #[LanguageLevelTypeAware(['8.2' => 'DateTimeInterface|null'], default: '')] #[Immutable] public $end; /** * The interval * @var DateInterval */ #[LanguageLevelTypeAware(['8.2' => 'DateInterval|null'], default: '')] #[Immutable] public $interval; /** * Number of recurrences. * @var int */ #[LanguageLevelTypeAware(['8.2' => 'int'], default: '')] #[Immutable] public $recurrences; /** * Start of period. * @var bool */ #[LanguageLevelTypeAware(['8.2' => 'bool'], default: '')] #[Immutable] public $include_start_date; /** * @since 8.2 */ #[Immutable] public bool $include_end_date; /** * @param TDate $start * @param DateInterval $interval * @param TEnd $end * @param int $options Can be set to DatePeriod::EXCLUDE_START_DATE. * @link https://php.net/manual/en/dateperiod.construct.php */ public function __construct(DateTimeInterface $start, DateInterval $interval, DateTimeInterface $end, $options = 0) {} /** * @param TDate $start * @param DateInterval $interval * @param int $recurrences Number of recurrences * @param int $options Can be set to DatePeriod::EXCLUDE_START_DATE. * @link https://php.net/manual/en/dateperiod.construct.php */ public function __construct(DateTimeInterface $start, DateInterval $interval, $recurrences, $options = 0) {} /** * @param string $isostr String containing the ISO interval. * @param int $options Can be set to DatePeriod::EXCLUDE_START_DATE. * @throws DateMalformedPeriodStringException * @link https://php.net/manual/en/dateperiod.construct.php */ public function __construct($isostr, $options = 0) {} /** * Gets the interval * @return DateInterval * @link https://php.net/manual/en/dateperiod.getdateinterval.php * @since 5.6.5 */ #[TentativeType] public function getDateInterval(): DateInterval {} /** * Gets the end date * @return DateTimeInterface|null * @link https://php.net/manual/en/dateperiod.getenddate.php * @since 5.6.5 * @return TEnd */ #[TentativeType] public function getEndDate(): ?DateTimeInterface {} /** * Gets the start date * @return DateTimeInterface * @link https://php.net/manual/en/dateperiod.getstartdate.php * @since 5.6.5 * @return TDate */ #[TentativeType] public function getStartDate(): DateTimeInterface {} #[TentativeType] public static function __set_state(#[PhpStormStubsElementAvailable(from: '7.3')] array $array): DatePeriod {} #[TentativeType] public function __wakeup(): void {} /** * Get the number of recurrences * @return int|null * @link https://php.net/manual/en/dateperiod.getrecurrences.php * @since 7.2.17 */ #[TentativeType] public function getRecurrences(): ?int {} /** * @return \Iterator * @since 8.0 */ public function getIterator(): Iterator {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __serialize(): array {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __unserialize(array $data): void {} /** * @since 8.3 */ public static function createFromISO8601String(string $specification, int $options = 0): static {} } /** * @since 8.3 */ class DateError extends Error {} /** * @since 8.3 */ class DateObjectError extends DateError {} /** * @since 8.3 */ class DateRangeError extends DateError {} /** * @since 8.3 */ class DateException extends Exception {} /** * @since 8.3 */ class DateInvalidTimeZoneException extends DateException {} /** * @since 8.3 */ class DateInvalidOperationException extends DateException {} /** * @since 8.3 */ class DateMalformedStringException extends DateException {} /** * @since 8.3 */ class DateMalformedIntervalStringException extends DateException {} /** * @since 8.3 */ class DateMalformedPeriodStringException extends DateException {} * The string to parse. Before PHP 5.0.0, microseconds weren't allowed in * the time, since PHP 5.0.0 they are allowed but ignored. *

    * @param int|null $baseTimestamp [optional]

    * Default value: null * The timestamp which is used as a base for the calculation of relative * dates. *

    * @return int|false a timestamp on success, false otherwise. Previous to PHP 5.1.0, * this function would return -1 on failure. */ #[Pure(true)] function strtotime(string $datetime, ?int $baseTimestamp): int|false {} /** * Format a local time/date * @link https://php.net/manual/en/function.date.php * @param string $format

    * The format of the outputted date string. See the formatting * options below. There are also several * predefined date constants * that may be used instead, so for example DATE_RSS * contains the format string 'D, d M Y H:i:s'. *

    *

    *
    * The following characters are recognized in the * format parameter string: *

    *

    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    format characterDescriptionExample returned values
    Day------
    dDay of the month, 2 digits with leading zeros01 to 31
    DA textual representation of a day, three lettersMon through Sun
    jDay of the month without leading zeros1 to 31
    l (lowercase 'L')A full textual representation of the day of the weekSunday through Saturday
    NISO-8601 numeric representation of the day of the week (added in * PHP 5.1.0)1 (for Monday) through 7 (for Sunday)
    SEnglish ordinal suffix for the day of the month, 2 characters * st, nd, rd or * th. Works well with j *
    wNumeric representation of the day of the week0 (for Sunday) through 6 (for Saturday)
    zThe day of the year (starting from 0)0 through 365
    Week------
    WISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0)Example: 42 (the 42nd week in the year)
    Month------
    FA full textual representation of a month, such as January or MarchJanuary through December
    mNumeric representation of a month, with leading zeros01 through 12
    MA short textual representation of a month, three lettersJan through Dec
    nNumeric representation of a month, without leading zeros1 through 12
    tNumber of days in the given month28 through 31
    Year------
    LWhether it's a leap year1 if it is a leap year, 0 otherwise.
    oISO-8601 year number. This has the same value as * Y, except that if the ISO week number * (W) belongs to the previous or next year, that year * is used instead. (added in PHP 5.1.0)Examples: 1999 or 2003
    YA full numeric representation of a year, 4 digitsExamples: 1999 or 2003
    yA two digit representation of a yearExamples: 99 or 03
    Time------
    aLowercase Ante meridiem and Post meridiemam or pm
    AUppercase Ante meridiem and Post meridiemAM or PM
    BSwatch Internet time000 through 999
    g12-hour format of an hour without leading zeros1 through 12
    G24-hour format of an hour without leading zeros0 through 23
    h12-hour format of an hour with leading zeros01 through 12
    H24-hour format of an hour with leading zeros00 through 23
    iMinutes with leading zeros00 to 59
    sSeconds, with leading zeros00 through 59
    uMicroseconds (added in PHP 5.2.2)Example: 654321
    Timezone------
    eTimezone identifier (added in PHP 5.1.0)Examples: UTC, GMT, Atlantic/Azores
    I (capital i)Whether or not the date is in daylight saving time1 if Daylight Saving Time, 0 otherwise.
    ODifference to Greenwich time (GMT) in hoursExample: +0200
    PDifference to Greenwich time (GMT) with colon between hours and minutes (added in PHP 5.1.3)Example: +02:00
    TTimezone abbreviationExamples: EST, MDT ...
    ZTimezone offset in seconds. The offset for timezones west of UTC is always * negative, and for those east of UTC is always positive.-43200 through 50400
    Full Date/Time------
    cISO 8601 date (added in PHP 5)2004-02-12T15:19:21+00:00
    rRFC 2822 formatted dateExample: Thu, 21 Dec 2000 16:01:07 +0200
    USeconds since the Unix Epoch (January 1 1970 00:00:00 GMT)See also time
    *

    *

    * Unrecognized characters in the format string will be printed * as-is. The Z format will always return * 0 when using gmdate. *

    *

    * Since this function only accepts integer timestamps the * u format character is only useful when using the * date_format function with user based timestamps * created with date_create. *

    * @param int|null $timestamp [optional] Default value: time(). The optional timestamp parameter is an integer Unix timestamp * that defaults to the current local time if a timestamp is not given. * @return string|false a formatted date string. If a non-numeric value is used for * timestamp, false is returned and an * E_WARNING level error is emitted. */ #[Pure(true)] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] function date(string $format, ?int $timestamp) {} /** * Format a local time/date as integer * @link https://php.net/manual/en/function.idate.php * @param string $format

    *

    * The following characters are recognized in the * format parameter string * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    format characterDescription
    BSwatch Beat/Internet Time
    dDay of the month
    hHour (12 hour format)
    HHour (24 hour format)
    iMinutes
    I (uppercase i)returns 1 if DST is activated, * 0 otherwise
    L (uppercase l)returns 1 for leap year, * 0 otherwise
    mMonth number
    sSeconds
    tDays in current month
    USeconds since the Unix Epoch - January 1 1970 00:00:00 UTC - * this is the same as time
    wDay of the week (0 on Sunday)
    WISO-8601 week number of year, weeks starting on * Monday
    yYear (1 or 2 digits - check note below)
    YYear (4 digits)
    zDay of the year
    ZTimezone offset in seconds
    *

    * @param int|null $timestamp [optional] Default value: time(). The optional timestamp parameter is an integer Unix timestamp * that defaults to the current local time if a timestamp is not given. * @return int|false an integer. *

    * As idate always returns an integer and * as they can't start with a "0", idate may return * fewer digits than you would expect. See the example below. *

    */ #[Pure(true)] function idate(string $format, ?int $timestamp): int|false {} /** * Format a GMT/UTC date/time * @link https://php.net/manual/en/function.gmdate.php * @param string $format

    * The format of the outputted date string. See the formatting * options for the date function. *

    * @param int|null $timestamp [optional] Default value: time(). The optional timestamp parameter is an integer Unix timestamp * that defaults to the current local time if a timestamp is not given. * @return string|false a formatted date string. If a non-numeric value is used for * timestamp, false is returned and an * E_WARNING level error is emitted. */ #[Pure(true)] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] function gmdate(string $format, ?int $timestamp) {} /** * Get Unix timestamp for a date * @link https://php.net/manual/en/function.mktime.php * @param int $hour

    * The number of the hour. *

    * @param int|null $minute

    * The number of the minute. *

    * @param int|null $second

    * The number of seconds past the minute. *

    * @param int|null $month

    * The number of the month. *

    * @param int|null $day

    * The number of the day. *

    * @param int|null $year [optional]

    * The number of the year, may be a two or four digit value, * with values between 0-69 mapping to 2000-2069 and 70-100 to * 1970-2000. On systems where time_t is a 32bit signed integer, as * most common today, the valid range for year * is somewhere between 1901 and 2038. However, before PHP 5.1.0 this * range was limited from 1970 to 2038 on some systems (e.g. Windows). *

    * @param int $is_dst [optional]

    * This parameter can be set to 1 if the time is during daylight savings time (DST), * 0 if it is not, or -1 (the default) if it is unknown whether the time is within * daylight savings time or not. If it's unknown, PHP tries to figure it out itself. * This can cause unexpected (but not incorrect) results. * Some times are invalid if DST is enabled on the system PHP is running on or * is_dst is set to 1. If DST is enabled in e.g. 2:00, all times * between 2:00 and 3:00 are invalid and mktime returns an undefined * (usually negative) value. * Some systems (e.g. Solaris 8) enable DST at midnight so time 0:30 of the day when DST * is enabled is evaluated as 23:30 of the previous day. *

    *

    * As of PHP 5.1.0, this parameter became deprecated. As a result, the * new timezone handling features should be used instead. *

    *

    * This parameter has been removed in PHP 7.0.0. *

    * @return int|false mktime returns the Unix timestamp of the arguments * given. * If the arguments are invalid, the function returns false (before PHP 5.1 * it returned -1). */ #[Pure(true)] function mktime( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] int $hour = null, #[PhpStormStubsElementAvailable(from: '8.0')] int $hour, ?int $minute = null, ?int $second = null, ?int $month = null, ?int $day = null, ?int $year = null, #[Deprecated('Use the new timezone handling functions instead', since: '5.3')] #[PhpStormStubsElementAvailable(from: '5.5', to: '5.6')] int $is_dst = -1 ): int|false {} /** * Get Unix timestamp for a GMT date * @link https://php.net/manual/en/function.gmmktime.php * @param int $hour

    * The hour *

    * @param int $minute

    * The minute *

    * @param int $second

    * The second *

    * @param int $month

    * The month *

    * @param int $day

    * The day *

    * @param int $year

    * The year *

    * @param int $is_dst

    * Parameters always represent a GMT date so is_dst * doesn't influence the result. *

    * @return int|false a integer Unix timestamp. */ #[Pure(true)] function gmmktime( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] int $hour = null, #[PhpStormStubsElementAvailable(from: '8.0')] int $hour, ?int $minute = null, ?int $second = null, ?int $month = null, ?int $day = null, ?int $year = null, #[PhpStormStubsElementAvailable(from: '5.5', to: '5.6')] $is_dst = null ): int|false {} /** * Validate a Gregorian date * @link https://php.net/manual/en/function.checkdate.php * @param int $month

    * The month is between 1 and 12 inclusive. *

    * @param int $day

    * The day is within the allowed number of days for the given * month. Leap years * are taken into consideration. *

    * @param int $year

    * The year is between 1 and 32767 inclusive. *

    * @return bool true if the date given is valid; otherwise returns false. */ #[Pure(true)] function checkdate(int $month, int $day, int $year): bool {} /** * Format a local time/date according to locale settings * The following characters are recognized in the * format parameter string * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    formatDescriptionExample returned values * Day
    %aAn abbreviated textual representation of the daySun through Sat
    %AA full textual representation of the daySunday through Saturday
    %dTwo-digit day of the month (with leading zeros)01 to 31
    %eDay of the month, with a space preceding single digits 1 to 31
    %jDay of the year, 3 digits with leading zeros001 to 366
    %uISO-8601 numeric representation of the day of the week1 (for Monday) though 7 (for Sunday)
    %wNumeric representation of the day of the week0 (for Sunday) through 6 (for Saturday)
    Week
    %UWeek number of the given year, starting with the first * Sunday as the first week13 (for the 13th full week of the year)
    %VISO-8601:1988 week number of the given year, starting with * the first week of the year with at least 4 weekdays, with Monday * being the start of the week01 through 53 (where 53 * accounts for an overlapping week)
    %WA numeric representation of the week of the year, starting * with the first Monday as the first week46 (for the 46th week of the year beginning * with a Monday)
    Month
    %bAbbreviated month name, based on the localeJan through Dec
    %BFull month name, based on the localeJanuary through December
    %hAbbreviated month name, based on the locale (an alias of %b)Jan through Dec
    %mTwo digit representation of the month01 (for January) through 12 (for December)
    Year
    %CTwo digit representation of the century (year divided by 100, truncated to an integer)19 for the 20th Century
    %gTwo digit representation of the year going by ISO-8601:1988 standards (see %V)Example: 09 for the week of January 6, 2009
    %GThe full four-digit version of %gExample: 2008 for the week of January 3, 2009
    %yTwo digit representation of the yearExample: 09 for 2009, 79 for 1979
    %YFour digit representation for the yearExample: 2038
    Time
    %HTwo digit representation of the hour in 24-hour format00 through 23
    %ITwo digit representation of the hour in 12-hour format01 through 12
    %l (lower-case 'L')Hour in 12-hour format, with a space preceding single digits 1 through 12
    %MTwo digit representation of the minute00 through 59
    %pUPPER-CASE 'AM' or 'PM' based on the given timeExample: AM for 00:31, PM for 22:23
    %Plower-case 'am' or 'pm' based on the given timeExample: am for 00:31, pm for 22:23
    %rSame as "%I:%M:%S %p"Example: 09:34:17 PM for 21:34:17
    %RSame as "%H:%M"Example: 00:35 for 12:35 AM, 16:44 for 4:44 PM
    %STwo digit representation of the second00 through 59
    %TSame as "%H:%M:%S"Example: 21:34:17 for 09:34:17 PM
    %XPreferred time representation based on locale, without the dateExample: 03:59:16 or 15:59:16
    %zEither the time zone offset from UTC or the abbreviation (depends * on operating system)Example: -0500 or EST for Eastern Time
    %ZThe time zone offset/abbreviation option NOT given by %z (depends * on operating system)Example: -0500 or EST for Eastern Time
    Time and Date Stamps
    %cPreferred date and time stamp based on localExample: Tue Feb 5 00:45:10 2009 for * February 4, 2009 at 12:45:10 AM
    %DSame as "%m/%d/%y"Example: 02/05/09 for February 5, 2009
    %FSame as "%Y-%m-%d" (commonly used in database datestamps)Example: 2009-02-05 for February 5, 2009
    %sUnix Epoch Time timestamp (same as the time * function)Example: 305815200 for September 10, 1979 08:40:00 AM
    %xPreferred date representation based on locale, without the timeExample: 02/05/09 for February 5, 2009
    Miscellaneous
    %nA newline character ("\n")---
    %tA Tab character ("\t")---
    %%A literal percentage character ("%")---
    *

    * Maximum length of this parameter is 1023 characters. *

    * Contrary to ISO-9899:1999, Sun Solaris starts with Sunday as 1. * As a result, %u may not function as described in this manual. * @link https://php.net/manual/en/function.strftime.php * @param string $format * @param int|null $timestamp [optional] defaults to the value of time() * Unix timestamp that defaults to the current local time if a timestamp is not given.. * @return string|false a string formatted according format * using the given timestamp or the current * local time if no timestamp is given. Month and weekday names and * other language-dependent strings respect the current locale set * with setlocale. */ #[Deprecated(since: '8.1')] function strftime(string $format, ?int $timestamp): string|false {} /** * Format a GMT/UTC time/date according to locale settings * @link https://php.net/manual/en/function.gmstrftime.php * @param string $format

    * See description in strftime. *

    * @param int|null $timestamp [optional] * @return string|false a string formatted according to the given format string * using the given timestamp or the current * local time if no timestamp is given. Month and weekday names and * other language dependent strings respect the current locale set * with setlocale. * @deprecated 8.1 */ #[Deprecated(since: '8.1')] function gmstrftime(string $format, ?int $timestamp): string|false {} /** * Return current Unix timestamp * @link https://php.net/manual/en/function.time.php * @return int

    Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).

    */ function time(): int {} /** * Get the local time * @link https://php.net/manual/en/function.localtime.php * @param int|null $timestamp [optional] * @param bool $associative [optional]

    * If set to false or not supplied then the array is returned as a regular, * numerically indexed array. If the argument is set to true then * localtime returns an associative array containing * all the different elements of the structure returned by the C * function call to localtime. The names of the different keys of * the associative array are as follows: *

    * "tm_sec" - seconds * @return array */ #[Pure(true)] #[ArrayShape([ 'tm_sec' => 'int', 'tm_min' => 'int', 'tm_hour' => 'int', 'tm_mday' => 'int', 'tm_mon' => 'int', 'tm_year' => 'int', 'tm_wday' => 'int', 'tm_yday' => 'int', 'tm_isdst' => 'int', ])] function localtime(?int $timestamp, bool $associative = false): array {} /** * Get date/time information * @link https://php.net/manual/en/function.getdate.php * @param int|null $timestamp [optional] * @return array an associative array of information related to * the timestamp. Elements from the returned * associative array are as follows: *

    *

    *

    * Key elements of the returned associative array * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    KeyDescriptionExample returned values
    "seconds"Numeric representation of seconds0 to 59
    "minutes"Numeric representation of minutes0 to 59
    "hours"Numeric representation of hours0 to 23
    "mday"Numeric representation of the day of the month1 to 31
    "wday"Numeric representation of the day of the week0 (for Sunday) through 6 (for Saturday)
    "mon"Numeric representation of a month1 through 12
    "year"A full numeric representation of a year, 4 digitsExamples: 1999 or 2003
    "yday"Numeric representation of the day of the year0 through 365
    "weekday"A full textual representation of the day of the weekSunday through Saturday
    "month"A full textual representation of a month, such as January or MarchJanuary through December
    0 * Seconds since the Unix Epoch, similar to the values returned by * time and used by date. * * System Dependent, typically -2147483648 through * 2147483647. *
    */ #[Pure(true)] #[ArrayShape([ 'seconds' => 'int', 'minutes' => 'int', 'hours' => 'int', 'mday' => 'int', 'wday' => 'int', 'mon' => 'int', 'year' => 'int', 'yday' => 'int', 'weekday' => 'int', 'month' => 'string', 0 => 'int', ])] function getdate(?int $timestamp): array {} /** * Returns new DateTime object * @link https://php.net/manual/en/function.date-create.php * @param string $datetime [optional]

    * String in a format accepted by strtotime. *

    * @param DateTimeZone|null $timezone [optional]

    * Time zone of the time. *

    * @return DateTime|false DateTime object on success or false on failure. */ #[Pure(true)] function date_create(string $datetime = 'now', ?DateTimeZone $timezone): DateTime|false {} /** * (PHP 5.5)
    * Alias: * {@see DateTimeImmutable::__construct} * Returns new DateTimeImmutable object * @link https://php.net/manual/en/function.date-create-immutable.php * @see DateTimeImmutable::__construct() * @param string $datetime [optional]

    * String in a format accepted by strtotime. *

    * @param DateTimeZone|null $timezone [optional]

    * Time zone of the time. *

    * @return DateTimeImmutable|false DateTime object on success or false on failure. */ #[Pure(true)] function date_create_immutable(string $datetime = 'now', ?DateTimeZone $timezone): DateTimeImmutable|false {} /** * Returns new DateTimeImmutable object formatted according to the specified format * @link https://php.net/manual/en/function.date-create-immutable-from-format.php * @param string $format * @param string $datetime * @param DateTimeZone|null $timezone [optional] * @return DateTimeImmutable|false */ #[Pure(true)] function date_create_immutable_from_format(string $format, string $datetime, ?DateTimeZone $timezone): DateTimeImmutable|false {} /** * Alias: * {@see DateTime::createFromFormat} * @link https://php.net/manual/en/function.date-create-from-format.php * @param string $format Format accepted by date(). *

    If format does not contain the character ! then portions of the generated time which are not specified in format will be set to the current system time.

    *

    If format contains the character !, then portions of the generated time not provided in format, as well as values to the left-hand side of the !, will be set to corresponding values from the Unix epoch.

    *

    The Unix epoch is 1970-01-01 00:00:00 UTC.

    * @param string $datetime String representing the time. * @param DateTimeZone|null $timezone [optional] A DateTimeZone object representing the desired time zone. * @return DateTime|false

    Returns a new * {@see DateTime} instance or FALSE on failure.

    */ #[Pure(true)] function date_create_from_format(string $format, string $datetime, ?DateTimeZone $timezone): DateTime|false {} /** * Returns associative array with detailed info about given date * @link https://php.net/manual/en/function.date-parse.php * @param string $datetime

    * Date in format accepted by strtotime. *

    * @return array|false array with information about the parsed date * on success or false on failure. */ #[Pure(true)] #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] #[ArrayShape([ "year" => "int", "month" => "int", "day" => "int", "hour" => "int", "minute" => "int", "second" => "int", "fraction" => "double", "is_localtime" => "bool", "zone_type" => "int", "zone" => "int", "is_dst" => "bool", "tz_abbr" => "string", "tz_id" => "string", "relative" => "array", "warning_count" => "int", "warnings" => "array", "error_count" => "int", "errors" => "array" ])] function date_parse(string $datetime): false|array {} /** * Get info about given date formatted according to the specified format * @link https://php.net/manual/en/function.date-parse-from-format.php * @param string $format

    * Format accepted by date with some extras. *

    * @param string $datetime

    * String representing the date. *

    * @return array associative array with detailed info about given date. */ #[Pure(true)] #[ArrayShape([ 'year' => 'int', 'month' => 'int', 'day' => 'int', 'hour' => 'int', 'minute' => 'int', 'second' => 'int', 'fraction' => 'double', 'is_localtime' => 'bool', 'zone_type' => 'int', 'zone' => 'int', 'is_dst' => 'bool', 'tz_abbr' => 'string', 'tz_id' => 'string', 'relative' => 'array', 'warning_count' => 'int', 'warnings' => 'array', 'error_count' => 'int', 'errors' => 'array' ])] function date_parse_from_format(string $format, string $datetime): array {} /** * Returns the warnings and errors * Alias: * {@see DateTime::getLastErrors} * @link https://php.net/manual/en/function.date-get-last-errors.php * @return array|false

    Returns array containing info about warnings and errors.

    */ #[ArrayShape(["warning_count" => "int", "warnings" => "string[]", "error_count" => "int", "errors" => "string[]"])] #[Pure(true)] function date_get_last_errors(): array|false {} /** * Alias: * {@see DateTime::format} * @link https://php.net/manual/en/function.date-format.php * @param DateTimeInterface $object * @param string $format * @return string|false formatted date string on success or FALSE on failure. */ #[Pure(true)] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] function date_format(DateTimeInterface $object, string $format) {} /** * Alter the timestamp of a DateTime object by incrementing or decrementing * in a format accepted by strtotime(). * Alias: * {@see DateTime::modify} * @link https://php.net/manual/en/function.date-modify.php * @param DateTime $object A DateTime object returned by date_create(). The function modifies this object. * @param string $modifier A date/time string. Valid formats are explained in {@link https://secure.php.net/manual/en/datetime.formats.php Date and Time Formats}. * @return DateTime|false Returns the DateTime object for method chaining or FALSE on failure. */ function date_modify(DateTime $object, string $modifier): DateTime|false {} /** * Alias: * {@see DateTime::add} * @link https://php.net/manual/en/function.date-add.php * @param DateTime $object

    Procedural style only: A * {@see DateTime} object returned by * {@see date_create()}. The function modifies this object.

    * @param DateInterval $interval

    A * {@see DateInterval} object

    * @return DateTime|false

    Returns the * {@see DateTime} object for method chaining or FALSE on failure.

    */ #[LanguageLevelTypeAware(["8.0" => "DateTime"], default: "DateTime|false")] function date_add(DateTime $object, DateInterval $interval) {} /** * Subtracts an amount of days, months, years, hours, minutes and seconds from a datetime object * Alias: * {@see DateTime::sub} * @link https://php.net/manual/en/function.date-sub.php * @param DateTime $object Procedural style only: A * {@see DateTime} object returned by * {@see date_create()}. The function modifies this object. * @param DateInterval $interval

    A * {@see DateInterval} object

    * @return DateTime|false

    Returns the * {@see DateTime} object for method chaining or FALSE on failure.

    */ #[LanguageLevelTypeAware(["8.0" => "DateTime"], default: "DateTime|false")] function date_sub(DateTime $object, DateInterval $interval) {} /** * Alias: * {@see DateTime::getTimezone} * @link https://php.net/manual/en/function.date-timezone-get.php * @param DateTimeInterface $object

    Procedural style only: A * {@see DateTime} object * returned by * {@see date_create()}

    * @return DateTimeZone|false *

    * Returns a * {@see DateTimeZone} object on success * or FALSE on failure. *

    */ #[Pure(true)] function date_timezone_get(DateTimeInterface $object): DateTimeZone|false {} /** * Sets the time zone for the datetime object * Alias: * {@see DateTime::setTimezone} * @link https://php.net/manual/en/function.date-timezone-set.php * @param DateTime|DateTimeInterface $object

    A * {@see DateTime} object returned by * {@see date_create()}. The function modifies this object.

    * @param DateTimeZone $timezone

    A * {@see DateTimeZone} object representing the desired time zone.

    * @return DateTime|false

    Returns the * {@see DateTime} object for method chaining or FALSE on failure.

    */ #[LanguageLevelTypeAware(["8.0" => "DateTime"], default: "DateTime|false")] function date_timezone_set(#[LanguageLevelTypeAware(["8.0" => "DateTime"], default: "DateTimeInterface")] $object, DateTimeZone $timezone) {} /** * Alias: * {@see DateTime::getOffset} * @link https://php.net/manual/en/function.date-offset-get.php * @param DateTimeInterface $object

    Procedural style only: A {@see DateTime} object * returned by {@see date_create()}

    * @return int|false

    Returns the timezone offset in seconds from UTC on success or FALSE on failure.

    */ #[Pure(true)] #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function date_offset_get(DateTimeInterface $object) {} /** * Returns the difference between two datetime objects * Alias: * {@see DateTime::diff} * @link https://php.net/manual/en/function.date-diff.php * @param DateTimeInterface $baseObject * @param DateTimeInterface $targetObject The date to compare to * @param bool $absolute [optional] Whether to return absolute difference. * @return DateInterval|false The DateInterval object representing the difference between the two dates or FALSE on failure. */ #[Pure(true)] #[LanguageLevelTypeAware(["8.0" => "DateInterval"], default: "DateInterval|false")] function date_diff(DateTimeInterface $baseObject, DateTimeInterface $targetObject, bool $absolute = false) {} /** * Alias: * {@see DateTime::setTime} * @link https://php.net/manual/en/function.date-time-set.php * @param DateTime $object * @param int $hour * @param int $minute * @param int $second [optional] * @param int $microsecond [optional] * @return DateTime

    Returns the * {@see DateTime} object for method chaining or FALSE on failure.

    */ function date_time_set( DateTime $object, int $hour, int $minute, int $second = 0, #[PhpStormStubsElementAvailable(from: '7.1')] int $microsecond = 0 ): DateTime {} /** * Alias: * {@see DateTime::setDate} * @link https://php.net/manual/en/function.date-date-set.php * @param DateTime $object

    Procedural style only: A {@see DateTime} object * returned by {@see date_create()}. * The function modifies this object.

    * @param int $year

    Year of the date.

    * @param int $month

    Month of the date.

    * @param int $day

    Day of the date.

    * @return DateTime|false *

    * Returns the * {@see DateTime} object for method chaining or FALSE on failure. *

    */ #[LanguageLevelTypeAware(["8.0" => "DateTime"], default: "DateTime|false")] function date_date_set(DateTime $object, int $year, int $month, int $day): DateTime|false {} /** * Alias: * {@see DateTime::setISODate} * @link https://php.net/manual/en/function.date-isodate-set.php * @param DateTime $object * @param int $year

    Year of the date

    * @param int $week

    Week of the date.

    * @param int $dayOfWeek [optional]

    Offset from the first day of the week.

    * @return DateTime|false

    * Returns the {@see DateTime} object for method chaining or FALSE on failure. *

    */ #[LanguageLevelTypeAware(["8.0" => "DateTime"], default: "DateTime|false")] function date_isodate_set(DateTime $object, int $year, int $week, int $dayOfWeek = 1) {} /** * Sets the date and time based on an unix timestamp * Alias: * {@see DateTime::setTimestamp} * @link https://php.net/manual/en/function.date-timestamp-set.php * @param DateTime $object

    Procedural style only: A * {@see DateTime} object returned by * {@see date_create()}. The function modifies this object.

    * @param int $timestamp

    Unix timestamp representing the date.

    * @return DateTime|false * {@see DateTime} object for call chaining or FALSE on failure */ #[LanguageLevelTypeAware(["8.0" => "DateTime"], default: "DateTime|false")] function date_timestamp_set(DateTime $object, int $timestamp): DateTime|false {} /** * Gets the unix timestamp * Alias: * {@see DateTime::getTimestamp} * @link https://php.net/manual/en/function.date-timestamp-get.php * @param DateTimeInterface $object * @return int

    Returns the Unix timestamp representing the date.

    */ #[Pure(true)] function date_timestamp_get(DateTimeInterface $object): int {} /** * Returns new DateTimeZone object * @link https://php.net/manual/en/function.timezone-open.php * @param string $timezone

    * Time zone identifier as full name (e.g. Europe/Prague) or abbreviation * (e.g. CET). *

    * @return DateTimeZone|false DateTimeZone object on success or false on failure. */ #[Pure(true)] function timezone_open(string $timezone): DateTimeZone|false {} /** * Alias: * {@see DateTimeZone::getName} * @link https://php.net/manual/en/function.timezone-name-get.php * @param DateTimeZone $object

    The * {@see DateTimeZone} for which to get a name.

    * @return string One of the timezone names in the list of timezones. */ #[Pure] function timezone_name_get(DateTimeZone $object): string {} /** * Returns the timezone name from abbreviation * @link https://php.net/manual/en/function.timezone-name-from-abbr.php * @param string $abbr

    * Time zone abbreviation. *

    * @param int $utcOffset [optional]

    * Offset from GMT in seconds. Defaults to -1 which means that first found * time zone corresponding to abbr is returned. * Otherwise exact offset is searched and only if not found then the first * time zone with any offset is returned. *

    * @param int $isDST [optional]

    * Daylight saving time indicator. If abbr doesn't * exist then the time zone is searched solely by * offset and isdst. *

    * @return string|false time zone name on success or false on failure. * @since 5.1.3 */ #[Pure(true)] function timezone_name_from_abbr(string $abbr, int $utcOffset = -1, int $isDST = -1): string|false {} /** * Alias: * {@link DateTimeZone::getOffset} * @link https://php.net/manual/en/function.timezone-offset-get.php * @param DateTimeZone $object

    Procedural style only: A * {@see DateTimeZone} object * returned by * {@see timezone_open()}

    * @param DateTimeInterface $datetime

    DateTime that contains the date/time to compute the offset from.

    * @return int|false

    Returns time zone offset in seconds on success or FALSE on failure.

    */ #[Pure(true)] #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function timezone_offset_get(DateTimeZone $object, DateTimeInterface $datetime) {} /** * Returns all transitions for the timezone * Alias: * {@see DateTimeZone::getTransitions} * @link https://php.net/manual/en/function.timezone-transitions-get.php * @param DateTimeZone $object

    Procedural style only: A * {@see DateTimeZone} object returned by * {@see timezone_open()}

    * @param int $timestampBegin [optional]

    Begin timestamp

    * @param int $timestampEnd [optional]

    End timestamp

    * @return array|false

    Returns numerically indexed array containing associative array with all transitions on success or FALSE on failure.

    */ #[Pure(true)] function timezone_transitions_get(DateTimeZone $object, int $timestampBegin = PHP_INT_MIN, int $timestampEnd = PHP_INT_MAX): array|false {} /** * Alias: * {@see DateTimeZone::getLocation} * @link https://php.net/manual/en/function.timezone-location-get.php * @param DateTimeZone $object

    Procedural style only: A {@see DateTimeZone} object returned by {@see timezone_open()}

    * @return array|false

    Array containing location information about timezone.

    */ #[Pure(true)] #[ArrayShape([ 'country_code' => 'string', 'latitude' => 'double', 'longitude' => 'double', 'comments' => 'string', ])] function timezone_location_get(DateTimeZone $object): array|false {} /** * Returns a numerically indexed array containing all defined timezone identifiers * Alias: * {@see DateTimeZone::listIdentifiers()} * @link https://php.net/manual/en/function.timezone-identifiers-list.php * @param int $timezoneGroup [optional] One of DateTimeZone class constants. * @param string|null $countryCode [optional] A two-letter ISO 3166-1 compatible country code. * Note: This option is only used when $timezoneGroup is set to DateTimeZone::PER_COUNTRY. * @return array|false Returns array on success or FALSE on failure. */ #[Pure(true)] #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] function timezone_identifiers_list(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode) {} /** * Returns associative array containing dst, offset and the timezone name * Alias: * {@see DateTimeZone::listAbbreviations} * @link https://php.net/manual/en/function.timezone-abbreviations-list.php * @return array>|false Array on success or FALSE on failure. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] function timezone_abbreviations_list() {} /** * Gets the version of the timezonedb * @link https://php.net/manual/en/function.timezone-version-get.php * @return string a string. */ #[Pure] function timezone_version_get(): string {} /** * Alias: * {@see DateInterval::createFromDateString} * @link https://php.net/manual/en/function.date-interval-create-from-date-string.php * @param string $datetime

    A date with relative parts. Specifically, the relative formats supported by the parser used for * {@see strtotime()} and * {@see DateTime} will be used to construct the * {@see DateInterval}.

    * @return DateInterval|false *

    Returns a new DateInterval instance.

    */ #[Pure(true)] function date_interval_create_from_date_string(string $datetime): DateInterval|false {} /** * Alias: * {@see DateInterval::format} * @link https://php.net/manual/en/function.date-interval-format.php * @param DateInterval $object * @param string $format * @return string */ #[Pure(true)] function date_interval_format(DateInterval $object, string $format): string {} /** * Sets the default timezone used by all date/time functions in a script * @link https://php.net/manual/en/function.date-default-timezone-set.php * @param string $timezoneId

    * The timezone identifier, like UTC or * Europe/Lisbon. The list of valid identifiers is * available in the . *

    * @return bool This function returns false if the * timezone_identifier isn't valid, or true * otherwise. */ function date_default_timezone_set(string $timezoneId): bool {} /** * Gets the default timezone used by all date/time functions in a script * @link https://php.net/manual/en/function.date-default-timezone-get.php * @return string a string. */ #[Pure] function date_default_timezone_get(): string {} /** * Returns time of sunrise for a given day and location * @link https://php.net/manual/en/function.date-sunrise.php * @param int $timestamp

    * The timestamp of the day from which the sunrise * time is taken. *

    * @param int $returnFormat [optional]

    *

    * format constants * * * * * * * * * * * * * * * * * * * * *
    constantdescriptionexample
    SUNFUNCS_RET_STRINGreturns the result as string16:46
    SUNFUNCS_RET_DOUBLEreturns the result as float16.78243132
    SUNFUNCS_RET_TIMESTAMPreturns the result as integer (timestamp)1095034606
    *

    * @param float|null $latitude [optional]

    * Defaults to North, pass in a negative value for South. * See also: date.default_latitude *

    * @param float|null $longitude [optional]

    * Defaults to East, pass in a negative value for West. * See also: date.default_longitude *

    * @param float|null $zenith [optional]

    * Default: date.sunrise_zenith *

    * @param float|null $utcOffset [optional] * @return string|int|float|false the sunrise time in a specified format on * success or false on failure. * @deprecated 8.1 * Use {@link date_sun_info} instead */ #[Pure(true)] #[Deprecated(reason: 'in 8.1. Use date_sun_info instead', since: '8.1')] function date_sunrise(int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING, ?float $latitude, ?float $longitude, ?float $zenith, ?float $utcOffset): string|int|float|false {} /** * Returns time of sunset for a given day and location * @link https://php.net/manual/en/function.date-sunset.php * @param int $timestamp

    * The timestamp of the day from which the sunset * time is taken. *

    * @param int $returnFormat [optional]

    *

    * format constants * * * * * * * * * * * * * * * * * * * * *
    constantdescriptionexample
    SUNFUNCS_RET_STRINGreturns the result as string16:46
    SUNFUNCS_RET_DOUBLEreturns the result as float16.78243132
    SUNFUNCS_RET_TIMESTAMPreturns the result as integer (timestamp)1095034606
    *

    * @param float|null $latitude [optional]

    * Defaults to North, pass in a negative value for South. * See also: date.default_latitude *

    * @param float|null $longitude [optional]

    * Defaults to East, pass in a negative value for West. * See also: date.default_longitude *

    * @param float|null $zenith [optional]

    * Default: date.sunset_zenith *

    * @param float|null $utcOffset [optional] * @return string|int|float|false the sunset time in a specified format on * success or false on failure. */ #[Pure(true)] #[Deprecated(reason: 'in 8.1. Use date_sun_info instead', since: '8.1')] function date_sunset(int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING, ?float $latitude, ?float $longitude, ?float $zenith, ?float $utcOffset): string|int|float|false {} /** * Returns an array with information about sunset/sunrise and twilight begin/end * @link https://php.net/manual/en/function.date-sun-info.php * @param int $timestamp

    * Timestamp. *

    * @param float $latitude

    * Latitude in degrees. *

    * @param float $longitude

    * Longitude in degrees. *

    * @return array{ * sunrise: int|bool, * sunset: int|bool, * transit: int|bool, * civil_twilight_begin: int|bool, * civil_twilight_end: int|bool, * nautical_twilight_begin: int|bool, * nautical_twilight_end: int|bool, * astronomical_twilight_begin: int|bool, * astronomical_twilight_end: int|bool, * }|false Returns array on success or false on failure. The structure of the array is detailed in the following list: * * * * * * * * * * *
    sunriseThe timestamp of the sunrise (zenith angle = 90°35').
    sunsetThe timestamp of the sunset (zenith angle = 90°35').
    transitThe timestamp when the sun is at its zenith, i.e. has reached its topmost point.
    civil_twilight_beginThe start of the civil dawn (zenith angle = 96°). It ends at sunrise.
    civil_twilight_endThe end of the civil dusk (zenith angle = 96°). It starts at sunset.
    nautical_twilight_beginThe start of the nautical dawn (zenith angle = 102°). It ends at civil_twilight_begin.
    nautical_twilight_endThe end of the nautical dusk (zenith angle = 102°). It starts at civil_twilight_end.
    astronomical_twilight_beginThe start of the astronomical dawn (zenith angle = 108°). It ends at nautical_twilight_begin.
    astronomical_twilight_endThe end of the astronomical dusk (zenith angle = 108°). It starts at nautical_twilight_end.
    *
    * The values of the array elements are either UNIX timestamps, false if the * sun is below the respective zenith for the whole day, or true if the sun is * above the respective zenith for the whole day. * @since 5.1.2 */ #[Pure(true)] #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] #[ArrayShape([ "sunrise" => "int", "sunset" => "int", "transit" => "int", "civil_twilight_begin" => "int", "civil_twilight_end" => "int", "nautical_twilight_begin" => "int", "nautical_twilight_end" => "int", "astronomical_twilight_begin" => "int", "astronomical_twilight_end" => "int" ])] function date_sun_info(int $timestamp, float $latitude, float $longitude): array|false {} // End of date v.5.3.2-0.dotdeb.1 Create and initialize new event base

    * *

    Returns new event base, which can be used later in {@link event_base_set}(), {@link event_base_loop}() and other functions.

    * * @link https://php.net/event_base_new * * @return resource|false returns valid event base resource on success or FALSE on error. */ function event_base_new() {} /** *

    Destroy event base

    *

    (PECL libevent >= 0.0.1)

    * *

    Destroys the specified event_base and frees all the resources associated. * Note that it's not possible to destroy an event base with events attached to it.

    * * @link https://php.net/event_base_free * * @param resource $event_base Valid event base resource. * * @return void */ function event_base_free($event_base) {} /** *

    Handle events

    *

    (PECL libevent >= 0.0.1)

    * *

    Starts event loop for the specified event base.

    * *

    By default, the {@link event_base_loop}() function runs an event_base until * there are no more events registered in it. To run the loop, it repeatedly * checks whether any of the registered events has triggered (for example, * if a read event's file descriptor is ready to read, or if a timeout event's * timeout is ready to expire). Once this happens, it marks all triggered events * as "active", and starts to run them. *

    * *

    You can change the behavior of event_base_loop() by setting one or more flags * in its flags argument. If EVLOOP_ONCE is set, then the loop will wait until some * events become active, then run active events until there are no more to run, then * return. If EVLOOP_NONBLOCK is set, then the loop will not wait for events to trigger: * it will only check whether any events are ready to trigger immediately, * and run their callbacks if so. *

    * * @link https://php.net/event_base_loop * * @param resource $event_base Valid event base resource. * @param int $flags [optional] Optional parameter, which can take any combination of EVLOOP_ONCE and EVLOOP_NONBLOCK. * * @return int

    * Returns 0 if it exited normally, * -1 if it exited because of some unhandled error in the backend * and 1 if no events were registered. *

    */ function event_base_loop($event_base, $flags = null) {} /** *

    Tells the event_base to exit its loop immediately.

    *

    (PECL libevent >= 0.0.1)

    * *

    It differs from {@link event_base_loopexit}() in that if the event_base is currently * running callbacks for any active events, it will exit immediately after finishing the * one it's currently processing. The behaviour is similar to break statement.

    * * @link https://php.net/event_base_loopbreak * * @param resource $event_base Valid event base resource. * * @return bool returns TRUE on success or FALSE on error. */ function event_base_loopbreak($event_base) {} /** *

    Tells an event_base to stop looping after a given time has elapsed

    *

    (PECL libevent >= 0.0.1)

    * *

    If the event_base is currently running callbacks for any active events, * it will continue running them, and not exit until they have all been run.

    * *

    If event loop isn't running {@link event_base_loopexit}() schedules the next instance * of the event loop to stop right after the next round of callbacks are run (as if it had * been invoked with EVLOOP_ONCE).

    * * @link https://php.net/event_base_loopexit * * @param resource $event_base

    * Valid event base resource. *

    * @param int $timeout [optional]

    * Optional timeout parameter (in microseconds). If lower than 1, * the event_base stops looping without a delay. *

    * * @return bool returns TRUE on success or FALSE on error. */ function event_base_loopexit($event_base, $timeout = -1) {} /** *

    Associate event base with an event

    *

    (PECL libevent >= 0.0.1)

    * *

    Associates the event_base with the event.

    * * @link https://php.net/event_base_set * * @param resource $event Valid event resource. * @param resource $base Valid event base resource. * * @return bool returns TRUE on success or FALSE on error. */ function event_base_set($event, $base) {} /** *

    Set the number of different event priority levels

    *

    (PECL libevent >= 0.0.2)

    * *

    By default all events are scheduled with the same priority (npriorities/2). * Using {@link event_base_priority_init}() you can change the number of event priority * levels and then set a desired priority for each event.

    * * @link https://php.net/event_base_priority_init * * @param resource $event_base Valid event base resource. * @param int $npriorities The number of event priority levels. * * @return bool returns TRUE on success or FALSE on error. */ function event_base_priority_init($event_base, $npriorities) {} /** *

    Creates and returns a new event resource.

    *

    (PECL libevent >= 0.0.1)

    * * @link https://php.net/event_new * * @return resource|false returns a new event resource on success or FALSE on error. */ function event_new() {} /** *

    Free event resource.

    *

    (PECL libevent >= 0.0.1)

    * * @link https://php.net/event_free * * @param resource $event Valid event resource. * * @return void */ function event_free($event) {} /** *

    Add an event to the set of monitored events

    *

    (PECL libevent >= 0.0.1)

    * *

    Schedules the execution of the non-pending event (makes it pending in it's * configured base) when the event specified in {@link event_set}() occurs or in * at least the time specified by the timeout argument. If timeout was not specified, * not timeout is set. The event must be already initialized by * {@link event_set}() and {@link event_base_set}() functions. * If the event already has a timeout set, * it is replaced by the new one.

    * *

    If you call {@link event_add}() on an event that is already pending, * it will leave it pending, and reschedule it with the provided timeout.

    * * @link https://php.net/event_add * * @param resource $event

    * Valid event resource. *

    * @param int $timeout [optional]

    * Optional timeout (in microseconds). *

    * * @return bool returns TRUE on success or FALSE on error. */ function event_add($event, $timeout = -1) {} /** *

    Prepares the event to be used in {@link event_add}().

    *

    (PECL libevent >= 0.0.1)

    * *

    The event is prepared to call the function specified by the callback * on the events specified in parameter events, which is a set of the following * flags: EV_TIMEOUT, EV_SIGNAL, EV_READ, EV_WRITE and EV_PERSIST.

    * *

    EV_SIGNAL support was added in version 0.0.4

    * *

    After initializing the event, use {@link event_base_set}() to associate the event with its event base.

    * *

    In case of matching event, these three arguments are passed to the callback function: *

    * * * * * * * * * * * * *
    $fdSignal number or resource indicating the stream.
    $eventsA flag indicating the event. Consists of the following flags: EV_TIMEOUT, EV_SIGNAL, EV_READ, EV_WRITE and EV_PERSIST.
    $argOptional parameter, previously passed to {@link event_set}() as arg.
    *

    * * @link https://php.net/event_set * * @param resource $event

    * Valid event resource. *

    * @param resource|int $fd

    * Valid PHP stream resource. The stream must be castable to file descriptor, * so you most likely won't be able to use any of filtered streams. *

    * @param int $events

    * A set of flags indicating the desired event, can be EV_READ and/or EV_WRITE. * The additional flag EV_PERSIST makes the event to persist until {@link event_del}() is * called, otherwise the callback is invoked only once. *

    * @param callable $callback

    * Callback function to be called when the matching event occurs. *

    * @param mixed $arg [optional]

    * Optional callback parameter. *

    * * @return bool returns TRUE on success or FALSE on error. */ function event_set($event, $fd, $events, $callback, $arg = null) {} /** *

    Remove an event from the set of monitored events.

    *

    (PECL libevent >= 0.0.1)

    * *

    Calling {@link event_del}() on an initialized event makes it non-pending * and non-active. If the event was not pending or active, there is no effect.

    * * @link https://php.net/event_del * * @param resource $event Valid event resource. * * @return bool returns TRUE on success or FALSE on error. */ function event_del($event) {} /** *

    Create new buffered event

    *

    (PECL libevent >= 0.0.1)

    * *

    Libevent provides an abstraction layer on top of the regular event API. * Using buffered event you don't need to deal with the I/O manually, instead * it provides input and output buffers that get filled and drained automatically.

    * *

    Every bufferevent has two data-related callbacks: a read callback and a write * callback. By default, the read callback is called whenever any data is read from * the underlying transport, and the write callback is called whenever enough data * from the output buffer is emptied to the underlying transport. You can override * the behavior of these functions by adjusting the read and write "watermarks" * of the bufferevent (see {@link event_buffer_watermark_set}()).

    * *

    A bufferevent also has an "error" or "event" callback that gets invoked to tell * the application about non-data-oriented events, like when a connection is closed or * an error occurs.

    * * @link https://php.net/event_buffer_new * * @param resource $stream Valid PHP stream resource. Must be castable to file descriptor. * @param callable|null $readcb Callback to invoke where there is data to read, or NULL if no callback is desired. * @param callable|null $writecb Callback to invoke where the descriptor is ready for writing, or NULL if no callback is desired. * @param callable $errorcb Callback to invoke where there is an error on the descriptor, cannot be NULL. * @param mixed $arg An argument that will be passed to each of the callbacks (optional). * * @return resource|false returns new buffered event resource on success or FALSE on error. */ function event_buffer_new($stream, $readcb, $writecb, $errorcb, $arg = null) {} /** *

    Destroys the specified buffered event and frees all the resources associated.

    *

    (PECL libevent >= 0.0.1)

    * * @link https://php.net/event_buffer_free * * @param resource $bevent Valid buffered event resource. * * @return void */ function event_buffer_free($bevent) {} /** *

    Associate buffered event with an event base

    *

    (PECL libevent >= 0.0.1)

    * *

    Assign the specified bevent to the event_base.

    * * @link https://php.net/event_buffer_base_set * * @param resource $bevent Valid buffered event resource. * @param resource $event_base Valid event base resource. * * @return bool returns TRUE on success or FALSE on error. */ function event_buffer_base_set($bevent, $event_base) {} /** *

    Assign a priority to a buffered event. Use it after * initializing event, but before adding an event to the event_base.

    *

    (PECL libevent >= 0.0.1)

    * *

    When multiple events trigger at the same time, Libevent * does not define any order with respect to when their callbacks * will be executed. You can define some events as more important * than others by using priorities.

    * *

    When multiple events of multiple priorities become active, * the low-priority events are not run. Instead, Libevent runs * the high priority events, then checks for events again. Only * when no high-priority events are active are the low-priority * events run.

    * *

    When you do not set the priority for an event, the default * is the number of queues in the event base, divided by 2.

    * * @link https://php.net/event_buffer_priority_set * * @see event_base_priority_init * * @param resource $bevent

    * Valid buffered event resource. *

    * @param int $priority

    * Priority level. Cannot be less than 0 and cannot exceed * maximum priority level of the event base (see {@link event_base_priority_init}()). *

    * * @return bool returns TRUE on success or FALSE on error. */ function event_buffer_priority_set($bevent, $priority) {} /** *

    Writes data to the specified buffered event.

    *

    (PECL libevent >= 0.0.1)

    * *

    The data is appended to the output buffer and written * to the descriptor when it becomes available for writing.

    * * @link https://php.net/event_buffer_write * * @param resource $bevent Valid buffered event resource. * @param string $data The data to be written. * @param int $data_size Optional size parameter. {@link event_buffer_write}() writes all the data by default * * @return bool returns TRUE on success or FALSE on error. */ function event_buffer_write($bevent, $data, $data_size = -1) {} /** *

    Reads data from the input buffer of the buffered event.

    *

    (PECL libevent >= 0.0.1)

    * * @link https://php.net/event_buffer_read * * @param resource $bevent Valid buffered event resource. * @param int $data_size Data size in bytes. * * @return string */ function event_buffer_read($bevent, $data_size) {} /** *

    Enables the specified buffered event.

    *

    (PECL libevent >= 0.0.1)

    * * @link https://php.net/event_buffer_enable * * @param resource $bevent Valid buffered event resource. * @param int $events Any combination of EV_READ and EV_WRITE. * * @return bool returns TRUE on success or FALSE on error. */ function event_buffer_enable($bevent, $events) {} /** *

    Disable a buffered event

    *

    (PECL libevent >= 0.0.1)

    * *

    Disables the specified buffered event.

    * * @link https://php.net/event_buffer_disable * * @param resource $bevent Valid buffered event resource. * @param int $events Any combination of EV_READ and EV_WRITE. * * @return bool returns TRUE on success or FALSE on error. */ function event_buffer_disable($bevent, $events) {} /** *

    Sets the read and write timeouts for the specified buffered event.

    *

    (PECL libevent >= 0.0.1)

    * * @link https://php.net/event_buffer_timeout_set * * @param resource $bevent Valid buffered event resource. * @param int $read_timeout Read timeout (in seconds). * @param int $write_timeout Write timeout (in seconds). * * @return void */ function event_buffer_timeout_set($bevent, $read_timeout, $write_timeout) {} /** *

    Set the watermarks for read and write events.

    *

    (PECL libevent >= 0.0.1)

    * *

    Every bufferevent has four watermarks:

    * *

    Read low-water mark
    * Whenever a read occurs that leaves the bufferevent's input buffer at this * level or higher, the bufferevent's read callback is invoked. Defaults to 0, * so that every read results in the read callback being invoked.

    * *

    Read high-water mark
    * If the bufferevent's input buffer ever gets to this level, the bufferevent * stops reading until enough data is drained from the input buffer to take us * below it again. Defaults to unlimited, so that we never stop reading because * of the size of the input buffer.

    * *

    Write low-water mark
    * Whenever a write occurs that takes us to this level or below, we invoke the write * callback. Defaults to 0, so that a write callback is not invoked unless the output * buffer is emptied.

    * *

    Write high-water mark
    * Not used by a bufferevent directly, this watermark can have special meaning when * a bufferevent is used as the underlying transport of another bufferevent.

    * *

    Libevent does not invoke read callback unless there is at least lowmark * bytes in the input buffer; if the read buffer is beyond the highmark, * reading is stopped. On output, the write callback is invoked whenever * the buffered data falls below the lowmark.

    * * @link https://php.net/event_buffer_watermark_set * * @param resource $bevent Valid buffered event resource. * @param int $events Any combination of EV_READ and EV_WRITE. * @param int $lowmark Low watermark. * @param int $highmark High watermark. * * @return void */ function event_buffer_watermark_set($bevent, $events, $lowmark, $highmark) {} /** *

    Changes the file descriptor on which the buffered event operates.

    *

    (PECL libevent >= 0.0.1)

    * * @link https://php.net/event_buffer_fd_set * * @param resource $bevent Valid buffered event resource. * @param resource $fd Valid PHP stream, must be castable to file descriptor. * * @return void */ function event_buffer_fd_set($bevent, $fd) {} /** *

    Set or reset callbacks for a buffered event

    *

    (PECL libevent >= 0.0.4)

    * *

    Sets or changes existing callbacks for the buffered event.

    * * @link https://php.net/event_buffer_set_callback * * @param resource $bevent Valid buffered event resource. * @param callable|null $readcb Callback to invoke where there is data to read, or NULL if no callback is desired. * @param callable|null $writecb Callback to invoke where the descriptor is ready for writing, or NULL if no callback is desired. * @param callable $errorcb Callback to invoke where there is an error on the descriptor, cannot be NULL. * @param mixed $arg An argument that will be passed to each of the callbacks (optional). * * @return bool returns TRUE on success or FALSE on error. */ function event_buffer_set_callback($bevent, $readcb, $writecb, $errorcb, $arg = null) {} /** *

    Alias of {@link event_new}().

    * * @return resource|false returns valid event base resource on success or FALSE on error. */ function event_timer_new() {} /** *

    Prepares the timer event to be used in {@link event_add}().

    * *

    The event is prepared to call the function specified by the callback * on the timeout event (EV_TIMEOUT).

    * *

    After initializing the event, use {@link event_base_set}() to associate the event with its event base.

    * *

    In case of matching event, these three arguments are passed to the callback function: *

    * * * * * * * * * * * * *
    $fdnull
    $eventsA flag indicating the event. EV_TIMEOUT.
    $argOptional parameter, previously passed to {@link event_timer_set}() as arg.
    *

    * * @param resource $event

    * Valid event resource. *

    * @param callable $callback

    * Callback function to be called when the matching event occurs. *

    * @param mixed $arg [optional]

    * Optional callback parameter. *

    * * @return void */ function event_timer_set($event, $callback, $arg = null) {} /** *

    Checks if a specific event is pending or scheduled.

    * * @param resource $event

    * Valid event resource. *

    * @param int $timeout [optional]

    * Optional timeout (in microseconds). *

    * * @return bool TRUE if event is not scheduled (added) FALSE otherwise */ function event_timer_pending($event, $timeout = -1) {} /** *

    Alias of {@link event_add}().

    * * @param resource $event

    * Valid event resource. *

    * @param int $timeout [optional]

    * Optional timeout (in microseconds). *

    * * @return bool returns TRUE on success or FALSE on error. */ function event_timer_add($event, $timeout = -1) {} /** *

    Alias of {@link event_del}().

    * * @param resource $event Valid event resource. * * @return bool returns TRUE on success or FALSE on error. */ function event_timer_del($event) {} // End of PECL libevent v.0.0.4 = 0.9.0)
    * Figures out the best way of encoding the content read from the given file pointer. * @link https://php.net/manual/en/function.mailparse-determine-best-xfer-encoding.php * @param resource $fp

    * A valid file pointer, which must be seek-able. *

    * @return string Returns one of the character encodings supported by the * {@link https://php.net/manual/en/ref.mbstring.php mbstring} module. */ function mailparse_determine_best_xfer_encoding($fp) {} /** * (PECL mailparse >= 0.9.0)
    * Create a MIME mail resource. * @link https://php.net/manual/en/function.mailparse-msg-create.php * @return resource Returns a handle that can be used to parse a message. */ function mailparse_msg_create() {} /** * (PECL mailparse >= 0.9.0)
    * Extracts/decodes a message section from the supplied filename. * The contents of the section will be decoded according to their transfer encoding - base64, quoted-printable and * uuencoded text are supported. * @link https://php.net/manual/en/function.mailparse-msg-extract-part-file.php * @param resource $mimemail

    * A valid MIME resource, created with {@link https://php.net/manual/en/function.mailparse-msg-create.php mailparse_msg_create()}. *

    * @param mixed $filename

    * Can be a file name or a valid stream resource. *

    * @param callable $callbackfunc [optional]

    * If set, this must be either a valid callback that will be passed the extracted section, or NULL to make this * function return the extracted section. *

    *

    * If not specified, the contents will be sent to "stdout". *

    * @return string|bool

    * If callbackfunc is not NULL returns TRUE on success. *

    *

    * If callbackfunc is set to NULL, returns the extracted section as a string. *

    *

    * Returns FALSE on error. *

    */ function mailparse_msg_extract_part_file($mimemail, $filename, $callbackfunc) {} /** * (PECL mailparse >= 0.9.0)
    * Extracts/decodes a message section * @link https://php.net/manual/en/function.mailparse-msg-extract-part.php * @param resource $mimemail

    * A valid MIME resource. *

    * @param string $msgbody * @param callable $callbackfunc [optional] * @return void */ function mailparse_msg_extract_part($mimemail, $msgbody, $callbackfunc) {} /** * (PECL mailparse >= 0.9.0)
    * Extracts a message section including headers without decoding the transfer encoding * @link https://php.net/manual/en/function.mailparse-msg-extract-whole-part-file.php * @param resource $mimemail

    * A valid MIME resource *

    * @param string $filename * @param callable $callbackfunc [optional] * @return string */ function mailparse_msg_extract_whole_part_file($mimemail, $filename, $callbackfunc) {} /** * (PECL mailparse >= 0.9.0)
    * Frees a MIME resource. * @link https://php.net/manual/en/function.mailparse-msg-free.php * @param resource $mimemail

    * A valid MIME resource allocated by * {@link https://php.net/manual/en/function.mailparse-msg-create.php mailparse_msg_create()} or * {@link https://php.net/manual/en/function.mailparse-msg-parse-file.php mailparse_msg_parse_file()}. *

    * @return bool Returns TRUE on success or FALSE on failure. */ function mailparse_msg_free($mimemail) {} /** * (PECL mailparse >= 0.9.0)
    * Returns an associative array of info about the message * @link https://php.net/manual/en/function.mailparse-msg-get-part-data.php * @param resource $mimemail

    * A valid MIME resource. *

    * @return array */ function mailparse_msg_get_part_data($mimemail) {} /** * (PECL mailparse >= 0.9.0)
    * Returns a handle on a given section in a mimemessage * @link https://php.net/manual/en/function.mailparse-msg-get-part.php * @param resource $mimemail

    * A valid MIME resource. *

    * @param string $mimesection * @return resource|false */ function mailparse_msg_get_part($mimemail, $mimesection) {} /** * (PECL mailparse >= 0.9.0)
    * Returns an array of mime section names in the supplied message * @link https://php.net/manual/en/function.mailparse-msg-get-structure.php * @param resource $mimemail

    * A valid MIME resource. *

    * @return array */ function mailparse_msg_get_structure($mimemail) {} /** * (PECL mailparse >= 0.9.0)
    * Parses a file. This is the optimal way of parsing a mail file that you have on disk. * @link https://php.net/manual/en/function.mailparse-msg-parse-file.php * @param string $filename

    * Path to the file holding the message. The file is opened and streamed through the parser. *

    * @return resource|false Returns a MIME resource representing the structure, or FALSE on error. */ function mailparse_msg_parse_file($filename) {} /** * (PECL mailparse >= 0.9.0)
    * Incrementally parse data into the supplied mime mail resource. * This function allow you to stream portions of a file at a time, rather than read and parse the whole thing. * @link https://php.net/manual/en/function.mailparse-msg-parse.php * @param resource $mimemail

    * A valid MIME resource. *

    * @param string $data * @return bool Returns TRUE on success or FALSE on failure. */ function mailparse_msg_parse($mimemail, $data) {} /** * (PECL mailparse >= 0.9.0)
    * Parses a {@link http://www.faqs.org/rfcs/rfc822 RFC 822} compliant recipient list, such as that found in the To: header. * @link https://php.net/manual/en/function.mailparse-rfc822-parse-addresses.php * @param string $addresses

    * A string containing addresses, like in:

    Wez Furlong , doe@example.com
    * Note: This string must not include the header name. *

    * @return array

    * Returns an array of associative arrays with the following keys for each recipient: *

    * * * * * * * * * * * * * *
    displayThe recipient name, for display purpose. If this part is not set for a recipient, this key will hold the same value as address.
    addressThe email address
    is_groupTRUE if the recipient is a newsgroup, FALSE otherwise.
    */ function mailparse_rfc822_parse_addresses($addresses) {} /** * (PECL mailparse >= 0.9.0)
    * Streams data from the source file pointer, apply encoding and write to the destination file pointer. * @link https://php.net/manual/en/function.mailparse-stream-encode.php * @param resource $sourcefp

    * A valid file handle. The file is streamed through the parser. *

    * @param resource $destfp

    * The destination file handle in which the encoded data will be written. *

    * @param string $encoding

    * One of the character encodings supported by the {@link https://php.net/manual/en/ref.mbstring.php mbstring} module. *

    * @return bool Returns TRUE on success or FALSE on failure. */ function mailparse_stream_encode($sourcefp, $destfp, $encoding) {} /** * (PECL mailparse >= 0.9.0)
    * Scans the data from the given file pointer and extract each embedded uuencoded file into a temporary file. * @link https://php.net/manual/en/function.mailparse-uudecode-all.php * @param resource $fp

    * A valid file pointer. *

    * @return array

    * Returns an array of associative arrays listing filename information. *

    * * * * * * * * * *
    filenamePath to the temporary file name created
    origfilenameThe original filename, for uuencoded parts only
    *

    * The first filename entry is the message body. The next entries are the decoded uuencoded files. *

    */ function mailparse_uudecode_all($fp) {} define('MAILPARSE_EXTRACT_OUTPUT', 0); define('MAILPARSE_EXTRACT_STREAM', 1); define('MAILPARSE_EXTRACT_RETURN', 2); // End of mailparse v. * Before 7.2.0 checked cookie status and since 7.2.0 checks both cookie and session status to avoid PHP crash. * @link https://php.net/manual/en/function.session-name.php * @param string|null $name [optional]

    * The session name references the name of the session, which is * used in cookies and URLs (e.g. PHPSESSID). It * should contain only alphanumeric characters; it should be short and * descriptive (i.e. for users with enabled cookie warnings). * If name is specified, the name of the current * session is changed to its value. *

    *

    *

    * The session name can't consist of digits only, at least one letter * must be present. Otherwise a new session id is generated every time. *

    *

    * @return string|false the name of the current session. */ #[LanguageLevelTypeAware(['8.0' => 'string|false'], default: 'string')] function session_name(#[LanguageLevelTypeAware(['8.0' => 'null|string'], default: 'string')] $name) {} /** * Get and/or set the current session module.
    * Since 7.2.0 it is forbidden to set the module name to "user". * @link https://php.net/manual/en/function.session-module-name.php * @param string|null $module [optional]

    * If module is specified, that module will be * used instead. *

    * @return string|false the name of the current session module. */ #[LanguageLevelTypeAware(['8.0' => 'string|false'], default: 'string')] function session_module_name(#[LanguageLevelTypeAware(['8.0' => 'null|string'], default: 'string')] $module) {} /** * Get and/or set the current session save path * @link https://php.net/manual/en/function.session-save-path.php * @param string|null $path [optional]

    * Session data path. If specified, the path to which data is saved will * be changed. session_save_path needs to be called * before session_start for that purpose. *

    *

    *

    * On some operating systems, you may want to specify a path on a * filesystem that handles lots of small files efficiently. For example, * on Linux, reiserfs may provide better performance than ext2fs. *

    *

    * @return string|false the path of the current directory used for data storage. */ #[LanguageLevelTypeAware(['8.0' => 'string|false'], default: 'string')] function session_save_path(#[LanguageLevelTypeAware(['8.0' => 'null|string'], default: 'string')] $path) {} /** * Get and/or set the current session id * @link https://php.net/manual/en/function.session-id.php * @param string|null $id [optional]

    * If id is specified, it will replace the current * session id. session_id needs to be called before * session_start for that purpose. Depending on the * session handler, not all characters are allowed within the session id. * For example, the file session handler only allows characters in the * range a-z A-Z 0-9 , (comma) and - (minus)! *

    * When using session cookies, specifying an id * for session_id will always send a new cookie * when session_start is called, regardless if the * current session id is identical to the one being set. * @return string|false session_id returns the session id for the current * session or the empty string ("") if there is no current * session (no current session id exists). */ #[LanguageLevelTypeAware(['8.0' => 'string|false'], default: 'string')] function session_id(#[LanguageLevelTypeAware(['8.0' => 'null|string'], default: 'string')] $id) {} /** * Update the current session id with a newly generated one * @link https://php.net/manual/en/function.session-regenerate-id.php * @param bool $delete_old_session [optional]

    * Whether to delete the old associated session file or not. *

    * @return bool true on success or false on failure. */ function session_regenerate_id(bool $delete_old_session = false): bool {} /** * PHP > 5.4.0
    * Session shutdown function * @link https://secure.php.net/manual/en/function.session-register-shutdown.php * @return void */ function session_register_shutdown(): void {} /** * Decodes session data from a string * @link https://php.net/manual/en/function.session-decode.php * @param string $data

    * The encoded data to be stored. *

    * @return bool true on success or false on failure. */ function session_decode(string $data): bool {} /** * Register one or more global variables with the current session * @link https://php.net/manual/en/function.session-register.php * @param mixed $name

    * A string holding the name of a variable or an array consisting of * variable names or other arrays. *

    * @param mixed ...$_ [optional] * @return bool true on success or false on failure. * @removed 5.4 */ #[Deprecated(since: '5.3')] function session_register(mixed $name, ...$_): bool {} /** * Unregister a global variable from the current session * @link https://php.net/manual/en/function.session-unregister.php * @param string $name

    * The variable name. *

    * @return bool true on success or false on failure. * @removed 5.4 */ #[Deprecated(since: '5.3')] function session_unregister(string $name): bool {} /** * Find out whether a global variable is registered in a session * @link https://php.net/manual/en/function.session-is-registered.php * @param string $name

    * The variable name. *

    * @return bool session_is_registered returns true if there is a * global variable with the name name registered in * the current session, false otherwise. * @removed 5.4 */ #[Deprecated(since: '5.3')] function session_is_registered(string $name): bool {} /** * Encodes the current session data as a string * @link https://php.net/manual/en/function.session-encode.php * @return string|false the contents of the current session encoded. */ #[LanguageLevelTypeAware(["8.0" => "string|false"], default: "string")] function session_encode() {} /** * Initialize session data * @link https://php.net/manual/en/function.session-start.php * @param array $options [optional]

    If provided, this is an associative array of options that will override the currently set session configuration directives. The keys should not include the session. prefix. * In addition to the normal set of configuration directives, a read_and_close option may also be provided. If set to TRUE, this will result in the session being closed immediately after being read, thereby avoiding unnecessary locking if the session data won't be changed.

    * @return bool This function returns true if a session was successfully started, * otherwise false. */ function session_start(#[PhpStormStubsElementAvailable(from: '7.0')] array $options = []): bool {} /** * Create new session id * @link https://www.php.net/manual/en/function.session-create-id.php * @param string $prefix [optional] If prefix is specified, new session id is prefixed by prefix. * Not all characters are allowed within the session id. * Characters in the range a-z A-Z 0-9 , (comma) and - (minus) are allowed. * @return string|false new collision free session id for the current session. * If it is used without active session, it omits collision check. * @since 7.1 */ #[LanguageLevelTypeAware(["8.0" => "string|false"], default: "string")] function session_create_id(string $prefix = '') {} /** * Perform session data garbage collection * @return int|false number of deleted session data for success, false for failure. * @since 7.1 */ #[LanguageLevelTypeAware(["8.0" => "int|false"], default: "int")] function session_gc() {} /** * Destroys all data registered to a session * @link https://php.net/manual/en/function.session-destroy.php * @return bool true on success or false on failure. */ function session_destroy(): bool {} /** * Free all session variables * @link https://php.net/manual/en/function.session-unset.php * @return void|bool since 7.2.0 returns true on success or false on failure. */ #[LanguageLevelTypeAware(["7.2" => "bool"], default: "void")] function session_unset() {} /** * Sets user-level session storage functions * @link https://php.net/manual/en/function.session-set-save-handler.php * @param callable $open

    * Open function, this works like a constructor in classes and is * executed when the session is being opened. The open function * expects two parameters, where the first is the save path and * the second is the session name. *

    * @param callable $close

    * Close function, this works like a destructor in classes and is * executed when the session operation is done. *

    * @param callable $read

    * Read function must return string value always to make save handler * work as expected. Return empty string if there is no data to read. * Return values from other handlers are converted to boolean expression. * true for success, false for failure. *

    * @param callable $write

    * Write function that is called when session data is to be saved. This * function expects two parameters: an identifier and the data associated * with it. *

    *

    * The "write" handler is not executed until after the output stream is * closed. Thus, output from debugging statements in the "write" * handler will never be seen in the browser. If debugging output is * necessary, it is suggested that the debug output be written to a * file instead. *

    * @param callable $destroy

    * The destroy handler, this is executed when a session is destroyed with * session_destroy and takes the session id as its * only parameter. *

    * @param callable $gc

    * The garbage collector, this is executed when the session garbage collector * is executed and takes the max session lifetime as its only parameter. *

    * @param callable|null $create_sid [optional] *

    This callback is executed when a new session ID is required. * No parameters are provided, and the return value should be a string that is a valid * session ID for your handler.

    * @param callable|null $validate_sid [optional] * @param callable|null $update_timestamp [optional] * @return bool true on success or false on failure. */ function session_set_save_handler(callable $open, callable $close, callable $read, callable $write, callable $destroy, callable $gc, ?callable $create_sid = null, ?callable $validate_sid = null, ?callable $update_timestamp = null): bool {} /** * (PHP 5.4)
    * Sets user-level session storage functions * @link https://php.net/manual/en/function.session-set-save-handler.php * @param SessionHandlerInterface $session_handler An instance of a class implementing SessionHandlerInterface, * and optionally SessionIdInterface and/or SessionUpdateTimestampHandlerInterface, such as SessionHandler, * to register as the session handler. Since PHP 5.4 only. * @param bool $register_shutdown [optional] Register session_write_close() as a register_shutdown_function() function. * @return bool true on success or false on failure. */ function session_set_save_handler(SessionHandlerInterface $sessionhandler, bool $register_shutdown = true): bool {} /** * Get and/or set the current cache limiter * @link https://php.net/manual/en/function.session-cache-limiter.php * @param string|null $value [optional]

    * If cache_limiter is specified, the name of the * current cache limiter is changed to the new value. *

    * * Possible values * * * * * * * * * * * * * * * * * * * * *
    ValueHeaders sent
    public *
     * Expires: (sometime in the future, according session.cache_expire)
     * Cache-Control: public, max-age=(sometime in the future, according to session.cache_expire)
     * Last-Modified: (the timestamp of when the session was last saved)
     * 
    *
    private_no_expire *
     * Cache-Control: private, max-age=(session.cache_expire in the future), pre-check=(session.cache_expire in the future)
     * Last-Modified: (the timestamp of when the session was last saved)
     * 
    *
    private *
     * Expires: Thu, 19 Nov 1981 08:52:00 GMT
     * Cache-Control: private, max-age=(session.cache_expire in the future), pre-check=(session.cache_expire in the future)
     * Last-Modified: (the timestamp of when the session was last saved)
     * 
    *
    nocache *
     * Expires: Thu, 19 Nov 1981 08:52:00 GMT
     * Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
     * Pragma: no-cache
     * 
    *
    * @return string|false the name of the current cache limiter. */ #[LanguageLevelTypeAware(["8.0" => "string|false"], default: "string")] function session_cache_limiter(#[LanguageLevelTypeAware(['8.0' => 'null|string'], default: 'string')] $value) {} /** * Return current cache expire * @link https://php.net/manual/en/function.session-cache-expire.php * @param int|null $value [optional]

    * If new_cache_expire is given, the current cache * expire is replaced with new_cache_expire. *

    *

    * Setting new_cache_expire is of value only, if * session.cache_limiter is set to a value * different from nocache. *

    * @return int|false the current setting of session.cache_expire. * The value returned should be read in minutes, defaults to 180. */ #[LanguageLevelTypeAware(["8.0" => "int|false"], default: "int")] function session_cache_expire(#[LanguageLevelTypeAware(['8.0' => 'null|int'], default: 'int')] $value) {} /** * Set the session cookie parameters * @link https://php.net/manual/en/function.session-set-cookie-params.php * @param array $lifetime_or_options

    * An associative array which may have any of the keys lifetime, path, domain, * secure, httponly and samesite. The values have the same meaning as described * for the parameters with the same name. The value of the samesite element * should be either Lax or Strict. If any of the allowed options are not given, * their default values are the same as the default values of the explicit * parameters. If the samesite element is omitted, no SameSite cookie attribute * is set. *

    * @return bool returns true on success or false on failure. * @since 7.3 */ function session_set_cookie_params(array $lifetime_or_options): bool {} /** * Set the session cookie parameters * @link https://php.net/manual/en/function.session-set-cookie-params.php * @param int $lifetime_or_options

    * Lifetime of the * session cookie, defined in seconds. *

    * @param string|null $path [optional]

    * Path on the domain where * the cookie will work. Use a single slash ('/') for all paths on the * domain. *

    * @param string|null $domain [optional]

    * Cookie domain, for * example 'www.php.net'. To make cookies visible on all subdomains then * the domain must be prefixed with a dot like '.php.net'. *

    * @param bool|null $secure [optional]

    * If true cookie will only be sent over * secure connections. *

    * @param bool|null $httponly [optional]

    * If set to true then PHP will attempt to send the * httponly * flag when setting the session cookie. *

    * @return void|bool since 7.2.0 returns true on success or false on failure. */ #[LanguageLevelTypeAware(["7.2" => "bool"], default: "void")] function session_set_cookie_params(int $lifetime_or_options, ?string $path = null, ?string $domain = null, ?bool $secure = null, ?bool $httponly = null) {} /** * Get the session cookie parameters * @link https://php.net/manual/en/function.session-get-cookie-params.php * @return array an array with the current session cookie information, the array * contains the following items: * "lifetime" - The * lifetime of the cookie in seconds. * "path" - The path where * information is stored. * "domain" - The domain * of the cookie. * "secure" - The cookie * should only be sent over secure connections. * "httponly" - The * cookie can only be accessed through the HTTP protocol. */ #[ArrayShape(["lifetime" => "int", "path" => "string", "domain" => "string", "secure" => "bool", "httponly" => "bool", "samesite" => "string"])] function session_get_cookie_params(): array {} /** * Write session data and end session * @link https://php.net/manual/en/function.session-write-close.php * @return void|bool since 7.2.0 returns true on success or false on failure. */ #[LanguageLevelTypeAware(["7.2" => "bool"], default: "void")] function session_write_close() {} /** * Alias of session_write_close * @link https://php.net/manual/en/function.session-commit.php * @return void|bool since 7.2.0 returns true on success or false on failure. */ #[LanguageLevelTypeAware(["7.2" => "bool"], default: "void")] function session_commit() {} /** * (PHP 5 >= 5.4.0)
    * Returns the current session status * @link https://php.net/manual/en/function.session-status.php * @return int PHP_SESSION_DISABLED if sessions are disabled. * PHP_SESSION_NONE if sessions are enabled, but none exists. * PHP_SESSION_ACTIVE if sessions are enabled, and one exists. * @since 5.4 */ function session_status(): int {} /** * (PHP 5 >= 5.6.0)
    * Discard session array changes and finish session * @link https://php.net/manual/en/function.session-abort.php * @return void|bool since 7.2.0 returns true if a session was successfully reinitialized or false on failure. * @since 5.6 */ #[LanguageLevelTypeAware(["7.2" => "bool"], default: "void")] function session_abort() {} /** * (PHP 5 >= 5.6.0)
    * Re-initialize session array with original values * @link https://php.net/manual/en/function.session-reset.php * @return void|bool since 7.2.0 returns true if a session was successfully reinitialized or false on failure. * @since 5.6 */ #[LanguageLevelTypeAware(["7.2" => "bool"], default: "void")] function session_reset() {} // End of session v. SessionHandlerInterface is an interface which defines * a prototype for creating a custom session handler. * In order to pass a custom session handler to * session_set_save_handler() using its OOP invocation, * the class must implement this interface. * @link https://php.net/manual/en/class.sessionhandlerinterface.php * @since 5.4 */ interface SessionHandlerInterface { /** * Close the session * @link https://php.net/manual/en/sessionhandlerinterface.close.php * @return bool

    * The return value (usually TRUE on success, FALSE on failure). * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function close(): bool; /** * Destroy a session * @link https://php.net/manual/en/sessionhandlerinterface.destroy.php * @param string $id The session ID being destroyed. * @return bool

    * The return value (usually TRUE on success, FALSE on failure). * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function destroy(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $id): bool; /** * Cleanup old sessions * @link https://php.net/manual/en/sessionhandlerinterface.gc.php * @param int $max_lifetime

    * Sessions that have not updated for * the last maxlifetime seconds will be removed. *

    * @return int|false

    * Returns the number of deleted sessions on success, or false on failure. Prior to PHP version 7.1, the function returned true on success. * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[LanguageLevelTypeAware(['7.1' => 'int|false'], default: 'bool')] #[TentativeType] public function gc(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $max_lifetime): int|false; /** * Initialize session * @link https://php.net/manual/en/sessionhandlerinterface.open.php * @param string $path The path where to store/retrieve the session. * @param string $name The session name. * @return bool

    * The return value (usually TRUE on success, FALSE on failure). * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function open( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $path, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name ): bool; /** * Read session data * @link https://php.net/manual/en/sessionhandlerinterface.read.php * @param string $id The session id to read data for. * @return string|false

    * Returns an encoded string of the read data. * If nothing was read, it must return false. * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function read(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $id): string|false; /** * Write session data * @link https://php.net/manual/en/sessionhandlerinterface.write.php * @param string $id The session id. * @param string $data

    * The encoded session data. This data is the * result of the PHP internally encoding * the $_SESSION superglobal to a serialized * string and passing it as this parameter. * Please note sessions use an alternative serialization method. *

    * @return bool

    * The return value (usually TRUE on success, FALSE on failure). * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function write( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $id, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data ): bool; } /** * SessionIdInterface * @link https://php.net/manual/en/class.sessionidinterface.php * @since 5.5.1 */ interface SessionIdInterface { /** * Create session ID * @link https://php.net/manual/en/sessionidinterface.create-sid.php * @return string

    * The new session ID. Note that this value is returned internally to PHP for processing. *

    */ #[TentativeType] public function create_sid(): string; } /** * SessionUpdateTimestampHandlerInterface is an interface which * defines a prototype for updating the life time of an existing session. * In order to use the lazy_write option must be enabled and a custom session * handler must implement this interface. * @since 7.0 */ interface SessionUpdateTimestampHandlerInterface { /** * Validate session id * @link https://www.php.net/manual/sessionupdatetimestamphandlerinterface.validateid * @param string $id The session id * @return bool

    * Note this value is returned internally to PHP for processing. *

    */ #[TentativeType] public function validateId($id): bool; /** * Update timestamp of a session * @link https://www.php.net/manual/sessionupdatetimestamphandlerinterface.updatetimestamp.php * @param string $id The session id * @param string $data

    * The encoded session data. This data is the * result of the PHP internally encoding * the $_SESSION superglobal to a serialized * string and passing it as this parameter. * Please note sessions use an alternative serialization method. *

    * @return bool */ #[TentativeType] public function updateTimestamp($id, $data): bool; } /** * SessionHandler a special class that can * be used to expose the current internal PHP session * save handler by inheritance. There are six methods * which wrap the six internal session save handler * callbacks (open, close, read, write, destroy and gc). * By default, this class will wrap whatever internal * save handler is set as as defined by the * session.save_handler configuration directive which is usually * files by default. Other internal session save handlers are provided by * PHP extensions such as SQLite (as sqlite), * Memcache (as memcache), and Memcached (as memcached). * @link https://php.net/manual/en/class.reflectionzendextension.php * @since 5.4 */ class SessionHandler implements SessionHandlerInterface, SessionIdInterface { /** * Close the session * @link https://php.net/manual/en/sessionhandler.close.php * @return bool

    * The return value (usually TRUE on success, FALSE on failure). * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function close(): bool {} /** * Return a new session ID * @link https://php.net/manual/en/sessionhandler.create-sid.php * @return string

    A session ID valid for the default session handler.

    * @since 5.5.1 */ #[TentativeType] public function create_sid(): string {} /** * Destroy a session * @link https://php.net/manual/en/sessionhandler.destroy.php * @param string $id The session ID being destroyed. * @return bool

    * The return value (usually TRUE on success, FALSE on failure). * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function destroy(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $id): bool {} /** * Cleanup old sessions * @link https://php.net/manual/en/sessionhandler.gc.php * @param int $max_lifetime

    * Sessions that have not updated for * the last maxlifetime seconds will be removed. *

    * @return int|bool

    * The return value (usually TRUE on success, FALSE on failure). * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function gc(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $max_lifetime): int|false {} /** * Initialize session * @link https://php.net/manual/en/sessionhandler.open.php * @param string $path The path where to store/retrieve the session. * @param string $name The session name. * @return bool

    * The return value (usually TRUE on success, FALSE on failure). * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function open( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $path, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name ): bool {} /** * Read session data * @link https://php.net/manual/en/sessionhandler.read.php * @param string $id The session id to read data for. * @return string|false

    * Returns an encoded string of the read data. * If nothing was read, it must return an empty string. * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function read(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $id): string|false {} /** * Write session data * @link https://php.net/manual/en/sessionhandler.write.php * @param string $id The session id. * @param string $data

    * The encoded session data. This data is the * result of the PHP internally encoding * the $_SESSION superglobal to a serialized * string and passing it as this parameter. * Please note sessions use an alternative serialization method. *

    * @return bool

    * The return value (usually TRUE on success, FALSE on failure). * Note this value is returned internally to PHP for processing. *

    * @since 5.4 */ #[TentativeType] public function write( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $id, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data ): bool {} } * * Elements of array returned by gd_info * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    AttributeMeaning
    GD Versionstring value describing the installed * libgd version.
    FreeType Supportboolean value. TRUE * if FreeType Support is installed.
    FreeType Linkagestring value describing the way in which * FreeType was linked. Expected values are: 'with freetype', * 'with TTF library', and 'with unknown library'. This element will * only be defined if FreeType Support evaluated to * TRUE.
    T1Lib Supportboolean value. TRUE * if T1Lib support is included.
    GIF Read Supportboolean value. TRUE * if support for reading GIF * images is included.
    GIF Create Supportboolean value. TRUE * if support for creating GIF * images is included.
    JPEG Supportboolean value. TRUE * if JPEG support is included.
    PNG Supportboolean value. TRUE * if PNG support is included.
    WBMP Supportboolean value. TRUE * if WBMP support is included.
    XBM Supportboolean value. TRUE * if XBM support is included.
    WebP Supportboolean value. TRUE * if WebP support is included.
    *

    *

    * Previous to PHP 5.3.0, the JPEG Support attribute was named * JPG Support. *

    */ #[Pure] #[ArrayShape([ "GD Version" => "string", "FreeType Support" => "bool", "GIF Read Support" => "bool", "GIF Create Support" => "bool", "JPEG Support" => "bool", "PNG Support" => "bool", "WBMP Support" => "bool", "XPM Support" => "bool", "XBM Support" => "bool", "WebP Support" => "bool", "BMP Support" => "bool", "TGA Read Support" => "bool", "AVIF Support" => "bool", "JIS-mapped Japanese Font Support" => "bool" ])] function gd_info(): array {} /** * Draws an arc * @link https://php.net/manual/en/function.imagearc.php * @param resource|GdImage $image * @param int $center_x

    * x-coordinate of the center. *

    * @param int $center_y

    * y-coordinate of the center. *

    * @param int $width

    * The arc width. *

    * @param int $height

    * The arc height. *

    * @param int $start_angle

    * The arc start angle, in degrees. *

    * @param int $end_angle

    * The arc end angle, in degrees. * 0° is located at the three-o'clock position, and the arc is drawn * clockwise. *

    * @param int $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool TRUE on success or FALSE on failure. */ function imagearc(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $start_angle, int $end_angle, int $color): bool {} /** * Draw an ellipse * @link https://php.net/manual/en/function.imageellipse.php * @param resource|GdImage $image * @param int $center_x

    * x-coordinate of the center. *

    * @param int $center_y

    * y-coordinate of the center. *

    * @param int $width

    * The ellipse width. *

    * @param int $height

    * The ellipse height. *

    * @param int $color

    * The color of the ellipse. A color identifier created with * imagecolorallocate. *

    * @return bool TRUE on success or FALSE on failure. */ function imageellipse(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $color): bool {} /** * Draw a character horizontally * @link https://php.net/manual/en/function.imagechar.php * @param resource|GdImage $image * @param int $font * @param int $x

    * x-coordinate of the start. *

    * @param int $y

    * y-coordinate of the start. *

    * @param string $char

    * The character to draw. *

    * @param int $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool TRUE on success or FALSE on failure. */ function imagechar( GdImage $image, #[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font, int $x, int $y, string $char, int $color ): bool {} /** * Draw a character vertically * @link https://php.net/manual/en/function.imagecharup.php * @param resource|GdImage $image * @param int $font * @param int $x

    * x-coordinate of the start. *

    * @param int $y

    * y-coordinate of the start. *

    * @param string $char

    * The character to draw. *

    * @param int $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool TRUE on success or FALSE on failure. */ function imagecharup( GdImage $image, #[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font, int $x, int $y, string $char, int $color ): bool {} /** * Get the index of the color of a pixel * @link https://php.net/manual/en/function.imagecolorat.php * @param resource|GdImage $image * @param int $x

    * x-coordinate of the point. *

    * @param int $y

    * y-coordinate of the point. *

    * @return int|false the index of the color or FALSE on failure */ #[Pure] function imagecolorat(GdImage $image, int $x, int $y): int|false {} /** * Allocate a color for an image * @link https://php.net/manual/en/function.imagecolorallocate.php * @param resource|GdImage $image * @param int $red

    Value of red component.

    * @param int $green

    Value of green component.

    * @param int $blue

    Value of blue component.

    * @return int|false A color identifier or FALSE if the allocation failed. */ function imagecolorallocate(GdImage $image, int $red, int $green, int $blue): int|false {} /** * Copy the palette from one image to another * @link https://php.net/manual/en/function.imagepalettecopy.php * @param resource|GdImage $dst

    * The destination image resource. *

    * @param resource|GdImage $src

    * The source image resource. *

    * @return void No value is returned. */ function imagepalettecopy(GdImage $dst, GdImage $src): void {} /** * Create a new image from the image stream in the string * @link https://php.net/manual/en/function.imagecreatefromstring.php * @param string $data

    * A string containing the image data. *

    * @return resource|GdImage|false An image resource will be returned on success. FALSE is returned if * the image type is unsupported, the data is not in a recognised format, * or the image is corrupt and cannot be loaded. */ #[Pure] function imagecreatefromstring(string $data): GdImage|false {} /** * Get the index of the closest color to the specified color * @link https://php.net/manual/en/function.imagecolorclosest.php * @param resource|GdImage $image * @param int $red

    Value of red component.

    * @param int $green

    Value of green component.

    * @param int $blue

    Value of blue component.

    * @return int|false the index of the closest color, in the palette of the image, to * the specified one or FALSE on failure */ #[Pure] function imagecolorclosest(GdImage $image, int $red, int $green, int $blue): int {} /** * Get the index of the color which has the hue, white and blackness * @link https://php.net/manual/en/function.imagecolorclosesthwb.php * @param resource|GdImage $image * @param int $red

    Value of red component.

    * @param int $green

    Value of green component.

    * @param int $blue

    Value of blue component.

    * @return int|false an integer with the index of the color which has * the hue, white and blackness nearest the given color or FALSE on failure */ #[Pure] function imagecolorclosesthwb(GdImage $image, int $red, int $green, int $blue): int {} /** * De-allocate a color for an image * @link https://php.net/manual/en/function.imagecolordeallocate.php * @param resource|GdImage $image * @param int $color

    * The color identifier. *

    * @return bool TRUE on success or FALSE on failure. */ function imagecolordeallocate(GdImage $image, int $color): bool {} /** * Get the index of the specified color or its closest possible alternative * @link https://php.net/manual/en/function.imagecolorresolve.php * @param resource|GdImage $image * @param int $red

    Value of red component.

    * @param int $green

    Value of green component.

    * @param int $blue

    Value of blue component.

    * @return int|false a color index or FALSE on failure */ #[Pure] function imagecolorresolve(GdImage $image, int $red, int $green, int $blue): int {} /** * Get the index of the specified color * @link https://php.net/manual/en/function.imagecolorexact.php * @param resource|GdImage $image * @param int $red

    Value of red component.

    * @param int $green

    Value of green component.

    * @param int $blue

    Value of blue component.

    * @return int|false the index of the specified color in the palette, -1 if the * color does not exist, or FALSE on failure */ #[Pure] function imagecolorexact(GdImage $image, int $red, int $green, int $blue): int {} /** * Set the color for the specified palette index * @link https://php.net/manual/en/function.imagecolorset.php * @param resource|GdImage $image * @param int $color

    * An index in the palette. *

    * @param int $red

    Value of red component.

    * @param int $green

    Value of green component.

    * @param int $blue

    Value of blue component.

    * @param int $alpha [optional]

    * Value of alpha component. *

    * @return bool|null */ #[LanguageLevelTypeAware(['8.2' => 'null|false'], default: 'null|bool')] function imagecolorset(GdImage $image, int $color, int $red, int $green, int $blue, int $alpha = 0): ?bool {} /** * Define a color as transparent * @link https://php.net/manual/en/function.imagecolortransparent.php * @param resource|GdImage $image * @param int $color [optional]

    * A color identifier created with * imagecolorallocate. *

    * @return int The identifier of the new (or current, if none is specified) * transparent color is returned. If color * is not specified, and the image has no transparent color, the * returned identifier will be -1. */ function imagecolortransparent(GdImage $image, ?int $color = null): int {} /** * Find out the number of colors in an image's palette * @link https://php.net/manual/en/function.imagecolorstotal.php * @param resource|GdImage $image

    * An image resource, returned by one of the image creation functions, such * as imagecreatefromgif. *

    * @return int|false the number of colors in the specified image's palette, 0 for * truecolor images, or FALSE on failure */ #[Pure] function imagecolorstotal(GdImage $image): int {} /** * Get the colors for an index * @link https://php.net/manual/en/function.imagecolorsforindex.php * @param resource|GdImage $image * @param int $color

    * The color index. *

    * @return array|false an associative array with red, green, blue and alpha keys that * contain the appropriate values for the specified color index or FALSE on failure */ #[Pure] #[LanguageLevelTypeAware(['8.0' => 'array'], default: 'array|false')] #[ArrayShape(["red" => "int", "green" => "int", "blue" => "int", "alpha" => "int"])] function imagecolorsforindex(GdImage $image, int $color) {} /** * Copy part of an image * @link https://php.net/manual/en/function.imagecopy.php * @param resource|GdImage $dst_image

    * Destination image link resource. *

    * @param resource|GdImage $src_image

    * Source image link resource. *

    * @param int $dst_x

    * x-coordinate of destination point. *

    * @param int $dst_y

    * y-coordinate of destination point. *

    * @param int $src_x

    * x-coordinate of source point. *

    * @param int $src_y

    * y-coordinate of source point. *

    * @param int $src_width

    * Source width. *

    * @param int $src_height

    * Source height. *

    * @return bool true on success or false on failure. */ function imagecopy(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height): bool {} /** * Copy and merge part of an image * @link https://php.net/manual/en/function.imagecopymerge.php * @param resource|GdImage $dst_image

    * Destination image link resource. *

    * @param resource|GdImage $src_image

    * Source image link resource. *

    * @param int $dst_x

    * x-coordinate of destination point. *

    * @param int $dst_y

    * y-coordinate of destination point. *

    * @param int $src_x

    * x-coordinate of source point. *

    * @param int $src_y

    * y-coordinate of source point. *

    * @param int $src_width

    * Source width. *

    * @param int $src_height

    * Source height. *

    * @param int $pct

    * The two images will be merged according to pct * which can range from 0 to 100. When pct = 0, * no action is taken, when 100 this function behaves identically * to imagecopy for pallete images, while it * implements alpha transparency for true colour images. *

    * @return bool true on success or false on failure. */ function imagecopymerge(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height, int $pct): bool {} /** * Copy and merge part of an image with gray scale * @link https://php.net/manual/en/function.imagecopymergegray.php * @param resource|GdImage $dst_image

    * Destination image link resource. *

    * @param resource|GdImage $src_image

    * Source image link resource. *

    * @param int $dst_x

    * x-coordinate of destination point. *

    * @param int $dst_y

    * y-coordinate of destination point. *

    * @param int $src_x

    * x-coordinate of source point. *

    * @param int $src_y

    * y-coordinate of source point. *

    * @param int $src_width

    * Source width. *

    * @param int $src_height

    * Source height. *

    * @param int $pct

    * The src_im will be changed to grayscale according * to pct where 0 is fully grayscale and 100 is * unchanged. When pct = 100 this function behaves * identically to imagecopy for pallete images, while * it implements alpha transparency for true colour images. *

    * @return bool true on success or false on failure. */ function imagecopymergegray(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height, int $pct): bool {} /** * Copy and resize part of an image * @link https://php.net/manual/en/function.imagecopyresized.php * @param resource|GdImage $dst_image * @param resource|GdImage $src_image * @param int $dst_x

    * x-coordinate of destination point. *

    * @param int $dst_y

    * y-coordinate of destination point. *

    * @param int $src_x

    * x-coordinate of source point. *

    * @param int $src_y

    * y-coordinate of source point. *

    * @param int $dst_width

    * Destination width. *

    * @param int $dst_height

    * Destination height. *

    * @param int $src_width

    * Source width. *

    * @param int $src_height

    * Source height. *

    * @return bool true on success or false on failure. */ function imagecopyresized(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $dst_width, int $dst_height, int $src_width, int $src_height): bool {} /** * Create a new palette based image * @link https://php.net/manual/en/function.imagecreate.php * @param int $width

    * The image width. *

    * @param int $height

    * The image height. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ #[Pure] function imagecreate(int $width, int $height): GdImage|false {} /** * Create a new true color image * @link https://php.net/manual/en/function.imagecreatetruecolor.php * @param int $width

    * Image width. *

    * @param int $height

    * Image height. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ #[Pure] function imagecreatetruecolor(int $width, int $height): GdImage|false {} /** * Finds whether an image is a truecolor image * @link https://php.net/manual/en/function.imageistruecolor.php * @param resource|GdImage $image * @return bool true if the image is truecolor, false * otherwise. */ #[Pure] function imageistruecolor(GdImage $image): bool {} /** * Convert a true color image to a palette image * @link https://php.net/manual/en/function.imagetruecolortopalette.php * @param resource|GdImage $image * @param bool $dither

    * Indicates if the image should be dithered - if it is true then * dithering will be used which will result in a more speckled image but * with better color approximation. *

    * @param int $num_colors

    * Sets the maximum number of colors that should be retained in the palette. *

    * @return bool true on success or false on failure. */ function imagetruecolortopalette(GdImage $image, bool $dither, int $num_colors): bool {} /** * Set the thickness for line drawing * @link https://php.net/manual/en/function.imagesetthickness.php * @param resource|GdImage $image * @param int $thickness

    * Thickness, in pixels. *

    * @return bool true on success or false on failure. */ function imagesetthickness(GdImage $image, int $thickness): bool {} /** * Draw a partial arc and fill it * @link https://php.net/manual/en/function.imagefilledarc.php * @param resource|GdImage $image * @param int $center_x

    * x-coordinate of the center. *

    * @param int $center_y

    * y-coordinate of the center. *

    * @param int $width

    * The arc width. *

    * @param int $height

    * The arc height. *

    * @param int $start_angle

    * The arc start angle, in degrees. *

    * @param int $end_angle

    * The arc end angle, in degrees. * 0° is located at the three-o'clock position, and the arc is drawn * clockwise. *

    * @param int $color

    * A color identifier created with * imagecolorallocate. *

    * @param int $style

    * A bitwise OR of the following possibilities: * IMG_ARC_PIE

    * @return bool true on success or false on failure. */ function imagefilledarc(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $start_angle, int $end_angle, int $color, int $style): bool {} /** * Draw a filled ellipse * @link https://php.net/manual/en/function.imagefilledellipse.php * @param resource|GdImage $image * @param int $center_x

    * x-coordinate of the center. *

    * @param int $center_y

    * y-coordinate of the center. *

    * @param int $width

    * The ellipse width. *

    * @param int $height

    * The ellipse height. *

    * @param int $color

    * The fill color. A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagefilledellipse(GdImage $image, int $center_x, int $center_y, int $width, int $height, int $color): bool {} /** * Set the blending mode for an image * @link https://php.net/manual/en/function.imagealphablending.php * @param resource|GdImage $image * @param bool $enable

    * Whether to enable the blending mode or not. On true color images * the default value is true otherwise the default value is false *

    * @return bool true on success or false on failure. */ function imagealphablending(GdImage $image, bool $enable): bool {} /** * Set the flag to save full alpha channel information (as opposed to single-color transparency) when saving PNG images * @link https://php.net/manual/en/function.imagesavealpha.php * @param resource|GdImage $image * @param bool $enable

    * Whether to save the alpha channel or not. Default to false. *

    * @return bool true on success or false on failure. */ function imagesavealpha(GdImage $image, bool $enable): bool {} /** * Allocate a color for an image * @link https://php.net/manual/en/function.imagecolorallocatealpha.php * @param resource|GdImage $image * @param int $red

    * Value of red component. *

    * @param int $green

    * Value of green component. *

    * @param int $blue

    * Value of blue component. *

    * @param int $alpha

    * A value between 0 and 127. * 0 indicates completely opaque while * 127 indicates completely transparent. *

    * @return int|false A color identifier or false if the allocation failed. */ function imagecolorallocatealpha(GdImage $image, int $red, int $green, int $blue, int $alpha): int|false {} /** * Get the index of the specified color + alpha or its closest possible alternative * @link https://php.net/manual/en/function.imagecolorresolvealpha.php * @param resource|GdImage $image * @param int $red

    * Value of red component. *

    * @param int $green

    * Value of green component. *

    * @param int $blue

    * Value of blue component. *

    * @param int $alpha

    * A value between 0 and 127. * 0 indicates completely opaque while * 127 indicates completely transparent. *

    * @return int|false a color index or FALSE on failure */ #[Pure] function imagecolorresolvealpha(GdImage $image, int $red, int $green, int $blue, int $alpha): int {} /** * Get the index of the closest color to the specified color + alpha * @link https://php.net/manual/en/function.imagecolorclosestalpha.php * @param resource|GdImage $image * @param int $red

    * Value of red component. *

    * @param int $green

    * Value of green component. *

    * @param int $blue

    * Value of blue component. *

    * @param int $alpha

    * A value between 0 and 127. * 0 indicates completely opaque while * 127 indicates completely transparent. *

    * @return int|false the index of the closest color in the palette or * FALSE on failure */ #[Pure] function imagecolorclosestalpha(GdImage $image, int $red, int $green, int $blue, int $alpha): int {} /** * Get the index of the specified color + alpha * @link https://php.net/manual/en/function.imagecolorexactalpha.php * @param resource|GdImage $image * @param int $red

    * Value of red component. *

    * @param int $green

    * Value of green component. *

    * @param int $blue

    * Value of blue component. *

    * @param int $alpha

    * A value between 0 and 127. * 0 indicates completely opaque while * 127 indicates completely transparent. *

    * @return int|false the index of the specified color+alpha in the palette of the * image, -1 if the color does not exist in the image's palette, or FALSE * on failure */ #[Pure] #[LanguageLevelTypeAware(['8.0' => 'int'], default: 'int|false')] function imagecolorexactalpha(GdImage $image, int $red, int $green, int $blue, int $alpha) {} /** * Copy and resize part of an image with resampling * @link https://php.net/manual/en/function.imagecopyresampled.php * @param resource|GdImage $dst_image * @param resource|GdImage $src_image * @param int $dst_x

    * x-coordinate of destination point. *

    * @param int $dst_y

    * y-coordinate of destination point. *

    * @param int $src_x

    * x-coordinate of source point. *

    * @param int $src_y

    * y-coordinate of source point. *

    * @param int $dst_width

    * Destination width. *

    * @param int $dst_height

    * Destination height. *

    * @param int $src_width

    * Source width. *

    * @param int $src_height

    * Source height. *

    * @return bool true on success or false on failure. */ function imagecopyresampled(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $dst_width, int $dst_height, int $src_width, int $src_height): bool {} /** * Rotate an image with a given angle * @link https://php.net/manual/en/function.imagerotate.php * @param resource|GdImage $image * @param float $angle

    * Rotation angle, in degrees. *

    * @param int $background_color

    * Specifies the color of the uncovered zone after the rotation *

    * @param bool $ignore_transparent [optional]

    * Prior to PHP 8.3 if set and non-zero, transparent colors are ignored (otherwise kept). *

    * @return resource|GdImage|false the rotated image or FALSE on failure */ function imagerotate( GdImage $image, float $angle, int $background_color, #[PhpStormStubsElementAvailable(to: '8.2')] bool $ignore_transparent = false ): GdImage|false {} /** * Should antialias functions be used or not.
    * Before 7.2.0 it's only available if PHP iscompiled with the bundled version of the GD library. * @link https://php.net/manual/en/function.imageantialias.php * @param resource|GdImage $image * @param bool $enable

    * Whether to enable antialiasing or not. *

    * @return bool true on success or false on failure. */ function imageantialias(GdImage $image, bool $enable): bool {} /** * Set the tile image for filling * @link https://php.net/manual/en/function.imagesettile.php * @param resource|GdImage $image * @param resource|GdImage $tile

    * The image resource to be used as a tile. *

    * @return bool true on success or false on failure. */ function imagesettile(GdImage $image, GdImage $tile): bool {} /** * Set the brush image for line drawing * @link https://php.net/manual/en/function.imagesetbrush.php * @param resource|GdImage $image * @param resource|GdImage $brush

    * An image resource. *

    * @return bool true on success or false on failure. */ function imagesetbrush(GdImage $image, GdImage $brush): bool {} /** * Set the style for line drawing * @link https://php.net/manual/en/function.imagesetstyle.php * @param resource|GdImage $image * @param int[] $style

    * An array of pixel colors. You can use the * IMG_COLOR_TRANSPARENT constant to add a * transparent pixel. *

    * @return bool true on success or false on failure. */ function imagesetstyle(GdImage $image, array $style): bool {} /** * Create a new image from file or URL * @link https://php.net/manual/en/function.imagecreatefrompng.php * @param string $filename

    * Path to the PNG image. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ function imagecreatefrompng(string $filename): GdImage|false {} /** * Create a new image from file or URL * @link https://www.php.net/manual/function.imagecreatefromavif.php * @param string $filename Path to the AVIF raster image. * @return GdImage|false returns an image object representing the image obtained from the given filename * @since 8.1 */ function imagecreatefromavif(string $filename): GdImage|false {} /** * Create a new image from file or URL * @link https://php.net/manual/en/function.imagecreatefromgif.php * @param string $filename

    * Path to the GIF image. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ function imagecreatefromgif(string $filename): GdImage|false {} /** * Create a new image from file or URL * @link https://php.net/manual/en/function.imagecreatefromjpeg.php * @param string $filename

    * Path to the JPEG image. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ function imagecreatefromjpeg(string $filename): GdImage|false {} /** * Create a new image from file or URL * @link https://php.net/manual/en/function.imagecreatefromwbmp.php * @param string $filename

    * Path to the WBMP image. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ function imagecreatefromwbmp(string $filename): GdImage|false {} /** * Create a new image from file or URL * @link https://php.net/manual/en/function.imagecreatefromwebp.php * @param string $filename

    * Path to the WebP image. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. * @since 5.4 */ function imagecreatefromwebp(string $filename): GdImage|false {} /** * Create a new image from file or URL * @link https://php.net/manual/en/function.imagecreatefromxbm.php * @param string $filename

    * Path to the XBM image. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ function imagecreatefromxbm(string $filename): GdImage|false {} /** * Create a new image from file or URL * @link https://php.net/manual/en/function.imagecreatefromxpm.php * @param string $filename

    * Path to the XPM image. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ function imagecreatefromxpm(string $filename): GdImage|false {} /** * Create a new image from GD file or URL * @link https://php.net/manual/en/function.imagecreatefromgd.php * @param string $filename

    * Path to the GD file. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ function imagecreatefromgd(string $filename): GdImage|false {} /** * Create a new image from GD2 file or URL * @link https://php.net/manual/en/function.imagecreatefromgd2.php * @param string $filename

    * Path to the GD2 image. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ function imagecreatefromgd2(string $filename): GdImage|false {} /** * Create a new image from a given part of GD2 file or URL * @link https://php.net/manual/en/function.imagecreatefromgd2part.php * @param string $filename

    * Path to the GD2 image. *

    * @param int $x

    * x-coordinate of source point. *

    * @param int $y

    * y-coordinate of source point. *

    * @param int $width

    * Source width. *

    * @param int $height

    * Source height. *

    * @return resource|GdImage|false an image resource identifier on success, false on errors. */ function imagecreatefromgd2part(string $filename, int $x, int $y, int $width, int $height): GdImage|false {} /** * Output a PNG image to either the browser or a file * @link https://php.net/manual/en/function.imagepng.php * @param resource|GdImage $image * @param string $file [optional]

    * The path to save the file to. If not set or null, the raw image stream * will be outputted directly. *

    *

    * null is invalid if the quality and * filters arguments are not used. *

    * @param int $quality [optional]

    * Compression level: from 0 (no compression) to 9. *

    * @param int $filters [optional]

    * Allows reducing the PNG file size. It is a bitmask field which may be * set to any combination of the PNG_FILTER_XXX * constants. PNG_NO_FILTER or * PNG_ALL_FILTERS may also be used to respectively * disable or activate all filters. *

    * @return bool true on success or false on failure. */ function imagepng(GdImage $image, $file = null, int $quality = -1, int $filters = -1): bool {} /** * Output a WebP image to browser or file * @link https://php.net/manual/en/function.imagewebp.php * @param resource|GdImage $image * @param resource|string|null $file [optional]

    * The path or an open stream resource (which is automatically closed after this function returns) * to save the file to. If not set or null, the raw image stream will be output directly. *

    * @param int $quality [optional]

    * quality ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file). *

    * @return bool true on success or false on failure. * @since 5.4 */ function imagewebp(GdImage $image, $file = null, int $quality = -1): bool {} /** * Output image to browser or file * @link https://php.net/manual/en/function.imagegif.php * @param resource|GdImage $image * @param string $file [optional]

    * The path to save the file to. If not set or null, the raw image stream * will be outputted directly. *

    * @return bool true on success or false on failure. */ function imagegif(GdImage $image, $file = null): bool {} /** * Output image to browser or file * @link https://php.net/manual/en/function.imagejpeg.php * @param resource|GdImage $image * @param string $file [optional]

    * The path to save the file to. If not set or null, the raw image stream * will be outputted directly. *

    *

    * To skip this argument in order to provide the * quality parameter, use null. *

    * @param int $quality [optional]

    * quality is optional, and ranges from 0 (worst * quality, smaller file) to 100 (best quality, biggest file). The * default is the default IJG quality value (about 75). *

    * @return bool true on success or false on failure. */ function imagejpeg(GdImage $image, $file = null, int $quality = -1): bool {} /** * Output image to browser or file * @link https://php.net/manual/en/function.imagewbmp.php * @param resource|GdImage $image * @param string $file [optional]

    * The path to save the file to. If not set or null, the raw image stream * will be outputted directly. *

    * @param int $foreground_color [optional]

    * You can set the foreground color with this parameter by setting an * identifier obtained from imagecolorallocate. * The default foreground color is black. *

    * @return bool true on success or false on failure. */ function imagewbmp(GdImage $image, $file = null, ?int $foreground_color = null): bool {} /** * Output GD image to browser or file.
    * Since 7.2.0 allows to output truecolor images. * @link https://php.net/manual/en/function.imagegd.php * @param resource|GdImage $image * @param string|null $file [optional]

    * The path to save the file to. If not set or null, the raw image stream * will be outputted directly. *

    * @return bool true on success or false on failure. */ function imagegd(GdImage $image, ?string $file = null): bool {} /** * Output GD2 image to browser or file * @link https://php.net/manual/en/function.imagegd2.php * @param resource|GdImage $image * @param string|null $file [optional]

    * The path to save the file to. If not set or null, the raw image stream * will be outputted directly. *

    * @param int $chunk_size [optional]

    * Chunk size. *

    * @param int $mode [optional]

    * Either IMG_GD2_RAW or * IMG_GD2_COMPRESSED. Default is * IMG_GD2_RAW. *

    * @return bool true on success or false on failure. */ function imagegd2(GdImage $image, ?string $file = null, int $chunk_size = 128, int $mode = IMG_GD2_RAW): bool {} /** * Destroy an image * @link https://php.net/manual/en/function.imagedestroy.php * @param resource|GdImage $image * @return bool true on success or false on failure. */ function imagedestroy(GdImage $image): bool {} /** * Apply a gamma correction to a GD image * @link https://php.net/manual/en/function.imagegammacorrect.php * @param resource|GdImage $image * @param float $input_gamma

    * The input gamma. *

    * @param float $output_gamma

    * The output gamma. *

    * @return bool true on success or false on failure. */ function imagegammacorrect(GdImage $image, float $input_gamma, float $output_gamma): bool {} /** * Flood fill * @link https://php.net/manual/en/function.imagefill.php * @param resource|GdImage $image * @param int $x

    * x-coordinate of start point. *

    * @param int $y

    * y-coordinate of start point. *

    * @param int $color

    * The fill color. A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagefill(GdImage $image, int $x, int $y, int $color): bool {} /** * Draw a filled polygon * @link https://php.net/manual/en/function.imagefilledpolygon.php * @param resource|GdImage $image * @param int[] $points

    * An array containing the x and y * coordinates of the polygons vertices consecutively. *

    * @param int $num_points_or_color

    * Total number of vertices, which must be at least 3. *

    * @param int|null $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagefilledpolygon( GdImage $image, array $points, #[Deprecated(since: "8.1")] int $num_points_or_color, ?int $color ): bool {} /** * Draw a filled polygon * @link https://php.net/manual/en/function.imagefilledpolygon.php * @param GdImage $image * @param int[] $points

    * An array containing the x and y * coordinates of the polygons vertices consecutively. *

    * @param int|null $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ #[PhpStormStubsElementAvailable(from: '8.0')] function imagefilledpolygon( GdImage $image, array $points, ?int $color ): bool {} /** * Draw a filled rectangle * @link https://php.net/manual/en/function.imagefilledrectangle.php * @param resource|GdImage $image * @param int $x1

    * x-coordinate for point 1. *

    * @param int $y1

    * y-coordinate for point 1. *

    * @param int $x2

    * x-coordinate for point 2. *

    * @param int $y2

    * y-coordinate for point 2. *

    * @param int $color

    * The fill color. A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagefilledrectangle(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): bool {} /** * Flood fill to specific color * @link https://php.net/manual/en/function.imagefilltoborder.php * @param resource|GdImage $image * @param int $x

    * x-coordinate of start. *

    * @param int $y

    * y-coordinate of start. *

    * @param int $border_color

    * The border color. A color identifier created with * imagecolorallocate. *

    * @param int $color

    * The fill color. A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagefilltoborder(GdImage $image, int $x, int $y, int $border_color, int $color): bool {} /** * Get font width * @link https://php.net/manual/en/function.imagefontwidth.php * @param int $font * @return int the width of the pixel */ #[Pure] function imagefontwidth(#[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font): int {} /** * Get font height * @link https://php.net/manual/en/function.imagefontheight.php * @param int $font * @return int the height of the pixel. */ #[Pure] function imagefontheight(#[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font): int {} /** * Enable or disable interlace * @link https://php.net/manual/en/function.imageinterlace.php * @param resource|GdImage $image * @param bool|null $enable [optional]

    * If non-zero, the image will be interlaced, else the interlace bit is * turned off. *

    * @return bool 1 if the interlace bit is set for the image, * 0 if it is not */ function imageinterlace(GdImage $image, ?bool $enable = null): bool {} /** * Draw a line * @link https://php.net/manual/en/function.imageline.php * @param resource|GdImage $image * @param int $x1

    * x-coordinate for first point. *

    * @param int $y1

    * y-coordinate for first point. *

    * @param int $x2

    * x-coordinate for second point. *

    * @param int $y2

    * y-coordinate for second point. *

    * @param int $color

    * The line color. A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imageline(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): bool {} /** * Load a new font * @link https://php.net/manual/en/function.imageloadfont.php * @param string $filename

    * The font file format is currently binary and architecture * dependent. This means you should generate the font files on the * same type of CPU as the machine you are running PHP on. *

    *

    *

    * Font file format * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    byte positionC data typedescription
    byte 0-3intnumber of characters in the font
    byte 4-7int * value of first character in the font (often 32 for space) *
    byte 8-11intpixel width of each character
    byte 12-15intpixel height of each character
    byte 16-char * array with character data, one byte per pixel in each * character, for a total of (nchars*width*height) bytes. *
    *

    * @return int|false The font identifier which is always bigger than 5 to avoid conflicts with * built-in fonts or false on errors. */ #[LanguageLevelTypeAware(['8.1' => 'GdFont|false'], default: 'int|false')] function imageloadfont(string $filename) {} /** * Draws a polygon * @link https://php.net/manual/en/function.imagepolygon.php * @param resource|GdImage $image * @param int[] $points

    * An array containing the polygon's vertices, e.g.: * * points[0] * = x0 * * * points[1] * = y0 * * * points[2] * = x1 * * * points[3] * = y1 * *

    * @param int $num_points_or_color

    * Total number of points (vertices). *

    * @param int|null $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagepolygon( GdImage $image, array $points, int $num_points_or_color, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] ?int $color, #[PhpStormStubsElementAvailable(from: '8.0')] ?int $color = null ): bool {} /** * Draw a rectangle * @link https://php.net/manual/en/function.imagerectangle.php * @param resource|GdImage $image * @param int $x1

    * Upper left x coordinate. *

    * @param int $y1

    * Upper left y coordinate * 0, 0 is the top left corner of the image. *

    * @param int $x2

    * Bottom right x coordinate. *

    * @param int $y2

    * Bottom right y coordinate. *

    * @param int $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagerectangle(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): bool {} /** * Set a single pixel * @link https://php.net/manual/en/function.imagesetpixel.php * @param resource|GdImage $image * @param int $x

    * x-coordinate. *

    * @param int $y

    * y-coordinate. *

    * @param int $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagesetpixel(GdImage $image, int $x, int $y, int $color): bool {} /** * Draw a string horizontally * @link https://php.net/manual/en/function.imagestring.php * @param resource|GdImage $image * @param int $font

    * Can be 1, 2, 3, 4, 5 for built-in fonts in latin2 encoding (where higher numbers corresponding to larger fonts) or (since 8.1) GdFont instance *

    * @param int $x

    * x-coordinate of the upper left corner. *

    * @param int $y

    * y-coordinate of the upper left corner. *

    * @param string $string

    * The string to be written. *

    * @param int $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagestring( GdImage $image, #[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font, int $x, int $y, string $string, int $color ): bool {} /** * Draw a string vertically * @link https://php.net/manual/en/function.imagestringup.php * @param resource|GdImage $image * @param int $font * @param int $x

    * x-coordinate of the upper left corner. *

    * @param int $y

    * y-coordinate of the upper left corner. *

    * @param string $string

    * The string to be written. *

    * @param int $color

    * A color identifier created with * imagecolorallocate. *

    * @return bool true on success or false on failure. */ function imagestringup( GdImage $image, #[LanguageLevelTypeAware(['8.1' => 'GdFont|int'], default: 'int')] $font, int $x, int $y, string $string, int $color ): bool {} /** * Get image width * @link https://php.net/manual/en/function.imagesx.php * @param resource|GdImage $image * @return int|false Return the width of the image or false on * errors. */ #[Pure] function imagesx(GdImage $image): int {} /** * Get image height * @link https://php.net/manual/en/function.imagesy.php * @param resource|GdImage $image * @return int|false Return the height of the image or false on * errors. */ #[Pure] function imagesy(GdImage $image): int {} /** * Draw a dashed line * @link https://php.net/manual/en/function.imagedashedline.php * @param resource|GdImage $image * @param int $x1

    * Upper left x coordinate. *

    * @param int $y1

    * Upper left y coordinate 0, 0 is the top left corner of the image. *

    * @param int $x2

    * Bottom right x coordinate. *

    * @param int $y2

    * Bottom right y coordinate. *

    * @param int $color

    * The fill color. A color identifier created with * imagecolorallocate. *

    * @return bool TRUE on success or FALSE on failure. */ function imagedashedline(GdImage $image, int $x1, int $y1, int $x2, int $y2, int $color): bool {} /** * Give the bounding box of a text using TrueType fonts * @link https://php.net/manual/en/function.imagettfbbox.php * @param float $size

    * The font size. Depending on your version of GD, this should be * specified as the pixel size (GD1) or point size (GD2). *

    * @param float $angle

    * Angle in degrees in which text will be measured. *

    * @param string $font_filename

    * The name of the TrueType font file (can be a URL). Depending on * which version of the GD library that PHP is using, it may attempt to * search for files that do not begin with a leading '/' by appending * '.ttf' to the filename and searching along a library-defined font path. *

    * @param string $string

    * The string to be measured. *

    * @param array $options [optional] * @return array|false imagettfbbox returns an array with 8 * elements representing four points making the bounding box of the * text on success and false on error. * * key * contents * * * 0 * lower left corner, X position * * * 1 * lower left corner, Y position * * * 2 * lower right corner, X position * * * 3 * lower right corner, Y position * * * 4 * upper right corner, X position * * * 5 * upper right corner, Y position * * * 6 * upper left corner, X position * * * 7 * upper left corner, Y position * *

    *

    * The points are relative to the text regardless of the * angle, so "upper left" means in the top left-hand * corner seeing the text horizontally. */ #[Pure] function imagettfbbox(float $size, float $angle, string $font_filename, string $string, #[PhpStormStubsElementAvailable(from: '8.0')] array $options = []): array|false {} /** * Write text to the image using TrueType fonts * @link https://php.net/manual/en/function.imagettftext.php * @param resource|GdImage $image * @param float $size

    * The font size. Depending on your version of GD, this should be * specified as the pixel size (GD1) or point size (GD2). *

    * @param float $angle

    * The angle in degrees, with 0 degrees being left-to-right reading text. * Higher values represent a counter-clockwise rotation. For example, a * value of 90 would result in bottom-to-top reading text. *

    * @param int $x

    * The coordinates given by x and * y will define the basepoint of the first * character (roughly the lower-left corner of the character). This * is different from the imagestring, where * x and y define the * upper-left corner of the first character. For example, "top left" * is 0, 0. *

    * @param int $y

    * The y-ordinate. This sets the position of the fonts baseline, not the * very bottom of the character. *

    * @param int $color

    * The color index. Using the negative of a color index has the effect of * turning off antialiasing. See imagecolorallocate. *

    * @param string $font_filename

    * The path to the TrueType font you wish to use. *

    *

    * Depending on which version of the GD library PHP is using, when * font_filename does not begin with a leading * / then .ttf will be appended * to the filename and the library will attempt to search for that * filename along a library-defined font path. *

    *

    * When using versions of the GD library lower than 2.0.18, a space character, * rather than a semicolon, was used as the 'path separator' for different font files. * Unintentional use of this feature will result in the warning message: * Warning: Could not find/open font. For these affected versions, the * only solution is moving the font to a path which does not contain spaces. *

    *

    * In many cases where a font resides in the same directory as the script using it * the following trick will alleviate any include problems. *

    *
     * 
     * 
    *

    * Note: * open_basedir does not apply to font_filename. *

    * @param string $text

    * The text string in UTF-8 encoding. *

    *

    * May include decimal numeric character references (of the form: * &#8364;) to access characters in a font beyond position 127. * The hexadecimal format (like &#xA9;) is supported. * Strings in UTF-8 encoding can be passed directly. *

    *

    * Named entities, such as &copy;, are not supported. Consider using * html_entity_decode * to decode these named entities into UTF-8 strings (html_entity_decode() * supports this as of PHP 5.0.0). *

    *

    * If a character is used in the string which is not supported by the * font, a hollow rectangle will replace the character. *

    * @param array $options [optional] * @return array|false an array with 8 elements representing four points making the * bounding box of the text. The order of the points is lower left, lower * right, upper right, upper left. The points are relative to the text * regardless of the angle, so "upper left" means in the top left-hand * corner when you see the text horizontally. * Returns false on error. */ function imagettftext(GdImage $image, float $size, float $angle, int $x, int $y, int $color, string $font_filename, string $text, #[PhpStormStubsElementAvailable(from: '8.0')] array $options = []): array|false {} /** * Give the bounding box of a text using fonts via freetype2 * @link https://php.net/manual/en/function.imageftbbox.php * @param float $size

    * The font size. Depending on your version of GD, this should be * specified as the pixel size (GD1) or point size (GD2). *

    * @param float $angle

    * Angle in degrees in which text will be * measured. *

    * @param string $font_filename

    * The name of the TrueType font file (can be a URL). Depending on * which version of the GD library that PHP is using, it may attempt to * search for files that do not begin with a leading '/' by appending * '.ttf' to the filename and searching along a library-defined font path. *

    * @param string $string

    * The string to be measured. *

    * @param array $options [optional]

    *

    * Possible array indexes for extrainfo * * * * * * * * * * *
    KeyTypeMeaning
    linespacingfloatDefines drawing linespacing
    *

    * @return array|false imageftbbox returns an array with 8 * elements representing four points making the bounding box of the * text: * * 0 * lower left corner, X position * * * 1 * lower left corner, Y position * * * 2 * lower right corner, X position * * * 3 * lower right corner, Y position * * * 4 * upper right corner, X position * * * 5 * upper right corner, Y position * * * 6 * upper left corner, X position * * * 7 * upper left corner, Y position * *

    *

    * The points are relative to the text regardless of the * angle, so "upper left" means in the top left-hand * corner seeing the text horizontally. * Returns false on error. */ #[Pure] function imageftbbox(float $size, float $angle, string $font_filename, string $string, array $options = []): array|false {} /** * Write text to the image using fonts using FreeType 2 * @link https://php.net/manual/en/function.imagefttext.php * @param resource|GdImage $image * @param float $size

    * The font size to use in points. *

    * @param float $angle

    * The angle in degrees, with 0 degrees being left-to-right reading text. * Higher values represent a counter-clockwise rotation. For example, a * value of 90 would result in bottom-to-top reading text. *

    * @param int $x

    * The coordinates given by x and * y will define the basepoint of the first * character (roughly the lower-left corner of the character). This * is different from the imagestring, where * x and y define the * upper-left corner of the first character. For example, "top left" * is 0, 0. *

    * @param int $y

    * The y-ordinate. This sets the position of the fonts baseline, not the * very bottom of the character. *

    * @param int $color

    * The index of the desired color for the text, see * imagecolorexact. *

    * @param string $font_filename

    * The path to the TrueType font you wish to use. *

    *

    * Depending on which version of the GD library PHP is using, when * font_filename does not begin with a leading * / then .ttf will be appended * to the filename and the library will attempt to search for that * filename along a library-defined font path. *

    *

    * When using versions of the GD library lower than 2.0.18, a space character, * rather than a semicolon, was used as the 'path separator' for different font files. * Unintentional use of this feature will result in the warning message: * Warning: Could not find/open font. For these affected versions, the * only solution is moving the font to a path which does not contain spaces. *

    *

    * In many cases where a font resides in the same directory as the script using it * the following trick will alleviate any include problems. *

    *
     * 
     * 
    *

    * Note: * open_basedir does not apply to font_filename. *

    * @param string $text

    * Text to be inserted into image. *

    * @param array $options [optional]

    *

    * Possible array indexes for extrainfo * * * * * * * * * * *
    KeyTypeMeaning
    linespacingfloatDefines drawing linespacing
    *

    * @return array|false This function returns an array defining the four points of the box, starting in the lower left and moving counter-clockwise: * * 0 * lower left x-coordinate * * * 1 * lower left y-coordinate * * * 2 * lower right x-coordinate * * * 3 * lower right y-coordinate * * * 4 * upper right x-coordinate * * * 5 * upper right y-coordinate * * * 6 * upper left x-coordinate * * * 7 * upper left y-coordinate * * Returns false on error. */ function imagefttext(GdImage $image, float $size, float $angle, int $x, int $y, int $color, string $font_filename, string $text, array $options = []): array|false {} /** * Load a PostScript Type 1 font from file * @link https://php.net/manual/en/function.imagepsloadfont.php * @param string $filename

    * Path to the Postscript font file. *

    * @return resource|GdImage|false In the case everything went right, a valid font index will be returned and * can be used for further purposes. Otherwise the function returns false. * @removed 7.0 This function was REMOVED in PHP 7.0.0. */ function imagepsloadfont($filename) {} /** * Free memory used by a PostScript Type 1 font * @link https://php.net/manual/en/function.imagepsfreefont.php * @param resource|GdImage $font_index

    * A font resource, returned by imagepsloadfont. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function imagepsfreefont($font_index) {} /** * Change the character encoding vector of a font * @link https://php.net/manual/en/function.imagepsencodefont.php * @param resource|GdImage $font_index

    * A font resource, returned by imagepsloadfont. *

    * @param string $encodingfile

    * The exact format of this file is described in T1libs documentation. * T1lib comes with two ready-to-use files, * IsoLatin1.enc and * IsoLatin2.enc. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function imagepsencodefont($font_index, $encodingfile) {} /** * Extend or condense a font * @link https://php.net/manual/en/function.imagepsextendfont.php * @param resource|GdImage $font_index

    * A font resource, returned by imagepsloadfont. *

    * @param float $extend

    * Extension value, must be greater than 0. *

    * @return bool true on success or false on failure. * @removed 7.0 */ function imagepsextendfont($font_index, $extend) {} /** * Slant a font * @link https://php.net/manual/en/function.imagepsslantfont.php * @param resource|GdImage $font_index

    * A font resource, returned by imagepsloadfont. *

    * @param float $slant

    * Slant level. *

    * @return bool true on success or false on failure. * @removed 7.0 This function was REMOVED in PHP 7.0.0. */ function imagepsslantfont($font_index, $slant) {} /** * Draws a text over an image using PostScript Type1 fonts * @link https://php.net/manual/en/function.imagepstext.php * @param resource|GdImage $image * @param string $text

    * The text to be written. *

    * @param resource|GdImage $font_index

    * A font resource, returned by imagepsloadfont. *

    * @param int $size

    * size is expressed in pixels. *

    * @param int $foreground

    * The color in which the text will be painted. *

    * @param int $background

    * The color to which the text will try to fade in with antialiasing. * No pixels with the color background are * actually painted, so the background image does not need to be of solid * color. *

    * @param int $x

    * x-coordinate for the lower-left corner of the first character. *

    * @param int $y

    * y-coordinate for the lower-left corner of the first character. *

    * @param int $space [optional]

    * Allows you to change the default value of a space in a font. This * amount is added to the normal value and can also be negative. * Expressed in character space units, where 1 unit is 1/1000th of an * em-square. *

    * @param int $tightness [optional]

    * tightness allows you to control the amount * of white space between characters. This amount is added to the * normal character width and can also be negative. * Expressed in character space units, where 1 unit is 1/1000th of an * em-square. *

    * @param float $angle [optional]

    * angle is in degrees. *

    * @param int $antialias_steps [optional]

    * Allows you to control the number of colours used for antialiasing * text. Allowed values are 4 and 16. The higher value is recommended * for text sizes lower than 20, where the effect in text quality is * quite visible. With bigger sizes, use 4. It's less computationally * intensive. *

    * @return array|false This function returns an array containing the following elements: * * 0 * lower left x-coordinate * * * 1 * lower left y-coordinate * * * 2 * upper right x-coordinate * * * 3 * upper right y-coordinate * * Returns false on error. * @removed 7.0 This function was REMOVED in PHP 7.0.0. */ function imagepstext($image, $text, $font_index, $size, $foreground, $background, $x, $y, $space = null, $tightness = null, $angle = null, $antialias_steps = null) {} /** * Give the bounding box of a text rectangle using PostScript Type1 fonts * @link https://php.net/manual/en/function.imagepsbbox.php * @param string $text

    * The text to be written. *

    * @param resource|GdImage $font * @param int $size

    * size is expressed in pixels. *

    * @return array|false an array containing the following elements: * * 0 * left x-coordinate * * * 1 * upper y-coordinate * * * 2 * right x-coordinate * * * 3 * lower y-coordinate * * Returns false on error. * @removed 7.0 */ function imagepsbbox($text, $font, $size) {} /** * Return the image types supported by this PHP build * @link https://php.net/manual/en/function.imagetypes.php * @return int a bit-field corresponding to the image formats supported by the * version of GD linked into PHP. The following bits are returned, * IMG_BMP | IMG_GIF | IMG_JPG | IMG_PNG | IMG_WBMP | IMG_XPM | IMG_WEBP */ #[Pure] function imagetypes(): int {} /** * Convert JPEG image file to WBMP image file * @link https://php.net/manual/en/function.jpeg2wbmp.php * @param string $jpegname

    * Path to JPEG file. *

    * @param string $wbmpname

    * Path to destination WBMP file. *

    * @param int $dest_height

    * Destination image height. *

    * @param int $dest_width

    * Destination image width. *

    * @param int $threshold

    * Threshold value, between 0 and 8 (inclusive). *

    * @return bool true on success or false on failure. * @removed 8.0 * @see imagecreatefromjpeg() */ #[Deprecated(reason: "Use imagecreatefromjpeg() and imagewbmp() instead", since: "7.2")] function jpeg2wbmp($jpegname, $wbmpname, $dest_height, $dest_width, $threshold) {} /** * Convert PNG image file to WBMP image file * @link https://php.net/manual/en/function.png2wbmp.php * @param string $pngname

    * Path to PNG file. *

    * @param string $wbmpname

    * Path to destination WBMP file. *

    * @param int $dest_height

    * Destination image height. *

    * @param int $dest_width

    * Destination image width. *

    * @param int $threshold

    * Threshold value, between 0 and 8 (inclusive). *

    * @return bool true on success or false on failure. * @removed 8.0 * @see imagecreatefrompng() * @see imagewbmp() */ #[Deprecated("Use imagecreatefrompng() and imagewbmp() instead", since: "7.2")] function png2wbmp($pngname, $wbmpname, $dest_height, $dest_width, $threshold) {} /** * Output image to browser or file * @link https://php.net/manual/en/function.image2wbmp.php * @param resource|GdImage $image * @param string $filename [optional]

    * Path to the saved file. If not given, the raw image stream will be * outputted directly. *

    * @param int $threshold [optional]

    * Threshold value, between 0 and 255 (inclusive). *

    * @return bool true on success or false on failure. * @removed 8.0 * @see imagewbmp() */ #[Deprecated(replacement: "imagewbmp(%parametersList%)", since: "7.3")] function image2wbmp($image, $filename = null, $threshold = null) {} /** * Set the alpha blending flag to use the bundled libgd layering effects * @link https://php.net/manual/en/function.imagelayereffect.php * @param resource|GdImage $image * @param int $effect

    * One of the following constants: * IMG_EFFECT_REPLACE * Use pixel replacement (equivalent of passing true to * imagealphablending)

    * @return bool true on success or false on failure. */ function imagelayereffect(GdImage $image, int $effect): bool {} /** * Makes the colors of the palette version of an image more closely match the true color version * @link https://php.net/manual/en/function.imagecolormatch.php * @param resource|GdImage $image1

    * A truecolor image link resource. *

    * @param resource|GdImage $image2

    * A palette image link resource pointing to an image that has the same * size as image1. *

    * @return bool true on success or false on failure. */ function imagecolormatch(GdImage $image1, GdImage $image2): bool {} /** * Output XBM image to browser or file * @link https://php.net/manual/en/function.imagexbm.php * @param resource|GdImage $image * @param string|null $filename

    * The path to save the file to. If not set or null, the raw image stream * will be outputted directly. *

    * @param int|null $foreground_color [optional]

    * You can set the foreground color with this parameter by setting an * identifier obtained from imagecolorallocate. * The default foreground color is black. *

    * @return bool true on success or false on failure. */ function imagexbm(GdImage $image, ?string $filename, ?int $foreground_color = null): bool {} /** * Applies a filter to an image * @link https://php.net/manual/en/function.imagefilter.php * @param resource|GdImage $image * @param int $filter

    * filtertype can be one of the following: * IMG_FILTER_NEGATE: Reverses all colors of * the image.

    * @param int ...$args * @return bool true on success or false on failure. */ function imagefilter( GdImage $image, int $filter, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arg1 = null, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arg2 = null, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arg3 = null, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arg4 = null, #[PhpStormStubsElementAvailable(from: '8.0')] ...$args ): bool {} /** * Apply a 3x3 convolution matrix, using coefficient and offset * @link https://php.net/manual/en/function.imageconvolution.php * @param resource|GdImage $image * @param array $matrix

    * A 3x3 matrix: an array of three arrays of three floats. *

    * @param float $divisor

    * The divisor of the result of the convolution, used for normalization. *

    * @param float $offset

    * Color offset. *

    * @return bool true on success or false on failure. */ function imageconvolution(GdImage $image, array $matrix, float $divisor, float $offset): bool {} /** * @param resource|GdImage $image An image resource, returned by one of the image creation functions, such as {@see imagecreatetruecolor()}. * @param int|null $resolution_x The horizontal resolution in DPI. * @param int|null $resolution_y The vertical resolution in DPI. * @return array|bool When used as getter (that is without the optional parameters), it returns TRUE on success, or FALSE on failure. When used as setter (that is with one or both optional parameters given), it returns an indexed array of the horizontal and vertical resolution on success, or FALSE on failure. * @link https://php.net/manual/en/function.imageresolution.php * @since 7.2 */ #[LanguageLevelTypeAware(['8.2' => 'array|true'], default: 'array|bool')] function imageresolution(GdImage $image, ?int $resolution_x = null, ?int $resolution_y = null): array|bool {} /** * imagesetclip() sets the current clipping rectangle, i.e. the area beyond which no pixels will be drawn. * @param resource|GdImage $image An image resource, returned by one of the image creation functions, such as {@see imagecreatetruecolor()}. * @param int $x1 The x-coordinate of the upper left corner. * @param int $y1 The y-coordinate of the upper left corner. * @param int $x2 The x-coordinate of the lower right corner. * @param int $y2 The y-coordinate of the lower right corner. * @return bool Returns TRUE on success or FALSE on failure. * @link https://php.net/manual/en/function.imagesetclip.php * @see imagegetclip() * @since 7.2 */ function imagesetclip(GdImage $image, int $x1, int $y1, int $x2, int $y2): bool {} /** * imagegetclip() retrieves the current clipping rectangle, i.e. the area beyond which no pixels will be drawn. * @param resource|GdImage $image An image resource, returned by one of the image creation functions, such as {@see imagecreatetruecolor()} * @return array|false an indexed array with the coordinates of the clipping rectangle which has the following entries: *
      *
    • x-coordinate of the upper left corner
    • *
    • y-coordinate of the upper left corner
    • *
    • x-coordinate of the lower right corner
    • *
    • y-coordinate of the lower right corner
    • *
    * Returns FALSE on error. * @link https://php.net/manual/en/function.imagegetclip.php * @see imagesetclip() * @since 7.2 */ function imagegetclip(GdImage $image): array {} /** * imageopenpolygon() draws an open polygon on the given image. Contrary to {@see imagepolygon()}, no line is drawn between the last and the first point. * @param resource|GdImage $image An image resource, returned by one of the image creation functions, such as {@see imagecreatetruecolor()}. * @param int[] $points An array containing the polygon's vertices, e.g.: *
     * points[0]	= x0
     * points[1]	= y0
     * points[2]	= x1
     * points[3]	= y1
     * 
    * @param int $num_points_or_color Total number of points (vertices). * @param int|null $color A color identifier created with {@see imagecolorallocate()}. * @return bool Returns TRUE on success or FALSE on failure. * @link https://php.net/manual/en/function.imageopenpolygon.php * @since 7.2 * @see imageplygon() */ function imageopenpolygon( GdImage $image, array $points, #[Deprecated(since: "8.1")] int $num_points_or_color, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] ?int $color, #[PhpStormStubsElementAvailable(from: '8.0')] ?int $color = null ): bool {} /** * imagecreatefrombmp() returns an image identifier representing the image obtained from the given filename. * TIP A URL can be used as a filename with this function if the fopen wrappers have been enabled. See {@see fopen()} for more details on how to specify the filename. See the Supported Protocols and Wrappers for links to information about what abilities the various wrappers have, notes on their usage, and information on any predefined variables they may provide. * @param string $filename Path to the BMP image. * @return resource|GdImage|false Returns an image resource identifier on success, FALSE on errors. * @link https://php.net/manual/en/function.imagecreatefrombmp.php * @since 7.2 */ function imagecreatefrombmp(string $filename): GdImage|false {} /** * Outputs or saves a BMP version of the given image. * @param resource|GdImage $image An image resource, returned by one of the image creation functions, such as {@see imagecreatetruecolor()}. * @param mixed $file The path or an open stream resource (which is automatically being closed after this function returns) to save the file to. If not set or NULL, the raw image stream will be outputted directly. *
    * Note: NULL is invalid if the compressed arguments is not used. * @param bool $compressed Whether the BMP should be compressed with run-length encoding (RLE), or not. * @return bool Returns TRUE on success or FALSE on failure. *
    * Caution However, if libgd fails to output the image, this function returns TRUE. * @link https://php.net/manual/en/function.imagebmp.php * @since 7.2 */ function imagebmp(GdImage $image, $file = null, bool $compressed = true): bool {} /** * @param string $filename * @return resource|GdImage|false */ function imagecreatefromtga(string $filename): GdImage|false {} /** * Captures the whole screen * * https://www.php.net/manual/en/function.imagegrabscreen.php * * @return resource|GdImage|false */ #[Pure] function imagegrabscreen() {} /** * Captures a window * * @link https://www.php.net/manual/en/function.imagegrabwindow.php * * @param int $handle * @param int|null $client_area * @return resource|GdImage|false */ #[Pure] function imagegrabwindow($handle, $client_area = null) {} /** * Gets the currently set interpolation method of the image. * * @link https://www.php.net/manual/en/function.imagegetinterpolation.php * * @param GdImage $image * @return int */ #[Pure] function imagegetinterpolation(GdImage $image): int {} /** * Used as a return value by {@see imagetypes()} * @link https://php.net/manual/en/image.constants.php#constant.img-gif */ define('IMG_GIF', 1); /** * Used as a return value by {@see imagetypes()} * @link https://php.net/manual/en/image.constants.php#constant.img-jpg */ define('IMG_JPG', 2); /** * Used as a return value by {@see imagetypes()} *

    * This constant has the same value as {@see IMG_JPG} *

    * @link https://php.net/manual/en/image.constants.php#constant.img-jpeg */ define('IMG_JPEG', 2); /** * Used as a return value by {@see imagetypes()} * @link https://php.net/manual/en/image.constants.php#constant.img-png */ define('IMG_PNG', 4); /** * Used as a return value by {@see imagetypes()} * @link https://php.net/manual/en/image.constants.php#constant.img-wbmp */ define('IMG_WBMP', 8); /** * Used as a return value by {@see imagetypes()} * @link https://php.net/manual/en/image.constants.php#constant.img-xpm */ define('IMG_XPM', 16); /** * Used as a return value by {@see imagetypes()} * @since 5.6.25 * @since 7.0.10 * @link https://php.net/manual/en/image.constants.php#constant.img-webp */ define('IMG_WEBP', 32); /** * Used as a return value by {@see imagetypes()} * @since 7.2 * @link https://php.net/manual/en/image.constants.php#constant.img-bmp */ define('IMG_BMP', 64); /** * Special color option which can be used instead of color allocated with * {@see imagecolorallocate()} or {@see imagecolorallocatealpha()} * @link https://php.net/manual/en/image.constants.php#constant.img-color-tiled */ define('IMG_COLOR_TILED', -5); /** * Special color option which can be used instead of color allocated with * {@see imagecolorallocate()} or {@see imagecolorallocatealpha()} * @link https://php.net/manual/en/image.constants.php#constant.img-color-styled */ define('IMG_COLOR_STYLED', -2); /** * Special color option which can be used instead of color allocated with * {@see imagecolorallocate()} or {@see imagecolorallocatealpha()} * @link https://php.net/manual/en/image.constants.php#constant.img-color-brushed */ define('IMG_COLOR_BRUSHED', -3); /** * Special color option which can be used instead of color allocated with * {@see imagecolorallocate()} or {@see imagecolorallocatealpha()} * @link https://php.net/manual/en/image.constants.php#constant.img-color-styledbrushed */ define('IMG_COLOR_STYLEDBRUSHED', -4); /** * Special color option which can be used instead of color allocated with * {@see imagecolorallocate()} or {@see imagecolorallocatealpha()} * @link https://php.net/manual/en/image.constants.php#constant.img-color-transparent */ define('IMG_COLOR_TRANSPARENT', -6); /** * A style constant used by the {@see imagefilledarc()} function. *

    * This constant has the same value as {@see IMG_ARC_PIE} *

    * @link https://php.net/manual/en/image.constants.php#constant.img-arc-rounded */ define('IMG_ARC_ROUNDED', 0); /** * A style constant used by the {@see imagefilledarc()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-arc-pie */ define('IMG_ARC_PIE', 0); /** * A style constant used by the {@see imagefilledarc()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-arc-chord */ define('IMG_ARC_CHORD', 1); /** * A style constant used by the {@see imagefilledarc()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-arc-nofill */ define('IMG_ARC_NOFILL', 2); /** * A style constant used by the {@see imagefilledarc()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-arc-edged */ define('IMG_ARC_EDGED', 4); /** * A type constant used by the {@see imagegd2()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-gd2-raw */ define('IMG_GD2_RAW', 1); /** * A type constant used by the {@see imagegd2()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-gd2-compressed */ define('IMG_GD2_COMPRESSED', 2); /** * Alpha blending effect used by the {@see imagelayereffect()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-effect-replace */ define('IMG_EFFECT_REPLACE', 0); /** * Alpha blending effect used by the {@see imagelayereffect()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-effect-alphablend */ define('IMG_EFFECT_ALPHABLEND', 1); /** * Alpha blending effect used by the {@see imagelayereffect()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-effect-normal */ define('IMG_EFFECT_NORMAL', 2); /** * Alpha blending effect used by the {@see imagelayereffect()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-effect-overlay */ define('IMG_EFFECT_OVERLAY', 3); /** * Alpha blending effect used by the {@see imagelayereffect()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-effect-multiply * @since 7.2 */ define('IMG_EFFECT_MULTIPLY', 4); /** * When the bundled version of GD is used this is 1 otherwise * it's set to 0. * @link https://php.net/manual/en/image.constants.php */ define('GD_BUNDLED', 1); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-negate */ define('IMG_FILTER_NEGATE', 0); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-grayscale */ define('IMG_FILTER_GRAYSCALE', 1); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-brightness */ define('IMG_FILTER_BRIGHTNESS', 2); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-contrast */ define('IMG_FILTER_CONTRAST', 3); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-colorize */ define('IMG_FILTER_COLORIZE', 4); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-edgedetect */ define('IMG_FILTER_EDGEDETECT', 5); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-gaussian-blur */ define('IMG_FILTER_GAUSSIAN_BLUR', 7); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-selective-blur */ define('IMG_FILTER_SELECTIVE_BLUR', 8); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-emboss */ define('IMG_FILTER_EMBOSS', 6); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-mean-removal */ define('IMG_FILTER_MEAN_REMOVAL', 9); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-smooth */ define('IMG_FILTER_SMOOTH', 10); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-pixelate */ define('IMG_FILTER_PIXELATE', 11); /** * Special GD filter used by the {@see imagefilter()} function. * @link https://php.net/manual/en/image.constants.php#constant.img-filter-scatter * @since 7.4 */ define('IMG_FILTER_SCATTER', 12); /** * The GD version PHP was compiled against. * @since 5.2.4 * @link https://php.net/manual/en/image.constants.php#constant.gd-version */ define('GD_VERSION', "2.0.35"); /** * The GD major version PHP was compiled against. * @since 5.2.4 * @link https://php.net/manual/en/image.constants.php#constant.gd-major-version */ define('GD_MAJOR_VERSION', 2); /** * The GD minor version PHP was compiled against. * @since 5.2.4 * @link https://php.net/manual/en/image.constants.php#constant.gd-minor-version */ define('GD_MINOR_VERSION', 0); /** * The GD release version PHP was compiled against. * @since 5.2.4 * @link https://php.net/manual/en/image.constants.php#constant.gd-release-version */ define('GD_RELEASE_VERSION', 35); /** * The GD "extra" version (beta/rc..) PHP was compiled against. * @since 5.2.4 * @link https://php.net/manual/en/image.constants.php#constant.gd-extra-version */ define('GD_EXTRA_VERSION', ""); /** * A special PNG filter, used by the {@see imagepng()} function. * @link https://php.net/manual/en/image.constants.php#constant.png-no-filter */ define('PNG_NO_FILTER', 0); /** * A special PNG filter, used by the {@see imagepng()} function. * @link https://php.net/manual/en/image.constants.php#constant.png-filter-none */ define('PNG_FILTER_NONE', 8); /** * A special PNG filter, used by the {@see imagepng()} function. * @link https://php.net/manual/en/image.constants.php#constant.png-filter-sub */ define('PNG_FILTER_SUB', 16); /** * A special PNG filter, used by the {@see imagepng()} function. * @link https://php.net/manual/en/image.constants.php#constant.png-filter-up */ define('PNG_FILTER_UP', 32); /** * A special PNG filter, used by the {@see imagepng()} function. * @link https://php.net/manual/en/image.constants.php#constant.png-filter-avg */ define('PNG_FILTER_AVG', 64); /** * A special PNG filter, used by the {@see imagepng()} function. * @link https://php.net/manual/en/image.constants.php#constant.png-filter-paeth */ define('PNG_FILTER_PAETH', 128); /** * A special PNG filter, used by the {@see imagepng()} function. * @link https://php.net/manual/en/image.constants.php#constant.png-all-filters */ define('PNG_ALL_FILTERS', 248); /** * An affine transformation type constant used by the {@see imageaffinematrixget()} function. * @since 5.5 * @link https://php.net/manual/en/image.constants.php#constant.img-affine-translate */ define('IMG_AFFINE_TRANSLATE', 0); /** * An affine transformation type constant used by the {@see imageaffinematrixget()} function. * @since 5.5 * @link https://php.net/manual/en/image.constants.php#constant.img-affine-scale */ define('IMG_AFFINE_SCALE', 1); /** * An affine transformation type constant used by the {@see imageaffinematrixget()} function. * @since 5.5 * @link https://php.net/manual/en/image.constants.php#constant.img-affine-rotate */ define('IMG_AFFINE_ROTATE', 2); /** * An affine transformation type constant used by the {@see imageaffinematrixget()} function. * @since 5.5 * @link https://php.net/manual/en/image.constants.php#constant.img-affine-shear-horizontal */ define('IMG_AFFINE_SHEAR_HORIZONTAL', 3); /** * An affine transformation type constant used by the {@see imageaffinematrixget()} function. * @since 5.5 * @link https://php.net/manual/en/image.constants.php#constant.img-affine-shear-vertical */ define('IMG_AFFINE_SHEAR_VERTICAL', 4); /** * Same as {@see IMG_CROP_TRANSPARENT}. Before PHP 7.4.0, the bundled libgd fell back to * {@see IMG_CROP_SIDES}, if the image had no transparent color. * Used together with {@see imagecropauto()}. * @since 5.5 */ define('IMG_CROP_DEFAULT', 0); /** * Crops out a transparent background. * Used together with {@see imagecropauto()}. * @since 5.5 */ define('IMG_CROP_TRANSPARENT', 1); /** * Crops out a black background. * Used together with {@see imagecropauto()}. * @since 5.5 */ define('IMG_CROP_BLACK', 2); /** * Crops out a white background. * Used together with {@see imagecropauto()}. * @since 5.5 */ define('IMG_CROP_WHITE', 3); /** * Uses the 4 corners of the image to attempt to detect the background to crop. * Used together with {@see imagecropauto()}. * @since 5.5 */ define('IMG_CROP_SIDES', 4); /** * Crops an image using the given threshold and color. * Used together with {@see imagecropauto()}. * @since 5.5 */ define('IMG_CROP_THRESHOLD', 5); /** * Used together with {@see imageflip()} * @since 5.5 * @link https://php.net/manual/en/image.constants.php#constant.img-flip-both */ define('IMG_FLIP_BOTH', 3); /** * Used together with {@see imageflip()} * @since 5.5 * @link https://php.net/manual/en/image.constants.php#constant.img-flip-horizontal */ define('IMG_FLIP_HORIZONTAL', 1); /** * Used together with {@see imageflip()} * @since 5.5 * @link https://php.net/manual/en/image.constants.php#constant.img-flip-vertical */ define('IMG_FLIP_VERTICAL', 2); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-bell * @since 5.5 */ define('IMG_BELL', 1); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-bessel * @since 5.5 */ define('IMG_BESSEL', 2); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-bicubic * @since 5.5 */ define('IMG_BICUBIC', 4); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-bicubic-fixed * @since 5.5 */ define('IMG_BICUBIC_FIXED', 5); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-bilinear-fixed * @since 5.5 */ define('IMG_BILINEAR_FIXED', 3); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-blackman * @since 5.5 */ define('IMG_BLACKMAN', 6); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-box * @since 5.5 */ define('IMG_BOX', 7); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-bspline * @since 5.5 */ define('IMG_BSPLINE', 8); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-catmullrom * @since 5.5 */ define('IMG_CATMULLROM', 9); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-gaussian * @since 5.5 */ define('IMG_GAUSSIAN', 10); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-generalized-cubic * @since 5.5 */ define('IMG_GENERALIZED_CUBIC', 11); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-hermite * @since 5.5 */ define('IMG_HERMITE', 12); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-hamming * @since 5.5 */ define('IMG_HAMMING', 13); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-hanning * @since 5.5 */ define('IMG_HANNING', 14); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-mitchell * @since 5.5 */ define('IMG_MITCHELL', 15); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-power * @since 5.5 */ define('IMG_POWER', 17); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-quadratic * @since 5.5 */ define('IMG_QUADRATIC', 18); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-sinc * @since 5.5 */ define('IMG_SINC', 19); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-nearest-neighbour * @since 5.5 */ define('IMG_NEAREST_NEIGHBOUR', 16); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-weighted4 * @since 5.5 */ define('IMG_WEIGHTED4', 21); /** * Used together with {@see imagesetinterpolation()}. * @link https://php.net/manual/en/image.constants.php#constant.img-triangle * @since 5.5 */ define('IMG_TRIANGLE', 20); define('IMG_TGA', 128); /** * @since 8.1 */ define('IMG_AVIF', 256); /** * @since 8.1 */ define('IMG_WEBP_LOSSLESS', 101); /** * Outputs or saves a AVIF Raster image from the given image * @link https://www.php.net/manual/function.imageavif.php * @param GdImage $image A GdImage object, returned by one of the image creation functions, such as imagecreatetruecolor(). * @param resource|string|null $file The path or an open stream resource (which is automatically closed after this function returns) to save the file to. If not set or null, the raw image stream will be output directly. * @param int $quality quality is optional, and ranges from 0 (worst quality, smaller file) to 100 (best quality, larger file). If -1 is provided, the default value 30 is used. * @param int $speed speed is optional, and ranges from 0 (slow, smaller file) to 10 (fast, larger file). If -1 is provided, the default value 6 is used. * @return bool Returns true on success or false on failure. However, if libgd fails to output the image, this function returns true. * @since 8.1 */ function imageavif(GdImage $image, string|null $file = null, int $quality = -1, int $speed = -1): bool {} /** * Return an image containing the affine tramsformed src image, using an optional clipping area * @link https://secure.php.net/manual/en/function.imageaffine.php * @param resource|GdImage $image

    An image resource, returned by one of the image creation functions, * such as {@link https://secure.php.net/manual/en/function.imagecreatetruecolor.php imagecreatetruecolor()}.

    * @param array $affine

    Array with keys 0 to 5.

    * @param array|null $clip [optional]

    Array with keys "x", "y", "width" and "height".

    * @return resource|GdImage|false Return affined image resource on success or FALSE on failure. */ function imageaffine(GdImage $image, array $affine, ?array $clip = null): GdImage|false {} /** * Concat two matrices (as in doing many ops in one go) * @link https://secure.php.net/manual/en/function.imageaffinematrixconcat.php * @param array $matrix1

    Array with keys 0 to 5.

    * @param array $matrix2

    Array with keys 0 to 5.

    * @return float[]|false Array with keys 0 to 5 and float values or FALSE on failure. * @since 5.5 */ function imageaffinematrixconcat(array $matrix1, array $matrix2): array|false {} /** * Return an image containing the affine tramsformed src image, using an optional clipping area * @link https://secure.php.net/manual/en/function.imageaffinematrixget.php * @param int $type

    One of IMG_AFFINE_* constants.

    * @param mixed $options * @return float[]|false Array with keys 0 to 5 and float values or FALSE on failure. * @since 5.5 */ function imageaffinematrixget( int $type, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $options = null, #[PhpStormStubsElementAvailable(from: '8.0')] $options ): array|false {} /** * Crop an image using the given coordinates and size, x, y, width and height * @link https://secure.php.net/manual/en/function.imagecrop.php * @param resource|GdImage $image

    * An image resource, returned by one of the image creation functions, such as {@link https://secure.php.net/manual/en/function.imagecreatetruecolor.php imagecreatetruecolor()}. *

    * @param array $rectangle

    Array with keys "x", "y", "width" and "height".

    * @return resource|GdImage|false Return cropped image resource on success or FALSE on failure. * @since 5.5 */ function imagecrop(GdImage $image, array $rectangle): GdImage|false {} /** * Crop an image automatically using one of the available modes * @link https://secure.php.net/manual/en/function.imagecropauto.php * @param resource|GdImage $image

    * An image resource, returned by one of the image creation functions, such as {@link https://secure.php.net/manual/en/function.imagecreatetruecolor.php imagecreatetruecolor()}. *

    * @param int $mode [optional]

    * One of IMG_CROP_* constants. *

    * @param float $threshold [optional]

    * Used IMG_CROP_THRESHOLD mode. *

    * @param int $color [optional] *

    * Used in IMG_CROP_THRESHOLD mode. *

    * @return resource|GdImage|false Return cropped image resource on success or FALSE on failure. * @since 5.5 */ function imagecropauto(GdImage $image, int $mode = IMG_CROP_DEFAULT, float $threshold = .5, int $color = -1): GdImage|false {} /** * Flips an image using a given mode * @link https://secure.php.net/manual/en/function.imageflip.php * @param resource|GdImage $image

    * An image resource, returned by one of the image creation functions, such as {@link https://secure.php.net/manual/en/function.imagecreatetruecolor.php imagecreatetruecolor()}. *

    * @param int $mode

    * Flip mode, this can be one of the IMG_FLIP_* constants: *

    * * * * * * * * * * * * * * * * * * * * * *
    ConstantMeaning
    IMG_FLIP_HORIZONTAL * Flips the image horizontally. *
    IMG_FLIP_VERTICAL * Flips the image vertically. *
    IMG_FLIP_BOTH * Flips the image both horizontally and vertically. *
    * @return bool Returns TRUE on success or FALSE on failure. * @since 5.5 */ function imageflip(GdImage $image, int $mode): bool {} /** * Converts a palette based image to true color * @link https://secure.php.net/manual/en/function.imagepalettetotruecolor.php * @param resource|GdImage $image

    * An image resource, returnd by one of the image creation functions, such as {@link https://secure.php.net/manual/en/function.imagecreatetruecolor.php imagecreatetruecolor()}. *

    * @return bool Returns TRUE if the convertion was complete, or if the source image already is a true color image, otherwise FALSE is returned. * @since 5.5 */ function imagepalettetotruecolor(GdImage $image): bool {} /** * @param resource|GdImage $image

    * An image resource, returnd by one of the image creation functions, such as {@link https://secure.php.net/manual/en/function.imagecreatetruecolor.php imagecreatetruecolor()}. *

    * @param int $width * @param int $height [optional] * @param int $mode [optional] One of IMG_NEAREST_NEIGHBOUR, IMG_BILINEAR_FIXED, IMG_BICUBIC, IMG_BICUBIC_FIXED or anything else (will use two pass). * @return resource|GdImage|false Return scaled image resource on success or FALSE on failure. *@link https://secure.php.net/manual/en/function.imagescale.php * @since 5.5 * Scale an image using the given new width and height */ function imagescale(GdImage $image, int $width, int $height = -1, int $mode = IMG_BILINEAR_FIXED): GdImage|false {} /** * Set the interpolation method * @link https://secure.php.net/manual/en/function.imagesetinterpolation.php * @param resource|GdImage $image

    * An image resource, returned by one of the image creation functions, such as {@link https://secure.php.net/manual/en/function.imagecreatetruecolor.php imagecreatetruecolor()}. *

    * @param int $method

    * The interpolation method, which can be one of the following: *

      *
    • * IMG_BELL: Bell filter. *
    • *
    • * IMG_BESSEL: Bessel filter. *
    • *
    • * IMG_BICUBIC: Bicubic interpolation. *
    • *
    • * IMG_BICUBIC_FIXED: Fixed point implementation of the bicubic interpolation. *
    • *
    • * IMG_BILINEAR_FIXED: Fixed point implementation of the bilinear interpolation (default (also on image creation)). *
    • *
    • * IMG_BLACKMAN: Blackman window function. *
    • *
    • * IMG_BOX: Box blur filter. *
    • *
    • * IMG_BSPLINE: Spline interpolation. *
    • *
    • * IMG_CATMULLROM: Cubbic Hermite spline interpolation. *
    • *
    • * IMG_GAUSSIAN: Gaussian function. *
    • *
    • * IMG_GENERALIZED_CUBIC: Generalized cubic spline fractal interpolation. *
    • *
    • * IMG_HERMITE: Hermite interpolation. *
    • *
    • * IMG_HAMMING: Hamming filter. *
    • *
    • * IMG_HANNING: Hanning filter. *
    • *
    • * IMG_MITCHELL: Mitchell filter. *
    • *
    • * IMG_POWER: Power interpolation. *
    • *
    • * IMG_QUADRATIC: Inverse quadratic interpolation. *
    • *
    • * IMG_SINC: Sinc function. *
    • *
    • * IMG_NEAREST_NEIGHBOUR: Nearest neighbour interpolation. *
    • *
    • * IMG_WEIGHTED4: Weighting filter. *
    • *
    • * IMG_TRIANGLE: Triangle interpolation. *
    • *
    *

    * @return bool Returns TRUE on success or FALSE on failure. * @since 5.5 */ function imagesetinterpolation(GdImage $image, int $method = IMG_BILINEAR_FIXED): bool {} /** * @since 8.0 */ final class GdImage { /** * You cannot initialize a GdImage object except through helper functions. */ private function __construct() {} private function __clone() {} } * @copyright © 2019 PHP Documentation Group * @license CC-BY 3.0, https://www.php.net/manual/en/cc.license.php */ namespace Ds; use ArrayAccess; use Countable; use IteratorAggregate; use JsonSerializable; use OutOfBoundsException; use OutOfRangeException; use Traversable; use UnderflowException; /** * Collection is the base interface which covers functionality common to all * the data structures in this library. It guarantees that all structures * are traversable, countable, and can be converted to json using * json_encode(). * @package Ds * * @template-covariant TKey * @template-covariant TValue * @extends IteratorAggregate */ interface Collection extends Countable, IteratorAggregate, JsonSerializable { /** * Removes all values from the collection. * @link https://www.php.net/manual/en/ds-collection.clear.php */ public function clear(): void; /** * Returns a shallow copy of the collection. * @link https://www.php.net/manual/en/ds-collection.copy.php * @return Collection */ public function copy(); /** * Returns whether the collection is empty. * @link https://www.php.net/manual/en/ds-collection.isempty.php * @return bool */ public function isEmpty(): bool; /** * Converts the collection to an array. *

    Note: Casting to an array is not supported yet.

    * @link https://www.php.net/manual/en/ds-collection.toarray.php * @return array An array containing all the values in the same order as * the collection. */ public function toArray(): array; } /** * Hashable is an interface which allows objects to be used as keys. It’s * an alternative to spl_object_hash(), which determines an object’s hash * based on its handle: this means that two objects that are considered * equal by an implicit definition would not treated as equal because they * are not the same instance. * * hash() is used to return a scalar value to be used as the object's hash * value, which determines where it goes in the hash table. While this value * does not have to be unique, objects which are equal must have the same * hash value. * * equals() is used to determine if two objects are equal. It's guaranteed * that the comparing object will be an instance of the same class as the * subject. * @package Ds */ interface Hashable { /** * Determines whether another object is equal to the current instance. * * This method allows objects to be used as keys in structures such as * Ds\Map and Ds\Set, or any other lookup structure that honors this * interface. * * Note: It's guaranteed that $obj is an instance of the same class. * * Caution: It's important that objects which are equal also have the * same hash value. * @see https://www.php.net/manual/en/ds-hashable.hash.php * @link https://www.php.net/manual/en/ds-hashable.equals.php * @param object $obj The object to compare the current instance to, * which is always an instance of the same class. * * @return bool True if equal, false otherwise. */ public function equals($obj): bool; /** * Returns a scalar value to be used as the hash value of the objects. * * While the hash value does not define equality, all objects that are * equal according to Ds\Hashable::equals() must have the same hash * value. Hash values of equal objects don't have to be unique, for * example you could just return TRUE for all objects and nothing * would break - the only implication would be that hash tables then * turn into linked lists because all your objects will be hashed to * the same bucket. It's therefore very important that you pick a good * hash value, such as an ID or email address. * * This method allows objects to be used as keys in structures such as * Ds\Map and Ds\Set, or any other lookup structure that honors this * interface. * * Caution: Do not pick a value that might change within the object, * such as a public property. Hash table lookups would fail because * the hash has changed. * * Caution: All objects that are equal must have the same hash value. * * @return mixed A scalar value to be used as this object's hash value. * @link https://www.php.net/manual/en/ds-hashable.hash.php */ public function hash(); } /** * A Sequence describes the behaviour of values arranged in a single, * linear dimension. Some languages refer to this as a "List". It’s * similar to an array that uses incremental integer keys, with the * exception of a few characteristics: *
      *
    • Values will always be indexed as [0, 1, 2, …, size - 1].
    • *
    • Only allowed to access values by index in the range [0, size - 1].
    • *
    *
    * Use cases: *
      *
    • Wherever you would use an array as a list (not concerned with keys).
    • *
    • A more efficient alternative to SplDoublyLinkedList and SplFixedArray.
    • *
    * @package Ds * @template TValue * @extends Collection */ interface Sequence extends Collection, ArrayAccess { /** * Ensures that enough memory is allocated for a required capacity. * This removes the need to reallocate the internal as values are added. * * @param int $capacity The number of values for which capacity should * be allocated.

    Note: Capacity will stay the same if this value is * less than or equal to the current capacity.

    * @link https://www.php.net/manual/en/ds-sequence.allocate.php */ public function allocate(int $capacity): void; /** * Updates all values by applying a callback function to each value in * the sequence. * @param callable(TValue): TValue $callback A callable to apply to each value in the * sequence. The callback should return what the value should be * replaced by. * callback ( mixed $value ) : mixed * @link https://www.php.net/manual/en/ds-sequence.apply.php */ public function apply(callable $callback): void; /** * Returns the current capacity. * @return int The current capacity. * @link https://www.php.net/manual/en/ds-sequence.capacity.php */ public function capacity(): int; /** * Determines if the sequence contains all values. * @param TValue ...$values Values to check. * @return bool FALSE if any of the provided values are not in the * sequence, TRUE otherwise. * @link https://www.php.net/manual/en/ds-sequence.contains.php */ public function contains(...$values): bool; /** * Creates a new sequence using a callable to determine which values * to include. * @param null|callable(TValue): bool $callback Optional callable which returns TRUE if the * value should be included, FALSE otherwise. If a callback is not * provided, only values which are TRUE (see converting to boolean) will * be included. * callback ( mixed $value ) : bool * @return Sequence A new sequence containing all the values for which * either the callback returned TRUE, or all values that convert to * TRUE if a callback was not provided. * @link https://www.php.net/manual/en/ds-sequence.filter.php */ public function filter(?callable $callback = null); /** * Returns the index of the value, or FALSE if not found. * @param TValue $value The value to find. * @return int|false The index of the value, or FALSE if not found. * @link https://www.php.net/manual/en/ds-sequence.find.php */ public function find($value); /** * Returns the first value in the sequence. * @return TValue The first value in the sequence. * @throws UnderflowException if empty. * @link https://www.php.net/manual/en/ds-sequence.first.php */ public function first(); /** * Returns the value at a given index. * @param int $index The index to access, starting at 0. * @return TValue The value at the requested index. * @throws OutOfRangeException if the index is not valid. * @link https://www.php.net/manual/en/ds-sequence.get.php */ public function get(int $index); /** * Inserts values into the sequence at a given index. * * @param int $index The index at which to insert. 0 <= index <= count *

    Note: You can insert at the index equal to the number of values.

    * @param TValue ...$values The value or values to insert. * @throws OutOfRangeException if the index is not valid. * @link https://www.php.net/manual/en/ds-sequence.insert.php */ public function insert(int $index, ...$values): void; /** * Joins all values together as a string using an optional separator * between each value. * @param string $glue An optional string to separate each value. * @return string All values of the sequence joined together as a * string. * @link https://www.php.net/manual/en/ds-sequence.join.php */ public function join(string $glue = ''): string; /** * Returns the last value in the sequence. * @return TValue The last value in the sequence. * @throws UnderflowException if empty. * @link https://www.php.net/manual/en/ds-sequence.last.php */ public function last(); /** * Returns the result of applying a callback function to each value in * the sequence. * @template TNewValue * @param callable(TValue): TNewValue $callback A callable to apply to each value in the * sequence. * The callable should return what the new value will be in the new * sequence. * callback ( mixed $value ) : mixed * @return Sequence The result of applying a callback to each value in * the sequence.

    Note: The values of the current instance won't be * affected.

    * @link https://www.php.net/manual/en/ds-sequence.map.php */ public function map(callable $callback): Sequence; /** * Returns the result of adding all given values to the sequence. * @template TValue2 * @param iterable $values A traversable object or an array. * @return Sequence The result of adding all given values to the * sequence, effectively the same as adding the values to a copy, * then returning that copy. * @link https://www.php.net/manual/en/ds-sequence.merge.php */ public function merge($values): Sequence; /** * Removes and returns the last value. * @return TValue The removed last value. * @throws UnderflowException if empty. * @link https://www.php.net/manual/en/ds-sequence.pop.php */ public function pop(); /** * Adds values to the end of the sequence. * @param TValue ...$values The values to add. */ public function push(...$values): void; /** * Reduces the sequence to a single value using a callback function. * @template TCarry * @param callable(TCarry, TValue): TCarry $callback

    * * callback ( mixed $carry , mixed $value ) : mixed * $carry The return value of the previous callback, or initial if it's * the first iteration.
    * $value The value of the current iteration. *

    * @param TCarry $initial The initial value of the carry value. Can be NULL. * @return TCarry The return value of the final callback. * @link https://www.php.net/manual/en/ds-sequence.reduce.php */ public function reduce(callable $callback, $initial = null); /** * Removes and returns a value by index. * @param int $index The index of the value to remove. * @return TValue The value that was removed. * @link https://www.php.net/manual/en/ds-sequence.remove.php */ public function remove(int $index); /** * Reverses the sequence in-place. * @link https://www.php.net/manual/en/ds-sequence.reverse.php */ public function reverse(): void; /** * Returns a reversed copy of the sequence. * @return Sequence A reversed copy of the sequence. *

    Note: The current instance is not affected.

    */ public function reversed(); /** * Rotates the sequence by a given number of rotations, which is * equivalent to successively calling * $sequence->push($sequence->shift()) if the number of rotations is * positive, or $sequence->unshift($sequence->pop()) if negative. * @param int $rotations The number of times the sequence should be * rotated. * @link https://www.php.net/manual/en/ds-sequence.rotate.php */ public function rotate(int $rotations): void; /** * Updates a value at a given index. * @param int $index The index of the value to update. * @param TValue $value The new value. * @throws OutOfRangeException if the index is not valid. * @link https://www.php.net/manual/en/ds-sequence.set.php */ public function set(int $index, $value): void; /** * Removes and returns the first value. * @return TValue * @throws UnderflowException if empty. * @link https://www.php.net/manual/en/ds-sequence.shift.php */ public function shift(); /** * Creates a sub-sequence of a given range. * @param int $index The index at which the sub-sequence starts. * If positive, the sequence will start at that index in the sequence. * If negative, the sequence will start that far from the end. * @param int|null $length If a length is given and is positive, the * resulting sequence will have up to that many values in it. If the * length results in an overflow, only values up to the end of the * sequence will be included. If a length is given and is negative, * the sequence will stop that many values from the end. If a length * is not provided, the resulting sequence will contain all values * between the index and the end of the sequence. * @return Sequence A sub-sequence of the given range. * @link https://www.php.net/manual/en/ds-sequence.slice.php */ public function slice(int $index, int $length = null); /** * Sorts the sequence in-place, using an optional comparator function. * @param callable(TValue, TValue): int|null $comparator The comparison function must return * an integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647.

    * callback ( mixed $a, mixed $b ) : int

    *

    Caution: Returning non-integer values from the comparison * function, such as float, will result in an internal cast to integer * of the callback's return value. So values such as 0.99 and 0.1 will * both be cast to an integer value of 0, which will compare such * values as equal.

    * @link https://www.php.net/manual/en/ds-sequence.sort.php */ public function sort(?callable $comparator = null): void; /** * Returns a sorted copy, using an optional comparator function. * @param callable(TValue, TValue): int|null $comparator The comparison function must return * an integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647.

    * callback ( mixed $a, mixed $b ) : int

    *

    Caution: Returning non-integer values from the comparison * function, such as float, will result in an internal cast to integer * of the callback's return value. So values such as 0.99 and 0.1 will * both be cast to an integer value of 0, which will compare such * values as equal.

    * @return Sequence Returns a sorted copy of the sequence. * @link https://www.php.net/manual/en/ds-sequence.sort.php */ public function sorted(?callable $comparator = null); /** * Returns the sum of all values in the sequence. *

    Note: Arrays and objects are considered equal to zero when * calculating the sum.

    * @return float|int The sum of all the values in the sequence as * either a float or int depending on the values in the sequence. */ public function sum(): float|int; /** * Adds values to the front of the sequence, moving all the current * values forward to make room for the new values. * @param TValue ...$values The values to add to the front of the sequence. *

    Note: Multiple values will be added in the same order that they * are passed.

    */ public function unshift(...$values): void; } /** * A Vector is a sequence of values in a contiguous buffer that grows and * shrinks automatically. It’s the most efficient sequential structure * because a value’s index is a direct mapping to its index in the buffer, * and the growth factor isn't bound to a specific multiple or exponent. *

    *

    *

    Strengths *
      *
    • Supports array syntax (square brackets).
    • *
    • Uses less overall memory than an array for the same number of values.
    • *
    • Automatically frees allocated memory when its size drops low enough.
    • *
    • Capacity does not have to be a power of 2.
    • *
    • get(), set(), push(), pop() are all O(1)
    • *
    *

    *

    Weaknesses *
      *
    • shift(), unshift(), insert() and remove() are all O(n).
    • *
    * * @link https://www.php.net/manual/en/class.ds-vector.php * * @package Ds * @template TValue * @implements Sequence */ class Vector implements Sequence { public const MIN_CAPACITY = 10; /** * Creates a new instance, using either a traversable object or an array for the initial values. * * @param array $values */ public function __construct($values = []) {} /** * Ensures that enough memory is allocated for a required capacity. * This removes the need to reallocate the internal as values are added. * @param int $capacity The number of values for which capacity should * be allocated. *

    Note: Capacity will stay the same if this value is less than or * equal to the current capacity.

    * @link https://www.php.net/manual/en/ds-vector.allocate.php */ public function allocate(int $capacity): void {} /** * Updates all values by applying a callback function to each value in * the vector. * @param callable(TValue): TValue $callback * callback ( mixed $value ) : mixed * A callable to apply to each value in the vector. The callback should * return what the value should be replaced by. * @link https://www.php.net/manual/en/ds-vector.apply.php */ public function apply(callable $callback): void {} /** * Returns the current capacity. * @return int The current capacity. * @link https://www.php.net/manual/en/ds-vector.capacity.php */ public function capacity(): int {} /** * Removes all values from the vector. * @link https://www.php.net/manual/en/ds-vector.clear.php */ public function clear(): void {} /** * Determines if the vector contains all values. * @param TValue ...$values Values to check. * @return bool FALSE if any of the provided values are not in the * vector, TRUE otherwise. * @link https://www.php.net/manual/en/ds-vector.contains.php */ public function contains(...$values): bool {} /** *Returns a shallow copy of the vector. * @return Vector Returns a shallow copy of the vector. */ public function copy(): Vector {} /** * Creates a new vector using a callable to determine which values to * include. * * @param null|callable(TValue): bool $callback * Optional callable which returns TRUE if the value should be included, * FALSE otherwise. If a callback is not provided, only values which are * TRUE (see converting to boolean) will be included. * callback ( mixed $value ) : bool * @return Vector A new vector containing all the values for which * either the callback returned TRUE, or all values that convert to * TRUE if a callback was not provided. * @link https://www.php.net/manual/en/ds-vector.filter.php */ public function filter(?callable $callback = null): Vector {} /** * Returns the index of the value, or FALSE if not found. * @param TValue $value The value to find. * @return int|false The index of the value, or FALSE if not found. *

    Note: Values will be compared by value and by type.

    * @link https://www.php.net/manual/en/ds-vector.find.php */ public function find($value) {} /** * Returns the first value in the vector. * @return TValue * @throws UnderflowException if empty. * @link https://www.php.net/manual/en/ds-vector.first.php */ public function first() {} /** * Returns the value at a given index. * @param int $index The index to access, starting at 0. * @return TValue * @link https://www.php.net/manual/en/ds-vector.get.php */ public function get(int $index) {} /** * @return Traversable */ public function getIterator(): Traversable {} /** * Inserts values into the sequence at a given index. * * @param int $index The index at which to insert. 0 <= index <= count * Note:
    * You can insert at the index equal to the number of values. * @param array ...$values The value or values to insert. * @link https://www.php.net/manual/en/ds-vector.insert.php */ public function insert(int $index, ...$values): void {} /** * Joins all values together as a string using an optional separator between each value. * * @param string|null $glue An optional string to separate each value. * @return string All values of the sequence joined together as a string. * @link https://www.php.net/manual/en/ds-vector.join.php */ public function join(?string $glue = null): string {} /** * Returns the last value in the sequence. * * @return TValue The last value in the sequence. * @link https://www.php.net/manual/en/ds-vector.last.php */ public function last() {} /** * Returns the result of applying a callback function to each value in the sequence. * * @template TNewValue * @param callable(TValue): TNewValue $callback A callable to apply to each value in the sequence. *
    The callable should return what the new value will be in the new sequence. * * @return Vector * @link https://www.php.net/manual/en/ds-vector.map.php */ public function map(callable $callback): Vector {} /** * Returns the result of adding all given values to the sequence. * * @template TValue2 * @param iterable $values A traversable object or an array. * @return Vector The result of adding all given values to the sequence, effectively the same as adding the * values to a copy, then returning that copy.
    * Note:
    * The current instance won't be affected. * @link https://www.php.net/manual/en/ds-vector.merge.php */ public function merge($values): Vector {} /** * Removes and returns the last value. * * @return TValue * @link https://www.php.net/manual/en/ds-vector.pop.php */ public function pop() {} /** * Adds values to the end of the sequence. * @param TValue ...$values * @link https://www.php.net/manual/en/ds-vector.push.php */ public function push(...$values): void {} /** * Reduces the sequence to a single value using a callback function. * @template TCarry * @param callable(TCarry, TValue): TCarry $callback
    * callback ( mixed $carry , mixed $value ) : mixed
    * carry The return value of the previous callback, or initial if it's the first iteration.
    * value The value of the current iteration. * @param TCarry $initial The initial value of the carry value. Can be NULL. * * @return TCarry The return value of the final callback. * * @link https://www.php.net/manual/en/ds-vector.reduce.php */ public function reduce(callable $callback, $initial = null) {} /** * Removes and returns a value by index. * @param int $index The index of the value to remove. * @return TValue The value that was removed. * @link https://www.php.net/manual/en/ds-vector.remove.php */ public function remove(int $index) {} /** * Reverses the sequence in-place. * @link https://www.php.net/manual/en/ds-vector.reverse.php */ public function reverse(): void {} /** * Returns a reversed copy of the sequence. * @return Vector A reversed copy of the sequence.
    * Note: The current instance is not affected. * @link https://www.php.net/manual/en/ds-vector.reversed.php */ public function reversed(): Vector {} /** * Rotates the sequence by a given number of rotations, which is * equivalent to successively calling $sequence->push($sequence->shift()) * if the number of rotations is positive, or $sequence->unshift($sequence->pop()) * if negative. * * @link https://www.php.net/manual/en/ds-vector.rotate.php * * @param int $rotations The number of times the sequence should be rotated. */ public function rotate(int $rotations): void {} /** * Updates a value at a given index. * * @link https://www.php.net/manual/en/ds-vector.set.php * * @param int $index The index of the value to update. * @param TValue $value The new value. * * @throws OutOfRangeException if the index is not valid. */ public function set(int $index, $value): void {} /** * Removes and returns the first value. * * @link https://www.php.net/manual/en/ds-vector.shift.php * * @return TValue The first value, which was removed. * @throws UnderflowException if empty. */ public function shift() {} /** * Creates a sub-sequence of a given range. * @link https://www.php.net/manual/en/ds-vector.slice.php * @param int $index The index at which the sub-sequence starts. If * positive, the sequence will start at that * index in the sequence. If negative, the sequence will start that * far from the end. * @param int|null $length If a length is given and is positive, the * resulting sequence will have up to that many values in it. If the * length results in an overflow, only values up to the end of the * sequence will be included. If a length is given and is negative, * the sequence will stop that many values from the end. If a length * is not provided, the resulting sequence will contain all values * between the index and the end of the sequence. * @return Vector */ public function slice(int $index, int $length = null): Vector {} /** * Sorts the sequence in-place, using an optional comparator function. * @link https://www.php.net/manual/en/ds-vector.sort.php * @param callable(TValue, TValue): int|null $comparator The comparison function must return an * integer less than, equal to, or greater * than zero if the first argument is considered to be respectively less than, equal to, or greater than the * second. Note that before PHP 7.0.0 this integer had to be in the * range from -2147483648 to 2147483647.
    * callback ( mixed $a, mixed $b ) : int * Caution: Returning non-integer values from the comparison function, * such as float, will result in an * internal cast to integer of the callback's return value. So values * such as 0.99 and 0.1 will both be cast to an integer value of 0, * which will compare such values as equal. */ public function sort(?callable $comparator = null): void {} /** * Returns a sorted copy, using an optional comparator function. * @link https://www.php.net/manual/en/ds-vector.sorted.php * @param callable(TValue, TValue): int|null $comparator The comparison function must return an integer less than, equal to, or * greater than zero if the first argument is considered to be respectively less than, equal to, or greater * than the second. Note that before PHP 7.0.0 this integer had to be in the range from -2147483648 to * 2147483647.
    * callback ( mixed $a, mixed $b ) : int * Caution: Returning non-integer values from the comparison function, such as float, will result in an * internal cast to integer of the callback's return value. So values such as 0.99 and 0.1 will both be cast to * an integer value of 0, which will compare such values as equal. * @return Vector Returns a sorted copy of the sequence. */ public function sorted(?callable $comparator = null): Vector {} /** * Returns the sum of all values in the sequence.
    * Note: Arrays and objects are considered equal to zero when * calculating the sum. * @link https://www.php.net/manual/en/ds-vector.sum.php * @return float */ public function sum(): float {} /** * Adds values to the front of the sequence, moving all the current * values forward to make room for the new values. * @param TValue ...$values The values to add to the front of the sequence.
    * Note: Multiple values will be added in the same order that they are * passed. * @link https://www.php.net/manual/en/ds-vector.unshift.php */ public function unshift($values): void {} /** * Count elements of an object * @link https://php.net/manual/en/ds-vector.count.php * @return int The custom count as an integer. *

    * The return value is cast to an integer. *

    * @since 5.1 */ public function count(): int {} /** * Returns whether the collection is empty. * @link https://www.php.net/manual/en/ds-vector.isempty.php * @return bool */ public function isEmpty(): bool {} /** * Converts the collection to an array. *

    Note: Casting to an array is not supported yet.

    * @link https://www.php.net/manual/en/ds-vector.toarray.php * @return array An array containing all the values in the same order as * the collection. */ public function toArray(): array {} /** * Specify data which should be serialized to JSON * @link https://php.net/manual/en/ds-vector.jsonserialize.php * @return mixed data which can be serialized by json_encode, * which is a value of any type other than a resource. * @since 5.4 */ public function jsonSerialize() {} /** * @param int $offset */ public function offsetExists(mixed $offset): bool {} /** * @param int $offset * * @return TValue */ public function offsetGet(mixed $offset) {} /** * @param int $offset * @param TValue $value */ public function offsetSet(mixed $offset, mixed $value) {} /** * @param int $offset */ public function offsetUnset(mixed $offset): void {} } /** * @template TValue * @implements Sequence */ class Deque implements Sequence { /** * Creates a new instance, using either a traversable object or an array for the initial values. * @param TValue ...$values A traversable object or an array to use for the initial values. * * @link https://www.php.net/manual/en/ds-deque.construct.php */ public function __construct(...$values) {} /** * Count elements of an object * @link https://php.net/manual/en/countable.count.php * @return int The custom count as an integer. *

    * The return value is cast to an integer. *

    * @since 5.1 */ public function count(): int {} /** * Removes all values from the deque. * @link https://www.php.net/manual/en/ds-deque.clear.php */ public function clear(): void {} /** * Returns a shallow copy of the deque. * @link https://www.php.net/manual/en/ds-deque.copy.php * @return Deque */ public function copy(): Collection {} /** * @return Traversable */ public function getIterator(): Traversable {} /** * Returns whether the deque is empty. * @link https://www.php.net/manual/en/ds-deque.isempty.php * @return bool */ public function isEmpty(): bool {} /** * Converts the deque to an array. *

    Note: Casting to an array is not supported yet.

    * @link https://www.php.net/manual/en/ds-deque.toarray.php * @return array An array containing all the values in the same order as * the deque. */ public function toArray(): array {} /** * Ensures that enough memory is allocated for a required capacity. * This removes the need to reallocate the internal as values are added. * * @param int $capacity The number of values for which capacity should * be allocated.

    Note: Capacity will stay the same if this value is * less than or equal to the current capacity.

    *

    Note: Capacity will always be rounded up to the nearest power of 2.

    * @link https://www.php.net/manual/en/ds-deque.allocate.php */ public function allocate(int $capacity): void {} /** * Updates all values by applying a callback function to each value in * the deque. * @param callable(TValue): TValue $callback A callable to apply to each value in the * deque. The callback should return what the value should be * replaced by.

    * callback ( mixed $value ) : mixed *

    * @link https://www.php.net/manual/en/ds-deque.apply.php */ public function apply(callable $callback): void {} /** * Returns the current capacity. * @return int The current capacity. * @link https://www.php.net/manual/en/ds-deque.capacity.php */ public function capacity(): int {} /** * Determines if the deque contains all values. * @param TValue $values Values to check. * @return bool FALSE if any of the provided values are not in the * deque, TRUE otherwise. * @link https://www.php.net/manual/en/ds-deque.contains.php */ public function contains(...$values): bool {} /** * Creates a new deque using a callable to determine which values * to include. * @param null|callable(TValue): bool $callback Optional callable which returns TRUE if the * value should be included, FALSE otherwise. If a callback is not * provided, only values which are TRUE (see converting to boolean) will * be included.

    * callback ( mixed $value ) : bool *

    * @return Deque A new deque containing all the values for which * either the callback returned TRUE, or all values that convert to * TRUE if a callback was not provided. * @link https://www.php.net/manual/en/ds-deque.filter.php */ public function filter(?callable $callback = null): Deque {} /** * Returns the index of the value, or FALSE if not found. * @param TValue $value The value to find. * @return int|false The index of the value, or FALSE if not found. * @link https://www.php.net/manual/en/ds-deque.find.php */ public function find($value) {} /** * Returns the first value in the deque. * @return TValue The first value in the deque. * @throws UnderflowException if empty. * @link https://www.php.net/manual/en/ds-deque.first.php */ public function first() {} /** * Returns the value at a given index. * @param int $index The index to access, starting at 0. * @return TValue The value at the requested index. * @throws OutOfRangeException if the index is not valid. * @link https://www.php.net/manual/en/ds-deque.get.php */ public function get(int $index) {} /** * Inserts values into the deque at a given index. * * @param int $index The index at which to insert. 0 <= index <= count *

    Note: You can insert at the index equal to the number of values.

    * @param TValue ...$values The value or values to insert. * @throws OutOfRangeException if the index is not valid. * @link https://www.php.net/manual/en/ds-deque.insert.php */ public function insert(int $index, ...$values): void {} /** * Joins all values together as a string using an optional separator * between each value. * @param string $glue An optional string to separate each value. * @return string All values of the deque joined together as a * string. * @link https://www.php.net/manual/en/ds-deque.join.php */ public function join(string $glue = ''): string {} /** * Returns the last value in the deque. * @return TValue The last value in the deque. * @throws UnderflowException if empty. * @link https://www.php.net/manual/en/ds-deque.last.php */ public function last() {} /** * Returns the result of applying a callback function to each value in * the deque. * * @template TNewValue * @param callable(TValue): TNewValue $callback A callable to apply to each value in the * deque. * The callable should return what the new value will be in the new * deque. * callback ( mixed $value ) : mixed * * @return Deque The result of applying a callback to each value in * the deque. *

    Note: The values of the current instance won't be * affected.

    * @link https://www.php.net/manual/en/ds-deque.map.php */ public function map(callable $callback): Deque {} /** * Returns the result of adding all given values to the deque. * @template TValue2 * @param iterable $values A traversable object or an array. * @return Deque The result of adding all given values to the * deque, effectively the same as adding the values to a copy, * then returning that copy. * @link https://www.php.net/manual/en/ds-deque.merge.php */ public function merge($values): Deque {} /** * Removes and returns the last value. * @return TValue The removed last value. * @throws UnderflowException if empty. * @link https://www.php.net/manual/en/ds-deque.pop.php */ public function pop() {} /** * Adds values to the end of the deque. * @param TValue ...$values The values to add. */ public function push(...$values): void {} /** * Reduces the deque to a single value using a callback function. * @template TCarry * @param callable(TCarry, TValue): TCarry $callback * callback ( mixed $carry , mixed $value ) : mixed * $carry The return value of the previous callback, or initial if it's * the first iteration.

    * $value The value of the current iteration. *

    * @param TCarry $initial The initial value of the carry value. Can be NULL. * @return TCarry The return value of the final callback. * @link https://www.php.net/manual/en/ds-deque.reduce.php */ public function reduce(callable $callback, $initial = null) {} /** * Removes and returns a value by index. * @param int $index The index of the value to remove. * @return TValue The value that was removed. * @link https://www.php.net/manual/en/ds-deque.remove.php */ public function remove(int $index) {} /** * Reverses the deque in-place. * @link https://www.php.net/manual/en/ds-deque.reverse.php */ public function reverse(): void {} /** * Returns a reversed copy of the deque. * @return Deque A reversed copy of the deque. *

    Note: The current instance is not affected.

    */ public function reversed(): Deque {} /** * Rotates the deque by a given number of rotations, which is * equivalent to successively calling * $deque->push($deque->shift()) if the number of rotations is * positive, or $deque->unshift($deque->pop()) if negative. * @param int $rotations The number of times the deque should be * rotated. * @link https://www.php.net/manual/en/ds-deque.rotate.php */ public function rotate(int $rotations): void {} /** * Updates a value at a given index. * @param int $index The index of the value to update. * @param TValue $value The new value. * @throws OutOfRangeException if the index is not valid. * @link https://www.php.net/manual/en/ds-deque.set.php */ public function set(int $index, $value): void {} /** * Removes and returns the first value. * @return TValue * @throws UnderflowException if empty. * @link https://www.php.net/manual/en/ds-deque.shift.php */ public function shift() {} /** * Creates a sub-deque of a given range. * @param int $index The index at which the sub-deque starts. * If positive, the deque will start at that index in the deque. * If negative, the deque will start that far from the end. * @param int|null $length If a length is given and is positive, the * resulting deque will have up to that many values in it. If the * length results in an overflow, only values up to the end of the * deque will be included. If a length is given and is negative, * the deque will stop that many values from the end. If a length * is not provided, the resulting deque will contain all values * between the index and the end of the deque. * @return Deque A sub-deque of the given range. * @link https://www.php.net/manual/en/ds-deque.slice.php */ public function slice(int $index, int $length = null): Deque {} /** * Sorts the deque in-place, using an optional comparator function. * @param callable(TValue, TValue): int|null $comparator The comparison function must return * an integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647. * callback ( mixed $a, mixed $b ) : int *

    Caution: Returning non-integer values from the comparison * function, such as float, will result in an internal cast to integer * of the callback's return value. So values such as 0.99 and 0.1 will * both be cast to an integer value of 0, which will compare such * values as equal.

    * @link https://www.php.net/manual/en/ds-deque.sort.php */ public function sort(?callable $comparator = null): void {} /** * Returns a sorted copy, using an optional comparator function. * @param callable(TValue, TValue): int|null $comparator The comparison function must return * an integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647. * callback ( mixed $a, mixed $b ) : int *

    Caution: Returning non-integer values from the comparison * function, such as float, will result in an internal cast to integer * of the callback's return value. So values such as 0.99 and 0.1 will * both be cast to an integer value of 0, which will compare such * values as equal.

    * @return Deque Returns a sorted copy of the deque. * @link https://www.php.net/manual/en/ds-deque.sort.php */ public function sorted(?callable $comparator = null): Deque {} /** * Returns the sum of all values in the deque. *

    Note: Arrays and objects are considered equal to zero when * calculating the sum.

    * @return float|int The sum of all the values in the deque as * either a float or int depending on the values in the deque. */ public function sum(): float|int {} /** * Adds values to the front of the deque, moving all the current * values forward to make room for the new values. * @param TValue ...$values The values to add to the front of the deque. *

    Note: Multiple values will be added in the same order that they * are passed.

    */ public function unshift(...$values): void {} /** * Specify data which should be serialized to JSON * @link https://php.net/manual/en/ds-vector.jsonserialize.php * @return mixed data which can be serialized by json_encode, * which is a value of any type other than a resource. * @since 5.4 */ public function jsonSerialize() {} /** * @param int $offset */ public function offsetExists(mixed $offset): bool {} /** * @param int $offset * * @return TValue */ public function offsetGet(mixed $offset) {} /** * @param int $offset * @param TValue $value */ public function offsetSet(mixed $offset, mixed $value) {} /** * @param int $offset */ public function offsetUnset(mixed $offset): void {} } /** * @template TKey * @template TValue * @implements Collection */ class Map implements Collection, ArrayAccess { /** * Creates a new instance, using either a traversable object or an array for the initial values. * @param iterable ...$values A traversable object or an array to use for the initial values. * * @link https://www.php.net/manual/en/ds-map.construct.php */ public function __construct(...$values) {} /** * Allocates enough memory for a required capacity. * * @param int $capacity The number of values for which capacity should be allocated.
    *

    Note: Capacity will stay the same if this value is less than or equal to the current capacity.

    * Capacity will always be rounded up to the nearest power of 2. * * @link https://www.php.net/manual/en/ds-map.allocate.php */ public function allocate(int $capacity) {} /** * Updates all values by applying a callback function to each value in the map. * * @param callable(TKey, TValue): TValue $callback A callable to apply to each value in the map. The callback should return what * the value should be replaced by. * * @link https://www.php.net/manual/en/ds-map.apply.php */ public function apply(callable $callback) {} /** * Returns the current capacity. * * @return int * * @link https://www.php.net/manual/en/ds-map.capacity.php */ public function capacity(): int {} /** * Count elements of an object * @link https://php.net/manual/en/countable.count.php * @return int The custom count as an integer. *

    *

    * The return value is cast to an integer. * @since 5.1 */ public function count(): int {} /** * Removes all values from the collection. * @link https://www.php.net/manual/en/ds-collection.clear.php */ public function clear(): void {} /** * Returns a shallow copy of the collection. * @link https://www.php.net/manual/en/ds-collection.copy.php * @return Map */ public function copy(): Collection {} /** * Returns the result of removing all keys from the current instance that are present in a given map. * * A \ B = {x ∈ A | x ∉ B} * * @template TValue2 * @param Map $map The map containing the keys to exclude in the resulting map. * * @return Map The result of removing all keys from the current instance that are present in a given map. * * @link https://www.php.net/manual/en/ds-map.diff.php */ public function diff(Map $map): Map {} /** * Creates a new map using a callable to determine which pairs to include * * @param null|callable(TKey, TValue): bool $callback Optional callable which returns TRUE if the pair should be included, FALSE * otherwise. If a callback is not provided, only values which are TRUE (see converting to boolean) will be included. * * @return Map * * @link https://www.php.net/manual/en/ds-map.filter.php */ public function filter(?callable $callback = null): Map {} /** * Returns the first pair in the map * * @return Pair The first pair in the map. * * @throws UnderflowException if empty * * @link https://www.php.net/manual/en/ds-map.first.php */ public function first(): Pair {} /** * Returns the value for a given key, or an optional default value if the key could not be found. *

    * Note: Keys of type object are supported. If an object implements Ds\Hashable, equality will be * determined by the object's equals function. If an object does not implement Ds\Hashable, objects must be references to the same instance to be considered equal. *

    *

    * Note: You can also use array syntax to access values by key, eg. $map["key"]. *

    *

    * Caution: Be careful when using array syntax. Scalar keys will be coerced to integers by the engine. For * example, $map["1"] will attempt to access int(1), while $map->get("1") will correctly look up the string key. *

    * * @template TDefault * @param TKey $key The key to look up. * @param TDefault $default The optional default value, returned if the key could not be found. * * @return TValue|TDefault The value mapped to the given key, or the default value if provided and the key could not be found in the map. * * @throws OutOfBoundsException if the key could not be found and a default value was not provided. * * @link https://www.php.net/manual/en/ds-map.get.php */ public function get($key, $default = null) {} /** * @return Traversable */ public function getIterator(): Traversable {} /** * Determines whether the map contains a given key * * @param TKey $key The key to look for. * * @return bool Returns TRUE if the key could found, FALSE otherwise. * * @link https://www.php.net/manual/en/ds-map.hasKey.php */ public function hasKey($key): bool {} /** * Determines whether the map contains a given value * * @param TValue $value The value to look for. * * @return bool Returns TRUE if the value could found, FALSE otherwise. * * @link https://www.php.net/manual/en/ds-map.hasValue.php */ public function hasValue($value): bool {} /** * Creates a new map containing the pairs of the current instance whose * keys are also present in the given map. In other words, returns a * copy of the current instance with all keys removed that are not also * in the other map. * * A ∩ B = {x : x ∈ A ∧ x ∈ B} * *

    Note: Values from the current instance will be kept.

    * * @template TKey2 * @template TValue2 * @param Map $map The other map, containing the keys to intersect with. * * @return Map The key intersection of the current instance and another map. * * @link https://www.php.net/manual/en/ds-map.intersect.php */ public function intersect(Map $map): Map {} /** * Returns whether the collection is empty. * * @link https://www.php.net/manual/en/ds-collection.isempty.php * * @return bool Returns TRUE if the map is empty, FALSE otherwise. * * @link https://www.php.net/manual/en/ds-map.isempty.php */ public function isEmpty(): bool {} /** * Converts the map to an array. *

    Note: Casting to an array is not supported yet.

    *

    Caution: Maps where non-scalar keys are can't be converted to an * array. *

    *

    Caution: An array will treat all numeric keys as integers, eg. * "1" and 1 as keys in the map will only result in 1 being included in * the array. *

    * * @link https://www.php.net/manual/en/ds-map.toarray.php * @return array An array containing all the values in the same order as * the map. */ public function toArray(): array {} /** * Specify data which should be serialized to JSON * @link https://php.net/manual/en/jsonserializable.jsonserialize.php * @return mixed data which can be serialized by json_encode, * which is a value of any type other than a resource. * @since 5.4 */ public function jsonSerialize() {} /** * Returns a set containing all the keys of the map, in the same order. * @link https://www.php.net/manual/en/ds-map.keys.php * @return Set A Ds\Set containing all the keys of the map. */ public function keys(): Set {} /** * Sorts the map in-place by key, using an optional comparator function. * @param callable(TKey, TKey):int|null $comparator The comparison function must return * an integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647. * callback ( mixed $a, mixed $b ) : int *

    Caution: Returning non-integer values from the comparison function, such * as float, will result in an internal cast to integer of the * callback's return value. So values such as 0.99 and 0.1 will both be * cast to an integer value of 0, which will compare such values as * equal.

    * @link https://www.php.net/manual/en/ds-map.ksort.php */ public function ksort(?callable $comparator = null) {} /** * Returns a copy sorted by key, using an optional comparator function. * @param callable(TKey, TKey): int|null $comparator The comparison function must return * an integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647. * callback ( mixed $a, mixed $b ) : int *

    Caution: Returning non-integer values from the comparison function, such * as float, will result in an internal cast to integer of the * callback's return value. So values such as 0.99 and 0.1 will both be * cast to an integer value of 0, which will compare such values as * equal.

    * @return Map Returns a copy of the map, sorted by key. * @link https://www.php.net/manual/en/ds-map.ksorted.php */ public function ksorted(?callable $comparator = null): Map {} /** * Returns the last pair of the map. * @return Pair The last pair of the map. * @throws UnderflowException if empty * @link https://www.php.net/manual/en/ds-map.last.php */ public function last(): Pair {} /** * Returns the result of applying a callback function to each value of * the map. * @template TNewValue * @param callable(TKey, TValue): TNewValue $callback A callable to apply to each value in the * map. The callable should return what the key will be mapped to in the * resulting map. * callback ( mixed $key , mixed $value ) : mixed * @return Map The result of applying a callback to each value in the * map. * * Note: The keys and values of the current instance won't be affected. * * @link https://www.php.net/manual/en/ds-map.map.php */ public function map(callable $callback): Map {} /** * Returns the result of associating all keys of a given traversable * object or array with their corresponding values, combined with the * current instance. * @template TKey2 * @template TValue2 * @param iterable $values A traversable object or an array. * @return Map The result of associating all keys of a given traversable * object or array with their corresponding values, combined with the * current instance. * * Note: The current instance won't be affected. * * @link https://www.php.net/manual/en/ds-map.merge.php */ public function merge($values): Map {} /** * Returns a Ds\Sequence containing all the pairs of the map. * * @return Sequence> Ds\Sequence containing all the pairs of the map. * * @link https://www.php.net/manual/en/ds-map.pairs.php */ public function pairs(): Sequence {} /** * Associates a key with a value, overwriting a previous association if * one exists. * @param TKey $key The key to associate the value with. * @param TValue $value The value to be associated with the key. * * Note: Keys of type object are supported. If an object implements * Ds\Hashable, equality will be determined by the object's equals * function. If an object does not implement Ds\Hashable, objects must * be references to the same instance to be considered equal. * * Note: You can also use array syntax to associate values by key, eg. * $map["key"] = $value. * * Caution: Be careful when using array syntax. Scalar keys will be * coerced to integers by the engine. For example, $map["1"] will * attempt to access int(1), while $map->get("1") will correctly look up * the string key. * * @link https://www.php.net/manual/en/ds-map.put.php */ public function put($key, $value) {} /** * Associates all key-value pairs of a traversable object or array. * * Note: Keys of type object are supported. If an object implements * Ds\Hashable, equality will be determined * by the object's equals function. If an object does not implement * Ds\Hashable, objects must be references to the same instance to be * considered equal. * * @param iterable $pairs traversable object or array. * * @link https://www.php.net/manual/en/ds-map.putall.php */ public function putAll($pairs) {} /** * Reduces the map to a single value using a callback function. * * @template TCarry * @param callable(TCarry, TKey, TValue): TCarry $callback * callback ( mixed $carry , mixed $key , mixed $value ) : mixed * carry The return value of the previous callback, or initial if * it's the first iteration. * key The key of the current iteration. * value The value of the current iteration. * * @param TCarry $initial The initial value of the carry value. Can be * NULL. * * @return TCarry * @link https://www.php.net/manual/en/ds-map.reduce.php */ public function reduce(callable $callback, $initial) {} /** * Removes and returns a value by key, or return an optional default * value if the key could not be found. * * @template TDefault * @param TKey $key The key to remove. * @param TDefault $default The optional default value, returned if the key * could not be found. * * Note: Keys of type object are supported. If an object implements * Ds\Hashable, equality will be determined * by the object's equals function. If an object does not implement * Ds\Hashable, objects must be references to the same instance to be * considered equal. * * Note: You can also use array syntax to access values by key, eg. * $map["key"]. * * Caution: Be careful when using array syntax. Scalar keys will be * coerced to integers by the engine. For example, $map["1"] will * attempt to access int(1), while $map->get("1") will correctly look up * the string key. * * @return TValue|TDefault The value that was removed, or the default value if * provided and the key could not be found in the map. * * @throws OutOfBoundsException if the key could not be found and a * default value was not provided. * * @link https://www.php.net/manual/en/ds-map.remove.php */ public function remove($key, $default = null) {} /** * Reverses the map in-place. * * @link https://www.php.net/manual/en/ds-map.reverse.php */ public function reverse() {} /** * Returns a reversed copy of the map. * * @return Map A reversed copy of the map. * *

    Note: The current instance is not affected.

    * * @link https://www.php.net/manual/en/ds-map.reversed.php */ public function reversed(): Map {} /** * Returns the pair at a given zero-based position. * * @param int $position The zero-based positional index to return. * * @return Pair Returns the Ds\Pair at the given position. * * @throws OutOfRangeException if the position is not valid. * * @link https://www.php.net/manual/en/ds-map.skip.php */ public function skip(int $position): Pair {} /** * Returns a subset of the map defined by a starting index and length. * * @param int $index The index at which the range starts. If positive, * the range will start at that index in the map. If negative, the range * will start that far from the end. * * @param int|null $length If a length is given and is positive, the * resulting map will have up to that many pairs in it. If a length is * given and is negative, the range will stop that many pairs from the * end. If the length results in an overflow, only pairs up to the end * of the map will be included. If a length is not provided, the * resulting map will contain all pairs between the index and the end of * the map. * * @return Map A subset of the map defined by a starting index and * length. * * @link https://www.php.net/manual/en/ds-map.slice.php */ public function slice(int $index, ?int $length = null): Map {} /** * Sorts the map in-place by value, using an optional comparator * function. * * @param callable(TValue, TValue): int|null $comparator The comparison function must return * an integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647. * * callback ( mixed $a, mixed $b ) : int * * Caution: Returning non-integer values from the comparison function, * such as float, will result in an internal cast to integer of the * callback's return value. So values such as 0.99 and 0.1 will both be * cast to an integer value of 0, which will compare such values as * equal. * * @link https://www.php.net/manual/en/ds-map.sort.php */ public function sort(?callable $comparator = null) {} /** * Returns a copy, sorted by value using an optional comparator function. * * @param callable(TValue, TValue): int|null $comparator The comparison function must return * an integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647. * * callback ( mixed $a, mixed $b ) : int * * Caution: Returning non-integer values from the comparison function, * such as float, will result in an internal cast to integer of the * callback's return value. So values such as 0.99 and 0.1 will both be * cast to an integer value of 0, which will compare such values as * equal. * * @return Map * * @link https://www.php.net/manual/en/ds-map.sorted.php */ public function sorted(?callable $comparator = null): Map {} /** * Returns the sum of all values in the map. * * Note: Arrays and objects are considered equal to zero when * calculating the sum. * * @return float|int The sum of all the values in the map as either a * float or int depending on the values in the map. * * @link https://www.php.net/manual/en/ds-map.sum.php */ public function sum(): float|int {} /** * Creates a new map using values from the current instance and another * map. * * A ∪ B = {x: x ∈ A ∨ x ∈ B} * *

    Note: Values of the current instance will be overwritten by those * provided where keys are equal.

    * * @template TKey2 * @template TValue2 * @param Map $map The other map, to combine with the current instance. * * @return Map A new map containing all the pairs of the current * instance as well as another map. * * @link https://www.php.net/manual/en/ds-map.union.php */ public function union(Map $map): Map {} /** * Returns a sequence containing all the values of the map, in the same * order. * * @return Sequence A Ds\Sequence containing all the values of the map. * * @link https://www.php.net/manual/en/ds-map.values.php */ public function values(): Sequence {} /** * Creates a new map containing keys of the current instance as well as * another map, but not of both. * * A ⊖ B = {x : x ∈ (A \ B) ∪ (B \ A)} * * @template TKey2 * @template TValue2 * @param Map $map The other map. * * @return Map A new map containing keys in the current instance as well * as another map, but not in both. * * @link https://www.php.net/manual/en/ds-map.xor.php */ public function xor(Map $map): Map {} /** * @param TKey $offset */ public function offsetExists(mixed $offset): bool {} /** * @param TKey $offset * * @return TValue */ public function offsetGet(mixed $offset) {} /** * @param TKey $offset * @param TValue $value */ public function offsetSet(mixed $offset, mixed $value) {} /** * @param TKey $offset */ public function offsetUnset(mixed $offset): void {} } /** * A pair is used by Ds\Map to pair keys with values. * @package Ds * @template-covariant TKey * @template-covariant TValue */ class Pair implements JsonSerializable { /** * @var TKey */ public $key; /** * @var TValue */ public $value; /** * Creates a new instance using a given key and value. * * @param TKey $key * @param TValue $value * * @link https://php.net/manual/en/ds-pair.construct.php */ public function __construct($key = null, $value = null) {} /** * Removes all values from the pair. * * @link https://php.net/manual/en/ds-pair.clear.php */ public function clear() {} /** * Returns a shallow copy of the pair. * * @return Pair Returns a shallow copy of the pair. * * @link https://php.net/manual/en/ds-pair.copy.php */ public function copy(): Pair {} /** * Returns whether the pair is empty. * * @return bool Returns TRUE if the pair is empty, FALSE otherwise. * * @link https://php.net/manual/en/ds-pair.isempty.php */ public function isEmpty(): bool {} /** * Converts the pair to an array. * *

    Note: Casting to an array is not supported yet.

    * * @return array{key: TKey, value: TValue} An array containing all the values in the same order as * the pair. * * @link https://php.net/manual/en/ds-pair.toarray.php */ public function toArray(): array {} /** * Specify data which should be serialized to JSON * @link https://php.net/manual/en/ds-pair.jsonserialize.php * @return mixed data which can be serialized by json_encode, * which is a value of any type other than a resource. */ public function jsonSerialize() {} } /** * A Set is a sequence of unique values. This implementation uses the same * hash table as Ds\Map, where values are used as keys and the mapped value * is ignored. * * @link https://www.php.net/manual/en/class.ds-set.php * * @package Ds * @template TValue * @implements Collection */ class Set implements Collection, ArrayAccess { /** * Creates a new instance, using either a traversable object or an array * for the initial values. * * @param iterable $values A traversable object of an array to * use the initial values. * * @link https://php.net/manual/en/ds-set.construct.php */ public function __construct(iterable $values = []) {} /** * Adds all given values to the set that haven't already been added. * *

    Note: Values of type object are supported. If an object implements * Ds\Hashable, equality will be determined by the object's equals * function. If an object does not implement Ds\Hashable, objects must * be references to the same instance to be considered equal. * *

    Caution: All comparisons are strict (type and value). * * @param TValue ...$values Values to add to the set. * * @link https://php.net/manual/en/ds-set.add.php */ public function add(...$values) {} /** * Allocates enough memory for a required capacity. * * @param int $capacity The number of values for which capacity should * be allocated. * *

    Note: Capacity will stay the same if this value is less than or * equal to the current capacity. * *

    Capacity will always be rounded up to the nearest power of 2. * * @link https://php.net/manual/en/ds-set.allocate.php */ public function allocate(int $capacity) {} /** * Determines if the set contains all values. * *

    Values of type object are supported. If an object implements * Ds\Hashable, equality will be determined by the object's equals * function. If an object does not implement Ds\Hashable, objects must * be references to the same instance to be considered equal. * *

    Caution: All comparisons are strict (type and value). * * @param TValue ...$values Values to check. * * @return bool * * @link https://php.net/manual/en/ds-set.contains.php */ public function contains(...$values): bool {} /** * Returns the current capacity. * @link https://www.php.net/manual/en/ds-set.capacity.php * * @return int */ public function capacity(): int {} /** * Removes all values from the set. * @link https://www.php.net/manual/en/ds-set.clear.php */ public function clear(): void {} /** * Count elements of an object * @link https://php.net/manual/en/ds-set.count.php * @return int The custom count as an integer. *

    *

    * The return value is cast to an integer. * @since 5.1 */ public function count(): int {} /** * Returns a shallow copy of the set. * @link https://www.php.net/manual/en/ds-set.copy.php * @return Set */ public function copy(): Set {} /** * Creates a new set using values that aren't in another set. * * A \ B = {x ∈ A | x ∉ B} * * @link https://www.php.net/manual/en/ds-set.diff.php * * @template TValue2 * @param Set $set Set containing the values to exclude. * * @return Set A new set containing all values that were not in the * other set. */ public function diff(Set $set): Set {} /** * Creates a new set using a callable to determine which values to * include * * @link https://www.php.net/manual/en/ds-set.filter.php * * @param null|callable(TValue): bool $callback Optional callable which returns TRUE if the * value should be included, FALSE otherwise. * If a callback is not provided, only values which are TRUE (see * converting to boolean) will be included. * * @return Set A new set containing all the values for which either the * callback returned TRUE, or all values that convert to TRUE if a * callback was not provided. */ public function filter(?callable $callback = null): Set {} /** * Returns the first value in the set. * * @link https://www.php.net/manual/en/ds-set.first.php * * @return TValue The first value in the set. */ public function first() {} /** * Returns the value at a given index. * * @link https://www.php.net/manual/en/ds-set.get.php * * @param int $index The index to access, starting at 0. * * @return TValue The value at the requested index. */ public function get(int $index) {} /** * @return Traversable */ public function getIterator(): Traversable {} /** * Creates a new set using values common to both the current instance * and another set. In other words, returns a copy of the current * instance with all values removed that are not in the other set. * * A ∩ B = {x : x ∈ A ∧ x ∈ B} * * @link https://www.php.net/manual/en/ds-set.intersect.php * * @template TValue2 * @param Set $set The other set. * @return Set The intersection of the current instance and another set. */ public function intersect(Set $set): Set {} /** * Returns whether the set is empty. * @link https://www.php.net/manual/en/ds-set.isempty.php * * @return bool */ public function isEmpty(): bool {} /** * Joins all values together as a string using an optional separator * between each value. * * @link https://www.php.net/manual/en/ds-set.join.php * * @param null|string $glue An optional string to separate each value. * * @return string */ public function join(?string $glue = null): string {} /** * Returns the result of applying a callback function to each value in * the set. * @template TNewValue * @param callable(TValue): TNewValue $callback A callable to apply to each value in the * set. * The callable should return what the new value will be in the new * set. * callback ( mixed $value ) : mixed * @return Set The result of applying a callback to each value in * the set. *

    Note: The values of the current instance won't be affected.

    */ public function map(callable $callback): Set {} /** * Returns the result of adding all given values to the set. * *

    Note: The current instance won't be affected.

    * * @link https://www.php.net/manual/en/ds-set.merge.php * * @template TValue2 * @param iterable $values A traversable object or an array. * * @return Set The result of adding all given values to the set, * effectively the same as adding the values to a copy, then returning * that copy. */ public function merge($values): Set {} /** * Reduces the set to a single value using a callback function. * * @link https://www.php.net/manual/en/ds-set.reduce.php * * @template TCarry * @param callable(TCarry, TValue): TCarry $callback * callback ( mixed $carry , mixed $value ) : mixed * $carry The return value of the previous callback, or initial if * it's the first iteration. * $value The value of the current iteration. * * @param TCarry $initial The initial value of the carry value. Can be * NULL. * * @return TCarry The return value of the final callback. */ public function reduce(callable $callback, $initial = null) {} /** * Removes all given values from the set, ignoring any that are not in * the set. * * @link https://www.php.net/manual/en/ds-set.remove.php * * @param TValue ...$values The values to remove. */ public function remove(...$values) {} /** * Reverses the set in-place. * * @link https://www.php.net/manual/en/ds-set.reverse.php */ public function reverse() {} /** * Returns a reversed copy of the set. * * @link https://www.php.net/manual/en/ds-set.reversed.php * *

    Note: The current instance is not affected.

    * * @return Set A reversed copy of the set. */ public function reversed(): Set {} /** * Returns a sub-set of a given range * * @param int $index The index at which the sub-set starts. If positive, * the set will start at that index in * the set. If negative, the set will start that far from the end. * * @param int|null $length If a length is given and is positive, the * resulting set will have up to that many values in it. If the length * results in an overflow, only values up to the end of the set will be * included. If a length is given and is negative, the set will stop * that many values from the end. If a length is not provided, the * resulting set will contain all values between the index and the end * of the set. * * @return Set A sub-set of the given range. */ public function slice(int $index, ?int $length = null): Set {} /** * Returns the last value in the set. * * @link https://www.php.net/manual/en/ds-set.last.php * * @return TValue The last value in the set. * * @throws UnderflowException if empty. */ public function last() {} /** * Sorts the set in-place, using an optional comparator function. * * @param callable(TValue, TValue): int|null $comparator The comparison function must return * an integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647. * callback ( mixed $a, mixed $b ) : int * Caution: Returning non-integer values from the comparison * function, such as float, will result in an internal cast to integer * of the callback's return value. So values such as 0.99 and 0.1 will * both be cast to an integer value of 0, which will compare such values * as equal. * * @link https://www.php.net/manual/en/ds-set.sort.php */ public function sort(?callable $comparator = null) {} /** * Returns a sorted copy, using an optional comparator function. * * @link https://www.php.net/manual/en/ds-set.sorted.php * * @param null|callable(TValue, TValue): int $comparator The comparison function must return an * integer less than, equal to, or greater than zero if the first * argument is considered to be respectively less than, equal to, or * greater than the second. Note that before PHP 7.0.0 this integer had * to be in the range from -2147483648 to 2147483647. * * callback ( mixed $a, mixed $b ) : int * *

    Caution: Returning non-integer values from the comparison * function, such as float, will result in an * internal cast to integer of the callback's return value. So values * such as 0.99 and 0.1 will both be cast to an integer value of 0, * which will compare such values as equal.

    * * @return Set Returns a sorted copy of the set. */ public function sorted(?callable $comparator = null): Set {} /** * Returns the sum of all values in the set. * *

    Note: Arrays and objects are considered equal to zero when * calculating the sum.

    * * @link https://www.php.net/manual/en/ds-set.sum.php * * @return float|int The sum of all the values in the set as either a * float or int depending on the values in the set. */ public function sum(): float|int {} /** * Creates a new set that contains the values of the current instance as * well as the values of another set. * * A ∪ B = {x: x ∈ A ∨ x ∈ B} * * @link https://www.php.net/manual/en/ds-set.union.php * * @template TValue2 * @param Set $set The other set, to combine with the current instance. * * @return Set A new set containing all the values of the current * instance as well as another set. */ public function union(Set $set): Set {} /** * Creates a new set using values in either the current instance or in * another set, but not in both. * * A ⊖ B = {x : x ∈ (A \ B) ∪ (B \ A)} * * @link https://www.php.net/manual/en/ds-set.xor.php * * @template TValue2 * @param Set $set The other set. * * @return Set A new set containing values in the current instance as * well as another set, but not in both. */ public function xor(Set $set): Set {} /** * Converts the set to an array. *

    Note: Casting to an array is not supported yet.

    * @link https://www.php.net/manual/en/ds-set.toarray.php * @return array An array containing all the values in the same order as * the collection. */ public function toArray(): array {} /** * Specify data which should be serialized to JSON * @link https://php.net/manual/en/ds-set.jsonserialize.php * @return mixed data which can be serialized by json_encode, * which is a value of any type other than a resource. * @since 5.4 */ public function jsonSerialize() {} /** * @param int $offset */ public function offsetExists(mixed $offset): bool {} /** * @param int $offset * * @return TValue */ public function offsetGet(mixed $offset) {} /** * @param int $offset * @param TValue $value */ public function offsetSet(mixed $offset, mixed $value) {} /** * @param int $offset */ public function offsetUnset(mixed $offset): void {} } /** * A Stack is a “last in, first out” or “LIFO” collection that only allows * access to the value at the top of the structure and iterates in that * order, destructively. * * @package Ds * @template TValue * @implements Collection * * @link https://www.php.net/manual/en/class.ds-stack.php */ class Stack implements Collection, ArrayAccess { /** * Creates a new instance, using either a traversable object or an array * for the initial values. * * @link https://www.php.net/manual/en/ds-stack.construct.php * * @param iterable $values A traversable object or an * array to use for the initial values. */ public function __construct($values = []) {} /** * Ensures that enough memory is allocated for a required capacity. This * removes the need to reallocate the internal as values are added. * * @link https://www.php.net/manual/en/ds-stack.allocate.php * * @param int $capacity The number of values for which capacity should * be allocated. * *

    Note: Capacity will stay the same if this value is less than or * equal to the current capacity.

    */ public function allocate(int $capacity) {} /** * Returns the current capacity. * * @link https://www.php.net/manual/en/ds-stack.capacity.php * * @return int The current capacity. */ public function capacity(): int {} /** * Removes all values from the stack. * @link https://www.php.net/manual/en/ds-stack.clear.php */ public function clear(): void {} /** * Count elements of an object * @link https://php.net/manual/en/ds-stack.count.php * @return int The custom count as an integer. *

    *

    * The return value is cast to an integer. * @since 5.1 */ public function count(): int {} /** * Returns a shallow copy of the collection. * @link https://www.php.net/manual/en/ds-stack.copy.php * @return Stack */ public function copy(): Stack {} /** * @return Traversable */ public function getIterator(): Traversable {} /** * Returns whether the collection is empty. * @link https://www.php.net/manual/en/ds-stack.isempty.php * @return bool */ public function isEmpty(): bool {} /** * Converts the collection to an array. *

    Note: Casting to an array is not supported yet.

    * @link https://www.php.net/manual/en/ds-stack.toarray.php * @return array An array containing all the values in the same order as * the collection. */ public function toArray(): array {} /** * Specify data which should be serialized to JSON * @link https://php.net/manual/en/jsonserializable.jsonserialize.php * @return mixed data which can be serialized by json_encode, * which is a value of any type other than a resource. * @since 5.4 */ public function jsonSerialize() {} /** * Returns the value at the top of the stack, but does not remove it. * * @link https://www.php.net/manual/en/ds-queue.peek.php * * @return TValue The value at the top of the stack. * * @throws UnderflowException */ public function peek() {} /** * Removes and returns the value at the top of the stack. * * @link https://www.php.net/manual/en/ds-queue.pop.php * * @return TValue The removed value which was at the top of the stack. * * @throws UnderflowException */ public function pop() {} /** * Pushes values onto the stack. * * @link https://www.php.net/manual/en/ds-queue.push.php * * @param TValue ...$values The values to push onto the stack. */ public function push(...$values) {} /** * @param int $offset */ public function offsetExists(mixed $offset): bool {} /** * @param int $offset * * @return TValue */ public function offsetGet(mixed $offset) {} /** * @param int $offset * @param TValue $value */ public function offsetSet(mixed $offset, mixed $value) {} /** * @param int $offset */ public function offsetUnset(mixed $offset): void {} } /** * A Queue is a “first in, first out” or “FIFO” collection that only allows * access to the value at the front of the queue and iterates in that order, * destructively. * * Uses a Ds\Vector internally. * * @package Ds * @template TValue * @implements Collection */ class Queue implements Collection, ArrayAccess { /** * Creates a new instance, using either a traversable object or an array * for the initial values. * * @link https://www.php.net/manual/en/ds-queue.construct.php * * @param iterable $values A traversable object or an * array to use for the initial values. */ public function __construct($values = []) {} /** * Ensures that enough memory is allocated for a required capacity. This * removes the need to reallocate the internal as values are added. * * @link https://www.php.net/manual/en/ds-queue.allocate.php * * @param int $capacity The number of values for which capacity should * be allocated. * *

    Note: Capacity will stay the same if this value is less than or * equal to the current capacity.

    */ public function allocate(int $capacity) {} /** * Returns the current capacity. * * @link https://www.php.net/manual/en/ds-queue.capacity.php * * @return int The current capacity. */ public function capacity(): int {} /** * Removes all values from the queue. * @link https://www.php.net/manual/en/ds-queue.clear.php */ public function clear(): void {} /** * Count elements of an object * @link https://php.net/manual/en/ds-queue.count.php * @return int The custom count as an integer. *

    *

    * The return value is cast to an integer. * @since 5.1 */ public function count(): int {} /** * Returns a shallow copy of the collection. * @link https://www.php.net/manual/en/ds-queue.copy.php * @return Queue */ public function copy(): Queue {} /** * @return Traversable */ public function getIterator(): Traversable {} /** * Returns whether the collection is empty. * @link https://www.php.net/manual/en/ds-queue.isempty.php * @return bool */ public function isEmpty(): bool {} /** * Converts the collection to an array. *

    Note: Casting to an array is not supported yet.

    * @link https://www.php.net/manual/en/ds-queue.toarray.php * @return array An array containing all the values in the same order as * the collection. */ public function toArray(): array {} /** * Specify data which should be serialized to JSON * @link https://php.net/manual/en/jsonserializable.jsonserialize.php * @return mixed data which can be serialized by json_encode, * which is a value of any type other than a resource. * @since 5.4 */ public function jsonSerialize() {} /** * Returns the value at the top of the queue, but does not remove it. * * @link https://www.php.net/manual/en/ds-queue.peek.php * * @return TValue The value at the top of the queue. * * @throws UnderflowException */ public function peek() {} /** * Removes and returns the value at the top of the queue. * * @link https://www.php.net/manual/en/ds-queue.pop.php * * @return TValue The removed value which was at the top of the queue. * * @throws UnderflowException */ public function pop() {} /** * Pushes values onto the queue. * * @link https://www.php.net/manual/en/ds-queue.push.php * * @param TValue ...$values The values to push onto the queue. */ public function push(...$values) {} /** * @param int $offset */ public function offsetExists(mixed $offset): bool {} /** * @param int $offset * * @return TValue */ public function offsetGet(mixed $offset) {} /** * @param int $offset * @param TValue $value */ public function offsetSet(mixed $offset, mixed $value) {} /** * @param int $offset */ public function offsetUnset(mixed $offset): void {} } /** * A PriorityQueue is very similar to a Queue. Values are pushed into the * queue with an assigned priority, and the value with the highest priority * will always be at the front of the queue. * * Implemented using a max heap. * * @package Ds * @template TValue * @implements Collection * * @link https://www.php.net/manual/en/class.ds-priorityqueue.php */ class PriorityQueue implements Collection { public const MIN_CAPACITY = 8; /** * Count elements of an object * @link https://php.net/manual/en/countable.count.php * @return int The custom count as an integer. *

    *

    * The return value is cast to an integer. * @since 5.1 */ public function count(): int {} /** * Allocates enough memory for a required capacity * @link https://www.php.net/manual/en/ds-priorityqueue.allocate.php * * @param int $capacity */ public function allocate(int $capacity): void {} /** * Returns the current capacity * @link https://www.php.net/manual/en/ds-priorityqueue.capacity.php * * @return int */ public function capacity(): int {} /** * Removes all values from the collection. * @link https://www.php.net/manual/en/ds-collection.clear.php */ public function clear(): void {} /** * Returns a shallow copy of the collection. * @link https://www.php.net/manual/en/ds-collection.copy.php * @return PriorityQueue */ public function copy() {} /** * @return Traversable */ public function getIterator(): Traversable {} /** * Returns whether the collection is empty. * @link https://www.php.net/manual/en/ds-collection.isempty.php * @return bool */ public function isEmpty(): bool {} /** * Returns the value at the front of the queue, but does not remove it. * @link https://www.php.net/manual/en/ds-priorityqueue.peek.php * * @return TValue The value at the front of the queue. * @throws UnderflowException if empty. */ public function peek() {} /** * Removes and returns the value with the highest priority * @link https://www.php.net/manual/en/ds-priorityqueue.pop.php * * @return TValue The removed value which was at the front of the queue. * @throws UnderflowException if empty. */ public function pop() {} /** * Pushes a value with a given priority into the queue. * * @param TValue $value * @param int $priority */ public function push($value, int $priority) {} /** * Converts the collection to an array. *

    Note: Casting to an array is not supported yet.

    * @link https://www.php.net/manual/en/ds-collection.toarray.php * @return array An array containing all the values in the same order as * the collection. */ public function toArray(): array {} /** * Specify data which should be serialized to JSON * @link https://php.net/manual/en/jsonserializable.jsonserialize.php * @return mixed data which can be serialized by json_encode, * which is a value of any type other than a resource. * @since 5.4 */ public function jsonSerialize() {} } */ function kafka_get_err_descs(): array {} /** * Returns an offset value that is $offset before the tail of the topic * * @param int $offset * @return int */ function kafka_offset_tail(int $offset): int {} /** * Retrieve the current number of threads in use by librdkafka. * * @return int */ function kafka_thread_cnt(): int {} */ public array $headers; /** * @return string */ public function getErrorString(): string {} } */ public function dump(): array {} /** * @param string $name * @param string $value */ public function set(string $name, string $value): void {} /** * @param callable $callback */ public function setErrorCb(callable $callback): void {} /** * @param callable $callback */ public function setDrMsgCb(callable $callback): void {} /** * @param callable $callback */ public function setStatsCb(callable $callback): void {} /** * @param callable $callback */ public function setRebalanceCb(callable $callback): void {} /** * @param callable $callback */ public function setOffsetCommitCb(callable $callback): void {} /** * @param callable $callback */ public function setLogCb(callable $callback): void {} /** * @param callable $callback */ public function setOAuthBearerTokenRefreshCb(callable $callback): void {} } |null $headers * @param int|null $timestampMs * @throws Exception */ public function producev(int $partition, int $msgFlags, ?string $payload = null, ?string $key = null, ?array $headers = null, ?int $timestampMs = null): void {} } * Get GeoIP Database information * @link https://php.net/manual/en/function.geoip-database-info.php * @param int $database [optional]

    * The database type as an integer. You can use the * various constants defined with * this extension (ie: GEOIP_*_EDITION). *

    * @return string|null the corresponding database version, or NULL on error. */ #[Pure] function geoip_database_info($database = GEOIP_COUNTRY_EDITION) {} /** * (PECL geoip >= 0.2.0)
    * Get the two letter country code * @link https://php.net/manual/en/function.geoip-country-code-by-name.php * @param string $hostname

    * The hostname or IP address whose location is to be looked-up. *

    * @return string|false the two letter ISO country code on success, or FALSE * if the address cannot be found in the database. */ #[Pure] function geoip_country_code_by_name($hostname) {} /** * (PECL geoip >= 0.2.0)
    * Get the three letter country code * @link https://php.net/manual/en/function.geoip-country-code3-by-name.php * @param string $hostname

    * The hostname or IP address whose location is to be looked-up. *

    * @return string|false the three letter country code on success, or FALSE * if the address cannot be found in the database. */ #[Pure] function geoip_country_code3_by_name($hostname) {} /** * (PECL geoip >= 0.2.0)
    * Get the full country name * @link https://php.net/manual/en/function.geoip-country-name-by-name.php * @param string $hostname

    * The hostname or IP address whose location is to be looked-up. *

    * @return string|false the country name on success, or FALSE if the address cannot * be found in the database. */ #[Pure] function geoip_country_name_by_name($hostname) {} /** * (PECL geoip >= 1.0.3)
    * Get the two letter continent code * @link https://php.net/manual/en/function.geoip-continent-code-by-name.php * @param string $hostname

    * The hostname or IP address whose location is to be looked-up. *

    * @return string|false the two letter continent code on success, or FALSE if the * address cannot be found in the database. */ #[Pure] function geoip_continent_code_by_name($hostname) {} /** * (PECL geoip >= 0.2.0)
    * Get the organization name * @link https://php.net/manual/en/function.geoip-org-by-name.php * @param string $hostname

    * The hostname or IP address. *

    * @return string|false the organization name on success, or FALSE if the address * cannot be found in the database. */ #[Pure] function geoip_org_by_name($hostname) {} /** * (PECL geoip >= 0.2.0)
    * Returns the detailed City information found in the GeoIP Database * @link https://php.net/manual/en/function.geoip-record-by-name.php * @param string $hostname

    * The hostname or IP address whose record is to be looked-up. *

    * @return array|false the associative array on success, or FALSE if the address * cannot be found in the database. */ #[Pure] function geoip_record_by_name($hostname) {} /** * (PECL geoip >= 0.2.0)
    * Get the Internet connection type * @link https://php.net/manual/en/function.geoip-id-by-name.php * @param string $hostname

    * The hostname or IP address whose connection type is to be looked-up. *

    * @return int the connection type. */ #[Pure] function geoip_id_by_name($hostname) {} /** * (PECL geoip >= 0.2.0)
    * Get the country code and region * @link https://php.net/manual/en/function.geoip-region-by-name.php * @param string $hostname

    * The hostname or IP address whose region is to be looked-up. *

    * @return array|false the associative array on success, or FALSE if the address * cannot be found in the database. */ #[Pure] function geoip_region_by_name($hostname) {} /** * (PECL geoip >= 1.0.2)
    * Get the Internet Service Provider (ISP) name * @link https://php.net/manual/en/function.geoip-isp-by-name.php * @param string $hostname

    * The hostname or IP address. *

    * @return string|false the ISP name on success, or FALSE if the address * cannot be found in the database. */ #[Pure] function geoip_isp_by_name($hostname) {} /** * (PECL geoip >= 1.0.1)
    * Determine if GeoIP Database is available * @link https://php.net/manual/en/function.geoip-db-avail.php * @param int $database

    * The database type as an integer. You can use the * various constants defined with * this extension (ie: GEOIP_*_EDITION). *

    * @return bool|null TRUE is database exists, FALSE if not found, or NULL on error. */ #[Pure] function geoip_db_avail($database) {} /** * (PECL geoip >= 1.0.1)
    * Returns detailed information about all GeoIP database types * @link https://php.net/manual/en/function.geoip-db-get-all-info.php * @return array the associative array. */ #[Pure] function geoip_db_get_all_info() {} /** * (PECL geoip >= 1.0.1)
    * Returns the filename of the corresponding GeoIP Database * @link https://php.net/manual/en/function.geoip-db-filename.php * @param int $database

    * The database type as an integer. You can use the * various constants defined with * this extension (ie: GEOIP_*_EDITION). *

    * @return string|null the filename of the corresponding database, or NULL on error. */ #[Pure] function geoip_db_filename($database) {} /** * (PECL geoip >= 1.0.4)
    * Returns the region name for some country and region code combo * @link https://php.net/manual/en/function.geoip-region-name-by-code.php * @param string $country_code

    * The two-letter country code (see * geoip_country_code_by_name) *

    * @param string $region_code

    * The two-letter (or digit) region code (see * geoip_region_by_name) *

    * @return string|false the region name on success, or FALSE if the country and region code * combo cannot be found. */ #[Pure] function geoip_region_name_by_code($country_code, $region_code) {} /** * (PECL geoip >= 1.0.4)
    * Returns the time zone for some country and region code combo * @link https://php.net/manual/en/function.geoip-time-zone-by-country-and-region.php * @param string $country_code

    * The two-letter country code (see * geoip_country_code_by_name) *

    * @param string $region_code [optional]

    * The two-letter (or digit) region code (see * geoip_region_by_name) *

    * @return string|false the time zone on success, or FALSE if the country and region code * combo cannot be found. */ #[Pure] function geoip_time_zone_by_country_and_region($country_code, $region_code = null) {} define('GEOIP_COUNTRY_EDITION', 1); define('GEOIP_REGION_EDITION_REV0', 7); define('GEOIP_CITY_EDITION_REV0', 6); define('GEOIP_ORG_EDITION', 5); define('GEOIP_ISP_EDITION', 4); define('GEOIP_CITY_EDITION_REV1', 2); define('GEOIP_REGION_EDITION_REV1', 3); define('GEOIP_PROXY_EDITION', 8); define('GEOIP_ASNUM_EDITION', 9); define('GEOIP_NETSPEED_EDITION', 10); define('GEOIP_DOMAIN_EDITION', 11); define('GEOIP_UNKNOWN_SPEED', 0); define('GEOIP_DIALUP_SPEED', 1); define('GEOIP_CABLEDSL_SPEED', 2); define('GEOIP_CORPORATE_SPEED', 3); /** * (PECL geoip >= 1.1.0)
    *

    * The geoip_asnum_by_name() function will return the Autonomous System Numbers (ASN) associated with an IP address. *

    * @link https://secure.php.net/manual/en/function.geoip-asnum-by-name.php * @param string $hostname The hostname or IP address * * @return string|false Returns the ASN on success, or FALSE if the address cannot be found in the database. * @since 1.1.0 */ function geoip_asnum_by_name($hostname) {} /** * (PECL geoip >= 1.1.0)
    *

    * The geoip_netspeedcell_by_name() function will return the Internet connection type and speed corresponding to a hostname or an IP address.
    *
    * This function is only available if using GeoIP Library version 1.4.8 or newer.
    *
    * This function is currently only available to users who have bought a commercial GeoIP NetSpeedCell Edition. A warning will be issued if the proper database cannot be located.
    *
    * The return value is a string, common values are:
    * - Cable/DSL
    * - Dialup
    * - Cellular
    * - Corporate
    *

    * @link https://secure.php.net/manual/en/function.geoip-netspeedcell-by-name.php * @param string $hostname The hostname or IP address * * @return string|false Returns the connection speed on success, or FALSE if the address cannot be found in the database. * @since 1.1.0 */ function geoip_netspeedcell_by_name($hostname) {} /** * (PECL geoip >= 1.1.0)
    *

    * The geoip_setup_custom_directory() function will change the default directory of the GeoIP database. This is equivalent to changing geoip.custom_directory *

    * @link https://secure.php.net/manual/en/function.geoip-setup-custom-directory.php * @param string $path The full path of where the GeoIP database is on disk. * * @return void * @since 1.1.0 */ function geoip_setup_custom_directory($path) {} // End of geoip v.1.1.0 * PASSWORD_BCRYPT is used to create new password * hashes using the CRYPT_BLOWFISH algorithm. *

    *

    * This will always result in a hash using the "$2y$" crypt format, * which is always 60 characters wide. *

    *

    * Supported Options: *

    *
      *
    • *

      * salt - to manually provide a salt to use when hashing the password. * Note that this will override and prevent a salt from being automatically generated. *

      *

      * If omitted, a random salt will be generated by {@link "https://secure.php.net/manual/en/function.password-hash.php" password_hash()} for * each password hashed. This is the intended mode of operation. *

      *
    • *
    • *

      * cost - which denotes the algorithmic cost that should be used. * Examples of these values can be found on the {@link "https://secure.php.net/manual/en/function.crypt.php crypt()"} page. *

      *

      * If omitted, a default value of 10 will be used. This is a good * baseline cost, but you may want to consider increasing it depending on your hardware. *

      *
    • *
    * @link https://secure.php.net/manual/en/password.constants.php */ use JetBrains\PhpStorm\ArrayShape; use JetBrains\PhpStorm\Internal\LanguageLevelTypeAware; define("PASSWORD_DEFAULT", "2y"); /** *

    * The default cost used for the BCRYPT hashing algorithm. *

    *

    * Values for this constant: *

    *
      *
    • * PHP 5.6.0 - PASSWORD_BCRYPT_DEFAULT_COST *
    • *
    */ define("PASSWORD_BCRYPT_DEFAULT_COST", 10); /** *

    * The default algorithm to use for hashing if no algorithm is provided. * This may change in newer PHP releases when newer, stronger hashing * algorithms are supported. *

    *

    * It is worth noting that over time this constant can (and likely will) * change. Therefore you should be aware that the length of the resulting * hash can change. Therefore, if you use PASSWORD_DEFAULT * you should store the resulting hash in a way that can store more than 60 * characters (255 is the recommended width). *

    *

    * Values for this constant: *

    *
      *
    • * PHP 5.5.0 - PASSWORD_BCRYPT *
    • *
    */ define("PASSWORD_BCRYPT", '2y'); /** * PASSWORD_ARGON2I is used to create new password hashes using the Argon2i algorithm. * * Supported Options: *
      *
    • memory_cost (integer) - Maximum memory (in bytes) that may be used to compute the Argon2 hash. Defaults to PASSWORD_ARGON2_DEFAULT_MEMORY_COST.
    • * *
    • time_cost (integer) - Maximum amount of time it may take to compute the Argon2 hash. Defaults to PASSWORD_ARGON2_DEFAULT_TIME_COST.
    • * *
    • threads (integer) - Number of threads to use for computing the Argon2 hash. Defaults to PASSWORD_ARGON2_DEFAULT_THREADS.
    • *
    * Available as of PHP 7.2.0. * @since 7.2 */ define('PASSWORD_ARGON2I', 'argon2i'); /** * PASSWORD_ARGON2ID is used to create new password hashes using the Argon2id algorithm. * * Supported Options: *
      *
    • memory_cost (integer) - Maximum memory (in bytes) that may be used to compute the Argon2 hash. Defaults to PASSWORD_ARGON2_DEFAULT_MEMORY_COST.
    • * *
    • time_cost (integer) - Maximum amount of time it may take to compute the Argon2 hash. Defaults to PASSWORD_ARGON2_DEFAULT_TIME_COST.
    • * *
    • threads (integer) - Number of threads to use for computing the Argon2 hash. Defaults to PASSWORD_ARGON2_DEFAULT_THREADS.
    • *
    * Available as of PHP 7.3.0. * @since 7.3 */ define('PASSWORD_ARGON2ID', 'argon2id'); /** * Default amount of memory in bytes that Argon2lib will use while trying to compute a hash. * Available as of PHP 7.2.0. * @since 7.2 */ define('PASSWORD_ARGON2_DEFAULT_MEMORY_COST', 65536); /** * Default amount of time that Argon2lib will spend trying to compute a hash. * Available as of PHP 7.2.0. * @since 7.2 */ define('PASSWORD_ARGON2_DEFAULT_TIME_COST', 4); /** * Default number of threads that Argon2lib will use. * Available as of PHP 7.2.0. * @since 7.2 */ define('PASSWORD_ARGON2_DEFAULT_THREADS', 1); /** * @since 7.4 */ define('PASSWORD_ARGON2_PROVIDER', 'standard'); /** * Returns information about the given hash * @link https://secure.php.net/manual/en/function.password-get-info.php * @param string $hash A hash created by password_hash(). * @return array|null Returns an associative array with three elements: *
      *
    • * algo, which will match a * {@link https://secure.php.net/manual/en/password.constants.php password algorithm constant} *
    • *
    • * algoName, which has the human readable name of the algorithm *
    • *
    • * options, which includes the options * provided when calling @link https://secure.php.net/manual/en/function.password-hash.php" password_hash() *
    • *
    * @since 5.5 */ #[ArrayShape(["algo" => "int", "algoName" => "string", "options" => "array"])] #[LanguageLevelTypeAware(['8.0' => 'array'], default: '?array')] function password_get_info(string $hash) {} /** * (PHP 5 >= 5.5.0, PHP 5)
    * * Creates a password hash. * @link https://secure.php.net/manual/en/function.password-hash.php * @param string $password The user's password. * @param string|int|null $algo A password algorithm constant denoting the algorithm to use when hashing the password. * @param array $options [optional]

    An associative array containing options. See the password algorithm constants for documentation on the supported options for each algorithm.

    * If omitted, a random salt will be created and the default cost will be used. * Warning *

    * The salt option has been deprecated as of PHP 7.0.0. It is now * preferred to simply use the salt that is generated by default. *

    * @return string|false|null Returns the hashed password, or FALSE on failure, or null if the algorithm is invalid * @since 5.5 */ #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false|null")] function password_hash(string $password, string|int|null $algo, array $options = []) {} /** * Checks if the given hash matches the given options. * @link https://secure.php.net/manual/en/function.password-needs-rehash.php * @param string $hash A hash created by password_hash(). * @param string|int|null $algo A password algorithm constant denoting the algorithm to use when hashing the password. * @param array $options [optional]

    An associative array containing options. See the password algorithm constants for documentation on the supported options for each algorithm.

    * @return bool Returns TRUE if the hash should be rehashed to match the given algo and options, or FALSE otherwise. * @since 5.5 */ function password_needs_rehash(string $hash, string|int|null $algo, array $options = []): bool {} /** * Checks if the given hash matches the given options. * @link https://secure.php.net/manual/en/function.password-verify.php * @param string $password The user's password. * @param string $hash A hash created by password_hash(). * @return bool Returns TRUE if the password and hash match, or FALSE otherwise. * @since 5.5 */ function password_verify(string $password, string $hash): bool {} /** * Return a complete list of all registered password hashing algorithms. * @return string[] * @since 7.4 */ function password_algos(): array {} // End of password v. "int", "message" => "string", "file" => "string", "line" => "int"])] #[Pure(true)] function error_get_last(): ?array {} /** * Call the callback given by the first parameter * @link https://php.net/manual/en/function.call-user-func.php * @param callable $callback

    * The function to be called. Class methods may also be invoked * statically using this function by passing * array($classname, $methodname) to this parameter. * Additionally class methods of an object instance may be called by passing * array($objectinstance, $methodname) to this parameter. *

    * @param mixed ...$args [optional]

    * Zero or more parameters to be passed to the function. *

    *

    * Note that the parameters for call_user_func are * not passed by reference. * call_user_func example and references *

    * @return mixed the function result, or false on error. */ function call_user_func(callable $callback, mixed ...$args): mixed {} /** * Call a callback with an array of parameters * @link https://php.net/manual/en/function.call-user-func-array.php * @param callable $callback

    * The function to be called. *

    * @param array $args

    * The parameters to be passed to the function, as an indexed array. *

    * @return mixed the function result, or false on error. */ function call_user_func_array(callable $callback, array $args): mixed {} /** * Call a user method on an specific object * @link https://php.net/manual/en/function.call-user-method.php * @param string $method_name * @param object &$obj * @param mixed ...$parameter [optional] * @return mixed * @removed 7.0 * @see call_user_func() */ #[Deprecated(reason: "use call_user_func() instead", since: "5.3")] function call_user_method(string $method_name, object &$obj, ...$parameter): mixed {} /** * Call a user method given with an array of parameters * @link https://php.net/manual/en/function.call-user-method-array.php * @param string $method_name * @param object &$obj * @param array $params * @return mixed * @removed 7.0 * @see call_user_func() */ #[Deprecated(reason: "use call_user_func() instead", since: "5.3")] function call_user_method_array(string $method_name, object &$obj, array $params): mixed {} /** * Call a static method * @link https://php.net/manual/en/function.forward-static-call.php * @param callable $callback

    * The function or method to be called. This parameter may be an array, * with the name of the class, and the method, or a string, with a function * name. *

    * @param mixed ...$args [optional]

    * Zero or more parameters to be passed to the function. *

    * @return mixed the function result, or false on error. */ function forward_static_call(callable $callback, mixed ...$args): mixed {} /** * Call a static method and pass the arguments as array * @link https://php.net/manual/en/function.forward-static-call-array.php * @param callable $callback

    * The function or method to be called. This parameter may be an array, * with the name of the class, and the method, or a string, with a function * name. *

    * @param array $args * @return mixed the function result, or false on error. */ function forward_static_call_array(callable $callback, array $args): mixed {} /** * Generates a storable representation of a value * @link https://php.net/manual/en/function.serialize.php * @param mixed $value

    * The value to be serialized. serialize * handles all types, except the resource-type. * You can even serialize arrays that contain * references to itself. Circular references inside the array/object you * are serializing will also be stored. Any other * reference will be lost. *

    *

    * When serializing objects, PHP will attempt to call the member function * __sleep prior to serialization. * This is to allow the object to do any last minute clean-up, etc. prior * to being serialized. Likewise, when the object is restored using * unserialize the __wakeup member function is called. *

    *

    * Object's private members have the class name prepended to the member * name; protected members have a '*' prepended to the member name. * These prepended values have null bytes on either side. *

    * @return string a string containing a byte-stream representation of * value that can be stored anywhere. */ function serialize(mixed $value): string {} /** * Creates a PHP value from a stored representation * @link https://php.net/manual/en/function.unserialize.php * @param string $data

    * The serialized string. *

    *

    * If the variable being unserialized is an object, after successfully * reconstructing the object PHP will automatically attempt to call the * __wakeup member function (if it exists). *

    *

    * unserialize_callback_func directive *

    *

    * It's possible to set a callback-function which will be called, * if an undefined class should be instantiated during unserializing. * (to prevent getting an incomplete object "__PHP_Incomplete_Class".) * Use your "php.ini", ini_set or ".htaccess" * to define 'unserialize_callback_func'. Everytime an undefined class * should be instantiated, it'll be called. To disable this feature just * empty this setting. *

    * @param array $options [optional] *

    Any options to be provided to unserialize(), as an associative array.

    *

    * The 'allowed_classes' option key may be set to a value that is * either an array of class names which should be accepted, FALSE to * accept no classes, or TRUE to accept all classes. If this option is defined * and unserialize() encounters an object of a class that isn't to be accepted, * then the object will be instantiated as __PHP_Incomplete_Class instead. * Omitting this option is the same as defining it as TRUE: PHP will attempt * to instantiate objects of any class. *

    * @return mixed

    The converted value is returned, and can be a boolean, * integer, float, string, * array or object. *

    *

    * In case the passed string is not unserializeable, false is returned and * E_NOTICE is issued.

    */ function unserialize(string $data, #[PhpStormStubsElementAvailable(from: '7.0')] array $options = []): mixed {} /** * Dumps information about a variable * @link https://php.net/manual/en/function.var-dump.php * @param mixed $value

    * The variable you want to export. *

    * @param mixed ...$values [optional] * @return void */ #[PhpStormStubsElementAvailable(from: '8.0')] function var_dump(mixed $value, mixed ...$values): void {} /** * Dumps information about a variable * @link https://php.net/manual/en/function.var-dump.php * @param mixed ...$vars

    * The variable you want to export. *

    * @return void */ #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] function var_dump(...$vars): void {} /** * Outputs or returns a parsable string representation of a variable * @link https://php.net/manual/en/function.var-export.php * @param mixed $value

    * The variable you want to export. *

    * @param bool $return [optional]

    * If used and set to true, var_export will return * the variable representation instead of outputting it. *

    * @return string|null the variable representation when the return * parameter is used and evaluates to true. Otherwise, this function will * return null. */ function var_export(mixed $value, bool $return = false): ?string {} /** * Dumps a string representation of an internal zend value to output * @link https://php.net/manual/en/function.debug-zval-dump.php * @param mixed $value The variable being evaluated. * @param mixed ...$values

    * The other variable being evaluated. *

    * @return void */ function debug_zval_dump( #[PhpStormStubsElementAvailable(from: '8.0')] mixed $value, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $values, mixed ...$values ): void {} /** * Prints human-readable information about a variable * @link https://php.net/manual/en/function.print-r.php * @param mixed $value

    * The expression to be printed. *

    * @param bool $return [optional]

    * If you would like to capture the output of print_r, * use the return parameter. If this parameter is set * to true, print_r will return its output, instead of * printing it (which it does by default). *

    * @return string|bool If given a string, integer or float, * the value itself will be printed. If given an array, values * will be presented in a format that shows keys and elements. Similar * notation is used for objects. */ #[LanguageLevelTypeAware(['8.4' => 'string|true'], default: 'string|bool')] function print_r(mixed $value, bool $return = false) {} /** * Returns the amount of memory allocated to PHP * @link https://php.net/manual/en/function.memory-get-usage.php * @param bool $real_usage [optional]

    * Set this to true to get the real size of memory allocated from * system. If not set or false only the memory used by * emalloc() is reported. *

    * @return int the memory amount in bytes. */ #[Pure(true)] function memory_get_usage(bool $real_usage = false): int {} /** * Returns the peak of memory allocated by PHP * @link https://php.net/manual/en/function.memory-get-peak-usage.php * @param bool $real_usage [optional]

    * Set this to true to get the real size of memory allocated from * system. If not set or false only the memory used by * emalloc() is reported. *

    * @return int the memory peak in bytes. */ #[Pure(true)] function memory_get_peak_usage(bool $real_usage = false): int {} /** * @since 8.2 */ function memory_reset_peak_usage(): void {} /** * Register a function for execution on shutdown * @link https://php.net/manual/en/function.register-shutdown-function.php * @param callable $callback

    * The shutdown function to register. *

    *

    * The shutdown functions are called as the part of the request so that * it's possible to send the output from them. There is currently no way * to process the data with output buffering functions in the shutdown * function. *

    *

    * Shutdown functions are called after closing all opened output buffers * thus, for example, its output will not be compressed if zlib.output_compression is * enabled. *

    * @param mixed ...$args [optional]

    * It is possible to pass parameters to the shutdown function by passing * additional parameters. *

    * @return bool|null */ #[LanguageLevelTypeAware(['8.2' => 'void'], default: 'null|bool')] function register_shutdown_function(callable $callback, mixed ...$args): ?bool {} /** * Register a function for execution on each tick * @link https://php.net/manual/en/function.register-tick-function.php * @param callable $callback

    * The function name as a string, or an array consisting of an object and * a method. *

    * @param mixed ...$args [optional]

    *

    * @return bool true on success or false on failure. */ function register_tick_function(callable $callback, mixed ...$args): bool {} /** * De-register a function for execution on each tick * @link https://php.net/manual/en/function.unregister-tick-function.php * @param callable $callback

    * The function name as a string, or an array consisting of an object and * a method. *

    * @return void */ function unregister_tick_function(callable $callback): void {} /** * Syntax highlighting of a file * @link https://php.net/manual/en/function.highlight-file.php * @param string $filename

    * Path to the PHP file to be highlighted. *

    * @param bool $return [optional]

    * Set this parameter to true to make this function return the * highlighted code. *

    * @return string|bool If return is set to true, returns the highlighted * code as a string instead of printing it out. Otherwise, it will return * true on success, false on failure. */ function highlight_file(string $filename, bool $return = false): string|bool {} /** * Alias: * {@see highlight_file} * @link https://php.net/manual/en/function.show-source.php * @param string $filename * @param bool $return [optional] * @return string|bool */ function show_source(string $filename, bool $return = false): string|bool {} /** * Syntax highlighting of a string * @link https://php.net/manual/en/function.highlight-string.php * @param string $string

    * The PHP code to be highlighted. This should include the opening tag. *

    * @param bool $return [optional]

    * Set this parameter to true to make this function return the * highlighted code. *

    * @return string|bool If return is set to true, returns the highlighted * code as a string instead of printing it out. Otherwise, it will return * true on success, false on failure. */ #[LanguageLevelTypeAware(['8.4' => 'string|true'], default: 'string|bool')] function highlight_string(string $string, bool $return = false) {} /** * Get the system's high resolution time * @link https://secure.php.net/manual/en/function.hrtime.php * @param bool $as_number

    Whether the high resolution time should be returned as array or number.

    * @since 7.3 * @return int[]|int|float|false Returns an array of integers in the form [seconds, nanoseconds], if the parameter get_as_number is false. * Otherwise the nanoseconds are returned as integer (64bit platforms) or float (32bit platforms). */ #[Pure(true)] function hrtime(bool $as_number = false): array|int|float|false {} /** * Return source with stripped comments and whitespace * @link https://php.net/manual/en/function.php-strip-whitespace.php * @param string $filename

    * Path to the PHP file. *

    * @return string The stripped source code will be returned on success, or an empty string * on failure. *

    *

    * This function works as described as of PHP 5.0.1. Before this it would * only return an empty string. For more information on this bug and its * prior behavior, see bug report * #29606. */ #[Pure(true)] function php_strip_whitespace(string $filename): string {} /** * Gets the value of a configuration option * @link https://php.net/manual/en/function.ini-get.php * @link https://php.net/manual/en/ini.list.php * @param string $option

    * The configuration option name. *

    * @return string|false the value of the configuration option as a string on success, or * an empty string on failure or for null values. */ #[Pure(true)] function ini_get(string $option): string|false {} /** * Gets all configuration options * @link https://php.net/manual/en/function.ini-get-all.php * @link https://php.net/manual/en/ini.list.php * @param string|null $extension [optional]

    * An optional extension name. If set, the function return only options * specific for that extension. *

    * @param bool $details [optional]

    * Retrieve details settings or only the current value for each setting. * Default is true (retrieve details). *

    * @return array|false an associative array with directive name as the array key. *

    * When details is true (default) the array will * contain global_value (set in * "php.ini"), local_value (perhaps set with * ini_set or ".htaccess"), and * access (the access level). *

    *

    * When details is false the value will be the * current value of the option. *

    *

    * See the manual section * for information on what access levels mean. *

    *

    * It's possible for a directive to have multiple access levels, which is * why access shows the appropriate bitmask values. *

    */ #[Pure(true)] #[ArrayShape(["global_value" => "string", "local_value" => "string", "access" => "int"])] function ini_get_all(?string $extension, #[PhpStormStubsElementAvailable(from: '7.0')] bool $details = true): array|false {} /** * Sets the value of a configuration option * @link https://php.net/manual/en/function.ini-set.php * @link https://php.net/manual/en/ini.list.php * @param string $option

    *

    *

    * Not all the available options can be changed using * ini_set. There is a list of all available options * in the appendix. *

    * @param string $value

    * The new value for the option. *

    * @return string|false the old value on success, false on failure. */ function ini_set(string $option, #[LanguageLevelTypeAware(['8.1' => 'string|int|float|bool|null'], default: 'string')] $value): string|false {} /** * Alias: * {@see ini_set} * @link https://php.net/manual/en/function.ini-alter.php * @link https://php.net/manual/en/ini.list.php * @param string $option * @param string $value * @return string|false */ function ini_alter(string $option, #[LanguageLevelTypeAware(['8.1' => 'string|int|float|bool|null'], default: 'string')] $value): string|false {} /** * Restores the value of a configuration option * @link https://php.net/manual/en/function.ini-restore.php * @link https://php.net/manual/en/ini.list.php * @param string $option

    * The configuration option name. *

    * @return void */ function ini_restore(string $option): void {} /** * @param string $shorthand * @return int * @since 8.2 */ function ini_parse_quantity(string $shorthand): int {} /** * Gets the current include_path configuration option * @link https://php.net/manual/en/function.get-include-path.php * @return string|false the path, as a string. */ #[Pure(true)] function get_include_path(): string|false {} /** * Sets the include_path configuration option * @link https://php.net/manual/en/function.set-include-path.php * @param string $include_path

    * The new value for the include_path *

    * @return string|false the old include_path on * success or false on failure. */ function set_include_path(string $include_path): string|false {} /** * Restores the value of the include_path configuration option * @link https://php.net/manual/en/function.restore-include-path.php * @return void * @removed 8.0 */ #[Deprecated(since: '7.4')] function restore_include_path() {} /** * Send a cookie * @link https://php.net/manual/en/function.setcookie.php * @param string $name

    * The name of the cookie. *

    * @param string $value [optional]

    * The value of the cookie. This value is stored on the clients * computer; do not store sensitive information. * Assuming the name is 'cookiename', this * value is retrieved through $_COOKIE['cookiename'] *

    * @param int $expires_or_options [optional]

    * The time the cookie expires. This is a Unix timestamp so is * in number of seconds since the epoch. In other words, you'll * most likely set this with the time function * plus the number of seconds before you want it to expire. Or * you might use mktime. * time()+60*60*24*30 will set the cookie to * expire in 30 days. If set to 0, or omitted, the cookie will expire at * the end of the session (when the browser closes). *

    *

    *

    * You may notice the expire parameter takes on a * Unix timestamp, as opposed to the date format Wdy, DD-Mon-YYYY * HH:MM:SS GMT, this is because PHP does this conversion * internally. *

    *

    * expire is compared to the client's time which can * differ from server's time. *

    *

    * @param string $path [optional]

    * The path on the server in which the cookie will be available on. * If set to '/', the cookie will be available * within the entire domain. If set to * '/foo/', the cookie will only be available * within the /foo/ directory and all * sub-directories such as /foo/bar/ of * domain. The default value is the * current directory that the cookie is being set in. *

    * @param string $domain [optional]

    * The domain that the cookie is available. * To make the cookie available on all subdomains of example.com * then you'd set it to '.example.com'. The * . is not required but makes it compatible * with more browsers. Setting it to www.example.com * will make the cookie only available in the www * subdomain. Refer to tail matching in the * spec for details. *

    * @param bool $secure [optional]

    * Indicates that the cookie should only be transmitted over a * secure HTTPS connection from the client. When set to true, the * cookie will only be set if a secure connection exists. * On the server-side, it's on the programmer to send this * kind of cookie only on secure connection (e.g. with respect to * $_SERVER["HTTPS"]). *

    * @param bool $httponly [optional]

    * When true the cookie will be made accessible only through the HTTP * protocol. This means that the cookie won't be accessible by * scripting languages, such as JavaScript. This setting can effectively * help to reduce identity theft through XSS attacks (although it is * not supported by all browsers). Added in PHP 5.2.0. * true or false *

    * @return bool If output exists prior to calling this function, * setcookie will fail and return false. If * setcookie successfully runs, it will return true. * This does not indicate whether the user accepted the cookie. */ function setcookie(string $name, string $value = "", int $expires_or_options = 0, string $path = "", string $domain = "", bool $secure = false, bool $httponly = false): bool {} /** * Send a cookie * * @link https://php.net/manual/en/function.setcookie.php * * @param string $name The name of the cookie. * @param string $value [optional] The value of the cookie. This value is stored on the clients * computer; do not store sensitive information. * Assuming the name is 'cookiename', this value is retrieved through $_COOKIE['cookiename'] * @param array $options [optional] An associative array which may have any of the keys expires, path, domain, secure, * httponly and samesite. The values have the same meaning as described for the parameters with * the same name. The value of the samesite element should be either Lax or Strict. * If any of the allowed options are not given, their default values are the same * as the default values of the explicit parameters. If the samesite element is omitted, * no SameSite cookie attribute is set. * * @return bool If output exists prior to calling this function, setcookie will fail and return false. If * setcookie successfully runs, it will return true. * This does not indicate whether the user accepted the cookie. * @since 7.3 */ function setcookie(string $name, string $value = '', array $options = []): bool {} /** * Send a cookie without urlencoding the cookie value * @link https://php.net/manual/en/function.setrawcookie.php * @param string $name * @param string $value [optional] * @param int $expires_or_options [optional] * @param string $path [optional] * @param string $domain [optional] * @param bool $secure [optional] * @param bool $httponly [optional] * @return bool true on success or false on failure. */ function setrawcookie(string $name, $value = '', $expires_or_options = 0, $path = "", $domain = "", $secure = false, $httponly = false): bool {} /** * Send a cookie without urlencoding the cookie value * * @link https://php.net/manual/en/function.setrawcookie.php * * @param string $name The name of the cookie. * @param string $value [optional] The value of the cookie. This value is stored on the clients * computer; do not store sensitive information. * Assuming the name is 'cookiename', this value is retrieved through $_COOKIE['cookiename'] * @param array $options [optional] An associative array which may have any of the keys expires, path, domain, secure, * httponly and samesite. The values have the same meaning as described for the parameters with * the same name. The value of the samesite element should be either Lax or Strict. * If any of the allowed options are not given, their default values are the same * as the default values of the explicit parameters. If the samesite element is omitted, * no SameSite cookie attribute is set. * * @return bool If output exists prior to calling this function, setcookie will fail and return false. If * setcookie successfully runs, it will return true. * This does not indicate whether the user accepted the cookie. * @since 7.3 */ function setrawcookie(string $name, $value = '', array $options = []): bool {} /** * Send a raw HTTP header * @link https://php.net/manual/en/function.header.php * @param string $header

    * The header string. *

    *

    * There are two special-case header calls. The first is a header * that starts with the string "HTTP/" (case is not * significant), which will be used to figure out the HTTP status * code to send. For example, if you have configured Apache to * use a PHP script to handle requests for missing files (using * the ErrorDocument directive), you may want to * make sure that your script generates the proper status code. *

    *

    * The second special case is the "Location:" header. Not only does * it send this header back to the browser, but it also returns a * REDIRECT (302) status code to the browser * unless the 201 or * a 3xx status code has already been set. *

    * @param bool $replace [optional]

    * The optional replace parameter indicates * whether the header should replace a previous similar header, or * add a second header of the same type. By default it will replace, * but if you pass in false as the second argument you can force * multiple headers of the same type. For example: *

    * @param int $response_code

    * Forces the HTTP response code to the specified value. *

    * @return void */ function header(string $header, bool $replace = true, int $response_code = 0): void {} /** * Remove previously set headers * @link https://php.net/manual/en/function.header-remove.php * @param string|null $name [optional]

    * The header name to be removed. *

    * This parameter is case-insensitive. * @return void */ function header_remove(?string $name = null): void {} /** * Checks if or where headers have been sent * @link https://php.net/manual/en/function.headers-sent.php * @param string &$filename [optional]

    * If the optional file and * line parameters are set, * headers_sent will put the PHP source file name * and line number where output started in the file * and line variables. *

    * @param int &$line [optional]

    * The line number where the output started. *

    * @return bool headers_sent will return false if no HTTP headers * have already been sent or true otherwise. */ function headers_sent(&$filename = null, &$line = null): bool {} /** * Returns a list of response headers sent (or ready to send) * @link https://php.net/manual/en/function.headers-list.php * @return array a numerically indexed array of headers. */ #[Pure] function headers_list(): array {} /** * Fetches all HTTP request headers from the current request * @link https://php.net/manual/en/function.apache-request-headers.php * @return array|false An associative array of all the HTTP headers in the current request, or FALSE on failure. */ #[Pure] function apache_request_headers(): false|array {} /** * Fetches all HTTP headers from the current request. * This function is an alias for apache_request_headers(). Please read the apache_request_headers() documentation for more information on how this function works. * @link https://php.net/manual/en/function.getallheaders.php * @return array|false An associative array of all the HTTP headers in the current request, or FALSE on failure. */ #[Pure] function getallheaders(): false|array {} /** * Check whether client disconnected * @link https://php.net/manual/en/function.connection-aborted.php * @return int 1 if client disconnected, 0 otherwise. */ #[Pure(true)] function connection_aborted(): int {} /** * Returns connection status bitfield * @link https://php.net/manual/en/function.connection-status.php * @return int the connection status bitfield, which can be used against the * CONNECTION_XXX constants to determine the connection * status. */ #[Pure(true)] function connection_status(): int {} /** * Set whether a client disconnect should abort script execution * @link https://php.net/manual/en/function.ignore-user-abort.php * @param bool|null $enable [optional]

    * If set, this function will set the ignore_user_abort ini setting * to the given value. If not, this function will * only return the previous setting without changing it. *

    * @return int the previous setting, as an integer. */ function ignore_user_abort(?bool $enable): int {} /** * Parse a configuration file * @link https://php.net/manual/en/function.parse-ini-file.php * @param string $filename

    * The filename of the ini file being parsed. *

    * @param bool $process_sections [optional]

    * By setting the process_sections * parameter to true, you get a multidimensional array, with * the section names and settings included. The default * for process_sections is false *

    * @param int $scanner_mode [optional]

    * Can either be INI_SCANNER_NORMAL (default) or * INI_SCANNER_RAW. If INI_SCANNER_RAW * is supplied, then option values will not be parsed. *

    *

    * As of PHP 5.6.1 can also be specified as INI_SCANNER_TYPED. * In this mode boolean, null and integer types are preserved when possible. * String values "true", "on" and "yes" * are converted to TRUE. "false", "off", "no" * and "none" are considered FALSE. "null" is converted to NULL * in typed mode. Also, all numeric strings are converted to integer type if it is possible. *

    * @return array|false The settings are returned as an associative array on success, * and false on failure. */ #[Pure(true)] function parse_ini_file(string $filename, bool $process_sections = false, int $scanner_mode = INI_SCANNER_NORMAL): array|false {} /** * Parse a configuration string * @link https://php.net/manual/en/function.parse-ini-string.php * @param string $ini_string

    * The contents of the ini file being parsed. *

    * @param bool $process_sections [optional]

    * By setting the process_sections * parameter to true, you get a multidimensional array, with * the section names and settings included. The default * for process_sections is false *

    * @param int $scanner_mode [optional]

    * Can either be INI_SCANNER_NORMAL (default) or * INI_SCANNER_RAW. If INI_SCANNER_RAW * is supplied, then option values will not be parsed. *

    * @return array|false The settings are returned as an associative array on success, * and false on failure. */ #[Pure] function parse_ini_string(string $ini_string, bool $process_sections = false, int $scanner_mode = INI_SCANNER_NORMAL): array|false {} /** * Tells whether the file was uploaded via HTTP POST * @link https://php.net/manual/en/function.is-uploaded-file.php * @param string $filename

    * The filename being checked. *

    * @return bool true on success or false on failure. */ #[Pure(true)] function is_uploaded_file(string $filename): bool {} /** * Moves an uploaded file to a new location * @link https://php.net/manual/en/function.move-uploaded-file.php * @param string $from

    * The filename of the uploaded file. *

    * @param string $to

    * The destination of the moved file. *

    * @return bool If filename is not a valid upload file, * then no action will occur, and * move_uploaded_file will return * false. *

    *

    * If filename is a valid upload file, but * cannot be moved for some reason, no action will occur, and * move_uploaded_file will return * false. Additionally, a warning will be issued. */ function move_uploaded_file(string $from, string $to): bool {} /** * @return array|false * @since 7.3 */ #[Pure] #[ArrayShape(["description" => "string", "mac" => "string", "mtu" => "int", "unicast" => "array", "up" => "bool"])] function net_get_interfaces(): array|false {} /** * Get the Internet host name corresponding to a given IP address * @link https://php.net/manual/en/function.gethostbyaddr.php * @param string $ip

    * The host IP address. *

    * @return string|false the host name or the unmodified ip_address * on failure. */ #[Pure] function gethostbyaddr(string $ip): string|false {} /** * Get the IPv4 address corresponding to a given Internet host name * @link https://php.net/manual/en/function.gethostbyname.php * @param string $hostname

    * The host name. *

    * @return string the IPv4 address or a string containing the unmodified * hostname on failure. */ #[Pure] function gethostbyname(string $hostname): string {} /** * Get a list of IPv4 addresses corresponding to a given Internet host * name * @link https://php.net/manual/en/function.gethostbynamel.php * @param string $hostname

    * The host name. *

    * @return array|false an array of IPv4 addresses or false if * hostname could not be resolved. */ #[Pure] function gethostbynamel(string $hostname): array|false {} /** * Gets the host name * @link https://php.net/manual/en/function.gethostname.php * @return string|false a string with the hostname on success, otherwise false is * returned. */ #[Pure] function gethostname(): string|false {} /** * Alias: * {@see checkdnsrr} * @link https://php.net/manual/en/function.dns-check-record.php * @param string $hostname

    * host may either be the IP address in * dotted-quad notation or the host name. *

    * @param string $type [optional]

    * type may be any one of: A, MX, NS, SOA, * PTR, CNAME, AAAA, A6, SRV, NAPTR, TXT or ANY. *

    * @return bool Returns TRUE if any records are found; returns FALSE if no records were found or if an error occurred. */ function dns_check_record(string $hostname, string $type = 'MX'): bool {} /** * Check DNS records corresponding to a given Internet host name or IP address * @link https://php.net/manual/en/function.checkdnsrr.php * @param string $hostname

    * host may either be the IP address in * dotted-quad notation or the host name. *

    * @param string $type [optional]

    * type may be any one of: A, MX, NS, SOA, * PTR, CNAME, AAAA, A6, SRV, NAPTR, TXT or ANY. *

    * @return bool true if any records are found; returns false if no records * were found or if an error occurred. */ #[Pure] function checkdnsrr(string $hostname, string $type = 'MX'): bool {} /** * Alias: * {@see getmxrr} * @link https://php.net/manual/en/function.dns-get-mx.php * @param string $hostname * @param array &$hosts * @param array &$weights [optional] * @return bool */ function dns_get_mx(string $hostname, &$hosts, &$weights): bool {} /** * Get MX records corresponding to a given Internet host name * @link https://php.net/manual/en/function.getmxrr.php * @param string $hostname

    * The Internet host name. *

    * @param array &$hosts

    * A list of the MX records found is placed into the array * mxhosts. *

    * @param array &$weights [optional]

    * If the weight array is given, it will be filled * with the weight information gathered. *

    * @return bool true if any records are found; returns false if no records * were found or if an error occurred. */ function getmxrr(string $hostname, &$hosts, &$weights): bool {} /** * Fetch DNS Resource Records associated with a hostname * @link https://php.net/manual/en/function.dns-get-record.php * @param string $hostname

    * hostname should be a valid DNS hostname such * as "www.example.com". Reverse lookups can be generated * using in-addr.arpa notation, but * gethostbyaddr is more suitable for * the majority of reverse lookups. *

    *

    * Per DNS standards, email addresses are given in user.host format (for * example: hostmaster.example.com as opposed to hostmaster@example.com), * be sure to check this value and modify if necessary before using it * with a functions such as mail. *

    * @param int $type [optional]

    * By default, dns_get_record will search for any * resource records associated with hostname. * To limit the query, specify the optional type * parameter. May be any one of the following: * DNS_A, DNS_CNAME, * DNS_HINFO, DNS_MX, * DNS_NS, DNS_PTR, * DNS_SOA, DNS_TXT, * DNS_AAAA, DNS_SRV, * DNS_NAPTR, DNS_A6, * DNS_ALL or DNS_ANY. *

    *

    * Because of eccentricities in the performance of libresolv * between platforms, DNS_ANY will not * always return every record, the slower DNS_ALL * will collect all records more reliably. *

    * @param array &$authoritative_name_servers [optional]

    * Passed by reference and, if given, will be populated with Resource * Records for the Authoritative Name Servers. *

    * @param array &$additional_records [optional]

    * Passed by reference and, if given, will be populated with any * Additional Records. *

    * @param bool $raw [optional]

    * In case of raw mode, we query only the requested type * instead of looping type by type before going with the additional info stuff. *

    * @return array|false This function returns an array of associative arrays. Each associative array contains * at minimum the following keys: * * Basic DNS attributes * * * * * * * * * * * * * * * * * * * * *
    AttributeMeaning
    host * The record in the DNS namespace to which the rest of the associated data refers. *
    class * dns_get_record only returns Internet class records and as * such this parameter will always return IN. *
    type * String containing the record type. Additional attributes will also be contained * in the resulting array dependant on the value of type. See table below. *
    ttl * "Time To Live" remaining for this record. This will not equal * the record's original ttl, but will rather equal the original ttl minus whatever * length of time has passed since the authoritative name server was queried. *
    *

    *

    *

    * Other keys in associative arrays dependant on 'type' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    TypeExtra Columns
    A * ip: An IPv4 addresses in dotted decimal notation. *
    MX * pri: Priority of mail exchanger. * Lower numbers indicate greater priority. * target: FQDN of the mail exchanger. * See also dns_get_mx. *
    CNAME * target: FQDN of location in DNS namespace to which * the record is aliased. *
    NS * target: FQDN of the name server which is authoritative * for this hostname. *
    PTR * target: Location within the DNS namespace to which * this record points. *
    TXT * txt: Arbitrary string data associated with this record. *
    HINFO * cpu: IANA number designating the CPU of the machine * referenced by this record. * os: IANA number designating the Operating System on * the machine referenced by this record. * See IANA's Operating System * Names for the meaning of these values. *
    SOA * mname: FQDN of the machine from which the resource * records originated. * rname: Email address of the administrative contain * for this domain. * serial: Serial # of this revision of the requested * domain. * refresh: Refresh interval (seconds) secondary name * servers should use when updating remote copies of this domain. * retry: Length of time (seconds) to wait after a * failed refresh before making a second attempt. * expire: Maximum length of time (seconds) a secondary * DNS server should retain remote copies of the zone data without a * successful refresh before discarding. * minimum-ttl: Minimum length of time (seconds) a * client can continue to use a DNS resolution before it should request * a new resolution from the server. Can be overridden by individual * resource records. *
    AAAA * ipv6: IPv6 address *
    A6(PHP >= 5.1.0) * masklen: Length (in bits) to inherit from the target * specified by chain. * ipv6: Address for this specific record to merge with * chain. * chain: Parent record to merge with * ipv6 data. *
    SRV * pri: (Priority) lowest priorities should be used first. * weight: Ranking to weight which of commonly prioritized * targets should be chosen at random. * target and port: hostname and port * where the requested service can be found. * For additional information see: RFC 2782 *
    NAPTR * order and pref: Equivalent to * pri and weight above. * flags, services, regex, * and replacement: Parameters as defined by * RFC 2915. *
    */ function dns_get_record(string $hostname, int $type = DNS_ANY, &$authoritative_name_servers, &$additional_records, bool $raw = false): array|false {} * The input string. *

    * @return string the uppercased string. */ #[Pure] function strtoupper(string $string): string {} /** * Make a string lowercase * @link https://php.net/manual/en/function.strtolower.php * @param string $string

    * The input string. *

    * @return string the lowercased string. */ #[Pure] function strtolower(string $string): string {} /** * Find the position of the first occurrence of a substring in a string * @link https://php.net/manual/en/function.strpos.php * @param string $haystack

    * The string to search in *

    * @param string $needle

    * If needle is not a string, it is converted * to an integer and applied as the ordinal value of a character. *

    * @param int<0,max> $offset [optional]

    * If specified, search will start this number of characters counted from * the beginning of the string. Unlike {@see strrpos()} and {@see strripos()}, the offset cannot be negative. *

    * @return int<0,max>|false

    * Returns the position where the needle exists relative to the beginning of * the haystack string (independent of search direction * or offset). * Also note that string positions start at 0, and not 1. *

    *

    * Returns FALSE if the needle was not found. *

    */ #[Pure] function strpos(string $haystack, string $needle, int $offset = 0): int|false {} /** * Find position of first occurrence of a case-insensitive string * @link https://php.net/manual/en/function.stripos.php * @param string $haystack

    * The string to search in *

    * @param string $needle

    * Note that the needle may be a string of one or * more characters. *

    *

    * If needle is not a string, it is converted to * an integer and applied as the ordinal value of a character. *

    * @param int $offset

    * The optional offset parameter allows you * to specify which character in haystack to * start searching. The position returned is still relative to the * beginning of haystack. *

    * @return int|false If needle is not found, * stripos will return boolean false. */ #[Pure] function stripos(string $haystack, string $needle, int $offset = 0): int|false {} /** * Find the position of the last occurrence of a substring in a string * @link https://php.net/manual/en/function.strrpos.php * @param string $haystack

    * The string to search in. *

    * @param string $needle

    * If needle is not a string, it is converted to an integer and applied as the ordinal value of a character. *

    * @param int $offset [optional]

    * If specified, search will start this number of characters counted from the beginning of the string. If the value is negative, search will instead start from that many characters from the end of the string, searching backwards. *

    * @return int|false

    * Returns the position where the needle exists relative to the beginning of * the haystack string (independent of search direction * or offset). * Also note that string positions start at 0, and not 1. *

    *

    * Returns FALSE if the needle was not found. *

    */ #[Pure] function strrpos(string $haystack, string $needle, int $offset = 0): int|false {} /** * Find position of last occurrence of a case-insensitive string in a string * @link https://php.net/manual/en/function.strripos.php * @param string $haystack

    * The string to search in *

    * @param string $needle

    * Note that the needle may be a string of one or * more characters. *

    * @param int $offset

    * The offset parameter may be specified to begin * searching an arbitrary number of characters into the string. *

    *

    * Negative offset values will start the search at * offset characters from the * start of the string. *

    * @return int|false the numerical position of the last occurrence of * needle. Also note that string positions start at 0, * and not 1. *

    *

    * If needle is not found, false is returned. */ #[Pure] function strripos(string $haystack, string $needle, int $offset = 0): int|false {} /** * Reverse a string * @link https://php.net/manual/en/function.strrev.php * @param string $string

    * The string to be reversed. *

    * @return string the reversed string. */ #[Pure] function strrev(string $string): string {} /** * Convert logical Hebrew text to visual text * @link https://php.net/manual/en/function.hebrev.php * @param string $string

    * A Hebrew input string. *

    * @param int $max_chars_per_line

    * This optional parameter indicates maximum number of characters per * line that will be returned. *

    * @return string the visual string. */ #[Pure] function hebrev(string $string, int $max_chars_per_line = 0): string {} /** * Convert logical Hebrew text to visual text with newline conversion * @link https://php.net/manual/en/function.hebrevc.php * @param string $hebrew_text

    * A Hebrew input string. *

    * @param int $max_chars_per_line [optional]

    * This optional parameter indicates maximum number of characters per * line that will be returned. *

    * @return string the visual string. * @removed 8.0 */ #[Deprecated(replacement: 'nl2br(hebrev(%parameter0%))', since: '7.4')] function hebrevc(string $hebrew_text, $max_chars_per_line): string {} /** * Inserts HTML line breaks before all newlines in a string * @link https://php.net/manual/en/function.nl2br.php * @param string $string

    * The input string. *

    * @param bool $use_xhtml [optional]

    * Whether to use XHTML compatible line breaks or not. *

    * @return string the altered string. */ #[Pure] function nl2br(string $string, bool $use_xhtml = true): string {} /** * Returns trailing name component of path * @link https://php.net/manual/en/function.basename.php * @param string $path

    * A path. *

    *

    * On Windows, both slash (/) and backslash * (\) are used as directory separator character. In * other environments, it is the forward slash (/). *

    * @param string $suffix

    * If the filename ends in suffix this will also * be cut off. *

    * @return string the base name of the given path. */ #[Pure] function basename(string $path, string $suffix = ''): string {} /** * Returns a parent directory's path * @link https://php.net/manual/en/function.dirname.php * @param string $path

    * A path. *

    *

    * On Windows, both slash (/) and backslash * (\) are used as directory separator character. In * other environments, it is the forward slash (/). *

    * @param int $levels

    * The number of parent directories to go up. * This must be an integer greater than 0. *

    * @return string the name of the directory. If there are no slashes in * path, a dot ('.') is returned, * indicating the current directory. Otherwise, the returned string is * path with any trailing * /component removed. */ #[Pure] function dirname(string $path, #[PhpStormStubsElementAvailable(from: '7.0')] int $levels = 1): string {} /** * Returns information about a file path * @link https://php.net/manual/en/function.pathinfo.php * @param string $path

    * The path being checked. *

    * @param int $flags [optional]

    * You can specify which elements are returned with optional parameter * options. It composes from * PATHINFO_DIRNAME, * PATHINFO_BASENAME, * PATHINFO_EXTENSION and * PATHINFO_FILENAME. It * defaults to return all elements. *

    * @return string|array{dirname: string, basename: string, extension: string, filename: string} The following associative array elements are returned: * dirname, basename, * extension (if any), and filename. *

    *

    * If options is used, this function will return a * string if not all elements are requested. */ #[Pure(true)] #[ArrayShape(['dirname' => 'string', 'basename' => 'string', 'extension' => 'string', 'filename' => 'string'])] function pathinfo(string $path, #[ExpectedValues(flags: [ PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION, PATHINFO_FILENAME ])] int $flags = PATHINFO_ALL): array|string {} /** * Un-quotes a quoted string * @link https://php.net/manual/en/function.stripslashes.php * @param string $string

    * The input string. *

    * @return string a string with backslashes stripped off. * (\' becomes ' and so on.) * Double backslashes (\\) are made into a single * backslash (\). */ #[Pure] function stripslashes(string $string): string {} /** * Un-quote string quoted with addcslashes * @link https://php.net/manual/en/function.stripcslashes.php * @param string $string

    * The string to be unescaped. *

    * @return string the unescaped string. */ #[Pure] function stripcslashes(string $string): string {} /** * Find the first occurrence of a string * @link https://php.net/manual/en/function.strstr.php * @param string $haystack

    * The input string. *

    * @param string $needle

    * If needle is not a string, it is converted to * an integer and applied as the ordinal value of a character. *

    * @param bool $before_needle [optional]

    * If true, strstr returns * the part of the haystack before the first * occurrence of the needle. *

    * @return string|false the portion of string, or false if needle * is not found. */ #[Pure] function strstr(string $haystack, string $needle, bool $before_needle = false): string|false {} /** * Case-insensitive strstr * @link https://php.net/manual/en/function.stristr.php * @param string $haystack

    * The string to search in *

    * @param string $needle

    * If needle is not a string, it is converted to * an integer and applied as the ordinal value of a character. *

    * @param bool $before_needle [optional]

    * If true, stristr * returns the part of the haystack before the * first occurrence of the needle. *

    * @return string|false the matched substring. If needle is not * found, returns false. */ #[Pure] function stristr(string $haystack, string $needle, bool $before_needle = false): string|false {} /** * Find the last occurrence of a character in a string * @link https://php.net/manual/en/function.strrchr.php * @param string $haystack

    * The string to search in *

    * @param string $needle

    * If needle contains more than one character, * only the first is used. This behavior is different from that of {@see strstr()}. *

    *

    * If needle is not a string, it is converted to * an integer and applied as the ordinal value of a character. *

    * @param bool $before_needle Since 8.3 If true, strrchr() returns the part of the haystack before the last occurrence * of the needle (excluding the needle). * @return string|false

    * This function returns the portion of string, or FALSE if * needle is not found. *

    */ #[Pure] function strrchr(string $haystack, string $needle, #[PhpStormStubsElementAvailable(from: '8.3')] bool $before_needle = false): string|false {} /** * Randomly shuffles a string * @link https://php.net/manual/en/function.str-shuffle.php * @param string $string

    * The input string. *

    * @return string the shuffled string. */ function str_shuffle(string $string): string {} /** * Return information about words used in a string * @link https://php.net/manual/en/function.str-word-count.php * @param string $string

    * The string *

    * @param int $format [optional]

    * Specify the return value of this function. The current supported values * are: * 0 - returns the number of words found *

    * @param string|null $characters [optional]

    * A list of additional characters which will be considered as 'word' *

    * @return string[]|int an array or an integer, depending on the * format chosen. */ #[Pure] function str_word_count(string $string, int $format = 0, ?string $characters): array|int {} /** * Convert a string to an array * @link https://php.net/manual/en/function.str-split.php * @param string $string

    * The input string. *

    * @param int $length [optional]

    * Maximum length of the chunk. *

    * @return string[]|false

    If the optional split_length parameter is * specified, the returned array will be broken down into chunks with each * being split_length in length, otherwise each chunk * will be one character in length. *

    *

    * FALSE is returned if split_length is less than 1. * If the split_length length exceeds the length of * string, the entire string is returned as the first * (and only) array element. *

    */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] function str_split(string $string, int $length = 1): array|false {} /** * Search a string for any of a set of characters * @link https://php.net/manual/en/function.strpbrk.php * @param string $string

    * The string where char_list is looked for. *

    * @param string $characters

    * This parameter is case sensitive. *

    * @return string|false a string starting from the character found, or false if it is * not found. */ #[Pure] function strpbrk( string $string, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] $char_list = '', #[PhpStormStubsElementAvailable(from: '7.1')] string $characters ): string|false {} /** * Binary safe comparison of two strings from an offset, up to length characters * @link https://php.net/manual/en/function.substr-compare.php * @param string $haystack

    * The main string being compared. *

    * @param string $needle

    * The secondary string being compared. *

    * @param int $offset

    * The start position for the comparison. If negative, it starts counting * from the end of the string. *

    * @param int|null $length [optional]

    * The length of the comparison. *

    * @param bool $case_insensitive [optional]

    * If case_insensitivity is true, comparison is * case insensitive. *

    * @return int if less than 0 if main_str from position * offset is less than str, > * 0 if it is greater than str, and 0 if they are equal. * If offset is equal to or greater than the length of * main_str or length is set and * is less than 1, substr_compare prints a warning and returns * false. */ #[Pure] function substr_compare(string $haystack, string $needle, int $offset, ?int $length, bool $case_insensitive = false): int {} /** * Locale based string comparison * @link https://php.net/manual/en/function.strcoll.php * @param string $string1

    * The first string. *

    * @param string $string2

    * The second string. *

    * @return int if less than 0 if str1 is less than * str2; > 0 if * str1 is greater than * str2, and 0 if they are equal. */ #[Pure] function strcoll(string $string1, string $string2): int {} /** * Formats a number as a currency string * @link https://php.net/manual/en/function.money-format.php * @param string $format

    * The format specification consists of the following sequence:
    * a % character

    * @param float $number

    * The number to be formatted. *

    * @return string|null the formatted string. Characters before and after the formatting * string will be returned unchanged. * Non-numeric number causes returning null and * emitting E_WARNING. * @removed 8.0 * @see NumberFormatter */ #[Deprecated(reason: 'Use the NumberFormatter functionality', since: '7.4')] function money_format(string $format, float $number): ?string {} /** * Return part of a string or false on failure. For PHP8.0+ only string is returned * @link https://php.net/manual/en/function.substr.php * @param string $string

    * The input string. *

    * @param int $offset

    * If start is non-negative, the returned string * will start at the start'th position in * string, counting from zero. For instance, * in the string 'abcdef', the character at * position 0 is 'a', the * character at position 2 is * 'c', and so forth. *

    *

    * If start is negative, the returned string * will start at the start'th character * from the end of string. *

    *

    * If string is less than or equal to * start characters long, false will be returned. *

    *

    * Using a negative start *

    *
     * 
     * 
    * @param int|null $length [optional]

    * If length is given and is positive, the string * returned will contain at most length characters * beginning from start (depending on the length of * string). *

    *

    * If length is given and is negative, then that many * characters will be omitted from the end of string * (after the start position has been calculated when a * start is negative). If * start denotes a position beyond this truncation, * an empty string will be returned. *

    *

    * If length is given and is 0, * false or null an empty string will be returned. *

    * Using a negative length: *
     * 
     * 
    */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] function substr(string $string, int $offset, ?int $length) {} /** * Replace text within a portion of a string * @link https://php.net/manual/en/function.substr-replace.php * @param string[]|string $string

    * The input string. *

    * @param string[]|string $replace

    * The replacement string. *

    * @param int[]|int $offset

    * If start is positive, the replacing will * begin at the start'th offset into * string. *

    *

    * If start is negative, the replacing will * begin at the start'th character from the * end of string. *

    * @param int[]|int $length [optional]

    * If given and is positive, it represents the length of the portion of * string which is to be replaced. If it is * negative, it represents the number of characters from the end of * string at which to stop replacing. If it * is not given, then it will default to strlen( * string ); i.e. end the replacing at the * end of string. Of course, if * length is zero then this function will have the * effect of inserting replacement into * string at the given * start offset. *

    * @return string|string[] The result string is returned. If string is an * array then array is returned. */ #[Pure] function substr_replace(array|string $string, array|string $replace, array|int $offset, array|int|null $length = null): array|string {} /** * Quote meta characters * @link https://php.net/manual/en/function.quotemeta.php * @param string $string

    * The input string. *

    * @return string the string with meta characters quoted. */ #[Pure] function quotemeta(string $string): string {} /** * Make a string's first character uppercase * @link https://php.net/manual/en/function.ucfirst.php * @param string $string

    * The input string. *

    * @return string the resulting string. */ #[Pure] function ucfirst(string $string): string {} /** * Make a string's first character lowercase * @link https://php.net/manual/en/function.lcfirst.php * @param string $string

    * The input string. *

    * @return string the resulting string. */ #[Pure] function lcfirst(string $string): string {} /** * Uppercase the first character of each word in a string * @link https://php.net/manual/en/function.ucwords.php * @param string $string

    * The input string. *

    * @param string $separators [optional]

    * The optional separators contains the word separator characters. *

    * @return string the modified string. */ #[Pure] function ucwords(string $string, string $separators = " \t\r\n\f\v"): string {} /** * Translate characters or replace substrings * @link https://php.net/manual/en/function.strtr.php * @param string $string

    * The string being translated. *

    * @param string $from

    * The string replacing from. *

    * @param string $to

    * The string being translated to to. *

    * @return string This function returns a copy of str, * translating all occurrences of each character in * from to the corresponding character in * to. */ #[Pure] function strtr(string $string, string $from, string $to): string {} /** * Translate certain characters * @link https://php.net/manual/en/function.strtr.php * @param string $str The string being translated. * @param array $replace_pairs The replace_pairs parameter may be used as a substitute for to and from in which case it's an array in the form array('from' => 'to', ...). * @return string A copy of str, translating all occurrences of each character in from to the corresponding character in to. */ #[Pure] function strtr(string $str, array $replace_pairs): string {} /** * Quote string with slashes * @link https://php.net/manual/en/function.addslashes.php * @param string $string

    * The string to be escaped. *

    * @return string the escaped string. */ #[Pure] function addslashes(string $string): string {} /** * Quote string with slashes in a C style * @link https://php.net/manual/en/function.addcslashes.php * @param string $string

    * The string to be escaped. *

    * @param string $characters

    * A list of characters to be escaped. If * charlist contains characters * \n, \r etc., they are * converted in C-like style, while other non-alphanumeric characters * with ASCII codes lower than 32 and higher than 126 converted to * octal representation. *

    *

    * When you define a sequence of characters in the charlist argument * make sure that you know what characters come between the * characters that you set as the start and end of the range. *

    *
     * 
     * 
    *

    * Also, if the first character in a range has a higher ASCII value * than the second character in the range, no range will be * constructed. Only the start, end and period characters will be * escaped. Use the ord function to find the * ASCII value for a character. *

    *
     * 
     * 
    *

    * Be careful if you choose to escape characters 0, a, b, f, n, r, * t and v. They will be converted to \0, \a, \b, \f, \n, \r, \t * and \v. * In PHP \0 (NULL), \r (carriage return), \n (newline), \f (form feed), * \v (vertical tab) and \t (tab) are predefined escape sequences, * while in C all of these are predefined escape sequences. *

    * @return string the escaped string. */ #[Pure] function addcslashes(string $string, string $characters): string {} /** * Strip whitespace (or other characters) from the end of a string. * Without the second parameter, rtrim() will strip these characters: *
      *
    • " " (ASCII 32 (0x20)), an ordinary space. *
    • "\t" (ASCII 9 (0x09)), a tab. *
    • "\n" (ASCII 10 (0x0A)), a new line (line feed). *
    • "\r" (ASCII 13 (0x0D)), a carriage return. *
    • "\0" (ASCII 0 (0x00)), the NUL-byte. *
    • "\x0B" (ASCII 11 (0x0B)), a vertical tab. *
    * @link https://php.net/manual/en/function.rtrim.php * @param string $string

    * The input string. *

    * @param string $characters [optional]

    * You can also specify the characters you want to strip, by means * of the charlist parameter. * Simply list all characters that you want to be stripped. With * .. you can specify a range of characters. *

    * @return string the modified string. */ #[Pure] function rtrim(string $string, string $characters = " \n\r\t\v\0"): string {} /** * Replace all occurrences of the search string with the replacement string * @link https://php.net/manual/en/function.str-replace.php * @param string|string[] $search

    * The value being searched for, otherwise known as the needle. * An array may be used to designate multiple needles. *

    * @param string|string[] $replace

    * The replacement value that replaces found search * values. An array may be used to designate multiple replacements. *

    * @param string|string[] $subject

    * The string or array being searched and replaced on, * otherwise known as the haystack. *

    *

    * If subject is an array, then the search and * replace is performed with every entry of * subject, and the return value is an array as * well. *

    * @param int &$count [optional] If passed, this will hold the number of matched and replaced needles. * @return string|string[] This function returns a string or an array with the replaced values. */ function str_replace(array|string $search, array|string $replace, array|string $subject, &$count): array|string {} /** * Case-insensitive version of str_replace. * @link https://php.net/manual/en/function.str-ireplace.php * @param mixed $search

    * Every replacement with search array is * performed on the result of previous replacement. *

    * @param array|string $replace

    *

    * @param array|string $subject

    * If subject is an array, then the search and * replace is performed with every entry of * subject, and the return value is an array as * well. *

    * @param int &$count [optional]

    * The number of matched and replaced needles will * be returned in count which is passed by * reference. *

    * @return string|string[] a string or an array of replacements. */ function str_ireplace(array|string $search, array|string $replace, array|string $subject, &$count): array|string {} /** * Repeat a string * @link https://php.net/manual/en/function.str-repeat.php * @param string $string

    * The string to be repeated. *

    * @param int $times

    * Number of time the input string should be * repeated. *

    *

    * multiplier has to be greater than or equal to 0. * If the multiplier is set to 0, the function * will return an empty string. *

    * @return string the repeated string. */ #[Pure] function str_repeat(string $string, int $times): string {} /** * Return information about characters used in a string * @link https://php.net/manual/en/function.count-chars.php * @param string $string

    * The examined string. *

    * @param int $mode

    * See return values. *

    * @return int[]|string Depending on mode * count_chars returns one of the following: * 0 - an array with the byte-value as key and the frequency of * every byte as value. * 1 - same as 0 but only byte-values with a frequency greater * than zero are listed. * 2 - same as 0 but only byte-values with a frequency equal to * zero are listed. * 3 - a string containing all unique characters is returned. * 4 - a string containing all not used characters is returned. */ #[Pure] function count_chars(string $string, int $mode = 0): array|string {} /** * Split a string into smaller chunks * @link https://php.net/manual/en/function.chunk-split.php * @param string $string

    * The string to be chunked. *

    * @param int $length [optional]

    * The chunk length. *

    * @param string $separator [optional]

    * The line ending sequence. *

    * @return string the chunked string. */ #[Pure] function chunk_split(string $string, int $length = 76, string $separator = "\r\n"): string {} /** * Strip whitespace (or other characters) from the beginning and end of a string * @link https://php.net/manual/en/function.trim.php * @param string $string

    * The string that will be trimmed. *

    * @param string $characters [optional]

    * Optionally, the stripped characters can also be specified using * the charlist parameter. * Simply list all characters that you want to be stripped. With * .. you can specify a range of characters. *

    * @return string The trimmed string. */ #[Pure] function trim(string $string, string $characters = " \n\r\t\v\0"): string {} /** * Strip whitespace (or other characters) from the beginning of a string * @link https://php.net/manual/en/function.ltrim.php * @param string $string

    * The input string. *

    * @param string $characters [optional]

    * You can also specify the characters you want to strip, by means of the * charlist parameter. * Simply list all characters that you want to be stripped. With * .. you can specify a range of characters. *

    * @return string This function returns a string with whitespace stripped from the * beginning of str. * Without the second parameter, * ltrim will strip these characters: * " " (ASCII 32 * (0x20)), an ordinary space. * "\t" (ASCII 9 * (0x09)), a tab. * "\n" (ASCII 10 * (0x0A)), a new line (line feed). * "\r" (ASCII 13 * (0x0D)), a carriage return. * "\0" (ASCII 0 * (0x00)), the NUL-byte. * "\x0B" (ASCII 11 * (0x0B)), a vertical tab. */ #[Pure] function ltrim(string $string, string $characters = " \n\r\t\v\0"): string {} /** * Strip HTML and PHP tags from a string * @link https://php.net/manual/en/function.strip-tags.php * @param string $string

    * The input string. *

    * @param string[]|string|null $allowed_tags [optional]

    * You can use the optional second parameter to specify tags which should * not be stripped. *

    *

    * HTML comments and PHP tags are also stripped. This is hardcoded and * can not be changed with allowable_tags. *

    * @return string the stripped string. */ #[Pure] function strip_tags(string $string, #[LanguageLevelTypeAware(["7.4" => "string[]|string|null"], default: "string|null")] $allowed_tags = null): string {} /** * Calculate the similarity between two strings * @link https://php.net/manual/en/function.similar-text.php * @param string $string1

    * The first string. *

    * @param string $string2

    * The second string. *

    * @param float &$percent [optional]

    * By passing a reference as third argument, * similar_text will calculate the similarity in * percent for you. *

    * @return int the number of matching chars in both strings. */ function similar_text(string $string1, string $string2, &$percent): int {} /** * Split a string by a string * @link https://php.net/manual/en/function.explode.php * @param string $separator

    * The boundary string. *

    * @param string $string

    * The input string. *

    * @param int $limit [optional]

    * If limit is set and positive, the returned array will contain * a maximum of limit elements with the last * element containing the rest of string. *

    *

    * If the limit parameter is negative, all components * except the last -limit are returned. *

    *

    * If the limit parameter is zero, then this is treated as 1. *

    * @return string[]|false If delimiter is an empty string (""), * explode will return false. * If delimiter contains a value that is not * contained in string and a negative * limit is used, then an empty array will be * returned. For any other limit, an array containing * string will be returned. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string[]"], default: "string[]|false")] function explode(string $separator, string $string, int $limit = PHP_INT_MAX) {} /** * Join array elements with a string * @link https://php.net/manual/en/function.implode.php * @param array|string $separator [optional]

    * Defaults to an empty string. This is not the preferred usage of * implode as glue would be * the second parameter and thus, the bad prototype would be used. *

    * @param array|null $array

    * The array of strings to implode. *

    * @return string a string containing a string representation of all the array * elements in the same order, with the glue string between each element. */ #[Pure] function implode(array|string $separator = "", ?array $array): string {} /** * Alias: * {@see implode} * @link https://php.net/manual/en/function.join.php * @param array|string $separator [optional]

    * Defaults to an empty string. This is not the preferred usage of * implode as glue would be * the second parameter and thus, the bad prototype would be used. *

    * @param array|null $array

    * The array of strings to implode. *

    * @return string a string containing a string representation of all the array * elements in the same order, with the glue string between each element. */ #[Pure] function join(array|string $separator = "", ?array $array): string {} /** * Set locale information * @link https://php.net/manual/en/function.setlocale.php * @param int $category

    * category is a named constant specifying the * category of the functions affected by the locale setting: *

      *
    • * LC_ALL for all of the below *
    • *
    • * LC_COLLATE for string comparison, see * {@see strcoll()} *
    • *
    • * LC_CTYPE for character classification and conversion, for * example {@see strtoupper()} *
    • *
    • * LC_MONETARY for {@see localeconv()} *
    • *
    • * LC_NUMERIC for decimal separator (See also * {@see localeconv()}) *
    • *
    • * LC_TIME for date and time formatting with * {@see strftime()} * *
    • *
    • * LC_MESSAGES for system responses (available if PHP was compiled with * libintl) * *
    • *
    * @param string|string[]|int $locales

    * If locale is null or the empty string * "", the locale names will be set from the * values of environment variables with the same names as the above * categories, or from "LANG". *

    *

    * If locale is "0", * the locale setting is not affected, only the current setting is returned. *

    *

    * If locale is an array or followed by additional * parameters then each array element or parameter is tried to be set as * new locale until success. This is useful if a locale is known under * different names on different systems or for providing a fallback * for a possibly not available locale. *

    * @param string|string[] ...$rest * @return string|false

    the new current locale, or false if the locale functionality is * not implemented on your platform, the specified locale does not exist or * the category name is invalid. *

    *

    * An invalid category name also causes a warning message. Category/locale * names can be found in RFC 1766 * and ISO 639. * Different systems have different naming schemes for locales. *

    *

    * The return value of setlocale depends * on the system that PHP is running. It returns exactly * what the system setlocale function returns.

    */ function setlocale( #[ExpectedValues([LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES])] int $category, #[PhpStormStubsElementAvailable(from: '8.0')] $locales, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $rest, ...$rest ): string|false {} /** * Get numeric formatting information * @link https://php.net/manual/en/function.localeconv.php * @return array localeconv returns data based upon the current locale * as set by setlocale. The associative array that is * returned contains the following fields: * * Array element * Description * * * decimal_point * Decimal point character * * * thousands_sep * Thousands separator * * * grouping * Array containing numeric groupings * * * int_curr_symbol * International currency symbol (i.e. USD) * * * currency_symbol * Local currency symbol (i.e. $) * * * mon_decimal_point * Monetary decimal point character * * * mon_thousands_sep * Monetary thousands separator * * * mon_grouping * Array containing monetary groupings * * * positive_sign * Sign for positive values * * * negative_sign * Sign for negative values * * * int_frac_digits * International fractional digits * * * frac_digits * Local fractional digits * * * p_cs_precedes * * true if currency_symbol precedes a positive value, false * if it succeeds one * * * * p_sep_by_space * * true if a space separates currency_symbol from a positive * value, false otherwise * * * * n_cs_precedes * * true if currency_symbol precedes a negative value, false * if it succeeds one * * * * n_sep_by_space * * true if a space separates currency_symbol from a negative * value, false otherwise * * * p_sign_posn * * 0 - Parentheses surround the quantity and currency_symbol * 1 - The sign string precedes the quantity and currency_symbol * 2 - The sign string succeeds the quantity and currency_symbol * 3 - The sign string immediately precedes the currency_symbol * 4 - The sign string immediately succeeds the currency_symbol * * * n_sign_posn * * 0 - Parentheses surround the quantity and currency_symbol * 1 - The sign string precedes the quantity and currency_symbol * 2 - The sign string succeeds the quantity and currency_symbol * 3 - The sign string immediately precedes the currency_symbol * 4 - The sign string immediately succeeds the currency_symbol * * *

    *

    * The p_sign_posn, and n_sign_posn contain a string * of formatting options. Each number representing one of the above listed conditions. *

    *

    * The grouping fields contain arrays that define the way numbers should be * grouped. For example, the monetary grouping field for the nl_NL locale (in * UTF-8 mode with the euro sign), would contain a 2 item array with the * values 3 and 3. The higher the index in the array, the farther left the * grouping is. If an array element is equal to CHAR_MAX, * no further grouping is done. If an array element is equal to 0, the previous * element should be used. */ #[ArrayShape(["decimal_point" => "string", "thousands_sep" => "string", "grouping" => "array", "int_curr_symbol" => "string", "currency_symbol" => "string", "mon_decimal_point" => "string", "mon_thousands_sep" => "string", "mon_grouping" => "string", "positive_sign" => "string", "negative_sign" => "string", "int_frac_digits" => "string", "frac_digits" => "string", "p_cs_precedes" => "bool", "p_sep_by_space" => "bool", "n_cs_precedes" => "bool", "n_sep_by_space" => "bool", "p_sign_posn" => "int", "n_sign_posn" => "int"])] #[Pure(true)] function localeconv(): array {} 'string'], default: '')] public $filtername; #[LanguageLevelTypeAware(['8.1' => 'mixed'], default: '')] public $params; public $stream; /** * @link https://php.net/manual/en/php-user-filter.filter.php * @param resource $in

    is a resource pointing to a bucket brigadebucket objects containing data to be filtered.

    * @param resource $out

    is a resource pointing to a second bucket brigade into which your modified buckets should be placed.

    * @param int &$consumed

    which must always be declared by reference, should be incremented by the length of the data which your filter reads in and alters. In most cases this means you will increment consumed by $bucket->datalen for each $bucket.

    * @param bool $closing

    If the stream is in the process of closing (and therefore this is the last pass through the filterchain), the closing parameter will be set to TRUE * @return int

    * The filter() method must return one of * three values upon completion. *

    * * * * * * * * * * * * * * * * * * * * * * * * */ #[TentativeType] public function filter( $in, $out, &$consumed, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $closing ): int {} /** * @link https://php.net/manual/en/php-user-filter.oncreate.php * @return bool */ #[TentativeType] public function onCreate(): bool {} /** * @link https://php.net/manual/en/php-user-filter.onclose.php */ #[TentativeType] public function onClose(): void {} } /** * @since 8.4 */ final class StreamBucket { public $bucket; public string $data; public int $datalen; public int $dataLength; } /** * Instances of Directory are created by calling the dir() function, not by the new operator. */ class Directory { /** * @var string The directory that was opened. * @removed 8.1 */ public $path; /** * @var string The directory that was opened. * @since 8.1 */ public readonly string $path; /** * @var resource Can be used with other directory functions such as {@see readdir()}, {@see rewinddir()} and {@see closedir()}. * @removed 8.1 */ public $handle; /** * @var resource Can be used with other directory functions such as {@see readdir()}, {@see rewinddir()} and {@see closedir()}. * @since 8.1 */ public readonly mixed $handle; /** * Close directory handle. * Same as closedir(), only dir_handle defaults to $this. * @param resource $dir_handle [optional] * @link https://secure.php.net/manual/en/directory.close.php */ #[TentativeType] public function close(#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $dir_handle = null): void {} /** * Rewind directory handle. * Same as rewinddir(), only dir_handle defaults to $this. * @param resource $dir_handle [optional] * @link https://secure.php.net/manual/en/directory.rewind.php */ #[TentativeType] public function rewind(#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $dir_handle = null): void {} /** * Read entry from directory handle. * Same as readdir(), only dir_handle defaults to $this. * @param resource $dir_handle [optional] * @return string|false * @link https://secure.php.net/manual/en/directory.read.php */ #[TentativeType] public function read(#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $dir_handle = null): string|false {} } /** * Returns the value of a constant * @link https://php.net/manual/en/function.constant.php * @param string $name

    * The constant name. *

    * @return mixed the value of the constant. * @throws Error If the constant is not defined */ #[Pure(true)] function constant(string $name): mixed {} /** * Convert binary data into hexadecimal representation * @link https://php.net/manual/en/function.bin2hex.php * @param string $string

    * A string. *

    * @return string the hexadecimal representation of the given string. */ #[Pure] function bin2hex(string $string): string {} /** * Delays the program execution for the given number of seconds * @link https://php.net/manual/en/function.sleep.php * @param int<0,max> $seconds

    * Halt time in seconds (must be greater than or equal to 0). *

    * @return int Returns zero on success. *

    * If the call was interrupted by a signal, sleep() returns a * non-zero value. On Windows, this value will always be 192 * (the value of the WAIT_IO_COMPLETION constant within the Windows API). * On other platforms, the return value will be the * number of seconds left to sleep. *

    *

    * As of PHP 8.0, if the specified number of seconds is negative, * this function will throw a ValueError. * Before PHP 8.0, an E_WARNING was raised instead, and the function returned false. *

    */ #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function sleep(int $seconds) {} /** * Delay execution in microseconds * @link https://php.net/manual/en/function.usleep.php * @param int<0,max> $microseconds

    * Halt time in micro seconds. A micro second is one millionth of a * second. *

    * @return void */ function usleep(int $microseconds): void {} /** * Delay for a number of seconds and nanoseconds * @link https://php.net/manual/en/function.time-nanosleep.php * @param positive-int $seconds

    * Must be a positive integer. *

    * @param positive-int $nanoseconds

    * Must be a positive integer less than 1 billion. *

    * @return bool|array true on success or false on failure. *

    * If the delay was interrupted by a signal, an associative array will be * returned with the components: * seconds - number of seconds remaining in * the delay * nanoseconds - number of nanoseconds * remaining in the delay *

    */ #[ArrayShape(["seconds" => "int", "nanoseconds" => "int"])] function time_nanosleep(int $seconds, int $nanoseconds): array|bool {} /** * Make the script sleep until the specified time * @link https://php.net/manual/en/function.time-sleep-until.php * @param float $timestamp

    * The timestamp when the script should wake. *

    * @return bool true on success or false on failure. */ function time_sleep_until(float $timestamp): bool {} /** * Parse a time/date generated with strftime * @link https://php.net/manual/en/function.strptime.php * @param string $timestamp

    * The string to parse (e.g. returned from strftime) *

    * @param string $format

    * The format used in date (e.g. the same as * used in strftime). *

    *

    * For more information about the format options, read the * strftime page. *

    * @return array|false an array or false on failure. *

    *

    Return ValueMeaning
    PSFS_PASS_ON * Filter processed successfully with data available in the * out bucket brigade. *
    PSFS_FEED_ME * Filter processed successfully, however no data was available to * return. More data is required from the stream or prior filter. *
    PSFS_ERR_FATAL (default) * The filter experienced an unrecoverable error and cannot continue. *
    * The following parameters are returned in the array * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    parametersDescription
    "tm_sec"Seconds after the minute (0-61)
    "tm_min"Minutes after the hour (0-59)
    "tm_hour"Hour since midnight (0-23)
    "tm_mday"Day of the month (1-31)
    "tm_mon"Months since January (0-11)
    "tm_year"Years since 1900
    "tm_wday"Days since Sunday (0-6)
    "tm_yday"Days since January 1 (0-365)
    "unparsed"the date part which was not * recognized using the specified format
    *

    * @deprecated 8.1 */ #[Pure(true)] #[Deprecated(since: '8.1')] #[ArrayShape([ 'tm_sec' => 'int', 'tm_min' => 'int', 'tm_hour' => 'int', 'tm_mday' => 'int', 'tm_mon' => 'int', 'tm_year' => 'int', 'tm_wday' => 'int', 'tm_yday' => 'int', 'unparsed' => 'string' ])] function strptime(string $timestamp, string $format): array|false {} /** * Flush system output buffer * @link https://php.net/manual/en/function.flush.php * @return void */ function flush(): void {} /** * Wraps a string to a given number of characters * @link https://php.net/manual/en/function.wordwrap.php * @param string $string

    * The input string. *

    * @param int $width [optional]

    * The number of characters at which the string will be wrapped. *

    * @param string $break [optional]

    * The line is broken using the optional * break parameter. *

    * @param bool $cut_long_words [optional]

    * If the cut is set to true, the string is * always wrapped at or before the specified width. So if you have * a word that is larger than the given width, it is broken apart. * (See second example). *

    * @return string the given string wrapped at the specified length. */ #[Pure] function wordwrap(string $string, int $width = 75, string $break = "\n", bool $cut_long_words = false): string {} /** * Convert special characters to HTML entities * @link https://php.net/manual/en/function.htmlspecialchars.php * @param string $string

    * The {@link https://secure.php.net/manual/en/language.types.string.php string} being converted. *

    * @param int $flags [optional]

    * A bitmask of one or more of the following flags, which specify how to handle quotes, * invalid code unit sequences and the used document type. The default is * ENT_COMPAT | ENT_HTML401. *

    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    Available flags constants
    Constant NameDescription
    ENT_COMPATWill convert double-quotes and leave single-quotes alone.
    ENT_QUOTESWill convert both double and single quotes.
    ENT_NOQUOTESWill leave both double and single quotes unconverted.
    ENT_IGNORE * Silently discard invalid code unit sequences instead of returning * an empty string. Using this flag is discouraged as it * {@link https://unicode.org/reports/tr36/#Deletion_of_Noncharacters » may have security implications}. *
    ENT_SUBSTITUTE * Replace invalid code unit sequences with a Unicode Replacement Character * U+FFFD (UTF-8) or &#FFFD; (otherwise) instead of returning an empty string. *
    ENT_DISALLOWED * Replace invalid code points for the given document type with a * Unicode Replacement Character U+FFFD (UTF-8) or &#FFFD; * (otherwise) instead of leaving them as is. This may be useful, for * instance, to ensure the well-formedness of XML documents with * embedded external content. *
    ENT_HTML401 * Handle code as HTML 4.01. *
    ENT_XML1 * Handle code as XML 1. *
    ENT_XHTML * Handle code as XHTML. *
    ENT_HTML5 * Handle code as HTML 5. *
    * @param string|null $encoding

    * Defines encoding used in conversion. * If omitted, the default value for this argument is ISO-8859-1 in * versions of PHP prior to 5.4.0, and UTF-8 from PHP 5.4.0 onwards. *

    *

    * For the purposes of this function, the encodings * ISO-8859-1, ISO-8859-15, * UTF-8, cp866, * cp1251, cp1252, and * KOI8-R are effectively equivalent, provided the * string itself is valid for the encoding, as * the characters affected by htmlspecialchars() occupy * the same positions in all of these encodings. *

    * @param bool $double_encode [optional]

    * When double_encode is turned off PHP will not * encode existing html entities, the default is to convert everything. *

    * @return string The converted string. */ #[Pure] function htmlspecialchars(string $string, int $flags = ENT_QUOTES|ENT_SUBSTITUTE, ?string $encoding = null, bool $double_encode = true): string {} /** * Convert all applicable characters to HTML entities * @link https://php.net/manual/en/function.htmlentities.php * @param string $string

    * The input string. *

    * @param int $flags [optional]

    * Like htmlspecialchars, the optional second * quote_style parameter lets you define what will * be done with 'single' and "double" quotes. It takes on one of three * constants with the default being ENT_COMPAT: *

    * Available quote_style constants * * * * * * * * * * * * * * * * *
    Constant NameDescription
    ENT_COMPATWill convert double-quotes and leave single-quotes alone.
    ENT_QUOTESWill convert both double and single quotes.
    ENT_NOQUOTESWill leave both double and single quotes unconverted.
    *

    * @param string|null $encoding [optional]

    * Like htmlspecialchars, it takes an optional * third argument charset which defines character * set used in conversion. * Presently, the ISO-8859-1 character set is used as the default. *

    * @param bool $double_encode [optional]

    * When double_encode is turned off PHP will not * encode existing html entities. The default is to convert everything. *

    * @return string the encoded string. */ #[Pure] function htmlentities(string $string, int $flags = ENT_QUOTES|ENT_SUBSTITUTE, ?string $encoding, bool $double_encode = true): string {} /** * Convert HTML entities to their corresponding characters * @link https://php.net/manual/en/function.html-entity-decode.php * @param string $string

    * The input string. *

    * @param int $flags [optional]

    * The optional second quote_style parameter lets * you define what will be done with 'single' and "double" quotes. It takes * on one of three constants with the default being * ENT_COMPAT: *

    * Available quote_style constants * * * * * * * * * * * * * * * * *
    Constant NameDescription
    ENT_COMPATWill convert double-quotes and leave single-quotes alone.
    ENT_QUOTESWill convert both double and single quotes.
    ENT_NOQUOTESWill leave both double and single quotes unconverted.
    *

    * @param string|null $encoding [optional]

    * The ISO-8859-1 character set is used as default for the optional third * charset. This defines the character set used in * conversion. *

    * @return string the decoded string. */ #[Pure] function html_entity_decode(string $string, int $flags = ENT_QUOTES|ENT_SUBSTITUTE, ?string $encoding): string {} /** * Convert special HTML entities back to characters * @link https://php.net/manual/en/function.htmlspecialchars-decode.php * @param string $string

    * The string to decode *

    * @param int $flags [optional]

    * The quote style. One of the following constants: *

    * quote_style constants * * * * * * * * * * * * * * * * *
    Constant NameDescription
    ENT_COMPATWill convert double-quotes and leave single-quotes alone * (default)
    ENT_QUOTESWill convert both double and single quotes
    ENT_NOQUOTESWill leave both double and single quotes unconverted
    *

    * @return string the decoded string. */ #[Pure] function htmlspecialchars_decode(string $string, int $flags = ENT_QUOTES|ENT_SUBSTITUTE): string {} /** * Returns the translation table used by htmlspecialchars and htmlentities * @link https://php.net/manual/en/function.get-html-translation-table.php * @param int $table

    * There are two new constants (HTML_ENTITIES, * HTML_SPECIALCHARS) that allow you to specify the * table you want. *

    * @param int $flags [optional]

    * Like the htmlspecialchars and * htmlentities functions you can optionally specify * the quote_style you are working with. * See the description * of these modes in htmlspecialchars. *

    * @param string $encoding [optional]

    * Encoding to use. * If omitted, the default value for this argument is ISO-8859-1 in * versions of PHP prior to 5.4.0, and UTF-8 from PHP 5.4.0 onwards. *

    * * *

    * The following character sets are supported: *

    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    Supported charsets
    CharsetAliasesDescription
    ISO-8859-1ISO8859-1 * Western European, Latin-1. *
    ISO-8859-5ISO8859-5 * Little used cyrillic charset (Latin/Cyrillic). *
    ISO-8859-15ISO8859-15 * Western European, Latin-9. Adds the Euro sign, French and Finnish * letters missing in Latin-1 (ISO-8859-1). *
    UTF-8  * ASCII compatible multi-byte 8-bit Unicode. *
    cp866ibm866, 866 * DOS-specific Cyrillic charset. *
    cp1251Windows-1251, win-1251, 1251 * Windows-specific Cyrillic charset. *
    cp1252Windows-1252, 1252 * Windows specific charset for Western European. *
    KOI8-Rkoi8-ru, koi8r * Russian. *
    BIG5950 * Traditional Chinese, mainly used in Taiwan. *
    GB2312936 * Simplified Chinese, national standard character set. *
    BIG5-HKSCS  * Big5 with Hong Kong extensions, Traditional Chinese. *
    Shift_JISSJIS, SJIS-win, cp932, 932 * Japanese *
    EUC-JPEUCJP, eucJP-win * Japanese *
    MacRoman  * Charset that was used by Mac OS. *
    ''  * An empty string activates detection from script encoding (Zend multibyte), * {@link https://php.net/manual/en/ini.core.php#ini.default-charset default_charset} and current * locale {@link https://php.net/manual/en/function.nl-langinfo.php nl_langinfo()} and * {@link https://php.net/manual/en/function.setlocale.php setlocale()}), in this order. Not recommended. *
    * *

    Note: * * Any other character sets are not recognized. The default encoding will be * used instead and a warning will be emitted. * *

    * @return array the translation table as an array. */ #[Pure] function get_html_translation_table( int $table = 0, int $flags = ENT_QUOTES|ENT_SUBSTITUTE, #[PhpStormStubsElementAvailable(from: '7.0')] string $encoding = "UTF-8" ): array {} /** * Calculate the sha1 hash of a string * @link https://php.net/manual/en/function.sha1.php * @param string $string

    * The input string. *

    * @param bool $binary [optional]

    * If the optional binary is set to true, * then the sha1 digest is instead returned in raw binary format with a * length of 20, otherwise the returned value is a 40-character * hexadecimal number. *

    * @return string the sha1 hash as a string. */ #[Pure] function sha1(string $string, bool $binary = false): string {} /** * Calculate the sha1 hash of a file * @link https://php.net/manual/en/function.sha1-file.php * @param string $filename

    * The filename *

    * @param bool $binary [optional]

    * When true, returns the digest in raw binary format with a length of * 20. *

    * @return string|false a string on success, false otherwise. */ #[Pure(true)] function sha1_file(string $filename, bool $binary = false): string|false {} /** * Calculate the md5 hash of a string * @link https://php.net/manual/en/function.md5.php * @param string $string

    * The string. *

    * @param bool $binary [optional]

    * If the optional raw_output is set to true, * then the md5 digest is instead returned in raw binary format with a * length of 16. *

    * @return string the hash as a 32-character hexadecimal number. */ #[Pure] function md5(string $string, bool $binary = false): string {} /** * Calculates the md5 hash of a given file * @link https://php.net/manual/en/function.md5-file.php * @param string $filename

    * The filename *

    * @param bool $binary [optional]

    * When true, returns the digest in raw binary format with a length of * 16. *

    * @return string|false a string on success, false otherwise. */ #[Pure(true)] function md5_file(string $filename, bool $binary = false): string|false {} /** * Calculates the crc32 polynomial of a string * @link https://php.net/manual/en/function.crc32.php * @param string $string

    * The data. *

    * @return int the crc32 checksum of str as an integer..1 */ #[Pure] function crc32(string $string): int {} /** * Parse a binary IPTC block into single tags. * Note: This function does not require the GD image library. * @link https://php.net/manual/en/function.iptcparse.php * @param string $iptc_block

    * A binary IPTC block. *

    * @return array|false an array using the tagmarker as an index and the value as the * value. It returns false on error or if no IPTC data was found. */ #[Pure] function iptcparse(string $iptc_block): array|false {} /** * Embeds binary IPTC data into a JPEG image. * Note: This function does not require the GD image library. * @link https://php.net/manual/en/function.iptcembed.php * @param string $iptc_data

    * The data to be written. *

    * @param string $filename

    * Path to the JPEG image. *

    * @param int $spool

    * Spool flag. If the spool flag is less than 2 then the JPEG will * be returned as a string. Otherwise the JPEG will be printed to * STDOUT. *

    * @return string|bool If spool is less than 2, the JPEG will be returned, or false on * failure. Otherwise returns true on success or false on failure. */ function iptcembed(string $iptc_data, string $filename, int $spool = 0): string|bool {} /** * Get the size of an image * @link https://php.net/manual/en/function.getimagesize.php * @param string $filename

    * This parameter specifies the file you wish to retrieve information * about. It can reference a local file or (configuration permitting) a * remote file using one of the supported streams. *

    * @param array &$image_info [optional]

    * This optional parameter allows you to extract some extended * information from the image file. Currently, this will return the * different JPG APP markers as an associative array. * Some programs use these APP markers to embed text information in * images. A very common one is to embed * IPTC information in the APP13 marker. * You can use the iptcparse function to parse the * binary APP13 marker into something readable. *

    * @return array|false an array with 7 elements. *

    * Index 0 and 1 contains respectively the width and the height of the image. *

    *

    * Some formats may contain no image or may contain multiple images. In these * cases, getimagesize might not be able to properly * determine the image size. getimagesize will return * zero for width and height in these cases. *

    *

    * Index 2 is one of the IMAGETYPE_XXX constants indicating * the type of the image. *

    *

    * Index 3 is a text string with the correct * height="yyy" width="xxx" string that can be used * directly in an IMG tag. *

    *

    * mime is the correspondant MIME type of the image. * This information can be used to deliver images with correct the HTTP * Content-type header: * getimagesize and MIME types *

    *

    * channels will be 3 for RGB pictures and 4 for CMYK * pictures. *

    *

    * bits is the number of bits for each color. *

    *

    * For some image types, the presence of channels and * bits values can be a bit * confusing. As an example, GIF always uses 3 channels * per pixel, but the number of bits per pixel cannot be calculated for an * animated GIF with a global color table. *

    *

    * On failure, false is returned. *

    */ #[ArrayShape([0 => "int", 1 => "int", 2 => "int", 3 => "string", "bits" => "int", "channels" => "int", "mime" => "string"])] function getimagesize(string $filename, &$image_info): array|false {} /** * Get Mime-Type for image-type returned by getimagesize, exif_read_data, exif_thumbnail, exif_imagetype * @link https://php.net/manual/en/function.image-type-to-mime-type.php * @param int $image_type

    * One of the IMAGETYPE_XXX constants. *

    * @return string The returned values are as follows * * Returned values Constants * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    imagetypeReturned value
    IMAGETYPE_GIFimage/gif
    IMAGETYPE_JPEGimage/jpeg
    IMAGETYPE_PNGimage/png
    IMAGETYPE_SWFapplication/x-shockwave-flash
    IMAGETYPE_PSDimage/psd
    IMAGETYPE_BMPimage/bmp
    IMAGETYPE_TIFF_II (intel byte order)image/tiff
    * IMAGETYPE_TIFF_MM (motorola byte order) * image/tiff
    IMAGETYPE_JPCapplication/octet-stream
    IMAGETYPE_JP2image/jp2
    IMAGETYPE_JPXapplication/octet-stream
    IMAGETYPE_JB2application/octet-stream
    IMAGETYPE_SWCapplication/x-shockwave-flash
    IMAGETYPE_IFFimage/iff
    IMAGETYPE_WBMPimage/vnd.wap.wbmp
    IMAGETYPE_XBMimage/xbm
    IMAGETYPE_ICOimage/vnd.microsoft.icon
    */ #[Pure] function image_type_to_mime_type(int $image_type): string {} /** * Get file extension for image type * @link https://php.net/manual/en/function.image-type-to-extension.php * @param int $image_type

    * One of the IMAGETYPE_XXX constant. *

    * @param bool $include_dot [optional]

    * Removed since 8.0. * Whether to prepend a dot to the extension or not. Default to true. *

    * @return string|false A string with the extension corresponding to the given image type, or false on failure. */ #[Pure] function image_type_to_extension(int $image_type, bool $include_dot = true): string|false {} /** * Outputs information about PHP's configuration * @link https://php.net/manual/en/function.phpinfo.php * @param int $flags [optional]

    * The output may be customized by passing one or more of the * following constants bitwise values summed * together in the optional what parameter. * One can also combine the respective constants or bitwise values * together with the or operator. *

    *

    *

    * phpinfo options * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    Name (constant)ValueDescription
    INFO_GENERAL1 * The configuration line, "php.ini" location, build date, Web * Server, System and more. *
    INFO_CREDITS2 * PHP Credits. See also phpcredits. *
    INFO_CONFIGURATION4 * Current Local and Main values for PHP directives. See * also ini_get. *
    INFO_MODULES8 * Loaded modules and their respective settings. See also * get_loaded_extensions. *
    INFO_ENVIRONMENT16 * Environment Variable information that's also available in * $_ENV. *
    INFO_VARIABLES32 * Shows all * predefined variables from EGPCS (Environment, GET, * POST, Cookie, Server). *
    INFO_LICENSE64 * PHP License information. See also the license FAQ. *
    INFO_ALL-1 * Shows all of the above. *
    *

    * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function phpinfo(#[ExpectedValues(flags: [INFO_GENERAL, INFO_CREDITS, INFO_CONFIGURATION, INFO_MODULES, INFO_ENVIRONMENT, INFO_VARIABLES, INFO_LICENSE, INFO_ALL])] int $flags = INFO_ALL): bool {} /** * Gets the current PHP version * @link https://php.net/manual/en/function.phpversion.php * @param string|null $extension [optional]

    * An optional extension name. *

    * @return string|false If the optional extension parameter is * specified, phpversion returns the version of that * extension, or false if there is no version information associated or * the extension isn't enabled. */ #[Pure] function phpversion(?string $extension): string|false {} /** * Prints out the credits for PHP * @link https://php.net/manual/en/function.phpcredits.php * @param int $flags [optional]

    * To generate a custom credits page, you may want to use the * flags parameter. *

    *

    *

    * Pre-defined phpcredits flags * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    namedescription
    CREDITS_ALL * All the credits, equivalent to using: CREDITS_DOCS + * CREDITS_GENERAL + CREDITS_GROUP + * CREDITS_MODULES + CREDITS_FULLPAGE. * It generates a complete stand-alone HTML page with the appropriate tags. *
    CREDITS_DOCSThe credits for the documentation team
    CREDITS_FULLPAGE * Usually used in combination with the other flags. Indicates * that a complete stand-alone HTML page needs to be * printed including the information indicated by the other * flags. *
    CREDITS_GENERAL * General credits: Language design and concept, PHP 4.0 * authors and SAPI module. *
    CREDITS_GROUPA list of the core developers
    CREDITS_MODULES * A list of the extension modules for PHP, and their authors *
    CREDITS_SAPI * A list of the server API modules for PHP, and their authors *
    *

    * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function phpcredits(int $flags = CREDITS_ALL): bool {} /** * Gets the logo guid * @removed 5.5 * @link https://php.net/manual/en/function.php-logo-guid.php * @return string PHPE9568F34-D428-11d2-A769-00AA001ACF42. */ #[Pure] function php_logo_guid(): string {} /** * @removed 5.5 */ function php_real_logo_guid() {} /** * @removed 5.5 */ function php_egg_logo_guid() {} /** * Gets the Zend guid * @removed 5.5 * @link https://php.net/manual/en/function.zend-logo-guid.php * @return string PHPE9568F35-D428-11d2-A769-00AA001ACF42. */ function zend_logo_guid(): string {} /** * Returns the type of interface between web server and PHP * @link https://php.net/manual/en/function.php-sapi-name.php * @return string|false the interface type, as a lowercase string, or false on failure. *

    * Although not exhaustive, the possible return values include * aolserver, apache, * apache2filter, apache2handler, * caudium, cgi (until PHP 5.3), * cgi-fcgi, cli, * continuity, embed, * isapi, litespeed, * milter, nsapi, * phttpd, pi3web, roxen, * thttpd, tux, and webjames. *

    */ #[Pure] #[ExpectedValues(['cli', 'phpdbg', 'embed', 'apache', 'apache2handler', 'cgi-fcgi', 'cli-server', 'fpm-fcgi', 'litespeed'])] function php_sapi_name(): string|false {} /** * Returns information about the operating system PHP is running on * @link https://php.net/manual/en/function.php-uname.php * @param string $mode [optional]

    * mode is a single character that defines what * information is returned: * 'a': This is the default. Contains all modes in * the sequence "s n r v m".

    * @return string the description, as a string. */ #[Pure(true)] function php_uname(#[PhpStormStubsElementAvailable(from: '7.0')] string $mode = 'a'): string {} /** * Return a list of .ini files parsed from the additional ini dir * @link https://php.net/manual/en/function.php-ini-scanned-files.php * @return string|false a comma-separated string of .ini files on success. Each comma is * followed by a newline. If the directive --with-config-file-scan-dir wasn't set, * false is returned. If it was set and the directory was empty, an * empty string is returned. If a file is unrecognizable, the file will * still make it into the returned string but a PHP error will also result. * This PHP error will be seen both at compile time and while using * php_ini_scanned_files. */ #[Pure] function php_ini_scanned_files(): string|false {} /** * Retrieve a path to the loaded php.ini file * @link https://php.net/manual/en/function.php-ini-loaded-file.php * @return string|false The loaded "php.ini" path, or false if one is not loaded. * @since 5.2.4 */ #[Pure] function php_ini_loaded_file(): string|false {} /** * String comparisons using a "natural order" algorithm * @link https://php.net/manual/en/function.strnatcmp.php * @param string $string1

    * The first string. *

    * @param string $string2

    * The second string. *

    * @return int Similar to other string comparison functions, this one returns < 0 if * str1 is less than str2; > * 0 if str1 is greater than * str2, and 0 if they are equal. */ #[Pure] function strnatcmp(string $string1, string $string2): int {} /** * Case insensitive string comparisons using a "natural order" algorithm * @link https://php.net/manual/en/function.strnatcasecmp.php * @param string $string1

    * The first string. *

    * @param string $string2

    * The second string. *

    * @return int Similar to other string comparison functions, this one returns < 0 if * str1 is less than str2 > * 0 if str1 is greater than * str2, and 0 if they are equal. */ #[Pure] function strnatcasecmp(string $string1, string $string2): int {} /** * Count the number of substring occurrences * @link https://php.net/manual/en/function.substr-count.php * @param string $haystack

    * The string to search in *

    * @param string $needle

    * The substring to search for *

    * @param int $offset

    * The offset where to start counting. If the offset is negative, * counting starts from the end of the string. *

    * @param int|null $length [optional]

    * The maximum length after the specified offset to search for the * substring. It outputs a warning if the offset plus the length is * greater than the haystack length. A negative length counts from * the end of haystack. *

    * @return int<0,max> This functions returns an integer. */ #[Pure] function substr_count(string $haystack, string $needle, int $offset = 0, ?int $length): int {} /** * Finds the length of the initial segment of a string consisting * entirely of characters contained within a given mask. * @link https://php.net/manual/en/function.strspn.php * @param string $string

    * The string to examine. *

    * @param string $characters

    * The list of allowable characters to include in counted segments. *

    * @param int $offset

    * The position in subject to * start searching. *

    *

    * If start is given and is non-negative, * then strspn will begin * examining subject at * the start'th position. For instance, in * the string 'abcdef', the character at * position 0 is 'a', the * character at position 2 is * 'c', and so forth. *

    *

    * If start is given and is negative, * then strspn will begin * examining subject at * the start'th position from the end * of subject. *

    * @param int|null $length [optional]

    * The length of the segment from subject * to examine. *

    *

    * If length is given and is non-negative, * then subject will be examined * for length characters after the starting * position. *

    *

    * If lengthis given and is negative, * then subject will be examined from the * starting position up to length * characters from the end of subject. *

    * @return int the length of the initial segment of str1 * which consists entirely of characters in str2. */ #[Pure] function strspn(string $string, string $characters, int $offset = 0, ?int $length): int {} /** * Find length of initial segment not matching mask * @link https://php.net/manual/en/function.strcspn.php * @param string $string

    * The first string. *

    * @param string $characters

    * The second string. *

    * @param int $offset

    * The start position of the string to examine. *

    * @param int|null $length [optional]

    * The length of the string to examine. *

    * @return int the length of the segment as an integer. */ #[Pure] function strcspn(string $string, string $characters, int $offset = 0, ?int $length): int {} /** * Tokenize string * Note that only the first call to strtok uses the string argument. * Every subsequent call to strtok only needs the token to use, as it keeps track of where it is in the current string. * To start over, or to tokenize a new string you simply call strtok with the string argument again to initialize it. * Note that you may put multiple tokens in the token parameter. * The string will be tokenized when any one of the characters in the argument are found. * @link https://php.net/manual/en/function.strtok.php * @param string $string

    * The string being split up into smaller strings (tokens). *

    * @param string|null $token

    * The delimiter used when splitting up str. *

    * @return string|false A string token. */ function strtok( string $string, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] $token, #[PhpStormStubsElementAvailable(from: '7.1')] ?string $token = null ): string|false {} */ function request_parse_body(?array $options = null): array {} /** * @since 8.4 */ function fpow(float $num1, float $num2): float {} /** * @since 8.4 */ enum RoundingMode implements \UnitEnum { case HalfAwayFromZero; case HalfTowardsZero; case HalfEven; case HalfOdd; case TowardsZero; case AwayFromZero; case NegativeInfinity; case PositiveInfinity; public static function cases(): array {} } * The encoded data. *

    * @param bool $strict [optional]

    * Returns false if input contains character from outside the base64 * alphabet. *

    * @return string|false the original data or false on failure. The returned data may be * binary. */ #[Pure] function base64_decode(string $string, bool $strict = false): string|false {} /** * Encodes data with MIME base64 * @link https://php.net/manual/en/function.base64-encode.php * @param string $string

    * The data to encode. *

    * @return string The encoded data, as a string. */ #[Pure] function base64_encode(string $string): string {} /** * Uuencode a string * @link https://php.net/manual/en/function.convert-uuencode.php * @param string $string

    * The data to be encoded. *

    * @return string the uuencoded data. */ #[Pure] function convert_uuencode(string $string): string {} /** * Decode a uuencoded string * @link https://php.net/manual/en/function.convert-uudecode.php * @param string $string

    * The uuencoded data. *

    * @return string|false the decoded data as a string. */ #[Pure] function convert_uudecode(string $string): string|false {} /** * Absolute value * @link https://php.net/manual/en/function.abs.php * @param int|float $num

    * The numeric value to process *

    * @return float|int The absolute value of number. If the * argument number is * of type float, the return type is also float, * otherwise it is integer (as float usually has a * bigger value range than integer). */ #[Pure] function abs(int|float $num): int|float {} /** * Round fractions up * @link https://php.net/manual/en/function.ceil.php * @param int|float $num

    * The value to round *

    * @return float|false value rounded up to the next highest * integer. * The return value of ceil is still of type * float as the value range of float is * usually bigger than that of integer. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "float"], default: "float|false")] function ceil(int|float $num) {} /** * Round fractions down * @link https://php.net/manual/en/function.floor.php * @param int|float $num

    * The numeric value to round *

    * @return float|false value rounded to the next lowest integer. * The return value of floor is still of type * float because the value range of float is * usually bigger than that of integer. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "float"], default: "float|false")] function floor(int|float $num) {} /** * Returns the rounded value of val to specified precision (number of digits after the decimal point). * precision can also be negative or zero (default). * Note: PHP doesn't handle strings like "12,300.2" correctly by default. See converting from strings. * @link https://php.net/manual/en/function.round.php * @param int|float $num

    * The value to round *

    * @param int $precision [optional]

    * The optional number of decimal digits to round to. *

    * @param int $mode [optional]

    * One of PHP_ROUND_HALF_UP, * PHP_ROUND_HALF_DOWN, * PHP_ROUND_HALF_EVEN, or * PHP_ROUND_HALF_ODD. *

    * @return float The rounded value */ #[Pure] function round(int|float $num, int $precision = 0, #[LanguageLevelTypeAware(['8.4' => 'RoundingMode|int'], default: 'int')] $mode = 0): float {} /** * Sine * @link https://php.net/manual/en/function.sin.php * @param float $num

    * A value in radians *

    * @return float The sine of arg */ #[Pure] function sin(float $num): float {} /** * Cosine * @link https://php.net/manual/en/function.cos.php * @param float $num

    * An angle in radians *

    * @return float The cosine of arg */ #[Pure] function cos(float $num): float {} /** * Tangent * @link https://php.net/manual/en/function.tan.php * @param float $num

    * The argument to process in radians *

    * @return float The tangent of arg */ #[Pure] function tan(float $num): float {} /** * Arc sine * @link https://php.net/manual/en/function.asin.php * @param float $num

    * The argument to process *

    * @return float The arc sine of arg in radians */ #[Pure] function asin(float $num): float {} /** * Arc cosine * @link https://php.net/manual/en/function.acos.php * @param float $num

    * The argument to process *

    * @return float The arc cosine of arg in radians. */ #[Pure] function acos(float $num): float {} /** * Arc tangent * @link https://php.net/manual/en/function.atan.php * @param float $num

    * The argument to process *

    * @return float The arc tangent of arg in radians. */ #[Pure] function atan(float $num): float {} /** * Inverse hyperbolic tangent * @link https://php.net/manual/en/function.atanh.php * @param float $num

    * The argument to process *

    * @return float Inverse hyperbolic tangent of arg */ #[Pure] function atanh(float $num): float {} /** * Arc tangent of two variables * @link https://php.net/manual/en/function.atan2.php * @param float $y

    * Dividend parameter *

    * @param float $x

    * Divisor parameter *

    * @return float The arc tangent of y/x * in radians. */ #[Pure] function atan2(float $y, float $x): float {} /** * Hyperbolic sine * @link https://php.net/manual/en/function.sinh.php * @param float $num

    * The argument to process *

    * @return float The hyperbolic sine of arg */ #[Pure] function sinh(float $num): float {} /** * Hyperbolic cosine * @link https://php.net/manual/en/function.cosh.php * @param float $num

    * The argument to process *

    * @return float The hyperbolic cosine of arg */ #[Pure] function cosh(float $num): float {} /** * Hyperbolic tangent * @link https://php.net/manual/en/function.tanh.php * @param float $num

    * The argument to process *

    * @return float The hyperbolic tangent of arg */ #[Pure] function tanh(float $num): float {} /** * Inverse hyperbolic sine * @link https://php.net/manual/en/function.asinh.php * @param float $num

    * The argument to process *

    * @return float The inverse hyperbolic sine of arg */ #[Pure] function asinh(float $num): float {} /** * Inverse hyperbolic cosine * @link https://php.net/manual/en/function.acosh.php * @param float $num

    * The value to process *

    * @return float The inverse hyperbolic cosine of arg */ #[Pure] function acosh(float $num): float {} /** * Returns exp(number) - 1, computed in a way that is accurate even * when the value of number is close to zero * @link https://php.net/manual/en/function.expm1.php * @param float $num

    * The argument to process *

    * @return float 'e' to the power of arg minus one */ #[Pure] function expm1(float $num): float {} /** * Returns log(1 + number), computed in a way that is accurate even when * the value of number is close to zero * @link https://php.net/manual/en/function.log1p.php * @param float $num

    * The argument to process *

    * @return float log(1 + number) */ #[Pure] function log1p(float $num): float {} /** * Get value of pi * @link https://php.net/manual/en/function.pi.php * @return float The value of pi as float. */ #[Pure] function pi(): float {} /** * Finds whether a value is a legal finite number * @link https://php.net/manual/en/function.is-finite.php * @param float $num

    * The value to check *

    * @return bool true if val is a legal finite * number within the allowed range for a PHP float on this platform, * else false. */ #[Pure] function is_finite(float $num): bool {} /** * Finds whether a value is not a number * @link https://php.net/manual/en/function.is-nan.php * @param float $num

    * The value to check *

    * @return bool true if val is 'not a number', * else false. */ #[Pure] function is_nan(float $num): bool {} /** * Integer division * @link https://php.net/manual/en/function.intdiv.php * @param int $num1

    Number to be divided.

    * @param int $num2

    Number which divides the dividend

    * @return int * @since 7.0 * @throws DivisionByZeroError

    if divisor is 0

    * @throws ArithmeticError

    if the dividend is PHP_INT_MIN and the divisor is -1

    */ #[Pure] function intdiv(int $num1, int $num2): int {} /** * Finds whether a value is infinite * @link https://php.net/manual/en/function.is-infinite.php * @param float $num

    * The value to check *

    * @return bool true if val is infinite, else false. */ #[Pure] function is_infinite(float $num): bool {} /** * Exponential expression * @link https://php.net/manual/en/function.pow.php * @param mixed $num

    * The base to use *

    * @param mixed $exponent

    * The exponent *

    * @return object|int|float base raised to the power of exp. * If the result can be represented as integer it will be returned as type * integer, else it will be returned as type float. * If the power cannot be computed false will be returned instead. */ #[Pure] function pow(mixed $num, mixed $exponent): object|int|float {} /** * Calculates the exponent of e * @link https://php.net/manual/en/function.exp.php * @param float $num

    * The argument to process *

    * @return float 'e' raised to the power of arg */ #[Pure] function exp(float $num): float {} /** * Natural logarithm * @link https://php.net/manual/en/function.log.php * @param float $num

    * The value to calculate the logarithm for *

    * @param float $base [optional]

    * The optional logarithmic base to use * (defaults to 'e' and so to the natural logarithm). *

    * @return float The logarithm of arg to * base, if given, or the * natural logarithm. */ #[Pure] function log(float $num, float $base = M_E): float {} /** * Base-10 logarithm * @link https://php.net/manual/en/function.log10.php * @param float $num

    * The argument to process *

    * @return float The base-10 logarithm of arg */ #[Pure] function log10(float $num): float {} /** * Square root * @link https://php.net/manual/en/function.sqrt.php * @param float $num

    * The argument to process *

    * @return float The square root of arg * or the special value NAN for negative numbers. */ #[Pure] function sqrt(float $num): float {} /** * Calculate the length of the hypotenuse of a right-angle triangle * @link https://php.net/manual/en/function.hypot.php * @param float $x

    * Length of first side *

    * @param float $y

    * Length of second side *

    * @return float Calculated length of the hypotenuse */ #[Pure] function hypot(float $x, float $y): float {} /** * Converts the number in degrees to the radian equivalent * @link https://php.net/manual/en/function.deg2rad.php * @param float $num

    * Angular value in degrees *

    * @return float The radian equivalent of number */ #[Pure] function deg2rad(float $num): float {} /** * Converts the radian number to the equivalent number in degrees * @link https://php.net/manual/en/function.rad2deg.php * @param float $num

    * A radian value *

    * @return float The equivalent of number in degrees */ #[Pure] function rad2deg(float $num): float {} /** * Binary to decimal * @link https://php.net/manual/en/function.bindec.php * @param string $binary_string

    * The binary string to convert *

    * @return int|float The decimal value of binary_string */ #[Pure] function bindec(string $binary_string): int|float {} /** * Hexadecimal to decimal * @link https://php.net/manual/en/function.hexdec.php * @param string $hex_string

    * The hexadecimal string to convert *

    * @return int|float The decimal representation of hex_string */ #[Pure] function hexdec(string $hex_string): int|float {} /** * Octal to decimal * @link https://php.net/manual/en/function.octdec.php * @param string $octal_string

    * The octal string to convert *

    * @return int|float The decimal representation of octal_string */ #[Pure] function octdec(string $octal_string): int|float {} /** * Decimal to binary * @link https://php.net/manual/en/function.decbin.php * @param int $num

    * Decimal value to convert *

    * * Range of inputs on 32-bit machines * * * * * * * * * * * * * * * * * * * * * * ... normal progression ... * * * * * * * * * * * * * * * * * * ... normal progression ... * * * * * * * * * * * *
    positive numbernegative numberreturn value
    00
    11
    210
    21474836461111111111111111111111111111110
    2147483647 (largest signed integer)1111111111111111111111111111111 (31 1's)
    2147483648-214748364810000000000000000000000000000000
    4294967294-211111111111111111111111111111110
    4294967295 (largest unsigned integer)-111111111111111111111111111111111 (32 1's)
    * * Range of inputs on 64-bit machines * * * * * * * * * * * * * * * * * * * * * * ... normal progression ... * * * * * * * * * * * * * * * * * * ... normal progression ... * * * * * * * * * * * *
    positive numbernegative numberreturn value
    00
    11
    210
    9223372036854775806111111111111111111111111111111111111111111111111111111111111110
    9223372036854775807 (largest signed integer)111111111111111111111111111111111111111111111111111111111111111 (31 1's)
    -92233720368547758081000000000000000000000000000000000000000000000000000000000000000
    -21111111111111111111111111111111111111111111111111111111111111110
    -11111111111111111111111111111111111111111111111111111111111111111 (64 1's)
    * @return string Binary string representation of number */ #[Pure] function decbin(int $num): string {} /** * Decimal to octal * @link https://php.net/manual/en/function.decoct.php * @param int $num

    * Decimal value to convert *

    * @return string Octal string representation of number */ #[Pure] function decoct(int $num): string {} /** * Decimal to hexadecimal * @link https://php.net/manual/en/function.dechex.php * @param int $num

    * Decimal value to convert *

    * @return string Hexadecimal string representation of number */ #[Pure] function dechex(int $num): string {} /** * Convert a number between arbitrary bases * @link https://php.net/manual/en/function.base-convert.php * @param string $num

    * The number to convert *

    * @param int $from_base

    * The base number is in *

    * @param int $to_base

    * The base to convert number to *

    * @return string number converted to base tobase */ #[Pure] function base_convert(string $num, int $from_base, int $to_base): string {} /** * Format a number with grouped thousands * @link https://php.net/manual/en/function.number-format.php * @param float $num

    * The number being formatted. *

    * @param int $decimals [optional]

    * Sets the number of decimal points. *

    * @param string|null $decimal_separator [optional] * @param string|null $thousands_separator [optional] * @return string A formatted version of number. */ #[Pure] function number_format(float $num, int $decimals = 0, ?string $decimal_separator = '.', ?string $thousands_separator = ','): string {} /** * Returns the floating point remainder (modulo) of the division * of the arguments * @link https://php.net/manual/en/function.fmod.php * @param float $num1

    * The dividend *

    * @param float $num2

    * The divisor *

    * @return float The floating point remainder of * x/y */ #[Pure] function fmod(float $num1, float $num2): float {} /** * Performs a floating-point division under * IEEE 754 semantics. Division by zero is considered well-defined and * will return one of Inf, -Inf or NaN. * @param float $num1 * @param float $num2 * @return float * @since 8.0 */ #[Pure] function fdiv(float $num1, float $num2): float {} /** * Converts a packed internet address to a human readable representation * @link https://php.net/manual/en/function.inet-ntop.php * @param string $ip

    * A 32bit IPv4, or 128bit IPv6 address. *

    * @return string|false a string representation of the address or false on failure. */ #[Pure] function inet_ntop(string $ip): string|false {} /** * Converts a human readable IP address to its packed in_addr representation * @link https://php.net/manual/en/function.inet-pton.php * @param string $ip

    * A human readable IPv4 or IPv6 address. *

    * @return string|false the in_addr representation of the given * address */ #[Pure] function inet_pton(string $ip): string|false {} /** * Converts a string containing an (IPv4) Internet Protocol dotted address into a long integer * @link https://php.net/manual/en/function.ip2long.php * @param string $ip

    * A standard format address. *

    * @return int|false the IPv4 address or false if ip_address * is invalid. */ #[Pure] function ip2long(string $ip): int|false {} /** * Converts an long integer address into a string in (IPv4) internet standard dotted format * @link https://php.net/manual/en/function.long2ip.php * @param int $ip

    * A proper address representation. *

    * @return string|false the Internet IP address as a string. */ #[Pure] #[LanguageLevelTypeAware(['8.4' => 'string'], default: 'string|false')] function long2ip(int $ip) {} /** * Gets the value of an environment variable * @link https://php.net/manual/en/function.getenv.php * @param string|null $name

    * The variable name. *

    * @param bool $local_only [optional]

    * Set to true to only return local environment variables (set by the operating system or putenv). *

    * @return string|array|false the value of the environment variable * varname or an associative array with all environment variables if no variable name * is provided, or false on an error. */ #[Pure(true)] function getenv( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] $varname, #[PhpStormStubsElementAvailable(from: '7.1')] ?string $name = null, #[PhpStormStubsElementAvailable(from: '5.6')] bool $local_only = false ): array|string|false {} /** * Sets the value of an environment variable * @link https://php.net/manual/en/function.putenv.php * @param string $assignment

    * The setting, like "FOO=BAR" *

    * @return bool true on success or false on failure. */ function putenv(string $assignment): bool {} /** * Gets options from the command line argument list * @link https://php.net/manual/en/function.getopt.php * @param string $short_options Each character in this string will be used as option characters and * matched against options passed to the script starting with a single * hyphen (-). * For example, an option string "x" recognizes an * option -x. * Only a-z, A-Z and 0-9 are allowed. * @param array $long_options An array of options. Each element in this array will be used as option * strings and matched against options passed to the script starting with * two hyphens (--). * For example, an longopts element "opt" recognizes an * option --opt. * Prior to PHP5.3.0 this parameter was only available on few systems * @param int &$rest_index [optional] If the optind parameter is present, then the index where argument parsing stopped will be written to this variable. * @return string[]|false[]|false This function will return an array of option / argument pairs or false on * failure. */ function getopt( string $short_options, array $long_options = [], #[PhpStormStubsElementAvailable(from: '7.1')] &$rest_index ): array|false {} /** * Gets system load average * @link https://php.net/manual/en/function.sys-getloadavg.php * @return array|false an array with three samples (last 1, 5 and 15 * minutes). * @since 5.1.3 */ #[Pure(true)] function sys_getloadavg(): array|false {} /** * Return current Unix timestamp with microseconds * @link https://php.net/manual/en/function.microtime.php * @param bool $as_float [optional]

    * When called without the optional argument, this function returns the string * "msec sec" where sec is the current time measured in the number of * seconds since the Unix Epoch (0:00:00 January 1, 1970 GMT), and * msec is the microseconds part. * Both portions of the string are returned in units of seconds. *

    *

    * If the optional get_as_float is set to * true then a float (in seconds) is returned. *

    * @return string|float */ #[Pure(true)] function microtime(#[TypeContract(true: "float", false: "string")] bool $as_float = false): string|float {} /** * Get current time * @link https://php.net/manual/en/function.gettimeofday.php * @param bool $as_float [optional]

    * When set to true, a float instead of an array is returned. *

    * @return int[]|float By default an array is returned. If return_float * is set, then a float is returned. *

    *

    * Array keys: * "sec" - seconds since the Unix Epoch * "usec" - microseconds * "minuteswest" - minutes west of Greenwich * "dsttime" - type of dst correction */ #[Pure(true)] #[ArrayShape(["sec" => "int", "usec" => "int", "minuteswest" => "int", "dsttime" => "int"])] function gettimeofday(#[TypeContract(true: "float", false: "int[]")] bool $as_float = false): array|float {} /** * Gets the current resource usages * @link https://php.net/manual/en/function.getrusage.php * @param int $mode

    * If who is 1, getrusage will be called with * RUSAGE_CHILDREN. *

    * @return array|false an associative array containing the data returned from the system * call. All entries are accessible by using their documented field names. */ #[Pure(true)] function getrusage(int $mode = 0): array|false {} /** * Generate a unique ID * @link https://php.net/manual/en/function.uniqid.php * @param string $prefix [optional]

    * Can be useful, for instance, if you generate identifiers * simultaneously on several hosts that might happen to generate the * identifier at the same microsecond. *

    *

    * With an empty prefix, the returned string will * be 13 characters long. If more_entropy is * true, it will be 23 characters. *

    * @param bool $more_entropy [optional]

    * If set to true, uniqid will add additional * entropy (using the combined linear congruential generator) at the end * of the return value, which should make the results more unique. *

    * @return string the unique identifier, as a string. */ function uniqid(string $prefix = "", bool $more_entropy = false): string {} /** * Convert a quoted-printable string to an 8 bit string * @link https://php.net/manual/en/function.quoted-printable-decode.php * @param string $string

    * The input string. *

    * @return string the 8-bit binary string. */ #[Pure] function quoted_printable_decode(string $string): string {} /** * Convert a 8 bit string to a quoted-printable string * @link https://php.net/manual/en/function.quoted-printable-encode.php * @param string $string

    * The input string. *

    * @return string the encoded string. */ #[Pure] function quoted_printable_encode(string $string): string {} /** * Convert from one Cyrillic character set to another * @link https://php.net/manual/en/function.convert-cyr-string.php * @param string $str

    * The string to be converted. *

    * @param string $from

    * The source Cyrillic character set, as a single character. *

    * @param string $to

    * The target Cyrillic character set, as a single character. *

    * @return string the converted string. * @removed 8.0 * @see mb_convert_string() * @see iconv() * @see UConverter */ #[Pure] #[Deprecated(since: '7.4', reason: 'Us mb_convert_string(), iconv() or UConverter instead.')] function convert_cyr_string(string $str, string $from, string $to): string {} /** * Gets the name of the owner of the current PHP script * @link https://php.net/manual/en/function.get-current-user.php * @return string the username as a string. */ #[Pure(true)] function get_current_user(): string {} /** * Limits the maximum execution time * @link https://php.net/manual/en/function.set-time-limit.php * @param int $seconds

    * The maximum execution time, in seconds. If set to zero, no time limit * is imposed. *

    * @return bool Returns TRUE on success, or FALSE on failure. */ function set_time_limit(int $seconds): bool {} /** * Gets the value of a PHP configuration option * @link https://php.net/manual/en/function.get-cfg-var.php * @param string $option

    * The configuration option name. *

    * @return array|string|false the current value of the PHP configuration variable specified by * option, or false if an error occurs. */ #[Pure] function get_cfg_var(string $option): array|string|false {} /** * Alias: * {@see set_magic_quotes_runtime} * @link https://php.net/manual/en/function.magic-quotes-runtime.php * @param bool $new_setting * @removed 7.0 */ #[Deprecated(since: '5.3')] function magic_quotes_runtime(bool $new_setting) {} /** * Sets the current active configuration setting of magic_quotes_runtime * @link https://php.net/manual/en/function.set-magic-quotes-runtime.php * @param bool $new_setting

    * false for off, true for on. *

    * @return bool true on success or false on failure. * @removed 7.0 */ #[Deprecated(reason: "This function has been DEPRECATED as of PHP 5.4.0. Raises an E_CORE_ERROR", since: "5.3")] function set_magic_quotes_runtime(bool $new_setting): bool {} /** * Gets the current configuration setting of magic quotes gpc * @link https://php.net/manual/en/function.get-magic-quotes-gpc.php * @return int 0 if magic quotes gpc are off, 1 otherwise. * @removed 8.0 */ #[Deprecated(since: '7.4')] function get_magic_quotes_gpc(): int {} /** * Gets the current active configuration setting of magic_quotes_runtime * @link https://php.net/manual/en/function.get-magic-quotes-runtime.php * @return int 0 if magic quotes runtime is off, 1 otherwise. */ #[Deprecated(since: '7.4')] function get_magic_quotes_runtime(): int {} /** * Import GET/POST/Cookie variables into the global scope * @link https://php.net/manual/en/function.import-request-variables.php * @param string $types

    * Using the types parameter, you can specify * which request variables to import. You can use 'G', 'P' and 'C' * characters respectively for GET, POST and Cookie. These characters are * not case sensitive, so you can also use any combination of 'g', 'p' * and 'c'. POST includes the POST uploaded file information. *

    *

    * Note that the order of the letters matters, as when using * "GP", the * POST variables will overwrite GET variables with the same name. Any * other letters than GPC are discarded. *

    * @param string $prefix [optional]

    * Variable name prefix, prepended before all variable's name imported * into the global scope. So if you have a GET value named * "userid", and provide a prefix * "pref_", then you'll get a global variable named * $pref_userid. *

    *

    * Although the prefix parameter is optional, you * will get an E_NOTICE level * error if you specify no prefix, or specify an empty string as a * prefix. This is a possible security hazard. Notice level errors are * not displayed using the default error reporting level. *

    * @return bool true on success or false on failure. * @removed 5.4 */ #[Deprecated(reason: "This function has been DEPRECATED as of PHP 5.3.0", since: "5.3")] function import_request_variables(string $types, $prefix = null): bool {} /** * Send an error message to the defined error handling routines * @link https://php.net/manual/en/function.error-log.php * @param string $message

    * The error message that should be logged. *

    * @param int $message_type

    * Says where the error should go. The possible message types are as * follows: *

    *

    *

    * error_log log types * * * * * * * * * * * * * * * * * * * * *
    0 * message is sent to PHP's system logger, using * the Operating System's system logging mechanism or a file, depending * on what the error_log * configuration directive is set to. This is the default option. *
    1 * message is sent by email to the address in * the destination parameter. This is the only * message type where the fourth parameter, * extra_headers is used. *
    2 * No longer an option. *
    3 * message is appended to the file * destination. A newline is not automatically * added to the end of the message string. *
    4 * message is sent directly to the SAPI logging * handler. *
    *

    * @param string|null $destination [optional]

    * The destination. Its meaning depends on the * message_type parameter as described above. *

    * @param string|null $additional_headers [optional]

    * The extra headers. It's used when the message_type * parameter is set to 1. * This message type uses the same internal function as * mail does. *

    * @return bool true on success or false on failure. */ function error_log(string $message, int $message_type = 0, ?string $destination, ?string $additional_headers): bool {} * This parameter is only the filename of the * extension to load which also depends on your platform. For example, * the sockets extension (if compiled * as a shared module, not the default!) would be called * sockets.so on Unix platforms whereas it is called * php_sockets.dll on the Windows platform. *

    *

    * The directory where the extension is loaded from depends on your * platform: *

    *

    * Windows - If not explicitly set in the php.ini, the extension is * loaded from C:\php4\extensions\ (PHP 4) or * C:\php5\ (PHP 5) by default. *

    *

    * Unix - If not explicitly set in the php.ini, the default extension * directory depends on * whether PHP has been built with --enable-debug * or not

    * @return bool TRUE on success or FALSE on failure. If the functionality of loading modules is not available * or has been disabled (either by setting * enable_dl off or by enabling safe mode * in php.ini) an E_ERROR is emitted * and execution is stopped. If dl fails because the * specified library couldn't be loaded, in addition to FALSE an * E_WARNING message is emitted. * Loads a PHP extension at runtime * @link https://php.net/manual/en/function.dl.php */ function dl(string $extension_filename): bool {} /** * Sets the process title * @link https://php.net/manual/en/function.cli-set-process-title.php * @param string $title

    * The new title. *

    * @return bool TRUE on success or FALSE on failure. * @since 5.5 */ function cli_set_process_title(string $title): bool {} /** * Returns the current process title, as set by cli_set_process_title(). Note that this may not exactly match what is shown in ps or top, depending on your operating system. * * @link https://php.net/manual/en/function.cli-get-process-title.php * @return string|null Return a string with the current process title or NULL on error. * @since 5.5 */ #[Pure(true)] function cli_get_process_title(): ?string {} /** * Verify that the contents of a variable is accepted by the iterable pseudo-type, i.e. that it is an array or an object implementing Traversable * @param mixed $value * @return bool * @since 7.1 * @link https://php.net/manual/en/function.is-iterable.php */ #[Pure] function is_iterable(mixed $value): bool {} /** * Encodes an ISO-8859-1 string to UTF-8 * @link https://php.net/manual/en/function.utf8-encode.php * @param string $string

    * An ISO-8859-1 string. *

    * @return string the UTF-8 translation of data. * @deprecated 8.2 Consider to use {@link mb_convert_encoding}, {@link UConverter::transcode()} or {@link iconv()} */ #[Pure] #[Deprecated(replacement: "mb_convert_encoding(%parameter0%, 'UTF-8', 'ISO-8859-1')", since: "8.2")] function utf8_encode(string $string): string {} /** * Converts a string with ISO-8859-1 characters encoded with UTF-8 * to single-byte ISO-8859-1 * @link https://php.net/manual/en/function.utf8-decode.php * @param string $string

    * An UTF-8 encoded string. *

    * @return string the ISO-8859-1 translation of data. * @deprecated 8.2 Consider to use {@link mb_convert_encoding}, {@link UConverter::transcode()} or {@link iconv()} */ #[Pure] #[Deprecated(replacement: "mb_convert_encoding(%parameter0%, 'ISO-8859-1', 'UTF-8')", since: "8.2")] function utf8_decode(string $string): string {} /** * Clear the most recent error * @link https://php.net/manual/en/function.error-clear-last.php * @return void * @since 7.0 */ function error_clear_last(): void {} /** * Get process codepage * @link https://php.net/manual/en/function.sapi-windows-cp-get * @param string $kind The kind of operating system codepage to get, either 'ansi' or 'oem'. Any other value refers to the current codepage of the process. * @return int

    * If kind is 'ansi', the current ANSI code page of the operating system is returned. * If kind is 'oem', the current OEM code page of the operating system is returned. * Otherwise, the current codepage of the process is returned. *

    * @since 7.1 */ function sapi_windows_cp_get(string $kind = ""): int {} /** * Set process codepage * @link https://php.net/manual/en/function.sapi-windows-cp-set * @param int $codepage A codepage identifier. * @return bool Returns true on success or false on failure. * @since 7.1 */ function sapi_windows_cp_set(int $codepage): bool {} /** * Convert string from one codepage to another * @link https://php.net/manual/en/function.sapi-windows-cp-conv.php * @param int|string $in_codepage The codepage of the subject string. Either the codepage name or identifier. * @param int|string $out_codepage The codepage to convert the subject string to. Either the codepage name or identifier. * @param string $subject The string to convert. * @return string|null The subject string converted to out_codepage, or null on failure. * @since 7.1 */ function sapi_windows_cp_conv(int|string $in_codepage, int|string $out_codepage, string $subject): ?string {} /** * Indicates whether the codepage is utf-8 compatible * @link https://www.php.net/manual/en/function.sapi-windows-cp-is-utf8.php * @return bool * @since 7.1 */ function sapi_windows_cp_is_utf8(): bool {} /** * Get or set VT100 support for the specified stream associated to an output buffer of a Windows console. * * At startup, PHP tries to enable the VT100 feature of the STDOUT/STDERR streams. * By the way, if those streams are redirected to a file, the VT100 features may not be enabled. * * If VT100 support is enabled, it is possible to use control sequences as they are known from the VT100 terminal. * They allow the modification of the terminal's output. On Windows these sequences are called Console Virtual Terminal Sequences. * * Warning This function uses the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag implemented in the Windows 10 API, so the VT100 feature may not be available on older Windows versions. * * @link https://php.net/manual/en/function.sapi-windows-vt100-support.php * @param resource $stream The stream on which the function will operate. * @param bool|null $enable

    * If bool, the VT100 feature will be enabled (if true) or disabled (if false). *

    *

    * If enable is null, the function returns true if the stream stream has VT100 control codes enabled, false otherwise. *

    *

    * If enable is a bool, the function will try to enable or disable the VT100 features of the stream stream. * If the feature has been successfully enabled (or disabled), the function will return true, or false otherwise. *

    * @return bool

    * If enable is null: returns true if the VT100 feature is enabled, false otherwise. *

    *

    * If enable is a bool: Returns true on success or false on failure. *

    * @since 7.2 */ function sapi_windows_vt100_support($stream, ?bool $enable = null): bool {} /** * Set or remove a CTRL event handler, which allows Windows CLI processes to intercept or ignore CTRL+C and CTRL+BREAK events. * Note that in multithreaded environments, this is only possible when called from the main thread. * * @link https://www.php.net/manual/en/function.sapi-windows-set-ctrl-handler.php * @param callable|null $handler

    * A callback function to set or remove. If set, this function will be called whenever a CTRL+C or CTRL+BREAK event occurs. *

    *

    * The function is supposed to have the following signature: * * handler(int $event): void * * event The CTRL event which has been received; either PHP_WINDOWS_EVENT_CTRL_C or PHP_WINDOWS_EVENT_CTRL_BREAK. *

    *

    * Setting a null handler causes the process to ignore CTRL+C events, but not CTRL+BREAK events. *

    * @param bool $add If true, the handler is set. If false, the handler is removed. * @return bool TRUE on success or FALSE on failure. * @since 7.4 */ function sapi_windows_set_ctrl_handler(?callable $handler, bool $add = true): bool {} /** * Send a CTRL event to another process. * * @link https://www.php.net/manual/en/function.sapi-windows-generate-ctrl-event.php * @param int $event The CTRL even to send; either PHP_WINDOWS_EVENT_CTRL_C or PHP_WINDOWS_EVENT_CTRL_BREAK. * @param int $pid [optional] The ID of the process to which to send the event to. If 0 is given, the event is sent to all processes of the process group. * @return bool TRUE on success or FALSE on failure. * @since 7.4 */ function sapi_windows_generate_ctrl_event(int $event, int $pid = 0): bool {} /** * The full path and filename of the file. If used inside an include, * the name of the included file is returned. * Since PHP 4.0.2, __FILE__ always contains an * absolute path with symlinks resolved whereas in older versions it contained relative path * under some circumstances. * @link https://php.net/manual/en/language.constants.predefined.php */ define('__FILE__', '', true); /** * The current line number of the file. * @link https://php.net/manual/en/language.constants.predefined.php */ define('__LINE__', 0, true); /** * The class name. (Added in PHP 4.3.0) As of PHP 5 this constant * returns the class name as it was declared (case-sensitive). In PHP * 4 its value is always lowercased. The class name includes the namespace * it was declared in (e.g. Foo\Bar). * Note that as of PHP 5.4 __CLASS__ works also in traits. When used * in a trait method, __CLASS__ is the name of the class the trait * is used in. * @link https://php.net/manual/en/language.constants.predefined.php */ define('__CLASS__', '', true); /** * The function name. (Added in PHP 4.3.0) As of PHP 5 this constant * returns the function name as it was declared (case-sensitive). In * PHP 4 its value is always lowercased. * @link https://php.net/manual/en/language.constants.predefined.php */ define('__FUNCTION__', '', true); /** * The class method name. (Added in PHP 5.0.0) The method name is * returned as it was declared (case-sensitive). * @link https://php.net/manual/en/language.constants.predefined.php */ define('__METHOD__', '', true); /** * The trait name. (Added in PHP 5.4.0) As of PHP 5.4 this constant * returns the trait as it was declared (case-sensitive). The trait name includes the namespace * it was declared in (e.g. Foo\Bar). * @since 5.4 * @link https://php.net/manual/en/language.constants.predefined.php */ define('__TRAIT__', '', true); /** * The directory of the file. If used inside an include, * the directory of the included file is returned. This is equivalent * to `dirname(__FILE__)`. This directory name * does not have a trailing slash unless it is the root directory. * @link https://php.net/manual/en/language.constants.predefined.php */ define('__DIR__', '', true); /** * The name of the current namespace (case-sensitive). This constant * is defined in compile-time (Added in PHP 5.3.0). * @link https://php.net/manual/en/language.constants.predefined.php */ define('__NAMESPACE__', '', true); e
    constant */ define('M_E', 2.718281828459); /** * {@link log}2e constant */ define('M_LOG2E', 1.442695040889); /** * {@link log}10e constant */ define('M_LOG10E', 0.43429448190325); /** * {@link log}e2 constant */ define('M_LN2', 0.69314718055995); /** * {@link log}e10 constant */ define('M_LN10', 2.302585092994); /** * π constant */ define('M_PI', 3.1415926535898); /** * π/2 constant */ define('M_PI_2', 1.5707963267949); /** * π/4 constant */ define('M_PI_4', 0.78539816339745); /** * 1/π constant */ define('M_1_PI', 0.31830988618379); /** * 2/π constant */ define('M_2_PI', 0.63661977236758); /** * {@link sqrt}(π) constant */ define('M_SQRTPI', 1.7724538509055); /** * 2/{@link sqrt}(π) constant */ define('M_2_SQRTPI', 1.1283791670955); /** * {@link log}eπ constant */ define('M_LNPI', 1.1447298858494); /** * Euler constant */ define('M_EULER', 0.57721566490153); /** * {@link sqrt}(2) constant */ define('M_SQRT2', 1.4142135623731); /** * 1/{@link sqrt}(2) constant */ define('M_SQRT1_2', 0.70710678118655); /** * {@link sqrt}(3) constant */ define('M_SQRT3', 1.7320508075689); /** * The infinite */ define('INF', (float)INF); /** * Not A Number */ define('NAN', (float)NAN); /** * Round halves up * @link https://php.net/manual/en/math.constants.php */ define('PHP_ROUND_HALF_UP', 1); /** * Round halves down * @link https://php.net/manual/en/math.constants.php */ define('PHP_ROUND_HALF_DOWN', 2); /** * Round halves to even numbers * @link https://php.net/manual/en/math.constants.php */ define('PHP_ROUND_HALF_EVEN', 3); /** * Round halves to odd numbers * @link https://php.net/manual/en/math.constants.php */ define('PHP_ROUND_HALF_ODD', 4); define('INFO_GENERAL', 1); /** * PHP Credits. See also phpcredits. * @link https://php.net/manual/en/info.constants.php */ define('INFO_CREDITS', 2); /** * Current Local and Main values for PHP directives. See * also ini_get. * @link https://php.net/manual/en/info.constants.php */ define('INFO_CONFIGURATION', 4); /** * Loaded modules and their respective settings. * @link https://php.net/manual/en/info.constants.php */ define('INFO_MODULES', 8); /** * Environment Variable information that's also available in * $_ENV. * @link https://php.net/manual/en/info.constants.php */ define('INFO_ENVIRONMENT', 16); /** * Shows all * predefined variables from EGPCS (Environment, GET, * POST, Cookie, Server). * @link https://php.net/manual/en/info.constants.php */ define('INFO_VARIABLES', 32); /** * PHP License information. See also the license faq. * @link https://php.net/manual/en/info.constants.php */ define('INFO_LICENSE', 64); define('INFO_ALL', 4294967295); /** * A list of the core developers * @link https://php.net/manual/en/info.constants.php */ define('CREDITS_GROUP', 1); /** * General credits: Language design and concept, PHP * authors and SAPI module. * @link https://php.net/manual/en/info.constants.php */ define('CREDITS_GENERAL', 2); /** * A list of the server API modules for PHP, and their authors. * @link https://php.net/manual/en/info.constants.php */ define('CREDITS_SAPI', 4); /** * A list of the extension modules for PHP, and their authors. * @link https://php.net/manual/en/info.constants.php */ define('CREDITS_MODULES', 8); /** * The credits for the documentation team. * @link https://php.net/manual/en/info.constants.php */ define('CREDITS_DOCS', 16); /** * Usually used in combination with the other flags. Indicates * that a complete stand-alone HTML page needs to be * printed including the information indicated by the other * flags. * @link https://php.net/manual/en/info.constants.php */ define('CREDITS_FULLPAGE', 32); /** * The credits for the quality assurance team. * @link https://php.net/manual/en/info.constants.php */ define('CREDITS_QA', 64); /** * The configuration line, "php.ini" location, build date, Web * Server, System and more. * @link https://php.net/manual/en/info.constants.php */ define('CREDITS_ALL', 4294967295); define('HTML_SPECIALCHARS', 0); define('HTML_ENTITIES', 1); /** * Will convert double-quotes and leave single-quotes alone. * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_COMPAT', 2); /** * Will convert both double and single quotes. * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_QUOTES', 3); /** * Will leave both double and single quotes unconverted. * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_NOQUOTES', 0); /** * Silently discard invalid code unit sequences instead of returning an empty string. * Using this flag is discouraged as it may have security implications. * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_IGNORE', 4); define('STR_PAD_LEFT', 0); define('STR_PAD_RIGHT', 1); define('STR_PAD_BOTH', 2); define('PATHINFO_DIRNAME', 1); define('PATHINFO_BASENAME', 2); define('PATHINFO_EXTENSION', 4); /** * @link https://php.net/manual/en/filesystem.constants.php */ define('PATHINFO_FILENAME', 8); define('PATHINFO_ALL', 15); define('CHAR_MAX', 127); define('LC_CTYPE', 0); define('LC_NUMERIC', 1); define('LC_TIME', 2); define('LC_COLLATE', 3); define('LC_MONETARY', 4); define('LC_ALL', 6); define('LC_MESSAGES', 5); define('SEEK_SET', 0); define('SEEK_CUR', 1); define('SEEK_END', 2); /** * Acquire a shared lock (reader). * @link https://www.php.net/manual/en/function.flock.php */ define('LOCK_SH', 1); /** * Acquire an exclusive lock (writer). * @link https://www.php.net/manual/en/function.flock.php */ define('LOCK_EX', 2); /** * Release lock (shared or exclusive). * @link https://www.php.net/manual/en/function.flock.php */ define('LOCK_UN', 3); /** * Non-blocking operation while locking. * @link https://www.php.net/manual/en/function.flock.php */ define('LOCK_NB', 4); /** * A connection with an external resource has been established. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_CONNECT', 2); /** * Additional authorization is required to access the specified resource. * Typical issued with severity level of * STREAM_NOTIFY_SEVERITY_ERR. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_AUTH_REQUIRED', 3); /** * Authorization has been completed (with or without success). * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_AUTH_RESULT', 10); /** * The mime-type of resource has been identified, * refer to message for a description of the * discovered type. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_MIME_TYPE_IS', 4); /** * The size of the resource has been discovered. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_FILE_SIZE_IS', 5); /** * The external resource has redirected the stream to an alternate * location. Refer to message. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_REDIRECTED', 6); /** * Indicates current progress of the stream transfer in * bytes_transferred and possibly * bytes_max as well. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_PROGRESS', 7); /** * A generic error occurred on the stream, consult * message and message_code * for details. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_FAILURE', 9); /** * There is no more data available on the stream. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_COMPLETED', 8); /** * A remote address required for this stream has been resolved, or the resolution * failed. See severity for an indication of which happened. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_RESOLVE', 1); /** * Normal, non-error related, notification. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_SEVERITY_INFO', 0); /** * Non critical error condition. Processing may continue. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_SEVERITY_WARN', 1); /** * A critical error occurred. Processing cannot continue. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_NOTIFY_SEVERITY_ERR', 2); /** * Used with stream_filter_append and * stream_filter_prepend to indicate * that the specified filter should only be applied when * reading * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_FILTER_READ', 1); /** * Used with stream_filter_append and * stream_filter_prepend to indicate * that the specified filter should only be applied when * writing * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_FILTER_WRITE', 2); /** * This constant is equivalent to * STREAM_FILTER_READ | STREAM_FILTER_WRITE * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_FILTER_ALL', 3); /** * Client socket opened with stream_socket_client * should remain persistent between page loads. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_CLIENT_PERSISTENT', 1); /** * Open client socket asynchronously. This option must be used * together with the STREAM_CLIENT_CONNECT flag. * Used with stream_socket_client. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_CLIENT_ASYNC_CONNECT', 2); /** * Open client socket connection. Client sockets should always * include this flag. Used with stream_socket_client. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_CLIENT_CONNECT', 4); /** * Used with stream_socket_shutdown to disable * further receptions. * @since 5.2.1 * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SHUT_RD', 0); /** * Used with stream_socket_shutdown to disable * further transmissions. * @since 5.2.1 * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SHUT_WR', 1); /** * Used with stream_socket_shutdown to disable * further receptions and transmissions. * @since 5.2.1 * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SHUT_RDWR', 2); /** * Internet Protocol Version 4 (IPv4). * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_PF_INET', 2); /** * Internet Protocol Version 6 (IPv6). * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_PF_INET6', 10); /** * Unix system internal protocols. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_PF_UNIX', 1); /** * Provides a IP socket. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_IPPROTO_IP', 0); /** * Provides a TCP socket. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_IPPROTO_TCP', 6); /** * Provides a UDP socket. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_IPPROTO_UDP', 17); /** * Provides a ICMP socket. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_IPPROTO_ICMP', 1); /** * Provides a RAW socket. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_IPPROTO_RAW', 255); /** * Provides sequenced, two-way byte streams with a transmission mechanism * for out-of-band data (TCP, for example). * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SOCK_STREAM', 1); /** * Provides datagrams, which are connectionless messages (UDP, for * example). * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SOCK_DGRAM', 2); /** * Provides a raw socket, which provides access to internal network * protocols and interfaces. Usually this type of socket is just available * to the root user. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SOCK_RAW', 3); /** * Provides a sequenced packet stream socket. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SOCK_SEQPACKET', 5); /** * Provides a RDM (Reliably-delivered messages) socket. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SOCK_RDM', 4); define('STREAM_PEEK', 2); define('STREAM_OOB', 1); /** * Tells a stream created with stream_socket_server * to bind to the specified target. Server sockets should always include this flag. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SERVER_BIND', 4); /** * Tells a stream created with stream_socket_server * and bound using the STREAM_SERVER_BIND flag to start * listening on the socket. Connection-orientated transports (such as TCP) * must use this flag, otherwise the server socket will not be enabled. * Using this flag for connect-less transports (such as UDP) is an error. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_SERVER_LISTEN', 8); /** * Search for filename in include_path * @link https://php.net/manual/en/filesystem.constants.php */ define('FILE_USE_INCLUDE_PATH', 1); /** * Strip EOL characters * @link https://php.net/manual/en/filesystem.constants.php */ define('FILE_IGNORE_NEW_LINES', 2); /** * Skip empty lines * @link https://php.net/manual/en/filesystem.constants.php */ define('FILE_SKIP_EMPTY_LINES', 4); /** * Append content to existing file. * @link https://php.net/manual/en/filesystem.constants.php */ define('FILE_APPEND', 8); define('FILE_NO_DEFAULT_CONTEXT', 16); /** *

    * This constant has no effect prior to PHP 6. It is only available for * forward compatibility. *

    * @since 5.2.7 * @link https://php.net/manual/en/filesystem.constants.php * @deprecated 8.1 */ define('FILE_TEXT', 0); /** *

    * This constant has no effect prior to PHP 6. It is only available for * forward compatibility. *

    * @since 5.2.7 * @link https://php.net/manual/en/filesystem.constants.php * @deprecated 8.1 */ define('FILE_BINARY', 0); /** * Disable backslash escaping. * @link https://php.net/manual/en/filesystem.constants.php */ define('FNM_NOESCAPE', 2); /** * Slash in string only matches slash in the given pattern. * @link https://php.net/manual/en/filesystem.constants.php */ define('FNM_PATHNAME', 1); /** * Leading period in string must be exactly matched by period in the given pattern. * @link https://php.net/manual/en/filesystem.constants.php */ define('FNM_PERIOD', 4); /** * Caseless match. Part of the GNU extension. * @link https://php.net/manual/en/filesystem.constants.php */ define('FNM_CASEFOLD', 16); /** * Return Code indicating that the * userspace filter returned buckets in $out. * @link https://php.net/manual/en/stream.constants.php */ define('PSFS_PASS_ON', 2); /** * Return Code indicating that the * userspace filter did not return buckets in $out * (i.e. No data available). * @link https://php.net/manual/en/stream.constants.php */ define('PSFS_FEED_ME', 1); /** * Return Code indicating that the * userspace filter encountered an unrecoverable error * (i.e. Invalid data received). * @link https://php.net/manual/en/stream.constants.php */ define('PSFS_ERR_FATAL', 0); /** * Regular read/write. * @link https://php.net/manual/en/stream.constants.php */ define('PSFS_FLAG_NORMAL', 0); /** * An incremental flush. * @link https://php.net/manual/en/stream.constants.php */ define('PSFS_FLAG_FLUSH_INC', 1); /** * Final flush prior to closing. * @link https://php.net/manual/en/stream.constants.php */ define('PSFS_FLAG_FLUSH_CLOSE', 2); define('ABDAY_1', 131072); define('ABDAY_2', 131073); define('ABDAY_3', 131074); define('ABDAY_4', 131075); define('ABDAY_5', 131076); define('ABDAY_6', 131077); define('ABDAY_7', 131078); define('DAY_1', 131079); define('DAY_2', 131080); define('DAY_3', 131081); define('DAY_4', 131082); define('DAY_5', 131083); define('DAY_6', 131084); define('DAY_7', 131085); define('ABMON_1', 131086); define('ABMON_2', 131087); define('ABMON_3', 131088); define('ABMON_4', 131089); define('ABMON_5', 131090); define('ABMON_6', 131091); define('ABMON_7', 131092); define('ABMON_8', 131093); define('ABMON_9', 131094); define('ABMON_10', 131095); define('ABMON_11', 131096); define('ABMON_12', 131097); define('MON_1', 131098); define('MON_2', 131099); define('MON_3', 131100); define('MON_4', 131101); define('MON_5', 131102); define('MON_6', 131103); define('MON_7', 131104); define('MON_8', 131105); define('MON_9', 131106); define('MON_10', 131107); define('MON_11', 131108); define('MON_12', 131109); define('AM_STR', 131110); define('PM_STR', 131111); define('D_T_FMT', 131112); define('D_FMT', 131113); define('T_FMT', 131114); define('T_FMT_AMPM', 131115); define('ERA', 131116); define('ERA_D_T_FMT', 131120); define('ERA_D_FMT', 131118); define('ERA_T_FMT', 131121); define('ALT_DIGITS', 131119); define('CRNCYSTR', 262159); define('RADIXCHAR', 65536); define('THOUSEP', 65537); define('YESEXPR', 327680); define('NOEXPR', 327681); define('YESSTR', 327682); define('NOSTR', 327683); define('CODESET', 14); define('CRYPT_SALT_LENGTH', 123); define('CRYPT_STD_DES', 1); define('CRYPT_EXT_DES', 1); define('CRYPT_MD5', 1); define('CRYPT_BLOWFISH', 1); define('CRYPT_SHA256', 1); define('CRYPT_SHA512', 1); define('DIRECTORY_SEPARATOR', "/"); define('PATH_SEPARATOR', ":"); define('GLOB_BRACE', 1024); define('GLOB_MARK', 2); define('GLOB_NOSORT', 4); define('GLOB_NOCHECK', 16); define('GLOB_NOESCAPE', 64); define('GLOB_ERR', 1); define('GLOB_ONLYDIR', 1073741824); define('GLOB_AVAILABLE_FLAGS', 1073741911); define('EXTR_OVERWRITE', 0); define('EXTR_SKIP', 1); define('EXTR_PREFIX_SAME', 2); define('EXTR_PREFIX_ALL', 3); define('EXTR_PREFIX_INVALID', 4); define('EXTR_PREFIX_IF_EXISTS', 5); define('EXTR_IF_EXISTS', 6); define('EXTR_REFS', 256); /** * SORT_ASC is used with * array_multisort to sort in ascending order. * @link https://php.net/manual/en/array.constants.php */ define('SORT_ASC', 4); /** * SORT_DESC is used with * array_multisort to sort in descending order. * @link https://php.net/manual/en/array.constants.php */ define('SORT_DESC', 3); /** * SORT_REGULAR is used to compare items normally. * @link https://php.net/manual/en/array.constants.php */ define('SORT_REGULAR', 0); /** * SORT_NUMERIC is used to compare items numerically. * @link https://php.net/manual/en/array.constants.php */ define('SORT_NUMERIC', 1); /** * SORT_STRING is used to compare items as strings. * @link https://php.net/manual/en/array.constants.php */ define('SORT_STRING', 2); /** * SORT_LOCALE_STRING is used to compare items as * strings, based on the current locale. * @since 5.0.2 * @link https://php.net/manual/en/array.constants.php */ define('SORT_LOCALE_STRING', 5); /** * CASE_LOWER is used with * array_change_key_case and is used to convert array * keys to lower case. This is also the default case for * array_change_key_case. * @link https://php.net/manual/en/array.constants.php */ define('CASE_LOWER', 0); /** * CASE_UPPER is used with * array_change_key_case and is used to convert array * keys to upper case. * @link https://php.net/manual/en/array.constants.php */ define('CASE_UPPER', 1); define('COUNT_NORMAL', 0); define('COUNT_RECURSIVE', 1); define('ASSERT_ACTIVE', 1); define('ASSERT_CALLBACK', 2); define('ASSERT_BAIL', 3); define('ASSERT_WARNING', 4); /** * @removed 8.0 */ define('ASSERT_QUIET_EVAL', 5); define('ASSERT_EXCEPTION', 5); /** * Flag indicating if the stream used the include path. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_USE_PATH', 1); define('STREAM_IGNORE_URL', 2); define('STREAM_ENFORCE_SAFE_MODE', 4); /** * Flag indicating if the wrapper * is responsible for raising errors using trigger_error * during opening of the stream. If this flag is not set, you * should not raise any errors. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_REPORT_ERRORS', 8); /** * This flag is useful when your extension really must be able to randomly * seek around in a stream. Some streams may not be seekable in their * native form, so this flag asks the streams API to check to see if the * stream does support seeking. If it does not, it will copy the stream * into temporary storage (which may be a temporary file or a memory * stream) which does support seeking. * Please note that this flag is not useful when you want to seek the * stream and write to it, because the stream you are accessing might * not be bound to the actual resource you requested. * If the requested resource is network based, this flag will cause the * opener to block until the whole contents have been downloaded. * @link https://www.php.net/manual/en/stream.constants.php */ define('STREAM_MUST_SEEK', 16); define('STREAM_URL_STAT_LINK', 1); define('STREAM_URL_STAT_QUIET', 2); define('STREAM_MKDIR_RECURSIVE', 1); define('STREAM_IS_URL', 1); define('STREAM_OPTION_BLOCKING', 1); define('STREAM_OPTION_READ_TIMEOUT', 4); define('STREAM_OPTION_READ_BUFFER', 2); define('STREAM_OPTION_WRITE_BUFFER', 3); define('STREAM_BUFFER_NONE', 0); define('STREAM_BUFFER_LINE', 1); define('STREAM_BUFFER_FULL', 2); /** * Stream casting, when stream_cast is called * otherwise (see above). * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_CAST_AS_STREAM', 0); /** * Stream casting, for when stream_select is * calling stream_cast. * @link https://php.net/manual/en/stream.constants.php */ define('STREAM_CAST_FOR_SELECT', 3); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_GIF', 1); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_JPEG', 2); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_PNG', 3); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_SWF', 4); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_PSD', 5); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_BMP', 6); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_TIFF_II', 7); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_TIFF_MM', 8); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_JPC', 9); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_JP2', 10); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_JPX', 11); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_JB2', 12); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_SWC', 13); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_IFF', 14); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_WBMP', 15); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_JPEG2000', 9); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_XBM', 16); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php */ define('IMAGETYPE_ICO', 17); /** * Image type constant used by the {@link image_type_to_mime_type()} and {@link image_type_to_extension()} functions. * @link https://php.net/manual/en/image.constants.php * @since 7.1 */ define('IMAGETYPE_WEBP', 18); define('IMAGETYPE_UNKNOWN', 0); define('IMAGETYPE_COUNT', 20); /** * @since 8.1 */ define('IMAGETYPE_AVIF', 19); /** * IPv4 Address Resource * @link https://php.net/manual/en/network.constants.php */ define('DNS_A', 1); define('DNS_CAA', 8192); /** * Authoritative Name Server Resource * @link https://php.net/manual/en/network.constants.php */ define('DNS_NS', 2); /** * Alias (Canonical Name) Resource * @link https://php.net/manual/en/network.constants.php */ define('DNS_CNAME', 16); /** * Start of Authority Resource * @link https://php.net/manual/en/network.constants.php */ define('DNS_SOA', 32); /** * Pointer Resource * @link https://php.net/manual/en/network.constants.php */ define('DNS_PTR', 2048); /** * Host Info Resource (See IANA's * Operating System Names * for the meaning of these values) * @link https://php.net/manual/en/network.constants.php */ define('DNS_HINFO', 4096); /** * Mail Exchanger Resource * @link https://php.net/manual/en/network.constants.php */ define('DNS_MX', 16384); /** * Text Resource * @link https://php.net/manual/en/network.constants.php */ define('DNS_TXT', 32768); define('DNS_SRV', 33554432); define('DNS_NAPTR', 67108864); /** * IPv6 Address Resource * @link https://php.net/manual/en/network.constants.php */ define('DNS_AAAA', 134217728); define('DNS_A6', 16777216); /** * Any Resource Record. On most systems * this returns all resource records, however * it should not be counted upon for critical * uses. Try DNS_ALL instead. * @link https://php.net/manual/en/network.constants.php */ define('DNS_ANY', 268435456); /** * Iteratively query the name server for * each available record type. * @link https://php.net/manual/en/network.constants.php */ define('DNS_ALL', 251721779); // End of standard v.5.3.1-0.dotdeb.1 //WI-11084 Constant not defined PHP_QUERY_RFC3986 /** * Encoding is performed per RFC 1738 and the application/x-www-form-urlencoded media type, * which implies that spaces are encoded as plus (+) signs. * @link https://php.net/manual/en/function.http-build-query.php */ define('PHP_QUERY_RFC1738', 1); /** * Encoding is performed according to RFC 3986, and spaces will be percent encoded (%20). * @link https://php.net/manual/en/function.http-build-query.php */ define('PHP_QUERY_RFC3986', 2); //WI-11254 Stubs for missing constants from PHP 5.4 /** * (PHP4, PHP5) *

    Constant containing either the session name and session ID in the form of "name=ID" or * empty string if session ID was set in an appropriate session cookie. * This is the same id as the one returned by session_id().

    * @see session_id() * @link https://php.net/manual/en/session.constants.php */ define('SID', "name=ID"); /** * Return value of session_status() if sessions are disabled. * @since 5.4 * @link https://php.net/manual/en/function.session-status.php */ define('PHP_SESSION_DISABLED', 0); /** * Return value of session_status() if sessions are enabled, but no session exists. * @since 5.4 * @link https://php.net/manual/en/function.session-status.php */ define('PHP_SESSION_NONE', 1); /** * Return value of session_status() if sessions are enabled, and a session exists. * @since 5.4 * @link https://php.net/manual/en/function.session-status.php */ define('PHP_SESSION_ACTIVE', 2); /** * Replace invalid code unit sequences with a Unicode Replacement Character * U+FFFD (UTF-8) or &#FFFD; (otherwise) instead of returning an empty string. * @since 5.4 * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_SUBSTITUTE', 8); /** * Replace invalid code points for the given document type with * a Unicode Replacement Character U+FFFD (UTF-8) or &#FFFD; * (otherwise) instead of leaving them as is. This may be useful, * for instance, to ensure the well-formedness of XML documents * with embedded external content. * @since 5.4 * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_DISALLOWED', 128); /** * Handle code as HTML 4.01. * @since 5.4 * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_HTML401', 0); /** * Handle code as XML 1. * @since 5.4 * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_XML1', 16); /** * Handle code as XHTML. * @since 5.4 * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_XHTML', 32); /** * Handle code as HTML 5. * @since 5.4 * @link https://php.net/manual/en/function.htmlspecialchars.php */ define('ENT_HTML5', 48); /** @link https://php.net/manual/en/function.scandir.php */ define('SCANDIR_SORT_ASCENDING', 0); /** @link https://php.net/manual/en/function.scandir.php */ define('SCANDIR_SORT_DESCENDING', 1); /** @link https://php.net/manual/en/function.scandir.php */ define('SCANDIR_SORT_NONE', 2); /** * SORT_NATURAL is used to compare items as strings using "natural ordering" like natsort(). * @since 5.4 * @link https://php.net/manual/en/array.constants.php */ define('SORT_NATURAL', 6); /** * SORT_FLAG_CASE can be combined (bitwise OR) with SORT_STRING or SORT_NATURAL to sort strings case-insensitively. * @since 5.4 * @link https://php.net/manual/en/array.constants.php */ define('SORT_FLAG_CASE', 8); /** @link https://php.net/manual/en/streamwrapper.stream-metadata.php */ define('STREAM_META_TOUCH', 1); /** @link https://php.net/manual/en/streamwrapper.stream-metadata.php */ define('STREAM_META_OWNER', 3); /** @link https://php.net/manual/en/streamwrapper.stream-metadata.php */ define('STREAM_META_OWNER_NAME', 2); /** @link https://php.net/manual/en/streamwrapper.stream-metadata.php */ define('STREAM_META_GROUP', 5); /** @link https://php.net/manual/en/streamwrapper.stream-metadata.php */ define('STREAM_META_GROUP_NAME', 4); /** @link https://php.net/manual/en/streamwrapper.stream-metadata.php */ define('STREAM_META_ACCESS', 6); define('STREAM_CRYPTO_METHOD_SSLv2_CLIENT', 3); define('STREAM_CRYPTO_METHOD_SSLv3_CLIENT', 5); define('STREAM_CRYPTO_METHOD_SSLv23_CLIENT', 57); define('STREAM_CRYPTO_METHOD_TLS_CLIENT', 121); define('STREAM_CRYPTO_METHOD_SSLv2_SERVER', 2); define('STREAM_CRYPTO_METHOD_SSLv3_SERVER', 4); define('STREAM_CRYPTO_METHOD_SSLv23_SERVER', 120); define('STREAM_CRYPTO_METHOD_TLS_SERVER', 120); define("STREAM_CRYPTO_METHOD_ANY_CLIENT", 127); define("STREAM_CRYPTO_METHOD_ANY_SERVER", 126); define("STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT", 9); define("STREAM_CRYPTO_METHOD_TLSv1_0_SERVER", 8); define("STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT", 17); define("STREAM_CRYPTO_METHOD_TLSv1_1_SERVER", 16); define("STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT", 33); define("STREAM_CRYPTO_METHOD_TLSv1_2_SERVER", 32); /** * @since 7.4 */ define("STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT", 65); /** * @since 7.4 */ define("STREAM_CRYPTO_METHOD_TLSv1_3_SERVER", 64); define("STREAM_CRYPTO_PROTO_SSLv3", 4); define("STREAM_CRYPTO_PROTO_TLSv1_0", 8); define("STREAM_CRYPTO_PROTO_TLSv1_1", 16); define("STREAM_CRYPTO_PROTO_TLSv1_2", 32); /** * @since 7.4 */ define("STREAM_CRYPTO_PROTO_TLSv1_3", 64); /** * @since 7.1 */ define("MT_RAND_MT19937", 0); /** * @since 7.1 * @deprecated 8.3 */ define("MT_RAND_PHP", 1); /** * system is unusable * @link https://php.net/manual/en/network.constants.php */ define('LOG_EMERG', 0); /** * action must be taken immediately * @link https://php.net/manual/en/network.constants.php */ define('LOG_ALERT', 1); /** * critical conditions * @link https://php.net/manual/en/network.constants.php */ define('LOG_CRIT', 2); /** * error conditions * @link https://php.net/manual/en/network.constants.php */ define('LOG_ERR', 3); /** * warning conditions * @link https://php.net/manual/en/network.constants.php */ define('LOG_WARNING', 4); /** * normal, but significant, condition * @link https://php.net/manual/en/network.constants.php */ define('LOG_NOTICE', 5); /** * informational message * @link https://php.net/manual/en/network.constants.php */ define('LOG_INFO', 6); /** * debug-level message * @link https://php.net/manual/en/network.constants.php */ define('LOG_DEBUG', 7); /** * kernel messages * @link https://php.net/manual/en/network.constants.php */ define('LOG_KERN', 0); /** * generic user-level messages * @link https://php.net/manual/en/network.constants.php */ define('LOG_USER', 8); /** * mail subsystem * @link https://php.net/manual/en/network.constants.php */ define('LOG_MAIL', 16); /** * other system daemons * @link https://php.net/manual/en/network.constants.php */ define('LOG_DAEMON', 24); /** * security/authorization messages (use LOG_AUTHPRIV instead * in systems where that constant is defined) * @link https://php.net/manual/en/network.constants.php */ define('LOG_AUTH', 32); /** * messages generated internally by syslogd * @link https://php.net/manual/en/network.constants.php */ define('LOG_SYSLOG', 40); /** * line printer subsystem * @link https://php.net/manual/en/network.constants.php */ define('LOG_LPR', 48); /** * USENET news subsystem * @link https://php.net/manual/en/network.constants.php */ define('LOG_NEWS', 56); /** * UUCP subsystem * @link https://php.net/manual/en/network.constants.php */ define('LOG_UUCP', 64); /** * clock daemon (cron and at) * @link https://php.net/manual/en/network.constants.php */ define('LOG_CRON', 72); /** * security/authorization messages (private) * @link https://php.net/manual/en/network.constants.php */ define('LOG_AUTHPRIV', 80); define('LOG_LOCAL0', 128); define('LOG_LOCAL1', 136); define('LOG_LOCAL2', 144); define('LOG_LOCAL3', 152); define('LOG_LOCAL4', 160); define('LOG_LOCAL5', 168); define('LOG_LOCAL6', 176); define('LOG_LOCAL7', 184); /** * include PID with each message * @link https://php.net/manual/en/network.constants.php */ define('LOG_PID', 1); /** * if there is an error while sending data to the system logger, * write directly to the system console * @link https://php.net/manual/en/network.constants.php */ define('LOG_CONS', 2); /** * (default) delay opening the connection until the first * message is logged * @link https://php.net/manual/en/network.constants.php */ define('LOG_ODELAY', 4); /** * open the connection to the logger immediately * @link https://php.net/manual/en/network.constants.php */ define('LOG_NDELAY', 8); define('LOG_NOWAIT', 16); /** * print log message also to standard error * @link https://php.net/manual/en/network.constants.php */ define('LOG_PERROR', 32); /** * @since 8.2 */ define('DECIMAL_POINT', 65536); /** * @since 8.2 */ define('THOUSANDS_SEP', 65537); /** * @since 8.2 */ define('GROUPING', 65538); /** * @since 8.2 */ define('ERA_YEAR', 131117); /** * @since 8.2 */ define('INT_CURR_SYMBOL', 262144); /** * @since 8.2 */ define('CURRENCY_SYMBOL', 262145); /** * @since 8.2 */ define('MON_DECIMAL_POINT', 262146); /** * @since 8.2 */ define('MON_THOUSANDS_SEP', 262147); /** * @since 8.2 */ define('MON_GROUPING', 262148); /** * @since 8.2 */ define('POSITIVE_SIGN', 262149); /** * @since 8.2 */ define('NEGATIVE_SIGN', 262150); /** * @since 8.2 */ define('INT_FRAC_DIGITS', 262151); /** * @since 8.2 */ define('FRAC_DIGITS', 262152); /** * @since 8.2 */ define('P_CS_PRECEDES', 262153); /** * @since 8.2 */ define('P_SEP_BY_SPACE', 262154); /** * @since 8.2 */ define('N_CS_PRECEDES', 262155); /** * @since 8.2 */ define('N_SEP_BY_SPACE', 262156); /** * @since 8.2 */ define('P_SIGN_POSN', 262157); /** * @since 8.2 */ define('N_SIGN_POSN', 262158); * Syntax "index => values", separated by commas, define index and values. * index may be of type string or integer. When index is omitted, an integer index is automatically generated, * starting at 0. If index is an integer, next generated index will be the biggest integer index + 1. * Note that when two identical index are defined, the last overwrite the first. *

    *

    * Having a trailing comma after the last defined array entry, while unusual, is a valid syntax. *

    * @return array an array of the parameters. The parameters can be given an index with the => operator. */ function PS_UNRESERVE_PREFIX_array(...$_) {} /** * Assigns a list of variables in one operation. * @link https://php.net/manual/en/function.list.php * @param mixed $var1

    A variable.

    * @param mixed ...$_ [optional]

    Another variable ...

    * @return array the assigned array. */ function PS_UNRESERVE_PREFIX_list($var1, ...$_) {} /** *

    Terminates execution of the script. Shutdown functions and object destructors will always be executed even if exit is called.

    *

    die is a language construct and it can be called without parentheses if no status is passed.

    * @link https://php.net/manual/en/function.die.php * @param int|string $status [optional]

    * If status is a string, this function prints the status just before exiting. *

    *

    * If status is an integer, that value will be used as the exit status and not printed. Exit statuses should be in the range 0 to 254, * the exit status 255 is reserved by PHP and shall not be used. The status 0 is used to terminate the program successfully. *

    *

    * Note: PHP >= 4.2.0 does NOT print the status if it is an integer. *

    * @return void */ function PS_UNRESERVE_PREFIX_die($status = "") {} /** *

    Terminates execution of the script. Shutdown functions and object destructors will always be executed even if exit is called.

    *

    exit is a language construct and it can be called without parentheses if no status is passed.

    * @link https://php.net/manual/en/function.exit.php * @param int|string $status [optional]

    * If status is a string, this function prints the status just before exiting. *

    *

    * If status is an integer, that value will be used as the exit status and not printed. Exit statuses should be in the range 0 to 254, * the exit status 255 is reserved by PHP and shall not be used. The status 0 is used to terminate the program successfully. *

    *

    * Note: PHP >= 4.2.0 does NOT print the status if it is an integer. *

    * @return void */ function PS_UNRESERVE_PREFIX_exit($status = "") {} /** * Determine whether a variable is considered to be empty. A variable is considered empty if it does not exist or if its value * equals FALSE. empty() does not generate a warning if the variable does not exist. * @link https://php.net/manual/en/function.empty.php * @param mixed $var

    Variable to be checked.

    *

    Note: Prior to PHP 5.5, empty() only supports variables; anything else will result in a parse error. In other words, * the following will not work: empty(trim($name)). Instead, use trim($name) == false. *

    *

    * No warning is generated if the variable does not exist. That means empty() is essentially the concise equivalent * to !isset($var) || $var == false. *

    * @return bool

    FALSE if var exists and has a non-empty, non-zero value. Otherwise returns TRUE.

    *

    * The following things are considered to be empty: *

      *
    • "" (an empty string)
    • *
    • 0 (0 as an integer)
    • *
    • 0.0 (0 as a float)
    • *
    • "0" (0 as a string)
    • *
    • NULL
    • *
    • FALSE
    • *
    • array() (an empty array)
    • *
    • $var; (a variable declared, but without a value)
    • *
    *

    */ function PS_UNRESERVE_PREFIX_empty($var) {} /** *

    Determine if a variable is set and is not NULL.

    *

    If a variable has been unset with unset(), it will no longer be set. isset() will return FALSE if testing a variable * that has been set to NULL. Also note that a null character ("\0") is not equivalent to the PHP NULL constant.

    *

    If multiple parameters are supplied then isset() will return TRUE only if all of the parameters are set. * Evaluation goes from left to right and stops as soon as an unset variable is encountered.

    * @link https://php.net/manual/en/function.isset.php * @param mixed $var

    The variable to be checked.

    * @param mixed ...$_ [optional]

    Another variable ...

    * @return bool Returns TRUE if var exists and has value other than NULL, FALSE otherwise. */ function PS_UNRESERVE_PREFIX_isset($var, ...$_) {} /** *

    Destroys the specified variables.

    *

    The behavior of unset() inside of a function can vary depending on what type of variable you are attempting to destroy.

    * @link https://php.net/manual/en/function.unset.php * @param mixed $var

    The variable to be unset.

    * @param mixed ...$_ [optional]

    Another variable ...

    * @return void */ function PS_UNRESERVE_PREFIX_unset($var, ...$_) {} /** *

    Evaluates the given code as PHP.

    *

    Caution: The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is * discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to * pass any user provided data into it without properly validating it beforehand.

    * @link https://php.net/manual/en/function.eval.php * @param string $code

    * Valid PHP code to be evaluated. *

    *

    * The code must not be wrapped in opening and closing PHP tags, i.e. 'echo "Hi!";' must be passed instead of ''. * It is still possible to leave and re-enter PHP mode though using the appropriate PHP tags, e.g. * 'echo "In PHP mode!"; ?>In HTML mode! *

    * Apart from that the passed code must be valid PHP. This includes that all statements must be properly terminated using a semicolon. * 'echo "Hi!"' for example will cause a parse error, whereas 'echo "Hi!";' will work. *

    *

    * A return statement will immediately terminate the evaluation of the code. *

    *

    * The code will be executed in the scope of the code calling eval(). Thus any variables defined or changed in the eval() * call will remain visible after it terminates. *

    * @return mixed NULL unless return is called in the evaluated code, in which case the value passed to return is returned. * As of PHP 7, if there is a parse error in the evaluated code, eval() throws a ParseError exception. Before PHP 7, in this * case eval() returned FALSE and execution of the following code continued normally. It is not possible to catch a parse * error in eval() using set_error_handler(). */ function PS_UNRESERVE_PREFIX_eval($code) {} /** * Generator objects are returned from generators, cannot be instantiated via new. * @link https://secure.php.net/manual/en/class.generator.php * @link https://wiki.php.net/rfc/generators * * @template-covariant TKey * @template-covariant TYield * @template TSend * @template-covariant TReturn * * @template-implements Iterator */ final class Generator implements Iterator { /** * Throws an exception if the generator is currently after the first yield. * @return void */ public function rewind(): void {} /** * Returns false if the generator has been closed, true otherwise. * @return bool */ public function valid(): bool {} /** * Returns whatever was passed to yield or null if nothing was passed or the generator is already closed. * @return TYield */ public function current(): mixed {} /** * Returns the yielded key or, if none was specified, an auto-incrementing key or null if the generator is already closed. * @return TKey */ #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: 'string|float|int|bool|null')] public function key() {} /** * Resumes the generator (unless the generator is already closed). * @return void */ public function next(): void {} /** * Sets the return value of the yield expression and resumes the generator (unless the generator is already closed). * @param TSend $value * @return TYield|null */ public function send(mixed $value): mixed {} /** * Throws an exception at the current suspension point in the generator. * @param Throwable $exception * @return TYield */ public function PS_UNRESERVE_PREFIX_throw(Throwable $exception): mixed {} /** * Returns whatever was passed to return or null if nothing. * Throws an exception if the generator is still valid. * @link https://wiki.php.net/rfc/generator-return-expressions * @return TReturn * @since 7.0 */ public function getReturn(): mixed {} /** * Serialize callback * Throws an exception as generators can't be serialized. * @link https://php.net/manual/en/generator.wakeup.php * @return void */ public function __wakeup() {} /** * @since 8.4 */ public function __debugInfo(): array {} } class ClosedGeneratorException extends Exception {} } namespace ___PHPSTORM_HELPERS { class PS_UNRESERVE_PREFIX_this {} class PS_UNRESERVE_PREFIX_static {} class object { /** * PHP 5 allows developers to declare constructor methods for classes. * Classes which have a constructor method call this method on each newly-created object, * so it is suitable for any initialization that the object may need before it is used. * * Note: Parent constructors are not called implicitly if the child class defines a constructor. * In order to run a parent constructor, a call to parent::__construct() within the child constructor is required. * * param [ mixed $args [, $... ]] * @link https://php.net/manual/en/language.oop5.decon.php */ public function __construct() {} /** * PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++. * The destructor method will be called as soon as all references to a particular object are removed or * when the object is explicitly destroyed or in any order in shutdown sequence. * * Like constructors, parent destructors will not be called implicitly by the engine. * In order to run a parent destructor, one would have to explicitly call parent::__destruct() in the destructor body. * * Note: Destructors called during the script shutdown have HTTP headers already sent. * The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache). * * Note: Attempting to throw an exception from a destructor (called in the time of script termination) causes a fatal error. * * @return void * @link https://php.net/manual/en/language.oop5.decon.php */ public function __destruct() {} /** * is triggered when invoking inaccessible methods in an object context. * * @param string $name * @param array $arguments * @return mixed * @link https://php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods */ public function __call(string $name, array $arguments) {} /** * is triggered when invoking inaccessible methods in a static context. * * @param string $name * @param array $arguments * @return mixed * @link https://php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods */ public static function __callStatic(string $name, array $arguments) {} /** * is utilized for reading data from inaccessible members. * * @param string $name * @return mixed * @link https://php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members */ public function __get(string $name) {} /** * run when writing data to inaccessible members. * * @param string $name * @param mixed $value * @return void * @link https://php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members */ public function __set(string $name, $value): void {} /** * is triggered by calling isset() or empty() on inaccessible members. * * @param string $name * @return bool * @link https://php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members */ public function __isset(string $name): bool {} /** * is invoked when unset() is used on inaccessible members. * * @param string $name * @return void * @link https://php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members */ public function __unset(string $name): void {} /** * serialize() checks if your class has a function with the magic name __sleep. * If so, that function is executed prior to any serialization. * It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized. * If the method doesn't return anything then NULL is serialized and E_NOTICE is issued. * The intended use of __sleep is to commit pending data or perform similar cleanup tasks. * Also, the function is useful if you have very large objects which do not need to be saved completely. * * @return string[] * @link https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.sleep */ public function __sleep(): array {} /** * unserialize() checks for the presence of a function with the magic name __wakeup. * If present, this function can reconstruct any resources that the object may have. * The intended use of __wakeup is to reestablish any database connections that may have been lost during * serialization and perform other reinitialization tasks. * * @return void * @link https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.sleep */ public function __wakeup(): void {} /** * The __toString method allows a class to decide how it will react when it is converted to a string. * * @return string * @link https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring */ public function __toString(): string {} /** * The __invoke method is called when a script tries to call an object as a function. * * @return mixed * @link https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.invoke */ public function __invoke() {} /** * This method is called by var_dump() when dumping an object to get the properties that should be shown. * If the method isn't defined on an object, then all public, protected and private properties will be shown. * * @return array|null * @link https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo */ public function __debugInfo(): ?array {} /** * This static method is called for classes exported by var_export() since PHP 5.1.0. * The only parameter of this method is an array containing exported properties in the form array('property' => value, ...). * * @param array $an_array * @return object * @link https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.set-state */ public static function __set_state(array $an_array): object {} /** * When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties. * Any properties that are references to other variables, will remain references. * Once the cloning is complete, if a __clone() method is defined, * then the newly created object's __clone() method will be called, to allow any necessary properties that need to be changed. * NOT CALLABLE DIRECTLY. * * @return void * @link https://php.net/manual/en/language.oop5.cloning.php */ public function __clone(): void {} /** * Returns array containing all the necessary state of the object. * @since 7.4 * @link https://wiki.php.net/rfc/custom_object_serialization */ public function __serialize(): array {} /** * Restores the object state from the given data array. * @param array $data * @since 7.4 * @link https://wiki.php.net/rfc/custom_object_serialization */ public function __unserialize(array $data): void {} } } * priority is a combination of the facility and * the level. Possible values are: * * syslog Priorities (in descending order) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    ConstantDescription
    LOG_EMERGsystem is unusable
    LOG_ALERTaction must be taken immediately
    LOG_CRITcritical conditions
    LOG_ERRerror conditions
    LOG_WARNINGwarning conditions
    LOG_NOTICEnormal, but significant, condition
    LOG_INFOinformational message
    LOG_DEBUGdebug-level message
    *

    * @param string $message

    * The message to send, except that the two characters * %m will be replaced by the error message string * (strerror) corresponding to the present value of * errno. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function syslog(int $priority, string $message) {} /** * Close connection to system logger * @link https://php.net/manual/en/function.closelog.php */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function closelog() {} /** * Registers a function that will be called when PHP starts sending output. * The callback is executed just after PHP prepares all headers to be sent,
    * and before any other output is sent, creating a window to manipulate the outgoing headers before being sent. * @link https://secure.php.net/manual/en/function.header-register-callback.php * @param callable $callback Function called just before the headers are sent. * @return bool true on success or false on failure. */ function header_register_callback(callable $callback): bool {} /** * Get the size of an image from a string. * @param string $string The image data, as a string. * @param array &$image_info [optional] This optional parameter allows you to extract
    * some extended information from the image file. Currently, this will
    * return the different JPG APP markers as an associative array.
    * Some programs use these APP markers to embed text information in images.
    * A very common one is to embed » IPTC information in the APP13 marker.
    * You can use the iptcparse() function to parse the binary APP13 marker into something readable. * @return array|false Returns an array with 7 elements.
    * Index 0 and 1 contains respectively the width and the height of the image.
    * Index 2 is one of the IMAGETYPE_XXX constants indicating the type of the image.
    * Index 3 is a text string with the correct height="yyy" width="xxx" string
    * that can be used directly in an IMG tag.
    * On failure, FALSE is returned. * @link https://secure.php.net/manual/en/function.getimagesizefromstring.php * @since 5.4 * @link https://secure.php.net/manual/en/function.getimagesizefromstring.php * @since 5.4 */ #[ArrayShape([0 => 'int', 1 => 'int', 2 => 'int', 3 => 'string', 'bits' => 'int', 'channels' => 'int', 'mime' => 'string'])] function getimagesizefromstring(string $string, &$image_info): array|false {} /** * Set the stream chunk size. * @param resource $stream The target stream. * @param int $size The desired new chunk size. * @return int|false Returns the previous chunk size on success.
    * Will return FALSE if chunk_size is less than 1 or greater than PHP_INT_MAX. * @link https://secure.php.net/manual/en/function.stream-set-chunk-size.php * @since 5.4 */ #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function stream_set_chunk_size($stream, int $size) {} /** * Initializes all syslog related variables * @link https://php.net/manual/en/function.define-syslog-variables.php * @return void * @removed 5.4 */ #[Deprecated(since: '5.3')] function define_syslog_variables() {} /** * Calculate the metaphone key of a string * @link https://php.net/manual/en/function.metaphone.php * @param string $string

    * The input string. *

    * @param int $max_phonemes [optional]

    * This parameter restricts the returned metaphone key to phonemes characters in length. * The default value of 0 means no restriction. *

    * @return string|false the metaphone key as a string, or FALSE on failure */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] function metaphone(string $string, int $max_phonemes = 0) {} /** * Turn on output buffering * @link https://php.net/manual/en/function.ob-start.php * @param callable $callback [optional]

    * An optional output_callback function may be * specified. This function takes a string as a parameter and should * return a string. The function will be called when * the output buffer is flushed (sent) or cleaned (with * ob_flush, ob_clean or similar * function) or when the output buffer * is flushed to the browser at the end of the request. When * output_callback is called, it will receive the * contents of the output buffer as its parameter and is expected to * return a new output buffer as a result, which will be sent to the * browser. If the output_callback is not a * callable function, this function will return false. *

    *

    * If the callback function has two parameters, the second parameter is * filled with a bit-field consisting of * PHP_OUTPUT_HANDLER_START, * PHP_OUTPUT_HANDLER_CONT and * PHP_OUTPUT_HANDLER_END. *

    *

    * If output_callback returns false original * input is sent to the browser. *

    *

    * The output_callback parameter may be bypassed * by passing a null value. *

    *

    * ob_end_clean, ob_end_flush, * ob_clean, ob_flush and * ob_start may not be called from a callback * function. If you call them from callback function, the behavior is * undefined. If you would like to delete the contents of a buffer, * return "" (a null string) from callback function. * You can't even call functions using the output buffering functions like * print_r($expression, true) or * highlight_file($filename, true) from a callback * function. *

    *

    * In PHP 4.0.4, ob_gzhandler was introduced to * facilitate sending gz-encoded data to web browsers that support * compressed web pages. ob_gzhandler determines * what type of content encoding the browser will accept and will return * its output accordingly. *

    * @param int $chunk_size

    * If the optional parameter chunk_size is passed, the * buffer will be flushed after any output call which causes the buffer's * length to equal or exceed chunk_size. * Default value 0 means that the function is called only in the end, * other special value 1 sets chunk_size to 4096. *

    * @param int $flags [optional]

    * The flags parameter is a bitmask that controls the operations that can be performed on the output buffer. * The default is to allow output buffers to be cleaned, flushed and removed, which can be set explicitly via * PHP_OUTPUT_HANDLER_CLEANABLE | PHP_OUTPUT_HANDLER_FLUSHABLE | PHP_OUTPUT_HANDLER_REMOVABLE, or PHP_OUTPUT_HANDLER_STDFLAGS as shorthand. *

    * @return bool true on success or false on failure. */ function ob_start($callback, int $chunk_size = 0, int $flags = PHP_OUTPUT_HANDLER_STDFLAGS): bool {} /** * Flush (send) the output buffer * @link https://php.net/manual/en/function.ob-flush.php * @return bool */ function ob_flush(): bool {} /** * Clean (erase) the output buffer * @link https://php.net/manual/en/function.ob-clean.php * @return bool */ function ob_clean(): bool {} /** * Flush (send) the output buffer and turn off output buffering * @link https://php.net/manual/en/function.ob-end-flush.php * @return bool true on success or false on failure. Reasons for failure are first that you called the * function without an active buffer or that for some reason a buffer could * not be deleted (possible for special buffer). */ function ob_end_flush(): bool {} /** * Clean (erase) the output buffer and turn off output buffering * @link https://php.net/manual/en/function.ob-end-clean.php * @return bool true on success or false on failure. Reasons for failure are first that you called the * function without an active buffer or that for some reason a buffer could * not be deleted (possible for special buffer). */ function ob_end_clean(): bool {} /** * Flush the output buffer, return it as a string and turn off output buffering * @link https://php.net/manual/en/function.ob-get-flush.php * @return string|false the output buffer or false if no buffering is active. */ function ob_get_flush(): string|false {} /** * Get current buffer contents and delete current output buffer * @link https://php.net/manual/en/function.ob-get-clean.php * @return string|false the contents of the output buffer and end output buffering. * If output buffering isn't active then false is returned. */ function ob_get_clean(): string|false {} /** * Return the length of the output buffer * @link https://php.net/manual/en/function.ob-get-length.php * @return int|false the length of the output buffer contents or false if no * buffering is active. */ function ob_get_length(): int|false {} /** * Return the nesting level of the output buffering mechanism * @link https://php.net/manual/en/function.ob-get-level.php * @return int the level of nested output buffering handlers or zero if output * buffering is not active. */ function ob_get_level(): int {} /** * Get status of output buffers * @link https://php.net/manual/en/function.ob-get-status.php * @param bool $full_status [optional]

    * true to return all active output buffer levels. If false or not * set, only the top level output buffer is returned. *

    * @return array If called without the full_status parameter * or with full_status = false a simple array * with the following elements is returned: *
     * Array
     * (
     *     [level] => 2
     *     [type] => 0
     *     [status] => 0
     *     [name] => URL-Rewriter
     *     [del] => 1
     * )
     * 
    * * * * * * * *
    KeyValue
    levelOutput nesting level
    typePHP_OUTPUT_HANDLER_INTERNAL (0) or PHP_OUTPUT_HANDLER_USER (1)
    statusOne of PHP_OUTPUT_HANDLER_START (0), PHP_OUTPUT_HANDLER_CONT (1) or PHP_OUTPUT_HANDLER_END (2)
    nameName of active output handler or ' default output handler' if none is set
    delErase-flag as set by ob_start()
    *

    * If called with full_status = TRUE an array with one element for each active output buffer * level is returned. The output level is used as key of the top level array and each array * element itself is another array holding status information on one active output level. *

    *
     * Array
     * (
     *     [0] => Array
     *         (
     *             [chunk_size] => 0
     *             [size] => 40960
     *             [block_size] => 10240
     *             [type] => 1
     *             [status] => 0
     *             [name] => default output handler
     *             [del] => 1
     *         )
     *
     *     [1] => Array
     *         (
     *             [chunk_size] => 0
     *             [size] => 40960
     *             [block_size] => 10240
     *             [type] => 0
     *             [buffer_size] => 0
     *             [status] => 0
     *             [name] => URL-Rewriter
     *             [del] => 1
     *         )
     *
     * )
     * 
    *

    The full output contains these additional elements:

    * * * * * *
    KeyValue
    chunk_sizeChunk size as set by ob_start()
    size...
    blocksize...
    */ #[ArrayShape([ "level" => "int", "type" => "int", "flags" => "int", "name" => "string", "del" => "int", "chunk_size" => "int", "buffer_size" => "int", "buffer_used" => "int", ])] function ob_get_status(bool $full_status = false): array {} /** * Return the contents of the output buffer * @link https://php.net/manual/en/function.ob-get-contents.php * @return string|false This will return the contents of the output buffer or false, if output * buffering isn't active. */ #[Pure(true)] function ob_get_contents(): string|false {} /** * Turn implicit flush on/off * @link https://php.net/manual/en/function.ob-implicit-flush.php * @param int|bool $enable [optional]

    * 1|TRUE to turn implicit flushing on, 0|FALSE turns it off. *

    default: 1|TRUE *

    * @return void */ function ob_implicit_flush(#[LanguageLevelTypeAware(["8.0" => "bool"], default: "int")] $enable = true): void {} /** * List all output handlers in use * @link https://php.net/manual/en/function.ob-list-handlers.php * @return array This will return an array with the output handlers in use (if any). If * output_buffering is enabled or * an anonymous function was used with ob_start, * ob_list_handlers will return "default output * handler". */ function ob_list_handlers(): array {} /** * Sort an array by key * @link https://php.net/manual/en/function.ksort.php * @param array &$array

    * The input array. *

    * @param int $flags

    * You may modify the behavior of the sort using the optional * parameter sort_flags, for details * see sort. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function ksort(array &$array, int $flags = SORT_REGULAR) {} /** * Sort an array by key in reverse order * @link https://php.net/manual/en/function.krsort.php * @param array &$array

    * The input array. *

    * @param int $flags

    * You may modify the behavior of the sort using the optional parameter * sort_flags, for details see * sort. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function krsort(array &$array, int $flags = SORT_REGULAR) {} /** * Sort an array using a "natural order" algorithm * @link https://php.net/manual/en/function.natsort.php * @param array &$array

    * The input array. *

    */ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function natsort(array &$array) {} /** * Sort an array using a case insensitive "natural order" algorithm * @link https://php.net/manual/en/function.natcasesort.php * @param array &$array

    * The input array. *

    */ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function natcasesort(array &$array) {} /** * Sort an array and maintain index association * @link https://php.net/manual/en/function.asort.php * @param array &$array

    * The input array. *

    * @param int $flags

    * You may modify the behavior of the sort using the optional * parameter sort_flags, for details * see sort. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function asort(array &$array, int $flags = SORT_REGULAR) {} /** * Sort an array in reverse order and maintain index association * @link https://php.net/manual/en/function.arsort.php * @param array &$array

    * The input array. *

    * @param int $flags

    * You may modify the behavior of the sort using the optional parameter * sort_flags, for details see * sort. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function arsort(array &$array, int $flags = SORT_REGULAR) {} /** * Sort an array * @link https://php.net/manual/en/function.sort.php * @param array &$array

    * The input array. *

    * @param int $flags

    * The optional second parameter sort_flags * may be used to modify the sorting behavior using these values. *

    *

    * Sorting type flags:
    * SORT_REGULAR - compare items normally * (don't change types)

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function sort(array &$array, int $flags = SORT_REGULAR) {} /** * Sort an array in reverse order * @link https://php.net/manual/en/function.rsort.php * @param array &$array

    * The input array. *

    * @param int $flags

    * You may modify the behavior of the sort using the optional * parameter sort_flags, for details see * sort. *

    */ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function rsort(array &$array, int $flags = SORT_REGULAR) {} /** * Sort an array by values using a user-defined comparison function * @link https://php.net/manual/en/function.usort.php * @param array &$array

    * The input array. *

    * @param callable $callback

    * The comparison function must return an integer less than, equal to, or * greater than zero if the first argument is considered to be * respectively less than, equal to, or greater than the second. *

    * @return true Always returns true. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function usort(array &$array, callable $callback) {} /** * Sort an array with a user-defined comparison function and maintain index association * @link https://php.net/manual/en/function.uasort.php * @param array &$array

    * The input array. *

    * @param callable $callback

    * See usort and uksort for * examples of user-defined comparison functions. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function uasort(array &$array, callable $callback) {} /** * Sort an array by keys using a user-defined comparison function * @link https://php.net/manual/en/function.uksort.php * @param array &$array

    * The input array. *

    * @param callable $callback

    * The callback comparison function. *

    *

    * Function cmp_function should accept two * parameters which will be filled by pairs of array keys. * The comparison function must return an integer less than, equal * to, or greater than zero if the first argument is considered to * be respectively less than, equal to, or greater than the * second. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function uksort(array &$array, callable $callback) {} /** * Shuffle an array * @link https://php.net/manual/en/function.shuffle.php * @param array &$array

    * The array. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function shuffle(array &$array) {} /** * Apply a user function to every member of an array * @link https://php.net/manual/en/function.array-walk.php * @param array|object &$array

    * The input array. *

    * @param callable $callback

    * Typically, funcname takes on two parameters. * The array parameter's value being the first, and * the key/index second. *

    *

    * If funcname needs to be working with the * actual values of the array, specify the first parameter of * funcname as a * reference. Then, * any changes made to those elements will be made in the * original array itself. *

    *

    * Users may not change the array itself from the * callback function. e.g. Add/delete elements, unset elements, etc. If * the array that array_walk is applied to is * changed, the behavior of this function is undefined, and unpredictable. *

    * @param mixed $arg [optional]

    * If the optional userdata parameter is supplied, * it will be passed as the third parameter to the callback * funcname. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function array_walk(object|array &$array, callable $callback, mixed $arg) {} /** * Apply a user function recursively to every member of an array * @link https://php.net/manual/en/function.array-walk-recursive.php * @param array|object &$array

    * The input array. *

    * @param callable $callback

    * Typically, funcname takes on two parameters. * The input parameter's value being the first, and * the key/index second. *

    *

    * If funcname needs to be working with the * actual values of the array, specify the first parameter of * funcname as a * reference. Then, * any changes made to those elements will be made in the * original array itself. *

    * @param mixed $arg [optional]

    * If the optional userdata parameter is supplied, * it will be passed as the third parameter to the callback * funcname. *

    */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function array_walk_recursive(object|array &$array, callable $callback, mixed $arg) {} /** * Counts all elements in an array, or something in an object. *

    For objects, if you have SPL installed, you can hook into count() by implementing interface {@see Countable}. * The interface has exactly one method, {@see Countable::count()}, which returns the return value for the count() function. * Please see the {@see Array} section of the manual for a detailed explanation of how arrays are implemented and used in PHP.

    * @link https://php.net/manual/en/function.count.php * @param array|Countable $value The array or the object. * @param int $mode [optional] If the optional mode parameter is set to * COUNT_RECURSIVE (or 1), count * will recursively count the array. This is particularly useful for * counting all the elements of a multidimensional array. count does not detect infinite recursion. * @return int<0,max> the number of elements in var, which is * typically an array, since anything else will have one * element. *

    * If var is not an array or an object with * implemented Countable interface, * 1 will be returned. * There is one exception, if var is null, * 0 will be returned. *

    *

    * Caution: count may return 0 for a variable that isn't set, * but it may also return 0 for a variable that has been initialized with an * empty array. Use isset to test if a variable is set. *

    */ #[Pure] function count(Countable|array $value, int $mode = COUNT_NORMAL): int {} /** * Set the internal pointer of an array to its last element * @link https://php.net/manual/en/function.end.php * @param array|object &$array

    * The array. This array is passed by reference because it is modified by * the function. This means you must pass it a real variable and not * a function returning an array because only actual variables may be * passed by reference. *

    * @return mixed|false the value of the last element or false for empty array. * @meta */ function end(object|array &$array): mixed {} /** * Rewind the internal array pointer * @link https://php.net/manual/en/function.prev.php * @param array|object &$array

    * The input array. *

    * @return mixed|false the array value in the previous place that's pointed to by * the internal array pointer, or false if there are no more * elements. * @meta */ function prev(object|array &$array): mixed {} /** * Advance the internal array pointer of an array * @link https://php.net/manual/en/function.next.php * @param array|object &$array

    * The array being affected. *

    * @return mixed|false the array value in the next place that's pointed to by the * internal array pointer, or false if there are no more elements. * @meta */ function next(object|array &$array): mixed {} /** * Set the internal pointer of an array to its first element * @link https://php.net/manual/en/function.reset.php * @param array|object &$array

    * The input array. *

    * @return mixed|false the value of the first array element, or false if the array is * empty. * @meta */ function reset(object|array &$array): mixed {} /** * Return the current element in an array * @link https://php.net/manual/en/function.current.php * @param array|object $array

    * The array. *

    * @return mixed|false The current function simply returns the * value of the array element that's currently being pointed to by the * internal pointer. It does not move the pointer in any way. If the * internal pointer points beyond the end of the elements list or the array is * empty, current returns false. * @meta */ #[Pure] function current(object|array $array): mixed {} /** * Fetch a key from an array * @link https://php.net/manual/en/function.key.php * @param array|object $array

    * The array. *

    * @return int|string|null The key function simply returns the * key of the array element that's currently being pointed to by the * internal pointer. It does not move the pointer in any way. If the * internal pointer points beyond the end of the elements list or the array is * empty, key returns null. */ #[Pure] function key(object|array $array): string|int|null {} /** * Find lowest value * @link https://php.net/manual/en/function.min.php * @param array|mixed $value Array to look through or first value to compare * @param mixed ...$values any comparable value * @return mixed min returns the numerically lowest of the * parameter values. */ #[Pure] function min( #[PhpStormStubsElementAvailable(from: '8.0')] mixed $value, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] mixed $values, mixed ...$values ): mixed {} /** * Find highest value * @link https://php.net/manual/en/function.max.php * @param array|mixed $value Array to look through or first value to compare * @param mixed ...$values any comparable value * @return mixed max returns the numerically highest of the * parameter values, either within a arg array or two arguments. */ #[Pure] function max( #[PhpStormStubsElementAvailable(from: '8.0')] mixed $value, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] mixed $values, mixed ...$values ): mixed {} /** * Checks if a value exists in an array * @link https://php.net/manual/en/function.in-array.php * @param mixed $needle

    * The searched value. *

    *

    * If needle is a string, the comparison is done * in a case-sensitive manner. *

    * @param array $haystack

    * The array. *

    * @param bool $strict [optional]

    * If the third parameter strict is set to true * then the in_array function will also check the * types of the * needle in the haystack. *

    * @return bool true if needle is found in the array, * false otherwise. */ #[Pure] function in_array(mixed $needle, array $haystack, bool $strict = false): bool {} /** * Searches the array for a given value and returns the first corresponding key if successful * @link https://php.net/manual/en/function.array-search.php * @param mixed $needle

    * The searched value. *

    *

    * If needle is a string, the comparison is done * in a case-sensitive manner. *

    * @param array $haystack

    * The array. *

    * @param bool $strict [optional]

    * If the third parameter strict is set to true * then the array_search function will also check the * types of the * needle in the haystack. *

    * @return int|string|false the key for needle if it is found in the * array, false otherwise. *

    *

    * If needle is found in haystack * more than once, the first matching key is returned. To return the keys for * all matching values, use array_keys with the optional * search_value parameter instead. */ #[Pure] function array_search(mixed $needle, array $haystack, bool $strict = false): string|int|false {} /** * Import variables into the current symbol table from an array * @link https://php.net/manual/en/function.extract.php * @param array &$array

    * Note that prefix is only required if * extract_type is EXTR_PREFIX_SAME, * EXTR_PREFIX_ALL, EXTR_PREFIX_INVALID * or EXTR_PREFIX_IF_EXISTS. If * the prefixed result is not a valid variable name, it is not * imported into the symbol table. Prefixes are automatically separated from * the array key by an underscore character. *

    * @param int $flags

    * The way invalid/numeric keys and collisions are treated is determined * by the extract_type. It can be one of the * following values: * EXTR_OVERWRITE * If there is a collision, overwrite the existing variable.

    * @param string $prefix

    Only overwrite the variable if it already exists in the * current symbol table, otherwise do nothing. This is useful * for defining a list of valid variables and then extracting * only those variables you have defined out of * $_REQUEST, for example.

    * @return int the number of variables successfully imported into the symbol * table. */ function extract( array &$array, #[ExpectedValues(flags: [ EXTR_OVERWRITE, EXTR_SKIP, EXTR_PREFIX_SAME, EXTR_PREFIX_ALL, EXTR_PREFIX_INVALID, EXTR_IF_EXISTS, EXTR_PREFIX_IF_EXISTS, EXTR_REFS ])] int $flags = EXTR_OVERWRITE, string $prefix = "" ): int {} /** * Create array containing variables and their values * @link https://php.net/manual/en/function.compact.php * @param mixed $var_name

    * compact takes a variable number of parameters. * Each parameter can be either a string containing the name of the * variable, or an array of variable names. The array can contain other * arrays of variable names inside it; compact * handles it recursively. *

    * @param mixed ...$var_names * @return array the output array with all the variables added to it. */ #[Pure] function compact(#[PhpStormStubsElementAvailable(from: '8.0')] $var_name, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $var_names, ...$var_names): array {} /** * Fill an array with values * @link https://php.net/manual/en/function.array-fill.php * @param int $start_index

    * The first index of the returned array. * Supports non-negative indexes only. *

    * @param int $count

    * Number of elements to insert *

    * @param mixed $value

    * Value to use for filling *

    * @return array the filled array */ #[Pure] function array_fill(int $start_index, int $count, mixed $value): array {} /** * Fill an array with values, specifying keys * @link https://php.net/manual/en/function.array-fill-keys.php * @param array $keys

    * Array of values that will be used as keys. Illegal values * for key will be converted to string. *

    * @param mixed $value

    * Value to use for filling *

    * @return array the filled array */ #[Pure] function array_fill_keys(array $keys, mixed $value): array {} /** * Create an array containing a range of elements * @link https://php.net/manual/en/function.range.php * @param mixed $start

    * First value of the sequence. *

    * @param mixed $end

    * The sequence is ended upon reaching the end value. *

    * @param positive-int|float $step [optional]

    * If a step value is given, it will be used as the * increment between elements in the sequence. step * should be given as a positive number. If not specified, * step will default to 1. *

    * @return array an array of elements from start to * end, inclusive. */ #[Pure] function range( #[LanguageLevelTypeAware(['8.3' => 'string|int|float'], default: '')] $start, #[LanguageLevelTypeAware(['8.3' => 'string|int|float'], default: '')] $end, int|float $step = 1 ): array {} /** * Sort multiple or multi-dimensional arrays * @link https://php.net/manual/en/function.array-multisort.php * @param array &$array

    * An array being sorted. *

    * @param &...$rest [optional]

    * More arrays, optionally followed by sort order and flags. * Only elements corresponding to equivalent elements in previous arrays are compared. * In other words, the sort is lexicographical. *

    * @return bool true on success or false on failure. */ function array_multisort( &$array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $sort_order = SORT_ASC, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $sort_flags = SORT_REGULAR, &...$rest ): bool {} /** * Push elements onto the end of array * Since 7.3.0 this function can be called with only one parameter. * For earlier versions at least two parameters are required. * @link https://php.net/manual/en/function.array-push.php * @param array &$array

    * The input array. *

    * @param mixed ...$values

    * The pushed variables. *

    * @return int the number of elements in the array. */ function array_push( array &$array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] $values, mixed ...$values ): int {} /** * Pop the element off the end of array * @link https://php.net/manual/en/function.array-pop.php * @param array &$array

    * The array to get the value from. *

    * @return mixed|null the last value of array. * If array is empty (or is not an array), * null will be returned. * @meta */ function array_pop(array &$array): mixed {} /** * Shift an element off the beginning of array * @link https://php.net/manual/en/function.array-shift.php * @param array &$array

    * The input array. *

    * @return mixed|null the shifted value, or null if array is * empty or is not an array. * @meta */ function array_shift(array &$array): mixed {} /** * Prepend elements to the beginning of an array * Since 7.3.0 this function can be called with only one parameter. * For earlier versions at least two parameters are required. * @link https://php.net/manual/en/function.array-unshift.php * @param array &$array

    * The input array. *

    * @param mixed ...$values

    * The prepended variables. *

    * @return int the number of elements in the array. */ function array_unshift(array &$array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.2')] $values, mixed ...$values): int {} /** * Remove a portion of the array and replace it with something else * @link https://php.net/manual/en/function.array-splice.php * @param array &$array

    * The input array. *

    * @param int $offset

    * If offset is positive then the start of removed * portion is at that offset from the beginning of the * input array. If offset * is negative then it starts that far from the end of the * input array. *

    * @param int|null $length [optional]

    * If length is omitted, removes everything * from offset to the end of the array. If * length is specified and is positive, then * that many elements will be removed. If * length is specified and is negative then * the end of the removed portion will be that many elements from * the end of the array. Tip: to remove everything from * offset to the end of the array when * replacement is also specified, use * count($input) for * length. *

    * @param mixed $replacement

    * If replacement array is specified, then the * removed elements are replaced with elements from this array. *

    *

    * If offset and length * are such that nothing is removed, then the elements from the * replacement array are inserted in the place * specified by the offset. Note that keys in * replacement array are not preserved. *

    *

    * If replacement is just one element it is * not necessary to put array() * around it, unless the element is an array itself. *

    * @return array the array consisting of the extracted elements. */ function array_splice(array &$array, int $offset, ?int $length, mixed $replacement = []): array {} /** * Extract a slice of the array * @link https://php.net/manual/en/function.array-slice.php * @param array $array

    * The input array. *

    * @param int $offset

    * If offset is non-negative, the sequence will * start at that offset in the array. If * offset is negative, the sequence will * start that far from the end of the array. *

    * @param int|null $length [optional]

    * If length is given and is positive, then * the sequence will have that many elements in it. If * length is given and is negative then the * sequence will stop that many elements from the end of the * array. If it is omitted, then the sequence will have everything * from offset up until the end of the * array. *

    * @param bool $preserve_keys [optional]

    * Note that array_slice will reorder and reset the * array indices by default. You can change this behaviour by setting * preserve_keys to true. *

    * @return array the slice. * @meta */ #[Pure] function array_slice(array $array, int $offset, ?int $length, bool $preserve_keys = false): array {} /** * Merges the elements of one or more arrays together (if the input arrays have the same string keys, then the later value for that key will overwrite the previous one; if the arrays contain numeric keys, the later value will be appended) * Since 7.4.0 this function can be called without any parameter, and it will return empty array. * @link https://php.net/manual/en/function.array-merge.php * @param array ...$arrays

    * Variable list of arrays to merge. *

    * @return array the resulting array. * @meta */ #[Pure] function array_merge( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.3')] $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] $arrays, array ...$arrays ): array {} * The streams listed in the read array will be watched to * see if characters become available for reading (more precisely, to see if * a read will not block - in particular, a stream resource is also ready on * end-of-file, in which case an fread will return * a zero length string). *

    * @param array|null &$write

    * The streams listed in the write array will be * watched to see if a write will not block. *

    * @param array|null &$except

    * The streams listed in the except array will be * watched for high priority exceptional ("out-of-band") data arriving. *

    *

    * When stream_select returns, the arrays * read, write and * except are modified to indicate which stream * resource(s) actually changed status. *

    * You do not need to pass every array to * stream_select. You can leave it out and use an * empty array or null instead. Also do not forget that those arrays are * passed by reference and will be modified after * stream_select returns. * @param int|null $seconds

    * The tv_sec and tv_usec * together form the timeout parameter, * tv_sec specifies the number of seconds while * tv_usec the number of microseconds. * The timeout is an upper bound on the amount of time * that stream_select will wait before it returns. * If tv_sec and tv_usec are * both set to 0, stream_select will * not wait for data - instead it will return immediately, indicating the * current status of the streams. *

    *

    * If tv_sec is null stream_select * can block indefinitely, returning only when an event on one of the * watched streams occurs (or if a signal interrupts the system call). *

    *

    * Using a timeout value of 0 allows you to * instantaneously poll the status of the streams, however, it is NOT a * good idea to use a 0 timeout value in a loop as it * will cause your script to consume too much CPU time. *

    *

    * It is much better to specify a timeout value of a few seconds, although * if you need to be checking and running other code concurrently, using a * timeout value of at least 200000 microseconds will * help reduce the CPU usage of your script. *

    *

    * Remember that the timeout value is the maximum time that will elapse; * stream_select will return as soon as the * requested streams are ready for use. *

    * @param int $microseconds [optional]

    * See tv_sec description. *

    * @return int|false On success stream_select returns the number of * stream resources contained in the modified arrays, which may be zero if * the timeout expires before anything interesting happens. On error false * is returned and a warning raised (this can happen if the system call is * interrupted by an incoming signal). */ function stream_select( ?array &$read, ?array &$write, ?array &$except, ?int $seconds, #[LanguageLevelTypeAware(['8.1' => 'int|null'], default: 'int')] $microseconds ): int|false {} /** * Create a stream context * @link https://php.net/manual/en/function.stream-context-create.php * @param null|array $options [optional]

    * Must be an associative array of associative arrays in the format * $arr['wrapper']['option'] = $value. *

    *

    * Default to an empty array. *

    * @param null|array $params [optional]

    * Must be an associative array in the format * $arr['parameter'] = $value. * Refer to context parameters for * a listing of standard stream parameters. *

    * @return resource A stream context resource. */ function stream_context_create(?array $options, ?array $params) {} /** * Set parameters for a stream/wrapper/context * @link https://php.net/manual/en/function.stream-context-set-params.php * @param resource $context

    * The stream or context to apply the parameters too. *

    * @param array $params

    * An array of parameters to set. *

    *

    * params should be an associative array of the structure: * $params['paramname'] = "paramvalue";. *

    * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] function stream_context_set_params($context, array $params) {} /** * Retrieves parameters from a context * @link https://php.net/manual/en/function.stream-context-get-params.php * @param resource $context

    * A stream resource or a * context resource *

    * @return array an associate array containing all context options and parameters. */ #[ArrayShape(["notification" => "string", "options" => "array"])] function stream_context_get_params($context): array {} /** * Sets an option for a stream/wrapper/context * @link https://php.net/manual/en/function.stream-context-set-option.php * @param resource $context

    * The stream or context resource to apply the options too. *

    * @param string $wrapper_or_options * @param string $option_name * @param mixed $value * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] function stream_context_set_option($context, string $wrapper_or_options, string $option_name, mixed $value) {} /** * Sets an option for a stream/wrapper/context * @link https://php.net/manual/en/function.stream-context-set-option.php * @param resource $stream_or_context The stream or context resource to apply the options too. * @param array $options The options to set for the default context. * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] function stream_context_set_option($stream_or_context, array $options) {} /** * @since 8.3 */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] function stream_context_set_options($context, array $options) {} /** * Retrieve options for a stream/wrapper/context * @link https://php.net/manual/en/function.stream-context-get-options.php * @param resource $stream_or_context

    * The stream or context to get options from *

    * @return array an associative array with the options. */ function stream_context_get_options($stream_or_context): array {} /** * Retreive the default stream context * @link https://php.net/manual/en/function.stream-context-get-default.php * @param null|array $options [optional] options must be an associative * array of associative arrays in the format * $arr['wrapper']['option'] = $value. *

    * As of PHP 5.3.0, the stream_context_set_default function * can be used to set the default context. *

    * @return resource A stream context resource. */ function stream_context_get_default(?array $options) {} /** * Set the default stream context * @link https://php.net/manual/en/function.stream-context-set-default.php * @param array $options

    * The options to set for the default context. *

    *

    * options must be an associative * array of associative arrays in the format * $arr['wrapper']['option'] = $value. *

    * @return resource the default stream context. */ function stream_context_set_default(array $options) {} /** * Attach a filter to a stream * @link https://php.net/manual/en/function.stream-filter-prepend.php * @param resource $stream

    * The target stream. *

    * @param string $filter_name

    * The filter name. *

    * @param int $mode

    * By default, stream_filter_prepend will * attach the filter to the read filter chain * if the file was opened for reading (i.e. File Mode: * r, and/or +). The filter * will also be attached to the write filter chain * if the file was opened for writing (i.e. File Mode: * w, a, and/or +). * STREAM_FILTER_READ, * STREAM_FILTER_WRITE, and/or * STREAM_FILTER_ALL can also be passed to the * read_write parameter to override this behavior. * See stream_filter_append for an example of * using this parameter. *

    * @param mixed $params [optional]

    * This filter will be added with the specified params * to the beginning of the list and will therefore be * called first during stream operations. To add a filter to the end of the * list, use stream_filter_append. *

    * @return resource|false a resource which can be used to refer to this filter * instance during a call to stream_filter_remove. */ function stream_filter_prepend($stream, string $filter_name, int $mode = 0, mixed $params) {} /** * Attach a filter to a stream * @link https://php.net/manual/en/function.stream-filter-append.php * @param resource $stream

    * The target stream. *

    * @param string $filter_name

    * The filter name. *

    * @param int $mode

    * By default, stream_filter_append will * attach the filter to the read filter chain * if the file was opened for reading (i.e. File Mode: * r, and/or +). The filter * will also be attached to the write filter chain * if the file was opened for writing (i.e. File Mode: * w, a, and/or +). * STREAM_FILTER_READ, * STREAM_FILTER_WRITE, and/or * STREAM_FILTER_ALL can also be passed to the * read_write parameter to override this behavior. *

    * @param mixed $params [optional]

    * This filter will be added with the specified * params to the end of * the list and will therefore be called last during stream operations. * To add a filter to the beginning of the list, use * stream_filter_prepend. *

    * @return resource|false a resource which can be used to refer to this filter * instance during a call to stream_filter_remove. */ function stream_filter_append($stream, string $filter_name, int $mode = 0, mixed $params) {} /** * Remove a filter from a stream * @link https://php.net/manual/en/function.stream-filter-remove.php * @param resource $stream_filter

    * The stream filter to be removed. *

    * @return bool true on success or false on failure. */ function stream_filter_remove($stream_filter): bool {} /** * Open Internet or Unix domain socket connection * @link https://php.net/manual/en/function.stream-socket-client.php * @param string $address

    * Address to the socket to connect to. *

    * @param int &$error_code [optional]

    * Will be set to the system level error number if connection fails. *

    * @param string &$error_message [optional]

    * Will be set to the system level error message if the connection fails. *

    * @param float|null $timeout [optional]

    * Number of seconds until the connect() system call * should timeout. * This parameter only applies when not making asynchronous * connection attempts. *

    * To set a timeout for reading/writing data over the socket, use the * stream_set_timeout, as the * timeout only applies while making connecting * the socket. *

    *

    * @param int $flags [optional]

    * Bitmask field which may be set to any combination of connection flags. * Currently the select of connection flags is limited to * STREAM_CLIENT_CONNECT (default), * STREAM_CLIENT_ASYNC_CONNECT and * STREAM_CLIENT_PERSISTENT. *

    * @param resource $context [optional]

    * A valid context resource created with stream_context_create. *

    * @return resource|false On success a stream resource is returned which may * be used together with the other file functions (such as * fgets, fgetss, * fwrite, fclose, and * feof), false on failure. */ function stream_socket_client(string $address, &$error_code, &$error_message, ?float $timeout, int $flags = STREAM_CLIENT_CONNECT, $context) {} /** * Create an Internet or Unix domain server socket * @link https://php.net/manual/en/function.stream-socket-server.php * @param string $address

    * The type of socket created is determined by the transport specified * using standard URL formatting: transport://target. *

    *

    * For Internet Domain sockets (AF_INET) such as TCP and UDP, the * target portion of the * remote_socket parameter should consist of a * hostname or IP address followed by a colon and a port number. For * Unix domain sockets, the target portion should * point to the socket file on the filesystem. *

    *

    * Depending on the environment, Unix domain sockets may not be available. * A list of available transports can be retrieved using * stream_get_transports. See * for a list of built-in transports. *

    * @param int &$error_code [optional]

    * If the optional errno and errstr * arguments are present they will be set to indicate the actual system * level error that occurred in the system-level socket(), * bind(), and listen() calls. If * the value returned in errno is * 0 and the function returned false, it is an * indication that the error occurred before the bind() * call. This is most likely due to a problem initializing the socket. * Note that the errno and * errstr arguments will always be passed by reference. *

    * @param string &$error_message [optional]

    * See errno description. *

    * @param int $flags [optional]

    * A bitmask field which may be set to any combination of socket creation * flags. *

    *

    * For UDP sockets, you must use STREAM_SERVER_BIND as * the flags parameter. *

    * @param resource $context [optional]

    *

    * @return resource|false the created stream, or false on error. */ function stream_socket_server(string $address, &$error_code, &$error_message, int $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context) {} /** * Accept a connection on a socket created by {@see stream_socket_server} * @link https://php.net/manual/en/function.stream-socket-accept.php * @param resource $socket * @param float|null $timeout [optional]

    * Override the default socket accept timeout. Time should be given in * seconds. *

    * @param string &$peer_name [optional]

    * Will be set to the name (address) of the client which connected, if * included and available from the selected transport. *

    *

    * Can also be determined later using * stream_socket_get_name. *

    * @return resource|false Returns a stream to the accepted socket connection or FALSE on failure. */ function stream_socket_accept($socket, ?float $timeout, &$peer_name) {} /** * Retrieve the name of the local or remote sockets * @link https://php.net/manual/en/function.stream-socket-get-name.php * @param resource $socket

    * The socket to get the name of. *

    * @param bool $remote

    * If set to true the remote socket name will be returned, if set * to false the local socket name will be returned. *

    * @return string|false The name of the socket or false on error. */ function stream_socket_get_name($socket, bool $remote): string|false {} /** * Receives data from a socket, connected or not * @link https://php.net/manual/en/function.stream-socket-recvfrom.php * @param resource $socket

    * The remote socket. *

    * @param int $length

    * The number of bytes to receive from the socket. *

    * @param int $flags

    * The value of flags can be any combination * of the following: *

    * Possible values for flags * * * * * * * * *
    STREAM_OOB * Process OOB (out-of-band) data. *
    STREAM_PEEK * Retrieve data from the socket, but do not consume the buffer. * Subsequent calls to fread or * stream_socket_recvfrom will see * the same data. *
    *

    * @param string &$address [optional]

    * If address is provided it will be populated with * the address of the remote socket. *

    * @return string|false the read data, as a string, or false on error */ function stream_socket_recvfrom($socket, int $length, int $flags = 0, &$address): string|false {} /** * Sends a message to a socket, whether it is connected or not * @link https://php.net/manual/en/function.stream-socket-sendto.php * @param resource $socket

    * The socket to send data to. *

    * @param string $data

    * The data to be sent. *

    * @param int $flags

    * The value of flags can be any combination * of the following: *

    * possible values for flags * * * * *
    STREAM_OOB * Process OOB (out-of-band) data. *
    *

    * @param string $address

    * The address specified when the socket stream was created will be used * unless an alternate address is specified in address. *

    *

    * If specified, it must be in dotted quad (or [ipv6]) format. *

    * @return int|false a result code, as an integer. */ function stream_socket_sendto($socket, string $data, int $flags = 0, string $address = ''): int|false {} /** * Turns encryption on/off on an already connected socket * @link https://php.net/manual/en/function.stream-socket-enable-crypto.php * @param resource $stream

    * The stream resource. *

    * @param bool $enable

    * Enable/disable cryptography on the stream. *

    * @param int|null $crypto_method [optional]

    * Setup encryption on the stream. * Valid methods are:
    * STREAM_CRYPTO_METHOD_SSLv2_CLIENT

    * @param resource $session_stream [optional]

    * Seed the stream with settings from session_stream. *

    * @return bool|int true on success, false if negotiation has failed or * 0 if there isn't enough data and you should try again * (only for non-blocking sockets). */ function stream_socket_enable_crypto($stream, bool $enable, ?int $crypto_method, $session_stream): int|bool {} /** * Shutdown a full-duplex connection * @link https://php.net/manual/en/function.stream-socket-shutdown.php * @param resource $stream

    * An open stream (opened with stream_socket_client, * for example) *

    * @param int $mode

    * One of the following constants: STREAM_SHUT_RD * (disable further receptions), STREAM_SHUT_WR * (disable further transmissions) or * STREAM_SHUT_RDWR (disable further receptions and * transmissions). *

    * @return bool true on success or false on failure. * @since 5.2.1 */ function stream_socket_shutdown($stream, int $mode): bool {} /** * Creates a pair of connected, indistinguishable socket streams * @link https://php.net/manual/en/function.stream-socket-pair.php * @param int $domain

    * The protocol family to be used: STREAM_PF_INET, * STREAM_PF_INET6 or * STREAM_PF_UNIX *

    * @param int $type

    * The type of communication to be used: * STREAM_SOCK_DGRAM, * STREAM_SOCK_RAW, * STREAM_SOCK_RDM, * STREAM_SOCK_SEQPACKET or * STREAM_SOCK_STREAM *

    * @param int $protocol

    * The protocol to be used: STREAM_IPPROTO_ICMP, * STREAM_IPPROTO_IP, * STREAM_IPPROTO_RAW, * STREAM_IPPROTO_TCP or * STREAM_IPPROTO_UDP *

    * @return array|false an array with the two socket resources on success, or * false on failure. */ function stream_socket_pair(int $domain, int $type, int $protocol): array|false {} /** * Copies data from one stream to another * @link https://php.net/manual/en/function.stream-copy-to-stream.php * @param resource $from

    * The source stream *

    * @param resource $to

    * The destination stream *

    * @param int|null $length [optional]

    * Maximum bytes to copy *

    * @param int $offset

    * The offset where to start to copy data *

    * @return int|false the total count of bytes copied, or false on failure. */ function stream_copy_to_stream($from, $to, ?int $length, int $offset = 0): int|false {} /** * Reads remainder of a stream into a string * @link https://php.net/manual/en/function.stream-get-contents.php * @param resource $stream

    * A stream resource (e.g. returned from fopen) *

    * @param int|null $length

    * The maximum bytes to read. Defaults to -1 (read all the remaining * buffer). *

    * @param int $offset [optional]

    * Seek to the specified offset before reading. *

    * @return string|false a string or false on failure. */ function stream_get_contents($stream, ?int $length = null, int $offset = -1): string|false {} /** * Tells whether the stream supports locking. * @link https://php.net/manual/en/function.stream-supports-lock.php * @param resource $stream

    * The stream to check. *

    * @return bool true on success or false on failure. */ function stream_supports_lock($stream): bool {} /** * Gets line from file pointer and parse for CSV fields * @link https://php.net/manual/en/function.fgetcsv.php * @param resource $stream

    * A valid file pointer to a file successfully opened by * fopen, popen, or * fsockopen. *

    * @param int|null $length

    * Must be greater than the longest line (in characters) to be found in * the CSV file (allowing for trailing line-end characters). It became * optional in PHP 5. Omitting this parameter (or setting it to 0 in PHP * 5.0.4 and later) the maximum line length is not limited, which is * slightly slower. *

    * @param string $separator [optional]

    * Set the field delimiter (one character only). *

    * @param string $enclosure [optional]

    * Set the field enclosure character (one character only). *

    * @param string $escape [optional]

    * Set the escape character (one character only). Defaults as a backslash. *

    * @return array|false|null an indexed array containing the fields read. *

    * A blank line in a CSV file will be returned as an array * comprising a single null field, and will not be treated * as an error. *

    *

    * fgetcsv returns null if an invalid * handle is supplied or false on other errors, * including end of file. *

    */ #[LanguageLevelTypeAware(['8.0' => 'array|false'], default: 'array|false|null')] function fgetcsv($stream, ?int $length = null, string $separator = ',', string $enclosure = '"', string $escape = '\\') {} /** * Format line as CSV and write to file pointer * @link https://php.net/manual/en/function.fputcsv.php * @param resource $stream The file pointer must be valid, and must point to a file successfully opened by fopen() or fsockopen() (and not yet closed by fclose()). * @param array $fields

    * An array of values. *

    * @param string $separator [optional]

    * The optional delimiter parameter sets the field * delimiter (one character only). *

    * @param string $enclosure [optional]

    * The optional enclosure parameter sets the field * enclosure (one character only). *

    * @param string $escape [optional]

    * The optional escape_char parameter sets the escape character (one character only). *

    * @return int|false the length of the written string or false on failure. */ function fputcsv( $stream, array $fields, string $separator = ",", string $enclosure = '"', #[PhpStormStubsElementAvailable(from: '7.0')] string $escape = "\\", #[PhpStormStubsElementAvailable('8.1')] string $eol = PHP_EOL ): int|false {} /** * Portable advisory file locking * @link https://php.net/manual/en/function.flock.php * @param resource $stream

    * An open file pointer. *

    * @param int $operation

    * operation is one of the following: * LOCK_SH to acquire a shared lock (reader).

    * @param int &$would_block [optional]

    * The optional third argument is set to 1 if the lock would block * (EWOULDBLOCK errno condition). *

    * @return bool true on success or false on failure. */ function flock($stream, int $operation, &$would_block): bool {} /** * Extracts all meta tag content attributes from a file and returns an array * @link https://php.net/manual/en/function.get-meta-tags.php * @param string $filename

    * The path to the HTML file, as a string. This can be a local file or an * URL. *

    *

    * What get_meta_tags parses *

    *
     * 
     * 
     * 
     * 
     *  
     * 
    *

    * (pay attention to line endings - PHP uses a native function to * parse the input, so a Mac file won't work on Unix). *

    * @param bool $use_include_path [optional]

    * Setting use_include_path to true will result * in PHP trying to open the file along the standard include path as per * the include_path directive. * This is used for local files, not URLs. *

    * @return array|false an array with all the parsed meta tags. *

    * The value of the name property becomes the key, the value of the content * property becomes the value of the returned array, so you can easily use * standard array functions to traverse it or access single values. * Special characters in the value of the name property are substituted with * '_', the rest is converted to lower case. If two meta tags have the same * name, only the last one is returned. *

    */ #[Pure(true)] function get_meta_tags(string $filename, bool $use_include_path = false): array|false {} /** * Sets write file buffering on the given stream * @link https://php.net/manual/en/function.stream-set-write-buffer.php * @param resource $stream

    * The file pointer. *

    * @param int $size

    * The number of bytes to buffer. If buffer * is 0 then write operations are unbuffered. This ensures that all writes * with fwrite are completed before other processes are * allowed to write to that output stream. *

    * @return int 0 on success, or EOF if the request cannot be honored. * @see stream_set_read_buffer() */ function stream_set_write_buffer($stream, int $size): int {} /** * Sets read file buffering on the given stream * @link https://php.net/manual/en/function.stream-set-read-buffer.php * @param resource $stream

    * The file pointer. *

    * @param int $size

    * The number of bytes to buffer. If buffer * is 0 then write operations are unbuffered. This ensures that all writes * with fwrite are completed before other processes are * allowed to write to that output stream. *

    * @return int 0 on success, or EOF if the request cannot be honored. * @see stream_set_write_buffer() */ function stream_set_read_buffer($stream, int $size): int {} /** * Alias: * {@see stream_set_write_buffer} *

    Sets the buffering for write operations on the given stream to buffer bytes. * Output using fwrite() is normally buffered at 8K. * This means that if there are two processes wanting to write to the same output stream (a file), * each is paused after 8K of data to allow the other to write. *

    * @link https://php.net/manual/en/function.set-file-buffer.php * @param resource $stream The file pointer. * @param int $size The number of bytes to buffer. If buffer is 0 then write operations are unbuffered. * This ensures that all writes with fwrite() are completed before other processes are allowed to write to that output stream. * @return int */ function set_file_buffer($stream, int $size): int {} /** * Alias: * {@see stream_set_blocking} *

    Sets blocking or non-blocking mode on a stream. * This function works for any stream that supports non-blocking mode (currently, regular files and socket streams) *

    * @link https://php.net/manual/en/function.set-socket-blocking.php * @param resource $socket * @param bool $mode If mode is FALSE, the given stream will be switched to non-blocking mode, and if TRUE, it will be switched to blocking mode. * This affects calls like fgets() and fread() that read from the stream. * In non-blocking mode an fgets() call will always return right away while in blocking mode it will wait for data to become available on the stream. * @return bool Returns TRUE on success or FALSE on failure. * @removed 7.0 * @see stream_set_blocking() */ #[Deprecated(replacement: "stream_set_blocking(%parametersList%)", since: 5.3)] function set_socket_blocking($socket, bool $mode): bool {} /** * Set blocking/non-blocking mode on a stream * @link https://php.net/manual/en/function.stream-set-blocking.php * @param resource $stream

    * The stream. *

    * @param bool $enable

    * If mode is FALSE, the given stream * will be switched to non-blocking mode, and if TRUE, it * will be switched to blocking mode. This affects calls like * fgets and fread * that read from the stream. In non-blocking mode an * fgets call will always return right away * while in blocking mode it will wait for data to become available * on the stream. *

    * @return bool true on success or false on failure. */ function stream_set_blocking($stream, bool $enable): bool {} /** * Alias: * {@see stream_set_blocking} * @link https://php.net/manual/en/function.socket-set-blocking.php * @param resource $stream

    * The stream. *

    * @param bool $enable

    * If mode is FALSE, the given stream * will be switched to non-blocking mode, and if TRUE, it * will be switched to blocking mode. This affects calls like * fgets and fread * that read from the stream. In non-blocking mode an * fgets call will always return right away * while in blocking mode it will wait for data to become available * on the stream. *

    * @return bool true on success or false on failure. */ function socket_set_blocking($stream, bool $enable): bool {} /** * Retrieves header/meta data from streams/file pointers * @link https://php.net/manual/en/function.stream-get-meta-data.php * @param resource $stream

    * The stream can be any stream created by fopen, * fsockopen and pfsockopen. *

    * @return array The result array contains the following items: *

    * timed_out (bool) - true if the stream * timed out while waiting for data on the last call to * fread or fgets. *

    *

    * blocked (bool) - true if the stream is * in blocking IO mode. See stream_set_blocking. *

    *

    * eof (bool) - true if the stream has reached * end-of-file. Note that for socket streams this member can be true * even when unread_bytes is non-zero. To * determine if there is more data to be read, use * feof instead of reading this item. *

    *

    * unread_bytes (int) - the number of bytes * currently contained in the PHP's own internal buffer. *

    * You shouldn't use this value in a script. *

    * stream_type (string) - a label describing * the underlying implementation of the stream. *

    *

    * wrapper_type (string) - a label describing * the protocol wrapper implementation layered over the stream. * See for more information about wrappers. *

    *

    * wrapper_data (mixed) - wrapper specific * data attached to this stream. See for * more information about wrappers and their wrapper data. *

    *

    * filters (array) - and array containing * the names of any filters that have been stacked onto this stream. * Documentation on filters can be found in the * Filters appendix. *

    *

    * mode (string) - the type of access required for * this stream (see Table 1 of the fopen() reference) *

    *

    * seekable (bool) - whether the current stream can * be seeked. *

    *

    * uri (string) - the URI/filename associated with this * stream. *

    */ #[ArrayShape(["timed_out" => "bool", "blocked" => "bool", "eof" => "bool", "unread_bytes" => "int", "stream_type" => "string", "wrapper_type" => "string", "wrapper_data" => "mixed", "mode" => "string", "seekable" => "bool", "uri" => "string", "crypto" => "array", "mediatype" => "string"])] function stream_get_meta_data($stream): array {} /** * Gets line from stream resource up to a given delimiter * @link https://php.net/manual/en/function.stream-get-line.php * @param resource $stream

    * A valid file handle. *

    * @param int $length

    * The number of bytes to read from the handle. *

    * @param string $ending

    * An optional string delimiter. *

    * @return string|false a string of up to length bytes read from the file * pointed to by handle. *

    * If an error occurs, returns false. *

    */ function stream_get_line($stream, int $length, string $ending = ''): string|false {} /** * Register a URL wrapper implemented as a PHP class * @link https://php.net/manual/en/function.stream-wrapper-register.php * @param string $protocol

    * The wrapper name to be registered. *

    * @param string $class

    * The classname which implements the protocol. *

    * @param int $flags

    * Should be set to STREAM_IS_URL if * protocol is a URL protocol. Default is 0, local * stream. *

    * @return bool true on success or false on failure. *

    * stream_wrapper_register will return false if the * protocol already has a handler. *

    */ function stream_wrapper_register(string $protocol, string $class, int $flags = 0): bool {} /** * Alias: * {@see stream_wrapper_register} *

    Register a URL wrapper implemented as a PHP class

    * @link https://php.net/manual/en/function.stream-register-wrapper.php * @param string $protocol

    * The wrapper name to be registered. *

    * @param string $class

    * The classname which implements the protocol. *

    * @param int $flags [optional]

    * Should be set to STREAM_IS_URL if * protocol is a URL protocol. Default is 0, local * stream. *

    * @return bool true on success or false on failure. *

    * stream_wrapper_register will return false if the * protocol already has a handler. *

    */ function stream_register_wrapper(string $protocol, string $class, int $flags = 0): bool {} /** * Resolve filename against the include path according to the same rules as fopen()/include(). * @link https://php.net/manual/en/function.stream-resolve-include-path.php * @param string $filename The filename to resolve. * @return string|false containing the resolved absolute filename, or FALSE on failure. * @since 5.3.2 */ function stream_resolve_include_path(string $filename): string|false {} /** * Unregister a URL wrapper * @link https://php.net/manual/en/function.stream-wrapper-unregister.php * @param string $protocol

    *

    * @return bool true on success or false on failure. */ function stream_wrapper_unregister(string $protocol): bool {} /** * Restores a previously unregistered built-in wrapper * @link https://php.net/manual/en/function.stream-wrapper-restore.php * @param string $protocol

    *

    * @return bool true on success or false on failure. */ function stream_wrapper_restore(string $protocol): bool {} /** * Retrieve list of registered streams * @link https://php.net/manual/en/function.stream-get-wrappers.php * @return list an indexed array containing the name of all stream wrappers * available on the running system. */ #[Pure(true)] function stream_get_wrappers(): array {} /** * Retrieve list of registered socket transports * @link https://php.net/manual/en/function.stream-get-transports.php * @return list an indexed array of socket transports names. */ #[Pure(true)] function stream_get_transports(): array {} /** * Checks if a stream is a local stream * @link https://php.net/manual/en/function.stream-is-local.php * @param mixed $stream

    * The stream resource or URL to check. *

    * @return bool true on success or false on failure. * @since 5.2.4 */ #[Pure] function stream_is_local($stream): bool {} /** * Fetches all the headers sent by the server in response to an HTTP request * @link https://php.net/manual/en/function.get-headers.php * @param string $url

    * The target URL. *

    * @param bool $associative [optional]

    * If the optional format parameter is set to true, * get_headers parses the response and sets the * array's keys. *

    * @param resource $context [optional] * @return array|false an indexed or associative array with the headers, or false on * failure. */ #[Pure(true)] function get_headers( string $url, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: 'int')] $associative = false, #[PhpStormStubsElementAvailable(from: '7.1')] $context = null ): array|false {} /** * Set timeout period on a stream * @link https://php.net/manual/en/function.stream-set-timeout.php * @param resource $stream

    * The target stream. *

    * @param int $seconds

    * The seconds part of the timeout to be set. *

    * @param int $microseconds

    * The microseconds part of the timeout to be set. *

    * @return bool true on success or false on failure. */ function stream_set_timeout( $stream, int $seconds, #[PhpStormStubsElementAvailable(from: '5.3', to: '5.6')] int $microseconds, #[PhpStormStubsElementAvailable(from: '7.0')] int $microseconds = 0 ): bool {} /** * Alias: * {@see stream_set_timeout} * Set timeout period on a stream * @link https://php.net/manual/en/function.socket-set-timeout.php * @param resource $stream

    * The target stream. *

    * @param int $seconds

    * The seconds part of the timeout to be set. *

    * @param int $microseconds

    * The microseconds part of the timeout to be set. *

    * @return bool true on success or false on failure. */ function socket_set_timeout( $stream, int $seconds, #[PhpStormStubsElementAvailable(from: '5.3', to: '5.6')] int $microseconds, #[PhpStormStubsElementAvailable(from: '7.0')] int $microseconds = 0 ): bool {} /** * Alias: * {@see stream_get_meta_data} * Retrieves header/meta data from streams/file pointers * @link https://php.net/manual/en/function.socket-get-status.php * @param resource $stream

    * The stream can be any stream created by fopen, * fsockopen and pfsockopen. *

    * @return array The result array contains the following items: *

    * timed_out (bool) - true if the stream * timed out while waiting for data on the last call to * fread or fgets. *

    *

    * blocked (bool) - true if the stream is * in blocking IO mode. See stream_set_blocking. *

    *

    * eof (bool) - true if the stream has reached * end-of-file. Note that for socket streams this member can be true * even when unread_bytes is non-zero. To * determine if there is more data to be read, use * feof instead of reading this item. *

    *

    * unread_bytes (int) - the number of bytes * currently contained in the PHP's own internal buffer. *

    * You shouldn't use this value in a script. *

    * stream_type (string) - a label describing * the underlying implementation of the stream. *

    *

    * wrapper_type (string) - a label describing * the protocol wrapper implementation layered over the stream. * See for more information about wrappers. *

    *

    * wrapper_data (mixed) - wrapper specific * data attached to this stream. See for * more information about wrappers and their wrapper data. *

    *

    * filters (array) - and array containing * the names of any filters that have been stacked onto this stream. * Documentation on filters can be found in the * Filters appendix. *

    *

    * mode (string) - the type of access required for * this stream (see Table 1 of the fopen() reference) *

    *

    * seekable (bool) - whether the current stream can * be seeked. *

    *

    * uri (string) - the URI/filename associated with this * stream. *

    */ function socket_get_status($stream): array {} /** * Returns canonicalized absolute pathname * @link https://php.net/manual/en/function.realpath.php * @param string $path

    * The path being checked. *

    * @return string|false the canonicalized absolute pathname on success. The resulting path * will have no symbolic link, '/./' or '/../' components. *

    * realpath returns false on failure, e.g. if * the file does not exist. *

    */ #[Pure(true)] function realpath(string $path): string|false {} /** * Match filename against a pattern * @link https://php.net/manual/en/function.fnmatch.php * @param string $pattern

    * The shell wildcard pattern. *

    * @param string $filename

    * The tested string. This function is especially useful for filenames, * but may also be used on regular strings. *

    *

    * The average user may be used to shell patterns or at least in their * simplest form to '?' and '*' * wildcards so using fnmatch instead of * preg_match for * frontend search expression input may be way more convenient for * non-programming users. *

    * @param int $flags

    * The value of flags can be any combination of * the following flags, joined with the * binary OR (|) operator. *

    * A list of possible flags for fnmatch * * * * * * * * * * * * * * * * * * * * *
    FlagDescription
    FNM_NOESCAPE * Disable backslash escaping. *
    FNM_PATHNAME * Slash in string only matches slash in the given pattern. *
    FNM_PERIOD * Leading period in string must be exactly matched by period in the given pattern. *
    FNM_CASEFOLD * Caseless match. Part of the GNU extension. *
    *

    * @return bool true if there is a match, false otherwise. */ #[Pure(true)] function fnmatch(string $pattern, string $filename, int $flags = 0): bool {} * item may be an integer value of the element or the * constant name of the element. The following is a list of constant names * for item that may be used and their description. * Some of these constants may not be defined or hold no value for certain * locales.

    * nl_langinfo Constants * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    ConstantDescription
    LC_TIME Category Constants
    ABDAY_(1-7)Abbreviated name of n-th day of the week.
    DAY_(1-7)Name of the n-th day of the week (DAY_1 = Sunday).
    ABMON_(1-12)Abbreviated name of the n-th month of the year.
    MON_(1-12)Name of the n-th month of the year.
    AM_STRString for Ante meridian.
    PM_STRString for Post meridian.
    D_T_FMTString that can be used as the format string for strftime to represent time and date.
    D_FMTString that can be used as the format string for strftime to represent date.
    T_FMTString that can be used as the format string for strftime to represent time.
    T_FMT_AMPMString that can be used as the format string for strftime to represent time in 12-hour format with ante/post meridian.
    ERAAlternate era.
    ERA_YEARYear in alternate era format.
    ERA_D_T_FMTDate and time in alternate era format (string can be used in strftime).
    ERA_D_FMTDate in alternate era format (string can be used in strftime).
    ERA_T_FMTTime in alternate era format (string can be used in strftime).
    LC_MONETARY Category Constants
    INT_CURR_SYMBOLInternational currency symbol.
    CURRENCY_SYMBOLLocal currency symbol.
    CRNCYSTRSame value as CURRENCY_SYMBOL.
    MON_DECIMAL_POINTDecimal point character.
    MON_THOUSANDS_SEPThousands separator (groups of three digits).
    MON_GROUPINGLike "grouping" element.
    POSITIVE_SIGNSign for positive values.
    NEGATIVE_SIGNSign for negative values.
    INT_FRAC_DIGITSInternational fractional digits.
    FRAC_DIGITSLocal fractional digits.
    P_CS_PRECEDESReturns 1 if CURRENCY_SYMBOL precedes a positive value.
    P_SEP_BY_SPACEReturns 1 if a space separates CURRENCY_SYMBOL from a positive value.
    N_CS_PRECEDESReturns 1 if CURRENCY_SYMBOL precedes a negative value.
    N_SEP_BY_SPACEReturns 1 if a space separates CURRENCY_SYMBOL from a negative value.
    P_SIGN_POSNReturns 0 if parentheses surround the quantity and CURRENCY_SYMBOL.
    * @return string|false the element as a string, or false if item * is not valid. */ #[Pure(true)] function nl_langinfo(int $item): string|false {} /** * Calculate the soundex key of a string * @link https://php.net/manual/en/function.soundex.php * @param string $string

    * The input string. *

    * @return string the soundex key as a string. */ #[Pure] function soundex(string $string): string {} /** * Calculate Levenshtein distance between two strings * @link https://php.net/manual/en/function.levenshtein.php * Note: In its simplest form the function will take only the two strings * as parameter and will calculate just the number of insert, replace and * delete operations needed to transform str1 into str2. * Note: A second variant will take three additional parameters that define * the cost of insert, replace and delete operations. This is more general * and adaptive than variant one, but not as efficient. * @param string $string1

    * One of the strings being evaluated for Levenshtein distance. *

    * @param string $string2

    * One of the strings being evaluated for Levenshtein distance. *

    * @param int $insertion_cost [optional]

    * Defines the cost of insertion. *

    * @param int $replacement_cost [optional]

    * Defines the cost of replacement. *

    * @param int $deletion_cost [optional]

    * Defines the cost of deletion. *

    * @return int This function returns the Levenshtein-Distance between the * two argument strings or -1, if one of the argument strings * is longer than the limit of 255 characters. */ function levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1): int {} /** * Generate a single-byte string from a number * @link https://php.net/manual/en/function.chr.php * @param int $codepoint

    * The ascii code. *

    * @return string the specified character. */ #[Pure] function chr(int $codepoint): string {} /** * Convert the first byte of a string to a value between 0 and 255 * @link https://php.net/manual/en/function.ord.php * @param string $character

    * A character. *

    * @return int<0, 255> the ASCII value as an integer. */ #[Pure] function ord(string $character): int {} /** * Parses the string into variables * @link https://php.net/manual/en/function.parse-str.php * @param string $string

    * The input string. *

    * @param array &$result

    * If the second parameter arr is present, * variables are stored in this variable as array elements instead.
    * Since 7.2.0 this parameter is not optional. *

    * @return void */ function parse_str( string $string, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] &$result = [], #[PhpStormStubsElementAvailable(from: '8.0')] &$result ): void {} /** * Parse a CSV string into an array * @link https://php.net/manual/en/function.str-getcsv.php * @param string $string

    * The string to parse. *

    * @param string $separator [optional]

    * Set the field delimiter (one character only). *

    * @param string $enclosure [optional]

    * Set the field enclosure character (one character only). *

    * @param string $escape [optional]

    * Set the escape character (one character only). * Defaults as a backslash (\) *

    * @return array an indexed array containing the fields read. */ #[Pure] function str_getcsv(string $string, string $separator = ",", string $enclosure = '"', string $escape = "\\"): array {} /** * Pad a string to a certain length with another string * @link https://php.net/manual/en/function.str-pad.php * @param string $string

    * The input string. *

    * @param int $length

    * If the value of pad_length is negative, * less than, or equal to the length of the input string, no padding * takes place. *

    * @param string $pad_string [optional]

    * The pad_string may be truncated if the * required number of padding characters can't be evenly divided by the * pad_string's length. *

    * @param int $pad_type [optional]

    * Optional argument pad_type can be * STR_PAD_RIGHT, STR_PAD_LEFT, * or STR_PAD_BOTH. If * pad_type is not specified it is assumed to be * STR_PAD_RIGHT. *

    * @return string the padded string. */ #[Pure] function str_pad(string $string, int $length, string $pad_string = " ", int $pad_type = STR_PAD_RIGHT): string {} /** * Alias: * {@see rtrim} * @param string $string The input string. * @param string $characters [optional] * @return string the modified string. * @link https://php.net/manual/en/function.chop.php * @see rtrim() */ #[Pure] function chop(string $string, string $characters = " \n\r\t\v\0"): string {} /** * Alias: * {@see strstr} * @link https://php.net/manual/en/function.strchr.php * Note: This function is case-sensitive. For case-insensitive searches, use stristr(). * Note: If you only want to determine if a particular needle occurs within haystack, * use the faster and less memory intensive function strpos() instead. * * @param string $haystack The input string. * @param string $needle If needle is not a string, it is converted to an integer and applied as the ordinal value of a character. * @param bool $before_needle [optional] If TRUE, strstr() returns the part of the haystack before the first occurrence of the needle (excluding the needle). * @return string|false Returns the portion of string, or FALSE if needle is not found. */ #[Pure] function strchr(string $haystack, string $needle, bool $before_needle = false): string|false {} /** * Return a formatted string * @link https://php.net/manual/en/function.sprintf.php * @param string $format

    * The format string is composed of zero or more directives: * ordinary characters (excluding %) that are * copied directly to the result, and conversion * specifications, each of which results in fetching its * own parameter. This applies to both sprintf * and printf. *

    *

    * Each conversion specification consists of a percent sign * (%), followed by one or more of these * elements, in order: * An optional sign specifier that forces a sign * (- or +) to be used on a number. By default, only the - sign is used * on a number if it's negative. This specifier forces positive numbers * to have the + sign attached as well, and was added in PHP 4.3.0.

    * @param string|int|float ...$values

    *

    * @return string a string produced according to the formatting string * format. */ #[Pure] function sprintf( string $format, #[PhpStormStubsElementAvailable(from: '5.3', to: '5.6')] $values, mixed ...$values ): string {} /** * Output a formatted string * @link https://php.net/manual/en/function.printf.php * @param string $format

    * See sprintf for a description of * format. *

    * @param string|int|float ...$values [optional]

    *

    * @return int the length of the outputted string. */ function printf(string $format, mixed ...$values): int {} /** * Output a formatted string * @link https://php.net/manual/en/function.vprintf.php * @param string $format

    * See sprintf for a description of * format. *

    * @param array $values

    *

    * @return int the length of the outputted string. */ function vprintf(string $format, array $values): int {} /** * Return a formatted string * @link https://php.net/manual/en/function.vsprintf.php * @param string $format

    * See sprintf for a description of * format. *

    * @param array $values

    *

    * @return string Return array values as a formatted string according to * format (which is described in the documentation * for sprintf). */ #[Pure] function vsprintf(string $format, array $values): string {} /** * Write a formatted string to a stream * @link https://php.net/manual/en/function.fprintf.php * @param resource $stream &fs.file.pointer; * @param string $format

    * See sprintf for a description of * format. *

    * @param mixed ...$values [optional]

    *

    * @return int the length of the string written. */ function fprintf($stream, string $format, mixed ...$values): int {} /** * Write a formatted string to a stream * @link https://php.net/manual/en/function.vfprintf.php * @param resource $stream

    *

    * @param string $format

    * See sprintf for a description of * format. *

    * @param array $values

    *

    * @return int the length of the outputted string. */ function vfprintf($stream, string $format, array $values): int {} /** * Parses input from a string according to a format * @link https://php.net/manual/en/function.sscanf.php * @param string $string

    * The input string being parsed. *

    * @param string $format

    * The interpreted format for str, which is * described in the documentation for sprintf with * following differences: * Function is not locale-aware. * F, g, G and * b are not supported. * D stands for decimal number. * i stands for integer with base detection. * n stands for number of characters processed so far. *

    * @param mixed &...$vars [optional] * @return array|int|null If only * two parameters were passed to this function, the values parsed * will be returned as an array. Otherwise, if optional parameters are passed, * the function will return the number of assigned values. The optional * parameters must be passed by reference. */ function sscanf(string $string, string $format, #[TypeContract(exists: "int|null", notExists: "array|null")] mixed &...$vars): array|int|null {} /** * Parses input from a file according to a format * @link https://php.net/manual/en/function.fscanf.php * @param resource $stream &fs.file.pointer; * @param string $format

    * The specified format as described in the * sprintf documentation. *

    * @param mixed &...$vars [optional] * @return array|int|false|null If only two parameters were passed to this function, the values parsed will be * returned as an array. Otherwise, if optional parameters are passed, the * function will return the number of assigned values. The optional * parameters must be passed by reference. */ function fscanf($stream, string $format, #[TypeContract(exists: "int|false|null", notExists: "array|false|null")] mixed &...$vars): array|int|false|null {} /** * Parse a URL and return its components * @link https://php.net/manual/en/function.parse-url.php * @param string $url

    * The URL to parse. Invalid characters are replaced by * _. *

    * @param int $component [optional]

    * Specify one of PHP_URL_SCHEME, * PHP_URL_HOST, PHP_URL_PORT, * PHP_URL_USER, PHP_URL_PASS, * PHP_URL_PATH, PHP_URL_QUERY * or PHP_URL_FRAGMENT to retrieve just a specific * URL component as a string. *

    * @return array|string|int|null|false On seriously malformed URLs, parse_url() may return FALSE. * If the component parameter is omitted, an associative array is returned. * At least one element will be present within the array. Potential keys within this array are: * scheme - e.g. http * host * port * user * pass * path * query - after the question mark ? * fragment - after the hashmark # *

    *

    * If the component parameter is specified a * string is returned instead of an array. */ #[ArrayShape(["scheme" => "string", "host" => "string", "port" => "int", "user" => "string", "pass" => "string", "query" => "string", "path" => "string", "fragment" => "string"])] #[Pure] function parse_url(string $url, int $component = -1): array|string|int|false|null {} /** * URL-encodes string * @link https://php.net/manual/en/function.urlencode.php * @param string $string

    * The string to be encoded. *

    * @return string a string in which all non-alphanumeric characters except * -_. have been replaced with a percent * (%) sign followed by two hex digits and spaces encoded * as plus (+) signs. It is encoded the same way that the * posted data from a WWW form is encoded, that is the same way as in * application/x-www-form-urlencoded media type. This * differs from the RFC 3986 encoding (see * rawurlencode) in that for historical reasons, spaces * are encoded as plus (+) signs. */ #[Pure] function urlencode(string $string): string {} /** * Decodes URL-encoded string * @link https://php.net/manual/en/function.urldecode.php * @param string $string

    * The string to be decoded. *

    * @return string the decoded string. */ #[Pure] function urldecode(string $string): string {} /** * URL-encode according to RFC 3986 * @link https://php.net/manual/en/function.rawurlencode.php * @param string $string

    * The URL to be encoded. *

    * @return string a string in which all non-alphanumeric characters except * -_. have been replaced with a percent * (%) sign followed by two hex digits. This is the * encoding described in RFC 1738 for * protecting literal characters from being interpreted as special URL * delimiters, and for protecting URLs from being mangled by transmission * media with character conversions (like some email systems). */ #[Pure] function rawurlencode(string $string): string {} /** * Decode URL-encoded strings * @link https://php.net/manual/en/function.rawurldecode.php * @param string $string

    * The URL to be decoded. *

    * @return string the decoded URL, as a string. */ #[Pure] function rawurldecode(string $string): string {} /** * Generate URL-encoded query string * @link https://php.net/manual/en/function.http-build-query.php * @param object|array $data

    * May be an array or object containing properties. *

    *

    * If query_data is an array, it may be a simple one-dimensional structure, * or an array of arrays (which in turn may contain other arrays). *

    *

    * If query_data is an object, then only public properties will be incorporated into the result. *

    * @param string $numeric_prefix [optional]

    * If numeric indices are used in the base array and this parameter is * provided, it will be prepended to the numeric index for elements in * the base array only. *

    *

    * This is meant to allow for legal variable names when the data is * decoded by PHP or another CGI application later on. *

    * @param string|null $arg_separator

    * arg_separator.output * is used to separate arguments, unless this parameter is specified, * and is then used. *

    * @param int $encoding_type By default, PHP_QUERY_RFC1738. *

    If enc_type is PHP_QUERY_RFC1738, then encoding is performed per » RFC 1738 and the application/x-www-form-urlencoded media type, * which implies that spaces are encoded as plus (+) signs. *

    If enc_type is PHP_QUERY_RFC3986, then encoding is performed according to » RFC 3986, and spaces will be percent encoded (%20). * @return string a URL-encoded string. */ #[Pure] function http_build_query(object|array $data, string $numeric_prefix = "", ?string $arg_separator = null, int $encoding_type = PHP_QUERY_RFC1738): string {} /** * Returns the target of a symbolic link * @link https://php.net/manual/en/function.readlink.php * @param string $path

    * The symbolic link path. *

    * @return string|false the contents of the symbolic link path or false on error. */ #[Pure(true)] function readlink(string $path): string|false {} /** * Gets information about a link * @link https://php.net/manual/en/function.linkinfo.php * @param string $path

    * Path to the link. *

    * @return int|false linkinfo returns the st_dev field * of the Unix C stat structure returned by the lstat * system call. Returns 0 or false in case of error. */ #[Pure(true)] function linkinfo(string $path): int|false {} /** * Creates a symbolic link * @link https://php.net/manual/en/function.symlink.php * @param string $target

    * Target of the link. *

    * @param string $link

    * The link name. *

    * @return bool true on success or false on failure. */ function symlink(string $target, string $link): bool {} /** * Create a hard link * @link https://php.net/manual/en/function.link.php * @param string $target Target of the link. * @param string $link The link name. * @return bool true on success or false on failure. */ function link(string $target, string $link): bool {} /** * Deletes a file * @link https://php.net/manual/en/function.unlink.php * @param string $filename

    * Path to the file. *

    * @param resource $context [optional] * @return bool true on success or false on failure. */ function unlink(string $filename, $context): bool {} /** * Execute an external program * @link https://php.net/manual/en/function.exec.php * @param string $command

    * The command that will be executed. *

    * @param array &$output [optional]

    * If the output argument is present, then the * specified array will be filled with every line of output from the * command. Trailing whitespace, such as \n, is not * included in this array. Note that if the array already contains some * elements, exec will append to the end of the array. * If you do not want the function to append elements, call * unset on the array before passing it to * exec. *

    * @param int &$result_code [optional]

    * If the result_code argument is present * along with the output argument, then the * return status of the executed command will be written to this * variable. *

    * @return string|false The last line from the result of the command. If you need to execute a * command and have all the data from the command passed directly back without * any interference, use the passthru function. *

    *

    * To get the output of the executed command, be sure to set and use the * output parameter. */ function exec(string $command, &$output, &$result_code): string|false {} /** * Execute an external program and display the output * @link https://php.net/manual/en/function.system.php * @param string $command

    * The command that will be executed. *

    * @param int &$result_code [optional]

    * If the result_code argument is present, then the * return status of the executed command will be written to this * variable. *

    * @return string|false the last line of the command output on success, and false * on failure. */ function system(string $command, &$result_code): string|false {} /** * Escape shell metacharacters * @link https://php.net/manual/en/function.escapeshellcmd.php * @param string $command

    * The command that will be escaped. *

    * @return string The escaped string. */ #[Pure] function escapeshellcmd(string $command): string {} /** * Escape a string to be used as a shell argument * @link https://php.net/manual/en/function.escapeshellarg.php * @param string $arg

    * The argument that will be escaped. *

    * @return string The escaped string. */ #[Pure] function escapeshellarg(string $arg): string {} /** * Execute an external program and display raw output * @link https://php.net/manual/en/function.passthru.php * @param string $command

    * The command that will be executed. *

    * @param int &$result_code [optional]

    * If the result_code argument is present, the * return status of the Unix command will be placed here. *

    * @return bool|null null on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'null|false'], default: 'null|bool')] function passthru(string $command, &$result_code): ?bool {} /** * Execute command via shell and return the complete output as a string * @link https://php.net/manual/en/function.shell-exec.php * @param string $command

    * The command that will be executed. *

    * @return string|false|null The output from the executed command or NULL if an error occurred or the command produces no output. */ function shell_exec(string $command): string|false|null {} /** * Execute a command and open file pointers for input/output * @link https://php.net/manual/en/function.proc-open.php * @param array|string $command

    * Execute a command and open file pointers for input/output *

    *

    * As of PHP 7.4.0, cmd may be passed as array of command parameters. * In this case the process will be opened directly * (without going through a shell) and PHP will take care of any * necessary argument escaping. *

    * @param array $descriptor_spec

    * An indexed array where the key represents the descriptor number and the * value represents how PHP will pass that descriptor to the child * process. 0 is stdin, 1 is stdout, while 2 is stderr. *

    *

    * Each element can be: * An array describing the pipe to pass to the process. The first * element is the descriptor type and the second element is an option for * the given type. Valid types are pipe (the second * element is either r to pass the read end of the pipe * to the process, or w to pass the write end) and * file (the second element is a filename). * A stream resource representing a real file descriptor (e.g. opened file, * a socket, STDIN). *

    *

    * The file descriptor numbers are not limited to 0, 1 and 2 - you may * specify any valid file descriptor number and it will be passed to the * child process. This allows your script to interoperate with other * scripts that run as "co-processes". In particular, this is useful for * passing passphrases to programs like PGP, GPG and openssl in a more * secure manner. It is also useful for reading status information * provided by those programs on auxiliary file descriptors. *

    * @param array &$pipes

    * Will be set to an indexed array of file pointers that correspond to * PHP's end of any pipes that are created. *

    * @param string|null $cwd [optional]

    * The initial working dir for the command. This must be an * absolute directory path, or null * if you want to use the default value (the working dir of the current * PHP process) *

    * @param array|null $env_vars [optional]

    * An array with the environment variables for the command that will be * run, or null to use the same environment as the current PHP process *

    * @param array|null $options [optional]

    * Allows you to specify additional options. Currently supported options * include: * suppress_errors (windows only): suppresses errors generated by this * function when it's set to TRUE * generated by this function when it's set to true * bypass_shell (windows only): bypass cmd.exe shell when set to TRUE * context: stream context used when opening files * (created with stream_context_create) * blocking_pipes: (windows only): force blocking pipes when set to TRUE * create_process_group (windows only): allow the child process to handle * CTRL events when set to TRUE * create_new_console (windows only): the new process has a new console, * instead of inheriting its parent's console *

    * @return resource|false a resource representing the process, which should be freed using * proc_close when you are finished with it. On failure * returns false. */ function proc_open(array|string $command, array $descriptor_spec, &$pipes, ?string $cwd, ?array $env_vars, ?array $options) {} /** * Close a process opened by {@see proc_open} and return the exit code of that process * @link https://php.net/manual/en/function.proc-close.php * @param resource $process

    * The proc_open resource that will * be closed. *

    * @return int the termination status of the process that was run. */ function proc_close($process): int {} /** * Kills a process opened by proc_open * @link https://php.net/manual/en/function.proc-terminate.php * @param resource $process

    * The proc_open resource that will * be closed. *

    * @param int $signal [optional]

    * This optional parameter is only useful on POSIX * operating systems; you may specify a signal to send to the process * using the kill(2) system call. The default is * SIGTERM. *

    * @return bool the termination status of the process that was run. */ function proc_terminate($process, int $signal = 15): bool {} /** * Get information about a process opened by {@see proc_open} * @link https://php.net/manual/en/function.proc-get-status.php * @param resource $process

    * The proc_open resource that will * be evaluated. *

    * @return array|false An array of collected information on success, and false * on failure. The returned array contains the following elements: *

    *

    * elementtypedescription * * command * string * * The command string that was passed to proc_open. * * * * pid * int * process id * * * running * bool * * true if the process is still running, false if it has * terminated. * * * * signaled * bool * * true if the child process has been terminated by * an uncaught signal. Always set to false on Windows. * * * * stopped * bool * * true if the child process has been stopped by a * signal. Always set to false on Windows. * * * * exitcode * int * * The exit code returned by the process (which is only * meaningful if running is false). * Only first call of this function return real value, next calls return * -1. * * * * termsig * int * * The number of the signal that caused the child process to terminate * its execution (only meaningful if signaled is true). * * * * stopsig * int * * The number of the signal that caused the child process to stop its * execution (only meaningful if stopped is true). * * */ #[ArrayShape(["command" => "string", "pid" => "int", "running" => "bool", "signaled" => "bool", "stopped" => "bool", "exitcode" => "int", "termsig" => "int", "stopsig" => "int"])] #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] function proc_get_status($process) {} /** * Change the priority of the current process.
    * Since 7.2.0 supported on Windows platforms. * @link https://php.net/manual/en/function.proc-nice.php * @param int $priority

    * The increment value of the priority change. *

    * @return bool true on success or false on failure. * If an error occurs, like the user lacks permission to change the priority, * an error of level E_WARNING is also generated. */ function proc_nice(int $priority): bool {} /** * Get port number associated with an Internet service and protocol * @link https://php.net/manual/en/function.getservbyname.php * @param string $service

    * The Internet service name, as a string. *

    * @param string $protocol

    * protocol is either "tcp" * or "udp" (in lowercase). *

    * @return int|false the port number, or false if service or * protocol is not found. */ #[Pure] function getservbyname(string $service, string $protocol): int|false {} /** * Get Internet service which corresponds to port and protocol * @link https://php.net/manual/en/function.getservbyport.php * @param int $port

    * The port number. *

    * @param string $protocol

    * protocol is either "tcp" * or "udp" (in lowercase). *

    * @return string|false the Internet service name as a string. */ #[Pure] function getservbyport(int $port, string $protocol): string|false {} /** * Get protocol number associated with protocol name * @link https://php.net/manual/en/function.getprotobyname.php * @param string $protocol

    * The protocol name. *

    * @return int|false the protocol number or -1 if the protocol is not found. */ #[Pure] function getprotobyname(string $protocol): int|false {} /** * Get protocol name associated with protocol number * @link https://php.net/manual/en/function.getprotobynumber.php * @param int $protocol

    * The protocol number. *

    * @return string|false the protocol name as a string. */ #[Pure] function getprotobynumber(int $protocol): string|false {} /** * Gets PHP script owner's UID * @link https://php.net/manual/en/function.getmyuid.php * @return int|false the user ID of the current script, or false on error. */ #[Pure] function getmyuid(): int|false {} /** * Get PHP script owner's GID * @link https://php.net/manual/en/function.getmygid.php * @return int|false the group ID of the current script, or false on error. */ #[Pure] function getmygid(): int|false {} /** * Gets PHP's process ID * @link https://php.net/manual/en/function.getmypid.php * @return int|false the current PHP process ID, or false on error. */ #[Pure] function getmypid(): int|false {} /** * Gets the inode of the current script * @link https://php.net/manual/en/function.getmyinode.php * @return int|false the current script's inode as an integer, or false on error. */ #[Pure] function getmyinode(): int|false {} * The array in which elements are replaced. *

    * @param array ...$replacements

    * The array from which elements will be extracted. *

    * @return array or null if an error occurs. */ #[Pure] function array_replace( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] $replacements, array ...$replacements ): array {} /** * Replaces elements from passed arrays into the first array recursively * @link https://php.net/manual/en/function.array-replace-recursive.php * @param array $array

    * The array in which elements are replaced. *

    * @param array ...$replacements

    * The array from which elements will be extracted. *

    * @return array an array, or null if an error occurs. */ #[Pure] function array_replace_recursive( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] $replacements, array ...$replacements ): array {} /** * Return all the keys or a subset of the keys of an array * @link https://php.net/manual/en/function.array-keys.php * @param array $array

    * An array containing keys to return. *

    * @param mixed $filter_value [optional]

    * If specified, then only keys containing these values are returned. *

    * @param bool $strict [optional]

    * Determines if strict comparison (===) should be used during the search. *

    * @return int[]|string[] an array of all the keys in input. */ #[Pure] function array_keys(array $array, mixed $filter_value, bool $strict = false): array {} /** * Return all the values of an array * @link https://php.net/manual/en/function.array-values.php * @param array $array

    * The array. *

    * @return array an indexed array of values. * @meta */ #[Pure] function array_values(array $array): array {} /** * Counts all the values of an array * @link https://php.net/manual/en/function.array-count-values.php * @param array $array

    * The array of values to count *

    * @return array an associative array of values from input as * keys and their count as value. */ #[Pure] function array_count_values(array $array): array {} /** * Return the values from a single column in the input array * @link https://secure.php.net/manual/en/function.array-column.php * @param array $array

    A multi-dimensional array (record set) from which to pull a column of values.

    * @param string|int|null $column_key

    The column of values to return. This value may be the integer key of the column you wish to retrieve, or it may be the string key name for an associative array. It may also be NULL to return complete arrays (useful together with index_key to reindex the array).

    * @param string|int|null $index_key [optional]

    The column to use as the index/keys for the returned array. This value may be the integer key of the column, or it may be the string key name.

    * @return array Returns an array of values representing a single column from the input array. * @since 5.5 */ #[Pure] function array_column(array $array, string|int|null $column_key, string|int|null $index_key = null): array {} /** * Return an array with elements in reverse order * @link https://php.net/manual/en/function.array-reverse.php * @param array $array

    * The input array. *

    * @param bool $preserve_keys [optional]

    * If set to true keys are preserved. *

    * @return array the reversed array. * @meta */ #[Pure] function array_reverse(array $array, bool $preserve_keys = false): array {} /** * Iteratively reduce the array to a single value using a callback function * @link https://php.net/manual/en/function.array-reduce.php * @param array $array

    * The input array. *

    * @param callable $callback

    * The callback function. Signature is

    callback ( mixed $carry , mixed $item ) : mixed
    *
    mixed $carry

    The return value of the previous iteration; on the first iteration it holds the value of $initial.

    *
    mixed $item

    Holds the current iteration value of the $input

    *

    * @param mixed $initial [optional]

    * If the optional initial is available, it will * be used at the beginning of the process, or as a final result in case * the array is empty. *

    * @return mixed the resulting value. *

    * If the array is empty and initial is not passed, * array_reduce returns null. *

    *
    *

    * Example use: *

    array_reduce(['2', '3', '4'], function($ax, $dx) { return $ax . ", {$dx}"; }, '1')  // Returns '1, 2, 3, 4'
    *
    array_reduce(['2', '3', '4'], function($ax, $dx) { return $ax + (int)$dx; }, 1)  // Returns 10
    *
    *

    * @meta */ function array_reduce(array $array, callable $callback, mixed $initial = null): mixed {} /** * Pad array to the specified length with a value * @link https://php.net/manual/en/function.array-pad.php * @param array $array

    * Initial array of values to pad. *

    * @param int $length

    * New size of the array. *

    * @param mixed $value

    * Value to pad if input is less than * pad_size. *

    * @return array a copy of the input padded to size specified * by pad_size with value * pad_value. If pad_size is * positive then the array is padded on the right, if it's negative then * on the left. If the absolute value of pad_size is less than or equal to * the length of the input then no padding takes place. */ #[Pure] function array_pad(array $array, int $length, mixed $value): array {} /** * Exchanges all keys with their associated values in an array * @link https://php.net/manual/en/function.array-flip.php * @param int[]|string[] $array

    * An array of key/value pairs to be flipped. *

    * @return int[]|string[] Returns the flipped array. */ #[Pure] function array_flip(array $array): array {} /** * Changes the case of all keys in an array * @link https://php.net/manual/en/function.array-change-key-case.php * @param array $array

    * The array to work on *

    * @param int $case

    * Either CASE_UPPER or * CASE_LOWER (default) *

    * @return array an array with its keys lower or uppercased * @meta */ #[Pure] function array_change_key_case(array $array, int $case = CASE_LOWER): array {} /** * Pick one or more random keys out of an array * @link https://php.net/manual/en/function.array-rand.php * @param array $array

    * The input array. *

    * @param int $num [optional]

    * Specifies how many entries you want to pick. *

    * @return int|string|array If you are picking only one entry, array_rand * returns the key for a random entry. Otherwise, it returns an array * of keys for the random entries. This is done so that you can pick * random keys as well as values out of the array. */ function array_rand(array $array, int $num = 1): array|string|int {} /** * Removes duplicate values from an array * @link https://php.net/manual/en/function.array-unique.php * @param array $array

    * The input array. *

    * @param int $flags [optional]

    * The optional second parameter sort_flags * may be used to modify the sorting behavior using these values: *

    *

    * Sorting type flags: *

      *
    • * SORT_REGULAR - compare items normally * (don't change types) *
    • *
    • * SORT_NUMERIC - compare items numerically *
    • *
    • * SORT_STRING - compare items as strings *
    • *
    • * SORT_LOCALE_STRING - compare items as strings, * based on the current locale *
    • *
    * @return array the filtered array. * @meta */ #[Pure] function array_unique(array $array, int $flags = SORT_STRING): array {} /** * Computes the intersection of arrays * @link https://php.net/manual/en/function.array-intersect.php * @param array $array

    * The array with main values to check. *

    * @param array ...$arrays arrays to compare values against. * @return array an array containing all the values of * array that are present in all the arguments. * Note that keys are preserved. * @meta */ #[Pure] function array_intersect(array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arrays, array ...$arrays): array {} /** * Computes the intersection of arrays using keys for comparison * @link https://php.net/manual/en/function.array-intersect-key.php * @param array $array

    * The array with main keys to check. *

    * @param array ...$arrays * @return array an array containing all the entries of * array which have keys that are present in all the * arguments. * @meta */ #[Pure] function array_intersect_key(array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arrays, array ...$arrays): array {} /** * Computes the intersection of arrays using a callback function on the keys for comparison * @link https://php.net/manual/en/function.array-intersect-ukey.php * @param array $array

    * Initial array for comparison of the arrays. *

    * @param array $array2

    * First array to compare keys against. *

    * @param callable $key_compare_func

    * User supplied callback function to do the comparison. *

    * @param ...$rest [optional] * @return array an array containing all the values of * array which have matching keys that are present * in all the arguments. * @meta */ function array_intersect_ukey( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $key_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest ): array {} /** * Computes the intersection of arrays, compares data by a callback function * @link https://php.net/manual/en/function.array-uintersect.php * @param array $array

    * The first array. *

    * @param array $array2

    * The second array. *

    * @param callable $data_compare_func

    * The callback comparison function. *

    * @param array ...$rest *

    * The user supplied callback function is used for comparison. * It must return an integer less than, equal to, or greater than zero if * the first argument is considered to be respectively less than, equal * to, or greater than the second. *

    * @return array an array containing all the values of array * that are present in all the arguments. * @meta */ function array_uintersect( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $data_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest ): array {} /** * Computes the intersection of arrays with additional index check * @link https://php.net/manual/en/function.array-intersect-assoc.php * @param array $array

    * The array with main values to check. *

    * @param array $arrays * @return array an associative array containing all the values in * array that are present in all of the arguments. * @meta */ #[Pure] function array_intersect_assoc(array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arrays, array ...$arrays): array {} /** * Computes the intersection of arrays with additional index check, compares data by a callback function * @link https://php.net/manual/en/function.array-uintersect-assoc.php * @param array $array

    * The first array. *

    * @param array $array2

    * The second array. *

    * @param callable $data_compare_func

    * For comparison is used the user supplied callback function. * It must return an integer less than, equal * to, or greater than zero if the first argument is considered to * be respectively less than, equal to, or greater than the * second. *

    * @param array ...$rest * @return array an array containing all the values of * array that are present in all the arguments. * @meta */ function array_uintersect_assoc( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $data_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest ): array {} /** * Computes the intersection of arrays with additional index check, compares indexes by a callback function * @link https://php.net/manual/en/function.array-intersect-uassoc.php * @param array $array

    * Initial array for comparison of the arrays. *

    * @param array $array2

    * First array to compare keys against. *

    * @param callable $key_compare_func

    * User supplied callback function to do the comparison. *

    * @param array ...$rest * @return array the values of array whose values exist in all of the arguments. * @meta */ function array_intersect_uassoc( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $key_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest ): array {} /** * Computes the intersection of arrays with additional index check, compares data and indexes by separate callback functions * @link https://php.net/manual/en/function.array-uintersect-uassoc.php * @param array $array

    * The first array. *

    * @param array $array2

    * The second array. *

    * @param callable $data_compare_func

    * For comparison is used the user supplied callback function. * It must return an integer less than, equal * to, or greater than zero if the first argument is considered to * be respectively less than, equal to, or greater than the * second. *

    * @param callable $key_compare_func

    * Key comparison callback function. *

    * @param array ...$rest * @return array an array containing all the values and keys of * array1 that are present in all the arguments. * @meta */ #[Pure] function array_uintersect_uassoc( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $data_compare_func, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $key_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest ): array {} /** * Computes the difference of arrays * @link https://php.net/manual/en/function.array-diff.php * @param array $array

    * The array to compare from *

    * @param array ...$arrays * @return array an array containing all the entries from * array that are not present in any of the other * arrays. Keys in the array array are preserved. * @meta */ #[Pure] function array_diff(array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arrays, array ...$arrays): array {} /** * Computes the difference of arrays using keys for comparison * @link https://php.net/manual/en/function.array-diff-key.php * @param array $array

    * The array to compare from *

    * @param array $arrays

    * An array to compare against *

    * @return array an array containing all the entries from * array whose keys are absent from all of the other arrays. * @meta */ #[Pure] function array_diff_key(array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arrays, array ...$arrays): array {} /** * Computes the difference of arrays using a callback function on the keys for comparison * @link https://php.net/manual/en/function.array-diff-ukey.php * @param array $array

    * The array to compare from *

    * @param array $array2

    * An array to compare against *

    * @param callable $key_compare_func

    * callback function to use. * The callback function must return an integer less than, equal * to, or greater than zero if the first argument is considered to * be respectively less than, equal to, or greater than the second. *

    * @param array ...$rest [optional] * @return array an array containing all the entries from * array that are not present in any of the other arrays. * @meta */ function array_diff_ukey( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $key_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest, ): array {} /** * Computes the difference of arrays by using a callback function for data comparison * @link https://php.net/manual/en/function.array-udiff.php * @param array $array

    * The first array. *

    * @param array $array2

    * The second array. *

    * @param callable $data_compare_func

    * The callback comparison function. *

    *

    * The user supplied callback function is used for comparison. * It must return an integer less than, equal to, or greater than zero if * the first argument is considered to be respectively less than, equal * to, or greater than the second. *

    * @param array ...$rest [optional] * @return array an array containing all the values of * array that are not present in any of the other arguments. * @meta */ function array_udiff( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $data_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest, ): array {} /** * Computes the difference of arrays with additional index check * @link https://php.net/manual/en/function.array-diff-assoc.php * @param array $array

    * The array to compare from *

    * @param array $arrays

    * An array to compare against *

    * @return array an array containing all the values from * array that are not present in any of the other arrays. * @meta */ #[Pure] function array_diff_assoc( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arrays, array ...$arrays ): array {} /** * Computes the difference of arrays with additional index check, compares data by a callback function * @link https://php.net/manual/en/function.array-udiff-assoc.php * @param array $array

    * The first array. *

    * @param array $array2

    * The second array. *

    * @param callable $data_compare_func

    * The callback comparison function. *

    *

    * The user supplied callback function is used for comparison. * It must return an integer less than, equal to, or greater than zero if * the first argument is considered to be respectively less than, equal * to, or greater than the second. *

    * @param array ...$rest [optional] * @return array returns an array containing all the values from array * that are not present in any of the other arguments. * Note that the keys are used in the comparison unlike * array_diff and array_udiff. * The comparison of arrays' data is performed by using an user-supplied * callback. In this aspect the behaviour is opposite to the behaviour of * array_diff_assoc which uses internal function for * comparison. * @meta */ function array_udiff_assoc( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $data_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest, ): array {} /** * Computes the difference of arrays with additional index check which is performed by a user supplied callback function * @link https://php.net/manual/en/function.array-diff-uassoc.php * @param array $array

    * The array to compare from *

    * @param array $array2

    * An array to compare against *

    * @param callable $key_compare_func

    * callback function to use. * The callback function must return an integer less than, equal * to, or greater than zero if the first argument is considered to * be respectively less than, equal to, or greater than the second. *

    * @param array ...$rest [optional] * @return array an array containing all the values and keys from * array that are not present in any of the other arrays. * @meta */ function array_diff_uassoc( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $key_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest, ): array {} /** * Computes the difference of arrays with additional index check, compares data and indexes by a callback function * @link https://php.net/manual/en/function.array-udiff-uassoc.php * @param array $array

    * The first array. *

    * @param array $array2

    * The second array. *

    * @param callable $data_compare_func

    * The callback comparison function. *

    *

    * The user supplied callback function is used for comparison. * It must return an integer less than, equal to, or greater than zero if * the first argument is considered to be respectively less than, equal * to, or greater than the second. *

    *

    * The comparison of arrays' data is performed by using an user-supplied * callback : data_compare_func. In this aspect * the behaviour is opposite to the behaviour of * array_diff_assoc which uses internal function for * comparison. *

    * @param callable $key_compare_func

    * The comparison of keys (indices) is done also by the callback function * key_compare_func. This behaviour is unlike what * array_udiff_assoc does, since the latter compares * the indices by using an internal function. *

    * @param array ...$rest [optional] * @return array an array containing all the values and keys from * array that are not present in any of the other * arguments. * @meta */ function array_udiff_uassoc( array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] array $array2, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $data_compare_func, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] callable $key_compare_func, #[PhpStormStubsElementAvailable(from: '8.0')] ...$rest ): array {} /** * Calculate the sum of values in an array * @link https://php.net/manual/en/function.array-sum.php * @param array $array

    * The input array. *

    * @return int|float the sum of values as an integer or float. */ #[Pure] function array_sum(array $array): int|float {} /** * Calculate the product of values in an array * @link https://php.net/manual/en/function.array-product.php * @param array $array

    * The array. *

    * @return int|float the product as an integer or float. */ #[Pure] function array_product(array $array): int|float {} /** * Iterates over each value in the array * passing them to the callback function. * If the callback function returns true, the * current value from array is returned into * the result array. Array keys are preserved. * @link https://php.net/manual/en/function.array-filter.php * @param array $array

    * The array to iterate over *

    * @param callable|null $callback [optional]

    * The callback function to use *

    *

    * If no callback is supplied, all entries of * input equal to false (see * converting to * boolean) will be removed. *

    * @param int $mode [optional]

    * Flag determining what arguments are sent to callback: *

      *
    • * ARRAY_FILTER_USE_KEY - pass key as the only argument * to callback instead of the value *
    • *
    • * ARRAY_FILTER_USE_BOTH - pass both value and key as * arguments to callback instead of the value *
    • *
    * @return array the filtered array. * @meta */ function array_filter(array $array, ?callable $callback, int $mode = 0): array {} /** * Applies the callback to the elements of the given arrays * @link https://php.net/manual/en/function.array-map.php * @param callable|null $callback

    * Callback function to run for each element in each array. *

    * @param array $array

    * An array to run through the callback function. *

    * @param array ...$arrays * @return array an array containing all the elements of arr1 * after applying the callback function to each one. * @meta */ function array_map( ?callable $callback, #[PhpStormStubsElementAvailable(from: '8.0')] array $array, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $arrays, array ...$arrays ): array {} /** * Split an array into chunks * @link https://php.net/manual/en/function.array-chunk.php * @param array $array

    * The array to work on *

    * @param int $length

    * The size of each chunk *

    * @param bool $preserve_keys [optional]

    * When set to true keys will be preserved. * Default is false which will reindex the chunk numerically *

    * @return array a multidimensional numerically indexed array, starting with zero, * with each dimension containing size elements. */ #[Pure] function array_chunk(array $array, int $length, bool $preserve_keys = false): array {} /** * Creates an array by using one array for keys and another for its values * @link https://php.net/manual/en/function.array-combine.php * @param array $keys

    * Array of keys to be used. Illegal values for key will be * converted to string. *

    * @param array $values

    * Array of values to be used *

    * @return array|false the combined array, false if the number of elements * for each array isn't equal or if the arrays are empty. * @meta */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] function array_combine(array $keys, array $values) {} /** * Checks if the given key or index exists in the array * @link https://php.net/manual/en/function.array-key-exists.php * @param int|string $key

    * Value to check. *

    * @param array|ArrayObject $array

    * An array with keys to check. *

    * @return bool true on success or false on failure. */ #[Pure] function array_key_exists($key, #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|ArrayObject")] $array): bool {} /** * Gets the first key of an array * * Get the first key of the given array without affecting the internal array pointer. * * @link https://secure.php.net/array_key_first * @param array $array An array * @return string|int|null Returns the first key of array if the array is not empty; NULL otherwise. * @since 7.3 */ #[Pure] function array_key_first(array $array): string|int|null {} /** * Gets the last key of an array * * Get the last key of the given array without affecting the internal array pointer. * * @link https://secure.php.net/array_key_last * @param array $array An array * @return string|int|null Returns the last key of array if the array is not empty; NULL otherwise. * @since 7.3 */ #[Pure] function array_key_last(array $array): string|int|null {} /** * @link https://secure.php.net/array_is_list * @param array $array An array * @return bool return true if the array keys are 0 .. count($array)-1 in that order. * For other arrays, it returns false. For non-arrays, it throws a TypeError. * @since 8.1 */ #[Pure] function array_is_list(array $array): bool {} /** * Alias: * {@see current} * @link https://php.net/manual/en/function.pos.php * @param array|ArrayAccess $array * @return mixed */ #[Pure] function pos(object|array $array): mixed {} /** * Alias: * {@see \count} * @link https://php.net/manual/en/function.sizeof.php * @param array|Countable $value * @param int $mode [optional] * @return int<0, max> */ #[Pure] function sizeof(Countable|array $value, int $mode = COUNT_NORMAL): int {} /** * Checks if the given key or index exists in the array. The name of this function is array_key_exists() in PHP > 4.0.6. * @link https://php.net/manual/en/function.array-key-exists.php * @param int|string $key

    * Value to check. *

    * @param array $array

    * An array with keys to check. *

    * @return bool true on success or false on failure. */ #[Pure] function key_exists($key, array $array): bool {} /** * Checks if assertion is FALSE * @link https://php.net/manual/en/function.assert.php * @param Throwable|string|null $assertion

    * The assertion. * In PHP 5, this must be either a string to be evaluated or a boolean to be tested. * In PHP 7, this may also be any expression that returns a value, * which will be executed and the result used to indicate whether the assertion succeeded or failed.
    * Since 7.2.0 using string is deprecated. *

    * @param string $description [optional] *

    An optional description that will be included in the failure message if the assertion fails.

    * @return bool false if the assertion is false, true otherwise. */ function assert( mixed $assertion, #[PhpStormStubsElementAvailable(from: '7.0')] #[LanguageLevelTypeAware(['7.0' => 'Throwable|string|null'], default: 'string')] $description = null ): bool {} /** * AssertionError is thrown when an assertion made via {@see assert()} fails. * @link https://php.net/manual/en/class.assertionerror.php * @since 7.0 */ class AssertionError extends Error {} /** * Set/get the various assert flags * @link https://php.net/manual/en/function.assert-options.php * @param int $option

    *

    * Assert Options * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    OptionINI SettingDefault valueDescription
    ASSERT_ACTIVEassert.active1enable assert evaluation
    ASSERT_WARNINGassert.warning1issue a PHP warning for each failed assertion
    ASSERT_BAILassert.bail0terminate execution on failed assertions
    ASSERT_QUIET_EVALassert.quiet_eval0 * disable error_reporting during assertion expression * evaluation *
    ASSERT_CALLBACKassert.callbacknullCallback to call on failed assertions
    *

    * @param mixed $value [optional]

    * An optional new value for the option. *

    * @return mixed The original setting of any option. */ #[Deprecated(since: "8.3")] function assert_options(int $option, mixed $value): mixed {} /** * Compares two "PHP-standardized" version number strings * @link https://php.net/manual/en/function.version-compare.php * @param string $version1

    * First version number. *

    * @param string $version2

    * Second version number. *

    * @param string|null $operator [optional]

    * If you specify the third optional operator * argument, you can test for a particular relationship. The * possible operators are: <, * lt, <=, * le, >, * gt, >=, * ge, ==, * =, eq, * !=, <>, * ne respectively. *

    *

    * This parameter is case-sensitive, so values should be lowercase. *

    * @return int|bool By default, version_compare returns * -1 if the first version is lower than the second, * 0 if they are equal, and * 1 if the second is lower. *

    *

    * When using the optional operator argument, the * function will return true if the relationship is the one specified * by the operator, false otherwise. */ #[ExpectedValues([-1, 0, 1, false, true])] function version_compare( string $version1, string $version2, #[ExpectedValues(values: [ "<", "lt", "<=", "le", ">", "gt", ">=", "ge", "==", "=", "eq", "!=", "<>", "ne" ])] ?string $operator ): int|bool {} /** * Convert a pathname and a project identifier to a System V IPC key * @link https://php.net/manual/en/function.ftok.php * @param string $filename

    * Path to an accessible file. *

    * @param string $project_id

    * Project identifier. This must be a one character string. *

    * @return int On success the return value will be the created key value, otherwise * -1 is returned. */ #[Pure(true)] function ftok(string $filename, string $project_id): int {} /** * Perform the rot13 transform on a string * @link https://php.net/manual/en/function.str-rot13.php * @param string $string

    * The input string. *

    * @return string the ROT13 version of the given string. */ #[Pure] function str_rot13(string $string): string {} /** * Retrieve list of registered filters * @link https://php.net/manual/en/function.stream-get-filters.php * @return list an indexed array containing the name of all stream filters * available. */ #[Pure(true)] function stream_get_filters(): array {} /** * Check if a stream is a TTY * @link https://php.net/manual/en/function.stream-isatty.php * @param resource $stream * @return bool * @since 7.2 */ #[Pure] function stream_isatty($stream): bool {} /** * Register a user defined stream filter * @link https://php.net/manual/en/function.stream-filter-register.php * @param string $filter_name

    * The filter name to be registered. *

    * @param string $class

    * To implement a filter, you need to define a class as an extension of * php_user_filter with a number of member functions * as defined below. When performing read/write operations on the stream * to which your filter is attached, PHP will pass the data through your * filter (and any other filters attached to that stream) so that the * data may be modified as desired. You must implement the methods * exactly as described below - doing otherwise will lead to undefined * behaviour. *

    * intfilter * resourcein * resourceout * intconsumed * boolclosing *

    * This method is called whenever data is read from or written to * the attached stream (such as with fread or fwrite). * in is a resource pointing to a bucket brigade * which contains one or more bucket objects containing data to be filtered. * out is a resource pointing to a second bucket brigade * into which your modified buckets should be placed. * consumed, which must always * be declared by reference, should be incremented by the length of the data * which your filter reads in and alters. In most cases this means you will * increment consumed by $bucket->datalen * for each $bucket. If the stream is in the process of closing * (and therefore this is the last pass through the filterchain), * the closing parameter will be set to true. * The filter method must return one of * three values upon completion. * * Return Value * Meaning * * * PSFS_PASS_ON * * Filter processed successfully with data available in the * out bucket brigade. * * * * PSFS_FEED_ME * * Filter processed successfully, however no data was available to * return. More data is required from the stream or prior filter. * * * * PSFS_ERR_FATAL (default) * * The filter experienced an unrecoverable error and cannot continue. * * *

    * boolonCreate * This method is called during instantiation of the filter class * object. If your filter allocates or initializes any other resources * (such as a buffer), this is the place to do it. Your implementation of * this method should return false on failure, or true on success. * When your filter is first instantiated, and * yourfilter->onCreate() is called, a number of properties * will be available as shown in the table below. *

    * * Property * Contents * * * FilterClass->filtername * * A string containing the name the filter was instantiated with. * Filters may be registered under multiple names or under wildcards. * Use this property to determine which name was used. * * * * FilterClass->params * * The contents of the params parameter passed * to stream_filter_append * or stream_filter_prepend. * * * * FilterClass->stream * * The stream resource being filtered. Maybe available only during * filter calls when the * closing parameter is set to false. * * *

    * voidonClose *

    * This method is called upon filter shutdown (typically, this is also * during stream shutdown), and is executed after * the flush method is called. If any resources * were allocated or initialized during onCreate() * this would be the time to destroy or dispose of them. *

    * @return bool true on success or false on failure. *

    * stream_filter_register will return false if the * filtername is already defined. *

    */ function stream_filter_register(string $filter_name, string $class): bool {} /** * Return a bucket object from the brigade for operating on * @link https://php.net/manual/en/function.stream-bucket-make-writeable.php * @param resource $brigade * @return object|null */ #[LanguageLevelTypeAware(["8.4" => "StreamBucket|null"], default: "object|null")] function stream_bucket_make_writeable($brigade) {} /** * Prepend bucket to brigade * @link https://php.net/manual/en/function.stream-bucket-prepend.php * @param resource $brigade * @param object $bucket * @return void */ function stream_bucket_prepend($brigade, #[LanguageLevelTypeAware(['8.4' => 'StreamBucket'], default: 'object')] $bucket): void {} /** * Append bucket to brigade * @link https://php.net/manual/en/function.stream-bucket-append.php * @param resource $brigade * @param object $bucket * @return void */ function stream_bucket_append($brigade, #[LanguageLevelTypeAware(['8.4' => 'StreamBucket'], default: 'object')] $bucket): void {} /** * Create a new bucket for use on the current stream * @link https://php.net/manual/en/function.stream-bucket-new.php * @param resource $stream * @param string $buffer * @return object */ #[LanguageLevelTypeAware(["8.4" => "StreamBucket"], default: "object")] function stream_bucket_new($stream, string $buffer) {} /** * Add URL rewriter values * @link https://php.net/manual/en/function.output-add-rewrite-var.php * @param string $name

    * The variable name. *

    * @param string $value

    * The variable value. *

    * @return bool true on success or false on failure. */ function output_add_rewrite_var(string $name, string $value): bool {} /** * Reset URL rewriter values * * * * * * * * * * * * * * * * * *
    VersionDescription
    7.1.0 * Before PHP 7.1.0, rewrite vars set by output_add_rewrite_var() * use the same Session module trans sid output buffer. Since PHP 7.1.0, * dedicated output buffer is used and {@see output_reset_rewrite_vars()} * only removes rewrite vars defined by {@see output_add_rewrite_var()}. *
    * * @link https://php.net/manual/en/function.output-reset-rewrite-vars.php * @return bool true on success or false on failure. */ function output_reset_rewrite_vars(): bool {} /** * Returns directory path used for temporary files * @link https://php.net/manual/en/function.sys-get-temp-dir.php * @return string the path of the temporary directory. * @since 5.2.1 */ function sys_get_temp_dir(): string {} /** * Get the contents of the realpath cache. * @link https://php.net/manual/en/function.realpath-cache-get.php * @return array Returns an array of realpath cache entries. The keys are * original path entries, and the values are arrays of data items, * containing the resolved path, expiration date, and other options kept in * the cache. * @since 5.3.2 */ #[Pure(true)] function realpath_cache_get(): array {} /** * Get the amount of memory used by the realpath cache. * @link https://php.net/manual/en/function.realpath-cache-size.php * @return int Returns how much memory realpath cache is using. * @since 5.3.2 */ #[Pure(true)] function realpath_cache_size(): int {} /** * It returns the same result as (array) $object, with the * exception that it ignores overloaded array casts, such as used by * ArrayObject. * @param object $object * @return array returns the mangled object properties * @since 7.4 */ function get_mangled_object_vars(object $object): array {} /** * Get the type or object name of a variable * * @param mixed $value The variable being type checked. * @return string Possibles values for the returned string are: * - "int" * - "float" * - "bool" * - "string" * - "array" * - "null" * - A class name for named classes * - "class@anonymous" for an anonymous classes * - "resource (xxx)" for any resources where "xxx" is a name of resource * - "resource (closed)" for closed resources * @since 8.0 */ #[Pure] function get_debug_type(mixed $value): string {} /** * A more obvious and type-safe form of "(int) $resource" * * @param resource $resource * @return int * @since 8.0 */ #[Pure] function get_resource_id($resource): int {} * If you have compiled in OpenSSL support, you may prefix the * hostname with either ssl:// * or tls:// to use an SSL or TLS client connection * over TCP/IP to connect to the remote host. *

    * @param int $port

    * The port number. *

    * @param int &$error_code [optional]

    * If provided, holds the system level error number that occurred in the * system-level connect() call. *

    *

    * If the value returned in errno is * 0 and the function returned false, it is an * indication that the error occurred before the * connect() call. This is most likely due to a * problem initializing the socket. *

    * @param string &$error_message [optional]

    * The error message as a string. *

    * @param float|null $timeout [optional]

    * The connection timeout, in seconds. *

    *

    * If you need to set a timeout for reading/writing data over the * socket, use stream_set_timeout, as the * timeout parameter to * fsockopen only applies while connecting the * socket. *

    * @return resource|false fsockopen returns a file pointer which may be used * together with the other file functions (such as * fgets, fgetss, * fwrite, fclose, and * feof). If the call fails, it will return false */ function fsockopen( string $hostname, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] int $port, #[PhpStormStubsElementAvailable(from: '7.1')] int $port = -1, &$error_code, &$error_message, ?float $timeout ) {} /** * Open persistent Internet or Unix domain socket connection * @link https://php.net/manual/en/function.pfsockopen.php * @see fsockopen * @param string $hostname * @param int $port * @param int &$error_code [optional] * @param string &$error_message [optional] * @param float|null $timeout [optional] * @return resource|false */ function pfsockopen( string $hostname, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] int $port, #[PhpStormStubsElementAvailable(from: '7.1')] int $port = -1, &$error_code, &$error_message, ?float $timeout ) {} /** * Pack data into binary string * @link https://php.net/manual/en/function.pack.php * @param string $format

    * The format string consists of format codes * followed by an optional repeater argument. The repeater argument can * be either an integer value or * for repeating to * the end of the input data. For a, A, h, H the repeat count specifies * how many characters of one data argument are taken, for @ it is the * absolute position where to put the next data, for everything else the * repeat count specifies how many data arguments are consumed and packed * into the resulting binary string. *

    *

    * Currently implemented formats are: *

    * pack format characters * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    CodeDescription
    aNUL-padded string
    ASPACE-padded string
    hHex string, low nibble first
    HHex string, high nibble first
    csigned char
    Cunsigned char
    ssigned short (always 16 bit, machine byte order)
    Sunsigned short (always 16 bit, machine byte order)
    nunsigned short (always 16 bit, big endian byte order)
    vunsigned short (always 16 bit, little endian byte order)
    isigned integer (machine dependent size and byte order)
    Iunsigned integer (machine dependent size and byte order)
    lsigned long (always 32 bit, machine byte order)
    Lunsigned long (always 32 bit, machine byte order)
    Nunsigned long (always 32 bit, big endian byte order)
    Vunsigned long (always 32 bit, little endian byte order)
    ffloat (machine dependent size and representation, both little and big endian)
    ddouble (machine dependent size and representation, both little and big endian)
    xNUL byte
    XBack up one byte
    @NUL-fill to absolute position
    *

    * @param mixed ...$values

    *

    * @return string|false a binary string containing data or false if the format string contains errors */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] function pack( string $format, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.3')] $values, mixed ...$values ) {} /** * Unpack data from binary string * @link https://php.net/manual/en/function.unpack.php * @param string $format

    * See pack for an explanation of the format codes. *

    * @param string $string

    * The packed data. *

    * @param int $offset [optional] * @return array|false an associative array containing unpacked elements of binary * string or false if the format string contains errors */ #[Pure] function unpack( string $format, string $string, #[PhpStormStubsElementAvailable(from: '7.1')] int $offset = 0 ): array|false {} /** * Tells what the user's browser is capable of * @link https://php.net/manual/en/function.get-browser.php * @param string|null $user_agent [optional]

    * The User Agent to be analyzed. By default, the value of HTTP * User-Agent header is used; however, you can alter this (i.e., look up * another browser's info) by passing this parameter. *

    *

    * You can bypass this parameter with a null value. *

    * @param bool $return_array [optional]

    * If set to true, this function will return an array * instead of an object. *

    * @return array|object|false Returns false if browscap.ini can't be loaded or the user agent can't be found, otherwise the information is returned in an object or an array which will contain * various data elements representing, for instance, the browser's major and * minor version numbers and ID string; true/false values for features * such as frames, JavaScript, and cookies; and so forth. *

    *

    * The cookies value simply means that the browser * itself is capable of accepting cookies and does not mean the user has * enabled the browser to accept cookies or not. The only way to test if * cookies are accepted is to set one with setcookie, * reload, and check for the value. */ #[Pure(true)] function get_browser(?string $user_agent, bool $return_array = false): object|array|false {} /** * One-way string encryption (hashing) * @link https://php.net/manual/en/function.crypt.php * @param string $string

    * The string to be encrypted. *

    * @param string $salt

    * An optional salt string to base the encryption on. If not provided, * one will be randomly generated by PHP each time you call this function. * PHP 5.6 or later raise E_NOTICE error if this parameter is omitted *

    *

    * If you are using the supplied salt, you should be aware that the salt * is generated once. If you are calling this function repeatedly, this * may impact both appearance and security. *

    * @return string|null the encrypted string or NULL if an error occurs */ #[Pure] #[PhpStormStubsElementAvailable(to: '7.4')] function crypt($string, $salt): ?string {} /** * One-way string encryption (hashing) * @link https://php.net/manual/en/function.crypt.php * @param string $string

    * The string to be encrypted. *

    * @param string $salt

    * An optional salt string to base the encryption on. If not provided, * one will be randomly generated by PHP each time you call this function. * PHP 5.6 or later raise E_NOTICE error if this parameter is omitted *

    *

    * If you are using the supplied salt, you should be aware that the salt * is generated once. If you are calling this function repeatedly, this * may impact both appearance and security. *

    * @return string the encrypted string or NULL if an error occurs */ #[Pure] #[PhpStormStubsElementAvailable('8.0')] function crypt(string $string, string $salt): string {} /** * Open directory handle * @link https://php.net/manual/en/function.opendir.php * @param string $directory

    * The directory path that is to be opened *

    * @param resource $context [optional]

    * For a description of the context parameter, * refer to the streams section of * the manual. *

    * @return resource|false a directory handle resource on success, or * false on failure. *

    *

    * If path is not a valid directory or the * directory can not be opened due to permission restrictions or * filesystem errors, opendir returns false and * generates a PHP error of level * E_WARNING. You can suppress the error output of * opendir by prepending * '@' to the * front of the function name. */ function opendir(string $directory, $context) {} /** * Close directory handle * @link https://php.net/manual/en/function.closedir.php * @param resource $dir_handle [optional]

    * The directory handle resource previously opened * with opendir. If the directory handle is * not specified, the last link opened by opendir * is assumed. *

    * @return void */ function closedir($dir_handle): void {} /** * Change directory * @link https://php.net/manual/en/function.chdir.php * @param string $directory

    * The new current directory *

    * @return bool true on success or false on failure. */ function chdir(string $directory): bool {} /** * Change the root directory * @link https://php.net/manual/en/function.chroot.php * @param string $directory

    * The new directory *

    * @return bool true on success or false on failure. */ function chroot(string $directory): bool {} /** * Gets the current working directory * @link https://php.net/manual/en/function.getcwd.php * @return string|false

    * the current working directory on success, or false on * failure.
    *
    * On some Unix variants, 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. See chmod for more information on * modes and permissions. *

    */ #[Pure(true)] function getcwd(): string|false {} /** * Rewind directory handle * @link https://php.net/manual/en/function.rewinddir.php * @param resource $dir_handle [optional]

    * The directory handle resource previously opened * with opendir. If the directory handle is * not specified, the last link opened by opendir * is assumed. *

    * @see https://bugs.php.net/bug.php?id=75485 */ function rewinddir($dir_handle): void {} /** * Read entry from directory handle * @link https://php.net/manual/en/function.readdir.php * @param resource $dir_handle [optional]

    * The directory handle resource previously opened * with opendir. If the directory handle is * not specified, the last link opened by opendir * is assumed. *

    * @return string|false the filename on success or false on failure. */ function readdir($dir_handle): string|false {} /** * Return an instance of the Directory class * @link https://php.net/manual/en/function.dir.php * @param string $directory

    * Directory to open *

    * @param resource $context [optional] * @return Directory|false an instance of Directory, or NULL with wrong * parameters, or FALSE in case of another error */ function dir(string $directory, $context): Directory|false {} /** * Alias of dir() * @param string $directory * @param resource $context * @since 8.0 * @return Directory|false * @see dir() */ function getdir(string $directory, $context = null): Directory|false {} /** * List files and directories inside the specified path * @link https://php.net/manual/en/function.scandir.php * @param string $directory

    * The directory that will be scanned. *

    * @param int $sorting_order

    * By default, the sorted order is alphabetical in ascending order. If * the optional sorting_order is set to non-zero, * then the sort order is alphabetical in descending order. *

    * @param resource $context [optional]

    * For a description of the context parameter, * refer to the streams section of * the manual. *

    * @return array|false an array of filenames on success, or false on * failure. If directory is not a directory, then * boolean false is returned, and an error of level * E_WARNING is generated. */ function scandir(string $directory, int $sorting_order = 0, $context): array|false {} /** * Find pathnames matching a pattern * @link https://php.net/manual/en/function.glob.php * @param string $pattern

    * The pattern. No tilde expansion or parameter substitution is done. *

    * @param int $flags

    * Valid flags: * GLOB_MARK - Adds a slash to each directory returned * GLOB_NOSORT - Return files as they appear in the directory (no sorting). When this flag is not used, the pathnames are sorted alphabetically * GLOB_NOCHECK - Return the search pattern if no files matching it were found * GLOB_NOESCAPE - Backslashes do not quote metacharacters * GLOB_BRACE - Expands {a,b,c} to match 'a', 'b', or 'c' * GLOB_ONLYDIR - Return only directory entries which match the pattern * GLOB_ERR - Stop on read errors (like unreadable directories), by default errors are ignored. * @return array|false an array containing the matched files/directories, an empty array * if no file matched or false on error. *

    *

    * On some systems it is impossible to distinguish between empty match and an * error.

    */ #[Pure(true)] function glob(string $pattern, int $flags = 0): array|false {} /** * Gets last access time of file * @link https://php.net/manual/en/function.fileatime.php * @param string $filename

    * Path to the file. *

    * @return int|false the time the file was last accessed, or false on failure. * The time is returned as a Unix timestamp. */ #[Pure(true)] function fileatime(string $filename): int|false {} /** * Gets inode change time of file * @link https://php.net/manual/en/function.filectime.php * @param string $filename

    * Path to the file. *

    * @return int|false the time the file was last changed, or false on failure. * The time is returned as a Unix timestamp. */ #[Pure(true)] function filectime(string $filename): int|false {} /** * Gets file group * @link https://php.net/manual/en/function.filegroup.php * @param string $filename

    * Path to the file. *

    * @return int|false the group ID of the file, or false in case * of an error. The group ID is returned in numerical format, use * posix_getgrgid to resolve it to a group name. * Upon failure, false is returned. */ #[Pure(true)] function filegroup(string $filename): int|false {} /** * Gets file inode * @link https://php.net/manual/en/function.fileinode.php * @param string $filename

    * Path to the file. *

    * @return int|false the inode number of the file, or false on failure. */ #[Pure(true)] function fileinode(string $filename): int|false {} /** * Gets file modification time * @link https://php.net/manual/en/function.filemtime.php * @param string $filename

    * Path to the file. *

    * @return int|false the time the file was last modified, or false on failure. * The time is returned as a Unix timestamp, which is * suitable for the date function. */ #[Pure(true)] function filemtime(string $filename): int|false {} /** * Gets file owner * @link https://php.net/manual/en/function.fileowner.php * @param string $filename

    * Path to the file. *

    * @return int|false the user ID of the owner of the file, or false on failure. * The user ID is returned in numerical format, use * posix_getpwuid to resolve it to a username. */ #[Pure(true)] function fileowner(string $filename): int|false {} /** * Gets file permissions * @link https://php.net/manual/en/function.fileperms.php * @param string $filename

    * Path to the file. *

    * @return int|false the permissions on the file, or false on failure. */ #[Pure(true)] function fileperms(string $filename): int|false {} /** * Gets file size * @link https://php.net/manual/en/function.filesize.php * @param string $filename

    * Path to the file. *

    * @return int|false the size of the file in bytes, or false (and generates an error * of level E_WARNING) in case of an error. */ #[Pure(true)] function filesize(string $filename): int|false {} /** * Gets file type * @link https://php.net/manual/en/function.filetype.php * @param string $filename

    * Path to the file. *

    * @return string|false the type of the file. Possible values are fifo, char, * dir, block, link, file, socket and unknown. *

    *

    * Returns false if an error occurs. filetype will also * produce an E_NOTICE message if the stat call fails * or if the file type is unknown. */ #[Pure(true)] function filetype(string $filename): string|false {} /** * Checks whether a file or directory exists * @link https://php.net/manual/en/function.file-exists.php * @param string $filename

    * Path to the file or directory. *

    *

    * On windows, use //computername/share/filename or * \\computername\share\filename to check files on * network shares. *

    * @return bool true if the file or directory specified by * filename exists; false otherwise. *

    *

    * This function will return false for symlinks pointing to non-existing * files. *

    *

    * This function returns false for files inaccessible due to safe mode restrictions. However these * files still can be included if * they are located in safe_mode_include_dir. *

    *

    * The check is done using the real UID/GID instead of the effective one. */ #[Pure(true)] function file_exists(string $filename): bool {} /** * Tells whether the filename is writable * @link https://php.net/manual/en/function.is-writable.php * @param string $filename

    * The filename being checked. *

    * @return bool true if the filename exists and is * writable. */ #[Pure(true)] function is_writable(string $filename): bool {} /** * Alias: * {@see is_writable} * @link https://php.net/manual/en/function.is-writeable.php * @param string $filename

    * The filename being checked. *

    * @return bool true if the filename exists and is * writable. */ #[Pure(true)] function is_writeable(string $filename): bool {} /** * Tells whether a file or a directory exists and is readable * @link https://php.net/manual/en/function.is-readable.php * @param string $filename

    * Path to the file or directory. *

    * @return bool true if the file or directory specified by * filename exists and is readable, false otherwise. */ #[Pure(true)] function is_readable(string $filename): bool {} /** * Tells whether the filename is executable * @link https://php.net/manual/en/function.is-executable.php * @param string $filename

    * Path to the file. *

    * @return bool true if the filename exists and is executable, or false on * error. */ #[Pure(true)] function is_executable(string $filename): bool {} /** * Tells whether the filename is a regular file * @link https://php.net/manual/en/function.is-file.php * @param string $filename

    * Path to the file. *

    * @return bool true if the filename exists and is a regular file, false * otherwise. */ #[Pure(true)] function is_file(string $filename): bool {} /** * Tells whether the filename is a directory * @link https://php.net/manual/en/function.is-dir.php * @param string $filename

    * Path to the file. If filename is a relative * filename, it will be checked relative to the current working * directory. If filename is a symbolic or hard link * then the link will be resolved and checked. *

    * @return bool true if the filename exists and is a directory, false * otherwise. */ #[Pure(true)] function is_dir(string $filename): bool {} /** * Tells whether the filename is a symbolic link * @link https://php.net/manual/en/function.is-link.php * @param string $filename

    * Path to the file. *

    * @return bool true if the filename exists and is a symbolic link, false * otherwise. */ #[Pure(true)] function is_link(string $filename): bool {} /** * Gives information about a file * @link https://php.net/manual/en/function.stat.php * @param string $filename

    * Path to the file. *

    * @return array|false * stat and fstat result * format * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    NumericAssociative (since PHP 4.0.6)Description
    0devdevice number
    1inoinode number *
    2modeinode protection mode
    3nlinknumber of links
    4uiduserid of owner *
    5gidgroupid of owner *
    6rdevdevice type, if inode device
    7sizesize in bytes
    8atimetime of last access (Unix timestamp)
    9mtimetime of last modification (Unix timestamp)
    10ctimetime of last inode change (Unix timestamp)
    11blksizeblocksize of filesystem IO **
    12blocksnumber of 512-byte blocks allocated **
    * * On Windows this will always be 0. *

    *

    * ** Only valid on systems supporting the st_blksize type - other * systems (e.g. Windows) return -1. *

    *

    * In case of error, stat returns false. */ #[Pure(true)] #[ArrayShape([ "dev" => "int", "ino" => "int", "mode" => "int", "nlink" => "int", "uid" => "int", "gid" => "int", "rdev" => "int", "size" => "int", "atime" => "int", "mtime" => "int", "ctime" => "int", "blksize" => "int", "blocks" => "int" ])] function stat(string $filename): array|false {} /** * Gives information about a file or symbolic link * @link https://php.net/manual/en/function.lstat.php * @see stat * @param string $filename

    * Path to a file or a symbolic link. *

    * @return array|false See the manual page for stat for information on * the structure of the array that lstat returns. * This function is identical to the stat function * except that if the filename parameter is a symbolic * link, the status of the symbolic link is returned, not the status of the * file pointed to by the symbolic link. */ #[Pure(true)] function lstat(string $filename): array|false {} /** * Changes file owner * @link https://php.net/manual/en/function.chown.php * @param string $filename

    * Path to the file. *

    * @param string|int $user

    * A user name or number. *

    * @return bool true on success or false on failure. */ function chown(string $filename, string|int $user): bool {} /** * Changes file group * @link https://php.net/manual/en/function.chgrp.php * @param string $filename

    * Path to the file. *

    * @param string|int $group

    * A group name or number. *

    * @return bool true on success or false on failure. */ function chgrp(string $filename, string|int $group): bool {} /** * Changes user ownership of symlink * @link https://php.net/manual/en/function.lchown.php * @param string $filename

    * Path to the file. *

    * @param string|int $user

    * User name or number. *

    * @return bool true on success or false on failure. * @since 5.1.2 */ function lchown(string $filename, string|int $user): bool {} /** * Changes group ownership of symlink * @link https://php.net/manual/en/function.lchgrp.php * @param string $filename

    * Path to the symlink. *

    * @param string|int $group

    * The group specified by name or number. *

    * @return bool true on success or false on failure. * @since 5.1.2 */ function lchgrp(string $filename, string|int $group): bool {} /** * Changes file mode * @link https://php.net/manual/en/function.chmod.php * @param string $filename

    * Path to the file. *

    * @param int $permissions

    * Note that mode is not automatically * assumed to be an octal value, so strings (such as "g+w") will * not work properly. To ensure the expected operation, * you need to prefix mode with a zero (0): *

    *
     * 
     * 
    *

    * The mode parameter consists of three octal * number components specifying access restrictions for the owner, * the user group in which the owner is in, and to everybody else in * this order. One component can be computed by adding up the needed * permissions for that target user base. Number 1 means that you * grant execute rights, number 2 means that you make the file * writeable, number 4 means that you make the file readable. Add * up these numbers to specify needed rights. You can also read more * about modes on Unix systems with 'man 1 chmod' * and 'man 2 chmod'. *

    * @return bool true on success or false on failure. */ function chmod(string $filename, int $permissions): bool {} /** * Sets access and modification time of file * @link https://php.net/manual/en/function.touch.php * @param string $filename

    * The name of the file being touched. *

    * @param int|null $mtime [optional]

    * The touch time. If time is not supplied, * the current system time is used. *

    * @param int|null $atime [optional]

    * If present, the access time of the given filename is set to * the value of atime. Otherwise, it is set to * time. *

    * @return bool true on success or false on failure. */ function touch(string $filename, ?int $mtime, ?int $atime): bool {} /** * Clears file status cache * @link https://php.net/manual/en/function.clearstatcache.php * @param bool $clear_realpath_cache [optional]

    * Whenever to clear realpath cache or not. *

    * @param string $filename

    * Clear realpath cache on a specific filename, only used if * clear_realpath_cache is true. *

    * @return void */ function clearstatcache(bool $clear_realpath_cache = false, string $filename = ''): void {} /** * Returns the total size of a filesystem or disk partition * @link https://php.net/manual/en/function.disk-total-space.php * @param string $directory

    * A directory of the filesystem or disk partition. *

    * @return float|false the total number of bytes as a float * or false on failure. */ #[Pure(true)] function disk_total_space(string $directory): float|false {} /** * Returns available space in directory * @link https://php.net/manual/en/function.disk-free-space.php * @param string $directory

    * A directory of the filesystem or disk partition. *

    *

    * Given a file name instead of a directory, the behaviour of the * function is unspecified and may differ between operating systems and * PHP versions. *

    * @return float|false the number of available bytes as a float * or false on failure. */ #[Pure(true)] function disk_free_space(string $directory): float|false {} /** * Alias of {@see disk_free_space} * @link https://php.net/manual/en/function.diskfreespace.php * @see disk_free_space * @param string $directory * @return float|false */ #[Pure(true)] function diskfreespace(string $directory): float|false {} /** * Send mail * @link https://php.net/manual/en/function.mail.php * @param string $to

    * Receiver, or receivers of the mail. *

    *

    * The formatting of this string must comply with * RFC 2822. Some examples are: * user@example.com * user@example.com, anotheruser@example.com * User <user@example.com> * User <user@example.com>, Another User <anotheruser@example.com> *

    * @param string $subject

    * Subject of the email to be sent. *

    *

    * Subject must satisfy RFC 2047. *

    * @param string $message

    * Message to be sent. *

    *

    * Each line should be separated with a LF (\n). Lines should not be larger * than 70 characters. *

    *

    * Caution * (Windows only) When PHP is talking to a SMTP server directly, if a full * stop is found on the start of a line, it is removed. To counter-act this, * replace these occurrences with a double dot. *

    *
     * 
     * 
    * @param string|array $additional_headers

    * String or array to be inserted at the end of the email header.
    * Since 7.2.0 accepts an array. Its keys are the header names and its values are the respective header values. *

    *

    * This is typically used to add extra headers (From, Cc, and Bcc). * Multiple extra headers should be separated with a CRLF (\r\n). *

    *

    * When sending mail, the mail must contain * a From header. This can be set with the * additional_headers parameter, or a default * can be set in "php.ini". *

    *

    * Failing to do this will result in an error * message similar to Warning: mail(): "sendmail_from" not * set in php.ini or custom "From:" header missing. * The From header sets also * Return-Path under Windows. *

    *

    * If messages are not received, try using a LF (\n) only. * Some poor quality Unix mail transfer agents replace LF by CRLF * automatically (which leads to doubling CR if CRLF is used). * This should be a last resort, as it does not comply with * RFC 2822. *

    * @param string $additional_params

    * The additional_parameters parameter * can be used to pass additional flags as command line options to the * program configured to be used when sending mail, as defined by the * sendmail_path configuration setting. For example, * this can be used to set the envelope sender address when using * sendmail with the -f sendmail option. *

    *

    * The user that the webserver runs as should be added as a trusted user to the * sendmail configuration to prevent a 'X-Warning' header from being added * to the message when the envelope sender (-f) is set using this method. * For sendmail users, this file is /etc/mail/trusted-users. *

    * @return bool true if the mail was successfully accepted for delivery, false otherwise. *

    * It is important to note that just because the mail was accepted for delivery, * it does NOT mean the mail will actually reach the intended destination. *

    */ function mail(string $to, string $subject, string $message, array|string $additional_headers = [], string $additional_params = ''): bool {} /** * Calculate the hash value needed by EZMLM * @link https://php.net/manual/en/function.ezmlm-hash.php * @param string $addr

    * The email address that's being hashed. *

    * @return int The hash value of addr. * @removed 8.0 */ #[Deprecated(since: '7.4')] function ezmlm_hash(string $addr): int {} /** * Open connection to system logger * @link https://php.net/manual/en/function.openlog.php * @param string $prefix

    * The string ident is added to each message. *

    * @param int $flags

    * The option argument is used to indicate * what logging options will be used when generating a log message. *

    * openlog Options * * * * * * * * * * * * * * * * * * * * * * * * *
    ConstantDescription
    LOG_CONS * if there is an error while sending data to the system logger, * write directly to the system console *
    LOG_NDELAY * open the connection to the logger immediately *
    LOG_ODELAY * (default) delay opening the connection until the first * message is logged *
    LOG_PERRORprint log message also to standard error
    LOG_PIDinclude PID with each message
    * You can use one or more of this options. When using multiple options * you need to OR them, i.e. to open the connection * immediately, write to the console and include the PID in each message, * you will use: LOG_CONS | LOG_NDELAY | LOG_PID *

    * @param int $facility

    * The facility argument is used to specify what * type of program is logging the message. This allows you to specify * (in your machine's syslog configuration) how messages coming from * different facilities will be handled. *

    * openlog Facilities * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    ConstantDescription
    LOG_AUTH * security/authorization messages (use * LOG_AUTHPRIV instead * in systems where that constant is defined) *
    LOG_AUTHPRIVsecurity/authorization messages (private)
    LOG_CRONclock daemon (cron and at)
    LOG_DAEMONother system daemons
    LOG_KERNkernel messages
    LOG_LOCAL0 ... LOG_LOCAL7reserved for local use, these are not available in Windows
    LOG_LPRline printer subsystem
    LOG_MAILmail subsystem
    LOG_NEWSUSENET news subsystem
    LOG_SYSLOGmessages generated internally by syslogd
    LOG_USERgeneric user-level messages
    LOG_UUCPUUCP subsystem
    *

    *

    * LOG_USER is the only valid log type under Windows * operating systems *

    * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function openlog(string $prefix, int $flags, int $facility) {} * Halts the execution of the compiler. This can be useful to embed data in PHP scripts, like the installation files. * Byte position of the data start can be determined by the __COMPILER_HALT_OFFSET__ constant * which is defined only if there is a __halt_compiler() presented in the file. *

    Note: __halt_compiler() can only be used from the outermost scope.

    * @link https://php.net/manual/en/function.halt-compiler.php * @return void */ function PS_UNRESERVE_PREFIX___halt_compiler() {} /** * (PHP 5.1)
    * Byte position of the data start, defined only if there is a __halt_compiler() presented in the file. * @link https://php.net/manual/en/function.halt-compiler.php * @return void */ define("__COMPILER_HALT_OFFSET__", 0); /** * Convert hexadecimal string to its binary representation. * * If the hexadecimal input string is of odd length or invalid hexadecimal string an E_WARNING level error is emitted. * * @link https://php.net/manual/en/function.hex2bin.php * @param string $string Hexadecimal string to convert. * @return string|false The binary representation of the given data or FALSE on failure. * @see bin2hex() * @see unpack() * @since 5.4 */ function hex2bin(string $string): string|false {}; /** * Get or Set the HTTP response code * @param int $response_code The optional response_code will set the response code. * @return int|bool The current response code. By default the return value is int(200). */ function http_response_code(int $response_code = 0): int|bool {} * Get the boolean value of a variable * @param mixed $value

    the scalar value being converted to a boolean.

    * @return bool The boolean value of var. * @since 5.5 */ #[Pure] function boolval(mixed $value): bool {} /** * Get the integer value of a variable * @link https://php.net/manual/en/function.intval.php * @param mixed $value

    * The scalar value being converted to an integer *

    * @param int $base [optional]

    * The base for the conversion *

    * @return int The integer value of var on success, or 0 on * failure. Empty arrays and objects return 0, non-empty arrays and * objects return 1. *

    *

    * The maximum value depends on the system. 32 bit systems have a * maximum signed integer range of -2147483648 to 2147483647. So for example * on such a system, intval('1000000000000') will return * 2147483647. The maximum signed integer value for 64 bit systems is * 9223372036854775807. *

    *

    * Strings will most likely return 0 although this depends on the * leftmost characters of the string. The common rules of * integer casting * apply. */ #[Pure] function intval(mixed $value, int $base = 10): int {} /** * Get float value of a variable * @link https://php.net/manual/en/function.floatval.php * @param mixed $value May be any scalar type. should not be used on objects, as doing so will emit an E_NOTICE level error and return 1. * @return float value of the given variable. Empty arrays return 0, non-empty arrays return 1. */ #[Pure] function floatval(mixed $value): float {} /** * (PHP 4.2.0, PHP 5)
    * Alias: * {@see floatval} * Get float value of a variable * @link https://php.net/manual/en/function.doubleval.php * @param mixed $value May be any scalar type. should not be used on objects, as doing so will emit an E_NOTICE level error and return 1. * @return float value of the given variable. Empty arrays return 0, non-empty arrays return 1. */ #[Pure] function doubleval(mixed $value): float {} /** * Get string value of a variable * @link https://php.net/manual/en/function.strval.php * @param mixed $value

    * The variable that is being converted to a string. *

    *

    * $var may be any scalar type or an object that implements the __toString() method. * You cannot use strval() on arrays or objects that do not implement the __toString() method. *

    * @return string The string value of var. */ #[Pure] function strval(mixed $value): string {} /** * Get the type of a variable * @link https://php.net/manual/en/function.gettype.php * @param mixed $value

    * The variable being type checked. *

    * @return string Possibles values for the returned string are: * "boolean" * "integer" * "double" (for historical reasons "double" is * returned in case of a float, and not simply * "float") * "string" * "array" * "object" * "resource" * "NULL" * "unknown type" * "resource (closed)" since 7.2.0 */ #[Pure] #[ExpectedValues([ "boolean", "integer", "double", "string", "array", "object", "resource", "NULL", "unknown type", "resource (closed)" ])] function gettype(mixed $value): string {} /** * Set the type of a variable * @link https://php.net/manual/en/function.settype.php * @param mixed &$var

    * The variable being converted. *

    * @param string $type

    * Possibles values of type are: *

      *
    • * "boolean" (or, since PHP 4.2.0, "bool") *
    • *
    • * "integer" (or, since PHP 4.2.0, "int") *
    • *
    • * "float" (only possible since PHP 4.2.0, for older versions use the * deprecated variant "double") *
    • *
    • * "string" *
    • *
    • * "array" *
    • *
    • * "object" *
    • *
    • * "null" (since PHP 4.2.0) *
    • *
    * @return bool true on success or false on failure. */ function settype(mixed &$var, #[ExpectedValues(["bool", "boolean", "int", "integer", "float", "double", "string", "array", "object", "null"])] string $type): bool {} /** * Finds whether a variable is null. * @link https://php.net/manual/en/function.is-null.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is null, false * otherwise. */ #[Pure] function is_null(mixed $value): bool {} /** * Finds whether a variable is a resource * @link https://php.net/manual/en/function.is-resource.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is a resource, * false otherwise. */ #[Pure] function is_resource(mixed $value): bool {} /** * Finds out whether a variable is a boolean * @link https://php.net/manual/en/function.is-bool.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is a boolean, * false otherwise. */ #[Pure] function is_bool(mixed $value): bool {} /** * Alias: * {@see is_int} * @link https://php.net/manual/en/function.is-long.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is an integer, * false otherwise. */ #[Pure] function is_long(mixed $value): bool {} /** * Finds whether the type of a variable is float * @link https://php.net/manual/en/function.is-float.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is a float, * false otherwise. */ #[Pure] function is_float(mixed $value): bool {} /** * Find whether the type of a variable is integer * @link https://php.net/manual/en/function.is-int.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is an integer, * false otherwise. */ #[Pure] function is_int(mixed $value): bool {} /** * Alias: * {@see is_int} * @link https://php.net/manual/en/function.is-integer.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is an integer, * false otherwise. */ #[Pure] function is_integer(mixed $value): bool {} /** * Alias: * {@see is_float} * @link https://php.net/manual/en/function.is-double.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is a float, * false otherwise. */ #[Pure] function is_double(mixed $value): bool {} /** * Alias: * {@see is_float} * @link https://php.net/manual/en/function.is-real.php * @param mixed $var

    * The variable being evaluated. *

    * @return bool true if var is a float, * false otherwise. */ #[Pure] #[Deprecated(since: '7.4')] function is_real(mixed $var): bool {} /** * Finds whether a variable is a number or a numeric string * @link https://php.net/manual/en/function.is-numeric.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is a number or a numeric * string, false otherwise. */ #[Pure] function is_numeric(mixed $value): bool {} /** * Find whether the type of a variable is string * @link https://php.net/manual/en/function.is-string.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is of type string, * false otherwise. */ #[Pure] function is_string(mixed $value): bool {} /** * Finds whether a variable is an array * @link https://php.net/manual/en/function.is-array.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is an array, * false otherwise. */ #[Pure] function is_array(mixed $value): bool {} /** * Finds whether a variable is an object * @link https://php.net/manual/en/function.is-object.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is an object, false otherwise.
    * Since 7.2.0 returns true for unserialized objects without a class definition (class of __PHP_Incomplete_Class). */ #[Pure] function is_object(mixed $value): bool {} /** * Finds whether a variable is a scalar * @link https://php.net/manual/en/function.is-scalar.php * @param mixed $value

    * The variable being evaluated. *

    * @return bool true if var is a scalar false * otherwise. */ #[Pure] function is_scalar(mixed $value): bool {} /** * Verify that the contents of a variable can be called as a function * @link https://php.net/manual/en/function.is-callable.php * @param callable|mixed $value

    * The value to check *

    * @param bool $syntax_only [optional]

    * If set to TRUE the function only verifies that * name might be a function or method. It will only * reject simple variables that are not strings, or an array that does * not have a valid structure to be used as a callback. The valid ones * are supposed to have only 2 entries, the first of which is an object * or a string, and the second a string. *

    * @param string &$callable_name [optional]

    * Receives the "callable name". In the example below it is * "someClass::someMethod". Note, however, that despite the implication * that someClass::SomeMethod() is a callable static method, this is not * the case. *

    * @return bool TRUE if $var is callable, FALSE * otherwise. */ function is_callable(mixed $value, bool $syntax_only = false, &$callable_name): bool {} /** * Verify that the contents of a variable is a countable value * @link https://secure.php.net/is_countable * * @param mixed $value The value to check * @return bool TRUE if $var is countable, FALSE otherwise. * @since 7.3 */ #[Pure] function is_countable(mixed $value): bool {} /** * Closes process file pointer * @link https://php.net/manual/en/function.pclose.php * @param resource $handle

    * The file pointer must be valid, and must have been returned by a * successful call to popen. *

    * @return int the termination status of the process that was run. In case of an error then -1 is returned. *

    * If PHP has been compiled with --enable-sigchild, the return value of this function is undefined. *

    */ function pclose($handle): int {} /** * Opens process file pointer * @link https://php.net/manual/en/function.popen.php * @param string $command

    * The command *

    * @param string $mode

    * The mode *

    * @return resource|false a file pointer identical to that returned by * fopen, except that it is unidirectional (may * only be used for reading or writing) and must be closed with * pclose. This pointer may be used with * fgets, fgetss, and * fwrite. *

    *

    * If an error occurs, returns false. */ function popen(string $command, string $mode) {} /** * Outputs a file * @link https://php.net/manual/en/function.readfile.php * @param string $filename

    * The filename being read. *

    * @param bool $use_include_path [optional]

    * You can use the optional second parameter and set it to true, if * you want to search for the file in the include_path, too. *

    * @param resource $context [optional]

    * A context stream resource. *

    * @return false|int the number of bytes read from the file, or FALSE on failure */ function readfile(string $filename, bool $use_include_path = false, $context): int|false {} /** * Rewind the position of a file pointer * @link https://php.net/manual/en/function.rewind.php * @param resource $stream

    * The file pointer must be valid, and must point to a file * successfully opened by fopen. *

    * @return bool true on success or false on failure. */ function rewind($stream): bool {} /** * Removes directory * @link https://php.net/manual/en/function.rmdir.php * @param string $directory

    * Path to the directory. *

    * @param resource $context [optional] * @return bool true on success or false on failure. */ function rmdir(string $directory, $context): bool {} /** * Changes the current umask * @link https://php.net/manual/en/function.umask.php * @param int|null $mask [optional]

    * The new umask. *

    * @return int umask without arguments simply returns the * current umask otherwise the old umask is returned. */ function umask(?int $mask): int {} /** * Closes an open file pointer * @link https://php.net/manual/en/function.fclose.php * @param resource $stream

    * The file pointer must be valid, and must point to a file successfully * opened by fopen or fsockopen. *

    * @return bool true on success or false on failure. */ function fclose($stream): bool {} /** * Tests for end-of-file on a file pointer * @link https://php.net/manual/en/function.feof.php * @param resource $stream The file pointer must be valid, and must point to a file successfully opened by fopen() or fsockopen() (and not yet closed by fclose()). * @return bool true if the file pointer is at EOF or an error occurs * (including socket timeout); otherwise returns false. */ #[Pure(true)] function feof($stream): bool {} /** * Gets character from file pointer * @link https://php.net/manual/en/function.fgetc.php * @param resource $stream The file pointer must be valid, and must point to a file successfully opened by fopen() or fsockopen() (and not yet closed by fclose()). * @return string|false a string containing a single character read from the file pointed * to by handle. Returns false on EOF. */ function fgetc($stream): string|false {} /** * Gets line from file pointer * @link https://php.net/manual/en/function.fgets.php * @param resource $stream The file pointer must be valid, and must point to a file successfully opened by fopen() or fsockopen() (and not yet closed by fclose()). * @param int|null $length [optional]

    * Reading ends when length - 1 bytes have been * read, on a newline (which is included in the return value), or on EOF * (whichever comes first). If no length is specified, it will keep * reading from the stream until it reaches the end of the line. *

    *

    * Until PHP 4.3.0, omitting it would assume 1024 as the line length. * If the majority of the lines in the file are all larger than 8KB, * it is more resource efficient for your script to specify the maximum * line length. *

    * @return string|false a string of up to length - 1 bytes read from * the file pointed to by handle. *

    *

    * If an error occurs, returns false. */ function fgets($stream, ?int $length): string|false {} /** * Gets line from file pointer and strip HTML tags * @link https://php.net/manual/en/function.fgetss.php * @param resource $handle The file pointer must be valid, and must point to a file successfully opened by fopen() or fsockopen() (and not yet closed by fclose()). * @param null|int $length [optional]

    * Length of the data to be retrieved. *

    * @param string $allowable_tags [optional]

    * You can use the optional third parameter to specify tags which should * not be stripped. *

    * @return string|false a string of up to length - 1 bytes read from * the file pointed to by handle, with all HTML and PHP * code stripped. *

    *

    * If an error occurs, returns false. * @removed 8.0 */ #[Deprecated(since: '7.3')] function fgetss($handle, ?int $length = null, $allowable_tags = null): false|string {} /** * Binary-safe file read * @link https://php.net/manual/en/function.fread.php * @param resource $stream &fs.file.pointer; * @param int $length

    * Up to length number of bytes read. *

    * @return string|false the read string or false on failure. */ function fread($stream, int $length): string|false {} /** * Opens file or URL * @link https://php.net/manual/en/function.fopen.php * @param string $filename

    * If filename is of the form "scheme://...", it * is assumed to be a URL and PHP will search for a protocol handler * (also known as a wrapper) for that scheme. If no wrappers for that * protocol are registered, PHP will emit a notice to help you track * potential problems in your script and then continue as though * filename specifies a regular file. *

    *

    * If PHP has decided that filename specifies * a local file, then it will try to open a stream on that file. * The file must be accessible to PHP, so you need to ensure that * the file access permissions allow this access. * If you have enabled "safemode", * or open_basedir further * restrictions may apply. *

    *

    * If PHP has decided that filename specifies * a registered protocol, and that protocol is registered as a * network URL, PHP will check to make sure that * allow_url_fopen is * enabled. If it is switched off, PHP will emit a warning and * the fopen call will fail. *

    *

    * The list of supported protocols can be found in . Some protocols (also referred to as * wrappers) support context * and/or "php.ini" options. Refer to the specific page for the * protocol in use for a list of options which can be set. (e.g. * "php.ini" value user_agent used by the * http wrapper). *

    *

    * On the Windows platform, be careful to escape any backslashes * used in the path to the file, or use forward slashes. *

    *
     * 
     * 
    * @param string $mode

    * The mode parameter specifies the type of access * you require to the stream. It may be any of the following: *

    * A list of possible modes for fopen * using mode * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    modeDescription
    'r' * Open for reading only; place the file pointer at the * beginning of the file. *
    'r+' * Open for reading and writing; place the file pointer at * the beginning of the file. *
    'w' * Open for writing only; place the file pointer at the * beginning of the file and truncate the file to zero length. * If the file does not exist, attempt to create it. *
    'w+' * Open for reading and writing; place the file pointer at * the beginning of the file and truncate the file to zero * length. If the file does not exist, attempt to create it. *
    'a' * Open for writing only; place the file pointer at the end of * the file. If the file does not exist, attempt to create it. *
    'a+' * Open for reading and writing; place the file pointer at * the end of the file. If the file does not exist, attempt to * create it. *
    'x' * Create and open for writing only; place the file pointer at the * beginning of the file. If the file already exists, the * fopen call will fail by returning false and * generating an error of level E_WARNING. If * the file does not exist, attempt to create it. This is equivalent * to specifying O_EXCL|O_CREAT flags for the * underlying open(2) system call. *
    'x+' * Create and open for reading and writing; place the file pointer at * the beginning of the file. If the file already exists, the * fopen call will fail by returning false and * generating an error of level E_WARNING. If * the file does not exist, attempt to create it. This is equivalent * to specifying O_EXCL|O_CREAT flags for the * underlying open(2) system call. *
    *

    *

    * Different operating system families have different line-ending * conventions. When you write a text file and want to insert a line * break, you need to use the correct line-ending character(s) for your * operating system. Unix based systems use \n as the * line ending character, Windows based systems use \r\n * as the line ending characters and Macintosh based systems use * \r as the line ending character. *

    *

    * If you use the wrong line ending characters when writing your files, you * might find that other applications that open those files will "look * funny". *

    *

    * Windows offers a text-mode translation flag ('t') * which will transparently translate \n to * \r\n when working with the file. In contrast, you * can also use 'b' to force binary mode, which will not * translate your data. To use these flags, specify either * 'b' or 't' as the last character * of the mode parameter. *

    *

    * The default translation mode depends on the SAPI and version of PHP that * you are using, so you are encouraged to always specify the appropriate * flag for portability reasons. You should use the 't' * mode if you are working with plain-text files and you use * \n to delimit your line endings in your script, but * expect your files to be readable with applications such as notepad. You * should use the 'b' in all other cases. *

    *

    * If you do not specify the 'b' flag when working with binary files, you * may experience strange problems with your data, including broken image * files and strange problems with \r\n characters. *

    *

    * For portability, it is strongly recommended that you always * use the 'b' flag when opening files with fopen. *

    *

    * Again, for portability, it is also strongly recommended that * you re-write code that uses or relies upon the 't' * mode so that it uses the correct line endings and * 'b' mode instead. *

    * @param bool $use_include_path [optional]

    * The optional third use_include_path parameter * can be set to '1' or true if you want to search for the file in the * include_path, too. *

    * @param resource $context [optional] * @return resource|false a file pointer resource on success, or false on error. */ function fopen(string $filename, string $mode, bool $use_include_path = false, $context) {} /** * Output all remaining data on a file pointer * @link https://php.net/manual/en/function.fpassthru.php * @param resource $stream The file pointer must be valid, and must point to a file successfully opened by fopen() or fsockopen() (and not yet closed by fclose()). * @return int|false If an error occurs, fpassthru returns * false. Otherwise, fpassthru returns * the number of characters read from handle * and passed through to the output. */ #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function fpassthru($stream) {} /** * Truncates a file to a given length * @link https://php.net/manual/en/function.ftruncate.php * @param resource $stream

    * The file pointer. *

    *

    * The handle must be open for writing. *

    * @param int $size

    * The size to truncate to. *

    *

    * If size is larger than the file it is extended * with null bytes. *

    *

    * If size is smaller than the extra data * will be lost. *

    * @return bool true on success or false on failure. */ function ftruncate($stream, int $size): bool {} /** * Gets information about a file using an open file pointer * @link https://php.net/manual/en/function.fstat.php * @param resource $stream &fs.file.pointer; * @return array|false an array with the statistics of the file; the format of the array * is described in detail on the stat manual page. */ #[Pure(true)] function fstat($stream): array|false {} /** * Seeks on a file pointer * @link https://php.net/manual/en/function.fseek.php * @param resource $stream &fs.file.pointer; * @param int $offset

    * The offset. *

    *

    * To move to a position before the end-of-file, you need to pass * a negative value in offset and * set whence * to SEEK_END. *

    * @param int $whence [optional]

    * whence values are: * SEEK_SET - Set position equal to offset bytes. * SEEK_CUR - Set position to current location plus offset. * SEEK_END - Set position to end-of-file plus offset. *

    *

    * If whence is not specified, it is assumed to be * SEEK_SET. *

    * @return int Upon success, returns 0; otherwise, returns -1. Note that seeking * past EOF is not considered an error. */ function fseek($stream, int $offset, int $whence = SEEK_SET): int {} /** * Returns the current position of the file read/write pointer * @link https://php.net/manual/en/function.ftell.php * @param resource $stream

    * The file pointer must be valid, and must point to a file successfully * opened by fopen or popen. * ftell gives undefined results for append-only streams * (opened with "a" flag). *

    * @return int|false the position of the file pointer referenced by * handle as an integer; i.e., its offset into the file stream. *

    *

    * If an error occurs, returns false. */ #[Pure(true)] function ftell($stream): int|false {} /** * Flushes the output to a file * @link https://php.net/manual/en/function.fflush.php * @param resource $stream The file pointer must be valid, and must point to a file successfully opened by fopen() or fsockopen() (and not yet closed by fclose()). * @return bool true on success or false on failure. */ function fflush($stream): bool {} /** * Sync file to storage. Similar to fflush() but blocks until OS buffers have flushed. * @param resource $stream * @since 8.1 */ function fsync($stream): bool {} /** * Sync file data only to storage. Similar to fsync but does not flush modified metadata. POSIX only, aliased to fsync on Win32. * @param resource $stream * @since 8.1 */ function fdatasync($stream): bool {} /** * Binary-safe file write * @link https://php.net/manual/en/function.fwrite.php * @param resource $stream &fs.file.pointer; * @param string $data

    * The string that is to be written. *

    * @param int|null $length [optional]

    * If the length argument is given, writing will * stop after length bytes have been written or * the end of string is reached, whichever comes * first. *

    *

    * Note that if the length argument is given, * then the magic_quotes_runtime * configuration option will be ignored and no slashes will be * stripped from string. *

    * @return int|false the number of bytes written, or FALSE on error. */ function fwrite($stream, string $data, ?int $length): int|false {} /** * Alias: * {@see fwrite} * @param resource $stream A file system pointer resource that is typically created using fopen(). * @param string $data

    * The string that is to be written. *

    * @param int|null $length [optional]

    * If the length argument is given, writing will * stop after length bytes have been written or * the end of string is reached, whichever comes * first. *

    *

    * Note that if the length argument is given, * then the magic_quotes_runtime * configuration option will be ignored and no slashes will be * stripped from string. *

    * @return int|false the number of bytes written, or FALSE on error. * @see fwrite() * @link https://php.net/manual/en/function.fputs.php * Binary-safe file write */ function fputs($stream, string $data, ?int $length): int|false {} /** * Attempts to create the directory specified by pathname. * @link https://php.net/manual/en/function.mkdir.php * @param string $directory

    * The directory path. *

    * @param int $permissions [optional]

    * The mode is 0777 by default, which means the widest possible * access. For more information on modes, read the details * on the chmod page. *

    *

    * mode is ignored on Windows. *

    *

    * Note that you probably want to specify the mode as an octal number, * which means it should have a leading zero. The mode is also modified * by the current umask, which you can change using * umask(). *

    * @param bool $recursive [optional]

    * Allows the creation of nested directories specified in the pathname. Default to false. *

    * @param resource $context [optional] * @return bool true on success or false on failure. */ function mkdir(string $directory, int $permissions = 0777, bool $recursive = false, $context): bool {} /** * Renames a file or directory * @link https://php.net/manual/en/function.rename.php * @param string $from

    *

    *

    * The old name. The wrapper used in oldname * must match the wrapper used in * newname. *

    * @param string $to

    * The new name. *

    * @param resource $context [optional] * @return bool true on success or false on failure. */ function rename(string $from, string $to, $context): bool {} /** * Copies file * @link https://php.net/manual/en/function.copy.php * @param string $from

    * Path to the source file. *

    * @param string $to

    * The destination path. If dest is a URL, the * copy operation may fail if the wrapper does not support overwriting of * existing files. *

    *

    * If the destination file already exists, it will be overwritten. *

    * @param resource $context [optional]

    * A valid context resource created with * stream_context_create. *

    * @return bool true on success or false on failure. */ function copy(string $from, string $to, $context): bool {} /** * Create file with unique file name * @link https://php.net/manual/en/function.tempnam.php * @param string $directory

    * The directory where the temporary filename will be created. *

    * @param string $prefix

    * The prefix of the generated temporary filename. *

    * Windows use only the first three characters of prefix. * @return string|false the new temporary filename, or false on * failure. */ function tempnam(string $directory, string $prefix): string|false {} /** * Creates a temporary file * @link https://php.net/manual/en/function.tmpfile.php * @return resource|false a file handle, similar to the one returned by * fopen, for the new file or false on failure. */ function tmpfile() {} /** * Reads entire file into an array * @link https://php.net/manual/en/function.file.php * @param string $filename

    * Path to the file. *

    * @param int $flags

    * The optional parameter flags can be one, or * more, of the following constants: *

      *
    • FILE_USE_INCLUDE_PATH - Search for the file in the include_path.
    • *
    • FILE_IGNORE_NEW_LINES - Omit newline at the end of each array element
    • *
    • FILE_SKIP_EMPTY_LINES - Skip empty lines
    • *
    *

    * @param resource $context [optional]

    * A context resource created with the * stream_context_create function. *

    * @return array|false the file in an array. Each element of the array corresponds to a * line in the file, with the newline still attached. Upon failure, * file returns false. *

    * Each line in the resulting array will include the line ending, unless * FILE_IGNORE_NEW_LINES is used, so you still need to * use rtrim if you do not want the line ending * present. *

    */ #[Pure(true)] function file(string $filename, int $flags = 0, $context): array|false {} /** * Reads entire file into a string * @link https://php.net/manual/en/function.file-get-contents.php * @param string $filename

    * Name of the file to read. *

    * @param bool $use_include_path [optional]

    * Note: As of PHP 5 the FILE_USE_INCLUDE_PATH constant can be * used to trigger include path search. *

    * @param resource $context [optional]

    * A valid context resource created with * stream_context_create. If you don't need to use a * custom context, you can skip this parameter by null. *

    * @param int $offset [optional]

    * The offset where the reading starts. *

    * @param int|null $length [optional]

    * Maximum length of data read. The default is to read until end * of file is reached. *

    * @return string|false The function returns the read data or false on failure. */ #[Pure(true)] function file_get_contents(string $filename, bool $use_include_path = false, $context, int $offset = 0, ?int $length): string|false {} /** * Write a string to a file * @link https://php.net/manual/en/function.file-put-contents.php * @param string $filename

    * Path to the file where to write the data. *

    * @param mixed $data

    * The data to write. Can be either a string, an * array or a stream resource. *

    *

    * If data is a stream resource, the * remaining buffer of that stream will be copied to the specified file. * This is similar with using stream_copy_to_stream. *

    *

    * You can also specify the data parameter as a single * dimension array. This is equivalent to * file_put_contents($filename, implode('', $array)). *

    * @param int $flags [optional]

    * The value of flags can be any combination of * the following flags (with some restrictions), joined with the binary OR * (|) operator. *

    *

    *

    * Available flags * * * * * * * * * * * * * * * * *
    FlagDescription
    * FILE_USE_INCLUDE_PATH * * Search for filename in the include directory. * See include_path for more * information. *
    * FILE_APPEND * * If file filename already exists, append * the data to the file instead of overwriting it. Mutually * exclusive with LOCK_EX since appends are atomic and thus there * is no reason to lock. *
    * LOCK_EX * * Acquire an exclusive lock on the file while proceeding to the * writing. Mutually exclusive with FILE_APPEND. *
    *

    * @param resource $context [optional]

    * A valid context resource created with * stream_context_create. *

    * @return int|false The function returns the number of bytes that were written to the file, or * false on failure. */ function file_put_contents(string $filename, mixed $data, int $flags = 0, $context): int|false {} FALSE if the server is terminating, giving the opportunity to the worker script to finish cleanly */ function frankenphp_handle_request(callable $callback): bool {} /** * Flushes all response data to the client and finishes the request. * This allows for time-consuming tasks to be performed without leaving the connection to the client open. * * Alias of fastcgi_finish_request. * * @link https://www.php.net/manual/en/function.fastcgi-finish-request.php * * @return bool Returns TRUE on success or FALSE on failure. */ function frankenphp_finish_request(): bool {} /** * Fetches all HTTP request headers from the current request. * * Alias of apache_request_headers. * * @link https://php.net/manual/en/function.apache-request-headers.php * * @return array An associative array of all the HTTP headers in the current request. */ function frankenphp_request_headers(): array {} /** * Fetches all HTTP response headers. * * Alias of apache_response_headers. * * @link https://php.net/manual/en/function.apache-response-headers.php * * @return array|false An array of all FrankenPHP response headers on success or FALSE on failure. */ function frankenphp_response_headers(): array|false {} * The PHP source to parse. *

    * @param int $flags *

    *

    * Valid flags: *

      *
    • * * TOKEN_PARSE - Recognises the ability to use * reserved words in specific contexts. *
    • *
    *

    * @return array An array of token identifiers. Each individual token identifier is either * a single character (i.e.: ;, ., * >, !, etc...), * or a three element array containing the token index in element 0, the string * content of the original token in element 1 and the line number in element 2. */ #[Pure] function token_get_all(string $code, #[PhpStormStubsElementAvailable(from: '7.0')] int $flags = 0): array {} /** * Get the symbolic name of a given PHP token * @link https://php.net/manual/en/function.token-name.php * @param int $id

    * The token value. *

    * @return string The symbolic name of the given token. */ #[Pure] function token_name(int $id): string {} define('TOKEN_PARSE', 1); define('T_REQUIRE_ONCE', 263); define('T_REQUIRE', 262); define('T_EVAL', 323); define('T_INCLUDE_ONCE', 261); define('T_INCLUDE', 260); define('T_LOGICAL_OR', 264); define('T_LOGICAL_XOR', 265); define('T_LOGICAL_AND', 266); define('T_PRINT', 267); define('T_YIELD', 268); define('T_DOUBLE_ARROW', 269); define('T_YIELD_FROM', 270); define('T_POW_EQUAL', 282); define('T_SR_EQUAL', 281); define('T_SL_EQUAL', 280); define('T_XOR_EQUAL', 279); define('T_OR_EQUAL', 278); define('T_AND_EQUAL', 277); define('T_MOD_EQUAL', 276); define('T_CONCAT_EQUAL', 275); define('T_DIV_EQUAL', 274); define('T_MUL_EQUAL', 273); define('T_MINUS_EQUAL', 272); define('T_PLUS_EQUAL', 271); /** * @since 7.4 */ define('T_COALESCE_EQUAL', 283); define('T_COALESCE', 284); define('T_BOOLEAN_OR', 285); define('T_BOOLEAN_AND', 286); define('T_SPACESHIP', 293); define('T_IS_NOT_IDENTICAL', 292); define('T_IS_IDENTICAL', 291); define('T_IS_NOT_EQUAL', 290); define('T_IS_EQUAL', 289); define('T_IS_GREATER_OR_EQUAL', 295); define('T_IS_SMALLER_OR_EQUAL', 294); define('T_SR', 297); define('T_SL', 296); define('T_INSTANCEOF', 298); define('T_UNSET_CAST', 305); define('T_BOOL_CAST', 304); define('T_OBJECT_CAST', 303); define('T_ARRAY_CAST', 302); define('T_STRING_CAST', 301); define('T_DOUBLE_CAST', 300); define('T_INT_CAST', 299); define('T_DEC', 389); define('T_INC', 388); define('T_POW', 306); define('T_CLONE', 307); define('T_NEW', 324); define('T_ELSEIF', 309); define('T_ELSE', 310); define('T_ENDIF', 327); define('T_PUBLIC', 362); define('T_PROTECTED', 361); define('T_PRIVATE', 360); define('T_FINAL', 359); define('T_ABSTRACT', 358); define('T_STATIC', 357); define('T_LNUMBER', 311); define('T_DNUMBER', 312); define('T_STRING', 313); define('T_VARIABLE', 317); define('T_INLINE_HTML', 318); define('T_ENCAPSED_AND_WHITESPACE', 319); define('T_CONSTANT_ENCAPSED_STRING', 320); define('T_STRING_VARNAME', 321); define('T_NUM_STRING', 322); define('T_EXIT', 325); define('T_IF', 326); define('T_ECHO', 328); define('T_DO', 329); define('T_WHILE', 330); define('T_ENDWHILE', 331); define('T_FOR', 332); define('T_ENDFOR', 333); define('T_FOREACH', 334); define('T_ENDFOREACH', 335); define('T_DECLARE', 336); define('T_ENDDECLARE', 337); define('T_AS', 338); define('T_SWITCH', 339); define('T_ENDSWITCH', 340); define('T_CASE', 341); define('T_DEFAULT', 342); define('T_MATCH', 343); define('T_BREAK', 344); define('T_CONTINUE', 345); define('T_GOTO', 346); define('T_FUNCTION', 347); define('T_CONST', 349); define('T_RETURN', 350); define('T_TRY', 351); define('T_CATCH', 352); define('T_FINALLY', 353); define('T_THROW', 258); define('T_USE', 354); define('T_INSTEADOF', 355); define('T_GLOBAL', 356); define('T_VAR', 364); define('T_UNSET', 365); define('T_ISSET', 366); define('T_EMPTY', 367); define('T_HALT_COMPILER', 368); define('T_CLASS', 369); define('T_TRAIT', 370); define('T_INTERFACE', 371); /** * @since 8.1 */ define('T_ENUM', 372); define('T_EXTENDS', 373); define('T_IMPLEMENTS', 374); define('T_OBJECT_OPERATOR', 390); define('T_LIST', 376); define('T_ARRAY', 377); define('T_CALLABLE', 378); define('T_LINE', 379); define('T_FILE', 380); define('T_DIR', 381); define('T_CLASS_C', 382); define('T_TRAIT_C', 383); define('T_METHOD_C', 384); define('T_FUNC_C', 385); define('T_NS_C', 386); /** * @since 8.4 */ define('T_PROPERTY_C', 350); /** * @since 8.0 */ define('T_ATTRIBUTE', 387); define('T_COMMENT', 392); define('T_DOC_COMMENT', 393); define('T_OPEN_TAG', 394); define('T_OPEN_TAG_WITH_ECHO', 395); define('T_CLOSE_TAG', 396); define('T_WHITESPACE', 397); define('T_START_HEREDOC', 398); define('T_END_HEREDOC', 399); define('T_DOLLAR_OPEN_CURLY_BRACES', 400); define('T_CURLY_OPEN', 401); define('T_PAAMAYIM_NEKUDOTAYIM', 402); define('T_NAMESPACE', 375); define('T_NS_SEPARATOR', 403); define('T_ELLIPSIS', 404); define('T_DOUBLE_COLON', 402); /** * @since 7.4 */ define('T_FN', 348); define('T_BAD_CHARACTER', 405); /** * @since 8.0 */ define('T_NAME_FULLY_QUALIFIED', 314); /** * @since 8.0 */ define('T_NAME_RELATIVE', 315); /** * @since 8.0 */ define('T_NAME_QUALIFIED', 316); /** * @since 8.0 */ define('T_NULLSAFE_OBJECT_OPERATOR', 391); /** * @since 8.1 */ define('T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG', 288); /** * @since 8.1 */ define('T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG', 287); /** * @since 8.1 */ define('T_READONLY', 363); /** * @removed 7.0 */ define('T_CHARACTER', 315); /** * @since 8.4 */ define('T_PRIVATE_SET', 327); /** * @since 8.4 */ define('T_PROTECTED_SET', 328); /** * @since 8.4 */ define('T_PUBLIC_SET', 329); * Retrieves information about files cached in the file cache * @link https://secure.php.net/manual/en/function.wincache-fcache-fileinfo.php * @param bool $summaryonly [optional] *

    Controls whether the returned array will contain information about individual * cache entries along with the file cache summary.

    * @return array|false Array of meta data about file cache or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • total_cache_uptime - total time in seconds that the file cache has been active
    • *
    • total_file_count - total number of files that are currently in the file cache
    • *
    • total_hit_count - number of times the files have been served from the file cache
    • *
    • total_miss_count - number of times the files have not been found in the file cache
    • *
    • file_entries - an array that contains the information about all the cached files: *
        *
      • file_name - absolute file name of the cached file
      • *
      • add_time - time in seconds since the file has been added to the file cache
      • *
      • use_time - time in seconds since the file has been accessed in the file cache
      • *
      • last_check - time in seconds since the file has been checked for modifications
      • *
      • hit_count - number of times the file has been served from the cache
      • *
      • file_size - size of the cached file in bytes
      • *
    • *

    */ function wincache_fcache_fileinfo($summaryonly = false) {} /** * (PHP 5.2+; PECL wincache >= 1.0.0)
    * Retrieves information about memory usage by file cache. * @link https://secure.php.net/manual/en/function.wincache-fcache-meminfo.php * @return array|false Array of meta data about file cache memory usage or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • memory_total - amount of memory in bytes allocated for the file cache
    • *
    • memory_free - amount of free memory in bytes available for the file cache
    • *
    • num_used_blks - number of memory blocks used by the file cache
    • *
    • num_free_blks - number of free memory blocks available for the file cache
    • *
    • memory_overhead - amount of memory in bytes used for the file cache internal structures
    • *

    */ function wincache_fcache_meminfo() {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Obtains an exclusive lock on a given key. *

    The execution of the current script will be blocked until the lock can be * obtained. Once the lock is obtained, the other scripts that try to request the * lock by using the same key will be blocked, until the current script releases * the lock by using wincache_unlock().

    * @link https://secure.php.net/manual/en/function.wincache-lock.php * @param string $key Name of the key in the cache to get the lock on. * @param bool $isglobal [optional] *

    Controls whether the scope of the lock is system-wide or local. Local locks * are scoped to the application pool in IIS FastCGI case or to all php processes * that have the same parent process identifier.

    * @return bool Returns TRUE on success or FALSE on failure. */ function wincache_lock($key, $isglobal = false) {} /** * (PHP 5.2+; PECL wincache >= 1.0.0)
    * Retrieves information about opcode cache content and its usage * @link https://secure.php.net/manual/en/function.wincache-ocache-fileinfo.php * @param bool $summaryonly [optional] *

    Controls whether the returned array will contain information about individual * cache entries along with the opcode cache summary.

    * @return array|false Array of meta data about opcode cache or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • total_cache_uptime - total time in seconds that the opcode cache has been active
    • *
    • total_file_count - total number of files that are currently in the opcode cache
    • *
    • total_hit_count - number of times the compiled opcode have been served from the cache
    • *
    • total_miss_count - number of times the compiled opcode have not been found in the cache
    • *
    • is_local_cache - true is the cache metadata is for a local cache instance, false * if the metadata is for the global cache
    • *
    • file_entries - an array that contains the information about all the cached files: *
        *
      • file_name - absolute file name of the cached file
      • *
      • add_time - time in seconds since the file has been added to the opcode cache
      • *
      • use_time - time in seconds since the file has been accessed in the opcode cache
      • *
      • last_check - time in seconds since the file has been checked for modifications
      • *
      • hit_count - number of times the file has been served from the cache
      • *
      • function_count - number of functions in the cached file
      • *
      • class_count - number of classes in the cached file
      • *
    • *

    */ function wincache_ocache_fileinfo($summaryonly = false) {} /** * (PHP 5.2+; PECL wincache >= 1.0.0)
    * Retrieves information about memory usage by opcode cache. * @link https://secure.php.net/manual/en/function.wincache-ocache-meminfo.php * @return array|false Array of meta data about opcode cache memory usage or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • memory_total - amount of memory in bytes allocated for the opcode cache
    • *
    • memory_free - amount of free memory in bytes available for the opcode cache
    • *
    • num_used_blks - number of memory blocks used by the opcode cache
    • *
    • num_free_blks - number of free memory blocks available for the opcode cache
    • *
    • memory_overhead - amount of memory in bytes used for the opcode cache internal structures
    • *

    */ function wincache_ocache_meminfo() {} /** * (PHP 5.2+; PECL wincache >= 1.0.0)
    * Refreshes the cache entries for the files, whose names were passed in the input argument. *

    If no argument is specified then refreshes all the entries in the cache.

    * @link https://secure.php.net/manual/en/function.wincache-refresh-if-changed.php * @param array $files [optional] *

    An array of file names for files that need to be refreshed. An absolute * or relative file paths can be used.

    * @return bool Returns TRUE on success or FALSE on failure. */ function wincache_refresh_if_changed(array $files) {} /** * (PHP 5.2+; PECL wincache >= 1.0.0)
    * Retrieves information about cached mappings between relative file paths and * corresponding absolute file paths. * @link https://secure.php.net/manual/en/function.wincache-rplist-fileinfo.php * @return array|false Array of meta data about the resolve file path cache or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • total_file_count - total number of file path mappings stored in the cache
    • *
    • rplist_entries - an array that contains the information about all the cached file paths: *
        *
      • resolve_path - path to a file
      • *
      • subkey_data - corresponding absolute path to a file
      • *
    • *

    */ function wincache_rplist_fileinfo() {} /** * (PHP 5.2+; PECL wincache >= 1.0.0)
    * Retrieves information about memory usage by resolve file path cache. * @link https://secure.php.net/manual/en/function.wincache-rplist-meminfo.php * @return array|false Array of meta data that describes memory usage by resolve file path cache. or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • memory_total - amount of memory in bytes allocated for the resolve file path cache
    • *
    • memory_free - amount of free memory in bytes available for the resolve file path cache
    • *
    • num_used_blks - number of memory blocks used by the resolve file path cache
    • *
    • num_free_blks - number of free memory blocks available for the resolve file path cache
    • *
    • memory_overhead - amount of memory in bytes used for the internal structures of resolve file path cache
    • *

    */ function wincache_rplist_meminfo() {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Retrieves information about session cache content and its usage. * @link https://secure.php.net/manual/en/function.wincache-scache-info.php * @param bool $summaryonly [optional] *

    Controls whether the returned array will contain information about individual * cache entries along with the session cache summary.

    * @return array|false Array of meta data about session cache or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • total_cache_uptime - total time in seconds that the session cache has been active
    • *
    • total_item_count - total number of elements that are currently in the session cache
    • *
    • is_local_cache - true is the cache metadata is for a local cache instance, false * if the metadata is for the global cache
    • *
    • total_hit_count - number of times the data has been served from the cache
    • *
    • total_miss_count - number of times the data has not been found in the cache
    • *
    • scache_entries - an array that contains the information about all the cached items: *
        *
      • key_name - name of the key which is used to store the data
      • *
      • value_type - type of value stored by the key
      • *
      • use_time - time in seconds since the file has been accessed in the opcode cache
      • *
      • last_check - time in seconds since the file has been checked for modifications
      • *
      • ttl_seconds - time remaining for the data to live in the cache, 0 meaning infinite
      • *
      • age_seconds - time elapsed from the time data has been added in the cache
      • *
      • hitcount - number of times data has been served from the cache
      • *
    • *

    */ function wincache_scache_info($summaryonly = false) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Retrieves information about memory usage by session cache. * @link https://secure.php.net/manual/en/function.wincache-scache-meminfo.php * @return array|false Array of meta data about session cache memory usage or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • memory_total - amount of memory in bytes allocated for the session cache
    • *
    • memory_free - amount of free memory in bytes available for the session cache
    • *
    • num_used_blks - number of memory blocks used by the session cache
    • *
    • num_free_blks - number of free memory blocks available for the session cache
    • *
    • memory_overhead - amount of memory in bytes used for the session cache internal structures
    • *

    */ function wincache_scache_meminfo() {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Adds a variable in user cache, only if this variable doesn't already exist in the cache. *

    The added variable remains in the user cache unless its time to live expires * or it is deleted by using wincache_ucache_delete() or wincache_ucache_clear() functions.

    * @link https://secure.php.net/manual/en/function.wincache-ucache-add.php * @param string $key

    Store the variable using this key name. If a variable with * same key is already present the function will fail and return FALSE. key is case * sensitive. To override the value even if key is present use wincache_ucache_set() * function instad. key can also take array of name => value pairs where names will * be used as keys. This can be used to add multiple values in the cache in one * operation, thus avoiding race condition.

    * @param mixed $value

    Value of a variable to store. Value supports all data * types except resources, such as file handles. This parameter is ignored if * first argument is an array. A general guidance is to pass NULL as value while * using array as key.

    * @param int $ttl [optional] *

    Time for the variable to live in the cache in seconds. After the value * specified in ttl has passed the stored variable will be deleted from the * cache. This parameter takes a default value of 0 which means the variable * will stay in the cache unless explicitly deleted by using wincache_ucache_delete() * or wincache_ucache_clear() functions.

    * @return bool If key is string, the function returns TRUE on success and FALSE on failure. *

    If key is an array, the function returns: *

      *
    • If all the name => value pairs in the array can be set, function returns an empty array;
    • *
    • If all the name => value pairs in the array cannot be set, function returns FALSE;
    • *
    • If some can be set while others cannot, function returns an array with name=>value pair * for which the addition failed in the user cache.
    • *

    */ function wincache_ucache_add($key, $value, $ttl = 0) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Compares the variable associated with the key with old_value * and if it matches then assigns the new_value to it. * @link https://secure.php.net/manual/en/function.wincache-ucache-cas.php * @param string $key The key that is used to store the variable in the cache. key is case sensitive. * @param int $old_value Old value of the variable pointed by key in the user cache. * The value should be of type long, otherwise the function returns FALSE. * @param int $new_value New value which will get assigned to variable pointer by key * if a match is found. The value should be of type long, otherwise the function returns FALSE. * @return bool Returns TRUE on success or FALSE on failure. */ function wincache_ucache_cas($key, $old_value, $new_value) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Clears/deletes all the values stored in the user cache. * @link https://secure.php.net/manual/en/function.wincache-ucache-clear.php * @return bool Returns TRUE on success or FALSE on failure. */ function wincache_ucache_clear() {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Decrements the value associated with the key by 1 or as specified by dec_by. * @link https://secure.php.net/manual/en/function.wincache-ucache-dec.php * @param string $key

    The key that was used to store the variable in the cache. * key is case sensitive.

    * @param int $dec_by

    The value by which the variable associated with the key will * get decremented. If the argument is a floating point number it will be truncated * to nearest integer. The variable associated with the key should be of type long, * otherwise the function fails and returns FALSE.

    * @param bool|null &$success [optional] *

    Will be set to TRUE on success and FALSE on failure.

    * @return int|false Returns the decremented value on success and FALSE on failure. */ function wincache_ucache_dec($key, $dec_by = 1, &$success) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Deletes the elements in the user cache pointed by key. * @link https://secure.php.net/manual/en/function.wincache-ucache-delete.php * @param string|string[] $key

    The key that was used to store the variable in the cache. * key is case sensitive. key can be an array of keys.

    * @return bool Returns TRUE on success or FALSE on failure. *

    If key is an array then the function returns FALSE if every element of * the array fails to get deleted from the user cache, otherwise returns an * array which consists of all the keys that are deleted.

    */ function wincache_ucache_delete($key) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Checks if a variable with the key exists in the user cache or not. * @link https://secure.php.net/manual/en/function.wincache-ucache-exists.php * @param string $key The key that was used to store the variable in the cache. key is case sensitive. * @return bool Returns TRUE if variable with the key exitsts, otherwise returns FALSE. */ function wincache_ucache_exists($key) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Gets a variable stored in the user cache. * @link https://secure.php.net/manual/en/function.wincache-ucache-get.php * @param string|string[] $key

    The key that was used to store the variable in the cache. * key is case sensitive. key can be an array of keys. In this case the return * value will be an array of values of each element in the key array.

    * @param bool|null &$success [optional] *

    Will be set to TRUE on success and FALSE on failure.

    * @return mixed

    If key is a string, the function returns the value of the variable * stored with that key. The success is set to TRUE on success and to FALSE on failure.

    *

    The key is an array, the parameter success is always set to TRUE. The returned array * (name => value pairs) will contain only those name => value pairs for which the get * operation in user cache was successful. If none of the keys in the key array finds a * match in the user cache an empty array will be returned.

    */ function wincache_ucache_get($key, &$success) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Increments the value associated with the key by 1 or as specified by inc_by. * @link https://secure.php.net/manual/en/function.wincache-ucache-inc.php * @param string $key

    The key that was used to store the variable in the cache. * key is case sensitive.

    * @param int $inc_by

    The value by which the variable associated with the key will * get incremented. If the argument is a floating point number it will be truncated * to nearest integer. The variable associated with the key should be of type long, * otherwise the function fails and returns FALSE.

    * @param bool|null &$success [optional] *

    Will be set to TRUE on success and FALSE on failure.

    * @return int|false Returns the incremented value on success and FALSE on failure. */ function wincache_ucache_inc($key, $inc_by = 1, &$success) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Retrieves information about data stored in the user cache. * @link https://secure.php.net/manual/en/function.wincache-ucache-info.php * @param bool $summaryonly [optional] *

    Controls whether the returned array will contain information about * individual cache entries along with the user cache summary.

    * @param null|string $key [optional] *

    The key of an entry in the user cache. If specified then the returned array * will contain information only about that cache entry. If not specified and * summaryonly is set to false then the returned array will contain information * about all entries in the cache.

    * @return array|false Array of meta data about user cache or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • total_cache_uptime - total time in seconds that the user cache has been active
    • *
    • total_item_count - total number of elements that are currently in the user cache
    • *
    • is_local_cache - true is the cache metadata is for a local cache instance, false * if the metadata is for the global cache
    • *
    • total_hit_count - number of times the data has been served from the cache
    • *
    • total_miss_count - number of times the data has not been found in the cache
    • *
    • ucache_entries - an array that contains the information about all the cached items: *
        *
      • key_name - name of the key which is used to store the data
      • *
      • value_type - type of value stored by the key
      • *
      • use_time - time in seconds since the file has been accessed in the opcode cache
      • *
      • last_check - time in seconds since the file has been checked for modifications
      • *
      • is_session - indicates if the data is a session variable
      • *
      • ttl_seconds - time remaining for the data to live in the cache, 0 meaning infinite
      • *
      • age_seconds - time elapsed from the time data has been added in the cache
      • *
      • hitcount - number of times data has been served from the cache
      • *
    • *

    */ function wincache_ucache_info(bool $summaryonly = false, $key = null) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Retrieves information about memory usage by user cache. * @link https://secure.php.net/manual/en/function.wincache-ucache-meminfo.php * @return array|false Array of meta data about user cache memory usage or FALSE on failure *

    The array returned by this function contains the following elements: *

      *
    • memory_total - amount of memory in bytes allocated for the user cache
    • *
    • memory_free - amount of free memory in bytes available for the user cache
    • *
    • num_used_blks - number of memory blocks used by the user cache
    • *
    • num_free_blks - number of free memory blocks available for the user cache
    • *
    • memory_overhead - amount of memory in bytes used for the user cache internal structures
    • *

    */ function wincache_ucache_meminfo() {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Adds a variable in user cache and overwrites a variable if it already exists in the cache. *

    The added or updated variable remains in the user cache unless its time to * live expires or it is deleted by using wincache_ucache_delete() or * wincache_ucache_clear() functions.

    * @link https://secure.php.net/manual/en/function.wincache-ucache-set.php * @param string|string[] $key

    * Store the variable using this key name. If a variable with same key is already * present the function will overwrite the previous value with the new one. key * is case sensitive. key can also take array of name => value pairs where * names will be used as keys. This can be used to add multiple values in the * cache in one operation, thus avoiding race condition.

    * @param mixed $value

    * Value of a variable to store. Value supports all data types except resources, * such as file handles. This parameter is ignored if first argument is an array. * A general guidance is to pass NULL as value while using array as key.

    * @param int $ttl [optional]

    * Time for the variable to live in the cache in seconds. After the value specified * in ttl has passed the stored variable will be deleted from the cache. This * parameter takes a default value of 0 which means the variable will stay in the * cache unless explicitly deleted by using wincache_ucache_delete() or * wincache_ucache_clear() functions.

    * @return bool

    * If key is string, the function returns TRUE on success and FALSE on failure.

    *

    If key is an array, the function returns: *

      *
    • If all the name => value pairs in the array can be set, function * returns an empty array;
    • *
    • If all the name => value pairs in the array cannot be set, function * returns FALSE;
    • *
    • If some can be set while others cannot, function returns an array with * name=>value pair for which the addition failed in the user cache.
    • *

    */ function wincache_ucache_set($key, $value, $ttl = 0) {} /** * (PHP 5.2+; PECL wincache >= 1.1.0)
    * Releases an exclusive lock that was obtained on a given key by using wincache_lock(). *

    If any other process was blocked waiting for the lock on this key, that process will be able to obtain the lock.

    * @link https://secure.php.net/manual/en/function.wincache-unlock.php * @param string $key Name of the key in the cache to release the lock on. * @return bool Returns TRUE on success or FALSE on failure. */ function wincache_unlock($key) {} * Undocumented template parameter *

    * @return mixed */ function msgpack_unserialize($str, $object = null) {} /** * Alias of msgpack_serialize * @param mixed $value * @return string */ function msgpack_pack($value) {} /** * Alias of msgpack_unserialize * @param string $str * @param null|array|string|object $object

    * Undocumented template parameter *

    * @return mixed */ function msgpack_unpack($str, $object = null) {} class MessagePack { public const OPT_PHPONLY = -1001; /** * @param $opt [optional] */ public function __construct($opt) {} public function setOption($option, $value) {} public function pack($value) {} /** * @param $str * @param $object [optional] */ public function unpack($str, $object) {} public function unpacker() {} } class MessagePackUnpacker { /** * @param $opt [optional] */ public function __construct($opt) {} public function __destruct() {} public function setOption($option, $value) {} public function feed($str) {} /** * @param $str [optional] * @param $offset [optional] */ public function execute($str, &$offset) {} /** * @param $object [optional] */ public function data($object) {} public function reset() {} } * The imported style sheet as a DOMDocument or * SimpleXMLElement object. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function importStylesheet(#[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $stylesheet): bool {} /** * Transform to a DOMDocument * @link https://php.net/manual/en/xsltprocessor.transformtodoc.php * @param object $document The DOMDocument or SimpleXMLElement or libxml-compatible object to be transformed. * @param string|null $returnClass * @return DOMDocument|false The resulting DOMDocument or FALSE on error. */ #[TentativeType] public function transformToDoc( #[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $document, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $returnClass = null ): object|false {} /** * Transform to URI * @link https://php.net/manual/en/xsltprocessor.transformtouri.php * @param DOMDocument|SimpleXMLElement $document

    * The document to transform. *

    * @param string $uri

    * The target URI for the transformation. *

    * @return int the number of bytes written or FALSE if an error occurred. */ #[TentativeType] public function transformToUri( #[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $document, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $uri ): int {} /** * Transform to XML * @link https://php.net/manual/en/xsltprocessor.transformtoxml.php * @param DOMDocument|SimpleXMLElement $document

    * The transformed document. *

    * @return string|false|null The result of the transformation as a string or FALSE on error. */ #[TentativeType] public function transformToXml(#[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $document): string|false|null {} /** * Set value for a parameter * @link https://php.net/manual/en/xsltprocessor.setparameter.php * @param string $namespace

    * The namespace URI of the XSLT parameter. *

    * @param string $name

    * The local name of the XSLT parameter. *

    * @param string $value

    * The new value of the XSLT parameter. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setParameter( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'array|string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $value = null ):bool {} /** * Get value of a parameter * @link https://php.net/manual/en/xsltprocessor.getparameter.php * @param string $namespace

    * The namespace URI of the XSLT parameter. *

    * @param string $name

    * The local name of the XSLT parameter. *

    * @return string|false The value of the parameter (as a string), or FALSE if it's not set. */ #[TentativeType] public function getParameter( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name ): string|false {} /** * Remove parameter * @link https://php.net/manual/en/xsltprocessor.removeparameter.php * @param string $namespace

    * The namespace URI of the XSLT parameter. *

    * @param string $name

    * The local name of the XSLT parameter. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function removeParameter( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name ): bool {} /** * Determine if PHP has EXSLT support * @link https://php.net/manual/en/xsltprocessor.hasexsltsupport.php * @return bool TRUE on success or FALSE on failure. * @since 5.0.4 */ #[TentativeType] public function hasExsltSupport(): bool {} /** * Enables the ability to use PHP functions as XSLT functions * @link https://php.net/manual/en/xsltprocessor.registerphpfunctions.php * @param array|string|null $functions [optional]

    * Use this parameter to only allow certain functions to be called from * XSLT. *

    *

    * This parameter can be either a string (a function name) or an array of * functions. *

    * @return void No value is returned. * @since 5.0.4 */ #[TentativeType] public function registerPHPFunctions(#[LanguageLevelTypeAware(['8.0' => 'array|string|null'], default: '')] $functions = null): void {} /** * Sets profiling output file * @link https://php.net/manual/en/xsltprocessor.setprofiling.php * @param string $filename

    * Path to the file to dump profiling information. *

    * @return bool TRUE on success or FALSE on failure. */ public function setProfiling(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $filename) {} /** * Set security preferences * @link https://php.net/manual/en/xsltprocessor.setsecurityprefs.php * @param int $preferences * @return int * @since 5.4 */ #[TentativeType] public function setSecurityPrefs(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $preferences): int {} /** * Get security preferences * @link https://php.net/manual/en/xsltprocessor.getsecurityprefs.php * @return int * @since 5.4 */ #[TentativeType] public function getSecurityPrefs(): int {} } define('XSL_CLONE_AUTO', 0); define('XSL_CLONE_NEVER', -1); define('XSL_CLONE_ALWAYS', 1); /** @link https://php.net/manual/en/xsl.constants.php */ define('XSL_SECPREF_NONE', 0); /** @link https://php.net/manual/en/xsl.constants.php */ define('XSL_SECPREF_READ_FILE', 2); /** @link https://php.net/manual/en/xsl.constants.php */ define('XSL_SECPREF_WRITE_FILE', 4); /** @link https://php.net/manual/en/xsl.constants.php */ define('XSL_SECPREF_CREATE_DIRECTORY', 8); /** @link https://php.net/manual/en/xsl.constants.php */ define('XSL_SECPREF_READ_NETWORK', 16); /** @link https://php.net/manual/en/xsl.constants.php */ define('XSL_SECPREF_WRITE_NETWORK', 32); /** @link https://php.net/manual/en/xsl.constants.php */ define('XSL_SECPREF_DEFAULT', 44); /** * libxslt version like 10117. Available as of PHP 5.1.2. * @link https://php.net/manual/en/xsl.constants.php */ define('LIBXSLT_VERSION', 10128); /** * libxslt version like 1.1.17. Available as of PHP 5.1.2. * @link https://php.net/manual/en/xsl.constants.php */ define('LIBXSLT_DOTTED_VERSION', "1.1.28"); /** * libexslt version like 813. Available as of PHP 5.1.2. * @link https://php.net/manual/en/xsl.constants.php */ define('LIBEXSLT_VERSION', 817); /** * libexslt version like 1.1.17. Available as of PHP 5.1.2. * @link https://php.net/manual/en/xsl.constants.php */ define('LIBEXSLT_DOTTED_VERSION', "1.1.28"); // End of xsl v.0.1 * The connection_string can be empty to use all default parameters, or it * can contain one or more parameter settings separated by whitespace. * Each parameter setting is in the form keyword = value. Spaces around * the equal sign are optional. To write an empty value or a value * containing spaces, surround it with single quotes, e.g., keyword = * 'a value'. Single quotes and backslashes within the value must be * escaped with a backslash, i.e., \' and \\. *

    *

    * The currently recognized parameter keywords are: * host, hostaddr, port, * dbname (defaults to value of user), * user, * password, connect_timeout, * options, tty (ignored), sslmode, * requiressl (deprecated in favor of sslmode), and * service. Which of these arguments exist depends * on your PostgreSQL version. *

    *

    * The options parameter can be used to set command line parameters * to be invoked by the server. *

    * @param int $flags

    * If PGSQL_CONNECT_FORCE_NEW is passed, then a new connection * is created, even if the connection_string is identical to * an existing connection. *

    * @return resource|false PostgreSQL connection resource on success, FALSE on failure. */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|false'], default: 'resource|false')] function pg_connect( string $connection_string, int $flags = 0, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $host = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $port = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $options = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $tty = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $dbname = '', ) {} /** * Open a persistent PostgreSQL connection * @link https://php.net/manual/en/function.pg-pconnect.php * @param string $connection_string

    * The connection_string can be empty to use all default parameters, or it * can contain one or more parameter settings separated by whitespace. * Each parameter setting is in the form keyword = value. Spaces around * the equal sign are optional. To write an empty value or a value * containing spaces, surround it with single quotes, e.g., keyword = * 'a value'. Single quotes and backslashes within the value must be * escaped with a backslash, i.e., \' and \\. *

    *

    * The currently recognized parameter keywords are: * host, hostaddr, port, * dbname, user, * password, connect_timeout, * options, tty (ignored), sslmode, * requiressl (deprecated in favor of sslmode), and * service. Which of these arguments exist depends * on your PostgreSQL version. *

    * @param int $flags

    * If PGSQL_CONNECT_FORCE_NEW is passed, then a new connection * is created, even if the connection_string is identical to * an existing connection. *

    * @return resource|false PostgreSQL connection resource on success, FALSE on failure. */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|false'], default: 'resource|false')] function pg_pconnect( string $connection_string, #[PhpStormStubsElementAvailable(from: '8.0')] int $flags = 0, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $host = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $port = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $options = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $tty = '', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $dbname = '', ) {} /** * Closes a PostgreSQL connection * @link https://php.net/manual/en/function.pg-close.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    */ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function pg_close(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null) {} /** * Poll the status of an in-progress asynchronous PostgreSQL connection attempt. * @link https://php.net/manual/en/function.pg-connect-poll.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @return int PGSQL_POLLING_FAILED, PGSQL_POLLING_READING, PGSQL_POLLING_WRITING, * PGSQL_POLLING_OK, or PGSQL_POLLING_ACTIVE. * @since 5.6 */ function pg_connect_poll( #[PhpStormStubsElementAvailable(from: '5.6', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection ): int {} /** * Get connection status * @link https://php.net/manual/en/function.pg-connection-status.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @return int PGSQL_CONNECTION_OK or * PGSQL_CONNECTION_BAD. */ function pg_connection_status(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection): int {} /** * Get connection is busy or not * @link https://php.net/manual/en/function.pg-connection-busy.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @return bool TRUE if the connection is busy, FALSE otherwise. */ function pg_connection_busy(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection): bool {} /** * Reset connection (reconnect) * @link https://php.net/manual/en/function.pg-connection-reset.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @return bool TRUE on success or FALSE on failure. */ function pg_connection_reset(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection): bool {} /** * Get a read only handle to the socket underlying a PostgreSQL connection * @link https://php.net/manual/en/function.pg-socket.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @return resource|false A socket resource on success or FALSE on failure. * @since 5.6 */ function pg_socket(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection) {} /** * Returns the host name associated with the connection * @link https://php.net/manual/en/function.pg-host.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return string|false A string containing the name of the host the * connection is to, or FALSE on error. */ function pg_host(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): string {} /** * Get the database name * @link https://php.net/manual/en/function.pg-dbname.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return string|false A string containing the name of the database the * connection is to, or FALSE on error. */ function pg_dbname(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): string {} /** * Return the port number associated with the connection * @link https://php.net/manual/en/function.pg-port.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return string A string containing the port number of the database server the connection is to, or empty string on error. */ function pg_port(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): string {} /** * Return the TTY name associated with the connection * @link https://php.net/manual/en/function.pg-tty.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return string A string containing the debug TTY of * the connection, or FALSE on error. */ function pg_tty(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): string {} /** * Get the options associated with the connection * @link https://php.net/manual/en/function.pg-options.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return string A string containing the connection * options, or FALSE on error. */ function pg_options(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): string {} /** * Returns an array with client, protocol and server version (when available) * @link https://php.net/manual/en/function.pg-version.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return array an array with client, protocol * and server keys and values (if available). Returns * FALSE on error or invalid connection. */ #[ArrayShape(["client" => "string", "protocol" => "int", "server" => "string"])] function pg_version(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): array {} /** * Ping database connection * @link https://php.net/manual/en/function.pg-ping.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return bool TRUE on success or FALSE on failure. */ function pg_ping(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): bool {} /** * Looks up a current parameter setting of the server. * @link https://php.net/manual/en/function.pg-parameter-status.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $name [optional]

    * Possible param_name values include server_version, * server_encoding, client_encoding, * is_superuser, session_authorization, * DateStyle, TimeZone, and * integer_datetimes. *

    * @return string|false A string containing the value of the parameter, FALSE on failure or invalid * param_name. */ function pg_parameter_status(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $name): string|false {} /** * Returns the current in-transaction status of the server. * @link https://php.net/manual/en/function.pg-transaction-status.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @return int The status can be PGSQL_TRANSACTION_IDLE (currently idle), * PGSQL_TRANSACTION_ACTIVE (a command is in progress), * PGSQL_TRANSACTION_INTRANS (idle, in a valid transaction block), * or PGSQL_TRANSACTION_INERROR (idle, in a failed transaction block). * PGSQL_TRANSACTION_UNKNOWN is reported if the connection is bad. * PGSQL_TRANSACTION_ACTIVE is reported only when a query * has been sent to the server and not yet completed. */ function pg_transaction_status(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection): int {} /** * Execute a query * @link https://php.net/manual/en/function.pg-query.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $query [optional]

    * The SQL statement or statements to be executed. When multiple statements are passed to the function, * they are automatically executed as one transaction, unless there are explicit BEGIN/COMMIT commands * included in the query string. However, using multiple transactions in one function call is not recommended. *

    *

    * String interpolation of user-supplied data is extremely dangerous and is * likely to lead to SQL * injection vulnerabilities. In most cases * pg_query_params should be preferred, passing * user-supplied values as parameters rather than substituting them into * the query string. *

    *

    * Any user-supplied data substituted directly into a query string should * be properly escaped. *

    * @return resource|false A query result resource on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result|false'], default: 'resource|false')] function pg_query( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $query ) {} /** * Submits a command to the server and waits for the result, with the ability to pass parameters separately from the SQL command text. * @link https://php.net/manual/en/function.pg-query-params.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $query

    * The parameterized SQL statement. Must contain only a single statement. * (multiple statements separated by semi-colons are not allowed.) If any parameters * are used, they are referred to as $1, $2, etc. *

    *

    * User-supplied values should always be passed as parameters, not * interpolated into the query string, where they form possible * SQL injection * attack vectors and introduce bugs when handling data containing quotes. * If for some reason you cannot use a parameter, ensure that interpolated * values are properly escaped. *

    * @param array $params [optional]

    * An array of parameter values to substitute for the $1, $2, etc. placeholders * in the original prepared query string. The number of elements in the array * must match the number of placeholders. *

    *

    * Values intended for bytea fields are not supported as * parameters. Use pg_escape_bytea instead, or use the * large object functions. *

    * @return resource|false A query result resource on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result|false'], default: 'resource|false')] function pg_query_params( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $query = '', #[PhpStormStubsElementAvailable(from: '8.0')] $query, array $params ) {} /** * Submits a request to create a prepared statement with the * given parameters, and waits for completion. * @link https://php.net/manual/en/function.pg-prepare.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $statement_name

    * The name to give the prepared statement. Must be unique per-connection. If * "" is specified, then an unnamed statement is created, overwriting any * previously defined unnamed statement. *

    * @param string $query [optional]

    * The parameterized SQL statement. Must contain only a single statement. * (multiple statements separated by semi-colons are not allowed.) If any parameters * are used, they are referred to as $1, $2, etc. *

    * @return resource|false A query result resource on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result|false'], default: 'resource|false')] function pg_prepare( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $statement_name = '', #[PhpStormStubsElementAvailable(from: '8.0')] string $statement_name, string $query ) {} /** * Sends a request to execute a prepared statement with given parameters, and waits for the result. * @link https://php.net/manual/en/function.pg-execute.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $statement_name

    * The name of the prepared statement to execute. if * "" is specified, then the unnamed statement is executed. The name must have * been previously prepared using pg_prepare, * pg_send_prepare or a PREPARE SQL * command. *

    * @param array $params [optional]

    * An array of parameter values to substitute for the $1, $2, etc. placeholders * in the original prepared query string. The number of elements in the array * must match the number of placeholders. *

    *

    * Elements are converted to strings by calling this function. *

    * @return resource|false A query result resource on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result|false'], default: 'resource|false')] function pg_execute( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $statement_name = '', #[PhpStormStubsElementAvailable(from: '8.0')] $statement_name, array $params ) {} /** * Sends asynchronous query * @link https://php.net/manual/en/function.pg-send-query.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param string $query

    * The SQL statement or statements to be executed. *

    *

    * Data inside the query should be properly escaped. *

    * @return int|bool TRUE on success or FALSE on failure.

    *

    * Use pg_get_result to determine the query result. */ function pg_send_query( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $query ): int|bool {} /** * Submits a command and separate parameters to the server without waiting for the result(s). * @link https://php.net/manual/en/function.pg-send-query-params.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param string $query

    * The parameterized SQL statement. Must contain only a single statement. * (multiple statements separated by semi-colons are not allowed.) If any parameters * are used, they are referred to as $1, $2, etc. *

    * @param array $params

    * An array of parameter values to substitute for the $1, $2, etc. placeholders * in the original prepared query string. The number of elements in the array * must match the number of placeholders. *

    * @return int|bool TRUE on success or FALSE on failure.

    *

    * Use pg_get_result to determine the query result. */ function pg_send_query_params( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $query, array $params ): int|bool {} /** * Sends a request to create a prepared statement with the given parameters, without waiting for completion. * @link https://php.net/manual/en/function.pg-send-prepare.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $statement_name

    * The name to give the prepared statement. Must be unique per-connection. If * "" is specified, then an unnamed statement is created, overwriting any * previously defined unnamed statement. *

    * @param string $query

    * The parameterized SQL statement. Must contain only a single statement. * (multiple statements separated by semi-colons are not allowed.) If any parameters * are used, they are referred to as $1, $2, etc. *

    * @return int|bool TRUE on success, FALSE on failure. Use pg_get_result * to determine the query result. */ function pg_send_prepare( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $statement_name, string $query ): int|bool {} /** * Sends a request to execute a prepared statement with given parameters, without waiting for the result(s). * @link https://php.net/manual/en/function.pg-send-execute.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $statement_name

    * The name of the prepared statement to execute. if * "" is specified, then the unnamed statement is executed. The name must have * been previously prepared using pg_prepare, * pg_send_prepare or a PREPARE SQL * command. *

    * @param array $params

    * An array of parameter values to substitute for the $1, $2, etc. placeholders * in the original prepared query string. The number of elements in the array * must match the number of placeholders. *

    * @return int|bool TRUE on success, FALSE on failure. Use pg_get_result * to determine the query result. */ function pg_send_execute( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $statement_name, array $params ): int|bool {} /** * Cancel an asynchronous query * @link https://php.net/manual/en/function.pg-cancel-query.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @return bool TRUE on success or FALSE on failure. */ function pg_cancel_query(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection): bool {} /** * Returns values from a result resource * @link https://php.net/manual/en/function.pg-fetch-result.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $row

    * Row number in result to fetch. Rows are numbered from 0 upwards. If omitted, * next row is fetched. *

    * @param mixed $field [optional]

    * A string representing the name of the field (column) to fetch, otherwise * an int representing the field number to fetch. Fields are * numbered from 0 upwards. *

    * @return string|false|null Boolean is returned as "t" or "f". All * other types, including arrays are returned as strings formatted * in the same default PostgreSQL manner that you would see in the * psql program. Database NULL * values are returned as NULL. *

    *

    * FALSE is returned if row exceeds the number * of rows in the set, or on any other error. */ function pg_fetch_result( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $row = 0, #[PhpStormStubsElementAvailable(from: '8.0')] $row, string|int $field ): string|false|null {} /** * Get a row as an enumerated array * @link https://php.net/manual/en/function.pg-fetch-row.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $row [optional]

    * Row number in result to fetch. Rows are numbered from 0 upwards. If * omitted or NULL, the next row is fetched. *

    * @param int $mode [optional] * @return array|false An array, indexed from 0 upwards, with each value * represented as a string. Database NULL * values are returned as NULL. *

    *

    * FALSE is returned if row exceeds the number * of rows in the set, there are no more rows, or on any other error. */ function pg_fetch_row(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, ?int $row = null, int $mode = 2): array|false {} /** * Fetch a row as an associative array * @link https://php.net/manual/en/function.pg-fetch-assoc.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $row [optional]

    * Row number in result to fetch. Rows are numbered from 0 upwards. If * omitted or NULL, the next row is fetched. *

    * @return array|false An array indexed associatively (by field name). * Each value in the array is represented as a * string. Database NULL * values are returned as NULL. *

    *

    * FALSE is returned if row exceeds the number * of rows in the set, there are no more rows, or on any other error. */ function pg_fetch_assoc(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, ?int $row = null): array|false {} /** * Fetch a row as an array * @link https://php.net/manual/en/function.pg-fetch-array.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $row [optional]

    * Row number in result to fetch. Rows are numbered from 0 upwards. If * omitted or NULL, the next row is fetched. *

    * @param int $mode [optional]

    * An optional parameter that controls * how the returned array is indexed. * result_type is a constant and can take the * following values: PGSQL_ASSOC, * PGSQL_NUM and PGSQL_BOTH. * Using PGSQL_NUM, pg_fetch_array * will return an array with numerical indices, using * PGSQL_ASSOC it will return only associative indices * while PGSQL_BOTH, the default, will return both * numerical and associative indices. *

    * @return array|false An array indexed numerically (beginning with 0) or * associatively (indexed by field name), or both. * Each value in the array is represented as a * string. Database NULL * values are returned as NULL. *

    *

    * FALSE is returned if row exceeds the number * of rows in the set, there are no more rows, or on any other error. */ function pg_fetch_array(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, ?int $row = null, int $mode = PGSQL_BOTH): array|false {} /** * Fetch a row as an object * @link https://php.net/manual/en/function.pg-fetch-object.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int|null $row [optional]

    * Row number in result to fetch. Rows are numbered from 0 upwards. If * omitted or NULL, the next row is fetched. *

    * @param string $class [optional]

    * Ignored and deprecated. *

    * @param array $constructor_args [optional]

    *

    * @return object|false An object with one attribute for each field * name in the result. Database NULL * values are returned as NULL. *

    *

    * FALSE is returned if row exceeds the number * of rows in the set, there are no more rows, or on any other error. */ function pg_fetch_object( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, ?int $row = null, string $class = 'stdClass', #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $l = null, array $constructor_args = [] ): object|false {} /** * Fetches all rows from a result as an array * @link https://php.net/manual/en/function.pg-fetch-all.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $mode [optional]

    * An optional parameter that controls * how the returned array is indexed. * result_type is a constant and can take the * following values: PGSQL_ASSOC, * PGSQL_NUM and PGSQL_BOTH. * Using PGSQL_NUM, pg_fetch_array * will return an array with numerical indices, using * PGSQL_ASSOC it will return only associative indices * while PGSQL_BOTH, the default, will return both * numerical and associative indices. *

    * @return array|false An array with all rows in the result. Each row is an array * of field values indexed by field name. *

    *

    * FALSE is returned if there are no rows in the result, or on any * other error. */ #[LanguageLevelTypeAware(['8.0' => 'array'], default: 'array|false')] function pg_fetch_all(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $mode = PGSQL_ASSOC) {} /** * Fetches all rows in a particular result column as an array * @link https://php.net/manual/en/function.pg-fetch-all-columns.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $field [optional]

    * Column number, zero-based, to be retrieved from the result resource. Defaults * to the first column if not specified. *

    * @return array An array with all values in the result column. *

    * FALSE is returned if column is larger than the number * of columns in the result, or on any other error. *

    */ function pg_fetch_all_columns(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field = 0): array {} /** * Returns number of affected records (tuples) * @link https://php.net/manual/en/function.pg-affected-rows.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @return int The number of rows affected by the query. If no tuple is * affected, it will return 0. */ function pg_affected_rows(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): int {} /** * Get asynchronous query result * @link https://php.net/manual/en/function.pg-get-result.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @return resource|false The result resource, or FALSE if no more results are available. */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result|false'], default: 'resource|false')] function pg_get_result(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection) {} /** * Set internal row offset in result resource * @link https://php.net/manual/en/function.pg-result-seek.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $row

    * Row to move the internal offset to in the result resource. * Rows are numbered starting from zero. *

    * @return bool TRUE on success or FALSE on failure. */ function pg_result_seek(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $row): bool {} /** * Get status of query result * @link https://php.net/manual/en/function.pg-result-status.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $mode [optional]

    * Either PGSQL_STATUS_LONG to return the numeric status * of the result, or PGSQL_STATUS_STRING * to return the command tag of the result. * If not specified, PGSQL_STATUS_LONG is the default. *

    * @return string|int Possible return values are PGSQL_EMPTY_QUERY, * PGSQL_COMMAND_OK, PGSQL_TUPLES_OK, PGSQL_COPY_OUT, * PGSQL_COPY_IN, PGSQL_BAD_RESPONSE, PGSQL_NONFATAL_ERROR and * PGSQL_FATAL_ERROR if PGSQL_STATUS_LONG is * specified. Otherwise, a string containing the PostgreSQL command tag is returned. */ function pg_result_status(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $mode = PGSQL_STATUS_LONG): string|int {} /** * Free result memory * @link https://php.net/manual/en/function.pg-free-result.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @return bool TRUE on success or FALSE on failure. */ function pg_free_result(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): bool {} /** * Returns the last row's OID * @link https://php.net/manual/en/function.pg-last-oid.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @return string|int|false A string containing the OID assigned to the most recently inserted * row in the specified connection, or FALSE on error or * no available OID. */ function pg_last_oid(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): string|int|false {} /** * Returns the number of rows in a result * @link https://php.net/manual/en/function.pg-num-rows.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @return int The number of rows in the result. On error, -1 is returned. */ function pg_num_rows(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): int {} /** * Returns the number of fields in a result * @link https://php.net/manual/en/function.pg-num-fields.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @return int The number of fields (columns) in the result. On error, -1 is returned. */ function pg_num_fields(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): int {} /** * Returns the name of a field * @link https://php.net/manual/en/function.pg-field-name.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $field

    * Field number, starting from 0. *

    * @return string|false The field name, or FALSE on error. */ function pg_field_name(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field): string {} /** * Returns the field number of the named field * @link https://php.net/manual/en/function.pg-field-num.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param string $field

    * The name of the field. *

    * @return int The field number (numbered from 0), or -1 on error. */ function pg_field_num(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, string $field): int {} /** * Returns the internal storage size of the named field * @link https://php.net/manual/en/function.pg-field-size.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $field

    * Field number, starting from 0. *

    * @return int The internal field storage size (in bytes). -1 indicates a variable * length field. FALSE is returned on error. */ function pg_field_size(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field): int {} /** * Returns the type name for the corresponding field number * @link https://php.net/manual/en/function.pg-field-type.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $field

    * Field number, starting from 0. *

    * @return string|false A string containing the base name of the field's type, or FALSE * on error. */ function pg_field_type(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field): string {} /** * Returns the type ID (OID) for the corresponding field number * @link https://php.net/manual/en/function.pg-field-type-oid.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $field

    * Field number, starting from 0. *

    * @return string|int The OID of the field's base type. FALSE is returned on error. */ function pg_field_type_oid(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field): string|int {} /** * Returns the printed length * @link https://php.net/manual/en/function.pg-field-prtlen.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $row * @param mixed $field [optional] * @return int|false The field printed length, or FALSE on error. */ function pg_field_prtlen( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $row = 0, #[PhpStormStubsElementAvailable(from: '8.0')] $row, string|int $field ): int|false {} /** * Test if a field is SQL NULL * @link https://php.net/manual/en/function.pg-field-is-null.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $row

    * Row number in result to fetch. Rows are numbered from 0 upwards. If omitted, * current row is fetched. *

    * @param mixed $field [optional]

    * Field number (starting from 0) as an integer or * the field name as a string. *

    * @return int|false 1 if the field in the given row is SQL NULL, 0 * if not. FALSE is returned if the row is out of range, or upon any other error. */ function pg_field_is_null( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $row = 0, #[PhpStormStubsElementAvailable(from: '8.0')] $row, string|int $field ): int|false {} /** * Returns the name or oid of the tables field * @link https://php.net/manual/en/function.pg-field-table.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @param int $field

    * Field number, starting from 0. *

    * @param bool $oid_only [optional]

    * By default the tables name that field belongs to is returned but * if oid_only is set to TRUE, then the * oid will instead be returned. *

    * @return string|int|false On success either the fields table name or oid. Or, FALSE on failure. */ function pg_field_table(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field, bool $oid_only = false): string|int|false {} /** * Gets SQL NOTIFY message * @link https://php.net/manual/en/function.pg-get-notify.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param int $mode [optional]

    * An optional parameter that controls * how the returned array is indexed. * result_type is a constant and can take the * following values: PGSQL_ASSOC, * PGSQL_NUM and PGSQL_BOTH. * Using PGSQL_NUM, pg_get_notify * will return an array with numerical indices, using * PGSQL_ASSOC it will return only associative indices * while PGSQL_BOTH, the default, will return both * numerical and associative indices. *

    * @return array|false An array containing the NOTIFY message name and backend PID. * Otherwise if no NOTIFY is waiting, then FALSE is returned. */ #[ArrayShape(["message" => "string", "pid" => "int", "payload" => "string"])] function pg_get_notify( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, int $mode = 1 ): array|false {} /** * Gets the backend's process ID * @link https://php.net/manual/en/function.pg-get-pid.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @return int The backend database process ID. */ function pg_get_pid( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, ): int {} /** * Get error message associated with result * @link https://php.net/manual/en/function.pg-result-error.php * @param resource $result

    * PostgreSQL query result resource, returned by pg_query, * pg_query_params or pg_execute * (among others). *

    * @return string|false a string if there is an error associated with the * result parameter, FALSE otherwise. */ function pg_result_error(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): string|false {} /** * Returns an individual field of an error report. * @link https://php.net/manual/en/function.pg-result-error-field.php * @param resource $result

    * A PostgreSQL query result resource from a previously executed * statement. *

    * @param int $field_code

    * Possible fieldcode values are: PGSQL_DIAG_SEVERITY, * PGSQL_DIAG_SQLSTATE, PGSQL_DIAG_MESSAGE_PRIMARY, * PGSQL_DIAG_MESSAGE_DETAIL, * PGSQL_DIAG_MESSAGE_HINT, PGSQL_DIAG_STATEMENT_POSITION, * PGSQL_DIAG_INTERNAL_POSITION (PostgreSQL 8.0+ only), * PGSQL_DIAG_INTERNAL_QUERY (PostgreSQL 8.0+ only), * PGSQL_DIAG_CONTEXT, PGSQL_DIAG_SOURCE_FILE, * PGSQL_DIAG_SOURCE_LINE or * PGSQL_DIAG_SOURCE_FUNCTION. *

    * @return string|null|false A string containing the contents of the error field, NULL if the field does not exist or FALSE * on failure. */ function pg_result_error_field( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field_code ): string|false|null {} /** * Get the last error message string of a connection * @link https://php.net/manual/en/function.pg-last-error.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return string A string containing the last error message on the * given connection, or FALSE on error. */ function pg_last_error(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): string {} /** * Returns the last notice message from PostgreSQL server * @link https://php.net/manual/en/function.pg-last-notice.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param int $mode [optional]

    * One of PGSQL_NOTICE_LAST (to return last notice), * PGSQL_NOTICE_ALL (to return all notices), or * PGSQL_NOTICE_CLEAR (to clear notices). *

    * @return array|string|bool A string containing the last notice on the * given connection with PGSQL_NOTICE_LAST, * an array with PGSQL_NOTICE_ALL, * a bool with PGSQL_NOTICE_CLEAR, or * FALSE on error. */ function pg_last_notice(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, int $mode = PGSQL_NOTICE_LAST): array|string|bool {} /** * Send a NULL-terminated string to PostgreSQL backend * @link https://php.net/manual/en/function.pg-put-line.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $query [optional]

    * A line of text to be sent directly to the PostgreSQL backend. A NULL * terminator is added automatically. *

    * @return bool TRUE on success or FALSE on failure. */ function pg_put_line( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $query ): bool {} /** * Sync with PostgreSQL backend * @link https://php.net/manual/en/function.pg-end-copy.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return bool TRUE on success or FALSE on failure. */ function pg_end_copy(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): bool {} /** * Copy a table to an array * @link https://php.net/manual/en/function.pg-copy-to.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param string $table_name

    * Name of the table from which to copy the data into rows. *

    * @param string $separator [optional]

    * The token that separates values for each field in each element of * rows. Default is TAB. *

    * @param string $null_as [optional]

    * How SQL NULL values are represented in the * rows. Default is \N ("\\N"). *

    * @return array|false An array with one element for each line of COPY data. * It returns FALSE on failure. */ function pg_copy_to( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $table_name, string $separator = ' ', string $null_as = '\\\\N' ): array|false {} /** * Insert records into a table from an array * @link https://php.net/manual/en/function.pg-copy-from.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param string $table_name

    * Name of the table into which to copy the rows. *

    * @param array $rows

    * An array of data to be copied into table_name. * Each value in rows becomes a row in table_name. * Each value in rows should be a delimited string of the values * to insert into each field. Values should be linefeed terminated. *

    * @param string $separator [optional]

    * The token that separates values for each field in each element of * rows. Default is TAB. *

    * @param string $null_as [optional]

    * How SQL NULL values are represented in the * rows. Default is \N ("\\N"). *

    * @return bool TRUE on success or FALSE on failure. */ function pg_copy_from( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $table_name, array $rows, string $separator = ' ', string $null_as = '\\\\N' ): bool {} /** * Enable tracing a PostgreSQL connection * @link https://php.net/manual/en/function.pg-trace.php * @param string $filename

    * The full path and file name of the file in which to write the * trace log. Same as in fopen. *

    * @param string $mode [optional]

    * An optional file access mode, same as for fopen. *

    * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param int $trace_mode Since PHP 8.3 optional trace mode * @return bool TRUE on success or FALSE on failure. */ function pg_trace( string $filename, string $mode = "w", #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.3')] int $trace_mode = 0 ): bool {} /** * Disable tracing of a PostgreSQL connection * @link https://php.net/manual/en/function.pg-untrace.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    */ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function pg_untrace(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null) {} /** * Create a large object * @link https://php.net/manual/en/function.pg-lo-create.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param mixed $oid [optional]

    * If an object_id is given the function * will try to create a large object with this id, else a free * object id is assigned by the server. The parameter * was added in PHP 5.3 and relies on functionality that first * appeared in PostgreSQL 8.1. *

    * @return string|int|false A large object OID or FALSE on error. */ function pg_lo_create(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, $oid): string|int|false {} /** * Delete a large object * @link https://php.net/manual/en/function.pg-lo-unlink.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param int $oid [optional]

    * The OID of the large object in the database. *

    * @return bool TRUE on success or FALSE on failure. */ function pg_lo_unlink( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, $oid ): bool {} /** * Open a large object * @link https://php.net/manual/en/function.pg-lo-open.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param int $oid [optional]

    * The OID of the large object in the database. *

    * @param string $mode [optional]

    * Can be either "r" for read-only, "w" for write only or "rw" for read and * write. *

    * @return resource|false A large object resource or FALSE on error. */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob|false'], default: 'resource|false')] function pg_lo_open( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, $oid, string $mode ) {} /** * Close a large object * @link https://php.net/manual/en/function.pg-lo-close.php * @param resource $lob * @return bool TRUE on success or FALSE on failure. */ function pg_lo_close(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob): bool {} /** * Read a large object * @link https://php.net/manual/en/function.pg-lo-read.php * @param resource $lob

    * PostgreSQL large object (LOB) resource, returned by pg_lo_open. *

    * @param int $length [optional]

    * An optional maximum number of bytes to return. *

    * @return string|false A string containing len bytes from the * large object, or FALSE on error. */ function pg_lo_read(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob, int $length = 8192): string|false {} /** * Write to a large object * @link https://php.net/manual/en/function.pg-lo-write.php * @param resource $lob

    * PostgreSQL large object (LOB) resource, returned by pg_lo_open. *

    * @param string $data

    * The data to be written to the large object. If len is * specified and is less than the length of data, only * len bytes will be written. *

    * @param int $length [optional]

    * An optional maximum number of bytes to write. Must be greater than zero * and no greater than the length of data. Defaults to * the length of data. *

    * @return int|false The number of bytes written to the large object, or FALSE on error. */ function pg_lo_write(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob, string $data, ?int $length = null): int|false {} /** * Reads an entire large object and send straight to browser * @link https://php.net/manual/en/function.pg-lo-read-all.php * @param resource $lob

    * PostgreSQL large object (LOB) resource, returned by pg_lo_open. *

    * @return int|false Number of bytes read or FALSE on error. */ function pg_lo_read_all(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob): int {} /** * Import a large object from file * @link https://php.net/manual/en/function.pg-lo-import.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $pathname

    * The full path and file name of the file on the client * filesystem from which to read the large object data. *

    * @param mixed $object_id [optional]

    * If an object_id is given the function * will try to create a large object with this id, else a free * object id is assigned by the server. The parameter * was added in PHP 5.3 and relies on functionality that first * appeared in PostgreSQL 8.1. *

    * @return string|int|false The OID of the newly created large object, or * FALSE on failure. */ function pg_lo_import( #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, $pathname, $object_id = null ): string|int|false {} /** * Export a large object to file * @link https://php.net/manual/en/function.pg-lo-export.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param int $oid

    * The OID of the large object in the database. *

    * @param string $pathname

    * The full path and file name of the file in which to write the * large object on the client filesystem. *

    * @return bool TRUE on success or FALSE on failure. */ function pg_lo_export( #[PhpStormStubsElementAvailable('8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, $oid, $pathname ): bool {} /** * Seeks position within a large object * @link https://php.net/manual/en/function.pg-lo-seek.php * @param resource $lob

    * PostgreSQL large object (LOB) resource, returned by pg_lo_open. *

    * @param int $offset

    * The number of bytes to seek. *

    * @param int $whence [optional]

    * One of the constants PGSQL_SEEK_SET (seek from object start), * PGSQL_SEEK_CUR (seek from current position) * or PGSQL_SEEK_END (seek from object end) . *

    * @return bool TRUE on success or FALSE on failure. */ function pg_lo_seek(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob, int $offset, int $whence = PGSQL_SEEK_CUR): bool {} /** * Returns current seek position a of large object * @link https://php.net/manual/en/function.pg-lo-tell.php * @param resource $lob

    * PostgreSQL large object (LOB) resource, returned by pg_lo_open. *

    * @return int The current seek offset (in number of bytes) from the beginning of the large * object. If there is an error, the return value is negative. */ function pg_lo_tell(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob): int {} /** * Truncates a large object * @link https://www.php.net/manual/en/function.pg-lo-truncate.php * @param resource $lob

    * PostgreSQL large object (LOB) resource, returned by pg_lo_open. *

    * @param int $size The number of bytes to truncate. * @return bool Returns true on success or false on failure. */ function pg_lo_truncate( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] int $size = 0, #[PhpStormStubsElementAvailable(from: '8.0')] int $size ): bool {} /** * Escape a string for query * @link https://php.net/manual/en/function.pg-escape-string.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $string [optional]

    * A string containing text to be escaped. *

    * @return string A string containing the escaped data. */ function pg_escape_string( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $string ): string {} /** * Escape a string for insertion into a bytea field * @link https://php.net/manual/en/function.pg-escape-bytea.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $string [optional]

    * A string containing text or binary data to be inserted into a bytea * column. *

    * @return string A string containing the escaped data. */ function pg_escape_bytea( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $string ): string {} /** * Escape a identifier for insertion into a text field * @link https://php.net/manual/en/function.pg-escape-identifier.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $string [optional]

    * A string containing text to be escaped. *

    * @return string|false A string containing the escaped data. * @since 5.4.4 */ function pg_escape_identifier( #[PhpStormStubsElementAvailable(from: '5.4', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $string ): string|false {} /** * Escape a literal for insertion into a text field * @link https://php.net/manual/en/function.pg-escape-literal.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $string [optional]

    * A string containing text to be escaped. *

    * @return string|false A string containing the escaped data. * @since 5.4.4 */ function pg_escape_literal( #[PhpStormStubsElementAvailable(from: '5.4', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $string ): string|false {} /** * Unescape binary for bytea type * @link https://php.net/manual/en/function.pg-unescape-bytea.php * @param string $string

    * A string containing PostgreSQL bytea data to be converted into * a PHP binary string. *

    * @return string A string containing the unescaped data. */ function pg_unescape_bytea(string $string): string {} /** * Determines the verbosity of messages returned by pg_last_error * and pg_result_error. * @link https://php.net/manual/en/function.pg-set-error-verbosity.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param int $verbosity [optional]

    * The required verbosity: PGSQL_ERRORS_TERSE, * PGSQL_ERRORS_DEFAULT * or PGSQL_ERRORS_VERBOSE. *

    * @return int|false The previous verbosity level: PGSQL_ERRORS_TERSE, * PGSQL_ERRORS_DEFAULT * or PGSQL_ERRORS_VERBOSE. */ function pg_set_error_verbosity( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, int $verbosity ): int|false {} /** * Gets the client encoding * @link https://php.net/manual/en/function.pg-client-encoding.php * @param resource $connection [optional]

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @return string|false The client encoding, or FALSE on error. */ function pg_client_encoding(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection = null): string {} /** * Set the client encoding * @link https://php.net/manual/en/function.pg-set-client-encoding.php * @param resource $connection

    * PostgreSQL database connection resource. When * connection is not present, the default connection * is used. The default connection is the last connection made by * pg_connect or pg_pconnect. *

    * @param string $encoding [optional]

    * The required client encoding. One of SQL_ASCII, EUC_JP, * EUC_CN, EUC_KR, EUC_TW, * UNICODE, MULE_INTERNAL, LATINX (X=1...9), * KOI8, WIN, ALT, SJIS, * BIG5 or WIN1250. *

    *

    * The exact list of available encodings depends on your PostgreSQL version, so check your * PostgreSQL manual for a more specific list. *

    * @return int 0 on success or -1 on error. */ function pg_set_client_encoding( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $encoding ): int {} /** * Get meta data for table * @link https://php.net/manual/en/function.pg-meta-data.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param string $table_name

    * The name of the table. *

    * @return array|false An array of the table definition, or FALSE on error. */ function pg_meta_data( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $table_name, #[PhpStormStubsElementAvailable(from: '8.0')] bool $extended = false ): array|false {} /** * Convert associative array values into suitable for SQL statement * @link https://php.net/manual/en/function.pg-convert.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param string $table_name

    * Name of the table against which to convert types. *

    * @param array $values

    * Data to be converted. *

    * @param int $flags [optional]

    * Any number of PGSQL_CONV_IGNORE_DEFAULT, * PGSQL_CONV_FORCE_NULL or * PGSQL_CONV_IGNORE_NOT_NULL, combined. *

    * @return array|false An array of converted values, or FALSE on error. */ function pg_convert( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $table_name, array $values, int $flags = 0 ): array|false {} /** * Insert array into table * @link https://php.net/manual/en/function.pg-insert.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param string $table_name

    * Name of the table into which to insert rows. The table table_name must at least * have as many columns as assoc_array has elements. *

    * @param array $values

    * An array whose keys are field names in the table table_name, * and whose values are the values of those fields that are to be inserted. *

    * @param int $flags [optional]

    * Any number of PGSQL_CONV_OPTS, * PGSQL_DML_NO_CONV, * PGSQL_DML_EXEC, * PGSQL_DML_ASYNC or * PGSQL_DML_STRING combined. If PGSQL_DML_STRING is part of the * options then query string is returned. *

    * @return mixed TRUE on success or FALSE on failure. Returns string if PGSQL_DML_STRING is passed * via options. */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result|string|bool'], default: 'resource|string|bool')] function pg_insert( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $table_name, array $values, int $flags = PGSQL_DML_EXEC ) {} /** * Update table * @link https://php.net/manual/en/function.pg-update.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param string $table_name

    * Name of the table into which to update rows. *

    * @param array $values

    * An array whose keys are field names in the table table_name, * and whose values are what matched rows are to be updated to. *

    * @param array $conditions

    * An array whose keys are field names in the table table_name, * and whose values are the conditions that a row must meet to be updated. *

    * @param int $flags [optional]

    * Any number of PGSQL_CONV_OPTS, * PGSQL_DML_NO_CONV, * PGSQL_DML_EXEC or * PGSQL_DML_STRING combined. If PGSQL_DML_STRING is part of the * options then query string is returned. *

    * @return string|bool TRUE on success or FALSE on failure. Returns string if PGSQL_DML_STRING is passed * via options. */ function pg_update( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $table_name, array $values, array $conditions, int $flags = PGSQL_DML_EXEC ): string|bool {} /** * Deletes records * @link https://php.net/manual/en/function.pg-delete.php * @param resource $connection

    * PostgreSQL database connection resource. *

    * @param string $table_name

    * Name of the table from which to delete rows. *

    * @param array $conditions

    * An array whose keys are field names in the table table_name, * and whose values are the values of those fields that are to be deleted. *

    * @param int $flags [optional]

    * Any number of PGSQL_CONV_FORCE_NULL, * PGSQL_DML_NO_CONV, * PGSQL_DML_EXEC or * PGSQL_DML_STRING combined. If PGSQL_DML_STRING is part of the * options then query string is returned. *

    * @return string|bool TRUE on success or FALSE on failure. Returns string if PGSQL_DML_STRING is passed * via options. */ function pg_delete( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $table_name, array $conditions, int $flags = PGSQL_DML_EXEC ): string|bool {} /** * Select records * @link https://php.net/manual/en/function.pg-select.php * @param resource|PgSql\Connection $connection

    * PostgreSQL database connection resource. *

    * @param string $table_name

    * Name of the table from which to select rows. *

    * @param array $conditions

    * An array whose keys are field names in the table table_name, * and whose values are the conditions that a row must meet to be retrieved. *

    * @param int $flags [optional]

    * Any number of PGSQL_CONV_FORCE_NULL, * PGSQL_DML_NO_CONV, * PGSQL_DML_EXEC, * PGSQL_DML_ASYNC or * PGSQL_DML_STRING combined. If PGSQL_DML_STRING is part of the * options then query string is returned. *

    * @param int $mode [optional]

    * An optional parameter that controls * how the returned array is indexed. * result_type is a constant and can take the * following values: PGSQL_ASSOC, * PGSQL_NUM and PGSQL_BOTH. * Using PGSQL_NUM, pg_fetch_array * will return an array with numerical indices, using * PGSQL_ASSOC it will return only associative indices * while PGSQL_BOTH, the default, will return both * numerical and associative indices. *

    * @return array|string|false TRUE on success or FALSE on failure. Returns string if PGSQL_DML_STRING is passed * via options. */ function pg_select( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $table_name, array $conditions = [], int $flags = PGSQL_DML_EXEC, int $mode = PGSQL_ASSOC ): array|string|false {} /** * @param $connection * @param $query [optional] * @return mixed */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result|false'], default: 'resource|false')] function pg_exec( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $query ) {} /** * @param $result * @return string|int|false * @deprecated 8.0 */ function pg_getlastoid(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): string|int|false {} /** * @param $result * @return int * @deprecated 8.0 */ function pg_cmdtuples(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): int {} // TODO remove /** * @param $connection [optional] * @return string * @deprecated 8.0 */ function pg_errormessage(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection): string {} /** * @param $result * @return int * @deprecated 8.0 */ function pg_numrows(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): int {} /** * @param $result * @return int * @deprecated 8.0 */ function pg_numfields(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): int {} /** * @param $result * @param $field * @return string * @deprecated 8.0 */ function pg_fieldname(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field): string {} /** * @param $result * @param $field * @return int * @deprecated 8.0 */ function pg_fieldsize(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field): int {} /** * @param $result * @param $field * @return string * @deprecated 8.0 */ function pg_fieldtype(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, int $field): string {} /** * @param $result * @param $field * @return int * @deprecated 8.0 */ function pg_fieldnum(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, string $field): int {} /** * @param $result * @param $row * @param $field [optional] * @return int|false * @deprecated 8.0 */ function pg_fieldprtlen( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $row = 0, #[PhpStormStubsElementAvailable(from: '8.0')] $row, string|int $field ): int|false {} /** * @param $result * @param $row * @param $field [optional] * @return int|false * @deprecated 8.0 */ function pg_fieldisnull( #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $row = 0, #[PhpStormStubsElementAvailable(from: '8.0')] $row, string|int $field ): int|false {} /** * @param $result * @return bool * @deprecated 8.0 */ function pg_freeresult(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result): bool {} /** * @param PgSql\Result|resource $result * @param $row * @param $field [optional] * @deprecated 8.0 */ function pg_result( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result, #[PhpStormStubsElementAvailable(from: '8.0')] $row, #[PhpStormStubsElementAvailable(from: '8.0')] string|int $field ): string|null|false {} /** * @param $lob * @deprecated 8.0 */ function pg_loreadall(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob): int {} // TODO remove /** * @param $connection [optional] * @param $oid [optional] * @return string|int|false * @deprecated 8.0 */ function pg_locreate(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, $oid): string|int|false {} /** * @param $connection * @param $oid [optional] * @return bool * @deprecated 8.0 */ function pg_lounlink( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, $oid ): bool {} /** * @param $connection * @param $oid [optional] * @param $mode [optional] * @return resource * @deprecated 8.0 */ #[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob|false'], default: 'resource|false')] function pg_loopen( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, $oid, string $mode ) {} /** * @param $lob * @return bool * @deprecated 8.0 */ function pg_loclose(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob): bool {} /** * @param $lob * @param $length * @return string|false * @deprecated 8.0 */ function pg_loread(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob, int $length = 8192): string|false {} /** * @param $lob * @param $data * @param $length [optional] * @return int|false * @deprecated 8.0 */ function pg_lowrite(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Lob'], default: 'resource')] $lob, string $data, ?int $length): int|false {} /** * @param $connection * @param $filename [optional] * @param $oid [optional] * @return string|int|false * @deprecated 8.0 */ function pg_loimport( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, $filename, $oid ): string|int|false {} /** * @param $connection * @param $oid [optional] * @param $filename [optional] * @return bool * @deprecated 8.0 */ function pg_loexport( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, $oid, $filename ): bool {} /** * @param $connection [optional] * @return string * @deprecated 8.0 */ function pg_clientencoding(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], default: 'resource')] $connection): string {} /** * @param $connection * @param $encoding [optional] * @return int * @deprecated 8.0 */ function pg_setclientencoding( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null, #[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $encoding ): int {} /** * Reads input on the connection * @link https://www.php.net/manual/en/function.pg-consume-input.php * @param PgSql\Connection|resource $connection * @return bool true if no error occurred, or false if there was an error. * Note that true does not necessarily indicate that input was waiting to be read. */ function pg_consume_input(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection): bool {} /** * Flush outbound query data on the connection * @link https://www.php.net/manual/en/function.pg-flush.php * @param PgSql\Connection|resource $connection * @return int|bool Returns true if the flush was successful or no data was waiting to be flushed, 0 if part of the pending * data was flushed but more remains or false on failure. */ function pg_flush(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection): int|bool {} /** * @since 8.3 */ function pg_set_error_context_visibility(PgSql\Connection $connection, int $visibility): int {} /** * @since 8.3 */ function pg_pipeline_status(PgSql\Connection $connection): int {} /** * @since 8.3 */ function pg_pipeline_sync(PgSql\Connection $connection): bool {} /** * @since 8.3 */ function pg_exit_pipeline_mode(PgSql\Connection $connection): bool {} /** * @since 8.3 */ function pg_enter_pipeline_mode(PgSql\Connection $connection): bool {} /** * @since 8.4 */ function pg_result_memory_size(PgSql\Result $result): int {} /** * @since 8.4 */ function pg_change_password(PgSql\Connection $connection, string $user, #[\SensitiveParameter] string $password): bool {} /** * @since 8.4 */ function pg_put_copy_data(PgSql\Connection $connection, string $cmd): int {} /** * @since 8.4 * @param resource $socket */ function pg_socket_poll($socket, int $read, int $write, int $timeout = -1): int {} /** * @since 8.4 */ function pg_put_copy_end(PgSql\Connection $connection, ?string $error = null): int {} /** * @since 8.4 * @return array */ function pg_jit(?PgSql\Connection $connection = null): array {} define('PGSQL_LIBPQ_VERSION', "16.2"); define('PGSQL_LIBPQ_VERSION_STR', "16.2"); /** * Passed to pg_connect to force the creation of a new connection, * rather than re-using an existing identical connection. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_CONNECT_FORCE_NEW', 2); /** * Passed to pg_fetch_array. Return an associative array of field * names and values. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_ASSOC', 1); /** * Passed to pg_fetch_array. Return a numerically indexed array of field * numbers and values. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_NUM', 2); /** * Passed to pg_fetch_array. Return an array of field values * that is both numerically indexed (by field number) and associated (by field name). * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_BOTH', 3); /** * Returned by pg_connection_status indicating that the database * connection is in an invalid state. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_CONNECTION_BAD', 1); /** * Returned by pg_connection_status indicating that the database * connection is in a valid state. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_CONNECTION_OK', 0); /** * Returned by pg_transaction_status. Connection is * currently idle, not in a transaction. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_TRANSACTION_IDLE', 0); /** * Returned by pg_transaction_status. A command * is in progress on the connection. A query has been sent via the connection * and not yet completed. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_TRANSACTION_ACTIVE', 1); /** * Returned by pg_transaction_status. The connection * is idle, in a transaction block. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_TRANSACTION_INTRANS', 2); /** * Returned by pg_transaction_status. The connection * is idle, in a failed transaction block. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_TRANSACTION_INERROR', 3); /** * Returned by pg_transaction_status. The connection * is bad. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_TRANSACTION_UNKNOWN', 4); /** * Passed to pg_set_error_verbosity. * Specified that returned messages include severity, primary text, * and position only; this will normally fit on a single line. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_ERRORS_TERSE', 0); /** * Passed to pg_set_error_verbosity. * The default mode produces messages that include the above * plus any detail, hint, or context fields (these may span * multiple lines). * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_ERRORS_DEFAULT', 1); /** * Passed to pg_set_error_verbosity. * The verbose mode includes all available fields. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_ERRORS_VERBOSE', 2); /** * Passed to pg_lo_seek. Seek operation is to begin * from the start of the object. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_SEEK_SET', 0); /** * Passed to pg_lo_seek. Seek operation is to begin * from the current position. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_SEEK_CUR', 1); /** * Passed to pg_lo_seek. Seek operation is to begin * from the end of the object. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_SEEK_END', 2); /** * Passed to pg_result_status. Indicates that * numerical result code is desired. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_STATUS_LONG', 1); /** * Passed to pg_result_status. Indicates that * textual result command tag is desired. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_STATUS_STRING', 2); /** * Returned by pg_result_status. The string sent to the server * was empty. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_EMPTY_QUERY', 0); /** * Returned by pg_result_status. Successful completion of a * command returning no data. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_COMMAND_OK', 1); /** * Returned by pg_result_status. Successful completion of a command * returning data (such as a SELECT or SHOW). * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_TUPLES_OK', 2); /** * Returned by pg_result_status. Copy Out (from server) data * transfer started. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_COPY_OUT', 3); /** * Returned by pg_result_status. Copy In (to server) data * transfer started. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_COPY_IN', 4); /** * Returned by pg_result_status. The server's response * was not understood. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_BAD_RESPONSE', 5); /** * Returned by pg_result_status. A nonfatal error * (a notice or warning) occurred. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_NONFATAL_ERROR', 6); /** * Returned by pg_result_status. A fatal error * occurred. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_FATAL_ERROR', 7); /** * Passed to pg_result_error_field. * The severity; the field contents are ERROR, * FATAL, or PANIC (in an error message), or * WARNING, NOTICE, DEBUG, * INFO, or LOG (in a notice message), or a localized * translation of one of these. Always present. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_SEVERITY', 83); /** * Passed to pg_result_error_field. * The SQLSTATE code for the error. The SQLSTATE code identifies the type of error * that has occurred; it can be used by front-end applications to perform specific * operations (such as error handling) in response to a particular database error. * This field is not localizable, and is always present. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_SQLSTATE', 67); /** * Passed to pg_result_error_field. * The primary human-readable error message (typically one line). Always present. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_MESSAGE_PRIMARY', 77); /** * Passed to pg_result_error_field. * Detail: an optional secondary error message carrying more detail about the problem. May run to multiple lines. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_MESSAGE_DETAIL', 68); /** * Passed to pg_result_error_field. * Hint: an optional suggestion what to do about the problem. This is intended to differ from detail in that it * offers advice (potentially inappropriate) rather than hard facts. May run to multiple lines. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_MESSAGE_HINT', 72); /** * Passed to pg_result_error_field. * A string containing a decimal integer indicating an error cursor position as an index into the original * statement string. The first character has index 1, and positions are measured in characters not bytes. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_STATEMENT_POSITION', 80); /** * Passed to pg_result_error_field. * This is defined the same as the PG_DIAG_STATEMENT_POSITION field, but * it is used when the cursor position refers to an internally generated * command rather than the one submitted by the client. The * PG_DIAG_INTERNAL_QUERY field will always appear when this * field appears. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_INTERNAL_POSITION', 112); /** * Passed to pg_result_error_field. * The text of a failed internally-generated command. This could be, for example, a * SQL query issued by a PL/pgSQL function. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_INTERNAL_QUERY', 113); /** * Passed to pg_result_error_field. * An indication of the context in which the error occurred. Presently * this includes a call stack traceback of active procedural language * functions and internally-generated queries. The trace is one entry * per line, most recent first. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_CONTEXT', 87); /** * Passed to pg_result_error_field. * The file name of the PostgreSQL source-code location where the error * was reported. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_SOURCE_FILE', 70); /** * Passed to pg_result_error_field. * The line number of the PostgreSQL source-code location where the * error was reported. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_SOURCE_LINE', 76); /** * Passed to pg_result_error_field. * The name of the PostgreSQL source-code function reporting the error. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_DIAG_SOURCE_FUNCTION', 82); /** * Passed to pg_convert. * Ignore default values in the table during conversion. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_CONV_IGNORE_DEFAULT', 2); /** * Passed to pg_convert. * Use SQL NULL in place of an empty string. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_CONV_FORCE_NULL', 4); /** * Passed to pg_convert. * Ignore conversion of NULL into SQL NOT NULL columns. * @link https://php.net/manual/en/pgsql.constants.php */ define('PGSQL_CONV_IGNORE_NOT_NULL', 8); define('PGSQL_DML_NO_CONV', 256); define('PGSQL_DML_EXEC', 512); define('PGSQL_DML_ASYNC', 1024); define('PGSQL_DML_STRING', 2048); /** * @link https://php.net/manual/en/function.pg-last-notice.php * @since 7.1 */ define('PGSQL_NOTICE_LAST', 1); /** * @link https://php.net/manual/en/function.pg-last-notice.php * @since 7.1 */ define('PGSQL_NOTICE_ALL', 2); /** * @link https://php.net/manual/en/function.pg-last-notice.php * @since 7.1 */ define('PGSQL_NOTICE_CLEAR', 3); const PGSQL_CONNECT_ASYNC = 4; const PGSQL_CONNECTION_AUTH_OK = 5; const PGSQL_CONNECTION_AWAITING_RESPONSE = 4; const PGSQL_CONNECTION_MADE = 3; const PGSQL_CONNECTION_SETENV = 6; const PGSQL_CONNECTION_STARTED = 2; const PGSQL_DML_ESCAPE = 4096; const PGSQL_POLLING_ACTIVE = 4; const PGSQL_POLLING_FAILED = 0; const PGSQL_POLLING_OK = 3; const PGSQL_POLLING_READING = 1; const PGSQL_POLLING_WRITING = 2; const PGSQL_DIAG_SCHEMA_NAME = 115; const PGSQL_DIAG_TABLE_NAME = 116; const PGSQL_DIAG_COLUMN_NAME = 99; const PGSQL_DIAG_DATATYPE_NAME = 100; const PGSQL_DIAG_CONSTRAINT_NAME = 110; const PGSQL_DIAG_SEVERITY_NONLOCALIZED = 86; const PGSQL_ERRORS_SQLSTATE = 0; const PGSQL_TRACE_REGRESS_MODE = 2; const PGSQL_PIPELINE_SYNC = 10; const PGSQL_PIPELINE_ON = 1; const PGSQL_PIPELINE_OFF = 0; const PGSQL_PIPELINE_ABORTED = 2; const PGSQL_SHOW_CONTEXT_NEVER = 0; const PGSQL_SHOW_CONTEXT_ERRORS = 1; const PGSQL_SHOW_CONTEXT_ALWAYS = 2; // End of pgsql v. 'string'], default: '')] protected $sqlstate; /** * The error code * * @var int */ protected $code; /** * @since 8.1 */ public function getSqlState(): string {} } /** * MySQLi Driver. * @link https://php.net/manual/en/class.mysqli-driver.php */ final class mysqli_driver { /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $client_info; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $client_version; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $driver_version; /** * @var string */ public $embedded; /** * @var bool */ #[LanguageLevelTypeAware(['8.1' => 'bool'], default: '')] public $reconnect; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $report_mode; } /** * Represents a connection between PHP and a MySQL database. * @link https://php.net/manual/en/class.mysqli.php */ class mysqli { /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'string|int'], default: '')] public $affected_rows; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $client_info; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $client_version; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $connect_errno; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $connect_error; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $errno; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $error; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $field_count; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $host_info; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $info; /** * @var int|string */ #[LanguageLevelTypeAware(['8.1' => 'int|string'], default: '')] public $insert_id; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $server_info; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $server_version; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $sqlstate; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $protocol_version; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $thread_id; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $warning_count; /** * @var array A list of errors, each as an associative array containing the errno, error, and sqlstate. * @link https://secure.php.net/manual/en/mysqli.error-list.php */ #[LanguageLevelTypeAware(['8.1' => 'array'], default: '')] public $error_list; public $stat; /** * Open a new connection to the MySQL server * @link https://php.net/manual/en/mysqli.construct.php * @param string $hostname [optional] Can be either a host name or an IP address. Passing the NULL value or the string "localhost" to this parameter, the local host is assumed. When possible, pipes will be used instead of the TCP/IP protocol. Prepending host by p: opens a persistent connection. mysqli_change_user() is automatically called on connections opened from the connection pool. Defaults to ini_get("mysqli.default_host") * @param string $username [optional] The MySQL user name. Defaults to ini_get("mysqli.default_user") * @param string $password [optional] If not provided or NULL, the MySQL server will attempt to authenticate the user against those user records which have no password only. This allows one username to be used with different permissions (depending on if a password as provided or not). Defaults to ini_get("mysqli.default_pw") * @param string $database [optional] If provided will specify the default database to be used when performing queries. Defaults to "" * @param int $port [optional] Specifies the port number to attempt to connect to the MySQL server. Defaults to ini_get("mysqli.default_port") * @param string $socket [optional] Specifies the socket or named pipe that should be used. Defaults to ini_get("mysqli.default_socket") */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $hostname = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $username = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $password = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $database = null, #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $port = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $socket = null ) {} /** * Turns on or off auto-committing database modifications * @link https://php.net/manual/en/mysqli.autocommit.php * @param bool $enable

    * Whether to turn on auto-commit or not. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function autocommit(#[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $enable): bool {} /** * Starts a transaction * @link https://secure.php.net/manual/en/mysqli.begin-transaction.php * @param int $flags [optional] * @param string $name [optional] * @return bool true on success or false on failure. * @since 5.5 */ #[TentativeType] public function begin_transaction( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $name = null ): bool {} /** * Changes the user of the specified database connection * @link https://php.net/manual/en/mysqli.change-user.php * @param string $username

    * The MySQL user name. *

    * @param string $password

    * The MySQL password. *

    * @param string|null $database

    * The database to change to. *

    *

    * If desired, the null value may be passed resulting in only changing * the user and not selecting a database. To select a database in this * case use the mysqli_select_db function. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function change_user( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $username, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $password, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $database ): bool {} /** * Returns the current character set of the database connection * @link https://php.net/manual/en/mysqli.character-set-name.php * @return string The current character set of the connection */ #[TentativeType] public function character_set_name(): string {} /** * @removed 5.4 */ #[Deprecated(since: '5.3')] public function client_encoding() {} /** * Closes a previously opened database connection * @link https://php.net/manual/en/mysqli.close.php * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function close() {} /** * Commits the current transaction * @link https://php.net/manual/en/mysqli.commit.php * @param int $flags A bitmask of MYSQLI_TRANS_COR_* constants. * @param string|null $name If provided then COMMIT $name is executed. * @return bool true on success or false on failure. */ #[TentativeType] public function commit( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $name = null ): bool {} /** * @link https://php.net/manual/en/function.mysqli-connect.php * @param string|null $hostname [optional] * @param string|null $username [optional] * @param string|null $password [optional] * @param string|null $database [optional] * @param int|null $port [optional] * @param string|null $socket [optional] * @return bool */ #[TentativeType] public function connect( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $hostname = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $username = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $password = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $database = null, #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $port = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $socket = null ): bool {} /** * Dump debugging information into the log * @link https://php.net/manual/en/mysqli.dump-debug-info.php * @return bool true on success or false on failure. */ #[TentativeType] public function dump_debug_info(): bool {} /** * Performs debugging operations * @link https://php.net/manual/en/mysqli.debug.php * @param string $options

    * A string representing the debugging operation to perform *

    * @return bool true. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function debug(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $options) {} /** * Returns a character set object * @link https://php.net/manual/en/mysqli.get-charset.php * @return object|null The function returns a character set object with the following properties: * charset *

    Character set name

    * collation *

    Collation name

    * dir *

    Directory the charset description was fetched from (?) or "" for built-in character sets

    * min_length *

    Minimum character length in bytes

    * max_length *

    Maximum character length in bytes

    * number *

    Internal character set number

    * state *

    Character set status (?)

    */ #[TentativeType] public function get_charset(): ?object {} /** * @param mysqli $mysql * @param string $query * @param array|null $params * @return mysqli_result|bool * @see mysqli_execute_query * @since 8.2 */ public function execute_query(string $query, ?array $params = null): mysqli_result|bool {} /** * Returns the MySQL client version as a string * @link https://php.net/manual/en/mysqli.get-client-info.php * @return string A string that represents the MySQL client library version */ #[TentativeType] public function get_client_info(): string {} /** * Returns statistics about the client connection * @link https://php.net/manual/en/mysqli.get-connection-stats.php * @return array an array with connection stats. */ #[TentativeType] public function get_connection_stats(): array {} /** * Returns the version of the MySQL server * @link https://php.net/manual/en/mysqli.get-server-info.php * @return string A character string representing the server version. */ #[TentativeType] public function get_server_info(): string {} /** * Get result of SHOW WARNINGS * @link https://php.net/manual/en/mysqli.get-warnings.php * @return mysqli_warning|false */ #[TentativeType] public function get_warnings(): mysqli_warning|false {} /** * Initializes MySQLi object * @link https://php.net/manual/en/mysqli.init.php * @return bool|null * @deprecated 8.1 */ public function init() {} /** * Asks the server to kill a MySQL thread * @link https://php.net/manual/en/mysqli.kill.php * @param int $process_id * @return bool true on success or false on failure. */ #[TentativeType] public function kill(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $process_id): bool {} /** * Performs one or more queries on the database * @link https://php.net/manual/en/mysqli.multi-query.php * @param string $query

    * A string containing the queries to be executed. * Multiple queries must be separated by a semicolon. *

    *

    * If the query contains any variable input then parameterized * prepared statements should be used instead. Alternatively, * the data must be properly formatted and all strings must be * escaped using the mysqli_real_escape_string function. *

    * @return bool false if the first statement failed. * To retrieve subsequent errors from other statements you have to call * mysqli_next_result first. */ #[TentativeType] public function multi_query(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $query): bool {} /** * @link https://php.net/manual/en/mysqli.construct.php * @param string $host [optional] * @param string $username [optional] * @param string $password [optional] * @param string $database [optional] * @param int $port [optional] * @param string $socket [optional] * * @removed 8.0 */ public function mysqli($host = null, $username = null, $password = null, $database = null, $port = null, $socket = null) {} /** * Check if there are any more query results from a multi query * @link https://php.net/manual/en/mysqli.more-results.php * @return bool true on success or false on failure. */ #[TentativeType] public function more_results(): bool {} /** * Prepare next result from multi_query * @link https://php.net/manual/en/mysqli.next-result.php * @return bool true on success or false on failure. */ #[TentativeType] public function next_result(): bool {} /** * Set options * @link https://php.net/manual/en/mysqli.options.php * @param int $option

    * The option that you want to set. It can be one of the following values: *

    * Valid options * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    NameDescription
    MYSQLI_OPT_CONNECT_TIMEOUTconnection timeout in seconds (supported on Windows with TCP/IP since PHP 5.3.1)
    MYSQLI_OPT_LOCAL_INFILEenable/disable use of LOAD LOCAL INFILE
    MYSQLI_INIT_COMMANDcommand to execute after when connecting to MySQL server
    MYSQLI_READ_DEFAULT_FILE * Read options from named option file instead of my.cnf *
    MYSQLI_READ_DEFAULT_GROUP * Read options from the named group from my.cnf * or the file specified with MYSQL_READ_DEFAULT_FILE *
    MYSQLI_SERVER_PUBLIC_KEY * RSA public key file used with the SHA-256 based authentication. *
    *

    * @param string|int $value

    * The value for the option. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function options(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $option, $value): bool {} /** * Pings a server connection, or tries to reconnect if the connection has gone down * @link https://php.net/manual/en/mysqli.ping.php * @return bool true on success or false on failure. */ #[TentativeType] public function ping(): bool {} /** * Prepares an SQL statement for execution * @link https://php.net/manual/en/mysqli.prepare.php * @param string $query

    * The query, as a string. It must consist of a single SQL statement. *

    *

    * The SQL statement may contain zero or more parameter markers * represented by question mark (?) characters * at the appropriate positions. *

    *

    * The markers are legal only in certain places in SQL statements. * For example, they are permitted in the VALUES() * list of an INSERT statement (to specify column * values for a row), or in a comparison with a column in a * WHERE clause to specify a comparison value. *

    *

    * However, they are not permitted for identifiers (such as table or * column names), or to specify both operands of a binary operator such as the = equal * sign. The latter restriction is necessary because it would be * impossible to determine the parameter type. * In general, parameters are legal * only in Data Manipulation Language (DML) statements, and not in Data * Definition Language (DDL) statements. *

    * @return mysqli_stmt|false mysqli_prepare returns a statement object or false if an error occurred. */ #[TentativeType] public function prepare(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $query): mysqli_stmt|false {} /** * Performs a query on the database * @link https://php.net/manual/en/mysqli.query.php * @param string $query

    * The query string. *

    *

    * If the query contains any variable input then parameterized * prepared statements should be used instead. Alternatively, * the data must be properly formatted and all strings must be * escaped using the mysqli_real_escape_string function. *

    * @param int $result_mode [optional]

    * The result mode can be one of 3 constants indicating * how the result will be returned from the MySQL server. *

    *

    * MYSQLI_STORE_RESULT (default) - returns a mysqli_result * object with buffered result set. *

    *

    * MYSQLI_USE_RESULT - returns a mysqli_result object * with unbuffered result set. As long as there are pending records * waiting to be fetched, the connection line will be busy and all * subsequent calls will return error Commands out of sync. To avoid * the error all records must be fetched from the server or the result * set must be discarded by calling mysqli_free_result. *

    *

    * MYSQLI_ASYNC (available with mysqlnd) - the query is performed * asynchronously and no result set is immediately returned. * mysqli_poll is then used to get results from such queries. * Used in combination with either * MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT constant. *

    * @return mysqli_result|bool Returns false on failure. * For successful queries which produce a result set, * such as SELECT, SHOW, DESCRIBE or EXPLAIN, * mysqli_query will return a mysqli_result object. * For other successful queries mysqli_query will * return true. */ #[TentativeType] public function query( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $query, #[PhpStormStubsElementAvailable(from: '7.1')] int $result_mode = MYSQLI_STORE_RESULT ): mysqli_result|bool {} /** * Opens a connection to a mysql server * @link https://php.net/manual/en/mysqli.real-connect.php * @param string $hostname [optional]

    * Can be either a host name or an IP address. Passing the null value * or the string "localhost" to this parameter, the local host is * assumed. When possible, pipes will be used instead of the TCP/IP * protocol. *

    * @param string $username [optional]

    * The MySQL user name. *

    * @param string $password [optional]

    * If provided or null, the MySQL server will attempt to authenticate * the user against those user records which have no password only. This * allows one username to be used with different permissions (depending * on if a password as provided or not). *

    * @param string $database [optional]

    * If provided will specify the default database to be used when * performing queries. *

    * @param int $port [optional]

    * Specifies the port number to attempt to connect to the MySQL server. *

    * @param string $socket [optional]

    * Specifies the socket or named pipe that should be used. *

    *

    * Specifying the socket parameter will not * explicitly determine the type of connection to be used when * connecting to the MySQL server. How the connection is made to the * MySQL database is determined by the host * parameter. *

    * @param int $flags [optional]

    * With the parameter flags you can set different * connection options: *

    * * Supported flags * * * * * * * * * * * * * * * * * * * * * * * * *
    NameDescription
    MYSQLI_CLIENT_COMPRESSUse compression protocol
    MYSQLI_CLIENT_FOUND_ROWSreturn number of matched rows, not the number of affected rows
    MYSQLI_CLIENT_IGNORE_SPACEAllow spaces after function names. Makes all function names reserved words.
    MYSQLI_CLIENT_INTERACTIVE * Allow interactive_timeout seconds (instead of * wait_timeout seconds) of inactivity before closing the connection *
    MYSQLI_CLIENT_SSLUse SSL (encryption)
    *

    * For security reasons the MULTI_STATEMENT flag is * not supported in PHP. If you want to execute multiple queries use the * mysqli_multi_query function. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function real_connect( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $hostname = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $username = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $password = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $database = null, #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $port = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $socket = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0 ): bool {} /** * Escapes special characters in a string for use in an SQL statement, taking into account the current charset of the connection * @link https://php.net/manual/en/mysqli.real-escape-string.php * @param string $string

    * The string to be escaped. *

    *

    * Characters encoded are NUL (ASCII 0), \n, \r, \, ', ", and * Control-Z. *

    * @return string an escaped string. */ #[TentativeType] public function real_escape_string(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $string): string {} /** * Poll connections * @link https://php.net/manual/en/mysqli.poll.php * @param array &$read

    *

    * @param array &$error

    *

    * @param array &$reject

    *

    * @param int $seconds

    * Number of seconds to wait, must be non-negative. *

    * @param int $microseconds [optional]

    * Number of microseconds to wait, must be non-negative. *

    * @return int|false number of ready connections in success, false otherwise. */ #[TentativeType] public static function poll( #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: '')] &$read, #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: '')] &$error, #[LanguageLevelTypeAware(['8.0' => 'array'], default: '')] &$reject, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $seconds, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $microseconds = 0 ): int|false {} /** * Get result from async query * @link https://php.net/manual/en/mysqli.reap-async-query.php * @return mysqli_result|false mysqli_result in success, false otherwise. */ #[TentativeType] public function reap_async_query(): mysqli_result|bool {} /** * Escapes special characters in a string for use in an SQL statement, taking into account the current charset of the connection * @param string $string The string to be escaped. * Characters encoded are NUL (ASCII 0), \n, \r, \, ', ", and Control-Z. * @return string * @link https://secure.php.net/manual/en/mysqli.real-escape-string.php */ #[TentativeType] public function escape_string(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $string): string {} /** * Execute an SQL query * @link https://php.net/manual/en/mysqli.real-query.php * @param string $query

    * The query, as a string. *

    *

    * If the query contains any variable input then parameterized * prepared statements should be used instead. Alternatively, * the data must be properly formatted and all strings must be * escaped using the mysqli_real_escape_string function. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function real_query(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $query): bool {} /** * Removes the named savepoint from the set of savepoints of the current transaction * @link https://php.net/manual/en/mysqli.release-savepoint.php * @param string $name The identifier of the savepoint. * @return bool Returns TRUE on success or FALSE on failure. * @since 5.5 */ #[TentativeType] public function release_savepoint(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): bool {} /** * Rolls back current transaction * @link https://php.net/manual/en/mysqli.rollback.php * @param int $flags [optional] A bitmask of MYSQLI_TRANS_COR_* constants. * @param string $name [optional] If provided then ROLLBACK $name is executed. * @return bool true on success or false on failure. * @since 5.5 Added flags and name parameters. */ #[TentativeType] public function rollback( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $name = null ): bool {} /** * Set a named transaction savepoint * @link https://secure.php.net/manual/en/mysqli.savepoint.php * @param string $name * @return bool Returns TRUE on success or FALSE on failure. * @since 5.5 */ #[TentativeType] public function savepoint(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): bool {} /** * Selects the default database for database queries * @link https://php.net/manual/en/mysqli.select-db.php * @param string $database

    * The database name. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function select_db(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $database): bool {} /** * Sets the client character set * @link https://php.net/manual/en/mysqli.set-charset.php * @param string $charset

    * The desired character set. *

    * @return bool true on success or false on failure */ #[TentativeType] public function set_charset(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $charset): bool {} /** * @link https://php.net/manual/en/function.mysqli-set-opt * @param int $option * @param string|int $value */ #[TentativeType] public function set_opt(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $option, $value): bool {} /** * Used for establishing secure connections using SSL * @link https://secure.php.net/manual/en/mysqli.ssl-set.php * @param string|null $key

    * The path name to the key file. *

    * @param string|null $certificate

    * The path name to the certificate file. *

    * @param string|null $ca_certificate

    * The path name to the certificate authority file. *

    * @param string|null $ca_path

    * The pathname to a directory that contains trusted SSL CA certificates in PEM format. *

    * @param string|null $cipher_algos

    * A list of allowable ciphers to use for SSL encryption. *

    * @return bool This function always returns TRUE value. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function ssl_set( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $key, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $certificate, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $ca_certificate, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $ca_path, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $cipher_algos ) {} /** * Gets the current system status * @link https://php.net/manual/en/mysqli.stat.php * @return string|false A string describing the server status. false if an error occurred. */ #[TentativeType] public function stat(): string|false {} /** * Initializes a statement and returns an object for use with mysqli_stmt_prepare * @link https://php.net/manual/en/mysqli.stmt-init.php * @return mysqli_stmt an object. */ #[TentativeType] public function stmt_init(): mysqli_stmt|false {} /** * Transfers a result set from the last query * @link https://php.net/manual/en/mysqli.store-result.php * @param int $mode [optional] The option that you want to set * @return mysqli_result|false a buffered result object or false if an error occurred. *

    *

    * mysqli_store_result returns false in case the query * didn't return a result set (if the query was, for example an INSERT * statement). This function also returns false if the reading of the * result set failed. You can check if you have got an error by checking * if mysqli_error doesn't return an empty string, if * mysqli_errno returns a non zero value, or if * mysqli_field_count returns a non zero value. * Also possible reason for this function returning false after * successful call to mysqli_query can be too large * result set (memory for it cannot be allocated). If * mysqli_field_count returns a non-zero value, the * statement should have produced a non-empty result set. */ #[TentativeType] public function store_result(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode = 0): mysqli_result|false {} /** * Returns whether thread safety is given or not * @link https://php.net/manual/en/mysqli.thread-safe.php * @return bool true if the client library is thread-safe, otherwise false. */ #[TentativeType] public function thread_safe(): bool {} /** * Initiate a result set retrieval * @link https://php.net/manual/en/mysqli.use-result.php * @return mysqli_result|false an unbuffered result object or false if an error occurred. */ #[TentativeType] public function use_result(): mysqli_result|false {} /** * @link https://php.net/manual/en/mysqli.refresh * @param int $flags MYSQLI_REFRESH_* * @return bool TRUE if the refresh was a success, otherwise FALSE * @since 5.3 */ #[TentativeType] public function refresh(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags): bool {} } /** * Represents one or more MySQL warnings. * @link https://php.net/manual/en/class.mysqli-warning.php */ final class mysqli_warning { /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $message; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $sqlstate; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $errno; /** * The __construct purpose * @link https://php.net/manual/en/mysqli-warning.construct.php */ #[PhpStormStubsElementAvailable(from: '8.0')] private function __construct() {} /** * The __construct purpose * @link https://php.net/manual/en/mysqli-warning.construct.php */ #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] protected function __construct() {} /** * Move to the next warning * @link https://php.net/manual/en/mysqli-warning.next.php * @return bool True if it successfully moved to the next warning */ public function next(): bool {} } /** * Represents the result set obtained from a query against the database. * Implements Traversable since 5.4 * @link https://php.net/manual/en/class.mysqli-result.php */ class mysqli_result implements IteratorAggregate { /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $current_field; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $field_count; /** * @var array|null */ #[LanguageLevelTypeAware(['8.1' => 'array|null'], default: '')] public $lengths; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int|string'], default: '')] public $num_rows; /** * @var mixed */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $type; /** * Constructor (no docs available) * @param object $mysql * @param int $result_mode [optional] */ public function __construct( #[PhpStormStubsElementAvailable(from: '8.0')] mysqli $mysql, #[PhpStormStubsElementAvailable(from: '8.0')] int $result_mode = MYSQLI_STORE_RESULT ) {} /** * Frees the memory associated with a result * @return void * @link https://php.net/manual/en/mysqli-result.free.php */ #[TentativeType] public function close(): void {} /** * Frees the memory associated with a result * @link https://php.net/manual/en/mysqli-result.free.php * @return void */ #[TentativeType] public function free(): void {} /** * Adjusts the result pointer to an arbitrary row in the result * @link https://php.net/manual/en/mysqli-result.data-seek.php * @param int $offset

    * The field offset. Must be between zero and the total number of rows * minus one (0..mysqli_num_rows - 1). *

    * @return bool true on success or false on failure. */ #[TentativeType] public function data_seek(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset): bool {} /** * Returns the next field in the result set * @link https://php.net/manual/en/mysqli-result.fetch-field.php * @return object|false an object which contains field definition information or false * if no field information is available. *

    *

    *

    * Object properties * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    PropertyDescription
    nameThe name of the column
    orgnameOriginal column name if an alias was specified
    tableThe name of the table this field belongs to (if not calculated)
    orgtableOriginal table name if an alias was specified
    defReserved for default value, currently always ""
    dbDatabase (since PHP 5.3.6)
    catalogThe catalog name, always "def" (since PHP 5.3.6)
    max_lengthThe maximum width of the field for the result set.
    lengthThe width of the field, as specified in the table definition.
    charsetnrThe character set number for the field.
    flagsAn integer representing the bit-flags for the field.
    typeThe data type used for this field
    decimalsThe number of decimals used (for integer fields)
    */ #[TentativeType] public function fetch_field(): object|false {} /** * Returns an array of objects representing the fields in a result set * @link https://php.net/manual/en/mysqli-result.fetch-fields.php * @return array an array of objects containing field definition information. *

    *

    *

    * Object properties * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    PropertyDescription
    nameThe name of the column
    orgnameOriginal column name if an alias was specified
    tableThe name of the table this field belongs to (if not calculated)
    orgtableOriginal table name if an alias was specified
    defThe default value for this field, represented as a string
    max_lengthThe maximum width of the field for the result set.
    lengthThe width of the field, as specified in the table definition.
    charsetnrThe character set number for the field.
    flagsAn integer representing the bit-flags for the field.
    typeThe data type used for this field
    decimalsThe number of decimals used (for integer fields)
    */ #[TentativeType] public function fetch_fields(): array {} /** * Fetch meta-data for a single field * @link https://php.net/manual/en/mysqli-result.fetch-field-direct.php * @param int $index

    * The field number. This value must be in the range from * 0 to number of fields - 1. *

    * @return object|false an object which contains field definition information or false * if no field information for specified fieldnr is * available. *

    *

    *

    * Object attributes * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    AttributeDescription
    nameThe name of the column
    orgnameOriginal column name if an alias was specified
    tableThe name of the table this field belongs to (if not calculated)
    orgtableOriginal table name if an alias was specified
    defThe default value for this field, represented as a string
    max_lengthThe maximum width of the field for the result set.
    lengthThe width of the field, as specified in the table definition.
    charsetnrThe character set number for the field.
    flagsAn integer representing the bit-flags for the field.
    typeThe data type used for this field
    decimalsThe number of decimals used (for integer fields)
    */ #[TentativeType] public function fetch_field_direct(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index): object|false {} /** * Fetches all result rows as an associative array, a numeric array, or both * @link https://php.net/manual/en/mysqli-result.fetch-all.php * @param int $mode [optional]

    * This optional parameter is a constant indicating what type of array * should be produced from the current row data. The possible values for * this parameter are the constants MYSQLI_ASSOC, * MYSQLI_NUM, or MYSQLI_BOTH. *

    * @return array an array of associative or numeric arrays holding result rows. */ #[TentativeType] public function fetch_all(#[PhpStormStubsElementAvailable(from: '7.0')] int $mode = MYSQLI_NUM): array {} /** * Fetch the next row of a result set as an associative, a numeric array, or both * @link https://php.net/manual/en/mysqli-result.fetch-array.php * @param int $mode [optional]

    * This optional parameter is a constant indicating what type of array * should be produced from the current row data. The possible values for * this parameter are the constants MYSQLI_ASSOC, * MYSQLI_NUM, or MYSQLI_BOTH. *

    *

    * By using the MYSQLI_ASSOC constant this function * will behave identically to the mysqli_fetch_assoc, * while MYSQLI_NUM will behave identically to the * mysqli_fetch_row function. The final option * MYSQLI_BOTH will create a single array with the * attributes of both. *

    * @return array|false|null an array representing the fetched row, null if there * are no more rows in the result set, or false on failure. */ #[TentativeType] public function fetch_array(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode = MYSQLI_BOTH): array|false|null {} /** * Fetch the next row of a result set as an associative array * @link https://php.net/manual/en/mysqli-result.fetch-assoc.php * @return array|false|null an associative array representing the fetched row, * where each key in the array represents the name of one of the result set's columns, null if there * are no more rows in the result set, or false on failure. */ #[TentativeType] public function fetch_assoc(): array|false|null {} /** * @template T * * Fetch the next row of a result set as an object * @link https://php.net/manual/en/mysqli-result.fetch-object.php * @param class-string $class [optional]

    * The name of the class to instantiate, set the properties of and return. * If not specified, a stdClass object is returned. *

    * @param null|array $constructor_args [optional]

    * An optional array of parameters to pass to the constructor * for class_name objects. *

    * @return T|stdClass|false|null an object representing the fetched row, where each property * represents the name of the result set's column, null if there * are no more rows in the result set, or false on failure. */ #[TentativeType] public function fetch_object(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $class = 'stdClass', array $constructor_args = []): object|false|null {} /** * Fetch the next row of a result set as an enumerated array * @link https://php.net/manual/en/mysqli-result.fetch-row.php * @return array|false|null an enumerated array representing * the fetched row, null if there * are no more rows in the result set, or false on failure. */ #[TentativeType] public function fetch_row(): array|false|null {} /** * Fetch a single column from the next row of a result set * * @param int $column [optional]

    * 0-indexed number of the column you wish to retrieve from the row. * If no value is supplied, the first column will be returned. *

    * @return string|int|float|false|null a single column from * the next row of a result set or false if there are no more rows. */ #[PhpStormStubsElementAvailable('8.1')] public function fetch_column(int $column = 0): string|int|float|false|null {} /** * Set result pointer to a specified field offset * @link https://php.net/manual/en/mysqli-result.field-seek.php * @param int $index

    * The field number. This value must be in the range from * 0 to number of fields - 1. *

    */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function field_seek(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index) {} /** * Frees the memory associated with a result * @return void * @link https://php.net/manual/en/mysqli-result.free.php */ #[TentativeType] public function free_result(): void {} /** * @return Iterator * @since 8.0 */ public function getIterator(): Iterator {} } /** * Represents a prepared statement. * @link https://php.net/manual/en/class.mysqli-stmt.php */ class mysqli_stmt { /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int|string'], default: '')] public $affected_rows; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int|string'], default: '')] public $insert_id; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int|string'], default: '')] public $num_rows; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $param_count; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $field_count; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $errno; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $error; /** * @var array */ #[LanguageLevelTypeAware(['8.1' => 'array'], default: '')] public $error_list; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $sqlstate; /** * @var string */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $id; /** * mysqli_stmt constructor * @param mysqli $mysql * @param string $query [optional] */ public function __construct($mysql, $query) {} /** * Used to get the current value of a statement attribute * @link https://php.net/manual/en/mysqli-stmt.attr-get.php * @param int $attribute The attribute that you want to get. * @return int Returns the value of the attribute. */ #[TentativeType] public function attr_get(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $attribute): int {} /** * Used to modify the behavior of a prepared statement * @link https://php.net/manual/en/mysqli-stmt.attr-set.php * @param int $attribute

    * The attribute that you want to set. It can have one of the following values: *

    * Attribute values * * * * * * * * * * * * * * * * *
    CharacterDescription
    MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH * If set to 1, causes mysqli_stmt_store_result to * update the metadata MYSQL_FIELD->max_length value. *
    MYSQLI_STMT_ATTR_CURSOR_TYPE * Type of cursor to open for statement when mysqli_stmt_execute * is invoked. mode can be MYSQLI_CURSOR_TYPE_NO_CURSOR * (the default) or MYSQLI_CURSOR_TYPE_READ_ONLY. *
    MYSQLI_STMT_ATTR_PREFETCH_ROWS * Number of rows to fetch from server at a time when using a cursor. * mode can be in the range from 1 to the maximum * value of unsigned long. The default is 1. *
    *

    *

    * If you use the MYSQLI_STMT_ATTR_CURSOR_TYPE option with * MYSQLI_CURSOR_TYPE_READ_ONLY, a cursor is opened for the * statement when you invoke mysqli_stmt_execute. If there * is already an open cursor from a previous mysqli_stmt_execute call, * it closes the cursor before opening a new one. mysqli_stmt_reset * also closes any open cursor before preparing the statement for re-execution. * mysqli_stmt_free_result closes any open cursor. *

    *

    * If you open a cursor for a prepared statement, mysqli_stmt_store_result * is unnecessary. *

    * @param int $value

    The value to assign to the attribute.

    * @return bool */ #[TentativeType] public function attr_set( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $attribute, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $value ): bool {} /** * Binds variables to a prepared statement as parameters * @link https://php.net/manual/en/mysqli-stmt.bind-param.php * @param string $types

    * A string that contains one or more characters which specify the types * for the corresponding bind variables: *

    * Type specification chars * * * * * * * * * * * * * * * * * * * * *
    CharacterDescription
    icorresponding variable has type integer
    dcorresponding variable has type double
    scorresponding variable has type string
    bcorresponding variable is a blob and will be sent in packets
    *

    * @param mixed &$var1

    * The number of variables and length of string * types must match the parameters in the statement. *

    * @param mixed &...$_ [optional] * @return bool true on success or false on failure. */ public function bind_param($types, &$var1, &...$_) {} /** * Binds variables to a prepared statement for result storage * @link https://php.net/manual/en/mysqli-stmt.bind-result.php * @param mixed &$var1 The variable to be bound. * @param mixed &...$_ The variables to be bound. * @return bool true on success or false on failure. */ public function bind_result(&$var1, &...$_) {} /** * Closes a prepared statement * @link https://php.net/manual/en/mysqli-stmt.close.php * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function close() {} /** * Seeks to an arbitrary row in statement result set * @link https://php.net/manual/en/mysqli-stmt.data-seek.php * @param int $offset

    * Must be between zero and the total number of rows minus one (0.. * mysqli_stmt_num_rows - 1). *

    * @return void */ #[TentativeType] public function data_seek(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset): void {} /** * Executes a prepared statement * @link https://php.net/manual/en/mysqli-stmt.execute.php * @param array|null $params [optional] An optional list array with as many elements * as there are bound parameters in the SQL statement being executed. Each value is treated as a string. * @return bool true on success or false on failure. */ #[TentativeType] public function execute(#[PhpStormStubsElementAvailable('8.1')] ?array $params = null): bool {} /** * Fetch results from a prepared statement into the bound variables * @link https://php.net/manual/en/mysqli-stmt.fetch.php * @return bool|null */ #[TentativeType] public function fetch(): ?bool {} /** * Get result of SHOW WARNINGS * @link https://php.net/manual/en/mysqli-stmt.get-warnings.php * @return object|false */ #[TentativeType] public function get_warnings(): mysqli_warning|false {} /** * Returns result set metadata from a prepared statement * @link https://php.net/manual/en/mysqli-stmt.result-metadata.php * @return mysqli_result|false a result object or false if an error occurred. */ #[TentativeType] public function result_metadata(): mysqli_result|false {} /** * Check if there are more query results from a multiple query * @link https://php.net/manual/en/mysqli-stmt.more-results.php * @return bool */ #[TentativeType] public function more_results(): bool {} /** * Reads the next result from a multiple query * @link https://php.net/manual/en/mysqli-stmt.next-result.php * @return bool */ #[TentativeType] public function next_result(): bool {} /** * Return the number of rows in statements result set * @link https://php.net/manual/en/mysqli-stmt.num-rows.php * @return string|int An integer representing the number of rows in result set. */ #[TentativeType] public function num_rows(): string|int {} /** * Send data in blocks * @link https://php.net/manual/en/mysqli-stmt.send-long-data.php * @param int $param_num

    * Indicates which parameter to associate the data with. Parameters are * numbered beginning with 0. *

    * @param string $data

    * A string containing data to be sent. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function send_long_data( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $param_num, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data ): bool {} /** * No documentation available * @removed 5.4 */ #[Deprecated(since: '5.3')] public function stmt() {} /** * Frees stored result memory for the given statement handle * @link https://php.net/manual/en/mysqli-stmt.free-result.php * @return void */ #[TentativeType] public function free_result(): void {} /** * Resets a prepared statement * @link https://php.net/manual/en/mysqli-stmt.reset.php * @return bool true on success or false on failure. */ #[TentativeType] public function reset(): bool {} /** * Prepare an SQL statement for execution * @link https://php.net/manual/en/mysqli-stmt.prepare.php * @param string $query

    * The query, as a string. It must consist of a single SQL statement. *

    *

    * The SQL statement may contain zero or more parameter markers * represented by question mark (?) characters at the appropriate positions. *

    *

    * The markers are legal only in certain places in SQL statements. * For example, they are permitted in the VALUES() list of an INSERT statement * (to specify column values for a row), or in a comparison with a column in * a WHERE clause to specify a comparison value. *

    *

    * However, they are not permitted for identifiers (such as table or column names), * or to specify both operands of a binary operator such as the = * equal sign. The latter restriction is necessary because it would be impossible * to determine the parameter type. In general, parameters are legal only in Data * Manipulation Language (DML) statements, and not in Data Definition Language * (DDL) statements. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function prepare(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $query): bool {} /** * Stores a result set in an internal buffer * @link https://php.net/manual/en/mysqli-stmt.store-result.php * @return bool true on success or false on failure. */ #[TentativeType] public function store_result(): bool {} /** * Gets a result set from a prepared statement as a mysqli_result object * @link https://php.net/manual/en/mysqli-stmt.get-result.php * @return mysqli_result|false Returns a resultset or FALSE on failure */ #[TentativeType] public function get_result(): mysqli_result|false {} } /** * Gets the number of affected rows in a previous MySQL operation * @link https://secure.php.net/manual/en/mysqli.affected-rows.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string|int An integer greater than zero indicates the number of rows affected or retrieved. * Zero indicates that no records were updated for an UPDATE statement, * no rows matched the WHERE clause in the query or that no query has yet been executed. -1 indicates that the query returned an error * or that mysqli_affected_rows was called for an unbuffered SELECT query. */ function mysqli_affected_rows(mysqli $mysql): string|int {} /** * Turns on or off auto-committing database modifications * @link https://secure.php.net/manual/en/mysqli.autocommit.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param bool $enable Whether to turn on auto-commit or not. * @return bool */ function mysqli_autocommit(mysqli $mysql, bool $enable): bool {} /** * Starts a transaction * @link https://secure.php.net/manual/en/mysqli.begin-transaction.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param int $flags [optional] * @param string|null $name [optional] * @return bool true on success or false on failure. * @since 5.5 */ function mysqli_begin_transaction(mysqli $mysql, int $flags = 0, ?string $name): bool {} /** * Changes the user of the specified database connection * @link https://php.net/manual/en/mysqli.change-user.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $username The MySQL user name. * @param string $password The MySQL password. * @param string|null $database The database to change to. If desired, the NULL value may be passed resulting in only changing the user and not selecting a database. * @return bool */ function mysqli_change_user(mysqli $mysql, string $username, string $password, ?string $database): bool {} /** * Returns the current character set of the database connection * @link https://php.net/manual/en/mysqli.character-set-name.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string The current character set of the connection */ function mysqli_character_set_name(mysqli $mysql): string {} /** * Closes a previously opened database connection * @link https://php.net/manual/en/mysqli.close.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return bool */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function mysqli_close(mysqli $mysql): bool {} /** * Commits the current transaction * @link https://php.net/manual/en/mysqli.commit.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param int $flags [optional] A bitmask of MYSQLI_TRANS_COR_* constants * @param string|null $name [optional] If provided then COMMITname is executed * @return bool */ function mysqli_commit(mysqli $mysql, int $flags = 0, ?string $name = null): bool {} /** * Open a new connection to the MySQL server * Alias of mysqli::__construct * @link https://php.net/manual/en/mysqli.construct.php * @param string|null $hostname Can be either a host name or an IP address. Passing the NULL value or the string "localhost" to this parameter, the local host is assumed. When possible, pipes will be used instead of the TCP/IP protocol. * @param string|null $username The MySQL user name. * @param string|null $password If not provided or NULL, the MySQL server will attempt to authenticate the user against those user records which have no password only. * @param string|null $database If provided will specify the default database to be used when performing queries. * @param int|null $port Specifies the port number to attempt to connect to the MySQL server. * @param string|null $socket Specifies the socket or named pipe that should be used. * @return mysqli|false object which represents the connection to a MySQL Server or false if an error occurred. */ function mysqli_connect(?string $hostname = null, ?string $username = null, ?string $password = null, ?string $database = null, ?int $port = null, ?string $socket = null): mysqli|false {} /** * Returns the error code from last connect call * @link https://php.net/manual/en/mysqli.connect-errno.php * @return int Last error code number from the last call to mysqli_connect(). Zero means no error occurred. */ function mysqli_connect_errno(): int {} /** * Returns a string description of the last connect error * @link https://php.net/manual/en/mysqli.connect-error.php * @return string|null Last error message string from the last call to mysqli_connect(). */ function mysqli_connect_error(): ?string {} /** * Adjusts the result pointer to an arbitrary row in the result * @link https://php.net/manual/en/mysqli-result.data-seek.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @param int $offset * @return bool Returns TRUE on success or FALSE on failure. */ function mysqli_data_seek(mysqli_result $result, int $offset): bool {} /** * Dump debugging information into the log * @link https://php.net/manual/en/mysqli.dump-debug-info.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return bool */ function mysqli_dump_debug_info(mysqli $mysql): bool {} /** * Performs debugging operations using the Fred Fish debugging library. * @link https://php.net/manual/en/mysqli.debug.php * @param string $options * @return bool */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function mysqli_debug(string $options): bool {} /** * Returns the error code for the most recent function call * @link https://php.net/manual/en/mysqli.errno.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return int An error code value for the last call, if it failed. zero means no error occurred. */ function mysqli_errno(mysqli $mysql): int {} /** * Returns a list of errors from the last command executed * @link https://php.net/manual/en/mysqli.error-list.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return array A list of errors, each as an associative array containing the errno, error, and sqlstate. * @since 5.4 */ #[ArrayShape([ "errno" => "int", "sqlstate" => "string", "error" => "string", ])] function mysqli_error_list(mysqli $mysql): array {} /** * Returns a list of errors from the last statement executed * @link https://secure.php.net/manual/en/mysqli-stmt.error-list.php * @param mysqli_stmt $statement A statement identifier returned by mysqli_stmt_init(). * @return array A list of errors, each as an associative array containing the errno, error, and sqlstate. * @since 5.4 */ function mysqli_stmt_error_list(mysqli_stmt $statement): array {} /** * Returns a string description of the last error * @link https://secure.php.net/manual/en/mysqli.error.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string */ function mysqli_error(mysqli $mysql): string {} /** * Executes a prepared statement * @link https://php.net/manual/en/mysqli-stmt.execute.php * @param mysqli_stmt $statement * @param array|null $params [optional] An optional list array with as many elements * as there are bound parameters in the SQL statement being executed. Each value is treated as a string. * @return bool true on success or false on failure. */ function mysqli_stmt_execute(mysqli_stmt $statement, #[PhpStormStubsElementAvailable('8.1')] ?array $params = null): bool {} /** * Executes a prepared statement * Alias for mysqli_stmt_execute * @link https://php.net/manual/en/function.mysqli-execute.php * @param mysqli_stmt $statement * @param array|null $params [optional] An optional list array with as many elements * as there are bound parameters in the SQL statement being executed. Each value is treated as a string. * @return bool */ function mysqli_execute(mysqli_stmt $statement, #[PhpStormStubsElementAvailable('8.1')] ?array $params = null): bool {} /** * @param mysqli $mysql * @param string $query * @param array|null $params * @return mysqli_result|bool * @since 8.2 */ function mysqli_execute_query(mysqli $mysql, string $query, ?array $params = null): mysqli_result|bool {} /** * Returns the next field in the result set * @link https://secure.php.net/manual/en/mysqli-result.fetch-field.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @return object|false Returns an object which contains field definition information or FALSE if no field information is available. */ function mysqli_fetch_field(mysqli_result $result): object|false {} /** * Returns an array of objects representing the fields in a result set * @link https://secure.php.net/manual/en/mysqli-result.fetch-fields.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @return array Returns an array of objects which contains field definition information. */ function mysqli_fetch_fields(mysqli_result $result): array {} /** * Fetch meta-data for a single field * @link https://secure.php.net/manual/en/mysqli-result.fetch-field-direct.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @param int $index The field number. This value must be in the range from 0 to number of fields - 1. * @return object|false Returns an object which contains field definition information or FALSE if no field information for specified fieldnr is available. */ function mysqli_fetch_field_direct(mysqli_result $result, int $index): object|false {} /** * Returns the lengths of the columns of the current row in the result set * @link https://php.net/manual/en/mysqli-result.lengths.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @return int[]|false An array of integers representing the size of each column (not including any terminating null characters). FALSE if an error occurred. */ function mysqli_fetch_lengths(mysqli_result $result): array|false {} /** * Fetch all result rows as an associative array, a numeric array, or both * @link https://php.net/manual/en/mysqli-result.fetch-all.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @param int $mode * @return array Returns an array of associative or numeric arrays holding result rows. */ function mysqli_fetch_all( mysqli_result $result, #[PhpStormStubsElementAvailable(from: '7.0')] int $mode = MYSQLI_NUM ): array {} /** * Fetch the next row of a result set as an associative, a numeric array, or both * @link https://php.net/manual/en/mysqli-result.fetch-array.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @param int $mode * @return array|false|null an array representing the fetched row, * null if there are no more rows in the result set, or false on failure. */ function mysqli_fetch_array(mysqli_result $result, int $mode = MYSQLI_BOTH): array|false|null {} /** * Fetch the next row of a result set as an associative array * @link https://php.net/manual/en/mysqli-result.fetch-assoc.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @return array|false|null an associative array representing the fetched row, * where each key in the array represents the name of one of the result set's columns, * null if there are no more rows in the result set, or false on failure. */ function mysqli_fetch_assoc(mysqli_result $result): array|null|false {} /** * @template T * * Fetch the next row of a result set as an object * @link https://php.net/manual/en/mysqli-result.fetch-object.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @param class-string $class [optional] The name of the class to instantiate, set the properties of and return. If not specified, a stdClass object is returned. * @param array $constructor_args [optional] An optional array of parameters to pass to the constructor for class_name objects. * @return T|stdClass|null|false an object representing the fetched row, * where each property represents the name of the result set's column, * null if there are no more rows in the result set, or false on failure. */ function mysqli_fetch_object(mysqli_result $result, string $class = 'stdClass', array $constructor_args = []): object|null|false {} /** * Fetch the next row of a result set as an enumerated array * @link https://php.net/manual/en/mysqli-result.fetch-row.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @return array|null|false an enumerated array representing the fetched row, * null if there are no more rows in the result set, or false on failure. * @link https://php.net/manual/en/mysqli-result.fetch-row.php */ function mysqli_fetch_row(mysqli_result $result): array|false|null {} /** * Fetch a single column from the next row of a result set * @link https://php.net/manual/en/mysqli-result.fetch-column.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @param int $column [optional]

    * 0-indexed number of the column you wish to retrieve from the row. * If no value is supplied, the first column will be returned. *

    * @return string|int|float|false|null a single column from * the next row of a result set or false if there are no more rows. */ #[PhpStormStubsElementAvailable('8.1')] function mysqli_fetch_column(mysqli_result $result, int $column = 0): string|int|float|false|null {} /** * Returns the number of columns for the most recent query * @link https://php.net/manual/en/mysqli.field-count.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return int An integer representing the number of fields in a result set. */ function mysqli_field_count(mysqli $mysql): int {} /** * Set result pointer to a specified field offset * @link https://php.net/manual/en/mysqli-result.field-seek.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @param int $index The field number. This value must be in the range from 0 to number of fields - 1. */ #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] function mysqli_field_seek(mysqli_result $result, int $index) {} /** * Get current field offset of a result pointer * @link https://php.net/manual/en/mysqli-result.current-field.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @return int */ function mysqli_field_tell(mysqli_result $result): int {} /** * Frees the memory associated with a result * @link https://php.net/manual/en/mysqli-result.free.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @return void */ function mysqli_free_result(mysqli_result $result): void {} /** * Returns client Zval cache statistics * Available only with mysqlnd. * @link https://php.net/manual/en/function.mysqli-get-cache-stats.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return array|false an array with client Zval cache stats if success, false otherwise. * @removed 5.4 */ function mysqli_get_cache_stats(mysqli $mysql) {} /** * Returns statistics about the client connection * @link https://php.net/manual/en/mysqli.get-connection-stats.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return array an array with connection stats. */ function mysqli_get_connection_stats(mysqli $mysql): array {} /** * Returns client per-process statistics * @link https://php.net/manual/en/function.mysqli-get-client-stats.php * @return array an array with client stats. */ function mysqli_get_client_stats(): array {} /** * Returns a character set object * @link https://php.net/manual/en/mysqli.get-charset.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return object|null */ function mysqli_get_charset(mysqli $mysql): ?object {} /** * Get MySQL client info * @link https://php.net/manual/en/mysqli.get-client-info.php * @param mysqli|null $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string|null A string that represents the MySQL client library version */ #[LanguageLevelTypeAware(['8.0' => 'string'], default: '?string')] function mysqli_get_client_info( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.1')] mysqli $mysql, #[PhpStormStubsElementAvailable(from: '8.0')] ?mysqli $mysql = null ) {} /** * Returns the MySQL client version as an integer * @link https://php.net/manual/en/mysqli.get-client-version.php * @return int */ function mysqli_get_client_version(#[PhpStormStubsElementAvailable(from: '5.3', to: '7.3')] $link): int {} /** * Returns a string representing the type of connection used * @link https://php.net/manual/en/mysqli.get-host-info.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string A character string representing the server hostname and the connection type. */ function mysqli_get_host_info(mysqli $mysql): string {} /** * Return information about open and cached links * @link https://php.net/manual/en/function.mysqli-get-links-stats.php * @return array mysqli_get_links_stats() returns an associative array with three elements, keyed as follows: *
    *
    * total
    *
    *

    * An integer indicating the total number of open links in * any state. *

    *
    * *
    * active_plinks
    *
    *

    * An integer representing the number of active persistent * connections. *

    *
    * *
    * cached_plinks
    *
    *

    * An integer representing the number of inactive persistent * connections. *

    *
    * *
    * @since 5.6 */ #[ArrayShape(["total" => "int", "active_plinks" => "int", "cached_plinks" => "int"])] function mysqli_get_links_stats(): array {} /** * Returns the version of the MySQL protocol used * @link https://php.net/manual/en/mysqli.get-proto-info.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return int Returns an integer representing the protocol version */ function mysqli_get_proto_info(mysqli $mysql): int {} /** * Returns the version of the MySQL server * @link https://php.net/manual/en/mysqli.get-server-info.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string A character string representing the server version. */ function mysqli_get_server_info(mysqli $mysql): string {} /** * Returns the version of the MySQL server as an integer * @link https://php.net/manual/en/mysqli.get-server-version.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return int An integer representing the server version. * The form of this version number is main_version * 10000 + minor_version * 100 + sub_version (i.e. version 4.1.0 is 40100). */ function mysqli_get_server_version(mysqli $mysql): int {} /** * Get result of SHOW WARNINGS * @link https://php.net/manual/en/mysqli.get-warnings.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return mysqli_warning|false */ function mysqli_get_warnings(mysqli $mysql): mysqli_warning|false {} /** * Initializes MySQLi and returns a resource for use with mysqli_real_connect() * @link https://php.net/manual/en/mysqli.init.php * @return mysqli|false * @see mysqli_real_connect() */ function mysqli_init(): mysqli|false {} /** * Retrieves information about the most recently executed query * @link https://php.net/manual/en/mysqli.info.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string|null A character string representing additional information about the most recently executed query. */ function mysqli_info(mysqli $mysql): ?string {} /** * Returns the value generated for an AUTO_INCREMENT column by the last query * @link https://php.net/manual/en/mysqli.insert-id.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return int|string The value of the AUTO_INCREMENT field that was updated by the previous query. Returns zero if there was no previous query on the connection or if the query did not update an AUTO_INCREMENT value. * If the number is greater than the maximum int value, it will be returned as a string. */ function mysqli_insert_id(mysqli $mysql): string|int {} /** * Asks the server to kill a MySQL thread * @link https://php.net/manual/en/mysqli.kill.php * @see mysqli_thread_id() * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param int $process_id * @return bool */ #[Deprecated("The function is deprecated", since: "8.4")] function mysqli_kill(mysqli $mysql, int $process_id): bool {} /** * Unsets user defined handler for load local infile command * @link https://php.net/manual/en/mysqli.set-local-infile-default.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return void * @removed 5.5 */ function mysqli_set_local_infile_default(mysqli $mysql) {} /** * Set callback function for LOAD DATA LOCAL INFILE command * @link https://php.net/manual/en/mysqli.set-local-infile-handler.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param callable $read_func * @return bool * @removed 5.5 */ function mysqli_set_local_infile_handler(mysqli $mysql, callable $read_func): bool {} /** * Check if there are any more query results from a multi query * @link https://php.net/manual/en/mysqli.more-results.php * @see mysqli_multi_query() * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return bool */ function mysqli_more_results(mysqli $mysql): bool {} /** * Performs one or more queries on the database * @link https://php.net/manual/en/mysqli.multi-query.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $query A string containing the queries to be executed. Multiple queries must be separated by a semicolon. * @return bool Returns FALSE if the first statement failed. To retrieve subsequent errors from other statements you have to call mysqli_next_result() first. */ function mysqli_multi_query( mysqli $mysql, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] string $query, #[PhpStormStubsElementAvailable(from: '7.1', to: '7.4')] string $query = null, #[PhpStormStubsElementAvailable(from: '8.0')] string $query ): bool {} /** * Prepare next result from multi_query * @link https://php.net/manual/en/mysqli.next-result.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return bool */ function mysqli_next_result(mysqli $mysql): bool {} /** * Gets the number of fields in the result set * @link https://php.net/manual/en/mysqli-result.field-count.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @return int */ function mysqli_num_fields(mysqli_result $result): int {} /** * Gets the number of rows in a result * @link https://php.net/manual/en/mysqli-result.num-rows.php * @param mysqli_result $result A mysqli_result object returned by mysqli_query(), * mysqli_store_result(), mysqli_use_result() or mysqli_stmt_get_result(). * @return string|int Returns number of rows in the result set. */ function mysqli_num_rows(mysqli_result $result): string|int {} /** * Set options * @link https://php.net/manual/en/mysqli.options.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param int $option * @param string|int $value * @return bool */ function mysqli_options(mysqli $mysql, int $option, $value): bool {} /** * Pings a server connection, or tries to reconnect if the connection has gone down * @link https://php.net/manual/en/mysqli.ping.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return bool */ #[Deprecated("The function is deprecated", since: "8.4")] function mysqli_ping(mysqli $mysql): bool {} /** * Poll connections * @link https://php.net/manual/en/mysqli.poll.php * @param array|null &$read * @param array|null &$error * @param array &$reject * @param int $seconds * @param int $microseconds [optional] * @return int|false number of ready connections upon success, FALSE otherwise. */ function mysqli_poll(?array &$read, ?array &$error, array &$reject, int $seconds, int $microseconds = 0): int|false {} /** * Prepares an SQL statement for execution * @link https://php.net/manual/en/mysqli.prepare.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $query The query, as a string. It must consist of a single SQL statement. * The SQL statement may contain zero or more parameter markers represented by question mark (?) characters at the appropriate positions. * @return mysqli_stmt|false A statement object or FALSE if an error occurred. */ function mysqli_prepare(mysqli $mysql, string $query): mysqli_stmt|false {} /** * Enables or disables internal report functions * @link https://php.net/manual/en/function.mysqli-report.php * @param int $flags

    *

    * Supported flags * * * * * * * * * * * * * * * * * * * * * * * * *
    NameDescription
    MYSQLI_REPORT_OFFTurns reporting off
    MYSQLI_REPORT_ERRORReport errors from mysqli function calls
    MYSQLI_REPORT_STRICT * Throw mysqli_sql_exception for errors * instead of warnings *
    MYSQLI_REPORT_INDEXReport if no index or bad index was used in a query
    MYSQLI_REPORT_ALLSet all options (report all)
    *

    * @return bool */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] function mysqli_report(int $flags) {} /** * Performs a query on the database * @link https://php.net/manual/en/mysqli.query.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $query An SQL query * @param int $result_mode * @return mysqli_result|bool * For successful SELECT, SHOW, DESCRIBE or EXPLAIN queries, mysqli_query() will return a mysqli_result object. * For other successful queries mysqli_query() will return TRUE. * Returns FALSE on failure. */ function mysqli_query( mysqli $mysql, string $query, #[PhpStormStubsElementAvailable(from: '7.1')] int $result_mode = MYSQLI_STORE_RESULT ): mysqli_result|bool {} /** * Opens a connection to a mysql server * @link https://php.net/manual/en/mysqli.real-connect.php * @see mysqli_connect() * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string|null $hostname [optional] * @param string|null $username [optional] * @param string|null $password [optional] * @param string|null $database [optional] * @param int|null $port [optional] * @param string|null $socket [optional] * @param int $flags * @return bool */ function mysqli_real_connect(mysqli $mysql, ?string $hostname, ?string $username, ?string $password, ?string $database, ?int $port, ?string $socket, int $flags = 0): bool {} /** * Escapes special characters in a string for use in an SQL statement, taking into account the current charset of the connection * @link https://php.net/manual/en/mysqli.real-escape-string.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $string The string to be escaped. Characters encoded are NUL (ASCII 0), \n, \r, \, ', ", and Control-Z. * @return string */ function mysqli_real_escape_string(mysqli $mysql, string $string): string {} /** * Execute an SQL query * @link https://php.net/manual/en/mysqli.real-query.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $query * @return bool */ function mysqli_real_query( mysqli $mysql, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] string $query, #[PhpStormStubsElementAvailable(from: '7.1', to: '7.4')] string $query = null, #[PhpStormStubsElementAvailable(from: '8.0')] string $query ): bool {} /** * Get result from async query * Available only with mysqlnd. * @link https://php.net/manual/en/mysqli.reap-async-query.php * @see mysqli_poll() * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return mysqli_result|bool mysqli_result in success, FALSE otherwise. */ function mysqli_reap_async_query(mysqli $mysql): mysqli_result|bool {} /** * Removes the named savepoint from the set of savepoints of the current transaction * @link https://secure.php.net/manual/en/mysqli.release-savepoint.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $name * @return bool Returns TRUE on success or FALSE on failure. * @since 5.5 */ function mysqli_release_savepoint(mysqli $mysql, string $name): bool {} /** * Rolls back current transaction * @link https://php.net/manual/en/mysqli.rollback.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param int $flags [optional] A bitmask of MYSQLI_TRANS_COR_* constants * @param string|null $name [optional] If provided then ROLLBACKname is executed * @return bool */ function mysqli_rollback(mysqli $mysql, int $flags = 0, ?string $name): bool {} /** * Set a named transaction savepoint * @link https://secure.php.net/manual/en/mysqli.savepoint.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $name * @return bool Returns TRUE on success or FALSE on failure. * @since 5.5 */ function mysqli_savepoint(mysqli $mysql, string $name): bool {} /** * Selects the default database for database queries * @link https://php.net/manual/en/mysqli.select-db.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $database * @return bool */ function mysqli_select_db(mysqli $mysql, string $database): bool {} /** * Sets the client character set * @link https://php.net/manual/en/mysqli.set-charset.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $charset * @return bool */ function mysqli_set_charset(mysqli $mysql, string $charset): bool {} /** * Returns the total number of rows changed, deleted, inserted, or matched by the last statement executed * @link https://php.net/manual/en/mysqli-stmt.affected-rows.php * @param mysqli_stmt $statement * @return int|string If the number of affected rows is greater than maximum PHP int value, the number of affected rows will be returned as a string value. */ function mysqli_stmt_affected_rows(mysqli_stmt $statement): string|int {} /** * Used to get the current value of a statement attribute * @link https://php.net/manual/en/mysqli-stmt.attr-get.php * @param mysqli_stmt $statement * @param int $attribute * @return int|false Returns FALSE if the attribute is not found, otherwise returns the value of the attribute. */ #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function mysqli_stmt_attr_get(mysqli_stmt $statement, int $attribute): false|int {} /** * Used to modify the behavior of a prepared statement * @link https://php.net/manual/en/mysqli-stmt.attr-set.php * @param mysqli_stmt $statement * @param int $attribute * @param int $value * @return bool */ function mysqli_stmt_attr_set(mysqli_stmt $statement, int $attribute, int $value): bool {} /** * Returns the number of fields in the given statement * @link https://php.net/manual/en/mysqli-stmt.field-count.php * @param mysqli_stmt $statement * @return int */ function mysqli_stmt_field_count(mysqli_stmt $statement): int {} /** * Initializes a statement and returns an object for use with mysqli_stmt_prepare * @link https://php.net/manual/en/mysqli.stmt-init.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return mysqli_stmt|false */ function mysqli_stmt_init(mysqli $mysql): mysqli_stmt|false {} /** * Prepares an SQL statement for execution * @link https://php.net/manual/en/mysqli-stmt.prepare.php * @param mysqli_stmt $statement * @param string $query * @return bool */ function mysqli_stmt_prepare(mysqli_stmt $statement, string $query): bool {} /** * Returns result set metadata from a prepared statement * @link https://php.net/manual/en/mysqli-stmt.result-metadata.php * @param mysqli_stmt $statement * @return mysqli_result|false Returns a result object or FALSE if an error occurred */ function mysqli_stmt_result_metadata(mysqli_stmt $statement): mysqli_result|false {} /** * Send data in blocks * @link https://php.net/manual/en/mysqli-stmt.send-long-data.php * @param mysqli_stmt $statement * @param int $param_num * @param string $data * @return bool */ function mysqli_stmt_send_long_data(mysqli_stmt $statement, int $param_num, string $data): bool {} /** * Binds variables to a prepared statement as parameters * @link https://php.net/manual/en/mysqli-stmt.bind-param.php * @param mysqli_stmt $statement A statement identifier returned by mysqli_stmt_init() * @param string $types

    * A string that contains one or more characters which specify the types * for the corresponding bind variables: *

    * Type specification chars * * * * * * * * * * * * * * * * * * * * *
    CharacterDescription
    icorresponding variable has type integer
    dcorresponding variable has type double
    scorresponding variable has type string
    bcorresponding variable is a blob and will be sent in packets
    *

    * @param mixed &$var1

    * The number of variables and length of string * types must match the parameters in the statement. *

    * @param mixed &...$vars * @return bool true on success or false on failure. */ function mysqli_stmt_bind_param( mysqli_stmt $statement, string $types, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] mixed &$vars, mixed &...$vars ): bool {} /** * Binds variables to a prepared statement for result storage * @link https://php.net/manual/en/mysqli-stmt.bind-result.php * @param mysqli_stmt $statement Statement * @param mixed &...$vars The variables to be bound. * @return bool */ function mysqli_stmt_bind_result( mysqli_stmt $statement, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] mixed &$vars, mixed &...$vars ): bool {} /** * Fetch results from a prepared statement into the bound variables * @link https://php.net/manual/en/mysqli-stmt.fetch.php * @param mysqli_stmt $statement * @return bool|null */ function mysqli_stmt_fetch(mysqli_stmt $statement): ?bool {} /** * Frees stored result memory for the given statement handle * @link https://php.net/manual/en/mysqli-stmt.free-result.php * @param mysqli_stmt $statement * @return void */ function mysqli_stmt_free_result(mysqli_stmt $statement): void {} /** * Gets a result set from a prepared statement as a mysqli_result object * @link https://php.net/manual/en/mysqli-stmt.get-result.php * @param mysqli_stmt $statement * @return mysqli_result|false Returns false on failure. For successful queries which produce a result set, * such as SELECT, SHOW, DESCRIBE or EXPLAIN, mysqli_stmt_get_result() will return a mysqli_result object. * For other successful queries, mysqli_stmt_get_result() will return false. */ function mysqli_stmt_get_result(mysqli_stmt $statement): mysqli_result|false {} /** * Get result of SHOW WARNINGS * @link https://php.net/manual/en/mysqli-stmt.get-warnings.php * @param mysqli_stmt $statement * @return mysqli_warning|false (not documented, but it's probably a mysqli_warning object) */ function mysqli_stmt_get_warnings(mysqli_stmt $statement): mysqli_warning|false {} /** * Get the ID generated from the previous INSERT operation * @link https://php.net/manual/en/mysqli-stmt.insert-id.php * @param mysqli_stmt $statement * @return string|int */ function mysqli_stmt_insert_id(mysqli_stmt $statement): string|int {} /** * Resets a prepared statement * @link https://php.net/manual/en/mysqli-stmt.reset.php * @param mysqli_stmt $statement * @return bool */ function mysqli_stmt_reset(mysqli_stmt $statement): bool {} /** * Returns the number of parameter for the given statement * @link https://php.net/manual/en/mysqli-stmt.param-count.php * @param mysqli_stmt $statement * @return int */ function mysqli_stmt_param_count(mysqli_stmt $statement): int {} /** * Returns the SQLSTATE error from previous MySQL operation * @link https://php.net/manual/en/mysqli.sqlstate.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string Returns a string containing the SQLSTATE error code for the last error. The error code consists of five characters. '00000' means no error. */ function mysqli_sqlstate(mysqli $mysql): string {} /** * Gets the current system status * @link https://php.net/manual/en/mysqli.stat.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string|false A string describing the server status. FALSE if an error occurred. */ function mysqli_stat(mysqli $mysql): string|false {} /** * Used for establishing secure connections using SSL * @link https://secure.php.net/manual/en/mysqli.ssl-set.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string|null $key The path name to the key file * @param string|null $certificate The path name to the certificate file * @param string|null $ca_certificate The path name to the certificate authority file * @param string|null $ca_path The pathname to a directory that contains trusted SSL CA certificates in PEM format * @param string|null $cipher_algos A list of allowable ciphers to use for SSL encryption * @return bool This function always returns TRUE value. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function mysqli_ssl_set( mysqli $mysql, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: 'string')] $key, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: 'string')] $certificate, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: 'string')] $ca_certificate, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: 'string')] $ca_path, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: 'string')] $cipher_algos ): bool {} /** * Closes a prepared statement * @link https://php.net/manual/en/mysqli-stmt.close.php * @param mysqli_stmt $statement * @return bool */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function mysqli_stmt_close(mysqli_stmt $statement): bool {} /** * Seeks to an arbitrary row in statement result set * @link https://php.net/manual/en/mysqli-stmt.data-seek.php * @param mysqli_stmt $statement * @param int $offset * @return void */ function mysqli_stmt_data_seek(mysqli_stmt $statement, int $offset): void {} /** * Returns the error code for the most recent statement call * @link https://php.net/manual/en/mysqli-stmt.errno.php * @param mysqli_stmt $statement * @return int */ function mysqli_stmt_errno(mysqli_stmt $statement): int {} /** * Returns a string description for last statement error * @link https://php.net/manual/en/mysqli-stmt.error.php * @param mysqli_stmt $statement * @return string */ function mysqli_stmt_error(mysqli_stmt $statement): string {} /** * Check if there are more query results from a multiple query * @link https://php.net/manual/en/mysqli-stmt.more-results.php * @param mysqli_stmt $statement * @return bool */ function mysqli_stmt_more_results(mysqli_stmt $statement): bool {} /** * Reads the next result from a multiple query * @link https://php.net/manual/en/mysqli-stmt.next-result.php * @param mysqli_stmt $statement * @return bool */ function mysqli_stmt_next_result(mysqli_stmt $statement): bool {} /** * Return the number of rows in statements result set * @link https://php.net/manual/en/mysqli-stmt.num-rows.php * @param mysqli_stmt $statement * @return string|int */ function mysqli_stmt_num_rows(mysqli_stmt $statement): string|int {} /** * Returns SQLSTATE error from previous statement operation * @link https://php.net/manual/en/mysqli-stmt.sqlstate.php * @param mysqli_stmt $statement * @return string Returns a string containing the SQLSTATE error code for the last error. The error code consists of five characters. '00000' means no error. */ function mysqli_stmt_sqlstate(mysqli_stmt $statement): string {} /** * Transfers a result set from a prepared statement * @link https://php.net/manual/en/mysqli-stmt.store-result.php * @param mysqli_stmt $statement * @return bool */ function mysqli_stmt_store_result(mysqli_stmt $statement): bool {} /** * Transfers a result set from the last query * @link https://php.net/manual/en/mysqli.store-result.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param int $mode [optional] The option that you want to set * @return mysqli_result|false */ function mysqli_store_result(mysqli $mysql, int $mode = 0): mysqli_result|false {} /** * Returns the thread ID for the current connection * @link https://php.net/manual/en/mysqli.thread-id.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return int Returns the Thread ID for the current connection. */ function mysqli_thread_id(mysqli $mysql): int {} /** * Returns whether thread safety is given or not * @link https://php.net/manual/en/mysqli.thread-safe.php * @return bool */ function mysqli_thread_safe(): bool {} /** * Initiate a result set retrieval * @link https://php.net/manual/en/mysqli.use-result.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return mysqli_result|false */ function mysqli_use_result(mysqli $mysql): mysqli_result|false {} /** * Returns the number of warnings from the last query for the given link * @link https://php.net/manual/en/mysqli.warning-count.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return int */ function mysqli_warning_count(mysqli $mysql): int {} /** * Flushes tables or caches, or resets the replication server information * @link https://php.net/manual/en/mysqli.refresh.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param int $flags * @return bool */ #[Deprecated("The function is deprecated", since: "8.4")] function mysqli_refresh(mysqli $mysql, int $flags): bool {} /** * Alias for mysqli_stmt_bind_param * @link https://php.net/manual/en/function.mysqli-bind-param.php * @param mysqli_stmt $statement * @param string $types * @removed 5.4 */ #[Deprecated(since: '5.3')] function mysqli_bind_param(mysqli_stmt $statement, string $types) {} /** * Alias for mysqli_stmt_bind_result * @link https://php.net/manual/en/function.mysqli-bind-result.php * @param mysqli_stmt $statement * @param string $types * @param mixed &$var1 * @removed 5.4 */ #[Deprecated(since: '5.3')] function mysqli_bind_result(mysqli_stmt $statement, string $types, mixed &$var1) {} /** * Alias of mysqli_character_set_name * @link https://php.net/manual/en/function.mysqli-client-encoding.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @return string * @removed 5.4 */ #[Deprecated(since: '5.3')] function mysqli_client_encoding(mysqli $mysql): string {} /** * Alias of mysqli_real_escape_string * @link https://php.net/manual/en/function.mysqli-escape-string.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param string $string The string to be escaped * @return string */ function mysqli_escape_string( mysqli $mysql, string $string, #[PhpStormStubsElementAvailable(from: '7.1', to: '7.4')] $resultmode = null ): string {} /** * Alias for mysqli_stmt_fetch * @link https://php.net/manual/en/function.mysqli-fetch.php * @param mysqli_stmt $statement * @return bool * @removed 5.4 */ #[Deprecated(since: '5.3')] function mysqli_fetch(mysqli_stmt $statement): bool {} /** * Alias for mysqli_stmt_param_count * @link https://php.net/manual/en/function.mysqli-param-count.php * @param mysqli_stmt $statement * @return int * @removed 5.4 */ #[Deprecated(since: '5.3')] function mysqli_param_count(mysqli_stmt $statement): int {} /** * Alias for mysqli_stmt_result_metadata * @link https://php.net/manual/en/function.mysqli-get-metadata.php * @param mysqli_stmt $statement * @return mysqli_result|false Returns a result object or FALSE if an error occurred * @removed 5.4 */ #[Deprecated(since: '5.3')] function mysqli_get_metadata(mysqli_stmt $statement): false|mysqli_result {} /** * Alias for mysqli_stmt_send_long_data * @link https://php.net/manual/en/function.mysqli-send-long-data.php * @param mysqli_stmt $statement * @param int $param_num * @param string $data * @return bool * @removed 5.4 */ #[Deprecated(since: '5.3')] function mysqli_send_long_data(mysqli_stmt $statement, int $param_num, string $data): bool {} /** * Alias of mysqli_options * @link https://php.net/manual/en/function.mysqli-set-opt.php * @param mysqli $mysql A link identifier returned by mysqli_connect() or mysqli_init() * @param int $option * @param string|int $value * @return bool */ function mysqli_set_opt( #[PhpStormStubsElementAvailable(from: '8.0')] mysqli $mysql, #[PhpStormStubsElementAvailable(from: '8.0')] int $option, #[PhpStormStubsElementAvailable(from: '8.0')] $value ): bool {} /** *

    * Read options from the named group from my.cnf * or the file specified with MYSQLI_READ_DEFAULT_FILE *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_READ_DEFAULT_GROUP', 5); /** *

    * Read options from the named option file instead of from my.cnf *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_READ_DEFAULT_FILE', 4); /** *

    * Connect timeout in seconds *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_OPT_CONNECT_TIMEOUT', 0); /** *

    * Enables command LOAD LOCAL INFILE *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_OPT_LOCAL_INFILE', 8); /** *

    * RSA public key file used with the SHA-256 based authentication. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_SERVER_PUBLIC_KEY', 35); /** *

    * Command to execute when connecting to MySQL server. Will automatically be re-executed when reconnecting. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_INIT_COMMAND', 3); define('MYSQLI_OPT_NET_CMD_BUFFER_SIZE', 202); define('MYSQLI_OPT_NET_READ_BUFFER_SIZE', 203); define('MYSQLI_OPT_INT_AND_FLOAT_NATIVE', 201); /** *

    * Use SSL (encrypted protocol). This option should not be set by application programs; * it is set internally in the MySQL client library *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_CLIENT_SSL', 2048); /** *

    * Use compression protocol *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_CLIENT_COMPRESS', 32); /** *

    * Allow interactive_timeout seconds * (instead of wait_timeout seconds) of inactivity before * closing the connection. The client's session * wait_timeout variable will be set to * the value of the session interactive_timeout variable. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_CLIENT_INTERACTIVE', 1024); /** *

    * Allow spaces after function names. Makes all functions names reserved words. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_CLIENT_IGNORE_SPACE', 256); /** *

    * Don't allow the db_name.tbl_name.col_name syntax. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_CLIENT_NO_SCHEMA', 16); define('MYSQLI_CLIENT_FOUND_ROWS', 2); /** *

    * For using buffered resultsets *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_STORE_RESULT', 0); /** *

    * For using unbuffered resultsets *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_USE_RESULT', 1); define('MYSQLI_ASYNC', 8); /** *

    * Columns are returned into the array having the fieldname as the array index. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_ASSOC', 1); /** *

    * Columns are returned into the array having an enumerated index. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_NUM', 2); /** *

    * Columns are returned into the array having both a numerical index and the fieldname as the associative index. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_BOTH', 3); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH', 0); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_STMT_ATTR_CURSOR_TYPE', 1); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_CURSOR_TYPE_NO_CURSOR', 0); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_CURSOR_TYPE_READ_ONLY', 1); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_CURSOR_TYPE_FOR_UPDATE', 2); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_CURSOR_TYPE_SCROLLABLE', 4); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_STMT_ATTR_PREFETCH_ROWS', 2); /** *

    * Indicates that a field is defined as NOT NULL *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_NOT_NULL_FLAG', 1); /** *

    * Field is part of a primary index *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_PRI_KEY_FLAG', 2); /** *

    * Field is part of a unique index. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_UNIQUE_KEY_FLAG', 4); /** *

    * Field is part of an index. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_MULTIPLE_KEY_FLAG', 8); /** *

    * Field is defined as BLOB *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_BLOB_FLAG', 16); /** *

    * Field is defined as UNSIGNED *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_UNSIGNED_FLAG', 32); /** *

    * Field is defined as ZEROFILL *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_ZEROFILL_FLAG', 64); /** *

    * Field is defined as AUTO_INCREMENT *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_AUTO_INCREMENT_FLAG', 512); /** *

    * Field is defined as TIMESTAMP *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TIMESTAMP_FLAG', 1024); /** *

    * Field is defined as SET *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_SET_FLAG', 2048); /** *

    * Field is defined as NUMERIC *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_NUM_FLAG', 32768); /** *

    * Field is part of an multi-index *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_PART_KEY_FLAG', 16384); /** *

    * Field is part of GROUP BY *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_GROUP_FLAG', 32768); /** *

    * Field is defined as ENUM. Available since PHP 5.3.0. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_ENUM_FLAG', 256); define('MYSQLI_BINARY_FLAG', 128); define('MYSQLI_NO_DEFAULT_VALUE_FLAG', 4096); define('MYSQLI_ON_UPDATE_NOW_FLAG', 8192); define('MYSQLI_TRANS_START_READ_ONLY', 4); define('MYSQLI_TRANS_START_READ_WRITE', 2); define('MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT', 1); /** *

    * Field is defined as DECIMAL *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_DECIMAL', 0); /** *

    * Field is defined as TINYINT *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_TINY', 1); /** *

    * Field is defined as SMALLINT *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_SHORT', 2); /** *

    * Field is defined as INT *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_LONG', 3); /** *

    * Field is defined as FLOAT *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_FLOAT', 4); /** *

    * Field is defined as DOUBLE *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_DOUBLE', 5); /** *

    * Field is defined as DEFAULT NULL *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_NULL', 6); /** *

    * Field is defined as TIMESTAMP *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_TIMESTAMP', 7); /** *

    * Field is defined as BIGINT *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_LONGLONG', 8); /** *

    * Field is defined as MEDIUMINT *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_INT24', 9); /** *

    * Field is defined as DATE *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_DATE', 10); /** *

    * Field is defined as TIME *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_TIME', 11); /** *

    * Field is defined as DATETIME *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_DATETIME', 12); /** *

    * Field is defined as YEAR *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_YEAR', 13); /** *

    * Field is defined as DATE *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_NEWDATE', 14); /** *

    * Field is defined as ENUM *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_ENUM', 247); /** *

    * Field is defined as SET *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_SET', 248); /** *

    * Field is defined as TINYBLOB *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_TINY_BLOB', 249); /** *

    * Field is defined as MEDIUMBLOB *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_MEDIUM_BLOB', 250); /** *

    * Field is defined as LONGBLOB *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_LONG_BLOB', 251); /** *

    * Field is defined as BLOB *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_BLOB', 252); /** *

    * Field is defined as VARCHAR *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_VAR_STRING', 253); /** *

    * Field is defined as STRING *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_STRING', 254); /** *

    * Field is defined as CHAR *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_CHAR', 1); /** *

    * Field is defined as INTERVAL *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_INTERVAL', 247); /** *

    * Field is defined as GEOMETRY *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_GEOMETRY', 255); /** *

    * Precision math DECIMAL or NUMERIC field (MySQL 5.0.3 and up) *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_NEWDECIMAL', 246); /** *

    * Field is defined as BIT (MySQL 5.0.3 and up) *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_TYPE_BIT', 16); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_SET_CHARSET_NAME', 7); /** *

    * No more data available for bind variable *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_NO_DATA', 100); /** *

    * Data truncation occurred. Available since PHP 5.1.0 and MySQL 5.0.5. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_DATA_TRUNCATED', 101); /** *

    * Report if no index or bad index was used in a query. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REPORT_INDEX', 4); /** *

    * Report errors from mysqli function calls. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REPORT_ERROR', 1); /** *

    * Throw a mysqli_sql_exception for errors instead of warnings. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REPORT_STRICT', 2); /** *

    * Set all options on (report all). *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REPORT_ALL', 255); /** *

    * Turns reporting off. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REPORT_OFF', 0); /** *

    * Is set to 1 if mysqli_debug functionality is enabled. *

    * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_DEBUG_TRACE_ENABLED', 0); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED', 16); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_SERVER_QUERY_NO_INDEX_USED', 32); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REFRESH_GRANT', 1); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REFRESH_LOG', 2); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REFRESH_TABLES', 4); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REFRESH_HOSTS', 8); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REFRESH_STATUS', 16); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REFRESH_THREADS', 32); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REFRESH_SLAVE', 64); /** * @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_REFRESH_MASTER', 128); define('MYSQLI_SERVER_QUERY_WAS_SLOW', 2048); define('MYSQLI_REFRESH_BACKUP_LOG', 2097152); // End of mysqli v.0.1 /** @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_OPT_SSL_VERIFY_SERVER_CERT', 21); /** @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_SET_CHARSET_DIR', 6); /** @link https://php.net/manual/en/mysqli.constants.php */ define('MYSQLI_SERVER_PS_OUT_PARAMS', 4096); define('MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT', 1073741824); define('MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT', 64); define('MYSQLI_CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS', 4194304); define('MYSQLI_OPT_CAN_HANDLE_EXPIRED_PASSWORDS', 37); define('MYSQLI_OPT_READ_TIMEOUT', 11); define('MYSQLI_STORE_RESULT_COPY_DATA', 16); define('MYSQLI_TYPE_JSON', 245); define('MYSQLI_TRANS_COR_AND_CHAIN', 1); define('MYSQLI_TRANS_COR_AND_NO_CHAIN', 2); define('MYSQLI_TRANS_COR_RELEASE', 4); define('MYSQLI_TRANS_COR_NO_RELEASE', 8); define('MYSQLI_OPT_LOAD_DATA_LOCAL_DIR', 43); define('MYSQLI_REFRESH_REPLICA', 64); /** * @since 8.1 */ define('MYSQLI_IS_MARIADB', 0); /** * @since 8.4 */ define('MYSQLI_TYPE_VECTOR', 242); * Message queue numeric ID *

    * @param int $permissions [optional]

    * Queue permissions. Default to 0666. If the message queue already * exists, the perms will be ignored. *

    * @return resource|SysvMessageQueue|false a resource handle that can be used to access the System V message queue. */ #[LanguageLevelTypeAware(["8.0" => "SysvMessageQueue|false"], default: "resource|false")] function msg_get_queue(int $key, int $permissions = 0666) {} /** * Send a message to a message queue * @link https://php.net/manual/en/function.msg-send.php * @param SysvMessageQueue|resource $queue * @param int $message_type * @param mixed $message * @param bool $serialize [optional]

    * The optional serialize controls how the * message is sent. serialize * defaults to TRUE which means that the message is * serialized using the same mechanism as the session module before being * sent to the queue. This allows complex arrays and objects to be sent to * other PHP scripts, or if you are using the WDDX serializer, to any WDDX * compatible client. *

    * @param bool $blocking [optional]

    * If the message is too large to fit in the queue, your script will wait * until another process reads messages from the queue and frees enough * space for your message to be sent. * This is called blocking; you can prevent blocking by setting the * optional blocking parameter to FALSE, in which * case msg_send will immediately return FALSE if the * message is too big for the queue, and set the optional * errorcode to MSG_EAGAIN, * indicating that you should try to send your message again a little * later on. *

    * @param int &$error_code [optional] * @return bool TRUE on success or FALSE on failure. *

    * Upon successful completion the message queue data structure is updated as * follows: msg_lspid is set to the process-ID of the * calling process, msg_qnum is incremented by 1 and * msg_stime is set to the current time. *

    */ function msg_send(#[LanguageLevelTypeAware(["8.0" => "SysvMessageQueue"], default: "resource")] $queue, int $message_type, $message, bool $serialize = true, bool $blocking = true, &$error_code): bool {} /** * Receive a message from a message queue * @link https://php.net/manual/en/function.msg-receive.php * @param SysvMessageQueue|resource $queue * @param int $desired_message_type

    * If desiredmsgtype is 0, the message from the front * of the queue is returned. If desiredmsgtype is * greater than 0, then the first message of that type is returned. * If desiredmsgtype is less than 0, the first * message on the queue with the lowest type less than or equal to the * absolute value of desiredmsgtype will be read. * If no messages match the criteria, your script will wait until a suitable * message arrives on the queue. You can prevent the script from blocking * by specifying MSG_IPC_NOWAIT in the * flags parameter. *

    * @param int &$received_message_type

    * The type of the message that was received will be stored in this * parameter. *

    * @param int $max_message_size

    * The maximum size of message to be accepted is specified by the * maxsize; if the message in the queue is larger * than this size the function will fail (unless you set * flags as described below). *

    * @param mixed &$message

    * The received message will be stored in message, * unless there were errors receiving the message. *

    * @param bool $unserialize [optional]

    * If set to * TRUE, the message is treated as though it was serialized using the * same mechanism as the session module. The message will be unserialized * and then returned to your script. This allows you to easily receive * arrays or complex object structures from other PHP scripts, or if you * are using the WDDX serializer, from any WDDX compatible source. *

    *

    * If unserialize is FALSE, the message will be * returned as a binary-safe string. *

    * @param int $flags [optional]

    * The optional flags allows you to pass flags to the * low-level msgrcv system call. It defaults to 0, but you may specify one * or more of the following values (by adding or ORing them together). *

    * Flag values for msg_receive * * * * * * * * * * * * *
    MSG_IPC_NOWAITIf there are no messages of the * desiredmsgtype, return immediately and do not * wait. The function will fail and return an integer value * corresponding to MSG_ENOMSG. *
    MSG_EXCEPTUsing this flag in combination with a * desiredmsgtype greater than 0 will cause the * function to receive the first message that is not equal to * desiredmsgtype.
    MSG_NOERROR * If the message is longer than maxsize, * setting this flag will truncate the message to * maxsize and will not signal an error. *
    *

    * @param int $error_code [optional]

    * If the function fails, the optional errorcode * will be set to the value of the system errno variable. *

    * @return bool TRUE on success or FALSE on failure. *

    * Upon successful completion the message queue data structure is updated as * follows: msg_lrpid is set to the process-ID of the * calling process, msg_qnum is decremented by 1 and * msg_rtime is set to the current time. *

    */ function msg_receive(#[LanguageLevelTypeAware(["8.0" => "SysvMessageQueue"], default: "resource")] $queue, int $desired_message_type, &$received_message_type, int $max_message_size, mixed & $message, bool $unserialize = true, int $flags = 0, &$error_code): bool {} /** * Destroy a message queue * @link https://php.net/manual/en/function.msg-remove-queue.php * @param SysvMessageQueue|resource $queue

    * Message queue resource handle *

    * @return bool TRUE on success or FALSE on failure. */ function msg_remove_queue(#[LanguageLevelTypeAware(["8.0" => "SysvMessageQueue"], default: "resource")] $queue): bool {} /** * Returns information from the message queue data structure * @link https://php.net/manual/en/function.msg-stat-queue.php * @param SysvMessageQueue|resource $queue

    * Message queue resource handle *

    * @return array|false The return value is an array whose keys and values have the following * meanings: * * Array structure for msg_stat_queue * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    msg_perm.uid * The uid of the owner of the queue. *
    msg_perm.gid * The gid of the owner of the queue. *
    msg_perm.mode * The file access mode of the queue. *
    msg_stime * The time that the last message was sent to the queue. *
    msg_rtime * The time that the last message was received from the queue. *
    msg_ctime * The time that the queue was last changed. *
    msg_qnum * The number of messages waiting to be read from the queue. *
    msg_qbytes * The maximum number of bytes allowed in one message queue. On * Linux, this value may be read and modified via * /proc/sys/kernel/msgmnb. *
    msg_lspid * The pid of the process that sent the last message to the queue. *
    msg_lrpid * The pid of the process that received the last message from the queue. *
    */ #[ArrayShape([ "msg_perm.uid" => "int", "msg_perm.gid" => "int", "msg_perm.mode" => "int", "msg_stime" => "int", "msg_rtime" => "int", "msg_ctime" => "int", "msg_qnum" => "int", "msg_qbytes" => "int", "msg_lspid" => "int", "msg_lrpid" => "int", ])] function msg_stat_queue(#[LanguageLevelTypeAware(["8.0" => "SysvMessageQueue"], default: "resource")] $queue): array|false {} /** * Set information in the message queue data structure * @link https://php.net/manual/en/function.msg-set-queue.php * @param SysvMessageQueue|resource $queue

    * Message queue resource handle *

    * @param array $data

    * You specify the values you require by setting the value of the keys * that you require in the data array. *

    * @return bool TRUE on success or FALSE on failure. */ function msg_set_queue(#[LanguageLevelTypeAware(["8.0" => "SysvMessageQueue"], default: "resource")] $queue, array $data): bool {} /** * Check whether a message queue exists * @link https://php.net/manual/en/function.msg-queue-exists.php * @param int $key

    * Queue key. *

    * @return bool TRUE on success or FALSE on failure. */ function msg_queue_exists(int $key): bool {} define('MSG_IPC_NOWAIT', 1); define('MSG_EAGAIN', 11); define('MSG_ENOMSG', 42); define('MSG_NOERROR', 2); define('MSG_EXCEPT', 4); /** * @since 8.0 */ final class SysvMessageQueue { /** * Cannot directly construct SysvMessageQueue, use msg_get_queue() instead * @see msg_get_queue() */ private function __construct() {} } // End of sysvmsg v. * You may specify a string with which to prompt the user. *

    * @return string|false a single string from the user. The line returned has the ending newline removed. * If there is no more data to read, then FALSE is returned. */ function readline(?string $prompt): string|false {} /** * Gets/sets various internal readline variables * @link https://php.net/manual/en/function.readline-info.php * @param string|null $var_name [optional]

    * A variable name. *

    * @param string $value [optional]

    * If provided, this will be the new value of the setting. *

    * @return mixed If called with no parameters, this function returns an array of * values for all the setting readline uses. The elements will * be indexed by the following values: done, end, erase_empty_line, * library_version, line_buffer, mark, pending_input, point, prompt, * readline_name, and terminal_name. *

    *

    * If called with one or two parameters, the old value is returned. */ #[ArrayShape([ 'line_buffer' => 'string', 'point' => 'int', 'end' => 'int', 'mark' => 'int', 'done' => 'int', 'pending_input' => 'int', 'prompt' => 'string', 'terminal_name' => 'string', 'completion_append_character' => 'string', 'completion_suppress_append' => 'bool', 'erase_empty_line' => 'int', 'library_version' => 'string', 'readline_name' => 'string', 'attempted_completion_over' => 'int', ])] function readline_info(?string $var_name, $value): mixed {} /** * Adds a line to the history * @link https://php.net/manual/en/function.readline-add-history.php * @param string $prompt

    * The line to be added in the history. *

    * @return bool TRUE on success or FALSE on failure. */ function readline_add_history(string $prompt): bool {} /** * Clears the history * @link https://php.net/manual/en/function.readline-clear-history.php * @return bool TRUE on success or FALSE on failure. */ function readline_clear_history(): bool {} /** * Lists the history * @link https://php.net/manual/en/function.readline-list-history.php * @return array an array of the entire command line history. The elements are * indexed by integers starting at zero. */ function readline_list_history(): array {} /** * Reads the history * @link https://php.net/manual/en/function.readline-read-history.php * @param string|null $filename [optional]

    * Path to the filename containing the command history. *

    * @return bool TRUE on success or FALSE on failure. */ function readline_read_history(?string $filename): bool {} /** * Writes the history * @link https://php.net/manual/en/function.readline-write-history.php * @param string|null $filename [optional]

    * Path to the saved file. *

    * @return bool TRUE on success or FALSE on failure. */ function readline_write_history(?string $filename): bool {} /** * Registers a completion function * @link https://php.net/manual/en/function.readline-completion-function.php * @param callable $callback

    * You must supply the name of an existing function which accepts a * partial command line and returns an array of possible matches. *

    * @return bool TRUE on success or FALSE on failure. */ function readline_completion_function(callable $callback): bool {} /** * Initializes the readline callback interface and terminal, prints the prompt and returns immediately * @link https://php.net/manual/en/function.readline-callback-handler-install.php * @param string $prompt

    * The prompt message. *

    * @param callable $callback

    * The callback function takes one parameter; the * user input returned. *

    * @return bool TRUE on success or FALSE on failure. */ function readline_callback_handler_install(string $prompt, callable $callback): bool {} /** * Reads a character and informs the readline callback interface when a line is received * @link https://php.net/manual/en/function.readline-callback-read-char.php * @return void No value is returned. */ function readline_callback_read_char(): void {} /** * Removes a previously installed callback handler and restores terminal settings * @link https://php.net/manual/en/function.readline-callback-handler-remove.php * @return bool TRUE if a previously installed callback handler was removed, or * FALSE if one could not be found. */ function readline_callback_handler_remove(): bool {} /** * Redraws the display * @link https://php.net/manual/en/function.readline-redisplay.php * @return void No value is returned. */ function readline_redisplay(): void {} /** * Inform readline that the cursor has moved to a new line * @link https://php.net/manual/en/function.readline-on-new-line.php * @return void No value is returned. */ function readline_on_new_line(): void {} define('READLINE_LIB', "readline"); // End of readline v.5.5.3-1ubuntu2.1 'string'], default: '')] $filename) {} /** * Gets the path without filename * @link https://php.net/manual/en/splfileinfo.getpath.php * @return string the path to the file. * @since 5.1.2 */ #[TentativeType] public function getPath(): string {} /** * Gets the filename * @link https://php.net/manual/en/splfileinfo.getfilename.php * @return string The filename. * @since 5.1.2 */ #[TentativeType] public function getFilename(): string {} /** * Gets the file extension * @link https://php.net/manual/en/splfileinfo.getextension.php * @return string a string containing the file extension, or an * empty string if the file has no extension. * @since 5.3.6 */ #[TentativeType] public function getExtension(): string {} /** * Gets the base name of the file * @link https://php.net/manual/en/splfileinfo.getbasename.php * @param string $suffix [optional]

    * Optional suffix to omit from the base name returned. *

    * @return string the base name without path information. * @since 5.2.2 */ #[TentativeType] public function getBasename(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $suffix = ''): string {} /** * Gets the path to the file * @link https://php.net/manual/en/splfileinfo.getpathname.php * @return string The path to the file. * @since 5.1.2 */ #[TentativeType] public function getPathname(): string {} /** * Gets file permissions * @link https://php.net/manual/en/splfileinfo.getperms.php * @return int|false The file permissions on success, or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function getPerms(): int|false {} /** * Gets the inode for the file * @link https://php.net/manual/en/splfileinfo.getinode.php * @return int|false The inode number for the filesystem object on success, or FALSE on failure. * @since 5.1.2 * @throws \RuntimeException on error. */ #[TentativeType] public function getInode(): int|false {} /** * Gets file size * @link https://php.net/manual/en/splfileinfo.getsize.php * @return int|false The filesize in bytes on success, or FALSE on failure. * @since 5.1.2 * @throws \RuntimeException on error. */ #[TentativeType] public function getSize(): int|false {} /** * Gets the owner of the file * @link https://php.net/manual/en/splfileinfo.getowner.php * @return int|false The owner id in numerical format on success, or FALSE on failure. * @since 5.1.2 * @throws \RuntimeException on error. */ #[TentativeType] public function getOwner(): int|false {} /** * Gets the file group * @link https://php.net/manual/en/splfileinfo.getgroup.php * @return int|false The group id in numerical format on success, or FALSE on failure. * @since 5.1.2 * @throws \RuntimeException on error. */ #[TentativeType] public function getGroup(): int|false {} /** * Gets last access time of the file * @link https://php.net/manual/en/splfileinfo.getatime.php * @return int|false The time the file was last accessed on success, or FALSE on failure. * @since 5.1.2 * @throws \RuntimeException on error. */ #[TentativeType] public function getATime(): int|false {} /** * Gets the last modified time * @link https://php.net/manual/en/splfileinfo.getmtime.php * @return int|false The last modified time for the file, in a Unix timestamp on success, or FALSE on failure. * @since 5.1.2 */ #[TentativeType] public function getMTime(): int|false {} /** * Gets the inode change time * @link https://php.net/manual/en/splfileinfo.getctime.php * @return int|false The last change time, in a Unix timestamp on success, or FALSE on failure. * @since 5.1.2 * @throws \RuntimeException on error. */ #[TentativeType] public function getCTime(): int|false {} /** * Gets file type * @link https://php.net/manual/en/splfileinfo.gettype.php * @return string|false A string representing the type of the entry. May be one of file, link, dir, block, fifo, char, socket, or unknown, or FALSE on failure. * May be one of file, link, * or dir * @since 5.1.2 * @throws \RuntimeException on error. */ #[TentativeType] public function getType(): string|false {} /** * Tells if the entry is writable * @link https://php.net/manual/en/splfileinfo.iswritable.php * @return bool true if writable, false otherwise; * @since 5.1.2 */ #[TentativeType] public function isWritable(): bool {} /** * Tells if file is readable * @link https://php.net/manual/en/splfileinfo.isreadable.php * @return bool true if readable, false otherwise. * @since 5.1.2 */ #[TentativeType] public function isReadable(): bool {} /** * Tells if the file is executable * @link https://php.net/manual/en/splfileinfo.isexecutable.php * @return bool true if executable, false otherwise. * @since 5.1.2 */ #[TentativeType] public function isExecutable(): bool {} /** * Tells if the object references a regular file * @link https://php.net/manual/en/splfileinfo.isfile.php * @return bool true if the file exists and is a regular file (not a link), false otherwise. * @since 5.1.2 */ #[TentativeType] public function isFile(): bool {} /** * Tells if the file is a directory * @link https://php.net/manual/en/splfileinfo.isdir.php * @return bool true if a directory, false otherwise. * @since 5.1.2 */ #[TentativeType] public function isDir(): bool {} /** * Tells if the file is a link * @link https://php.net/manual/en/splfileinfo.islink.php * @return bool true if the file is a link, false otherwise. * @since 5.1.2 */ #[TentativeType] public function isLink(): bool {} /** * Gets the target of a link * @link https://php.net/manual/en/splfileinfo.getlinktarget.php * @return string|false The target of the filesystem link on success, or FALSE on failure. * @since 5.2.2 * @throws \RuntimeException on error. */ #[TentativeType] public function getLinkTarget(): string|false {} /** * Gets absolute path to file * @link https://php.net/manual/en/splfileinfo.getrealpath.php * @return string|false the path to the file, or FALSE if the file does not exist. * @since 5.2.2 */ #[TentativeType] public function getRealPath(): string|false {} /** * Gets an SplFileInfo object for the file * @template T of SplFileInfo * @link https://php.net/manual/en/splfileinfo.getfileinfo.php * @param class-string $class [optional]

    * Name of an SplFileInfo derived class to use. *

    * @return T An SplFileInfo object created for the file. * @since 5.1.2 */ #[TentativeType] public function getFileInfo(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $class = null): SplFileInfo {} /** * Gets an SplFileInfo object for the path * @template T of SplFileInfo * @link https://php.net/manual/en/splfileinfo.getpathinfo.php * @param class-string $class [optional]

    * Name of an SplFileInfo derived class to use. *

    * @return T|null A SplFileInfo object for the parent path of the file on success, or NULL on failure. * @since 5.1.2 */ #[TentativeType] public function getPathInfo(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $class = null): ?SplFileInfo {} /** * Gets an SplFileObject object for the file * @link https://php.net/manual/en/splfileinfo.openfile.php * @param string $mode [optional]

    * The mode for opening the file. See the fopen * documentation for descriptions of possible modes. The default * is read only. *

    * @param bool $useIncludePath [optional]

    *

    * @param resource $context [optional]

    *

    * @return SplFileObject The opened file as an SplFileObject object. * @since 5.1.2 * @throws \RuntimeException If the file cannot be opened (e.g. insufficient access rights). */ #[TentativeType] public function openFile( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $mode = 'r', #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $useIncludePath = false, $context = null ): SplFileObject {} /** * Sets the class name used with SplFileInfo::openFile * @template T of SplFileObject * @link https://php.net/manual/en/splfileinfo.setfileclass.php * @param class-string $class [optional]

    * The class name to use when openFile() is called. *

    * @return void * @since 5.1.2 */ #[TentativeType] public function setFileClass(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $class = SplFileObject::class): void {} /** * Sets the class used with getFileInfo and getPathInfo * @template T of SplFileInfo * @link https://php.net/manual/en/splfileinfo.setinfoclass.php * @param class-string $class [optional]

    * The class name to use. *

    * @return void * @since 5.1.2 */ #[TentativeType] public function setInfoClass(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $class = SplFileInfo::class): void {} /** * Returns the path to the file as a string * @link https://php.net/manual/en/splfileinfo.tostring.php * @return string the path to the file. * @since 5.1.2 */ #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] public function __toString() {} #[TentativeType] final public function _bad_state_ex(): void {} public function __wakeup() {} /** * @return array * @since 7.4 */ #[TentativeType] public function __debugInfo(): array {} } /** * The DirectoryIterator class provides a simple interface for viewing * the contents of filesystem directories. * @link https://php.net/manual/en/class.directoryiterator.php */ class DirectoryIterator extends SplFileInfo implements SeekableIterator { /** * Constructs a new directory iterator from a path * @link https://php.net/manual/en/directoryiterator.construct.php * @param string $directory * @throws UnexpectedValueException if the path cannot be opened. * @throws RuntimeException if the path is an empty string. */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $directory) {} /** * Determine if current DirectoryIterator item is '.' or '..' * @link https://php.net/manual/en/directoryiterator.isdot.php * @return bool true if the entry is . or .., * otherwise false */ #[TentativeType] public function isDot(): bool {} /** * Rewind the DirectoryIterator back to the start * @link https://php.net/manual/en/directoryiterator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Check whether current DirectoryIterator position is a valid file * @link https://php.net/manual/en/directoryiterator.valid.php * @return bool true if the position is valid, otherwise false */ #[TentativeType] public function valid(): bool {} /** * Return the key for the current DirectoryIterator item * @link https://php.net/manual/en/directoryiterator.key.php * @return string The key for the current DirectoryIterator item. */ #[TentativeType] public function key(): mixed {} /** * Return the current DirectoryIterator item. * @link https://php.net/manual/en/directoryiterator.current.php * @return DirectoryIterator The current DirectoryIterator item. */ #[TentativeType] public function current(): mixed {} /** * Move forward to next DirectoryIterator item * @link https://php.net/manual/en/directoryiterator.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Seek to a DirectoryIterator item * @link https://php.net/manual/en/directoryiterator.seek.php * @param int $offset

    * The zero-based numeric position to seek to. *

    * @return void */ #[TentativeType] public function seek(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset): void {} } /** * The Filesystem iterator * @link https://php.net/manual/en/class.filesystemiterator.php */ class FilesystemIterator extends DirectoryIterator { public const CURRENT_MODE_MASK = 240; public const CURRENT_AS_PATHNAME = 32; public const CURRENT_AS_FILEINFO = 0; public const CURRENT_AS_SELF = 16; public const KEY_MODE_MASK = 3840; public const KEY_AS_PATHNAME = 0; public const FOLLOW_SYMLINKS = 16384; public const KEY_AS_FILENAME = 256; public const NEW_CURRENT_AND_KEY = 256; public const SKIP_DOTS = 4096; public const UNIX_PATHS = 8192; public const OTHER_MODE_MASK = 28672; /** * Constructs a new filesystem iterator * @link https://php.net/manual/en/filesystemiterator.construct.php * @param string $directory * @param int $flags [optional] * @throws UnexpectedValueException if the path cannot be found. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $directory, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = FilesystemIterator::KEY_AS_PATHNAME|FilesystemIterator::CURRENT_AS_FILEINFO|FilesystemIterator::SKIP_DOTS ) {} /** * Rewinds back to the beginning * @link https://php.net/manual/en/filesystemiterator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Move to the next file * @link https://php.net/manual/en/filesystemiterator.next.php * @return void */ public function next() {} /** * Retrieve the key for the current file * @link https://php.net/manual/en/filesystemiterator.key.php * @return string the pathname or filename depending on the set flags. * See the FilesystemIterator constants. */ #[TentativeType] public function key(): string {} /** * The current file * @link https://php.net/manual/en/filesystemiterator.current.php * @return string|SplFileInfo|self The filename, file information, or $this depending on the set flags. * See the FilesystemIterator constants. */ #[TentativeType] public function current(): SplFileInfo|FilesystemIterator|string {} /** * Get the handling flags * @link https://php.net/manual/en/filesystemiterator.getflags.php * @return int The integer value of the set flags. */ #[TentativeType] public function getFlags(): int {} /** * Sets handling flags * @link https://php.net/manual/en/filesystemiterator.setflags.php * @param int $flags

    * The handling flags to set. * See the FilesystemIterator constants. *

    * @return void */ #[TentativeType] public function setFlags( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $flags = null, #[PhpStormStubsElementAvailable(from: '8.0')] int $flags ): void {} } /** * The RecursiveDirectoryIterator provides * an interface for iterating recursively over filesystem directories. * @link https://php.net/manual/en/class.recursivedirectoryiterator.php */ class RecursiveDirectoryIterator extends FilesystemIterator implements RecursiveIterator { /** * Constructs a RecursiveDirectoryIterator * @link https://php.net/manual/en/recursivedirectoryiterator.construct.php * @param string $directory * @param int $flags [optional] * @throws UnexpectedValueException if the path cannot be found or is not a directory. * @since 5.1.2 */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $directory, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = FilesystemIterator::KEY_AS_PATHNAME|FilesystemIterator::CURRENT_AS_FILEINFO ) {} /** * Returns whether current entry is a directory and not '.' or '..' * @link https://php.net/manual/en/recursivedirectoryiterator.haschildren.php * @param bool $allowLinks [optional]

    *

    * @return bool whether the current entry is a directory, but not '.' or '..' */ #[TentativeType] public function hasChildren(#[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $allowLinks = false): bool {} /** * Returns an iterator for the current entry if it is a directory * @link https://php.net/manual/en/recursivedirectoryiterator.getchildren.php * @return RecursiveDirectoryIterator An iterator for the current entry, if it is a directory. */ #[TentativeType] public function getChildren(): RecursiveDirectoryIterator {} /** * Get sub path * @link https://php.net/manual/en/recursivedirectoryiterator.getsubpath.php * @return string The sub path (sub directory). */ #[TentativeType] public function getSubPath(): string {} /** * Get sub path and name * @link https://php.net/manual/en/recursivedirectoryiterator.getsubpathname.php * @return string The sub path (sub directory) and filename. */ #[TentativeType] public function getSubPathname(): string {} /** * Rewinds back to the beginning * @link https://php.net/manual/en/filesystemiterator.rewind.php * @return void */ public function rewind() {} /** * Move to the next file * @link https://php.net/manual/en/filesystemiterator.next.php * @return void */ public function next() {} /** * Retrieve the key for the current file * @link https://php.net/manual/en/filesystemiterator.key.php * @return string the pathname or filename depending on the set flags. * See the FilesystemIterator constants. */ public function key() {} /** * The current file * @link https://php.net/manual/en/filesystemiterator.current.php * @return string|SplFileInfo|self The filename, file information, or $this depending on the set flags. * See the FilesystemIterator constants. */ public function current() {} } /** * Iterates through a file system in a similar fashion to * glob. * @link https://php.net/manual/en/class.globiterator.php */ class GlobIterator extends FilesystemIterator implements Countable { /** * Construct a directory using glob * @link https://php.net/manual/en/globiterator.construct.php * @param $pattern * @param int $flags [optional] */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $pattern, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = FilesystemIterator::KEY_AS_PATHNAME|FilesystemIterator::CURRENT_AS_FILEINFO ) {} /** * Get the number of directories and files * @link https://php.net/manual/en/globiterator.count.php * @return int<0,max> The number of returned directories and files, as an * integer. */ #[TentativeType] public function count(): int {} } /** * The SplFileObject class offers an object oriented interface for a file. * @link https://php.net/manual/en/class.splfileobject.php */ class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIterator { /** * Drop newlines at the end of a line. */ public const DROP_NEW_LINE = 1; /** * Read on rewind/next. */ public const READ_AHEAD = 2; /** * Skip empty lines in the file. This requires the {@see READ_AHEAD} flag to work as expected. */ public const SKIP_EMPTY = 4; /** * Read lines as CSV rows. */ public const READ_CSV = 8; /** * Construct a new file object. * * @link https://php.net/manual/en/splfileobject.construct.php * * @param string $filename The file to open * @param string $mode [optional] The mode in which to open the file. See {@see fopen} for a list of allowed modes. * @param bool $useIncludePath [optional] Whether to search in the include_path for filename * @param resource $context [optional] A valid context resource created with {@see stream_context_create} * * @throws RuntimeException When the filename cannot be opened * @throws LogicException When the filename is a directory */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $mode = 'r', #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $useIncludePath = false, $context = null ) {} /** * Rewind the file to the first line * @link https://php.net/manual/en/splfileobject.rewind.php * @return void * * @throws RuntimeException If cannot be rewound */ #[TentativeType] public function rewind(): void {} /** * Reached end of file * @link https://php.net/manual/en/splfileobject.eof.php * @return bool true if file is at EOF, false otherwise. */ #[TentativeType] public function eof(): bool {} /** * Not at EOF * @link https://php.net/manual/en/splfileobject.valid.php * @return bool true if not reached EOF, false otherwise. */ #[TentativeType] public function valid(): bool {} /** * Gets line from file * @link https://php.net/manual/en/splfileobject.fgets.php * @return string a string containing the next line from the file. * * @throws RuntimeException If the file cannot be read */ #[TentativeType] public function fgets(): string {} /** * Read from file * @link https://php.net/manual/en/splfileobject.fread.php * @param int $length

    * The number of bytes to read. *

    * @return string|false returns the string read from the file or FALSE on failure. * @since 5.5.11 */ #[TentativeType] public function fread(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $length): string|false {} /** * Gets line from file and parse as CSV fields * @link https://php.net/manual/en/splfileobject.fgetcsv.php * @param string $separator [optional]

    * The field delimiter (one character only). Defaults as a comma or the value set using SplFileObject::setCsvControl. *

    * @param string $enclosure [optional]

    * The field enclosure character (one character only). Defaults as a double quotation mark or the value set using SplFileObject::setCsvControl. *

    * @param string $escape [optional]

    * The escape character (one character only). Defaults as a backslash (\) or the value set using SplFileObject::setCsvControl. *

    * @return array|false|null an indexed array containing the fields read, or false on error. *

    *

    * A blank line in a CSV file will be returned as an array * comprising a single null field unless using SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE, * in which case empty lines are skipped. */ #[TentativeType] #[LanguageLevelTypeAware(['8.1' => 'array|false'], default: 'array|false|null')] public function fgetcsv( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $separator = ",", #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $enclosure = "\"", #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $escape = "\\" ) {} /** * Write a field array as a CSV line * @link https://php.net/manual/en/splfileobject.fputcsv.php * @param array $fields An array of values * @param string $separator [optional]

    * The field delimiter (one character only). Defaults as a comma or the value set using SplFileObject::setCsvControl. *

    * @param string $enclosure [optional]

    * The field enclosure character (one character only). Defaults as a double quotation mark or the value set using SplFileObject::setCsvControl. *

    * @param string $escape The optional escape parameter sets the escape character (one character only). * @return int|false Returns the length of the written string or FALSE on failure. * @since 5.4 */ #[TentativeType] public function fputcsv( array $fields, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $separator = ',', #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $enclosure = '"', #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $escape = "\\", #[PhpStormStubsElementAvailable('8.1')] string $eol = PHP_EOL ): int|false {} /** * Set the delimiter and enclosure character for CSV * @link https://php.net/manual/en/splfileobject.setcsvcontrol.php * @param string $separator [optional]

    * The field delimiter (one character only). *

    * @param string $enclosure [optional]

    * The field enclosure character (one character only). *

    * @param string $escape [optional]

    * The field escape character (one character only). *

    * @return void */ #[TentativeType] public function setCsvControl( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $separator = ",", #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $enclosure = "\"", #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $escape = "\\" ): void {} /** * Get the delimiter and enclosure character for CSV * @link https://php.net/manual/en/splfileobject.getcsvcontrol.php * @return array an indexed array containing the delimiter and enclosure character. */ #[TentativeType] public function getCsvControl(): array {} /** * Portable file locking * @link https://php.net/manual/en/splfileobject.flock.php * @param int $operation

    * operation is one of the following: * LOCK_SH to acquire a shared lock (reader). *

    * @param int &$wouldBlock [optional]

    * Set to 1 if the lock would block (EWOULDBLOCK errno condition). *

    * @return bool true on success or false on failure. */ #[TentativeType] public function flock(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $operation, &$wouldBlock = null): bool {} /** * Flushes the output to the file * @link https://php.net/manual/en/splfileobject.fflush.php * @return bool true on success or false on failure. */ #[TentativeType] public function fflush(): bool {} /** * Return current file position * @link https://php.net/manual/en/splfileobject.ftell.php * @return int|false the position of the file pointer as an integer, or false on error. */ #[TentativeType] public function ftell(): int|false {} /** * Seek to a position * @link https://php.net/manual/en/splfileobject.fseek.php * @param int $offset

    * The offset. A negative value can be used to move backwards through the file which * is useful when SEEK_END is used as the whence value. *

    * @param int $whence [optional]

    * whence values are: * SEEK_SET - Set position equal to offset bytes. * SEEK_CUR - Set position to current location plus offset. * SEEK_END - Set position to end-of-file plus offset. *

    *

    * If whence is not specified, it is assumed to be SEEK_SET. *

    * @return int 0 if the seek was successful, -1 otherwise. Note that seeking * past EOF is not considered an error. */ #[TentativeType] public function fseek( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $whence = SEEK_SET ): int {} /** * Gets character from file * @link https://php.net/manual/en/splfileobject.fgetc.php * @return string|false a string containing a single character read from the file or false on EOF. */ #[TentativeType] public function fgetc(): string|false {} /** * Output all remaining data on a file pointer * @link https://php.net/manual/en/splfileobject.fpassthru.php * @return int the number of characters read from handle * and passed through to the output. */ #[TentativeType] public function fpassthru(): int {} /** * Gets line from file and strip HTML tags * @link https://php.net/manual/en/splfileobject.fgetss.php * @param string $allowable_tags [optional]

    * You can use the optional third parameter to specify tags which should * not be stripped. *

    * @return string|false a string containing the next line of the file with HTML and PHP * code stripped, or false on error. * @removed 8.0 */ #[Deprecated(since: '7.3')] public function fgetss($allowable_tags = null) {} /** * Parses input from file according to a format * @link https://php.net/manual/en/splfileobject.fscanf.php * @param string $format

    * The specified format as described in the sprintf documentation. *

    * @param mixed &...$vars [optional]

    * The optional assigned values. *

    * @return array|int|null If only one parameter is passed to this method, the values parsed will be * returned as an array. Otherwise, if optional parameters are passed, the * function will return the number of assigned values. The optional * parameters must be passed by reference. */ #[TentativeType] public function fscanf( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $format, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] &...$vars ): array|int|null {} /** * Write to file * @link https://php.net/manual/en/splfileobject.fwrite.php * @param string $data

    * The string to be written to the file. *

    * @param int $length [optional]

    * If the length argument is given, writing will * stop after length bytes have been written or * the end of string is reached, whichever comes * first. *

    * @return int|false the number of bytes written, or 0 (false since 7.4) on error. */ #[LanguageLevelTypeAware(['7.4' => 'int|false'], default: 'int')] #[TentativeType] public function fwrite( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $length = 0 ): int|false {} /** * Gets information about the file * @link https://php.net/manual/en/splfileobject.fstat.php * @return array an array with the statistics of the file; the format of the array * is described in detail on the stat manual page. */ #[TentativeType] public function fstat(): array {} /** * Truncates the file to a given length * @link https://php.net/manual/en/splfileobject.ftruncate.php * @param int $size

    * The size to truncate to. *

    *

    * If size is larger than the file it is extended with null bytes. *

    *

    * If size is smaller than the file, the extra data will be lost. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function ftruncate(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $size): bool {} /** * Retrieve current line of file * @link https://php.net/manual/en/splfileobject.current.php * @return string|array|false Retrieves the current line of the file. If the SplFileObject::READ_CSV flag is set, this method returns an array containing the current line parsed as CSV data. */ #[TentativeType] public function current(): string|array|false {} /** * Get line number * @link https://php.net/manual/en/splfileobject.key.php * @return int the current line number. */ #[TentativeType] public function key(): int {} /** * Read next line * @link https://php.net/manual/en/splfileobject.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Sets flags for the SplFileObject * @link https://php.net/manual/en/splfileobject.setflags.php * @param int $flags

    * Bit mask of the flags to set. See * SplFileObject constants * for the available flags. *

    * @return void */ #[TentativeType] public function setFlags(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags): void {} /** * Gets flags for the SplFileObject * @link https://php.net/manual/en/splfileobject.getflags.php * @return int an integer representing the flags. */ #[TentativeType] public function getFlags(): int {} /** * Set maximum line length * @link https://php.net/manual/en/splfileobject.setmaxlinelen.php * @param int $maxLength

    * The maximum length of a line. *

    * @return void * * @throws DomainException When maxLength is less than zero. */ #[TentativeType] public function setMaxLineLen(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $maxLength): void {} /** * Get maximum line length * @link https://php.net/manual/en/splfileobject.getmaxlinelen.php * @return int<0, max> the maximum line length if one has been set with * SplFileObject::setMaxLineLen, default is 0. */ #[TentativeType] public function getMaxLineLen(): int {} /** * SplFileObject does not have children * @link https://php.net/manual/en/splfileobject.haschildren.php * @return bool false * @since 5.1.2 */ #[TentativeType] #[LanguageLevelTypeAware(['8.2' => 'false'], default: 'bool')] public function hasChildren() {} /** * No purpose * @link https://php.net/manual/en/splfileobject.getchildren.php * @return null|RecursiveIterator An SplFileObject does not have children so this method returns NULL. */ #[TentativeType] #[LanguageLevelTypeAware(['8.2' => 'null'], default: 'null|RecursiveIterator')] public function getChildren() {} /** * Seek to specified line * @link https://php.net/manual/en/splfileobject.seek.php * @param int $line

    * The zero-based line number to seek to. *

    * @return void * @throws LogicException If the line is negative */ #[TentativeType] public function seek(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $line): void {} /** * Alias of SplFileObject::fgets * @link https://php.net/manual/en/splfileobject.getcurrentline.php * @return string Returns a string containing the next line from the file. * @since 5.1.2 */ #[TentativeType] public function getCurrentLine(): string {} /** * Alias of SplFileObject::current * @link https://php.net/manual/en/splfileobject.tostring.php */ #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] public function __toString() {} } /** * The SplTempFileObject class offers an object oriented interface for a temporary file. * @link https://php.net/manual/en/class.spltempfileobject.php */ class SplTempFileObject extends SplFileObject { /** * Construct a new temporary file object * @link https://php.net/manual/en/spltempfileobject.construct.php * @param int $maxMemory [optional] * @throws RuntimeException if an error occurs. * @since 5.1.2 */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $maxMemory = 2097152) {} } /** * @template TValue * The SplDoublyLinkedList class provides the main functionalities of a doubly linked list. * @link https://php.net/manual/en/class.spldoublylinkedlist.php * @template-implements Iterator * @template-implements ArrayAccess */ class SplDoublyLinkedList implements Iterator, Countable, ArrayAccess, Serializable { public const IT_MODE_LIFO = 2; public const IT_MODE_FIFO = 0; public const IT_MODE_DELETE = 1; public const IT_MODE_KEEP = 0; /** * Add/insert a new value at the specified index * @param mixed $index The index where the new value is to be inserted. * @param TValue $value The new value for the index. * @return void * @link https://php.net/spldoublylinkedlist.add * @since 5.5 */ #[TentativeType] public function add( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value ): void {} /** * Pops a node from the end of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.pop.php * @return TValue The value of the popped node. */ #[TentativeType] public function pop(): mixed {} /** * Shifts a node from the beginning of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.shift.php * @return TValue The value of the shifted node. */ #[TentativeType] public function shift(): mixed {} /** * Pushes an element at the end of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.push.php * @param TValue $value

    * The value to push. *

    * @return void */ #[TentativeType] public function push(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value): void {} /** * Prepends the doubly linked list with an element * @link https://php.net/manual/en/spldoublylinkedlist.unshift.php * @param TValue $value

    * The value to unshift. *

    * @return void */ #[TentativeType] public function unshift(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value): void {} /** * Peeks at the node from the end of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.top.php * @return TValue The value of the last node. */ #[TentativeType] public function top(): mixed {} /** * Peeks at the node from the beginning of the doubly linked list * @link https://php.net/manual/en/spldoublylinkedlist.bottom.php * @return TValue The value of the first node. */ #[TentativeType] public function bottom(): mixed {} /** * Counts the number of elements in the doubly linked list. * @link https://php.net/manual/en/spldoublylinkedlist.count.php * @return int the number of elements in the doubly linked list. */ #[TentativeType] public function count(): int {} /** * Checks whether the doubly linked list is empty. * @link https://php.net/manual/en/spldoublylinkedlist.isempty.php * @return bool whether the doubly linked list is empty. */ #[TentativeType] public function isEmpty(): bool {} /** * Sets the mode of iteration * @link https://php.net/manual/en/spldoublylinkedlist.setiteratormode.php * @param int $mode

    * There are two orthogonal sets of modes that can be set: *

    * The direction of the iteration (either one or the other): * SplDoublyLinkedList::IT_MODE_LIFO (Stack style) * @return int */ #[TentativeType] public function setIteratorMode(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode): int {} /** * Returns the mode of iteration * @link https://php.net/manual/en/spldoublylinkedlist.getiteratormode.php * @return int the different modes and flags that affect the iteration. */ #[TentativeType] public function getIteratorMode(): int {} /** * Returns whether the requested $index exists * @link https://php.net/manual/en/spldoublylinkedlist.offsetexists.php * @param mixed $index

    * The index being checked. *

    * @return bool true if the requested index exists, otherwise false */ #[TentativeType] public function offsetExists($index): bool {} /** * Returns the value at the specified $index * @link https://php.net/manual/en/spldoublylinkedlist.offsetget.php * @param mixed $index

    * The index with the value. *

    * @return TValue The value at the specified index. */ #[TentativeType] public function offsetGet($index): mixed {} /** * Sets the value at the specified $index to $newval * @link https://php.net/manual/en/spldoublylinkedlist.offsetset.php * @param mixed $index

    * The index being set. *

    * @param TValue $value

    * The new value for the index. *

    * @return void */ #[TentativeType] public function offsetSet($index, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value): void {} /** * Unsets the value at the specified $index * @link https://php.net/manual/en/spldoublylinkedlist.offsetunset.php * @param mixed $index

    * The index being unset. *

    * @return void */ #[TentativeType] public function offsetUnset($index): void {} /** * Rewind iterator back to the start * @link https://php.net/manual/en/spldoublylinkedlist.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Return current array entry * @link https://php.net/manual/en/spldoublylinkedlist.current.php * @return TValue The current node value. */ #[TentativeType] public function current(): mixed {} /** * Return current node index * @link https://php.net/manual/en/spldoublylinkedlist.key.php * @return string|float|int|bool|null The current node index. */ #[TentativeType] public function key(): int {} /** * Move to next entry * @link https://php.net/manual/en/spldoublylinkedlist.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Move to previous entry * @link https://php.net/manual/en/spldoublylinkedlist.prev.php * @return void */ #[TentativeType] public function prev(): void {} /** * Check whether the doubly linked list contains more nodes * @link https://php.net/manual/en/spldoublylinkedlist.valid.php * @return bool true if the doubly linked list contains any more nodes, false otherwise. */ #[TentativeType] public function valid(): bool {} /** * Unserializes the storage * @link https://php.net/manual/en/spldoublylinkedlist.serialize.php * @param string $data The serialized string. * @return void * @since 5.4 */ #[TentativeType] public function unserialize(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data): void {} /** * Serializes the storage * @link https://php.net/manual/en/spldoublylinkedlist.unserialize.php * @return string The serialized string. * @since 5.4 */ #[TentativeType] public function serialize(): string {} /** * @return array * @since 7.4 */ #[TentativeType] public function __debugInfo(): array {} /** * @return array * @since 7.4 */ #[TentativeType] public function __serialize(): array {} /** * @param array $data * @since 7.4 */ #[TentativeType] public function __unserialize(array $data): void {} } /** * @template TValue * The SplQueue class provides the main functionalities of a queue implemented using a doubly linked list. * @link https://php.net/manual/en/class.splqueue.php */ class SplQueue extends SplDoublyLinkedList { /** * Adds an element to the queue. * @link https://php.net/manual/en/splqueue.enqueue.php * @param TValue $value

    * The value to enqueue. *

    * @return void */ #[TentativeType] public function enqueue(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value): void {} /** * Dequeues a node from the queue * @link https://php.net/manual/en/splqueue.dequeue.php * @return TValue The value of the dequeued node. */ #[TentativeType] public function dequeue(): mixed {} /** * Sets the mode of iteration * @link https://php.net/manual/en/spldoublylinkedlist.setiteratormode.php * @param int $mode

    * There are two orthogonal sets of modes that can be set: *

    * The direction of the iteration (either one or the other): * SplDoublyLinkedList::IT_MODE_LIFO (Stack style) * @return void */ public function setIteratorMode($mode) {} } /** * @template TValue * The SplStack class provides the main functionalities of a stack implemented using a doubly linked list. * @link https://php.net/manual/en/class.splstack.php * @template-extends SplDoublyLinkedList */ class SplStack extends SplDoublyLinkedList { /** * Sets the mode of iteration * @link https://php.net/manual/en/spldoublylinkedlist.setiteratormode.php * @param int $mode

    * There are two orthogonal sets of modes that can be set: *

    * The direction of the iteration (either one or the other): * SplDoublyLinkedList::IT_MODE_LIFO (Stack style) * @return void */ public function setIteratorMode($mode) {} } /** * @template TValue * The SplHeap class provides the main functionalities of an Heap. * @link https://php.net/manual/en/class.splheap.php * @template-implements Iterator */ abstract class SplHeap implements Iterator, Countable { /** * Extracts a node from top of the heap and sift up. * @link https://php.net/manual/en/splheap.extract.php * @return TValue The value of the extracted node. */ #[TentativeType] public function extract(): mixed {} /** * Inserts an element in the heap by sifting it up. * @link https://php.net/manual/en/splheap.insert.php * @param TValue $value

    * The value to insert. *

    * @return bool */ #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] public function insert(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value) {} /** * Peeks at the node from the top of the heap * @link https://php.net/manual/en/splheap.top.php * @return TValue The value of the node on the top. */ #[TentativeType] public function top(): mixed {} /** * Counts the number of elements in the heap. * @link https://php.net/manual/en/splheap.count.php * @return int the number of elements in the heap. */ #[TentativeType] public function count(): int {} /** * Checks whether the heap is empty. * @link https://php.net/manual/en/splheap.isempty.php * @return bool whether the heap is empty. */ #[TentativeType] public function isEmpty(): bool {} /** * Rewind iterator back to the start (no-op) * @link https://php.net/manual/en/splheap.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Return current node pointed by the iterator * @link https://php.net/manual/en/splheap.current.php * @return TValue The current node value. */ #[TentativeType] public function current(): mixed {} /** * Return current node index * @link https://php.net/manual/en/splheap.key.php * @return int The current node index. */ #[TentativeType] public function key(): int {} /** * Move to the next node * @link https://php.net/manual/en/splheap.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Check whether the heap contains more nodes * @link https://php.net/manual/en/splheap.valid.php * @return bool true if the heap contains any more nodes, false otherwise. */ #[TentativeType] public function valid(): bool {} /** * Recover from the corrupted state and allow further actions on the heap. * @link https://php.net/manual/en/splheap.recoverfromcorruption.php * @return bool */ #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] public function recoverFromCorruption() {} /** * Compare elements in order to place them correctly in the heap while sifting up. * @link https://php.net/manual/en/splheap.compare.php * @param mixed $value1

    * The value of the first node being compared. *

    * @param mixed $value2

    * The value of the second node being compared. *

    * @return int Result of the comparison, positive integer if value1 is greater than value2, 0 if they are equal, negative integer otherwise. *

    *

    * Having multiple elements with the same value in a Heap is not recommended. They will end up in an arbitrary relative position. */ abstract protected function compare($value1, $value2); /** * @return bool */ #[TentativeType] public function isCorrupted(): bool {} /** * @return array * @since 7.4 */ #[TentativeType] public function __debugInfo(): array {} } /** * @template TValue * The SplMinHeap class provides the main functionalities of a heap, keeping the minimum on the top. * @link https://php.net/manual/en/class.splminheap.php * @template-extends SplHeap */ class SplMinHeap extends SplHeap { /** * Compare elements in order to place them correctly in the heap while sifting up. * @link https://php.net/manual/en/splminheap.compare.php * @param TValue $value1

    * The value of the first node being compared. *

    * @param TValue $value2

    * The value of the second node being compared. *

    * @return int Result of the comparison, positive integer if value1 is lower than value2, 0 if they are equal, negative integer otherwise. *

    *

    * Having multiple elements with the same value in a Heap is not recommended. They will end up in an arbitrary relative position. */ #[TentativeType] protected function compare( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value1, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value2 ): int {} /** * Extracts a node from top of the heap and sift up. * @link https://php.net/manual/en/splheap.extract.php * @return TValue The value of the extracted node. */ public function extract() {} /** * Inserts an element in the heap by sifting it up. * @link https://php.net/manual/en/splheap.insert.php * @param TValue $value

    * The value to insert. *

    * @return true */ public function insert($value) {} /** * Peeks at the node from the top of the heap * @link https://php.net/manual/en/splheap.top.php * @return TValue The value of the node on the top. */ public function top() {} /** * Counts the number of elements in the heap. * @link https://php.net/manual/en/splheap.count.php * @return int the number of elements in the heap. */ public function count() {} /** * Checks whether the heap is empty. * @link https://php.net/manual/en/splheap.isempty.php * @return bool whether the heap is empty. */ public function isEmpty() {} /** * Rewind iterator back to the start (no-op) * @link https://php.net/manual/en/splheap.rewind.php * @return void */ public function rewind() {} /** * Return current node pointed by the iterator * @link https://php.net/manual/en/splheap.current.php * @return TValue The current node value. */ public function current() {} /** * Return current node index * @link https://php.net/manual/en/splheap.key.php * @return int The current node index. */ public function key() {} /** * Move to the next node * @link https://php.net/manual/en/splheap.next.php * @return void */ public function next() {} /** * Check whether the heap contains more nodes * @link https://php.net/manual/en/splheap.valid.php * @return bool true if the heap contains any more nodes, false otherwise. */ public function valid() {} /** * Recover from the corrupted state and allow further actions on the heap. * @link https://php.net/manual/en/splheap.recoverfromcorruption.php * @return void */ public function recoverFromCorruption() {} } /** * @template TValue * The SplMaxHeap class provides the main functionalities of a heap, keeping the maximum on the top. * @link https://php.net/manual/en/class.splmaxheap.php * @template-extends SplHeap */ class SplMaxHeap extends SplHeap { /** * Compare elements in order to place them correctly in the heap while sifting up. * @link https://php.net/manual/en/splmaxheap.compare.php * @param TValue $value1

    * The value of the first node being compared. *

    * @param TValue $value2

    * The value of the second node being compared. *

    * @return int Result of the comparison, positive integer if value1 is greater than value2, 0 if they are equal, negative integer otherwise. *

    *

    * Having multiple elements with the same value in a Heap is not recommended. They will end up in an arbitrary relative position. */ #[TentativeType] protected function compare( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value1, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value2 ): int {} } /** * @template TPriority * @template TValue * The SplPriorityQueue class provides the main functionalities of an * prioritized queue, implemented using a heap. * @link https://php.net/manual/en/class.splpriorityqueue.php * @template-implements Iterator */ class SplPriorityQueue implements Iterator, Countable { public const EXTR_BOTH = 3; public const EXTR_PRIORITY = 2; public const EXTR_DATA = 1; /** * Compare priorities in order to place elements correctly in the heap while sifting up. * @link https://php.net/manual/en/splpriorityqueue.compare.php * @param TPriority $priority1

    * The priority of the first node being compared. *

    * @param TPriority $priority2

    * The priority of the second node being compared. *

    * @return int Result of the comparison, positive integer if priority1 is greater than priority2, 0 if they are equal, negative integer otherwise. *

    *

    * Multiple elements with the same priority will get dequeued in no particular order. */ #[TentativeType] public function compare( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $priority1, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $priority2 ): int {} /** * Inserts an element in the queue by sifting it up. * @link https://php.net/manual/en/splpriorityqueue.insert.php * @param TValue $value

    * The value to insert. *

    * @param TPriority $priority

    * The associated priority. *

    * @return true */ #[TentativeType] public function insert( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $priority ): true {} /** * Sets the mode of extraction * @link https://php.net/manual/en/splpriorityqueue.setextractflags.php * @param int $flags

    * Defines what is extracted by SplPriorityQueue::current, * SplPriorityQueue::top and * SplPriorityQueue::extract. *

    * SplPriorityQueue::EXTR_DATA (0x00000001): Extract the data * @return int */ #[TentativeType] public function setExtractFlags(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags): int {} /** * Peeks at the node from the top of the queue * @link https://php.net/manual/en/splpriorityqueue.top.php * @return TValue The value or priority (or both) of the top node, depending on the extract flag. */ #[TentativeType] public function top(): mixed {} /** * Extracts a node from top of the heap and sift up. * @link https://php.net/manual/en/splpriorityqueue.extract.php * @return TValue The value or priority (or both) of the extracted node, depending on the extract flag. */ #[TentativeType] public function extract(): mixed {} /** * Counts the number of elements in the queue. * @link https://php.net/manual/en/splpriorityqueue.count.php * @return int the number of elements in the queue. */ #[TentativeType] public function count(): int {} /** * Checks whether the queue is empty. * @link https://php.net/manual/en/splpriorityqueue.isempty.php * @return bool whether the queue is empty. */ #[TentativeType] public function isEmpty(): bool {} /** * Rewind iterator back to the start (no-op) * @link https://php.net/manual/en/splpriorityqueue.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Return current node pointed by the iterator * @link https://php.net/manual/en/splpriorityqueue.current.php * @return TValue The value or priority (or both) of the current node, depending on the extract flag. */ #[TentativeType] public function current(): mixed {} /** * Return current node index * @link https://php.net/manual/en/splpriorityqueue.key.php * @return int The current node index. */ #[TentativeType] public function key(): int {} /** * Move to the next node * @link https://php.net/manual/en/splpriorityqueue.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Check whether the queue contains more nodes * @link https://php.net/manual/en/splpriorityqueue.valid.php * @return bool true if the queue contains any more nodes, false otherwise. */ #[TentativeType] public function valid(): bool {} /** * Recover from the corrupted state and allow further actions on the queue. * @link https://php.net/manual/en/splpriorityqueue.recoverfromcorruption.php */ #[TentativeType] public function recoverFromCorruption(): true {} /** * @return bool */ #[TentativeType] public function isCorrupted(): bool {} /** * @return int */ #[TentativeType] public function getExtractFlags(): int {} /** * @return array * @since 7.4 */ #[TentativeType] public function __debugInfo(): array {} } /** * @template TValue * The SplFixedArray class provides the main functionalities of array. The * main differences between a SplFixedArray and a normal PHP array is that * the SplFixedArray is of fixed length and allows only integers within * the range as indexes. The advantage is that it allows a faster array * implementation. * @link https://php.net/manual/en/class.splfixedarray.php * @template-implements Iterator * @template-implements ArrayAccess * @template-implements IteratorAggregate */ class SplFixedArray implements Iterator, ArrayAccess, Countable, IteratorAggregate, JsonSerializable { /** * Constructs a new fixed array * @link https://php.net/manual/en/splfixedarray.construct.php * @param int $size [optional] */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $size = 0) {} /** * Returns the size of the array * @link https://php.net/manual/en/splfixedarray.count.php * @return int the size of the array. */ #[TentativeType] public function count(): int {} /** * Returns a PHP array from the fixed array * @link https://php.net/manual/en/splfixedarray.toarray.php * @return TValue[] a PHP array, similar to the fixed array. */ #[TentativeType] public function toArray(): array {} /** * Import a PHP array in a SplFixedArray instance * @link https://php.net/manual/en/splfixedarray.fromarray.php * @param array $array

    * The array to import. *

    * @param bool $preserveKeys [optional]

    * Try to save the numeric indexes used in the original array. *

    * @return SplFixedArray an instance of SplFixedArray * containing the array content. */ #[TentativeType] public static function fromArray( #[LanguageLevelTypeAware(['8.0' => 'array'], default: '')] $array, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $preserveKeys = true ): SplFixedArray {} /** * Gets the size of the array * @link https://php.net/manual/en/splfixedarray.getsize.php * @return int the size of the array, as an integer. */ #[TentativeType] public function getSize(): int {} /** * Change the size of an array * @link https://php.net/manual/en/splfixedarray.setsize.php * @param int $size

    * The new array size. *

    * @return bool */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function setSize(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $size) {} /** * Returns whether the requested index exists * @link https://php.net/manual/en/splfixedarray.offsetexists.php * @param int $index

    * The index being checked. *

    * @return bool true if the requested index exists, otherwise false */ #[TentativeType] public function offsetExists($index): bool {} /** * Returns the value at the specified index * @link https://php.net/manual/en/splfixedarray.offsetget.php * @param int $index

    * The index with the value. *

    * @return TValue The value at the specified index. */ #[TentativeType] public function offsetGet($index): mixed {} /** * Sets a new value at a specified index * @link https://php.net/manual/en/splfixedarray.offsetset.php * @param int $index

    * The index being set. *

    * @param TValue $value

    * The new value for the index. *

    * @return void */ #[TentativeType] public function offsetSet($index, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value): void {} /** * Unsets the value at the specified $index * @link https://php.net/manual/en/splfixedarray.offsetunset.php * @param int $index

    * The index being unset. *

    * @return void */ #[TentativeType] public function offsetUnset($index): void {} /** * Rewind iterator back to the start * @link https://php.net/manual/en/splfixedarray.rewind.php * @return void */ public function rewind() {} /** * Return current array entry * @link https://php.net/manual/en/splfixedarray.current.php * @return TValue The current element value. */ public function current() {} /** * Return current array index * @link https://php.net/manual/en/splfixedarray.key.php * @return int The current array index. */ public function key() {} /** * Move to next entry * @link https://php.net/manual/en/splfixedarray.next.php * @return void */ public function next() {} /** * Check whether the array contains more elements * @link https://php.net/manual/en/splfixedarray.valid.php * @return bool true if the array contains any more elements, false otherwise. */ #[TentativeType] public function valid(): bool {} #[TentativeType] public function __wakeup(): void {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __serialize(): array {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __unserialize(array $data): void {} /** * @since 8.0 * @return Iterator */ public function getIterator(): Iterator {} #[PhpStormStubsElementAvailable(from: '8.1')] public function jsonSerialize(): array {} } /** * The SplObserver interface is used alongside * SplSubject to implement the Observer Design Pattern. * @link https://php.net/manual/en/class.splobserver.php */ interface SplObserver { /** * Receive update from subject * @link https://php.net/manual/en/splobserver.update.php * @param SplSubject $subject

    * The SplSubject notifying the observer of an update. *

    * @return void */ #[TentativeType] public function update(SplSubject $subject): void; } /** * The SplSubject interface is used alongside * SplObserver to implement the Observer Design Pattern. * @link https://php.net/manual/en/class.splsubject.php */ interface SplSubject { /** * Attach an SplObserver * @link https://php.net/manual/en/splsubject.attach.php * @param SplObserver $observer

    * The SplObserver to attach. *

    * @return void */ #[TentativeType] public function attach(SplObserver $observer): void; /** * Detach an observer * @link https://php.net/manual/en/splsubject.detach.php * @param SplObserver $observer

    * The SplObserver to detach. *

    * @return void */ #[TentativeType] public function detach(SplObserver $observer): void; /** * Notify an observer * @link https://php.net/manual/en/splsubject.notify.php * @return void */ #[TentativeType] public function notify(): void; } /** * @template TObject of object * @template TValue * The SplObjectStorage class provides a map from objects to data or, by * ignoring data, an object set. This dual purpose can be useful in many * cases involving the need to uniquely identify objects. * @link https://php.net/manual/en/class.splobjectstorage.php * @template-implements Iterator * @template-implements ArrayAccess */ class SplObjectStorage implements Countable, SeekableIterator, Serializable, ArrayAccess { /** * Adds an object in the storage * @link https://php.net/manual/en/splobjectstorage.attach.php * @param TObject $object

    * The object to add. *

    * @param TValue $info [optional]

    * The data to associate with the object. *

    * @return void */ #[TentativeType] public function attach( #[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $object, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $info = null ): void {} /** * Removes an object from the storage * @link https://php.net/manual/en/splobjectstorage.detach.php * @param TObject $object

    * The object to remove. *

    * @return void */ #[TentativeType] public function detach(#[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $object): void {} /** * Checks if the storage contains a specific object * @link https://php.net/manual/en/splobjectstorage.contains.php * @param TObject $object

    * The object to look for. *

    * @return bool true if the object is in the storage, false otherwise. */ #[TentativeType] public function contains(#[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $object): bool {} /** * Adds all objects from another storage * @link https://php.net/manual/en/splobjectstorage.addall.php * @param SplObjectStorage $storage

    * The storage you want to import. *

    * @return int */ #[TentativeType] public function addAll(#[LanguageLevelTypeAware(['8.0' => 'SplObjectStorage'], default: '')] $storage): int {} /** * Removes objects contained in another storage from the current storage * @link https://php.net/manual/en/splobjectstorage.removeall.php * @param SplObjectStorage $storage

    * The storage containing the elements to remove. *

    * @return int */ #[TentativeType] public function removeAll(#[LanguageLevelTypeAware(['8.0' => 'SplObjectStorage'], default: '')] $storage): int {} /** * Removes all objects except for those contained in another storage from the current storage * @link https://php.net/manual/en/splobjectstorage.removeallexcept.php * @param SplObjectStorage $storage

    * The storage containing the elements to retain in the current storage. *

    * @return int * @since 5.3.6 */ #[TentativeType] public function removeAllExcept(#[LanguageLevelTypeAware(['8.0' => 'SplObjectStorage'], default: '')] $storage): int {} /** * Returns the data associated with the current iterator entry * @link https://php.net/manual/en/splobjectstorage.getinfo.php * @return TValue The data associated with the current iterator position. */ #[TentativeType] public function getInfo(): mixed {} /** * Sets the data associated with the current iterator entry * @link https://php.net/manual/en/splobjectstorage.setinfo.php * @param TValue $info

    * The data to associate with the current iterator entry. *

    * @return void */ #[TentativeType] public function setInfo(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $info): void {} /** * Returns the number of objects in the storage * @link https://php.net/manual/en/splobjectstorage.count.php * @param int $mode [optional] * @return int The number of objects in the storage. */ #[TentativeType] public function count(#[PhpStormStubsElementAvailable(from: '8.0')] int $mode = COUNT_NORMAL): int {} /** * Rewind the iterator to the first storage element * @link https://php.net/manual/en/splobjectstorage.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Returns if the current iterator entry is valid * @link https://php.net/manual/en/splobjectstorage.valid.php * @return bool true if the iterator entry is valid, false otherwise. */ #[TentativeType] public function valid(): bool {} /** * Returns the index at which the iterator currently is * @link https://php.net/manual/en/splobjectstorage.key.php * @return int The index corresponding to the position of the iterator. */ #[TentativeType] public function key(): int {} /** * Returns the current storage entry * @link https://php.net/manual/en/splobjectstorage.current.php * @return TObject The object at the current iterator position. */ #[TentativeType] public function current(): object {} /** * Move to the next entry * @link https://php.net/manual/en/splobjectstorage.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Unserializes a storage from its string representation * @link https://php.net/manual/en/splobjectstorage.unserialize.php * @param string $data

    * The serialized representation of a storage. *

    * @return void * @since 5.2.2 */ #[TentativeType] public function unserialize(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data): void {} /** * Serializes the storage * @link https://php.net/manual/en/splobjectstorage.serialize.php * @return string A string representing the storage. * @since 5.2.2 */ #[TentativeType] public function serialize(): string {} /** * Checks whether an object exists in the storage * @link https://php.net/manual/en/splobjectstorage.offsetexists.php * @param TObject $object

    * The object to look for. *

    * @return bool true if the object exists in the storage, * and false otherwise. */ #[TentativeType] public function offsetExists($object): bool {} /** * Associates data to an object in the storage * @link https://php.net/manual/en/splobjectstorage.offsetset.php * @param TObject $object

    * The object to associate data with. *

    * @param TValue $info [optional]

    * The data to associate with the object. *

    * @return void */ #[TentativeType] public function offsetSet( #[LanguageLevelTypeAware(['8.1' => 'mixed'], default: '')] $object, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $info = null ): void {} /** * Removes an object from the storage * @link https://php.net/manual/en/splobjectstorage.offsetunset.php * @param TObject $object

    * The object to remove. *

    * @return void */ #[TentativeType] public function offsetUnset($object): void {} /** * Returns the data associated with an object * @link https://php.net/manual/en/splobjectstorage.offsetget.php * @param TObject $object

    * The object to look for. *

    * @return TValue The data previously associated with the object in the storage. */ #[TentativeType] public function offsetGet($object): mixed {} /** * Calculate a unique identifier for the contained objects * @link https://php.net/manual/en/splobjectstorage.gethash.php * @param TObject $object

    * object whose identifier is to be calculated. *

    * @return string A string with the calculated identifier. * @since 5.4 */ #[TentativeType] public function getHash(#[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $object): string {} /** * @return array * @since 7.4 */ #[TentativeType] public function __serialize(): array {} /** * @param array $data * @since 7.4 */ #[TentativeType] public function __unserialize(array $data): void {} /** * @return array * @since 7.4 */ #[TentativeType] public function __debugInfo(): array {} /** * @since 8.4 */ public function seek(int $offset): void {} } /** * An Iterator that sequentially iterates over all attached iterators * @link https://php.net/manual/en/class.multipleiterator.php */ class MultipleIterator implements Iterator { public const MIT_NEED_ANY = 0; public const MIT_NEED_ALL = 1; public const MIT_KEYS_NUMERIC = 0; public const MIT_KEYS_ASSOC = 2; /** * Constructs a new MultipleIterator * @link https://php.net/manual/en/multipleiterator.construct.php * @param int $flags Defaults to MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC */ public function __construct( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $flags, #[PhpStormStubsElementAvailable(from: '8.0')] int $flags = MultipleIterator::MIT_NEED_ALL|MultipleIterator::MIT_KEYS_NUMERIC ) {} /** * Gets the flag information * @link https://php.net/manual/en/multipleiterator.getflags.php * @return int Information about the flags, as an integer. */ #[TentativeType] public function getFlags(): int {} /** * Sets flags * @link https://php.net/manual/en/multipleiterator.setflags.php * @param int $flags

    * The flags to set, according to the * Flag Constants *

    * @return void */ #[TentativeType] public function setFlags(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags): void {} /** * Attaches iterator information * @link https://php.net/manual/en/multipleiterator.attachiterator.php * @param Iterator $iterator

    * The new iterator to attach. *

    * @param int|string|null $info [optional]

    * The associative information for the Iterator, which must be an * integer, a string, or null. *

    * @return void Description... */ #[TentativeType] public function attachIterator(Iterator $iterator, #[LanguageLevelTypeAware(['8.0' => 'int|string|null'], default: '')] $info = null): void {} /** * Detaches an iterator * @link https://php.net/manual/en/multipleiterator.detachiterator.php * @param Iterator $iterator

    * The iterator to detach. *

    * @return void */ #[TentativeType] public function detachIterator(Iterator $iterator): void {} /** * Checks if an iterator is attached * @link https://php.net/manual/en/multipleiterator.containsiterator.php * @param Iterator $iterator

    * The iterator to check. *

    * @return bool true on success or false on failure. */ #[TentativeType] public function containsIterator(Iterator $iterator): bool {} /** * Gets the number of attached iterator instances * @link https://php.net/manual/en/multipleiterator.countiterators.php * @return int The number of attached iterator instances (as an integer). */ #[TentativeType] public function countIterators(): int {} /** * Rewinds all attached iterator instances * @link https://php.net/manual/en/multipleiterator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Checks the validity of sub iterators * @link https://php.net/manual/en/multipleiterator.valid.php * @return bool true if one or all sub iterators are valid depending on flags, * otherwise false */ #[TentativeType] public function valid(): bool {} /** * Gets the registered iterator instances * @link https://php.net/manual/en/multipleiterator.key.php * @return array An array of all registered iterator instances, * or false if no sub iterator is attached. */ #[TentativeType] public function key(): array {} /** * Gets the registered iterator instances * @link https://php.net/manual/en/multipleiterator.current.php * @return array An array containing the current values of each attached iterator, * or false if no iterators are attached. * @throws RuntimeException if mode MIT_NEED_ALL is set and at least one attached iterator is not valid. * @throws InvalidArgumentException if a key is NULL and MIT_KEYS_ASSOC is set. */ #[TentativeType] public function current(): array {} /** * Moves all attached iterator instances forward * @link https://php.net/manual/en/multipleiterator.next.php * @return void */ #[TentativeType] public function next(): void {} /** * @return array * @since 7.4 */ #[TentativeType] public function __debugInfo(): array {} } DomainException. * @link https://php.net/manual/en/class.rangeexception.php */ class RangeException extends RuntimeException {} /** * Exception thrown when performing an invalid operation on an empty container, such as removing an element. * @link https://php.net/manual/en/class.underflowexception.php */ class UnderflowException extends RuntimeException {} /** * Exception thrown if a value does not match with a set of values. Typically * this happens when a function calls another function and expects the return * value to be of a certain type or value not including arithmetic or buffer * related errors. * @link https://php.net/manual/en/class.unexpectedvalueexception.php */ class UnexpectedValueException extends RuntimeException {} /** * The EmptyIterator class for an empty iterator. * @link https://secure.php.net/manual/en/class.emptyiterator.php */ class EmptyIterator implements Iterator { /** * Return the current element * @link https://php.net/manual/en/iterator.current.php * @return mixed Can return any type. */ #[TentativeType] public function current(): never {} /** * Move forward to next element * @link https://php.net/manual/en/iterator.next.php * @return void Any returned value is ignored. */ #[TentativeType] public function next(): void {} /** * Return the key of the current element * @link https://php.net/manual/en/iterator.key.php * @return mixed The key of the current element. */ #[TentativeType] public function key(): never {} /** * Checks if current position is valid * @link https://php.net/manual/en/iterator.valid.php * @return bool The return value will be casted to boolean and then evaluated. * Returns true on success or false on failure. */ #[TentativeType] #[LanguageLevelTypeAware(['8.2' => 'false'], default: 'bool')] public function valid() {} /** * Rewind the Iterator to the first element * @link https://php.net/manual/en/iterator.rewind.php * @return void Any returned value is ignored. */ #[TentativeType] public function rewind(): void {} } /** * Filtered iterator using the callback to determine which items are accepted or rejected. * @link https://secure.php.net/manual/en/class.callbackfilteriterator.php * @since 5.4 */ class CallbackFilterIterator extends FilterIterator { /** * Creates a filtered iterator using the callback to determine which items are accepted or rejected. * @param Iterator $iterator The iterator to be filtered. * @param callable $callback The callback, which should return TRUE to accept the current item or FALSE otherwise. * May be any valid callable value. * The callback should accept up to three arguments: the current item, the current key and the iterator, respectively. * function my_callback($current, $key, $iterator) * @link https://secure.php.net/manual/en/callbackfilteriterator.construct.php */ public function __construct(Iterator $iterator, callable $callback) {} /** * This method calls the callback with the current value, current key and the inner iterator. * The callback is expected to return TRUE if the current item is to be accepted, or FALSE otherwise. * @link https://secure.php.net/manual/en/callbackfilteriterator.accept.php * @return bool true if the current element is acceptable, otherwise false. */ #[TentativeType] public function accept(): bool {} } /** * (PHP 5 >= 5.4.0)
    * RecursiveCallbackFilterIterator from a RecursiveIterator * @link https://secure.php.net/manual/en/class.recursivecallbackfilteriterator.php * @since 5.4 */ class RecursiveCallbackFilterIterator extends CallbackFilterIterator implements RecursiveIterator { /** * Create a RecursiveCallbackFilterIterator from a RecursiveIterator * @param RecursiveIterator $iterator The recursive iterator to be filtered. * @param callable $callback The callback, which should return TRUE to accept the current item or FALSE otherwise. See Examples. * May be any valid callable value. * @link https://www.php.net/manual/en/recursivecallbackfilteriterator.construct.php */ public function __construct( RecursiveIterator $iterator, #[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback ) {} /** * Check whether the inner iterator's current element has children * @link https://php.net/manual/en/recursiveiterator.haschildren.php * @return bool Returns TRUE if the current element has children, FALSE otherwise. */ #[TentativeType] public function hasChildren(): bool {} /** * Returns an iterator for the current entry. * @link https://secure.php.net/manual/en/recursivecallbackfilteriterator.haschildren.php * @return RecursiveCallbackFilterIterator containing the children. */ #[TentativeType] public function getChildren(): RecursiveCallbackFilterIterator {} } /** * Classes implementing RecursiveIterator can be used to iterate * over iterators recursively. * @link https://php.net/manual/en/class.recursiveiterator.php */ interface RecursiveIterator extends Iterator { /** * Returns if an iterator can be created for the current entry. * @link https://php.net/manual/en/recursiveiterator.haschildren.php * @return bool true if the current entry can be iterated over, otherwise returns false. */ #[TentativeType] public function hasChildren(): bool; /** * Returns an iterator for the current entry. * @link https://php.net/manual/en/recursiveiterator.getchildren.php * @return RecursiveIterator|null An iterator for the current entry. */ #[TentativeType] public function getChildren(): ?RecursiveIterator; } /** * Can be used to iterate through recursive iterators. * @link https://php.net/manual/en/class.recursiveiteratoriterator.php */ class RecursiveIteratorIterator implements OuterIterator { /** * The default. Lists only leaves in iteration. */ public const LEAVES_ONLY = 0; /** * Lists leaves and parents in iteration with parents coming first. */ public const SELF_FIRST = 1; /** * Lists leaves and parents in iteration with leaves coming first. */ public const CHILD_FIRST = 2; /** * Special flag: Ignore exceptions thrown in accessing children. */ public const CATCH_GET_CHILD = 16; /** * Construct a RecursiveIteratorIterator * @link https://php.net/manual/en/recursiveiteratoriterator.construct.php * @param Traversable $iterator * @param int $mode [optional] The operation mode. See class constants for details. * @param int $flags [optional] A bitmask of special flags. See class constants for details. * @since 5.1.3 */ public function __construct( Traversable $iterator, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode = self::LEAVES_ONLY, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0 ) {} /** * Rewind the iterator to the first element of the top level inner iterator * @link https://php.net/manual/en/recursiveiteratoriterator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Check whether the current position is valid * @link https://php.net/manual/en/recursiveiteratoriterator.valid.php * @return bool true if the current position is valid, otherwise false */ #[TentativeType] public function valid(): bool {} /** * Access the current key * @link https://php.net/manual/en/recursiveiteratoriterator.key.php * @return mixed The key of the current element. */ #[TentativeType] public function key(): mixed {} /** * Access the current element value * @link https://php.net/manual/en/recursiveiteratoriterator.current.php * @return mixed The current elements value. */ #[TentativeType] public function current(): mixed {} /** * Move forward to the next element * @link https://php.net/manual/en/recursiveiteratoriterator.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Get the current depth of the recursive iteration * @link https://php.net/manual/en/recursiveiteratoriterator.getdepth.php * @return int The current depth of the recursive iteration. */ #[TentativeType] public function getDepth(): int {} /** * The current active sub iterator * @link https://php.net/manual/en/recursiveiteratoriterator.getsubiterator.php * @param int $level [optional] * @return RecursiveIterator|null The current active sub iterator. */ #[TentativeType] public function getSubIterator(#[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $level): ?RecursiveIterator {} /** * Get inner iterator * @link https://php.net/manual/en/recursiveiteratoriterator.getinneriterator.php * @return RecursiveIterator The current active sub iterator. */ #[TentativeType] public function getInnerIterator(): RecursiveIterator {} /** * Begin Iteration * @link https://php.net/manual/en/recursiveiteratoriterator.beginiteration.php * @return void */ #[TentativeType] public function beginIteration(): void {} /** * End Iteration * @link https://php.net/manual/en/recursiveiteratoriterator.enditeration.php * @return void */ #[TentativeType] public function endIteration(): void {} /** * Has children * @link https://php.net/manual/en/recursiveiteratoriterator.callhaschildren.php * @return bool true if the element has children, otherwise false */ #[TentativeType] public function callHasChildren(): bool {} /** * Get children * @link https://php.net/manual/en/recursiveiteratoriterator.callgetchildren.php * @return RecursiveIterator|null A RecursiveIterator. */ #[TentativeType] public function callGetChildren(): ?RecursiveIterator {} /** * Begin children * @link https://php.net/manual/en/recursiveiteratoriterator.beginchildren.php * @return void */ #[TentativeType] public function beginChildren(): void {} /** * End children * @link https://php.net/manual/en/recursiveiteratoriterator.endchildren.php * @return void */ #[TentativeType] public function endChildren(): void {} /** * Next element * @link https://php.net/manual/en/recursiveiteratoriterator.nextelement.php * @return void */ #[TentativeType] public function nextElement(): void {} /** * Set max depth * @link https://php.net/manual/en/recursiveiteratoriterator.setmaxdepth.php * @param int $maxDepth [optional]

    * The maximum allowed depth. Default -1 is used * for any depth. *

    * @return void */ #[TentativeType] public function setMaxDepth(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $maxDepth = -1): void {} /** * Get max depth * @link https://php.net/manual/en/recursiveiteratoriterator.getmaxdepth.php * @return int|false The maximum accepted depth, or false if any depth is allowed. */ #[TentativeType] public function getMaxDepth(): int|false {} } /** * Classes implementing OuterIterator can be used to iterate * over iterators. * @link https://php.net/manual/en/class.outeriterator.php */ interface OuterIterator extends Iterator { /** * Returns the inner iterator for the current entry. * @link https://php.net/manual/en/outeriterator.getinneriterator.php * @return Iterator|null The inner iterator for the current entry. */ #[TentativeType] public function getInnerIterator(): ?Iterator; } /** * This iterator wrapper allows the conversion of anything that is * Traversable into an Iterator. * It is important to understand that most classes that do not implement * Iterators have reasons as most likely they do not allow the full * Iterator feature set. If so, techniques should be provided to prevent * misuse, otherwise expect exceptions or fatal errors. * @link https://php.net/manual/en/class.iteratoriterator.php */ class IteratorIterator implements OuterIterator { /** * Create an iterator from anything that is traversable * @link https://php.net/manual/en/iteratoriterator.construct.php * @param Traversable $iterator * @param string|null $class [optional] */ public function __construct(Traversable $iterator, #[PhpStormStubsElementAvailable(from: '8.0')] ?string $class = null) {} /** * Get the inner iterator * @link https://php.net/manual/en/iteratoriterator.getinneriterator.php * @return Iterator|null The inner iterator as passed to IteratorIterator::__construct. */ #[TentativeType] public function getInnerIterator(): ?Iterator {} /** * Rewind to the first element * @link https://php.net/manual/en/iteratoriterator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Checks if the iterator is valid * @link https://php.net/manual/en/iteratoriterator.valid.php * @return bool true if the iterator is valid, otherwise false */ #[TentativeType] public function valid(): bool {} /** * Get the key of the current element * @link https://php.net/manual/en/iteratoriterator.key.php * @return mixed The key of the current element. */ #[TentativeType] public function key(): mixed {} /** * Get the current value * @link https://php.net/manual/en/iteratoriterator.current.php * @return mixed The value of the current element. */ #[TentativeType] public function current(): mixed {} /** * Forward to the next element * @link https://php.net/manual/en/iteratoriterator.next.php * @return void */ #[TentativeType] public function next(): void {} } /** * This abstract iterator filters out unwanted values. This class should be extended to * implement custom iterator filters. The FilterIterator::accept * must be implemented in the subclass. * @link https://php.net/manual/en/class.filteriterator.php */ abstract class FilterIterator extends IteratorIterator { /** * Check whether the current element of the iterator is acceptable * @link https://php.net/manual/en/filteriterator.accept.php * @return bool true if the current element is acceptable, otherwise false. */ #[TentativeType] abstract public function accept(): bool; /** * Construct a filterIterator * @link https://php.net/manual/en/filteriterator.construct.php * @param Iterator $iterator */ public function __construct(Iterator $iterator) {} /** * Rewind the iterator * @link https://php.net/manual/en/filteriterator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Check whether the current element is valid * @link https://php.net/manual/en/filteriterator.valid.php * @return bool true if the current element is valid, otherwise false */ public function valid() {} /** * Get the current key * @link https://php.net/manual/en/filteriterator.key.php * @return mixed The key of the current element. */ public function key() {} /** * Get the current element value * @link https://php.net/manual/en/filteriterator.current.php * @return mixed The current element value. */ public function current() {} /** * Move the iterator forward * @link https://php.net/manual/en/filteriterator.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Get the inner iterator * @link https://php.net/manual/en/filteriterator.getinneriterator.php * @return Iterator The inner iterator. */ public function getInnerIterator() {} } /** * This abstract iterator filters out unwanted values for a RecursiveIterator. * This class should be extended to implement custom filters. * The RecursiveFilterIterator::accept must be implemented in the subclass. * @link https://php.net/manual/en/class.recursivefilteriterator.php */ abstract class RecursiveFilterIterator extends FilterIterator implements RecursiveIterator { /** * Create a RecursiveFilterIterator from a RecursiveIterator * @link https://php.net/manual/en/recursivefilteriterator.construct.php * @param RecursiveIterator $iterator */ public function __construct(RecursiveIterator $iterator) {} /** * Check whether the inner iterator's current element has children * @link https://php.net/manual/en/recursivefilteriterator.haschildren.php * @return bool true if the inner iterator has children, otherwise false */ #[TentativeType] public function hasChildren(): bool {} /** * Return the inner iterator's children contained in a RecursiveFilterIterator * @link https://php.net/manual/en/recursivefilteriterator.getchildren.php * @return RecursiveFilterIterator|null containing the inner iterator's children. */ #[TentativeType] public function getChildren(): ?RecursiveFilterIterator {} } /** * This extended FilterIterator allows a recursive iteration using RecursiveIteratorIterator that only shows those elements which have children. * @link https://php.net/manual/en/class.parentiterator.php */ class ParentIterator extends RecursiveFilterIterator { /** * Determines acceptability * @link https://php.net/manual/en/parentiterator.accept.php * @return bool true if the current element is acceptable, otherwise false. */ #[TentativeType] public function accept(): bool {} /** * Constructs a ParentIterator * @link https://php.net/manual/en/parentiterator.construct.php * @param RecursiveIterator $iterator */ public function __construct(RecursiveIterator $iterator) {} /** * Check whether the inner iterator's current element has children * @link https://php.net/manual/en/recursivefilteriterator.haschildren.php * @return bool true if the inner iterator has children, otherwise false */ public function hasChildren() {} /** * Return the inner iterator's children contained in a RecursiveFilterIterator * @link https://php.net/manual/en/recursivefilteriterator.getchildren.php * @return ParentIterator containing the inner iterator's children. */ public function getChildren() {} } /** * The Seekable iterator. * @link https://php.net/manual/en/class.seekableiterator.php */ interface SeekableIterator extends Iterator { /** * Seeks to a position * @link https://php.net/manual/en/seekableiterator.seek.php * @param int $offset

    * The position to seek to. *

    * @return void */ #[TentativeType] public function seek(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset): void; } /** * The LimitIterator class allows iteration over * a limited subset of items in an Iterator. * @link https://php.net/manual/en/class.limititerator.php */ class LimitIterator extends IteratorIterator { /** * Construct a LimitIterator * @link https://php.net/manual/en/limititerator.construct.php * @param Iterator $iterator The iterator to limit. * @param int $offset [optional] The offset to start at. Must be zero or greater. * @param int $limit [optional] The number of items to iterate. Must be -1 or greater. -1, the default, means no limit. */ public function __construct( Iterator $iterator, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset = 0, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $limit = -1 ) {} /** * Rewind the iterator to the specified starting offset * @link https://php.net/manual/en/limititerator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Check whether the current element is valid * @link https://php.net/manual/en/limititerator.valid.php * @return bool true on success or false on failure. */ #[TentativeType] public function valid(): bool {} /** * Get current key * @link https://php.net/manual/en/limititerator.key.php * @return mixed The key of the current element. */ public function key() {} /** * Get current element * @link https://php.net/manual/en/limititerator.current.php * @return mixed the current element or null if there is none. */ public function current() {} /** * Move the iterator forward * @link https://php.net/manual/en/limititerator.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Seek to the given position * @link https://php.net/manual/en/limititerator.seek.php * @param int $offset

    * The position to seek to. *

    * @return int the offset position after seeking. */ #[TentativeType] public function seek(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset): int {} /** * Return the current position * @link https://php.net/manual/en/limititerator.getposition.php * @return int The current position. */ #[TentativeType] public function getPosition(): int {} /** * Get inner iterator * @link https://php.net/manual/en/limititerator.getinneriterator.php * @return Iterator The inner iterator passed to LimitIterator::__construct. */ public function getInnerIterator() {} } /** * This object supports cached iteration over another iterator. * @link https://php.net/manual/en/class.cachingiterator.php */ class CachingIterator extends IteratorIterator implements ArrayAccess, Countable, Stringable { /** * String conversion flag (mutually exclusive): Uses the current element for the iterator's string conversion. * This converts the current element to a string only once, regardless of whether it is needed or not. */ public const CALL_TOSTRING = 1; /** * String conversion flag (mutually exclusive). Uses the current key for the iterator's string conversion. */ public const TOSTRING_USE_KEY = 2; /** * String conversion flag (mutually exclusive). Uses the current element for the iterator's string conversion. * This converts the current element to a string only when (and every time) it is needed. */ public const TOSTRING_USE_CURRENT = 4; /** * String conversion flag (mutually exclusive). Forwards the string conversion to the inner iterator. * This converts the inner iterator to a string only once, regardless of whether it is needed or not. */ public const TOSTRING_USE_INNER = 8; /** * Ignore exceptions thrown in accessing children. Only used with {@see RecursiveCachingIterator}. */ public const CATCH_GET_CHILD = 16; /** * Cache all read data. This is needed to use {@see CachingIterator::getCache}, and ArrayAccess and Countable methods. */ public const FULL_CACHE = 256; /** * Constructs a new CachingIterator. * @link https://php.net/manual/en/cachingiterator.construct.php * @param Iterator $iterator The iterator to cache. * @param int $flags [optional] A bitmask of flags. See CachingIterator class constants for details. */ public function __construct(Iterator $iterator, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = self::CALL_TOSTRING) {} /** * Rewind the iterator * @link https://php.net/manual/en/cachingiterator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Check whether the current element is valid * @link https://php.net/manual/en/cachingiterator.valid.php * @return bool true on success or false on failure. */ #[TentativeType] public function valid(): bool {} /** * Return the key for the current element * @link https://php.net/manual/en/cachingiterator.key.php * @return mixed The key of the current element. */ public function key() {} /** * Return the current element * @link https://php.net/manual/en/cachingiterator.current.php * @return mixed */ public function current() {} /** * Move the iterator forward * @link https://php.net/manual/en/cachingiterator.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Check whether the inner iterator has a valid next element * @link https://php.net/manual/en/cachingiterator.hasnext.php * @return bool true on success or false on failure. */ #[TentativeType] public function hasNext(): bool {} /** * Return the string representation of the current iteration based on the flag being used. * @link https://php.net/manual/en/cachingiterator.tostring.php * @return string The string representation of the current iteration based on the flag being used. */ #[TentativeType] public function __toString(): string {} /** * Returns the inner iterator * @link https://php.net/manual/en/cachingiterator.getinneriterator.php * @return Iterator an object implementing the Iterator interface. */ public function getInnerIterator() {} /** * Get flags used * @link https://php.net/manual/en/cachingiterator.getflags.php * @return int Bitmask of the flags */ #[TentativeType] public function getFlags(): int {} /** * The setFlags purpose * @link https://php.net/manual/en/cachingiterator.setflags.php * @param int $flags Bitmask of the flags to set. * @return void */ #[TentativeType] public function setFlags(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags): void {} /** * Internal cache array index to retrieve. * @link https://php.net/manual/en/cachingiterator.offsetget.php * @param string $key The index of the element to retrieve. * @return mixed * @throws BadMethodCallException when the {@see CachingIterator::FULL_CACHE} flag is not being used. */ #[TentativeType] public function offsetGet($key): mixed {} /** * Set an element on the internal cache array. * @link https://php.net/manual/en/cachingiterator.offsetset.php * @param string $key The index of the element to be set. * @param string $value The new value for the index. * @return void * @throws BadMethodCallException when the {@see CachingIterator::FULL_CACHE} flag is not being used. */ #[TentativeType] public function offsetSet($key, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value): void {} /** * Remove an element from the internal cache array. * @link https://php.net/manual/en/cachingiterator.offsetunset.php * @param string $key The index of the element to be unset. * @return void * @throws BadMethodCallException when the {@see CachingIterator::FULL_CACHE} flag is not being used. */ #[TentativeType] public function offsetUnset($key): void {} /** * Return whether an element at the index exists on the internal cache array. * @link https://php.net/manual/en/cachingiterator.offsetexists.php * @param string $key The index being checked. * @return bool true if an entry referenced by the offset exists, false otherwise. * @throws BadMethodCallException when the {@see CachingIterator::FULL_CACHE} flag is not being used. */ #[TentativeType] public function offsetExists($key): bool {} /** * Retrieve the contents of the cache * @link https://php.net/manual/en/cachingiterator.getcache.php * @return array An array containing the cache items. * @throws BadMethodCallException when the {@see CachingIterator::FULL_CACHE} flag is not being used. */ #[TentativeType] public function getCache(): array {} /** * The number of elements in the iterator * @link https://php.net/manual/en/cachingiterator.count.php * @return int The count of the elements iterated over. * @throws BadMethodCallException when the {@see CachingIterator::FULL_CACHE} flag is not being used. * @since 5.2.2 */ #[TentativeType] public function count(): int {} } /** * ... * @link https://php.net/manual/en/class.recursivecachingiterator.php */ class RecursiveCachingIterator extends CachingIterator implements RecursiveIterator { /** * Constructs a new RecursiveCachingIterator. * @link https://php.net/manual/en/recursivecachingiterator.construct.php * @param Iterator $iterator The iterator to cache. * @param int $flags [optional] A bitmask of flags. See CachingIterator class constants for details. */ public function __construct(Iterator $iterator, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = CachingIterator::CALL_TOSTRING) {} /** * Check whether the current element of the inner iterator has children * @link https://php.net/manual/en/recursivecachingiterator.haschildren.php * @return bool true if the inner iterator has children, otherwise false */ #[TentativeType] public function hasChildren(): bool {} /** * Return the inner iterator's children as a RecursiveCachingIterator * @link https://php.net/manual/en/recursivecachingiterator.getchildren.php * @return RecursiveCachingIterator|null The inner iterator's children, as a RecursiveCachingIterator. */ #[TentativeType] public function getChildren(): ?RecursiveCachingIterator {} } /** * This iterator cannot be rewinded. * @link https://php.net/manual/en/class.norewinditerator.php */ class NoRewindIterator extends IteratorIterator { /** * Construct a NoRewindIterator * @link https://php.net/manual/en/norewinditerator.construct.php * @param Iterator $iterator */ public function __construct(Iterator $iterator) {} /** * Prevents the rewind operation on the inner iterator. * @link https://php.net/manual/en/norewinditerator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Validates the iterator * @link https://php.net/manual/en/norewinditerator.valid.php * @return bool true on success or false on failure. */ #[TentativeType] public function valid(): bool {} /** * Get the current key * @link https://php.net/manual/en/norewinditerator.key.php * @return mixed The key of the current element. */ #[TentativeType] public function key(): mixed {} /** * Get the current value * @link https://php.net/manual/en/norewinditerator.current.php * @return mixed The current value. */ #[TentativeType] public function current(): mixed {} /** * Forward to the next element * @link https://php.net/manual/en/norewinditerator.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Get the inner iterator * @link https://php.net/manual/en/norewinditerator.getinneriterator.php * @return Iterator The inner iterator, as passed to NoRewindIterator::__construct. */ public function getInnerIterator() {} } /** * An Iterator that iterates over several iterators one after the other. * @link https://php.net/manual/en/class.appenditerator.php */ class AppendIterator extends IteratorIterator { /** * Constructs an AppendIterator * @link https://php.net/manual/en/appenditerator.construct.php */ public function __construct() {} /** * Appends an iterator * @link https://php.net/manual/en/appenditerator.append.php * @param Iterator $iterator

    * The iterator to append. *

    * @return void */ #[TentativeType] public function append(Iterator $iterator): void {} /** * Rewinds the Iterator * @link https://php.net/manual/en/appenditerator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Checks validity of the current element * @link https://php.net/manual/en/appenditerator.valid.php * @return bool true on success or false on failure. */ #[TentativeType] public function valid(): bool {} /** * Gets the current key * @link https://php.net/manual/en/appenditerator.key.php * @return mixed The key of the current element. */ public function key() {} /** * Gets the current value * @link https://php.net/manual/en/appenditerator.current.php * @return mixed The current value if it is valid or null otherwise. */ #[TentativeType] public function current(): mixed {} /** * Moves to the next element * @link https://php.net/manual/en/appenditerator.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Gets an inner iterator * @link https://php.net/manual/en/appenditerator.getinneriterator.php * @return Iterator the current inner Iterator. */ public function getInnerIterator() {} /** * Gets an index of iterators * @link https://php.net/manual/en/appenditerator.getiteratorindex.php * @return int|null The index of iterators. */ #[TentativeType] public function getIteratorIndex(): ?int {} /** * The getArrayIterator method * @link https://php.net/manual/en/appenditerator.getarrayiterator.php * @return ArrayIterator containing the appended iterators. */ #[TentativeType] public function getArrayIterator(): ArrayIterator {} } /** * The InfiniteIterator allows one to * infinitely iterate over an iterator without having to manually * rewind the iterator upon reaching its end. * @link https://php.net/manual/en/class.infiniteiterator.php */ class InfiniteIterator extends IteratorIterator { /** * Constructs an InfiniteIterator * @link https://php.net/manual/en/infiniteiterator.construct.php * @param Iterator $iterator */ public function __construct(Iterator $iterator) {} /** * Moves the inner Iterator forward or rewinds it * @link https://php.net/manual/en/infiniteiterator.next.php * @return void */ #[TentativeType] public function next(): void {} } /** * This iterator can be used to filter another iterator based on a regular expression. * @link https://php.net/manual/en/class.regexiterator.php */ class RegexIterator extends FilterIterator { /** * Return all matches for the current entry @see preg_match_all */ public const ALL_MATCHES = 2; /** * Return the first match for the current entry @see preg_match */ public const GET_MATCH = 1; /** * Only execute match (filter) for the current entry @see preg_match */ public const MATCH = 0; /** * Replace the current entry (Not fully implemented yet) @see preg_replace */ public const REPLACE = 4; /** * Returns the split values for the current entry @see preg_split */ public const SPLIT = 3; /** * Special flag: Match the entry key instead of the entry value. */ public const USE_KEY = 1; public const INVERT_MATCH = 2; #[LanguageLevelTypeAware(['8.1' => 'string|null'], default: '')] public $replacement; /** * Create a new RegexIterator * @link https://php.net/manual/en/regexiterator.construct.php * @param Iterator $iterator The iterator to apply this regex filter to. * @param string $pattern The regular expression to match. * @param int $mode [optional] Operation mode, see RegexIterator::setMode() for a list of modes. * @param int $flags [optional] Special flags, see RegexIterator::setFlags() for a list of available flags. * @param int $pregFlags [optional] The regular expression flags. These flags depend on the operation mode parameter */ public function __construct( Iterator $iterator, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $pattern, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode = self::MATCH, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $pregFlags = 0 ) {} /** * Get accept status * @link https://php.net/manual/en/regexiterator.accept.php * @return bool true if a match, false otherwise. */ #[TentativeType] public function accept(): bool {} /** * Returns operation mode. * @link https://php.net/manual/en/regexiterator.getmode.php * @return int the operation mode. */ #[TentativeType] public function getMode(): int {} /** * Sets the operation mode. * @link https://php.net/manual/en/regexiterator.setmode.php * @param int $mode

    * The operation mode. *

    *

    * The available modes are listed below. The actual * meanings of these modes are described in the * predefined constants. *

    * RegexIterator modes * * * * * * * * * * * * * * * * * * * * * * * * *
    valueconstant
    0 * RegexIterator::MATCH *
    1 * RegexIterator::GET_MATCH *
    2 * RegexIterator::ALL_MATCHES *
    3 * RegexIterator::SPLIT *
    4 * RegexIterator::REPLACE *
    *

    * @return void */ #[TentativeType] public function setMode(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode): void {} /** * Get flags * @link https://php.net/manual/en/regexiterator.getflags.php * @return int the set flags. */ #[TentativeType] public function getFlags(): int {} /** * Sets the flags. * @link https://php.net/manual/en/regexiterator.setflags.php * @param int $flags

    * The flags to set, a bitmask of class constants. *

    *

    * The available flags are listed below. The actual * meanings of these flags are described in the * predefined constants. *

    * RegexIterator flags * * * * * * * * *
    valueconstant
    1 * RegexIterator::USE_KEY *
    *

    * @return void */ #[TentativeType] public function setFlags(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags): void {} /** * Returns current regular expression * @link https://secure.php.net/manual/en/regexiterator.getregex.php * @return string * @since 5.4 */ #[TentativeType] public function getRegex(): string {} /** * Returns the regular expression flags. * @link https://php.net/manual/en/regexiterator.getpregflags.php * @return int a bitmask of the regular expression flags. */ #[TentativeType] public function getPregFlags(): int {} /** * Sets the regular expression flags. * @link https://php.net/manual/en/regexiterator.setpregflags.php * @param int $pregFlags

    * The regular expression flags. See RegexIterator::__construct * for an overview of available flags. *

    * @return void */ #[TentativeType] public function setPregFlags(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $pregFlags): void {} } /** * This recursive iterator can filter another recursive iterator via a regular expression. * @link https://php.net/manual/en/class.recursiveregexiterator.php */ class RecursiveRegexIterator extends RegexIterator implements RecursiveIterator { /** * Creates a new RecursiveRegexIterator. * @link https://php.net/manual/en/recursiveregexiterator.construct.php * @param RecursiveIterator $iterator The iterator to apply this regex filter to. * @param string $pattern The regular expression to match. * @param int $mode [optional] Operation mode, see RegexIterator::setMode() for a list of modes. * @param int $flags [optional] Special flags, see RegexIterator::setFlags() for a list of available flags. * @param int $pregFlags [optional] The regular expression flags. These flags depend on the operation mode parameter */ public function __construct( RecursiveIterator $iterator, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $pattern, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode = RegexIterator::MATCH, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $pregFlags = 0 ) {} /** * Returns whether an iterator can be obtained for the current entry. * @link https://php.net/manual/en/recursiveregexiterator.haschildren.php * @return bool true if an iterator can be obtained for the current entry, otherwise returns false. */ #[TentativeType] public function hasChildren(): bool {} /** * Returns an iterator for the current entry. * @link https://php.net/manual/en/recursiveregexiterator.getchildren.php * @return RecursiveRegexIterator An iterator for the current entry, if it can be iterated over by the inner iterator. */ #[TentativeType] public function getChildren(): RecursiveRegexIterator {} } /** * Allows iterating over a RecursiveIterator to generate an ASCII graphic tree. * @link https://php.net/manual/en/class.recursivetreeiterator.php */ class RecursiveTreeIterator extends RecursiveIteratorIterator { public const BYPASS_CURRENT = 4; public const BYPASS_KEY = 8; public const PREFIX_LEFT = 0; public const PREFIX_MID_HAS_NEXT = 1; public const PREFIX_MID_LAST = 2; public const PREFIX_END_HAS_NEXT = 3; public const PREFIX_END_LAST = 4; public const PREFIX_RIGHT = 5; /** * Construct a RecursiveTreeIterator * @link https://php.net/manual/en/recursivetreeiterator.construct.php * @param RecursiveIterator|IteratorAggregate $iterator * @param int $flags [optional] Flags to control the behavior of the RecursiveTreeIterator object. * @param int $cachingIteratorFlags [optional] Flags to affect the behavior of the {@see RecursiveCachingIterator} used internally. * @param int $mode [optional] Flags to affect the behavior of the {@see RecursiveIteratorIterator} used internally. */ public function __construct( $iterator, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = self::BYPASS_KEY, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $cachingIteratorFlags = CachingIterator::CATCH_GET_CHILD, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $mode = RecursiveIteratorIterator::SELF_FIRST ) {} /** * Rewind iterator * @link https://php.net/manual/en/recursivetreeiterator.rewind.php * @return void */ public function rewind() {} /** * Check validity * @link https://php.net/manual/en/recursivetreeiterator.valid.php * @return bool true if the current position is valid, otherwise false */ public function valid() {} /** * Get the key of the current element * @link https://php.net/manual/en/recursivetreeiterator.key.php * @return string the current key prefixed and postfixed. */ #[TentativeType] public function key(): mixed {} /** * Get current element * @link https://php.net/manual/en/recursivetreeiterator.current.php * @return string the current element prefixed and postfixed. */ #[TentativeType] public function current(): mixed {} /** * Move to next element * @link https://php.net/manual/en/recursivetreeiterator.next.php * @return void */ public function next() {} /** * Begin iteration * @link https://php.net/manual/en/recursivetreeiterator.beginiteration.php * @return RecursiveIterator A RecursiveIterator. */ public function beginIteration() {} /** * End iteration * @link https://php.net/manual/en/recursivetreeiterator.enditeration.php * @return void */ public function endIteration() {} /** * Has children * @link https://php.net/manual/en/recursivetreeiterator.callhaschildren.php * @return bool true if there are children, otherwise false */ public function callHasChildren() {} /** * Get children * @link https://php.net/manual/en/recursivetreeiterator.callgetchildren.php * @return RecursiveIterator A RecursiveIterator. */ public function callGetChildren() {} /** * Begin children * @link https://php.net/manual/en/recursivetreeiterator.beginchildren.php * @return void */ public function beginChildren() {} /** * End children * @link https://php.net/manual/en/recursivetreeiterator.endchildren.php * @return void */ public function endChildren() {} /** * Next element * @link https://php.net/manual/en/recursivetreeiterator.nextelement.php * @return void */ public function nextElement() {} /** * Get the prefix * @link https://php.net/manual/en/recursivetreeiterator.getprefix.php * @return string the string to place in front of current element */ #[TentativeType] public function getPrefix(): string {} /** * @param string $postfix */ #[TentativeType] public function setPostfix(#[PhpStormStubsElementAvailable(from: '7.3')] string $postfix): void {} /** * Set a part of the prefix * @link https://php.net/manual/en/recursivetreeiterator.setprefixpart.php * @param int $part

    * One of the RecursiveTreeIterator::PREFIX_* constants. *

    * @param string $value

    * The value to assign to the part of the prefix specified in part. *

    * @return void */ #[TentativeType] public function setPrefixPart( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $part, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $value ): void {} /** * Get current entry * @link https://php.net/manual/en/recursivetreeiterator.getentry.php * @return string the part of the tree built for the current element. */ #[TentativeType] public function getEntry(): string {} /** * Get the postfix * @link https://php.net/manual/en/recursivetreeiterator.getpostfix.php * @return string to place after the current element. */ #[TentativeType] public function getPostfix(): string {} } /** * This class allows objects to work as arrays. * @link https://php.net/manual/en/class.arrayobject.php * @template TKey * @template TValue * @template-implements IteratorAggregate * @template-implements ArrayAccess */ class ArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable { /** * Properties of the object have their normal functionality when accessed as list (var_dump, foreach, etc.). */ public const STD_PROP_LIST = 1; /** * Entries can be accessed as properties (read and write). */ public const ARRAY_AS_PROPS = 2; /** * Construct a new array object * @link https://php.net/manual/en/arrayobject.construct.php * @param array|object $array The input parameter accepts an array or an Object. * @param int $flags Flags to control the behaviour of the ArrayObject object. * @param class-string $iteratorClass Specify the class that will be used for iteration of the ArrayObject object. ArrayIterator is the default class used. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'object|array'], default: '')] $array = [], #[PhpStormStubsElementAvailable(from: '5.3')] #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0, #[PhpStormStubsElementAvailable(from: '5.3')] #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $iteratorClass = "ArrayIterator" ) {} /** * Returns whether the requested index exists * @link https://php.net/manual/en/arrayobject.offsetexists.php * @param TKey $key

    * The index being checked. *

    * @return bool true if the requested index exists, otherwise false */ #[TentativeType] public function offsetExists(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $key): bool {} /** * Returns the value at the specified index * @link https://php.net/manual/en/arrayobject.offsetget.php * @param TKey $key

    * The index with the value. *

    * @return TValue|null The value at the specified index or null. */ #[TentativeType] public function offsetGet(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $key): mixed {} /** * Sets the value at the specified index to newval * @link https://php.net/manual/en/arrayobject.offsetset.php * @param TKey $key

    * The index being set. *

    * @param TValue $value

    * The new value for the index. *

    * @return void */ #[TentativeType] public function offsetSet( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $key, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value ): void {} /** * Unsets the value at the specified index * @link https://php.net/manual/en/arrayobject.offsetunset.php * @param TKey $key

    * The index being unset. *

    * @return void */ #[TentativeType] public function offsetUnset(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $key): void {} /** * Appends the value * @link https://php.net/manual/en/arrayobject.append.php * @param TValue $value

    * The value being appended. *

    * @return void */ #[TentativeType] public function append(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value): void {} /** * Creates a copy of the ArrayObject. * @link https://php.net/manual/en/arrayobject.getarraycopy.php * @return array a copy of the array. When the ArrayObject refers to an object * an array of the public properties of that object will be returned. */ #[TentativeType] public function getArrayCopy(): array {} /** * Get the number of public properties in the ArrayObject * When the ArrayObject is constructed from an array all properties are public. * @link https://php.net/manual/en/arrayobject.count.php * @return int The number of public properties in the ArrayObject. */ #[TentativeType] public function count(): int {} /** * Gets the behavior flags. * @link https://php.net/manual/en/arrayobject.getflags.php * @return int the behavior flags of the ArrayObject. */ #[TentativeType] public function getFlags(): int {} /** * Sets the behavior flags. * @link https://php.net/manual/en/arrayobject.setflags.php * @param int $flags

    * The new ArrayObject behavior. * It takes on either a bitmask, or named constants. Using named * constants is strongly encouraged to ensure compatibility for future * versions. *

    *

    * The available behavior flags are listed below. The actual * meanings of these flags are described in the * predefined constants. *

    * ArrayObject behavior flags * * * * * * * * * * * * *
    valueconstant
    1 * ArrayObject::STD_PROP_LIST *
    2 * ArrayObject::ARRAY_AS_PROPS *
    *

    * @return void */ #[TentativeType] public function setFlags(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags): void {} /** * Sort the entries by value * @link https://php.net/manual/en/arrayobject.asort.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function asort(#[PhpStormStubsElementAvailable(from: '8.0')] int $flags = SORT_REGULAR) {} /** * Sort the entries by key * @link https://php.net/manual/en/arrayobject.ksort.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function ksort(#[PhpStormStubsElementAvailable(from: '8.0')] int $flags = SORT_REGULAR) {} /** * Sort the entries with a user-defined comparison function and maintain key association * @link https://php.net/manual/en/arrayobject.uasort.php * @param callable(TValue, TValue):int $callback

    * Function cmp_function should accept two * parameters which will be filled by pairs of entries. * The comparison function must return an integer less than, equal * to, or greater than zero if the first argument is considered to * be respectively less than, equal to, or greater than the * second. *

    */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function uasort(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback) {} /** * Sort the entries by keys using a user-defined comparison function * @link https://php.net/manual/en/arrayobject.uksort.php * @param callable(TValue, TValue):int $callback

    * The callback comparison function. *

    *

    * Function cmp_function should accept two * parameters which will be filled by pairs of entry keys. * The comparison function must return an integer less than, equal * to, or greater than zero if the first argument is considered to * be respectively less than, equal to, or greater than the * second. *

    */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function uksort(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback) {} /** * Sort entries using a "natural order" algorithm * @link https://php.net/manual/en/arrayobject.natsort.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function natsort() {} /** * Sort an array using a case insensitive "natural order" algorithm * @link https://php.net/manual/en/arrayobject.natcasesort.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function natcasesort() {} /** * Unserialize an ArrayObject * @link https://php.net/manual/en/arrayobject.unserialize.php * @param string $data

    * The serialized ArrayObject. *

    * @return void */ #[TentativeType] public function unserialize(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data): void {} /** * Serialize an ArrayObject * @link https://php.net/manual/en/arrayobject.serialize.php * @return string The serialized representation of the ArrayObject. */ #[TentativeType] public function serialize(): string {} /** * @return array * @since 7.4 */ #[TentativeType] public function __debugInfo(): array {} /** * @return array * @since 7.4 */ #[TentativeType] public function __serialize(): array {} /** * @param array $data * @since 7.4 */ #[TentativeType] public function __unserialize(array $data): void {} /** * Create a new iterator from an ArrayObject instance * @link https://php.net/manual/en/arrayobject.getiterator.php * @return ArrayIterator An iterator from an ArrayObject. */ #[TentativeType] public function getIterator(): Iterator {} /** * Exchange the array for another one. * @link https://php.net/manual/en/arrayobject.exchangearray.php * @param mixed $array

    * The new array or object to exchange with the current array. *

    * @return array the old array. */ #[TentativeType] public function exchangeArray(#[LanguageLevelTypeAware(['8.0' => 'object|array'], default: '')] $array): array {} /** * Sets the iterator classname for the ArrayObject. * @link https://php.net/manual/en/arrayobject.setiteratorclass.php * @param class-string $iteratorClass

    * The classname of the array iterator to use when iterating over this object. *

    * @return void */ #[TentativeType] public function setIteratorClass(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $iteratorClass): void {} /** * Gets the iterator classname for the ArrayObject. * @link https://php.net/manual/en/arrayobject.getiteratorclass.php * @return class-string the iterator class name that is used to iterate over this object. */ #[TentativeType] public function getIteratorClass(): string {} } /** * This iterator allows to unset and modify values and keys while iterating * over Arrays and Objects. * @link https://php.net/manual/en/class.arrayiterator.php */ class ArrayIterator implements SeekableIterator, ArrayAccess, Serializable, Countable { public const STD_PROP_LIST = 1; public const ARRAY_AS_PROPS = 2; /** * Construct an ArrayIterator * @link https://php.net/manual/en/arrayiterator.construct.php * @param array $array The array or object to be iterated on. * @param int $flags Flags to control the behaviour of the ArrayObject object. * @see ArrayObject::setFlags() */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'object|array'], default: '')] $array = [], #[PhpStormStubsElementAvailable(from: '7.0')] #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0, #[PhpStormStubsElementAvailable(from: '7.0', to: '7.1')] $iterator_class = null ) {} /** * Check if offset exists * @link https://php.net/manual/en/arrayiterator.offsetexists.php * @param string $key

    * The offset being checked. *

    * @return bool true if the offset exists, otherwise false */ #[TentativeType] public function offsetExists(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $key): bool {} /** * Get value for an offset * @link https://php.net/manual/en/arrayiterator.offsetget.php * @param string $key

    * The offset to get the value from. *

    * @return mixed The value at offset index. */ #[TentativeType] public function offsetGet(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $key): mixed {} /** * Set value for an offset * @link https://php.net/manual/en/arrayiterator.offsetset.php * @param string $key

    * The index to set for. *

    * @param string $value

    * The new value to store at the index. *

    * @return void */ #[TentativeType] public function offsetSet( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $key, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value ): void {} /** * Unset value for an offset * @link https://php.net/manual/en/arrayiterator.offsetunset.php * @param string $key

    * The offset to unset. *

    * @return void */ #[TentativeType] public function offsetUnset(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $key): void {} /** * Append an element * @link https://php.net/manual/en/arrayiterator.append.php * @param mixed $value

    * The value to append. *

    * @return void */ #[TentativeType] public function append(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value): void {} /** * Get array copy * @link https://php.net/manual/en/arrayiterator.getarraycopy.php * @return array A copy of the array, or array of public properties * if ArrayIterator refers to an object. */ #[TentativeType] public function getArrayCopy(): array {} /** * Count elements * @link https://php.net/manual/en/arrayiterator.count.php * @return int<0,max> The number of elements or public properties in the associated * array or object, respectively. */ #[TentativeType] public function count(): int {} /** * Get flags * @link https://php.net/manual/en/arrayiterator.getflags.php * @return int The current flags. */ #[TentativeType] public function getFlags(): int {} /** * Set behaviour flags * @link https://php.net/manual/en/arrayiterator.setflags.php * @param string $flags

    * A bitmask as follows: * 0 = Properties of the object have their normal functionality * when accessed as list (var_dump, foreach, etc.). * 1 = Array indices can be accessed as properties in read/write. *

    * @return void */ #[TentativeType] public function setFlags(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags): void {} /** * Sort array by values * @link https://php.net/manual/en/arrayiterator.asort.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function asort(#[PhpStormStubsElementAvailable(from: '8.0')] int $flags = SORT_REGULAR) {} /** * Sort array by keys * @link https://php.net/manual/en/arrayiterator.ksort.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function ksort(#[PhpStormStubsElementAvailable(from: '8.0')] int $flags = SORT_REGULAR) {} /** * User defined sort * @link https://php.net/manual/en/arrayiterator.uasort.php * @param callable $callback

    * The compare function used for the sort. *

    */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function uasort(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback) {} /** * User defined sort * @link https://php.net/manual/en/arrayiterator.uksort.php * @param callable $callback

    * The compare function used for the sort. *

    */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function uksort(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback) {} /** * Sort an array naturally * @link https://php.net/manual/en/arrayiterator.natsort.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function natsort() {} /** * Sort an array naturally, case insensitive * @link https://php.net/manual/en/arrayiterator.natcasesort.php */ #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] public function natcasesort() {} /** * Unserialize * @link https://php.net/manual/en/arrayiterator.unserialize.php * @param string $data

    * The serialized ArrayIterator object to be unserialized. *

    * @return void */ #[TentativeType] public function unserialize(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data): void {} /** * Serialize * @link https://php.net/manual/en/arrayiterator.serialize.php * @return string The serialized ArrayIterator. */ #[TentativeType] public function serialize(): string {} /** * Rewind array back to the start * @link https://php.net/manual/en/arrayiterator.rewind.php * @return void */ #[TentativeType] public function rewind(): void {} /** * Return current array entry * @link https://php.net/manual/en/arrayiterator.current.php * @return mixed The current array entry. */ #[TentativeType] public function current(): mixed {} /** * Return current array key * @link https://php.net/manual/en/arrayiterator.key.php * @return string|int|null The key of the current element. */ #[TentativeType] public function key(): string|int|null {} /** * Move to next entry * @link https://php.net/manual/en/arrayiterator.next.php * @return void */ #[TentativeType] public function next(): void {} /** * Check whether array contains more entries * @link https://php.net/manual/en/arrayiterator.valid.php * @return bool */ #[TentativeType] public function valid(): bool {} /** * Seek to position * @link https://php.net/manual/en/arrayiterator.seek.php * @param int $offset

    * The position to seek to. *

    * @return void */ #[TentativeType] public function seek(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $offset): void {} /** * @return array * @since 7.4 */ #[TentativeType] public function __debugInfo(): array {} /** * @return array * @since 7.4 */ #[TentativeType] public function __serialize(): array {} /** * @param array $data * @since 7.4 */ #[TentativeType] public function __unserialize(array $data): void {} } /** * This iterator allows to unset and modify values and keys while iterating over Arrays and Objects * in the same way as the ArrayIterator. Additionally it is possible to iterate * over the current iterator entry. * @link https://php.net/manual/en/class.recursivearrayiterator.php */ class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator { public const CHILD_ARRAYS_ONLY = 4; /** * Returns whether current entry is an array or an object. * @link https://php.net/manual/en/recursivearrayiterator.haschildren.php * @return bool true if the current entry is an array or an object, * otherwise false is returned. */ #[TentativeType] public function hasChildren(): bool {} /** * Returns an iterator for the current entry if it is an array or an object. * @link https://php.net/manual/en/recursivearrayiterator.getchildren.php * @return RecursiveArrayIterator|null An iterator for the current entry, if it is an array or object. */ #[TentativeType] public function getChildren(): ?RecursiveArrayIterator {} } *

    * @param string|null $file_extensions [optional]

    * By default it checks all include paths to * contain filenames built up by the lowercase class name appended by the * filename extensions .inc and .php. *

    * @return void * @since 5.1.2 */ function spl_autoload(string $class, ?string $file_extensions): void {} /** * Register and return default file extensions for spl_autoload * @link https://php.net/manual/en/function.spl-autoload-extensions.php * @param string|null $file_extensions [optional]

    * When calling without an argument, it simply returns the current list * of extensions each separated by comma. To modify the list of file * extensions, simply invoke the functions with the new list of file * extensions to use in a single string with each extensions separated * by comma. *

    * @return string A comma delimited list of default file extensions for * spl_autoload. * @since 5.1.2 */ function spl_autoload_extensions(?string $file_extensions): string {} /** * Register given function as __autoload() implementation * @link https://php.net/manual/en/function.spl-autoload-register.php * @param callable|null $callback [optional]

    * The autoload function being registered. * If no parameter is provided, then the default implementation of * spl_autoload will be registered. *

    * @param bool $throw This parameter specifies whether spl_autoload_register() should throw exceptions when the * autoload_function cannot be registered. Ignored since since 8.0. * @param bool $prepend If true, spl_autoload_register() will prepend the autoloader on the autoload stack instead of * appending it. * @return bool true on success or false on failure. * @throws TypeError Since 8.0. * @since 5.1.2 */ function spl_autoload_register(?callable $callback, bool $throw = true, bool $prepend = false): bool {} /** * Unregister given function as __autoload() implementation * @link https://php.net/manual/en/function.spl-autoload-unregister.php * @param callable $callback

    * The autoload function being unregistered. *

    * @return bool true on success or false on failure. * @since 5.1.2 */ function spl_autoload_unregister(callable $callback): bool {} /** * Return all registered __autoload() functions * @link https://php.net/manual/en/function.spl-autoload-functions.php * @return array|false An array of all registered __autoload functions. * If the autoload stack is not activated then the return value is false. * If no function is registered the return value will be an empty array. * @since 5.1.2 */ #[LanguageLevelTypeAware(["8.0" => "array"], default: "array|false")] function spl_autoload_functions() {} /** * Try all registered __autoload() functions to load the requested class * @link https://php.net/manual/en/function.spl-autoload-call.php * @param string $class

    * The class name being searched. *

    * @return void * @since 5.1.2 */ function spl_autoload_call(string $class): void {} /** * Return the parent classes of the given class * @link https://php.net/manual/en/function.class-parents.php * @param object|string $object_or_class

    * An object (class instance) or a string (class name). *

    * @param bool $autoload [optional]

    * Whether to allow this function to load the class automatically through * the __autoload magic * method. *

    * @return string[]|false An array on success, or false on error. */ #[Pure] function class_parents($object_or_class, bool $autoload = true): array|false {} /** * Return the interfaces which are implemented by the given class * @link https://php.net/manual/en/function.class-implements.php * @param object|string $object_or_class

    * An object (class instance) or a string (class name). *

    * @param bool $autoload [optional]

    * Whether to allow this function to load the class automatically through * the __autoload magic * method. *

    * @return string[]|false An array on success, or false on error. */ #[Pure] function class_implements($object_or_class, bool $autoload = true): array|false {} /** * Return hash id for given object * @link https://php.net/manual/en/function.spl-object-hash.php * @param object $object * @return string A string that is unique for each object and is always the same for * the same object. */ #[Pure] function spl_object_hash(object $object): string {} /** * Copy the iterator into an array * @link https://php.net/manual/en/function.iterator-to-array.php * @param Traversable $iterator

    * The iterator being copied. *

    * @param bool $preserve_keys [optional]

    * Whether to use the iterator element keys as index. *

    * @return array An array containing the elements of the iterator. */ function iterator_to_array(#[LanguageLevelTypeAware(['8.2' => 'Traversable|array'], default: 'Traversable')] $iterator, bool $preserve_keys = true): array {} /** * Count the elements in an iterator * @link https://php.net/manual/en/function.iterator-count.php * @param Traversable $iterator

    * The iterator being counted. *

    * @return int The number of elements in iterator. */ #[Pure] function iterator_count(#[LanguageLevelTypeAware(['8.2' => 'Traversable|array'], default: 'Traversable')] $iterator): int {} /** * Call a function for every element in an iterator * @link https://php.net/manual/en/function.iterator-apply.php * @param Traversable $iterator

    * The class to iterate over. *

    * @param callable $callback

    * The callback function to call on every element. * The function must return true in order to * continue iterating over the iterator. *

    * @param array|null $args [optional]

    * Arguments to pass to the callback function. *

    * @return int the iteration count. */ function iterator_apply(Traversable $iterator, callable $callback, ?array $args): int {} // End of SPL v.0.2 /** * Return the traits used by the given class * @param object|string $object_or_class An object (class instance) or a string (class name). * @param bool $autoload Whether to allow this function to load the class automatically through the __autoload() magic method. * @return string[]|false An array on success, or false on error. * @link https://php.net/manual/en/function.class-uses.php * @see class_parents() * @see get_declared_traits() * @since 5.4 */ function class_uses($object_or_class, bool $autoload = true): array|false {} /** * return the integer object handle for given object * @param object $object * @return int * @since 7.2 */ function spl_object_id(object $object): int {} 'ReflectionNamedType[]|ReflectionIntersectionType[]' ], default: 'ReflectionNamedType[]' )] public function getTypes(): array {} } ReflectionFunction class reports * information about a function. * * @link https://php.net/manual/en/class.reflectionfunction.php */ class ReflectionFunction extends ReflectionFunctionAbstract { /** * @var string Function name, same as calling the {@see ReflectionFunction::getName()} method */ #[Immutable] public $name; /** * Indicates deprecated functions. * * @link https://www.php.net/manual/en/class.reflectionfunction.php#reflectionfunction.constants.is-deprecated */ public const IS_DEPRECATED = 2048; /** * Constructs a ReflectionFunction object * * @link https://php.net/manual/en/reflectionfunction.construct.php * @param string|Closure $function The name of the function to reflect or a closure. * @throws ReflectionException if the function does not exist. */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'Closure|string'], default: '')] $function) {} /** * Returns the string representation of the ReflectionFunction object. * * @link https://php.net/manual/en/reflectionfunction.tostring.php */ #[TentativeType] public function __toString(): string {} /** * Exports function * * @link https://php.net/manual/en/reflectionfunction.export.php * @param string $name The reflection to export. * @param bool $return Setting to {@see true} will return the * export, as opposed to emitting it. Setting to {@see false} (the default) * will do the opposite. * @return string|null If the $return parameter is set to {@see true}, then * the export is returned as a string, otherwise {@see null} is returned. * @removed 8.0 */ #[Deprecated(since: '7.4')] public static function export($name, $return = false) {} /** * Checks if function is disabled * * @link https://php.net/manual/en/reflectionfunction.isdisabled.php * @return bool {@see true} if it's disable, otherwise {@see false} */ #[Deprecated(since: '8.0')] #[Pure] #[TentativeType] public function isDisabled(): bool {} /** * Invokes function * * @link https://www.php.net/manual/en/reflectionfunction.invoke.php * @param mixed ...$args [optional] The passed in argument list. It accepts a * variable number of arguments which are passed to the function much * like {@see call_user_func} is. * @return mixed Returns the result of the invoked function call. */ #[TentativeType] public function invoke(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] ...$args): mixed {} /** * Invokes function args * * @link https://php.net/manual/en/reflectionfunction.invokeargs.php * @param array $args The passed arguments to the function as an array, much * like {@see call_user_func_array} works. * @return mixed the result of the invoked function */ #[TentativeType] public function invokeArgs(array $args): mixed {} /** * Returns a dynamically created closure for the function * * @link https://php.net/manual/en/reflectionfunction.getclosure.php * @return Closure|null Returns {@see Closure} or {@see null} in case of an error. */ #[Pure] #[TentativeType] public function getClosure(): Closure {} #[PhpStormStubsElementAvailable(from: '8.2')] public function isAnonymous(): bool {} } ReflectionExtension class reports information about an extension. * * @link https://php.net/manual/en/class.reflectionextension.php */ class ReflectionExtension implements Reflector { /** * @var string Name of the extension, same as calling the {@see ReflectionExtension::getName()} method */ #[Immutable] #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $name; /** * Constructs a ReflectionExtension * * @link https://php.net/manual/en/reflectionextension.construct.php * @param string $name Name of the extension. * @throws ReflectionException if the extension does not exist. */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name) {} /** * Exports a reflected extension. * The output format of this function is the same as the CLI argument --re [extension]. * * @link https://php.net/manual/en/reflectionextension.export.php * @param string $name The reflection to export. * @param bool $return Setting to {@see true} will return the * export, as opposed to emitting it. Setting to {@see false} (the default) * will do the opposite. * @return string|null If the $return parameter is set to {@see true}, then * the export is returned as a string, otherwise {@see null} is returned. * @removed 8.0 */ #[Deprecated(since: '7.4')] public static function export($name, $return = false) {} /** * To string * * @link https://php.net/manual/en/reflectionextension.tostring.php * @return string the exported extension as a string, in the same way as * the {@see ReflectionExtension::export()}. */ #[TentativeType] public function __toString(): string {} /** * Gets extension name * * @link https://php.net/manual/en/reflectionextension.getname.php * @return string The extensions name. */ #[Pure] #[TentativeType] public function getName(): string {} /** * Gets extension version * * @link https://php.net/manual/en/reflectionextension.getversion.php * @return string|null The version of the extension. */ #[Pure] #[TentativeType] public function getVersion(): ?string {} /** * Gets extension functions * * @link https://php.net/manual/en/reflectionextension.getfunctions.php * @return ReflectionFunction[] An associative array of {@see ReflectionFunction} objects, * for each function defined in the extension with the keys being the function * names. If no function are defined, an empty array is returned. */ #[Pure] #[TentativeType] public function getFunctions(): array {} /** * Gets constants * * @link https://php.net/manual/en/reflectionextension.getconstants.php * @return array An associative array with constant names as keys. */ #[Pure] #[TentativeType] public function getConstants(): array {} /** * Gets extension ini entries * * @link https://php.net/manual/en/reflectionextension.getinientries.php * @return array An associative array with the ini entries as keys, * with their defined values as values. */ #[Pure] #[TentativeType] public function getINIEntries(): array {} /** * Gets classes * * @link https://php.net/manual/en/reflectionextension.getclasses.php * @return ReflectionClass[] An array of {@see ReflectionClass} objects, one * for each class within the extension. If no classes are defined, * an empty array is returned. */ #[Pure] #[TentativeType] public function getClasses(): array {} /** * Gets class names * * @link https://php.net/manual/en/reflectionextension.getclassnames.php * @return string[] An array of class names, as defined in the extension. * If no classes are defined, an empty array is returned. */ #[Pure] #[TentativeType] public function getClassNames(): array {} /** * Gets dependencies * * @link https://php.net/manual/en/reflectionextension.getdependencies.php * @return string[] An associative array with dependencies as keys and * either Required, Optional or Conflicts as the values. */ #[Pure] #[TentativeType] public function getDependencies(): array {} /** * Print extension info * * @link https://php.net/manual/en/reflectionextension.info.php * @return void Print extension info */ #[TentativeType] public function info(): void {} /** * Returns whether this extension is persistent * * @link https://php.net/manual/en/reflectionextension.ispersistent.php * @return bool Returns {@see true} for extensions loaded by extension, {@see false} otherwise. * @since 5.4 */ #[Pure] #[TentativeType] public function isPersistent(): bool {} /** * Returns whether this extension is temporary * * @link https://php.net/manual/en/reflectionextension.istemporary.php * @return bool Returns {@see true} for extensions loaded by {@see dl()}, {@see false} otherwise. * @since 5.4 */ #[Pure] #[TentativeType] public function isTemporary(): bool {} /** * Clones * * @link https://php.net/manual/en/reflectionextension.clone.php * @return void No value is returned, if called a fatal error will occur. */ #[PhpStormStubsElementAvailable(from: "5.4", to: "8.0")] final private function __clone(): void {} /** * Clones * * @link https://php.net/manual/en/reflectionextension.clone.php * @return void No value is returned, if called a fatal error will occur. */ #[PhpStormStubsElementAvailable(from: "8.1")] private function __clone(): void {} } ReflectionClass class reports information about a class. * * @link https://php.net/manual/en/class.reflectionclass.php */ class ReflectionClass implements Reflector { /** * @var class-string Name of the class, same as calling the {@see ReflectionClass::getName()} method */ #[Immutable] #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $name; /** * Indicates class that is abstract because it has some abstract methods. * * @link https://www.php.net/manual/en/class.reflectionclass.php#reflectionclass.constants.is-implicit-abstract */ public const IS_IMPLICIT_ABSTRACT = 16; /** * Indicates class that is abstract because of its definition. * * @link https://www.php.net/manual/en/class.reflectionclass.php#reflectionclass.constants.is-explicit-abstract */ public const IS_EXPLICIT_ABSTRACT = 64; /** * Indicates final class. * * @link https://www.php.net/manual/en/class.reflectionclass.php#reflectionclass.constants.is-final */ public const IS_FINAL = 32; /** * @since 8.2 */ public const IS_READONLY = 65536; /** * Constructs a ReflectionClass * * @link https://php.net/manual/en/reflectionclass.construct.php * @param class-string|T $objectOrClass Either a string containing the name of * the class to reflect, or an object. * @throws ReflectionException if the class does not exist. */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'object|string'], default: '')] $objectOrClass) {} /** * Exports a reflected class * * @link https://php.net/manual/en/reflectionclass.export.php * @param mixed $argument The reflection to export. * @param bool $return Setting to {@see true} will return the export, as * opposed to emitting it. Setting to {@see false} (the default) will do the opposite. * @return string|null If the $return parameter is set to {@see true}, then the * export is returned as a string, otherwise {@see null} is returned. * @removed 8.0 */ #[Deprecated(since: '7.4')] public static function export($argument, $return = false) {} /** * Returns the string representation of the ReflectionClass object. * * @link https://php.net/manual/en/reflectionclass.tostring.php * @return string A string representation of this {@see ReflectionClass} instance. */ #[TentativeType] public function __toString(): string {} /** * Gets class name * * @link https://php.net/manual/en/reflectionclass.getname.php * @return string The class name. */ #[Pure] #[TentativeType] public function getName(): string {} /** * Checks if class is defined internally by an extension, or the core * * @link https://php.net/manual/en/reflectionclass.isinternal.php * @return bool Returns {@see true} on success or {@see false} on failure. */ #[Pure] #[TentativeType] public function isInternal(): bool {} /** * Checks if user defined * * @link https://php.net/manual/en/reflectionclass.isuserdefined.php * @return bool Returns {@see true} on success or {@see false} on failure. */ #[Pure] #[TentativeType] public function isUserDefined(): bool {} /** * Checks if the class is instantiable * * @link https://php.net/manual/en/reflectionclass.isinstantiable.php * @return bool Returns {@see true} on success or {@see false} on failure. */ #[Pure] #[TentativeType] public function isInstantiable(): bool {} /** * Returns whether this class is cloneable * * @link https://php.net/manual/en/reflectionclass.iscloneable.php * @return bool Returns {@see true} if the class is cloneable, {@see false} otherwise. * @since 5.4 */ #[Pure] #[TentativeType] public function isCloneable(): bool {} /** * Gets the filename of the file in which the class has been defined * * @link https://php.net/manual/en/reflectionclass.getfilename.php * @return string|false the filename of the file in which the class has been defined. * If the class is defined in the PHP core or in a PHP extension, {@see false} * is returned. */ #[Pure] #[TentativeType] public function getFileName(): string|false {} /** * Gets starting line number * * @link https://php.net/manual/en/reflectionclass.getstartline.php * @return int The starting line number, as an integer. */ #[Pure] #[TentativeType] public function getStartLine(): int|false {} /** * Gets end line * * @link https://php.net/manual/en/reflectionclass.getendline.php * @return int|false The ending line number of the user defined class, or * {@see false} if unknown. */ #[Pure] #[TentativeType] public function getEndLine(): int|false {} /** * Gets doc comments * * @link https://php.net/manual/en/reflectionclass.getdoccomment.php * @return string|false The doc comment if it exists, otherwise {@see false} */ #[Pure] #[TentativeType] public function getDocComment(): string|false {} /** * Gets the constructor of the class * * @link https://php.net/manual/en/reflectionclass.getconstructor.php * @return ReflectionMethod|null A {@see ReflectionMethod} object reflecting * the class' constructor, or {@see null} if the class has no constructor. */ #[Pure] #[TentativeType] public function getConstructor(): ?ReflectionMethod {} /** * Checks if method is defined * * @link https://php.net/manual/en/reflectionclass.hasmethod.php * @param string $name Name of the method being checked for. * @return bool Returns {@see true} if it has the method, otherwise {@see false} */ #[TentativeType] public function hasMethod(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): bool {} /** * Gets a ReflectionMethod for a class method. * * @link https://php.net/manual/en/reflectionclass.getmethod.php * @param string $name The method name to reflect. * @return ReflectionMethod A {@see ReflectionMethod} * @throws ReflectionException if the method does not exist. */ #[Pure] #[TentativeType] public function getMethod(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): ReflectionMethod {} /** * Gets an array of methods for the class. * * @link https://php.net/manual/en/reflectionclass.getmethods.php * @param int|null $filter Filter the results to include only methods * with certain attributes. Defaults to no filtering. * @return ReflectionMethod[] An array of {@see ReflectionMethod} objects * reflecting each method. */ #[Pure] #[TentativeType] public function getMethods(#[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $filter = null): array {} /** * Checks if property is defined * * @link https://php.net/manual/en/reflectionclass.hasproperty.php * @param string $name Name of the property being checked for. * @return bool Returns {@see true} if it has the property, otherwise {@see false} */ #[TentativeType] public function hasProperty(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): bool {} /** * Gets a ReflectionProperty for a class's property * * @link https://php.net/manual/en/reflectionclass.getproperty.php * @param string $name The property name. * @return ReflectionProperty A {@see ReflectionProperty} * @throws ReflectionException If no property exists by that name. */ #[Pure] #[TentativeType] public function getProperty(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): ReflectionProperty {} /** * Gets properties * * @link https://php.net/manual/en/reflectionclass.getproperties.php * @param int|null $filter The optional filter, for filtering desired * property types. It's configured using the {@see ReflectionProperty} constants, * and defaults to all property types. * @return ReflectionProperty[] */ #[Pure] #[TentativeType] public function getProperties(#[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $filter = null): array {} /** * Gets a ReflectionClassConstant for a class's property * * @link https://php.net/manual/en/reflectionclass.getreflectionconstant.php * @param string $name The class constant name. * @return ReflectionClassConstant|false A {@see ReflectionClassConstant}. * @since 7.1 */ #[Pure] #[TentativeType] public function getReflectionConstant(string $name): ReflectionClassConstant|false {} /** * Gets class constants * * @link https://php.net/manual/en/reflectionclass.getreflectionconstants.php * @param int|null $filter [optional] allows the filtering of constants defined in a class by their visibility. Since 8.0. * @return ReflectionClassConstant[] An array of ReflectionClassConstant objects. * @since 7.1 */ #[Pure] #[TentativeType] public function getReflectionConstants(#[PhpStormStubsElementAvailable(from: '8.0')] ?int $filter = null): array {} /** * Checks if constant is defined * * @link https://php.net/manual/en/reflectionclass.hasconstant.php * @param string $name The name of the constant being checked for. * @return bool Returns {@see true} if the constant is defined, otherwise {@see false} */ #[TentativeType] public function hasConstant(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): bool {} /** * Gets constants * * @link https://php.net/manual/en/reflectionclass.getconstants.php * @param int|null $filter [optional] allows the filtering of constants defined in a class by their visibility. Since 8.0. * @return array An array of constants, where the keys hold the name and * the values the value of the constants. */ #[Pure] #[TentativeType] public function getConstants(#[PhpStormStubsElementAvailable(from: '8.0')] ?int $filter = null): array {} /** * Gets defined constant * * @link https://php.net/manual/en/reflectionclass.getconstant.php * @param string $name Name of the constant. * @return mixed|false Value of the constant with the name name. * Returns {@see false} if the constant was not found in the class. */ #[Pure] #[TentativeType] public function getConstant(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): mixed {} /** * Gets the interfaces * * @link https://php.net/manual/en/reflectionclass.getinterfaces.php * @return ReflectionClass[] An associative array of interfaces, with keys as interface * names and the array values as {@see ReflectionClass} objects. */ #[Pure] #[TentativeType] public function getInterfaces(): array {} /** * Gets the interface names * * @link https://php.net/manual/en/reflectionclass.getinterfacenames.php * @return string[] A numerical array with interface names as the values. */ #[Pure] #[TentativeType] public function getInterfaceNames(): array {} /** * Checks if the class is anonymous * * @link https://php.net/manual/en/reflectionclass.isanonymous.php * @return bool Returns {@see true} on success or {@see false} on failure. * @since 7.0 */ #[Pure] #[TentativeType] public function isAnonymous(): bool {} /** * Checks if the class is an interface * * @link https://php.net/manual/en/reflectionclass.isinterface.php * @return bool Returns {@see true} on success or {@see false} on failure. */ #[Pure] #[TentativeType] public function isInterface(): bool {} /** * Returns an array of traits used by this class * * @link https://php.net/manual/en/reflectionclass.gettraits.php * @return ReflectionClass[] an array with trait names in keys and * instances of trait's {@see ReflectionClass} in values. * @since 5.4 */ #[Pure] #[TentativeType] public function getTraits(): array {} /** * Returns an array of names of traits used by this class * * @link https://php.net/manual/en/reflectionclass.gettraitnames.php * @return string[] An array with trait names in values. * Returns {@see null} in case of an error. * @since 5.4 */ #[Pure] #[TentativeType] public function getTraitNames(): array {} /** * Returns an array of trait aliases * * @link https://php.net/manual/en/reflectionclass.gettraitaliases.php * @return string[] an array with new method names in keys and original * names (in the format "TraitName::original") in values. * Returns {@see null} in case of an error. * @since 5.4 */ #[Pure] #[TentativeType] public function getTraitAliases(): array {} /** * Returns whether this is a trait * * @link https://php.net/manual/en/reflectionclass.istrait.php * @return bool Returns {@see true} if this is a trait, {@see false} otherwise. * Returns {@see null} in case of an error. * @since 5.4 */ #[Pure] #[TentativeType] public function isTrait(): bool {} /** * Checks if class is abstract * * @link https://php.net/manual/en/reflectionclass.isabstract.php * @return bool Returns {@see true} on success or {@see false} on failure. */ #[Pure] #[TentativeType] public function isAbstract(): bool {} /** * Checks if class is final * * @link https://php.net/manual/en/reflectionclass.isfinal.php * @return bool Returns {@see true} on success or {@see false} on failure. */ #[Pure] #[TentativeType] public function isFinal(): bool {} /** * @return bool */ #[Pure] #[PhpStormStubsElementAvailable(from: '8.2')] public function isReadOnly(): bool {} /** * Gets modifiers * * @link https://php.net/manual/en/reflectionclass.getmodifiers.php * @return int bitmask of modifier constants. */ #[Pure] #[TentativeType] public function getModifiers(): int {} /** * Checks class for instance * * @link https://php.net/manual/en/reflectionclass.isinstance.php * @param object $object The object being compared to. * @return bool Returns {@see true} on success or {@see false} on failure. */ #[Pure] #[TentativeType] public function isInstance(#[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $object): bool {} /** * Creates a new class instance from given arguments. * * @link https://php.net/manual/en/reflectionclass.newinstance.php * @param mixed ...$args Accepts a variable number of arguments which are * passed to the class constructor, much like {@see call_user_func} * @return T a new instance of the class. * @throws ReflectionException if the class constructor is not public or if * the class does not have a constructor and the $args parameter contains * one or more parameters. */ public function newInstance(...$args) {} /** * Creates a new class instance without invoking the constructor. * * @link https://php.net/manual/en/reflectionclass.newinstancewithoutconstructor.php * @return T a new instance of the class. * @throws ReflectionException if the class is an internal class that * cannot be instantiated without invoking the constructor. In PHP 5.6.0 * onwards, this exception is limited only to internal classes that are final. * @since 5.4 */ #[TentativeType] public function newInstanceWithoutConstructor(): object {} /** * Creates a new class instance from given arguments. * * @link https://php.net/manual/en/reflectionclass.newinstanceargs.php * @param array $args The parameters to be passed to the class constructor as an array. * @return T|null a new instance of the class. * @throws ReflectionException if the class constructor is not public or if * the class does not have a constructor and the $args parameter contains * one or more parameters. * @since 5.1.3 */ #[TentativeType] public function newInstanceArgs(array $args = []): ?object {} /** * Gets parent class * * @link https://php.net/manual/en/reflectionclass.getparentclass.php * @return ReflectionClass|false A {@see ReflectionClass} or {@see false} * if there's no parent. */ #[Pure] #[TentativeType] public function getParentClass(): ReflectionClass|false {} /** * Checks if a subclass * * @link https://php.net/manual/en/reflectionclass.issubclassof.php * @param string|ReflectionClass $class Either the name of the class as * string or a {@see ReflectionClass} object of the class to check against. * @return bool {@see true} on success or {@see false} on failure. */ #[Pure] #[TentativeType] public function isSubclassOf(#[LanguageLevelTypeAware(['8.0' => 'ReflectionClass|string'], default: '')] $class): bool {} /** * Gets static properties * * @link https://php.net/manual/en/reflectionclass.getstaticproperties.php * @return array|null The static properties, as an array where the keys hold * the name and the values the value of the properties. */ #[Pure] #[TentativeType] #[LanguageLevelTypeAware(['8.3' => 'array'], default: 'array|null')] public function getStaticProperties() {} /** * Gets static property value * * @link https://php.net/manual/en/reflectionclass.getstaticpropertyvalue.php * @param string $name The name of the static property for which to return a value. * @param mixed $default [optional] A default value to return in case the class does * not declare a static property with the given name. If the property does * not exist and this argument is omitted, a {@see ReflectionException} is thrown. * @return mixed The value of the static property. */ #[Pure] #[TentativeType] public function getStaticPropertyValue( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $default ): mixed {} /** * Sets static property value * * @link https://php.net/manual/en/reflectionclass.setstaticpropertyvalue.php * @param string $name Property name. * @param mixed $value New property value. * @return void No value is returned. */ #[TentativeType] public function setStaticPropertyValue( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value ): void {} /** * Gets default properties * * @link https://php.net/manual/en/reflectionclass.getdefaultproperties.php * @return mixed[] An array of default properties, with the key being the name * of the property and the value being the default value of the property * or {@see null} if the property doesn't have a default value. The function * does not distinguish between static and non static properties and does * not take visibility modifiers into account. */ #[Pure] #[TentativeType] public function getDefaultProperties(): array {} /** * An alias of {@see ReflectionClass::isIterable} method. * * @link https://php.net/manual/en/reflectionclass.isiterateable.php * @return bool Returns {@see true} on success or {@see false} on failure. */ #[Pure] #[TentativeType] public function isIterateable(): bool {} /** * Check whether this class is iterable * * @link https://php.net/manual/en/reflectionclass.isiterable.php * @return bool Returns {@see true} on success or {@see false} on failure. * @since 7.2 */ #[Pure] #[TentativeType] public function isIterable(): bool {} /** * Checks whether it implements an interface. * * @link https://php.net/manual/en/reflectionclass.implementsinterface.php * @param string $interface The interface name. * @return bool Returns {@see true} on success or {@see false} on failure. */ #[TentativeType] public function implementsInterface(#[LanguageLevelTypeAware(['8.0' => 'ReflectionClass|string'], default: '')] $interface): bool {} /** * Gets a ReflectionExtension object for the extension which defined the class * * @link https://php.net/manual/en/reflectionclass.getextension.php * @return ReflectionExtension|null A {@see ReflectionExtension} object representing * the extension which defined the class, or {@see null} for user-defined classes. */ #[Pure] #[TentativeType] public function getExtension(): ?ReflectionExtension {} /** * Gets the name of the extension which defined the class * * @link https://php.net/manual/en/reflectionclass.getextensionname.php * @return string|false The name of the extension which defined the class, * or {@see false} for user-defined classes. */ #[Pure] #[TentativeType] public function getExtensionName(): string|false {} /** * Checks if in namespace * * @link https://php.net/manual/en/reflectionclass.innamespace.php * @return bool {@see true} on success or {@see false} on failure. */ #[TentativeType] public function inNamespace(): bool {} /** * Gets namespace name * * @link https://php.net/manual/en/reflectionclass.getnamespacename.php * @return string The namespace name. */ #[Pure] #[TentativeType] public function getNamespaceName(): string {} /** * Gets short name * * @link https://php.net/manual/en/reflectionclass.getshortname.php * @return string The class short name. */ #[Pure] #[TentativeType] public function getShortName(): string {} /** * @template T * * Returns an array of class attributes. * * @param class-string|null $name Name of an attribute class * @param int $flags Сriteria by which the attribute is searched. * @return ReflectionAttribute[] * @since 8.0 */ #[Pure] public function getAttributes(?string $name = null, int $flags = 0): array {} /** * Clones object * * @link https://php.net/manual/en/reflectionclass.clone.php * @return void */ #[PhpStormStubsElementAvailable(from: "5.4", to: "8.0")] final private function __clone(): void {} /** * Clones object * * @link https://php.net/manual/en/reflectionclass.clone.php * @return void */ #[PhpStormStubsElementAvailable(from: "8.1")] private function __clone(): void {} #[PhpStormStubsElementAvailable('8.1')] public function isEnum(): bool {} } Reflector is an interface implemented by all * exportable Reflection classes. * * @link https://php.net/manual/en/class.reflector.php */ interface Reflector extends Stringable { /** * Exports a class. * * @link https://php.net/manual/en/reflector.export.php * @return string|null * @removed 7.4 */ public static function export(); /** * Returns the string representation of any Reflection object. * * Please note that since PHP 8.0 this method is absent in this interface * and inherits from the {@see Stringable} parent. * * @return string */ public function __toString(); } ReflectionMethod class reports * information about a method. * * @link https://php.net/manual/en/class.reflectionmethod.php */ class ReflectionMethod extends ReflectionFunctionAbstract { /** * @var string Name of the method, same as calling the {@see ReflectionMethod::getName()} method */ #[Immutable] public $name; /** * @var string Fully qualified class name where this method was defined */ #[Immutable] #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $class; /** * Indicates that the method is static. */ public const IS_STATIC = 16; /** * Indicates that the method is public. */ public const IS_PUBLIC = 1; /** * Indicates that the method is protected. */ public const IS_PROTECTED = 2; /** * Indicates that the method is private. */ public const IS_PRIVATE = 4; /** * Indicates that the method is abstract. */ public const IS_ABSTRACT = 64; /** * Indicates that the method is final. */ public const IS_FINAL = 32; /** * Constructs a ReflectionMethod * * * $reflection = new ReflectionMethod(new Example(), 'method'); * $reflection = new ReflectionMethod(Example::class, 'method'); * $reflection = new ReflectionMethod('Example::method'); * * * @link https://php.net/manual/en/reflectionmethod.construct.php * @param string|object $objectOrMethod Classname, object * (instance of the class) that contains the method or class name and * method name delimited by ::. * @param string|null $method Name of the method if the first argument is a * classname or an object. * @throws ReflectionException if the class or method does not exist. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'object|string'], default: '')] $objectOrMethod, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $method = null ) {} /** * Export a reflection method. * * @link https://php.net/manual/en/reflectionmethod.export.php * @param string $class The class name. * @param string $name The name of the method. * @param bool $return Setting to {@see true} will return the export, * as opposed to emitting it. Setting to {@see false} (the default) will do the * opposite. * @return string|null If the $return parameter is set to {@see true}, then * the export is returned as a string, otherwise {@see null} is returned. * @removed 8.0 */ #[Deprecated(since: '7.4')] public static function export($class, $name, $return = false) {} /** * Returns the string representation of the ReflectionMethod object. * * @link https://php.net/manual/en/reflectionmethod.tostring.php * @return string A string representation of this {@see ReflectionMethod} instance. */ #[TentativeType] public function __toString(): string {} /** * Checks if method is public * * @link https://php.net/manual/en/reflectionmethod.ispublic.php * @return bool Returns {@see true} if the method is public, otherwise {@see false} */ #[Pure] #[TentativeType] public function isPublic(): bool {} /** * Checks if method is private * * @link https://php.net/manual/en/reflectionmethod.isprivate.php * @return bool Returns {@see true} if the method is private, otherwise {@see false} */ #[Pure] #[TentativeType] public function isPrivate(): bool {} /** * Checks if method is protected * * @link https://php.net/manual/en/reflectionmethod.isprotected.php * @return bool Returns {@see true} if the method is protected, otherwise {@see false} */ #[Pure] #[TentativeType] public function isProtected(): bool {} /** * Checks if method is abstract * * @link https://php.net/manual/en/reflectionmethod.isabstract.php * @return bool Returns {@see true} if the method is abstract, otherwise {@see false} */ #[Pure] #[TentativeType] public function isAbstract(): bool {} /** * Checks if method is final * * @link https://php.net/manual/en/reflectionmethod.isfinal.php * @return bool Returns {@see true} if the method is final, otherwise {@see false} */ #[Pure] #[TentativeType] public function isFinal(): bool {} /** * Checks if method is static * * @link https://php.net/manual/en/reflectionmethod.isstatic.php * @return bool Returns {@see true} if the method is static, otherwise {@see false} */ #[Pure] #[TentativeType] public function isStatic(): bool {} /** * Checks if method is a constructor * * @link https://php.net/manual/en/reflectionmethod.isconstructor.php * @return bool Returns {@see true} if the method is a constructor, otherwise {@see false} */ #[Pure] #[TentativeType] public function isConstructor(): bool {} /** * Checks if method is a destructor * * @link https://php.net/manual/en/reflectionmethod.isdestructor.php * @return bool Returns {@see true} if the method is a destructor, otherwise {@see false} */ #[Pure] #[TentativeType] public function isDestructor(): bool {} /** * Returns a dynamically created closure for the method * * @link https://php.net/manual/en/reflectionmethod.getclosure.php * @param object|null $object Forbidden for static methods, required for other methods or nothing. * @return Closure Returns the newly created {@see Closure}. * @throws ValueError if object is null but the method is non-static. * @throws ReflectionException if object is not an instance of the class this method was declared in. * @since 5.4 */ #[Pure] #[TentativeType] public function getClosure( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.3')] $object, #[PhpStormStubsElementAvailable(from: '7.4')] #[LanguageLevelTypeAware(['8.0' => 'object|null'], default: '')] $object = null ): Closure {} /** * Gets the method modifiers * * @link https://php.net/manual/en/reflectionmethod.getmodifiers.php * @return int A numeric representation of the modifiers. The modifiers are * listed below. The actual meanings of these modifiers are described in the * predefined constants. * * ReflectionMethod modifiers: * * - {@see ReflectionMethod::IS_STATIC} - Indicates that the method is static. * - {@see ReflectionMethod::IS_PUBLIC} - Indicates that the method is public. * - {@see ReflectionMethod::IS_PROTECTED} - Indicates that the method is protected. * - {@see ReflectionMethod::IS_PRIVATE} - Indicates that the method is private. * - {@see ReflectionMethod::IS_ABSTRACT} - Indicates that the method is abstract. * - {@see ReflectionMethod::IS_FINAL} - Indicates that the method is final. */ #[Pure] #[TentativeType] public function getModifiers(): int {} /** * Invokes a reflected method. * * @link https://php.net/manual/en/reflectionmethod.invoke.php * @param object|null $object The object to invoke the method on. For static * methods, pass {@see null} to this parameter. * @param mixed ...$args Zero or more parameters to be passed to the * method. It accepts a variable number of parameters which are passed to * the method. * @return mixed Returns the method result. * @throws ReflectionException if the object parameter does not contain an * instance of the class that this method was declared in or the method * invocation failed. */ public function invoke($object, ...$args) {} /** * Invokes the reflected method and pass its arguments as array. * * @link https://php.net/manual/en/reflectionmethod.invokeargs.php * @param object|null $object The object to invoke the method on. In case * of static methods, you can pass {@see null} to this parameter. * @param array $args The parameters to be passed to the function, as an {@see array}. * @return mixed the method result. * @throws ReflectionException if the object parameter does not contain an * instance of the class that this method was declared in or the method * invocation failed. */ #[TentativeType] public function invokeArgs(#[LanguageLevelTypeAware(['8.0' => 'object|null'], default: '')] $object, array $args): mixed {} /** * Gets declaring class for the reflected method. * * @link https://php.net/manual/en/reflectionmethod.getdeclaringclass.php * @return ReflectionClass A {@see ReflectionClass} object of the class that the * reflected method is part of. */ #[Pure] #[TentativeType] public function getDeclaringClass(): ReflectionClass {} /** * Gets the method prototype (if there is one). * * @link https://php.net/manual/en/reflectionmethod.getprototype.php * @return ReflectionMethod A {@see ReflectionMethod} instance of the method prototype. * @throws ReflectionException if the method does not have a prototype */ #[Pure] #[TentativeType] public function getPrototype(): ReflectionMethod {} /** * Set method accessibility * * @link https://php.net/manual/en/reflectionmethod.setaccessible.php * @param bool $accessible {@see true} to allow accessibility, or {@see false} * @return void No value is returned. */ #[PhpStormStubsElementAvailable(from: "5.3", to: "8.0")] #[TentativeType] public function setAccessible(#[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $accessible): void {} /** * Set method accessibility * This method is no-op starting from PHP 8.1 * * @link https://php.net/manual/en/reflectionmethod.setaccessible.php * @param bool $accessible {@see true} to allow accessibility, or {@see false} * @return void No value is returned. */ #[Pure] #[PhpStormStubsElementAvailable(from: "8.1")] #[TentativeType] public function setAccessible(bool $accessible): void {} #[PhpStormStubsElementAvailable(from: '8.2')] public function hasPrototype(): bool {} /** * @since 8.3 */ public static function createFromMethodName(string $method): static {} } ReflectionObject class reports * information about an object. * * @link https://php.net/manual/en/class.reflectionobject.php */ class ReflectionObject extends ReflectionClass { /** * Constructs a ReflectionObject * * @link https://php.net/manual/en/reflectionobject.construct.php * @param object $object An object instance. */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'object'], default: '')] $object) {} /** * Export * * @link https://php.net/manual/en/reflectionobject.export.php * @param string $argument The reflection to export. * @param bool $return Setting to {@see true} will return the export, * as opposed to emitting it. Setting to {@see false} (the default) will do * the opposite. * @return string|null If the $return parameter is set to {@see true}, then * the export is returned as a string, otherwise {@see null} is returned. * @removed 8.0 */ #[Deprecated(since: '7.4')] public static function export($argument, $return = false) {} } ReflectionParameter class retrieves * information about function's or method's parameters. * * @link https://php.net/manual/en/class.reflectionparameter.php */ class ReflectionParameter implements Reflector { /** * @var string Name of the parameter, same as calling the {@see ReflectionParameter::getName()} method */ #[Immutable] #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $name; /** * Construct * * @link https://php.net/manual/en/reflectionparameter.construct.php * @param callable $function The function to reflect parameters from. * @param string|int $param Either an integer specifying the position * of the parameter (starting with zero), or a the parameter name as string. * @throws ReflectionException if the function or parameter does not exist. */ public function __construct($function, #[LanguageLevelTypeAware(['8.0' => 'string|int'], default: '')] $param) {} /** * Exports * * @link https://php.net/manual/en/reflectionparameter.export.php * @param string $function The function name. * @param string $parameter The parameter name. * @param bool $return Setting to {@see true} will return the export, * as opposed to emitting it. Setting to {@see false} (the default) will do the * opposite. * @return string|null The exported reflection. * @removed 8.0 */ #[Deprecated(since: '7.4')] public static function export($function, $parameter, $return = false) {} /** * Returns the string representation of the ReflectionParameter object. * * @link https://php.net/manual/en/reflectionparameter.tostring.php * @return string */ #[TentativeType] public function __toString(): string {} /** * Gets parameter name * * @link https://php.net/manual/en/reflectionparameter.getname.php * @return string The name of the reflected parameter. */ #[Pure] #[TentativeType] public function getName(): string {} /** * Checks if passed by reference * * @link https://php.net/manual/en/reflectionparameter.ispassedbyreference.php * @return bool {@see true} if the parameter is passed in by reference, otherwise {@see false} */ #[Pure] #[TentativeType] public function isPassedByReference(): bool {} /** * Returns whether this parameter can be passed by value * * @link https://php.net/manual/en/reflectionparameter.canbepassedbyvalue.php * @return bool|null {@see true} if the parameter can be passed by value, {@see false} otherwise. * Returns {@see null} in case of an error. * @since 5.4 */ #[TentativeType] public function canBePassedByValue(): bool {} /** * Gets declaring function * * @link https://php.net/manual/en/reflectionparameter.getdeclaringfunction.php * @return ReflectionFunctionAbstract A {@see ReflectionFunctionAbstract} object. * @since 5.2.3 */ #[Pure] #[TentativeType] public function getDeclaringFunction(): ReflectionFunctionAbstract {} /** * Gets declaring class * * @link https://php.net/manual/en/reflectionparameter.getdeclaringclass.php * @return ReflectionClass|null A {@see ReflectionClass} object or {@see null} if * called on function. */ #[Pure] #[TentativeType] public function getDeclaringClass(): ?ReflectionClass {} /** * Gets the class type hinted for the parameter as a ReflectionClass object. * * @link https://php.net/manual/en/reflectionparameter.getclass.php * @return ReflectionClass|null A {@see ReflectionClass} object. * @see ReflectionParameter::getType() */ #[Deprecated(reason: "Use ReflectionParameter::getType() and the ReflectionType APIs should be used instead.", since: "8.0")] #[Pure] #[TentativeType] public function getClass(): ?ReflectionClass {} /** * Checks if the parameter has a type associated with it. * * @link https://php.net/manual/en/reflectionparameter.hastype.php * @return bool {@see true} if a type is specified, {@see false} otherwise. * @since 7.0 */ #[TentativeType] public function hasType(): bool {} /** * Gets a parameter's type * * @link https://php.net/manual/en/reflectionparameter.gettype.php * @return ReflectionType|null Returns a {@see ReflectionType} object if a * parameter type is specified, {@see null} otherwise. * @since 7.0 */ #[Pure] #[LanguageLevelTypeAware( [ '7.1' => 'ReflectionNamedType|null', '8.0' => 'ReflectionNamedType|ReflectionUnionType|null', '8.1' => 'ReflectionNamedType|ReflectionUnionType|ReflectionIntersectionType|null' ], default: 'ReflectionType|null' )] #[TentativeType] public function getType(): ?ReflectionType {} /** * Checks if parameter expects an array * * @link https://php.net/manual/en/reflectionparameter.isarray.php * @return bool {@see true} if an array is expected, {@see false} otherwise. * @see ReflectionParameter::getType() */ #[Deprecated(reason: "Use ReflectionParameter::getType() and the ReflectionType APIs should be used instead.", since: "8.0")] #[Pure] #[TentativeType] public function isArray(): bool {} /** * Returns whether parameter MUST be callable * * @link https://php.net/manual/en/reflectionparameter.iscallable.php * @return bool|null Returns {@see true} if the parameter is callable, {@see false} * if it is not or {@see null} on failure. * @since 5.4 * @see ReflectionParameter::getType() */ #[Deprecated(reason: "Use ReflectionParameter::getType() and the ReflectionType APIs should be used instead.", since: "8.0")] #[Pure] #[TentativeType] public function isCallable(): bool {} /** * Checks if null is allowed * * @link https://php.net/manual/en/reflectionparameter.allowsnull.php * @return bool Returns {@see true} if {@see null} is allowed, * otherwise {@see false} */ #[TentativeType] public function allowsNull(): bool {} /** * Gets parameter position * * @link https://php.net/manual/en/reflectionparameter.getposition.php * @return int The position of the parameter, left to right, starting at position #0. * @since 5.2.3 */ #[Pure] #[TentativeType] public function getPosition(): int {} /** * Checks if optional * * @link https://php.net/manual/en/reflectionparameter.isoptional.php * @return bool Returns {@see true} if the parameter is optional, otherwise {@see false} * @since 5.0.3 */ #[Pure] #[TentativeType] public function isOptional(): bool {} /** * Checks if a default value is available * * @link https://php.net/manual/en/reflectionparameter.isdefaultvalueavailable.php * @return bool Returns {@see true} if a default value is available, otherwise {@see false} * @since 5.0.3 */ #[Pure] #[TentativeType] public function isDefaultValueAvailable(): bool {} /** * Gets default parameter value * * @link https://php.net/manual/en/reflectionparameter.getdefaultvalue.php * @return mixed The parameters default value. * @throws ReflectionException if the parameter is not optional * @since 5.0.3 */ #[Pure] #[TentativeType] public function getDefaultValue(): mixed {} /** * Returns whether the default value of this parameter is constant * * @link https://php.net/manual/en/reflectionparameter.isdefaultvalueconstant.php * @return bool Returns {@see true} if the default value is constant, and {@see false} otherwise. * @since 5.4.6 */ #[Pure] #[TentativeType] public function isDefaultValueConstant(): bool {} /** * Returns the default value's constant name if default value is constant or null * * @link https://php.net/manual/en/reflectionparameter.getdefaultvalueconstantname.php * @return string|null Returns string on success or {@see null} on failure. * @throws ReflectionException if the parameter is not optional * @since 5.4.6 */ #[Pure] #[TentativeType] public function getDefaultValueConstantName(): ?string {} /** * Returns whether this function is variadic * * @link https://php.net/manual/en/reflectionparameter.isvariadic.php * @return bool Returns {@see true} if the function is variadic, otherwise {@see false} * @since 5.6 */ #[Pure] #[TentativeType] public function isVariadic(): bool {} /** * Returns information about whether the parameter is a promoted. * * @return bool Returns {@see true} if the parameter promoted or {@see false} instead * @since 8.0 */ #[Pure] public function isPromoted(): bool {} /** * @template T * * Returns an array of parameter attributes. * * @param class-string|null $name Name of an attribute class * @param int $flags Сriteria by which the attribute is searched. * @return ReflectionAttribute[] * @since 8.0 */ #[Pure] public function getAttributes(?string $name = null, int $flags = 0): array {} /** * Clone * * @link https://php.net/manual/en/reflectionparameter.clone.php * @return void */ #[PhpStormStubsElementAvailable(from: "5.4", to: "8.0")] final private function __clone(): void {} /** * Clone * * @link https://php.net/manual/en/reflectionparameter.clone.php * @return void */ #[PhpStormStubsElementAvailable(from: "8.1")] private function __clone(): void {} } ReflectionFunction, read its * description for details. * * @link https://php.net/manual/en/class.reflectionfunctionabstract.php */ abstract class ReflectionFunctionAbstract implements Reflector { /** * @var string Name of the function, same as calling the {@see ReflectionFunctionAbstract::getName()} method */ #[Immutable] #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $name; /** * Clones function * * @link https://php.net/manual/en/reflectionfunctionabstract.clone.php * @return void */ #[PhpStormStubsElementAvailable(from: "5.4", to: "8.0")] final private function __clone(): void {} /** * Clones function * * @link https://php.net/manual/en/reflectionfunctionabstract.clone.php * @return void */ #[PhpStormStubsElementAvailable(from: "8.1")] private function __clone(): void {} /** * Checks if function in namespace * * @link https://php.net/manual/en/reflectionfunctionabstract.innamespace.php * @return bool {@see true} if it's in a namespace, otherwise {@see false} */ #[TentativeType] public function inNamespace(): bool {} /** * Checks if closure * * @link https://php.net/manual/en/reflectionfunctionabstract.isclosure.php * @return bool {@see true} if it's a closure, otherwise {@see false} */ #[Pure] #[TentativeType] public function isClosure(): bool {} /** * Checks if deprecated * * @link https://php.net/manual/en/reflectionfunctionabstract.isdeprecated.php * @return bool {@see true} if it's deprecated, otherwise {@see false} */ #[Pure] #[TentativeType] public function isDeprecated(): bool {} /** * Checks if is internal * * @link https://php.net/manual/en/reflectionfunctionabstract.isinternal.php * @return bool {@see true} if it's internal, otherwise {@see false} */ #[Pure] #[TentativeType] public function isInternal(): bool {} /** * Checks if user defined * * @link https://php.net/manual/en/reflectionfunctionabstract.isuserdefined.php * @return bool {@see true} if it's user-defined, otherwise {@see false} */ #[Pure] #[TentativeType] public function isUserDefined(): bool {} /** * Returns whether this function is a generator * * @link https://php.net/manual/en/reflectionfunctionabstract.isgenerator.php * @return bool {@see true} if the function is generator, otherwise {@see false} * @since 5.5 */ #[Pure] #[TentativeType] public function isGenerator(): bool {} /** * Returns whether this function is variadic * * @link https://php.net/manual/en/reflectionfunctionabstract.isvariadic.php * @return bool {@see true} if the function is variadic, otherwise {@see false} * @since 5.6 */ #[Pure] #[TentativeType] public function isVariadic(): bool {} /** * Returns this pointer bound to closure * * @link https://php.net/manual/en/reflectionfunctionabstract.getclosurethis.php * @return object|null Returns $this pointer or {@see null} in case of an error. */ #[Pure] #[TentativeType] public function getClosureThis(): ?object {} /** * Returns the scope associated to the closure * * @link https://php.net/manual/en/reflectionfunctionabstract.getclosurescopeclass.php * @return ReflectionClass|null Returns the class on success or {@see null} * on failure. * @since 5.4 */ #[Pure] #[TentativeType] public function getClosureScopeClass(): ?ReflectionClass {} /** * @return ReflectionClass|null Returns the class on success or {@see null} * on failure. * @since 8.0 */ #[Pure] #[TentativeType] public function getClosureCalledClass(): ?ReflectionClass {} /** * Gets doc comment * * @link https://php.net/manual/en/reflectionfunctionabstract.getdoccomment.php * @return string|false The doc comment if it exists, otherwise {@see false} */ #[Pure] #[TentativeType] public function getDocComment(): string|false {} /** * Gets end line number * * @link https://php.net/manual/en/reflectionfunctionabstract.getendline.php * @return int|false The ending line number of the user defined function, * or {@see false} if unknown. */ #[Pure] #[TentativeType] public function getEndLine(): int|false {} /** * Gets extension info * * @link https://php.net/manual/en/reflectionfunctionabstract.getextension.php * @return ReflectionExtension|null The extension information, as a * {@see ReflectionExtension} object or {@see null} instead. */ #[Pure] #[TentativeType] public function getExtension(): ?ReflectionExtension {} /** * Gets extension name * * @link https://php.net/manual/en/reflectionfunctionabstract.getextensionname.php * @return string|false The extension's name or {@see false} instead. */ #[Pure] #[TentativeType] public function getExtensionName(): string|false {} /** * Gets file name * * @link https://php.net/manual/en/reflectionfunctionabstract.getfilename.php * @return string|false The file name or {@see false} in case of error. */ #[Pure] #[TentativeType] public function getFileName(): string|false {} /** * Gets function name * * @link https://php.net/manual/en/reflectionfunctionabstract.getname.php * @return string The name of the function. */ #[Pure] #[TentativeType] public function getName(): string {} /** * Gets namespace name * * @link https://php.net/manual/en/reflectionfunctionabstract.getnamespacename.php * @return string The namespace name. */ #[Pure] #[TentativeType] public function getNamespaceName(): string {} /** * Gets number of parameters * * @link https://php.net/manual/en/reflectionfunctionabstract.getnumberofparameters.php * @return int The number of parameters. * @since 5.0.3 */ #[Pure] #[TentativeType] public function getNumberOfParameters(): int {} /** * Gets number of required parameters * * @link https://php.net/manual/en/reflectionfunctionabstract.getnumberofrequiredparameters.php * @return int The number of required parameters. * @since 5.0.3 */ #[Pure] #[TentativeType] public function getNumberOfRequiredParameters(): int {} /** * Gets parameters * * @link https://php.net/manual/en/reflectionfunctionabstract.getparameters.php * @return ReflectionParameter[] The parameters, as a ReflectionParameter objects. */ #[Pure] #[TentativeType] public function getParameters(): array {} /** * Gets the specified return type of a function * * @link https://php.net/manual/en/reflectionfunctionabstract.getreturntype.php * @return ReflectionType|null Returns a {@see ReflectionType} object if a * return type is specified, {@see null} otherwise. * @since 7.0 */ #[Pure] #[LanguageLevelTypeAware( [ '7.1' => 'ReflectionNamedType|null', '8.0' => 'ReflectionNamedType|ReflectionUnionType|null', '8.1' => 'ReflectionNamedType|ReflectionUnionType|ReflectionIntersectionType|null' ], default: 'ReflectionType|null' )] #[TentativeType] public function getReturnType(): ?ReflectionType {} /** * Gets function short name * * @link https://php.net/manual/en/reflectionfunctionabstract.getshortname.php * @return string The short name of the function. */ #[Pure] #[TentativeType] public function getShortName(): string {} /** * Gets starting line number * * @link https://php.net/manual/en/reflectionfunctionabstract.getstartline.php * @return int|false The starting line number or {@see false} if unknown. */ #[Pure] #[TentativeType] public function getStartLine(): int|false {} /** * Gets static variables * * @link https://php.net/manual/en/reflectionfunctionabstract.getstaticvariables.php * @return array An array of static variables. */ #[Pure] #[TentativeType] public function getStaticVariables(): array {} /** * Checks if returns reference * * @link https://php.net/manual/en/reflectionfunctionabstract.returnsreference.php * @return bool {@see true} if it returns a reference, otherwise {@see false} */ #[TentativeType] public function returnsReference(): bool {} /** * Checks if the function has a specified return type * * @link https://php.net/manual/en/reflectionfunctionabstract.hasreturntype.php * @return bool Returns {@see true} if the function is a specified return * type, otherwise {@see false}. * @since 7.0 */ #[TentativeType] public function hasReturnType(): bool {} /** * @template T * * Returns an array of function attributes. * * @param class-string|null $name Name of an attribute class * @param int $flags Сriteria by which the attribute is searched. * @return ReflectionAttribute[] * @since 8.0 */ #[Pure] public function getAttributes(?string $name = null, int $flags = 0): array {} #[PhpStormStubsElementAvailable('8.1')] #[Pure] public function getClosureUsedVariables(): array {} #[PhpStormStubsElementAvailable('8.1')] #[Pure] public function hasTentativeReturnType(): bool {} #[PhpStormStubsElementAvailable('8.1')] #[Pure] public function getTentativeReturnType(): ?ReflectionType {} #[PhpStormStubsElementAvailable('8.1')] #[Pure] #[TentativeType] public function isStatic(): bool {} public function __toString() {} } 'string'], default: '')] public $name; /** * Constructs a ReflectionZendExtension object * * @link https://php.net/manual/en/reflectionzendextension.construct.php * @param string $name * @throws ReflectionException if the extension does not exist. * @since 5.4 */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name) {} /** * Exports a reflected zend extension. * * @link https://php.net/manual/en/reflectionzendextension.export.php * @param string $name The reflection to export. * @param bool $return Setting to {@see true} will return the * export, as opposed to emitting it. Setting to {@see false} (the default) * will do the opposite. * @return string|null If the $return parameter is set to {@see true}, then * the export is returned as a string, otherwise {@see null} is returned. */ public static function export($name, $return = false) {} /** * To string handler * * @link https://php.net/manual/en/reflectionzendextension.tostring.php * @return string * @since 5.4 */ #[TentativeType] public function __toString(): string {} /** * Gets name * * @link https://php.net/manual/en/reflectionzendextension.getname.php * @return string * @since 5.4 */ #[Pure] #[TentativeType] public function getName(): string {} /** * Gets version * * @link https://php.net/manual/en/reflectionzendextension.getversion.php * @return string * @since 5.4 */ #[Pure] #[TentativeType] public function getVersion(): string {} /** * Gets author * * @link https://php.net/manual/en/reflectionzendextension.getauthor.php * @return string * @since 5.4 */ #[Pure] #[TentativeType] public function getAuthor(): string {} /** * Gets URL * * @link https://php.net/manual/en/reflectionzendextension.geturl.php * @return string * @since 5.4 */ #[Pure] #[TentativeType] public function getURL(): string {} /** * Gets copyright * * @link https://php.net/manual/en/reflectionzendextension.getcopyright.php * @return string * @since 5.4 */ #[Pure] #[TentativeType] public function getCopyright(): string {} /** * Clone handler * * @link https://php.net/manual/en/reflectionzendextension.clone.php * @return void * @since 5.4 */ #[PhpStormStubsElementAvailable(from: "5.4", to: "8.0")] final private function __clone(): void {} /** * Clone handler * * @link https://php.net/manual/en/reflectionzendextension.clone.php * @return void * @since 5.4 */ #[PhpStormStubsElementAvailable(from: "8.1")] private function __clone(): void {} } 'string|int'], default: '')] $key ): ?ReflectionReference {} /** * Returns unique identifier for the reference. The return value format is unspecified * * @link https://php.net/manual/en/reflectionreference.getid.php * @return int|string Returns an integer or string of unspecified format. */ #[Pure] public function getId(): string {} /** * ReflectionReference cannot be cloned * * @return void */ private function __clone(): void {} } 'null|ReflectionNamedType'], default: 'null|ReflectionType')] public function getBackingType() {} } ReflectionProperty class reports information about a classes * properties. * * @link https://php.net/manual/en/class.reflectionproperty.php */ class ReflectionProperty implements Reflector { /** * @since 8.4 */ public const IS_ABSTRACT = 64; /** * @var string Name of the property, same as calling the {@see ReflectionProperty::getName()} method */ #[Immutable] #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $name; /** * @var string Fully qualified class name where this property was defined */ #[Immutable] #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $class; /** * Indicates that the property is static. * * @link https://www.php.net/manual/en/class.reflectionproperty.php#reflectionproperty.constants.is-static */ public const IS_STATIC = 16; /** * Indicates that the property is public. * * @link https://www.php.net/manual/en/class.reflectionproperty.php#reflectionproperty.constants.is-public */ public const IS_PUBLIC = 1; /** * Indicates that the property is protected. * * @link https://www.php.net/manual/en/class.reflectionproperty.php#reflectionproperty.constants.is-protected */ public const IS_PROTECTED = 2; /** * Indicates that the property is private. * * @link https://www.php.net/manual/en/class.reflectionproperty.php#reflectionproperty.constants.is-private */ public const IS_PRIVATE = 4; /** * @since 8.1 */ public const IS_READONLY = 128; /** * @since 8.4 */ public const IS_PROTECTED_SET = 2048; /** * @since 8.4 */ public const IS_PRIVATE_SET = 4096; /** * Construct a ReflectionProperty object * * @link https://php.net/manual/en/reflectionproperty.construct.php * @param string|object $class The class name, that contains the property. * @param string $property The name of the property being reflected. * @throws ReflectionException if the class or property does not exist. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'object|string'], default: '')] $class, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $property ) {} /** * Export * * @link https://php.net/manual/en/reflectionproperty.export.php * @param mixed $class The reflection to export. * @param string $name The property name. * @param bool $return Setting to {@see true} will return the export, as * opposed to emitting it. Setting to {@see false} (the default) will do the * opposite. * @return string|null * @removed 8.0 */ #[Deprecated(since: '7.4')] public static function export($class, $name, $return = false) {} /** * To string * * @link https://php.net/manual/en/reflectionproperty.tostring.php * @return string */ #[TentativeType] public function __toString(): string {} /** * Gets property name * * @link https://php.net/manual/en/reflectionproperty.getname.php * @return string The name of the reflected property. */ #[Pure] #[TentativeType] public function getName(): string {} /** * Gets value * * @link https://php.net/manual/en/reflectionproperty.getvalue.php * @param object|null $object If the property is non-static an object must be * provided to fetch the property from. If you want to fetch the default * property without providing an object use {@see ReflectionClass::getDefaultProperties} * instead. * @return mixed The current value of the property. */ #[Pure] #[TentativeType] public function getValue(#[LanguageLevelTypeAware(['8.0' => 'object|null'], default: '')] $object = null): mixed {} /** * Set property value * * @link https://php.net/manual/en/reflectionproperty.setvalue.php * @param mixed $objectOrValue If the property is non-static an object must * be provided to change the property on. If the property is static this * parameter is left out and only $value needs to be provided. * @param mixed $value [optional] The new value. * @return void No value is returned. */ #[TentativeType] public function setValue( #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $objectOrValue, #[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value ): void {} /** * Checks if property is public * * @link https://php.net/manual/en/reflectionproperty.ispublic.php * @return bool Return {@see true} if the property is public, {@see false} otherwise. */ #[Pure] #[TentativeType] public function isPublic(): bool {} /** * Checks if property is private * * @link https://php.net/manual/en/reflectionproperty.isprivate.php * @return bool Return {@see true} if the property is private, {@see false} otherwise. */ #[Pure] #[TentativeType] public function isPrivate(): bool {} /** * Checks if property is protected * * @link https://php.net/manual/en/reflectionproperty.isprotected.php * @return bool Returns {@see true} if the property is protected, {@see false} otherwise. */ #[Pure] #[TentativeType] public function isProtected(): bool {} /** * Checks if property is static * * @link https://php.net/manual/en/reflectionproperty.isstatic.php * @return bool Returns {@see true} if the property is static, {@see false} otherwise. */ #[Pure] #[TentativeType] public function isStatic(): bool {} /** * Checks if default value * * @link https://php.net/manual/en/reflectionproperty.isdefault.php * @return bool Returns {@see true} if the property was declared at * compile-time, or {@see false} if it was created at run-time. */ #[Pure] #[TentativeType] public function isDefault(): bool {} /** * Gets modifiers * * @link https://php.net/manual/en/reflectionproperty.getmodifiers.php * @return int A numeric representation of the modifiers. */ #[Pure] #[TentativeType] public function getModifiers(): int {} /** * Gets declaring class * * @link https://php.net/manual/en/reflectionproperty.getdeclaringclass.php * @return ReflectionClass A {@see ReflectionClass} object. */ #[Pure] #[TentativeType] public function getDeclaringClass(): ReflectionClass {} /** * Gets doc comment * * @link https://php.net/manual/en/reflectionproperty.getdoccomment.php * @return string|false The doc comment if it exists, otherwise {@see false} */ #[Pure] #[TentativeType] public function getDocComment(): string|false {} /** * Set property accessibility * * @link https://php.net/manual/en/reflectionproperty.setaccessible.php * @param bool $accessible A boolean {@see true} to allow accessibility, or {@see false} * @return void No value is returned. */ #[PhpStormStubsElementAvailable(to: "8.0")] #[TentativeType] public function setAccessible(#[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $accessible): void {} /** * Set property accessibility * This method is no-op starting from PHP 8.1 * * @link https://php.net/manual/en/reflectionproperty.setaccessible.php * @param bool $accessible A boolean {@see true} to allow accessibility, or {@see false} * @return void No value is returned. */ #[Pure] #[PhpStormStubsElementAvailable(from: "8.1")] #[TentativeType] public function setAccessible(bool $accessible): void {} /** * Gets property type * * @link https://php.net/manual/en/reflectionproperty.gettype.php * @return ReflectionType|null Returns a {@see ReflectionType} if the * property has a type, and {@see null} otherwise. * @since 7.4 */ #[Pure] #[LanguageLevelTypeAware( [ '8.0' => 'ReflectionNamedType|ReflectionUnionType|null', '8.1' => 'ReflectionNamedType|ReflectionUnionType|ReflectionIntersectionType|null' ], default: 'ReflectionNamedType|null' )] #[TentativeType] public function getType(): ?ReflectionType {} /** * Checks if property has type * * @link https://php.net/manual/en/reflectionproperty.hastype.php * @return bool Returns {@see true} if a type is specified, {@see false} otherwise. * @since 7.4 */ #[TentativeType] public function hasType(): bool {} /** * Checks if property is initialized * * @link https://php.net/manual/en/reflectionproperty.isinitialized.php * @param object|null $object If the property is non-static an object must be provided to fetch the property from. * @return bool Returns {@see false} for typed properties prior to initialization, and for properties that have * been explicitly {@see unset()}. For all other properties {@see true} will be returned. * @since 7.4 */ #[Pure] #[TentativeType] public function isInitialized(?object $object = null): bool {} /** * Returns information about whether the property was promoted. * * @return bool Returns {@see true} if the property was promoted or {@see false} instead. * @since 8.0 */ #[Pure] public function isPromoted(): bool {} /** * Clone * * @link https://php.net/manual/en/reflectionproperty.clone.php * @return void */ #[PhpStormStubsElementAvailable(from: "5.4", to: "8.0")] final private function __clone(): void {} /** * Clone * * @link https://php.net/manual/en/reflectionproperty.clone.php * @return void */ #[PhpStormStubsElementAvailable(from: "8.1")] private function __clone(): void {} /** * @return bool * @since 8.0 */ public function hasDefaultValue(): bool {} /** * @return mixed * @since 8.0 */ #[Pure] #[TentativeType] public function getDefaultValue(): mixed {} /** * @template T * * Returns an array of property attributes. * * @param class-string|null $name Name of an attribute class * @param int $flags Сriteria by which the attribute is searched. * @return ReflectionAttribute[] * @since 8.0 */ #[Pure] public function getAttributes(?string $name = null, int $flags = 0): array {} /** * @return bool * @since 8.1 */ public function isReadOnly(): bool {} /** * @since 8.4 */ public function getRawValue(object $object): mixed {} /** * @since 8.4 */ public function setRawValue(object $object, mixed $value): void {} /** * @since 8.4 */ public function isAbstract(): bool {} /** * @since 8.4 */ public function isVirtual(): bool {} /** * @since 8.4 */ public function getSettableType(): ?ReflectionType {} /** * @since 8.4 */ public function getHooks(): array {} /** * @since 8.4 */ public function getHook(PropertyHookType $type): ?ReflectionMethod {} /** * @since 8.4 */ public function isPrivateSet(): bool {} /** * @since 8.4 */ public function isProtectedSet(): bool {} } 'int'], default: '')] $modifiers): array {} /** * Exports * * @link https://php.net/manual/en/reflection.export.php * @param Reflector $reflector The reflection to export. * @param bool $return Setting to {@see true} will return the export, as * opposed to emitting it. Setting to {@see false} (the default) will do the opposite. * @return string|null If the return parameter is set to {@see true}, then the * export is returned as a string, otherwise {@see null} is returned. * @removed 8.0 */ #[Deprecated(since: '7.4')] public static function export(Reflector $reflector, $return = false) {} } options can be any of the following the following flags. * * Available options: * * {@see DEBUG_BACKTRACE_PROVIDE_OBJECT} - Default * * {@see DEBUG_BACKTRACE_IGNORE_ARGS} - Don't include the argument * information for functions in the stack trace. * * @return array Returns the trace of the currently executing generator. * @since 7.0 */ #[Pure] #[TentativeType] public function getTrace(int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT): array {} /** * Gets the function name of the generator * * @link https://php.net/manual/en/reflectiongenerator.getfunction.php * @return ReflectionFunctionAbstract Returns a {@see ReflectionFunctionAbstract} * class. This will be {@see ReflectionFunction} for functions, * or {@see ReflectionMethod} for methods. * @since 7.0 */ #[Pure] #[TentativeType] public function getFunction(): ReflectionFunctionAbstract {} /** * Gets the function name of the generator * * @link https://php.net/manual/en/reflectiongenerator.getthis.php * @return object|null Returns the $this value, or {@see null} if the * generator was not created in a class context. * @since 7.0 */ #[Pure] #[TentativeType] public function getThis(): ?object {} /** * Gets the executing Generator object * * @link https://php.net/manual/en/reflectiongenerator.construct.php * @return Generator Returns the currently executing Generator object. * @since 7.0 */ #[Pure] #[TentativeType] public function getExecutingGenerator(): Generator {} /** * @since 8.4 */ public function isClosed(): bool {} } 'string'], default: '')] public $name; /** * @var string Fully qualified class name where this constant was defined */ #[Immutable] #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $class; /** * @var bool * @since 8.1 */ #[Immutable] public bool $isFinal; /** * Indicates that the constant is public. * * @since 8.0 */ public const IS_PUBLIC = 1; /** * Indicates that the constant is protected. * * @since 8.0 */ public const IS_PROTECTED = 2; /** * Indicates that the constant is private. * * @since 8.0 */ public const IS_PRIVATE = 4; /** * @since 8.1 */ public const IS_FINAL = 5; /** * ReflectionClassConstant constructor. * * @param string|object $class Either a string containing the name of the class to reflect, or an object. * @param string $constant The name of the class constant. * @since 7.1 * @link https://php.net/manual/en/reflectionclassconstant.construct.php */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string|object'], default: '')] $class, string $constant) {} /** * @link https://php.net/manual/en/reflectionclassconstant.export.php * @param string|object $class The reflection to export. * @param string $name The class constant name. * @param bool $return Setting to {@see true} will return the export, as opposed to emitting it. Setting * to {@see false} (the default) will do the opposite. * @return string|null * @since 7.1 * @removed 8.0 */ #[Deprecated(since: '7.4')] public static function export($class, $name, $return = false) {} /** * Gets declaring class * * @return ReflectionClass * @link https://php.net/manual/en/reflectionclassconstant.getdeclaringclass.php * @since 7.1 */ #[Pure] #[TentativeType] public function getDeclaringClass(): ReflectionClass {} /** * Gets doc comments * * @return string|false The doc comment if it exists, otherwise {@see false} * @link https://php.net/manual/en/reflectionclassconstant.getdoccomment.php * @since 7.1 */ #[Pure] #[TentativeType] public function getDocComment(): string|false {} /** * Gets the class constant modifiers * * @return int A numeric representation of the modifiers. The actual meanings of these modifiers are described in * the predefined constants. * @link https://php.net/manual/en/reflectionclassconstant.getmodifiers.php * @since 7.1 */ #[Pure] #[TentativeType] public function getModifiers(): int {} /** * Get name of the constant * * @link https://php.net/manual/en/reflectionclassconstant.getname.php * @return string Returns the constant's name. * @since 7.1 */ #[Pure] #[TentativeType] public function getName(): string {} /** * Gets value * * @link https://php.net/manual/en/reflectionclassconstant.getvalue.php * @return mixed The value of the class constant. * @since 7.1 */ #[Pure] #[TentativeType] public function getValue(): mixed {} /** * Checks if class constant is private * * @link https://php.net/manual/en/reflectionclassconstant.isprivate.php * @return bool * @since 7.1 */ #[Pure] #[TentativeType] public function isPrivate(): bool {} /** * Checks if class constant is protected * * @link https://php.net/manual/en/reflectionclassconstant.isprotected.php * @return bool * @since 7.1 */ #[Pure] #[TentativeType] public function isProtected(): bool {} /** * Checks if class constant is public * * @link https://php.net/manual/en/reflectionclassconstant.ispublic.php * @return bool * @since 7.1 */ #[Pure] #[TentativeType] public function isPublic(): bool {} /** * Returns the string representation of the ReflectionClassConstant object. * * @link https://php.net/manual/en/reflectionclassconstant.tostring.php * @return string * @since 7.1 */ public function __toString(): string {} /** * @template T * * Returns an array of constant attributes. * * @param class-string|null $name Name of an attribute class * @param int $flags Сriteria by which the attribute is searched. * @return ReflectionAttribute[] * @since 8.0 */ #[Pure] public function getAttributes(?string $name = null, int $flags = 0): array {} /** * ReflectionClassConstant cannot be cloned * * @return void */ #[PhpStormStubsElementAvailable(from: "5.4", to: "8.0")] final private function __clone(): void {} /** * ReflectionClassConstant cannot be cloned * * @return void */ #[PhpStormStubsElementAvailable(from: "8.1")] private function __clone(): void {} #[PhpStormStubsElementAvailable('8.1')] public function isEnumCase(): bool {} /** * @return bool * @since 8.1 */ public function isFinal(): bool {} /** * @since 8.3 */ public function hasType(): bool {} /** * @since 8.3 */ public function getType(): ?ReflectionType {} /** * @since 8.4 */ public function isDeprecated(): bool {} } * The name of the file to open, or an existing stream resource. *

    * @param string $mode

    * Similar to the fopen function, only 'r' (read) * and 'w' (write) are supported. Everything else will cause bzopen * to return FALSE. *

    * @return resource|false If the open fails, bzopen returns FALSE, otherwise * it returns a pointer to the newly opened file. */ #[Pure] function bzopen($file, string $mode) {} /** * Binary safe bzip2 file read * @link https://php.net/manual/en/function.bzread.php * @param resource $bz

    * The file pointer. It must be valid and must point to a file * successfully opened by bzopen. *

    * @param int<1024, 8192> $length [optional]

    * If not specified, bzread will read 1024 * (uncompressed) bytes at a time. A maximum of 8192 * uncompressed bytes will be read at a time. *

    * @return string|false the uncompressed data, or FALSE on error. */ function bzread($bz, int $length = 1024): string|false {} /** * Binary safe bzip2 file write * @link https://php.net/manual/en/function.bzwrite.php * @param resource $bz

    * The file pointer. It must be valid and must point to a file * successfully opened by bzopen. *

    * @param string $data

    * The written data. *

    * @param int|null $length [optional]

    * If supplied, writing will stop after length * (uncompressed) bytes have been written or the end of * data is reached, whichever comes first. *

    * @return int|false the number of bytes written, or FALSE on error. */ function bzwrite($bz, string $data, ?int $length): int|false {} /** * Force a write of all buffered data * @link https://php.net/manual/en/function.bzflush.php * @param resource $bz

    * The file pointer. It must be valid and must point to a file * successfully opened by bzopen. *

    * @return bool TRUE on success or FALSE on failure. */ function bzflush($bz): bool {} /** * Close a bzip2 file * @link https://php.net/manual/en/function.bzclose.php * @param resource $bz

    * The file pointer. It must be valid and must point to a file * successfully opened by bzopen. *

    * @return bool TRUE on success or FALSE on failure. */ function bzclose($bz): bool {} /** * Returns a bzip2 error number * @link https://php.net/manual/en/function.bzerrno.php * @param resource $bz

    * The file pointer. It must be valid and must point to a file * successfully opened by bzopen. *

    * @return int the error number as an integer. */ #[Pure] #[LanguageLevelTypeAware(['8.1' => 'int', '8.0' => 'int|false'], default: 'int')] function bzerrno($bz) {} /** * Returns a bzip2 error string * @link https://php.net/manual/en/function.bzerrstr.php * @param resource $bz

    * The file pointer. It must be valid and must point to a file * successfully opened by bzopen. *

    * @return string a string containing the error message. */ #[Pure] #[LanguageLevelTypeAware(['8.1' => 'string', '8.0' => 'string|false'], default: 'string')] function bzerrstr($bz) {} /** * Returns the bzip2 error number and error string in an array * @link https://php.net/manual/en/function.bzerror.php * @param resource $bz

    * The file pointer. It must be valid and must point to a file * successfully opened by bzopen. *

    * @return array an associative array, with the error code in the * errno entry, and the error message in the * errstr entry. */ #[Pure] #[LanguageLevelTypeAware(['8.1' => 'array', '8.0' => 'array|false'], default: 'array')] #[ArrayShape(["errno" => "int", "errstr" => "string"])] function bzerror($bz) {} /** * Compress a string into bzip2 encoded data * @link https://php.net/manual/en/function.bzcompress.php * @param string $data

    * The string to compress. *

    * @param int $block_size

    * Specifies the blocksize used during compression and should be a number * from 1 to 9 with 9 giving the best compression, but using more * resources to do so. *

    * @param int $work_factor [optional]

    * Controls how the compression phase behaves when presented with worst * case, highly repetitive, input data. The value can be between 0 and * 250 with 0 being a special case. *

    *

    * Regardless of the workfactor, the generated * output is the same. *

    * @return string|int The compressed string, or an error number if an error occurred. */ #[Pure] function bzcompress( string $data, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.0')] int $blocksize, #[PhpStormStubsElementAvailable(from: '7.1')] int $block_size = 4, int $work_factor = 0 ): string|int {} /** * Decompresses bzip2 encoded data * @link https://php.net/manual/en/function.bzdecompress.php * @param string $data

    * The string to decompress. *

    * @param bool $use_less_memory [optional]

    * If TRUE, an alternative decompression algorithm will be used which * uses less memory (the maximum memory requirement drops to around 2300K) * but works at roughly half the speed. *

    *

    * See the bzip2 documentation for more * information about this feature. *

    * @return string|int|false The decompressed string, or an error number if an error occurred. */ #[Pure] function bzdecompress(string $data, bool $use_less_memory = false): string|int|false {} distributedTracingHeaderExtractor() instead * * @return TransactionInterface New transaction * * @see TransactionInterface::setName() For the description. * @see TransactionInterface::setType() For the description. * @see TransactionInterface::getTimestamp() For the description. */ public static function beginCurrentTransaction( string $name, string $type, ?float $timestamp = null, ?string $serializedDistTracingData = null ): TransactionInterface {} /** * Begins a new transaction, sets as the current transaction, * runs the provided callback as the new transaction and automatically ends the new transaction. * * @param string $name New transaction's name * @param string $type New transaction's type * @param \Closure $callback Callback to execute as the new transaction * @param float|null $timestamp Start time of the new transaction * @param string|null $serializedDistTracingData - DEPRECATED since version 1.3 - * use newTransaction()->distributedTracingHeaderExtractor() instead * * @return mixed The return value of $callback * * @see TransactionInterface::setName() For the description. * @see TransactionInterface::setType() For the description. * @see TransactionInterface::getTimestamp() For the description. */ public static function captureCurrentTransaction( string $name, string $type, \Closure $callback, ?float $timestamp = null, ?string $serializedDistTracingData = null ) {} /** * Returns the current transaction. * * @return TransactionInterface The current transaction */ public static function getCurrentTransaction(): TransactionInterface {} /** * If there is the current span then it returns the current span. * Otherwise if there is the current transaction then it returns the current transaction. * Otherwise it returns the noop execution segment. * * @return ExecutionSegmentInterface The current execution segment */ public static function getCurrentExecutionSegment(): ExecutionSegmentInterface {} /** * Begins a new transaction. * * @param string $name New transaction's name * @param string $type New transaction's type * @param float|null $timestamp Start time of the new transaction * @param string|null $serializedDistTracingData - DEPRECATED since version 1.3 - * use newTransaction()->distributedTracingHeaderExtractor() instead * * @return TransactionInterface New transaction * * @see TransactionInterface::setName() For the description. * @see TransactionInterface::setType() For the description. * @see TransactionInterface::getTimestamp() For the description. */ public static function beginTransaction( string $name, string $type, ?float $timestamp = null, ?string $serializedDistTracingData = null ): TransactionInterface {} /** * Begins a new transaction, * runs the provided callback as the new transaction and automatically ends the new transaction. * * @param string $name New transaction's name * @param string $type New transaction's type * @param \Closure $callback Callback to execute as the new transaction * @param float|null $timestamp Start time of the new transaction * @param string|null $serializedDistTracingData - DEPRECATED since version 1.3 - * use newTransaction()->distributedTracingHeaderExtractor() instead * * @return mixed The return value of $callback * * @see TransactionInterface::setName() For the description. * @see TransactionInterface::setType() For the description. * @see TransactionInterface::getTimestamp() For the description. */ public static function captureTransaction( string $name, string $type, \Closure $callback, ?float $timestamp = null, ?string $serializedDistTracingData = null ) {} /** * Advanced API to begin a new transaction * * @param string $name New transaction's name * @param string $type New transaction's type * * @return TransactionBuilderInterface New transaction builder * * @see TransactionInterface::setName() For the description. * @see TransactionInterface::setType() For the description. */ public static function newTransaction(string $name, string $type): TransactionBuilderInterface {} /** * Creates an error based on the given Throwable instance * with the current execution segment (if there is one) as the parent. * * @param \Throwable $throwable * * @return string|null ID of the reported error event or null if no event was reported * (for example, because recording is disabled) * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json */ public static function createErrorFromThrowable(\Throwable $throwable): ?string {} /** * Creates an error based on the given data * with the current execution segment (if there is one) as the parent. * * @param CustomErrorData $customErrorData * * @return string|null ID of the reported error event or null if no event was reported * (for example, because recording is disabled) * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json */ public static function createCustomError(CustomErrorData $customErrorData): ?string {} /** * Pauses recording */ public static function pauseRecording(): void {} /** * Resumes recording */ public static function resumeRecording(): void {} /** * @deprecated Deprecated since version 1.3 - use injectDistributedTracingHeaders() instead * @see injectDistributedTracingHeaders() Use it instead of this method * * Returns distributed tracing data for the current span/transaction */ public static function getSerializedCurrentDistributedTracingData(): string {} } /** * Class to gather optional parameters to start a new transaction * * @see ElasticApm::beginCurrentTransaction() * @see ElasticApm::captureCurrentTransaction() */ interface TransactionBuilderInterface { /** * New transaction will be set as the current one * * @return TransactionBuilderInterface */ public function asCurrent(): self; /** * Set start time of the new transaction * * @param float $timestamp * * @return TransactionBuilderInterface */ public function timestamp(float $timestamp): self; /** * @param \Closure $headerExtractor * * @return TransactionBuilderInterface */ public function distributedTracingHeaderExtractor(\Closure $headerExtractor): self; /** * Begins a new transaction. * * @return TransactionInterface New transaction */ public function begin(): TransactionInterface; /** * Begins a new transaction, * runs the provided callback as the new transaction and automatically ends the new transaction. * * @param \Closure $callback * * @return mixed The return value of $callback */ public function capture(\Closure $callback); } interface TransactionInterface extends ExecutionSegmentInterface { /** * Transactions that are 'sampled' will include all available information * Transactions that are not sampled will not have 'spans' or 'context'. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/transactions/transaction.json#L72 */ public function isSampled(): bool; /** * Hex encoded 64 random bits ID of the parent transaction or span. * Only a root transaction of a trace does not have a parent ID, otherwise it needs to be set. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/transactions/transaction.json#L19 */ public function getParentId(): ?string; /** * Begins a new span with the current execution segment * as the new span's parent and sets as the new span as the current span for this transaction. * The current execution segment is the current span if there is one or this transaction itself otherwise. * * @param string $name New span's name. * @param string $type New span's type * @param string|null $subtype New span's subtype * @param string|null $action New span's action * @param float|null $timestamp Start time of the new span * * @see SpanInterface::setName() For the description. * @see SpanInterface::setType() For the description. * @see SpanInterface::setSubtype() For the description. * @see SpanInterface::setAction() For the description. * @see SpanInterface::getTimestamp() For the description. * * @return SpanInterface New span */ public function beginCurrentSpan( string $name, string $type, ?string $subtype = null, ?string $action = null, ?float $timestamp = null ): SpanInterface; /** * Begins a new span with the current execution segment as the new span's parent and * sets the new span as the current span for this transaction. * The current execution segment is the current span if there is one or this transaction itself otherwise. * * @param string $name New span's name * @param string $type New span's type * @param \Closure $callback Callback to execute as the new span * @param string|null $subtype New span's subtype * @param string|null $action New span's action * @param float|null $timestamp Start time of the new span * * @see SpanInterface::setName() For the description. * @see SpanInterface::setType() For the description. * @see SpanInterface::setSubtype() For the description. * @see SpanInterface::setAction() For the description. * @see SpanInterface::getTimestamp() For the description. * * @return mixed The return value of $callback */ public function captureCurrentSpan( string $name, string $type, \Closure $callback, ?string $subtype = null, ?string $action = null, ?float $timestamp = null ); /** * Returns the current span. * * @return SpanInterface The current span */ public function getCurrentSpan(): SpanInterface; /** * Returns context (context allows to set labels, etc.) */ public function context(): TransactionContextInterface; /** * The result of the transaction. * For HTTP-related transactions, this should be the status code formatted like 'HTTP 2xx'. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/transactions/transaction.json#L52 * * @param string|null $result * * @return void */ public function setResult(?string $result): void; /** * @see setResult() For the description */ public function getResult(): ?string; /** * If the transaction does not have a parent ID yet, * calling this method generates a new ID, * sets it as the parent ID of this transaction, and returns it as a string. * * @return string */ public function ensureParentId(): string; } interface SpanInterface extends ExecutionSegmentInterface { /** * Hex encoded 64 random bits ID of the correlated transaction. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L14 */ public function getTransactionId(): string; /** * Hex encoded 64 random bits ID of the parent. * If this span is the root span of the correlated transaction the its parent is the correlated transaction * otherwise its parent is the parent span. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L24 */ public function getParentId(): string; /** * The specific kind of event within the sub-type represented by the span * e.g., 'query' for type/sub-type 'db'/'mysql', 'connect' for type/sub-type 'db'/'cassandra' * * The length of this string is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L38 * * @param string|null $action * * @return void */ public function setAction(?string $action): void; /** * A further sub-division of the type * e.g., 'mysql', 'postgresql' or 'elasticsearch' for type 'db', 'http' for type 'external', etc. * * The length of this string is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L33 * * @param string|null $subtype */ public function setSubtype(?string $subtype): void; /** * Returns context (context allows to set labels, etc.) */ public function context(): SpanContextInterface; /** * Extended version of ExecutionSegmentInterface::end() * * @param int $numberOfStackFramesToSkip Number of stack frames to skip when capturing stack trace. * @param float|null $duration In milliseconds with 3 decimal points. * * @see ExecutionSegmentInterface::end() For the description */ public function endSpanEx(int $numberOfStackFramesToSkip, ?float $duration = null): void; } interface SpanContextInterface extends ExecutionSegmentContextInterface { /** * Returns an object containing contextual data for database spans * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L47 */ public function db(): SpanContextDbInterface; /** * Returns an object containing contextual data of the related http request * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L69 */ public function http(): SpanContextHttpInterface; /** * Returns an object containing contextual data about the destination for spans * * @link https://github.com/elastic/apm-server/blob/7.6/docs/spec/spans/span.json#L44 */ public function destination(): SpanContextDestinationInterface; } interface SpanContextDbInterface { /** * A database statement (e.g. query) for the given database type * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L55 * * @param string|null $statement * * @return void */ public function setStatement(?string $statement): void; } interface SpanContextHttpInterface { /** * The raw url of the correlating http request * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L73 * * @param string|null $url * * @return void */ public function setUrl(?string $url): void; /** * The status code of the http request * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L77 * * @param int|null $statusCode * * @return void */ public function setStatusCode(?int $statusCode): void; /** * The method of the http request * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L81 * * @param string|null $method * * @return void */ public function setMethod(?string $method): void; } /** * An object containing contextual data about the destination for spans * * @link https://github.com/elastic/apm-server/blob/7.6/docs/spec/spans/span.json#L44 */ interface SpanContextDestinationInterface { /** * Sets destination service context * * @link https://github.com/elastic/apm-server/blob/v7.11.0/docs/spec/v2/span.json#L106 * * @param string $name * @param string $resource * @param string $type */ public function setService(string $name, string $resource, string $type): void; } /** * This interface has functionality shared between Transaction and Span. */ interface ExecutionSegmentInterface { /** * Hex encoded 64 random bits (== 8 bytes == 16 hex digits) ID. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/transactions/transaction.json#L9 * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L9 */ public function getId(): string; /** * Hex encoded 128 random bits (== 16 bytes == 32 hex digits) ID of the correlated trace. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/transactions/transaction.json#L14 * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L19 */ public function getTraceId(): string; /** * Recorded time of the event. * For events that have non-zero duration this time corresponds to the start of the event. * UTC based and in microseconds since Unix epoch. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/transactions/transaction.json#L6 * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L6 * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/timestamp_epoch.json#L7 */ public function getTimestamp(): float; /** * Begins a new span with this execution segment as the new span's parent. * * @param string $name New span's name * @param string $type New span's type * @param string|null $subtype New span's subtype * @param string|null $action New span's action * @param float|null $timestamp Start time of the new span * * @see SpanInterface::setName() For the description. * @see SpanInterface::setType() For the description. * @see SpanInterface::setSubtype() For the description. * @see SpanInterface::setAction() For the description. * @see SpanInterface::setTimestamp() For the description. * * @return SpanInterface New span */ public function beginChildSpan( string $name, string $type, ?string $subtype = null, ?string $action = null, ?float $timestamp = null ): SpanInterface; /** * Begins a new span with this execution segment as the new span's parent, * runs the provided callback as the new span and automatically ends the new span. * * @param string $name New span's name * @param string $type New span's type * @param \Closure $callback Callback to execute as the new span * @param string|null $subtype New span's subtype * @param string|null $action New span's action * @param float|null $timestamp Start time of the new span * * @see SpanInterface::setName() For the description. * @see SpanInterface::setType() For the description. * @see SpanInterface::setSubtype() For the description. * @see SpanInterface::setAction() For the description. * @see SpanInterface::setTimestamp() For the description. * * @return mixed The return value of $callback */ public function captureChildSpan( string $name, string $type, \Closure $callback, ?string $subtype = null, ?string $action = null, ?float $timestamp = null ); /** * - For transactions: * The name of this transaction. * Generic designation of a transaction in the scope of a single service (eg: 'GET /users/:id'). * * - For spans: * Generic designation of a span in the scope of a transaction. * * The length of this string is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/transactions/transaction.json#L47 * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L136 * * @param string $name */ public function setName(string $name): void; /** * Type is a keyword of specific relevance in the service's domain * e.g., * - For transaction: 'db', 'external' for a span and 'request', 'backgroundjob' for a transaction, etc. * - For span: 'db.postgresql.query', 'template.erb', etc. * * The length of this string is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/transactions/transaction.json#L57 * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L149 * * @param string $type */ public function setType(string $type): void; /** * @deprecated Deprecated since version 1.3 - use injectDistributedTracingHeaders() instead * @see injectDistributedTracingHeaders() Use it instead of this method * * Returns distributed tracing data */ public function getDistributedTracingData(): ?DistributedTracingData; /** * Returns distributed tracing data for the current span/transaction * * $headerInjector is callback to inject headers with signature * * (string $headerName, string $headerValue): void * * @param \Closure $headerInjector Callback that actually injects header(s) for the underlying transport */ public function injectDistributedTracingHeaders(\Closure $headerInjector): void; /** * Sets the end timestamp and finalizes this object's state. * * If any mutating method (for example any `set...` method is a mutating method) * is called on a instance which has already then a warning is logged. * For example, end() is a mutating method as well. * * @param float|null $duration In milliseconds with 3 decimal points. */ public function end(?float $duration = null): void; /** * Returns true if this execution segment has already ended. */ public function hasEnded(): bool; /** * Creates an error based on the given Throwable instance with this execution segment as the parent. * * @param \Throwable $throwable * * @return string|null ID of the reported error event or null if no event was reported * (for example, because recording is disabled) * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json */ public function createErrorFromThrowable(\Throwable $throwable): ?string; /** * Creates an error based on the given Throwable instance with this execution segment as the parent. * * @param CustomErrorData $customErrorData * * @return string|null ID of the reported error event or null if no event was reported * (for example, because recording is disabled) * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json */ public function createCustomError(CustomErrorData $customErrorData): ?string; /** * The outcome of the transaction/span: success, failure, or unknown. * Outcome may be one of a limited set of permitted values * describing the success or failure of the transaction/span. * This field can be used for calculating error rates for incoming/outgoing requests. * * @link https://github.com/elastic/apm-server/blob/v7.10.0/docs/spec/transactions/transaction.json#L59 * @link https://github.com/elastic/apm-server/blob/v7.10.0/docs/spec/spans/span.json#L54 * @link https://github.com/elastic/apm-server/blob/v7.10.0/docs/spec/outcome.json * * @param string|null $outcome * * @return void */ public function setOutcome(?string $outcome): void; /** * @see setOutcome() For the description */ public function getOutcome(): ?string; /** * Returns true if this execution segment is a no-op (for example when recording is disabled). */ public function isNoop(): bool; /** * Discards this execution segment. */ public function discard(): void; } final class DistributedTracingData { /** @var string */ public $traceId; /** @var string */ public $parentId; /** @var bool */ public $isSampled; /** * @deprecated Deprecated since version 1.3 - use injectHeaders() instead * @see injectHeaders() Use it instead of this method * * Returns distributed tracing data for the current span/transaction */ public function serializeToString(): string {} /** * Gets distributed tracing data for the current span/transaction * * $headerInjector is callback to inject headers with signature * * (string $headerName, string $headerValue): void * * @param \Closure $headerInjector Callback that actually injects header(s) for the underlying transport */ public function injectHeaders(\Closure $headerInjector): void {} } /** * Data to create custom error event * * @see ElasticApm::createCustomError * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json#L53 * * Code in this file is part of implementation internals and thus it is not covered by the backward compatibility. */ class CustomErrorData { /** * @var int|string|null * * The error code set when the error happened, e.g. database error code * * The length of a string value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json#L56 */ public $code = null; /** * @var string|null * * The original error message * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json#L61 */ public $message = null; /** * @var string|null * * Describes the exception type's module namespace * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json#L65 */ public $module = null; /** * @var string|null * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/errors/error.json#L80 */ public $type = null; } interface TransactionContextInterface extends ExecutionSegmentContextInterface { /** * Returns an object that can be used to collect information about HTTP request * * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/context.json#L43 * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/request.json */ public function request(): TransactionContextRequestInterface; } /** * This interface has functionality shared between Transaction and Span contexts'. */ interface ExecutionSegmentContextInterface { /** * @param string $key * @param string|bool|int|float|null $value * * Labels is a flat mapping of user-defined labels with string keys and null, string, boolean or number values. * * The length of a key and a string value is limited to 1024. * * @return void * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/transactions/transaction.json#L40 * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/context.json#L46 * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/spans/span.json#L88 * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/tags.json */ public function setLabel(string $key, $value): void; } interface TransactionContextRequestInterface { /** * HTTP method * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/request.json#L33 * * @param string $method * * @return void */ public function setMethod(string $method): void; /** * Returns an object that can be used to collect information about HTTP request's URL * * @link https://github.com/elastic/apm-server/blob/7.0/docs/spec/request.json#L50 */ public function url(): TransactionContextRequestUrlInterface; } interface TransactionContextRequestUrlInterface { /** * The domain of the request, e.g. 'example.com' * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/request.json#L69 * * @param ?string $domain * * @return void */ public function setDomain(?string $domain): void; /** * The full, possibly agent-assembled URL of the request * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/request.json#L64 * * @param ?string $full * * @return void */ public function setFull(?string $full): void; /** * The raw, unparsed URL of the HTTP request line, e.g https://example.com:443/search?q=elasticsearch. * This URL may be absolute or relative. * For more details, see https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/request.json#L54 * * @param ?string $original * * @return void */ public function setOriginal(?string $original): void; /** * The path of the request, e.g. '/search' * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/request.json#L79 * * @param ?string $path * * @return void */ public function setPath(?string $path): void; /** * The port of the request, e.g. 443 * * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/request.json#L74 * * @param ?int $port * * @return void */ public function setPort(?int $port): void; /** * The protocol of the request, e.g. 'http' * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/request.json#L59 * * @param ?string $protocol * * @return void */ public function setProtocol(?string $protocol): void; /** * Sets the query string information of the request. * It is expected to have values delimited by ampersands. * * The length of a value is limited to 1024. * * @link https://github.com/elastic/apm-server/blob/v7.0.0/docs/spec/request.json#L84 * * @param ?string $query * * @return void */ public function setQuery(?string $query): void; } 'amqp/amqp.stub', 'AMQPChannel' => 'amqp/amqp.stub', 'AMQPChannelException' => 'amqp/amqp.stub', 'AMQPConnection' => 'amqp/amqp.stub', 'AMQPConnectionException' => 'amqp/amqp.stub', 'AMQPDecimal' => 'amqp/amqp.stub', 'AMQPEnvelope' => 'amqp/amqp.stub', 'AMQPEnvelopeException' => 'amqp/amqp.stub', 'AMQPException' => 'amqp/amqp.stub', 'AMQPExchange' => 'amqp/amqp.stub', 'AMQPExchangeException' => 'amqp/amqp.stub', 'AMQPExchangeValue' => 'amqp/amqp.stub', 'AMQPQueue' => 'amqp/amqp.stub', 'AMQPQueueException' => 'amqp/amqp.stub', 'AMQPTimestamp' => 'amqp/amqp.stub', 'AMQPValue' => 'amqp/amqp.stub', 'AMQPValueException' => 'amqp/amqp.stub', 'APCIterator' => 'apcu/apcu.stub', 'APCUIterator' => 'apcu/apcu.stub', 'AddressInfo' => 'sockets/sockets.stub', 'Aerospike' => 'aerospike/aerospike.stub', 'Aerospike\\Bytes' => 'aerospike/Bytes.stub', 'AllowDynamicProperties' => 'Core/Core_c.stub', 'AppendIterator' => 'SPL/SPL.stub', 'ArgumentCountError' => 'Core/Core_c.stub', 'ArithmeticError' => 'Core/Core_c.stub', 'ArrayAccess' => 'Core/Core_c.stub', 'ArrayIterator' => 'SPL/SPL.stub', 'ArrayObject' => 'SPL/SPL.stub', 'AssertionError' => 'standard/standard_9.stub', 'Attribute' => 'Core/Core_c.stub', 'BackedEnum' => 'Core/Core_c.stub', 'BadFunctionCallException' => 'SPL/SPL.stub', 'BadMethodCallException' => 'SPL/SPL.stub', 'BlackfireProbe' => 'blackfire/blackfire.stub', 'COM' => 'com_dotnet/com_dotnet.stub', 'CURLFile' => 'curl/curl.stub', 'CURLStringFile' => 'curl/CURLStringFile.stub', 'CachingIterator' => 'SPL/SPL.stub', 'CallbackFilterIterator' => 'SPL/SPL.stub', 'Cassandra' => 'cassandra/cassandra.stub', 'Cassandra\\Aggregate' => 'cassandra/cassandra.stub', 'Cassandra\\BatchStatement' => 'cassandra/cassandra.stub', 'Cassandra\\Bigint' => 'cassandra/cassandra.stub', 'Cassandra\\Blob' => 'cassandra/cassandra.stub', 'Cassandra\\Cluster' => 'cassandra/cassandra.stub', 'Cassandra\\Cluster\\Builder' => 'cassandra/cassandra.stub', 'Cassandra\\Collection' => 'cassandra/cassandra.stub', 'Cassandra\\Column' => 'cassandra/cassandra.stub', 'Cassandra\\Custom' => 'cassandra/cassandra.stub', 'Cassandra\\Date' => 'cassandra/cassandra.stub', 'Cassandra\\Decimal' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultAggregate' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultCluster' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultColumn' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultFunction' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultIndex' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultKeyspace' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultMaterializedView' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultSchema' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultSession' => 'cassandra/cassandra.stub', 'Cassandra\\DefaultTable' => 'cassandra/cassandra.stub', 'Cassandra\\Duration' => 'cassandra/cassandra.stub', 'Cassandra\\Exception' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\AlreadyExistsException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\AuthenticationException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\ConfigurationException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\DivideByZeroException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\DomainException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\ExecutionException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\InvalidArgumentException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\InvalidQueryException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\InvalidSyntaxException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\IsBootstrappingException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\LogicException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\OverloadedException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\ProtocolException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\RangeException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\ReadTimeoutException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\RuntimeException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\ServerException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\TimeoutException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\TruncateException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\UnauthorizedException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\UnavailableException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\UnpreparedException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\ValidationException' => 'cassandra/cassandra.stub', 'Cassandra\\Exception\\WriteTimeoutException' => 'cassandra/cassandra.stub', 'Cassandra\\ExecutionOptions' => 'cassandra/cassandra.stub', 'Cassandra\\Float_' => 'cassandra/cassandra.stub', 'Cassandra\\Function_' => 'cassandra/cassandra.stub', 'Cassandra\\Future' => 'cassandra/cassandra.stub', 'Cassandra\\FutureClose' => 'cassandra/cassandra.stub', 'Cassandra\\FuturePreparedStatement' => 'cassandra/cassandra.stub', 'Cassandra\\FutureRows' => 'cassandra/cassandra.stub', 'Cassandra\\FutureSession' => 'cassandra/cassandra.stub', 'Cassandra\\FutureValue' => 'cassandra/cassandra.stub', 'Cassandra\\Index' => 'cassandra/cassandra.stub', 'Cassandra\\Inet' => 'cassandra/cassandra.stub', 'Cassandra\\Keyspace' => 'cassandra/cassandra.stub', 'Cassandra\\Map' => 'cassandra/cassandra.stub', 'Cassandra\\MaterializedView' => 'cassandra/cassandra.stub', 'Cassandra\\Numeric' => 'cassandra/cassandra.stub', 'Cassandra\\PreparedStatement' => 'cassandra/cassandra.stub', 'Cassandra\\RetryPolicy' => 'cassandra/cassandra.stub', 'Cassandra\\RetryPolicy\\DefaultPolicy' => 'cassandra/cassandra.stub', 'Cassandra\\RetryPolicy\\DowngradingConsistency' => 'cassandra/cassandra.stub', 'Cassandra\\RetryPolicy\\Fallthrough' => 'cassandra/cassandra.stub', 'Cassandra\\RetryPolicy\\Logging' => 'cassandra/cassandra.stub', 'Cassandra\\Rows' => 'cassandra/cassandra.stub', 'Cassandra\\SSLOptions' => 'cassandra/cassandra.stub', 'Cassandra\\SSLOptions\\Builder' => 'cassandra/cassandra.stub', 'Cassandra\\Schema' => 'cassandra/cassandra.stub', 'Cassandra\\Session' => 'cassandra/cassandra.stub', 'Cassandra\\Set' => 'cassandra/cassandra.stub', 'Cassandra\\SimpleStatement' => 'cassandra/cassandra.stub', 'Cassandra\\Smallint' => 'cassandra/cassandra.stub', 'Cassandra\\Statement' => 'cassandra/cassandra.stub', 'Cassandra\\Table' => 'cassandra/cassandra.stub', 'Cassandra\\Time' => 'cassandra/cassandra.stub', 'Cassandra\\Timestamp' => 'cassandra/cassandra.stub', 'Cassandra\\TimestampGenerator' => 'cassandra/cassandra.stub', 'Cassandra\\TimestampGenerator\\Monotonic' => 'cassandra/cassandra.stub', 'Cassandra\\TimestampGenerator\\ServerSide' => 'cassandra/cassandra.stub', 'Cassandra\\Timeuuid' => 'cassandra/cassandra.stub', 'Cassandra\\Tinyint' => 'cassandra/cassandra.stub', 'Cassandra\\Tuple' => 'cassandra/cassandra.stub', 'Cassandra\\Type' => 'cassandra/cassandra.stub', 'Cassandra\\Type\\Collection' => 'cassandra/cassandra.stub', 'Cassandra\\Type\\Custom' => 'cassandra/cassandra.stub', 'Cassandra\\Type\\Map' => 'cassandra/cassandra.stub', 'Cassandra\\Type\\Scalar' => 'cassandra/cassandra.stub', 'Cassandra\\Type\\Set' => 'cassandra/cassandra.stub', 'Cassandra\\Type\\Tuple' => 'cassandra/cassandra.stub', 'Cassandra\\Type\\UserType' => 'cassandra/cassandra.stub', 'Cassandra\\UserTypeValue' => 'cassandra/cassandra.stub', 'Cassandra\\Uuid' => 'cassandra/cassandra.stub', 'Cassandra\\UuidInterface' => 'cassandra/cassandra.stub', 'Cassandra\\Value' => 'cassandra/cassandra.stub', 'Cassandra\\Varint' => 'cassandra/cassandra.stub', 'ClosedGeneratorException' => 'standard/_types.stub', 'Closure' => 'Core/Core_c.stub', 'Collator' => 'intl/intl.stub', 'Collectable' => 'pthreads/pthreads.stub', 'CompileError' => 'Core/Core_c.stub', 'Couchbase\\AnalyticsEncryptionLevel' => 'couchbase/couchbase.stub', 'Couchbase\\AnalyticsException' => 'couchbase/couchbase.stub', 'Couchbase\\AnalyticsIndexManager' => 'couchbase/couchbase.stub', 'Couchbase\\AnalyticsLink' => 'couchbase/couchbase.stub', 'Couchbase\\AnalyticsLinkType' => 'couchbase/couchbase.stub', 'Couchbase\\AnalyticsOptions' => 'couchbase/couchbase.stub', 'Couchbase\\AnalyticsResult' => 'couchbase/couchbase.stub', 'Couchbase\\AppendOptions' => 'couchbase/couchbase.stub', 'Couchbase\\AuthenticationException' => 'couchbase/couchbase.stub', 'Couchbase\\AzureBlobExternalAnalyticsLink' => 'couchbase/couchbase.stub', 'Couchbase\\BadInputException' => 'couchbase/couchbase.stub', 'Couchbase\\BaseException' => 'couchbase/couchbase.stub', 'Couchbase\\BinaryCollection' => 'couchbase/couchbase.stub', 'Couchbase\\BindingsException' => 'couchbase/couchbase.stub', 'Couchbase\\BooleanFieldSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\BooleanSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\Bucket' => 'couchbase/couchbase.stub', 'Couchbase\\BucketManager' => 'couchbase/couchbase.stub', 'Couchbase\\BucketMissingException' => 'couchbase/couchbase.stub', 'Couchbase\\BucketSettings' => 'couchbase/couchbase.stub', 'Couchbase\\CasMismatchException' => 'couchbase/couchbase.stub', 'Couchbase\\Cluster' => 'couchbase/couchbase.stub', 'Couchbase\\ClusterOptions' => 'couchbase/couchbase.stub', 'Couchbase\\Collection' => 'couchbase/couchbase.stub', 'Couchbase\\CollectionManager' => 'couchbase/couchbase.stub', 'Couchbase\\CollectionMissingException' => 'couchbase/couchbase.stub', 'Couchbase\\CollectionSpec' => 'couchbase/couchbase.stub', 'Couchbase\\ConjunctionSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\ConnectAnalyticsLinkOptions' => 'couchbase/couchbase.stub', 'Couchbase\\Coordinate' => 'couchbase/couchbase.stub', 'Couchbase\\CouchbaseRemoteAnalyticsLink' => 'couchbase/couchbase.stub', 'Couchbase\\CounterResult' => 'couchbase/couchbase.stub', 'Couchbase\\CreateAnalyticsDatasetOptions' => 'couchbase/couchbase.stub', 'Couchbase\\CreateAnalyticsDataverseOptions' => 'couchbase/couchbase.stub', 'Couchbase\\CreateAnalyticsIndexOptions' => 'couchbase/couchbase.stub', 'Couchbase\\CreateAnalyticsLinkOptions' => 'couchbase/couchbase.stub', 'Couchbase\\CreateQueryIndexOptions' => 'couchbase/couchbase.stub', 'Couchbase\\CreateQueryPrimaryIndexOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DateRangeFacetResult' => 'couchbase/couchbase.stub', 'Couchbase\\DateRangeSearchFacet' => 'couchbase/couchbase.stub', 'Couchbase\\DateRangeSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\DecrementOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DesignDocument' => 'couchbase/couchbase.stub', 'Couchbase\\DisconnectAnalyticsLinkOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DisjunctionSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\DmlFailureException' => 'couchbase/couchbase.stub', 'Couchbase\\DocIdSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\DocumentNotFoundException' => 'couchbase/couchbase.stub', 'Couchbase\\DropAnalyticsDatasetOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DropAnalyticsDataverseOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DropAnalyticsIndexOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DropAnalyticsLinkOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DropQueryIndexOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DropQueryPrimaryIndexOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DropUserOptions' => 'couchbase/couchbase.stub', 'Couchbase\\DurabilityException' => 'couchbase/couchbase.stub', 'Couchbase\\DurabilityLevel' => 'couchbase/couchbase.stub', 'Couchbase\\EncryptionSettings' => 'couchbase/couchbase.stub', 'Couchbase\\EvictionPolicy' => 'couchbase/couchbase.stub', 'Couchbase\\ExistsOptions' => 'couchbase/couchbase.stub', 'Couchbase\\ExistsResult' => 'couchbase/couchbase.stub', 'Couchbase\\GeoBoundingBoxSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\GeoDistanceSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\GeoPolygonQuery' => 'couchbase/couchbase.stub', 'Couchbase\\GetAllReplicasOptions' => 'couchbase/couchbase.stub', 'Couchbase\\GetAllUsersOptions' => 'couchbase/couchbase.stub', 'Couchbase\\GetAnalyticsLinksOptions' => 'couchbase/couchbase.stub', 'Couchbase\\GetAndLockOptions' => 'couchbase/couchbase.stub', 'Couchbase\\GetAndTouchOptions' => 'couchbase/couchbase.stub', 'Couchbase\\GetAnyReplicaOptions' => 'couchbase/couchbase.stub', 'Couchbase\\GetOptions' => 'couchbase/couchbase.stub', 'Couchbase\\GetReplicaResult' => 'couchbase/couchbase.stub', 'Couchbase\\GetResult' => 'couchbase/couchbase.stub', 'Couchbase\\GetUserOptions' => 'couchbase/couchbase.stub', 'Couchbase\\Group' => 'couchbase/couchbase.stub', 'Couchbase\\HttpException' => 'couchbase/couchbase.stub', 'Couchbase\\IncrementOptions' => 'couchbase/couchbase.stub', 'Couchbase\\IndexFailureException' => 'couchbase/couchbase.stub', 'Couchbase\\IndexNotFoundException' => 'couchbase/couchbase.stub', 'Couchbase\\InsertOptions' => 'couchbase/couchbase.stub', 'Couchbase\\InvalidConfigurationException' => 'couchbase/couchbase.stub', 'Couchbase\\InvalidRangeException' => 'couchbase/couchbase.stub', 'Couchbase\\InvalidStateException' => 'couchbase/couchbase.stub', 'Couchbase\\KeyDeletedException' => 'couchbase/couchbase.stub', 'Couchbase\\KeyExistsException' => 'couchbase/couchbase.stub', 'Couchbase\\KeyLockedException' => 'couchbase/couchbase.stub', 'Couchbase\\KeyValueException' => 'couchbase/couchbase.stub', 'Couchbase\\KeyspaceNotFoundException' => 'couchbase/couchbase.stub', 'Couchbase\\LoggingMeter' => 'couchbase/couchbase.stub', 'Couchbase\\LookupCountSpec' => 'couchbase/couchbase.stub', 'Couchbase\\LookupExistsSpec' => 'couchbase/couchbase.stub', 'Couchbase\\LookupGetFullSpec' => 'couchbase/couchbase.stub', 'Couchbase\\LookupGetSpec' => 'couchbase/couchbase.stub', 'Couchbase\\LookupInOptions' => 'couchbase/couchbase.stub', 'Couchbase\\LookupInResult' => 'couchbase/couchbase.stub', 'Couchbase\\LookupInSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MatchAllSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\MatchNoneSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\MatchPhraseSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\MatchSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\Meter' => 'couchbase/couchbase.stub', 'Couchbase\\MutateArrayAddUniqueSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutateArrayAppendSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutateArrayInsertSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutateArrayPrependSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutateCounterSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutateInOptions' => 'couchbase/couchbase.stub', 'Couchbase\\MutateInResult' => 'couchbase/couchbase.stub', 'Couchbase\\MutateInSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutateInsertSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutateRemoveSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutateReplaceSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutateUpsertSpec' => 'couchbase/couchbase.stub', 'Couchbase\\MutationResult' => 'couchbase/couchbase.stub', 'Couchbase\\MutationState' => 'couchbase/couchbase.stub', 'Couchbase\\MutationToken' => 'couchbase/couchbase.stub', 'Couchbase\\NetworkException' => 'couchbase/couchbase.stub', 'Couchbase\\NoopMeter' => 'couchbase/couchbase.stub', 'Couchbase\\NoopTracer' => 'couchbase/couchbase.stub', 'Couchbase\\NumericRangeFacetResult' => 'couchbase/couchbase.stub', 'Couchbase\\NumericRangeSearchFacet' => 'couchbase/couchbase.stub', 'Couchbase\\NumericRangeSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\Origin' => 'couchbase/couchbase.stub', 'Couchbase\\ParsingFailureException' => 'couchbase/couchbase.stub', 'Couchbase\\PartialViewException' => 'couchbase/couchbase.stub', 'Couchbase\\PathExistsException' => 'couchbase/couchbase.stub', 'Couchbase\\PathNotFoundException' => 'couchbase/couchbase.stub', 'Couchbase\\PhraseSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\PlanningFailureException' => 'couchbase/couchbase.stub', 'Couchbase\\PrefixSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\PreparedStatementException' => 'couchbase/couchbase.stub', 'Couchbase\\PrependOptions' => 'couchbase/couchbase.stub', 'Couchbase\\QueryErrorException' => 'couchbase/couchbase.stub', 'Couchbase\\QueryException' => 'couchbase/couchbase.stub', 'Couchbase\\QueryIndex' => 'couchbase/couchbase.stub', 'Couchbase\\QueryIndexManager' => 'couchbase/couchbase.stub', 'Couchbase\\QueryMetaData' => 'couchbase/couchbase.stub', 'Couchbase\\QueryOptions' => 'couchbase/couchbase.stub', 'Couchbase\\QueryProfile' => 'couchbase/couchbase.stub', 'Couchbase\\QueryResult' => 'couchbase/couchbase.stub', 'Couchbase\\QueryScanConsistency' => 'couchbase/couchbase.stub', 'Couchbase\\QueryServiceException' => 'couchbase/couchbase.stub', 'Couchbase\\QueryStringSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\QuotaLimitedException' => 'couchbase/couchbase.stub', 'Couchbase\\RateLimitedException' => 'couchbase/couchbase.stub', 'Couchbase\\RegexpSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\RemoveOptions' => 'couchbase/couchbase.stub', 'Couchbase\\ReplaceAnalyticsLinkOptions' => 'couchbase/couchbase.stub', 'Couchbase\\ReplaceOptions' => 'couchbase/couchbase.stub', 'Couchbase\\RequestCanceledException' => 'couchbase/couchbase.stub', 'Couchbase\\RequestSpan' => 'couchbase/couchbase.stub', 'Couchbase\\RequestTracer' => 'couchbase/couchbase.stub', 'Couchbase\\Result' => 'couchbase/couchbase.stub', 'Couchbase\\Role' => 'couchbase/couchbase.stub', 'Couchbase\\RoleAndDescription' => 'couchbase/couchbase.stub', 'Couchbase\\RoleAndOrigin' => 'couchbase/couchbase.stub', 'Couchbase\\S3ExternalAnalyticsLink' => 'couchbase/couchbase.stub', 'Couchbase\\Scope' => 'couchbase/couchbase.stub', 'Couchbase\\ScopeMissingException' => 'couchbase/couchbase.stub', 'Couchbase\\ScopeSpec' => 'couchbase/couchbase.stub', 'Couchbase\\SearchException' => 'couchbase/couchbase.stub', 'Couchbase\\SearchFacet' => 'couchbase/couchbase.stub', 'Couchbase\\SearchFacetResult' => 'couchbase/couchbase.stub', 'Couchbase\\SearchHighlightMode' => 'couchbase/couchbase.stub', 'Couchbase\\SearchIndex' => 'couchbase/couchbase.stub', 'Couchbase\\SearchIndexManager' => 'couchbase/couchbase.stub', 'Couchbase\\SearchMetaData' => 'couchbase/couchbase.stub', 'Couchbase\\SearchOptions' => 'couchbase/couchbase.stub', 'Couchbase\\SearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\SearchResult' => 'couchbase/couchbase.stub', 'Couchbase\\SearchSort' => 'couchbase/couchbase.stub', 'Couchbase\\SearchSortField' => 'couchbase/couchbase.stub', 'Couchbase\\SearchSortGeoDistance' => 'couchbase/couchbase.stub', 'Couchbase\\SearchSortId' => 'couchbase/couchbase.stub', 'Couchbase\\SearchSortMissing' => 'couchbase/couchbase.stub', 'Couchbase\\SearchSortMode' => 'couchbase/couchbase.stub', 'Couchbase\\SearchSortScore' => 'couchbase/couchbase.stub', 'Couchbase\\SearchSortType' => 'couchbase/couchbase.stub', 'Couchbase\\ServiceMissingException' => 'couchbase/couchbase.stub', 'Couchbase\\StorageBackend' => 'couchbase/couchbase.stub', 'Couchbase\\StoreSemantics' => 'couchbase/couchbase.stub', 'Couchbase\\SubdocumentException' => 'couchbase/couchbase.stub', 'Couchbase\\TempFailException' => 'couchbase/couchbase.stub', 'Couchbase\\TermFacetResult' => 'couchbase/couchbase.stub', 'Couchbase\\TermRangeSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\TermSearchFacet' => 'couchbase/couchbase.stub', 'Couchbase\\TermSearchQuery' => 'couchbase/couchbase.stub', 'Couchbase\\ThresholdLoggingTracer' => 'couchbase/couchbase.stub', 'Couchbase\\TimeoutException' => 'couchbase/couchbase.stub', 'Couchbase\\TouchOptions' => 'couchbase/couchbase.stub', 'Couchbase\\UnlockOptions' => 'couchbase/couchbase.stub', 'Couchbase\\UpsertOptions' => 'couchbase/couchbase.stub', 'Couchbase\\UpsertUserOptions' => 'couchbase/couchbase.stub', 'Couchbase\\User' => 'couchbase/couchbase.stub', 'Couchbase\\UserAndMetadata' => 'couchbase/couchbase.stub', 'Couchbase\\UserManager' => 'couchbase/couchbase.stub', 'Couchbase\\ValueRecorder' => 'couchbase/couchbase.stub', 'Couchbase\\ValueTooBigException' => 'couchbase/couchbase.stub', 'Couchbase\\View' => 'couchbase/couchbase.stub', 'Couchbase\\ViewConsistency' => 'couchbase/couchbase.stub', 'Couchbase\\ViewException' => 'couchbase/couchbase.stub', 'Couchbase\\ViewIndexManager' => 'couchbase/couchbase.stub', 'Couchbase\\ViewMetaData' => 'couchbase/couchbase.stub', 'Couchbase\\ViewOptions' => 'couchbase/couchbase.stub', 'Couchbase\\ViewOrdering' => 'couchbase/couchbase.stub', 'Couchbase\\ViewResult' => 'couchbase/couchbase.stub', 'Couchbase\\ViewRow' => 'couchbase/couchbase.stub', 'Couchbase\\WatchQueryIndexesOptions' => 'couchbase/couchbase.stub', 'Couchbase\\WildcardSearchQuery' => 'couchbase/couchbase.stub', 'Countable' => 'Core/Core_c.stub', 'Crypto\\Base64' => 'crypto/crypto.stub', 'Crypto\\Base64Exception' => 'crypto/crypto.stub', 'Crypto\\CMAC' => 'crypto/crypto.stub', 'Crypto\\Cipher' => 'crypto/crypto.stub', 'Crypto\\CipherException' => 'crypto/crypto.stub', 'Crypto\\HMAC' => 'crypto/crypto.stub', 'Crypto\\Hash' => 'crypto/crypto.stub', 'Crypto\\HashException' => 'crypto/crypto.stub', 'Crypto\\KDF' => 'crypto/crypto.stub', 'Crypto\\KDFException' => 'crypto/crypto.stub', 'Crypto\\MAC' => 'crypto/crypto.stub', 'Crypto\\MACException' => 'crypto/crypto.stub', 'Crypto\\PBKDF2' => 'crypto/crypto.stub', 'Crypto\\PBKDF2Exception' => 'crypto/crypto.stub', 'Crypto\\Rand' => 'crypto/crypto.stub', 'Crypto\\RandException' => 'crypto/crypto.stub', 'CurlHandle' => 'curl/curl.stub', 'CurlMultiHandle' => 'curl/curl.stub', 'CurlShareHandle' => 'curl/curl.stub', 'DOMAttr' => 'dom/dom_c.stub', 'DOMCdataSection' => 'dom/dom_c.stub', 'DOMCharacterData' => 'dom/dom_c.stub', 'DOMChildNode' => 'dom/dom_c.stub', 'DOMComment' => 'dom/dom_c.stub', 'DOMConfiguration' => 'dom/dom_c.stub', 'DOMDocument' => 'dom/dom_c.stub', 'DOMDocumentFragment' => 'dom/dom_c.stub', 'DOMDocumentType' => 'dom/dom_c.stub', 'DOMDomError' => 'dom/dom_c.stub', 'DOMElement' => 'dom/dom_c.stub', 'DOMEntity' => 'dom/dom_c.stub', 'DOMEntityReference' => 'dom/dom_c.stub', 'DOMErrorHandler' => 'dom/dom_c.stub', 'DOMException' => 'dom/dom_c.stub', 'DOMImplementation' => 'dom/dom_c.stub', 'DOMImplementationList' => 'dom/dom_c.stub', 'DOMImplementationSource' => 'dom/dom_c.stub', 'DOMLocator' => 'dom/dom_c.stub', 'DOMNameList' => 'dom/dom_c.stub', 'DOMNameSpaceNode' => 'dom/dom_c.stub', 'DOMNamedNodeMap' => 'dom/dom_c.stub', 'DOMNode' => 'dom/dom_c.stub', 'DOMNodeList' => 'dom/dom_c.stub', 'DOMNotation' => 'dom/dom_c.stub', 'DOMParentNode' => 'dom/dom_c.stub', 'DOMProcessingInstruction' => 'dom/dom_c.stub', 'DOMStringExtend' => 'dom/dom_c.stub', 'DOMStringList' => 'dom/dom_c.stub', 'DOMText' => 'dom/dom_c.stub', 'DOMTypeinfo' => 'dom/dom_c.stub', 'DOMUserDataHandler' => 'dom/dom_c.stub', 'DOMXPath' => 'dom/dom_c.stub', 'DOTNET' => 'com_dotnet/com_dotnet.stub', 'DateError' => 'date/date_c.stub', 'DateException' => 'date/date_c.stub', 'DateInterval' => 'date/date_c.stub', 'DateInvalidOperationException' => 'date/date_c.stub', 'DateInvalidTimeZoneException' => 'date/date_c.stub', 'DateMalformedIntervalStringException' => 'date/date_c.stub', 'DateMalformedPeriodStringException' => 'date/date_c.stub', 'DateMalformedStringException' => 'date/date_c.stub', 'DateObjectError' => 'date/date_c.stub', 'DatePeriod' => 'date/date_c.stub', 'DateRangeError' => 'date/date_c.stub', 'DateTime' => 'date/date_c.stub', 'DateTimeImmutable' => 'date/date_c.stub', 'DateTimeInterface' => 'date/date_c.stub', 'DateTimeZone' => 'date/date_c.stub', 'Dba\\Connection' => 'dba/Connection.stub', 'Decimal\\Decimal' => 'decimal/decimal.stub', 'DeflateContext' => 'zlib/zlib.stub', 'Deprecated' => 'Core/Core_c.stub', 'Directory' => 'standard/standard_0.stub', 'DirectoryIterator' => 'SPL/SPL_c1.stub', 'DivisionByZeroError' => 'Core/Core_c.stub', 'Dom\\AdjacentPosition' => 'dom/dom_n.stub', 'Dom\\Attr' => 'dom/dom_n.stub', 'Dom\\BrokenRandomEngineError' => 'dom/dom_n.stub', 'Dom\\CDATASection' => 'dom/dom_n.stub', 'Dom\\CharacterData' => 'dom/dom_n.stub', 'Dom\\ChildNode' => 'dom/dom_n.stub', 'Dom\\Comment' => 'dom/dom_n.stub', 'Dom\\Document' => 'dom/dom_n.stub', 'Dom\\DocumentFragment' => 'dom/dom_n.stub', 'Dom\\DocumentType' => 'dom/dom_n.stub', 'Dom\\DtdNamedNodeMap' => 'dom/dom_n.stub', 'Dom\\Element' => 'dom/dom_n.stub', 'Dom\\Entity' => 'dom/dom_n.stub', 'Dom\\EntityReference' => 'dom/dom_n.stub', 'Dom\\HTMLCollection' => 'dom/dom_n.stub', 'Dom\\HTMLDocument' => 'dom/dom_n.stub', 'Dom\\HTMLElement' => 'dom/dom_n.stub', 'Dom\\Implementation' => 'dom/dom_n.stub', 'Dom\\Mysql' => 'dom/dom_n.stub', 'Dom\\NamedNodeMap' => 'dom/dom_n.stub', 'Dom\\NamespaceInfo' => 'dom/dom_n.stub', 'Dom\\Node' => 'dom/dom_n.stub', 'Dom\\NodeList' => 'dom/dom_n.stub', 'Dom\\Notation' => 'dom/dom_n.stub', 'Dom\\ParentNode' => 'dom/dom_n.stub', 'Dom\\ProcessingInstruction' => 'dom/dom_n.stub', 'Dom\\RandomError' => 'dom/dom_n.stub', 'Dom\\RandomException' => 'dom/dom_n.stub', 'Dom\\Sqlite' => 'dom/dom_n.stub', 'Dom\\Text' => 'dom/dom_n.stub', 'Dom\\TokenList' => 'dom/dom_n.stub', 'Dom\\XMLDocument' => 'dom/dom_n.stub', 'Dom\\XPath' => 'dom/dom_n.stub', 'DomainException' => 'SPL/SPL.stub', 'Ds\\Collection' => 'ds/ds.stub', 'Ds\\Deque' => 'ds/ds.stub', 'Ds\\Hashable' => 'ds/ds.stub', 'Ds\\Map' => 'ds/ds.stub', 'Ds\\Pair' => 'ds/ds.stub', 'Ds\\PriorityQueue' => 'ds/ds.stub', 'Ds\\Queue' => 'ds/ds.stub', 'Ds\\Sequence' => 'ds/ds.stub', 'Ds\\Set' => 'ds/ds.stub', 'Ds\\Stack' => 'ds/ds.stub', 'Ds\\Vector' => 'ds/ds.stub', 'Elastic\\Apm\\CustomErrorData' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\DistributedTracingData' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\ElasticApm' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\ExecutionSegmentContextInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\ExecutionSegmentInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\SpanContextDbInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\SpanContextDestinationInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\SpanContextHttpInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\SpanContextInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\SpanInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\TransactionBuilderInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\TransactionContextInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\TransactionContextRequestInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\TransactionContextRequestUrlInterface' => 'elastic_apm/elastic_apm.stub', 'Elastic\\Apm\\TransactionInterface' => 'elastic_apm/elastic_apm.stub', 'EmptyIterator' => 'SPL/SPL.stub', 'EnchantBroker' => 'enchant/enchant.stub', 'EnchantDictionary' => 'enchant/enchant.stub', 'Error' => 'Core/Core_c.stub', 'ErrorException' => 'Core/Core_c.stub', 'Ev' => 'Ev/Ev.stub', 'EvCheck' => 'Ev/Ev.stub', 'EvChild' => 'Ev/Ev.stub', 'EvEmbed' => 'Ev/Ev.stub', 'EvFork' => 'Ev/Ev.stub', 'EvIdle' => 'Ev/Ev.stub', 'EvIo' => 'Ev/Ev.stub', 'EvLoop' => 'Ev/Ev.stub', 'EvPeriodic' => 'Ev/Ev.stub', 'EvPrepare' => 'Ev/Ev.stub', 'EvSignal' => 'Ev/Ev.stub', 'EvStat' => 'Ev/Ev.stub', 'EvTimer' => 'Ev/Ev.stub', 'EvWatcher' => 'Ev/Ev.stub', 'Event' => 'event/event.stub', 'EventBase' => 'event/event.stub', 'EventBuffer' => 'event/event.stub', 'EventBufferEvent' => 'event/event.stub', 'EventConfig' => 'event/event.stub', 'EventDnsBase' => 'event/event.stub', 'EventHttp' => 'event/event.stub', 'EventHttpConnection' => 'event/event.stub', 'EventHttpRequest' => 'event/event.stub', 'EventListener' => 'event/event.stub', 'EventSslContext' => 'event/event.stub', 'EventUtil' => 'event/event.stub', 'Exception' => 'Core/Core_c.stub', 'FANNConnection' => 'fann/fann.stub', 'FFI' => 'FFI/FFI.stub', 'FFI\\CData' => 'FFI/FFI.stub', 'FFI\\CType' => 'FFI/FFI.stub', 'FFI\\Exception' => 'FFI/FFI.stub', 'FFI\\ParserException' => 'FFI/FFI.stub', 'FTP\\Connection' => 'ftp/Connection.stub', 'Fiber' => 'Core/Core_c.stub', 'FiberError' => 'Core/Core_c.stub', 'FilesystemIterator' => 'SPL/SPL_c1.stub', 'FilterIterator' => 'SPL/SPL.stub', 'GEOSGeometry' => 'geos/geos.stub', 'GEOSWKBReader' => 'geos/geos.stub', 'GEOSWKBWriter' => 'geos/geos.stub', 'GEOSWKTReader' => 'geos/geos.stub', 'GEOSWKTWriter' => 'geos/geos.stub', 'GMP' => 'gmp/gmp.stub', 'GdFont' => 'gd/GdFont.stub', 'GdImage' => 'gd/gd.stub', 'GearmanClient' => 'gearman/gearman.stub', 'GearmanException' => 'gearman/gearman.stub', 'GearmanJob' => 'gearman/gearman.stub', 'GearmanTask' => 'gearman/gearman.stub', 'GearmanWorker' => 'gearman/gearman.stub', 'Generator' => 'standard/_types.stub', 'GlobIterator' => 'SPL/SPL_c1.stub', 'Gmagick' => 'gmagick/gmagick.stub', 'GmagickDraw' => 'gmagick/gmagick.stub', 'GmagickException' => 'gmagick/gmagick.stub', 'GmagickPixel' => 'gmagick/gmagick.stub', 'GmagickPixelException' => 'gmagick/gmagick.stub', 'Grpc\\Call' => 'grpc/grpc.stub', 'Grpc\\CallCredentials' => 'grpc/grpc.stub', 'Grpc\\Channel' => 'grpc/grpc.stub', 'Grpc\\ChannelCredentials' => 'grpc/grpc.stub', 'Grpc\\Server' => 'grpc/grpc.stub', 'Grpc\\ServerCredentials' => 'grpc/grpc.stub', 'Grpc\\Timeval' => 'grpc/grpc.stub', 'HashContext' => 'hash/hash.stub', 'HttpDeflateStream' => 'http/http.stub', 'HttpEncodingException' => 'http/http.stub', 'HttpException' => 'http/http.stub', 'HttpHeaderException' => 'http/http.stub', 'HttpInflateStream' => 'http/http.stub', 'HttpInvalidParamException' => 'http/http.stub', 'HttpMalformedHeadersException' => 'http/http.stub', 'HttpMessage' => 'http/http.stub', 'HttpMessageTypeException' => 'http/http.stub', 'HttpQueryString' => 'http/http.stub', 'HttpQueryStringException' => 'http/http.stub', 'HttpRequest' => 'http/http.stub', 'HttpRequestDataShare' => 'http/http.stub', 'HttpRequestException' => 'http/http.stub', 'HttpRequestMethodException' => 'http/http.stub', 'HttpRequestPool' => 'http/http.stub', 'HttpRequestPoolException' => 'http/http.stub', 'HttpResponse' => 'http/http.stub', 'HttpResponseException' => 'http/http.stub', 'HttpRuntimeException' => 'http/http.stub', 'HttpSocketException' => 'http/http.stub', 'HttpUrlException' => 'http/http.stub', 'HttpUtil' => 'http/http.stub', 'IMAP\\Connection' => 'imap/Connection.stub', 'Imagick' => 'imagick/imagick.stub', 'ImagickDraw' => 'imagick/imagick.stub', 'ImagickDrawException' => 'imagick/imagick.stub', 'ImagickException' => 'imagick/imagick.stub', 'ImagickKernel' => 'imagick/imagick.stub', 'ImagickKernelException' => 'imagick/imagick.stub', 'ImagickPixel' => 'imagick/imagick.stub', 'ImagickPixelException' => 'imagick/imagick.stub', 'ImagickPixelIterator' => 'imagick/imagick.stub', 'ImagickPixelIteratorException' => 'imagick/imagick.stub', 'InfiniteIterator' => 'SPL/SPL.stub', 'InflateContext' => 'zlib/zlib.stub', 'InternalIterator' => 'Core/Core_c.stub', 'IntlBreakIterator' => 'intl/intl.stub', 'IntlCalendar' => 'intl/intl.stub', 'IntlChar' => 'intl/IntlChar.stub', 'IntlCodePointBreakIterator' => 'intl/intl.stub', 'IntlDateFormatter' => 'intl/intl.stub', 'IntlDatePatternGenerator' => 'intl/IntlDatePatternGenerator.stub', 'IntlException' => 'intl/intl.stub', 'IntlGregorianCalendar' => 'intl/intl.stub', 'IntlIterator' => 'intl/intl.stub', 'IntlPartsIterator' => 'intl/intl.stub', 'IntlRuleBasedBreakIterator' => 'intl/intl.stub', 'IntlTimeZone' => 'intl/intl.stub', 'InvalidArgumentException' => 'SPL/SPL.stub', 'Iterator' => 'Core/Core_c.stub', 'IteratorAggregate' => 'Core/Core_c.stub', 'IteratorIterator' => 'SPL/SPL.stub', 'JavaException' => 'zend/zend.stub', 'JsonException' => 'json/json.stub', 'JsonIncrementalParser' => 'json/json.stub', 'JsonSerializable' => 'json/json.stub', 'Judy' => 'judy/judy.stub', 'LDAP\\Connection' => 'ldap/Connection.stub', 'LDAP\\Result' => 'ldap/Result.stub', 'LDAP\\ResultEntry' => 'ldap/ResultEntry.stub', 'LengthException' => 'SPL/SPL.stub', 'LevelDB' => 'leveldb/LevelDB.stub', 'LevelDBException' => 'leveldb/LevelDB.stub', 'LevelDBIterator' => 'leveldb/LevelDB.stub', 'LevelDBSnapshot' => 'leveldb/LevelDB.stub', 'LevelDBWriteBatch' => 'leveldb/LevelDB.stub', 'LibXMLError' => 'libxml/libxml.stub', 'LimitIterator' => 'SPL/SPL.stub', 'Locale' => 'intl/intl.stub', 'LogicException' => 'SPL/SPL.stub', 'Lua' => 'lua/lua.stub', 'LuaSandbox' => 'LuaSandbox/LuaSandbox.stub', 'LuaSandboxError' => 'LuaSandbox/LuaSandbox.stub', 'LuaSandboxErrorError' => 'LuaSandbox/LuaSandbox.stub', 'LuaSandboxFatalError' => 'LuaSandbox/LuaSandbox.stub', 'LuaSandboxFunction' => 'LuaSandbox/LuaSandbox.stub', 'LuaSandboxMemoryError' => 'LuaSandbox/LuaSandbox.stub', 'LuaSandboxRuntimeError' => 'LuaSandbox/LuaSandbox.stub', 'LuaSandboxSyntaxError' => 'LuaSandbox/LuaSandbox.stub', 'LuaSandboxTimeoutError' => 'LuaSandbox/LuaSandbox.stub', 'Memcache' => 'memcache/memcache.stub', 'MemcachePool' => 'memcache/memcache.stub', 'Memcached' => 'memcached/memcached.stub', 'MemcachedException' => 'memcached/memcached.stub', 'MessageFormatter' => 'intl/intl.stub', 'MessagePack' => 'msgpack/msgpack.stub', 'MessagePackUnpacker' => 'msgpack/msgpack.stub', 'Mongo' => 'mongo/mongo.stub', 'MongoBinData' => 'mongo/mongo.stub', 'MongoClient' => 'mongo/mongo.stub', 'MongoCode' => 'mongo/mongo.stub', 'MongoCollection' => 'mongo/mongo.stub', 'MongoCommandCursor' => 'mongo/mongo.stub', 'MongoConnectionException' => 'mongo/mongo.stub', 'MongoCursor' => 'mongo/mongo.stub', 'MongoCursorException' => 'mongo/mongo.stub', 'MongoCursorInterface' => 'mongo/mongo.stub', 'MongoCursorTimeoutException' => 'mongo/mongo.stub', 'MongoDB' => 'mongo/mongo.stub', 'MongoDBRef' => 'mongo/mongo.stub', 'MongoDB\\BSON\\Binary' => 'mongodb/BSON/Binary.stub', 'MongoDB\\BSON\\BinaryInterface' => 'mongodb/BSON/BinaryInterface.stub', 'MongoDB\\BSON\\DBPointer' => 'mongodb/BSON/DBPointer.stub', 'MongoDB\\BSON\\Decimal128' => 'mongodb/BSON/Decimal128.stub', 'MongoDB\\BSON\\Decimal128Interface' => 'mongodb/BSON/Decimal128Interface.stub', 'MongoDB\\BSON\\Document' => 'mongodb/BSON/Document.stub', 'MongoDB\\BSON\\Int64' => 'mongodb/BSON/Int64.stub', 'MongoDB\\BSON\\Iterator' => 'mongodb/BSON/Iterator.stub', 'MongoDB\\BSON\\Javascript' => 'mongodb/BSON/Javascript.stub', 'MongoDB\\BSON\\JavascriptInterface' => 'mongodb/BSON/JavascriptInterface.stub', 'MongoDB\\BSON\\MaxKey' => 'mongodb/BSON/MaxKey.stub', 'MongoDB\\BSON\\MaxKeyInterface' => 'mongodb/BSON/MaxKeyInterface.stub', 'MongoDB\\BSON\\MinKey' => 'mongodb/BSON/MinKey.stub', 'MongoDB\\BSON\\MinKeyInterface' => 'mongodb/BSON/MinKeyInterface.stub', 'MongoDB\\BSON\\ObjectId' => 'mongodb/BSON/ObjectId.stub', 'MongoDB\\BSON\\ObjectIdInterface' => 'mongodb/BSON/ObjectIdInterface.stub', 'MongoDB\\BSON\\PackedArray' => 'mongodb/BSON/PackedArray.stub', 'MongoDB\\BSON\\Persistable' => 'mongodb/BSON/Persistable.stub', 'MongoDB\\BSON\\Regex' => 'mongodb/BSON/Regex.stub', 'MongoDB\\BSON\\RegexInterface' => 'mongodb/BSON/RegexInterface.stub', 'MongoDB\\BSON\\Serializable' => 'mongodb/BSON/Serializable.stub', 'MongoDB\\BSON\\Symbol' => 'mongodb/BSON/Symbol.stub', 'MongoDB\\BSON\\Timestamp' => 'mongodb/BSON/Timestamp.stub', 'MongoDB\\BSON\\TimestampInterface' => 'mongodb/BSON/TimestampInterface.stub', 'MongoDB\\BSON\\Type' => 'mongodb/BSON/Type.stub', 'MongoDB\\BSON\\UTCDateTime' => 'mongodb/BSON/UTCDateTime.stub', 'MongoDB\\BSON\\UTCDateTimeInterface' => 'mongodb/BSON/UTCDateTimeInterface.stub', 'MongoDB\\BSON\\Undefined' => 'mongodb/BSON/Undefined.stub', 'MongoDB\\BSON\\Unserializable' => 'mongodb/BSON/Unserializable.stub', 'MongoDB\\Driver\\BulkWrite' => 'mongodb/BulkWrite.stub', 'MongoDB\\Driver\\ClientEncryption' => 'mongodb/ClientEncryption.stub', 'MongoDB\\Driver\\Command' => 'mongodb/Command.stub', 'MongoDB\\Driver\\Cursor' => 'mongodb/Cursor.stub', 'MongoDB\\Driver\\CursorId' => 'mongodb/CursorId.stub', 'MongoDB\\Driver\\CursorInterface' => 'mongodb/CursorInterface.stub', 'MongoDB\\Driver\\Exception\\AuthenticationException' => 'mongodb/Exception/AuthenticationException.stub', 'MongoDB\\Driver\\Exception\\BulkWriteException' => 'mongodb/Exception/BulkWriteException.stub', 'MongoDB\\Driver\\Exception\\CommandException' => 'mongodb/Exception/CommandException.stub', 'MongoDB\\Driver\\Exception\\ConnectionException' => 'mongodb/Exception/ConnectionException.stub', 'MongoDB\\Driver\\Exception\\ConnectionTimeoutException' => 'mongodb/Exception/ConnectionTimeoutException.stub', 'MongoDB\\Driver\\Exception\\EncryptionException' => 'mongodb/Exception/EncryptionException.stub', 'MongoDB\\Driver\\Exception\\Exception' => 'mongodb/Exception/Exception.stub', 'MongoDB\\Driver\\Exception\\ExecutionTimeoutException' => 'mongodb/Exception/ExecutionTimeoutException.stub', 'MongoDB\\Driver\\Exception\\InvalidArgumentException' => 'mongodb/Exception/InvalidArgumentException.stub', 'MongoDB\\Driver\\Exception\\LogicException' => 'mongodb/Exception/LogicException.stub', 'MongoDB\\Driver\\Exception\\RuntimeException' => 'mongodb/Exception/RuntimeException.stub', 'MongoDB\\Driver\\Exception\\SSLConnectionException' => 'mongodb/Exception/SSLConnectionException.stub', 'MongoDB\\Driver\\Exception\\ServerException' => 'mongodb/Exception/ServerException.stub', 'MongoDB\\Driver\\Exception\\UnexpectedValueException' => 'mongodb/Exception/UnexpectedValueException.stub', 'MongoDB\\Driver\\Exception\\WriteConcernException' => 'mongodb/Exception/WriteConcernException.stub', 'MongoDB\\Driver\\Exception\\WriteException' => 'mongodb/Exception/WriteException.stub', 'MongoDB\\Driver\\Manager' => 'mongodb/Manager.stub', 'MongoDB\\Driver\\Monitoring\\CommandFailedEvent' => 'mongodb/Monitoring/CommandFailedEvent.stub', 'MongoDB\\Driver\\Monitoring\\CommandStartedEvent' => 'mongodb/Monitoring/CommandStartedEvent.stub', 'MongoDB\\Driver\\Monitoring\\CommandSubscriber' => 'mongodb/Monitoring/CommandSubscriber.stub', 'MongoDB\\Driver\\Monitoring\\CommandSucceededEvent' => 'mongodb/Monitoring/CommandSucceededEvent.stub', 'MongoDB\\Driver\\Monitoring\\LogSubscriber' => 'mongodb/Monitoring/LogSubscriber.stub', 'MongoDB\\Driver\\Monitoring\\SDAMSubscriber' => 'mongodb/Monitoring/SDAMSubscriber.stub', 'MongoDB\\Driver\\Monitoring\\ServerChangedEvent' => 'mongodb/Monitoring/ServerChangedEvent.stub', 'MongoDB\\Driver\\Monitoring\\ServerClosedEvent' => 'mongodb/Monitoring/ServerClosedEvent.stub', 'MongoDB\\Driver\\Monitoring\\ServerHeartbeatFailedEvent' => 'mongodb/Monitoring/ServerHeartbeatFailedEvent.stub', 'MongoDB\\Driver\\Monitoring\\ServerHeartbeatStartedEvent' => 'mongodb/Monitoring/ServerHeartbeatStartedEvent.stub', 'MongoDB\\Driver\\Monitoring\\ServerHeartbeatSucceededEvent' => 'mongodb/Monitoring/ServerHeartbeatSucceededEvent.stub', 'MongoDB\\Driver\\Monitoring\\ServerOpeningEvent' => 'mongodb/Monitoring/ServerOpeningEvent.stub', 'MongoDB\\Driver\\Monitoring\\Subscriber' => 'mongodb/Monitoring/Subscriber.stub', 'MongoDB\\Driver\\Monitoring\\TopologyChangedEvent' => 'mongodb/Monitoring/TopologyChangedEvent.stub', 'MongoDB\\Driver\\Monitoring\\TopologyClosedEvent' => 'mongodb/Monitoring/TopologyClosedEvent.stub', 'MongoDB\\Driver\\Monitoring\\TopologyOpeningEvent' => 'mongodb/Monitoring/TopologyOpeningEvent.stub', 'MongoDB\\Driver\\Query' => 'mongodb/Query.stub', 'MongoDB\\Driver\\ReadConcern' => 'mongodb/ReadConcern.stub', 'MongoDB\\Driver\\ReadPreference' => 'mongodb/ReadPreference.stub', 'MongoDB\\Driver\\Server' => 'mongodb/Server.stub', 'MongoDB\\Driver\\ServerApi' => 'mongodb/ServerApi.stub', 'MongoDB\\Driver\\ServerDescription' => 'mongodb/ServerDescription.stub', 'MongoDB\\Driver\\Session' => 'mongodb/Session.stub', 'MongoDB\\Driver\\TopologyDescription' => 'mongodb/TopologyDescription.stub', 'MongoDB\\Driver\\WriteConcern' => 'mongodb/WriteConcern.stub', 'MongoDB\\Driver\\WriteConcernError' => 'mongodb/WriteConcernError.stub', 'MongoDB\\Driver\\WriteError' => 'mongodb/WriteError.stub', 'MongoDB\\Driver\\WriteResult' => 'mongodb/WriteResult.stub', 'MongoDate' => 'mongo/mongo.stub', 'MongoDuplicateKeyException' => 'mongo/mongo.stub', 'MongoException' => 'mongo/mongo.stub', 'MongoExecutionTimeoutException' => 'mongo/mongo.stub', 'MongoGridFS' => 'mongo/mongo.stub', 'MongoGridFSCursor' => 'mongo/mongo.stub', 'MongoGridFSException' => 'mongo/mongo.stub', 'MongoGridFSFile' => 'mongo/mongo.stub', 'MongoId' => 'mongo/mongo.stub', 'MongoInt32' => 'mongo/mongo.stub', 'MongoInt64' => 'mongo/mongo.stub', 'MongoLog' => 'mongo/mongo.stub', 'MongoMaxKey' => 'mongo/mongo.stub', 'MongoMinKey' => 'mongo/mongo.stub', 'MongoPool' => 'mongo/mongo.stub', 'MongoProtocolException' => 'mongo/mongo.stub', 'MongoRegex' => 'mongo/mongo.stub', 'MongoResultException' => 'mongo/mongo.stub', 'MongoTimestamp' => 'mongo/mongo.stub', 'MongoUpdateBatch' => 'mongo/mongo.stub', 'MongoWriteBatch' => 'mongo/mongo.stub', 'MongoWriteConcernException' => 'mongo/mongo.stub', 'Mosquitto\\Client' => 'mosquitto-php/mosquitto-php.stub', 'Mosquitto\\Exception' => 'mosquitto-php/mosquitto-php.stub', 'Mosquitto\\Message' => 'mosquitto-php/mosquitto-php.stub', 'MultipleIterator' => 'SPL/SPL_c1.stub', 'NoRewindIterator' => 'SPL/SPL.stub', 'Normalizer' => 'intl/intl.stub', 'NumberFormatter' => 'intl/intl.stub', 'OAuth' => 'oauth/oauth.stub', 'OAuthException' => 'oauth/oauth.stub', 'OAuthProvider' => 'oauth/oauth.stub', 'OCICollection' => 'oci8/oci8v3.stub', 'OCILob' => 'oci8/oci8v3.stub', 'OCI_Collection' => 'oci8/oci8.stub', 'OCI_Lob' => 'oci8/oci8.stub', 'OpenSSLAsymmetricKey' => 'openssl/openssl.stub', 'OpenSSLCertificate' => 'openssl/openssl.stub', 'OpenSSLCertificateSigningRequest' => 'openssl/openssl.stub', 'OutOfBoundsException' => 'SPL/SPL.stub', 'OutOfRangeException' => 'SPL/SPL.stub', 'OuterIterator' => 'SPL/SPL.stub', 'OverflowException' => 'SPL/SPL.stub', 'Override' => 'Core/Core_c.stub', 'OwsrequestObj' => 'mapscript/mapscript.stub', 'PDFlib' => 'pdflib/PDFlib.stub', 'PDFlibException' => 'pdflib/PDFlib.stub', 'PDO' => 'PDO/PDO.stub', 'PDOException' => 'PDO/PDO.stub', 'PDORow' => 'PDO/PDO.stub', 'PDOStatement' => 'PDO/PDO.stub', 'PSpell\\Config' => 'pspell/pspell_c.stub', 'PSpell\\Dictionary' => 'pspell/pspell_c.stub', 'ParentIterator' => 'SPL/SPL.stub', 'Parle\\ErrorInfo' => 'Parle/ErrorInfo.stub', 'Parle\\Lexer' => 'Parle/Lexer.stub', 'Parle\\LexerException' => 'Parle/LexerException.stub', 'Parle\\Parser' => 'Parle/Parser.stub', 'Parle\\ParserException' => 'Parle/ParserException.stub', 'Parle\\RLexer' => 'Parle/RLexer.stub', 'Parle\\RParser' => 'Parle/RParser.stub', 'Parle\\Stack' => 'Parle/Stack.stub', 'Parle\\Token' => 'Parle/Token.stub', 'ParseError' => 'Core/Core_c.stub', 'Pcntl\\QosClass' => 'pcntl/pcntl_c.stub', 'Pdo\\Mysql' => 'PDO/PDO.stub', 'Pdo\\Sqlite' => 'PDO/PDO.stub', 'PgSql\\Connection' => 'pgsql/pgsql_c.stub', 'PgSql\\Lob' => 'pgsql/pgsql_c.stub', 'PgSql\\Result' => 'pgsql/pgsql_c.stub', 'Phar' => 'Phar/Phar.stub', 'PharData' => 'Phar/Phar.stub', 'PharException' => 'Phar/Phar.stub', 'PharFileInfo' => 'Phar/Phar.stub', 'PhpToken' => 'tokenizer/PhpToken.stub', 'Pool' => 'pthreads/pthreads.stub', 'PropertyHookType' => 'Reflection/PropertyHookType.stub', 'RRDCreator' => 'rrd/rrd.stub', 'RRDGraph' => 'rrd/rrd.stub', 'RRDUpdater' => 'rrd/rrd.stub', 'Random\\BrokenRandomEngineError' => 'random/random.stub', 'Random\\CryptoSafeEngine' => 'random/random.stub', 'Random\\Engine' => 'random/random.stub', 'Random\\Engine\\Mt19937' => 'random/random.stub', 'Random\\Engine\\PcgOneseq128XslRr64' => 'random/random.stub', 'Random\\Engine\\Secure' => 'random/random.stub', 'Random\\Engine\\Xoshiro256StarStar' => 'random/random.stub', 'Random\\IntervalBoundary' => 'random/random.stub', 'Random\\RandomError' => 'random/random.stub', 'Random\\RandomException' => 'random/random.stub', 'Random\\Randomizer' => 'random/random.stub', 'RangeException' => 'SPL/SPL.stub', 'RarArchive' => 'rar/rar.stub', 'RarEntry' => 'rar/rar.stub', 'RarException' => 'rar/rar.stub', 'RdKafka' => 'rdkafka/RdKafka.stub', 'RdKafka\\Conf' => 'rdkafka/RdKafka/Conf.stub', 'RdKafka\\Consumer' => 'rdkafka/RdKafka/Consumer.stub', 'RdKafka\\ConsumerTopic' => 'rdkafka/RdKafka/ConsumerTopic.stub', 'RdKafka\\Exception' => 'rdkafka/RdKafka/Exception.stub', 'RdKafka\\KafkaConsumer' => 'rdkafka/RdKafka/KafkaConsumer.stub', 'RdKafka\\KafkaConsumerTopic' => 'rdkafka/RdKafka/KafkaConsumerTopic.stub', 'RdKafka\\KafkaErrorException' => 'rdkafka/RdKafka/KafkaErrorException.stub', 'RdKafka\\Message' => 'rdkafka/RdKafka/Message.stub', 'RdKafka\\Metadata' => 'rdkafka/RdKafka/Metadata.stub', 'RdKafka\\Metadata\\Broker' => 'rdkafka/RdKafka/Metadata/Broker.stub', 'RdKafka\\Metadata\\Collection' => 'rdkafka/RdKafka/Metadata/Collection.stub', 'RdKafka\\Metadata\\Partition' => 'rdkafka/RdKafka/Metadata/Partition.stub', 'RdKafka\\Metadata\\Topic' => 'rdkafka/RdKafka/Metadata/Topic.stub', 'RdKafka\\Producer' => 'rdkafka/RdKafka/Producer.stub', 'RdKafka\\ProducerTopic' => 'rdkafka/RdKafka/ProducerTopic.stub', 'RdKafka\\Queue' => 'rdkafka/RdKafka/Queue.stub', 'RdKafka\\Topic' => 'rdkafka/RdKafka/Topic.stub', 'RdKafka\\TopicConf' => 'rdkafka/RdKafka/TopicConf.stub', 'RdKafka\\TopicPartition' => 'rdkafka/RdKafka/TopicPartition.stub', 'RecursiveArrayIterator' => 'SPL/SPL.stub', 'RecursiveCachingIterator' => 'SPL/SPL.stub', 'RecursiveCallbackFilterIterator' => 'SPL/SPL.stub', 'RecursiveDirectoryIterator' => 'SPL/SPL_c1.stub', 'RecursiveFilterIterator' => 'SPL/SPL.stub', 'RecursiveIterator' => 'SPL/SPL.stub', 'RecursiveIteratorIterator' => 'SPL/SPL.stub', 'RecursiveRegexIterator' => 'SPL/SPL.stub', 'RecursiveTreeIterator' => 'SPL/SPL.stub', 'Redis' => 'redis/Redis.stub', 'RedisArray' => 'redis/RedisArray.stub', 'RedisCluster' => 'redis/RedisCluster.stub', 'RedisClusterException' => 'redis/RedisCluster.stub', 'RedisException' => 'redis/Redis.stub', 'RedisSentinel' => 'redis/RedisSentinel.stub', 'Reflection' => 'Reflection/Reflection.stub', 'ReflectionAttribute' => 'Reflection/ReflectionAttribute.stub', 'ReflectionClass' => 'Reflection/ReflectionClass.stub', 'ReflectionClassConstant' => 'Reflection/ReflectionClassConstant.stub', 'ReflectionConstant' => 'Reflection/ReflectionConstant.stub', 'ReflectionEnum' => 'Reflection/ReflectionEnum.stub', 'ReflectionEnumBackedCase' => 'Reflection/ReflectionEnumBackedCase.stub', 'ReflectionEnumUnitCase' => 'Reflection/ReflectionEnumUnitCase.stub', 'ReflectionException' => 'Reflection/ReflectionException.stub', 'ReflectionExtension' => 'Reflection/ReflectionExtension.stub', 'ReflectionFiber' => 'Reflection/ReflectionFiber.stub', 'ReflectionFunction' => 'Reflection/ReflectionFunction.stub', 'ReflectionFunctionAbstract' => 'Reflection/ReflectionFunctionAbstract.stub', 'ReflectionGenerator' => 'Reflection/ReflectionGenerator.stub', 'ReflectionIntersectionType' => 'Reflection/ReflectionIntersectionType.stub', 'ReflectionMethod' => 'Reflection/ReflectionMethod.stub', 'ReflectionNamedType' => 'Reflection/ReflectionNamedType.stub', 'ReflectionObject' => 'Reflection/ReflectionObject.stub', 'ReflectionParameter' => 'Reflection/ReflectionParameter.stub', 'ReflectionProperty' => 'Reflection/ReflectionProperty.stub', 'ReflectionReference' => 'Reflection/ReflectionReference.stub', 'ReflectionType' => 'Reflection/ReflectionType.stub', 'ReflectionUnionType' => 'Reflection/ReflectionUnionType.stub', 'ReflectionZendExtension' => 'Reflection/ReflectionZendExtension.stub', 'Reflector' => 'Reflection/Reflector.stub', 'RegexIterator' => 'SPL/SPL.stub', 'Relay\\Cluster' => 'relay/Cluster.stub', 'Relay\\Event' => 'relay/Event.stub', 'Relay\\Event\\Flushed' => 'relay/Events.stub', 'Relay\\Event\\Invalidated' => 'relay/Events.stub', 'Relay\\Exception' => 'relay/Exception.stub', 'Relay\\KeyType' => 'relay/KeyType.stub', 'Relay\\Relay' => 'relay/Relay.stub', 'Relay\\Sentinel' => 'relay/Sentinel.stub', 'Relay\\Table' => 'relay/Table.stub', 'RequestParseBodyException' => 'Core/Core_c.stub', 'ResourceBundle' => 'intl/intl.stub', 'ReturnTypeWillChange' => 'Core/Core_c.stub', 'RoundingMode' => 'standard/standard_10.stub', 'RuntimeException' => 'SPL/SPL.stub', 'SNMP' => 'snmp/snmp.stub', 'SNMPException' => 'snmp/snmp.stub', 'SQLite3' => 'sqlite3/sqlite3.stub', 'SQLite3Exception' => 'sqlite3/sqlite3.stub', 'SQLite3Result' => 'sqlite3/sqlite3.stub', 'SQLite3Stmt' => 'sqlite3/sqlite3.stub', 'SQLiteDatabase' => 'SQLite/SQLite.stub', 'SQLiteException' => 'SQLite/SQLite.stub', 'SQLiteResult' => 'SQLite/SQLite.stub', 'SQLiteUnbuffered' => 'SQLite/SQLite.stub', 'SVM' => 'svm/SVM.stub', 'SVMModel' => 'svm/SVMModel.stub', 'SWFAction' => 'ming/ming.stub', 'SWFBitmap' => 'ming/ming.stub', 'SWFButton' => 'ming/ming.stub', 'SWFDisplayItem' => 'ming/ming.stub', 'SWFFill' => 'ming/ming.stub', 'SWFFont' => 'ming/ming.stub', 'SWFFontChar' => 'ming/ming.stub', 'SWFGradient' => 'ming/ming.stub', 'SWFMorph' => 'ming/ming.stub', 'SWFMovie' => 'ming/ming.stub', 'SWFShape' => 'ming/ming.stub', 'SWFSound' => 'ming/ming.stub', 'SWFSoundInstance' => 'ming/ming.stub', 'SWFSprite' => 'ming/ming.stub', 'SWFText' => 'ming/ming.stub', 'SWFTextField' => 'ming/ming.stub', 'SWFVideoStream' => 'ming/ming.stub', 'Saxon\\SaxonProcessor' => 'SaxonC/SaxonC.stub', 'Saxon\\SchemaValidator' => 'SaxonC/SaxonC.stub', 'Saxon\\XPathProcessor' => 'SaxonC/SaxonC.stub', 'Saxon\\XQueryProcessor' => 'SaxonC/SaxonC.stub', 'Saxon\\XdmAtomicValue' => 'SaxonC/SaxonC.stub', 'Saxon\\XdmItem' => 'SaxonC/SaxonC.stub', 'Saxon\\XdmNode' => 'SaxonC/SaxonC.stub', 'Saxon\\XdmValue' => 'SaxonC/SaxonC.stub', 'Saxon\\Xslt30Processor' => 'SaxonC/SaxonC.stub', 'Saxon\\XsltProcessor' => 'SaxonC/SaxonC.stub', 'SeekableIterator' => 'SPL/SPL.stub', 'SensitiveParameter' => 'Core/Core_c.stub', 'SensitiveParameterValue' => 'Core/Core_c.stub', 'Serializable' => 'Core/Core_c.stub', 'SessionHandler' => 'session/SessionHandler.stub', 'SessionHandlerInterface' => 'session/SessionHandler.stub', 'SessionIdInterface' => 'session/SessionHandler.stub', 'SessionUpdateTimestampHandlerInterface' => 'session/SessionHandler.stub', 'Shmop' => 'shmop/shmop.stub', 'SimdJsonException' => 'simdjson/simdjson.stub', 'SimdJsonValueError' => 'simdjson/simdjson.stub', 'SimpleKafkaClient' => 'simple_kafka_client/SimpleKafkaClient.stub', 'SimpleKafkaClient\\Configuration' => 'simple_kafka_client/SimpleKafkaClient/Configuration.stub', 'SimpleKafkaClient\\Consumer' => 'simple_kafka_client/SimpleKafkaClient/Consumer.stub', 'SimpleKafkaClient\\ConsumerTopic' => 'simple_kafka_client/SimpleKafkaClient/Topic.stub', 'SimpleKafkaClient\\Exception' => 'simple_kafka_client/SimpleKafkaClient/Exception.stub', 'SimpleKafkaClient\\KafkaErrorException' => 'simple_kafka_client/SimpleKafkaClient/KafkaErrorException.stub', 'SimpleKafkaClient\\Message' => 'simple_kafka_client/SimpleKafkaClient/Message.stub', 'SimpleKafkaClient\\Metadata' => 'simple_kafka_client/SimpleKafkaClient/Metadata.stub', 'SimpleKafkaClient\\Metadata\\Broker' => 'simple_kafka_client/SimpleKafkaClient/Metadata/Broker.stub', 'SimpleKafkaClient\\Metadata\\Collection' => 'simple_kafka_client/SimpleKafkaClient/Metadata/Collection.stub', 'SimpleKafkaClient\\Metadata\\Partition' => 'simple_kafka_client/SimpleKafkaClient/Metadata/Partition.stub', 'SimpleKafkaClient\\Metadata\\Topic' => 'simple_kafka_client/SimpleKafkaClient/Metadata/Topic.stub', 'SimpleKafkaClient\\Producer' => 'simple_kafka_client/SimpleKafkaClient/Producer.stub', 'SimpleKafkaClient\\ProducerTopic' => 'simple_kafka_client/SimpleKafkaClient/Topic.stub', 'SimpleKafkaClient\\Topic' => 'simple_kafka_client/SimpleKafkaClient/Topic.stub', 'SimpleKafkaClient\\TopicPartition' => 'simple_kafka_client/SimpleKafkaClient/TopicPartition.stub', 'SimpleXMLElement' => 'SimpleXML/SimpleXML.stub', 'SimpleXMLIterator' => 'SimpleXML/SimpleXML.stub', 'SoapClient' => 'soap/soap.stub', 'SoapFault' => 'soap/soap.stub', 'SoapHeader' => 'soap/soap.stub', 'SoapParam' => 'soap/soap.stub', 'SoapServer' => 'soap/soap.stub', 'SoapVar' => 'soap/soap.stub', 'Soap\\Sdl' => 'soap/soap_n.stub', 'Soap\\Url' => 'soap/soap_n.stub', 'Socket' => 'sockets/sockets.stub', 'SodiumException' => 'sodium/sodium.stub', 'SolrClient' => 'solr/SolrClient.stub', 'SolrClientException' => 'solr/Exceptions/SolrClientException.stub', 'SolrCollapseFunction' => 'solr/Queries/SolrCollapseFunction.stub', 'SolrDisMaxQuery' => 'solr/Queries/SolrDisMaxQuery.stub', 'SolrDocument' => 'solr/Documents/SolrDocument.stub', 'SolrDocumentField' => 'solr/Documents/SolrDocumentField.stub', 'SolrException' => 'solr/Exceptions/SolrException.stub', 'SolrGenericResponse' => 'solr/Responses/SolrGenericResponse.stub', 'SolrIllegalArgumentException' => 'solr/Exceptions/SolrIllegalArgumentException.stub', 'SolrIllegalOperationException' => 'solr/Exceptions/SolrIllegalOperationException.stub', 'SolrInputDocument' => 'solr/Documents/SolrInputDocument.stub', 'SolrMissingMandatoryParameterException' => 'solr/Exceptions/SolrMissingMandatoryParameterException.stub', 'SolrModifiableParams' => 'solr/Queries/SolrModifiableParams.stub', 'SolrObject' => 'solr/Utils/SolrObject.stub', 'SolrParams' => 'solr/Queries/SolrParams.stub', 'SolrPingResponse' => 'solr/Responses/SolrPingResponse.stub', 'SolrQuery' => 'solr/Queries/SolrQuery.stub', 'SolrQueryResponse' => 'solr/Responses/SolrQueryResponse.stub', 'SolrResponse' => 'solr/Responses/SolrResponse.stub', 'SolrServerException' => 'solr/Exceptions/SolrServerException.stub', 'SolrUpdateResponse' => 'solr/Responses/SolrUpdateResponse.stub', 'SolrUtils' => 'solr/Utils/SolrUtils.stub', 'SplBool' => 'SplType/SplType.stub', 'SplDoublyLinkedList' => 'SPL/SPL_c1.stub', 'SplEnum' => 'SplType/SplType.stub', 'SplFileInfo' => 'SPL/SPL_c1.stub', 'SplFileObject' => 'SPL/SPL_c1.stub', 'SplFixedArray' => 'SPL/SPL_c1.stub', 'SplFloat' => 'SplType/SplType.stub', 'SplHeap' => 'SPL/SPL_c1.stub', 'SplInt' => 'SplType/SplType.stub', 'SplMaxHeap' => 'SPL/SPL_c1.stub', 'SplMinHeap' => 'SPL/SPL_c1.stub', 'SplObjectStorage' => 'SPL/SPL_c1.stub', 'SplObserver' => 'SPL/SPL_c1.stub', 'SplPriorityQueue' => 'SPL/SPL_c1.stub', 'SplQueue' => 'SPL/SPL_c1.stub', 'SplStack' => 'SPL/SPL_c1.stub', 'SplString' => 'SplType/SplType.stub', 'SplSubject' => 'SPL/SPL_c1.stub', 'SplTempFileObject' => 'SPL/SPL_c1.stub', 'SplType' => 'SplType/SplType.stub', 'Spoofchecker' => 'intl/intl.stub', 'Stomp' => 'stomp/stomp.stub', 'StompException' => 'stomp/stomp.stub', 'StompFrame' => 'stomp/stomp.stub', 'StreamBucket' => 'standard/standard_0.stub', 'Stringable' => 'Core/Core_c.stub', 'Svn' => 'svn/svn.stub', 'SvnNode' => 'svn/svn.stub', 'SvnWc' => 'svn/svn.stub', 'SvnWcSchedule' => 'svn/svn.stub', 'Swoole\\Atomic' => 'swoole/Swoole/Atomic.stub', 'Swoole\\Atomic\\Long' => 'swoole/Swoole/Atomic/Long.stub', 'Swoole\\Client' => 'swoole/Swoole/Client.stub', 'Swoole\\Client\\Exception' => 'swoole/Swoole/Client/Exception.stub', 'Swoole\\Connection\\Iterator' => 'swoole/Swoole/Connection/Iterator.stub', 'Swoole\\Coroutine' => 'swoole/Swoole/Coroutine.stub', 'Swoole\\Coroutine\\Channel' => 'swoole/Swoole/Coroutine/Channel.stub', 'Swoole\\Coroutine\\Client' => 'swoole/Swoole/Coroutine/Client.stub', 'Swoole\\Coroutine\\Context' => 'swoole/Swoole/Coroutine/Context.stub', 'Swoole\\Coroutine\\Curl\\Exception' => 'swoole/Swoole/Coroutine/Curl/Exception.stub', 'Swoole\\Coroutine\\Http2\\Client' => 'swoole/Swoole/Coroutine/Http2/Client.stub', 'Swoole\\Coroutine\\Http2\\Client\\Exception' => 'swoole/Swoole/Coroutine/Http2/Client/Exception.stub', 'Swoole\\Coroutine\\Http\\Client' => 'swoole/Swoole/Coroutine/Http/Client.stub', 'Swoole\\Coroutine\\Http\\Client\\Exception' => 'swoole/Swoole/Coroutine/Http/Client/Exception.stub', 'Swoole\\Coroutine\\Http\\Server' => 'swoole/Swoole/Coroutine/Http/Server.stub', 'Swoole\\Coroutine\\Iterator' => 'swoole/Swoole/Coroutine/Iterator.stub', 'Swoole\\Coroutine\\MySQL' => 'swoole/Swoole/Coroutine/MySQL.stub', 'Swoole\\Coroutine\\MySQL\\Exception' => 'swoole/Swoole/Coroutine/MySQL/Exception.stub', 'Swoole\\Coroutine\\MySQL\\Statement' => 'swoole/Swoole/Coroutine/MySQL/Statement.stub', 'Swoole\\Coroutine\\Redis' => 'swoole/Swoole/Coroutine/Redis.stub', 'Swoole\\Coroutine\\Scheduler' => 'swoole/Swoole/Coroutine/Scheduler.stub', 'Swoole\\Coroutine\\Socket' => 'swoole/Swoole/Coroutine/Socket.stub', 'Swoole\\Coroutine\\Socket\\Exception' => 'swoole/Swoole/Coroutine/Socket/Exception.stub', 'Swoole\\Coroutine\\System' => 'swoole/Swoole/Coroutine/System.stub', 'Swoole\\Error' => 'swoole/Swoole/Error.stub', 'Swoole\\Event' => 'swoole/Swoole/Event.stub', 'Swoole\\Exception' => 'swoole/Swoole/Exception.stub', 'Swoole\\ExitException' => 'swoole/Swoole/ExitException.stub', 'Swoole\\Http2\\Request' => 'swoole/Swoole/Http2/Request.stub', 'Swoole\\Http2\\Response' => 'swoole/Swoole/Http2/Response.stub', 'Swoole\\Http\\Request' => 'swoole/Swoole/Http/Request.stub', 'Swoole\\Http\\Response' => 'swoole/Swoole/Http/Response.stub', 'Swoole\\Http\\Server' => 'swoole/Swoole/Http/Server.stub', 'Swoole\\Lock' => 'swoole/Swoole/Lock.stub', 'Swoole\\Process' => 'swoole/Swoole/Process.stub', 'Swoole\\Process\\Pool' => 'swoole/Swoole/Process/Pool.stub', 'Swoole\\Redis\\Server' => 'swoole/Swoole/Redis/Server.stub', 'Swoole\\Runtime' => 'swoole/Swoole/Runtime.stub', 'Swoole\\Server' => 'swoole/Swoole/Server.stub', 'Swoole\\Server\\Event' => 'swoole/Swoole/Server/Event.stub', 'Swoole\\Server\\Packet' => 'swoole/Swoole/Server/Packet.stub', 'Swoole\\Server\\PipeMessage' => 'swoole/Swoole/Server/PipeMessage.stub', 'Swoole\\Server\\Port' => 'swoole/Swoole/Server/Port.stub', 'Swoole\\Server\\StatusInfo' => 'swoole/Swoole/Server/StatusInfo.stub', 'Swoole\\Server\\Task' => 'swoole/Swoole/Server/Task.stub', 'Swoole\\Server\\TaskResult' => 'swoole/Swoole/Server/TaskResult.stub', 'Swoole\\Table' => 'swoole/Swoole/Table.stub', 'Swoole\\Timer' => 'swoole/Swoole/Timer.stub', 'Swoole\\Timer\\Iterator' => 'swoole/Swoole/Timer/Iterator.stub', 'Swoole\\WebSocket\\CloseFrame' => 'swoole/Swoole/WebSocket/CloseFrame.stub', 'Swoole\\WebSocket\\Frame' => 'swoole/Swoole/WebSocket/Frame.stub', 'Swoole\\WebSocket\\Server' => 'swoole/Swoole/WebSocket/Server.stub', 'SyncEvent' => 'sync/sync.stub', 'SyncMutex' => 'sync/sync.stub', 'SyncReaderWriter' => 'sync/sync.stub', 'SyncSemaphore' => 'sync/sync.stub', 'SyncSharedMemory' => 'sync/sync.stub', 'SysvMessageQueue' => 'sysvmsg/sysvmsg.stub', 'SysvSemaphore' => 'sysvsem/sysvsem.stub', 'SysvSharedMemory' => 'sysvshm/sysvshm.stub', 'Thread' => 'pthreads/pthreads.stub', 'Threaded' => 'pthreads/pthreads.stub', 'Throwable' => 'Core/Core_c.stub', 'Transliterator' => 'intl/intl.stub', 'Traversable' => 'Core/Core_c.stub', 'TypeError' => 'Core/Core_c.stub', 'UConverter' => 'intl/intl.stub', 'UV' => 'uv/UV.stub', 'UVAddrinfo' => 'uv/UV.stub', 'UVAsync' => 'uv/UV.stub', 'UVCheck' => 'uv/UV.stub', 'UVFs' => 'uv/UV.stub', 'UVFsEvent' => 'uv/UV.stub', 'UVFsPoll' => 'uv/UV.stub', 'UVIdle' => 'uv/UV.stub', 'UVLock' => 'uv/UV.stub', 'UVLoop' => 'uv/UV.stub', 'UVPipe' => 'uv/UV.stub', 'UVPoll' => 'uv/UV.stub', 'UVPrepare' => 'uv/UV.stub', 'UVProcess' => 'uv/UV.stub', 'UVSignal' => 'uv/UV.stub', 'UVSockAddr' => 'uv/UV.stub', 'UVSockAddrIPv4' => 'uv/UV.stub', 'UVSockAddrIPv6' => 'uv/UV.stub', 'UVStdio' => 'uv/UV.stub', 'UVStream' => 'uv/UV.stub', 'UVTcp' => 'uv/UV.stub', 'UVTimer' => 'uv/UV.stub', 'UVTty' => 'uv/UV.stub', 'UVUdp' => 'uv/UV.stub', 'UVWork' => 'uv/UV.stub', 'UnderflowException' => 'SPL/SPL.stub', 'UnexpectedValueException' => 'SPL/SPL.stub', 'UnhandledMatchError' => 'Core/Core_c.stub', 'UnitEnum' => 'Core/Core_c.stub', 'V8Js' => 'v8js/v8js.stub', 'V8JsMemoryLimitException' => 'v8js/v8js.stub', 'V8JsScriptException' => 'v8js/v8js.stub', 'V8JsTimeLimitException' => 'v8js/v8js.stub', 'VARIANT' => 'com_dotnet/com_dotnet.stub', 'ValueError' => 'Core/Core_c.stub', 'Volatile' => 'pthreads/pthreads.stub', 'Vtiful\\Kernel\\Excel' => 'xlswriter/xlswriter.stub', 'Vtiful\\Kernel\\Format' => 'xlswriter/xlswriter.stub', 'WeakMap' => 'Core/Core_c.stub', 'WeakReference' => 'Core/Core_c.stub', 'Worker' => 'pthreads/pthreads.stub', 'XMLParser' => 'xml/xml.stub', 'XMLReader' => 'xmlreader/xmlreader.stub', 'XMLWriter' => 'xmlwriter/xmlwriter.stub', 'XSLTProcessor' => 'xsl/xsl.stub', 'XXTEA' => 'xxtea/xxtea.stub', 'Yaf\\Action_Abstract' => 'yaf/yaf_namespace.stub', 'Yaf\\Application' => 'yaf/yaf_namespace.stub', 'Yaf\\Bootstrap_Abstract' => 'yaf/yaf_namespace.stub', 'Yaf\\Config\\Ini' => 'yaf/yaf_namespace.stub', 'Yaf\\Config\\Simple' => 'yaf/yaf_namespace.stub', 'Yaf\\Config_Abstract' => 'yaf/yaf_namespace.stub', 'Yaf\\Controller_Abstract' => 'yaf/yaf_namespace.stub', 'Yaf\\Dispatcher' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception\\DispatchFailed' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception\\LoadFailed' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception\\LoadFailed\\Action' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception\\LoadFailed\\Controller' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception\\LoadFailed\\Module' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception\\LoadFailed\\View' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception\\RouterFailed' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception\\StartupError' => 'yaf/yaf_namespace.stub', 'Yaf\\Exception\\TypeError' => 'yaf/yaf_namespace.stub', 'Yaf\\Loader' => 'yaf/yaf_namespace.stub', 'Yaf\\Plugin_Abstract' => 'yaf/yaf_namespace.stub', 'Yaf\\Registry' => 'yaf/yaf_namespace.stub', 'Yaf\\Request\\Http' => 'yaf/yaf_namespace.stub', 'Yaf\\Request\\Simple' => 'yaf/yaf_namespace.stub', 'Yaf\\Request_Abstract' => 'yaf/yaf_namespace.stub', 'Yaf\\Response\\Cli' => 'yaf/yaf_namespace.stub', 'Yaf\\Response\\Http' => 'yaf/yaf_namespace.stub', 'Yaf\\Response_Abstract' => 'yaf/yaf_namespace.stub', 'Yaf\\Route\\Map' => 'yaf/yaf_namespace.stub', 'Yaf\\Route\\Regex' => 'yaf/yaf_namespace.stub', 'Yaf\\Route\\Rewrite' => 'yaf/yaf_namespace.stub', 'Yaf\\Route\\Simple' => 'yaf/yaf_namespace.stub', 'Yaf\\Route\\Supervar' => 'yaf/yaf_namespace.stub', 'Yaf\\Route_Interface' => 'yaf/yaf_namespace.stub', 'Yaf\\Route_Static' => 'yaf/yaf_namespace.stub', 'Yaf\\Router' => 'yaf/yaf_namespace.stub', 'Yaf\\Session' => 'yaf/yaf_namespace.stub', 'Yaf\\View\\Simple' => 'yaf/yaf_namespace.stub', 'Yaf\\View_Interface' => 'yaf/yaf_namespace.stub', 'Yaf_Action_Abstract' => 'yaf/yaf.stub', 'Yaf_Application' => 'yaf/yaf.stub', 'Yaf_Bootstrap_Abstract' => 'yaf/yaf.stub', 'Yaf_Config_Abstract' => 'yaf/yaf.stub', 'Yaf_Config_Ini' => 'yaf/yaf.stub', 'Yaf_Config_Simple' => 'yaf/yaf.stub', 'Yaf_Controller_Abstract' => 'yaf/yaf.stub', 'Yaf_Dispatcher' => 'yaf/yaf.stub', 'Yaf_Exception' => 'yaf/yaf.stub', 'Yaf_Exception_DispatchFailed' => 'yaf/yaf.stub', 'Yaf_Exception_LoadFailed' => 'yaf/yaf.stub', 'Yaf_Exception_LoadFailed_Action' => 'yaf/yaf.stub', 'Yaf_Exception_LoadFailed_Controller' => 'yaf/yaf.stub', 'Yaf_Exception_LoadFailed_Module' => 'yaf/yaf.stub', 'Yaf_Exception_LoadFailed_View' => 'yaf/yaf.stub', 'Yaf_Exception_RouterFailed' => 'yaf/yaf.stub', 'Yaf_Exception_StartupError' => 'yaf/yaf.stub', 'Yaf_Exception_TypeError' => 'yaf/yaf.stub', 'Yaf_Loader' => 'yaf/yaf.stub', 'Yaf_Plugin_Abstract' => 'yaf/yaf.stub', 'Yaf_Registry' => 'yaf/yaf.stub', 'Yaf_Request_Abstract' => 'yaf/yaf.stub', 'Yaf_Request_Http' => 'yaf/yaf.stub', 'Yaf_Request_Simple' => 'yaf/yaf.stub', 'Yaf_Response_Abstract' => 'yaf/yaf.stub', 'Yaf_Response_Cli' => 'yaf/yaf.stub', 'Yaf_Response_Http' => 'yaf/yaf.stub', 'Yaf_Route_Interface' => 'yaf/yaf.stub', 'Yaf_Route_Map' => 'yaf/yaf.stub', 'Yaf_Route_Regex' => 'yaf/yaf.stub', 'Yaf_Route_Rewrite' => 'yaf/yaf.stub', 'Yaf_Route_Simple' => 'yaf/yaf.stub', 'Yaf_Route_Static' => 'yaf/yaf.stub', 'Yaf_Route_Supervar' => 'yaf/yaf.stub', 'Yaf_Router' => 'yaf/yaf.stub', 'Yaf_Session' => 'yaf/yaf.stub', 'Yaf_View_Interface' => 'yaf/yaf.stub', 'Yaf_View_Simple' => 'yaf/yaf.stub', 'Yar_Client' => 'yar/yar.stub', 'Yar_Client_Exception' => 'yar/yar.stub', 'Yar_Client_Packager_Exception' => 'yar/yar.stub', 'Yar_Client_Protocol_Exception' => 'yar/yar.stub', 'Yar_Client_Transport_Exception' => 'yar/yar.stub', 'Yar_Concurrent_Client' => 'yar/yar.stub', 'Yar_Server' => 'yar/yar.stub', 'Yar_Server_Exception' => 'yar/yar.stub', 'Yar_Server_Output_Exception' => 'yar/yar.stub', 'Yar_Server_Packager_Exception' => 'yar/yar.stub', 'Yar_Server_Protocol_Exception' => 'yar/yar.stub', 'Yar_Server_Request_Exception' => 'yar/yar.stub', 'ZMQ' => 'zmq/zmq.stub', 'ZMQContext' => 'zmq/zmq.stub', 'ZMQContextException' => 'zmq/zmq.stub', 'ZMQDevice' => 'zmq/zmq.stub', 'ZMQDeviceException' => 'zmq/zmq.stub', 'ZMQException' => 'zmq/zmq.stub', 'ZMQPoll' => 'zmq/zmq.stub', 'ZMQPollException' => 'zmq/zmq.stub', 'ZMQSocket' => 'zmq/zmq.stub', 'ZMQSocketException' => 'zmq/zmq.stub', 'ZendAPI_Job' => 'zend/zend.stub', 'ZendAPI_Queue' => 'zend/zend.stub', 'ZipArchive' => 'zip/zip.stub', 'Zookeeper' => 'zookeeper/zookeeper.stub', 'ZookeeperAuthenticationException' => 'zookeeper/zookeeper.stub', 'ZookeeperConnectionException' => 'zookeeper/zookeeper.stub', 'ZookeeperException' => 'zookeeper/zookeeper.stub', 'ZookeeperMarshallingException' => 'zookeeper/zookeeper.stub', 'ZookeeperNoNodeException' => 'zookeeper/zookeeper.stub', 'ZookeeperOperationTimeoutException' => 'zookeeper/zookeeper.stub', 'ZookeeperSessionException' => 'zookeeper/zookeeper.stub', '__PHP_Incomplete_Class' => 'standard/standard_0.stub', '___PHPSTORM_HELPERS\\PS_UNRESERVE_PREFIX_static' => 'standard/_types.stub', '___PHPSTORM_HELPERS\\PS_UNRESERVE_PREFIX_this' => 'standard/_types.stub', '___PHPSTORM_HELPERS\\object' => 'standard/_types.stub', 'ast\\Metadata' => 'ast/ast.stub', 'ast\\Node' => 'ast/ast.stub', 'classObj' => 'mapscript/mapscript.stub', 'clusterObj' => 'mapscript/mapscript.stub', 'colorObj' => 'mapscript/mapscript.stub', 'com_exception' => 'com_dotnet/com_dotnet.stub', 'errorObj' => 'mapscript/mapscript.stub', 'ffmpeg_animated_gif' => 'ffmpeg/ffmpeg.stub', 'ffmpeg_frame' => 'ffmpeg/ffmpeg.stub', 'ffmpeg_movie' => 'ffmpeg/ffmpeg.stub', 'finfo' => 'fileinfo/fileinfo.stub', 'gnupg' => 'gnupg/gnupg.stub', 'gnupg_keylistiterator' => 'gnupg/gnupg.stub', 'gridObj' => 'mapscript/mapscript.stub', 'hashTableObj' => 'mapscript/mapscript.stub', 'http\\Client' => 'http/http3.stub', 'http\\Client\\Curl\\User' => 'http/http3.stub', 'http\\Client\\Request' => 'http/http3.stub', 'http\\Client\\Response' => 'http/http3.stub', 'http\\Cookie' => 'http/http3.stub', 'http\\Encoding\\Stream' => 'http/http3.stub', 'http\\Encoding\\Stream\\Debrotli' => 'http/http3.stub', 'http\\Encoding\\Stream\\Dechunk' => 'http/http3.stub', 'http\\Encoding\\Stream\\Deflate' => 'http/http3.stub', 'http\\Encoding\\Stream\\Enbrotli' => 'http/http3.stub', 'http\\Encoding\\Stream\\Inflate' => 'http/http3.stub', 'http\\Env' => 'http/http3.stub', 'http\\Env\\Request' => 'http/http3.stub', 'http\\Env\\Response' => 'http/http3.stub', 'http\\Env\\Url' => 'http/http3.stub', 'http\\Exception' => 'http/http3.stub', 'http\\Exception\\BadConversionException' => 'http/http3.stub', 'http\\Exception\\BadHeaderException' => 'http/http3.stub', 'http\\Exception\\BadMessageException' => 'http/http3.stub', 'http\\Exception\\BadMethodCallException' => 'http/http3.stub', 'http\\Exception\\BadQueryStringException' => 'http/http3.stub', 'http\\Exception\\BadUrlException' => 'http/http3.stub', 'http\\Exception\\InvalidArgumentException' => 'http/http3.stub', 'http\\Exception\\RuntimeException' => 'http/http3.stub', 'http\\Exception\\UnexpectedValueException' => 'http/http3.stub', 'http\\Header' => 'http/http3.stub', 'http\\Header\\Parser' => 'http/http3.stub', 'http\\Message' => 'http/http3.stub', 'http\\Message\\Body' => 'http/http3.stub', 'http\\Message\\Parser' => 'http/http3.stub', 'http\\Params' => 'http/http3.stub', 'http\\QueryString' => 'http/http3.stub', 'http\\Url' => 'http/http3.stub', 'imageObj' => 'mapscript/mapscript.stub', 'iterable' => 'Core/Core_c.stub', 'java' => 'zend/zend.stub', 'labelObj' => 'mapscript/mapscript.stub', 'labelcacheMemberObj' => 'mapscript/mapscript.stub', 'labelcacheObj' => 'mapscript/mapscript.stub', 'layerObj' => 'mapscript/mapscript.stub', 'legendObj' => 'mapscript/mapscript.stub', 'lineObj' => 'mapscript/mapscript.stub', 'mapObj' => 'mapscript/mapscript.stub', 'mysql_xdevapi\\BaseResult' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Collection' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\CollectionAdd' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\CollectionFind' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\CollectionModify' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\CollectionRemove' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\ColumnResult' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\CrudOperationBindable' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\CrudOperationLimitable' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\CrudOperationSkippable' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\CrudOperationSortable' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\DatabaseObject' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\DocResult' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Exception' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Executable' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\ExecutionStatus' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Expression' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Result' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\RowResult' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Schema' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\SchemaObject' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Session' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\SqlStatement' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\SqlStatementResult' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Statement' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Table' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\TableDelete' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\TableInsert' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\TableSelect' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\TableUpdate' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\Warning' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\XSession' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysqli' => 'mysqli/mysqli.stub', 'mysqli_driver' => 'mysqli/mysqli.stub', 'mysqli_result' => 'mysqli/mysqli.stub', 'mysqli_sql_exception' => 'mysqli/mysqli.stub', 'mysqli_stmt' => 'mysqli/mysqli.stub', 'mysqli_warning' => 'mysqli/mysqli.stub', 'newrelic\\DistributedTracePayload' => 'newrelic/newrelic.stub', 'outputformatObj' => 'mapscript/mapscript.stub', 'parallel\\Channel' => 'parallel/parallel/Channel.stub', 'parallel\\Channel\\Error' => 'parallel/parallel/Channel/Error.stub', 'parallel\\Channel\\Error\\Closed' => 'parallel/parallel/Channel/Error/Closed.stub', 'parallel\\Channel\\Error\\Existence' => 'parallel/parallel/Channel/Error/Existence.stub', 'parallel\\Channel\\Error\\IllegalValue' => 'parallel/parallel/Channel/Error/IllegalValue.stub', 'parallel\\Error' => 'parallel/parallel/Error.stub', 'parallel\\Events' => 'parallel/parallel/Events.stub', 'parallel\\Events\\Error' => 'parallel/parallel/Events/Error.stub', 'parallel\\Events\\Error\\Existence' => 'parallel/parallel/Events/Error/Existence.stub', 'parallel\\Events\\Error\\Timeout' => 'parallel/parallel/Events/Error/Timeout.stub', 'parallel\\Events\\Event' => 'parallel/parallel/Events/Event.stub', 'parallel\\Events\\Event\\Error' => 'parallel/parallel/Events/Event/Error.stub', 'parallel\\Events\\Event\\Type' => 'parallel/parallel/Events/Event/Type.stub', 'parallel\\Events\\Input' => 'parallel/parallel/Events/Input.stub', 'parallel\\Events\\Input\\Error' => 'parallel/parallel/Events/Input/Error.stub', 'parallel\\Events\\Input\\Error\\Existence' => 'parallel/parallel/Events/Input/Error/Existence.stub', 'parallel\\Events\\Input\\Error\\IllegalValue' => 'parallel/parallel/Events/Input/Error/IllegalValue.stub', 'parallel\\Future' => 'parallel/parallel/Future.stub', 'parallel\\Future\\Error' => 'parallel/parallel/Future/Error.stub', 'parallel\\Future\\Error\\Cancelled' => 'parallel/parallel/Future/Error/Cancelled.stub', 'parallel\\Future\\Error\\Foreign' => 'parallel/parallel/Future/Error/Foreign.stub', 'parallel\\Future\\Error\\Killed' => 'parallel/parallel/Future/Error/Killed.stub', 'parallel\\Runtime' => 'parallel/parallel/Runtime.stub', 'parallel\\Runtime\\Error' => 'parallel/parallel/Runtime/Error.stub', 'parallel\\Runtime\\Error\\Bootstrap' => 'parallel/parallel/Runtime/Error/Bootstrap.stub', 'parallel\\Runtime\\Error\\Closed' => 'parallel/parallel/Runtime/Error/Closed.stub', 'parallel\\Runtime\\Error\\IllegalFunction' => 'parallel/parallel/Runtime/Error/IllegalFunction.stub', 'parallel\\Runtime\\Error\\IllegalInstruction' => 'parallel/parallel/Runtime/Error/IllegalInstruction.stub', 'parallel\\Runtime\\Error\\IllegalParameter' => 'parallel/parallel/Runtime/Error/IllegalParameter.stub', 'parallel\\Runtime\\Error\\IllegalReturn' => 'parallel/parallel/Runtime/Error/IllegalReturn.stub', 'parallel\\Runtime\\Error\\IllegalVariable' => 'parallel/parallel/Runtime/Error/IllegalVariable.stub', 'parallel\\Runtime\\Error\\Killed' => 'parallel/parallel/Runtime/Error/Killed.stub', 'parallel\\Runtime\\Object\\Unavailable' => 'parallel/parallel/Runtime/Object/Unavailable.stub', 'parallel\\Runtime\\Type\\Unavailable' => 'parallel/parallel/Runtime/Type/Unavailable.stub', 'parallel\\Sync' => 'parallel/parallel/Sync.stub', 'parallel\\Sync\\Error' => 'parallel/parallel/Sync/Error.stub', 'parallel\\Sync\\Error\\IllegalValue' => 'parallel/parallel/Sync/Error/IllegalValue.stub', 'php_user_filter' => 'standard/standard_0.stub', 'pointObj' => 'mapscript/mapscript.stub', 'pq\\COPY' => 'pq/pq.stub', 'pq\\Cancel' => 'pq/pq.stub', 'pq\\Connection' => 'pq/pq.stub', 'pq\\Converter' => 'pq/pq.stub', 'pq\\Cursor' => 'pq/pq.stub', 'pq\\DateTime' => 'pq/pq.stub', 'pq\\Exception' => 'pq/pq.stub', 'pq\\Exception\\BadMethodCallException' => 'pq/pq.stub', 'pq\\Exception\\DomainException' => 'pq/pq.stub', 'pq\\Exception\\InvalidArgumentException' => 'pq/pq.stub', 'pq\\Exception\\RuntimeException' => 'pq/pq.stub', 'pq\\LOB' => 'pq/pq.stub', 'pq\\Result' => 'pq/pq.stub', 'pq\\Statement' => 'pq/pq.stub', 'pq\\Transaction' => 'pq/pq.stub', 'pq\\Types' => 'pq/pq.stub', 'projectionObj' => 'mapscript/mapscript.stub', 'querymapObj' => 'mapscript/mapscript.stub', 'rectObj' => 'mapscript/mapscript.stub', 'referenceMapObj' => 'mapscript/mapscript.stub', 'resultObj' => 'mapscript/mapscript.stub', 'scalebarObj' => 'mapscript/mapscript.stub', 'shapeObj' => 'mapscript/mapscript.stub', 'shapefileObj' => 'mapscript/mapscript.stub', 'stdClass' => 'Core/Core_c.stub', 'styleObj' => 'mapscript/mapscript.stub', 'symbolObj' => 'mapscript/mapscript.stub', 'tidy' => 'tidy/tidy.stub', 'tidyNode' => 'tidy/tidy.stub', 'webObj' => 'mapscript/mapscript.stub'); const FUNCTIONS = array('Brotli\\compress' => 'brotli/brotli.stub', 'Brotli\\compress_add' => 'brotli/brotli.stub', 'Brotli\\compress_init' => 'brotli/brotli.stub', 'Brotli\\uncompress' => 'brotli/brotli.stub', 'Brotli\\uncompress_add' => 'brotli/brotli.stub', 'Brotli\\uncompress_init' => 'brotli/brotli.stub', 'Dom\\import_simplexml' => 'dom/dom_n.stub', 'GEOSLineMerge' => 'geos/geos.stub', 'GEOSPolygonize' => 'geos/geos.stub', 'GEOSRelateMatch' => 'geos/geos.stub', 'GEOSSharedPaths' => 'geos/geos.stub', 'GEOSVersion' => 'geos/geos.stub', 'MongoDB\\BSON\\fromJSON' => 'mongodb/BSON/functions.stub', 'MongoDB\\BSON\\fromPHP' => 'mongodb/BSON/functions.stub', 'MongoDB\\BSON\\toCanonicalExtendedJSON' => 'mongodb/BSON/functions.stub', 'MongoDB\\BSON\\toJSON' => 'mongodb/BSON/functions.stub', 'MongoDB\\BSON\\toPHP' => 'mongodb/BSON/functions.stub', 'MongoDB\\BSON\\toRelaxedExtendedJSON' => 'mongodb/BSON/functions.stub', 'MongoDB\\Driver\\Monitoring\\addSubscriber' => 'mongodb/Monitoring/functions.stub', 'MongoDB\\Driver\\Monitoring\\removeSubscriber' => 'mongodb/Monitoring/functions.stub', 'OpenTelemetry\\Instrumentation\\hook' => 'opentelemetry/opentelemetry.stub', 'PDF_activate_item' => 'pdflib/PDFlib.stub', 'PDF_add_launchlink' => 'pdflib/PDFlib.stub', 'PDF_add_locallink' => 'pdflib/PDFlib.stub', 'PDF_add_nameddest' => 'pdflib/PDFlib.stub', 'PDF_add_note' => 'pdflib/PDFlib.stub', 'PDF_add_pdflink' => 'pdflib/PDFlib.stub', 'PDF_add_table_cell' => 'pdflib/PDFlib.stub', 'PDF_add_textflow' => 'pdflib/PDFlib.stub', 'PDF_add_thumbnail' => 'pdflib/PDFlib.stub', 'PDF_add_weblink' => 'pdflib/PDFlib.stub', 'PDF_arc' => 'pdflib/PDFlib.stub', 'PDF_arcn' => 'pdflib/PDFlib.stub', 'PDF_attach_file' => 'pdflib/PDFlib.stub', 'PDF_begin_document' => 'pdflib/PDFlib.stub', 'PDF_begin_font' => 'pdflib/PDFlib.stub', 'PDF_begin_glyph' => 'pdflib/PDFlib.stub', 'PDF_begin_item' => 'pdflib/PDFlib.stub', 'PDF_begin_layer' => 'pdflib/PDFlib.stub', 'PDF_begin_page' => 'pdflib/PDFlib.stub', 'PDF_begin_page_ext' => 'pdflib/PDFlib.stub', 'PDF_begin_pattern' => 'pdflib/PDFlib.stub', 'PDF_begin_template' => 'pdflib/PDFlib.stub', 'PDF_begin_template_ext' => 'pdflib/PDFlib.stub', 'PDF_circle' => 'pdflib/PDFlib.stub', 'PDF_clip' => 'pdflib/PDFlib.stub', 'PDF_close' => 'pdflib/PDFlib.stub', 'PDF_close_image' => 'pdflib/PDFlib.stub', 'PDF_close_pdi' => 'pdflib/PDFlib.stub', 'PDF_close_pdi_document' => 'pdflib/PDFlib.stub', 'PDF_close_pdi_page' => 'pdflib/PDFlib.stub', 'PDF_closepath' => 'pdflib/PDFlib.stub', 'PDF_closepath_fill_stroke' => 'pdflib/PDFlib.stub', 'PDF_closepath_stroke' => 'pdflib/PDFlib.stub', 'PDF_concat' => 'pdflib/PDFlib.stub', 'PDF_continue_text' => 'pdflib/PDFlib.stub', 'PDF_create_3dview' => 'pdflib/PDFlib.stub', 'PDF_create_action' => 'pdflib/PDFlib.stub', 'PDF_create_annotation' => 'pdflib/PDFlib.stub', 'PDF_create_bookmark' => 'pdflib/PDFlib.stub', 'PDF_create_field' => 'pdflib/PDFlib.stub', 'PDF_create_fieldgroup' => 'pdflib/PDFlib.stub', 'PDF_create_gstate' => 'pdflib/PDFlib.stub', 'PDF_create_pvf' => 'pdflib/PDFlib.stub', 'PDF_create_textflow' => 'pdflib/PDFlib.stub', 'PDF_curveto' => 'pdflib/PDFlib.stub', 'PDF_define_layer' => 'pdflib/PDFlib.stub', 'PDF_delete' => 'pdflib/PDFlib.stub', 'PDF_delete_pvf' => 'pdflib/PDFlib.stub', 'PDF_delete_table' => 'pdflib/PDFlib.stub', 'PDF_delete_textflow' => 'pdflib/PDFlib.stub', 'PDF_encoding_set_char' => 'pdflib/PDFlib.stub', 'PDF_end_document' => 'pdflib/PDFlib.stub', 'PDF_end_font' => 'pdflib/PDFlib.stub', 'PDF_end_glyph' => 'pdflib/PDFlib.stub', 'PDF_end_item' => 'pdflib/PDFlib.stub', 'PDF_end_layer' => 'pdflib/PDFlib.stub', 'PDF_end_page' => 'pdflib/PDFlib.stub', 'PDF_end_page_ext' => 'pdflib/PDFlib.stub', 'PDF_end_pattern' => 'pdflib/PDFlib.stub', 'PDF_end_template' => 'pdflib/PDFlib.stub', 'PDF_endpath' => 'pdflib/PDFlib.stub', 'PDF_fill' => 'pdflib/PDFlib.stub', 'PDF_fill_imageblock' => 'pdflib/PDFlib.stub', 'PDF_fill_pdfblock' => 'pdflib/PDFlib.stub', 'PDF_fill_stroke' => 'pdflib/PDFlib.stub', 'PDF_fill_textblock' => 'pdflib/PDFlib.stub', 'PDF_findfont' => 'pdflib/PDFlib.stub', 'PDF_fit_image' => 'pdflib/PDFlib.stub', 'PDF_fit_pdi_page' => 'pdflib/PDFlib.stub', 'PDF_fit_table' => 'pdflib/PDFlib.stub', 'PDF_fit_textflow' => 'pdflib/PDFlib.stub', 'PDF_fit_textline' => 'pdflib/PDFlib.stub', 'PDF_get_apiname' => 'pdflib/PDFlib.stub', 'PDF_get_buffer' => 'pdflib/PDFlib.stub', 'PDF_get_errmsg' => 'pdflib/PDFlib.stub', 'PDF_get_errnum' => 'pdflib/PDFlib.stub', 'PDF_get_majorversion' => 'pdflib/PDFlib.stub', 'PDF_get_minorversion' => 'pdflib/PDFlib.stub', 'PDF_get_option' => 'pdflib/PDFlib.stub', 'PDF_get_parameter' => 'pdflib/PDFlib.stub', 'PDF_get_pdi_parameter' => 'pdflib/PDFlib.stub', 'PDF_get_pdi_value' => 'pdflib/PDFlib.stub', 'PDF_get_string' => 'pdflib/PDFlib.stub', 'PDF_get_value' => 'pdflib/PDFlib.stub', 'PDF_info_font' => 'pdflib/PDFlib.stub', 'PDF_info_graphics' => 'pdflib/PDFlib.stub', 'PDF_info_image' => 'pdflib/PDFlib.stub', 'PDF_info_matchbox' => 'pdflib/PDFlib.stub', 'PDF_info_path' => 'pdflib/PDFlib.stub', 'PDF_info_pdi_page' => 'pdflib/PDFlib.stub', 'PDF_info_pvf' => 'pdflib/PDFlib.stub', 'PDF_info_table' => 'pdflib/PDFlib.stub', 'PDF_info_textflow' => 'pdflib/PDFlib.stub', 'PDF_info_textline' => 'pdflib/PDFlib.stub', 'PDF_initgraphics' => 'pdflib/PDFlib.stub', 'PDF_lineto' => 'pdflib/PDFlib.stub', 'PDF_load_3ddata' => 'pdflib/PDFlib.stub', 'PDF_load_font' => 'pdflib/PDFlib.stub', 'PDF_load_iccprofile' => 'pdflib/PDFlib.stub', 'PDF_load_image' => 'pdflib/PDFlib.stub', 'PDF_makespotcolor' => 'pdflib/PDFlib.stub', 'PDF_moveto' => 'pdflib/PDFlib.stub', 'PDF_new' => 'pdflib/PDFlib.stub', 'PDF_open_ccitt' => 'pdflib/PDFlib.stub', 'PDF_open_file' => 'pdflib/PDFlib.stub', 'PDF_open_image' => 'pdflib/PDFlib.stub', 'PDF_open_image_file' => 'pdflib/PDFlib.stub', 'PDF_open_memory_image' => 'pdflib/PDFlib.stub', 'PDF_open_pdi' => 'pdflib/PDFlib.stub', 'PDF_open_pdi_document' => 'pdflib/PDFlib.stub', 'PDF_open_pdi_page' => 'pdflib/PDFlib.stub', 'PDF_pcos_get_number' => 'pdflib/PDFlib.stub', 'PDF_pcos_get_stream' => 'pdflib/PDFlib.stub', 'PDF_pcos_get_string' => 'pdflib/PDFlib.stub', 'PDF_place_image' => 'pdflib/PDFlib.stub', 'PDF_place_pdi_page' => 'pdflib/PDFlib.stub', 'PDF_process_pdi' => 'pdflib/PDFlib.stub', 'PDF_rect' => 'pdflib/PDFlib.stub', 'PDF_restore' => 'pdflib/PDFlib.stub', 'PDF_resume_page' => 'pdflib/PDFlib.stub', 'PDF_rotate' => 'pdflib/PDFlib.stub', 'PDF_save' => 'pdflib/PDFlib.stub', 'PDF_scale' => 'pdflib/PDFlib.stub', 'PDF_set_border_color' => 'pdflib/PDFlib.stub', 'PDF_set_border_dash' => 'pdflib/PDFlib.stub', 'PDF_set_border_style' => 'pdflib/PDFlib.stub', 'PDF_set_gstate' => 'pdflib/PDFlib.stub', 'PDF_set_info' => 'pdflib/PDFlib.stub', 'PDF_set_layer_dependency' => 'pdflib/PDFlib.stub', 'PDF_set_option' => 'pdflib/PDFlib.stub', 'PDF_set_parameter' => 'pdflib/PDFlib.stub', 'PDF_set_text_option' => 'pdflib/PDFlib.stub', 'PDF_set_text_pos' => 'pdflib/PDFlib.stub', 'PDF_set_value' => 'pdflib/PDFlib.stub', 'PDF_setcolor' => 'pdflib/PDFlib.stub', 'PDF_setdash' => 'pdflib/PDFlib.stub', 'PDF_setdashpattern' => 'pdflib/PDFlib.stub', 'PDF_setflat' => 'pdflib/PDFlib.stub', 'PDF_setfont' => 'pdflib/PDFlib.stub', 'PDF_setgray' => 'pdflib/PDFlib.stub', 'PDF_setgray_fill' => 'pdflib/PDFlib.stub', 'PDF_setgray_stroke' => 'pdflib/PDFlib.stub', 'PDF_setlinecap' => 'pdflib/PDFlib.stub', 'PDF_setlinejoin' => 'pdflib/PDFlib.stub', 'PDF_setlinewidth' => 'pdflib/PDFlib.stub', 'PDF_setmatrix' => 'pdflib/PDFlib.stub', 'PDF_setmiterlimit' => 'pdflib/PDFlib.stub', 'PDF_setrgbcolor' => 'pdflib/PDFlib.stub', 'PDF_setrgbcolor_fill' => 'pdflib/PDFlib.stub', 'PDF_setrgbcolor_stroke' => 'pdflib/PDFlib.stub', 'PDF_shading' => 'pdflib/PDFlib.stub', 'PDF_shading_pattern' => 'pdflib/PDFlib.stub', 'PDF_shfill' => 'pdflib/PDFlib.stub', 'PDF_show' => 'pdflib/PDFlib.stub', 'PDF_show_boxed' => 'pdflib/PDFlib.stub', 'PDF_show_xy' => 'pdflib/PDFlib.stub', 'PDF_skew' => 'pdflib/PDFlib.stub', 'PDF_stringwidth' => 'pdflib/PDFlib.stub', 'PDF_stroke' => 'pdflib/PDFlib.stub', 'PDF_suspend_page' => 'pdflib/PDFlib.stub', 'PDF_translate' => 'pdflib/PDFlib.stub', 'PDF_utf16_to_utf8' => 'pdflib/PDFlib.stub', 'PDF_utf32_to_utf16' => 'pdflib/PDFlib.stub', 'PDF_utf8_to_utf16' => 'pdflib/PDFlib.stub', 'PS_UNRESERVE_PREFIX___halt_compiler' => 'standard/_standard_manual.stub', 'PS_UNRESERVE_PREFIX_array' => 'standard/_types.stub', 'PS_UNRESERVE_PREFIX_die' => 'standard/_types.stub', 'PS_UNRESERVE_PREFIX_empty' => 'standard/_types.stub', 'PS_UNRESERVE_PREFIX_eval' => 'standard/_types.stub', 'PS_UNRESERVE_PREFIX_exit' => 'standard/_types.stub', 'PS_UNRESERVE_PREFIX_isset' => 'standard/_types.stub', 'PS_UNRESERVE_PREFIX_list' => 'standard/_types.stub', 'PS_UNRESERVE_PREFIX_unset' => 'standard/_types.stub', 'SQLSRV_PHPTYPE_STREAM' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_PHPTYPE_STRING' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_BINARY' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_CHAR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_DECIMAL' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_NCHAR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_NUMERIC' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_NVARCHAR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_VARBINARY' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_VARCHAR' => 'sqlsrv/sqlsrv.stub', 'Sodium\\add' => 'libsodium/libsodium.stub', 'Sodium\\bin2hex' => 'libsodium/libsodium.stub', 'Sodium\\compare' => 'libsodium/libsodium.stub', 'Sodium\\crypto_aead_aes256gcm_decrypt' => 'libsodium/libsodium.stub', 'Sodium\\crypto_aead_aes256gcm_encrypt' => 'libsodium/libsodium.stub', 'Sodium\\crypto_aead_aes256gcm_is_available' => 'libsodium/libsodium.stub', 'Sodium\\crypto_aead_chacha20poly1305_decrypt' => 'libsodium/libsodium.stub', 'Sodium\\crypto_aead_chacha20poly1305_encrypt' => 'libsodium/libsodium.stub', 'Sodium\\crypto_auth' => 'libsodium/libsodium.stub', 'Sodium\\crypto_auth_verify' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box_keypair' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box_keypair_from_secretkey_and_publickey' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box_open' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box_publickey' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box_publickey_from_secretkey' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box_seal' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box_seal_open' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box_secretkey' => 'libsodium/libsodium.stub', 'Sodium\\crypto_box_seed_keypair' => 'libsodium/libsodium.stub', 'Sodium\\crypto_generichash' => 'libsodium/libsodium.stub', 'Sodium\\crypto_generichash_final' => 'libsodium/libsodium.stub', 'Sodium\\crypto_generichash_init' => 'libsodium/libsodium.stub', 'Sodium\\crypto_generichash_update' => 'libsodium/libsodium.stub', 'Sodium\\crypto_kx' => 'libsodium/libsodium.stub', 'Sodium\\crypto_pwhash' => 'libsodium/libsodium.stub', 'Sodium\\crypto_pwhash_scryptsalsa208sha256' => 'libsodium/libsodium.stub', 'Sodium\\crypto_pwhash_scryptsalsa208sha256_str' => 'libsodium/libsodium.stub', 'Sodium\\crypto_pwhash_scryptsalsa208sha256_str_verify' => 'libsodium/libsodium.stub', 'Sodium\\crypto_pwhash_str' => 'libsodium/libsodium.stub', 'Sodium\\crypto_pwhash_str_verify' => 'libsodium/libsodium.stub', 'Sodium\\crypto_scalarmult' => 'libsodium/libsodium.stub', 'Sodium\\crypto_scalarmult_base' => 'libsodium/libsodium.stub', 'Sodium\\crypto_secretbox' => 'libsodium/libsodium.stub', 'Sodium\\crypto_secretbox_open' => 'libsodium/libsodium.stub', 'Sodium\\crypto_shorthash' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_detached' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_ed25519_pk_to_curve25519' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_ed25519_sk_to_curve25519' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_keypair' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_keypair_from_secretkey_and_publickey' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_open' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_publickey' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_publickey_from_secretkey' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_secretkey' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_seed_keypair' => 'libsodium/libsodium.stub', 'Sodium\\crypto_sign_verify_detached' => 'libsodium/libsodium.stub', 'Sodium\\crypto_stream' => 'libsodium/libsodium.stub', 'Sodium\\crypto_stream_xor' => 'libsodium/libsodium.stub', 'Sodium\\hex2bin' => 'libsodium/libsodium.stub', 'Sodium\\increment' => 'libsodium/libsodium.stub', 'Sodium\\library_version_major' => 'libsodium/libsodium.stub', 'Sodium\\library_version_minor' => 'libsodium/libsodium.stub', 'Sodium\\memcmp' => 'libsodium/libsodium.stub', 'Sodium\\memzero' => 'libsodium/libsodium.stub', 'Sodium\\randombytes_buf' => 'libsodium/libsodium.stub', 'Sodium\\randombytes_random16' => 'libsodium/libsodium.stub', 'Sodium\\randombytes_uniform' => 'libsodium/libsodium.stub', 'Sodium\\version_string' => 'libsodium/libsodium.stub', 'Zstd\\compress' => 'zstd/zstd.stub', 'Zstd\\compress_dict' => 'zstd/zstd.stub', 'Zstd\\uncompress' => 'zstd/zstd.stub', 'Zstd\\uncompress_dict' => 'zstd/zstd.stub', '_' => 'gettext/gettext.stub', 'abs' => 'standard/standard_3.stub', 'accelerator_set_status' => 'zend/zend.stub', 'acos' => 'standard/standard_3.stub', 'acosh' => 'standard/standard_3.stub', 'addcslashes' => 'standard/standard_1.stub', 'addslashes' => 'standard/standard_1.stub', 'apache_child_terminate' => 'apache/apache.stub', 'apache_get_modules' => 'apache/apache.stub', 'apache_get_version' => 'apache/apache.stub', 'apache_getenv' => 'apache/apache.stub', 'apache_lookup_uri' => 'apache/apache.stub', 'apache_note' => 'apache/apache.stub', 'apache_request_headers' => 'standard/standard_4.stub', 'apache_reset_timeout' => 'apache/apache.stub', 'apache_response_headers' => 'apache/apache.stub', 'apache_setenv' => 'apache/apache.stub', 'apc_add' => 'apcu/apcu.stub', 'apc_bin_dump' => 'apcu/apcu.stub', 'apc_bin_dumpfile' => 'apcu/apcu.stub', 'apc_bin_load' => 'apcu/apcu.stub', 'apc_bin_loadfile' => 'apcu/apcu.stub', 'apc_cache_info' => 'apcu/apcu.stub', 'apc_cas' => 'apcu/apcu.stub', 'apc_clear_cache' => 'apcu/apcu.stub', 'apc_compile_file' => 'apcu/apcu.stub', 'apc_dec' => 'apcu/apcu.stub', 'apc_define_constants' => 'apcu/apcu.stub', 'apc_delete' => 'apcu/apcu.stub', 'apc_delete_file' => 'apcu/apcu.stub', 'apc_exists' => 'apcu/apcu.stub', 'apc_fetch' => 'apcu/apcu.stub', 'apc_inc' => 'apcu/apcu.stub', 'apc_load_constants' => 'apcu/apcu.stub', 'apc_sma_info' => 'apcu/apcu.stub', 'apc_store' => 'apcu/apcu.stub', 'apcu_add' => 'apcu/apcu.stub', 'apcu_cache_info' => 'apcu/apcu.stub', 'apcu_cas' => 'apcu/apcu.stub', 'apcu_clear_cache' => 'apcu/apcu.stub', 'apcu_dec' => 'apcu/apcu.stub', 'apcu_delete' => 'apcu/apcu.stub', 'apcu_enabled' => 'apcu/apcu.stub', 'apcu_entry' => 'apcu/apcu.stub', 'apcu_exists' => 'apcu/apcu.stub', 'apcu_fetch' => 'apcu/apcu.stub', 'apcu_inc' => 'apcu/apcu.stub', 'apcu_key_info' => 'apcu/apcu.stub', 'apcu_sma_info' => 'apcu/apcu.stub', 'apcu_store' => 'apcu/apcu.stub', 'array_all' => 'standard/standard_10.stub', 'array_any' => 'standard/standard_10.stub', 'array_change_key_case' => 'standard/standard_9.stub', 'array_chunk' => 'standard/standard_9.stub', 'array_column' => 'standard/standard_9.stub', 'array_combine' => 'standard/standard_9.stub', 'array_count_values' => 'standard/standard_9.stub', 'array_diff' => 'standard/standard_9.stub', 'array_diff_assoc' => 'standard/standard_9.stub', 'array_diff_key' => 'standard/standard_9.stub', 'array_diff_uassoc' => 'standard/standard_9.stub', 'array_diff_ukey' => 'standard/standard_9.stub', 'array_fill' => 'standard/standard_8.stub', 'array_fill_keys' => 'standard/standard_8.stub', 'array_filter' => 'standard/standard_9.stub', 'array_find' => 'standard/standard_10.stub', 'array_find_key' => 'standard/standard_10.stub', 'array_flip' => 'standard/standard_9.stub', 'array_intersect' => 'standard/standard_9.stub', 'array_intersect_assoc' => 'standard/standard_9.stub', 'array_intersect_key' => 'standard/standard_9.stub', 'array_intersect_uassoc' => 'standard/standard_9.stub', 'array_intersect_ukey' => 'standard/standard_9.stub', 'array_is_list' => 'standard/standard_9.stub', 'array_key_exists' => 'standard/standard_9.stub', 'array_key_first' => 'standard/standard_9.stub', 'array_key_last' => 'standard/standard_9.stub', 'array_keys' => 'standard/standard_9.stub', 'array_map' => 'standard/standard_9.stub', 'array_merge' => 'standard/standard_8.stub', 'array_merge_recursive' => 'standard/standard_9.stub', 'array_multisort' => 'standard/standard_8.stub', 'array_pad' => 'standard/standard_9.stub', 'array_pop' => 'standard/standard_8.stub', 'array_product' => 'standard/standard_9.stub', 'array_push' => 'standard/standard_8.stub', 'array_rand' => 'standard/standard_9.stub', 'array_reduce' => 'standard/standard_9.stub', 'array_replace' => 'standard/standard_9.stub', 'array_replace_recursive' => 'standard/standard_9.stub', 'array_reverse' => 'standard/standard_9.stub', 'array_search' => 'standard/standard_8.stub', 'array_shift' => 'standard/standard_8.stub', 'array_slice' => 'standard/standard_8.stub', 'array_splice' => 'standard/standard_8.stub', 'array_sum' => 'standard/standard_9.stub', 'array_udiff' => 'standard/standard_9.stub', 'array_udiff_assoc' => 'standard/standard_9.stub', 'array_udiff_uassoc' => 'standard/standard_9.stub', 'array_uintersect' => 'standard/standard_9.stub', 'array_uintersect_assoc' => 'standard/standard_9.stub', 'array_uintersect_uassoc' => 'standard/standard_9.stub', 'array_unique' => 'standard/standard_9.stub', 'array_unshift' => 'standard/standard_8.stub', 'array_values' => 'standard/standard_9.stub', 'array_walk' => 'standard/standard_8.stub', 'array_walk_recursive' => 'standard/standard_8.stub', 'arsort' => 'standard/standard_8.stub', 'asin' => 'standard/standard_3.stub', 'asinh' => 'standard/standard_3.stub', 'asort' => 'standard/standard_8.stub', 'assert' => 'standard/standard_9.stub', 'assert_options' => 'standard/standard_9.stub', 'ast\\get_kind_name' => 'ast/ast.stub', 'ast\\get_metadata' => 'ast/ast.stub', 'ast\\get_supported_versions' => 'ast/ast.stub', 'ast\\kind_uses_flags' => 'ast/ast.stub', 'ast\\parse_code' => 'ast/ast.stub', 'ast\\parse_file' => 'ast/ast.stub', 'atan' => 'standard/standard_3.stub', 'atan2' => 'standard/standard_3.stub', 'atanh' => 'standard/standard_3.stub', 'base64_decode' => 'standard/standard_3.stub', 'base64_encode' => 'standard/standard_3.stub', 'base_convert' => 'standard/standard_3.stub', 'basename' => 'standard/standard_1.stub', 'bcadd' => 'bcmath/bcmath.stub', 'bcceil' => 'bcmath/bcmath.stub', 'bccomp' => 'bcmath/bcmath.stub', 'bcdiv' => 'bcmath/bcmath.stub', 'bcfloor' => 'bcmath/bcmath.stub', 'bcmod' => 'bcmath/bcmath.stub', 'bcmul' => 'bcmath/bcmath.stub', 'bcpow' => 'bcmath/bcmath.stub', 'bcpowmod' => 'bcmath/bcmath.stub', 'bcround' => 'bcmath/bcmath.stub', 'bcscale' => 'bcmath/bcmath.stub', 'bcsqrt' => 'bcmath/bcmath.stub', 'bcsub' => 'bcmath/bcmath.stub', 'bin2hex' => 'standard/standard_0.stub', 'bind_textdomain_codeset' => 'gettext/gettext.stub', 'bindec' => 'standard/standard_3.stub', 'bindtextdomain' => 'gettext/gettext.stub', 'boolval' => 'standard/standard_5.stub', 'brotli_compress' => 'brotli/brotli.stub', 'brotli_compress_add' => 'brotli/brotli.stub', 'brotli_compress_init' => 'brotli/brotli.stub', 'brotli_uncompress' => 'brotli/brotli.stub', 'brotli_uncompress_add' => 'brotli/brotli.stub', 'brotli_uncompress_init' => 'brotli/brotli.stub', 'bzclose' => 'bz2/bz2.stub', 'bzcompress' => 'bz2/bz2.stub', 'bzdecompress' => 'bz2/bz2.stub', 'bzerrno' => 'bz2/bz2.stub', 'bzerror' => 'bz2/bz2.stub', 'bzerrstr' => 'bz2/bz2.stub', 'bzflush' => 'bz2/bz2.stub', 'bzopen' => 'bz2/bz2.stub', 'bzread' => 'bz2/bz2.stub', 'bzwrite' => 'bz2/bz2.stub', 'cal_days_in_month' => 'calendar/calendar.stub', 'cal_from_jd' => 'calendar/calendar.stub', 'cal_info' => 'calendar/calendar.stub', 'cal_to_jd' => 'calendar/calendar.stub', 'call_user_func' => 'standard/standard_4.stub', 'call_user_func_array' => 'standard/standard_4.stub', 'call_user_method' => 'standard/standard_4.stub', 'call_user_method_array' => 'standard/standard_4.stub', 'ceil' => 'standard/standard_3.stub', 'chdir' => 'standard/standard_7.stub', 'checkdate' => 'date/date.stub', 'checkdnsrr' => 'standard/standard_4.stub', 'chgrp' => 'standard/standard_7.stub', 'chmod' => 'standard/standard_7.stub', 'chop' => 'standard/standard_2.stub', 'chown' => 'standard/standard_7.stub', 'chr' => 'standard/standard_2.stub', 'chroot' => 'standard/standard_7.stub', 'chunk_split' => 'standard/standard_1.stub', 'class_alias' => 'Core/Core.stub', 'class_exists' => 'Core/Core.stub', 'class_implements' => 'SPL/SPL_f.stub', 'class_parents' => 'SPL/SPL_f.stub', 'class_uses' => 'SPL/SPL_f.stub', 'clearstatcache' => 'standard/standard_7.stub', 'cli_get_process_title' => 'standard/basic.stub', 'cli_set_process_title' => 'standard/basic.stub', 'closedir' => 'standard/standard_7.stub', 'closelog' => 'standard/standard_8.stub', 'collator_asort' => 'intl/intl.stub', 'collator_compare' => 'intl/intl.stub', 'collator_create' => 'intl/intl.stub', 'collator_get_attribute' => 'intl/intl.stub', 'collator_get_error_code' => 'intl/intl.stub', 'collator_get_error_message' => 'intl/intl.stub', 'collator_get_locale' => 'intl/intl.stub', 'collator_get_sort_key' => 'intl/intl.stub', 'collator_get_strength' => 'intl/intl.stub', 'collator_set_attribute' => 'intl/intl.stub', 'collator_set_strength' => 'intl/intl.stub', 'collator_sort' => 'intl/intl.stub', 'collator_sort_with_sort_keys' => 'intl/intl.stub', 'com_create_guid' => 'com_dotnet/com_dotnet.stub', 'com_event_sink' => 'com_dotnet/com_dotnet.stub', 'com_get_active_object' => 'com_dotnet/com_dotnet.stub', 'com_load_typelib' => 'com_dotnet/com_dotnet.stub', 'com_message_pump' => 'com_dotnet/com_dotnet.stub', 'com_print_typeinfo' => 'com_dotnet/com_dotnet.stub', 'compact' => 'standard/standard_8.stub', 'config_get_hash' => 'xdebug/xdebug.stub', 'confirm_pdo_ibm_compiled' => 'PDO/PDO.stub', 'connection_aborted' => 'standard/standard_4.stub', 'connection_status' => 'standard/standard_4.stub', 'constant' => 'standard/standard_0.stub', 'convert_cyr_string' => 'standard/standard_3.stub', 'convert_uudecode' => 'standard/standard_3.stub', 'convert_uuencode' => 'standard/standard_3.stub', 'copy' => 'standard/standard_5.stub', 'cos' => 'standard/standard_3.stub', 'cosh' => 'standard/standard_3.stub', 'count' => 'standard/standard_8.stub', 'count_chars' => 'standard/standard_1.stub', 'crc32' => 'standard/standard_0.stub', 'create_function' => 'Core/Core.stub', 'crypt' => 'standard/standard_7.stub', 'ctype_alnum' => 'ctype/ctype.stub', 'ctype_alpha' => 'ctype/ctype.stub', 'ctype_cntrl' => 'ctype/ctype.stub', 'ctype_digit' => 'ctype/ctype.stub', 'ctype_graph' => 'ctype/ctype.stub', 'ctype_lower' => 'ctype/ctype.stub', 'ctype_print' => 'ctype/ctype.stub', 'ctype_punct' => 'ctype/ctype.stub', 'ctype_space' => 'ctype/ctype.stub', 'ctype_upper' => 'ctype/ctype.stub', 'ctype_xdigit' => 'ctype/ctype.stub', 'cubrid_affected_rows' => 'cubrid/cubrid.stub', 'cubrid_bind' => 'cubrid/cubrid.stub', 'cubrid_client_encoding' => 'cubrid/cubrid.stub', 'cubrid_close' => 'cubrid/cubrid.stub', 'cubrid_close_prepare' => 'cubrid/cubrid.stub', 'cubrid_close_request' => 'cubrid/cubrid.stub', 'cubrid_col_get' => 'cubrid/cubrid.stub', 'cubrid_col_size' => 'cubrid/cubrid.stub', 'cubrid_column_names' => 'cubrid/cubrid.stub', 'cubrid_column_types' => 'cubrid/cubrid.stub', 'cubrid_commit' => 'cubrid/cubrid.stub', 'cubrid_connect' => 'cubrid/cubrid.stub', 'cubrid_connect_with_url' => 'cubrid/cubrid.stub', 'cubrid_current_oid' => 'cubrid/cubrid.stub', 'cubrid_data_seek' => 'cubrid/cubrid.stub', 'cubrid_db_name' => 'cubrid/cubrid.stub', 'cubrid_db_parameter' => 'cubrid/cubrid.stub', 'cubrid_disconnect' => 'cubrid/cubrid.stub', 'cubrid_drop' => 'cubrid/cubrid.stub', 'cubrid_errno' => 'cubrid/cubrid.stub', 'cubrid_error' => 'cubrid/cubrid.stub', 'cubrid_error_code' => 'cubrid/cubrid.stub', 'cubrid_error_code_facility' => 'cubrid/cubrid.stub', 'cubrid_error_msg' => 'cubrid/cubrid.stub', 'cubrid_execute' => 'cubrid/cubrid.stub', 'cubrid_fetch' => 'cubrid/cubrid.stub', 'cubrid_fetch_array' => 'cubrid/cubrid.stub', 'cubrid_fetch_assoc' => 'cubrid/cubrid.stub', 'cubrid_fetch_field' => 'cubrid/cubrid.stub', 'cubrid_fetch_lengths' => 'cubrid/cubrid.stub', 'cubrid_fetch_object' => 'cubrid/cubrid.stub', 'cubrid_fetch_row' => 'cubrid/cubrid.stub', 'cubrid_field_flags' => 'cubrid/cubrid.stub', 'cubrid_field_len' => 'cubrid/cubrid.stub', 'cubrid_field_name' => 'cubrid/cubrid.stub', 'cubrid_field_seek' => 'cubrid/cubrid.stub', 'cubrid_field_table' => 'cubrid/cubrid.stub', 'cubrid_field_type' => 'cubrid/cubrid.stub', 'cubrid_free_result' => 'cubrid/cubrid.stub', 'cubrid_get' => 'cubrid/cubrid.stub', 'cubrid_get_autocommit' => 'cubrid/cubrid.stub', 'cubrid_get_charset' => 'cubrid/cubrid.stub', 'cubrid_get_class_name' => 'cubrid/cubrid.stub', 'cubrid_get_client_info' => 'cubrid/cubrid.stub', 'cubrid_get_db_parameter' => 'cubrid/cubrid.stub', 'cubrid_get_query_timeout' => 'cubrid/cubrid.stub', 'cubrid_get_server_info' => 'cubrid/cubrid.stub', 'cubrid_insert_id' => 'cubrid/cubrid.stub', 'cubrid_is_instance' => 'cubrid/cubrid.stub', 'cubrid_list_dbs' => 'cubrid/cubrid.stub', 'cubrid_lob2_bind' => 'cubrid/cubrid.stub', 'cubrid_lob2_close' => 'cubrid/cubrid.stub', 'cubrid_lob2_export' => 'cubrid/cubrid.stub', 'cubrid_lob2_import' => 'cubrid/cubrid.stub', 'cubrid_lob2_new' => 'cubrid/cubrid.stub', 'cubrid_lob2_read' => 'cubrid/cubrid.stub', 'cubrid_lob2_seek' => 'cubrid/cubrid.stub', 'cubrid_lob2_seek64' => 'cubrid/cubrid.stub', 'cubrid_lob2_size' => 'cubrid/cubrid.stub', 'cubrid_lob2_size64' => 'cubrid/cubrid.stub', 'cubrid_lob2_tell' => 'cubrid/cubrid.stub', 'cubrid_lob2_tell64' => 'cubrid/cubrid.stub', 'cubrid_lob2_write' => 'cubrid/cubrid.stub', 'cubrid_lob_close' => 'cubrid/cubrid.stub', 'cubrid_lob_export' => 'cubrid/cubrid.stub', 'cubrid_lob_get' => 'cubrid/cubrid.stub', 'cubrid_lob_send' => 'cubrid/cubrid.stub', 'cubrid_lob_size' => 'cubrid/cubrid.stub', 'cubrid_lock_read' => 'cubrid/cubrid.stub', 'cubrid_lock_write' => 'cubrid/cubrid.stub', 'cubrid_move_cursor' => 'cubrid/cubrid.stub', 'cubrid_next_result' => 'cubrid/cubrid.stub', 'cubrid_num_cols' => 'cubrid/cubrid.stub', 'cubrid_num_fields' => 'cubrid/cubrid.stub', 'cubrid_num_rows' => 'cubrid/cubrid.stub', 'cubrid_pconnect' => 'cubrid/cubrid.stub', 'cubrid_pconnect_with_url' => 'cubrid/cubrid.stub', 'cubrid_ping' => 'cubrid/cubrid.stub', 'cubrid_prepare' => 'cubrid/cubrid.stub', 'cubrid_put' => 'cubrid/cubrid.stub', 'cubrid_query' => 'cubrid/cubrid.stub', 'cubrid_real_escape_string' => 'cubrid/cubrid.stub', 'cubrid_result' => 'cubrid/cubrid.stub', 'cubrid_rollback' => 'cubrid/cubrid.stub', 'cubrid_schema' => 'cubrid/cubrid.stub', 'cubrid_seq_add' => 'cubrid/cubrid.stub', 'cubrid_seq_drop' => 'cubrid/cubrid.stub', 'cubrid_seq_insert' => 'cubrid/cubrid.stub', 'cubrid_seq_put' => 'cubrid/cubrid.stub', 'cubrid_set_add' => 'cubrid/cubrid.stub', 'cubrid_set_autocommit' => 'cubrid/cubrid.stub', 'cubrid_set_db_parameter' => 'cubrid/cubrid.stub', 'cubrid_set_drop' => 'cubrid/cubrid.stub', 'cubrid_set_query_timeout' => 'cubrid/cubrid.stub', 'cubrid_unbuffered_query' => 'cubrid/cubrid.stub', 'cubrid_version' => 'cubrid/cubrid.stub', 'curl_close' => 'curl/curl.stub', 'curl_copy_handle' => 'curl/curl.stub', 'curl_errno' => 'curl/curl.stub', 'curl_error' => 'curl/curl.stub', 'curl_escape' => 'curl/curl.stub', 'curl_exec' => 'curl/curl.stub', 'curl_file_create' => 'curl/curl.stub', 'curl_getinfo' => 'curl/curl.stub', 'curl_init' => 'curl/curl.stub', 'curl_multi_add_handle' => 'curl/curl.stub', 'curl_multi_close' => 'curl/curl.stub', 'curl_multi_errno' => 'curl/curl.stub', 'curl_multi_exec' => 'curl/curl.stub', 'curl_multi_getcontent' => 'curl/curl.stub', 'curl_multi_info_read' => 'curl/curl.stub', 'curl_multi_init' => 'curl/curl.stub', 'curl_multi_remove_handle' => 'curl/curl.stub', 'curl_multi_select' => 'curl/curl.stub', 'curl_multi_setopt' => 'curl/curl.stub', 'curl_multi_strerror' => 'curl/curl.stub', 'curl_pause' => 'curl/curl.stub', 'curl_reset' => 'curl/curl.stub', 'curl_setopt' => 'curl/curl.stub', 'curl_setopt_array' => 'curl/curl.stub', 'curl_share_close' => 'curl/curl.stub', 'curl_share_errno' => 'curl/curl.stub', 'curl_share_init' => 'curl/curl.stub', 'curl_share_setopt' => 'curl/curl.stub', 'curl_share_strerror' => 'curl/curl.stub', 'curl_strerror' => 'curl/curl.stub', 'curl_unescape' => 'curl/curl.stub', 'curl_upkeep' => 'curl/curl.stub', 'curl_version' => 'curl/curl.stub', 'current' => 'standard/standard_8.stub', 'date' => 'date/date.stub', 'date_add' => 'date/date.stub', 'date_create' => 'date/date.stub', 'date_create_from_format' => 'date/date.stub', 'date_create_immutable' => 'date/date.stub', 'date_create_immutable_from_format' => 'date/date.stub', 'date_date_set' => 'date/date.stub', 'date_default_timezone_get' => 'date/date.stub', 'date_default_timezone_set' => 'date/date.stub', 'date_diff' => 'date/date.stub', 'date_format' => 'date/date.stub', 'date_get_last_errors' => 'date/date.stub', 'date_interval_create_from_date_string' => 'date/date.stub', 'date_interval_format' => 'date/date.stub', 'date_isodate_set' => 'date/date.stub', 'date_modify' => 'date/date.stub', 'date_offset_get' => 'date/date.stub', 'date_parse' => 'date/date.stub', 'date_parse_from_format' => 'date/date.stub', 'date_sub' => 'date/date.stub', 'date_sun_info' => 'date/date.stub', 'date_sunrise' => 'date/date.stub', 'date_sunset' => 'date/date.stub', 'date_time_set' => 'date/date.stub', 'date_timestamp_get' => 'date/date.stub', 'date_timestamp_set' => 'date/date.stub', 'date_timezone_get' => 'date/date.stub', 'date_timezone_set' => 'date/date.stub', 'datefmt_create' => 'intl/intl.stub', 'datefmt_format' => 'intl/intl.stub', 'datefmt_format_object' => 'intl/intl.stub', 'datefmt_get_calendar' => 'intl/intl.stub', 'datefmt_get_calendar_object' => 'intl/intl.stub', 'datefmt_get_datetype' => 'intl/intl.stub', 'datefmt_get_error_code' => 'intl/intl.stub', 'datefmt_get_error_message' => 'intl/intl.stub', 'datefmt_get_locale' => 'intl/intl.stub', 'datefmt_get_pattern' => 'intl/intl.stub', 'datefmt_get_timetype' => 'intl/intl.stub', 'datefmt_get_timezone' => 'intl/intl.stub', 'datefmt_get_timezone_id' => 'intl/intl.stub', 'datefmt_is_lenient' => 'intl/intl.stub', 'datefmt_localtime' => 'intl/intl.stub', 'datefmt_parse' => 'intl/intl.stub', 'datefmt_set_calendar' => 'intl/intl.stub', 'datefmt_set_lenient' => 'intl/intl.stub', 'datefmt_set_pattern' => 'intl/intl.stub', 'datefmt_set_timezone' => 'intl/intl.stub', 'datefmt_set_timezone_id' => 'intl/intl.stub', 'db2_autocommit' => 'ibm_db2/ibm_db2.stub', 'db2_bind_param' => 'ibm_db2/ibm_db2.stub', 'db2_client_info' => 'ibm_db2/ibm_db2.stub', 'db2_close' => 'ibm_db2/ibm_db2.stub', 'db2_column_privileges' => 'ibm_db2/ibm_db2.stub', 'db2_columnprivileges' => 'ibm_db2/ibm_db2.stub', 'db2_columns' => 'ibm_db2/ibm_db2.stub', 'db2_commit' => 'ibm_db2/ibm_db2.stub', 'db2_conn_error' => 'ibm_db2/ibm_db2.stub', 'db2_conn_errormsg' => 'ibm_db2/ibm_db2.stub', 'db2_connect' => 'ibm_db2/ibm_db2.stub', 'db2_cursor_type' => 'ibm_db2/ibm_db2.stub', 'db2_escape_string' => 'ibm_db2/ibm_db2.stub', 'db2_exec' => 'ibm_db2/ibm_db2.stub', 'db2_execute' => 'ibm_db2/ibm_db2.stub', 'db2_fetch_array' => 'ibm_db2/ibm_db2.stub', 'db2_fetch_assoc' => 'ibm_db2/ibm_db2.stub', 'db2_fetch_both' => 'ibm_db2/ibm_db2.stub', 'db2_fetch_object' => 'ibm_db2/ibm_db2.stub', 'db2_fetch_row' => 'ibm_db2/ibm_db2.stub', 'db2_field_display_size' => 'ibm_db2/ibm_db2.stub', 'db2_field_name' => 'ibm_db2/ibm_db2.stub', 'db2_field_num' => 'ibm_db2/ibm_db2.stub', 'db2_field_precision' => 'ibm_db2/ibm_db2.stub', 'db2_field_scale' => 'ibm_db2/ibm_db2.stub', 'db2_field_type' => 'ibm_db2/ibm_db2.stub', 'db2_field_width' => 'ibm_db2/ibm_db2.stub', 'db2_foreign_keys' => 'ibm_db2/ibm_db2.stub', 'db2_foreignkeys' => 'ibm_db2/ibm_db2.stub', 'db2_free_result' => 'ibm_db2/ibm_db2.stub', 'db2_free_stmt' => 'ibm_db2/ibm_db2.stub', 'db2_get_option' => 'ibm_db2/ibm_db2.stub', 'db2_last_insert_id' => 'ibm_db2/ibm_db2.stub', 'db2_lob_read' => 'ibm_db2/ibm_db2.stub', 'db2_next_result' => 'ibm_db2/ibm_db2.stub', 'db2_num_fields' => 'ibm_db2/ibm_db2.stub', 'db2_num_rows' => 'ibm_db2/ibm_db2.stub', 'db2_pclose' => 'ibm_db2/ibm_db2.stub', 'db2_pconnect' => 'ibm_db2/ibm_db2.stub', 'db2_prepare' => 'ibm_db2/ibm_db2.stub', 'db2_primary_keys' => 'ibm_db2/ibm_db2.stub', 'db2_primarykeys' => 'ibm_db2/ibm_db2.stub', 'db2_procedure_columns' => 'ibm_db2/ibm_db2.stub', 'db2_procedurecolumns' => 'ibm_db2/ibm_db2.stub', 'db2_procedures' => 'ibm_db2/ibm_db2.stub', 'db2_result' => 'ibm_db2/ibm_db2.stub', 'db2_rollback' => 'ibm_db2/ibm_db2.stub', 'db2_server_info' => 'ibm_db2/ibm_db2.stub', 'db2_set_option' => 'ibm_db2/ibm_db2.stub', 'db2_setoption' => 'ibm_db2/ibm_db2.stub', 'db2_special_columns' => 'ibm_db2/ibm_db2.stub', 'db2_specialcolumns' => 'ibm_db2/ibm_db2.stub', 'db2_statistics' => 'ibm_db2/ibm_db2.stub', 'db2_stmt_error' => 'ibm_db2/ibm_db2.stub', 'db2_stmt_errormsg' => 'ibm_db2/ibm_db2.stub', 'db2_table_privileges' => 'ibm_db2/ibm_db2.stub', 'db2_tableprivileges' => 'ibm_db2/ibm_db2.stub', 'db2_tables' => 'ibm_db2/ibm_db2.stub', 'dba_close' => 'dba/dba.stub', 'dba_delete' => 'dba/dba.stub', 'dba_exists' => 'dba/dba.stub', 'dba_fetch' => 'dba/dba.stub', 'dba_firstkey' => 'dba/dba.stub', 'dba_handlers' => 'dba/dba.stub', 'dba_insert' => 'dba/dba.stub', 'dba_key_split' => 'dba/dba.stub', 'dba_list' => 'dba/dba.stub', 'dba_nextkey' => 'dba/dba.stub', 'dba_open' => 'dba/dba.stub', 'dba_optimize' => 'dba/dba.stub', 'dba_popen' => 'dba/dba.stub', 'dba_replace' => 'dba/dba.stub', 'dba_sync' => 'dba/dba.stub', 'dcgettext' => 'gettext/gettext.stub', 'dcngettext' => 'gettext/gettext.stub', 'debug_backtrace' => 'Core/Core.stub', 'debug_print_backtrace' => 'Core/Core.stub', 'debug_zval_dump' => 'standard/standard_4.stub', 'debugger_connect' => 'ZendDebugger/ZendDebugger.stub', 'debugger_connector_pid' => 'ZendDebugger/ZendDebugger.stub', 'debugger_get_server_start_time' => 'ZendDebugger/ZendDebugger.stub', 'debugger_print' => 'ZendDebugger/ZendDebugger.stub', 'debugger_start_debug' => 'ZendDebugger/ZendDebugger.stub', 'decbin' => 'standard/standard_3.stub', 'dechex' => 'standard/standard_3.stub', 'decoct' => 'standard/standard_3.stub', 'defer' => 'swoole/functions.stub', 'define' => 'Core/Core.stub', 'define_syslog_variables' => 'standard/standard_8.stub', 'defined' => 'Core/Core.stub', 'deflate_add' => 'zlib/zlib.stub', 'deflate_init' => 'zlib/zlib.stub', 'deg2rad' => 'standard/standard_3.stub', 'dgettext' => 'gettext/gettext.stub', 'dio_close' => 'dio/dio.stub', 'dio_fcntl' => 'dio/dio.stub', 'dio_open' => 'dio/dio.stub', 'dio_raw' => 'dio/dio.stub', 'dio_read' => 'dio/dio.stub', 'dio_seek' => 'dio/dio.stub', 'dio_serial' => 'dio/dio.stub', 'dio_stat' => 'dio/dio.stub', 'dio_tcsetattr' => 'dio/dio.stub', 'dio_truncate' => 'dio/dio.stub', 'dio_write' => 'dio/dio.stub', 'dir' => 'standard/standard_7.stub', 'dirname' => 'standard/standard_1.stub', 'disk_free_space' => 'standard/standard_7.stub', 'disk_total_space' => 'standard/standard_7.stub', 'diskfreespace' => 'standard/standard_7.stub', 'dl' => 'standard/basic.stub', 'dngettext' => 'gettext/gettext.stub', 'dns_check_record' => 'standard/standard_4.stub', 'dns_get_mx' => 'standard/standard_4.stub', 'dns_get_record' => 'standard/standard_4.stub', 'dom_import_simplexml' => 'dom/dom.stub', 'doubleval' => 'standard/standard_5.stub', 'each' => 'Core/Core.stub', 'easter_date' => 'calendar/calendar.stub', 'easter_days' => 'calendar/calendar.stub', 'eio_busy' => 'eio/eio.stub', 'eio_cancel' => 'eio/eio.stub', 'eio_chmod' => 'eio/eio.stub', 'eio_chown' => 'eio/eio.stub', 'eio_close' => 'eio/eio.stub', 'eio_custom' => 'eio/eio.stub', 'eio_dup2' => 'eio/eio.stub', 'eio_event_loop' => 'eio/eio.stub', 'eio_fallocate' => 'eio/eio.stub', 'eio_fchmod' => 'eio/eio.stub', 'eio_fchown' => 'eio/eio.stub', 'eio_fdatasync' => 'eio/eio.stub', 'eio_fstat' => 'eio/eio.stub', 'eio_fstatvfs' => 'eio/eio.stub', 'eio_fsync' => 'eio/eio.stub', 'eio_ftruncate' => 'eio/eio.stub', 'eio_futime' => 'eio/eio.stub', 'eio_get_event_stream' => 'eio/eio.stub', 'eio_get_last_error' => 'eio/eio.stub', 'eio_grp' => 'eio/eio.stub', 'eio_grp_add' => 'eio/eio.stub', 'eio_grp_cancel' => 'eio/eio.stub', 'eio_grp_limit' => 'eio/eio.stub', 'eio_link' => 'eio/eio.stub', 'eio_lstat' => 'eio/eio.stub', 'eio_mkdir' => 'eio/eio.stub', 'eio_mknod' => 'eio/eio.stub', 'eio_nop' => 'eio/eio.stub', 'eio_npending' => 'eio/eio.stub', 'eio_nready' => 'eio/eio.stub', 'eio_nreqs' => 'eio/eio.stub', 'eio_nthreads' => 'eio/eio.stub', 'eio_open' => 'eio/eio.stub', 'eio_poll' => 'eio/eio.stub', 'eio_read' => 'eio/eio.stub', 'eio_readahead' => 'eio/eio.stub', 'eio_readdir' => 'eio/eio.stub', 'eio_readlink' => 'eio/eio.stub', 'eio_realpath' => 'eio/eio.stub', 'eio_rename' => 'eio/eio.stub', 'eio_rmdir' => 'eio/eio.stub', 'eio_seek' => 'eio/eio.stub', 'eio_sendfile' => 'eio/eio.stub', 'eio_set_max_idle' => 'eio/eio.stub', 'eio_set_max_parallel' => 'eio/eio.stub', 'eio_set_max_poll_reqs' => 'eio/eio.stub', 'eio_set_max_poll_time' => 'eio/eio.stub', 'eio_set_min_parallel' => 'eio/eio.stub', 'eio_stat' => 'eio/eio.stub', 'eio_statvfs' => 'eio/eio.stub', 'eio_symlink' => 'eio/eio.stub', 'eio_sync' => 'eio/eio.stub', 'eio_sync_file_range' => 'eio/eio.stub', 'eio_syncfs' => 'eio/eio.stub', 'eio_truncate' => 'eio/eio.stub', 'eio_unlink' => 'eio/eio.stub', 'eio_utime' => 'eio/eio.stub', 'eio_write' => 'eio/eio.stub', 'enchant_broker_describe' => 'enchant/enchant.stub', 'enchant_broker_dict_exists' => 'enchant/enchant.stub', 'enchant_broker_free' => 'enchant/enchant.stub', 'enchant_broker_free_dict' => 'enchant/enchant.stub', 'enchant_broker_get_dict_path' => 'enchant/enchant.stub', 'enchant_broker_get_error' => 'enchant/enchant.stub', 'enchant_broker_init' => 'enchant/enchant.stub', 'enchant_broker_list_dicts' => 'enchant/enchant.stub', 'enchant_broker_request_dict' => 'enchant/enchant.stub', 'enchant_broker_request_pwl_dict' => 'enchant/enchant.stub', 'enchant_broker_set_dict_path' => 'enchant/enchant.stub', 'enchant_broker_set_ordering' => 'enchant/enchant.stub', 'enchant_dict_add' => 'enchant/enchant.stub', 'enchant_dict_add_to_personal' => 'enchant/enchant.stub', 'enchant_dict_add_to_session' => 'enchant/enchant.stub', 'enchant_dict_check' => 'enchant/enchant.stub', 'enchant_dict_describe' => 'enchant/enchant.stub', 'enchant_dict_get_error' => 'enchant/enchant.stub', 'enchant_dict_is_added' => 'enchant/enchant.stub', 'enchant_dict_is_in_session' => 'enchant/enchant.stub', 'enchant_dict_quick_check' => 'enchant/enchant.stub', 'enchant_dict_store_replacement' => 'enchant/enchant.stub', 'enchant_dict_suggest' => 'enchant/enchant.stub', 'end' => 'standard/standard_8.stub', 'enum_exists' => 'Core/Core.stub', 'ereg' => 'regex/ereg.stub', 'ereg_replace' => 'regex/ereg.stub', 'eregi' => 'regex/ereg.stub', 'eregi_replace' => 'regex/ereg.stub', 'error_clear_last' => 'standard/basic.stub', 'error_get_last' => 'standard/standard_4.stub', 'error_log' => 'standard/standard_3.stub', 'error_reporting' => 'Core/Core.stub', 'escapeshellarg' => 'standard/standard_2.stub', 'escapeshellcmd' => 'standard/standard_2.stub', 'event_add' => 'libevent/libevent.stub', 'event_base_free' => 'libevent/libevent.stub', 'event_base_loop' => 'libevent/libevent.stub', 'event_base_loopbreak' => 'libevent/libevent.stub', 'event_base_loopexit' => 'libevent/libevent.stub', 'event_base_new' => 'libevent/libevent.stub', 'event_base_priority_init' => 'libevent/libevent.stub', 'event_base_set' => 'libevent/libevent.stub', 'event_buffer_base_set' => 'libevent/libevent.stub', 'event_buffer_disable' => 'libevent/libevent.stub', 'event_buffer_enable' => 'libevent/libevent.stub', 'event_buffer_fd_set' => 'libevent/libevent.stub', 'event_buffer_free' => 'libevent/libevent.stub', 'event_buffer_new' => 'libevent/libevent.stub', 'event_buffer_priority_set' => 'libevent/libevent.stub', 'event_buffer_read' => 'libevent/libevent.stub', 'event_buffer_set_callback' => 'libevent/libevent.stub', 'event_buffer_timeout_set' => 'libevent/libevent.stub', 'event_buffer_watermark_set' => 'libevent/libevent.stub', 'event_buffer_write' => 'libevent/libevent.stub', 'event_del' => 'libevent/libevent.stub', 'event_free' => 'libevent/libevent.stub', 'event_new' => 'libevent/libevent.stub', 'event_set' => 'libevent/libevent.stub', 'event_timer_add' => 'libevent/libevent.stub', 'event_timer_del' => 'libevent/libevent.stub', 'event_timer_new' => 'libevent/libevent.stub', 'event_timer_pending' => 'libevent/libevent.stub', 'event_timer_set' => 'libevent/libevent.stub', 'exec' => 'standard/standard_2.stub', 'exif_imagetype' => 'exif/exif.stub', 'exif_read_data' => 'exif/exif.stub', 'exif_tagname' => 'exif/exif.stub', 'exif_thumbnail' => 'exif/exif.stub', 'exp' => 'standard/standard_3.stub', 'expect_expectl' => 'expect/expect.stub', 'expect_popen' => 'expect/expect.stub', 'explode' => 'standard/standard_1.stub', 'expm1' => 'standard/standard_3.stub', 'extension_loaded' => 'Core/Core.stub', 'extract' => 'standard/standard_8.stub', 'ezmlm_hash' => 'standard/standard_7.stub', 'fann_cascadetrain_on_data' => 'fann/fann.stub', 'fann_cascadetrain_on_file' => 'fann/fann.stub', 'fann_clear_scaling_params' => 'fann/fann.stub', 'fann_copy' => 'fann/fann.stub', 'fann_create_from_file' => 'fann/fann.stub', 'fann_create_shortcut' => 'fann/fann.stub', 'fann_create_shortcut_array' => 'fann/fann.stub', 'fann_create_sparse' => 'fann/fann.stub', 'fann_create_sparse_array' => 'fann/fann.stub', 'fann_create_standard' => 'fann/fann.stub', 'fann_create_standard_array' => 'fann/fann.stub', 'fann_create_train' => 'fann/fann.stub', 'fann_create_train_from_callback' => 'fann/fann.stub', 'fann_descale_input' => 'fann/fann.stub', 'fann_descale_output' => 'fann/fann.stub', 'fann_descale_train' => 'fann/fann.stub', 'fann_destroy' => 'fann/fann.stub', 'fann_destroy_train' => 'fann/fann.stub', 'fann_duplicate_train_data' => 'fann/fann.stub', 'fann_get_MSE' => 'fann/fann.stub', 'fann_get_activation_function' => 'fann/fann.stub', 'fann_get_activation_steepness' => 'fann/fann.stub', 'fann_get_bias_array' => 'fann/fann.stub', 'fann_get_bit_fail' => 'fann/fann.stub', 'fann_get_bit_fail_limit' => 'fann/fann.stub', 'fann_get_cascade_activation_functions' => 'fann/fann.stub', 'fann_get_cascade_activation_functions_count' => 'fann/fann.stub', 'fann_get_cascade_activation_steepnesses' => 'fann/fann.stub', 'fann_get_cascade_activation_steepnesses_count' => 'fann/fann.stub', 'fann_get_cascade_candidate_change_fraction' => 'fann/fann.stub', 'fann_get_cascade_candidate_limit' => 'fann/fann.stub', 'fann_get_cascade_candidate_stagnation_epochs' => 'fann/fann.stub', 'fann_get_cascade_max_cand_epochs' => 'fann/fann.stub', 'fann_get_cascade_max_out_epochs' => 'fann/fann.stub', 'fann_get_cascade_min_cand_epochs' => 'fann/fann.stub', 'fann_get_cascade_min_out_epochs' => 'fann/fann.stub', 'fann_get_cascade_num_candidate_groups' => 'fann/fann.stub', 'fann_get_cascade_num_candidates' => 'fann/fann.stub', 'fann_get_cascade_output_change_fraction' => 'fann/fann.stub', 'fann_get_cascade_output_stagnation_epochs' => 'fann/fann.stub', 'fann_get_cascade_weight_multiplier' => 'fann/fann.stub', 'fann_get_connection_array' => 'fann/fann.stub', 'fann_get_connection_rate' => 'fann/fann.stub', 'fann_get_errno' => 'fann/fann.stub', 'fann_get_errstr' => 'fann/fann.stub', 'fann_get_layer_array' => 'fann/fann.stub', 'fann_get_learning_momentum' => 'fann/fann.stub', 'fann_get_learning_rate' => 'fann/fann.stub', 'fann_get_network_type' => 'fann/fann.stub', 'fann_get_num_input' => 'fann/fann.stub', 'fann_get_num_layers' => 'fann/fann.stub', 'fann_get_num_output' => 'fann/fann.stub', 'fann_get_quickprop_decay' => 'fann/fann.stub', 'fann_get_quickprop_mu' => 'fann/fann.stub', 'fann_get_rprop_decrease_factor' => 'fann/fann.stub', 'fann_get_rprop_delta_max' => 'fann/fann.stub', 'fann_get_rprop_delta_min' => 'fann/fann.stub', 'fann_get_rprop_delta_zero' => 'fann/fann.stub', 'fann_get_rprop_increase_factor' => 'fann/fann.stub', 'fann_get_sarprop_step_error_shift' => 'fann/fann.stub', 'fann_get_sarprop_step_error_threshold_factor' => 'fann/fann.stub', 'fann_get_sarprop_temperature' => 'fann/fann.stub', 'fann_get_sarprop_weight_decay_shift' => 'fann/fann.stub', 'fann_get_total_connections' => 'fann/fann.stub', 'fann_get_total_neurons' => 'fann/fann.stub', 'fann_get_train_error_function' => 'fann/fann.stub', 'fann_get_train_stop_function' => 'fann/fann.stub', 'fann_get_training_algorithm' => 'fann/fann.stub', 'fann_init_weights' => 'fann/fann.stub', 'fann_length_train_data' => 'fann/fann.stub', 'fann_merge_train_data' => 'fann/fann.stub', 'fann_num_input_train_data' => 'fann/fann.stub', 'fann_num_output_train_data' => 'fann/fann.stub', 'fann_print_error' => 'fann/fann.stub', 'fann_randomize_weights' => 'fann/fann.stub', 'fann_read_train_from_file' => 'fann/fann.stub', 'fann_reset_MSE' => 'fann/fann.stub', 'fann_reset_errno' => 'fann/fann.stub', 'fann_reset_errstr' => 'fann/fann.stub', 'fann_run' => 'fann/fann.stub', 'fann_save' => 'fann/fann.stub', 'fann_save_train' => 'fann/fann.stub', 'fann_scale_input' => 'fann/fann.stub', 'fann_scale_input_train_data' => 'fann/fann.stub', 'fann_scale_output' => 'fann/fann.stub', 'fann_scale_output_train_data' => 'fann/fann.stub', 'fann_scale_train' => 'fann/fann.stub', 'fann_scale_train_data' => 'fann/fann.stub', 'fann_set_activation_function' => 'fann/fann.stub', 'fann_set_activation_function_hidden' => 'fann/fann.stub', 'fann_set_activation_function_layer' => 'fann/fann.stub', 'fann_set_activation_function_output' => 'fann/fann.stub', 'fann_set_activation_steepness' => 'fann/fann.stub', 'fann_set_activation_steepness_hidden' => 'fann/fann.stub', 'fann_set_activation_steepness_layer' => 'fann/fann.stub', 'fann_set_activation_steepness_output' => 'fann/fann.stub', 'fann_set_bit_fail_limit' => 'fann/fann.stub', 'fann_set_callback' => 'fann/fann.stub', 'fann_set_cascade_activation_functions' => 'fann/fann.stub', 'fann_set_cascade_activation_steepnesses' => 'fann/fann.stub', 'fann_set_cascade_candidate_change_fraction' => 'fann/fann.stub', 'fann_set_cascade_candidate_limit' => 'fann/fann.stub', 'fann_set_cascade_candidate_stagnation_epochs' => 'fann/fann.stub', 'fann_set_cascade_max_cand_epochs' => 'fann/fann.stub', 'fann_set_cascade_max_out_epochs' => 'fann/fann.stub', 'fann_set_cascade_min_cand_epochs' => 'fann/fann.stub', 'fann_set_cascade_min_out_epochs' => 'fann/fann.stub', 'fann_set_cascade_num_candidate_groups' => 'fann/fann.stub', 'fann_set_cascade_output_change_fraction' => 'fann/fann.stub', 'fann_set_cascade_output_stagnation_epochs' => 'fann/fann.stub', 'fann_set_cascade_weight_multiplier' => 'fann/fann.stub', 'fann_set_error_log' => 'fann/fann.stub', 'fann_set_input_scaling_params' => 'fann/fann.stub', 'fann_set_learning_momentum' => 'fann/fann.stub', 'fann_set_learning_rate' => 'fann/fann.stub', 'fann_set_output_scaling_params' => 'fann/fann.stub', 'fann_set_quickprop_decay' => 'fann/fann.stub', 'fann_set_quickprop_mu' => 'fann/fann.stub', 'fann_set_rprop_decrease_factor' => 'fann/fann.stub', 'fann_set_rprop_delta_max' => 'fann/fann.stub', 'fann_set_rprop_delta_min' => 'fann/fann.stub', 'fann_set_rprop_delta_zero' => 'fann/fann.stub', 'fann_set_rprop_increase_factor' => 'fann/fann.stub', 'fann_set_sarprop_step_error_shift' => 'fann/fann.stub', 'fann_set_sarprop_step_error_threshold_factor' => 'fann/fann.stub', 'fann_set_sarprop_temperature' => 'fann/fann.stub', 'fann_set_sarprop_weight_decay_shift' => 'fann/fann.stub', 'fann_set_scaling_params' => 'fann/fann.stub', 'fann_set_train_error_function' => 'fann/fann.stub', 'fann_set_train_stop_function' => 'fann/fann.stub', 'fann_set_training_algorithm' => 'fann/fann.stub', 'fann_set_weight' => 'fann/fann.stub', 'fann_set_weight_array' => 'fann/fann.stub', 'fann_shuffle_train_data' => 'fann/fann.stub', 'fann_subset_train_data' => 'fann/fann.stub', 'fann_test' => 'fann/fann.stub', 'fann_test_data' => 'fann/fann.stub', 'fann_train' => 'fann/fann.stub', 'fann_train_epoch' => 'fann/fann.stub', 'fann_train_on_data' => 'fann/fann.stub', 'fann_train_on_file' => 'fann/fann.stub', 'fastcgi_finish_request' => 'fpm/fpm.stub', 'fbird_add_user' => 'interbase/interbase.stub', 'fbird_affected_rows' => 'interbase/interbase.stub', 'fbird_backup' => 'interbase/interbase.stub', 'fbird_blob_add' => 'interbase/interbase.stub', 'fbird_blob_cancel' => 'interbase/interbase.stub', 'fbird_blob_close' => 'interbase/interbase.stub', 'fbird_blob_create' => 'interbase/interbase.stub', 'fbird_blob_echo' => 'interbase/interbase.stub', 'fbird_blob_get' => 'interbase/interbase.stub', 'fbird_blob_import' => 'interbase/interbase.stub', 'fbird_blob_info' => 'interbase/interbase.stub', 'fbird_blob_open' => 'interbase/interbase.stub', 'fbird_close' => 'interbase/interbase.stub', 'fbird_commit' => 'interbase/interbase.stub', 'fbird_commit_ret' => 'interbase/interbase.stub', 'fbird_connect' => 'interbase/interbase.stub', 'fbird_db_info' => 'interbase/interbase.stub', 'fbird_delete_user' => 'interbase/interbase.stub', 'fbird_drop_db' => 'interbase/interbase.stub', 'fbird_errcode' => 'interbase/interbase.stub', 'fbird_errmsg' => 'interbase/interbase.stub', 'fbird_execute' => 'interbase/interbase.stub', 'fbird_fetch_assoc' => 'interbase/interbase.stub', 'fbird_fetch_object' => 'interbase/interbase.stub', 'fbird_fetch_row' => 'interbase/interbase.stub', 'fbird_field_info' => 'interbase/interbase.stub', 'fbird_free_event_handler' => 'interbase/interbase.stub', 'fbird_free_query' => 'interbase/interbase.stub', 'fbird_free_result' => 'interbase/interbase.stub', 'fbird_gen_id' => 'interbase/interbase.stub', 'fbird_maintain_db' => 'interbase/interbase.stub', 'fbird_modify_user' => 'interbase/interbase.stub', 'fbird_name_result' => 'interbase/interbase.stub', 'fbird_num_fields' => 'interbase/interbase.stub', 'fbird_num_params' => 'interbase/interbase.stub', 'fbird_param_info' => 'interbase/interbase.stub', 'fbird_pconnect' => 'interbase/interbase.stub', 'fbird_prepare' => 'interbase/interbase.stub', 'fbird_query' => 'interbase/interbase.stub', 'fbird_restore' => 'interbase/interbase.stub', 'fbird_rollback' => 'interbase/interbase.stub', 'fbird_rollback_ret' => 'interbase/interbase.stub', 'fbird_server_info' => 'interbase/interbase.stub', 'fbird_service_attach' => 'interbase/interbase.stub', 'fbird_service_detach' => 'interbase/interbase.stub', 'fbird_set_event_handler' => 'interbase/interbase.stub', 'fbird_trans' => 'interbase/interbase.stub', 'fbird_wait_event' => 'interbase/interbase.stub', 'fclose' => 'standard/standard_5.stub', 'fdatasync' => 'standard/standard_5.stub', 'fdiv' => 'standard/standard_3.stub', 'feof' => 'standard/standard_5.stub', 'fflush' => 'standard/standard_5.stub', 'fgetc' => 'standard/standard_5.stub', 'fgetcsv' => 'standard/standard_6.stub', 'fgets' => 'standard/standard_5.stub', 'fgetss' => 'standard/standard_5.stub', 'file' => 'standard/standard_5.stub', 'file_exists' => 'standard/standard_7.stub', 'file_get_contents' => 'standard/standard_5.stub', 'file_put_contents' => 'standard/standard_5.stub', 'fileatime' => 'standard/standard_7.stub', 'filectime' => 'standard/standard_7.stub', 'filegroup' => 'standard/standard_7.stub', 'fileinode' => 'standard/standard_7.stub', 'filemtime' => 'standard/standard_7.stub', 'fileowner' => 'standard/standard_7.stub', 'fileperms' => 'standard/standard_7.stub', 'filesize' => 'standard/standard_7.stub', 'filetype' => 'standard/standard_7.stub', 'filter_has_var' => 'filter/filter.stub', 'filter_id' => 'filter/filter.stub', 'filter_input' => 'filter/filter.stub', 'filter_input_array' => 'filter/filter.stub', 'filter_list' => 'filter/filter.stub', 'filter_var' => 'filter/filter.stub', 'filter_var_array' => 'filter/filter.stub', 'finfo_buffer' => 'fileinfo/fileinfo.stub', 'finfo_close' => 'fileinfo/fileinfo.stub', 'finfo_file' => 'fileinfo/fileinfo.stub', 'finfo_open' => 'fileinfo/fileinfo.stub', 'finfo_set_flags' => 'fileinfo/fileinfo.stub', 'floatval' => 'standard/standard_5.stub', 'flock' => 'standard/standard_6.stub', 'floor' => 'standard/standard_3.stub', 'flush' => 'standard/standard_0.stub', 'fmod' => 'standard/standard_3.stub', 'fnmatch' => 'standard/standard_6.stub', 'fopen' => 'standard/standard_5.stub', 'forward_static_call' => 'standard/standard_4.stub', 'forward_static_call_array' => 'standard/standard_4.stub', 'fpassthru' => 'standard/standard_5.stub', 'fpm_get_status' => 'fpm/fpm.stub', 'fpow' => 'standard/standard_10.stub', 'fprintf' => 'standard/standard_2.stub', 'fputcsv' => 'standard/standard_6.stub', 'fputs' => 'standard/standard_5.stub', 'frankenphp_finish_request' => 'frankenphp/frankenphp.stub', 'frankenphp_handle_request' => 'frankenphp/frankenphp.stub', 'frankenphp_request_headers' => 'frankenphp/frankenphp.stub', 'frankenphp_response_headers' => 'frankenphp/frankenphp.stub', 'fread' => 'standard/standard_5.stub', 'frenchtojd' => 'calendar/calendar.stub', 'fscanf' => 'standard/standard_2.stub', 'fseek' => 'standard/standard_5.stub', 'fsockopen' => 'standard/standard_7.stub', 'fstat' => 'standard/standard_5.stub', 'fsync' => 'standard/standard_5.stub', 'ftell' => 'standard/standard_5.stub', 'ftok' => 'standard/standard_9.stub', 'ftp_alloc' => 'ftp/ftp.stub', 'ftp_append' => 'ftp/ftp.stub', 'ftp_cdup' => 'ftp/ftp.stub', 'ftp_chdir' => 'ftp/ftp.stub', 'ftp_chmod' => 'ftp/ftp.stub', 'ftp_close' => 'ftp/ftp.stub', 'ftp_connect' => 'ftp/ftp.stub', 'ftp_delete' => 'ftp/ftp.stub', 'ftp_exec' => 'ftp/ftp.stub', 'ftp_fget' => 'ftp/ftp.stub', 'ftp_fput' => 'ftp/ftp.stub', 'ftp_get' => 'ftp/ftp.stub', 'ftp_get_option' => 'ftp/ftp.stub', 'ftp_login' => 'ftp/ftp.stub', 'ftp_mdtm' => 'ftp/ftp.stub', 'ftp_mkdir' => 'ftp/ftp.stub', 'ftp_mlsd' => 'ftp/ftp.stub', 'ftp_nb_continue' => 'ftp/ftp.stub', 'ftp_nb_fget' => 'ftp/ftp.stub', 'ftp_nb_fput' => 'ftp/ftp.stub', 'ftp_nb_get' => 'ftp/ftp.stub', 'ftp_nb_put' => 'ftp/ftp.stub', 'ftp_nlist' => 'ftp/ftp.stub', 'ftp_pasv' => 'ftp/ftp.stub', 'ftp_put' => 'ftp/ftp.stub', 'ftp_pwd' => 'ftp/ftp.stub', 'ftp_quit' => 'ftp/ftp.stub', 'ftp_raw' => 'ftp/ftp.stub', 'ftp_rawlist' => 'ftp/ftp.stub', 'ftp_rename' => 'ftp/ftp.stub', 'ftp_rmdir' => 'ftp/ftp.stub', 'ftp_set_option' => 'ftp/ftp.stub', 'ftp_site' => 'ftp/ftp.stub', 'ftp_size' => 'ftp/ftp.stub', 'ftp_ssl_connect' => 'ftp/ftp.stub', 'ftp_systype' => 'ftp/ftp.stub', 'ftruncate' => 'standard/standard_5.stub', 'func_get_arg' => 'Core/Core.stub', 'func_get_args' => 'Core/Core.stub', 'func_num_args' => 'Core/Core.stub', 'function_exists' => 'Core/Core.stub', 'fwrite' => 'standard/standard_5.stub', 'gc_collect_cycles' => 'Core/Core.stub', 'gc_disable' => 'Core/Core.stub', 'gc_enable' => 'Core/Core.stub', 'gc_enabled' => 'Core/Core.stub', 'gc_mem_caches' => 'Core/Core.stub', 'gc_status' => 'Core/Core.stub', 'gd_info' => 'gd/gd.stub', 'gearman_bugreport' => 'gearman/gearman.stub', 'gearman_client_add_options' => 'gearman/gearman.stub', 'gearman_client_add_server' => 'gearman/gearman.stub', 'gearman_client_add_servers' => 'gearman/gearman.stub', 'gearman_client_add_task' => 'gearman/gearman.stub', 'gearman_client_add_task_background' => 'gearman/gearman.stub', 'gearman_client_add_task_high' => 'gearman/gearman.stub', 'gearman_client_add_task_high_background' => 'gearman/gearman.stub', 'gearman_client_add_task_low' => 'gearman/gearman.stub', 'gearman_client_add_task_low_background' => 'gearman/gearman.stub', 'gearman_client_add_task_status' => 'gearman/gearman.stub', 'gearman_client_clear_fn' => 'gearman/gearman.stub', 'gearman_client_clone' => 'gearman/gearman.stub', 'gearman_client_context' => 'gearman/gearman.stub', 'gearman_client_create' => 'gearman/gearman.stub', 'gearman_client_do' => 'gearman/gearman.stub', 'gearman_client_do_background' => 'gearman/gearman.stub', 'gearman_client_do_high' => 'gearman/gearman.stub', 'gearman_client_do_high_background' => 'gearman/gearman.stub', 'gearman_client_do_job_handle' => 'gearman/gearman.stub', 'gearman_client_do_low' => 'gearman/gearman.stub', 'gearman_client_do_low_background' => 'gearman/gearman.stub', 'gearman_client_do_normal' => 'gearman/gearman.stub', 'gearman_client_do_status' => 'gearman/gearman.stub', 'gearman_client_echo' => 'gearman/gearman.stub', 'gearman_client_errno' => 'gearman/gearman.stub', 'gearman_client_error' => 'gearman/gearman.stub', 'gearman_client_job_status' => 'gearman/gearman.stub', 'gearman_client_options' => 'gearman/gearman.stub', 'gearman_client_remove_options' => 'gearman/gearman.stub', 'gearman_client_return_code' => 'gearman/gearman.stub', 'gearman_client_run_tasks' => 'gearman/gearman.stub', 'gearman_client_set_complete_fn' => 'gearman/gearman.stub', 'gearman_client_set_context' => 'gearman/gearman.stub', 'gearman_client_set_created_fn' => 'gearman/gearman.stub', 'gearman_client_set_data_fn' => 'gearman/gearman.stub', 'gearman_client_set_exception_fn' => 'gearman/gearman.stub', 'gearman_client_set_fail_fn' => 'gearman/gearman.stub', 'gearman_client_set_options' => 'gearman/gearman.stub', 'gearman_client_set_status_fn' => 'gearman/gearman.stub', 'gearman_client_set_timeout' => 'gearman/gearman.stub', 'gearman_client_set_warning_fn' => 'gearman/gearman.stub', 'gearman_client_set_workload_fn' => 'gearman/gearman.stub', 'gearman_client_timeout' => 'gearman/gearman.stub', 'gearman_client_wait' => 'gearman/gearman.stub', 'gearman_job_function_name' => 'gearman/gearman.stub', 'gearman_job_handle' => 'gearman/gearman.stub', 'gearman_job_return_code' => 'gearman/gearman.stub', 'gearman_job_send_complete' => 'gearman/gearman.stub', 'gearman_job_send_data' => 'gearman/gearman.stub', 'gearman_job_send_exception' => 'gearman/gearman.stub', 'gearman_job_send_fail' => 'gearman/gearman.stub', 'gearman_job_send_status' => 'gearman/gearman.stub', 'gearman_job_send_warning' => 'gearman/gearman.stub', 'gearman_job_unique' => 'gearman/gearman.stub', 'gearman_job_workload' => 'gearman/gearman.stub', 'gearman_job_workload_size' => 'gearman/gearman.stub', 'gearman_task_data' => 'gearman/gearman.stub', 'gearman_task_data_size' => 'gearman/gearman.stub', 'gearman_task_denominator' => 'gearman/gearman.stub', 'gearman_task_function_name' => 'gearman/gearman.stub', 'gearman_task_is_known' => 'gearman/gearman.stub', 'gearman_task_is_running' => 'gearman/gearman.stub', 'gearman_task_job_handle' => 'gearman/gearman.stub', 'gearman_task_numerator' => 'gearman/gearman.stub', 'gearman_task_recv_data' => 'gearman/gearman.stub', 'gearman_task_return_code' => 'gearman/gearman.stub', 'gearman_task_send_workload' => 'gearman/gearman.stub', 'gearman_task_unique' => 'gearman/gearman.stub', 'gearman_verbose_name' => 'gearman/gearman.stub', 'gearman_version' => 'gearman/gearman.stub', 'gearman_worker_add_function' => 'gearman/gearman.stub', 'gearman_worker_add_options' => 'gearman/gearman.stub', 'gearman_worker_add_server' => 'gearman/gearman.stub', 'gearman_worker_add_servers' => 'gearman/gearman.stub', 'gearman_worker_clone' => 'gearman/gearman.stub', 'gearman_worker_create' => 'gearman/gearman.stub', 'gearman_worker_echo' => 'gearman/gearman.stub', 'gearman_worker_errno' => 'gearman/gearman.stub', 'gearman_worker_error' => 'gearman/gearman.stub', 'gearman_worker_grab_job' => 'gearman/gearman.stub', 'gearman_worker_options' => 'gearman/gearman.stub', 'gearman_worker_register' => 'gearman/gearman.stub', 'gearman_worker_remove_options' => 'gearman/gearman.stub', 'gearman_worker_return_code' => 'gearman/gearman.stub', 'gearman_worker_set_options' => 'gearman/gearman.stub', 'gearman_worker_set_timeout' => 'gearman/gearman.stub', 'gearman_worker_timeout' => 'gearman/gearman.stub', 'gearman_worker_unregister' => 'gearman/gearman.stub', 'gearman_worker_unregister_all' => 'gearman/gearman.stub', 'gearman_worker_wait' => 'gearman/gearman.stub', 'gearman_worker_work' => 'gearman/gearman.stub', 'geoip_asnum_by_name' => 'geoip/geoip.stub', 'geoip_continent_code_by_name' => 'geoip/geoip.stub', 'geoip_country_code3_by_name' => 'geoip/geoip.stub', 'geoip_country_code_by_name' => 'geoip/geoip.stub', 'geoip_country_name_by_name' => 'geoip/geoip.stub', 'geoip_database_info' => 'geoip/geoip.stub', 'geoip_db_avail' => 'geoip/geoip.stub', 'geoip_db_filename' => 'geoip/geoip.stub', 'geoip_db_get_all_info' => 'geoip/geoip.stub', 'geoip_id_by_name' => 'geoip/geoip.stub', 'geoip_isp_by_name' => 'geoip/geoip.stub', 'geoip_netspeedcell_by_name' => 'geoip/geoip.stub', 'geoip_org_by_name' => 'geoip/geoip.stub', 'geoip_record_by_name' => 'geoip/geoip.stub', 'geoip_region_by_name' => 'geoip/geoip.stub', 'geoip_region_name_by_code' => 'geoip/geoip.stub', 'geoip_setup_custom_directory' => 'geoip/geoip.stub', 'geoip_time_zone_by_country_and_region' => 'geoip/geoip.stub', 'get_browser' => 'standard/standard_7.stub', 'get_call_stack' => 'ZendDebugger/ZendDebugger.stub', 'get_called_class' => 'Core/Core.stub', 'get_cfg_var' => 'standard/standard_3.stub', 'get_class' => 'Core/Core.stub', 'get_class_methods' => 'Core/Core.stub', 'get_class_vars' => 'Core/Core.stub', 'get_current_user' => 'standard/standard_3.stub', 'get_debug_type' => 'standard/standard_9.stub', 'get_declared_classes' => 'Core/Core.stub', 'get_declared_interfaces' => 'Core/Core.stub', 'get_declared_traits' => 'Core/Core.stub', 'get_defined_constants' => 'Core/Core.stub', 'get_defined_functions' => 'Core/Core.stub', 'get_defined_vars' => 'Core/Core.stub', 'get_extension_funcs' => 'Core/Core.stub', 'get_headers' => 'standard/standard_6.stub', 'get_html_translation_table' => 'standard/standard_0.stub', 'get_include_path' => 'standard/standard_4.stub', 'get_included_files' => 'Core/Core.stub', 'get_loaded_extensions' => 'Core/Core.stub', 'get_magic_quotes_gpc' => 'standard/standard_3.stub', 'get_magic_quotes_runtime' => 'standard/standard_3.stub', 'get_mangled_object_vars' => 'standard/standard_9.stub', 'get_meta_tags' => 'standard/standard_6.stub', 'get_object_vars' => 'Core/Core.stub', 'get_parent_class' => 'Core/Core.stub', 'get_required_files' => 'Core/Core.stub', 'get_resource_id' => 'standard/standard_9.stub', 'get_resource_type' => 'Core/Core.stub', 'get_resources' => 'Core/Core.stub', 'getallheaders' => 'standard/standard_4.stub', 'getcwd' => 'standard/standard_7.stub', 'getdate' => 'date/date.stub', 'getdir' => 'standard/standard_7.stub', 'getenv' => 'standard/standard_3.stub', 'gethostbyaddr' => 'standard/standard_4.stub', 'gethostbyname' => 'standard/standard_4.stub', 'gethostbynamel' => 'standard/standard_4.stub', 'gethostname' => 'standard/standard_4.stub', 'getimagesize' => 'standard/standard_0.stub', 'getimagesizefromstring' => 'standard/standard_8.stub', 'getlastmod' => 'standard/standard_3.stub', 'getmxrr' => 'standard/standard_4.stub', 'getmygid' => 'standard/standard_2.stub', 'getmyinode' => 'standard/standard_2.stub', 'getmypid' => 'standard/standard_2.stub', 'getmyuid' => 'standard/standard_2.stub', 'getopt' => 'standard/standard_3.stub', 'getprotobyname' => 'standard/standard_2.stub', 'getprotobynumber' => 'standard/standard_2.stub', 'getrandmax' => 'random/random.stub', 'getrusage' => 'standard/standard_3.stub', 'getservbyname' => 'standard/standard_2.stub', 'getservbyport' => 'standard/standard_2.stub', 'gettext' => 'gettext/gettext.stub', 'gettimeofday' => 'standard/standard_3.stub', 'gettype' => 'standard/standard_5.stub', 'glob' => 'standard/standard_7.stub', 'gmdate' => 'date/date.stub', 'gmmktime' => 'date/date.stub', 'gmp_abs' => 'gmp/gmp.stub', 'gmp_add' => 'gmp/gmp.stub', 'gmp_and' => 'gmp/gmp.stub', 'gmp_binomial' => 'gmp/gmp.stub', 'gmp_clrbit' => 'gmp/gmp.stub', 'gmp_cmp' => 'gmp/gmp.stub', 'gmp_com' => 'gmp/gmp.stub', 'gmp_div' => 'gmp/gmp.stub', 'gmp_div_q' => 'gmp/gmp.stub', 'gmp_div_qr' => 'gmp/gmp.stub', 'gmp_div_r' => 'gmp/gmp.stub', 'gmp_divexact' => 'gmp/gmp.stub', 'gmp_export' => 'gmp/gmp.stub', 'gmp_fact' => 'gmp/gmp.stub', 'gmp_gcd' => 'gmp/gmp.stub', 'gmp_gcdext' => 'gmp/gmp.stub', 'gmp_hamdist' => 'gmp/gmp.stub', 'gmp_import' => 'gmp/gmp.stub', 'gmp_init' => 'gmp/gmp.stub', 'gmp_intval' => 'gmp/gmp.stub', 'gmp_invert' => 'gmp/gmp.stub', 'gmp_jacobi' => 'gmp/gmp.stub', 'gmp_kronecker' => 'gmp/gmp.stub', 'gmp_lcm' => 'gmp/gmp.stub', 'gmp_legendre' => 'gmp/gmp.stub', 'gmp_mod' => 'gmp/gmp.stub', 'gmp_mul' => 'gmp/gmp.stub', 'gmp_neg' => 'gmp/gmp.stub', 'gmp_nextprime' => 'gmp/gmp.stub', 'gmp_or' => 'gmp/gmp.stub', 'gmp_perfect_power' => 'gmp/gmp.stub', 'gmp_perfect_square' => 'gmp/gmp.stub', 'gmp_popcount' => 'gmp/gmp.stub', 'gmp_pow' => 'gmp/gmp.stub', 'gmp_powm' => 'gmp/gmp.stub', 'gmp_prob_prime' => 'gmp/gmp.stub', 'gmp_random' => 'gmp/gmp.stub', 'gmp_random_bits' => 'gmp/gmp.stub', 'gmp_random_range' => 'gmp/gmp.stub', 'gmp_random_seed' => 'gmp/gmp.stub', 'gmp_root' => 'gmp/gmp.stub', 'gmp_rootrem' => 'gmp/gmp.stub', 'gmp_scan0' => 'gmp/gmp.stub', 'gmp_scan1' => 'gmp/gmp.stub', 'gmp_setbit' => 'gmp/gmp.stub', 'gmp_sign' => 'gmp/gmp.stub', 'gmp_sqrt' => 'gmp/gmp.stub', 'gmp_sqrtrem' => 'gmp/gmp.stub', 'gmp_strval' => 'gmp/gmp.stub', 'gmp_sub' => 'gmp/gmp.stub', 'gmp_testbit' => 'gmp/gmp.stub', 'gmp_xor' => 'gmp/gmp.stub', 'gmstrftime' => 'date/date.stub', 'gnupg_adddecryptkey' => 'gnupg/gnupg.stub', 'gnupg_addencryptkey' => 'gnupg/gnupg.stub', 'gnupg_addsignkey' => 'gnupg/gnupg.stub', 'gnupg_cleardecryptkeys' => 'gnupg/gnupg.stub', 'gnupg_clearencryptkeys' => 'gnupg/gnupg.stub', 'gnupg_clearsignkeys' => 'gnupg/gnupg.stub', 'gnupg_decrypt' => 'gnupg/gnupg.stub', 'gnupg_decryptverify' => 'gnupg/gnupg.stub', 'gnupg_deletekey' => 'gnupg/gnupg.stub', 'gnupg_encrypt' => 'gnupg/gnupg.stub', 'gnupg_encryptsign' => 'gnupg/gnupg.stub', 'gnupg_export' => 'gnupg/gnupg.stub', 'gnupg_getengineinfo' => 'gnupg/gnupg.stub', 'gnupg_geterror' => 'gnupg/gnupg.stub', 'gnupg_geterrorinfo' => 'gnupg/gnupg.stub', 'gnupg_getprotocol' => 'gnupg/gnupg.stub', 'gnupg_gettrustlist' => 'gnupg/gnupg.stub', 'gnupg_import' => 'gnupg/gnupg.stub', 'gnupg_init' => 'gnupg/gnupg.stub', 'gnupg_keyinfo' => 'gnupg/gnupg.stub', 'gnupg_listsignatures' => 'gnupg/gnupg.stub', 'gnupg_setarmor' => 'gnupg/gnupg.stub', 'gnupg_seterrormode' => 'gnupg/gnupg.stub', 'gnupg_setsignmode' => 'gnupg/gnupg.stub', 'gnupg_sign' => 'gnupg/gnupg.stub', 'gnupg_verify' => 'gnupg/gnupg.stub', 'go' => 'swoole/functions.stub', 'grapheme_extract' => 'intl/intl.stub', 'grapheme_str_split' => 'intl/intl.stub', 'grapheme_stripos' => 'intl/intl.stub', 'grapheme_stristr' => 'intl/intl.stub', 'grapheme_strlen' => 'intl/intl.stub', 'grapheme_strpos' => 'intl/intl.stub', 'grapheme_strripos' => 'intl/intl.stub', 'grapheme_strrpos' => 'intl/intl.stub', 'grapheme_strstr' => 'intl/intl.stub', 'grapheme_substr' => 'intl/intl.stub', 'gregoriantojd' => 'calendar/calendar.stub', 'gzclose' => 'zlib/zlib.stub', 'gzcompress' => 'zlib/zlib.stub', 'gzdecode' => 'zlib/zlib.stub', 'gzdeflate' => 'zlib/zlib.stub', 'gzencode' => 'zlib/zlib.stub', 'gzeof' => 'zlib/zlib.stub', 'gzfile' => 'zlib/zlib.stub', 'gzgetc' => 'zlib/zlib.stub', 'gzgets' => 'zlib/zlib.stub', 'gzgetss' => 'zlib/zlib.stub', 'gzinflate' => 'zlib/zlib.stub', 'gzopen' => 'zlib/zlib.stub', 'gzpassthru' => 'zlib/zlib.stub', 'gzputs' => 'zlib/zlib.stub', 'gzread' => 'zlib/zlib.stub', 'gzrewind' => 'zlib/zlib.stub', 'gzseek' => 'zlib/zlib.stub', 'gztell' => 'zlib/zlib.stub', 'gzuncompress' => 'zlib/zlib.stub', 'gzwrite' => 'zlib/zlib.stub', 'hash' => 'hash/hash.stub', 'hash_algos' => 'hash/hash.stub', 'hash_copy' => 'hash/hash.stub', 'hash_equals' => 'hash/hash.stub', 'hash_file' => 'hash/hash.stub', 'hash_final' => 'hash/hash.stub', 'hash_hkdf' => 'hash/hash.stub', 'hash_hmac' => 'hash/hash.stub', 'hash_hmac_algos' => 'hash/hash.stub', 'hash_hmac_file' => 'hash/hash.stub', 'hash_init' => 'hash/hash.stub', 'hash_pbkdf2' => 'hash/hash.stub', 'hash_update' => 'hash/hash.stub', 'hash_update_file' => 'hash/hash.stub', 'hash_update_stream' => 'hash/hash.stub', 'header' => 'standard/standard_4.stub', 'header_register_callback' => 'standard/standard_8.stub', 'header_remove' => 'standard/standard_4.stub', 'headers_list' => 'standard/standard_4.stub', 'headers_send' => 'frankenphp/frankenphp.stub', 'headers_sent' => 'standard/standard_4.stub', 'hebrev' => 'standard/standard_1.stub', 'hebrevc' => 'standard/standard_1.stub', 'hex2bin' => 'standard/_standard_manual.stub', 'hexdec' => 'standard/standard_3.stub', 'highlight_file' => 'standard/standard_4.stub', 'highlight_string' => 'standard/standard_4.stub', 'hrtime' => 'standard/standard_4.stub', 'html_entity_decode' => 'standard/standard_0.stub', 'htmlentities' => 'standard/standard_0.stub', 'htmlspecialchars' => 'standard/standard_0.stub', 'htmlspecialchars_decode' => 'standard/standard_0.stub', 'http_build_cookie' => 'http/http.stub', 'http_build_query' => 'standard/standard_2.stub', 'http_build_str' => 'http/http.stub', 'http_build_url' => 'http/http.stub', 'http_cache_etag' => 'http/http.stub', 'http_cache_last_modified' => 'http/http.stub', 'http_chunked_decode' => 'http/http.stub', 'http_clear_last_response_headers' => 'standard/standard_10.stub', 'http_date' => 'http/http.stub', 'http_deflate' => 'http/http.stub', 'http_get' => 'http/http.stub', 'http_get_last_response_headers' => 'standard/standard_10.stub', 'http_get_request_body' => 'http/http.stub', 'http_get_request_body_stream' => 'http/http.stub', 'http_get_request_headers' => 'http/http.stub', 'http_head' => 'http/http.stub', 'http_inflate' => 'http/http.stub', 'http_match_etag' => 'http/http.stub', 'http_match_modified' => 'http/http.stub', 'http_match_request_header' => 'http/http.stub', 'http_negotiate_charset' => 'http/http.stub', 'http_negotiate_content_type' => 'http/http.stub', 'http_negotiate_language' => 'http/http.stub', 'http_parse_cookie' => 'http/http.stub', 'http_parse_headers' => 'http/http.stub', 'http_parse_message' => 'http/http.stub', 'http_parse_params' => 'http/http.stub', 'http_persistent_handles_clean' => 'http/http.stub', 'http_persistent_handles_count' => 'http/http.stub', 'http_persistent_handles_ident' => 'http/http.stub', 'http_post_data' => 'http/http.stub', 'http_post_fields' => 'http/http.stub', 'http_put_data' => 'http/http.stub', 'http_put_file' => 'http/http.stub', 'http_put_stream' => 'http/http.stub', 'http_redirect' => 'http/http.stub', 'http_request' => 'http/http.stub', 'http_request_body_encode' => 'http/http.stub', 'http_request_method_exists' => 'http/http.stub', 'http_request_method_name' => 'http/http.stub', 'http_request_method_register' => 'http/http.stub', 'http_request_method_unregister' => 'http/http.stub', 'http_response_code' => 'standard/_standard_manual.stub', 'http_send_content_disposition' => 'http/http.stub', 'http_send_content_type' => 'http/http.stub', 'http_send_data' => 'http/http.stub', 'http_send_file' => 'http/http.stub', 'http_send_last_modified' => 'http/http.stub', 'http_send_status' => 'http/http.stub', 'http_send_stream' => 'http/http.stub', 'http_support' => 'http/http.stub', 'http_throttle' => 'http/http.stub', 'hypot' => 'standard/standard_3.stub', 'ibase_add_user' => 'interbase/interbase.stub', 'ibase_affected_rows' => 'interbase/interbase.stub', 'ibase_backup' => 'interbase/interbase.stub', 'ibase_blob_add' => 'interbase/interbase.stub', 'ibase_blob_cancel' => 'interbase/interbase.stub', 'ibase_blob_close' => 'interbase/interbase.stub', 'ibase_blob_create' => 'interbase/interbase.stub', 'ibase_blob_echo' => 'interbase/interbase.stub', 'ibase_blob_get' => 'interbase/interbase.stub', 'ibase_blob_import' => 'interbase/interbase.stub', 'ibase_blob_info' => 'interbase/interbase.stub', 'ibase_blob_open' => 'interbase/interbase.stub', 'ibase_close' => 'interbase/interbase.stub', 'ibase_commit' => 'interbase/interbase.stub', 'ibase_commit_ret' => 'interbase/interbase.stub', 'ibase_connect' => 'interbase/interbase.stub', 'ibase_db_info' => 'interbase/interbase.stub', 'ibase_delete_user' => 'interbase/interbase.stub', 'ibase_drop_db' => 'interbase/interbase.stub', 'ibase_errcode' => 'interbase/interbase.stub', 'ibase_errmsg' => 'interbase/interbase.stub', 'ibase_execute' => 'interbase/interbase.stub', 'ibase_fetch_assoc' => 'interbase/interbase.stub', 'ibase_fetch_object' => 'interbase/interbase.stub', 'ibase_fetch_row' => 'interbase/interbase.stub', 'ibase_field_info' => 'interbase/interbase.stub', 'ibase_free_event_handler' => 'interbase/interbase.stub', 'ibase_free_query' => 'interbase/interbase.stub', 'ibase_free_result' => 'interbase/interbase.stub', 'ibase_gen_id' => 'interbase/interbase.stub', 'ibase_maintain_db' => 'interbase/interbase.stub', 'ibase_modify_user' => 'interbase/interbase.stub', 'ibase_name_result' => 'interbase/interbase.stub', 'ibase_num_fields' => 'interbase/interbase.stub', 'ibase_num_params' => 'interbase/interbase.stub', 'ibase_param_info' => 'interbase/interbase.stub', 'ibase_pconnect' => 'interbase/interbase.stub', 'ibase_prepare' => 'interbase/interbase.stub', 'ibase_query' => 'interbase/interbase.stub', 'ibase_restore' => 'interbase/interbase.stub', 'ibase_rollback' => 'interbase/interbase.stub', 'ibase_rollback_ret' => 'interbase/interbase.stub', 'ibase_server_info' => 'interbase/interbase.stub', 'ibase_service_attach' => 'interbase/interbase.stub', 'ibase_service_detach' => 'interbase/interbase.stub', 'ibase_set_event_handler' => 'interbase/interbase.stub', 'ibase_trans' => 'interbase/interbase.stub', 'ibase_wait_event' => 'interbase/interbase.stub', 'iconv' => 'iconv/iconv.stub', 'iconv_get_encoding' => 'iconv/iconv.stub', 'iconv_mime_decode' => 'iconv/iconv.stub', 'iconv_mime_decode_headers' => 'iconv/iconv.stub', 'iconv_mime_encode' => 'iconv/iconv.stub', 'iconv_set_encoding' => 'iconv/iconv.stub', 'iconv_strlen' => 'iconv/iconv.stub', 'iconv_strpos' => 'iconv/iconv.stub', 'iconv_strrpos' => 'iconv/iconv.stub', 'iconv_substr' => 'iconv/iconv.stub', 'idate' => 'date/date.stub', 'idn_to_ascii' => 'intl/intl.stub', 'idn_to_utf8' => 'intl/intl.stub', 'igbinary_serialize' => 'igbinary/igbinary.stub', 'igbinary_unserialize' => 'igbinary/igbinary.stub', 'ignore_user_abort' => 'standard/standard_4.stub', 'image2wbmp' => 'gd/gd.stub', 'image_type_to_extension' => 'standard/standard_0.stub', 'image_type_to_mime_type' => 'standard/standard_0.stub', 'imageaffine' => 'gd/gd.stub', 'imageaffinematrixconcat' => 'gd/gd.stub', 'imageaffinematrixget' => 'gd/gd.stub', 'imagealphablending' => 'gd/gd.stub', 'imageantialias' => 'gd/gd.stub', 'imagearc' => 'gd/gd.stub', 'imageavif' => 'gd/gd.stub', 'imagebmp' => 'gd/gd.stub', 'imagechar' => 'gd/gd.stub', 'imagecharup' => 'gd/gd.stub', 'imagecolorallocate' => 'gd/gd.stub', 'imagecolorallocatealpha' => 'gd/gd.stub', 'imagecolorat' => 'gd/gd.stub', 'imagecolorclosest' => 'gd/gd.stub', 'imagecolorclosestalpha' => 'gd/gd.stub', 'imagecolorclosesthwb' => 'gd/gd.stub', 'imagecolordeallocate' => 'gd/gd.stub', 'imagecolorexact' => 'gd/gd.stub', 'imagecolorexactalpha' => 'gd/gd.stub', 'imagecolormatch' => 'gd/gd.stub', 'imagecolorresolve' => 'gd/gd.stub', 'imagecolorresolvealpha' => 'gd/gd.stub', 'imagecolorset' => 'gd/gd.stub', 'imagecolorsforindex' => 'gd/gd.stub', 'imagecolorstotal' => 'gd/gd.stub', 'imagecolortransparent' => 'gd/gd.stub', 'imageconvolution' => 'gd/gd.stub', 'imagecopy' => 'gd/gd.stub', 'imagecopymerge' => 'gd/gd.stub', 'imagecopymergegray' => 'gd/gd.stub', 'imagecopyresampled' => 'gd/gd.stub', 'imagecopyresized' => 'gd/gd.stub', 'imagecreate' => 'gd/gd.stub', 'imagecreatefromavif' => 'gd/gd.stub', 'imagecreatefrombmp' => 'gd/gd.stub', 'imagecreatefromgd' => 'gd/gd.stub', 'imagecreatefromgd2' => 'gd/gd.stub', 'imagecreatefromgd2part' => 'gd/gd.stub', 'imagecreatefromgif' => 'gd/gd.stub', 'imagecreatefromjpeg' => 'gd/gd.stub', 'imagecreatefrompng' => 'gd/gd.stub', 'imagecreatefromstring' => 'gd/gd.stub', 'imagecreatefromtga' => 'gd/gd.stub', 'imagecreatefromwbmp' => 'gd/gd.stub', 'imagecreatefromwebp' => 'gd/gd.stub', 'imagecreatefromxbm' => 'gd/gd.stub', 'imagecreatefromxpm' => 'gd/gd.stub', 'imagecreatetruecolor' => 'gd/gd.stub', 'imagecrop' => 'gd/gd.stub', 'imagecropauto' => 'gd/gd.stub', 'imagedashedline' => 'gd/gd.stub', 'imagedestroy' => 'gd/gd.stub', 'imageellipse' => 'gd/gd.stub', 'imagefill' => 'gd/gd.stub', 'imagefilledarc' => 'gd/gd.stub', 'imagefilledellipse' => 'gd/gd.stub', 'imagefilledpolygon' => 'gd/gd.stub', 'imagefilledrectangle' => 'gd/gd.stub', 'imagefilltoborder' => 'gd/gd.stub', 'imagefilter' => 'gd/gd.stub', 'imageflip' => 'gd/gd.stub', 'imagefontheight' => 'gd/gd.stub', 'imagefontwidth' => 'gd/gd.stub', 'imageftbbox' => 'gd/gd.stub', 'imagefttext' => 'gd/gd.stub', 'imagegammacorrect' => 'gd/gd.stub', 'imagegd' => 'gd/gd.stub', 'imagegd2' => 'gd/gd.stub', 'imagegetclip' => 'gd/gd.stub', 'imagegetinterpolation' => 'gd/gd.stub', 'imagegif' => 'gd/gd.stub', 'imagegrabscreen' => 'gd/gd.stub', 'imagegrabwindow' => 'gd/gd.stub', 'imageinterlace' => 'gd/gd.stub', 'imageistruecolor' => 'gd/gd.stub', 'imagejpeg' => 'gd/gd.stub', 'imagelayereffect' => 'gd/gd.stub', 'imageline' => 'gd/gd.stub', 'imageloadfont' => 'gd/gd.stub', 'imageopenpolygon' => 'gd/gd.stub', 'imagepalettecopy' => 'gd/gd.stub', 'imagepalettetotruecolor' => 'gd/gd.stub', 'imagepng' => 'gd/gd.stub', 'imagepolygon' => 'gd/gd.stub', 'imagepsbbox' => 'gd/gd.stub', 'imagepsencodefont' => 'gd/gd.stub', 'imagepsextendfont' => 'gd/gd.stub', 'imagepsfreefont' => 'gd/gd.stub', 'imagepsloadfont' => 'gd/gd.stub', 'imagepsslantfont' => 'gd/gd.stub', 'imagepstext' => 'gd/gd.stub', 'imagerectangle' => 'gd/gd.stub', 'imageresolution' => 'gd/gd.stub', 'imagerotate' => 'gd/gd.stub', 'imagesavealpha' => 'gd/gd.stub', 'imagescale' => 'gd/gd.stub', 'imagesetbrush' => 'gd/gd.stub', 'imagesetclip' => 'gd/gd.stub', 'imagesetinterpolation' => 'gd/gd.stub', 'imagesetpixel' => 'gd/gd.stub', 'imagesetstyle' => 'gd/gd.stub', 'imagesetthickness' => 'gd/gd.stub', 'imagesettile' => 'gd/gd.stub', 'imagestring' => 'gd/gd.stub', 'imagestringup' => 'gd/gd.stub', 'imagesx' => 'gd/gd.stub', 'imagesy' => 'gd/gd.stub', 'imagetruecolortopalette' => 'gd/gd.stub', 'imagettfbbox' => 'gd/gd.stub', 'imagettftext' => 'gd/gd.stub', 'imagetypes' => 'gd/gd.stub', 'imagewbmp' => 'gd/gd.stub', 'imagewebp' => 'gd/gd.stub', 'imagexbm' => 'gd/gd.stub', 'imap_8bit' => 'imap/imap.stub', 'imap_alerts' => 'imap/imap.stub', 'imap_append' => 'imap/imap.stub', 'imap_base64' => 'imap/imap.stub', 'imap_binary' => 'imap/imap.stub', 'imap_body' => 'imap/imap.stub', 'imap_bodystruct' => 'imap/imap.stub', 'imap_check' => 'imap/imap.stub', 'imap_clearflag_full' => 'imap/imap.stub', 'imap_close' => 'imap/imap.stub', 'imap_create' => 'imap/imap.stub', 'imap_createmailbox' => 'imap/imap.stub', 'imap_delete' => 'imap/imap.stub', 'imap_deletemailbox' => 'imap/imap.stub', 'imap_errors' => 'imap/imap.stub', 'imap_expunge' => 'imap/imap.stub', 'imap_fetch_overview' => 'imap/imap.stub', 'imap_fetchbody' => 'imap/imap.stub', 'imap_fetchheader' => 'imap/imap.stub', 'imap_fetchmime' => 'imap/imap.stub', 'imap_fetchstructure' => 'imap/imap.stub', 'imap_fetchtext' => 'imap/imap.stub', 'imap_gc' => 'imap/imap.stub', 'imap_get_quota' => 'imap/imap.stub', 'imap_get_quotaroot' => 'imap/imap.stub', 'imap_getacl' => 'imap/imap.stub', 'imap_getannotation' => 'imap/imap.stub', 'imap_getmailboxes' => 'imap/imap.stub', 'imap_getsubscribed' => 'imap/imap.stub', 'imap_header' => 'imap/imap.stub', 'imap_headerinfo' => 'imap/imap.stub', 'imap_headers' => 'imap/imap.stub', 'imap_is_open' => 'imap/imap.stub', 'imap_last_error' => 'imap/imap.stub', 'imap_list' => 'imap/imap.stub', 'imap_listmailbox' => 'imap/imap.stub', 'imap_listscan' => 'imap/imap.stub', 'imap_listsubscribed' => 'imap/imap.stub', 'imap_lsub' => 'imap/imap.stub', 'imap_mail' => 'imap/imap.stub', 'imap_mail_compose' => 'imap/imap.stub', 'imap_mail_copy' => 'imap/imap.stub', 'imap_mail_move' => 'imap/imap.stub', 'imap_mailboxmsginfo' => 'imap/imap.stub', 'imap_mime_header_decode' => 'imap/imap.stub', 'imap_msgno' => 'imap/imap.stub', 'imap_mutf7_to_utf8' => 'imap/imap.stub', 'imap_myrights' => 'imap/imap.stub', 'imap_num_msg' => 'imap/imap.stub', 'imap_num_recent' => 'imap/imap.stub', 'imap_open' => 'imap/imap.stub', 'imap_ping' => 'imap/imap.stub', 'imap_qprint' => 'imap/imap.stub', 'imap_rename' => 'imap/imap.stub', 'imap_renamemailbox' => 'imap/imap.stub', 'imap_reopen' => 'imap/imap.stub', 'imap_rfc822_parse_adrlist' => 'imap/imap.stub', 'imap_rfc822_parse_headers' => 'imap/imap.stub', 'imap_rfc822_write_address' => 'imap/imap.stub', 'imap_savebody' => 'imap/imap.stub', 'imap_scan' => 'imap/imap.stub', 'imap_scanmailbox' => 'imap/imap.stub', 'imap_search' => 'imap/imap.stub', 'imap_set_quota' => 'imap/imap.stub', 'imap_setacl' => 'imap/imap.stub', 'imap_setannotation' => 'imap/imap.stub', 'imap_setflag_full' => 'imap/imap.stub', 'imap_sort' => 'imap/imap.stub', 'imap_status' => 'imap/imap.stub', 'imap_status_current' => 'imap/imap.stub', 'imap_subscribe' => 'imap/imap.stub', 'imap_thread' => 'imap/imap.stub', 'imap_timeout' => 'imap/imap.stub', 'imap_uid' => 'imap/imap.stub', 'imap_undelete' => 'imap/imap.stub', 'imap_unsubscribe' => 'imap/imap.stub', 'imap_utf7_decode' => 'imap/imap.stub', 'imap_utf7_encode' => 'imap/imap.stub', 'imap_utf8' => 'imap/imap.stub', 'imap_utf8_to_mutf7' => 'imap/imap.stub', 'implode' => 'standard/standard_1.stub', 'import_request_variables' => 'standard/standard_3.stub', 'in_array' => 'standard/standard_8.stub', 'inet_ntop' => 'standard/standard_3.stub', 'inet_pton' => 'standard/standard_3.stub', 'inflate_add' => 'zlib/zlib.stub', 'inflate_get_read_len' => 'zlib/zlib.stub', 'inflate_get_status' => 'zlib/zlib.stub', 'inflate_init' => 'zlib/zlib.stub', 'ini_alter' => 'standard/standard_4.stub', 'ini_get' => 'standard/standard_4.stub', 'ini_get_all' => 'standard/standard_4.stub', 'ini_parse_quantity' => 'standard/standard_4.stub', 'ini_restore' => 'standard/standard_4.stub', 'ini_set' => 'standard/standard_4.stub', 'inotify_add_watch' => 'inotify/inotify.stub', 'inotify_init' => 'inotify/inotify.stub', 'inotify_queue_len' => 'inotify/inotify.stub', 'inotify_read' => 'inotify/inotify.stub', 'inotify_rm_watch' => 'inotify/inotify.stub', 'intcal_get_maximum' => 'intl/intl.stub', 'intdiv' => 'standard/standard_3.stub', 'interface_exists' => 'Core/Core.stub', 'intl_error_name' => 'intl/intl.stub', 'intl_get' => 'intl/intl.stub', 'intl_get_error_code' => 'intl/intl.stub', 'intl_get_error_message' => 'intl/intl.stub', 'intl_is_failure' => 'intl/intl.stub', 'intlcal_add' => 'intl/intl.stub', 'intlcal_after' => 'intl/intl.stub', 'intlcal_before' => 'intl/intl.stub', 'intlcal_clear' => 'intl/intl.stub', 'intlcal_create_instance' => 'intl/intl.stub', 'intlcal_equals' => 'intl/intl.stub', 'intlcal_field_difference' => 'intl/intl.stub', 'intlcal_from_date_time' => 'intl/intl.stub', 'intlcal_get' => 'intl/intl.stub', 'intlcal_get_actual_maximum' => 'intl/intl.stub', 'intlcal_get_actual_minimum' => 'intl/intl.stub', 'intlcal_get_available_locales' => 'intl/intl.stub', 'intlcal_get_day_of_week_type' => 'intl/intl.stub', 'intlcal_get_error_code' => 'intl/intl.stub', 'intlcal_get_error_message' => 'intl/intl.stub', 'intlcal_get_first_day_of_week' => 'intl/intl.stub', 'intlcal_get_greatest_minimum' => 'intl/intl.stub', 'intlcal_get_keyword_values_for_locale' => 'intl/intl.stub', 'intlcal_get_least_maximum' => 'intl/intl.stub', 'intlcal_get_locale' => 'intl/intl.stub', 'intlcal_get_maximum' => 'intl/intl.stub', 'intlcal_get_minimal_days_in_first_week' => 'intl/intl.stub', 'intlcal_get_minimum' => 'intl/intl.stub', 'intlcal_get_now' => 'intl/intl.stub', 'intlcal_get_repeated_wall_time_option' => 'intl/intl.stub', 'intlcal_get_skipped_wall_time_option' => 'intl/intl.stub', 'intlcal_get_time' => 'intl/intl.stub', 'intlcal_get_time_zone' => 'intl/intl.stub', 'intlcal_get_type' => 'intl/intl.stub', 'intlcal_get_weekend_transition' => 'intl/intl.stub', 'intlcal_greates_minimum' => 'intl/intl.stub', 'intlcal_in_daylight_time' => 'intl/intl.stub', 'intlcal_is_equivalent_to' => 'intl/intl.stub', 'intlcal_is_lenient' => 'intl/intl.stub', 'intlcal_is_set' => 'intl/intl.stub', 'intlcal_is_weekend' => 'intl/intl.stub', 'intlcal_roll' => 'intl/intl.stub', 'intlcal_set' => 'intl/intl.stub', 'intlcal_set_first_day_of_week' => 'intl/intl.stub', 'intlcal_set_lenient' => 'intl/intl.stub', 'intlcal_set_minimal_days_in_first_week' => 'intl/intl.stub', 'intlcal_set_repeated_wall_time_option' => 'intl/intl.stub', 'intlcal_set_skipped_wall_time_option' => 'intl/intl.stub', 'intlcal_set_time' => 'intl/intl.stub', 'intlcal_set_time_zone' => 'intl/intl.stub', 'intlcal_to_date_time' => 'intl/intl.stub', 'intlgregcal_create_instance' => 'intl/intl.stub', 'intlgregcal_get_gregorian_change' => 'intl/intl.stub', 'intlgregcal_is_leap_year' => 'intl/intl.stub', 'intlgregcal_set_gregorian_change' => 'intl/intl.stub', 'intltz_count_equivalent_ids' => 'intl/intl.stub', 'intltz_create_default' => 'intl/intl.stub', 'intltz_create_enumeration' => 'intl/intl.stub', 'intltz_create_time_zone' => 'intl/intl.stub', 'intltz_create_time_zone_id_enumeration' => 'intl/intl.stub', 'intltz_from_date_time_zone' => 'intl/intl.stub', 'intltz_getGMT' => 'intl/intl.stub', 'intltz_get_canonical_id' => 'intl/intl.stub', 'intltz_get_display_name' => 'intl/intl.stub', 'intltz_get_dst_savings' => 'intl/intl.stub', 'intltz_get_equivalent_id' => 'intl/intl.stub', 'intltz_get_error_code' => 'intl/intl.stub', 'intltz_get_error_message' => 'intl/intl.stub', 'intltz_get_gmt' => 'intl/intl.stub', 'intltz_get_iana_id' => 'intl/intl.stub', 'intltz_get_id' => 'intl/intl.stub', 'intltz_get_id_for_windows_id' => 'intl/intl.stub', 'intltz_get_offset' => 'intl/intl.stub', 'intltz_get_raw_offset' => 'intl/intl.stub', 'intltz_get_region' => 'intl/intl.stub', 'intltz_get_tz_data_version' => 'intl/intl.stub', 'intltz_get_unknown' => 'intl/intl.stub', 'intltz_get_windows_id' => 'intl/intl.stub', 'intltz_has_same_rules' => 'intl/intl.stub', 'intltz_to_date_time_zone' => 'intl/intl.stub', 'intltz_use_daylight_time' => 'intl/intl.stub', 'intlz_create_default' => 'intl/intl.stub', 'intval' => 'standard/standard_5.stub', 'ip2long' => 'standard/standard_3.stub', 'iptcembed' => 'standard/standard_0.stub', 'iptcparse' => 'standard/standard_0.stub', 'is_a' => 'Core/Core.stub', 'is_array' => 'standard/standard_5.stub', 'is_bool' => 'standard/standard_5.stub', 'is_callable' => 'standard/standard_5.stub', 'is_countable' => 'standard/standard_5.stub', 'is_dir' => 'standard/standard_7.stub', 'is_double' => 'standard/standard_5.stub', 'is_executable' => 'standard/standard_7.stub', 'is_file' => 'standard/standard_7.stub', 'is_finite' => 'standard/standard_3.stub', 'is_float' => 'standard/standard_5.stub', 'is_infinite' => 'standard/standard_3.stub', 'is_int' => 'standard/standard_5.stub', 'is_integer' => 'standard/standard_5.stub', 'is_iterable' => 'standard/basic.stub', 'is_link' => 'standard/standard_7.stub', 'is_long' => 'standard/standard_5.stub', 'is_nan' => 'standard/standard_3.stub', 'is_null' => 'standard/standard_5.stub', 'is_numeric' => 'standard/standard_5.stub', 'is_object' => 'standard/standard_5.stub', 'is_readable' => 'standard/standard_7.stub', 'is_real' => 'standard/standard_5.stub', 'is_resource' => 'standard/standard_5.stub', 'is_scalar' => 'standard/standard_5.stub', 'is_soap_fault' => 'soap/soap.stub', 'is_string' => 'standard/standard_5.stub', 'is_subclass_of' => 'Core/Core.stub', 'is_uploaded_file' => 'standard/standard_4.stub', 'is_writable' => 'standard/standard_7.stub', 'is_writeable' => 'standard/standard_7.stub', 'iterator_apply' => 'SPL/SPL_f.stub', 'iterator_count' => 'SPL/SPL_f.stub', 'iterator_to_array' => 'SPL/SPL_f.stub', 'java' => 'zend/zend_f.stub', 'java_last_exception_clear' => 'zend/zend_f.stub', 'java_last_exception_get' => 'zend/zend_f.stub', 'java_reload' => 'zend/zend_f.stub', 'java_require' => 'zend/zend_f.stub', 'java_set_encoding' => 'zend/zend_f.stub', 'java_set_ignore_case' => 'zend/zend_f.stub', 'java_throw_exceptions' => 'zend/zend_f.stub', 'jddayofweek' => 'calendar/calendar.stub', 'jdmonthname' => 'calendar/calendar.stub', 'jdtofrench' => 'calendar/calendar.stub', 'jdtogregorian' => 'calendar/calendar.stub', 'jdtojewish' => 'calendar/calendar.stub', 'jdtojulian' => 'calendar/calendar.stub', 'jdtounix' => 'calendar/calendar.stub', 'jewishtojd' => 'calendar/calendar.stub', 'jobqueue_license_info' => 'zend/zend_f.stub', 'join' => 'standard/standard_1.stub', 'jpeg2wbmp' => 'gd/gd.stub', 'json_decode' => 'json/json.stub', 'json_encode' => 'json/json.stub', 'json_last_error' => 'json/json.stub', 'json_last_error_msg' => 'json/json.stub', 'json_validate' => 'json/json.stub', 'juliantojd' => 'calendar/calendar.stub', 'kafka_err2name' => 'simple_kafka_client/functions.stub', 'kafka_err2str' => 'simple_kafka_client/functions.stub', 'kafka_get_err_descs' => 'simple_kafka_client/functions.stub', 'kafka_offset_tail' => 'simple_kafka_client/functions.stub', 'kafka_thread_cnt' => 'simple_kafka_client/functions.stub', 'key' => 'standard/standard_8.stub', 'key_exists' => 'standard/standard_9.stub', 'krsort' => 'standard/standard_8.stub', 'ksort' => 'standard/standard_8.stub', 'lcfirst' => 'standard/standard_1.stub', 'lcg_value' => 'random/random.stub', 'lchgrp' => 'standard/standard_7.stub', 'lchown' => 'standard/standard_7.stub', 'ldap_8859_to_t61' => 'ldap/ldap.stub', 'ldap_add' => 'ldap/ldap.stub', 'ldap_add_ext' => 'ldap/ldap.stub', 'ldap_bind' => 'ldap/ldap.stub', 'ldap_bind_ext' => 'ldap/ldap.stub', 'ldap_close' => 'ldap/ldap.stub', 'ldap_compare' => 'ldap/ldap.stub', 'ldap_connect' => 'ldap/ldap.stub', 'ldap_control_paged_result' => 'ldap/ldap.stub', 'ldap_control_paged_result_response' => 'ldap/ldap.stub', 'ldap_count_entries' => 'ldap/ldap.stub', 'ldap_count_references' => 'ldap/ldap.stub', 'ldap_delete' => 'ldap/ldap.stub', 'ldap_delete_ext' => 'ldap/ldap.stub', 'ldap_dn2ufn' => 'ldap/ldap.stub', 'ldap_err2str' => 'ldap/ldap.stub', 'ldap_errno' => 'ldap/ldap.stub', 'ldap_error' => 'ldap/ldap.stub', 'ldap_escape' => 'ldap/ldap.stub', 'ldap_exop' => 'ldap/ldap.stub', 'ldap_exop_passwd' => 'ldap/ldap.stub', 'ldap_exop_refresh' => 'ldap/ldap.stub', 'ldap_exop_sync' => 'ldap/ldap.stub', 'ldap_exop_whoami' => 'ldap/ldap.stub', 'ldap_explode_dn' => 'ldap/ldap.stub', 'ldap_first_attribute' => 'ldap/ldap.stub', 'ldap_first_entry' => 'ldap/ldap.stub', 'ldap_first_reference' => 'ldap/ldap.stub', 'ldap_free_result' => 'ldap/ldap.stub', 'ldap_get_attributes' => 'ldap/ldap.stub', 'ldap_get_dn' => 'ldap/ldap.stub', 'ldap_get_entries' => 'ldap/ldap.stub', 'ldap_get_option' => 'ldap/ldap.stub', 'ldap_get_values' => 'ldap/ldap.stub', 'ldap_get_values_len' => 'ldap/ldap.stub', 'ldap_list' => 'ldap/ldap.stub', 'ldap_mod_add' => 'ldap/ldap.stub', 'ldap_mod_add_ext' => 'ldap/ldap.stub', 'ldap_mod_del' => 'ldap/ldap.stub', 'ldap_mod_del_ext' => 'ldap/ldap.stub', 'ldap_mod_replace' => 'ldap/ldap.stub', 'ldap_mod_replace_ext' => 'ldap/ldap.stub', 'ldap_modify' => 'ldap/ldap.stub', 'ldap_modify_batch' => 'ldap/ldap.stub', 'ldap_next_attribute' => 'ldap/ldap.stub', 'ldap_next_entry' => 'ldap/ldap.stub', 'ldap_next_reference' => 'ldap/ldap.stub', 'ldap_parse_exop' => 'ldap/ldap.stub', 'ldap_parse_reference' => 'ldap/ldap.stub', 'ldap_parse_result' => 'ldap/ldap.stub', 'ldap_read' => 'ldap/ldap.stub', 'ldap_rename' => 'ldap/ldap.stub', 'ldap_rename_ext' => 'ldap/ldap.stub', 'ldap_sasl_bind' => 'ldap/ldap.stub', 'ldap_search' => 'ldap/ldap.stub', 'ldap_set_option' => 'ldap/ldap.stub', 'ldap_set_rebind_proc' => 'ldap/ldap.stub', 'ldap_sort' => 'ldap/ldap.stub', 'ldap_start_tls' => 'ldap/ldap.stub', 'ldap_t61_to_8859' => 'ldap/ldap.stub', 'ldap_unbind' => 'ldap/ldap.stub', 'levenshtein' => 'standard/standard_2.stub', 'libvirt_check_version' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_all_domain_stats' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_capabilities' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_emulator' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_encrypted' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_hostname' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_hypervisor' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_information' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_machine_types' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_maxvcpus' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_nic_models' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_secure' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_soundhw_models' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_sysinfo' => 'libvirt-php/libvirt-php.stub', 'libvirt_connect_get_uri' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_attach_device' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_block_commit' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_block_job_abort' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_block_job_info' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_block_job_set_speed' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_block_resize' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_block_stats' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_change_boot_devices' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_change_memory' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_change_vcpus' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_core_dump' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_create' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_create_xml' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_define_xml' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_destroy' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_detach_device' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_disk_add' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_disk_remove' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_autostart' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_block_info' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_connect' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_counts' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_disk_devices' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_id' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_info' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_interface_devices' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_job_info' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_metadata' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_network_info' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_next_dev_ids' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_screen_dimensions' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_screenshot' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_screenshot_api' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_uuid' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_uuid_string' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_get_xml_desc' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_has_current_snapshot' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_interface_addresses' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_interface_stats' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_is_active' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_is_persistent' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_lookup_by_id' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_lookup_by_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_lookup_by_uuid' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_lookup_by_uuid_string' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_managedsave' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_memory_peek' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_memory_stats' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_migrate' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_migrate_to_uri' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_migrate_to_uri2' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_new' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_new_get_vnc' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_nic_add' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_nic_remove' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_qemu_agent_command' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_reboot' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_reset' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_resume' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_send_key_api' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_send_keys' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_send_pointer_event' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_set_autostart' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_set_max_memory' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_set_memory' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_set_memory_flags' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_set_metadata' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_shutdown' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_snapshot_create' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_snapshot_current' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_snapshot_delete' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_snapshot_get_xml' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_snapshot_lookup_by_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_snapshot_revert' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_suspend' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_undefine' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_undefine_flags' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_update_device' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_xml_from_native' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_xml_to_native' => 'libvirt-php/libvirt-php.stub', 'libvirt_domain_xml_xpath' => 'libvirt-php/libvirt-php.stub', 'libvirt_get_iso_images' => 'libvirt-php/libvirt-php.stub', 'libvirt_get_last_error' => 'libvirt-php/libvirt-php.stub', 'libvirt_get_last_error_code' => 'libvirt-php/libvirt-php.stub', 'libvirt_get_last_error_domain' => 'libvirt-php/libvirt-php.stub', 'libvirt_has_feature' => 'libvirt-php/libvirt-php.stub', 'libvirt_image_create' => 'libvirt-php/libvirt-php.stub', 'libvirt_image_remove' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_active_domain_ids' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_active_domains' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_active_storagepools' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_all_networks' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_all_nwfilters' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_domain_resources' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_domain_snapshots' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_domains' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_inactive_domains' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_inactive_storagepools' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_networks' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_nodedevs' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_nwfilters' => 'libvirt-php/libvirt-php.stub', 'libvirt_list_storagepools' => 'libvirt-php/libvirt-php.stub', 'libvirt_logfile_set' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_define_xml' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_get' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_get_active' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_get_autostart' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_get_bridge' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_get_information' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_get_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_get_uuid' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_get_uuid_string' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_get_xml_desc' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_set_active' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_set_autostart' => 'libvirt-php/libvirt-php.stub', 'libvirt_network_undefine' => 'libvirt-php/libvirt-php.stub', 'libvirt_node_get_cpu_stats' => 'libvirt-php/libvirt-php.stub', 'libvirt_node_get_cpu_stats_for_each_cpu' => 'libvirt-php/libvirt-php.stub', 'libvirt_node_get_free_memory' => 'libvirt-php/libvirt-php.stub', 'libvirt_node_get_info' => 'libvirt-php/libvirt-php.stub', 'libvirt_node_get_mem_stats' => 'libvirt-php/libvirt-php.stub', 'libvirt_nodedev_capabilities' => 'libvirt-php/libvirt-php.stub', 'libvirt_nodedev_get' => 'libvirt-php/libvirt-php.stub', 'libvirt_nodedev_get_information' => 'libvirt-php/libvirt-php.stub', 'libvirt_nodedev_get_xml_desc' => 'libvirt-php/libvirt-php.stub', 'libvirt_nwfilter_define_xml' => 'libvirt-php/libvirt-php.stub', 'libvirt_nwfilter_get_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_nwfilter_get_uuid' => 'libvirt-php/libvirt-php.stub', 'libvirt_nwfilter_get_uuid_string' => 'libvirt-php/libvirt-php.stub', 'libvirt_nwfilter_get_xml_desc' => 'libvirt-php/libvirt-php.stub', 'libvirt_nwfilter_lookup_by_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_nwfilter_lookup_by_uuid_string' => 'libvirt-php/libvirt-php.stub', 'libvirt_nwfilter_undefine' => 'libvirt-php/libvirt-php.stub', 'libvirt_print_binding_resources' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_build' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_create' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_define_xml' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_delete' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_destroy' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_get_autostart' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_get_info' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_get_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_get_uuid_string' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_get_volume_count' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_get_xml_desc' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_is_active' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_list_volumes' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_lookup_by_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_lookup_by_uuid_string' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_lookup_by_volume' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_refresh' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_set_autostart' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagepool_undefine' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_create_xml' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_create_xml_from' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_delete' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_download' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_get_info' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_get_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_get_path' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_get_xml_desc' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_lookup_by_name' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_lookup_by_path' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_resize' => 'libvirt-php/libvirt-php.stub', 'libvirt_storagevolume_upload' => 'libvirt-php/libvirt-php.stub', 'libvirt_stream_abort' => 'libvirt-php/libvirt-php.stub', 'libvirt_stream_close' => 'libvirt-php/libvirt-php.stub', 'libvirt_stream_create' => 'libvirt-php/libvirt-php.stub', 'libvirt_stream_finish' => 'libvirt-php/libvirt-php.stub', 'libvirt_stream_recv' => 'libvirt-php/libvirt-php.stub', 'libvirt_stream_send' => 'libvirt-php/libvirt-php.stub', 'libvirt_version' => 'libvirt-php/libvirt-php.stub', 'libxml_clear_errors' => 'libxml/libxml.stub', 'libxml_disable_entity_loader' => 'libxml/libxml.stub', 'libxml_get_errors' => 'libxml/libxml.stub', 'libxml_get_external_entity_loader' => 'libxml/libxml.stub', 'libxml_get_last_error' => 'libxml/libxml.stub', 'libxml_set_external_entity_loader' => 'libxml/libxml.stub', 'libxml_set_streams_context' => 'libxml/libxml.stub', 'libxml_use_internal_errors' => 'libxml/libxml.stub', 'link' => 'standard/standard_2.stub', 'linkinfo' => 'standard/standard_2.stub', 'locale_accept_from_http' => 'intl/intl.stub', 'locale_canonicalize' => 'intl/intl.stub', 'locale_compose' => 'intl/intl.stub', 'locale_filter_matches' => 'intl/intl.stub', 'locale_get_all_variants' => 'intl/intl.stub', 'locale_get_default' => 'intl/intl.stub', 'locale_get_display_language' => 'intl/intl.stub', 'locale_get_display_name' => 'intl/intl.stub', 'locale_get_display_region' => 'intl/intl.stub', 'locale_get_display_script' => 'intl/intl.stub', 'locale_get_display_variant' => 'intl/intl.stub', 'locale_get_keywords' => 'intl/intl.stub', 'locale_get_primary_language' => 'intl/intl.stub', 'locale_get_region' => 'intl/intl.stub', 'locale_get_script' => 'intl/intl.stub', 'locale_lookup' => 'intl/intl.stub', 'locale_parse' => 'intl/intl.stub', 'locale_set_default' => 'intl/intl.stub', 'localeconv' => 'standard/standard_1.stub', 'localtime' => 'date/date.stub', 'log' => 'standard/standard_3.stub', 'log10' => 'standard/standard_3.stub', 'log1p' => 'standard/standard_3.stub', 'long2ip' => 'standard/standard_3.stub', 'lstat' => 'standard/standard_7.stub', 'ltrim' => 'standard/standard_1.stub', 'lzf_compress' => 'lzf/lzf.stub', 'lzf_decompress' => 'lzf/lzf.stub', 'lzf_optimized_for' => 'lzf/lzf.stub', 'magic_quotes_runtime' => 'standard/standard_3.stub', 'mail' => 'standard/standard_7.stub', 'mailparse_determine_best_xfer_encoding' => 'mailparse/mailparse.stub', 'mailparse_msg_create' => 'mailparse/mailparse.stub', 'mailparse_msg_extract_part' => 'mailparse/mailparse.stub', 'mailparse_msg_extract_part_file' => 'mailparse/mailparse.stub', 'mailparse_msg_extract_whole_part_file' => 'mailparse/mailparse.stub', 'mailparse_msg_free' => 'mailparse/mailparse.stub', 'mailparse_msg_get_part' => 'mailparse/mailparse.stub', 'mailparse_msg_get_part_data' => 'mailparse/mailparse.stub', 'mailparse_msg_get_structure' => 'mailparse/mailparse.stub', 'mailparse_msg_parse' => 'mailparse/mailparse.stub', 'mailparse_msg_parse_file' => 'mailparse/mailparse.stub', 'mailparse_rfc822_parse_addresses' => 'mailparse/mailparse.stub', 'mailparse_stream_encode' => 'mailparse/mailparse.stub', 'mailparse_uudecode_all' => 'mailparse/mailparse.stub', 'max' => 'standard/standard_8.stub', 'mb_check_encoding' => 'mbstring/mbstring.stub', 'mb_chr' => 'mbstring/mbstring.stub', 'mb_convert_case' => 'mbstring/mbstring.stub', 'mb_convert_encoding' => 'mbstring/mbstring.stub', 'mb_convert_kana' => 'mbstring/mbstring.stub', 'mb_convert_variables' => 'mbstring/mbstring.stub', 'mb_decode_mimeheader' => 'mbstring/mbstring.stub', 'mb_decode_numericentity' => 'mbstring/mbstring.stub', 'mb_detect_encoding' => 'mbstring/mbstring.stub', 'mb_detect_order' => 'mbstring/mbstring.stub', 'mb_encode_mimeheader' => 'mbstring/mbstring.stub', 'mb_encode_numericentity' => 'mbstring/mbstring.stub', 'mb_encoding_aliases' => 'mbstring/mbstring.stub', 'mb_ereg' => 'mbstring/mbstring.stub', 'mb_ereg_match' => 'mbstring/mbstring.stub', 'mb_ereg_replace' => 'mbstring/mbstring.stub', 'mb_ereg_replace_callback' => 'mbstring/mbstring.stub', 'mb_ereg_search' => 'mbstring/mbstring.stub', 'mb_ereg_search_getpos' => 'mbstring/mbstring.stub', 'mb_ereg_search_getregs' => 'mbstring/mbstring.stub', 'mb_ereg_search_init' => 'mbstring/mbstring.stub', 'mb_ereg_search_pos' => 'mbstring/mbstring.stub', 'mb_ereg_search_regs' => 'mbstring/mbstring.stub', 'mb_ereg_search_setpos' => 'mbstring/mbstring.stub', 'mb_eregi' => 'mbstring/mbstring.stub', 'mb_eregi_replace' => 'mbstring/mbstring.stub', 'mb_get_info' => 'mbstring/mbstring.stub', 'mb_http_input' => 'mbstring/mbstring.stub', 'mb_http_output' => 'mbstring/mbstring.stub', 'mb_internal_encoding' => 'mbstring/mbstring.stub', 'mb_language' => 'mbstring/mbstring.stub', 'mb_lcfirst' => 'mbstring/mbstring.stub', 'mb_list_encodings' => 'mbstring/mbstring.stub', 'mb_ltrim' => 'mbstring/mbstring.stub', 'mb_ord' => 'mbstring/mbstring.stub', 'mb_output_handler' => 'mbstring/mbstring.stub', 'mb_parse_str' => 'mbstring/mbstring.stub', 'mb_preferred_mime_name' => 'mbstring/mbstring.stub', 'mb_regex_encoding' => 'mbstring/mbstring.stub', 'mb_regex_set_options' => 'mbstring/mbstring.stub', 'mb_rtrim' => 'mbstring/mbstring.stub', 'mb_scrub' => 'mbstring/mbstring.stub', 'mb_send_mail' => 'mbstring/mbstring.stub', 'mb_split' => 'mbstring/mbstring.stub', 'mb_str_pad' => 'mbstring/mbstring.stub', 'mb_str_split' => 'mbstring/mbstring.stub', 'mb_strcut' => 'mbstring/mbstring.stub', 'mb_strimwidth' => 'mbstring/mbstring.stub', 'mb_stripos' => 'mbstring/mbstring.stub', 'mb_stristr' => 'mbstring/mbstring.stub', 'mb_strlen' => 'mbstring/mbstring.stub', 'mb_strpos' => 'mbstring/mbstring.stub', 'mb_strrchr' => 'mbstring/mbstring.stub', 'mb_strrichr' => 'mbstring/mbstring.stub', 'mb_strripos' => 'mbstring/mbstring.stub', 'mb_strrpos' => 'mbstring/mbstring.stub', 'mb_strstr' => 'mbstring/mbstring.stub', 'mb_strtolower' => 'mbstring/mbstring.stub', 'mb_strtoupper' => 'mbstring/mbstring.stub', 'mb_strwidth' => 'mbstring/mbstring.stub', 'mb_substitute_character' => 'mbstring/mbstring.stub', 'mb_substr' => 'mbstring/mbstring.stub', 'mb_substr_count' => 'mbstring/mbstring.stub', 'mb_trim' => 'mbstring/mbstring.stub', 'mb_ucfirst' => 'mbstring/mbstring.stub', 'mbereg' => 'mbstring/mbstring.stub', 'mbereg_match' => 'mbstring/mbstring.stub', 'mbereg_replace' => 'mbstring/mbstring.stub', 'mbereg_search' => 'mbstring/mbstring.stub', 'mbereg_search_getpos' => 'mbstring/mbstring.stub', 'mbereg_search_getregs' => 'mbstring/mbstring.stub', 'mbereg_search_init' => 'mbstring/mbstring.stub', 'mbereg_search_pos' => 'mbstring/mbstring.stub', 'mbereg_search_regs' => 'mbstring/mbstring.stub', 'mbereg_search_setpos' => 'mbstring/mbstring.stub', 'mberegi' => 'mbstring/mbstring.stub', 'mberegi_replace' => 'mbstring/mbstring.stub', 'mbregex_encoding' => 'mbstring/mbstring.stub', 'mbsplit' => 'mbstring/mbstring.stub', 'mcrypt_cbc' => 'mcrypt/mcrypt.stub', 'mcrypt_cfb' => 'mcrypt/mcrypt.stub', 'mcrypt_create_iv' => 'mcrypt/mcrypt.stub', 'mcrypt_decrypt' => 'mcrypt/mcrypt.stub', 'mcrypt_ecb' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_get_algorithms_name' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_get_block_size' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_get_iv_size' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_get_key_size' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_get_modes_name' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_get_supported_key_sizes' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_is_block_algorithm' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_is_block_algorithm_mode' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_is_block_mode' => 'mcrypt/mcrypt.stub', 'mcrypt_enc_self_test' => 'mcrypt/mcrypt.stub', 'mcrypt_encrypt' => 'mcrypt/mcrypt.stub', 'mcrypt_generic' => 'mcrypt/mcrypt.stub', 'mcrypt_generic_deinit' => 'mcrypt/mcrypt.stub', 'mcrypt_generic_end' => 'mcrypt/mcrypt.stub', 'mcrypt_generic_init' => 'mcrypt/mcrypt.stub', 'mcrypt_get_block_size' => 'mcrypt/mcrypt.stub', 'mcrypt_get_cipher_name' => 'mcrypt/mcrypt.stub', 'mcrypt_get_iv_size' => 'mcrypt/mcrypt.stub', 'mcrypt_get_key_size' => 'mcrypt/mcrypt.stub', 'mcrypt_list_algorithms' => 'mcrypt/mcrypt.stub', 'mcrypt_list_modes' => 'mcrypt/mcrypt.stub', 'mcrypt_module_close' => 'mcrypt/mcrypt.stub', 'mcrypt_module_get_algo_block_size' => 'mcrypt/mcrypt.stub', 'mcrypt_module_get_algo_key_size' => 'mcrypt/mcrypt.stub', 'mcrypt_module_get_supported_key_sizes' => 'mcrypt/mcrypt.stub', 'mcrypt_module_is_block_algorithm' => 'mcrypt/mcrypt.stub', 'mcrypt_module_is_block_algorithm_mode' => 'mcrypt/mcrypt.stub', 'mcrypt_module_is_block_mode' => 'mcrypt/mcrypt.stub', 'mcrypt_module_open' => 'mcrypt/mcrypt.stub', 'mcrypt_module_self_test' => 'mcrypt/mcrypt.stub', 'mcrypt_ofb' => 'mcrypt/mcrypt.stub', 'md5' => 'standard/standard_0.stub', 'md5_file' => 'standard/standard_0.stub', 'mdecrypt_generic' => 'mcrypt/mcrypt.stub', 'memcache_add' => 'memcache/memcache.stub', 'memcache_add_server' => 'memcache/memcache.stub', 'memcache_append' => 'memcache/memcache.stub', 'memcache_cas' => 'memcache/memcache.stub', 'memcache_close' => 'memcache/memcache.stub', 'memcache_connect' => 'memcache/memcache.stub', 'memcache_debug' => 'memcache/memcache.stub', 'memcache_decrement' => 'memcache/memcache.stub', 'memcache_delete' => 'memcache/memcache.stub', 'memcache_flush' => 'memcache/memcache.stub', 'memcache_get' => 'memcache/memcache.stub', 'memcache_get_extended_stats' => 'memcache/memcache.stub', 'memcache_get_server_status' => 'memcache/memcache.stub', 'memcache_get_stats' => 'memcache/memcache.stub', 'memcache_get_version' => 'memcache/memcache.stub', 'memcache_increment' => 'memcache/memcache.stub', 'memcache_pconnect' => 'memcache/memcache.stub', 'memcache_prepend' => 'memcache/memcache.stub', 'memcache_replace' => 'memcache/memcache.stub', 'memcache_set' => 'memcache/memcache.stub', 'memcache_set_compress_threshold' => 'memcache/memcache.stub', 'memcache_set_failure_callback' => 'memcache/memcache.stub', 'memcache_set_server_params' => 'memcache/memcache.stub', 'meminfo_dump' => 'meminfo/meminfo.stub', 'memory_get_peak_usage' => 'standard/standard_4.stub', 'memory_get_usage' => 'standard/standard_4.stub', 'memory_reset_peak_usage' => 'standard/standard_4.stub', 'metaphone' => 'standard/standard_8.stub', 'method_exists' => 'Core/Core.stub', 'mhash' => 'hash/hash.stub', 'mhash_count' => 'hash/hash.stub', 'mhash_get_block_size' => 'hash/hash.stub', 'mhash_get_hash_name' => 'hash/hash.stub', 'mhash_keygen_s2k' => 'hash/hash.stub', 'microtime' => 'standard/standard_3.stub', 'mime_content_type' => 'fileinfo/fileinfo.stub', 'min' => 'standard/standard_8.stub', 'ming_keypress' => 'ming/ming.stub', 'ming_setcubicthreshold' => 'ming/ming.stub', 'ming_setscale' => 'ming/ming.stub', 'ming_setswfcompression' => 'ming/ming.stub', 'ming_useconstants' => 'ming/ming.stub', 'ming_useswfversion' => 'ming/ming.stub', 'mkdir' => 'standard/standard_5.stub', 'mktime' => 'date/date.stub', 'money_format' => 'standard/standard_1.stub', 'monitor_custom_event' => 'zend/zend.stub', 'monitor_httperror_event' => 'zend/zend.stub', 'monitor_license_info' => 'zend/zend.stub', 'monitor_pass_error' => 'zend/zend.stub', 'monitor_set_aggregation_hint' => 'zend/zend.stub', 'move_uploaded_file' => 'standard/standard_4.stub', 'mqseries_back' => 'mqseries/mqseries.stub', 'mqseries_begin' => 'mqseries/mqseries.stub', 'mqseries_close' => 'mqseries/mqseries.stub', 'mqseries_cmit' => 'mqseries/mqseries.stub', 'mqseries_conn' => 'mqseries/mqseries.stub', 'mqseries_connx' => 'mqseries/mqseries.stub', 'mqseries_disc' => 'mqseries/mqseries.stub', 'mqseries_get' => 'mqseries/mqseries.stub', 'mqseries_inq' => 'mqseries/mqseries.stub', 'mqseries_open' => 'mqseries/mqseries.stub', 'mqseries_put' => 'mqseries/mqseries.stub', 'mqseries_put1' => 'mqseries/mqseries.stub', 'mqseries_set' => 'mqseries/mqseries.stub', 'mqseries_strerror' => 'mqseries/mqseries.stub', 'ms_GetErrorObj' => 'mapscript/mapscript.stub', 'ms_GetVersion' => 'mapscript/mapscript.stub', 'ms_GetVersionInt' => 'mapscript/mapscript.stub', 'ms_ResetErrorList' => 'mapscript/mapscript.stub', 'ms_TokenizeMap' => 'mapscript/mapscript.stub', 'ms_iogetStdoutBufferBytes' => 'mapscript/mapscript.stub', 'ms_iogetstdoutbufferstring' => 'mapscript/mapscript.stub', 'ms_ioinstallstdinfrombuffer' => 'mapscript/mapscript.stub', 'ms_ioinstallstdouttobuffer' => 'mapscript/mapscript.stub', 'ms_ioresethandlers' => 'mapscript/mapscript.stub', 'ms_iostripstdoutbuffercontentheaders' => 'mapscript/mapscript.stub', 'ms_iostripstdoutbuffercontenttype' => 'mapscript/mapscript.stub', 'msg_get_queue' => 'sysvmsg/sysvmsg.stub', 'msg_queue_exists' => 'sysvmsg/sysvmsg.stub', 'msg_receive' => 'sysvmsg/sysvmsg.stub', 'msg_remove_queue' => 'sysvmsg/sysvmsg.stub', 'msg_send' => 'sysvmsg/sysvmsg.stub', 'msg_set_queue' => 'sysvmsg/sysvmsg.stub', 'msg_stat_queue' => 'sysvmsg/sysvmsg.stub', 'msgfmt_create' => 'intl/intl.stub', 'msgfmt_format' => 'intl/intl.stub', 'msgfmt_format_message' => 'intl/intl.stub', 'msgfmt_get_error_code' => 'intl/intl.stub', 'msgfmt_get_error_message' => 'intl/intl.stub', 'msgfmt_get_locale' => 'intl/intl.stub', 'msgfmt_get_pattern' => 'intl/intl.stub', 'msgfmt_parse' => 'intl/intl.stub', 'msgfmt_parse_message' => 'intl/intl.stub', 'msgfmt_set_pattern' => 'intl/intl.stub', 'msgpack_pack' => 'msgpack/msgpack.stub', 'msgpack_serialize' => 'msgpack/msgpack.stub', 'msgpack_unpack' => 'msgpack/msgpack.stub', 'msgpack_unserialize' => 'msgpack/msgpack.stub', 'mssql_bind' => 'mssql/mssql.stub', 'mssql_close' => 'mssql/mssql.stub', 'mssql_connect' => 'mssql/mssql.stub', 'mssql_data_seek' => 'mssql/mssql.stub', 'mssql_execute' => 'mssql/mssql.stub', 'mssql_fetch_array' => 'mssql/mssql.stub', 'mssql_fetch_assoc' => 'mssql/mssql.stub', 'mssql_fetch_batch' => 'mssql/mssql.stub', 'mssql_fetch_field' => 'mssql/mssql.stub', 'mssql_fetch_object' => 'mssql/mssql.stub', 'mssql_fetch_row' => 'mssql/mssql.stub', 'mssql_field_length' => 'mssql/mssql.stub', 'mssql_field_name' => 'mssql/mssql.stub', 'mssql_field_seek' => 'mssql/mssql.stub', 'mssql_field_type' => 'mssql/mssql.stub', 'mssql_free_result' => 'mssql/mssql.stub', 'mssql_free_statement' => 'mssql/mssql.stub', 'mssql_get_last_message' => 'mssql/mssql.stub', 'mssql_guid_string' => 'mssql/mssql.stub', 'mssql_init' => 'mssql/mssql.stub', 'mssql_min_error_severity' => 'mssql/mssql.stub', 'mssql_min_message_severity' => 'mssql/mssql.stub', 'mssql_next_result' => 'mssql/mssql.stub', 'mssql_num_fields' => 'mssql/mssql.stub', 'mssql_num_rows' => 'mssql/mssql.stub', 'mssql_pconnect' => 'mssql/mssql.stub', 'mssql_query' => 'mssql/mssql.stub', 'mssql_result' => 'mssql/mssql.stub', 'mssql_rows_affected' => 'mssql/mssql.stub', 'mssql_select_db' => 'mssql/mssql.stub', 'mt_getrandmax' => 'random/random.stub', 'mt_rand' => 'random/random.stub', 'mt_srand' => 'random/random.stub', 'mysql' => 'mysql/mysql.stub', 'mysql_affected_rows' => 'mysql/mysql.stub', 'mysql_client_encoding' => 'mysql/mysql.stub', 'mysql_close' => 'mysql/mysql.stub', 'mysql_connect' => 'mysql/mysql.stub', 'mysql_data_seek' => 'mysql/mysql.stub', 'mysql_db_name' => 'mysql/mysql.stub', 'mysql_db_query' => 'mysql/mysql.stub', 'mysql_dbname' => 'mysql/mysql.stub', 'mysql_errno' => 'mysql/mysql.stub', 'mysql_error' => 'mysql/mysql.stub', 'mysql_escape_string' => 'mysql/mysql.stub', 'mysql_fetch_array' => 'mysql/mysql.stub', 'mysql_fetch_assoc' => 'mysql/mysql.stub', 'mysql_fetch_field' => 'mysql/mysql.stub', 'mysql_fetch_lengths' => 'mysql/mysql.stub', 'mysql_fetch_object' => 'mysql/mysql.stub', 'mysql_fetch_row' => 'mysql/mysql.stub', 'mysql_field_flags' => 'mysql/mysql.stub', 'mysql_field_len' => 'mysql/mysql.stub', 'mysql_field_name' => 'mysql/mysql.stub', 'mysql_field_seek' => 'mysql/mysql.stub', 'mysql_field_table' => 'mysql/mysql.stub', 'mysql_field_type' => 'mysql/mysql.stub', 'mysql_fieldflags' => 'mysql/mysql.stub', 'mysql_fieldlen' => 'mysql/mysql.stub', 'mysql_fieldname' => 'mysql/mysql.stub', 'mysql_fieldtable' => 'mysql/mysql.stub', 'mysql_fieldtype' => 'mysql/mysql.stub', 'mysql_free_result' => 'mysql/mysql.stub', 'mysql_freeresult' => 'mysql/mysql.stub', 'mysql_get_client_info' => 'mysql/mysql.stub', 'mysql_get_host_info' => 'mysql/mysql.stub', 'mysql_get_proto_info' => 'mysql/mysql.stub', 'mysql_get_server_info' => 'mysql/mysql.stub', 'mysql_info' => 'mysql/mysql.stub', 'mysql_insert_id' => 'mysql/mysql.stub', 'mysql_list_dbs' => 'mysql/mysql.stub', 'mysql_list_fields' => 'mysql/mysql.stub', 'mysql_list_processes' => 'mysql/mysql.stub', 'mysql_list_tables' => 'mysql/mysql.stub', 'mysql_listdbs' => 'mysql/mysql.stub', 'mysql_listfields' => 'mysql/mysql.stub', 'mysql_listtables' => 'mysql/mysql.stub', 'mysql_num_fields' => 'mysql/mysql.stub', 'mysql_num_rows' => 'mysql/mysql.stub', 'mysql_numfields' => 'mysql/mysql.stub', 'mysql_numrows' => 'mysql/mysql.stub', 'mysql_pconnect' => 'mysql/mysql.stub', 'mysql_ping' => 'mysql/mysql.stub', 'mysql_query' => 'mysql/mysql.stub', 'mysql_real_escape_string' => 'mysql/mysql.stub', 'mysql_result' => 'mysql/mysql.stub', 'mysql_select_db' => 'mysql/mysql.stub', 'mysql_selectdb' => 'mysql/mysql.stub', 'mysql_set_charset' => 'mysql/mysql.stub', 'mysql_stat' => 'mysql/mysql.stub', 'mysql_table_name' => 'mysql/mysql.stub', 'mysql_tablename' => 'mysql/mysql.stub', 'mysql_thread_id' => 'mysql/mysql.stub', 'mysql_unbuffered_query' => 'mysql/mysql.stub', 'mysql_xdevapi\\expression' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysql_xdevapi\\getSession' => 'mysql_xdevapi/mysql_xdevapi.stub', 'mysqli_affected_rows' => 'mysqli/mysqli.stub', 'mysqli_autocommit' => 'mysqli/mysqli.stub', 'mysqli_begin_transaction' => 'mysqli/mysqli.stub', 'mysqli_bind_param' => 'mysqli/mysqli.stub', 'mysqli_bind_result' => 'mysqli/mysqli.stub', 'mysqli_change_user' => 'mysqli/mysqli.stub', 'mysqli_character_set_name' => 'mysqli/mysqli.stub', 'mysqli_client_encoding' => 'mysqli/mysqli.stub', 'mysqli_close' => 'mysqli/mysqli.stub', 'mysqli_commit' => 'mysqli/mysqli.stub', 'mysqli_connect' => 'mysqli/mysqli.stub', 'mysqli_connect_errno' => 'mysqli/mysqli.stub', 'mysqli_connect_error' => 'mysqli/mysqli.stub', 'mysqli_data_seek' => 'mysqli/mysqli.stub', 'mysqli_debug' => 'mysqli/mysqli.stub', 'mysqli_dump_debug_info' => 'mysqli/mysqli.stub', 'mysqli_errno' => 'mysqli/mysqli.stub', 'mysqli_error' => 'mysqli/mysqli.stub', 'mysqli_error_list' => 'mysqli/mysqli.stub', 'mysqli_escape_string' => 'mysqli/mysqli.stub', 'mysqli_execute' => 'mysqli/mysqli.stub', 'mysqli_execute_query' => 'mysqli/mysqli.stub', 'mysqli_fetch' => 'mysqli/mysqli.stub', 'mysqli_fetch_all' => 'mysqli/mysqli.stub', 'mysqli_fetch_array' => 'mysqli/mysqli.stub', 'mysqli_fetch_assoc' => 'mysqli/mysqli.stub', 'mysqli_fetch_column' => 'mysqli/mysqli.stub', 'mysqli_fetch_field' => 'mysqli/mysqli.stub', 'mysqli_fetch_field_direct' => 'mysqli/mysqli.stub', 'mysqli_fetch_fields' => 'mysqli/mysqli.stub', 'mysqli_fetch_lengths' => 'mysqli/mysqli.stub', 'mysqli_fetch_object' => 'mysqli/mysqli.stub', 'mysqli_fetch_row' => 'mysqli/mysqli.stub', 'mysqli_field_count' => 'mysqli/mysqli.stub', 'mysqli_field_seek' => 'mysqli/mysqli.stub', 'mysqli_field_tell' => 'mysqli/mysqli.stub', 'mysqli_free_result' => 'mysqli/mysqli.stub', 'mysqli_get_cache_stats' => 'mysqli/mysqli.stub', 'mysqli_get_charset' => 'mysqli/mysqli.stub', 'mysqli_get_client_info' => 'mysqli/mysqli.stub', 'mysqli_get_client_stats' => 'mysqli/mysqli.stub', 'mysqli_get_client_version' => 'mysqli/mysqli.stub', 'mysqli_get_connection_stats' => 'mysqli/mysqli.stub', 'mysqli_get_host_info' => 'mysqli/mysqli.stub', 'mysqli_get_links_stats' => 'mysqli/mysqli.stub', 'mysqli_get_metadata' => 'mysqli/mysqli.stub', 'mysqli_get_proto_info' => 'mysqli/mysqli.stub', 'mysqli_get_server_info' => 'mysqli/mysqli.stub', 'mysqli_get_server_version' => 'mysqli/mysqli.stub', 'mysqli_get_warnings' => 'mysqli/mysqli.stub', 'mysqli_info' => 'mysqli/mysqli.stub', 'mysqli_init' => 'mysqli/mysqli.stub', 'mysqli_insert_id' => 'mysqli/mysqli.stub', 'mysqli_kill' => 'mysqli/mysqli.stub', 'mysqli_more_results' => 'mysqli/mysqli.stub', 'mysqli_multi_query' => 'mysqli/mysqli.stub', 'mysqli_next_result' => 'mysqli/mysqli.stub', 'mysqli_num_fields' => 'mysqli/mysqli.stub', 'mysqli_num_rows' => 'mysqli/mysqli.stub', 'mysqli_options' => 'mysqli/mysqli.stub', 'mysqli_param_count' => 'mysqli/mysqli.stub', 'mysqli_ping' => 'mysqli/mysqli.stub', 'mysqli_poll' => 'mysqli/mysqli.stub', 'mysqli_prepare' => 'mysqli/mysqli.stub', 'mysqli_query' => 'mysqli/mysqli.stub', 'mysqli_real_connect' => 'mysqli/mysqli.stub', 'mysqli_real_escape_string' => 'mysqli/mysqli.stub', 'mysqli_real_query' => 'mysqli/mysqli.stub', 'mysqli_reap_async_query' => 'mysqli/mysqli.stub', 'mysqli_refresh' => 'mysqli/mysqli.stub', 'mysqli_release_savepoint' => 'mysqli/mysqli.stub', 'mysqli_report' => 'mysqli/mysqli.stub', 'mysqli_rollback' => 'mysqli/mysqli.stub', 'mysqli_savepoint' => 'mysqli/mysqli.stub', 'mysqli_select_db' => 'mysqli/mysqli.stub', 'mysqli_send_long_data' => 'mysqli/mysqli.stub', 'mysqli_set_charset' => 'mysqli/mysqli.stub', 'mysqli_set_local_infile_default' => 'mysqli/mysqli.stub', 'mysqli_set_local_infile_handler' => 'mysqli/mysqli.stub', 'mysqli_set_opt' => 'mysqli/mysqli.stub', 'mysqli_sqlstate' => 'mysqli/mysqli.stub', 'mysqli_ssl_set' => 'mysqli/mysqli.stub', 'mysqli_stat' => 'mysqli/mysqli.stub', 'mysqli_stmt_affected_rows' => 'mysqli/mysqli.stub', 'mysqli_stmt_attr_get' => 'mysqli/mysqli.stub', 'mysqli_stmt_attr_set' => 'mysqli/mysqli.stub', 'mysqli_stmt_bind_param' => 'mysqli/mysqli.stub', 'mysqli_stmt_bind_result' => 'mysqli/mysqli.stub', 'mysqli_stmt_close' => 'mysqli/mysqli.stub', 'mysqli_stmt_data_seek' => 'mysqli/mysqli.stub', 'mysqli_stmt_errno' => 'mysqli/mysqli.stub', 'mysqli_stmt_error' => 'mysqli/mysqli.stub', 'mysqli_stmt_error_list' => 'mysqli/mysqli.stub', 'mysqli_stmt_execute' => 'mysqli/mysqli.stub', 'mysqli_stmt_fetch' => 'mysqli/mysqli.stub', 'mysqli_stmt_field_count' => 'mysqli/mysqli.stub', 'mysqli_stmt_free_result' => 'mysqli/mysqli.stub', 'mysqli_stmt_get_result' => 'mysqli/mysqli.stub', 'mysqli_stmt_get_warnings' => 'mysqli/mysqli.stub', 'mysqli_stmt_init' => 'mysqli/mysqli.stub', 'mysqli_stmt_insert_id' => 'mysqli/mysqli.stub', 'mysqli_stmt_more_results' => 'mysqli/mysqli.stub', 'mysqli_stmt_next_result' => 'mysqli/mysqli.stub', 'mysqli_stmt_num_rows' => 'mysqli/mysqli.stub', 'mysqli_stmt_param_count' => 'mysqli/mysqli.stub', 'mysqli_stmt_prepare' => 'mysqli/mysqli.stub', 'mysqli_stmt_reset' => 'mysqli/mysqli.stub', 'mysqli_stmt_result_metadata' => 'mysqli/mysqli.stub', 'mysqli_stmt_send_long_data' => 'mysqli/mysqli.stub', 'mysqli_stmt_sqlstate' => 'mysqli/mysqli.stub', 'mysqli_stmt_store_result' => 'mysqli/mysqli.stub', 'mysqli_store_result' => 'mysqli/mysqli.stub', 'mysqli_thread_id' => 'mysqli/mysqli.stub', 'mysqli_thread_safe' => 'mysqli/mysqli.stub', 'mysqli_use_result' => 'mysqli/mysqli.stub', 'mysqli_warning_count' => 'mysqli/mysqli.stub', 'natcasesort' => 'standard/standard_8.stub', 'natsort' => 'standard/standard_8.stub', 'ncurses_addch' => 'ncurses/ncurses.stub', 'ncurses_addchnstr' => 'ncurses/ncurses.stub', 'ncurses_addchstr' => 'ncurses/ncurses.stub', 'ncurses_addnstr' => 'ncurses/ncurses.stub', 'ncurses_addstr' => 'ncurses/ncurses.stub', 'ncurses_assume_default_colors' => 'ncurses/ncurses.stub', 'ncurses_attroff' => 'ncurses/ncurses.stub', 'ncurses_attron' => 'ncurses/ncurses.stub', 'ncurses_attrset' => 'ncurses/ncurses.stub', 'ncurses_baudrate' => 'ncurses/ncurses.stub', 'ncurses_beep' => 'ncurses/ncurses.stub', 'ncurses_bkgd' => 'ncurses/ncurses.stub', 'ncurses_bkgdset' => 'ncurses/ncurses.stub', 'ncurses_border' => 'ncurses/ncurses.stub', 'ncurses_bottom_panel' => 'ncurses/ncurses.stub', 'ncurses_can_change_color' => 'ncurses/ncurses.stub', 'ncurses_cbreak' => 'ncurses/ncurses.stub', 'ncurses_clear' => 'ncurses/ncurses.stub', 'ncurses_clrtobot' => 'ncurses/ncurses.stub', 'ncurses_clrtoeol' => 'ncurses/ncurses.stub', 'ncurses_color_content' => 'ncurses/ncurses.stub', 'ncurses_color_set' => 'ncurses/ncurses.stub', 'ncurses_curs_set' => 'ncurses/ncurses.stub', 'ncurses_def_prog_mode' => 'ncurses/ncurses.stub', 'ncurses_def_shell_mode' => 'ncurses/ncurses.stub', 'ncurses_define_key' => 'ncurses/ncurses.stub', 'ncurses_del_panel' => 'ncurses/ncurses.stub', 'ncurses_delay_output' => 'ncurses/ncurses.stub', 'ncurses_delch' => 'ncurses/ncurses.stub', 'ncurses_deleteln' => 'ncurses/ncurses.stub', 'ncurses_delwin' => 'ncurses/ncurses.stub', 'ncurses_doupdate' => 'ncurses/ncurses.stub', 'ncurses_echo' => 'ncurses/ncurses.stub', 'ncurses_echochar' => 'ncurses/ncurses.stub', 'ncurses_end' => 'ncurses/ncurses.stub', 'ncurses_erase' => 'ncurses/ncurses.stub', 'ncurses_erasechar' => 'ncurses/ncurses.stub', 'ncurses_filter' => 'ncurses/ncurses.stub', 'ncurses_flash' => 'ncurses/ncurses.stub', 'ncurses_flushinp' => 'ncurses/ncurses.stub', 'ncurses_getch' => 'ncurses/ncurses.stub', 'ncurses_getmaxyx' => 'ncurses/ncurses.stub', 'ncurses_getmouse' => 'ncurses/ncurses.stub', 'ncurses_getyx' => 'ncurses/ncurses.stub', 'ncurses_halfdelay' => 'ncurses/ncurses.stub', 'ncurses_has_colors' => 'ncurses/ncurses.stub', 'ncurses_has_ic' => 'ncurses/ncurses.stub', 'ncurses_has_il' => 'ncurses/ncurses.stub', 'ncurses_has_key' => 'ncurses/ncurses.stub', 'ncurses_hide_panel' => 'ncurses/ncurses.stub', 'ncurses_hline' => 'ncurses/ncurses.stub', 'ncurses_inch' => 'ncurses/ncurses.stub', 'ncurses_init' => 'ncurses/ncurses.stub', 'ncurses_init_color' => 'ncurses/ncurses.stub', 'ncurses_init_pair' => 'ncurses/ncurses.stub', 'ncurses_insch' => 'ncurses/ncurses.stub', 'ncurses_insdelln' => 'ncurses/ncurses.stub', 'ncurses_insertln' => 'ncurses/ncurses.stub', 'ncurses_insstr' => 'ncurses/ncurses.stub', 'ncurses_instr' => 'ncurses/ncurses.stub', 'ncurses_isendwin' => 'ncurses/ncurses.stub', 'ncurses_keyok' => 'ncurses/ncurses.stub', 'ncurses_keypad' => 'ncurses/ncurses.stub', 'ncurses_killchar' => 'ncurses/ncurses.stub', 'ncurses_longname' => 'ncurses/ncurses.stub', 'ncurses_meta' => 'ncurses/ncurses.stub', 'ncurses_mouse_trafo' => 'ncurses/ncurses.stub', 'ncurses_mouseinterval' => 'ncurses/ncurses.stub', 'ncurses_mousemask' => 'ncurses/ncurses.stub', 'ncurses_move' => 'ncurses/ncurses.stub', 'ncurses_move_panel' => 'ncurses/ncurses.stub', 'ncurses_mvaddch' => 'ncurses/ncurses.stub', 'ncurses_mvaddchnstr' => 'ncurses/ncurses.stub', 'ncurses_mvaddchstr' => 'ncurses/ncurses.stub', 'ncurses_mvaddnstr' => 'ncurses/ncurses.stub', 'ncurses_mvaddstr' => 'ncurses/ncurses.stub', 'ncurses_mvcur' => 'ncurses/ncurses.stub', 'ncurses_mvdelch' => 'ncurses/ncurses.stub', 'ncurses_mvgetch' => 'ncurses/ncurses.stub', 'ncurses_mvhline' => 'ncurses/ncurses.stub', 'ncurses_mvinch' => 'ncurses/ncurses.stub', 'ncurses_mvwaddstr' => 'ncurses/ncurses.stub', 'ncurses_napms' => 'ncurses/ncurses.stub', 'ncurses_new_panel' => 'ncurses/ncurses.stub', 'ncurses_newpad' => 'ncurses/ncurses.stub', 'ncurses_newwin' => 'ncurses/ncurses.stub', 'ncurses_nl' => 'ncurses/ncurses.stub', 'ncurses_nocbreak' => 'ncurses/ncurses.stub', 'ncurses_noecho' => 'ncurses/ncurses.stub', 'ncurses_nonl' => 'ncurses/ncurses.stub', 'ncurses_noqiflush' => 'ncurses/ncurses.stub', 'ncurses_noraw' => 'ncurses/ncurses.stub', 'ncurses_pair_content' => 'ncurses/ncurses.stub', 'ncurses_panel_above' => 'ncurses/ncurses.stub', 'ncurses_panel_below' => 'ncurses/ncurses.stub', 'ncurses_panel_window' => 'ncurses/ncurses.stub', 'ncurses_pnoutrefresh' => 'ncurses/ncurses.stub', 'ncurses_prefresh' => 'ncurses/ncurses.stub', 'ncurses_putp' => 'ncurses/ncurses.stub', 'ncurses_qiflush' => 'ncurses/ncurses.stub', 'ncurses_raw' => 'ncurses/ncurses.stub', 'ncurses_refresh' => 'ncurses/ncurses.stub', 'ncurses_replace_panel' => 'ncurses/ncurses.stub', 'ncurses_reset_prog_mode' => 'ncurses/ncurses.stub', 'ncurses_reset_shell_mode' => 'ncurses/ncurses.stub', 'ncurses_resetty' => 'ncurses/ncurses.stub', 'ncurses_savetty' => 'ncurses/ncurses.stub', 'ncurses_scr_dump' => 'ncurses/ncurses.stub', 'ncurses_scr_init' => 'ncurses/ncurses.stub', 'ncurses_scr_restore' => 'ncurses/ncurses.stub', 'ncurses_scr_set' => 'ncurses/ncurses.stub', 'ncurses_scrl' => 'ncurses/ncurses.stub', 'ncurses_show_panel' => 'ncurses/ncurses.stub', 'ncurses_slk_attr' => 'ncurses/ncurses.stub', 'ncurses_slk_attroff' => 'ncurses/ncurses.stub', 'ncurses_slk_attron' => 'ncurses/ncurses.stub', 'ncurses_slk_attrset' => 'ncurses/ncurses.stub', 'ncurses_slk_clear' => 'ncurses/ncurses.stub', 'ncurses_slk_color' => 'ncurses/ncurses.stub', 'ncurses_slk_init' => 'ncurses/ncurses.stub', 'ncurses_slk_noutrefresh' => 'ncurses/ncurses.stub', 'ncurses_slk_refresh' => 'ncurses/ncurses.stub', 'ncurses_slk_restore' => 'ncurses/ncurses.stub', 'ncurses_slk_set' => 'ncurses/ncurses.stub', 'ncurses_slk_touch' => 'ncurses/ncurses.stub', 'ncurses_standend' => 'ncurses/ncurses.stub', 'ncurses_standout' => 'ncurses/ncurses.stub', 'ncurses_start_color' => 'ncurses/ncurses.stub', 'ncurses_termattrs' => 'ncurses/ncurses.stub', 'ncurses_termname' => 'ncurses/ncurses.stub', 'ncurses_timeout' => 'ncurses/ncurses.stub', 'ncurses_top_panel' => 'ncurses/ncurses.stub', 'ncurses_typeahead' => 'ncurses/ncurses.stub', 'ncurses_ungetch' => 'ncurses/ncurses.stub', 'ncurses_ungetmouse' => 'ncurses/ncurses.stub', 'ncurses_update_panels' => 'ncurses/ncurses.stub', 'ncurses_use_default_colors' => 'ncurses/ncurses.stub', 'ncurses_use_env' => 'ncurses/ncurses.stub', 'ncurses_use_extended_names' => 'ncurses/ncurses.stub', 'ncurses_vidattr' => 'ncurses/ncurses.stub', 'ncurses_vline' => 'ncurses/ncurses.stub', 'ncurses_waddch' => 'ncurses/ncurses.stub', 'ncurses_waddstr' => 'ncurses/ncurses.stub', 'ncurses_wattroff' => 'ncurses/ncurses.stub', 'ncurses_wattron' => 'ncurses/ncurses.stub', 'ncurses_wattrset' => 'ncurses/ncurses.stub', 'ncurses_wborder' => 'ncurses/ncurses.stub', 'ncurses_wclear' => 'ncurses/ncurses.stub', 'ncurses_wcolor_set' => 'ncurses/ncurses.stub', 'ncurses_werase' => 'ncurses/ncurses.stub', 'ncurses_wgetch' => 'ncurses/ncurses.stub', 'ncurses_whline' => 'ncurses/ncurses.stub', 'ncurses_wmouse_trafo' => 'ncurses/ncurses.stub', 'ncurses_wmove' => 'ncurses/ncurses.stub', 'ncurses_wnoutrefresh' => 'ncurses/ncurses.stub', 'ncurses_wrefresh' => 'ncurses/ncurses.stub', 'ncurses_wstandend' => 'ncurses/ncurses.stub', 'ncurses_wstandout' => 'ncurses/ncurses.stub', 'ncurses_wvline' => 'ncurses/ncurses.stub', 'net_get_interfaces' => 'standard/standard_4.stub', 'newrelic_accept_distributed_trace_headers' => 'newrelic/newrelic.stub', 'newrelic_accept_distributed_trace_payload' => 'newrelic/newrelic.stub', 'newrelic_accept_distributed_trace_payload_httpsafe' => 'newrelic/newrelic.stub', 'newrelic_add_custom_parameter' => 'newrelic/newrelic.stub', 'newrelic_add_custom_span_parameter' => 'newrelic/newrelic.stub', 'newrelic_add_custom_tracer' => 'newrelic/newrelic.stub', 'newrelic_background_job' => 'newrelic/newrelic.stub', 'newrelic_capture_params' => 'newrelic/newrelic.stub', 'newrelic_create_distributed_trace_payload' => 'newrelic/newrelic.stub', 'newrelic_custom_metric' => 'newrelic/newrelic.stub', 'newrelic_disable_autorum' => 'newrelic/newrelic.stub', 'newrelic_enable_params' => 'newrelic/newrelic.stub', 'newrelic_end_of_transaction' => 'newrelic/newrelic.stub', 'newrelic_end_transaction' => 'newrelic/newrelic.stub', 'newrelic_get_browser_timing_footer' => 'newrelic/newrelic.stub', 'newrelic_get_browser_timing_header' => 'newrelic/newrelic.stub', 'newrelic_get_linking_metadata' => 'newrelic/newrelic.stub', 'newrelic_get_trace_metadata' => 'newrelic/newrelic.stub', 'newrelic_ignore_apdex' => 'newrelic/newrelic.stub', 'newrelic_ignore_transaction' => 'newrelic/newrelic.stub', 'newrelic_insert_distributed_trace_headers' => 'newrelic/newrelic.stub', 'newrelic_is_sampled' => 'newrelic/newrelic.stub', 'newrelic_name_transaction' => 'newrelic/newrelic.stub', 'newrelic_notice_error' => 'newrelic/newrelic.stub', 'newrelic_record_custom_event' => 'newrelic/newrelic.stub', 'newrelic_record_datastore_segment' => 'newrelic/newrelic.stub', 'newrelic_set_appname' => 'newrelic/newrelic.stub', 'newrelic_set_user_attributes' => 'newrelic/newrelic.stub', 'newrelic_set_user_id' => 'newrelic/newrelic.stub', 'newrelic_start_transaction' => 'newrelic/newrelic.stub', 'next' => 'standard/standard_8.stub', 'ngettext' => 'gettext/gettext.stub', 'nl2br' => 'standard/standard_1.stub', 'nl_langinfo' => 'standard/standard_2.stub', 'normalizer_get_raw_decomposition' => 'intl/intl.stub', 'normalizer_is_normalized' => 'intl/intl.stub', 'normalizer_normalize' => 'intl/intl.stub', 'number_format' => 'standard/standard_3.stub', 'numfmt_create' => 'intl/intl.stub', 'numfmt_format' => 'intl/intl.stub', 'numfmt_format_currency' => 'intl/intl.stub', 'numfmt_get_attribute' => 'intl/intl.stub', 'numfmt_get_error_code' => 'intl/intl.stub', 'numfmt_get_error_message' => 'intl/intl.stub', 'numfmt_get_locale' => 'intl/intl.stub', 'numfmt_get_pattern' => 'intl/intl.stub', 'numfmt_get_symbol' => 'intl/intl.stub', 'numfmt_get_text_attribute' => 'intl/intl.stub', 'numfmt_parse' => 'intl/intl.stub', 'numfmt_parse_currency' => 'intl/intl.stub', 'numfmt_set_attribute' => 'intl/intl.stub', 'numfmt_set_pattern' => 'intl/intl.stub', 'numfmt_set_symbol' => 'intl/intl.stub', 'numfmt_set_text_attribute' => 'intl/intl.stub', 'oauth_get_sbs' => 'oauth/oauth.stub', 'oauth_urlencode' => 'oauth/oauth.stub', 'ob_clean' => 'standard/standard_8.stub', 'ob_deflatehandler' => 'http/http.stub', 'ob_end_clean' => 'standard/standard_8.stub', 'ob_end_flush' => 'standard/standard_8.stub', 'ob_etaghandler' => 'http/http.stub', 'ob_flush' => 'standard/standard_8.stub', 'ob_get_clean' => 'standard/standard_8.stub', 'ob_get_contents' => 'standard/standard_8.stub', 'ob_get_flush' => 'standard/standard_8.stub', 'ob_get_length' => 'standard/standard_8.stub', 'ob_get_level' => 'standard/standard_8.stub', 'ob_get_status' => 'standard/standard_8.stub', 'ob_gzhandler' => 'zlib/zlib.stub', 'ob_iconv_handler' => 'iconv/iconv.stub', 'ob_implicit_flush' => 'standard/standard_8.stub', 'ob_inflatehandler' => 'http/http.stub', 'ob_list_handlers' => 'standard/standard_8.stub', 'ob_start' => 'standard/standard_8.stub', 'ob_tidyhandler' => 'tidy/tidy.stub', 'oci_bind_array_by_name' => 'oci8/oci8.stub', 'oci_bind_by_name' => 'oci8/oci8.stub', 'oci_cancel' => 'oci8/oci8.stub', 'oci_client_version' => 'oci8/oci8.stub', 'oci_close' => 'oci8/oci8.stub', 'oci_commit' => 'oci8/oci8.stub', 'oci_connect' => 'oci8/oci8.stub', 'oci_define_by_name' => 'oci8/oci8.stub', 'oci_error' => 'oci8/oci8.stub', 'oci_execute' => 'oci8/oci8.stub', 'oci_fetch' => 'oci8/oci8.stub', 'oci_fetch_all' => 'oci8/oci8.stub', 'oci_fetch_array' => 'oci8/oci8.stub', 'oci_fetch_assoc' => 'oci8/oci8.stub', 'oci_fetch_object' => 'oci8/oci8.stub', 'oci_fetch_row' => 'oci8/oci8.stub', 'oci_field_is_null' => 'oci8/oci8.stub', 'oci_field_name' => 'oci8/oci8.stub', 'oci_field_precision' => 'oci8/oci8.stub', 'oci_field_scale' => 'oci8/oci8.stub', 'oci_field_size' => 'oci8/oci8.stub', 'oci_field_type' => 'oci8/oci8.stub', 'oci_field_type_raw' => 'oci8/oci8.stub', 'oci_free_cursor' => 'oci8/oci8.stub', 'oci_free_descriptor' => 'oci8/oci8.stub', 'oci_free_statement' => 'oci8/oci8.stub', 'oci_get_implicit_resultset' => 'oci8/oci8.stub', 'oci_internal_debug' => 'oci8/oci8.stub', 'oci_lob_copy' => 'oci8/oci8.stub', 'oci_lob_is_equal' => 'oci8/oci8.stub', 'oci_new_collection' => 'oci8/oci8.stub', 'oci_new_connect' => 'oci8/oci8.stub', 'oci_new_cursor' => 'oci8/oci8.stub', 'oci_new_descriptor' => 'oci8/oci8.stub', 'oci_num_fields' => 'oci8/oci8.stub', 'oci_num_rows' => 'oci8/oci8.stub', 'oci_parse' => 'oci8/oci8.stub', 'oci_password_change' => 'oci8/oci8.stub', 'oci_pconnect' => 'oci8/oci8.stub', 'oci_register_taf_callback' => 'oci8/oci8.stub', 'oci_result' => 'oci8/oci8.stub', 'oci_rollback' => 'oci8/oci8.stub', 'oci_server_version' => 'oci8/oci8.stub', 'oci_set_action' => 'oci8/oci8.stub', 'oci_set_call_timeout' => 'oci8/oci8v3.stub', 'oci_set_client_identifier' => 'oci8/oci8.stub', 'oci_set_client_info' => 'oci8/oci8.stub', 'oci_set_db_operation' => 'oci8/oci8v3.stub', 'oci_set_edition' => 'oci8/oci8.stub', 'oci_set_module_name' => 'oci8/oci8.stub', 'oci_set_prefetch' => 'oci8/oci8.stub', 'oci_set_prefetch_lob' => 'oci8/oci8v3.stub', 'oci_statement_type' => 'oci8/oci8.stub', 'oci_unregister_taf_callback' => 'oci8/oci8.stub', 'ocibindbyname' => 'oci8/oci8.stub', 'ocicancel' => 'oci8/oci8.stub', 'ocicloselob' => 'oci8/oci8.stub', 'ocicollappend' => 'oci8/oci8.stub', 'ocicollassign' => 'oci8/oci8.stub', 'ocicollassignelem' => 'oci8/oci8.stub', 'ocicollgetelem' => 'oci8/oci8.stub', 'ocicollmax' => 'oci8/oci8.stub', 'ocicollsize' => 'oci8/oci8.stub', 'ocicolltrim' => 'oci8/oci8.stub', 'ocicolumnisnull' => 'oci8/oci8.stub', 'ocicolumnname' => 'oci8/oci8.stub', 'ocicolumnprecision' => 'oci8/oci8.stub', 'ocicolumnscale' => 'oci8/oci8.stub', 'ocicolumnsize' => 'oci8/oci8.stub', 'ocicolumntype' => 'oci8/oci8.stub', 'ocicolumntyperaw' => 'oci8/oci8.stub', 'ocicommit' => 'oci8/oci8.stub', 'ocidefinebyname' => 'oci8/oci8.stub', 'ocierror' => 'oci8/oci8.stub', 'ociexecute' => 'oci8/oci8.stub', 'ocifetch' => 'oci8/oci8.stub', 'ocifetchinto' => 'oci8/oci8.stub', 'ocifetchstatement' => 'oci8/oci8.stub', 'ocifreecollection' => 'oci8/oci8.stub', 'ocifreecursor' => 'oci8/oci8.stub', 'ocifreedesc' => 'oci8/oci8.stub', 'ocifreestatement' => 'oci8/oci8.stub', 'ociinternaldebug' => 'oci8/oci8.stub', 'ociloadlob' => 'oci8/oci8.stub', 'ocilogoff' => 'oci8/oci8.stub', 'ocilogon' => 'oci8/oci8.stub', 'ocinewcollection' => 'oci8/oci8.stub', 'ocinewcursor' => 'oci8/oci8.stub', 'ocinewdescriptor' => 'oci8/oci8.stub', 'ocinlogon' => 'oci8/oci8.stub', 'ocinumcols' => 'oci8/oci8.stub', 'ociparse' => 'oci8/oci8.stub', 'ocipasswordchange' => 'oci8/oci8.stub', 'ociplogon' => 'oci8/oci8.stub', 'ociresult' => 'oci8/oci8.stub', 'ocirollback' => 'oci8/oci8.stub', 'ocirowcount' => 'oci8/oci8.stub', 'ocisavelob' => 'oci8/oci8.stub', 'ocisavelobfile' => 'oci8/oci8.stub', 'ociserverversion' => 'oci8/oci8.stub', 'ocisetprefetch' => 'oci8/oci8.stub', 'ocistatementtype' => 'oci8/oci8.stub', 'ociwritelobtofile' => 'oci8/oci8.stub', 'ociwritetemporarylob' => 'oci8/oci8.stub', 'octdec' => 'standard/standard_3.stub', 'odbc_autocommit' => 'odbc/odbc.stub', 'odbc_binmode' => 'odbc/odbc.stub', 'odbc_close' => 'odbc/odbc.stub', 'odbc_close_all' => 'odbc/odbc.stub', 'odbc_columnprivileges' => 'odbc/odbc.stub', 'odbc_columns' => 'odbc/odbc.stub', 'odbc_commit' => 'odbc/odbc.stub', 'odbc_connect' => 'odbc/odbc.stub', 'odbc_connection_string_is_quoted' => 'odbc/odbc.stub', 'odbc_connection_string_quote' => 'odbc/odbc.stub', 'odbc_connection_string_should_quote' => 'odbc/odbc.stub', 'odbc_cursor' => 'odbc/odbc.stub', 'odbc_data_source' => 'odbc/odbc.stub', 'odbc_do' => 'odbc/odbc.stub', 'odbc_error' => 'odbc/odbc.stub', 'odbc_errormsg' => 'odbc/odbc.stub', 'odbc_exec' => 'odbc/odbc.stub', 'odbc_execute' => 'odbc/odbc.stub', 'odbc_fetch_array' => 'odbc/odbc.stub', 'odbc_fetch_into' => 'odbc/odbc.stub', 'odbc_fetch_object' => 'odbc/odbc.stub', 'odbc_fetch_row' => 'odbc/odbc.stub', 'odbc_field_len' => 'odbc/odbc.stub', 'odbc_field_name' => 'odbc/odbc.stub', 'odbc_field_num' => 'odbc/odbc.stub', 'odbc_field_precision' => 'odbc/odbc.stub', 'odbc_field_scale' => 'odbc/odbc.stub', 'odbc_field_type' => 'odbc/odbc.stub', 'odbc_foreignkeys' => 'odbc/odbc.stub', 'odbc_free_result' => 'odbc/odbc.stub', 'odbc_gettypeinfo' => 'odbc/odbc.stub', 'odbc_longreadlen' => 'odbc/odbc.stub', 'odbc_next_result' => 'odbc/odbc.stub', 'odbc_num_fields' => 'odbc/odbc.stub', 'odbc_num_rows' => 'odbc/odbc.stub', 'odbc_pconnect' => 'odbc/odbc.stub', 'odbc_prepare' => 'odbc/odbc.stub', 'odbc_primarykeys' => 'odbc/odbc.stub', 'odbc_procedurecolumns' => 'odbc/odbc.stub', 'odbc_procedures' => 'odbc/odbc.stub', 'odbc_result' => 'odbc/odbc.stub', 'odbc_result_all' => 'odbc/odbc.stub', 'odbc_rollback' => 'odbc/odbc.stub', 'odbc_setoption' => 'odbc/odbc.stub', 'odbc_specialcolumns' => 'odbc/odbc.stub', 'odbc_statistics' => 'odbc/odbc.stub', 'odbc_tableprivileges' => 'odbc/odbc.stub', 'odbc_tables' => 'odbc/odbc.stub', 'opcache_compile_file' => 'Zend OPcache/OPcache.stub', 'opcache_get_configuration' => 'Zend OPcache/OPcache.stub', 'opcache_get_status' => 'Zend OPcache/OPcache.stub', 'opcache_invalidate' => 'Zend OPcache/OPcache.stub', 'opcache_is_script_cached' => 'Zend OPcache/OPcache.stub', 'opcache_reset' => 'Zend OPcache/OPcache.stub', 'opendir' => 'standard/standard_7.stub', 'openlog' => 'standard/standard_7.stub', 'openssl_cipher_iv_length' => 'openssl/openssl.stub', 'openssl_cipher_key_length' => 'openssl/openssl.stub', 'openssl_cms_decrypt' => 'openssl/openssl.stub', 'openssl_cms_encrypt' => 'openssl/openssl.stub', 'openssl_cms_read' => 'openssl/openssl.stub', 'openssl_cms_sign' => 'openssl/openssl.stub', 'openssl_cms_verify' => 'openssl/openssl.stub', 'openssl_csr_export' => 'openssl/openssl.stub', 'openssl_csr_export_to_file' => 'openssl/openssl.stub', 'openssl_csr_get_public_key' => 'openssl/openssl.stub', 'openssl_csr_get_subject' => 'openssl/openssl.stub', 'openssl_csr_new' => 'openssl/openssl.stub', 'openssl_csr_sign' => 'openssl/openssl.stub', 'openssl_decrypt' => 'openssl/openssl.stub', 'openssl_dh_compute_key' => 'openssl/openssl.stub', 'openssl_digest' => 'openssl/openssl.stub', 'openssl_encrypt' => 'openssl/openssl.stub', 'openssl_error_string' => 'openssl/openssl.stub', 'openssl_free_key' => 'openssl/openssl.stub', 'openssl_get_cert_locations' => 'openssl/openssl.stub', 'openssl_get_cipher_methods' => 'openssl/openssl.stub', 'openssl_get_curve_names' => 'openssl/openssl.stub', 'openssl_get_md_methods' => 'openssl/openssl.stub', 'openssl_get_privatekey' => 'openssl/openssl.stub', 'openssl_get_publickey' => 'openssl/openssl.stub', 'openssl_open' => 'openssl/openssl.stub', 'openssl_pbkdf2' => 'openssl/openssl.stub', 'openssl_pkcs12_export' => 'openssl/openssl.stub', 'openssl_pkcs12_export_to_file' => 'openssl/openssl.stub', 'openssl_pkcs12_read' => 'openssl/openssl.stub', 'openssl_pkcs7_decrypt' => 'openssl/openssl.stub', 'openssl_pkcs7_encrypt' => 'openssl/openssl.stub', 'openssl_pkcs7_read' => 'openssl/openssl.stub', 'openssl_pkcs7_sign' => 'openssl/openssl.stub', 'openssl_pkcs7_verify' => 'openssl/openssl.stub', 'openssl_pkey_derive' => 'openssl/openssl.stub', 'openssl_pkey_export' => 'openssl/openssl.stub', 'openssl_pkey_export_to_file' => 'openssl/openssl.stub', 'openssl_pkey_free' => 'openssl/openssl.stub', 'openssl_pkey_get_details' => 'openssl/openssl.stub', 'openssl_pkey_get_private' => 'openssl/openssl.stub', 'openssl_pkey_get_public' => 'openssl/openssl.stub', 'openssl_pkey_new' => 'openssl/openssl.stub', 'openssl_private_decrypt' => 'openssl/openssl.stub', 'openssl_private_encrypt' => 'openssl/openssl.stub', 'openssl_public_decrypt' => 'openssl/openssl.stub', 'openssl_public_encrypt' => 'openssl/openssl.stub', 'openssl_random_pseudo_bytes' => 'openssl/openssl.stub', 'openssl_seal' => 'openssl/openssl.stub', 'openssl_sign' => 'openssl/openssl.stub', 'openssl_spki_export' => 'openssl/openssl.stub', 'openssl_spki_export_challenge' => 'openssl/openssl.stub', 'openssl_spki_new' => 'openssl/openssl.stub', 'openssl_spki_verify' => 'openssl/openssl.stub', 'openssl_verify' => 'openssl/openssl.stub', 'openssl_x509_check_private_key' => 'openssl/openssl.stub', 'openssl_x509_checkpurpose' => 'openssl/openssl.stub', 'openssl_x509_export' => 'openssl/openssl.stub', 'openssl_x509_export_to_file' => 'openssl/openssl.stub', 'openssl_x509_fingerprint' => 'openssl/openssl.stub', 'openssl_x509_free' => 'openssl/openssl.stub', 'openssl_x509_parse' => 'openssl/openssl.stub', 'openssl_x509_read' => 'openssl/openssl.stub', 'openssl_x509_verify' => 'openssl/openssl.stub', 'ord' => 'standard/standard_2.stub', 'output_add_rewrite_var' => 'standard/standard_9.stub', 'output_cache_disable' => 'zend/zend.stub', 'output_cache_disable_compression' => 'zend/zend.stub', 'output_cache_exists' => 'zend/zend.stub', 'output_cache_fetch' => 'zend/zend.stub', 'output_cache_get' => 'zend/zend.stub', 'output_cache_output' => 'zend/zend.stub', 'output_cache_put' => 'zend/zend.stub', 'output_cache_remove' => 'zend/zend.stub', 'output_cache_remove_key' => 'zend/zend.stub', 'output_cache_remove_url' => 'zend/zend.stub', 'output_cache_stop' => 'zend/zend.stub', 'output_reset_rewrite_vars' => 'standard/standard_9.stub', 'pack' => 'standard/standard_7.stub', 'pam_auth' => 'pam/pam.stub', 'pam_chpass' => 'pam/pam.stub', 'parallel\\bootstrap' => 'parallel/parallel.stub', 'parallel\\count' => 'parallel/parallel.stub', 'parallel\\run' => 'parallel/parallel.stub', 'parse_ini_file' => 'standard/standard_4.stub', 'parse_ini_string' => 'standard/standard_4.stub', 'parse_str' => 'standard/standard_2.stub', 'parse_url' => 'standard/standard_2.stub', 'passthru' => 'standard/standard_2.stub', 'password_algos' => 'standard/password.stub', 'password_get_info' => 'standard/password.stub', 'password_hash' => 'standard/password.stub', 'password_needs_rehash' => 'standard/password.stub', 'password_verify' => 'standard/password.stub', 'pathinfo' => 'standard/standard_1.stub', 'pclose' => 'standard/standard_5.stub', 'pcntl_alarm' => 'pcntl/pcntl.stub', 'pcntl_async_signals' => 'pcntl/pcntl.stub', 'pcntl_errno' => 'pcntl/pcntl.stub', 'pcntl_exec' => 'pcntl/pcntl.stub', 'pcntl_fork' => 'pcntl/pcntl.stub', 'pcntl_get_last_error' => 'pcntl/pcntl.stub', 'pcntl_getcpu' => 'pcntl/pcntl.stub', 'pcntl_getcpuaffinity' => 'pcntl/pcntl.stub', 'pcntl_getpriority' => 'pcntl/pcntl.stub', 'pcntl_setcpuaffinity' => 'pcntl/pcntl.stub', 'pcntl_setpriority' => 'pcntl/pcntl.stub', 'pcntl_signal' => 'pcntl/pcntl.stub', 'pcntl_signal_dispatch' => 'pcntl/pcntl.stub', 'pcntl_signal_get_handler' => 'pcntl/pcntl.stub', 'pcntl_sigprocmask' => 'pcntl/pcntl.stub', 'pcntl_sigtimedwait' => 'pcntl/pcntl.stub', 'pcntl_sigwaitinfo' => 'pcntl/pcntl.stub', 'pcntl_strerror' => 'pcntl/pcntl.stub', 'pcntl_unshare' => 'pcntl/pcntl.stub', 'pcntl_wait' => 'pcntl/pcntl.stub', 'pcntl_waitid' => 'pcntl/pcntl.stub', 'pcntl_waitpid' => 'pcntl/pcntl.stub', 'pcntl_wexitstatus' => 'pcntl/pcntl.stub', 'pcntl_wifcontinued' => 'pcntl/pcntl.stub', 'pcntl_wifexited' => 'pcntl/pcntl.stub', 'pcntl_wifsignaled' => 'pcntl/pcntl.stub', 'pcntl_wifstopped' => 'pcntl/pcntl.stub', 'pcntl_wstopsig' => 'pcntl/pcntl.stub', 'pcntl_wtermsig' => 'pcntl/pcntl.stub', 'pcov\\clear' => 'pcov/pcov.stub', 'pcov\\collect' => 'pcov/pcov.stub', 'pcov\\memory' => 'pcov/pcov.stub', 'pcov\\start' => 'pcov/pcov.stub', 'pcov\\stop' => 'pcov/pcov.stub', 'pcov\\waiting' => 'pcov/pcov.stub', 'pdo_drivers' => 'PDO/PDO.stub', 'pfsockopen' => 'standard/standard_7.stub', 'pg_affected_rows' => 'pgsql/pgsql.stub', 'pg_cancel_query' => 'pgsql/pgsql.stub', 'pg_change_password' => 'pgsql/pgsql.stub', 'pg_client_encoding' => 'pgsql/pgsql.stub', 'pg_clientencoding' => 'pgsql/pgsql.stub', 'pg_close' => 'pgsql/pgsql.stub', 'pg_cmdtuples' => 'pgsql/pgsql.stub', 'pg_connect' => 'pgsql/pgsql.stub', 'pg_connect_poll' => 'pgsql/pgsql.stub', 'pg_connection_busy' => 'pgsql/pgsql.stub', 'pg_connection_reset' => 'pgsql/pgsql.stub', 'pg_connection_status' => 'pgsql/pgsql.stub', 'pg_consume_input' => 'pgsql/pgsql.stub', 'pg_convert' => 'pgsql/pgsql.stub', 'pg_copy_from' => 'pgsql/pgsql.stub', 'pg_copy_to' => 'pgsql/pgsql.stub', 'pg_dbname' => 'pgsql/pgsql.stub', 'pg_delete' => 'pgsql/pgsql.stub', 'pg_end_copy' => 'pgsql/pgsql.stub', 'pg_enter_pipeline_mode' => 'pgsql/pgsql.stub', 'pg_errormessage' => 'pgsql/pgsql.stub', 'pg_escape_bytea' => 'pgsql/pgsql.stub', 'pg_escape_identifier' => 'pgsql/pgsql.stub', 'pg_escape_literal' => 'pgsql/pgsql.stub', 'pg_escape_string' => 'pgsql/pgsql.stub', 'pg_exec' => 'pgsql/pgsql.stub', 'pg_execute' => 'pgsql/pgsql.stub', 'pg_exit_pipeline_mode' => 'pgsql/pgsql.stub', 'pg_fetch_all' => 'pgsql/pgsql.stub', 'pg_fetch_all_columns' => 'pgsql/pgsql.stub', 'pg_fetch_array' => 'pgsql/pgsql.stub', 'pg_fetch_assoc' => 'pgsql/pgsql.stub', 'pg_fetch_object' => 'pgsql/pgsql.stub', 'pg_fetch_result' => 'pgsql/pgsql.stub', 'pg_fetch_row' => 'pgsql/pgsql.stub', 'pg_field_is_null' => 'pgsql/pgsql.stub', 'pg_field_name' => 'pgsql/pgsql.stub', 'pg_field_num' => 'pgsql/pgsql.stub', 'pg_field_prtlen' => 'pgsql/pgsql.stub', 'pg_field_size' => 'pgsql/pgsql.stub', 'pg_field_table' => 'pgsql/pgsql.stub', 'pg_field_type' => 'pgsql/pgsql.stub', 'pg_field_type_oid' => 'pgsql/pgsql.stub', 'pg_fieldisnull' => 'pgsql/pgsql.stub', 'pg_fieldname' => 'pgsql/pgsql.stub', 'pg_fieldnum' => 'pgsql/pgsql.stub', 'pg_fieldprtlen' => 'pgsql/pgsql.stub', 'pg_fieldsize' => 'pgsql/pgsql.stub', 'pg_fieldtype' => 'pgsql/pgsql.stub', 'pg_flush' => 'pgsql/pgsql.stub', 'pg_free_result' => 'pgsql/pgsql.stub', 'pg_freeresult' => 'pgsql/pgsql.stub', 'pg_get_notify' => 'pgsql/pgsql.stub', 'pg_get_pid' => 'pgsql/pgsql.stub', 'pg_get_result' => 'pgsql/pgsql.stub', 'pg_getlastoid' => 'pgsql/pgsql.stub', 'pg_host' => 'pgsql/pgsql.stub', 'pg_insert' => 'pgsql/pgsql.stub', 'pg_jit' => 'pgsql/pgsql.stub', 'pg_last_error' => 'pgsql/pgsql.stub', 'pg_last_notice' => 'pgsql/pgsql.stub', 'pg_last_oid' => 'pgsql/pgsql.stub', 'pg_lo_close' => 'pgsql/pgsql.stub', 'pg_lo_create' => 'pgsql/pgsql.stub', 'pg_lo_export' => 'pgsql/pgsql.stub', 'pg_lo_import' => 'pgsql/pgsql.stub', 'pg_lo_open' => 'pgsql/pgsql.stub', 'pg_lo_read' => 'pgsql/pgsql.stub', 'pg_lo_read_all' => 'pgsql/pgsql.stub', 'pg_lo_seek' => 'pgsql/pgsql.stub', 'pg_lo_tell' => 'pgsql/pgsql.stub', 'pg_lo_truncate' => 'pgsql/pgsql.stub', 'pg_lo_unlink' => 'pgsql/pgsql.stub', 'pg_lo_write' => 'pgsql/pgsql.stub', 'pg_loclose' => 'pgsql/pgsql.stub', 'pg_locreate' => 'pgsql/pgsql.stub', 'pg_loexport' => 'pgsql/pgsql.stub', 'pg_loimport' => 'pgsql/pgsql.stub', 'pg_loopen' => 'pgsql/pgsql.stub', 'pg_loread' => 'pgsql/pgsql.stub', 'pg_loreadall' => 'pgsql/pgsql.stub', 'pg_lounlink' => 'pgsql/pgsql.stub', 'pg_lowrite' => 'pgsql/pgsql.stub', 'pg_meta_data' => 'pgsql/pgsql.stub', 'pg_num_fields' => 'pgsql/pgsql.stub', 'pg_num_rows' => 'pgsql/pgsql.stub', 'pg_numfields' => 'pgsql/pgsql.stub', 'pg_numrows' => 'pgsql/pgsql.stub', 'pg_options' => 'pgsql/pgsql.stub', 'pg_parameter_status' => 'pgsql/pgsql.stub', 'pg_pconnect' => 'pgsql/pgsql.stub', 'pg_ping' => 'pgsql/pgsql.stub', 'pg_pipeline_status' => 'pgsql/pgsql.stub', 'pg_pipeline_sync' => 'pgsql/pgsql.stub', 'pg_port' => 'pgsql/pgsql.stub', 'pg_prepare' => 'pgsql/pgsql.stub', 'pg_put_copy_data' => 'pgsql/pgsql.stub', 'pg_put_copy_end' => 'pgsql/pgsql.stub', 'pg_put_line' => 'pgsql/pgsql.stub', 'pg_query' => 'pgsql/pgsql.stub', 'pg_query_params' => 'pgsql/pgsql.stub', 'pg_result' => 'pgsql/pgsql.stub', 'pg_result_error' => 'pgsql/pgsql.stub', 'pg_result_error_field' => 'pgsql/pgsql.stub', 'pg_result_memory_size' => 'pgsql/pgsql.stub', 'pg_result_seek' => 'pgsql/pgsql.stub', 'pg_result_status' => 'pgsql/pgsql.stub', 'pg_select' => 'pgsql/pgsql.stub', 'pg_send_execute' => 'pgsql/pgsql.stub', 'pg_send_prepare' => 'pgsql/pgsql.stub', 'pg_send_query' => 'pgsql/pgsql.stub', 'pg_send_query_params' => 'pgsql/pgsql.stub', 'pg_set_client_encoding' => 'pgsql/pgsql.stub', 'pg_set_error_context_visibility' => 'pgsql/pgsql.stub', 'pg_set_error_verbosity' => 'pgsql/pgsql.stub', 'pg_setclientencoding' => 'pgsql/pgsql.stub', 'pg_socket' => 'pgsql/pgsql.stub', 'pg_socket_poll' => 'pgsql/pgsql.stub', 'pg_trace' => 'pgsql/pgsql.stub', 'pg_transaction_status' => 'pgsql/pgsql.stub', 'pg_tty' => 'pgsql/pgsql.stub', 'pg_unescape_bytea' => 'pgsql/pgsql.stub', 'pg_untrace' => 'pgsql/pgsql.stub', 'pg_update' => 'pgsql/pgsql.stub', 'pg_version' => 'pgsql/pgsql.stub', 'php_egg_logo_guid' => 'standard/standard_0.stub', 'php_ini_loaded_file' => 'standard/standard_0.stub', 'php_ini_scanned_files' => 'standard/standard_0.stub', 'php_logo_guid' => 'standard/standard_0.stub', 'php_real_logo_guid' => 'standard/standard_0.stub', 'php_sapi_name' => 'standard/standard_0.stub', 'php_strip_whitespace' => 'standard/standard_4.stub', 'php_uname' => 'standard/standard_0.stub', 'phpcredits' => 'standard/standard_0.stub', 'phpdbg_break_file' => 'phpdbg/phpdbg.stub', 'phpdbg_break_function' => 'phpdbg/phpdbg.stub', 'phpdbg_break_method' => 'phpdbg/phpdbg.stub', 'phpdbg_break_next' => 'phpdbg/phpdbg.stub', 'phpdbg_clear' => 'phpdbg/phpdbg.stub', 'phpdbg_color' => 'phpdbg/phpdbg.stub', 'phpdbg_end_oplog' => 'phpdbg/phpdbg.stub', 'phpdbg_exec' => 'phpdbg/phpdbg.stub', 'phpdbg_get_executable' => 'phpdbg/phpdbg.stub', 'phpdbg_prompt' => 'phpdbg/phpdbg.stub', 'phpdbg_start_oplog' => 'phpdbg/phpdbg.stub', 'phpinfo' => 'standard/standard_0.stub', 'phpversion' => 'standard/standard_0.stub', 'pi' => 'standard/standard_3.stub', 'png2wbmp' => 'gd/gd.stub', 'popen' => 'standard/standard_5.stub', 'pos' => 'standard/standard_9.stub', 'posix_access' => 'posix/posix.stub', 'posix_ctermid' => 'posix/posix.stub', 'posix_eaccess' => 'posix/posix.stub', 'posix_errno' => 'posix/posix.stub', 'posix_get_last_error' => 'posix/posix.stub', 'posix_getcwd' => 'posix/posix.stub', 'posix_getegid' => 'posix/posix.stub', 'posix_geteuid' => 'posix/posix.stub', 'posix_getgid' => 'posix/posix.stub', 'posix_getgrgid' => 'posix/posix.stub', 'posix_getgrnam' => 'posix/posix.stub', 'posix_getgroups' => 'posix/posix.stub', 'posix_getlogin' => 'posix/posix.stub', 'posix_getpgid' => 'posix/posix.stub', 'posix_getpgrp' => 'posix/posix.stub', 'posix_getpid' => 'posix/posix.stub', 'posix_getppid' => 'posix/posix.stub', 'posix_getpwnam' => 'posix/posix.stub', 'posix_getpwuid' => 'posix/posix.stub', 'posix_getrlimit' => 'posix/posix.stub', 'posix_getsid' => 'posix/posix.stub', 'posix_getuid' => 'posix/posix.stub', 'posix_initgroups' => 'posix/posix.stub', 'posix_isatty' => 'posix/posix.stub', 'posix_kill' => 'posix/posix.stub', 'posix_mkfifo' => 'posix/posix.stub', 'posix_mknod' => 'posix/posix.stub', 'posix_setegid' => 'posix/posix.stub', 'posix_seteuid' => 'posix/posix.stub', 'posix_setgid' => 'posix/posix.stub', 'posix_setpgid' => 'posix/posix.stub', 'posix_setrlimit' => 'posix/posix.stub', 'posix_setsid' => 'posix/posix.stub', 'posix_setuid' => 'posix/posix.stub', 'posix_strerror' => 'posix/posix.stub', 'posix_sysconf' => 'posix/posix.stub', 'posix_times' => 'posix/posix.stub', 'posix_ttyname' => 'posix/posix.stub', 'posix_uname' => 'posix/posix.stub', 'pow' => 'standard/standard_3.stub', 'preg_filter' => 'pcre/pcre.stub', 'preg_grep' => 'pcre/pcre.stub', 'preg_last_error' => 'pcre/pcre.stub', 'preg_last_error_msg' => 'pcre/pcre.stub', 'preg_match' => 'pcre/pcre.stub', 'preg_match_all' => 'pcre/pcre.stub', 'preg_quote' => 'pcre/pcre.stub', 'preg_replace' => 'pcre/pcre.stub', 'preg_replace_callback' => 'pcre/pcre.stub', 'preg_replace_callback_array' => 'pcre/pcre.stub', 'preg_split' => 'pcre/pcre.stub', 'prev' => 'standard/standard_8.stub', 'print_r' => 'standard/standard_4.stub', 'printf' => 'standard/standard_2.stub', 'proc_close' => 'standard/standard_2.stub', 'proc_get_status' => 'standard/standard_2.stub', 'proc_nice' => 'standard/standard_2.stub', 'proc_open' => 'standard/standard_2.stub', 'proc_terminate' => 'standard/standard_2.stub', 'property_exists' => 'Core/Core.stub', 'pspell_add_to_personal' => 'pspell/pspell.stub', 'pspell_add_to_session' => 'pspell/pspell.stub', 'pspell_check' => 'pspell/pspell.stub', 'pspell_clear_session' => 'pspell/pspell.stub', 'pspell_config_create' => 'pspell/pspell.stub', 'pspell_config_data_dir' => 'pspell/pspell.stub', 'pspell_config_dict_dir' => 'pspell/pspell.stub', 'pspell_config_ignore' => 'pspell/pspell.stub', 'pspell_config_mode' => 'pspell/pspell.stub', 'pspell_config_personal' => 'pspell/pspell.stub', 'pspell_config_repl' => 'pspell/pspell.stub', 'pspell_config_runtogether' => 'pspell/pspell.stub', 'pspell_config_save_repl' => 'pspell/pspell.stub', 'pspell_new' => 'pspell/pspell.stub', 'pspell_new_config' => 'pspell/pspell.stub', 'pspell_new_personal' => 'pspell/pspell.stub', 'pspell_save_wordlist' => 'pspell/pspell.stub', 'pspell_store_replacement' => 'pspell/pspell.stub', 'pspell_suggest' => 'pspell/pspell.stub', 'putenv' => 'standard/standard_3.stub', 'quoted_printable_decode' => 'standard/standard_3.stub', 'quoted_printable_encode' => 'standard/standard_3.stub', 'quotemeta' => 'standard/standard_1.stub', 'rad2deg' => 'standard/standard_3.stub', 'radius_acct_open' => 'radius/radius.stub', 'radius_add_server' => 'radius/radius.stub', 'radius_auth_open' => 'radius/radius.stub', 'radius_close' => 'radius/radius.stub', 'radius_config' => 'radius/radius.stub', 'radius_create_request' => 'radius/radius.stub', 'rand' => 'random/random.stub', 'random_bytes' => 'random/random.stub', 'random_int' => 'random/random.stub', 'range' => 'standard/standard_8.stub', 'rawurldecode' => 'standard/standard_2.stub', 'rawurlencode' => 'standard/standard_2.stub', 'rd_kafka_err2str' => 'rdkafka/functions.stub', 'rd_kafka_errno' => 'rdkafka/functions.stub', 'rd_kafka_errno2err' => 'rdkafka/functions.stub', 'rd_kafka_get_err_descs' => 'rdkafka/functions.stub', 'rd_kafka_offset_tail' => 'rdkafka/functions.stub', 'rd_kafka_thread_cnt' => 'rdkafka/functions.stub', 'read_exif_data' => 'exif/exif.stub', 'readdir' => 'standard/standard_7.stub', 'readfile' => 'standard/standard_5.stub', 'readgzfile' => 'zlib/zlib.stub', 'readline' => 'readline/readline.stub', 'readline_add_history' => 'readline/readline.stub', 'readline_callback_handler_install' => 'readline/readline.stub', 'readline_callback_handler_remove' => 'readline/readline.stub', 'readline_callback_read_char' => 'readline/readline.stub', 'readline_clear_history' => 'readline/readline.stub', 'readline_completion_function' => 'readline/readline.stub', 'readline_info' => 'readline/readline.stub', 'readline_list_history' => 'readline/readline.stub', 'readline_on_new_line' => 'readline/readline.stub', 'readline_read_history' => 'readline/readline.stub', 'readline_redisplay' => 'readline/readline.stub', 'readline_write_history' => 'readline/readline.stub', 'readlink' => 'standard/standard_2.stub', 'realpath' => 'standard/standard_6.stub', 'realpath_cache_get' => 'standard/standard_9.stub', 'realpath_cache_size' => 'standard/standard_9.stub', 'recode' => 'recode/recode.stub', 'recode_file' => 'recode/recode.stub', 'recode_string' => 'recode/recode.stub', 'register_event_handler' => 'zend/zend.stub', 'register_shutdown_function' => 'standard/standard_4.stub', 'register_tick_function' => 'standard/standard_4.stub', 'rename' => 'standard/standard_5.stub', 'request_parse_body' => 'standard/standard_10.stub', 'reset' => 'standard/standard_8.stub', 'resourcebundle_count' => 'intl/intl.stub', 'resourcebundle_create' => 'intl/intl.stub', 'resourcebundle_get' => 'intl/intl.stub', 'resourcebundle_get_error_code' => 'intl/intl.stub', 'resourcebundle_get_error_message' => 'intl/intl.stub', 'resourcebundle_locales' => 'intl/intl.stub', 'restore_error_handler' => 'Core/Core.stub', 'restore_exception_handler' => 'Core/Core.stub', 'restore_include_path' => 'standard/standard_4.stub', 'rewind' => 'standard/standard_5.stub', 'rewinddir' => 'standard/standard_7.stub', 'rmdir' => 'standard/standard_5.stub', 'round' => 'standard/standard_3.stub', 'rpmaddtag' => 'rpminfo/rpminfo.stub', 'rpmdbinfo' => 'rpminfo/rpminfo.stub', 'rpmdbsearch' => 'rpminfo/rpminfo.stub', 'rpminfo' => 'rpminfo/rpminfo.stub', 'rpmvercmp' => 'rpminfo/rpminfo.stub', 'rrd_create' => 'rrd/rrd.stub', 'rrd_disconnect' => 'rrd/rrd.stub', 'rrd_error' => 'rrd/rrd.stub', 'rrd_fetch' => 'rrd/rrd.stub', 'rrd_first' => 'rrd/rrd.stub', 'rrd_graph' => 'rrd/rrd.stub', 'rrd_info' => 'rrd/rrd.stub', 'rrd_last' => 'rrd/rrd.stub', 'rrd_lastupdate' => 'rrd/rrd.stub', 'rrd_restore' => 'rrd/rrd.stub', 'rrd_tune' => 'rrd/rrd.stub', 'rrd_update' => 'rrd/rrd.stub', 'rrd_version' => 'rrd/rrd.stub', 'rrd_xport' => 'rrd/rrd.stub', 'rrdc_disconnect' => 'rrd/rrd.stub', 'rsort' => 'standard/standard_8.stub', 'rtrim' => 'standard/standard_1.stub', 'sapi_windows_cp_conv' => 'standard/basic.stub', 'sapi_windows_cp_get' => 'standard/basic.stub', 'sapi_windows_cp_is_utf8' => 'standard/basic.stub', 'sapi_windows_cp_set' => 'standard/basic.stub', 'sapi_windows_generate_ctrl_event' => 'standard/basic.stub', 'sapi_windows_set_ctrl_handler' => 'standard/basic.stub', 'sapi_windows_vt100_support' => 'standard/basic.stub', 'scandir' => 'standard/standard_7.stub', 'sem_acquire' => 'sysvsem/sysvsem.stub', 'sem_get' => 'sysvsem/sysvsem.stub', 'sem_release' => 'sysvsem/sysvsem.stub', 'sem_remove' => 'sysvsem/sysvsem.stub', 'serialize' => 'standard/standard_4.stub', 'session_abort' => 'session/session.stub', 'session_cache_expire' => 'session/session.stub', 'session_cache_limiter' => 'session/session.stub', 'session_commit' => 'session/session.stub', 'session_create_id' => 'session/session.stub', 'session_decode' => 'session/session.stub', 'session_destroy' => 'session/session.stub', 'session_encode' => 'session/session.stub', 'session_gc' => 'session/session.stub', 'session_get_cookie_params' => 'session/session.stub', 'session_id' => 'session/session.stub', 'session_is_registered' => 'session/session.stub', 'session_module_name' => 'session/session.stub', 'session_name' => 'session/session.stub', 'session_regenerate_id' => 'session/session.stub', 'session_register' => 'session/session.stub', 'session_register_shutdown' => 'session/session.stub', 'session_reset' => 'session/session.stub', 'session_save_path' => 'session/session.stub', 'session_set_cookie_params' => 'session/session.stub', 'session_set_save_handler' => 'session/session.stub', 'session_start' => 'session/session.stub', 'session_status' => 'session/session.stub', 'session_unregister' => 'session/session.stub', 'session_unset' => 'session/session.stub', 'session_write_close' => 'session/session.stub', 'set_error_handler' => 'Core/Core.stub', 'set_exception_handler' => 'Core/Core.stub', 'set_file_buffer' => 'standard/standard_6.stub', 'set_include_path' => 'standard/standard_4.stub', 'set_job_failed' => 'zend/zend_f.stub', 'set_magic_quotes_runtime' => 'standard/standard_3.stub', 'set_socket_blocking' => 'standard/standard_6.stub', 'set_time_limit' => 'standard/standard_3.stub', 'setcookie' => 'standard/standard_4.stub', 'setlocale' => 'standard/standard_1.stub', 'setrawcookie' => 'standard/standard_4.stub', 'settype' => 'standard/standard_5.stub', 'sha1' => 'standard/standard_0.stub', 'sha1_file' => 'standard/standard_0.stub', 'shell_exec' => 'standard/standard_2.stub', 'shm_attach' => 'sysvshm/sysvshm.stub', 'shm_detach' => 'sysvshm/sysvshm.stub', 'shm_get_var' => 'sysvshm/sysvshm.stub', 'shm_has_var' => 'sysvshm/sysvshm.stub', 'shm_put_var' => 'sysvshm/sysvshm.stub', 'shm_remove' => 'sysvshm/sysvshm.stub', 'shm_remove_var' => 'sysvshm/sysvshm.stub', 'shmop_close' => 'shmop/shmop.stub', 'shmop_delete' => 'shmop/shmop.stub', 'shmop_open' => 'shmop/shmop.stub', 'shmop_read' => 'shmop/shmop.stub', 'shmop_size' => 'shmop/shmop.stub', 'shmop_write' => 'shmop/shmop.stub', 'show_source' => 'standard/standard_4.stub', 'shuffle' => 'standard/standard_8.stub', 'simdjson_decode' => 'simdjson/simdjson.stub', 'simdjson_is_valid' => 'simdjson/simdjson.stub', 'simdjson_key_count' => 'simdjson/simdjson.stub', 'simdjson_key_exists' => 'simdjson/simdjson.stub', 'simdjson_key_value' => 'simdjson/simdjson.stub', 'similar_text' => 'standard/standard_1.stub', 'simplexml_import_dom' => 'SimpleXML/SimpleXML.stub', 'simplexml_load_file' => 'SimpleXML/SimpleXML.stub', 'simplexml_load_string' => 'SimpleXML/SimpleXML.stub', 'sin' => 'standard/standard_3.stub', 'sinh' => 'standard/standard_3.stub', 'sizeof' => 'standard/standard_9.stub', 'sleep' => 'standard/standard_0.stub', 'snappy_compress' => 'snappy/snappy/snappy.stub', 'snappy_uncompress' => 'snappy/snappy/snappy.stub', 'snmp2_get' => 'snmp/snmp.stub', 'snmp2_getnext' => 'snmp/snmp.stub', 'snmp2_real_walk' => 'snmp/snmp.stub', 'snmp2_set' => 'snmp/snmp.stub', 'snmp2_walk' => 'snmp/snmp.stub', 'snmp3_get' => 'snmp/snmp.stub', 'snmp3_getnext' => 'snmp/snmp.stub', 'snmp3_real_walk' => 'snmp/snmp.stub', 'snmp3_set' => 'snmp/snmp.stub', 'snmp3_walk' => 'snmp/snmp.stub', 'snmp_get_quick_print' => 'snmp/snmp.stub', 'snmp_get_valueretrieval' => 'snmp/snmp.stub', 'snmp_read_mib' => 'snmp/snmp.stub', 'snmp_set_enum_print' => 'snmp/snmp.stub', 'snmp_set_oid_numeric_print' => 'snmp/snmp.stub', 'snmp_set_oid_output_format' => 'snmp/snmp.stub', 'snmp_set_quick_print' => 'snmp/snmp.stub', 'snmp_set_valueretrieval' => 'snmp/snmp.stub', 'snmpget' => 'snmp/snmp.stub', 'snmpgetnext' => 'snmp/snmp.stub', 'snmprealwalk' => 'snmp/snmp.stub', 'snmpset' => 'snmp/snmp.stub', 'snmpwalk' => 'snmp/snmp.stub', 'snmpwalkoid' => 'snmp/snmp.stub', 'socket_accept' => 'sockets/sockets.stub', 'socket_addrinfo_bind' => 'sockets/sockets.stub', 'socket_addrinfo_connect' => 'sockets/sockets.stub', 'socket_addrinfo_explain' => 'sockets/sockets.stub', 'socket_addrinfo_lookup' => 'sockets/sockets.stub', 'socket_atmark' => 'sockets/sockets.stub', 'socket_bind' => 'sockets/sockets.stub', 'socket_clear_error' => 'sockets/sockets.stub', 'socket_close' => 'sockets/sockets.stub', 'socket_cmsg_space' => 'sockets/sockets.stub', 'socket_connect' => 'sockets/sockets.stub', 'socket_create' => 'sockets/sockets.stub', 'socket_create_listen' => 'sockets/sockets.stub', 'socket_create_pair' => 'sockets/sockets.stub', 'socket_export_stream' => 'sockets/sockets.stub', 'socket_get_option' => 'sockets/sockets.stub', 'socket_get_status' => 'standard/standard_6.stub', 'socket_getopt' => 'sockets/sockets.stub', 'socket_getpeername' => 'sockets/sockets.stub', 'socket_getsockname' => 'sockets/sockets.stub', 'socket_import_stream' => 'sockets/sockets.stub', 'socket_last_error' => 'sockets/sockets.stub', 'socket_listen' => 'sockets/sockets.stub', 'socket_read' => 'sockets/sockets.stub', 'socket_recv' => 'sockets/sockets.stub', 'socket_recvfrom' => 'sockets/sockets.stub', 'socket_recvmsg' => 'sockets/sockets.stub', 'socket_select' => 'sockets/sockets.stub', 'socket_send' => 'sockets/sockets.stub', 'socket_sendmsg' => 'sockets/sockets.stub', 'socket_sendto' => 'sockets/sockets.stub', 'socket_set_block' => 'sockets/sockets.stub', 'socket_set_blocking' => 'standard/standard_6.stub', 'socket_set_nonblock' => 'sockets/sockets.stub', 'socket_set_option' => 'sockets/sockets.stub', 'socket_set_timeout' => 'standard/standard_6.stub', 'socket_setopt' => 'sockets/sockets.stub', 'socket_shutdown' => 'sockets/sockets.stub', 'socket_strerror' => 'sockets/sockets.stub', 'socket_write' => 'sockets/sockets.stub', 'socket_wsaprotocol_info_export' => 'sockets/sockets.stub', 'socket_wsaprotocol_info_import' => 'sockets/sockets.stub', 'socket_wsaprotocol_info_release' => 'sockets/sockets.stub', 'sodium_add' => 'sodium/sodium.stub', 'sodium_base642bin' => 'sodium/sodium.stub', 'sodium_bin2base64' => 'sodium/sodium.stub', 'sodium_bin2hex' => 'sodium/sodium.stub', 'sodium_compare' => 'sodium/sodium.stub', 'sodium_crypto_aead_aegis128l_decrypt' => 'libsodium/libsodium_f.stub', 'sodium_crypto_aead_aegis128l_encrypt' => 'libsodium/libsodium_f.stub', 'sodium_crypto_aead_aegis128l_keygen' => 'libsodium/libsodium_f.stub', 'sodium_crypto_aead_aegis256_decrypt' => 'libsodium/libsodium_f.stub', 'sodium_crypto_aead_aegis256_encrypt' => 'libsodium/libsodium_f.stub', 'sodium_crypto_aead_aegis256_keygen' => 'libsodium/libsodium_f.stub', 'sodium_crypto_aead_aes256gcm_decrypt' => 'sodium/sodium.stub', 'sodium_crypto_aead_aes256gcm_encrypt' => 'sodium/sodium.stub', 'sodium_crypto_aead_aes256gcm_is_available' => 'sodium/sodium.stub', 'sodium_crypto_aead_aes256gcm_keygen' => 'sodium/sodium.stub', 'sodium_crypto_aead_chacha20poly1305_decrypt' => 'sodium/sodium.stub', 'sodium_crypto_aead_chacha20poly1305_encrypt' => 'sodium/sodium.stub', 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => 'sodium/sodium.stub', 'sodium_crypto_aead_chacha20poly1305_ietf_encrypt' => 'sodium/sodium.stub', 'sodium_crypto_aead_chacha20poly1305_ietf_keygen' => 'sodium/sodium.stub', 'sodium_crypto_aead_chacha20poly1305_keygen' => 'sodium/sodium.stub', 'sodium_crypto_aead_xchacha20poly1305_ietf_decrypt' => 'sodium/sodium.stub', 'sodium_crypto_aead_xchacha20poly1305_ietf_encrypt' => 'sodium/sodium.stub', 'sodium_crypto_aead_xchacha20poly1305_ietf_keygen' => 'sodium/sodium.stub', 'sodium_crypto_auth' => 'sodium/sodium.stub', 'sodium_crypto_auth_keygen' => 'sodium/sodium.stub', 'sodium_crypto_auth_verify' => 'sodium/sodium.stub', 'sodium_crypto_box' => 'sodium/sodium.stub', 'sodium_crypto_box_keypair' => 'sodium/sodium.stub', 'sodium_crypto_box_keypair_from_secretkey_and_publickey' => 'sodium/sodium.stub', 'sodium_crypto_box_open' => 'sodium/sodium.stub', 'sodium_crypto_box_publickey' => 'sodium/sodium.stub', 'sodium_crypto_box_publickey_from_secretkey' => 'sodium/sodium.stub', 'sodium_crypto_box_seal' => 'sodium/sodium.stub', 'sodium_crypto_box_seal_open' => 'sodium/sodium.stub', 'sodium_crypto_box_secretkey' => 'sodium/sodium.stub', 'sodium_crypto_box_seed_keypair' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_add' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_from_hash' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_is_valid_point' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_random' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_scalar_add' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_scalar_complement' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_scalar_invert' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_scalar_mul' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_scalar_negate' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_scalar_random' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_scalar_reduce' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_scalar_sub' => 'sodium/sodium.stub', 'sodium_crypto_core_ristretto255_sub' => 'sodium/sodium.stub', 'sodium_crypto_generichash' => 'sodium/sodium.stub', 'sodium_crypto_generichash_final' => 'sodium/sodium.stub', 'sodium_crypto_generichash_init' => 'sodium/sodium.stub', 'sodium_crypto_generichash_keygen' => 'sodium/sodium.stub', 'sodium_crypto_generichash_update' => 'sodium/sodium.stub', 'sodium_crypto_kdf_derive_from_key' => 'sodium/sodium.stub', 'sodium_crypto_kdf_keygen' => 'sodium/sodium.stub', 'sodium_crypto_kx' => 'sodium/sodium.stub', 'sodium_crypto_kx_client_session_keys' => 'sodium/sodium.stub', 'sodium_crypto_kx_keypair' => 'sodium/sodium.stub', 'sodium_crypto_kx_publickey' => 'sodium/sodium.stub', 'sodium_crypto_kx_secretkey' => 'sodium/sodium.stub', 'sodium_crypto_kx_seed_keypair' => 'sodium/sodium.stub', 'sodium_crypto_kx_server_session_keys' => 'sodium/sodium.stub', 'sodium_crypto_pwhash' => 'sodium/sodium.stub', 'sodium_crypto_pwhash_scryptsalsa208sha256' => 'sodium/sodium.stub', 'sodium_crypto_pwhash_scryptsalsa208sha256_str' => 'sodium/sodium.stub', 'sodium_crypto_pwhash_scryptsalsa208sha256_str_verify' => 'sodium/sodium.stub', 'sodium_crypto_pwhash_str' => 'sodium/sodium.stub', 'sodium_crypto_pwhash_str_needs_rehash' => 'sodium/sodium.stub', 'sodium_crypto_pwhash_str_verify' => 'sodium/sodium.stub', 'sodium_crypto_scalarmult' => 'sodium/sodium.stub', 'sodium_crypto_scalarmult_base' => 'sodium/sodium.stub', 'sodium_crypto_scalarmult_ristretto255' => 'sodium/sodium.stub', 'sodium_crypto_scalarmult_ristretto255_base' => 'sodium/sodium.stub', 'sodium_crypto_secretbox' => 'sodium/sodium.stub', 'sodium_crypto_secretbox_keygen' => 'sodium/sodium.stub', 'sodium_crypto_secretbox_open' => 'sodium/sodium.stub', 'sodium_crypto_secretstream_xchacha20poly1305_init_pull' => 'sodium/sodium.stub', 'sodium_crypto_secretstream_xchacha20poly1305_init_push' => 'sodium/sodium.stub', 'sodium_crypto_secretstream_xchacha20poly1305_keygen' => 'sodium/sodium.stub', 'sodium_crypto_secretstream_xchacha20poly1305_pull' => 'sodium/sodium.stub', 'sodium_crypto_secretstream_xchacha20poly1305_push' => 'sodium/sodium.stub', 'sodium_crypto_secretstream_xchacha20poly1305_rekey' => 'sodium/sodium.stub', 'sodium_crypto_shorthash' => 'sodium/sodium.stub', 'sodium_crypto_shorthash_keygen' => 'sodium/sodium.stub', 'sodium_crypto_sign' => 'sodium/sodium.stub', 'sodium_crypto_sign_detached' => 'sodium/sodium.stub', 'sodium_crypto_sign_ed25519_pk_to_curve25519' => 'sodium/sodium.stub', 'sodium_crypto_sign_ed25519_sk_to_curve25519' => 'sodium/sodium.stub', 'sodium_crypto_sign_keypair' => 'sodium/sodium.stub', 'sodium_crypto_sign_keypair_from_secretkey_and_publickey' => 'sodium/sodium.stub', 'sodium_crypto_sign_open' => 'sodium/sodium.stub', 'sodium_crypto_sign_publickey' => 'sodium/sodium.stub', 'sodium_crypto_sign_publickey_from_secretkey' => 'sodium/sodium.stub', 'sodium_crypto_sign_secretkey' => 'sodium/sodium.stub', 'sodium_crypto_sign_seed_keypair' => 'sodium/sodium.stub', 'sodium_crypto_sign_verify_detached' => 'sodium/sodium.stub', 'sodium_crypto_stream' => 'sodium/sodium.stub', 'sodium_crypto_stream_keygen' => 'sodium/sodium.stub', 'sodium_crypto_stream_xchacha20' => 'sodium/sodium.stub', 'sodium_crypto_stream_xchacha20_keygen' => 'sodium/sodium.stub', 'sodium_crypto_stream_xchacha20_xor' => 'sodium/sodium.stub', 'sodium_crypto_stream_xchacha20_xor_ic' => 'sodium/sodium.stub', 'sodium_crypto_stream_xor' => 'sodium/sodium.stub', 'sodium_hex2bin' => 'sodium/sodium.stub', 'sodium_increment' => 'sodium/sodium.stub', 'sodium_library_version_major' => 'sodium/sodium.stub', 'sodium_library_version_minor' => 'sodium/sodium.stub', 'sodium_memcmp' => 'sodium/sodium.stub', 'sodium_memzero' => 'sodium/sodium.stub', 'sodium_pad' => 'sodium/sodium.stub', 'sodium_randombytes_buf' => 'sodium/sodium.stub', 'sodium_randombytes_random16' => 'sodium/sodium.stub', 'sodium_randombytes_uniform' => 'sodium/sodium.stub', 'sodium_unpad' => 'sodium/sodium.stub', 'sodium_version_string' => 'sodium/sodium.stub', 'solr_get_version' => 'solr/functions.stub', 'sort' => 'standard/standard_8.stub', 'soundex' => 'standard/standard_2.stub', 'spl_autoload' => 'SPL/SPL_f.stub', 'spl_autoload_call' => 'SPL/SPL_f.stub', 'spl_autoload_extensions' => 'SPL/SPL_f.stub', 'spl_autoload_functions' => 'SPL/SPL_f.stub', 'spl_autoload_register' => 'SPL/SPL_f.stub', 'spl_autoload_unregister' => 'SPL/SPL_f.stub', 'spl_classes' => 'SPL/SPL_f.stub', 'spl_object_hash' => 'SPL/SPL_f.stub', 'spl_object_id' => 'SPL/SPL_f.stub', 'split' => 'regex/ereg.stub', 'spliti' => 'regex/ereg.stub', 'sprintf' => 'standard/standard_2.stub', 'sql_regcase' => 'regex/ereg.stub', 'sqlite_array_query' => 'SQLite/SQLite.stub', 'sqlite_busy_timeout' => 'SQLite/SQLite.stub', 'sqlite_changes' => 'SQLite/SQLite.stub', 'sqlite_close' => 'SQLite/SQLite.stub', 'sqlite_column' => 'SQLite/SQLite.stub', 'sqlite_create_aggregate' => 'SQLite/SQLite.stub', 'sqlite_create_function' => 'SQLite/SQLite.stub', 'sqlite_current' => 'SQLite/SQLite.stub', 'sqlite_error_string' => 'SQLite/SQLite.stub', 'sqlite_escape_string' => 'SQLite/SQLite.stub', 'sqlite_exec' => 'SQLite/SQLite.stub', 'sqlite_factory' => 'SQLite/SQLite.stub', 'sqlite_fetch_all' => 'SQLite/SQLite.stub', 'sqlite_fetch_array' => 'SQLite/SQLite.stub', 'sqlite_fetch_column_types' => 'SQLite/SQLite.stub', 'sqlite_fetch_object' => 'SQLite/SQLite.stub', 'sqlite_fetch_single' => 'SQLite/SQLite.stub', 'sqlite_fetch_string' => 'SQLite/SQLite.stub', 'sqlite_field_name' => 'SQLite/SQLite.stub', 'sqlite_has_more' => 'SQLite/SQLite.stub', 'sqlite_has_prev' => 'SQLite/SQLite.stub', 'sqlite_last_error' => 'SQLite/SQLite.stub', 'sqlite_last_insert_rowid' => 'SQLite/SQLite.stub', 'sqlite_libencoding' => 'SQLite/SQLite.stub', 'sqlite_libversion' => 'SQLite/SQLite.stub', 'sqlite_next' => 'SQLite/SQLite.stub', 'sqlite_num_fields' => 'SQLite/SQLite.stub', 'sqlite_num_rows' => 'SQLite/SQLite.stub', 'sqlite_open' => 'SQLite/SQLite.stub', 'sqlite_popen' => 'SQLite/SQLite.stub', 'sqlite_prev' => 'SQLite/SQLite.stub', 'sqlite_query' => 'SQLite/SQLite.stub', 'sqlite_rewind' => 'SQLite/SQLite.stub', 'sqlite_seek' => 'SQLite/SQLite.stub', 'sqlite_single_query' => 'SQLite/SQLite.stub', 'sqlite_udf_decode_binary' => 'SQLite/SQLite.stub', 'sqlite_udf_encode_binary' => 'SQLite/SQLite.stub', 'sqlite_unbuffered_query' => 'SQLite/SQLite.stub', 'sqlite_valid' => 'SQLite/SQLite.stub', 'sqlsrv_begin_transaction' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_cancel' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_client_info' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_close' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_commit' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_configure' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_connect' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_errors' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_execute' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_fetch' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_fetch_array' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_fetch_object' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_field_metadata' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_free_stmt' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_get_config' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_get_field' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_has_rows' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_next_result' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_num_fields' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_num_rows' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_prepare' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_query' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_rollback' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_rows_affected' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_send_stream_data' => 'sqlsrv/sqlsrv.stub', 'sqlsrv_server_info' => 'sqlsrv/sqlsrv.stub', 'sqrt' => 'standard/standard_3.stub', 'srand' => 'random/random.stub', 'sscanf' => 'standard/standard_2.stub', 'ssh2_auth_agent' => 'ssh2/ssh2.stub', 'ssh2_auth_hostbased_file' => 'ssh2/ssh2.stub', 'ssh2_auth_none' => 'ssh2/ssh2.stub', 'ssh2_auth_password' => 'ssh2/ssh2.stub', 'ssh2_auth_pubkey_file' => 'ssh2/ssh2.stub', 'ssh2_connect' => 'ssh2/ssh2.stub', 'ssh2_disconnect' => 'ssh2/ssh2.stub', 'ssh2_exec' => 'ssh2/ssh2.stub', 'ssh2_fetch_stream' => 'ssh2/ssh2.stub', 'ssh2_fingerprint' => 'ssh2/ssh2.stub', 'ssh2_forward_accept' => 'ssh2/ssh2.stub', 'ssh2_forward_listen' => 'ssh2/ssh2.stub', 'ssh2_methods_negotiated' => 'ssh2/ssh2.stub', 'ssh2_poll' => 'ssh2/ssh2.stub', 'ssh2_publickey_add' => 'ssh2/ssh2.stub', 'ssh2_publickey_init' => 'ssh2/ssh2.stub', 'ssh2_publickey_list' => 'ssh2/ssh2.stub', 'ssh2_publickey_remove' => 'ssh2/ssh2.stub', 'ssh2_scp_recv' => 'ssh2/ssh2.stub', 'ssh2_scp_send' => 'ssh2/ssh2.stub', 'ssh2_send_eof' => 'ssh2/ssh2.stub', 'ssh2_sftp' => 'ssh2/ssh2.stub', 'ssh2_sftp_chmod' => 'ssh2/ssh2.stub', 'ssh2_sftp_lstat' => 'ssh2/ssh2.stub', 'ssh2_sftp_mkdir' => 'ssh2/ssh2.stub', 'ssh2_sftp_readlink' => 'ssh2/ssh2.stub', 'ssh2_sftp_realpath' => 'ssh2/ssh2.stub', 'ssh2_sftp_rename' => 'ssh2/ssh2.stub', 'ssh2_sftp_rmdir' => 'ssh2/ssh2.stub', 'ssh2_sftp_stat' => 'ssh2/ssh2.stub', 'ssh2_sftp_symlink' => 'ssh2/ssh2.stub', 'ssh2_sftp_unlink' => 'ssh2/ssh2.stub', 'ssh2_shell' => 'ssh2/ssh2.stub', 'ssh2_tunnel' => 'ssh2/ssh2.stub', 'stat' => 'standard/standard_7.stub', 'stats_absolute_deviation' => 'stats/stats.stub', 'stats_cdf_beta' => 'stats/stats.stub', 'stats_cdf_binomial' => 'stats/stats.stub', 'stats_cdf_cauchy' => 'stats/stats.stub', 'stats_cdf_chisquare' => 'stats/stats.stub', 'stats_cdf_exponential' => 'stats/stats.stub', 'stats_cdf_f' => 'stats/stats.stub', 'stats_cdf_gamma' => 'stats/stats.stub', 'stats_cdf_laplace' => 'stats/stats.stub', 'stats_cdf_logistic' => 'stats/stats.stub', 'stats_cdf_negative_binomial' => 'stats/stats.stub', 'stats_cdf_noncentral_chisquare' => 'stats/stats.stub', 'stats_cdf_noncentral_f' => 'stats/stats.stub', 'stats_cdf_noncentral_t' => 'stats/stats.stub', 'stats_cdf_normal' => 'stats/stats.stub', 'stats_cdf_poisson' => 'stats/stats.stub', 'stats_cdf_t' => 'stats/stats.stub', 'stats_cdf_uniform' => 'stats/stats.stub', 'stats_cdf_weibull' => 'stats/stats.stub', 'stats_covariance' => 'stats/stats.stub', 'stats_dens_beta' => 'stats/stats.stub', 'stats_dens_cauchy' => 'stats/stats.stub', 'stats_dens_chisquare' => 'stats/stats.stub', 'stats_dens_exponential' => 'stats/stats.stub', 'stats_dens_f' => 'stats/stats.stub', 'stats_dens_gamma' => 'stats/stats.stub', 'stats_dens_laplace' => 'stats/stats.stub', 'stats_dens_logistic' => 'stats/stats.stub', 'stats_dens_normal' => 'stats/stats.stub', 'stats_dens_pmf_binomial' => 'stats/stats.stub', 'stats_dens_pmf_hypergeometric' => 'stats/stats.stub', 'stats_dens_pmf_negative_binomial' => 'stats/stats.stub', 'stats_dens_pmf_poisson' => 'stats/stats.stub', 'stats_dens_t' => 'stats/stats.stub', 'stats_dens_uniform' => 'stats/stats.stub', 'stats_dens_weibull' => 'stats/stats.stub', 'stats_harmonic_mean' => 'stats/stats.stub', 'stats_kurtosis' => 'stats/stats.stub', 'stats_rand_gen_beta' => 'stats/stats.stub', 'stats_rand_gen_chisquare' => 'stats/stats.stub', 'stats_rand_gen_exponential' => 'stats/stats.stub', 'stats_rand_gen_f' => 'stats/stats.stub', 'stats_rand_gen_funiform' => 'stats/stats.stub', 'stats_rand_gen_gamma' => 'stats/stats.stub', 'stats_rand_gen_ibinomial' => 'stats/stats.stub', 'stats_rand_gen_ibinomial_negative' => 'stats/stats.stub', 'stats_rand_gen_int' => 'stats/stats.stub', 'stats_rand_gen_ipoisson' => 'stats/stats.stub', 'stats_rand_gen_iuniform' => 'stats/stats.stub', 'stats_rand_gen_noncentral_f' => 'stats/stats.stub', 'stats_rand_gen_noncentral_t' => 'stats/stats.stub', 'stats_rand_gen_normal' => 'stats/stats.stub', 'stats_rand_gen_t' => 'stats/stats.stub', 'stats_rand_get_seeds' => 'stats/stats.stub', 'stats_rand_phrase_to_seeds' => 'stats/stats.stub', 'stats_rand_ranf' => 'stats/stats.stub', 'stats_rand_setall' => 'stats/stats.stub', 'stats_skew' => 'stats/stats.stub', 'stats_standard_deviation' => 'stats/stats.stub', 'stats_stat_binomial_coef' => 'stats/stats.stub', 'stats_stat_correlation' => 'stats/stats.stub', 'stats_stat_factorial' => 'stats/stats.stub', 'stats_stat_independent_t' => 'stats/stats.stub', 'stats_stat_innerproduct' => 'stats/stats.stub', 'stats_stat_paired_t' => 'stats/stats.stub', 'stats_stat_percentile' => 'stats/stats.stub', 'stats_stat_powersum' => 'stats/stats.stub', 'stats_variance' => 'stats/stats.stub', 'stomp_abort' => 'stomp/stomp.stub', 'stomp_ack' => 'stomp/stomp.stub', 'stomp_begin' => 'stomp/stomp.stub', 'stomp_close' => 'stomp/stomp.stub', 'stomp_commit' => 'stomp/stomp.stub', 'stomp_connect' => 'stomp/stomp.stub', 'stomp_error' => 'stomp/stomp.stub', 'stomp_get_session_id' => 'stomp/stomp.stub', 'stomp_get_timeout' => 'stomp/stomp.stub', 'stomp_has_frame' => 'stomp/stomp.stub', 'stomp_read_frame' => 'stomp/stomp.stub', 'stomp_send' => 'stomp/stomp.stub', 'stomp_set_timeout' => 'stomp/stomp.stub', 'stomp_subscribe' => 'stomp/stomp.stub', 'stomp_unsubscribe' => 'stomp/stomp.stub', 'stomp_version' => 'stomp/stomp.stub', 'str_contains' => 'Core/Core.stub', 'str_decrement' => 'Core/Core.stub', 'str_ends_with' => 'Core/Core.stub', 'str_getcsv' => 'standard/standard_2.stub', 'str_increment' => 'Core/Core.stub', 'str_ireplace' => 'standard/standard_1.stub', 'str_pad' => 'standard/standard_2.stub', 'str_repeat' => 'standard/standard_1.stub', 'str_replace' => 'standard/standard_1.stub', 'str_rot13' => 'standard/standard_9.stub', 'str_shuffle' => 'standard/standard_1.stub', 'str_split' => 'standard/standard_1.stub', 'str_starts_with' => 'Core/Core.stub', 'str_word_count' => 'standard/standard_1.stub', 'strcasecmp' => 'Core/Core.stub', 'strchr' => 'standard/standard_2.stub', 'strcmp' => 'Core/Core.stub', 'strcoll' => 'standard/standard_1.stub', 'strcspn' => 'standard/standard_0.stub', 'stream_bucket_append' => 'standard/standard_9.stub', 'stream_bucket_make_writeable' => 'standard/standard_9.stub', 'stream_bucket_new' => 'standard/standard_9.stub', 'stream_bucket_prepend' => 'standard/standard_9.stub', 'stream_context_create' => 'standard/standard_6.stub', 'stream_context_get_default' => 'standard/standard_6.stub', 'stream_context_get_options' => 'standard/standard_6.stub', 'stream_context_get_params' => 'standard/standard_6.stub', 'stream_context_set_default' => 'standard/standard_6.stub', 'stream_context_set_option' => 'standard/standard_6.stub', 'stream_context_set_options' => 'standard/standard_6.stub', 'stream_context_set_params' => 'standard/standard_6.stub', 'stream_copy_to_stream' => 'standard/standard_6.stub', 'stream_filter_append' => 'standard/standard_6.stub', 'stream_filter_prepend' => 'standard/standard_6.stub', 'stream_filter_register' => 'standard/standard_9.stub', 'stream_filter_remove' => 'standard/standard_6.stub', 'stream_get_contents' => 'standard/standard_6.stub', 'stream_get_filters' => 'standard/standard_9.stub', 'stream_get_line' => 'standard/standard_6.stub', 'stream_get_meta_data' => 'standard/standard_6.stub', 'stream_get_transports' => 'standard/standard_6.stub', 'stream_get_wrappers' => 'standard/standard_6.stub', 'stream_is_local' => 'standard/standard_6.stub', 'stream_isatty' => 'standard/standard_9.stub', 'stream_register_wrapper' => 'standard/standard_6.stub', 'stream_resolve_include_path' => 'standard/standard_6.stub', 'stream_select' => 'standard/standard_6.stub', 'stream_set_blocking' => 'standard/standard_6.stub', 'stream_set_chunk_size' => 'standard/standard_8.stub', 'stream_set_read_buffer' => 'standard/standard_6.stub', 'stream_set_timeout' => 'standard/standard_6.stub', 'stream_set_write_buffer' => 'standard/standard_6.stub', 'stream_socket_accept' => 'standard/standard_6.stub', 'stream_socket_client' => 'standard/standard_6.stub', 'stream_socket_enable_crypto' => 'standard/standard_6.stub', 'stream_socket_get_name' => 'standard/standard_6.stub', 'stream_socket_pair' => 'standard/standard_6.stub', 'stream_socket_recvfrom' => 'standard/standard_6.stub', 'stream_socket_sendto' => 'standard/standard_6.stub', 'stream_socket_server' => 'standard/standard_6.stub', 'stream_socket_shutdown' => 'standard/standard_6.stub', 'stream_supports_lock' => 'standard/standard_6.stub', 'stream_wrapper_register' => 'standard/standard_6.stub', 'stream_wrapper_restore' => 'standard/standard_6.stub', 'stream_wrapper_unregister' => 'standard/standard_6.stub', 'strftime' => 'date/date.stub', 'strip_tags' => 'standard/standard_1.stub', 'stripcslashes' => 'standard/standard_1.stub', 'stripos' => 'standard/standard_1.stub', 'stripslashes' => 'standard/standard_1.stub', 'stristr' => 'standard/standard_1.stub', 'strlen' => 'Core/Core.stub', 'strnatcasecmp' => 'standard/standard_0.stub', 'strnatcmp' => 'standard/standard_0.stub', 'strncasecmp' => 'Core/Core.stub', 'strncmp' => 'Core/Core.stub', 'strpbrk' => 'standard/standard_1.stub', 'strpos' => 'standard/standard_1.stub', 'strptime' => 'standard/standard_0.stub', 'strrchr' => 'standard/standard_1.stub', 'strrev' => 'standard/standard_1.stub', 'strripos' => 'standard/standard_1.stub', 'strrpos' => 'standard/standard_1.stub', 'strspn' => 'standard/standard_0.stub', 'strstr' => 'standard/standard_1.stub', 'strtok' => 'standard/standard_0.stub', 'strtolower' => 'standard/standard_1.stub', 'strtotime' => 'date/date.stub', 'strtoupper' => 'standard/standard_1.stub', 'strtr' => 'standard/standard_1.stub', 'strval' => 'standard/standard_5.stub', 'substr' => 'standard/standard_1.stub', 'substr_compare' => 'standard/standard_1.stub', 'substr_count' => 'standard/standard_0.stub', 'substr_replace' => 'standard/standard_1.stub', 'suhosin_encrypt_cookie' => 'suhosin/suhosin.stub', 'suhosin_get_raw_cookies' => 'suhosin/suhosin.stub', 'svn_add' => 'svn/svn.stub', 'svn_auth_get_parameter' => 'svn/svn.stub', 'svn_auth_set_parameter' => 'svn/svn.stub', 'svn_blame' => 'svn/svn.stub', 'svn_cat' => 'svn/svn.stub', 'svn_checkout' => 'svn/svn.stub', 'svn_cleanup' => 'svn/svn.stub', 'svn_client_version' => 'svn/svn.stub', 'svn_commit' => 'svn/svn.stub', 'svn_config_ensure' => 'svn/svn.stub', 'svn_copy' => 'svn/svn.stub', 'svn_delete' => 'svn/svn.stub', 'svn_diff' => 'svn/svn.stub', 'svn_export' => 'svn/svn.stub', 'svn_fs_abort_txn' => 'svn/svn.stub', 'svn_fs_apply_text' => 'svn/svn.stub', 'svn_fs_begin_txn2' => 'svn/svn.stub', 'svn_fs_change_node_prop' => 'svn/svn.stub', 'svn_fs_check_path' => 'svn/svn.stub', 'svn_fs_contents_changed' => 'svn/svn.stub', 'svn_fs_copy' => 'svn/svn.stub', 'svn_fs_delete' => 'svn/svn.stub', 'svn_fs_dir_entries' => 'svn/svn.stub', 'svn_fs_file_contents' => 'svn/svn.stub', 'svn_fs_file_length' => 'svn/svn.stub', 'svn_fs_is_dir' => 'svn/svn.stub', 'svn_fs_is_file' => 'svn/svn.stub', 'svn_fs_make_dir' => 'svn/svn.stub', 'svn_fs_make_file' => 'svn/svn.stub', 'svn_fs_node_created_rev' => 'svn/svn.stub', 'svn_fs_node_prop' => 'svn/svn.stub', 'svn_fs_props_changed' => 'svn/svn.stub', 'svn_fs_revision_prop' => 'svn/svn.stub', 'svn_fs_revision_root' => 'svn/svn.stub', 'svn_fs_txn_root' => 'svn/svn.stub', 'svn_fs_youngest_rev' => 'svn/svn.stub', 'svn_import' => 'svn/svn.stub', 'svn_info' => 'svn/svn.stub', 'svn_lock' => 'svn/svn.stub', 'svn_log' => 'svn/svn.stub', 'svn_ls' => 'svn/svn.stub', 'svn_mkdir' => 'svn/svn.stub', 'svn_move' => 'svn/svn.stub', 'svn_propget' => 'svn/svn.stub', 'svn_proplist' => 'svn/svn.stub', 'svn_repos_create' => 'svn/svn.stub', 'svn_repos_fs' => 'svn/svn.stub', 'svn_repos_fs_begin_txn_for_commit' => 'svn/svn.stub', 'svn_repos_fs_commit_txn' => 'svn/svn.stub', 'svn_repos_hotcopy' => 'svn/svn.stub', 'svn_repos_open' => 'svn/svn.stub', 'svn_repos_recover' => 'svn/svn.stub', 'svn_resolved' => 'svn/svn.stub', 'svn_revert' => 'svn/svn.stub', 'svn_status' => 'svn/svn.stub', 'svn_switch' => 'svn/svn.stub', 'svn_unlock' => 'svn/svn.stub', 'svn_update' => 'svn/svn.stub', 'swoole_async_dns_lookup_coro' => 'swoole/functions.stub', 'swoole_async_set' => 'swoole/functions.stub', 'swoole_clear_dns_cache' => 'swoole/functions.stub', 'swoole_clear_error' => 'swoole/functions.stub', 'swoole_client_select' => 'swoole/functions.stub', 'swoole_coroutine_create' => 'swoole/functions.stub', 'swoole_coroutine_defer' => 'swoole/functions.stub', 'swoole_coroutine_socketpair' => 'swoole/functions.stub', 'swoole_cpu_num' => 'swoole/functions.stub', 'swoole_errno' => 'swoole/functions.stub', 'swoole_error_log' => 'swoole/functions.stub', 'swoole_error_log_ex' => 'swoole/functions.stub', 'swoole_event_add' => 'swoole/functions.stub', 'swoole_event_cycle' => 'swoole/functions.stub', 'swoole_event_defer' => 'swoole/functions.stub', 'swoole_event_del' => 'swoole/functions.stub', 'swoole_event_dispatch' => 'swoole/functions.stub', 'swoole_event_exit' => 'swoole/functions.stub', 'swoole_event_isset' => 'swoole/functions.stub', 'swoole_event_set' => 'swoole/functions.stub', 'swoole_event_wait' => 'swoole/functions.stub', 'swoole_event_write' => 'swoole/functions.stub', 'swoole_get_local_ip' => 'swoole/functions.stub', 'swoole_get_local_mac' => 'swoole/functions.stub', 'swoole_get_mime_type' => 'swoole/functions.stub', 'swoole_get_object_by_handle' => 'swoole/functions.stub', 'swoole_get_objects' => 'swoole/functions.stub', 'swoole_get_vm_status' => 'swoole/functions.stub', 'swoole_hashcode' => 'swoole/functions.stub', 'swoole_ignore_error' => 'swoole/functions.stub', 'swoole_internal_call_user_shutdown_begin' => 'swoole/functions.stub', 'swoole_last_error' => 'swoole/functions.stub', 'swoole_mime_type_add' => 'swoole/functions.stub', 'swoole_mime_type_delete' => 'swoole/functions.stub', 'swoole_mime_type_exists' => 'swoole/functions.stub', 'swoole_mime_type_get' => 'swoole/functions.stub', 'swoole_mime_type_list' => 'swoole/functions.stub', 'swoole_mime_type_set' => 'swoole/functions.stub', 'swoole_select' => 'swoole/functions.stub', 'swoole_set_process_name' => 'swoole/functions.stub', 'swoole_strerror' => 'swoole/functions.stub', 'swoole_substr_json_decode' => 'swoole/functions.stub', 'swoole_substr_unserialize' => 'swoole/functions.stub', 'swoole_test_kernel_coroutine' => 'swoole/functions.stub', 'swoole_timer_after' => 'swoole/functions.stub', 'swoole_timer_clear' => 'swoole/functions.stub', 'swoole_timer_clear_all' => 'swoole/functions.stub', 'swoole_timer_exists' => 'swoole/functions.stub', 'swoole_timer_info' => 'swoole/functions.stub', 'swoole_timer_list' => 'swoole/functions.stub', 'swoole_timer_set' => 'swoole/functions.stub', 'swoole_timer_stats' => 'swoole/functions.stub', 'swoole_timer_tick' => 'swoole/functions.stub', 'swoole_version' => 'swoole/functions.stub', 'sybase_affected_rows' => 'sybase/sybase_ct.stub', 'sybase_close' => 'sybase/sybase_ct.stub', 'sybase_connect' => 'sybase/sybase_ct.stub', 'sybase_data_seek' => 'sybase/sybase_ct.stub', 'sybase_deadlock_retry_count' => 'sybase/sybase_ct.stub', 'sybase_fetch_array' => 'sybase/sybase_ct.stub', 'sybase_fetch_assoc' => 'sybase/sybase_ct.stub', 'sybase_fetch_field' => 'sybase/sybase_ct.stub', 'sybase_fetch_object' => 'sybase/sybase_ct.stub', 'sybase_fetch_row' => 'sybase/sybase_ct.stub', 'sybase_field_seek' => 'sybase/sybase_ct.stub', 'sybase_free_result' => 'sybase/sybase_ct.stub', 'sybase_get_last_message' => 'sybase/sybase_ct.stub', 'sybase_min_client_severity' => 'sybase/sybase_ct.stub', 'sybase_min_server_severity' => 'sybase/sybase_ct.stub', 'sybase_num_fields' => 'sybase/sybase_ct.stub', 'sybase_num_rows' => 'sybase/sybase_ct.stub', 'sybase_pconnect' => 'sybase/sybase_ct.stub', 'sybase_query' => 'sybase/sybase_ct.stub', 'sybase_result' => 'sybase/sybase_ct.stub', 'sybase_select_db' => 'sybase/sybase_ct.stub', 'sybase_set_message_handler' => 'sybase/sybase_ct.stub', 'sybase_unbuffered_query' => 'sybase/sybase_ct.stub', 'symlink' => 'standard/standard_2.stub', 'sys_get_temp_dir' => 'standard/standard_9.stub', 'sys_getloadavg' => 'standard/standard_3.stub', 'syslog' => 'standard/standard_8.stub', 'system' => 'standard/standard_2.stub', 'tan' => 'standard/standard_3.stub', 'tanh' => 'standard/standard_3.stub', 'tempnam' => 'standard/standard_5.stub', 'textdomain' => 'gettext/gettext.stub', 'tidy_access_count' => 'tidy/tidy.stub', 'tidy_clean_repair' => 'tidy/tidy.stub', 'tidy_config_count' => 'tidy/tidy.stub', 'tidy_diagnose' => 'tidy/tidy.stub', 'tidy_error_count' => 'tidy/tidy.stub', 'tidy_get_body' => 'tidy/tidy.stub', 'tidy_get_config' => 'tidy/tidy.stub', 'tidy_get_error_buffer' => 'tidy/tidy.stub', 'tidy_get_head' => 'tidy/tidy.stub', 'tidy_get_html' => 'tidy/tidy.stub', 'tidy_get_html_ver' => 'tidy/tidy.stub', 'tidy_get_opt_doc' => 'tidy/tidy.stub', 'tidy_get_output' => 'tidy/tidy.stub', 'tidy_get_release' => 'tidy/tidy.stub', 'tidy_get_root' => 'tidy/tidy.stub', 'tidy_get_status' => 'tidy/tidy.stub', 'tidy_getopt' => 'tidy/tidy.stub', 'tidy_is_xhtml' => 'tidy/tidy.stub', 'tidy_is_xml' => 'tidy/tidy.stub', 'tidy_parse_file' => 'tidy/tidy.stub', 'tidy_parse_string' => 'tidy/tidy.stub', 'tidy_repair_file' => 'tidy/tidy.stub', 'tidy_repair_string' => 'tidy/tidy.stub', 'tidy_warning_count' => 'tidy/tidy.stub', 'time' => 'date/date.stub', 'time_nanosleep' => 'standard/standard_0.stub', 'time_sleep_until' => 'standard/standard_0.stub', 'timezone_abbreviations_list' => 'date/date.stub', 'timezone_identifiers_list' => 'date/date.stub', 'timezone_location_get' => 'date/date.stub', 'timezone_name_from_abbr' => 'date/date.stub', 'timezone_name_get' => 'date/date.stub', 'timezone_offset_get' => 'date/date.stub', 'timezone_open' => 'date/date.stub', 'timezone_transitions_get' => 'date/date.stub', 'timezone_version_get' => 'date/date.stub', 'tmpfile' => 'standard/standard_5.stub', 'token_get_all' => 'tokenizer/tokenizer.stub', 'token_name' => 'tokenizer/tokenizer.stub', 'touch' => 'standard/standard_7.stub', 'trait_exists' => 'Core/Core.stub', 'transliterator_create' => 'intl/intl.stub', 'transliterator_create_from_rules' => 'intl/intl.stub', 'transliterator_create_inverse' => 'intl/intl.stub', 'transliterator_get_error_code' => 'intl/intl.stub', 'transliterator_get_error_message' => 'intl/intl.stub', 'transliterator_list_ids' => 'intl/intl.stub', 'transliterator_transliterate' => 'intl/intl.stub', 'trigger_error' => 'Core/Core.stub', 'trim' => 'standard/standard_1.stub', 'uasort' => 'standard/standard_8.stub', 'ucfirst' => 'standard/standard_1.stub', 'ucwords' => 'standard/standard_1.stub', 'uksort' => 'standard/standard_8.stub', 'umask' => 'standard/standard_5.stub', 'uniqid' => 'standard/standard_3.stub', 'unixtojd' => 'calendar/calendar.stub', 'unlink' => 'standard/standard_2.stub', 'unpack' => 'standard/standard_7.stub', 'unregister_event_handler' => 'zend/zend.stub', 'unregister_tick_function' => 'standard/standard_4.stub', 'unserialize' => 'standard/standard_4.stub', 'uopz_add_function' => 'uopz/uopz.stub', 'uopz_allow_exit' => 'uopz/uopz.stub', 'uopz_call_user_func' => 'uopz/uopz.stub', 'uopz_call_user_func_array' => 'uopz/uopz.stub', 'uopz_del_function' => 'uopz/uopz.stub', 'uopz_extend' => 'uopz/uopz.stub', 'uopz_flags' => 'uopz/uopz.stub', 'uopz_get_exit_status' => 'uopz/uopz.stub', 'uopz_get_hook' => 'uopz/uopz.stub', 'uopz_get_mock' => 'uopz/uopz.stub', 'uopz_get_property' => 'uopz/uopz.stub', 'uopz_get_return' => 'uopz/uopz.stub', 'uopz_get_static' => 'uopz/uopz.stub', 'uopz_implement' => 'uopz/uopz.stub', 'uopz_redefine' => 'uopz/uopz.stub', 'uopz_set_hook' => 'uopz/uopz.stub', 'uopz_set_mock' => 'uopz/uopz.stub', 'uopz_set_property' => 'uopz/uopz.stub', 'uopz_set_return' => 'uopz/uopz.stub', 'uopz_set_static' => 'uopz/uopz.stub', 'uopz_undefine' => 'uopz/uopz.stub', 'uopz_unset_hook' => 'uopz/uopz.stub', 'uopz_unset_mock' => 'uopz/uopz.stub', 'uopz_unset_return' => 'uopz/uopz.stub', 'uploadprogress_get_contents' => 'uploadprogress/uploadprogress.stub', 'uploadprogress_get_info' => 'uploadprogress/uploadprogress.stub', 'urldecode' => 'standard/standard_2.stub', 'urlencode' => 'standard/standard_2.stub', 'use_soap_error_handler' => 'soap/soap.stub', 'user_error' => 'Core/Core.stub', 'usleep' => 'standard/standard_0.stub', 'usort' => 'standard/standard_8.stub', 'utf8_decode' => 'standard/basic.stub', 'utf8_encode' => 'standard/basic.stub', 'uuid_compare' => 'uuid/uuid_c.stub', 'uuid_create' => 'uuid/uuid_c.stub', 'uuid_generate_md5' => 'uuid/uuid_c.stub', 'uuid_generate_sha1' => 'uuid/uuid_c.stub', 'uuid_is_null' => 'uuid/uuid_c.stub', 'uuid_is_valid' => 'uuid/uuid_c.stub', 'uuid_mac' => 'uuid/uuid_c.stub', 'uuid_parse' => 'uuid/uuid_c.stub', 'uuid_time' => 'uuid/uuid_c.stub', 'uuid_type' => 'uuid/uuid_c.stub', 'uuid_unparse' => 'uuid/uuid_c.stub', 'uuid_variant' => 'uuid/uuid_c.stub', 'uv_accept' => 'uv/uv_functions.stub', 'uv_async_init' => 'uv/uv_functions.stub', 'uv_async_send' => 'uv/uv_functions.stub', 'uv_chdir' => 'uv/uv_functions.stub', 'uv_check_init' => 'uv/uv_functions.stub', 'uv_check_start' => 'uv/uv_functions.stub', 'uv_check_stop' => 'uv/uv_functions.stub', 'uv_close' => 'uv/uv_functions.stub', 'uv_cpu_info' => 'uv/uv_functions.stub', 'uv_default_loop' => 'uv/uv_functions.stub', 'uv_err_name' => 'uv/uv_functions.stub', 'uv_exepath' => 'uv/uv_functions.stub', 'uv_fs_chmod' => 'uv/uv_functions.stub', 'uv_fs_chown' => 'uv/uv_functions.stub', 'uv_fs_close' => 'uv/uv_functions.stub', 'uv_fs_event_init' => 'uv/uv_functions.stub', 'uv_fs_fchmod' => 'uv/uv_functions.stub', 'uv_fs_fchown' => 'uv/uv_functions.stub', 'uv_fs_fdatasync' => 'uv/uv_functions.stub', 'uv_fs_fstat' => 'uv/uv_functions.stub', 'uv_fs_fsync' => 'uv/uv_functions.stub', 'uv_fs_ftruncate' => 'uv/uv_functions.stub', 'uv_fs_futime' => 'uv/uv_functions.stub', 'uv_fs_link' => 'uv/uv_functions.stub', 'uv_fs_lstat' => 'uv/uv_functions.stub', 'uv_fs_mkdir' => 'uv/uv_functions.stub', 'uv_fs_open' => 'uv/uv_functions.stub', 'uv_fs_poll_init' => 'uv/uv_functions.stub', 'uv_fs_poll_start' => 'uv/uv_functions.stub', 'uv_fs_poll_stop' => 'uv/uv_functions.stub', 'uv_fs_read' => 'uv/uv_functions.stub', 'uv_fs_readdir' => 'uv/uv_functions.stub', 'uv_fs_readlink' => 'uv/uv_functions.stub', 'uv_fs_rename' => 'uv/uv_functions.stub', 'uv_fs_rmdir' => 'uv/uv_functions.stub', 'uv_fs_sendfile' => 'uv/uv_functions.stub', 'uv_fs_stat' => 'uv/uv_functions.stub', 'uv_fs_symlink' => 'uv/uv_functions.stub', 'uv_fs_unlink' => 'uv/uv_functions.stub', 'uv_fs_utime' => 'uv/uv_functions.stub', 'uv_fs_write' => 'uv/uv_functions.stub', 'uv_get_free_memory' => 'uv/uv_functions.stub', 'uv_get_total_memory' => 'uv/uv_functions.stub', 'uv_getaddrinfo' => 'uv/uv_functions.stub', 'uv_guess_handle' => 'uv/uv_functions.stub', 'uv_hrtime' => 'uv/uv_functions.stub', 'uv_idle_init' => 'uv/uv_functions.stub', 'uv_idle_start' => 'uv/uv_functions.stub', 'uv_idle_stop' => 'uv/uv_functions.stub', 'uv_interface_addresses' => 'uv/uv_functions.stub', 'uv_ip4_addr' => 'uv/uv_functions.stub', 'uv_ip4_name' => 'uv/uv_functions.stub', 'uv_ip6_addr' => 'uv/uv_functions.stub', 'uv_ip6_name' => 'uv/uv_functions.stub', 'uv_is_active' => 'uv/uv_functions.stub', 'uv_is_closing' => 'uv/uv_functions.stub', 'uv_is_readable' => 'uv/uv_functions.stub', 'uv_is_writable' => 'uv/uv_functions.stub', 'uv_kill' => 'uv/uv_functions.stub', 'uv_last_error' => 'uv/uv_functions.stub', 'uv_listen' => 'uv/uv_functions.stub', 'uv_loadavg' => 'uv/uv_functions.stub', 'uv_loop_delete' => 'uv/uv_functions.stub', 'uv_loop_new' => 'uv/uv_functions.stub', 'uv_mutex_init' => 'uv/uv_functions.stub', 'uv_mutex_lock' => 'uv/uv_functions.stub', 'uv_mutex_trylock' => 'uv/uv_functions.stub', 'uv_now' => 'uv/uv_functions.stub', 'uv_pipe_bind' => 'uv/uv_functions.stub', 'uv_pipe_connect' => 'uv/uv_functions.stub', 'uv_pipe_init' => 'uv/uv_functions.stub', 'uv_pipe_open' => 'uv/uv_functions.stub', 'uv_pipe_pending_instances' => 'uv/uv_functions.stub', 'uv_poll_init' => 'uv/uv_functions.stub', 'uv_poll_start' => 'uv/uv_functions.stub', 'uv_poll_stop' => 'uv/uv_functions.stub', 'uv_prepare_init' => 'uv/uv_functions.stub', 'uv_prepare_start' => 'uv/uv_functions.stub', 'uv_prepare_stop' => 'uv/uv_functions.stub', 'uv_process_kill' => 'uv/uv_functions.stub', 'uv_queue_work' => 'uv/uv_functions.stub', 'uv_read_start' => 'uv/uv_functions.stub', 'uv_read_stop' => 'uv/uv_functions.stub', 'uv_ref' => 'uv/uv_functions.stub', 'uv_resident_set_memory' => 'uv/uv_functions.stub', 'uv_run' => 'uv/uv_functions.stub', 'uv_run_once' => 'uv/uv_functions.stub', 'uv_rwlock_init' => 'uv/uv_functions.stub', 'uv_rwlock_rdlock' => 'uv/uv_functions.stub', 'uv_rwlock_rdunlock' => 'uv/uv_functions.stub', 'uv_rwlock_tryrdlock' => 'uv/uv_functions.stub', 'uv_rwlock_trywrlock' => 'uv/uv_functions.stub', 'uv_rwlock_wrlock' => 'uv/uv_functions.stub', 'uv_rwlock_wrunlock' => 'uv/uv_functions.stub', 'uv_sem_init' => 'uv/uv_functions.stub', 'uv_sem_post' => 'uv/uv_functions.stub', 'uv_sem_trywait' => 'uv/uv_functions.stub', 'uv_sem_wait' => 'uv/uv_functions.stub', 'uv_shutdown' => 'uv/uv_functions.stub', 'uv_signal_stop' => 'uv/uv_functions.stub', 'uv_spawn' => 'uv/uv_functions.stub', 'uv_stdio_new' => 'uv/uv_functions.stub', 'uv_stop' => 'uv/uv_functions.stub', 'uv_strerror' => 'uv/uv_functions.stub', 'uv_tcp_bind' => 'uv/uv_functions.stub', 'uv_tcp_bind6' => 'uv/uv_functions.stub', 'uv_tcp_connect' => 'uv/uv_functions.stub', 'uv_tcp_connect6' => 'uv/uv_functions.stub', 'uv_tcp_getpeername' => 'uv/uv_functions.stub', 'uv_tcp_getsockname' => 'uv/uv_functions.stub', 'uv_tcp_init' => 'uv/uv_functions.stub', 'uv_tcp_nodelay' => 'uv/uv_functions.stub', 'uv_timer_again' => 'uv/uv_functions.stub', 'uv_timer_get_repeat' => 'uv/uv_functions.stub', 'uv_timer_init' => 'uv/uv_functions.stub', 'uv_timer_set_repeat' => 'uv/uv_functions.stub', 'uv_timer_start' => 'uv/uv_functions.stub', 'uv_timer_stop' => 'uv/uv_functions.stub', 'uv_tty_get_winsize' => 'uv/uv_functions.stub', 'uv_tty_init' => 'uv/uv_functions.stub', 'uv_tty_reset_mode' => 'uv/uv_functions.stub', 'uv_tty_set_mode' => 'uv/uv_functions.stub', 'uv_udp_bind' => 'uv/uv_functions.stub', 'uv_udp_bind6' => 'uv/uv_functions.stub', 'uv_udp_getsockname' => 'uv/uv_functions.stub', 'uv_udp_init' => 'uv/uv_functions.stub', 'uv_udp_recv_start' => 'uv/uv_functions.stub', 'uv_udp_recv_stop' => 'uv/uv_functions.stub', 'uv_udp_send' => 'uv/uv_functions.stub', 'uv_udp_send6' => 'uv/uv_functions.stub', 'uv_udp_set_broadcast' => 'uv/uv_functions.stub', 'uv_udp_set_membership' => 'uv/uv_functions.stub', 'uv_udp_set_multicast_loop' => 'uv/uv_functions.stub', 'uv_udp_set_multicast_ttl' => 'uv/uv_functions.stub', 'uv_unref' => 'uv/uv_functions.stub', 'uv_update_time' => 'uv/uv_functions.stub', 'uv_uptime' => 'uv/uv_functions.stub', 'uv_walk' => 'uv/uv_functions.stub', 'uv_write' => 'uv/uv_functions.stub', 'uv_write2' => 'uv/uv_functions.stub', 'var_dump' => 'standard/standard_4.stub', 'var_export' => 'standard/standard_4.stub', 'variant_abs' => 'com_dotnet/com_dotnet.stub', 'variant_add' => 'com_dotnet/com_dotnet.stub', 'variant_and' => 'com_dotnet/com_dotnet.stub', 'variant_cast' => 'com_dotnet/com_dotnet.stub', 'variant_cat' => 'com_dotnet/com_dotnet.stub', 'variant_cmp' => 'com_dotnet/com_dotnet.stub', 'variant_date_from_timestamp' => 'com_dotnet/com_dotnet.stub', 'variant_date_to_timestamp' => 'com_dotnet/com_dotnet.stub', 'variant_div' => 'com_dotnet/com_dotnet.stub', 'variant_eqv' => 'com_dotnet/com_dotnet.stub', 'variant_fix' => 'com_dotnet/com_dotnet.stub', 'variant_get_type' => 'com_dotnet/com_dotnet.stub', 'variant_idiv' => 'com_dotnet/com_dotnet.stub', 'variant_imp' => 'com_dotnet/com_dotnet.stub', 'variant_int' => 'com_dotnet/com_dotnet.stub', 'variant_mod' => 'com_dotnet/com_dotnet.stub', 'variant_mul' => 'com_dotnet/com_dotnet.stub', 'variant_neg' => 'com_dotnet/com_dotnet.stub', 'variant_not' => 'com_dotnet/com_dotnet.stub', 'variant_or' => 'com_dotnet/com_dotnet.stub', 'variant_pow' => 'com_dotnet/com_dotnet.stub', 'variant_round' => 'com_dotnet/com_dotnet.stub', 'variant_set' => 'com_dotnet/com_dotnet.stub', 'variant_set_type' => 'com_dotnet/com_dotnet.stub', 'variant_sub' => 'com_dotnet/com_dotnet.stub', 'variant_xor' => 'com_dotnet/com_dotnet.stub', 'version_compare' => 'standard/standard_9.stub', 'vfprintf' => 'standard/standard_2.stub', 'virtual' => 'apache/apache.stub', 'vprintf' => 'standard/standard_2.stub', 'vsprintf' => 'standard/standard_2.stub', 'wb_call_function' => 'winbinder/winbinder.stub', 'wb_create_font' => 'winbinder/winbinder.stub', 'wb_create_image' => 'winbinder/winbinder.stub', 'wb_create_mask' => 'winbinder/winbinder.stub', 'wb_create_timer' => 'winbinder/winbinder.stub', 'wb_create_window' => 'winbinder/winbinder.stub', 'wb_delete_items' => 'winbinder/winbinder.stub', 'wb_destroy_control' => 'winbinder/winbinder.stub', 'wb_destroy_font' => 'winbinder/winbinder.stub', 'wb_destroy_image' => 'winbinder/winbinder.stub', 'wb_destroy_timer' => 'winbinder/winbinder.stub', 'wb_destroy_window' => 'winbinder/winbinder.stub', 'wb_draw_ellipse' => 'winbinder/winbinder.stub', 'wb_draw_image' => 'winbinder/winbinder.stub', 'wb_draw_line' => 'winbinder/winbinder.stub', 'wb_draw_point' => 'winbinder/winbinder.stub', 'wb_draw_rect' => 'winbinder/winbinder.stub', 'wb_draw_text' => 'winbinder/winbinder.stub', 'wb_exec' => 'winbinder/winbinder.stub', 'wb_find_file' => 'winbinder/winbinder.stub', 'wb_get_address' => 'winbinder/winbinder.stub', 'wb_get_class' => 'winbinder/winbinder.stub', 'wb_get_control' => 'winbinder/winbinder.stub', 'wb_get_enabled' => 'winbinder/winbinder.stub', 'wb_get_enum_callback' => 'winbinder/winbinder.stub', 'wb_get_focus' => 'winbinder/winbinder.stub', 'wb_get_function_address' => 'winbinder/winbinder.stub', 'wb_get_hook_callback' => 'winbinder/winbinder.stub', 'wb_get_id' => 'winbinder/winbinder.stub', 'wb_get_image_data' => 'winbinder/winbinder.stub', 'wb_get_instance' => 'winbinder/winbinder.stub', 'wb_get_item_count' => 'winbinder/winbinder.stub', 'wb_get_item_list' => 'winbinder/winbinder.stub', 'wb_get_level' => 'winbinder/winbinder.stub', 'wb_get_midi_callback' => 'winbinder/winbinder.stub', 'wb_get_parent' => 'winbinder/winbinder.stub', 'wb_get_pixel' => 'winbinder/winbinder.stub', 'wb_get_position' => 'winbinder/winbinder.stub', 'wb_get_registry_key' => 'winbinder/winbinder.stub', 'wb_get_selected' => 'winbinder/winbinder.stub', 'wb_get_size' => 'winbinder/winbinder.stub', 'wb_get_state' => 'winbinder/winbinder.stub', 'wb_get_system_info' => 'winbinder/winbinder.stub', 'wb_get_value' => 'winbinder/winbinder.stub', 'wb_get_visible' => 'winbinder/winbinder.stub', 'wb_load_image' => 'winbinder/winbinder.stub', 'wb_load_library' => 'winbinder/winbinder.stub', 'wb_main_loop' => 'winbinder/winbinder.stub', 'wb_message_box' => 'winbinder/winbinder.stub', 'wb_peek' => 'winbinder/winbinder.stub', 'wb_play_sound' => 'winbinder/winbinder.stub', 'wb_poke' => 'winbinder/winbinder.stub', 'wb_refresh' => 'winbinder/winbinder.stub', 'wb_release_library' => 'winbinder/winbinder.stub', 'wb_save_image' => 'winbinder/winbinder.stub', 'wb_send_message' => 'winbinder/winbinder.stub', 'wb_set_area' => 'winbinder/winbinder.stub', 'wb_set_cursor' => 'winbinder/winbinder.stub', 'wb_set_enabled' => 'winbinder/winbinder.stub', 'wb_set_focus' => 'winbinder/winbinder.stub', 'wb_set_font' => 'winbinder/winbinder.stub', 'wb_set_handler' => 'winbinder/winbinder.stub', 'wb_set_image' => 'winbinder/winbinder.stub', 'wb_set_item_image' => 'winbinder/winbinder.stub', 'wb_set_location' => 'winbinder/winbinder.stub', 'wb_set_position' => 'winbinder/winbinder.stub', 'wb_set_range' => 'winbinder/winbinder.stub', 'wb_set_registry_key' => 'winbinder/winbinder.stub', 'wb_set_size' => 'winbinder/winbinder.stub', 'wb_set_state' => 'winbinder/winbinder.stub', 'wb_set_style' => 'winbinder/winbinder.stub', 'wb_set_visible' => 'winbinder/winbinder.stub', 'wb_sort' => 'winbinder/winbinder.stub', 'wb_stop_sound' => 'winbinder/winbinder.stub', 'wb_sys_dlg_color' => 'winbinder/winbinder.stub', 'wb_sys_dlg_path' => 'winbinder/winbinder.stub', 'wb_wait' => 'winbinder/winbinder.stub', 'wbtemp_clear_listview_columns' => 'winbinder/winbinder.stub', 'wbtemp_create_control' => 'winbinder/winbinder.stub', 'wbtemp_create_item' => 'winbinder/winbinder.stub', 'wbtemp_create_listview_column' => 'winbinder/winbinder.stub', 'wbtemp_create_listview_item' => 'winbinder/winbinder.stub', 'wbtemp_create_menu' => 'winbinder/winbinder.stub', 'wbtemp_create_statusbar_items' => 'winbinder/winbinder.stub', 'wbtemp_create_toolbar' => 'winbinder/winbinder.stub', 'wbtemp_create_treeview_item' => 'winbinder/winbinder.stub', 'wbtemp_get_listview_columns' => 'winbinder/winbinder.stub', 'wbtemp_get_listview_item_checked' => 'winbinder/winbinder.stub', 'wbtemp_get_listview_text' => 'winbinder/winbinder.stub', 'wbtemp_get_menu_item_checked' => 'winbinder/winbinder.stub', 'wbtemp_get_text' => 'winbinder/winbinder.stub', 'wbtemp_get_treeview_item_text' => 'winbinder/winbinder.stub', 'wbtemp_select_all_listview_items' => 'winbinder/winbinder.stub', 'wbtemp_select_listview_item' => 'winbinder/winbinder.stub', 'wbtemp_select_tab' => 'winbinder/winbinder.stub', 'wbtemp_set_accel_table' => 'winbinder/winbinder.stub', 'wbtemp_set_listview_item_checked' => 'winbinder/winbinder.stub', 'wbtemp_set_listview_item_text' => 'winbinder/winbinder.stub', 'wbtemp_set_menu_item_checked' => 'winbinder/winbinder.stub', 'wbtemp_set_menu_item_image' => 'winbinder/winbinder.stub', 'wbtemp_set_menu_item_selected' => 'winbinder/winbinder.stub', 'wbtemp_set_text' => 'winbinder/winbinder.stub', 'wbtemp_set_treeview_item_selected' => 'winbinder/winbinder.stub', 'wbtemp_set_treeview_item_text' => 'winbinder/winbinder.stub', 'wbtemp_set_treeview_item_value' => 'winbinder/winbinder.stub', 'wbtemp_set_value' => 'winbinder/winbinder.stub', 'wbtemp_sys_dlg_open' => 'winbinder/winbinder.stub', 'wbtemp_sys_dlg_save' => 'winbinder/winbinder.stub', 'wddx_add_vars' => 'wddx/wddx.stub', 'wddx_deserialize' => 'wddx/wddx.stub', 'wddx_packet_end' => 'wddx/wddx.stub', 'wddx_packet_start' => 'wddx/wddx.stub', 'wddx_serialize_value' => 'wddx/wddx.stub', 'wddx_serialize_vars' => 'wddx/wddx.stub', 'win32_continue_service' => 'win32service/win32service.stub', 'win32_create_service' => 'win32service/win32service.stub', 'win32_delete_service' => 'win32service/win32service.stub', 'win32_get_last_control_message' => 'win32service/win32service.stub', 'win32_pause_service' => 'win32service/win32service.stub', 'win32_query_service_status' => 'win32service/win32service.stub', 'win32_set_service_status' => 'win32service/win32service.stub', 'win32_start_service' => 'win32service/win32service.stub', 'win32_start_service_ctrl_dispatcher' => 'win32service/win32service.stub', 'win32_stop_service' => 'win32service/win32service.stub', 'wincache_fcache_fileinfo' => 'wincache/wincache.stub', 'wincache_fcache_meminfo' => 'wincache/wincache.stub', 'wincache_lock' => 'wincache/wincache.stub', 'wincache_ocache_fileinfo' => 'wincache/wincache.stub', 'wincache_ocache_meminfo' => 'wincache/wincache.stub', 'wincache_refresh_if_changed' => 'wincache/wincache.stub', 'wincache_rplist_fileinfo' => 'wincache/wincache.stub', 'wincache_rplist_meminfo' => 'wincache/wincache.stub', 'wincache_scache_info' => 'wincache/wincache.stub', 'wincache_scache_meminfo' => 'wincache/wincache.stub', 'wincache_ucache_add' => 'wincache/wincache.stub', 'wincache_ucache_cas' => 'wincache/wincache.stub', 'wincache_ucache_clear' => 'wincache/wincache.stub', 'wincache_ucache_dec' => 'wincache/wincache.stub', 'wincache_ucache_delete' => 'wincache/wincache.stub', 'wincache_ucache_exists' => 'wincache/wincache.stub', 'wincache_ucache_get' => 'wincache/wincache.stub', 'wincache_ucache_inc' => 'wincache/wincache.stub', 'wincache_ucache_info' => 'wincache/wincache.stub', 'wincache_ucache_meminfo' => 'wincache/wincache.stub', 'wincache_ucache_set' => 'wincache/wincache.stub', 'wincache_unlock' => 'wincache/wincache.stub', 'wordwrap' => 'standard/standard_0.stub', 'xcache_asm' => 'xcache/xcache.stub', 'xcache_clear_cache' => 'xcache/xcache.stub', 'xcache_coredump' => 'xcache/xcache.stub', 'xcache_count' => 'xcache/xcache.stub', 'xcache_coverager_decode' => 'xcache/xcache.stub', 'xcache_coverager_get' => 'xcache/xcache.stub', 'xcache_coverager_start' => 'xcache/xcache.stub', 'xcache_coverager_stop' => 'xcache/xcache.stub', 'xcache_dasm_file' => 'xcache/xcache.stub', 'xcache_dasm_string' => 'xcache/xcache.stub', 'xcache_dec' => 'xcache/xcache.stub', 'xcache_decode' => 'xcache/xcache.stub', 'xcache_encode' => 'xcache/xcache.stub', 'xcache_get' => 'xcache/xcache.stub', 'xcache_get_data_type' => 'xcache/xcache.stub', 'xcache_get_op_spec' => 'xcache/xcache.stub', 'xcache_get_op_type' => 'xcache/xcache.stub', 'xcache_get_opcode' => 'xcache/xcache.stub', 'xcache_get_opcode_spec' => 'xcache/xcache.stub', 'xcache_inc' => 'xcache/xcache.stub', 'xcache_info' => 'xcache/xcache.stub', 'xcache_is_autoglobal' => 'xcache/xcache.stub', 'xcache_isset' => 'xcache/xcache.stub', 'xcache_list' => 'xcache/xcache.stub', 'xcache_set' => 'xcache/xcache.stub', 'xcache_unset' => 'xcache/xcache.stub', 'xcache_unset_by_prefix' => 'xcache/xcache.stub', 'xdebug_break' => 'xdebug/xdebug.stub', 'xdebug_call_class' => 'xdebug/xdebug.stub', 'xdebug_call_file' => 'xdebug/xdebug.stub', 'xdebug_call_function' => 'xdebug/xdebug.stub', 'xdebug_call_line' => 'xdebug/xdebug.stub', 'xdebug_clear_aggr_profiling_data' => 'xdebug/xdebug.stub', 'xdebug_code_coverage_started' => 'xdebug/xdebug.stub', 'xdebug_connect_to_client' => 'xdebug/xdebug.stub', 'xdebug_debug_zval' => 'xdebug/xdebug.stub', 'xdebug_debug_zval_stdout' => 'xdebug/xdebug.stub', 'xdebug_disable' => 'xdebug/xdebug.stub', 'xdebug_dump_aggr_profiling_data' => 'xdebug/xdebug.stub', 'xdebug_dump_superglobals' => 'xdebug/xdebug.stub', 'xdebug_enable' => 'xdebug/xdebug.stub', 'xdebug_get_code_coverage' => 'xdebug/xdebug.stub', 'xdebug_get_collected_errors' => 'xdebug/xdebug.stub', 'xdebug_get_declared_vars' => 'xdebug/xdebug.stub', 'xdebug_get_formatted_function_stack' => 'xdebug/xdebug.stub', 'xdebug_get_function_count' => 'xdebug/xdebug.stub', 'xdebug_get_function_stack' => 'xdebug/xdebug.stub', 'xdebug_get_gc_run_count' => 'xdebug/xdebug.stub', 'xdebug_get_gc_total_collected_roots' => 'xdebug/xdebug.stub', 'xdebug_get_gcstats_filename' => 'xdebug/xdebug.stub', 'xdebug_get_headers' => 'xdebug/xdebug.stub', 'xdebug_get_monitored_functions' => 'xdebug/xdebug.stub', 'xdebug_get_profiler_filename' => 'xdebug/xdebug.stub', 'xdebug_get_stack_depth' => 'xdebug/xdebug.stub', 'xdebug_get_tracefile_name' => 'xdebug/xdebug.stub', 'xdebug_info' => 'xdebug/xdebug.stub', 'xdebug_is_debugger_active' => 'xdebug/xdebug.stub', 'xdebug_is_enabled' => 'xdebug/xdebug.stub', 'xdebug_memory_usage' => 'xdebug/xdebug.stub', 'xdebug_notify' => 'xdebug/xdebug.stub', 'xdebug_peak_memory_usage' => 'xdebug/xdebug.stub', 'xdebug_print_function_stack' => 'xdebug/xdebug.stub', 'xdebug_set_filter' => 'xdebug/xdebug.stub', 'xdebug_start_code_coverage' => 'xdebug/xdebug.stub', 'xdebug_start_error_collection' => 'xdebug/xdebug.stub', 'xdebug_start_function_monitor' => 'xdebug/xdebug.stub', 'xdebug_start_gcstats' => 'xdebug/xdebug.stub', 'xdebug_start_trace' => 'xdebug/xdebug.stub', 'xdebug_stop_code_coverage' => 'xdebug/xdebug.stub', 'xdebug_stop_error_collection' => 'xdebug/xdebug.stub', 'xdebug_stop_function_monitor' => 'xdebug/xdebug.stub', 'xdebug_stop_gcstats' => 'xdebug/xdebug.stub', 'xdebug_stop_trace' => 'xdebug/xdebug.stub', 'xdebug_time_index' => 'xdebug/xdebug.stub', 'xdebug_var_dump' => 'xdebug/xdebug.stub', 'xdiff_file_bdiff' => 'xdiff/xdiff.stub', 'xdiff_file_bdiff_size' => 'xdiff/xdiff.stub', 'xdiff_file_bpatch' => 'xdiff/xdiff.stub', 'xdiff_file_diff' => 'xdiff/xdiff.stub', 'xdiff_file_diff_binary' => 'xdiff/xdiff.stub', 'xdiff_file_merge3' => 'xdiff/xdiff.stub', 'xdiff_file_patch' => 'xdiff/xdiff.stub', 'xdiff_file_patch_binary' => 'xdiff/xdiff.stub', 'xdiff_file_rabdiff' => 'xdiff/xdiff.stub', 'xdiff_string_bdiff' => 'xdiff/xdiff.stub', 'xdiff_string_bdiff_size' => 'xdiff/xdiff.stub', 'xdiff_string_bpatch' => 'xdiff/xdiff.stub', 'xdiff_string_diff' => 'xdiff/xdiff.stub', 'xdiff_string_diff_binary' => 'xdiff/xdiff.stub', 'xdiff_string_merge3' => 'xdiff/xdiff.stub', 'xdiff_string_patch' => 'xdiff/xdiff.stub', 'xdiff_string_patch_binary' => 'xdiff/xdiff.stub', 'xdiff_string_rabdiff' => 'xdiff/xdiff.stub', 'xhprof_disable' => 'xhprof/xhprof.stub', 'xhprof_enable' => 'xhprof/xhprof.stub', 'xhprof_sample_disable' => 'xhprof/xhprof.stub', 'xhprof_sample_enable' => 'xhprof/xhprof.stub', 'xml_error_string' => 'xml/xml.stub', 'xml_get_current_byte_index' => 'xml/xml.stub', 'xml_get_current_column_number' => 'xml/xml.stub', 'xml_get_current_line_number' => 'xml/xml.stub', 'xml_get_error_code' => 'xml/xml.stub', 'xml_parse' => 'xml/xml.stub', 'xml_parse_into_struct' => 'xml/xml.stub', 'xml_parser_create' => 'xml/xml.stub', 'xml_parser_create_ns' => 'xml/xml.stub', 'xml_parser_free' => 'xml/xml.stub', 'xml_parser_get_option' => 'xml/xml.stub', 'xml_parser_set_option' => 'xml/xml.stub', 'xml_set_character_data_handler' => 'xml/xml.stub', 'xml_set_default_handler' => 'xml/xml.stub', 'xml_set_element_handler' => 'xml/xml.stub', 'xml_set_end_namespace_decl_handler' => 'xml/xml.stub', 'xml_set_external_entity_ref_handler' => 'xml/xml.stub', 'xml_set_notation_decl_handler' => 'xml/xml.stub', 'xml_set_object' => 'xml/xml.stub', 'xml_set_processing_instruction_handler' => 'xml/xml.stub', 'xml_set_start_namespace_decl_handler' => 'xml/xml.stub', 'xml_set_unparsed_entity_decl_handler' => 'xml/xml.stub', 'xmlrpc_decode' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_decode_request' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_encode' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_encode_request' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_get_type' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_is_fault' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_parse_method_descriptions' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_server_add_introspection_data' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_server_call_method' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_server_create' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_server_destroy' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_server_register_introspection_callback' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_server_register_method' => 'xmlrpc/xmlrpc.stub', 'xmlrpc_set_type' => 'xmlrpc/xmlrpc.stub', 'xmlwriter_end_attribute' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_end_cdata' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_end_comment' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_end_document' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_end_dtd' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_end_dtd_attlist' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_end_dtd_element' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_end_dtd_entity' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_end_element' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_end_pi' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_flush' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_full_end_element' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_open_memory' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_open_uri' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_output_memory' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_set_indent' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_set_indent_string' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_attribute' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_attribute_ns' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_cdata' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_comment' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_document' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_dtd' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_dtd_attlist' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_dtd_element' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_dtd_entity' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_element' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_element_ns' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_start_pi' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_text' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_attribute' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_attribute_ns' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_cdata' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_comment' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_dtd' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_dtd_attlist' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_dtd_element' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_dtd_entity' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_element' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_element_ns' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_pi' => 'xmlwriter/xmlwriter.stub', 'xmlwriter_write_raw' => 'xmlwriter/xmlwriter.stub', 'xxtea_decrypt' => 'xxtea/xxtea.stub', 'xxtea_encrypt' => 'xxtea/xxtea.stub', 'yaml_emit' => 'yaml/yaml.stub', 'yaml_emit_file' => 'yaml/yaml.stub', 'yaml_parse' => 'yaml/yaml.stub', 'yaml_parse_file' => 'yaml/yaml.stub', 'yaml_parse_url' => 'yaml/yaml.stub', 'zem_get_extension_info_by_id' => 'ZendUtils/ZendUtils.stub', 'zem_get_extension_info_by_name' => 'ZendUtils/ZendUtils.stub', 'zem_get_extensions_info' => 'ZendUtils/ZendUtils.stub', 'zem_get_license_info' => 'ZendUtils/ZendUtils.stub', 'zend_current_obfuscation_level' => 'zend/zend_f.stub', 'zend_disk_cache_clear' => 'ZendCache/ZendCache.stub', 'zend_disk_cache_delete' => 'ZendCache/ZendCache.stub', 'zend_disk_cache_fetch' => 'ZendCache/ZendCache.stub', 'zend_disk_cache_info' => 'ZendCache/ZendCache.stub', 'zend_disk_cache_store' => 'ZendCache/ZendCache.stub', 'zend_get_id' => 'zend/zend_f.stub', 'zend_is_configuration_changed' => 'ZendUtils/ZendUtils.stub', 'zend_loader_current_file' => 'zend/zend_f.stub', 'zend_loader_enabled' => 'zend/zend_f.stub', 'zend_loader_file_encoded' => 'zend/zend_f.stub', 'zend_loader_file_licensed' => 'zend/zend_f.stub', 'zend_loader_install_license' => 'zend/zend_f.stub', 'zend_logo_guid' => 'standard/standard_0.stub', 'zend_obfuscate_class_name' => 'zend/zend_f.stub', 'zend_obfuscate_function_name' => 'zend/zend_f.stub', 'zend_optimizer_version' => 'zend/zend_f.stub', 'zend_runtime_obfuscate' => 'zend/zend_f.stub', 'zend_send_buffer' => 'zend/zend.stub', 'zend_send_file' => 'zend/zend.stub', 'zend_set_configuration_changed' => 'ZendUtils/ZendUtils.stub', 'zend_shm_cache_clear' => 'ZendCache/ZendCache.stub', 'zend_shm_cache_delete' => 'ZendCache/ZendCache.stub', 'zend_shm_cache_fetch' => 'ZendCache/ZendCache.stub', 'zend_shm_cache_info' => 'ZendCache/ZendCache.stub', 'zend_shm_cache_store' => 'ZendCache/ZendCache.stub', 'zend_version' => 'Core/Core.stub', 'zip_close' => 'zip/zip.stub', 'zip_entry_close' => 'zip/zip.stub', 'zip_entry_compressedsize' => 'zip/zip.stub', 'zip_entry_compressionmethod' => 'zip/zip.stub', 'zip_entry_filesize' => 'zip/zip.stub', 'zip_entry_name' => 'zip/zip.stub', 'zip_entry_open' => 'zip/zip.stub', 'zip_entry_read' => 'zip/zip.stub', 'zip_open' => 'zip/zip.stub', 'zip_read' => 'zip/zip.stub', 'zlib_decode' => 'zlib/zlib.stub', 'zlib_encode' => 'zlib/zlib.stub', 'zlib_get_coding_type' => 'zlib/zlib.stub', 'zstd_compress' => 'zstd/zstd.stub', 'zstd_compress_dict' => 'zstd/zstd.stub', 'zstd_compress_usingcdict' => 'zstd/zstd.stub', 'zstd_decompress_dict' => 'zstd/zstd.stub', 'zstd_decompress_usingcdict' => 'zstd/zstd.stub', 'zstd_uncompress' => 'zstd/zstd.stub', 'zstd_uncompress_dict' => 'zstd/zstd.stub', 'zstd_uncompress_usingcdict' => 'zstd/zstd.stub'); const CONSTANTS = array('ABDAY_1' => 'standard/standard_defines.stub', 'ABDAY_2' => 'standard/standard_defines.stub', 'ABDAY_3' => 'standard/standard_defines.stub', 'ABDAY_4' => 'standard/standard_defines.stub', 'ABDAY_5' => 'standard/standard_defines.stub', 'ABDAY_6' => 'standard/standard_defines.stub', 'ABDAY_7' => 'standard/standard_defines.stub', 'ABMON_1' => 'standard/standard_defines.stub', 'ABMON_10' => 'standard/standard_defines.stub', 'ABMON_11' => 'standard/standard_defines.stub', 'ABMON_12' => 'standard/standard_defines.stub', 'ABMON_2' => 'standard/standard_defines.stub', 'ABMON_3' => 'standard/standard_defines.stub', 'ABMON_4' => 'standard/standard_defines.stub', 'ABMON_5' => 'standard/standard_defines.stub', 'ABMON_6' => 'standard/standard_defines.stub', 'ABMON_7' => 'standard/standard_defines.stub', 'ABMON_8' => 'standard/standard_defines.stub', 'ABMON_9' => 'standard/standard_defines.stub', 'AF_INET' => 'sockets/sockets.stub', 'AF_INET6' => 'sockets/sockets.stub', 'AF_UNIX' => 'sockets/sockets.stub', 'AI_ADDRCONFIG' => 'sockets/sockets.stub', 'AI_ALL' => 'sockets/sockets.stub', 'AI_CANONNAME' => 'sockets/sockets.stub', 'AI_NUMERICHOST' => 'sockets/sockets.stub', 'AI_NUMERICSERV' => 'sockets/sockets.stub', 'AI_PASSIVE' => 'sockets/sockets.stub', 'AI_V4MAPPED' => 'sockets/sockets.stub', 'ALT_DIGITS' => 'standard/standard_defines.stub', 'AMQP_AUTOACK' => 'amqp/amqp.stub', 'AMQP_AUTODELETE' => 'amqp/amqp.stub', 'AMQP_DELIVERY_MODE_PERSISTENT' => 'amqp/amqp.stub', 'AMQP_DELIVERY_MODE_TRANSIENT' => 'amqp/amqp.stub', 'AMQP_DURABLE' => 'amqp/amqp.stub', 'AMQP_EXCLUSIVE' => 'amqp/amqp.stub', 'AMQP_EXTENSION_VERSION' => 'amqp/amqp.stub', 'AMQP_EXTENSION_VERSION_EXTRA' => 'amqp/amqp.stub', 'AMQP_EXTENSION_VERSION_ID' => 'amqp/amqp.stub', 'AMQP_EXTENSION_VERSION_MAJOR' => 'amqp/amqp.stub', 'AMQP_EXTENSION_VERSION_MINOR' => 'amqp/amqp.stub', 'AMQP_EXTENSION_VERSION_PATCH' => 'amqp/amqp.stub', 'AMQP_EX_TYPE_DIRECT' => 'amqp/amqp.stub', 'AMQP_EX_TYPE_FANOUT' => 'amqp/amqp.stub', 'AMQP_EX_TYPE_HEADERS' => 'amqp/amqp.stub', 'AMQP_EX_TYPE_TOPIC' => 'amqp/amqp.stub', 'AMQP_IFEMPTY' => 'amqp/amqp.stub', 'AMQP_IFUNUSED' => 'amqp/amqp.stub', 'AMQP_IMMEDIATE' => 'amqp/amqp.stub', 'AMQP_INTERNAL' => 'amqp/amqp.stub', 'AMQP_JUST_CONSUME' => 'amqp/amqp.stub', 'AMQP_MANDATORY' => 'amqp/amqp.stub', 'AMQP_MULTIPLE' => 'amqp/amqp.stub', 'AMQP_NOLOCAL' => 'amqp/amqp.stub', 'AMQP_NOPARAM' => 'amqp/amqp.stub', 'AMQP_NOWAIT' => 'amqp/amqp.stub', 'AMQP_OS_SOCKET_TIMEOUT_ERRNO' => 'amqp/amqp.stub', 'AMQP_PASSIVE' => 'amqp/amqp.stub', 'AMQP_REQUEUE' => 'amqp/amqp.stub', 'AMQP_SASL_METHOD_EXTERNAL' => 'amqp/amqp.stub', 'AMQP_SASL_METHOD_PLAIN' => 'amqp/amqp.stub', 'AM_STR' => 'standard/standard_defines.stub', 'APACHE_MAP' => 'soap/soap.stub', 'APC_BIN_VERIFY_CRC32' => 'apcu/apcu.stub', 'APC_BIN_VERIFY_MD5' => 'apcu/apcu.stub', 'APC_ITER_ALL' => 'apcu/apcu.stub', 'APC_ITER_ATIME' => 'apcu/apcu.stub', 'APC_ITER_CTIME' => 'apcu/apcu.stub', 'APC_ITER_DEVICE' => 'apcu/apcu.stub', 'APC_ITER_DTIME' => 'apcu/apcu.stub', 'APC_ITER_FILENAME' => 'apcu/apcu.stub', 'APC_ITER_INODE' => 'apcu/apcu.stub', 'APC_ITER_KEY' => 'apcu/apcu.stub', 'APC_ITER_MD5' => 'apcu/apcu.stub', 'APC_ITER_MEM_SIZE' => 'apcu/apcu.stub', 'APC_ITER_MTIME' => 'apcu/apcu.stub', 'APC_ITER_NONE' => 'apcu/apcu.stub', 'APC_ITER_NUM_HITS' => 'apcu/apcu.stub', 'APC_ITER_REFCOUNT' => 'apcu/apcu.stub', 'APC_ITER_TTL' => 'apcu/apcu.stub', 'APC_ITER_TYPE' => 'apcu/apcu.stub', 'APC_ITER_VALUE' => 'apcu/apcu.stub', 'APC_LIST_ACTIVE' => 'apcu/apcu.stub', 'APC_LIST_DELETED' => 'apcu/apcu.stub', 'ARRAY_FILTER_USE_BOTH' => 'standard/standard_9.stub', 'ARRAY_FILTER_USE_KEY' => 'standard/standard_9.stub', 'ASSERT_ACTIVE' => 'standard/standard_defines.stub', 'ASSERT_BAIL' => 'standard/standard_defines.stub', 'ASSERT_CALLBACK' => 'standard/standard_defines.stub', 'ASSERT_EXCEPTION' => 'standard/standard_defines.stub', 'ASSERT_QUIET_EVAL' => 'standard/standard_defines.stub', 'ASSERT_WARNING' => 'standard/standard_defines.stub', 'Accel' => 'winbinder/winbinder.stub', 'AppWindow' => 'winbinder/winbinder.stub', 'BLACK' => 'winbinder/winbinder.stub', 'BLUE' => 'winbinder/winbinder.stub', 'BROTLI_COMPRESS_LEVEL_DEFAULT' => 'brotli/brotli.stub', 'BROTLI_COMPRESS_LEVEL_MAX' => 'brotli/brotli.stub', 'BROTLI_COMPRESS_LEVEL_MIN' => 'brotli/brotli.stub', 'BROTLI_FINISH' => 'brotli/brotli.stub', 'BROTLI_FLUSH' => 'brotli/brotli.stub', 'BROTLI_FONT' => 'brotli/brotli.stub', 'BROTLI_GENERIC' => 'brotli/brotli.stub', 'BROTLI_PROCESS' => 'brotli/brotli.stub', 'BROTLI_TEXT' => 'brotli/brotli.stub', 'BUS_ADRALN' => 'pcntl/pcntl.stub', 'BUS_ADRERR' => 'pcntl/pcntl.stub', 'BUS_OBJERR' => 'pcntl/pcntl.stub', 'CAL_DOW_DAYNO' => 'calendar/calendar.stub', 'CAL_DOW_LONG' => 'calendar/calendar.stub', 'CAL_DOW_SHORT' => 'calendar/calendar.stub', 'CAL_EASTER_ALWAYS_GREGORIAN' => 'calendar/calendar.stub', 'CAL_EASTER_ALWAYS_JULIAN' => 'calendar/calendar.stub', 'CAL_EASTER_DEFAULT' => 'calendar/calendar.stub', 'CAL_EASTER_ROMAN' => 'calendar/calendar.stub', 'CAL_FRENCH' => 'calendar/calendar.stub', 'CAL_GREGORIAN' => 'calendar/calendar.stub', 'CAL_JEWISH' => 'calendar/calendar.stub', 'CAL_JEWISH_ADD_ALAFIM' => 'calendar/calendar.stub', 'CAL_JEWISH_ADD_ALAFIM_GERESH' => 'calendar/calendar.stub', 'CAL_JEWISH_ADD_GERESHAYIM' => 'calendar/calendar.stub', 'CAL_JULIAN' => 'calendar/calendar.stub', 'CAL_MONTH_FRENCH' => 'calendar/calendar.stub', 'CAL_MONTH_GREGORIAN_LONG' => 'calendar/calendar.stub', 'CAL_MONTH_GREGORIAN_SHORT' => 'calendar/calendar.stub', 'CAL_MONTH_JEWISH' => 'calendar/calendar.stub', 'CAL_MONTH_JULIAN_LONG' => 'calendar/calendar.stub', 'CAL_MONTH_JULIAN_SHORT' => 'calendar/calendar.stub', 'CAL_NUM_CALS' => 'calendar/calendar.stub', 'CASE_LOWER' => 'standard/standard_defines.stub', 'CASE_UPPER' => 'standard/standard_defines.stub', 'CHAR_MAX' => 'standard/standard_defines.stub', 'CLD_CONTINUED' => 'pcntl/pcntl.stub', 'CLD_DUMPED' => 'pcntl/pcntl.stub', 'CLD_EXITED' => 'pcntl/pcntl.stub', 'CLD_KILLED' => 'pcntl/pcntl.stub', 'CLD_STOPPED' => 'pcntl/pcntl.stub', 'CLD_TRAPPED' => 'pcntl/pcntl.stub', 'CLONE_NEWCGROUP' => 'pcntl/pcntl.stub', 'CLONE_NEWIPC' => 'pcntl/pcntl.stub', 'CLONE_NEWNET' => 'pcntl/pcntl.stub', 'CLONE_NEWNS' => 'pcntl/pcntl.stub', 'CLONE_NEWPID' => 'pcntl/pcntl.stub', 'CLONE_NEWUSER' => 'pcntl/pcntl.stub', 'CLONE_NEWUTS' => 'pcntl/pcntl.stub', 'CLSCTX_ALL' => 'com_dotnet/com_dotnet.stub', 'CLSCTX_INPROC_HANDLER' => 'com_dotnet/com_dotnet.stub', 'CLSCTX_INPROC_SERVER' => 'com_dotnet/com_dotnet.stub', 'CLSCTX_LOCAL_SERVER' => 'com_dotnet/com_dotnet.stub', 'CLSCTX_REMOTE_SERVER' => 'com_dotnet/com_dotnet.stub', 'CLSCTX_SERVER' => 'com_dotnet/com_dotnet.stub', 'CL_EXPUNGE' => 'imap/imap.stub', 'CODESET' => 'standard/standard_defines.stub', 'CONNECTION_ABORTED' => 'standard/standard_defines.stub', 'CONNECTION_NORMAL' => 'standard/standard_defines.stub', 'CONNECTION_TIMEOUT' => 'standard/standard_defines.stub', 'COUNT_NORMAL' => 'standard/standard_defines.stub', 'COUNT_RECURSIVE' => 'standard/standard_defines.stub', 'CP_ACP' => 'com_dotnet/com_dotnet.stub', 'CP_MACCP' => 'com_dotnet/com_dotnet.stub', 'CP_MOVE' => 'imap/imap.stub', 'CP_OEMCP' => 'com_dotnet/com_dotnet.stub', 'CP_SYMBOL' => 'com_dotnet/com_dotnet.stub', 'CP_THREAD_ACP' => 'com_dotnet/com_dotnet.stub', 'CP_UID' => 'imap/imap.stub', 'CP_UTF7' => 'com_dotnet/com_dotnet.stub', 'CP_UTF8' => 'com_dotnet/com_dotnet.stub', 'CREDITS_ALL' => 'standard/standard_defines.stub', 'CREDITS_DOCS' => 'standard/standard_defines.stub', 'CREDITS_FULLPAGE' => 'standard/standard_defines.stub', 'CREDITS_GENERAL' => 'standard/standard_defines.stub', 'CREDITS_GROUP' => 'standard/standard_defines.stub', 'CREDITS_MODULES' => 'standard/standard_defines.stub', 'CREDITS_QA' => 'standard/standard_defines.stub', 'CREDITS_SAPI' => 'standard/standard_defines.stub', 'CRNCYSTR' => 'standard/standard_defines.stub', 'CRYPT_BLOWFISH' => 'standard/standard_defines.stub', 'CRYPT_EXT_DES' => 'standard/standard_defines.stub', 'CRYPT_MD5' => 'standard/standard_defines.stub', 'CRYPT_SALT_LENGTH' => 'standard/standard_defines.stub', 'CRYPT_SHA256' => 'standard/standard_defines.stub', 'CRYPT_SHA512' => 'standard/standard_defines.stub', 'CRYPT_STD_DES' => 'standard/standard_defines.stub', 'CUBRID_ASSOC' => 'cubrid/cubrid.stub', 'CUBRID_ASYNC' => 'cubrid/cubrid.stub', 'CUBRID_AUTOCOMMIT_FALSE' => 'cubrid/cubrid.stub', 'CUBRID_AUTOCOMMIT_TRUE' => 'cubrid/cubrid.stub', 'CUBRID_BOTH' => 'cubrid/cubrid.stub', 'CUBRID_CURSOR_CURRENT' => 'cubrid/cubrid.stub', 'CUBRID_CURSOR_ERROR' => 'cubrid/cubrid.stub', 'CUBRID_CURSOR_FIRST' => 'cubrid/cubrid.stub', 'CUBRID_CURSOR_LAST' => 'cubrid/cubrid.stub', 'CUBRID_CURSOR_SUCCESS' => 'cubrid/cubrid.stub', 'CUBRID_EXEC_QUERY_ALL' => 'cubrid/cubrid.stub', 'CUBRID_INCLUDE_OID' => 'cubrid/cubrid.stub', 'CUBRID_NO_MORE_DATA' => 'cubrid/cubrid.stub', 'CUBRID_NUM' => 'cubrid/cubrid.stub', 'CUBRID_OBJECT' => 'cubrid/cubrid.stub', 'CURLALTSVC_H1' => 'curl/curl_d.stub', 'CURLALTSVC_H2' => 'curl/curl_d.stub', 'CURLALTSVC_H3' => 'curl/curl_d.stub', 'CURLALTSVC_READONLYFILE' => 'curl/curl_d.stub', 'CURLAUTH_ANY' => 'curl/curl_d.stub', 'CURLAUTH_ANYSAFE' => 'curl/curl_d.stub', 'CURLAUTH_AWS_SIGV4' => 'curl/curl_d.stub', 'CURLAUTH_BASIC' => 'curl/curl_d.stub', 'CURLAUTH_BEARER' => 'curl/curl_d.stub', 'CURLAUTH_DIGEST' => 'curl/curl_d.stub', 'CURLAUTH_DIGEST_IE' => 'curl/curl_d.stub', 'CURLAUTH_GSSAPI' => 'curl/curl_d.stub', 'CURLAUTH_GSSNEGOTIATE' => 'curl/curl_d.stub', 'CURLAUTH_NEGOTIATE' => 'curl/curl_d.stub', 'CURLAUTH_NONE' => 'curl/curl_d.stub', 'CURLAUTH_NTLM' => 'curl/curl_d.stub', 'CURLAUTH_NTLM_WB' => 'curl/curl_d.stub', 'CURLAUTH_ONLY' => 'curl/curl_d.stub', 'CURLCLOSEPOLICY_CALLBACK' => 'curl/curl_d.stub', 'CURLCLOSEPOLICY_LEAST_RECENTLY_USED' => 'curl/curl_d.stub', 'CURLCLOSEPOLICY_LEAST_TRAFFIC' => 'curl/curl_d.stub', 'CURLCLOSEPOLICY_OLDEST' => 'curl/curl_d.stub', 'CURLCLOSEPOLICY_SLOWEST' => 'curl/curl_d.stub', 'CURLE_ABORTED_BY_CALLBACK' => 'curl/curl_d.stub', 'CURLE_BAD_CALLING_ORDER' => 'curl/curl_d.stub', 'CURLE_BAD_CONTENT_ENCODING' => 'curl/curl_d.stub', 'CURLE_BAD_DOWNLOAD_RESUME' => 'curl/curl_d.stub', 'CURLE_BAD_FUNCTION_ARGUMENT' => 'curl/curl_d.stub', 'CURLE_BAD_PASSWORD_ENTERED' => 'curl/curl_d.stub', 'CURLE_COULDNT_CONNECT' => 'curl/curl_d.stub', 'CURLE_COULDNT_RESOLVE_HOST' => 'curl/curl_d.stub', 'CURLE_COULDNT_RESOLVE_PROXY' => 'curl/curl_d.stub', 'CURLE_FAILED_INIT' => 'curl/curl_d.stub', 'CURLE_FILESIZE_EXCEEDED' => 'curl/curl_d.stub', 'CURLE_FILE_COULDNT_READ_FILE' => 'curl/curl_d.stub', 'CURLE_FTP_ACCESS_DENIED' => 'curl/curl_d.stub', 'CURLE_FTP_BAD_DOWNLOAD_RESUME' => 'curl/curl_d.stub', 'CURLE_FTP_CANT_GET_HOST' => 'curl/curl_d.stub', 'CURLE_FTP_CANT_RECONNECT' => 'curl/curl_d.stub', 'CURLE_FTP_COULDNT_GET_SIZE' => 'curl/curl_d.stub', 'CURLE_FTP_COULDNT_RETR_FILE' => 'curl/curl_d.stub', 'CURLE_FTP_COULDNT_SET_ASCII' => 'curl/curl_d.stub', 'CURLE_FTP_COULDNT_SET_BINARY' => 'curl/curl_d.stub', 'CURLE_FTP_COULDNT_STOR_FILE' => 'curl/curl_d.stub', 'CURLE_FTP_COULDNT_USE_REST' => 'curl/curl_d.stub', 'CURLE_FTP_PARTIAL_FILE' => 'curl/curl_d.stub', 'CURLE_FTP_PORT_FAILED' => 'curl/curl_d.stub', 'CURLE_FTP_QUOTE_ERROR' => 'curl/curl_d.stub', 'CURLE_FTP_SSL_FAILED' => 'curl/curl_d.stub', 'CURLE_FTP_USER_PASSWORD_INCORRECT' => 'curl/curl_d.stub', 'CURLE_FTP_WEIRD_227_FORMAT' => 'curl/curl_d.stub', 'CURLE_FTP_WEIRD_PASS_REPLY' => 'curl/curl_d.stub', 'CURLE_FTP_WEIRD_PASV_REPLY' => 'curl/curl_d.stub', 'CURLE_FTP_WEIRD_SERVER_REPLY' => 'curl/curl_d.stub', 'CURLE_FTP_WEIRD_USER_REPLY' => 'curl/curl_d.stub', 'CURLE_FTP_WRITE_ERROR' => 'curl/curl_d.stub', 'CURLE_FUNCTION_NOT_FOUND' => 'curl/curl_d.stub', 'CURLE_GOT_NOTHING' => 'curl/curl_d.stub', 'CURLE_HTTP_NOT_FOUND' => 'curl/curl_d.stub', 'CURLE_HTTP_PORT_FAILED' => 'curl/curl_d.stub', 'CURLE_HTTP_POST_ERROR' => 'curl/curl_d.stub', 'CURLE_HTTP_RANGE_ERROR' => 'curl/curl_d.stub', 'CURLE_HTTP_RETURNED_ERROR' => 'curl/curl_d.stub', 'CURLE_LDAP_CANNOT_BIND' => 'curl/curl_d.stub', 'CURLE_LDAP_INVALID_URL' => 'curl/curl_d.stub', 'CURLE_LDAP_SEARCH_FAILED' => 'curl/curl_d.stub', 'CURLE_LIBRARY_NOT_FOUND' => 'curl/curl_d.stub', 'CURLE_MALFORMAT_USER' => 'curl/curl_d.stub', 'CURLE_OBSOLETE' => 'curl/curl_d.stub', 'CURLE_OK' => 'curl/curl_d.stub', 'CURLE_OPERATION_TIMEDOUT' => 'curl/curl_d.stub', 'CURLE_OPERATION_TIMEOUTED' => 'curl/curl_d.stub', 'CURLE_OUT_OF_MEMORY' => 'curl/curl_d.stub', 'CURLE_PARTIAL_FILE' => 'curl/curl_d.stub', 'CURLE_PROXY' => 'curl/curl_d.stub', 'CURLE_READ_ERROR' => 'curl/curl_d.stub', 'CURLE_RECV_ERROR' => 'curl/curl_d.stub', 'CURLE_SEND_ERROR' => 'curl/curl_d.stub', 'CURLE_SHARE_IN_USE' => 'curl/curl_d.stub', 'CURLE_SSH' => 'curl/curl_d.stub', 'CURLE_SSL_CACERT' => 'curl/curl_d.stub', 'CURLE_SSL_CACERT_BADFILE' => 'curl/curl_d.stub', 'CURLE_SSL_CERTPROBLEM' => 'curl/curl_d.stub', 'CURLE_SSL_CIPHER' => 'curl/curl_d.stub', 'CURLE_SSL_CONNECT_ERROR' => 'curl/curl_d.stub', 'CURLE_SSL_ENGINE_NOTFOUND' => 'curl/curl_d.stub', 'CURLE_SSL_ENGINE_SETFAILED' => 'curl/curl_d.stub', 'CURLE_SSL_PEER_CERTIFICATE' => 'curl/curl_d.stub', 'CURLE_SSL_PINNEDPUBKEYNOTMATCH' => 'curl/curl_d.stub', 'CURLE_TELNET_OPTION_SYNTAX' => 'curl/curl_d.stub', 'CURLE_TOO_MANY_REDIRECTS' => 'curl/curl_d.stub', 'CURLE_UNKNOWN_TELNET_OPTION' => 'curl/curl_d.stub', 'CURLE_UNSUPPORTED_PROTOCOL' => 'curl/curl_d.stub', 'CURLE_URL_MALFORMAT' => 'curl/curl_d.stub', 'CURLE_URL_MALFORMAT_USER' => 'curl/curl_d.stub', 'CURLE_WEIRD_SERVER_REPLY' => 'curl/curl_d.stub', 'CURLE_WRITE_ERROR' => 'curl/curl_d.stub', 'CURLFTPAUTH_DEFAULT' => 'curl/curl_d.stub', 'CURLFTPAUTH_SSL' => 'curl/curl_d.stub', 'CURLFTPAUTH_TLS' => 'curl/curl_d.stub', 'CURLFTPMETHOD_DEFAULT' => 'curl/curl_d.stub', 'CURLFTPMETHOD_MULTICWD' => 'curl/curl_d.stub', 'CURLFTPMETHOD_NOCWD' => 'curl/curl_d.stub', 'CURLFTPMETHOD_SINGLECWD' => 'curl/curl_d.stub', 'CURLFTPSSL_ALL' => 'curl/curl_d.stub', 'CURLFTPSSL_CCC_ACTIVE' => 'curl/curl_d.stub', 'CURLFTPSSL_CCC_NONE' => 'curl/curl_d.stub', 'CURLFTPSSL_CCC_PASSIVE' => 'curl/curl_d.stub', 'CURLFTPSSL_CONTROL' => 'curl/curl_d.stub', 'CURLFTPSSL_NONE' => 'curl/curl_d.stub', 'CURLFTPSSL_TRY' => 'curl/curl_d.stub', 'CURLFTP_CREATE_DIR' => 'curl/curl_d.stub', 'CURLFTP_CREATE_DIR_NONE' => 'curl/curl_d.stub', 'CURLFTP_CREATE_DIR_RETRY' => 'curl/curl_d.stub', 'CURLGSSAPI_DELEGATION_FLAG' => 'curl/curl_d.stub', 'CURLGSSAPI_DELEGATION_POLICY_FLAG' => 'curl/curl_d.stub', 'CURLHEADER_SEPARATE' => 'curl/curl_d.stub', 'CURLHEADER_UNIFIED' => 'curl/curl_d.stub', 'CURLHSTS_ENABLE' => 'curl/curl_d.stub', 'CURLHSTS_READONLYFILE' => 'curl/curl_d.stub', 'CURLINFO_APPCONNECT_TIME' => 'curl/curl_d.stub', 'CURLINFO_APPCONNECT_TIME_T' => 'curl/curl_d.stub', 'CURLINFO_CAINFO' => 'curl/curl_d.stub', 'CURLINFO_CAPATH' => 'curl/curl_d.stub', 'CURLINFO_CERTINFO' => 'curl/curl_d.stub', 'CURLINFO_CONDITION_UNMET' => 'curl/curl_d.stub', 'CURLINFO_CONNECT_TIME' => 'curl/curl_d.stub', 'CURLINFO_CONNECT_TIME_T' => 'curl/curl_d.stub', 'CURLINFO_CONTENT_LENGTH_DOWNLOAD' => 'curl/curl_d.stub', 'CURLINFO_CONTENT_LENGTH_DOWNLOAD_T' => 'curl/curl_d.stub', 'CURLINFO_CONTENT_LENGTH_UPLOAD' => 'curl/curl_d.stub', 'CURLINFO_CONTENT_LENGTH_UPLOAD_T' => 'curl/curl_d.stub', 'CURLINFO_CONTENT_TYPE' => 'curl/curl_d.stub', 'CURLINFO_COOKIELIST' => 'curl/curl_d.stub', 'CURLINFO_EFFECTIVE_METHOD' => 'curl/curl_d.stub', 'CURLINFO_EFFECTIVE_URL' => 'curl/curl_d.stub', 'CURLINFO_FILETIME' => 'curl/curl_d.stub', 'CURLINFO_FILETIME_T' => 'curl/curl_d.stub', 'CURLINFO_FTP_ENTRY_PATH' => 'curl/curl_d.stub', 'CURLINFO_HEADER_OUT' => 'curl/curl_d.stub', 'CURLINFO_HEADER_SIZE' => 'curl/curl_d.stub', 'CURLINFO_HTTPAUTH_AVAIL' => 'curl/curl_d.stub', 'CURLINFO_HTTP_CODE' => 'curl/curl_d.stub', 'CURLINFO_HTTP_CONNECTCODE' => 'curl/curl_d.stub', 'CURLINFO_HTTP_VERSION' => 'curl/curl_d.stub', 'CURLINFO_LASTONE' => 'curl/curl_d.stub', 'CURLINFO_LOCAL_IP' => 'curl/curl_d.stub', 'CURLINFO_LOCAL_PORT' => 'curl/curl_d.stub', 'CURLINFO_NAMELOOKUP_TIME' => 'curl/curl_d.stub', 'CURLINFO_NAMELOOKUP_TIME_T' => 'curl/curl_d.stub', 'CURLINFO_NUM_CONNECTS' => 'curl/curl_d.stub', 'CURLINFO_OS_ERRNO' => 'curl/curl_d.stub', 'CURLINFO_PRETRANSFER_TIME' => 'curl/curl_d.stub', 'CURLINFO_PRETRANSFER_TIME_T' => 'curl/curl_d.stub', 'CURLINFO_PRIMARY_IP' => 'curl/curl_d.stub', 'CURLINFO_PRIMARY_PORT' => 'curl/curl_d.stub', 'CURLINFO_PRIVATE' => 'curl/curl_d.stub', 'CURLINFO_PROTOCOL' => 'curl/curl_d.stub', 'CURLINFO_PROXYAUTH_AVAIL' => 'curl/curl_d.stub', 'CURLINFO_PROXY_ERROR' => 'curl/curl_d.stub', 'CURLINFO_PROXY_SSL_VERIFYRESULT' => 'curl/curl_d.stub', 'CURLINFO_REDIRECT_COUNT' => 'curl/curl_d.stub', 'CURLINFO_REDIRECT_TIME' => 'curl/curl_d.stub', 'CURLINFO_REDIRECT_TIME_T' => 'curl/curl_d.stub', 'CURLINFO_REDIRECT_URL' => 'curl/curl_d.stub', 'CURLINFO_REFERER' => 'curl/curl_d.stub', 'CURLINFO_REQUEST_SIZE' => 'curl/curl_d.stub', 'CURLINFO_RESPONSE_CODE' => 'curl/curl_d.stub', 'CURLINFO_RETRY_AFTER' => 'curl/curl_d.stub', 'CURLINFO_RTSP_CLIENT_CSEQ' => 'curl/curl_d.stub', 'CURLINFO_RTSP_CSEQ_RECV' => 'curl/curl_d.stub', 'CURLINFO_RTSP_SERVER_CSEQ' => 'curl/curl_d.stub', 'CURLINFO_RTSP_SESSION_ID' => 'curl/curl_d.stub', 'CURLINFO_SCHEME' => 'curl/curl_d.stub', 'CURLINFO_SIZE_DOWNLOAD' => 'curl/curl_d.stub', 'CURLINFO_SIZE_DOWNLOAD_T' => 'curl/curl_d.stub', 'CURLINFO_SIZE_UPLOAD' => 'curl/curl_d.stub', 'CURLINFO_SIZE_UPLOAD_T' => 'curl/curl_d.stub', 'CURLINFO_SPEED_DOWNLOAD' => 'curl/curl_d.stub', 'CURLINFO_SPEED_DOWNLOAD_T' => 'curl/curl_d.stub', 'CURLINFO_SPEED_UPLOAD' => 'curl/curl_d.stub', 'CURLINFO_SPEED_UPLOAD_T' => 'curl/curl_d.stub', 'CURLINFO_SSL_ENGINES' => 'curl/curl_d.stub', 'CURLINFO_SSL_VERIFYRESULT' => 'curl/curl_d.stub', 'CURLINFO_STARTTRANSFER_TIME' => 'curl/curl_d.stub', 'CURLINFO_STARTTRANSFER_TIME_T' => 'curl/curl_d.stub', 'CURLINFO_TOTAL_TIME' => 'curl/curl_d.stub', 'CURLINFO_TOTAL_TIME_T' => 'curl/curl_d.stub', 'CURLKHMATCH_LAST' => 'curl/curl_d.stub', 'CURLKHMATCH_MISMATCH' => 'curl/curl_d.stub', 'CURLKHMATCH_MISSING' => 'curl/curl_d.stub', 'CURLKHMATCH_OK' => 'curl/curl_d.stub', 'CURLMIMEOPT_FORMESCAPE' => 'curl/curl_d.stub', 'CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE' => 'curl/curl_d.stub', 'CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE' => 'curl/curl_d.stub', 'CURLMOPT_MAXCONNECTS' => 'curl/curl_d.stub', 'CURLMOPT_MAX_CONCURRENT_STREAMS' => 'curl/curl_d.stub', 'CURLMOPT_MAX_HOST_CONNECTIONS' => 'curl/curl_d.stub', 'CURLMOPT_MAX_PIPELINE_LENGTH' => 'curl/curl_d.stub', 'CURLMOPT_MAX_TOTAL_CONNECTIONS' => 'curl/curl_d.stub', 'CURLMOPT_PIPELINING' => 'curl/curl_d.stub', 'CURLMOPT_PUSHFUNCTION' => 'curl/curl_d.stub', 'CURLMSG_DONE' => 'curl/curl_d.stub', 'CURLM_ADDED_ALREADY' => 'curl/curl_d.stub', 'CURLM_BAD_EASY_HANDLE' => 'curl/curl_d.stub', 'CURLM_BAD_HANDLE' => 'curl/curl_d.stub', 'CURLM_CALL_MULTI_PERFORM' => 'curl/curl_d.stub', 'CURLM_INTERNAL_ERROR' => 'curl/curl_d.stub', 'CURLM_OK' => 'curl/curl_d.stub', 'CURLM_OUT_OF_MEMORY' => 'curl/curl_d.stub', 'CURLOPT_ABSTRACT_UNIX_SOCKET' => 'curl/curl_d.stub', 'CURLOPT_ACCEPTTIMEOUT_MS' => 'curl/curl_d.stub', 'CURLOPT_ACCEPT_ENCODING' => 'curl/curl_d.stub', 'CURLOPT_ADDRESS_SCOPE' => 'curl/curl_d.stub', 'CURLOPT_ALTSVC' => 'curl/curl_d.stub', 'CURLOPT_ALTSVC_CTRL' => 'curl/curl_d.stub', 'CURLOPT_APPEND' => 'curl/curl_d.stub', 'CURLOPT_AUTOREFERER' => 'curl/curl_d.stub', 'CURLOPT_AWS_SIGV4' => 'curl/curl_d.stub', 'CURLOPT_BINARYTRANSFER' => 'curl/curl_d.stub', 'CURLOPT_BUFFERSIZE' => 'curl/curl_d.stub', 'CURLOPT_CAINFO' => 'curl/curl_d.stub', 'CURLOPT_CAINFO_BLOB' => 'curl/curl_d.stub', 'CURLOPT_CAPATH' => 'curl/curl_d.stub', 'CURLOPT_CA_CACHE_TIMEOUT' => 'curl/curl_d.stub', 'CURLOPT_CERTINFO' => 'curl/curl_d.stub', 'CURLOPT_CLOSEPOLICY' => 'curl/curl_d.stub', 'CURLOPT_CONNECTTIMEOUT' => 'curl/curl_d.stub', 'CURLOPT_CONNECTTIMEOUT_MS' => 'curl/curl_d.stub', 'CURLOPT_CONNECT_ONLY' => 'curl/curl_d.stub', 'CURLOPT_CONNECT_TO' => 'curl/curl_d.stub', 'CURLOPT_COOKIE' => 'curl/curl_d.stub', 'CURLOPT_COOKIEFILE' => 'curl/curl_d.stub', 'CURLOPT_COOKIEJAR' => 'curl/curl_d.stub', 'CURLOPT_COOKIELIST' => 'curl/curl_d.stub', 'CURLOPT_COOKIESESSION' => 'curl/curl_d.stub', 'CURLOPT_CRLF' => 'curl/curl_d.stub', 'CURLOPT_CRLFILE' => 'curl/curl_d.stub', 'CURLOPT_CUSTOMREQUEST' => 'curl/curl_d.stub', 'CURLOPT_DEFAULT_PROTOCOL' => 'curl/curl_d.stub', 'CURLOPT_DIRLISTONLY' => 'curl/curl_d.stub', 'CURLOPT_DISALLOW_USERNAME_IN_URL' => 'curl/curl_d.stub', 'CURLOPT_DNS_CACHE_TIMEOUT' => 'curl/curl_d.stub', 'CURLOPT_DNS_INTERFACE' => 'curl/curl_d.stub', 'CURLOPT_DNS_LOCAL_IP4' => 'curl/curl_d.stub', 'CURLOPT_DNS_LOCAL_IP6' => 'curl/curl_d.stub', 'CURLOPT_DNS_SERVERS' => 'curl/curl_d.stub', 'CURLOPT_DNS_SHUFFLE_ADDRESSES' => 'curl/curl_d.stub', 'CURLOPT_DNS_USE_GLOBAL_CACHE' => 'curl/curl_d.stub', 'CURLOPT_DOH_SSL_VERIFYHOST' => 'curl/curl_d.stub', 'CURLOPT_DOH_SSL_VERIFYPEER' => 'curl/curl_d.stub', 'CURLOPT_DOH_SSL_VERIFYSTATUS' => 'curl/curl_d.stub', 'CURLOPT_DOH_URL' => 'curl/curl_d.stub', 'CURLOPT_EGDSOCKET' => 'curl/curl_d.stub', 'CURLOPT_ENCODING' => 'curl/curl_d.stub', 'CURLOPT_EXPECT_100_TIMEOUT_MS' => 'curl/curl_d.stub', 'CURLOPT_FAILONERROR' => 'curl/curl_d.stub', 'CURLOPT_FILE' => 'curl/curl_d.stub', 'CURLOPT_FILETIME' => 'curl/curl_d.stub', 'CURLOPT_FNMATCH_FUNCTION' => 'curl/curl_d.stub', 'CURLOPT_FOLLOWLOCATION' => 'curl/curl_d.stub', 'CURLOPT_FORBID_REUSE' => 'curl/curl_d.stub', 'CURLOPT_FRESH_CONNECT' => 'curl/curl_d.stub', 'CURLOPT_FTPAPPEND' => 'curl/curl_d.stub', 'CURLOPT_FTPASCII' => 'curl/curl_d.stub', 'CURLOPT_FTPLISTONLY' => 'curl/curl_d.stub', 'CURLOPT_FTPPORT' => 'curl/curl_d.stub', 'CURLOPT_FTPSSLAUTH' => 'curl/curl_d.stub', 'CURLOPT_FTP_ACCOUNT' => 'curl/curl_d.stub', 'CURLOPT_FTP_ALTERNATIVE_TO_USER' => 'curl/curl_d.stub', 'CURLOPT_FTP_CREATE_MISSING_DIRS' => 'curl/curl_d.stub', 'CURLOPT_FTP_FILEMETHOD' => 'curl/curl_d.stub', 'CURLOPT_FTP_RESPONSE_TIMEOUT' => 'curl/curl_d.stub', 'CURLOPT_FTP_SKIP_PASV_IP' => 'curl/curl_d.stub', 'CURLOPT_FTP_SSL' => 'curl/curl_d.stub', 'CURLOPT_FTP_SSL_CCC' => 'curl/curl_d.stub', 'CURLOPT_FTP_USE_EPRT' => 'curl/curl_d.stub', 'CURLOPT_FTP_USE_EPSV' => 'curl/curl_d.stub', 'CURLOPT_FTP_USE_PRET' => 'curl/curl_d.stub', 'CURLOPT_GSSAPI_DELEGATION' => 'curl/curl_d.stub', 'CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS' => 'curl/curl_d.stub', 'CURLOPT_HAPROXYPROTOCOL' => 'curl/curl_d.stub', 'CURLOPT_HEADER' => 'curl/curl_d.stub', 'CURLOPT_HEADERFUNCTION' => 'curl/curl_d.stub', 'CURLOPT_HEADEROPT' => 'curl/curl_d.stub', 'CURLOPT_HSTS' => 'curl/curl_d.stub', 'CURLOPT_HSTS_CTRL' => 'curl/curl_d.stub', 'CURLOPT_HTTP09_ALLOWED' => 'curl/curl_d.stub', 'CURLOPT_HTTP200ALIASES' => 'curl/curl_d.stub', 'CURLOPT_HTTPAUTH' => 'curl/curl_d.stub', 'CURLOPT_HTTPGET' => 'curl/curl_d.stub', 'CURLOPT_HTTPHEADER' => 'curl/curl_d.stub', 'CURLOPT_HTTPPROXYTUNNEL' => 'curl/curl_d.stub', 'CURLOPT_HTTP_CONTENT_DECODING' => 'curl/curl_d.stub', 'CURLOPT_HTTP_TRANSFER_DECODING' => 'curl/curl_d.stub', 'CURLOPT_HTTP_VERSION' => 'curl/curl_d.stub', 'CURLOPT_IGNORE_CONTENT_LENGTH' => 'curl/curl_d.stub', 'CURLOPT_INFILE' => 'curl/curl_d.stub', 'CURLOPT_INFILESIZE' => 'curl/curl_d.stub', 'CURLOPT_INTERFACE' => 'curl/curl_d.stub', 'CURLOPT_IPRESOLVE' => 'curl/curl_d.stub', 'CURLOPT_ISSUERCERT' => 'curl/curl_d.stub', 'CURLOPT_ISSUERCERT_BLOB' => 'curl/curl_d.stub', 'CURLOPT_KEEP_SENDING_ON_ERROR' => 'curl/curl_d.stub', 'CURLOPT_KEYPASSWD' => 'curl/curl_d.stub', 'CURLOPT_KRB4LEVEL' => 'curl/curl_d.stub', 'CURLOPT_KRBLEVEL' => 'curl/curl_d.stub', 'CURLOPT_LOCALPORT' => 'curl/curl_d.stub', 'CURLOPT_LOCALPORTRANGE' => 'curl/curl_d.stub', 'CURLOPT_LOGIN_OPTIONS' => 'curl/curl_d.stub', 'CURLOPT_LOW_SPEED_LIMIT' => 'curl/curl_d.stub', 'CURLOPT_LOW_SPEED_TIME' => 'curl/curl_d.stub', 'CURLOPT_MAIL_AUTH' => 'curl/curl_d.stub', 'CURLOPT_MAIL_FROM' => 'curl/curl_d.stub', 'CURLOPT_MAIL_RCPT' => 'curl/curl_d.stub', 'CURLOPT_MAIL_RCPT_ALLLOWFAILS' => 'curl/curl_d.stub', 'CURLOPT_MAXAGE_CONN' => 'curl/curl_d.stub', 'CURLOPT_MAXCONNECTS' => 'curl/curl_d.stub', 'CURLOPT_MAXFILESIZE' => 'curl/curl_d.stub', 'CURLOPT_MAXFILESIZE_LARGE' => 'curl/curl_d.stub', 'CURLOPT_MAXLIFETIME_CONN' => 'curl/curl_d.stub', 'CURLOPT_MAXREDIRS' => 'curl/curl_d.stub', 'CURLOPT_MAX_RECV_SPEED_LARGE' => 'curl/curl_d.stub', 'CURLOPT_MAX_SEND_SPEED_LARGE' => 'curl/curl_d.stub', 'CURLOPT_MIME_OPTIONS' => 'curl/curl_d.stub', 'CURLOPT_MUTE' => 'curl/curl_d.stub', 'CURLOPT_NETRC' => 'curl/curl_d.stub', 'CURLOPT_NETRC_FILE' => 'curl/curl_d.stub', 'CURLOPT_NEW_DIRECTORY_PERMS' => 'curl/curl_d.stub', 'CURLOPT_NEW_FILE_PERMS' => 'curl/curl_d.stub', 'CURLOPT_NOBODY' => 'curl/curl_d.stub', 'CURLOPT_NOPROGRESS' => 'curl/curl_d.stub', 'CURLOPT_NOPROXY' => 'curl/curl_d.stub', 'CURLOPT_NOSIGNAL' => 'curl/curl_d.stub', 'CURLOPT_PASSWDFUNCTION' => 'curl/curl_d.stub', 'CURLOPT_PASSWORD' => 'curl/curl_d.stub', 'CURLOPT_PATH_AS_IS' => 'curl/curl_d.stub', 'CURLOPT_PINNEDPUBLICKEY' => 'curl/curl_d.stub', 'CURLOPT_PIPEWAIT' => 'curl/curl_d.stub', 'CURLOPT_PORT' => 'curl/curl_d.stub', 'CURLOPT_POST' => 'curl/curl_d.stub', 'CURLOPT_POSTFIELDS' => 'curl/curl_d.stub', 'CURLOPT_POSTQUOTE' => 'curl/curl_d.stub', 'CURLOPT_POSTREDIR' => 'curl/curl_d.stub', 'CURLOPT_PREQUOTE' => 'curl/curl_d.stub', 'CURLOPT_PREREQFUNCTION' => 'curl/curl_d.stub', 'CURLOPT_PRE_PROXY' => 'curl/curl_d.stub', 'CURLOPT_PRIVATE' => 'curl/curl_d.stub', 'CURLOPT_PROGRESSFUNCTION' => 'curl/curl_d.stub', 'CURLOPT_PROTOCOLS' => 'curl/curl_d.stub', 'CURLOPT_PROTOCOLS_STR' => 'curl/curl_d.stub', 'CURLOPT_PROXY' => 'curl/curl_d.stub', 'CURLOPT_PROXYAUTH' => 'curl/curl_d.stub', 'CURLOPT_PROXYHEADER' => 'curl/curl_d.stub', 'CURLOPT_PROXYPASSWORD' => 'curl/curl_d.stub', 'CURLOPT_PROXYPORT' => 'curl/curl_d.stub', 'CURLOPT_PROXYTYPE' => 'curl/curl_d.stub', 'CURLOPT_PROXYUSERNAME' => 'curl/curl_d.stub', 'CURLOPT_PROXYUSERPWD' => 'curl/curl_d.stub', 'CURLOPT_PROXY_CAINFO' => 'curl/curl_d.stub', 'CURLOPT_PROXY_CAINFO_BLOB' => 'curl/curl_d.stub', 'CURLOPT_PROXY_CAPATH' => 'curl/curl_d.stub', 'CURLOPT_PROXY_CRLFILE' => 'curl/curl_d.stub', 'CURLOPT_PROXY_ISSUERCERT' => 'curl/curl_d.stub', 'CURLOPT_PROXY_ISSUERCERT_BLOB' => 'curl/curl_d.stub', 'CURLOPT_PROXY_KEYPASSWD' => 'curl/curl_d.stub', 'CURLOPT_PROXY_PINNEDPUBLICKEY' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SERVICE_NAME' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSLCERT' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSLCERTTYPE' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSLCERT_BLOB' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSLKEY' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSLKEYTYPE' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSLKEY_BLOB' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSLVERSION' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSL_CIPHER_LIST' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSL_OPTIONS' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSL_VERIFYHOST' => 'curl/curl_d.stub', 'CURLOPT_PROXY_SSL_VERIFYPEER' => 'curl/curl_d.stub', 'CURLOPT_PROXY_TLS13_CIPHERS' => 'curl/curl_d.stub', 'CURLOPT_PROXY_TLSAUTH_PASSWORD' => 'curl/curl_d.stub', 'CURLOPT_PROXY_TLSAUTH_TYPE' => 'curl/curl_d.stub', 'CURLOPT_PROXY_TLSAUTH_USERNAME' => 'curl/curl_d.stub', 'CURLOPT_PROXY_TRANSFER_MODE' => 'curl/curl_d.stub', 'CURLOPT_PUT' => 'curl/curl_d.stub', 'CURLOPT_QUICK_EXIT' => 'curl/curl_d.stub', 'CURLOPT_QUOTE' => 'curl/curl_d.stub', 'CURLOPT_RANDOM_FILE' => 'curl/curl_d.stub', 'CURLOPT_RANGE' => 'curl/curl_d.stub', 'CURLOPT_READDATA' => 'curl/curl_d.stub', 'CURLOPT_READFUNCTION' => 'curl/curl_d.stub', 'CURLOPT_REDIR_PROTOCOLS' => 'curl/curl_d.stub', 'CURLOPT_REDIR_PROTOCOLS_STR' => 'curl/curl_d.stub', 'CURLOPT_REFERER' => 'curl/curl_d.stub', 'CURLOPT_REQUEST_TARGET' => 'curl/curl_d.stub', 'CURLOPT_RESOLVE' => 'curl/curl_d.stub', 'CURLOPT_RESUME_FROM' => 'curl/curl_d.stub', 'CURLOPT_RETURNTRANSFER' => 'curl/curl_d.stub', 'CURLOPT_RTSP_CLIENT_CSEQ' => 'curl/curl_d.stub', 'CURLOPT_RTSP_REQUEST' => 'curl/curl_d.stub', 'CURLOPT_RTSP_SERVER_CSEQ' => 'curl/curl_d.stub', 'CURLOPT_RTSP_SESSION_ID' => 'curl/curl_d.stub', 'CURLOPT_RTSP_STREAM_URI' => 'curl/curl_d.stub', 'CURLOPT_RTSP_TRANSPORT' => 'curl/curl_d.stub', 'CURLOPT_SAFE_UPLOAD' => 'curl/curl_d.stub', 'CURLOPT_SASL_AUTHZID' => 'curl/curl_d.stub', 'CURLOPT_SASL_IR' => 'curl/curl_d.stub', 'CURLOPT_SERVICE_NAME' => 'curl/curl_d.stub', 'CURLOPT_SHARE' => 'curl/curl_d.stub', 'CURLOPT_SOCKS5_AUTH' => 'curl/curl_d.stub', 'CURLOPT_SOCKS5_GSSAPI_NEC' => 'curl/curl_d.stub', 'CURLOPT_SOCKS5_GSSAPI_SERVICE' => 'curl/curl_d.stub', 'CURLOPT_SSH_AUTH_TYPES' => 'curl/curl_d.stub', 'CURLOPT_SSH_COMPRESSION' => 'curl/curl_d.stub', 'CURLOPT_SSH_HOSTKEYFUNCTION' => 'curl/curl_d.stub', 'CURLOPT_SSH_HOST_PUBLIC_KEY_MD5' => 'curl/curl_d.stub', 'CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256' => 'curl/curl_d.stub', 'CURLOPT_SSH_KNOWNHOSTS' => 'curl/curl_d.stub', 'CURLOPT_SSH_PRIVATE_KEYFILE' => 'curl/curl_d.stub', 'CURLOPT_SSH_PUBLIC_KEYFILE' => 'curl/curl_d.stub', 'CURLOPT_SSLCERT' => 'curl/curl_d.stub', 'CURLOPT_SSLCERTPASSWD' => 'curl/curl_d.stub', 'CURLOPT_SSLCERTTYPE' => 'curl/curl_d.stub', 'CURLOPT_SSLCERT_BLOB' => 'curl/curl_d.stub', 'CURLOPT_SSLENGINE' => 'curl/curl_d.stub', 'CURLOPT_SSLENGINE_DEFAULT' => 'curl/curl_d.stub', 'CURLOPT_SSLKEY' => 'curl/curl_d.stub', 'CURLOPT_SSLKEYPASSWD' => 'curl/curl_d.stub', 'CURLOPT_SSLKEYTYPE' => 'curl/curl_d.stub', 'CURLOPT_SSLKEY_BLOB' => 'curl/curl_d.stub', 'CURLOPT_SSLVERSION' => 'curl/curl_d.stub', 'CURLOPT_SSL_CIPHER_LIST' => 'curl/curl_d.stub', 'CURLOPT_SSL_EC_CURVES' => 'curl/curl_d.stub', 'CURLOPT_SSL_ENABLE_ALPN' => 'curl/curl_d.stub', 'CURLOPT_SSL_ENABLE_NPN' => 'curl/curl_d.stub', 'CURLOPT_SSL_FALSESTART' => 'curl/curl_d.stub', 'CURLOPT_SSL_OPTIONS' => 'curl/curl_d.stub', 'CURLOPT_SSL_SESSIONID_CACHE' => 'curl/curl_d.stub', 'CURLOPT_SSL_VERIFYHOST' => 'curl/curl_d.stub', 'CURLOPT_SSL_VERIFYPEER' => 'curl/curl_d.stub', 'CURLOPT_SSL_VERIFYSTATUS' => 'curl/curl_d.stub', 'CURLOPT_STDERR' => 'curl/curl_d.stub', 'CURLOPT_STREAM_WEIGHT' => 'curl/curl_d.stub', 'CURLOPT_SUPPRESS_CONNECT_HEADERS' => 'curl/curl_d.stub', 'CURLOPT_TCP_FASTOPEN' => 'curl/curl_d.stub', 'CURLOPT_TCP_KEEPALIVE' => 'curl/curl_d.stub', 'CURLOPT_TCP_KEEPCNT' => 'curl/curl_d.stub', 'CURLOPT_TCP_KEEPIDLE' => 'curl/curl_d.stub', 'CURLOPT_TCP_KEEPINTVL' => 'curl/curl_d.stub', 'CURLOPT_TCP_NODELAY' => 'curl/curl_d.stub', 'CURLOPT_TELNETOPTIONS' => 'curl/curl_d.stub', 'CURLOPT_TFTP_BLKSIZE' => 'curl/curl_d.stub', 'CURLOPT_TFTP_NO_OPTIONS' => 'curl/curl_d.stub', 'CURLOPT_TIMECONDITION' => 'curl/curl_d.stub', 'CURLOPT_TIMEOUT' => 'curl/curl_d.stub', 'CURLOPT_TIMEOUT_MS' => 'curl/curl_d.stub', 'CURLOPT_TIMEVALUE' => 'curl/curl_d.stub', 'CURLOPT_TIMEVALUE_LARGE' => 'curl/curl_d.stub', 'CURLOPT_TLS13_CIPHERS' => 'curl/curl_d.stub', 'CURLOPT_TLSAUTH_PASSWORD' => 'curl/curl_d.stub', 'CURLOPT_TLSAUTH_TYPE' => 'curl/curl_d.stub', 'CURLOPT_TLSAUTH_USERNAME' => 'curl/curl_d.stub', 'CURLOPT_TRANSFERTEXT' => 'curl/curl_d.stub', 'CURLOPT_TRANSFER_ENCODING' => 'curl/curl_d.stub', 'CURLOPT_UNIX_SOCKET_PATH' => 'curl/curl_d.stub', 'CURLOPT_UNRESTRICTED_AUTH' => 'curl/curl_d.stub', 'CURLOPT_UPKEEP_INTERVAL_MS' => 'curl/curl_d.stub', 'CURLOPT_UPLOAD' => 'curl/curl_d.stub', 'CURLOPT_UPLOAD_BUFFERSIZE' => 'curl/curl_d.stub', 'CURLOPT_URL' => 'curl/curl_d.stub', 'CURLOPT_USERAGENT' => 'curl/curl_d.stub', 'CURLOPT_USERNAME' => 'curl/curl_d.stub', 'CURLOPT_USERPWD' => 'curl/curl_d.stub', 'CURLOPT_USE_SSL' => 'curl/curl_d.stub', 'CURLOPT_VERBOSE' => 'curl/curl_d.stub', 'CURLOPT_WILDCARDMATCH' => 'curl/curl_d.stub', 'CURLOPT_WRITEFUNCTION' => 'curl/curl_d.stub', 'CURLOPT_WRITEHEADER' => 'curl/curl_d.stub', 'CURLOPT_WS_OPTIONS' => 'curl/curl_d.stub', 'CURLOPT_XFERINFOFUNCTION' => 'curl/curl_d.stub', 'CURLOPT_XOAUTH2_BEARER' => 'curl/curl_d.stub', 'CURLPAUSE_ALL' => 'curl/curl_d.stub', 'CURLPAUSE_CONT' => 'curl/curl_d.stub', 'CURLPAUSE_RECV' => 'curl/curl_d.stub', 'CURLPAUSE_RECV_CONT' => 'curl/curl_d.stub', 'CURLPAUSE_SEND' => 'curl/curl_d.stub', 'CURLPAUSE_SEND_CONT' => 'curl/curl_d.stub', 'CURLPIPE_HTTP1' => 'curl/curl_d.stub', 'CURLPIPE_MULTIPLEX' => 'curl/curl_d.stub', 'CURLPIPE_NOTHING' => 'curl/curl_d.stub', 'CURLPROTO_ALL' => 'curl/curl_d.stub', 'CURLPROTO_DICT' => 'curl/curl_d.stub', 'CURLPROTO_FILE' => 'curl/curl_d.stub', 'CURLPROTO_FTP' => 'curl/curl_d.stub', 'CURLPROTO_FTPS' => 'curl/curl_d.stub', 'CURLPROTO_GOPHER' => 'curl/curl_d.stub', 'CURLPROTO_HTTP' => 'curl/curl_d.stub', 'CURLPROTO_HTTPS' => 'curl/curl_d.stub', 'CURLPROTO_IMAP' => 'curl/curl_d.stub', 'CURLPROTO_IMAPS' => 'curl/curl_d.stub', 'CURLPROTO_LDAP' => 'curl/curl_d.stub', 'CURLPROTO_LDAPS' => 'curl/curl_d.stub', 'CURLPROTO_MQTT' => 'curl/curl_d.stub', 'CURLPROTO_POP3' => 'curl/curl_d.stub', 'CURLPROTO_POP3S' => 'curl/curl_d.stub', 'CURLPROTO_RTMP' => 'curl/curl_d.stub', 'CURLPROTO_RTMPE' => 'curl/curl_d.stub', 'CURLPROTO_RTMPS' => 'curl/curl_d.stub', 'CURLPROTO_RTMPT' => 'curl/curl_d.stub', 'CURLPROTO_RTMPTE' => 'curl/curl_d.stub', 'CURLPROTO_RTMPTS' => 'curl/curl_d.stub', 'CURLPROTO_RTSP' => 'curl/curl_d.stub', 'CURLPROTO_SCP' => 'curl/curl_d.stub', 'CURLPROTO_SFTP' => 'curl/curl_d.stub', 'CURLPROTO_SMB' => 'curl/curl_d.stub', 'CURLPROTO_SMBS' => 'curl/curl_d.stub', 'CURLPROTO_SMTP' => 'curl/curl_d.stub', 'CURLPROTO_SMTPS' => 'curl/curl_d.stub', 'CURLPROTO_TELNET' => 'curl/curl_d.stub', 'CURLPROTO_TFTP' => 'curl/curl_d.stub', 'CURLPROXY_HTTP' => 'curl/curl_d.stub', 'CURLPROXY_HTTPS' => 'curl/curl_d.stub', 'CURLPROXY_HTTP_1_0' => 'curl/curl_d.stub', 'CURLPROXY_SOCKS4' => 'curl/curl_d.stub', 'CURLPROXY_SOCKS4A' => 'curl/curl_d.stub', 'CURLPROXY_SOCKS5' => 'curl/curl_d.stub', 'CURLPROXY_SOCKS5_HOSTNAME' => 'curl/curl_d.stub', 'CURLPX_BAD_ADDRESS_TYPE' => 'curl/curl_d.stub', 'CURLPX_BAD_VERSION' => 'curl/curl_d.stub', 'CURLPX_CLOSED' => 'curl/curl_d.stub', 'CURLPX_GSSAPI' => 'curl/curl_d.stub', 'CURLPX_GSSAPI_PERMSG' => 'curl/curl_d.stub', 'CURLPX_GSSAPI_PROTECTION' => 'curl/curl_d.stub', 'CURLPX_IDENTD' => 'curl/curl_d.stub', 'CURLPX_IDENTD_DIFFER' => 'curl/curl_d.stub', 'CURLPX_LONG_HOSTNAME' => 'curl/curl_d.stub', 'CURLPX_LONG_PASSWD' => 'curl/curl_d.stub', 'CURLPX_LONG_USER' => 'curl/curl_d.stub', 'CURLPX_NO_AUTH' => 'curl/curl_d.stub', 'CURLPX_OK' => 'curl/curl_d.stub', 'CURLPX_RECV_ADDRESS' => 'curl/curl_d.stub', 'CURLPX_RECV_AUTH' => 'curl/curl_d.stub', 'CURLPX_RECV_CONNECT' => 'curl/curl_d.stub', 'CURLPX_RECV_REQACK' => 'curl/curl_d.stub', 'CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED' => 'curl/curl_d.stub', 'CURLPX_REPLY_COMMAND_NOT_SUPPORTED' => 'curl/curl_d.stub', 'CURLPX_REPLY_CONNECTION_REFUSED' => 'curl/curl_d.stub', 'CURLPX_REPLY_GENERAL_SERVER_FAILURE' => 'curl/curl_d.stub', 'CURLPX_REPLY_HOST_UNREACHABLE' => 'curl/curl_d.stub', 'CURLPX_REPLY_NETWORK_UNREACHABLE' => 'curl/curl_d.stub', 'CURLPX_REPLY_NOT_ALLOWED' => 'curl/curl_d.stub', 'CURLPX_REPLY_TTL_EXPIRED' => 'curl/curl_d.stub', 'CURLPX_REPLY_UNASSIGNED' => 'curl/curl_d.stub', 'CURLPX_REQUEST_FAILED' => 'curl/curl_d.stub', 'CURLPX_RESOLVE_HOST' => 'curl/curl_d.stub', 'CURLPX_SEND_AUTH' => 'curl/curl_d.stub', 'CURLPX_SEND_CONNECT' => 'curl/curl_d.stub', 'CURLPX_SEND_REQUEST' => 'curl/curl_d.stub', 'CURLPX_UNKNOWN_FAIL' => 'curl/curl_d.stub', 'CURLPX_UNKNOWN_MODE' => 'curl/curl_d.stub', 'CURLPX_USER_REJECTED' => 'curl/curl_d.stub', 'CURLSHOPT_NONE' => 'curl/curl_d.stub', 'CURLSHOPT_SHARE' => 'curl/curl_d.stub', 'CURLSHOPT_UNSHARE' => 'curl/curl_d.stub', 'CURLSSH_AUTH_AGENT' => 'curl/curl_d.stub', 'CURLSSH_AUTH_ANY' => 'curl/curl_d.stub', 'CURLSSH_AUTH_DEFAULT' => 'curl/curl_d.stub', 'CURLSSH_AUTH_GSSAPI' => 'curl/curl_d.stub', 'CURLSSH_AUTH_HOST' => 'curl/curl_d.stub', 'CURLSSH_AUTH_KEYBOARD' => 'curl/curl_d.stub', 'CURLSSH_AUTH_NONE' => 'curl/curl_d.stub', 'CURLSSH_AUTH_PASSWORD' => 'curl/curl_d.stub', 'CURLSSH_AUTH_PUBLICKEY' => 'curl/curl_d.stub', 'CURLSSLOPT_ALLOW_BEAST' => 'curl/curl_d.stub', 'CURLSSLOPT_AUTO_CLIENT_CERT' => 'curl/curl_d.stub', 'CURLSSLOPT_NATIVE_CA' => 'curl/curl_d.stub', 'CURLSSLOPT_NO_PARTIALCHAIN' => 'curl/curl_d.stub', 'CURLSSLOPT_NO_REVOKE' => 'curl/curl_d.stub', 'CURLSSLOPT_REVOKE_BEST_EFFORT' => 'curl/curl_d.stub', 'CURLUSESSL_ALL' => 'curl/curl_d.stub', 'CURLUSESSL_CONTROL' => 'curl/curl_d.stub', 'CURLUSESSL_NONE' => 'curl/curl_d.stub', 'CURLUSESSL_TRY' => 'curl/curl_d.stub', 'CURLVERSION_NOW' => 'curl/curl_d.stub', 'CURLWS_RAW_MODE' => 'curl/curl_d.stub', 'CURL_FNMATCHFUNC_FAIL' => 'curl/curl_d.stub', 'CURL_FNMATCHFUNC_MATCH' => 'curl/curl_d.stub', 'CURL_FNMATCHFUNC_NOMATCH' => 'curl/curl_d.stub', 'CURL_HTTP_VERSION_1_0' => 'curl/curl_d.stub', 'CURL_HTTP_VERSION_1_1' => 'curl/curl_d.stub', 'CURL_HTTP_VERSION_2' => 'curl/curl_d.stub', 'CURL_HTTP_VERSION_2TLS' => 'curl/curl_d.stub', 'CURL_HTTP_VERSION_2_0' => 'curl/curl_d.stub', 'CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE' => 'curl/curl_d.stub', 'CURL_HTTP_VERSION_3' => 'curl/curl_d.stub', 'CURL_HTTP_VERSION_3ONLY' => 'curl/curl_d.stub', 'CURL_HTTP_VERSION_NONE' => 'curl/curl_d.stub', 'CURL_IPRESOLVE_V4' => 'curl/curl_d.stub', 'CURL_IPRESOLVE_V6' => 'curl/curl_d.stub', 'CURL_IPRESOLVE_WHATEVER' => 'curl/curl_d.stub', 'CURL_LOCK_DATA_CONNECT' => 'curl/curl_d.stub', 'CURL_LOCK_DATA_COOKIE' => 'curl/curl_d.stub', 'CURL_LOCK_DATA_DNS' => 'curl/curl_d.stub', 'CURL_LOCK_DATA_PSL' => 'curl/curl_d.stub', 'CURL_LOCK_DATA_SSL_SESSION' => 'curl/curl_d.stub', 'CURL_MAX_READ_SIZE' => 'curl/curl_d.stub', 'CURL_NETRC_IGNORED' => 'curl/curl_d.stub', 'CURL_NETRC_OPTIONAL' => 'curl/curl_d.stub', 'CURL_NETRC_REQUIRED' => 'curl/curl_d.stub', 'CURL_PREREQFUNC_ABORT' => 'curl/curl_d.stub', 'CURL_PREREQFUNC_OK' => 'curl/curl_d.stub', 'CURL_PUSH_DENY' => 'curl/curl_d.stub', 'CURL_PUSH_OK' => 'curl/curl_d.stub', 'CURL_READFUNC_PAUSE' => 'curl/curl_d.stub', 'CURL_REDIR_POST_301' => 'curl/curl_d.stub', 'CURL_REDIR_POST_302' => 'curl/curl_d.stub', 'CURL_REDIR_POST_303' => 'curl/curl_d.stub', 'CURL_REDIR_POST_ALL' => 'curl/curl_d.stub', 'CURL_RTSPREQ_ANNOUNCE' => 'curl/curl_d.stub', 'CURL_RTSPREQ_DESCRIBE' => 'curl/curl_d.stub', 'CURL_RTSPREQ_GET_PARAMETER' => 'curl/curl_d.stub', 'CURL_RTSPREQ_OPTIONS' => 'curl/curl_d.stub', 'CURL_RTSPREQ_PAUSE' => 'curl/curl_d.stub', 'CURL_RTSPREQ_PLAY' => 'curl/curl_d.stub', 'CURL_RTSPREQ_RECEIVE' => 'curl/curl_d.stub', 'CURL_RTSPREQ_RECORD' => 'curl/curl_d.stub', 'CURL_RTSPREQ_SETUP' => 'curl/curl_d.stub', 'CURL_RTSPREQ_SET_PARAMETER' => 'curl/curl_d.stub', 'CURL_RTSPREQ_TEARDOWN' => 'curl/curl_d.stub', 'CURL_SSLVERSION_DEFAULT' => 'curl/curl_d.stub', 'CURL_SSLVERSION_MAX_DEFAULT' => 'curl/curl_d.stub', 'CURL_SSLVERSION_MAX_NONE' => 'curl/curl_d.stub', 'CURL_SSLVERSION_MAX_TLSv1_0' => 'curl/curl_d.stub', 'CURL_SSLVERSION_MAX_TLSv1_1' => 'curl/curl_d.stub', 'CURL_SSLVERSION_MAX_TLSv1_2' => 'curl/curl_d.stub', 'CURL_SSLVERSION_MAX_TLSv1_3' => 'curl/curl_d.stub', 'CURL_SSLVERSION_SSLv2' => 'curl/curl_d.stub', 'CURL_SSLVERSION_SSLv3' => 'curl/curl_d.stub', 'CURL_SSLVERSION_TLSv1' => 'curl/curl_d.stub', 'CURL_SSLVERSION_TLSv1_0' => 'curl/curl_d.stub', 'CURL_SSLVERSION_TLSv1_1' => 'curl/curl_d.stub', 'CURL_SSLVERSION_TLSv1_2' => 'curl/curl_d.stub', 'CURL_SSLVERSION_TLSv1_3' => 'curl/curl_d.stub', 'CURL_TIMECOND_IFMODSINCE' => 'curl/curl_d.stub', 'CURL_TIMECOND_IFUNMODSINCE' => 'curl/curl_d.stub', 'CURL_TIMECOND_LASTMOD' => 'curl/curl_d.stub', 'CURL_TIMECOND_NONE' => 'curl/curl_d.stub', 'CURL_TLSAUTH_SRP' => 'curl/curl_d.stub', 'CURL_VERSION_ALTSVC' => 'curl/curl_d.stub', 'CURL_VERSION_ASYNCHDNS' => 'curl/curl_d.stub', 'CURL_VERSION_BROTLI' => 'curl/curl_d.stub', 'CURL_VERSION_CONV' => 'curl/curl_d.stub', 'CURL_VERSION_CURLDEBUG' => 'curl/curl_d.stub', 'CURL_VERSION_DEBUG' => 'curl/curl_d.stub', 'CURL_VERSION_GSASL' => 'curl/curl_d.stub', 'CURL_VERSION_GSSAPI' => 'curl/curl_d.stub', 'CURL_VERSION_GSSNEGOTIATE' => 'curl/curl_d.stub', 'CURL_VERSION_HSTS' => 'curl/curl_d.stub', 'CURL_VERSION_HTTP2' => 'curl/curl_d.stub', 'CURL_VERSION_HTTP3' => 'curl/curl_d.stub', 'CURL_VERSION_HTTPS_PROXY' => 'curl/curl_d.stub', 'CURL_VERSION_IDN' => 'curl/curl_d.stub', 'CURL_VERSION_IPV6' => 'curl/curl_d.stub', 'CURL_VERSION_KERBEROS4' => 'curl/curl_d.stub', 'CURL_VERSION_KERBEROS5' => 'curl/curl_d.stub', 'CURL_VERSION_LARGEFILE' => 'curl/curl_d.stub', 'CURL_VERSION_LIBZ' => 'curl/curl_d.stub', 'CURL_VERSION_MULTI_SSL' => 'curl/curl_d.stub', 'CURL_VERSION_NTLM' => 'curl/curl_d.stub', 'CURL_VERSION_NTLM_WB' => 'curl/curl_d.stub', 'CURL_VERSION_PSL' => 'curl/curl_d.stub', 'CURL_VERSION_SPNEGO' => 'curl/curl_d.stub', 'CURL_VERSION_SSL' => 'curl/curl_d.stub', 'CURL_VERSION_SSPI' => 'curl/curl_d.stub', 'CURL_VERSION_TLSAUTH_SRP' => 'curl/curl_d.stub', 'CURL_VERSION_UNICODE' => 'curl/curl_d.stub', 'CURL_VERSION_UNIX_SOCKETS' => 'curl/curl_d.stub', 'CURL_VERSION_ZSTD' => 'curl/curl_d.stub', 'CURL_WRITEFUNC_PAUSE' => 'curl/curl_d.stub', 'CURRENCY_SYMBOL' => 'standard/standard_defines.stub', 'CYAN' => 'winbinder/winbinder.stub', 'Calendar' => 'winbinder/winbinder.stub', 'CheckBox' => 'winbinder/winbinder.stub', 'ComboBox' => 'winbinder/winbinder.stub', 'DARKBLUE' => 'winbinder/winbinder.stub', 'DARKCYAN' => 'winbinder/winbinder.stub', 'DARKGRAY' => 'winbinder/winbinder.stub', 'DARKGREEN' => 'winbinder/winbinder.stub', 'DARKMAGENTA' => 'winbinder/winbinder.stub', 'DARKRED' => 'winbinder/winbinder.stub', 'DARKYELLOW' => 'winbinder/winbinder.stub', 'DATE_ATOM' => 'date/date_d.stub', 'DATE_COOKIE' => 'date/date_d.stub', 'DATE_ISO8601' => 'date/date_d.stub', 'DATE_ISO8601_EXPANDED' => 'date/date_d.stub', 'DATE_RFC1036' => 'date/date_d.stub', 'DATE_RFC1123' => 'date/date_d.stub', 'DATE_RFC2822' => 'date/date_d.stub', 'DATE_RFC3339' => 'date/date_d.stub', 'DATE_RFC3339_EXTENDED' => 'date/date_d.stub', 'DATE_RFC7231' => 'date/date_d.stub', 'DATE_RFC822' => 'date/date_d.stub', 'DATE_RFC850' => 'date/date_d.stub', 'DATE_RSS' => 'date/date_d.stub', 'DATE_W3C' => 'date/date_d.stub', 'DAY_1' => 'standard/standard_defines.stub', 'DAY_2' => 'standard/standard_defines.stub', 'DAY_3' => 'standard/standard_defines.stub', 'DAY_4' => 'standard/standard_defines.stub', 'DAY_5' => 'standard/standard_defines.stub', 'DAY_6' => 'standard/standard_defines.stub', 'DAY_7' => 'standard/standard_defines.stub', 'DB2_AUTOCOMMIT_OFF' => 'ibm_db2/ibm_db2.stub', 'DB2_AUTOCOMMIT_ON' => 'ibm_db2/ibm_db2.stub', 'DB2_BINARY' => 'ibm_db2/ibm_db2.stub', 'DB2_CASE_LOWER' => 'ibm_db2/ibm_db2.stub', 'DB2_CASE_NATURAL' => 'ibm_db2/ibm_db2.stub', 'DB2_CASE_UPPER' => 'ibm_db2/ibm_db2.stub', 'DB2_CHAR' => 'ibm_db2/ibm_db2.stub', 'DB2_CONVERT' => 'ibm_db2/ibm_db2.stub', 'DB2_DEFERRED_PREPARE_OFF' => 'ibm_db2/ibm_db2.stub', 'DB2_DEFERRED_PREPARE_ON' => 'ibm_db2/ibm_db2.stub', 'DB2_DOUBLE' => 'ibm_db2/ibm_db2.stub', 'DB2_FORWARD_ONLY' => 'ibm_db2/ibm_db2.stub', 'DB2_LONG' => 'ibm_db2/ibm_db2.stub', 'DB2_PARAM_FILE' => 'ibm_db2/ibm_db2.stub', 'DB2_PARAM_IN' => 'ibm_db2/ibm_db2.stub', 'DB2_PARAM_INOUT' => 'ibm_db2/ibm_db2.stub', 'DB2_PARAM_OUT' => 'ibm_db2/ibm_db2.stub', 'DB2_PASSTHRU' => 'ibm_db2/ibm_db2.stub', 'DB2_SCROLLABLE' => 'ibm_db2/ibm_db2.stub', 'DB2_XML' => 'ibm_db2/ibm_db2.stub', 'DBA_LMDB_NO_SUB_DIR' => 'dba/dba.stub', 'DBA_LMDB_USE_SUB_DIR' => 'dba/dba.stub', 'DEBUG_BACKTRACE_IGNORE_ARGS' => 'Core/Core_d.stub', 'DEBUG_BACKTRACE_PROVIDE_OBJECT' => 'Core/Core_d.stub', 'DECIMAL_POINT' => 'standard/standard_defines.stub', 'DEFAULT_INCLUDE_PATH' => 'Core/Core_d.stub', 'DIRECTORY_SEPARATOR' => 'standard/standard_defines.stub', 'DISP_E_DIVBYZERO' => 'com_dotnet/com_dotnet.stub', 'DISP_E_OVERFLOW' => 'com_dotnet/com_dotnet.stub', 'DNS_A' => 'standard/standard_defines.stub', 'DNS_A6' => 'standard/standard_defines.stub', 'DNS_AAAA' => 'standard/standard_defines.stub', 'DNS_ALL' => 'standard/standard_defines.stub', 'DNS_ANY' => 'standard/standard_defines.stub', 'DNS_CAA' => 'standard/standard_defines.stub', 'DNS_CNAME' => 'standard/standard_defines.stub', 'DNS_HINFO' => 'standard/standard_defines.stub', 'DNS_MX' => 'standard/standard_defines.stub', 'DNS_NAPTR' => 'standard/standard_defines.stub', 'DNS_NS' => 'standard/standard_defines.stub', 'DNS_PTR' => 'standard/standard_defines.stub', 'DNS_SOA' => 'standard/standard_defines.stub', 'DNS_SRV' => 'standard/standard_defines.stub', 'DNS_TXT' => 'standard/standard_defines.stub', 'DOMSTRING_SIZE_ERR' => 'dom/dom.stub', 'DOM_HIERARCHY_REQUEST_ERR' => 'dom/dom.stub', 'DOM_INDEX_SIZE_ERR' => 'dom/dom.stub', 'DOM_INUSE_ATTRIBUTE_ERR' => 'dom/dom.stub', 'DOM_INVALID_ACCESS_ERR' => 'dom/dom.stub', 'DOM_INVALID_CHARACTER_ERR' => 'dom/dom.stub', 'DOM_INVALID_MODIFICATION_ERR' => 'dom/dom.stub', 'DOM_INVALID_STATE_ERR' => 'dom/dom.stub', 'DOM_NAMESPACE_ERR' => 'dom/dom.stub', 'DOM_NOT_FOUND_ERR' => 'dom/dom.stub', 'DOM_NOT_SUPPORTED_ERR' => 'dom/dom.stub', 'DOM_NO_DATA_ALLOWED_ERR' => 'dom/dom.stub', 'DOM_NO_MODIFICATION_ALLOWED_ERR' => 'dom/dom.stub', 'DOM_PHP_ERR' => 'dom/dom.stub', 'DOM_SYNTAX_ERR' => 'dom/dom.stub', 'DOM_VALIDATION_ERR' => 'dom/dom.stub', 'DOM_WRONG_DOCUMENT_ERR' => 'dom/dom.stub', 'D_FMT' => 'standard/standard_defines.stub', 'D_T_FMT' => 'standard/standard_defines.stub', 'Dom\\HIERARCHY_REQUEST_ERR' => 'dom/dom_n.stub', 'Dom\\HTML_NO_DEFAULT_NS' => 'dom/dom_n.stub', 'Dom\\INDEX_SIZE_ERR' => 'dom/dom_n.stub', 'Dom\\INUSE_ATTRIBUTE_ERR' => 'dom/dom_n.stub', 'Dom\\INVALID_CHARACTER_ERR' => 'dom/dom_n.stub', 'Dom\\INVALID_MODIFICATION_ERR' => 'dom/dom_n.stub', 'Dom\\INVALID_STATE_ERR' => 'dom/dom_n.stub', 'Dom\\NAMESPACE_ERR' => 'dom/dom_n.stub', 'Dom\\NOT_FOUND_ERR' => 'dom/dom_n.stub', 'Dom\\NOT_SUPPORTED_ERR' => 'dom/dom_n.stub', 'Dom\\NO_DATA_ALLOWED_ERR' => 'dom/dom_n.stub', 'Dom\\NO_MODIFICATION_ALLOWED_ERR' => 'dom/dom_n.stub', 'Dom\\STRING_SIZE_ERR' => 'dom/dom_n.stub', 'Dom\\SYNTAX_ERR' => 'dom/dom_n.stub', 'Dom\\VALIDATION_ERR' => 'dom/dom_n.stub', 'Dom\\WRONG_DOCUMENT_ERR' => 'dom/dom_n.stub', 'EIO_DEBUG' => 'eio/eio.stub', 'EIO_DT_BLK' => 'eio/eio.stub', 'EIO_DT_CHR' => 'eio/eio.stub', 'EIO_DT_CMP' => 'eio/eio.stub', 'EIO_DT_DIR' => 'eio/eio.stub', 'EIO_DT_DOOR' => 'eio/eio.stub', 'EIO_DT_FIFO' => 'eio/eio.stub', 'EIO_DT_LNK' => 'eio/eio.stub', 'EIO_DT_MAX' => 'eio/eio.stub', 'EIO_DT_MPB' => 'eio/eio.stub', 'EIO_DT_MPC' => 'eio/eio.stub', 'EIO_DT_NAM' => 'eio/eio.stub', 'EIO_DT_NWK' => 'eio/eio.stub', 'EIO_DT_REG' => 'eio/eio.stub', 'EIO_DT_SOCK' => 'eio/eio.stub', 'EIO_DT_UNKNOWN' => 'eio/eio.stub', 'EIO_DT_WHT' => 'eio/eio.stub', 'EIO_FALLOC_FL_KEEP_SIZE' => 'eio/eio.stub', 'EIO_O_APPEND' => 'eio/eio.stub', 'EIO_O_CREAT' => 'eio/eio.stub', 'EIO_O_EXCL' => 'eio/eio.stub', 'EIO_O_FSYNC' => 'eio/eio.stub', 'EIO_O_NONBLOCK' => 'eio/eio.stub', 'EIO_O_RDONLY' => 'eio/eio.stub', 'EIO_O_RDWR' => 'eio/eio.stub', 'EIO_O_TRUNC' => 'eio/eio.stub', 'EIO_O_WRONLY' => 'eio/eio.stub', 'EIO_PRI_DEFAULT' => 'eio/eio.stub', 'EIO_PRI_MAX' => 'eio/eio.stub', 'EIO_PRI_MIN' => 'eio/eio.stub', 'EIO_READDIR_DENTS' => 'eio/eio.stub', 'EIO_READDIR_DIRS_FIRST' => 'eio/eio.stub', 'EIO_READDIR_FOUND_UNKNOWN' => 'eio/eio.stub', 'EIO_READDIR_STAT_ORDER' => 'eio/eio.stub', 'EIO_SEEK_CUR' => 'eio/eio.stub', 'EIO_SEEK_END' => 'eio/eio.stub', 'EIO_SEEK_SET' => 'eio/eio.stub', 'EIO_SYNC_FILE_RANGE_WAIT_AFTER' => 'eio/eio.stub', 'EIO_SYNC_FILE_RANGE_WAIT_BEFORE' => 'eio/eio.stub', 'EIO_SYNC_FILE_RANGE_WRITE' => 'eio/eio.stub', 'EIO_S_IFBLK' => 'eio/eio.stub', 'EIO_S_IFCHR' => 'eio/eio.stub', 'EIO_S_IFIFO' => 'eio/eio.stub', 'EIO_S_IFREG' => 'eio/eio.stub', 'EIO_S_IFSOCK' => 'eio/eio.stub', 'EIO_S_IRGRP' => 'eio/eio.stub', 'EIO_S_IROTH' => 'eio/eio.stub', 'EIO_S_IRUSR' => 'eio/eio.stub', 'EIO_S_IWGRP' => 'eio/eio.stub', 'EIO_S_IWOTH' => 'eio/eio.stub', 'EIO_S_IWUSR' => 'eio/eio.stub', 'EIO_S_IXGRP' => 'eio/eio.stub', 'EIO_S_IXOTH' => 'eio/eio.stub', 'EIO_S_IXUSR' => 'eio/eio.stub', 'ENC7BIT' => 'imap/imap.stub', 'ENC8BIT' => 'imap/imap.stub', 'ENCBASE64' => 'imap/imap.stub', 'ENCBINARY' => 'imap/imap.stub', 'ENCHANT_ISPELL' => 'enchant/enchant.stub', 'ENCHANT_MYSPELL' => 'enchant/enchant.stub', 'ENCOTHER' => 'imap/imap.stub', 'ENCQUOTEDPRINTABLE' => 'imap/imap.stub', 'ENT_COMPAT' => 'standard/standard_defines.stub', 'ENT_DISALLOWED' => 'standard/standard_defines.stub', 'ENT_HTML401' => 'standard/standard_defines.stub', 'ENT_HTML5' => 'standard/standard_defines.stub', 'ENT_IGNORE' => 'standard/standard_defines.stub', 'ENT_NOQUOTES' => 'standard/standard_defines.stub', 'ENT_QUOTES' => 'standard/standard_defines.stub', 'ENT_SUBSTITUTE' => 'standard/standard_defines.stub', 'ENT_XHTML' => 'standard/standard_defines.stub', 'ENT_XML1' => 'standard/standard_defines.stub', 'ERA' => 'standard/standard_defines.stub', 'ERA_D_FMT' => 'standard/standard_defines.stub', 'ERA_D_T_FMT' => 'standard/standard_defines.stub', 'ERA_T_FMT' => 'standard/standard_defines.stub', 'ERA_YEAR' => 'standard/standard_defines.stub', 'EVBUFFER_EOF' => 'libevent/libevent.stub', 'EVBUFFER_ERROR' => 'libevent/libevent.stub', 'EVBUFFER_READ' => 'libevent/libevent.stub', 'EVBUFFER_TIMEOUT' => 'libevent/libevent.stub', 'EVBUFFER_WRITE' => 'libevent/libevent.stub', 'EVLOOP_NONBLOCK' => 'libevent/libevent.stub', 'EVLOOP_ONCE' => 'libevent/libevent.stub', 'EV_PERSIST' => 'libevent/libevent.stub', 'EV_READ' => 'libevent/libevent.stub', 'EV_SIGNAL' => 'libevent/libevent.stub', 'EV_TIMEOUT' => 'libevent/libevent.stub', 'EV_WRITE' => 'libevent/libevent.stub', 'EXIF_USE_MBSTRING' => 'exif/exif.stub', 'EXP_EOF' => 'expect/expect.stub', 'EXP_EXACT' => 'expect/expect.stub', 'EXP_FULLBUFFER' => 'expect/expect.stub', 'EXP_GLOB' => 'expect/expect.stub', 'EXP_REGEXP' => 'expect/expect.stub', 'EXP_TIMEOUT' => 'expect/expect.stub', 'EXTR_IF_EXISTS' => 'standard/standard_defines.stub', 'EXTR_OVERWRITE' => 'standard/standard_defines.stub', 'EXTR_PREFIX_ALL' => 'standard/standard_defines.stub', 'EXTR_PREFIX_IF_EXISTS' => 'standard/standard_defines.stub', 'EXTR_PREFIX_INVALID' => 'standard/standard_defines.stub', 'EXTR_PREFIX_SAME' => 'standard/standard_defines.stub', 'EXTR_REFS' => 'standard/standard_defines.stub', 'EXTR_SKIP' => 'standard/standard_defines.stub', 'E_ALL' => 'Core/Core_d.stub', 'E_COMPILE_ERROR' => 'Core/Core_d.stub', 'E_COMPILE_WARNING' => 'Core/Core_d.stub', 'E_CORE_ERROR' => 'Core/Core_d.stub', 'E_CORE_WARNING' => 'Core/Core_d.stub', 'E_DEPRECATED' => 'Core/Core_d.stub', 'E_ERROR' => 'Core/Core_d.stub', 'E_NOTICE' => 'Core/Core_d.stub', 'E_PARSE' => 'Core/Core_d.stub', 'E_RECOVERABLE_ERROR' => 'Core/Core_d.stub', 'E_STRICT' => 'Core/Core_d.stub', 'E_USER_DEPRECATED' => 'Core/Core_d.stub', 'E_USER_ERROR' => 'Core/Core_d.stub', 'E_USER_NOTICE' => 'Core/Core_d.stub', 'E_USER_WARNING' => 'Core/Core_d.stub', 'E_WARNING' => 'Core/Core_d.stub', 'EditBox' => 'winbinder/winbinder.stub', 'FANN_COS' => 'fann/fann.stub', 'FANN_COS_SYMMETRIC' => 'fann/fann.stub', 'FANN_ELLIOT' => 'fann/fann.stub', 'FANN_ELLIOT_SYMMETRIC' => 'fann/fann.stub', 'FANN_ERRORFUNC_LINEAR' => 'fann/fann.stub', 'FANN_ERRORFUNC_TANH' => 'fann/fann.stub', 'FANN_E_CANT_ALLOCATE_MEM' => 'fann/fann.stub', 'FANN_E_CANT_OPEN_CONFIG_R' => 'fann/fann.stub', 'FANN_E_CANT_OPEN_CONFIG_W' => 'fann/fann.stub', 'FANN_E_CANT_OPEN_TD_R' => 'fann/fann.stub', 'FANN_E_CANT_OPEN_TD_W' => 'fann/fann.stub', 'FANN_E_CANT_READ_CONFIG' => 'fann/fann.stub', 'FANN_E_CANT_READ_CONNECTIONS' => 'fann/fann.stub', 'FANN_E_CANT_READ_NEURON' => 'fann/fann.stub', 'FANN_E_CANT_READ_TD' => 'fann/fann.stub', 'FANN_E_CANT_TRAIN_ACTIVATION' => 'fann/fann.stub', 'FANN_E_CANT_USE_ACTIVATION' => 'fann/fann.stub', 'FANN_E_CANT_USE_TRAIN_ALG' => 'fann/fann.stub', 'FANN_E_INDEX_OUT_OF_BOUND' => 'fann/fann.stub', 'FANN_E_INPUT_NO_MATCH' => 'fann/fann.stub', 'FANN_E_NO_ERROR' => 'fann/fann.stub', 'FANN_E_OUTPUT_NO_MATCH' => 'fann/fann.stub', 'FANN_E_SCALE_NOT_PRESENT' => 'fann/fann.stub', 'FANN_E_TRAIN_DATA_MISMATCH' => 'fann/fann.stub', 'FANN_E_TRAIN_DATA_SUBSET' => 'fann/fann.stub', 'FANN_E_WRONG_CONFIG_VERSION' => 'fann/fann.stub', 'FANN_E_WRONG_NUM_CONNECTIONS' => 'fann/fann.stub', 'FANN_GAUSSIAN' => 'fann/fann.stub', 'FANN_GAUSSIAN_STEPWISE' => 'fann/fann.stub', 'FANN_GAUSSIAN_SYMMETRIC' => 'fann/fann.stub', 'FANN_LINEAR' => 'fann/fann.stub', 'FANN_LINEAR_PIECE' => 'fann/fann.stub', 'FANN_LINEAR_PIECE_SYMMETRIC' => 'fann/fann.stub', 'FANN_NETTYPE_LAYER' => 'fann/fann.stub', 'FANN_NETTYPE_SHORTCUT' => 'fann/fann.stub', 'FANN_SIGMOID' => 'fann/fann.stub', 'FANN_SIGMOID_STEPWISE' => 'fann/fann.stub', 'FANN_SIGMOID_SYMMETRIC' => 'fann/fann.stub', 'FANN_SIGMOID_SYMMETRIC_STEPWISE' => 'fann/fann.stub', 'FANN_SIN' => 'fann/fann.stub', 'FANN_SIN_SYMMETRIC' => 'fann/fann.stub', 'FANN_STOPFUNC_BIT' => 'fann/fann.stub', 'FANN_STOPFUNC_MSE' => 'fann/fann.stub', 'FANN_THRESHOLD' => 'fann/fann.stub', 'FANN_THRESHOLD_SYMMETRIC' => 'fann/fann.stub', 'FANN_TRAIN_BATCH' => 'fann/fann.stub', 'FANN_TRAIN_INCREMENTAL' => 'fann/fann.stub', 'FANN_TRAIN_QUICKPROP' => 'fann/fann.stub', 'FANN_TRAIN_RPROP' => 'fann/fann.stub', 'FANN_TRAIN_SARPROP' => 'fann/fann.stub', 'FANN_VERSION' => 'fann/fann.stub', 'FILEINFO_APPLE' => 'fileinfo/fileinfo.stub', 'FILEINFO_CONTINUE' => 'fileinfo/fileinfo.stub', 'FILEINFO_DEVICES' => 'fileinfo/fileinfo.stub', 'FILEINFO_EXTENSION' => 'fileinfo/fileinfo.stub', 'FILEINFO_MIME' => 'fileinfo/fileinfo.stub', 'FILEINFO_MIME_ENCODING' => 'fileinfo/fileinfo.stub', 'FILEINFO_MIME_TYPE' => 'fileinfo/fileinfo.stub', 'FILEINFO_NONE' => 'fileinfo/fileinfo.stub', 'FILEINFO_PRESERVE_ATIME' => 'fileinfo/fileinfo.stub', 'FILEINFO_RAW' => 'fileinfo/fileinfo.stub', 'FILEINFO_SYMLINK' => 'fileinfo/fileinfo.stub', 'FILE_APPEND' => 'standard/standard_defines.stub', 'FILE_BINARY' => 'standard/standard_defines.stub', 'FILE_IGNORE_NEW_LINES' => 'standard/standard_defines.stub', 'FILE_NO_DEFAULT_CONTEXT' => 'standard/standard_defines.stub', 'FILE_SKIP_EMPTY_LINES' => 'standard/standard_defines.stub', 'FILE_TEXT' => 'standard/standard_defines.stub', 'FILE_USE_INCLUDE_PATH' => 'standard/standard_defines.stub', 'FILTER_CALLBACK' => 'filter/filter.stub', 'FILTER_DEFAULT' => 'filter/filter.stub', 'FILTER_FLAG_ALLOW_FRACTION' => 'filter/filter.stub', 'FILTER_FLAG_ALLOW_HEX' => 'filter/filter.stub', 'FILTER_FLAG_ALLOW_OCTAL' => 'filter/filter.stub', 'FILTER_FLAG_ALLOW_SCIENTIFIC' => 'filter/filter.stub', 'FILTER_FLAG_ALLOW_THOUSAND' => 'filter/filter.stub', 'FILTER_FLAG_EMAIL_UNICODE' => 'filter/filter.stub', 'FILTER_FLAG_EMPTY_STRING_NULL' => 'filter/filter.stub', 'FILTER_FLAG_ENCODE_AMP' => 'filter/filter.stub', 'FILTER_FLAG_ENCODE_HIGH' => 'filter/filter.stub', 'FILTER_FLAG_ENCODE_LOW' => 'filter/filter.stub', 'FILTER_FLAG_GLOBAL_RANGE' => 'filter/filter.stub', 'FILTER_FLAG_HOSTNAME' => 'filter/filter.stub', 'FILTER_FLAG_HOST_REQUIRED' => 'filter/filter.stub', 'FILTER_FLAG_IPV4' => 'filter/filter.stub', 'FILTER_FLAG_IPV6' => 'filter/filter.stub', 'FILTER_FLAG_NONE' => 'filter/filter.stub', 'FILTER_FLAG_NO_ENCODE_QUOTES' => 'filter/filter.stub', 'FILTER_FLAG_NO_PRIV_RANGE' => 'filter/filter.stub', 'FILTER_FLAG_NO_RES_RANGE' => 'filter/filter.stub', 'FILTER_FLAG_PATH_REQUIRED' => 'filter/filter.stub', 'FILTER_FLAG_QUERY_REQUIRED' => 'filter/filter.stub', 'FILTER_FLAG_SCHEME_REQUIRED' => 'filter/filter.stub', 'FILTER_FLAG_STRIP_BACKTICK' => 'filter/filter.stub', 'FILTER_FLAG_STRIP_HIGH' => 'filter/filter.stub', 'FILTER_FLAG_STRIP_LOW' => 'filter/filter.stub', 'FILTER_FORCE_ARRAY' => 'filter/filter.stub', 'FILTER_NULL_ON_FAILURE' => 'filter/filter.stub', 'FILTER_REQUIRE_ARRAY' => 'filter/filter.stub', 'FILTER_REQUIRE_SCALAR' => 'filter/filter.stub', 'FILTER_SANITIZE_ADD_SLASHES' => 'filter/filter.stub', 'FILTER_SANITIZE_EMAIL' => 'filter/filter.stub', 'FILTER_SANITIZE_ENCODED' => 'filter/filter.stub', 'FILTER_SANITIZE_FULL_SPECIAL_CHARS' => 'filter/filter.stub', 'FILTER_SANITIZE_MAGIC_QUOTES' => 'filter/filter.stub', 'FILTER_SANITIZE_NUMBER_FLOAT' => 'filter/filter.stub', 'FILTER_SANITIZE_NUMBER_INT' => 'filter/filter.stub', 'FILTER_SANITIZE_SPECIAL_CHARS' => 'filter/filter.stub', 'FILTER_SANITIZE_STRING' => 'filter/filter.stub', 'FILTER_SANITIZE_STRIPPED' => 'filter/filter.stub', 'FILTER_SANITIZE_URL' => 'filter/filter.stub', 'FILTER_UNSAFE_RAW' => 'filter/filter.stub', 'FILTER_VALIDATE_BOOL' => 'filter/filter.stub', 'FILTER_VALIDATE_BOOLEAN' => 'filter/filter.stub', 'FILTER_VALIDATE_DOMAIN' => 'filter/filter.stub', 'FILTER_VALIDATE_EMAIL' => 'filter/filter.stub', 'FILTER_VALIDATE_FLOAT' => 'filter/filter.stub', 'FILTER_VALIDATE_INT' => 'filter/filter.stub', 'FILTER_VALIDATE_IP' => 'filter/filter.stub', 'FILTER_VALIDATE_MAC' => 'filter/filter.stub', 'FILTER_VALIDATE_REGEXP' => 'filter/filter.stub', 'FILTER_VALIDATE_URL' => 'filter/filter.stub', 'FNM_CASEFOLD' => 'standard/standard_defines.stub', 'FNM_NOESCAPE' => 'standard/standard_defines.stub', 'FNM_PATHNAME' => 'standard/standard_defines.stub', 'FNM_PERIOD' => 'standard/standard_defines.stub', 'FORCE_DEFLATE' => 'zlib/zlib.stub', 'FORCE_GZIP' => 'zlib/zlib.stub', 'FPE_FLTDIV' => 'pcntl/pcntl.stub', 'FPE_FLTINV' => 'pcntl/pcntl.stub', 'FPE_FLTOVF' => 'pcntl/pcntl.stub', 'FPE_FLTRES' => 'pcntl/pcntl.stub', 'FPE_FLTSUB' => 'pcntl/pcntl.stub', 'FPE_FLTUND' => 'pcntl/pcntl.stub', 'FPE_INTDIV' => 'pcntl/pcntl.stub', 'FPE_INTOVF' => 'pcntl/pcntl.stub', 'FRAC_DIGITS' => 'standard/standard_defines.stub', 'FTA_BOLD' => 'winbinder/winbinder.stub', 'FTA_ITALIC' => 'winbinder/winbinder.stub', 'FTA_NORMAL' => 'winbinder/winbinder.stub', 'FTA_REGULAR' => 'winbinder/winbinder.stub', 'FTA_STRIKEOUT' => 'winbinder/winbinder.stub', 'FTA_UNDERLINE' => 'winbinder/winbinder.stub', 'FTP_ASCII' => 'ftp/ftp.stub', 'FTP_AUTORESUME' => 'ftp/ftp.stub', 'FTP_AUTOSEEK' => 'ftp/ftp.stub', 'FTP_BINARY' => 'ftp/ftp.stub', 'FTP_FAILED' => 'ftp/ftp.stub', 'FTP_FINISHED' => 'ftp/ftp.stub', 'FTP_IMAGE' => 'ftp/ftp.stub', 'FTP_MOREDATA' => 'ftp/ftp.stub', 'FTP_TEXT' => 'ftp/ftp.stub', 'FTP_TIMEOUT_SEC' => 'ftp/ftp.stub', 'FTP_USEPASVADDRESS' => 'ftp/ftp.stub', 'FT_INTERNAL' => 'imap/imap.stub', 'FT_NOT' => 'imap/imap.stub', 'FT_PEEK' => 'imap/imap.stub', 'FT_PREFETCHTEXT' => 'imap/imap.stub', 'FT_UID' => 'imap/imap.stub', 'F_DUPFD' => 'dio/dio_d.stub', 'F_GETFD' => 'dio/dio_d.stub', 'F_GETFL' => 'dio/dio_d.stub', 'F_GETLK' => 'dio/dio_d.stub', 'F_GETOWN' => 'dio/dio_d.stub', 'F_RDLCK' => 'dio/dio_d.stub', 'F_SETFL' => 'dio/dio_d.stub', 'F_SETLK' => 'dio/dio_d.stub', 'F_SETLKW' => 'dio/dio_d.stub', 'F_SETOWN' => 'dio/dio_d.stub', 'F_UNLCK' => 'dio/dio_d.stub', 'F_WRLCK' => 'dio/dio_d.stub', 'Frame' => 'winbinder/winbinder.stub', 'GD_BUNDLED' => 'gd/gd.stub', 'GD_EXTRA_VERSION' => 'gd/gd.stub', 'GD_MAJOR_VERSION' => 'gd/gd.stub', 'GD_MINOR_VERSION' => 'gd/gd.stub', 'GD_RELEASE_VERSION' => 'gd/gd.stub', 'GD_VERSION' => 'gd/gd.stub', 'GEARMAN_ARGS_BUFFER_SIZE' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_ALLOCATED' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_FREE_TASKS' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_NON_BLOCKING' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_NO_NEW' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_STATE_IDLE' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_STATE_NEW' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_STATE_PACKET' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_STATE_SUBMIT' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_TASK_IN_USE' => 'gearman/gearman.stub', 'GEARMAN_CLIENT_UNBUFFERED_RESULT' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_ALL_YOURS' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_CANT_DO' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_CAN_DO' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_CAN_DO_TIMEOUT' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_ECHO_REQ' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_ECHO_RES' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_ERROR' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_GET_STATUS' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_GRAB_JOB' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_GRAB_JOB_UNIQ' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_JOB_ASSIGN' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_JOB_ASSIGN_UNIQ' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_JOB_CREATED' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_MAX' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_NOOP' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_NO_JOB' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_OPTION_REQ' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_OPTION_RES' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_PRE_SLEEP' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_RESET_ABILITIES' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_SET_CLIENT_ID' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_STATUS_RES' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_SUBMIT_JOB' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_SUBMIT_JOB_BG' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_SUBMIT_JOB_EPOCH' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_SUBMIT_JOB_HIGH' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_SUBMIT_JOB_HIGH_BG' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_SUBMIT_JOB_LOW' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_SUBMIT_JOB_LOW_BG' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_SUBMIT_JOB_SCHED' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_TEXT' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_UNUSED' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_WORK_COMPLETE' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_WORK_DATA' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_WORK_EXCEPTION' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_WORK_FAIL' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_WORK_STATUS' => 'gearman/gearman.stub', 'GEARMAN_COMMAND_WORK_WARNING' => 'gearman/gearman.stub', 'GEARMAN_CON_CLOSE_AFTER_FLUSH' => 'gearman/gearman.stub', 'GEARMAN_CON_EXTERNAL_FD' => 'gearman/gearman.stub', 'GEARMAN_CON_IGNORE_LOST_CONNECTION' => 'gearman/gearman.stub', 'GEARMAN_CON_PACKET_IN_USE' => 'gearman/gearman.stub', 'GEARMAN_CON_READY' => 'gearman/gearman.stub', 'GEARMAN_CON_RECV_STATE_READ_DATA' => 'gearman/gearman.stub', 'GEARMAN_CON_SEND_STATE_NONE' => 'gearman/gearman.stub', 'GEARMAN_COULD_NOT_CONNECT' => 'gearman/gearman.stub', 'GEARMAN_DATA_TOO_LARGE' => 'gearman/gearman.stub', 'GEARMAN_DEFAULT_SOCKET_RECV_SIZE' => 'gearman/gearman.stub', 'GEARMAN_DEFAULT_SOCKET_SEND_SIZE' => 'gearman/gearman.stub', 'GEARMAN_DEFAULT_SOCKET_TIMEOUT' => 'gearman/gearman.stub', 'GEARMAN_DEFAULT_TCP_HOST' => 'gearman/gearman.stub', 'GEARMAN_DEFAULT_TCP_PORT' => 'gearman/gearman.stub', 'GEARMAN_DONT_TRACK_PACKETS' => 'gearman/gearman.stub', 'GEARMAN_ECHO_DATA_CORRUPTION' => 'gearman/gearman.stub', 'GEARMAN_ERRNO' => 'gearman/gearman.stub', 'GEARMAN_EVENT' => 'gearman/gearman.stub', 'GEARMAN_FLUSH_DATA' => 'gearman/gearman.stub', 'GEARMAN_GETADDRINFO' => 'gearman/gearman.stub', 'GEARMAN_IGNORE_PACKET' => 'gearman/gearman.stub', 'GEARMAN_INVALID_COMMAND' => 'gearman/gearman.stub', 'GEARMAN_INVALID_FUNCTION_NAME' => 'gearman/gearman.stub', 'GEARMAN_INVALID_MAGIC' => 'gearman/gearman.stub', 'GEARMAN_INVALID_PACKET' => 'gearman/gearman.stub', 'GEARMAN_INVALID_WORKER_FUNCTION' => 'gearman/gearman.stub', 'GEARMAN_IO_WAIT' => 'gearman/gearman.stub', 'GEARMAN_JOB_EXISTS' => 'gearman/gearman.stub', 'GEARMAN_JOB_HANDLE_SIZE' => 'gearman/gearman.stub', 'GEARMAN_JOB_PRIORITY_HIGH' => 'gearman/gearman.stub', 'GEARMAN_JOB_PRIORITY_LOW' => 'gearman/gearman.stub', 'GEARMAN_JOB_PRIORITY_MAX' => 'gearman/gearman.stub', 'GEARMAN_JOB_PRIORITY_NORMAL' => 'gearman/gearman.stub', 'GEARMAN_JOB_QUEUE_FULL' => 'gearman/gearman.stub', 'GEARMAN_LOST_CONNECTION' => 'gearman/gearman.stub', 'GEARMAN_MAGIC_REQUEST' => 'gearman/gearman.stub', 'GEARMAN_MAGIC_RESPONSE' => 'gearman/gearman.stub', 'GEARMAN_MAGIC_TEXT' => 'gearman/gearman.stub', 'GEARMAN_MAX_COMMAND_ARGS' => 'gearman/gearman.stub', 'GEARMAN_MAX_ERROR_SIZE' => 'gearman/gearman.stub', 'GEARMAN_MAX_RETURN' => 'gearman/gearman.stub', 'GEARMAN_MEMORY_ALLOCATION_FAILURE' => 'gearman/gearman.stub', 'GEARMAN_NEED_WORKLOAD_FN' => 'gearman/gearman.stub', 'GEARMAN_NON_BLOCKING' => 'gearman/gearman.stub', 'GEARMAN_NOT_CONNECTED' => 'gearman/gearman.stub', 'GEARMAN_NOT_FLUSHING' => 'gearman/gearman.stub', 'GEARMAN_NO_ACTIVE_FDS' => 'gearman/gearman.stub', 'GEARMAN_NO_JOBS' => 'gearman/gearman.stub', 'GEARMAN_NO_REGISTERED_FUNCTIONS' => 'gearman/gearman.stub', 'GEARMAN_NO_SERVERS' => 'gearman/gearman.stub', 'GEARMAN_OPTION_SIZE' => 'gearman/gearman.stub', 'GEARMAN_PACKET_HEADER_SIZE' => 'gearman/gearman.stub', 'GEARMAN_PAUSE' => 'gearman/gearman.stub', 'GEARMAN_PIPE_EOF' => 'gearman/gearman.stub', 'GEARMAN_PTHREAD' => 'gearman/gearman.stub', 'GEARMAN_QUEUE_ERROR' => 'gearman/gearman.stub', 'GEARMAN_RECV_BUFFER_SIZE' => 'gearman/gearman.stub', 'GEARMAN_RECV_IN_PROGRESS' => 'gearman/gearman.stub', 'GEARMAN_SEND_BUFFER_SIZE' => 'gearman/gearman.stub', 'GEARMAN_SEND_BUFFER_TOO_SMALL' => 'gearman/gearman.stub', 'GEARMAN_SEND_IN_PROGRESS' => 'gearman/gearman.stub', 'GEARMAN_SERVER_ERROR' => 'gearman/gearman.stub', 'GEARMAN_SHUTDOWN' => 'gearman/gearman.stub', 'GEARMAN_SHUTDOWN_GRACEFUL' => 'gearman/gearman.stub', 'GEARMAN_SUCCESS' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_COMPLETE' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_CREATED' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_DATA' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_EXCEPTION' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_FAIL' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_FINISHED' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_NEW' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_STATUS' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_SUBMIT' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_WARNING' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_WORK' => 'gearman/gearman.stub', 'GEARMAN_TASK_STATE_WORKLOAD' => 'gearman/gearman.stub', 'GEARMAN_TIMEOUT' => 'gearman/gearman.stub', 'GEARMAN_TOO_MANY_ARGS' => 'gearman/gearman.stub', 'GEARMAN_UNEXPECTED_PACKET' => 'gearman/gearman.stub', 'GEARMAN_UNIQUE_SIZE' => 'gearman/gearman.stub', 'GEARMAN_UNKNOWN_OPTION' => 'gearman/gearman.stub', 'GEARMAN_UNKNOWN_STATE' => 'gearman/gearman.stub', 'GEARMAN_VERBOSE_CRAZY' => 'gearman/gearman.stub', 'GEARMAN_VERBOSE_DEBUG' => 'gearman/gearman.stub', 'GEARMAN_VERBOSE_ERROR' => 'gearman/gearman.stub', 'GEARMAN_VERBOSE_FATAL' => 'gearman/gearman.stub', 'GEARMAN_VERBOSE_INFO' => 'gearman/gearman.stub', 'GEARMAN_VERBOSE_MAX' => 'gearman/gearman.stub', 'GEARMAN_VERBOSE_NEVER' => 'gearman/gearman.stub', 'GEARMAN_WORKER_ALLOCATED' => 'gearman/gearman.stub', 'GEARMAN_WORKER_CHANGE' => 'gearman/gearman.stub', 'GEARMAN_WORKER_GRAB_JOB_IN_USE' => 'gearman/gearman.stub', 'GEARMAN_WORKER_GRAB_UNIQ' => 'gearman/gearman.stub', 'GEARMAN_WORKER_NON_BLOCKING' => 'gearman/gearman.stub', 'GEARMAN_WORKER_PACKET_INIT' => 'gearman/gearman.stub', 'GEARMAN_WORKER_PRE_SLEEP_IN_USE' => 'gearman/gearman.stub', 'GEARMAN_WORKER_STATE_CONNECT' => 'gearman/gearman.stub', 'GEARMAN_WORKER_STATE_FUNCTION_SEND' => 'gearman/gearman.stub', 'GEARMAN_WORKER_STATE_GRAB_JOB_RECV' => 'gearman/gearman.stub', 'GEARMAN_WORKER_STATE_GRAB_JOB_SEND' => 'gearman/gearman.stub', 'GEARMAN_WORKER_STATE_PRE_SLEEP' => 'gearman/gearman.stub', 'GEARMAN_WORKER_STATE_START' => 'gearman/gearman.stub', 'GEARMAN_WORKER_TIMEOUT_RETURN' => 'gearman/gearman.stub', 'GEARMAN_WORKER_WAIT_TIMEOUT' => 'gearman/gearman.stub', 'GEARMAN_WORKER_WORK_JOB_IN_USE' => 'gearman/gearman.stub', 'GEARMAN_WORK_DATA' => 'gearman/gearman.stub', 'GEARMAN_WORK_ERROR' => 'gearman/gearman.stub', 'GEARMAN_WORK_EXCEPTION' => 'gearman/gearman.stub', 'GEARMAN_WORK_FAIL' => 'gearman/gearman.stub', 'GEARMAN_WORK_STATUS' => 'gearman/gearman.stub', 'GEARMAN_WORK_WARNING' => 'gearman/gearman.stub', 'GEOIP_ASNUM_EDITION' => 'geoip/geoip.stub', 'GEOIP_CABLEDSL_SPEED' => 'geoip/geoip.stub', 'GEOIP_CITY_EDITION_REV0' => 'geoip/geoip.stub', 'GEOIP_CITY_EDITION_REV1' => 'geoip/geoip.stub', 'GEOIP_CORPORATE_SPEED' => 'geoip/geoip.stub', 'GEOIP_COUNTRY_EDITION' => 'geoip/geoip.stub', 'GEOIP_DIALUP_SPEED' => 'geoip/geoip.stub', 'GEOIP_DOMAIN_EDITION' => 'geoip/geoip.stub', 'GEOIP_ISP_EDITION' => 'geoip/geoip.stub', 'GEOIP_NETSPEED_EDITION' => 'geoip/geoip.stub', 'GEOIP_ORG_EDITION' => 'geoip/geoip.stub', 'GEOIP_PROXY_EDITION' => 'geoip/geoip.stub', 'GEOIP_REGION_EDITION_REV0' => 'geoip/geoip.stub', 'GEOIP_REGION_EDITION_REV1' => 'geoip/geoip.stub', 'GEOIP_UNKNOWN_SPEED' => 'geoip/geoip.stub', 'GEOSBUF_CAP_FLAT' => 'geos/geos.stub', 'GEOSBUF_CAP_ROUND' => 'geos/geos.stub', 'GEOSBUF_CAP_SQUARE' => 'geos/geos.stub', 'GEOSBUF_JOIN_BEVEL' => 'geos/geos.stub', 'GEOSBUF_JOIN_MITRE' => 'geos/geos.stub', 'GEOSBUF_JOIN_ROUND' => 'geos/geos.stub', 'GEOSRELATE_BNR_ENDPOINT' => 'geos/geos.stub', 'GEOSRELATE_BNR_MOD2' => 'geos/geos.stub', 'GEOSRELATE_BNR_MONOVALENT_ENDPOINT' => 'geos/geos.stub', 'GEOSRELATE_BNR_MULTIVALENT_ENDPOINT' => 'geos/geos.stub', 'GEOSRELATE_BNR_OGC' => 'geos/geos.stub', 'GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE' => 'geos/geos.stub', 'GEOS_GEOMETRYCOLLECTION' => 'geos/geos.stub', 'GEOS_LINEARRING' => 'geos/geos.stub', 'GEOS_LINESTRING' => 'geos/geos.stub', 'GEOS_MULTILINESTRING' => 'geos/geos.stub', 'GEOS_MULTIPOINT' => 'geos/geos.stub', 'GEOS_MULTIPOLYGON' => 'geos/geos.stub', 'GEOS_POINT' => 'geos/geos.stub', 'GEOS_POLYGON' => 'geos/geos.stub', 'GLOB_AVAILABLE_FLAGS' => 'standard/standard_defines.stub', 'GLOB_BRACE' => 'standard/standard_defines.stub', 'GLOB_ERR' => 'standard/standard_defines.stub', 'GLOB_MARK' => 'standard/standard_defines.stub', 'GLOB_NOCHECK' => 'standard/standard_defines.stub', 'GLOB_NOESCAPE' => 'standard/standard_defines.stub', 'GLOB_NOSORT' => 'standard/standard_defines.stub', 'GLOB_ONLYDIR' => 'standard/standard_defines.stub', 'GMP_BIG_ENDIAN' => 'gmp/gmp.stub', 'GMP_LITTLE_ENDIAN' => 'gmp/gmp.stub', 'GMP_LSW_FIRST' => 'gmp/gmp.stub', 'GMP_MPIR_VERSION' => 'gmp/gmp.stub', 'GMP_MSW_FIRST' => 'gmp/gmp.stub', 'GMP_NATIVE_ENDIAN' => 'gmp/gmp.stub', 'GMP_ROUND_MINUSINF' => 'gmp/gmp.stub', 'GMP_ROUND_PLUSINF' => 'gmp/gmp.stub', 'GMP_ROUND_ZERO' => 'gmp/gmp.stub', 'GMP_VERSION' => 'gmp/gmp.stub', 'GNUPG_ERROR_EXCEPTION' => 'gnupg/gnupg.stub', 'GNUPG_ERROR_SILENT' => 'gnupg/gnupg.stub', 'GNUPG_ERROR_WARNING' => 'gnupg/gnupg.stub', 'GNUPG_GPGME_VERSION' => 'gnupg/gnupg.stub', 'GNUPG_PK_DSA' => 'gnupg/gnupg.stub', 'GNUPG_PK_ECC' => 'gnupg/gnupg.stub', 'GNUPG_PK_ECDH' => 'gnupg/gnupg.stub', 'GNUPG_PK_ECDSA' => 'gnupg/gnupg.stub', 'GNUPG_PK_EDDSA' => 'gnupg/gnupg.stub', 'GNUPG_PK_ELG' => 'gnupg/gnupg.stub', 'GNUPG_PK_ELG_E' => 'gnupg/gnupg.stub', 'GNUPG_PK_RSA' => 'gnupg/gnupg.stub', 'GNUPG_PK_RSA_E' => 'gnupg/gnupg.stub', 'GNUPG_PK_RSA_S' => 'gnupg/gnupg.stub', 'GNUPG_PROTOCOL_CMS' => 'gnupg/gnupg.stub', 'GNUPG_PROTOCOL_OpenPGP' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_BAD_POLICY' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_CRL_MISSING' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_CRL_TOO_OLD' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_GREEN' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_KEY_EXPIRED' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_KEY_MISSING' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_KEY_REVOKED' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_RED' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_SIG_EXPIRED' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_SYS_ERROR' => 'gnupg/gnupg.stub', 'GNUPG_SIGSUM_VALID' => 'gnupg/gnupg.stub', 'GNUPG_SIG_MODE_CLEAR' => 'gnupg/gnupg.stub', 'GNUPG_SIG_MODE_DETACH' => 'gnupg/gnupg.stub', 'GNUPG_SIG_MODE_NORMAL' => 'gnupg/gnupg.stub', 'GNUPG_VALIDITY_FULL' => 'gnupg/gnupg.stub', 'GNUPG_VALIDITY_MARGINAL' => 'gnupg/gnupg.stub', 'GNUPG_VALIDITY_NEVER' => 'gnupg/gnupg.stub', 'GNUPG_VALIDITY_ULTIMATE' => 'gnupg/gnupg.stub', 'GNUPG_VALIDITY_UNDEFINED' => 'gnupg/gnupg.stub', 'GNUPG_VALIDITY_UNKNOWN' => 'gnupg/gnupg.stub', 'GRAPHEME_EXTR_COUNT' => 'intl/intl.stub', 'GRAPHEME_EXTR_MAXBYTES' => 'intl/intl.stub', 'GRAPHEME_EXTR_MAXCHARS' => 'intl/intl.stub', 'GREEN' => 'winbinder/winbinder.stub', 'GROUPING' => 'standard/standard_defines.stub', 'Gauge' => 'winbinder/winbinder.stub', 'Grpc\\CALL_ERROR' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_ALREADY_ACCEPTED' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_ALREADY_FINISHED' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_ALREADY_INVOKED' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_BATCH_TOO_BIG' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_INVALID_FLAGS' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_INVALID_MESSAGE' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_INVALID_METADATA' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_NOT_INVOKED' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_NOT_ON_CLIENT' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_NOT_ON_SERVER' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_PAYLOAD_TYPE_MISMATCH' => 'grpc/grpc.stub', 'Grpc\\CALL_ERROR_TOO_MANY_OPERATIONS' => 'grpc/grpc.stub', 'Grpc\\CALL_OK' => 'grpc/grpc.stub', 'Grpc\\CHANNEL_CONNECTING' => 'grpc/grpc.stub', 'Grpc\\CHANNEL_FATAL_FAILURE' => 'grpc/grpc.stub', 'Grpc\\CHANNEL_IDLE' => 'grpc/grpc.stub', 'Grpc\\CHANNEL_READY' => 'grpc/grpc.stub', 'Grpc\\CHANNEL_SHUTDOWN' => 'grpc/grpc.stub', 'Grpc\\CHANNEL_TRANSIENT_FAILURE' => 'grpc/grpc.stub', 'Grpc\\OP_RECV_CLOSE_ON_SERVER' => 'grpc/grpc.stub', 'Grpc\\OP_RECV_INITIAL_METADATA' => 'grpc/grpc.stub', 'Grpc\\OP_RECV_MESSAGE' => 'grpc/grpc.stub', 'Grpc\\OP_RECV_STATUS_ON_CLIENT' => 'grpc/grpc.stub', 'Grpc\\OP_SEND_CLOSE_FROM_CLIENT' => 'grpc/grpc.stub', 'Grpc\\OP_SEND_INITIAL_METADATA' => 'grpc/grpc.stub', 'Grpc\\OP_SEND_MESSAGE' => 'grpc/grpc.stub', 'Grpc\\OP_SEND_STATUS_FROM_SERVER' => 'grpc/grpc.stub', 'Grpc\\STATUS_ABORTED' => 'grpc/grpc.stub', 'Grpc\\STATUS_ALREADY_EXISTS' => 'grpc/grpc.stub', 'Grpc\\STATUS_CANCELLED' => 'grpc/grpc.stub', 'Grpc\\STATUS_DATA_LOSS' => 'grpc/grpc.stub', 'Grpc\\STATUS_DEADLINE_EXCEEDED' => 'grpc/grpc.stub', 'Grpc\\STATUS_FAILED_PRECONDITION' => 'grpc/grpc.stub', 'Grpc\\STATUS_INTERNAL' => 'grpc/grpc.stub', 'Grpc\\STATUS_INVALID_ARGUMENT' => 'grpc/grpc.stub', 'Grpc\\STATUS_NOT_FOUND' => 'grpc/grpc.stub', 'Grpc\\STATUS_OK' => 'grpc/grpc.stub', 'Grpc\\STATUS_OUT_OF_RANGE' => 'grpc/grpc.stub', 'Grpc\\STATUS_PERMISSION_DENIED' => 'grpc/grpc.stub', 'Grpc\\STATUS_RESOURCE_EXHAUSTED' => 'grpc/grpc.stub', 'Grpc\\STATUS_UNAUTHENTICATED' => 'grpc/grpc.stub', 'Grpc\\STATUS_UNAVAILABLE' => 'grpc/grpc.stub', 'Grpc\\STATUS_UNIMPLEMENTED' => 'grpc/grpc.stub', 'Grpc\\STATUS_UNKNOWN' => 'grpc/grpc.stub', 'Grpc\\WRITE_BUFFER_HINT' => 'grpc/grpc.stub', 'Grpc\\WRITE_NO_COMPRESS' => 'grpc/grpc.stub', 'HASH_HMAC' => 'hash/hash.stub', 'HTMLControl' => 'winbinder/winbinder.stub', 'HTML_ENTITIES' => 'standard/standard_defines.stub', 'HTML_SPECIALCHARS' => 'standard/standard_defines.stub', 'HTTP_AUTH_ANY' => 'http/http.stub', 'HTTP_AUTH_BASIC' => 'http/http.stub', 'HTTP_AUTH_DIGEST' => 'http/http.stub', 'HTTP_AUTH_GSSNEG' => 'http/http.stub', 'HTTP_AUTH_NTLM' => 'http/http.stub', 'HTTP_COOKIE_HTTPONLY' => 'http/http.stub', 'HTTP_COOKIE_PARSE_RAW' => 'http/http.stub', 'HTTP_COOKIE_SECURE' => 'http/http.stub', 'HTTP_DEFLATE_LEVEL_DEF' => 'http/http.stub', 'HTTP_DEFLATE_LEVEL_MAX' => 'http/http.stub', 'HTTP_DEFLATE_LEVEL_MIN' => 'http/http.stub', 'HTTP_DEFLATE_STRATEGY_DEF' => 'http/http.stub', 'HTTP_DEFLATE_STRATEGY_FILT' => 'http/http.stub', 'HTTP_DEFLATE_STRATEGY_FIXED' => 'http/http.stub', 'HTTP_DEFLATE_STRATEGY_HUFF' => 'http/http.stub', 'HTTP_DEFLATE_STRATEGY_RLE' => 'http/http.stub', 'HTTP_DEFLATE_TYPE_GZIP' => 'http/http.stub', 'HTTP_DEFLATE_TYPE_RAW' => 'http/http.stub', 'HTTP_DEFLATE_TYPE_ZLIB' => 'http/http.stub', 'HTTP_ENCODING_STREAM_FLUSH_FULL' => 'http/http.stub', 'HTTP_ENCODING_STREAM_FLUSH_NONE' => 'http/http.stub', 'HTTP_ENCODING_STREAM_FLUSH_SYNC' => 'http/http.stub', 'HTTP_E_ENCODING' => 'http/http.stub', 'HTTP_E_HEADER' => 'http/http.stub', 'HTTP_E_INVALID_PARAM' => 'http/http.stub', 'HTTP_E_MALFORMED_HEADERS' => 'http/http.stub', 'HTTP_E_MESSAGE_TYPE' => 'http/http.stub', 'HTTP_E_QUERYSTRING' => 'http/http.stub', 'HTTP_E_REQUEST' => 'http/http.stub', 'HTTP_E_REQUEST_METHOD' => 'http/http.stub', 'HTTP_E_REQUEST_POOL' => 'http/http.stub', 'HTTP_E_RESPONSE' => 'http/http.stub', 'HTTP_E_RUNTIME' => 'http/http.stub', 'HTTP_E_SOCKET' => 'http/http.stub', 'HTTP_E_URL' => 'http/http.stub', 'HTTP_IPRESOLVE_ANY' => 'http/http.stub', 'HTTP_IPRESOLVE_V4' => 'http/http.stub', 'HTTP_IPRESOLVE_V6' => 'http/http.stub', 'HTTP_METH_ACL' => 'http/http.stub', 'HTTP_METH_BASELINE_CONTROL' => 'http/http.stub', 'HTTP_METH_CHECKIN' => 'http/http.stub', 'HTTP_METH_CHECKOUT' => 'http/http.stub', 'HTTP_METH_CONNECT' => 'http/http.stub', 'HTTP_METH_COPY' => 'http/http.stub', 'HTTP_METH_DELETE' => 'http/http.stub', 'HTTP_METH_GET' => 'http/http.stub', 'HTTP_METH_HEAD' => 'http/http.stub', 'HTTP_METH_LABEL' => 'http/http.stub', 'HTTP_METH_LOCK' => 'http/http.stub', 'HTTP_METH_MERGE' => 'http/http.stub', 'HTTP_METH_MKACTIVITY' => 'http/http.stub', 'HTTP_METH_MKCOL' => 'http/http.stub', 'HTTP_METH_MKWORKSPACE' => 'http/http.stub', 'HTTP_METH_MOVE' => 'http/http.stub', 'HTTP_METH_OPTIONS' => 'http/http.stub', 'HTTP_METH_POST' => 'http/http.stub', 'HTTP_METH_PROPFIND' => 'http/http.stub', 'HTTP_METH_PROPPATCH' => 'http/http.stub', 'HTTP_METH_PUT' => 'http/http.stub', 'HTTP_METH_REPORT' => 'http/http.stub', 'HTTP_METH_TRACE' => 'http/http.stub', 'HTTP_METH_UNCHECKOUT' => 'http/http.stub', 'HTTP_METH_UNLOCK' => 'http/http.stub', 'HTTP_METH_UPDATE' => 'http/http.stub', 'HTTP_METH_VERSION_CONTROL' => 'http/http.stub', 'HTTP_MSG_NONE' => 'http/http.stub', 'HTTP_MSG_REQUEST' => 'http/http.stub', 'HTTP_MSG_RESPONSE' => 'http/http.stub', 'HTTP_PARAMS_ALLOW_COMMA' => 'http/http.stub', 'HTTP_PARAMS_ALLOW_FAILURE' => 'http/http.stub', 'HTTP_PARAMS_DEFAULT' => 'http/http.stub', 'HTTP_PARAMS_RAISE_ERROR' => 'http/http.stub', 'HTTP_PROXY_HTTP' => 'http/http.stub', 'HTTP_PROXY_SOCKS4' => 'http/http.stub', 'HTTP_PROXY_SOCKS5' => 'http/http.stub', 'HTTP_QUERYSTRING_TYPE_ARRAY' => 'http/http.stub', 'HTTP_QUERYSTRING_TYPE_BOOL' => 'http/http.stub', 'HTTP_QUERYSTRING_TYPE_FLOAT' => 'http/http.stub', 'HTTP_QUERYSTRING_TYPE_INT' => 'http/http.stub', 'HTTP_QUERYSTRING_TYPE_OBJECT' => 'http/http.stub', 'HTTP_QUERYSTRING_TYPE_STRING' => 'http/http.stub', 'HTTP_REDIRECT' => 'http/http.stub', 'HTTP_REDIRECT_FOUND' => 'http/http.stub', 'HTTP_REDIRECT_PERM' => 'http/http.stub', 'HTTP_REDIRECT_POST' => 'http/http.stub', 'HTTP_REDIRECT_PROXY' => 'http/http.stub', 'HTTP_REDIRECT_TEMP' => 'http/http.stub', 'HTTP_SSL_VERSION_ANY' => 'http/http.stub', 'HTTP_SSL_VERSION_SSLv2' => 'http/http.stub', 'HTTP_SSL_VERSION_SSLv3' => 'http/http.stub', 'HTTP_SSL_VERSION_TLSv1' => 'http/http.stub', 'HTTP_SUPPORT' => 'http/http.stub', 'HTTP_SUPPORT_ENCODINGS' => 'http/http.stub', 'HTTP_SUPPORT_EVENTS' => 'http/http.stub', 'HTTP_SUPPORT_MAGICMIME' => 'http/http.stub', 'HTTP_SUPPORT_REQUESTS' => 'http/http.stub', 'HTTP_SUPPORT_SSLREQUESTS' => 'http/http.stub', 'HTTP_URL_FROM_ENV' => 'http/http.stub', 'HTTP_URL_JOIN_PATH' => 'http/http.stub', 'HTTP_URL_JOIN_QUERY' => 'http/http.stub', 'HTTP_URL_REPLACE' => 'http/http.stub', 'HTTP_URL_STRIP_ALL' => 'http/http.stub', 'HTTP_URL_STRIP_AUTH' => 'http/http.stub', 'HTTP_URL_STRIP_FRAGMENT' => 'http/http.stub', 'HTTP_URL_STRIP_PASS' => 'http/http.stub', 'HTTP_URL_STRIP_PATH' => 'http/http.stub', 'HTTP_URL_STRIP_PORT' => 'http/http.stub', 'HTTP_URL_STRIP_QUERY' => 'http/http.stub', 'HTTP_URL_STRIP_USER' => 'http/http.stub', 'HTTP_VERSION_1_0' => 'http/http.stub', 'HTTP_VERSION_1_1' => 'http/http.stub', 'HTTP_VERSION_ANY' => 'http/http.stub', 'HTTP_VERSION_NONE' => 'http/http.stub', 'HyperLink' => 'winbinder/winbinder.stub', 'IBASE_BKP_CONVERT' => 'interbase/interbase.stub', 'IBASE_BKP_IGNORE_CHECKSUMS' => 'interbase/interbase.stub', 'IBASE_BKP_IGNORE_LIMBO' => 'interbase/interbase.stub', 'IBASE_BKP_METADATA_ONLY' => 'interbase/interbase.stub', 'IBASE_BKP_NON_TRANSPORTABLE' => 'interbase/interbase.stub', 'IBASE_BKP_NO_GARBAGE_COLLECT' => 'interbase/interbase.stub', 'IBASE_BKP_OLD_DESCRIPTIONS' => 'interbase/interbase.stub', 'IBASE_COMMITTED' => 'interbase/interbase.stub', 'IBASE_CONCURRENCY' => 'interbase/interbase.stub', 'IBASE_CONSISTENCY' => 'interbase/interbase.stub', 'IBASE_CREATE' => 'interbase/interbase.stub', 'IBASE_DEFAULT' => 'interbase/interbase.stub', 'IBASE_FETCH_ARRAYS' => 'interbase/interbase.stub', 'IBASE_FETCH_BLOBS' => 'interbase/interbase.stub', 'IBASE_NOWAIT' => 'interbase/interbase.stub', 'IBASE_PRP_ACCESS_MODE' => 'interbase/interbase.stub', 'IBASE_PRP_ACTIVATE' => 'interbase/interbase.stub', 'IBASE_PRP_AM_READONLY' => 'interbase/interbase.stub', 'IBASE_PRP_AM_READWRITE' => 'interbase/interbase.stub', 'IBASE_PRP_DB_ONLINE' => 'interbase/interbase.stub', 'IBASE_PRP_DENY_NEW_ATTACHMENTS' => 'interbase/interbase.stub', 'IBASE_PRP_DENY_NEW_TRANSACTIONS' => 'interbase/interbase.stub', 'IBASE_PRP_PAGE_BUFFERS' => 'interbase/interbase.stub', 'IBASE_PRP_RES' => 'interbase/interbase.stub', 'IBASE_PRP_RESERVE_SPACE' => 'interbase/interbase.stub', 'IBASE_PRP_RES_USE_FULL' => 'interbase/interbase.stub', 'IBASE_PRP_SET_SQL_DIALECT' => 'interbase/interbase.stub', 'IBASE_PRP_SHUTDOWN_DB' => 'interbase/interbase.stub', 'IBASE_PRP_SWEEP_INTERVAL' => 'interbase/interbase.stub', 'IBASE_PRP_WM_ASYNC' => 'interbase/interbase.stub', 'IBASE_PRP_WM_SYNC' => 'interbase/interbase.stub', 'IBASE_PRP_WRITE_MODE' => 'interbase/interbase.stub', 'IBASE_READ' => 'interbase/interbase.stub', 'IBASE_REC_NO_VERSION' => 'interbase/interbase.stub', 'IBASE_REC_VERSION' => 'interbase/interbase.stub', 'IBASE_RES_CREATE' => 'interbase/interbase.stub', 'IBASE_RES_DEACTIVATE_IDX' => 'interbase/interbase.stub', 'IBASE_RES_NO_SHADOW' => 'interbase/interbase.stub', 'IBASE_RES_NO_VALIDITY' => 'interbase/interbase.stub', 'IBASE_RES_ONE_AT_A_TIME' => 'interbase/interbase.stub', 'IBASE_RES_REPLACE' => 'interbase/interbase.stub', 'IBASE_RES_USE_ALL_SPACE' => 'interbase/interbase.stub', 'IBASE_RPR_CHECK_DB' => 'interbase/interbase.stub', 'IBASE_RPR_FULL' => 'interbase/interbase.stub', 'IBASE_RPR_IGNORE_CHECKSUM' => 'interbase/interbase.stub', 'IBASE_RPR_KILL_SHADOWS' => 'interbase/interbase.stub', 'IBASE_RPR_MEND_DB' => 'interbase/interbase.stub', 'IBASE_RPR_SWEEP_DB' => 'interbase/interbase.stub', 'IBASE_RPR_VALIDATE_DB' => 'interbase/interbase.stub', 'IBASE_STS_DATA_PAGES' => 'interbase/interbase.stub', 'IBASE_STS_DB_LOG' => 'interbase/interbase.stub', 'IBASE_STS_HDR_PAGES' => 'interbase/interbase.stub', 'IBASE_STS_IDX_PAGES' => 'interbase/interbase.stub', 'IBASE_STS_SYS_RELATIONS' => 'interbase/interbase.stub', 'IBASE_SVC_GET_ENV' => 'interbase/interbase.stub', 'IBASE_SVC_GET_ENV_LOCK' => 'interbase/interbase.stub', 'IBASE_SVC_GET_ENV_MSG' => 'interbase/interbase.stub', 'IBASE_SVC_GET_USERS' => 'interbase/interbase.stub', 'IBASE_SVC_IMPLEMENTATION' => 'interbase/interbase.stub', 'IBASE_SVC_SERVER_VERSION' => 'interbase/interbase.stub', 'IBASE_SVC_SVR_DB_INFO' => 'interbase/interbase.stub', 'IBASE_SVC_USER_DBPATH' => 'interbase/interbase.stub', 'IBASE_TEXT' => 'interbase/interbase.stub', 'IBASE_UNIXTIME' => 'interbase/interbase.stub', 'IBASE_WAIT' => 'interbase/interbase.stub', 'IBASE_WRITE' => 'interbase/interbase.stub', 'ICONV_IMPL' => 'iconv/iconv.stub', 'ICONV_MIME_DECODE_CONTINUE_ON_ERROR' => 'iconv/iconv.stub', 'ICONV_MIME_DECODE_STRICT' => 'iconv/iconv.stub', 'ICONV_VERSION' => 'iconv/iconv.stub', 'IDABORT' => 'winbinder/winbinder.stub', 'IDCANCEL' => 'winbinder/winbinder.stub', 'IDCLOSE' => 'winbinder/winbinder.stub', 'IDDEFAULT' => 'winbinder/winbinder.stub', 'IDHELP' => 'winbinder/winbinder.stub', 'IDIGNORE' => 'winbinder/winbinder.stub', 'IDNA_ALLOW_UNASSIGNED' => 'intl/intl.stub', 'IDNA_CHECK_BIDI' => 'intl/intl.stub', 'IDNA_CHECK_CONTEXTJ' => 'intl/intl.stub', 'IDNA_DEFAULT' => 'intl/intl.stub', 'IDNA_ERROR_BIDI' => 'intl/intl.stub', 'IDNA_ERROR_CONTEXTJ' => 'intl/intl.stub', 'IDNA_ERROR_DISALLOWED' => 'intl/intl.stub', 'IDNA_ERROR_DOMAIN_NAME_TOO_LONG' => 'intl/intl.stub', 'IDNA_ERROR_EMPTY_LABEL' => 'intl/intl.stub', 'IDNA_ERROR_HYPHEN_3_4' => 'intl/intl.stub', 'IDNA_ERROR_INVALID_ACE_LABEL' => 'intl/intl.stub', 'IDNA_ERROR_LABEL_HAS_DOT' => 'intl/intl.stub', 'IDNA_ERROR_LABEL_TOO_LONG' => 'intl/intl.stub', 'IDNA_ERROR_LEADING_COMBINING_MARK' => 'intl/intl.stub', 'IDNA_ERROR_LEADING_HYPHEN' => 'intl/intl.stub', 'IDNA_ERROR_PUNYCODE' => 'intl/intl.stub', 'IDNA_ERROR_TRAILING_HYPHEN' => 'intl/intl.stub', 'IDNA_NONTRANSITIONAL_TO_ASCII' => 'intl/intl.stub', 'IDNA_NONTRANSITIONAL_TO_UNICODE' => 'intl/intl.stub', 'IDNA_USE_STD3_RULES' => 'intl/intl.stub', 'IDNO' => 'winbinder/winbinder.stub', 'IDOK' => 'winbinder/winbinder.stub', 'IDRETRY' => 'winbinder/winbinder.stub', 'IDYES' => 'winbinder/winbinder.stub', 'ILL_BADSTK' => 'pcntl/pcntl.stub', 'ILL_COPROC' => 'pcntl/pcntl.stub', 'ILL_ILLADR' => 'pcntl/pcntl.stub', 'ILL_ILLOPC' => 'pcntl/pcntl.stub', 'ILL_ILLOPN' => 'pcntl/pcntl.stub', 'ILL_ILLTRP' => 'pcntl/pcntl.stub', 'ILL_PRVOPC' => 'pcntl/pcntl.stub', 'ILL_PRVREG' => 'pcntl/pcntl.stub', 'IMAGETYPE_AVIF' => 'standard/standard_defines.stub', 'IMAGETYPE_BMP' => 'standard/standard_defines.stub', 'IMAGETYPE_COUNT' => 'standard/standard_defines.stub', 'IMAGETYPE_GIF' => 'standard/standard_defines.stub', 'IMAGETYPE_ICO' => 'standard/standard_defines.stub', 'IMAGETYPE_IFF' => 'standard/standard_defines.stub', 'IMAGETYPE_JB2' => 'standard/standard_defines.stub', 'IMAGETYPE_JP2' => 'standard/standard_defines.stub', 'IMAGETYPE_JPC' => 'standard/standard_defines.stub', 'IMAGETYPE_JPEG' => 'standard/standard_defines.stub', 'IMAGETYPE_JPEG2000' => 'standard/standard_defines.stub', 'IMAGETYPE_JPX' => 'standard/standard_defines.stub', 'IMAGETYPE_PNG' => 'standard/standard_defines.stub', 'IMAGETYPE_PSD' => 'standard/standard_defines.stub', 'IMAGETYPE_SWC' => 'standard/standard_defines.stub', 'IMAGETYPE_SWF' => 'standard/standard_defines.stub', 'IMAGETYPE_TIFF_II' => 'standard/standard_defines.stub', 'IMAGETYPE_TIFF_MM' => 'standard/standard_defines.stub', 'IMAGETYPE_UNKNOWN' => 'standard/standard_defines.stub', 'IMAGETYPE_WBMP' => 'standard/standard_defines.stub', 'IMAGETYPE_WEBP' => 'standard/standard_defines.stub', 'IMAGETYPE_XBM' => 'standard/standard_defines.stub', 'IMAP_CLOSETIMEOUT' => 'imap/imap.stub', 'IMAP_GC_ELT' => 'imap/imap.stub', 'IMAP_GC_ENV' => 'imap/imap.stub', 'IMAP_GC_TEXTS' => 'imap/imap.stub', 'IMAP_OPENTIMEOUT' => 'imap/imap.stub', 'IMAP_READTIMEOUT' => 'imap/imap.stub', 'IMAP_WRITETIMEOUT' => 'imap/imap.stub', 'IMG_AFFINE_ROTATE' => 'gd/gd.stub', 'IMG_AFFINE_SCALE' => 'gd/gd.stub', 'IMG_AFFINE_SHEAR_HORIZONTAL' => 'gd/gd.stub', 'IMG_AFFINE_SHEAR_VERTICAL' => 'gd/gd.stub', 'IMG_AFFINE_TRANSLATE' => 'gd/gd.stub', 'IMG_ARC_CHORD' => 'gd/gd.stub', 'IMG_ARC_EDGED' => 'gd/gd.stub', 'IMG_ARC_NOFILL' => 'gd/gd.stub', 'IMG_ARC_PIE' => 'gd/gd.stub', 'IMG_ARC_ROUNDED' => 'gd/gd.stub', 'IMG_AVIF' => 'gd/gd.stub', 'IMG_BELL' => 'gd/gd.stub', 'IMG_BESSEL' => 'gd/gd.stub', 'IMG_BICUBIC' => 'gd/gd.stub', 'IMG_BICUBIC_FIXED' => 'gd/gd.stub', 'IMG_BILINEAR_FIXED' => 'gd/gd.stub', 'IMG_BLACKMAN' => 'gd/gd.stub', 'IMG_BMP' => 'gd/gd.stub', 'IMG_BOX' => 'gd/gd.stub', 'IMG_BSPLINE' => 'gd/gd.stub', 'IMG_CATMULLROM' => 'gd/gd.stub', 'IMG_COLOR_BRUSHED' => 'gd/gd.stub', 'IMG_COLOR_STYLED' => 'gd/gd.stub', 'IMG_COLOR_STYLEDBRUSHED' => 'gd/gd.stub', 'IMG_COLOR_TILED' => 'gd/gd.stub', 'IMG_COLOR_TRANSPARENT' => 'gd/gd.stub', 'IMG_CROP_BLACK' => 'gd/gd.stub', 'IMG_CROP_DEFAULT' => 'gd/gd.stub', 'IMG_CROP_SIDES' => 'gd/gd.stub', 'IMG_CROP_THRESHOLD' => 'gd/gd.stub', 'IMG_CROP_TRANSPARENT' => 'gd/gd.stub', 'IMG_CROP_WHITE' => 'gd/gd.stub', 'IMG_EFFECT_ALPHABLEND' => 'gd/gd.stub', 'IMG_EFFECT_MULTIPLY' => 'gd/gd.stub', 'IMG_EFFECT_NORMAL' => 'gd/gd.stub', 'IMG_EFFECT_OVERLAY' => 'gd/gd.stub', 'IMG_EFFECT_REPLACE' => 'gd/gd.stub', 'IMG_FILTER_BRIGHTNESS' => 'gd/gd.stub', 'IMG_FILTER_COLORIZE' => 'gd/gd.stub', 'IMG_FILTER_CONTRAST' => 'gd/gd.stub', 'IMG_FILTER_EDGEDETECT' => 'gd/gd.stub', 'IMG_FILTER_EMBOSS' => 'gd/gd.stub', 'IMG_FILTER_GAUSSIAN_BLUR' => 'gd/gd.stub', 'IMG_FILTER_GRAYSCALE' => 'gd/gd.stub', 'IMG_FILTER_MEAN_REMOVAL' => 'gd/gd.stub', 'IMG_FILTER_NEGATE' => 'gd/gd.stub', 'IMG_FILTER_PIXELATE' => 'gd/gd.stub', 'IMG_FILTER_SCATTER' => 'gd/gd.stub', 'IMG_FILTER_SELECTIVE_BLUR' => 'gd/gd.stub', 'IMG_FILTER_SMOOTH' => 'gd/gd.stub', 'IMG_FLIP_BOTH' => 'gd/gd.stub', 'IMG_FLIP_HORIZONTAL' => 'gd/gd.stub', 'IMG_FLIP_VERTICAL' => 'gd/gd.stub', 'IMG_GAUSSIAN' => 'gd/gd.stub', 'IMG_GD2_COMPRESSED' => 'gd/gd.stub', 'IMG_GD2_RAW' => 'gd/gd.stub', 'IMG_GENERALIZED_CUBIC' => 'gd/gd.stub', 'IMG_GIF' => 'gd/gd.stub', 'IMG_HAMMING' => 'gd/gd.stub', 'IMG_HANNING' => 'gd/gd.stub', 'IMG_HERMITE' => 'gd/gd.stub', 'IMG_JPEG' => 'gd/gd.stub', 'IMG_JPG' => 'gd/gd.stub', 'IMG_MITCHELL' => 'gd/gd.stub', 'IMG_NEAREST_NEIGHBOUR' => 'gd/gd.stub', 'IMG_PNG' => 'gd/gd.stub', 'IMG_POWER' => 'gd/gd.stub', 'IMG_QUADRATIC' => 'gd/gd.stub', 'IMG_SINC' => 'gd/gd.stub', 'IMG_TGA' => 'gd/gd.stub', 'IMG_TRIANGLE' => 'gd/gd.stub', 'IMG_WBMP' => 'gd/gd.stub', 'IMG_WEBP' => 'gd/gd.stub', 'IMG_WEBP_LOSSLESS' => 'gd/gd.stub', 'IMG_WEIGHTED4' => 'gd/gd.stub', 'IMG_XPM' => 'gd/gd.stub', 'INF' => 'standard/standard_defines.stub', 'INFO_ALL' => 'standard/standard_defines.stub', 'INFO_CONFIGURATION' => 'standard/standard_defines.stub', 'INFO_CREDITS' => 'standard/standard_defines.stub', 'INFO_ENVIRONMENT' => 'standard/standard_defines.stub', 'INFO_GENERAL' => 'standard/standard_defines.stub', 'INFO_LICENSE' => 'standard/standard_defines.stub', 'INFO_MODULES' => 'standard/standard_defines.stub', 'INFO_VARIABLES' => 'standard/standard_defines.stub', 'INI_ALL' => 'standard/standard_defines.stub', 'INI_PERDIR' => 'standard/standard_defines.stub', 'INI_SCANNER_NORMAL' => 'standard/standard_defines.stub', 'INI_SCANNER_RAW' => 'standard/standard_defines.stub', 'INI_SCANNER_TYPED' => 'standard/standard_defines.stub', 'INI_SYSTEM' => 'standard/standard_defines.stub', 'INI_USER' => 'standard/standard_defines.stub', 'INPUT_COOKIE' => 'filter/filter.stub', 'INPUT_ENV' => 'filter/filter.stub', 'INPUT_GET' => 'filter/filter.stub', 'INPUT_POST' => 'filter/filter.stub', 'INPUT_REQUEST' => 'filter/filter.stub', 'INPUT_SERVER' => 'filter/filter.stub', 'INPUT_SESSION' => 'filter/filter.stub', 'INTL_ICU_DATA_VERSION' => 'intl/intl.stub', 'INTL_ICU_VERSION' => 'intl/intl.stub', 'INTL_IDNA_VARIANT_2003' => 'intl/intl.stub', 'INTL_IDNA_VARIANT_UTS46' => 'intl/intl.stub', 'INTL_MAX_LOCALE_LEN' => 'intl/intl.stub', 'INT_CURR_SYMBOL' => 'standard/standard_defines.stub', 'INT_FRAC_DIGITS' => 'standard/standard_defines.stub', 'IN_ACCESS' => 'inotify/inotify.stub', 'IN_ALL_EVENTS' => 'inotify/inotify.stub', 'IN_ATTRIB' => 'inotify/inotify.stub', 'IN_CLOSE' => 'inotify/inotify.stub', 'IN_CLOSE_NOWRITE' => 'inotify/inotify.stub', 'IN_CLOSE_WRITE' => 'inotify/inotify.stub', 'IN_CREATE' => 'inotify/inotify.stub', 'IN_DELETE' => 'inotify/inotify.stub', 'IN_DELETE_SELF' => 'inotify/inotify.stub', 'IN_DONT_FOLLOW' => 'inotify/inotify.stub', 'IN_IGNORED' => 'inotify/inotify.stub', 'IN_ISDIR' => 'inotify/inotify.stub', 'IN_MASK_ADD' => 'inotify/inotify.stub', 'IN_MODIFY' => 'inotify/inotify.stub', 'IN_MOVE' => 'inotify/inotify.stub', 'IN_MOVED_FROM' => 'inotify/inotify.stub', 'IN_MOVED_TO' => 'inotify/inotify.stub', 'IN_MOVE_SELF' => 'inotify/inotify.stub', 'IN_ONESHOT' => 'inotify/inotify.stub', 'IN_ONLYDIR' => 'inotify/inotify.stub', 'IN_OPEN' => 'inotify/inotify.stub', 'IN_Q_OVERFLOW' => 'inotify/inotify.stub', 'IN_UNMOUNT' => 'inotify/inotify.stub', 'IPPROTO_IP' => 'sockets/sockets.stub', 'IPPROTO_IPV6' => 'sockets/sockets.stub', 'IPV6_HOPLIMIT' => 'sockets/sockets.stub', 'IPV6_MULTICAST_HOPS' => 'sockets/sockets.stub', 'IPV6_MULTICAST_IF' => 'sockets/sockets.stub', 'IPV6_MULTICAST_LOOP' => 'sockets/sockets.stub', 'IPV6_PKTINFO' => 'sockets/sockets.stub', 'IPV6_RECVHOPLIMIT' => 'sockets/sockets.stub', 'IPV6_RECVPKTINFO' => 'sockets/sockets.stub', 'IPV6_RECVTCLASS' => 'sockets/sockets.stub', 'IPV6_TCLASS' => 'sockets/sockets.stub', 'IPV6_UNICAST_HOPS' => 'sockets/sockets.stub', 'IPV6_V6ONLY' => 'sockets/sockets.stub', 'IP_BIND_ADDRESS_NO_PORT' => 'sockets/sockets.stub', 'IP_MTU_DISCOVER' => 'sockets/sockets.stub', 'IP_MULTICAST_IF' => 'sockets/sockets.stub', 'IP_MULTICAST_LOOP' => 'sockets/sockets.stub', 'IP_MULTICAST_TTL' => 'sockets/sockets.stub', 'IP_PMTUDISC_DO' => 'sockets/sockets.stub', 'IP_PMTUDISC_DONT' => 'sockets/sockets.stub', 'IP_PMTUDISC_INTERFACE' => 'sockets/sockets.stub', 'IP_PMTUDISC_OMIT' => 'sockets/sockets.stub', 'IP_PMTUDISC_PROBE' => 'sockets/sockets.stub', 'IP_PMTUDISC_WANT' => 'sockets/sockets.stub', 'ImageButton' => 'winbinder/winbinder.stub', 'InvisibleArea' => 'winbinder/winbinder.stub', 'JOB_QUEUE_PRIORITY_HIGH' => 'zend/zend_d.stub', 'JOB_QUEUE_PRIORITY_LOW' => 'zend/zend_d.stub', 'JOB_QUEUE_PRIORITY_NORMAL' => 'zend/zend_d.stub', 'JOB_QUEUE_PRIORITY_URGENT' => 'zend/zend_d.stub', 'JOB_QUEUE_SAVE_COOKIE' => 'zend/zend_d.stub', 'JOB_QUEUE_SAVE_ENV' => 'zend/zend_d.stub', 'JOB_QUEUE_SAVE_FILES' => 'zend/zend_d.stub', 'JOB_QUEUE_SAVE_GET' => 'zend/zend_d.stub', 'JOB_QUEUE_SAVE_POST' => 'zend/zend_d.stub', 'JOB_QUEUE_SAVE_RAW_POST' => 'zend/zend_d.stub', 'JOB_QUEUE_SAVE_SERVER' => 'zend/zend_d.stub', 'JOB_QUEUE_SAVE_SESSION' => 'zend/zend_d.stub', 'JOB_QUEUE_STATUS_EXECUTION_FAILED' => 'zend/zend_d.stub', 'JOB_QUEUE_STATUS_IN_PROCESS' => 'zend/zend_d.stub', 'JOB_QUEUE_STATUS_LOGICALLY_FAILED' => 'zend/zend_d.stub', 'JOB_QUEUE_STATUS_SCHEDULED' => 'zend/zend_d.stub', 'JOB_QUEUE_STATUS_SUCCESS' => 'zend/zend_d.stub', 'JOB_QUEUE_STATUS_SUSPENDED' => 'zend/zend_d.stub', 'JOB_QUEUE_STATUS_WAITING' => 'zend/zend_d.stub', 'JOB_QUEUE_STATUS_WAITING_PREDECESSOR' => 'zend/zend_d.stub', 'JSON_BIGINT_AS_STRING' => 'json/json.stub', 'JSON_ERROR_CTRL_CHAR' => 'json/json.stub', 'JSON_ERROR_DEPTH' => 'json/json.stub', 'JSON_ERROR_INF_OR_NAN' => 'json/json.stub', 'JSON_ERROR_INVALID_PROPERTY_NAME' => 'json/json.stub', 'JSON_ERROR_NONE' => 'json/json.stub', 'JSON_ERROR_NON_BACKED_ENUM' => 'json/json.stub', 'JSON_ERROR_RECURSION' => 'json/json.stub', 'JSON_ERROR_STATE_MISMATCH' => 'json/json.stub', 'JSON_ERROR_SYNTAX' => 'json/json.stub', 'JSON_ERROR_UNSUPPORTED_TYPE' => 'json/json.stub', 'JSON_ERROR_UTF16' => 'json/json.stub', 'JSON_ERROR_UTF8' => 'json/json.stub', 'JSON_FORCE_OBJECT' => 'json/json.stub', 'JSON_HEX_AMP' => 'json/json.stub', 'JSON_HEX_APOS' => 'json/json.stub', 'JSON_HEX_QUOT' => 'json/json.stub', 'JSON_HEX_TAG' => 'json/json.stub', 'JSON_INVALID_UTF8_IGNORE' => 'json/json.stub', 'JSON_INVALID_UTF8_SUBSTITUTE' => 'json/json.stub', 'JSON_NUMERIC_CHECK' => 'json/json.stub', 'JSON_OBJECT_AS_ARRAY' => 'json/json.stub', 'JSON_PARSER_NOTSTRICT' => 'json/json.stub', 'JSON_PARTIAL_OUTPUT_ON_ERROR' => 'json/json.stub', 'JSON_PRESERVE_ZERO_FRACTION' => 'json/json.stub', 'JSON_PRETTY_PRINT' => 'json/json.stub', 'JSON_THROW_ON_ERROR' => 'json/json.stub', 'JSON_UNESCAPED_LINE_TERMINATORS' => 'json/json.stub', 'JSON_UNESCAPED_SLASHES' => 'json/json.stub', 'JSON_UNESCAPED_UNICODE' => 'json/json.stub', 'LATT_HASCHILDREN' => 'imap/imap.stub', 'LATT_HASNOCHILDREN' => 'imap/imap.stub', 'LATT_MARKED' => 'imap/imap.stub', 'LATT_NOINFERIORS' => 'imap/imap.stub', 'LATT_NOSELECT' => 'imap/imap.stub', 'LATT_REFERRAL' => 'imap/imap.stub', 'LATT_UNMARKED' => 'imap/imap.stub', 'LC_ALL' => 'standard/standard_defines.stub', 'LC_COLLATE' => 'standard/standard_defines.stub', 'LC_CTYPE' => 'standard/standard_defines.stub', 'LC_MESSAGES' => 'standard/standard_defines.stub', 'LC_MONETARY' => 'standard/standard_defines.stub', 'LC_NUMERIC' => 'standard/standard_defines.stub', 'LC_TIME' => 'standard/standard_defines.stub', 'LDAP_CONTROL_ASSERT' => 'ldap/ldap.stub', 'LDAP_CONTROL_AUTHZID_REQUEST' => 'ldap/ldap.stub', 'LDAP_CONTROL_AUTHZID_RESPONSE' => 'ldap/ldap.stub', 'LDAP_CONTROL_DONTUSECOPY' => 'ldap/ldap.stub', 'LDAP_CONTROL_MANAGEDSAIT' => 'ldap/ldap.stub', 'LDAP_CONTROL_PAGEDRESULTS' => 'ldap/ldap.stub', 'LDAP_CONTROL_PASSWORDPOLICYREQUEST' => 'ldap/ldap.stub', 'LDAP_CONTROL_PASSWORDPOLICYRESPONSE' => 'ldap/ldap.stub', 'LDAP_CONTROL_POST_READ' => 'ldap/ldap.stub', 'LDAP_CONTROL_PRE_READ' => 'ldap/ldap.stub', 'LDAP_CONTROL_PROXY_AUTHZ' => 'ldap/ldap.stub', 'LDAP_CONTROL_SORTREQUEST' => 'ldap/ldap.stub', 'LDAP_CONTROL_SORTRESPONSE' => 'ldap/ldap.stub', 'LDAP_CONTROL_SUBENTRIES' => 'ldap/ldap.stub', 'LDAP_CONTROL_SYNC' => 'ldap/ldap.stub', 'LDAP_CONTROL_SYNC_DONE' => 'ldap/ldap.stub', 'LDAP_CONTROL_SYNC_STATE' => 'ldap/ldap.stub', 'LDAP_CONTROL_VALUESRETURNFILTER' => 'ldap/ldap.stub', 'LDAP_CONTROL_VLVREQUEST' => 'ldap/ldap.stub', 'LDAP_CONTROL_VLVRESPONSE' => 'ldap/ldap.stub', 'LDAP_CONTROL_X_DOMAIN_SCOPE' => 'ldap/ldap.stub', 'LDAP_CONTROL_X_EXTENDED_DN' => 'ldap/ldap.stub', 'LDAP_CONTROL_X_INCREMENTAL_VALUES' => 'ldap/ldap.stub', 'LDAP_CONTROL_X_PERMISSIVE_MODIFY' => 'ldap/ldap.stub', 'LDAP_CONTROL_X_SEARCH_OPTIONS' => 'ldap/ldap.stub', 'LDAP_CONTROL_X_TREE_DELETE' => 'ldap/ldap.stub', 'LDAP_DEREF_ALWAYS' => 'ldap/ldap.stub', 'LDAP_DEREF_FINDING' => 'ldap/ldap.stub', 'LDAP_DEREF_NEVER' => 'ldap/ldap.stub', 'LDAP_DEREF_SEARCHING' => 'ldap/ldap.stub', 'LDAP_ESCAPE_DN' => 'ldap/ldap.stub', 'LDAP_ESCAPE_FILTER' => 'ldap/ldap.stub', 'LDAP_EXOP_MODIFY_PASSWD' => 'ldap/ldap.stub', 'LDAP_EXOP_REFRESH' => 'ldap/ldap.stub', 'LDAP_EXOP_START_TLS' => 'ldap/ldap.stub', 'LDAP_EXOP_TURN' => 'ldap/ldap.stub', 'LDAP_EXOP_WHO_AM_I' => 'ldap/ldap.stub', 'LDAP_MODIFY_BATCH_ADD' => 'ldap/ldap.stub', 'LDAP_MODIFY_BATCH_ATTRIB' => 'ldap/ldap.stub', 'LDAP_MODIFY_BATCH_MODTYPE' => 'ldap/ldap.stub', 'LDAP_MODIFY_BATCH_REMOVE' => 'ldap/ldap.stub', 'LDAP_MODIFY_BATCH_REMOVE_ALL' => 'ldap/ldap.stub', 'LDAP_MODIFY_BATCH_REPLACE' => 'ldap/ldap.stub', 'LDAP_MODIFY_BATCH_VALUES' => 'ldap/ldap.stub', 'LDAP_OPT_CLIENT_CONTROLS' => 'ldap/ldap.stub', 'LDAP_OPT_DEBUG_LEVEL' => 'ldap/ldap.stub', 'LDAP_OPT_DEREF' => 'ldap/ldap.stub', 'LDAP_OPT_DIAGNOSTIC_MESSAGE' => 'ldap/ldap.stub', 'LDAP_OPT_ERROR_NUMBER' => 'ldap/ldap.stub', 'LDAP_OPT_ERROR_STRING' => 'ldap/ldap.stub', 'LDAP_OPT_HOST_NAME' => 'ldap/ldap.stub', 'LDAP_OPT_MATCHED_DN' => 'ldap/ldap.stub', 'LDAP_OPT_NETWORK_TIMEOUT' => 'ldap/ldap.stub', 'LDAP_OPT_PROTOCOL_VERSION' => 'ldap/ldap.stub', 'LDAP_OPT_REFERRALS' => 'ldap/ldap.stub', 'LDAP_OPT_RESTART' => 'ldap/ldap.stub', 'LDAP_OPT_SERVER_CONTROLS' => 'ldap/ldap.stub', 'LDAP_OPT_SIZELIMIT' => 'ldap/ldap.stub', 'LDAP_OPT_TIMELIMIT' => 'ldap/ldap.stub', 'LDAP_OPT_TIMEOUT' => 'ldap/ldap.stub', 'LDAP_OPT_X_KEEPALIVE_IDLE' => 'ldap/ldap.stub', 'LDAP_OPT_X_KEEPALIVE_INTERVAL' => 'ldap/ldap.stub', 'LDAP_OPT_X_KEEPALIVE_PROBES' => 'ldap/ldap.stub', 'LDAP_OPT_X_SASL_AUTHCID' => 'ldap/ldap.stub', 'LDAP_OPT_X_SASL_AUTHZID' => 'ldap/ldap.stub', 'LDAP_OPT_X_SASL_MECH' => 'ldap/ldap.stub', 'LDAP_OPT_X_SASL_NOCANON' => 'ldap/ldap.stub', 'LDAP_OPT_X_SASL_REALM' => 'ldap/ldap.stub', 'LDAP_OPT_X_SASL_USERNAME' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_ALLOW' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_CACERTDIR' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_CACERTFILE' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_CERTFILE' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_CIPHER_SUITE' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_CRLCHECK' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_CRLFILE' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_CRL_ALL' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_CRL_NONE' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_CRL_PEER' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_DEMAND' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_DHFILE' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_HARD' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_KEYFILE' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_NEVER' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_PACKAGE' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_PROTOCOL_MAX' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_PROTOCOL_MIN' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_PROTOCOL_SSL2' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_PROTOCOL_SSL3' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_0' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_1' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_2' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_3' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_RANDOM_FILE' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_REQUIRE_CERT' => 'ldap/ldap.stub', 'LDAP_OPT_X_TLS_TRY' => 'ldap/ldap.stub', 'LEVELDB_NO_COMPRESSION' => 'leveldb/LevelDB.stub', 'LEVELDB_SNAPPY_COMPRESSION' => 'leveldb/LevelDB.stub', 'LIBEXSLT_DOTTED_VERSION' => 'xsl/xsl.stub', 'LIBEXSLT_VERSION' => 'xsl/xsl.stub', 'LIBXML_BIGLINES' => 'libxml/libxml.stub', 'LIBXML_COMPACT' => 'libxml/libxml.stub', 'LIBXML_DOTTED_VERSION' => 'libxml/libxml.stub', 'LIBXML_DTDATTR' => 'libxml/libxml.stub', 'LIBXML_DTDLOAD' => 'libxml/libxml.stub', 'LIBXML_DTDVALID' => 'libxml/libxml.stub', 'LIBXML_ERR_ERROR' => 'libxml/libxml.stub', 'LIBXML_ERR_FATAL' => 'libxml/libxml.stub', 'LIBXML_ERR_NONE' => 'libxml/libxml.stub', 'LIBXML_ERR_WARNING' => 'libxml/libxml.stub', 'LIBXML_HTML_NODEFDTD' => 'libxml/libxml.stub', 'LIBXML_HTML_NOIMPLIED' => 'libxml/libxml.stub', 'LIBXML_LOADED_VERSION' => 'libxml/libxml.stub', 'LIBXML_NOBLANKS' => 'libxml/libxml.stub', 'LIBXML_NOCDATA' => 'libxml/libxml.stub', 'LIBXML_NOEMPTYTAG' => 'libxml/libxml.stub', 'LIBXML_NOENT' => 'libxml/libxml.stub', 'LIBXML_NOERROR' => 'libxml/libxml.stub', 'LIBXML_NONET' => 'libxml/libxml.stub', 'LIBXML_NOWARNING' => 'libxml/libxml.stub', 'LIBXML_NOXMLDECL' => 'libxml/libxml.stub', 'LIBXML_NSCLEAN' => 'libxml/libxml.stub', 'LIBXML_PARSEHUGE' => 'libxml/libxml.stub', 'LIBXML_PEDANTIC' => 'libxml/libxml.stub', 'LIBXML_RECOVER' => 'libxml/libxml.stub', 'LIBXML_SCHEMA_CREATE' => 'libxml/libxml.stub', 'LIBXML_VERSION' => 'libxml/libxml.stub', 'LIBXML_XINCLUDE' => 'libxml/libxml.stub', 'LIBXSLT_DOTTED_VERSION' => 'xsl/xsl.stub', 'LIBXSLT_VERSION' => 'xsl/xsl.stub', 'LIBZSTD_VERSION_NUMBER' => 'zstd/zstd.stub', 'LIBZSTD_VERSION_STRING' => 'zstd/zstd.stub', 'LIGHTGRAY' => 'winbinder/winbinder.stub', 'LOCK_EX' => 'standard/standard_defines.stub', 'LOCK_NB' => 'standard/standard_defines.stub', 'LOCK_SH' => 'standard/standard_defines.stub', 'LOCK_UN' => 'standard/standard_defines.stub', 'LOG_ALERT' => 'standard/standard_defines.stub', 'LOG_AUTH' => 'standard/standard_defines.stub', 'LOG_AUTHPRIV' => 'standard/standard_defines.stub', 'LOG_CONS' => 'standard/standard_defines.stub', 'LOG_CRIT' => 'standard/standard_defines.stub', 'LOG_CRON' => 'standard/standard_defines.stub', 'LOG_DAEMON' => 'standard/standard_defines.stub', 'LOG_DEBUG' => 'standard/standard_defines.stub', 'LOG_EMERG' => 'standard/standard_defines.stub', 'LOG_ERR' => 'standard/standard_defines.stub', 'LOG_INFO' => 'standard/standard_defines.stub', 'LOG_KERN' => 'standard/standard_defines.stub', 'LOG_LOCAL0' => 'standard/standard_defines.stub', 'LOG_LOCAL1' => 'standard/standard_defines.stub', 'LOG_LOCAL2' => 'standard/standard_defines.stub', 'LOG_LOCAL3' => 'standard/standard_defines.stub', 'LOG_LOCAL4' => 'standard/standard_defines.stub', 'LOG_LOCAL5' => 'standard/standard_defines.stub', 'LOG_LOCAL6' => 'standard/standard_defines.stub', 'LOG_LOCAL7' => 'standard/standard_defines.stub', 'LOG_LPR' => 'standard/standard_defines.stub', 'LOG_MAIL' => 'standard/standard_defines.stub', 'LOG_NDELAY' => 'standard/standard_defines.stub', 'LOG_NEWS' => 'standard/standard_defines.stub', 'LOG_NOTICE' => 'standard/standard_defines.stub', 'LOG_NOWAIT' => 'standard/standard_defines.stub', 'LOG_ODELAY' => 'standard/standard_defines.stub', 'LOG_PERROR' => 'standard/standard_defines.stub', 'LOG_PID' => 'standard/standard_defines.stub', 'LOG_SYSLOG' => 'standard/standard_defines.stub', 'LOG_USER' => 'standard/standard_defines.stub', 'LOG_UUCP' => 'standard/standard_defines.stub', 'LOG_WARNING' => 'standard/standard_defines.stub', 'Label' => 'winbinder/winbinder.stub', 'ListBox' => 'winbinder/winbinder.stub', 'ListView' => 'winbinder/winbinder.stub', 'MAGENTA' => 'winbinder/winbinder.stub', 'MAILPARSE_EXTRACT_OUTPUT' => 'mailparse/mailparse.stub', 'MAILPARSE_EXTRACT_RETURN' => 'mailparse/mailparse.stub', 'MAILPARSE_EXTRACT_STREAM' => 'mailparse/mailparse.stub', 'MB_CASE_FOLD' => 'mbstring/mbstring.stub', 'MB_CASE_FOLD_SIMPLE' => 'mbstring/mbstring.stub', 'MB_CASE_LOWER' => 'mbstring/mbstring.stub', 'MB_CASE_LOWER_SIMPLE' => 'mbstring/mbstring.stub', 'MB_CASE_TITLE' => 'mbstring/mbstring.stub', 'MB_CASE_TITLE_SIMPLE' => 'mbstring/mbstring.stub', 'MB_CASE_UPPER' => 'mbstring/mbstring.stub', 'MB_CASE_UPPER_SIMPLE' => 'mbstring/mbstring.stub', 'MB_ONIGURUMA_VERSION' => 'mbstring/mbstring.stub', 'MB_OVERLOAD_MAIL' => 'mbstring/mbstring.stub', 'MB_OVERLOAD_REGEX' => 'mbstring/mbstring.stub', 'MB_OVERLOAD_STRING' => 'mbstring/mbstring.stub', 'MCAST_BLOCK_SOURCE' => 'sockets/sockets.stub', 'MCAST_JOIN_GROUP' => 'sockets/sockets.stub', 'MCAST_JOIN_SOURCE_GROUP' => 'sockets/sockets.stub', 'MCAST_LEAVE_GROUP' => 'sockets/sockets.stub', 'MCAST_LEAVE_SOURCE_GROUP' => 'sockets/sockets.stub', 'MCAST_UNBLOCK_SOURCE' => 'sockets/sockets.stub', 'MCRYPT_3DES' => 'mcrypt/mcrypt.stub', 'MCRYPT_ARCFOUR' => 'mcrypt/mcrypt.stub', 'MCRYPT_ARCFOUR_IV' => 'mcrypt/mcrypt.stub', 'MCRYPT_BLOWFISH' => 'mcrypt/mcrypt.stub', 'MCRYPT_BLOWFISH_COMPAT' => 'mcrypt/mcrypt.stub', 'MCRYPT_CAST_128' => 'mcrypt/mcrypt.stub', 'MCRYPT_CAST_256' => 'mcrypt/mcrypt.stub', 'MCRYPT_CRYPT' => 'mcrypt/mcrypt.stub', 'MCRYPT_DECRYPT' => 'mcrypt/mcrypt.stub', 'MCRYPT_DES' => 'mcrypt/mcrypt.stub', 'MCRYPT_DES_COMPAT' => 'mcrypt/mcrypt.stub', 'MCRYPT_DEV_RANDOM' => 'mcrypt/mcrypt.stub', 'MCRYPT_DEV_URANDOM' => 'mcrypt/mcrypt.stub', 'MCRYPT_ENCRYPT' => 'mcrypt/mcrypt.stub', 'MCRYPT_ENIGNA' => 'mcrypt/mcrypt.stub', 'MCRYPT_GOST' => 'mcrypt/mcrypt.stub', 'MCRYPT_IDEA' => 'mcrypt/mcrypt.stub', 'MCRYPT_LOKI97' => 'mcrypt/mcrypt.stub', 'MCRYPT_MARS' => 'mcrypt/mcrypt.stub', 'MCRYPT_MODE_CBC' => 'mcrypt/mcrypt.stub', 'MCRYPT_MODE_CFB' => 'mcrypt/mcrypt.stub', 'MCRYPT_MODE_ECB' => 'mcrypt/mcrypt.stub', 'MCRYPT_MODE_NOFB' => 'mcrypt/mcrypt.stub', 'MCRYPT_MODE_OFB' => 'mcrypt/mcrypt.stub', 'MCRYPT_MODE_STREAM' => 'mcrypt/mcrypt.stub', 'MCRYPT_PANAMA' => 'mcrypt/mcrypt.stub', 'MCRYPT_RAND' => 'mcrypt/mcrypt.stub', 'MCRYPT_RC2' => 'mcrypt/mcrypt.stub', 'MCRYPT_RC4' => 'mcrypt/mcrypt.stub', 'MCRYPT_RC6' => 'mcrypt/mcrypt.stub', 'MCRYPT_RC6_128' => 'mcrypt/mcrypt.stub', 'MCRYPT_RC6_192' => 'mcrypt/mcrypt.stub', 'MCRYPT_RC6_256' => 'mcrypt/mcrypt.stub', 'MCRYPT_RIJNDAEL_128' => 'mcrypt/mcrypt.stub', 'MCRYPT_RIJNDAEL_192' => 'mcrypt/mcrypt.stub', 'MCRYPT_RIJNDAEL_256' => 'mcrypt/mcrypt.stub', 'MCRYPT_SAFER128' => 'mcrypt/mcrypt.stub', 'MCRYPT_SAFER64' => 'mcrypt/mcrypt.stub', 'MCRYPT_SAFERPLUS' => 'mcrypt/mcrypt.stub', 'MCRYPT_SERPENT' => 'mcrypt/mcrypt.stub', 'MCRYPT_SERPENT_128' => 'mcrypt/mcrypt.stub', 'MCRYPT_SERPENT_192' => 'mcrypt/mcrypt.stub', 'MCRYPT_SERPENT_256' => 'mcrypt/mcrypt.stub', 'MCRYPT_SKIPJACK' => 'mcrypt/mcrypt.stub', 'MCRYPT_THREEWAY' => 'mcrypt/mcrypt.stub', 'MCRYPT_TRIPLEDES' => 'mcrypt/mcrypt.stub', 'MCRYPT_TWOFISH' => 'mcrypt/mcrypt.stub', 'MCRYPT_WAKE' => 'mcrypt/mcrypt.stub', 'MCRYPT_XTEA' => 'mcrypt/mcrypt.stub', 'MEMCACHE_COMPRESSED' => 'memcache/memcache.stub', 'MEMCACHE_HAVE_SESSION' => 'memcache/memcache.stub', 'MEMCACHE_USER1' => 'memcache/memcache.stub', 'MEMCACHE_USER2' => 'memcache/memcache.stub', 'MEMCACHE_USER3' => 'memcache/memcache.stub', 'MEMCACHE_USER4' => 'memcache/memcache.stub', 'MESSAGEPACK_OPT_PHPONLY' => 'msgpack/msgpack.stub', 'MHASH_ADLER32' => 'hash/hash.stub', 'MHASH_CRC32' => 'hash/hash.stub', 'MHASH_CRC32B' => 'hash/hash.stub', 'MHASH_CRC32C' => 'hash/hash.stub', 'MHASH_FNV132' => 'hash/hash.stub', 'MHASH_FNV164' => 'hash/hash.stub', 'MHASH_FNV1A32' => 'hash/hash.stub', 'MHASH_FNV1A64' => 'hash/hash.stub', 'MHASH_GOST' => 'hash/hash.stub', 'MHASH_HAVAL128' => 'hash/hash.stub', 'MHASH_HAVAL160' => 'hash/hash.stub', 'MHASH_HAVAL192' => 'hash/hash.stub', 'MHASH_HAVAL224' => 'hash/hash.stub', 'MHASH_HAVAL256' => 'hash/hash.stub', 'MHASH_JOAAT' => 'hash/hash.stub', 'MHASH_MD2' => 'hash/hash.stub', 'MHASH_MD4' => 'hash/hash.stub', 'MHASH_MD5' => 'hash/hash.stub', 'MHASH_MURMUR3A' => 'hash/hash.stub', 'MHASH_MURMUR3C' => 'hash/hash.stub', 'MHASH_MURMUR3F' => 'hash/hash.stub', 'MHASH_RIPEMD128' => 'hash/hash.stub', 'MHASH_RIPEMD160' => 'hash/hash.stub', 'MHASH_RIPEMD256' => 'hash/hash.stub', 'MHASH_RIPEMD320' => 'hash/hash.stub', 'MHASH_SHA1' => 'hash/hash.stub', 'MHASH_SHA224' => 'hash/hash.stub', 'MHASH_SHA256' => 'hash/hash.stub', 'MHASH_SHA384' => 'hash/hash.stub', 'MHASH_SHA512' => 'hash/hash.stub', 'MHASH_SNEFRU256' => 'hash/hash.stub', 'MHASH_TIGER' => 'hash/hash.stub', 'MHASH_TIGER128' => 'hash/hash.stub', 'MHASH_TIGER160' => 'hash/hash.stub', 'MHASH_WHIRLPOOL' => 'hash/hash.stub', 'MHASH_XXH128' => 'hash/hash.stub', 'MHASH_XXH3' => 'hash/hash.stub', 'MHASH_XXH32' => 'hash/hash.stub', 'MHASH_XXH64' => 'hash/hash.stub', 'MING_NEW' => 'ming/ming.stub', 'MING_ZLIB' => 'ming/ming.stub', 'MK_E_UNAVAILABLE' => 'com_dotnet/com_dotnet.stub', 'MONGODB_STABILITY' => 'mongodb/mongodb.stub', 'MONGODB_VERSION' => 'mongodb/mongodb.stub', 'MON_1' => 'standard/standard_defines.stub', 'MON_10' => 'standard/standard_defines.stub', 'MON_11' => 'standard/standard_defines.stub', 'MON_12' => 'standard/standard_defines.stub', 'MON_2' => 'standard/standard_defines.stub', 'MON_3' => 'standard/standard_defines.stub', 'MON_4' => 'standard/standard_defines.stub', 'MON_5' => 'standard/standard_defines.stub', 'MON_6' => 'standard/standard_defines.stub', 'MON_7' => 'standard/standard_defines.stub', 'MON_8' => 'standard/standard_defines.stub', 'MON_9' => 'standard/standard_defines.stub', 'MON_DECIMAL_POINT' => 'standard/standard_defines.stub', 'MON_GROUPING' => 'standard/standard_defines.stub', 'MON_THOUSANDS_SEP' => 'standard/standard_defines.stub', 'MQSERIES_MQACT_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_AIX' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_BATCH' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_BROKER' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_CHANNEL_INITIATOR' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_CICS' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_CICS_BRIDGE' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_CICS_VSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_DEFAULT' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_DOS' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_DQM' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_GUARDIAN' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_IMS' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_IMS_BRIDGE' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_JAVA' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_MCAST_PUBLISH' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_MVS' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_NOTES_AGENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_NO_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_NSK' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_OPEN_TP1' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_OS2' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_OS390' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_OS400' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_QMGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_QMGR_PUBLISH' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_RRS_BATCH' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_SIB' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_SYSTEM_EXTENSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_TPF' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_UNIX' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_UNKNOWN' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_USER' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_USER_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_USER_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_VM' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_VMS' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_VOS' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_WINDOWS' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_WINDOWS_NT' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_WLM' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_XCF' => 'mqseries/mqseries.stub', 'MQSERIES_MQAT_ZOS' => 'mqseries/mqseries.stub', 'MQSERIES_MQBO_CURRENT_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQBO_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQBO_VERSION_1' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_ADMIN_TOPIC_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_ALTERATION_DATE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_ALTERATION_TIME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_APPL_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_AUTH_INFO_CONN_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_AUTH_INFO_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_AUTH_INFO_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_AUTH_INFO_OCSP_URL' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_AUTO_REORG_CATALOG' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_AUTO_REORG_START_TIME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_BACKOUT_REQ_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_BASE_OBJECT_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_BASE_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_BATCH_INTERFACE_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CF_STRUC_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CF_STRUC_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CHANNEL_AUTO_DEF_EXIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CHILD' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CHINIT_SERVICE_PARM' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CHLAUTH_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CICS_FILE_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CLUSTER_DATE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CLUSTER_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CLUSTER_NAMELIST' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CLUSTER_Q_MGR_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CLUSTER_TIME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CLUSTER_WORKLOAD_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CLUSTER_WORKLOAD_EXIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CLUS_CHL_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_COMMAND_INPUT_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_COMMAND_REPLY_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_COMM_INFO_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_COMM_INFO_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CREATION_DATE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CREATION_TIME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_CUSTOM' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_DEAD_LETTER_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_DEF_XMIT_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_DNS_GROUP' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_ENV_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_IGQ_USER_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_INITIATION_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_INSTALLATION_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_INSTALLATION_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_INSTALLATION_PATH' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_LAST_USED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_LDAP_PASSWORD' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_LDAP_USER_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_LU62_ARM_SUFFIX' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_LU_GROUP_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_LU_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_MODEL_DURABLE_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_MODEL_NON_DURABLE_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_MONITOR_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_NAMELIST_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_NAMELIST_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_NAMES' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_PARENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_PASS_TICKET_APPL' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_POLICY_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_PROCESS_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_PROCESS_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_QSG_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_Q_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_Q_MGR_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_Q_MGR_IDENTIFIER' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_Q_MGR_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_RECIPIENT_DN' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_REMOTE_Q_MGR_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_REMOTE_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_REPOSITORY_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_REPOSITORY_NAMELIST' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_RESUME_DATE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_RESUME_TIME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SERVICE_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SERVICE_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SERVICE_START_ARGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SERVICE_START_COMMAND' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SERVICE_STOP_ARGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SERVICE_STOP_COMMAND' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SIGNER_DN' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SSL_CRL_NAMELIST' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SSL_CRYPTO_HARDWARE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SSL_KEY_LIBRARY' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SSL_KEY_MEMBER' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SSL_KEY_REPOSITORY' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_STDERR_DESTINATION' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_STDOUT_DESTINATION' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_STORAGE_CLASS' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_STORAGE_CLASS_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_SYSTEM_LOG_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TCP_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TOPIC_DESC' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TOPIC_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TOPIC_STRING' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TOPIC_STRING_FILTER' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TPIPE_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TRIGGER_CHANNEL_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TRIGGER_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TRIGGER_PROGRAM_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TRIGGER_TERM_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_TRIGGER_TRANS_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_USER_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_USER_LIST' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_XCF_GROUP_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_XCF_MEMBER_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_XMIT_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_XR_SSL_CIPHER_SUITES' => 'mqseries/mqseries.stub', 'MQSERIES_MQCA_XR_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQCCSI_APPL' => 'mqseries/mqseries.stub', 'MQSERIES_MQCCSI_AS_PUBLISHED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCCSI_DEFAULT' => 'mqseries/mqseries.stub', 'MQSERIES_MQCCSI_EMBEDDED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCCSI_INHERIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQCCSI_Q_MGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQCCSI_UNDEFINED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCC_FAILED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCC_OK' => 'mqseries/mqseries.stub', 'MQSERIES_MQCC_UNKNOWN' => 'mqseries/mqseries.stub', 'MQSERIES_MQCC_WARNING' => 'mqseries/mqseries.stub', 'MQSERIES_MQCI_NEW_SESSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQCI_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_ACCOUNTING_MQI_DISABLED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_ACCOUNTING_MQI_ENABLED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_ACCOUNTING_Q_DISABLED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_ACCOUNTING_Q_ENABLED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_ACTIVITY_TRACE_DISABLED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_ACTIVITY_TRACE_ENABLED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_ALL_CONVS_SHARE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_CD_FOR_OUTPUT_ONLY' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_CLIENT_BINDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_CURRENT_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_FASTPATH_BINDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_HANDLE_SHARE_BLOCK' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_HANDLE_SHARE_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_HANDLE_SHARE_NO_BLOCK' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_ISOLATED_BINDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_LOCAL_BINDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_NO_CONV_SHARING' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_RECONNECT' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_RECONNECT_AS_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_RECONNECT_DISABLED' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_RECONNECT_Q_MGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_RESTRICT_CONN_TAG_QSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_RESTRICT_CONN_TAG_Q_MGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_SERIALIZE_CONN_TAG_QSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_SERIALIZE_CONN_TAG_Q_MGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_SHARED_BINDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_STANDARD_BINDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_USE_CD_SELECTION' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_VERSION_1' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_VERSION_2' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_VERSION_3' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_VERSION_4' => 'mqseries/mqseries.stub', 'MQSERIES_MQCNO_VERSION_5' => 'mqseries/mqseries.stub', 'MQSERIES_MQCO_DELETE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCO_DELETE_PURGE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCO_IMMEDIATE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCO_KEEP_SUB' => 'mqseries/mqseries.stub', 'MQSERIES_MQCO_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCO_QUIESCE' => 'mqseries/mqseries.stub', 'MQSERIES_MQCO_REMOVE_SUB' => 'mqseries/mqseries.stub', 'MQSERIES_MQEC_CONNECTION_QUIESCING' => 'mqseries/mqseries.stub', 'MQSERIES_MQEC_MSG_ARRIVED' => 'mqseries/mqseries.stub', 'MQSERIES_MQEC_Q_MGR_QUIESCING' => 'mqseries/mqseries.stub', 'MQSERIES_MQEC_WAIT_CANCELED' => 'mqseries/mqseries.stub', 'MQSERIES_MQEC_WAIT_INTERVAL_EXPIRED' => 'mqseries/mqseries.stub', 'MQSERIES_MQEI_UNLIMITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_AS_PUBLISHED' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_DECIMAL_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_DECIMAL_NORMAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_DECIMAL_REVERSED' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_DECIMAL_UNDEFINED' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_FLOAT_IEEE_NORMAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_FLOAT_IEEE_REVERSED' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_FLOAT_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_FLOAT_S390' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_FLOAT_TNS' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_FLOAT_UNDEFINED' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_INTEGER_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_INTEGER_NORMAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_INTEGER_REVERSED' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_INTEGER_UNDEFINED' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_NATIVE' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_NORMAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_RESERVED_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_REVERSED' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_S390' => 'mqseries/mqseries.stub', 'MQSERIES_MQENC_TNS' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_ACTIVITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_APPL_CANNOT_BE_STARTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_APPL_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_APPL_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_APPL_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_BIND_OPEN_CLUSRCVR_DEL' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_BUFFER_OVERFLOW' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CHANNEL_COMPLETED' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CHANNEL_FAIL' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CHANNEL_FAIL_RETRY' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_APPL_ABENDED' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_APPL_NOT_STARTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_BRIDGE_FAILURE' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_CCSID_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_CIH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_COMMAREA_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_CORREL_ID_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_DLQ_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_ENCODING_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_INTERNAL_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_NOT_AUTHORIZED' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_UOW_BACKED_OUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_CICS_UOW_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_COA' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_COD' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_DATA_LENGTH_NEGATIVE' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_DATA_LENGTH_TOO_BIG' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_DATA_LENGTH_ZERO' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_EXPIRATION' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_IIH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_IMS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_IMS_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_IMS_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_IMS_NACK_1A_REASON_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_IMS_NACK_1A_REASON_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_LENGTH_OFF_BY_ONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_MAX_ACTIVITIES' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_MSG_SCOPE_MISMATCH' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_NAN' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_NOT_AUTHORIZED_FOR_IMS' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_NOT_A_GROUPUR_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_NOT_A_REPOSITORY_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_NOT_DELIVERED' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_NOT_FORWARDED' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_PAN' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_PUBLICATIONS_ON_REQUEST' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_QUIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_SELECTOR_MISMATCH' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_STOPPED_BY_CHAD_EXIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_STOPPED_BY_MSG_EXIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_STOPPED_BY_PUBSUB_EXIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_SUBSCRIBER_IS_PUBLISHER' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_SYSTEM_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_SYSTEM_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_TM_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_UNSUPPORTED_DELIVERY' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_UNSUPPORTED_FORWARDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQFB_XMIT_Q_MSG_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_ADMIN' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_CHANNEL_COMPLETED' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_CICS' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_COMMAND_1' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_COMMAND_2' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_DEAD_LETTER_HEADER' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_DIST_HEADER' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_EMBEDDED_PCF' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_IMS' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_IMS_VAR_STRING' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_MD_EXTENSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_PCF' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_REF_MSG_HEADER' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_RF_HEADER' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_RF_HEADER_1' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_RF_HEADER_2' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_STRING' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_TRIGGER' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_WORK_INFO_HEADER' => 'mqseries/mqseries.stub', 'MQSERIES_MQFMT_XMIT_Q_HEADER' => 'mqseries/mqseries.stub', 'MQSERIES_MQGI_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_ACCEPT_TRUNCATED_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_ALL_MSGS_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_ALL_SEGMENTS_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_BROWSE_CO_OP' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_BROWSE_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_BROWSE_HANDLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_BROWSE_MSG_UNDER_CURSOR' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_BROWSE_NEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_COMPLETE_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_CONVERT' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_CURRENT_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_FAIL_IF_QUIESCING' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_LOCK' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_LOGICAL_ORDER' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_MARK_BROWSE_CO_OP' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_MARK_BROWSE_HANDLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_MARK_SKIP_BACKOUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_MSG_UNDER_CURSOR' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_NO_PROPERTIES' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_NO_SYNCPOINT' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_NO_WAIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_PROPERTIES_AS_Q_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_PROPERTIES_COMPATIBILITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_PROPERTIES_FORCE_MQRFH2' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_PROPERTIES_IN_HANDLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_SET_SIGNAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_SYNCPOINT' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_SYNCPOINT_IF_PERSISTENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_UNLOCK' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_UNMARKED_BROWSE_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_UNMARK_BROWSE_CO_OP' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_UNMARK_BROWSE_HANDLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_VERSION_1' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_VERSION_2' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_VERSION_3' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_VERSION_4' => 'mqseries/mqseries.stub', 'MQSERIES_MQGMO_WAIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ACCOUNTING_CONN_OVERRIDE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ACCOUNTING_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ACCOUNTING_MQI' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ACCOUNTING_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ACTIVE_CHANNELS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ACTIVITY_CONN_OVERRIDE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ACTIVITY_RECORDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ACTIVITY_TRACE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ADOPTNEWMCA_CHECK' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ADOPTNEWMCA_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ADOPTNEWMCA_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_APPL_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ARCHIVE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_AUTHORITY_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_AUTH_INFO_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_AUTO_REORGANIZATION' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_AUTO_REORG_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_BACKOUT_THRESHOLD' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_BASE_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_BATCH_INTERFACE_AUTO' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_BRIDGE_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CERT_VAL_POLICY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_CFCONLOS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_LEVEL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_OFFLDUSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_OFFLOAD' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_OFFLOAD_THRESHOLD1' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_OFFLOAD_THRESHOLD2' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_OFFLOAD_THRESHOLD3' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_RECAUTO' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_RECOVER' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CF_SMDS_BUFFERS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CHANNEL_AUTO_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CHANNEL_AUTO_DEF_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CHANNEL_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CHINIT_ADAPTERS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CHINIT_CONTROL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CHINIT_DISPATCHERS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CHINIT_TRACE_AUTO_START' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CHINIT_TRACE_TABLE_SIZE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CHLAUTH_RECORDS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CLUSTER_Q_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CLUSTER_WORKLOAD_LENGTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CLWL_MRU_CHANNELS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CLWL_Q_PRIORITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CLWL_Q_RANK' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CLWL_USEQ' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CMD_SERVER_AUTO' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CMD_SERVER_CONTROL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CMD_SERVER_CONVERT_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CMD_SERVER_DLQ_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CODED_CHAR_SET_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_COMMAND_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_COMMAND_LEVEL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_COMM_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_COMM_INFO_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CONFIGURATION_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CPI_LEVEL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_CURRENT_Q_DEPTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DEFINITION_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DEF_BIND' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DEF_CLUSTER_XMIT_Q_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DEF_INPUT_OPEN_OPTION' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DEF_PERSISTENCE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DEF_PRIORITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DEF_PUT_RESPONSE_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DEF_READ_AHEAD' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DIST_LISTS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DNS_WLM' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_DURABLE_SUB' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_ENCRYPTION_ALGORITHM' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_EXPIRY_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_GROUP_UR' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_HARDEN_GET_BACKOUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_HIGH_Q_DEPTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_IGQ_PUT_AUTHORITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_INDEX_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_INHIBIT_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_INHIBIT_GET' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_INHIBIT_PUB' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_INHIBIT_PUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_INHIBIT_SUB' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_INTRA_GROUP_QUEUING' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_IP_ADDRESS_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_LISTENER_PORT_NUMBER' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_LISTENER_TIMER' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_LOCAL_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_LOGGER_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_LU62_CHANNELS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MASTER_ADMIN' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_CHANNELS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_CLIENTS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_GLOBAL_LOCKS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_HANDLES' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_LOCAL_LOCKS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_MSG_LENGTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_OPEN_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_PRIORITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_PROPERTIES_LENGTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_Q_DEPTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_Q_TRIGGERS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_RECOVERY_TASKS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_RESPONSES' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MAX_UNCOMMITTED_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MCAST_BRIDGE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MONITORING_AUTO_CLUSSDR' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MONITORING_CHANNEL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MONITORING_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MONITOR_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MSG_DELIVERY_SEQUENCE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MSG_DEQ_COUNT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MSG_ENQ_COUNT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MSG_MARK_BROWSE_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_MULTICAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_NAMELIST_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_NAME_COUNT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_NPM_CLASS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_NPM_DELIVERY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_OPEN_INPUT_COUNT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_OPEN_OUTPUT_COUNT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_OUTBOUND_PORT_MAX' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_OUTBOUND_PORT_MIN' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PAGESET_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PERFORMANCE_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PLATFORM' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PM_DELIVERY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_POLICY_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PROPERTY_CONTROL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PROT_POLICY_CAPABILITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PROXY_SUB' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PUBSUB_CLUSTER' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PUBSUB_MAXMSG_RETRY_COUNT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PUBSUB_MODE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PUBSUB_NP_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PUBSUB_NP_RESP' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PUBSUB_SYNC_PT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PUB_COUNT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_PUB_SCOPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMGR_CFCONLOS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_CONS_COMMS_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_CONS_CRITICAL_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_CONS_ERROR_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_CONS_INFO_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_CONS_REORG_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_CONS_SYSTEM_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_CONS_WARNING_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_CSMT_ON_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_INTERNAL_DUMP' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_LOG_COMMS_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_LOG_CRITICAL_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_LOG_ERROR_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_LOG_INFO_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_LOG_REORG_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_LOG_SYSTEM_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_LOG_WARNING_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_TRACE_COMMS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_TRACE_CONVERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_TRACE_MQI_CALLS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_TRACE_REORG' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QMOPT_TRACE_SYSTEM' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_QSG_DISP' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_Q_DEPTH_HIGH_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_Q_DEPTH_HIGH_LIMIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_Q_DEPTH_LOW_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_Q_DEPTH_LOW_LIMIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_Q_DEPTH_MAX_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_Q_SERVICE_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_Q_SERVICE_INTERVAL_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_Q_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_Q_USERS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_READ_AHEAD' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_RECEIVE_TIMEOUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_RECEIVE_TIMEOUT_MIN' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_RECEIVE_TIMEOUT_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_REMOTE_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_RESPONSE_RESTART_POINT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_RETENTION_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SCOPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SECURITY_CASE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SERVICE_CONTROL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SERVICE_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SHAREABILITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SHARED_Q_Q_MGR_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SIGNATURE_ALGORITHM' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SSL_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SSL_FIPS_REQUIRED' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SSL_RESET_COUNT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SSL_TASKS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_START_STOP_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_STATISTICS_AUTO_CLUSSDR' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_STATISTICS_CHANNEL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_STATISTICS_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_STATISTICS_MQI' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_STATISTICS_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SUB_CONFIGURATION_EVENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SUB_COUNT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SUB_SCOPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SUITE_B_STRENGTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_SYNCPOINT' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TCP_CHANNELS' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TCP_KEEP_ALIVE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TCP_STACK_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TIME_SINCE_RESET' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TOLERATE_UNPROTECTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TOPIC_DEF_PERSISTENCE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TOPIC_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TRACE_ROUTE_RECORDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TREE_LIFE_TIME' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TRIGGER_CONTROL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TRIGGER_DEPTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TRIGGER_INTERVAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TRIGGER_MSG_PRIORITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TRIGGER_RESTART' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_TRIGGER_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_UR_DISP' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_USAGE' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_USER_LIST' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_USE_DEAD_LETTER_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_WILDCARD_OPERATION' => 'mqseries/mqseries.stub', 'MQSERIES_MQIA_XR_CAPABILITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQMD_CURRENT_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQMD_VERSION_1' => 'mqseries/mqseries.stub', 'MQSERIES_MQMD_VERSION_2' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_ACCEPT_UNSUP_IF_XMIT_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_ACCEPT_UNSUP_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_LAST_MSG_IN_GROUP' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_LAST_SEGMENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_MSG_IN_GROUP' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_REJECT_UNSUP_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_SEGMENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_SEGMENTATION_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQMF_SEGMENTATION_INHIBITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQMI_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQMO_MATCH_CORREL_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQMO_MATCH_GROUP_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQMO_MATCH_MSG_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQMO_MATCH_MSG_SEQ_NUMBER' => 'mqseries/mqseries.stub', 'MQSERIES_MQMO_MATCH_MSG_TOKEN' => 'mqseries/mqseries.stub', 'MQSERIES_MQMO_MATCH_OFFSET' => 'mqseries/mqseries.stub', 'MQSERIES_MQMO_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQMTOK_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_APPL_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_APPL_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_DATAGRAM' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_MQE_FIELDS' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_MQE_FIELDS_FROM_MQE' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_REPLY' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_REPORT' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_REQUEST' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_SYSTEM_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQMT_SYSTEM_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQOD_CURRENT_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQOD_VERSION_1' => 'mqseries/mqseries.stub', 'MQSERIES_MQOD_VERSION_2' => 'mqseries/mqseries.stub', 'MQSERIES_MQOD_VERSION_3' => 'mqseries/mqseries.stub', 'MQSERIES_MQOD_VERSION_4' => 'mqseries/mqseries.stub', 'MQSERIES_MQOL_UNDEFINED' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_ALTERNATE_USER_AUTHORITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_BIND_AS_Q_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_BIND_NOT_FIXED' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_BIND_ON_GROUP' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_BIND_ON_OPEN' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_BROWSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_CO_OP' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_FAIL_IF_QUIESCING' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_INPUT_AS_Q_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_INPUT_EXCLUSIVE' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_INPUT_SHARED' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_INQUIRE' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_NO_MULTICAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_NO_READ_AHEAD' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_OUTPUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_PASS_ALL_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_PASS_IDENTITY_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_READ_AHEAD' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_READ_AHEAD_AS_Q_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_RESOLVE_LOCAL_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_RESOLVE_LOCAL_TOPIC' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_SAVE_ALL_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_SET' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_SET_ALL_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQOO_SET_IDENTITY_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_AUTH_INFO' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_CF_STRUC' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_CHANNEL' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_COMM_INFO' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_LISTENER' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_NAMELIST' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_PROCESS' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_Q_MGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_RESERVED_1' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_SERVICE' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_STORAGE_CLASS' => 'mqseries/mqseries.stub', 'MQSERIES_MQOT_TOPIC' => 'mqseries/mqseries.stub', 'MQSERIES_MQPER_NOT_PERSISTENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPER_PERSISTENCE_AS_PARENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPER_PERSISTENCE_AS_Q_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQPER_PERSISTENCE_AS_TOPIC_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQPER_PERSISTENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_ALTERNATE_USER_AUTHORITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_ASYNC_RESPONSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_CURRENT_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_DEFAULT_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_FAIL_IF_QUIESCING' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_LOGICAL_ORDER' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_MD_FOR_OUTPUT_ONLY' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_NEW_CORREL_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_NEW_MSG_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_NOT_OWN_SUBS' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_NO_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_NO_SYNCPOINT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_PASS_ALL_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_PASS_IDENTITY_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_RESOLVE_LOCAL_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_RESPONSE_AS_Q_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_RESPONSE_AS_TOPIC_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_RETAIN' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_SCOPE_QMGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_SET_ALL_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_SET_IDENTITY_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_SUPPRESS_REPLYTO' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_SYNCPOINT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_SYNC_RESPONSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_VERSION_1' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_VERSION_2' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_VERSION_3' => 'mqseries/mqseries.stub', 'MQSERIES_MQPMO_WARN_IF_NO_SUBS_MATCHED' => 'mqseries/mqseries.stub', 'MQSERIES_MQPRI_PRIORITY_AS_PARENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPRI_PRIORITY_AS_PUBLISHED' => 'mqseries/mqseries.stub', 'MQSERIES_MQPRI_PRIORITY_AS_Q_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQPRI_PRIORITY_AS_TOPIC_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQPRT_ASYNC_RESPONSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQPRT_RESPONSE_AS_PARENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQPRT_SYNC_RESPONSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ACTION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ADAPTER_CONN_LOAD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ADAPTER_CONV_LOAD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ADAPTER_DEFS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ADAPTER_DEFS_LOAD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ADAPTER_DISC_LOAD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ADAPTER_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ADAPTER_SERV_LOAD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ADAPTER_STORAGE_SHORTAGE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_AIR_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ALIAS_BASE_Q_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ALIAS_TARGTYPE_CHANGED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ALREADY_CONNECTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ALREADY_JOINED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ALTER_SUB_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ANOTHER_Q_MGR_CONNECTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_API_EXIT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_API_EXIT_INIT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_API_EXIT_LOAD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_API_EXIT_NOT_FOUND' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_API_EXIT_TERM_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_APPL_FIRST' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_APPL_LAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ASID_MISMATCH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ASYNC_UOW_CONFLICT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ASYNC_XA_CONFLICT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ATTRIBUTE_LOCKED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_AUTH_INFO_CONN_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_AUTH_INFO_REC_COUNT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_AUTH_INFO_REC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_AUTH_INFO_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BACKED_OUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BACKOUT_THRESHOLD_REACHED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BAG_CONVERSION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BAG_WRONG_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BINARY_DATA_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BMHO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BRIDGE_STARTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BRIDGE_STOPPED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BUFFER_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BUFFER_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_BUFFER_NOT_AUTOMATIC' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CALLBACK_LINK_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CALLBACK_NOT_REGISTERED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CALLBACK_ROUTINE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CALLBACK_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CALL_INTERRUPTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CALL_IN_PROGRESS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CBD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CBD_OPTIONS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CD_ARRAY_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CERT_VAL_POLICY_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFBF_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFBS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFGR_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFIF_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFIL_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFIN_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFSF_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFSL_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CFST_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CF_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CF_STRUC_AUTH_FAILED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CF_STRUC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CF_STRUC_FAILED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CF_STRUC_IN_USE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CF_STRUC_LIST_HDR_IN_USE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_ACTIVATED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_AUTO_DEF_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_AUTO_DEF_OK' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_BLOCKED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_BLOCKED_WARNING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_CONFIG_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_CONV_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_NOT_ACTIVATED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_SSL_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_SSL_WARNING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_STARTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_STOPPED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHANNEL_STOPPED_BY_USER' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHAR_ATTRS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHAR_ATTRS_TOO_SHORT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHAR_ATTR_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CHAR_CONVERSION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CICS_BRIDGE_RESTRICTION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CICS_WAIT_FAILED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CIPHER_SPEC_NOT_SUITE_B' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CLIENT_CHANNEL_CONFLICT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CLIENT_CONN_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CLIENT_EXIT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CLIENT_EXIT_LOAD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CLUSTER_EXIT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CLUSTER_EXIT_LOAD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CLUSTER_PUT_INHIBITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CLUSTER_RESOLUTION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CLUSTER_RESOURCE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CMD_SERVER_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CMHO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CNO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CODED_CHAR_SET_ID_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_COD_NOT_VALID_FOR_XCF_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_COMMAND_MQSC' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_COMMAND_PCF' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_COMMAND_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_COMMINFO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONFIG_CHANGE_OBJECT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONFIG_CREATE_OBJECT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONFIG_DELETE_OBJECT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONFIG_REFRESH_OBJECT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONNECTION_BROKEN' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONNECTION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONNECTION_NOT_AUTHORIZED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONNECTION_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONNECTION_QUIESCING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONNECTION_STOPPED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONNECTION_STOPPING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONNECTION_SUSPENDED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONN_ID_IN_USE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONN_TAG_IN_USE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONN_TAG_NOT_RELEASED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONN_TAG_NOT_USABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONTENT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONTEXT_HANDLE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONTEXT_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONTEXT_OBJECT_NOT_VALID' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONTEXT_OPEN_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONVERTED_MSG_TOO_BIG' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CONVERTED_STRING_TOO_BIG' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CORREL_ID_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CRYPTO_HARDWARE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CTLO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CURRENT_RECORD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_CURSOR_NOT_VALID' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DATA_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DATA_SET_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DATA_TRUNCATED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DB2_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DBCS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DEF_SYNCPOINT_INHIBITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DEF_XMIT_Q_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DEF_XMIT_Q_USAGE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DEST_CLASS_NOT_ALTERABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DEST_ENV_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DEST_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DISTRIBUTION_LIST_EMPTY' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DLH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DMHO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DMPO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DUPLICATE_GROUP_SUB' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DUPLICATE_RECOV_COORD' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DURABILITY_NOT_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DURABILITY_NOT_ALTERABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_DYNAMIC_Q_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ENCODING_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ENCODING_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ENVIRONMENT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_EPH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_EXIT_PROPS_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_EXIT_REASON_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_EXPIRY_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_FASTPATH_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_FEEDBACK_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_FILE_NOT_AUDITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_FILE_SYSTEM_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_FILTER_OPERATOR_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_FORMAT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_FORMAT_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_FUNCTION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_FUNCTION_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_GET_ENABLED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_GET_INHIBITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_GLOBAL_UOW_CONFLICT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_GMO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_GROUPING_NOT_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_GROUPING_NOT_ALTERABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_GROUP_ADDRESS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_GROUP_ID_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HANDLE_IN_USE_FOR_UOW' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HANDLE_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HBAG_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HCONFIG_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HCONN_ASYNC_ACTIVE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HCONN_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HEADER_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HMSG_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HMSG_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HOBJ_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HOBJ_QUIESCED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HOBJ_QUIESCED_NO_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_HOST_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_IDENTITY_MISMATCH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_IIH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_IMPO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCOMPLETE_GROUP' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCOMPLETE_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCONSISTENT_BROWSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCONSISTENT_CCSIDS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCONSISTENT_ENCODINGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCONSISTENT_FORMAT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCONSISTENT_ITEM_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCONSISTENT_OBJECT_STATE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCONSISTENT_OPEN_OPTIONS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCONSISTENT_PERSISTENCE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INCONSISTENT_UOW' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INDEX_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INDEX_NOT_PRESENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INHIBIT_VALUE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INITIALIZATION_FAILED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INQUIRY_COMMAND_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INSTALLATION_MISMATCH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INSTALLATION_MISSING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INSUFFICIENT_BUFFER' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INSUFFICIENT_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INT_ATTRS_ARRAY_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INT_ATTR_COUNT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INT_ATTR_COUNT_TOO_SMALL' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INVALID_DESTINATION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INVALID_MSG_UNDER_CURSOR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_INVALID_SUBSCRIPTION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ITEM_COUNT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ITEM_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ITEM_VALUE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_JMS_FORMAT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_JSSE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_KEY_REPOSITORY_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_LDAP_PASSWORD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_LDAP_USER_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_LDAP_USER_NAME_LENGTH_ERR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_LOCAL_UOW_CONFLICT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_LOGGER_STATUS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_LOOPING_PUBLICATION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MATCH_OPTIONS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MAX_CONNS_LIMIT_REACHED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MAX_MSG_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MCAST_PUB_STATUS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MCAST_SUB_STATUS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MDE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MHBO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MISSING_REPLY_TO_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MISSING_WIH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MIXED_CONTENT_NOT_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MODULE_ENTRY_NOT_FOUND' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MODULE_INVALID' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MODULE_NOT_FOUND' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_FLAGS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_HANDLE_COPY_FAILURE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_HANDLE_IN_USE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_ID_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_MARKED_BROWSE_CO_OP' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_NOT_ALLOWED_IN_GROUP' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_NOT_MATCHED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_SEQ_NUMBER_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_TOKEN_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_TOO_BIG_FOR_CHANNEL' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_TOO_BIG_FOR_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_TOO_BIG_FOR_Q_MGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MSG_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MULTICAST_CONFIG_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MULTICAST_INTERFACE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MULTICAST_INTERNAL_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MULTICAST_ONLY' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MULTICAST_SEND_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MULTIPLE_INSTANCE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_MULTIPLE_REASONS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NAME_IN_USE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NAME_NOT_VALID_FOR_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NEGATIVE_LENGTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NEGATIVE_OFFSET' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NESTED_BAG_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NESTED_SELECTOR_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NEXT_OFFSET_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NEXT_RECORD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_AUTHORIZED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_CONNECTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_CONVERTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN_FOR_BROWSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN_FOR_INPUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN_FOR_INQUIRE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN_FOR_OUTPUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN_FOR_PASS_ALL' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN_FOR_PASS_IDENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN_FOR_SET' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN_FOR_SET_ALL' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_OPEN_FOR_SET_IDENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NOT_PRIVILEGED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_BUFFER' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_CALLBACKS_ACTIVE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_CONNECTION_REFERENCE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_DATA_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_DESTINATIONS_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_EXTERNAL_PARTICIPANTS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_MSG_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_MSG_LOCKED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_MSG_UNDER_CURSOR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_RECORD_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_RETAINED_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_SUBSCRIPTION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NO_SUBS_MATCHED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_NULL_POINTER' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_ALREADY_EXISTS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_CHANGED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_DAMAGED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_IN_USE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_LEVEL_INCOMPATIBLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_NOT_UNIQUE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_Q_MGR_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_RECORDS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_STRING_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OBJECT_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OCSP_URL_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OFFSET_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OPEN_FAILED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OPERATION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OPERATION_NOT_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OPTIONS_CHANGED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OPTIONS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OPTION_ENVIRONMENT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OPTION_NOT_VALID_FOR_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ORIGINAL_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OUTCOME_MIXED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OUTCOME_PENDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_OUT_SELECTOR_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PAGESET_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PAGESET_FULL' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PARAMETER_MISSING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PARTIALLY_CONVERTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PARTICIPANT_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PARTICIPANT_NOT_DEFINED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PCF_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PERSISTENCE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PERSISTENT_NOT_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PMO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PMO_RECORD_FLAGS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PRECONN_EXIT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PRECONN_EXIT_LOAD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PRECONN_EXIT_NOT_FOUND' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PRIORITY_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PRIORITY_EXCEEDS_MAXIMUM' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROPERTIES_DISABLED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROPERTIES_TOO_BIG' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROPERTY_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROPERTY_NAME_LENGTH_ERR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROPERTY_NAME_TOO_BIG' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROPERTY_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROPERTY_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROPERTY_VALUE_TOO_BIG' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROP_CONV_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROP_NAME_NOT_CONVERTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROP_NUMBER_FORMAT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROP_TYPE_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PROP_VALUE_NOT_CONVERTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PUBLICATION_FAILURE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PUBLISH_EXIT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PUBSUB_INHIBITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PUT_INHIBITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PUT_MSG_RECORDS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_PUT_NOT_RETAINED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_ALREADY_EXISTS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_DELETED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_DEPTH_HIGH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_DEPTH_LOW' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_FULL' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_INDEX_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_MGR_ACTIVE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_MGR_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_MGR_NOT_ACTIVE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_MGR_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_MGR_QUIESCING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_MGR_STOPPING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_NOT_EMPTY' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_SERVICE_INTERVAL_HIGH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_SERVICE_INTERVAL_OK' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_SPACE_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_Q_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RAS_PROPERTY_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_READ_AHEAD_MSGS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RECONNECTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RECONNECTING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RECONNECT_FAILED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RECONNECT_INCOMPATIBLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RECONNECT_QMID_MISMATCH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RECONNECT_Q_MGR_REQD' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RECONNECT_TIMED_OUT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RECS_PRESENT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_REFERENCE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_REMOTE_Q_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_REOPEN_EXCL_INPUT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_REOPEN_INQUIRE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_REOPEN_SAVED_CONTEXT_ERR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_REOPEN_TEMPORARY_Q_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_REPORT_OPTIONS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RESERVED_VALUE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RESOURCE_PROBLEM' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RESPONSE_RECORDS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RES_OBJECT_STRING_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RETAINED_MSG_Q_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RETAINED_NOT_DELIVERED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RFH_COMMAND_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RFH_DUPLICATE_PARM' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RFH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RFH_FORMAT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RFH_HEADER_FIELD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RFH_PARM_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RFH_PARM_MISSING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RFH_RESTRICTED_FORMAT_ERR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RFH_STRING_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_RMH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SCO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SD_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SECOND_MARK_NOT_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SECURITY_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SEGMENTATION_NOT_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SEGMENTS_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SEGMENT_LENGTH_ZERO' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTION_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTION_STRING_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_ALWAYS_FALSE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_COUNT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_INVALID_FOR_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_LIMIT_EXCEEDED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_NOT_ALTERABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_NOT_FOR_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_NOT_PRESENT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_NOT_UNIQUE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_OUT_OF_RANGE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_SYNTAX_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SELECTOR_WRONG_TYPE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SERVICE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SERVICE_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SIGNAL1_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SIGNAL_OUTSTANDING' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SIGNAL_REQUEST_ACCEPTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SMPO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SOAP_AXIS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SOAP_DOTNET_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SOAP_URL_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SOURCE_BUFFER_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SOURCE_CCSID_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SOURCE_DECIMAL_ENC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SOURCE_FLOAT_ENC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SOURCE_INTEGER_ENC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SOURCE_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SRC_ENV_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SRC_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SRO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_ALREADY_INITIALIZED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_ALT_PROVIDER_REQUIRED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_CERTIFICATE_REVOKED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_CERT_STORE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_CONFIG_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_INITIALIZATION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_KEY_RESET_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_NOT_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_PEER_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SSL_PEER_NAME_MISMATCH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STANDBY_Q_MGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STAT_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STOPPED_BY_CLUSTER_EXIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STORAGE_CLASS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STORAGE_MEDIUM_FULL' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STORAGE_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STRING_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STRING_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STRING_TRUNCATED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STRUC_ID_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STRUC_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_STS_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUBLEVEL_NOT_ALTERABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUBSCRIPTION_CHANGE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUBSCRIPTION_CREATE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUBSCRIPTION_DELETE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUBSCRIPTION_IN_USE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUBSCRIPTION_REFRESH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUB_ALREADY_EXISTS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUB_INHIBITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUB_NAME_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUB_USER_DATA_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUITE_B_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SUPPRESSED_BY_EXIT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SYNCPOINT_LIMIT_REACHED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SYNCPOINT_NOT_ALLOWED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SYNCPOINT_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SYSTEM_BAG_NOT_ALTERABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SYSTEM_BAG_NOT_DELETABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SYSTEM_ITEM_NOT_ALTERABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_SYSTEM_ITEM_NOT_DELETABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TARGET_BUFFER_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TARGET_CCSID_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TARGET_DECIMAL_ENC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TARGET_FLOAT_ENC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TARGET_INTEGER_ENC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TARGET_LENGTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TERMINATION_FAILED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TMC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TM_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TOPIC_NOT_ALTERABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TOPIC_STRING_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TRIGGER_CONTROL_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TRIGGER_DEPTH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TRIGGER_MSG_PRIORITY_ERR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TRIGGER_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TRUNCATED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TRUNCATED_MSG_ACCEPTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_TRUNCATED_MSG_FAILED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UCS2_CONVERSION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNEXPECTED_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNIT_OF_WORK_NOT_STARTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_ALIAS_BASE_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_AUTH_ENTITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_CHANNEL_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_COMPONENT_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_DEF_XMIT_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_ENTITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_OBJECT_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_OBJECT_Q_MGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_Q_NAME' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_REF_OBJECT' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_REMOTE_Q_MGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_REPORT_OPTION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNKNOWN_XMIT_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNSUPPORTED_CIPHER_SUITE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UNSUPPORTED_PROPERTY' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UOW_CANCELED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UOW_COMMITTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UOW_ENLISTMENT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UOW_IN_PROGRESS' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UOW_MIX_NOT_SUPPORTED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_UOW_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_USER_ID_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_WAIT_INTERVAL_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_WIH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_WRONG_CF_LEVEL' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_WRONG_GMO_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_WRONG_MD_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_WRONG_VERSION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_WXP_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_XEPO_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_XMIT_Q_TYPE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_XMIT_Q_USAGE_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_XQH_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_XR_NOT_AVAILABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_XWAIT_CANCELED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_XWAIT_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQRC_ZERO_LENGTH' => 'mqseries/mqseries.stub', 'MQSERIES_MQRL_UNDEFINED' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_ACCEPT_UNSUP_IF_XMIT_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_ACCEPT_UNSUP_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_ACTIVITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_COA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_COA_WITH_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_COA_WITH_FULL_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_COD' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_COD_WITH_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_COD_WITH_FULL_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_COPY_MSG_ID_TO_CORREL_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_DEAD_LETTER_Q' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_DISCARD_MSG' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_EXCEPTION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_EXCEPTION_WITH_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_EXCEPTION_WITH_FULL_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_EXPIRATION' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_EXPIRATION_WITH_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_EXPIRATION_WITH_FULL_DATA' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_NAN' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_NEW_MSG_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_PAN' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_PASS_CORREL_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_PASS_DISCARD_AND_EXPIRY' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_PASS_MSG_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQRO_REJECT_UNSUP_MASK' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_ALTER' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_ALTERNATE_USER_AUTHORITY' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_ANY_USERID' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_CREATE' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_DURABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_FAIL_IF_QUIESCING' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_FIXED_USERID' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_GROUP_SUB' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_MANAGED' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_NEW_PUBLICATIONS_ONLY' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_NONE' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_NON_DURABLE' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_NO_MULTICAST' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_NO_READ_AHEAD' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_PUBLICATIONS_ON_REQUEST' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_READ_AHEAD' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_READ_AHEAD_AS_Q_DEF' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_RESUME' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_SCOPE_QMGR' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_SET_CORREL_ID' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_SET_IDENTITY_CONTEXT' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_WILDCARD_CHAR' => 'mqseries/mqseries.stub', 'MQSERIES_MQSO_WILDCARD_TOPIC' => 'mqseries/mqseries.stub', 'MQSERIES_MQSTAT_TYPE_ASYNC_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQSTAT_TYPE_RECONNECTION' => 'mqseries/mqseries.stub', 'MQSERIES_MQSTAT_TYPE_RECONNECTION_ERROR' => 'mqseries/mqseries.stub', 'MQSERIES_MQWI_UNLIMITED' => 'mqseries/mqseries.stub', 'MQSERIES_MQXPT_ALL' => 'mqseries/mqseries.stub', 'MQSERIES_MQXPT_DECNET' => 'mqseries/mqseries.stub', 'MQSERIES_MQXPT_LOCAL' => 'mqseries/mqseries.stub', 'MQSERIES_MQXPT_LU62' => 'mqseries/mqseries.stub', 'MQSERIES_MQXPT_NETBIOS' => 'mqseries/mqseries.stub', 'MQSERIES_MQXPT_SPX' => 'mqseries/mqseries.stub', 'MQSERIES_MQXPT_TCP' => 'mqseries/mqseries.stub', 'MQSERIES_MQXPT_UDP' => 'mqseries/mqseries.stub', 'MSG_CMSG_CLOEXEC' => 'sockets/sockets.stub', 'MSG_CONFIRM' => 'sockets/sockets.stub', 'MSG_CTRUNC' => 'sockets/sockets.stub', 'MSG_DONTROUTE' => 'sockets/sockets.stub', 'MSG_DONTWAIT' => 'sockets/sockets.stub', 'MSG_EAGAIN' => 'sysvmsg/sysvmsg.stub', 'MSG_ENOMSG' => 'sysvmsg/sysvmsg.stub', 'MSG_EOF' => 'sockets/sockets.stub', 'MSG_EOR' => 'sockets/sockets.stub', 'MSG_ERRQUEUE' => 'sockets/sockets.stub', 'MSG_EXCEPT' => 'sysvmsg/sysvmsg.stub', 'MSG_IPC_NOWAIT' => 'sysvmsg/sysvmsg.stub', 'MSG_MORE' => 'sockets/sockets.stub', 'MSG_NOERROR' => 'sysvmsg/sysvmsg.stub', 'MSG_NOSIGNAL' => 'sockets/sockets.stub', 'MSG_OOB' => 'sockets/sockets.stub', 'MSG_PEEK' => 'sockets/sockets.stub', 'MSG_TRUNC' => 'sockets/sockets.stub', 'MSG_WAITALL' => 'sockets/sockets.stub', 'MSG_WAITFORONE' => 'sockets/sockets.stub', 'MSG_ZEROCOPY' => 'sockets/sockets.stub', 'MSSQL_ASSOC' => 'mssql/mssql.stub', 'MSSQL_BOTH' => 'mssql/mssql.stub', 'MSSQL_NUM' => 'mssql/mssql.stub', 'MS_ALIGN_CENTER' => 'mapscript/mapscript.stub', 'MS_ALIGN_LEFT' => 'mapscript/mapscript.stub', 'MS_ALIGN_RIGHT' => 'mapscript/mapscript.stub', 'MS_AUTO' => 'mapscript/mapscript.stub', 'MS_AUTO2' => 'mapscript/mapscript.stub', 'MS_CC' => 'mapscript/mapscript.stub', 'MS_CGIERR' => 'mapscript/mapscript.stub', 'MS_CL' => 'mapscript/mapscript.stub', 'MS_CR' => 'mapscript/mapscript.stub', 'MS_DBFERR' => 'mapscript/mapscript.stub', 'MS_DD' => 'mapscript/mapscript.stub', 'MS_DEFAULT' => 'mapscript/mapscript.stub', 'MS_DELETE' => 'mapscript/mapscript.stub', 'MS_EMBED' => 'mapscript/mapscript.stub', 'MS_EOFERR' => 'mapscript/mapscript.stub', 'MS_FALSE' => 'mapscript/mapscript.stub', 'MS_FEET' => 'mapscript/mapscript.stub', 'MS_FOLLOW' => 'mapscript/mapscript.stub', 'MS_GDERR' => 'mapscript/mapscript.stub', 'MS_GD_ALPHA' => 'mapscript/mapscript.stub', 'MS_GET_REQUEST' => 'mapscript/mapscript.stub', 'MS_GIANT' => 'mapscript/mapscript.stub', 'MS_GRATICULE' => 'mapscript/mapscript.stub', 'MS_HASHERR' => 'mapscript/mapscript.stub', 'MS_HILITE' => 'mapscript/mapscript.stub', 'MS_HTTPERR' => 'mapscript/mapscript.stub', 'MS_IDENTERR' => 'mapscript/mapscript.stub', 'MS_IMAGEMODE_BYTE' => 'mapscript/mapscript.stub', 'MS_IMAGEMODE_FEATURE' => 'mapscript/mapscript.stub', 'MS_IMAGEMODE_FLOAT32' => 'mapscript/mapscript.stub', 'MS_IMAGEMODE_INT16' => 'mapscript/mapscript.stub', 'MS_IMAGEMODE_NULL' => 'mapscript/mapscript.stub', 'MS_IMAGEMODE_PC256' => 'mapscript/mapscript.stub', 'MS_IMAGEMODE_RGB' => 'mapscript/mapscript.stub', 'MS_IMAGEMODE_RGBA' => 'mapscript/mapscript.stub', 'MS_IMGERR' => 'mapscript/mapscript.stub', 'MS_INCHES' => 'mapscript/mapscript.stub', 'MS_INLINE' => 'mapscript/mapscript.stub', 'MS_IOERR' => 'mapscript/mapscript.stub', 'MS_JOINERR' => 'mapscript/mapscript.stub', 'MS_KILOMETERS' => 'mapscript/mapscript.stub', 'MS_LABEL_BINDING_ANGLE' => 'mapscript/mapscript.stub', 'MS_LABEL_BINDING_COLOR' => 'mapscript/mapscript.stub', 'MS_LABEL_BINDING_FONT' => 'mapscript/mapscript.stub', 'MS_LABEL_BINDING_OUTLINECOLOR' => 'mapscript/mapscript.stub', 'MS_LABEL_BINDING_POSITION' => 'mapscript/mapscript.stub', 'MS_LABEL_BINDING_PRIORITY' => 'mapscript/mapscript.stub', 'MS_LABEL_BINDING_SHADOWSIZEX' => 'mapscript/mapscript.stub', 'MS_LABEL_BINDING_SHADOWSIZEY' => 'mapscript/mapscript.stub', 'MS_LABEL_BINDING_SIZE' => 'mapscript/mapscript.stub', 'MS_LARGE' => 'mapscript/mapscript.stub', 'MS_LAYER_ANNOTATION' => 'mapscript/mapscript.stub', 'MS_LAYER_CHART' => 'mapscript/mapscript.stub', 'MS_LAYER_CIRCLE' => 'mapscript/mapscript.stub', 'MS_LAYER_LINE' => 'mapscript/mapscript.stub', 'MS_LAYER_POINT' => 'mapscript/mapscript.stub', 'MS_LAYER_POLYGON' => 'mapscript/mapscript.stub', 'MS_LAYER_QUERY' => 'mapscript/mapscript.stub', 'MS_LAYER_RASTER' => 'mapscript/mapscript.stub', 'MS_LAYER_TILEINDEX' => 'mapscript/mapscript.stub', 'MS_LC' => 'mapscript/mapscript.stub', 'MS_LL' => 'mapscript/mapscript.stub', 'MS_LR' => 'mapscript/mapscript.stub', 'MS_MAPCONTEXTERR' => 'mapscript/mapscript.stub', 'MS_MEDIUM' => 'mapscript/mapscript.stub', 'MS_MEMERR' => 'mapscript/mapscript.stub', 'MS_METERS' => 'mapscript/mapscript.stub', 'MS_MILES' => 'mapscript/mapscript.stub', 'MS_MISCERR' => 'mapscript/mapscript.stub', 'MS_MULTIPLE' => 'mapscript/mapscript.stub', 'MS_NAUTICALMILES' => 'mapscript/mapscript.stub', 'MS_NO' => 'mapscript/mapscript.stub', 'MS_NOERR' => 'mapscript/mapscript.stub', 'MS_NONE' => 'mapscript/mapscript.stub', 'MS_NORMAL' => 'mapscript/mapscript.stub', 'MS_NOTFOUND' => 'mapscript/mapscript.stub', 'MS_OFF' => 'mapscript/mapscript.stub', 'MS_OGR' => 'mapscript/mapscript.stub', 'MS_OGRERR' => 'mapscript/mapscript.stub', 'MS_ON' => 'mapscript/mapscript.stub', 'MS_ORACLESPATIAL' => 'mapscript/mapscript.stub', 'MS_ORACLESPATIALERR' => 'mapscript/mapscript.stub', 'MS_PARSEERR' => 'mapscript/mapscript.stub', 'MS_PIXELS' => 'mapscript/mapscript.stub', 'MS_PLUGIN' => 'mapscript/mapscript.stub', 'MS_POSTGIS' => 'mapscript/mapscript.stub', 'MS_POST_REQUEST' => 'mapscript/mapscript.stub', 'MS_PROJERR' => 'mapscript/mapscript.stub', 'MS_QUERYERR' => 'mapscript/mapscript.stub', 'MS_RASTER' => 'mapscript/mapscript.stub', 'MS_REGEXERR' => 'mapscript/mapscript.stub', 'MS_SDE' => 'mapscript/mapscript.stub', 'MS_SDEERR' => 'mapscript/mapscript.stub', 'MS_SELECTED' => 'mapscript/mapscript.stub', 'MS_SHAPEFILE' => 'mapscript/mapscript.stub', 'MS_SHAPE_LINE' => 'mapscript/mapscript.stub', 'MS_SHAPE_NULL' => 'mapscript/mapscript.stub', 'MS_SHAPE_POINT' => 'mapscript/mapscript.stub', 'MS_SHAPE_POLYGON' => 'mapscript/mapscript.stub', 'MS_SHPERR' => 'mapscript/mapscript.stub', 'MS_SHP_ARC' => 'mapscript/mapscript.stub', 'MS_SHP_MULTIPOINT' => 'mapscript/mapscript.stub', 'MS_SHP_POINT' => 'mapscript/mapscript.stub', 'MS_SHP_POLYGON' => 'mapscript/mapscript.stub', 'MS_SINGLE' => 'mapscript/mapscript.stub', 'MS_SMALL' => 'mapscript/mapscript.stub', 'MS_STYLE_BINDING_ANGLE' => 'mapscript/mapscript.stub', 'MS_STYLE_BINDING_COLOR' => 'mapscript/mapscript.stub', 'MS_STYLE_BINDING_OUTLINECOLOR' => 'mapscript/mapscript.stub', 'MS_STYLE_BINDING_SIZE' => 'mapscript/mapscript.stub', 'MS_STYLE_BINDING_SYMBOL' => 'mapscript/mapscript.stub', 'MS_STYLE_BINDING_WIDTH' => 'mapscript/mapscript.stub', 'MS_SYMBOL_ELLIPSE' => 'mapscript/mapscript.stub', 'MS_SYMBOL_PIXMAP' => 'mapscript/mapscript.stub', 'MS_SYMBOL_SIMPLE' => 'mapscript/mapscript.stub', 'MS_SYMBOL_TRUETYPE' => 'mapscript/mapscript.stub', 'MS_SYMBOL_VECTOR' => 'mapscript/mapscript.stub', 'MS_SYMERR' => 'mapscript/mapscript.stub', 'MS_TILED_OGR' => 'mapscript/mapscript.stub', 'MS_TILED_SHAPEFILE' => 'mapscript/mapscript.stub', 'MS_TINY' => 'mapscript/mapscript.stub', 'MS_TRUE' => 'mapscript/mapscript.stub', 'MS_TTFERR' => 'mapscript/mapscript.stub', 'MS_TYPEERR' => 'mapscript/mapscript.stub', 'MS_UC' => 'mapscript/mapscript.stub', 'MS_UL' => 'mapscript/mapscript.stub', 'MS_UNION' => 'mapscript/mapscript.stub', 'MS_UR' => 'mapscript/mapscript.stub', 'MS_WCSERR' => 'mapscript/mapscript.stub', 'MS_WEBERR' => 'mapscript/mapscript.stub', 'MS_WFS' => 'mapscript/mapscript.stub', 'MS_WFSCONNERR' => 'mapscript/mapscript.stub', 'MS_WFSERR' => 'mapscript/mapscript.stub', 'MS_WMS' => 'mapscript/mapscript.stub', 'MS_WMSCONNERR' => 'mapscript/mapscript.stub', 'MS_WMSERR' => 'mapscript/mapscript.stub', 'MS_XY' => 'mapscript/mapscript.stub', 'MS_YES' => 'mapscript/mapscript.stub', 'MT_RAND_MT19937' => 'standard/standard_defines.stub', 'MT_RAND_PHP' => 'standard/standard_defines.stub', 'MYSQLI_ASSOC' => 'mysqli/mysqli.stub', 'MYSQLI_ASYNC' => 'mysqli/mysqli.stub', 'MYSQLI_AUTO_INCREMENT_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_BINARY_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_BLOB_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_BOTH' => 'mysqli/mysqli.stub', 'MYSQLI_CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS' => 'mysqli/mysqli.stub', 'MYSQLI_CLIENT_COMPRESS' => 'mysqli/mysqli.stub', 'MYSQLI_CLIENT_FOUND_ROWS' => 'mysqli/mysqli.stub', 'MYSQLI_CLIENT_IGNORE_SPACE' => 'mysqli/mysqli.stub', 'MYSQLI_CLIENT_INTERACTIVE' => 'mysqli/mysqli.stub', 'MYSQLI_CLIENT_NO_SCHEMA' => 'mysqli/mysqli.stub', 'MYSQLI_CLIENT_SSL' => 'mysqli/mysqli.stub', 'MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT' => 'mysqli/mysqli.stub', 'MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT' => 'mysqli/mysqli.stub', 'MYSQLI_CURSOR_TYPE_FOR_UPDATE' => 'mysqli/mysqli.stub', 'MYSQLI_CURSOR_TYPE_NO_CURSOR' => 'mysqli/mysqli.stub', 'MYSQLI_CURSOR_TYPE_READ_ONLY' => 'mysqli/mysqli.stub', 'MYSQLI_CURSOR_TYPE_SCROLLABLE' => 'mysqli/mysqli.stub', 'MYSQLI_DATA_TRUNCATED' => 'mysqli/mysqli.stub', 'MYSQLI_DEBUG_TRACE_ENABLED' => 'mysqli/mysqli.stub', 'MYSQLI_ENUM_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_GROUP_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_INIT_COMMAND' => 'mysqli/mysqli.stub', 'MYSQLI_IS_MARIADB' => 'mysqli/mysqli.stub', 'MYSQLI_MULTIPLE_KEY_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_NOT_NULL_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_NO_DATA' => 'mysqli/mysqli.stub', 'MYSQLI_NO_DEFAULT_VALUE_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_NUM' => 'mysqli/mysqli.stub', 'MYSQLI_NUM_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_ON_UPDATE_NOW_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_OPT_CAN_HANDLE_EXPIRED_PASSWORDS' => 'mysqli/mysqli.stub', 'MYSQLI_OPT_CONNECT_TIMEOUT' => 'mysqli/mysqli.stub', 'MYSQLI_OPT_INT_AND_FLOAT_NATIVE' => 'mysqli/mysqli.stub', 'MYSQLI_OPT_LOAD_DATA_LOCAL_DIR' => 'mysqli/mysqli.stub', 'MYSQLI_OPT_LOCAL_INFILE' => 'mysqli/mysqli.stub', 'MYSQLI_OPT_NET_CMD_BUFFER_SIZE' => 'mysqli/mysqli.stub', 'MYSQLI_OPT_NET_READ_BUFFER_SIZE' => 'mysqli/mysqli.stub', 'MYSQLI_OPT_READ_TIMEOUT' => 'mysqli/mysqli.stub', 'MYSQLI_OPT_SSL_VERIFY_SERVER_CERT' => 'mysqli/mysqli.stub', 'MYSQLI_PART_KEY_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_PRI_KEY_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_READ_DEFAULT_FILE' => 'mysqli/mysqli.stub', 'MYSQLI_READ_DEFAULT_GROUP' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_BACKUP_LOG' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_GRANT' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_HOSTS' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_LOG' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_MASTER' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_REPLICA' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_SLAVE' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_STATUS' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_TABLES' => 'mysqli/mysqli.stub', 'MYSQLI_REFRESH_THREADS' => 'mysqli/mysqli.stub', 'MYSQLI_REPORT_ALL' => 'mysqli/mysqli.stub', 'MYSQLI_REPORT_ERROR' => 'mysqli/mysqli.stub', 'MYSQLI_REPORT_INDEX' => 'mysqli/mysqli.stub', 'MYSQLI_REPORT_OFF' => 'mysqli/mysqli.stub', 'MYSQLI_REPORT_STRICT' => 'mysqli/mysqli.stub', 'MYSQLI_SERVER_PS_OUT_PARAMS' => 'mysqli/mysqli.stub', 'MYSQLI_SERVER_PUBLIC_KEY' => 'mysqli/mysqli.stub', 'MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED' => 'mysqli/mysqli.stub', 'MYSQLI_SERVER_QUERY_NO_INDEX_USED' => 'mysqli/mysqli.stub', 'MYSQLI_SERVER_QUERY_WAS_SLOW' => 'mysqli/mysqli.stub', 'MYSQLI_SET_CHARSET_DIR' => 'mysqli/mysqli.stub', 'MYSQLI_SET_CHARSET_NAME' => 'mysqli/mysqli.stub', 'MYSQLI_SET_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_STMT_ATTR_CURSOR_TYPE' => 'mysqli/mysqli.stub', 'MYSQLI_STMT_ATTR_PREFETCH_ROWS' => 'mysqli/mysqli.stub', 'MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH' => 'mysqli/mysqli.stub', 'MYSQLI_STORE_RESULT' => 'mysqli/mysqli.stub', 'MYSQLI_STORE_RESULT_COPY_DATA' => 'mysqli/mysqli.stub', 'MYSQLI_TIMESTAMP_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_TRANS_COR_AND_CHAIN' => 'mysqli/mysqli.stub', 'MYSQLI_TRANS_COR_AND_NO_CHAIN' => 'mysqli/mysqli.stub', 'MYSQLI_TRANS_COR_NO_RELEASE' => 'mysqli/mysqli.stub', 'MYSQLI_TRANS_COR_RELEASE' => 'mysqli/mysqli.stub', 'MYSQLI_TRANS_START_READ_ONLY' => 'mysqli/mysqli.stub', 'MYSQLI_TRANS_START_READ_WRITE' => 'mysqli/mysqli.stub', 'MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_BIT' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_BLOB' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_CHAR' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_DATE' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_DATETIME' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_DECIMAL' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_DOUBLE' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_ENUM' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_FLOAT' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_GEOMETRY' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_INT24' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_INTERVAL' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_JSON' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_LONG' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_LONGLONG' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_LONG_BLOB' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_MEDIUM_BLOB' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_NEWDATE' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_NEWDECIMAL' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_NULL' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_SET' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_SHORT' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_STRING' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_TIME' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_TIMESTAMP' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_TINY' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_TINY_BLOB' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_VAR_STRING' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_VECTOR' => 'mysqli/mysqli.stub', 'MYSQLI_TYPE_YEAR' => 'mysqli/mysqli.stub', 'MYSQLI_UNIQUE_KEY_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_UNSIGNED_FLAG' => 'mysqli/mysqli.stub', 'MYSQLI_USE_RESULT' => 'mysqli/mysqli.stub', 'MYSQLI_ZEROFILL_FLAG' => 'mysqli/mysqli.stub', 'MYSQLX_LOCK_DEFAULT' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_LOCK_NOWAIT' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_LOCK_SKIP_LOCKED' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_BIGINT' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_BIT' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_BLOB' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_BYTES' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_CHAR' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_DATE' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_DATETIME' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_DECIMAL' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_DOUBLE' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_ENUM' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_FLOAT' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_GEOMETRY' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_INT' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_INT24' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_INTERVAL' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_JSON' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_LONG' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_LONGLONG' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_LONG_BLOB' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_MEDIUMINT' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_MEDIUM_BLOB' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_NEWDATE' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_NEWDECIMAL' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_NULL' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_SET' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_SHORT' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_SMALLINT' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_STRING' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_TIME' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_TIMESTAMP' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_TINY' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_TINY_BLOB' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_VAR_STRING' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQLX_TYPE_YEAR' => 'mysql_xdevapi/mysql_xdevapi.stub', 'MYSQL_ASSOC' => 'mysql/mysql.stub', 'MYSQL_BOTH' => 'mysql/mysql.stub', 'MYSQL_CLIENT_COMPRESS' => 'mysql/mysql.stub', 'MYSQL_CLIENT_IGNORE_SPACE' => 'mysql/mysql.stub', 'MYSQL_CLIENT_INTERACTIVE' => 'mysql/mysql.stub', 'MYSQL_CLIENT_SSL' => 'mysql/mysql.stub', 'MYSQL_NUM' => 'mysql/mysql.stub', 'M_1_PI' => 'standard/standard_defines.stub', 'M_2_PI' => 'standard/standard_defines.stub', 'M_2_SQRTPI' => 'standard/standard_defines.stub', 'M_E' => 'standard/standard_defines.stub', 'M_EULER' => 'standard/standard_defines.stub', 'M_LN10' => 'standard/standard_defines.stub', 'M_LN2' => 'standard/standard_defines.stub', 'M_LNPI' => 'standard/standard_defines.stub', 'M_LOG10E' => 'standard/standard_defines.stub', 'M_LOG2E' => 'standard/standard_defines.stub', 'M_PI' => 'standard/standard_defines.stub', 'M_PI_2' => 'standard/standard_defines.stub', 'M_PI_4' => 'standard/standard_defines.stub', 'M_SQRT1_2' => 'standard/standard_defines.stub', 'M_SQRT2' => 'standard/standard_defines.stub', 'M_SQRT3' => 'standard/standard_defines.stub', 'M_SQRTPI' => 'standard/standard_defines.stub', 'Menu' => 'winbinder/winbinder.stub', 'ModalDialog' => 'winbinder/winbinder.stub', 'ModelessDialog' => 'winbinder/winbinder.stub', 'NAN' => 'standard/standard_defines.stub', 'NCURSES_ALL_MOUSE_EVENTS' => 'ncurses/ncurses.stub', 'NCURSES_A_ALTCHARSET' => 'ncurses/ncurses.stub', 'NCURSES_A_BLINK' => 'ncurses/ncurses.stub', 'NCURSES_A_BOLD' => 'ncurses/ncurses.stub', 'NCURSES_A_CHARTEXT' => 'ncurses/ncurses.stub', 'NCURSES_A_DIM' => 'ncurses/ncurses.stub', 'NCURSES_A_INVIS' => 'ncurses/ncurses.stub', 'NCURSES_A_NORMAL' => 'ncurses/ncurses.stub', 'NCURSES_A_PROTECT' => 'ncurses/ncurses.stub', 'NCURSES_A_REVERSE' => 'ncurses/ncurses.stub', 'NCURSES_A_STANDOUT' => 'ncurses/ncurses.stub', 'NCURSES_A_UNDERLINE' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON1_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON1_DOUBLE_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON1_PRESSED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON1_RELEASED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON1_TRIPLE_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON2_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON2_DOUBLE_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON2_PRESSED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON2_RELEASED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON2_TRIPLE_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON3_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON3_DOUBLE_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON3_PRESSED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON3_RELEASED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON3_TRIPLE_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON4_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON4_DOUBLE_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON4_PRESSED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON4_RELEASED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON4_TRIPLE_CLICKED' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON_ALT' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON_CTRL' => 'ncurses/ncurses.stub', 'NCURSES_BUTTON_SHIFT' => 'ncurses/ncurses.stub', 'NCURSES_COLOR_BLACK' => 'ncurses/ncurses.stub', 'NCURSES_COLOR_BLUE' => 'ncurses/ncurses.stub', 'NCURSES_COLOR_CYAN' => 'ncurses/ncurses.stub', 'NCURSES_COLOR_GREEN' => 'ncurses/ncurses.stub', 'NCURSES_COLOR_MAGENTA' => 'ncurses/ncurses.stub', 'NCURSES_COLOR_RED' => 'ncurses/ncurses.stub', 'NCURSES_COLOR_WHITE' => 'ncurses/ncurses.stub', 'NCURSES_COLOR_YELLOW' => 'ncurses/ncurses.stub', 'NCURSES_KEY_A1' => 'ncurses/ncurses.stub', 'NCURSES_KEY_A3' => 'ncurses/ncurses.stub', 'NCURSES_KEY_B2' => 'ncurses/ncurses.stub', 'NCURSES_KEY_BACKSPACE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_BEG' => 'ncurses/ncurses.stub', 'NCURSES_KEY_BTAB' => 'ncurses/ncurses.stub', 'NCURSES_KEY_C1' => 'ncurses/ncurses.stub', 'NCURSES_KEY_C3' => 'ncurses/ncurses.stub', 'NCURSES_KEY_CANCEL' => 'ncurses/ncurses.stub', 'NCURSES_KEY_CATAB' => 'ncurses/ncurses.stub', 'NCURSES_KEY_CLEAR' => 'ncurses/ncurses.stub', 'NCURSES_KEY_CLOSE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_COMMAND' => 'ncurses/ncurses.stub', 'NCURSES_KEY_COPY' => 'ncurses/ncurses.stub', 'NCURSES_KEY_CREATE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_CTAB' => 'ncurses/ncurses.stub', 'NCURSES_KEY_DC' => 'ncurses/ncurses.stub', 'NCURSES_KEY_DL' => 'ncurses/ncurses.stub', 'NCURSES_KEY_DOWN' => 'ncurses/ncurses.stub', 'NCURSES_KEY_EIC' => 'ncurses/ncurses.stub', 'NCURSES_KEY_END' => 'ncurses/ncurses.stub', 'NCURSES_KEY_ENTER' => 'ncurses/ncurses.stub', 'NCURSES_KEY_EOL' => 'ncurses/ncurses.stub', 'NCURSES_KEY_EOS' => 'ncurses/ncurses.stub', 'NCURSES_KEY_EXIT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F0' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F1' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F10' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F11' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F12' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F2' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F3' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F4' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F5' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F6' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F7' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F8' => 'ncurses/ncurses.stub', 'NCURSES_KEY_F9' => 'ncurses/ncurses.stub', 'NCURSES_KEY_FIND' => 'ncurses/ncurses.stub', 'NCURSES_KEY_HELP' => 'ncurses/ncurses.stub', 'NCURSES_KEY_HOME' => 'ncurses/ncurses.stub', 'NCURSES_KEY_IC' => 'ncurses/ncurses.stub', 'NCURSES_KEY_IL' => 'ncurses/ncurses.stub', 'NCURSES_KEY_LEFT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_LL' => 'ncurses/ncurses.stub', 'NCURSES_KEY_MARK' => 'ncurses/ncurses.stub', 'NCURSES_KEY_MESSAGE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_MOUSE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_MOVE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_NEXT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_NPAGE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_OPEN' => 'ncurses/ncurses.stub', 'NCURSES_KEY_OPTIONS' => 'ncurses/ncurses.stub', 'NCURSES_KEY_PPAGE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_PREVIOUS' => 'ncurses/ncurses.stub', 'NCURSES_KEY_PRINT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_REDO' => 'ncurses/ncurses.stub', 'NCURSES_KEY_REFERENCE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_REFRESH' => 'ncurses/ncurses.stub', 'NCURSES_KEY_REPLACE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_RESET' => 'ncurses/ncurses.stub', 'NCURSES_KEY_RESIZE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_RESTART' => 'ncurses/ncurses.stub', 'NCURSES_KEY_RESUME' => 'ncurses/ncurses.stub', 'NCURSES_KEY_RIGHT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SAVE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SBEG' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SCANCEL' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SCOMMAND' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SCOPY' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SCREATE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SDC' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SDL' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SELECT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SEND' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SEOL' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SEXIT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SF' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SFIND' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SHELP' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SHOME' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SIC' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SLEFT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SMESSAGE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SMOVE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SNEXT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SOPTIONS' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SPREVIOUS' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SPRINT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SR' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SREDO' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SREPLACE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SRESET' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SRIGHT' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SRSUME' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SSAVE' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SSUSPEND' => 'ncurses/ncurses.stub', 'NCURSES_KEY_STAB' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SUNDO' => 'ncurses/ncurses.stub', 'NCURSES_KEY_SUSPEND' => 'ncurses/ncurses.stub', 'NCURSES_KEY_UNDO' => 'ncurses/ncurses.stub', 'NCURSES_KEY_UP' => 'ncurses/ncurses.stub', 'NCURSES_REPORT_MOUSE_POSITION' => 'ncurses/ncurses.stub', 'NEGATIVE_SIGN' => 'standard/standard_defines.stub', 'NIL' => 'imap/imap.stub', 'NOCOLOR' => 'winbinder/winbinder.stub', 'NOEXPR' => 'standard/standard_defines.stub', 'NORM_IGNORECASE' => 'com_dotnet/com_dotnet.stub', 'NORM_IGNOREKANATYPE' => 'com_dotnet/com_dotnet.stub', 'NORM_IGNOREKASHIDA' => 'com_dotnet/com_dotnet.stub', 'NORM_IGNORENONSPACE' => 'com_dotnet/com_dotnet.stub', 'NORM_IGNORESYMBOLS' => 'com_dotnet/com_dotnet.stub', 'NORM_IGNOREWIDTH' => 'com_dotnet/com_dotnet.stub', 'NOSTR' => 'standard/standard_defines.stub', 'N_CS_PRECEDES' => 'standard/standard_defines.stub', 'N_SEP_BY_SPACE' => 'standard/standard_defines.stub', 'N_SIGN_POSN' => 'standard/standard_defines.stub', 'NakedWindow' => 'winbinder/winbinder.stub', 'OAUTH_AUTH_TYPE_AUTHORIZATION' => 'oauth/oauth.stub', 'OAUTH_AUTH_TYPE_FORM' => 'oauth/oauth.stub', 'OAUTH_AUTH_TYPE_NONE' => 'oauth/oauth.stub', 'OAUTH_AUTH_TYPE_URI' => 'oauth/oauth.stub', 'OAUTH_BAD_NONCE' => 'oauth/oauth.stub', 'OAUTH_BAD_TIMESTAMP' => 'oauth/oauth.stub', 'OAUTH_CONSUMER_KEY_REFUSED' => 'oauth/oauth.stub', 'OAUTH_CONSUMER_KEY_UNKNOWN' => 'oauth/oauth.stub', 'OAUTH_HTTP_METHOD_DELETE' => 'oauth/oauth.stub', 'OAUTH_HTTP_METHOD_GET' => 'oauth/oauth.stub', 'OAUTH_HTTP_METHOD_HEAD' => 'oauth/oauth.stub', 'OAUTH_HTTP_METHOD_POST' => 'oauth/oauth.stub', 'OAUTH_HTTP_METHOD_PUT' => 'oauth/oauth.stub', 'OAUTH_INVALID_SIGNATURE' => 'oauth/oauth.stub', 'OAUTH_OK' => 'oauth/oauth.stub', 'OAUTH_PARAMETER_ABSENT' => 'oauth/oauth.stub', 'OAUTH_REQENGINE_CURL' => 'oauth/oauth.stub', 'OAUTH_REQENGINE_STREAMS' => 'oauth/oauth.stub', 'OAUTH_SIGNATURE_METHOD_REJECTED' => 'oauth/oauth.stub', 'OAUTH_SIG_METHOD_HMACSHA1' => 'oauth/oauth.stub', 'OAUTH_SIG_METHOD_HMACSHA256' => 'oauth/oauth.stub', 'OAUTH_SIG_METHOD_RSASHA1' => 'oauth/oauth.stub', 'OAUTH_TOKEN_EXPIRED' => 'oauth/oauth.stub', 'OAUTH_TOKEN_REJECTED' => 'oauth/oauth.stub', 'OAUTH_TOKEN_USED' => 'oauth/oauth.stub', 'OAUTH_VERIFIER_INVALID' => 'oauth/oauth.stub', 'OCI_ASSOC' => 'oci8/oci8.stub', 'OCI_BOTH' => 'oci8/oci8.stub', 'OCI_B_BFILE' => 'oci8/oci8.stub', 'OCI_B_BIN' => 'oci8/oci8.stub', 'OCI_B_BLOB' => 'oci8/oci8.stub', 'OCI_B_BOL' => 'oci8/oci8.stub', 'OCI_B_CFILEE' => 'oci8/oci8.stub', 'OCI_B_CLOB' => 'oci8/oci8.stub', 'OCI_B_CURSOR' => 'oci8/oci8.stub', 'OCI_B_INT' => 'oci8/oci8.stub', 'OCI_B_NTY' => 'oci8/oci8.stub', 'OCI_B_NUM' => 'oci8/oci8.stub', 'OCI_B_ROWID' => 'oci8/oci8.stub', 'OCI_COMMIT_ON_SUCCESS' => 'oci8/oci8.stub', 'OCI_CRED_EXT' => 'oci8/oci8.stub', 'OCI_DEFAULT' => 'oci8/oci8.stub', 'OCI_DESCRIBE_ONLY' => 'oci8/oci8.stub', 'OCI_DTYPE_FILE' => 'oci8/oci8.stub', 'OCI_DTYPE_LOB' => 'oci8/oci8.stub', 'OCI_DTYPE_ROWID' => 'oci8/oci8.stub', 'OCI_D_FILE' => 'oci8/oci8.stub', 'OCI_D_LOB' => 'oci8/oci8.stub', 'OCI_D_ROWID' => 'oci8/oci8.stub', 'OCI_EXACT_FETCH' => 'oci8/oci8.stub', 'OCI_FETCHSTATEMENT_BY_COLUMN' => 'oci8/oci8.stub', 'OCI_FETCHSTATEMENT_BY_ROW' => 'oci8/oci8.stub', 'OCI_LOB_BUFFER_FREE' => 'oci8/oci8.stub', 'OCI_NO_AUTO_COMMIT' => 'oci8/oci8.stub', 'OCI_NUM' => 'oci8/oci8.stub', 'OCI_RETURN_LOBS' => 'oci8/oci8.stub', 'OCI_RETURN_NULLS' => 'oci8/oci8.stub', 'OCI_SEEK_CUR' => 'oci8/oci8.stub', 'OCI_SEEK_END' => 'oci8/oci8.stub', 'OCI_SEEK_SET' => 'oci8/oci8.stub', 'OCI_SYSDATE' => 'oci8/oci8.stub', 'OCI_SYSDBA' => 'oci8/oci8.stub', 'OCI_SYSOPER' => 'oci8/oci8.stub', 'OCI_TEMP_BLOB' => 'oci8/oci8.stub', 'OCI_TEMP_CLOB' => 'oci8/oci8.stub', 'ODBC_BINMODE_CONVERT' => 'odbc/odbc.stub', 'ODBC_BINMODE_PASSTHRU' => 'odbc/odbc.stub', 'ODBC_BINMODE_RETURN' => 'odbc/odbc.stub', 'ODBC_TYPE' => 'odbc/odbc.stub', 'OPENSSL_ALGO_DSS1' => 'openssl/openssl.stub', 'OPENSSL_ALGO_MD2' => 'openssl/openssl.stub', 'OPENSSL_ALGO_MD4' => 'openssl/openssl.stub', 'OPENSSL_ALGO_MD5' => 'openssl/openssl.stub', 'OPENSSL_ALGO_RMD160' => 'openssl/openssl.stub', 'OPENSSL_ALGO_SHA1' => 'openssl/openssl.stub', 'OPENSSL_ALGO_SHA224' => 'openssl/openssl.stub', 'OPENSSL_ALGO_SHA256' => 'openssl/openssl.stub', 'OPENSSL_ALGO_SHA384' => 'openssl/openssl.stub', 'OPENSSL_ALGO_SHA512' => 'openssl/openssl.stub', 'OPENSSL_CIPHER_3DES' => 'openssl/openssl.stub', 'OPENSSL_CIPHER_AES_128_CBC' => 'openssl/openssl.stub', 'OPENSSL_CIPHER_AES_192_CBC' => 'openssl/openssl.stub', 'OPENSSL_CIPHER_AES_256_CBC' => 'openssl/openssl.stub', 'OPENSSL_CIPHER_DES' => 'openssl/openssl.stub', 'OPENSSL_CIPHER_RC2_128' => 'openssl/openssl.stub', 'OPENSSL_CIPHER_RC2_40' => 'openssl/openssl.stub', 'OPENSSL_CIPHER_RC2_64' => 'openssl/openssl.stub', 'OPENSSL_CMS_BINARY' => 'openssl/openssl.stub', 'OPENSSL_CMS_DETACHED' => 'openssl/openssl.stub', 'OPENSSL_CMS_NOATTR' => 'openssl/openssl.stub', 'OPENSSL_CMS_NOCERTS' => 'openssl/openssl.stub', 'OPENSSL_CMS_NOINTERN' => 'openssl/openssl.stub', 'OPENSSL_CMS_NOSIGS' => 'openssl/openssl.stub', 'OPENSSL_CMS_NOVERIFY' => 'openssl/openssl.stub', 'OPENSSL_CMS_OLDMIMETYPE' => 'openssl/openssl.stub', 'OPENSSL_CMS_TEXT' => 'openssl/openssl.stub', 'OPENSSL_DEFAULT_STREAM_CIPHERS' => 'openssl/openssl.stub', 'OPENSSL_DONT_ZERO_PAD_KEY' => 'openssl/openssl.stub', 'OPENSSL_ENCODING_DER' => 'openssl/openssl.stub', 'OPENSSL_ENCODING_PEM' => 'openssl/openssl.stub', 'OPENSSL_ENCODING_SMIME' => 'openssl/openssl.stub', 'OPENSSL_KEYTYPE_DH' => 'openssl/openssl.stub', 'OPENSSL_KEYTYPE_DSA' => 'openssl/openssl.stub', 'OPENSSL_KEYTYPE_EC' => 'openssl/openssl.stub', 'OPENSSL_KEYTYPE_ED25519' => 'openssl/openssl.stub', 'OPENSSL_KEYTYPE_ED448' => 'openssl/openssl.stub', 'OPENSSL_KEYTYPE_RSA' => 'openssl/openssl.stub', 'OPENSSL_KEYTYPE_X25519' => 'openssl/openssl.stub', 'OPENSSL_KEYTYPE_X448' => 'openssl/openssl.stub', 'OPENSSL_NO_PADDING' => 'openssl/openssl.stub', 'OPENSSL_PKCS1_OAEP_PADDING' => 'openssl/openssl.stub', 'OPENSSL_PKCS1_PADDING' => 'openssl/openssl.stub', 'OPENSSL_RAW_DATA' => 'openssl/openssl.stub', 'OPENSSL_SSLV23_PADDING' => 'openssl/openssl.stub', 'OPENSSL_TLSEXT_SERVER_NAME' => 'openssl/openssl.stub', 'OPENSSL_VERSION_NUMBER' => 'openssl/openssl.stub', 'OPENSSL_VERSION_TEXT' => 'openssl/openssl.stub', 'OPENSSL_ZERO_PADDING' => 'openssl/openssl.stub', 'OP_ANONYMOUS' => 'imap/imap.stub', 'OP_DEBUG' => 'imap/imap.stub', 'OP_EXPUNGE' => 'imap/imap.stub', 'OP_HALFOPEN' => 'imap/imap.stub', 'OP_PROTOTYPE' => 'imap/imap.stub', 'OP_READONLY' => 'imap/imap.stub', 'OP_SECURE' => 'imap/imap.stub', 'OP_SHORTCACHE' => 'imap/imap.stub', 'OP_SILENT' => 'imap/imap.stub', 'O_APPEND' => 'dio/dio_d.stub', 'O_ASYNC' => 'dio/dio_d.stub', 'O_CREAT' => 'dio/dio_d.stub', 'O_EXCL' => 'dio/dio_d.stub', 'O_NDELAY' => 'dio/dio_d.stub', 'O_NOCTTY' => 'dio/dio_d.stub', 'O_NONBLOCK' => 'dio/dio_d.stub', 'O_RDONLY' => 'dio/dio_d.stub', 'O_RDWR' => 'dio/dio_d.stub', 'O_SYNC' => 'dio/dio_d.stub', 'O_TRUNC' => 'dio/dio_d.stub', 'O_WRONLY' => 'dio/dio_d.stub', 'PASSWORD_ARGON2I' => 'standard/password.stub', 'PASSWORD_ARGON2ID' => 'standard/password.stub', 'PASSWORD_ARGON2_DEFAULT_MEMORY_COST' => 'standard/password.stub', 'PASSWORD_ARGON2_DEFAULT_THREADS' => 'standard/password.stub', 'PASSWORD_ARGON2_DEFAULT_TIME_COST' => 'standard/password.stub', 'PASSWORD_ARGON2_PROVIDER' => 'standard/password.stub', 'PASSWORD_BCRYPT' => 'standard/password.stub', 'PASSWORD_BCRYPT_DEFAULT_COST' => 'standard/password.stub', 'PASSWORD_DEFAULT' => 'standard/password.stub', 'PATHINFO_ALL' => 'standard/standard_defines.stub', 'PATHINFO_BASENAME' => 'standard/standard_defines.stub', 'PATHINFO_DIRNAME' => 'standard/standard_defines.stub', 'PATHINFO_EXTENSION' => 'standard/standard_defines.stub', 'PATHINFO_FILENAME' => 'standard/standard_defines.stub', 'PATH_SEPARATOR' => 'standard/standard_defines.stub', 'PCNTL_E2BIG' => 'pcntl/pcntl.stub', 'PCNTL_EACCES' => 'pcntl/pcntl.stub', 'PCNTL_EAGAIN' => 'pcntl/pcntl.stub', 'PCNTL_ECHILD' => 'pcntl/pcntl.stub', 'PCNTL_EFAULT' => 'pcntl/pcntl.stub', 'PCNTL_EINTR' => 'pcntl/pcntl.stub', 'PCNTL_EINVAL' => 'pcntl/pcntl.stub', 'PCNTL_EIO' => 'pcntl/pcntl.stub', 'PCNTL_EISDIR' => 'pcntl/pcntl.stub', 'PCNTL_ELIBBAD' => 'pcntl/pcntl.stub', 'PCNTL_ELOOP' => 'pcntl/pcntl.stub', 'PCNTL_EMFILE' => 'pcntl/pcntl.stub', 'PCNTL_ENAMETOOLONG' => 'pcntl/pcntl.stub', 'PCNTL_ENFILE' => 'pcntl/pcntl.stub', 'PCNTL_ENOENT' => 'pcntl/pcntl.stub', 'PCNTL_ENOEXEC' => 'pcntl/pcntl.stub', 'PCNTL_ENOMEM' => 'pcntl/pcntl.stub', 'PCNTL_ENOSPC' => 'pcntl/pcntl.stub', 'PCNTL_ENOTDIR' => 'pcntl/pcntl.stub', 'PCNTL_EPERM' => 'pcntl/pcntl.stub', 'PCNTL_ESRCH' => 'pcntl/pcntl.stub', 'PCNTL_ETXTBSY' => 'pcntl/pcntl.stub', 'PCNTL_EUSERS' => 'pcntl/pcntl.stub', 'PCRE_JIT_SUPPORT' => 'pcre/pcre.stub', 'PCRE_VERSION' => 'pcre/pcre.stub', 'PCRE_VERSION_MAJOR' => 'pcre/pcre.stub', 'PCRE_VERSION_MINOR' => 'pcre/pcre.stub', 'PEAR_EXTENSION_DIR' => 'Core/Core_d.stub', 'PEAR_INSTALL_DIR' => 'Core/Core_d.stub', 'PGSQL_ASSOC' => 'pgsql/pgsql.stub', 'PGSQL_BAD_RESPONSE' => 'pgsql/pgsql.stub', 'PGSQL_BOTH' => 'pgsql/pgsql.stub', 'PGSQL_COMMAND_OK' => 'pgsql/pgsql.stub', 'PGSQL_CONNECTION_AUTH_OK' => 'pgsql/pgsql.stub', 'PGSQL_CONNECTION_AWAITING_RESPONSE' => 'pgsql/pgsql.stub', 'PGSQL_CONNECTION_BAD' => 'pgsql/pgsql.stub', 'PGSQL_CONNECTION_MADE' => 'pgsql/pgsql.stub', 'PGSQL_CONNECTION_OK' => 'pgsql/pgsql.stub', 'PGSQL_CONNECTION_SETENV' => 'pgsql/pgsql.stub', 'PGSQL_CONNECTION_STARTED' => 'pgsql/pgsql.stub', 'PGSQL_CONNECT_ASYNC' => 'pgsql/pgsql.stub', 'PGSQL_CONNECT_FORCE_NEW' => 'pgsql/pgsql.stub', 'PGSQL_CONV_FORCE_NULL' => 'pgsql/pgsql.stub', 'PGSQL_CONV_IGNORE_DEFAULT' => 'pgsql/pgsql.stub', 'PGSQL_CONV_IGNORE_NOT_NULL' => 'pgsql/pgsql.stub', 'PGSQL_COPY_IN' => 'pgsql/pgsql.stub', 'PGSQL_COPY_OUT' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_COLUMN_NAME' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_CONSTRAINT_NAME' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_CONTEXT' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_DATATYPE_NAME' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_INTERNAL_POSITION' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_INTERNAL_QUERY' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_MESSAGE_DETAIL' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_MESSAGE_HINT' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_MESSAGE_PRIMARY' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_SCHEMA_NAME' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_SEVERITY' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_SEVERITY_NONLOCALIZED' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_SOURCE_FILE' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_SOURCE_FUNCTION' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_SOURCE_LINE' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_SQLSTATE' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_STATEMENT_POSITION' => 'pgsql/pgsql.stub', 'PGSQL_DIAG_TABLE_NAME' => 'pgsql/pgsql.stub', 'PGSQL_DML_ASYNC' => 'pgsql/pgsql.stub', 'PGSQL_DML_ESCAPE' => 'pgsql/pgsql.stub', 'PGSQL_DML_EXEC' => 'pgsql/pgsql.stub', 'PGSQL_DML_NO_CONV' => 'pgsql/pgsql.stub', 'PGSQL_DML_STRING' => 'pgsql/pgsql.stub', 'PGSQL_EMPTY_QUERY' => 'pgsql/pgsql.stub', 'PGSQL_ERRORS_DEFAULT' => 'pgsql/pgsql.stub', 'PGSQL_ERRORS_SQLSTATE' => 'pgsql/pgsql.stub', 'PGSQL_ERRORS_TERSE' => 'pgsql/pgsql.stub', 'PGSQL_ERRORS_VERBOSE' => 'pgsql/pgsql.stub', 'PGSQL_FATAL_ERROR' => 'pgsql/pgsql.stub', 'PGSQL_LIBPQ_VERSION' => 'pgsql/pgsql.stub', 'PGSQL_LIBPQ_VERSION_STR' => 'pgsql/pgsql.stub', 'PGSQL_NONFATAL_ERROR' => 'pgsql/pgsql.stub', 'PGSQL_NOTICE_ALL' => 'pgsql/pgsql.stub', 'PGSQL_NOTICE_CLEAR' => 'pgsql/pgsql.stub', 'PGSQL_NOTICE_LAST' => 'pgsql/pgsql.stub', 'PGSQL_NUM' => 'pgsql/pgsql.stub', 'PGSQL_PIPELINE_ABORTED' => 'pgsql/pgsql.stub', 'PGSQL_PIPELINE_OFF' => 'pgsql/pgsql.stub', 'PGSQL_PIPELINE_ON' => 'pgsql/pgsql.stub', 'PGSQL_PIPELINE_SYNC' => 'pgsql/pgsql.stub', 'PGSQL_POLLING_ACTIVE' => 'pgsql/pgsql.stub', 'PGSQL_POLLING_FAILED' => 'pgsql/pgsql.stub', 'PGSQL_POLLING_OK' => 'pgsql/pgsql.stub', 'PGSQL_POLLING_READING' => 'pgsql/pgsql.stub', 'PGSQL_POLLING_WRITING' => 'pgsql/pgsql.stub', 'PGSQL_SEEK_CUR' => 'pgsql/pgsql.stub', 'PGSQL_SEEK_END' => 'pgsql/pgsql.stub', 'PGSQL_SEEK_SET' => 'pgsql/pgsql.stub', 'PGSQL_SHOW_CONTEXT_ALWAYS' => 'pgsql/pgsql.stub', 'PGSQL_SHOW_CONTEXT_ERRORS' => 'pgsql/pgsql.stub', 'PGSQL_SHOW_CONTEXT_NEVER' => 'pgsql/pgsql.stub', 'PGSQL_STATUS_LONG' => 'pgsql/pgsql.stub', 'PGSQL_STATUS_STRING' => 'pgsql/pgsql.stub', 'PGSQL_TRACE_REGRESS_MODE' => 'pgsql/pgsql.stub', 'PGSQL_TRANSACTION_ACTIVE' => 'pgsql/pgsql.stub', 'PGSQL_TRANSACTION_IDLE' => 'pgsql/pgsql.stub', 'PGSQL_TRANSACTION_INERROR' => 'pgsql/pgsql.stub', 'PGSQL_TRANSACTION_INTRANS' => 'pgsql/pgsql.stub', 'PGSQL_TRANSACTION_UNKNOWN' => 'pgsql/pgsql.stub', 'PGSQL_TUPLES_OK' => 'pgsql/pgsql.stub', 'PHP_AMQP_MAX_CHANNELS' => 'amqp/amqp.stub', 'PHP_BINARY' => 'Core/Core_d.stub', 'PHP_BINARY_READ' => 'sockets/sockets.stub', 'PHP_BINDIR' => 'Core/Core_d.stub', 'PHP_CLI_PROCESS_TITLE' => 'Core/Core_d.stub', 'PHP_CONFIG_FILE_PATH' => 'Core/Core_d.stub', 'PHP_CONFIG_FILE_SCAN_DIR' => 'Core/Core_d.stub', 'PHP_DATADIR' => 'Core/Core_d.stub', 'PHP_DEBUG' => 'Core/Core_d.stub', 'PHP_EOL' => 'Core/Core_d.stub', 'PHP_EXTENSION_DIR' => 'Core/Core_d.stub', 'PHP_EXTRA_VERSION' => 'Core/Core_d.stub', 'PHP_FD_SETSIZE' => 'Core/Core_d.stub', 'PHP_FLOAT_DIG' => 'Core/Core_d.stub', 'PHP_FLOAT_EPSILON' => 'Core/Core_d.stub', 'PHP_FLOAT_MAX' => 'Core/Core_d.stub', 'PHP_FLOAT_MIN' => 'Core/Core_d.stub', 'PHP_INT_MAX' => 'Core/Core_d.stub', 'PHP_INT_MIN' => 'Core/Core_d.stub', 'PHP_INT_SIZE' => 'Core/Core_d.stub', 'PHP_LIBDIR' => 'Core/Core_d.stub', 'PHP_LOCALSTATEDIR' => 'Core/Core_d.stub', 'PHP_MAJOR_VERSION' => 'Core/Core_d.stub', 'PHP_MANDIR' => 'Core/Core_d.stub', 'PHP_MAXPATHLEN' => 'Core/Core_d.stub', 'PHP_MINOR_VERSION' => 'Core/Core_d.stub', 'PHP_NORMAL_READ' => 'sockets/sockets.stub', 'PHP_OS' => 'Core/Core_d.stub', 'PHP_OS_FAMILY' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_CLEAN' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_CLEANABLE' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_CONT' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_DISABLED' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_END' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_FINAL' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_FLUSH' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_FLUSHABLE' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_PROCESSED' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_REMOVABLE' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_START' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_STARTED' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_STDFLAGS' => 'Core/Core_d.stub', 'PHP_OUTPUT_HANDLER_WRITE' => 'Core/Core_d.stub', 'PHP_PREFIX' => 'Core/Core_d.stub', 'PHP_QUERY_RFC1738' => 'standard/standard_defines.stub', 'PHP_QUERY_RFC3986' => 'standard/standard_defines.stub', 'PHP_RELEASE_VERSION' => 'Core/Core_d.stub', 'PHP_ROUND_HALF_DOWN' => 'standard/standard_defines.stub', 'PHP_ROUND_HALF_EVEN' => 'standard/standard_defines.stub', 'PHP_ROUND_HALF_ODD' => 'standard/standard_defines.stub', 'PHP_ROUND_HALF_UP' => 'standard/standard_defines.stub', 'PHP_SAPI' => 'Core/Core_d.stub', 'PHP_SBINDIR' => 'Core/Core_d.stub', 'PHP_SESSION_ACTIVE' => 'standard/standard_defines.stub', 'PHP_SESSION_DISABLED' => 'standard/standard_defines.stub', 'PHP_SESSION_NONE' => 'standard/standard_defines.stub', 'PHP_SHLIB_SUFFIX' => 'Core/Core_d.stub', 'PHP_SVN_AUTH_PARAM_IGNORE_SSL_VERIFY_ERRORS' => 'svn/svn.stub', 'PHP_SYSCONFDIR' => 'Core/Core_d.stub', 'PHP_URL_FRAGMENT' => 'standard/standard_defines.stub', 'PHP_URL_HOST' => 'standard/standard_defines.stub', 'PHP_URL_PASS' => 'standard/standard_defines.stub', 'PHP_URL_PATH' => 'standard/standard_defines.stub', 'PHP_URL_PORT' => 'standard/standard_defines.stub', 'PHP_URL_QUERY' => 'standard/standard_defines.stub', 'PHP_URL_SCHEME' => 'standard/standard_defines.stub', 'PHP_URL_USER' => 'standard/standard_defines.stub', 'PHP_VERSION' => 'Core/Core_d.stub', 'PHP_VERSION_ID' => 'Core/Core_d.stub', 'PHP_WINDOWS_EVENT_CTRL_BREAK' => 'Core/Core_d.stub', 'PHP_WINDOWS_EVENT_CTRL_C' => 'Core/Core_d.stub', 'PHP_WINDOWS_NT_DOMAIN_CONTROLLER' => 'Core/Core_d.stub', 'PHP_WINDOWS_NT_SERVER' => 'Core/Core_d.stub', 'PHP_WINDOWS_NT_WORKSTATION' => 'Core/Core_d.stub', 'PHP_WINDOWS_VERSION_BUILD' => 'Core/Core_d.stub', 'PHP_WINDOWS_VERSION_MAJOR' => 'Core/Core_d.stub', 'PHP_WINDOWS_VERSION_MINOR' => 'Core/Core_d.stub', 'PHP_WINDOWS_VERSION_PLATFORM' => 'Core/Core_d.stub', 'PHP_WINDOWS_VERSION_PRODUCTTYPE' => 'Core/Core_d.stub', 'PHP_WINDOWS_VERSION_SP_MAJOR' => 'Core/Core_d.stub', 'PHP_WINDOWS_VERSION_SP_MINOR' => 'Core/Core_d.stub', 'PHP_WINDOWS_VERSION_SUITEMASK' => 'Core/Core_d.stub', 'PHP_ZTS' => 'Core/Core_d.stub', 'PKCS7_BINARY' => 'openssl/openssl.stub', 'PKCS7_DETACHED' => 'openssl/openssl.stub', 'PKCS7_NOATTR' => 'openssl/openssl.stub', 'PKCS7_NOCERTS' => 'openssl/openssl.stub', 'PKCS7_NOCHAIN' => 'openssl/openssl.stub', 'PKCS7_NOINTERN' => 'openssl/openssl.stub', 'PKCS7_NOOLDMIMETYPE' => 'openssl/openssl.stub', 'PKCS7_NOSIGS' => 'openssl/openssl.stub', 'PKCS7_NOVERIFY' => 'openssl/openssl.stub', 'PKCS7_TEXT' => 'openssl/openssl.stub', 'PM_STR' => 'standard/standard_defines.stub', 'PNG_ALL_FILTERS' => 'gd/gd.stub', 'PNG_FILTER_AVG' => 'gd/gd.stub', 'PNG_FILTER_NONE' => 'gd/gd.stub', 'PNG_FILTER_PAETH' => 'gd/gd.stub', 'PNG_FILTER_SUB' => 'gd/gd.stub', 'PNG_FILTER_UP' => 'gd/gd.stub', 'PNG_NO_FILTER' => 'gd/gd.stub', 'POLL_ERR' => 'pcntl/pcntl.stub', 'POLL_HUP' => 'pcntl/pcntl.stub', 'POLL_IN' => 'pcntl/pcntl.stub', 'POLL_MSG' => 'pcntl/pcntl.stub', 'POLL_OUT' => 'pcntl/pcntl.stub', 'POLL_PRI' => 'pcntl/pcntl.stub', 'POSITIVE_SIGN' => 'standard/standard_defines.stub', 'POSIX_F_OK' => 'posix/posix.stub', 'POSIX_PC_ALLOC_SIZE_MIN' => 'posix/posix.stub', 'POSIX_PC_CHOWN_RESTRICTED' => 'posix/posix.stub', 'POSIX_PC_LINK_MAX' => 'posix/posix.stub', 'POSIX_PC_MAX_CANON' => 'posix/posix.stub', 'POSIX_PC_MAX_INPUT' => 'posix/posix.stub', 'POSIX_PC_NAME_MAX' => 'posix/posix.stub', 'POSIX_PC_NO_TRUNC' => 'posix/posix.stub', 'POSIX_PC_PATH_MAX' => 'posix/posix.stub', 'POSIX_PC_PIPE_BUF' => 'posix/posix.stub', 'POSIX_PC_SYMLINK_MAX' => 'posix/posix.stub', 'POSIX_RLIMIT_AS' => 'posix/posix.stub', 'POSIX_RLIMIT_CORE' => 'posix/posix.stub', 'POSIX_RLIMIT_CPU' => 'posix/posix.stub', 'POSIX_RLIMIT_DATA' => 'posix/posix.stub', 'POSIX_RLIMIT_FSIZE' => 'posix/posix.stub', 'POSIX_RLIMIT_INFINITY' => 'posix/posix.stub', 'POSIX_RLIMIT_LOCKS' => 'posix/posix.stub', 'POSIX_RLIMIT_MEMLOCK' => 'posix/posix.stub', 'POSIX_RLIMIT_MSGQUEUE' => 'posix/posix.stub', 'POSIX_RLIMIT_NICE' => 'posix/posix.stub', 'POSIX_RLIMIT_NOFILE' => 'posix/posix.stub', 'POSIX_RLIMIT_NPROC' => 'posix/posix.stub', 'POSIX_RLIMIT_RSS' => 'posix/posix.stub', 'POSIX_RLIMIT_RTPRIO' => 'posix/posix.stub', 'POSIX_RLIMIT_RTTIME' => 'posix/posix.stub', 'POSIX_RLIMIT_SIGPENDING' => 'posix/posix.stub', 'POSIX_RLIMIT_STACK' => 'posix/posix.stub', 'POSIX_R_OK' => 'posix/posix.stub', 'POSIX_SC_ARG_MAX' => 'posix/posix.stub', 'POSIX_SC_CHILD_MAX' => 'posix/posix.stub', 'POSIX_SC_CLK_TCK' => 'posix/posix.stub', 'POSIX_SC_NPROCESSORS_CONF' => 'posix/posix.stub', 'POSIX_SC_NPROCESSORS_ONLN' => 'posix/posix.stub', 'POSIX_SC_PAGESIZE' => 'posix/posix.stub', 'POSIX_S_IFBLK' => 'posix/posix.stub', 'POSIX_S_IFCHR' => 'posix/posix.stub', 'POSIX_S_IFIFO' => 'posix/posix.stub', 'POSIX_S_IFREG' => 'posix/posix.stub', 'POSIX_S_IFSOCK' => 'posix/posix.stub', 'POSIX_W_OK' => 'posix/posix.stub', 'POSIX_X_OK' => 'posix/posix.stub', 'PREG_BACKTRACK_LIMIT_ERROR' => 'pcre/pcre.stub', 'PREG_BAD_UTF8_ERROR' => 'pcre/pcre.stub', 'PREG_BAD_UTF8_OFFSET_ERROR' => 'pcre/pcre.stub', 'PREG_GREP_INVERT' => 'pcre/pcre.stub', 'PREG_INTERNAL_ERROR' => 'pcre/pcre.stub', 'PREG_JIT_STACKLIMIT_ERROR' => 'pcre/pcre.stub', 'PREG_NO_ERROR' => 'pcre/pcre.stub', 'PREG_OFFSET_CAPTURE' => 'pcre/pcre.stub', 'PREG_PATTERN_ORDER' => 'pcre/pcre.stub', 'PREG_RECURSION_LIMIT_ERROR' => 'pcre/pcre.stub', 'PREG_SET_ORDER' => 'pcre/pcre.stub', 'PREG_SPLIT_DELIM_CAPTURE' => 'pcre/pcre.stub', 'PREG_SPLIT_NO_EMPTY' => 'pcre/pcre.stub', 'PREG_SPLIT_OFFSET_CAPTURE' => 'pcre/pcre.stub', 'PREG_UNMATCHED_AS_NULL' => 'pcre/pcre.stub', 'PRIO_PGRP' => 'pcntl/pcntl.stub', 'PRIO_PROCESS' => 'pcntl/pcntl.stub', 'PRIO_USER' => 'pcntl/pcntl.stub', 'PSFS_ERR_FATAL' => 'standard/standard_defines.stub', 'PSFS_FEED_ME' => 'standard/standard_defines.stub', 'PSFS_FLAG_FLUSH_CLOSE' => 'standard/standard_defines.stub', 'PSFS_FLAG_FLUSH_INC' => 'standard/standard_defines.stub', 'PSFS_FLAG_NORMAL' => 'standard/standard_defines.stub', 'PSFS_PASS_ON' => 'standard/standard_defines.stub', 'PSPELL_BAD_SPELLERS' => 'pspell/pspell.stub', 'PSPELL_FAST' => 'pspell/pspell.stub', 'PSPELL_NORMAL' => 'pspell/pspell.stub', 'PSPELL_RUN_TOGETHER' => 'pspell/pspell.stub', 'PTHREADS_ALLOW_HEADERS' => 'pthreads/pthreads.stub', 'PTHREADS_INHERIT_ALL' => 'pthreads/pthreads.stub', 'PTHREADS_INHERIT_CLASSES' => 'pthreads/pthreads.stub', 'PTHREADS_INHERIT_COMMENTS' => 'pthreads/pthreads.stub', 'PTHREADS_INHERIT_CONSTANTS' => 'pthreads/pthreads.stub', 'PTHREADS_INHERIT_FUNCTIONS' => 'pthreads/pthreads.stub', 'PTHREADS_INHERIT_INCLUDES' => 'pthreads/pthreads.stub', 'PTHREADS_INHERIT_INI' => 'pthreads/pthreads.stub', 'PTHREADS_INHERIT_NONE' => 'pthreads/pthreads.stub', 'P_ALL' => 'pcntl/pcntl.stub', 'P_CS_PRECEDES' => 'standard/standard_defines.stub', 'P_PGID' => 'pcntl/pcntl.stub', 'P_PID' => 'pcntl/pcntl.stub', 'P_PIDFD' => 'pcntl/pcntl.stub', 'P_SEP_BY_SPACE' => 'standard/standard_defines.stub', 'P_SIGN_POSN' => 'standard/standard_defines.stub', 'PopupWindow' => 'winbinder/winbinder.stub', 'PushButton' => 'winbinder/winbinder.stub', 'RADIUS_ACCESS_ACCEPT' => 'radius/radius.stub', 'RADIUS_ACCESS_CHALLENGE' => 'radius/radius.stub', 'RADIUS_ACCESS_REJECT' => 'radius/radius.stub', 'RADIUS_ACCESS_REQUEST' => 'radius/radius.stub', 'RADIUS_ACCOUNTING_OFF' => 'radius/radius.stub', 'RADIUS_ACCOUNTING_ON' => 'radius/radius.stub', 'RADIUS_ACCOUNTING_REQUEST' => 'radius/radius.stub', 'RADIUS_ACCOUNTING_RESPONSE' => 'radius/radius.stub', 'RADIUS_ACCT_AUTHENTIC' => 'radius/radius.stub', 'RADIUS_ACCT_DELAY_TIME' => 'radius/radius.stub', 'RADIUS_ACCT_INPUT_OCTETS' => 'radius/radius.stub', 'RADIUS_ACCT_INPUT_PACKETS' => 'radius/radius.stub', 'RADIUS_ACCT_LINK_COUNT' => 'radius/radius.stub', 'RADIUS_ACCT_MULTI_SESSION_ID' => 'radius/radius.stub', 'RADIUS_ACCT_OUTPUT_OCTETS' => 'radius/radius.stub', 'RADIUS_ACCT_OUTPUT_PACKETS' => 'radius/radius.stub', 'RADIUS_ACCT_SESSION_ID' => 'radius/radius.stub', 'RADIUS_ACCT_SESSION_TIME' => 'radius/radius.stub', 'RADIUS_ACCT_STATUS_TYPE' => 'radius/radius.stub', 'RADIUS_ACCT_TERMINATE_CAUSE' => 'radius/radius.stub', 'RADIUS_ADMINISTRATIVE' => 'radius/radius.stub', 'RADIUS_ADSL_CAP' => 'radius/radius.stub', 'RADIUS_ADSL_DMT' => 'radius/radius.stub', 'RADIUS_ARAP' => 'radius/radius.stub', 'RADIUS_ASYNC' => 'radius/radius.stub', 'RADIUS_AUTHENTICATE_ONLY' => 'radius/radius.stub', 'RADIUS_AUTH_LOCAL' => 'radius/radius.stub', 'RADIUS_AUTH_RADIUS' => 'radius/radius.stub', 'RADIUS_AUTH_REMOTE' => 'radius/radius.stub', 'RADIUS_CABLE' => 'radius/radius.stub', 'RADIUS_CALLBACK_FRAMED' => 'radius/radius.stub', 'RADIUS_CALLBACK_ID' => 'radius/radius.stub', 'RADIUS_CALLBACK_LOGIN' => 'radius/radius.stub', 'RADIUS_CALLBACK_NAS_PROMPT' => 'radius/radius.stub', 'RADIUS_CALLBACK_NUMBER' => 'radius/radius.stub', 'RADIUS_CALLED_STATION_ID' => 'radius/radius.stub', 'RADIUS_CALLING_STATION_ID' => 'radius/radius.stub', 'RADIUS_CHAP_CHALLENGE' => 'radius/radius.stub', 'RADIUS_CHAP_PASSWORD' => 'radius/radius.stub', 'RADIUS_CLASS' => 'radius/radius.stub', 'RADIUS_COA_ACK' => 'radius/radius.stub', 'RADIUS_COA_NAK' => 'radius/radius.stub', 'RADIUS_COA_REQUEST' => 'radius/radius.stub', 'RADIUS_COMP_IPXHDR' => 'radius/radius.stub', 'RADIUS_COMP_NONE' => 'radius/radius.stub', 'RADIUS_COMP_VJ' => 'radius/radius.stub', 'RADIUS_CONNECT_INFO' => 'radius/radius.stub', 'RADIUS_DISCONNECT_ACK' => 'radius/radius.stub', 'RADIUS_DISCONNECT_NAK' => 'radius/radius.stub', 'RADIUS_DISCONNECT_REQUEST' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_INVALID_EAP_PACKET' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_INVALID_REQUEST' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_MISSING_ATTRIBUTE' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_OTHER_PROXY_PROCESSING_ERROR' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_REQUEST_INITIATED' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_REQUEST_NOT_ROUTABLE' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_RESIDUAL_SESSION_CONTEXT_REMOVED' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_RESOURCES_UNAVAILABLE' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_UNSUPPORTED_EXCEPTION' => 'radius/radius.stub', 'RADIUS_ERROR_CAUSE_UNSUPPORTED_SERVICE' => 'radius/radius.stub', 'RADIUS_ETHERNET' => 'radius/radius.stub', 'RADIUS_FILTER_ID' => 'radius/radius.stub', 'RADIUS_FRAMED' => 'radius/radius.stub', 'RADIUS_FRAMED_APPLETALK_LINK' => 'radius/radius.stub', 'RADIUS_FRAMED_APPLETALK_NETWORK' => 'radius/radius.stub', 'RADIUS_FRAMED_APPLETALK_ZONE' => 'radius/radius.stub', 'RADIUS_FRAMED_COMPRESSION' => 'radius/radius.stub', 'RADIUS_FRAMED_INTERFACE_ID' => 'radius/radius.stub', 'RADIUS_FRAMED_IPV6_POOL' => 'radius/radius.stub', 'RADIUS_FRAMED_IPV6_PREFIX' => 'radius/radius.stub', 'RADIUS_FRAMED_IPV6_ROUTE' => 'radius/radius.stub', 'RADIUS_FRAMED_IPX_NETWORK' => 'radius/radius.stub', 'RADIUS_FRAMED_IP_ADDRESS' => 'radius/radius.stub', 'RADIUS_FRAMED_IP_NETMASK' => 'radius/radius.stub', 'RADIUS_FRAMED_MTU' => 'radius/radius.stub', 'RADIUS_FRAMED_PROTOCOL' => 'radius/radius.stub', 'RADIUS_FRAMED_ROUTE' => 'radius/radius.stub', 'RADIUS_FRAMED_ROUTING' => 'radius/radius.stub', 'RADIUS_GANDALF' => 'radius/radius.stub', 'RADIUS_G_3_FAX' => 'radius/radius.stub', 'RADIUS_HDLC_CLEAR_CHANNEL' => 'radius/radius.stub', 'RADIUS_IDLE_TIMEOUT' => 'radius/radius.stub', 'RADIUS_IDSL' => 'radius/radius.stub', 'RADIUS_ISDN_ASYNC_V110' => 'radius/radius.stub', 'RADIUS_ISDN_ASYNC_V120' => 'radius/radius.stub', 'RADIUS_ISDN_SYNC' => 'radius/radius.stub', 'RADIUS_LOGIN' => 'radius/radius.stub', 'RADIUS_LOGIN_IPV6_HOST' => 'radius/radius.stub', 'RADIUS_LOGIN_IP_HOST' => 'radius/radius.stub', 'RADIUS_LOGIN_LAT_GROUP' => 'radius/radius.stub', 'RADIUS_LOGIN_LAT_NODE' => 'radius/radius.stub', 'RADIUS_LOGIN_LAT_PORT' => 'radius/radius.stub', 'RADIUS_LOGIN_LAT_SERVICE' => 'radius/radius.stub', 'RADIUS_LOGIN_SERVICE' => 'radius/radius.stub', 'RADIUS_LOGIN_TCP_PORT' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_ACCT_AUTH_TYPE' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_ACCT_EAP_TYPE' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_ARAP_CHALLENGE' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_ARAP_PASSWORD_CHANGE_REASON' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_BAP_USAGE' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP2_PW' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP2_RESPONSE' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP2_SUCCESS' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP_CHALLENGE' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP_DOMAIN' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP_ERROR' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP_LM_ENC_PW' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP_NT_ENC_PW' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP_PW_1' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP_PW_2' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_CHAP_RESPONSE' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_FILTER' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_LINK_DROP_TIME_LIMIT' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_LINK_UTILIZATION_THRESHOLD' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_MPPE_RECV_KEY' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_MPPE_SEND_KEY' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_NEW_ARAP_PASSWORD' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_OLD_ARAP_PASSWORD' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_PRIMARY_NBNS_SERVER' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_RAS_VENDOR' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_RAS_VERSION' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_SECONDARY_DNS_SERVER' => 'radius/radius.stub', 'RADIUS_MICROSOFT_MS_SECONDARY_NBNS_SERVER' => 'radius/radius.stub', 'RADIUS_MPPE_KEY_LEN' => 'radius/radius.stub', 'RADIUS_NAS_IDENTIFIER' => 'radius/radius.stub', 'RADIUS_NAS_IPV6_ADDRESS' => 'radius/radius.stub', 'RADIUS_NAS_IP_ADDRESS' => 'radius/radius.stub', 'RADIUS_NAS_PORT' => 'radius/radius.stub', 'RADIUS_NAS_PORT_TYPE' => 'radius/radius.stub', 'RADIUS_NAS_PROMPT' => 'radius/radius.stub', 'RADIUS_OPTION_NONE' => 'radius/radius.stub', 'RADIUS_OPTION_SALT' => 'radius/radius.stub', 'RADIUS_OPTION_TAGGED' => 'radius/radius.stub', 'RADIUS_OUTBOUND' => 'radius/radius.stub', 'RADIUS_PIAFS' => 'radius/radius.stub', 'RADIUS_PORT_LIMIT' => 'radius/radius.stub', 'RADIUS_PPP' => 'radius/radius.stub', 'RADIUS_PROXY_STATE' => 'radius/radius.stub', 'RADIUS_REPLY_MESSAGE' => 'radius/radius.stub', 'RADIUS_SDSL' => 'radius/radius.stub', 'RADIUS_SERVICE_TYPE' => 'radius/radius.stub', 'RADIUS_SESSION_TIMEOUT' => 'radius/radius.stub', 'RADIUS_SLIP' => 'radius/radius.stub', 'RADIUS_START' => 'radius/radius.stub', 'RADIUS_STATE' => 'radius/radius.stub', 'RADIUS_STOP' => 'radius/radius.stub', 'RADIUS_SYNC' => 'radius/radius.stub', 'RADIUS_TERMINATION_ACTION' => 'radius/radius.stub', 'RADIUS_TERM_ADMIN_REBOOT' => 'radius/radius.stub', 'RADIUS_TERM_ADMIN_RESET' => 'radius/radius.stub', 'RADIUS_TERM_CALLBACK' => 'radius/radius.stub', 'RADIUS_TERM_HOST_REQUEST' => 'radius/radius.stub', 'RADIUS_TERM_IDLE_TIMEOUT' => 'radius/radius.stub', 'RADIUS_TERM_LOST_CARRIER' => 'radius/radius.stub', 'RADIUS_TERM_LOST_SERVICE' => 'radius/radius.stub', 'RADIUS_TERM_NAS_ERROR' => 'radius/radius.stub', 'RADIUS_TERM_NAS_REBOOT' => 'radius/radius.stub', 'RADIUS_TERM_NAS_REQUEST' => 'radius/radius.stub', 'RADIUS_TERM_PORT_ERROR' => 'radius/radius.stub', 'RADIUS_TERM_PORT_PREEMPTED' => 'radius/radius.stub', 'RADIUS_TERM_PORT_SUSPENDED' => 'radius/radius.stub', 'RADIUS_TERM_PORT_UNNEEDED' => 'radius/radius.stub', 'RADIUS_TERM_SERVICE_UNAVAILABLE' => 'radius/radius.stub', 'RADIUS_TERM_SESSION_TIMEOUT' => 'radius/radius.stub', 'RADIUS_TERM_USER_ERROR' => 'radius/radius.stub', 'RADIUS_TERM_USER_REQUEST' => 'radius/radius.stub', 'RADIUS_USER_NAME' => 'radius/radius.stub', 'RADIUS_USER_PASSWORD' => 'radius/radius.stub', 'RADIUS_VENDOR_MICROSOFT' => 'radius/radius.stub', 'RADIUS_VENDOR_SPECIFIC' => 'radius/radius.stub', 'RADIUS_VIRTUAL' => 'radius/radius.stub', 'RADIUS_WIRELESS_IEEE_802_11' => 'radius/radius.stub', 'RADIUS_WIRELESS_OTHER' => 'radius/radius.stub', 'RADIUS_XDSL' => 'radius/radius.stub', 'RADIUS_XYLOGICS' => 'radius/radius.stub', 'RADIUS_X_25' => 'radius/radius.stub', 'RADIUS_X_75' => 'radius/radius.stub', 'RADIXCHAR' => 'standard/standard_defines.stub', 'RAD_OPTION_TAG' => 'radius/radius.stub', 'RD_KAFKA_BUILD_VERSION' => 'rdkafka/constants.stub', 'RD_KAFKA_CONF_INVALID' => 'rdkafka/constants.stub', 'RD_KAFKA_CONF_OK' => 'rdkafka/constants.stub', 'RD_KAFKA_CONF_UNKNOWN' => 'rdkafka/constants.stub', 'RD_KAFKA_CONSUMER' => 'rdkafka/constants.stub', 'RD_KAFKA_LOG_PRINT' => 'rdkafka/constants.stub', 'RD_KAFKA_LOG_SYSLOG' => 'rdkafka/constants.stub', 'RD_KAFKA_LOG_SYSLOG_PRINT' => 'rdkafka/constants.stub', 'RD_KAFKA_MSG_F_BLOCK' => 'rdkafka/constants.stub', 'RD_KAFKA_MSG_PARTITIONER_CONSISTENT' => 'rdkafka/constants.stub', 'RD_KAFKA_MSG_PARTITIONER_CONSISTENT_RANDOM' => 'rdkafka/constants.stub', 'RD_KAFKA_MSG_PARTITIONER_MURMUR2' => 'rdkafka/constants.stub', 'RD_KAFKA_MSG_PARTITIONER_MURMUR2_RANDOM' => 'rdkafka/constants.stub', 'RD_KAFKA_MSG_PARTITIONER_RANDOM' => 'rdkafka/constants.stub', 'RD_KAFKA_OFFSET_BEGINNING' => 'rdkafka/constants.stub', 'RD_KAFKA_OFFSET_END' => 'rdkafka/constants.stub', 'RD_KAFKA_OFFSET_INVALID' => 'rdkafka/constants.stub', 'RD_KAFKA_OFFSET_STORED' => 'rdkafka/constants.stub', 'RD_KAFKA_PARTITION_UA' => 'rdkafka/constants.stub', 'RD_KAFKA_PRODUCER' => 'rdkafka/constants.stub', 'RD_KAFKA_PURGE_F_INFLIGHT' => 'rdkafka/constants.stub', 'RD_KAFKA_PURGE_F_NON_BLOCKING' => 'rdkafka/constants.stub', 'RD_KAFKA_PURGE_F_QUEUE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_BROKER_NOT_AVAILABLE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_CLUSTER_AUTHORIZATION_FAILED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_CONCURRENT_TRANSACTIONS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_COORDINATOR_LOAD_IN_PROGRESS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_DELEGATION_TOKEN_AUTHORIZATION_FAILED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_DELEGATION_TOKEN_AUTH_DISABLED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_DELEGATION_TOKEN_EXPIRED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_DELEGATION_TOKEN_NOT_FOUND' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_DELEGATION_TOKEN_OWNER_MISMATCH' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_DELEGATION_TOKEN_REQUEST_NOT_ALLOWED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_DUPLICATE_RESOURCE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_DUPLICATE_SEQUENCE_NUMBER' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_ELECTION_NOT_NEEDED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_ELIGIBLE_LEADERS_NOT_AVAILABLE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_FEATURE_UPDATE_FAILED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_FENCED_INSTANCE_ID' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_FENCED_LEADER_EPOCH' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_FETCH_SESSION_ID_NOT_FOUND' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_GROUP_AUTHORIZATION_FAILED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_GROUP_COORDINATOR_NOT_AVAILABLE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_GROUP_ID_NOT_FOUND' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_GROUP_LOAD_IN_PROGRESS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_GROUP_MAX_SIZE_REACHED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_GROUP_SUBSCRIBED_TO_TOPIC' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_ILLEGAL_GENERATION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_ILLEGAL_SASL_STATE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INCONSISTENT_GROUP_PROTOCOL' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INCONSISTENT_VOTER_SET' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_COMMIT_OFFSET_SIZE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_CONFIG' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_FETCH_SESSION_EPOCH' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_GROUP_ID' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_MSG' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_MSG_SIZE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_PARTITIONS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_PRINCIPAL_TYPE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_PRODUCER_EPOCH' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_PRODUCER_ID_MAPPING' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_RECORD' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_REPLICATION_FACTOR' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_REPLICA_ASSIGNMENT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_REQUEST' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_REQUIRED_ACKS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_SESSION_TIMEOUT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_TIMESTAMP' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_TRANSACTION_TIMEOUT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_TXN_STATE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_INVALID_UPDATE_VERSION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_KAFKA_STORAGE_ERROR' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_LEADER_NOT_AVAILABLE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_LISTENER_NOT_FOUND' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_LOG_DIR_NOT_FOUND' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_MEMBER_ID_REQUIRED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_MSG_SIZE_TOO_LARGE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NETWORK_EXCEPTION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NON_EMPTY_GROUP' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NOT_CONTROLLER' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NOT_COORDINATOR' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NOT_COORDINATOR_FOR_GROUP' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NOT_ENOUGH_REPLICAS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NOT_ENOUGH_REPLICAS_AFTER_APPEND' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NOT_LEADER_FOR_PARTITION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NO_ERROR' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_NO_REASSIGNMENT_IN_PROGRESS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_OFFSET_METADATA_TOO_LARGE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_OFFSET_NOT_AVAILABLE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_OFFSET_OUT_OF_RANGE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_OPERATION_NOT_ATTEMPTED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_OUT_OF_ORDER_SEQUENCE_NUMBER' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_POLICY_VIOLATION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_PREFERRED_LEADER_NOT_AVAILABLE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_PRINCIPAL_DESERIALIZATION_FAILURE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_PRODUCER_FENCED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_REASSIGNMENT_IN_PROGRESS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_REBALANCE_IN_PROGRESS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_RECORD_LIST_TOO_LARGE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_REPLICA_NOT_AVAILABLE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_REQUEST_TIMED_OUT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_RESOURCE_NOT_FOUND' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_SASL_AUTHENTICATION_FAILED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_SECURITY_DISABLED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_STALE_BROKER_EPOCH' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_STALE_CTRL_EPOCH' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_THROTTLING_QUOTA_EXCEEDED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_TOPIC_ALREADY_EXISTS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_TOPIC_DELETION_DISABLED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_TOPIC_EXCEPTION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_TRANSACTIONAL_ID_AUTHORIZATION_FAILED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_TRANSACTION_COORDINATOR_FENCED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNACCEPTABLE_CREDENTIAL' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNKNOWN' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNKNOWN_LEADER_EPOCH' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNKNOWN_MEMBER_ID' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNKNOWN_PRODUCER_ID' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNSTABLE_OFFSET_COMMIT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNSUPPORTED_COMPRESSION_TYPE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNSUPPORTED_FOR_MESSAGE_FORMAT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNSUPPORTED_SASL_MECHANISM' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR_UNSUPPORTED_VERSION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__ALL_BROKERS_DOWN' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__APPLICATION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__ASSIGNMENT_LOST' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__AUTHENTICATION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__AUTO_OFFSET_RESET' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__BAD_COMPRESSION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__BAD_MSG' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__BEGIN' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__CONFLICT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__CRIT_SYS_RESOURCE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__DESTROY' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__END' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__EXISTING_SUBSCRIPTION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__FAIL' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__FATAL' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__FENCED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__FS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__GAPLESS_GUARANTEE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__INCONSISTENT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__INTR' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__INVALID_ARG' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__INVALID_TYPE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__IN_PROGRESS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__ISR_INSUFF' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__KEY_DESERIALIZATION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__KEY_SERIALIZATION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__MAX_POLL_EXCEEDED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__MSG_TIMED_OUT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__NODE_UPDATE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__NOENT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__NOOP' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__NOT_CONFIGURED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__NOT_IMPLEMENTED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__NO_OFFSET' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__OUTDATED' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__PARTIAL' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__PARTITION_EOF' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__PREV_IN_PROGRESS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__PURGE_INFLIGHT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__PURGE_QUEUE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__QUEUE_FULL' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__READ_ONLY' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__RESOLVE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__RETRY' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__SSL' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__STATE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__TIMED_OUT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__TIMED_OUT_QUEUE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__TRANSPORT' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__UNDERFLOW' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__UNKNOWN_BROKER' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__UNKNOWN_GROUP' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__UNKNOWN_PROTOCOL' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__UNKNOWN_TOPIC' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__UNSUPPORTED_FEATURE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__VALUE_DESERIALIZATION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__VALUE_SERIALIZATION' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__WAIT_CACHE' => 'rdkafka/constants.stub', 'RD_KAFKA_RESP_ERR__WAIT_COORD' => 'rdkafka/constants.stub', 'RD_KAFKA_VERSION' => 'rdkafka/constants.stub', 'READLINE_LIB' => 'readline/readline.stub', 'RED' => 'winbinder/winbinder.stub', 'RPMMIRE_DEFAULT' => 'rpminfo/rpminfo.stub', 'RPMMIRE_GLOB' => 'rpminfo/rpminfo.stub', 'RPMMIRE_REGEX' => 'rpminfo/rpminfo.stub', 'RPMMIRE_STRCMP' => 'rpminfo/rpminfo.stub', 'RPMSENSE_ANY' => 'rpminfo/rpminfo.stub', 'RPMSENSE_CONFIG' => 'rpminfo/rpminfo.stub', 'RPMSENSE_EQUAL' => 'rpminfo/rpminfo.stub', 'RPMSENSE_FIND_PROVIDES' => 'rpminfo/rpminfo.stub', 'RPMSENSE_FIND_REQUIRES' => 'rpminfo/rpminfo.stub', 'RPMSENSE_GREATER' => 'rpminfo/rpminfo.stub', 'RPMSENSE_INTERP' => 'rpminfo/rpminfo.stub', 'RPMSENSE_KEYRING' => 'rpminfo/rpminfo.stub', 'RPMSENSE_LESS' => 'rpminfo/rpminfo.stub', 'RPMSENSE_MISSINGOK' => 'rpminfo/rpminfo.stub', 'RPMSENSE_POSTTRANS' => 'rpminfo/rpminfo.stub', 'RPMSENSE_PREREQ' => 'rpminfo/rpminfo.stub', 'RPMSENSE_PRETRANS' => 'rpminfo/rpminfo.stub', 'RPMSENSE_RPMLIB' => 'rpminfo/rpminfo.stub', 'RPMSENSE_SCRIPT_POST' => 'rpminfo/rpminfo.stub', 'RPMSENSE_SCRIPT_POSTUN' => 'rpminfo/rpminfo.stub', 'RPMSENSE_SCRIPT_PRE' => 'rpminfo/rpminfo.stub', 'RPMSENSE_SCRIPT_PREUN' => 'rpminfo/rpminfo.stub', 'RPMSENSE_SCRIPT_VERIFY' => 'rpminfo/rpminfo.stub', 'RPMSENSE_TRIGGERIN' => 'rpminfo/rpminfo.stub', 'RPMSENSE_TRIGGERPOSTUN' => 'rpminfo/rpminfo.stub', 'RPMSENSE_TRIGGERPREIN' => 'rpminfo/rpminfo.stub', 'RPMSENSE_TRIGGERUN' => 'rpminfo/rpminfo.stub', 'RPMTAG_ARCH' => 'rpminfo/rpminfo.stub', 'RPMTAG_ARCHIVESIZE' => 'rpminfo/rpminfo.stub', 'RPMTAG_BASENAMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_BUGURL' => 'rpminfo/rpminfo.stub', 'RPMTAG_BUILDARCHS' => 'rpminfo/rpminfo.stub', 'RPMTAG_BUILDHOST' => 'rpminfo/rpminfo.stub', 'RPMTAG_BUILDTIME' => 'rpminfo/rpminfo.stub', 'RPMTAG_C' => 'rpminfo/rpminfo.stub', 'RPMTAG_CHANGELOGNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_CHANGELOGTEXT' => 'rpminfo/rpminfo.stub', 'RPMTAG_CHANGELOGTIME' => 'rpminfo/rpminfo.stub', 'RPMTAG_CLASSDICT' => 'rpminfo/rpminfo.stub', 'RPMTAG_CONFLICTFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_CONFLICTNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_CONFLICTNEVRS' => 'rpminfo/rpminfo.stub', 'RPMTAG_CONFLICTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_CONFLICTVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_COOKIE' => 'rpminfo/rpminfo.stub', 'RPMTAG_DBINSTANCE' => 'rpminfo/rpminfo.stub', 'RPMTAG_DEPENDSDICT' => 'rpminfo/rpminfo.stub', 'RPMTAG_DESCRIPTION' => 'rpminfo/rpminfo.stub', 'RPMTAG_DIRINDEXES' => 'rpminfo/rpminfo.stub', 'RPMTAG_DIRNAMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_DISTRIBUTION' => 'rpminfo/rpminfo.stub', 'RPMTAG_DISTTAG' => 'rpminfo/rpminfo.stub', 'RPMTAG_DISTURL' => 'rpminfo/rpminfo.stub', 'RPMTAG_DSAHEADER' => 'rpminfo/rpminfo.stub', 'RPMTAG_E' => 'rpminfo/rpminfo.stub', 'RPMTAG_ENCODING' => 'rpminfo/rpminfo.stub', 'RPMTAG_ENHANCEFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_ENHANCENAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_ENHANCENEVRS' => 'rpminfo/rpminfo.stub', 'RPMTAG_ENHANCES' => 'rpminfo/rpminfo.stub', 'RPMTAG_ENHANCEVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_EPOCH' => 'rpminfo/rpminfo.stub', 'RPMTAG_EPOCHNUM' => 'rpminfo/rpminfo.stub', 'RPMTAG_EVR' => 'rpminfo/rpminfo.stub', 'RPMTAG_EXCLUDEARCH' => 'rpminfo/rpminfo.stub', 'RPMTAG_EXCLUDEOS' => 'rpminfo/rpminfo.stub', 'RPMTAG_EXCLUSIVEARCH' => 'rpminfo/rpminfo.stub', 'RPMTAG_EXCLUSIVEOS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILECAPS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILECLASS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILECOLORS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILECONTEXTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEDEPENDSN' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEDEPENDSX' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEDEVICES' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEDIGESTALGO' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEDIGESTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEGROUPNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEINODES' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILELANGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILELINKTOS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEMD5S' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEMODES' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEMTIMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILENAMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILENLINKS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEPROVIDE' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILERDEVS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEREQUIRE' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILESIGNATURELENGTH' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILESIGNATURES' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILESIZES' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILESTATES' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERCONDS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERINDEX' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERPRIORITIES' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERSCRIPTFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERSCRIPTPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERSCRIPTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERTYPE' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILETRIGGERVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEUSERNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_FILEVERIFYFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_FSCONTEXTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_GIF' => 'rpminfo/rpminfo.stub', 'RPMTAG_GROUP' => 'rpminfo/rpminfo.stub', 'RPMTAG_HDRID' => 'rpminfo/rpminfo.stub', 'RPMTAG_HEADERCOLOR' => 'rpminfo/rpminfo.stub', 'RPMTAG_HEADERI18NTABLE' => 'rpminfo/rpminfo.stub', 'RPMTAG_HEADERIMAGE' => 'rpminfo/rpminfo.stub', 'RPMTAG_HEADERIMMUTABLE' => 'rpminfo/rpminfo.stub', 'RPMTAG_HEADERREGIONS' => 'rpminfo/rpminfo.stub', 'RPMTAG_HEADERSIGNATURES' => 'rpminfo/rpminfo.stub', 'RPMTAG_ICON' => 'rpminfo/rpminfo.stub', 'RPMTAG_INSTALLCOLOR' => 'rpminfo/rpminfo.stub', 'RPMTAG_INSTALLTID' => 'rpminfo/rpminfo.stub', 'RPMTAG_INSTALLTIME' => 'rpminfo/rpminfo.stub', 'RPMTAG_INSTFILENAMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_INSTPREFIXES' => 'rpminfo/rpminfo.stub', 'RPMTAG_LICENSE' => 'rpminfo/rpminfo.stub', 'RPMTAG_LONGARCHIVESIZE' => 'rpminfo/rpminfo.stub', 'RPMTAG_LONGFILESIZES' => 'rpminfo/rpminfo.stub', 'RPMTAG_LONGSIGSIZE' => 'rpminfo/rpminfo.stub', 'RPMTAG_LONGSIZE' => 'rpminfo/rpminfo.stub', 'RPMTAG_MODULARITYLABEL' => 'rpminfo/rpminfo.stub', 'RPMTAG_N' => 'rpminfo/rpminfo.stub', 'RPMTAG_NAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_NEVR' => 'rpminfo/rpminfo.stub', 'RPMTAG_NEVRA' => 'rpminfo/rpminfo.stub', 'RPMTAG_NOPATCH' => 'rpminfo/rpminfo.stub', 'RPMTAG_NOSOURCE' => 'rpminfo/rpminfo.stub', 'RPMTAG_NVR' => 'rpminfo/rpminfo.stub', 'RPMTAG_NVRA' => 'rpminfo/rpminfo.stub', 'RPMTAG_O' => 'rpminfo/rpminfo.stub', 'RPMTAG_OBSOLETEFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_OBSOLETENAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_OBSOLETENEVRS' => 'rpminfo/rpminfo.stub', 'RPMTAG_OBSOLETES' => 'rpminfo/rpminfo.stub', 'RPMTAG_OBSOLETEVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_OLDENHANCES' => 'rpminfo/rpminfo.stub', 'RPMTAG_OLDENHANCESFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_OLDENHANCESNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_OLDENHANCESVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_OLDFILENAMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_OLDSUGGESTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_OLDSUGGESTSFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_OLDSUGGESTSNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_OLDSUGGESTSVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_OPTFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_ORDERFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_ORDERNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_ORDERVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_ORIGBASENAMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_ORIGDIRINDEXES' => 'rpminfo/rpminfo.stub', 'RPMTAG_ORIGDIRNAMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_ORIGFILENAMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_OS' => 'rpminfo/rpminfo.stub', 'RPMTAG_P' => 'rpminfo/rpminfo.stub', 'RPMTAG_PACKAGER' => 'rpminfo/rpminfo.stub', 'RPMTAG_PATCH' => 'rpminfo/rpminfo.stub', 'RPMTAG_PATCHESFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_PATCHESNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_PATCHESVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_PAYLOADCOMPRESSOR' => 'rpminfo/rpminfo.stub', 'RPMTAG_PAYLOADDIGEST' => 'rpminfo/rpminfo.stub', 'RPMTAG_PAYLOADDIGESTALGO' => 'rpminfo/rpminfo.stub', 'RPMTAG_PAYLOADFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_PAYLOADFORMAT' => 'rpminfo/rpminfo.stub', 'RPMTAG_PKGID' => 'rpminfo/rpminfo.stub', 'RPMTAG_PLATFORM' => 'rpminfo/rpminfo.stub', 'RPMTAG_POLICIES' => 'rpminfo/rpminfo.stub', 'RPMTAG_POLICYFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_POLICYNAMES' => 'rpminfo/rpminfo.stub', 'RPMTAG_POLICYTYPES' => 'rpminfo/rpminfo.stub', 'RPMTAG_POLICYTYPESINDEXES' => 'rpminfo/rpminfo.stub', 'RPMTAG_POSTIN' => 'rpminfo/rpminfo.stub', 'RPMTAG_POSTINFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_POSTINPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_POSTTRANS' => 'rpminfo/rpminfo.stub', 'RPMTAG_POSTTRANSFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_POSTTRANSPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_POSTUN' => 'rpminfo/rpminfo.stub', 'RPMTAG_POSTUNFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_POSTUNPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_PREFIXES' => 'rpminfo/rpminfo.stub', 'RPMTAG_PREIN' => 'rpminfo/rpminfo.stub', 'RPMTAG_PREINFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_PREINPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_PRETRANS' => 'rpminfo/rpminfo.stub', 'RPMTAG_PRETRANSFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_PRETRANSPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_PREUN' => 'rpminfo/rpminfo.stub', 'RPMTAG_PREUNFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_PREUNPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_PROVIDEFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_PROVIDENAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_PROVIDENEVRS' => 'rpminfo/rpminfo.stub', 'RPMTAG_PROVIDES' => 'rpminfo/rpminfo.stub', 'RPMTAG_PROVIDEVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_PUBKEYS' => 'rpminfo/rpminfo.stub', 'RPMTAG_R' => 'rpminfo/rpminfo.stub', 'RPMTAG_RECOMMENDFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_RECOMMENDNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_RECOMMENDNEVRS' => 'rpminfo/rpminfo.stub', 'RPMTAG_RECOMMENDS' => 'rpminfo/rpminfo.stub', 'RPMTAG_RECOMMENDVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_RECONTEXTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_RELEASE' => 'rpminfo/rpminfo.stub', 'RPMTAG_REMOVETID' => 'rpminfo/rpminfo.stub', 'RPMTAG_REQUIREFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_REQUIRENAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_REQUIRENEVRS' => 'rpminfo/rpminfo.stub', 'RPMTAG_REQUIRES' => 'rpminfo/rpminfo.stub', 'RPMTAG_REQUIREVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_RPMVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_RSAHEADER' => 'rpminfo/rpminfo.stub', 'RPMTAG_SHA1HEADER' => 'rpminfo/rpminfo.stub', 'RPMTAG_SHA256HEADER' => 'rpminfo/rpminfo.stub', 'RPMTAG_SIGGPG' => 'rpminfo/rpminfo.stub', 'RPMTAG_SIGMD5' => 'rpminfo/rpminfo.stub', 'RPMTAG_SIGPGP' => 'rpminfo/rpminfo.stub', 'RPMTAG_SIGSIZE' => 'rpminfo/rpminfo.stub', 'RPMTAG_SIZE' => 'rpminfo/rpminfo.stub', 'RPMTAG_SOURCE' => 'rpminfo/rpminfo.stub', 'RPMTAG_SOURCEPACKAGE' => 'rpminfo/rpminfo.stub', 'RPMTAG_SOURCEPKGID' => 'rpminfo/rpminfo.stub', 'RPMTAG_SOURCERPM' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUGGESTFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUGGESTNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUGGESTNEVRS' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUGGESTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUGGESTVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUMMARY' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUPPLEMENTFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUPPLEMENTNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUPPLEMENTNEVRS' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUPPLEMENTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_SUPPLEMENTVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERCONDS' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERINDEX' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERPRIORITIES' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERSCRIPTPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERSCRIPTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERTYPE' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRANSFILETRIGGERVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRIGGERCONDS' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRIGGERFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRIGGERINDEX' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRIGGERNAME' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRIGGERSCRIPTFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRIGGERSCRIPTPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRIGGERSCRIPTS' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRIGGERTYPE' => 'rpminfo/rpminfo.stub', 'RPMTAG_TRIGGERVERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_URL' => 'rpminfo/rpminfo.stub', 'RPMTAG_V' => 'rpminfo/rpminfo.stub', 'RPMTAG_VCS' => 'rpminfo/rpminfo.stub', 'RPMTAG_VENDOR' => 'rpminfo/rpminfo.stub', 'RPMTAG_VERBOSE' => 'rpminfo/rpminfo.stub', 'RPMTAG_VERIFYSCRIPT' => 'rpminfo/rpminfo.stub', 'RPMTAG_VERIFYSCRIPTFLAGS' => 'rpminfo/rpminfo.stub', 'RPMTAG_VERIFYSCRIPTPROG' => 'rpminfo/rpminfo.stub', 'RPMTAG_VERSION' => 'rpminfo/rpminfo.stub', 'RPMTAG_XPM' => 'rpminfo/rpminfo.stub', 'RPMVERSION' => 'rpminfo/rpminfo.stub', 'RTFEditBox' => 'winbinder/winbinder.stub', 'RadioButton' => 'winbinder/winbinder.stub', 'ResizableWindow' => 'winbinder/winbinder.stub', 'SA_ALL' => 'imap/imap.stub', 'SA_MESSAGES' => 'imap/imap.stub', 'SA_RECENT' => 'imap/imap.stub', 'SA_UIDNEXT' => 'imap/imap.stub', 'SA_UIDVALIDITY' => 'imap/imap.stub', 'SA_UNSEEN' => 'imap/imap.stub', 'SCANDIR_SORT_ASCENDING' => 'standard/standard_defines.stub', 'SCANDIR_SORT_DESCENDING' => 'standard/standard_defines.stub', 'SCANDIR_SORT_NONE' => 'standard/standard_defines.stub', 'SCM_CREDENTIALS' => 'sockets/sockets.stub', 'SCM_RIGHTS' => 'sockets/sockets.stub', 'SEEK_CUR' => 'standard/standard_defines.stub', 'SEEK_END' => 'standard/standard_defines.stub', 'SEEK_SET' => 'standard/standard_defines.stub', 'SEGV_ACCERR' => 'pcntl/pcntl.stub', 'SEGV_MAPERR' => 'pcntl/pcntl.stub', 'SE_FREE' => 'imap/imap.stub', 'SE_NOPREFETCH' => 'imap/imap.stub', 'SE_UID' => 'imap/imap.stub', 'SID' => 'standard/standard_defines.stub', 'SIGABRT' => 'pcntl/pcntl.stub', 'SIGALRM' => 'pcntl/pcntl.stub', 'SIGBABY' => 'pcntl/pcntl.stub', 'SIGBUS' => 'pcntl/pcntl.stub', 'SIGCHLD' => 'pcntl/pcntl.stub', 'SIGCLD' => 'pcntl/pcntl.stub', 'SIGCONT' => 'pcntl/pcntl.stub', 'SIGFPE' => 'pcntl/pcntl.stub', 'SIGHUP' => 'pcntl/pcntl.stub', 'SIGILL' => 'pcntl/pcntl.stub', 'SIGINT' => 'pcntl/pcntl.stub', 'SIGIO' => 'pcntl/pcntl.stub', 'SIGIOT' => 'pcntl/pcntl.stub', 'SIGKILL' => 'pcntl/pcntl.stub', 'SIGPIPE' => 'pcntl/pcntl.stub', 'SIGPOLL' => 'pcntl/pcntl.stub', 'SIGPROF' => 'pcntl/pcntl.stub', 'SIGPWR' => 'pcntl/pcntl.stub', 'SIGQUIT' => 'pcntl/pcntl.stub', 'SIGRTMAX' => 'pcntl/pcntl.stub', 'SIGRTMIN' => 'pcntl/pcntl.stub', 'SIGSEGV' => 'pcntl/pcntl.stub', 'SIGSTKFLT' => 'pcntl/pcntl.stub', 'SIGSTOP' => 'pcntl/pcntl.stub', 'SIGSYS' => 'pcntl/pcntl.stub', 'SIGTERM' => 'pcntl/pcntl.stub', 'SIGTRAP' => 'pcntl/pcntl.stub', 'SIGTSTP' => 'pcntl/pcntl.stub', 'SIGTTIN' => 'pcntl/pcntl.stub', 'SIGTTOU' => 'pcntl/pcntl.stub', 'SIGURG' => 'pcntl/pcntl.stub', 'SIGUSR1' => 'pcntl/pcntl.stub', 'SIGUSR2' => 'pcntl/pcntl.stub', 'SIGVTALRM' => 'pcntl/pcntl.stub', 'SIGWINCH' => 'pcntl/pcntl.stub', 'SIGXCPU' => 'pcntl/pcntl.stub', 'SIGXFSZ' => 'pcntl/pcntl.stub', 'SIG_BLOCK' => 'pcntl/pcntl.stub', 'SIG_DFL' => 'pcntl/pcntl.stub', 'SIG_ERR' => 'pcntl/pcntl.stub', 'SIG_IGN' => 'pcntl/pcntl.stub', 'SIG_SETMASK' => 'pcntl/pcntl.stub', 'SIG_UNBLOCK' => 'pcntl/pcntl.stub', 'SI_ASYNCIO' => 'pcntl/pcntl.stub', 'SI_KERNEL' => 'pcntl/pcntl.stub', 'SI_MESGQ' => 'pcntl/pcntl.stub', 'SI_QUEUE' => 'pcntl/pcntl.stub', 'SI_SIGIO' => 'pcntl/pcntl.stub', 'SI_TIMER' => 'pcntl/pcntl.stub', 'SI_TKILL' => 'pcntl/pcntl.stub', 'SI_USER' => 'pcntl/pcntl.stub', 'SKF_AD_ALU_XOR_X' => 'sockets/sockets.stub', 'SKF_AD_CPU' => 'sockets/sockets.stub', 'SKF_AD_HATYPE' => 'sockets/sockets.stub', 'SKF_AD_IFINDEX' => 'sockets/sockets.stub', 'SKF_AD_MARK' => 'sockets/sockets.stub', 'SKF_AD_MAX' => 'sockets/sockets.stub', 'SKF_AD_NLATTR' => 'sockets/sockets.stub', 'SKF_AD_NLATTR_NEST' => 'sockets/sockets.stub', 'SKF_AD_OFF' => 'sockets/sockets.stub', 'SKF_AD_PAY_OFFSET' => 'sockets/sockets.stub', 'SKF_AD_PKTTYPE' => 'sockets/sockets.stub', 'SKF_AD_PROTOCOL' => 'sockets/sockets.stub', 'SKF_AD_QUEUE' => 'sockets/sockets.stub', 'SKF_AD_RANDOM' => 'sockets/sockets.stub', 'SKF_AD_RXHASH' => 'sockets/sockets.stub', 'SKF_AD_VLAN_TAG' => 'sockets/sockets.stub', 'SKF_AD_VLAN_TAG_PRESENT' => 'sockets/sockets.stub', 'SKF_AD_VLAN_TPID' => 'sockets/sockets.stub', 'SNMP_BIT_STR' => 'snmp/snmp.stub', 'SNMP_COUNTER' => 'snmp/snmp.stub', 'SNMP_COUNTER64' => 'snmp/snmp.stub', 'SNMP_INTEGER' => 'snmp/snmp.stub', 'SNMP_IPADDRESS' => 'snmp/snmp.stub', 'SNMP_NULL' => 'snmp/snmp.stub', 'SNMP_OBJECT_ID' => 'snmp/snmp.stub', 'SNMP_OCTET_STR' => 'snmp/snmp.stub', 'SNMP_OID_OUTPUT_FULL' => 'snmp/snmp.stub', 'SNMP_OID_OUTPUT_MODULE' => 'snmp/snmp.stub', 'SNMP_OID_OUTPUT_NONE' => 'snmp/snmp.stub', 'SNMP_OID_OUTPUT_NUMERIC' => 'snmp/snmp.stub', 'SNMP_OID_OUTPUT_SUFFIX' => 'snmp/snmp.stub', 'SNMP_OID_OUTPUT_UCD' => 'snmp/snmp.stub', 'SNMP_OPAQUE' => 'snmp/snmp.stub', 'SNMP_TIMETICKS' => 'snmp/snmp.stub', 'SNMP_UINTEGER' => 'snmp/snmp.stub', 'SNMP_UNSIGNED' => 'snmp/snmp.stub', 'SNMP_VALUE_LIBRARY' => 'snmp/snmp.stub', 'SNMP_VALUE_OBJECT' => 'snmp/snmp.stub', 'SNMP_VALUE_PLAIN' => 'snmp/snmp.stub', 'SOAP_1_1' => 'soap/soap.stub', 'SOAP_1_2' => 'soap/soap.stub', 'SOAP_ACTOR_NEXT' => 'soap/soap.stub', 'SOAP_ACTOR_NONE' => 'soap/soap.stub', 'SOAP_ACTOR_UNLIMATERECEIVER' => 'soap/soap.stub', 'SOAP_AUTHENTICATION_BASIC' => 'soap/soap.stub', 'SOAP_AUTHENTICATION_DIGEST' => 'soap/soap.stub', 'SOAP_COMPRESSION_ACCEPT' => 'soap/soap.stub', 'SOAP_COMPRESSION_DEFLATE' => 'soap/soap.stub', 'SOAP_COMPRESSION_GZIP' => 'soap/soap.stub', 'SOAP_DOCUMENT' => 'soap/soap.stub', 'SOAP_ENCODED' => 'soap/soap.stub', 'SOAP_ENC_ARRAY' => 'soap/soap.stub', 'SOAP_ENC_OBJECT' => 'soap/soap.stub', 'SOAP_FUNCTIONS_ALL' => 'soap/soap.stub', 'SOAP_LITERAL' => 'soap/soap.stub', 'SOAP_PERSISTENCE_REQUEST' => 'soap/soap.stub', 'SOAP_PERSISTENCE_SESSION' => 'soap/soap.stub', 'SOAP_RPC' => 'soap/soap.stub', 'SOAP_SINGLE_ELEMENT_ARRAYS' => 'soap/soap.stub', 'SOAP_SSL_METHOD_SSLv2' => 'soap/soap.stub', 'SOAP_SSL_METHOD_SSLv23' => 'soap/soap.stub', 'SOAP_SSL_METHOD_SSLv3' => 'soap/soap.stub', 'SOAP_SSL_METHOD_TLS' => 'soap/soap.stub', 'SOAP_USE_XSI_ARRAY_TYPE' => 'soap/soap.stub', 'SOAP_WAIT_ONE_WAY_CALLS' => 'soap/soap.stub', 'SOCKET_E2BIG' => 'sockets/sockets.stub', 'SOCKET_EACCES' => 'sockets/sockets.stub', 'SOCKET_EADDRINUSE' => 'sockets/sockets.stub', 'SOCKET_EADDRNOTAVAIL' => 'sockets/sockets.stub', 'SOCKET_EADV' => 'sockets/sockets.stub', 'SOCKET_EAFNOSUPPORT' => 'sockets/sockets.stub', 'SOCKET_EAGAIN' => 'sockets/sockets.stub', 'SOCKET_EALREADY' => 'sockets/sockets.stub', 'SOCKET_EBADE' => 'sockets/sockets.stub', 'SOCKET_EBADF' => 'sockets/sockets.stub', 'SOCKET_EBADFD' => 'sockets/sockets.stub', 'SOCKET_EBADMSG' => 'sockets/sockets.stub', 'SOCKET_EBADR' => 'sockets/sockets.stub', 'SOCKET_EBADRQC' => 'sockets/sockets.stub', 'SOCKET_EBADSLT' => 'sockets/sockets.stub', 'SOCKET_EBUSY' => 'sockets/sockets.stub', 'SOCKET_ECANCELED' => 'swoole/constants.stub', 'SOCKET_ECHRNG' => 'sockets/sockets.stub', 'SOCKET_ECOMM' => 'sockets/sockets.stub', 'SOCKET_ECONNABORTED' => 'sockets/sockets.stub', 'SOCKET_ECONNREFUSED' => 'sockets/sockets.stub', 'SOCKET_ECONNRESET' => 'sockets/sockets.stub', 'SOCKET_EDESTADDRREQ' => 'sockets/sockets.stub', 'SOCKET_EDISCON' => 'sockets/sockets.stub', 'SOCKET_EDQUOT' => 'sockets/sockets.stub', 'SOCKET_EEXIST' => 'sockets/sockets.stub', 'SOCKET_EFAULT' => 'sockets/sockets.stub', 'SOCKET_EHOSTDOWN' => 'sockets/sockets.stub', 'SOCKET_EHOSTUNREACH' => 'sockets/sockets.stub', 'SOCKET_EIDRM' => 'sockets/sockets.stub', 'SOCKET_EINPROGRESS' => 'sockets/sockets.stub', 'SOCKET_EINTR' => 'sockets/sockets.stub', 'SOCKET_EINVAL' => 'sockets/sockets.stub', 'SOCKET_EIO' => 'sockets/sockets.stub', 'SOCKET_EISCONN' => 'sockets/sockets.stub', 'SOCKET_EISDIR' => 'sockets/sockets.stub', 'SOCKET_EISNAM' => 'sockets/sockets.stub', 'SOCKET_EL2HLT' => 'sockets/sockets.stub', 'SOCKET_EL2NSYNC' => 'sockets/sockets.stub', 'SOCKET_EL3HLT' => 'sockets/sockets.stub', 'SOCKET_EL3RST' => 'sockets/sockets.stub', 'SOCKET_ELNRNG' => 'sockets/sockets.stub', 'SOCKET_ELOOP' => 'sockets/sockets.stub', 'SOCKET_EMEDIUMTYPE' => 'sockets/sockets.stub', 'SOCKET_EMFILE' => 'sockets/sockets.stub', 'SOCKET_EMLINK' => 'sockets/sockets.stub', 'SOCKET_EMSGSIZE' => 'sockets/sockets.stub', 'SOCKET_EMULTIHOP' => 'sockets/sockets.stub', 'SOCKET_ENAMETOOLONG' => 'sockets/sockets.stub', 'SOCKET_ENETDOWN' => 'sockets/sockets.stub', 'SOCKET_ENETRESET' => 'sockets/sockets.stub', 'SOCKET_ENETUNREACH' => 'sockets/sockets.stub', 'SOCKET_ENFILE' => 'sockets/sockets.stub', 'SOCKET_ENOANO' => 'sockets/sockets.stub', 'SOCKET_ENOBUFS' => 'sockets/sockets.stub', 'SOCKET_ENOCSI' => 'sockets/sockets.stub', 'SOCKET_ENODATA' => 'sockets/sockets.stub', 'SOCKET_ENODEV' => 'sockets/sockets.stub', 'SOCKET_ENOENT' => 'sockets/sockets.stub', 'SOCKET_ENOLCK' => 'sockets/sockets.stub', 'SOCKET_ENOLINK' => 'sockets/sockets.stub', 'SOCKET_ENOMEDIUM' => 'sockets/sockets.stub', 'SOCKET_ENOMEM' => 'sockets/sockets.stub', 'SOCKET_ENOMSG' => 'sockets/sockets.stub', 'SOCKET_ENONET' => 'sockets/sockets.stub', 'SOCKET_ENOPROTOOPT' => 'sockets/sockets.stub', 'SOCKET_ENOSPC' => 'sockets/sockets.stub', 'SOCKET_ENOSR' => 'sockets/sockets.stub', 'SOCKET_ENOSTR' => 'sockets/sockets.stub', 'SOCKET_ENOSYS' => 'sockets/sockets.stub', 'SOCKET_ENOTBLK' => 'sockets/sockets.stub', 'SOCKET_ENOTCONN' => 'sockets/sockets.stub', 'SOCKET_ENOTDIR' => 'sockets/sockets.stub', 'SOCKET_ENOTEMPTY' => 'sockets/sockets.stub', 'SOCKET_ENOTSOCK' => 'sockets/sockets.stub', 'SOCKET_ENOTTY' => 'sockets/sockets.stub', 'SOCKET_ENOTUNIQ' => 'sockets/sockets.stub', 'SOCKET_ENXIO' => 'sockets/sockets.stub', 'SOCKET_EOPNOTSUPP' => 'sockets/sockets.stub', 'SOCKET_EPERM' => 'sockets/sockets.stub', 'SOCKET_EPFNOSUPPORT' => 'sockets/sockets.stub', 'SOCKET_EPIPE' => 'sockets/sockets.stub', 'SOCKET_EPROCLIM' => 'sockets/sockets.stub', 'SOCKET_EPROTO' => 'sockets/sockets.stub', 'SOCKET_EPROTONOSUPPORT' => 'sockets/sockets.stub', 'SOCKET_EPROTOTYPE' => 'sockets/sockets.stub', 'SOCKET_EREMCHG' => 'sockets/sockets.stub', 'SOCKET_EREMOTE' => 'sockets/sockets.stub', 'SOCKET_EREMOTEIO' => 'sockets/sockets.stub', 'SOCKET_ERESTART' => 'sockets/sockets.stub', 'SOCKET_EROFS' => 'sockets/sockets.stub', 'SOCKET_ESHUTDOWN' => 'sockets/sockets.stub', 'SOCKET_ESOCKTNOSUPPORT' => 'sockets/sockets.stub', 'SOCKET_ESPIPE' => 'sockets/sockets.stub', 'SOCKET_ESRMNT' => 'sockets/sockets.stub', 'SOCKET_ESTALE' => 'sockets/sockets.stub', 'SOCKET_ESTRPIPE' => 'sockets/sockets.stub', 'SOCKET_ETIME' => 'sockets/sockets.stub', 'SOCKET_ETIMEDOUT' => 'sockets/sockets.stub', 'SOCKET_ETOOMANYREFS' => 'sockets/sockets.stub', 'SOCKET_EUNATCH' => 'sockets/sockets.stub', 'SOCKET_EUSERS' => 'sockets/sockets.stub', 'SOCKET_EWOULDBLOCK' => 'sockets/sockets.stub', 'SOCKET_EXDEV' => 'sockets/sockets.stub', 'SOCKET_EXFULL' => 'sockets/sockets.stub', 'SOCKET_HOST_NOT_FOUND' => 'sockets/sockets.stub', 'SOCKET_NOTINITIALISED' => 'sockets/sockets.stub', 'SOCKET_NO_ADDRESS' => 'sockets/sockets.stub', 'SOCKET_NO_DATA' => 'sockets/sockets.stub', 'SOCKET_NO_RECOVERY' => 'sockets/sockets.stub', 'SOCKET_SYSNOTREADY' => 'sockets/sockets.stub', 'SOCKET_TRY_AGAIN' => 'sockets/sockets.stub', 'SOCKET_VERNOTSUPPORTED' => 'sockets/sockets.stub', 'SOCK_CLOEXEC' => 'sockets/sockets.stub', 'SOCK_DCCP' => 'sockets/sockets.stub', 'SOCK_DGRAM' => 'sockets/sockets.stub', 'SOCK_NONBLOCK' => 'sockets/sockets.stub', 'SOCK_RAW' => 'sockets/sockets.stub', 'SOCK_RDM' => 'sockets/sockets.stub', 'SOCK_SEQPACKET' => 'sockets/sockets.stub', 'SOCK_STREAM' => 'sockets/sockets.stub', 'SODIUM_BASE64_VARIANT_ORIGINAL' => 'sodium/sodium.stub', 'SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING' => 'sodium/sodium.stub', 'SODIUM_BASE64_VARIANT_URLSAFE' => 'sodium/sodium.stub', 'SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_AEGIS128L_ABYTES' => 'libsodium/libsodium_d.stub', 'SODIUM_CRYPTO_AEAD_AEGIS128L_KEYBYTES' => 'libsodium/libsodium_d.stub', 'SODIUM_CRYPTO_AEAD_AEGIS128L_NPUBBYTES' => 'libsodium/libsodium_d.stub', 'SODIUM_CRYPTO_AEAD_AEGIS128L_NSECBYTES' => 'libsodium/libsodium_d.stub', 'SODIUM_CRYPTO_AEAD_AEGIS256_ABYTES' => 'libsodium/libsodium_d.stub', 'SODIUM_CRYPTO_AEAD_AEGIS256_KEYBYTES' => 'libsodium/libsodium_d.stub', 'SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES' => 'libsodium/libsodium_d.stub', 'SODIUM_CRYPTO_AEAD_AEGIS256_NSECBYTES' => 'libsodium/libsodium_d.stub', 'SODIUM_CRYPTO_AEAD_AES256GCM_ABYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_AES256GCM_NSECBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_ABYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NSECBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AUTH_BYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_AUTH_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_BOX_KEYPAIRBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_BOX_MACBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_BOX_NONCEBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_BOX_PUBLICKEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_BOX_SEALBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_BOX_SECRETKEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_BOX_SEEDBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_CORE_RISTRETTO255_HASHBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_CORE_RISTRETTO255_NONREDUCEDSCALARBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_GENERICHASH_BYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_GENERICHASH_BYTES_MAX' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_GENERICHASH_BYTES_MIN' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_GENERICHASH_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MAX' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MIN' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KDF_BYTES_MAX' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KDF_BYTES_MIN' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KDF_CONTEXTBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KDF_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KX_BYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KX_KEYPAIRBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KX_PUBLICKEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KX_SECRETKEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KX_SEEDBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_KX_SESSIONKEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_ALG_ARGON2I13' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_ALG_DEFAULT' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_SALTBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_PWHASH_STRPREFIX' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SCALARMULT_BYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_BYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_SCALARBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SCALARMULT_SCALARBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETBOX_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETBOX_MACBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETBOX_NONCEBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SHORTHASH_BYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SHORTHASH_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SIGN_BYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SIGN_KEYPAIRBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SIGN_SECRETKEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_SIGN_SEEDBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_STREAM_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_STREAM_NONCEBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_STREAM_XCHACHA20_KEYBYTES' => 'sodium/sodium.stub', 'SODIUM_CRYPTO_STREAM_XCHACHA20_NONCEBYTES' => 'sodium/sodium.stub', 'SODIUM_LIBRARY_MAJOR_VERSION' => 'sodium/sodium.stub', 'SODIUM_LIBRARY_MINOR_VERSION' => 'sodium/sodium.stub', 'SODIUM_LIBRARY_VERSION' => 'sodium/sodium.stub', 'SOLR_EXTENSION_VERSION' => 'solr/constants.stub', 'SOLR_MAJOR_VERSION' => 'solr/constants.stub', 'SOLR_MINOR_VERSION' => 'solr/constants.stub', 'SOLR_PATCH_VERSION' => 'solr/constants.stub', 'SOL_SOCKET' => 'sockets/sockets.stub', 'SOL_TCP' => 'sockets/sockets.stub', 'SOL_UDP' => 'sockets/sockets.stub', 'SOL_UDPLITE' => 'sockets/sockets.stub', 'SOMAXCONN' => 'sockets/sockets.stub', 'SORTARRIVAL' => 'imap/imap.stub', 'SORTCC' => 'imap/imap.stub', 'SORTDATE' => 'imap/imap.stub', 'SORTFROM' => 'imap/imap.stub', 'SORTSIZE' => 'imap/imap.stub', 'SORTSUBJECT' => 'imap/imap.stub', 'SORTTO' => 'imap/imap.stub', 'SORT_ASC' => 'standard/standard_defines.stub', 'SORT_DESC' => 'standard/standard_defines.stub', 'SORT_FLAG_CASE' => 'standard/standard_defines.stub', 'SORT_LOCALE_STRING' => 'standard/standard_defines.stub', 'SORT_NATURAL' => 'standard/standard_defines.stub', 'SORT_NUMERIC' => 'standard/standard_defines.stub', 'SORT_REGULAR' => 'standard/standard_defines.stub', 'SORT_STRING' => 'standard/standard_defines.stub', 'SO_ATTACH_REUSEPORT_CBPF' => 'sockets/sockets.stub', 'SO_BINDTODEVICE' => 'sockets/sockets.stub', 'SO_BINDTOIFINDEX' => 'sockets/sockets.stub', 'SO_BPF_EXTENSIONS' => 'sockets/sockets.stub', 'SO_BROADCAST' => 'sockets/sockets.stub', 'SO_DEBUG' => 'sockets/sockets.stub', 'SO_DETACH_BPF' => 'sockets/sockets.stub', 'SO_DETACH_FILTER' => 'sockets/sockets.stub', 'SO_DONTROUTE' => 'sockets/sockets.stub', 'SO_ERROR' => 'sockets/sockets.stub', 'SO_FREE' => 'imap/imap.stub', 'SO_INCOMING_CPU' => 'sockets/sockets.stub', 'SO_KEEPALIVE' => 'sockets/sockets.stub', 'SO_LINGER' => 'sockets/sockets.stub', 'SO_MARK' => 'sockets/sockets.stub', 'SO_MEMINFO' => 'sockets/sockets.stub', 'SO_NOSERVER' => 'imap/imap.stub', 'SO_OOBINLINE' => 'sockets/sockets.stub', 'SO_PASSCRED' => 'sockets/sockets.stub', 'SO_RCVBUF' => 'sockets/sockets.stub', 'SO_RCVLOWAT' => 'sockets/sockets.stub', 'SO_RCVTIMEO' => 'sockets/sockets.stub', 'SO_REUSEADDR' => 'sockets/sockets.stub', 'SO_REUSEPORT' => 'sockets/sockets.stub', 'SO_SNDBUF' => 'sockets/sockets.stub', 'SO_SNDLOWAT' => 'sockets/sockets.stub', 'SO_SNDTIMEO' => 'sockets/sockets.stub', 'SO_TYPE' => 'sockets/sockets.stub', 'SO_ZEROCOPY' => 'sockets/sockets.stub', 'SQLBIT' => 'mssql/mssql.stub', 'SQLCHAR' => 'mssql/mssql.stub', 'SQLFLT4' => 'mssql/mssql.stub', 'SQLFLT8' => 'mssql/mssql.stub', 'SQLFLTN' => 'mssql/mssql.stub', 'SQLINT1' => 'mssql/mssql.stub', 'SQLINT2' => 'mssql/mssql.stub', 'SQLINT4' => 'mssql/mssql.stub', 'SQLITE3_ASSOC' => 'sqlite3/sqlite3.stub', 'SQLITE3_BLOB' => 'sqlite3/sqlite3.stub', 'SQLITE3_BOTH' => 'sqlite3/sqlite3.stub', 'SQLITE3_DETERMINISTIC' => 'sqlite3/sqlite3.stub', 'SQLITE3_FLOAT' => 'sqlite3/sqlite3.stub', 'SQLITE3_INTEGER' => 'sqlite3/sqlite3.stub', 'SQLITE3_NULL' => 'sqlite3/sqlite3.stub', 'SQLITE3_NUM' => 'sqlite3/sqlite3.stub', 'SQLITE3_OPEN_CREATE' => 'sqlite3/sqlite3.stub', 'SQLITE3_OPEN_READONLY' => 'sqlite3/sqlite3.stub', 'SQLITE3_OPEN_READWRITE' => 'sqlite3/sqlite3.stub', 'SQLITE3_TEXT' => 'sqlite3/sqlite3.stub', 'SQLITE_ABORT' => 'SQLite/SQLite.stub', 'SQLITE_ASSOC' => 'SQLite/SQLite.stub', 'SQLITE_AUTH' => 'SQLite/SQLite.stub', 'SQLITE_BOTH' => 'SQLite/SQLite.stub', 'SQLITE_BUSY' => 'SQLite/SQLite.stub', 'SQLITE_CANTOPEN' => 'SQLite/SQLite.stub', 'SQLITE_CONSTRAINT' => 'SQLite/SQLite.stub', 'SQLITE_CORRUPT' => 'SQLite/SQLite.stub', 'SQLITE_DONE' => 'SQLite/SQLite.stub', 'SQLITE_EMPTY' => 'SQLite/SQLite.stub', 'SQLITE_ERROR' => 'SQLite/SQLite.stub', 'SQLITE_FORMAT' => 'SQLite/SQLite.stub', 'SQLITE_FULL' => 'SQLite/SQLite.stub', 'SQLITE_INTERNAL' => 'SQLite/SQLite.stub', 'SQLITE_INTERRUPT' => 'SQLite/SQLite.stub', 'SQLITE_IOERR' => 'SQLite/SQLite.stub', 'SQLITE_LOCKED' => 'SQLite/SQLite.stub', 'SQLITE_MISMATCH' => 'SQLite/SQLite.stub', 'SQLITE_MISUSE' => 'SQLite/SQLite.stub', 'SQLITE_NOLFS' => 'SQLite/SQLite.stub', 'SQLITE_NOMEM' => 'SQLite/SQLite.stub', 'SQLITE_NOTADB' => 'SQLite/SQLite.stub', 'SQLITE_NOTFOUND' => 'SQLite/SQLite.stub', 'SQLITE_NUM' => 'SQLite/SQLite.stub', 'SQLITE_OK' => 'SQLite/SQLite.stub', 'SQLITE_PERM' => 'SQLite/SQLite.stub', 'SQLITE_PROTOCOL' => 'SQLite/SQLite.stub', 'SQLITE_READONLY' => 'SQLite/SQLite.stub', 'SQLITE_ROW' => 'SQLite/SQLite.stub', 'SQLITE_SCHEMA' => 'SQLite/SQLite.stub', 'SQLITE_TOOBIG' => 'SQLite/SQLite.stub', 'SQLSRV_CURSOR_CLIENT_BUFFERED' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_CURSOR_DYNAMIC' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_CURSOR_FORWARD' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_CURSOR_KEYSET' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_CURSOR_STATIC' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_ENC_BINARY' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_ENC_CHAR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_ERR_ALL' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_ERR_ERRORS' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_ERR_WARNINGS' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_FETCH_ASSOC' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_FETCH_BOTH' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_FETCH_NUMERIC' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SEVERITY_ALL' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SEVERITY_ERROR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SEVERITY_NOTICE' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SEVERITY_WARNING' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SYSTEM_ALL' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SYSTEM_CONN' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SYSTEM_INIT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SYSTEM_OFF' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SYSTEM_STMT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_LOG_SYSTEM_UTIL' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_NULLABLE_NO' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_NULLABLE_UNKNOWN' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_NULLABLE_YES' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_PARAM_IN' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_PARAM_INOUT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_PARAM_OUT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_PHPTYPE_DATETIME' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_PHPTYPE_FLOAT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_PHPTYPE_INT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_PHPTYPE_NULL' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SCROLL_ABSOLUTE' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SCROLL_FIRST' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SCROLL_LAST' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SCROLL_NEXT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SCROLL_PRIOR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SCROLL_RELATIVE' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_BIGINT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_BIT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_CHAR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_DATE' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_DATETIME' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_DATETIME2' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_DATETIMEOFFSET' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_DECIMAL' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_FLOAT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_IMAGE' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_INT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_MONEY' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_NCHAR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_NTEXT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_NUMERIC' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_NVARCHAR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_REAL' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_SMALLDATETIME' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_SMALLINT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_SMALLMONEY' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_TEXT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_TIME' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_TIMESTAMP' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_TINYINT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_UDT' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_UNIQUEIDENTIFIER' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_VARBINARY' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_VARCHAR' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_SQLTYPE_XML' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_TXN_READ_COMMITTED' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_TXN_READ_UNCOMMITTED' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_TXN_REPEATABLE_READ' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_TXN_SERIALIZABLE' => 'sqlsrv/sqlsrv.stub', 'SQLSRV_TXN_SNAPSHOT' => 'sqlsrv/sqlsrv.stub', 'SQLTEXT' => 'mssql/mssql.stub', 'SQLT_AFC' => 'oci8/oci8.stub', 'SQLT_AVC' => 'oci8/oci8.stub', 'SQLT_BDOUBLE' => 'oci8/oci8.stub', 'SQLT_BFILEE' => 'oci8/oci8.stub', 'SQLT_BFLOAT' => 'oci8/oci8.stub', 'SQLT_BIN' => 'oci8/oci8.stub', 'SQLT_BLOB' => 'oci8/oci8.stub', 'SQLT_BOL' => 'oci8/oci8.stub', 'SQLT_CFILEE' => 'oci8/oci8.stub', 'SQLT_CHR' => 'oci8/oci8.stub', 'SQLT_CLOB' => 'oci8/oci8.stub', 'SQLT_FLT' => 'oci8/oci8.stub', 'SQLT_INT' => 'oci8/oci8.stub', 'SQLT_LBI' => 'oci8/oci8.stub', 'SQLT_LNG' => 'oci8/oci8.stub', 'SQLT_LVC' => 'oci8/oci8.stub', 'SQLT_NTY' => 'oci8/oci8.stub', 'SQLT_NUM' => 'oci8/oci8.stub', 'SQLT_ODT' => 'oci8/oci8.stub', 'SQLT_RDD' => 'oci8/oci8.stub', 'SQLT_RSET' => 'oci8/oci8.stub', 'SQLT_STR' => 'oci8/oci8.stub', 'SQLT_UIN' => 'oci8/oci8.stub', 'SQLT_VCS' => 'oci8/oci8.stub', 'SQLVARCHAR' => 'mssql/mssql.stub', 'SQL_BEST_ROWID' => 'odbc/odbc.stub', 'SQL_BIGINT' => 'odbc/odbc.stub', 'SQL_BINARY' => 'odbc/odbc.stub', 'SQL_BIT' => 'odbc/odbc.stub', 'SQL_CHAR' => 'odbc/odbc.stub', 'SQL_CONCURRENCY' => 'odbc/odbc.stub', 'SQL_CONCUR_LOCK' => 'odbc/odbc.stub', 'SQL_CONCUR_READ_ONLY' => 'odbc/odbc.stub', 'SQL_CONCUR_ROWVER' => 'odbc/odbc.stub', 'SQL_CONCUR_VALUES' => 'odbc/odbc.stub', 'SQL_CURSOR_DYNAMIC' => 'odbc/odbc.stub', 'SQL_CURSOR_FORWARD_ONLY' => 'odbc/odbc.stub', 'SQL_CURSOR_KEYSET_DRIVEN' => 'odbc/odbc.stub', 'SQL_CURSOR_STATIC' => 'odbc/odbc.stub', 'SQL_CURSOR_TYPE' => 'odbc/odbc.stub', 'SQL_CUR_USE_DRIVER' => 'odbc/odbc.stub', 'SQL_CUR_USE_IF_NEEDED' => 'odbc/odbc.stub', 'SQL_CUR_USE_ODBC' => 'odbc/odbc.stub', 'SQL_DATE' => 'odbc/odbc.stub', 'SQL_DECIMAL' => 'odbc/odbc.stub', 'SQL_DOUBLE' => 'odbc/odbc.stub', 'SQL_ENSURE' => 'odbc/odbc.stub', 'SQL_FETCH_FIRST' => 'odbc/odbc.stub', 'SQL_FETCH_NEXT' => 'odbc/odbc.stub', 'SQL_FLOAT' => 'odbc/odbc.stub', 'SQL_INDEX_ALL' => 'odbc/odbc.stub', 'SQL_INDEX_UNIQUE' => 'odbc/odbc.stub', 'SQL_INTEGER' => 'odbc/odbc.stub', 'SQL_KEYSET_SIZE' => 'odbc/odbc.stub', 'SQL_LONGVARBINARY' => 'odbc/odbc.stub', 'SQL_LONGVARCHAR' => 'odbc/odbc.stub', 'SQL_NO_NULLS' => 'odbc/odbc.stub', 'SQL_NULLABLE' => 'odbc/odbc.stub', 'SQL_NUMERIC' => 'odbc/odbc.stub', 'SQL_ODBC_CURSORS' => 'odbc/odbc.stub', 'SQL_QUICK' => 'odbc/odbc.stub', 'SQL_REAL' => 'odbc/odbc.stub', 'SQL_ROWVER' => 'odbc/odbc.stub', 'SQL_SCOPE_CURROW' => 'odbc/odbc.stub', 'SQL_SCOPE_SESSION' => 'odbc/odbc.stub', 'SQL_SCOPE_TRANSACTION' => 'odbc/odbc.stub', 'SQL_SMALLINT' => 'odbc/odbc.stub', 'SQL_TIME' => 'odbc/odbc.stub', 'SQL_TIMESTAMP' => 'odbc/odbc.stub', 'SQL_TINYINT' => 'odbc/odbc.stub', 'SQL_TYPE_DATE' => 'odbc/odbc.stub', 'SQL_TYPE_TIME' => 'odbc/odbc.stub', 'SQL_TYPE_TIMESTAMP' => 'odbc/odbc.stub', 'SQL_VARBINARY' => 'odbc/odbc.stub', 'SQL_VARCHAR' => 'odbc/odbc.stub', 'SQL_WCHAR' => 'odbc/odbc.stub', 'SQL_WLONGVARCHAR' => 'odbc/odbc.stub', 'SQL_WVARCHAR' => 'odbc/odbc.stub', 'SSH2_DEFAULT_TERMINAL' => 'ssh2/ssh2.stub', 'SSH2_DEFAULT_TERM_HEIGHT' => 'ssh2/ssh2.stub', 'SSH2_DEFAULT_TERM_UNIT' => 'ssh2/ssh2.stub', 'SSH2_DEFAULT_TERM_WIDTH' => 'ssh2/ssh2.stub', 'SSH2_FINGERPRINT_HEX' => 'ssh2/ssh2.stub', 'SSH2_FINGERPRINT_MD5' => 'ssh2/ssh2.stub', 'SSH2_FINGERPRINT_RAW' => 'ssh2/ssh2.stub', 'SSH2_FINGERPRINT_SHA1' => 'ssh2/ssh2.stub', 'SSH2_POLLERR' => 'ssh2/ssh2.stub', 'SSH2_POLLEXT' => 'ssh2/ssh2.stub', 'SSH2_POLLHUP' => 'ssh2/ssh2.stub', 'SSH2_POLLIN' => 'ssh2/ssh2.stub', 'SSH2_POLLNVAL' => 'ssh2/ssh2.stub', 'SSH2_POLLOUT' => 'ssh2/ssh2.stub', 'SSH2_POLL_CHANNEL_CLOSED' => 'ssh2/ssh2.stub', 'SSH2_POLL_LISTENER_CLOSED' => 'ssh2/ssh2.stub', 'SSH2_POLL_SESSION_CLOSED' => 'ssh2/ssh2.stub', 'SSH2_STREAM_STDERR' => 'ssh2/ssh2.stub', 'SSH2_STREAM_STDIO' => 'ssh2/ssh2.stub', 'SSH2_TERM_UNIT_CHARS' => 'ssh2/ssh2.stub', 'SSH2_TERM_UNIT_PIXELS' => 'ssh2/ssh2.stub', 'STDERR' => 'Core/Core_d.stub', 'STDIN' => 'Core/Core_d.stub', 'STDOUT' => 'Core/Core_d.stub', 'STREAM_BUFFER_FULL' => 'standard/standard_defines.stub', 'STREAM_BUFFER_LINE' => 'standard/standard_defines.stub', 'STREAM_BUFFER_NONE' => 'standard/standard_defines.stub', 'STREAM_CAST_AS_STREAM' => 'standard/standard_defines.stub', 'STREAM_CAST_FOR_SELECT' => 'standard/standard_defines.stub', 'STREAM_CLIENT_ASYNC_CONNECT' => 'standard/standard_defines.stub', 'STREAM_CLIENT_CONNECT' => 'standard/standard_defines.stub', 'STREAM_CLIENT_PERSISTENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_ANY_CLIENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_ANY_SERVER' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_SSLv23_CLIENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_SSLv23_SERVER' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_SSLv2_CLIENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_SSLv2_SERVER' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_SSLv3_CLIENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_SSLv3_SERVER' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLS_CLIENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLS_SERVER' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLSv1_0_SERVER' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLSv1_1_SERVER' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLSv1_2_SERVER' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_METHOD_TLSv1_3_SERVER' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_PROTO_SSLv3' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_PROTO_TLSv1_0' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_PROTO_TLSv1_1' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_PROTO_TLSv1_2' => 'standard/standard_defines.stub', 'STREAM_CRYPTO_PROTO_TLSv1_3' => 'standard/standard_defines.stub', 'STREAM_ENFORCE_SAFE_MODE' => 'standard/standard_defines.stub', 'STREAM_FILTER_ALL' => 'standard/standard_defines.stub', 'STREAM_FILTER_READ' => 'standard/standard_defines.stub', 'STREAM_FILTER_WRITE' => 'standard/standard_defines.stub', 'STREAM_IGNORE_URL' => 'standard/standard_defines.stub', 'STREAM_IPPROTO_ICMP' => 'standard/standard_defines.stub', 'STREAM_IPPROTO_IP' => 'standard/standard_defines.stub', 'STREAM_IPPROTO_RAW' => 'standard/standard_defines.stub', 'STREAM_IPPROTO_TCP' => 'standard/standard_defines.stub', 'STREAM_IPPROTO_UDP' => 'standard/standard_defines.stub', 'STREAM_IS_URL' => 'standard/standard_defines.stub', 'STREAM_META_ACCESS' => 'standard/standard_defines.stub', 'STREAM_META_GROUP' => 'standard/standard_defines.stub', 'STREAM_META_GROUP_NAME' => 'standard/standard_defines.stub', 'STREAM_META_OWNER' => 'standard/standard_defines.stub', 'STREAM_META_OWNER_NAME' => 'standard/standard_defines.stub', 'STREAM_META_TOUCH' => 'standard/standard_defines.stub', 'STREAM_MKDIR_RECURSIVE' => 'standard/standard_defines.stub', 'STREAM_MUST_SEEK' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_AUTH_REQUIRED' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_AUTH_RESULT' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_COMPLETED' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_CONNECT' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_FAILURE' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_FILE_SIZE_IS' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_MIME_TYPE_IS' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_PROGRESS' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_REDIRECTED' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_RESOLVE' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_SEVERITY_ERR' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_SEVERITY_INFO' => 'standard/standard_defines.stub', 'STREAM_NOTIFY_SEVERITY_WARN' => 'standard/standard_defines.stub', 'STREAM_OOB' => 'standard/standard_defines.stub', 'STREAM_OPTION_BLOCKING' => 'standard/standard_defines.stub', 'STREAM_OPTION_READ_BUFFER' => 'standard/standard_defines.stub', 'STREAM_OPTION_READ_TIMEOUT' => 'standard/standard_defines.stub', 'STREAM_OPTION_WRITE_BUFFER' => 'standard/standard_defines.stub', 'STREAM_PEEK' => 'standard/standard_defines.stub', 'STREAM_PF_INET' => 'standard/standard_defines.stub', 'STREAM_PF_INET6' => 'standard/standard_defines.stub', 'STREAM_PF_UNIX' => 'standard/standard_defines.stub', 'STREAM_REPORT_ERRORS' => 'standard/standard_defines.stub', 'STREAM_SERVER_BIND' => 'standard/standard_defines.stub', 'STREAM_SERVER_LISTEN' => 'standard/standard_defines.stub', 'STREAM_SHUT_RD' => 'standard/standard_defines.stub', 'STREAM_SHUT_RDWR' => 'standard/standard_defines.stub', 'STREAM_SHUT_WR' => 'standard/standard_defines.stub', 'STREAM_SOCK_DGRAM' => 'standard/standard_defines.stub', 'STREAM_SOCK_RAW' => 'standard/standard_defines.stub', 'STREAM_SOCK_RDM' => 'standard/standard_defines.stub', 'STREAM_SOCK_SEQPACKET' => 'standard/standard_defines.stub', 'STREAM_SOCK_STREAM' => 'standard/standard_defines.stub', 'STREAM_URL_STAT_LINK' => 'standard/standard_defines.stub', 'STREAM_URL_STAT_QUIET' => 'standard/standard_defines.stub', 'STREAM_USE_PATH' => 'standard/standard_defines.stub', 'STR_PAD_BOTH' => 'standard/standard_defines.stub', 'STR_PAD_LEFT' => 'standard/standard_defines.stub', 'STR_PAD_RIGHT' => 'standard/standard_defines.stub', 'ST_SET' => 'imap/imap.stub', 'ST_SILENT' => 'imap/imap.stub', 'ST_UID' => 'imap/imap.stub', 'SUHOSIN_PATCH' => 'Core/Core_d.stub', 'SUHOSIN_PATCH_VERSION' => 'Core/Core_d.stub', 'SUNFUNCS_RET_DOUBLE' => 'date/date_d.stub', 'SUNFUNCS_RET_STRING' => 'date/date_d.stub', 'SUNFUNCS_RET_TIMESTAMP' => 'date/date_d.stub', 'SVN_ALL' => 'svn/svn.stub', 'SVN_AUTH_PARAM_CONFIG' => 'svn/svn.stub', 'SVN_AUTH_PARAM_CONFIG_DIR' => 'svn/svn.stub', 'SVN_AUTH_PARAM_DEFAULT_PASSWORD' => 'svn/svn.stub', 'SVN_AUTH_PARAM_DEFAULT_USERNAME' => 'svn/svn.stub', 'SVN_AUTH_PARAM_DONT_STORE_PASSWORDS' => 'svn/svn.stub', 'SVN_AUTH_PARAM_NON_INTERACTIVE' => 'svn/svn.stub', 'SVN_AUTH_PARAM_NO_AUTH_CACHE' => 'svn/svn.stub', 'SVN_AUTH_PARAM_SERVER_GROUP' => 'svn/svn.stub', 'SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO' => 'svn/svn.stub', 'SVN_AUTH_PARAM_SSL_SERVER_FAILURES' => 'svn/svn.stub', 'SVN_DISCOVER_CHANGED_PATHS' => 'svn/svn.stub', 'SVN_FS_CONFIG_FS_TYPE' => 'svn/svn.stub', 'SVN_FS_TYPE_BDB' => 'svn/svn.stub', 'SVN_FS_TYPE_FSFS' => 'svn/svn.stub', 'SVN_NODE_DIR' => 'svn/svn.stub', 'SVN_NODE_FILE' => 'svn/svn.stub', 'SVN_NODE_NONE' => 'svn/svn.stub', 'SVN_NODE_UNKNOWN' => 'svn/svn.stub', 'SVN_NON_RECURSIVE' => 'svn/svn.stub', 'SVN_NO_IGNORE' => 'svn/svn.stub', 'SVN_OMIT_MESSAGES' => 'svn/svn.stub', 'SVN_PROP_REVISION_AUTHOR' => 'svn/svn.stub', 'SVN_PROP_REVISION_DATE' => 'svn/svn.stub', 'SVN_PROP_REVISION_LOG' => 'svn/svn.stub', 'SVN_PROP_REVISION_ORIG_DATE' => 'svn/svn.stub', 'SVN_REVISION_BASE' => 'svn/svn.stub', 'SVN_REVISION_COMMITTED' => 'svn/svn.stub', 'SVN_REVISION_HEAD' => 'svn/svn.stub', 'SVN_REVISION_INITIAL' => 'svn/svn.stub', 'SVN_REVISION_PREV' => 'svn/svn.stub', 'SVN_REVISION_UNSPECIFIED' => 'svn/svn.stub', 'SVN_SHOW_UPDATES' => 'svn/svn.stub', 'SVN_STOP_ON_COPY' => 'svn/svn.stub', 'SVN_WC_SCHEDULE_ADD' => 'svn/svn.stub', 'SVN_WC_SCHEDULE_DELETE' => 'svn/svn.stub', 'SVN_WC_SCHEDULE_NORMAL' => 'svn/svn.stub', 'SVN_WC_SCHEDULE_REPLACE' => 'svn/svn.stub', 'SVN_WC_STATUS_ADDED' => 'svn/svn.stub', 'SVN_WC_STATUS_CONFLICTED' => 'svn/svn.stub', 'SVN_WC_STATUS_DELETED' => 'svn/svn.stub', 'SVN_WC_STATUS_EXTERNAL' => 'svn/svn.stub', 'SVN_WC_STATUS_IGNORED' => 'svn/svn.stub', 'SVN_WC_STATUS_INCOMPLETE' => 'svn/svn.stub', 'SVN_WC_STATUS_MERGED' => 'svn/svn.stub', 'SVN_WC_STATUS_MISSING' => 'svn/svn.stub', 'SVN_WC_STATUS_MODIFIED' => 'svn/svn.stub', 'SVN_WC_STATUS_NONE' => 'svn/svn.stub', 'SVN_WC_STATUS_NORMAL' => 'svn/svn.stub', 'SVN_WC_STATUS_OBSTRUCTED' => 'svn/svn.stub', 'SVN_WC_STATUS_REPLACED' => 'svn/svn.stub', 'SVN_WC_STATUS_UNVERSIONED' => 'svn/svn.stub', 'SWFACTION_DATA' => 'ming/ming.stub', 'SWFACTION_ENTERFRAME' => 'ming/ming.stub', 'SWFACTION_KEYDOWN' => 'ming/ming.stub', 'SWFACTION_KEYUP' => 'ming/ming.stub', 'SWFACTION_MOUSEDOWN' => 'ming/ming.stub', 'SWFACTION_MOUSEMOVE' => 'ming/ming.stub', 'SWFACTION_MOUSEUP' => 'ming/ming.stub', 'SWFACTION_ONLOAD' => 'ming/ming.stub', 'SWFACTION_UNLOAD' => 'ming/ming.stub', 'SWFBUTTON_DOWN' => 'ming/ming.stub', 'SWFBUTTON_DRAGOUT' => 'ming/ming.stub', 'SWFBUTTON_DRAGOVER' => 'ming/ming.stub', 'SWFBUTTON_HIT' => 'ming/ming.stub', 'SWFBUTTON_MOUSEDOWN' => 'ming/ming.stub', 'SWFBUTTON_MOUSEOUT' => 'ming/ming.stub', 'SWFBUTTON_MOUSEOVER' => 'ming/ming.stub', 'SWFBUTTON_MOUSEUP' => 'ming/ming.stub', 'SWFBUTTON_MOUSEUPOUTSIDE' => 'ming/ming.stub', 'SWFBUTTON_OVER' => 'ming/ming.stub', 'SWFBUTTON_UP' => 'ming/ming.stub', 'SWFFILL_CLIPPED_BITMAP' => 'ming/ming.stub', 'SWFFILL_LINEAR_GRADIENT' => 'ming/ming.stub', 'SWFFILL_RADIAL_GRADIENT' => 'ming/ming.stub', 'SWFFILL_TILED_BITMAP' => 'ming/ming.stub', 'SWFTEXTFIELD_ALIGN_CENTER' => 'ming/ming.stub', 'SWFTEXTFIELD_ALIGN_JUSTIFY' => 'ming/ming.stub', 'SWFTEXTFIELD_ALIGN_LEFT' => 'ming/ming.stub', 'SWFTEXTFIELD_ALIGN_RIGHT' => 'ming/ming.stub', 'SWFTEXTFIELD_AUTOSIZE' => 'ming/ming.stub', 'SWFTEXTFIELD_DRAWBOX' => 'ming/ming.stub', 'SWFTEXTFIELD_HASLENGTH' => 'ming/ming.stub', 'SWFTEXTFIELD_HTML' => 'ming/ming.stub', 'SWFTEXTFIELD_MULTILINE' => 'ming/ming.stub', 'SWFTEXTFIELD_NOEDIT' => 'ming/ming.stub', 'SWFTEXTFIELD_NOSELECT' => 'ming/ming.stub', 'SWFTEXTFIELD_PASSWORD' => 'ming/ming.stub', 'SWFTEXTFIELD_USEFONT' => 'ming/ming.stub', 'SWFTEXTFIELD_WORDWRAP' => 'ming/ming.stub', 'SWF_SOUND_11KHZ' => 'ming/ming.stub', 'SWF_SOUND_16BITS' => 'ming/ming.stub', 'SWF_SOUND_22KHZ' => 'ming/ming.stub', 'SWF_SOUND_44KHZ' => 'ming/ming.stub', 'SWF_SOUND_5KHZ' => 'ming/ming.stub', 'SWF_SOUND_8BITS' => 'ming/ming.stub', 'SWF_SOUND_ADPCM_COMPRESSED' => 'ming/ming.stub', 'SWF_SOUND_MONO' => 'ming/ming.stub', 'SWF_SOUND_MP3_COMPRESSED' => 'ming/ming.stub', 'SWF_SOUND_NELLY_COMPRESSED' => 'ming/ming.stub', 'SWF_SOUND_NOT_COMPRESSED' => 'ming/ming.stub', 'SWF_SOUND_NOT_COMPRESSED_LE' => 'ming/ming.stub', 'SWF_SOUND_STEREO' => 'ming/ming.stub', 'SWOOLE_ASYNC' => 'swoole/constants.stub', 'SWOOLE_BASE' => 'swoole/constants.stub', 'SWOOLE_CHANNEL_CANCELED' => 'swoole/constants.stub', 'SWOOLE_CHANNEL_CLOSED' => 'swoole/constants.stub', 'SWOOLE_CHANNEL_OK' => 'swoole/constants.stub', 'SWOOLE_CHANNEL_TIMEOUT' => 'swoole/constants.stub', 'SWOOLE_CORO_END' => 'swoole/constants.stub', 'SWOOLE_CORO_INIT' => 'swoole/constants.stub', 'SWOOLE_CORO_MAX_NUM_LIMIT' => 'swoole/constants.stub', 'SWOOLE_CORO_RUNNING' => 'swoole/constants.stub', 'SWOOLE_CORO_WAITING' => 'swoole/constants.stub', 'SWOOLE_DEBUG' => 'swoole/constants.stub', 'SWOOLE_DEFAULT_MAX_CORO_NUM' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_CO_CONN_LB' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_CO_REQ_LB' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_FDMOD' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_IDLE_WORKER' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_IPMOD' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_RESULT_CLOSE_CONNECTION' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_RESULT_DISCARD_PACKET' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_RESULT_USERFUNC_FALLBACK' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_ROUND' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_STREAM' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_UIDMOD' => 'swoole/constants.stub', 'SWOOLE_DISPATCH_USERFUNC' => 'swoole/constants.stub', 'SWOOLE_DTLS_CLIENT_METHOD' => 'swoole/constants.stub', 'SWOOLE_DTLS_SERVER_METHOD' => 'swoole/constants.stub', 'SWOOLE_ERROR_AIO_BAD_REQUEST' => 'swoole/constants.stub', 'SWOOLE_ERROR_AIO_CANCELED' => 'swoole/constants.stub', 'SWOOLE_ERROR_AIO_TIMEOUT' => 'swoole/constants.stub', 'SWOOLE_ERROR_BAD_IPV6_ADDRESS' => 'swoole/constants.stub', 'SWOOLE_ERROR_CLIENT_NO_CONNECTION' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_BLOCK_OBJECT_LOCKED' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_BLOCK_OBJECT_WAITING' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_CANCELED' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_CANNOT_CANCEL' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_DISABLED_MULTI_THREAD' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_GETCONTEXT_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_HAS_BEEN_BOUND' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_HAS_BEEN_DISCARDED' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_IOCPINIT_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_MAKECONTEXT_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_MUTEX_DOUBLE_UNLOCK' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_NOT_EXISTS' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_OUT_OF_COROUTINE' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_PROTECT_STACK_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_STD_THREAD_LINK_ERROR' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_SWAPCONTEXT_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_TIMEDOUT' => 'swoole/constants.stub', 'SWOOLE_ERROR_CO_YIELD_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_DATA_LENGTH_TOO_LARGE' => 'swoole/constants.stub', 'SWOOLE_ERROR_DNSLOOKUP_DUPLICATE_REQUEST' => 'swoole/constants.stub', 'SWOOLE_ERROR_DNSLOOKUP_NO_SERVER' => 'swoole/constants.stub', 'SWOOLE_ERROR_DNSLOOKUP_RESOLVE_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT' => 'swoole/constants.stub', 'SWOOLE_ERROR_DNSLOOKUP_UNSUPPORTED' => 'swoole/constants.stub', 'SWOOLE_ERROR_EVENT_SOCKET_REMOVED' => 'swoole/constants.stub', 'SWOOLE_ERROR_FILE_EMPTY' => 'swoole/constants.stub', 'SWOOLE_ERROR_FILE_NOT_EXIST' => 'swoole/constants.stub', 'SWOOLE_ERROR_FILE_TOO_LARGE' => 'swoole/constants.stub', 'SWOOLE_ERROR_HTTP2_STREAM_ID_TOO_BIG' => 'swoole/constants.stub', 'SWOOLE_ERROR_HTTP2_STREAM_IGNORE' => 'swoole/constants.stub', 'SWOOLE_ERROR_HTTP2_STREAM_NOT_FOUND' => 'swoole/constants.stub', 'SWOOLE_ERROR_HTTP2_STREAM_NO_HEADER' => 'swoole/constants.stub', 'SWOOLE_ERROR_HTTP_INVALID_PROTOCOL' => 'swoole/constants.stub', 'SWOOLE_ERROR_HTTP_PROXY_BAD_RESPONSE' => 'swoole/constants.stub', 'SWOOLE_ERROR_HTTP_PROXY_HANDSHAKE_ERROR' => 'swoole/constants.stub', 'SWOOLE_ERROR_HTTP_PROXY_HANDSHAKE_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_INVALID_PARAMS' => 'swoole/constants.stub', 'SWOOLE_ERROR_MALLOC_FAIL' => 'swoole/constants.stub', 'SWOOLE_ERROR_NAME_TOO_LONG' => 'swoole/constants.stub', 'SWOOLE_ERROR_OPERATION_NOT_SUPPORT' => 'swoole/constants.stub', 'SWOOLE_ERROR_OUTPUT_BUFFER_OVERFLOW' => 'swoole/constants.stub', 'SWOOLE_ERROR_OUTPUT_SEND_YIELD' => 'swoole/constants.stub', 'SWOOLE_ERROR_PACKAGE_LENGTH_NOT_FOUND' => 'swoole/constants.stub', 'SWOOLE_ERROR_PACKAGE_LENGTH_TOO_LARGE' => 'swoole/constants.stub', 'SWOOLE_ERROR_PACKAGE_MALFORMED_DATA' => 'swoole/constants.stub', 'SWOOLE_ERROR_PHP_FATAL_ERROR' => 'swoole/constants.stub', 'SWOOLE_ERROR_PROTOCOL_ERROR' => 'swoole/constants.stub', 'SWOOLE_ERROR_QUEUE_FULL' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_CONNECT_FAIL' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_INVALID_COMMAND' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_INVALID_LISTEN_PORT' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_INVALID_REQUEST' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_MUST_CREATED_BEFORE_CLIENT' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_NO_IDLE_WORKER' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_ONLY_START_ONE' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_PIPE_BUFFER_FULL' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_SEND_IN_MASTER' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_TOO_MANY_LISTEN_PORT' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_TOO_MANY_SOCKET' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_WORKER_EXIT_TIMEOUT' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_WORKER_TERMINATED' => 'swoole/constants.stub', 'SWOOLE_ERROR_SERVER_WORKER_UNPROCESSED_DATA' => 'swoole/constants.stub', 'SWOOLE_ERROR_SESSION_CLOSED' => 'swoole/constants.stub', 'SWOOLE_ERROR_SESSION_CLOSED_BY_CLIENT' => 'swoole/constants.stub', 'SWOOLE_ERROR_SESSION_CLOSED_BY_SERVER' => 'swoole/constants.stub', 'SWOOLE_ERROR_SESSION_CLOSING' => 'swoole/constants.stub', 'SWOOLE_ERROR_SESSION_DISCARD_DATA' => 'swoole/constants.stub', 'SWOOLE_ERROR_SESSION_DISCARD_TIMEOUT_DATA' => 'swoole/constants.stub', 'SWOOLE_ERROR_SESSION_INVALID_ID' => 'swoole/constants.stub', 'SWOOLE_ERROR_SESSION_NOT_EXIST' => 'swoole/constants.stub', 'SWOOLE_ERROR_SOCKET_CLOSED' => 'swoole/constants.stub', 'SWOOLE_ERROR_SOCKET_POLL_TIMEOUT' => 'swoole/constants.stub', 'SWOOLE_ERROR_SOCKS5_AUTH_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_SOCKS5_HANDSHAKE_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_SOCKS5_SERVER_ERROR' => 'swoole/constants.stub', 'SWOOLE_ERROR_SOCKS5_UNSUPPORT_METHOD' => 'swoole/constants.stub', 'SWOOLE_ERROR_SOCKS5_UNSUPPORT_VERSION' => 'swoole/constants.stub', 'SWOOLE_ERROR_SSL_BAD_CLIENT' => 'swoole/constants.stub', 'SWOOLE_ERROR_SSL_BAD_PROTOCOL' => 'swoole/constants.stub', 'SWOOLE_ERROR_SSL_CANNOT_USE_SENFILE' => 'swoole/constants.stub', 'SWOOLE_ERROR_SSL_EMPTY_PEER_CERTIFICATE' => 'swoole/constants.stub', 'SWOOLE_ERROR_SSL_HANDSHAKE_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_SSL_NOT_READY' => 'swoole/constants.stub', 'SWOOLE_ERROR_SSL_RESET' => 'swoole/constants.stub', 'SWOOLE_ERROR_SSL_VERIFY_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_SYSTEM_CALL_FAIL' => 'swoole/constants.stub', 'SWOOLE_ERROR_TASK_DISPATCH_FAIL' => 'swoole/constants.stub', 'SWOOLE_ERROR_TASK_PACKAGE_TOO_BIG' => 'swoole/constants.stub', 'SWOOLE_ERROR_TASK_TIMEOUT' => 'swoole/constants.stub', 'SWOOLE_ERROR_UNREGISTERED_SIGNAL' => 'swoole/constants.stub', 'SWOOLE_ERROR_WEBSOCKET_BAD_CLIENT' => 'swoole/constants.stub', 'SWOOLE_ERROR_WEBSOCKET_BAD_OPCODE' => 'swoole/constants.stub', 'SWOOLE_ERROR_WEBSOCKET_HANDSHAKE_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_WEBSOCKET_INCOMPLETE_PACKET' => 'swoole/constants.stub', 'SWOOLE_ERROR_WEBSOCKET_PACK_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_WEBSOCKET_UNCONNECTED' => 'swoole/constants.stub', 'SWOOLE_ERROR_WEBSOCKET_UNPACK_FAILED' => 'swoole/constants.stub', 'SWOOLE_ERROR_WRONG_OPERATION' => 'swoole/constants.stub', 'SWOOLE_EVENT_READ' => 'swoole/constants.stub', 'SWOOLE_EVENT_WRITE' => 'swoole/constants.stub', 'SWOOLE_EXIT_IN_COROUTINE' => 'swoole/constants.stub', 'SWOOLE_EXIT_IN_SERVER' => 'swoole/constants.stub', 'SWOOLE_EXTRA_VERSION' => 'swoole/constants.stub', 'SWOOLE_FILELOCK' => 'swoole/constants.stub', 'SWOOLE_HAVE_BROTLI' => 'swoole/constants.stub', 'SWOOLE_HAVE_COMPRESSION' => 'swoole/constants.stub', 'SWOOLE_HAVE_ZLIB' => 'swoole/constants.stub', 'SWOOLE_HOOK_ALL' => 'swoole/constants.stub', 'SWOOLE_HOOK_BLOCKING_FUNCTION' => 'swoole/constants.stub', 'SWOOLE_HOOK_CURL' => 'swoole/constants.stub', 'SWOOLE_HOOK_FILE' => 'swoole/constants.stub', 'SWOOLE_HOOK_NATIVE_CURL' => 'swoole/constants.stub', 'SWOOLE_HOOK_PROC' => 'swoole/constants.stub', 'SWOOLE_HOOK_SLEEP' => 'swoole/constants.stub', 'SWOOLE_HOOK_SOCKETS' => 'swoole/constants.stub', 'SWOOLE_HOOK_SSL' => 'swoole/constants.stub', 'SWOOLE_HOOK_STDIO' => 'swoole/constants.stub', 'SWOOLE_HOOK_STREAM_FUNCTION' => 'swoole/constants.stub', 'SWOOLE_HOOK_STREAM_SELECT' => 'swoole/constants.stub', 'SWOOLE_HOOK_TCP' => 'swoole/constants.stub', 'SWOOLE_HOOK_TLS' => 'swoole/constants.stub', 'SWOOLE_HOOK_UDG' => 'swoole/constants.stub', 'SWOOLE_HOOK_UDP' => 'swoole/constants.stub', 'SWOOLE_HOOK_UNIX' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_CANCEL' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_COMPRESSION_ERROR' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_CONNECT_ERROR' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_ENHANCE_YOUR_CALM' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_FLOW_CONTROL_ERROR' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_FRAME_SIZE_ERROR' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_INADEQUATE_SECURITY' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_INTERNAL_ERROR' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_NO_ERROR' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_PROTOCOL_ERROR' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_REFUSED_STREAM' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_SETTINGS_TIMEOUT' => 'swoole/constants.stub', 'SWOOLE_HTTP2_ERROR_STREAM_CLOSED' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_CONTINUATION' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_DATA' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_GOAWAY' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_HEADERS' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_PING' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_PRIORITY' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_PUSH_PROMISE' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_RST_STREAM' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_SETTINGS' => 'swoole/constants.stub', 'SWOOLE_HTTP2_TYPE_WINDOW_UPDATE' => 'swoole/constants.stub', 'SWOOLE_HTTP_CLIENT_ESTATUS_CONNECT_FAILED' => 'swoole/constants.stub', 'SWOOLE_HTTP_CLIENT_ESTATUS_REQUEST_TIMEOUT' => 'swoole/constants.stub', 'SWOOLE_HTTP_CLIENT_ESTATUS_SEND_FAILED' => 'swoole/constants.stub', 'SWOOLE_HTTP_CLIENT_ESTATUS_SERVER_RESET' => 'swoole/constants.stub', 'SWOOLE_IOV_MAX' => 'swoole/constants.stub', 'SWOOLE_IPC_MSGQUEUE' => 'swoole/constants.stub', 'SWOOLE_IPC_NONE' => 'swoole/constants.stub', 'SWOOLE_IPC_PREEMPTIVE' => 'swoole/constants.stub', 'SWOOLE_IPC_SOCKET' => 'swoole/constants.stub', 'SWOOLE_IPC_UNIXSOCK' => 'swoole/constants.stub', 'SWOOLE_IPC_UNSOCK' => 'swoole/constants.stub', 'SWOOLE_KEEP' => 'swoole/constants.stub', 'SWOOLE_LOG_DEBUG' => 'swoole/constants.stub', 'SWOOLE_LOG_ERROR' => 'swoole/constants.stub', 'SWOOLE_LOG_INFO' => 'swoole/constants.stub', 'SWOOLE_LOG_NONE' => 'swoole/constants.stub', 'SWOOLE_LOG_NOTICE' => 'swoole/constants.stub', 'SWOOLE_LOG_ROTATION_DAILY' => 'swoole/constants.stub', 'SWOOLE_LOG_ROTATION_EVERY_MINUTE' => 'swoole/constants.stub', 'SWOOLE_LOG_ROTATION_HOURLY' => 'swoole/constants.stub', 'SWOOLE_LOG_ROTATION_MONTHLY' => 'swoole/constants.stub', 'SWOOLE_LOG_ROTATION_SINGLE' => 'swoole/constants.stub', 'SWOOLE_LOG_TRACE' => 'swoole/constants.stub', 'SWOOLE_LOG_WARNING' => 'swoole/constants.stub', 'SWOOLE_MAJOR_VERSION' => 'swoole/constants.stub', 'SWOOLE_MINOR_VERSION' => 'swoole/constants.stub', 'SWOOLE_MUTEX' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_CANT_FIND_CHARSET' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_COMMANDS_OUT_OF_SYNC' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_CONNECTION_ERROR' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_INVALID_BUFFER_USE' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_INVALID_PARAMETER_NO' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_MALFORMED_PACKET' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_NOT_IMPLEMENTED' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_NO_PREPARE_STMT' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_OUT_OF_MEMORY' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_PARAMS_NOT_BOUND' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_SERVER_GONE_ERROR' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_SERVER_LOST' => 'swoole/constants.stub', 'SWOOLE_MYSQLND_CR_UNKNOWN_ERROR' => 'swoole/constants.stub', 'SWOOLE_PROCESS' => 'swoole/constants.stub', 'SWOOLE_REDIS_ERR_ALLOC' => 'swoole/constants.stub', 'SWOOLE_REDIS_ERR_CLOSED' => 'swoole/constants.stub', 'SWOOLE_REDIS_ERR_EOF' => 'swoole/constants.stub', 'SWOOLE_REDIS_ERR_IO' => 'swoole/constants.stub', 'SWOOLE_REDIS_ERR_NOAUTH' => 'swoole/constants.stub', 'SWOOLE_REDIS_ERR_OOM' => 'swoole/constants.stub', 'SWOOLE_REDIS_ERR_OTHER' => 'swoole/constants.stub', 'SWOOLE_REDIS_ERR_PROTOCOL' => 'swoole/constants.stub', 'SWOOLE_REDIS_MODE_MULTI' => 'swoole/constants.stub', 'SWOOLE_REDIS_MODE_PIPELINE' => 'swoole/constants.stub', 'SWOOLE_REDIS_TYPE_HASH' => 'swoole/constants.stub', 'SWOOLE_REDIS_TYPE_LIST' => 'swoole/constants.stub', 'SWOOLE_REDIS_TYPE_NOT_FOUND' => 'swoole/constants.stub', 'SWOOLE_REDIS_TYPE_SET' => 'swoole/constants.stub', 'SWOOLE_REDIS_TYPE_STRING' => 'swoole/constants.stub', 'SWOOLE_REDIS_TYPE_ZSET' => 'swoole/constants.stub', 'SWOOLE_RELEASE_VERSION' => 'swoole/constants.stub', 'SWOOLE_RWLOCK' => 'swoole/constants.stub', 'SWOOLE_SEM' => 'swoole/constants.stub', 'SWOOLE_SERVER_COMMAND_EVENT_WORKER' => 'swoole/constants.stub', 'SWOOLE_SERVER_COMMAND_MANAGER' => 'swoole/constants.stub', 'SWOOLE_SERVER_COMMAND_MASTER' => 'swoole/constants.stub', 'SWOOLE_SERVER_COMMAND_REACTOR_THREAD' => 'swoole/constants.stub', 'SWOOLE_SERVER_COMMAND_TASK_WORKER' => 'swoole/constants.stub', 'SWOOLE_SERVER_COMMAND_WORKER' => 'swoole/constants.stub', 'SWOOLE_SOCK_ASYNC' => 'swoole/constants.stub', 'SWOOLE_SOCK_SYNC' => 'swoole/constants.stub', 'SWOOLE_SOCK_TCP' => 'swoole/constants.stub', 'SWOOLE_SOCK_TCP6' => 'swoole/constants.stub', 'SWOOLE_SOCK_UDP' => 'swoole/constants.stub', 'SWOOLE_SOCK_UDP6' => 'swoole/constants.stub', 'SWOOLE_SOCK_UNIX_DGRAM' => 'swoole/constants.stub', 'SWOOLE_SOCK_UNIX_STREAM' => 'swoole/constants.stub', 'SWOOLE_SPINLOCK' => 'swoole/constants.stub', 'SWOOLE_SSL' => 'swoole/constants.stub', 'SWOOLE_SSL_DTLS' => 'swoole/constants.stub', 'SWOOLE_SSL_SSLv2' => 'swoole/constants.stub', 'SWOOLE_SSL_TLSv1' => 'swoole/constants.stub', 'SWOOLE_SSL_TLSv1_1' => 'swoole/constants.stub', 'SWOOLE_SSL_TLSv1_2' => 'swoole/constants.stub', 'SWOOLE_SSL_TLSv1_3' => 'swoole/constants.stub', 'SWOOLE_SSLv23_CLIENT_METHOD' => 'swoole/constants.stub', 'SWOOLE_SSLv23_METHOD' => 'swoole/constants.stub', 'SWOOLE_SSLv23_SERVER_METHOD' => 'swoole/constants.stub', 'SWOOLE_SSLv3_CLIENT_METHOD' => 'swoole/constants.stub', 'SWOOLE_SSLv3_METHOD' => 'swoole/constants.stub', 'SWOOLE_SSLv3_SERVER_METHOD' => 'swoole/constants.stub', 'SWOOLE_STRERROR_DNS' => 'swoole/constants.stub', 'SWOOLE_STRERROR_GAI' => 'swoole/constants.stub', 'SWOOLE_STRERROR_SWOOLE' => 'swoole/constants.stub', 'SWOOLE_STRERROR_SYSTEM' => 'swoole/constants.stub', 'SWOOLE_SYNC' => 'swoole/constants.stub', 'SWOOLE_TASK_CALLBACK' => 'swoole/constants.stub', 'SWOOLE_TASK_COROUTINE' => 'swoole/constants.stub', 'SWOOLE_TASK_NONBLOCK' => 'swoole/constants.stub', 'SWOOLE_TASK_NOREPLY' => 'swoole/constants.stub', 'SWOOLE_TASK_PEEK' => 'swoole/constants.stub', 'SWOOLE_TASK_SERIALIZE' => 'swoole/constants.stub', 'SWOOLE_TASK_TMPFILE' => 'swoole/constants.stub', 'SWOOLE_TASK_WAITALL' => 'swoole/constants.stub', 'SWOOLE_TCP' => 'swoole/constants.stub', 'SWOOLE_TCP6' => 'swoole/constants.stub', 'SWOOLE_TIMER_MAX_MS' => 'swoole/constants.stub', 'SWOOLE_TIMER_MAX_SEC' => 'swoole/constants.stub', 'SWOOLE_TIMER_MIN_MS' => 'swoole/constants.stub', 'SWOOLE_TIMER_MIN_SEC' => 'swoole/constants.stub', 'SWOOLE_TLS_CLIENT_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLS_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLS_SERVER_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLSv1_1_CLIENT_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLSv1_1_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLSv1_1_SERVER_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLSv1_2_CLIENT_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLSv1_2_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLSv1_2_SERVER_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLSv1_CLIENT_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLSv1_METHOD' => 'swoole/constants.stub', 'SWOOLE_TLSv1_SERVER_METHOD' => 'swoole/constants.stub', 'SWOOLE_TRACE_AIO' => 'swoole/constants.stub', 'SWOOLE_TRACE_ALL' => 'swoole/constants.stub', 'SWOOLE_TRACE_BUFFER' => 'swoole/constants.stub', 'SWOOLE_TRACE_CARES' => 'swoole/constants.stub', 'SWOOLE_TRACE_CHANNEL' => 'swoole/constants.stub', 'SWOOLE_TRACE_CLIENT' => 'swoole/constants.stub', 'SWOOLE_TRACE_CLOSE' => 'swoole/constants.stub', 'SWOOLE_TRACE_CONN' => 'swoole/constants.stub', 'SWOOLE_TRACE_CONTEXT' => 'swoole/constants.stub', 'SWOOLE_TRACE_COROUTINE' => 'swoole/constants.stub', 'SWOOLE_TRACE_CO_CURL' => 'swoole/constants.stub', 'SWOOLE_TRACE_CO_HTTP_SERVER' => 'swoole/constants.stub', 'SWOOLE_TRACE_EOF_PROTOCOL' => 'swoole/constants.stub', 'SWOOLE_TRACE_EVENT' => 'swoole/constants.stub', 'SWOOLE_TRACE_HTTP' => 'swoole/constants.stub', 'SWOOLE_TRACE_HTTP2' => 'swoole/constants.stub', 'SWOOLE_TRACE_HTTP_CLIENT' => 'swoole/constants.stub', 'SWOOLE_TRACE_LENGTH_PROTOCOL' => 'swoole/constants.stub', 'SWOOLE_TRACE_MEMORY' => 'swoole/constants.stub', 'SWOOLE_TRACE_MYSQL_CLIENT' => 'swoole/constants.stub', 'SWOOLE_TRACE_NORMAL' => 'swoole/constants.stub', 'SWOOLE_TRACE_PHP' => 'swoole/constants.stub', 'SWOOLE_TRACE_REACTOR' => 'swoole/constants.stub', 'SWOOLE_TRACE_REDIS_CLIENT' => 'swoole/constants.stub', 'SWOOLE_TRACE_SERVER' => 'swoole/constants.stub', 'SWOOLE_TRACE_SOCKET' => 'swoole/constants.stub', 'SWOOLE_TRACE_SSL' => 'swoole/constants.stub', 'SWOOLE_TRACE_TABLE' => 'swoole/constants.stub', 'SWOOLE_TRACE_TIMER' => 'swoole/constants.stub', 'SWOOLE_TRACE_WEBSOCKET' => 'swoole/constants.stub', 'SWOOLE_TRACE_WORKER' => 'swoole/constants.stub', 'SWOOLE_UDP' => 'swoole/constants.stub', 'SWOOLE_UDP6' => 'swoole/constants.stub', 'SWOOLE_UNIX_DGRAM' => 'swoole/constants.stub', 'SWOOLE_UNIX_STREAM' => 'swoole/constants.stub', 'SWOOLE_USE_HTTP2' => 'swoole/constants.stub', 'SWOOLE_USE_SHORTNAME' => 'swoole/constants.stub', 'SWOOLE_VERSION' => 'swoole/constants.stub', 'SWOOLE_VERSION_ID' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_ABNORMAL' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_DATA_ERROR' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_EXTENSION_MISSING' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_GOING_AWAY' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_MESSAGE_ERROR' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_MESSAGE_TOO_BIG' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_NORMAL' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_POLICY_ERROR' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_PROTOCOL_ERROR' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_SERVER_ERROR' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_STATUS_ERROR' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_CLOSE_TLS' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_FLAG_COMPRESS' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_FLAG_FIN' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_FLAG_MASK' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_FLAG_RSV1' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_FLAG_RSV2' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_FLAG_RSV3' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_OPCODE_BINARY' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_OPCODE_CLOSE' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_OPCODE_CONTINUATION' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_OPCODE_PING' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_OPCODE_PONG' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_OPCODE_TEXT' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_STATUS_ACTIVE' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_STATUS_CLOSING' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_STATUS_CONNECTION' => 'swoole/constants.stub', 'SWOOLE_WEBSOCKET_STATUS_HANDSHAKE' => 'swoole/constants.stub', 'SWOOLE_WORKER_BUSY' => 'swoole/constants.stub', 'SWOOLE_WORKER_EXIT' => 'swoole/constants.stub', 'SWOOLE_WORKER_IDLE' => 'swoole/constants.stub', 'S_ALL' => 'Core/Core_d.stub', 'S_EXECUTOR' => 'Core/Core_d.stub', 'S_FILES' => 'Core/Core_d.stub', 'S_INCLUDE' => 'Core/Core_d.stub', 'S_INTERNAL' => 'Core/Core_d.stub', 'S_IRGRP' => 'dio/dio_d.stub', 'S_IROTH' => 'dio/dio_d.stub', 'S_IRUSR' => 'dio/dio_d.stub', 'S_IRWXG' => 'dio/dio_d.stub', 'S_IRWXO' => 'dio/dio_d.stub', 'S_IRWXU' => 'dio/dio_d.stub', 'S_IWGRP' => 'dio/dio_d.stub', 'S_IWOTH' => 'dio/dio_d.stub', 'S_IWUSR' => 'dio/dio_d.stub', 'S_IXGRP' => 'dio/dio_d.stub', 'S_IXOTH' => 'dio/dio_d.stub', 'S_IXUSR' => 'dio/dio_d.stub', 'S_MAIL' => 'Core/Core_d.stub', 'S_MEMORY' => 'Core/Core_d.stub', 'S_MISC' => 'Core/Core_d.stub', 'S_SESSION' => 'Core/Core_d.stub', 'S_SQL' => 'Core/Core_d.stub', 'S_VARS' => 'Core/Core_d.stub', 'ScrollBar' => 'winbinder/winbinder.stub', 'Slider' => 'winbinder/winbinder.stub', 'Sodium\\CRYPTO_AEAD_AES256GCM_ABYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_AEAD_AES256GCM_KEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_AEAD_AES256GCM_NPUBBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_AEAD_AES256GCM_NSECBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_AEAD_CHACHA20POLY1305_ABYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_AUTH_BYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_AUTH_KEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_BOX_KEYPAIRBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_BOX_MACBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_BOX_NONCEBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_BOX_PUBLICKEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_BOX_SEALBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_BOX_SECRETKEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_BOX_SEEDBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_GENERICHASH_BYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_GENERICHASH_BYTES_MAX' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_GENERICHASH_BYTES_MIN' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_GENERICHASH_KEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_GENERICHASH_KEYBYTES_MAX' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_GENERICHASH_KEYBYTES_MIN' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_KX_BYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_KX_PUBLICKEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_KX_SECRETKEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_MEMLIMIT_MODERATE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_MEMLIMIT_SENSITIVE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_OPSLIMIT_MODERATE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_OPSLIMIT_SENSITIVE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SCALARMULT_BYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SCALARMULT_SCALARBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SECRETBOX_KEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SECRETBOX_MACBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SECRETBOX_NONCEBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SHORTHASH_BYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SHORTHASH_KEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SIGN_BYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SIGN_KEYPAIRBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SIGN_PUBLICKEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SIGN_SECRETKEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_SIGN_SEEDBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_STREAM_KEYBYTES' => 'libsodium/libsodium.stub', 'Sodium\\CRYPTO_STREAM_NONCEBYTES' => 'libsodium/libsodium.stub', 'Spinner' => 'winbinder/winbinder.stub', 'StatusBar' => 'winbinder/winbinder.stub', 'TCP_CONGESTION' => 'sockets/sockets.stub', 'TCP_DEFER_ACCEPT' => 'sockets/sockets.stub', 'TCP_KEEPCNT' => 'sockets/sockets.stub', 'TCP_KEEPIDLE' => 'sockets/sockets.stub', 'TCP_KEEPINTVL' => 'sockets/sockets.stub', 'TCP_NODELAY' => 'sockets/sockets.stub', 'TCP_NOTSENT_LOWAT' => 'sockets/sockets.stub', 'TCP_QUICKACK' => 'sockets/sockets.stub', 'TCP_REPAIR' => 'sockets/sockets.stub', 'TCP_SYNCNT' => 'sockets/sockets.stub', 'THOUSANDS_SEP' => 'standard/standard_defines.stub', 'THOUSEP' => 'standard/standard_defines.stub', 'TIDY_NODETYPE_ASP' => 'tidy/tidy.stub', 'TIDY_NODETYPE_CDATA' => 'tidy/tidy.stub', 'TIDY_NODETYPE_COMMENT' => 'tidy/tidy.stub', 'TIDY_NODETYPE_DOCTYPE' => 'tidy/tidy.stub', 'TIDY_NODETYPE_END' => 'tidy/tidy.stub', 'TIDY_NODETYPE_JSTE' => 'tidy/tidy.stub', 'TIDY_NODETYPE_PHP' => 'tidy/tidy.stub', 'TIDY_NODETYPE_PROCINS' => 'tidy/tidy.stub', 'TIDY_NODETYPE_ROOT' => 'tidy/tidy.stub', 'TIDY_NODETYPE_SECTION' => 'tidy/tidy.stub', 'TIDY_NODETYPE_START' => 'tidy/tidy.stub', 'TIDY_NODETYPE_STARTEND' => 'tidy/tidy.stub', 'TIDY_NODETYPE_TEXT' => 'tidy/tidy.stub', 'TIDY_NODETYPE_XMLDECL' => 'tidy/tidy.stub', 'TIDY_TAG_A' => 'tidy/tidy.stub', 'TIDY_TAG_ABBR' => 'tidy/tidy.stub', 'TIDY_TAG_ACRONYM' => 'tidy/tidy.stub', 'TIDY_TAG_ADDRESS' => 'tidy/tidy.stub', 'TIDY_TAG_ALIGN' => 'tidy/tidy.stub', 'TIDY_TAG_APPLET' => 'tidy/tidy.stub', 'TIDY_TAG_AREA' => 'tidy/tidy.stub', 'TIDY_TAG_ARTICLE' => 'tidy/tidy.stub', 'TIDY_TAG_ASIDE' => 'tidy/tidy.stub', 'TIDY_TAG_AUDIO' => 'tidy/tidy.stub', 'TIDY_TAG_B' => 'tidy/tidy.stub', 'TIDY_TAG_BASE' => 'tidy/tidy.stub', 'TIDY_TAG_BASEFONT' => 'tidy/tidy.stub', 'TIDY_TAG_BDI' => 'tidy/tidy.stub', 'TIDY_TAG_BDO' => 'tidy/tidy.stub', 'TIDY_TAG_BGSOUND' => 'tidy/tidy.stub', 'TIDY_TAG_BIG' => 'tidy/tidy.stub', 'TIDY_TAG_BLINK' => 'tidy/tidy.stub', 'TIDY_TAG_BLOCKQUOTE' => 'tidy/tidy.stub', 'TIDY_TAG_BODY' => 'tidy/tidy.stub', 'TIDY_TAG_BR' => 'tidy/tidy.stub', 'TIDY_TAG_BUTTON' => 'tidy/tidy.stub', 'TIDY_TAG_CANVAS' => 'tidy/tidy.stub', 'TIDY_TAG_CAPTION' => 'tidy/tidy.stub', 'TIDY_TAG_CENTER' => 'tidy/tidy.stub', 'TIDY_TAG_CITE' => 'tidy/tidy.stub', 'TIDY_TAG_CODE' => 'tidy/tidy.stub', 'TIDY_TAG_COL' => 'tidy/tidy.stub', 'TIDY_TAG_COLGROUP' => 'tidy/tidy.stub', 'TIDY_TAG_COMMAND' => 'tidy/tidy.stub', 'TIDY_TAG_COMMENT' => 'tidy/tidy.stub', 'TIDY_TAG_DATALIST' => 'tidy/tidy.stub', 'TIDY_TAG_DD' => 'tidy/tidy.stub', 'TIDY_TAG_DEL' => 'tidy/tidy.stub', 'TIDY_TAG_DETAILS' => 'tidy/tidy.stub', 'TIDY_TAG_DFN' => 'tidy/tidy.stub', 'TIDY_TAG_DIALOG' => 'tidy/tidy.stub', 'TIDY_TAG_DIR' => 'tidy/tidy.stub', 'TIDY_TAG_DIV' => 'tidy/tidy.stub', 'TIDY_TAG_DL' => 'tidy/tidy.stub', 'TIDY_TAG_DT' => 'tidy/tidy.stub', 'TIDY_TAG_EM' => 'tidy/tidy.stub', 'TIDY_TAG_EMBED' => 'tidy/tidy.stub', 'TIDY_TAG_FIELDSET' => 'tidy/tidy.stub', 'TIDY_TAG_FIGCAPTION' => 'tidy/tidy.stub', 'TIDY_TAG_FIGURE' => 'tidy/tidy.stub', 'TIDY_TAG_FONT' => 'tidy/tidy.stub', 'TIDY_TAG_FOOTER' => 'tidy/tidy.stub', 'TIDY_TAG_FORM' => 'tidy/tidy.stub', 'TIDY_TAG_FRAME' => 'tidy/tidy.stub', 'TIDY_TAG_FRAMESET' => 'tidy/tidy.stub', 'TIDY_TAG_H1' => 'tidy/tidy.stub', 'TIDY_TAG_H2' => 'tidy/tidy.stub', 'TIDY_TAG_H3' => 'tidy/tidy.stub', 'TIDY_TAG_H4' => 'tidy/tidy.stub', 'TIDY_TAG_H5' => 'tidy/tidy.stub', 'TIDY_TAG_H6' => 'tidy/tidy.stub', 'TIDY_TAG_HEAD' => 'tidy/tidy.stub', 'TIDY_TAG_HEADER' => 'tidy/tidy.stub', 'TIDY_TAG_HGROUP' => 'tidy/tidy.stub', 'TIDY_TAG_HR' => 'tidy/tidy.stub', 'TIDY_TAG_HTML' => 'tidy/tidy.stub', 'TIDY_TAG_I' => 'tidy/tidy.stub', 'TIDY_TAG_IFRAME' => 'tidy/tidy.stub', 'TIDY_TAG_ILAYER' => 'tidy/tidy.stub', 'TIDY_TAG_IMG' => 'tidy/tidy.stub', 'TIDY_TAG_INPUT' => 'tidy/tidy.stub', 'TIDY_TAG_INS' => 'tidy/tidy.stub', 'TIDY_TAG_ISINDEX' => 'tidy/tidy.stub', 'TIDY_TAG_KBD' => 'tidy/tidy.stub', 'TIDY_TAG_KEYGEN' => 'tidy/tidy.stub', 'TIDY_TAG_LABEL' => 'tidy/tidy.stub', 'TIDY_TAG_LAYER' => 'tidy/tidy.stub', 'TIDY_TAG_LEGEND' => 'tidy/tidy.stub', 'TIDY_TAG_LI' => 'tidy/tidy.stub', 'TIDY_TAG_LINK' => 'tidy/tidy.stub', 'TIDY_TAG_LISTING' => 'tidy/tidy.stub', 'TIDY_TAG_MAIN' => 'tidy/tidy.stub', 'TIDY_TAG_MAP' => 'tidy/tidy.stub', 'TIDY_TAG_MARK' => 'tidy/tidy.stub', 'TIDY_TAG_MARQUEE' => 'tidy/tidy.stub', 'TIDY_TAG_MENU' => 'tidy/tidy.stub', 'TIDY_TAG_MENUITEM' => 'tidy/tidy.stub', 'TIDY_TAG_META' => 'tidy/tidy.stub', 'TIDY_TAG_METER' => 'tidy/tidy.stub', 'TIDY_TAG_MULTICOL' => 'tidy/tidy.stub', 'TIDY_TAG_NAV' => 'tidy/tidy.stub', 'TIDY_TAG_NOBR' => 'tidy/tidy.stub', 'TIDY_TAG_NOEMBED' => 'tidy/tidy.stub', 'TIDY_TAG_NOFRAMES' => 'tidy/tidy.stub', 'TIDY_TAG_NOLAYER' => 'tidy/tidy.stub', 'TIDY_TAG_NOSAVE' => 'tidy/tidy.stub', 'TIDY_TAG_NOSCRIPT' => 'tidy/tidy.stub', 'TIDY_TAG_OBJECT' => 'tidy/tidy.stub', 'TIDY_TAG_OL' => 'tidy/tidy.stub', 'TIDY_TAG_OPTGROUP' => 'tidy/tidy.stub', 'TIDY_TAG_OPTION' => 'tidy/tidy.stub', 'TIDY_TAG_OUTPUT' => 'tidy/tidy.stub', 'TIDY_TAG_P' => 'tidy/tidy.stub', 'TIDY_TAG_PARAM' => 'tidy/tidy.stub', 'TIDY_TAG_PLAINTEXT' => 'tidy/tidy.stub', 'TIDY_TAG_PRE' => 'tidy/tidy.stub', 'TIDY_TAG_PROGRESS' => 'tidy/tidy.stub', 'TIDY_TAG_Q' => 'tidy/tidy.stub', 'TIDY_TAG_RB' => 'tidy/tidy.stub', 'TIDY_TAG_RBC' => 'tidy/tidy.stub', 'TIDY_TAG_RP' => 'tidy/tidy.stub', 'TIDY_TAG_RT' => 'tidy/tidy.stub', 'TIDY_TAG_RTC' => 'tidy/tidy.stub', 'TIDY_TAG_RUBY' => 'tidy/tidy.stub', 'TIDY_TAG_S' => 'tidy/tidy.stub', 'TIDY_TAG_SAMP' => 'tidy/tidy.stub', 'TIDY_TAG_SCRIPT' => 'tidy/tidy.stub', 'TIDY_TAG_SECTION' => 'tidy/tidy.stub', 'TIDY_TAG_SELECT' => 'tidy/tidy.stub', 'TIDY_TAG_SERVER' => 'tidy/tidy.stub', 'TIDY_TAG_SERVLET' => 'tidy/tidy.stub', 'TIDY_TAG_SMALL' => 'tidy/tidy.stub', 'TIDY_TAG_SOURCE' => 'tidy/tidy.stub', 'TIDY_TAG_SPACER' => 'tidy/tidy.stub', 'TIDY_TAG_SPAN' => 'tidy/tidy.stub', 'TIDY_TAG_STRIKE' => 'tidy/tidy.stub', 'TIDY_TAG_STRONG' => 'tidy/tidy.stub', 'TIDY_TAG_STYLE' => 'tidy/tidy.stub', 'TIDY_TAG_SUB' => 'tidy/tidy.stub', 'TIDY_TAG_SUMMARY' => 'tidy/tidy.stub', 'TIDY_TAG_SUP' => 'tidy/tidy.stub', 'TIDY_TAG_TABLE' => 'tidy/tidy.stub', 'TIDY_TAG_TBODY' => 'tidy/tidy.stub', 'TIDY_TAG_TD' => 'tidy/tidy.stub', 'TIDY_TAG_TEMPLATE' => 'tidy/tidy.stub', 'TIDY_TAG_TEXTAREA' => 'tidy/tidy.stub', 'TIDY_TAG_TFOOT' => 'tidy/tidy.stub', 'TIDY_TAG_TH' => 'tidy/tidy.stub', 'TIDY_TAG_THEAD' => 'tidy/tidy.stub', 'TIDY_TAG_TIME' => 'tidy/tidy.stub', 'TIDY_TAG_TITLE' => 'tidy/tidy.stub', 'TIDY_TAG_TR' => 'tidy/tidy.stub', 'TIDY_TAG_TRACK' => 'tidy/tidy.stub', 'TIDY_TAG_TT' => 'tidy/tidy.stub', 'TIDY_TAG_U' => 'tidy/tidy.stub', 'TIDY_TAG_UL' => 'tidy/tidy.stub', 'TIDY_TAG_UNKNOWN' => 'tidy/tidy.stub', 'TIDY_TAG_VAR' => 'tidy/tidy.stub', 'TIDY_TAG_VIDEO' => 'tidy/tidy.stub', 'TIDY_TAG_WBR' => 'tidy/tidy.stub', 'TIDY_TAG_XMP' => 'tidy/tidy.stub', 'TOKEN_PARSE' => 'tokenizer/tokenizer.stub', 'TRAP_BRKPT' => 'pcntl/pcntl.stub', 'TRAP_TRACE' => 'pcntl/pcntl.stub', 'TYPEAPPLICATION' => 'imap/imap.stub', 'TYPEAUDIO' => 'imap/imap.stub', 'TYPEIMAGE' => 'imap/imap.stub', 'TYPEMESSAGE' => 'imap/imap.stub', 'TYPEMODEL' => 'imap/imap.stub', 'TYPEMULTIPART' => 'imap/imap.stub', 'TYPEOTHER' => 'imap/imap.stub', 'TYPETEXT' => 'imap/imap.stub', 'TYPEVIDEO' => 'imap/imap.stub', 'T_ABSTRACT' => 'tokenizer/tokenizer.stub', 'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG' => 'tokenizer/tokenizer.stub', 'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG' => 'tokenizer/tokenizer.stub', 'T_AND_EQUAL' => 'tokenizer/tokenizer.stub', 'T_ARRAY' => 'tokenizer/tokenizer.stub', 'T_ARRAY_CAST' => 'tokenizer/tokenizer.stub', 'T_AS' => 'tokenizer/tokenizer.stub', 'T_ATTRIBUTE' => 'tokenizer/tokenizer.stub', 'T_BAD_CHARACTER' => 'tokenizer/tokenizer.stub', 'T_BOOLEAN_AND' => 'tokenizer/tokenizer.stub', 'T_BOOLEAN_OR' => 'tokenizer/tokenizer.stub', 'T_BOOL_CAST' => 'tokenizer/tokenizer.stub', 'T_BREAK' => 'tokenizer/tokenizer.stub', 'T_CALLABLE' => 'tokenizer/tokenizer.stub', 'T_CASE' => 'tokenizer/tokenizer.stub', 'T_CATCH' => 'tokenizer/tokenizer.stub', 'T_CHARACTER' => 'tokenizer/tokenizer.stub', 'T_CLASS' => 'tokenizer/tokenizer.stub', 'T_CLASS_C' => 'tokenizer/tokenizer.stub', 'T_CLONE' => 'tokenizer/tokenizer.stub', 'T_CLOSE_TAG' => 'tokenizer/tokenizer.stub', 'T_COALESCE' => 'tokenizer/tokenizer.stub', 'T_COALESCE_EQUAL' => 'tokenizer/tokenizer.stub', 'T_COMMENT' => 'tokenizer/tokenizer.stub', 'T_CONCAT_EQUAL' => 'tokenizer/tokenizer.stub', 'T_CONST' => 'tokenizer/tokenizer.stub', 'T_CONSTANT_ENCAPSED_STRING' => 'tokenizer/tokenizer.stub', 'T_CONTINUE' => 'tokenizer/tokenizer.stub', 'T_CURLY_OPEN' => 'tokenizer/tokenizer.stub', 'T_DEC' => 'tokenizer/tokenizer.stub', 'T_DECLARE' => 'tokenizer/tokenizer.stub', 'T_DEFAULT' => 'tokenizer/tokenizer.stub', 'T_DIR' => 'tokenizer/tokenizer.stub', 'T_DIV_EQUAL' => 'tokenizer/tokenizer.stub', 'T_DNUMBER' => 'tokenizer/tokenizer.stub', 'T_DO' => 'tokenizer/tokenizer.stub', 'T_DOC_COMMENT' => 'tokenizer/tokenizer.stub', 'T_DOLLAR_OPEN_CURLY_BRACES' => 'tokenizer/tokenizer.stub', 'T_DOUBLE_ARROW' => 'tokenizer/tokenizer.stub', 'T_DOUBLE_CAST' => 'tokenizer/tokenizer.stub', 'T_DOUBLE_COLON' => 'tokenizer/tokenizer.stub', 'T_ECHO' => 'tokenizer/tokenizer.stub', 'T_ELLIPSIS' => 'tokenizer/tokenizer.stub', 'T_ELSE' => 'tokenizer/tokenizer.stub', 'T_ELSEIF' => 'tokenizer/tokenizer.stub', 'T_EMPTY' => 'tokenizer/tokenizer.stub', 'T_ENCAPSED_AND_WHITESPACE' => 'tokenizer/tokenizer.stub', 'T_ENDDECLARE' => 'tokenizer/tokenizer.stub', 'T_ENDFOR' => 'tokenizer/tokenizer.stub', 'T_ENDFOREACH' => 'tokenizer/tokenizer.stub', 'T_ENDIF' => 'tokenizer/tokenizer.stub', 'T_ENDSWITCH' => 'tokenizer/tokenizer.stub', 'T_ENDWHILE' => 'tokenizer/tokenizer.stub', 'T_END_HEREDOC' => 'tokenizer/tokenizer.stub', 'T_ENUM' => 'tokenizer/tokenizer.stub', 'T_EVAL' => 'tokenizer/tokenizer.stub', 'T_EXIT' => 'tokenizer/tokenizer.stub', 'T_EXTENDS' => 'tokenizer/tokenizer.stub', 'T_FILE' => 'tokenizer/tokenizer.stub', 'T_FINAL' => 'tokenizer/tokenizer.stub', 'T_FINALLY' => 'tokenizer/tokenizer.stub', 'T_FMT' => 'standard/standard_defines.stub', 'T_FMT_AMPM' => 'standard/standard_defines.stub', 'T_FN' => 'tokenizer/tokenizer.stub', 'T_FOR' => 'tokenizer/tokenizer.stub', 'T_FOREACH' => 'tokenizer/tokenizer.stub', 'T_FUNCTION' => 'tokenizer/tokenizer.stub', 'T_FUNC_C' => 'tokenizer/tokenizer.stub', 'T_GLOBAL' => 'tokenizer/tokenizer.stub', 'T_GOTO' => 'tokenizer/tokenizer.stub', 'T_HALT_COMPILER' => 'tokenizer/tokenizer.stub', 'T_IF' => 'tokenizer/tokenizer.stub', 'T_IMPLEMENTS' => 'tokenizer/tokenizer.stub', 'T_INC' => 'tokenizer/tokenizer.stub', 'T_INCLUDE' => 'tokenizer/tokenizer.stub', 'T_INCLUDE_ONCE' => 'tokenizer/tokenizer.stub', 'T_INLINE_HTML' => 'tokenizer/tokenizer.stub', 'T_INSTANCEOF' => 'tokenizer/tokenizer.stub', 'T_INSTEADOF' => 'tokenizer/tokenizer.stub', 'T_INTERFACE' => 'tokenizer/tokenizer.stub', 'T_INT_CAST' => 'tokenizer/tokenizer.stub', 'T_ISSET' => 'tokenizer/tokenizer.stub', 'T_IS_EQUAL' => 'tokenizer/tokenizer.stub', 'T_IS_GREATER_OR_EQUAL' => 'tokenizer/tokenizer.stub', 'T_IS_IDENTICAL' => 'tokenizer/tokenizer.stub', 'T_IS_NOT_EQUAL' => 'tokenizer/tokenizer.stub', 'T_IS_NOT_IDENTICAL' => 'tokenizer/tokenizer.stub', 'T_IS_SMALLER_OR_EQUAL' => 'tokenizer/tokenizer.stub', 'T_LINE' => 'tokenizer/tokenizer.stub', 'T_LIST' => 'tokenizer/tokenizer.stub', 'T_LNUMBER' => 'tokenizer/tokenizer.stub', 'T_LOGICAL_AND' => 'tokenizer/tokenizer.stub', 'T_LOGICAL_OR' => 'tokenizer/tokenizer.stub', 'T_LOGICAL_XOR' => 'tokenizer/tokenizer.stub', 'T_MATCH' => 'tokenizer/tokenizer.stub', 'T_METHOD_C' => 'tokenizer/tokenizer.stub', 'T_MINUS_EQUAL' => 'tokenizer/tokenizer.stub', 'T_MOD_EQUAL' => 'tokenizer/tokenizer.stub', 'T_MUL_EQUAL' => 'tokenizer/tokenizer.stub', 'T_NAMESPACE' => 'tokenizer/tokenizer.stub', 'T_NAME_FULLY_QUALIFIED' => 'tokenizer/tokenizer.stub', 'T_NAME_QUALIFIED' => 'tokenizer/tokenizer.stub', 'T_NAME_RELATIVE' => 'tokenizer/tokenizer.stub', 'T_NEW' => 'tokenizer/tokenizer.stub', 'T_NS_C' => 'tokenizer/tokenizer.stub', 'T_NS_SEPARATOR' => 'tokenizer/tokenizer.stub', 'T_NULLSAFE_OBJECT_OPERATOR' => 'tokenizer/tokenizer.stub', 'T_NUM_STRING' => 'tokenizer/tokenizer.stub', 'T_OBJECT_CAST' => 'tokenizer/tokenizer.stub', 'T_OBJECT_OPERATOR' => 'tokenizer/tokenizer.stub', 'T_OPEN_TAG' => 'tokenizer/tokenizer.stub', 'T_OPEN_TAG_WITH_ECHO' => 'tokenizer/tokenizer.stub', 'T_OR_EQUAL' => 'tokenizer/tokenizer.stub', 'T_PAAMAYIM_NEKUDOTAYIM' => 'tokenizer/tokenizer.stub', 'T_PLUS_EQUAL' => 'tokenizer/tokenizer.stub', 'T_POW' => 'tokenizer/tokenizer.stub', 'T_POW_EQUAL' => 'tokenizer/tokenizer.stub', 'T_PRINT' => 'tokenizer/tokenizer.stub', 'T_PRIVATE' => 'tokenizer/tokenizer.stub', 'T_PRIVATE_SET' => 'tokenizer/tokenizer.stub', 'T_PROPERTY_C' => 'tokenizer/tokenizer.stub', 'T_PROTECTED' => 'tokenizer/tokenizer.stub', 'T_PROTECTED_SET' => 'tokenizer/tokenizer.stub', 'T_PUBLIC' => 'tokenizer/tokenizer.stub', 'T_PUBLIC_SET' => 'tokenizer/tokenizer.stub', 'T_READONLY' => 'tokenizer/tokenizer.stub', 'T_REQUIRE' => 'tokenizer/tokenizer.stub', 'T_REQUIRE_ONCE' => 'tokenizer/tokenizer.stub', 'T_RETURN' => 'tokenizer/tokenizer.stub', 'T_SL' => 'tokenizer/tokenizer.stub', 'T_SL_EQUAL' => 'tokenizer/tokenizer.stub', 'T_SPACESHIP' => 'tokenizer/tokenizer.stub', 'T_SR' => 'tokenizer/tokenizer.stub', 'T_SR_EQUAL' => 'tokenizer/tokenizer.stub', 'T_START_HEREDOC' => 'tokenizer/tokenizer.stub', 'T_STATIC' => 'tokenizer/tokenizer.stub', 'T_STRING' => 'tokenizer/tokenizer.stub', 'T_STRING_CAST' => 'tokenizer/tokenizer.stub', 'T_STRING_VARNAME' => 'tokenizer/tokenizer.stub', 'T_SWITCH' => 'tokenizer/tokenizer.stub', 'T_THROW' => 'tokenizer/tokenizer.stub', 'T_TRAIT' => 'tokenizer/tokenizer.stub', 'T_TRAIT_C' => 'tokenizer/tokenizer.stub', 'T_TRY' => 'tokenizer/tokenizer.stub', 'T_UNSET' => 'tokenizer/tokenizer.stub', 'T_UNSET_CAST' => 'tokenizer/tokenizer.stub', 'T_USE' => 'tokenizer/tokenizer.stub', 'T_VAR' => 'tokenizer/tokenizer.stub', 'T_VARIABLE' => 'tokenizer/tokenizer.stub', 'T_WHILE' => 'tokenizer/tokenizer.stub', 'T_WHITESPACE' => 'tokenizer/tokenizer.stub', 'T_XOR_EQUAL' => 'tokenizer/tokenizer.stub', 'T_YIELD' => 'tokenizer/tokenizer.stub', 'T_YIELD_FROM' => 'tokenizer/tokenizer.stub', 'TabControl' => 'winbinder/winbinder.stub', 'Timer' => 'winbinder/winbinder.stub', 'ToolBar' => 'winbinder/winbinder.stub', 'ToolDialog' => 'winbinder/winbinder.stub', 'TreeView' => 'winbinder/winbinder.stub', 'ULOC_ACTUAL_LOCALE' => 'intl/intl.stub', 'ULOC_VALID_LOCALE' => 'intl/intl.stub', 'UNKNOWN_TYPE' => 'soap/soap.stub', 'UPLOAD_ERR_CANT_WRITE' => 'Core/Core_d.stub', 'UPLOAD_ERR_EXTENSION' => 'Core/Core_d.stub', 'UPLOAD_ERR_FORM_SIZE' => 'Core/Core_d.stub', 'UPLOAD_ERR_INI_SIZE' => 'Core/Core_d.stub', 'UPLOAD_ERR_NO_FILE' => 'Core/Core_d.stub', 'UPLOAD_ERR_NO_TMP_DIR' => 'Core/Core_d.stub', 'UPLOAD_ERR_OK' => 'Core/Core_d.stub', 'UPLOAD_ERR_PARTIAL' => 'Core/Core_d.stub', 'UUID_TYPE_DCE' => 'uuid/uuid_c.stub', 'UUID_TYPE_DEFAULT' => 'uuid/uuid_c.stub', 'UUID_TYPE_INVALID' => 'uuid/uuid_c.stub', 'UUID_TYPE_MD5' => 'uuid/uuid_c.stub', 'UUID_TYPE_NAME' => 'uuid/uuid_c.stub', 'UUID_TYPE_NULL' => 'uuid/uuid_c.stub', 'UUID_TYPE_RANDOM' => 'uuid/uuid_c.stub', 'UUID_TYPE_SECURITY' => 'uuid/uuid_c.stub', 'UUID_TYPE_SHA1' => 'uuid/uuid_c.stub', 'UUID_TYPE_TIME' => 'uuid/uuid_c.stub', 'UUID_VARIANT_DCE' => 'uuid/uuid_c.stub', 'UUID_VARIANT_MICROSOFT' => 'uuid/uuid_c.stub', 'UUID_VARIANT_NCS' => 'uuid/uuid_c.stub', 'UUID_VARIANT_OTHER' => 'uuid/uuid_c.stub', 'U_AMBIGUOUS_ALIAS_WARNING' => 'intl/intl.stub', 'U_BAD_VARIABLE_DEFINITION' => 'intl/intl.stub', 'U_BRK_ASSIGN_ERROR' => 'intl/intl.stub', 'U_BRK_ERROR_LIMIT' => 'intl/intl.stub', 'U_BRK_ERROR_START' => 'intl/intl.stub', 'U_BRK_HEX_DIGITS_EXPECTED' => 'intl/intl.stub', 'U_BRK_INIT_ERROR' => 'intl/intl.stub', 'U_BRK_INTERNAL_ERROR' => 'intl/intl.stub', 'U_BRK_MALFORMED_RULE_TAG' => 'intl/intl.stub', 'U_BRK_MISMATCHED_PAREN' => 'intl/intl.stub', 'U_BRK_NEW_LINE_IN_QUOTED_STRING' => 'intl/intl.stub', 'U_BRK_RULE_EMPTY_SET' => 'intl/intl.stub', 'U_BRK_RULE_SYNTAX' => 'intl/intl.stub', 'U_BRK_SEMICOLON_EXPECTED' => 'intl/intl.stub', 'U_BRK_UNCLOSED_SET' => 'intl/intl.stub', 'U_BRK_UNDEFINED_VARIABLE' => 'intl/intl.stub', 'U_BRK_UNRECOGNIZED_OPTION' => 'intl/intl.stub', 'U_BRK_VARIABLE_REDFINITION' => 'intl/intl.stub', 'U_BUFFER_OVERFLOW_ERROR' => 'intl/intl.stub', 'U_CE_NOT_FOUND_ERROR' => 'intl/intl.stub', 'U_COLLATOR_VERSION_MISMATCH' => 'intl/intl.stub', 'U_DIFFERENT_UCA_VERSION' => 'intl/intl.stub', 'U_ENUM_OUT_OF_SYNC_ERROR' => 'intl/intl.stub', 'U_ERROR_LIMIT' => 'intl/intl.stub', 'U_ERROR_WARNING_LIMIT' => 'intl/intl.stub', 'U_ERROR_WARNING_START' => 'intl/intl.stub', 'U_FILE_ACCESS_ERROR' => 'intl/intl.stub', 'U_FMT_PARSE_ERROR_LIMIT' => 'intl/intl.stub', 'U_FMT_PARSE_ERROR_START' => 'intl/intl.stub', 'U_IDNA_ACE_PREFIX_ERROR' => 'intl/intl.stub', 'U_IDNA_CHECK_BIDI_ERROR' => 'intl/intl.stub', 'U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR' => 'intl/intl.stub', 'U_IDNA_ERROR_LIMIT' => 'intl/intl.stub', 'U_IDNA_ERROR_START' => 'intl/intl.stub', 'U_IDNA_LABEL_TOO_LONG_ERROR' => 'intl/intl.stub', 'U_IDNA_PROHIBITED_ERROR' => 'intl/intl.stub', 'U_IDNA_STD3_ASCII_RULES_ERROR' => 'intl/intl.stub', 'U_IDNA_UNASSIGNED_ERROR' => 'intl/intl.stub', 'U_IDNA_VERIFICATION_ERROR' => 'intl/intl.stub', 'U_IDNA_ZERO_LENGTH_LABEL_ERROR' => 'intl/intl.stub', 'U_ILLEGAL_ARGUMENT_ERROR' => 'intl/intl.stub', 'U_ILLEGAL_CHARACTER' => 'intl/intl.stub', 'U_ILLEGAL_CHAR_FOUND' => 'intl/intl.stub', 'U_ILLEGAL_CHAR_IN_SEGMENT' => 'intl/intl.stub', 'U_ILLEGAL_ESCAPE_SEQUENCE' => 'intl/intl.stub', 'U_ILLEGAL_PAD_POSITION' => 'intl/intl.stub', 'U_INDEX_OUTOFBOUNDS_ERROR' => 'intl/intl.stub', 'U_INTERNAL_PROGRAM_ERROR' => 'intl/intl.stub', 'U_INTERNAL_TRANSLITERATOR_ERROR' => 'intl/intl.stub', 'U_INVALID_CHAR_FOUND' => 'intl/intl.stub', 'U_INVALID_FORMAT_ERROR' => 'intl/intl.stub', 'U_INVALID_FUNCTION' => 'intl/intl.stub', 'U_INVALID_ID' => 'intl/intl.stub', 'U_INVALID_PROPERTY_PATTERN' => 'intl/intl.stub', 'U_INVALID_RBT_SYNTAX' => 'intl/intl.stub', 'U_INVALID_STATE_ERROR' => 'intl/intl.stub', 'U_INVALID_TABLE_FILE' => 'intl/intl.stub', 'U_INVALID_TABLE_FORMAT' => 'intl/intl.stub', 'U_INVARIANT_CONVERSION_ERROR' => 'intl/intl.stub', 'U_MALFORMED_EXPONENTIAL_PATTERN' => 'intl/intl.stub', 'U_MALFORMED_PRAGMA' => 'intl/intl.stub', 'U_MALFORMED_RULE' => 'intl/intl.stub', 'U_MALFORMED_SET' => 'intl/intl.stub', 'U_MALFORMED_SYMBOL_REFERENCE' => 'intl/intl.stub', 'U_MALFORMED_UNICODE_ESCAPE' => 'intl/intl.stub', 'U_MALFORMED_VARIABLE_DEFINITION' => 'intl/intl.stub', 'U_MALFORMED_VARIABLE_REFERENCE' => 'intl/intl.stub', 'U_MEMORY_ALLOCATION_ERROR' => 'intl/intl.stub', 'U_MESSAGE_PARSE_ERROR' => 'intl/intl.stub', 'U_MISMATCHED_SEGMENT_DELIMITERS' => 'intl/intl.stub', 'U_MISPLACED_ANCHOR_START' => 'intl/intl.stub', 'U_MISPLACED_COMPOUND_FILTER' => 'intl/intl.stub', 'U_MISPLACED_CURSOR_OFFSET' => 'intl/intl.stub', 'U_MISPLACED_QUANTIFIER' => 'intl/intl.stub', 'U_MISSING_OPERATOR' => 'intl/intl.stub', 'U_MISSING_RESOURCE_ERROR' => 'intl/intl.stub', 'U_MISSING_SEGMENT_CLOSE' => 'intl/intl.stub', 'U_MULTIPLE_ANTE_CONTEXTS' => 'intl/intl.stub', 'U_MULTIPLE_COMPOUND_FILTERS' => 'intl/intl.stub', 'U_MULTIPLE_CURSORS' => 'intl/intl.stub', 'U_MULTIPLE_DECIMAL_SEPARATORS' => 'intl/intl.stub', 'U_MULTIPLE_DECIMAL_SEPERATORS' => 'intl/intl.stub', 'U_MULTIPLE_EXPONENTIAL_SYMBOLS' => 'intl/intl.stub', 'U_MULTIPLE_PAD_SPECIFIERS' => 'intl/intl.stub', 'U_MULTIPLE_PERCENT_SYMBOLS' => 'intl/intl.stub', 'U_MULTIPLE_PERMILL_SYMBOLS' => 'intl/intl.stub', 'U_MULTIPLE_POST_CONTEXTS' => 'intl/intl.stub', 'U_NO_SPACE_AVAILABLE' => 'intl/intl.stub', 'U_NO_WRITE_PERMISSION' => 'intl/intl.stub', 'U_PARSE_ERROR' => 'intl/intl.stub', 'U_PARSE_ERROR_LIMIT' => 'intl/intl.stub', 'U_PARSE_ERROR_START' => 'intl/intl.stub', 'U_PATTERN_SYNTAX_ERROR' => 'intl/intl.stub', 'U_PRIMARY_TOO_LONG_ERROR' => 'intl/intl.stub', 'U_REGEX_BAD_ESCAPE_SEQUENCE' => 'intl/intl.stub', 'U_REGEX_BAD_INTERVAL' => 'intl/intl.stub', 'U_REGEX_ERROR_LIMIT' => 'intl/intl.stub', 'U_REGEX_ERROR_START' => 'intl/intl.stub', 'U_REGEX_INTERNAL_ERROR' => 'intl/intl.stub', 'U_REGEX_INVALID_BACK_REF' => 'intl/intl.stub', 'U_REGEX_INVALID_FLAG' => 'intl/intl.stub', 'U_REGEX_INVALID_STATE' => 'intl/intl.stub', 'U_REGEX_LOOK_BEHIND_LIMIT' => 'intl/intl.stub', 'U_REGEX_MAX_LT_MIN' => 'intl/intl.stub', 'U_REGEX_MISMATCHED_PAREN' => 'intl/intl.stub', 'U_REGEX_NUMBER_TOO_BIG' => 'intl/intl.stub', 'U_REGEX_PROPERTY_SYNTAX' => 'intl/intl.stub', 'U_REGEX_RULE_SYNTAX' => 'intl/intl.stub', 'U_REGEX_SET_CONTAINS_STRING' => 'intl/intl.stub', 'U_REGEX_UNIMPLEMENTED' => 'intl/intl.stub', 'U_RESOURCE_TYPE_MISMATCH' => 'intl/intl.stub', 'U_RULE_MASK_ERROR' => 'intl/intl.stub', 'U_SAFECLONE_ALLOCATED_WARNING' => 'intl/intl.stub', 'U_SORT_KEY_TOO_SHORT_WARNING' => 'intl/intl.stub', 'U_STANDARD_ERROR_LIMIT' => 'intl/intl.stub', 'U_STATE_OLD_WARNING' => 'intl/intl.stub', 'U_STATE_TOO_OLD_ERROR' => 'intl/intl.stub', 'U_STRINGPREP_CHECK_BIDI_ERROR' => 'intl/intl.stub', 'U_STRINGPREP_PROHIBITED_ERROR' => 'intl/intl.stub', 'U_STRINGPREP_UNASSIGNED_ERROR' => 'intl/intl.stub', 'U_STRING_NOT_TERMINATED_WARNING' => 'intl/intl.stub', 'U_TOO_MANY_ALIASES_ERROR' => 'intl/intl.stub', 'U_TRAILING_BACKSLASH' => 'intl/intl.stub', 'U_TRUNCATED_CHAR_FOUND' => 'intl/intl.stub', 'U_UNCLOSED_SEGMENT' => 'intl/intl.stub', 'U_UNDEFINED_SEGMENT_REFERENCE' => 'intl/intl.stub', 'U_UNDEFINED_VARIABLE' => 'intl/intl.stub', 'U_UNEXPECTED_TOKEN' => 'intl/intl.stub', 'U_UNMATCHED_BRACES' => 'intl/intl.stub', 'U_UNQUOTED_SPECIAL' => 'intl/intl.stub', 'U_UNSUPPORTED_ATTRIBUTE' => 'intl/intl.stub', 'U_UNSUPPORTED_ERROR' => 'intl/intl.stub', 'U_UNSUPPORTED_ESCAPE_SEQUENCE' => 'intl/intl.stub', 'U_UNSUPPORTED_PROPERTY' => 'intl/intl.stub', 'U_UNTERMINATED_QUOTE' => 'intl/intl.stub', 'U_USELESS_COLLATOR_ERROR' => 'intl/intl.stub', 'U_USING_DEFAULT_WARNING' => 'intl/intl.stub', 'U_USING_FALLBACK_WARNING' => 'intl/intl.stub', 'U_VARIABLE_RANGE_EXHAUSTED' => 'intl/intl.stub', 'U_VARIABLE_RANGE_OVERLAP' => 'intl/intl.stub', 'U_ZERO_ERROR' => 'intl/intl.stub', 'VARCMP_EQ' => 'com_dotnet/com_dotnet.stub', 'VARCMP_GT' => 'com_dotnet/com_dotnet.stub', 'VARCMP_LT' => 'com_dotnet/com_dotnet.stub', 'VARCMP_NULL' => 'com_dotnet/com_dotnet.stub', 'VIR_CONNECT_FLAG_SOUNDHW_GET_NAMES' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_GET_ALL_DOMAINS_STATS_ACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_GET_ALL_DOMAINS_STATS_INACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_GET_ALL_DOMAINS_STATS_OTHER' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_GET_ALL_DOMAINS_STATS_PAUSED' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_GET_ALL_DOMAINS_STATS_PERSISTENT' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_GET_ALL_DOMAINS_STATS_RUNNING' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_GET_ALL_DOMAINS_STATS_SHUTOFF' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_GET_ALL_DOMAINS_STATS_TRANSIENT' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_LIST_NETWORKS_ACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_LIST_NETWORKS_AUTOSTART' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_LIST_NETWORKS_INACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_LIST_NETWORKS_PERSISTENT' => 'libvirt-php/libvirt-php.stub', 'VIR_CONNECT_LIST_NETWORKS_TRANSIENT' => 'libvirt-php/libvirt-php.stub', 'VIR_CRED_AUTHNAME' => 'libvirt-php/libvirt-php.stub', 'VIR_CRED_CNONCE' => 'libvirt-php/libvirt-php.stub', 'VIR_CRED_ECHOPROMPT' => 'libvirt-php/libvirt-php.stub', 'VIR_CRED_EXTERNAL' => 'libvirt-php/libvirt-php.stub', 'VIR_CRED_LANGUAGE' => 'libvirt-php/libvirt-php.stub', 'VIR_CRED_NOECHOPROMPT' => 'libvirt-php/libvirt-php.stub', 'VIR_CRED_PASSPHRASE' => 'libvirt-php/libvirt-php.stub', 'VIR_CRED_REALM' => 'libvirt-php/libvirt-php.stub', 'VIR_CRED_USERNAME' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_AFFECT_CONFIG' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_AFFECT_CURRENT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_AFFECT_LIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCKED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_COMMIT_ACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_COMMIT_BANDWIDTH_BYTES' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_COMMIT_DELETE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_COMMIT_RELATIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_COMMIT_SHALLOW' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_COPY_REUSE_EXT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_COPY_SHALLOW' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_JOB_TYPE_COPY' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_JOB_TYPE_PULL' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_REBASE_COPY' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_REBASE_COPY_DEV' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_REBASE_COPY_RAW' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_REBASE_RELATIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_REBASE_SHALLOW' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_BLOCK_RESIZE_BYTES' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_CRASHED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_DEVICE_MODIFY_CONFIG' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_DEVICE_MODIFY_CURRENT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_DEVICE_MODIFY_FORCE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_DEVICE_MODIFY_LIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_DISK_ACCESS_ALL' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_DISK_BLOCK' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_DISK_FILE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_FLAG_CLOCK_LOCALTIME' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_FLAG_FEATURE_ACPI' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_FLAG_FEATURE_APIC' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_FLAG_FEATURE_PAE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_FLAG_SOUND_AC97' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_FLAG_TEST_LOCAL_VNC' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_JOB_BOUNDED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_JOB_CANCELLED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_JOB_COMPLETED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_JOB_FAILED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_JOB_NONE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_JOB_UNBOUNDED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEMORY_STAT_AVAILABLE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEMORY_STAT_NR' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEMORY_STAT_RSS' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEMORY_STAT_SWAP_IN' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEMORY_STAT_SWAP_OUT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEMORY_STAT_UNUSED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEM_CONFIG' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEM_CURRENT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEM_LIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_MEM_MAXIMUM' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_METADATA_DESCRIPTION' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_METADATA_ELEMENT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_METADATA_TITLE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_NONE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_NOSTATE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_PAUSED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_PMSUSPENDED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_RUNNING' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_SHUTDOWN' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_SHUTOFF' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_START_AUTODESTROY' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_START_BYPASS_CACHE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_START_FORCE_BOOT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_START_PAUSED' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_START_VALIDATE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_STATS_BALLOON' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_STATS_BLOCK' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_STATS_CPU_TOTAL' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_STATS_INTERFACE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_STATS_STATE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_STATS_VCPU' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_UNDEFINE_KEEP_NVRAM' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_UNDEFINE_MANAGED_SAVE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_UNDEFINE_NVRAM' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_VCPU_CONFIG' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_VCPU_CURRENT' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_VCPU_GUEST' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_VCPU_LIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_VCPU_MAXIMUM' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_XML_INACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_XML_MIGRATABLE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_XML_SECURE' => 'libvirt-php/libvirt-php.stub', 'VIR_DOMAIN_XML_UPDATE_CPU' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_ATSET1' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_ATSET2' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_ATSET3' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_LINUX' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_OSX' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_RFB' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_USB' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_WIN32' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_XT' => 'libvirt-php/libvirt-php.stub', 'VIR_KEYCODE_SET_XT_KBD' => 'libvirt-php/libvirt-php.stub', 'VIR_MEMORY_PHYSICAL' => 'libvirt-php/libvirt-php.stub', 'VIR_MEMORY_VIRTUAL' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_ABORT_ON_ERROR' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_AUTO_CONVERGE' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_CHANGE_PROTECTION' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_COMPRESSED' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_LIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_NON_SHARED_DISK' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_NON_SHARED_INC' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_OFFLINE' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_PAUSED' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_PEER2PEER' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_PERSIST_DEST' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_TUNNELLED' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_UNDEFINE_SOURCE' => 'libvirt-php/libvirt-php.stub', 'VIR_MIGRATE_UNSAFE' => 'libvirt-php/libvirt-php.stub', 'VIR_NETWORKS_ACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_NETWORKS_ALL' => 'libvirt-php/libvirt-php.stub', 'VIR_NETWORKS_INACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_NODE_CPU_STATS_ALL_CPUS' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_CREATE_ATOMIC' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_CREATE_CURRENT' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_CREATE_DISK_ONLY' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_CREATE_HALT' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_CREATE_LIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_CREATE_NO_METADATA' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_CREATE_QUIESCE' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_CREATE_REDEFINE' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_CREATE_REUSE_EXT' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_DELETE_CHILDREN' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_DELETE_CHILDREN_ONLY' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_DELETE_METADATA_ONLY' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_ACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_DESCENDANTS' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_DISK_ONLY' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_EXTERNAL' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_INACTIVE' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_INTERNAL' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_LEAVES' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_METADATA' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_NO_LEAVES' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_NO_METADATA' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_LIST_ROOTS' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_REVERT_FORCE' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_REVERT_PAUSED' => 'libvirt-php/libvirt-php.stub', 'VIR_SNAPSHOT_REVERT_RUNNING' => 'libvirt-php/libvirt-php.stub', 'VIR_STORAGE_POOL_BUILD_NEW' => 'libvirt-php/libvirt-php.stub', 'VIR_STORAGE_POOL_BUILD_REPAIR' => 'libvirt-php/libvirt-php.stub', 'VIR_STORAGE_POOL_BUILD_RESIZE' => 'libvirt-php/libvirt-php.stub', 'VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA' => 'libvirt-php/libvirt-php.stub', 'VIR_STORAGE_VOL_CREATE_REFLINK' => 'libvirt-php/libvirt-php.stub', 'VIR_STORAGE_VOL_RESIZE_ALLOCATE' => 'libvirt-php/libvirt-php.stub', 'VIR_STORAGE_VOL_RESIZE_DELTA' => 'libvirt-php/libvirt-php.stub', 'VIR_STORAGE_VOL_RESIZE_SHRINK' => 'libvirt-php/libvirt-php.stub', 'VIR_VERSION_BINDING' => 'libvirt-php/libvirt-php.stub', 'VIR_VERSION_LIBVIRT' => 'libvirt-php/libvirt-php.stub', 'VT_ARRAY' => 'com_dotnet/com_dotnet.stub', 'VT_BOOL' => 'com_dotnet/com_dotnet.stub', 'VT_BSTR' => 'com_dotnet/com_dotnet.stub', 'VT_BYREF' => 'com_dotnet/com_dotnet.stub', 'VT_CY' => 'com_dotnet/com_dotnet.stub', 'VT_DATE' => 'com_dotnet/com_dotnet.stub', 'VT_DECIMAL' => 'com_dotnet/com_dotnet.stub', 'VT_DISPATCH' => 'com_dotnet/com_dotnet.stub', 'VT_EMPTY' => 'com_dotnet/com_dotnet.stub', 'VT_ERROR' => 'com_dotnet/com_dotnet.stub', 'VT_I1' => 'com_dotnet/com_dotnet.stub', 'VT_I2' => 'com_dotnet/com_dotnet.stub', 'VT_I4' => 'com_dotnet/com_dotnet.stub', 'VT_INT' => 'com_dotnet/com_dotnet.stub', 'VT_NULL' => 'com_dotnet/com_dotnet.stub', 'VT_R4' => 'com_dotnet/com_dotnet.stub', 'VT_R8' => 'com_dotnet/com_dotnet.stub', 'VT_UI1' => 'com_dotnet/com_dotnet.stub', 'VT_UI2' => 'com_dotnet/com_dotnet.stub', 'VT_UI4' => 'com_dotnet/com_dotnet.stub', 'VT_UINT' => 'com_dotnet/com_dotnet.stub', 'VT_UNKNOWN' => 'com_dotnet/com_dotnet.stub', 'VT_VARIANT' => 'com_dotnet/com_dotnet.stub', 'WBC_ALT' => 'winbinder/winbinder.stub', 'WBC_AUTOREPEAT' => 'winbinder/winbinder.stub', 'WBC_BEEP' => 'winbinder/winbinder.stub', 'WBC_BORDER' => 'winbinder/winbinder.stub', 'WBC_BOTTOM' => 'winbinder/winbinder.stub', 'WBC_CENTER' => 'winbinder/winbinder.stub', 'WBC_CHECKBOXES' => 'winbinder/winbinder.stub', 'WBC_CONTROL' => 'winbinder/winbinder.stub', 'WBC_CUSTOMDRAW' => 'winbinder/winbinder.stub', 'WBC_DBLCLICK' => 'winbinder/winbinder.stub', 'WBC_DEFAULT' => 'winbinder/winbinder.stub', 'WBC_DEFAULTPOS' => 'winbinder/winbinder.stub', 'WBC_DISABLED' => 'winbinder/winbinder.stub', 'WBC_ELLIPSIS' => 'winbinder/winbinder.stub', 'WBC_ENABLED' => 'winbinder/winbinder.stub', 'WBC_GETFOCUS' => 'winbinder/winbinder.stub', 'WBC_GROUP' => 'winbinder/winbinder.stub', 'WBC_HEADERSEL' => 'winbinder/winbinder.stub', 'WBC_IMAGE' => 'winbinder/winbinder.stub', 'WBC_INFO' => 'winbinder/winbinder.stub', 'WBC_INVISIBLE' => 'winbinder/winbinder.stub', 'WBC_KEYDOWN' => 'winbinder/winbinder.stub', 'WBC_KEYUP' => 'winbinder/winbinder.stub', 'WBC_LBUTTON' => 'winbinder/winbinder.stub', 'WBC_LEFT' => 'winbinder/winbinder.stub', 'WBC_LINES' => 'winbinder/winbinder.stub', 'WBC_LV_BACK' => 'winbinder/winbinder.stub', 'WBC_LV_COLUMNS' => 'winbinder/winbinder.stub', 'WBC_LV_DEFAULT' => 'winbinder/winbinder.stub', 'WBC_LV_DRAW' => 'winbinder/winbinder.stub', 'WBC_LV_FORE' => 'winbinder/winbinder.stub', 'WBC_LV_NONE' => 'winbinder/winbinder.stub', 'WBC_MASKED' => 'winbinder/winbinder.stub', 'WBC_MAXIMIZED' => 'winbinder/winbinder.stub', 'WBC_MAXSIZE' => 'winbinder/winbinder.stub', 'WBC_MBUTTON' => 'winbinder/winbinder.stub', 'WBC_MIDDLE' => 'winbinder/winbinder.stub', 'WBC_MINIMIZED' => 'winbinder/winbinder.stub', 'WBC_MINSIZE' => 'winbinder/winbinder.stub', 'WBC_MOUSEDOWN' => 'winbinder/winbinder.stub', 'WBC_MOUSEMOVE' => 'winbinder/winbinder.stub', 'WBC_MOUSEUP' => 'winbinder/winbinder.stub', 'WBC_MULTILINE' => 'winbinder/winbinder.stub', 'WBC_MULTISELECT' => 'winbinder/winbinder.stub', 'WBC_NOHEADER' => 'winbinder/winbinder.stub', 'WBC_NORMAL' => 'winbinder/winbinder.stub', 'WBC_NOTIFY' => 'winbinder/winbinder.stub', 'WBC_NUMBER' => 'winbinder/winbinder.stub', 'WBC_OK' => 'winbinder/winbinder.stub', 'WBC_OKCANCEL' => 'winbinder/winbinder.stub', 'WBC_QUESTION' => 'winbinder/winbinder.stub', 'WBC_RBUTTON' => 'winbinder/winbinder.stub', 'WBC_READONLY' => 'winbinder/winbinder.stub', 'WBC_REDRAW' => 'winbinder/winbinder.stub', 'WBC_RESIZE' => 'winbinder/winbinder.stub', 'WBC_RIGHT' => 'winbinder/winbinder.stub', 'WBC_RTF_TEXT' => 'winbinder/winbinder.stub', 'WBC_SHIFT' => 'winbinder/winbinder.stub', 'WBC_SINGLE' => 'winbinder/winbinder.stub', 'WBC_SORT' => 'winbinder/winbinder.stub', 'WBC_STOP' => 'winbinder/winbinder.stub', 'WBC_TASKBAR' => 'winbinder/winbinder.stub', 'WBC_TITLE' => 'winbinder/winbinder.stub', 'WBC_TOP' => 'winbinder/winbinder.stub', 'WBC_TRANSPARENT' => 'winbinder/winbinder.stub', 'WBC_VERSION' => 'winbinder/winbinder.stub', 'WBC_VISIBLE' => 'winbinder/winbinder.stub', 'WBC_WARNING' => 'winbinder/winbinder.stub', 'WBC_YESNO' => 'winbinder/winbinder.stub', 'WBC_YESNOCANCEL' => 'winbinder/winbinder.stub', 'WCONTINUED' => 'pcntl/pcntl.stub', 'WEBSOCKET_CLOSE_ABNORMAL' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_DATA_ERROR' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_EXTENSION_MISSING' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_GOING_AWAY' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_MESSAGE_ERROR' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_MESSAGE_TOO_BIG' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_NORMAL' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_POLICY_ERROR' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_PROTOCOL_ERROR' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_SERVER_ERROR' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_STATUS_ERROR' => 'swoole/constants.stub', 'WEBSOCKET_CLOSE_TLS' => 'swoole/constants.stub', 'WEBSOCKET_OPCODE_BINARY' => 'swoole/constants.stub', 'WEBSOCKET_OPCODE_CLOSE' => 'swoole/constants.stub', 'WEBSOCKET_OPCODE_CONTINUATION' => 'swoole/constants.stub', 'WEBSOCKET_OPCODE_PING' => 'swoole/constants.stub', 'WEBSOCKET_OPCODE_PONG' => 'swoole/constants.stub', 'WEBSOCKET_OPCODE_TEXT' => 'swoole/constants.stub', 'WEBSOCKET_STATUS_ACTIVE' => 'swoole/constants.stub', 'WEBSOCKET_STATUS_CLOSING' => 'swoole/constants.stub', 'WEBSOCKET_STATUS_CONNECTION' => 'swoole/constants.stub', 'WEBSOCKET_STATUS_FRAME' => 'swoole/constants.stub', 'WEBSOCKET_STATUS_HANDSHAKE' => 'swoole/constants.stub', 'WEXITED' => 'pcntl/pcntl.stub', 'WHITE' => 'winbinder/winbinder.stub', 'WIN32_ABOVE_NORMAL_PRIORITY_CLASS' => 'win32service/win32service.stub', 'WIN32_BELOW_NORMAL_PRIORITY_CLASS' => 'win32service/win32service.stub', 'WIN32_ERROR_ACCESS_DENIED' => 'win32service/win32service.stub', 'WIN32_ERROR_CIRCULAR_DEPENDENCY' => 'win32service/win32service.stub', 'WIN32_ERROR_DATABASE_DOES_NOT_EXIST' => 'win32service/win32service.stub', 'WIN32_ERROR_DEPENDENT_SERVICES_RUNNING' => 'win32service/win32service.stub', 'WIN32_ERROR_DUPLICATE_SERVICE_NAME' => 'win32service/win32service.stub', 'WIN32_ERROR_FAILED_SERVICE_CONTROLLER_CONNECT' => 'win32service/win32service.stub', 'WIN32_ERROR_INSUFFICIENT_BUFFER' => 'win32service/win32service.stub', 'WIN32_ERROR_INVALID_DATA' => 'win32service/win32service.stub', 'WIN32_ERROR_INVALID_HANDLE' => 'win32service/win32service.stub', 'WIN32_ERROR_INVALID_LEVEL' => 'win32service/win32service.stub', 'WIN32_ERROR_INVALID_NAME' => 'win32service/win32service.stub', 'WIN32_ERROR_INVALID_PARAMETER' => 'win32service/win32service.stub', 'WIN32_ERROR_INVALID_SERVICE_ACCOUNT' => 'win32service/win32service.stub', 'WIN32_ERROR_INVALID_SERVICE_CONTROL' => 'win32service/win32service.stub', 'WIN32_ERROR_PATH_NOT_FOUND' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_ALREADY_RUNNING' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_CANNOT_ACCEPT_CTRL' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_DATABASE_LOCKED' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_DEPENDENCY_DELETED' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_DEPENDENCY_FAIL' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_DISABLED' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_DOES_NOT_EXIST' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_EXISTS' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_LOGON_FAILED' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_MARKED_FOR_DELETE' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_NOT_ACTIVE' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_NO_THREAD' => 'win32service/win32service.stub', 'WIN32_ERROR_SERVICE_REQUEST_TIMEOUT' => 'win32service/win32service.stub', 'WIN32_ERROR_SHUTDOWN_IN_PROGRESS' => 'win32service/win32service.stub', 'WIN32_HIGH_PRIORITY_CLASS' => 'win32service/win32service.stub', 'WIN32_IDLE_PRIORITY_CLASS' => 'win32service/win32service.stub', 'WIN32_NORMAL_PRIORITY_CLASS' => 'win32service/win32service.stub', 'WIN32_NO_ERROR' => 'win32service/win32service.stub', 'WIN32_REALTIME_PRIORITY_CLASS' => 'win32service/win32service.stub', 'WIN32_SERVICE_ACCEPT_PAUSE_CONTINUE' => 'win32service/win32service.stub', 'WIN32_SERVICE_ACCEPT_PRESHUTDOWN' => 'win32service/win32service.stub', 'WIN32_SERVICE_ACCEPT_SHUTDOWN' => 'win32service/win32service.stub', 'WIN32_SERVICE_ACCEPT_STOP' => 'win32service/win32service.stub', 'WIN32_SERVICE_AUTO_START' => 'win32service/win32service.stub', 'WIN32_SERVICE_CONTINUE_PENDING' => 'win32service/win32service.stub', 'WIN32_SERVICE_CONTROL_CONTINUE' => 'win32service/win32service.stub', 'WIN32_SERVICE_CONTROL_INTERROGATE' => 'win32service/win32service.stub', 'WIN32_SERVICE_CONTROL_PAUSE' => 'win32service/win32service.stub', 'WIN32_SERVICE_CONTROL_PRESHUTDOWN' => 'win32service/win32service.stub', 'WIN32_SERVICE_CONTROL_SHUTDOWN' => 'win32service/win32service.stub', 'WIN32_SERVICE_CONTROL_STOP' => 'win32service/win32service.stub', 'WIN32_SERVICE_DEMAND_START' => 'win32service/win32service.stub', 'WIN32_SERVICE_DISABLED' => 'win32service/win32service.stub', 'WIN32_SERVICE_ERROR_IGNORE' => 'win32service/win32service.stub', 'WIN32_SERVICE_ERROR_NORMAL' => 'win32service/win32service.stub', 'WIN32_SERVICE_INTERACTIVE_PROCESS' => 'win32service/win32service.stub', 'WIN32_SERVICE_PAUSED' => 'win32service/win32service.stub', 'WIN32_SERVICE_PAUSE_PENDING' => 'win32service/win32service.stub', 'WIN32_SERVICE_RUNNING' => 'win32service/win32service.stub', 'WIN32_SERVICE_RUNS_IN_SYSTEM_PROCESS' => 'win32service/win32service.stub', 'WIN32_SERVICE_START_PENDING' => 'win32service/win32service.stub', 'WIN32_SERVICE_STOPPED' => 'win32service/win32service.stub', 'WIN32_SERVICE_STOP_PENDING' => 'win32service/win32service.stub', 'WIN32_SERVICE_WIN32_OWN_PROCESS' => 'win32service/win32service.stub', 'WIN32_SERVICE_WIN32_OWN_PROCESS_INTERACTIVE' => 'win32service/win32service.stub', 'WNOHANG' => 'pcntl/pcntl.stub', 'WNOWAIT' => 'pcntl/pcntl.stub', 'WSDL_CACHE_BOTH' => 'soap/soap.stub', 'WSDL_CACHE_DISK' => 'soap/soap.stub', 'WSDL_CACHE_MEMORY' => 'soap/soap.stub', 'WSDL_CACHE_NONE' => 'soap/soap.stub', 'WSTOPPED' => 'pcntl/pcntl.stub', 'WUNTRACED' => 'pcntl/pcntl.stub', 'X509_PURPOSE_ANY' => 'openssl/openssl.stub', 'X509_PURPOSE_CRL_SIGN' => 'openssl/openssl.stub', 'X509_PURPOSE_NS_SSL_SERVER' => 'openssl/openssl.stub', 'X509_PURPOSE_OCSP_HELPER' => 'openssl/openssl.stub', 'X509_PURPOSE_SMIME_ENCRYPT' => 'openssl/openssl.stub', 'X509_PURPOSE_SMIME_SIGN' => 'openssl/openssl.stub', 'X509_PURPOSE_SSL_CLIENT' => 'openssl/openssl.stub', 'X509_PURPOSE_SSL_SERVER' => 'openssl/openssl.stub', 'X509_PURPOSE_TIMESTAMP_SIGN' => 'openssl/openssl.stub', 'XDEBUG_CC_BRANCH_CHECK' => 'xdebug/xdebug.stub', 'XDEBUG_CC_DEAD_CODE' => 'xdebug/xdebug.stub', 'XDEBUG_CC_UNUSED' => 'xdebug/xdebug.stub', 'XDEBUG_FILTER_CODE_COVERAGE' => 'xdebug/xdebug.stub', 'XDEBUG_FILTER_NONE' => 'xdebug/xdebug.stub', 'XDEBUG_FILTER_STACK' => 'xdebug/xdebug.stub', 'XDEBUG_FILTER_TRACING' => 'xdebug/xdebug.stub', 'XDEBUG_NAMESPACE_BLACKLIST' => 'xdebug/xdebug.stub', 'XDEBUG_NAMESPACE_EXCLUDE' => 'xdebug/xdebug.stub', 'XDEBUG_NAMESPACE_INCLUDE' => 'xdebug/xdebug.stub', 'XDEBUG_NAMESPACE_WHITELIST' => 'xdebug/xdebug.stub', 'XDEBUG_PATH_BLACKLIST' => 'xdebug/xdebug.stub', 'XDEBUG_PATH_EXCLUDE' => 'xdebug/xdebug.stub', 'XDEBUG_PATH_INCLUDE' => 'xdebug/xdebug.stub', 'XDEBUG_PATH_WHITELIST' => 'xdebug/xdebug.stub', 'XDEBUG_STACK_NO_DESC' => 'xdebug/xdebug.stub', 'XDEBUG_TRACE_APPEND' => 'xdebug/xdebug.stub', 'XDEBUG_TRACE_COMPUTERIZED' => 'xdebug/xdebug.stub', 'XDEBUG_TRACE_HTML' => 'xdebug/xdebug.stub', 'XDEBUG_TRACE_NAKED_FILENAME' => 'xdebug/xdebug.stub', 'XDIFF_PATCH_IGNORESPACE' => 'xdiff/xdiff.stub', 'XDIFF_PATCH_NORMAL' => 'xdiff/xdiff.stub', 'XDIFF_PATCH_REVERSE' => 'xdiff/xdiff.stub', 'XHPROF_FLAGS_CPU' => 'xhprof/xhprof.stub', 'XHPROF_FLAGS_MEMORY' => 'xhprof/xhprof.stub', 'XHPROF_FLAGS_NO_BUILTINS' => 'xhprof/xhprof.stub', 'XML_ATTRIBUTE_CDATA' => 'dom/dom.stub', 'XML_ATTRIBUTE_DECL_NODE' => 'dom/dom.stub', 'XML_ATTRIBUTE_ENTITY' => 'dom/dom.stub', 'XML_ATTRIBUTE_ENUMERATION' => 'dom/dom.stub', 'XML_ATTRIBUTE_ID' => 'dom/dom.stub', 'XML_ATTRIBUTE_IDREF' => 'dom/dom.stub', 'XML_ATTRIBUTE_IDREFS' => 'dom/dom.stub', 'XML_ATTRIBUTE_NMTOKEN' => 'dom/dom.stub', 'XML_ATTRIBUTE_NMTOKENS' => 'dom/dom.stub', 'XML_ATTRIBUTE_NODE' => 'dom/dom.stub', 'XML_ATTRIBUTE_NOTATION' => 'dom/dom.stub', 'XML_CDATA_SECTION_NODE' => 'dom/dom.stub', 'XML_COMMENT_NODE' => 'dom/dom.stub', 'XML_DOCUMENT_FRAG_NODE' => 'dom/dom.stub', 'XML_DOCUMENT_NODE' => 'dom/dom.stub', 'XML_DOCUMENT_TYPE_NODE' => 'dom/dom.stub', 'XML_DTD_NODE' => 'dom/dom.stub', 'XML_ELEMENT_DECL_NODE' => 'dom/dom.stub', 'XML_ELEMENT_NODE' => 'dom/dom.stub', 'XML_ENTITY_DECL_NODE' => 'dom/dom.stub', 'XML_ENTITY_NODE' => 'dom/dom.stub', 'XML_ENTITY_REF_NODE' => 'dom/dom.stub', 'XML_ERROR_ASYNC_ENTITY' => 'xml/xml.stub', 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF' => 'xml/xml.stub', 'XML_ERROR_BAD_CHAR_REF' => 'xml/xml.stub', 'XML_ERROR_BINARY_ENTITY_REF' => 'xml/xml.stub', 'XML_ERROR_DUPLICATE_ATTRIBUTE' => 'xml/xml.stub', 'XML_ERROR_EXTERNAL_ENTITY_HANDLING' => 'xml/xml.stub', 'XML_ERROR_INCORRECT_ENCODING' => 'xml/xml.stub', 'XML_ERROR_INVALID_TOKEN' => 'xml/xml.stub', 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT' => 'xml/xml.stub', 'XML_ERROR_MISPLACED_XML_PI' => 'xml/xml.stub', 'XML_ERROR_NONE' => 'xml/xml.stub', 'XML_ERROR_NO_ELEMENTS' => 'xml/xml.stub', 'XML_ERROR_NO_MEMORY' => 'xml/xml.stub', 'XML_ERROR_PARAM_ENTITY_REF' => 'xml/xml.stub', 'XML_ERROR_PARTIAL_CHAR' => 'xml/xml.stub', 'XML_ERROR_RECURSIVE_ENTITY_REF' => 'xml/xml.stub', 'XML_ERROR_SYNTAX' => 'xml/xml.stub', 'XML_ERROR_TAG_MISMATCH' => 'xml/xml.stub', 'XML_ERROR_UNCLOSED_CDATA_SECTION' => 'xml/xml.stub', 'XML_ERROR_UNCLOSED_TOKEN' => 'xml/xml.stub', 'XML_ERROR_UNDEFINED_ENTITY' => 'xml/xml.stub', 'XML_ERROR_UNKNOWN_ENCODING' => 'xml/xml.stub', 'XML_HTML_DOCUMENT_NODE' => 'dom/dom.stub', 'XML_LOCAL_NAMESPACE' => 'dom/dom.stub', 'XML_NAMESPACE_DECL_NODE' => 'dom/dom.stub', 'XML_NOTATION_NODE' => 'dom/dom.stub', 'XML_OPTION_CASE_FOLDING' => 'xml/xml.stub', 'XML_OPTION_PARSE_HUGE' => 'xml/xml.stub', 'XML_OPTION_SKIP_TAGSTART' => 'xml/xml.stub', 'XML_OPTION_SKIP_WHITE' => 'xml/xml.stub', 'XML_OPTION_TARGET_ENCODING' => 'xml/xml.stub', 'XML_PI_NODE' => 'dom/dom.stub', 'XML_SAX_IMPL' => 'xml/xml.stub', 'XML_TEXT_NODE' => 'dom/dom.stub', 'XSD_1999_NAMESPACE' => 'soap/soap.stub', 'XSD_1999_TIMEINSTANT' => 'soap/soap.stub', 'XSD_ANYTYPE' => 'soap/soap.stub', 'XSD_ANYURI' => 'soap/soap.stub', 'XSD_ANYXML' => 'soap/soap.stub', 'XSD_BASE64BINARY' => 'soap/soap.stub', 'XSD_BOOLEAN' => 'soap/soap.stub', 'XSD_BYTE' => 'soap/soap.stub', 'XSD_DATE' => 'soap/soap.stub', 'XSD_DATETIME' => 'soap/soap.stub', 'XSD_DECIMAL' => 'soap/soap.stub', 'XSD_DOUBLE' => 'soap/soap.stub', 'XSD_DURATION' => 'soap/soap.stub', 'XSD_ENTITIES' => 'soap/soap.stub', 'XSD_ENTITY' => 'soap/soap.stub', 'XSD_FLOAT' => 'soap/soap.stub', 'XSD_GDAY' => 'soap/soap.stub', 'XSD_GMONTH' => 'soap/soap.stub', 'XSD_GMONTHDAY' => 'soap/soap.stub', 'XSD_GYEAR' => 'soap/soap.stub', 'XSD_GYEARMONTH' => 'soap/soap.stub', 'XSD_HEXBINARY' => 'soap/soap.stub', 'XSD_ID' => 'soap/soap.stub', 'XSD_IDREF' => 'soap/soap.stub', 'XSD_IDREFS' => 'soap/soap.stub', 'XSD_INT' => 'soap/soap.stub', 'XSD_INTEGER' => 'soap/soap.stub', 'XSD_LANGUAGE' => 'soap/soap.stub', 'XSD_LONG' => 'soap/soap.stub', 'XSD_NAME' => 'soap/soap.stub', 'XSD_NAMESPACE' => 'soap/soap.stub', 'XSD_NCNAME' => 'soap/soap.stub', 'XSD_NEGATIVEINTEGER' => 'soap/soap.stub', 'XSD_NMTOKEN' => 'soap/soap.stub', 'XSD_NMTOKENS' => 'soap/soap.stub', 'XSD_NONNEGATIVEINTEGER' => 'soap/soap.stub', 'XSD_NONPOSITIVEINTEGER' => 'soap/soap.stub', 'XSD_NORMALIZEDSTRING' => 'soap/soap.stub', 'XSD_NOTATION' => 'soap/soap.stub', 'XSD_POSITIVEINTEGER' => 'soap/soap.stub', 'XSD_QNAME' => 'soap/soap.stub', 'XSD_SHORT' => 'soap/soap.stub', 'XSD_STRING' => 'soap/soap.stub', 'XSD_TIME' => 'soap/soap.stub', 'XSD_TOKEN' => 'soap/soap.stub', 'XSD_UNSIGNEDBYTE' => 'soap/soap.stub', 'XSD_UNSIGNEDINT' => 'soap/soap.stub', 'XSD_UNSIGNEDLONG' => 'soap/soap.stub', 'XSD_UNSIGNEDSHORT' => 'soap/soap.stub', 'XSL_CLONE_ALWAYS' => 'xsl/xsl.stub', 'XSL_CLONE_AUTO' => 'xsl/xsl.stub', 'XSL_CLONE_NEVER' => 'xsl/xsl.stub', 'XSL_SECPREF_CREATE_DIRECTORY' => 'xsl/xsl.stub', 'XSL_SECPREF_DEFAULT' => 'xsl/xsl.stub', 'XSL_SECPREF_NONE' => 'xsl/xsl.stub', 'XSL_SECPREF_READ_FILE' => 'xsl/xsl.stub', 'XSL_SECPREF_READ_NETWORK' => 'xsl/xsl.stub', 'XSL_SECPREF_WRITE_FILE' => 'xsl/xsl.stub', 'XSL_SECPREF_WRITE_NETWORK' => 'xsl/xsl.stub', 'YAF\\ENVIRON' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\AUTOLOAD\\FAILED' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\CALL\\FAILED' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\DISPATCH\\FAILED' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\NOTFOUND\\ACTION' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\NOTFOUND\\CONTROLLER' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\NOTFOUND\\MODULE' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\NOTFOUND\\VIEW' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\ROUTE\\FAILED' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\STARTUP\\FAILED' => 'yaf/yaf_namespace.stub', 'YAF\\ERR\\TYPE\\ERROR' => 'yaf/yaf_namespace.stub', 'YAF\\VERSION' => 'yaf/yaf_namespace.stub', 'YAF_ENVIRON' => 'yaf/yaf.stub', 'YAF_ERR_ACCESS_ERROR' => 'yaf/yaf.stub', 'YAF_ERR_AUTOLOAD_FAILED' => 'yaf/yaf.stub', 'YAF_ERR_CALL_FAILED' => 'yaf/yaf.stub', 'YAF_ERR_DISPATCH_FAILED' => 'yaf/yaf.stub', 'YAF_ERR_NOTFOUND_ACTION' => 'yaf/yaf.stub', 'YAF_ERR_NOTFOUND_CONTROLLER' => 'yaf/yaf.stub', 'YAF_ERR_NOTFOUND_MODULE' => 'yaf/yaf.stub', 'YAF_ERR_NOTFOUND_VIEW' => 'yaf/yaf.stub', 'YAF_ERR_ROUTE_FAILED' => 'yaf/yaf.stub', 'YAF_ERR_STARTUP_FAILED' => 'yaf/yaf.stub', 'YAF_ERR_TYPE_ERROR' => 'yaf/yaf.stub', 'YAF_VERSION' => 'yaf/yaf.stub', 'YAML_ANY_BREAK' => 'yaml/yaml.stub', 'YAML_ANY_ENCODING' => 'yaml/yaml.stub', 'YAML_ANY_SCALAR_STYLE' => 'yaml/yaml.stub', 'YAML_BINARY_TAG' => 'yaml/yaml.stub', 'YAML_BOOL_TAG' => 'yaml/yaml.stub', 'YAML_CRLN_BREAK' => 'yaml/yaml.stub', 'YAML_CR_BREAK' => 'yaml/yaml.stub', 'YAML_DOUBLE_QUOTED_SCALAR_STYLE' => 'yaml/yaml.stub', 'YAML_FLOAT_TAG' => 'yaml/yaml.stub', 'YAML_FOLDED_SCALAR_STYLE' => 'yaml/yaml.stub', 'YAML_INT_TAG' => 'yaml/yaml.stub', 'YAML_LITERAL_SCALAR_STYLE' => 'yaml/yaml.stub', 'YAML_LN_BREAK' => 'yaml/yaml.stub', 'YAML_MAP_TAG' => 'yaml/yaml.stub', 'YAML_MERGE_TAG' => 'yaml/yaml.stub', 'YAML_NULL_TAG' => 'yaml/yaml.stub', 'YAML_PHP_TAG' => 'yaml/yaml.stub', 'YAML_PLAIN_SCALAR_STYLE' => 'yaml/yaml.stub', 'YAML_SEQ_TAG' => 'yaml/yaml.stub', 'YAML_SINGLE_QUOTED_SCALAR_STYLE' => 'yaml/yaml.stub', 'YAML_STR_TAG' => 'yaml/yaml.stub', 'YAML_TIMESTAMP_TAG' => 'yaml/yaml.stub', 'YAML_UTF16BE_ENCODING' => 'yaml/yaml.stub', 'YAML_UTF16LE_ENCODING' => 'yaml/yaml.stub', 'YAML_UTF8_ENCODING' => 'yaml/yaml.stub', 'YAR_CLIENT_PROTOCOL_HTTP' => 'yar/yar.stub', 'YAR_CLIENT_PROTOCOL_TCP' => 'yar/yar.stub', 'YAR_CLIENT_PROTOCOL_UNIX' => 'yar/yar.stub', 'YAR_ERR_EXCEPTION' => 'yar/yar.stub', 'YAR_ERR_OKEY' => 'yar/yar.stub', 'YAR_ERR_OUTPUT' => 'yar/yar.stub', 'YAR_ERR_PACKAGER' => 'yar/yar.stub', 'YAR_ERR_PROTOCOL' => 'yar/yar.stub', 'YAR_ERR_REQUEST' => 'yar/yar.stub', 'YAR_ERR_TRANSPORT' => 'yar/yar.stub', 'YAR_OPT_CONNECT_TIMEOUT' => 'yar/yar.stub', 'YAR_OPT_HEADER' => 'yar/yar.stub', 'YAR_OPT_PACKAGER' => 'yar/yar.stub', 'YAR_OPT_PERSISTENT' => 'yar/yar.stub', 'YAR_OPT_RESOLVE' => 'yar/yar.stub', 'YAR_OPT_TIMEOUT' => 'yar/yar.stub', 'YAR_PACKAGER_JSON' => 'yar/yar.stub', 'YAR_PACKAGER_PHP' => 'yar/yar.stub', 'YAR_VERSION' => 'yar/yar.stub', 'YELLOW' => 'winbinder/winbinder.stub', 'YESEXPR' => 'standard/standard_defines.stub', 'YESSTR' => 'standard/standard_defines.stub', 'ZEND_ACC_ABSTRACT' => 'uopz/uopz.stub', 'ZEND_ACC_FETCH' => 'uopz/uopz.stub', 'ZEND_ACC_FINAL' => 'uopz/uopz.stub', 'ZEND_ACC_PPP_MASK' => 'uopz/uopz.stub', 'ZEND_ACC_PRIVATE' => 'uopz/uopz.stub', 'ZEND_ACC_PROTECTED' => 'uopz/uopz.stub', 'ZEND_ACC_PUBLIC' => 'uopz/uopz.stub', 'ZEND_ACC_STATIC' => 'uopz/uopz.stub', 'ZEND_DEBUG_BUILD' => 'Core/Core_d.stub', 'ZEND_MULTIBYTE' => 'Core/Core_d.stub', 'ZEND_THREAD_SAFE' => 'Core/Core_d.stub', 'ZLIB_BLOCK' => 'zlib/zlib.stub', 'ZLIB_BUF_ERROR' => 'zlib/zlib.stub', 'ZLIB_DATA_ERROR' => 'zlib/zlib.stub', 'ZLIB_DEFAULT_STRATEGY' => 'zlib/zlib.stub', 'ZLIB_ENCODING_DEFLATE' => 'zlib/zlib.stub', 'ZLIB_ENCODING_GZIP' => 'zlib/zlib.stub', 'ZLIB_ENCODING_RAW' => 'zlib/zlib.stub', 'ZLIB_ERRNO' => 'zlib/zlib.stub', 'ZLIB_FILTERED' => 'zlib/zlib.stub', 'ZLIB_FINISH' => 'zlib/zlib.stub', 'ZLIB_FIXED' => 'zlib/zlib.stub', 'ZLIB_FULL_FLUSH' => 'zlib/zlib.stub', 'ZLIB_HUFFMAN_ONLY' => 'zlib/zlib.stub', 'ZLIB_MEM_ERROR' => 'zlib/zlib.stub', 'ZLIB_NEED_DICT' => 'zlib/zlib.stub', 'ZLIB_NO_FLUSH' => 'zlib/zlib.stub', 'ZLIB_OK' => 'zlib/zlib.stub', 'ZLIB_PARTIAL_FLUSH' => 'zlib/zlib.stub', 'ZLIB_RLE' => 'zlib/zlib.stub', 'ZLIB_STREAM_END' => 'zlib/zlib.stub', 'ZLIB_STREAM_ERROR' => 'zlib/zlib.stub', 'ZLIB_SYNC_FLUSH' => 'zlib/zlib.stub', 'ZLIB_VERNUM' => 'zlib/zlib.stub', 'ZLIB_VERSION' => 'zlib/zlib.stub', 'ZLIB_VERSION_ERROR' => 'zlib/zlib.stub', 'ZSTD_COMPRESS_LEVEL_DEFAULT' => 'zstd/zstd.stub', 'ZSTD_COMPRESS_LEVEL_MAX' => 'zstd/zstd.stub', 'ZSTD_COMPRESS_LEVEL_MIN' => 'zstd/zstd.stub', '__CLASS__' => 'standard/basic.stub', '__COMPILER_HALT_OFFSET__' => 'standard/_standard_manual.stub', '__DIR__' => 'standard/basic.stub', '__FILE__' => 'standard/basic.stub', '__FUNCTION__' => 'standard/basic.stub', '__LINE__' => 'standard/basic.stub', '__METHOD__' => 'standard/basic.stub', '__NAMESPACE__' => 'standard/basic.stub', '__TRAIT__' => 'standard/basic.stub', '__class__' => 'standard/basic.stub', '__dir__' => 'standard/basic.stub', '__file__' => 'standard/basic.stub', '__function__' => 'standard/basic.stub', '__line__' => 'standard/basic.stub', '__method__' => 'standard/basic.stub', '__namespace__' => 'standard/basic.stub', '__trait__' => 'standard/basic.stub', 'ast\\AST_ARG_LIST' => 'ast/ast.stub', 'ast\\AST_ARRAY' => 'ast/ast.stub', 'ast\\AST_ARRAY_ELEM' => 'ast/ast.stub', 'ast\\AST_ARROW_FUNC' => 'ast/ast.stub', 'ast\\AST_ASSIGN' => 'ast/ast.stub', 'ast\\AST_ASSIGN_OP' => 'ast/ast.stub', 'ast\\AST_ASSIGN_REF' => 'ast/ast.stub', 'ast\\AST_ATTRIBUTE' => 'ast/ast.stub', 'ast\\AST_ATTRIBUTE_GROUP' => 'ast/ast.stub', 'ast\\AST_ATTRIBUTE_LIST' => 'ast/ast.stub', 'ast\\AST_BINARY_OP' => 'ast/ast.stub', 'ast\\AST_BREAK' => 'ast/ast.stub', 'ast\\AST_CALL' => 'ast/ast.stub', 'ast\\AST_CAST' => 'ast/ast.stub', 'ast\\AST_CATCH' => 'ast/ast.stub', 'ast\\AST_CATCH_LIST' => 'ast/ast.stub', 'ast\\AST_CLASS' => 'ast/ast.stub', 'ast\\AST_CLASS_CONST' => 'ast/ast.stub', 'ast\\AST_CLASS_CONST_DECL' => 'ast/ast.stub', 'ast\\AST_CLASS_CONST_GROUP' => 'ast/ast.stub', 'ast\\AST_CLASS_NAME' => 'ast/ast.stub', 'ast\\AST_CLONE' => 'ast/ast.stub', 'ast\\AST_CLOSURE' => 'ast/ast.stub', 'ast\\AST_CLOSURE_USES' => 'ast/ast.stub', 'ast\\AST_CLOSURE_VAR' => 'ast/ast.stub', 'ast\\AST_CONDITIONAL' => 'ast/ast.stub', 'ast\\AST_CONST' => 'ast/ast.stub', 'ast\\AST_CONST_DECL' => 'ast/ast.stub', 'ast\\AST_CONST_ELEM' => 'ast/ast.stub', 'ast\\AST_CONTINUE' => 'ast/ast.stub', 'ast\\AST_DECLARE' => 'ast/ast.stub', 'ast\\AST_DIM' => 'ast/ast.stub', 'ast\\AST_DO_WHILE' => 'ast/ast.stub', 'ast\\AST_ECHO' => 'ast/ast.stub', 'ast\\AST_EMPTY' => 'ast/ast.stub', 'ast\\AST_ENCAPS_LIST' => 'ast/ast.stub', 'ast\\AST_EXIT' => 'ast/ast.stub', 'ast\\AST_EXPR_LIST' => 'ast/ast.stub', 'ast\\AST_FOR' => 'ast/ast.stub', 'ast\\AST_FOREACH' => 'ast/ast.stub', 'ast\\AST_FUNC_DECL' => 'ast/ast.stub', 'ast\\AST_GLOBAL' => 'ast/ast.stub', 'ast\\AST_GOTO' => 'ast/ast.stub', 'ast\\AST_GROUP_USE' => 'ast/ast.stub', 'ast\\AST_HALT_COMPILER' => 'ast/ast.stub', 'ast\\AST_IF' => 'ast/ast.stub', 'ast\\AST_IF_ELEM' => 'ast/ast.stub', 'ast\\AST_INCLUDE_OR_EVAL' => 'ast/ast.stub', 'ast\\AST_INSTANCEOF' => 'ast/ast.stub', 'ast\\AST_ISSET' => 'ast/ast.stub', 'ast\\AST_LABEL' => 'ast/ast.stub', 'ast\\AST_LIST' => 'ast/ast.stub', 'ast\\AST_MAGIC_CONST' => 'ast/ast.stub', 'ast\\AST_MATCH' => 'ast/ast.stub', 'ast\\AST_MATCH_ARM' => 'ast/ast.stub', 'ast\\AST_MATCH_ARM_LIST' => 'ast/ast.stub', 'ast\\AST_METHOD' => 'ast/ast.stub', 'ast\\AST_METHOD_CALL' => 'ast/ast.stub', 'ast\\AST_METHOD_REFERENCE' => 'ast/ast.stub', 'ast\\AST_NAME' => 'ast/ast.stub', 'ast\\AST_NAMED_ARG' => 'ast/ast.stub', 'ast\\AST_NAMESPACE' => 'ast/ast.stub', 'ast\\AST_NAME_LIST' => 'ast/ast.stub', 'ast\\AST_NEW' => 'ast/ast.stub', 'ast\\AST_NULLABLE_TYPE' => 'ast/ast.stub', 'ast\\AST_NULLSAFE_METHOD_CALL' => 'ast/ast.stub', 'ast\\AST_NULLSAFE_PROP' => 'ast/ast.stub', 'ast\\AST_PARAM' => 'ast/ast.stub', 'ast\\AST_PARAM_LIST' => 'ast/ast.stub', 'ast\\AST_POST_DEC' => 'ast/ast.stub', 'ast\\AST_POST_INC' => 'ast/ast.stub', 'ast\\AST_PRE_DEC' => 'ast/ast.stub', 'ast\\AST_PRE_INC' => 'ast/ast.stub', 'ast\\AST_PRINT' => 'ast/ast.stub', 'ast\\AST_PROP' => 'ast/ast.stub', 'ast\\AST_PROP_DECL' => 'ast/ast.stub', 'ast\\AST_PROP_ELEM' => 'ast/ast.stub', 'ast\\AST_PROP_GROUP' => 'ast/ast.stub', 'ast\\AST_REF' => 'ast/ast.stub', 'ast\\AST_RETURN' => 'ast/ast.stub', 'ast\\AST_SHELL_EXEC' => 'ast/ast.stub', 'ast\\AST_STATIC' => 'ast/ast.stub', 'ast\\AST_STATIC_CALL' => 'ast/ast.stub', 'ast\\AST_STATIC_PROP' => 'ast/ast.stub', 'ast\\AST_STMT_LIST' => 'ast/ast.stub', 'ast\\AST_SWITCH' => 'ast/ast.stub', 'ast\\AST_SWITCH_CASE' => 'ast/ast.stub', 'ast\\AST_SWITCH_LIST' => 'ast/ast.stub', 'ast\\AST_THROW' => 'ast/ast.stub', 'ast\\AST_TRAIT_ADAPTATIONS' => 'ast/ast.stub', 'ast\\AST_TRAIT_ALIAS' => 'ast/ast.stub', 'ast\\AST_TRAIT_PRECEDENCE' => 'ast/ast.stub', 'ast\\AST_TRY' => 'ast/ast.stub', 'ast\\AST_TYPE' => 'ast/ast.stub', 'ast\\AST_TYPE_UNION' => 'ast/ast.stub', 'ast\\AST_UNARY_OP' => 'ast/ast.stub', 'ast\\AST_UNPACK' => 'ast/ast.stub', 'ast\\AST_UNSET' => 'ast/ast.stub', 'ast\\AST_USE' => 'ast/ast.stub', 'ast\\AST_USE_ELEM' => 'ast/ast.stub', 'ast\\AST_USE_TRAIT' => 'ast/ast.stub', 'ast\\AST_VAR' => 'ast/ast.stub', 'ast\\AST_WHILE' => 'ast/ast.stub', 'ast\\AST_YIELD' => 'ast/ast.stub', 'ast\\AST_YIELD_FROM' => 'ast/ast.stub', 'ast\\flags\\ARRAY_ELEM_REF' => 'ast/ast.stub', 'ast\\flags\\ARRAY_SYNTAX_LIST' => 'ast/ast.stub', 'ast\\flags\\ARRAY_SYNTAX_LONG' => 'ast/ast.stub', 'ast\\flags\\ARRAY_SYNTAX_SHORT' => 'ast/ast.stub', 'ast\\flags\\BINARY_ADD' => 'ast/ast.stub', 'ast\\flags\\BINARY_BITWISE_AND' => 'ast/ast.stub', 'ast\\flags\\BINARY_BITWISE_OR' => 'ast/ast.stub', 'ast\\flags\\BINARY_BITWISE_XOR' => 'ast/ast.stub', 'ast\\flags\\BINARY_BOOL_AND' => 'ast/ast.stub', 'ast\\flags\\BINARY_BOOL_OR' => 'ast/ast.stub', 'ast\\flags\\BINARY_BOOL_XOR' => 'ast/ast.stub', 'ast\\flags\\BINARY_COALESCE' => 'ast/ast.stub', 'ast\\flags\\BINARY_CONCAT' => 'ast/ast.stub', 'ast\\flags\\BINARY_DIV' => 'ast/ast.stub', 'ast\\flags\\BINARY_IS_EQUAL' => 'ast/ast.stub', 'ast\\flags\\BINARY_IS_GREATER' => 'ast/ast.stub', 'ast\\flags\\BINARY_IS_GREATER_OR_EQUAL' => 'ast/ast.stub', 'ast\\flags\\BINARY_IS_IDENTICAL' => 'ast/ast.stub', 'ast\\flags\\BINARY_IS_NOT_EQUAL' => 'ast/ast.stub', 'ast\\flags\\BINARY_IS_NOT_IDENTICAL' => 'ast/ast.stub', 'ast\\flags\\BINARY_IS_SMALLER' => 'ast/ast.stub', 'ast\\flags\\BINARY_IS_SMALLER_OR_EQUAL' => 'ast/ast.stub', 'ast\\flags\\BINARY_MOD' => 'ast/ast.stub', 'ast\\flags\\BINARY_MUL' => 'ast/ast.stub', 'ast\\flags\\BINARY_POW' => 'ast/ast.stub', 'ast\\flags\\BINARY_SHIFT_LEFT' => 'ast/ast.stub', 'ast\\flags\\BINARY_SHIFT_RIGHT' => 'ast/ast.stub', 'ast\\flags\\BINARY_SPACESHIP' => 'ast/ast.stub', 'ast\\flags\\BINARY_SUB' => 'ast/ast.stub', 'ast\\flags\\CLASS_ABSTRACT' => 'ast/ast.stub', 'ast\\flags\\CLASS_ANONYMOUS' => 'ast/ast.stub', 'ast\\flags\\CLASS_FINAL' => 'ast/ast.stub', 'ast\\flags\\CLASS_INTERFACE' => 'ast/ast.stub', 'ast\\flags\\CLASS_TRAIT' => 'ast/ast.stub', 'ast\\flags\\CLOSURE_USE_REF' => 'ast/ast.stub', 'ast\\flags\\DIM_ALTERNATIVE_SYNTAX' => 'ast/ast.stub', 'ast\\flags\\EXEC_EVAL' => 'ast/ast.stub', 'ast\\flags\\EXEC_INCLUDE' => 'ast/ast.stub', 'ast\\flags\\EXEC_INCLUDE_ONCE' => 'ast/ast.stub', 'ast\\flags\\EXEC_REQUIRE' => 'ast/ast.stub', 'ast\\flags\\EXEC_REQUIRE_ONCE' => 'ast/ast.stub', 'ast\\flags\\FUNC_GENERATOR' => 'ast/ast.stub', 'ast\\flags\\FUNC_RETURNS_REF' => 'ast/ast.stub', 'ast\\flags\\MAGIC_CLASS' => 'ast/ast.stub', 'ast\\flags\\MAGIC_DIR' => 'ast/ast.stub', 'ast\\flags\\MAGIC_FILE' => 'ast/ast.stub', 'ast\\flags\\MAGIC_FUNCTION' => 'ast/ast.stub', 'ast\\flags\\MAGIC_LINE' => 'ast/ast.stub', 'ast\\flags\\MAGIC_METHOD' => 'ast/ast.stub', 'ast\\flags\\MAGIC_NAMESPACE' => 'ast/ast.stub', 'ast\\flags\\MAGIC_TRAIT' => 'ast/ast.stub', 'ast\\flags\\MODIFIER_ABSTRACT' => 'ast/ast.stub', 'ast\\flags\\MODIFIER_FINAL' => 'ast/ast.stub', 'ast\\flags\\MODIFIER_PRIVATE' => 'ast/ast.stub', 'ast\\flags\\MODIFIER_PROTECTED' => 'ast/ast.stub', 'ast\\flags\\MODIFIER_PUBLIC' => 'ast/ast.stub', 'ast\\flags\\MODIFIER_STATIC' => 'ast/ast.stub', 'ast\\flags\\NAME_FQ' => 'ast/ast.stub', 'ast\\flags\\NAME_NOT_FQ' => 'ast/ast.stub', 'ast\\flags\\NAME_RELATIVE' => 'ast/ast.stub', 'ast\\flags\\PARAM_MODIFIER_PRIVATE' => 'ast/ast.stub', 'ast\\flags\\PARAM_MODIFIER_PROTECTED' => 'ast/ast.stub', 'ast\\flags\\PARAM_MODIFIER_PUBLIC' => 'ast/ast.stub', 'ast\\flags\\PARAM_REF' => 'ast/ast.stub', 'ast\\flags\\PARAM_VARIADIC' => 'ast/ast.stub', 'ast\\flags\\PARENTHESIZED_CONDITIONAL' => 'ast/ast.stub', 'ast\\flags\\RETURNS_REF' => 'ast/ast.stub', 'ast\\flags\\TYPE_ARRAY' => 'ast/ast.stub', 'ast\\flags\\TYPE_BOOL' => 'ast/ast.stub', 'ast\\flags\\TYPE_CALLABLE' => 'ast/ast.stub', 'ast\\flags\\TYPE_DOUBLE' => 'ast/ast.stub', 'ast\\flags\\TYPE_FALSE' => 'ast/ast.stub', 'ast\\flags\\TYPE_ITERABLE' => 'ast/ast.stub', 'ast\\flags\\TYPE_LONG' => 'ast/ast.stub', 'ast\\flags\\TYPE_MIXED' => 'ast/ast.stub', 'ast\\flags\\TYPE_NULL' => 'ast/ast.stub', 'ast\\flags\\TYPE_OBJECT' => 'ast/ast.stub', 'ast\\flags\\TYPE_STATIC' => 'ast/ast.stub', 'ast\\flags\\TYPE_STRING' => 'ast/ast.stub', 'ast\\flags\\TYPE_VOID' => 'ast/ast.stub', 'ast\\flags\\UNARY_BITWISE_NOT' => 'ast/ast.stub', 'ast\\flags\\UNARY_BOOL_NOT' => 'ast/ast.stub', 'ast\\flags\\UNARY_MINUS' => 'ast/ast.stub', 'ast\\flags\\UNARY_PLUS' => 'ast/ast.stub', 'ast\\flags\\UNARY_SILENCE' => 'ast/ast.stub', 'ast\\flags\\USE_CONST' => 'ast/ast.stub', 'ast\\flags\\USE_FUNCTION' => 'ast/ast.stub', 'ast\\flags\\USE_NORMAL' => 'ast/ast.stub', 'bgrBLACK' => 'winbinder/winbinder.stub', 'bgrBLUE' => 'winbinder/winbinder.stub', 'bgrCYAN' => 'winbinder/winbinder.stub', 'bgrDARKBLUE' => 'winbinder/winbinder.stub', 'bgrDARKCYAN' => 'winbinder/winbinder.stub', 'bgrDARKGRAY' => 'winbinder/winbinder.stub', 'bgrDARKGREEN' => 'winbinder/winbinder.stub', 'bgrDARKMAGENTA' => 'winbinder/winbinder.stub', 'bgrDARKRED' => 'winbinder/winbinder.stub', 'bgrDARKYELLOW' => 'winbinder/winbinder.stub', 'bgrGREEN' => 'winbinder/winbinder.stub', 'bgrLIGHTGRAY' => 'winbinder/winbinder.stub', 'bgrMAGENTA' => 'winbinder/winbinder.stub', 'bgrNOCOLOR' => 'winbinder/winbinder.stub', 'bgrRED' => 'winbinder/winbinder.stub', 'bgrWHITE' => 'winbinder/winbinder.stub', 'bgrYELLOW' => 'winbinder/winbinder.stub', 'false' => 'Core/Core_d.stub', 'http\\Client\\Curl\\AUTH_ANY' => 'http/http3.stub', 'http\\Client\\Curl\\AUTH_BASIC' => 'http/http3.stub', 'http\\Client\\Curl\\AUTH_DIGEST' => 'http/http3.stub', 'http\\Client\\Curl\\AUTH_DIGEST_IE' => 'http/http3.stub', 'http\\Client\\Curl\\AUTH_GSSNEG' => 'http/http3.stub', 'http\\Client\\Curl\\AUTH_NTLM' => 'http/http3.stub', 'http\\Client\\Curl\\AUTH_SPNEGO' => 'http/http3.stub', 'http\\Client\\Curl\\FEATURES' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\ASYNCHDNS' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\GSSAPI' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\GSSNEGOTIATE' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\HTTP2' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\IDN' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\IPV6' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\KERBEROS4' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\KERBEROS5' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\LARGEFILE' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\LIBZ' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\NTLM' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\NTLM_WB' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\PSL' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\SPNEGO' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\SSL' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\SSPI' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\TLSAUTH_SRP' => 'http/http3.stub', 'http\\Client\\Curl\\Features\\UNIX_SOCKETS' => 'http/http3.stub', 'http\\Client\\Curl\\HTTP_VERSION_1_0' => 'http/http3.stub', 'http\\Client\\Curl\\HTTP_VERSION_1_1' => 'http/http3.stub', 'http\\Client\\Curl\\HTTP_VERSION_2TLS' => 'http/http3.stub', 'http\\Client\\Curl\\HTTP_VERSION_2_0' => 'http/http3.stub', 'http\\Client\\Curl\\HTTP_VERSION_ANY' => 'http/http3.stub', 'http\\Client\\Curl\\IPRESOLVE_ANY' => 'http/http3.stub', 'http\\Client\\Curl\\IPRESOLVE_V4' => 'http/http3.stub', 'http\\Client\\Curl\\IPRESOLVE_V6' => 'http/http3.stub', 'http\\Client\\Curl\\POSTREDIR_301' => 'http/http3.stub', 'http\\Client\\Curl\\POSTREDIR_302' => 'http/http3.stub', 'http\\Client\\Curl\\POSTREDIR_303' => 'http/http3.stub', 'http\\Client\\Curl\\POSTREDIR_ALL' => 'http/http3.stub', 'http\\Client\\Curl\\PROXY_HTTP' => 'http/http3.stub', 'http\\Client\\Curl\\PROXY_HTTP_1_0' => 'http/http3.stub', 'http\\Client\\Curl\\PROXY_SOCKS4' => 'http/http3.stub', 'http\\Client\\Curl\\PROXY_SOCKS4A' => 'http/http3.stub', 'http\\Client\\Curl\\PROXY_SOCKS5' => 'http/http3.stub', 'http\\Client\\Curl\\PROXY_SOCKS5_HOSTNAME' => 'http/http3.stub', 'http\\Client\\Curl\\SSL_VERSION_ANY' => 'http/http3.stub', 'http\\Client\\Curl\\SSL_VERSION_SSLv2' => 'http/http3.stub', 'http\\Client\\Curl\\SSL_VERSION_SSLv3' => 'http/http3.stub', 'http\\Client\\Curl\\SSL_VERSION_TLSv1' => 'http/http3.stub', 'http\\Client\\Curl\\SSL_VERSION_TLSv1_0' => 'http/http3.stub', 'http\\Client\\Curl\\SSL_VERSION_TLSv1_1' => 'http/http3.stub', 'http\\Client\\Curl\\SSL_VERSION_TLSv1_2' => 'http/http3.stub', 'http\\Client\\Curl\\TLSAUTH_SRP' => 'http/http3.stub', 'http\\Client\\Curl\\VERSIONS' => 'http/http3.stub', 'http\\Client\\Curl\\Versions\\ARES' => 'http/http3.stub', 'http\\Client\\Curl\\Versions\\CURL' => 'http/http3.stub', 'http\\Client\\Curl\\Versions\\IDN' => 'http/http3.stub', 'http\\Client\\Curl\\Versions\\LIBZ' => 'http/http3.stub', 'http\\Client\\Curl\\Versions\\SSL' => 'http/http3.stub', 'null' => 'Core/Core_d.stub', 'pcov\\all' => 'pcov/pcov.stub', 'pcov\\exclusive' => 'pcov/pcov.stub', 'pcov\\inclusive' => 'pcov/pcov.stub', 'pcov\\version' => 'pcov/pcov.stub', 'true' => 'Core/Core_d.stub', 'yaf\\environ' => 'yaf/yaf_namespace.stub', 'yaf\\err\\autoload\\failed' => 'yaf/yaf_namespace.stub', 'yaf\\err\\call\\failed' => 'yaf/yaf_namespace.stub', 'yaf\\err\\dispatch\\failed' => 'yaf/yaf_namespace.stub', 'yaf\\err\\notfound\\action' => 'yaf/yaf_namespace.stub', 'yaf\\err\\notfound\\controller' => 'yaf/yaf_namespace.stub', 'yaf\\err\\notfound\\module' => 'yaf/yaf_namespace.stub', 'yaf\\err\\notfound\\view' => 'yaf/yaf_namespace.stub', 'yaf\\err\\route\\failed' => 'yaf/yaf_namespace.stub', 'yaf\\err\\startup\\failed' => 'yaf/yaf_namespace.stub', 'yaf\\err\\type\\error' => 'yaf/yaf_namespace.stub', 'yaf\\version' => 'yaf/yaf_namespace.stub', 'yaf_environ' => 'yaf/yaf.stub', 'yaf_err_autoload_failed' => 'yaf/yaf.stub', 'yaf_err_call_failed' => 'yaf/yaf.stub', 'yaf_err_dispatch_failed' => 'yaf/yaf.stub', 'yaf_err_notfound_action' => 'yaf/yaf.stub', 'yaf_err_notfound_controller' => 'yaf/yaf.stub', 'yaf_err_notfound_module' => 'yaf/yaf.stub', 'yaf_err_notfound_view' => 'yaf/yaf.stub', 'yaf_err_route_failed' => 'yaf/yaf.stub', 'yaf_err_startup_failed' => 'yaf/yaf.stub', 'yaf_err_type_error' => 'yaf/yaf.stub', 'yaf_version' => 'yaf/yaf.stub'); } https://secure.php.net/manual/en/reserved.variables.php */ $GLOBALS = []; /** * @xglobal $_COOKIE array * Variables provided to the script via HTTP cookies. Analogous to the old $HTTP_COOKIE_VARS array * (which is still available, but deprecated). * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $_COOKIE = []; /** * @xglobal $_ENV array * @xglobal $HTTP_ENV_VARS array * * Variables provided to the script via the environment. * Analogous to the old $HTTP_ENV_VARS array (which is still available, but deprecated). * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $_ENV = []; /** * @deprecated 4.1 * @removed 5.4 */ $HTTP_ENV_VARS = []; /** * @xglobal $_FILES array * @xglobal $HTTP_POST_FILES array * * Variables provided to the script via HTTP post file uploads. Analogous to the old $HTTP_POST_FILES array * (which is still available, but deprecated). * See POST method uploads for more information. * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $_FILES = []; /** * @deprecated 4.1 * @removed 5.4 */ $HTTP_POST_FILES = []; /** * @xglobal $_GET array * @xglobal $HTTP_GET_VARS array * * Variables provided to the script via URL query string. * Analogous to the old $HTTP_GET_VARS array (which is still available, but deprecated). * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $_GET = []; /** * @deprecated 4.1 * @removed 5.4 */ $HTTP_GET_VARS = []; /** * @xglobal $_POST array * @xglobal $HTTP_POST_VARS array * * Variables provided to the script via HTTP POST. Analogous to the old $HTTP_POST_VARS array * (which is still available, but deprecated). * @link https://secure.php.net/manual/en/language.variables.predefined.php * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $_POST = []; /** * @deprecated 4.1 * @removed 5.4 */ $HTTP_POST_VARS = []; /** * @xglobal $_REQUEST array * Variables provided to the script via the GET, POST, and COOKIE input mechanisms, * and which therefore cannot be trusted. * The presence and order of variable inclusion in this array is defined according to the * PHP variables_order configuration directive. * This array has no direct analogue in versions of PHP prior to 4.1.0. * See also import_request_variables(). *

    * Caution *

    Since PHP 4.3.0, FILE information from $_FILES does not exist in $_REQUEST. *

    * Note: When running on the command line , this will not include the argv and argc entries; these are present in the $_SERVER array. * * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $_REQUEST = []; /** * @xglobal $_SERVER array * @xglobal $HTTP_SERVER_VARS array * * Variables set by the web server or otherwise directly related to the execution environment of the current script. * Analogous to the old $HTTP_SERVER_VARS array (which is still available, but deprecated). * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $_SERVER = []; /** * @deprecated 4.1 * @removed 5.4 */ $HTTP_SERVER_VARS = []; $_SERVER['PHP_SELF'] = ''; $_SERVER['argv'] = ''; $_SERVER['argc'] = ''; $_SERVER['GATEWAY_INTERFACE'] = 'CGI/1.1'; $_SERVER['SERVER_ADDR'] = '127.0.0.1'; $_SERVER['SERVER_NAME'] = 'localhost'; $_SERVER['SERVER_SOFTWARE'] = ''; $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0'; $_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['REQUEST_TIME'] = 946713600; $_SERVER['REQUEST_TIME_FLOAT'] = 946713600.123456; $_SERVER['QUERY_STRING'] = ''; $_SERVER['DOCUMENT_ROOT'] = ''; $_SERVER['HTTP_ACCEPT'] = ''; $_SERVER['HTTP_ACCEPT_CHARSET'] = 'iso-8859-1,*,utf-8'; $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip'; $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en'; $_SERVER['HTTP_CONNECTION'] = 'Keep-Alive'; $_SERVER['HTTP_HOST'] = ''; $_SERVER['HTTP_REFERER'] = ''; $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586).'; $_SERVER['HTTPS'] = ''; $_SERVER['REMOTE_ADDR'] = ''; $_SERVER['REMOTE_HOST'] = ''; $_SERVER['REMOTE_PORT'] = ''; $_SERVER['REMOTE_USER'] = ''; $_SERVER['REDIRECT_REMOTE_USER'] = ''; $_SERVER['SCRIPT_FILENAME'] = ''; $_SERVER['SERVER_ADMIN'] = ''; $_SERVER['SERVER_PORT'] = '80'; $_SERVER['SERVER_SIGNATURE'] = ''; $_SERVER['PATH_TRANSLATED'] = ''; $_SERVER['SCRIPT_NAME'] = ''; $_SERVER['REQUEST_URI'] = '/index.html'; $_SERVER['PHP_AUTH_DIGEST'] = ''; $_SERVER['PHP_AUTH_USER'] = ''; $_SERVER['PHP_AUTH_PW'] = ''; $_SERVER['AUTH_TYPE'] = ''; $_SERVER['PATH_INFO'] = ''; $_SERVER['ORIG_PATH_INFO'] = ''; /** * @xglobal $_SESSION array * @xglobal $HTTP_SESSION_VARS array * * Variables which are currently registered to a script's session. * Analogous to the old $HTTP_SESSION_VARS array (which is still available, but deprecated). * See the Session handling functions section for more information. * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $_SESSION = []; /** * @deprecated 4.1 * @removed 5.4 */ $HTTP_SESSION_VARS = []; /** * @xglobal $argc int * @type int<1, max> * * The number of arguments passed to script * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $argc = 0; /** * @xglobal $argv array * * Array of arguments passed to script * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $argv = [1 + 1 => "a" . "b"]; /** * @xglobal $HTTP_RAW_POST_DATA string * * Raw POST data * *

    * https://secure.php.net/manual/en/reserved.variables.php * * @deprecated 5.6 Deprecated as of PHP 5.6.0. Use the php://input stream instead. * @removed 7.0 */ $HTTP_RAW_POST_DATA = ''; /** * @xglobal $http_response_header array * * HTTP response headers * *

    * https://secure.php.net/manual/en/reserved.variables.php */ $http_response_header = []; /** * @xglobal $php_errormsg string * The previous error message * *

    * https://secure.php.net/manual/en/reserved.variables.php * @deprecated 7.2 */ $php_errormsg = ''; * swoole_coroutine_create(function () { // The surrounding function of a coroutine. * echo '1'; * swoole_coroutine_defer(function () { // The callback function to be deferred. * echo '3'; * }); * echo '2'; * }); *

     */
    function swoole_coroutine_defer(callable $callback) {}
    
    /**
     * @param $domain[required]
     * @param $type[required]
     * @param $protocol[required]
     * @return mixed
     */
    function swoole_coroutine_socketpair($domain, $type, $protocol) {}
    
    /**
     * @param $count[optional]
     * @param $sleep_time[optional]
     * @return mixed
     */
    function swoole_test_kernel_coroutine($count = null, $sleep_time = null) {}
    
    /**
     * @param $read_array[required]
     * @param $write_array[required]
     * @param $error_array[required]
     * @param $timeout[optional]
     * @return mixed
     */
    function swoole_client_select(&$read_array, &$write_array, &$error_array, $timeout = null) {}
    
    /**
     * @param $read_array[required]
     * @param $write_array[required]
     * @param $error_array[required]
     * @param $timeout[optional]
     * @return mixed
     */
    function swoole_select(&$read_array, &$write_array, &$error_array, $timeout = null) {}
    
    /**
     * @param $process_name[required]
     * @return mixed
     */
    function swoole_set_process_name($process_name) {}
    
    /**
     * @return mixed
     */
    function swoole_get_local_ip() {}
    
    /**
     * @return mixed
     */
    function swoole_get_local_mac() {}
    
    /**
     * @param $errno[required]
     * @param $error_type[optional]
     * @return mixed
     */
    function swoole_strerror($errno, $error_type = null) {}
    
    /**
     * @return mixed
     */
    function swoole_errno() {}
    
    /**
     * @return mixed
     */
    function swoole_clear_error() {}
    
    /**
     * @return void
     */
    function swoole_error_log(int $level, string $msg) {}
    
    /**
     * @return void
     * @since 4.8.1
     */
    function swoole_error_log_ex(int $level, int $error, string $msg) {}
    
    /**
     * @return void
     * @since 4.8.1
     */
    function swoole_ignore_error(int $error) {}
    
    /**
     * @param $data[required]
     * @param $type[optional]
     * @return mixed
     */
    function swoole_hashcode($data, $type = null) {}
    
    /**
     * @param $suffix[required]
     * @param $mime_type[required]
     * @return mixed
     */
    function swoole_mime_type_add($suffix, $mime_type) {}
    
    /**
     * @param $suffix[required]
     * @param $mime_type[required]
     * @return mixed
     */
    function swoole_mime_type_set($suffix, $mime_type) {}
    
    /**
     * @param $suffix[required]
     * @return mixed
     */
    function swoole_mime_type_delete($suffix) {}
    
    /**
     * @param $filename[required]
     * @return mixed
     */
    function swoole_mime_type_get($filename) {}
    
    /**
     * @param $filename[required]
     * @return mixed
     */
    function swoole_get_mime_type($filename) {}
    
    /**
     * @param $filename[required]
     * @return mixed
     */
    function swoole_mime_type_exists($filename) {}
    
    /**
     * @return mixed
     */
    function swoole_mime_type_list() {}
    
    /**
     * @return mixed
     */
    function swoole_clear_dns_cache() {}
    
    /**
     * @param $str[required]
     * @param $offset[required]
     * @param $length[optional]
     * @param $options[optional]
     * @return mixed
     */
    function swoole_substr_unserialize($str, $offset, $length = null, $options = null) {}
    
    /**
     * @param $json[required]
     * @param $offset[required]
     * @param $length[optional]
     * @param $associative[optional]
     * @param $depth[optional]
     * @param $flags[optional]
     * @return mixed
     */
    function swoole_substr_json_decode($json, $offset, $length = null, $associative = null, $depth = null, $flags = null) {}
    
    /**
     * @return mixed
     */
    function swoole_internal_call_user_shutdown_begin() {}
    
    /**
     * Get all PHP objects of current call stack.
     *
     * @return array|false Return an array of objects back; return FALSE when no objects exist or when error happens.
     * @since 4.8.1
     */
    function swoole_get_objects() {}
    
    /**
     * Get status information of current call stack.
     *
     * @return array The array contains two fields: "object_num" (# of objects) and "resource_num" (# of resources).
     * @since 4.8.1
     */
    function swoole_get_vm_status() {}
    
    /**
     * @return array|false Return the specified object back; return FALSE when no object found or when error happens.
     * @since 4.8.1
     */
    function swoole_get_object_by_handle(int $handle) {}
    
    /**
     * This function is an alias of function swoole_coroutine_create(); it's available only when directive
     * "swoole.use_shortname" is not explicitly turned off.
     *
     * @return int|false
     * @see swoole_coroutine_create()
     */
    function go(callable $func, ...$params) {}
    
    /**
     * Defers the execution of a callback function until the surrounding function of a coroutine returns.
     *
     * This function is an alias of function swoole_coroutine_defer(); it's available only when directive
     * "swoole.use_shortname" is not explicitly turned off.
     *
     * @return void
     * @see swoole_coroutine_defer()
     *
     * @example
     * 
     * go(function () {      // The surrounding function of a coroutine.
     *   echo '1';
     *   defer(function () { // The callback function to be deferred.
     *     echo '3';
     *   });
     *   echo '2';
     * });
     * 
     */
    function defer(callable $callback) {}
    
    /**
     * @param $fd[required]
     * @param $read_callback[required]
     * @param $write_callback[optional]
     * @param $events[optional]
     * @return mixed
     */
    function swoole_event_add($fd, $read_callback, $write_callback = null, $events = null) {}
    
    /**
     * @param $fd[required]
     * @return mixed
     */
    function swoole_event_del($fd) {}
    
    /**
     * @param $fd[required]
     * @param $read_callback[optional]
     * @param $write_callback[optional]
     * @param $events[optional]
     * @return mixed
     */
    function swoole_event_set($fd, $read_callback = null, $write_callback = null, $events = null) {}
    
    /**
     * @param $fd[required]
     * @param $events[optional]
     * @return mixed
     */
    function swoole_event_isset($fd, $events = null) {}
    
    /**
     * @return mixed
     */
    function swoole_event_dispatch() {}
    
    /**
     * This function is an alias of method \Swoole\Event::defer().
     *
     * @return true
     * @see \Swoole\Event::defer()
     */
    function swoole_event_defer(callable $callback) {}
    
    /**
     * @param $callback[required]
     * @param $before[optional]
     * @return mixed
     */
    function swoole_event_cycle($callback, $before = null) {}
    
    /**
     * @param $fd[required]
     * @param $data[required]
     * @return mixed
     */
    function swoole_event_write($fd, $data) {}
    
    /**
     * @return mixed
     */
    function swoole_event_wait() {}
    
    /**
     * @return mixed
     */
    function swoole_event_exit() {}
    
    /**
     * This function is an alias of method \Swoole\Timer::set().
     *
     * @return void
     * @see \Swoole\Timer::set()
     */
    function swoole_timer_set(array $settings) {}
    
    /**
     * This function is an alias of method \Swoole\Timer::after().
     *
     * @return int
     * @see \Swoole\Timer::after()
     */
    function swoole_timer_after(int $ms, callable $callback, ...$params) {}
    
    /**
     * This function is an alias of method \Swoole\Timer::tick().
     *
     * @return int
     * @see \Swoole\Timer::tick()
     */
    function swoole_timer_tick(int $ms, callable $callback, ...$params) {}
    
    /**
     * This function is an alias of method \Swoole\Timer::exists().
     *
     * @return bool
     * @see \Swoole\Timer::exists()
     */
    function swoole_timer_exists(int $timer_id) {}
    
    /**
     * This function is an alias of method \Swoole\Timer::info().
     *
     * @return array
     * @see \Swoole\Timer::info()
     */
    function swoole_timer_info(int $timer_id) {}
    
    /**
     * This function is an alias of method \Swoole\Timer::stats().
     *
     * @return array
     * @see \Swoole\Timer::stats()
     */
    function swoole_timer_stats() {}
    
    /**
     * This function is an alias of method \Swoole\Timer::list().
     *
     * @return \Swoole\timer\Iterator
     * @see \Swoole\Timer::list()
     */
    function swoole_timer_list() {}
    
    /**
     * This function is an alias of method \Swoole\Timer::clear().
     *
     * @return bool
     * @see \Swoole\Timer::clear()
     */
    function swoole_timer_clear(int $timer_id) {}
    
    /**
     * This function is an alias of method \Swoole\Timer::clearAll().
     *
     * @return bool
     * @see \Swoole\Timer::clearAll()
     */
    function swoole_timer_clear_all() {}
    
     * The tested string.
     * 

    * @return bool TRUE if every character in text is either * a letter or a digit, FALSE otherwise. */ #[Pure] function ctype_alnum(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for alphabetic character(s) * @link https://php.net/manual/en/function.ctype-alpha.php * @param string $text

    * The tested string. *

    * @return bool TRUE if every character in text is * a letter from the current locale, FALSE otherwise. */ #[Pure] function ctype_alpha(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for control character(s) * @link https://php.net/manual/en/function.ctype-cntrl.php * @param string $text

    * The tested string. *

    * @return bool TRUE if every character in text is * a control character from the current locale, FALSE otherwise. */ #[Pure] function ctype_cntrl(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for numeric character(s) * @link https://php.net/manual/en/function.ctype-digit.php * @param string $text

    * The tested string. *

    * @return bool TRUE if every character in the string * text is a decimal digit, FALSE otherwise. */ #[Pure] function ctype_digit(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for lowercase character(s) * @link https://php.net/manual/en/function.ctype-lower.php * @param string $text

    * The tested string. *

    * @return bool TRUE if every character in text is * a lowercase letter in the current locale. */ #[Pure] function ctype_lower(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for any printable character(s) except space * @link https://php.net/manual/en/function.ctype-graph.php * @param string $text

    * The tested string. *

    * @return bool TRUE if every character in text is * printable and actually creates visible output (no white space), FALSE * otherwise. */ #[Pure] function ctype_graph(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for printable character(s) * @link https://php.net/manual/en/function.ctype-print.php * @param string $text

    * The tested string. *

    * @return bool 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. */ #[Pure] function ctype_print(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for any printable character which is not whitespace or an * alphanumeric character * @link https://php.net/manual/en/function.ctype-punct.php * @param string $text

    * The tested string. *

    * @return bool TRUE if every character in text * is printable, but neither letter, digit or blank, FALSE otherwise. */ #[Pure] function ctype_punct(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for whitespace character(s) * @link https://php.net/manual/en/function.ctype-space.php * @param string $text

    * The tested string. *

    * @return bool 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. */ #[Pure] function ctype_space(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for uppercase character(s) * @link https://php.net/manual/en/function.ctype-upper.php * @param string $text

    * The tested string. *

    * @return bool TRUE if every character in text is * an uppercase letter in the current locale. */ #[Pure] function ctype_upper(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} /** * Check for character(s) representing a hexadecimal digit * @link https://php.net/manual/en/function.ctype-xdigit.php * @param string $text

    * The tested string. *

    * @return bool TRUE if every character in text is * a hexadecimal 'digit', that is a decimal digit or a character from * [A-Fa-f] , FALSE otherwise. */ #[Pure] function ctype_xdigit(#[LanguageLevelTypeAware(['8.1' => 'string'], default: 'mixed')] mixed $text): bool {} Used to specify if {@link sqlsrv_errors() sqlsrv_errors} returns errors, warnings, or both.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_ERR_ERRORS', 0); /** * Warnings generated on the last sqlsrv function call are returned. * *
    Used to specify if {@link sqlsrv_errors() sqlsrv_errors} returns errors, warnings, or both.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_ERR_WARNINGS', 1); /** * Errors and warnings generated on the last sqlsrv function call are returned. * *
    This is the default value.
    * * Used to specify if {@link sqlsrv_errors() sqlsrv_errors} returns errors, warnings, or both.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_ERR_ALL', 2); /** * Turns on logging of all subsystems. * *
    Used as the value for the LogSubsystems setting with * {@link sqlsrv_configure() sqlsrv_configure}.
    * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SYSTEM_ALL', -1); /** * Turns logging off. * *
    Used as the value for the LogSubsystems setting with {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SYSTEM_OFF', 0); /** * Turns on logging of initialization activity. * *
    Used as the value for the LogSubsystems setting with {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SYSTEM_INIT', 1); /** * Turns on logging of connection activity. * *
    Used as the value for the LogSubsystems setting with {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SYSTEM_CONN', 2); /** * Turns on logging of statement activity. * *
    Used as the value for the LogSubsystems setting with {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SYSTEM_STMT', 4); /** * Turns on logging of error functions activity (such as handle_error and handle_warning). * *
    Used as the value for the * LogSubsystems setting with {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SYSTEM_UTIL', 8); /** * Specifies that errors, warnings, and notices will be logged. * *
    Used as the value for the LogSeverity setting with {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SEVERITY_ALL', -1); /** * Specifies that errors will be logged. * *
    Used as the value for the LogSeverity setting with {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SEVERITY_ERROR', 1); /** * Specifies that notices will be logged. * *
    Used as the value for the LogSeverity setting with {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SEVERITY_NOTICE', 4); /** * Specifies that warnings will be logged. * *
    Used as the value for the LogSeverity setting with {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_LOG_SEVERITY_WARNING', 2); /** * Returns numerically indexed array. * *
    {@link sqlsrv_fetch_array() sqlsrv_fetch_array} returns the next row of data as a numerically indexed array.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_FETCH_NUMERIC', 1); /** * Returns an associative array. * *
    {@link sqlsrv_fetch_array() sqlsrv_fetch_array} returns the next row of data as an associative array.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_FETCH_ASSOC', 2); /** * Returns both a numeric and associative array. * *
    {@link sqlsrv_fetch_array() sqlsrv_fetch_array} returns the next row of data as an array with both numeric and * associative keys.
    * * This is the default value.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_FETCH_BOTH', 3); /** * Null * *
    Used with {@link sqlsrv_prepare() sqlsrv_prepare}, * {@link sqlsrv_query() sqlsrv_query} * and {@link sqlsrv_get_field() sqlsrv_get_field} to request a field be return as a specific PHP type.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_PHPTYPE_NULL', 1); /** * Integer * *
    Used with {@link sqlsrv_prepare() sqlsrv_prepare}, * {@link sqlsrv_query() sqlsrv_query} * and {@link sqlsrv_get_field() sqlsrv_get_field} to request a field be return as a specific PHP type.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_PHPTYPE_INT', 2); /** * Float * *
    Used with {@link sqlsrv_prepare() sqlsrv_prepare}, * {@link sqlsrv_query() sqlsrv_query} * and {@link sqlsrv_get_field() sqlsrv_get_field} to request a field be return as a specific PHP type.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_PHPTYPE_FLOAT', 3); /** * Datetime * *
    Used with {@link sqlsrv_prepare() sqlsrv_prepare}, * {@link sqlsrv_query() sqlsrv_query} * and {@link sqlsrv_get_field() sqlsrv_get_field} to request a field be return as a specific PHP type.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_PHPTYPE_DATETIME', 4); /** * Binary Encoding * *
    Data is returned as a raw byte stream from the server without performing encoding or translation.
    * * Used with {@link sqlsrv_prepare() sqlsrv_prepare}, * {@link sqlsrv_query() sqlsrv_query} * and {@link sqlsrv_get_field() sqlsrv_get_field} to request a field be return as a specific PHP type.
    * * This is used with {@link SQLSRV_PHPTYPE_STREAM() SQLSRV_PHPTYPE_STREAM} and * {@link SQLSRV_PHPTYPE_STRING() SQLSRV_PHPTYPE_STRING} to specify the encoding of those PHP types types.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_ENC_BINARY', 'binary'); /** * Character Encoding * *
    Data is returned in 8-bit characters as specified in the code page of the Windows locale that is set on the * system. Any multi-byte characters or characters that do not map into this code page are substituted with a single * byte question mark (?) character.
    * * This is the default encoding.
    * * Used with {@link sqlsrv_prepare() sqlsrv_prepare}, * {@link sqlsrv_query() sqlsrv_query} * and {@link sqlsrv_get_field() sqlsrv_get_field} to request a field be return as a specific PHP type.
    * * This is used with {@link SQLSRV_PHPTYPE_STREAM() SQLSRV_PHPTYPE_STREAM} and * {@link SQLSRV_PHPTYPE_STRING() SQLSRV_PHPTYPE_STRING} to specify the encoding of those PHP types types.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_ENC_CHAR', 'char'); /** * The column is not nullable. * *
    You can compare the value of the Nullable key that is returned by * {@link sqlsrv_field_metadata() sqlsrv_field_metadata} to determine the column's nullable status.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_NULLABLE_NO', 0); /** * The column is nullable. * *
    You can compare the value of the Nullable key that is returned by * {@link sqlsrv_field_metadata() sqlsrv_field_metadata} to determine the column's nullable status.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_NULLABLE_YES', 1); /** * It is not known if the column is nullable. * *
    You can compare the value of the Nullable key that is returned by * {@link sqlsrv_field_metadata() sqlsrv_field_metadata} to determine the column's nullable status.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_NULLABLE_UNKNOWN', 2); /** * bigint. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_BIGINT', -5); /** * bit. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_BIT', -7); /** * char. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_CHAR', 1); /** * datetime. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_DATETIME', 25177693); /** * decimal. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_DECIMAL', 3); /** * float. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_FLOAT', 6); /** * image. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_IMAGE', -4); /** * int. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_INT', 4); /** * money. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_MONEY', 33564163); /** * nchar. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_NCHAR', -8); /** * ntext. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_NTEXT', -10); /** * numeric. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_NUMERIC', 2); /** * nvarchar. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_NVARCHAR', -9); /** * text. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_TEXT', -1); /** * real. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_REAL', 7); /** * smalldatetime. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_SMALLDATETIME', 8285); /** * smallint. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_SMALLINT', 5); /** * smallmoney. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_SMALLMONEY', 33559555); /** * timestamp. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_TIMESTAMP', 4606); /** * tinyint. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_TINYINT', -6); /** * udt. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_UDT', -151); /** * uniqueidentifier. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_UNIQUEIDENTIFIER', -11); /** * varbinary. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_VARBINARY', -3); /** * varchar. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_VARCHAR', 12); /** * xml. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_XML', -152); /** * date. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_DATE', 5211); /** * time. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_TIME', 58728806); /** * datetimeoffset. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_DATETIMEOFFSET', 58738021); /** * datetime2. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the SQL Server data type of a parameter.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SQLTYPE_DATETIME2', 58734173); /** * Indicates an input parameter. * *
    Used for specifying parameter direction when you call {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_PARAM_IN', 1); /** * Indicates a bidirectional parameter. * *
    Used for specifying parameter direction when you call {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_PARAM_INOUT', 2); /** * Indicates an output parameter. * *
    Used for specifying parameter direction when you call {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_PARAM_OUT', 4); /** * Read Uncommitted. * *
    Specifies that statements can read rows that have been modified by other transactions but not yet committed.
    * * Transactions running at the READ UNCOMMITTED level do not issue shared locks to prevent other transactions from * modifying data read by the current transaction. READ UNCOMMITTED transactions are also not blocked by exclusive locks * that would prevent the current transaction from reading rows that have been modified but not committed by other * transactions. When this option is set, it is possible to read uncommitted modifications, which are called dirty reads. * Values in the data can be changed and rows can appear or disappear in the data set before the end of the transaction. * This option has the same effect as setting NOLOCK on all tables in all SELECT statements in a transaction. This is * the least restrictive of the isolation levels.
    * * Used with the TransactionIsolation key when calling {@link sqlsrv_connect() sqlsrv_connect}. For information on using * these constants, see {@link http://msdn.microsoft.com/en-us/library/ms173763(v=sql.110).aspx SET TRANSACTION ISOLATION LEVEL (Transact-SQL)}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_TXN_READ_UNCOMMITTED', 1); /** * Read Committed. * *
    Specifies that statements cannot read data that has been modified but not committed by other transactions. * This prevents dirty reads. Data can be changed by other transactions between individual statements within the current * transaction, resulting in nonrepeatable reads or phantom data. This option is the SQL Server default.
    * * The behavior of READ COMMITTED depends on the setting of the READ_COMMITTED_SNAPSHOT database option.
    * * Used with the TransactionIsolation key when calling {@link sqlsrv_connect() sqlsrv_connect}. For information on using * these constants, see {@link http://msdn.microsoft.com/en-us/library/ms173763(v=sql.110).aspx SET TRANSACTION ISOLATION LEVEL (Transact-SQL)}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_TXN_READ_COMMITTED', 2); /** * Repeatable Read. * *
    Specifies that statements cannot read data that has been modified but not yet committed by other transactions and * that no other transactions can modify data that has been read by the current transaction until the current transaction * completes.
    * * Shared locks are placed on all data read by each statement in the transaction and are held until the transaction * completes. This prevents other transactions from modifying any rows that have been read by the current transaction. * Other transactions can insert new rows that match the search conditions of statements issued by the current transaction. * If the current transaction then retries the statement it will retrieve the new rows, which results in phantom reads. * Because shared locks are held to the end of a transaction instead of being released at the end of each statement, * concurrency is lower than the default READ COMMITTED isolation level.
    * * Use this option only when necessary.
    * * Used with the TransactionIsolation key when calling {@link sqlsrv_connect() sqlsrv_connect}. For information on using * these constants, see {@link http://msdn.microsoft.com/en-us/library/ms173763(v=sql.110).aspx SET TRANSACTION ISOLATION LEVEL (Transact-SQL)}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_TXN_REPEATABLE_READ', 4); /** * Serializable. * *
    Specifies the following: *
    • Statements cannot read data that has been modified but not yet committed by other transactions.
    • *
    • No other transactions can modify data that has been read by the current transaction until the current * transaction completes.
    • *
    • Other transactions cannot insert new rows with key values that would fall in the range of keys read by any * statements in the current transaction until the current transaction completes.
    * * Range locks are placed in the range of key values that match the search conditions of each statement executed in a * transaction. This blocks other transactions from updating or inserting any rows that would qualify for any of the * statements executed by the current transaction. This means that if any of the statements in a transaction are * executed a second time, they will read the same set of rows. The range locks are held until the transaction completes. * This is the most restrictive of the isolation levels because it locks entire ranges of keys and holds the locks until * the transaction completes. Because concurrency is lower, use this option only when necessary. This option has the same * effect as setting HOLDLOCK on all tables in all SELECT statements in a transaction.
    * * Used with the TransactionIsolation key when calling {@link sqlsrv_connect() sqlsrv_connect}. For information on using * these constants, see {@link http://msdn.microsoft.com/en-us/library/ms173763(v=sql.110).aspx SET TRANSACTION ISOLATION LEVEL (Transact-SQL)}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_TXN_SERIALIZABLE', 8); /** * Snapshot. * *
    Specifies that data read by any statement in a transaction will be the transactionally consistent version of * the data that existed at the start of the transaction. The transaction can only recognize data modifications that * were committed before the start of the transaction. Data modifications made by other transactions after the start of * the current transaction are not visible to statements executing in the current transaction. The effect is as if the * statements in a transaction get a snapshot of the committed data as it existed at the start of the transaction.
    * * Except when a database is being recovered, SNAPSHOT transactions do not request locks when reading data. SNAPSHOT * transactions reading data do not block other transactions from writing data. Transactions writing data do not block * SNAPSHOT transactions from reading data.
    * * During the roll-back phase of a database recovery, SNAPSHOT transactions will request a lock if an attempt is made to * read data that is locked by another transaction that is being rolled back. The SNAPSHOT transaction is blocked until * that transaction has been rolled back. The lock is released immediately after it has been granted.
    * * The ALLOW_SNAPSHOT_ISOLATION database option must be set to ON before you can start a transaction that uses the * SNAPSHOT isolation level. If a transaction using the SNAPSHOT isolation level accesses data in multiple databases, * ALLOW_SNAPSHOT_ISOLATION must be set to ON in each database.
    * * A transaction cannot be set to SNAPSHOT isolation level that started with another isolation level; doing so will * cause the transaction to abort. If a transaction starts in the SNAPSHOT isolation level, you can change it to another * isolation level and then back to SNAPSHOT. A transaction starts the first time it accesses data.
    * * A transaction running under SNAPSHOT isolation level can view changes made by that transaction. For example, if the * transaction performs an UPDATE on a table and then issues a SELECT statement against the same table, the modified * data will be included in the result set.
    * * Used with the TransactionIsolation key when calling {@link sqlsrv_connect() sqlsrv_connect}. For information on using * these constants, see {@link http://msdn.microsoft.com/en-us/library/ms173763(v=sql.110).aspx SET TRANSACTION ISOLATION LEVEL (Transact-SQL)}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_TXN_SNAPSHOT', 32); /** * Specifies the next row. * *
    This is the default value, if you do not specify the row parameter for a scrollable result set.
    * * Used with {@link sqlsrv_fetch() sqlsrv_fetch}, * {@link sqlsrv_fetch_array() sqlsrv_fetch_array}, * or {@link sqlsrv_fetch_object() sqlsrv_fetch_object} to specify a row.
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify which row to select in the result set. For * information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SCROLL_NEXT', 1); /** * Specifies the row before the current row. * *
    Used with {@link sqlsrv_fetch() sqlsrv_fetch}, * {@link sqlsrv_fetch_array() sqlsrv_fetch_array}, * or {@link sqlsrv_fetch_object() sqlsrv_fetch_object} to specify a row.
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify which row to select in the result set. For * information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SCROLL_PRIOR', 4); /** * Specifies the first row in the result set. * *
    Used with {@link sqlsrv_fetch() sqlsrv_fetch}, * {@link sqlsrv_fetch_array() sqlsrv_fetch_array}, * or {@link sqlsrv_fetch_object() sqlsrv_fetch_object} to specify a row.
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify which row to select in the result set. For * information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SCROLL_FIRST', 2); /** * Specifies the last row in the result set. * *
    Used with {@link sqlsrv_fetch() sqlsrv_fetch}, * {@link sqlsrv_fetch_array() sqlsrv_fetch_array}, * or {@link sqlsrv_fetch_object() sqlsrv_fetch_object} to specify a row.
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify which row to select in the result set. For * information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SCROLL_LAST', 3); /** * Specifies the row specified with the offset parameter. * *
    Used with {@link sqlsrv_fetch() sqlsrv_fetch}, * {@link sqlsrv_fetch_array() sqlsrv_fetch_array}, * or {@link sqlsrv_fetch_object() sqlsrv_fetch_object} to specify a row.
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify which row to select in the result set. For * information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SCROLL_ABSOLUTE', 5); /** * Specifies the row specified with the offset parameter from the current row. * *
    Used with {@link sqlsrv_fetch() sqlsrv_fetch}, * {@link sqlsrv_fetch_array() sqlsrv_fetch_array}, * or {@link sqlsrv_fetch_object() sqlsrv_fetch_object} to specify a row.
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify which row to select in the result set. For * information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_SCROLL_RELATIVE', 6); /** * Lets you move one row at a time starting at the first row of the result set until you reach the end of * the result set. * *
    This is the default cursor type.
    * * {@link sqlsrv_num_rows() sqlsrv_num_rows} returns an error for result sets created with this cursor type.
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the kind of cursor that you can use in a result * set. For information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_CURSOR_FORWARD', 'forward'); /** * Lets you access rows in any order but will not reflect changes in the database. * *
    Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the kind of cursor that you can use in a result * set. For information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_CURSOR_STATIC', 'static'); /** * Lets you access rows in any order and will reflect changes in the database. * *
    {@link sqlsrv_num_rows() sqlsrv_num_rows} returns an error for result sets created with this cursor type.
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the kind of cursor that you can use in a result * set. For information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_CURSOR_DYNAMIC', 'dynamic'); /** * Lets you access rows in any order. * *
    However, a keyset cursor does not update the row count if a row is deleted from the table (a deleted row is * returned with no values).
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the kind of cursor that you can use in a result * set. For information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_CURSOR_KEYSET', 'keyset'); /** * Lets you access rows in any order. * *
    Creates a client-side cursor query.
    * * Used when calling {@link sqlsrv_query() sqlsrv_query} or *{@link sqlsrv_prepare() sqlsrv_prepare} to specify the kind of cursor that you can use in a result * set. For information on using these constants, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server */ define('SQLSRV_CURSOR_CLIENT_BUFFERED', 'buffered'); /** * Creates and opens a connection. * *
    Creates a connection resource and opens a connection. By default, the connection is attempted using Windows * Authentication.
    * * If values for the UID and PWD keys are not specified in the optional $connectionInfo parameter, the connection will * be attempted using Windows Authentication. For more information about connecting to the server, * see {@link http://msdn.microsoft.com/en-us/library/cc296205.aspx How to: Connect Using Windows Authentication} * and {@link http://msdn.microsoft.com/en-us/library/cc296182.aspx How to: Connect Using SQL Server Authentication.}
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-connect * @param string $server_name A string specifying the name of the server to which a connection is being established. * An instance name (for example, "myServer\instanceName") or port number (for example, "myServer, 1521") can be * included as part of this string. For a complete description of the options available for this parameter, see the * Server keyword in the ODBC Driver Connection String Keywords section * of {@link http://go.microsoft.com/fwlink/?LinkId=105504 Using Connection String Keywords with SQL Native Client}.
    * * Beginning in version 3.0 of the Microsoft Drivers for PHP for SQL Server, you can also specify a LocalDB instance * with "(localdb)\instancename". For more information, * see {@link http://msdn.microsoft.com/en-us/library/hh487161.aspx PHP Driver for SQL Server Support for LocalDB} .
    * * Also beginning in version 3.0 of the Microsoft Drivers for PHP for SQL Server, you can specify a virtual network name, * to connect to an AlwaysOn availability group. For more information about Microsoft Drivers for PHP for SQL Server * support for AlwaysOn Availability Groups, * see {@link http://msdn.microsoft.com/en-us/library/hh487159.aspx PHP Driver for SQL Server Support for High Availability, Disaster Recovery}. * @param array $connection_info [optional] An associative array that contains connection attributes (for example, array("Database" => "AdventureWorks")). * See {@link http://msdn.microsoft.com/en-us/library/ff628167.aspx Connection Options} for a list of the supported keys for the array. * @return resource|false A PHP connection resource. If a connection cannot be successfully created and opened, false is returned. */ function sqlsrv_connect($server_name, $connection_info = []) {} /** * Closes a connection. Frees all resources associated with the connection. * *
    Null is a valid parameter for this function. This allows the function to be called multiple times in a script. For * example, if you close a connection in an error condition and close it again at the end of the script, the second call * to sqlsrv_close will return true because the first call to sqlsrv_close (in the error condition) sets the connection * resource to null.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-close * @param resource|null $conn The connection to be closed. * @return bool The Boolean value true unless the function is called with an invalid parameter. If the function is called with an invalid parameter, false is returned. */ function sqlsrv_close($conn) {} /** * Commits a transaction that was begun with sqlsrv_begin_transaction. * *
    Commits the current transaction on the specified connection and returns the connection to the auto-commit mode. * The current transaction includes all statements on the specified connection that were executed after the call to * sqlsrv_begin_transaction and before any calls to sqlsrv_rollback or sqlsrv_commit.
    * * The Microsoft Drivers for PHP for SQL Server is in auto-commit mode by default. This means that all queries are * automatically committed upon success unless they have been designated as part of an explicit transaction by using * sqlsrv_begin_transaction.
    * * If sqlsrv_commit is called on a connection that is not in an active transaction and that was initiated with * sqlsrv_begin_transaction, the call returns false and a Not in Transaction error is added to the error collection.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-commit * @param resource $conn The connection on which the transaction is active. * @return bool A Boolean value: true if the transaction was successfully committed. Otherwise, false. */ function sqlsrv_commit($conn) {} /** * Begins a database transaction. * *
    Begins a transaction on a specified connection. The current transaction includes all statements on the specified * connection that were executed after the call to sqlsrv_begin_transaction and before any calls to sqlsrv_rollback or * sqlsrv_commit.
    * * The Microsoft Drivers for PHP for SQL Server is in auto-commit mode by default. This means that all queries are * automatically committed upon success unless they have been designated as part of an explicit transaction by using * sqlsrv_begin_transaction.
    * * If sqlsrv_begin_transaction is called after a transaction has already been initiated on the connection but not * completed by calling either sqlsrv_commit or sqlsrv_rollback, the call returns false and an Already in Transaction * error is added to the error collection.
    * * Do not use embedded Transact-SQL to perform transactions. For example, do not execute a statement with * "BEGIN TRANSACTION" as the Transact-SQL query to begin a transaction. The expected transactional behavior cannot be * guaranteed when using embedded Transact-SQL to perform transactions.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296206.aspx How to Perform Transactions} * and {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-begin-transaction * @param resource $conn The connection with which the transaction is associated. * @return bool A Boolean value: true if the transaction was successfully begun. Otherwise, false. */ function sqlsrv_begin_transaction($conn) {} /** * Rolls back a transaction that was begun with {@see sqlsrv_begin_transaction}. * *
    Rolls back the current transaction on the specified connection and returns the connection to the auto-commit mode. * The current transaction includes all statements on the specified connection that were executed after the call to * sqlsrv_begin_transaction and before any calls to {@link sqlsrv_rollback() sqlsrv_rollback} or * {@link sqlsrv_commit() sqlsrv_commit}.
    * * The Microsoft Drivers for PHP for SQL Server is in auto-commit mode by default. This means that all queries are * automatically committed upon success unless they have been designated as part of an explicit transaction by using * {@link sqlsrv_begin_transaction() sqlsrv_begin_transaction}.
    * * If sqlsrv_rollback is called on a connection that is not in an active transaction that was initiated with * {@link sqlsrv_begin_transaction() sqlsrv_begin_transaction}, the call returns false and a Not in Transaction error * is added to the error collection.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296206.aspx How to Perform Transactions} * and {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-rollback * @param resource $conn The connection on which the transaction is active. * @return bool A Boolean value: true if the transaction was successfully rolled back. Otherwise, false. */ function sqlsrv_rollback($conn) {} /** * Returns error and/or warning information about the last operation. * *
    Returns extended error and/or warning information about the last sqlsrv operation performed.
    * * The sqlsrv_errors function can return error and/or warning information by calling it with one of the parameter values * specified in the Parameters section below.
    * * By default, warnings generated on a call to any sqlsrv function are treated as errors; if a warning occurs on a call * to a sqlsrv function, the function returns false. However, warnings that correspond to SQLSTATE values 01000, 01001, * 01003, and 01S02 are never treated as errors.
    * * The following line of code turns off the behavior mentioned above; a warning generated by a call to a sqlsrv function * does not cause the function to return false:
    * * {@link sqlsrv_configure() sqlsrv_configure}("WarningsReturnAsErrors", 0); * * The following line of code reinstates the default behavior; warnings (with exceptions, noted above) are treated as * errors:
    * * {@link sqlsrv_configure() sqlsrv_configure}("WarningsReturnAsErrors", 1); * * Regardless of the setting, warnings can only be retrieved by calling sqlsrv_errors with either the SQLSRV_ERR_ALL or * SQLSRV_ERR_WARNINGS parameter value (see Parameters section below for details).
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-errors * @param int $errorsAndOrWarnings [optional] A predefined constant. This parameter can take one of the values in the * following list: SQLSRV_ERR_ALL, SQLSRV_ERR_ERRORS, SQLSRV_ERR_WARNINGS. If no parameter value is supplied, both * errors and warnings generated by the last sqlsrv function call are returned. * @return array|null An array of arrays, or null. Each array in the returned array contains three key-value pairs. The * following table lists each key and its description:
    * SQLSTATE: *
      *
    • For errors that originate from the ODBC driver, the SQLSTATE returned by ODBC.For information about SQLSTATE * values for ODBC, see {@link http://go.microsoft.com/fwlink/?linkid=119618 ODBC Error Codes}.
    • *
    • For errors that originate from the Microsoft Drivers for PHP for SQL Server, a SQLSTATE of IMSSP.
    • *
    • For warnings that originate from the Microsoft Drivers for PHP for SQL Server, a SQLSTATE of 01SSP.
    • *
    * code: *
      *
    • For errors that originate from SQL Server, the native SQL Server error code.
    • *
    • For errors that originate from the ODBC driver, the error code returned by ODBC.
    • *
    • For errors that originate from the Microsoft Drivers for PHP for SQL Server, the Microsoft Drivers for PHP for SQL Server error code. For more information, see {@link http://msdn.microsoft.com/en-us/library/cc626302.aspx Handling Errors and Warnings}.
    • *
    * message: A description of the error.
    * * The array values can also be accessed with numeric keys 0, 1, and 2.

    * * If no errors or warnings occur, null is returned.
    */ function sqlsrv_errors($errorsAndOrWarnings = SQLSRV_ERR_ALL) {} /** * Changes the driver error handling and logging configurations. * *
    Changes the settings for error handling and logging options.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-configure * @param string $setting The name of the setting to be configured. See table below for list of settings. * @param mixed $value The value to be applied to the setting specified in the $setting parameter. The possible values for this parameter depend on which setting is specified. The following table lists the possible combinations.
    * ClientBufferMaxKBSize (Default: 10240)
    * For more information about client-side queries, see {@link http://msdn.microsoft.com/en-us/library/hh487160.aspx Cursor Types (SQLSRV Driver)}. *
      *
    • A non negative number up to the PHP memory limit.
    • *
    • Zero (0) means no limit to the buffer size.
    • *
    * LogSeverity (Default: SQLSRV_LOG_SEVERITY_ERROR )
    * For more information about logging activity, see {@link http://msdn.microsoft.com/en-us/library/cc296188.aspx Logging Activity}. *
    • SQLSRV_LOG_SEVERITY_ALL (-1)
    • *
    • SQLSRV_LOG_SEVERITY_ERROR (1)
    • *
    • SQLSRV_LOG_SEVERITY_NOTICE (4)
    • *
    • SQLSRV_LOG_SEVERITY_WARNING (2)
    * WarningsReturnAsErrors (Default: true )
    * For more information about configuring error and warning handling, see {@link http://msdn.microsoft.com/en-us/library/cc626306.aspx How to: Configure Error and Warning Handling Using the SQLSRV Driver}. *
    • true (1)
    • *
    • false (0)
    * @return bool If sqlsrv_configure is called with an unsupported setting or value, the function returns false. Otherwise, the function returns true. */ function sqlsrv_configure($setting, $value) {} /** * Returns the current value of the specified configuration setting. * *
    If false is returned by sqlsrv_get_config, you must call {@link sqlsrv_errors() sqlsrv_errors} to determine if an error occurred or * if false is the value of the setting specified by the $setting parameter.
    * * For a list of configurable settings, see {@link sqlsrv_configure() sqlsrv_configure}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-get-config * @param string $setting The configuration setting for which the value is returned. * @return mixed|false The value of the setting specified by the $setting parameter. If an invalid setting is specified, false is returned and an error is added to the error collection. */ function sqlsrv_get_config($setting) {} /** * Prepares a Transact-SQL query without executing it. Implicitly binds parameters. * *
    Creates a statement resource associated with the specified connection. This function is useful for execution of * multiple queries.
    * * Variables passed as query parameters should be passed by reference instead of by value. For example, pass * &$myVariable instead of $myVariable. A PHP warning will be raised when a query with by-value parameters is * executed.
    * * When you prepare a statement that uses variables as parameters, the variables are bound to the statement. That means * that if you update the values of the variables, the next time you execute the statement it will run with updated * parameter values.
    * * The combination of sqlsrv_prepare and {@link sqlsrv_execute() sqlsrv_execute} separates statement preparation and * statement execution in to two function calls and can be used to execute parameterized queries. This function is ideal * to execute a statement multiple times with different parameter values for each execution.
    * * For alternative strategies for writing and reading large amounts of information, see * {@link http://go.microsoft.com/fwlink/?LinkId=104225 Batches of SQL Statements} and * {@link http://go.microsoft.com/fwlink/?LinkId=104226 BULK INSERT}.
    * * For more information, see * {@link http://msdn.microsoft.com/en-us/library/cc626303.aspx How to: Retrieve Output Parameters Using the SQLSRV Driver.}
    * * For additional Information see: *
    • {@link http://msdn.microsoft.com/en-us/library/cc644934.aspx Using Directional Parameters}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296202.aspx Updating Data (Microsoft Drivers for PHP for SQL Server)}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296201.aspx How to: Perform Parameterized Queries}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296191.aspx How to: Send Data as a Stream}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-prepare * @param resource $conn The connection resource associated with the created statement. * @param string $tsql The Transact-SQL expression that corresponds to the created statement. * @param array $params [optional]: An array of values that correspond to parameters in a parameterized query. Each * element of the array can be one of the following: a literal value, a reference to a PHP variable, or an array with * the following structure: * array(&$value [, $direction [, $phpType [, $sqlType]]]) * The following table describes these array elements: *
    • &$value - A literal value or a reference to a PHP variable.
    • *
    • $direction[optional] - One of the following SQLSRV_PARAM_* constants used to indicate the parameter direction: * SQLSRV_PARAM_IN, SQLSRV_PARAM_OUT, SQLSRV_PARAM_INOUT. The default value is SQLSRV_PARAM_IN. For more information * about PHP constants, see * {@link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server Constants (Microsoft Drivers for PHP for SQL Server)}.
    • *
    • $phpType[optional] - A SQLSRV_PHPTYPE_* constant that specifies PHP data type of the returned value.
    • *
    • $sqlType[optional] - A SQLSRV_SQLTYPE_* constant that specifies the SQL Server data type of the input value.
    * @param array $options [optional]: An associative array that sets query properties. The table below lists the * supported keys and corresponding values:
    * * QueryTimeout (int) - Sets the query timeout in seconds. By default, the driver will wait indefinitely for results. * Any positive integer value.
    * * SendStreamParamsAtExec (bool) - Configures the driver to send all stream data at execution (true), or to send stream * data in chunks (false). By default, the value is set to true. For more information, see * {@link sqlsrv_send_stream_data() sqlsrv_send_stream_data}.
    * * Scrollable - For more information about these values, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}. *
    • SQLSRV_CURSOR_FORWARD
    • *
    • SQLSRV_CURSOR_STATIC
    • *
    • SQLSRV_CURSOR_DYNAMIC
    • *
    • SQLSRV_CURSOR_KEYSET
    • *
    • SQLSRV_CURSOR_CLIENT_BUFFERED
    * @return resource|false A statement resource. If the statement resource cannot be created, false is returned. */ function sqlsrv_prepare($conn, $tsql, $params = [], $options = []) {} /** * Executes a statement prepared with {@see sqlsrv_prepare} * *
    Executes a previously prepared statement. See {@link sqlsrv_prepare() sqlsrv_prepare} for information on preparing a statement * for execution.
    * * This function is ideal for executing a prepared statement multiple times with different parameter values.
    * * For additional Information see: *
    • {@link sqlsrv_query() sqlsrv_query}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296201.aspx How to: Perform Parameterized Queries}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-execute * @param resource $stmt A resource specifying the statement to be executed. For more information about how to create a * statement resource, see {@link sqlsrv_prepare() sqlsrv_prepare}. * @return bool A Boolean value: true if the statement was successfully executed. Otherwise, false. */ function sqlsrv_execute($stmt) {} /** * Prepares and executes a Transact-SQL query. * *
    Prepares and executes a statement.
    * * The sqlsrv_query function is well-suited for one-time queries and should be the default choice to execute queries * unless special circumstances apply. This function provides a streamlined method to execute a query with a minimum * amount of code. The sqlsrv_query function does both statement preparation and statement execution, and can be used to * execute parameterized queries.
    * * For more information, see * {@link http://msdn.microsoft.com/en-us/library/cc626303.aspx How to: Retrieve Output Parameters Using the SQLSRV Driver.}
    * * For additional Information see: *
    • {@link http://msdn.microsoft.com/en-us/library/cc644934.aspx Using Directional Parameters}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296202.aspx Updating Data (Microsoft Drivers for PHP for SQL Server)}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296201.aspx How to: Perform Parameterized Queries}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296191.aspx How to: Send Data as a Stream}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-query * @param resource $conn The connection resource associated with the prepared statement. * @param string $tsql The Transact-SQL expression that corresponds to the prepared statement. * @param array $params [optional]: An array of values that correspond to parameters in a parameterized query. Each * element of the array can be one of the following: a literal value, a reference to a PHP variable, or an array with * the following structure: * array($value [, $direction [, $phpType [, $sqlType]]]) * The following table describes these array elements: *
    • &$value - A literal value, a PHP variable, or a PHP by-reference variable.
    • *
    • $direction[optional] - One of the following SQLSRV_PARAM_* constants used to indicate the parameter direction: * SQLSRV_PARAM_IN, SQLSRV_PARAM_OUT, SQLSRV_PARAM_INOUT. The default value is SQLSRV_PARAM_IN. For more information * about PHP constants, see * {@link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server Constants (Microsoft Drivers for PHP for SQL Server)}.
    • *
    • $phpType[optional] - A SQLSRV_PHPTYPE_* constant that specifies PHP data type of the returned value.
    • *
    • $sqlType[optional] - A SQLSRV_SQLTYPE_* constant that specifies the SQL Server data type of the input value.
    * @param array $options [optional]: An associative array that sets query properties. The table below lists the * supported keys and corresponding values:
    * * QueryTimeout (int) - Sets the query timeout in seconds. By default, the driver will wait indefinitely for results. * Any positive integer value.
    * * SendStreamParamsAtExec (bool) - Configures the driver to send all stream data at execution (true), or to send stream * data in chunks (false). By default, the value is set to true. For more information, see * {@link sqlsrv_send_stream_data() sqlsrv_send_stream_data}.
    * * Scrollable - For more information about these values, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}. *
    • SQLSRV_CURSOR_FORWARD
    • *
    • SQLSRV_CURSOR_STATIC
    • *
    • SQLSRV_CURSOR_DYNAMIC
    • *
    • SQLSRV_CURSOR_KEYSET
    • *
    • SQLSRV_CURSOR_CLIENT_BUFFERED
    * @return resource|false A statement resource. If the statement cannot be created and/or executed, false is returned. */ function sqlsrv_query($conn, $tsql, $params = [], $options = []) {} /** * Makes the next row in a result set available for reading. * *
    Makes the next row of a result set available for reading. Use {@link sqlsrv_get_field() sqlsrv_get_field} to read fields of * the row.
    * * A statement must be executed before results can be retrieved. For information on executing a statement, see {@link sqlsrv_query() sqlsrv_query} * and {@link sqlsrv_execute() sqlsrv_execute}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-fetch * @param resource|null $stmt A statement resource corresponding to an executed statement. * @param int|null $row [optional]: One of the following values, specifying the row to access in a result set that uses a * scrollable cursor: SQLSRV_SCROLL_NEXT, SQLSRV_SCROLL_PRIOR, SQLSRV_SCROLL_FIRST, SQLSRV_SCROLL_LAST, * SQLSRV_SCROLL_ABSOLUTE, SQLSRV_SCROLL_RELATIVE.
    * * For more information on these values, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}. * @param int|null $offset [optional] Used with SQLSRV_SCROLL_ABSOLUTE and SQLSRV_SCROLL_RELATIVE to specify the row to * retrieve. The first record in the result set is 0. * @return bool|null If the next row of the result set was successfully retrieved, true is returned. If there are * no more results in the result set, null is returned. If an error occurred, false is returned. */ function sqlsrv_fetch($stmt, $row = null, $offset = null) {} /** * Retrieves a field in the current row by index. The PHP return type can be specified. * *
    Retrieves data from the specified field of the current row. Field data must be accessed in order. For example, * data from the first field cannot be accessed after data from the second field has been accessed.
    * * The combination of {@link sqlsrv_fetch() sqlsrv_fetch} and * {@link sqlsrv_get_field() sqlsrv_get_field} provides forward-only access to data.
    * * The combination of {@link sqlsrv_fetch() sqlsrv_fetch} and * {@link sqlsrv_get_field() sqlsrv_get_field} loads only one * field of a result set row into script memory and allows PHP return type specification. (For information about how to * specify the PHP return type, see {@link http://msdn.microsoft.com/en-us/library/cc296208.aspx How to: Specify PHP Data Types}.) * This combination of functions also allows data to be retrieved as a stream. (For information about retrieving data * as a stream, see {@link http://msdn.microsoft.com/en-us/library/cc296155.aspx Retrieving Data as a Stream Using the SQLSRV Driver}.)
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-get-field * @param resource $stmt A statement resource corresponding to an executed statement. * @param int $field_index The index of the field to be retrieved. Indexes begin at zero. * @param int $get_as_type [optional] A SQLSRV constant (SQLSRV_PHPTYPE_*) that determines the PHP data type for the returned * data. For information about supported data types, see * {@link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server Constants (Microsoft Drivers for PHP for SQL Server)}. * If no return type is specified, a default PHP type will be returned. For information about default PHP types, see * {@link http://msdn.microsoft.com/en-us/library/cc296193.aspx Default PHP Data Types}. For information about * specifying PHP data types, see {@link http://msdn.microsoft.com/en-us/library/cc296208.aspx How to: Specify PHP Data Types}. * @return mixed The field data. You can specify the PHP data type of the returned data by using the $getAsType * parameter. If no return data type is specified, the default PHP data type will be returned. For information about * default PHP types, see {@link http://msdn.microsoft.com/en-us/library/cc296193.aspx Default PHP Data Types}. For * information about specifying PHP data types, * see {@link http://msdn.microsoft.com/en-us/library/cc296208.aspx How to: Specify PHP Data Types}. */ function sqlsrv_get_field($stmt, $field_index, $get_as_type = null) {} /** * Retrieves the next row of data as a numerically indexed array, an associative array, or both. * *
    If a column with no name is returned, the associative key for the array element will be an empty string (""). For * example, consider this Transact-SQL statement that inserts a value into a database table and retrieves the * server-generated primary key: * INSERT INTO Production.ProductPhoto (LargePhoto) VALUES (?); * SELECT SCOPE_IDENTITY() * If the result set returned by the SELECT SCOPE_IDENTITY() portion of this statement is retrieved as an associative * array, the key for the returned value will be an empty string ("") because the returned column has no name. To avoid * this, you can retrieve the result as a numeric array, or you can specify a name for the returned column in the * Transact-SQL statement. The following is one way to specify a column name in Transact-SQL: * SELECT SCOPE_IDENTITY() AS PictureID * If a result set contains multiple columns without names, the value of the last unnamed column will be assigned to the * empty string ("") key.
    * * The sqlsrv_fetch_array function always returns data according to the * {@link http://msdn.microsoft.com/en-us/library/cc296193.aspx Default PHP Data Types}. For information about * how to specify the PHP data type, * see {@link http://msdn.microsoft.com/en-us/library/cc296208.aspx How to: Specify PHP Data Types}.
    * * If a field with no name is retrieved, the associative key for the array element will be an empty string (""). For * more information, see {@link sqlsrv_fetch_array() sqlsrv_fetch_array}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296160.aspx Retrieving Data} and * {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-fetch-array * @param resource|null $stmt A statement resource corresponding to an executed statement. * @param int $fetch_type [optional] A predefined constant. This parameter can take on one of the values listed in the * following table: *
    • SQLSRV_FETCH_NUMERIC - The next row of data is returned as a numeric array.
    • *
    • SQLSRV_FETCH_ASSOC - The next row of data is returned as an associative array. The array keys are the column * names in the result set.
    • *
    • SQLSRV_FETCH_BOTH - The next row of data is returned as both a numeric array and an associative array. This is * the default value.
    * @param int|null $row [optional]: One of the following values, specifying the row to access in a result set that uses a * scrollable cursor: SQLSRV_SCROLL_NEXT, SQLSRV_SCROLL_PRIOR, SQLSRV_SCROLL_FIRST, SQLSRV_SCROLL_LAST, * SQLSRV_SCROLL_ABSOLUTE, SQLSRV_SCROLL_RELATIVE.
    * * For more information on these values, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}. * @param int|null $offset [optional] Used with SQLSRV_SCROLL_ABSOLUTE and SQLSRV_SCROLL_RELATIVE to specify the row to * retrieve. The first record in the result set is 0. * @return array|null|false If a row of data is retrieved, an array is returned. If there are no more rows to retrieve, null is returned. If an error occurs, false is returned. */ function sqlsrv_fetch_array($stmt, $fetch_type = null, $row = null, $offset = null) {} /** * Retrieves the next row of data as an object. * *
    Retrieves the next row of data as a PHP object.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296160.aspx Retrieving Data} and * {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-fetch-object * @param resource $stmt A statement resource corresponding to an executed statement. * @param string|null $class_name [optional] A string specifying the name of the class to instantiate. If a value for the * $className parameter is not specified, an instance of the PHP {@link stdClass} is instantiated. * @param array|null $ctor_params [optional] An array that contains values passed to the constructor of the class * specified with the $className parameter. If the constructor of the specified class accepts parameter values, the * $ctorParams parameter must be used when calling sqlsrv_fetch_object. * @param int|null $row [optional] One of the following values, specifying the row to access in a result set that uses a * scrollable cursor: SQLSRV_SCROLL_NEXT, SQLSRV_SCROLL_PRIOR, SQLSRV_SCROLL_FIRST, SQLSRV_SCROLL_LAST, * SQLSRV_SCROLL_ABSOLUTE, SQLSRV_SCROLL_RELATIVE.
    * * For more information on these values, see * {@link http://msdn.microsoft.com/en-us/library/ee376927.aspx Specifying a Cursor Type and Selecting Rows}. * @param int|null $offset [optional] Used with SQLSRV_SCROLL_ABSOLUTE and SQLSRV_SCROLL_RELATIVE to specify the row to * retrieve. The first record in the result set is 0. * @return object|false|null A PHP object with properties that correspond to result set field names. Property values are * populated with the corresponding result set field values. If the class specified with the optional $className * parameter does not exist or if there is no active result set associated with the specified statement, false is * returned. If there are no more rows to retrieve, null is returned.

    * * The data type of a value in the returned object will be the default PHP data type. For information on default PHP data * types, see {@link http://msdn.microsoft.com/en-us/library/cc296193.aspx Default PHP Data Types}.
    */ function sqlsrv_fetch_object($stmt, $class_name = null, $ctor_params = null, $row = null, $offset = null) {} /** * Detects if a result set has one or more rows. * *
    Indicates if the result set has one or more rows.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-has-rows * @param resource $stmt The executed statement. * @return bool If there are rows in the result set, the return value will be true. If there are no rows, or if the * function call fails, the return value will be false. */ function sqlsrv_has_rows($stmt) {} /** * Retrieves the number of fields (columns) on a statemen. * *
    Retrieves the number of fields in an active result set. Note that sqlsrv_num_fields can be called on any * prepared statement, before or after execution.
    * * Additional Information at {@link sqlsrv_field_metadata() sqlsrv_field_metadata} and * {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-num-fields * @param resource $stmt The statement on which the targeted result set is active. * @return int|false An integer value that represents the number of fields in the active result set. If an error occurs, * the Boolean value false is returned. */ function sqlsrv_num_fields($stmt) {} /** * Makes the next result of the specified statement active. * *
    Makes the next result (result set, row count, or output parameter) of the specified statement active.
    * * The first (or only) result returned by a batch query or stored procedure is active without a call to sqlsrv_next_result.
    * * Additional Information at * {@link http://msdn.microsoft.com/en-us/library/cc296202.aspx Updating Data (Microsoft Drivers for PHP for SQL Server)} and * {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-next-result * @param resource $stmt The executed statement on which the next result is made active. * @return bool|null If the next result was successfully made active, the Boolean value true is returned. If an error occurred in * making the next result active, false is returned. If no more results are available, null is returned. */ function sqlsrv_next_result($stmt) {} /** * Retrieves the number of rows in a result set. * *
    sqlsrv_num_rows requires a client-side, static, or keyset cursor, and will return false if you use a forward cursor * or a dynamic cursor. (A forward cursor is the default.) For more information about cursors, see * {@link sqlsrv_prepare() sqlsrv_prepare}, * {@link sqlsrv_query() sqlsrv_query} and * {@link http://msdn.microsoft.com/en-us/library/hh487160.aspx Cursor Types (SQLSRV Driver)}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-num-rows * @param resource $stmt The result set for which to count the rows. * @return int|false False if there was an error calculating the number of rows. Otherwise, returns the number of rows in the result set. */ function sqlsrv_num_rows($stmt) {} /** * Returns the number of modified rows. * *
    Returns the number of rows modified by the last statement executed. This function does not return the number of * rows returned by a SELECT statement.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-rows-affected * @param resource $stmt A statement resource corresponding to an executed statement. * @return int|false An integer indicating the number of rows modified by the last executed statement. If no rows were * modified, zero (0) is returned. If no information about the number of modified rows is available, negative one (-1) * is returned. If an error occurred in retrieving the number of modified rows, false is returned. */ function sqlsrv_rows_affected($stmt) {} /** * Provides information about the client. * *
    Returns information about the connection and client stack.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-client-info * @param resource $conn The connection resource by which the client is connected. * @return array|false An associative array with keys described in the table below, or false if the connection resource * is null.
    *
    • DriverDllName - SQLNCLI10.DLL (Microsoft Drivers for PHP for SQL Server version 2.0)
    • *
    • DriverODBCVer - ODBC version (xx.yy)
    • *
    • DriverVer - SQL Server Native Client DLL version: 10.50.xxx (Microsoft Drivers for PHP for SQL Server version 2.0)
    • *
    • ExtensionVer - php_sqlsrv.dll version: 2.0.xxxx.x(Microsoft Drivers for PHP for SQL Server version 2.0)
    */ function sqlsrv_client_info($conn) {} /** * Returns information about the server. * *
    Returns information about the server. A connection must be established before calling this function.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-server-info * @param resource $conn The connection resource by which the client and server are connected. * @return array An associative array with the following keys: *
    • CurrentDatabase - The database currently being targeted.
    • *
    • SQLServerVersion - The version of SQL Server.
    • *
    • SQLServerName - The name of the server.
    */ function sqlsrv_server_info($conn) {} /** * Cancels a statement; discards any pending results for the statement. * *
    Cancels a statement. This means that any pending results for the statement are discarded. After this function * is called, the statement can be re-executed if it was prepared with {@link sqlsrv_prepare() sqlsrv_prepare}. Calling * this function is not necessary if all the results associated with the statement have been consumed.
    * * A statement that is prepared and executed using the combination of {@link sqlsrv_prepare() sqlsrv_prepare} and * {@link sqlsrv_execute() sqlsrv_execute} can be re-executed * with {@link sqlsrv_execute() sqlsrv_execute} after calling sqlsrv_cancel. A statement that is executed with * {@link sqlsrv_query() sqlsrv_query} cannot be re-executed after calling sqlsrv_cancel.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-cancel * @param resource $stmt The statement to be canceled. * @return bool A Boolean value: true if the operation was successful. Otherwise, false. */ function sqlsrv_cancel($stmt) {} /** * Closes a statement. Frees all resources associated with the statement. * *
    Frees all resources associated with the specified statement. The statement cannot be used again after this function * has been called.
    * * Null is a valid parameter for this function. This allows the function to be called multiple times in a script. For * example, if you free a statement in an error condition and free it again at the end of the script, the second call to * sqlsrv_free_stmt will return true because the first call to sqlsrv_free_stmt (in the error condition) sets the * statement resource to null.
    * * Additional Information at {@link sqlsrv_cancel() sqlsrv_cancel} and * {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-free-stmt * @param resource|null $stmt The statement to be closed. * @return bool The Boolean value true unless the function is called with an invalid parameter. If the function is * called with an invalid parameter, false is returned. */ function sqlsrv_free_stmt($stmt) {} /** * Returns field metadata. * *
    Retrieves metadata for the fields of a prepared statement. For information about preparing a statement, * see {@link sqlsrv_query() sqlsrv_query} * or {@link sqlsrv_prepare() sqlsrv_prepare}. Note that sqlsrv_field_metadata can be called on any prepared statement, * pre- or post-execution.
    * * Additional Information at {@link sqlsrv_cancel() sqlsrv_cancel} and * {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-field-metadata * @param resource $stmt A statement resource for which field metadata is sought. * @return array|false An array of arrays or false. The array consists of one array for each field in the result set. * Each sub-array has keys as described in the table below. If there is an error in retrieving field metadata, false is * returned. *
    • Name - Name of the column to which the field corresponds.
    • *
    • Type - Numeric value that corresponds to a SQL type.
    • *
    • Size - Number of characters for fields of character type (char(n), varchar(n), nchar(n), nvarchar(n), XML). * Number of bytes for fields of binary type (binary(n), varbinary(n), UDT). NULL for other SQL Server data types.
    • *
    • Precision - The precision for types of variable precision (real, numeric, decimal, datetime2, datetimeoffset, and * time). NULL for other SQL Server data types.
    • *
    • Scale - The scale for types of variable scale (numeric, decimal, datetime2, datetimeoffset, and time). NULL for other * SQL Server data types.
    • *
    • Nullable - An enumerated value indicating whether the column is nullable (SQLSRV_NULLABLE_YES), the column is not * nullable (SQLSRV_NULLABLE_NO), or it is not known if the column is nullable (SQLSRV_NULLABLE_UNKNOWN).
    * See the {@link http://msdn.microsoft.com/en-us/library/cc296197.aspx function documentation} for more information on * the keys for each sub-array. */ function sqlsrv_field_metadata($stmt) {} /** * Sends up to eight kilobytes (8 KB) of data to the server with each call to the function. * *
    Sends data from parameter streams to the server. Up to eight kilobytes (8K) of data is sent with each call to * sqlsrv_send_stream_data.
    * * By default, all stream data is sent to the server when a query is executed. If this default behavior is not changed, * you do not have to use sqlsrv_send_stream_data to send stream data to the server. For information about changing the * default behavior, see the Parameters section of {@link sqlsrv_query() sqlsrv_query} * or {@link sqlsrv_prepare() sqlsrv_prepare}.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-send-stream-data * @param resource $stmt A statement resource corresponding to an executed statement. * @return bool Boolean : true if there is more data to be sent. Otherwise, false. */ function sqlsrv_send_stream_data($stmt) {} /** * Specifies the encoding of a stream of data from the server. * *
    When specifying the PHP data type of a value being returned from the server, this allows you to specify the encoding * used to process the value if the value is a stream.
    * * In the documentation this is presented as a constant that accepts an arguement.
    * * When you use SQLSRV_PHPTYPE_STREAM, the encoding must be specified. If no parameter is supplied, an error will be * returned.
    * * Additional Information at: *
      *
    • {@link http://msdn.microsoft.com/en-us/library/cc296208.aspx How to: Specify PHP Data Types}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296163.aspx How to: Retrieve Character Data as a Stream Using the SQLSRV Driver.}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc626307.aspx How to: Send and Retrieve UTF-8 Data Using Built-In UTF-8 Support.}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    • *
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * * @param string $encoding The encoding to use for the stream. The valid options are SQLSRV_ENC_BINARY, SQLSRV_ENC_CHAR * or "UTF-8". * * @return int Value to use in any place that accepts a SQLSRV_PHPTYPE_* constant to represent a PHP stream with the * given encoding. */ function SQLSRV_PHPTYPE_STREAM($encoding) {} /** * Specifies the encoding of a string being received form the server. * *
    When specifying the PHP data type of a value being returned from the server, this allows you to specify the * encoding used to process the value if the value is a string.
    * * In the documentation this is presented as a constant that accepts an arguement.
    * * When you use SQLSRV_PHPTYPE_STRING, the encoding must be specified. If no parameter is supplied, an error will be * returned.
    * * Additional Information at: *
      *
    • {@link http://msdn.microsoft.com/en-us/library/cc296208.aspx How to: Specify PHP Data Types}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296163.aspx How to: Retrieve Character Data as a Stream Using the SQLSRV Driver.}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc626307.aspx How to: Send and Retrieve UTF-8 Data Using Built-In UTF-8 Support.}
    • *
    • {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    • *
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * * @param string $encoding The encoding to use for the stream. The valid options are SQLSRV_ENC_BINARY, SQLSRV_ENC_CHAR * or "UTF-8". * * @return int Value to use in any place that accepts a SQLSRV_PHPTYPE_* constant to represent a PHP string with the * given encoding. */ function SQLSRV_PHPTYPE_STRING($encoding) {} /** * Specifies a SQL Server binary field. * *
    In the documentation this is presented as a constant that accepts an arguement.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * @param int $byteCount Must be between 1 and 8000. * @return int Value to use in any place that accepts a SQLSRV_SQLTYPE_* constant to represent the 'binary' data type. */ function SQLSRV_SQLTYPE_BINARY($byteCount) {} /** * Specifies a SQL Server varbinary field. * *
    In the documentation this is presented as a constant that accepts an arguement.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * @param int|string $byteCount Must be between 1 and 8000 or 'max'. * @return int Value to use in any place that accepts a SQLSRV_SQLTYPE_* constant to represent the varbinary data type. */ function SQLSRV_SQLTYPE_VARBINARY($byteCount) {} /** * Specifies a SQL Server varchar filed. * *
    In the documentation this is presented as a constant that accepts an arguement.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * * @param int|string $charCount Must be between 1 and 8000 or 'max'. * * @return int Value to use in any place that accepts a SQLSRV_SQLTYPE_* constant to represent the varchar data type. */ function SQLSRV_SQLTYPE_VARCHAR($charCount) {} /** * Specifies a SQL Server char field. * *
    In the documentation this is presented as a constant that accepts an arguement.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * @param int $charCount Must be between 1 and 8000. * @return int Value to use in any place that accepts a SQLSRV_SQLTYPE_* constant to represent the char data type. */ function SQLSRV_SQLTYPE_CHAR($charCount) {} /** * Specifies a SQL Server nchar field. * *
    In the documentation this is presented as a constant that accepts an arguement.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * @param int $charCount Must be between 1 and 4000. * @return int Value to use in any place that accepts a SQLSRV_SQLTYPE_* constant to represent the nchar data type. */ function SQLSRV_SQLTYPE_NCHAR($charCount) {} /** * Specifies a SQL Server nvarchar field. * *
    In the documentation this is presented as a constant that accepts an arguement.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * @param int|string $charCount Must be between 1 and 4000 or 'max'. * @return int Value to use in any place that accepts a SQLSRV_SQLTYPE_* constant to represent the nvarchar data type. */ function SQLSRV_SQLTYPE_NVARCHAR($charCount) {} /** * Specifies a SQL Server decimal field. * *
    In the documentation this is presented as a constant that accepts an arguement.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * @param int $precision Must be between 1 and 38. * @param int $scale Must be between 1 and $precision. * @return int Value to use in any place that accepts a SQLSRV_SQLTYPE_* constant to represent the decimal data type. */ function SQLSRV_SQLTYPE_DECIMAL($precision, $scale) {} /** * Specifies a SQL Server numeric field. * *
    In the documentation this is presented as a constant that accepts an arguement.
    * * Additional Information at {@link http://msdn.microsoft.com/en-us/library/cc296152.aspx SQLSRV Driver API Reference}
    * * @link https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server * @param int $precision Must be between 1 and 38. * @param int $scale Must be between 1 and $precision. * @return int Value to use in any place that accepts a SQLSRV_SQLTYPE_* constant to represent the numeric data type. */ function SQLSRV_SQLTYPE_NUMERIC($precision, $scale) {} * @link https://github.com/soulshockers/cassandra-phpdoc */ /** * Copyright 2019 DataStax, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace { /** * The main entry point to the PHP Driver for Apache Cassandra. * * Use Cassandra::cluster() to build a cluster instance. * Use Cassandra::ssl() to build SSL options instance. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/ */ final class Cassandra { /** * Consistency level ANY means the request is fulfilled as soon as the data * has been written on the Coordinator. Requests with this consistency level * are not guaranteed to make it to Replica nodes. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_ANY */ public const CONSISTENCY_ANY = 0; /** * Consistency level ONE guarantees that data has been written to at least * one Replica node. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_ONE */ public const CONSISTENCY_ONE = 1; /** * Consistency level TWO guarantees that data has been written to at least * two Replica nodes. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_TWO */ public const CONSISTENCY_TWO = 2; /** * Consistency level THREE guarantees that data has been written to at least * three Replica nodes. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_THREE */ public const CONSISTENCY_THREE = 3; /** * Consistency level QUORUM guarantees that data has been written to at least * the majority of Replica nodes. How many nodes exactly are a majority * depends on the replication factor of a given keyspace and is calculated * using the formula `ceil(RF / 2 + 1)`, where `ceil` is a mathematical * ceiling function and `RF` is the replication factor used. For example, * for a replication factor of `5`, the majority is `ceil(5 / 2 + 1) = 3`. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_QUORUM */ public const CONSISTENCY_QUORUM = 4; /** * Consistency level ALL guarantees that data has been written to all * Replica nodes. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_ALL */ public const CONSISTENCY_ALL = 5; /** * Same as `CONSISTENCY_QUORUM`, but confined to the local data center. This * consistency level works only with `NetworkTopologyStrategy` replication. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_LOCAL_QUORUM */ public const CONSISTENCY_LOCAL_QUORUM = 6; /** * Consistency level EACH_QUORUM guarantees that data has been written to at * least a majority Replica nodes in all datacenters. This consistency level * works only with `NetworkTopologyStrategy` replication. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_EACH_QUORUM */ public const CONSISTENCY_EACH_QUORUM = 7; /** * This is a serial consistency level, it is used in conditional updates, * e.g. (`CREATE|INSERT ... IF NOT EXISTS`), and should be specified as the * `serial_consistency` execution option when invoking `session.execute` * or `session.execute_async`. * * Consistency level SERIAL, when set, ensures that a Paxos commit fails if * any of the replicas is down. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_SERIAL */ public const CONSISTENCY_SERIAL = 8; /** * Same as `CONSISTENCY_SERIAL`, but confined to the local data center. This * consistency level works only with `NetworkTopologyStrategy` replication. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_LOCAL_SERIAL */ public const CONSISTENCY_LOCAL_SERIAL = 9; /** * Same as `CONSISTENCY_ONE`, but confined to the local data center. This * consistency level works only with `NetworkTopologyStrategy` replication. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CONSISTENCY_LOCAL_ONE */ public const CONSISTENCY_LOCAL_ONE = 10; /** * Perform no verification of nodes when using SSL encryption. * * @see \Cassandra\SSLOptions\Builder::withVerifyFlags() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-VERIFY_NONE */ public const VERIFY_NONE = 0; /** * Verify presence and validity of SSL certificates. * * @see \Cassandra\SSLOptions\Builder::withVerifyFlags() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-VERIFY_PEER_CERT */ public const VERIFY_PEER_CERT = 1; /** * Verify that the IP address matches the SSL certificate’s common name or * one of its subject alternative names. This implies the certificate is * also present. * * @see \Cassandra\SSLOptions\Builder::withVerifyFlags() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-VERIFY_PEER_IDENTITY */ public const VERIFY_PEER_IDENTITY = 2; /** * @see \Cassandra\BatchStatement::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-BATCH_LOGGED */ public const BATCH_LOGGED = 0; /** * @see \Cassandra\BatchStatement::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-BATCH_UNLOGGED */ public const BATCH_UNLOGGED = 1; /** * @see \Cassandra\BatchStatement::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-BATCH_COUNTER */ public const BATCH_COUNTER = 2; /** * Used to disable logging. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-LOG_DISABLED */ public const LOG_DISABLED = 0; /** * Allow critical level logging. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-LOG_CRITICAL */ public const LOG_CRITICAL = 1; /** * Allow error level logging. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-LOG_ERROR */ public const LOG_ERROR = 2; /** * Allow warning level logging. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-LOG_WARN */ public const LOG_WARN = 3; /** * Allow info level logging. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-LOG_INFO */ public const LOG_INFO = 4; /** * Allow debug level logging. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-LOG_DEBUG */ public const LOG_DEBUG = 5; /** * Allow trace level logging. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-LOG_TRACE */ public const LOG_TRACE = 6; /** * When using a map, collection or set of type text, all of its elements * must be strings. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_TEXT */ public const TYPE_TEXT = 'text'; /** * When using a map, collection or set of type ascii, all of its elements * must be strings. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_ASCII */ public const TYPE_ASCII = 'ascii'; /** * When using a map, collection or set of type varchar, all of its elements * must be strings. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_VARCHAR */ public const TYPE_VARCHAR = 'varchar'; /** * When using a map, collection or set of type bigint, all of its elements * must be instances of Bigint. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_BIGINT */ public const TYPE_BIGINT = 'bigint'; /** * When using a map, collection or set of type smallint, all of its elements * must be instances of Inet. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_SMALLINT */ public const TYPE_SMALLINT = 'smallint'; /** * When using a map, collection or set of type tinyint, all of its elements * must be instances of Inet. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_TINYINT */ public const TYPE_TINYINT = 'tinyint'; /** * When using a map, collection or set of type blob, all of its elements * must be instances of Blob. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_BLOB */ public const TYPE_BLOB = 'blob'; /** * When using a map, collection or set of type bool, all of its elements * must be boolean. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_BOOLEAN */ public const TYPE_BOOLEAN = 'boolean'; /** * When using a map, collection or set of type counter, all of its elements * must be instances of Bigint. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_COUNTER */ public const TYPE_COUNTER = 'counter'; /** * When using a map, collection or set of type decimal, all of its elements * must be instances of Decimal. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_DECIMAL */ public const TYPE_DECIMAL = 'decimal'; /** * When using a map, collection or set of type double, all of its elements * must be doubles. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_DOUBLE */ public const TYPE_DOUBLE = 'double'; /** * When using a map, collection or set of type float, all of its elements * must be instances of Float. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_FLOAT */ public const TYPE_FLOAT = 'float'; /** * When using a map, collection or set of type int, all of its elements * must be ints. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_INT */ public const TYPE_INT = 'int'; /** * When using a map, collection or set of type timestamp, all of its elements * must be instances of Timestamp. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_TIMESTAMP */ public const TYPE_TIMESTAMP = 'timestamp'; /** * When using a map, collection or set of type uuid, all of its elements * must be instances of Uuid. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_UUID */ public const TYPE_UUID = 'uuid'; /** * When using a map, collection or set of type varint, all of its elements * must be instances of Varint. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_VARINT */ public const TYPE_VARINT = 'varint'; /** * When using a map, collection or set of type timeuuid, all of its elements * must be instances of Timeuuid. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_TIMEUUID */ public const TYPE_TIMEUUID = 'timeuuid'; /** * When using a map, collection or set of type inet, all of its elements * must be instances of Inet. * * @see Set::__construct() * @see Collection::__construct() * @see Map::__construct() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-TYPE_INET */ public const TYPE_INET = 'inet'; /** * The current version of the extension. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-VERSION */ public const VERSION = '1.3.2'; /** * The version of the cpp-driver the extension is compiled against. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#constant-CPP_DRIVER_VERSION */ public const CPP_DRIVER_VERSION = '2.13.0'; /** * Creates a new cluster builder for constructing a Cluster object. * * @return \Cassandra\Cluster\Builder A cluster builder object with default settings * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#method-cluster */ public static function cluster() {} /** * Creates a new ssl builder for constructing a SSLOptions object. * * @return \Cassandra\SSLOptions\Builder A SSL options builder with default settings * @link https://docs.datastax.com/en/developer/php-driver/latest/api/class.Cassandra/#method-ssl */ public static function ssl() {} } } /** * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/ */ namespace Cassandra { use JetBrains\PhpStorm\Deprecated; /** * A PHP representation of a column * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Column/ */ interface Column { /** * Returns the name of the column. * * @return string Name of the column or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Column/#method-name */ public function name(); /** * Returns the type of the column. * * @return \Cassandra\Type Type of the column * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Column/#method-type */ public function type(); /** * Returns whether the column is in descending or ascending order. * * @return bool Whether the column is stored in descending order. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Column/#method-isReversed */ public function isReversed(); /** * Returns true for static columns. * * @return bool Whether the column is static * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Column/#method-isStatic */ public function isStatic(); /** * Returns true for frozen columns. * * @return bool Whether the column is frozen * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Column/#method-isFrozen */ public function isFrozen(); /** * Returns name of the index if defined. * * @return string Name of the index if defined or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Column/#method-indexName */ public function indexName(); /** * Returns index options if present. * * @return string Index options if present or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Column/#method-indexOptions */ public function indexOptions(); } /** * A session is used to prepare and execute statements. * * @see \Cassandra\Cluster::connect() * @see \Cassandra\Cluster::connectAsync() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Session/ */ interface Session { /** * Execute a query. * * Available execution options: * | Option Name | Option **Type** | Option Details | * |--------------------|-----------------|----------------------------------------------------------------------------------------------------------| * | arguments | array | An array or positional or named arguments | * | consistency | int | A consistency constant e.g Dse::CONSISTENCY_ONE, Dse::CONSISTENCY_QUORUM, etc. | * | timeout | int | A number of rows to include in result for paging | * | paging_state_token | string | A string token use to resume from the state of a previous result set | * | retry_policy | RetryPolicy | A retry policy that is used to handle server-side failures for this request | * | serial_consistency | int | Either Dse::CONSISTENCY_SERIAL or Dse::CONSISTENCY_LOCAL_SERIAL | * | timestamp | int\|string | Either an integer or integer string timestamp that represents the number of microseconds since the epoch | * | execute_as | string | User to execute statement as | * * @param string|\Cassandra\Statement $statement string or statement to be executed. * @param array|\Cassandra\ExecutionOptions|null $options Options to control execution of the query. * * @return \Cassandra\Rows A collection of rows. * @throws \Cassandra\Exception * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Session/#method-execute */ public function execute($statement, $options); /** * Execute a query asynchronously. This method returns immediately, but * the query continues execution in the background. * * @param string|\Cassandra\Statement $statement string or statement to be executed. * @param array|\Cassandra\ExecutionOptions|null $options Options to control execution of the query. * * @return \Cassandra\FutureRows A future that can be used to retrieve the result. * * @see \Cassandra\Session::execute() for valid execution options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Session/#method-executeAsync */ public function executeAsync($statement, $options); /** * Prepare a query for execution. * * @param string $cql The query to be prepared. * @param array|\Cassandra\ExecutionOptions|null $options Options to control preparing the query. * * @return \Cassandra\PreparedStatement A prepared statement that can be bound with parameters and executed. * * @throws \Cassandra\Exception * * @see \Cassandra\Session::execute() for valid execution options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Session/#method-prepare */ public function prepare($cql, $options); /** * Asynchronously prepare a query for execution. * * @param string $cql The query to be prepared. * @param array|\Cassandra\ExecutionOptions|null $options Options to control preparing the query. * * @return \Cassandra\FuturePreparedStatement A future that can be used to retrieve the prepared statement. * * @see \Cassandra\Session::execute() for valid execution options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Session/#method-prepareAsync */ public function prepareAsync($cql, $options); /** * Close the session and all its connections. * * @param float $timeout The amount of time in seconds to wait for the session to close. * * @return null Nothing. * @throws \Cassandra\Exception * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Session/#method-close */ public function close($timeout); /** * Asynchronously close the session and all its connections. * * @return \Cassandra\FutureClose A future that can be waited on. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Session/#method-closeAsync */ public function closeAsync(); /** * Get performance and diagnostic metrics. * * @return array Performance/Diagnostic metrics. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Session/#method-metrics */ public function metrics(); /** * Get a snapshot of the cluster's current schema. * * @return \Cassandra\Schema A snapshot of the cluster's schema. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Session/#method-schema */ public function schema(); } /** * A PHP representation of a table * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/ */ interface Table { /** * Returns the name of this table * * @return string Name of the table * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-name */ public function name(); /** * Return a table's option by name * * @param string $name The name of the option * * @return \Cassandra\Value Value of an option by name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-option */ public function option($name); /** * Returns all the table's options * * @return array A dictionary of `string` and `Value` pairs of the table's options. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-options */ public function options(); /** * Description of the table, if any * * @return string Table description or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-comment */ public function comment(); /** * Returns read repair chance * * @return float Read repair chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-readRepairChance */ public function readRepairChance(); /** * Returns local read repair chance * * @return float Local read repair chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-localReadRepairChance */ public function localReadRepairChance(); /** * Returns GC grace seconds * * @return int GC grace seconds * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-gcGraceSeconds */ public function gcGraceSeconds(); /** * Returns caching options * * @return string Caching options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-caching */ public function caching(); /** * Returns bloom filter FP chance * * @return float Bloom filter FP chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-bloomFilterFPChance */ public function bloomFilterFPChance(); /** * Returns memtable flush period in milliseconds * * @return int Memtable flush period in milliseconds * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-memtableFlushPeriodMs */ public function memtableFlushPeriodMs(); /** * Returns default TTL. * * @return int Default TTL. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-defaultTTL */ public function defaultTTL(); /** * Returns speculative retry. * * @return string Speculative retry. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-speculativeRetry */ public function speculativeRetry(); /** * Returns index interval * * @return int Index interval * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-indexInterval */ public function indexInterval(); /** * Returns compaction strategy class name * * @return string Compaction strategy class name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-compactionStrategyClassName */ public function compactionStrategyClassName(); /** * Returns compaction strategy options * * @return \Cassandra\Map Compaction strategy options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-compactionStrategyOptions */ public function compactionStrategyOptions(); /** * Returns compression parameters * * @return \Cassandra\Map Compression parameters * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-compressionParameters */ public function compressionParameters(); /** * Returns whether or not the `populate_io_cache_on_flush` is true * * @return bool Value of `populate_io_cache_on_flush` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-populateIOCacheOnFlush */ public function populateIOCacheOnFlush(); /** * Returns whether or not the `replicate_on_write` is true * * @return bool Value of `replicate_on_write` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-replicateOnWrite */ public function replicateOnWrite(); /** * Returns the value of `max_index_interval` * * @return int Value of `max_index_interval` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-maxIndexInterval */ public function maxIndexInterval(); /** * Returns the value of `min_index_interval` * * @return int Value of `min_index_interval` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-minIndexInterval */ public function minIndexInterval(); /** * Returns column by name * * @param string $name Name of the column * * @return \Cassandra\Column Column instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-column */ public function column($name); /** * Returns all columns in this table * * @return array A list of Column instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-columns */ public function columns(); /** * Returns the partition key columns of the table * * @return array A list of Column instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-partitionKey */ public function partitionKey(); /** * Returns both the partition and clustering key columns of the table * * @return array A list of Column instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-primaryKey */ public function primaryKey(); /** * Returns the clustering key columns of the table * * @return array A list of Column instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-clusteringKey */ public function clusteringKey(); /** * @return array A list of cluster column orders ('asc' and 'desc') * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Table/#method-clusteringOrder */ public function clusteringOrder(); } /** * Interface for retry policies. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.RetryPolicy/ */ interface RetryPolicy {} /** * Interface for timestamp generators. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.TimestampGenerator/ */ interface TimestampGenerator {} /** * An interface implemented by all exceptions thrown by the PHP Driver. * Makes it easy to catch all driver-related exceptions using * `catch (Exception $e)`. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Exception/ */ interface Exception {} /** * A PHP representation of a function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Function/ */ interface Function_ { /** * Returns the full name of the function * * @return string Full name of the function including name and types * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Function/#method-name */ public function name(); /** * Returns the simple name of the function * * @return string Simple name of the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Function/#method-simpleName */ public function simpleName(); /** * Returns the arguments of the function * * @return array Arguments of the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Function/#method-arguments */ public function arguments(); /** * Returns the return type of the function * * @return \Cassandra\Type Return type of the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Function/#method-returnType */ public function returnType(); /** * Returns the signature of the function * * @return string Signature of the function (same as name()) * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Function/#method-signature */ public function signature(); /** * Returns the lanuage of the function * * @return string Language used by the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Function/#method-language */ public function language(); /** * Returns the body of the function * * @return string Body of the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Function/#method-body */ public function body(); /** * Determines if a function is called when the value is null. * * @return bool Returns whether the function is called when the input columns are null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Function/#method-isCalledOnNullInput */ public function isCalledOnNullInput(); } /** * A PHP representation of the CQL `uuid` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.UuidInterface/ */ interface UuidInterface { /** * Returns this uuid as string. * * @return string uuid as string * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.UuidInterface/#method-uuid */ public function uuid(); /** * Returns the version of this uuid. * * @return int version of this uuid * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.UuidInterface/#method-version */ public function version(); } /** * A PHP representation of an index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Index/ */ interface Index { /** * Returns the name of the index * * @return string Name of the index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Index/#method-name */ public function name(); /** * Returns the kind of index * * @return string Kind of the index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Index/#method-kind */ public function kind(); /** * Returns the target column of the index * * @return string Target column name of the index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Index/#method-target */ public function target(); /** * Return a column's option by name * * @param string $name The name of the option * * @return \Cassandra\Value Value of an option by name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Index/#method-option */ public function option($name); /** * Returns all the index's options * * @return array A dictionary of `string` and `Value` pairs of the index's options. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Index/#method-options */ public function options(); /** * Returns the class name of the index * * @return string Class name of a custom index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Index/#method-className */ public function className(); /** * Determines if the index is a custom index. * * @return bool true if a custom index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Index/#method-isCustom */ public function isCustom(); } /** * Cluster object is used to create Sessions. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Cluster/ */ interface Cluster { /** * Creates a new Session instance. * * @param string $keyspace Optional keyspace name * * @return \Cassandra\Session Session instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Cluster/#method-connect */ public function connect($keyspace); /** * Creates a new Session instance. * * @param string $keyspace Optional keyspace name * * @return \Cassandra\Future A Future Session instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Cluster/#method-connectAsync */ public function connectAsync($keyspace); } /** * Common interface implemented by all numeric types, providing basic * arithmetic functions. * * @see \Cassandra\Bigint * @see \Cassandra\Decimal * @see \Cassandra\Float_ * @see \Cassandra\Varint * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/ */ interface Numeric { /** * @param \Cassandra\Numeric $num a number to add to this one * * @return \Cassandra\Numeric sum * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-add */ public function add($num); /** * @param \Cassandra\Numeric $num a number to subtract from this one * * @return \Cassandra\Numeric difference * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-sub */ public function sub($num); /** * @param \Cassandra\Numeric $num a number to multiply this one by * * @return \Cassandra\Numeric product * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-mul */ public function mul($num); /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric quotient * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-div */ public function div($num); /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric remainder * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-mod */ public function mod($num); /** * @return \Cassandra\Numeric absolute value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-abs */ public function abs(); /** * @return \Cassandra\Numeric negative value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-neg */ public function neg(); /** * @return \Cassandra\Numeric square root * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-sqrt */ public function sqrt(); /** * @return int this number as int * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-toInt */ public function toInt(); /** * @return float this number as float * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Numeric/#method-toDouble */ public function toDouble(); } /** * Futures are returns from asynchronous methods. * * @see \Cassandra\Cluster::connectAsync() * @see \Cassandra\Session::executeAsync() * @see \Cassandra\Session::prepareAsync() * @see \Cassandra\Session::closeAsync() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Future/ */ interface Future { /** * Waits for a given future resource to resolve and throws errors if any. * * @param int|float|null $timeout A timeout in seconds * * @return mixed a value that the future has been resolved with * @throws \Cassandra\Exception\TimeoutException * * @throws \Cassandra\Exception\InvalidArgumentException * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Future/#method-get */ public function get($timeout); } /** * A PHP representation of a keyspace * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/ */ interface Keyspace { /** * Returns keyspace name * * @return string Name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-name */ public function name(); /** * Returns replication class name * * @return string Replication class * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-replicationClassName */ public function replicationClassName(); /** * Returns replication options * * @return \Cassandra\Map Replication options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-replicationOptions */ public function replicationOptions(); /** * Returns whether the keyspace has durable writes enabled * * @return string Whether durable writes are enabled * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-hasDurableWrites */ public function hasDurableWrites(); /** * Returns a table by name * * @param string $name Table name * * @return \Cassandra\Table|null Table instance or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-table */ public function table($name); /** * Returns all tables defined in this keyspace * * @return array An array of `Table` instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-tables */ public function tables(); /** * Get user type by name * * @param string $name User type name * * @return \Cassandra\Type\UserType|null A user type or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-userType */ public function userType($name); /** * Get all user types * * @return array An array of user types * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-userTypes */ public function userTypes(); /** * Get materialized view by name * * @param string $name Materialized view name * * @return \Cassandra\MaterializedView|null A materialized view or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-materializedView */ public function materializedView($name); /** * Gets all materialized views * * @return array An array of materialized views * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-materializedViews */ public function materializedViews(); /** * Get a function by name and signature * * @param string $name Function name * @param string|\Cassandra\Type $params Function arguments * * @return \Cassandra\Function_|null A function or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-function */ public function function_($name, ...$params); /** * Get all functions * * @return array An array of functions * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-functions */ public function functions(); /** * Get an aggregate by name and signature * * @param string $name Aggregate name * @param string|\Cassandra\Type $params Aggregate arguments * * @return \Cassandra\Aggregate|null An aggregate or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-aggregate */ public function aggregate($name, ...$params); /** * Get all aggregates * * @return array An array of aggregates * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Keyspace/#method-aggregates */ public function aggregates(); } /** * Common interface implemented by all Cassandra value types. * * @see \Cassandra\Bigint * @see \Cassandra\Smallint * @see \Cassandra\Tinyint * @see \Cassandra\Blob * @see \Cassandra\Collection * @see \Cassandra\Float_ * @see \Cassandra\Inet * @see \Cassandra\Map * @see \Cassandra\Set * @see \Cassandra\Timestamp * @see \Cassandra\Timeuuid * @see \Cassandra\Uuid * @see \Cassandra\Varint * @see \Cassandra\Date * @see \Cassandra\Time * * @see \Cassandra\Numeric * @see \Cassandra\UuidInterface * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Value/ */ interface Value { /** * The type of represented by the value. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Value/#method-type */ public function type(); } /** * A PHP representation of an aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/ */ interface Aggregate { /** * Returns the full name of the aggregate * * @return string Full name of the aggregate including name and types * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/#method-name */ public function name(); /** * Returns the simple name of the aggregate * * @return string Simple name of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/#method-simpleName */ public function simpleName(); /** * Returns the argument types of the aggregate * * @return array Argument types of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/#method-argumentTypes */ public function argumentTypes(); /** * Returns the final function of the aggregate * * @return \Cassandra\Function_ Final function of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/#method-finalFunction */ public function finalFunction(); /** * Returns the state function of the aggregate * * @return \Cassandra\Function_ State function of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/#method-stateFunction */ public function stateFunction(); /** * Returns the initial condition of the aggregate * * @return \Cassandra\Value Initial condition of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/#method-initialCondition */ public function initialCondition(); /** * Returns the return type of the aggregate * * @return \Cassandra\Type Return type of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/#method-returnType */ public function returnType(); /** * Returns the state type of the aggregate * * @return \Cassandra\Type State type of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/#method-stateType */ public function stateType(); /** * Returns the signature of the aggregate * * @return string Signature of the aggregate (same as name()) * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Aggregate/#method-signature */ public function signature(); } /** * All statements implement this common interface. * * @see \Cassandra\SimpleStatement * @see \Cassandra\PreparedStatement * @see \Cassandra\BatchStatement * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Statement/ */ interface Statement {} /** * A PHP representation of a schema * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Schema/ */ interface Schema { /** * Returns a Keyspace instance by name. * * @param string $name Name of the keyspace to get * * @return \Cassandra\Keyspace Keyspace instance or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Schema/#method-keyspace */ public function keyspace($name); /** * Returns all keyspaces defined in the schema. * * @return array An array of Keyspace instances. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/interface.Schema/#method-keyspaces */ public function keyspaces(); } /** * Rows represent a result of statement execution. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/ */ final class Rows implements \Iterator, \ArrayAccess { /** * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-__construct */ public function __construct() {} /** * Returns the number of rows. * * @return int number of rows * * @see \Countable::count() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-count */ public function count() {} /** * Resets the rows iterator. * * @return void * * @see \Iterator::rewind() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-rewind */ public function rewind() {} /** * Returns current row. * * @return array current row * * @see \Iterator::current() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-current */ public function current() {} /** * Returns current index. * * @return int index * * @see \Iterator::key() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-key */ public function key() {} /** * Advances the rows iterator by one. * * @return void * * @see \Iterator::next() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-next */ public function next() {} /** * Returns existence of more rows being available. * * @return bool whether there are more rows available for iteration * * @see \Iterator::valid() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-valid */ public function valid() {} /** * Returns existence of a given row. * * @param int $offset row index * * @return bool whether a row at a given index exists * * @see \ArrayAccess::offsetExists() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-offsetExists */ public function offsetExists($offset) {} /** * Returns a row at given index. * * @param int $offset row index * * @return array|null row at a given index * * @see \ArrayAccess::offsetGet() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-offsetGet */ public function offsetGet($offset) {} /** * Sets a row at given index. * * @param int $offset row index * @param array $value row value * * @return void * * @throws \Cassandra\Exception\DomainException * * @see \ArrayAccess::offsetSet() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-offsetSet */ public function offsetSet($offset, $value) {} /** * Removes a row at given index. * * @param int $offset row index * * @return void * * @throws \Cassandra\Exception\DomainException * * @see \ArrayAccess::offsetUnset() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-offsetUnset */ public function offsetUnset($offset) {} /** * Check for the last page when paging. * * @return bool whether this is the last page or not * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-isLastPage */ public function isLastPage() {} /** * Get the next page of results. * * @param float|null $timeout * * @return \Cassandra\Rows|null loads and returns next result page * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-nextPage */ public function nextPage($timeout) {} /** * Get the next page of results asynchronously. * * @return \Cassandra\Future returns future of the next result page * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-nextPageAsync */ public function nextPageAsync() {} /** * Returns the raw paging state token. * * @return string * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-pagingStateToken */ public function pagingStateToken() {} /** * Get the first row. * * @return array|null returns first row if any * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Rows/#method-first */ public function first() {} } /** * Default cluster implementation. * * @see \Cassandra\Cluster * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultCluster/ */ final class DefaultCluster implements Cluster { /** * Creates a new Session instance. * * @param string $keyspace Optional keyspace name * @param int $timeout Optional timeout * * @return \Cassandra\Session Session instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultCluster/#method-connect */ public function connect($keyspace, $timeout) {} /** * Creates a new Session instance. * * @param string $keyspace Optional keyspace name * * @return \Cassandra\Future A Future Session instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultCluster/#method-connectAsync */ public function connectAsync($keyspace) {} } /** * A PHP representation of a public function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultFunction/ */ final class DefaultFunction implements Function_ { /** * Returns the full name of the function * * @return string Full name of the function including name and types * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultFunction/#method-name */ public function name() {} /** * Returns the simple name of the function * * @return string Simple name of the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultFunction/#method-simpleName */ public function simpleName() {} /** * Returns the arguments of the function * * @return array Arguments of the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultFunction/#method-arguments */ public function arguments() {} /** * Returns the return type of the function * * @return \Cassandra\Type Return type of the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultFunction/#method-returnType */ public function returnType() {} /** * Returns the signature of the function * * @return string Signature of the function (same as name()) * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultFunction/#method-signature */ public function signature() {} /** * Returns the lanuage of the function * * @return string Language used by the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultFunction/#method-language */ public function language() {} /** * Returns the body of the function * * @return string Body of the function * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultFunction/#method-body */ public function body() {} /** * Determines if a function is called when the value is null. * * @return bool Returns whether the function is called when the input columns are null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultFunction/#method-isCalledOnNullInput */ public function isCalledOnNullInput() {} } /** * Simple statements can be executed using a Session instance. * They are constructed with a CQL string that can contain positional * argument markers `?`. * * NOTE: Positional argument are only valid for native protocol v2+. * * @see \Cassandra\Session::execute() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.SimpleStatement/ */ final class SimpleStatement implements Statement { /** * Creates a new simple statement with the provided CQL. * * @param string $cql CQL string for this simple statement * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.SimpleStatement/#method-__construct */ public function __construct($cql) {} } /** * A PHP representation of the CQL `tuple` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/ */ final class Tuple implements Value, \Countable, \Iterator { /** * Creates a new tuple with the given types. * * @param array $types Array of types * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-__construct */ public function __construct($types) {} /** * The type of this tuple. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-type */ public function type() {} /** * Array of values in this tuple. * * @return array values * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-values */ public function values() {} /** * Sets the value at index in this tuple . * * @param mixed $value A value or null * * @return void * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-set */ public function set($value) {} /** * Retrieves the value at a given index. * * @param int $index Index * * @return mixed A value or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-get */ public function get($index) {} /** * Total number of elements in this tuple * * @return int count * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-count */ public function count() {} /** * Current element for iteration * * @return mixed current element * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-current */ public function current() {} /** * Current key for iteration * * @return int current key * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-key */ public function key() {} /** * Move internal iterator forward * * @return void * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-next */ public function next() {} /** * Check whether a current value exists * * @return bool * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-valid */ public function valid() {} /** * Rewind internal iterator * * @return void * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tuple/#method-rewind */ public function rewind() {} } /** * A PHP representation of the CQL `smallint` datatype. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/ */ final class Smallint implements Value, Numeric { /** * Creates a new 16-bit signed integer. * * @param int|float|string $value The value as an integer, double or string * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-__construct */ public function __construct($value) {} /** * Minimum possible Smallint value * * @return \Cassandra\Smallint minimum value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-min */ public static function min() {} /** * Maximum possible Smallint value * * @return \Cassandra\Smallint maximum value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-max */ public static function max() {} /** * @return string * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-__toString */ public function __toString() {} /** * The type of this value (smallint). * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-type */ public function type() {} /** * Returns the integer value. * * @return int integer value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-value */ public function value() {} /** * @param \Cassandra\Numeric $num a number to add to this one * * @return \Cassandra\Numeric sum * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-add */ public function add($num) {} /** * @param \Cassandra\Numeric $num a number to subtract from this one * * @return \Cassandra\Numeric difference * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-sub */ public function sub($num) {} /** * @param \Cassandra\Numeric $num a number to multiply this one by * * @return \Cassandra\Numeric product * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-mul */ public function mul($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric quotient * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-div */ public function div($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric remainder * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-mod */ public function mod($num) {} /** * @return \Cassandra\Numeric absolute value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-abs */ public function abs() {} /** * @return \Cassandra\Numeric negative value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-neg */ public function neg() {} /** * @return \Cassandra\Numeric square root * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-sqrt */ public function sqrt() {} /** * @return int this number as int * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-toInt */ public function toInt() {} /** * @return float this number as float * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Smallint/#method-toDouble */ public function toDouble() {} } /** * A future returned from `Session::prepareAsync()` * This future will resolve with a PreparedStatement or an exception. * * @see \Cassandra\Session::prepareAsync() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.FuturePreparedStatement/ */ final class FuturePreparedStatement implements Future { /** * Waits for a given future resource to resolve and throws errors if any. * * @param int|float|null $timeout A timeout in seconds * * @return \Cassandra\PreparedStatement A prepared statement * @throws \Cassandra\Exception\TimeoutException * * @throws \Cassandra\Exception\InvalidArgumentException * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.FuturePreparedStatement/#method-get */ public function get($timeout) {} } /** * A PHP representation of a schema * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSchema/ */ final class DefaultSchema implements Schema { /** * Returns a Keyspace instance by name. * * @param string $name Name of the keyspace to get * * @return \Cassandra\Keyspace Keyspace instance or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSchema/#method-keyspace */ public function keyspace($name) {} /** * Returns all keyspaces defined in the schema. * * @return array An array of `Keyspace` instances. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSchema/#method-keyspaces */ public function keyspaces() {} /** * Get the version of the schema snapshot * * @return int Version of the schema. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSchema/#method-version */ public function version() {} } /** * Batch statements are used to execute a series of simple or prepared * statements. * * There are 3 types of batch statements: * * `Cassandra::BATCH_LOGGED` - this is the default batch type. This batch * guarantees that either all or none of its statements will be executed. * This behavior is achieved by writing a batch log on the coordinator, * which slows down the execution somewhat. * * `Cassandra::BATCH_UNLOGGED` - this batch will not be verified when * executed, which makes it faster than a `LOGGED` batch, but means that * some of its statements might fail, while others - succeed. * * `Cassandra::BATCH_COUNTER` - this batch is used for counter updates, * which are, unlike other writes, not idempotent. * * @see Cassandra::BATCH_LOGGED * @see Cassandra::BATCH_UNLOGGED * @see Cassandra::BATCH_COUNTER * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.BatchStatement/ */ final class BatchStatement implements Statement { /** * Creates a new batch statement. * * @param int $type must be one of Cassandra::BATCH_* (default: Cassandra::BATCH_LOGGED). * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.BatchStatement/#method-__construct */ public function __construct($type) {} /** * Adds a statement to this batch. * * @param string|\Cassandra\Statement $statement string or statement to add * @param array|null $arguments positional or named arguments (optional) * * @return \Cassandra\BatchStatement self * @throws \Cassandra\Exception\InvalidArgumentException * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.BatchStatement/#method-add */ public function add($statement, $arguments) {} } /** * A PHP representation of the CQL `list` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/ */ final class Collection implements Value, \Countable, \Iterator { /** * Creates a new collection of a given type. * * @param \Cassandra\Type $type * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-__construct */ public function __construct($type) {} /** * The type of this collection. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-type */ public function type() {} /** * Array of values in this collection. * * @return array values * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-values */ public function values() {} /** * Adds one or more values to this collection. * * @param mixed ...$value one or more values to add * * @return int total number of values in this collection * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-add */ public function add(...$value) {} /** * Retrieves the value at a given index. * * @param int $index Index * * @return mixed Value or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-get */ public function get($index) {} /** * Finds index of a value in this collection. * * @param mixed $value Value * * @return int Index or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-find */ public function find($value) {} /** * Total number of elements in this collection * * @return int count * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-count */ public function count() {} /** * Current element for iteration * * @return mixed current element * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-current */ public function current() {} /** * Current key for iteration * * @return int current key * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-key */ public function key() {} /** * Move internal iterator forward * * @return void * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-next */ public function next() {} /** * Check whether a current value exists * * @return bool * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-valid */ public function valid() {} /** * Rewind internal iterator * * @return void * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-rewind */ public function rewind() {} /** * Deletes the value at a given index * * @param int $index Index * * @return bool Whether the value at a given index is correctly removed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Collection/#method-remove */ public function remove($index) {} } /** * This future results is resolved with Rows. * * @see \Cassandra\Session::executeAsync() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.FutureRows/ */ final class FutureRows implements Future { /** * Waits for a given future resource to resolve and throws errors if any. * * @param int|float|null $timeout A timeout in seconds * * @return \Cassandra\Rows|null The result set * @throws \Cassandra\Exception\TimeoutException * * @throws \Cassandra\Exception\InvalidArgumentException * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.FutureRows/#method-get */ public function get($timeout) {} } /** * A PHP representation of a materialized view * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/ */ final class DefaultMaterializedView extends MaterializedView { /** * Returns the name of this view * * @return string Name of the view * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-name */ public function name() {} /** * Return a view's option by name * * @param string $name The name of the option * * @return \Cassandra\Value Value of an option by name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-option */ public function option($name) {} /** * Returns all the view's options * * @return array A dictionary of string and Value pairs of the * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-options */ public function options() {} /** * Description of the view, if any * * @return string Table description or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-comment */ public function comment() {} /** * Returns read repair chance * * @return float Read repair chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-readRepairChance */ public function readRepairChance() {} /** * Returns local read repair chance * * @return float Local read repair chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-localReadRepairChance */ public function localReadRepairChance() {} /** * Returns GC grace seconds * * @return int GC grace seconds * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-gcGraceSeconds */ public function gcGraceSeconds() {} /** * Returns caching options * * @return string Caching options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-caching */ public function caching() {} /** * Returns bloom filter FP chance * * @return float Bloom filter FP chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-bloomFilterFPChance */ public function bloomFilterFPChance() {} /** * Returns memtable flush period in milliseconds * * @return int Memtable flush period in milliseconds * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-memtableFlushPeriodMs */ public function memtableFlushPeriodMs() {} /** * Returns default TTL. * * @return int Default TTL. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-defaultTTL */ public function defaultTTL() {} /** * Returns speculative retry. * * @return string Speculative retry. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-speculativeRetry */ public function speculativeRetry() {} /** * Returns index interval * * @return int Index interval * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-indexInterval */ public function indexInterval() {} /** * Returns compaction strategy class name * * @return string Compaction strategy class name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-compactionStrategyClassName */ public function compactionStrategyClassName() {} /** * Returns compaction strategy options * * @return \Cassandra\Map Compaction strategy options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-compactionStrategyOptions */ public function compactionStrategyOptions() {} /** * Returns compression parameters * * @return \Cassandra\Map Compression parameters * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-compressionParameters */ public function compressionParameters() {} /** * Returns whether or not the `populate_io_cache_on_flush` is true * * @return bool Value of `populate_io_cache_on_flush` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-populateIOCacheOnFlush */ public function populateIOCacheOnFlush() {} /** * Returns whether or not the `replicate_on_write` is true * * @return bool Value of `replicate_on_write` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-replicateOnWrite */ public function replicateOnWrite() {} /** * Returns the value of `max_index_interval` * * @return int Value of `max_index_interval` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-maxIndexInterval */ public function maxIndexInterval() {} /** * Returns the value of `min_index_interval` * * @return int Value of `min_index_interval` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-minIndexInterval */ public function minIndexInterval() {} /** * Returns column by name * * @param string $name Name of the column * * @return \Cassandra\Column Column instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-column */ public function column($name) {} /** * Returns all columns in this view * * @return array A list of Column instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-columns */ public function columns() {} /** * Returns the partition key columns of the view * * @return array A list of Column instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-partitionKey */ public function partitionKey() {} /** * Returns both the partition and clustering key columns of the view * * @return array A list of Column instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-primaryKey */ public function primaryKey() {} /** * Returns the clustering key columns of the view * * @return array A list of Column instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-clusteringKey */ public function clusteringKey() {} /** * @return array A list of cluster column orders ('asc' and 'desc') * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-clusteringOrder */ public function clusteringOrder() {} /** * Returns the base table of the view * * @return \Cassandra\Table Base table of the view * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultMaterializedView/#method-baseTable */ public function baseTable() {} } /** * SSL options for Cluster. * * @see \Cassandra\SSLOptions\Builder * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.SSLOptions/ */ final class SSLOptions {} /** * A PHP representation of the CQL `bigint` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/ */ final class Bigint implements Value, Numeric { /** * Creates a new 64bit integer. * * @param string $value integer value as a string * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-__construct */ public function __construct($value) {} /** * Minimum possible Bigint value * * @return \Cassandra\Bigint minimum value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-min */ public static function min() {} /** * Maximum possible Bigint value * * @return \Cassandra\Bigint maximum value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-max */ public static function max() {} /** * Returns string representation of the integer value. * * @return string integer value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-__toString */ public function __toString() {} /** * The type of this bigint. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-type */ public function type() {} /** * Returns the integer value. * * @return string integer value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-value */ public function value() {} /** * @param \Cassandra\Numeric $num a number to add to this one * * @return \Cassandra\Numeric sum * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-add */ public function add($num) {} /** * @param \Cassandra\Numeric $num a number to subtract from this one * * @return \Cassandra\Numeric difference * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-sub */ public function sub($num) {} /** * @param \Cassandra\Numeric $num a number to multiply this one by * * @return \Cassandra\Numeric product * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-mul */ public function mul($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric quotient * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-div */ public function div($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric remainder * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-mod */ public function mod($num) {} /** * @return \Cassandra\Numeric absolute value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-abs */ public function abs() {} /** * @return \Cassandra\Numeric negative value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-neg */ public function neg() {} /** * @return \Cassandra\Numeric square root * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-sqrt */ public function sqrt() {} /** * @return int this number as int * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-toInt */ public function toInt() {} /** * @return float this number as float * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Bigint/#method-toDouble */ public function toDouble() {} } /** * A future that resolves with Session. * * @see \Cassandra\Cluster::connectAsync() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.FutureSession/ */ final class FutureSession implements Future { /** * Waits for a given future resource to resolve and throws errors if any. * * @param int|float|null $timeout A timeout in seconds * * @return \Cassandra\Session A connected session * @throws \Cassandra\Exception\TimeoutException * * @throws \Cassandra\Exception\InvalidArgumentException * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.FutureSession/#method-get */ public function get($timeout) {} } /** * A PHP representation of the CQL `set` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/ */ final class Set implements Value, \Countable, \Iterator { /** * Creates a new collection of a given type. * * @param \Cassandra\Type $type * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-__construct */ public function __construct($type) {} /** * The type of this set. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-type */ public function type() {} /** * Array of values in this set. * * @return array values * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-values */ public function values() {} /** * Adds a value to this set. * * @param mixed $value Value * * @return bool whether the value has been added * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-add */ public function add($value) {} /** * Returns whether a value is in this set. * * @param mixed $value Value * * @return bool whether the value is in the set * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-has */ public function has($value) {} /** * Removes a value to this set. * * @param mixed $value Value * * @return bool whether the value has been removed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-remove */ public function remove($value) {} /** * Total number of elements in this set * * @return int count * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-count */ public function count() {} /** * Current element for iteration * * @return mixed current element * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-current */ public function current() {} /** * Current key for iteration * * @return int current key * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-key */ public function key() {} /** * Move internal iterator forward * * @return void * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-next */ public function next() {} /** * Check whether a current value exists * * @return bool * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-valid */ public function valid() {} /** * Rewind internal iterator * * @return void * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Set/#method-rewind */ public function rewind() {} } /** * A PHP representation of an index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultIndex/ */ final class DefaultIndex implements Index { /** * Returns the name of the index * * @return string Name of the index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultIndex/#method-name */ public function name() {} /** * Returns the kind of index * * @return string Kind of the index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultIndex/#method-kind */ public function kind() {} /** * Returns the target column of the index * * @return string Target column name of the index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultIndex/#method-target */ public function target() {} /** * Return a column's option by name * * @param string $name The name of the option * * @return \Cassandra\Value Value of an option by name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultIndex/#method-option */ public function option($name) {} /** * Returns all the index's options * * @return array A dictionary of `string` and `Value` pairs of the index's options. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultIndex/#method-options */ public function options() {} /** * Returns the class name of the index * * @return string Class name of a custom index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultIndex/#method-className */ public function className() {} /** * Determines if the index is a custom index. * * @return bool true if a custom index * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultIndex/#method-isCustom */ public function isCustom() {} } /** * A PHP representation of an aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/ */ final class DefaultAggregate implements Aggregate { /** * Returns the full name of the aggregate * * @return string Full name of the aggregate including name and types * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/#method-name */ public function name() {} /** * Returns the simple name of the aggregate * * @return string Simple name of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/#method-simpleName */ public function simpleName() {} /** * Returns the argument types of the aggregate * * @return array Argument types of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/#method-argumentTypes */ public function argumentTypes() {} /** * Returns the state function of the aggregate * * @return \Cassandra\Function_ State public function of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/#method-stateFunction */ public function stateFunction() {} /** * Returns the final function of the aggregate * * @return \Cassandra\Function_ Final public function of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/#method-finalFunction */ public function finalFunction() {} /** * Returns the initial condition of the aggregate * * @return \Cassandra\Value Initial condition of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/#method-initialCondition */ public function initialCondition() {} /** * Returns the state type of the aggregate * * @return \Cassandra\Type State type of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/#method-stateType */ public function stateType() {} /** * Returns the return type of the aggregate * * @return \Cassandra\Type Return type of the aggregate * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/#method-returnType */ public function returnType() {} /** * Returns the signature of the aggregate * * @return string Signature of the aggregate (same as name()) * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultAggregate/#method-signature */ public function signature() {} } /** * A PHP representation of the CQL `timestamp` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timestamp/ */ final class Timestamp implements Value { /** * Creates a new timestamp from either unix timestamp and microseconds or * from the current time by default. * * @param int $seconds The number of seconds * @param int $microseconds The number of microseconds * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timestamp/#method-__construct */ public function __construct($seconds, $microseconds) {} /** * The type of this timestamp. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timestamp/#method-type */ public function type() {} /** * Unix timestamp. * * @return int seconds * * @see time * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timestamp/#method-time */ public function time() {} /** * Microtime from this timestamp * * @param bool $get_as_float Whether to get this value as float * * @return float|string Float or string representation * * @see microtime * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timestamp/#method-microtime */ public function microtime($get_as_float) {} /** * Converts current timestamp to PHP DateTime. * * @return \DateTime PHP representation * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timestamp/#method-toDateTime */ public function toDateTime() {} /** * Returns a string representation of this timestamp. * * @return string timestamp * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timestamp/#method-__toString */ public function __toString() {} } /** * A PHP representation of the CQL `tinyint` datatype. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/ */ final class Tinyint implements Value, Numeric { /** * Creates a new 8-bit signed integer. * * @param int|float|string $value The value as an integer, float or string * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-__construct */ public function __construct($value) {} /** * Minimum possible Tinyint value * * @return \Cassandra\Tinyint minimum value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-min */ public static function min() {} /** * Maximum possible Tinyint value * * @return \Cassandra\Tinyint maximum value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-max */ public static function max() {} /** * @return string * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-__toString */ public function __toString() {} /** * The type of this value (tinyint). * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-type */ public function type() {} /** * Returns the integer value. * * @return int integer value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-value */ public function value() {} /** * @param \Cassandra\Numeric $num a number to add to this one * * @return \Cassandra\Numeric sum * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-add */ public function add($num) {} /** * @param \Cassandra\Numeric $num a number to subtract from this one * * @return \Cassandra\Numeric difference * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-sub */ public function sub($num) {} /** * @param \Cassandra\Numeric $num a number to multiply this one by * * @return \Cassandra\Numeric product * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-mul */ public function mul($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric quotient * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-div */ public function div($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric remainder * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-mod */ public function mod($num) {} /** * @return \Cassandra\Numeric absolute value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-abs */ public function abs() {} /** * @return \Cassandra\Numeric negative value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-neg */ public function neg() {} /** * @return \Cassandra\Numeric square root * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-sqrt */ public function sqrt() {} /** * @return int this number as int * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-toInt */ public function toInt() {} /** * @return float this number as float * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Tinyint/#method-toDouble */ public function toDouble() {} } /** * A PHP representation of the CQL `timeuuid` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timeuuid/ */ final class Timeuuid implements Value, UuidInterface { /** * Creates a timeuuid from a given timestamp or current time. * * @param int $timestamp Unix timestamp * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timeuuid/#method-__construct */ public function __construct($timestamp) {} /** * Returns this timeuuid as string. * * @return string timeuuid * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timeuuid/#method-__toString */ public function __toString() {} /** * The type of this timeuuid. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timeuuid/#method-type */ public function type() {} /** * Returns this timeuuid as string. * * @return string timeuuid * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timeuuid/#method-uuid */ public function uuid() {} /** * Returns the version of this timeuuid. * * @return int version of this timeuuid * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timeuuid/#method-version */ public function version() {} /** * Unix timestamp. * * @return int seconds * * @see time * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timeuuid/#method-time */ public function time() {} /** * Converts current timeuuid to PHP DateTime. * * @return \DateTime PHP representation * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Timeuuid/#method-toDateTime */ public function toDateTime() {} } /** * A session is used to prepare and execute statements. * * @see \Cassandra\Cluster::connect() * @see \Cassandra\Cluster::connectAsync() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSession/ */ final class DefaultSession implements Session { /** * Execute a query. * * Available execution options: * | Option Name | Option **Type** | Option Details | * |--------------------|-----------------|----------------------------------------------------------------------------------------------------------| * | arguments | array | An array or positional or named arguments | * | consistency | int | A consistency constant e.g Dse::CONSISTENCY_ONE, Dse::CONSISTENCY_QUORUM, etc. | * | timeout | int | A number of rows to include in result for paging | * | paging_state_token | string | A string token use to resume from the state of a previous result set | * | retry_policy | RetryPolicy | A retry policy that is used to handle server-side failures for this request | * | serial_consistency | int | Either Dse::CONSISTENCY_SERIAL or Dse::CONSISTENCY_LOCAL_SERIAL | * | timestamp | int\|string | Either an integer or integer string timestamp that represents the number of microseconds since the epoch | * | execute_as | string | User to execute statement as | * * @param string|\Cassandra\Statement $statement string or statement to be executed. * @param array|\Cassandra\ExecutionOptions|null $options Options to control execution of the query. * * @return \Cassandra\Rows A collection of rows. * @throws \Cassandra\Exception * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSession/#method-execute */ public function execute($statement, $options) {} /** * Execute a query asynchronously. This method returns immediately, but * the query continues execution in the background. * * @param string|\Cassandra\Statement $statement string or statement to be executed. * @param array|\Cassandra\ExecutionOptions|null $options Options to control execution of the query. * * @return \Cassandra\FutureRows A future that can be used to retrieve the result. * * @see \Cassandra\Session::execute() for valid execution options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSession/#method-executeAsync */ public function executeAsync($statement, $options) {} /** * Prepare a query for execution. * * @param string $cql The query to be prepared. * @param array|\Cassandra\ExecutionOptions|null $options Options to control preparing the query. * * @return \Cassandra\PreparedStatement A prepared statement that can be bound with parameters and executed. * * @throws \Cassandra\Exception * * @see \Cassandra\Session::execute() for valid execution options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSession/#method-prepare */ public function prepare($cql, $options) {} /** * Asynchronously prepare a query for execution. * * @param string $cql The query to be prepared. * @param array|\Cassandra\ExecutionOptions|null $options Options to control preparing the query. * * @return \Cassandra\FuturePreparedStatement A future that can be used to retrieve the prepared statement. * * @see \Cassandra\Session::execute() for valid execution options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSession/#method-prepareAsync */ public function prepareAsync($cql, $options) {} /** * Close the session and all its connections. * * @param float $timeout The amount of time in seconds to wait for the session to close. * * @return null Nothing. * @throws \Cassandra\Exception * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSession/#method-close */ public function close($timeout) {} /** * Asynchronously close the session and all its connections. * * @return \Cassandra\FutureClose A future that can be waited on. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSession/#method-closeAsync */ public function closeAsync() {} /** * Get performance and diagnostic metrics. * * @return array Performance/Diagnostic metrics. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSession/#method-metrics */ public function metrics() {} /** * Get a snapshot of the cluster's current schema. * * @return \Cassandra\Schema A snapshot of the cluster's schema. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultSession/#method-schema */ public function schema() {} } /** * A class for representing custom values. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Custom/ */ abstract class Custom implements Value { /** * The type of this value. * * @return \Cassandra\Type\Custom * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Custom/#method-type */ abstract public function type(); } /** * A PHP representation of a materialized view * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/ */ abstract class MaterializedView implements Table { /** * Returns the base table of the view * * @return \Cassandra\Table Base table of the view * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-baseTable */ abstract public function baseTable(); /** * Returns the name of this view * * @return string Name of the view * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-name */ abstract public function name(); /** * Return a view's option by name * * @param string $name The name of the option * * @return \Cassandra\Value Value of an option by name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-option */ abstract public function option($name); /** * Returns all the view's options * * @return array A dictionary of string and Value pairs of the * view's options. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-options */ abstract public function options(); /** * Description of the view, if any * * @return string View description or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-comment */ abstract public function comment(); /** * Returns read repair chance * * @return float Read repair chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-readRepairChance */ abstract public function readRepairChance(); /** * Returns local read repair chance * * @return float Local read repair chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-localReadRepairChance */ abstract public function localReadRepairChance(); /** * Returns GC grace seconds * * @return int GC grace seconds * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-gcGraceSeconds */ abstract public function gcGraceSeconds(); /** * Returns caching options * * @return string Caching options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-caching */ abstract public function caching(); /** * Returns bloom filter FP chance * * @return float Bloom filter FP chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-bloomFilterFPChance */ abstract public function bloomFilterFPChance(); /** * Returns memtable flush period in milliseconds * * @return int Memtable flush period in milliseconds * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-memtableFlushPeriodMs */ abstract public function memtableFlushPeriodMs(); /** * Returns default TTL. * * @return int Default TTL. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-defaultTTL */ abstract public function defaultTTL(); /** * Returns speculative retry. * * @return string Speculative retry. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-speculativeRetry */ abstract public function speculativeRetry(); /** * Returns index interval * * @return int Index interval * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-indexInterval */ abstract public function indexInterval(); /** * Returns compaction strategy class name * * @return string Compaction strategy class name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-compactionStrategyClassName */ abstract public function compactionStrategyClassName(); /** * Returns compaction strategy options * * @return \Cassandra\Map Compaction strategy options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-compactionStrategyOptions */ abstract public function compactionStrategyOptions(); /** * Returns compression parameters * * @return \Cassandra\Map Compression parameters * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-compressionParameters */ abstract public function compressionParameters(); /** * Returns whether or not the `populate_io_cache_on_flush` is true * * @return bool Value of `populate_io_cache_on_flush` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-populateIOCacheOnFlush */ abstract public function populateIOCacheOnFlush(); /** * Returns whether or not the `replicate_on_write` is true * * @return bool Value of `replicate_on_write` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-replicateOnWrite */ abstract public function replicateOnWrite(); /** * Returns the value of `max_index_interval` * * @return int Value of `max_index_interval` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-maxIndexInterval */ abstract public function maxIndexInterval(); /** * Returns the value of `min_index_interval` * * @return int Value of `min_index_interval` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-minIndexInterval */ abstract public function minIndexInterval(); /** * Returns column by name * * @param string $name Name of the column * * @return \Cassandra\Column Column instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-column */ abstract public function column($name); /** * Returns all columns in this view * * @return array A list of `Column` instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-columns */ abstract public function columns(); /** * Returns the partition key columns of the view * * @return array A list of `Column` instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-partitionKey */ abstract public function partitionKey(); /** * Returns both the partition and clustering key columns of the view * * @return array A list of `Column` instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-primaryKey */ abstract public function primaryKey(); /** * Returns the clustering key columns of the view * * @return array A list of `Column` instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-clusteringKey */ abstract public function clusteringKey(); /** * @return array A list of cluster column orders ('asc' and 'desc') * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.MaterializedView/#method-clusteringOrder */ abstract public function clusteringOrder(); } /** * A PHP representation of the CQL `time` type. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Time/ */ final class Time implements Value { /** * Creates a new Time object * * @param int|string $nanoseconds Number of nanoseconds since last microsecond * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Time/#method-__construct */ public function __construct($nanoseconds) {} /** * @param \DateTime $datetime * * @return \Cassandra\Time * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Time/#method-fromDateTime */ public static function fromDateTime($datetime) {} /** * The type of this date. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Time/#method-type */ public function type() {} /** * @return int * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Time/#method-seconds */ public function seconds() {} /** * @return string this date in string format: Time(nanoseconds=$nanoseconds) * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Time/#method-__toString */ public function __toString() {} } /** * Cluster object is used to create Sessions. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/ */ abstract class Type { /** * Get representation of ascii type * * @return \Cassandra\Type ascii type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-ascii */ final public static function ascii() {} /** * Get representation of bigint type * * @return \Cassandra\Type bigint type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-bigint */ final public static function bigint() {} /** * Get representation of smallint type * * @return \Cassandra\Type smallint type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-smallint */ final public static function smallint() {} /** * Get representation of tinyint type * * @return \Cassandra\Type tinyint type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-tinyint */ final public static function tinyint() {} /** * Get representation of blob type * * @return \Cassandra\Type blob type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-blob */ final public static function blob() {} /** * Get representation of boolean type * * @return \Cassandra\Type boolean type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-boolean */ final public static function boolean() {} /** * Get representation of counter type * * @return \Cassandra\Type counter type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-counter */ final public static function counter() {} /** * Get representation of decimal type * * @return \Cassandra\Type decimal type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-decimal */ final public static function decimal() {} /** * Get representation of double type * * @return \Cassandra\Type double type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-double */ final public static function double() {} /** * Get representation of duration type * * @return \Cassandra\Type duration type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-duration */ final public static function duration() {} /** * Get representation of float type * * @return \Cassandra\Type float type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-float */ final public static function float() {} /** * Get representation of int type * * @return \Cassandra\Type int type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-int */ final public static function int() {} /** * Get representation of text type * * @return \Cassandra\Type text type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-text */ final public static function text() {} /** * Get representation of timestamp type * * @return \Cassandra\Type timestamp type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-timestamp */ final public static function timestamp() {} /** * Get representation of date type * * @return \Cassandra\Type date type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-date */ final public static function date() {} /** * Get representation of time type * * @return \Cassandra\Type time type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-time */ final public static function time() {} /** * Get representation of uuid type * * @return \Cassandra\Type uuid type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-uuid */ final public static function uuid() {} /** * Get representation of varchar type * * @return \Cassandra\Type varchar type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-varchar */ final public static function varchar() {} /** * Get representation of varint type * * @return \Cassandra\Type varint type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-varint */ final public static function varint() {} /** * Get representation of timeuuid type * * @return \Cassandra\Type timeuuid type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-timeuuid */ final public static function timeuuid() {} /** * Get representation of inet type * * @return \Cassandra\Type inet type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-inet */ final public static function inet() {} /** * Initialize a Collection type * ```php * create(1, 2, 3, 4, 5, 6, 7, 8, 9); * * var_dump($collection); * ``` * * @param \Cassandra\Type $type The type of values * * @return \Cassandra\Type The collection type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-collection */ final public static function collection($type) {} /** * Initialize a set type * ``` * create("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"); * * var_dump($set); * ``` * * @param \Cassandra\Type $type The types of values * * @return \Cassandra\Type The set type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-set */ final public static function set($type) {} /** * Initialize a map type * ```create(1, "a", 2, "b", 3, "c", 4, "d", 5, "e", 6, "f") * * var_dump($map);``` * * @param \Cassandra\Type $keyType The type of keys * @param \Cassandra\Type $valueType The type of values * * @return \Cassandra\Type The map type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-map */ final public static function map($keyType, $valueType) {} /** * Initialize a tuple type * ```create("a", 123); * * var_dump($tuple);``` * * @param \Cassandra\Type $types A variadic list of types * * @return \Cassandra\Type The tuple type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-tuple */ final public static function tuple($types) {} /** * Initialize a user type * ```create("a", "abc", "b", 123); * * var_dump($userType);``` * * @param \Cassandra\Type $types A variadic list of name/type pairs * * @return \Cassandra\Type The user type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-userType */ final public static function userType($types) {} /** * Returns the name of this type as string. * * @return string Name of this type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-name */ abstract public function name(); /** * Returns string representation of this type. * * @return string String representation of this type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Type/#method-__toString */ abstract public function __toString(); } /** * A PHP representation of the CQL `varint` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/ */ final class Varint implements Value, Numeric { /** * Creates a new variable length integer. * * @param string $value integer value as a string * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-__construct */ public function __construct($value) {} /** * Returns the integer value. * * @return string integer value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-__toString */ public function __toString() {} /** * The type of this varint. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-type */ public function type() {} /** * Returns the integer value. * * @return string integer value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-value */ public function value() {} /** * @param \Cassandra\Numeric $num a number to add to this one * * @return \Cassandra\Numeric sum * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-add */ public function add($num) {} /** * @param \Cassandra\Numeric $num a number to subtract from this one * * @return \Cassandra\Numeric difference * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-sub */ public function sub($num) {} /** * @param \Cassandra\Numeric $num a number to multiply this one by * * @return \Cassandra\Numeric product * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-mul */ public function mul($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric quotient * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-div */ public function div($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric remainder * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-mod */ public function mod($num) {} /** * @return \Cassandra\Numeric absolute value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-abs */ public function abs() {} /** * @return \Cassandra\Numeric negative value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-neg */ public function neg() {} /** * @return \Cassandra\Numeric square root * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-sqrt */ public function sqrt() {} /** * @return int this number as int * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-toInt */ public function toInt() {} /** * @return float this number as float * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Varint/#method-toDouble */ public function toDouble() {} } /** * A PHP representation of the CQL `map` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/ */ final class Map implements Value, \Countable, \Iterator, \ArrayAccess { /** * Creates a new map of a given key and value type. * * @param \Cassandra\Type $keyType * @param \Cassandra\Type $valueType * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-__construct */ public function __construct($keyType, $valueType) {} /** * The type of this map. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-type */ public function type() {} /** * Returns all keys in the map as an array. * * @return array keys * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-keys */ public function keys() {} /** * Returns all values in the map as an array. * * @return array values * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-values */ public function values() {} /** * Sets key/value in the map. * * @param mixed $key key * @param mixed $value value * * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-set */ public function set($key, $value) {} /** * Gets the value of the key in the map. * * @param mixed $key Key * * @return mixed Value or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-get */ public function get($key) {} /** * Removes the key from the map. * * @param mixed $key Key * * @return bool Whether the key was removed or not, e.g. didn't exist * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-remove */ public function remove($key) {} /** * Returns whether the key is in the map. * * @param mixed $key Key * * @return bool Whether the key is in the map or not * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-has */ public function has($key) {} /** * Total number of elements in this map * * @return int count * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-count */ public function count() {} /** * Current value for iteration * * @return mixed current value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-current */ public function current() {} /** * Current key for iteration * * @return int current key * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-key */ public function key() {} /** * Move internal iterator forward * * @return void * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-next */ public function next() {} /** * Check whether a current value exists * * @return bool * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-valid */ public function valid() {} /** * Rewind internal iterator * * @return void * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-rewind */ public function rewind() {} /** * Sets the value at a given key * * @param mixed $key Key to use. * @param mixed $value Value to set. * * @return void * @throws \Cassandra\Exception\InvalidArgumentException when the type of key or value is wrong * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-offsetSet */ public function offsetSet($key, $value) {} /** * Retrieves the value at a given key * * @param mixed $key Key to use. * * @return mixed Value or `null` * @throws \Cassandra\Exception\InvalidArgumentException when the type of key is wrong * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-offsetGet */ public function offsetGet($key) {} /** * Deletes the value at a given key * * @param mixed $key Key to use. * * @return void * @throws \Cassandra\Exception\InvalidArgumentException when the type of key is wrong * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-offsetUnset */ public function offsetUnset($key) {} /** * Returns whether the value a given key is present * * @param mixed $key Key to use. * * @return bool Whether the value at a given key is present * @throws \Cassandra\Exception\InvalidArgumentException when the type of key is wrong * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Map/#method-offsetExists */ public function offsetExists($key) {} } /** * A PHP representation of the CQL `uuid` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Uuid/ */ final class Uuid implements Value, UuidInterface { /** * Creates a uuid from a given uuid string or a random one. * * @param string $uuid A uuid string * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Uuid/#method-__construct */ public function __construct($uuid) {} /** * Returns this uuid as string. * * @return string uuid * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Uuid/#method-__toString */ public function __toString() {} /** * The type of this uuid. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Uuid/#method-type */ public function type() {} /** * Returns this uuid as string. * * @return string uuid * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Uuid/#method-uuid */ public function uuid() {} /** * Returns the version of this uuid. * * @return int version of this uuid * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Uuid/#method-version */ public function version() {} } /** * A PHP representation of the CQL `float` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/ */ final class Float_ implements Value, Numeric { /** * Creates a new float. * * @param float|int|string|\Cassandra\Float_ $value A float value as a string, number or Float * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-__construct */ public function __construct($value) {} /** * Minimum possible Float value * * @return \Cassandra\Float_ minimum value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-min */ public static function min() {} /** * Maximum possible Float value * * @return \Cassandra\Float_ maximum value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-max */ public static function max() {} /** * Returns string representation of the float value. * * @return string float value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-__toString */ public function __toString() {} /** * The type of this float. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-type */ public function type() {} /** * Returns the float value. * * @return float float value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-value */ public function value() {} /** * @return bool * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-isInfinite */ public function isInfinite() {} /** * @return bool * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-isFinite */ public function isFinite() {} /** * @return bool * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-isNaN */ public function isNaN() {} /** * @param \Cassandra\Numeric $num a number to add to this one * * @return \Cassandra\Numeric sum * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-add */ public function add($num) {} /** * @param \Cassandra\Numeric $num a number to subtract from this one * * @return \Cassandra\Numeric difference * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-sub */ public function sub($num) {} /** * @param \Cassandra\Numeric $num a number to multiply this one by * * @return \Cassandra\Numeric product * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-mul */ public function mul($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric quotient * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-div */ public function div($num) {} /** * @param \Cassandra\Numeric $num a number to divide this one by * * @return \Cassandra\Numeric remainder * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-mod */ public function mod($num) {} /** * @return \Cassandra\Numeric absolute value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-abs */ public function abs() {} /** * @return \Cassandra\Numeric negative value * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-neg */ public function neg() {} /** * @return \Cassandra\Numeric square root * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-sqrt */ public function sqrt() {} /** * @return int this number as int * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-toInt */ public function toInt() {} /** * @return float this number as float * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Float/#method-toDouble */ public function toDouble() {} } /** * A PHP representation of the CQL `duration` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Duration/ */ final class Duration implements Value { /** * @param int|float|string|\Cassandra\Bigint $months Months attribute of the duration. * @param int|float|string|\Cassandra\Bigint $days Days attribute of the duration. * @param int|float|string|\Cassandra\Bigint $nanos Nanos attribute of the duration. * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Duration/#method-__construct */ public function __construct($months, $days, $nanos) {} /** * The type of represented by the value. * * @return \Cassandra\Type the Cassandra type for Duration * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Duration/#method-type */ public function type() {} /** * @return string the months attribute of this Duration * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Duration/#method-months */ public function months() {} /** * @return string the days attribute of this Duration * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Duration/#method-days */ public function days() {} /** * @return string the nanoseconds attribute of this Duration * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Duration/#method-nanos */ public function nanos() {} /** * @return string string representation of this Duration; may be used as a literal parameter in CQL queries. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Duration/#method-__toString */ public function __toString() {} } /** * A PHP representation of a keyspace * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/ */ final class DefaultKeyspace implements Keyspace { /** * Returns keyspace name * * @return string Name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-name */ public function name() {} /** * Returns replication class name * * @return string Replication class * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-replicationClassName */ public function replicationClassName() {} /** * Returns replication options * * @return \Cassandra\Map Replication options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-replicationOptions */ public function replicationOptions() {} /** * Returns whether the keyspace has durable writes enabled * * @return string Whether durable writes are enabled * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-hasDurableWrites */ public function hasDurableWrites() {} /** * Returns a table by name * * @param string $name Table name * * @return \Cassandra\Table * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-table */ public function table($name) {} /** * Returns all tables defined in this keyspace * * @return array An array of `Table` instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-tables */ public function tables() {} /** * Get user type by name * * @param string $name User type name * * @return \Cassandra\Type\UserType|null A user type or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-userType */ public function userType($name) {} /** * Get all user types * * @return array An array of user types * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-userTypes */ public function userTypes() {} /** * Get materialized view by name * * @param string $name Materialized view name * * @return \Cassandra\MaterializedView|null A materialized view or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-materializedView */ public function materializedView($name) {} /** * Gets all materialized views * * @return array An array of materialized views * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-materializedViews */ public function materializedViews() {} /** * Get a function by name and signature * * @param string $name Function name * @param string|\Cassandra\Type $params Function arguments * * @return \Cassandra\Function_|null A function or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-function */ public function function_($name, ...$params) {} /** * Get all functions * * @return array An array of functions * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-functions */ public function functions() {} /** * Get an aggregate by name and signature * * @param string $name Aggregate name * @param string|\Cassandra\Type $params Aggregate arguments * * @return \Cassandra\Aggregate|null An aggregate or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-aggregate */ public function aggregate($name, ...$params) {} /** * Get all aggregates * * @return array An array of aggregates * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultKeyspace/#method-aggregates */ public function aggregates() {} } /** * A PHP representation of the CQL `inet` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Inet/ */ final class Inet implements Value { /** * Creates a new IPv4 or IPv6 inet address. * * @param string $address any IPv4 or IPv6 address * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Inet/#method-__construct */ public function __construct($address) {} /** * Returns the normalized string representation of the address. * * @return string address * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Inet/#method-__toString */ public function __toString() {} /** * The type of this inet. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Inet/#method-type */ public function type() {} /** * Returns the normalized string representation of the address. * * @return string address * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Inet/#method-address */ public function address() {} } /** * A PHP representation of the CQL `date` type. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Date/ */ final class Date implements Value { /** * Creates a new Date object * * @param int $seconds Absolute seconds from epoch (1970, 1, 1), can be negative, defaults to current time. * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Date/#method-__construct */ public function __construct($seconds) {} /** * Creates a new Date object from a \DateTime object. * * @param \DateTime $datetime A \DateTime object to convert. * * @return \DateTime PHP representation * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Date/#method-fromDateTime */ public static function fromDateTime($datetime) {} /** * The type of this date. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Date/#method-type */ public function type() {} /** * @return int Absolute seconds from epoch (1970, 1, 1), can be negative * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Date/#method-seconds */ public function seconds() {} /** * Converts current date to PHP DateTime. * * @param \Cassandra\Time $time An optional Time object that is added to the DateTime object. * * @return \DateTime PHP representation * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Date/#method-toDateTime */ public function toDateTime($time) {} /** * @return string this date in string format: Date(seconds=$seconds) * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Date/#method-__toString */ public function __toString() {} } /** * A PHP representation of a column * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultColumn/ */ final class DefaultColumn implements Column { /** * Returns the name of the column. * * @return string Name of the column or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultColumn/#method-name */ public function name() {} /** * Returns the type of the column. * * @return \Cassandra\Type Type of the column * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultColumn/#method-type */ public function type() {} /** * Returns whether the column is in descending or ascending order. * * @return bool Whether the column is stored in descending order. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultColumn/#method-isReversed */ public function isReversed() {} /** * Returns true for static columns. * * @return bool Whether the column is static * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultColumn/#method-isStatic */ public function isStatic() {} /** * Returns true for frozen columns. * * @return bool Whether the column is frozen * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultColumn/#method-isFrozen */ public function isFrozen() {} /** * Returns name of the index if defined. * * @return string Name of the index if defined or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultColumn/#method-indexName */ public function indexName() {} /** * Returns index options if present. * * @return string Index options if present or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultColumn/#method-indexOptions */ public function indexOptions() {} } /** * A PHP representation of the CQL `blob` datatype * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Blob/ */ final class Blob implements Value { /** * Creates a new bytes array. * * @param string $bytes any bytes * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Blob/#method-__construct */ public function __construct($bytes) {} /** * Returns bytes as a hex string. * * @return string bytes as hexadecimal string * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Blob/#method-__toString */ public function __toString() {} /** * The type of this blob. * * @return \Cassandra\Type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Blob/#method-type */ public function type() {} /** * Returns bytes as a hex string. * * @return string bytes as hexadecimal string * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Blob/#method-bytes */ public function bytes() {} /** * Returns bytes as a binary string. * * @return string bytes as binary string * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Blob/#method-toBinaryString */ public function toBinaryString() {} } /** * A PHP representation of a table * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/ */ final class DefaultTable implements Table { /** * Returns the name of this table * * @return string Name of the table * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-name */ public function name() {} /** * Return a table's option by name * * @param string $name The name of the option * * @return \Cassandra\Value Value of an option by name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-option */ public function option($name) {} /** * Returns all the table's options * * @return array A dictionary of `string` and `Value` pairs of the table's options. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-options */ public function options() {} /** * Description of the table, if any * * @return string Table description or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-comment */ public function comment() {} /** * Returns read repair chance * * @return float Read repair chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-readRepairChance */ public function readRepairChance() {} /** * Returns local read repair chance * * @return float Local read repair chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-localReadRepairChance */ public function localReadRepairChance() {} /** * Returns GC grace seconds * * @return int GC grace seconds * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-gcGraceSeconds */ public function gcGraceSeconds() {} /** * Returns caching options * * @return string Caching options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-caching */ public function caching() {} /** * Returns bloom filter FP chance * * @return float Bloom filter FP chance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-bloomFilterFPChance */ public function bloomFilterFPChance() {} /** * Returns memtable flush period in milliseconds * * @return int Memtable flush period in milliseconds * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-memtableFlushPeriodMs */ public function memtableFlushPeriodMs() {} /** * Returns default TTL. * * @return int Default TTL. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-defaultTTL */ public function defaultTTL() {} /** * Returns speculative retry. * * @return string Speculative retry. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-speculativeRetry */ public function speculativeRetry() {} /** * Returns index interval * * @return int Index interval * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-indexInterval */ public function indexInterval() {} /** * Returns compaction strategy class name * * @return string Compaction strategy class name * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-compactionStrategyClassName */ public function compactionStrategyClassName() {} /** * Returns compaction strategy options * * @return \Cassandra\Map Compaction strategy options * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-compactionStrategyOptions */ public function compactionStrategyOptions() {} /** * Returns compression parameters * * @return \Cassandra\Map Compression parameters * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-compressionParameters */ public function compressionParameters() {} /** * Returns whether or not the `populate_io_cache_on_flush` is true * * @return bool Value of `populate_io_cache_on_flush` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-populateIOCacheOnFlush */ public function populateIOCacheOnFlush() {} /** * Returns whether or not the `replicate_on_write` is true * * @return bool Value of `replicate_on_write` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-replicateOnWrite */ public function replicateOnWrite() {} /** * Returns the value of `max_index_interval` * * @return int Value of `max_index_interval` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-maxIndexInterval */ public function maxIndexInterval() {} /** * Returns the value of `min_index_interval` * * @return int Value of `min_index_interval` or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-minIndexInterval */ public function minIndexInterval() {} /** * Returns column by name * * @param string $name Name of the column * * @return \Cassandra\Column Column instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-column */ public function column($name) {} /** * Returns all columns in this table * * @return array A list of `Column` instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-columns */ public function columns() {} /** * Returns the partition key columns of the table * * @return array A list of `Column` instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-partitionKey */ public function partitionKey() {} /** * Returns both the partition and clustering key columns of the table * * @return array A list of `Column` instance * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-primaryKey */ public function primaryKey() {} /** * Returns the clustering key columns of the table * * @return array A list of `Column` instances * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-clusteringKey */ public function clusteringKey() {} /** * @return array A list of cluster column orders ('asc' and 'desc') * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-clusteringOrder */ public function clusteringOrder() {} /** * Get an index by name * * @param string $name Index name * * @return \Cassandra\Index|null An index or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-index */ public function index($name) {} /** * Gets all indexes * * @return array An array of indexes * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-indexes */ public function indexes() {} /** * Get materialized view by name * * @param string $name Materialized view name * * @return \Cassandra\MaterializedView|null A materialized view or null * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-materializedView */ public function materializedView($name) {} /** * Gets all materialized views * * @return array An array of materialized views * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.DefaultTable/#method-materializedViews */ public function materializedViews() {} } /** * A future that always resolves in a value. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.FutureValue/ */ final class FutureValue implements Future { /** * Waits for a given future resource to resolve and throws errors if any. * * @param int|float|null $timeout A timeout in seconds * * @return mixed A value * @throws \Cassandra\Exception\TimeoutException * * @throws \Cassandra\Exception\InvalidArgumentException * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.FutureValue/#method-get */ public function get($timeout) {} } /** * A PHP representation of the CQL `decimal` datatype * * The actual value of a decimal is `$value * pow(10, $scale * -1)` * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/class.Decimal/ */ final class Decimal implements Value, Numeric { /** * Creates a decimal from a given decimal string: * * ~~~{.php} * schema() will always return an empty object. This * can be useful for reducing the startup overhead of short-lived sessions. * * @param bool $enabled whether the driver fetches and maintains schema metadata. * * @return \Cassandra\Cluster\Builder self * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Cluster/class.Builder/#method-withSchemaMetadata */ public function withSchemaMetadata($enabled) {} /** * Enables/disables Hostname Resolution. * * If enabled the driver will resolve hostnames for IP addresses using * reverse IP lookup. This is useful for authentication (Kerberos) or * encryption SSL services that require a valid hostname for verification. * * Important: It's possible that the underlying C/C++ driver does not * support hostname resolution. A PHP warning will be emitted if the driver * does not support hostname resolution. * * @param bool $enabled whether the driver uses hostname resolution. * * @return \Cassandra\Cluster\Builder self * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Cluster/class.Builder/#method-withHostnameResolution */ public function withHostnameResolution($enabled) {} /** * Enables/disables Randomized Contact Points. * * If enabled this allows the driver randomly use contact points in order * to evenly spread the load across the cluster and prevent * hotspots/load spikes during notifications (e.g. massive schema change). * * Note: This setting should only be disabled for debugging and testing. * * @param bool $enabled whether the driver uses randomized contact points. * * @return \Cassandra\Cluster\Builder self * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Cluster/class.Builder/#method-withRandomizedContactPoints */ public function withRandomizedContactPoints($enabled) {} /** * Specify interval in seconds that the driver should wait before attempting * to send heartbeat messages and control the amount of time the connection * must be idle before sending heartbeat messages. This is useful for * preventing intermediate network devices from dropping connections. * * @param float $interval interval in seconds (0 to disable heartbeat). * * @return \Cassandra\Cluster\Builder self * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Cluster/class.Builder/#method-withConnectionHeartbeatInterval */ public function withConnectionHeartbeatInterval($interval) {} } } /** * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/TimestampGenerator/ */ namespace Cassandra\TimestampGenerator { /** * A timestamp generator that allows the server-side to assign timestamps. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/TimestampGenerator/class.ServerSide/ */ final class ServerSide implements \Cassandra\TimestampGenerator {} /** * A timestamp generator that generates monotonically increasing timestamps * client-side. The timestamps generated have a microsecond granularity with * the sub-millisecond part generated using a counter. The implementation * guarantees that no more than 1000 timestamps will be generated for a given * clock tick even if shared by multiple session objects. If that rate is * exceeded then a warning is logged and timestamps stop incrementing until * the next clock tick. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/TimestampGenerator/class.Monotonic/ */ final class Monotonic implements \Cassandra\TimestampGenerator {} } /** * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/RetryPolicy/ */ namespace Cassandra\RetryPolicy { /** * The default retry policy. This policy retries a query, using the * request's original consistency level, in the following cases: * * * On a read timeout, if enough replicas replied but the data was not received. * * On a write timeout, if a timeout occurs while writing a distributed batch log. * * On unavailable, it will move to the next host. * * In all other cases the error will be returned. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/RetryPolicy/class.DefaultPolicy/ */ final class DefaultPolicy implements \Cassandra\RetryPolicy {} /** * A retry policy that will downgrade the consistency of a request in * an attempt to save a request in cases where there is any chance of success. A * write request will succeed if there is at least a single copy persisted and a * read request will succeed if there is some data available even if it increases * the risk of reading stale data. This policy will retry in the same scenarios as * the default policy, and it will also retry in the following case: * * * On a read timeout, if some replicas responded but is lower than * required by the current consistency level then retry with a lower * consistency level * * On a write timeout, Retry unlogged batches at a lower consistency level * if at least one replica responded. For single queries and batch if any * replicas responded then consider the request successful and swallow the * error. * * On unavailable, retry at a lower consistency if at lease one replica * responded. * * Important: This policy may attempt to retry requests with a lower * consistency level. Using this policy can break consistency guarantees. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/RetryPolicy/class.DowngradingConsistency/ */ final class DowngradingConsistency implements \Cassandra\RetryPolicy {} /** * A retry policy that never retries and allows all errors to fallthrough. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/RetryPolicy/class.Fallthrough/ */ final class Fallthrough implements \Cassandra\RetryPolicy {} /** * A retry policy that logs the decisions of its child policy. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/RetryPolicy/class.Logging/ */ final class Logging implements \Cassandra\RetryPolicy { /** * Creates a new Logging retry policy. * * @param \Cassandra\RetryPolicy $childPolicy Any retry policy other than Logging * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/RetryPolicy/class.Logging/#method-__construct */ public function __construct($childPolicy) {} } } /** * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/ */ namespace Cassandra\Type { /** * A class that represents the tuple type. The tuple type is able to represent * a composite type of one or more types accessed by index. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Tuple/ */ final class Tuple extends \Cassandra\Type { private function __construct() {} /** * Returns "tuple" * * @return string "tuple" * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Tuple/#method-name */ public function name() {} /** * Returns type representation in CQL, e.g. `tuple` * * @return string Type representation in CQL * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Tuple/#method-__toString */ public function __toString() {} /** * Returns types of values * * @return array An array of types * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Tuple/#method-types */ public function types() {} /** * Creates a new Tuple from the given values. When no values given, * creates a tuple with null for the values. * * @param mixed ...$values One or more values to be added to the tuple. * * @return \Cassandra\Tuple A tuple with given values. * @throws \Cassandra\Exception\InvalidArgumentException when values given are of a * different type than what the * tuple expects. * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Tuple/#method-create */ public function create(...$values) {} } /** * A class that represents the list type. The list type contains the type of the * elements contain in the list. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Collection/ */ final class Collection extends \Cassandra\Type { private function __construct() {} /** * Returns "list" * * @return string "list" * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Collection/#method-name */ public function name() {} /** * Returns type of values * * @return \Cassandra\Type Type of values * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Collection/#method-valueType */ public function valueType() {} /** * Returns type representation in CQL, e.g. `list` * * @return string Type representation in CQL * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Collection/#method-__toString */ public function __toString() {} /** * Creates a new Collection from the given values. When no values * given, creates an empty list. * * @param mixed ...$value One or more values to be added to the list. * * @return \Cassandra\Collection A list with given values. * @throws \Cassandra\Exception\InvalidArgumentException when values given are of a * different type than what this * list type expects. * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Collection/#method-create */ public function create(...$value) {} } /** * A class that represents the set type. The set type contains the type of the * elements contain in the set. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Set/ */ final class Set extends \Cassandra\Type { private function __construct() {} /** * Returns "set" * * @return string "set" * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Set/#method-name */ public function name() {} /** * Returns type of values * * @return \Cassandra\Type Type of values * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Set/#method-valueType */ public function valueType() {} /** * Returns type representation in CQL, e.g. `set` * * @return string Type representation in CQL * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Set/#method-__toString */ public function __toString() {} /** * Creates a new Set from the given values. * * @param mixed ...$value One or more values to be added to the set. When no values are given, creates an empty set. * * @return \Cassandra\Set A set with given values. * @throws \Cassandra\Exception\InvalidArgumentException when values given are of a * different type than what this * set type expects. * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Set/#method-create */ public function create(...$value) {} } /** * A class that represents a custom type. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Custom/ */ final class Custom extends \Cassandra\Type { private function __construct() {} /** * Returns the name of this type as string. * * @return string The name of this type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Custom/#method-name */ public function name() {} /** * Returns string representation of this type. * * @return string String representation of this type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Custom/#method-__toString */ public function __toString() {} /** * @param mixed $value * * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Custom/#method-create */ public function create($value) {} } /** * A class that represents a user type. The user type is able to represent a * composite type of one or more types accessed by name. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.UserType/ */ final class UserType extends \Cassandra\Type { private function __construct() {} /** * Associate the user type with a name. * * @param string $name Name of the user type. * * @return null Nothing. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.UserType/#method-withName */ public function withName($name) {} /** * Returns type name for the user type * * @return string Name of this type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.UserType/#method-name */ public function name() {} /** * Associate the user type with a keyspace. * * @param string $keyspace Keyspace that contains the user type. * * @return null Nothing. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.UserType/#method-withKeyspace */ public function withKeyspace($keyspace) {} /** * Returns keyspace for the user type * * @return string * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.UserType/#method-keyspace */ public function keyspace() {} /** * Returns type representation in CQL, e.g. keyspace1.type_name1 or * `userType`. * * @return string Type representation in CQL * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.UserType/#method-__toString */ public function __toString() {} /** * Returns types of values * * @return array An array of types * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.UserType/#method-types */ public function types() {} /** * Creates a new UserTypeValue from the given name/value pairs. When * no values given, creates an empty user type. * * @param mixed ...$value One or more name/value pairs to be added to the user type. * * @return \Cassandra\UserTypeValue A user type value with given name/value pairs. * @throws \Cassandra\Exception\InvalidArgumentException when values given are of a * different types than what the * user type expects. * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.UserType/#method-create */ public function create(...$value) {} } /** * A class that represents the map type. The map type contains two types that * represents the types of the key and value contained in the map. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Map/ */ final class Map extends \Cassandra\Type { private function __construct() {} /** * Returns "map" * * @return string "map" * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Map/#method-name */ public function name() {} /** * Returns type of keys * * @return \Cassandra\Type Type of keys * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Map/#method-keyType */ public function keyType() {} /** * Returns type of values * * @return \Cassandra\Type Type of values * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Map/#method-valueType */ public function valueType() {} /** * Returns type representation in CQL, e.g. `map` * * @return string Type representation in CQL * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Map/#method-__toString */ public function __toString() {} /** * Creates a new Map from the given values. * * ```create(new Uuid(), 'first uuid', * new Uuid(), 'second uuid', * new Uuid(), 'third uuid'); * * var_dump($map);``` * * * is a key and each even value is a value for the * map, e.g. `create(key, value, key, value)`. * When no values given, creates an empty map. * * @param mixed ...$value An even number of values, where each odd value * * @return \Cassandra\Map A set with given values. * @throws \Cassandra\Exception\InvalidArgumentException when keys or values given are * of a different type than what * this map type expects. * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Map/#method-create */ public function create(...$value) {} } /** * A class that represents a primitive type (e.g. `varchar` or `bigint`) * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Scalar/ */ final class Scalar extends \Cassandra\Type { private function __construct() {} /** * Returns the name of this type as string. * * @return string Name of this type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Scalar/#method-name */ public function name() {} /** * Returns string representation of this type. * * @return string String representation of this type * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Scalar/#method-__toString */ public function __toString() {} /** * @param mixed $value * * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Type/class.Scalar/#method-create */ public function create($value) {} } } /** * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/SSLOptions/ */ namespace Cassandra\SSLOptions { /** * SSLOptions builder allows fluent configuration of ssl options. * * @see \Cassandra::ssl() * @see \Cassandra\Cluster\Builder::withSSL() * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/SSLOptions/class.Builder/ */ final class Builder { /** * Builds SSL options. * * @return \Cassandra\SSLOptions ssl options configured accordingly. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/SSLOptions/class.Builder/#method-build */ public function build() {} /** * Adds a trusted certificate. This is used to verify node's identity. * * @param string ...$path one or more paths to files containing a PEM formatted certificate. * * @return \Cassandra\Cluster\Builder self * @throws \Cassandra\Exception\InvalidArgumentException * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/SSLOptions/class.Builder/#method-withTrustedCerts */ public function withTrustedCerts(...$path) {} /** * Disable certificate verification. * * @param int $flags * * @return \Cassandra\Cluster\Builder self * @throws \Cassandra\Exception\InvalidArgumentException * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/SSLOptions/class.Builder/#method-withVerifyFlags */ public function withVerifyFlags($flags) {} /** * Set client-side certificate chain. * * This is used to authenticate the client on the server-side. This should contain the entire Certificate * chain starting with the certificate itself. * * @param string $path path to a file containing a PEM formatted certificate. * * @return \Cassandra\Cluster\Builder self * @throws \Cassandra\Exception\InvalidArgumentException * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/SSLOptions/class.Builder/#method-withClientCert */ public function withClientCert($path) {} /** * Set client-side private key. This is used to authenticate the client on * the server-side. * * @param string $path Path to the private key file * @param string|null $passphrase Passphrase for the private key, if any * * @return \Cassandra\Cluster\Builder self * @throws \Cassandra\Exception\InvalidArgumentException * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/SSLOptions/class.Builder/#method-withPrivateKey */ public function withPrivateKey($path, $passphrase) {} } } /** * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/ */ namespace Cassandra\Exception { use JetBrains\PhpStorm\Pure; /** * ConfigurationException is raised when query is syntactically correct but * invalid because of some configuration issue. * For example when attempting to drop a non-existent keyspace. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ConfigurationException/ */ class ConfigurationException extends ValidationException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ConfigurationException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ConfigurationException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ConfigurationException/#method-__toString */ public function __toString() {} } /** * Cassandra domain exception. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.DomainException/ */ class DomainException extends \DomainException implements \Cassandra\Exception { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.DomainException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.DomainException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.DomainException/#method-__toString */ public function __toString() {} } /** * InvalidQueryException is raised when query is syntactically correct but invalid. * For example when attempting to create a table without specifying a keyspace. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidQueryException/ */ class InvalidQueryException extends ValidationException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidQueryException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidQueryException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidQueryException/#method-__toString */ public function __toString() {} } /** * UnpreparedException is raised when a given prepared statement id does not * exist on the server. The driver should be automatically re-preparing the * statement in this case. Seeing this error could be considered a bug. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnpreparedException/ */ class UnpreparedException extends ValidationException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnpreparedException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnpreparedException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnpreparedException/#method-__toString */ public function __toString() {} } /** * Cassandra invalid argument exception. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidArgumentException/ */ class InvalidArgumentException extends \InvalidArgumentException implements \Cassandra\Exception { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidArgumentException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidArgumentException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidArgumentException/#method-__toString */ public function __toString() {} } /** * ServerException is raised when something unexpected happened on the server. * This exception is most likely due to a server-side bug. * **NOTE** This exception and all its children are generated on the server. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ServerException/ */ class ServerException extends RuntimeException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ServerException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ServerException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ServerException/#method-__toString */ public function __toString() {} } /** * Cassandra domain exception. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.RangeException/ */ class RangeException extends \RangeException implements \Cassandra\Exception { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.RangeException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.RangeException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.RangeException/#method-__toString */ public function __toString() {} } /** * UnauthorizedException is raised when the current user doesn't have * sufficient permissions to access data. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnauthorizedException/ */ class UnauthorizedException extends ValidationException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnauthorizedException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnauthorizedException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnauthorizedException/#method-__toString */ public function __toString() {} } /** * Cassandra logic exception. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.LogicException/ */ class LogicException extends \LogicException implements \Cassandra\Exception { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.LogicException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.LogicException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.LogicException/#method-__toString */ public function __toString() {} } /** * UnavailableException is raised when a coordinator detected that there aren't * enough replica nodes available to fulfill the request. * * NOTE: Request has not even been forwarded to the replica nodes in this case. * @see https://github.com/apache/cassandra/blob/cassandra-2.1/doc/native_protocol_v1.spec#L667-L677 Description of the Unavailable error in the native protocol v1 spec. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnavailableException/ */ class UnavailableException extends ExecutionException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnavailableException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnavailableException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.UnavailableException/#method-__toString */ public function __toString() {} } /** * AuthenticationException is raised when client was not configured with valid * authentication credentials. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.AuthenticationException/ */ class AuthenticationException extends RuntimeException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.AuthenticationException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.AuthenticationException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.AuthenticationException/#method-__toString */ public function __toString() {} } /** * OverloadedException is raised when a node is overloaded. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.OverloadedException/ */ class OverloadedException extends ServerException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.OverloadedException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.OverloadedException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.OverloadedException/#method-__toString */ public function __toString() {} } /** * ReadTimeoutException is raised when a coordinator failed to receive acks * from the required number of replica nodes in time during a read. * @see https://github.com/apache/cassandra/blob/cassandra-2.1/doc/native_protocol_v1.spec#L709-L726 Description of ReadTimeout error in the native protocol spec * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ReadTimeoutException/ */ class ReadTimeoutException extends ExecutionException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ReadTimeoutException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ReadTimeoutException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ReadTimeoutException/#method-__toString */ public function __toString() {} } /** * IsBootstrappingException is raised when a node is bootstrapping. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.IsBootstrappingException/ */ class IsBootstrappingException extends ServerException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.IsBootstrappingException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.IsBootstrappingException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.IsBootstrappingException/#method-__toString */ public function __toString() {} } /** * ProtocolException is raised when a client did not follow server's protocol, * e.g. sending a QUERY message before STARTUP. Seeing this error can be * considered a bug. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ProtocolException/ */ class ProtocolException extends RuntimeException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ProtocolException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ProtocolException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ProtocolException/#method-__toString */ public function __toString() {} } /** * ExecutionException is raised when something went wrong during request execution. * @see \Cassandra\Exception\TruncateException * @see \Cassandra\Exception\UnavailableException * @see \Cassandra\Exception\ReadTimeoutException * @see \Cassandra\Exception\WriteTimeoutException * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ExecutionException/ */ class ExecutionException extends RuntimeException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ExecutionException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ExecutionException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ExecutionException/#method-__toString */ public function __toString() {} } /** * InvalidSyntaxException is raised when CQL in the request is syntactically incorrect. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidSyntaxException/ */ class InvalidSyntaxException extends ValidationException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidSyntaxException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidSyntaxException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.InvalidSyntaxException/#method-__toString */ public function __toString() {} } /** * Cassandra runtime exception. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.RuntimeException/ */ class RuntimeException extends \RuntimeException implements \Cassandra\Exception { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.RuntimeException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.RuntimeException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.RuntimeException/#method-__toString */ public function __toString() {} } /** * TimeoutException is generally raised when a future did not resolve * within a given time interval. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.TimeoutException/ */ class TimeoutException extends RuntimeException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.TimeoutException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.TimeoutException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.TimeoutException/#method-__toString */ public function __toString() {} } /** * ValidationException is raised on invalid request, before even attempting to * execute it. * @see \Cassandra\Exception\InvalidSyntaxException * @see \Cassandra\Exception\UnauthorizedException * @see \Cassandra\Exception\InvalidQueryException * @see \Cassandra\Exception\ConfigurationException * @see \Cassandra\Exception\AlreadyExistsException * @see \Cassandra\Exception\UnpreparedException * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ValidationException/ */ class ValidationException extends RuntimeException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ValidationException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ValidationException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.ValidationException/#method-__toString */ public function __toString() {} } /** * TruncateException is raised when something went wrong during table * truncation. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.TruncateException/ */ class TruncateException extends ExecutionException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.TruncateException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.TruncateException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.TruncateException/#method-__toString */ public function __toString() {} } /** * AlreadyExistsException is raised when attempting to re-create existing keyspace. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.AlreadyExistsException/ */ class AlreadyExistsException extends ConfigurationException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.AlreadyExistsException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.AlreadyExistsException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.AlreadyExistsException/#method-__toString */ public function __toString() {} } /** * Cassandra domain exception. * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.DivideByZeroException/ */ class DivideByZeroException extends RangeException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.DivideByZeroException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.DivideByZeroException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.DivideByZeroException/#method-__toString */ public function __toString() {} } /** * WriteTimeoutException is raised when a coordinator failed to receive acks * from the required number of replica nodes in time during a write. * @see https://github.com/apache/cassandra/blob/cassandra-2.1/doc/native_protocol_v1.spec#L683-L708 Description of WriteTimeout error in the native protocol spec * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.WriteTimeoutException/ */ class WriteTimeoutException extends ExecutionException { /** * @param mixed $message * @param mixed $code * @param mixed $previous * * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.WriteTimeoutException/#method-__construct */ #[Pure] public function __construct($message, $code, $previous) {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.WriteTimeoutException/#method-__wakeup */ public function __wakeup() {} /** * @return mixed * @link https://docs.datastax.com/en/developer/php-driver/latest/api/Cassandra/Exception/class.WriteTimeoutException/#method-__toString */ public function __toString() {} } } * Construct a Phar archive object * @link https://php.net/manual/en/phar.construct.php * @param string $filename

    * Path to an existing Phar archive or to-be-created archive. The file name's * extension must contain .phar. *

    * @param int $flags [optional]

    * Flags to pass to parent class RecursiveDirectoryIterator. *

    * @param string $alias [optional]

    * Alias with which this Phar archive should be referred to in calls to stream * functionality. *

    * @throws BadMethodCallException If called twice. * @throws UnexpectedValueException If the phar archive can't be opened. */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = FilesystemIterator::SKIP_DOTS|FilesystemIterator::UNIX_PATHS, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $alias = null, #[PhpStormStubsElementAvailable(from: '5.3', to: '5.6')] $fileformat = null ) {} public function __destruct() {} /** * (Unknown)
    * Add an empty directory to the phar archive * @link https://php.net/manual/en/phar.addemptydir.php * @param string $directory

    * The name of the empty directory to create in the phar archive *

    * @return void no return value, exception is thrown on failure. */ #[TentativeType] public function addEmptyDir( #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $directory = '', #[PhpStormStubsElementAvailable(from: '8.0')] string $directory ): void {} /** * (Unknown)
    * Add a file from the filesystem to the phar archive * @link https://php.net/manual/en/phar.addfile.php * @param string $filename

    * Full or relative path to a file on disk to be added * to the phar archive. *

    * @param string $localName [optional]

    * Path that the file will be stored in the archive. *

    * @return void no return value, exception is thrown on failure. */ #[TentativeType] public function addFile( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $localName = null ): void {} /** * (Unknown)
    * Add a file from the filesystem to the phar archive * @link https://php.net/manual/en/phar.addfromstring.php * @param string $localName

    * Path that the file will be stored in the archive. *

    * @param string $contents

    * The file contents to store *

    * @return void no return value, exception is thrown on failure. */ #[TentativeType] public function addFromString( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $contents = '', #[PhpStormStubsElementAvailable(from: '8.0')] string $contents ): void {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Construct a phar archive from the files within a directory. * @link https://php.net/manual/en/phar.buildfromdirectory.php * @param string $directory

    * The full or relative path to the directory that contains all files * to add to the archive. *

    * @param $pattern $regex [optional]

    * An optional pcre regular expression that is used to filter the * list of files. Only file paths matching the regular expression * will be included in the archive. *

    * @return array Phar::buildFromDirectory returns an associative array * mapping internal path of file to the full path of the file on the * filesystem. */ #[TentativeType] public function buildFromDirectory( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $directory, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $pattern = '' ): array {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Construct a phar archive from an iterator. * @link https://php.net/manual/en/phar.buildfromiterator.php * @param Traversable $iterator

    * Any iterator that either associatively maps phar file to location or * returns SplFileInfo objects *

    * @param string $baseDirectory [optional]

    * For iterators that return SplFileInfo objects, the portion of each * file's full path to remove when adding to the phar archive *

    * @return array Phar::buildFromIterator returns an associative array * mapping internal path of file to the full path of the file on the * filesystem. */ #[TentativeType] public function buildFromIterator( Traversable $iterator, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $baseDirectory = null ): array {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Compresses all files in the current Phar archive * @link https://php.net/manual/en/phar.compressfiles.php * @param int $compression

    * Compression must be one of Phar::GZ, * Phar::BZ2 to add compression, or Phar::NONE * to remove compression. *

    * @return void No value is returned. */ #[TentativeType] public function compressFiles(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $compression): void {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Decompresses all files in the current Phar archive * @link https://php.net/manual/en/phar.decompressfiles.php * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function decompressFiles() {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Compresses the entire Phar archive using Gzip or Bzip2 compression * @link https://php.net/manual/en/phar.compress.php * @param int $compression

    * Compression must be one of Phar::GZ, * Phar::BZ2 to add compression, or Phar::NONE * to remove compression. *

    * @param string $extension [optional]

    * By default, the extension is .phar.gz * or .phar.bz2 for compressing phar archives, and * .phar.tar.gz or .phar.tar.bz2 for * compressing tar archives. For decompressing, the default file extensions * are .phar and .phar.tar. *

    * @return static|null a Phar object. */ #[TentativeType] public function compress( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $compression, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $extension = null ): ?Phar {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Decompresses the entire Phar archive * @link https://php.net/manual/en/phar.decompress.php * @param string $extension [optional]

    * For decompressing, the default file extensions * are .phar and .phar.tar. * Use this parameter to specify another file extension. Be aware * that all executable phar archives must contain .phar * in their filename. *

    * @return static|null A Phar object is returned. */ #[TentativeType] public function decompress(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $extension = null): ?Phar {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Convert a phar archive to another executable phar archive file format * @link https://php.net/manual/en/phar.converttoexecutable.php * @param int $format [optional]

    * This should be one of Phar::PHAR, Phar::TAR, * or Phar::ZIP. If set to NULL, the existing file format * will be preserved. *

    * @param int $compression [optional]

    * This should be one of Phar::NONE for no whole-archive * compression, Phar::GZ for zlib-based compression, and * Phar::BZ2 for bzip-based compression. *

    * @param string $extension [optional]

    * This parameter is used to override the default file extension for a * converted archive. Note that all zip- and tar-based phar archives must contain * .phar in their file extension in order to be processed as a * phar archive. *

    *

    * If converting to a phar-based archive, the default extensions are * .phar, .phar.gz, or .phar.bz2 * depending on the specified compression. For tar-based phar archives, the * default extensions are .phar.tar, .phar.tar.gz, * and .phar.tar.bz2. For zip-based phar archives, the * default extension is .phar.zip. *

    * @return Phar|null The method returns a Phar object on success and throws an * exception on failure. */ #[TentativeType] public function convertToExecutable( #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $format = null, #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $compression = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $extension = null ): ?Phar {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Convert a phar archive to a non-executable tar or zip file * @link https://php.net/manual/en/phar.converttodata.php * @param int $format [optional]

    * This should be one of Phar::TAR * or Phar::ZIP. If set to NULL, the existing file format * will be preserved. *

    * @param int $compression [optional]

    * This should be one of Phar::NONE for no whole-archive * compression, Phar::GZ for zlib-based compression, and * Phar::BZ2 for bzip-based compression. *

    * @param string $extension [optional]

    * This parameter is used to override the default file extension for a * converted archive. Note that .phar cannot be used * anywhere in the filename for a non-executable tar or zip archive. *

    *

    * If converting to a tar-based phar archive, the * default extensions are .tar, .tar.gz, * and .tar.bz2 depending on specified compression. * For zip-based archives, the * default extension is .zip. *

    * @return PharData|null The method returns a PharData object on success and throws an * exception on failure. */ #[TentativeType] public function convertToData( #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $format = null, #[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $compression = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $extension = null ): ?PharData {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Copy a file internal to the phar archive to another new file within the phar * @link https://php.net/manual/en/phar.copy.php * @param string $to * @param string $from * @return bool returns TRUE on success, but it is safer to encase method call in a * try/catch block and assume success if no exception is thrown. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function copy( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $to, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $from ) {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns the number of entries (files) in the Phar archive * @link https://php.net/manual/en/phar.count.php * @param int $mode [optional] * @return int<0,max> The number of files contained within this phar, or 0 (the number zero) * if none. */ #[TentativeType] public function count(#[PhpStormStubsElementAvailable(from: '8.0')] int $mode = COUNT_NORMAL): int {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Delete a file within a phar archive * @link https://php.net/manual/en/phar.delete.php * @param string $localName

    * Path within an archive to the file to delete. *

    * @return bool returns TRUE on success, but it is better to check for thrown exception, * and assume success if none is thrown. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function delete(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $localName) {} /** * (PHP >= 5.3.0, PECL phar >= 1.2.0)
    * Deletes the global metadata of the phar * @link https://php.net/manual/en/phar.delmetadata.php * @return bool returns TRUE on success, but it is better to check for thrown exception, * and assume success if none is thrown. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function delMetadata() {} /** * (Unknown)
    * Extract the contents of a phar archive to a directory * @link https://php.net/manual/en/phar.extractto.php * @param string $directory

    * Path within an archive to the file to delete. *

    * @param string|array|null $files [optional]

    * The name of a file or directory to extract, or an array of files/directories to extract *

    * @param bool $overwrite [optional]

    * Set to TRUE to enable overwriting existing files *

    * @return bool returns TRUE on success, but it is better to check for thrown exception, * and assume success if none is thrown. */ #[TentativeType] public function extractTo( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $directory, #[LanguageLevelTypeAware(['8.0' => 'array|string|null'], default: '')] $files = null, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $overwrite = false ): bool {} /** * @return string|null * @see setAlias */ #[TentativeType] public function getAlias(): ?string {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns phar archive meta-data * @link https://php.net/manual/en/phar.getmetadata.php * @param array $unserializeOptions [optional] if is set to anything other than the default, * the resulting metadata won't be cached and this won't return the value from the cache * @return mixed any PHP variable that can be serialized and is stored as meta-data for the Phar archive, * or NULL if no meta-data is stored. */ #[TentativeType] public function getMetadata(#[PhpStormStubsElementAvailable(from: '8.0')] array $unserializeOptions = []): mixed {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Return whether phar was modified * @link https://php.net/manual/en/phar.getmodified.php * @return bool TRUE if the phar has been modified since opened, FALSE if not. */ #[TentativeType] public function getModified(): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Return MD5/SHA1/SHA256/SHA512/OpenSSL signature of a Phar archive * @link https://php.net/manual/en/phar.getsignature.php * @return array Array with the opened archive's signature in hash key and MD5, * SHA-1, * SHA-256, SHA-512, or OpenSSL * in hash_type. This signature is a hash calculated on the * entire phar's contents, and may be used to verify the integrity of the archive. * A valid signature is absolutely required of all executable phar archives if the * phar.require_hash INI variable * is set to true. */ #[ArrayShape(["hash" => "string", "hash_type" => "string"])] #[TentativeType] public function getSignature(): array|false {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Return the PHP loader or bootstrap stub of a Phar archive * @link https://php.net/manual/en/phar.getstub.php * @return string a string containing the contents of the bootstrap loader (stub) of * the current Phar archive. */ #[TentativeType] public function getStub(): string {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Return version info of Phar archive * @link https://php.net/manual/en/phar.getversion.php * @return string The opened archive's API version. This is not to be confused with * the API version that the loaded phar extension will use to create * new phars. Each Phar archive has the API version hard-coded into * its manifest. See Phar file format * documentation for more information. */ #[TentativeType] public function getVersion(): string {} /** * (PHP >= 5.3.0, PECL phar >= 1.2.0)
    * Returns whether phar has global meta-data * @link https://php.net/manual/en/phar.hasmetadata.php * @return bool TRUE if meta-data has been set, and FALSE if not. */ #[TentativeType] public function hasMetadata(): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Used to determine whether Phar write operations are being buffered, or are flushing directly to disk * @link https://php.net/manual/en/phar.isbuffering.php * @return bool TRUE if the write operations are being buffer, FALSE otherwise. */ #[TentativeType] public function isBuffering(): bool {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Returns Phar::GZ or PHAR::BZ2 if the entire phar archive is compressed (.tar.gz/tar.bz and so on) * @link https://php.net/manual/en/phar.iscompressed.php * @return mixed Phar::GZ, Phar::BZ2 or FALSE */ #[TentativeType] public function isCompressed(): int|false {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Returns true if the phar archive is based on the tar/phar/zip file format depending on the parameter * @link https://php.net/manual/en/phar.isfileformat.php * @param int $format

    * Either Phar::PHAR, Phar::TAR, or * Phar::ZIP to test for the format of the archive. *

    * @return bool TRUE if the phar archive matches the file format requested by the parameter */ #[TentativeType] public function isFileFormat(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $format): bool {} /** * (Unknown)
    * Returns true if the phar archive can be modified * @link https://php.net/manual/en/phar.iswritable.php * @return bool TRUE if the phar archive can be modified */ #[TentativeType] public function isWritable(): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * determines whether a file exists in the phar * @link https://php.net/manual/en/phar.offsetexists.php * @param string $localName

    * The filename (relative path) to look for in a Phar. *

    * @return bool TRUE if the file exists within the phar, or FALSE if not. */ #[TentativeType] public function offsetExists($localName): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Gets a PharFileInfo object for a specific file * @link https://php.net/manual/en/phar.offsetget.php * @param string $localName

    * The filename (relative path) to look for in a Phar. *

    * @return PharFileInfo A PharFileInfo object is returned that can be used to * iterate over a file's contents or to retrieve information about the current file. */ #[TentativeType] public function offsetGet($localName): SplFileInfo {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * set the contents of an internal file to those of an external file * @link https://php.net/manual/en/phar.offsetset.php * @param string $localName

    * The filename (relative path) to modify in a Phar. *

    * @param string $value

    * Content of the file. *

    * @return void No return values. */ #[TentativeType] public function offsetSet($localName, $value): void {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * remove a file from a phar * @link https://php.net/manual/en/phar.offsetunset.php * @param string $localName

    * The filename (relative path) to modify in a Phar. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function offsetUnset($localName): void {} /** * (PHP >= 5.3.0, PECL phar >= 1.2.1)
    * Set the alias for the Phar archive * @link https://php.net/manual/en/phar.setalias.php * @param string $alias

    * A shorthand string that this archive can be referred to in phar * stream wrapper access. *

    * @return bool */ #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] public function setAlias(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $alias) {} /** * (Unknown)
    * Used to set the PHP loader or bootstrap stub of a Phar archive to the default loader * @link https://php.net/manual/en/phar.setdefaultstub.php * @param string $index [optional]

    * Relative path within the phar archive to run if accessed on the command-line *

    * @param string $webIndex [optional]

    * Relative path within the phar archive to run if accessed through a web browser *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] public function setDefaultStub( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $index = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $webIndex = null ) {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Sets phar archive meta-data * @link https://php.net/manual/en/phar.setmetadata.php * @param mixed $metadata

    * Any PHP variable containing information to store that describes the phar archive *

    * @return void No value is returned. */ #[TentativeType] public function setMetadata(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $metadata): void {} /** * (PHP >= 5.3.0, PECL phar >= 1.1.0)
    * set the signature algorithm for a phar and apply it. * @link https://php.net/manual/en/phar.setsignaturealgorithm.php * @param int $algo

    * One of Phar::MD5, * Phar::SHA1, Phar::SHA256, * Phar::SHA512, or Phar::OPENSSL *

    * @param string $privateKey [optional]

    * The contents of an OpenSSL private key, as extracted from a certificate or * OpenSSL key file: * * $private = openssl_get_privatekey(file_get_contents('private.pem')); * $pkey = ''; * openssl_pkey_export($private, $pkey); * $p->setSignatureAlgorithm(Phar::OPENSSL, $pkey); * * See phar introduction for instructions on * naming and placement of the public key file. *

    * @return void No value is returned. */ #[TentativeType] public function setSignatureAlgorithm( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $algo, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $privateKey = null ): void {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Used to set the PHP loader or bootstrap stub of a Phar archive * @link https://php.net/manual/en/phar.setstub.php * @param string $stub

    * A string or an open stream handle to use as the executable stub for this * phar archive. *

    * @param int $length [optional]

    *

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function setStub( $stub, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $length ) {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Start buffering Phar write operations, do not modify the Phar object on disk * @link https://php.net/manual/en/phar.startbuffering.php * @return void No value is returned. */ #[TentativeType] public function startBuffering(): void {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Stop buffering write requests to the Phar archive, and save changes to disk * @link https://php.net/manual/en/phar.stopbuffering.php * @return void No value is returned. */ #[TentativeType] public function stopBuffering(): void {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns the api version * @link https://php.net/manual/en/phar.apiversion.php * @return string The API version string as in "1.0.0". */ final public static function apiVersion(): string {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns whether phar extension supports compression using either zlib or bzip2 * @link https://php.net/manual/en/phar.cancompress.php * @param int $compression [optional]

    * Either Phar::GZ or Phar::BZ2 can be * used to test whether compression is possible with a specific compression * algorithm (zlib or bzip2). *

    * @return bool TRUE if compression/decompression is available, FALSE if not. */ final public static function canCompress(int $compression = 0): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns whether phar extension supports writing and creating phars * @link https://php.net/manual/en/phar.canwrite.php * @return bool TRUE if write access is enabled, FALSE if it is disabled. */ final public static function canWrite(): bool {} /** * (Unknown)
    * Create a phar-file format specific stub * @link https://php.net/manual/en/phar.createdefaultstub.php * @param string|null $index [optional] * @param string|null $webIndex [optional] * @return string a string containing the contents of a customized bootstrap loader (stub) * that allows the created Phar archive to work with or without the Phar extension * enabled. */ final public static function createDefaultStub(?string $index = null, ?string $webIndex = null): string {} /** * (PHP >= 5.3.0, PECL phar >= 1.2.0)
    * Return array of supported compression algorithms * @link https://php.net/manual/en/phar.getsupportedcompression.php * @return string[] an array containing any of "GZ" or * "BZ2", depending on the availability of * the zlib extension or the * bz2 extension. */ final public static function getSupportedCompression(): array {} /** * (PHP >= 5.3.0, PECL phar >= 1.1.0)
    * Return array of supported signature types * @link https://php.net/manual/en/phar.getsupportedsignatures.php * @return string[] an array containing any of "MD5", "SHA-1", * "SHA-256", "SHA-512", or "OpenSSL". */ final public static function getSupportedSignatures(): array {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * instructs phar to intercept fopen, file_get_contents, opendir, and all of the stat-related functions * @link https://php.net/manual/en/phar.interceptfilefuncs.php * @return void */ final public static function interceptFileFuncs(): void {} /** * (PHP >= 5.3.0, PECL phar >= 1.2.0)
    * Returns whether the given filename is a valid phar filename * @link https://php.net/manual/en/phar.isvalidpharfilename.php * @param string $filename

    * The name or full path to a phar archive not yet created *

    * @param bool $executable [optional]

    * This parameter determines whether the filename should be treated as * a phar executable archive, or a data non-executable archive *

    * @return bool TRUE if the filename is valid, FALSE if not. */ final public static function isValidPharFilename(string $filename, bool $executable = true): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Loads any phar archive with an alias * @link https://php.net/manual/en/phar.loadphar.php * @param string $filename

    * the full or relative path to the phar archive to open *

    * @param string|null $alias [optional]

    * The alias that may be used to refer to the phar archive. Note * that many phar archives specify an explicit alias inside the * phar archive, and a PharException will be thrown if * a new alias is specified in this case. *

    * @return bool TRUE on success or FALSE on failure. */ final public static function loadPhar(string $filename, ?string $alias = null): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Reads the currently executed file (a phar) and registers its manifest * @link https://php.net/manual/en/phar.mapphar.php * @param string|null $alias [optional]

    * The alias that can be used in phar:// URLs to * refer to this archive, rather than its full path. *

    * @param int $offset [optional]

    * Unused variable, here for compatibility with PEAR's PHP_Archive. *

    * @return bool TRUE on success or FALSE on failure. */ final public static function mapPhar(?string $alias = null, int $offset = 0): bool {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Returns the full path on disk or full phar URL to the currently executing Phar archive * @link https://php.net/manual/en/phar.running.php * @param bool $returnPhar

    * If FALSE, the full path on disk to the phar * archive is returned. If TRUE, a full phar URL is returned. *

    * @return string the filename if valid, empty string otherwise. */ final public static function running( #[PhpStormStubsElementAvailable(from: '5.3', to: '5.6')] $returnPhar, #[PhpStormStubsElementAvailable(from: '7.0')] bool $returnPhar = true ): string {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Mount an external path or file to a virtual location within the phar archive * @link https://php.net/manual/en/phar.mount.php * @param string $pharPath

    * The internal path within the phar archive to use as the mounted path location. * This must be a relative path within the phar archive, and must not already exist. *

    * @param string $externalPath

    * A path or URL to an external file or directory to mount within the phar archive *

    * @return void No return. PharException is thrown on failure. */ final public static function mount(string $pharPath, string $externalPath): void {} /** * (Unknown)
    * Defines a list of up to 4 $_SERVER variables that should be modified for execution * @link https://php.net/manual/en/phar.mungserver.php * @param array $variables

    * an array containing as string indices any of * REQUEST_URI, PHP_SELF, * SCRIPT_NAME and SCRIPT_FILENAME. * Other values trigger an exception, and Phar::mungServer * is case-sensitive. *

    * @return void No return. */ final public static function mungServer(array $variables): void {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Completely remove a phar archive from disk and from memory * @link https://php.net/manual/en/phar.unlinkarchive.php * @param string $filename

    * The path on disk to the phar archive. *

    * @throws PharException * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] final public static function unlinkArchive(string $filename) {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * mapPhar for web-based phars. front controller for web applications * @link https://php.net/manual/en/phar.webphar.php * @param null|string $alias [optional]

    * The alias that can be used in phar:// URLs to * refer to this archive, rather than its full path. *

    * @param string|null $index [optional]

    * The location within the phar of the directory index. *

    * @param null|string $fileNotFoundScript [optional]

    * The location of the script to run when a file is not found. This * script should output the proper HTTP 404 headers. *

    * @param null|array $mimeTypes [optional]

    * An array mapping additional file extensions to MIME type. * If the default mapping is sufficient, pass an empty array. * By default, these extensions are mapped to these MIME types: * * $mimes = array( * 'phps' => Phar::PHPS, // pass to highlight_file() * 'c' => 'text/plain', * 'cc' => 'text/plain', * 'cpp' => 'text/plain', * 'c++' => 'text/plain', * 'dtd' => 'text/plain', * 'h' => 'text/plain', * 'log' => 'text/plain', * 'rng' => 'text/plain', * 'txt' => 'text/plain', * 'xsd' => 'text/plain', * 'php' => Phar::PHP, // parse as PHP * 'inc' => Phar::PHP, // parse as PHP * 'avi' => 'video/avi', * 'bmp' => 'image/bmp', * 'css' => 'text/css', * 'gif' => 'image/gif', * 'htm' => 'text/html', * 'html' => 'text/html', * 'htmls' => 'text/html', * 'ico' => 'image/x-ico', * 'jpe' => 'image/jpeg', * 'jpg' => 'image/jpeg', * 'jpeg' => 'image/jpeg', * 'js' => 'application/x-javascript', * 'midi' => 'audio/midi', * 'mid' => 'audio/midi', * 'mod' => 'audio/mod', * 'mov' => 'movie/quicktime', * 'mp3' => 'audio/mp3', * 'mpg' => 'video/mpeg', * 'mpeg' => 'video/mpeg', * 'pdf' => 'application/pdf', * 'png' => 'image/png', * 'swf' => 'application/shockwave-flash', * 'tif' => 'image/tiff', * 'tiff' => 'image/tiff', * 'wav' => 'audio/wav', * 'xbm' => 'image/xbm', * 'xml' => 'text/xml', * ); * *

    * @param null|callable $rewrite [optional]

    * The rewrites function is passed a string as its only parameter and must return a string or FALSE. *

    *

    * If you are using fast-cgi or cgi then the parameter passed to the function is the value of the * $_SERVER['PATH_INFO'] variable. Otherwise, the parameter passed to the function is the value * of the $_SERVER['REQUEST_URI'] variable. *

    *

    * If a string is returned it is used as the internal file path. If FALSE is returned then webPhar() will * send a HTTP 403 Denied Code. *

    * @return void No value is returned. */ final public static function webPhar( ?string $alias = null, ?string $index = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: 'string')] $fileNotFoundScript = null, array $mimeTypes = [], ?callable $rewrite = null ): void {} /** * Returns whether current entry is a directory and not '.' or '..' * @link https://php.net/manual/en/recursivedirectoryiterator.haschildren.php * @param bool $allow_links [optional]

    *

    * @return bool whether the current entry is a directory, but not '.' or '..' */ public function hasChildren($allow_links = false) {} /** * Returns an iterator for the current entry if it is a directory * @link https://php.net/manual/en/recursivedirectoryiterator.getchildren.php * @return mixed The filename, file information, or $this depending on the set flags. * See the FilesystemIterator * constants. */ public function getChildren() {} /** * Rewinds back to the beginning * @link https://php.net/manual/en/filesystemiterator.rewind.php * @return void No value is returned. */ public function rewind() {} /** * Move to the next file * @link https://php.net/manual/en/filesystemiterator.next.php * @return void No value is returned. */ public function next() {} /** * Retrieve the key for the current file * @link https://php.net/manual/en/filesystemiterator.key.php * @return string the pathname or filename depending on the set flags. * See the FilesystemIterator constants. */ public function key() {} /** * The current file * @link https://php.net/manual/en/filesystemiterator.current.php * @return mixed The filename, file information, or $this depending on the set flags. * See the FilesystemIterator constants. */ public function current() {} /** * Check whether current DirectoryIterator position is a valid file * @link https://php.net/manual/en/directoryiterator.valid.php * @return bool TRUE if the position is valid, otherwise FALSE */ public function valid() {} /** * Seek to a DirectoryIterator item * @link https://php.net/manual/en/directoryiterator.seek.php * @param int $position

    * The zero-based numeric position to seek to. *

    * @return void No value is returned. */ public function seek($position) {} public function _bad_state_ex() {} } /** * The PharData class provides a high-level interface to accessing and creating * non-executable tar and zip archives. Because these archives do not contain * a stub and cannot be executed by the phar extension, it is possible to create * and manipulate regular zip and tar files using the PharData class even if * phar.readonly php.ini setting is 1. * @link https://php.net/manual/en/class.phardata.php */ class PharData extends Phar { /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Construct a non-executable tar or zip archive object * @link https://php.net/manual/en/phardata.construct.php * @param string $filename

    * Path to an existing tar/zip archive or to-be-created archive *

    * @param int $flags [optional]

    * Flags to pass to Phar parent class * RecursiveDirectoryIterator. *

    * @param string $alias [optional]

    * Alias with which this Phar archive should be referred to in calls to stream * functionality. *

    * @param int $format [optional]

    * One of the * file format constants * available within the Phar class. *

    */ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = FilesystemIterator::SKIP_DOTS|FilesystemIterator::UNIX_PATHS, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $alias = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $format = 0 ) {} /** * @param string $localName * @return bool */ #[TentativeType] public function offsetExists($localName): bool {} /** * @param string $localName * @return SplFileInfo */ #[TentativeType] public function offsetGet($localName): SplFileInfo {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * set the contents of a file within the tar/zip to those of an external file or string * @link https://php.net/manual/en/phardata.offsetset.php * @param string $localName

    * The filename (relative path) to modify in a tar or zip archive. *

    * @param string $value

    * Content of the file. *

    * @return void No return values. */ #[TentativeType] public function offsetSet($localName, $value): void {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * remove a file from a tar/zip archive * @link https://php.net/manual/en/phardata.offsetunset.php * @param string $localName

    * The filename (relative path) to modify in the tar/zip archive. *

    * @return void */ #[TentativeType] public function offsetUnset($localName): void {} /** * Returns whether current entry is a directory and not '.' or '..' * @link https://php.net/manual/en/recursivedirectoryiterator.haschildren.php * @param bool $allow_links [optional]

    *

    * @return bool whether the current entry is a directory, but not '.' or '..' */ public function hasChildren($allow_links = false) {} /** * Returns an iterator for the current entry if it is a directory * @link https://php.net/manual/en/recursivedirectoryiterator.getchildren.php * @return mixed The filename, file information, or $this depending on the set flags. * See the FilesystemIterator * constants. */ public function getChildren() {} /** * Rewinds back to the beginning * @link https://php.net/manual/en/filesystemiterator.rewind.php * @return void No value is returned. */ public function rewind() {} /** * Move to the next file * @link https://php.net/manual/en/filesystemiterator.next.php * @return void No value is returned. */ public function next() {} /** * Retrieve the key for the current file * @link https://php.net/manual/en/filesystemiterator.key.php * @return string the pathname or filename depending on the set flags. * See the FilesystemIterator constants. */ public function key() {} /** * The current file * @link https://php.net/manual/en/filesystemiterator.current.php * @return mixed The filename, file information, or $this depending on the set flags. * See the FilesystemIterator constants. */ public function current() {} /** * Check whether current DirectoryIterator position is a valid file * @link https://php.net/manual/en/directoryiterator.valid.php * @return bool TRUE if the position is valid, otherwise FALSE */ public function valid() {} /** * Seek to a DirectoryIterator item * @link https://php.net/manual/en/directoryiterator.seek.php * @param int $position

    * The zero-based numeric position to seek to. *

    * @return void No value is returned. */ public function seek($position) {} } /** * The PharFileInfo class provides a high-level interface to the contents * and attributes of a single file within a phar archive. * @link https://php.net/manual/en/class.pharfileinfo.php */ class PharFileInfo extends SplFileInfo { /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Construct a Phar entry object * @link https://php.net/manual/en/pharfileinfo.construct.php * @param string $filename

    * The full url to retrieve a file. If you wish to retrieve the information * for the file my/file.php from the phar boo.phar, * the entry should be phar://boo.phar/my/file.php. *

    */ public function __construct(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename) {} public function __destruct() {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Sets file-specific permission bits * @link https://php.net/manual/en/pharfileinfo.chmod.php * @param int $perms

    * permissions (see chmod) *

    * @return void No value is returned. */ #[TentativeType] public function chmod(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $perms): void {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Compresses the current Phar entry with either zlib or bzip2 compression * @link https://php.net/manual/en/pharfileinfo.compress.php * @param int $compression * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function compress(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $compression) {} /** * (PHP >= 5.3.0, PECL phar >= 2.0.0)
    * Decompresses the current Phar entry within the phar * @link https://php.net/manual/en/pharfileinfo.decompress.php * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function decompress() {} /** * (PHP >= 5.3.0, PECL phar >= 1.2.0)
    * Deletes the metadata of the entry * @link https://php.net/manual/en/pharfileinfo.delmetadata.php * @return bool TRUE if successful, FALSE if the entry had no metadata. * As with all functionality that modifies the contents of * a phar, the phar.readonly INI variable * must be off in order to succeed if the file is within a Phar * archive. Files within PharData archives do not have * this restriction. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function delMetadata() {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns the actual size of the file (with compression) inside the Phar archive * @link https://php.net/manual/en/pharfileinfo.getcompressedsize.php * @return int<0, max> The size in bytes of the file within the Phar archive on disk. */ #[TentativeType] public function getCompressedSize(): int {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns CRC32 code or throws an exception if CRC has not been verified * @link https://php.net/manual/en/pharfileinfo.getcrc32.php * @return int The crc32 checksum of the file within the Phar archive. */ #[TentativeType] public function getCRC32(): int {} #[TentativeType] public function getContent(): string {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns file-specific meta-data saved with a file * @link https://php.net/manual/en/pharfileinfo.getmetadata.php * @param array $unserializeOptions [optional] if is set to anything other than the default, * the resulting metadata won't be cached and this won't return the value from the cache * @return mixed any PHP variable that can be serialized and is stored as meta-data for the file, * or NULL if no meta-data is stored. */ #[TentativeType] public function getMetadata(#[PhpStormStubsElementAvailable(from: '8.0')] array $unserializeOptions = []): mixed {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns the Phar file entry flags * @link https://php.net/manual/en/pharfileinfo.getpharflags.php * @return int The Phar flags (always 0 in the current implementation) */ #[TentativeType] public function getPharFlags(): int {} /** * (PHP >= 5.3.0, PECL phar >= 1.2.0)
    * Returns the metadata of the entry * @link https://php.net/manual/en/pharfileinfo.hasmetadata.php * @return bool FALSE if no metadata is set or is NULL, TRUE if metadata is not NULL */ #[TentativeType] public function hasMetadata(): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns whether the entry is compressed * @link https://php.net/manual/en/pharfileinfo.iscompressed.php * @param int $compression [optional]

    * One of Phar::GZ or Phar::BZ2, * defaults to any compression. *

    * @return bool TRUE if the file is compressed within the Phar archive, FALSE if not. */ #[TentativeType] public function isCompressed(#[LanguageLevelTypeAware(['8.0' => 'int|null'], default: '')] $compression = null): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Returns whether file entry has had its CRC verified * @link https://php.net/manual/en/pharfileinfo.iscrcchecked.php * @return bool TRUE if the file has had its CRC verified, FALSE if not. */ #[TentativeType] public function isCRCChecked(): bool {} /** * (PHP >= 5.3.0, PECL phar >= 1.0.0)
    * Sets file-specific meta-data saved with a file * @link https://php.net/manual/en/pharfileinfo.setmetadata.php * @param mixed $metadata

    * Any PHP variable containing information to store alongside a file *

    * @return void No value is returned. */ #[TentativeType] public function setMetadata(#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $metadata): void {} } // End of Phar v.2.0.1 'int'], default: '')] public $status; /** * System status of the Zip Archive * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $statusSys; /** * Number of files in archive * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $numFiles; /** * File name in the file system * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $filename; /** * Comment for the archive * @var string */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $comment; /** * @var int */ #[LanguageLevelTypeAware(['8.1' => 'int'], default: '')] public $lastId; /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Open a ZIP file archive * * @link https://php.net/manual/en/ziparchive.open.php * * @param string $filename

    * The file name of the ZIP archive to open. *

    * @param int $flags [optional]

    * The mode to use to open the archive. *

    *

    * ZipArchive::OVERWRITE *

    * * @return int|bool Error codes *

    * Returns TRUE on success, FALSE or the error code on error. *

    *

    * ZipArchive::ER_EXISTS *

    *

    * File already exists. *

    *

    * ZipArchive::ER_INCONS *

    *

    * Zip archive inconsistent. *

    *

    * ZipArchive::ER_INVAL *

    *

    * Invalid argument. *

    *

    * ZipArchive::ER_MEMORY *

    *

    * Malloc failure. *

    *

    * ZipArchive::ER_NOENT *

    *

    * No such file. *

    *

    * ZipArchive::ER_NOZIP *

    *

    * Not a zip archive. *

    *

    * ZipArchive::ER_OPEN *

    *

    * Can't open file. *

    *

    * ZipArchive::ER_READ *

    *

    * Read error. *

    *

    * ZipArchive::ER_SEEK *

    *

    * Seek error. *

    */ #[TentativeType] public function open( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): int|bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Close the active archive (opened or newly created) * @link https://php.net/manual/en/ziparchive.close.php * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function close(): bool {} /** * (PHP 7 >= 7.2.0, PECL zip >= 1.15.0)
    * Counts the number of files in the archive. * @link https://www.php.net/manual/en/ziparchive.count.php * @return int * @since 7.2 */ #[TentativeType] public function count(): int {} /** * Returns the status error message, system and/or zip messages * @link https://php.net/manual/en/ziparchive.getstatusstring.php * @return string|false a string with the status message on success or FALSE on failure. * @since 5.2.7 */ #[TentativeType] public function getStatusString(): string {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.8.0)
    * Add a new directory * @link https://php.net/manual/en/ziparchive.addemptydir.php * @param string $dirname

    * The directory to add. *

    * @param int $flags [optional] Set how to manage name encoding (ZipArchive::FL_ENC_*) and entry replacement (ZipArchive::FL_OVERWRITE) * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function addEmptyDir( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $dirname, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags ): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Add a file to a ZIP archive using its contents * @link https://php.net/manual/en/ziparchive.addfromstring.php * @param string $name

    * The name of the entry to create. *

    * @param string $content

    * The contents to use to create the entry. It is used in a binary * safe mode. *

    * @param int $flags [optional] Set how to manage name encoding (ZipArchive::FL_ENC_*) and entry replacement (ZipArchive::FL_OVERWRITE) * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function addFromString( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $content, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 8192 ): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Adds a file to a ZIP archive from the given path * @link https://php.net/manual/en/ziparchive.addfile.php * @param string $filepath

    * The path to the file to add. *

    * @param string $entryname [optional]

    * If supplied, this is the local name inside the ZIP archive that will override the filename. *

    * @param int $start [optional]

    * This parameter is not used but is required to extend ZipArchive. *

    * @param int $length [optional]

    * This parameter is not used but is required to extend ZipArchive. *

    * @param int $flags [optional] Set how to manage name encoding (ZipArchive::FL_ENC_*) and entry replacement (ZipArchive::FL_OVERWRITE) * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function addFile( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filepath, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $entryname = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $start = 0, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $length = 0, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 8192 ): bool {} /** * (PHP 5 >= 5.3.0, PECL zip >= 1.9.0)
    * Add files from a directory by glob pattern * @link https://php.net/manual/en/ziparchive.addglob.php * @param string $pattern

    * A glob pattern against which files will be matched. *

    * @param int $flags [optional]

    * A bit mask of glob() flags. *

    * @param array $options [optional]

    * An associative array of options. Available options are: *

    *

    * "add_path" *

    *

    * Prefix to prepend when translating to the local path of the file within * the archive. This is applied after any remove operations defined by the * "remove_path" or "remove_all_path" * options. *

    * @return array|false */ #[TentativeType] public function addGlob( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $pattern, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0, array $options = [] ): array|false {} /** * (PHP 5 >= 5.3.0, PECL zip >= 1.9.0)
    * Add files from a directory by PCRE pattern * @link https://php.net/manual/en/ziparchive.addpattern.php * @param string $pattern

    * A PCRE pattern against which files will be matched. *

    * @param string $path [optional]

    * The directory that will be scanned. Defaults to the current working directory. *

    * @param array $options [optional]

    * An associative array of options accepted by ZipArchive::addGlob. *

    * @return array|false */ #[TentativeType] public function addPattern( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $pattern, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $path = '.', array $options = [] ): array|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.5.0)
    * Renames an entry defined by its index * @link https://php.net/manual/en/ziparchive.renameindex.php * @param int $index

    * Index of the entry to rename. *

    * @param string $new_name

    * New name. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function renameIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $new_name ):bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.5.0)
    * Renames an entry defined by its name * @link https://php.net/manual/en/ziparchive.renamename.php * @param string $name

    * Name of the entry to rename. *

    * @param string $new_name

    * New name. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function renameName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $new_name ): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.4.0)
    * Set the comment of a ZIP archive * @link https://php.net/manual/en/ziparchive.setarchivecomment.php * @param string $comment

    * The contents of the comment. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setArchiveComment(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $comment): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Returns the Zip archive comment * @link https://php.net/manual/en/ziparchive.getarchivecomment.php * @param int $flags [optional]

    * If flags is set to ZipArchive::FL_UNCHANGED, the original unchanged * comment is returned. *

    * @return string|false the Zip archive comment or FALSE on failure. */ #[TentativeType] public function getArchiveComment(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null): string|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.4.0)
    * Set the comment of an entry defined by its index * @link https://php.net/manual/en/ziparchive.setcommentindex.php * @param int $index

    * Index of the entry. *

    * @param string $comment

    * The contents of the comment. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setCommentIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $comment ): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.4.0)
    * Set the comment of an entry defined by its name * @link https://php.net/manual/en/ziparchive.setcommentname.php * @param string $name

    * Name of the entry. *

    * @param string $comment

    * The contents of the comment. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function setCommentName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $comment ): bool {} /** * Set the compression method of an entry defined by its index * @link https://php.net/manual/en/ziparchive.setcompressionindex.php * @param int $index Index of the entry. * @param int $method The compression method. Either ZipArchive::CM_DEFAULT, ZipArchive::CM_STORE or ZipArchive::CM_DEFLATE. * @param int $compflags [optional] Compression flags. Currently unused. * @return bool Returns TRUE on success or FALSE on failure. * @since 7.0 */ #[TentativeType] public function setCompressionIndex(int $index, int $method, int $compflags = 0): bool {} /** * Set the compression method of an entry defined by its name * https://secure.php.net/manual/en/ziparchive.setcompressionname.php * @param string $name Name of the entry. * @param int $method The compression method. Either ZipArchive::CM_DEFAULT, ZipArchive::CM_STORE or ZipArchive::CM_DEFLATE. * @param int $compflags [optional] Compression flags. Currently unused. * @return bool Returns TRUE on success or FALSE on failure. * @since 7.0 */ #[TentativeType] public function setCompressionName(string $name, int $method, int $compflags = 0): bool {} /** * Set the encryption method of an entry defined by its index * @link https://php.net/manual/en/ziparchive.setencryptionindex.php * @param int $index Index of the entry. * @param int $method The encryption method defined by one of the ZipArchive::EM_ constants. * @param string|null $password [optional] Optional password, default used when missing. * @return bool Returns TRUE on success or FALSE on failure. * @since 7.2 */ #[TentativeType] public function setEncryptionIndex(int $index, int $method, ?string $password = null): bool {} /** * Set the encryption method of an entry defined by its name * @link https://php.net/manual/en/ziparchive.setencryptionname.php * @param string $name Name of the entry. * @param int $method The encryption method defined by one of the ZipArchive::EM_ constants. * @param string|null $password [optional] Optional password, default used when missing. * @return bool Returns TRUE on success or FALSE on failure. * @since 7.2 */ #[TentativeType] public function setEncryptionName(string $name, int $method, ?string $password = null): bool {} /** * (PHP 5 >= 5.6.0, PECL zip >= 1.12.0)
    * @param string $password * @return bool */ #[TentativeType] public function setPassword(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $password): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.4.0)
    * Returns the comment of an entry using the entry index * @link https://php.net/manual/en/ziparchive.getcommentindex.php * @param int $index

    * Index of the entry *

    * @param int $flags [optional]

    * If flags is set to ZipArchive::FL_UNCHANGED, the original unchanged * comment is returned. *

    * @return string|false the comment on success or FALSE on failure. */ #[TentativeType] public function getCommentIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): string|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.4.0)
    * Returns the comment of an entry using the entry name * @link https://php.net/manual/en/ziparchive.getcommentname.php * @param string $name

    * Name of the entry *

    * @param int $flags [optional]

    * If flags is set to ZipArchive::FL_UNCHANGED, the original unchanged * comment is returned. *

    * @return string|false the comment on success or FALSE on failure. */ #[TentativeType] public function getCommentName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): string|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.5.0)
    * delete an entry in the archive using its index * @link https://php.net/manual/en/ziparchive.deleteindex.php * @param int $index

    * Index of the entry to delete. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function deleteIndex(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.5.0)
    * delete an entry in the archive using its name * @link https://php.net/manual/en/ziparchive.deletename.php * @param string $name

    * Name of the entry to delete. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function deleteName(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.5.0)
    * Get the details of an entry defined by its name. * @link https://php.net/manual/en/ziparchive.statname.php * @param string $name

    * Name of the entry *

    * @param int $flags [optional]

    * The flags argument specifies how the name lookup should be done. * Also, ZipArchive::FL_UNCHANGED may be ORed to it to request * information about the original file in the archive, * ignoring any changes made. * ZipArchive::FL_NOCASE *

    * @return array{name: string, index: int, crc: int, size: int, mtime: int, comp_size: int, comp_method: int, encryption_method: int}|false an array containing the entry details or FALSE on failure. */ #[TentativeType] public function statName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): array|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Get the details of an entry defined by its index. * @link https://php.net/manual/en/ziparchive.statindex.php * @param int $index

    * Index of the entry *

    * @param int $flags [optional]

    * ZipArchive::FL_UNCHANGED may be ORed to it to request * information about the original file in the archive, * ignoring any changes made. *

    * @return array{name: string, index: int, crc: int, size: int, mtime: int, comp_size: int, comp_method: int, encryption_method: int}|false an array containing the entry details or FALSE on failure. */ #[TentativeType] public function statIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ):array|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.5.0)
    * Returns the index of the entry in the archive * @link https://php.net/manual/en/ziparchive.locatename.php * @param string $name

    * The name of the entry to look up *

    * @param int $flags [optional]

    * The flags are specified by ORing the following values, * or 0 for none of them. * ZipArchive::FL_NOCASE *

    * @return int|false the index of the entry on success or FALSE on failure. */ #[TentativeType] public function locateName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): int|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.5.0)
    * Returns the name of an entry using its index * @link https://php.net/manual/en/ziparchive.getnameindex.php * @param int $index

    * Index of the entry. *

    * @param int $flags [optional]

    * If flags is set to ZipArchive::FL_UNCHANGED, the original unchanged * name is returned. *

    * @return string|false the name on success or FALSE on failure. */ #[TentativeType] public function getNameIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ):string|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Revert all global changes done in the archive. * @link https://php.net/manual/en/ziparchive.unchangearchive.php * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function unchangeArchive(): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Undo all changes done in the archive * @link https://php.net/manual/en/ziparchive.unchangeall.php * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function unchangeAll(): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Revert all changes done to an entry at the given index * @link https://php.net/manual/en/ziparchive.unchangeindex.php * @param int $index

    * Index of the entry. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function unchangeIndex(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.5.0)
    * Revert all changes done to an entry with the given name. * @link https://php.net/manual/en/ziparchive.unchangename.php * @param string $name

    * Name of the entry. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function unchangeName(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Extract the archive contents * @link https://php.net/manual/en/ziparchive.extractto.php * @param string $pathto

    * Location where to extract the files. *

    * @param string[]|string|null $files [optional]

    * The entries to extract. It accepts either a single entry name or * an array of names. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function extractTo( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $pathto, #[LanguageLevelTypeAware(['8.0' => 'array|string|null'], default: '')] $files = null ): bool {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Returns the entry contents using its name * @link https://php.net/manual/en/ziparchive.getfromname.php * @param string $name

    * Name of the entry *

    * @param int $len [optional]

    * The length to be read from the entry. If 0, then the * entire entry is read. *

    * @param int $flags [optional]

    * The flags to use to open the archive. the following values may * be ORed to it. * ZipArchive::FL_UNCHANGED *

    * @return string|false the contents of the entry on success or FALSE on failure. */ #[TentativeType] public function getFromName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $len = 0, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): string|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.3.0)
    * Returns the entry contents using its index * @link https://php.net/manual/en/ziparchive.getfromindex.php * @param int $index

    * Index of the entry *

    * @param int $len [optional]

    * The length to be read from the entry. If 0, then the * entire entry is read. *

    * @param int $flags [optional]

    * The flags to use to open the archive. the following values may * be ORed to it. *

    *

    * ZipArchive::FL_UNCHANGED *

    * @return string|false the contents of the entry on success or FALSE on failure. */ #[TentativeType] public function getFromIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $len = 0, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): string|false {} /** * (PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
    * Get a file handler to the entry defined by its name (read only). * @link https://php.net/manual/en/ziparchive.getstream.php * @param string $name

    * The name of the entry to use. *

    * @return resource|false a file pointer (resource) on success or FALSE on failure. */ public function getStream(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name) {} /** * (PHP 8 >= 8.2.0, PECL zip >= 1.20.0)
    * Get a file handler to the entry defined by its index (read only) * @link https://php.net/manual/en/ziparchive.getstreamindex.php * @param int $index

    * Index of the entry *

    * @param int $flags [optional]

    * If flags is set to ZipArchive::FL_UNCHANGED, the original unchanged stream is returned. *

    * @return resource|false a file pointer (resource) on success or FALSE on failure. */ public function getStreamIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = 0 ) {} /** * Set the external attributes of an entry defined by its name * @link https://www.php.net/manual/en/ziparchive.setexternalattributesname.php * @param string $name Name of the entry * @param int $opsys The operating system code defined by one of the ZipArchive::OPSYS_ constants. * @param int $attr The external attributes. Value depends on operating system. * @param int $flags [optional] Optional flags. Currently unused. * @return bool Returns TRUE on success or FALSE on failure. */ #[TentativeType] public function setExternalAttributesName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $opsys, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $attr, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): bool {} /** * Retrieve the external attributes of an entry defined by its name * @link https://www.php.net/manual/en/ziparchive.getexternalattributesname.php * @param string $name Name of the entry * @param int &$opsys On success, receive the operating system code defined by one of the ZipArchive::OPSYS_ constants. * @param int &$attr On success, receive the external attributes. Value depends on operating system. * @param int $flags [optional] If flags is set to ZipArchive::FL_UNCHANGED, the original unchanged attributes are returned. * @return bool Returns TRUE on success or FALSE on failure. */ #[TentativeType] public function getExternalAttributesName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] &$opsys, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] &$attr, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): bool {} /** * Set the external attributes of an entry defined by its index * @link https://www.php.net/manual/en/ziparchive.setexternalattributesindex.php * @param int $index Index of the entry. * @param int $opsys The operating system code defined by one of the ZipArchive::OPSYS_ constants. * @param int $attr The external attributes. Value depends on operating system. * @param int $flags [optional] Optional flags. Currently unused. * @return bool Returns TRUE on success or FALSE on failure. */ #[TentativeType] public function setExternalAttributesIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $opsys, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $attr, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): bool {} /** * Retrieve the external attributes of an entry defined by its index * @link https://www.php.net/manual/en/ziparchive.getexternalattributesindex.php * @param int $index Index of the entry. * @param int &$opsys On success, receive the operating system code defined by one of the ZipArchive::OPSYS_ constants. * @param int &$attr On success, receive the external attributes. Value depends on operating system. * @param int $flags [optional] If flags is set to ZipArchive::FL_UNCHANGED, the original unchanged attributes are returned. * @return bool Returns TRUE on success or FALSE on failure. */ #[TentativeType] public function getExternalAttributesIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] &$opsys, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] &$attr, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): bool {} #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] public static function isEncryptionMethodSupported( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $method, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $enc = true ) {} #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] public static function isCompressionMethodSupported( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $method, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $enc = true ) {} #[TentativeType] public function registerCancelCallback(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback): bool {} #[TentativeType] public function registerProgressCallback( #[LanguageLevelTypeAware(['8.0' => 'float'], default: '')] $rate, #[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback ): bool {} #[TentativeType] public function setMtimeName( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $timestamp, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): bool {} #[TentativeType] public function setMtimeIndex( #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $timestamp, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): bool {} #[TentativeType] public function replaceFile( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filepath, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $index, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $start = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $length = null, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = null ): bool {} #[LanguageLevelTypeAware(['8.0' => 'void'], default: '')] public function clearError() {} /** * @param int $flag * @param int $value * @return bool */ #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] public function setArchiveFlag( #[LanguageLevelTypeAware(['8.3' => 'int'], default: '')] $flag, #[LanguageLevelTypeAware(['8.3' => 'int'], default: '')] $value ) {} /** * @param int $flag * @param int $flags * @return int */ #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] public function getArchiveFlag( #[LanguageLevelTypeAware(['8.3' => 'int'], default: '')] $flag, #[LanguageLevelTypeAware(['8.3' => 'int'], default: '')] $flags = 0 ) {} /** * @param string $name * @param int $flags * @return void */ public function getStreamName( #[LanguageLevelTypeAware(['8.2' => 'string'], default: '')] $name, #[LanguageLevelTypeAware(['8.2' => 'int'], default: '')] $flags = 0 ) {} } /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Open a ZIP file archive * @link https://php.net/manual/en/function.zip-open.php * @param string $filename

    * The file name of the ZIP archive to open. *

    * @return resource|int|false a resource handle for later use with * zip_read and zip_close * or returns the number of error if filename does not * exist or in case of other error. * @deprecated 8.0 Use {@link ZipArchive} instead. */ function zip_open(string $filename) {} /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Close a ZIP file archive * @link https://php.net/manual/en/function.zip-close.php * @param resource $zip

    * A ZIP file previously opened with zip_open. *

    * @return void No value is returned. * @deprecated 8.0 Use {@link ZipArchive} instead. */ function zip_close($zip): void {} /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Read next entry in a ZIP file archive * @link https://php.net/manual/en/function.zip-read.php * @param resource $zip

    * A ZIP file previously opened with zip_open. *

    * @return resource|false a directory entry resource for later use with the * zip_entry_... functions, or FALSE if * there are no more entries to read, or an error code if an error * occurred. * @deprecated 8.0 Use {@link ZipArchive} instead. */ function zip_read($zip) {} /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Open a directory entry for reading * @link https://php.net/manual/en/function.zip-entry-open.php * @param resource $zip_dp

    * A valid resource handle returned by zip_open. *

    * @param resource $zip_entry

    * A directory entry returned by zip_read. *

    * @param string $mode [optional]

    * Any of the modes specified in the documentation of * fopen. *

    *

    * Currently, mode is ignored and is always * "rb". This is due to the fact that zip support * in PHP is read only access. *

    * @return bool TRUE on success or FALSE on failure. *

    * Unlike fopen and other similar functions, * the return value of zip_entry_open only * indicates the result of the operation and is not needed for * reading or closing the directory entry. *

    */ #[Deprecated(reason: 'This function is deprecated in favor of the Object API', since: "8.0")] function zip_entry_open($zip_dp, $zip_entry, string $mode = 'rb'): bool {} /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Close a directory entry * @link https://php.net/manual/en/function.zip-entry-close.php * @param resource $zip_entry

    * A directory entry previously opened zip_entry_open. *

    * @return bool TRUE on success or FALSE on failure. * @deprecated 8.0 Use {@link ZipArchive} instead. */ function zip_entry_close($zip_entry): bool {} /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Read from an open directory entry * @link https://php.net/manual/en/function.zip-entry-read.php * @param resource $zip_entry

    * A directory entry returned by zip_read. *

    * @param int $len [optional]

    * The number of bytes to return. *

    *

    * This should be the uncompressed length you wish to read. *

    * @return string|false the data read, empty string on end of a file, or FALSE on error. * @deprecated 8.0 Use {@link ZipArchive} instead. */ function zip_entry_read($zip_entry, int $len = 1024): string|false {} /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Retrieve the actual file size of a directory entry * @link https://php.net/manual/en/function.zip-entry-filesize.php * @param resource $zip_entry

    * A directory entry returned by zip_read. *

    * @return int|false The size of the directory entry. * @deprecated 8.0 Use {@link ZipArchive} instead. */ function zip_entry_filesize($zip_entry): int|false {} /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Retrieve the name of a directory entry * @link https://php.net/manual/en/function.zip-entry-name.php * @param resource $zip_entry

    * A directory entry returned by zip_read. *

    * @return string|false The name of the directory entry. * @deprecated 8.0 Use {@link ZipArchive} instead. */ function zip_entry_name($zip_entry): string|false {} /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Retrieve the compressed size of a directory entry * @link https://php.net/manual/en/function.zip-entry-compressedsize.php * @param resource $zip_entry

    * A directory entry returned by zip_read. *

    * @return int|false The compressed size. * @deprecated 8.0 Use {@link ZipArchive} instead. */ function zip_entry_compressedsize($zip_entry): int|false {} /** * (PHP 4 >= 4.1.0, PHP 5 >= 5.2.0, PECL zip >= 1.0.0)
    * Retrieve the compression method of a directory entry * @link https://php.net/manual/en/function.zip-entry-compressionmethod.php * @param resource $zip_entry

    * A directory entry returned by zip_read. *

    * @return string|false The compression method. * @deprecated 8.0 Use {@link ZipArchive} instead. */ function zip_entry_compressionmethod($zip_entry): string|false {} // End of zip v.1.11.0 * First epoch:version-release string *

    * @param string $evr2

    * Second epoch:version-release string *

    * @return int

    * < 0 if evr1 < evr2, > 0 if evr1 > evr2, 0 if equal. *

    * @since 0.1.0 */ function rpmvercmp(string $evr1, string $evr2) {} /** * Retrieve information from a RPM file, reading its metadata. * If given error will be used to store error message * instead of raising a warning. The return * value is a hash table, * or false if it fails. * * @param string $path

    * Path to the RPM file. *

    * @param bool $full [optional]

    * If TRUE all information headers for the file are retrieved, else only a minimal set. *

    * @param null|string &$error [optional]

    * If provided, will receive the possible error message, and will avoid a runtime warning. *

    * * @return array|null

    * An array of information or NULL on error. *

    * @since 0.1.0 */ function rpminfo(string $path, bool $full = false, ?string &$error = null) {} /** * Retrieve information about an installed package, from the system RPM database. * * @param string $nevr

    * Name with optional epoch, version and release. *

    * @param bool $full [optional]

    * If TRUE all information headers for the file are retrieved, else only a minimal set. *

    * * @return array|null

    * An array of arrays of information or NULL on error. *

    * @since 0.2.0 */ function rpmdbinfo(string $nevr, bool $full = false) {} /** * Retriev information from the local RPM database. * * @param string $pattern

    * Value to search for. *

    * @param int $rpmtag [optional]

    * Search criterion, one of RPMTAG_* constant. *

    * @param int $rpmmire [optional]

    * Pattern type, one of RPMMIRE_* constant. * When < 0 the criterion must equals the value, and database index is used if possible. *

    * @param bool $full [optional]

    * If TRUE all information headers for the file are retrieved, else only a minimal set. *

    * * @return array|null

    * An array of arrays of information or NULL on error. *

    * @since 0.3.0 */ function rpmdbsearch(string $pattern, int $rpmtag = RPMTAG_NAME, int $rpmmire = -1, bool $full = false) {} /** * Add an additional retrieved tag in subsequent queries. * * @param int $tag One of RPMTAG_* constant, see the rpminfo constants page. * * @return bool Returns true on success or false on failure. * @since 0.5.0 */ function rpmaddtag(int $tag): bool {} NULL on error. * @link https://secure.php.net/serialize PHP default serialize */ function igbinary_serialize($value) {} /** Creates a PHP value from a stored representation. * igbinary_unserialize() takes a single serialized variable and converts it back into a PHP value. * * If the variable being unserialized is an object, after successfully reconstructing the object * PHP will automatically attempt to call the __wakeup() member function (if it exists). * In case the passed string is not unserializeable, NULL is returned and E_WARNING is issued. * * @param string $str The serialized string. * @return mixed|false The converted value is returned, and can be a boolean, integer, float, string, array, object or false by empty string input. * @link https://secure.php.net/manual/en/function.unserialize.php PHP default unserialize * @link https://secure.php.net/~helly/php/ext/spl/interfaceSerializable.html Serializable */ function igbinary_unserialize($str) {} // End of igbinary v.1.0.0 * The MySQL server. It can also include a port number. e.g. * "hostname:port" or a path to a local socket e.g. ":/path/to/socket" for * the localhost. *

    *

    * If the PHP directive * mysql.default_host is undefined (default), then the default * value is 'localhost:3306'. In "ini.sql.safe-mode", this parameter is ignored * and value 'localhost:3306' is always used. *

    * @param string $username [optional]

    * The username. Default value is defined by mysql.default_user. In * "ini.sql.safe-mode", this parameter is ignored and the name of the user that * owns the server process is used. *

    * @param string $password [optional]

    * The password. Default value is defined by mysql.default_password. In * "ini.sql.safe-mode", this parameter is ignored and empty password is used. *

    * @param bool $new_link [optional]

    * If a second call is made to mysql_connect * with the same arguments, no new link will be established, but * instead, the link identifier of the already opened link will be * returned. The new_link parameter modifies this * behavior and makes mysql_connect always open * a new link, even if mysql_connect was called * before with the same parameters. * In "ini.sql.safe-mode", this parameter is ignored. *

    * @param int $client_flags [optional]

    * The client_flags parameter can be a combination * of the following constants: * 128 (enable LOAD DATA LOCAL handling), * MYSQL_CLIENT_SSL, * MYSQL_CLIENT_COMPRESS, * MYSQL_CLIENT_IGNORE_SPACE or * MYSQL_CLIENT_INTERACTIVE. * Read the section about for further information. * In "ini.sql.safe-mode", this parameter is ignored. *

    * @return resource|false a MySQL link identifier on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_connect($server = 'ini_get("mysql.default_host")', $username = 'ini_get("mysql.default_user")', $password = 'ini_get("mysql.default_password")', $new_link = false, $client_flags = 0) {} /** * Open a persistent connection to a MySQL server * @link https://php.net/manual/en/function.mysql-pconnect.php * @param string $server [optional]

    * The MySQL server. It can also include a port number. e.g. * "hostname:port" or a path to a local socket e.g. ":/path/to/socket" for * the localhost. *

    *

    * If the PHP directive * mysql.default_host is undefined (default), then the default * value is 'localhost:3306' *

    * @param string $username [optional]

    * The username. Default value is the name of the user that owns the * server process. *

    * @param string $password [optional]

    * The password. Default value is an empty password. *

    * @param int $client_flags [optional]

    * The client_flags parameter can be a combination * of the following constants: * 128 (enable LOAD DATA LOCAL handling), * MYSQL_CLIENT_SSL, * MYSQL_CLIENT_COMPRESS, * MYSQL_CLIENT_IGNORE_SPACE or * MYSQL_CLIENT_INTERACTIVE. *

    * @return resource|false a MySQL persistent link identifier on success, or false on * failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_pconnect($server = 'ini_get("mysql.default_host")', $username = 'ini_get("mysql.default_user")', $password = 'ini_get("mysql.default_password")', $client_flags = null) {} /** * Close MySQL connection * @link https://php.net/manual/en/function.mysql-close.php * @param resource $link_identifier [optional] * @return bool true on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_close($link_identifier = null) {} /** * Select a MySQL database * @link https://php.net/manual/en/function.mysql-select-db.php * @param string $database_name

    * The name of the database that is to be selected. *

    * @param resource $link_identifier [optional] * @return bool true on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_select_db($database_name, $link_identifier = null) {} /** * Send a MySQL query * @link https://php.net/manual/en/function.mysql-query.php * @param string $query

    * An SQL query *

    *

    * The query string should not end with a semicolon. * Data inside the query should be properly escaped. *

    * @param resource $link_identifier [optional] * @return resource|bool For SELECT, SHOW, DESCRIBE, EXPLAIN and other statements returning resultset, * mysql_query * returns a resource on success, or false on * error. *

    *

    * For other type of SQL statements, INSERT, UPDATE, DELETE, DROP, etc, * mysql_query returns true on success * or false on error. *

    *

    * The returned result resource should be passed to * mysql_fetch_array, and other * functions for dealing with result tables, to access the returned data. *

    *

    * Use mysql_num_rows to find out how many rows * were returned for a SELECT statement or * mysql_affected_rows to find out how many * rows were affected by a DELETE, INSERT, REPLACE, or UPDATE * statement. *

    *

    * mysql_query will also fail and return false * if the user does not have permission to access the table(s) referenced by * the query. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_query($query, $link_identifier = null) {} /** * @deprecated 5.5 * Send an SQL query to MySQL without fetching and buffering the result rows. * @link https://php.net/manual/en/function.mysql-unbuffered-query.php * @param string $query

    * The SQL query to execute. *

    *

    * Data inside the query should be properly escaped. *

    * @param resource $link_identifier [optional] * @return resource|bool For SELECT, SHOW, DESCRIBE or EXPLAIN statements, * mysql_unbuffered_query * returns a resource on success, or false on * error. *

    *

    * For other type of SQL statements, UPDATE, DELETE, DROP, etc, * mysql_unbuffered_query returns true on success * or false on error. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_unbuffered_query($query, $link_identifier = null) {} /** * Selects a database and executes a query on it * @link https://php.net/manual/en/function.mysql-db-query.php * @param string $database

    * The name of the database that will be selected. *

    * @param string $query

    * The MySQL query. *

    *

    * Data inside the query should be properly escaped. *

    * @param resource $link_identifier [optional] * @return resource|bool a positive MySQL result resource to the query result, * or false on error. The function also returns true/false for * INSERT/UPDATE/DELETE * queries to indicate success/failure. * @removed 7.0 * @see mysql_select_db() * @see mysql_query() */ #[Deprecated('Use mysql_select_db() and mysql_query() instead', since: '5.3')] function mysql_db_query($database, $query, $link_identifier = null) {} /** * List databases available on a MySQL server * @link https://php.net/manual/en/function.mysql-list-dbs.php * @param resource $link_identifier [optional] * @return resource|false a result pointer resource on success, or false on * failure. Use the mysql_tablename function to traverse * this result pointer, or any function for result tables, such as * mysql_fetch_array. * @removed 7.0 */ #[Deprecated(since: '5.4')] function mysql_list_dbs($link_identifier = null) {} /** * List tables in a MySQL database * @link https://php.net/manual/en/function.mysql-list-tables.php * @param string $database

    * The name of the database *

    * @param resource $link_identifier [optional] * @return resource|false A result pointer resource on success or false on failure. *

    * Use the mysql_tablename function to * traverse this result pointer, or any function for result tables, * such as mysql_fetch_array. *

    * @removed 7.0 */ #[Deprecated(since: '5.3')] function mysql_list_tables($database, $link_identifier = null) {} /** * List MySQL table fields * @link https://php.net/manual/en/function.mysql-list-fields.php * @param string $database_name

    * The name of the database that's being queried. *

    * @param string $table_name

    * The name of the table that's being queried. *

    * @param resource $link_identifier [optional] * @return resource|false A result pointer resource on success, or false on * failure. *

    *

    * The returned result can be used with mysql_field_flags, * mysql_field_len, * mysql_field_name * mysql_field_type. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_list_fields($database_name, $table_name, $link_identifier = null) {} /** * List MySQL processes * @link https://php.net/manual/en/function.mysql-list-processes.php * @param resource $link_identifier [optional] * @return resource|false A result pointer resource on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_list_processes($link_identifier = null) {} /** * Returns the text of the error message from previous MySQL operation * @link https://php.net/manual/en/function.mysql-error.php * @param resource $link_identifier [optional] * @return string the error text from the last MySQL function, or * '' (empty string) if no error occurred. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_error($link_identifier = null) {} /** * Returns the numerical value of the error message from previous MySQL operation * @link https://php.net/manual/en/function.mysql-errno.php * @param resource $link_identifier [optional] * @return int the error number from the last MySQL function, or * 0 (zero) if no error occurred. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_errno($link_identifier = null) {} /** * Get number of affected rows in previous MySQL operation * @link https://php.net/manual/en/function.mysql-affected-rows.php * @param resource $link_identifier [optional] * @return int the number of affected rows on success, and -1 if the last query * failed. *

    *

    * If the last query was a DELETE query with no WHERE clause, all * of the records will have been deleted from the table but this * function will return zero with MySQL versions prior to 4.1.2. *

    *

    * When using UPDATE, MySQL will not update columns where the new value is the * same as the old value. This creates the possibility that * mysql_affected_rows may not actually equal the number * of rows matched, only the number of rows that were literally affected by * the query. *

    *

    * The REPLACE statement first deletes the record with the same primary key * and then inserts the new record. This function returns the number of * deleted records plus the number of inserted records. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_affected_rows($link_identifier = null) {} /** * Get the ID generated in the last query * @link https://php.net/manual/en/function.mysql-insert-id.php * @param resource $link_identifier [optional] * @return int The ID generated for an AUTO_INCREMENT column by the previous * query on success, 0 if the previous * query does not generate an AUTO_INCREMENT value, or false if * no MySQL connection was established. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_insert_id($link_identifier = null) {} /** * Get result data * @link https://php.net/manual/en/function.mysql-result.php * @param resource $result * @param int $row

    * The row number from the result that's being retrieved. Row numbers * start at 0. *

    * @param mixed $field [optional]

    * The name or offset of the field being retrieved. *

    *

    * It can be the field's offset, the field's name, or the field's table * dot field name (tablename.fieldname). If the column name has been * aliased ('select foo as bar from...'), use the alias instead of the * column name. If undefined, the first field is retrieved. *

    * @return string The contents of one cell from a MySQL result set on success, or * false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_result($result, $row, $field = 0) {} /** * Get number of rows in result * @link https://php.net/manual/en/function.mysql-num-rows.php * @param resource $result

    The result resource that is being evaluated. This result comes from a call to mysql_query().

    * @return int|false

    The number of rows in the result set on success or FALSE on failure.

    * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_num_rows($result) {} /** * Get number of fields in result * @link https://php.net/manual/en/function.mysql-num-fields.php * @param resource $result * @return int the number of fields in the result set resource on * success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_num_fields($result) {} /** * Get a result row as an enumerated array * @link https://php.net/manual/en/function.mysql-fetch-row.php * @param resource $result * @return array an numerical array of strings that corresponds to the fetched row, or * false if there are no more rows. *

    *

    * mysql_fetch_row fetches one row of data from * the result associated with the specified result identifier. The * row is returned as an array. Each result column is stored in an * array offset, starting at offset 0. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_fetch_row($result) {} /** * Fetch a result row as an associative array, a numeric array, or both * @link https://php.net/manual/en/function.mysql-fetch-array.php * @param resource $result * @param int $result_type [optional]

    * The type of array that is to be fetched. It's a constant and can * take the following values: MYSQL_ASSOC, * MYSQL_NUM, and * MYSQL_BOTH. *

    * @return array|false an array of strings that corresponds to the fetched row, or false * if there are no more rows. The type of returned array depends on * how result_type is defined. By using * MYSQL_BOTH (default), you'll get an array with both * associative and number indices. Using MYSQL_ASSOC, you * only get associative indices (as mysql_fetch_assoc * works), using MYSQL_NUM, you only get number indices * (as mysql_fetch_row works). *

    *

    * If two or more columns of the result have the same field names, * the last column will take precedence. To access the other column(s) * of the same name, you must use the numeric index of the column or * make an alias for the column. For aliased columns, you cannot * access the contents with the original column name. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_fetch_array($result, $result_type = MYSQL_BOTH) {} /** * Fetch a result row as an associative array * @link https://php.net/manual/en/function.mysql-fetch-assoc.php * @param resource $result * @return array an associative array of strings that corresponds to the fetched row, or * false if there are no more rows. *

    *

    * If two or more columns of the result have the same field names, * the last column will take precedence. To access the other * column(s) of the same name, you either need to access the * result with numeric indices by using * mysql_fetch_row or add alias names. * See the example at the mysql_fetch_array * description about aliases. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_fetch_assoc($result) {} /** * @template T * * Fetch a result row as an object * @link https://php.net/manual/en/function.mysql-fetch-object.php * @param resource $result * @param class-string $class_name [optional]

    * The name of the class to instantiate, set the properties of and return. * If not specified, a stdClass object is returned. *

    * @param array $params [optional]

    * An optional array of parameters to pass to the constructor * for class_name objects. *

    * @return T|stdClass an object with string properties that correspond to the * fetched row, or false if there are no more rows. *

    *

    * mysql_fetch_row fetches one row of data from * the result associated with the specified result identifier. The * row is returned as an array. Each result column is stored in an * array offset, starting at offset 0. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_fetch_object($result, $class_name = 'stdClass', array $params = null) {} /** * Move internal result pointer * @link https://php.net/manual/en/function.mysql-data-seek.php * @param resource $result * @param int $row_number

    * The desired row number of the new result pointer. *

    * @return bool true on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_data_seek($result, $row_number) {} /** * Get the length of each output in a result * @link https://php.net/manual/en/function.mysql-fetch-lengths.php * @param resource $result * @return array|false An array of lengths on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_fetch_lengths($result) {} /** * Get column information from a result and return as an object * @link https://php.net/manual/en/function.mysql-fetch-field.php * @param resource $result * @param int $field_offset [optional]

    * The numerical field offset. If the field offset is not specified, the * next field that was not yet retrieved by this function is retrieved. * The field_offset starts at 0. *

    * @return object an object containing field information. The properties * of the object are: *

    *

    * name - column name * table - name of the table the column belongs to * def - default value of the column * max_length - maximum length of the column * not_null - 1 if the column cannot be null * primary_key - 1 if the column is a primary key * unique_key - 1 if the column is a unique key * multiple_key - 1 if the column is a non-unique key * numeric - 1 if the column is numeric * blob - 1 if the column is a BLOB * type - the type of the column * unsigned - 1 if the column is unsigned * zerofill - 1 if the column is zero-filled * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_fetch_field($result, $field_offset = 0) {} /** * Set result pointer to a specified field offset * @link https://php.net/manual/en/function.mysql-field-seek.php * @param resource $result * @param int $field_offset * @return bool true on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_field_seek($result, $field_offset) {} /** * Free result memory * @link https://php.net/manual/en/function.mysql-free-result.php * @param resource $result * @return bool true on success or false on failure. *

    * If a non-resource is used for the result, an * error of level E_WARNING will be emitted. It's worth noting that * mysql_query only returns a resource * for SELECT, SHOW, EXPLAIN, and DESCRIBE queries. *

    * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_free_result($result) {} /** * Get the name of the specified field in a result * @link https://php.net/manual/en/function.mysql-field-name.php * @param resource $result * @param int $field_offset * @return string|false The name of the specified field index on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_field_name($result, $field_offset) {} /** * Get name of the table the specified field is in * @link https://php.net/manual/en/function.mysql-field-table.php * @param resource $result * @param int $field_offset * @return string The name of the table on success. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_field_table($result, $field_offset) {} /** * Returns the length of the specified field * @link https://php.net/manual/en/function.mysql-field-len.php * @param resource $result * @param int $field_offset * @return int|false The length of the specified field index on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_field_len($result, $field_offset) {} /** * Get the type of the specified field in a result * @link https://php.net/manual/en/function.mysql-field-type.php * @param resource $result * @param int $field_offset * @return string The returned field type * will be one of "int", "real", * "string", "blob", and others as * detailed in the MySQL * documentation. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_field_type($result, $field_offset) {} /** * Get the flags associated with the specified field in a result * @link https://php.net/manual/en/function.mysql-field-flags.php * @param resource $result * @param int $field_offset * @return string|false a string of flags associated with the result or false on failure. *

    * The following flags are reported, if your version of MySQL * is current enough to support them: "not_null", * "primary_key", "unique_key", * "multiple_key", "blob", * "unsigned", "zerofill", * "binary", "enum", * "auto_increment" and "timestamp". *

    * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_field_flags($result, $field_offset) {} /** * Escapes a string for use in a mysql_query * @link https://php.net/manual/en/function.mysql-escape-string.php * @param string $unescaped_string

    * The string that is to be escaped. *

    * @return string the escaped string. * @removed 7.0 */ #[Deprecated(replacement: 'mysql_real_escape_string(%parameter0%)', since: '5.3')] function mysql_escape_string($unescaped_string) {} /** * Escapes special characters in a string for use in an SQL statement * @link https://php.net/manual/en/function.mysql-real-escape-string.php * @param string $unescaped_string

    * The string that is to be escaped. *

    * @param resource $link_identifier [optional] * @return string|false the escaped string, or false on error. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_real_escape_string($unescaped_string, $link_identifier = null) {} /** * Get current system status * @link https://php.net/manual/en/function.mysql-stat.php * @param resource $link_identifier [optional] * @return string a string with the status for uptime, threads, queries, open tables, * flush tables and queries per second. For a complete list of other status * variables, you have to use the SHOW STATUS SQL command. * If link_identifier is invalid, null is returned. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_stat($link_identifier = null) {} /** * Return the current thread ID * @link https://php.net/manual/en/function.mysql-thread-id.php * @param resource $link_identifier [optional] * @return int|false The thread ID on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_thread_id($link_identifier = null) {} /** * Returns the name of the character set * @link https://php.net/manual/en/function.mysql-client-encoding.php * @param resource $link_identifier [optional] * @return string the default character set name for the current connection. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_client_encoding($link_identifier = null) {} /** * Ping a server connection or reconnect if there is no connection * @link https://php.net/manual/en/function.mysql-ping.php * @param resource $link_identifier [optional] * @return bool true if the connection to the server MySQL server is working, * otherwise false. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_ping($link_identifier = null) {} /** * Get MySQL client info * @link https://php.net/manual/en/function.mysql-get-client-info.php * @return string The MySQL client version. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_get_client_info() {} /** * Get MySQL host info * @link https://php.net/manual/en/function.mysql-get-host-info.php * @param resource $link_identifier [optional] * @return string a string describing the type of MySQL connection in use for the * connection or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_get_host_info($link_identifier = null) {} /** * Get MySQL protocol info * @link https://php.net/manual/en/function.mysql-get-proto-info.php * @param resource $link_identifier [optional] * @return int|false the MySQL protocol on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_get_proto_info($link_identifier = null) {} /** * Get MySQL server info * @link https://php.net/manual/en/function.mysql-get-server-info.php * @param resource $link_identifier [optional] * @return string|false the MySQL server version on success or false on failure. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_get_server_info($link_identifier = null) {} /** * Get information about the most recent query * @link https://php.net/manual/en/function.mysql-info.php * @param resource $link_identifier [optional] * @return string|false information about the statement on success, or false on * failure. See the example below for which statements provide information, * and what the returned value may look like. Statements that are not listed * will return false. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_info($link_identifier = null) {} /** * Sets the client character set * @link https://php.net/manual/en/function.mysql-set-charset.php * @param string $charset

    * A valid character set name. *

    * @param resource $link_identifier [optional] * @return bool true on success or false on failure. * @since 5.2.3 * @removed 7.0 * @see mysqli_set_charset() */ #[Deprecated(replacement: 'Use mysqli_set_charset instead', since: '5.5')] function mysql_set_charset($charset, $link_identifier = null) {} /** * @param $database_name * @param $query * @param $link_identifier [optional] * @removed 7.0 */ #[Deprecated(replacement: "mysql_db_query(%parametersList%)", since: '5.3')] function mysql($database_name, $query, $link_identifier) {} /** * @param $result * @param $field_index * @removed 7.0 */ #[Deprecated(replacement: 'mysql_field_name(%parametersList%)', since: '5.5')] function mysql_fieldname($result, $field_index) {} /** * @param $result * @param $field_offset * @removed 7.0 */ #[Deprecated(replacement: 'mysql_field_table(%parametersList%)', since: '5.5')] function mysql_fieldtable($result, $field_offset) {} /** * @param $result * @param $field_offset * @removed 7.0 */ #[Deprecated(replacement: 'mysql_field_len(%parametersList%)', since: '5.5')] function mysql_fieldlen($result, $field_offset) {} /** * @param $result * @param $field_offset * @removed 7.0 */ #[Deprecated(replacement: 'mysql_field_type(%parametersList%)', since: '5.5')] function mysql_fieldtype($result, $field_offset) {} /** * @param $result * @param $field_offset * @removed 7.0 */ #[Deprecated(replacement: 'mysql_field_flags(%parametersList%)', since: '5.5')] function mysql_fieldflags($result, $field_offset) {} /** * @param $database_name * @param $link_identifier [optional] * @removed 7.0 */ #[Deprecated(replacement: 'mysql_select_db(%parametersList%)', since: '5.5')] function mysql_selectdb($database_name, $link_identifier) {} /** * @param $result * @removed 7.0 */ #[Deprecated(replacement: 'mysql_free_result(%parametersList%)', since: '5.5')] function mysql_freeresult($result) {} /** * @param $result * @removed 7.0 */ #[Deprecated(replacement: 'mysql_num_fields(%parametersList%)', since: '5.5')] function mysql_numfields($result) {} /** * (PHP 4, PHP 5) * Alias of mysql_num_rows() * @link https://php.net/manual/en/function.mysql-num-rows.php * @param resource $result

    The result resource that is being evaluated. This result comes from a call to mysql_query().

    * @return int|false

    The number of rows in the result set on success or FALSE on failure.

    * @removed 7.0 */ #[Deprecated(replacement: 'mysql_num_rows(%parametersList%)', since: '5.5')] function mysql_numrows($result) {} /** * @param $link_identifier [optional] * @removed 7.0 */ #[Deprecated(replacement: 'mysql_list_dbs(%parametersList%)', since: '5.5')] function mysql_listdbs($link_identifier) {} /** * @param $database_name * @param $link_identifier [optional] * @removed 7.0 */ #[Deprecated(replacement: 'mysql_list_tables(%parametersList%)', since: '5.5')] function mysql_listtables($database_name, $link_identifier) {} /** * @param $database_name * @param $table_name * @param $link_identifier [optional] * @removed 7.0 */ #[Deprecated(replacement: 'mysql_list_fields(%parametersList%)', since: '5.5')] function mysql_listfields($database_name, $table_name, $link_identifier) {} /** * Retrieves database name from the call to {@see mysql_list_dbs} * @link https://php.net/manual/en/function.mysql-db-name.php * @param resource $result

    * The result pointer from a call to mysql_list_dbs. *

    * @param int $row

    * The index into the result set. *

    * @param mixed $field [optional]

    * The field name. *

    * @return string|false the database name on success, and false on failure. If false * is returned, use mysql_error to determine the nature * of the error. * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_db_name($result, $row, $field = null) {} /** * @param $result * @param $row * @param $field [optional] * @removed 7.0 */ #[Deprecated(replacement: 'mysql_db_name(%parametersList%)', since: '5.5')] function mysql_dbname($result, $row, $field) {} /** * Get table name of field * @link https://php.net/manual/en/function.mysql-tablename.php * @param resource $result

    * A result pointer resource that's returned from * mysql_list_tables. *

    * @param int $i

    * The integer index (row/table number) *

    * @return string|false The name of the table on success or false on failure. *

    * Use the mysql_tablename function to * traverse this result pointer, or any function for result tables, * such as mysql_fetch_array. *

    * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_tablename($result, $i) {} /** * @param $result * @param $row * @param $field [optional] * @removed 7.0 */ #[Deprecated(since: '5.5')] function mysql_table_name($result, $row, $field) {} /** * Columns are returned into the array having the fieldname as the array * index. * @link https://php.net/manual/en/mysql.constants.php * @deprecated 5.5 * @removed 7.0 */ define('MYSQL_ASSOC', 1); /** * Columns are returned into the array having a numerical index to the * fields. This index starts with 0, the first field in the result. * @link https://php.net/manual/en/mysql.constants.php * @deprecated 5.5 * @removed 7.0 */ define('MYSQL_NUM', 2); /** * Columns are returned into the array having both a numerical index * and the fieldname as the array index. * @link https://php.net/manual/en/mysql.constants.php * @deprecated 5.5 * @removed 7.0 */ define('MYSQL_BOTH', 3); /** * Use compression protocol * @link https://php.net/manual/en/mysql.constants.php * @deprecated 5.5 * @removed 7.0 */ define('MYSQL_CLIENT_COMPRESS', 32); /** * Use SSL encryption. This flag is only available with version 4.x * of the MySQL client library or newer. Version 3.23.x is bundled both * with PHP 4 and Windows binaries of PHP 5. * @link https://php.net/manual/en/mysql.constants.php * @deprecated 5.5 * @removed 7.0 */ define('MYSQL_CLIENT_SSL', 2048); /** * Allow interactive_timeout seconds (instead of wait_timeout) of * inactivity before closing the connection. * @link https://php.net/manual/en/mysql.constants.php * @deprecated 5.5 * @removed 7.0 */ define('MYSQL_CLIENT_INTERACTIVE', 1024); /** * Allow space after function names * @link https://php.net/manual/en/mysql.constants.php * @deprecated 5.5 * @removed 7.0 */ define('MYSQL_CLIENT_IGNORE_SPACE', 256); // End of mysql v.1.0 data pairs. A URL to a file containing a SVM Light formatted problem, with the each line being a new training example, the start of each line containing the class (1, -1) then a series of tab separated data values shows as key:value. A opened stream pointing to a data source formatted as in the file above. * @param array|null $weights Weights are an optional set of weighting parameters for the different classes, to help account for unbalanced training sets. For example, if the classes were 1 and -1, and -1 had significantly more example than one, the weight for -1 could be 0.5. Weights should be in the range 0-1. * @return SVMModel Returns an SVMModel that can be used to classify previously unseen data. Throws SVMException on error * @throws SMVException * @link https://www.php.net/manual/en/svm.train.php */ public function train(array $problem, array $weights = null): SVMModel {} } value pairs in increasing key order, but not necessarily continuous. * @return float the predicted value. This will be a class label in the case of classification, a real value in the case of regression. Throws SVMException on error * @throws SVMException Throws SVMException on error * @link https://www.php.net/manual/en/svmmodel.predict-probability.php */ public function predict_probability(array $data): float {} /** * Predict a value for previously unseen data * * This function accepts an array of data and attempts to predict the class or regression value based on the model extracted from previously trained data. * @param array $data The array to be classified. This should be a series of key => value pairs in increasing key order, but not necessarily continuous. * @return float the predicted value. This will be a class label in the case of classification, a real value in the case of regression. Throws SVMException on error * @throws SVMException Throws SVMException on error * @link https://www.php.net/manual/en/svmmodel.predict.php */ public function predict(array $data): float {} /** * Save a model to a file, for later use * @param string $filename The file to save the model to. * @return bool Throws SVMException on error. Returns true on success. * @throws SVMException Throws SVMException on error * @link https://www.php.net/manual/en/svmmodel.save.php */ public function save(string $filename): bool {} } 'string'], default: '')] $data, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = 0, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $dataIsURL = false, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespaceOrPrefix = "", #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $isPrefix = false ) {} /** * Provides access to element's children * private Method not callable directly, stub exists for typehint only * @param string $name child name * @return static */ private function __get($name) {} /** * Return a well-formed XML string based on SimpleXML element * @link https://php.net/manual/en/simplexmlelement.asxml.php * @param string $filename [optional]

    * If specified, the function writes the data to the file rather than * returning it. *

    * @return string|bool If the filename isn't specified, this function * returns a string on success and FALSE on error. If the * parameter is specified, it returns TRUE if the file was written * successfully and FALSE otherwise. * @since 5.0.1 */ #[TentativeType] public function asXML(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $filename = null): string|bool {} /** * Alias of SimpleXMLElement::asXML * Return a well-formed XML string based on SimpleXML element * @link https://php.net/manual/en/simplexmlelement.savexml.php * @param string $filename [optional]

    * If specified, the function writes the data to the file rather than * returning it. *

    * @return string|bool If the filename isn't specified, this function * returns a string on success and false on error. If the * parameter is specified, it returns true if the file was written * successfully and false otherwise. */ #[TentativeType] public function saveXML(#[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $filename = null): string|bool {} /** * Runs XPath query on XML data * @link https://php.net/manual/en/simplexmlelement.xpath.php * @param string $expression

    * An XPath path *

    * @return static[]|false|null an array of SimpleXMLElement objects or FALSE in * case of an error. */ #[TentativeType] public function xpath(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $expression): array|false|null {} /** * Creates a prefix/ns context for the next XPath query * @link https://php.net/manual/en/simplexmlelement.registerxpathnamespace.php * @param string $prefix

    * The namespace prefix to use in the XPath query for the namespace given in * ns. *

    * @param string $namespace

    * The namespace to use for the XPath query. This must match a namespace in * use by the XML document or the XPath query using * prefix will not return any results. *

    * @return bool TRUE on success or FALSE on failure. */ #[TentativeType] public function registerXPathNamespace( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $prefix, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace ): bool {} /** * Identifies an element's attributes * @link https://php.net/manual/en/simplexmlelement.attributes.php * @param string $namespaceOrPrefix [optional]

    * An optional namespace for the retrieved attributes *

    * @param bool $isPrefix [optional]

    * Default to FALSE *

    * @return static|null a SimpleXMLElement object that can be * iterated over to loop through the attributes on the tag. *

    *

    * Returns NULL if called on a SimpleXMLElement * object that already represents an attribute and not a tag. * @since 5.0.1 */ #[TentativeType] public function attributes( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespaceOrPrefix = null, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $isPrefix = false ): ?static {} /** * Finds children of given node * @link https://php.net/manual/en/simplexmlelement.children.php * @param string $namespaceOrPrefix [optional]

    * An XML namespace. *

    * @param bool $isPrefix [optional]

    * If is_prefix is TRUE, * ns will be regarded as a prefix. If FALSE, * ns will be regarded as a namespace * URL. *

    * @return static|null a SimpleXMLElement element, whether the node * has children or not. * @since 5.0.1 */ #[Pure] #[TentativeType] public function children( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespaceOrPrefix = null, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $isPrefix = false ): ?static {} /** * Returns namespaces used in document * @link https://php.net/manual/en/simplexmlelement.getnamespaces.php * @param bool $recursive [optional]

    * If specified, returns all namespaces used in parent and child nodes. * Otherwise, returns only namespaces used in root node. *

    * @return array The getNamespaces method returns an array of * namespace names with their associated URIs. * @since 5.1.2 */ #[Pure] #[TentativeType] public function getNamespaces(#[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $recursive = false): array {} /** * Returns namespaces declared in document * @link https://php.net/manual/en/simplexmlelement.getdocnamespaces.php * @param bool $recursive [optional]

    * If specified, returns all namespaces declared in parent and child nodes. * Otherwise, returns only namespaces declared in root node. *

    * @param bool $fromRoot [optional]

    * Allows you to recursively check namespaces under a child node instead of * from the root of the XML doc. *

    * @return array The getDocNamespaces method returns an array * of namespace names with their associated URIs. * @since 5.1.2 */ #[Pure] #[TentativeType] public function getDocNamespaces( #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $recursive = false, #[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $fromRoot = true ): array|false {} /** * Gets the name of the XML element * @link https://php.net/manual/en/simplexmlelement.getname.php * @return string The getName method returns as a string the * name of the XML tag referenced by the SimpleXMLElement object. * @since 5.1.3 */ #[Pure] #[TentativeType] public function getName(): string {} /** * Adds a child element to the XML node * @link https://php.net/manual/en/simplexmlelement.addchild.php * @param string $qualifiedName

    * The name of the child element to add. *

    * @param string $value [optional]

    * If specified, the value of the child element. *

    * @param string $namespace [optional]

    * If specified, the namespace to which the child element belongs. *

    * @return static|null The addChild method returns a SimpleXMLElement * object representing the child added to the XML node. * @since 5.1.3 */ #[TentativeType] public function addChild( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $value = null, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace = null ): ?static {} /** * Adds an attribute to the SimpleXML element * @link https://php.net/manual/en/simplexmlelement.addattribute.php * @param string $qualifiedName

    * The name of the attribute to add. *

    * @param string $value

    * The value of the attribute. *

    * @param string $namespace [optional]

    * If specified, the namespace to which the attribute belongs. *

    * @return void No value is returned. * @since 5.1.3 */ #[TentativeType] public function addAttribute( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $qualifiedName, #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $value = null, #[PhpStormStubsElementAvailable(from: '8.0')] string $value, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $namespace = null ): void {} /** * Returns the string content * @link https://php.net/manual/en/simplexmlelement.tostring.php * @return string the string content on success or an empty string on failure. * @since 5.3 */ #[TentativeType] public function __toString(): string {} /** * Counts the children of an element * @link https://php.net/manual/en/simplexmlelement.count.php * @return int<0,max> the number of elements of an element. */ #[Pure] #[TentativeType] public function count(): int {} /** * Class provides access to children by position, and attributes by name * private Method not callable directly, stub exists for typehint only * @param string|int $offset * @return bool true on success or false on failure. */ #[Pure] public function offsetExists($offset) {} /** * Class provides access to children by position, and attributes by name * private Method not callable directly, stub exists for typehint only * @param string|int $offset * @return static Either a named attribute or an element from a list of children */ #[Pure] public function offsetGet($offset) {} /** * Class provides access to children by position, and attributes by name * private Method not callable directly, stub exists for typehint only * @param string|int $offset * @param mixed $value * @return void */ public function offsetSet($offset, $value) {} /** * Class provides access to children by position, and attributes by name * private Method not callable directly, stub exists for typehint only * @param string|int $offset * @return void */ public function offsetUnset($offset) {} /** * Rewind to the first element * @link https://php.net/manual/en/simplexmliterator.rewind.php * @return void No value is returned. */ #[TentativeType] public function rewind(): void {} /** * Check whether the current element is valid * @link https://php.net/manual/en/simplexmliterator.valid.php * @return bool TRUE if the current element is valid, otherwise FALSE */ #[Pure] #[TentativeType] public function valid(): bool {} /** * Returns the current element * @link https://php.net/manual/en/simplexmliterator.current.php * @return static|null the current element as a SimpleXMLElement object or NULL on failure. */ #[Pure] #[TentativeType] public function current(): ?static {} /** * Return current key * @link https://php.net/manual/en/simplexmliterator.key.php * @return string|false the XML tag name of the element referenced by the current SimpleXMLIterator object */ #[TentativeType] #[LanguageLevelTypeAware(['8.0' => 'string'], default: 'string|false')] public function key() {} /** * Move to next element * @link https://php.net/manual/en/simplexmliterator.next.php * @return void No value is returned. */ #[TentativeType] public function next(): void {} /** * @return bool * @since 8.0 */ #[Pure] #[TentativeType] public function hasChildren(): bool {} /** * @since 8.0 */ #[Pure] #[TentativeType] public function getChildren(): ?SimpleXMLElement {} } /** * The SimpleXMLIterator provides recursive iteration over all nodes of a SimpleXMLElement object. * @link https://php.net/manual/en/class.simplexmliterator.php */ class SimpleXMLIterator extends SimpleXMLElement implements RecursiveIterator, Countable, Stringable { /** * Rewind to the first element * @link https://php.net/manual/en/simplexmliterator.rewind.php * @return void No value is returned. */ public function rewind() {} /** * Check whether the current element is valid * @link https://php.net/manual/en/simplexmliterator.valid.php * @return bool TRUE if the current element is valid, otherwise FALSE */ #[Pure] public function valid() {} /** * Returns the current element * @link https://php.net/manual/en/simplexmliterator.current.php * @return static|null the current element as a SimpleXMLIterator object or NULL on failure. */ #[Pure] public function current() {} /** * Return current key * @link https://php.net/manual/en/simplexmliterator.key.php * @return string|false the XML tag name of the element referenced by the current SimpleXMLIterator object or FALSE */ public function key() {} /** * Move to next element * @link https://php.net/manual/en/simplexmliterator.next.php * @return void No value is returned. */ public function next() {} /** * Checks whether the current element has sub elements. * @link https://php.net/manual/en/simplexmliterator.haschildren.php * @return bool TRUE if the current element has sub-elements, otherwise FALSE */ #[Pure] public function hasChildren() {} /** * Returns the sub-elements of the current element * @link https://php.net/manual/en/simplexmliterator.getchildren.php * @return SimpleXMLIterator a SimpleXMLIterator object containing * the sub-elements of the current element. */ #[Pure] public function getChildren() {} /** * Returns the string content * @link https://php.net/manual/en/simplexmlelement.tostring.php * @return string the string content on success or an empty string on failure. * @since 5.3 */ public function __toString() {} /** * Counts the children of an element * @link https://php.net/manual/en/simplexmlelement.count.php * @return int the number of elements of an element. */ #[Pure] public function count() {} } /** * Interprets an XML file into an object * @link https://php.net/manual/en/function.simplexml-load-file.php * @param string $filename

    * Path to the XML file *

    *

    * Libxml 2 unescapes the URI, so if you want to pass e.g. * b&c as the URI parameter a, * you have to call * simplexml_load_file(rawurlencode('https://example.com/?a=' . * urlencode('b&c'))). Since PHP 5.1.0 you don't need to do * this because PHP will do it for you. *

    * @param string|null $class_name [optional]

    * You may use this optional parameter so that * simplexml_load_file will return an object of * the specified class. That class should extend the * SimpleXMLElement class. *

    * @param int $options [optional]

    * Since PHP 5.1.0 and Libxml 2.6.0, you may also use the * options parameter to specify additional Libxml parameters. *

    * @param string $namespace_or_prefix [optional]

    * Namespace prefix or URI. *

    * @param bool $is_prefix [optional]

    * TRUE if ns is a prefix, FALSE if it's a URI; * defaults to FALSE. *

    * @return SimpleXMLElement|false an object of class SimpleXMLElement with * properties containing the data held within the XML document, or FALSE on failure. */ function simplexml_load_file(string $filename, ?string $class_name = "SimpleXMLElement", int $options = 0, string $namespace_or_prefix = "", bool $is_prefix = false): SimpleXMLElement|false {} /** * Interprets a string of XML into an object * @link https://php.net/manual/en/function.simplexml-load-string.php * @param string $data

    * A well-formed XML string *

    * @param string|null $class_name [optional]

    * You may use this optional parameter so that * simplexml_load_string will return an object of * the specified class. That class should extend the * SimpleXMLElement class. *

    * @param int $options [optional]

    * Since PHP 5.1.0 and Libxml 2.6.0, you may also use the * options parameter to specify additional Libxml parameters. *

    * @param string $namespace_or_prefix [optional]

    * Namespace prefix or URI. *

    * @param bool $is_prefix [optional]

    * TRUE if ns is a prefix, FALSE if it's a URI; * defaults to FALSE. *

    * @return SimpleXMLElement|false an object of class SimpleXMLElement with * properties containing the data held within the xml document, or FALSE on failure. */ function simplexml_load_string(string $data, ?string $class_name = "SimpleXMLElement", int $options = 0, string $namespace_or_prefix = "", bool $is_prefix = false): SimpleXMLElement|false {} /** * Get a SimpleXMLElement object from a DOM node. * @link https://php.net/manual/en/function.simplexml-import-dom.php * @param SimpleXMLElement|DOMNode $node

    * A DOM Element node *

    * @param string|null $class_name [optional]

    * You may use this optional parameter so that * simplexml_import_dom will return an object of * the specified class. That class should extend the * SimpleXMLElement class. *

    * @return SimpleXMLElement|null a SimpleXMLElement or FALSE on failure. */ function simplexml_import_dom(#[LanguageLevelTypeAware(['8.4' => 'object'], default: 'SimpleXMLElement|DOMNode')] $node, ?string $class_name = "SimpleXMLElement"): ?SimpleXMLElement {} // End of SimpleXML v.0.1 * create a new broker object capable of requesting * @link https://php.net/manual/en/function.enchant-broker-init.php * @return resource|false|EnchantBroker a broker resource on success or FALSE. */ function enchant_broker_init() {} /** * Free the broker resource and its dictionaries * @link https://php.net/manual/en/function.enchant-broker-free.php * @param resource|EnchantBroker $broker

    * Broker resource *

    * @return bool TRUE on success or FALSE on failure. * @since 5.3 */ #[Deprecated(reason: "Unset the object instead", since: '8.0')] function enchant_broker_free($broker) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * Returns the last error of the broker * @link https://php.net/manual/en/function.enchant-broker-get-error.php * @param resource|EnchantBroker $broker

    * Broker resource. *

    * @return string|false Return the msg string if an error was found or FALSE */ function enchant_broker_get_error($broker) {} /** * Set the directory path for a given backend * @link https://www.php.net/manual/en/function.enchant-broker-set-dict-path.php * @param resource|EnchantBroker $broker * @param int $dict_type * @param string $value * @return bool TRUE on success or FALSE on failure. */ #[Deprecated(since: '8.0', reason: 'Relying on this function is highly discouraged.')] function enchant_broker_set_dict_path($broker, int $dict_type, string $value) {} /** * Get the directory path for a given backend * @link https://www.php.net/manual/en/function.enchant-broker-get-dict-path.php * @param resource|EnchantBroker $broker * @param int $dict_type * @return string|false */ #[Deprecated(since: '8.0', reason: 'Relying on this function is highly discouraged.')] function enchant_broker_get_dict_path($broker, $dict_type) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 1.0.1)
    * Returns a list of available dictionaries * @link https://php.net/manual/en/function.enchant-broker-list-dicts.php * @param resource|EnchantBroker $broker

    * Broker resource *

    * @return array Returns an array of available dictionaries with their details. */ function enchant_broker_list_dicts($broker) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * create a new dictionary using a tag * @link https://php.net/manual/en/function.enchant-broker-request-dict.php * @param resource|EnchantBroker $broker

    * Broker resource *

    * @param string $tag

    * A tag describing the locale, for example en_US, de_DE *

    * @return resource|false|EnchantDictionary a dictionary resource on success or FALSE on failure. */ function enchant_broker_request_dict($broker, $tag) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * creates a dictionary using a PWL file * @link https://php.net/manual/en/function.enchant-broker-request-pwl-dict.php * @param resource|EnchantBroker $broker

    * Broker resource *

    * @param string $filename

    * Path to the PWL file. *

    * @return resource|false|EnchantDictionary a dictionary resource on success or FALSE on failure. */ function enchant_broker_request_pwl_dict($broker, $filename) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * Free a dictionary resource * @link https://php.net/manual/en/function.enchant-broker-free-dict.php * @param resource|EnchantDictionary $dict

    * Dictionary resource. *

    * @return bool TRUE on success or FALSE on failure. */ #[Deprecated("Unset the object instead", since: '8.0')] function enchant_broker_free_dict($dict) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * Whether a dictionary exists or not. Using non-empty tag * @link https://php.net/manual/en/function.enchant-broker-dict-exists.php * @param resource|EnchantBroker $broker

    * Broker resource *

    * @param string $tag

    * non-empty tag in the LOCALE format, ex: us_US, ch_DE, etc. *

    * @return bool TRUE when the tag exist or FALSE when not. */ function enchant_broker_dict_exists($broker, $tag) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * Declares a preference of dictionaries to use for the language * @link https://php.net/manual/en/function.enchant-broker-set-ordering.php * @param resource|EnchantBroker $broker

    * Broker resource *

    * @param string $tag

    * Language tag. The special "*" tag can be used as a language tag * to declare a default ordering for any language that does not * explicitly declare an ordering. *

    * @param string $ordering

    * Comma delimited list of provider names *

    * @return bool TRUE on success or FALSE on failure. */ function enchant_broker_set_ordering($broker, $tag, $ordering) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0)
    * Enumerates the Enchant providers * @link https://php.net/manual/en/function.enchant-broker-describe.php * @param resource|EnchantBroker $broker

    * Broker resource *

    * @return array|false */ function enchant_broker_describe($broker) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * Check whether a word is correctly spelled or not * @link https://php.net/manual/en/function.enchant-dict-check.php * @param resource|EnchantDictionary $dict

    * Dictionary resource *

    * @param string $word

    * The word to check *

    * @return bool TRUE if the word is spelled correctly, FALSE if not. */ function enchant_dict_check($dict, $word) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * Will return a list of values if any of those pre-conditions are not met * @link https://php.net/manual/en/function.enchant-dict-suggest.php * @param resource|EnchantDictionary $dict

    * Dictionary resource *

    * @param string $word

    * Word to use for the suggestions. *

    * @return array|false Will returns an array of suggestions if the word is bad spelled. */ function enchant_dict_suggest($dict, $word) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * add a word to personal word list * @link https://php.net/manual/en/function.enchant-dict-add-to-personal.php * @param resource $dict

    * Dictionary resource *

    * @param string $word

    * The word to add *

    * @return void * @see enchant_dict_add() */ #[Deprecated( reason: 'Use enchant_dict_add instead', replacement: 'enchant_dict_add(%parameter0%, %parameter1%)', since: '8.0' )] function enchant_dict_add_to_personal($dict, $word) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * add 'word' to this spell-checking session * @link https://php.net/manual/en/function.enchant-dict-add-to-session.php * @param resource|EnchantDictionary $dict

    * Dictionary resource *

    * @param string $word

    * The word to add *

    * @return void */ function enchant_dict_add_to_session($dict, $word) {} /** * (PHP 8)
    * Add a word to personal word list * @link https://php.net/manual/en/function.enchant-dict-add.php * @param EnchantDictionary $dictionary

    * An Enchant dictionary returned by enchant_broker_request_dict() or enchant_broker_request_pwl_dict(). *

    * @param string $word

    * The word to add *

    * @return void * @since 8.0 */ function enchant_dict_add($dictionary, $word) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * whether or not 'word' exists in this spelling-session * @link https://php.net/manual/en/function.enchant-dict-is-in-session.php * @param resource $dict

    * Dictionary resource *

    * @param string $word

    * The word to lookup *

    * @return bool TRUE if the word exists or FALSE * @see enchant_dict_is_added */ #[Deprecated( reason: 'Use enchant_dict_is_added instead', replacement: 'enchant_dict_is_added(%parameter0%, %parameter1%)', since: '8.0' )] function enchant_dict_is_in_session($dict, $word) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * Add a correction for a word * @link https://php.net/manual/en/function.enchant-dict-store-replacement.php * @param resource|EnchantDictionary $dict

    * Dictionary resource *

    * @param string $mis

    * The work to fix *

    * @param string $cor

    * The correct word *

    * @return void */ function enchant_dict_store_replacement($dict, $mis, $cor) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * Returns the last error of the current spelling-session * @link https://php.net/manual/en/function.enchant-dict-get-error.php * @param resource|EnchantDictionary $dict

    * Dictinaray resource *

    * @return string|false the error message as string or FALSE if no error occurred. */ function enchant_dict_get_error($dict) {} /** * (PHP 8)
    * Whether or not 'word' exists in this spelling-session * @link https://php.net/manual/en/function.enchant-dict-is-added.php * @param EnchantDictionary $dictionary

    * An Enchant dictionary returned by enchant_broker_request_dict() or enchant_broker_request_pwl_dict(). *

    * @param string $word

    * The word to lookup *

    * @return bool TRUE if the word exists or FALSE * @since 8.0 */ function enchant_dict_is_added($dictionary, $word) {} /** * (PHP 5 >= 5.3.0, PECL enchant >= 0.1.0 )
    * Describes an individual dictionary * @link https://php.net/manual/en/function.enchant-dict-describe.php * @param resource|EnchantDictionary $dict

    * Dictionary resource *

    * @return array Returns the details of the dictionary. */ function enchant_dict_describe($dict) {} /** * (PHP 5 >= 5.3.0, PECL enchant:0.2.0-1.0.1)
    * Check the word is correctly spelled and provide suggestions * @link https://php.net/manual/en/function.enchant-dict-quick-check.php * @param resource|EnchantDictionary $dict

    * Dictionary resource *

    * @param string $word

    * The word to check *

    * @param null|array &$suggestions [optional]

    * If the word is not correctly spelled, this variable will * contain an array of suggestions. *

    * @return bool TRUE if the word is correctly spelled or FALSE */ function enchant_dict_quick_check($dict, $word, ?array &$suggestions = null) {} /** * @deprecated 8.0 */ define('ENCHANT_MYSPELL', 1); /** * @deprecated 8.0 */ define('ENCHANT_ISPELL', 2); final class EnchantBroker {} final class EnchantDictionary {} // End of enchant v.1.1.0 * For a cataloged connection to a database, this parameter * represents the connection alias in the DB2 client catalog. *

    *

    * For an uncataloged connection to a database, * this parameter represents a complete DSN in the following format: * DRIVER=driver;DATABASE=database;HOSTNAME=hostname;PORT=port;PROTOCOL=TCPIP;UID=username;PWD=password; *

    * @param string|null $username

    * The username with which you are connecting to the database, or null if * the $database parameter contains a DSN which already provides the username for * the connection. *

    * @param string|null $password

    * The password with which you are connecting to the database, or null if * the $database parameter contains a DSN which already provides the password for * the connection. *

    * @param array $options

    * An associative array of connection options that affect the behavior * of the connection, where valid array keys include: * autocommit *

    * Passing the DB2_AUTOCOMMIT_ON value turns * autocommit on for this connection handle. *

    *

    * Passing the DB2_AUTOCOMMIT_OFF value turns * autocommit off for this connection handle. *

    * @return resource|false A connection handle resource if the connection attempt is * successful. If the connection attempt fails, db2_connect * returns false. */ function db2_connect(#[\SensitiveParameter] string $database, ?string $username, #[\SensitiveParameter] ?string $password, array $options = []) {} /** * Commits a transaction * @link https://php.net/manual/en/function.db2-commit.php * @param resource $connection

    * A valid database connection resource variable as returned from * db2_connect or db2_pconnect. *

    * @return bool true on success or false on failure. */ function db2_commit($connection): bool {} /** * Returns a persistent connection to a database * @link https://php.net/manual/en/function.db2-pconnect.php * @param string $database

    * For a cataloged connection to a database, this parameter * represents the connection alias in the DB2 client catalog. *

    *

    * For an uncataloged connection to a database, * this parameter represents a complete DSN in the following format: * DRIVER=driver;DATABASE=database;HOSTNAME=hostname;PORT=port;PROTOCOL=TCPIP;UID=username;PWD=password; *

    * @param string|null $username

    * The username with which you are connecting to the database, or null if * the $database parameter contains a DSN which already provides the username for * the connection. *

    * @param string|null $password

    * The password with which you are connecting to the database, or null if * the $database parameter contains a DSN which already provides the password for * the connection. *

    * @param array $options

    * An associative array of connection options that affect the behavior * of the connection, where valid array keys include: * autocommit *

    *

    * Passing the DB2_AUTOCOMMIT_ON value turns * autocommit on for this connection handle. *

    *

    * Passing the DB2_AUTOCOMMIT_OFF value turns * autocommit off for this connection handle. *

    * @return resource|false A connection handle resource if the connection attempt is * successful. db2_pconnect tries to reuse an existing * connection resource that exactly matches the * database, username, and * password parameters. If the connection attempt fails, * db2_pconnect returns false. */ function db2_pconnect(#[\SensitiveParameter] string $database, ?string $username, #[\SensitiveParameter] ?string $password, array $options = []) {} /** * Closes a persistent database connection * * This function closes a persistent DB2 client connection. * * @link https://php.net/manual/en/function.db2-pclose.php * * @param resource $connection Specifies a persistent DB2 client connection. * * @return bool Returns true on success or false on failure. */ function db2_pclose($connection): bool {} /** * Returns or sets the AUTOCOMMIT state for a database connection * @link https://php.net/manual/en/function.db2-autocommit.php * @param resource $connection

    * A valid database connection resource variable as returned from * db2_connect or db2_pconnect. *

    * @param int $value

    * One of the following constants:

    *

    * DB2_AUTOCOMMIT_OFF * Turns AUTOCOMMIT off. *

    *

    * DB2_AUTOCOMMIT_ON * Turns AUTOCOMMIT on. *

    * @return int|bool

    When db2_autocommit receives only the * connection parameter, it returns the current state * of AUTOCOMMIT for the requested connection as an integer value. A value of * 0 indicates that AUTOCOMMIT is off, while a value of 1 indicates that * AUTOCOMMIT is on. *

    *

    * When db2_autocommit receives both the * connection parameter and * autocommit parameter, it attempts to set the * AUTOCOMMIT state of the requested connection to the corresponding state. * true on success or false on failure.

    */ function db2_autocommit($connection, int $value = null): int|bool {} /** * Binds a PHP variable to an SQL statement parameter * @link https://php.net/manual/en/function.db2-bind-param.php * @param resource $stmt

    * A prepared statement returned from db2_prepare. *

    * @param int $parameter_number * @param string $variable_name * @param int $parameter_type * @param int $data_type * @param int $precision

    * Specifies the precision with which the variable should be bound to the * database. This parameter can also be used for retrieving XML output values * from stored procedures. A non-negative value specifies the maximum size of * the XML data that will be retrieved from the database. If this parameter * is not used, a default of 1MB will be assumed for retrieving the XML * output value from the stored procedure. *

    * @param int $scale

    * Specifies the scale with which the variable should be bound to the * database. *

    * @return bool true on success or false on failure. */ function db2_bind_param($stmt, int $parameter_number, string $variable_name, int $parameter_type = DB2_PARAM_IN, int $data_type = 0, int $precision = -1, int $scale = 0): bool {} /** * Closes a database connection * @link https://php.net/manual/en/function.db2-close.php * @param resource $connection

    * Specifies an active DB2 client connection. *

    * @return bool true on success or false on failure. */ function db2_close($connection): bool {} /** * Returns a result set listing the columns and associated privileges for a table * @link https://php.net/manual/en/function.db2-column-privileges.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string|null $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string|null $schema

    * The schema which contains the tables. To match all schemas, pass null * or an empty string. *

    * @param string|null $table_name * @param string|null $column_name * @return resource|false a statement resource with a result set containing rows describing * the column privileges for columns matching the specified parameters. The * rows are composed of the following columns: * * Column name * Description * * * TABLE_CAT * Name of the catalog. The value is NULL if this table does not * have catalogs. * * * TABLE_SCHEM * Name of the schema. * * * TABLE_NAME * Name of the table or view. * * * COLUMN_NAME * Name of the column. * * * GRANTOR * Authorization ID of the user who granted the privilege. * * * GRANTEE * Authorization ID of the user to whom the privilege was * granted. * * * PRIVILEGE * The privilege for the column. * * * IS_GRANTABLE * Whether the GRANTEE is permitted to grant this privilege to * other users. * */ function db2_column_privileges($connection, ?string $qualifier = null, ?string $schema = null, ?string $table_name = null, ?string $column_name = null) {} function db2_columnprivileges() {} /** * Returns a result set listing the columns and associated metadata for a table * @link https://php.net/manual/en/function.db2-columns.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string $schema

    * The schema which contains the tables. To match all schemas, pass * '%'. *

    * @param string $table_name * @param string $column_name * @return resource|false A statement resource with a result set containing rows describing * the columns matching the specified parameters. The rows are composed of * the following columns: * * Column name * Description * * * TABLE_CAT * Name of the catalog. The value is NULL if this table does not * have catalogs. * * * TABLE_SCHEM * Name of the schema. * * * TABLE_NAME * Name of the table or view. * * * COLUMN_NAME * Name of the column. * * * DATA_TYPE * The SQL data type for the column represented as an integer value. * * * TYPE_NAME * A string representing the data type for the column. * * * COLUMN_SIZE * An integer value representing the size of the column. * * * BUFFER_LENGTH * * Maximum number of bytes necessary to store data from this column. * * * * DECIMAL_DIGITS * * The scale of the column, or null where scale is not applicable. * * * * NUM_PREC_RADIX * * An integer value of either 10 (representing * an exact numeric data type), 2 (representing an * approximate numeric data type), or null (representing a data type for * which radix is not applicable). * * * * NULLABLE * An integer value representing whether the column is nullable or * not. * * * REMARKS * Description of the column. * * * COLUMN_DEF * Default value for the column. * * * SQL_DATA_TYPE * An integer value representing the size of the column. * * * SQL_DATETIME_SUB * * Returns an integer value representing a datetime subtype code, * or null for SQL data types to which this does not apply. * * * * CHAR_OCTET_LENGTH * * Maximum length in octets for a character data type column, which * matches COLUMN_SIZE for single-byte character set data, or null for * non-character data types. * * * * ORDINAL_POSITION * The 1-indexed position of the column in the table. * * * IS_NULLABLE * * A string value where 'YES' means that the column is nullable and * 'NO' means that the column is not nullable. * * */ function db2_columns($connection, $qualifier = null, $schema = null, $table_name = null, $column_name = null) {} /** * Returns a result set listing the foreign keys for a table * @link https://php.net/manual/en/function.db2-foreign-keys.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string|null $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string|null $schema

    * The schema which contains the tables. If schema * is null, db2_foreign_keys matches the schema for * the current connection. *

    * @param string $table_name * @return resource|false A statement resource with a result set containing rows describing * the foreign keys for the specified table. The result set is composed of the * following columns: * * Column name * Description * * * PKTABLE_CAT * * Name of the catalog for the table containing the primary key. The * value is NULL if this table does not have catalogs. * * * * PKTABLE_SCHEM * * Name of the schema for the table containing the primary key. * * * * PKTABLE_NAME * Name of the table containing the primary key. * * * PKCOLUMN_NAME * Name of the column containing the primary key. * * * FKTABLE_CAT * * Name of the catalog for the table containing the foreign key. The * value is NULL if this table does not have catalogs. * * * * FKTABLE_SCHEM * * Name of the schema for the table containing the foreign key. * * * * FKTABLE_NAME * Name of the table containing the foreign key. * * * FKCOLUMN_NAME * Name of the column containing the foreign key. * * * KEY_SEQ * 1-indexed position of the column in the key. * * * UPDATE_RULE * * Integer value representing the action applied to the foreign key * when the SQL operation is UPDATE. * * * * DELETE_RULE * * Integer value representing the action applied to the foreign key * when the SQL operation is DELETE. * * * * FK_NAME * The name of the foreign key. * * * PK_NAME * The name of the primary key. * * * DEFERRABILITY * * An integer value representing whether the foreign key deferrability is * SQL_INITIALLY_DEFERRED, SQL_INITIALLY_IMMEDIATE, or * SQL_NOT_DEFERRABLE. * * */ function db2_foreign_keys($connection, ?string $qualifier, ?string $schema, string $table_name) {} function db2_foreignkeys() {} /** * Returns a result set listing primary keys for a table * @link https://php.net/manual/en/function.db2-primary-keys.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string|null $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string|null $schema

    * The schema which contains the tables. If schema * is null, db2_primary_keys matches the schema for * the current connection. *

    * @param string $table_name * @return resource|false A statement resource with a result set containing rows describing * the primary keys for the specified table. The result set is composed of the * following columns: * * Column name * Description * * * TABLE_CAT * * Name of the catalog for the table containing the primary key. The * value is NULL if this table does not have catalogs. * * * * TABLE_SCHEM * * Name of the schema for the table containing the primary key. * * * * TABLE_NAME * Name of the table containing the primary key. * * * COLUMN_NAME * Name of the column containing the primary key. * * * KEY_SEQ * 1-indexed position of the column in the key. * * * PK_NAME * The name of the primary key. * */ function db2_primary_keys($connection, ?string $qualifier, ?string $schema, string $table_name) {} function db2_primarykeys() {} /** * Returns a result set listing stored procedure parameters * @link https://php.net/manual/en/function.db2-procedure-columns.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string|null $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string $schema

    * The schema which contains the procedures. This parameter accepts a * search pattern containing _ and % * as wildcards. *

    * @param string $procedure

    * The name of the procedure. This parameter accepts a * search pattern containing _ and % * as wildcards. *

    * @param string|null $parameter

    * The name of the parameter. This parameter accepts a search pattern * containing _ and % as wildcards. * If this parameter is null, all parameters for the specified stored * procedures are returned. *

    * @return resource|false A statement resource with a result set containing rows describing * the parameters for the stored procedures matching the specified parameters. * The rows are composed of the following columns: * * Column name * Description * * * PROCEDURE_CAT * The catalog that contains the procedure. The value is null if * this table does not have catalogs. * * * PROCEDURE_SCHEM * Name of the schema that contains the stored procedure. * * * PROCEDURE_NAME * Name of the procedure. * * * COLUMN_NAME * Name of the parameter. * * * COLUMN_TYPE * *

    * An integer value representing the type of the parameter: * * Return value * Parameter type * * * 1 (SQL_PARAM_INPUT) * Input (IN) parameter. * * * 2 (SQL_PARAM_INPUT_OUTPUT) * Input/output (INOUT) parameter. * * * 3 (SQL_PARAM_OUTPUT) * Output (OUT) parameter. * *

    * * * * DATA_TYPE * The SQL data type for the parameter represented as an integer * value. * * * TYPE_NAME * A string representing the data type for the parameter. * * * COLUMN_SIZE * An integer value representing the size of the parameter. * * * BUFFER_LENGTH * * Maximum number of bytes necessary to store data for this parameter. * * * * DECIMAL_DIGITS * * The scale of the parameter, or null where scale is not applicable. * * * * NUM_PREC_RADIX * * An integer value of either 10 (representing * an exact numeric data type), 2 (representing an * approximate numeric data type), or null (representing a data type for * which radix is not applicable). * * * * NULLABLE * An integer value representing whether the parameter is nullable * or not. * * * REMARKS * Description of the parameter. * * * COLUMN_DEF * Default value for the parameter. * * * SQL_DATA_TYPE * An integer value representing the size of the parameter. * * * SQL_DATETIME_SUB * * Returns an integer value representing a datetime subtype code, * or null for SQL data types to which this does not apply. * * * * CHAR_OCTET_LENGTH * * Maximum length in octets for a character data type parameter, which * matches COLUMN_SIZE for single-byte character set data, or null for * non-character data types. * * * * ORDINAL_POSITION * The 1-indexed position of the parameter in the CALL * statement. * * * IS_NULLABLE * * A string value where 'YES' means that the parameter accepts or * returns null values and 'NO' means that the parameter does not * accept or return null values. * * */ function db2_procedure_columns($connection, ?string $qualifier, string $schema, string $procedure, ?string $parameter) {} function db2_procedurecolumns() {} /** * Returns a result set listing the stored procedures registered in a database * @link https://php.net/manual/en/function.db2-procedures.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string|null $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string $schema

    * The schema which contains the procedures. This parameter accepts a * search pattern containing _ and % * as wildcards. *

    * @param string $procedure

    * The name of the procedure. This parameter accepts a * search pattern containing _ and % * as wildcards. *

    * @return resource|false A statement resource with a result set containing rows describing * the stored procedures matching the specified parameters. The rows are * composed of the following columns: * * Column name * Description * * * PROCEDURE_CAT * The catalog that contains the procedure. The value is null if * this table does not have catalogs. * * * PROCEDURE_SCHEM * Name of the schema that contains the stored procedure. * * * PROCEDURE_NAME * Name of the procedure. * * * NUM_INPUT_PARAMS * Number of input (IN) parameters for the stored procedure. * * * NUM_OUTPUT_PARAMS * Number of output (OUT) parameters for the stored procedure. * * * NUM_RESULT_SETS * Number of result sets returned by the stored procedure. * * * REMARKS * Any comments about the stored procedure. * * * PROCEDURE_TYPE * Always returns 1, indicating that the stored * procedure does not return a return value. * */ function db2_procedures($connection, ?string $qualifier, string $schema, string $procedure) {} /** * Returns a result set listing the unique row identifier columns for a table * @link https://php.net/manual/en/function.db2-special-columns.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string|null $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string $schema

    * The schema which contains the tables. *

    * @param string $table_name

    * The name of the table. *

    * @param int $scope

    * Integer value representing the minimum duration for which the * unique row identifier is valid. This can be one of the following * values: * * Integer value * SQL constant * Description * * * 0 * SQL_SCOPE_CURROW * Row identifier is valid only while the cursor is positioned * on the row. * * * 1 * SQL_SCOPE_TRANSACTION * Row identifier is valid for the duration of the * transaction. * * * 2 * SQL_SCOPE_SESSION * Row identifier is valid for the duration of the * connection. * *

    * @return resource|false A statement resource with a result set containing rows with unique * row identifier information for a table. The rows are composed of the * following columns: * * Column name * Description * * * SCOPE * *

    * * Integer value * SQL constant * Description * * * 0 * SQL_SCOPE_CURROW * Row identifier is valid only while the cursor is positioned * on the row. * * * 1 * SQL_SCOPE_TRANSACTION * Row identifier is valid for the duration of the * transaction. * * * 2 * SQL_SCOPE_SESSION * Row identifier is valid for the duration of the * connection. * *

    * * * * COLUMN_NAME * Name of the unique column. * * * DATA_TYPE * SQL data type for the column. * * * TYPE_NAME * Character string representation of the SQL data type for the * column. * * * COLUMN_SIZE * An integer value representing the size of the column. * * * BUFFER_LENGTH * * Maximum number of bytes necessary to store data from this column. * * * * DECIMAL_DIGITS * * The scale of the column, or null where scale is not applicable. * * * * NUM_PREC_RADIX * * An integer value of either 10 (representing * an exact numeric data type), 2 (representing an * approximate numeric data type), or null (representing a data type for * which radix is not applicable). * * * * PSEUDO_COLUMN * Always returns 1. * */ function db2_special_columns($connection, ?string $qualifier, string $schema, string $table_name, int $scope) {} function db2_specialcolumns() {} /** * Returns a result set listing the index and statistics for a table * @link https://php.net/manual/en/function.db2-statistics.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string|null $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string|null $schema

    * The schema that contains the targeted table. If this parameter is * null, the statistics and indexes are returned for the schema of the * current user. *

    * @param string $table_name

    * The name of the table. *

    * @param bool $unique

    * Whether to return the only the unique indexes or all the indexes in the table. *

    *

    * Return only the information for unique indexes on the table. *

    * @return resource|false A statement resource with a result set containing rows describing * the statistics and indexes for the base tables matching the specified * parameters. The rows are composed of the following columns: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    Column nameDescription
    TABLE_CATThe catalog that contains the table. The value is null if * this table does not have catalogs.
    TABLE_SCHEMName of the schema that contains the table.
    TABLE_NAMEName of the table.
    NON_UNIQUE * *

    * An boolean value representing whether the index prohibits unique * values, or whether the row represents statistics on the table itself:

    * * * * * * * * * * * * * * * * *
    Return valueParameter type
    false (SQL_FALSE)The index allows duplicate values.
    true (SQL_TRUE)The index values must be unique.
    nullThis row is statistics information for the table itself.
    *
    INDEX_QUALIFIERA string value representing the qualifier that would have to be * prepended to INDEX_NAME to fully qualify the index.
    INDEX_NAMEA string representing the name of the index.
    TYPE *

    * An integer value representing the type of information contained in * this row of the result set:

    * * * * * * * * * * * * * * * * * * * * * *
    Return valueParameter type
    0 (SQL_TABLE_STAT)The row contains statistics about the table itself.
    1 (SQL_INDEX_CLUSTERED)The row contains information about a clustered index.
    2 (SQL_INDEX_HASH)The row contains information about a hashed index.
    3 (SQL_INDEX_OTHER)The row contains information about a type of index that * is neither clustered nor hashed.
    *
    ORDINAL_POSITIONThe 1-indexed position of the column in the index. null if * the row contains statistics information about the table itself.
    COLUMN_NAMEThe name of the column in the index. null if the row * contains statistics information about the table itself.
    ASC_OR_DESC * A if the column is sorted in ascending order, * D if the column is sorted in descending order, * null if the row contains statistics information about the table * itself. *
    CARDINALITY *

    * If the row contains information about an index, this column contains * an integer value representing the number of unique values in the * index. *

    *

    * If the row contains information about the table itself, this column * contains an integer value representing the number of rows in the * table. *

    *
    PAGES *

    * If the row contains information about an index, this column contains * an integer value representing the number of pages used to store the * index. *

    *

    * If the row contains information about the table itself, this column * contains an integer value representing the number of pages used to * store the table. *

    *
    FILTER_CONDITIONAlways returns null.
    */ function db2_statistics($connection, ?string $qualifier, ?string $schema, string $table_name, bool $unique) {} /** * Returns a result set listing the tables and associated privileges in a database * @link https://php.net/manual/en/function.db2-table-privileges.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string|null $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string|null $schema

    * The schema which contains the tables. This parameter accepts a * search pattern containing _ and % * as wildcards. *

    * @param string|null $table_name

    * The name of the table. This parameter accepts a search pattern * containing _ and % as wildcards. *

    * @return resource|false A statement resource with a result set containing rows describing * the privileges for the tables that match the specified parameters. The rows * are composed of the following columns: * * Column name * Description * * * TABLE_CAT * The catalog that contains the table. The value is null if * this table does not have catalogs. * * * TABLE_SCHEM * Name of the schema that contains the table. * * * TABLE_NAME * Name of the table. * * * GRANTOR * Authorization ID of the user who granted the privilege. * * * GRANTEE * Authorization ID of the user to whom the privilege was * granted. * * * PRIVILEGE * * The privilege that has been granted. This can be one of ALTER, * CONTROL, DELETE, INDEX, INSERT, REFERENCES, SELECT, or UPDATE. * * * * IS_GRANTABLE * * A string value of "YES" or "NO" indicating whether the grantee * can grant the privilege to other users. * * */ function db2_table_privileges($connection, ?string $qualifier = null, ?string $schema = null, ?string $table_name = null) {} function db2_tableprivileges() {} /** * Returns a result set listing the tables and associated metadata in a database * @link https://php.net/manual/en/function.db2-tables.php * @param resource $connection

    * A valid connection to an IBM DB2, Cloudscape, or Apache Derby database. *

    * @param string|null $qualifier

    * A qualifier for DB2 databases running on OS/390 or z/OS servers. For * other databases, pass null or an empty string. *

    * @param string|null $schema

    * The schema which contains the tables. This parameter accepts a * search pattern containing _ and % * as wildcards. *

    * @param string|null $table_name * @param string|null $table_type * @return resource|false A statement resource with a result set containing rows describing * the tables that match the specified parameters. The rows are composed of * the following columns: * * Column name * Description * * * TABLE_CAT * The catalog that contains the table. The value is null if * this table does not have catalogs. * * * TABLE_SCHEM * Name of the schema that contains the table. * * * TABLE_NAME * Name of the table. * * * TABLE_TYPE * Table type identifier for the table. * * * REMARKS * Description of the table. * */ function db2_tables($connection, ?string $qualifier = null, ?string $schema = null, ?string $table_name = null, ?string $table_type = null) {} /** * Executes an SQL statement directly * @link https://php.net/manual/en/function.db2-exec.php * @param resource $connection

    * A valid database connection resource variable as returned from * db2_connect or db2_pconnect. *

    * @param string $statement

    * An SQL statement. The statement cannot contain any parameter markers. *

    * @param array $options

    * An associative array containing statement options. You can use this * parameter to request a scrollable cursor on database servers that * support this functionality. * cursor *

    *

    * Passing the DB2_FORWARD_ONLY value requests a * forward-only cursor for this SQL statement. This is the default * type of cursor, and it is supported by all database servers. It is * also much faster than a scrollable cursor. *

    *

    * Passing the DB2_SCROLLABLE value requests a * scrollable cursor for this SQL statement. This type of cursor * enables you to fetch rows non-sequentially from the database * server. However, it is only supported by DB2 servers, and is much * slower than forward-only cursors. *

    * @return resource|false A statement resource if the SQL statement was issued successfully, * or false if the database failed to execute the SQL statement. */ function db2_exec($connection, string $statement, array $options = []) {} /** * Prepares an SQL statement to be executed * @link https://php.net/manual/en/function.db2-prepare.php * @param resource $connection

    * A valid database connection resource variable as returned from * db2_connect or db2_pconnect. *

    * @param string $statement

    * An SQL statement, optionally containing one or more parameter markers.. *

    * @param array $options

    * An associative array containing statement options. You can use this * parameter to request a scrollable cursor on database servers that * support this functionality. * cursor *

    *

    * Passing the DB2_FORWARD_ONLY value requests a * forward-only cursor for this SQL statement. This is the default * type of cursor, and it is supported by all database servers. It is * also much faster than a scrollable cursor. *

    *

    * Passing the DB2_SCROLLABLE value requests a * scrollable cursor for this SQL statement. This type of cursor * enables you to fetch rows non-sequentially from the database * server. However, it is only supported by DB2 servers, and is much * slower than forward-only cursors. *

    * @return resource|false A statement resource if the SQL statement was successfully parsed and * prepared by the database server. Returns false if the database server * returned an error. You can determine which error was returned by calling * db2_stmt_error or db2_stmt_errormsg. */ function db2_prepare($connection, string $statement, array $options = []) {} /** * Executes a prepared SQL statement * @link https://php.net/manual/en/function.db2-execute.php * @param resource $stmt

    * A prepared statement returned from db2_prepare. *

    * @param array $parameters

    * An array of input parameters matching any parameter markers contained * in the prepared statement. *

    * @return bool true on success or false on failure. */ function db2_execute($stmt, array $parameters = []): bool {} /** * Returns a string containing the last SQL statement error message * @link https://php.net/manual/en/function.db2-stmt-errormsg.php * @param resource|null $stmt

    * A valid statement resource or NULL. *

    * @return string a string containing the error message and SQLCODE value for the * last error that occurred issuing an SQL statement. */ function db2_stmt_errormsg($stmt = null) {} /** * Returns the last connection error message and SQLCODE value * @link https://php.net/manual/en/function.db2-conn-errormsg.php * @param resource|null $connection

    * A connection resource associated with a connection that initially * succeeded, but which over time became invalid. *

    * @return string a string containing the error message and SQLCODE value resulting * from a failed connection attempt. If there is no error associated with the last * connection attempt, db2_conn_errormsg returns an empty * string. */ function db2_conn_errormsg($connection = null) {} /** * Returns a string containing the SQLSTATE returned by the last connection attempt * @link https://php.net/manual/en/function.db2-conn-error.php * @param resource|null $connection

    * A connection resource associated with a connection that initially * succeeded, but which over time became invalid. *

    * @return string the SQLSTATE value resulting from a failed connection attempt. * Returns an empty string if there is no error associated with the last * connection attempt. */ function db2_conn_error($connection = null) {} /** * Returns a string containing the SQLSTATE returned by an SQL statement * @link https://php.net/manual/en/function.db2-stmt-error.php * @param resource|null $stmt

    * A valid statement resource or NULL. *

    * @return string a string containing an SQLSTATE value. */ function db2_stmt_error($stmt = null) {} /** * Requests the next result set from a stored procedure * @link https://php.net/manual/en/function.db2-next-result.php * @param resource $stmt

    * A prepared statement returned from db2_exec or * db2_execute. *

    * @return resource|false A new statement resource containing the next result set if the * stored procedure returned another result set. Returns false if the stored * procedure did not return another result set. */ function db2_next_result($stmt) {} /** * Returns the number of fields contained in a result set * @link https://php.net/manual/en/function.db2-num-fields.php * @param resource $stmt

    * A valid statement resource containing a result set. *

    * @return int|false An integer value representing the number of fields in the result * set associated with the specified statement resource. Returns false if * the statement resource is not a valid input value. */ function db2_num_fields($stmt): int|false {} /** * Returns the number of rows affected by an SQL statement * @link https://php.net/manual/en/function.db2-num-rows.php * @param resource $stmt

    * A valid stmt resource containing a result set. *

    * @return int|false the number of rows affected by the last SQL statement issued by * the specified statement handle, or false in case of failure. */ function db2_num_rows($stmt): int|false {} /** * Returns the name of the column in the result set * @link https://php.net/manual/en/function.db2-field-name.php * @param resource $stmt

    * Specifies a statement resource containing a result set. *

    * @param int|string $column

    * Specifies the column in the result set. This can either be an integer * representing the 0-indexed position of the column, or a string * containing the name of the column. *

    * @return string|false A string containing the name of the specified column. If the * specified column does not exist in the result * set, db2_field_name returns false. */ function db2_field_name($stmt, int|string $column): string|false {} /** * Returns the maximum number of bytes required to display a column * @link https://php.net/manual/en/function.db2-field-display-size.php * @param resource $stmt

    * Specifies a statement resource containing a result set. *

    * @param int|string $column

    * Specifies the column in the result set. This can either be an integer * representing the 0-indexed position of the column, or a string * containing the name of the column. *

    * @return int|false An integer value with the maximum number of bytes required to * display the specified column. If the column does not exist in the result * set, db2_field_display_size returns false. */ function db2_field_display_size($stmt, int|string $column): int|false {} /** * Returns the position of the named column in a result set * @link https://php.net/manual/en/function.db2-field-num.php * @param resource $stmt

    * Specifies a statement resource containing a result set. *

    * @param int|string $column

    * Specifies the column in the result set. This can either be an integer * representing the 0-indexed position of the column, or a string * containing the name of the column. *

    * @return int|false An integer containing the 0-indexed position of the named column in * the result set. If the specified column does not exist in the result set, * db2_field_num returns false. */ function db2_field_num($stmt, int|string $column): int|false {} /** * Returns the precision of the indicated column in a result set * @link https://php.net/manual/en/function.db2-field-precision.php * @param resource $stmt

    * Specifies a statement resource containing a result set. *

    * @param int|string $column

    * Specifies the column in the result set. This can either be an integer * representing the 0-indexed position of the column, or a string * containing the name of the column. *

    * @return int|false An integer containing the precision of the specified column. If the * specified column does not exist in the result set, * db2_field_precision returns false. */ function db2_field_precision($stmt, int|string $column): int|false {} /** * Returns the scale of the indicated column in a result set * @link https://php.net/manual/en/function.db2-field-scale.php * @param resource $stmt

    * Specifies a statement resource containing a result set. *

    * @param int|string $column

    * Specifies the column in the result set. This can either be an integer * representing the 0-indexed position of the column, or a string * containing the name of the column. *

    * @return int|false An integer containing the scale of the specified column. If the * specified column does not exist in the result set, * db2_field_scale returns false. */ function db2_field_scale($stmt, int|string $column): int|false {} /** * Returns the data type of the indicated column in a result set * @link https://php.net/manual/en/function.db2-field-type.php * @param resource $stmt

    * Specifies a statement resource containing a result set. *

    * @param int|string $column

    * Specifies the column in the result set. This can either be an integer * representing the 0-indexed position of the column, or a string * containing the name of the column. *

    * @return string|false A string containing the defined data type of the specified column. * If the specified column does not exist in the result set, * db2_field_type returns false. */ function db2_field_type($stmt, int|string $column): string|false {} /** * Returns the width of the current value of the indicated column in a result set * @link https://php.net/manual/en/function.db2-field-width.php * @param resource $stmt

    * Specifies a statement resource containing a result set. *

    * @param int|string $column

    * Specifies the column in the result set. This can either be an integer * representing the 0-indexed position of the column, or a string * containing the name of the column. *

    * @return int|false An integer containing the width of the specified character or * binary data type column in a result set. If the specified column does not * exist in the result set, db2_field_width returns * false. */ function db2_field_width($stmt, int|string $column): int|false {} /** * Returns the cursor type used by a statement resource * @link https://php.net/manual/en/function.db2-cursor-type.php * @param resource $stmt

    * A valid statement resource. *

    * @return int either DB2_FORWARD_ONLY if the statement * resource uses a forward-only cursor or DB2_SCROLLABLE if * the statement resource uses a scrollable cursor. */ function db2_cursor_type($stmt): int {} /** * Rolls back a transaction * @link https://php.net/manual/en/function.db2-rollback.php * @param resource $connection

    * A valid database connection resource variable as returned from * db2_connect or db2_pconnect. *

    * @return bool true on success or false on failure. */ function db2_rollback($connection): bool {} /** * Frees resources associated with the indicated statement resource * @link https://php.net/manual/en/function.db2-free-stmt.php * @param resource $stmt

    * A valid statement resource. *

    * @return bool true on success or false on failure. */ function db2_free_stmt($stmt): bool {} /** * Returns a single column from a row in the result set * @link https://php.net/manual/en/function.db2-result.php * @param resource $stmt

    * A valid stmt resource. *

    * @param int|string $column

    * Either an integer mapping to the 0-indexed field in the result set, or * a string matching the name of the column. *

    * @return mixed the value of the requested field if the field exists in the result * set. Returns NULL if the field does not exist, and issues a warning. */ function db2_result($stmt, int|string $column): mixed {} /** * Sets the result set pointer to the next row or requested row * @link https://php.net/manual/en/function.db2-fetch-row.php * @param resource $stmt

    * A valid stmt resource. *

    * @param int $row_number

    * With scrollable cursors, you can request a specific row number in the * result set. Row numbering is 1-indexed. *

    * @return bool true if the requested row exists in the result set. Returns * false if the requested row does not exist in the result set. */ function db2_fetch_row($stmt, int $row_number = null) {} /** * Returns an array, indexed by column name, representing a row in a result set * @link https://php.net/manual/en/function.db2-fetch-assoc.php * @param resource $stmt

    * A valid stmt resource containing a result set. *

    * @param int $row_number

    * Requests a specific 1-indexed row from the result set. Passing this * parameter results in a PHP warning if the result set uses a * forward-only cursor. *

    * @return array|false An associative array with column values indexed by the column name * representing the next or requested row in the result set. Returns false if * there are no rows left in the result set, or if the row requested by * row_number does not exist in the result set. */ function db2_fetch_assoc($stmt, int $row_number = null): array|false {} /** * Returns an array, indexed by column position, representing a row in a result set * @link https://php.net/manual/en/function.db2-fetch-array.php * @param resource $stmt

    * A valid stmt resource containing a result set. *

    * @param int $row_number

    * Requests a specific 1-indexed row from the result set. Passing this * parameter results in a PHP warning if the result set uses a * forward-only cursor. *

    * @return array|false A 0-indexed array with column values indexed by the column position * representing the next or requested row in the result set. Returns false if * there are no rows left in the result set, or if the row requested by * row_number does not exist in the result set. */ function db2_fetch_array($stmt, int $row_number = null): array|false {} /** * Returns an array, indexed by both column name and position, representing a row in a result set * @link https://php.net/manual/en/function.db2-fetch-both.php * @param resource $stmt

    * A valid stmt resource containing a result set. *

    * @param int $row_number

    * Requests a specific 1-indexed row from the result set. Passing this * parameter results in a PHP warning if the result set uses a * forward-only cursor. *

    * @return array|false An associative array with column values indexed by both the column * name and 0-indexed column number. The array represents the next or * requested row in the result set. Returns false if there are no rows left * in the result set, or if the row requested by * row_number does not exist in the result set. */ function db2_fetch_both($stmt, int $row_number = null): array|false {} /** * Frees resources associated with a result set * @link https://php.net/manual/en/function.db2-free-result.php * @param resource $stmt

    * A valid statement resource. *

    * @return bool true on success or false on failure. */ function db2_free_result($stmt): bool {} /** * Set options for connection or statement resources * @link https://php.net/manual/en/function.db2-set-option.php * @param resource $resource

    * A valid statement resource as returned from * db2_prepare or a valid connection resource as * returned from db2_connect or * db2_pconnect. *

    * @param array $options

    * An associative array containing valid statement or connection * options. This parameter can be used to change autocommit values, * cursor types (scrollable or forward), and to specify the case of * the column names (lower, upper, or natural) that will appear in a * result set. * autocommit *

    * Passing DB2_AUTOCOMMIT_ON turns * autocommit on for the specified connection resource. *

    *

    * Passing DB2_AUTOCOMMIT_OFF turns * autocommit off for the specified connection resource. *

    * @param int $type

    * An integer value that specifies the type of resource that was * passed into the function. The type of resource and this value * must correspond. *

    * Passing 1 as the value specifies that * a connection resource has been passed into the function. *

    *

    * Passing any integer not equal to 1 as * the value specifies that a statement resource has been * passed into the function. *

    * @return bool true on success or false on failure. */ function db2_set_option($resource, array $options, int $type): bool {} function db2_setoption(): bool {} /** * Returns an object with properties representing columns in the fetched row * @link https://php.net/manual/en/function.db2-fetch-object.php * @param resource $stmt

    * A valid stmt resource containing a result set. *

    * @param int $row_number

    * Requests a specific 1-indexed row from the result set. Passing this * parameter results in a PHP warning if the result set uses a * forward-only cursor. *

    * @return stdClass|false An object representing a single row in the result set. The * properties of the object map to the names of the columns in the result set. *

    *

    * The IBM DB2, Cloudscape, and Apache Derby database servers typically fold * column names to upper-case, so the object properties will reflect that case. *

    *

    * If your SELECT statement calls a scalar function to modify the value * of a column, the database servers return the column number as the name of * the column in the result set. If you prefer a more descriptive column name * and object property, you can use the AS clause to assign a name to the * column in the result set. *

    *

    * Returns false if no row was retrieved. */ function db2_fetch_object($stmt, int $row_number = null): stdClass|false {} /** * Returns an object with properties that describe the DB2 database server * @link https://php.net/manual/en/function.db2-server-info.php * @param resource $connection

    * Specifies an active DB2 client connection. *

    * @return stdClass|false An object on a successful call. Returns false on failure. */ function db2_server_info($connection): stdClass|false {} /** * Returns an object with properties that describe the DB2 database client * @link https://php.net/manual/en/function.db2-client-info.php * @param resource $connection

    * Specifies an active DB2 client connection. *

    * @return stdClass|false An object on a successful call. Returns false on failure. */ function db2_client_info($connection): stdClass|false {} /** * Used to escape certain characters * @link https://php.net/manual/en/function.db2-escape-string.php * @param string $string_literal

    * The string that contains special characters that need to be modified. * Characters that are prepended with a backslash are \x00, * \n, \r, \, * ', " and \x1a. *

    * @return string string_literal with the special characters * noted above prepended with backslashes. */ function db2_escape_string(string $string_literal): string {} /** * Gets a user defined size of LOB files with each invocation * @link https://php.net/manual/en/function.db2-lob-read.php * @param resource $stmt

    * A valid stmt resource containing LOB data. *

    * @param int $colnum

    * A valid column number in the result set of the stmt resource. *

    * @param int $length

    * The size of the LOB data to be retrieved from the stmt resource. *

    * @return string|false The amount of data the user specifies. Returns * false if the data cannot be retrieved. */ function db2_lob_read($stmt, int $colnum, int $length): string|false {} /** * Retrieves an option value for a statement resource or a connection resource * @link https://php.net/manual/en/function.db2-get-option.php * @param resource $resource

    * A valid statement resource as returned from * db2_prepare or a valid connection resource as * returned from db2_connect or * db2_pconnect. *

    * @param string $option

    * A valid statement or connection options. The following new options are available * as of ibm_db2 version 1.6.0. They provide useful tracking information * that can be set during execution with db2_get_option. *

    *

    * Note: Prior versions of ibm_db2 do not support these new options. *

    *

    * When the value in each option is being set, some servers might not handle * the entire length provided and might truncate the value. *

    *

    * To ensure that the data specified in each option is converted correctly * when transmitted to a host system, use only the characters A through Z, * 0 through 9, and the underscore (_) or period (.). *

    *

    * SQL_ATTR_INFO_USERID - A pointer to a null-terminated * character string used to identify the client user ID sent to the host * database server when using DB2 Connect. *

    *

    * Note: DB2 for z/OS and OS/390 servers support up to a length of 16 characters. * This user-id is not to be confused with the authentication user-id, it is for * identification purposes only and is not used for any authorization. *

    * @return string|false The current setting of the connection attribute provided on success * or false on failure. */ function db2_get_option($resource, string $option): string|false {} /** * Returns the auto generated ID of the last insert query that successfully executed on this connection. * @link https://php.net/manual/en/function.db2-last-insert-id.php * The result of this function is not affected by any of the following: *
    • A single row INSERT statement with a VALUES clause for a table without an identity column. *
    • A multiple row INSERT statement with a VALUES clause. *
    • An INSERT statement with a fullselect. *
    • A ROLLBACK TO SAVEPOINT statement. *
    * @param resource $resource A valid connection resource as returned from db2_connect() or db2_pconnect(). * The value of this parameter cannot be a statement resource or result set resource. * @return string|null Returns the auto generated ID of last insert query that successfully executed on this connection * or NULL if no ID was found. */ function db2_last_insert_id($resource): ?string {} /** * Specifies that binary data shall be returned as is. This is the default * mode. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_BINARY', 1); /** * Specifies that binary data shall be converted to a hexadecimal encoding * and returned as an ASCII string. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_CONVERT', 2); /** * Specifies that binary data shall be converted to a null value. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_PASSTHRU', 3); /** * Specifies a scrollable cursor for a statement resource. This mode enables * random access to rows in a result set, but currently is supported only by * IBM DB2 Universal Database. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_SCROLLABLE', 1); /** * Specifies a forward-only cursor for a statement resource. This is the * default cursor type and is supported on all database servers. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_FORWARD_ONLY', 0); /** * Specifies the PHP variable should be bound as an IN parameter for a * stored procedure. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_PARAM_IN', 1); /** * Specifies the PHP variable should be bound as an OUT parameter for a * stored procedure. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_PARAM_OUT', 4); /** * Specifies the PHP variable should be bound as an INOUT parameter for a * stored procedure. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_PARAM_INOUT', 2); /** * Specifies that the column should be bound directly to a file for input. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_PARAM_FILE', 11); /** * Specifies that autocommit should be turned on. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_AUTOCOMMIT_ON', 1); /** * Specifies that autocommit should be turned off. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_AUTOCOMMIT_OFF', 0); /** * Specifies that deferred prepare should be turned on for the specified statement resource. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_DEFERRED_PREPARE_ON', 1); /** * Specifies that deferred prepare should be turned off for the specified statement resource. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_DEFERRED_PREPARE_OFF', 0); /** * Specifies that the variable should be bound as a DOUBLE, FLOAT, or REAL * data type. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_DOUBLE', 8); /** * Specifies that the variable should be bound as a SMALLINT, INTEGER, or * BIGINT data type. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_LONG', 4); /** * Specifies that the variable should be bound as a CHAR or VARCHAR data type. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_CHAR', 1); define('DB2_XML', -370); /** * Specifies that column names will be returned in their natural case. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_CASE_NATURAL', 0); /** * Specifies that column names will be returned in lower case. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_CASE_LOWER', 1); /** * Specifies that column names will be returned in upper case. * @link https://php.net/manual/en/ibm-db2.constants.php */ define('DB2_CASE_UPPER', 2); // End of ibm_db2 v.1.6.0 * The following error codes are used:
      *
    • -1 - error outside UnRAR library
    • *
    • 11 - insufficient memory
    • *
    • 12 - bad data
    • *
    • 13 - bad archive
    • *
    • 14 - unknown format
    • *
    • 15 - file open error
    • *
    • 16 - file create error
    • *
    • 17 - file close error
    • *
    • 18 - read error
    • *
    • 19 - write error
    • *
    • 20 - buffer too small
    • *
    • 21 - unkown RAR error
    • *
    • 22 - password required but not given
    • *
    * * @link https://php.net/manual/en/class.rarexception.php */ final class RarException extends Exception { /** * Check whether error handling with exceptions is in use * * @link https://php.net/manual/en/rarexception.isusingexceptions.php * * @return bool TRUE if exceptions are being used, FALSE otherwise */ public static function isUsingExceptions() {} /** * Activate and deactivate error handling with exceptions * * @link https://php.net/manual/en/rarexception.setusingexceptions.php * * @param bool $using_exceptions Should be TRUE to activate exception throwing, FALSE to deactivate (the default) */ public static function setUsingExceptions($using_exceptions) {} } *
  • %parametersList%: parameters of the function call. For example, for the "f(1,2)" call, %parametersList% will be "1,2"
  • *
  • %parameter0%,%parameter1%,%parameter2%,...: parameters of the function call. For example, for the "f(1,2)" call, %parameter1% will be "2"
  • *
  • %name%: For "\x\f(1,2)", %name% will be "\x\f", for "$this->ff()", %name% will be "ff"
  • *
  • %class%: If the attribute is provided for method "m", then for "$this->f()->m()", %class% will be "$this->f()"
  • * * The following example shows how to wrap a function call in another call and swap arguments:
    * "#[Deprecated(replacement: "wrappedCall(%name%(%parameter1%, %parameter0%))")] f($a, $b){}
    * f(1,2) will be replaced with wrappedCall(f(2,1)) * @param string $since Element is deprecated starting with the provided PHP language level, applicable only for PhpStorm stubs entries */ public function __construct( $reason = "", $replacement = "", #[ExpectedValues(self::PHP_VERSIONS)] $since = "5.6" ) {} } *
  • Code completion - expected arguments are displayed on the top of the suggestions list when used in comparison expressions
  • *
  • Inspections [when used in a comparison with a value/assignment to/return from method] - the element absent from the expected values list produces the inspection warning
  • *
  • Code generation - for example, when generating the 'switch' statement, all possible expected values are inserted automatically
  • * * * Expected values can be any of the following: *
      *
    • numbers
    • *
    • string literals
    • *
    • constant references
    • *
    • class constant references
    • *
    * * Expected arguments can be specified in any of the following ways: *
      *
    • #[ExpectedValues(values: [1,2,3])] means that one of the following is expected: `1`, `2`, or `3`
    • *
    • #[ExpectedValues(values: MY_CONST] - default value of MY_CONST is expected to be array creation expression, in this case value of MY_CONST will be inlined
    • *
    • #[ExpectedValues(flags: [1,2,3])] means that a bitmask of the following is expected: `1`, `2`, or `3`
    • *
    • #[ExpectedValues(valuesFromClass: MyClass::class)] means that one of the constants from the class `MyClass` is expected
    • *
    • #[ExpectedValues(flagsFromClass: ExpectedValues::class)] means that a bitmask of the constants from the class `MyClass` is expected
    • *
    * * The attribute with the number of provided constructor arguments different from 1 will result in undefined behavior. * @since 8.0 */ #[Attribute(Attribute::TARGET_FUNCTION|Attribute::TARGET_METHOD|Attribute::TARGET_PARAMETER|Attribute::TARGET_PROPERTY)] class ExpectedValues { public function __construct(array $values = [], array $flags = [], string $valuesFromClass = null, string $flagsFromClass = null) {} } *
  • {@link Immutable::CONSTRUCTOR_WRITE_SCOPE}: write is allowed only in containing class constructor (default choice)
  • *
  • {@link Immutable::PRIVATE_WRITE_SCOPE}: write is allowed only in places where the property would be accessible if it had 'private' visibility modifier
  • *
  • {@link Immutable::PROTECTED_WRITE_SCOPE}: write is allowed only in places where the property would be accessible if it had 'protected' visibility modifier
  • * * @since 8.0 */ #[Attribute(Attribute::TARGET_PROPERTY|Attribute::TARGET_CLASS)] class Immutable { public const CONSTRUCTOR_WRITE_SCOPE = "constructor"; public const PRIVATE_WRITE_SCOPE = "private"; public const PROTECTED_WRITE_SCOPE = "protected"; public function __construct(#[ExpectedValues(valuesFromClass: Immutable::class)] $allowedWriteScope = self::CONSTRUCTOR_WRITE_SCOPE) {} } * * Example:
    * #[ArrayShape(["f" => "int", "string", "x" => "float"])] * This usage applied on an element effectively means that the array has 3 elements, the keys are "f", 1, and "x", and the corresponding types are "int", "string", and "float". */ #[Attribute(Attribute::TARGET_FUNCTION|Attribute::TARGET_METHOD|Attribute::TARGET_PARAMETER|Attribute::TARGET_PROPERTY)] class ArrayShape { public function __construct(array $shape) {} } #[ObjectShape(["age" => "int", "name" => "string"])]
    * * This usage applied on an element effectively means that the object has 2 fields, the names are "age" and "name", and the corresponding types are "int" and "string". */ #[Attribute(Attribute::TARGET_FUNCTION|Attribute::TARGET_METHOD|Attribute::TARGET_PARAMETER|Attribute::TARGET_PROPERTY)] class ObjectShape { public function __construct(array $shape) {} } json_encode. * @link https://php.net/manual/en/class.jsonserializable.php * @since 5.4 */ interface JsonSerializable { /** * Specify data which should be serialized to JSON * @link https://php.net/manual/en/jsonserializable.jsonserialize.php * @return mixed data which can be serialized by json_encode, * which is a value of any type other than a resource. * @since 5.4 */ #[TentativeType] public function jsonSerialize(): mixed; } class JsonIncrementalParser { public const JSON_PARSER_SUCCESS = 0; public const JSON_PARSER_CONTINUE = 1; /** * @param int $depth [optional] * @param int $options [optional] */ #[Pure] public function __construct($depth, $options) {} #[Pure] public function getError() {} public function reset() {} /** * @param string $json */ public function parse($json) {} /** * @param string $filename */ public function parseFile($filename) {} /** * @param int $options [optional] */ #[Pure] public function get($options) {} } /** * (PHP 5 >= 5.2.0, PECL json >= 1.2.0)
    * Returns the JSON representation of a value * @link https://php.net/manual/en/function.json-encode.php * @param mixed $value

    * The value being encoded. Can be any type except * a resource. *

    *

    * All string data must be UTF-8 encoded. *

    *

    PHP implements a superset of * JSON - it will also encode and decode scalar types and NULL. The JSON standard * only supports these values when they are nested inside an array or an object. *

    * @param int $flags [optional]

    * Bitmask consisting of JSON_HEX_QUOT, * JSON_HEX_TAG, * JSON_HEX_AMP, * JSON_HEX_APOS, * JSON_NUMERIC_CHECK, * JSON_PRETTY_PRINT, * JSON_UNESCAPED_SLASHES, * JSON_FORCE_OBJECT, * JSON_UNESCAPED_UNICODE. * JSON_THROW_ON_ERROR The behaviour of these * constants is described on * the JSON constants page. *

    * @param int $depth [optional]

    * Set the maximum depth. Must be greater than zero. *

    * @return string|false a JSON encoded string on success or FALSE on failure. */ function json_encode(mixed $value, int $flags = 0, int $depth = 512): string|false {} /** * (PHP 5 >= 5.2.0, PECL json >= 1.2.0)
    * Decodes a JSON string * @link https://php.net/manual/en/function.json-decode.php * @param string $json

    * The json string being decoded. *

    *

    * This function only works with UTF-8 encoded strings. *

    *

    PHP implements a superset of * JSON - it will also encode and decode scalar types and NULL. The JSON standard * only supports these values when they are nested inside an array or an object. *

    * @param bool|null $associative

    * When TRUE, returned objects will be converted into * associative arrays. *

    * @param int $depth [optional]

    * User specified recursion depth. *

    * @param int $flags [optional]

    * Bitmask of JSON decode options:
    * {@see JSON_BIGINT_AS_STRING} decodes large integers as their original string value.
    * {@see JSON_INVALID_UTF8_IGNORE} ignores invalid UTF-8 characters,
    * {@see JSON_INVALID_UTF8_SUBSTITUTE} converts invalid UTF-8 characters to \0xfffd,
    * {@see JSON_OBJECT_AS_ARRAY} decodes JSON objects as PHP array, since 7.2.0 used by default if $assoc parameter is true,
    * {@see JSON_THROW_ON_ERROR} when passed this flag, the error behaviour of these functions is changed. The global error state is left untouched, and if an error occurs that would otherwise set it, these functions instead throw a JsonException
    *

    * @return mixed the value encoded in json in appropriate * PHP type. Values true, false and * null (case-insensitive) are returned as TRUE, FALSE * and NULL respectively. NULL is returned if the * json cannot be decoded or if the encoded * data is deeper than the recursion limit. */ function json_decode(string $json, ?bool $associative = null, int $depth = 512, int $flags = 0): mixed {} /** * Returns the last error occurred * @link https://php.net/manual/en/function.json-last-error.php * @return int an integer, the value can be one of the following * constants: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    ConstantMeaningAvailability
    JSON_ERROR_NONENo error has occurred 
    JSON_ERROR_DEPTHThe maximum stack depth has been exceeded 
    JSON_ERROR_STATE_MISMATCHInvalid or malformed JSON 
    JSON_ERROR_CTRL_CHARControl character error, possibly incorrectly encoded 
    JSON_ERROR_SYNTAXSyntax error 
    JSON_ERROR_UTF8Malformed UTF-8 characters, possibly incorrectly encodedPHP 5.3.3
    JSON_ERROR_RECURSIONOne or more recursive references in the value to be encodedPHP 5.5.0
    JSON_ERROR_INF_OR_NAN * One or more * NAN * or INF * values in the value to be encoded * PHP 5.5.0
    JSON_ERROR_UNSUPPORTED_TYPEA value of a type that cannot be encoded was givenPHP 5.5.0
    JSON_ERROR_INVALID_PROPERTY_NAMEA property name that cannot be encoded was givenPHP 7.0.0
    JSON_ERROR_UTF16Malformed UTF-16 characters, possibly incorrectly encodedPHP 7.0.0
    */ #[Pure(true)] function json_last_error(): int {} /** * Returns the error string of the last json_encode() or json_decode() call, which did not specify JSON_THROW_ON_ERROR. * @link https://php.net/manual/en/function.json-last-error-msg.php * @return string Returns the error message on success, "No error" if no error has occurred. * @since 5.5 */ #[Pure] function json_last_error_msg(): string {} /** * @since 8.3 */ function json_validate(string $json, int $depth = 512, int $flags = 0): bool {} /** * All < and > are converted to \u003C and \u003E. * @link https://php.net/manual/en/json.constants.php */ define('JSON_HEX_TAG', 1); /** * All &s are converted to \u0026. * @link https://php.net/manual/en/json.constants.php */ define('JSON_HEX_AMP', 2); /** * All ' are converted to \u0027. * @link https://php.net/manual/en/json.constants.php */ define('JSON_HEX_APOS', 4); /** * All " are converted to \u0022. * @link https://php.net/manual/en/json.constants.php */ define('JSON_HEX_QUOT', 8); /** * Outputs an object rather than an array when a non-associative array is * used. Especially useful when the recipient of the output is expecting * an object and the array is empty. * @link https://php.net/manual/en/json.constants.php */ define('JSON_FORCE_OBJECT', 16); /** * Encodes numeric strings as numbers. * @since 5.3.3 * @link https://php.net/manual/en/json.constants.php */ define('JSON_NUMERIC_CHECK', 32); /** * Don't escape /. * @since 5.4 * @link https://php.net/manual/en/json.constants.php */ define('JSON_UNESCAPED_SLASHES', 64); /** * Use whitespace in returned data to format it. * @since 5.4 * @link https://php.net/manual/en/json.constants.php */ define('JSON_PRETTY_PRINT', 128); /** * Encode multibyte Unicode characters literally (default is to escape as \uXXXX). * @since 5.4 * @link https://php.net/manual/en/json.constants.php */ define('JSON_UNESCAPED_UNICODE', 256); define('JSON_PARTIAL_OUTPUT_ON_ERROR', 512); /** * Occurs with underflow or with the modes mismatch. * @link https://php.net/manual/en/json.constants.php */ define('JSON_ERROR_STATE_MISMATCH', 2); /** * Control character error, possibly incorrectly encoded. * @link https://php.net/manual/en/json.constants.php */ define('JSON_ERROR_CTRL_CHAR', 3); /** * Malformed UTF-8 characters, possibly incorrectly encoded. This * constant is available as of PHP 5.3.3. * @link https://php.net/manual/en/json.constants.php */ define('JSON_ERROR_UTF8', 5); /** *

    * The object or array passed to json_encode include * recursive references and cannot be encoded. * If the JSON_PARTIAL_OUTPUT_ON_ERROR option was * given, NULL will be encoded in the place of the recursive reference. *

    *

    * This constant is available as of PHP 5.5.0. *

    * @link https://php.net/manual/en/json.constants.php */ define('JSON_ERROR_RECURSION', 6); /** *

    * The value passed to json_encode includes either * NAN * or INF. * If the JSON_PARTIAL_OUTPUT_ON_ERROR option was * given, 0 will be encoded in the place of these * special numbers. *

    *

    * This constant is available as of PHP 5.5.0. *

    * @link https://php.net/manual/en/json.constants.php */ define('JSON_ERROR_INF_OR_NAN', 7); /** *

    * A value of an unsupported type was given to * json_encode, such as a resource. * If the JSON_PARTIAL_OUTPUT_ON_ERROR option was * given, NULL will be encoded in the place of the unsupported value. *

    *

    * This constant is available as of PHP 5.5.0. *

    * @link https://php.net/manual/en/json.constants.php */ define('JSON_ERROR_UNSUPPORTED_TYPE', 8); /** * No error has occurred. * @link https://php.net/manual/en/json.constants.php */ define('JSON_ERROR_NONE', 0); /** * The maximum stack depth has been exceeded. * @link https://php.net/manual/en/json.constants.php */ define('JSON_ERROR_DEPTH', 1); /** * Syntax error. * @link https://php.net/manual/en/json.constants.php */ define('JSON_ERROR_SYNTAX', 4); /** * Decodes JSON objects as PHP array. * @since 5.4 * @link https://php.net/manual/en/json.constants.php */ define('JSON_OBJECT_AS_ARRAY', 1); define('JSON_PARSER_NOTSTRICT', 4); /** * Decodes large integers as their original string value. * @since 5.4 * @link https://php.net/manual/en/json.constants.php */ define('JSON_BIGINT_AS_STRING', 2); /** * Ensures that float values are always encoded as a float value. * @since 5.6.6 * @link https://php.net/manual/en/json.constants.php */ define('JSON_PRESERVE_ZERO_FRACTION', 1024); /** * The line terminators are kept unescaped when JSON_UNESCAPED_UNICODE is supplied. * It uses the same behaviour as it was before PHP 7.1 without this constant. Available since PHP 7.1.0. * @link https://php.net/manual/en/json.constants.php * @since 7.1 */ define('JSON_UNESCAPED_LINE_TERMINATORS', 2048); /** * Ignore invalid UTF-8 characters. * @since 7.2 */ define('JSON_INVALID_UTF8_IGNORE', 1048576); /** * Convert invalid UTF-8 characters to \0xfffd (Unicode Character 'REPLACEMENT CHARACTER'). * @since 7.2 */ define('JSON_INVALID_UTF8_SUBSTITUTE', 2097152); /** * A key starting with \u0000 character was in the string passed to json_decode() when decoding a JSON object into a PHP object. * Available since PHP 7.0.0. * @link https://php.net/manual/en/json.constants.php * @since 7.0 */ define('JSON_ERROR_INVALID_PROPERTY_NAME', 9); /** * Single unpaired UTF-16 surrogate in unicode escape contained in the JSON string passed to json_encode(). * Available since PHP 7.0.0. * @link https://php.net/manual/en/json.constants.php * @since 7.0 */ define('JSON_ERROR_UTF16', 10); /** * Throws JsonException if an error occurs instead of setting the global error state * that is retrieved with json_last_error() and json_last_error_msg(). * * {@see JSON_PARTIAL_OUTPUT_ON_ERROR} takes precedence over JSON_THROW_ON_ERROR. * @since 7.3 */ define('JSON_THROW_ON_ERROR', 4194304); /** * @since 8.1 */ define('JSON_ERROR_NON_BACKED_ENUM', 11); /** * Class JsonException * *

    A new flag has been added, JSON_THROW_ON_ERROR, which can be used with * json_decode() or json_encode() and causes these functions to throw a * JsonException upon an error, instead of setting the global error state that * is retrieved with json_last_error(). JSON_PARTIAL_OUTPUT_ON_ERROR takes * precedence over JSON_THROW_ON_ERROR. *

    * * @since 7.3 * @link https://wiki.php.net/rfc/json_throw_on_error */ class JsonException extends Exception {} // End of json v.1.3.1 'int'], default: '')] $flags = 0, #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $magic_database ) {} /** * @param $options [optional] * @param $arg [optional] */ #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] public function finfo($options, $arg) {} /** * (PHP >= 5.3.0, PECL fileinfo >= 0.1.0)
    * Set libmagic configuration options * @link https://php.net/manual/en/function.finfo-set-flags.php * @param int $flags

    * One or disjunction of more Fileinfo * constants. *

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] #[TentativeType] public function set_flags(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags) {} /** * (PHP >= 5.3.0, PECL fileinfo >= 0.1.0)
    * Return information about a file * @link https://php.net/manual/en/function.finfo-file.php * @param string $filename

    * Name of a file to be checked. *

    * @param int $flags [optional]

    * One or disjunction of more Fileinfo * constants. *

    * @param resource $context [optional]

    * For a description of contexts, refer to . *

    * @return string a textual description of the contents of the * filename argument, or FALSE if an error occurred. */ #[Pure] #[TentativeType] public function file( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = FILEINFO_NONE, $context = null ): string|false {} /** * (PHP 5 >= 5.3.0, PECL fileinfo >= 0.1.0)
    * Return information about a string buffer * @link https://php.net/manual/en/function.finfo-buffer.php * @param string $string

    * Content of a file to be checked. *

    * @param int $flags [optional]

    * One or disjunction of more Fileinfo * constants. *

    * @param resource $context [optional] * @return string a textual description of the string * argument, or FALSE if an error occurred. */ #[Pure] #[TentativeType] public function buffer( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $string, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $flags = FILEINFO_NONE, $context = null ): string|false {} } /** * (PHP >= 5.3.0, PECL fileinfo >= 0.1.0)
    * Create a new fileinfo resource * @link https://php.net/manual/en/function.finfo-open.php * @param int $flags

    * One or disjunction of more Fileinfo * constants. *

    * @param string|null $magic_database [optional]

    * Name of a magic database file, usually something like * /path/to/magic.mime. If not specified, * the MAGIC environment variable is used. If this variable * is not set either, /usr/share/misc/magic is used by default. * A .mime and/or .mgc suffix is added if * needed. *

    * @return resource|false a magic database resource on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.1' => 'finfo|false'], default: 'resource|false')] function finfo_open(int $flags = 0, ?string $magic_database = null) {} /** * (PHP >= 5.3.0, PECL fileinfo >= 0.1.0)
    * Close fileinfo resource * @link https://php.net/manual/en/function.finfo-close.php * @param resource $finfo

    * Fileinfo resource returned by finfo_open. *

    * @return bool TRUE on success or FALSE on failure. */ function finfo_close(#[LanguageLevelTypeAware(['8.1' => 'finfo'], default: 'resource')] $finfo): bool {} /** * (PHP >= 5.3.0, PECL fileinfo >= 0.1.0)
    * Set libmagic configuration options * @link https://php.net/manual/en/function.finfo-set-flags.php * @param resource $finfo

    * Fileinfo resource returned by finfo_open. *

    * @param int $flags

    * One or disjunction of more Fileinfo * constants. *

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(['8.4' => 'true'], default: 'bool')] function finfo_set_flags(#[LanguageLevelTypeAware(['8.1' => 'finfo'], default: 'resource')] $finfo, int $flags) {} /** * (PHP >= 5.3.0, PECL fileinfo >= 0.1.0)
    * Return information about a file * @link https://php.net/manual/en/function.finfo-file.php * @param resource $finfo

    * Fileinfo resource returned by finfo_open. *

    * @param string $filename

    * Name of a file to be checked. *

    * @param int $flags

    * One or disjunction of more Fileinfo * constants. *

    * @param resource $context [optional]

    * For a description of contexts, refer to . *

    * @return string|false a textual description of the contents of the * filename argument, or FALSE if an error occurred. */ function finfo_file(#[LanguageLevelTypeAware(['8.1' => 'finfo'], default: 'resource')] $finfo, string $filename, int $flags = 0, $context): string|false {} /** * (PHP 5 >= 5.3.0, PECL fileinfo >= 0.1.0)
    * Return information about a string buffer * @link https://php.net/manual/en/function.finfo-buffer.php * @param resource $finfo

    * Fileinfo resource returned by finfo_open. *

    * @param string $string

    * Content of a file to be checked. *

    * @param int $flags [optional] One or disjunction of more * Fileinfo constants. * @param resource $context [optional] * @return string|false a textual description of the string * argument, or FALSE if an error occurred. */ function finfo_buffer(#[LanguageLevelTypeAware(['8.1' => 'finfo'], default: 'resource')] $finfo, string $string, int $flags = FILEINFO_NONE, $context): string|false {} /** * Detect MIME Content-type for a file * @link https://php.net/manual/en/function.mime-content-type.php * @param string $filename

    * Path to the tested file. *

    * @return string|false the content type in MIME format, like * text/plain or application/octet-stream. */ function mime_content_type($filename): string|false {} /** * No special handling. * @link https://php.net/manual/en/fileinfo.constants.php */ define('FILEINFO_NONE', 0); /** * Follow symlinks. * @link https://php.net/manual/en/fileinfo.constants.php */ define('FILEINFO_SYMLINK', 2); /** * Return the mime type and mime encoding as defined by RFC 2045. * @link https://php.net/manual/en/fileinfo.constants.php */ define('FILEINFO_MIME', 1040); /** * Return the mime type. * @link https://php.net/manual/en/fileinfo.constants.php */ define('FILEINFO_MIME_TYPE', 16); /** * Return the mime encoding of the file. * @link https://php.net/manual/en/fileinfo.constants.php */ define('FILEINFO_MIME_ENCODING', 1024); /** * Look at the contents of blocks or character special devices. * @link https://php.net/manual/en/fileinfo.constants.php */ define('FILEINFO_DEVICES', 8); /** * Return all matches, not just the first. * @link https://php.net/manual/en/fileinfo.constants.php */ define('FILEINFO_CONTINUE', 32); /** * If possible preserve the original access time. * @link https://php.net/manual/en/fileinfo.constants.php */ define('FILEINFO_PRESERVE_ATIME', 128); /** * Don't translate unprintable characters to a \ooo octal * representation. * @link https://php.net/manual/en/fileinfo.constants.php */ define('FILEINFO_RAW', 256); /** * Returns the file extension appropriate for a the MIME type detected in the file. * For types that commonly have multiple file extensions, such as JPEG images, then the return value is multiple extensions speparated by a forward slash e.g.: "jpeg/jpg/jpe/jfif". * For unknown types not available in the magic.mime database, then return value is "???". Available since PHP 7.2.0. * @since 7.2 */ define('FILEINFO_EXTENSION', 2097152); /** * @since 8.2 */ define('FILEINFO_APPLE', 2048); // End of fileinfo v.1.0.5 /dev/null && pwd )" cd "$SCRIPT_DIR" || exit echo "Building docker container for PHP_$i..." docker-compose -f docker-compose.yml build echo "Dumping reflection data to file $SCRIPT_DIR/ReflectionData.json for PHP_$i..." docker-compose -f docker-compose.yml run -e PHP_VERSION="$i" php_under_test /usr/local/bin/php tests/Tools/dump-reflection-to-file.php ReflectionData.json echo "Running tests agains PHP_$i..." docker-compose -f docker-compose.yml run -e PHP_VERSION="$i" test_runner vendor/bin/phpunit --testsuite PHP_"$i" echo "Removing file $SCRIPT_DIR/ReflectionData.json with reflection data for PHP_$i..." rm -f "$SCRIPT_DIR/ReflectionData.json" done Instead of embedding of a long C definition into PHP string, * and creating FFI through FFI::cdef(), it's possible to separate * it into a C header file. Note, that C preprocessor directives * (e.g. #define or #ifdef) are not supported. And only a couple of * special macros may be used especially for FFI.

    * * * #define FFI_LIB "libc.so.6" * * int printf(const char *format, ...); * * * Here, FFI_LIB specifies, that the given library should be loaded. * * * $ffi = FFI::load(__DIR__ . "/printf.h"); * $ffi->printf("Hello world!\n"); * * * @param string $filename * @return FFI|null */ public static function load(string $filename): ?FFI {} /** * FFI definition parsing and shared library loading may take * significant time. It's not useful to do it on each HTTP request in * WEB environment. However, it's possible to pre-load FFI definitions * and libraries at php startup, and instantiate FFI objects when * necessary. Header files may be extended with FFI_SCOPE define * (default pre-loading scope is "C"). This name is going to be * used as FFI::scope() argument. It's possible to pre-load few * files into a single scope. * * * #define FFI_LIB "libc.so.6" * #define FFI_SCOPE "libc" * * int printf(const char *format, ...); * * * These files are loaded through the same FFI::load() load function, * executed from file loaded by opcache.preload php.ini directive. * * * ffi.preload=/etc/php/ffi/printf.h * * * Finally, FFI::scope() instantiate an FFI object, that implements * all C definition from the given scope. * * * $ffi = FFI::scope("libc"); * $ffi->printf("Hello world!\n"); * * * @param string $name * @return FFI */ public static function scope(string $name): FFI {} /** * Method that creates an arbitrary C structure. * * @param string|CType $type * @param bool $owned * @param bool $persistent * @return CData|null * @throws ParserException */ public static function new($type, bool $owned = true, bool $persistent = false): ?CData {} /** * Manually removes previously created "not-owned" data structure. * * @param CData $ptr * @return void */ public static function free(CData $ptr): void {} /** * Casts given $pointer to another C type, specified by C declaration * string or FFI\CType object. * * This function may be called statically and use only predefined * types, or as a method of previously created FFI object. In last * case the first argument may reuse all type and tag names * defined in FFI::cdef(). * * @param CType|string $type * @param CData|int|float|bool|null $ptr * @return CData|null */ public static function cast($type, $ptr): ?CData {} /** * This function creates and returns a FFI\CType object, representng * type of the given C type declaration string. * * FFI::type() may be called statically and use only predefined types, * or as a method of previously created FFI object. In last case the * first argument may reuse all type and tag names defined in * FFI::cdef(). * * @param string $type * @return CType|null */ public static function type(string $type): ?CType {} /** * This function returns the FFI\CType object, representing the type of * the given FFI\CData object. * * @param CData $ptr * @return CType */ public static function typeof(CData $ptr): CType {} /** * Constructs a new C array type with elements of $type and * dimensions specified by $dimensions. * * @param CType $type * @param int[] $dimensions * @return CType */ public static function arrayType(CType $type, array $dimensions): CType {} /** * Returns C pointer to the given C data structure. The pointer is * not "owned" and won't be free. Anyway, this is a potentially * unsafe operation, because the life-time of the returned pointer * may be longer than life-time of the source object, and this may * cause dangling pointer dereference (like in regular C). * * @param CData $ptr * @return CData */ public static function addr(CData $ptr): CData {} /** * Returns size of C data type of the given FFI\CData or FFI\CType. * * @param CData|CType $ptr * @return int */ public static function sizeof($ptr): int {} /** * Returns size of C data type of the given FFI\CData or FFI\CType. * * @param CData|CType $ptr * @return int */ public static function alignof($ptr): int {} /** * Copies $size bytes from memory area $source to memory area $target. * $source may be any native data structure (FFI\CData) or PHP string. * * @param CData $to * @param CData|string $from * @param int $size */ public static function memcpy(CData $to, $from, int $size): void {} /** * Compares $size bytes from memory area $ptr1 and $ptr2. * * @param CData|string $ptr1 * @param CData|string $ptr2 * @param int $size * @return int */ public static function memcmp($ptr1, $ptr2, int $size): int {} /** * Fills the $size bytes of the memory area pointed to by $target with * the constant byte $byte. * * @param CData $ptr * @param int $value * @param int $size */ public static function memset(CData $ptr, int $value, int $size): void {} /** * Creates a PHP string from $size bytes of memory area pointed by * $source. If size is omitted, $source must be zero terminated * array of C chars. * * @param CData $ptr * @param int|null $size * @return string */ public static function string(CData $ptr, ?int $size = null): string {} /** * Checks whether the FFI\CData is a null pointer. * * @param CData $ptr * @return bool */ public static function isNull(CData $ptr): bool {} } } namespace FFI { /** * General FFI exception. * * @since 7.4 */ class Exception extends \Error {} /** * An exception that occurs when parsing invalid header files. * * @since 7.4 */ class ParserException extends Exception {} /** * Proxy object that provides access to compiled structures. * * In the case that CData is a wrapper over a scalar, it contains an * additional "cdata" property. * * @property int|float|bool|null|string|CData $cdata * * In the case that the CData is a wrapper over an arbitrary C structure, * then it allows reading and writing to the fields defined by * this structure. * * @method mixed __get(string $name) * @method mixed __set(string $name, mixed $value) * * In the case that CData is a wrapper over an array, it is an * implementation of the {@see \Traversable}, {@see \Countable}, * and {@see \ArrayAccess} * * @mixin \Traversable * @mixin \Countable * @mixin \ArrayAccess * * In the case when CData is a wrapper over a function pointer, it can * be called. * * @method mixed __invoke(mixed ...$args) * * @since 7.4 */ class CData { /** * Note that this method does not physically exist and is only required * for correct type inference. * * @param int $offset * @return bool */ private function offsetExists(int $offset) {} /** * Note that this method does not physically exist and is only required * for correct type inference. * * @param int $offset * @return CData|int|float|bool|null|string */ private function offsetGet(int $offset) {} /** * Note that this method does not physically exist and is only required * for correct type inference. * * @param int $offset * @param CData|int|float|bool|null|string $value */ private function offsetSet(int $offset, $value) {} /** * Note that this method does not physically exist and is only required * for correct type inference. * * @param int $offset */ private function offsetUnset(int $offset) {} /** * Note that this method does not physically exist and is only required * for correct type inference. * * @return int */ private function count(): int {} } /** * Class containing C type information. * * @since 7.4 */ class CType { /** * @since 8.1 */ public const TYPE_VOID = 0; /** * @since 8.1 */ public const TYPE_FLOAT = 1; /** * @since 8.1 */ public const TYPE_DOUBLE = 2; /** * Please note that this constant may NOT EXIST if there is * no long double support on the current platform. * * @since 8.1 */ public const TYPE_LONGDOUBLE = 3; /** * @since 8.1 */ public const TYPE_UINT8 = 4; /** * @since 8.1 */ public const TYPE_SINT8 = 5; /** * @since 8.1 */ public const TYPE_UINT16 = 6; /** * @since 8.1 */ public const TYPE_SINT16 = 7; /** * @since 8.1 */ public const TYPE_UINT32 = 8; /** * @since 8.1 */ public const TYPE_SINT32 = 9; /** * @since 8.1 */ public const TYPE_UINT64 = 10; /** * @since 8.1 */ public const TYPE_SINT64 = 11; /** * @since 8.1 */ public const TYPE_ENUM = 12; /** * @since 8.1 */ public const TYPE_BOOL = 13; /** * @since 8.1 */ public const TYPE_CHAR = 14; /** * @since 8.1 */ public const TYPE_POINTER = 15; /** * @since 8.1 */ public const TYPE_FUNC = 16; /** * @since 8.1 */ public const TYPE_ARRAY = 17; /** * @since 8.1 */ public const TYPE_STRUCT = 18; /** * @since 8.1 */ public const ATTR_CONST = 1; /** * @since 8.1 */ public const ATTR_INCOMPLETE_TAG = 2; /** * @since 8.1 */ public const ATTR_VARIADIC = 4; /** * @since 8.1 */ public const ATTR_INCOMPLETE_ARRAY = 8; /** * @since 8.1 */ public const ATTR_VLA = 16; /** * @since 8.1 */ public const ATTR_UNION = 32; /** * @since 8.1 */ public const ATTR_PACKED = 64; /** * @since 8.1 */ public const ATTR_MS_STRUCT = 128; /** * @since 8.1 */ public const ATTR_GCC_STRUCT = 256; /** * @since 8.1 */ public const ABI_DEFAULT = 0; /** * @since 8.1 */ public const ABI_CDECL = 1; /** * @since 8.1 */ public const ABI_FASTCALL = 2; /** * @since 8.1 */ public const ABI_THISCALL = 3; /** * @since 8.1 */ public const ABI_STDCALL = 4; /** * @since 8.1 */ public const ABI_PASCAL = 5; /** * @since 8.1 */ public const ABI_REGISTER = 6; /** * @since 8.1 */ public const ABI_MS = 7; /** * @since 8.1 */ public const ABI_SYSV = 8; /** * @since 8.1 */ public const ABI_VECTORCALL = 9; /** * Returns the name of the type. * * @since 8.0 * @return string */ public function getName(): string {} /** * Returns the identifier of the root type. * * Value may be one of: * - {@see CType::TYPE_VOID} * - {@see CType::TYPE_FLOAT} * - {@see CType::TYPE_DOUBLE} * - {@see CType::TYPE_LONGDOUBLE} * - {@see CType::TYPE_UINT8} * - {@see CType::TYPE_SINT8} * - {@see CType::TYPE_UINT16} * - {@see CType::TYPE_SINT16} * - {@see CType::TYPE_UINT32} * - {@see CType::TYPE_SINT32} * - {@see CType::TYPE_UINT64} * - {@see CType::TYPE_SINT64} * - {@see CType::TYPE_ENUM} * - {@see CType::TYPE_BOOL} * - {@see CType::TYPE_CHAR} * - {@see CType::TYPE_POINTER} * - {@see CType::TYPE_FUNC} * - {@see CType::TYPE_ARRAY} * - {@see CType::TYPE_STRUCT} * * @since 8.1 * @return int */ public function getKind(): int {} /** * Returns the size of the type in bytes. * * @since 8.1 * @return int */ public function getSize(): int {} /** * Returns the alignment of the type in bytes. * * @since 8.1 * @return int */ public function getAlignment(): int {} /** * Returns the bit-mask of type attributes. * * @since 8.1 * @return int */ public function getAttributes(): int {} /** * Returns the identifier of the enum value type. * * Value may be one of: * - {@see CType::TYPE_UINT32} * - {@see CType::TYPE_UINT64} * * @since 8.1 * @return int * @throws Exception In the case that the type is not an enumeration. */ public function getEnumKind(): int {} /** * Returns the type of array elements. * * @since 8.1 * @return CType * @throws Exception In the case that the type is not an array. */ public function getArrayElementType(): CType {} /** * Returns the size of an array. * * @since 8.1 * @return int * @throws Exception In the case that the type is not an array. */ public function getArrayLength(): int {} /** * Returns the original type of the pointer. * * @since 8.1 * @return CType * @throws Exception In the case that the type is not a pointer. */ public function getPointerType(): CType {} /** * Returns the field string names of a structure or union. * * @since 8.1 * @return array * @throws Exception In the case that the type is not a struct or union. */ public function getStructFieldNames(): array {} /** * Returns the offset of the structure by the name of this field. In * the case that the type is a union, then for each field of this type * the offset will be equal to 0. * * @since 8.1 * @param string $name * @return int * @throws Exception In the case that the type is not a struct or union. */ public function getStructFieldOffset(string $name): int {} /** * Returns the field type of a structure or union. * * @since 8.1 * @param string $name * @return CType * @throws Exception In the case that the type is not a struct or union. */ public function getStructFieldType(string $name): CType {} /** * Returns the application binary interface (ABI) identifier with which * you can call the function. * * Value may be one of: * - {@see CType::ABI_DEFAULT} * - {@see CType::ABI_CDECL} * - {@see CType::ABI_FASTCALL} * - {@see CType::ABI_THISCALL} * - {@see CType::ABI_STDCALL} * - {@see CType::ABI_PASCAL} * - {@see CType::ABI_REGISTER} * - {@see CType::ABI_MS} * - {@see CType::ABI_SYSV} * - {@see CType::ABI_VECTORCALL} * * @since 8.1 * @return int * @throws Exception In the case that the type is not a function. */ public function getFuncABI(): int {} /** * Returns the return type of the function. * * @since 8.1 * @return CType * @throws Exception In the case that the type is not a function. */ public function getFuncReturnType(): CType {} /** * Returns the number of arguments to the function. * * @since 8.1 * @return int * @throws Exception In the case that the type is not a function. */ public function getFuncParameterCount(): int {} /** * Returns the type of the function argument by its numeric index. * * @since 8.1 * @param int $index * @return CType * @throws Exception In the case that the type is not a function. */ public function getFuncParameterType(int $index): CType {} } } *

    * @return int */ function ncurses_addch($ch) {} /** * Set fore- and background color * @link https://php.net/manual/en/function.ncurses-color-set.php * @param int $pair

    *

    * @return int */ function ncurses_color_set($pair) {} /** * Delete a ncurses window * @link https://php.net/manual/en/function.ncurses-delwin.php * @param resource $window

    *

    * @return bool */ function ncurses_delwin($window) {} /** * Stop using ncurses, clean up the screen * @link https://php.net/manual/en/function.ncurses-end.php * @return int */ function ncurses_end() {} /** * Read a character from keyboard * @link https://php.net/manual/en/function.ncurses-getch.php * @return int */ function ncurses_getch() {} /** * Check if terminal has colors * @link https://php.net/manual/en/function.ncurses-has-colors.php * @return bool Return true if the terminal has color capacities, false otherwise. */ function ncurses_has_colors() {} /** * Initialize ncurses * @link https://php.net/manual/en/function.ncurses-init.php * @return void */ function ncurses_init() {} /** * Allocate a color pair * @link https://php.net/manual/en/function.ncurses-init-pair.php * @param int $pair

    *

    * @param int $fg

    *

    * @param int $bg

    *

    * @return int */ function ncurses_init_pair($pair, $fg, $bg) {} /** * Gets the RGB value for color * @link https://php.net/manual/en/function.ncurses-color-content.php * @param int $color

    *

    * @param int &$r

    *

    * @param int &$g

    *

    * @param int &$b

    *

    * @return int */ function ncurses_color_content($color, &$r, &$g, &$b) {} /** * Gets the RGB value for color * @link https://php.net/manual/en/function.ncurses-pair-content.php * @param int $pair

    *

    * @param int &$f

    *

    * @param int &$b

    *

    * @return int */ function ncurses_pair_content($pair, &$f, &$b) {} /** * Move output position * @link https://php.net/manual/en/function.ncurses-move.php * @param int $y

    *

    * @param int $x

    *

    * @return int */ function ncurses_move($y, $x) {} /** * Create a new window * @link https://php.net/manual/en/function.ncurses-newwin.php * @param int $rows

    * Number of rows *

    * @param int $cols

    * Number of columns *

    * @param int $y

    * y-ccordinate of the origin *

    * @param int $x

    * x-ccordinate of the origin *

    * @return resource a resource ID for the new window. */ function ncurses_newwin($rows, $cols, $y, $x) {} /** * Refresh screen * @link https://php.net/manual/en/function.ncurses-refresh.php * @param int $ch

    *

    * @return int */ function ncurses_refresh($ch) {} /** * Start using colors * @link https://php.net/manual/en/function.ncurses-start-color.php * @return int */ function ncurses_start_color() {} /** * Start using 'standout' attribute * @link https://php.net/manual/en/function.ncurses-standout.php * @return int */ function ncurses_standout() {} /** * Stop using 'standout' attribute * @link https://php.net/manual/en/function.ncurses-standend.php * @return int */ function ncurses_standend() {} /** * Returns baudrate of terminal * @link https://php.net/manual/en/function.ncurses-baudrate.php * @return int */ function ncurses_baudrate() {} /** * Let the terminal beep * @link https://php.net/manual/en/function.ncurses-beep.php * @return int */ function ncurses_beep() {} /** * Check if we can change terminals colors * @link https://php.net/manual/en/function.ncurses-can-change-color.php * @return bool Return true if the terminal has color capabilities and you can change * the colors, false otherwise. */ function ncurses_can_change_color() {} /** * Switch of input buffering * @link https://php.net/manual/en/function.ncurses-cbreak.php * @return bool true or NCURSES_ERR if any error occurred. */ function ncurses_cbreak() {} /** * Clear screen * @link https://php.net/manual/en/function.ncurses-clear.php * @return bool */ function ncurses_clear() {} /** * Clear screen from current position to bottom * @link https://php.net/manual/en/function.ncurses-clrtobot.php * @return bool */ function ncurses_clrtobot() {} /** * Clear screen from current position to end of line * @link https://php.net/manual/en/function.ncurses-clrtoeol.php * @return bool */ function ncurses_clrtoeol() {} /** * Saves terminals (program) mode * @link https://php.net/manual/en/function.ncurses-def-prog-mode.php * @return bool false on success, otherwise true. */ function ncurses_def_prog_mode() {} /** * Resets the prog mode saved by def_prog_mode * @link https://php.net/manual/en/function.ncurses-reset-prog-mode.php * @return int */ function ncurses_reset_prog_mode() {} /** * Saves terminals (shell) mode * @link https://php.net/manual/en/function.ncurses-def-shell-mode.php * @return bool false on success, true otherwise. */ function ncurses_def_shell_mode() {} /** * Resets the shell mode saved by def_shell_mode * @link https://php.net/manual/en/function.ncurses-reset-shell-mode.php * @return int */ function ncurses_reset_shell_mode() {} /** * Delete character at current position, move rest of line left * @link https://php.net/manual/en/function.ncurses-delch.php * @return bool false on success, true otherwise. */ function ncurses_delch() {} /** * Delete line at current position, move rest of screen up * @link https://php.net/manual/en/function.ncurses-deleteln.php * @return bool false on success, otherwise true. */ function ncurses_deleteln() {} /** * Write all prepared refreshes to terminal * @link https://php.net/manual/en/function.ncurses-doupdate.php * @return bool */ function ncurses_doupdate() {} /** * Activate keyboard input echo * @link https://php.net/manual/en/function.ncurses-echo.php * @return bool false on success, true if any error occurred. */ function ncurses_echo() {} /** * Erase terminal screen * @link https://php.net/manual/en/function.ncurses-erase.php * @return bool */ function ncurses_erase() {} /** * Erase window contents * @link https://php.net/manual/en/function.ncurses-werase.php * @param resource $window

    *

    * @return int */ function ncurses_werase($window) {} /** * Returns current erase character * @link https://php.net/manual/en/function.ncurses-erasechar.php * @return string The current erase char, as a string. */ function ncurses_erasechar() {} /** * Flash terminal screen (visual bell) * @link https://php.net/manual/en/function.ncurses-flash.php * @return bool false on success, otherwise true. */ function ncurses_flash() {} /** * Flush keyboard input buffer * @link https://php.net/manual/en/function.ncurses-flushinp.php * @return bool false on success, otherwise true. */ function ncurses_flushinp() {} /** * Check for insert- and delete-capabilities * @link https://php.net/manual/en/function.ncurses-has-ic.php * @return bool true if the terminal has insert/delete-capabilities, false * otherwise. */ function ncurses_has_ic() {} /** * Check for line insert- and delete-capabilities * @link https://php.net/manual/en/function.ncurses-has-il.php * @return bool true if the terminal has insert/delete-line capabilities, * false otherwise. */ function ncurses_has_il() {} /** * Get character and attribute at current position * @link https://php.net/manual/en/function.ncurses-inch.php * @return string the character, as a string. */ function ncurses_inch() {} /** * Insert a line, move rest of screen down * @link https://php.net/manual/en/function.ncurses-insertln.php * @return int */ function ncurses_insertln() {} /** * Ncurses is in endwin mode, normal screen output may be performed * @link https://php.net/manual/en/function.ncurses-isendwin.php * @return bool true, if ncurses_endwin has been called * without any subsequent calls to ncurses_wrefresh, * false otherwise. */ function ncurses_isendwin() {} /** * Returns current line kill character * @link https://php.net/manual/en/function.ncurses-killchar.php * @return string the kill character, as a string. */ function ncurses_killchar() {} /** * Translate newline and carriage return / line feed * @link https://php.net/manual/en/function.ncurses-nl.php * @return bool */ function ncurses_nl() {} /** * Switch terminal to cooked mode * @link https://php.net/manual/en/function.ncurses-nocbreak.php * @return bool true if any error occurred, otherwise false. */ function ncurses_nocbreak() {} /** * Switch off keyboard input echo * @link https://php.net/manual/en/function.ncurses-noecho.php * @return bool true if any error occurred, false otherwise. */ function ncurses_noecho() {} /** * Do not translate newline and carriage return / line feed * @link https://php.net/manual/en/function.ncurses-nonl.php * @return bool */ function ncurses_nonl() {} /** * Switch terminal out of raw mode * @link https://php.net/manual/en/function.ncurses-noraw.php * @return bool true if any error occurred, otherwise false. */ function ncurses_noraw() {} /** * Switch terminal into raw mode * @link https://php.net/manual/en/function.ncurses-raw.php * @return bool true if any error occurred, otherwise false. */ function ncurses_raw() {} /** * Enables/Disable 8-bit meta key information * @link https://php.net/manual/en/function.ncurses-meta.php * @param resource $window

    *

    * @param $bit8 bool

    *

    * @return int */ function ncurses_meta($window, $bit8) {} /** * Restores saved terminal state * @link https://php.net/manual/en/function.ncurses-resetty.php * @return bool Always returns false. */ function ncurses_resetty() {} /** * Saves terminal state * @link https://php.net/manual/en/function.ncurses-savetty.php * @return bool Always returns false. */ function ncurses_savetty() {} /** * Returns a logical OR of all attribute flags supported by terminal * @link https://php.net/manual/en/function.ncurses-termattrs.php * @return bool */ function ncurses_termattrs() {} /** * Assign terminal default colors to color id -1 * @link https://php.net/manual/en/function.ncurses-use-default-colors.php * @return bool */ function ncurses_use_default_colors() {} /** * Returns current soft label key attribute * @link https://php.net/manual/en/function.ncurses-slk-attr.php * @return int The attribute, as an integer. */ function ncurses_slk_attr() {} /** * Clears soft labels from screen * @link https://php.net/manual/en/function.ncurses-slk-clear.php * @return bool true on errors, false otherwise. */ function ncurses_slk_clear() {} /** * Copies soft label keys to virtual screen * @link https://php.net/manual/en/function.ncurses-slk-noutrefresh.php * @return bool */ function ncurses_slk_noutrefresh() {} /** * Copies soft label keys to screen * @link https://php.net/manual/en/function.ncurses-slk-refresh.php * @return int */ function ncurses_slk_refresh() {} /** * Restores soft label keys * @link https://php.net/manual/en/function.ncurses-slk-restore.php * @return int */ function ncurses_slk_restore() {} /** * Forces output when ncurses_slk_noutrefresh is performed * @link https://php.net/manual/en/function.ncurses-slk-touch.php * @return int */ function ncurses_slk_touch() {} /** * Turn off the given attributes * @link https://php.net/manual/en/function.ncurses-attroff.php * @param int $attributes

    *

    * @return int */ function ncurses_attroff($attributes) {} /** * Turn on the given attributes * @link https://php.net/manual/en/function.ncurses-attron.php * @param int $attributes

    *

    * @return int */ function ncurses_attron($attributes) {} /** * Set given attributes * @link https://php.net/manual/en/function.ncurses-attrset.php * @param int $attributes

    *

    * @return int */ function ncurses_attrset($attributes) {} /** * Set background property for terminal screen * @link https://php.net/manual/en/function.ncurses-bkgd.php * @param int $attrchar

    *

    * @return int */ function ncurses_bkgd($attrchar) {} /** * Set cursor state * @link https://php.net/manual/en/function.ncurses-curs-set.php * @param int $visibility

    *

    * @return int */ function ncurses_curs_set($visibility) {} /** * Delay output on terminal using padding characters * @link https://php.net/manual/en/function.ncurses-delay-output.php * @param int $milliseconds

    *

    * @return int */ function ncurses_delay_output($milliseconds) {} /** * Single character output including refresh * @link https://php.net/manual/en/function.ncurses-echochar.php * @param int $character

    *

    * @return int */ function ncurses_echochar($character) {} /** * Put terminal into halfdelay mode * @link https://php.net/manual/en/function.ncurses-halfdelay.php * @param int $tenth

    *

    * @return int */ function ncurses_halfdelay($tenth) {} /** * Check for presence of a function key on terminal keyboard * @link https://php.net/manual/en/function.ncurses-has-key.php * @param int $keycode

    *

    * @return int */ function ncurses_has_key($keycode) {} /** * Insert character moving rest of line including character at current position * @link https://php.net/manual/en/function.ncurses-insch.php * @param int $character

    *

    * @return int */ function ncurses_insch($character) {} /** * Insert lines before current line scrolling down (negative numbers delete and scroll up) * @link https://php.net/manual/en/function.ncurses-insdelln.php * @param int $count

    *

    * @return int */ function ncurses_insdelln($count) {} /** * Set timeout for mouse button clicks * @link https://php.net/manual/en/function.ncurses-mouseinterval.php * @param int $milliseconds

    *

    * @return int */ function ncurses_mouseinterval($milliseconds) {} /** * Sleep * @link https://php.net/manual/en/function.ncurses-napms.php * @param int $milliseconds

    *

    * @return int */ function ncurses_napms($milliseconds) {} /** * Scroll window content up or down without changing current position * @link https://php.net/manual/en/function.ncurses-scrl.php * @param int $count

    *

    * @return int */ function ncurses_scrl($count) {} /** * Turn off the given attributes for soft function-key labels * @link https://php.net/manual/en/function.ncurses-slk-attroff.php * @param int $intarg

    *

    * @return int */ function ncurses_slk_attroff($intarg) {} /** * Turn on the given attributes for soft function-key labels * @link https://php.net/manual/en/function.ncurses-slk-attron.php * @param int $intarg

    *

    * @return int */ function ncurses_slk_attron($intarg) {} /** * Set given attributes for soft function-key labels * @link https://php.net/manual/en/function.ncurses-slk-attrset.php * @param int $intarg

    *

    * @return int */ function ncurses_slk_attrset($intarg) {} /** * Sets color for soft label keys * @link https://php.net/manual/en/function.ncurses-slk-color.php * @param int $intarg

    *

    * @return int */ function ncurses_slk_color($intarg) {} /** * Initializes soft label key functions * @link https://php.net/manual/en/function.ncurses-slk-init.php * @param int $format

    * If ncurses_initscr eventually uses a line from * stdscr to emulate the soft labels, then this parameter determines how * the labels are arranged of the screen. *

    *

    * 0 indicates a 3-2-3 arrangement of the labels, 1 indicates a 4-4 * arrangement and 2 indicates the PC like 4-4-4 mode, but in addition an * index line will be created. *

    * @return bool */ function ncurses_slk_init($format) {} /** * Sets function key labels * @link https://php.net/manual/en/function.ncurses-slk-set.php * @param int $labelnr

    *

    * @param string $label

    *

    * @param int $format

    *

    * @return bool */ function ncurses_slk_set($labelnr, $label, $format) {} /** * Specify different filedescriptor for typeahead checking * @link https://php.net/manual/en/function.ncurses-typeahead.php * @param int $fd

    *

    * @return int */ function ncurses_typeahead($fd) {} /** * Put a character back into the input stream * @link https://php.net/manual/en/function.ncurses-ungetch.php * @param int $keycode

    *

    * @return int */ function ncurses_ungetch($keycode) {} /** * Display the string on the terminal in the video attribute mode * @link https://php.net/manual/en/function.ncurses-vidattr.php * @param int $intarg

    *

    * @return int */ function ncurses_vidattr($intarg) {} /** * Refresh window on terminal screen * @link https://php.net/manual/en/function.ncurses-wrefresh.php * @param resource $window

    *

    * @return int */ function ncurses_wrefresh($window) {} /** * Control use of extended names in terminfo descriptions * @link https://php.net/manual/en/function.ncurses-use-extended-names.php * @param bool $flag

    *

    * @return int */ function ncurses_use_extended_names($flag) {} /** * Control screen background * @link https://php.net/manual/en/function.ncurses-bkgdset.php * @param int $attrchar

    *

    * @return void */ function ncurses_bkgdset($attrchar) {} /** * Set LINES for iniscr() and newterm() to 1 * @link https://php.net/manual/en/function.ncurses-filter.php * @return void */ function ncurses_filter() {} /** * Do not flush on signal characters * @link https://php.net/manual/en/function.ncurses-noqiflush.php * @return void */ function ncurses_noqiflush() {} /** * Flush on signal characters * @link https://php.net/manual/en/function.ncurses-qiflush.php * @return void */ function ncurses_qiflush() {} /** * Set timeout for special key sequences * @link https://php.net/manual/en/function.ncurses-timeout.php * @param int $millisec

    *

    * @return void */ function ncurses_timeout($millisec) {} /** * Control use of environment information about terminal size * @link https://php.net/manual/en/function.ncurses-use-env.php * @param bool $flag

    *

    * @return void */ function ncurses_use_env($flag) {} /** * Output text at current position * @link https://php.net/manual/en/function.ncurses-addstr.php * @param string $text

    *

    * @return int */ function ncurses_addstr($text) {} /** * Apply padding information to the string and output it * @link https://php.net/manual/en/function.ncurses-putp.php * @param string $text

    *

    * @return int */ function ncurses_putp($text) {} /** * Dump screen content to file * @link https://php.net/manual/en/function.ncurses-scr-dump.php * @param string $filename

    *

    * @return int */ function ncurses_scr_dump($filename) {} /** * Initialize screen from file dump * @link https://php.net/manual/en/function.ncurses-scr-init.php * @param string $filename

    *

    * @return int */ function ncurses_scr_init($filename) {} /** * Restore screen from file dump * @link https://php.net/manual/en/function.ncurses-scr-restore.php * @param string $filename

    *

    * @return int */ function ncurses_scr_restore($filename) {} /** * Inherit screen from file dump * @link https://php.net/manual/en/function.ncurses-scr-set.php * @param string $filename

    *

    * @return int */ function ncurses_scr_set($filename) {} /** * Move current position and add character * @link https://php.net/manual/en/function.ncurses-mvaddch.php * @param int $y

    *

    * @param int $x

    *

    * @param int $c

    *

    * @return int */ function ncurses_mvaddch($y, $x, $c) {} /** * Move position and add attributed string with specified length * @link https://php.net/manual/en/function.ncurses-mvaddchnstr.php * @param int $y

    *

    * @param int $x

    *

    * @param string $s

    *

    * @param int $n

    *

    * @return int */ function ncurses_mvaddchnstr($y, $x, $s, $n) {} /** * Add attributed string with specified length at current position * @link https://php.net/manual/en/function.ncurses-addchnstr.php * @param string $s

    *

    * @param int $n

    *

    * @return int */ function ncurses_addchnstr($s, $n) {} /** * Move position and add attributed string * @link https://php.net/manual/en/function.ncurses-mvaddchstr.php * @param int $y

    *

    * @param int $x

    *

    * @param string $s

    *

    * @return int */ function ncurses_mvaddchstr($y, $x, $s) {} /** * Add attributed string at current position * @link https://php.net/manual/en/function.ncurses-addchstr.php * @param string $s

    *

    * @return int */ function ncurses_addchstr($s) {} /** * Move position and add string with specified length * @link https://php.net/manual/en/function.ncurses-mvaddnstr.php * @param int $y

    *

    * @param int $x

    *

    * @param string $s

    *

    * @param int $n

    *

    * @return int */ function ncurses_mvaddnstr($y, $x, $s, $n) {} /** * Add string with specified length at current position * @link https://php.net/manual/en/function.ncurses-addnstr.php * @param string $s

    *

    * @param int $n

    *

    * @return int */ function ncurses_addnstr($s, $n) {} /** * Move position and add string * @link https://php.net/manual/en/function.ncurses-mvaddstr.php * @param int $y

    *

    * @param int $x

    *

    * @param string $s

    *

    * @return int */ function ncurses_mvaddstr($y, $x, $s) {} /** * Move position and delete character, shift rest of line left * @link https://php.net/manual/en/function.ncurses-mvdelch.php * @param int $y

    *

    * @param int $x

    *

    * @return int */ function ncurses_mvdelch($y, $x) {} /** * Move position and get character at new position * @link https://php.net/manual/en/function.ncurses-mvgetch.php * @param int $y

    *

    * @param int $x

    *

    * @return int */ function ncurses_mvgetch($y, $x) {} /** * Move position and get attributed character at new position * @link https://php.net/manual/en/function.ncurses-mvinch.php * @param int $y

    *

    * @param int $x

    *

    * @return int */ function ncurses_mvinch($y, $x) {} /** * Add string at new position in window * @link https://php.net/manual/en/function.ncurses-mvwaddstr.php * @param resource $window

    *

    * @param int $y

    *

    * @param int $x

    *

    * @param string $text

    *

    * @return int */ function ncurses_mvwaddstr($window, $y, $x, $text) {} /** * Insert string at current position, moving rest of line right * @link https://php.net/manual/en/function.ncurses-insstr.php * @param string $text

    *

    * @return int */ function ncurses_insstr($text) {} /** * Reads string from terminal screen * @link https://php.net/manual/en/function.ncurses-instr.php * @param string &$buffer

    * The characters. Attributes will be stripped. *

    * @return int the number of characters. */ function ncurses_instr(&$buffer) {} /** * Set new position and draw a horizontal line using an attributed character and max. n characters long * @link https://php.net/manual/en/function.ncurses-mvhline.php * @param int $y

    *

    * @param int $x

    *

    * @param int $attrchar

    *

    * @param int $n

    *

    * @return int */ function ncurses_mvhline($y, $x, $attrchar, $n) {} /** * Move cursor immediately * @link https://php.net/manual/en/function.ncurses-mvcur.php * @param int $old_y

    *

    * @param int $old_x

    *

    * @param int $new_y

    *

    * @param int $new_x

    *

    * @return int */ function ncurses_mvcur($old_y, $old_x, $new_y, $new_x) {} /** * Set new RGB value for color * @link https://php.net/manual/en/function.ncurses-init-color.php * @param int $color

    *

    * @param int $r

    *

    * @param int $g

    *

    * @param int $b

    *

    * @return int */ function ncurses_init_color($color, $r, $g, $b) {} /** * Draw a border around the screen using attributed characters * @link https://php.net/manual/en/function.ncurses-border.php * @param int $left

    *

    * @param int $right

    *

    * @param int $top

    *

    * @param int $bottom

    *

    * @param int $tl_corner

    * Top left corner *

    * @param int $tr_corner

    * Top right corner *

    * @param int $bl_corner

    * Bottom left corner *

    * @param int $br_corner

    * Bottom right corner *

    * @return int */ function ncurses_border($left, $right, $top, $bottom, $tl_corner, $tr_corner, $bl_corner, $br_corner) {} /** * Define default colors for color 0 * @link https://php.net/manual/en/function.ncurses-assume-default-colors.php * @param int $fg

    *

    * @param int $bg

    *

    * @return int */ function ncurses_assume_default_colors($fg, $bg) {} /** * Define a keycode * @link https://php.net/manual/en/function.ncurses-define-key.php * @param string $definition

    *

    * @param int $keycode

    *

    * @return int */ function ncurses_define_key($definition, $keycode) {} /** * Draw a horizontal line at current position using an attributed character and max. n characters long * @link https://php.net/manual/en/function.ncurses-hline.php * @param int $charattr

    *

    * @param int $n

    *

    * @return int */ function ncurses_hline($charattr, $n) {} /** * Draw a vertical line at current position using an attributed character and max. n characters long * @link https://php.net/manual/en/function.ncurses-vline.php * @param int $charattr

    *

    * @param int $n

    *

    * @return int */ function ncurses_vline($charattr, $n) {} /** * Enable or disable a keycode * @link https://php.net/manual/en/function.ncurses-keyok.php * @param int $keycode

    *

    * @param bool $enable

    *

    * @return int */ function ncurses_keyok($keycode, $enable) {} /** * Returns terminals (short)-name * @link https://php.net/manual/en/function.ncurses-termname.php * @return string|null the shortname of the terminal, truncated to 14 characters. * On errors, returns null. */ function ncurses_termname() {} /** * Returns terminals description * @link https://php.net/manual/en/function.ncurses-longname.php * @return string|null the description, as a string truncated to 128 characters. * On errors, returns null. */ function ncurses_longname() {} /** * Sets mouse options * @link https://php.net/manual/en/function.ncurses-mousemask.php * @param int $newmask

    * Mouse mask options can be set with the following predefined constants: *

    NCURSES_BUTTON1_PRESSED

    * @param int &$oldmask

    * This will be set to the previous value of the mouse event mask. *

    * @return int a mask to indicated which of the in parameter * newmask specified mouse events can be reported. On * complete failure, it returns 0. *

    */ function ncurses_mousemask($newmask, &$oldmask) {} /** * Reads mouse event * @link https://php.net/manual/en/function.ncurses-getmouse.php * @param array &$mevent

    * Event options will be delivered in this parameter which has to be an * array, passed by reference (see example below). *

    *

    * On success an associative array with following keys will be delivered: *

    * "id" : Id to distinguish multiple devices *

    * @return bool false if a mouse event is actually visible in the given window, * otherwise returns true. *

    */ function ncurses_getmouse(array &$mevent) {} /** * Pushes mouse event to queue * @link https://php.net/manual/en/function.ncurses-ungetmouse.php * @param array $mevent

    * An associative array specifying the event options: * "id" : Id to distinguish multiple devices *

    * @return bool false on success, true otherwise. */ function ncurses_ungetmouse(array $mevent) {} /** * Transforms coordinates * @link https://php.net/manual/en/function.ncurses-mouse-trafo.php * @param int &$y

    *

    * @param int &$x

    *

    * @param bool $toscreen

    *

    * @return bool */ function ncurses_mouse_trafo(&$y, &$x, $toscreen) {} /** * Transforms window/stdscr coordinates * @link https://php.net/manual/en/function.ncurses-wmouse-trafo.php * @param resource $window

    *

    * @param int &$y

    *

    * @param int &$x

    *

    * @param bool $toscreen

    *

    * @return bool */ function ncurses_wmouse_trafo($window, &$y, &$x, $toscreen) {} /** * Outputs text at current position in window * @link https://php.net/manual/en/function.ncurses-waddstr.php * @param resource $window

    *

    * @param string $str

    *

    * @param int $n [optional]

    *

    * @return int */ function ncurses_waddstr($window, $str, $n = null) {} /** * Copies window to virtual screen * @link https://php.net/manual/en/function.ncurses-wnoutrefresh.php * @param resource $window

    *

    * @return int */ function ncurses_wnoutrefresh($window) {} /** * Clears window * @link https://php.net/manual/en/function.ncurses-wclear.php * @param resource $window

    *

    * @return int */ function ncurses_wclear($window) {} /** * Sets windows color pairings * @link https://php.net/manual/en/function.ncurses-wcolor-set.php * @param resource $window

    *

    * @param int $color_pair

    *

    * @return int */ function ncurses_wcolor_set($window, $color_pair) {} /** * Reads a character from keyboard (window) * @link https://php.net/manual/en/function.ncurses-wgetch.php * @param resource $window

    *

    * @return int */ function ncurses_wgetch($window) {} /** * Turns keypad on or off * @link https://php.net/manual/en/function.ncurses-keypad.php * @param resource $window

    *

    * @param bool $bf

    *

    * @return int */ function ncurses_keypad($window, $bf) {} /** * Moves windows output position * @link https://php.net/manual/en/function.ncurses-wmove.php * @param resource $window

    *

    * @param int $y

    *

    * @param int $x

    *

    * @return int */ function ncurses_wmove($window, $y, $x) {} /** * Creates a new pad (window) * @link https://php.net/manual/en/function.ncurses-newpad.php * @param int $rows

    *

    * @param int $cols

    *

    * @return resource */ function ncurses_newpad($rows, $cols) {} /** * Copies a region from a pad into the virtual screen * @link https://php.net/manual/en/function.ncurses-prefresh.php * @param resource $pad

    *

    * @param int $pminrow

    *

    * @param int $pmincol

    *

    * @param int $sminrow

    *

    * @param int $smincol

    *

    * @param int $smaxrow

    *

    * @param int $smaxcol

    *

    * @return int */ function ncurses_prefresh($pad, $pminrow, $pmincol, $sminrow, $smincol, $smaxrow, $smaxcol) {} /** * Copies a region from a pad into the virtual screen * @link https://php.net/manual/en/function.ncurses-pnoutrefresh.php * @param resource $pad

    *

    * @param int $pminrow

    *

    * @param int $pmincol

    *

    * @param int $sminrow

    *

    * @param int $smincol

    *

    * @param int $smaxrow

    *

    * @param int $smaxcol

    *

    * @return int */ function ncurses_pnoutrefresh($pad, $pminrow, $pmincol, $sminrow, $smincol, $smaxrow, $smaxcol) {} /** * Enter standout mode for a window * @link https://php.net/manual/en/function.ncurses-wstandout.php * @param resource $window

    *

    * @return int */ function ncurses_wstandout($window) {} /** * End standout mode for a window * @link https://php.net/manual/en/function.ncurses-wstandend.php * @param resource $window

    *

    * @return int */ function ncurses_wstandend($window) {} /** * Set the attributes for a window * @link https://php.net/manual/en/function.ncurses-wattrset.php * @param resource $window

    *

    * @param int $attrs

    *

    * @return int */ function ncurses_wattrset($window, $attrs) {} /** * Turns on attributes for a window * @link https://php.net/manual/en/function.ncurses-wattron.php * @param resource $window

    *

    * @param int $attrs

    *

    * @return int */ function ncurses_wattron($window, $attrs) {} /** * Turns off attributes for a window * @link https://php.net/manual/en/function.ncurses-wattroff.php * @param resource $window

    *

    * @param int $attrs

    *

    * @return int */ function ncurses_wattroff($window, $attrs) {} /** * Adds character at current position in a window and advance cursor * @link https://php.net/manual/en/function.ncurses-waddch.php * @param resource $window

    *

    * @param int $ch

    *

    * @return int */ function ncurses_waddch($window, $ch) {} /** * Draws a border around the window using attributed characters * @link https://php.net/manual/en/function.ncurses-wborder.php * @param resource $window

    * The window on which we operate *

    * @param int $left

    *

    * @param int $right

    *

    * @param int $top

    *

    * @param int $bottom

    *

    * @param int $tl_corner

    * Top left corner *

    * @param int $tr_corner

    * Top right corner *

    * @param int $bl_corner

    * Bottom left corner *

    * @param int $br_corner

    * Bottom right corner *

    * @return int */ function ncurses_wborder($window, $left, $right, $top, $bottom, $tl_corner, $tr_corner, $bl_corner, $br_corner) {} /** * Draws a horizontal line in a window at current position using an attributed character and max. n characters long * @link https://php.net/manual/en/function.ncurses-whline.php * @param resource $window

    *

    * @param int $charattr

    *

    * @param int $n

    *

    * @return int */ function ncurses_whline($window, $charattr, $n) {} /** * Draws a vertical line in a window at current position using an attributed character and max. n characters long * @link https://php.net/manual/en/function.ncurses-wvline.php * @param resource $window

    *

    * @param int $charattr

    *

    * @param int $n

    *

    * @return int */ function ncurses_wvline($window, $charattr, $n) {} /** * Returns the current cursor position for a window * @link https://php.net/manual/en/function.ncurses-getyx.php * @param resource $window

    *

    * @param int &$y

    *

    * @param int &$x

    *

    * @return void */ function ncurses_getyx($window, &$y, &$x) {} /** * Returns the size of a window * @link https://php.net/manual/en/function.ncurses-getmaxyx.php * @param resource $window

    * The measured window *

    * @param int &$y

    * This will be set to the window height *

    * @param int &$x

    * This will be set to the window width *

    * @return void */ function ncurses_getmaxyx($window, &$y, &$x) {} /** * Refreshes the virtual screen to reflect the relations between panels in the stack * @link https://php.net/manual/en/function.ncurses-update-panels.php * @return void */ function ncurses_update_panels() {} /** * Returns the window associated with panel * @link https://php.net/manual/en/function.ncurses-panel-window.php * @param resource $panel

    *

    * @return resource */ function ncurses_panel_window($panel) {} /** * Returns the panel below panel * @link https://php.net/manual/en/function.ncurses-panel-below.php * @param resource $panel

    *

    * @return resource */ function ncurses_panel_below($panel) {} /** * Returns the panel above panel * @link https://php.net/manual/en/function.ncurses-panel-above.php * @param resource $panel

    *

    * @return resource If panel is null, returns the bottom panel in the stack. */ function ncurses_panel_above($panel) {} /** * Replaces the window associated with panel * @link https://php.net/manual/en/function.ncurses-replace-panel.php * @param resource $panel

    *

    * @param resource $window

    *

    * @return int */ function ncurses_replace_panel($panel, $window) {} /** * Moves a panel so that its upper-left corner is at [startx, starty] * @link https://php.net/manual/en/function.ncurses-move-panel.php * @param resource $panel

    *

    * @param int $startx

    *

    * @param int $starty

    *

    * @return int */ function ncurses_move_panel($panel, $startx, $starty) {} /** * Moves a visible panel to the bottom of the stack * @link https://php.net/manual/en/function.ncurses-bottom-panel.php * @param resource $panel

    *

    * @return int */ function ncurses_bottom_panel($panel) {} /** * Moves a visible panel to the top of the stack * @link https://php.net/manual/en/function.ncurses-top-panel.php * @param resource $panel

    *

    * @return int */ function ncurses_top_panel($panel) {} /** * Places an invisible panel on top of the stack, making it visible * @link https://php.net/manual/en/function.ncurses-show-panel.php * @param resource $panel

    *

    * @return int */ function ncurses_show_panel($panel) {} /** * Remove panel from the stack, making it invisible * @link https://php.net/manual/en/function.ncurses-hide-panel.php * @param resource $panel

    *

    * @return int */ function ncurses_hide_panel($panel) {} /** * Remove panel from the stack and delete it (but not the associated window) * @link https://php.net/manual/en/function.ncurses-del-panel.php * @param resource $panel

    *

    * @return bool */ function ncurses_del_panel($panel) {} /** * Create a new panel and associate it with window * @link https://php.net/manual/en/function.ncurses-new-panel.php * @param resource $window

    *

    * @return resource */ function ncurses_new_panel($window) {} define('NCURSES_COLOR_BLACK', 0); define('NCURSES_COLOR_RED', 1); define('NCURSES_COLOR_GREEN', 2); define('NCURSES_COLOR_YELLOW', 3); define('NCURSES_COLOR_BLUE', 4); define('NCURSES_COLOR_MAGENTA', 5); define('NCURSES_COLOR_CYAN', 6); define('NCURSES_COLOR_WHITE', 7); define('NCURSES_KEY_DOWN', 258); define('NCURSES_KEY_UP', 259); define('NCURSES_KEY_LEFT', 260); define('NCURSES_KEY_RIGHT', 261); define('NCURSES_KEY_HOME', 262); define('NCURSES_KEY_END', 360); define('NCURSES_KEY_BACKSPACE', 263); define('NCURSES_KEY_MOUSE', 409); define('NCURSES_KEY_F0', 264); define('NCURSES_KEY_F1', 265); define('NCURSES_KEY_F2', 266); define('NCURSES_KEY_F3', 267); define('NCURSES_KEY_F4', 268); define('NCURSES_KEY_F5', 269); define('NCURSES_KEY_F6', 270); define('NCURSES_KEY_F7', 271); define('NCURSES_KEY_F8', 272); define('NCURSES_KEY_F9', 273); define('NCURSES_KEY_F10', 274); define('NCURSES_KEY_F11', 275); define('NCURSES_KEY_F12', 276); define('NCURSES_KEY_DL', 328); define('NCURSES_KEY_IL', 329); define('NCURSES_KEY_DC', 330); define('NCURSES_KEY_IC', 331); define('NCURSES_KEY_EIC', 332); define('NCURSES_KEY_CLEAR', 333); define('NCURSES_KEY_EOS', 334); define('NCURSES_KEY_EOL', 335); define('NCURSES_KEY_SF', 336); define('NCURSES_KEY_SR', 337); define('NCURSES_KEY_NPAGE', 338); define('NCURSES_KEY_PPAGE', 339); define('NCURSES_KEY_STAB', 340); define('NCURSES_KEY_CTAB', 341); define('NCURSES_KEY_CATAB', 342); define('NCURSES_KEY_ENTER', 343); define('NCURSES_KEY_SRESET', 344); define('NCURSES_KEY_RESET', 345); define('NCURSES_KEY_PRINT', 346); define('NCURSES_KEY_LL', 347); define('NCURSES_KEY_A1', 348); define('NCURSES_KEY_A3', 349); define('NCURSES_KEY_B2', 350); define('NCURSES_KEY_C1', 351); define('NCURSES_KEY_C3', 352); define('NCURSES_KEY_BTAB', 353); define('NCURSES_KEY_BEG', 354); define('NCURSES_KEY_CANCEL', 355); define('NCURSES_KEY_CLOSE', 356); define('NCURSES_KEY_COMMAND', 357); define('NCURSES_KEY_COPY', 358); define('NCURSES_KEY_CREATE', 359); define('NCURSES_KEY_EXIT', 361); define('NCURSES_KEY_FIND', 362); define('NCURSES_KEY_HELP', 363); define('NCURSES_KEY_MARK', 364); define('NCURSES_KEY_MESSAGE', 365); define('NCURSES_KEY_MOVE', 366); define('NCURSES_KEY_NEXT', 367); define('NCURSES_KEY_OPEN', 368); define('NCURSES_KEY_OPTIONS', 369); define('NCURSES_KEY_PREVIOUS', 370); define('NCURSES_KEY_REDO', 371); define('NCURSES_KEY_REFERENCE', 372); define('NCURSES_KEY_REFRESH', 373); define('NCURSES_KEY_REPLACE', 374); define('NCURSES_KEY_RESTART', 375); define('NCURSES_KEY_RESUME', 376); define('NCURSES_KEY_SAVE', 377); define('NCURSES_KEY_SBEG', 378); define('NCURSES_KEY_SCANCEL', 379); define('NCURSES_KEY_SCOMMAND', 380); define('NCURSES_KEY_SCOPY', 381); define('NCURSES_KEY_SCREATE', 382); define('NCURSES_KEY_SDC', 383); define('NCURSES_KEY_SDL', 384); define('NCURSES_KEY_SELECT', 385); define('NCURSES_KEY_SEND', 386); define('NCURSES_KEY_SEOL', 387); define('NCURSES_KEY_SEXIT', 388); define('NCURSES_KEY_SFIND', 389); define('NCURSES_KEY_SHELP', 390); define('NCURSES_KEY_SHOME', 391); define('NCURSES_KEY_SIC', 392); define('NCURSES_KEY_SLEFT', 393); define('NCURSES_KEY_SMESSAGE', 394); define('NCURSES_KEY_SMOVE', 395); define('NCURSES_KEY_SNEXT', 396); define('NCURSES_KEY_SOPTIONS', 397); define('NCURSES_KEY_SPREVIOUS', 398); define('NCURSES_KEY_SPRINT', 399); define('NCURSES_KEY_SREDO', 400); define('NCURSES_KEY_SREPLACE', 401); define('NCURSES_KEY_SRIGHT', 402); define('NCURSES_KEY_SRSUME', 403); define('NCURSES_KEY_SSAVE', 404); define('NCURSES_KEY_SSUSPEND', 405); define('NCURSES_KEY_SUNDO', 406); define('NCURSES_KEY_SUSPEND', 407); define('NCURSES_KEY_UNDO', 408); define('NCURSES_KEY_RESIZE', 410); define('NCURSES_A_NORMAL', 0); define('NCURSES_A_STANDOUT', 65536); define('NCURSES_A_UNDERLINE', 131072); define('NCURSES_A_REVERSE', 262144); define('NCURSES_A_BLINK', 524288); define('NCURSES_A_DIM', 1048576); define('NCURSES_A_BOLD', 2097152); define('NCURSES_A_PROTECT', 16777216); define('NCURSES_A_INVIS', 8388608); define('NCURSES_A_ALTCHARSET', 4194304); define('NCURSES_A_CHARTEXT', 255); define('NCURSES_BUTTON1_PRESSED', 2); define('NCURSES_BUTTON1_RELEASED', 1); define('NCURSES_BUTTON1_CLICKED', 4); define('NCURSES_BUTTON1_DOUBLE_CLICKED', 8); define('NCURSES_BUTTON1_TRIPLE_CLICKED', 16); define('NCURSES_BUTTON2_PRESSED', 128); define('NCURSES_BUTTON2_RELEASED', 64); define('NCURSES_BUTTON2_CLICKED', 256); define('NCURSES_BUTTON2_DOUBLE_CLICKED', 512); define('NCURSES_BUTTON2_TRIPLE_CLICKED', 1024); define('NCURSES_BUTTON3_PRESSED', 8192); define('NCURSES_BUTTON3_RELEASED', 4096); define('NCURSES_BUTTON3_CLICKED', 16384); define('NCURSES_BUTTON3_DOUBLE_CLICKED', 32768); define('NCURSES_BUTTON3_TRIPLE_CLICKED', 65536); define('NCURSES_BUTTON4_PRESSED', 524288); define('NCURSES_BUTTON4_RELEASED', 262144); define('NCURSES_BUTTON4_CLICKED', 1048576); define('NCURSES_BUTTON4_DOUBLE_CLICKED', 2097152); define('NCURSES_BUTTON4_TRIPLE_CLICKED', 4194304); define('NCURSES_BUTTON_SHIFT', 33554432); define('NCURSES_BUTTON_CTRL', 16777216); define('NCURSES_BUTTON_ALT', 67108864); define('NCURSES_ALL_MOUSE_EVENTS', 134217727); define('NCURSES_REPORT_MOUSE_POSITION', 134217728); // End of ncurses v. * @link https://github.com/i-ekho/zmq-phpdoc */ /** * Class ZMQ * @link https://secure.php.net/manual/en/class.zmq.php */ class ZMQ { /** * Exclusive pair pattern */ public const SOCKET_PAIR = 0; /** * Publisher socket */ public const SOCKET_PUB = 1; /** * Subscriber socket */ public const SOCKET_SUB = 2; /** * Request socket */ public const SOCKET_REQ = 3; /** * Reply socket */ public const SOCKET_REP = 4; /** * Alias for SOCKET_DEALER */ public const SOCKET_XREQ = 5; /** * Alias for SOCKET_ROUTER */ public const SOCKET_XREP = 6; /** * Pipeline upstream push socket */ public const SOCKET_PUSH = 8; /** * Pipeline downstream pull socket */ public const SOCKET_PULL = 7; /** * Extended REP socket that can route replies to requesters */ public const SOCKET_ROUTER = 6; /** * Extended REQ socket that load balances to all connected peers */ public const SOCKET_DEALER = 5; /** * Similar to SOCKET_PUB, except you can receive subscriptions as messages. * The subscription message is 0 (unsubscribe) or 1 (subscribe) followed by the topic. */ public const SOCKET_XPUB = 9; /** * Similar to SOCKET_SUB, except you can send subscriptions as messages. See SOCKET_XPUB for format. */ public const SOCKET_XSUB = 10; /** * Used to send and receive TCP data from a non-ØMQ peer. * Available if compiled against ZeroMQ 4.x or higher. */ public const SOCKET_STREAM = 11; /** * The high water mark for inbound and outbound messages is a hard * limit on the maximum number of outstanding messages ØMQ shall queue in memory * for any single peer that the specified socket is communicating with. * Setting this option on a socket will only affect connections made after the option has been set. * On ZeroMQ 3.x this is a wrapper for setting both SNDHWM and RCVHWM. */ public const SOCKOPT_HWM = 1; /** * The ZMQ_SNDHWM option shall set the high water mark for outbound messages on the specified socket. * Available if compiled against ZeroMQ 3.x or higher. */ public const SOCKOPT_SNDHWM = 23; /** * The ZMQ_SNDHWM option shall set the high water mark for inbound messages on the specified socket. * Available if compiled against ZeroMQ 3.x or higher. */ public const SOCKOPT_RCVHWM = 24; /** * Set I/O thread affinity */ public const SOCKOPT_AFFINITY = 4; /** * Set socket identity */ public const SOCKOPT_IDENTITY = 5; /** * Establish message filter. Valid for subscriber socket */ public const SOCKOPT_SUBSCRIBE = 6; /** * Remove message filter. Valid for subscriber socket */ public const SOCKOPT_UNSUBSCRIBE = 7; /** * Set rate for multicast sockets (pgm) (Value: int >= 0) */ public const SOCKOPT_RATE = 8; /** * Set multicast recovery interval (Value: int >= 0) */ public const SOCKOPT_RECOVERY_IVL = 9; /** * Set the initial reconnection interval (Value: int >= 0) */ public const SOCKOPT_RECONNECT_IVL = 18; /** * Set the max reconnection interval (Value: int >= 0) */ public const SOCKOPT_RECONNECT_IVL_MAX = 21; /** * Control multicast loopback (Value: int >= 0) */ public const SOCKOPT_MCAST_LOOP = 10; /** * Set kernel transmit buffer size (Value: int >= 0) */ public const SOCKOPT_SNDBUF = 11; /** * Set kernel receive buffer size (Value: int >= 0) */ public const SOCKOPT_RCVBUF = 12; /** * Receive multi-part messages */ public const SOCKOPT_RCVMORE = 13; /** * Get the socket type. Valid for getSockOpt */ public const SOCKOPT_TYPE = 16; /** * The linger value of the socket. * Specifies how long the socket blocks trying flush messages after it has been closed */ public const SOCKOPT_LINGER = 17; /** * The SOCKOPT_BACKLOG option shall set the maximum length of the queue of outstanding peer connections * for the specified socket; this only applies to connection-oriented transports. */ public const SOCKOPT_BACKLOG = 19; /** * Limits the maximum size of the inbound message. Value -1 means no limit. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_MAXMSGSIZE = 22; /** * Sets the timeout for send operation on the socket. Value -1 means no limit. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_SNDTIMEO = 28; /** * Sets the timeout for receive operation on the socket. Value -1 means no limit. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_RCVTIMEO = 27; /** * Disable IPV6 support if 1. * Available if compiled against ZeroMQ 3.x */ public const SOCKOPT_IPV4ONLY = 31; /** * Retrieve the last connected endpoint - for use with * wildcard ports. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_LAST_ENDPOINT = 32; /** * Idle time for TCP keepalive. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_TCP_KEEPALIVE_IDLE = 36; /** * Count time for TCP keepalive. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_TCP_KEEPALIVE_CNT = 35; /** * Interval for TCP keepalive. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_TCP_KEEPALIVE_INTVL = 37; /** * Set a CIDR string to match against incoming TCP connections. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_DELAY_ATTACH_ON_CONNECT = 39; /** * Set a CIDR string to match against incoming TCP connections. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_TCP_ACCEPT_FILTER = 38; /** * Set the XPUB to receive an application message on each instance of a subscription. * Available if compiled against ZeroMQ 3.x or higher */ public const SOCKOPT_XPUB_VERBOSE = 40; /** * Sets the raw mode on the ROUTER, when set to 1. * In raw mode when using tcp:// transport the socket will read and write without ZeroMQ framing. * Available if compiled against ZeroMQ 4.0 or higher */ public const SOCKOPT_ROUTER_RAW = 41; /** * Enable IPV6. * Available if compiled against ZeroMQ 4.0 or higher */ public const SOCKOPT_IPV6 = 42; /** * The socket limit for this context. * Available if compiled against ZeroMQ 3.x or higher */ public const CTXOPT_MAX_SOCKETS = 2; /** * Poll for incoming data */ public const POLL_IN = 1; /** * Poll for outgoing data */ public const POLL_OUT = 2; /** * Non-blocking operation. * @deprecated use ZMQ::MODE_DONTWAIT instead */ public const MODE_NOBLOCK = 1; /** * Non-blocking operation */ public const MODE_DONTWAIT = 1; /** * Send multi-part message */ public const MODE_SNDMORE = 2; /** * Forwarder device */ public const DEVICE_FORWARDER = 2; /** * Queue device */ public const DEVICE_QUEUE = 3; /** * Streamer device */ public const DEVICE_STREAMER = 1; /** * ZMQ extension internal error */ public const ERR_INTERNAL = -99; /** * Implies that the operation would block when ZMQ::MODE_DONTWAIT is used */ public const ERR_EAGAIN = 11; /** * The operation is not supported by the socket type */ public const ERR_ENOTSUP = 156384713; /** * The operation can not be executed because the socket is not in correct state */ public const ERR_EFSM = 156384763; /** * The context has been terminated */ public const ERR_ETERM = 156384765; /** * Private constructor to prevent direct initialization. This class holds the constants for ZMQ extension. * @link https://secure.php.net/manual/en/zmq.construct.php */ private function __construct() {} } /** * Class ZMQContext * @link https://secure.php.net/manual/en/class.zmqcontext.php */ class ZMQContext { /** * Constructs a new ZMQ context. The context is used to initialize sockets. * A persistent context is required to initialize persistent sockets. * * @link https://secure.php.net/manual/en/zmqcontext.construct.php * * @param int $io_threads Number of io-threads in the context * @param bool $is_persistent Whether the context is persistent. Persistent context is stored over multiple requests and is a requirement for persistent sockets. */ public function __construct($io_threads = 1, $is_persistent = true) {} /** * (PECL zmq >= 1.0.4) * Returns the value of a context option. * * @link https://secure.php.net/manual/en/zmqcontext.getopt.php * * @param string $key An int representing the option. See the ZMQ::CTXOPT_* constants. * @return string|int Returns either a string or an integer depending on key. Throws ZMQContextException on error. * @throws ZMQContextException */ public function getOpt($key) {} /** * (PECL zmq >= 0.5.0) * Shortcut for creating new sockets from the context. * If the context is not persistent the persistent_id parameter is ignored * and the socket falls back to being non-persistent. * The on_new_socket is called only when a new underlying socket structure is created. * * @link https://secure.php.net/manual/en/zmqcontext.getsocket.php * * @param int $type ZMQ::SOCKET_* constant to specify socket type. * @param string $persistent_id If persistent_id is specified the socket will be persisted over multiple requests. * @param callable $on_new_socket Callback function, which is executed when a new socket structure is created. This function does not get invoked if the underlying persistent connection is re-used. The callback takes ZMQSocket and persistent_id as two arguments. * @return ZMQSocket * @throws ZMQSocketException */ public function getSocket($type, $persistent_id = null, $on_new_socket = null) {} /** * (PECL zmq >= 0.5.0) * Whether the context is persistent. * Persistent context is needed for persistent connections as each socket is allocated from a context. * * @link https://secure.php.net/manual/en/zmqcontext.ispersistent.php * * @return bool Returns TRUE if the context is persistent and FALSE if the context is non-persistent. */ public function isPersistent() {} /** * (PECL zmq >= 1.0.4) * Sets a ZMQ context option. The type of the value depends on the key. * See ZMQ Constant Types for more information. * * @link https://secure.php.net/manual/en/zmqcontext.setopt.php * * @param int $key One of the ZMQ::CTXOPT_* constants. * @param mixed $value The value of the parameter. * @return ZMQContext * @throws ZMQContextException */ public function setOpt($key, $value) {} } /** * Class ZMQSocket * @link https://secure.php.net/manual/en/class.zmqsocket.php */ class ZMQSocket { /** * (PECL zmq >= 0.5.0) * Constructs a ZMQSocket object. * The persistent_id parameter can be used to allocated a persistent socket. * A persistent socket has to be allocated from a persistent context and it stays connected over multiple requests. * The persistent_id parameter can be used to recall the same socket over multiple requests. * The on_new_socket is called only when a new underlying socket structure is created. * * @link https://secure.php.net/manual/en/zmqsocket.construct.php * * @param ZMQContext $context

    ZMQContext to build this object

    * @param int $type

    The type of the socket. See ZMQ::SOCKET_* constants.

    * @param string $persistent_id [optional]

    If persistent_id is specified the socket will be persisted over multiple requests. If context is not persistent the socket falls back to non-persistent mode.

    * @param callable $on_new_socket [optional]

    Callback function, which is executed when a new socket structure is created. This function does not get invoked if the underlying persistent connection is re-used.

    * * @throws ZMQSocketException */ public function __construct(ZMQContext $context, $type, $persistent_id = null, $on_new_socket = null) {} /** * (PECL zmq >= 0.5.0) * Bind the socket to an endpoint. * The endpoint is defined in format transport://address * where transport is one of the following: inproc, ipc, tcp, pgm or epgm. * * @link https://secure.php.net/manual/en/zmqsocket.bind.php * * @param string $dsn The bind dsn, for example transport://address. * @param bool $force Tries to bind even if the socket has already been bound to the given endpoint. * * @return ZMQSocket * @throws ZMQSocketException if binding fails */ public function bind($dsn, $force = false) {} /** * (PECL zmq >= 0.5.0) * Connect the socket to a remote endpoint. * The endpoint is defined in format transport://address * where transport is one of the following: inproc, ipc, tcp, pgm or epgm. * * @link https://secure.php.net/manual/en/zmqsocket.connect.php * * @param string $dsn The bind dsn, for example transport://address. * @param bool $force Tries to bind even if the socket has already been bound to the given endpoint. * * @return ZMQSocket * @throws ZMQSocketException If connection fails */ public function connect($dsn, $force = false) {} /** * (PECL zmq >= 1.0.4) * Disconnect the socket from a previously connected remote endpoint. * The endpoint is defined in format transport://address * where transport is one of the following: inproc, ipc, tcp, pgm or epgm. * * @link https://secure.php.net/manual/en/zmqsocket.disconnect.php * * @param string $dsn The bind dsn, for example transport://address. * * @return ZMQSocket * @throws ZMQSocketException If connection fails */ public function disconnect($dsn) {} /** * Returns a list of endpoints where the socket is connected or bound to. * * @link https://secure.php.net/manual/en/zmqsocket.getendpoints.php * * @return array contains two sub-arrays: 'connect' and 'bind' * @throws ZMQSocketException */ public function getEndpoints() {} /** * Returns the persistent id string assigned of the object and NULL if socket is not persistent. * * @link https://secure.php.net/manual/en/zmqsocket.getpersistentid.php * * @return string|null

    * Returns the persistent id string assigned of the object and NULL if socket is not persistent. *

    */ public function getPersistentId() {} /** * Returns the value of a socket option. * This method is available if ZMQ extension has been compiled against ZMQ version 2.0.7 or higher * * @link https://secure.php.net/manual/en/zmqsocket.getsockopt.php * * @since 0MQ 2.0.7 * @param int $key An int representing the option. See the ZMQ::SOCKOPT_* constants. * * @return string|int

    * Returns either a string or an integer depending on key. Throws * ZMQSocketException on error. *

    * @throws ZMQSocketException */ public function getSockOpt($key) {} /** * Return the socket type. * The socket type can be compared against ZMQ::SOCKET_* constants. * * @link https://secure.php.net/manual/en/zmqsocket.getsockettype.php * * @return int

    * Returns an integer representing the socket type. The integer can be compared against * ZMQ::SOCKET_* constants. *

    */ public function getSocketType() {} /** * Check whether the socket is persistent. * * @link https://secure.php.net/manual/en/zmqsocket.ispersistent.php * * @return bool

    Returns a boolean based on whether the socket is persistent or not.

    */ public function isPersistent() {} /** * Receive a message from a socket. * By default receiving will block until a message is available unless ZMQ::MODE_NOBLOCK flag is used. * ZMQ::SOCKOPT_RCVMORE socket option can be used for receiving multi-part messages. * Returns the message. * If ZMQ::MODE_NOBLOCK is used and the operation would block bool false shall be returned. * * @link https://secure.php.net/manual/en/zmqsocket.recv.php * @see ZMQSocket::setSockOpt() * * @param int $mode Pass mode flags to receive multipart messages or non-blocking operation. See ZMQ::MODE_* constants. * * @return string|false

    Returns the message. Throws ZMQSocketException in error. If ZMQ::MODE_NOBLOCK is used and the operation would block boolean false shall be returned.

    * @throws ZMQSocketException if receiving fails. */ public function recv($mode = 0) {} /** * Receive an array multipart message from a socket. * By default receiving will block until a message is available unless ZMQ::MODE_NOBLOCK flag is used. * Returns the array of message parts. * If ZMQ::MODE_NOBLOCK is used and the operation would block bool false shall be returned. * * @link https://secure.php.net/manual/en/zmqsocket.recvmulti.php * * @param int $mode Pass mode flags to receive multipart messages or non-blocking operation. See ZMQ::MODE_* constants. * * @return string[] Returns the array of message parts. Throws ZMQSocketException in error. If ZMQ::MODE_NOBLOCK is used and the operation would block boolean false shall be returned. * @throws ZMQSocketException if receiving fails. */ public function recvMulti($mode = 0) {} /** * Send a message using the socket. The operation can block unless ZMQ::MODE_NOBLOCK is used. * If ZMQ::MODE_NOBLOCK is used and the operation would block bool false shall be returned. * * @link https://secure.php.net/manual/en/zmqsocket.send.php * * @param string $message The message to send * @param int $mode Pass mode flags to receive multipart messages or non-blocking operation. See ZMQ::MODE_* constants. * * * @return ZMQSocket * @throws ZMQSocketException if sending message fails */ public function send($message, $mode = 0) {} /** * Send a multipart message using the socket. The operation can block unless ZMQ::MODE_NOBLOCK is used. * If ZMQ::MODE_NOBLOCK is used and the operation would block bool false shall be returned. * * @link https://secure.php.net/manual/en/zmqsocket.sendmulti.php * * @param array $message The message to send - an array of strings * @param int $mode Pass mode flags to receive multipart messages or non-blocking operation. See ZMQ::MODE_* constants. * * * @return ZMQSocket * @throws ZMQSocketException if sending message fails */ public function sendmulti(array $message, $mode = 0) {} /** * Sets a ZMQ socket option. The type of the value depends on the key. * @see ZMQ Constant Types for more information. * * @link https://secure.php.net/manual/en/zmqsocket.setsockopt.php * * @param int $key One of the ZMQ::SOCKOPT_* constants. * @param mixed $value The value of the parameter. * * @return ZMQSocket * @throws ZMQSocketException */ public function setSockOpt($key, $value) {} /** * Unbind the socket from an endpoint. * The endpoint is defined in format transport://address * where transport is one of the following: inproc, ipc, tcp, pgm or epgm. * * @link https://secure.php.net/manual/en/zmqsocket.unbind.php * * @param string $dsn The previously bound dsn, for example transport://address. * * @return ZMQSocket * @throws ZMQSocketException if binding fails */ public function unbind($dsn) {} } /** * Class ZMQPoll * @link https://secure.php.net/manual/en/class.zmqpoll.php */ class ZMQPoll { /** * (PECL zmq >= 0.5.0) * Adds a new item to the poll set and returns the internal id of the added item. * The item can be removed from the poll set using the returned string id. * Returns a string id of the added item which can be later used to remove the item. * * @link https://secure.php.net/manual/en/zmqpoll.add.php * * @param ZMQSocket $entry ZMQSocket object or a PHP stream resource * @param int $type Defines what activity the socket is polled for. See ZMQ::POLL_IN and ZMQ::POLL_OUT constants. * * @return int Returns a string id of the added item which can be later used to remove the item. Throws ZMQPollException on error. * @throws ZMQPollException if the object has not been initialized with polling */ public function add(ZMQSocket $entry, $type) {} /** * (PECL zmq >= 1.0.4) * Clears all elements from the poll set. * * @link https://secure.php.net/manual/en/zmqpoll.clear.php * * @return ZMQPoll Returns the current object. */ public function clear() {} /** * (PECL zmq >= 0.5.0) * Count the items in the poll set. * * @link https://secure.php.net/manual/en/zmqpoll.count.php * * @return int Returns an integer representing the amount of items in the poll set. */ public function count() {} /** * (PECL zmq >= 0.5.0) * Returns the ids of the objects that had errors in the last poll. * Returns an array containing ids for the items that had errors in the last poll. * Empty array is returned if there were no errors. * * @link https://secure.php.net/manual/en/zmqpoll.getlasterrors.php * * @return int[] */ public function getLastErrors() {} /** * (PECL zmq >= 0.5.0) * Polls the items in the current poll set. * The readable and writable items are returned in the readable and writable parameters. * ZMQPoll::getLastErrors() can be used to check if there were errors. * Returns an int representing amount of items with activity. * * @link https://secure.php.net/manual/en/zmqpoll.poll.php * * @param array &$readable Array where readable ZMQSockets/PHP streams are returned. The array will be cleared at the beginning of the operation. * @param array &$writable Array where writable ZMQSockets/PHP streams are returned. The array will be cleared at the beginning of the operation. * @param int $timeout Timeout for the operation. -1 means that poll waits until at least one item has activity. Please note that starting from version 1.0.0 the poll timeout is defined in milliseconds, rather than microseconds. * * @throws ZMQPollException if polling fails * @return int */ public function poll(array &$readable, array &$writable, $timeout = -1) {} /** * (PECL zmq >= 0.5.0) * Remove item from the poll set. * The item parameter can be ZMQSocket object, a stream resource or the id returned from ZMQPoll::add() method. * Returns true if the item was removed and false if the object with given id does not exist in the poll set. * * @link https://secure.php.net/manual/en/zmqpoll.remove.php * * @param ZMQSocket|string|mixed $item The ZMQSocket object, PHP stream or string id of the item. * @return bool Returns true if the item was removed and false if the object with given id does not exist in the poll set. */ public function remove($item) {} } /** * Class ZMQDevice * @link https://secure.php.net/manual/en/class.zmqdevice.php */ class ZMQDevice { /** * (PECL zmq >= 1.0.4) * Construct a new device. * "ØMQ devices can do intermediation of addresses, services, queues, or any other abstraction you care * to define above the message and socket layers." -- zguide * Call to this method will prepare the device. Usually devices are very long running processes so running this method from interactive script is not recommended. This method throw ZMQDeviceException if the device cannot be started. * * @link https://secure.php.net/manual/en/zmqdevice.construct.php * * @param ZMQSocket $frontend Frontend parameter for the devices. Usually where there messages are coming. * @param ZMQSocket $backend Backend parameter for the devices. Usually where there messages going to. * @param null|ZMQSocket $listener Listener socket, which receives a copy of all messages going both directions. The type of this socket should be SUB, PULL or DEALER. */ public function __construct(ZMQSocket $frontend, ZMQSocket $backend, ZMQSocket $listener = null) {} /** * Gets the idle callback timeout value. * This method returns the idle callback timeout value. * Added in ZMQ extension version 1.1.0. * * @link https://secure.php.net/manual/en/zmqdevice.getidletimeout.php * * @return int This method returns the idle callback timeout value. */ public function getIdleTimeout() {} /** * Gets the timer callback timeout value. * Added in ZMQ extension version 1.1.0. * * @link https://secure.php.net/manual/en/zmqdevice.gettimertimeout.php * * @return int This method returns the timer timeout value. */ public function getTimerTimeout() {} /** * Runs the device. * Call to this method will block until the device is running. * It is not recommended that devices are used from interactive scripts. * * @link https://secure.php.net/manual/en/zmqdevice.run.php * * @throws ZMQDeviceException */ public function run() {} /** * Sets the idle callback function. * If idle timeout is defined the idle callback function shall be called if the internal poll loop times out * without events. If the callback function returns false or a value that evaluates to false the device is stopped. * The callback function signature is callback (mixed $user_data). * * @link https://secure.php.net/manual/en/zmqdevice.setidlecallback.php * * @param callable $cb_func Callback function to invoke when the device is idle. Returning false or a value that evaluates to false from this function will cause the device to stop. * @param int $timeout How often to invoke the idle callback in milliseconds. The idle callback is invoked periodically when there is no activity on the device. The timeout value guarantees that there is at least this amount of milliseconds between invocations of the callback function. * @param mixed $user_data Additional data to pass to the callback function. * * @return ZMQDevice On success this method returns the current object. */ public function setIdleCallback($cb_func, $timeout, $user_data) {} /** * Sets the idle callback timeout value. The idle callback is invoked periodically when the device is idle. * On success this method returns the current object. * * @link https://secure.php.net/manual/en/zmqdevice.setidletimeout.php * * @param int $timeout The idle callback timeout value in milliseconds * * @return ZMQDevice On success this method returns the current object. */ public function setIdleTimeout($timeout) {} /** * Sets the timer callback function. The timer callback will be invoked after timeout has passed. * The difference between idle and timer callbacks are that idle callback is invoked only when the device is idle. * The callback function signature is callback (mixed $user_data). * Added in ZMQ extension version 1.1.0. * * @link https://secure.php.net/manual/en/zmqdevice.settimercallback.php * * @param callable $cb_func Callback function to invoke when the device is idle. Returning false or a value that evaluates to false from this function will cause the device to stop. * @param int $timeout How often to invoke the idle callback in milliseconds. The idle callback is invoked periodically when there is no activity on the device. The timeout value guarantees that there is at least this amount of milliseconds between invocations of the callback function. * @param mixed $user_data Additional data to pass to the callback function. * * @return ZMQDevice */ public function setTimerCallback($cb_func, $timeout, $user_data) {} /** * Sets the timer callback timeout value. The timer callback is invoked periodically if it's set. * Added in ZMQ extension version 1.1.0. * * @link https://secure.php.net/manual/en/zmqdevice.settimertimeout.php * * @param int $timeout The timer callback timeout value. * * @return ZMQDevice */ public function setTimerTimeout($timeout) {} } class ZMQException extends Exception {} class ZMQContextException extends ZMQException {} class ZMQSocketException extends ZMQException {} class ZMQPollException extends ZMQException {} class ZMQDeviceException extends ZMQException {} * COM class constructor. * @param string $module_name * @param string $server_name [optional] * @param int $codepage [optional] * @param string $typelib [optional] */ public function __construct($module_name, $server_name = null, $codepage = CP_ACP, $typelib = null) {} public function __get($name) {} public function __set($name, $value) {} public function __call($name, $args) {} } /** * The DOTNET class allows you to instantiate a class from a .Net assembly and call its methods and access its properties. * @link https://php.net/manual/en/class.dotnet.php */ class DOTNET { /** * (PHP 4 >= 4.1.0, PHP 5, PHP 7)
    * COM class constructor. * @param string $assembly_name * @param string $class_name * @param int $codepage [optional] */ public function __construct($assembly_name, string $class_name, $codepage = CP_ACP) {} public function __get($name) {} public function __set($name, $value) {} public function __call($name, $args) {} } /** * The VARIANT is COM's equivalent of the PHP zval; it is a structure that can contain a value with a range of different possible types. The VARIANT class provided by the COM extension allows you to have more control over the way that PHP passes values to and from COM. * @link https://php.net/manual/en/class.variant.php */ class VARIANT { /** * (PHP 4 >= 4.1.0, PHP 5, PHP 7)
    * COM class constructor. * @param mixed $value [optional] * @param int $type [optional] * @param int $codepage [optional] */ public function __construct($value = null, int $type = VT_EMPTY, $codepage = CP_ACP) {} public function __get($name) {} public function __set($name, $value) {} public function __call($name, $args) {} } /** * This extension will throw instances of the class com_exception whenever there is a potentially fatal error reported by COM. All COM exceptions have a well-defined code property that corresponds to the HRESULT return value from the various COM operations. You may use this code to make programmatic decisions on how to handle the exception. * @link https://php.net/manual/en/com.error-handling.php */ class com_exception extends \Exception {} /** * (PHP 5, PHP 7)
    * Generate a globally unique identifier (GUID) * @link https://php.net/manual/en/function.com-create-guid.php * @return string */ function com_create_guid() {} /** * (PHP 4 >= 4.2.0, PHP 5, PHP 7)
    * Connect events from a COM object to a PHP object * @link https://php.net/manual/en/function.com-event-sink.php * @param \VARIANT $comobject * @param object $sinkobject * @param string $sinkinterface [optional] * @return bool */ function com_event_sink($comobject, $sinkobject, $sinkinterface = null) {} /** * (PHP 5, PHP 7)
    * Returns a handle to an already running instance of a COM object * @link https://php.net/manual/en/function.com-get-active-object.php * @param string $progid * @param int $code_page [optional] * @return \VARIANT */ function com_get_active_object($progid, $code_page = CP_ACP) {} /** * (PHP 4 >= 4.1.0, PHP 5, PHP 7)
    * Loads a Typelib * @link https://php.net/manual/en/function.com-get-active-object.php * @param string $typelib_name * @param bool $case_insensitive [optional] * @return bool */ function com_load_typelib($typelib_name, $case_insensitive = true) {} /** * (PHP 4 >= 4.2.0, PHP 5, PHP 7)
    * Process COM messages, sleeping for up to timeoutms milliseconds * @link https://php.net/manual/en/function.com-message-pump.php * @param int $timeoutms [optional] * @return bool */ function com_message_pump($timeoutms = 0) {} /** * (PHP 4 >= 4.2.0, PHP 5, PHP 7)
    * Print out a PHP class definition for a dispatchable interface * @link https://php.net/manual/en/function.com-print-typeinfo.php * @param object $comobject * @param string $dispinterface [optional] * @param bool $wantsink [optional] * @return bool */ function com_print_typeinfo($comobject, $dispinterface = null, $wantsink = false) {} /** * (PHP 5, PHP 7)
    * Returns the absolute value of a variant * @link https://php.net/manual/en/function.variant-abs.php * @param mixed $val * @return mixed */ function variant_abs($val) {} /** * (PHP 5, PHP 7)
    * "Adds" two variant values together and returns the result * @link https://php.net/manual/en/function.variant-abs.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_add($left, $right) {} /** * (PHP 5, PHP 7)
    * Performs a bitwise AND operation between two variants * @link https://php.net/manual/en/function.variant-and.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_and($left, $right) {} /** * (PHP 5, PHP 7)
    * Convert a variant into a new variant object of another type * @link https://php.net/manual/en/function.variant-cast.php * @param \VARIANT $variant * @param int $type * @return \VARIANT */ function variant_cast($variant, $type) {} /** * (PHP 5, PHP 7)
    * Concatenates two variant values together and returns the result * @link https://php.net/manual/en/function.variant-cat.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_cat($left, $right) {} /** * (PHP 5, PHP 7)
    * Compares two variants * @link https://php.net/manual/en/function.variant-cmp.php * @param mixed $left * @param mixed $right * @param int $lcid [optional] * @param int $flags [optional] * @return int */ function variant_cmp($left, $right, $lcid = null, $flags = null) {} /** * (PHP 5, PHP 7)
    * Returns a variant date representation of a Unix timestamp * @link https://php.net/manual/en/function.variant-date-from-timestamp.php * @param int $timestamp * @return \VARIANT */ function variant_date_from_timestamp($timestamp) {} /** * (PHP 5, PHP 7)
    * Converts a variant date/time value to Unix timestamp * @link https://php.net/manual/en/function.variant-date-to-timestamp.php * @param \VARIANT $variant * @return int */ function variant_date_to_timestamp($variant) {} /** * (PHP 5, PHP 7)
    * Returns the result from dividing two variants * @link https://php.net/manual/en/function.variant-div.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_div($left, $right) {} /** * (PHP 5, PHP 7)
    * Performs a bitwise equivalence on two variants * @link https://php.net/manual/en/function.variant-eqv.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_eqv($left, $right) {} /** * (PHP 5, PHP 7)
    * Returns the integer portion of a variant * @link https://php.net/manual/en/function.variant-fix.php * @param mixed $variant * @return mixed */ function variant_fix($variant) {} /** * (PHP 5, PHP 7)
    * Returns the type of a variant object * @link https://php.net/manual/en/function.variant-get-type.php * @param VARIANT $variant * @return int */ function variant_get_type($variant) {} /** * (PHP 5, PHP 7)
    * Converts variants to integers and then returns the result from dividing them * @link https://php.net/manual/en/function.variant-idiv.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_idiv($left, $right) {} /** * (PHP 5, PHP 7)
    * Performs a bitwise implication on two variants * @link https://php.net/manual/en/function.variant-imp.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_imp($left, $right) {} /** * (PHP 5, PHP 7)
    * Returns the integer portion of a variant * @link https://php.net/manual/en/function.variant-int.php * @param mixed $variant * @return mixed */ function variant_int($variant) {} /** * (PHP 5, PHP 7)
    * Divides two variants and returns only the remainder * @link https://php.net/manual/en/function.variant-mod.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_mod($left, $right) {} /** * (PHP 5, PHP 7)
    * Multiplies the values of the two variants * @link https://php.net/manual/en/function.variant-mul.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_mul($left, $right) {} /** * (PHP 5, PHP 7)
    * Performs logical negation on a variant * @link https://php.net/manual/en/function.variant-neg.php * @param mixed $variant * @return mixed */ function variant_neg($variant) {} /** * (PHP 5, PHP 7)
    * Performs bitwise not negation on a variant * @link https://php.net/manual/en/function.variant-not.php * @param mixed $variant * @return mixed */ function variant_not($variant) {} /** * (PHP 5, PHP 7)
    * Performs a logical disjunction on two variants * @link https://php.net/manual/en/function.variant-or.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_or($left, $right) {} /** * (PHP 5, PHP 7)
    * Returns the result of performing the power function with two variants * @link https://php.net/manual/en/function.variant-pow.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_pow($left, $right) {} /** * (PHP 5, PHP 7)
    * Rounds a variant to the specified number of decimal places * @link https://php.net/manual/en/function.variant-round.php * @param mixed $variant * @param int $decimals * @return mixed */ function variant_round($variant, $decimals) {} /** * (PHP 5, PHP 7)
    * Convert a variant into another type "in-place" * @link https://php.net/manual/en/function.variant-set-type.php * @param VARIANT $variant * @param int $type * @return void */ function variant_set_type($variant, $type) {} /** * (PHP 5, PHP 7)
    * Assigns a new value for a variant object * @link https://php.net/manual/en/function.variant-set.php * @param VARIANT $variant * @param mixed $value * @return void */ function variant_set($variant, $value) {} /** * (PHP 5, PHP 7)
    * Subtracts the value of the right variant from the left variant value * @link https://php.net/manual/en/function.variant-sub.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_sub($left, $right) {} /** * (PHP 5, PHP 7)
    * Performs a logical exclusion on two variants * @link https://php.net/manual/en/function.variant-xor.php * @param mixed $left * @param mixed $right * @return mixed */ function variant_xor($left, $right) {} define('CLSCTX_INPROC_SERVER', 1); define('CLSCTX_INPROC_HANDLER', 2); define('CLSCTX_LOCAL_SERVER', 4); define('CLSCTX_REMOTE_SERVER', 16); define('CLSCTX_SERVER', 21); define('CLSCTX_ALL', 23); define('VT_NULL', 1); define('VT_EMPTY', 0); define('VT_UI1', 17); define('VT_I2', 2); define('VT_I4', 3); define('VT_R4', 4); define('VT_R8', 5); define('VT_BOOL', 11); define('VT_ERROR', 10); define('VT_CY', 6); define('VT_DATE', 7); define('VT_BSTR', 8); define('VT_DECIMAL', 14); define('VT_UNKNOWN', 13); define('VT_DISPATCH', 9); define('VT_VARIANT', 12); define('VT_I1', 16); define('VT_UI2', 18); define('VT_UI4', 19); define('VT_INT', 22); define('VT_UINT', 23); define('VT_ARRAY', 8192); define('VT_BYREF', 16384); define('CP_ACP', 0); define('CP_MACCP', 2); define('CP_OEMCP', 1); define('CP_UTF7', 65000); define('CP_UTF8', 65001); define('CP_SYMBOL', 42); define('CP_THREAD_ACP', 3); define('VARCMP_LT', 0); define('VARCMP_EQ', 1); define('VARCMP_GT', 2); define('VARCMP_NULL', 3); define('NORM_IGNORECASE', 1); define('NORM_IGNORENONSPACE', 2); define('NORM_IGNORESYMBOLS', 4); define('NORM_IGNOREWIDTH', 131072); define('NORM_IGNOREKANATYPE', 65536); define('NORM_IGNOREKASHIDA', 262144); define('DISP_E_DIVBYZERO', -2147352558); define('DISP_E_OVERFLOW', -2147352566); define('MK_E_UNAVAILABLE', -2147221021); // End of com v. * The optional encoding specifies the character * encoding for the input/output in PHP 4. Starting from PHP 5, the input * encoding is automatically detected, so that the * encoding parameter specifies only the output * encoding. In PHP 4, the default output encoding is the same as the * input charset. If empty string is passed, the parser attempts to identify * which encoding the document is encoded in by looking at the heading 3 or * 4 bytes. In PHP 5.0.0 and 5.0.1, the default output charset is * ISO-8859-1, while in PHP 5.0.2 and upper is UTF-8. The supported * encodings are ISO-8859-1, UTF-8 and * US-ASCII. *

    * @return resource|false|XMLParser a resource handle for the new XML parser. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] function xml_parser_create(?string $encoding) {} /** * Create an XML parser with namespace support * @link https://php.net/manual/en/function.xml-parser-create-ns.php * @param string|null $encoding [optional]

    * The optional encoding specifies the character * encoding for the input/output in PHP 4. Starting from PHP 5, the input * encoding is automatically detected, so that the * encoding parameter specifies only the output * encoding. In PHP 4, the default output encoding is the same as the * input charset. In PHP 5.0.0 and 5.0.1, the default output charset is * ISO-8859-1, while in PHP 5.0.2 and upper is UTF-8. The supported * encodings are ISO-8859-1, UTF-8 and * US-ASCII. *

    * @param string $separator [optional]

    * With a namespace aware parser tag parameters passed to the various * handler functions will consist of namespace and tag name separated by * the string specified in separator. *

    * @return resource|false|XMLParser a resource handle for the new XML parser. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] function xml_parser_create_ns(?string $encoding, string $separator = ':') {} /** * Use XML Parser within an object * @link https://php.net/manual/en/function.xml-set-object.php * @param XMLParser|resource $parser

    * A reference to the XML parser to use inside the object. *

    * @param object $object

    * The object where to use the XML parser. *

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] #[Deprecated("The function is deprecated", since: "8.4")] function xml_set_object(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, object $object) {} /** * Set up start and end element handlers * @link https://php.net/manual/en/function.xml-set-element-handler.php * @param XMLParser|resource $parser

    * A reference to the XML parser to set up start and end element handler functions. *

    * @param callable $start_handler

    * The function named by start_element_handler * must accept three parameters: * start_element_handler * resourceparser * stringname * arrayattribs * parser * The first parameter, parser, is a * reference to the XML parser calling the handler.

    * @param callable $end_handler

    * The function named by end_element_handler * must accept two parameters: * end_element_handler * resourceparser * stringname * parser * The first parameter, parser, is a * reference to the XML parser calling the handler.

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function xml_set_element_handler( #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $start_handler, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $end_handler ) {} /** * Set up character data handler * @link https://php.net/manual/en/function.xml-set-character-data-handler.php * @param XMLParser|resource $parser

    * A reference to the XML parser to set up character data handler function. *

    * @param callable $handler

    * handler is a string containing the name of a * function that must exist when xml_parse is called * for parser. *

    *

    * The function named by handler must accept * two parameters: * handler * resourceparser * stringdata * parser * The first parameter, parser, is a * reference to the XML parser calling the handler.

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function xml_set_character_data_handler( #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $handler ) {} /** * Set up processing instruction (PI) handler * @link https://php.net/manual/en/function.xml-set-processing-instruction-handler.php * @param XMLParser|resource $parser

    * A reference to the XML parser to set up processing instruction (PI) handler function. *

    * @param callable $handler

    * handler is a string containing the name of a * function that must exist when xml_parse is called * for parser. *

    *

    * The function named by handler must accept * three parameters: * handler * resourceparser * stringtarget * stringdata * parser * The first parameter, parser, is a * reference to the XML parser calling the handler.

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function xml_set_processing_instruction_handler( #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $handler ) {} /** * Set up default handler * @link https://php.net/manual/en/function.xml-set-default-handler.php * @param XMLParser|resource $parser

    * A reference to the XML parser to set up default handler function. *

    * @param callable $handler

    * handler is a string containing the name of a * function that must exist when xml_parse is called * for parser. *

    *

    * The function named by handler must accept * two parameters: * handler * resourceparser * stringdata * parser * The first parameter, parser, is a * reference to the XML parser calling the handler.

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function xml_set_default_handler( #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $handler ) {} /** * Set up unparsed entity declaration handler * @link https://php.net/manual/en/function.xml-set-unparsed-entity-decl-handler.php * @param XMLParser|resource $parser

    * A reference to the XML parser to set up unparsed entity declaration handler function. *

    * @param callable $handler

    * handler is a string containing the name of a * function that must exist when xml_parse is called * for parser. *

    *

    * The function named by handler must accept six * parameters: * handler * resourceparser * stringentity_name * stringbase * stringsystem_id * stringpublic_id * stringnotation_name * parser * The first parameter, parser, is a * reference to the XML parser calling the * handler.

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function xml_set_unparsed_entity_decl_handler( #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $handler ) {} /** * Set up notation declaration handler * @link https://php.net/manual/en/function.xml-set-notation-decl-handler.php * @param XMLParser|resource $parser

    * A reference to the XML parser to set up notation declaration handler function. *

    * @param callable $handler

    * handler is a string containing the name of a * function that must exist when xml_parse is called * for parser. *

    *

    * The function named by handler must accept * five parameters: * handler * resourceparser * stringnotation_name * stringbase * stringsystem_id * stringpublic_id * parser * The first parameter, parser, is a * reference to the XML parser calling the handler.

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function xml_set_notation_decl_handler( #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $handler ) {} /** * Set up external entity reference handler * @link https://php.net/manual/en/function.xml-set-external-entity-ref-handler.php * @param XMLParser|resource $parser

    * A reference to the XML parser to set up external entity reference handler function. *

    * @param callable $handler

    * handler is a string containing the name of a * function that must exist when xml_parse is called * for parser. *

    *

    * The function named by handler must accept * five parameters, and should return an integer value.If the * value returned from the handler is FALSE (which it will be if no * value is returned), the XML parser will stop parsing and * xml_get_error_code will return * XML_ERROR_EXTERNAL_ENTITY_HANDLING. * handler * resourceparser * stringopen_entity_names * stringbase * stringsystem_id * stringpublic_id * parser * The first parameter, parser, is a * reference to the XML parser calling the handler.

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function xml_set_external_entity_ref_handler( #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $handler ) {} /** * Set up start namespace declaration handler * @link https://php.net/manual/en/function.xml-set-start-namespace-decl-handler.php * @param XMLParser|resource $parser

    * A reference to the XML parser. *

    * @param callable $handler

    * handler is a string containing the name of a * function that must exist when xml_parse is called * for parser. *

    *

    * The function named by handler must accept * three parameters, and should return an integer value. If the * value returned from the handler is FALSE (which it will be if no * value is returned), the XML parser will stop parsing and * xml_get_error_code will return * XML_ERROR_EXTERNAL_ENTITY_HANDLING. * handler * resourceparser * stringprefix * stringuri * parser * The first parameter, parser, is a * reference to the XML parser calling the handler.

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function xml_set_start_namespace_decl_handler( #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $handler ) {} /** * Set up end namespace declaration handler * @link https://php.net/manual/en/function.xml-set-end-namespace-decl-handler.php * @param XMLParser|resource $parser

    * A reference to the XML parser. *

    * @param callable $handler

    * handler is a string containing the name of a * function that must exist when xml_parse is called * for parser. *

    *

    * The function named by handler must accept * two parameters, and should return an integer value. If the * value returned from the handler is FALSE (which it will be if no * value is returned), the XML parser will stop parsing and * xml_get_error_code will return * XML_ERROR_EXTERNAL_ENTITY_HANDLING. * handler * resourceparser * stringprefix * parser * The first parameter, parser, is a * reference to the XML parser calling the handler.

    * @return bool TRUE on success or FALSE on failure. */ #[LanguageLevelTypeAware(["8.2" => "true"], default: "bool")] function xml_set_end_namespace_decl_handler( #[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, #[LanguageLevelTypeAware(["8.4" => "callable|string|null"], default: "callable")] $handler ) {} /** * Start parsing an XML document * @link https://php.net/manual/en/function.xml-parse.php * @param XMLParser|resource $parser

    * A reference to the XML parser to use. *

    * @param string $data

    * Chunk of data to parse. A document may be parsed piece-wise by * calling xml_parse several times with new data, * as long as the is_final parameter is set and * TRUE when the last data is parsed. *

    * @param bool $is_final [optional]

    * If set and TRUE, data is the last piece of * data sent in this parse. *

    * @return int 1 on success or 0 on failure. *

    * For unsuccessful parses, error information can be retrieved with * xml_get_error_code, * xml_error_string, * xml_get_current_line_number, * xml_get_current_column_number and * xml_get_current_byte_index. *

    *

    * Entity errors are reported at the end of the data thus only if * is_final is set and TRUE. *

    */ function xml_parse(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, string $data, bool $is_final = false): int {} /** * Parse XML data into an array structure * @link https://php.net/manual/en/function.xml-parse-into-struct.php * @param XMLParser|resource $parser

    * A reference to the XML parser. *

    * @param string $data

    * A string containing the XML data. *

    * @param array &$values

    * An array containing the values of the XML data *

    * @param array &$index [optional]

    * An array containing pointers to the location of the appropriate values in the $values. *

    * @return int xml_parse_into_struct returns 0 for failure and 1 for * success. This is not the same as FALSE and TRUE, be careful with * operators such as ===. */ #[LanguageLevelTypeAware(['8.1' => 'int|false'], default: 'int')] function xml_parse_into_struct(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, string $data, &$values, &$index) {} /** * Get XML parser error code * @link https://php.net/manual/en/function.xml-get-error-code.php * @param XMLParser|resource $parser

    * A reference to the XML parser to get error code from. *

    * @return int|false Returns one of the error codes listed in the error codes * section. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function xml_get_error_code(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser) {} /** * Get XML parser error string * @link https://php.net/manual/en/function.xml-error-string.php * @param int $error_code

    * An error code from xml_get_error_code. *

    * @return string|null a string with a textual description of the error * code, or FALSE if no description was found. */ #[Pure] function xml_error_string(int $error_code): ?string {} /** * Get current line number for an XML parser * @link https://php.net/manual/en/function.xml-get-current-line-number.php * @param XMLParser|resource $parser

    * A reference to the XML parser to get line number from. *

    * @return int|false This function returns FALSE if parser does * not refer to a valid parser, or else it returns which line the * parser is currently at in its data buffer. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function xml_get_current_line_number(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser) {} /** * Get current column number for an XML parser * @link https://php.net/manual/en/function.xml-get-current-column-number.php * @param XMLParser|resource $parser

    * A reference to the XML parser to get column number from. *

    * @return int|false This function returns FALSE if parser does * not refer to a valid parser, or else it returns which column on * the current line (as given by * xml_get_current_line_number) the parser is * currently at. */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function xml_get_current_column_number(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser) {} /** * Get current byte index for an XML parser * @link https://php.net/manual/en/function.xml-get-current-byte-index.php * @param XMLParser|resource $parser

    * A reference to the XML parser to get byte index from. *

    * @return int|false This function returns FALSE if parser does * not refer to a valid parser, or else it returns which byte index * the parser is currently at in its data buffer (starting at 0). */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "int"], default: "int|false")] function xml_get_current_byte_index(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser) {} /** * Free an XML parser * @link https://php.net/manual/en/function.xml-parser-free.php * @param XMLParser|resource $parser A reference to the XML parser to free. * @return bool This function returns FALSE if parser does not * refer to a valid parser, or else it frees the parser and returns TRUE. */ function xml_parser_free(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser): bool {} /** * Set options in an XML parser * @link https://php.net/manual/en/function.xml-parser-set-option.php * @param XMLParser|resource $parser

    * A reference to the XML parser to set an option in. *

    * @param int $option

    * Which option to set. See below. *

    *

    * The following options are available: *

    * XML parser options * * * * * * * * * * * * * * * * * * * * * * * * * *
    Option constantData typeDescription
    XML_OPTION_CASE_FOLDINGinteger * Controls whether case-folding is enabled for this * XML parser. Enabled by default. *
    XML_OPTION_SKIP_TAGSTARTinteger * Specify how many characters should be skipped in the beginning of a * tag name. *
    XML_OPTION_SKIP_WHITEinteger * Whether to skip values consisting of whitespace characters. *
    XML_OPTION_TARGET_ENCODINGstring * Sets which target encoding to * use in this XML parser.By default, it is set to the same as the * source encoding used by xml_parser_create. * Supported target encodings are ISO-8859-1, * US-ASCII and UTF-8. *
    *

    * @param mixed $value

    * The option's new value. *

    * @return bool This function returns FALSE if parser does not * refer to a valid parser, or if the option could not be set. Else the * option is set and TRUE is returned. */ function xml_parser_set_option(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, int $option, $value): bool {} /** * Get options from an XML parser * @link https://php.net/manual/en/function.xml-parser-get-option.php * @param XMLParser|resource $parser A reference to the XML parser to get an option from. * @param int $option Which option to fetch. XML_OPTION_CASE_FOLDING * and XML_OPTION_TARGET_ENCODING are available. * See xml_parser_set_option for their description. * @return string|int|bool This function returns FALSE if parser does * not refer to a valid parser or if option isn't * valid (generates also a E_WARNING). * Else the option's value is returned. */ #[Pure] #[LanguageLevelTypeAware(["8.3" => "string|int|bool"], default: "string|int")] function xml_parser_get_option(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, int $option) {} define('XML_ERROR_NONE', 0); define('XML_ERROR_NO_MEMORY', 1); define('XML_ERROR_SYNTAX', 2); define('XML_ERROR_NO_ELEMENTS', 3); define('XML_ERROR_INVALID_TOKEN', 4); define('XML_ERROR_UNCLOSED_TOKEN', 5); define('XML_ERROR_PARTIAL_CHAR', 6); define('XML_ERROR_TAG_MISMATCH', 7); define('XML_ERROR_DUPLICATE_ATTRIBUTE', 8); define('XML_ERROR_JUNK_AFTER_DOC_ELEMENT', 9); define('XML_ERROR_PARAM_ENTITY_REF', 10); define('XML_ERROR_UNDEFINED_ENTITY', 11); define('XML_ERROR_RECURSIVE_ENTITY_REF', 12); define('XML_ERROR_ASYNC_ENTITY', 13); define('XML_ERROR_BAD_CHAR_REF', 14); define('XML_ERROR_BINARY_ENTITY_REF', 15); define('XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF', 16); define('XML_ERROR_MISPLACED_XML_PI', 17); define('XML_ERROR_UNKNOWN_ENCODING', 18); define('XML_ERROR_INCORRECT_ENCODING', 19); define('XML_ERROR_UNCLOSED_CDATA_SECTION', 20); define('XML_ERROR_EXTERNAL_ENTITY_HANDLING', 21); define('XML_OPTION_CASE_FOLDING', 1); define('XML_OPTION_TARGET_ENCODING', 2); define('XML_OPTION_SKIP_TAGSTART', 3); define('XML_OPTION_SKIP_WHITE', 4); /** * @since 8.4 */ define('XML_OPTION_PARSE_HUGE', 5); /** * Holds the SAX implementation method. * Can be libxml or expat. * @link https://php.net/manual/en/xml.constants.php */ define('XML_SAX_IMPL', "libxml"); /** * @since 8.0 */ final class XMLParser {} // End of xml v. next() method. * * @return void */ function ms_ResetErrorList() {} /** * Class Objects can be returned by the `layerObj`_ class, or can be * created using: */ final class classObj { /** * @var string */ public $group; /** * @var string */ public $keyimage; /** * Removed (6.2) - use addLabel, getLabel, ... * * @var labelObj */ public $label; /** * @var float */ public $maxscaledenom; /** * @var hashTableObj */ public $metadata; /** * @var float */ public $minscaledenom; /** * @var string */ public $name; /** * read-only (since 6.2) * * @var int */ public $numlabels; /** * read-only * * @var int */ public $numstyles; /** * MS_ON, MS_OFF or MS_DELETE * * @var int */ public $status; /** * @var string */ public $template; /** * @var string */ public $title; /** * @var int */ public $type; /** * The second argument class is optional. If given, the new class * created will be a copy of this class. * * @param layerObj $layer * @param classObj $class */ final public function __construct(layerObj $layer, classObj $class) {} /** * Old style constructor * * @param layerObj $layer * @param classObj $class * @return classObj */ final public function ms_newClassObj(layerObj $layer, classObj $class) {} /** * Add a labelObj to the classObj and return its index in the labels * array. * .. versionadded:: 6.2 * * @param labelObj $label * @return int */ final public function addLabel(labelObj $label) {} /** * Saves the object to a string. Provides the inverse option for * updateFromString. * * @return string */ final public function convertToString() {} /** * Draw the legend icon and return a new imageObj. * * @param int $width * @param int $height * @return imageObj */ final public function createLegendIcon($width, $height) {} /** * Delete the style specified by the style index. If there are any * style that follow the deleted style, their index will decrease by 1. * * @param int $index * @return int */ final public function deletestyle($index) {} /** * Draw the legend icon on im object at dstX, dstY. * Returns MS_SUCCESS/MS_FAILURE. * * @param int $width * @param int $height * @param imageObj $im * @param int $dstX * @param int $dstY * @return int */ final public function drawLegendIcon($width, $height, imageObj $im, $dstX, $dstY) {} /** * Free the object properties and break the internal references. * Note that you have to unset the php variable to free totally the * resources. * * @return void */ final public function free() {} /** * Returns the :ref:`expression ` string for the class * object. * * @return string */ final public function getExpressionString() {} /** * Return a reference to the labelObj at *index* in the labels array. * See the labelObj_ section for more details on multiple class * labels. * .. versionadded:: 6.2 * * @param int $index * @return labelObj */ final public function getLabel($index) {} /** * Fetch class metadata entry by name. Returns "" if no entry * matches the name. Note that the search is case sensitive. * .. note:: * getMetaData's query is case sensitive. * * @param string $name * @return int */ final public function getMetaData($name) {} /** * Return the style object using an index. index >= 0 && * index < class->numstyles. * * @param int $index * @return styleObj */ final public function getStyle($index) {} /** * Returns the text string for the class object. * * @return string */ final public function getTextString() {} /** * The style specified by the style index will be moved down into * the array of classes. Returns MS_SUCCESS or MS_FAILURE. * ex class->movestyledown(0) will have the effect of moving style 0 * up to position 1, and the style at position 1 will be moved * to position 0. * * @param int $index * @return int */ final public function movestyledown($index) {} /** * The style specified by the style index will be moved up into * the array of classes. Returns MS_SUCCESS or MS_FAILURE. * ex class->movestyleup(1) will have the effect of moving style 1 * up to position 0, and the style at position 0 will be moved * to position 1. * * @param int $index * @return int */ final public function movestyleup($index) {} /** * Remove the labelObj at *index* from the labels array and return a * reference to the labelObj. numlabels is decremented, and the * array is updated. * .. versionadded:: 6.2 * * @param int $index * @return labelObj */ final public function removeLabel($index) {} /** * Remove a metadata entry for the class. Returns MS_SUCCESS/MS_FAILURE. * * @param string $name * @return int */ final public function removeMetaData($name) {} /** * Set object property to a new value. * * @param string $property_name * @param $new_value * @return int */ final public function set($property_name, $new_value) {} /** * Set the :ref:`expression ` string for the class * object. * * @param string $expression * @return int */ final public function setExpression($expression) {} /** * Set a metadata entry for the class. Returns MS_SUCCESS/MS_FAILURE. * * @param string $name * @param string $value * @return int */ final public function setMetaData($name, $value) {} /** * Set the text string for the class object. * * @param string $text * @return int */ final public function settext($text) {} /** * Update a class from a string snippet. Returns MS_SUCCESS/MS_FAILURE. * .. code-block:: php * set the color * $oClass->updateFromString('CLASS STYLE COLOR 255 0 255 END END'); * * @param string $snippet * @return int */ final public function updateFromString($snippet) {} } /** * Instance of clusterObj is always embedded inside the `layerObj`_. */ final class clusterObj { /** * @var float */ public $buffer; /** * @var float */ public $maxdistance; /** * @var string */ public $region; /** * Saves the object to a string. Provides the inverse option for * updateFromString. * * @return string */ final public function convertToString() {} /** * Returns the :ref:`expression ` for this cluster * filter or NULL on error. * * @return string */ final public function getFilterString() {} /** * Returns the :ref:`expression ` for this cluster group * or NULL on error. * * @return string */ final public function getGroupString() {} /** * Set layer filter :ref:`expression `. * * @param string $expression * @return int */ final public function setFilter($expression) {} /** * Set layer group :ref:`expression `. * * @param string $expression * @return int */ final public function setGroup($expression) {} } /** * Instances of colorObj are always embedded inside other classes. */ final class colorObj { /** * @var int */ public $red; /** * @var int */ public $green; /** * @var int */ public $blue; /** * @var int */ public $alpha; /** * Get the color as a hex string "#rrggbb" or (if alpha is not 255) * "#rrggbbaa". * * @return string */ final public function toHex() {} /** * Set red, green, blue and alpha values. The hex string should have the form * "#rrggbb" (alpha will be set to 255) or "#rrggbbaa". Returns MS_SUCCESS. * * @param string $hex * @return int */ final public function setHex($hex) {} } final class errorObj { /** * //See error code constants above * * @var int */ public $code; /** * @var string */ public $message; /** * @var string */ public $routine; } /** * The grid is always embedded inside a layer object defined as * a grid (layer->connectiontype = MS_GRATICULE) * (for more docs : https://github.com/mapserver/mapserver/wiki/MapServerGrid) * A layer can become a grid layer by adding a grid object to it using : * ms_newGridObj(layerObj layer) * $oLayer = ms_newlayerobj($oMap); * $oLayer->set("name", "GRID"); * ms_newgridobj($oLayer); * $oLayer->grid->set("labelformat", "DDMMSS"); */ final class gridObj { /** * @var string */ public $labelformat; /** * @var float */ public $maxacrs; /** * @var float */ public $maxinterval; /** * @var float */ public $maxsubdivide; /** * @var float */ public $minarcs; /** * @var float */ public $mininterval; /** * @var float */ public $minsubdivide; /** * Set object property to a new value. * * @param string $property_name * @param $new_value * @return int */ final public function set($property_name, $new_value) {} } /** * Instance of hashTableObj is always embedded inside the `classObj`_, * `layerObj`_, `mapObj`_ and `webObj`_. It is uses a read only. * $hashTable = $oLayer->metadata; * $key = null; * while ($key = $hashTable->nextkey($key)) * echo "Key: ".$key." value: ".$hashTable->get($key)."
    "; */ final class hashTableObj { /** * Clear all items in the hashTable (To NULL). * * @return void */ final public function clear() {} /** * Fetch class metadata entry by name. Returns "" if no entry * matches the name. Note that the search is case sensitive. * * @param string $key * @return string */ final public function get($key) {} /** * Return the next key or first key if previousKey = NULL. * Return NULL if no item is in the hashTable or end of hashTable is * reached * * @param string $previousKey * @return string */ final public function nextkey($previousKey) {} /** * Remove a metadata entry in the hashTable. Returns MS_SUCCESS/MS_FAILURE. * * @param string $key * @return int */ final public function remove($key) {} /** * Set a metadata entry in the hashTable. Returns MS_SUCCESS/MS_FAILURE. * * @param string $key * @param string $value * @return int */ final public function set($key, $value) {} } /** * Instances of imageObj are always created by the `mapObj`_ class methods. */ final class imageObj { /** * read-only * * @var int */ public $width; /** * read-only * * @var int */ public $height; /** * read-only * * @var int */ public $resolution; /** * read-only * * @var int */ public $resolutionfactor; /** * @var string */ public $imagepath; /** * @var string */ public $imageurl; /** * Copy srcImg on top of the current imageObj. * transparentColorHex is the color (in 0xrrggbb format) from srcImg * that should be considered transparent (i.e. those pixels won't * be copied). Pass -1 if you don't want any transparent color. * If optional dstx,dsty are provided then it defines the position * where the image should be copied (dstx,dsty = top-left corner * position). * The optional angle is a value between 0 and 360 degrees to rotate * the source image counterclockwise. Note that if an angle is specified * (even if its value is zero) then the dstx and dsty coordinates * specify the CENTER of the destination area. * Note: this function works only with 8 bits GD images (PNG or GIF). * * @param imageObj $srcImg * @param int $transparentColorHex * @param int $dstX * @param int $dstY * @param int $angle * @return void */ final public function pasteImage(imageObj $srcImg, $transparentColorHex, $dstX, $dstY, $angle) {} /** * Writes image object to specified filename. * Passing no filename or an empty filename sends output to stdout. In * this case, the PHP header() function should be used to set the * document's content-type prior to calling saveImage(). The output * format is the one that is currently selected in the map file. The * second argument oMap is not manadatory. It is usful when saving to * formats like GTIFF that needs georeference information contained in * the map file. On success, it returns either MS_SUCCESS if writing to an * external file, or the number of bytes written if output is sent to * stdout. * * @param string $filename * @param mapObj $oMap * @return int */ final public function saveImage($filename, mapObj $oMap) {} /** * Writes image to temp directory. Returns image URL. * The output format is the one that is currently selected in the * map file. * * @return string */ final public function saveWebImage() {} } final class labelcacheMemberObj { /** * read-only * * @var int */ public $classindex; /** * read-only * * @var int */ public $featuresize; /** * read-only * * @var int */ public $layerindex; /** * read-only * * @var int */ public $markerid; /** * read-only * * @var int */ public $numstyles; /** * read-only * * @var int */ public $shapeindex; /** * read-only * * @var int */ public $status; /** * read-only * * @var string */ public $text; /** * read-only * * @var int */ public $tileindex; } final class labelcacheObj { /** * Free the label cache. Always returns MS_SUCCESS. * Ex : map->labelcache->freeCache(); * * @return bool */ final public function freeCache() {} } /** * labelObj are always embedded inside other classes. */ final class labelObj { /** * @var int */ public $align; /** * @var float */ public $angle; /** * @var int */ public $anglemode; /** * @var int */ public $antialias; /** * @var int */ public $autominfeaturesize; /** * (deprecated since 6.0) * * @var colorObj */ public $backgroundcolor; /** * (deprecated since 6.0) * * @var colorObj */ public $backgroundshadowcolor; /** * (deprecated since 6.0) * * @var int */ public $backgroundshadowsizex; /** * (deprecated since 6.0) * * @var int */ public $backgroundshadowsizey; /** * @var int */ public $buffer; /** * @var colorObj */ public $color; /** * @var string */ public $encoding; /** * @var string */ public $font; /** * @var int */ public $force; /** * @var int */ public $maxlength; /** * @var int */ public $maxsize; /** * @var int */ public $mindistance; /** * @var int */ public $minfeaturesize; /** * @var int */ public $minlength; /** * @var int */ public $minsize; /** * @var int */ public $numstyles; /** * @var int */ public $offsetx; /** * @var int */ public $offsety; /** * @var colorObj */ public $outlinecolor; /** * @var int */ public $outlinewidth; /** * @var int */ public $partials; /** * @var int */ public $position; /** * @var int */ public $priority; /** * @var int */ public $repeatdistance; /** * @var colorObj */ public $shadowcolor; /** * @var int */ public $shadowsizex; /** * @var int */ public $shadowsizey; /** * @var int */ public $size; /** * @var int */ public $wrap; final public function __construct() {} /** * Saves the object to a string. Provides the inverse option for * updateFromString. * * @return string */ final public function convertToString() {} /** * Delete the style specified by the style index. If there are any * style that follow the deleted style, their index will decrease by 1. * * @param int $index * @return int */ final public function deleteStyle($index) {} /** * Free the object properties and break the internal references. * Note that you have to unset the php variable to free totally the * resources. * * @return void */ final public function free() {} /** * Get the attribute binding for a specified label property. Returns * NULL if there is no binding for this property. * Example: * .. code-block:: php * $oLabel->setbinding(MS_LABEL_BINDING_COLOR, "FIELD_NAME_COLOR"); * echo $oLabel->getbinding(MS_LABEL_BINDING_COLOR); // FIELD_NAME_COLOR * * @param mixed $labelbinding * @return string */ final public function getBinding($labelbinding) {} /** * Returns the label expression string. * * @return string */ final public function getExpressionString() {} /** * Return the style object using an index. index >= 0 && * index < label->numstyles. * * @param int $index * @return styleObj */ final public function getStyle($index) {} /** * Returns the label text string. * * @return string */ final public function getTextString() {} /** * The style specified by the style index will be moved down into * the array of classes. Returns MS_SUCCESS or MS_FAILURE. * ex label->movestyledown(0) will have the effect of moving style 0 * up to position 1, and the style at position 1 will be moved * to position 0. * * @param int $index * @return int */ final public function moveStyleDown($index) {} /** * The style specified by the style index will be moved up into * the array of classes. Returns MS_SUCCESS or MS_FAILURE. * ex label->movestyleup(1) will have the effect of moving style 1 * up to position 0, and the style at position 0 will be moved * to position 1. * * @param int $index * @return int */ final public function moveStyleUp($index) {} /** * Remove the attribute binding for a specfiled style property. * Example: * .. code-block:: php * $oStyle->removebinding(MS_LABEL_BINDING_COLOR); * * @param mixed $labelbinding * @return int */ final public function removeBinding($labelbinding) {} /** * Set object property to a new value. * * @param string $property_name * @param $new_value * @return int */ final public function set($property_name, $new_value) {} /** * Set the attribute binding for a specified label property. * Example: * .. code-block:: php * $oLabel->setbinding(MS_LABEL_BINDING_COLOR, "FIELD_NAME_COLOR"); * This would bind the color parameter with the data (ie will extract * the value of the color from the field called "FIELD_NAME_COLOR" * * @param mixed $labelbinding * @param string $value * @return int */ final public function setBinding($labelbinding, $value) {} /** * Set the label expression. * * @param string $expression * @return int */ final public function setExpression($expression) {} /** * Set the label text. * * @param string $text * @return int */ final public function setText($text) {} /** * Update a label from a string snippet. Returns MS_SUCCESS/MS_FAILURE. * * @param string $snippet * @return int */ final public function updateFromString($snippet) {} } /** * Layer Objects can be returned by the `mapObj`_ class, or can be * created using: * A second optional argument can be given to ms_newLayerObj() to create * the new layer as a copy of an existing layer. If a layer is given as * argument then all members of a this layer will be copied in the new * layer created. */ final class layerObj { /** * @var int */ public $annotate; /** * @var hashTableObj */ public $bindvals; /** * @var string */ public $classgroup; /** * @var string */ public $classitem; /** * @var clusterObj */ public $cluster; /** * @var string */ public $connection; /** * read-only, use setConnectionType() to set it * * @var int */ public $connectiontype; /** * @var string */ public $data; /** * @var int */ public $debug; /** * deprecated since 6.0 * * @var int */ public $dump; /** * @var string */ public $filteritem; /** * @var string */ public $footer; /** * only available on a layer defined as grid (MS_GRATICULE) * * @var gridObj */ public $grid; /** * @var string */ public $group; /** * @var string */ public $header; /** * read-only * * @var int */ public $index; /** * @var int */ public $labelcache; /** * @var string */ public $labelitem; /** * @var float */ public $labelmaxscaledenom; /** * @var float */ public $labelminscaledenom; /** * @var string */ public $labelrequires; /** * @var string */ public $mask; /** * @var int */ public $maxfeatures; /** * @var float */ public $maxscaledenom; /** * @var hashTableObj */ public $metadata; /** * @var float */ public $minscaledenom; /** * @var string */ public $name; /** * @var int */ public $num_processing; /** * read-only * * @var int */ public $numclasses; /** * @var colorObj */ public $offsite; /** * @var int */ public $opacity; /** * @var projectionObj */ public $projection; /** * @var int */ public $postlabelcache; /** * @var string */ public $requires; /** * @var int */ public $sizeunits; /** * @var int */ public $startindex; /** * MS_ON, MS_OFF, MS_DEFAULT or MS_DELETE * * @var int */ public $status; /** * @var string */ public $styleitem; /** * @var float */ public $symbolscaledenom; /** * @var string */ public $template; /** * @var string */ public $tileindex; /** * @var string */ public $tileitem; /** * @var float */ public $tolerance; /** * @var int */ public $toleranceunits; /** * @var int */ public $transform; /** * @var int */ public $type; /** * Old style constructor * * @param mapObj $map * @param layerObj $layer * @return layerObj */ final public function ms_newLayerObj(mapObj $map, layerObj $layer) {} /** * Add a new feature in a layer. Returns MS_SUCCESS or MS_FAILURE on * error. * * @param shapeObj $shape * @return int */ final public function addFeature(shapeObj $shape) {} /** * Apply the :ref:`SLD ` document to the layer object. * The matching between the sld document and the layer will be done * using the layer's name. * If a namedlayer argument is passed (argument is optional), * the NamedLayer in the sld that matchs it will be used to style * the layer. * See :ref:`SLD HowTo ` for more information on the SLD support. * * @param string $sldxml * @param string $namedlayer * @return int */ final public function applySLD($sldxml, $namedlayer) {} /** * Apply the :ref:`SLD ` document pointed by the URL to the * layer object. The matching between the sld document and the layer * will be done using the layer's name. If a namedlayer argument is * passed (argument is optional), the NamedLayer in the sld that * matchs it will be used to style the layer. See :ref:`SLD HowTo ` * for more information on the SLD support. * * @param string $sldurl * @param string $namedlayer * @return int */ final public function applySLDURL($sldurl, $namedlayer) {} /** * Clears all the processing strings. * * @return void */ final public function clearProcessing() {} /** * Close layer previously opened with open(). * * @return void */ final public function close() {} /** * Saves the object to a string. Provides the inverse option for * updateFromString. * * @return string */ final public function convertToString() {} /** * Draw a single layer, add labels to cache if required. * Returns MS_SUCCESS or MS_FAILURE on error. * * @param imageObj $image * @return int */ final public function draw(imageObj $image) {} /** * Draw query map for a single layer. * string executeWFSGetfeature() * Executes a GetFeature request on a WFS layer and returns the * name of the temporary GML file created. Returns an empty * string on error. * * @param imageObj $image * @return int */ final public function drawQuery(imageObj $image) {} /** * Free the object properties and break the internal references. * Note that you have to unset the php variable to free totally the * resources. * * @return void */ final public function free() {} /** * Returns an SLD XML string based on all the classes found in the * layer (the layer must have `STATUS` `on`). * * @return string */ final public function generateSLD() {} /** * Returns a classObj from the layer given an index value (0=first class) * * @param int $classIndex * @return classObj */ final public function getClass($classIndex) {} /** * Get the class index of a shape for a given scale. Returns -1 if no * class matches. classgroup is an array of class ids to check * (Optional). numclasses is the number of classes that the classgroup * array contains. By default, all the layer classes will be checked. * * @param $shape * @param $classgroup * @param $numclasses * @return int */ final public function getClassIndex($shape, $classgroup, $numclasses) {} /** * Returns the layer's data extents or NULL on error. * If the layer's EXTENT member is set then this value is used, * otherwise this call opens/closes the layer to read the * extents. This is quick on shapefiles, but can be * an expensive operation on some file formats or data sources. * This function is safe to use on both opened or closed layers: it * is not necessary to call open()/close() before/after calling it. * * @return rectObj */ final public function getExtent() {} /** * Returns the :ref:`expression ` for this layer or NULL * on error. * * @return string|null */ final public function getFilterString() {} /** * Returns an array containing the grid intersection coordinates. If * there are no coordinates, it returns an empty array. * * @return array */ final public function getGridIntersectionCoordinates() {} /** * Returns an array containing the items. Must call open function first. * If there are no items, it returns an empty array. * * @return array */ final public function getItems() {} /** * Fetch layer metadata entry by name. Returns "" if no entry * matches the name. Note that the search is case sensitive. * .. note:: * getMetaData's query is case sensitive. * * @param string $name * @return int */ final public function getMetaData($name) {} /** * Returns the number of results in the last query. * * @return int */ final public function getNumResults() {} /** * Returns an array containing the processing strings. * If there are no processing strings, it returns an empty array. * * @return array */ final public function getProcessing() {} /** * Returns a string representation of the :ref:`projection `. * Returns NULL on error or if no projection is set. * * @return string */ final public function getProjection() {} /** * Returns a resultObj by index from a layer object with * index in the range 0 to numresults-1. * Returns a valid object or FALSE(0) if index is invalid. * * @param int $index * @return resultObj */ final public function getResult($index) {} /** * Returns the bounding box of the latest result. * * @return rectObj */ final public function getResultsBounds() {} /** * If the resultObj passed has a valid resultindex, retrieve shapeObj from * a layer's resultset. (You get it from the resultObj returned by * getResult() for instance). Otherwise, it will do a single query on * the layer to fetch the shapeindex * .. code-block:: php * $map = new mapObj("gmap75.map"); * $l = $map->getLayerByName("popplace"); * $l->queryByRect($map->extent); * for ($i = 0; $i < $l->getNumResults(); $i++) { * $s = $l->getShape($l->getResult($i)); * echo $s->getValue($l,"Name"); * echo "\n"; * } * * @param resultObj $result * @return shapeObj */ final public function getShape(resultObj $result) {} /** * Returns a WMS GetFeatureInfo URL (works only for WMS layers) * clickX, clickY is the location of to query in pixel coordinates * with (0,0) at the top left of the image. * featureCount is the number of results to return. * infoFormat is the format the format in which the result should be * requested. Depends on remote server's capabilities. MapServer * WMS servers support only "MIME" (and should support "GML.1" soon). * Returns "" and outputs a warning if layer is not a WMS layer * or if it is not queriable. * * @param int $clickX * @param int $clickY * @param int $featureCount * @param string $infoFormat * @return string */ final public function getWMSFeatureInfoURL($clickX, $clickY, $featureCount, $infoFormat) {} /** * Returns MS_TRUE/MS_FALSE depending on whether the layer is * currently visible in the map (i.e. turned on, in scale, etc.). * * @return bool */ final public function isVisible() {} /** * The class specified by the class index will be moved down into * the array of layers. Returns MS_SUCCESS or MS_FAILURE. * ex layer->moveclassdown(0) will have the effect of moving class 0 * up to position 1, and the class at position 1 will be moved * to position 0. * * @param int $index * @return int */ final public function moveclassdown($index) {} /** * The class specified by the class index will be moved up into * the array of layers. Returns MS_SUCCESS or MS_FAILURE. * ex layer->moveclassup(1) will have the effect of moving class 1 * up to position 0, and the class at position 0 will be moved * to position 1. * * @param int $index * @return int */ final public function moveclassup($index) {} /** * Open the layer for use with getShape(). * Returns MS_SUCCESS/MS_FAILURE. * * @return int */ final public function open() {} /** * Called after msWhichShapes has been called to actually retrieve * shapes within a given area. Returns a shape object or NULL on * error. * .. code-block:: php * $map = ms_newmapobj("d:/msapps/gmap-ms40/htdocs/gmap75.map"); * $layer = $map->getLayerByName('road'); * $status = $layer->open(); * $status = $layer->whichShapes($map->extent); * while ($shape = $layer->nextShape()) * { * echo $shape->index ."
    \n"; * } * $layer->close(); * * @return shapeObj */ final public function nextShape() {} /** * Query layer for shapes that intersect current map extents. qitem * is the item (attribute) on which the query is performed, and * qstring is the expression to match. The query is performed on all * the shapes that are part of a :ref:`CLASS` that contains a * :ref:`TEMPLATE